aboutsummaryrefslogtreecommitdiff
path: root/contrib/extractor
diff options
context:
space:
mode:
authorNeo2003 <none@none>2008-10-02 16:23:55 -0500
committerNeo2003 <none@none>2008-10-02 16:23:55 -0500
commit9b1c0e006f20091f28f3f468cfcab1feb51286bd (patch)
treeb5d1ba94a656e6679f8737f9ea6bed1239b73b14 /contrib/extractor
[svn] * Proper SVN structureinit
--HG-- branch : trunk
Diffstat (limited to 'contrib/extractor')
-rw-r--r--contrib/extractor/Makefile470
-rw-r--r--contrib/extractor/Makefile.am10
-rw-r--r--contrib/extractor/README.linux13
-rw-r--r--contrib/extractor/System.cpp320
-rw-r--r--contrib/extractor/VC71_AD.sln19
-rw-r--r--contrib/extractor/VC71_ad.vcproj316
-rw-r--r--contrib/extractor/VC80_AD.sln19
-rw-r--r--contrib/extractor/VC80_ad.vcproj339
-rw-r--r--contrib/extractor/VC90_AD.sln19
-rw-r--r--contrib/extractor/VC90_ad.vcproj315
-rw-r--r--contrib/extractor/adbin0 -> 216203 bytes
-rw-r--r--contrib/extractor/ad.exebin0 -> 167936 bytes
-rw-r--r--contrib/extractor/adt.cpp501
-rw-r--r--contrib/extractor/adt.h54
-rw-r--r--contrib/extractor/dbcfile.cpp69
-rw-r--r--contrib/extractor/dbcfile.h118
-rw-r--r--contrib/extractor/debug/zlib.libbin0 -> 198300 bytes
-rw-r--r--contrib/extractor/libmpq/Makefile17
-rw-r--r--contrib/extractor/libmpq/Makefile.am23
-rw-r--r--contrib/extractor/libmpq/common.cpp801
-rw-r--r--contrib/extractor/libmpq/common.h66
-rw-r--r--contrib/extractor/libmpq/explode.cpp428
-rw-r--r--contrib/extractor/libmpq/explode.h86
-rw-r--r--contrib/extractor/libmpq/extract.cpp262
-rw-r--r--contrib/extractor/libmpq/huffman.cpp833
-rw-r--r--contrib/extractor/libmpq/huffman.h105
-rw-r--r--contrib/extractor/libmpq/mpq.cpp626
-rw-r--r--contrib/extractor/libmpq/mpq.h225
-rw-r--r--contrib/extractor/libmpq/parser.cpp294
-rw-r--r--contrib/extractor/libmpq/wave.cpp185
-rw-r--r--contrib/extractor/libmpq/wave.h37
-rw-r--r--contrib/extractor/libmpq/zconf.h323
-rw-r--r--contrib/extractor/libmpq/zlib.h1200
-rw-r--r--contrib/extractor/mpq_libmpq.cpp133
-rw-r--r--contrib/extractor/mpq_libmpq.h124
-rw-r--r--contrib/extractor/release/zlib.libbin0 -> 212284 bytes
36 files changed, 8350 insertions, 0 deletions
diff --git a/contrib/extractor/Makefile b/contrib/extractor/Makefile
new file mode 100644
index 00000000000..64153634c88
--- /dev/null
+++ b/contrib/extractor/Makefile
@@ -0,0 +1,470 @@
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+
+# Copyright (C) 2005,2006 MaNGOS <http://www.mangosproject.org/>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+SOURCES = $(ad_SOURCES)
+
+srcdir = .
+top_srcdir = .
+
+pkgdatadir = $(datadir)/mangos
+pkglibdir = $(libdir)/mangos
+pkgincludedir = $(includedir)/mangos
+top_builddir = ../..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = /usr/bin/ginstall -c
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = i686-pc-linux-gnu
+host_triplet = i686-pc-linux-gnu
+bin_PROGRAMS = ad$(EXEEXT)
+subdir = contrib/extractor
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+am__installdirs = "$(DESTDIR)$(bindir)"
+binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
+PROGRAMS = $(bin_PROGRAMS)
+am_ad_OBJECTS = System.$(OBJEXT) adt.$(OBJEXT) dbcfile.$(OBJEXT) \
+ mpq_libmpq.$(OBJEXT)
+ad_OBJECTS = $(am_ad_OBJECTS)
+ad_DEPENDENCIES =
+DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) --tag=CXX --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(ad_SOURCES)
+DIST_SOURCES = $(ad_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL =
+ALLOCA =
+AMDEP_FALSE = #
+AMDEP_TRUE =
+AMTAR = ${SHELL} /home/wow/MaNGOS/trunk/missing --run tar
+AR = ar
+AUTOCONF = ${SHELL} /home/wow/MaNGOS/trunk/missing --run autoconf
+AUTOHEADER = ${SHELL} /home/wow/MaNGOS/trunk/missing --run autoheader
+AUTOMAKE = ${SHELL} /home/wow/MaNGOS/trunk/missing --run automake-1.9
+AWK = gawk
+CC = gcc
+CCDEPMODE = depmode=gcc3
+CFLAGS = -g -O3
+COMPILER_OPTIONS = -g -O3
+CPP = gcc -E
+CPPFLAGS =
+CXX = g++
+CXXCPP = g++ -E
+CXXDEPMODE = depmode=gcc3
+CXXFLAGS = -g -O3
+CYGPATH_W = echo
+DEFS = -DHAVE_CONFIG_H
+DEPDIR = .deps
+ECHO = echo
+ECHO_C =
+ECHO_N = -n
+ECHO_T =
+EGREP = grep -E
+EXEEXT =
+EXTRA_COMPILER_OPTIONS =
+EXTRA_LINKER_OPTIONS =
+F77 =
+FFLAGS =
+INCLUDES = -I$(srcdir)
+INSTALL_DATA = ${INSTALL} -m 644
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_SCRIPT = ${INSTALL}
+INSTALL_STRIP_PROGRAM = ${SHELL} $(install_sh) -c -s
+LDFLAGS =
+LIBOBJS =
+LIBS = -lz -lpthread
+LIBTOOL = $(SHELL) $(top_builddir)/libtool
+LINKER_OPTIONS = -static
+LN_S = ln -s
+LTLIBOBJS =
+LT_AGE = 2
+LT_CURRENT = 2
+LT_RELEASE = 2.3.2
+LT_REVISION = 3
+MAINT = #
+MAINTAINER_MODE_FALSE =
+MAINTAINER_MODE_TRUE = #
+MAKEINFO =
+MANGOSD_CONFIG = /home/wow/server/etc/mangosd.conf
+MANGOSD_CONFIGDIR = /home/wow/server/etc
+MANGOSD_DATA = /home/wow/server/share/mangos
+OBJEXT = o
+PACKAGE = mangos
+PACKAGE_BUGREPORT = http://www.mangosproject.org/
+PACKAGE_NAME = MaNGOS
+PACKAGE_STRING = MaNGOS 0.2-SVN
+PACKAGE_TARNAME = mangos
+PACKAGE_VERSION = 0.2-SVN
+PATH_SEPARATOR = :
+RANLIB = ranlib
+SET_MAKE =
+SHELL = /bin/sh
+STRIP = strip
+VERSION = 0.2-SVN
+ac_ct_AR = ar
+ac_ct_CC = gcc
+ac_ct_CXX = g++
+ac_ct_F77 =
+ac_ct_RANLIB = ranlib
+ac_ct_STRIP = strip
+am__fastdepCC_FALSE = #
+am__fastdepCC_TRUE =
+am__fastdepCXX_FALSE = #
+am__fastdepCXX_TRUE =
+am__include = include
+am__leading_dot = .
+am__quote =
+am__tar = ${AMTAR} chof - "$$tardir"
+am__untar = ${AMTAR} xf -
+bindir = ${exec_prefix}/bin
+build = i686-pc-linux-gnu
+build_alias =
+build_cpu = i686
+build_os = linux-gnu
+build_vendor = pc
+datadir = ${prefix}/share
+exec_prefix = ${prefix}
+host = i686-pc-linux-gnu
+host_alias =
+host_cpu = i686
+host_os = linux-gnu
+host_vendor = pc
+includedir = ${prefix}/include
+infodir = ${prefix}/info
+install_sh = /home/wow/MaNGOS/trunk/install-sh
+libdir = ${exec_prefix}/lib
+libexecdir = ${exec_prefix}/libexec
+localstatedir = ${prefix}/var
+mandir = ${prefix}/man
+mkdir_p = mkdir -p --
+oldincludedir = /usr/include
+prefix = /home/wow/server
+program_transform_name = s,x,x,
+sbindir = ${exec_prefix}/sbin
+sharedstatedir = ${prefix}/com
+
+# use our configured sysconfdir
+sysconfdir = /home/wow/server/etc
+target_alias =
+ad_SOURCES = \
+ System.cpp \
+ adt.h \
+ adt.cpp \
+ dbcfile.cpp \
+ dbcfile.h \
+ mpq_libmpq.cpp \
+ mpq_libmpq.h
+
+ad_LDADD = libmpq/libmpq.a
+add_LDFLAGS = -L$(srcdir) -L$(srcdir)/libmpq
+
+all: create-dir all-am
+
+.SUFFIXES:
+.SUFFIXES: .cpp .lo .o .obj
+
+.PRECIOUS: Makefile
+
+install-binPROGRAMS: $(bin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ test -z "$(bindir)" || $(mkdir_p) "$(DESTDIR)$(bindir)"
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
+ p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+ if test -f $$p \
+ || test -f $$p1 \
+ ; then \
+ f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
+ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \
+ else :; fi; \
+ done
+
+uninstall-binPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
+ f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+ echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \
+ rm -f "$(DESTDIR)$(bindir)/$$f"; \
+ done
+
+clean-binPROGRAMS:
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
+ f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f $$p $$f"; \
+ rm -f $$p $$f ; \
+ done
+ad$(EXEEXT): $(ad_OBJECTS) $(ad_DEPENDENCIES)
+ @rm -f ad$(EXEEXT)
+ $(CXXLINK) $(ad_LDFLAGS) $(ad_OBJECTS) $(ad_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+.cpp.o:
+ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+# source='$<' object='$@' libtool=no \
+# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \
+# $(CXXCOMPILE) -c -o $@ $<
+
+.cpp.obj:
+ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+# source='$<' object='$@' libtool=no \
+# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \
+# $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cpp.lo:
+ if $(LTCXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+# source='$<' object='$@' libtool=yes \
+# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \
+# $(LTCXXCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+ -rm .deps/*
+
+distclean-libtool:
+ -rm -f libtool
+uninstall-info-am:
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+ list='$(DISTFILES)'; for file in $$list; do \
+ case $$file in \
+ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+ esac; \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+ dir="/$$dir"; \
+ $(mkdir_p) "$(distdir)$$dir"; \
+ else \
+ dir=''; \
+ fi; \
+ if test -d $$d/$$file; then \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS);
+installdirs:
+ for dir in "$(DESTDIR)$(bindir)"; do \
+ test -z "$$dir" || $(mkdir_p) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-libtool distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am: install-binPROGRAMS
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-binPROGRAMS uninstall-info-am
+
+create-dir:
+ mkdir -p ".deps"
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \
+ clean-generic clean-libtool ctags distclean distclean-compile \
+ distclean-generic distclean-libtool distclean-tags distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-binPROGRAMS install-data install-data-am install-exec \
+ install-exec-am install-info install-info-am install-man \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-binPROGRAMS uninstall-info-am
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/contrib/extractor/Makefile.am b/contrib/extractor/Makefile.am
new file mode 100644
index 00000000000..b84617069a1
--- /dev/null
+++ b/contrib/extractor/Makefile.am
@@ -0,0 +1,10 @@
+# The top-level input Makefile for mpq-tools
+
+# Any directories which should be built and installed.
+SUBDIRS = libmpq
+
+# The directories which are part of the distribution.
+DIST_SUBDIRS = $(SUBDIRS)
+
+EXTRA_DIST = \
+ README.linux
diff --git a/contrib/extractor/README.linux b/contrib/extractor/README.linux
new file mode 100644
index 00000000000..e1ebdb8bb2e
--- /dev/null
+++ b/contrib/extractor/README.linux
@@ -0,0 +1,13 @@
+Linux instructions
+------------------
+
+1. Configure and build MaNGOS.
+2. cd contrib/map_extractor/libmpq/
+3. make
+4. cd ..
+5. make
+6. run ad
+
+if there are any problems create folder named .deps in contrib/map_extractor/
+it is old bug from first extractor and i am too lasy to fix it :)
+
diff --git a/contrib/extractor/System.cpp b/contrib/extractor/System.cpp
new file mode 100644
index 00000000000..090fc557ed7
--- /dev/null
+++ b/contrib/extractor/System.cpp
@@ -0,0 +1,320 @@
+#define _CRT_SECURE_NO_DEPRECATE
+
+#include <stdio.h>
+#include <deque>
+#include <set>
+
+#ifdef WIN32
+#include "direct.h"
+#else
+#include <sys/stat.h>
+#endif
+
+#include "dbcfile.h"
+#include "mpq_libmpq.h"
+
+extern unsigned int iRes;
+extern ArchiveSet gOpenArchives;
+
+bool ConvertADT(char*,char*);
+
+typedef struct{
+ char name[64];
+ unsigned int id;
+}map_id;
+
+typedef unsigned char uint8;
+typedef unsigned short uint16;
+typedef unsigned int uint32;
+
+map_id * map_ids;
+uint16 * areas;
+char output_path[128]=".";
+char input_path[128]=".";
+
+enum Extract
+{
+ EXTRACT_MAP = 1,
+ EXTRACT_DBC = 2
+};
+int extract = EXTRACT_MAP | EXTRACT_DBC;
+
+static char* const langs[]={"deDE", "enGB", "enUS", "esES", "frFR", "koKR", "zhCN", "zhTW", "enCN", "enTW", "esMX", "ruRU" };
+#define LANG_COUNT 12
+
+#define ADT_RES 64
+
+void CreateDir( const std::string& Path )
+{
+ #ifdef WIN32
+ _mkdir( Path.c_str());
+ #else
+ mkdir( Path.c_str(), 0777 );
+ #endif
+}
+
+bool FileExists( const char* FileName )
+{
+ if( FILE* fp = fopen( FileName, "rb" ) )
+ {
+ fclose( fp );
+ return true;
+ }
+
+ return false;
+}
+
+void Usage(char* prg)
+{
+ printf("Usage:\n%s -[var] [value]\n-i set input path\n-o set output path\n-r set resolution\n-e extract only MAP(1)/DBC(2) - standard: both(3)\nExample: %s -r 256 -i \"c:\\games\\game\"",
+ prg,prg);
+ exit(1);
+}
+
+void HandleArgs(int argc, char * arg[])
+{
+ for(int c=1;c<argc;c++)
+ {
+ //i - input path
+ //o - output path
+ //r - resolution, array of (r * r) heights will be created
+ //e - extract only MAP(1)/DBC(2) - standard both(3)
+ if(arg[c][0] != '-')
+ Usage(arg[0]);
+
+ switch(arg[c][1])
+ {
+ case 'i':
+ if(c+1<argc)//all ok
+ strcpy(input_path,arg[(c++) +1]);
+ else
+ Usage(arg[0]);
+ break;
+ case 'o':
+ if(c+1<argc)//all ok
+ strcpy(output_path,arg[(c++) +1]);
+ else
+ Usage(arg[0]);
+ break;
+ case 'r':
+ if(c+1<argc)//all ok
+ iRes=atoi(arg[(c++) +1]);
+ else
+ Usage(arg[0]);
+ break;
+ case 'e':
+ if(c+1<argc)//all ok
+ {
+ extract=atoi(arg[(c++) +1]);
+ if(!(extract > 0 && extract < 4))
+ Usage(arg[0]);
+ }
+ else
+ Usage(arg[0]);
+ break;
+ }
+ }
+}
+
+uint32 ReadMapDBC()
+{
+ printf("Read Map.dbc file... ");
+ DBCFile dbc("DBFilesClient\\Map.dbc");
+ dbc.open();
+
+ uint32 map_count=dbc.getRecordCount();
+ map_ids=new map_id[map_count];
+ for(unsigned int x=0;x<map_count;x++)
+ {
+ map_ids[x].id=dbc.getRecord(x).getUInt(0);
+ strcpy(map_ids[x].name,dbc.getRecord(x).getString(1));
+ }
+ printf("Done! (%u maps loaded)\n", map_count);
+ return map_count;
+}
+
+void ReadAreaTableDBC()
+{
+ printf("Read AreaTable.dbc file... ");
+ DBCFile dbc("DBFilesClient\\AreaTable.dbc");
+ dbc.open();
+
+ unsigned int area_count=dbc.getRecordCount();
+ uint32 maxid = dbc.getMaxId();
+ areas=new uint16[maxid + 1];
+ memset(areas, 0xff, sizeof(areas));
+ for(unsigned int x=0; x<area_count;++x)
+ areas[dbc.getRecord(x).getUInt(0)] = dbc.getRecord(x).getUInt(3);
+
+ printf("Done! (%u areas loaded)\n", area_count);
+}
+
+void ExtractMapsFromMpq()
+{
+ char mpq_filename[1024];
+ char output_filename[1024];
+
+ printf("Extracting maps...\n");
+
+ uint32 map_count = ReadMapDBC();
+
+ ReadAreaTableDBC();
+
+ unsigned int total=map_count*ADT_RES*ADT_RES;
+ unsigned int done=0;
+
+ std::string path = output_path;
+ path += "/maps/";
+ CreateDir(path);
+
+ for(int x = 0; x < ADT_RES; ++x)
+ {
+ for(int y = 0; y < ADT_RES; ++y)
+ {
+ for(int z = 0; z < map_count; ++z)
+ {
+ sprintf(mpq_filename,"World\\Maps\\%s\\%s_%u_%u.adt",map_ids[z].name,map_ids[z].name,x,y);
+ sprintf(output_filename,"%s/maps/%03u%02u%02u.map",output_path,map_ids[z].id,y,x);
+ ConvertADT(mpq_filename,output_filename);
+ done++;
+ }
+ //draw progess bar
+ printf("Processing........................%d%%\r",(100*done)/total);
+ }
+ }
+
+ delete [] areas;
+ delete [] map_ids;
+}
+
+//bool WMO(char* filename);
+
+void ExtractDBCFiles()
+{
+ printf("Extracting dbc files...\n");
+
+ set<string> dbcfiles;
+
+ // get DBC file list
+ for(ArchiveSet::iterator i = gOpenArchives.begin(); i != gOpenArchives.end();++i)
+ {
+ vector<string> files = (*i)->GetFileList();
+ for (vector<string>::iterator iter = files.begin(); iter != files.end(); ++iter)
+ if (iter->rfind(".dbc") == iter->length() - strlen(".dbc"))
+ dbcfiles.insert(*iter);
+ }
+
+ std::string path = output_path;
+ path += "/dbc/";
+ CreateDir(path);
+
+ // extract DBCs
+ int count = 0;
+ for (set<string>::iterator iter = dbcfiles.begin(); iter != dbcfiles.end(); ++iter)
+ {
+ string filename = output_path;
+ filename += "/dbc/";
+ filename += (iter->c_str() + strlen("DBFilesClient\\"));
+
+ //cout << filename << endl;
+
+ FILE *output=fopen(filename.c_str(),"wb");
+ if(!output)
+ {
+ printf("Can't create the output file '%s'\n",filename.c_str());
+ continue;
+ }
+ MPQFile m(iter->c_str());
+ if(!m.isEof())
+ fwrite(m.getPointer(),1,m.getSize(),output);
+
+ fclose(output);
+ ++count;
+ }
+ printf("Extracted %u DBC files\n", count);
+}
+
+int GetLocale()
+{
+ for (int i = 0; i < LANG_COUNT; i++)
+ {
+ char tmp1[512];
+ sprintf(tmp1, "%s/Data/%s/locale-%s.MPQ", input_path, langs[i], langs[i]);
+ if (FileExists(tmp1))
+ {
+ printf("Detected locale: %s\n", langs[i]);
+ return i;
+ }
+ }
+
+ printf("Could not detect locale.\n");
+ return -1;
+}
+
+void LoadMPQFiles(int const locale)
+{
+ char filename[512];
+
+ sprintf(filename,"%s/Data/%s/locale-%s.MPQ",input_path,langs[locale],langs[locale]);
+ new MPQArchive(filename);
+
+ for(int i = 1; i < 5; ++i)
+ {
+ char ext[3] = "";
+ if(i > 1)
+ sprintf(ext, "-%i", i);
+
+ sprintf(filename,"%s/Data/%s/patch-%s%s.MPQ",input_path,langs[locale],langs[locale],ext);
+ if(!FileExists(filename))
+ break;
+ new MPQArchive(filename);
+ }
+
+ //need those files only if extract maps
+ if(extract & EXTRACT_MAP)
+ {
+ sprintf(filename,"%s/Data/common.MPQ",input_path);
+ new MPQArchive(filename);
+ sprintf(filename,"%s/Data/expansion.MPQ",input_path);
+ new MPQArchive(filename);
+
+ for(int i = 1; i < 5; ++i)
+ {
+ char ext[3] = "";
+ if(i > 1)
+ sprintf(ext, "-%i", i);
+
+ sprintf(filename,"%s/Data/patch%s.MPQ",input_path,ext);
+ if(!FileExists(filename))
+ break;
+ new MPQArchive(filename);
+ }
+ }
+}
+
+int main(int argc, char * arg[])
+{
+ printf("Map & DBC Extractor\n");
+ printf("===================\n");
+
+ HandleArgs(argc, arg);
+
+ int const locale = GetLocale();
+ if(locale < 0)
+ return 1;
+
+ LoadMPQFiles(locale);
+
+ if(extract & EXTRACT_DBC)
+ ExtractDBCFiles();
+
+ if(extract & EXTRACT_MAP)
+ ExtractMapsFromMpq();
+
+ //Close MPQs
+ for(ArchiveSet::iterator i = gOpenArchives.begin(); i != gOpenArchives.end();++i)
+ (*i)->close();
+ gOpenArchives.clear();
+
+ return 0;
+}
diff --git a/contrib/extractor/VC71_AD.sln b/contrib/extractor/VC71_AD.sln
new file mode 100644
index 00000000000..f914661b1a1
--- /dev/null
+++ b/contrib/extractor/VC71_AD.sln
@@ -0,0 +1,19 @@
+Microsoft Visual Studio Solution File, Format Version 8.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ad", "VC71_ad.vcproj", "{D7552D4F-408F-4F8E-859B-366659150CF4}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {D7552D4F-408F-4F8E-859B-366659150CF4}.Debug|Win32.ActiveCfg = Debug|Win32
+ {D7552D4F-408F-4F8E-859B-366659150CF4}.Debug|Win32.Build.0 = Debug|Win32
+ {D7552D4F-408F-4F8E-859B-366659150CF4}.Release|Win32.ActiveCfg = Release|Win32
+ {D7552D4F-408F-4F8E-859B-366659150CF4}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/contrib/extractor/VC71_ad.vcproj b/contrib/extractor/VC71_ad.vcproj
new file mode 100644
index 00000000000..b1154138251
--- /dev/null
+++ b/contrib/extractor/VC71_ad.vcproj
@@ -0,0 +1,316 @@
+<?xml version="1.0" encoding="windows-1251"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="ad"
+ ProjectGUID="{D7552D4F-408F-4F8E-859B-366659150CF4}"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="."
+ IntermediateDirectory=".\debug\"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="_DEBUG"
+ MkTypLibCompatible="true"
+ SuppressStartupBanner="true"
+ TargetEnvironment="1"
+ TypeLibraryName="./ad.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="libmpq"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile="c:\windows\temp/ad.pch"
+ AssemblerListingLocation="c:\windows\temp/"
+ ObjectFile="c:\windows\temp/"
+ ProgramDataBaseFileName="c:\windows\temp/"
+ BrowseInformation="1"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1049"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="zlib.lib"
+ OutputFile="ad debug.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="true"
+ AdditionalLibraryDirectories="./debug/"
+ IgnoreDefaultLibraryNames="LIBCD.lib"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="./ad debug.pdb"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="."
+ IntermediateDirectory=".\release"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="NDEBUG"
+ MkTypLibCompatible="true"
+ SuppressStartupBanner="true"
+ TargetEnvironment="1"
+ TypeLibraryName="./ad.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="libmpq"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile="c:\windows\temp/ad.pch"
+ AssemblerListingLocation="c:\windows\temp/"
+ ObjectFile="c:\windows\temp/"
+ ProgramDataBaseFileName="c:\windows\temp/"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1049"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="zlib.lib"
+ OutputFile="./ad.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="true"
+ AdditionalLibraryDirectories="./release/"
+ IgnoreDefaultLibraryNames="LIBC.lib"
+ ProgramDatabaseFile="./ad.pdb"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+ >
+ <File
+ RelativePath=".\adt.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libmpq\common.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\dbcfile.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libmpq\explode.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libmpq\extract.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libmpq\huffman.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libmpq\mpq.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\mpq_libmpq.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libmpq\parser.cpp"
+ >
+ </File>
+ <File
+ RelativePath="system.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\libmpq\wave.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl"
+ >
+ <File
+ RelativePath=".\libmpq\common.h"
+ >
+ </File>
+ <File
+ RelativePath=".\dbcfile.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libmpq\explode.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libmpq\huffman.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libmpq\mpq.h"
+ >
+ </File>
+ <File
+ RelativePath=".\mpq_libmpq.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libmpq\wave.h"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/contrib/extractor/VC80_AD.sln b/contrib/extractor/VC80_AD.sln
new file mode 100644
index 00000000000..1c46986e858
--- /dev/null
+++ b/contrib/extractor/VC80_AD.sln
@@ -0,0 +1,19 @@
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ad", "VC80_ad.vcproj", "{D7552D4F-408F-4F8E-859B-366659150CF4}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {D7552D4F-408F-4F8E-859B-366659150CF4}.Debug|Win32.ActiveCfg = Debug|Win32
+ {D7552D4F-408F-4F8E-859B-366659150CF4}.Debug|Win32.Build.0 = Debug|Win32
+ {D7552D4F-408F-4F8E-859B-366659150CF4}.Release|Win32.ActiveCfg = Release|Win32
+ {D7552D4F-408F-4F8E-859B-366659150CF4}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/contrib/extractor/VC80_ad.vcproj b/contrib/extractor/VC80_ad.vcproj
new file mode 100644
index 00000000000..ddf423c4bde
--- /dev/null
+++ b/contrib/extractor/VC80_ad.vcproj
@@ -0,0 +1,339 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8,00"
+ Name="ad"
+ ProjectGUID="{D7552D4F-408F-4F8E-859B-366659150CF4}"
+ RootNamespace="ad"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="."
+ IntermediateDirectory=".\debug\"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="_DEBUG"
+ MkTypLibCompatible="true"
+ SuppressStartupBanner="true"
+ TargetEnvironment="1"
+ TypeLibraryName="./ad.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/wd4018"
+ Optimization="0"
+ AdditionalIncludeDirectories="libmpq"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile="c:\windows\temp/ad.pch"
+ AssemblerListingLocation="c:\windows\temp/"
+ ObjectFile="c:\windows\temp/"
+ ProgramDataBaseFileName="c:\windows\temp/"
+ BrowseInformation="1"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1049"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="zlib.lib"
+ OutputFile="ad debug.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="true"
+ AdditionalLibraryDirectories="./debug/"
+ IgnoreDefaultLibraryNames="LIBCD.lib"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="./ad debug.pdb"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="."
+ IntermediateDirectory=".\release"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="NDEBUG"
+ MkTypLibCompatible="true"
+ SuppressStartupBanner="true"
+ TargetEnvironment="1"
+ TypeLibraryName="./ad.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/wd4018"
+ Optimization="3"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="libmpq"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile="c:\windows\temp/ad.pch"
+ AssemblerListingLocation="c:\windows\temp/"
+ ObjectFile="c:\windows\temp/"
+ ProgramDataBaseFileName="c:\windows\temp/"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1049"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="zlib.lib"
+ OutputFile="./ad.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="true"
+ AdditionalLibraryDirectories="./release/"
+ IgnoreDefaultLibraryNames="LIBC.lib"
+ ProgramDatabaseFile="./ad.pdb"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+ >
+ <File
+ RelativePath=".\adt.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\dbcfile.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\mpq_libmpq.cpp"
+ >
+ </File>
+ <File
+ RelativePath="system.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <Filter
+ Name="libmpq"
+ >
+ <File
+ RelativePath=".\libmpq\common.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libmpq\explode.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libmpq\extract.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libmpq\huffman.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libmpq\mpq.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libmpq\parser.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libmpq\wave.cpp"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl"
+ >
+ <File
+ RelativePath=".\adt.h"
+ >
+ </File>
+ <File
+ RelativePath=".\dbcfile.h"
+ >
+ </File>
+ <File
+ RelativePath=".\mpq_libmpq.h"
+ >
+ </File>
+ <Filter
+ Name="libmpq"
+ >
+ <File
+ RelativePath=".\libmpq\common.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libmpq\explode.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libmpq\huffman.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libmpq\mpq.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libmpq\wave.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libmpq\zconf.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libmpq\zlib.h"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/contrib/extractor/VC90_AD.sln b/contrib/extractor/VC90_AD.sln
new file mode 100644
index 00000000000..68dd66e1f7f
--- /dev/null
+++ b/contrib/extractor/VC90_AD.sln
@@ -0,0 +1,19 @@
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ad", "VC90_ad.vcproj", "{D7552D4F-408F-4F8E-859B-366659150CF4}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {D7552D4F-408F-4F8E-859B-366659150CF4}.Debug|Win32.ActiveCfg = Debug|Win32
+ {D7552D4F-408F-4F8E-859B-366659150CF4}.Debug|Win32.Build.0 = Debug|Win32
+ {D7552D4F-408F-4F8E-859B-366659150CF4}.Release|Win32.ActiveCfg = Release|Win32
+ {D7552D4F-408F-4F8E-859B-366659150CF4}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/contrib/extractor/VC90_ad.vcproj b/contrib/extractor/VC90_ad.vcproj
new file mode 100644
index 00000000000..148c33643c3
--- /dev/null
+++ b/contrib/extractor/VC90_ad.vcproj
@@ -0,0 +1,315 @@
+<?xml version="1.0" encoding="windows-1251"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9,00"
+ Name="ad"
+ ProjectGUID="{D7552D4F-408F-4F8E-859B-366659150CF4}"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="."
+ IntermediateDirectory=".\debug\"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="_DEBUG"
+ MkTypLibCompatible="true"
+ SuppressStartupBanner="true"
+ TargetEnvironment="1"
+ TypeLibraryName="./ad.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="libmpq"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile="c:\windows\temp/ad.pch"
+ AssemblerListingLocation="c:\windows\temp/"
+ ObjectFile="c:\windows\temp/"
+ ProgramDataBaseFileName="c:\windows\temp/"
+ BrowseInformation="1"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1049"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="zlib.lib"
+ OutputFile="ad debug.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="true"
+ AdditionalLibraryDirectories="./debug/"
+ IgnoreDefaultLibraryNames="LIBCD.lib"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="./ad debug.pdb"
+ SubSystem="1"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="."
+ IntermediateDirectory=".\release"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="NDEBUG"
+ MkTypLibCompatible="true"
+ SuppressStartupBanner="true"
+ TargetEnvironment="1"
+ TypeLibraryName="./ad.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="libmpq"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile="c:\windows\temp/ad.pch"
+ AssemblerListingLocation="c:\windows\temp/"
+ ObjectFile="c:\windows\temp/"
+ ProgramDataBaseFileName="c:\windows\temp/"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1049"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="zlib.lib"
+ OutputFile="./ad.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="true"
+ AdditionalLibraryDirectories="./release/"
+ IgnoreDefaultLibraryNames="LIBC.lib"
+ ProgramDatabaseFile="./ad.pdb"
+ SubSystem="1"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+ >
+ <File
+ RelativePath=".\adt.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libmpq\common.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\dbcfile.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libmpq\explode.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libmpq\extract.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libmpq\huffman.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libmpq\mpq.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\mpq_libmpq.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libmpq\parser.cpp"
+ >
+ </File>
+ <File
+ RelativePath="system.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\libmpq\wave.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl"
+ >
+ <File
+ RelativePath=".\libmpq\common.h"
+ >
+ </File>
+ <File
+ RelativePath=".\dbcfile.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libmpq\explode.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libmpq\huffman.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libmpq\mpq.h"
+ >
+ </File>
+ <File
+ RelativePath=".\mpq_libmpq.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libmpq\wave.h"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/contrib/extractor/ad b/contrib/extractor/ad
new file mode 100644
index 00000000000..564eceaaa5f
--- /dev/null
+++ b/contrib/extractor/ad
Binary files differ
diff --git a/contrib/extractor/ad.exe b/contrib/extractor/ad.exe
new file mode 100644
index 00000000000..e9606e8e0eb
--- /dev/null
+++ b/contrib/extractor/ad.exe
Binary files differ
diff --git a/contrib/extractor/adt.cpp b/contrib/extractor/adt.cpp
new file mode 100644
index 00000000000..26adaa28537
--- /dev/null
+++ b/contrib/extractor/adt.cpp
@@ -0,0 +1,501 @@
+#define _CRT_SECURE_NO_DEPRECATE
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+#include <string>
+#include <map>
+#include <vector>
+#include <set>
+
+#include "adt.h"
+#include "mpq_libmpq.h"
+
+//#include <windows.h>
+unsigned int iRes=256;
+extern uint16*areas;
+
+vec wmoc;
+
+Cell * cell;
+uint32 wmo_count;
+mcell *mcells;
+
+int holetab_h[4] = {0x1111, 0x2222, 0x4444, 0x8888};
+int holetab_v[4] = {0x000F, 0x00F0, 0x0F00, 0xF000};
+
+bool LoadADT(char* filename)
+{
+ size_t size;
+ MPQFile mf(filename);
+
+ if(mf.isEof())
+ {
+ //printf("No such file.\n");
+ return false;
+ }
+ mcells=new mcell;
+
+ wmoc.x =65*TILESIZE;
+ wmoc.z =65*TILESIZE;
+
+ size_t mcnk_offsets[256], mcnk_sizes[256];
+
+ wmo_count=0;
+ bool found=false;
+ //uint32 fs=mf.getSize()-3;
+ //while (mf.getPos()<fs)
+ while (!mf.isEof())
+ {
+ uint32 fourcc;
+ mf.read(&fourcc,4);
+ mf.read(&size, 4);
+
+ size_t nextpos = mf.getPos() + size;
+ switch(fourcc)
+ {
+ case 0x4d43494e: // MCIN
+ {
+ //printf("Found chunks info\n");
+ // mapchunk offsets/sizes
+ for (int i=0; i<256; i++)
+ {
+ mf.read(&mcnk_offsets[i],4);
+ mf.read(&mcnk_sizes[i],4);
+ mf.seekRelative(8);
+ }
+ break;
+ }
+ case 0x4d4f4446: // MODF
+ {
+ /*
+ if(size)
+ {
+ //printf("\nwmo count %d\n",size/64);
+ wmo_count =size/64;
+ for (int i=0; i<wmo_count; i++)
+ {
+ int id;
+ mf.read(&id, 4);
+ WMO *wmo = (WMO*)wmomanager.items[wmomanager.get(wmos[id])];
+ WMOInstance inst(wmo, mf);
+ wmois.push_back(inst);
+ }
+
+ }*/
+ break;
+ }
+ case 0x4d574d4f: // MWMO
+ {
+ /*
+ if (size)
+ {
+ char *buf = new char[size];
+ mf.read(buf, size);
+ char *p=buf;
+ while (p<buf+size)
+ {
+ std::string path(p);
+ p+=strlen(p)+1;
+ fixname(path);
+
+ wmomanager.add(path);
+ wmos.push_back(path);
+ }
+ delete[] buf;
+ }*/
+ break;
+ }
+ case 0x4d564552: // MVER
+ case 0x4d484452: // MHDR header
+ case 0x4d434e4b: // MCNK
+ case 0x4d544558: // MTEX textures (strings)
+ case 0x4d4d4458: // MMDX m2 models (strings)
+ case 0x4d4d4944: // MMID offsets for strings in MMDX
+ case 0x4d574944: // MWID offsets for strings in MWMO
+ case 0x4d444446: // MDDF
+ case 0x4d46424f: // MFBO new in BC
+ case 0x4d48324f: // MH2O new in WotLK
+ break;
+ default:
+ {
+ // mf.seekRelative(-3);
+ printf("Unhandled map chunk: %u\n",fourcc);
+ break;
+ }
+ }
+ mf.seek(nextpos);
+ }
+
+ //printf("Loading chunks info\n");
+ // read individual map chunks
+ for (int j=0; j<16; j++)
+ for (int i=0; i<16; i++)
+ {
+ mf.seek((int)mcnk_offsets[j*16+i]);
+ LoadMapChunk(mf,&(mcells->ch[i][j]));
+ }
+
+ /*
+ for(uint32 t=0;t<wmo_count ;t++)
+ {
+ wmois[t].draw();
+ }*/
+
+ mf.close();
+ return true;
+}
+
+struct MapChunkHeader {
+ uint32 flags;
+ uint32 ix;
+ uint32 iy;
+ uint32 nLayers;
+ uint32 nDoodadRefs;
+ uint32 ofsHeight;
+ uint32 ofsNormal;
+ uint32 ofsLayer;
+ uint32 ofsRefs;
+ uint32 ofsAlpha;
+ uint32 sizeAlpha;
+ uint32 ofsShadow;
+ uint32 sizeShadow;
+ uint32 areaid;
+ uint32 nMapObjRefs;
+ uint32 holes;
+ uint16 s1;
+ uint16 s2;
+ uint32 d1;
+ uint32 d2;
+ uint32 d3;
+ uint32 predTex;
+ uint32 nEffectDoodad;
+ uint32 ofsSndEmitters;
+ uint32 nSndEmitters;
+ uint32 ofsLiquid;
+ uint32 sizeLiquid;
+ float zpos;
+ float xpos;
+ float ypos;
+ uint32 textureId;
+ uint32 props;
+ uint32 effectId;
+};
+
+bool isHole(int holes, int i, int j)
+{
+ int testi = i/2;
+ int testj = j/4;
+ if(testi>3) testi = 3;
+ if(testj>3) testj = 3;
+ return (holes & holetab_h[testi] & holetab_v[testj])!=0;
+}
+
+inline
+void LoadMapChunk(MPQFile & mf, chunk*_chunk)
+{
+ float h;
+ uint32 fourcc;
+ uint32 size;
+ MapChunkHeader header;
+
+ mf.seekRelative(4);
+ mf.read(&size, 4);
+
+ size_t lastpos = mf.getPos() + size;
+ mf.read(&header, 0x80);
+ _chunk->area_id =header.areaid ;
+ _chunk->flag =0;
+
+ float xbase = header.xpos;
+ float ybase = header.ypos;
+ float zbase = header.zpos;
+ zbase = TILESIZE*32-zbase;
+ xbase = TILESIZE*32-xbase;
+ if(wmoc.x >xbase)wmoc.x =xbase;
+ if(wmoc.z >zbase)wmoc.z =zbase;
+ int chunkflags = header.flags;
+ float zmin=999999999.0f;
+ float zmax=-999999999.0f;
+ //must be there, bl!zz uses some crazy format
+ int nTextures;
+ while (mf.getPos() < lastpos)
+ {
+ mf.read(&fourcc,4);
+ mf.read(&size, 4);
+ //if(size!=580)
+ // printf("\n sz=%d",size);
+ size_t nextpos = mf.getPos() + size;
+ if(fourcc==0x4d435654) // MCVT
+ {
+ for (int j=0; j<17; j++)
+ for (int i=0; i<((j%2)?8:9); i++)
+ {
+ mf.read(&h,4);
+ float z=h+ybase;
+ if (j%2)
+ {
+ if(isHole(header.holes,i,j))
+ _chunk->v8[i][j/2] = -1000;
+ else
+ _chunk->v8[i][j/2] = z;
+ }
+ else
+ {
+ if(isHole(header.holes,i,j))
+ _chunk->v9[i][j/2] = -1000;
+ else
+ _chunk->v9[i][j/2] = z;
+ }
+
+ if(z>zmax)zmax=z;
+ //if(z<zmin)zmin=z;
+ }
+ }
+ else if(fourcc==0x4d434e52) // MCNR
+ {
+ nextpos = mf.getPos() + 0x1C0; // size fix
+ }
+ else if(fourcc==0x4d434c51) // MCLQ
+ {
+ // liquid / water level
+ //bool haswater;
+ char fcc1[5];
+ mf.read(fcc1,4);
+ flipcc(fcc1);
+ fcc1[4]=0;
+
+ if (!strcmp(fcc1,"MCSE"))
+ {
+ for(int i=0;i<9;i++)
+ for(int j=0;j<9;j++)
+ _chunk->waterlevel[i][j]=-999999; // no liquid/water
+ }
+ else
+ {
+ float maxheight;
+ mf.read(&maxheight, 4);
+
+ for(int j=0;j<9;j++)
+ for(int i=0;i<9;i++)
+ {
+ mf.read(&h, 4);
+ mf.read(&h, 4);
+ if(h > maxheight)
+ _chunk->waterlevel[i][j]=-999999;
+ else
+ _chunk->waterlevel[i][j]=h;
+ }
+
+ if(chunkflags & 4 || chunkflags & 8)
+ _chunk->flag |=1;
+ if(chunkflags & 16)
+ _chunk->flag |=2;
+
+ }
+ break;
+ }
+ else if (fourcc==0x4d434c59) // MCLY
+ {
+ // texture info
+ nTextures = (int)size;
+ }
+ else if (fourcc==0x4d43414c) // MCAL
+ {
+ if (nTextures<=0)
+ continue;
+ }
+
+ mf.seek(nextpos);
+ }
+}
+
+double solve (vec *v,vec *p)
+{
+ double a = v[0].y *(v[1].z - v[2].z) + v[1].y *(v[2].z - v[0].z) + v[2].y *(v[0].z - v[1].z);
+ double b = v[0].z *(v[1].x - v[2].x) + v[1].z *(v[2].x - v[0].x) + v[2].z *(v[0].x - v[1].x);
+ double c = v[0].x *(v[1].y - v[2].y) + v[1].x *(v[2].y - v[0].y) + v[2].x *(v[0].y - v[1].y);
+ double d = v[0].x *(v[1].y*v[2].z - v[2].y*v[1].z) + v[1].x* (v[2].y*v[0].z - v[0].y*v[2].z) + v[2].x* (v[0].y*v[1].z - v[1].y*v[0].z);
+ //-d
+
+ //plane equation ax+by+cz+d=0
+ return ((a*p->x+c*p->z-d)/b);
+}
+
+inline
+double GetZ(double x,double z)
+{
+ vec v[3];
+ vec p;
+
+ //bool inWMO=false;
+
+ //if(!inWMO)
+ {
+ //find out quadrant
+ int xc=(int)(x/UNITSIZE);
+ int zc=(int)(z/UNITSIZE);
+ if(xc>127)xc=127;
+ if(zc>127)zc=127;
+
+ double lx=x-xc*UNITSIZE;
+ double lz=z-zc*UNITSIZE;
+ p.x=lx;
+ p.z=lz;
+
+ v[0].x=UNITSIZE/2;
+ v[0].y =cell->v8[xc][zc];
+ v[0].z=UNITSIZE/2;
+
+ if(lx>lz)
+ {
+ v[1].x=UNITSIZE;
+ v[1].y =cell->v9[xc+1][zc];
+ v[1].z=0;
+ }
+ else
+ {
+ v[1].x=0.0;
+ v[1].y =cell->v9[xc][zc+1];
+ v[1].z=UNITSIZE;
+ }
+
+ if(lz>UNITSIZE-lx)
+ {
+ v[2].x=UNITSIZE;
+ v[2].y =cell->v9[xc+1][zc+1];
+ v[2].z=UNITSIZE;
+ }
+ else
+ {
+ v[2].x=0;
+ v[2].y=cell->v9[xc][zc];
+ v[2].z=0;
+ }
+
+ return -solve(v,&p);
+ }
+}
+
+inline
+void TransformWaterData()
+{
+ cell= new Cell;
+
+ for(int x=0;x<128;x++)
+ for(int y=0;y<128;y++)
+ cell->v9[x][y] = mcells->ch[x/8][y/8].waterlevel[x%8][y%8];
+
+ //and the last 1
+ cell->v9[128][128] = mcells->ch[15][15].waterlevel[8][8];
+}
+
+inline
+void TransformData()
+{
+ cell= new Cell;
+
+ for(int x=0;x<128;x++)
+ {
+ for(int y=0;y<128;y++)
+ {
+ cell->v8[x][y] = (float)mcells->ch[x/8][y/8].v8[x%8][y%8];
+ cell->v9[x][y] = (float)mcells->ch[x/8][y/8].v9[x%8][y%8];
+ }
+
+ //extra 1 point on bounds
+ cell->v9[x][128] = (float)mcells->ch[x/8][15].v9[x%8][8];
+ //x==y
+ cell->v9[128][x] = (float)mcells->ch[15][x/8].v9[8][x%8];
+
+ }
+
+ //and the last 1
+ cell->v9[128][128] = (float)mcells->ch[15][15].v9[8][8];
+
+ delete mcells;
+}
+
+const char MAP_MAGIC[] = "MAP_2.00";
+
+bool ConvertADT(char * filename,char * filename2)
+{
+ //if(!strstr(filename,"oth_32_48"))return false;
+ if(!LoadADT(filename))
+ return false;
+
+ FILE *output=fopen(filename2,"wb");
+ if(!output)
+ {
+ printf("Can't create the output file '%s'\n",filename2);
+ return false;
+ }
+
+ // write magic header
+ fwrite(MAP_MAGIC,1,8,output);
+
+ for(unsigned int x=0;x<16;x++)
+ {
+ for(unsigned int y=0;y<16;y++)
+ {
+ if(mcells->ch[y][x].area_id && mcells->ch[y][x].area_id < 0x102D)
+ {
+ if(areas[mcells->ch[y][x].area_id]==0xffff)
+ printf("\nCan't find area flag for areaid %u.\n",mcells->ch[y][x].area_id);
+
+ fwrite(&areas[mcells->ch[y][x].area_id],1,2,output);
+ }
+ else
+ {
+ uint16 flag=0xffff;
+ fwrite(&flag,1,2,output);
+ }
+ }
+ }
+
+ for(unsigned int x=0;x<16;x++)
+ for(unsigned int y=0;y<16;y++)
+ fwrite(&mcells->ch[y][x].flag,1,1,output);
+
+ TransformWaterData();
+
+ for(unsigned int x=0;x<128;x++)
+ for(unsigned int y=0;y<128;y++)
+ fwrite(&cell->v9[y][x],1,sizeof(float),output);
+
+ delete cell;
+ TransformData();
+
+ for(unsigned int x=0;x<iRes;x++)
+ for(unsigned int y=0;y<iRes;y++)
+ {
+ float z=(float)GetZ(
+ (((double)(y))*TILESIZE)/((double)(iRes-1)),
+ (((double)(x))*TILESIZE)/((double)(iRes-1)));
+
+ fwrite(&z,1,sizeof(z),output);
+ }
+
+ fclose(output);
+ delete cell;
+/*
+ for (std::vector<std::string>::iterator it = wmos.begin(); it != wmos.end(); ++it)
+ wmomanager.delbyname(*it);
+
+ wmos.clear();
+ wmois.clear();
+
+ for (std::vector<model>::iterator it = wmomodel.begin(); it != wmomodel.end(); ++it)
+ {
+ it->tr.clear();
+
+ }
+ //printf("\n %d \n",in);
+ wmomodel.clear();
+ //polygons.clear();*/
+ return true;
+}
diff --git a/contrib/extractor/adt.h b/contrib/extractor/adt.h
new file mode 100644
index 00000000000..6e079461a66
--- /dev/null
+++ b/contrib/extractor/adt.h
@@ -0,0 +1,54 @@
+#ifndef ADT_H
+#define ADT_H
+
+#define TILESIZE (533.33333f)
+#define CHUNKSIZE ((TILESIZE) / 16.0f)
+#define UNITSIZE (CHUNKSIZE / 8.0f)
+
+typedef unsigned char uint8;
+typedef unsigned short uint16;
+typedef unsigned int uint32;
+class Liquid;
+typedef struct {
+float x;
+float y;
+float z;
+}svec;
+
+typedef struct {
+double x;
+double y;
+double z;
+}vec;
+
+typedef struct{
+ vec v[3];
+}triangle;
+
+typedef struct{
+float v9[16*8+1][16*8+1];
+float v8[16*8][16*8];
+}Cell;
+
+typedef struct{
+double v9[9][9];
+double v8[8][8];
+uint16 area_id;
+//Liquid *lq;
+float waterlevel[9][9];
+uint8 flag;
+}chunk;
+
+class WMO;
+class WMOManager;
+void fixname(std::string &name);
+
+typedef struct
+{
+chunk ch[16][16];
+}mcell;
+class MPQFile;
+void LoadMapChunk(MPQFile &,chunk*);
+bool LoadWMO(char* filename);
+#endif
+
diff --git a/contrib/extractor/dbcfile.cpp b/contrib/extractor/dbcfile.cpp
new file mode 100644
index 00000000000..acfb35482ff
--- /dev/null
+++ b/contrib/extractor/dbcfile.cpp
@@ -0,0 +1,69 @@
+#define _CRT_SECURE_NO_DEPRECATE
+
+#include "dbcfile.h"
+#include "mpq_libmpq.h"
+
+DBCFile::DBCFile(const std::string &filename):
+ filename(filename),
+ data(0)
+{
+
+}
+void DBCFile::open()
+{
+ MPQFile f(filename.c_str());
+ char header[4];
+ unsigned int na,nb,es,ss;
+
+ f.read(header,4); // Number of records
+ assert(header[0]=='W' && header[1]=='D' && header[2]=='B' && header[3] == 'C');
+ f.read(&na,4); // Number of records
+ f.read(&nb,4); // Number of fields
+ f.read(&es,4); // Size of a record
+ f.read(&ss,4); // String size
+
+ recordSize = es;
+ recordCount = na;
+ fieldCount = nb;
+ stringSize = ss;
+ assert(fieldCount*4 == recordSize);
+
+ data = new unsigned char[recordSize*recordCount+stringSize];
+ stringTable = data + recordSize*recordCount;
+ f.read(data,recordSize*recordCount+stringSize);
+ f.close();
+}
+DBCFile::~DBCFile()
+{
+ delete [] data;
+}
+
+DBCFile::Record DBCFile::getRecord(size_t id)
+{
+ assert(data);
+ return Record(*this, data + id*recordSize);
+}
+
+size_t DBCFile::getMaxId()
+{
+ assert(data);
+
+ size_t maxId = 0;
+ for(size_t i = 0; i < getRecordCount(); ++i)
+ {
+ if(maxId < getRecord(i).getUInt(0))
+ maxId = getRecord(i).getUInt(0);
+ }
+ return maxId;
+}
+
+DBCFile::Iterator DBCFile::begin()
+{
+ assert(data);
+ return Iterator(*this, data);
+}
+DBCFile::Iterator DBCFile::end()
+{
+ assert(data);
+ return Iterator(*this, stringTable);
+}
diff --git a/contrib/extractor/dbcfile.h b/contrib/extractor/dbcfile.h
new file mode 100644
index 00000000000..521ca67423c
--- /dev/null
+++ b/contrib/extractor/dbcfile.h
@@ -0,0 +1,118 @@
+#ifndef DBCFILE_H
+#define DBCFILE_H
+#include <cassert>
+#include <string>
+
+class DBCFile
+{
+public:
+ DBCFile(const std::string &filename);
+ ~DBCFile();
+
+ // Open database. It must be openened before it can be used.
+ void open();
+
+ // Database exceptions
+ class Exception
+ {
+ public:
+ Exception(const std::string &message): message(message)
+ { }
+ virtual ~Exception()
+ { }
+ const std::string &getMessage() {return message;}
+ private:
+ std::string message;
+ };
+ class NotFound: public Exception
+ {
+ public:
+ NotFound(): Exception("Key was not found")
+ { }
+ };
+ // Iteration over database
+ class Iterator;
+ class Record
+ {
+ public:
+ float getFloat(size_t field) const
+ {
+ assert(field < file.fieldCount);
+ return *reinterpret_cast<float*>(offset+field*4);
+ }
+ unsigned int getUInt(size_t field) const
+ {
+ assert(field < file.fieldCount);
+ return *reinterpret_cast<unsigned int*>(offset+field*4);
+ }
+ int getInt(size_t field) const
+ {
+ assert(field < file.fieldCount);
+ return *reinterpret_cast<int*>(offset+field*4);
+ }
+ const char *getString(size_t field) const
+ {
+ assert(field < file.fieldCount);
+ size_t stringOffset = getUInt(field);
+ assert(stringOffset < file.stringSize);
+ return reinterpret_cast<char*>(file.stringTable + stringOffset);
+ }
+ private:
+ Record(DBCFile &file, unsigned char *offset): file(file), offset(offset) {}
+ unsigned char *offset;
+ DBCFile &file;
+
+ friend class DBCFile;
+ friend class DBCFile::Iterator;
+ };
+ /** Iterator that iterates over records
+ */
+ class Iterator
+ {
+ public:
+ Iterator(DBCFile &file, unsigned char *offset):
+ record(file, offset) {}
+ /// Advance (prefix only)
+ Iterator & operator++() {
+ record.offset += record.file.recordSize;
+ return *this;
+ }
+ /// Return address of current instance
+ Record const & operator*() const { return record; }
+ const Record* operator->() const {
+ return &record;
+ }
+ /// Comparison
+ bool operator==(const Iterator &b) const
+ {
+ return record.offset == b.record.offset;
+ }
+ bool operator!=(const Iterator &b) const
+ {
+ return record.offset != b.record.offset;
+ }
+ private:
+ Record record;
+ };
+
+ // Get record by id
+ Record getRecord(size_t id);
+ /// Get begin iterator over records
+ Iterator begin();
+ /// Get begin iterator over records
+ Iterator end();
+ /// Trivial
+ size_t getRecordCount() const { return recordCount;}
+ size_t getFieldCount() const { return fieldCount; }
+ size_t getMaxId();
+private:
+ std::string filename;
+ size_t recordSize;
+ size_t recordCount;
+ size_t fieldCount;
+ size_t stringSize;
+ unsigned char *data;
+ unsigned char *stringTable;
+};
+
+#endif
diff --git a/contrib/extractor/debug/zlib.lib b/contrib/extractor/debug/zlib.lib
new file mode 100644
index 00000000000..ffd7d9a2605
--- /dev/null
+++ b/contrib/extractor/debug/zlib.lib
Binary files differ
diff --git a/contrib/extractor/libmpq/Makefile b/contrib/extractor/libmpq/Makefile
new file mode 100644
index 00000000000..eb1965e29f1
--- /dev/null
+++ b/contrib/extractor/libmpq/Makefile
@@ -0,0 +1,17 @@
+CC = g++
+AR = ar
+objects = common.o explode.o extract.o huffman.o wave.o mpq.o parser.o
+zlib_objects = ../../../dep/src/zlib/*.o #adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o zutil.o inflate.o inftrees.o inffast.o
+
+all: libmpq.a libmpq.so
+
+clean:
+ rm -f libmpq.a libmpq.so *.o
+
+libmpq.a: $(objects) $(zlib_objects)
+ $(AR) cru $@ $+
+libmpq.so: $(objects) $(zlib_objects)
+ $(CC) -fPIC -o $@ $+
+
+%.o:%.cpp
+ $(CC) -I../ -c $+
diff --git a/contrib/extractor/libmpq/Makefile.am b/contrib/extractor/libmpq/Makefile.am
new file mode 100644
index 00000000000..192bd1369ef
--- /dev/null
+++ b/contrib/extractor/libmpq/Makefile.am
@@ -0,0 +1,23 @@
+# The input Makefile for the main mpq-tools
+
+lib_LTLIBRARIES = libmpq.la
+noinst_HEADERS = explode.h huffman.h wave.h common.h
+
+# The directory where the include files will be installed.
+libmpq_includedir = $(includedir)/libmpq
+
+# Which header files to install.
+libmpq_include_HEADERS = mpq.h
+
+libmpq_la_SOURCES = $(GENERAL_SRCS)
+libmpq_la_LDFLAGS = -release $(LIBMPQ_VERSION)
+libmpq_la_LIBADD = @Z_LIBS@
+
+GENERAL_SRCS = \
+ common.c \
+ huffman.c \
+ extract.c \
+ explode.c \
+ mpq.c \
+ parser.c \
+ wave.c
diff --git a/contrib/extractor/libmpq/common.cpp b/contrib/extractor/libmpq/common.cpp
new file mode 100644
index 00000000000..7b902087540
--- /dev/null
+++ b/contrib/extractor/libmpq/common.cpp
@@ -0,0 +1,801 @@
+/*
+ * common.c -- shared functions used by mpq-tools.
+ *
+ * Copyright (C) 2003 Maik Broemme <mbroemme@plusserver.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Id: common.c,v 1.12 2004/02/12 00:42:54 mbroemme Exp $
+ */
+#define _CRT_SECURE_NO_DEPRECATE
+//#include <dirent.h>
+#include <sys/stat.h>
+//#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include "mpq.h"
+#include "common.h"
+#include <ctype.h>
+
+/*
+ * This function decrypts a MPQ block.
+ */
+int libmpq_decrypt_block(mpq_archive *mpq_a, unsigned int *block, unsigned int length, unsigned int seed1) {
+ unsigned int seed2 = 0xEEEEEEEE;
+ unsigned int ch;
+
+ /* Round to unsigned int's */
+ length >>= 2;
+ while (length-- > 0) {
+ seed2 += mpq_a->buf[0x400 + (seed1 & 0xFF)];
+ ch = *block ^ (seed1 + seed2);
+ seed1 = ((~seed1 << 0x15) + 0x11111111) | (seed1 >> 0x0B);
+ seed2 = ch + seed2 + (seed2 << 5) + 3;
+ *block++ = ch;
+ }
+ return LIBMPQ_TOOLS_SUCCESS;
+}
+
+/*
+ * This function decrypts the hashtable for the
+ * file informations.
+ */
+int libmpq_decrypt_hashtable(mpq_archive *mpq_a, unsigned char *pbKey) {
+ unsigned int seed1 = 0x7FED7FED;
+ unsigned int seed2 = 0xEEEEEEEE;
+ unsigned int ch; /* One key character */
+ unsigned int *pdwTable = (unsigned int *)(mpq_a->hashtable);
+ unsigned int length = mpq_a->header->hashtablesize * 4;
+
+ /* Prepare seeds */
+ while (*pbKey != 0) {
+ ch = toupper(*pbKey++);
+ seed1 = mpq_a->buf[0x300 + ch] ^ (seed1 + seed2);
+ seed2 = ch + seed1 + seed2 + (seed2 << 5) + 3;
+ }
+
+ /* Decrypt it */
+ seed2 = 0xEEEEEEEE;
+ while (length-- > 0) {
+ seed2 += mpq_a->buf[0x400 + (seed1 & 0xFF)];
+ ch = *pdwTable ^ (seed1 + seed2);
+ seed1 = ((~seed1 << 0x15) + 0x11111111) | (seed1 >> 0x0B);
+ seed2 = ch + seed2 + (seed2 << 5) + 3;
+ *pdwTable++ = ch;
+ }
+ return LIBMPQ_TOOLS_SUCCESS;
+}
+
+/*
+ * This function decrypts the blocktable.
+ */
+int libmpq_decrypt_blocktable(mpq_archive *mpq_a, unsigned char *pbKey) {
+ unsigned int seed1 = 0x7FED7FED;
+ unsigned int seed2 = 0xEEEEEEEE;
+ unsigned int ch; /* One key character */
+ unsigned int *pdwTable = (unsigned int *)(mpq_a->blocktable);
+ unsigned int length = mpq_a->header->blocktablesize * 4;
+
+ /* Prepare seeds */
+ while(*pbKey != 0) {
+ ch = toupper(*pbKey++);
+ seed1 = mpq_a->buf[0x300 + ch] ^ (seed1 + seed2);
+ seed2 = ch + seed1 + seed2 + (seed2 << 5) + 3;
+ }
+
+ /* Decrypt it */
+ seed2 = 0xEEEEEEEE;
+ while(length-- > 0) {
+ seed2 += mpq_a->buf[0x400 + (seed1 & 0xFF)];
+ ch = *pdwTable ^ (seed1 + seed2);
+ seed1 = ((~seed1 << 0x15) + 0x11111111) | (seed1 >> 0x0B);
+ seed2 = ch + seed2 + (seed2 << 5) + 3;
+ *pdwTable++ = ch;
+ }
+ return LIBMPQ_TOOLS_SUCCESS;
+}
+
+int libmpq_read_listfile(mpq_archive *mpq_a, FILE *fp) {
+ int mpq_size;
+ int mpq_ht_size;
+ int mpq_bt_size;
+ int mpq_blocksize;
+ int mpq_files;
+ int mpq_csize;
+ int mpq_fsize;
+ int entries;
+ char listdb_version[10];
+ char libmpq_version[10];
+ int listdb_temp_version = 0;
+ int libmpq_temp_version = 0;
+
+ /* first check header and version */
+ if (libmpq_conf_get_value(fp, "LIBMPQ_VERSION", mpq_a->mpq_l->mpq_version, LIBMPQ_CONF_TYPE_CHAR, sizeof(mpq_a->mpq_l->mpq_version))) {
+ return LIBMPQ_CONF_EFILE_CORRUPT;
+ } else {
+
+ /* copy to temp buffer for removing . characters */
+ sprintf(listdb_version, (char *)mpq_a->mpq_l->mpq_version);
+
+ /* remove . characters from listfile version */
+ libmpq_conf_delete_char(listdb_version, ".");
+
+ /* get libmpq version */
+ sprintf(libmpq_version, "%i%i%i",LIBMPQ_MAJOR_VERSION, LIBMPQ_MINOR_VERSION, LIBMPQ_PATCH_VERSION);
+
+ /* convert to number */
+ listdb_temp_version = atoi(listdb_version);
+ libmpq_temp_version = atoi(libmpq_version);
+
+ /* check if installed libmpq version is valid for listfile version */
+ if ((libmpq_temp_version < listdb_temp_version) || (libmpq_temp_version == 0) || (listdb_temp_version == 0)) {
+ return LIBMPQ_CONF_EFILE_VERSION;
+ }
+ }
+
+ /* check listfile header, the following entries must be set */
+ if (libmpq_conf_get_value(fp, "MPQ_SIZE", &mpq_size, LIBMPQ_CONF_TYPE_INT, 0)) {
+ return LIBMPQ_CONF_EFILE_CORRUPT;
+ }
+ if (libmpq_conf_get_value(fp, "MPQ_HASHTABLE_SIZE", &mpq_ht_size, LIBMPQ_CONF_TYPE_INT, 0)) {
+ return LIBMPQ_CONF_EFILE_CORRUPT;
+ }
+ if (libmpq_conf_get_value(fp, "MPQ_BLOCKTABLE_SIZE", &mpq_bt_size, LIBMPQ_CONF_TYPE_INT, 0)) {
+ return LIBMPQ_CONF_EFILE_CORRUPT;
+ }
+ if (libmpq_conf_get_value(fp, "MPQ_BLOCKSIZE", &mpq_blocksize, LIBMPQ_CONF_TYPE_INT, 0)) {
+ return LIBMPQ_CONF_EFILE_CORRUPT;
+ }
+ if (libmpq_conf_get_value(fp, "MPQ_FILES", &mpq_files, LIBMPQ_CONF_TYPE_INT, 0)) {
+ return LIBMPQ_CONF_EFILE_CORRUPT;
+ }
+ if (libmpq_conf_get_value(fp, "MPQ_COMPRESSED_SIZE", &mpq_csize, LIBMPQ_CONF_TYPE_INT, 0)) {
+ return LIBMPQ_CONF_EFILE_CORRUPT;
+ }
+ if (libmpq_conf_get_value(fp, "MPQ_UNCOMPRESSED_SIZE", &mpq_fsize, LIBMPQ_CONF_TYPE_INT, 0)) {
+ return LIBMPQ_CONF_EFILE_CORRUPT;
+ }
+ if (libmpq_conf_get_value(fp, "MPQ_NAME", mpq_a->mpq_l->mpq_name, LIBMPQ_CONF_TYPE_CHAR, PATH_MAX)) {
+ return LIBMPQ_CONF_EFILE_CORRUPT;
+ }
+ if (libmpq_conf_get_value(fp, "MPQ_TYPE", mpq_a->mpq_l->mpq_type, LIBMPQ_CONF_TYPE_CHAR, sizeof(mpq_a->mpq_l->mpq_type))) {
+ return LIBMPQ_CONF_EFILE_CORRUPT;
+ }
+
+ /* these are optional parameters, if they are empty we set the struct members empty */
+ libmpq_conf_get_value(fp, "MPQ_GAME", mpq_a->mpq_l->mpq_game, LIBMPQ_CONF_TYPE_CHAR, sizeof(mpq_a->mpq_l->mpq_game));
+ libmpq_conf_get_value(fp, "MPQ_GAME_VERSION", mpq_a->mpq_l->mpq_game_version, LIBMPQ_CONF_TYPE_CHAR, sizeof(mpq_a->mpq_l->mpq_game_version));
+
+ /* check if we found a valid listfile for the given archive */
+ if (mpq_a->header->hashtablesize == mpq_ht_size && mpq_a->header->blocktablesize == mpq_bt_size && mpq_a->blocksize == mpq_blocksize && libmpq_archive_info(mpq_a, LIBMPQ_MPQ_ARCHIVE_SIZE) == mpq_size && libmpq_archive_info(mpq_a, LIBMPQ_MPQ_NUMFILES) == mpq_files && libmpq_archive_info(mpq_a, LIBMPQ_MPQ_COMPRESSED_SIZE) == mpq_csize && libmpq_archive_info(mpq_a, LIBMPQ_MPQ_UNCOMPRESSED_SIZE) == mpq_fsize) {
+
+ /* check if the filelist is correct */
+ if (!libmpq_conf_get_array(fp, "FILE_NAMES", (char ***)&mpq_a->mpq_l->mpq_files, &entries)) {
+
+ /* we have a corrupt filelist, so return */
+ return LIBMPQ_CONF_EFILE_LIST_CORRUPT;
+ } else {
+
+ /* now check if filelist entries matches number of files in the archive. */
+ if (entries != libmpq_archive_info(mpq_a, LIBMPQ_MPQ_NUMFILES)) {
+ libmpq_free_listfile((char **)mpq_a->mpq_l->mpq_files);
+ mpq_a->mpq_l->mpq_files = NULL;
+ return LIBMPQ_CONF_EFILE_LIST_CORRUPT;
+ }
+ }
+ }
+
+ return LIBMPQ_TOOLS_SUCCESS;
+}
+
+/*
+ * This function frees up the space reserved by libmpq_get_listfile()
+ */
+int libmpq_free_listfile(char **filelist) {
+ int i = 0;
+ while (filelist[i]) {
+ free(filelist[i++]);
+ }
+ free(filelist);
+
+ return LIBMPQ_TOOLS_SUCCESS;
+}
+
+/*
+ * This function reads the directory and the subdirectories
+ * of the listfile database and adds a entry to the lisfile
+ * array.
+ */
+/*int libmpq_detect_listfile_rec(char path[PATH_MAX], char ***filelist, int *fl_count, int *fl_size) {
+ char nextpath[PATH_MAX];
+ DIR *dp = opendir(path);
+ FILE *fp;
+ struct dirent *entry;
+ struct stat statbuf;
+ char buf[LIBMPQ_CONF_BUFSIZE];
+
+ if (dp == NULL) {
+ return LIBMPQ_CONF_EOPEN_DIR;
+ } else {
+ while ((entry = readdir(dp)) != NULL) {
+ if (strncmp(entry->d_name, ".", 1) == 0 || strncmp(entry->d_name, "..", 2) == 0) {
+ continue;
+ }
+ if (strnlen(path, PATH_MAX) + strnlen(entry->d_name, PATH_MAX) + 2 > sizeof nextpath) {
+ continue;
+ }
+
+ snprintf(nextpath, PATH_MAX, "%s/%s", path, entry->d_name);
+
+ // check if file extension matches listdb file extension
+ if (strncmp(&entry->d_name[strlen(entry->d_name) - strlen(LIBMPQ_CONF_EXT)], LIBMPQ_CONF_EXT, strlen(LIBMPQ_CONF_EXT)) == 0) {
+
+ // check if it is really a listdb file
+ if ((fp = fopen(nextpath, "r")) != NULL ) {
+ while (fgets(buf, LIBMPQ_CONF_BUFSIZE, fp) != NULL) {
+ char *line;
+
+ buf[strlen(buf) - 1] = '\0';
+
+ // skip whitespace
+ for (line = buf; isspace(*line); line++) {
+ continue;
+ }
+
+ // skip empty line
+ if (line[0] == '\0') {
+ continue;
+ }
+
+ // skip comments
+ if (line[0] == '#') {
+ continue;
+ }
+
+ //search for listdb header; dirty but works :)
+ if (!strncasecmp(line, LIBMPQ_CONF_HEADER, strlen(LIBMPQ_CONF_HEADER))) {
+
+ // set the next filelist entry to a copy of the file path
+ (*filelist)[(*fl_count)++] = strdup(nextpath);
+
+ // increase the array size
+ if ((*fl_count) == (*fl_size)) {
+ (*filelist) = realloc((*filelist), ((*fl_size) + LIBMPQ_CONF_FL_INCREMENT) * sizeof(char *));
+ (*fl_size) += LIBMPQ_CONF_FL_INCREMENT;
+ }
+
+ // header found so we could stop reading the file.
+ break;
+ }
+ }
+ fclose(fp);
+ }
+ }
+
+ if (stat(nextpath, &statbuf) < 0) {
+ continue;
+ }
+
+ // if entry ia a subdirectory, read it
+ if (S_ISDIR(statbuf.st_mode)) {
+ libmpq_detect_listfile_rec(nextpath, filelist, fl_count, fl_size);
+ }
+ }
+ closedir(dp);
+ }
+
+ return LIBMPQ_TOOLS_SUCCESS;
+}
+*/
+
+/*
+ * This functions tries to get file decryption key. The trick comes from block
+ * positions which are stored at the begin of each compressed file. We know the
+ * file size, that means we know number of blocks that means we know the first
+ * int value in block position. And if we know encrypted and decrypted value,
+ * we can find the decryption key.
+ */
+int libmpq_detect_fileseed(mpq_archive *mpq_a, unsigned int *block, unsigned int decrypted) {
+ unsigned int saveseed1;
+ unsigned int temp = *block ^ decrypted; /* temp = seed1 + seed2 */
+ int i = 0;
+ temp -= 0xEEEEEEEE; /* temp = seed1 + mpq_a->buf[0x400 + (seed1 & 0xFF)] */
+
+ for (i = 0; i < 0x100; i++) { /* Try all 255 possibilities */
+ unsigned int seed1;
+ unsigned int seed2 = 0xEEEEEEEE;
+ unsigned int ch;
+
+ /* Try the first unsigned int's (We exactly know the value) */
+ seed1 = temp - mpq_a->buf[0x400 + i];
+ seed2 += mpq_a->buf[0x400 + (seed1 & 0xFF)];
+ ch = block[0] ^ (seed1 + seed2);
+
+ if (ch != decrypted) {
+ continue;
+ }
+
+ /* Add 1 because we are decrypting block positions */
+ saveseed1 = seed1 + 1;
+
+ /*
+ * If OK, continue and test the second value. We don't know exactly the value,
+ * but we know that the second one has lower 16 bits set to zero
+ * (no compressed block is larger than 0xFFFF bytes)
+ */
+ seed1 = ((~seed1 << 0x15) + 0x11111111) | (seed1 >> 0x0B);
+ seed2 = ch + seed2 + (seed2 << 5) + 3;
+ seed2 += mpq_a->buf[0x400 + (seed1 & 0xFF)];
+ ch = block[1] ^ (seed1 + seed2);
+ if ((ch & 0xFFFF0000) == 0) {
+ return saveseed1;
+ }
+ }
+ return LIBMPQ_TOOLS_SUCCESS;
+}
+
+/*
+ * This function initialize the decryption buffer
+ */
+int libmpq_init_buffer(mpq_archive *mpq_a) {
+ unsigned int seed = 0x00100001;
+ unsigned int index1 = 0;
+ unsigned int index2 = 0;
+ int i;
+
+ memset(mpq_a->buf, 0, sizeof(mpq_a->buf));
+
+ /* Initialize the decryption buffer. */
+ for (index1 = 0; index1 < 0x100; index1++) {
+ for(index2 = index1, i = 0; i < 5; i++, index2 += 0x100) {
+ unsigned int temp1, temp2;
+ seed = (seed * 125 + 3) % 0x2AAAAB;
+ temp1 = (seed & 0xFFFF) << 0x10;
+
+ seed = (seed * 125 + 3) % 0x2AAAAB;
+ temp2 = (seed & 0xFFFF);
+
+ mpq_a->buf[index2] = (temp1 | temp2);
+ }
+ }
+ return LIBMPQ_TOOLS_SUCCESS;
+}
+
+/*
+ * This functions fills the mpq_hash structure with the
+ * hashtable found in the MPQ file. The hashtable will
+ * be decrypted for later use.
+ */
+int libmpq_read_hashtable(mpq_archive *mpq_a) {
+ unsigned int bytes = 0;
+ int rb = 0;
+
+ /*
+ * Allocate memory. Note that the block table should be as large as the
+ * hash table. (for later file additions)
+ */
+ mpq_a->hashtable = (mpq_hash *)malloc(sizeof(mpq_hash) * mpq_a->header->hashtablesize);
+
+ if (!mpq_a->hashtable) {
+ return LIBMPQ_EALLOCMEM;
+ }
+
+ /* Read the hash table into the buffer */
+ bytes = mpq_a->header->hashtablesize * sizeof(mpq_hash);
+
+ #ifdef WIN32
+ _lseeki64(mpq_a->fd, mpq_a->header->hashtablepos, SEEK_SET);
+ #else
+ lseek64(mpq_a->fd, mpq_a->header->hashtablepos, SEEK_SET);
+ #endif
+
+ rb = _read(mpq_a->fd, mpq_a->hashtable, bytes);
+ if (rb != bytes) {
+ return LIBMPQ_EFILE_CORRUPT;
+ }
+
+ /* Decrypt hash table and check if it is correctly decrypted */
+ mpq_hash *mpq_h_end = mpq_a->hashtable + mpq_a->header->hashtablesize;
+ mpq_hash *mpq_h = NULL;
+
+ libmpq_decrypt_hashtable(mpq_a, (unsigned char *)"(hash table)");
+
+ /* Check hash table if is correctly decrypted */
+ for (mpq_h = mpq_a->hashtable; mpq_h < mpq_h_end; mpq_h++) {
+ if (mpq_h->locale != 0xFFFFFFFF && (mpq_h->locale & 0xFFFF0000) != 0) {
+ return LIBMPQ_EFILE_FORMAT;
+ }
+
+ /* Remember the highest block table entry */
+ if (mpq_h->blockindex < LIBMPQ_HASH_ENTRY_DELETED && mpq_h->blockindex > 0) {
+ mpq_a->maxblockindex = mpq_h->blockindex;
+ }
+ }
+
+ return LIBMPQ_TOOLS_SUCCESS;
+}
+
+/*
+ * This functions fills the mpq_block structure with the
+ * blocktable found in the MPQ file. The blocktable will
+ * be decrypted for later use.
+ *
+ * NOTICE: Some MPQs have decrypted block table, e.g.
+ * cracked Diablo versions.
+ */
+int libmpq_read_blocktable(mpq_archive *mpq_a) {
+ unsigned int bytes = 0;
+ int rb = 0;
+
+ /*
+ * Allocate memory. Note that the block table should be as large as the
+ * hash table. (for later file additions)
+ */
+ mpq_a->blocktable = (mpq_block *)malloc(sizeof(mpq_block) * mpq_a->header->hashtablesize);
+ mpq_a->blockbuf = (unsigned char *)malloc(mpq_a->blocksize);
+
+ if (!mpq_a->blocktable || !mpq_a->blockbuf) {
+ return LIBMPQ_EALLOCMEM;
+ }
+
+ /* Read the block table into the buffer */
+ bytes = mpq_a->header->blocktablesize * sizeof(mpq_block);
+ memset(mpq_a->blocktable, 0, mpq_a->header->blocktablesize * sizeof(mpq_block));
+
+ #ifdef WIN32
+ _lseeki64(mpq_a->fd, mpq_a->header->blocktablepos, SEEK_SET);
+ #else
+ lseek64(mpq_a->fd, mpq_a->header->blocktablepos, SEEK_SET);
+ #endif
+
+ rb = _read(mpq_a->fd, mpq_a->blocktable, bytes);
+ if (rb != bytes) {
+ return LIBMPQ_EFILE_CORRUPT;
+ }
+
+ /*
+ * Decrypt block table. Some MPQs don't have encrypted block table,
+ * e.g. cracked Diablo version. We have to check if block table is
+ * already decrypted
+ */
+ mpq_block *mpq_b_end = mpq_a->blocktable + mpq_a->maxblockindex + 1;
+ mpq_block *mpq_b = NULL;
+ unsigned int archivesize = mpq_a->header->archivesize + mpq_a->mpqpos;
+
+ if (mpq_a->header->offset != mpq_a->blocktable->filepos) {
+ libmpq_decrypt_blocktable(mpq_a, (unsigned char *)"(block table)");
+ }
+ for (mpq_b = mpq_a->blocktable; mpq_b < mpq_b_end; mpq_b++) {
+ if (mpq_b->filepos > archivesize || mpq_b->csize > archivesize) {
+ if ((mpq_a->flags & LIBMPQ_FLAG_PROTECTED) == 0) {
+ return LIBMPQ_EFILE_FORMAT;
+ }
+ }
+ mpq_b->filepos += mpq_a->mpqpos;
+ }
+
+ return LIBMPQ_TOOLS_SUCCESS;
+}
+
+int libmpq_file_read_block(mpq_archive *mpq_a, mpq_file *mpq_f, unsigned int blockpos, char *buffer, unsigned int blockbytes) {
+ unsigned char *tempbuf = NULL; /* Buffer for reading compressed data from the file */
+ unsigned int readpos; /* Reading position from the file */
+ unsigned int toread = 0; /* Number of bytes to read */
+ unsigned int blocknum; /* Block number (needed for decrypt) */
+ unsigned int bytesread = 0; /* Total number of bytes read */
+ unsigned int nblocks; /* Number of blocks to load */
+ unsigned int i;
+
+ /* Test parameters. Block position and block size must be block-aligned, block size nonzero */
+ if ((blockpos & (mpq_a->blocksize - 1)) || blockbytes == 0) {
+ return 0;
+ }
+
+ /* Check the end of file */
+ if ((blockpos + blockbytes) > mpq_f->mpq_b->fsize) {
+ blockbytes = mpq_f->mpq_b->fsize - blockpos;
+ }
+ blocknum = blockpos / mpq_a->blocksize;
+ nblocks = blockbytes / mpq_a->blocksize;
+ if (blockbytes % mpq_a->blocksize) {
+ nblocks++;
+ }
+
+ /* If file has variable block positions, we have to load them */
+ if ((mpq_f->mpq_b->flags & LIBMPQ_FILE_COMPRESSED) && mpq_f->blockposloaded == FALSE) {
+ unsigned int nread;
+
+ if (mpq_f->mpq_b->filepos != mpq_a->filepos) {
+ #ifdef WIN32
+ _lseeki64(mpq_a->fd, mpq_f->mpq_b->filepos, SEEK_SET);
+ #else
+ lseek64(mpq_a->fd, mpq_f->mpq_b->filepos, SEEK_SET);
+
+ #endif
+ }
+
+ /* Read block positions from begin of file. */
+ nread = (mpq_f->nblocks + 1) * sizeof(int);
+ nread = _read(mpq_a->fd, mpq_f->blockpos, nread);
+
+ /*
+ * If the archive is protected some way, perform additional check
+ * Sometimes, the file appears not to be encrypted, but it is.
+ */
+ /*if (mpq_f->blockpos[0] != nread) {
+ mpq_f->mpq_b->flags |= LIBMPQ_FILE_ENCRYPTED;
+ }*/
+
+ if ((mpq_f->mpq_b->flags & LIBMPQ_FILE_HAS_METADATA) == 0) {
+ if (mpq_f->blockpos[0] != nread) {
+ mpq_f->mpq_b->flags |= LIBMPQ_FILE_ENCRYPTED;
+ }
+ }
+
+ /* Decrypt loaded block positions if necessary */
+ if (mpq_f->mpq_b->flags & LIBMPQ_FILE_ENCRYPTED) {
+
+ /* If we don't know the file seed, try to find it. */
+ if (mpq_f->seed == 0) {
+ mpq_f->seed = libmpq_detect_fileseed(mpq_a, mpq_f->blockpos, nread);
+ }
+
+ /* If we don't know the file seed, sorry but we cannot extract the file. */
+ if (mpq_f->seed == 0) {
+ return 0;
+ }
+
+ /* Decrypt block positions */
+ libmpq_decrypt_block(mpq_a, mpq_f->blockpos, nread, mpq_f->seed - 1);
+
+ /*
+ * Check if the block positions are correctly decrypted
+ * I don't know why, but sometimes it will result invalid
+ * block positions on some files.
+ */
+ if (mpq_f->blockpos[0] != nread) {
+
+ /* Try once again to detect file seed and decrypt the blocks */
+
+ #ifdef WIN32
+ _lseeki64(mpq_a->fd, mpq_f->mpq_b->filepos, SEEK_SET);
+ #else
+ lseek64(mpq_a->fd, mpq_f->mpq_b->filepos, SEEK_SET);
+ #endif
+
+ nread = _read(mpq_a->fd, mpq_f->blockpos, (mpq_f->nblocks + 1) * sizeof(int));
+ mpq_f->seed = libmpq_detect_fileseed(mpq_a, mpq_f->blockpos, nread);
+ libmpq_decrypt_block(mpq_a, mpq_f->blockpos, nread, mpq_f->seed - 1);
+
+ /* Check if the block positions are correctly decrypted. */
+ if (mpq_f->blockpos[0] != nread) {
+ return 0;
+ }
+ }
+ }
+
+ /* Update mpq_f's variables */
+ mpq_f->blockposloaded = TRUE;
+ mpq_a->filepos = mpq_f->mpq_b->filepos + nread;
+ }
+
+ /* Get file position and number of bytes to read */
+ readpos = blockpos;
+ toread = blockbytes;
+
+ if (mpq_f->mpq_b->flags & LIBMPQ_FILE_COMPRESSED) {
+ readpos = mpq_f->blockpos[blocknum];
+ toread = mpq_f->blockpos[blocknum + nblocks] - readpos;
+ }
+
+ readpos += mpq_f->mpq_b->filepos;
+
+ /* Get work buffer for store read data */
+ if ((tempbuf = (unsigned char *)malloc(toread)) == NULL) {
+ /* Hmmm... We should add a better error handling here :) */
+ return 0;
+ }
+
+ /* Set file pointer, if necessary. */
+ if (mpq_a->filepos != readpos) {
+
+ #ifdef WIN32
+ mpq_a->filepos = _lseeki64(mpq_a->fd, readpos, SEEK_SET);
+ #else
+ mpq_a->filepos = lseek64(mpq_a->fd, readpos, SEEK_SET);
+ #endif
+
+ }
+
+ /* 15018F87 - Read all requested blocks. */
+ bytesread = _read(mpq_a->fd, tempbuf, toread);
+ mpq_a->filepos = readpos + bytesread;
+
+ /* Block processing part. */
+ unsigned int blockstart = 0; /* Index of block start in work buffer. */
+ unsigned int blocksize = min(blockbytes, mpq_a->blocksize);
+ unsigned int index = blocknum; /* Current block index. */
+ bytesread = 0; /* Clear read byte counter */
+
+ /* Walk through all blocks. */
+ for (i = 0; i < nblocks; i++, index++) {
+ int outlength = mpq_a->blocksize;
+
+ /* Get current block length */
+ if (mpq_f->mpq_b->flags & LIBMPQ_FILE_COMPRESSED) {
+ blocksize = mpq_f->blockpos[index + 1] - mpq_f->blockpos[index];
+ }
+
+ /* If block is encrypted, we have to decrypt it. */
+ if (mpq_f->mpq_b->flags & LIBMPQ_FILE_ENCRYPTED) {
+ if (mpq_f->seed == 0) {
+ return 0;
+ }
+ libmpq_decrypt_block(mpq_a, (unsigned int *)&tempbuf[blockstart], blocksize, mpq_f->seed + index);
+ }
+
+ /*
+ * If the block is really compressed, recompress it.
+ * WARNING: Some block may not be compressed, it can
+ * only be determined by comparing uncompressed and
+ * compressed size!
+ */
+ if (blocksize < blockbytes) {
+
+ /* Is the file compressed with PKWARE Data Compression Library? */
+ if (mpq_f->mpq_b->flags & LIBMPQ_FILE_COMPRESS_PKWARE) {
+ libmpq_pkzip_decompress(buffer, &outlength, (char *)&tempbuf[blockstart], blocksize);
+ }
+
+ /*
+ * Is it a file compressed by Blizzard's multiple compression ?
+ * Note that Storm.dll v 1.0.9 distributed with Warcraft III
+ * passes the full path name of the opened archive as the new
+ * last parameter.
+ */
+ if (mpq_f->mpq_b->flags & LIBMPQ_FILE_COMPRESS_MULTI) {
+ libmpq_multi_decompress(buffer, &outlength, (char *)&tempbuf[blockstart], blocksize);
+ }
+ bytesread += outlength;
+ buffer += outlength;
+ } else {
+ memcpy(buffer, tempbuf, blocksize);
+ bytesread += blocksize;
+ buffer += blocksize;
+ }
+ blockstart += blocksize;
+ }
+
+ /* Delete input buffer, if necessary. */
+ free(tempbuf);
+
+ return bytesread;
+}
+
+int libmpq_file_read_file(mpq_archive *mpq_a, mpq_file *mpq_f, unsigned int filepos, char *buffer, unsigned int toread) {
+ unsigned int bytesread = 0; /* Number of bytes read from the file */
+ unsigned int blockpos; /* Position in the file aligned to the whole blocks */
+ unsigned int loaded = 0;
+
+ /* File position is greater or equal to file size? */
+ if (filepos >= mpq_f->mpq_b->fsize) {
+ return 0;
+ }
+
+ /* If to few bytes in the file remaining, cut them */
+ if ((mpq_f->mpq_b->fsize - filepos) < toread) {
+ toread = (mpq_f->mpq_b->fsize - filepos);
+ }
+
+ /* Block position in the file */
+ blockpos = filepos & ~(mpq_a->blocksize - 1);
+
+ /*
+ * Load the first block, if noncomplete. It may be loaded in the cache buffer.
+ * We have to check if this block is loaded. If not, load it.
+ */
+ if ((filepos % mpq_a->blocksize) != 0) {
+ /* Number of bytes remaining in the buffer */
+ unsigned int tocopy;
+ unsigned int loaded = mpq_a->blocksize;
+
+ /* Check if data are loaded in the cache */
+ if (mpq_f->accessed == FALSE || blockpos != mpq_a->blockpos) {
+
+ /* Load one MPQ block into archive buffer */
+ loaded = libmpq_file_read_block(mpq_a, mpq_f, blockpos, (char *)mpq_a->blockbuf, mpq_a->blocksize);
+ if (loaded == 0) {
+ return 0;
+ }
+
+ /* Save lastly accessed file and block position for later use */
+ mpq_f->accessed = TRUE;
+ mpq_a->blockpos = blockpos;
+ mpq_a->bufpos = filepos % mpq_a->blocksize;
+ }
+ tocopy = loaded - mpq_a->bufpos;
+ if (tocopy > toread) {
+ tocopy = toread;
+ }
+
+ /* Copy data from block buffer into target buffer */
+ memcpy(buffer, mpq_a->blockbuf + mpq_a->bufpos, tocopy);
+
+ /* Update pointers */
+ toread -= tocopy;
+ bytesread += tocopy;
+ buffer += tocopy;
+ blockpos += mpq_a->blocksize;
+ mpq_a->bufpos += tocopy;
+
+ /* If all, return. */
+ if (toread == 0) {
+ return bytesread;
+ }
+ }
+
+ /* Load the whole ("middle") blocks only if there are more or equal one block */
+ if (toread > mpq_a->blocksize) {
+ unsigned int blockbytes = toread & ~(mpq_a->blocksize - 1);
+ loaded = libmpq_file_read_block(mpq_a, mpq_f, blockpos, buffer, blockbytes);
+ if (loaded == 0) {
+ return 0;
+ }
+
+ /* Update pointers */
+ toread -= loaded;
+ bytesread += loaded;
+ buffer += loaded;
+ blockpos += loaded;
+
+ /* If all, return. */
+ if (toread == 0) {
+ return bytesread;
+ }
+ }
+
+ /* Load the terminating block */
+ if (toread > 0) {
+ unsigned int tocopy = mpq_a->blocksize;
+
+ /* Check if data are loaded in the cache */
+ if (mpq_f->accessed == FALSE || blockpos != mpq_a->blockpos) {
+
+ /* Load one MPQ block into archive buffer */
+ tocopy = libmpq_file_read_block(mpq_a, mpq_f, blockpos, (char *)mpq_a->blockbuf, mpq_a->blocksize);
+ if (tocopy == 0) {
+ return 0;
+ }
+
+ /* Save lastly accessed file and block position for later use */
+ mpq_f->accessed = TRUE;
+ mpq_a->blockpos = blockpos;
+ }
+ mpq_a->bufpos = 0;
+
+ /* Check number of bytes read */
+ if (tocopy > toread) {
+ tocopy = toread;
+ }
+
+ memcpy(buffer, mpq_a->blockbuf, tocopy);
+ bytesread += tocopy;
+ mpq_a->bufpos = tocopy;
+ }
+
+ /* Return what we've read */
+ return bytesread;
+}
diff --git a/contrib/extractor/libmpq/common.h b/contrib/extractor/libmpq/common.h
new file mode 100644
index 00000000000..ad2c0f101fa
--- /dev/null
+++ b/contrib/extractor/libmpq/common.h
@@ -0,0 +1,66 @@
+/*
+ * common.h -- defines and structs used by the config files.
+ *
+ * Copyright (C) 2003 Maik Broemme <mbroemme@plusserver.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Id: common.h,v 1.4 2004/02/12 00:41:55 mbroemme Exp $
+ */
+
+#define LIBMPQ_CONF_FL_INCREMENT 512 /* i hope we did not need more :) */
+#define LIBMPQ_CONF_EXT ".conf" /* listdb file seems to be valid with this extension */
+#define LIBMPQ_CONF_HEADER "LIBMPQ_VERSION" /* listdb file must include this entry to be valid */
+#define LIBMPQ_CONF_BUFSIZE 4096 /* maximum number of bytes a line in the file could contain */
+
+#define LIBMPQ_CONF_TYPE_CHAR 1 /* value in config file is from type char */
+#define LIBMPQ_CONF_TYPE_INT 2 /* value in config file is from type int */
+
+#define LIBMPQ_CONF_EOPEN_DIR -1 /* error on open directory */
+#define LIBMPQ_CONF_EVALUE_NOT_FOUND -2 /* value for the option was not found */
+
+#if defined( __GNUC__ )
+ #include <sys/types.h>
+ #include <unistd.h>
+
+ #define _lseek lseek
+ #define _read read
+ #define _open open
+ #define _write write
+ #define _close close
+ #define _strdup strdup
+
+ #ifndef O_BINARY
+ #define O_BINARY 0
+ #endif
+#else
+ #include <io.h>
+#endif
+
+#ifndef min
+ #define min(a, b) ((a < b) ? a : b)
+#endif
+
+int libmpq_init_buffer(mpq_archive *mpq_a);
+int libmpq_read_hashtable(mpq_archive *mpq_a);
+int libmpq_read_blocktable(mpq_archive *mpq_a);
+int libmpq_file_read_file(mpq_archive *mpq_a, mpq_file *mpq_f, unsigned int filepos, char *buffer, unsigned int toread);
+int libmpq_read_listfile(mpq_archive *mpq_a, FILE *fp);
+
+int libmpq_conf_get_value(FILE *fp, char *search_value, void *return_value, int type, int size);
+char *libmpq_conf_delete_char(char *buf, char *chars);
+int libmpq_conf_get_array(FILE *fp, char *search_value, char ***filelist, int *entries);
+int libmpq_free_listfile(char **filelist);
+int libmpq_read_listfile(mpq_archive *mpq_a, FILE *fp);
diff --git a/contrib/extractor/libmpq/explode.cpp b/contrib/extractor/libmpq/explode.cpp
new file mode 100644
index 00000000000..bcf9e7857a2
--- /dev/null
+++ b/contrib/extractor/libmpq/explode.cpp
@@ -0,0 +1,428 @@
+/*
+ * explode.c -- explode function of PKWARE data compression library.
+ *
+ * Copyright (C) 2003 Maik Broemme <mbroemme@plusserver.de>
+ *
+ * This source was adepted from the C++ version of pkware.cpp included
+ * in stormlib. The C++ version belongs to the following authors,
+ *
+ * Ladislav Zezula <ladik.zezula.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include "mpq.h"
+#include "explode.h"
+
+/* Tables */
+static unsigned char pkzip_dist_bits[] = {
+ 0x02, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
+};
+
+static unsigned char pkzip_dist_code[] = {
+ 0x03, 0x0D, 0x05, 0x19, 0x09, 0x11, 0x01, 0x3E, 0x1E, 0x2E, 0x0E, 0x36, 0x16, 0x26, 0x06, 0x3A,
+ 0x1A, 0x2A, 0x0A, 0x32, 0x12, 0x22, 0x42, 0x02, 0x7C, 0x3C, 0x5C, 0x1C, 0x6C, 0x2C, 0x4C, 0x0C,
+ 0x74, 0x34, 0x54, 0x14, 0x64, 0x24, 0x44, 0x04, 0x78, 0x38, 0x58, 0x18, 0x68, 0x28, 0x48, 0x08,
+ 0xF0, 0x70, 0xB0, 0x30, 0xD0, 0x50, 0x90, 0x10, 0xE0, 0x60, 0xA0, 0x20, 0xC0, 0x40, 0x80, 0x00
+};
+
+static unsigned char pkzip_clen_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08
+};
+
+static unsigned short pkzip_len_base[] = {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x000A, 0x000E, 0x0016, 0x0026, 0x0046, 0x0086, 0x0106
+};
+
+static unsigned char pkzip_slen_bits[] = {
+ 0x03, 0x02, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x07, 0x07
+};
+
+static unsigned char pkzip_len_code[] = {
+ 0x05, 0x03, 0x01, 0x06, 0x0A, 0x02, 0x0C, 0x14, 0x04, 0x18, 0x08, 0x30, 0x10, 0x20, 0x40, 0x00
+};
+
+static unsigned char pkzip_bits_asc[] = {
+ 0x0B, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x08, 0x07, 0x0C, 0x0C, 0x07, 0x0C, 0x0C,
+ 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
+ 0x04, 0x0A, 0x08, 0x0C, 0x0A, 0x0C, 0x0A, 0x08, 0x07, 0x07, 0x08, 0x09, 0x07, 0x06, 0x07, 0x08,
+ 0x07, 0x06, 0x07, 0x07, 0x07, 0x07, 0x08, 0x07, 0x07, 0x08, 0x08, 0x0C, 0x0B, 0x07, 0x09, 0x0B,
+ 0x0C, 0x06, 0x07, 0x06, 0x06, 0x05, 0x07, 0x08, 0x08, 0x06, 0x0B, 0x09, 0x06, 0x07, 0x06, 0x06,
+ 0x07, 0x0B, 0x06, 0x06, 0x06, 0x07, 0x09, 0x08, 0x09, 0x09, 0x0B, 0x08, 0x0B, 0x09, 0x0C, 0x08,
+ 0x0C, 0x05, 0x06, 0x06, 0x06, 0x05, 0x06, 0x06, 0x06, 0x05, 0x0B, 0x07, 0x05, 0x06, 0x05, 0x05,
+ 0x06, 0x0A, 0x05, 0x05, 0x05, 0x05, 0x08, 0x07, 0x08, 0x08, 0x0A, 0x0B, 0x0B, 0x0C, 0x0C, 0x0C,
+ 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
+ 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
+ 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
+ 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
+ 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
+ 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
+ 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D,
+ 0x0D, 0x0D, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D
+};
+
+static unsigned short pkzip_code_asc[] = {
+ 0x0490, 0x0FE0, 0x07E0, 0x0BE0, 0x03E0, 0x0DE0, 0x05E0, 0x09E0,
+ 0x01E0, 0x00B8, 0x0062, 0x0EE0, 0x06E0, 0x0022, 0x0AE0, 0x02E0,
+ 0x0CE0, 0x04E0, 0x08E0, 0x00E0, 0x0F60, 0x0760, 0x0B60, 0x0360,
+ 0x0D60, 0x0560, 0x1240, 0x0960, 0x0160, 0x0E60, 0x0660, 0x0A60,
+ 0x000F, 0x0250, 0x0038, 0x0260, 0x0050, 0x0C60, 0x0390, 0x00D8,
+ 0x0042, 0x0002, 0x0058, 0x01B0, 0x007C, 0x0029, 0x003C, 0x0098,
+ 0x005C, 0x0009, 0x001C, 0x006C, 0x002C, 0x004C, 0x0018, 0x000C,
+ 0x0074, 0x00E8, 0x0068, 0x0460, 0x0090, 0x0034, 0x00B0, 0x0710,
+ 0x0860, 0x0031, 0x0054, 0x0011, 0x0021, 0x0017, 0x0014, 0x00A8,
+ 0x0028, 0x0001, 0x0310, 0x0130, 0x003E, 0x0064, 0x001E, 0x002E,
+ 0x0024, 0x0510, 0x000E, 0x0036, 0x0016, 0x0044, 0x0030, 0x00C8,
+ 0x01D0, 0x00D0, 0x0110, 0x0048, 0x0610, 0x0150, 0x0060, 0x0088,
+ 0x0FA0, 0x0007, 0x0026, 0x0006, 0x003A, 0x001B, 0x001A, 0x002A,
+ 0x000A, 0x000B, 0x0210, 0x0004, 0x0013, 0x0032, 0x0003, 0x001D,
+ 0x0012, 0x0190, 0x000D, 0x0015, 0x0005, 0x0019, 0x0008, 0x0078,
+ 0x00F0, 0x0070, 0x0290, 0x0410, 0x0010, 0x07A0, 0x0BA0, 0x03A0,
+ 0x0240, 0x1C40, 0x0C40, 0x1440, 0x0440, 0x1840, 0x0840, 0x1040,
+ 0x0040, 0x1F80, 0x0F80, 0x1780, 0x0780, 0x1B80, 0x0B80, 0x1380,
+ 0x0380, 0x1D80, 0x0D80, 0x1580, 0x0580, 0x1980, 0x0980, 0x1180,
+ 0x0180, 0x1E80, 0x0E80, 0x1680, 0x0680, 0x1A80, 0x0A80, 0x1280,
+ 0x0280, 0x1C80, 0x0C80, 0x1480, 0x0480, 0x1880, 0x0880, 0x1080,
+ 0x0080, 0x1F00, 0x0F00, 0x1700, 0x0700, 0x1B00, 0x0B00, 0x1300,
+ 0x0DA0, 0x05A0, 0x09A0, 0x01A0, 0x0EA0, 0x06A0, 0x0AA0, 0x02A0,
+ 0x0CA0, 0x04A0, 0x08A0, 0x00A0, 0x0F20, 0x0720, 0x0B20, 0x0320,
+ 0x0D20, 0x0520, 0x0920, 0x0120, 0x0E20, 0x0620, 0x0A20, 0x0220,
+ 0x0C20, 0x0420, 0x0820, 0x0020, 0x0FC0, 0x07C0, 0x0BC0, 0x03C0,
+ 0x0DC0, 0x05C0, 0x09C0, 0x01C0, 0x0EC0, 0x06C0, 0x0AC0, 0x02C0,
+ 0x0CC0, 0x04C0, 0x08C0, 0x00C0, 0x0F40, 0x0740, 0x0B40, 0x0340,
+ 0x0300, 0x0D40, 0x1D00, 0x0D00, 0x1500, 0x0540, 0x0500, 0x1900,
+ 0x0900, 0x0940, 0x1100, 0x0100, 0x1E00, 0x0E00, 0x0140, 0x1600,
+ 0x0600, 0x1A00, 0x0E40, 0x0640, 0x0A40, 0x0A00, 0x1200, 0x0200,
+ 0x1C00, 0x0C00, 0x1400, 0x0400, 0x1800, 0x0800, 0x1000, 0x0000
+};
+
+/* Local variables */
+static char copyright[] = "PKWARE Data Compression Library for Win32\r\n"
+ "Copyright 1989-1995 PKWARE Inc. All Rights Reserved\r\n"
+ "Patent No. 5,051,745\r\n"
+ "PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off.\r\n"
+ "Version 1.11\r\n";
+
+/* Local functions */
+static void libmpq_pkzip_gen_decode_tabs(long count, unsigned char *bits, unsigned char *code, unsigned char *buf2) {
+ long i;
+
+ for (i = count-1; i >= 0; i--) { /* EBX - count */
+ unsigned long idx1 = code[i];
+ unsigned long idx2 = 1 << bits[i];
+ do {
+ buf2[idx1] = (unsigned char)i;
+ idx1 += idx2;
+ } while (idx1 < 0x100);
+ }
+}
+
+static void libmpq_pkzip_gen_asc_tabs(pkzip_data_cmp *mpq_pkzip) {
+ unsigned short *code_asc = &pkzip_code_asc[0xFF];
+ unsigned long acc, add;
+ unsigned short count;
+
+ for (count = 0x00FF; code_asc >= pkzip_code_asc; code_asc--, count--) {
+ unsigned char *bits_asc = mpq_pkzip->bits_asc + count;
+ unsigned char bits_tmp = *bits_asc;
+
+ if (bits_tmp <= 8) {
+ add = (1 << bits_tmp);
+ acc = *code_asc;
+ do {
+ mpq_pkzip->offs_2c34[acc] = (unsigned char)count;
+ acc += add;
+ } while (acc < 0x100);
+ } else {
+ if ((acc = (*code_asc & 0xFF)) != 0) {
+ mpq_pkzip->offs_2c34[acc] = 0xFF;
+ if (*code_asc & 0x3F) {
+ bits_tmp -= 4;
+ *bits_asc = bits_tmp;
+ add = (1 << bits_tmp);
+ acc = *code_asc >> 4;
+ do {
+ mpq_pkzip->offs_2d34[acc] = (unsigned char)count;
+ acc += add;
+ } while (acc < 0x100);
+ } else {
+ bits_tmp -= 6;
+ *bits_asc = bits_tmp;
+ add = (1 << bits_tmp);
+ acc = *code_asc >> 6;
+ do {
+ mpq_pkzip->offs_2e34[acc] = (unsigned char)count;
+ acc += add;
+ } while (acc < 0x80);
+ }
+ } else {
+ bits_tmp -= 8;
+ *bits_asc = bits_tmp;
+ add = (1 << bits_tmp);
+ acc = *code_asc >> 8;
+ do {
+ mpq_pkzip->offs_2eb4[acc] = (unsigned char)count;
+ acc += add;
+ } while (acc < 0x100);
+ }
+ }
+ }
+}
+
+/*
+ * Skips given number of bits in bit buffer. Result is stored in mpq_pkzip->bit_buf
+ * If no data in input buffer, returns true
+ */
+static int libmpq_pkzip_skip_bits(pkzip_data_cmp *mpq_pkzip, unsigned long bits) {
+ /* If number of bits required is less than number of (bits in the buffer) ? */
+ if (bits <= mpq_pkzip->extra_bits) {
+ mpq_pkzip->extra_bits -= bits;
+ mpq_pkzip->bit_buf >>= bits;
+ return 0;
+ }
+
+ /* Load input buffer if necessary */
+ mpq_pkzip->bit_buf >>= mpq_pkzip->extra_bits;
+ if (mpq_pkzip->in_pos == mpq_pkzip->in_bytes) {
+ mpq_pkzip->in_pos = sizeof(mpq_pkzip->in_buf);
+ if ((mpq_pkzip->in_bytes = mpq_pkzip->read_buf((char *)mpq_pkzip->in_buf, &mpq_pkzip->in_pos, mpq_pkzip->param)) == 0) {
+ return 1;
+ }
+ mpq_pkzip->in_pos = 0;
+ }
+
+ /* Update bit buffer */
+ mpq_pkzip->bit_buf |= (mpq_pkzip->in_buf[mpq_pkzip->in_pos++] << 8);
+ mpq_pkzip->bit_buf >>= (bits - mpq_pkzip->extra_bits);
+ mpq_pkzip->extra_bits = (mpq_pkzip->extra_bits - bits) + 8;
+ return 0;
+}
+
+/*
+ * Decompress the imploded data using coded literals.
+ * Returns: 0x000 - 0x0FF : One byte from compressed file.
+ * 0x100 - 0x305 : Copy previous block (0x100 = 1 byte)
+ * 0x306 : Out of buffer (?)
+ */
+static unsigned long libmpq_pkzip_explode_lit(pkzip_data_cmp *mpq_pkzip) {
+ unsigned long bits; /* Number of bits to skip */
+ unsigned long value; /* Position in buffers */
+
+ /* Test the current bit in byte buffer. If is not set, simply return the next byte. */
+ if (mpq_pkzip->bit_buf & 1) {
+
+ /* Skip current bit in the buffer. */
+ if (libmpq_pkzip_skip_bits(mpq_pkzip, 1)) {
+ return 0x306;
+ }
+
+ /* The next bits are position in buffers. */
+ value = mpq_pkzip->pos2[(mpq_pkzip->bit_buf & 0xFF)];
+
+ /* Get number of bits to skip */
+ if (libmpq_pkzip_skip_bits(mpq_pkzip, mpq_pkzip->slen_bits[value])) {
+ return 0x306;
+ }
+ if ((bits = mpq_pkzip->clen_bits[value]) != 0) {
+ unsigned long val2 = mpq_pkzip->bit_buf & ((1 << bits) - 1);
+ if (libmpq_pkzip_skip_bits(mpq_pkzip, bits)) {
+ if ((value + val2) != 0x10E) {
+ return 0x306;
+ }
+ }
+ value = mpq_pkzip->len_base[value] + val2;
+ }
+ return value + 0x100; /* Return number of bytes to repeat */
+ }
+
+ /* Skip one bit */
+ if (libmpq_pkzip_skip_bits(mpq_pkzip, 1)) {
+ return 0x306;
+ }
+
+ /* If the binary compression type, read 8 bits and return them as one byte. */
+ if (mpq_pkzip->cmp_type == LIBMPQ_PKZIP_CMP_BINARY) {
+ value = mpq_pkzip->bit_buf & 0xFF;
+ if (libmpq_pkzip_skip_bits(mpq_pkzip, 8)) {
+ return 0x306;
+ }
+ return value;
+ }
+
+ /* When ASCII compression ... */
+ if (mpq_pkzip->bit_buf & 0xFF) {
+ value = mpq_pkzip->offs_2c34[mpq_pkzip->bit_buf & 0xFF];
+ if (value == 0xFF) {
+ if (mpq_pkzip->bit_buf & 0x3F) {
+ if (libmpq_pkzip_skip_bits(mpq_pkzip, 4)) {
+ return 0x306;
+ }
+ value = mpq_pkzip->offs_2d34[mpq_pkzip->bit_buf & 0xFF];
+ } else {
+ if (libmpq_pkzip_skip_bits(mpq_pkzip, 6)) {
+ return 0x306;
+ }
+ value = mpq_pkzip->offs_2e34[mpq_pkzip->bit_buf & 0x7F];
+ }
+ }
+ } else {
+ if (libmpq_pkzip_skip_bits(mpq_pkzip, 8)) {
+ return 0x306;
+ }
+ value = mpq_pkzip->offs_2eb4[mpq_pkzip->bit_buf & 0xFF];
+ }
+ return libmpq_pkzip_skip_bits(mpq_pkzip, mpq_pkzip->bits_asc[value]) ? 0x306 : value;
+}
+
+/*
+ * Retrieves the number of bytes to move back.
+ */
+static unsigned long libmpq_pkzip_explode_dist(pkzip_data_cmp *mpq_pkzip, unsigned long length) {
+ unsigned long pos = mpq_pkzip->pos1[(mpq_pkzip->bit_buf & 0xFF)];
+ unsigned long skip = mpq_pkzip->dist_bits[pos]; /* Number of bits to skip */
+
+ /* Skip the appropriate number of bits */
+ if (libmpq_pkzip_skip_bits(mpq_pkzip, skip) == 1) {
+ return 0;
+ }
+ if (length == 2) {
+ pos = (pos << 2) | (mpq_pkzip->bit_buf & 0x03);
+ if (libmpq_pkzip_skip_bits(mpq_pkzip, 2) == 1) {
+ return 0;
+ }
+ } else {
+ pos = (pos << mpq_pkzip->dsize_bits) | (mpq_pkzip->bit_buf & mpq_pkzip->dsize_mask);
+
+ /* Skip the bits */
+ if (libmpq_pkzip_skip_bits(mpq_pkzip, mpq_pkzip->dsize_bits) == 1) {
+ return 0;
+ }
+ }
+ return pos + 1;
+}
+
+static unsigned long libmpq_pkzip_expand(pkzip_data_cmp *mpq_pkzip) {
+ unsigned int copy_bytes; /* Number of bytes to copy */
+ unsigned long one_byte; /* One byte from compressed file */
+ unsigned long result;
+
+ mpq_pkzip->out_pos = 0x1000; /* Initialize output buffer position */
+
+ /* If end of data or error, terminate decompress */
+ while ((result = one_byte = libmpq_pkzip_explode_lit(mpq_pkzip)) < 0x305) {
+
+ /* If one byte is greater than 0x100, means "Repeat n - 0xFE bytes" */
+ if (one_byte >= 0x100) {
+ unsigned char *source; /* ECX */
+ unsigned char *target; /* EDX */
+ unsigned long copy_length = one_byte - 0xFE;
+ unsigned long move_back;
+
+ /* Get length of data to copy */
+ if ((move_back = libmpq_pkzip_explode_dist(mpq_pkzip, copy_length)) == 0) {
+ result = 0x306;
+ break;
+ }
+
+ /* Target and source pointer */
+ target = &mpq_pkzip->out_buf[mpq_pkzip->out_pos];
+ source = target - move_back;
+ mpq_pkzip->out_pos += copy_length;
+ while (copy_length-- > 0) {
+ *target++ = *source++;
+ }
+ } else {
+ mpq_pkzip->out_buf[mpq_pkzip->out_pos++] = (unsigned char)one_byte;
+ }
+
+ /*
+ * If number of extracted bytes has reached 1/2 of output buffer,
+ * flush output buffer.
+ */
+ if (mpq_pkzip->out_pos >= 0x2000) {
+
+ /* Copy decompressed data into user buffer. */
+ copy_bytes = 0x1000;
+ mpq_pkzip->write_buf((char *)&mpq_pkzip->out_buf[0x1000], &copy_bytes, mpq_pkzip->param);
+
+ /* If there are some data left, keep them alive */
+ memcpy(mpq_pkzip->out_buf, &mpq_pkzip->out_buf[0x1000], mpq_pkzip->out_pos - 0x1000);
+ mpq_pkzip->out_pos -= 0x1000;
+ }
+ }
+ copy_bytes = mpq_pkzip->out_pos - 0x1000;
+ mpq_pkzip->write_buf((char *)&mpq_pkzip->out_buf[0x1000], &copy_bytes, mpq_pkzip->param);
+ return result;
+}
+
+/*
+ * Main exploding function.
+ */
+unsigned int libmpq_pkzip_explode(
+ unsigned int (*read_buf)(char *buf, unsigned int *size, void *param),
+ void (*write_buf)(char *buf, unsigned int *size, void *param),
+ char *work_buf,
+ void *param) {
+
+ pkzip_data_cmp *mpq_pkzip = (pkzip_data_cmp *)work_buf;
+
+ /* Set the whole work buffer to zeros */
+ memset(mpq_pkzip, 0, sizeof(pkzip_data_cmp));
+
+ /* Initialize work struct and load compressed data */
+ mpq_pkzip->read_buf = read_buf;
+ mpq_pkzip->write_buf = write_buf;
+ mpq_pkzip->param = param;
+ mpq_pkzip->in_pos = sizeof(mpq_pkzip->in_buf);
+ mpq_pkzip->in_bytes = mpq_pkzip->read_buf((char *)mpq_pkzip->in_buf, &mpq_pkzip->in_pos, mpq_pkzip->param);
+ if (mpq_pkzip->in_bytes <= 4) {
+ return LIBMPQ_PKZIP_CMP_BAD_DATA;
+ }
+ mpq_pkzip->cmp_type = mpq_pkzip->in_buf[0]; /* Get the compression type */
+ mpq_pkzip->dsize_bits = mpq_pkzip->in_buf[1]; /* Get the dictionary size */
+ mpq_pkzip->bit_buf = mpq_pkzip->in_buf[2]; /* Initialize 16-bit bit buffer */
+ mpq_pkzip->extra_bits = 0; /* Extra (over 8) bits */
+ mpq_pkzip->in_pos = 3; /* Position in input buffer */
+
+ /* Test for the valid dictionary size */
+ if (4 > mpq_pkzip->dsize_bits || mpq_pkzip->dsize_bits > 6) {
+ return LIBMPQ_PKZIP_CMP_INV_DICTSIZE;
+ }
+ mpq_pkzip->dsize_mask = 0xFFFF >> (0x10 - mpq_pkzip->dsize_bits); /* Shifted by 'sar' instruction */
+ if (mpq_pkzip->cmp_type != LIBMPQ_PKZIP_CMP_BINARY) {
+ if (mpq_pkzip->cmp_type != LIBMPQ_PKZIP_CMP_ASCII) {
+ return LIBMPQ_PKZIP_CMP_INV_MODE;
+ }
+ memcpy(mpq_pkzip->bits_asc, pkzip_bits_asc, sizeof(mpq_pkzip->bits_asc));
+ libmpq_pkzip_gen_asc_tabs(mpq_pkzip);
+ }
+ memcpy(mpq_pkzip->slen_bits, pkzip_slen_bits, sizeof(mpq_pkzip->slen_bits));
+ libmpq_pkzip_gen_decode_tabs(0x10, mpq_pkzip->slen_bits, pkzip_len_code, mpq_pkzip->pos2);
+ memcpy(mpq_pkzip->clen_bits, pkzip_clen_bits, sizeof(mpq_pkzip->clen_bits));
+ memcpy(mpq_pkzip->len_base, pkzip_len_base, sizeof(mpq_pkzip->len_base));
+ memcpy(mpq_pkzip->dist_bits, pkzip_dist_bits, sizeof(mpq_pkzip->dist_bits));
+ libmpq_pkzip_gen_decode_tabs(0x40, mpq_pkzip->dist_bits, pkzip_dist_code, mpq_pkzip->pos1);
+ if (libmpq_pkzip_expand(mpq_pkzip) != 0x306) {
+ return LIBMPQ_PKZIP_CMP_NO_ERROR;
+ }
+ return LIBMPQ_PKZIP_CMP_ABORT;
+}
diff --git a/contrib/extractor/libmpq/explode.h b/contrib/extractor/libmpq/explode.h
new file mode 100644
index 00000000000..1f916f778ae
--- /dev/null
+++ b/contrib/extractor/libmpq/explode.h
@@ -0,0 +1,86 @@
+/*
+ * explode.h -- header file for PKWARE data decompression library
+ * used by mpq-tools.
+ *
+ * Copyright (C) 2003 Maik Broemme <mbroemme@plusserver.de>
+ *
+ * This source was adepted from the C++ version of pklib.h included
+ * in stormlib. The C++ version belongs to the following authors,
+ *
+ * Ladislav Zezula <ladik.zezula.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _EXPLODE_H
+#define _EXPLODE_H
+
+#define LIBMPQ_PKZIP_EXP_BUFFER_SIZE 12596 /* Size of decompress buffer */
+#define LIBMPQ_PKZIP_CMP_BINARY 0 /* Binary compression */
+#define LIBMPQ_PKZIP_CMP_ASCII 1 /* Ascii compression */
+#define LIBMPQ_PKZIP_CMP_NO_ERROR 0
+#define LIBMPQ_PKZIP_CMP_INV_DICTSIZE 1
+#define LIBMPQ_PKZIP_CMP_INV_MODE 2
+#define LIBMPQ_PKZIP_CMP_BAD_DATA 3
+#define LIBMPQ_PKZIP_CMP_ABORT 4
+
+/* Compression structure (size: 12596 bytes on x86-32) */
+typedef struct {
+ unsigned long offs0000; /* 0000 */
+ unsigned long cmp_type; /* 0004 - Compression type (LIBMPQ_PZIP_CMP_BINARY or LIBMPQ_PKZIP_CMP_ASCII) */
+ unsigned long out_pos; /* 0008 - Position in output buffer */
+ unsigned long dsize_bits; /* 000C - Dict size (4, 5, 6 for 0x400, 0x800, 0x1000) */
+ unsigned long dsize_mask; /* 0010 - Dict size bitmask (0x0F, 0x1F, 0x3F for 0x400, 0x800, 0x1000) */
+ unsigned long bit_buf; /* 0014 - 16-bit buffer for processing input data */
+ unsigned long extra_bits; /* 0018 - Number of extra (above 8) bits in bit buffer */
+ unsigned int in_pos; /* 001C - Position in in_buf */
+ unsigned long in_bytes; /* 0020 - Number of bytes in input buffer */
+ void *param; /* 0024 - Custom parameter */
+ unsigned int (*read_buf)(char *buf, unsigned int *size, void *param); /* 0028 */
+ void (*write_buf)(char *buf, unsigned int *size, void *param); /* 002C */
+ unsigned char out_buf[0x2000]; /* 0030 - Output circle buffer. Starting position is 0x1000 */
+ unsigned char offs_2030[0x204]; /* 2030 - ??? */
+ unsigned char in_buf[0x800]; /* 2234 - Buffer for data to be decompressed */
+ unsigned char pos1[0x100]; /* 2A34 - Positions in buffers */
+ unsigned char pos2[0x100]; /* 2B34 - Positions in buffers */
+ unsigned char offs_2c34[0x100]; /* 2C34 - Buffer for */
+ unsigned char offs_2d34[0x100]; /* 2D34 - Buffer for */
+ unsigned char offs_2e34[0x80]; /* 2EB4 - Buffer for */
+ unsigned char offs_2eb4[0x100]; /* 2EB4 - Buffer for */
+ unsigned char bits_asc[0x100]; /* 2FB4 - Buffer for */
+ unsigned char dist_bits[0x40]; /* 30B4 - Numbers of bytes to skip copied block length */
+ unsigned char slen_bits[0x10]; /* 30F4 - Numbers of bits for skip copied block length */
+ unsigned char clen_bits[0x10]; /* 3104 - Number of valid bits for copied block */
+ unsigned short len_base[0x10]; /* 3114 - Buffer for */
+} pkzip_data_cmp;
+// __attribute__ ((packed)) pkzip_data_cmp;
+
+typedef struct {
+ char *in_buf; /* Pointer to input data buffer */
+ unsigned int in_pos; /* Current offset in input data buffer */
+ int in_bytes; /* Number of bytes in the input buffer */
+ char *out_buf; /* Pointer to output data buffer */
+ unsigned int out_pos; /* Position in the output buffer */
+ int max_out; /* Maximum number of bytes in the output buffer */
+} pkzip_data;
+
+extern unsigned int libmpq_pkzip_explode(
+ unsigned int (*read_buf)(char *buf, unsigned int *size, void *param),
+ void (*write_buf)(char *buf, unsigned int *size, void *param),
+ char *work_buf,
+ void *param
+);
+
+#endif /* _EXPLODE_H */
diff --git a/contrib/extractor/libmpq/extract.cpp b/contrib/extractor/libmpq/extract.cpp
new file mode 100644
index 00000000000..41472b3c426
--- /dev/null
+++ b/contrib/extractor/libmpq/extract.cpp
@@ -0,0 +1,262 @@
+/*
+ * extract.c -- global extracting function for all known file compressions
+ * in a MPQ archive.
+ *
+ * Copyright (C) 2003 Maik Broemme <mbroemme@plusserver.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#define HAVE_LIBZ
+#ifdef HAVE_LIBZ
+#include <zlib.h>
+#endif
+
+#include "mpq.h"
+#include "explode.h"
+#include "huffman.h"
+
+#include "wave.h"
+
+/*
+ * Support functions for PKWARE data compression library.
+ *
+ * Function loads data from the input buffer. Used by mpq_pkzip
+ * "implode" and "explode" function as user-defined callback.
+ * Returns number of bytes loaded.
+ *
+ * char * buf - Pointer to a buffer where to store loaded data
+ * unsigned int * size - Max. number of bytes to read
+ * void * param - Custom pointer, parameter of implode/explode
+ */
+static unsigned int libmpq_pkzip_read_input_data(char *buf, unsigned int *size, void *param) {
+ pkzip_data *info = (pkzip_data *)param;
+ unsigned int max_avail = (info->in_bytes - info->in_pos);
+ unsigned int to_read = *size;
+
+ /* Check the case when not enough data available */
+ if (to_read > max_avail) {
+ to_read = max_avail;
+ }
+
+ /* Load data and increment offsets */
+ memcpy(buf, info->in_buf + info->in_pos, to_read);
+ info->in_pos += to_read;
+
+ return to_read;
+}
+
+/*
+ * Support functions for PKWARE data compression library.
+ *
+ * Function for store output data. Used by mpq_pkzip "implode" and
+ * "explode" as user-defined callback.
+ *
+ * char * buf - Pointer to data to be written
+ * unsigned int * size - Number of bytes to write
+ * void * param - Custom pointer, parameter of implode/explode
+ */
+static void libmpq_pkzip_write_output_data(char *buf, unsigned int *size, void *param) {
+ pkzip_data *info = (pkzip_data *)param;
+ unsigned int max_write = (info->max_out - info->out_pos);
+ unsigned int to_write = *size;
+
+ /* Check the case when not enough space in the output buffer */
+ if (to_write > max_write) {
+ to_write = max_write;
+ }
+
+ /* Write output data and increments offsets */
+ memcpy(info->out_buf + info->out_pos, buf, to_write);
+ info->out_pos += to_write;
+}
+
+int libmpq_pkzip_decompress(char *out_buf, int *out_length, char *in_buf, int in_length) {
+ pkzip_data info; /* Data information */
+ char *work_buf = (char *)malloc(LIBMPQ_PKZIP_EXP_BUFFER_SIZE); /* mpq_pkzip work buffer */
+
+ /* Fill data information structure */
+ info.in_buf = in_buf;
+ info.in_pos = 0;
+ info.in_bytes = in_length;
+ info.out_buf = out_buf;
+ info.out_pos = 0;
+ info.max_out = *out_length;
+
+ /* Do the decompression */
+ libmpq_pkzip_explode(libmpq_pkzip_read_input_data, libmpq_pkzip_write_output_data, work_buf, &info);
+ *out_length = info.out_pos;
+ free(work_buf);
+ return 0;
+}
+
+int libmpq_wave_decompress_mono(char *out_buf, int *out_length, char *in_buf, int in_length) {
+ *out_length = libmpq_wave_decompress((unsigned char *)out_buf, *out_length, (unsigned char *)in_buf, in_length, 1);
+ return 1;
+}
+
+int libmpq_wave_decompress_stereo(char *out_buf, int *out_length, char *in_buf, int in_length) {
+ *out_length = libmpq_wave_decompress((unsigned char *)out_buf, *out_length, (unsigned char *)in_buf, in_length, 2);
+ return 1;
+}
+
+int libmpq_zlib_decompress(char *out_buf, int *out_length, char *in_buf, int in_length) {
+#ifdef HAVE_LIBZ
+ z_stream z; /* Stream information for zlib */
+ int result;
+
+ /* Fill the stream structure for zlib */
+ z.next_in = (Bytef *)in_buf;
+ z.avail_in = (uInt)in_length;
+ z.total_in = in_length;
+ z.next_out = (Bytef *)out_buf;
+ z.avail_out = *out_length;
+ z.total_out = 0;
+ z.zalloc = NULL;
+ z.zfree = NULL;
+
+ /* Initialize the decompression structure. Storm.dll uses zlib version 1.1.3 */
+ if ((result = inflateInit(&z)) == 0) {
+
+ /* Call zlib to decompress the data */
+ result = inflate(&z, Z_FINISH);
+ *out_length = z.total_out;
+ inflateEnd(&z);
+ }
+ return result;
+#else
+ memset(out_buf, '0', *out_length);
+ return 0;
+#endif
+}
+
+/*
+ * Huffmann decompression routine. The in_length parameter is not used, but needs
+ * to be specified due to compatibility reasons.
+ *
+ * 1500F5F0
+ */
+int libmpq_huff_decompress(char *out_buf, int *out_length, char *in_buf, int in_length) {
+ struct huffman_tree *ht = (huffman_tree *)malloc(sizeof(struct huffman_tree));
+ struct huffman_input_stream *is = (huffman_input_stream *)malloc(sizeof(struct huffman_input_stream));
+ struct huffman_tree_item *hi = (huffman_tree_item *)malloc(sizeof(struct huffman_tree_item));
+ memset(ht, 0, sizeof(struct huffman_tree));
+ memset(is, 0, sizeof(struct huffman_input_stream));
+ memset(hi, 0, sizeof(struct huffman_tree_item));
+
+ /* Initialize input stream */
+ is->bit_buf = *(unsigned long *)in_buf;
+ in_buf += sizeof(unsigned long);
+ is->in_buf = (unsigned char *)in_buf;
+ is->bits = 32;
+
+ /* Initialize the Huffmann tree for decompression */
+ libmpq_huff_init_tree(ht, hi, LIBMPQ_HUFF_DECOMPRESS);
+
+ *out_length = libmpq_huff_do_decompress(ht, is, (unsigned char *)out_buf, *out_length);
+
+ free(hi);
+ free(is);
+ free(ht);
+ return 0;
+}
+
+int libmpq_multi_decompress(char *out_buf, int *pout_length, char *in_buf, int in_length) {
+ char *temp_buf = NULL; /* Temporary storage for decompressed data */
+ char *work_buf = NULL; /* Where to store decompressed data */
+ int out_length = *pout_length; /* For storage number of output bytes */
+ unsigned fDecompressions1; /* Decompressions applied to the block */
+ unsigned fDecompressions2; /* Just another copy of decompressions applied to the block */
+ int count = 0; /* Counter for every use */
+ int entries = (sizeof(dcmp_table) / sizeof(decompress_table));
+ int i;
+
+ /* If the input length is the same as output, do nothing. */
+ if (in_length == out_length) {
+ if (in_buf == out_buf) {
+ return 1;
+ }
+ memcpy(out_buf, in_buf, in_length);
+ return 1;
+ }
+
+ /* Get applied compression types and decrement data length */
+ fDecompressions1 = fDecompressions2 = (unsigned char)*in_buf++;
+ in_length--;
+
+ /* Search decompression table type and get all types of compression */
+ for (i = 0; i < entries; i++) {
+ /* We have to apply this decompression? */
+ if (fDecompressions1 & dcmp_table[i].mask) {
+ count++;
+ }
+
+ /* Clear this flag from temporary variable. */
+ fDecompressions2 &= ~dcmp_table[i].mask;
+ }
+
+ /*
+ * Check if there is some method unhandled
+ * (E.g. compressed by future versions)
+ */
+ if (fDecompressions2 != 0) {
+ printf("Unknown Compression\n");
+ return 0;
+ }
+
+ /* If there is more than only one compression, we have to allocate extra buffer */
+ if (count >= 2) {
+ temp_buf = (char *)malloc(out_length);
+ }
+
+ /* Apply all decompressions */
+ for (i = 0, count = 0; i < entries; i++) {
+
+ /* If not used this kind of compression, skip the loop */
+ if (fDecompressions1 & dcmp_table[i].mask) {
+
+ /* If odd case, use target buffer for output, otherwise use allocated tempbuf */
+ work_buf = (count++ & 1) ? temp_buf : out_buf;
+ out_length = *pout_length;
+
+ /* Decompress buffer using corresponding function */
+ dcmp_table[i].decompress(work_buf, &out_length, in_buf, in_length);
+
+ /* Move output length to src length for next compression */
+ in_length = out_length;
+ in_buf = work_buf;
+ }
+ }
+
+ /* If output buffer is not the same like target buffer, we have to copy data */
+ if (work_buf != out_buf) {
+ memcpy(out_buf, in_buf, out_length);
+ }
+ *pout_length = out_length;
+
+ /* Delete temporary buffer, if necessary */
+ if (temp_buf != NULL) {
+ free(temp_buf);
+ }
+ return 1;
+}
diff --git a/contrib/extractor/libmpq/huffman.cpp b/contrib/extractor/libmpq/huffman.cpp
new file mode 100644
index 00000000000..b63eee43e42
--- /dev/null
+++ b/contrib/extractor/libmpq/huffman.cpp
@@ -0,0 +1,833 @@
+/*
+ * huffman.c -- functions do decompress files in MPQ files which
+ * uses a modified huffman version.
+ *
+ * Copyright (C) 2003 Maik Broemme <mbroemme@plusserver.de>
+ *
+ * Differences between C++ and C version:
+ *
+ * - Removed the object oriented stuff.
+ * - Replaced the goto things with some better C code.
+ *
+ * This source was adepted from the C++ version of huffman.cpp included
+ * in stormlib. The C++ version belongs to the following authors,
+ *
+ * Ladislav Zezula <ladik.zezula.net>
+ * ShadowFlare <BlakFlare@hotmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#include <stdlib.h>
+#include <string.h>
+
+#include "mpq.h"
+#include "huffman.h"
+
+unsigned char table1502A630[] = {
+
+ /* Data for compression type 0x00 */
+ 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x00, 0x00,
+
+ /* Data for compression type 0x01 */
+ 0x54, 0x16, 0x16, 0x0D, 0x0C, 0x08, 0x06, 0x05, 0x06, 0x05, 0x06, 0x03, 0x04, 0x04, 0x03, 0x05,
+ 0x0E, 0x0B, 0x14, 0x13, 0x13, 0x09, 0x0B, 0x06, 0x05, 0x04, 0x03, 0x02, 0x03, 0x02, 0x02, 0x02,
+ 0x0D, 0x07, 0x09, 0x06, 0x06, 0x04, 0x03, 0x02, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02,
+ 0x09, 0x06, 0x04, 0x04, 0x04, 0x04, 0x03, 0x02, 0x03, 0x02, 0x02, 0x02, 0x02, 0x03, 0x02, 0x04,
+ 0x08, 0x03, 0x04, 0x07, 0x09, 0x05, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x03, 0x02, 0x02,
+ 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02,
+ 0x06, 0x0A, 0x08, 0x08, 0x06, 0x07, 0x04, 0x03, 0x04, 0x04, 0x02, 0x02, 0x04, 0x02, 0x03, 0x03,
+ 0x04, 0x03, 0x07, 0x07, 0x09, 0x06, 0x04, 0x03, 0x03, 0x02, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x0A, 0x02, 0x02, 0x03, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x06, 0x03, 0x05, 0x02, 0x03,
+ 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x03, 0x01, 0x01, 0x01,
+ 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x04, 0x04, 0x04, 0x07, 0x09, 0x08, 0x0C, 0x02,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x03,
+ 0x04, 0x01, 0x02, 0x04, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01,
+ 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x06, 0x4B,
+ 0x00, 0x00,
+
+ /* Data for compression type 0x02 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x27, 0x00, 0x00, 0x23, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x06, 0x0E, 0x10, 0x04,
+ 0x06, 0x08, 0x05, 0x04, 0x04, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03, 0x01, 0x01, 0x02, 0x01, 0x01,
+ 0x01, 0x04, 0x02, 0x04, 0x02, 0x02, 0x02, 0x01, 0x01, 0x04, 0x01, 0x01, 0x02, 0x03, 0x03, 0x02,
+ 0x03, 0x01, 0x03, 0x06, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x01, 0x01,
+ 0x01, 0x29, 0x07, 0x16, 0x12, 0x40, 0x0A, 0x0A, 0x11, 0x25, 0x01, 0x03, 0x17, 0x10, 0x26, 0x2A,
+ 0x10, 0x01, 0x23, 0x23, 0x2F, 0x10, 0x06, 0x07, 0x02, 0x09, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00,
+
+ /* Data for compression type 0x03 */
+ 0xFF, 0x0B, 0x07, 0x05, 0x0B, 0x02, 0x02, 0x02, 0x06, 0x02, 0x02, 0x01, 0x04, 0x02, 0x01, 0x03,
+ 0x09, 0x01, 0x01, 0x01, 0x03, 0x04, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01,
+ 0x05, 0x01, 0x01, 0x01, 0x0D, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x0A, 0x04, 0x02, 0x01, 0x06, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x01,
+ 0x05, 0x02, 0x03, 0x04, 0x03, 0x03, 0x03, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x03, 0x03,
+ 0x01, 0x03, 0x01, 0x01, 0x02, 0x05, 0x01, 0x01, 0x04, 0x03, 0x05, 0x01, 0x03, 0x01, 0x03, 0x03,
+ 0x02, 0x01, 0x04, 0x03, 0x0A, 0x06, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x01, 0x0A, 0x02, 0x05, 0x01, 0x01, 0x02, 0x07, 0x02, 0x17, 0x01, 0x05, 0x01, 0x01,
+ 0x0E, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x06, 0x02, 0x01, 0x04, 0x05, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x11,
+ 0x00, 0x00,
+
+ /* Data for compression type 0x04 */
+ 0xFF, 0xFB, 0x98, 0x9A, 0x84, 0x85, 0x63, 0x64, 0x3E, 0x3E, 0x22, 0x22, 0x13, 0x13, 0x18, 0x17,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00,
+
+ /* Data for compression type 0x05 */
+ 0xFF, 0xF1, 0x9D, 0x9E, 0x9A, 0x9B, 0x9A, 0x97, 0x93, 0x93, 0x8C, 0x8E, 0x86, 0x88, 0x80, 0x82,
+ 0x7C, 0x7C, 0x72, 0x73, 0x69, 0x6B, 0x5F, 0x60, 0x55, 0x56, 0x4A, 0x4B, 0x40, 0x41, 0x37, 0x37,
+ 0x2F, 0x2F, 0x27, 0x27, 0x21, 0x21, 0x1B, 0x1C, 0x17, 0x17, 0x13, 0x13, 0x10, 0x10, 0x0D, 0x0D,
+ 0x0B, 0x0B, 0x09, 0x09, 0x08, 0x08, 0x07, 0x07, 0x06, 0x05, 0x05, 0x04, 0x04, 0x04, 0x19, 0x18,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00,
+
+ /* Data for compression type 0x06 */
+ 0xC3, 0xCB, 0xF5, 0x41, 0xFF, 0x7B, 0xF7, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xBF, 0xCC, 0xF2, 0x40, 0xFD, 0x7C, 0xF7, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x7A, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00,
+
+ /* Data for compression type 0x07 */
+ 0xC3, 0xD9, 0xEF, 0x3D, 0xF9, 0x7C, 0xE9, 0x1E, 0xFD, 0xAB, 0xF1, 0x2C, 0xFC, 0x5B, 0xFE, 0x17,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xBD, 0xD9, 0xEC, 0x3D, 0xF5, 0x7D, 0xE8, 0x1D, 0xFB, 0xAE, 0xF0, 0x2C, 0xFB, 0x5C, 0xFF, 0x18,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x70, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00,
+
+ /* Data for compression type 0x08 */
+ 0xBA, 0xC5, 0xDA, 0x33, 0xE3, 0x6D, 0xD8, 0x18, 0xE5, 0x94, 0xDA, 0x23, 0xDF, 0x4A, 0xD1, 0x10,
+ 0xEE, 0xAF, 0xE4, 0x2C, 0xEA, 0x5A, 0xDE, 0x15, 0xF4, 0x87, 0xE9, 0x21, 0xF6, 0x43, 0xFC, 0x12,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xB0, 0xC7, 0xD8, 0x33, 0xE3, 0x6B, 0xD6, 0x18, 0xE7, 0x95, 0xD8, 0x23, 0xDB, 0x49, 0xD0, 0x11,
+ 0xE9, 0xB2, 0xE2, 0x2B, 0xE8, 0x5C, 0xDD, 0x15, 0xF1, 0x87, 0xE7, 0x20, 0xF7, 0x44, 0xFF, 0x13,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x5F, 0x9E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00
+};
+
+/* Gets previous Huffman tree item (?) */
+struct huffman_tree_item *libmpq_huff_get_prev_item(struct huffman_tree_item *hi, long value) {
+ if (PTR_INT(hi->prev) < 0) {
+ return PTR_NOT(hi->prev);
+ }
+ if (value < 0) {
+ value = hi - hi->next->prev;
+ }
+ return hi->prev + value;
+}
+
+/* 1500BC90 */
+static void libmpq_huff_remove_item(struct huffman_tree_item *hi) {
+ struct huffman_tree_item *temp; /* EDX */
+
+ if (hi->next != NULL) {
+ temp = hi->prev;
+ if (PTR_INT(temp) <= 0) {
+ temp = PTR_NOT(temp);
+ } else {
+ temp += (hi - hi->next->prev);
+ }
+ temp->next = hi->next;
+ hi->next->prev = hi->prev;
+ hi->next = hi->prev = NULL;
+ }
+}
+
+static void libmpq_huff_insert_item(struct huffman_tree_item **p_item, struct huffman_tree_item *item, unsigned long where, struct huffman_tree_item *item2) {
+ struct huffman_tree_item *next = item->next; /* EDI - next to the first item */
+ struct huffman_tree_item *prev = item->prev; /* ESI - prev to the first item */
+ struct huffman_tree_item *prev2; /* Pointer to previous item */
+ long next2; /* Pointer to the next item */
+
+ /* The same code like in mpq_huff_remove_item(); */
+ if (next != 0) { /* If the first item already has next one */
+ if (PTR_INT(prev) < 0) {
+ prev = PTR_NOT(prev);
+ } else {
+ prev += (item - next->prev);
+ }
+
+ /*
+ * 150083C1
+ * Remove the item from the tree
+ */
+ prev->next = next;
+ next->prev = prev;
+
+ /* Invalidate 'prev' and 'next' pointer */
+ item->next = 0;
+ item->prev = 0;
+ }
+
+ if (item2 == NULL) { /* EDX - If the second item is not entered, */
+ item2 = PTR_PTR(&p_item[1]); /* take the first tree item */
+ }
+
+ switch (where) {
+ case SWITCH_ITEMS: /* Switch the two items */
+ item->next = item2->next; /* item2->next (Pointer to pointer to first) */
+ item->prev = item2->next->prev;
+ item2->next->prev = item;
+ item2->next = item; /* Set the first item */
+ return;
+ case INSERT_ITEM: /* Insert as the last item */
+ item->next = item2; /* Set next item (or pointer to pointer to first item) */
+ item->prev = item2->prev; /* Set prev item (or last item in the tree) */
+ next2 = PTR_INT(p_item[0]); /* Usually NULL */
+ prev2 = item2->prev; /* Prev item to the second (or last tree item) */
+ if (PTR_INT(prev2) < 0) {
+ prev2 = PTR_NOT(prev);
+ prev2->next = item;
+ item2->prev = item; /* Next after last item */
+ return;
+ }
+ if (next2 < 0) {
+ next2 = item2 - item2->next->prev;
+ }
+ prev2 += next2;
+ prev2->next = item;
+ item2->prev = item; /* Set the next/last item */
+ return;
+ default:
+ return;
+ }
+}
+
+/* Builds Huffman tree. Called with the first 8 bits loaded from input stream. */
+static void libmpq_huff_build_tree(struct huffman_tree *ht, unsigned int cmp_type) {
+ unsigned long max_byte; /* [ESP+10] - The greatest character found in table */
+ unsigned char *byte_array; /* [ESP+1C] - Pointer to unsigned char in table1502A630 */
+ unsigned long i; /* egcs in linux doesn't like multiple for loops without an explicit i */
+ unsigned int found; /* Thats needed to replace the goto stuff from original source :) */
+ struct huffman_tree_item **p_item; /* [ESP+14] - Pointer to Huffman tree item pointer array */
+ struct huffman_tree_item *child1;
+
+ /* Loop while pointer has a negative value. */
+ while (PTR_INT(ht->last) > 0) { /* ESI - Last entry */
+ struct huffman_tree_item *temp; /* EAX */
+
+ if (ht->last->next != NULL) { /* ESI->next */
+ libmpq_huff_remove_item(ht->last);
+ }
+ ht->item3058 = PTR_PTR(&ht->item3054);/* [EDI+4] */
+ ht->last->prev = ht->item3058; /* EAX */
+ temp = libmpq_huff_get_prev_item(PTR_PTR(&ht->item3054), PTR_INT(&ht->item3050));
+ temp->next = ht->last;
+ ht->item3054 = ht->last;
+ }
+
+ /* Clear all pointers in huffman tree item array. */
+ memset(ht->items306C, 0, sizeof(ht->items306C));
+
+ max_byte = 0; /* Greatest character found init to zero. */
+ p_item = (struct huffman_tree_item **)&ht->items306C; /* Pointer to current entry in huffman tree item pointer array */
+
+ /* Ensure we have low 8 bits only */
+ cmp_type &= 0xFF;
+ byte_array = table1502A630 + cmp_type * 258; /* EDI also */
+
+ for (i = 0; i < 0x100; i++, p_item++) {
+ struct huffman_tree_item *item = ht->item3058; /* Item to be created */
+ struct huffman_tree_item *p_item3 = ht->item3058;
+ unsigned char one_byte = byte_array[i];
+
+ /* Skip all the bytes which are zero. */
+ if (byte_array[i] == 0) {
+ continue;
+ }
+
+ /* If not valid pointer, take the first available item in the array. */
+ if (PTR_INT(item) <= 0) {
+ item = &ht->items0008[ht->items++];
+ }
+
+ /* Insert this item as the top of the tree. */
+ libmpq_huff_insert_item(&ht->item305C, item, SWITCH_ITEMS, NULL);
+
+ item->parent = NULL; /* Invalidate child and parent */
+ item->child = NULL;
+ *p_item = item; /* Store pointer into pointer array */
+
+ item->dcmp_byte = i; /* Store counter */
+ item->byte_value = one_byte; /* Store byte value */
+ if (one_byte >= max_byte) {
+ max_byte = one_byte;
+ continue;
+ }
+
+ /* Find the first item which has byte value greater than current one byte */
+ found = 0;
+ if (PTR_INT((p_item3 = ht->last)) > 0) {/* EDI - Pointer to the last item */
+
+ /* 15006AF7 */
+ if (p_item3 != NULL) {
+ do { /* 15006AFB */
+ if (p_item3->byte_value >= one_byte) {
+ found = 1;
+ break;
+ }
+ p_item3 = p_item3->prev;
+ } while (PTR_INT(p_item3) > 0);
+ }
+ }
+
+ if (found == 0) {
+ p_item3 = NULL;
+ }
+
+ /* 15006B09 */
+ if (item->next != NULL) {
+ libmpq_huff_remove_item(item);
+ }
+
+ /* 15006B15 */
+ if (p_item3 == NULL) {
+ p_item3 = PTR_PTR(&ht->first);
+ }
+
+ /* 15006B1F */
+ item->next = p_item3->next;
+ item->prev = p_item3->next->prev;
+ p_item3->next->prev = item;
+ p_item3->next = item;
+ }
+
+ /* 15006B4A */
+ for (; i < 0x102; i++) {
+ struct huffman_tree_item **p_item2 = &ht->items306C[i]; /* EDI */
+
+ /* 15006B59 */
+ struct huffman_tree_item *item2 = ht->item3058; /* ESI */
+ if (PTR_INT(item2) <= 0) {
+ item2 = &ht->items0008[ht->items++];
+ }
+ libmpq_huff_insert_item(&ht->item305C, item2, INSERT_ITEM, NULL);
+
+ /* 15006B89 */
+ item2->dcmp_byte = i;
+ item2->byte_value = 1;
+ item2->parent = NULL;
+ item2->child = NULL;
+ *p_item2++ = item2;
+ }
+
+ /* 15006BAA */
+ if (PTR_INT((child1 = ht->last)) > 0) { /* EDI - last item (first child to item */
+ struct huffman_tree_item *child2; /* EBP */
+ struct huffman_tree_item *item; /* ESI */
+
+ /* 15006BB8 */
+ while (PTR_INT((child2 = child1->prev)) > 0) {
+ if (PTR_INT((item = ht->item3058)) <= 0) {
+ item = &ht->items0008[ht->items++];
+ }
+ /* 15006BE3 */
+ libmpq_huff_insert_item(&ht->item305C, item, SWITCH_ITEMS, NULL);
+
+ /* 15006BF3 */
+ item->parent = NULL;
+ item->child = NULL;
+
+ /*
+ * EDX = child2->byte_value + child1->byte_value;
+ * EAX = child1->byte_value;
+ * ECX = max_byte; The greatest character (0xFF usually)
+ */
+ item->byte_value = child1->byte_value + child2->byte_value; /* 0x02 */
+ item->child = child1; /* Prev item in the */
+ child1->parent = item;
+ child2->parent = item;
+
+ /* EAX = item->byte_value; */
+ if (item->byte_value >= max_byte) {
+ max_byte = item->byte_value;
+ } else {
+ struct huffman_tree_item *p_item2 = child2->prev; /* EDI */
+ found = 0;
+ if (PTR_INT(p_item2) > 0) {
+
+ /* 15006C2D */
+ do {
+ if (p_item2->byte_value >= item->byte_value) {
+ found = 1;
+ break;
+ }
+ p_item2 = p_item2->prev;
+ } while (PTR_INT(p_item2) > 0);
+ }
+ if (found == 0) {
+ p_item2 = NULL;
+ }
+ if (item->next != 0) {
+ struct huffman_tree_item *temp4 = libmpq_huff_get_prev_item(item, -1);
+ temp4->next = item->next; /* The first item changed */
+ item->next->prev = item->prev; /* First->prev changed to negative value */
+ item->next = NULL;
+ item->prev = NULL;
+ }
+
+ /* 15006C62 */
+ if (p_item2 == NULL) {
+ p_item2 = PTR_PTR(&ht->first);
+ }
+ item->next = p_item2->next; /* Set item with 0x100 byte value */
+ item->prev = p_item2->next->prev; /* Set item with 0x17 byte value */
+ p_item2->next->prev = item; /* Changed prev of item with */
+ p_item2->next = item;
+ }
+
+ /* 15006C7B */
+ if (PTR_INT((child1 = child2->prev)) <= 0) {
+ break;
+ }
+ }
+ }
+
+ /* 15006C88 */
+ ht->offs0004 = 1;
+}
+
+/* Gets the whole byte from the input stream. */
+static unsigned long libmpq_huff_get_8bits(struct huffman_input_stream *is) {
+ unsigned long one_byte;
+
+ if (is->bits <= 8) {
+ is->bit_buf |= *(unsigned short *)is->in_buf << is->bits;
+ is->in_buf += sizeof(unsigned short);
+ is->bits += 16;
+ }
+
+ one_byte = (is->bit_buf & 0xFF);
+ is->bit_buf >>= 8;
+ is->bits -= 8;
+
+ return one_byte;
+}
+
+/* Gets 7 bits from the stream. */
+static unsigned long libmpq_huff_get_7bits(struct huffman_input_stream *is) {
+ if (is->bits <= 7) {
+ is->bit_buf |= *(unsigned short *)is->in_buf << is->bits;
+ is->in_buf += sizeof(unsigned short);
+ is->bits += 16;
+ }
+
+ /* Get 7 bits from input stream. */
+ return (is->bit_buf & 0x7F);
+}
+
+/* Gets one bit from input stream. */
+unsigned long libmpq_huff_get_bit(struct huffman_input_stream *is) {
+ unsigned long bit = (is->bit_buf & 1);
+
+ is->bit_buf >>= 1;
+ if (--is->bits == 0) {
+ is->bit_buf = *(unsigned long *)is->in_buf;
+ is->in_buf += sizeof(unsigned long);
+ is->bits = 32;
+ }
+ return bit;
+}
+
+static struct huffman_tree_item *libmpq_huff_call1500E740(struct huffman_tree *ht, unsigned int value) {
+ struct huffman_tree_item *p_item1 = ht->item3058; /* EDX */
+ struct huffman_tree_item *p_item2; /* EAX */
+ struct huffman_tree_item *p_next;
+ struct huffman_tree_item *p_prev;
+ struct huffman_tree_item **pp_item;
+
+ if (PTR_INT(p_item1) <= 0 || (p_item2 = p_item1) == NULL) {
+ if((p_item2 = &ht->items0008[ht->items++]) != NULL) {
+ p_item1 = p_item2;
+ } else {
+ p_item1 = ht->first;
+ }
+ } else {
+ p_item1 = p_item2;
+ }
+
+ p_next = p_item1->next;
+ if (p_next != NULL) {
+ p_prev = p_item1->prev;
+ if (PTR_INT(p_prev) <= 0) {
+ p_prev = PTR_NOT(p_prev);
+ } else {
+ p_prev += (p_item1 - p_item1->next->prev);
+ }
+
+ p_prev->next = p_next;
+ p_next->prev = p_prev;
+ p_item1->next = NULL;
+ p_item1->prev = NULL;
+ }
+ pp_item = &ht->first; /* ESI */
+ if (value > 1) {
+
+ /* ECX = ht->first->next; */
+ p_item1->next = *pp_item;
+ p_item1->prev = (*pp_item)->prev;
+
+ (*pp_item)->prev = p_item2;
+ *pp_item = p_item1;
+
+ p_item2->parent = NULL;
+ p_item2->child = NULL;
+ } else {
+ p_item1->next = (struct huffman_tree_item *)pp_item;
+ p_item1->prev = pp_item[1];
+ /* EDI = ht->item305C; */
+ p_prev = pp_item[1]; /* ECX */
+ if (p_prev <= 0) {
+ p_prev = PTR_NOT(p_prev);
+ p_prev->next = p_item1;
+ p_prev->prev = p_item2;
+
+ p_item2->parent = NULL;
+ p_item2->child = NULL;
+ } else {
+ if (PTR_INT(ht->item305C) < 0) {
+ p_prev += (struct huffman_tree_item *)pp_item - (*pp_item)->prev;
+ } else {
+ p_prev += PTR_INT(ht->item305C);
+ }
+
+ p_prev->next = p_item1;
+ pp_item[1] = p_item2;
+ p_item2->parent = NULL;
+ p_item2->child = NULL;
+ }
+ }
+ return p_item2;
+}
+
+static void libmpq_huff_call1500E820(struct huffman_tree *ht, struct huffman_tree_item *p_item) {
+ struct huffman_tree_item *p_item1; /* EDI */
+ struct huffman_tree_item *p_item2 = NULL; /* EAX */
+ struct huffman_tree_item *p_item3; /* EDX */
+ struct huffman_tree_item *p_prev; /* EBX */
+
+ for (; p_item != NULL; p_item = p_item->parent) {
+ p_item->byte_value++;
+
+ for (p_item1 = p_item; ; p_item1 = p_prev) {
+ p_prev = p_item1->prev;
+ if (PTR_INT(p_prev) <= 0) {
+ p_prev = NULL;
+ break;
+ }
+ if (p_prev->byte_value >= p_item->byte_value) {
+ break;
+ }
+ }
+
+ if (p_item1 == p_item) {
+ continue;
+ }
+
+ if (p_item1->next != NULL) {
+ p_item2 = libmpq_huff_get_prev_item(p_item1, -1);
+ p_item2->next = p_item1->next;
+ p_item1->next->prev = p_item1->prev;
+ p_item1->next = NULL;
+ p_item1->prev = NULL;
+ }
+ p_item2 = p_item->next;
+ p_item1->next = p_item2;
+ p_item1->prev = p_item2->prev;
+ p_item2->prev = p_item1;
+ p_item->next = p_item1;
+ if ((p_item2 = p_item1) != NULL) {
+ p_item2 = libmpq_huff_get_prev_item(p_item, -1);
+ p_item2->next = p_item->next;
+ p_item->next->prev = p_item->prev;
+ p_item->next = NULL;
+ p_item->prev = NULL;
+ }
+
+ if (p_prev == NULL) {
+ p_prev = PTR_PTR(&ht->first);
+ }
+ p_item2 = p_prev->next;
+ p_item->next = p_item2;
+ p_item->prev = p_item2->prev;
+ p_item2->prev = p_item;
+ p_prev->next = p_item;
+
+ p_item3 = p_item1->parent->child;
+ p_item2 = p_item->parent;
+ if (p_item2->child == p_item) {
+ p_item2->child = p_item1;
+ }
+
+ if (p_item3 == p_item1) {
+ p_item1->parent->child = p_item;
+ }
+
+ p_item2 = p_item->parent;
+ p_item->parent = p_item1->parent;
+ p_item1->parent = p_item2;
+ ht->offs0004++;
+ }
+}
+
+int libmpq_huff_do_decompress(struct huffman_tree *ht, struct huffman_input_stream *is, unsigned char *out_buf, unsigned int out_length) {
+ unsigned int n8bits; /* 8 bits loaded from input stream */
+ unsigned int n7bits; /* 7 bits loaded from input stream */
+ unsigned int found; /* Thats needed to replace the goto stuff from original source :) */
+ unsigned int dcmp_byte = 0;
+ unsigned long bit_count;
+ struct huffman_decompress *qd;
+ unsigned int has_qd; /* Can we use quick decompression? */
+ struct huffman_tree_item *p_item1;
+ struct huffman_tree_item *p_item2;
+ unsigned char *out_pos = out_buf;
+
+ /* Test the output length. Must not be non zero. */
+ if (out_length == 0) {
+ return 0;
+ }
+
+ /* Get the compression type from the input stream. */
+ n8bits = libmpq_huff_get_8bits(is);
+
+ /* Build the Huffman tree */
+ libmpq_huff_build_tree(ht, n8bits);
+ ht->cmp0 = (n8bits == 0) ? TRUE : FALSE;
+
+ for(;;) {
+ n7bits = libmpq_huff_get_7bits(is); /* Get 7 bits from input stream */
+
+ /*
+ * Try to use quick decompression. Check huffman_decompress array for corresponding item.
+ * If found, use the result byte instead.
+ */
+ qd = &ht->qd3474[n7bits];
+
+ /* If there is a quick-pass possible (ebx) */
+ has_qd = (qd->offs00 >= ht->offs0004) ? TRUE : FALSE;
+
+ /* If we can use quick decompress, use it. */
+ if (has_qd) {
+ found = 0;
+ if (qd->bits > 7) {
+ is->bit_buf >>= 7;
+ is->bits -= 7;
+ p_item1 = qd->p_item;
+ found = 1;
+ }
+ if (found == 0) {
+ is->bit_buf >>= qd->bits;
+ is->bits -= qd->bits;
+ dcmp_byte = qd->dcmp_byte;
+ }
+ } else {
+ found = 1;
+ p_item1 = ht->first->next->prev;
+ if (PTR_INT(p_item1) <= 0) {
+ p_item1 = NULL;
+ }
+ }
+
+ if (found == 1) {
+ bit_count = 0;
+ p_item2 = NULL;
+ do {
+ p_item1 = p_item1->child; /* Move down by one level */
+ if (libmpq_huff_get_bit(is)) { /* If current bit is set, move to previous */
+ p_item1 = p_item1->prev;
+ }
+ if (++bit_count == 7) { /* If we are at 7th bit, save current huffman tree item. */
+ p_item2 = p_item1;
+ }
+ } while (p_item1->child != NULL); /* Walk until tree has no deeper level */
+
+ if (has_qd == FALSE) {
+ if (bit_count > 7) {
+ qd->offs00 = ht->offs0004;
+ qd->bits = bit_count;
+ qd->p_item = p_item2;
+ } else {
+ unsigned long index = n7bits & (0xFFFFFFFF >> (32 - bit_count));
+ unsigned long add = (1 << bit_count);
+
+ for (qd = &ht->qd3474[index]; index <= 0x7F; index += add, qd += add) {
+ qd->offs00 = ht->offs0004;
+ qd->bits = bit_count;
+ qd->dcmp_byte = p_item1->dcmp_byte;
+ }
+ }
+ }
+ dcmp_byte = p_item1->dcmp_byte;
+ }
+
+ if (dcmp_byte == 0x101) { /* Huffman tree needs to be modified */
+ n8bits = libmpq_huff_get_8bits(is);
+ p_item1 = (ht->last <= 0) ? NULL : ht->last;
+
+ p_item2 = libmpq_huff_call1500E740(ht, 1);
+ p_item2->parent = p_item1;
+ p_item2->dcmp_byte = p_item1->dcmp_byte;
+ p_item2->byte_value = p_item1->byte_value;
+ ht->items306C[p_item2->dcmp_byte] = p_item2;
+
+ p_item2 = libmpq_huff_call1500E740(ht, 1);
+ p_item2->parent = p_item1;
+ p_item2->dcmp_byte = n8bits;
+ p_item2->byte_value = 0;
+ ht->items306C[p_item2->dcmp_byte] = p_item2;
+
+ p_item1->child = p_item2;
+ libmpq_huff_call1500E820(ht, p_item2);
+ if (ht->cmp0 == 0) {
+ libmpq_huff_call1500E820(ht, ht->items306C[n8bits]);
+ }
+ dcmp_byte = n8bits;
+ }
+
+ if (dcmp_byte == 0x100) {
+ break;
+ }
+
+ *out_pos++ = (unsigned char)dcmp_byte;
+ if (--out_length == 0) {
+ break;
+ }
+ if (ht->cmp0) {
+ libmpq_huff_call1500E820(ht, ht->items306C[dcmp_byte]);
+ }
+ }
+ return (out_pos - out_buf);
+}
+
+int libmpq_huff_init_tree(struct huffman_tree *ht, struct huffman_tree_item *hi, unsigned int cmp) {
+ int count;
+
+ /* Clear links for all the items in the tree */
+ for (hi = ht->items0008, count = 0x203; count != 0; hi++, count--) {
+ hi->next = hi->prev = NULL;
+ }
+
+ ht->item3050 = NULL;
+ ht->item3054 = PTR_PTR(&ht->item3054);
+ ht->item3058 = PTR_NOT(ht->item3054);
+
+ ht->item305C = NULL;
+ ht->first = PTR_PTR(&ht->first);
+ ht->last = PTR_NOT(ht->first);
+
+ ht->offs0004 = 1;
+ ht->items = 0;
+
+ /* Clear all huffman_decompress items. Do this only if preparing for decompression */
+ if (cmp == LIBMPQ_HUFF_DECOMPRESS) {
+ for (count = 0; count < sizeof(ht->qd3474) / sizeof(struct huffman_decompress); count++) {
+ ht->qd3474[count].offs00 = 0;
+ }
+ }
+
+ return 0;
+}
diff --git a/contrib/extractor/libmpq/huffman.h b/contrib/extractor/libmpq/huffman.h
new file mode 100644
index 00000000000..1f8eae54eb4
--- /dev/null
+++ b/contrib/extractor/libmpq/huffman.h
@@ -0,0 +1,105 @@
+/*
+ * huffman.h -- structures used for huffman compression.
+ *
+ * Copyright (C) 2003 Maik Broemme <mbroemme@plusserver.de>
+ *
+ * This source was adepted from the C++ version of huffman.h included
+ * in stormlib. The C++ version belongs to the following authors,
+ *
+ * Ladislav Zezula <ladik.zezula.net>
+ * ShadowFlare <BlakFlare@hotmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _HUFFMAN_H
+#define _HUFFMAN_H
+
+#define PTR_NOT(ptr) (struct huffman_tree_item *)(~(unsigned long)(ptr))
+#define PTR_PTR(ptr) ((struct huffman_tree_item *)(ptr))
+#define PTR_INT(ptr) (long)(ptr)
+
+#define INSERT_ITEM 1
+#define SWITCH_ITEMS 2 /* Switch the item1 and item2 */
+
+/*
+ * Input stream for Huffmann decompression
+ */
+struct huffman_input_stream {
+ unsigned char *in_buf; /* 00 - Input data */
+ unsigned long bit_buf; /* 04 - Input bit buffer */
+ unsigned int bits; /* 08 - Number of bits remaining in 'byte' */
+};
+
+/*
+ * Huffmann tree item.
+ */
+struct huffman_tree_item {
+ struct huffman_tree_item *next; /* 00 - Pointer to next huffman_tree_item */
+ struct huffman_tree_item *prev; /* 04 - Pointer to prev huffman_tree_item (< 0 if none) */
+ unsigned long dcmp_byte; /* 08 - Index of this item in item pointer array, decompressed byte value */
+ unsigned long byte_value; /* 0C - Some byte value */
+ struct huffman_tree_item *parent; /* 10 - Pointer to parent huffman_tree_item (NULL if none) */
+ struct huffman_tree_item *child; /* 14 - Pointer to child huffman_tree_item */
+};
+
+/*
+ * Structure used for quick decompress. The 'bits' contains
+ * number of bits and dcmp_byte contains result decompressed byte
+ * value. After each walk through Huffman tree are filled all entries
+ * which are multiplies of number of bits loaded from input stream.
+ * These entries contain number of bits and result value. At the next
+ * 7 bits is tested this structure first. If corresponding entry found,
+ * decompression routine will not walk through Huffman tree and
+ * directly stores output byte to output stream.
+ */
+struct huffman_decompress {
+ unsigned long offs00; /* 00 - 1 if resolved */
+ unsigned long bits; /* 04 - Bit count */
+ union {
+ unsigned long dcmp_byte; /* 08 - Byte value for decompress (if bitCount <= 7) */
+ struct huffman_tree_item *p_item; /* 08 - THTreeItem (if number of bits is greater than 7 */
+ };
+};
+
+/*
+ * Structure for Huffman tree.
+ */
+struct huffman_tree {
+ unsigned long cmp0; /* 0000 - 1 if compression type 0 */
+ unsigned long offs0004; /* 0004 - Some flag */
+
+ struct huffman_tree_item items0008[0x203]; /* 0008 - huffman tree items */
+
+ /* Sometimes used as huffman tree item */
+ struct huffman_tree_item *item3050; /* 3050 - Always NULL (?) */
+ struct huffman_tree_item *item3054; /* 3054 - Pointer to huffman_tree_item */
+ struct huffman_tree_item *item3058; /* 3058 - Pointer to huffman_tree_item (< 0 if invalid) */
+
+ /* Sometimes used as huffman tree item */
+ struct huffman_tree_item *item305C; /* 305C - Usually NULL */
+ struct huffman_tree_item *first; /* 3060 - Pointer to top (first) Huffman tree item */
+ struct huffman_tree_item *last; /* 3064 - Pointer to bottom (last) Huffman tree item (< 0 if invalid) */
+ unsigned long items; /* 3068 - Number of used huffman tree items */
+
+ struct huffman_tree_item *items306C[0x102]; /* 306C - huffman_tree_item pointer array */
+ struct huffman_decompress qd3474[0x80]; /* 3474 - Array for quick decompression */
+
+ //unsigned char table1502A630[]; /* Some table to make struct size flexible */
+};
+
+int libmpq_huff_init_tree(struct huffman_tree *ht, struct huffman_tree_item *hi, unsigned int cmp);
+int libmpq_huff_do_decompress(struct huffman_tree *ht, struct huffman_input_stream *is, unsigned char *out_buf, unsigned int out_length);
+#endif /* _HUFFMAN_H */
diff --git a/contrib/extractor/libmpq/mpq.cpp b/contrib/extractor/libmpq/mpq.cpp
new file mode 100644
index 00000000000..dda89a3b989
--- /dev/null
+++ b/contrib/extractor/libmpq/mpq.cpp
@@ -0,0 +1,626 @@
+/*
+ * mpq.c -- functions for developers using libmpq.
+ *
+ * Copyright (C) 2003 Maik Broemme <mbroemme@plusserver.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Id: mpq.c,v 1.6 2004/02/12 00:49:00 mbroemme Exp $
+ */
+#define _CRT_SECURE_NO_DEPRECATE
+
+#include <stdlib.h>
+#include <sys/stat.h>
+//#include <unistd.h>
+//#include <io.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include "mpq.h"
+#include "common.h"
+
+/*
+ * This function returns version information.
+ * format: MAJOR.MINOR.PATCH
+ */
+char *libmpq_version() {
+ static char version[10];
+ sprintf(version, "%i.%i.%i", LIBMPQ_MAJOR_VERSION, LIBMPQ_MINOR_VERSION, LIBMPQ_PATCH_VERSION);
+ return version;
+}
+
+/*
+ * This function reads a file and verify if it is a legit MPQ archive
+ * or not. Then it fills the mpq_header structure and reads the hash
+ * table.
+ */
+int libmpq_archive_open(mpq_archive *mpq_a, unsigned char *mpq_filename) {
+ int fd = 0;
+ int rb = 0;
+ int ncnt = FALSE;
+ struct stat fileinfo;
+
+ /* allocate memory */
+ mpq_a->mpq_l = (mpq_list *)malloc(sizeof(mpq_list));
+ memset(mpq_a->mpq_l, 0, sizeof(mpq_list));
+ mpq_a->header = (mpq_header *)malloc(sizeof(mpq_header));
+ memset(mpq_a->header, 0, sizeof(mpq_header));
+
+ /* Check if file exists and is readable */
+ fd = _open((char *)mpq_filename, O_RDONLY | O_BINARY);
+ if (fd == LIBMPQ_EFILE) {
+ return LIBMPQ_EFILE;
+ }
+
+ /* fill the structures with informations */
+ strcpy((char *)mpq_a->filename, (char *)mpq_filename);
+ libmpq_init_buffer(mpq_a);
+ mpq_a->fd = fd;
+ mpq_a->header->id = 0;
+ mpq_a->maxblockindex = 0;
+ mpq_a->mpq_l->mpq_files = NULL;
+
+ mpq_a->mpqpos = 0; //k
+
+ while (!ncnt) {
+ mpq_a->header->id = 0;
+ #ifdef WIN32
+ _lseeki64(mpq_a->fd, mpq_a->mpqpos, SEEK_SET);
+ #else
+ lseek64(mpq_a->fd, mpq_a->mpqpos, SEEK_SET);
+ #endif
+ rb = _read(mpq_a->fd, mpq_a->header, sizeof(mpq_header));
+
+ /* if different number of bytes read, break the loop */
+ if (rb != sizeof(mpq_header)) {
+ return LIBMPQ_EFILE_FORMAT;
+ }
+
+ /* special offset for protected MPQs */
+ if (mpq_a->header->offset == LIBMPQ_HEADER_W3M) {
+ mpq_a->flags |= LIBMPQ_FLAG_PROTECTED;
+ mpq_a->header->offset = sizeof(mpq_header);
+ }
+
+ /* if valid signature has been found, break the loop */
+ if (mpq_a->header->id == LIBMPQ_ID_MPQ) {
+ ncnt = true;
+ }
+ /*if (mpq_a->header->id == LIBMPQ_ID_MPQ &&
+ mpq_a->header->offset == sizeof(mpq_header) &&
+ mpq_a->header->hashtablepos < mpq_a->header->archivesize &&
+ mpq_a->header->blocktablepos < mpq_a->header->archivesize) {
+ ncnt = TRUE;
+ }*/
+
+ /* move to the next possible offset */
+ if (!ncnt) {
+ mpq_a->mpqpos += 0x200;
+ }
+ }
+
+ /* get the right positions of the hash table and the block table. */
+ mpq_a->blocksize = (0x200 << mpq_a->header->blocksize);
+ fstat(mpq_a->fd, &fileinfo);
+
+ /* Normal MPQs must have position of */
+ /*if (mpq_a->header->hashtablepos + mpq_a->mpqpos < fileinfo.st_size &&
+ mpq_a->header->blocktablepos + mpq_a->mpqpos < fileinfo.st_size) {
+ mpq_a->header->hashtablepos += mpq_a->mpqpos;
+ mpq_a->header->blocktablepos += mpq_a->mpqpos;
+ } else {
+ return LIBMPQ_EFILE_FORMAT;
+ }*/
+
+ /* Try to read and decrypt the hashtable */
+ if (libmpq_read_hashtable(mpq_a) != 0) {
+ return LIBMPQ_EHASHTABLE;
+ }
+
+ /* Try to read and decrypt the blocktable */
+ if (libmpq_read_blocktable(mpq_a) != 0) {
+ return LIBMPQ_EBLOCKTABLE;
+ }
+
+ return LIBMPQ_TOOLS_SUCCESS;
+}
+
+/*
+ * This function closes the file descriptor opened by
+ * mpq_open_archive(); and frees the decryption buffer.
+ */
+int libmpq_archive_close(mpq_archive *mpq_a) {
+ memset(mpq_a->buf, 0, sizeof(mpq_a->buf));
+
+ /* free the allocated memory. */
+ free(mpq_a->header);
+ free(mpq_a->mpq_l);
+
+ /* Check if file descriptor is valid. */
+ if ((_close(mpq_a->fd)) == LIBMPQ_EFILE) {
+ return LIBMPQ_EFILE;
+ }
+
+ return LIBMPQ_TOOLS_SUCCESS;
+}
+
+/*
+ * This function returns the value for the given infotype.
+ * If an error occurs something < 0 is returned.
+ */
+int libmpq_archive_info(mpq_archive *mpq_a, unsigned int infotype) {
+ unsigned int filecount = 0;
+ unsigned int fsize = 0;
+ unsigned int csize = 0;
+ mpq_block *mpq_b_end = mpq_a->blocktable + mpq_a->header->blocktablesize;
+ mpq_block *mpq_b = NULL;
+
+ switch (infotype) {
+ case LIBMPQ_MPQ_ARCHIVE_SIZE:
+ return mpq_a->header->archivesize;
+ case LIBMPQ_MPQ_HASHTABLE_SIZE:
+ return mpq_a->header->hashtablesize;
+ case LIBMPQ_MPQ_BLOCKTABLE_SIZE:
+ return mpq_a->header->blocktablesize;
+ case LIBMPQ_MPQ_BLOCKSIZE:
+ return mpq_a->blocksize;
+ case LIBMPQ_MPQ_NUMFILES:
+ for (mpq_b = mpq_a->blocktable; mpq_b < mpq_b_end; mpq_b++) {
+ filecount++;
+ }
+ return filecount;
+ case LIBMPQ_MPQ_COMPRESSED_SIZE:
+ for (mpq_b = mpq_a->blocktable; mpq_b < mpq_b_end; mpq_b++) {
+ csize += mpq_b->csize;
+ }
+ return csize;
+ case LIBMPQ_MPQ_UNCOMPRESSED_SIZE:
+ for (mpq_b = mpq_a->blocktable; mpq_b < mpq_b_end; mpq_b++) {
+ fsize += mpq_b->fsize;
+ }
+ return fsize;
+ default:
+ return LIBMPQ_TOOLS_SUCCESS;
+ }
+}
+
+/*
+ * This function returns some useful file information.
+ */
+int libmpq_file_info(mpq_archive *mpq_a, unsigned int infotype, const int number) {
+ int blockindex = number; //-1;
+ int i = 0;
+ mpq_block *mpq_b = NULL;
+ mpq_hash *mpq_h = NULL;
+
+ /* check if given number is not out of range */
+ if (number < 1 || number > mpq_a->header->blocktablesize) {
+ return LIBMPQ_EINV_RANGE;
+ }
+
+ /* search for correct hashtable */
+ /*for (i = 0; i < mpq_a->header->hashtablesize; i++) {
+ if ((number - 1) == (mpq_a->hashtable[i]).blockindex) {
+ blockindex = (mpq_a->hashtable[i]).blockindex;
+ mpq_h = &(mpq_a->hashtable[i]);
+ break;
+ }
+ }*/
+
+ /* check if file was found */
+ /*if (blockindex == -1 || blockindex > mpq_a->header->blocktablesize) {
+ return LIBMPQ_EFILE_NOT_FOUND;
+ }*/
+
+ /* check if sizes are correct */
+ mpq_b = mpq_a->blocktable + blockindex;
+ if (mpq_b->filepos > (mpq_a->header->archivesize + mpq_a->mpqpos) || mpq_b->csize > mpq_a->header->archivesize) {
+ return LIBMPQ_EFILE_CORRUPT;
+ }
+
+ /* check if file exists */
+ if ((mpq_b->flags & LIBMPQ_FILE_EXISTS) == 0) {
+ return LIBMPQ_EFILE_NOT_FOUND;
+ }
+
+ switch (infotype) {
+ case LIBMPQ_FILE_COMPRESSED_SIZE:
+ return mpq_b->csize;
+ case LIBMPQ_FILE_UNCOMPRESSED_SIZE:
+ return mpq_b->fsize;
+ case LIBMPQ_FILE_COMPRESSION_TYPE:
+ if (mpq_b->flags & LIBMPQ_FILE_COMPRESS_PKWARE) {
+ return LIBMPQ_FILE_COMPRESS_PKWARE;
+ }
+ if (mpq_b->flags & LIBMPQ_FILE_COMPRESS_MULTI) {
+ return LIBMPQ_FILE_COMPRESS_MULTI;
+ }
+ default:
+ return LIBMPQ_TOOLS_SUCCESS;
+ }
+}
+
+/*
+ * This function searches the listfile for the filename.
+ * On success it returns the filename, otherwiese a name
+ * like file000001.xxx and if number is out of range it
+ * returns NULL.
+ */
+char *libmpq_file_name(mpq_archive *mpq_a, const int number) {
+ static char tempfile[PATH_MAX];
+
+ /* check if we are in the range of available files. */
+ if (number > libmpq_archive_info(mpq_a, LIBMPQ_MPQ_NUMFILES) || number < 1) {
+ return NULL;
+ }
+
+ /* this is safe because we built a fallback filelist, if something was wrong. */
+ sprintf(tempfile, (char *)mpq_a->mpq_l->mpq_files[number - 1], number);
+
+ return tempfile;
+}
+
+/*
+ * This function returns the number to the given
+ * filename.
+ */
+int libmpq_file_number(mpq_archive *mpq_a, const char *name) {
+ int i;
+ char tempfile[PATH_MAX];
+
+ for (i = 0; mpq_a->mpq_l->mpq_files[i]; i++) {
+ sprintf(tempfile, (char *)mpq_a->mpq_l->mpq_files[i], i + 1);
+ if (strncmp(tempfile, name, strlen(name)) == 0) {
+
+ /* if file found return the number */
+ return i + 1;
+ }
+ }
+
+ /* if no matching entry found return LIBMPQ_EFILE_NOT_FOUND */
+ return LIBMPQ_EFILE_NOT_FOUND;
+}
+
+/*
+ * This function verifies if a given file (by number
+ * or name) is in the opened mpq archive. On success
+ * it returns 0, otherwise LIBMPQ_EFILE_NOT_FOUND.
+ */
+int libmpq_file_check(mpq_archive *mpq_a, void *file, int type) {
+ int found = 0;
+ int i;
+ char tempfile[PATH_MAX];
+
+ switch (type) {
+ case LIBMPQ_FILE_TYPE_INT:
+
+ /* check if we are in the range of available files. */
+ if (*(int *)file > libmpq_archive_info(mpq_a, LIBMPQ_MPQ_NUMFILES) || *(int *)file < 1) {
+ return LIBMPQ_EFILE_NOT_FOUND;
+ } else {
+ return LIBMPQ_TOOLS_SUCCESS;
+ }
+ case LIBMPQ_FILE_TYPE_CHAR:
+ for (i = 0; mpq_a->mpq_l->mpq_files[i]; i++) {
+ sprintf(tempfile, (char *)mpq_a->mpq_l->mpq_files[i], i);
+ if (strncmp(tempfile, (char *)file, strlen((char *)file)) == 0) {
+
+ /* if file found break */
+ found = 1;
+ break;
+ }
+ }
+
+ /* if a file was found return 0 */
+ if (found == 1) {
+ return LIBMPQ_TOOLS_SUCCESS;
+ } else {
+ return LIBMPQ_EFILE_NOT_FOUND;
+ }
+ default:
+ return LIBMPQ_TOOLS_SUCCESS;
+ }
+}
+
+/*
+ * This function extracts a file from a MPQ archive
+ * by the given number.
+ */
+int libmpq_file_extract(mpq_archive *mpq_a, const int number, const char *filename) {
+ int blockindex = number; //-1;
+ int fd = 0;
+ int i = 0;
+ char buffer[0x1000];
+ //char tempfile[PATH_MAX];
+ unsigned int transferred = 1;
+ mpq_file *mpq_f = NULL;
+ mpq_block *mpq_b = NULL;
+ mpq_hash *mpq_h = NULL;
+
+/* if (number < 1 || number > mpq_a->header->blocktablesize) {
+ return LIBMPQ_EINV_RANGE;
+ }*/
+/*
+ sprintf(tempfile, libmpq_file_name(mpq_a, number));
+*/
+ /* check if mpq_f->filename could be written here. */
+ fd = _open(filename, O_RDWR|O_CREAT|O_TRUNC, 0644);
+ if (fd == LIBMPQ_EFILE) {
+ return LIBMPQ_EFILE;
+ }
+
+ /* search for correct hashtable */
+ /*for (i = 0; i < mpq_a->header->hashtablesize; i++) {
+ if ((number - 1) == (mpq_a->hashtable[i]).blockindex) {
+ blockindex = (mpq_a->hashtable[i]).blockindex;
+ mpq_h = &(mpq_a->hashtable[i]);
+ break;
+ }
+ }*/
+
+ /* check if file was found */
+ if (blockindex == -1 || blockindex > mpq_a->header->blocktablesize) {
+ return LIBMPQ_EFILE_NOT_FOUND;
+ }
+
+ /* check if sizes are correct */
+ mpq_b = mpq_a->blocktable + blockindex;
+ if (mpq_b->filepos > (mpq_a->header->archivesize + mpq_a->mpqpos) || mpq_b->csize > mpq_a->header->archivesize) {
+ return LIBMPQ_EFILE_CORRUPT;
+ }
+
+ /* check if file exists */
+ if ((mpq_b->flags & LIBMPQ_FILE_EXISTS) == 0) {
+ return LIBMPQ_EFILE_NOT_FOUND;
+ }
+
+ /* allocate memory for file structure */
+ mpq_f = (mpq_file *)malloc(sizeof(mpq_file));
+ if (!mpq_f) {
+ return LIBMPQ_EALLOCMEM;
+ }
+
+ /* initialize file structure */
+ memset(mpq_f, 0, sizeof(mpq_file));
+ mpq_f->fd = fd;
+ mpq_f->mpq_b = mpq_b;
+ mpq_f->nblocks = (mpq_f->mpq_b->fsize + mpq_a->blocksize - 1) / mpq_a->blocksize;
+ mpq_f->mpq_h = mpq_h;
+ mpq_f->accessed = FALSE;
+ mpq_f->blockposloaded = FALSE;
+ sprintf((char *)mpq_f->filename, filename);
+
+ /* allocate buffers for decompression. */
+ if (mpq_f->mpq_b->flags & LIBMPQ_FILE_COMPRESSED) {
+
+ /*
+ * Allocate buffer for block positions. At the begin of file are stored
+ * unsigned ints holding positions of each block relative from begin of
+ * file in the archive.
+ */
+ if ((mpq_f->blockpos = (unsigned int *)malloc(sizeof(int) * mpq_f->nblocks + 1)) == NULL) {
+ return LIBMPQ_EALLOCMEM;
+ }
+ }
+
+ while (transferred > 0) {
+ transferred = libmpq_file_read_file(mpq_a, mpq_f, mpq_f->filepos, buffer, sizeof(buffer));
+ if (transferred == 0) {
+ break;
+ } else {
+ mpq_f->accessed = TRUE;
+ mpq_f->filepos += transferred;
+ }
+
+ transferred = _write(mpq_f->fd, buffer, transferred);
+ if (transferred == 0) {
+ break;
+ }
+ }
+
+ _close(fd);
+
+ /* freeing the file structure */
+ free(mpq_f);
+ return LIBMPQ_TOOLS_SUCCESS;
+}
+
+/*
+ * This function tries to get the filenames for the hashes. It uses
+ * an internal listfile database and gets the correct listfile from
+ * some specific archive informations.
+ */
+
+int libmpq_listfile_open(mpq_archive *mpq_a, char file[PATH_MAX]) {
+ FILE *fp;
+ //char **filelist;
+ int i = 0;
+ //int fl_count;
+ //int fl_size;
+ int fl_count_fb;
+ int fl_size_fb;
+ int result = LIBMPQ_TOOLS_SUCCESS;
+ struct stat statbuf;
+
+ /* get file status */
+ if (stat(file, &statbuf) < 0) {
+ result = LIBMPQ_CONF_EFILE_NOT_FOUND;
+ }
+
+ /* check if file is a filename or directory */
+ /*if (S_ISDIR(statbuf.st_mode)) {
+
+ // allocate memory for the file list
+ filelist = (char **)malloc(LIBMPQ_CONF_FL_INCREMENT * sizeof(char *));
+ fl_count = 0;
+ fl_size = LIBMPQ_CONF_FL_INCREMENT;
+
+ // check if it is a valid listfile
+ if (libmpq_detect_listfile_rec(file, &filelist, &fl_count, &fl_size)) {
+ filelist == NULL;
+ }
+
+ filelist[fl_count] = NULL;
+
+ // return if no listfile was found
+ if (filelist == NULL) {
+ result = LIBMPQ_CONF_EFILE_NOT_FOUND;
+ }
+
+ for (i = 0; filelist[i]; i++) {
+ if ((fp = fopen(filelist[i], "r")) != NULL ) {
+ result = libmpq_read_listfile(mpq_a, fp);
+ fclose(fp);
+ }
+ }
+
+ // freeing the listfile struct
+ libmpq_free_listfile(filelist);
+ }*/
+
+ /* if file is a regular file use it */
+ //if (S_ISREG(statbuf.st_mode)) {
+
+ /* if specific listfile was forced. */
+ if ((fp = fopen(file, "r")) != NULL ) {
+ result = libmpq_read_listfile(mpq_a, fp);
+ fclose(fp);
+ } else {
+ result = LIBMPQ_CONF_EFILE_OPEN;
+ }
+ //}
+
+ /* if error occured we need to create a fallback filelist. */
+ if (mpq_a->mpq_l->mpq_files == NULL) {
+
+ /* allocate memory for the file list */
+ mpq_a->mpq_l->mpq_files = (unsigned char **)malloc(LIBMPQ_CONF_FL_INCREMENT * sizeof(char *));
+ fl_count_fb = 0;
+ fl_size_fb = LIBMPQ_CONF_FL_INCREMENT;
+
+ for (i = 0; i < libmpq_archive_info(mpq_a, LIBMPQ_MPQ_NUMFILES); i++) {
+
+ /* set the next filelist entry to a copy of the file */
+ mpq_a->mpq_l->mpq_files[fl_count_fb++] = (unsigned char *)_strdup("file%06lu.xxx");
+
+ /* increase the array size */
+ if (fl_count_fb == fl_size_fb) {
+ mpq_a->mpq_l->mpq_files = (unsigned char **)realloc(mpq_a->mpq_l->mpq_files, (fl_size_fb + LIBMPQ_CONF_FL_INCREMENT) * sizeof(char *));
+ fl_size_fb += LIBMPQ_CONF_FL_INCREMENT;
+ }
+ }
+ mpq_a->mpq_l->mpq_files[fl_count_fb] = NULL;
+
+ /* if no error occurs and no listfile was assigned, we think there was no matching listfile. */
+ if (result == 0) {
+ result = LIBMPQ_CONF_EFILE_NOT_FOUND;
+ }
+ }
+
+ return result;
+}
+
+/*
+ * This function frees the allocated memory for the listfile.
+ */
+int libmpq_listfile_close(mpq_archive *mpq_a) {
+ int i = 0;
+
+ /* safety check if we really have a filelist. */
+ if (mpq_a->mpq_l->mpq_files != NULL) {
+ /* freeing the filelist */
+ while (mpq_a->mpq_l->mpq_files[i]) {
+ free(mpq_a->mpq_l->mpq_files[i++]);
+ }
+ free(mpq_a->mpq_l->mpq_files);
+ }
+ return 0;
+}
+
+int libmpq_file_getdata(mpq_archive *mpq_a, mpq_hash mpq_h, const int number, unsigned char *dest) {
+ int blockindex = number; //-1;
+ int i = 0;
+ mpq_file *mpq_f = NULL;
+ mpq_block *mpq_b = NULL;
+ int success = 0;
+
+ /*if (number < 1 || number > mpq_a->header->blocktablesize) {
+ return LIBMPQ_EINV_RANGE;
+ }*/
+
+ /* search for correct hashtable */
+ /*for (i = 0; i < mpq_a->header->hashtablesize; i++) {
+ if ((number - 1) == (mpq_a->hashtable[i]).blockindex) {
+ blockindex = (mpq_a->hashtable[i]).blockindex;
+ mpq_h = &(mpq_a->hashtable[i]);
+ break;
+ }
+ }*/
+
+ /* check if file was found */
+ if (blockindex == -1 || blockindex > mpq_a->header->blocktablesize) {
+ return LIBMPQ_EFILE_NOT_FOUND;
+ }
+
+ /* check if sizes are correct */
+ mpq_b = mpq_a->blocktable + blockindex;
+ if (mpq_b->filepos > (mpq_a->header->archivesize + mpq_a->mpqpos) || mpq_b->csize > mpq_a->header->archivesize) {
+ return LIBMPQ_EFILE_CORRUPT;
+ }
+
+ /* check if file exists */
+ if ((mpq_b->flags & LIBMPQ_FILE_EXISTS) == 0) {
+ return LIBMPQ_EFILE_NOT_FOUND;
+ }
+
+ /* allocate memory for file structure */
+ mpq_f = (mpq_file*)malloc(sizeof(mpq_file));
+ if (!mpq_f) {
+ return LIBMPQ_EALLOCMEM;
+ }
+
+ /* initialize file structure */
+ memset(mpq_f, 0, sizeof(mpq_file));
+ mpq_f->mpq_b = mpq_b;
+ mpq_f->nblocks = (mpq_f->mpq_b->fsize + mpq_a->blocksize - 1) / mpq_a->blocksize;
+ mpq_f->mpq_h = &mpq_h;
+ mpq_f->accessed = FALSE;
+ mpq_f->blockposloaded = FALSE;
+
+ /* allocate buffers for decompression. */
+ if (mpq_f->mpq_b->flags & LIBMPQ_FILE_COMPRESSED) {
+
+ /*
+ * Allocate buffer for block positions. At the begin of file are stored
+ * unsigned ints holding positions of each block relative from begin of
+ * file in the archive.
+ */
+ if ((mpq_f->blockpos = (unsigned int*)malloc(sizeof(int) * (mpq_f->nblocks + 1))) == NULL) {
+ return LIBMPQ_EALLOCMEM;
+ }
+ }
+
+ if(libmpq_file_read_file(mpq_a, mpq_f, 0, (char*)dest, mpq_b->fsize) == mpq_b->fsize)
+ success = 1;
+
+ if (mpq_f->mpq_b->flags & LIBMPQ_FILE_COMPRESSED) {
+ // Free buffer for block positions
+
+ free(mpq_f->blockpos);
+ }
+ /* freeing the file structure */
+ free(mpq_f);
+ return success?LIBMPQ_TOOLS_SUCCESS:LIBMPQ_EFILE_CORRUPT;
+}
diff --git a/contrib/extractor/libmpq/mpq.h b/contrib/extractor/libmpq/mpq.h
new file mode 100644
index 00000000000..0a136f95f30
--- /dev/null
+++ b/contrib/extractor/libmpq/mpq.h
@@ -0,0 +1,225 @@
+/*
+ * mpq.h -- some default types and defines.
+ *
+ * Copyright (C) 2003 Maik Broemme <mbroemme@plusserver.de>
+ *
+ * This source was adepted from the C++ version of StormLib.h and
+ * StormPort.h included in stormlib. The C++ version belongs to
+ * the following authors,
+ *
+ * Ladislav Zezula <ladik.zezula.net>
+ * Marko Friedemann <marko.friedemann@bmx-chemnitz.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Id: mpq.h,v 1.8 2004/02/12 00:45:50 mbroemme Exp $
+ */
+
+#ifndef _MPQ_H
+#define _MPQ_H
+
+#include <limits.h>
+
+#ifndef PATH_MAX
+ #define PATH_MAX 260
+#endif
+
+
+#define LIBMPQ_MAJOR_VERSION 0 /* Major version number... maybe sometimes we reach version 1 :) */
+#define LIBMPQ_MINOR_VERSION 3 /* Minor version number - increased only for small changes */
+#define LIBMPQ_PATCH_VERSION 0 /* Patchlevel - changed on bugfixes etc... */
+
+#define LIBMPQ_TOOLS_SUCCESS 0 /* return value for all functions which success */
+#define LIBMPQ_TOOLS_BUFSIZE 0x500 /* buffer size for the decryption engine */
+
+#define LIBMPQ_EFILE -1 /* error on file operation */
+#define LIBMPQ_EFILE_FORMAT -2 /* bad file format */
+#define LIBMPQ_EFILE_CORRUPT -3 /* file corrupt */
+#define LIBMPQ_EFILE_NOT_FOUND -4 /* file in archive not found */
+#define LIBMPQ_EFILE_READ -5 /* Read error in archive */
+#define LIBMPQ_EALLOCMEM -6 /* maybe not enough memory? :) */
+#define LIBMPQ_EFREEMEM -7 /* can not free memory */
+#define LIBMPQ_EINV_RANGE -8 /* Given filenumber is out of range */
+#define LIBMPQ_EHASHTABLE -9 /* error in reading hashtable */
+#define LIBMPQ_EBLOCKTABLE -10 /* error in reading blocktable */
+
+#define LIBMPQ_ID_MPQ 0x1A51504D /* MPQ archive header ID ('MPQ\x1A') */
+#define LIBMPQ_HEADER_W3M 0x6D9E4B86 /* special value used by W3M Map Protector */
+#define LIBMPQ_FLAG_PROTECTED 0x00000002 /* Set on protected MPQs (like W3M maps) */
+#define LIBMPQ_HASH_ENTRY_DELETED 0xFFFFFFFE /* Block index for deleted hash entry */
+
+#define LIBMPQ_FILE_COMPRESS_PKWARE 0x00000100 /* Compression made by PKWARE Data Compression Library */
+#define LIBMPQ_FILE_COMPRESS_MULTI 0x00000200 /* Multiple compressions */
+#define LIBMPQ_FILE_COMPRESSED 0x0000FF00 /* File is compressed */
+#define LIBMPQ_FILE_EXISTS 0x80000000 /* Set if file exists, reset when the file was deleted */
+#define LIBMPQ_FILE_ENCRYPTED 0x00010000 /* Indicates whether file is encrypted */
+#define LIBMPQ_FILE_HAS_METADATA 0x04000000
+
+#define LIBMPQ_FILE_COMPRESSED_SIZE 1 /* MPQ compressed filesize of given file */
+#define LIBMPQ_FILE_UNCOMPRESSED_SIZE 2 /* MPQ uncompressed filesize of given file */
+#define LIBMPQ_FILE_COMPRESSION_TYPE 3 /* MPQ compression type of given file */
+#define LIBMPQ_FILE_TYPE_INT 4 /* file is given by number */
+#define LIBMPQ_FILE_TYPE_CHAR 5 /* file is given by name */
+
+#define LIBMPQ_MPQ_ARCHIVE_SIZE 1 /* MPQ archive size */
+#define LIBMPQ_MPQ_HASHTABLE_SIZE 2 /* MPQ archive hashtable size */
+#define LIBMPQ_MPQ_BLOCKTABLE_SIZE 3 /* MPQ archive blocktable size */
+#define LIBMPQ_MPQ_BLOCKSIZE 4 /* MPQ archive blocksize */
+#define LIBMPQ_MPQ_NUMFILES 5 /* Number of files in the MPQ archive */
+#define LIBMPQ_MPQ_COMPRESSED_SIZE 6 /* Compressed archive size */
+#define LIBMPQ_MPQ_UNCOMPRESSED_SIZE 7 /* Uncompressed archive size */
+
+#define LIBMPQ_HUFF_DECOMPRESS 0 /* Defines that we want to decompress using huffman trees. */
+
+#define LIBMPQ_CONF_EFILE_OPEN -1 /* error if a specific listfile was forced and could not be opened. */
+#define LIBMPQ_CONF_EFILE_CORRUPT -2 /* listfile seems to be corrupt */
+#define LIBMPQ_CONF_EFILE_LIST_CORRUPT -3 /* listfile seems correct, but filelist is broken */
+#define LIBMPQ_CONF_EFILE_NOT_FOUND -4 /* error if no matching listfile found */
+#define LIBMPQ_CONF_EFILE_VERSION -5 /* libmpq version does not match required listfile version */
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+/*
+#ifndef min
+#define min(a, b) ((a < b) ? a : b)
+#endif
+*/
+
+typedef unsigned int mpq_buffer[LIBMPQ_TOOLS_BUFSIZE];
+typedef int (*DECOMPRESS)(char *, int *, char *, int);
+typedef struct {
+ unsigned long mask; /* Decompression bit */
+ DECOMPRESS decompress; /* Decompression function */
+} decompress_table;
+
+/* MPQ file header */
+typedef struct {
+ unsigned int id; /* The 0x1A51504D ('MPQ\x1A') signature */
+ unsigned int offset; /* Offset of the first file (Relative to MPQ start) */
+ unsigned int archivesize; /* Size of MPQ archive */
+ unsigned short offsetsc; /* 0000 for SC and BW */
+ unsigned short blocksize; /* Size of file block is (0x200 << blockSize) */
+ unsigned int hashtablepos; /* File position of hashTable */
+ unsigned int blocktablepos; /* File position of blockTable. Each entry has 16 bytes */
+ unsigned int hashtablesize; /* Number of entries in hash table */
+ unsigned int blocktablesize; /* Number of entries in the block table */
+} mpq_header;
+//} __attribute__ ((packed)) mpq_header;
+
+
+/* Hash entry. All files in the archive are searched by their hashes. */
+typedef struct {
+ unsigned int name1; /* The first two unsigned ints */
+ unsigned int name2; /* are the encrypted file name */
+ unsigned int locale; /* Locale information. */
+ unsigned int blockindex; /* Index to file description block */
+} mpq_hash;
+
+/* File description block contains informations about the file */
+typedef struct {
+ unsigned int filepos; /* Block file starting position in the archive */
+ unsigned int csize; /* Compressed file size */
+ unsigned int fsize; /* Uncompressed file size */
+ unsigned int flags; /* Flags */
+} mpq_block;
+
+/* File handle structure used since Diablo 1.00 (0x38 bytes) */
+typedef struct {
+ unsigned char filename[PATH_MAX]; /* filename of the actual file in the archive */
+ int fd; /* File handle */
+ unsigned int seed; /* Seed used for file decrypt */
+ unsigned int filepos; /* Current file position */
+ unsigned int offset;
+ unsigned int nblocks; /* Number of blocks in the file (incl. the last noncomplete one) */
+ unsigned int *blockpos; /* Position of each file block (only for compressed files) */
+ int blockposloaded; /* TRUE if block positions loaded */
+ unsigned int offset2; /* (Number of bytes somewhere ?) */
+ mpq_hash *mpq_h; /* Hash table entry */
+ mpq_block *mpq_b; /* File block pointer */
+
+ /* Non-Storm.dll members */
+
+ unsigned int accessed; /* Was something from the file already read? */
+} mpq_file;
+
+/* List handle structure */
+typedef struct {
+ unsigned char mpq_version[10]; /* libmpq version required by the listfile */
+ unsigned char mpq_name[PATH_MAX]; /* mpq archive name without full path */
+ unsigned char mpq_type[20]; /* mpq archive type */
+ unsigned char mpq_game[40]; /* blizzard title the file matches */
+ unsigned char mpq_game_version[10]; /* game version */
+ unsigned char **mpq_files; /* filelist */
+} mpq_list;
+
+/* Archive handle structure used since Diablo 1.00 */
+typedef struct {
+ unsigned char filename[PATH_MAX]; /* Opened archive file name */
+ int fd; /* File handle */
+ unsigned int blockpos; /* Position of loaded block in the file */
+ unsigned int blocksize; /* Size of file block */
+ unsigned char *blockbuf; /* Buffer (cache) for file block */
+ unsigned int bufpos; /* Position in block buffer */
+ unsigned int mpqpos; /* MPQ archive position in the file */
+ unsigned int filepos; /* Current file pointer */
+ unsigned int openfiles; /* Number of open files + 1 */
+ mpq_buffer buf; /* MPQ buffer */
+ mpq_header *header; /* MPQ file header */
+ mpq_hash *hashtable; /* Hash table */
+ mpq_block *blocktable; /* Block table */
+
+ /* Non-Storm.dll members */
+
+ mpq_list *mpq_l; /* Handle to file list from database */
+
+ unsigned int flags; /* See LIBMPQ_TOOLS_FLAG_XXXXX */
+ unsigned int maxblockindex; /* The highest block table entry */
+} mpq_archive;
+
+extern char *libmpq_version();
+extern int libmpq_archive_open(mpq_archive *mpq_a, unsigned char *mpq_filename);
+extern int libmpq_archive_close(mpq_archive *mpq_a);
+extern int libmpq_archive_info(mpq_archive *mpq_a, unsigned int infotype);
+//extern int libmpq_file_extract(mpq_archive *mpq_a, const int number);
+extern int libmpq_file_info(mpq_archive *mpq_a, unsigned int infotype, const int number);
+extern char *libmpq_file_name(mpq_archive *mpq_a, const int number);
+extern int libmpq_file_number(mpq_archive *mpq_a, const char *name);
+extern int libmpq_file_check(mpq_archive *mpq_a, void *file, int type);
+extern int libmpq_listfile_open(mpq_archive *mpq_a, char file[PATH_MAX]);
+extern int libmpq_listfile_close(mpq_archive *mpq_a);
+
+extern int libmpq_pkzip_decompress(char *out_buf, int *out_length, char *in_buf, int in_length);
+extern int libmpq_zlib_decompress(char *out_buf, int *out_length, char *in_buf, int in_length);
+extern int libmpq_huff_decompress(char *out_buf, int *out_length, char *in_buf, int in_length);
+extern int libmpq_wave_decompress_stereo(char *out_buf, int *out_length, char *in_buf, int in_length);
+extern int libmpq_wave_decompress_mono(char *out_buf, int *out_length, char *in_buf, int in_length);
+extern int libmpq_multi_decompress(char *out_buf, int *pout_length, char *in_buf, int in_length);
+
+static decompress_table dcmp_table[] = {
+ {0x08, libmpq_pkzip_decompress}, /* Decompression with Pkware Data Compression Library */
+ {0x02, libmpq_zlib_decompress}, /* Decompression with the "zlib" library */
+ {0x01, libmpq_huff_decompress}, /* Huffmann decompression */
+ {0x80, libmpq_wave_decompress_stereo}, /* WAVE decompression for stereo waves */
+ {0x40, libmpq_wave_decompress_mono} /* WAVE decompression for mono waves */
+};
+
+int libmpq_file_extract(mpq_archive *mpq_a, const int number, const char *filename);
+int libmpq_file_getdata(mpq_archive *mpq_a, mpq_hash mpq_h, const int number, unsigned char *dest);
+#endif /* _MPQ_H */
diff --git a/contrib/extractor/libmpq/parser.cpp b/contrib/extractor/libmpq/parser.cpp
new file mode 100644
index 00000000000..b7a70400f5a
--- /dev/null
+++ b/contrib/extractor/libmpq/parser.cpp
@@ -0,0 +1,294 @@
+/*
+ * parser.c -- functions used to parse list or config file.
+ *
+ * Copyright (C) 2003 Maik Broemme <mbroemme@plusserver.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Id: parser.c,v 1.5 2004/02/12 00:47:53 mbroemme Exp $
+ */
+#define _CRT_SECURE_NO_DEPRECATE
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "mpq.h"
+#include "common.h"
+#include <ctype.h>
+
+/*
+ * This function deletes the specified characters, but leaves
+ * escape sequences unaffected. This means that " would be
+ * deleted but \" would not.
+ */
+char *libmpq_conf_delete_char(char *buf, char *chars) {
+ static char *temp;
+ char ch;
+
+ temp = buf;
+
+ /* strip out special chars like " */
+ while (temp = strpbrk(temp, chars)) {
+ ch = temp[0];
+ memmove(&temp[0], &temp[1], strlen(temp));
+ if (ch == '\\') {
+ temp++;
+ }
+ }
+
+ return buf;
+}
+
+/*
+ * This function parses a line for the value to the given option. It
+ * return 1 on success and the byte array or 0 and null.
+ */
+int libmpq_conf_parse_line(char *line, char *search_value, char *return_value, int size) {
+ int level = 0;
+ int found = 0;
+ int i = 0;
+ int pos = 0;
+
+ /* search value */
+ while (*(++line)) {
+
+ /* check for spaces */
+ if (!isspace(*line) && level == 1) {
+
+ /* we found our value so break */
+ found = 1;
+ break;
+ }
+
+ /* check for '=' so the value follows as next parameter */
+ if (*line == '=' && level == 0) {
+ level = 1;
+ }
+ }
+
+ /* now search for comment in this line */
+ for (i = 0; i < strlen(line); i++) {
+ if (line[i] == '#') {
+ pos = i - 1;
+ break;
+ }
+ }
+
+ /* now set end of byte array behind value, but only if comment was found */
+ if (pos != 0) {
+ for (i = pos; i >= 0; i--) {
+ if (line[i] != ' ' && line[i] != '\t') {
+ line[i + 1] = '\0';
+ break;
+ }
+ }
+ }
+
+ /* now check if line has trailing spaces */
+ for (i = strlen(line); i >= 0; i--) {
+ if (line[i] != ' ' && line[i] != '\t') {
+ line[i + 1] = '\0';
+ break;
+ }
+ }
+
+ /* now check if value is quoted with "" and if there is a char behind. */
+ for (i = strlen(line); i >= 0; i--) {
+ if (line[i] == '"') {
+ line[i + 1] = '\0';
+ break;
+ }
+ }
+
+ /* return the values */
+ strncpy(return_value, line, size);
+ return found;
+}
+
+/*
+ * This function returns the value for a given option in the
+ * listdb or config file. On success it returns 1, otherwise 0.
+ */
+int libmpq_conf_get_value(FILE *fp, char *search_value, void *return_value, int type, int size) {
+ char buf[LIBMPQ_CONF_BUFSIZE];
+ int found = 0;
+ int result = LIBMPQ_TOOLS_SUCCESS;
+
+ while (fgets(buf, LIBMPQ_CONF_BUFSIZE, fp) != NULL) {
+ char *line;
+
+ buf[strlen(buf) - 1] = '\0';
+
+ /* skip whitespace */
+ for (line = buf; isspace(*line); line++) {
+ continue;
+ }
+
+ /* skip empty line */
+ if (line[0] == '\0') {
+ continue;
+ }
+
+ /* skip comments */
+ if (line[0] == '#') {
+ continue;
+ }
+
+ /* process the line */
+ //if (!strncasecmp(line, search_value, strlen(search_value))) {
+ if (!strcmp(line, search_value)) {
+ found = libmpq_conf_parse_line(line, search_value, line, LIBMPQ_CONF_BUFSIZE);
+ if (found == 1) {
+ libmpq_conf_delete_char(line, "\"\\");
+
+ switch (type) {
+ case LIBMPQ_CONF_TYPE_INT:
+
+ /* if it is no valid number it is safe to return 0 */
+ *(int *)return_value = atoi(line);
+ break;
+ default:
+ strncpy((char *)return_value, line, size);
+ break;
+ }
+
+ /* value found, so rewind stream */
+ break;
+ }
+ }
+ }
+
+ /* if value was not found */
+ if (found == 0) {
+ switch (type) {
+ case LIBMPQ_CONF_TYPE_INT:
+ *(int *)return_value = 0;
+ result = LIBMPQ_CONF_EVALUE_NOT_FOUND;
+ break;
+ default:
+ strncpy((char *)return_value, "", size);
+ result = LIBMPQ_CONF_EVALUE_NOT_FOUND;
+ break;
+ }
+ }
+ fseek(fp, 0L, SEEK_SET);
+
+ return result;
+}
+
+/*
+ * This function returns a pointer to a byte array, with all values
+ * found in the config file. As second value it returns th number of
+ * entries in the byte array. On success it returns 1, otherwise 0.
+ */
+int libmpq_conf_get_array(FILE *fp, char *search_value, char ***filelist, int *entries) {
+ char buf[LIBMPQ_CONF_BUFSIZE];
+ char temp[LIBMPQ_CONF_BUFSIZE];
+ int level = 0;
+ int array_start = 0;
+ int array_end = 0;
+ int fl_count;
+ int fl_size;
+ int found = 0;
+ int i = 0;
+
+ *entries = 0;
+
+ /* allocate memory for the file list */
+ (*filelist) = (char **)malloc(LIBMPQ_CONF_FL_INCREMENT * sizeof(char *));
+ fl_count = 0;
+ fl_size = LIBMPQ_CONF_FL_INCREMENT;
+
+ while (fgets(buf, LIBMPQ_CONF_BUFSIZE, fp) != NULL) {
+ char *line;
+
+ buf[strlen(buf) - 1] = '\0';
+
+ /* skip whitespace */
+ for (line = buf; isspace(*line); line++) {
+ continue;
+ }
+
+ /* skip empty line */
+ if (line[0] == '\0') {
+ continue;
+ }
+
+ /* skip comments */
+ if (line[0] == '#') {
+ continue;
+ }
+
+ /* check for array end ) */
+ if (*line == ')') {
+ array_end = 1;
+ break;
+ }
+
+ /* process entries between () */
+ if (array_start == 1 && array_end == 0) {
+
+ /* add dummy option to use with libmpq_conf_parse_line() */
+ strncpy(temp, "MPQ_BUFFER = ", LIBMPQ_CONF_BUFSIZE);
+ strncat(temp, line, LIBMPQ_CONF_BUFSIZE);
+ found = libmpq_conf_parse_line(temp, "MPQ_BUFFER", temp, LIBMPQ_CONF_BUFSIZE);
+
+ if (found == 1) {
+ libmpq_conf_delete_char(temp, "\"\\");
+
+ /* set the next filelist entry to a copy of the file */
+ (*filelist)[fl_count++] = _strdup(temp);
+
+ /* increase the array size */
+ if (fl_count == fl_size) {
+ (*filelist) = (char **)realloc((*filelist), (fl_size + LIBMPQ_CONF_FL_INCREMENT) * sizeof(char *));
+ fl_size += LIBMPQ_CONF_FL_INCREMENT;
+ }
+
+ /* increase number of entries */
+ (*entries)++;
+ }
+ }
+
+ /* process the line and search array start */
+ //if (!strncasecmp(line, search_value, strlen(search_value))) {
+ if (!strcmp(line, search_value)) {
+
+ /* search value */
+ while (*(++line)) {
+
+ /* check for array start ( */
+ if (*line == '(' && level == 1) {
+
+ /* we found our value so break */
+ array_start = 1;
+ break;
+ }
+
+ /* check for '=' so the value follows as next parameter */
+ if (*line == '=' && level == 0) {
+ level = 1;
+ }
+ }
+ }
+ }
+
+ /* we got all files, so rewind stream */
+ fseek(fp, 0L, SEEK_SET);
+
+ (*filelist)[fl_count] = NULL;
+
+ return found;
+}
diff --git a/contrib/extractor/libmpq/wave.cpp b/contrib/extractor/libmpq/wave.cpp
new file mode 100644
index 00000000000..8edc1f7fa41
--- /dev/null
+++ b/contrib/extractor/libmpq/wave.cpp
@@ -0,0 +1,185 @@
+/*
+ * wave.c -- this file contains decompression methods used by Storm.dll
+ * to decompress wave files.
+ *
+ * Copyright (C) 2003 Maik Broemme <mbroemme@plusserver.de>
+ *
+ * This source was adepted from the C++ version of wave.cpp included
+ * in stormlib. The C++ version belongs to the following authors,
+ *
+ * Ladislav Zezula <ladik.zezula.net>
+ * Tom Amigo <tomamigo@apexmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "wave.h"
+
+/* Tables necessary dor decompression */
+static unsigned long wave_table_1503f120[] = {
+ 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000004, 0xFFFFFFFF, 0x00000002, 0xFFFFFFFF, 0x00000006,
+ 0xFFFFFFFF, 0x00000001, 0xFFFFFFFF, 0x00000005, 0xFFFFFFFF, 0x00000003, 0xFFFFFFFF, 0x00000007,
+ 0xFFFFFFFF, 0x00000001, 0xFFFFFFFF, 0x00000005, 0xFFFFFFFF, 0x00000003, 0xFFFFFFFF, 0x00000007,
+ 0xFFFFFFFF, 0x00000002, 0xFFFFFFFF, 0x00000004, 0xFFFFFFFF, 0x00000006, 0xFFFFFFFF, 0x00000008
+};
+
+static unsigned long wave_table_1503f1a0[] = {
+ 0x00000007, 0x00000008, 0x00000009, 0x0000000A, 0x0000000B, 0x0000000C, 0x0000000D, 0x0000000E,
+ 0x00000010, 0x00000011, 0x00000013, 0x00000015, 0x00000017, 0x00000019, 0x0000001C, 0x0000001F,
+ 0x00000022, 0x00000025, 0x00000029, 0x0000002D, 0x00000032, 0x00000037, 0x0000003C, 0x00000042,
+ 0x00000049, 0x00000050, 0x00000058, 0x00000061, 0x0000006B, 0x00000076, 0x00000082, 0x0000008F,
+ 0x0000009D, 0x000000AD, 0x000000BE, 0x000000D1, 0x000000E6, 0x000000FD, 0x00000117, 0x00000133,
+ 0x00000151, 0x00000173, 0x00000198, 0x000001C1, 0x000001EE, 0x00000220, 0x00000256, 0x00000292,
+ 0x000002D4, 0x0000031C, 0x0000036C, 0x000003C3, 0x00000424, 0x0000048E, 0x00000502, 0x00000583,
+ 0x00000610, 0x000006AB, 0x00000756, 0x00000812, 0x000008E0, 0x000009C3, 0x00000ABD, 0x00000BD0,
+ 0x00000CFF, 0x00000E4C, 0x00000FBA, 0x0000114C, 0x00001307, 0x000014EE, 0x00001706, 0x00001954,
+ 0x00001BDC, 0x00001EA5, 0x000021B6, 0x00002515, 0x000028CA, 0x00002CDF, 0x0000315B, 0x0000364B,
+ 0x00003BB9, 0x000041B2, 0x00004844, 0x00004F7E, 0x00005771, 0x0000602F, 0x000069CE, 0x00007462,
+ 0x00007FFF
+};
+
+/*
+ * Decompress a wave file, mono or stereo
+ *
+ * Offset: 1500F230
+ */
+int libmpq_wave_decompress(unsigned char *out_buf, int out_length, unsigned char *in_buf, int in_length, int channels) {
+ byte_and_short out;
+ byte_and_short in;
+ unsigned char *in_end = in_buf + in_length; /* End on input buffer */
+ unsigned long index;
+ long nr_array1[2];
+ long nr_array2[2];
+ int count = 0;
+
+ out.pb = out_buf;
+ in.pb = in_buf;
+ nr_array1[0] = 0x2C;
+ nr_array1[1] = 0x2C;
+ in.pw++;
+
+ /* 15007AD7 */
+ for (count = 0; count < channels; count++) {
+ long temp;
+ temp = *(short *)in.pw++;
+ nr_array2[count] = temp;
+ if (out_length < 2) {
+ return out.pb - out_buf;
+ }
+ *out.pw++ = (unsigned short)temp;
+ out_length -= 2;
+ }
+ index = channels - 1;
+ while (in.pb < in_end) {
+ unsigned char one_byte = *in.pb++;
+ if (channels == 2) {
+ index = (index == 0) ? 1 : 0;
+ }
+
+ /*
+ * Get one byte from input buffer
+ * 15007B25
+ */
+ if (one_byte & 0x80) {
+ /* 15007B32 */
+ switch(one_byte & 0x7F) {
+ case 0: /* 15007B8E */
+ if (nr_array1[index] != 0) {
+ nr_array1[index]--;
+ }
+ if (out_length < 2) {
+ break;
+ }
+ *out.pw++ = (unsigned short)nr_array2[index];
+ out_length -= 2;
+ continue;
+ case 1: /* 15007B72 */
+ nr_array1[index] += 8; /* EBX also */
+ if (nr_array1[index] > 0x58) {
+ nr_array1[index] = 0x58;
+ }
+ if (channels == 2) {
+ index = (index == 0) ? 1 : 0;
+ }
+ continue;
+ case 2:
+ continue;
+ default:
+ nr_array1[index] -= 8;
+ if (nr_array1[index] < 0) {
+ nr_array1[index] = 0;
+ }
+ if (channels != 2) {
+ continue;
+ }
+ index = (index == 0) ? 1 : 0;
+ continue;
+ }
+ } else {
+ unsigned long temp1 = wave_table_1503f1a0[nr_array1[index]]; /* EDI */
+ unsigned long temp2 = temp1 >> in_buf[1]; /* ESI */
+ long temp3 = nr_array2[index]; /* ECX */
+ if (one_byte & 0x01) { /* EBX = one_byte */
+ temp2 += (temp1 >> 0);
+ }
+ if (one_byte & 0x02) {
+ temp2 += (temp1 >> 1);
+ }
+ if (one_byte & 0x04) {
+ temp2 += (temp1 >> 2);
+ }
+ if (one_byte & 0x08) {
+ temp2 += (temp1 >> 3);
+ }
+ if (one_byte & 0x10) {
+ temp2 += (temp1 >> 4);
+ }
+ if (one_byte & 0x20) {
+ temp2 += (temp1 >> 5);
+ }
+ if(one_byte & 0x40) {
+ temp3 -= temp2;
+ if (temp3 <= (long)0xFFFF8000) {
+ temp3 = (long)0xFFFF8000;
+ }
+ } else {
+ temp3 += temp2;
+ if (temp3 >= 0x7FFF) {
+ temp3 = 0x7FFF;
+ }
+ }
+ nr_array2[index] = temp3;
+ if (out_length < 2) {
+ break;
+ }
+
+ temp2 = nr_array1[index];
+ one_byte &= 0x1F;
+ *out.pw++ = (unsigned short)temp3;
+ out_length -= 2;
+ temp2 += wave_table_1503f120[one_byte];
+ nr_array1[index] = temp2;
+
+ if (nr_array1[index] < 0) {
+ nr_array1[index] = 0;
+ } else {
+ if (nr_array1[index] > 0x58) {
+ nr_array1[index] = 0x58;
+ }
+ }
+ }
+ }
+ return (out.pb - out_buf);
+}
diff --git a/contrib/extractor/libmpq/wave.h b/contrib/extractor/libmpq/wave.h
new file mode 100644
index 00000000000..8920880a04f
--- /dev/null
+++ b/contrib/extractor/libmpq/wave.h
@@ -0,0 +1,37 @@
+/*
+ * wave.h -- header file for WAVe unplode functions used by mpq-tools.
+ *
+ * Copyright (C) 2003 Maik Broemme <mbroemme@plusserver.de>
+ *
+ * This source was adepted from the C++ version of wave.h included
+ * in stormlib. The C++ version belongs to the following authors,
+ *
+ * Ladislav Zezula <ladik.zezula.net>
+ * Tom Amigo <tomamigo@apexmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _WAVE_H
+#define _WAVE_H
+
+typedef union {
+ unsigned short *pw;
+ unsigned char *pb;
+} byte_and_short;
+
+int libmpq_wave_decompress(unsigned char *out_buf, int out_length, unsigned char *in_buf, int in_length, int channels);
+
+#endif /* _WAVE_H */
diff --git a/contrib/extractor/libmpq/zconf.h b/contrib/extractor/libmpq/zconf.h
new file mode 100644
index 00000000000..3cea897eda7
--- /dev/null
+++ b/contrib/extractor/libmpq/zconf.h
@@ -0,0 +1,323 @@
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995-2003 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#ifndef ZCONF_H
+#define ZCONF_H
+
+/*
+ * If you *really* need a unique prefix for all types and library functions,
+ * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
+ */
+#ifdef Z_PREFIX
+# define deflateInit_ z_deflateInit_
+# define deflate z_deflate
+# define deflateEnd z_deflateEnd
+# define inflateInit_ z_inflateInit_
+# define inflate z_inflate
+# define inflateEnd z_inflateEnd
+# define deflateInit2_ z_deflateInit2_
+# define deflateSetDictionary z_deflateSetDictionary
+# define deflateCopy z_deflateCopy
+# define deflateReset z_deflateReset
+# define deflatePrime z_deflatePrime
+# define deflateParams z_deflateParams
+# define deflateBound z_deflateBound
+# define inflateInit2_ z_inflateInit2_
+# define inflateSetDictionary z_inflateSetDictionary
+# define inflateSync z_inflateSync
+# define inflateSyncPoint z_inflateSyncPoint
+# define inflateCopy z_inflateCopy
+# define inflateReset z_inflateReset
+# define compress z_compress
+# define compress2 z_compress2
+# define compressBound z_compressBound
+# define uncompress z_uncompress
+# define adler32 z_adler32
+# define crc32 z_crc32
+# define get_crc_table z_get_crc_table
+
+# define Byte z_Byte
+# define uInt z_uInt
+# define uLong z_uLong
+# define Bytef z_Bytef
+# define charf z_charf
+# define intf z_intf
+# define uIntf z_uIntf
+# define uLongf z_uLongf
+# define voidpf z_voidpf
+# define voidp z_voidp
+#endif
+
+#if defined(__MSDOS__) && !defined(MSDOS)
+# define MSDOS
+#endif
+#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
+# define OS2
+#endif
+#if defined(_WINDOWS) && !defined(WINDOWS)
+# define WINDOWS
+#endif
+#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
+# define WIN32
+#endif
+#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
+# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
+# ifndef SYS16BIT
+# define SYS16BIT
+# endif
+# endif
+#endif
+
+/*
+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
+ * than 64k bytes at a time (needed on systems with 16-bit int).
+ */
+#ifdef SYS16BIT
+# define MAXSEG_64K
+#endif
+#ifdef MSDOS
+# define UNALIGNED_OK
+#endif
+
+#ifdef __STDC_VERSION__
+# ifndef STDC
+# define STDC
+# endif
+# if __STDC_VERSION__ >= 199901L
+# ifndef STDC99
+# define STDC99
+# endif
+# endif
+#endif
+#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
+# define STDC
+#endif
+
+#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */
+# define STDC
+#endif
+
+#ifndef STDC
+# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
+# define const /* note: need a more gentle solution here */
+# endif
+#endif
+
+/* Some Mac compilers merge all .h files incorrectly: */
+#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__)
+# define NO_DUMMY_DECL
+#endif
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+# ifdef MAXSEG_64K
+# define MAX_MEM_LEVEL 8
+# else
+# define MAX_MEM_LEVEL 9
+# endif
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2.
+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
+ * created by gzip. (Files created by minigzip can still be extracted by
+ * gzip.)
+ */
+#ifndef MAX_WBITS
+# define MAX_WBITS 15 /* 32K LZ77 window */
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+ (1 << (windowBits+2)) + (1 << (memLevel+9))
+ that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+ make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+ The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus a few kilobytes
+ for small objects.
+*/
+
+ /* Type declarations */
+
+#ifndef OF /* function prototypes */
+# ifdef STDC
+# define OF(args) args
+# else
+# define OF(args) ()
+# endif
+#endif
+
+/* The following definitions for FAR are needed only for MSDOS mixed
+ * model programming (small or medium model with some far allocations).
+ * This was tested only with MSC; for other MSDOS compilers you may have
+ * to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
+ * just define FAR to be empty.
+ */
+#ifdef SYS16BIT
+# if defined(M_I86SM) || defined(M_I86MM)
+ /* MSC small or medium model */
+# define SMALL_MEDIUM
+# ifdef _MSC_VER
+# define FAR _far
+# else
+# define FAR far
+# endif
+# endif
+# if (defined(__SMALL__) || defined(__MEDIUM__))
+ /* Turbo C small or medium model */
+# define SMALL_MEDIUM
+# ifdef __BORLANDC__
+# define FAR _far
+# else
+# define FAR far
+# endif
+# endif
+#endif
+
+#if defined(WINDOWS) || defined(WIN32)
+ /* If building or using zlib as a DLL, define ZLIB_DLL.
+ * This is not mandatory, but it offers a little performance increase.
+ */
+# ifdef ZLIB_DLL
+# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
+# ifdef ZLIB_INTERNAL
+# define ZEXTERN extern __declspec(dllexport)
+# else
+# define ZEXTERN extern __declspec(dllimport)
+# endif
+# endif
+# endif /* ZLIB_DLL */
+ /* If building or using zlib with the WINAPI/WINAPIV calling convention,
+ * define ZLIB_WINAPI.
+ * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
+ */
+# ifdef ZLIB_WINAPI
+# ifdef FAR
+# undef FAR
+# endif
+# include <windows.h>
+ /* No need for _export, use ZLIB.DEF instead. */
+ /* For complete Windows compatibility, use WINAPI, not __stdcall. */
+# define ZEXPORT WINAPI
+# ifdef WIN32
+# define ZEXPORTVA WINAPIV
+# else
+# define ZEXPORTVA FAR CDECL
+# endif
+# endif
+#endif
+
+#if defined (__BEOS__)
+# ifdef ZLIB_DLL
+# ifdef ZLIB_INTERNAL
+# define ZEXPORT __declspec(dllexport)
+# define ZEXPORTVA __declspec(dllexport)
+# else
+# define ZEXPORT __declspec(dllimport)
+# define ZEXPORTVA __declspec(dllimport)
+# endif
+# endif
+#endif
+
+#ifndef ZEXTERN
+# define ZEXTERN extern
+#endif
+#ifndef ZEXPORT
+# define ZEXPORT
+#endif
+#ifndef ZEXPORTVA
+# define ZEXPORTVA
+#endif
+
+#ifndef FAR
+# define FAR
+#endif
+
+#if !defined(__MACTYPES__)
+typedef unsigned char Byte; /* 8 bits */
+#endif
+typedef unsigned int uInt; /* 16 bits or more */
+typedef unsigned long uLong; /* 32 bits or more */
+
+#ifdef SMALL_MEDIUM
+ /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
+# define Bytef Byte FAR
+#else
+ typedef Byte FAR Bytef;
+#endif
+typedef char FAR charf;
+typedef int FAR intf;
+typedef uInt FAR uIntf;
+typedef uLong FAR uLongf;
+
+#ifdef STDC
+ typedef void const *voidpc;
+ typedef void FAR *voidpf;
+ typedef void *voidp;
+#else
+ typedef Byte const *voidpc;
+ typedef Byte FAR *voidpf;
+ typedef Byte *voidp;
+#endif
+
+#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
+# define SEEK_SET 0 /* Seek from beginning of file. */
+# define SEEK_CUR 1 /* Seek from current position. */
+# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
+#endif
+#ifndef z_off_t
+# define z_off_t long
+#endif
+
+#if defined(__OS400__)
+#define NO_vsnprintf
+#endif
+
+#if defined(__MVS__)
+# define NO_vsnprintf
+# ifdef FAR
+# undef FAR
+# endif
+#endif
+
+/* MVS linker does not support external names larger than 8 bytes */
+#if defined(__MVS__)
+# pragma map(deflateInit_,"DEIN")
+# pragma map(deflateInit2_,"DEIN2")
+# pragma map(deflateEnd,"DEEND")
+# pragma map(deflateBound,"DEBND")
+# pragma map(inflateInit_,"ININ")
+# pragma map(inflateInit2_,"ININ2")
+# pragma map(inflateEnd,"INEND")
+# pragma map(inflateSync,"INSY")
+# pragma map(inflateSetDictionary,"INSEDI")
+# pragma map(compressBound,"CMBND")
+# pragma map(inflate_table,"INTABL")
+# pragma map(inflate_fast,"INFA")
+# pragma map(inflate_copyright,"INCOPY")
+#endif
+
+#endif /* ZCONF_H */
diff --git a/contrib/extractor/libmpq/zlib.h b/contrib/extractor/libmpq/zlib.h
new file mode 100644
index 00000000000..92edf96ff3e
--- /dev/null
+++ b/contrib/extractor/libmpq/zlib.h
@@ -0,0 +1,1200 @@
+/* zlib.h -- interface of the 'zlib' general purpose compression library
+ version 1.2.1, November 17th, 2003
+
+ Copyright (C) 1995-2003 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+ jloup@gzip.org madler@alumni.caltech.edu
+
+
+ The data format used by the zlib library is described by RFCs (Request for
+ Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt
+ (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
+*/
+
+#ifndef ZLIB_H
+#define ZLIB_H
+
+#include "zconf.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ZLIB_VERSION "1.2.1"
+#define ZLIB_VERNUM 0x1210
+
+/*
+ The 'zlib' compression library provides in-memory compression and
+ decompression functions, including integrity checks of the uncompressed
+ data. This version of the library supports only one compression method
+ (deflation) but other algorithms will be added later and will have the same
+ stream interface.
+
+ Compression can be done in a single step if the buffers are large
+ enough (for example if an input file is mmap'ed), or can be done by
+ repeated calls of the compression function. In the latter case, the
+ application must provide more input and/or consume the output
+ (providing more output space) before each call.
+
+ The compressed data format used by the in-memory functions is the zlib
+ format, which is a zlib wrapper documented in RFC 1950, wrapped around a
+ deflate stream, which is itself documented in RFC 1951.
+
+ The library also supports reading and writing files in gzip (.gz) format
+ with an interface similar to that of stdio using the functions that start
+ with "gz". The gzip format is different from the zlib format. gzip is a
+ gzip wrapper, documented in RFC 1952, wrapped around a deflate stream.
+
+ The zlib format was designed to be compact and fast for use in memory
+ and on communications channels. The gzip format was designed for single-
+ file compression on file systems, has a larger header than zlib to maintain
+ directory information, and uses a different, slower check method than zlib.
+
+ This library does not provide any functions to write gzip files in memory.
+ However such functions could be easily written using zlib's deflate function,
+ the documentation in the gzip RFC, and the examples in gzio.c.
+
+ The library does not install any signal handler. The decoder checks
+ the consistency of the compressed data, so the library should never
+ crash even in case of corrupted input.
+*/
+
+typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
+typedef void (*free_func) OF((voidpf opaque, voidpf address));
+
+struct internal_state;
+
+typedef struct z_stream_s {
+ Bytef *next_in; /* next input byte */
+ uInt avail_in; /* number of bytes available at next_in */
+ uLong total_in; /* total nb of input bytes read so far */
+
+ Bytef *next_out; /* next output byte should be put there */
+ uInt avail_out; /* remaining free space at next_out */
+ uLong total_out; /* total nb of bytes output so far */
+
+ char *msg; /* last error message, NULL if no error */
+ struct internal_state FAR *state; /* not visible by applications */
+
+ alloc_func zalloc; /* used to allocate the internal state */
+ free_func zfree; /* used to free the internal state */
+ voidpf opaque; /* private data object passed to zalloc and zfree */
+
+ int data_type; /* best guess about the data type: ascii or binary */
+ uLong adler; /* adler32 value of the uncompressed data */
+ uLong reserved; /* reserved for future use */
+} z_stream;
+
+typedef z_stream FAR *z_streamp;
+
+/*
+ The application must update next_in and avail_in when avail_in has
+ dropped to zero. It must update next_out and avail_out when avail_out
+ has dropped to zero. The application must initialize zalloc, zfree and
+ opaque before calling the init function. All other fields are set by the
+ compression library and must not be updated by the application.
+
+ The opaque value provided by the application will be passed as the first
+ parameter for calls of zalloc and zfree. This can be useful for custom
+ memory management. The compression library attaches no meaning to the
+ opaque value.
+
+ zalloc must return Z_NULL if there is not enough memory for the object.
+ If zlib is used in a multi-threaded application, zalloc and zfree must be
+ thread safe.
+
+ On 16-bit systems, the functions zalloc and zfree must be able to allocate
+ exactly 65536 bytes, but will not be required to allocate more than this
+ if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
+ pointers returned by zalloc for objects of exactly 65536 bytes *must*
+ have their offset normalized to zero. The default allocation function
+ provided by this library ensures this (see zutil.c). To reduce memory
+ requirements and avoid any allocation of 64K objects, at the expense of
+ compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
+
+ The fields total_in and total_out can be used for statistics or
+ progress reports. After compression, total_in holds the total size of
+ the uncompressed data and may be saved for use in the decompressor
+ (particularly if the decompressor wants to decompress everything in
+ a single step).
+*/
+
+ /* constants */
+
+#define Z_NO_FLUSH 0
+#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */
+#define Z_SYNC_FLUSH 2
+#define Z_FULL_FLUSH 3
+#define Z_FINISH 4
+#define Z_BLOCK 5
+/* Allowed flush values; see deflate() and inflate() below for details */
+
+#define Z_OK 0
+#define Z_STREAM_END 1
+#define Z_NEED_DICT 2
+#define Z_ERRNO (-1)
+#define Z_STREAM_ERROR (-2)
+#define Z_DATA_ERROR (-3)
+#define Z_MEM_ERROR (-4)
+#define Z_BUF_ERROR (-5)
+#define Z_VERSION_ERROR (-6)
+/* Return codes for the compression/decompression functions. Negative
+ * values are errors, positive values are used for special but normal events.
+ */
+
+#define Z_NO_COMPRESSION 0
+#define Z_BEST_SPEED 1
+#define Z_BEST_COMPRESSION 9
+#define Z_DEFAULT_COMPRESSION (-1)
+/* compression levels */
+
+#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 */
+
+#define Z_BINARY 0
+#define Z_ASCII 1
+#define Z_UNKNOWN 2
+/* Possible values of the data_type field (though see inflate()) */
+
+#define Z_DEFLATED 8
+/* The deflate compression method (the only one supported in this version) */
+
+#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */
+
+#define zlib_version zlibVersion()
+/* for compatibility with versions < 1.0.2 */
+
+ /* basic functions */
+
+ZEXTERN const char * ZEXPORT zlibVersion OF((void));
+/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
+ If the first character differs, the library code actually used is
+ not compatible with the zlib.h header file used by the application.
+ This check is automatically made by deflateInit and inflateInit.
+ */
+
+/*
+ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level));
+
+ Initializes the internal stream state for compression. The fields
+ zalloc, zfree and opaque must be initialized before by the caller.
+ If zalloc and zfree are set to Z_NULL, deflateInit updates them to
+ use default allocation functions.
+
+ The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
+ 1 gives best speed, 9 gives best compression, 0 gives no compression at
+ all (the input data is simply copied a block at a time).
+ Z_DEFAULT_COMPRESSION requests a default compromise between speed and
+ compression (currently equivalent to level 6).
+
+ deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if level is not a valid compression level,
+ Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
+ with the version assumed by the caller (ZLIB_VERSION).
+ msg is set to null if there is no error message. deflateInit does not
+ perform any compression: this will be done by deflate().
+*/
+
+
+ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
+/*
+ deflate compresses as much data as possible, and stops when the input
+ buffer becomes empty or the output buffer becomes full. It may introduce some
+ output latency (reading input without producing any output) except when
+ forced to flush.
+
+ The detailed semantics are as follows. deflate performs one or both of the
+ following actions:
+
+ - Compress more input starting at next_in and update next_in and avail_in
+ accordingly. If not all input can be processed (because there is not
+ enough room in the output buffer), next_in and avail_in are updated and
+ processing will resume at this point for the next call of deflate().
+
+ - Provide more output starting at next_out and update next_out and avail_out
+ accordingly. This action is forced if the parameter flush is non zero.
+ Forcing flush frequently degrades the compression ratio, so this parameter
+ should be set only when necessary (in interactive applications).
+ Some output may be provided even if flush is not set.
+
+ Before the call of deflate(), the application should ensure that at least
+ one of the actions is possible, by providing more input and/or consuming
+ more output, and updating avail_in or avail_out accordingly; avail_out
+ should never be zero before the call. The application can consume the
+ compressed output when it wants, for example when the output buffer is full
+ (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK
+ and with zero avail_out, it must be called again after making room in the
+ output buffer because there might be more output pending.
+
+ If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
+ flushed to the output buffer and the output is aligned on a byte boundary, so
+ that the decompressor can get all input data available so far. (In particular
+ avail_in is zero after the call if enough output space has been provided
+ before the call.) Flushing may degrade compression for some compression
+ algorithms and so it should be used only when necessary.
+
+ If flush is set to Z_FULL_FLUSH, all output is flushed as with
+ Z_SYNC_FLUSH, and the compression state is reset so that decompression can
+ restart from this point if previous compressed data has been damaged or if
+ random access is desired. Using Z_FULL_FLUSH too often can seriously degrade
+ the compression.
+
+ If deflate returns with avail_out == 0, this function must be called again
+ with the same value of the flush parameter and more output space (updated
+ avail_out), until the flush is complete (deflate returns with non-zero
+ avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that
+ avail_out is greater than six to avoid repeated flush markers due to
+ avail_out == 0 on return.
+
+ If the parameter flush is set to Z_FINISH, pending input is processed,
+ pending output is flushed and deflate returns with Z_STREAM_END if there
+ was enough output space; if deflate returns with Z_OK, this function must be
+ called again with Z_FINISH and more output space (updated avail_out) but no
+ more input data, until it returns with Z_STREAM_END or an error. After
+ deflate has returned Z_STREAM_END, the only possible operations on the
+ stream are deflateReset or deflateEnd.
+
+ Z_FINISH can be used immediately after deflateInit if all the compression
+ is to be done in a single step. In this case, avail_out must be at least
+ the value returned by deflateBound (see below). If deflate does not return
+ Z_STREAM_END, then it must be called again as described above.
+
+ deflate() sets strm->adler to the adler32 checksum of all input read
+ so far (that is, total_in bytes).
+
+ deflate() may update data_type if it can make a good guess about
+ the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered
+ binary. This field is only for information purposes and does not affect
+ the compression algorithm in any manner.
+
+ deflate() returns Z_OK if some progress has been made (more input
+ processed or more output produced), Z_STREAM_END if all input has been
+ consumed and all output has been produced (only when flush is set to
+ Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
+ if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible
+ (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not
+ fatal, and deflate() can be called again with more input and more output
+ space to continue compressing.
+*/
+
+
+ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm));
+/*
+ All dynamically allocated data structures for this stream are freed.
+ This function discards any unprocessed input and does not flush any
+ pending output.
+
+ deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
+ stream state was inconsistent, Z_DATA_ERROR if the stream was freed
+ prematurely (some input or output was discarded). In the error case,
+ msg may be set but then points to a static string (which must not be
+ deallocated).
+*/
+
+
+/*
+ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm));
+
+ Initializes the internal stream state for decompression. The fields
+ next_in, avail_in, zalloc, zfree and opaque must be initialized before by
+ the caller. If next_in is not Z_NULL and avail_in is large enough (the exact
+ value depends on the compression method), inflateInit determines the
+ compression method from the zlib header and allocates all data structures
+ accordingly; otherwise the allocation will be deferred to the first call of
+ inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to
+ use default allocation functions.
+
+ inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
+ version assumed by the caller. msg is set to null if there is no error
+ message. inflateInit does not perform any decompression apart from reading
+ the zlib header if present: this will be done by inflate(). (So next_in and
+ avail_in may be modified, but next_out and avail_out are unchanged.)
+*/
+
+
+ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
+/*
+ inflate decompresses as much data as possible, and stops when the input
+ buffer becomes empty or the output buffer becomes full. It may introduce
+ some output latency (reading input without producing any output) except when
+ forced to flush.
+
+ The detailed semantics are as follows. inflate performs one or both of the
+ following actions:
+
+ - Decompress more input starting at next_in and update next_in and avail_in
+ accordingly. If not all input can be processed (because there is not
+ enough room in the output buffer), next_in is updated and processing
+ will resume at this point for the next call of inflate().
+
+ - Provide more output starting at next_out and update next_out and avail_out
+ accordingly. inflate() provides as much output as possible, until there
+ is no more input data or no more space in the output buffer (see below
+ about the flush parameter).
+
+ Before the call of inflate(), the application should ensure that at least
+ one of the actions is possible, by providing more input and/or consuming
+ more output, and updating the next_* and avail_* values accordingly.
+ The application can consume the uncompressed output when it wants, for
+ example when the output buffer is full (avail_out == 0), or after each
+ call of inflate(). If inflate returns Z_OK and with zero avail_out, it
+ must be called again after making room in the output buffer because there
+ might be more output pending.
+
+ The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH,
+ Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much
+ output as possible to the output buffer. Z_BLOCK requests that inflate() stop
+ if and when it get to the next deflate block boundary. When decoding the zlib
+ or gzip format, this will cause inflate() to return immediately after the
+ header and before the first block. When doing a raw inflate, inflate() will
+ go ahead and process the first block, and will return when it gets to the end
+ of that block, or when it runs out of data.
+
+ The Z_BLOCK option assists in appending to or combining deflate streams.
+ Also to assist in this, on return inflate() will set strm->data_type to the
+ number of unused bits in the last byte taken from strm->next_in, plus 64
+ if inflate() is currently decoding the last block in the deflate stream,
+ plus 128 if inflate() returned immediately after decoding an end-of-block
+ code or decoding the complete header up to just before the first byte of the
+ deflate stream. The end-of-block will not be indicated until all of the
+ uncompressed data from that block has been written to strm->next_out. The
+ number of unused bits may in general be greater than seven, except when
+ bit 7 of data_type is set, in which case the number of unused bits will be
+ less than eight.
+
+ inflate() should normally be called until it returns Z_STREAM_END or an
+ error. However if all decompression is to be performed in a single step
+ (a single call of inflate), the parameter flush should be set to
+ Z_FINISH. In this case all pending input is processed and all pending
+ output is flushed; avail_out must be large enough to hold all the
+ uncompressed data. (The size of the uncompressed data may have been saved
+ by the compressor for this purpose.) The next operation on this stream must
+ be inflateEnd to deallocate the decompression state. The use of Z_FINISH
+ is never required, but can be used to inform inflate that a faster approach
+ may be used for the single inflate() call.
+
+ In this implementation, inflate() always flushes as much output as
+ possible to the output buffer, and always uses the faster approach on the
+ first call. So the only effect of the flush parameter in this implementation
+ is on the return value of inflate(), as noted below, or when it returns early
+ because Z_BLOCK is used.
+
+ If a preset dictionary is needed after this call (see inflateSetDictionary
+ below), inflate sets strm-adler to the adler32 checksum of the dictionary
+ chosen by the compressor and returns Z_NEED_DICT; otherwise it sets
+ strm->adler to the adler32 checksum of all output produced so far (that is,
+ total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described
+ below. At the end of the stream, inflate() checks that its computed adler32
+ checksum is equal to that saved by the compressor and returns Z_STREAM_END
+ only if the checksum is correct.
+
+ inflate() will decompress and check either zlib-wrapped or gzip-wrapped
+ deflate data. The header type is detected automatically. Any information
+ contained in the gzip header is not retained, so applications that need that
+ information should instead use raw inflate, see inflateInit2() below, or
+ inflateBack() and perform their own processing of the gzip header and
+ trailer.
+
+ inflate() returns Z_OK if some progress has been made (more input processed
+ or more output produced), Z_STREAM_END if the end of the compressed data has
+ been reached and all uncompressed output has been produced, Z_NEED_DICT if a
+ preset dictionary is needed at this point, Z_DATA_ERROR if the input data was
+ corrupted (input stream not conforming to the zlib format or incorrect check
+ value), Z_STREAM_ERROR if the stream structure was inconsistent (for example
+ if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory,
+ Z_BUF_ERROR if no progress is possible or if there was not enough room in the
+ output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and
+ inflate() can be called again with more input and more output space to
+ continue decompressing. If Z_DATA_ERROR is returned, the application may then
+ call inflateSync() to look for a good compression block if a partial recovery
+ of the data is desired.
+*/
+
+
+ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm));
+/*
+ All dynamically allocated data structures for this stream are freed.
+ This function discards any unprocessed input and does not flush any
+ pending output.
+
+ inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
+ was inconsistent. In the error case, msg may be set but then points to a
+ static string (which must not be deallocated).
+*/
+
+ /* Advanced functions */
+
+/*
+ The following functions are needed only in some special applications.
+*/
+
+/*
+ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,
+ int level,
+ int method,
+ int windowBits,
+ int memLevel,
+ int strategy));
+
+ This is another version of deflateInit with more compression options. The
+ fields next_in, zalloc, zfree and opaque must be initialized before by
+ the caller.
+
+ The method parameter is the compression method. It must be Z_DEFLATED in
+ this version of the library.
+
+ The windowBits parameter is the base two logarithm of the window size
+ (the size of the history buffer). It should be in the range 8..15 for this
+ version of the library. Larger values of this parameter result in better
+ compression at the expense of memory usage. The default value is 15 if
+ deflateInit is used instead.
+
+ windowBits can also be -8..-15 for raw deflate. In this case, -windowBits
+ determines the window size. deflate() will then generate raw deflate data
+ with no zlib header or trailer, and will not compute an adler32 check value.
+
+ windowBits can also be greater than 15 for optional gzip encoding. Add
+ 16 to windowBits to write a simple gzip header and trailer around the
+ compressed data instead of a zlib wrapper. The gzip header will have no
+ file name, no extra data, no comment, no modification time (set to zero),
+ no header crc, and the operating system will be set to 255 (unknown).
+
+ The memLevel parameter specifies how much memory should be allocated
+ for the internal compression state. memLevel=1 uses minimum memory but
+ is slow and reduces compression ratio; memLevel=9 uses maximum memory
+ for optimal speed. The default value is 8. See zconf.h for total memory
+ usage as a function of windowBits and memLevel.
+
+ The strategy parameter is used to tune the compression algorithm. Use the
+ value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
+ filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no
+ string match), or Z_RLE to limit match distances to one (run-length
+ encoding). Filtered data consists mostly of small values with a somewhat
+ random distribution. In this case, the compression algorithm is tuned to
+ compress them better. The effect of Z_FILTERED is to force more Huffman
+ coding and less string matching; it is somewhat intermediate between
+ Z_DEFAULT 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
+ method). msg is set to null if there is no error message. deflateInit2 does
+ not perform any compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
+ const Bytef *dictionary,
+ uInt dictLength));
+/*
+ Initializes the compression dictionary from the given byte sequence
+ without producing any compressed output. This function must be called
+ immediately after deflateInit, deflateInit2 or deflateReset, before any
+ call of deflate. The compressor and decompressor must use exactly the same
+ dictionary (see inflateSetDictionary).
+
+ The dictionary should consist of strings (byte sequences) that are likely
+ to be encountered later in the data to be compressed, with the most commonly
+ used strings preferably put towards the end of the dictionary. Using a
+ dictionary is most useful when the data to be compressed is short and can be
+ predicted with good accuracy; the data can then be compressed better than
+ with the default empty dictionary.
+
+ Depending on the size of the compression data structures selected by
+ deflateInit or deflateInit2, a part of the dictionary may in effect be
+ discarded, for example if the dictionary is larger than the window size in
+ deflate or deflate2. Thus the strings most likely to be useful should be
+ put at the end of the dictionary, not at the front.
+
+ Upon return of this function, strm->adler is set to the adler32 value
+ of the dictionary; the decompressor may later use this value to determine
+ which dictionary has been used by the compressor. (The adler32 value
+ applies to the whole dictionary even if only a subset of the dictionary is
+ actually used by the compressor.) If a raw deflate was requested, then the
+ adler32 value is not computed and strm->adler is not set.
+
+ deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
+ parameter is invalid (such as NULL dictionary) or the stream state is
+ inconsistent (for example if deflate has already been called for this stream
+ or if the compression method is bsort). deflateSetDictionary does not
+ perform any compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest,
+ z_streamp source));
+/*
+ Sets the destination stream as a complete copy of the source stream.
+
+ This function can be useful when several compression strategies will be
+ tried, for example when there are several ways of pre-processing the input
+ data with a filter. The streams that will be discarded should then be freed
+ by calling deflateEnd. Note that deflateCopy duplicates the internal
+ compression state which can be quite large, so this strategy is slow and
+ can consume lots of memory.
+
+ deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+ (such as zalloc being NULL). msg is left unchanged in both source and
+ destination.
+*/
+
+ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm));
+/*
+ This function is equivalent to deflateEnd followed by deflateInit,
+ but does not free and reallocate all the internal compression state.
+ The stream will keep the same compression level and any other attributes
+ that may have been set by deflateInit2.
+
+ deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,
+ int level,
+ int strategy));
+/*
+ Dynamically update the compression level and compression strategy. The
+ interpretation of level and strategy is as in deflateInit2. This can be
+ used to switch between compression and straight copy of the input data, or
+ to switch to a different kind of input data requiring a different
+ strategy. If the compression level is changed, the input available so far
+ is compressed with the old level (and may be flushed); the new level will
+ take effect only at the next call of deflate().
+
+ Before the call of deflateParams, the stream state must be set as for
+ a call of deflate(), since the currently available input may have to
+ be compressed and flushed. In particular, strm->avail_out must be non-zero.
+
+ deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source
+ stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR
+ if strm->avail_out was zero.
+*/
+
+ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm,
+ uLong sourceLen));
+/*
+ deflateBound() returns an upper bound on the compressed size after
+ deflation of sourceLen bytes. It must be called after deflateInit()
+ or deflateInit2(). This would be used to allocate an output buffer
+ for deflation in a single pass, and so would be called before deflate().
+*/
+
+ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm,
+ int bits,
+ int value));
+/*
+ deflatePrime() inserts bits in the deflate output stream. The intent
+ is that this function is used to start off the deflate output with the
+ bits leftover from a previous deflate stream when appending to it. As such,
+ this function can only be used for raw deflate, and must be used before the
+ first deflate() call after a deflateInit2() or deflateReset(). bits must be
+ less than or equal to 16, and that many of the least significant bits of
+ value will be inserted in the output.
+
+ deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
+/*
+ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,
+ int windowBits));
+
+ This is another version of inflateInit with an extra parameter. The
+ fields next_in, avail_in, zalloc, zfree and opaque must be initialized
+ before by the caller.
+
+ The windowBits parameter is the base two logarithm of the maximum window
+ size (the size of the history buffer). It should be in the range 8..15 for
+ this version of the library. The default value is 15 if inflateInit is used
+ instead. windowBits must be greater than or equal to the windowBits value
+ provided to deflateInit2() while compressing, or it must be equal to 15 if
+ deflateInit2() was not used. If a compressed stream with a larger window
+ size is given as input, inflate() will return with the error code
+ Z_DATA_ERROR instead of trying to allocate a larger window.
+
+ windowBits can also be -8..-15 for raw inflate. In this case, -windowBits
+ determines the window size. inflate() will then process raw deflate data,
+ not looking for a zlib or gzip header, not generating a check value, and not
+ looking for any check values for comparison at the end of the stream. This
+ is for use with other formats that use the deflate compressed data format
+ such as zip. Those formats provide their own check values. If a custom
+ format is developed using the raw deflate format for compressed data, it is
+ recommended that a check value such as an adler32 or a crc32 be applied to
+ the uncompressed data as is done in the zlib, gzip, and zip formats. For
+ most applications, the zlib format should be used as is. Note that comments
+ above on the use in deflateInit2() applies to the magnitude of windowBits.
+
+ windowBits can also be greater than 15 for optional gzip decoding. Add
+ 32 to windowBits to enable zlib and gzip decoding with automatic header
+ detection, or add 16 to decode only the gzip format (the zlib format will
+ return a Z_DATA_ERROR).
+
+ inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative
+ memLevel). msg is set to null if there is no error message. inflateInit2
+ does not perform any decompression apart from reading the zlib header if
+ present: this will be done by inflate(). (So next_in and avail_in may be
+ modified, but next_out and avail_out are unchanged.)
+*/
+
+ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
+ const Bytef *dictionary,
+ uInt dictLength));
+/*
+ Initializes the decompression dictionary from the given uncompressed byte
+ sequence. This function must be called immediately after a call of inflate
+ if this call returned Z_NEED_DICT. The dictionary chosen by the compressor
+ can be determined from the adler32 value returned by this call of
+ inflate. The compressor and decompressor must use exactly the same
+ dictionary (see deflateSetDictionary).
+
+ inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
+ parameter is invalid (such as NULL dictionary) or the stream state is
+ inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
+ expected one (incorrect adler32 value). inflateSetDictionary does not
+ perform any decompression: this will be done by subsequent calls of
+ inflate().
+*/
+
+ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm));
+/*
+ Skips invalid compressed data until a full flush point (see above the
+ description of deflate with Z_FULL_FLUSH) can be found, or until all
+ available input is skipped. No output is provided.
+
+ inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR
+ if no more input was provided, Z_DATA_ERROR if no flush point has been found,
+ or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
+ case, the application may save the current current value of total_in which
+ indicates where valid compressed data was found. In the error case, the
+ application may repeatedly call inflateSync, providing more input each time,
+ until success or end of the input data.
+*/
+
+ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest,
+ z_streamp source));
+/*
+ Sets the destination stream as a complete copy of the source stream.
+
+ This function can be useful when randomly accessing a large stream. The
+ first pass through the stream can periodically record the inflate state,
+ allowing restarting inflate at those points when randomly accessing the
+ stream.
+
+ inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+ (such as zalloc being NULL). msg is left unchanged in both source and
+ destination.
+*/
+
+ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm));
+/*
+ This function is equivalent to inflateEnd followed by inflateInit,
+ but does not free and reallocate all the internal decompression state.
+ The stream will keep attributes that may have been set by inflateInit2.
+
+ inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+/*
+ZEXTERN int ZEXPORT inflateBackInit OF((z_stream FAR *strm, int windowBits,
+ unsigned char FAR *window));
+
+ Initialize the internal stream state for decompression using inflateBack()
+ calls. The fields zalloc, zfree and opaque in strm must be initialized
+ before the call. If zalloc and zfree are Z_NULL, then the default library-
+ derived memory allocation routines are used. windowBits is the base two
+ logarithm of the window size, in the range 8..15. window is a caller
+ supplied buffer of that size. Except for special applications where it is
+ assured that deflate was used with small window sizes, windowBits must be 15
+ and a 32K byte window must be supplied to be able to decompress general
+ deflate streams.
+
+ See inflateBack() for the usage of these routines.
+
+ inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of
+ the paramaters are invalid, Z_MEM_ERROR if the internal state could not
+ be allocated, or Z_VERSION_ERROR if the version of the library does not
+ match the version of the header file.
+*/
+
+typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *));
+typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned));
+
+ZEXTERN int ZEXPORT inflateBack OF((z_stream FAR *strm,
+ in_func in, void FAR *in_desc,
+ out_func out, void FAR *out_desc));
+/*
+ inflateBack() does a raw inflate with a single call using a call-back
+ interface for input and output. This is more efficient than inflate() for
+ file i/o applications in that it avoids copying between the output and the
+ sliding window by simply making the window itself the output buffer. This
+ function trusts the application to not change the output buffer passed by
+ the output function, at least until inflateBack() returns.
+
+ inflateBackInit() must be called first to allocate the internal state
+ and to initialize the state with the user-provided window buffer.
+ inflateBack() may then be used multiple times to inflate a complete, raw
+ deflate stream with each call. inflateBackEnd() is then called to free
+ the allocated state.
+
+ A raw deflate stream is one with no zlib or gzip header or trailer.
+ This routine would normally be used in a utility that reads zip or gzip
+ files and writes out uncompressed files. The utility would decode the
+ header and process the trailer on its own, hence this routine expects
+ only the raw deflate stream to decompress. This is different from the
+ normal behavior of inflate(), which expects either a zlib or gzip header and
+ trailer around the deflate stream.
+
+ inflateBack() uses two subroutines supplied by the caller that are then
+ called by inflateBack() for input and output. inflateBack() calls those
+ routines until it reads a complete deflate stream and writes out all of the
+ uncompressed data, or until it encounters an error. The function's
+ parameters and return types are defined above in the in_func and out_func
+ typedefs. inflateBack() will call in(in_desc, &buf) which should return the
+ number of bytes of provided input, and a pointer to that input in buf. If
+ there is no input available, in() must return zero--buf is ignored in that
+ case--and inflateBack() will return a buffer error. inflateBack() will call
+ out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out()
+ should return zero on success, or non-zero on failure. If out() returns
+ non-zero, inflateBack() will return with an error. Neither in() nor out()
+ are permitted to change the contents of the window provided to
+ inflateBackInit(), which is also the buffer that out() uses to write from.
+ The length written by out() will be at most the window size. Any non-zero
+ amount of input may be provided by in().
+
+ For convenience, inflateBack() can be provided input on the first call by
+ setting strm->next_in and strm->avail_in. If that input is exhausted, then
+ in() will be called. Therefore strm->next_in must be initialized before
+ calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called
+ immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in
+ must also be initialized, and then if strm->avail_in is not zero, input will
+ initially be taken from strm->next_in[0 .. strm->avail_in - 1].
+
+ The in_desc and out_desc parameters of inflateBack() is passed as the
+ first parameter of in() and out() respectively when they are called. These
+ descriptors can be optionally used to pass any information that the caller-
+ supplied in() and out() functions need to do their job.
+
+ On return, inflateBack() will set strm->next_in and strm->avail_in to
+ pass back any unused input that was provided by the last in() call. The
+ return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR
+ if in() or out() returned an error, Z_DATA_ERROR if there was a format
+ error in the deflate stream (in which case strm->msg is set to indicate the
+ nature of the error), or Z_STREAM_ERROR if the stream was not properly
+ initialized. In the case of Z_BUF_ERROR, an input or output error can be
+ distinguished using strm->next_in which will be Z_NULL only if in() returned
+ an error. If strm->next is not Z_NULL, then the Z_BUF_ERROR was due to
+ out() returning non-zero. (in() will always be called before out(), so
+ strm->next_in is assured to be defined if out() returns non-zero.) Note
+ that inflateBack() cannot return Z_OK.
+*/
+
+ZEXTERN int ZEXPORT inflateBackEnd OF((z_stream FAR *strm));
+/*
+ All memory allocated by inflateBackInit() is freed.
+
+ inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream
+ state was inconsistent.
+*/
+
+ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void));
+/* Return flags indicating compile-time options.
+
+ Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other:
+ 1.0: size of uInt
+ 3.2: size of uLong
+ 5.4: size of voidpf (pointer)
+ 7.6: size of z_off_t
+
+ Compiler, assembler, and debug options:
+ 8: DEBUG
+ 9: ASMV or ASMINF -- use ASM code
+ 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention
+ 11: 0 (reserved)
+
+ One-time table building (smaller code, but not thread-safe if true):
+ 12: BUILDFIXED -- build static block decoding tables when needed
+ 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed
+ 14,15: 0 (reserved)
+
+ Library content (indicates missing functionality):
+ 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking
+ deflate code when not needed)
+ 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect
+ and decode gzip streams (to avoid linking crc code)
+ 18-19: 0 (reserved)
+
+ Operation variations (changes in library functionality):
+ 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate
+ 21: FASTEST -- deflate algorithm with only one, lowest compression level
+ 22,23: 0 (reserved)
+
+ The sprintf variant used by gzprintf (zero is best):
+ 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format
+ 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure!
+ 26: 0 = returns value, 1 = void -- 1 means inferred string length returned
+
+ Remainder:
+ 27-31: 0 (reserved)
+ */
+
+
+ /* utility functions */
+
+/*
+ The following utility functions are implemented on top of the
+ basic stream-oriented functions. To simplify the interface, some
+ default options are assumed (compression level and memory usage,
+ standard memory allocation functions). The source code of these
+ utility functions can easily be modified if you need special options.
+*/
+
+ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen));
+/*
+ Compresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total
+ size of the destination buffer, which must be at least the value returned
+ by compressBound(sourceLen). Upon exit, destLen is the actual size of the
+ compressed buffer.
+ This function can be used to compress a whole file at once if the
+ input file is mmap'ed.
+ compress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer.
+*/
+
+ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen,
+ int level));
+/*
+ Compresses the source buffer into the destination buffer. The level
+ parameter has the same meaning as in deflateInit. sourceLen is the byte
+ length of the source buffer. Upon entry, destLen is the total size of the
+ destination buffer, which must be at least the value returned by
+ compressBound(sourceLen). Upon exit, destLen is the actual size of the
+ compressed buffer.
+
+ compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_BUF_ERROR if there was not enough room in the output buffer,
+ Z_STREAM_ERROR if the level parameter is invalid.
+*/
+
+ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen));
+/*
+ compressBound() returns an upper bound on the compressed size after
+ compress() or compress2() on sourceLen bytes. It would be used before
+ a compress() or compress2() call to allocate the destination buffer.
+*/
+
+ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen));
+/*
+ Decompresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total
+ size of the destination buffer, which must be large enough to hold the
+ entire uncompressed data. (The size of the uncompressed data must have
+ been saved previously by the compressor and transmitted to the decompressor
+ by some mechanism outside the scope of this compression library.)
+ Upon exit, destLen is the actual size of the compressed buffer.
+ This function can be used to decompress a whole file at once if the
+ input file is mmap'ed.
+
+ uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete.
+*/
+
+
+typedef voidp gzFile;
+
+ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
+/*
+ Opens a gzip (.gz) file for reading or writing. The mode parameter
+ is as in fopen ("rb" or "wb") but can also include a compression level
+ ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for
+ Huffman only compression as in "wb1h", 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.
+
+ gzopen returns NULL if the file could not be opened or if there was
+ insufficient memory to allocate the (de)compression state; errno
+ can be checked to distinguish the two cases (if errno is zero, the
+ zlib error is Z_MEM_ERROR). */
+
+ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode));
+/*
+ gzdopen() associates a gzFile with the file descriptor fd. File
+ descriptors are obtained from calls like open, dup, creat, pipe or
+ fileno (in the file has been previously opened with fopen).
+ The mode parameter is as in gzopen.
+ The next call of gzclose on the returned gzFile will also close the
+ file descriptor fd, just like fclose(fdopen(fd), mode) closes the file
+ descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode).
+ gzdopen returns NULL if there was insufficient memory to allocate
+ the (de)compression state.
+*/
+
+ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
+/*
+ Dynamically update the compression level or strategy. See the description
+ of deflateInit2 for the meaning of these parameters.
+ gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not
+ opened for writing.
+*/
+
+ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len));
+/*
+ Reads the given number of uncompressed bytes from the compressed file.
+ If the input file was not in gzip format, gzread copies the given number
+ of bytes into the buffer.
+ gzread returns the number of uncompressed bytes actually read (0 for
+ end of file, -1 for error). */
+
+ZEXTERN int ZEXPORT gzwrite OF((gzFile file,
+ voidpc buf, unsigned len));
+/*
+ Writes the given number of uncompressed bytes into the compressed file.
+ gzwrite returns the number of uncompressed bytes actually written
+ (0 in case of error).
+*/
+
+ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...));
+/*
+ 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. If it is exceeded, then gzprintf() will return
+ return an error (0) with nothing written. In this case, there may also be a
+ buffer overflow with unpredictable consequences, which is possible only if
+ zlib was compiled with the insecure functions sprintf() or vsprintf()
+ because the secure snprintf() or vsnprintf() functions were not available.
+*/
+
+ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));
+/*
+ Writes the given null-terminated string to the compressed file, excluding
+ the terminating null character.
+ gzputs returns the number of characters written, or -1 in case of error.
+*/
+
+ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));
+/*
+ Reads bytes from the compressed file until len-1 characters are read, or
+ a newline character is read and transferred to buf, or an end-of-file
+ condition is encountered. The string is then terminated with a null
+ character.
+ gzgets returns buf, or Z_NULL in case of error.
+*/
+
+ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c));
+/*
+ Writes c, converted to an unsigned char, into the compressed file.
+ gzputc returns the value that was written, or -1 in case of error.
+*/
+
+ZEXTERN int ZEXPORT gzgetc OF((gzFile file));
+/*
+ Reads one byte from the compressed file. gzgetc returns this byte
+ or -1 in case of end of file or error.
+*/
+
+ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file));
+/*
+ Push one character back onto the stream to be read again later.
+ Only one character of push-back is allowed. gzungetc() returns the
+ character pushed, or -1 on failure. gzungetc() will fail if a
+ character has been pushed but not read yet, or if c is -1. The pushed
+ character will be discarded if the stream is repositioned with gzseek()
+ or gzrewind().
+*/
+
+ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush));
+/*
+ Flushes all pending output into the compressed file. The parameter
+ flush is as in the deflate() function. The return value is the zlib
+ error number (see function gzerror below). gzflush returns Z_OK if
+ the flush parameter is Z_FINISH and all output could be flushed.
+ gzflush should be called only when strictly necessary because it can
+ degrade compression.
+*/
+
+ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file,
+ z_off_t offset, int whence));
+/*
+ Sets the starting position for the next gzread or gzwrite on the
+ given compressed file. The offset represents a number of bytes in the
+ uncompressed data stream. The whence parameter is defined as in lseek(2);
+ the value SEEK_END is not supported.
+ If the file is opened for reading, this function is emulated but can be
+ extremely slow. If the file is opened for writing, only forward seeks are
+ supported; gzseek then compresses a sequence of zeroes up to the new
+ starting position.
+
+ gzseek returns the resulting offset location as measured in bytes from
+ the beginning of the uncompressed stream, or -1 in case of error, in
+ particular if the file is opened for writing and the new starting position
+ would be before the current position.
+*/
+
+ZEXTERN int ZEXPORT gzrewind OF((gzFile file));
+/*
+ Rewinds the given file. This function is supported only for reading.
+
+ gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
+*/
+
+ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file));
+/*
+ Returns the starting position for the next gzread or gzwrite on the
+ given compressed file. This position represents a number of bytes in the
+ uncompressed data stream.
+
+ gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
+*/
+
+ZEXTERN int ZEXPORT gzeof OF((gzFile file));
+/*
+ Returns 1 when EOF has previously been detected reading the given
+ input stream, otherwise zero.
+*/
+
+ZEXTERN int ZEXPORT gzclose OF((gzFile file));
+/*
+ Flushes all pending output if necessary, closes the compressed file
+ and deallocates all the (de)compression state. The return value is the zlib
+ error number (see function gzerror below).
+*/
+
+ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));
+/*
+ Returns the error message for the last error which occurred on the
+ given compressed file. errnum is set to zlib error number. If an
+ error occurred in the file system and not in the compression library,
+ errnum is set to Z_ERRNO and the application may consult errno
+ to get the exact error code.
+*/
+
+ZEXTERN void ZEXPORT gzclearerr OF((gzFile file));
+/*
+ Clears the error and end-of-file flags for file. This is analogous to the
+ clearerr() function in stdio. This is useful for continuing to read a gzip
+ file that is being written concurrently.
+*/
+
+ /* checksum functions */
+
+/*
+ These functions are not related to compression but are exported
+ anyway because they might be useful in applications using the
+ compression library.
+*/
+
+ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
+
+/*
+ Update a running Adler-32 checksum with the bytes buf[0..len-1] and
+ return the updated checksum. If buf is NULL, this function returns
+ the required initial value for the checksum.
+ An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
+ much faster. Usage example:
+
+ uLong adler = adler32(0L, Z_NULL, 0);
+
+ while (read_buffer(buffer, length) != EOF) {
+ adler = adler32(adler, buffer, length);
+ }
+ if (adler != original_adler) error();
+*/
+
+ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len));
+/*
+ Update a running crc with the bytes buf[0..len-1] and return the updated
+ crc. If buf is NULL, this function returns the required initial value
+ for the crc. Pre- and post-conditioning (one's complement) is performed
+ within this function so it shouldn't be done by the application.
+ Usage example:
+
+ uLong crc = crc32(0L, Z_NULL, 0);
+
+ while (read_buffer(buffer, length) != EOF) {
+ crc = crc32(crc, buffer, length);
+ }
+ if (crc != original_crc) error();
+*/
+
+
+ /* various hacks, don't look :) */
+
+/* deflateInit and inflateInit are macros to allow checking the zlib version
+ * and the compiler's view of z_stream:
+ */
+ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level,
+ const char *version, int stream_size));
+ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm,
+ const char *version, int stream_size));
+ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method,
+ int windowBits, int memLevel,
+ int strategy, const char *version,
+ int stream_size));
+ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits,
+ const char *version, int stream_size));
+ZEXTERN int ZEXPORT inflateBackInit_ OF((z_stream FAR *strm, int windowBits,
+ unsigned char FAR *window,
+ const char *version,
+ int stream_size));
+#define deflateInit(strm, level) \
+ deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit(strm) \
+ inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream))
+#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
+ deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
+ (strategy), ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit2(strm, windowBits) \
+ inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))
+#define inflateBackInit(strm, windowBits, window) \
+ inflateBackInit_((strm), (windowBits), (window), \
+ ZLIB_VERSION, sizeof(z_stream))
+
+
+#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL)
+ struct internal_state {int dummy;}; /* hack for buggy compilers */
+#endif
+
+ZEXTERN const char * ZEXPORT zError OF((int err));
+ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z));
+ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZLIB_H */
diff --git a/contrib/extractor/mpq_libmpq.cpp b/contrib/extractor/mpq_libmpq.cpp
new file mode 100644
index 00000000000..98d114c572f
--- /dev/null
+++ b/contrib/extractor/mpq_libmpq.cpp
@@ -0,0 +1,133 @@
+#include "mpq_libmpq.h"
+#include <deque>
+
+ArchiveSet gOpenArchives;
+
+MPQArchive::MPQArchive(const char* filename)
+{
+ int result = libmpq_archive_open(&mpq_a, (unsigned char*)filename);
+ printf("Opening %s\n", filename);
+ if(result) {
+ switch(result) {
+ case LIBMPQ_EFILE : /* error on file operation */
+ printf("Error opening archive '%s': File operation Error\n", filename);
+ break;
+ case LIBMPQ_EFILE_FORMAT : /* bad file format */
+ printf("Error opening archive '%s': Bad file format\n", filename);
+ break;
+ case LIBMPQ_EFILE_CORRUPT : /* file corrupt */
+ printf("Error opening archive '%s': File corrupt\n", filename);
+ break;
+ case LIBMPQ_EFILE_NOT_FOUND : /* file in archive not found */
+ printf("Error opening archive '%s': File in archive not found\n", filename);
+ break;
+ case LIBMPQ_EFILE_READ : /* Read error in archive */
+ printf("Error opening archive '%s': Read error in archive\n", filename);
+ break;
+ case LIBMPQ_EALLOCMEM : /* maybe not enough memory? :) */
+ printf("Error opening archive '%s': Maybe not enough memory\n", filename);
+ break;
+ case LIBMPQ_EFREEMEM : /* can not free memory */
+ printf("Error opening archive '%s': Cannot free memory\n", filename);
+ break;
+ case LIBMPQ_EINV_RANGE : /* Given filenumber is out of range */
+ printf("Error opening archive '%s': Given filenumber is out of range\n", filename);
+ break;
+ case LIBMPQ_EHASHTABLE : /* error in reading hashtable */
+ printf("Error opening archive '%s': Error in reading hashtable\n", filename);
+ break;
+ case LIBMPQ_EBLOCKTABLE : /* error in reading blocktable */
+ printf("Error opening archive '%s': Error in reading blocktable\n", filename);
+ break;
+ default:
+ printf("Error opening archive '%s': Unknown error\n", filename);
+ break;
+ }
+ return;
+ }
+ gOpenArchives.push_front(this);
+}
+
+void MPQArchive::close()
+{
+ //gOpenArchives.erase(erase(&mpq_a);
+ libmpq_archive_close(&mpq_a);
+}
+
+MPQFile::MPQFile(const char* filename):
+ eof(false),
+ buffer(0),
+ pointer(0),
+ size(0)
+{
+ for(ArchiveSet::iterator i=gOpenArchives.begin(); i!=gOpenArchives.end();++i)
+ {
+ mpq_archive &mpq_a = (*i)->mpq_a;
+
+ mpq_hash hash = (*i)->GetHashEntry(filename);
+ uint32 blockindex = hash.blockindex;
+
+ if ((blockindex == 0xFFFFFFFF) || (blockindex == 0)) {
+ continue; //file not found
+ }
+
+ int fileno = blockindex;
+
+ //int fileno = libmpq_file_number(&mpq_a, filename);
+ //if(fileno == LIBMPQ_EFILE_NOT_FOUND)
+ // continue;
+
+ // Found!
+ size = libmpq_file_info(&mpq_a, LIBMPQ_FILE_UNCOMPRESSED_SIZE, fileno);
+ // HACK: in patch.mpq some files don't want to open and give 1 for filesize
+ if (size<=1) {
+ eof = true;
+ buffer = 0;
+ return;
+ }
+ buffer = new char[size];
+
+ //libmpq_file_getdata
+ libmpq_file_getdata(&mpq_a, hash, fileno, (unsigned char*)buffer);
+ return;
+
+ }
+ eof = true;
+ buffer = 0;
+}
+
+size_t MPQFile::read(void* dest, size_t bytes)
+{
+ if (eof) return 0;
+
+ size_t rpos = pointer + bytes;
+ if (rpos > size) {
+ bytes = size - pointer;
+ eof = true;
+ }
+
+ memcpy(dest, &(buffer[pointer]), bytes);
+
+ pointer = rpos;
+
+ return bytes;
+}
+
+void MPQFile::seek(int offset)
+{
+ pointer = offset;
+ eof = (pointer >= size);
+}
+
+void MPQFile::seekRelative(int offset)
+{
+ pointer += offset;
+ eof = (pointer >= size);
+}
+
+void MPQFile::close()
+{
+ if (buffer) delete[] buffer;
+ buffer = 0;
+ eof = true;
+}
diff --git a/contrib/extractor/mpq_libmpq.h b/contrib/extractor/mpq_libmpq.h
new file mode 100644
index 00000000000..542e7b21d17
--- /dev/null
+++ b/contrib/extractor/mpq_libmpq.h
@@ -0,0 +1,124 @@
+#define _CRT_SECURE_NO_DEPRECATE
+#define _CRT_SECURE_NO_WARNINGS
+
+#ifndef MPQ_H
+#define MPQ_H
+
+#include "libmpq/mpq.h"
+#include <string.h>
+#include <ctype.h>
+#include <vector>
+#include <iostream>
+#include <deque>
+
+using namespace std;
+
+typedef unsigned int uint32;
+class MPQArchive
+{
+
+public:
+ mpq_archive mpq_a;
+
+ MPQArchive(const char* filename);
+ void close();
+
+ uint32 HashString(const char* Input, uint32 Offset) {
+ uint32 seed1 = 0x7fed7fed;
+ uint32 seed2 = 0xeeeeeeee;
+
+ for (uint32 i = 0; i < strlen(Input); i++) {
+ uint32 val = toupper(Input[i]);
+ seed1 = mpq_a.buf[Offset + val] ^ (seed1 + seed2);
+ seed2 = val + seed1 + seed2 + (seed2 << 5) + 3;
+ }
+
+ return seed1;
+ }
+ mpq_hash GetHashEntry(const char* Filename) {
+ uint32 index = HashString(Filename, 0);
+ index &= mpq_a.header->hashtablesize - 1;
+ uint32 name1 = HashString(Filename, 0x100);
+ uint32 name2 = HashString(Filename, 0x200);
+
+ for(uint32 i = index; i < mpq_a.header->hashtablesize; ++i) {
+ mpq_hash hash = mpq_a.hashtable[i];
+ if (hash.name1 == name1 && hash.name2 == name2) return hash;
+ }
+
+ mpq_hash nullhash;
+ nullhash.blockindex = 0xFFFFFFFF;
+ return nullhash;
+ }
+
+ vector<string> GetFileList() {
+ vector<string> filelist;
+
+ mpq_hash hash = GetHashEntry("(listfile)");
+ uint32 blockindex = hash.blockindex;
+
+ if ((blockindex == 0xFFFFFFFF) || (blockindex == 0))
+ return filelist;
+
+ uint32 size = libmpq_file_info(&mpq_a, LIBMPQ_FILE_UNCOMPRESSED_SIZE, blockindex);
+ char *buffer = new char[size];
+
+ libmpq_file_getdata(&mpq_a, hash, blockindex, (unsigned char*)buffer);
+
+ char seps[] = "\n";
+ char *token;
+
+ token = strtok( buffer, seps );
+ uint32 counter = 0;
+ while ((token != NULL) && (counter < size)) {
+ //cout << token << endl;
+ token[strlen(token) - 1] = 0;
+ string s = token;
+ filelist.push_back(s);
+ counter += strlen(token) + 2;
+ token = strtok(NULL, seps);
+ }
+
+ delete buffer;
+ return filelist;
+ }
+};
+typedef std::deque<MPQArchive*> ArchiveSet;
+
+class MPQFile
+{
+ //MPQHANDLE handle;
+ bool eof;
+ char *buffer;
+ size_t pointer,size;
+
+ // disable copying
+ MPQFile(const MPQFile &f) {}
+ void operator=(const MPQFile &f) {}
+
+public:
+ MPQFile(const char* filename); // filenames are not case sensitive
+ ~MPQFile() { close(); }
+ size_t read(void* dest, size_t bytes);
+ size_t getSize() { return size; }
+ size_t getPos() { return pointer; }
+ char* getBuffer() { return buffer; }
+ char* getPointer() { return buffer + pointer; }
+ bool isEof() { return eof; }
+ void seek(int offset);
+ void seekRelative(int offset);
+ void close();
+};
+
+inline void flipcc(char *fcc)
+{
+ char t;
+ t=fcc[0];
+ fcc[0]=fcc[3];
+ fcc[3]=t;
+ t=fcc[1];
+ fcc[1]=fcc[2];
+ fcc[2]=t;
+}
+
+#endif
diff --git a/contrib/extractor/release/zlib.lib b/contrib/extractor/release/zlib.lib
new file mode 100644
index 00000000000..42dded3ce23
--- /dev/null
+++ b/contrib/extractor/release/zlib.lib
Binary files differ