HIGHLY EXPERIMENTAL - USE AT YOUR OWN RISK

Implement the use of the new vmap3-format by Lynx3d (mad props to you for this, and thanks for the talks earlier)
+ reduced Vmap size to less than one third, and improve precision
+ indoor/outdoor check which allows automatic unmounting of players
+ additional area information from WMOAreaTable.dbc, removed existing "hacks"
+ WMO liquid information for swimming and fishing correctly in buildings/cities/caves/instances (lava and slime WILL hurt from now on!)
- buildfiles for windows are not properly done, and will need to be sorted out
NOTE: Do NOT annoy Lynx3d about this, any issues with this "port" is entirely our fault !
THIS REVISION IS CONSIDERED UNSTABLE AND CONTAINS WORK IN PROGRESS - USE AT YOUR OWN RISK!

--HG--
branch : trunk
This commit is contained in:
click
2010-06-05 00:59:25 +02:00
parent 1426c2970f
commit e777161888
566 changed files with 71675 additions and 153185 deletions
+10
View File
@@ -0,0 +1,10 @@
Project Initiator:
* Maik Broemme <[email protected]>
Developers:
* Maik Broemme <[email protected]>
* Tilman Sauerbeck <[email protected]>
* Forrest Voight <[email protected]>
* Georg Lukas <[email protected]>
+339
View File
@@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
Appendix: How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
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 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.
+68
View File
@@ -0,0 +1,68 @@
FAQ - Frequently Asked Questions
================================
Q: What is libmpq?
A: libmpq is a library for manipulating MoPaQ mpq archives mostly used
used by Blizzard in their games.
Q: What can i do with libmpq?
A: With libmpq you can write applications which can extract, create
and manipulate mpq archives.
Q: Is it legal?
A: Yes, i think so. I have no idea why it should not, all informations
about the fileformat are available.
Q: Is there a description of the functions?
A: Since version 0.4.0 libmpq comes with a API documentation for
developers. The documentation is written as manual pages.
Q: Can i help?
A: Yes, help is needed, not only with developing, also with testing.
A good point to start is using a recent SVN version of libmpq and
trying to use it with every mpq archive you could get :)
Q: Can you give a small example to demonstrate the usage?
A: Of course :) The example below takes first parameter as mpq archive
and extracts the first file to a buffer.
/*
* Compile with:
*
* x86_32:
*
* gcc \
* -D_FILE_OFFSET_BITS=64 \
* -D_LARGE_FILES=1 \
* -D_LARGEFILE_SOURCE=1 \
* mpq-example.c -o mpq-example -lmpq -lz -lbz2 -I/usr/local/include/libmpq
*
* x86_64:
*
* gcc \
* -D_LARGE_FILES=1 \
* mpq-example.c -o mpq-example -lmpq -lz -lbz2 -I/usr/local/include/libmpq
*/
#include <mpq.h>
#include <stdlib.h>
#include <limits.h>
int main(int argc, char **argv) {
mpq_archive_s *mpq_archive;
off_t out_size;
char *out_buf;
/* open the mpq archive given as first parameter. */
libmpq__archive_open(&mpq_archive, argv[1], -1);
/* get size of first file (0) and malloc output buffer. */
libmpq__file_unpacked_size(mpq_archive, 0, &out_size);
out_buf = malloc(out_size);
/* read, decrypt and unpack file to output buffer. */
libmpq__file_read(mpq_archive, 0, out_buf, out_size, NULL);
/* close the mpq archive. */
libmpq__archive_close(mpq_archive);
}
+26
View File
@@ -0,0 +1,26 @@
# minimum required automake 1.6
AUTOMAKE_OPTIONS = 1.6
# any directories which should be built and installed.
SUBDIRS = libmpq bindings doc
# the directories which are part of the distribution.
DIST_SUBDIRS = $(SUBDIRS)
# libmpq runtime configuration script.
bin_SCRIPTS = libmpq-config
# pkg-config installation directory.
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libmpq.pc
# extra stuff.
EXTRA_DIST = \
AUTHORS \
COPYING \
FAQ \
INSTALL \
NEWS \
README \
THANKS \
TODO
+76
View File
@@ -0,0 +1,76 @@
Changes version 0.4.2 (2008-05-16)
==================================
* added full extraction support for protected maps used in
warcraft 3.
* added full extraction support for all blizzard titles until
world of warcraft - the burning crusade.
* added support for archives version 2 with extended header and
extended block table.
* added support for the bzip2 compression algorithm.
* added support for archives and files inside archive > 2gb.
* added generic read functions, which will do decryption,
decompression or exploding.
* the info functions are no longer exported by the library and
were replaced by separate api functions.
* the file number and block number are count from 0 instead
of 1.
* added python bindings.
* linking against libmpq requires from now on the usual largefile
macros -D_FILE_OFFSET_BITS=64 -D_LARGE_FILES=1 -D_LARGEFILE_SOURCE=1
Changes version 0.4.1 (2008-04-02)
==================================
* memory, speed and stability improvements.
* split sourcecode into library and utility package.
Changes version 0.4.0 (2008-03-31)
==================================
* added robust error handling to make the library and extracting
utility more stable.
* added c++ bindings to public include and moved internal defines
and functions to private include.
* added support for 64-bit architectures and removed any stupid
pointer to int arithmetics.
* added much better member names to the structures to make
developers able to understand the code on reading.
* added full api documentation using manual pages.
* added full extraction support for all blizzard titles until
warcraft 3 - the frozen throne.
* added support for single sector and stored files (neither
compressed nor imploded).
* added support for files which have compressed size greater than
uncompressed size.
* removed the external listfile database support from 0.3.0 it
was a weird implementation.
Changes version 0.3.0 (2004-02-12)
==================================
* added listfile database support from external files.
Initial version 0.2.1 (2004-01-17)
==================================
* first version which was able to extract some of the older mopaq
archives.
+34
View File
@@ -0,0 +1,34 @@
Introduction
============
'libmpq' is a library which can be easily used in own applications
to extract, create or manipulate MoPaQ mpq archives.
MPQ, or MoPaQ, is a proprietary archive format created by
Mike O'Brien, the man hailed as Blizzard's multiplayer engine
genius, back in 1996 as a general purpose archive for use with
Diablo, and named narcissistically for its creator
"Mike O'brien PaCK". The copyrights to it, however, are held by
Havas Interactive, Blizzard's parent company. The archive format
is used by many Blizzard titles like Diablo, Diablo 2, Starcraft,
Warcraft 2: BNE, a newer version in Warcraft 3 and World of
Warcraft (WoW).
Manual
======
Since version 0.4.0 the 'libmpq' package comes with a manpage for
every library function. If you use 'libmpq' first time it is a good
idea to read the `FAQ' file.
Reporting Bugs
==============
Bug reports for 'libmpq' can be send to me directly.
* Maik Broemme <[email protected]>
Enjoy!
Maik Broemme <[email protected]>
http://www.babelize.org/
+21
View File
@@ -0,0 +1,21 @@
'libmpq' was originaly created by Maik Broemme <[email protected]>
and i want to thank some people which helped by supplying knowledge, code or
something else.
* Romy Trompke <[email protected]>
- my lovely girlfriend for her patience
* Ladislav Zezula <[email protected]>
- stormlib creator
* Marko Friedemann <[email protected]>
- initial port of stormlib to linux
* Tom Amigo <[email protected]>
- first people who decrypts the MoPaQ archive format
* ShadowFlare <[email protected]>
- creator of the ShadowFlare MPQ API
* Justin Olbrantz (Quantam) <[email protected]>
- creator of the client using ShadowFlare MPQ API
+10
View File
@@ -0,0 +1,10 @@
Features and functionality which should be added in the future.
* Porting for big endian systems.
* Porting for Windows? :)
* Creating mpq archives.
* Brute all unknown filenames, Blizzard uses in their
archives.
Look at the AUTHORS file if you want help me with 'libmpq', or
if you have other interesting features which should be added.
+19
View File
@@ -0,0 +1,19 @@
#!/bin/sh
#
echo "Generating build information using aclocal, autoheader, automake and autoconf"
echo "This may take a while ..."
# Touch the timestamps on all the files since CVS messes them up
directory=`dirname $0`
touch $directory/configure.ac
# Regenerate configuration files
libtoolize --copy
aclocal
autoheader
automake --foreign --add-missing --copy
autoconf
# Run configure for this platform
#./configure $*
echo "Now you are ready to run ./configure"
+6
View File
@@ -0,0 +1,6 @@
# any directories which should be built and installed.
SUBDIRS = d
if HAVE_PYTHON
SUBDIRS += python
endif
+6
View File
@@ -0,0 +1,6 @@
# minimum required automake 1.6
AUTOMAKE_OPTIONS = 1.6
# install D binding to /usr/include/d by default
libmpq_includedir = $(includedir)/d
libmpq_include_HEADERS = mpq.d
+2
View File
@@ -0,0 +1,2 @@
[mpq.d]
type=sourcelibrary
+318
View File
@@ -0,0 +1,318 @@
/*
* mpq.d -- D programming language module for libmpq
*
* Copyright (c) 2008 Georg Lukas <[email protected]>
*
* 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.
*
* This module is written to support Phobos. Patches to allow binding to
* Tango are welcome.
*/
module mpq;
/* the following pragma does not work on DMD/Linux, generates a warning on
* GDC/Linux and has not been tested on Windows. Commented out for now. */
// pragma(lib, "libmpq");
import std.string; // for format() and toStringz()
import std.traits; // for ParameterTypeTuple!()
/* XXX: this assumes that libmpq is compiled with Large File Support on */
alias long off_t;
/* libmpq error return values */
const LIBMPQ_ERROR_OPEN = -1; /* open error on file. */
const LIBMPQ_ERROR_CLOSE = -2; /* close error on file. */
const LIBMPQ_ERROR_SEEK = -3; /* lseek error on file. */
const LIBMPQ_ERROR_READ = -4; /* read error on file. */
const LIBMPQ_ERROR_WRITE = -5; /* write error on file. */
const LIBMPQ_ERROR_MALLOC = -6; /* memory allocation error. */
const LIBMPQ_ERROR_FORMAT = -7; /* format errror. */
const LIBMPQ_ERROR_NOT_INITIALIZED = -8; /* init() wasn't called. */
const LIBMPQ_ERROR_SIZE = -9; /* buffer size is to small. */
const LIBMPQ_ERROR_EXIST = -10; /* file or block does not exist in archive. */
const LIBMPQ_ERROR_DECRYPT = -11; /* we don't know the decryption seed. */
const LIBMPQ_ERROR_UNPACK = -12; /* error on unpacking file. */
/** libmpq internal meta-data for an archive */
struct mpq_archive_s;
extern(C) {
/* libmpq__generic information about library. */
char *libmpq__version();
/* libmpq__generic mpq archive information. */
int libmpq__archive_open(mpq_archive_s **mpq_archive, char *mpq_filename, off_t archive_offset);
int libmpq__archive_close(mpq_archive_s *mpq_archive);
int libmpq__archive_packed_size(mpq_archive_s *mpq_archive, off_t *packed_size);
int libmpq__archive_unpacked_size(mpq_archive_s *mpq_archive, off_t *unpacked_size);
int libmpq__archive_offset(mpq_archive_s *mpq_archive, off_t *offset);
int libmpq__archive_version(mpq_archive_s *mpq_archive, uint *version_);
int libmpq__archive_files(mpq_archive_s *mpq_archive, uint *files);
/* libmpq__generic file processing functions. */
int libmpq__file_packed_size(mpq_archive_s *mpq_archive, uint file_number, off_t *packed_size);
int libmpq__file_unpacked_size(mpq_archive_s *mpq_archive, uint file_number, off_t *unpacked_size);
int libmpq__file_offset(mpq_archive_s *mpq_archive, uint file_number, off_t *offset);
int libmpq__file_blocks(mpq_archive_s *mpq_archive, uint file_number, uint *blocks);
int libmpq__file_encrypted(mpq_archive_s *mpq_archive, uint file_number, uint *encrypted);
int libmpq__file_compressed(mpq_archive_s *mpq_archive, uint file_number, uint *compressed);
int libmpq__file_imploded(mpq_archive_s *mpq_archive, uint file_number, uint *imploded);
int libmpq__file_number(mpq_archive_s *mpq_archive, char *filename, uint *number);
int libmpq__file_read(mpq_archive_s *mpq_archive, uint file_number, ubyte *out_buf, off_t out_size, off_t *transferred);
/* libmpq__generic block processing functions. */
int libmpq__block_open_offset(mpq_archive_s *mpq_archive, uint file_number);
int libmpq__block_close_offset(mpq_archive_s *mpq_archive, uint file_number);
int libmpq__block_unpacked_size(mpq_archive_s *mpq_archive, uint file_number, uint block_number, off_t *unpacked_size);
int libmpq__block_read(mpq_archive_s *mpq_archive, uint file_number, uint block_number, ubyte *out_buf, off_t out_size, off_t *transferred);
}
/** exception class for failed libmpq calls */
class MPQException : Exception {
const string[] Errors = [
"unknown error",
"open error on file",
"close error on file",
"lseek error on file",
"read error on file",
"write error on file",
"memory allocation error",
"format errror",
"init() wasn't called",
"buffer size is to small",
"file or block does not exist in archive",
"we don't know the decryption seed",
"error on unpacking file"];
public int errno;
this(char[] fnname = "unknown_function", int errno = 0) {
this.errno = errno;
if (-errno >= Errors.length)
errno = 0;
super(std.string.format("Error in %s(): %s (%d)",
fnname, Errors[-errno], errno));
}
}
/** template to wrap function calls and throw exceptions in case of error
*
* thanks for the idea to while(nan) blog,
* http://while-nan.blogspot.com/2007/06/wrapping-functions-for-fun-and-profit.html
*
* use: MPQ_CHECKERR(libmpq__archive_open)(&m, "foo.mpq", -1);
* returns the retval of archive_open on success;
* throws an MPQException on failure.
*
* @param Fn libmpq__function reference
* @param args libmpq__function parameters
* @return return value of libmpq__function on success
* @throw MPQException on error
*/
int MPQ_CHECKERR(alias Fn)(ParameterTypeTuple!(Fn) args)
{
int result = Fn(args);
if (result < 0) {
/* XXX: relying on non-specified stringof() behaviour */
throw new MPQException((&Fn).stringof[2..$], result);
}
return result;
}
/** mixin alias to wrap library functions into MPQ_CHECKERR.
*
* alias mpq.func_name(...) to MPQ_CHECKERR(libmpq__func_name)(...)
* @param func_name name of the function to be wrapped
*/
template MPQ_FUNC(char[] func_name) {
const char[] MPQ_FUNC = "alias MPQ_CHECKERR!(libmpq__" ~ func_name ~ ") " ~ func_name ~ ";";
}
alias libmpq__version libversion; /* must be direct alias because it returns char*, not error int */
mixin(MPQ_FUNC!("archive_open"));
mixin(MPQ_FUNC!("archive_close"));
mixin(MPQ_FUNC!("archive_packed_size"));
mixin(MPQ_FUNC!("archive_unpacked_size"));
mixin(MPQ_FUNC!("archive_offset"));
mixin(MPQ_FUNC!("archive_version"));
mixin(MPQ_FUNC!("archive_files"));
mixin(MPQ_FUNC!("file_packed_size"));
mixin(MPQ_FUNC!("file_unpacked_size"));
mixin(MPQ_FUNC!("file_offset"));
mixin(MPQ_FUNC!("file_blocks"));
mixin(MPQ_FUNC!("file_encrypted"));
mixin(MPQ_FUNC!("file_compressed"));
mixin(MPQ_FUNC!("file_imploded"));
mixin(MPQ_FUNC!("file_number"));
mixin(MPQ_FUNC!("file_read"));
mixin(MPQ_FUNC!("block_open_offset"));
mixin(MPQ_FUNC!("block_close_offset"));
mixin(MPQ_FUNC!("block_unpacked_size"));
mixin(MPQ_FUNC!("block_read"));
/** getter function named name for returning archive_* single values:
*
* <type> Archive.<name>() { return libmpq__archive_<name>() }
*
* @param type return type for the original function reference
* @param name name of the original function
* @param name2 name for the prototype (defaults to name, used for "version")
* @return getter function mixin
*/
template MPQ_A_GET(char[] type, char[] name, char[] name2 = name) {
const char[] MPQ_A_GET = type ~ " " ~ name2 ~ "() { " ~
type ~ " ret; " ~
"archive_" ~ name ~ "(m, &ret); return ret;" ~
"}";
}
/** wrapper class for an MPQ Archive
*
* syntax: auto a = new mpq.Archive("somefile.mpq");
*/
class Archive {
mpq_archive_s *m;
File listfile;
char[][] listfiledata;
this(char[] archivename, off_t offset = -1) {
archive_open(&m, toStringz(archivename), offset);
}
mixin(MPQ_A_GET!("off_t", "packed_size"));
mixin(MPQ_A_GET!("off_t", "unpacked_size"));
mixin(MPQ_A_GET!("off_t", "offset"));
mixin(MPQ_A_GET!("uint", "version", "version_"));
mixin(MPQ_A_GET!("uint", "files"));
~this() {
archive_close(m);
}
mpq_archive_s* archive() {
return m;
}
File opIndex(char[] fname) {
return new File(this, fname);
}
File opIndex(int fno) {
return new File(this, fno);
}
char[][] filelist() {
try {
if (!listfile) {
listfile = this["(listfile)"];
listfiledata = (cast(char[])listfile.read()).splitlines();
}
return listfiledata;
} catch (MPQException e) {
return [];
}
}
/+uint filenumber(char[] filename) {
try {
if (!listfile) {
listfile = this["(listfile)"];
listfiledata = (cast(char[])listfile.read()).splitlines();
}
return listfiledata;
} catch (MPQException e) {
return [];
}
}+/
}
/** getter function named name for returning file_* single values:
*
* <type> File.<name>() { return libmpq__file_<name>() }
*
* @param type return type for the original function reference
* @param name name of the original function
* @param name2 name for the prototype (defaults to name, used for "version")
* @return getter function mixin
*/
template MPQ_F_GET(char[] type, char[] name, char[] name2 = name) {
const char[] MPQ_F_GET = type ~ " " ~ name2 ~ "() { " ~
type ~ " ret; " ~
"file_" ~ name ~ "(am, fileno, &ret); " ~
"return ret;" ~
"}";
}
/** wrapper class for a single file in an MPQ Archive
*
* syntax:
* auto a = new mpq.Archive("somefile.mpq");
* auto f = a["(listfile)"];
* auto f2 = a[0];
* auto f3 = new File(a, "(listfile)");
*/
class File {
Archive a;
mpq_archive_s* am;
char[] filename;
uint fileno;
this(Archive a, int fileno) {
this.a = a;
this.am = a.archive();
if (fileno >= a.files) {
throw new MPQException(format("File(%d)", fileno),
LIBMPQ_ERROR_EXIST);
}
this.filename = format("file%04d.xxx", fileno);
this.fileno = fileno;
}
this(Archive a, char[] filename) {
this.a = a;
this.am = a.archive();
this.filename = filename;
/* this line will throw an exception when the file is not there */
mpq.file_number(am, toStringz(filename), &this.fileno);
}
mixin(MPQ_F_GET!("off_t", "packed_size"));
mixin(MPQ_F_GET!("off_t", "unpacked_size"));
mixin(MPQ_F_GET!("off_t", "offset"));
mixin(MPQ_F_GET!("uint", "blocks"));
mixin(MPQ_F_GET!("uint", "encrypted"));
mixin(MPQ_F_GET!("uint", "compressed"));
mixin(MPQ_F_GET!("uint", "imploded"));
uint no() { return fileno; }
char[] name() { return filename; }
ubyte[] read() {
ubyte[] content;
content.length = this.unpacked_size();
off_t trans;
mpq.file_read(am, fileno, content.ptr, content.length, &trans);
content.length = trans;
return content;
}
}
@@ -0,0 +1,5 @@
# minimum required automake 1.6
AUTOMAKE_OPTIONS = 1.6
# library information and headers which should not be installed.
python_PYTHON = mpq.py
+16
View File
@@ -0,0 +1,16 @@
#!/usr/bin/env python
from __future__ import division
import sys
import mpq
archive = mpq.Archive(sys.argv[1])
print "Name: %s" % sys.argv[1]
print "Version: %s" % archive.filename
print "Offset: %s" % archive.offset
print "Packed size: %s" % archive.packed_size
print "Unpacked size: %s" % archive.unpacked_size
print "Compression ratio: %s" % (archive.packed_size/archive.unpacked_size)
+322
View File
@@ -0,0 +1,322 @@
"""wrapper for libmpq"""
# 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.
import ctypes
import ctypes.util
import os
libmpq = ctypes.CDLL(ctypes.util.find_library("mpq"))
class Error(Exception):
pass
errors = {
-1: (IOError, "open"),
-2: (IOError, "close"),
-3: (IOError, "seek"),
-4: (IOError, "read"),
-5: (IOError, "write"),
-6: (MemoryError,),
-7: (Error, "file is not an mpq or is corrupted"),
-8: (AssertionError, "not initialized"),
-9: (AssertionError, "buffer size too small"),
-10: (IndexError, "file not in archive"),
-11: (AssertionError, "decrypt"),
-12: (AssertionError, "unpack"),
}
def check_error(result, func, arguments, errors=errors):
try:
error = errors[result]
except KeyError:
return result
else:
raise error[0](*error[1:])
libmpq.libmpq__version.restype = ctypes.c_char_p
libmpq.libmpq__archive_open.errcheck = check_error
libmpq.libmpq__archive_close.errcheck = check_error
libmpq.libmpq__archive_packed_size.errcheck = check_error
libmpq.libmpq__archive_unpacked_size.errcheck = check_error
libmpq.libmpq__archive_offset.errcheck = check_error
libmpq.libmpq__archive_version.errcheck = check_error
libmpq.libmpq__archive_files.errcheck = check_error
libmpq.libmpq__file_packed_size.errcheck = check_error
libmpq.libmpq__file_unpacked_size.errcheck = check_error
libmpq.libmpq__file_offset.errcheck = check_error
libmpq.libmpq__file_blocks.errcheck = check_error
libmpq.libmpq__file_encrypted.errcheck = check_error
libmpq.libmpq__file_compressed.errcheck = check_error
libmpq.libmpq__file_imploded.errcheck = check_error
libmpq.libmpq__file_number.errcheck = check_error
libmpq.libmpq__file_read.errcheck = check_error
libmpq.libmpq__block_open_offset.errcheck = check_error
libmpq.libmpq__block_close_offset.errcheck = check_error
libmpq.libmpq__block_unpacked_size.errcheck = check_error
libmpq.libmpq__block_read.errcheck = check_error
__version__ = libmpq.libmpq__version()
class Reader(object):
def __init__(self, file, libmpq=libmpq):
self._file = file
self._pos = 0
self._buf = []
self._cur_block = 0
libmpq.libmpq__block_open_offset(self._file._archive._mpq,
self._file.number)
def __iter__(self):
return self
def __repr__(self):
return "iter(%r)" % self._file
def seek(self, offset, whence=os.SEEK_SET, os=os):
if whence == os.SEEK_SET:
pass
elif whence == os.SEEK_CUR:
offset += self._pos
elif whence == os.SEEK_END:
offset += self._file.unpacked_size
else:
raise ValueError, "invalid whence"
if offset >= self._pos:
self.read(offset - self._pos)
else:
self._pos = 0
self._buf = []
self._cur_block = 0
self.read(offset)
def tell(self):
return self._pos
def _read_block(self, ctypes=ctypes, libmpq=libmpq):
block_size = ctypes.c_uint64()
libmpq.libmpq__block_unpacked_size(self._file._archive._mpq,
self._file.number, self._cur_block, ctypes.byref(block_size))
block_data = ctypes.create_string_buffer(block_size.value)
libmpq.libmpq__block_read(self._file._archive._mpq,
self._file.number, self._cur_block,
block_data, ctypes.c_uint64(len(block_data)), None)
self._buf.append(block_data.raw)
self._cur_block += 1
def read(self, size=-1):
while size < 0 or sum(map(len, self._buf)) < size:
if self._cur_block == self._file.blocks:
break
self._read_block()
buf = "".join(self._buf)
if size < 0:
ret = buf
self._buf = []
else:
ret = buf[:size]
self._buf = [buf[size:]]
self._pos += len(ret)
return ret
def readline(self, os=os):
line = []
while True:
char = self.read(1)
if char == "":
break
if char not in '\r\n' and line and line[-1] in '\r\n':
self.seek(-1, os.SEEK_CUR)
break
line.append(char)
return ''.join(line)
def next(self):
line = self.readline()
if not line:
raise StopIteration
return line
def readlines(self, sizehint=-1):
res = []
while sizehint < 0 or sum(map(len, res)) < sizehint:
line = self.readline()
if not line:
break
res.append(line)
return res
xreadlines = __iter__
def __del__(self, libmpq=libmpq):
libmpq.libmpq__block_close_offset(self._file._archive._mpq,
self._file.number)
class File(object):
def __init__(self, archive, number, ctypes=ctypes, libmpq=libmpq):
self._archive = archive
self.number = number
for name, atype in [
("packed_size", ctypes.c_uint64),
("unpacked_size", ctypes.c_uint64),
("offset", ctypes.c_uint64),
("blocks", ctypes.c_uint32),
("encrypted", ctypes.c_uint32),
("compressed", ctypes.c_uint32),
("imploded", ctypes.c_uint32),
]:
data = atype()
func = getattr(libmpq, "libmpq__file_"+name)
func(self._archive._mpq, self.number, ctypes.byref(data))
setattr(self, name, data.value)
def __str__(self, ctypes=ctypes, libmpq=libmpq):
data = ctypes.create_string_buffer(self.unpacked_size)
libmpq.libmpq__file_read(self._archive._mpq, self.number,
data, ctypes.c_uint64(len(data)), None)
return data.raw
def __repr__(self):
return "%r[%i]" % (self._archive, self.number)
def __iter__(self, Reader=Reader):
return Reader(self)
class Archive(object):
def __init__(self, source, ctypes=ctypes, File=File, libmpq=libmpq):
self._source = source
if isinstance(source, File):
assert not source.encrypted
assert not source.compressed
assert not source.imploded
self.filename = source._archive.filename
offset = source._archive.offset + source.offset
else:
self.filename = source
offset = -1
self._mpq = ctypes.c_void_p()
libmpq.libmpq__archive_open(ctypes.byref(self._mpq), self.filename,
ctypes.c_uint64(offset))
self._opened = True
for field_name, field_type in [
("packed_size", ctypes.c_uint64),
("unpacked_size", ctypes.c_uint64),
("offset", ctypes.c_uint64),
("version", ctypes.c_uint32),
("files", ctypes.c_uint32),
]:
func = getattr(libmpq, "libmpq__archive_" + field_name)
data = field_type()
func(self._mpq, ctypes.byref(data))
setattr(self, field_name, data.value)
def __del__(self, libmpq=libmpq):
if getattr(self, "_opened", False):
libmpq.libmpq__archive_close(self._mpq)
def __len__(self):
return self.files
def __contains__(self, item, ctypes=ctypes, libmpq=libmpq):
if isinstance(item, str):
data = ctypes.c_uint32()
try:
libmpq.libmpq__file_number(self._mpq, ctypes.c_char_p(item),
ctypes.byref(data))
except IndexError:
return False
return True
return 0 <= item < self.files
def __getitem__(self, item, ctypes=ctypes, File=File, libmpq=libmpq):
if isinstance(item, str):
data = ctypes.c_int()
libmpq.libmpq__file_number(self._mpq, ctypes.c_char_p(item),
ctypes.byref(data))
item = data.value
else:
if not 0 <= item < self.files:
raise IndexError, "file not in archive"
return File(self, item)
def __repr__(self):
return "mpq.Archive(%r)" % self._source
# Remove clutter - everything except Error and Archive.
del os, check_error, ctypes, errors, File, libmpq, Reader
if __name__ == "__main__":
import sys, random
archive = Archive(sys.argv[1])
print repr(archive)
for k, v in archive.__dict__.iteritems():
#if k[0] == '_': continue
print " " * (4 - 1), k, v
assert '(listfile)' in archive
assert 0 in archive
assert len(archive) == archive.files
files = [x.strip() for x in archive['(listfile)']]
files.extend(xrange(archive.files))
for key in files: #sys.argv[2:] if sys.argv[2:] else xrange(archive.files):
file = archive[key]
print
print " " * (4 - 1), repr(file)
for k, v in file.__dict__.iteritems():
#if k[0] == '_': continue
print " " * (8 - 1), k, v
a = str(file)
b = iter(file).read()
reader = iter(file)
c = []
while True:
l = random.randrange(1, 10)
d = reader.read(l)
if not d: break
assert len(d) <= l
c.append(d)
c = "".join(c)
d = []
reader.seek(0)
for line in reader:
d.append(line)
d = "".join(d)
assert a == b == c == d, map(hash, [a,b,c,d])
assert len(a) == file.unpacked_size
repr(iter(file))
reader.seek(0)
a = reader.readlines()
reader.seek(0)
b = list(reader)
assert a == b
+84
View File
@@ -0,0 +1,84 @@
# the autoconf initilization.
AC_INIT(libmpq, 0.4.2, [[email protected]], [libmpq])
# detect the canonical host and target build environment.
AC_CANONICAL_SYSTEM
# initialize autoconf and automake system.
AM_INIT_AUTOMAKE([no-dependencies])
AC_CONFIG_HEADERS([config.h:config.h.in])
# notices.
AC_PREREQ(2.53)
AC_REVISION($Revision: 1.6 $)
# checking for programs.
AC_PROG_LIBTOOL
AC_PROG_MAKE_SET
AC_PROG_CC
AC_SYS_LARGEFILE
AC_FUNC_FSEEKO
# check if we need to export some largefile flags.
if test "$enable_largefile" != no; then
if test "$ac_cv_sys_file_offset_bits" != 'no'; then
if test -z "$LFS_CFLAGS" ; then
LFS_CFLAGS="-D_FILE_OFFSET_BITS=$ac_cv_sys_file_offset_bits"
else
LFS_CFLAGS="$LFS_CFLAGS -D_FILE_OFFSET_BITS=$ac_cv_sys_file_offset_bits"
fi
fi
if test "$ac_cv_sys_large_files" != 'no'; then
if test -z "$LFS_CFLAGS" ; then
LFS_CFLAGS="-D_LARGE_FILES=1"
else
LFS_CFLAGS="$LFS_CFLAGS -D_LARGE_FILES=1"
fi
fi
if test "$ac_cv_sys_largefile_source" != 'no'; then
if test -z "$LFS_CFLAGS" ; then
LFS_CFLAGS="-D_LARGEFILE_SOURCE=1"
else
LFS_CFLAGS="$LFS_CFLAGS -D_LARGEFILE_SOURCE=1"
fi
fi
fi
# export largefile flags.
AC_SUBST(LFS_CFLAGS)
# check for zlib library.
AC_CHECK_HEADER([zlib.h], [], [AC_MSG_ERROR([*** zlib.h is required, install zlib header files])])
AC_CHECK_LIB([z], [inflateEnd], [], [AC_MSG_ERROR([*** inflateEnd is required, install zlib library files])])
# check for bzlib2 library.
AC_CHECK_HEADER([bzlib.h], [], [AC_MSG_ERROR([*** bzlib.h is required, install bzip2 header files])])
AC_CHECK_LIB([bz2], [BZ2_bzDecompressInit], [], [AC_MSG_ERROR([*** BZ2_bzDecompressInit is required, install bzip2 library files])])
# When we're running gcc 4 or greater, compile with -fvisibility=hidden.
AC_TRY_COMPILE([
#if !defined(__GNUC__) || (__GNUC__ < 4)
#error not gcc4
#endif
], [], [CFLAGS="$CFLAGS -fvisibility=hidden"])
# find python for binding
AM_PATH_PYTHON([2.4],,[:])
AM_CONDITIONAL([HAVE_PYTHON], [test "$PYTHON" != :])
# configuration files.
AC_CONFIG_FILES([libmpq.pc])
AC_CONFIG_FILES([libmpq-config],[chmod +x libmpq-config])
# creating files.
AC_OUTPUT([
Makefile
libmpq/Makefile
bindings/Makefile
bindings/d/Makefile
bindings/python/Makefile
doc/Makefile
doc/man1/Makefile
doc/man3/Makefile
tools/Makefile
])
+35
View File
@@ -0,0 +1,35 @@
libmpq (0.4.2-svn288-1) unstable; urgency=low
[ babyface ]
* Due to the nature of MPQ archives which can have valid block entries
* removed function libmpq__init() and libmpq__shutdown(), because they
are no longer required and libmpq__file_name(), because it is up to
the application to provide listfile support
* updated documentation to latest API changes
* removed API documentation for removed function prototypes
* removed no longer required files from target
[ forrestv ]
* mpq.py fix
* spelling - huffmann to huffman
* changed pkware/pkzip to pkzip and used constants instead of numbers
in extract.c
* sanified huffman decoder a bit
* cleanup + update of mpq.py
* Added support for library finding on platforms besides Linux.
* python bindings - sequence methods on Archive, example code
[ georg ]
* libmpq: file number search now continued over hashtable end
* debian debug package
-- Georg Lukas <[email protected]> Fri, 22 May 2009 22:38:26 +0200
libmpq (0.4.2-svn270-1) unstable; urgency=low
* First debian package
* compatible to new libmpq API (post 0.4.2)
* contains preliminary python-mpq package
-- Georg Lukas <[email protected]> Tue, 07 Oct 2008 14:38:58 +0200
+1
View File
@@ -0,0 +1 @@
7
+50
View File
@@ -0,0 +1,50 @@
Source: libmpq
Priority: extra
Maintainer: Georg Lukas <[email protected]>
Build-Depends: debhelper (>= 7), autotools-dev, libbz2-dev
Standards-Version: 3.7.3
Section: libs
Homepage: https://libmpq.org/
Package: libmpq-dev
Section: libdevel
Architecture: any
Depends: libmpq0 (= ${binary:Version})
Description: Headers for libmpq, a library for MoPaQ mpq archives
libmpq is a library for extracting and manipulating MoPaQ mpq archives.
This package provides header files and bindings for applications using
the libmpq library for the following languages:
* C
* Python
* D
Package: libmpq0
Section: libs
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: A library for extracting and manipulating MoPaQ mpq archives
MPQ, or MoPaQ, is a proprietary archive format created by
Mike O'Brien, the man hailed as Blizzard's multiplayer engine
genius, back in 1996 as a general purpose archive for use with
Diablo, and named narcissistically for its creator
"Mike O'brien PaCK". The copyrights to it, however, are held by
Havas Interactive, Blizzard's parent company. The archive format
is used by many Blizzard titles like Diablo, Diablo 2, Starcraft,
Warcraft 2: BNE, a newer version in Warcraft 3 and World of
Warcraft (WoW).
Package: libmpq0-dbg
Section: libdevel
Architecture: any
Depends: libmpq0 (= ${binary:Version})
Description: Debug symbols for libmpq0 library package
Package: python-mpq
Architecture: all
Depends: ${python:Depends}
XB-Python-Version: ${python:Versions}
XS-Python-Version: current
Description: Python bindings for libmpq, a library for MoPaQ mpq archives
libmpq is a library for extracting and manipulating MoPaQ mpq archives.
This package provides the python bindings for libmpq.
+23
View File
@@ -0,0 +1,23 @@
This package was debianized by Georg Lukas <[email protected]> on
Fri, 04 Jul 2008 18:17:08 +0200.
It was downloaded from <https://libmpq.org/>
Upstream Author:
Maik Broemme <[email protected]>
Copyright:
Copyright (C) 2008 Maik Broemme
License:
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.
The Debian packaging is (C) 2008, Georg Lukas <[email protected]> and
is licensed under the GPL, see `/usr/share/common-licenses/GPL'.
+6
View File
@@ -0,0 +1,6 @@
usr/bin
usr/lib
usr/lib/pkgconfig
usr/include
usr/share/man/man1
usr/share/man/man3
+6
View File
@@ -0,0 +1,6 @@
usr/bin/*
usr/include/*
usr/lib/lib*.a
usr/lib/pkgconfig/*
usr/lib/*.la
usr/share/man/man?/*
+1
View File
@@ -0,0 +1 @@
usr/lib
+6
View File
@@ -0,0 +1,6 @@
FAQ
NEWS
README
TODO
THANKS
AUTHORS
+1
View File
@@ -0,0 +1 @@
usr/lib/lib*.so*
+1
View File
@@ -0,0 +1 @@
usr/lib/python?.?
+112
View File
@@ -0,0 +1,112 @@
#!/usr/bin/make -f
# -*- makefile -*-
# Sample debian/rules that uses debhelper.
# This file was originally written by Joey Hess and Craig Small.
# As a special exception, when this file is copied by dh-make into a
# dh-make output file, you may use that output file without restriction.
# This special exception was added by Craig Small in version 0.37 of dh-make.
# Uncomment this to turn on verbose mode.
export DH_VERBOSE=1
# These are used for cross-compiling and for saving the configure script
# from having to guess our platform (since we know it already)
DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
ifneq ($(DEB_HOST_GNU_TYPE),$(DEB_BUILD_GNU_TYPE))
CROSS= --build $(DEB_BUILD_GNU_TYPE) --host $(DEB_HOST_GNU_TYPE)
else
CROSS= --build $(DEB_BUILD_GNU_TYPE)
endif
# shared library versions, option 1
version=2.0.5
major=2
# option 2, assuming the library is created as src/.libs/libfoo.so.2.0.5 or so
#version=`ls src/.libs/lib*.so.* | \
# awk '{if (match($$0,/[0-9]+\.[0-9]+\.[0-9]+$$/)) print substr($$0,RSTART)}'`
#major=`ls src/.libs/lib*.so.* | \
# awk '{if (match($$0,/\.so\.[0-9]+$$/)) print substr($$0,RSTART+4)}'`
config.status: configure
dh_testdir
# Add here commands to configure the package.
ifneq "$(wildcard /usr/share/misc/config.sub)" ""
cp -f /usr/share/misc/config.sub config.sub
endif
ifneq "$(wildcard /usr/share/misc/config.guess)" ""
cp -f /usr/share/misc/config.guess config.guess
endif
./configure $(CROSS) --prefix=/usr --mandir=\$${prefix}/share/man --infodir=\$${prefix}/share/info CFLAGS="$(CFLAGS)" LDFLAGS="-Wl,-z,defs"
build: build-stamp
build-stamp: config.status
dh_testdir
# Add here commands to compile the package.
$(MAKE)
touch $@
clean:
dh_testdir
dh_testroot
rm -f build-stamp
# Add here commands to clean up after the build process.
[ ! -f Makefile ] || $(MAKE) distclean
rm -f config.sub config.guess
dh_clean
install: build
dh_testdir
dh_testroot
dh_clean -k
dh_installdirs
# Add here commands to install the package into debian/tmp
$(MAKE) DESTDIR=$(CURDIR)/debian/tmp install
# Build architecture-independent files here.
binary-indep: build install
dh_pysupport usr/lib/python?.?/site-packages
# Build architecture-dependent files here.
binary-arch: build install
dh_testdir
dh_testroot
dh_installchangelogs
dh_installdocs
dh_installexamples
dh_install
# dh_installmenu
# dh_installdebconf
# dh_installlogrotate
# dh_installemacsen
# dh_installpam
# dh_installmime
# dh_installinit
# dh_installcron
# dh_installinfo
dh_installman
dh_link
dh_strip --dbg-package=libmpq0-dbg
dh_compress
dh_fixperms
# dh_perl
dh_makeshlibs
dh_installdeb
dh_shlibdeps
dh_gencontrol
dh_md5sums
dh_builddeb
binary: binary-indep binary-arch
.PHONY: build clean binary-indep binary-arch binary install
+5
View File
@@ -0,0 +1,5 @@
# minimum required automake 1.6
AUTOMAKE_OPTIONS = 1.6
# any directories which should be built and installed.
SUBDIRS = man1 man3
+9
View File
@@ -0,0 +1,9 @@
# minimum required automake 1.6
AUTOMAKE_OPTIONS = 1.6
# manual page directory.
EXTRA_DIST = $(man_MANS)
# manual pages for the installed binaries.
man_MANS = \
libmpq-config.1
+69
View File
@@ -0,0 +1,69 @@
.\" Copyright (c) 2003-2008 Maik Broemme <[email protected]>
.\"
.\" This is free documentation; 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.
.\"
.\" The GNU General Public License's references to "object code"
.\" and "executables" are to be interpreted as the output of any
.\" document formatting or typesetting system, including
.\" intermediate and printed output.
.\"
.\" This manual 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 manual; if not, write to the Free
.\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111,
.\" USA.
.TH libmpq 1 2008-02-10 "The MoPaQ archive library"
.SH NAME
libmpq-config \- script to get information about the installed version of libmpq.
.SH SYNOPSIS
.B libmpq-config
[\-\-prefix\fI[=DIR]\fP] [\-\-exec\-prefix\fI[=DIR]\fP] [\-\-version]
.br
[\-\-cflags] [\-\-libs] [\-\-static\-libs]
.SH DESCRIPTION
.PP
\fIlibmpq-config\fP is a tool that is used to determine the compiler and linker flags that should be used to compile and link programs that use \fIlibmpq\fP. Finally, it's also used internally by the .m4 macros for GNU autoconf that are included with \fIlibmpq\fP.
.SH OPTIONS
\fIlibmpq-config\fP accepts the following options:
.TP 8
.B \-\-version
.ti 15
Print the currently installed version of \fIlibmpq\fP on the standard output.
.TP 8
.B \-\-libs
.ti 15
Print the linker flags that are necessary to link \fIlibmpq\fP to a program.
.TP 8
.B \-\-static\-libs
.ti 15
Print the linker flags that are necessary to statically link \fIlibmpq\fP to a program.
.TP 8
.B \-\-cflags
.ti 15
Print the compiler flags that are necessary to compile a program that use \fIlibmpq\fP.
.TP 8
.B \-\-prefix=PREFIX
.ti 15
If specified, use PREFIX instead of the installation prefix that \fIlibmpq\fP was built with when computing the output for the \-\-cflags and \-\-libs options. This option is also used for the exec prefix if \-\-exec\-prefix was not specified. This option must be specified before any \-\-libs or \-\-cflags options.
.TP 8
.B \-\-exec\-prefix=PREFIX
.ti 15
If specified, use PREFIX instead of the installation exec prefix that \fIlibmpq\fP was built with when computing the output for the \-\-cflags and \-\-libs options. This option must be specified before any \-\-libs or \-\-cflags options.
.SH NOTE
Instead of using this configuration script you should better use the pkg-config version because this would be more platform independent and makes the usage within GNU autoconf much easier.
.SH SEE ALSO
\fBlibmpq\fR(3)
.SH AUTHOR
Check documentation.
.TP
libmpq is (c) 2003-2008
.B Maik Broemme <[email protected]>
.PP
The above e-mail address can be used to send bug reports, feedbacks or library enhancements.
+30
View File
@@ -0,0 +1,30 @@
# minimum required automake 1.6
AUTOMAKE_OPTIONS = 1.6
# manual page directory.
EXTRA_DIST = $(man_MANS)
# manual pages for the installed binaries.
man_MANS = \
libmpq.3 \
libmpq__archive_close.3 \
libmpq__archive_files.3 \
libmpq__archive_offset.3 \
libmpq__archive_open.3 \
libmpq__archive_packed_size.3 \
libmpq__archive_unpacked_size.3 \
libmpq__archive_version.3 \
libmpq__block_close_offset.3 \
libmpq__block_open_offset.3 \
libmpq__block_read.3 \
libmpq__block_unpacked_size.3 \
libmpq__file_blocks.3 \
libmpq__file_compressed.3 \
libmpq__file_encrypted.3 \
libmpq__file_imploded.3 \
libmpq__file_number.3 \
libmpq__file_offset.3 \
libmpq__file_packed_size.3 \
libmpq__file_read.3 \
libmpq__file_unpacked_size.3 \
libmpq__version.3
+204
View File
@@ -0,0 +1,204 @@
.\" Copyright (c) 2003-2008 Maik Broemme <[email protected]>
.\"
.\" This is free documentation; 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.
.\"
.\" The GNU General Public License's references to "object code"
.\" and "executables" are to be interpreted as the output of any
.\" document formatting or typesetting system, including
.\" intermediate and printed output.
.\"
.\" This manual 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 manual; if not, write to the Free
.\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111,
.\" USA.
.TH libmpq 3 2008-04-29 "The MoPaQ archive library"
.SH NAME
libmpq \- cross-platform C library for manipulating mpq archives.
.SH SYNOPSIS
.nf
.B
#include <mpq.h>
.sp
.BI "const char *libmpq__version();"
.sp
.BI "int32_t libmpq__archive_open("
.BI " mpq_archive_s **" "mpq_archive",
.BI " const char *" "mpq_filename",
.BI " off_t " "archive_offset"
.BI ");"
.sp
.BI "int32_t libmpq__archive_close("
.BI " mpq_archive_s *" "mpq_archive"
.BI ");"
.sp
.BI "int32_t libmpq__archive_packed_size("
.BI " mpq_archive_s *" "mpq_archive",
.BI " off_t *" "packed_size"
.BI ");"
.sp
.BI "int32_t libmpq__archive_unpacked_size("
.BI " mpq_archive_s *" "mpq_archive",
.BI " off_t *" "unpacked_size"
.BI ");"
.sp
.BI "int32_t libmpq__archive_offset("
.BI " mpq_archive_s *" "mpq_archive",
.BI " off_t *" "offset"
.BI ");"
.sp
.BI "int32_t libmpq__archive_version("
.BI " mpq_archive_s *" "mpq_archive",
.BI " uint32_t *" "version"
.BI ");"
.sp
.BI "int32_t libmpq__archive_files("
.BI " mpq_archive_s *" "mpq_archive",
.BI " uint32_t *" "files"
.BI ");"
.sp
.BI "int32_t libmpq__file_packed_size("
.BI " mpq_archive_s *" "mpq_archive",
.BI " uint32_t " "file_number",
.BI " off_t *" "packed_size"
.BI ");"
.sp
.BI "int32_t libmpq__file_unpacked_size("
.BI " mpq_archive_s *" "mpq_archive",
.BI " uint32_t " "file_number",
.BI " off_t *" "unpacked_size"
.BI ");"
.sp
.BI "int32_t libmpq__file_offset("
.BI " mpq_archive_s *" "mpq_archive",
.BI " uint32_t " "file_number",
.BI " off_t *" "offset"
.BI ");"
.sp
.BI "int32_t libmpq__file_blocks("
.BI " mpq_archive_s *" "mpq_archive",
.BI " uint32_t " "file_number",
.BI " off_t *" "blocks"
.BI ");"
.sp
.BI "int32_t libmpq__file_encrypted("
.BI " mpq_archive_s *" "mpq_archive",
.BI " uint32_t " "file_number",
.BI " off_t *" "encrypted"
.BI ");"
.sp
.BI "int32_t libmpq__file_compressed("
.BI " mpq_archive_s *" "mpq_archive",
.BI " uint32_t " "file_number",
.BI " off_t *" "compressed"
.BI ");"
.sp
.BI "int32_t libmpq__file_imploded("
.BI " mpq_archive_s *" "mpq_archive",
.BI " uint32_t " "file_number",
.BI " off_t *" "imploded"
.BI ");"
.sp
.BI "int32_t libmpq__file_number("
.BI " mpq_archive_s *" "mpq_archive",
.BI " const char *" "filename",
.BI " uint32_t *" "number"
.BI ");"
.sp
.BI "int32_t libmpq__file_read("
.BI " mpq_archive_s *" "mpq_archive",
.BI " uint32_t " "file_number",
.BI " uint8_t *" "out_buf",
.BI " off_t " "out_size",
.BI " off_t *" "transferred"
.BI ");"
.sp
.BI "int32_t libmpq__block_open_offset("
.BI " mpq_archive_s *" "mpq_archive",
.BI " uint32_t " "file_number"
.BI ");"
.sp
.BI "int32_t libmpq__block_close_offset("
.BI " mpq_archive_s *" "mpq_archive",
.BI " uint32_t " "file_number"
.BI ");"
.sp
.BI "int32_t libmpq__block_packed_size("
.BI " mpq_archive_s *" "mpq_archive",
.BI " uint32_t " "file_number",
.BI " uint32_t " "block_number",
.BI " off_t *" "packed_size"
.BI ");"
.sp
.BI "int32_t libmpq__block_unpacked_size("
.BI " mpq_archive_s *" "mpq_archive",
.BI " uint32_t " "file_number",
.BI " uint32_t " "block_number",
.BI " off_t *" "unpacked_size"
.BI ");"
.sp
.BI "int32_t libmpq__block_offset("
.BI " mpq_archive_s *" "mpq_archive",
.BI " uint32_t " "file_number",
.BI " uint32_t " "block_number",
.BI " off_t *" "offset"
.BI ");"
.sp
.BI "int32_t libmpq__block_seed("
.BI " mpq_archive_s *" "mpq_archive",
.BI " uint32_t " "file_number",
.BI " uint32_t " "block_number",
.BI " uint32_t *" "seed"
.BI ");"
.sp
.BI "int32_t libmpq__block_read("
.BI " mpq_archive_s *" "mpq_archive",
.BI " uint32_t " "file_number",
.BI " uint32_t " "block_number",
.BI " uint8_t *" "out_buf",
.BI " off_t " "out_size",
.BI " off_t *" "transferred"
.BI ");"
.fi
.SH DESCRIPTION
.PP
The \fIlibmpq\fP library supports decrypting, decompressing, exploding and various manipulations of the MoPaQ archive files. It uses \fIzlib(3)\fP and \fIbzip2(1)\fP compression library. At this moment \fIlibmpq\fP is not able to create MoPaQ archives, this limitation will be removed in a future version.
.SH SEE ALSO
.BR libmpq__version (3),
.BR libmpq__archive_open (3),
.BR libmpq__archive_close (3),
.BR libmpq__archive_packed_size (3),
.BR libmpq__archive_unpacked_size (3),
.BR libmpq__archive_offset (3),
.BR libmpq__archive_version (3),
.BR libmpq__archive_files (3),
.BR libmpq__file_packed_size (3),
.BR libmpq__file_unpacked_size (3),
.BR libmpq__file_offset (3),
.BR libmpq__file_blocks (3),
.BR libmpq__file_encrypted (3),
.BR libmpq__file_compressed (3),
.BR libmpq__file_imploded (3),
.BR libmpq__file_number (3),
.BR libmpq__file_read (3),
.BR libmpq__block_open_offset (3),
.BR libmpq__block_close_offset (3),
.BR libmpq__block_packed_size (3),
.BR libmpq__block_unpacked_size (3),
.BR libmpq__block_offset (3),
.BR libmpq__block_seed (3),
.BR libmpq__block_read (3)
.SH AUTHOR
Check documentation.
.TP
libmpq is (c) 2003-2008
.B Maik Broemme <[email protected]>
.PP
The above e-mail address can be used to send bug reports, feedbacks or library enhancements.
@@ -0,0 +1,57 @@
.\" Copyright (c) 2003-2008 Maik Broemme <[email protected]>
.\"
.\" This is free documentation; 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.
.\"
.\" The GNU General Public License's references to "object code"
.\" and "executables" are to be interpreted as the output of any
.\" document formatting or typesetting system, including
.\" intermediate and printed output.
.\"
.\" This manual 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 manual; if not, write to the Free
.\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111,
.\" USA.
.TH libmpq 3 2008-04-29 "The MoPaQ archive library"
.SH NAME
libmpq \- cross-platform C library for manipulating mpq archives.
.SH SYNOPSIS
.nf
.B
#include <mpq.h>
.sp
.BI "int32_t libmpq__archive_close("
.BI " mpq_archive_s *" "mpq_archive"
.BI ");"
.fi
.SH DESCRIPTION
.PP
Call \fBlibmpq__archive_close\fP() to close a mpq archive which was opened by \fBlibmpq__archive_open\fP(). The function frees the archive structure itself and the contents of it.
.LP
The \fBlibmpq__archive_close\fP() function one takes one argument of the archive structure \fImpq_archive\fP which has to be set by \fBlibmpq__archive_open\fP.
.SH RETURN VALUE
On success, a zero is returned and on error one of the following constants.
.TP
.B LIBMPQ_ERROR_CLOSE
The given file could not be closed.
.SH SEE ALSO
.BR libmpq__archive_open (3),
.BR libmpq__archive_packed_size (3),
.BR libmpq__archive_unpacked_size (3),
.BR libmpq__archive_offset (3),
.BR libmpq__archive_version (3),
.BR libmpq__archive_files (3)
.SH AUTHOR
Check documentation.
.TP
libmpq is (c) 2003-2008
.B Maik Broemme <[email protected]>
.PP
The above e-mail address can be used to send bug reports, feedbacks or library enhancements.
@@ -0,0 +1,50 @@
.\" Copyright (c) 2003-2008 Maik Broemme <[email protected]>
.\"
.\" This is free documentation; 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.
.\"
.\" The GNU General Public License's references to "object code"
.\" and "executables" are to be interpreted as the output of any
.\" document formatting or typesetting system, including
.\" intermediate and printed output.
.\"
.\" This manual 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 manual; if not, write to the Free
.\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111,
.\" USA.
.TH libmpq 3 2008-05-14 "The MoPaQ archive library"
.SH NAME
libmpq \- cross-platform C library for manipulating mpq archives.
.SH SYNOPSIS
.nf
.B
#include <mpq.h>
.sp
.BI "int32_t libmpq__archive_files("
.BI " mpq_archive_s *" "mpq_archive",
.BI " uint32_t *" "files"
.BI ");"
.fi
.SH DESCRIPTION
.PP
Call \fBlibmpq__archive_files\fP() to get the number of files inside the archive. It will count only valid files and skip files which have deleted or freed hash entries.
.LP
The \fBlibmpq__archive_files\fP() function takes as first argument the archive structure \fImpq_archive\fP which have to be allocated first and opened by \fBlibmpq__archive_open\fP(). The second argument is a reference to the number of \fIfiles\fP in the archive.
.SH RETURN VALUE
On success, a zero is returned.
.SH SEE ALSO
.BR libmpq__file_blocks (3)
.SH AUTHOR
Check documentation.
.TP
libmpq is (c) 2003-2008
.B Maik Broemme <[email protected]>
.PP
The above e-mail address can be used to send bug reports, feedbacks or library enhancements.
@@ -0,0 +1,51 @@
.\" Copyright (c) 2003-2008 Maik Broemme <[email protected]>
.\"
.\" This is free documentation; 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.
.\"
.\" The GNU General Public License's references to "object code"
.\" and "executables" are to be interpreted as the output of any
.\" document formatting or typesetting system, including
.\" intermediate and printed output.
.\"
.\" This manual 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 manual; if not, write to the Free
.\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111,
.\" USA.
.TH libmpq 3 2008-05-14 "The MoPaQ archive library"
.SH NAME
libmpq \- cross-platform C library for manipulating mpq archives.
.SH SYNOPSIS
.nf
.B
#include <mpq.h>
.sp
.BI "int32_t libmpq__archive_offset("
.BI " mpq_archive_s *" "mpq_archive",
.BI " off_t *" "offset"
.BI ");"
.fi
.SH DESCRIPTION
.PP
Call \fBlibmpq__archive_offset\fP() to get the offset of the archive, which is the absolute position in the file. It also supports archives within archives.
.LP
The \fBlibmpq__archive_offset\fP() function takes as first argument the archive structure \fImpq_archive\fP which have to be allocated first and opened by \fBlibmpq__archive_open\fP(). The second argument is a reference to the archive starting position \fIoffset\fP in file.
.SH RETURN VALUE
On success, a zero is returned.
.SH SEE ALSO
.BR libmpq__file_offset (3),
.BR libmpq__block_offset (3)
.SH AUTHOR
Check documentation.
.TP
libmpq is (c) 2003-2008
.B Maik Broemme <[email protected]>
.PP
The above e-mail address can be used to send bug reports, feedbacks or library enhancements.
@@ -0,0 +1,71 @@
.\" Copyright (c) 2003-2008 Maik Broemme <[email protected]>
.\"
.\" This is free documentation; 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.
.\"
.\" The GNU General Public License's references to "object code"
.\" and "executables" are to be interpreted as the output of any
.\" document formatting or typesetting system, including
.\" intermediate and printed output.
.\"
.\" This manual 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 manual; if not, write to the Free
.\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111,
.\" USA.
.TH libmpq 3 2008-04-29 "The MoPaQ archive library"
.SH NAME
libmpq \- cross-platform C library for manipulating mpq archives.
.SH SYNOPSIS
.nf
.B
#include <mpq.h>
.sp
.BI "int32_t libmpq__archive_open("
.BI " mpq_archive_s **" "mpq_archive",
.BI " const char *" "mpq_filename",
.BI " off_t " "archive_offset"
.BI ");"
.fi
.SH DESCRIPTION
.PP
Call \fBlibmpq__archive_open\fP() to open a given mpq archive for later use to extract or manipulate files inside the archive. It will create all required file structures and you have to call \fBlibmpq__archive_close\fP() on success to clean the opened structures. On failure there is no need to call \fBlibmpq__archive_close\fP() because everything will be cleaned up.
.LP
The \fBlibmpq__archive_open\fP() function takes as first argument a reference to the archive structure \fImpq_archive\fP and will open the file \fImpq_filename\fP to the structure pointed to by \fImpq_archive\fP. The last argument, \fIarchive_offset\fP is normally -1, but can be specified when the archive offset is known, or not 512-byte aligned.
.SH RETURN VALUE
On success, *\fImpq_archive\fP is set to a new \fBmpq_archive_s\fP* and zero is returned, and on error one of the following constants is returned.
.TP
.B LIBMPQ_ERROR_OPEN
The given file could not be opened.
.TP
.B LIBMPQ_ERROR_MALLOC
Not enough memory for creating required structures.
.TP
.B LIBMPQ_ERROR_SEEK
Seeking in file failed.
.TP
.B LIBMPQ_ERROR_FORMAT
The given file is no valid mpq archive.
.TP
.B LIBMPQ_ERROR_READ
Reading in archive failed.
.SH SEE ALSO
.BR libmpq__archive_close (3),
.BR libmpq__archive_packed_size (3),
.BR libmpq__archive_unpacked_size (3),
.BR libmpq__archive_offset (3),
.BR libmpq__archive_version (3),
.BR libmpq__archive_files (3)
.SH AUTHOR
Check documentation.
.TP
libmpq is (c) 2003-2008
.B Maik Broemme <[email protected]>
.PP
The above e-mail address can be used to send bug reports, feedbacks or library enhancements.
@@ -0,0 +1,51 @@
.\" Copyright (c) 2003-2008 Maik Broemme <[email protected]>
.\"
.\" This is free documentation; 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.
.\"
.\" The GNU General Public License's references to "object code"
.\" and "executables" are to be interpreted as the output of any
.\" document formatting or typesetting system, including
.\" intermediate and printed output.
.\"
.\" This manual 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 manual; if not, write to the Free
.\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111,
.\" USA.
.TH libmpq 3 2008-04-29 "The MoPaQ archive library"
.SH NAME
libmpq \- cross-platform C library for manipulating mpq archives.
.SH SYNOPSIS
.nf
.B
#include <mpq.h>
.sp
.BI "int32_t libmpq__archive_packed_size("
.BI " mpq_archive_s *" "mpq_archive",
.BI " off_t *" "packed_size"
.BI ");"
.fi
.SH DESCRIPTION
.PP
Call \fBlibmpq__archive_packed_size\fP() to get the packed size of all files in the archive. It will count compressed and imploded files as well as stored only.
.LP
The \fBlibmpq__archive_packed_size\fP() function takes as first argument the archive structure \fImpq_archive\fP which have to be allocated first and opened by \fBlibmpq__archive_open\fP(). The second argument is a reference to the compressed, imploded or stored size \fIpacked_size\fP of file.
.SH RETURN VALUE
On success, a zero is returned.
.SH SEE ALSO
.BR libmpq__file_packed_size (3),
.BR libmpq__block_packed_size (3)
.SH AUTHOR
Check documentation.
.TP
libmpq is (c) 2003-2008
.B Maik Broemme <[email protected]>
.PP
The above e-mail address can be used to send bug reports, feedbacks or library enhancements.
@@ -0,0 +1,51 @@
.\" Copyright (c) 2003-2008 Maik Broemme <[email protected]>
.\"
.\" This is free documentation; 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.
.\"
.\" The GNU General Public License's references to "object code"
.\" and "executables" are to be interpreted as the output of any
.\" document formatting or typesetting system, including
.\" intermediate and printed output.
.\"
.\" This manual 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 manual; if not, write to the Free
.\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111,
.\" USA.
.TH libmpq 3 2008-04-29 "The MoPaQ archive library"
.SH NAME
libmpq \- cross-platform C library for manipulating mpq archives.
.SH SYNOPSIS
.nf
.B
#include <mpq.h>
.sp
.BI "int32_t libmpq__archive_unpacked_size("
.BI " mpq_archive_s *" "mpq_archive",
.BI " off_t *" "unpacked_size"
.BI ");"
.fi
.SH DESCRIPTION
.PP
Call \fBlibmpq__archive_unpacked_size\fP() to get the unpacked size of all files in the archive. It will count uncompressed and exploded files as well as stored only.
.LP
The \fBlibmpq__archive_unpacked_size\fP() function takes as first argument the archive structure \fImpq_archive\fP which have to be allocated first and opened by \fBlibmpq__archive_open\fP(). The second argument is a reference to the uncompressed, exploded or stored size \fIunpacked_size\fP of file.
.SH RETURN VALUE
On success, a zero is returned.
.SH SEE ALSO
.BR libmpq__file_unpacked_size (3),
.BR libmpq__block_unpacked_size (3)
.SH AUTHOR
Check documentation.
.TP
libmpq is (c) 2003-2008
.B Maik Broemme <[email protected]>
.PP
The above e-mail address can be used to send bug reports, feedbacks or library enhancements.
@@ -0,0 +1,48 @@
.\" Copyright (c) 2003-2008 Maik Broemme <[email protected]>
.\"
.\" This is free documentation; 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.
.\"
.\" The GNU General Public License's references to "object code"
.\" and "executables" are to be interpreted as the output of any
.\" document formatting or typesetting system, including
.\" intermediate and printed output.
.\"
.\" This manual 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 manual; if not, write to the Free
.\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111,
.\" USA.
.TH libmpq 3 2008-05-14 "The MoPaQ archive library"
.SH NAME
libmpq \- cross-platform C library for manipulating mpq archives.
.SH SYNOPSIS
.nf
.B
#include <mpq.h>
.sp
.BI "int32_t libmpq__archive_version("
.BI " mpq_archive_s *" "mpq_archive",
.BI " uint32_t *" "version"
.BI ");"
.fi
.SH DESCRIPTION
.PP
Call \fBlibmpq__archive_version\fP() to get the archive version. Currently there exist two known versions, version 1 which supports archives until 2GB total size and version 2 which supports archives above 2GB total size and both are supported.
.LP
The \fBlibmpq__archive_version\fP() function takes as first argument the archive structure \fImpq_archive\fP which have to be allocated first and opened by \fBlibmpq__archive_open\fP(). The second argument is a reference to the \fIversion\fP of archive.
.SH RETURN VALUE
On success, a zero is returned.
.SH AUTHOR
Check documentation.
.TP
libmpq is (c) 2003-2008
.B Maik Broemme <[email protected]>
.PP
The above e-mail address can be used to send bug reports, feedbacks or library enhancements.
@@ -0,0 +1,53 @@
.\" Copyright (c) 2003-2008 Maik Broemme <[email protected]>
.\"
.\" This is free documentation; 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.
.\"
.\" The GNU General Public License's references to "object code"
.\" and "executables" are to be interpreted as the output of any
.\" document formatting or typesetting system, including
.\" intermediate and printed output.
.\"
.\" This manual 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 manual; if not, write to the Free
.\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111,
.\" USA.
.TH libmpq 3 2008-05-16 "The MoPaQ archive library"
.SH NAME
libmpq \- cross-platform C library for manipulating mpq archives.
.SH SYNOPSIS
.nf
.B
#include <mpq.h>
.sp
.BI "int32_t libmpq__block_close_offset("
.BI " mpq_archive_s *" "mpq_archive",
.BI " uint32_t " "file_number"
.BI ");"
.fi
.SH DESCRIPTION
.PP
Call \fBlibmpq__block_close_offset\fP() to close the block offset table for the given file. It will close the block offset table regardless of compression (compressed, imploded or stored) type of file.
.LP
The \fBlibmpq__block_close_offset\fP() function takes as first argument the archive structure \fImpq_archive\fP which have to be allocated first and opened by \fBlibmpq__archive_open\fP(). The second argument \fIfile_number\fP is the number of file to close.
.SH RETURN VALUE
On success, a zero is returned and on error one of the following constants.
.TP
.B LIBMPQ_ERROR_EXIST
File or block does not exist in archive.
.SH SEE ALSO
.BR libmpq__block_open_offset (3)
.SH AUTHOR
Check documentation.
.TP
libmpq is (c) 2003-2008
.B Maik Broemme <[email protected]>
.PP
The above e-mail address can be used to send bug reports, feedbacks or library enhancements.
@@ -0,0 +1,65 @@
.\" Copyright (c) 2003-2008 Maik Broemme <[email protected]>
.\"
.\" This is free documentation; 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.
.\"
.\" The GNU General Public License's references to "object code"
.\" and "executables" are to be interpreted as the output of any
.\" document formatting or typesetting system, including
.\" intermediate and printed output.
.\"
.\" This manual 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 manual; if not, write to the Free
.\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111,
.\" USA.
.TH libmpq 3 2008-05-16 "The MoPaQ archive library"
.SH NAME
libmpq \- cross-platform C library for manipulating mpq archives.
.SH SYNOPSIS
.nf
.B
#include <mpq.h>
.sp
.BI "int32_t libmpq__block_open_offset("
.BI " mpq_archive_s *" "mpq_archive",
.BI " uint32_t " "file_number"
.BI ");"
.fi
.SH DESCRIPTION
.PP
Call \fBlibmpq__block_open_offset\fP() to open the block offset table for the given file. It will open the block offset table regardless of compression (compressed, imploded or stored) type of file.
.LP
The \fBlibmpq__block_open_offset\fP() function takes as first argument the archive structure \fImpq_archive\fP which have to be allocated first and opened by \fBlibmpq__archive_open\fP(). The second argument \fIfile_number\fP is the number of file to open.
.SH RETURN VALUE
On success, a zero is returned and on error one of the following constants.
.TP
.B LIBMPQ_ERROR_EXIST
File or block does not exist in archive.
.TP
.B LIBMPQ_ERROR_SEEK
Seeking in file failed.
.TP
.B LIBMPQ_ERROR_MALLOC
Not enough memory for creating required structures.
.TP
.B LIBMPQ_ERROR_READ
Reading in archive failed.
.TP
.B LIBMPQ_ERROR_DECRYPT
Decrypting block failed.
.SH SEE ALSO
.BR libmpq__block_close_offset (3)
.SH AUTHOR
Check documentation.
.TP
libmpq is (c) 2003-2008
.B Maik Broemme <[email protected]>
.PP
The above e-mail address can be used to send bug reports, feedbacks or library enhancements.
@@ -0,0 +1,78 @@
.\" Copyright (c) 2003-2008 Maik Broemme <[email protected]>
.\"
.\" This is free documentation; 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.
.\"
.\" The GNU General Public License's references to "object code"
.\" and "executables" are to be interpreted as the output of any
.\" document formatting or typesetting system, including
.\" intermediate and printed output.
.\"
.\" This manual 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 manual; if not, write to the Free
.\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111,
.\" USA.
.TH libmpq 3 2008-05-16 "The MoPaQ archive library"
.SH NAME
libmpq \- cross-platform C library for manipulating mpq archives.
.SH SYNOPSIS
.nf
.B
#include <mpq.h>
.sp
.BI "int32_t libmpq__block_read("
.BI " mpq_archive_s *" "mpq_archive",
.BI " uint32_t " "file_number",
.BI " uint32_t " "block_number,
.BI " uint8_t *" "out_buf",
.BI " off_t " "out_size",
.BI " off_t " "transferred"
.BI ");"
.fi
.SH DESCRIPTION
.PP
Call \fBlibmpq__block_read\fP() to read a given block into memory. If the block is encrypted it will be first decrypted and then if it is packed (compressed or imploded) it will be unpacked.
.LP
The \fBlibmpq__block_read\fP() function takes as first argument the archive structure \fImpq_archive\fP which have to be allocated first and opened by \fBlibmpq__archive_open\fP(). The second argument \fIfile_number\fP is the number of file, the third argument \fIblock_number\fP is the number of block. The fourth argument \fIout_buf\fP is the output data buffer which contains the extracted data and the fifth argument \fIout_size\fP is the size of \fIout_buf\fP. The sixth argument is a reference to the \fItransferred\fP bytes of the file.
.SH RETURN VALUE
On success, a zero is returned and on error one of the following constants.
.TP
.B LIBMPQ_ERROR_EXIST
Block does not exist in archive.
.TP
.B LIBMPQ_ERROR_OPEN
Block offset table was not opened by calling \fBlibmpq__block_open_offset\fP(), or it was closed by an \fBlibmpq__block_close_offset\fP() call.
.TP
.B LIBMPQ_ERROR_SIZE
The output buffer is to small.
.TP
.B LIBMPQ_ERROR_SEEK
Seeking in file failed.
.TP
.B LIBMPQ_ERROR_MALLOC
Not enough memory for creating required structures.
.TP
.B LIBMPQ_ERROR_READ
Reading in archive failed.
.TP
.B LIBMPQ_ERROR_DECRYPT
Decrypting block failed.
.TP
.B LIBMPQ_ERROR_UNPACK
Unpacking block failed.
.SH SEE ALSO
.BR libmpq__file_read (3)
.SH AUTHOR
Check documentation.
.TP
libmpq is (c) 2003-2008
.B Maik Broemme <[email protected]>
.PP
The above e-mail address can be used to send bug reports, feedbacks or library enhancements.
@@ -0,0 +1,59 @@
.\" Copyright (c) 2003-2008 Maik Broemme <[email protected]>
.\"
.\" This is free documentation; 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.
.\"
.\" The GNU General Public License's references to "object code"
.\" and "executables" are to be interpreted as the output of any
.\" document formatting or typesetting system, including
.\" intermediate and printed output.
.\"
.\" This manual 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 manual; if not, write to the Free
.\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111,
.\" USA.
.TH libmpq 3 2008-05-16 "The MoPaQ archive library"
.SH NAME
libmpq \- cross-platform C library for manipulating mpq archives.
.SH SYNOPSIS
.nf
.B
#include <mpq.h>
.sp
.BI "int32_t libmpq__block_unpacked_size("
.BI " mpq_archive_s *" "mpq_archive",
.BI " uint32_t " "file_number",
.BI " uint32_t " "block_number",
.BI " off_t *" "unpacked_size"
.BI ");"
.fi
.SH DESCRIPTION
.PP
Call \fBlibmpq__block_unpacked_size\fP() to get the unpacked size of a given block in the file. It will return a valid size for compressed and imploded blocks as well as stored only.
.LP
The \fBlibmpq__block_unpacked_size\fP() function takes as first argument the archive structure \fImpq_archive\fP which have to be allocated first and opened by \fBlibmpq__archive_open\fP(). The second argument \fIfile_number\fP is the number of file, the third argument \fIblock_number\fP is the number of block and the fourth argument is a reference to the uncompressed, exploded or stored size \fIunpacked_size\fP of block.
.SH RETURN VALUE
On success, a zero is returned and on error one of the following constants.
.TP
.B LIBMPQ_ERROR_EXIST
File or block does not exist in archive.
.TP
.B LIBMPQ_ERROR_OPEN
Block offset table was not opened by calling \fBlibmpq__block_open_offset\fP(), or it was closed by an \fBlibmpq__block_close_offset\fP() call.
.SH SEE ALSO
.BR libmpq__archive_unpacked_size (3),
.BR libmpq__file_unpacked_size (3)
.SH AUTHOR
Check documentation.
.TP
libmpq is (c) 2003-2008
.B Maik Broemme <[email protected]>
.PP
The above e-mail address can be used to send bug reports, feedbacks or library enhancements.
@@ -0,0 +1,54 @@
.\" Copyright (c) 2003-2008 Maik Broemme <[email protected]>
.\"
.\" This is free documentation; 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.
.\"
.\" The GNU General Public License's references to "object code"
.\" and "executables" are to be interpreted as the output of any
.\" document formatting or typesetting system, including
.\" intermediate and printed output.
.\"
.\" This manual 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 manual; if not, write to the Free
.\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111,
.\" USA.
.TH libmpq 3 2008-05-16 "The MoPaQ archive library"
.SH NAME
libmpq \- cross-platform C library for manipulating mpq archives.
.SH SYNOPSIS
.nf
.B
#include <mpq.h>
.sp
.BI "int32_t libmpq__file_blocks("
.BI " mpq_archive_s *" "mpq_archive",
.BI " uint32_t " "file_number",
.BI " uint32_t *" "blocks"
.BI ");"
.fi
.SH DESCRIPTION
.PP
Call \fBlibmpq__file_blocks\fP() to get the number of blocks for a given file. It will count all blocks for files stored in multiple sectors or count one for files stored in single sector.
.LP
The \fBlibmpq__file_blocks\fP() function takes as first argument the archive structure \fImpq_archive\fP which have to be allocated first and opened by \fBlibmpq__archive_open\fP(). The second argument \fIfile_number\fP is the number of file and the third argument is a reference to the number of \fIblocks\fP of the file.
.SH RETURN VALUE
On success, a zero is returned and on error one of the following constants.
.TP
.B LIBMPQ_ERROR_EXIST
File does not exist in archive.
.SH SEE ALSO
.BR libmpq__archive_files (3)
.SH AUTHOR
Check documentation.
.TP
libmpq is (c) 2003-2008
.B Maik Broemme <[email protected]>
.PP
The above e-mail address can be used to send bug reports, feedbacks or library enhancements.
@@ -0,0 +1,54 @@
.\" Copyright (c) 2003-2008 Maik Broemme <[email protected]>
.\"
.\" This is free documentation; 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.
.\"
.\" The GNU General Public License's references to "object code"
.\" and "executables" are to be interpreted as the output of any
.\" document formatting or typesetting system, including
.\" intermediate and printed output.
.\"
.\" This manual 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 manual; if not, write to the Free
.\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111,
.\" USA.
.TH libmpq 3 2008-05-16 "The MoPaQ archive library"
.SH NAME
libmpq \- cross-platform C library for manipulating mpq archives.
.SH SYNOPSIS
.nf
.B
#include <mpq.h>
.sp
.BI "int32_t libmpq__file_compressed("
.BI " mpq_archive_s *" "mpq_archive",
.BI " uint32_t " "file_number",
.BI " uint32_t *" "compressed"
.BI ");"
.fi
.SH DESCRIPTION
.PP
Call \fBlibmpq__file_compressed\fP() to get the compression status of the given file. It will return true for compressed files and false otherwise.
.LP
The \fBlibmpq__file_compressed\fP() function takes as first argument the archive structure \fImpq_archive\fP which have to be allocated first and opened by \fBlibmpq__archive_open\fP(). The second argument \fIfile_number\fP is the number of file and the third argument is a reference to the compression status \fIcompressed\fP of the file.
.SH RETURN VALUE
On success, a zero is returned and on error one of the following constants.
.TP
.B LIBMPQ_ERROR_EXIST
File does not exist in archive.
.SH SEE ALSO
.BR libmpq__archive_files (3)
.SH AUTHOR
Check documentation.
.TP
libmpq is (c) 2003-2008
.B Maik Broemme <[email protected]>
.PP
The above e-mail address can be used to send bug reports, feedbacks or library enhancements.
@@ -0,0 +1,54 @@
.\" Copyright (c) 2003-2008 Maik Broemme <[email protected]>
.\"
.\" This is free documentation; 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.
.\"
.\" The GNU General Public License's references to "object code"
.\" and "executables" are to be interpreted as the output of any
.\" document formatting or typesetting system, including
.\" intermediate and printed output.
.\"
.\" This manual 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 manual; if not, write to the Free
.\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111,
.\" USA.
.TH libmpq 3 2008-05-16 "The MoPaQ archive library"
.SH NAME
libmpq \- cross-platform C library for manipulating mpq archives.
.SH SYNOPSIS
.nf
.B
#include <mpq.h>
.sp
.BI "int32_t libmpq__file_encrypted("
.BI " mpq_archive_s *" "mpq_archive",
.BI " uint32_t " "file_number",
.BI " uint32_t *" "encrypted"
.BI ");"
.fi
.SH DESCRIPTION
.PP
Call \fBlibmpq__file_encrypted\fP() to get the encryption status of the given file. It will return true for encrypted files and false otherwise.
.LP
The \fBlibmpq__file_encrypted\fP() function takes as first argument the archive structure \fImpq_archive\fP which have to be allocated first and opened by \fBlibmpq__archive_open\fP(). The second argument \fIfile_number\fP is the number of file and the third argument is a reference to the encryption status \fIencrypted\fP of the file.
.SH RETURN VALUE
On success, a zero is returned and on error one of the following constants.
.TP
.B LIBMPQ_ERROR_EXIST
File does not exist in archive.
.SH SEE ALSO
.BR libmpq__archive_files (3)
.SH AUTHOR
Check documentation.
.TP
libmpq is (c) 2003-2008
.B Maik Broemme <[email protected]>
.PP
The above e-mail address can be used to send bug reports, feedbacks or library enhancements.
@@ -0,0 +1,54 @@
.\" Copyright (c) 2003-2008 Maik Broemme <[email protected]>
.\"
.\" This is free documentation; 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.
.\"
.\" The GNU General Public License's references to "object code"
.\" and "executables" are to be interpreted as the output of any
.\" document formatting or typesetting system, including
.\" intermediate and printed output.
.\"
.\" This manual 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 manual; if not, write to the Free
.\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111,
.\" USA.
.TH libmpq 3 2008-05-16 "The MoPaQ archive library"
.SH NAME
libmpq \- cross-platform C library for manipulating mpq archives.
.SH SYNOPSIS
.nf
.B
#include <mpq.h>
.sp
.BI "int32_t libmpq__file_imploded("
.BI " mpq_archive_s *" "mpq_archive",
.BI " uint32_t " "file_number",
.BI " uint32_t *" "imploded"
.BI ");"
.fi
.SH DESCRIPTION
.PP
Call \fBlibmpq__file_imploded\fP() to get the implosion status of the given file. It will return true for imploded files and false otherwise.
.LP
The \fBlibmpq__file_imploded\fP() function takes as first argument the archive structure \fImpq_archive\fP which have to be allocated first and opened by \fBlibmpq__archive_open\fP(). The second argument \fIfile_number\fP is the number of file and the third argument is a reference to the implosion status \fIimploded\fP of the file.
.SH RETURN VALUE
On success, a zero is returned and on error one of the following constants.
.TP
.B LIBMPQ_ERROR_EXIST
File does not exist in archive.
.SH SEE ALSO
.BR libmpq__archive_files (3)
.SH AUTHOR
Check documentation.
.TP
libmpq is (c) 2003-2008
.B Maik Broemme <[email protected]>
.PP
The above e-mail address can be used to send bug reports, feedbacks or library enhancements.
@@ -0,0 +1,52 @@
.\" Copyright (c) 2003-2008 Maik Broemme <[email protected]>
.\"
.\" This is free documentation; 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.
.\"
.\" The GNU General Public License's references to "object code"
.\" and "executables" are to be interpreted as the output of any
.\" document formatting or typesetting system, including
.\" intermediate and printed output.
.\"
.\" This manual 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 manual; if not, write to the Free
.\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111,
.\" USA.
.TH libmpq 3 2008-05-16 "The MoPaQ archive library"
.SH NAME
libmpq \- cross-platform C library for manipulating mpq archives.
.SH SYNOPSIS
.nf
.B
#include <mpq.h>
.sp
.BI "int32_t libmpq__file_number("
.BI " mpq_archive_s *" "mpq_archive",
.BI " const char *" "filename",
.BI " uint32_t *" "number"
.BI ");"
.fi
.SH DESCRIPTION
.PP
Call \fBlibmpq__file_number\fP() to get the number of a given file in the archive. This function will return a file number regardless of a known or opened listfile.
.LP
The \fBlibmpq__file_number\fP() function takes as first argument the archive structure \fImpq_archive\fP which have to be allocated first and opened by \fBlibmpq__archive_open\fP(). The second argument \fIfilename\fP is the name of the file and the third argument is a reference to the \fInumber\fP of the file.
.SH RETURN VALUE
On success, the number of the file is returned and on error one of the following constants.
.TP
.B LIBMPQ_ERROR_EXIST
File does not exist in archive.
.SH AUTHOR
Check documentation.
.TP
libmpq is (c) 2003-2008
.B Maik Broemme <[email protected]>
.PP
The above e-mail address can be used to send bug reports, feedbacks or library enhancements.
@@ -0,0 +1,55 @@
.\" Copyright (c) 2003-2008 Maik Broemme <[email protected]>
.\"
.\" This is free documentation; 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.
.\"
.\" The GNU General Public License's references to "object code"
.\" and "executables" are to be interpreted as the output of any
.\" document formatting or typesetting system, including
.\" intermediate and printed output.
.\"
.\" This manual 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 manual; if not, write to the Free
.\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111,
.\" USA.
.TH libmpq 3 2008-05-15 "The MoPaQ archive library"
.SH NAME
libmpq \- cross-platform C library for manipulating mpq archives.
.SH SYNOPSIS
.nf
.B
#include <mpq.h>
.sp
.BI "int32_t libmpq__file_offset("
.BI " mpq_archive_s *" "mpq_archive",
.BI " uint32_t " "file_number",
.BI " off_t *" "offset"
.BI ");"
.fi
.SH DESCRIPTION
.PP
Call \fBlibmpq__file_offset\fP() to get the offset of the file, which is the absolute position in the archive. It also supports archives within archives.
.LP
The \fBlibmpq__file_offset\fP() function takes as first argument the archive structure \fImpq_archive\fP which have to be allocated first and opened by \fBlibmpq__archive_open\fP(). The second argument \fIfile_number\fP is the number of file and the third argument is a reference to the file starting position \fIoffset\fP in archive.
.SH RETURN VALUE
On success, a zero is returned and on error one of the following constants.
.TP
.B LIBMPQ_ERROR_EXIST
File does not exist in archive.
.SH SEE ALSO
.BR libmpq__archive_offset (3),
.BR libmpq__block_offset (3)
.SH AUTHOR
Check documentation.
.TP
libmpq is (c) 2003-2008
.B Maik Broemme <[email protected]>
.PP
The above e-mail address can be used to send bug reports, feedbacks or library enhancements.
@@ -0,0 +1,55 @@
.\" Copyright (c) 2003-2008 Maik Broemme <[email protected]>
.\"
.\" This is free documentation; 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.
.\"
.\" The GNU General Public License's references to "object code"
.\" and "executables" are to be interpreted as the output of any
.\" document formatting or typesetting system, including
.\" intermediate and printed output.
.\"
.\" This manual 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 manual; if not, write to the Free
.\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111,
.\" USA.
.TH libmpq 3 2008-05-15 "The MoPaQ archive library"
.SH NAME
libmpq \- cross-platform C library for manipulating mpq archives.
.SH SYNOPSIS
.nf
.B
#include <mpq.h>
.sp
.BI "int32_t libmpq__file_packed_size("
.BI " mpq_archive_s *" "mpq_archive",
.BI " uint32_t " "file_number",
.BI " off_t *" "packed_size"
.BI ");"
.fi
.SH DESCRIPTION
.PP
Call \fBlibmpq__file_packed_size\fP() to get the packed size of a given file in the archive. It will return a valid size for compressed and imploded files as well as stored only.
.LP
The \fBlibmpq__file_packed_size\fP() function takes as first argument the archive structure \fImpq_archive\fP which have to be allocated first and opened by \fBlibmpq__archive_open\fP(). The second argument \fIfile_number\fP is the number of file and the third argument is a reference to the compressed, imploded or stored size \fIpacked_size\fP of file.
.SH RETURN VALUE
On success, a zero is returned and on error one of the following constants.
.TP
.B LIBMPQ_ERROR_EXIST
File does not exist in archive.
.SH SEE ALSO
.BR libmpq__archive_packed_size (3),
.BR libmpq__block_packed_size (3)
.SH AUTHOR
Check documentation.
.TP
libmpq is (c) 2003-2008
.B Maik Broemme <[email protected]>
.PP
The above e-mail address can be used to send bug reports, feedbacks or library enhancements.
@@ -0,0 +1,77 @@
.\" Copyright (c) 2003-2008 Maik Broemme <[email protected]>
.\"
.\" This is free documentation; 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.
.\"
.\" The GNU General Public License's references to "object code"
.\" and "executables" are to be interpreted as the output of any
.\" document formatting or typesetting system, including
.\" intermediate and printed output.
.\"
.\" This manual 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 manual; if not, write to the Free
.\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111,
.\" USA.
.TH libmpq 3 2008-05-16 "The MoPaQ archive library"
.SH NAME
libmpq \- cross-platform C library for manipulating mpq archives.
.SH SYNOPSIS
.nf
.B
#include <mpq.h>
.sp
.BI "int32_t libmpq__file_read("
.BI " mpq_archive_s *" "mpq_archive",
.BI " uint32_t " "file_number",
.BI " uint8_t *" "out_buf",
.BI " off_t " "out_size",
.BI " off_t *" "transferred"
.BI ");"
.fi
.SH DESCRIPTION
.PP
Call \fBlibmpq__file_read\fP() to read a given file into memory. If the file is encrypted it will be first decrypted and then if it is packed (compressed or imploded) it will be unpacked.
.LP
The \fBlibmpq__file_read\fP() function takes as first argument the archive structure \fImpq_archive\fP which have to be allocated first and opened by \fBlibmpq__archive_open\fP(). The second argument \fIfile_number\fP is the file to extract, the third argument \fIout_buf\fP is the output data buffer which contains the extracted data. The fourth argument \fIout_size\fP is the size of \fIout_buf\fP and the fifth argument is a reference to the \fItransferred\fP bytes of the file.
.SH RETURN VALUE
On success, a zero is returned and on error one of the following constants.
.TP
.B LIBMPQ_ERROR_EXIST
File does not exist in archive.
.TP
.B LIBMPQ_ERROR_OPEN
Block offset table was not opened by calling \fBlibmpq__block_open_offset\fP(), or it was closed by an \fBlibmpq__block_close_offset\fP() call.
.TP
.B LIBMPQ_ERROR_SIZE
The output buffer is to small.
.TP
.B LIBMPQ_ERROR_SEEK
Seeking in file failed.
.TP
.B LIBMPQ_ERROR_MALLOC
Not enough memory for creating required structures.
.TP
.B LIBMPQ_ERROR_READ
Reading in archive failed.
.TP
.B LIBMPQ_ERROR_DECRYPT
Decrypting file failed.
.TP
.B LIBMPQ_ERROR_UNPACK
Unpacking file failed.
.SH SEE ALSO
.BR libmpq__block_read (3)
.SH AUTHOR
Check documentation.
.TP
libmpq is (c) 2003-2008
.B Maik Broemme <[email protected]>
.PP
The above e-mail address can be used to send bug reports, feedbacks or library enhancements.
@@ -0,0 +1,55 @@
.\" Copyright (c) 2003-2008 Maik Broemme <[email protected]>
.\"
.\" This is free documentation; 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.
.\"
.\" The GNU General Public License's references to "object code"
.\" and "executables" are to be interpreted as the output of any
.\" document formatting or typesetting system, including
.\" intermediate and printed output.
.\"
.\" This manual 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 manual; if not, write to the Free
.\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111,
.\" USA.
.TH libmpq 3 2008-05-15 "The MoPaQ archive library"
.SH NAME
libmpq \- cross-platform C library for manipulating mpq archives.
.SH SYNOPSIS
.nf
.B
#include <mpq.h>
.sp
.BI "int32_t libmpq__file_unpacked_size("
.BI " mpq_archive_s *" "mpq_archive",
.BI " uint32_t " "file_number",
.BI " off_t *" "unpacked_size"
.BI ");"
.fi
.SH DESCRIPTION
.PP
Call \fBlibmpq__file_unpacked_size\fP() to get the unpacked size of a given file in the archive. It will return a valid size for compressed and imploded files as well as stored only.
.LP
The \fBlibmpq__file_unpacked_size\fP() function takes as first argument the archive structure \fImpq_archive\fP which have to be allocated first and opened by \fBlibmpq__archive_open\fP(). The second argument \fIfile_number\fP is the number of file and the third argument is a reference to the uncompressed, exploded or stored size \fIunpacked_size\fP of file.
.SH RETURN VALUE
On success, a zero is returned and on error one of the following constants.
.TP
.B LIBMPQ_ERROR_EXIST
File does not exist in archive.
.SH SEE ALSO
.BR libmpq__archive_unpacked_size (3),
.BR libmpq__block_unpacked_size (3)
.SH AUTHOR
Check documentation.
.TP
libmpq is (c) 2003-2008
.B Maik Broemme <[email protected]>
.PP
The above e-mail address can be used to send bug reports, feedbacks or library enhancements.
+45
View File
@@ -0,0 +1,45 @@
.\" Copyright (c) 2003-2008 Maik Broemme <[email protected]>
.\"
.\" This is free documentation; 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.
.\"
.\" The GNU General Public License's references to "object code"
.\" and "executables" are to be interpreted as the output of any
.\" document formatting or typesetting system, including
.\" intermediate and printed output.
.\"
.\" This manual 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 manual; if not, write to the Free
.\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111,
.\" USA.
.TH libmpq 3 2008-03-31 "The MoPaQ archive library"
.SH NAME
libmpq \- cross-platform C library for manipulating mpq archives.
.SH SYNOPSIS
.nf
.B
#include <mpq.h>
.sp
.BI "const char *libmpq__version();"
.fi
.SH DESCRIPTION
.PP
Call \fBlibmpq__version\fP() to get information about the version of the library, it is useful to create minimum required version verifications.
.SH RETURN VALUE
The function returns the library version.
.SH SEE ALSO
.BR libmpq (3)
.SH AUTHOR
Check documentation.
.TP
libmpq is (c) 2003-2008
.B Maik Broemme <[email protected]>
.PP
The above e-mail address can be used to send bug reports, feedbacks or library enhancements.
+57
View File
@@ -0,0 +1,57 @@
#!/bin/sh
prefix="@prefix@"
exec_prefix="@exec_prefix@"
exec_prefix_set=no
usage="\
Usage: libmpq-config [--prefix[=DIR]] [--exec-prefix[=DIR]] [--version] [--libs] [--cflags]"
if test "$#" -eq "0"; then
echo "${usage}" 1>&2
exit 1
fi
while test "$#" -gt "0"; do
case "$1" in
-*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
*) optarg= ;;
esac
case "$1" in
--prefix=*)
prefix="$optarg"
if test "$exec_prefix_set" = "no" ; then
exec_prefix="$optarg"
fi
;;
--prefix)
echo "$prefix"
;;
--exec-prefix=*)
exec_prefix="$optarg"
exec_prefix_set=yes
;;
--exec-prefix)
echo "$exec_prefix"
;;
--version)
echo "@VERSION@"
;;
--cflags)
largefile="@LFS_CFLAGS@"
includes=-I@includedir@/libmpq
echo "$includes $largefile"
;;
--libs)
libdirs="-L@libdir@"
echo "$libdirs -lmpq"
;;
*)
echo "${usage}" 1>&2
exit 1
;;
esac
shift
done
+10
View File
@@ -0,0 +1,10 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: libmpq
Description: GPL version of the libmpq library
Version: @VERSION@
Libs: -L${libdir} -lmpq
Cflags: -I${includedir}/libmpq @LFS_CFLAGS@
+23
View File
@@ -0,0 +1,23 @@
# minimum required automake 1.6
AUTOMAKE_OPTIONS = 1.6
# library information and headers which should not be installed.
lib_LTLIBRARIES = libmpq.la
noinst_HEADERS = common.h explode.h extract.h huffman.h mpq-internal.h wave.h
# directory where the include files will be installed.
libmpq_includedir = $(includedir)/libmpq
# header files to install.
libmpq_include_HEADERS = mpq.h
libmpq_la_SOURCES = $(GENERAL_SRCS)
libmpq_la_LDFLAGS = -release $(PACKAGE_VERSION)
GENERAL_SRCS = \
common.c \
huffman.c \
extract.c \
explode.c \
mpq.c \
wave.c
+222
View File
@@ -0,0 +1,222 @@
/*
* common.c -- shared functions used by mpq-tools.
*
* Copyright (c) 2003-2008 Maik Broemme <[email protected]>
*
* 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.
*/
/* generic includes. */
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
/* libmpq main includes. */
#include "mpq.h"
#include "mpq-internal.h"
/* libmpq generic includes. */
#include "extract.h"
#include "common.h"
/* the global shared decryption buffer. it's a static array compiled into the
* library, and can be re-created by compiling and running crypt_buf_gen.c
*/
#include "crypt_buf.h"
/* function to return the hash to a given string. */
uint32_t libmpq__hash_string(const char *key, uint32_t offset) {
/* some common variables. */
uint32_t seed1 = 0x7FED7FED;
uint32_t seed2 = 0xEEEEEEEE;
/* one key character. */
uint32_t ch;
/* prepare seeds. */
while (*key != 0) {
ch = toupper(*key++);
seed1 = crypt_buf[offset + ch] ^ (seed1 + seed2);
seed2 = ch + seed1 + seed2 + (seed2 << 5) + 3;
}
return seed1;
}
/* function to encrypt a block. */
int32_t libmpq__encrypt_block(uint32_t *in_buf, uint32_t in_size, uint32_t seed) {
/* some common variables. */
uint32_t seed2 = 0xEEEEEEEE;
uint32_t ch;
/* we're processing the data 4 bytes at a time. */
for (; in_size >= 4; in_size -= 4) {
seed2 += crypt_buf[0x400 + (seed & 0xFF)];
ch = *in_buf ^ (seed + seed2);
seed = ((~seed << 0x15) + 0x11111111) | (seed >> 0x0B);
seed2 = *in_buf + seed2 + (seed2 << 5) + 3;
*in_buf++ = ch;
}
/* if no error was found, return decrypted bytes. */
return LIBMPQ_SUCCESS;
}
/* function to decrypt a block. */
int32_t libmpq__decrypt_block(uint32_t *in_buf, uint32_t in_size, uint32_t seed) {
/* some common variables. */
uint32_t seed2 = 0xEEEEEEEE;
uint32_t ch;
/* we're processing the data 4 bytes at a time. */
for (; in_size >= 4; in_size -= 4) {
seed2 += crypt_buf[0x400 + (seed & 0xFF)];
ch = *in_buf ^ (seed + seed2);
seed = ((~seed << 0x15) + 0x11111111) | (seed >> 0x0B);
seed2 = ch + seed2 + (seed2 << 5) + 3;
*in_buf++ = ch;
}
/* if no error was found, return decrypted bytes. */
return LIBMPQ_SUCCESS;
}
/* function to detect decryption key. */
int32_t libmpq__decrypt_key(uint8_t *in_buf, uint32_t in_size, uint32_t block_size) {
/* some common variables. */
uint32_t saveseed1;
/* temp = seed1 + seed2 */
uint32_t temp;
uint32_t i = 0;
/* temp = seed1 + buffer[0x400 + (seed1 & 0xFF)] */
temp = (*(uint32_t *)in_buf ^ in_size) - 0xEEEEEEEE;
/* try all 255 possibilities. */
for (i = 0; i < 0x100; i++) {
/* some common variables. */
uint32_t seed1;
uint32_t seed2 = 0xEEEEEEEE;
uint32_t ch;
uint32_t ch2;
/* try the first uint32_t's (we exactly know the value). */
seed1 = temp - crypt_buf[0x400 + i];
seed2 += crypt_buf[0x400 + (seed1 & 0xFF)];
ch = ((uint32_t *)in_buf)[0] ^ (seed1 + seed2);
if (ch != in_size) {
continue;
}
/* add one because we are decrypting block positions. */
saveseed1 = seed1 + 1;
ch2 = ch;
/*
* 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 += crypt_buf[0x400 + (seed1 & 0xFF)];
ch = ((uint32_t *)in_buf)[1] ^ (seed1 + seed2);
/* check if we found the file seed. */
if ((ch - ch2) <= block_size) {
/* file seed found, so return it. */
return saveseed1;
}
}
/* if no file seed was found return with error. */
return LIBMPQ_ERROR_DECRYPT;
}
/* function to decompress or explode a block from mpq archive. */
int32_t libmpq__decompress_block(uint8_t *in_buf, uint32_t in_size, uint8_t *out_buf, uint32_t out_size, uint32_t compression_type) {
/* some common variables. */
int32_t tb = 0;
/* check if buffer is not compressed. */
if (compression_type == LIBMPQ_FLAG_COMPRESS_NONE) {
/* no compressed data, so copy input buffer to output buffer. */
memcpy(out_buf, in_buf, out_size);
/* store number of bytes copied. */
tb = out_size;
}
/* check if one compression mode is used. */
else if (compression_type == LIBMPQ_FLAG_COMPRESS_PKZIP ||
compression_type == LIBMPQ_FLAG_COMPRESS_MULTI) {
/* check if block is really compressed, some blocks have set the compression flag, but are not compressed. */
if (in_size < out_size) {
/* check if we are using pkzip compression algorithm. */
if (compression_type == LIBMPQ_FLAG_COMPRESS_PKZIP) {
/* decompress using pkzip. */
if ((tb = libmpq__decompress_pkzip(in_buf, in_size, out_buf, out_size)) < 0) {
/* something on decompression failed. */
return tb;
}
}
/* check if we are using multiple compression algorithm. */
else if (compression_type == LIBMPQ_FLAG_COMPRESS_MULTI) {
/*
* check if it is a file compressed by blizzard's multiple compression, note that storm.dll
* version 1.0.9 distributed with warcraft 3 passes the full path name of the opened archive
* as the new last parameter.
*/
if ((tb = libmpq__decompress_multi(in_buf, in_size, out_buf, out_size)) < 0) {
/* something on decompression failed. */
return tb;
}
}
} else {
/* block has set compression flag, but is not compressed, so copy data to output buffer. */
memcpy(out_buf, in_buf, out_size);
/* save the number of transferred bytes. */
tb = in_size;
}
}
/* if no error was found, return transferred bytes. */
return tb;
}
+60
View File
@@ -0,0 +1,60 @@
/*
* common.h -- header functions used by mpq-tools.
*
* Copyright (c) 2003-2008 Maik Broemme <[email protected]>
*
* 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 _COMMON_H
#define _COMMON_H
/* function to return the hash to a given string. */
uint32_t libmpq__hash_string(
const char *key,
uint32_t offset
);
/* function to encrypt a block. */
int32_t libmpq__encrypt_block(
uint32_t *in_buf,
uint32_t in_size,
uint32_t seed
);
/* function to decrypt a block. */
int32_t libmpq__decrypt_block(
uint32_t *in_buf,
uint32_t in_size,
uint32_t seed
);
/* function to detect decryption key. */
int32_t libmpq__decrypt_key(
uint8_t *in_buf,
uint32_t in_size,
uint32_t block_size
);
/* function to decompress or explode block from archive. */
int32_t libmpq__decompress_block(
uint8_t *in_buf,
uint32_t in_size,
uint8_t *out_buf,
uint32_t out_size,
uint32_t compression_type
);
#endif /* _COMMON_H */
+217
View File
@@ -0,0 +1,217 @@
/* DO NOT CHANGE! this file is auto-generated by crypt_buf_gen.c */
static const uint32_t crypt_buf[0x500] = {
0x55c636e2, 0x02be0170, 0x584b71d4, 0x2984f00e, 0xb682c809, 0x91cf876b,
0x775a9c24, 0x597d5ca5, 0x5a1afeb2, 0xd3e9ce0d, 0x32cdcdf8, 0xb18201cd,
0x3cce05ce, 0xa55d13be, 0xbb0afe71, 0x9376ab33, 0x848f645e, 0x87e45a45,
0x45b86017, 0x5e656ca8, 0x1b851a95, 0x2542dbd7, 0xab4df9e4, 0x5976ae9b,
0x6c317e7d, 0xcddd2f94, 0x3c3c13e5, 0x335b1371, 0x31a592ca, 0x51e4fc4c,
0xf7db5b2f, 0x8abdbe41, 0x8beaa674, 0x20d6b319, 0xde6c9a9d, 0xc5ac84e5,
0x445a5feb, 0x94958cb0, 0x1e7d3847, 0xf35d29b0, 0xca5cceda, 0xb732c8b5,
0xfdcc41dd, 0x0edcec16, 0x9d01feae, 0x1165d38e, 0x9ee193c8, 0xbf33b13c,
0x61bc0dfc, 0xef3e7be9, 0xf8d4d4c5, 0xc79b7694, 0x5a255943, 0x0b3dd20a,
0x9d1ab5a3, 0xcfa8ba57, 0x5e6d7069, 0xcb89b731, 0x3dc0d15b, 0x0d4d7e7e,
0x97e37f2b, 0xfefc2bb1, 0xf95b16b5, 0x27a55b93, 0x45f22729, 0x4c986630,
0x7c666862, 0x5fa40847, 0xa3f16205, 0x791b7764, 0x386b36d6, 0x6e6c3fef,
0xc75855db, 0x4abc7dc7, 0x4a328f9b, 0xcef20c0f, 0x60b88f07, 0xf7bb4b8f,
0x830b5192, 0x94f711ec, 0x20250752, 0x399d21a3, 0xe5c0840d, 0xe76cffa5,
0x624fab29, 0x5df133e6, 0x83e0b9b8, 0xc5796bfb, 0x4a7ab2d0, 0xba59a821,
0x03a81e4c, 0xcd3adfdb, 0x32b26b8c, 0x8e35c533, 0x9e6300e9, 0x8cf92ac5,
0x880d18eb, 0x131a53b3, 0x2ed2dc64, 0xb23257c1, 0xa06450c1, 0x1b92cb8e,
0x72ed730e, 0x19a685f0, 0x82836483, 0x42d94e8a, 0xee9bd6f6, 0x556d0b6a,
0xba65589a, 0xde24cce4, 0x53329f6c, 0xc754fe8b, 0x503d2dc7, 0x10027ba4,
0xd3b60a8b, 0x68e68d83, 0x0a9128a9, 0x595fa35f, 0x0b03b5be, 0x150a45c4,
0xb1629cce, 0xe5f7497b, 0x8a7098a4, 0xb8233e69, 0x8ea0f978, 0x5b579970,
0xeab14318, 0x4b28b263, 0xb6766cef, 0x06782877, 0x155c6dd0, 0xc711333c,
0xf819cedf, 0x00eb1d68, 0xd6fffa6e, 0x439e5962, 0xd765d6db, 0xcb0bcee9,
0x6d3c5647, 0x965466f3, 0x0ca983c9, 0x74ecc1ce, 0xfc0563b6, 0x42b08fee,
0xc5b38853, 0xfe502ceb, 0x7b432faf, 0xc309e610, 0x2c3997d8, 0x43774654,
0x15bd9d2c, 0xed6a420d, 0xc7ff520c, 0xb8a97fd1, 0x5e4d60cc, 0xb9738d11,
0xda2181ff, 0x73ac2597, 0x3a8eec8d, 0xac85e779, 0xf3f975d6, 0xb9fe7b91,
0x0f155d1e, 0x2860b6dd, 0x835977cb, 0xb0607436, 0x9cab7f6b, 0x8ab91186,
0xc12b51e9, 0x20084e8b, 0x44ba8ead, 0xa542b130, 0x82bcd5c4, 0xcc747f4e,
0x0f1909d8, 0xda242e1c, 0x6f7d1aa0, 0xd2626486, 0x88d0781e, 0xab695ccd,
0xfa569145, 0xb4feb55c, 0xbe47e896, 0xe70a7a88, 0xd56185a2, 0xacf4c871,
0x09282332, 0x1ddeeaa8, 0x590c7adb, 0xf4a97667, 0xbfd85705, 0x0ea77ccc,
0xa9f85364, 0x83195869, 0x8bfb041a, 0xdb842f5c, 0xd6f0f315, 0xa7756ea7,
0x0a51b439, 0xa9edf8a3, 0xd9084e2f, 0x827407f8, 0xd4ac8284, 0x09739d0d,
0xb3bb6cfc, 0xd539c77d, 0x6bbc9ac0, 0x35c641aa, 0x934c96b0, 0xd17af317,
0x29c6baef, 0xb275cdac, 0xd72662de, 0x9f5c2544, 0xc1a98f75, 0xd98e8f9a,
0x47bd5c86, 0x70c610a6, 0xb5482ed4, 0x23b9c68c, 0x3c1bae66, 0x69556e7f,
0xd902f5e0, 0x653d195b, 0xde6541fb, 0x07bcc6ac, 0xc6ee7788, 0x801534d4,
0x2c1f35c0, 0xd9de614d, 0xbdccac85, 0xb4d4a0da, 0x242d549b, 0x9d964796,
0xb9ceb982, 0x59fa99a9, 0xd8986cc1, 0x9e90c1a1, 0x01bbd82f, 0xd7f1c5fd,
0xdd847eba, 0x883d305d, 0x25f13152, 0x4a92694d, 0x77f1e601, 0x8024e6e7,
0x02a5f53d, 0x9c3ef4d9, 0xaf403ccc, 0xe2ad03c0, 0x46edf6ec, 0x6f9bd3e6,
0xcc24ad7a, 0x47afab12, 0x82298df7, 0x708c9eec, 0x76f8c1b1, 0xb39459d2,
0x3f1e26d9, 0xe1811be7, 0x56ed1c4d, 0xc9d18af8, 0xe828060e, 0x91cada2e,
0x5ccbf9b7, 0xf1a552d4, 0x3c9d4343, 0xe1008785, 0x2adfeebf, 0xf90240a0,
0x3d08cce7, 0x426e6fb0, 0x573c984f, 0x13a843ae, 0x406b7439, 0x636085d9,
0x5000ba9a, 0xad4a47ab, 0xaf001d8d, 0x419907ae, 0x185c8f96, 0xe5e9ed4d,
0x61764133, 0xd3703d97, 0xac98f0c6, 0xdbc3a37c, 0x85f010c4, 0x90491e32,
0xf12e18bf, 0xc88c96e1, 0xd3fbd6d9, 0xe3c28b08, 0xd5bf08cc, 0xb1e78859,
0x2546ddcf, 0xb030b200, 0xaafd2811, 0x55b22d21, 0xd38bf567, 0x469c7a2b,
0x5ad05792, 0xa1a5981e, 0x7dfb8384, 0x34d1ca0a, 0x7eb0dbe0, 0xd61ce0f6,
0x398068b7, 0xe6406d1f, 0x95ae6b47, 0xe4281230, 0xb0843061, 0xa70a3a68,
0xe340f625, 0x72dcbffd, 0x8eb8afcd, 0x18b6661f, 0x17ef5a5c, 0x000c5b22,
0x6ba13836, 0x6165e383, 0x74481c5b, 0xe56f0711, 0xa26f5024, 0x5ff22e60,
0x31a5e829, 0xa1094bf0, 0xc680ec6c, 0x8cf327d7, 0xebf1348a, 0x6a227d2f,
0x74065184, 0x8df65112, 0x2bbd05ee, 0xe4d00ed6, 0x2980ee1a, 0x6ae1da73,
0xe84614da, 0x6c9906ab, 0xcf8e02db, 0xd3723e97, 0x92f66caf, 0xac8491c7,
0xaec65696, 0xb98997cf, 0xfa16c762, 0x6d73c65f, 0x205d22a6, 0x4dd3aaa5,
0x2deb6bc0, 0x9f37686c, 0x71a5282b, 0x376bb9e0, 0x7fff2a1b, 0xde67982f,
0x9cbf33ce, 0x2e6dab37, 0x6e3424b9, 0x0ee143bc, 0x832a60d9, 0xbb6329e1,
0x13f6befd, 0x5965fb84, 0xf60b233c, 0x3d695183, 0x433224a1, 0xb5d9cae5,
0x82459bab, 0x9f21b311, 0xaf6c5247, 0xb447b13a, 0x7b2676c3, 0xc38979cd,
0x8526ae25, 0xc550ad5b, 0x685099a7, 0x65e9c2bd, 0xe5c6dc36, 0xe10b37a9,
0x88016878, 0xce81d4e4, 0x24d6fc80, 0x4106152d, 0x6d4f5f90, 0xc4dc74be,
0xdb48676c, 0x6cb569b7, 0xf3bf598f, 0x042b08d9, 0x02ccb2de, 0xb1056f65,
0x47994af4, 0xfa141ba4, 0x9376ab2e, 0x07a76737, 0x75e7e6fc, 0x449d80a1,
0x03b7259d, 0xf6df358a, 0x5a75d5b9, 0x47286923, 0x3b1a30ef, 0xeebe3d6a,
0x9db1aa00, 0x007a90d9, 0x24667071, 0x019c73cf, 0x69039bcd, 0x95900744,
0x6518b1eb, 0x6905f202, 0xee3951b2, 0xe141fca9, 0x797fa832, 0x5a95e55b,
0xd6263b15, 0x5b61f394, 0x897acb1c, 0x005f83a9, 0x22420f71, 0xf495176e,
0x7e138f3d, 0x1392e384, 0x373bf7aa, 0x8e512816, 0xa960b3ca, 0x0474d74c,
0xffacd6d7, 0x2ef5ed9e, 0x60992aaa, 0x7e690e99, 0x23c0749d, 0xd8e29105,
0x555d5909, 0x15631bfe, 0xa69c5a1c, 0x501017ca, 0x99438048, 0x38733ac7,
0xe682e2c8, 0xd4655fd6, 0x956e4c04, 0x347df643, 0x2f4b177b, 0x93ed3aa4,
0xa77e1dd5, 0x7ae55702, 0xd2a52fd9, 0xef8ba18c, 0xb7d3c1ee, 0x8078ba8d,
0xab5aaadb, 0x752be08f, 0x068b31c1, 0x078aae3c, 0xaa5a8343, 0x123d9268,
0x2ceaee43, 0x8ebdb239, 0x650251f3, 0x04883648, 0x8c62e12e, 0x12b32167,
0xe5112e9a, 0x10002548, 0x3e7a818d, 0x077e5327, 0xf140cc21, 0x6ce7d75d,
0x9b99f9a5, 0x3215741c, 0xb6aadbae, 0x738768dc, 0x82a3742f, 0x76517020,
0xdd872ad8, 0x9d0902b2, 0x7d1a6b04, 0x49381592, 0x63a652a5, 0x0c15e626,
0xe22f70d6, 0x01e84385, 0xb29de134, 0x20c5000e, 0xe961f443, 0x2d31662e,
0x3ce6bc28, 0x34f9dd94, 0xfa45de53, 0x497588bd, 0x9468215b, 0x0777fa5c,
0x6f7114c0, 0xe0e82694, 0xe4371986, 0x57112de2, 0xe0cac289, 0xf2a3cee0,
0x6a41e1b9, 0xbfcea77d, 0xf927fd52, 0x69747d98, 0xbea76cdb, 0x8dd39557,
0x04db5ece, 0x2a0885c8, 0x3be4e8ee, 0x21d785dc, 0x09de7c0e, 0x3258ea33,
0x51922982, 0xee8dd024, 0x3df6965d, 0x30c1237b, 0xf7f6686a, 0x9faca186,
0x7c400076, 0x85acef8a, 0xf4b6d220, 0xddc3481c, 0x439eaec4, 0x717bbe63,
0x8259faa7, 0xd682bd68, 0x932a8610, 0x38bf0a7f, 0x6212e2c7, 0x88ee3168,
0xb3c27047, 0x6133cb1e, 0x15295506, 0x5ae66246, 0x1d208ddd, 0xa91d3dba,
0xc315968d, 0x6aa2664b, 0x716d0cca, 0x891f4956, 0x80866bff, 0xbd56c847,
0x9093425a, 0x28dd9e87, 0x84ef3e08, 0x690a49d6, 0x6a7eff82, 0xabcfe400,
0x3d3be5ca, 0x381b650c, 0x4b7c8622, 0x3e0246f3, 0xa3561654, 0x9488865c,
0x3aef1bf2, 0x5e5d68a2, 0xd32f1ddc, 0x51972bf0, 0x177a213b, 0x469375c2,
0x37640bd0, 0xfc3324c8, 0x07091a09, 0x2d63d3fb, 0x2153f023, 0x48223875,
0x61a55826, 0x8c136538, 0x49f71d98, 0x84c7d51e, 0x85551a73, 0x13d604c5,
0xd701a626, 0x87b844ca, 0x741eb29d, 0x2a2c977c, 0xc797ca03, 0x6c4085d7,
0x2dacf79b, 0x734fa2eb, 0xcc290557, 0xfa1e75e4, 0x06b29a27, 0xbece2a7a,
0x70a4554b, 0xc935942e, 0xa764bbc1, 0x1fe391d6, 0x7807f0c2, 0x40606ed9,
0xe5153086, 0xe91d7dd2, 0xed5d3ba9, 0xaa14b64a, 0x83b24dd9, 0xec1ff5cd,
0xba33ead3, 0xe4ef735c, 0xbc062438, 0xd8bfd523, 0x473d1e04, 0x2007f8a7,
0xb02903ed, 0x86ea8ada, 0x95ab69cf, 0xfd1f9809, 0x9cb3d8bb, 0x51f45958,
0x9cdd4276, 0xc245865e, 0x8f0c836b, 0x4ee7dc07, 0xf6368d9d, 0xef2c1dc1,
0xee56b54b, 0xbd62ce2f, 0xf4916aad, 0xc81cb594, 0x41729f49, 0x24bef0a4,
0xdef487a9, 0x222e05b8, 0x8d3bf5c6, 0x11b55009, 0xad09d2b3, 0x19db9fd1,
0xd7427085, 0x33dbfc8b, 0x526b9378, 0x790e1bc8, 0xb2998a00, 0xa5641703,
0x0676d249, 0x6b9185cc, 0x30e4348f, 0x82c52f65, 0x57c7dc24, 0x489c1ecd,
0x9fcab02a, 0x56d61117, 0xfe869cac, 0x55fc5140, 0x7fbbb382, 0x9e5afc79,
0x10047c99, 0xfc9f5984, 0x56587e2d, 0xb98193f0, 0x98fe5e8e, 0x29b15b6b,
0x9561f055, 0xbb0caa25, 0x1e4ecc15, 0x23f5393b, 0x0845b458, 0xceff67ca,
0xb099900c, 0x00b1564f, 0x39eef3d1, 0xfcc1bf84, 0xac8893b5, 0x6484bf0e,
0x91c02ab3, 0x8c0c0c70, 0x686fa8c6, 0xe171bed6, 0xdfae37df, 0xd5a1a4e7,
0xe3eb49a1, 0x5e6014e0, 0x205b21ac, 0xfd58b3da, 0x2e7c07cd, 0xef2cc85a,
0xd7587b46, 0xf417847d, 0x8a30cec1, 0x70984f6c, 0xf0b63388, 0xc220c98d,
0xede62936, 0x92c0a7b3, 0x1ef371e8, 0x2005f7af, 0x91a47265, 0xb0cf5504,
0xd500aba8, 0xcb5c4bd3, 0x9b3bcbc3, 0xcf6644b5, 0xce9488ef, 0x003fc96e,
0xaa42222f, 0x4844f3d0, 0x4db89d77, 0x08681aae, 0x662f3a28, 0x761552db,
0x1df7a17a, 0x93feed9a, 0xcc496a4f, 0xa217cfcd, 0x3ba3c930, 0x268f7e77,
0x0797b4a1, 0x8bebfc51, 0x068930c4, 0x16c874e2, 0xc242da24, 0xfb229f76,
0xa0795b02, 0x689fc036, 0x17a73732, 0xd21aec00, 0xac00a692, 0x5b217f18,
0xae421624, 0x2bc05cc0, 0x48c1db7a, 0x4f4e63b4, 0x1667f04e, 0x34020f94,
0x972b2555, 0x9a07355b, 0x01665970, 0x7db60c6f, 0x3ad7103b, 0x5c3d09c0,
0xeea3dada, 0x88c21c10, 0x102436d7, 0x6a3b3400, 0xeb523c4c, 0xfb97d896,
0x964cb86b, 0xdd878038, 0x0529da4d, 0x0b1468a5, 0x18739ac8, 0xf7f26668,
0xf64f4471, 0x5c14f5c3, 0x44a081fb, 0x39ac7e37, 0x8a17c26b, 0x868f5e67,
0x3931978d, 0x6edf7817, 0x4951cc67, 0x943407f3, 0xcc5e748f, 0x2b7ee729,
0xcbb320f0, 0x11fec8e7, 0xfccfc658, 0x03454354, 0x373aa1ec, 0x1d58fe9a,
0x064710ae, 0xa88aa0ba, 0xd183a23e, 0x40d150a3, 0xf531b8d1, 0xa7d99f85,
0x11838cd5, 0xb19e64b3, 0x3d67a5e9, 0xb02c5ac6, 0x99b9b9e8, 0x4c202b7a,
0x15f261d3, 0xa84c2d0d, 0x50f185a6, 0x33ba41d5, 0x39791013, 0x4baff44e,
0xeeeeaa1c, 0xe0488314, 0x559ccd2b, 0xa104f445, 0x636f37c4, 0x264d5e3b,
0x75c17f35, 0x75424131, 0xbb115739, 0x74fe755a, 0x7d3a7aa6, 0x2d8be784,
0x83ed154a, 0xfc2673d8, 0x44dd4a7f, 0x79056cc8, 0x82cc8831, 0x9d3c1b7c,
0xe9453bfa, 0x24315694, 0x661f3253, 0x75549f5c, 0xbb2b63ed, 0x67e00d96,
0xf48966c7, 0x0d7bea56, 0xc25f92ef, 0xa947a79d, 0xde4adf6f, 0xac0f0342,
0xd3eb246b, 0xa4aa118e, 0x3c3e6a46, 0x457f4441, 0xa50a406f, 0x6c508d9f,
0xe9ac18e7, 0x1ecdb4ba, 0x39ac7e3a, 0x7fb304fa, 0x6f38f8e8, 0x4aecea6d,
0x61035e73, 0x81708907, 0xebc07205, 0x90fd7614, 0xb52d217f, 0x6c4de195,
0x1dd49084, 0x64ee482c, 0x94c7a521, 0x540c09d8, 0x75df8dd5, 0x414131f7,
0x3698fd76, 0xf784db4f, 0xf8c97a03, 0x048f39b9, 0x3bf4f0bd, 0x8cb50992,
0x9b58d9ee, 0xe5ab79cc, 0x9a5f6052, 0xbd9591b0, 0xfad2232b, 0x5a632254,
0x0286e618, 0x8ad3c8f7, 0xe4060176, 0x754c4617, 0x5c10490b, 0x6f7d6fff,
0x2187b42a, 0x5775095b, 0x02f4c663, 0x5a5dca06, 0xfe4ad4c7, 0x53e19f7d,
0x59ff46b5, 0xbcc42ba5, 0xfd2f4a97, 0xbed6d905, 0x95629b6b, 0x21a1c0db,
0xaa10b45d, 0xe6ef6d58, 0x2892cf4d, 0x9fed6c10, 0x1e386bf7, 0x9be0c6e8,
0x2b2f15ef, 0x19f5ac7b, 0x7aff0e72, 0x31da576f, 0x30252cb4, 0x577960ac,
0x166e9e5a, 0xa9374a61, 0x71369c96, 0x7ff826ae, 0xe8175326, 0xcabbfd33,
0x0191190e, 0x699d3c3e, 0x36b40b22, 0xb3950513, 0x9b889bfa, 0xa52a5007,
0xac290fed, 0x3b4e4a4f, 0xb753d8d6, 0x3c531f22, 0x582f6427, 0xa9cd93a9,
0x546e39ae, 0x242faad2, 0xd2e0f747, 0x09f6325d, 0x59d48719, 0xad7eb66e,
0xd5512878, 0x56debf9d, 0x5107e5a5, 0xf1c00aa4, 0x814ccca8, 0x600d90f0,
0x9be97619, 0x915fa5f2, 0x2b5628dd, 0xa33d5f5a, 0x595df7c1, 0x6966215d,
0x50ec8337, 0xf1d21372, 0x0ee2eefb, 0xad9e70b7, 0xab0d2fe4, 0xcf277b5d,
0x62585a2c, 0x835a7844, 0x74b1fa6b, 0x49baffd5, 0x2ea9c864, 0x129311a8,
0xbdfa1867, 0x83ca5997, 0x9d1db719, 0x84bb79e6, 0x9e3f99f2, 0x313f6101,
0x1b99245b, 0xd15d8fb2, 0xcef90f81, 0x2945268d, 0xdbbcf573, 0xb1021886,
0x9ee7ec1d, 0x1cf824f7, 0x7eaa2e32, 0x69c0a2b5, 0x7494419c, 0xe253d7d3,
0x48da3d12, 0x45b8b571, 0xdb4d147a, 0xd82d8dde, 0x265d10a2, 0xb0a6eb9a,
0x7e1c93a6, 0x36fe2f46, 0xdcad6b00, 0x05439191, 0xb0ce5484, 0x61d1c309,
0x8da62a03, 0x06d0fe2f, 0xbac6dd3c, 0xca2006f3, 0x8321b1af, 0x0411a6f3,
0xe8918eac, 0x21a2c152, 0x91c0d54f, 0x6aaa14fa, 0xdd22a440, 0x88cb2075,
0x7a4eb813, 0x67afa071, 0xd8d98c9c, 0x31f10d47, 0x6ff1a8a8, 0x2faaf0a1,
0x48a221bb, 0x3be6948b, 0xaa79e79b, 0x0ea7278c, 0x7a3857ef, 0x49b7fe55,
0xd51cb931, 0x041c018d, 0x00b90501, 0x45ea7881, 0x8fc1dbcf, 0xb80b32a9,
0xabacd2e9, 0x677bdc40, 0xecace542, 0x6d6514eb, 0x31c09ff7, 0x5e6c1abd,
0x1c391d0f, 0x0e9d77f1, 0x7119392d, 0x6be9b0ba, 0x6194fa77, 0x45e62148,
0x42234af2, 0xc3239d66, 0x939cbdbc, 0x56200d9c, 0x6b275208, 0x001a61f3,
0xccc2a546, 0x4b722be0, 0xee25f2b7, 0x6d86cf9e, 0xaa6be0cd, 0x4dcda7b6,
0x78d4aa13, 0x36ea7ad9, 0x3f29d700, 0xdeea2d84, 0x6a6af5bd, 0x18afb81c,
0xd8e4e73c, 0x8aa708ba, 0x658b94d9, 0xa676478c, 0xcfa10c22, 0x25593c74,
0x8d962235, 0x5f980270, 0x3df6ebc0, 0x8e7d92fa, 0xc3ee55e1, 0xd5f72447,
0x02b0fa95, 0x52b0b520, 0x70d2c11f, 0x3a6fdd6c, 0x193aa698, 0x5496f7d5,
0x4208931b, 0x7a4106ec, 0x83e86840, 0xf49b6f8c, 0xba3d9a51, 0x55f54ddd,
0x2de51372, 0x9afb571b, 0x3ab35406, 0xad64ff1f, 0xc77764fe, 0x7f864466,
0x416d9cd4, 0xa2489278, 0xe30b86e4, 0x0b5231b6, 0xba67aed6, 0xe5ab2467,
0x60028b90, 0x1d9e20c6, 0x2a7c692a, 0x6b691cdb, 0x9e51f817, 0x9b763dec,
0x3d29323f, 0xcfe12b68, 0x754b459b, 0xa2238047, 0xd9c55514, 0x6bdcffc1,
0x693e6340, 0x82383fe7, 0x1916ea5f, 0xec7bcd59, 0x72de165a, 0xe79a1617,
0x8ec86234, 0xa8f0d284, 0x20c90226, 0x7bf98884, 0x28a58331, 0x3ec3fa6e,
0x4ce0895b, 0xc353b4d0, 0x33ef064f, 0x21e5e210, 0xc8bb589d, 0xe85dcab2,
0xac65829f, 0xa7bf92d0, 0x05a6174d, 0x25a50c2e, 0xe5c78777, 0x3d75021f,
0x4baa9c98, 0x23bdc884, 0x9653bbd7, 0xbadce7f5, 0xc283a484, 0xc040df2e,
0x9370a841, 0x2f316022, 0x36eed231, 0xac2cbc0c, 0x13c0a49b, 0xcdd12997,
0x07fe91b2, 0xcd7eabcd, 0x2c01271d, 0x18432df8, 0x599c6bc7, 0x75e93d5a,
0xb67a6ee2, 0x8e738e16, 0xff9073fd, 0xaf77026a, 0xf86ea2fc, 0x91509ea3,
0x33a78dc6, 0x4f79234a, 0x3a7535bc, 0x3539fcb1, 0x3103ee52, 0x4f6f1e69,
0x6bb3ebbc, 0x4cb77555, 0x8dd1e999, 0x2ade439d, 0x11521fae, 0xb94d2545,
0x8dde9abd, 0x1909393f, 0xb792a23d, 0x749c455b, 0xb5b60f2c, 0x380459ce,
0x0dad5820, 0xb130845b, 0x291cbd52, 0xde9a5bb7, 0x51def961, 0x515b6408,
0xca6e823e, 0x382e6e74, 0xeebe3d71, 0x4c8f0c6a, 0xe676dcea, 0x14e1dc7c,
0x6f7fc634, 0xcf85a943, 0xd39ea96e, 0x136e7c93, 0x7164b304, 0xf32f1333,
0x35c34034, 0xde39d721, 0x91a87439, 0xc410111f, 0x29f17aac, 0x1316a6ff,
0x12f194ee, 0x420b9499, 0xf72db0dc, 0x690b9f93, 0x17d14bb2, 0x8f931ab8,
0x217500bc, 0x875413f8, 0x98b2e43d, 0xc51f9571, 0x54cebdca, 0x0719cc79,
0xf3c7080d, 0xe4286771, 0xa3eab3cd, 0x4a6b00e0, 0x11cf0759, 0x7e897379,
0x5b32876c, 0x5e8cd4f6, 0x0cedfa64, 0x919ac2c7, 0xb214f3b3, 0x0e89c38c,
0xf0c43a39, 0xeae10522, 0x835bce06, 0x9eec43c2, 0xea26a9d6, 0x69531821,
0x6725b24a, 0xda81b0e2, 0xd5b4ae33, 0x080f99fb, 0x15a83daf, 0x29dfc720,
0x91e1900f, 0x28163d58, 0x83d107a2, 0x4eac149a, 0x9f71da18, 0x61d5c4fa,
0xe3ab2a5f, 0xc7b0d63f, 0xb3cc752a, 0x61ebcfb6, 0x26ffb52a, 0xed789e3f,
0xaa3bc958, 0x455a8788, 0xc9c082a9, 0x0a1bef0e, 0xc29a5a7e, 0x150d4735,
0x943809e0, 0x69215510, 0xef0b0da9, 0x3b4e9fb3, 0xd8b5d04c, 0xc7a023a8,
0xb0d50288, 0x64821375, 0xc260e8cf, 0x8496bd2c, 0xff4f5435, 0x0fb5560c,
0x7cd74a52, 0x93589c80, 0x88975c47, 0x83bda89d, 0x8bcc4296, 0x01b82c21,
0xfd821dbf, 0x26520b47, 0x04983e19, 0xd3e1ca27, 0x782c580f, 0x326ff573,
0xc157bcc7, 0x4f5e6b84, 0x44ebfbfb, 0xda26d9d8, 0x6cd9d08e, 0x1719f1d8,
0x715c0487, 0x2c2d3c92, 0x53faaba9, 0xbc836146, 0x510c92d6, 0xe089f82a,
0x4680171f, 0x369f00de, 0x70ec2331, 0x0e253d55, 0xdafb9717, 0xe5dd922d,
0x95915d21, 0xa0202f96, 0xa161cc47, 0xeacfa6f1, 0xed5e9189, 0xdab87684,
0xa4b76d4a, 0xfa704897, 0x631f10ba, 0xd39da8f9, 0x5db4c0e4, 0x16fde42a,
0x2dff7580, 0xb56fec7e, 0xc3ffb370, 0x8e6f36bc, 0x6097d459, 0x514d5d36,
0xa5a737e2, 0x3977b9b3, 0xfd31a0ca, 0x903368db, 0xe8370d61, 0x98109520,
0xade23cac, 0x99f82e04, 0x41de7ea3, 0x84a1c295, 0x09191be0, 0x30930d02,
0x1c9fa44a, 0xc406b6d7, 0xeedca152, 0x6149809c, 0xb0099ef4, 0xc5f653a5,
0x4c10790d, 0x7303286c
};
+602
View File
@@ -0,0 +1,602 @@
/*
* explode.c -- explode function of pkware data compression library.
*
* Copyright (c) 2003-2008 Maik Broemme <[email protected]>
*
* This source was adepted from the C++ version of pkware.cpp included
* in stormlib. The C++ version belongs to the following authors:
*
* Ladislav Zezula <[email protected]>
*
* 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.
*/
/* generic includes. */
#include <string.h>
/* libmpq main includes. */
#include "mpq.h"
/* libmpq generic includes. */
#include "explode.h"
/* tables used for data extraction. */
static const uint8_t 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
};
/* tables used for data extraction. */
static const uint8_t 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
};
/* tables used for data extraction. */
static const uint8_t pkzip_clen_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08
};
/* tables used for data extraction. */
static const uint16_t pkzip_len_base[] = {
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
0x0008, 0x000A, 0x000E, 0x0016, 0x0026, 0x0046, 0x0086, 0x0106
};
/* tables used for data extraction. */
static const uint8_t pkzip_slen_bits[] = {
0x03, 0x02, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x07, 0x07
};
/* tables used for data extraction. */
static const uint8_t pkzip_len_code[] = {
0x05, 0x03, 0x01, 0x06, 0x0A, 0x02, 0x0C, 0x14, 0x04, 0x18, 0x08, 0x30, 0x10, 0x20, 0x40, 0x00
};
/* tables used for data extraction. */
static const uint8_t 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
};
/* tables used for data extraction. */
static const uint16_t 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 unused variables. */
char pkware_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";
/* skips given number of bits. */
static int32_t skip_bit(pkzip_cmp_s *mpq_pkzip, uint32_t bits) {
/* check 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;
/* if no error was found, return zero. */
return 0;
}
/* this function generate the decode tables used for decryption. */
static void generate_tables_decode(int32_t count, uint8_t *bits, const uint8_t *code, uint8_t *buf2) {
/* some common variables. */
int32_t i;
/* EBX - count */
for (i = count-1; i >= 0; i--) {
/* some common variables. */
uint32_t idx1 = code[i];
uint32_t idx2 = 1 << bits[i];
/* loop until table is ready. */
do {
buf2[idx1] = (uint8_t)i;
idx1 += idx2;
} while (idx1 < 0x100);
}
}
/* this function generate the tables for ascii decompression. */
static void generate_tables_ascii(pkzip_cmp_s *mpq_pkzip) {
/* some common variables. */
const uint16_t *code_asc = &pkzip_code_asc[0xFF];
uint32_t acc;
uint32_t add;
uint16_t count;
/* loop through ascii table. */
for (count = 0x00FF; code_asc >= pkzip_code_asc; code_asc--, count--) {
uint8_t *bits_asc = mpq_pkzip->bits_asc + count;
uint8_t bits_tmp = *bits_asc;
/* check if byte is finished. */
if (bits_tmp <= 8) {
add = (1 << bits_tmp);
acc = *code_asc;
do {
mpq_pkzip->offs_2c34[acc] = (uint8_t)count;
acc += add;
} while (acc < 0x100);
} else {
if ((acc = (*code_asc & 0xFF)) != 0) {
mpq_pkzip->offs_2c34[acc] = 0xFF;
if (*code_asc & 0x3F) {
/* decrease bit by four. */
bits_tmp -= 4;
*bits_asc = bits_tmp;
add = (1 << bits_tmp);
acc = *code_asc >> 4;
do {
mpq_pkzip->offs_2d34[acc] = (uint8_t)count;
acc += add;
} while (acc < 0x100);
} else {
/* decrease bit by six. */
bits_tmp -= 6;
*bits_asc = bits_tmp;
add = (1 << bits_tmp);
acc = *code_asc >> 6;
do {
mpq_pkzip->offs_2e34[acc] = (uint8_t)count;
acc += add;
} while (acc < 0x80);
}
} else {
/* decrease bit by eight. (one byte) */
bits_tmp -= 8;
*bits_asc = bits_tmp;
add = (1 << bits_tmp);
acc = *code_asc >> 8;
do {
mpq_pkzip->offs_2eb4[acc] = (uint8_t)count;
acc += add;
} while (acc < 0x100);
}
}
}
}
/*
* 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 uint32_t decode_literal(pkzip_cmp_s *mpq_pkzip) {
/* number of bits to skip. */
uint32_t bits;
/* position in buffers. */
uint32_t value;
/* check if bit the current buffer is set, if not return the next byte. */
if (mpq_pkzip->bit_buf & 1) {
/* skip current bit in the buffer. */
if (skip_bit(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 (skip_bit(mpq_pkzip, mpq_pkzip->slen_bits[value])) {
return 0x306;
}
/* check bits. */
if ((bits = mpq_pkzip->clen_bits[value]) != 0) {
/* some common variables. */
uint32_t val2 = mpq_pkzip->bit_buf & ((1 << bits) - 1);
/* check if we should skip one bit. */
if (skip_bit(mpq_pkzip, bits)) {
/* check position if we should skip the bit. */
if ((value + val2) != 0x10E) {
return 0x306;
}
}
/* fill values. */
value = mpq_pkzip->len_base[value] + val2;
}
/* return number of bytes to repeat. */
return value + 0x100;
}
/* skip one bit. */
if (skip_bit(mpq_pkzip, 1)) {
return 0x306;
}
/* check the binary compression type, read 8 bits and return them as one byte. */
if (mpq_pkzip->cmp_type == LIBMPQ_PKZIP_CMP_BINARY) {
/* fill values. */
value = mpq_pkzip->bit_buf & 0xFF;
/* check if we should skip one bit. */
if (skip_bit(mpq_pkzip, 8)) {
return 0x306;
}
/* return value from bit buffer. */
return value;
}
/* check if ascii compression is used. */
if (mpq_pkzip->bit_buf & 0xFF) {
/* fill values. */
value = mpq_pkzip->offs_2c34[mpq_pkzip->bit_buf & 0xFF];
/* check value. */
if (value == 0xFF) {
if (mpq_pkzip->bit_buf & 0x3F) {
/* check if four bits are in bit buffer for skipping. */
if (skip_bit(mpq_pkzip, 4)) {
return 0x306;
}
/* fill values. */
value = mpq_pkzip->offs_2d34[mpq_pkzip->bit_buf & 0xFF];
} else {
/* check if six bits are in bit buffer for skipping. */
if (skip_bit(mpq_pkzip, 6)) {
return 0x306;
}
/* fill values. */
value = mpq_pkzip->offs_2e34[mpq_pkzip->bit_buf & 0x7F];
}
}
} else {
/* check if eight bits are in bit buffer for skipping. */
if (skip_bit(mpq_pkzip, 8)) {
return 0x306;
}
/* fill values. */
value = mpq_pkzip->offs_2eb4[mpq_pkzip->bit_buf & 0xFF];
}
/* return out of buffer error (0x306) or position in buffer. */
return skip_bit(mpq_pkzip, mpq_pkzip->bits_asc[value]) ? 0x306 : value;
}
/* this function retrieves the number of bytes to move back. */
static uint32_t decode_distance(pkzip_cmp_s *mpq_pkzip, uint32_t length) {
/* some common variables. */
uint32_t pos = mpq_pkzip->pos1[(mpq_pkzip->bit_buf & 0xFF)];
/* number of bits to skip. */
uint32_t skip = mpq_pkzip->dist_bits[pos];
/* skip the appropriate number of bits. */
if (skip_bit(mpq_pkzip, skip) == 1) {
return 0;
}
/* check if length is two. */
if (length == 2) {
pos = (pos << 2) | (mpq_pkzip->bit_buf & 0x03);
/* skip the bits. */
if (skip_bit(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 (skip_bit(mpq_pkzip, mpq_pkzip->dsize_bits) == 1) {
return 0;
}
}
/* return the bytes to move back. */
return pos + 1;
}
/*
* function loads data from the input buffer used by mpq_pkzip
* "implode" and "explode" function as user defined callback and
* returns number of bytes loaded.
*
* char *buf - pointer to a buffer where to store loaded data.
* uint32_t *size - maximum number of bytes to read.
* void *param - custom pointer, parameter of implode/explode.
*/
static uint32_t data_read_input(char *buf, uint32_t *size, void *param) {
/* some common variables. */
pkzip_data_s *info = (pkzip_data_s *)param;
uint32_t max_avail = (info->in_bytes - info->in_pos);
uint32_t 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 bytes read. */
return to_read;
}
/*
* function for store output data used by mpq_pkzip "implode" and
* "explode" as userdefined callback.
*
* char *buf - pointer to data to be written.
* uint32_t *size - number of bytes to write.
* void *param - custom pointer, parameter of implode/explode.
*/
static void data_write_output(char *buf, uint32_t *size, void *param) {
/* some common variables. */
pkzip_data_s *info = (pkzip_data_s *)param;
uint32_t max_write = (info->max_out - info->out_pos);
uint32_t 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;
}
/* this function extract the data from input stream. */
static uint32_t expand(pkzip_cmp_s *mpq_pkzip) {
/* number of bytes to copy. */
uint32_t copy_bytes;
/* one byte from compressed file. */
uint32_t one_byte;
/* some common variables. */
uint32_t result;
/* initialize output buffer position. */
mpq_pkzip->out_pos = 0x1000;
/* check if end of data or error, so terminate decompress. */
while ((result = one_byte = decode_literal(mpq_pkzip)) < 0x305) {
/* check if one byte is greater than 0x100, which means 'repeat n - 0xFE bytes'. */
if (one_byte >= 0x100) {
/* ECX */
uint8_t *source;
/* EDX */
uint8_t *target;
/* some common variables. */
uint32_t copy_length = one_byte - 0xFE;
uint32_t move_back;
/* get length of data to copy. */
if ((move_back = decode_distance(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;
/* copy until nothing left. */
while (copy_length-- > 0) {
*target++ = *source++;
}
} else {
/* byte is 0x100 great, so add one byte. */
mpq_pkzip->out_buf[mpq_pkzip->out_pos++] = (uint8_t)one_byte;
}
/* check if number of extracted bytes has reached 1/2 of output buffer, so 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);
/* check 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 the rest. */
copy_bytes = mpq_pkzip->out_pos - 0x1000;
mpq_pkzip->write_buf((char *)&mpq_pkzip->out_buf[0x1000], &copy_bytes, mpq_pkzip->param);
/* return copied bytes. */
return result;
}
/* this function explode the data stream. */
uint32_t libmpq__do_decompress_pkzip(uint8_t *work_buf, void *param) {
/* some common variables. */
pkzip_cmp_s *mpq_pkzip = (pkzip_cmp_s *)work_buf;
/* set the whole work buffer to zeros. */
memset(mpq_pkzip, 0, sizeof(pkzip_cmp_s));
/* initialize work struct and load compressed data. */
mpq_pkzip->read_buf = data_read_input;
mpq_pkzip->write_buf = data_write_output;
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);
/* check if we have pkzip data. */
if (mpq_pkzip->in_bytes <= 4) {
return LIBMPQ_PKZIP_CMP_BAD_DATA;
}
/* get the compression type. */
mpq_pkzip->cmp_type = mpq_pkzip->in_buf[0];
/* get the dictionary size. */
mpq_pkzip->dsize_bits = mpq_pkzip->in_buf[1];
/* initialize 16-bit bit buffer. */
mpq_pkzip->bit_buf = mpq_pkzip->in_buf[2];
/* extra (over 8) bits. */
mpq_pkzip->extra_bits = 0;
/* position in input buffer. */
mpq_pkzip->in_pos = 3;
/* check if valid dictionary size. */
if (4 > mpq_pkzip->dsize_bits || mpq_pkzip->dsize_bits > 6) {
return LIBMPQ_PKZIP_CMP_INV_DICTSIZE;
}
/* shifted by 'sar' instruction. */
mpq_pkzip->dsize_mask = 0xFFFF >> (0x10 - mpq_pkzip->dsize_bits);
/* check if we are using binary compression. */
if (mpq_pkzip->cmp_type != LIBMPQ_PKZIP_CMP_BINARY) {
/* check if we are using ascii compression. */
if (mpq_pkzip->cmp_type != LIBMPQ_PKZIP_CMP_ASCII) {
return LIBMPQ_PKZIP_CMP_INV_MODE;
}
/* create ascii buffer. */
memcpy(mpq_pkzip->bits_asc, pkzip_bits_asc, sizeof(mpq_pkzip->bits_asc));
generate_tables_ascii(mpq_pkzip);
}
/* create the tables for decode. */
memcpy(mpq_pkzip->slen_bits, pkzip_slen_bits, sizeof(mpq_pkzip->slen_bits));
generate_tables_decode(0x10, mpq_pkzip->slen_bits, pkzip_len_code, mpq_pkzip->pos2);
/* create the tables for decode. */
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));
generate_tables_decode(0x40, mpq_pkzip->dist_bits, pkzip_dist_code, mpq_pkzip->pos1);
/* check if data extraction works. */
if (expand(mpq_pkzip) != 0x306) {
return LIBMPQ_PKZIP_CMP_NO_ERROR;
}
/* something failed, so return error. */
return LIBMPQ_PKZIP_CMP_ABORT;
}
+94
View File
@@ -0,0 +1,94 @@
/*
* explode.h -- header file for pkware data decompression library
* used by mpq-tools.
*
* Copyright (c) 2003-2008 Maik Broemme <[email protected]>
*
* This source was adepted from the C++ version of pklib.h included
* in stormlib. The C++ version belongs to the following authors:
*
* Ladislav Zezula <[email protected]>
*
* 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 compression constants and return values. */
#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
#ifdef _MSC_VER
#pragma pack(push,1)
#endif
/* compression structure. */
typedef struct {
uint32_t offs0000; /* 0000 - start. */
uint32_t cmp_type; /* 0004 - compression type (binary or ascii). */
uint32_t out_pos; /* 0008 - position in output buffer. */
uint32_t dsize_bits; /* 000C - dict size (4, 5, 6 for 0x400, 0x800, 0x1000). */
uint32_t dsize_mask; /* 0010 - dict size bitmask (0x0F, 0x1F, 0x3F for 0x400, 0x800, 0x1000). */
uint32_t bit_buf; /* 0014 - 16-bit buffer for processing input data. */
uint32_t extra_bits; /* 0018 - number of extra (above 8) bits in bit buffer. */
uint32_t in_pos; /* 001C - position in in_buf. */
uint32_t in_bytes; /* 0020 - number of bytes in input buffer. */
void *param; /* 0024 - custom parameter. */
uint32_t (*read_buf)(char *buf, uint32_t *size, void *param); /* 0028 offset.*/
void (*write_buf)(char *buf, uint32_t *size, void *param); /* 002C offset. */
uint8_t out_buf[0x2000]; /* 0030 - output circle buffer, starting position is 0x1000. */
uint8_t offs_2030[0x204]; /* 2030 - whats that? */
uint8_t in_buf[0x800]; /* 2234 - buffer for data to be decompressed. */
uint8_t pos1[0x100]; /* 2A34 - positions in buffers. */
uint8_t pos2[0x100]; /* 2B34 - positions in buffers. */
uint8_t offs_2c34[0x100]; /* 2C34 - buffer. */
uint8_t offs_2d34[0x100]; /* 2D34 - buffer. */
uint8_t offs_2e34[0x80]; /* 2EB4 - buffer. */
uint8_t offs_2eb4[0x100]; /* 2EB4 - buffer. */
uint8_t bits_asc[0x100]; /* 2FB4 - buffer. */
uint8_t dist_bits[0x40]; /* 30B4 - numbers of bytes to skip copied block length. */
uint8_t slen_bits[0x10]; /* 30F4 - numbers of bits for skip copied block length. */
uint8_t clen_bits[0x10]; /* 3104 - number of valid bits for copied block. */
uint16_t len_base[0x10]; /* 3114 - buffer. */
#ifdef _MSC_VER
} pkzip_cmp_s;
#pragma pack(pop)
#else
} __attribute__ ((packed)) pkzip_cmp_s;
#endif
/* data structure. */
typedef struct {
uint8_t *in_buf; /* pointer to input data buffer. */
uint32_t in_pos; /* current offset in input data buffer. */
int32_t in_bytes; /* number of bytes in the input buffer. */
uint8_t *out_buf; /* pointer to output data buffer. */
uint32_t out_pos; /* position in the output buffer. */
int32_t max_out; /* maximum number of bytes in the output buffer. */
} pkzip_data_s;
/* decompress the stream using pkzip compression. */
uint32_t libmpq__do_decompress_pkzip(
uint8_t *work_buf,
void *param
);
#endif /* _EXPLODE_H */
+361
View File
@@ -0,0 +1,361 @@
/*
* extract.c -- global extracting function for all known file compressions
* in a mpq archive.
*
* Copyright (c) 2003-2008 Maik Broemme <[email protected]>
*
* 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.
*/
/* generic includes. */
#include <stdlib.h>
#include <string.h>
/* zlib includes. */
#include <zlib.h>
#include <bzlib.h>
/* libmpq main includes. */
#include "mpq.h"
/* libmpq generic includes. */
#include "explode.h"
#include "extract.h"
#include "huffman.h"
#include "wave.h"
/* table with decompression bits and functions. */
static decompress_table_s dcmp_table[] = {
{LIBMPQ_COMPRESSION_HUFFMAN, libmpq__decompress_huffman}, /* decompression using huffman trees. */
{LIBMPQ_COMPRESSION_ZLIB, libmpq__decompress_zlib}, /* decompression with the zlib library. */
{LIBMPQ_COMPRESSION_PKZIP, libmpq__decompress_pkzip}, /* decompression with pkware data compression library. */
{LIBMPQ_COMPRESSION_BZIP2, libmpq__decompress_bzip2}, /* decompression with bzip2 library. */
{LIBMPQ_COMPRESSION_WAVE_MONO, libmpq__decompress_wave_mono}, /* decompression for mono waves. */
{LIBMPQ_COMPRESSION_WAVE_STEREO, libmpq__decompress_wave_stereo} /* decompression for stereo waves. */
};
/* this function decompress a stream using huffman algorithm. */
int32_t libmpq__decompress_huffman(uint8_t *in_buf, uint32_t in_size, uint8_t *out_buf, uint32_t out_size) {
/* TODO: make typdefs of this structs? */
/* some common variables. */
int32_t tb = 0;
struct huffman_tree_s *ht;
struct huffman_input_stream_s *is;
/* allocate memory for the huffman tree. */
if ((ht = malloc(sizeof(struct huffman_tree_s))) == NULL ||
(is = malloc(sizeof(struct huffman_input_stream_s))) == NULL) {
/* memory allocation problem. */
return LIBMPQ_ERROR_MALLOC;
}
/* cleanup structures. */
memset(ht, 0, sizeof(struct huffman_tree_s));
memset(is, 0, sizeof(struct huffman_input_stream_s));
/* initialize input stream. */
is->bit_buf = *(uint32_t *)in_buf;
in_buf += sizeof(int32_t);
is->in_buf = (uint8_t *)in_buf;
is->bits = 32;
// TODO: add all the mallocs to init function and add function libmpq__huffman_tree_free() */
// if ((result = libmpq__huffman_tree_init(ht, LIBMPQ_HUFF_DECOMPRESS)) < 0) {
//
// /* something on zlib initialization failed. */
// return LIBMPQ_ERROR_UNPACK;
// }
/* initialize the huffman tree for decompression. */
libmpq__huffman_tree_init(ht, LIBMPQ_HUFF_DECOMPRESS);
/* save the number of copied bytes. */
tb = libmpq__do_decompress_huffman(ht, is, out_buf, out_size);
/* free structures. */
free(is);
free(ht);
/* return transferred bytes. */
return tb;
}
/* this function decompress a stream using zlib algorithm. */
int32_t libmpq__decompress_zlib(uint8_t *in_buf, uint32_t in_size, uint8_t *out_buf, uint32_t out_size) {
/* some common variables. */
int32_t result = 0;
int32_t tb = 0;
z_stream z;
/* fill the stream structure for zlib. */
z.next_in = (Bytef *)in_buf;
z.avail_in = (uInt)in_size;
z.total_in = in_size;
z.next_out = (Bytef *)out_buf;
z.avail_out = (uInt)out_size;
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)) != Z_OK) {
/* something on zlib initialization failed. */
return result;
}
/* call zlib to decompress the data. */
if ((result = inflate(&z, Z_FINISH)) != Z_STREAM_END) {
/* something on zlib decompression failed. */
return result;
}
/* save transferred bytes. */
tb = z.total_out;
/* cleanup zlib. */
if ((result = inflateEnd(&z)) != Z_OK) {
/* something on zlib finalization failed. */
return result;
}
/* return transferred bytes. */
return tb;
}
/* this function decompress a stream using pkzip algorithm. */
int32_t libmpq__decompress_pkzip(uint8_t *in_buf, uint32_t in_size, uint8_t *out_buf, uint32_t out_size) {
/* some common variables. */
int32_t tb = 0;
uint8_t *work_buf;
pkzip_data_s info;
/* allocate memory for pkzip data structure. */
if ((work_buf = malloc(sizeof(pkzip_cmp_s))) == NULL) {
/* memory allocation problem. */
return LIBMPQ_ERROR_MALLOC;
}
/* cleanup. */
memset(work_buf, 0, sizeof(pkzip_cmp_s));
/* fill data information structure. */
info.in_buf = in_buf;
info.in_pos = 0;
info.in_bytes = in_size;
info.out_buf = out_buf;
info.out_pos = 0;
info.max_out = out_size;
/* do the decompression. */
if ((tb = libmpq__do_decompress_pkzip(work_buf, &info)) < 0) {
/* free working buffer. */
free(work_buf);
/* something failed on pkzip decompression. */
return tb;
}
/* save transferred bytes. */
tb = info.out_pos;
/* free working buffer. */
free(work_buf);
/* return transferred bytes. */
return tb;
}
/* this function decompress a stream using bzip2 library. */
int32_t libmpq__decompress_bzip2(uint8_t *in_buf, uint32_t in_size, uint8_t *out_buf, uint32_t out_size) {
/* some common variables. */
int32_t result = 0;
int32_t tb = 0;
bz_stream strm;
/* initialize the bzlib decompression. */
strm.bzalloc = NULL;
strm.bzfree = NULL;
/* initialize the structure. */
if ((result = BZ2_bzDecompressInit(&strm, 0, 0)) != BZ_OK) {
/* something on bzlib initialization failed. */
return result;
}
/* fill the stream structure for bzlib. */
strm.next_in = (char *)in_buf;
strm.avail_in = in_size;
strm.next_out = (char *)out_buf;
strm.avail_out = out_size;
/* do the decompression. */
while (BZ2_bzDecompress(&strm) != BZ_STREAM_END);
/* save transferred bytes. */
tb = strm.total_out_lo32;
/* cleanup of bzip stream. */
BZ2_bzDecompressEnd(&strm);
/* return transferred bytes. */
return tb;
}
/* this function decompress a stream using wave algorithm. (1 channel) */
int32_t libmpq__decompress_wave_mono(uint8_t *in_buf, uint32_t in_size, uint8_t *out_buf, uint32_t out_size) {
/* some common variables. */
int32_t tb = 0;
/* save the number of copied bytes. */
if ((tb = libmpq__do_decompress_wave(out_buf, out_size, in_buf, in_size, 1)) < 0) {
/* something on wave decompression failed. */
return tb;
}
/* return transferred bytes. */
return tb;
}
/* this function decompress a stream using wave algorithm. (2 channels) */
int32_t libmpq__decompress_wave_stereo(uint8_t *in_buf, uint32_t in_size, uint8_t *out_buf, uint32_t out_size) {
/* some common variables. */
int32_t tb = 0;
/* save the number of copied bytes. */
if ((tb = libmpq__do_decompress_wave(out_buf, out_size, in_buf, in_size, 2)) < 0) {
/* something on wave decompression failed. */
return tb;
}
/* return transferred bytes. */
return tb;
}
/* this function decompress a stream using a combination of the other compression algorithm. */
int32_t libmpq__decompress_multi(uint8_t *in_buf, uint32_t in_size, uint8_t *out_buf, uint32_t out_size) {
/* some common variables. */
int32_t tb = 0;
uint32_t count = 0;
uint32_t entries = (sizeof(dcmp_table) / sizeof(decompress_table_s));
uint8_t *temp_buf = NULL;
uint8_t *work_buf = 0;
uint8_t decompress_flag, decompress_unsupp;
uint32_t i;
/* get applied compression types. */
decompress_flag = decompress_unsupp = *in_buf++;
/* decrement data size. */
in_size--;
/* search decompression table type and get all types of compression. */
for (i = 0; i < entries; i++) {
/* check if have to apply this decompression. */
if (decompress_flag & dcmp_table[i].mask) {
/* increase counter for used compression algorithms. */
count++;
/* this algorithm is supported, remove from unsupp mask */
decompress_unsupp &= ~dcmp_table[i].mask;
}
}
/* check if there is some method unhandled. (e.g. compressed by future versions) */
if (decompress_unsupp) {
/* compression type is unknown and we need to implement it. :) */
return LIBMPQ_ERROR_UNPACK;
}
/* if multiple decompressions should be made, we need temporary buffer for the data. */
if (count > 1) {
/* allocate memory for temporary buffer. */
if ((temp_buf = malloc(out_size)) == NULL) {
/* memory allocation problem. */
return LIBMPQ_ERROR_MALLOC;
}
/* cleanup. */
memset(temp_buf, 0, out_size);
}
/* apply all decompressions. */
for (i = 0, count = 0; i < entries; i++) {
/* check if not used this kind of compression. */
if (decompress_flag & dcmp_table[i].mask) {
/* if multiple decompressions should be made, we need temporary buffer for the data. */
if (count == 0) {
/* use output buffer as working buffer. */
work_buf = out_buf;
} else {
/* use temporary buffer as working buffer. */
work_buf = temp_buf;
}
/* decompress buffer using corresponding function. */
if ((tb = dcmp_table[i].decompress(in_buf, in_size, work_buf, out_size)) < 0) {
/* free temporary buffer. */
free(temp_buf);
/* something on decompression failed. */
return tb;
}
/* move output size to source size for next compression. */
in_size = out_size;
in_buf = work_buf;
/* increase counter. */
count++;
}
}
/* if output buffer is not the same like target buffer, we have to copy data (this will happen on multiple decompressions). */
if (work_buf != out_buf) {
/* copy buffer. */
memcpy(out_buf, in_buf, out_size);
}
/* free temporary buffer. */
free(temp_buf);
/* return transferred bytes. */
return tb;
}
+106
View File
@@ -0,0 +1,106 @@
/*
* extract.h -- header for the extraction functions used by mpq-tools.
*
* Copyright (c) 2003-2008 Maik Broemme <[email protected]>
*
* 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 _EXTRACT_H
#define _EXTRACT_H
/* define compression types for multilpe compressions. */
#define LIBMPQ_COMPRESSION_HUFFMAN 0x01 /* huffman compression. (used on wave files only and introduced in starcraft) */
#define LIBMPQ_COMPRESSION_ZLIB 0x02 /* zlib compression. (introduced in warcraft 3) */
#define LIBMPQ_COMPRESSION_PKZIP 0x08 /* pkware dcl compression. (first used compression algorithm) */
#define LIBMPQ_COMPRESSION_BZIP2 0x10 /* bzip compression. (introduced in warcraft 3 - the frozen throne) */
#define LIBMPQ_COMPRESSION_WAVE_MONO 0x40 /* adpcm 4:1 compression. (introduced in starcraft) */
#define LIBMPQ_COMPRESSION_WAVE_STEREO 0x80 /* adpcm 4:1 compression. (introduced in starcraft) */
/*
* table for decompression functions, return value for all functions
* is the transferred data size or one of the following error constants:
*
* LIBMPQ_ERROR_MALLOC
* LIBMPQ_ERROR_DECOMPRESS
*/
typedef int32_t (*DECOMPRESS)(uint8_t *, uint32_t, uint8_t *, uint32_t);
typedef struct {
uint32_t mask; /* decompression bit. */
DECOMPRESS decompress; /* decompression function. */
} decompress_table_s;
/*
* huffman decompression routine, the in_size parameter is not used,
* but needs to be specified due to compatibility reasons.
*
* 1500F5F0
*/
extern int32_t libmpq__decompress_huffman(
uint8_t *in_buf,
uint32_t in_size,
uint8_t *out_buf,
uint32_t out_size
);
/* decompression using zlib. */
extern int32_t libmpq__decompress_zlib(
uint8_t *in_buf,
uint32_t in_size,
uint8_t *out_buf,
uint32_t out_size
);
/* decompression using pkzip. */
extern int32_t libmpq__decompress_pkzip(
uint8_t *in_buf,
uint32_t in_size,
uint8_t *out_buf,
uint32_t out_size
);
/* decompression using bzip2. */
extern int32_t libmpq__decompress_bzip2(
uint8_t *in_buf,
uint32_t in_size,
uint8_t *out_buf,
uint32_t out_size
);
/* decompression using wave. (1 channel) */
extern int32_t libmpq__decompress_wave_mono(
uint8_t *in_buf,
uint32_t in_size,
uint8_t *out_buf,
uint32_t out_size
);
/* decompression using wave. (2 channels) */
extern int32_t libmpq__decompress_wave_stereo(
uint8_t *in_buf,
uint32_t in_size,
uint8_t *out_buf,
uint32_t out_size
);
/* decompression using multiple of the above algorithm. */
extern int32_t libmpq__decompress_multi(
uint8_t *in_buf,
uint32_t in_size,
uint8_t *out_buf,
uint32_t out_size
);
#endif /* _EXTRACT_H */
File diff suppressed because it is too large Load Diff
+151
View File
@@ -0,0 +1,151 @@
/*
* huffman.h -- structures used for huffman compression.
*
* Copyright (c) 2003-2008 Maik Broemme <[email protected]>
*
* This source was adepted from the C++ version of huffman.h included
* in stormlib. The C++ version belongs to the following authors:
*
* Ladislav Zezula <[email protected]>
* ShadowFlare <[email protected]>
*
* 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 huffman compression and decompression values. */
#define LIBMPQ_HUFF_DECOMPRESS 0 /* we want to decompress using huffman trees. */
/* define pointer conversions. */
#define PTR_NOT(ptr) (struct huffman_tree_item_s *)(~(unsigned long)(ptr))
#define PTR_PTR(ptr) ((struct huffman_tree_item_s *)(ptr))
#define PTR_INT(ptr) (long)(ptr)
/* define item handling. */
#define INSERT_ITEM 1 /* insert item into huffman tree. */
#define SWITCH_ITEMS 2 /* switch items isnide huffman tree. */
/* input stream for huffman decompression. */
struct huffman_input_stream_s {
uint8_t *in_buf; /* 00 - input data. */
uint32_t bit_buf; /* 04 - input bit buffer. */
uint32_t bits; /* 08 - number of bits remaining in byte. */
};
/* huffman tree item. */
struct huffman_tree_item_s {
struct huffman_tree_item_s *next; /* 00 - pointer to next huffman tree item. */
struct huffman_tree_item_s *prev; /* 04 - pointer to prev huffman tree item (< 0 if none). */
uint32_t dcmp_byte; /* 08 - index of this item in item pointer array, decompressed byte value. */
uint32_t byte_value; /* 0C - some byte value. */
struct huffman_tree_item_s *parent; /* 10 - pointer to parent huffman tree item (NULL if none). */
struct huffman_tree_item_s *child; /* 14 - pointer to child huffman tree item. */
};
/* structure used for quick decompression. */
struct huffman_decompress_s {
uint32_t offs00; /* 00 - 1 if resolved. */
uint32_t bits; /* 04 - bit count. */
union {
uint32_t dcmp_byte; /* 08 - byte value for decompress (if bitCount <= 7). */
struct huffman_tree_item_s *p_item; /* 08 - huffman tree item (if number of bits is greater than 7). */
};
};
/* structure for huffman tree. */
struct huffman_tree_s {
uint32_t cmp0; /* 0000 - 1 if compression type 0. */
uint32_t offs0004; /* 0004 - some flag. */
struct huffman_tree_item_s items0008[0x203]; /* 0008 - huffman tree items. */
struct huffman_tree_item_s *item3050; /* 3050 - always NULL? */
struct huffman_tree_item_s *item3054; /* 3054 - pointer to huffman tree item. */
struct huffman_tree_item_s *item3058; /* 3058 - pointer to huffman tree item (< 0 if invalid). */
struct huffman_tree_item_s *item305C; /* 305C - usually NULL. */
struct huffman_tree_item_s *first; /* 3060 - pointer to top (first) huffman tree item. */
struct huffman_tree_item_s *last; /* 3064 - pointer to bottom (last) huffman tree item (< 0 if invalid). */
uint32_t items; /* 3068 - number of used huffman tree items. */
struct huffman_tree_item_s *items306C[0x102]; /* 306C - huffman tree item pointer array. */
struct huffman_decompress_s qd3474[0x80]; /* 3474 - array for quick decompression. */
uint8_t table_1502A630[]; /* some table to make struct size flexible. */
};
/* insert a new item into huffman tree. */
void libmpq__huffman_insert_item(
struct huffman_tree_item_s **p_item,
struct huffman_tree_item_s *item,
uint32_t where,
struct huffman_tree_item_s *item2
);
/* remove item from huffman tree. */
void libmpq__huffman_remove_item(
struct huffman_tree_item_s *hi
);
/* get previous item from huffman tree. */
struct huffman_tree_item_s *libmpq__huffman_previous_item(
struct huffman_tree_item_s *hi,
long value
);
/* get one bit from stream. */
uint32_t libmpq__huffman_get_1bit(
struct huffman_input_stream_s *is
);
/* get seven bit from stream. */
uint32_t libmpq__huffman_get_7bit(
struct huffman_input_stream_s *is
);
/* get eight bit from stream. */
uint32_t libmpq__huffman_get_8bit(
struct huffman_input_stream_s *is
);
/* call 1500E740. */
struct huffman_tree_item_s *libmpq__huffman_call_1500E740(
struct huffman_tree_s *ht
);
/* call 1500E820- */
void libmpq__huffman_call_1500E820(
struct huffman_tree_s *ht,
struct huffman_tree_item_s *p_item
);
/* initialize the huffman tree. */
void libmpq__huffman_tree_init(
struct huffman_tree_s *ht,
uint32_t cmp
);
/* build the huffman tree. */
void libmpq__huffman_tree_build(
struct huffman_tree_s *ht,
uint32_t cmp_type
);
/* decompress the stream using huffman compression. */
int32_t libmpq__do_decompress_huffman(
struct huffman_tree_s *ht,
struct huffman_input_stream_s *is,
uint8_t *out_buf,
uint32_t out_length
);
#endif /* _HUFFMAN_H */
+155
View File
@@ -0,0 +1,155 @@
/*
* mpq-internal.h -- some default types and defines, but only required for
* compilation of the library.
*
* Copyright (c) 2003-2008 Maik Broemme <[email protected]>
*
* 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 _MPQ_INTERNAL_H
#define _MPQ_INTERNAL_H
/* generic includes. */
#include <stdint.h>
#include <stdio.h>
/* define return value if nothing failed. */
#define LIBMPQ_SUCCESS 0 /* return value for all functions which success. */
/* define generic mpq archive information. */
#define LIBMPQ_HEADER 0x1A51504D /* mpq archive header ('MPQ\x1A') */
/* define the known archive versions. */
#define LIBMPQ_ARCHIVE_VERSION_ONE 0 /* version one used until world of warcraft. */
#define LIBMPQ_ARCHIVE_VERSION_TWO 1 /* version two used from world of warcraft - the burning crusade. */
/* define values used by blizzard as flags. */
#define LIBMPQ_FLAG_EXISTS 0x80000000 /* set if file exists, reset when the file was deleted. */
#define LIBMPQ_FLAG_ENCRYPTED 0x00010000 /* indicates whether file is encrypted. */
#define LIBMPQ_FLAG_COMPRESSED 0x0000FF00 /* file is compressed. */
#define LIBMPQ_FLAG_COMPRESS_PKZIP 0x00000100 /* compression made by pkware data compression library. */
#define LIBMPQ_FLAG_COMPRESS_MULTI 0x00000200 /* multiple compressions. */
#define LIBMPQ_FLAG_COMPRESS_NONE 0x00000300 /* no compression (no blizzard flag used by myself). */
#define LIBMPQ_FLAG_SINGLE 0x01000000 /* file is stored in one single sector, first seen in world of warcraft. */
#define LIBMPQ_FLAG_EXTRA 0x04000000 /* compressed block offset table has one extra entry. */
/* define generic hash values. */
#define LIBMPQ_HASH_FREE 0xFFFFFFFF /* hash table entry is empty and has always been empty. */
/* define special files. */
#define LIBMPQ_LISTFILE_NAME "(listfile)" /* internal listfile. */
#define LIBMPQ_SIGNATURE_NAME "(signature)" /* internal signature file. */
#define LIBMPQ_ATTRIBUTES_NAME "(attributes)" /* internal attributes file. */
/* define true and false, because not all systems have them. */
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
#ifdef _MSC_VER
#pragma pack(push,1)
#define PACK_STRUCT
#else
#define PACK_STRUCT __attribute__((packed))
#endif
/* mpq archive header. */
typedef struct {
uint32_t mpq_magic; /* the 0x1A51504D ('MPQ\x1A') signature. */
uint32_t header_size; /* mpq archive header size. */
uint32_t archive_size; /* size of mpq archive. */
uint16_t version; /* 0000 for starcraft and broodwar. */
uint16_t block_size; /* size of file block is (512 * 2 ^ block size). */
uint32_t hash_table_offset; /* file position of mpq_hash. */
uint32_t block_table_offset; /* file position of mpq_block, each entry has 16 bytes. */
uint32_t hash_table_count; /* number of entries in hash table. */
uint32_t block_table_count; /* number of entries in the block table. */
} PACK_STRUCT mpq_header_s;
/* mpq extended archive header, used since world of warcraft - the burning crusade. */
typedef struct {
uint64_t extended_offset; /* offset to the beginning of the extended block table, relative to the beginning of the archive. */
uint16_t hash_table_offset_high; /* upper 16 bits of the hash table offset for large archives. */
uint16_t block_table_offset_high;/* upper 16 bits of the block table offset for large archives.*/
} PACK_STRUCT mpq_header_ex_s;
/* hash entry, all files in the archive are searched by their hashes. */
typedef struct {
uint32_t hash_a; /* the first two uint32_ts are the encrypted file. */
uint32_t hash_b; /* the first two uint32_ts are the encrypted file. */
uint16_t locale; /* locale information. */
uint16_t platform; /* platform information and zero is default. */
uint32_t block_table_index; /* index to file description block. */
} PACK_STRUCT mpq_hash_s;
/* file description block contains informations about the file. */
typedef struct {
uint32_t offset; /* block file starting position in the archive. */
uint32_t packed_size; /* packed file size. */
uint32_t unpacked_size; /* unpacked file size. */
uint32_t flags; /* flags. */
} PACK_STRUCT mpq_block_s;
/* extended file description block contains information about the offset beyond 2^32 (4GB). */
typedef struct {
uint16_t offset_high; /* upper 16 bit of the file offset in archive. */
} PACK_STRUCT mpq_block_ex_s;
/* file structure used since diablo 1.00 (0x38 bytes). */
typedef struct {
uint32_t seed; /* seed used for file decrypt. */
uint32_t *packed_offset; /* position of each file block (only for packed files). */
uint32_t open_count; /* number of times it has been opened - used for freeing */
} PACK_STRUCT mpq_file_s;
/* map structure for valid blocks and hashes (first seen in warcraft 3 archives). */
typedef struct {
uint32_t block_table_indices; /* real mapping for file number to block entry. */
uint32_t block_table_diff; /* block table difference between valid blocks and invalid blocks before. */
} PACK_STRUCT mpq_map_s;
#ifdef _MSC_VER
#pragma pack(pop)
#endif
#undef PACK_STRUCT
/* archive structure used since diablo 1.00 by blizzard. */
struct mpq_archive {
/* generic file information. */
FILE *fp; /* file handle. */
/* generic size information. */
uint32_t block_size; /* size of the mpq block. */
off_t archive_offset; /* absolute start position of archive. */
/* archive related buffers and tables. */
mpq_header_s mpq_header; /* mpq file header. */
mpq_header_ex_s mpq_header_ex; /* mpq extended file header. */
mpq_hash_s *mpq_hash; /* hash table. */
mpq_block_s *mpq_block; /* block table. */
mpq_block_ex_s *mpq_block_ex; /* extended block table. */
mpq_file_s **mpq_file; /* pointer to the file pointers which are opened. */
/* non archive structure related members. */
mpq_map_s *mpq_map; /* map table between valid blocks and hashes. */
uint32_t files; /* number of files in archive, which could be extracted. */
};
#endif /* _MPQ_INTERNAL_H */
File diff suppressed because it is too large Load Diff
+98
View File
@@ -0,0 +1,98 @@
/*
* mpq.h -- some default types and defines.
*
* Copyright (c) 2003-2008 Maik Broemme <[email protected]>
*
* Some parts (the encryption and decryption stuff) were adapted from
* the C++ version of StormLib.h and StormPort.h included in stormlib.
* The C++ version belongs to the following authors:
*
* Ladislav Zezula <[email protected]>
* Marko Friedemann <[email protected]>
*
* 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 _MPQ_H
#define _MPQ_H
#ifdef __cplusplus
extern "C" {
#endif
/* generic includes. */
#include <stdint.h>
#include <sys/types.h>
#if defined(__GNUC__) && (__GNUC__ >= 4)
# define LIBMPQ_API __attribute__((visibility("default")))
#else
# define LIBMPQ_API
#endif
/* define errors. */
#define LIBMPQ_ERROR_OPEN -1 /* open error on file. */
#define LIBMPQ_ERROR_CLOSE -2 /* close error on file. */
#define LIBMPQ_ERROR_SEEK -3 /* lseek error on file. */
#define LIBMPQ_ERROR_READ -4 /* read error on file. */
#define LIBMPQ_ERROR_WRITE -5 /* write error on file. */
#define LIBMPQ_ERROR_MALLOC -6 /* memory allocation error. */
#define LIBMPQ_ERROR_FORMAT -7 /* format errror. */
#define LIBMPQ_ERROR_NOT_INITIALIZED -8 /* libmpq__init() wasn't called. */
#define LIBMPQ_ERROR_SIZE -9 /* buffer size is to small. */
#define LIBMPQ_ERROR_EXIST -10 /* file or block does not exist in archive. */
#define LIBMPQ_ERROR_DECRYPT -11 /* we don't know the decryption seed. */
#define LIBMPQ_ERROR_UNPACK -12 /* error on unpacking file. */
/* internal data structure. */
typedef struct mpq_archive mpq_archive_s;
/* file offset data type for API*/
typedef int64_t libmpq__off_t;
/* generic information about library. */
extern LIBMPQ_API const char *libmpq__version(void);
/* generic mpq archive information. */
extern LIBMPQ_API int32_t libmpq__archive_open(mpq_archive_s **mpq_archive, const char *mpq_filename, libmpq__off_t archive_offset);
extern LIBMPQ_API int32_t libmpq__archive_close(mpq_archive_s *mpq_archive);
extern LIBMPQ_API int32_t libmpq__archive_packed_size(mpq_archive_s *mpq_archive, libmpq__off_t *packed_size);
extern LIBMPQ_API int32_t libmpq__archive_unpacked_size(mpq_archive_s *mpq_archive, libmpq__off_t *unpacked_size);
extern LIBMPQ_API int32_t libmpq__archive_offset(mpq_archive_s *mpq_archive, libmpq__off_t *offset);
extern LIBMPQ_API int32_t libmpq__archive_version(mpq_archive_s *mpq_archive, uint32_t *version);
extern LIBMPQ_API int32_t libmpq__archive_files(mpq_archive_s *mpq_archive, uint32_t *files);
/* generic file processing functions. */
extern LIBMPQ_API int32_t libmpq__file_packed_size(mpq_archive_s *mpq_archive, uint32_t file_number, libmpq__off_t *packed_size);
extern LIBMPQ_API int32_t libmpq__file_unpacked_size(mpq_archive_s *mpq_archive, uint32_t file_number, libmpq__off_t *unpacked_size);
extern LIBMPQ_API int32_t libmpq__file_offset(mpq_archive_s *mpq_archive, uint32_t file_number, libmpq__off_t *offset);
extern LIBMPQ_API int32_t libmpq__file_blocks(mpq_archive_s *mpq_archive, uint32_t file_number, uint32_t *blocks);
extern LIBMPQ_API int32_t libmpq__file_encrypted(mpq_archive_s *mpq_archive, uint32_t file_number, uint32_t *encrypted);
extern LIBMPQ_API int32_t libmpq__file_compressed(mpq_archive_s *mpq_archive, uint32_t file_number, uint32_t *compressed);
extern LIBMPQ_API int32_t libmpq__file_imploded(mpq_archive_s *mpq_archive, uint32_t file_number, uint32_t *imploded);
extern LIBMPQ_API int32_t libmpq__file_number(mpq_archive_s *mpq_archive, const char *filename, uint32_t *number);
extern LIBMPQ_API int32_t libmpq__file_read(mpq_archive_s *mpq_archive, uint32_t file_number, uint8_t *out_buf, libmpq__off_t out_size, libmpq__off_t *transferred);
/* generic block processing functions. */
extern LIBMPQ_API int32_t libmpq__block_open_offset(mpq_archive_s *mpq_archive, uint32_t file_number);
extern LIBMPQ_API int32_t libmpq__block_close_offset(mpq_archive_s *mpq_archive, uint32_t file_number);
extern LIBMPQ_API int32_t libmpq__block_unpacked_size(mpq_archive_s *mpq_archive, uint32_t file_number, uint32_t block_number, libmpq__off_t *unpacked_size);
extern LIBMPQ_API int32_t libmpq__block_read(mpq_archive_s *mpq_archive, uint32_t file_number, uint32_t block_number, uint8_t *out_buf, libmpq__off_t out_size, libmpq__off_t *transferred);
#ifdef __cplusplus
}
#endif
#endif /* _MPQ_H */
+250
View File
@@ -0,0 +1,250 @@
/*
* wave.c -- this file contains decompression methods used by mpq-tools
* to decompress wave files.
*
* Copyright (c) 2003-2007 Maik Broemme <[email protected]>
*
* This source was adepted from the C++ version of wave.cpp included
* in stormlib. The C++ version belongs to the following authors:
*
* Ladislav Zezula <[email protected]>
* Tom Amigo <[email protected]>
*
* 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.
*/
/* generic includes. */
#include <stdint.h>
/* libmpq generic includes. */
#include "wave.h"
/* table necessary dor decompression. */
static const uint32_t 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
};
/* table necessary dor decompression. */
static const uint32_t 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
};
/* this function decompress a wave file, mono or stereo, 1500F230 offset. */
int32_t libmpq__do_decompress_wave(uint8_t *out_buf, int32_t out_length, uint8_t *in_buf, int32_t in_length, int32_t channels) {
/* some common variables. */
byte_and_int16_t out;
byte_and_int16_t in;
uint32_t index;
int32_t nr_array1[2];
int32_t nr_array2[2];
uint32_t count = 0;
/* end on input buffer. */
uint8_t *in_end = in_buf + in_length;
/* assign default values. */
out.pb = out_buf;
in.pb = in_buf;
nr_array1[0] = 0x2C;
nr_array1[1] = 0x2C;
/* increase. */
in.pw++;
/* 15007AD7 */
for (count = 0; count < channels; count++) {
/* some common variables. */
int32_t temp;
/* save pointer. */
temp = *(int16_t *)in.pw++;
nr_array2[count] = temp;
/* check if should break. */
if (out_length < 2) {
return out.pb - out_buf;
}
/* return values. */
*out.pw++ = (uint16_t)temp;
out_length -= 2;
}
/* decrease channels. */
index = channels - 1;
/* loop through input buffer until end reached. */
while (in.pb < in_end) {
/* save the byte. */
uint8_t one_byte = *in.pb++;
/* check how many channels and set index. */
if (channels == 2) {
index = (index == 0) ? 1 : 0;
}
/* 15007B25 - get one byte from input buffer. */
if (one_byte & 0x80) {
/* 15007B32 */
switch (one_byte & 0x7F) {
case 0:
/* 15007B8E */
if (nr_array1[index] != 0) {
nr_array1[index]--;
}
/* check if should break. */
if (out_length < 2) {
break;
}
/* return values. */
*out.pw++ = (uint16_t)nr_array2[index];
out_length -= 2;
/* continue loop. */
continue;
case 1:
/* 15007B72 and EBX. */
nr_array1[index] += 8;
/* check index. */
if (nr_array1[index] > 0x58) {
nr_array1[index] = 0x58;
}
/* check how many channels and set index. */
if (channels == 2) {
index = (index == 0) ? 1 : 0;
}
/* continue loop. */
continue;
case 2:
/* nothing todo, so continue. */
continue;
default:
/* decrease index. */
nr_array1[index] -= 8;
/* check index. */
if (nr_array1[index] < 0) {
nr_array1[index] = 0;
}
/* check if two channels left. */
if (channels != 2) {
continue;
}
index = (index == 0) ? 1 : 0;
/* continue loop. */
continue;
}
} else {
/* EDI */
uint32_t temp1 = wave_table_1503f1a0[nr_array1[index]];
/* ESI */
uint32_t temp2 = temp1 >> in_buf[1];
/* ECX */
int32_t temp3 = nr_array2[index];
/* EBX = one byte. */
if (one_byte & 0x01) {
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 <= (int32_t)0xFFFF8000) {
temp3 = (int32_t)0xFFFF8000;
}
} else {
temp3 += temp2;
if (temp3 >= 0x7FFF) {
temp3 = 0x7FFF;
}
}
/* restore index. */
nr_array2[index] = temp3;
/* check if should break. */
if (out_length < 2) {
break;
}
/* assign values. */
temp2 = nr_array1[index];
one_byte &= 0x1F;
*out.pw++ = (uint16_t)temp3;
out_length -= 2;
temp2 += wave_table_1503f120[one_byte];
nr_array1[index] = temp2;
/* check index. */
if (nr_array1[index] < 0) {
nr_array1[index] = 0;
} else {
/* check index. */
if (nr_array1[index] > 0x58) {
nr_array1[index] = 0x58;
}
}
}
}
/* return copied bytes. */
return (out.pb - out_buf);
}
+45
View File
@@ -0,0 +1,45 @@
/*
* wave.h -- header file for wav unplode functions used by mpq-tools.
*
* Copyright (c) 2003-2007 Maik Broemme <[email protected]>
*
* 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 <[email protected]>
*
* 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
/* buffer. */
typedef union {
uint16_t *pw;
uint8_t *pb;
} byte_and_int16_t;
/* decompress a wave file, mono or stereo, 1500F230 offset. */
int32_t libmpq__do_decompress_wave(
uint8_t *out_buf,
int32_t out_length,
uint8_t *in_buf,
int32_t in_length,
int32_t channels
);
#endif /* _WAVE_H */
+8
View File
@@ -0,0 +1,8 @@
# minimum required automake 1.6
AUTOMAKE_OPTIONS = 1.6
# the main programs.
bin_PROGRAMS = crypt_buf_gen
# sources for crypt_buf_gen program.
crypt_buf_gen_SOURCES = crypt_buf_gen.c
+85
View File
@@ -0,0 +1,85 @@
/*
* crypt_buf_gen.c -- tool to re-create the static decryption buffer.
*
* Copyright (c) 2003-2008 Maik Broemme <[email protected]>
* Copyright (c) 2008 Georg Lukas <[email protected]>
*
* 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.
*
*
* Usage:
* $ make crypt_buf_gen
* $ ./crypt_buf_gen > crypt_buf.h
*
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
static uint32_t *buffer;
int32_t libmpq__buffer_init() {
buffer = malloc(sizeof(uint32_t) * 0x500);
if (!buffer)
return -1;
/* some common variables. */
uint32_t seed = 0x00100001;
uint32_t index1 = 0;
uint32_t index2 = 0;
uint32_t i;
/* initialize the decryption buffer. */
for (index1 = 0; index1 < 0x100; index1++) {
for(index2 = index1, i = 0; i < 5; i++, index2 += 0x100) {
/* some common variables. */
uint32_t temp1, temp2;
/* temporary copy. */
seed = (seed * 125 + 3) % 0x2AAAAB;
temp1 = (seed & 0xFFFF) << 0x10;
/* temporary copy. */
seed = (seed * 125 + 3) % 0x2AAAAB;
temp2 = (seed & 0xFFFF);
/* assign buffer. */
buffer[index2] = (temp1 | temp2);
}
}
/* if no error was found, return zero. */
return 0;
}
int main() {
if (libmpq__buffer_init() != 0)
perror("libmpq__buffer_init()");
int x;
printf("/* DO NOT CHANGE! this file is auto-generated by crypt_buf_gen.c */\n");
printf("static const uint32_t crypt_buf[0x500] = {\n\t");
for (x = 0; x < 0x500; x++) {
printf("0x%08x", buffer[x]);
if (x < 0x500 - 1) {
if (x % 6 == 5)
printf(",\n\t");
else
printf(", ");
}
}
printf("\n};\n");
}
+115
View File
@@ -0,0 +1,115 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectName>libmpq</ProjectName>
<ProjectGuid>{03AB0F44-628E-4855-99A0-C98A1EB52C50}</ProjectGuid>
<RootNamespace>libmpq</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\bin\$(Platform)_$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\bin\$(ProjectName)__$(Platform)_$(Configuration)\</IntDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\bin\$(Platform)_$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\bin\$(ProjectName)__$(Platform)_$(Configuration)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\; ..\..\..\..\dep\include\zlib; ..\..\..\..\dep\include\bzip2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<CompileAs>CompileAsC</CompileAs>
</ClCompile>
<ProjectReference>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
</ProjectReference>
<Lib>
<AdditionalLibraryDirectories>..\dep\lib\$(Platform)_$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\; ..\..\..\..\dep\include\zlib; ..\..\..\..\dep\include\bzip2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>CompileAsC</CompileAs>
</ClCompile>
<ProjectReference>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
</ProjectReference>
<Lib>
<AdditionalLibraryDirectories>..\dep\lib\$(Platform)_$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Lib>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\libmpq\common.c" />
<ClCompile Include="..\..\libmpq\explode.c" />
<ClCompile Include="..\..\libmpq\extract.c" />
<ClCompile Include="..\..\libmpq\huffman.c" />
<ClCompile Include="..\..\libmpq\mpq.c" />
<ClCompile Include="..\..\libmpq\wave.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\libmpq\common.h" />
<ClInclude Include="..\..\libmpq\crypt_buf.h" />
<ClInclude Include="..\..\libmpq\explode.h" />
<ClInclude Include="..\..\libmpq\extract.h" />
<ClInclude Include="..\..\libmpq\huffman.h" />
<ClInclude Include="..\..\libmpq\mpq-internal.h" />
<ClInclude Include="..\..\libmpq\mpq.h" />
<ClInclude Include="..\..\libmpq\wave.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\win\VC100\bzip2.vcxproj">
<Project>{b96f612a-c91d-43b3-a4c3-d4294817ec6c}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
<ProjectReference Include="..\..\..\..\win\VC100\zlib.vcxproj">
<Project>{8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
+81
View File
@@ -0,0 +1,81 @@
/* config.h. Generated from config.h.in by configure. */
/* config.h.in. Generated from configure.ac by autoheader. */
/* Define to 1 if you have the <dlfcn.h> header file. */
#define HAVE_DLFCN_H 1
/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
#define HAVE_FSEEKO 1
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define to 1 if you have the `bz2' library (-lbz2). */
#define HAVE_LIBBZ2 1
/* Define to 1 if you have the `z' library (-lz). */
#define HAVE_LIBZ 1
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 0
/* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
#define LT_OBJDIR ".libs/"
/* Name of package */
#define PACKAGE "libmpq"
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT "[email protected]"
/* Define to the full name of this package. */
#define PACKAGE_NAME "libmpq"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "libmpq 0.4.2"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "libmpq"
/* Define to the home page for this package. */
#define PACKAGE_URL ""
/* Define to the version of this package. */
#define PACKAGE_VERSION "0.4.2"
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Version number of package */
#define VERSION "0.4.2"
/* Number of bits in a file offset, on hosts where this is settable. */
/* #undef _FILE_OFFSET_BITS */
/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
/* #undef _LARGEFILE_SOURCE */
/* Define for large files, on AIX-style hosts. */
/* #undef _LARGE_FILES */
+31
View File
@@ -0,0 +1,31 @@
Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmpq", "VS100\libmpq.vcxproj", "{03AB0F44-628E-4855-99A0-C98A1EB52C50}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib", "..\..\..\win\VC100\zlib.vcxproj", "{8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bzip2", "..\..\..\win\VC100\bzip2.vcxproj", "{B96F612A-C91D-43B3-A4C3-D4294817EC6C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{03AB0F44-628E-4855-99A0-C98A1EB52C50}.Debug|Win32.ActiveCfg = Debug|Win32
{03AB0F44-628E-4855-99A0-C98A1EB52C50}.Debug|Win32.Build.0 = Debug|Win32
{03AB0F44-628E-4855-99A0-C98A1EB52C50}.Release|Win32.ActiveCfg = Release|Win32
{03AB0F44-628E-4855-99A0-C98A1EB52C50}.Release|Win32.Build.0 = Release|Win32
{8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}.Debug|Win32.ActiveCfg = Debug|Win32
{8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}.Debug|Win32.Build.0 = Debug|Win32
{8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}.Release|Win32.ActiveCfg = Release|Win32
{8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}.Release|Win32.Build.0 = Release|Win32
{B96F612A-C91D-43B3-A4C3-D4294817EC6C}.Debug|Win32.ActiveCfg = Debug|Win32
{B96F612A-C91D-43B3-A4C3-D4294817EC6C}.Debug|Win32.Build.0 = Debug|Win32
{B96F612A-C91D-43B3-A4C3-D4294817EC6C}.Release|Win32.ActiveCfg = Release|Win32
{B96F612A-C91D-43B3-A4C3-D4294817EC6C}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
+35
View File
@@ -0,0 +1,35 @@
Microsoft Visual Studio Solution File, Format Version 10.00
# Visual C++ Express 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmpq", "VC90\libmpq.vcproj", "{03AB0F44-628E-4855-99A0-C98A1EB52C50}"
ProjectSection(ProjectDependencies) = postProject
{B96F612A-C91D-43B3-A4C3-D4294817EC6C} = {B96F612A-C91D-43B3-A4C3-D4294817EC6C}
{8F1DEA42-6A5B-4B62-839D-C141A7BFACF2} = {8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib", "..\..\..\win\VC90\zlib.vcproj", "{8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bzip2", "..\..\..\win\VC90\bzip2.vcproj", "{B96F612A-C91D-43B3-A4C3-D4294817EC6C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{03AB0F44-628E-4855-99A0-C98A1EB52C50}.Debug|Win32.ActiveCfg = Debug|Win32
{03AB0F44-628E-4855-99A0-C98A1EB52C50}.Debug|Win32.Build.0 = Debug|Win32
{03AB0F44-628E-4855-99A0-C98A1EB52C50}.Release|Win32.ActiveCfg = Release|Win32
{03AB0F44-628E-4855-99A0-C98A1EB52C50}.Release|Win32.Build.0 = Release|Win32
{8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}.Debug|Win32.ActiveCfg = Debug|Win32
{8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}.Debug|Win32.Build.0 = Debug|Win32
{8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}.Release|Win32.ActiveCfg = Release|Win32
{8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}.Release|Win32.Build.0 = Release|Win32
{B96F612A-C91D-43B3-A4C3-D4294817EC6C}.Debug|Win32.ActiveCfg = Debug|Win32
{B96F612A-C91D-43B3-A4C3-D4294817EC6C}.Debug|Win32.Build.0 = Debug|Win32
{B96F612A-C91D-43B3-A4C3-D4294817EC6C}.Release|Win32.ActiveCfg = Release|Win32
{B96F612A-C91D-43B3-A4C3-D4294817EC6C}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
+247
View File
@@ -0,0 +1,247 @@
// ISO C9x compliant stdint.h for Microsoft Visual Studio
// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
//
// Copyright (c) 2006-2008 Alexander Chemeris
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. The name of the author may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef _MSC_VER // [
#error "Use this header only with Microsoft Visual C++ compilers!"
#endif // _MSC_VER ]
#ifndef _MSC_STDINT_H_ // [
#define _MSC_STDINT_H_
#if _MSC_VER > 1000
#pragma once
#endif
#include <limits.h>
// For Visual Studio 6 in C++ mode and for many Visual Studio versions when
// compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}'
// or compiler give many errors like this:
// error C2733: second C linkage of overloaded function 'wmemchr' not allowed
#ifdef __cplusplus
extern "C" {
#endif
# include <wchar.h>
#ifdef __cplusplus
}
#endif
// Define _W64 macros to mark types changing their size, like intptr_t.
#ifndef _W64
# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
# define _W64 __w64
# else
# define _W64
# endif
#endif
// 7.18.1 Integer types
// 7.18.1.1 Exact-width integer types
// Visual Studio 6 and Embedded Visual C++ 4 doesn't
// realize that, e.g. char has the same size as __int8
// so we give up on __intX for them.
#if (_MSC_VER < 1300)
typedef signed char int8_t;
typedef signed short int16_t;
typedef signed int int32_t;
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
#else
typedef signed __int8 int8_t;
typedef signed __int16 int16_t;
typedef signed __int32 int32_t;
typedef unsigned __int8 uint8_t;
typedef unsigned __int16 uint16_t;
typedef unsigned __int32 uint32_t;
#endif
typedef signed __int64 int64_t;
typedef unsigned __int64 uint64_t;
// 7.18.1.2 Minimum-width integer types
typedef int8_t int_least8_t;
typedef int16_t int_least16_t;
typedef int32_t int_least32_t;
typedef int64_t int_least64_t;
typedef uint8_t uint_least8_t;
typedef uint16_t uint_least16_t;
typedef uint32_t uint_least32_t;
typedef uint64_t uint_least64_t;
// 7.18.1.3 Fastest minimum-width integer types
typedef int8_t int_fast8_t;
typedef int16_t int_fast16_t;
typedef int32_t int_fast32_t;
typedef int64_t int_fast64_t;
typedef uint8_t uint_fast8_t;
typedef uint16_t uint_fast16_t;
typedef uint32_t uint_fast32_t;
typedef uint64_t uint_fast64_t;
// 7.18.1.4 Integer types capable of holding object pointers
#ifdef _WIN64 // [
typedef signed __int64 intptr_t;
typedef unsigned __int64 uintptr_t;
#else // _WIN64 ][
typedef _W64 signed int intptr_t;
typedef _W64 unsigned int uintptr_t;
#endif // _WIN64 ]
// 7.18.1.5 Greatest-width integer types
typedef int64_t intmax_t;
typedef uint64_t uintmax_t;
// 7.18.2 Limits of specified-width integer types
#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259
// 7.18.2.1 Limits of exact-width integer types
#define INT8_MIN ((int8_t)_I8_MIN)
#define INT8_MAX _I8_MAX
#define INT16_MIN ((int16_t)_I16_MIN)
#define INT16_MAX _I16_MAX
#define INT32_MIN ((int32_t)_I32_MIN)
#define INT32_MAX _I32_MAX
#define INT64_MIN ((int64_t)_I64_MIN)
#define INT64_MAX _I64_MAX
#define UINT8_MAX _UI8_MAX
#define UINT16_MAX _UI16_MAX
#define UINT32_MAX _UI32_MAX
#define UINT64_MAX _UI64_MAX
// 7.18.2.2 Limits of minimum-width integer types
#define INT_LEAST8_MIN INT8_MIN
#define INT_LEAST8_MAX INT8_MAX
#define INT_LEAST16_MIN INT16_MIN
#define INT_LEAST16_MAX INT16_MAX
#define INT_LEAST32_MIN INT32_MIN
#define INT_LEAST32_MAX INT32_MAX
#define INT_LEAST64_MIN INT64_MIN
#define INT_LEAST64_MAX INT64_MAX
#define UINT_LEAST8_MAX UINT8_MAX
#define UINT_LEAST16_MAX UINT16_MAX
#define UINT_LEAST32_MAX UINT32_MAX
#define UINT_LEAST64_MAX UINT64_MAX
// 7.18.2.3 Limits of fastest minimum-width integer types
#define INT_FAST8_MIN INT8_MIN
#define INT_FAST8_MAX INT8_MAX
#define INT_FAST16_MIN INT16_MIN
#define INT_FAST16_MAX INT16_MAX
#define INT_FAST32_MIN INT32_MIN
#define INT_FAST32_MAX INT32_MAX
#define INT_FAST64_MIN INT64_MIN
#define INT_FAST64_MAX INT64_MAX
#define UINT_FAST8_MAX UINT8_MAX
#define UINT_FAST16_MAX UINT16_MAX
#define UINT_FAST32_MAX UINT32_MAX
#define UINT_FAST64_MAX UINT64_MAX
// 7.18.2.4 Limits of integer types capable of holding object pointers
#ifdef _WIN64 // [
# define INTPTR_MIN INT64_MIN
# define INTPTR_MAX INT64_MAX
# define UINTPTR_MAX UINT64_MAX
#else // _WIN64 ][
# define INTPTR_MIN INT32_MIN
# define INTPTR_MAX INT32_MAX
# define UINTPTR_MAX UINT32_MAX
#endif // _WIN64 ]
// 7.18.2.5 Limits of greatest-width integer types
#define INTMAX_MIN INT64_MIN
#define INTMAX_MAX INT64_MAX
#define UINTMAX_MAX UINT64_MAX
// 7.18.3 Limits of other integer types
#ifdef _WIN64 // [
# define PTRDIFF_MIN _I64_MIN
# define PTRDIFF_MAX _I64_MAX
#else // _WIN64 ][
# define PTRDIFF_MIN _I32_MIN
# define PTRDIFF_MAX _I32_MAX
#endif // _WIN64 ]
#define SIG_ATOMIC_MIN INT_MIN
#define SIG_ATOMIC_MAX INT_MAX
#ifndef SIZE_MAX // [
# ifdef _WIN64 // [
# define SIZE_MAX _UI64_MAX
# else // _WIN64 ][
# define SIZE_MAX _UI32_MAX
# endif // _WIN64 ]
#endif // SIZE_MAX ]
// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
#ifndef WCHAR_MIN // [
# define WCHAR_MIN 0
#endif // WCHAR_MIN ]
#ifndef WCHAR_MAX // [
# define WCHAR_MAX _UI16_MAX
#endif // WCHAR_MAX ]
#define WINT_MIN 0
#define WINT_MAX _UI16_MAX
#endif // __STDC_LIMIT_MACROS ]
// 7.18.4 Limits of other integer types
#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260
// 7.18.4.1 Macros for minimum-width integer constants
#define INT8_C(val) val##i8
#define INT16_C(val) val##i16
#define INT32_C(val) val##i32
#define INT64_C(val) val##i64
#define UINT8_C(val) val##ui8
#define UINT16_C(val) val##ui16
#define UINT32_C(val) val##ui32
#define UINT64_C(val) val##ui64
// 7.18.4.2 Macros for greatest-width integer constants
#define INTMAX_C INT64_C
#define UINTMAX_C UINT64_C
#endif // __STDC_CONSTANT_MACROS ]
#endif // _MSC_STDINT_H_ ]
+85
View File
@@ -0,0 +1,85 @@
# Copyright (C) 2005-2009 MaNGOS project <http://getmangos.com/>
#
# This file is free software; as a special exception the author 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.
cmake_minimum_required (VERSION 2.6)
project (MANGOS_VMAP_ASSEMB_IO)
set(CMAKE_VERBOSE_MAKEFILE true)
# uncomment next line to disable debug mode
ADD_DEFINITIONS("-DIOMAP_DEBUG")
ADD_DEFINITIONS("-Wall")
ADD_DEFINITIONS("-ggdb")
ADD_DEFINITIONS("-O3")
include_directories(../../src/shared/vmap/)
include_directories(../../dep/include/g3dlite/)
include_directories(../../dep/ACE_wrappers/)
include_directories(../../objdir/dep/ACE_wrappers)
include_directories(../../src/framework/)
add_library(g3dlite ../../dep/src/g3dlite/AABox.cpp
../../dep/src/g3dlite/Box.cpp
../../dep/src/g3dlite/Crypto.cpp
../../dep/src/g3dlite/format.cpp
../../dep/src/g3dlite/Matrix3.cpp
../../dep/src/g3dlite/Plane.cpp
../../dep/src/g3dlite/System.cpp
../../dep/src/g3dlite/Triangle.cpp
../../dep/src/g3dlite/Vector3.cpp
../../dep/src/g3dlite/Vector4.cpp
../../dep/src/g3dlite/debugAssert.cpp
../../dep/src/g3dlite/fileutils.cpp
../../dep/src/g3dlite/g3dmath.cpp
../../dep/src/g3dlite/g3dfnmatch.cpp
../../dep/src/g3dlite/prompt.cpp
../../dep/src/g3dlite/stringutils.cpp
../../dep/src/g3dlite/Any.cpp
../../dep/src/g3dlite/BinaryFormat.cpp
../../dep/src/g3dlite/BinaryInput.cpp
../../dep/src/g3dlite/BinaryOutput.cpp
../../dep/src/g3dlite/Capsule.cpp
../../dep/src/g3dlite/CollisionDetection.cpp
../../dep/src/g3dlite/CoordinateFrame.cpp
../../dep/src/g3dlite/Cylinder.cpp
../../dep/src/g3dlite/Line.cpp
../../dep/src/g3dlite/LineSegment.cpp
../../dep/src/g3dlite/Log.cpp
../../dep/src/g3dlite/Matrix4.cpp
../../dep/src/g3dlite/MemoryManager.cpp
../../dep/src/g3dlite/Quat.cpp
../../dep/src/g3dlite/Random.cpp
../../dep/src/g3dlite/Ray.cpp
../../dep/src/g3dlite/ReferenceCount.cpp
../../dep/src/g3dlite/Sphere.cpp
../../dep/src/g3dlite/TextInput.cpp
../../dep/src/g3dlite/TextOutput.cpp
../../dep/src/g3dlite/UprightFrame.cpp
../../dep/src/g3dlite/Vector2.cpp
)
add_library(vmap
../../src/shared/vmap/BIH.cpp
../../src/shared/vmap/VMapManager2.cpp
../../src/shared/vmap/MapTree.cpp
../../src/shared/vmap/TileAssembler.cpp
../../src/shared/vmap/WorldModel.cpp
../../src/shared/vmap/ModelInstance.cpp
)
target_link_libraries(vmap g3dlite z)
add_executable(vmap_assembler vmap_assembler.cpp)
target_link_libraries(vmap_assembler vmap)
# add_executable(vmap_test coordinate_test.cpp)
# target_link_libraries(vmap_test vmap)
@@ -0,0 +1,214 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{572FFF74-480C-4472-8ABF-81733BB4049D}</ProjectGuid>
<RootNamespace>vmap_assembler</RootNamespace>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\bin\$(Platform)_$(Configuration)\</OutDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\bin\$(Platform)_$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\bin\$(ProjectName)__$(Platform)_$(Configuration)\</IntDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\bin\$(ProjectName)__$(Platform)_$(Configuration)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</LinkIncremental>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</LinkIncremental>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\bin\$(Platform)_$(Configuration)\</OutDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\bin\$(Platform)_$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\bin\$(ProjectName)__$(Platform)_$(Configuration)\</IntDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\bin\$(ProjectName)__$(Platform)_$(Configuration)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\dep\include\g3dlite;..\..\..\src\shared\vmap;..\..\..\src\framework;..\..\..\dep\ACE_wrappers;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<OutputFile>$(OutDir)vmap_assembler.exe</OutputFile>
<IgnoreSpecificDefaultLibraries>
</IgnoreSpecificDefaultLibraries>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(OutDir)$(TargetName).pdb</ProgramDatabaseFile>
<SubSystem>Console</SubSystem>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<TargetMachine>MachineX86</TargetMachine>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<AdditionalLibraryDirectories>
</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\dep\include\g3dlite;..\..\..\src\shared\vmap;..\..\..\src\framework;..\..\..\dep\ACE_wrappers;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<OutputFile>$(OutDir)vmap_assembler.exe</OutputFile>
<IgnoreSpecificDefaultLibraries>
</IgnoreSpecificDefaultLibraries>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(OutDir)$(TargetName).pdb</ProgramDatabaseFile>
<SubSystem>Console</SubSystem>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<AdditionalIncludeDirectories>..\..\..\dep\include\g3dlite;..\..\..\src\shared\vmap;..\..\..\src\framework;..\..\..\dep\ACE_wrappers;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<OutputFile>$(OutDir)vmap_assembler.exe</OutputFile>
<GenerateDebugInformation>false</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<AdditionalIncludeDirectories>..\..\..\dep\include\g3dlite;..\..\..\src\shared\vmap;..\..\..\src\framework;..\..\..\dep\ACE_wrappers;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<OutputFile>$(OutDir)vmap_assembler.exe</OutputFile>
<GenerateDebugInformation>false</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\vmap_assembler.cpp" />
<ClCompile Include="..\..\..\src\shared\vmap\BIH.cpp" />
<ClCompile Include="..\..\..\src\shared\vmap\MapTree.cpp" />
<ClCompile Include="..\..\..\src\shared\vmap\ModelInstance.cpp" />
<ClCompile Include="..\..\..\src\shared\vmap\TileAssembler.cpp" />
<ClCompile Include="..\..\..\src\shared\vmap\VMapManager2.cpp" />
<ClCompile Include="..\..\..\src\shared\vmap\WorldModel.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\src\shared\vmap\BIH.h" />
<ClInclude Include="..\..\..\src\shared\vmap\MapTree.h" />
<ClInclude Include="..\..\..\src\shared\vmap\ModelInstance.h" />
<ClInclude Include="..\..\..\src\shared\vmap\TileAssembler.h" />
<ClInclude Include="..\..\..\src\shared\vmap\VMapManager2.h" />
<ClInclude Include="..\..\..\src\shared\vmap\VMapTools.h" />
<ClInclude Include="..\..\..\src\shared\vmap\WorldModel.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\win\VC100\g3dlite.vcxproj">
<Project>{8072769e-cf10-48bf-b9e1-12752a5dac6e}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
<ProjectReference Include="..\..\..\win\VC100\zlib.vcxproj">
<Project>{8f1dea42-6a5b-4b62-839d-c141a7bfacf2}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
@@ -12,8 +12,8 @@
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="..\Debug"
IntermediateDirectory="..\Debug\obj"
OutputDirectory="..\bin\$(PlatformName)_$(ConfigurationName)\"
IntermediateDirectory="bin\$(ProjectName)__$(PlatformName)_$(ConfigurationName)\"
ConfigurationType="1"
CharacterSet="2">
<Tool
@@ -61,8 +61,8 @@
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="..\Release"
IntermediateDirectory="..\Release\obj"
OutputDirectory="..\bin\$(PlatformName)_$(ConfigurationName)\"
IntermediateDirectory="bin\$(ProjectName)__$(PlatformName)_$(ConfigurationName)\"
ConfigurationType="1"
CharacterSet="2">
<Tool
+169 -113
View File
@@ -16,8 +16,8 @@
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="..\Debug"
IntermediateDirectory="..\Debug\obj"
OutputDirectory="..\bin\$(PlatformName)_$(ConfigurationName)\"
IntermediateDirectory="bin\$(ProjectName)__$(PlatformName)_$(ConfigurationName)\"
ConfigurationType="1"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
CharacterSet="2"
@@ -96,8 +96,8 @@
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="..\Release"
IntermediateDirectory="..\Release\obj"
OutputDirectory="..\bin\$(PlatformName)_$(ConfigurationName)\"
IntermediateDirectory="bin\$(ProjectName)__$(PlatformName)_$(ConfigurationName)\"
ConfigurationType="1"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
CharacterSet="2"
@@ -190,67 +190,27 @@
Name="vmaplib"
>
<File
RelativePath="..\..\..\src\shared\vmap\AABSPTree.h"
RelativePath="..\..\..\src\shared\vmap\BIH.cpp"
>
</File>
<File
RelativePath="..\..\..\src\shared\vmap\BaseModel.cpp"
RelativePath="..\..\..\src\shared\vmap\BIH.h"
>
</File>
<File
RelativePath="..\..\..\src\shared\vmap\BaseModel.h"
RelativePath="..\..\..\src\shared\vmap\MapTree.cpp"
>
</File>
<File
RelativePath="..\..\..\src\shared\vmap\CoordModelMapping.cpp"
RelativePath="..\..\..\src\shared\vmap\MapTree.h"
>
</File>
<File
RelativePath="..\..\..\src\shared\vmap\CoordModelMapping.h"
RelativePath="..\..\..\src\shared\vmap\ModelInstance.cpp"
>
</File>
<File
RelativePath="..\..\..\src\shared\vmap\DebugCmdLogger.cpp"
>
</File>
<File
RelativePath="..\..\..\src\shared\vmap\DebugCmdLogger.h"
>
</File>
<File
RelativePath="..\..\..\src\shared\vmap\ManagedModelContainer.cpp"
>
</File>
<File
RelativePath="..\..\..\src\shared\vmap\ManagedModelContainer.h"
>
</File>
<File
RelativePath="..\..\..\src\shared\vmap\ModelContainer.cpp"
>
</File>
<File
RelativePath="..\..\..\src\shared\vmap\ModelContainer.h"
>
</File>
<File
RelativePath="..\..\..\src\shared\vmap\NodeValueAccess.h"
>
</File>
<File
RelativePath="..\..\..\src\shared\vmap\ShortBox.h"
>
</File>
<File
RelativePath="..\..\..\src\shared\vmap\ShortVector.h"
>
</File>
<File
RelativePath="..\..\..\src\shared\vmap\SubModel.cpp"
>
</File>
<File
RelativePath="..\..\..\src\shared\vmap\SubModel.h"
RelativePath="..\..\..\src\shared\vmap\ModelInstance.h"
>
</File>
<File
@@ -262,41 +222,37 @@
>
</File>
<File
RelativePath="..\..\..\src\shared\vmap\TreeNode.cpp"
RelativePath="..\..\..\src\shared\vmap\VMapManager2.cpp"
>
</File>
<File
RelativePath="..\..\..\src\shared\vmap\TreeNode.h"
RelativePath="..\..\..\src\shared\vmap\VMapManager2.h"
>
</File>
<File
RelativePath="..\..\..\src\shared\vmap\VMapTools.h"
>
</File>
<File
RelativePath="..\..\..\src\shared\vmap\WorldModel.cpp"
>
</File>
<File
RelativePath="..\..\..\src\shared\vmap\WorldModel.h"
>
</File>
</Filter>
<Filter
Name="g3dlite"
>
<File
RelativePath="..\..\..\dep\src\g3dlite\AABox.cpp"
>
</File>
<File
RelativePath="..\..\..\dep\include\g3dlite\G3D\AABox.h"
>
</File>
<File
RelativePath="..\..\..\dep\include\g3dlite\G3D\AABSPTree.h"
>
</File>
<File
RelativePath="..\..\..\dep\include\g3dlite\G3D\Array.h"
>
</File>
<File
RelativePath="..\..\..\dep\src\g3dlite\Box.cpp"
>
</File>
<File
RelativePath="..\..\..\dep\include\g3dlite\G3D\Box.h"
>
@@ -309,10 +265,6 @@
RelativePath="..\..\..\dep\include\g3dlite\G3D\CoordinateFrame.h"
>
</File>
<File
RelativePath="..\..\..\dep\src\g3dlite\Crypto.cpp"
>
</File>
<File
RelativePath="..\..\..\dep\include\g3dlite\G3D\Crypto.h"
>
@@ -321,10 +273,6 @@
RelativePath="..\..\..\dep\include\g3dlite\G3D\debug.h"
>
</File>
<File
RelativePath="..\..\..\dep\src\g3dlite\format.cpp"
>
</File>
<File
RelativePath="..\..\..\dep\include\g3dlite\G3D\format.h"
>
@@ -333,10 +281,6 @@
RelativePath="..\..\..\dep\include\g3dlite\G3D\g3dmath.h"
>
</File>
<File
RelativePath="..\..\..\dep\include\g3dlite\G3D\g3dmath.inl"
>
</File>
<File
RelativePath="..\..\..\dep\include\g3dlite\G3D\GCamera.h"
>
@@ -345,18 +289,10 @@
RelativePath="..\..\..\dep\include\g3dlite\G3D\Line.h"
>
</File>
<File
RelativePath="..\..\..\dep\src\g3dlite\Matrix3.cpp"
>
</File>
<File
RelativePath="..\..\..\dep\include\g3dlite\G3D\Matrix3.h"
>
</File>
<File
RelativePath="..\..\..\dep\src\g3dlite\Plane.cpp"
>
</File>
<File
RelativePath="..\..\..\dep\include\g3dlite\G3D\Plane.h"
>
@@ -369,10 +305,6 @@
RelativePath="..\..\..\dep\include\g3dlite\G3D\Quat.h"
>
</File>
<File
RelativePath="..\..\..\dep\include\g3dlite\G3D\Quat.inl"
>
</File>
<File
RelativePath="..\..\..\dep\include\g3dlite\G3D\Ray.h"
>
@@ -389,10 +321,6 @@
RelativePath="..\..\..\dep\include\g3dlite\G3D\stringutils.h"
>
</File>
<File
RelativePath="..\..\..\dep\src\g3dlite\System.cpp"
>
</File>
<File
RelativePath="..\..\..\dep\include\g3dlite\G3D\System.h"
>
@@ -401,10 +329,6 @@
RelativePath="..\..\..\dep\include\g3dlite\G3D\Table.h"
>
</File>
<File
RelativePath="..\..\..\dep\src\g3dlite\Triangle.cpp"
>
</File>
<File
RelativePath="..\..\..\dep\include\g3dlite\G3D\Triangle.h"
>
@@ -413,40 +337,172 @@
RelativePath="..\..\..\dep\include\g3dlite\G3D\Vector2.h"
>
</File>
<File
RelativePath="..\..\..\dep\include\g3dlite\G3D\Vector2.inl"
>
</File>
<File
RelativePath="..\..\..\dep\include\g3dlite\G3D\Vector2int16.h"
>
</File>
<File
RelativePath="..\..\..\dep\src\g3dlite\Vector3.cpp"
>
</File>
<File
RelativePath="..\..\..\dep\include\g3dlite\G3D\Vector3.h"
>
</File>
<File
RelativePath="..\..\..\dep\include\g3dlite\G3D\Vector3.inl"
>
</File>
<File
RelativePath="..\..\..\dep\include\g3dlite\G3D\Vector3int16.h"
>
</File>
<File
RelativePath="..\..\..\dep\src\g3dlite\Vector4.cpp"
>
</File>
<File
RelativePath="..\..\..\dep\include\g3dlite\G3D\Vector4.h"
>
</File>
<File
RelativePath="..\..\..\dep\include\g3dlite\G3D\Vector4.inl"
RelativePath="..\..\..\dep\src\g3dlite\AABox.cpp"
>
</File>
<File
RelativePath="..\..\..\dep\src\g3dlite\Box.cpp"
>
</File>
<File
RelativePath="..\..\..\dep\src\g3dlite\Crypto.cpp"
>
</File>
<File
RelativePath="..\..\..\dep\src\g3dlite\format.cpp"
>
</File>
<File
RelativePath="..\..\..\dep\src\g3dlite\Matrix3.cpp"
>
</File>
<File
RelativePath="..\..\..\dep\src\g3dlite\Plane.cpp"
>
</File>
<File
RelativePath="..\..\..\dep\src\g3dlite\System.cpp"
>
</File>
<File
RelativePath="..\..\..\dep\src\g3dlite\Triangle.cpp"
>
</File>
<File
RelativePath="..\..\..\dep\src\g3dlite\Vector3.cpp"
>
</File>
<File
RelativePath="..\..\..\dep\src\g3dlite\Vector4.cpp"
>
</File>
<File
RelativePath="..\..\..\dep\src\g3dlite\debugAssert.cpp"
>
</File>
<File
RelativePath="..\..\..\dep\src\g3dlite\fileutils.cpp"
>
</File>
<File
RelativePath="..\..\..\dep\src\g3dlite\g3dmath.cpp"
>
</File>
<File
RelativePath="..\..\..\dep\src\g3dlite\g3dfnmatch.cpp"
>
</File>
<File
RelativePath="..\..\..\dep\src\g3dlite\prompt.cpp"
>
</File>
<File
RelativePath="..\..\..\dep\src\g3dlite\stringutils.cpp"
>
</File>
<File
RelativePath="..\..\..\dep\src\g3dlite\Any.cpp"
>
</File>
<File
RelativePath="..\..\..\dep\src\g3dlite\BinaryFormat.cpp"
>
</File>
<File
RelativePath="..\..\..\dep\src\g3dlite\BinaryInput.cpp"
>
</File>
<File
RelativePath="..\..\..\dep\src\g3dlite\BinaryOutput.cpp"
>
</File>
<File
RelativePath="..\..\..\dep\src\g3dlite\Capsule.cpp"
>
</File>
<File
RelativePath="..\..\..\dep\src\g3dlite\CollisionDetection.cpp"
>
</File>
<File
RelativePath="..\..\..\dep\src\g3dlite\CoordinateFrame.cpp"
>
</File>
<File
RelativePath="..\..\..\dep\src\g3dlite\Cylinder.cpp"
>
</File>
<File
RelativePath="..\..\..\dep\src\g3dlite\Line.cpp"
>
</File>
<File
RelativePath="..\..\..\dep\src\g3dlite\LineSegment.cpp"
>
</File>
<File
RelativePath="..\..\..\dep\src\g3dlite\Log.cpp"
>
</File>
<File
RelativePath="..\..\..\dep\src\g3dlite\Matrix4.cpp"
>
</File>
<File
RelativePath="..\..\..\dep\src\g3dlite\MemoryManager.cpp"
>
</File>
<File
RelativePath="..\..\..\dep\src\g3dlite\Quat.cpp"
>
</File>
<File
RelativePath="..\..\..\dep\src\g3dlite\Random.cpp"
>
</File>
<File
RelativePath="..\..\..\dep\src\g3dlite\Ray.cpp"
>
</File>
<File
RelativePath="..\..\..\dep\src\g3dlite\ReferenceCount.cpp"
>
</File>
<File
RelativePath="..\..\..\dep\src\g3dlite\Sphere.cpp"
>
</File>
<File
RelativePath="..\..\..\dep\src\g3dlite\TextInput.cpp"
>
</File>
<File
RelativePath="..\..\..\dep\src\g3dlite\TextOutput.cpp"
>
</File>
<File
RelativePath="..\..\..\dep\src\g3dlite\UprightFrame.cpp"
>
</File>
<File
RelativePath="..\..\..\dep\src\g3dlite\Vector2.cpp"
>
</File>
</Filter>
@@ -0,0 +1,249 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="vmap_assembler"
ProjectGUID="{572FFF74-480C-4472-8ABF-81733BB4049D}"
RootNamespace="vmap_assembler"
Keyword="Win32Proj"
TargetFrameworkVersion="131072"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="..\bin\$(PlatformName)_$(ConfigurationName)\"
IntermediateDirectory="bin\$(ProjectName)__$(PlatformName)_$(ConfigurationName)\"
ConfigurationType="1"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\..\dep\include\g3dlite;..\..\..\src\shared\vmap;"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
EnableEnhancedInstructionSet="1"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)/vmap_assembler.exe"
LinkIncremental="1"
IgnoreDefaultLibraryNames=""
GenerateDebugInformation="true"
ProgramDatabaseFile="$(OutDir)/vmap_assembler.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="..\bin\$(PlatformName)_$(ConfigurationName)\"
IntermediateDirectory="bin\$(ProjectName)__$(PlatformName)_$(ConfigurationName)\"
ConfigurationType="1"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\..\dep\include\g3dlite;..\..\..\src\shared\vmap;..\..\..\src\framework;..\..\..\dep\ACE_wrappers"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
EnableEnhancedInstructionSet="1"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)/vmap_assembler.exe"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
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;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\..\vmap_assembler.cpp"
>
</File>
</Filter>
<Filter
Name="vmaplib"
>
<File
RelativePath="..\..\..\src\shared\vmap\BIH.cpp"
>
</File>
<File
RelativePath="..\..\..\src\shared\vmap\BIH.h"
>
</File>
<File
RelativePath="..\..\..\src\shared\vmap\MapTree.cpp"
>
</File>
<File
RelativePath="..\..\..\src\shared\vmap\MapTree.h"
>
</File>
<File
RelativePath="..\..\..\src\shared\vmap\ModelInstance.cpp"
>
</File>
<File
RelativePath="..\..\..\src\shared\vmap\ModelInstance.h"
>
</File>
<File
RelativePath="..\..\..\src\shared\vmap\TileAssembler.cpp"
>
</File>
<File
RelativePath="..\..\..\src\shared\vmap\TileAssembler.h"
>
</File>
<File
RelativePath="..\..\..\src\shared\vmap\VMapManager2.cpp"
>
</File>
<File
RelativePath="..\..\..\src\shared\vmap\VMapManager2.h"
>
</File>
<File
RelativePath="..\..\..\src\shared\vmap\VMapTools.h"
>
</File>
<File
RelativePath="..\..\..\src\shared\vmap\WorldModel.cpp"
>
</File>
<File
RelativePath="..\..\..\src\shared\vmap\WorldModel.h"
>
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
+5 -6
View File
@@ -54,7 +54,7 @@ File contains map names that should be split into tiles
A '#' at the beginning of a line defines a comment
*/
bool readConfigFile(char *pConffile, VMAP::TileAssembler* pTa)
/* bool readConfigFile(char *pConffile, VMAP::TileAssembler* pTa)
{
bool result = false;
char buffer[501];
@@ -74,7 +74,7 @@ bool readConfigFile(char *pConffile, VMAP::TileAssembler* pTa)
result = true;
}
return(result);
}
} */
//=======================================================
int main(int argc, char* argv[])
{
@@ -97,7 +97,7 @@ int main(int argc, char* argv[])
All the names in the list are considered to be world maps or huge instances.
These maps will be spilt into tiles in the vmap assemble process
*/
if(conffile != NULL)
/* if(conffile != NULL)
{
if(!readConfigFile(conffile, ta))
{
@@ -105,9 +105,9 @@ int main(int argc, char* argv[])
delete ta;
return 1;
}
}
} */
if(!ta->convertWorld())
if(!ta->convertWorld2())
{
printf("exit with errors\n");
delete ta;
@@ -118,4 +118,3 @@ int main(int argc, char* argv[])
printf("Ok, all done\n");
return 0;
}
@@ -0,0 +1,59 @@
Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vmap_assembler", "VC100\vmap_assembler.vcxproj", "{572FFF74-480C-4472-8ABF-81733BB4049D}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib", "..\..\win\VC100\zlib.vcxproj", "{8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "g3dlite", "..\..\win\VC100\g3dlite.vcxproj", "{8072769E-CF10-48BF-B9E1-12752A5DAC6E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug_NoPCH|Win32 = Debug_NoPCH|Win32
Debug_NoPCH|x64 = Debug_NoPCH|x64
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{572FFF74-480C-4472-8ABF-81733BB4049D}.Debug_NoPCH|Win32.ActiveCfg = Debug|Win32
{572FFF74-480C-4472-8ABF-81733BB4049D}.Debug_NoPCH|Win32.Build.0 = Debug|Win32
{572FFF74-480C-4472-8ABF-81733BB4049D}.Debug_NoPCH|x64.ActiveCfg = Debug|x64
{572FFF74-480C-4472-8ABF-81733BB4049D}.Debug_NoPCH|x64.Build.0 = Debug|x64
{572FFF74-480C-4472-8ABF-81733BB4049D}.Debug|Win32.ActiveCfg = Debug|Win32
{572FFF74-480C-4472-8ABF-81733BB4049D}.Debug|Win32.Build.0 = Debug|Win32
{572FFF74-480C-4472-8ABF-81733BB4049D}.Debug|x64.ActiveCfg = Debug|x64
{572FFF74-480C-4472-8ABF-81733BB4049D}.Debug|x64.Build.0 = Debug|x64
{572FFF74-480C-4472-8ABF-81733BB4049D}.Release|Win32.ActiveCfg = Release|Win32
{572FFF74-480C-4472-8ABF-81733BB4049D}.Release|Win32.Build.0 = Release|Win32
{572FFF74-480C-4472-8ABF-81733BB4049D}.Release|x64.ActiveCfg = Release|x64
{572FFF74-480C-4472-8ABF-81733BB4049D}.Release|x64.Build.0 = Release|x64
{8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}.Debug_NoPCH|Win32.ActiveCfg = Debug_NoPCH|Win32
{8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}.Debug_NoPCH|Win32.Build.0 = Debug_NoPCH|Win32
{8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}.Debug_NoPCH|x64.ActiveCfg = Debug_NoPCH|x64
{8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}.Debug_NoPCH|x64.Build.0 = Debug_NoPCH|x64
{8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}.Debug|Win32.ActiveCfg = Debug|Win32
{8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}.Debug|Win32.Build.0 = Debug|Win32
{8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}.Debug|x64.ActiveCfg = Debug|x64
{8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}.Debug|x64.Build.0 = Debug|x64
{8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}.Release|Win32.ActiveCfg = Release|Win32
{8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}.Release|Win32.Build.0 = Release|Win32
{8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}.Release|x64.ActiveCfg = Release|x64
{8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}.Release|x64.Build.0 = Release|x64
{8072769E-CF10-48BF-B9E1-12752A5DAC6E}.Debug_NoPCH|Win32.ActiveCfg = Debug_NoPCH|Win32
{8072769E-CF10-48BF-B9E1-12752A5DAC6E}.Debug_NoPCH|Win32.Build.0 = Debug_NoPCH|Win32
{8072769E-CF10-48BF-B9E1-12752A5DAC6E}.Debug_NoPCH|x64.ActiveCfg = Debug_NoPCH|x64
{8072769E-CF10-48BF-B9E1-12752A5DAC6E}.Debug_NoPCH|x64.Build.0 = Debug_NoPCH|x64
{8072769E-CF10-48BF-B9E1-12752A5DAC6E}.Debug|Win32.ActiveCfg = Debug|Win32
{8072769E-CF10-48BF-B9E1-12752A5DAC6E}.Debug|Win32.Build.0 = Debug|Win32
{8072769E-CF10-48BF-B9E1-12752A5DAC6E}.Debug|x64.ActiveCfg = Debug|x64
{8072769E-CF10-48BF-B9E1-12752A5DAC6E}.Debug|x64.Build.0 = Debug|x64
{8072769E-CF10-48BF-B9E1-12752A5DAC6E}.Release|Win32.ActiveCfg = Release|Win32
{8072769E-CF10-48BF-B9E1-12752A5DAC6E}.Release|Win32.Build.0 = Release|Win32
{8072769E-CF10-48BF-B9E1-12752A5DAC6E}.Release|x64.ActiveCfg = Release|x64
{8072769E-CF10-48BF-B9E1-12752A5DAC6E}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
@@ -0,0 +1,42 @@
Microsoft Visual Studio Solution File, Format Version 10.00
# Visual C++ Express 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vmap_assembler", "VC90\vmap_assembler.vcproj", "{572FFF74-480C-4472-8ABF-81733BB4049D}"
ProjectSection(ProjectDependencies) = postProject
{8F1DEA42-6A5B-4B62-839D-C141A7BFACF2} = {8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}
{8072769E-CF10-48BF-B9E1-12752A5DAC6E} = {8072769E-CF10-48BF-B9E1-12752A5DAC6E}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib", "..\..\win\VC90\zlib.vcproj", "{8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "g3dlite", "..\..\win\VC90\g3dlite.vcproj", "{8072769E-CF10-48BF-B9E1-12752A5DAC6E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug_NoPCH|Win32 = Debug_NoPCH|Win32
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{572FFF74-480C-4472-8ABF-81733BB4049D}.Debug_NoPCH|Win32.ActiveCfg = Debug|Win32
{572FFF74-480C-4472-8ABF-81733BB4049D}.Debug_NoPCH|Win32.Build.0 = Debug|Win32
{572FFF74-480C-4472-8ABF-81733BB4049D}.Debug|Win32.ActiveCfg = Debug|Win32
{572FFF74-480C-4472-8ABF-81733BB4049D}.Debug|Win32.Build.0 = Debug|Win32
{572FFF74-480C-4472-8ABF-81733BB4049D}.Release|Win32.ActiveCfg = Release|Win32
{572FFF74-480C-4472-8ABF-81733BB4049D}.Release|Win32.Build.0 = Release|Win32
{8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}.Debug_NoPCH|Win32.ActiveCfg = Debug_NoPCH|Win32
{8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}.Debug_NoPCH|Win32.Build.0 = Debug_NoPCH|Win32
{8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}.Debug|Win32.ActiveCfg = Debug|Win32
{8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}.Debug|Win32.Build.0 = Debug|Win32
{8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}.Release|Win32.ActiveCfg = Release|Win32
{8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}.Release|Win32.Build.0 = Release|Win32
{8072769E-CF10-48BF-B9E1-12752A5DAC6E}.Debug_NoPCH|Win32.ActiveCfg = Debug_NoPCH|Win32
{8072769E-CF10-48BF-B9E1-12752A5DAC6E}.Debug_NoPCH|Win32.Build.0 = Debug_NoPCH|Win32
{8072769E-CF10-48BF-B9E1-12752A5DAC6E}.Debug|Win32.ActiveCfg = Debug|Win32
{8072769E-CF10-48BF-B9E1-12752A5DAC6E}.Debug|Win32.Build.0 = Debug|Win32
{8072769E-CF10-48BF-B9E1-12752A5DAC6E}.Release|Win32.ActiveCfg = Release|Win32
{8072769E-CF10-48BF-B9E1-12752A5DAC6E}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
+26
View File
@@ -0,0 +1,26 @@
# Copyright (C) 2005-2009 MaNGOS project <http://getmangos.com/>
#
# This file is free software; as a special exception the author 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.
cmake_minimum_required (VERSION 2.6)
project (MANGOS_VMAP_EXTRACT_IO)
# uncomment next line to disable debug mode
ADD_DEFINITIONS("-DIOMAP_DEBUG")
# build setup currently only supports libmpq 0.4.x
ADD_DEFINITIONS("-DUSE_LIBMPQ04")
ADD_DEFINITIONS("-Wall")
ADD_DEFINITIONS("-ggdb")
ADD_DEFINITIONS("-O3")
include_directories(../libmpq)
#add_subdirectory(stormlib)
add_subdirectory(vmapextract)
@@ -1,117 +0,0 @@
/*****************************************************************************/
/* Storm.cpp Copyright (c) Ladislav Zezula 2003 */
/*---------------------------------------------------------------------------*/
/* This is just a dummy module for building import library for Storm.dll */
/*---------------------------------------------------------------------------*/
/* Date Ver Who Comment */
/* -------- ---- --- ------- */
/* 11.04.03 1.00 Lad The first version of Storm.cpp */
/*****************************************************************************/
#include <windows.h>
#define BUILDING_STORM_CPP
#define STORM_ALTERNATE_NAMES
#include "StormDll.h"
BOOL WINAPI SFILE(OpenArchive)(LPCSTR lpFileName, DWORD dwPriority, DWORD dwFlags, HANDLE *hMPQ)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
BOOL WINAPI SFILE(CloseArchive)(HANDLE hMPQ)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
BOOL WINAPI SFILE(GetArchiveName)(HANDLE hMPQ, LPCSTR lpBuffer, DWORD dwBufferLength)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
BOOL WINAPI SFILE(OpenFile)(LPCSTR lpFileName, HANDLE *hFile)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
BOOL WINAPI SFILE(OpenFileEx)(HANDLE hMPQ, LPCSTR lpFileName, DWORD dwSearchScope, HANDLE *hFile)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
BOOL WINAPI SFILE(CloseFile)(HANDLE hFile)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
DWORD WINAPI SFILE(GetFileSize)(HANDLE hFile, LPDWORD lpFileSizeHigh)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
BOOL WINAPI SFILE(GetFileArchive)(HANDLE hFile, HANDLE *hMPQ)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
BOOL WINAPI SFILE(GetFileName)(HANDLE hFile, LPCSTR lpBuffer, DWORD dwBufferLength)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
DWORD WINAPI SFILE(SetFilePointer)(HANDLE hFile, long lDistanceToMove, PLONG lplDistanceToMoveHigh, DWORD dwMoveMethod)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
BOOL WINAPI SFILE(ReadFile)(HANDLE hFile,LPVOID lpBuffer,DWORD nNumberOfBytesToRead,LPDWORD lpNumberOfBytesRead,LPOVERLAPPED lpOverlapped)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
LCID WINAPI SFILE(SetLocale)(LCID nNewLocale)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
BOOL WINAPI SFILE(GetBasePath)(LPCSTR lpBuffer, DWORD dwBufferLength)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
BOOL WINAPI SFILE(SetBasePath)(LPCSTR lpNewBasePath)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
BOOL WINAPI SFILE(Destroy)()
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
BOOL WINAPI SCOMP(Compress)(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength, int uCmp, int uCmpType, int nCmpLevel)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
BOOL WINAPI SCOMP(Decompress)(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
@@ -1,25 +0,0 @@
; Storm definition file with alternate Storm.dll names
LIBRARY "Storm"
EXPORTS
StormCloseArchive @252 ; 0x0FC
StormCloseFile @253 ; 0x0FD
StormDestroy @262 ; 0x106
StormGetFileArchive @264 ; 0x108
StormGetFileSize @265 ; 0x109
StormOpenArchive @266 ; 0x10A
StormOpenFile @267 ; 0x10B
StormOpenFileEx @268 ; 0x10C
StormReadFile @269 ; 0x10D
StormSetBasePath @270 ; 0x10E
StormSetFilePointer @271 ; 0x10F
StormSetLocale @272 ; 0x110
StormGetBasePath @273 ; 0x111
StormGetArchiveName @275 ; 0x113
StormGetFileName @276 ; 0x114
; StormSetLastError @465 ; 0x
StormCompress @551 ; 0x227
StormDecompress @552 ; 0x228
@@ -1,67 +0,0 @@
/*****************************************************************************/
/* Storm.h Copyright Justin Olbrantz(Quantam) 2000 */
/*---------------------------------------------------------------------------*/
/* Storm Interface Library v1.0 for Windows */
/* */
/* Author : Justin Olbrantz(Quantam) */
/* E-mail : [email protected] */
/* WWW : www.campaigncreations.com/starcraft/mpq2k/inside_mopaq/ */
/*---------------------------------------------------------------------------*/
/* Date Ver Who Comment */
/* -------- ---- --- ------- */
/* xx.xx.00 1.00 Qua The first version of Storm.h */
/* 11.04.03 1.00 Lad Added some functions */
/*****************************************************************************/
// We need the Windows data types for the Storm prototypes
#include <windows.h>
#ifndef __STORM_H__
#define __STORM_H__
// Somethimes is necessary to change the function names so they
// will not conflict with other MPQ tools.
#ifdef STORM_ALTERNATE_NAMES
#define SFILE(Name) Storm##Name
#define SCOMP(Name) Storm##Name
#else
#define SFILE(Name) SFile##Name
#define SCOMP(Name) SComp##Name
#endif
// Just in case anyone is still using C out there
#ifdef __cplusplus
extern "C" {
#endif
// Storm file function prototypes
BOOL WINAPI SFILE(OpenArchive)(LPCSTR lpFileName, DWORD dwPriority, DWORD dwFlags, HANDLE *hMPQ);
BOOL WINAPI SFILE(CloseArchive)(HANDLE hMPQ);
BOOL WINAPI SFILE(GetArchiveName)(HANDLE hMPQ, LPCSTR lpBuffer, DWORD dwBufferLength);
BOOL WINAPI SFILE(OpenFile)(LPCSTR lpFileName, HANDLE *hFile);
BOOL WINAPI SFILE(OpenFileEx)(HANDLE hMPQ, LPCSTR lpFileName, DWORD dwSearchScope, HANDLE *hFile);
BOOL WINAPI SFILE(CloseFile)(HANDLE hFile);
DWORD WINAPI SFILE(GetFileSize)(HANDLE hFile, LPDWORD lpFileSizeHigh);
BOOL WINAPI SFILE(GetFileArchive)(HANDLE hFile, HANDLE *hMPQ);
BOOL WINAPI SFILE(GetFileName)(HANDLE hFile, LPCSTR lpBuffer, DWORD dwBufferLength);
DWORD WINAPI SFILE(SetFilePointer)(HANDLE hFile, long lDistanceToMove, PLONG lplDistanceToMoveHigh, DWORD dwMoveMethod);
BOOL WINAPI SFILE(ReadFile)(HANDLE hFile,LPVOID lpBuffer,DWORD nNumberOfBytesToRead,LPDWORD lpNumberOfBytesRead,LPOVERLAPPED lpOverlapped);
LCID WINAPI SFILE(SetLocale)(LCID nNewLocale);
BOOL WINAPI SFILE(GetBasePath)(LPCSTR lpBuffer, DWORD dwBufferLength);
BOOL WINAPI SFILE(SetBasePath)(LPCSTR lpNewBasePath);
// Storm (de)compression functions
BOOL WINAPI SCOMP(Compress) (char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength, int uCmp, int uCmpType, int nCmpLevel);
BOOL WINAPI SCOMP(Decompress)(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength);
#if defined(_MSC_VER) && !defined(BUILDING_STORM_CPP)
#pragma comment(lib, "Storm.lib") // Force linking Storm.lib and thus Storm.dll
#endif
#ifdef __cplusplus
}
#endif
#endif // __STORM_H__
@@ -1,697 +0,0 @@
/***********************************************************************
*
* Description: GfxDecode -- functions for reading Diablo's GFX files
* Author: Marko Friedemann <marko.friedemann@bmx-chemnitz.de>
* Created at: Son Jan 27 15:20:43 CET 2002
* Computer: hangloose.flachland-chemnitz.de
* System: Linux 2.4.16 on i686
*
* Copyright (c) 2002 BMX-Chemnitz.DE All rights reserved.
*
* ---------------------------------------------------------------------
* included are functions for getting:
* - the framecount of .CEL-files -> celGetFrameCount()
* - single frames of .CEL-files -> celGetFrameData()
* - the framecount of .CL2-files -> cl2GetFrameCount()
* - single directions of .CL2-files (all frames) -> cl2GetDirData()
* - single .PCX-files (256 color; v2, v5) -> pcxGetData()
***********************************************************************/
#include <vector>
#include <cmath>
#include <iostream>
#include "StormLib.h"
#define TRANS_COL 256
using std::cerr;
using std::vector;
/****** RAMP stuff *****************************************************
* for a more detailed description/explanation see below
***********************************************************************/
// two variations: one/two ramp(s)
static const uint16_t c_2RampSize = 544; // the frame size
static const uint16_t c_1RampSize = 800; // the frame size
// ramps (both variations) can be either left or right
static const uint16_t c_RampOffsetLeft[17] = {
0, // __
8, // + 8 note that this __--
24, // + 16 "drawing" is __--
48, // + 24 upside down! __-- this area
80, // + 32 __-- is always
120, // + 40 __-- colored
168, // + 48 __--
224, // + 56 __-- lower ramp ends here (+30 == 254)
288, // + 64 --__ upper ramp might be missing
348, // + 60 | --__
400, // + 52 | --__ this area
444, // + 44 | --__ is always
480, // + 36 | --__ colored
508, // + 28 | either trans- --__
528, // + 20 | parent or colored --__
540, // + 12 | --__ +2 Pixels = 544
542 // + 2 | this last one doesn't exist, it's those^ 2 pixels
};
static const uint16_t c_RampOffsetRight[17] = {
2, // __ before this, there are 2 Pixels
14, // + 12 --__ 4^2 - 2
34, // + 20 --__ 6^2 - 2
62, // + 28 this area --__ 8^2 - 2
98, // + 36 is always --__ 10^2 - 2 pattern anyone? ;)
142, // + 44 colored --__
194, // + 52 --__
254, // + 60 lower ramp ends here --__ (-30 == 224)
318, // + 64 upper ramp might be missing __--
374, // + 56 __-- |
422, // + 48 this area __-- | note that this
462, // + 40 is always __-- | "drawing"
494, // + 32 colored __-- eiter trans- | is upside down!
518, // + 24 __-- parent or colored |
534, // + 16 __-- |
542, // + 8 __-- +2 Startpixels = 544 |
542 // + 0 this last one doesn't exist, it | would be EOF
};
/****** FrameBuffer class **********************************************
* holds buffers and size information of the actual target image
* purpose: buffer management and avoidance of ugly globals
**********************************************************************/
class FrameBuf
{
protected:
vector <uint8_t *> vecData;
uint8_t *pCurrRow;
uint8_t *pPalette;
uint16_t uRows;
uint16_t *upYSize;
uint16_t *upMaxX;
public:
uint16_t uCols;
uint16_t uXSize;
uint16_t uMaxBlock;
uint16_t uFrameNum;
bool bHasBlocks;
bool bHasRamps;
FrameBuf(
uint8_t *pPal=NULL, uint16_t frame=0, uint16_t xsize=0,
uint16_t *pysize=NULL, uint16_t *pmaxx=NULL, uint16_t maxblock=0)
{
pCurrRow = new uint8_t[4*xsize];
pPalette = pPal;
uCols = 0;
uRows = 0;
uXSize = xsize;
uFrameNum = frame;
uMaxBlock = maxblock;
upYSize = pysize;
upMaxX = pmaxx;
bHasBlocks= false;
bHasRamps = false;
}
~FrameBuf()
{
delete[] pCurrRow;
for (vector <uint8_t *>::iterator vi=vecData.begin(); vi!=vecData.end(); vi++)
delete[] *vi;
vecData.clear();
}
void addLine()
{
++uRows;
uCols = 0;
vecData.push_back(pCurrRow);
pCurrRow = new uint8_t[4*uXSize];
}
void addPixel(uint16_t uColorNum)
{
if (uColorNum > TRANS_COL) {
cerr << "\n*** there seemed to be an error, illegal color index " << uColorNum;
cerr << "\n +++ at (" << uCols << "," << uRows << "), see for yourself *** \n\n";
uColorNum = TRANS_COL; // sane setting to avoid segfaults
}
memcpy(pCurrRow + 4*uCols, pPalette + 4*uColorNum, 4*sizeof(uint8_t));
if (++uCols == uXSize)
addLine();
else if ((uColorNum != TRANS_COL) && (upMaxX != NULL) && (uCols > *upMaxX))
*upMaxX = uCols;
}
// used to return the actual image data
uint8_t *getData()
{
uint16_t i;
vector <uint8_t *>::reverse_iterator vri;
// allocate a buffer to hold the actual image size
uint8_t *tmp = new uint8_t[4*uXSize*uRows];
// the lines are upside down inside the vector, use reverse iterator
for (i=0, vri=vecData.rbegin(); vri!=vecData.rend(); vri++, i++)
memcpy(tmp+4*uXSize*i, *vri, 4*uXSize*sizeof(uint8_t));
*upYSize = uRows; // set height
if (uCols > 0) {
cerr << "\n*** there seemed to be an error (last line does not match boundary, " << uCols << " pixels left)";
cerr << "\n +++ this is often caused by specifying an invalid width, see for yourself *** \n\n";
}
return tmp;
}
};
uint16_t WINAPI celGetFrameCount(uint8_t *pFileBuf)
{
uint32_t tmp;
memcpy(&tmp, pFileBuf, sizeof(uint32_t));
return (uint16_t)tmp;
}
/***** Block Decoder ***************************************************
* one of three possible decoding techniques necessary for .cel
* possible block contents are either colored (in that case the
* appropriate number of pixels are read) or transparent pixels
* there are neither ramps nor plain pixels allowed here
***********************************************************************/
uint8_t *celDecodeBlocks(uint8_t *pFileBuf, FrameBuf *pFrame, uint32_t *framestart)
{
uint32_t uFilePos=framestart[pFrame->uFrameNum];
uint8_t cRead=0, i=0;
if (!pFrame->bHasBlocks) // sanity check
return NULL;
while (uFilePos < framestart[pFrame->uFrameNum+1]) {
cRead = pFileBuf[uFilePos++];
if ((uFilePos == framestart[pFrame->uFrameNum]+1))
// TODO: what is this 0x0A 0x00 stuff all about?
if ((cRead == 0x0A) && (pFileBuf[uFilePos] == 0x00)) {
uFilePos += 9;
cRead = pFileBuf[uFilePos++];
}
if (cRead > 0x7F)
// transparent block (complement, 256-val)
for (i=0; i<256-cRead; i++)
pFrame->addPixel(TRANS_COL);
else if (cRead < pFrame->uMaxBlock + 1)
// pixel block (block size pixels to be read!)
for (i=0; i<cRead; i++)
pFrame->addPixel(pFileBuf[uFilePos++]);
else
cerr << "\n*** block mode: illegal block (> max_size) ***\n\n";
}
return pFrame->getData();
}
/***** Ramp Decoder ****************************************************
* the second of three possible decoding techniques necessary for .cel
* each block save the first/last is enclosed by two 0x00 pairs
* those blocks affect _TWO_ rows with one being 2 colored pixels shorter
* the first/last "block" affects only one row
***********************************************************************/
uint8_t *celDecodeRamps(uint8_t *pFileBuf, FrameBuf *pFrame, uint32_t *framestart, bool bLeft)
{
uint32_t uFrameLen = framestart[pFrame->uFrameNum+1]-framestart[pFrame->uFrameNum];
uint32_t uFilePos=0;
uint16_t uBlockLen=0, i=0, j=0;
bool bFirstLonger=false;
if (!pFrame->bHasRamps) // sanity check
return NULL;
if (pFrame->uXSize != 32) // only used in that case
return NULL;
if (!bLeft) { // get first two pixels for right side ramps
pFrame->addPixel(pFileBuf[framestart[pFrame->uFrameNum]]);
pFrame->addPixel(pFileBuf[framestart[pFrame->uFrameNum]+1]);
}
// do all the ramp blocks
for (i=0; i<(uFrameLen == c_2RampSize ? 15 : 7); i++) {
uBlockLen = (bLeft ? (c_RampOffsetLeft[i+1] - c_RampOffsetLeft[i]) : (c_RampOffsetRight[i+1] - c_RampOffsetRight[i]));
uFilePos = framestart[pFrame->uFrameNum] + (bLeft ? c_RampOffsetLeft[i] : c_RampOffsetRight[i]) + 2;
bFirstLonger = (i>(bLeft ? 7 : 6));
if (bLeft) {
// OK, first line, starting with transparency
for (j=0; j<pFrame->uXSize - uBlockLen/2 + (bFirstLonger ? 0 : 2); j++)
pFrame->addPixel(TRANS_COL);
// fill it up with the pixel block
for (j=0; j<uBlockLen/2 - (bFirstLonger ? 0 : 2); j++)
pFrame->addPixel(pFileBuf[uFilePos++]);
// second line, starting again with transparency
for (j=0; j<pFrame->uXSize - uBlockLen/2 + (bFirstLonger ? 2 : 0); j++)
pFrame->addPixel(TRANS_COL);
// fill the second line with the remaining pixels
for (j=0; j<uBlockLen/2 - (bFirstLonger ? 2 : 0); j++)
pFrame->addPixel(pFileBuf[uFilePos++]);
} else {
if (pFrame->uCols != 0) // fill current line with trans (if not empty)
for (j=pFrame->uXSize - pFrame->uCols; j>0; j--)
pFrame->addPixel(TRANS_COL);
// OK, insert the first pixels into a new line
for (j=0; j<uBlockLen/2 - (bFirstLonger ? 0 : 2); j++)
pFrame->addPixel(pFileBuf[uFilePos++]);
// fill the line with transparency
for (j=0; j<pFrame->uXSize - uBlockLen/2 + (bFirstLonger ? 0 : 2); j++)
pFrame->addPixel(TRANS_COL);
// start a second line with the remaining pixels
for (j=0; j<uBlockLen/2 - (bFirstLonger ? 2 : 0); j++)
pFrame->addPixel(pFileBuf[uFilePos++]);
}
}
// now read the last 0x00 pair and fill up
uBlockLen = (uFrameLen == c_2RampSize ? 30 : 2); // one or two ramps?
uFilePos = framestart[pFrame->uFrameNum] + (bLeft ? c_RampOffsetLeft[i] : c_RampOffsetRight[i]) + 2;
// the transparency for the last (single) 0x00 pair
for (j=0; j<uBlockLen; j++)
pFrame->addPixel(TRANS_COL);
if (bLeft) { // left side only: the remaining line
for (j=0; j<pFrame->uXSize - uBlockLen; j++)
pFrame->addPixel(pFileBuf[uFilePos++]);
}
// now the rest of the file (plain)
while (uFilePos < framestart[pFrame->uFrameNum+1])
pFrame->addPixel(pFileBuf[uFilePos++]);
// the uppermost line is emtpy when 2 ramps are used
if (uFrameLen == c_2RampSize)
for (j=0; j<pFrame->uXSize; j++)
pFrame->addPixel(TRANS_COL);
return pFrame->getData();
}
/***** celGetFrameData *************************************************
* decode .cel data for given frame and xsize
* Args:
* *vpFileBuf the buffer containing the filecontent
* *palette the palette (4 bytes for each of the 257 entries)
* 256 colors are needed + 1 for alpha
* uXSize this information must be given
* uFrameNume the frame to get
* *uYSize the actual value is returned therein
* *uMaxX this can be used (if != NULL) to get the column
* of the rightmost nontransparent pixel (useable
* eg for fonts)
*
* Returns: an array containing 4 Bytes (RGBA) for each pixel
*
* ---------------------------------------------------------------
* Comments: dirty hack, started from scratch @ 2000-10-11
* cleanly rewritten during incorporation into ladiks StormLib
* status: structured hack ;)
*
* It took me approx. 6 days to understand the format basics (hex viewer)
* For this I had a little help from a dos tool ("ddecode", from
* www.cowlevel.com, binary only, no sources) which, however, gave
* me the general idea what the pictures are actually supposed to look like.
*
* The fine adjustments, however, took quite some time and a little luck.
* After I had written to various people (mickyk and ladik), which could
* not help me, but wished best luck (thanks, btw, it helped ;)), I tried
* some reverse engineering which was not succesful in the end.
*
* I then had incidentally a new idea of what could be going on @ 2002-01-23.
* It just came to my mind that I could retry some actual painting in
* reverse order (had done that before to no avail) and when looking closer
* at it I realized the "ramp" stuff. This really is the trickiest part and
* it took me some eight days to implement it without breaking the other
* parts of the code. Very odd format indeed.
*
* TODO: learn what 0x0A 0x00 means
**********************************************************************/
uint8_t * WINAPI celGetFrameData(uint8_t *pFileBuf, uint8_t *palette, uint16_t uXSize, uint16_t uFrameNum, uint16_t *uYSize, uint16_t *uMaxX)
{
FrameBuf *pFrame;
uint32_t *framestart=NULL, frames=0, uFilePos=0;
uint16_t i, tmpWord=0;
uint8_t cRead=0, *data;
memcpy(&frames, pFileBuf, sizeof(uint32_t));
uFilePos += sizeof(uint32_t);
if (pFileBuf == NULL) {
SetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
if (palette == NULL) {
SetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
if (uFrameNum > frames-1) {
SetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
if (uYSize == NULL) {
SetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
// in case we want to know the rightmost pixels column (usable eg. for fonts)
if (uMaxX != NULL)
*uMaxX = 0;
// get the frame offsets
framestart = new uint32_t[frames+1];
for (i=0; i<frames+1; i++) {
memcpy(&framestart[i], pFileBuf+uFilePos, sizeof(uint32_t));
uFilePos += sizeof(uint32_t);
}
/****** block size *************************************************
* depends on the image width
******************************/
double erg = rint(sqrt(pow(2, rint(log((double)(framestart[uFrameNum+1] - framestart[uFrameNum])) / log(2.0)))));
pFrame = new FrameBuf(palette, uFrameNum, uXSize, uYSize, uMaxX, max((uint16_t)min((int)erg, 0x7F), uXSize));
/****** ramp detection -- AFAIK only needed for 32x32 tiles ********
* here I use hard coded constants because this is the only simple
* way to get the detection done; plus this stuff is only to be
* found in such 32x32 (tile) files and so wont hurt anyone ;)
******************************************************************/
uint32_t uFrameLen = framestart[uFrameNum+1] - framestart[uFrameNum];
if ((uXSize == 32) && ((uFrameLen == c_2RampSize) || (uFrameLen == c_1RampSize))) {
// use the static arrays for the check
for (i=0; i<(uFrameLen == c_2RampSize ? 16 : 8); i++) {
memcpy(&tmpWord, pFileBuf+framestart[uFrameNum]+c_RampOffsetLeft[i], sizeof(uint16_t));
if (tmpWord != 0)
break;
}
bool bRampsLeft = pFrame->bHasRamps = (i==(uFrameLen == c_2RampSize ? 16 : 8));
if (!pFrame->bHasRamps) { // only one can apply
for (i=0; i<(uFrameLen == c_2RampSize ? 16 : 8); i++) {
memcpy(&tmpWord, pFileBuf+framestart[uFrameNum]+c_RampOffsetRight[i], sizeof(uint16_t));
if (tmpWord != 0)
break;
}
pFrame->bHasRamps = (i==(uFrameLen == c_2RampSize ? 16 : 8)); // bRampsLeft stays false in this case
}
if (pFrame->bHasRamps) { // decode ramps and be off (if appropriate)
data = celDecodeRamps(pFileBuf, pFrame, framestart, bRampsLeft);
delete pFrame;
delete[] framestart;
return data;
}
}
/*********** block detection ***************************************
* 0x0A as start byte seems to be sufficient (though I still dunno
* what the trailing 10 bytes mean); in any other case we act as if
* blocks were to be used and check afterwards if the image looks
* OK (that is, the last line has no pixels in it)
******************************************************************/
cRead = pFileBuf[framestart[uFrameNum]];
if (cRead == 0x0A) // sufficient
pFrame->bHasBlocks = true;
// if width == 32 && framelen == 32*32, assume plain
else if ((uXSize != 32) || (uFrameLen != 32*32)) { // check needed
uFilePos=framestart[uFrameNum];
i=0;
// rush through the frame
while (uFilePos < framestart[uFrameNum+1]) {
cRead = pFileBuf[uFilePos++];
// transparency blocks
while (cRead > 0x7F) {
i += 256-cRead;
i %= uXSize;
if (uFilePos < framestart[uFrameNum+1])
cRead = pFileBuf[uFilePos++];
else
cRead = 0;
}
// colored pixel block
if (uFilePos < framestart[uFrameNum+1]) {
if (cRead < pFrame->uMaxBlock + 1) {
i+=cRead;
i%=uXSize;
uFilePos+=cRead;
} else {
// when the value is out of valid blockrange
i=1; // trigger error (1%uXSize != 0)
break;
}
}
}
if (i%uXSize == 0) // looks as if we got it right
pFrame->bHasBlocks=true;
}
if (pFrame->bHasBlocks) { // use block decoder if appropriate
data = celDecodeBlocks(pFileBuf, pFrame, framestart);
delete pFrame;
delete[] framestart;
return data;
}
// plain mode (#3), read each color index and write the pixel
uFilePos=framestart[uFrameNum];
while (uFilePos < framestart[uFrameNum+1])
pFrame->addPixel(pFileBuf[uFilePos++]);
// cleanup, return image data and height
data = pFrame->getData();
delete pFrame;
delete[] framestart;
return data;
}
uint16_t WINAPI cl2GetFrameCount(uint8_t *pFileBuf)
{
uint32_t tmp;
memcpy(&tmp, pFileBuf, sizeof(uint32_t));
memcpy(&tmp, pFileBuf+tmp, sizeof(uint32_t));
return (uint16_t)tmp;
}
/***** cl2GetDirData ***************************************************
* decodes all frames of a .cl2 for given direction and xsize
* Args:
* *pFileBuf the buffer containing the filecontent
* *palette the palette (4 bytes for each of the 257 entries)
* 256 colors are needed + 1 for alpha
* uXSize this information must be given
* uDirNum the direction to get the frames from
* *uYSize the actual height is returned herein
*
* Returns: <frames> arrays containing 4 Bytes (RGBA) for each pixel
* where <frames> is read at runtime and handed back via *uFrames
*
* ---------------------------------------------------------------
* Comments: dirty hack, started from scratch @ 2000-10-12
*
* The format basics are similar to .cel, with the main difference
* that the values read have reverse interpretation. In .cel a value
* greater than 0x7F means transparency, while in .cl2 this means
* color and vice-versa. .cl2 has the additional understanding
* of blocks of the same color (0x80 .. 0xBF) where the one color is
* written multiple times.
*
* .cl2 only uses the block scheme, so there is no detection
* necessary in order to get it right. The only thing still unknown
* is that 0x0A 0x00 stuff...
*
* TODO: learn what 0x0A 0x00 means
***********************************************************************/
BYTE ** WINAPI cl2GetDirData(BYTE *pFileBuf, BYTE *palette, WORD uXSize, WORD uDirNum, WORD *uYSize)
{
FrameBuf *pFrame;
uint32_t frames=0, *framestart=NULL, uFilePos=0;
uint16_t i, fc;
uint8_t cRead=0, **data=NULL;
if (pFileBuf == NULL) {
SetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
if (palette == NULL) {
SetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
if (uDirNum > 7) {
SetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
if (uYSize == NULL) {
SetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
// get direction offsets
uint32_t dirstart[8];
for (i=0; i<8; i++) {
memcpy(&dirstart[i], pFileBuf+uFilePos, sizeof(uint32_t));
uFilePos += sizeof(uint32_t);
}
uFilePos = dirstart[uDirNum];
memcpy(&frames, pFileBuf+uFilePos, sizeof(uint32_t));
uFilePos += sizeof(uint32_t);
data = new uint8_t*[frames];
// get frame offsets
framestart = new uint32_t[frames+1];
for (i=0; i<frames+1; i++) {
memcpy(&framestart[i], pFileBuf+uFilePos, sizeof(uint32_t));
uFilePos += sizeof(uint32_t);
}
// get frame data
for (fc=0; fc<frames; fc++) {
pFrame = new FrameBuf(palette, 0, uXSize, uYSize, NULL, 0);
uFilePos = dirstart[uDirNum] + framestart[fc];
while (uFilePos < dirstart[uDirNum] + framestart[fc+1]) {
cRead = pFileBuf[uFilePos++];
if (cRead < 0x80) { // transparency
// TODO: what is this 0x0A 0x00 stuff all about?
if ((cRead == 0x0A) && (pFileBuf[uFilePos] == 0) && (uFilePos == dirstart[uDirNum] + framestart[fc] + 1))
uFilePos += 9; // ignore the 9 bytes after 0x0A 0x00 at the framestart
else
for (i=0; i<cRead; i++)
pFrame->addPixel(TRANS_COL);
} else if (cRead < 0xC0) {
// read the next byte and write it <0xBF - cRead> times
for (i=0; i<0xBF - cRead; i++)
pFrame->addPixel(pFileBuf[uFilePos]);
++uFilePos;
} else // cRead > 0xBF
// read a block of the given size and write it
for (i=0; i < 256-cRead; i++)
pFrame->addPixel(pFileBuf[uFilePos++]);
}
// got the frame data, save it
data[fc] = pFrame->getData();
delete pFrame;
}
delete[] framestart;
return data;
}
/****** pcxGetData *****************************************************
* decodes pcx files (256 color, as in diablo mpq)
* Args:
* *pFileBuf the buffer containing the filecontent
* uFileSize the size of the file buffer
* uTransColor the palette entry to be transparent
* *uXSize the actual width is returned herein
* *uYSize the actual height is returned herein
*
* Returns: an array containing 4 Bytes (RGBA) for each pixel
*
* ---------------------------------------------------------------
* Comments: format info and pseudocode taken from:
* Klaus Holtorf, "Das Handbuch der Grafikformate"
* ISBN 3-7723-6393-8
***********************************************************************/
BYTE * WINAPI pcxGetData(BYTE *pFileBuf, DWORD uFileSize, BYTE uTransColor, WORD *uXSize, WORD *uYSize)
{
uint32_t uFilePos=0;
uint32_t uDataRead=0; // potentially big! (logo.pcx: 550 * 216 * 15 = 1,782,000)
uint16_t i=0;
uint8_t *data, *palette;
uint8_t uColorNum=0, uCount=0;
struct pcx_header_t {
uint8_t id;
uint8_t version;
uint8_t compressed;
uint8_t bpp;
uint16_t x0;
uint16_t y0;
uint16_t x1;
uint16_t y1;
uint16_t xdpi;
uint16_t ydpi;
uint8_t pal[16][3];
uint8_t reserved;
uint8_t layers;
uint16_t rowbytes;
uint16_t colortype;
uint8_t pad[58];
} pcxHeader;
if (pFileBuf == NULL) {
SetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
if (uXSize == NULL) {
SetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
if (uYSize == NULL) {
SetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
// get image information
memcpy(&pcxHeader, pFileBuf, sizeof(struct pcx_header_t));
*uXSize = (pcxHeader.x1 - pcxHeader.x0 + 1);
*uYSize = (pcxHeader.y1 - pcxHeader.y0 + 1);
if ((pcxHeader.version != 2) && (pcxHeader.version != 5)) {
cerr << "cannot handle pcx v" << pcxHeader.version << "\n";
return NULL;
}
// get palette
palette = new uint8_t[256*4];
if (pFileBuf[uFileSize - 768 - 1] != 0x0C) {
cerr << "palette error at " << uFileSize - 768 - 1 << "\n";
return NULL;
}
for (i=0; i<256; i++) {
memcpy(palette+i*4, pFileBuf+uFileSize-768+i*3, 3*sizeof(uint8_t));
palette[i*4+3] = 0xFF;
}
memset(palette+uTransColor*4, 0, 4*sizeof(uint8_t)); // transparent black
// start right after the header
uFilePos = sizeof(struct pcx_header_t);
data = new uint8_t[*uXSize * *uYSize * 4];
while (uDataRead < (uint32_t)(*uXSize * *uYSize)) {
// decompress
uColorNum = pFileBuf[uFilePos++];
if ((pcxHeader.compressed) && (uColorNum > 0xBF)) {
uCount = (uColorNum & 0x3F);
uColorNum = pFileBuf[uFilePos++];
} else
uCount = 1;
// draw count pixels with color val
for (i=0; i<uCount; i++)
memcpy(data+(uDataRead++)*4, palette+uColorNum*4, 4*sizeof(uint8_t));
}
// cleanup
delete[] palette;
return data;
}
File diff suppressed because it is too large Load Diff
@@ -1,88 +0,0 @@
/*****************************************************************************/
/* SCommon.h Copyright (c) Ladislav Zezula 2003 */
/*---------------------------------------------------------------------------*/
/* Common functions for encryption/decryption from Storm.dll. Included by */
/* SFile*** functions, do not include and do not use this file directly */
/*---------------------------------------------------------------------------*/
/* Date Ver Who Comment */
/* -------- ---- --- ------- */
/* 24.03.03 1.00 Lad The first version of SFileCommon.h */
/* 12.06.04 1.00 Lad Renamed to SCommon.h */
/*****************************************************************************/
#ifndef __SCOMMON_H__
#define __SCOMMON_H__
//-----------------------------------------------------------------------------
// StormLib private defines
#define SFILE_TYPE_DATA 0 // Process the file as data file
#define SFILE_TYPE_WAVE 1 // Process the file as WAVe file
//-----------------------------------------------------------------------------
// External variables
extern TMPQArchive * pFirstOpen;
extern LCID lcLocale;
//-----------------------------------------------------------------------------
// Encryption and decryption functions
int PrepareStormBuffer();
void EncryptHashTable(DWORD * pdwTable, BYTE * pbKey, DWORD dwLength);
void DecryptHashTable(DWORD * pdwTable, BYTE * pbKey, DWORD dwLength);
TMPQHash * FindFreeHashEntry(TMPQArchive * ha, const char * szFileName);
void EncryptBlockTable(DWORD * pdwTable, BYTE * pbKey, DWORD dwLength);
void DecryptBlockTable(DWORD * pdwTable, BYTE * pbKey, DWORD dwLength);
DWORD DetectFileSeed(DWORD * block, DWORD decrypted);
DWORD DetectFileSeed2(DWORD * block, UINT nDwords, ...);
void EncryptMPQBlock(DWORD * pdwBlock, DWORD dwLength, DWORD dwSeed1);
void DecryptMPQBlock(DWORD * pdwBlock, DWORD dwLength, DWORD dwSeed1);
DWORD DecryptHashIndex(TMPQArchive * ha, const char * szFileName);
DWORD DecryptName1 (const char * szFileName);
DWORD DecryptName2 (const char * szFileName);
DWORD DecryptFileSeed (const char * szFileName);
TMPQHash * GetHashEntry (TMPQArchive * ha, const char * szFileName);
TMPQHash * GetHashEntryEx(TMPQArchive * ha, const char * szFileName, LCID lcLocale);
//-----------------------------------------------------------------------------
// Compression and decompression functions
int Compress_pklib (char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength, int * pCmpType, int nCmpLevel);
int Decompress_pklib(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength);
//-----------------------------------------------------------------------------
// Checking functions
BOOL IsValidMpqHandle(TMPQArchive * ha);
BOOL IsValidFileHandle(TMPQFile * hf);
//-----------------------------------------------------------------------------
// Other functions
BOOL SFileOpenArchiveEx(const char * szMpqName, DWORD dwPriority, DWORD dwFlags, HANDLE * phMPQ, DWORD dwAccessMode = GENERIC_READ);
int AddFileToArchive(TMPQArchive * ha, HANDLE hFile, const char * szArchivedName, DWORD dwFlags, DWORD dwQuality, int nFileType, BOOL * pbReplaced);
int SetDataCompression(int nDataCompression);
int SaveMPQTables(TMPQArchive * ha);
void FreeMPQArchive(TMPQArchive *& ha);
BOOL CheckWildCard(const char * szString, const char * szWildCard);
//-----------------------------------------------------------------------------
// Listfile functions
int SListFileCreateListFile(TMPQArchive * ha);
int SListFileAddNode(TMPQArchive * ha, const char * szAddedFile);
int SListFileRemoveNode(TMPQArchive * ha, const char * szFileName);
int SListFileRenameNode(TMPQArchive * ha, const char * szOldFileName, const char * szNewFileName);
int SListFileFreeListFile(TMPQArchive * ha);
int SListFileSaveToMpq(TMPQArchive * ha);
#endif // __SCOMMON_H__
@@ -1,715 +0,0 @@
/*****************************************************************************/
/* SCompression.cpp Copyright (c) Ladislav Zezula 2003 */
/*---------------------------------------------------------------------------*/
/* This module serves as a bridge between StormLib code and (de)compression */
/* functions. All (de)compression calls go (and should only go) through this */
/* module. No system headers should be included in this module to prevent */
/* compile-time problems. */
/*---------------------------------------------------------------------------*/
/* Date Ver Who Comment */
/* -------- ---- --- ------- */
/* 01.04.03 1.00 Lad The first version of SCompression.cpp */
/* 19.11.03 1.01 Dan Big endian handling */
/*****************************************************************************/
#define __STORMLIB_SELF__
#include "StormLib.h"
#include "SCommon.h"
#include <string.h>
// Include functions from Pkware Data Compression Library
#include "pklib/pklib.h"
// Include functions from zlib
#ifndef __SYS_ZLIB
#include "zlib/zlib.h" // Include functions from zlib
#else
#include <zlib.h> // If zlib is available on system, use this instead
#endif
// Include functions from Huffmann compression
#include "huffman/huff.h"
// Include functions from WAVe compression
#include "wave/wave.h"
// Include functions from BZip2 compression library
#ifndef __SYS_BZLIB
#include "bzip2/bzlib.h" // Include functions from bzlib
#else
#include <bzlib.h> // If bzlib is available on system, use this instead
#endif
//-----------------------------------------------------------------------------
// Local structures
// Information about the input and output buffers for pklib
typedef struct
{
char * pInBuff; // Pointer to input data buffer
int nInPos; // Current offset in input data buffer
int nInBytes; // Number of bytes in the input buffer
char * pOutBuff; // Pointer to output data buffer
int nOutPos; // Position in the output buffer
int nMaxOut; // Maximum number of bytes in the output buffer
} TDataInfo;
// Table of compression functions
typedef int (*COMPRESS)(char *, int *, char *, int, int *, int);
typedef struct
{
unsigned long dwMask; // Compression mask
COMPRESS Compress; // Compression function
} TCompressTable;
// Table of decompression functions
typedef int (*DECOMPRESS)(char *, int *, char *, int);
typedef struct
{
unsigned long dwMask; // Decompression bit
DECOMPRESS Decompress; // Decompression function
} TDecompressTable;
/*****************************************************************************/
/* */
/* Support functions for Pkware Data Compression Library */
/* */
/*****************************************************************************/
// Function loads data from the input buffer. Used by Pklib's "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 ReadInputData(char * buf, unsigned int * size, void * param)
{
TDataInfo * pInfo = (TDataInfo *)param;
unsigned int nMaxAvail = (pInfo->nInBytes - pInfo->nInPos);
unsigned int nToRead = *size;
// Check the case when not enough data available
if(nToRead > nMaxAvail)
nToRead = nMaxAvail;
// Load data and increment offsets
memcpy(buf, pInfo->pInBuff + pInfo->nInPos, nToRead);
pInfo->nInPos += nToRead;
return nToRead;
}
// Function for store output data. Used by Pklib's "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 WriteOutputData(char * buf, unsigned int * size, void * param)
{
TDataInfo * pInfo = (TDataInfo *)param;
unsigned int nMaxWrite = (pInfo->nMaxOut - pInfo->nOutPos);
unsigned int nToWrite = *size;
// Check the case when not enough space in the output buffer
if(nToWrite > nMaxWrite)
nToWrite = nMaxWrite;
// Write output data and increments offsets
memcpy(pInfo->pOutBuff + pInfo->nOutPos, buf, nToWrite);
pInfo->nOutPos += nToWrite;
}
/*****************************************************************************/
/* */
/* "80" is IMA ADPCM stereo (de)compression */
/* "40" is IMA ADPCM mono (de)compression */
/* */
/*****************************************************************************/
int Compress_wave_mono(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength, int * pCmpType, int nCmpLevel)
{
// Prepare the compression level for the next compression
// (After us, the Huffmann compression will be called)
if(0 < nCmpLevel && nCmpLevel <= 2)
{
nCmpLevel = 4;
*pCmpType = 6;
}
else if(nCmpLevel == 3)
{
nCmpLevel = 6;
*pCmpType = 8;
}
else
{
nCmpLevel = 5;
*pCmpType = 7;
}
*pdwOutLength = CompressWave((unsigned char *)pbOutBuffer, *pdwOutLength, (short *)pbInBuffer, dwInLength, 1, nCmpLevel);
return 0;
}
int Decompress_wave_mono(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength)
{
*pdwOutLength = DecompressWave((unsigned char *)pbOutBuffer, *pdwOutLength, (unsigned char *)pbInBuffer, dwInLength, 1);
return 1;
}
int Compress_wave_stereo(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength, int * pCmpType, int nCmpLevel)
{
// Prepare the compression type for the next compression
// (After us, the Huffmann compression will be called)
if(0 < nCmpLevel && nCmpLevel <= 2)
{
nCmpLevel = 4;
*pCmpType = 6;
}
else if(nCmpLevel == 3)
{
nCmpLevel = 6;
*pCmpType = 8;
}
else
{
nCmpLevel = 5;
*pCmpType = 7;
}
*pdwOutLength = CompressWave((unsigned char *)pbOutBuffer, *pdwOutLength, (short *)pbInBuffer, dwInLength, 2, nCmpLevel);
return 0;
}
int Decompress_wave_stereo(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength)
{
*pdwOutLength = DecompressWave((unsigned char *)pbOutBuffer, *pdwOutLength, (unsigned char *)pbInBuffer, dwInLength, 2);
return 1;
}
/*****************************************************************************/
/* */
/* The "01" (de)compression is the Huffman (de)compression */
/* */
/*****************************************************************************/
// 1500F4C0
int Compress_huff(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength, int * pCmpType, int /* nCmpLevel */)
{
THuffmannTree ht; // Huffmann tree for compression
TOutputStream os; // Output stream
// Initialize output stream
os.pbOutBuffer = (unsigned char *)pbOutBuffer;
os.dwOutSize = *pdwOutLength;
os.pbOutPos = (unsigned char *)pbOutBuffer;
os.dwBitBuff = 0;
os.nBits = 0;
// Initialize the Huffmann tree for compression
ht.InitTree(true);
*pdwOutLength = ht.DoCompression(&os, (unsigned char *)pbInBuffer, dwInLength, *pCmpType);
// The following code is not necessary to run, because it has no
// effect on the output data. It only clears the huffmann tree, but when
// the tree is on the stack, who cares ?
// ht.UninitTree();
return 0;
}
// 1500F5F0
int Decompress_huff(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int /* dwInLength */)
{
THuffmannTree ht;
TInputStream is;
// Initialize input stream
// is.pbInBuffer = (unsigned char *)pbInBuffer;
is.dwBitBuff = BSWAP_INT32_UNSIGNED(*(unsigned long *)pbInBuffer);
pbInBuffer += sizeof(unsigned long);
is.pbInBuffer = (unsigned char *)pbInBuffer;
is.nBits = 32;
// Initialize the Huffmann tree for compression
ht.InitTree(false);
*pdwOutLength = ht.DoDecompression((unsigned char *)pbOutBuffer, *pdwOutLength, &is);
// The following code is not necessary to run, because it has no
// effect on the output data. It only clears the huffmann tree, but when
// the tree is on the stack, who cares ?
// ht.UninitTree();
return 0;
}
/*****************************************************************************/
/* */
/* The "02" (de)compression is the ZLIB (de)compression */
/* */
/*****************************************************************************/
int Compress_zlib(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength, int * /* pCmpType */, int /* nCmpLevel */)
{
z_stream z; // Stream information for zlib
int nResult;
// Fill the stream structure for zlib
z.next_in = (Bytef *)pbInBuffer;
z.avail_in = (uInt)dwInLength;
z.total_in = dwInLength;
z.next_out = (Bytef *)pbOutBuffer;
z.avail_out = *pdwOutLength;
z.total_out = 0;
z.zalloc = NULL;
z.zfree = NULL;
// Initialize the compression structure. Storm.dll uses zlib version 1.1.3
*pdwOutLength = 0;
if((nResult = deflateInit(&z, Z_DEFAULT_COMPRESSION)) == 0)
{
// Call zlib to compress the data
nResult = deflate(&z, Z_FINISH);
if(nResult == Z_OK || nResult == Z_STREAM_END)
*pdwOutLength = z.total_out;
deflateEnd(&z);
}
return nResult;
}
int Decompress_zlib(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength)
{
z_stream z; // Stream information for zlib
int nResult;
// Fill the stream structure for zlib
z.next_in = (Bytef *)pbInBuffer;
z.avail_in = (uInt)dwInLength;
z.total_in = dwInLength;
z.next_out = (Bytef *)pbOutBuffer;
z.avail_out = *pdwOutLength;
z.total_out = 0;
z.zalloc = NULL;
z.zfree = NULL;
// Initialize the decompression structure. Storm.dll uses zlib version 1.1.3
if((nResult = inflateInit(&z)) == 0)
{
// Call zlib to decompress the data
nResult = inflate(&z, Z_FINISH);
*pdwOutLength = z.total_out;
inflateEnd(&z);
}
return nResult;
}
/*****************************************************************************/
/* */
/* The "08" (de)compression is the Pkware DCL (de)compression */
/* */
/*****************************************************************************/
int Compress_pklib(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength, int * pCmpType, int /* nCmpLevel */)
{
TDataInfo Info; // Data information
char * work_buf = ALLOCMEM(char, CMP_BUFFER_SIZE);// Pklib's work buffer
unsigned int dict_size; // Dictionary size
unsigned int ctype; // Compression type
// Fill data information structure
Info.pInBuff = pbInBuffer;
Info.nInPos = 0;
Info.nInBytes = dwInLength;
Info.pOutBuff = pbOutBuffer;
Info.nOutPos = 0;
Info.nMaxOut = *pdwOutLength;
// Set the compression type and dictionary size
ctype = (*pCmpType == 2) ? CMP_ASCII : CMP_BINARY;
if (dwInLength < 0x600)
dict_size = 0x400;
else if(0x600 <= dwInLength && dwInLength < 0xC00)
dict_size = 0x800;
else
dict_size = 0x1000;
// Do the compression
implode(ReadInputData, WriteOutputData, work_buf, &Info, &ctype, &dict_size);
*pdwOutLength = Info.nOutPos;
FREEMEM(work_buf);
return 0;
}
int Decompress_pklib(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength)
{
TDataInfo Info; // Data information
char * work_buf = ALLOCMEM(char, EXP_BUFFER_SIZE);// Pklib's work buffer
// Fill data information structure
Info.pInBuff = pbInBuffer;
Info.nInPos = 0;
Info.nInBytes = dwInLength;
Info.pOutBuff = pbOutBuffer;
Info.nOutPos = 0;
Info.nMaxOut = *pdwOutLength;
// Do the decompression
explode(ReadInputData, WriteOutputData, work_buf, &Info);
// Fix: If PKLIB is unable to decompress the data, they are uncompressed
if(Info.nOutPos == 0)
{
Info.nOutPos = min(*pdwOutLength, dwInLength);
memcpy(pbOutBuffer, pbInBuffer, Info.nOutPos);
}
*pdwOutLength = Info.nOutPos;
FREEMEM(work_buf);
return 0;
}
/*****************************************************************************/
/* */
/* The "10" (de)compression is the Bzip2 (de)compression */
/* */
/*****************************************************************************/
int Compress_bzip2(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength, int * pCmpType, int nCmpLevel)
{
bz_stream strm;
int blockSize100k;
int workFactor = 30;
// Keep compiler happy
nCmpLevel = nCmpLevel;
// Initialize the BZLIB compression
strm.bzalloc = NULL;
strm.bzfree = NULL;
// Adjust the block size
blockSize100k = *pCmpType;
if(blockSize100k < 1 || blockSize100k > 9)
blockSize100k = 9;
// Blizzard uses 9 as blockSize100k, (0 as workFactor)
if(BZ2_bzCompressInit(&strm, blockSize100k, 0, workFactor) == 0)
{
strm.next_in = pbInBuffer;
strm.avail_in = dwInLength;
strm.next_out = pbOutBuffer;
strm.avail_out = *pdwOutLength;
// Perform the compression
while(BZ2_bzCompress(&strm, (strm.avail_in != 0) ? BZ_RUN : BZ_FINISH) != BZ_STREAM_END);
// Put the stream into idle state
BZ2_bzCompressEnd(&strm);
*pdwOutLength = strm.total_out_lo32;
}
else
{
*pdwOutLength = 0;
}
return 0;
}
int Decompress_bzip2(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength)
{
bz_stream strm;
// Initialize the BZLIB decompression
strm.bzalloc = NULL;
strm.bzfree = NULL;
if(BZ2_bzDecompressInit(&strm, 0, 0) == 0)
{
strm.next_in = pbInBuffer;
strm.avail_in = dwInLength;
strm.next_out = pbOutBuffer;
strm.avail_out = *pdwOutLength;
// Perform the decompression
while(BZ2_bzDecompress(&strm) != BZ_STREAM_END);
// Put the stream into idle state
BZ2_bzDecompressEnd(&strm);
*pdwOutLength = strm.total_out_lo32;
}
else
{
// Set zero output length
*pdwOutLength = 0;
}
return 0;
}
/*****************************************************************************/
/* */
/* SCompCompress */
/* */
/*****************************************************************************/
// This table contains compress functions which can be applied to
// uncompressed blocks. Each bit set means the corresponding
// compression method/function must be applied.
//
// WAVes compression Data compression
// ------------------ -------------------
// 1st block - 0x08 0x08 (D, HF, W2, SC, D2)
// Rest blocks - 0x81 0x02 (W3)
static TCompressTable cmp_table[] =
{
{MPQ_COMPRESSION_WAVE_MONO, Compress_wave_mono}, // IMA ADPCM mono compression
{MPQ_COMPRESSION_WAVE_STEREO, Compress_wave_stereo}, // IMA ADPCM stereo compression
{MPQ_COMPRESSION_HUFFMANN, Compress_huff}, // Huffmann compression
{MPQ_COMPRESSION_ZLIB, Compress_zlib}, // Compression with the "zlib" library
{MPQ_COMPRESSION_PKWARE, Compress_pklib}, // Compression with Pkware DCL
{MPQ_COMPRESSION_BZIP2, Compress_bzip2} // Compression Bzip2 library
};
int WINAPI SCompCompress(char * pbCompressed, int * pdwOutLength, char * pbUncompressed, int dwInLength,
int uCompressions, int nCmpType, int nCmpLevel)
{
char * pbTempBuff = NULL; // Temporary storage for decompressed data
char * pbOutput = pbCompressed; // Current output buffer
char * pbInput; // Current input buffer
int uCompressions2;
int dwCompressCount = 0;
int dwDoneCount = 0;
int dwOutSize = 0;
int dwInSize = dwInLength;
int dwEntries = (sizeof(cmp_table) / sizeof(TCompressTable));
int nResult = 1;
int i;
// Check for valid parameters
if(!pdwOutLength || *pdwOutLength < dwInLength || !pbCompressed || !pbUncompressed)
{
SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
// Count the compressions
for(i = 0, uCompressions2 = uCompressions; i < dwEntries; i++)
{
if(uCompressions & cmp_table[i].dwMask)
dwCompressCount++;
uCompressions2 &= ~cmp_table[i].dwMask;
}
// If a compression remains, do nothing
if(uCompressions2 != 0)
{
SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
// If more that one compression, allocate intermediate buffer
if(dwCompressCount >= 2)
pbTempBuff = ALLOCMEM(char, *pdwOutLength + 1);
// Perform the compressions
pbInput = pbUncompressed;
dwInSize = dwInLength;
for(i = 0, uCompressions2 = uCompressions; i < dwEntries; i++)
{
if(uCompressions2 & cmp_table[i].dwMask)
{
// Set the right output buffer
dwCompressCount--;
pbOutput = (dwCompressCount & 1) ? pbTempBuff : pbCompressed;
// Perform the partial compression
dwOutSize = *pdwOutLength - 1;
cmp_table[i].Compress(pbOutput + 1, &dwOutSize, pbInput, dwInSize, &nCmpType, nCmpLevel);
if(dwOutSize == 0)
{
SetLastError(ERROR_GEN_FAILURE);
*pdwOutLength = 0;
nResult = 0;
break;
}
// If the compression failed, copy the block instead
if(dwOutSize >= dwInSize - 1)
{
if(dwDoneCount > 0)
pbOutput++;
memcpy(pbOutput, pbInput, dwInSize);
pbInput = pbOutput;
uCompressions &= ~cmp_table[i].dwMask;
dwOutSize = dwInSize;
}
else
{
pbInput = pbOutput + 1;
dwInSize = dwOutSize;
dwDoneCount++;
}
}
}
// Copy the compressed data to the correct output buffer
if(nResult != 0)
{
if(uCompressions && (dwInSize + 1) < *pdwOutLength)
{
if(pbOutput != pbCompressed && pbOutput != pbCompressed + 1)
memcpy(pbCompressed, pbOutput, dwInSize);
*pbCompressed = (char)uCompressions;
*pdwOutLength = dwInSize + 1;
}
else
{
memmove(pbCompressed, pbUncompressed, dwInSize);
*pdwOutLength = dwInSize;
}
}
// Cleanup and return
if(pbTempBuff != NULL)
FREEMEM(pbTempBuff);
return nResult;
}
/*****************************************************************************/
/* */
/* SCompDecompress */
/* */
/*****************************************************************************/
// This table contains decompress functions which can be applied to
// uncompressed blocks. The compression mask is stored in the first byte
// of compressed block
static TDecompressTable dcmp_table[] =
{
{MPQ_COMPRESSION_BZIP2, Decompress_bzip2}, // Decompression with Bzip2 library
{MPQ_COMPRESSION_PKWARE, Decompress_pklib}, // Decompression with Pkware Data Compression Library
{MPQ_COMPRESSION_ZLIB, Decompress_zlib}, // Decompression with the "zlib" library
{MPQ_COMPRESSION_HUFFMANN, Decompress_huff}, // Huffmann decompression
{MPQ_COMPRESSION_WAVE_STEREO, Decompress_wave_stereo}, // IMA ADPCM stereo decompression
{MPQ_COMPRESSION_WAVE_MONO, Decompress_wave_mono} // IMA ADPCM mono decompression
};
int WINAPI SCompDecompress(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength)
{
char * pbTempBuff = NULL; // Temporary storage for decompressed data
char * pbWorkBuff = NULL; // Where to store decompressed data
int dwOutLength = *pdwOutLength; // 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 dwCount = 0; // Counter for every use
int dwEntries = (sizeof(dcmp_table) / sizeof(TDecompressTable));
int nResult = 1;
int i;
// If the input length is the same as output, do nothing.
if(dwInLength == dwOutLength)
{
if(pbInBuffer == pbOutBuffer)
return 1;
memcpy(pbOutBuffer, pbInBuffer, dwInLength);
*pdwOutLength = dwInLength;
return 1;
}
// Get applied compression types and decrement data length
fDecompressions1 = fDecompressions2 = (unsigned char)*pbInBuffer++;
dwInLength--;
// Search decompression table type and get all types of compression
for(i = 0; i < dwEntries; i++)
{
// We have to apply this decompression ?
if(fDecompressions1 & dcmp_table[i].dwMask)
dwCount++;
// Clear this flag from temporary variable.
fDecompressions2 &= ~dcmp_table[i].dwMask;
}
// Check if there is some method unhandled
// (E.g. compressed by future versions)
if(fDecompressions2 != 0)
{
SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
// If there is more than only one compression, we have to allocate extra buffer
if(dwCount >= 2)
pbTempBuff = ALLOCMEM(char, dwOutLength);
// Apply all decompressions
for(i = 0, dwCount = 0; i < dwEntries; i++)
{
// If not used this kind of compression, skip the loop
if(fDecompressions1 & dcmp_table[i].dwMask)
{
// If odd case, use target buffer for output, otherwise use allocated tempbuffer
pbWorkBuff = (dwCount++ & 1) ? pbTempBuff : pbOutBuffer;
dwOutLength = *pdwOutLength;
// Decompress buffer using corresponding function
dcmp_table[i].Decompress(pbWorkBuff, &dwOutLength, pbInBuffer, dwInLength);
if(dwOutLength == 0)
{
SetLastError(ERROR_GEN_FAILURE);
nResult = 0;
break;
}
// Move output length to src length for next compression
dwInLength = dwOutLength;
pbInBuffer = pbWorkBuff;
}
}
// If output buffer is not the same like target buffer, we have to copy data
if(nResult != 0)
{
if(pbWorkBuff != pbOutBuffer)
memcpy(pbOutBuffer, pbInBuffer, dwOutLength);
}
// Delete temporary buffer, if necessary
if(pbTempBuff != NULL)
FREEMEM(pbTempBuff);
*pdwOutLength = dwOutLength;
return nResult;
}
/*****************************************************************************/
/* */
/* SCompSetDataCompression */
/* */
/*****************************************************************************/
int WINAPI SCompSetDataCompression(int nDataCompression)
{
int nValidMask = (MPQ_COMPRESSION_ZLIB | MPQ_COMPRESSION_PKWARE | MPQ_COMPRESSION_BZIP2);
if((nDataCompression & nValidMask) != nDataCompression)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
SetDataCompression(nDataCompression);
return TRUE;
}
@@ -1,691 +0,0 @@
/*****************************************************************************/
/* SFileCompactArchive.cpp Copyright (c) Ladislav Zezula 2003 */
/*---------------------------------------------------------------------------*/
/* Archive compacting function */
/*---------------------------------------------------------------------------*/
/* Date Ver Who Comment */
/* -------- ---- --- ------- */
/* 14.04.03 1.00 Lad Splitted from SFileCreateArchiveEx.cpp */
/* 19.11.03 1.01 Dan Big endian handling */
/*****************************************************************************/
#define __STORMLIB_SELF__
#include "StormLib.h"
#include "SCommon.h"
/*****************************************************************************/
/* Local structures */
/*****************************************************************************/
/*****************************************************************************/
/* Local variables */
/*****************************************************************************/
static COMPACTCB CompactCB = NULL;
static void * lpUserData = NULL;
/*****************************************************************************/
/* Local functions */
/*****************************************************************************/
// Creates a copy of hash table
static TMPQHash * CopyHashTable(TMPQArchive * ha)
{
TMPQHash * pHashTableCopy = ALLOCMEM(TMPQHash, ha->pHeader->dwHashTableSize);
if(pHashTableCopy != NULL)
memcpy(pHashTableCopy, ha->pHashTable, sizeof(TMPQHash) * ha->pHeader->dwHashTableSize);
return pHashTableCopy;
}
// TODO: Test for archives > 4GB
static int CheckIfAllFilesKnown(TMPQArchive * ha, const char * szListFile, DWORD * pFileSeeds)
{
TMPQHash * pHashTableCopy = NULL; // Copy of the hash table
TMPQHash * pHash;
TMPQHash * pHashEnd = NULL; // End of the hash table
DWORD dwFileCount = 0;
int nError = ERROR_SUCCESS;
// First of all, create a copy of hash table
if(nError == ERROR_SUCCESS)
{
if((pHashTableCopy = CopyHashTable(ha)) == NULL)
nError = ERROR_NOT_ENOUGH_MEMORY;
pHashEnd = pHashTableCopy + ha->pHeader->dwHashTableSize;
// Notify the user
if(CompactCB != NULL)
CompactCB(lpUserData, CCB_CHECKING_FILES, 0, ha->pHeader->dwBlockTableSize);
}
// Now check all the files from the filelist
if(nError == ERROR_SUCCESS)
{
SFILE_FIND_DATA wf;
HANDLE hFind = SFileFindFirstFile((HANDLE)ha, "*", &wf, szListFile);
BOOL bResult = TRUE;
// Do while some files have been found
while(hFind != NULL && bResult)
{
TMPQHash * pHash = GetHashEntry(ha, wf.cFileName);
// If the hash table entry has been found, find it's position
// in the hash table copy
if(pHash != NULL)
{
pHash = pHashTableCopy + (pHash - ha->pHashTable);
if(pHash->dwName1 != (DWORD)-1 && pHash->dwName2 != (DWORD)-1)
{
TMPQBlock * pBlock = ha->pBlockTable + pHash->dwBlockIndex;
DWORD dwSeed = 0;
// Resolve the file seed. Use plain file name for it
if(pBlock->dwFlags & MPQ_FILE_ENCRYPTED)
{
char * szFileName = strrchr(wf.cFileName, '\\');
if(szFileName == NULL)
szFileName = wf.cFileName;
else
szFileName++;
dwSeed = DecryptFileSeed(szFileName);
if(pBlock->dwFlags & MPQ_FILE_FIXSEED)
dwSeed = (dwSeed + pBlock->dwFilePos) ^ pBlock->dwFSize;
}
pFileSeeds[pHash->dwBlockIndex] = dwSeed;
pHash->dwName1 = 0xFFFFFFFF;
pHash->dwName2 = 0xFFFFFFFF;
pHash->lcLocale = 0xFFFF;
pHash->wPlatform = 0xFFFF;
pHash->dwBlockIndex = 0xFFFFFFFF;
}
}
// Notify the user
if(CompactCB != NULL)
CompactCB(lpUserData, CCB_CHECKING_FILES, ++dwFileCount, ha->pHeader->dwBlockTableSize);
// Find the next file in the archive
bResult = SFileFindNextFile(hFind, &wf);
}
if(hFind != NULL)
SFileFindClose(hFind);
}
// When the filelist checking is complete, parse the hash table copy and find the
if(nError == ERROR_SUCCESS)
{
// Notify the user about checking hash table
dwFileCount = 0;
if(CompactCB != NULL)
CompactCB(lpUserData, CCB_CHECKING_HASH_TABLE, dwFileCount, ha->pHeader->dwBlockTableSize);
for(pHash = pHashTableCopy; pHash < pHashEnd; pHash++)
{
// If there is an unresolved entry, try to detect its seed. If it fails,
// we cannot complete the work
if(pHash->dwName1 != (DWORD)-1 && pHash->dwName2 != (DWORD)-1)
{
HANDLE hFile = NULL;
DWORD dwFlags = 0;
DWORD dwSeed = 0;
if(SFileOpenFileEx((HANDLE)ha, (char *)(DWORD_PTR)pHash->dwBlockIndex, 0, &hFile))
{
TMPQFile * hf = (TMPQFile *)hFile;
dwFlags = hf->pBlock->dwFlags;
dwSeed = hf->dwSeed1;
SFileCloseFile(hFile);
}
// If the file is encrypted, we have to check
// If we can apply the file decryption seed
if(dwFlags & MPQ_FILE_ENCRYPTED && dwSeed == 0)
{
nError = ERROR_CAN_NOT_COMPLETE;
break;
}
// Remember the seed
pFileSeeds[pHash->dwBlockIndex] = dwSeed;
// Notify the user
if(CompactCB != NULL)
CompactCB(lpUserData, CCB_CHECKING_HASH_TABLE, ++dwFileCount, ha->pHeader->dwBlockTableSize);
}
}
}
// Delete the copy of hash table
if(pHashTableCopy != NULL)
FREEMEM(pHashTableCopy);
return nError;
}
// Copies all file blocks into another archive.
// TODO: Test for archives > 4GB
static int CopyMpqFileBlocks(
HANDLE hFile,
TMPQArchive * ha,
TMPQBlockEx * pBlockEx,
TMPQBlock * pBlock,
DWORD dwSeed)
{
LARGE_INTEGER FilePos = {0};
DWORD * pdwBlockPos2 = NULL; // File block positions to be written to target file
DWORD * pdwBlockPos = NULL; // File block positions (unencrypted)
BYTE * pbBlock = NULL; // Buffer for the file block
DWORD dwTransferred; // Number of bytes transferred
DWORD dwCSize = 0; // Compressed file size
DWORD dwBytes = 0; // Number of bytes
DWORD dwSeed1 = 0; // File seed used for decryption
DWORD dwSeed2 = 0; // File seed used for encryption
DWORD nBlocks = 0; // Number of file blocks
DWORD nBlock = 0; // Currently processed file block
int nError = ERROR_SUCCESS;
// When file length is zero, do nothing
if(pBlock->dwFSize == 0)
return ERROR_SUCCESS;
// Calculate number of blocks in the file
if(nError == ERROR_SUCCESS)
{
nBlocks = pBlock->dwFSize / ha->dwBlockSize;
if(pBlock->dwFSize % ha->dwBlockSize)
nBlocks++;
pbBlock = ALLOCMEM(BYTE, ha->dwBlockSize);
if(pbBlock == NULL)
nError = ERROR_NOT_ENOUGH_MEMORY;
}
// Set the position to the begin of the file within archive
if(nError == ERROR_SUCCESS)
{
FilePos.HighPart = pBlockEx->wFilePosHigh;
FilePos.LowPart = pBlock->dwFilePos;
FilePos.QuadPart += ha->MpqPos.QuadPart;
if(SetFilePointer(ha->hFile, FilePos.LowPart, &FilePos.HighPart, FILE_BEGIN) != FilePos.LowPart)
nError = GetLastError();
}
// Remember the position in the destination file
if(nError == ERROR_SUCCESS)
{
FilePos.HighPart = 0;
FilePos.LowPart = SetFilePointer(hFile, 0, &FilePos.HighPart, FILE_CURRENT);
}
// Resolve decryption seeds. The 'dwSeed' parameter is the decryption
// seed for the file.
if(nError == ERROR_SUCCESS && (pBlock->dwFlags & MPQ_FILE_ENCRYPTED))
{
dwSeed1 = dwSeed;
if(pBlock->dwFlags & MPQ_FILE_FIXSEED)
dwSeed = (dwSeed1 ^ pBlock->dwFSize) - pBlock->dwFilePos;
dwSeed2 = dwSeed;
if(pBlock->dwFlags & MPQ_FILE_FIXSEED)
dwSeed2 = (dwSeed + (DWORD)(FilePos.QuadPart - ha->MpqPos.QuadPart)) ^ pBlock->dwFSize;
}
// Load the file positions from the archive and save it to the target file
// (only if the file is compressed)
if(pBlock->dwFlags & MPQ_FILE_COMPRESSED)
{
// Allocate buffers
if(nError == ERROR_SUCCESS)
{
pdwBlockPos = ALLOCMEM(DWORD, nBlocks + 2);
pdwBlockPos2 = ALLOCMEM(DWORD, nBlocks + 2);
if(pdwBlockPos == NULL || pdwBlockPos2 == NULL)
nError = ERROR_NOT_ENOUGH_MEMORY;
}
// Load the block positions
if(nError == ERROR_SUCCESS)
{
dwBytes = (nBlocks + 1) * sizeof(DWORD);
if(pBlock->dwFlags & MPQ_FILE_HAS_EXTRA)
dwBytes += sizeof(DWORD);
ReadFile(ha->hFile, pdwBlockPos, dwBytes, &dwTransferred, NULL);
if(dwTransferred != dwBytes)
nError = ERROR_FILE_CORRUPT;
}
// Re-encrypt the block table positions
if(nError == ERROR_SUCCESS)
{
BSWAP_ARRAY32_UNSIGNED(pdwBlockPos, dwBytes / sizeof(DWORD));
if(pBlock->dwFlags & MPQ_FILE_ENCRYPTED)
{
DecryptMPQBlock(pdwBlockPos, dwBytes, dwSeed1 - 1);
if(pdwBlockPos[0] != dwBytes)
nError = ERROR_FILE_CORRUPT;
memcpy(pdwBlockPos2, pdwBlockPos, dwBytes);
EncryptMPQBlock(pdwBlockPos2, dwBytes, dwSeed2 - 1);
}
else
{
memcpy(pdwBlockPos2, pdwBlockPos, dwBytes);
}
BSWAP_ARRAY32_UNSIGNED(pdwBlockPos2, dwBytes / sizeof(DWORD));
}
// Write to the target file
if(nError == ERROR_SUCCESS)
{
WriteFile(hFile, pdwBlockPos2, dwBytes, &dwTransferred, NULL);
dwCSize += dwTransferred;
if(dwTransferred != dwBytes)
nError = ERROR_DISK_FULL;
}
}
// Now we have to copy all file block. We will do it without
// recompression, because re-compression is not necessary in this case
if(nError == ERROR_SUCCESS)
{
for(nBlock = 0; nBlock < nBlocks; nBlock++)
{
// Fix: The last block must not be exactly the size of one block.
dwBytes = ha->dwBlockSize;
if(nBlock == nBlocks - 1)
{
dwBytes = pBlock->dwFSize - (ha->dwBlockSize * (nBlocks - 1));
}
if(pBlock->dwFlags & MPQ_FILE_COMPRESSED)
dwBytes = pdwBlockPos[nBlock+1] - pdwBlockPos[nBlock];
// Read the file block
ReadFile(ha->hFile, pbBlock, dwBytes, &dwTransferred, NULL);
if(dwTransferred != dwBytes)
{
nError = ERROR_FILE_CORRUPT;
break;
}
// If necessary, re-encrypt the block
// Note: Recompression is not necessary here. Unlike encryption,
// the compression does not depend on the position of the file in MPQ.
if((pBlock->dwFlags & MPQ_FILE_ENCRYPTED) && dwSeed1 != dwSeed2)
{
BSWAP_ARRAY32_UNSIGNED((DWORD *)pbBlock, dwBytes/sizeof(DWORD));
DecryptMPQBlock((DWORD *)pbBlock, dwBytes, dwSeed1 + nBlock);
EncryptMPQBlock((DWORD *)pbBlock, dwBytes, dwSeed2 + nBlock);
BSWAP_ARRAY32_UNSIGNED((DWORD *)pbBlock, dwBytes/sizeof(DWORD));
}
// Now write the block back to the file
WriteFile(hFile, pbBlock, dwBytes, &dwTransferred, NULL);
dwCSize += dwTransferred;
if(dwTransferred != dwBytes)
{
nError = ERROR_DISK_FULL;
break;
}
}
}
// Copy the file extras, if any
// These extras does not seem to be encrypted, and their purpose is unknown
if(nError == ERROR_SUCCESS && (pBlock->dwFlags & MPQ_FILE_HAS_EXTRA))
{
dwBytes = pdwBlockPos[nBlocks + 1] - pdwBlockPos[nBlocks];
if(dwBytes != 0)
{
ReadFile(ha->hFile, pbBlock, dwBytes, &dwTransferred, NULL);
if(dwTransferred == dwBytes)
{
WriteFile(hFile, pbBlock, dwBytes, &dwTransferred, NULL);
dwCSize += dwTransferred;
if(dwTransferred != dwBytes)
nError = ERROR_DISK_FULL;
}
else
{
nError = ERROR_FILE_CORRUPT;
}
}
}
// Update file position in the block table
if(nError == ERROR_SUCCESS)
{
// At this point, number of bytes written should be exactly
// the same like the compressed file size. If it isn't, there's something wrong
// (maybe new archive version ?)
assert(dwCSize == pBlock->dwCSize);
// Update file pos in the block table
FilePos.QuadPart -= ha->MpqPos.QuadPart;
pBlockEx->wFilePosHigh = (USHORT)FilePos.HighPart;
pBlock->dwFilePos = FilePos.LowPart;
}
// Cleanup and return
if(pdwBlockPos2 != NULL)
FREEMEM(pdwBlockPos2);
if(pdwBlockPos != NULL)
FREEMEM(pdwBlockPos);
if(pbBlock != NULL)
FREEMEM(pbBlock);
return nError;
}
static int CopyNonMpqData(
HANDLE hSrcFile,
HANDLE hTrgFile,
LARGE_INTEGER & DataSizeToCopy)
{
LARGE_INTEGER DataSize = DataSizeToCopy;
DWORD dwTransferred;
DWORD dwToRead;
char DataBuffer[0x1000];
int nError = ERROR_SUCCESS;
while(DataSize.QuadPart > 0)
{
// Get the proper size of data
dwToRead = sizeof(DataBuffer);
if(DataSize.HighPart == 0 && DataSize.LowPart < dwToRead)
dwToRead = DataSize.LowPart;
// Read the source file
ReadFile(hSrcFile, DataBuffer, dwToRead, &dwTransferred, NULL);
if(dwTransferred != dwToRead)
{
nError = ERROR_CAN_NOT_COMPLETE;
break;
}
// Write to the target file
WriteFile(hTrgFile, DataBuffer, dwToRead, &dwTransferred, NULL);
if(dwTransferred != dwToRead)
{
nError = ERROR_DISK_FULL;
break;
}
// Decrement the number of data to be copied
DataSize.QuadPart -= dwTransferred;
}
return ERROR_SUCCESS;
}
// TODO: Test for archives > 4GB
static int CopyMpqFiles(HANDLE hFile, TMPQArchive * ha, DWORD * pFileSeeds)
{
TMPQBlockEx * pBlockEx;
TMPQBlock * pBlock;
DWORD dwSeed1;
DWORD dwIndex;
int nError = ERROR_SUCCESS;
// Walk through all files and write them to the destination MPQ archive
for(dwIndex = 0; dwIndex < ha->pHeader->dwBlockTableSize; dwIndex++)
{
pBlockEx = ha->pExtBlockTable + dwIndex;
pBlock = ha->pBlockTable + dwIndex;
dwSeed1 = pFileSeeds[dwIndex];
// Notify the caller about work
if(CompactCB != NULL)
CompactCB(lpUserData, CCB_COMPACTING_FILES, dwIndex, ha->pHeader->dwBlockTableSize);
// if(dwIndex == 0x1B9)
// DebugBreak();
// Copy all the file blocks
// Debug: Break at (dwIndex == 5973)
if(pBlock->dwFlags & MPQ_FILE_EXISTS)
{
nError = CopyMpqFileBlocks(hFile, ha, pBlockEx, pBlock, dwSeed1);
if(nError != ERROR_SUCCESS)
break;
}
}
// Cleanup and exit
return nError;
}
/*****************************************************************************/
/* Public functions */
/*****************************************************************************/
BOOL WINAPI SFileSetCompactCallback(HANDLE /* hMPQ */, COMPACTCB aCompactCB, void * lpData)
{
CompactCB = aCompactCB;
lpUserData = lpData;
return TRUE;
}
//-----------------------------------------------------------------------------
// Archive compacting (incomplete)
// TODO: Test for archives > 4GB
BOOL WINAPI SFileCompactArchive(HANDLE hMPQ, const char * szListFile, BOOL /* bReserved */)
{
TMPQArchive * ha = (TMPQArchive *)hMPQ;
HANDLE hFile = INVALID_HANDLE_VALUE;
DWORD * pFileSeeds = NULL;
char szTempFile[MAX_PATH] = "";
char * szTemp = NULL;
DWORD dwTransferred;
int nError = ERROR_SUCCESS;
// Test the valid parameters
if(!IsValidMpqHandle(ha))
nError = ERROR_INVALID_PARAMETER;
// Create the table with file seeds
if(nError == ERROR_SUCCESS)
{
if((pFileSeeds = ALLOCMEM(DWORD, ha->pHeader->dwBlockTableSize)) != NULL)
memset(pFileSeeds, 0, sizeof(DWORD) * ha->pHeader->dwBlockTableSize);
else
nError = ERROR_NOT_ENOUGH_MEMORY;
}
// First of all, we have to check of we are able to decrypt all files.
// If not, sorry, but the archive cannot be compacted.
if(nError == ERROR_SUCCESS)
nError = CheckIfAllFilesKnown(ha, szListFile, pFileSeeds);
// Get the temporary file name and create it
if(nError == ERROR_SUCCESS)
{
if(CompactCB != NULL)
CompactCB(lpUserData, CCB_COPYING_NON_MPQ_DATA, 0, 0);
strcpy(szTempFile, ha->szFileName);
if((szTemp = strrchr(szTempFile, '.')) != NULL)
strcpy(szTemp + 1, "mp_");
else
strcat(szTempFile, "_");
hFile = CreateFile(szTempFile, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL);
if(hFile == INVALID_HANDLE_VALUE)
nError = GetLastError();
}
// Write the data before MPQ header (if any)
if(nError == ERROR_SUCCESS && ha->MpqPos.QuadPart > 0)
{
SetFilePointer(ha->hFile, 0, NULL, FILE_BEGIN);
if(ha->pShunt != NULL)
nError = CopyNonMpqData(ha->hFile, hFile, ha->ShuntPos);
else
nError = CopyNonMpqData(ha->hFile, hFile, ha->MpqPos);
}
// Write the MPQ shunt (if any)
if(nError == ERROR_SUCCESS && ha->pShunt != NULL)
{
BSWAP_TMPQSHUNT(ha->pShunt);
WriteFile(hFile, ha->pShunt, sizeof(TMPQShunt), &dwTransferred, NULL);
BSWAP_TMPQSHUNT(ha->pShunt);
if(dwTransferred != sizeof(TMPQShunt))
nError = ERROR_DISK_FULL;
}
// Write the data between MPQ shunt and the MPQ header (if any)
if(nError == ERROR_SUCCESS && ha->pShunt != NULL)
{
LARGE_INTEGER BytesToCopy;
BytesToCopy.QuadPart = ha->MpqPos.QuadPart - (ha->ShuntPos.QuadPart + sizeof(TMPQShunt));
nError = CopyNonMpqData(ha->hFile, hFile, BytesToCopy);
}
// Write the MPQ header
if(nError == ERROR_SUCCESS)
{
BSWAP_TMPQHEADER(ha->pHeader);
WriteFile(hFile, ha->pHeader, ha->pHeader->dwHeaderSize, &dwTransferred, NULL);
BSWAP_TMPQHEADER(ha->pHeader);
if(dwTransferred != ha->pHeader->dwHeaderSize)
nError = ERROR_DISK_FULL;
}
// Write the data between the header and between the first file
// For this, we have to determine where the first file begins
if(nError == ERROR_SUCCESS)
{
LARGE_INTEGER FirstFilePos;
LARGE_INTEGER TempPos;
TMPQBlockEx * pBlockEx = ha->pExtBlockTable;
TMPQBlock * pBlockEnd = ha->pBlockTable + ha->pHeader->dwBlockTableSize;
TMPQBlock * pBlock = ha->pBlockTable;
// Maximum file position
FirstFilePos.HighPart = 0x7FFFFFFF;
FirstFilePos.LowPart = 0xFFFFFFFF;
// Find the block with the least position in the MPQ
while(pBlock < pBlockEnd)
{
TempPos.HighPart = pBlockEx->wFilePosHigh;
TempPos.LowPart = pBlock->dwFilePos;
if(TempPos.QuadPart < FirstFilePos.QuadPart)
FirstFilePos = TempPos;
pBlockEx++;
pBlock++;
}
// Set the position in the source file right after the file header
TempPos.QuadPart = ha->MpqPos.QuadPart + ha->pHeader->dwHeaderSize;
SetFilePointer(ha->hFile, TempPos.LowPart, &TempPos.HighPart, FILE_BEGIN);
// Get the number of bytes to copy
FirstFilePos.QuadPart -= ha->pHeader->dwHeaderSize;
nError = CopyNonMpqData(ha->hFile, hFile, FirstFilePos);
}
// Now write all file blocks.
if(nError == ERROR_SUCCESS)
nError = CopyMpqFiles(hFile, ha, pFileSeeds);
// Now we need to update the tables positions
// (but only if the tables are at the end of the file)
if(nError == ERROR_SUCCESS)
{
LARGE_INTEGER RelativePos;
LARGE_INTEGER FilePos = {0};
// Set the hash table position
FilePos.LowPart = SetFilePointer(hFile, 0, &FilePos.HighPart, FILE_CURRENT);
RelativePos.QuadPart = FilePos.QuadPart - ha->MpqPos.QuadPart;
ha->pHeader->wHashTablePosHigh = (USHORT)RelativePos.HighPart;
ha->pHeader->dwHashTablePos = RelativePos.LowPart;
ha->HashTablePos = FilePos;
// Set the block table position
RelativePos.QuadPart += ha->pHeader->dwHashTableSize * sizeof(TMPQHash);
FilePos.QuadPart += ha->pHeader->dwHashTableSize * sizeof(TMPQHash);
ha->pHeader->wBlockTablePosHigh = (USHORT)RelativePos.HighPart;
ha->pHeader->dwBlockTablePos = RelativePos.LowPart;
ha->BlockTablePos = FilePos;
// Set the extended block table position
RelativePos.QuadPart += ha->pHeader->dwBlockTableSize * sizeof(TMPQBlock);
FilePos.QuadPart += ha->pHeader->dwBlockTableSize * sizeof(TMPQBlock);
if(ha->ExtBlockTablePos.QuadPart != 0)
{
ha->pHeader->ExtBlockTablePos = RelativePos;
ha->ExtBlockTablePos = FilePos;
RelativePos.QuadPart += ha->pHeader->dwBlockTableSize * sizeof(TMPQBlockEx);
FilePos.QuadPart += ha->pHeader->dwBlockTableSize * sizeof(TMPQBlockEx);
}
// Set the archive size
ha->pHeader->dwArchiveSize = RelativePos.LowPart;
ha->MpqSize = RelativePos;
}
// If succeeded, update the tables in the file
if(nError == ERROR_SUCCESS)
{
CloseHandle(ha->hFile);
ha->FilePointer.QuadPart = 0;
ha->hFile = hFile;
hFile = INVALID_HANDLE_VALUE;
nError = SaveMPQTables(ha);
}
// If all succeeded, switch the archives
if(nError == ERROR_SUCCESS)
{
if(CompactCB != NULL)
CompactCB(lpUserData, CCB_CLOSING_ARCHIVE, 0, 0);
if(!DeleteFile(ha->szFileName) || // Delete the old archive
!CloseHandle(ha->hFile) || // Close the new archive
!MoveFile(szTempFile, ha->szFileName)) // Rename the temporary archive
nError = GetLastError();
}
// Now open the freshly renamed archive file
if(nError == ERROR_SUCCESS)
{
ha->hFile = CreateFile(ha->szFileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if(ha->hFile == INVALID_HANDLE_VALUE)
nError = GetLastError();
}
// Invalidate the positions of the archive
if(nError == ERROR_SUCCESS)
{
ha->FilePointer.QuadPart = 0;
ha->pLastFile = NULL;
ha->dwBlockPos = 0;
ha->dwBuffPos = 0;
}
// Cleanup and return
if(hFile != INVALID_HANDLE_VALUE)
CloseHandle(hFile);
if(pFileSeeds != NULL)
FREEMEM(pFileSeeds);
if(nError != ERROR_SUCCESS)
SetLastError(nError);
DeleteFile(szTempFile);
CompactCB = NULL;
return (nError == ERROR_SUCCESS);
}
@@ -1,530 +0,0 @@
/*****************************************************************************/
/* SFileCreateArchiveEx.cpp Copyright (c) Ladislav Zezula 2003 */
/*---------------------------------------------------------------------------*/
/* MPQ Editing functions */
/*---------------------------------------------------------------------------*/
/* Date Ver Who Comment */
/* -------- ---- --- ------- */
/* 24.03.03 1.00 Lad Splitted from SFileOpenArchive.cpp */
/*****************************************************************************/
#define __STORMLIB_SELF__
#include "StormLib.h"
#include "SCommon.h"
//-----------------------------------------------------------------------------
// Defines
#define DEFAULT_BLOCK_SIZE 3 // Default size of the block
//-----------------------------------------------------------------------------
// Local tables
static DWORD PowersOfTwo[] =
{
0x0000002, 0x0000004, 0x0000008,
0x0000010, 0x0000020, 0x0000040, 0x0000080,
0x0000100, 0x0000200, 0x0000400, 0x0000800,
0x0001000, 0x0002000, 0x0004000, 0x0008000,
0x0010000, 0x0020000, 0x0040000, 0x0080000,
0x0000000
};
/*****************************************************************************/
/* Public functions */
/*****************************************************************************/
//-----------------------------------------------------------------------------
// Opens or creates a (new) MPQ archive.
//
// szMpqName - Name of the archive to be created.
//
// dwCreationDisposition:
//
// Value Archive exists Archive doesn't exist
// ---------- --------------------- ---------------------
// CREATE_NEW Fails Creates new archive
// CREATE_ALWAYS Overwrites existing Creates new archive
// OPEN_EXISTING Opens the archive Fails
// OPEN_ALWAYS Opens the archive Creates new archive
//
// The above mentioned values can be combined with the following flags:
//
// MPQ_CREATE_ARCHIVE_V1 - Creates MPQ archive version 1
// MPQ_CREATE_ARCHIVE_V2 - Creates MPQ archive version 2
//
// dwHashTableSize - Size of the hash table (only if creating a new archive).
// Must be between 2^4 (= 16) and 2^18 (= 262 144)
//
// phMpq - Receives handle to the archive
//
// TODO: Test for archives > 4GB
BOOL WINAPI SFileCreateArchiveEx(const char * szMpqName, DWORD dwCreationDisposition, DWORD dwHashTableSize, HANDLE * phMPQ)
{
LARGE_INTEGER MpqPos = {0}; // Position of MPQ header in the file
TMPQArchive * ha = NULL; // MPQ archive handle
HANDLE hFile = INVALID_HANDLE_VALUE; // File handle
DWORD dwTransferred = 0; // Number of bytes written into the archive
USHORT wFormatVersion;
BOOL bFileExists = FALSE;
int nIndex = 0;
int nError = ERROR_SUCCESS;
// Pre-initialize the result value
if(phMPQ != NULL)
*phMPQ = NULL;
// Check the parameters, if they are valid
if(szMpqName == NULL || *szMpqName == 0 || phMPQ == NULL)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
// Check the value of dwCreationDisposition against file existence
bFileExists = (GetFileAttributes(szMpqName) != 0xFFFFFFFF);
// Extract format version from the "dwCreationDisposition"
wFormatVersion = (USHORT)(dwCreationDisposition >> 0x10);
dwCreationDisposition &= 0x0000FFFF;
// If the file exists and open required, do it.
if(bFileExists && (dwCreationDisposition == OPEN_EXISTING || dwCreationDisposition == OPEN_ALWAYS))
{
// Try to open the archive normal way. If it fails, it means that
// the file exist, but it is not a MPQ archive.
if(SFileOpenArchiveEx(szMpqName, 0, 0, phMPQ, GENERIC_READ | GENERIC_WRITE))
return TRUE;
}
// Two error cases
if(dwCreationDisposition == CREATE_NEW && bFileExists)
{
SetLastError(ERROR_ALREADY_EXISTS);
return FALSE;
}
if(dwCreationDisposition == OPEN_EXISTING && bFileExists == FALSE)
{
SetLastError(ERROR_FILE_NOT_FOUND);
return FALSE;
}
// At this point, we have to create the archive. If the file exists,
// we will convert it to MPQ archive.
// Check the value of hash table size. It has to be a power of two
// and must be between HASH_TABLE_SIZE_MIN and HASH_TABLE_SIZE_MAX
if(dwHashTableSize < HASH_TABLE_SIZE_MIN)
dwHashTableSize = HASH_TABLE_SIZE_MIN;
if(dwHashTableSize > HASH_TABLE_SIZE_MAX)
dwHashTableSize = HASH_TABLE_SIZE_MAX;
// Round the hash table size up to the nearest power of two
for(nIndex = 0; PowersOfTwo[nIndex] != 0; nIndex++)
{
if(dwHashTableSize <= PowersOfTwo[nIndex])
{
dwHashTableSize = PowersOfTwo[nIndex];
break;
}
}
// Prepare the buffer for decryption engine
if(nError == ERROR_SUCCESS)
nError = PrepareStormBuffer();
// Get the position where the MPQ header will begin.
if(nError == ERROR_SUCCESS)
{
hFile = CreateFile(szMpqName,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
dwCreationDisposition,
0,
NULL);
if(hFile == INVALID_HANDLE_VALUE)
nError = GetLastError();
}
// Retrieve the file size and round it up to 0x200 bytes
if(nError == ERROR_SUCCESS)
{
MpqPos.LowPart = GetFileSize(hFile, (LPDWORD)&MpqPos.HighPart);
MpqPos.QuadPart += 0x1FF;
MpqPos.LowPart &= 0xFFFFFE00;
if(wFormatVersion == MPQ_FORMAT_VERSION_1 && MpqPos.HighPart != 0)
nError = ERROR_DISK_FULL;
if(wFormatVersion == MPQ_FORMAT_VERSION_2 && MpqPos.HighPart > 0x0000FFFF)
nError = ERROR_DISK_FULL;
}
// Move to the end of the file (i.e. begin of the MPQ)
if(nError == ERROR_SUCCESS)
{
if(SetFilePointer(hFile, MpqPos.LowPart, &MpqPos.HighPart, FILE_BEGIN) == 0xFFFFFFFF)
nError = GetLastError();
}
// Set the new end of the file to the MPQ header position
if(nError == ERROR_SUCCESS)
{
if(!SetEndOfFile(hFile))
nError = GetLastError();
}
// Create the archive handle
if(nError == ERROR_SUCCESS)
{
if((ha = ALLOCMEM(TMPQArchive, 1)) == NULL)
nError = ERROR_NOT_ENOUGH_MEMORY;
}
// Fill the MPQ archive handle structure and create the header,
// block buffer, hash table and block table
if(nError == ERROR_SUCCESS)
{
memset(ha, 0, sizeof(TMPQArchive));
strcpy(ha->szFileName, szMpqName);
ha->hFile = hFile;
ha->dwBlockSize = 0x200 << DEFAULT_BLOCK_SIZE;
ha->MpqPos = MpqPos;
ha->FilePointer = MpqPos;
ha->pHeader = &ha->Header;
ha->pHashTable = ALLOCMEM(TMPQHash, dwHashTableSize);
ha->pBlockTable = ALLOCMEM(TMPQBlock, dwHashTableSize);
ha->pExtBlockTable = ALLOCMEM(TMPQBlockEx, dwHashTableSize);
ha->pbBlockBuffer = ALLOCMEM(BYTE, ha->dwBlockSize);
ha->pListFile = NULL;
ha->dwFlags |= MPQ_FLAG_CHANGED;
if(!ha->pHashTable || !ha->pBlockTable || !ha->pExtBlockTable || !ha->pbBlockBuffer)
nError = GetLastError();
hFile = INVALID_HANDLE_VALUE;
}
// Fill the MPQ header and all buffers
if(nError == ERROR_SUCCESS)
{
LARGE_INTEGER TempPos;
TMPQHeader2 * pHeader = ha->pHeader;
DWORD dwHeaderSize = (wFormatVersion == MPQ_FORMAT_VERSION_2) ? sizeof(TMPQHeader2) : sizeof(TMPQHeader);
memset(pHeader, 0, sizeof(TMPQHeader2));
pHeader->dwID = ID_MPQ;
pHeader->dwHeaderSize = dwHeaderSize;
pHeader->dwArchiveSize = pHeader->dwHeaderSize + dwHashTableSize * sizeof(TMPQHash);
pHeader->wFormatVersion = wFormatVersion;
pHeader->wBlockSize = 3; // 0x1000 bytes per block
pHeader->dwHashTableSize = dwHashTableSize;
// Set proper hash table positions
ha->HashTablePos.QuadPart = ha->MpqPos.QuadPart + pHeader->dwHeaderSize;
ha->pHeader->dwHashTablePos = pHeader->dwHeaderSize;
ha->pHeader->wHashTablePosHigh = 0;
// Set proper block table positions
ha->BlockTablePos.QuadPart = ha->HashTablePos.QuadPart +
(ha->pHeader->dwHashTableSize * sizeof(TMPQHash));
TempPos.QuadPart = ha->BlockTablePos.QuadPart - ha->MpqPos.QuadPart;
ha->pHeader->dwBlockTablePos = TempPos.LowPart;
ha->pHeader->wBlockTablePosHigh = (USHORT)TempPos.HighPart;
// For now, we set extended block table positioon top zero unless we add enough
// files to cause the archive size exceed 4 GB
ha->ExtBlockTablePos.QuadPart = 0;
// Clear all tables
memset(ha->pBlockTable, 0, sizeof(TMPQBlock) * dwHashTableSize);
memset(ha->pExtBlockTable, 0, sizeof(TMPQBlockEx) * dwHashTableSize);
memset(ha->pHashTable, 0xFF, sizeof(TMPQHash) * dwHashTableSize);
}
// Write the MPQ header to the file
if(nError == ERROR_SUCCESS)
{
DWORD dwHeaderSize = ha->pHeader->dwHeaderSize;
BSWAP_TMPQHEADER(ha->pHeader);
WriteFile(ha->hFile, ha->pHeader, dwHeaderSize, &dwTransferred, NULL);
BSWAP_TMPQHEADER(ha->pHeader);
if(dwTransferred != ha->pHeader->dwHeaderSize)
nError = ERROR_DISK_FULL;
ha->FilePointer.QuadPart = ha->MpqPos.QuadPart + dwTransferred;
ha->MpqSize.QuadPart += dwTransferred;
}
// Create the internal listfile
if(nError == ERROR_SUCCESS)
nError = SListFileCreateListFile(ha);
// Try to add the internal listfile
if(nError == ERROR_SUCCESS)
SFileAddListFile((HANDLE)ha, NULL);
// Cleanup : If an error, delete all buffers and return
if(nError != ERROR_SUCCESS)
{
FreeMPQArchive(ha);
if(hFile != INVALID_HANDLE_VALUE)
CloseHandle(hFile);
SetLastError(nError);
}
// Return the values
*phMPQ = (HANDLE)ha;
return (nError == ERROR_SUCCESS);
}
//-----------------------------------------------------------------------------
// Changes locale ID of a file
// TODO: Test for archives > 4GB
BOOL WINAPI SFileSetFileLocale(HANDLE hFile, LCID lcNewLocale)
{
TMPQFile * hf = (TMPQFile *)hFile;
// Invalid handle => do nothing
if(IsValidFileHandle(hf) == FALSE || IsValidMpqHandle(hf->ha) == FALSE)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
// If the file has not been open for writing, do nothing.
if(hf->ha->pListFile == NULL)
return ERROR_ACCESS_DENIED;
hf->pHash->lcLocale = (USHORT)lcNewLocale;
hf->ha->dwFlags |= MPQ_FLAG_CHANGED;
return TRUE;
}
//-----------------------------------------------------------------------------
// Adds a file into the archive
// TODO: Test for archives > 4GB
BOOL WINAPI SFileAddFileEx(HANDLE hMPQ, const char * szFileName, const char * szArchivedName, DWORD dwFlags, DWORD dwQuality, int nFileType)
{
TMPQArchive * ha = (TMPQArchive *)hMPQ;
HANDLE hFile = INVALID_HANDLE_VALUE;
BOOL bReplaced = FALSE; // TRUE if replacing file in the archive
int nError = ERROR_SUCCESS;
if(nError == ERROR_SUCCESS)
{
// Check valid parameters
if(IsValidMpqHandle(ha) == FALSE || szFileName == NULL || *szFileName == 0 || szArchivedName == NULL || *szArchivedName == 0)
nError = ERROR_INVALID_PARAMETER;
// Check the values of dwFlags
if((dwFlags & MPQ_FILE_COMPRESS_PKWARE) && (dwFlags & MPQ_FILE_COMPRESS_MULTI))
nError = ERROR_INVALID_PARAMETER;
}
// If anyone is trying to add listfile, and the archive already has a listfile,
// deny the operation, but return success.
if(nError == ERROR_SUCCESS)
{
if(ha->pListFile != NULL && !_stricmp(szFileName, LISTFILE_NAME))
return ERROR_SUCCESS;
}
// Open added file
if(nError == ERROR_SUCCESS)
{
hFile = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, NULL);
if(hFile == INVALID_HANDLE_VALUE)
nError = GetLastError();
}
if(nError == ERROR_SUCCESS)
nError = AddFileToArchive(ha, hFile, szArchivedName, dwFlags, dwQuality, nFileType, &bReplaced);
// Add the file into listfile also
if(nError == ERROR_SUCCESS && bReplaced == FALSE)
nError = SListFileAddNode(ha, szArchivedName);
// Cleanup and exit
if(hFile != INVALID_HANDLE_VALUE)
CloseHandle(hFile);
if(nError != ERROR_SUCCESS)
SetLastError(nError);
return (nError == ERROR_SUCCESS);
}
// Adds a data file into the archive
// TODO: Test for archives > 4GB
BOOL WINAPI SFileAddFile(HANDLE hMPQ, const char * szFileName, const char * szArchivedName, DWORD dwFlags)
{
return SFileAddFileEx(hMPQ, szFileName, szArchivedName, dwFlags, 0, SFILE_TYPE_DATA);
}
// Adds a WAVE file into the archive
// TODO: Test for archives > 4GB
BOOL WINAPI SFileAddWave(HANDLE hMPQ, const char * szFileName, const char * szArchivedName, DWORD dwFlags, DWORD dwQuality)
{
return SFileAddFileEx(hMPQ, szFileName, szArchivedName, dwFlags, dwQuality, SFILE_TYPE_WAVE);
}
//-----------------------------------------------------------------------------
// BOOL SFileRemoveFile(HANDLE hMPQ, char * szFileName)
//
// This function removes a file from the archive. The file content
// remains there, only the entries in the hash table and in the block
// table are updated.
// TODO: Test for archives > 4GB
BOOL WINAPI SFileRemoveFile(HANDLE hMPQ, const char * szFileName, DWORD dwSearchScope)
{
TMPQArchive * ha = (TMPQArchive *)hMPQ;
TMPQBlockEx * pBlockEx = NULL; // Block entry of deleted file
TMPQBlock * pBlock = NULL; // Block entry of deleted file
TMPQHash * pHash = NULL; // Hash entry of deleted file
DWORD dwBlockIndex = 0;
int nError = ERROR_SUCCESS;
// Check the parameters
if(nError == ERROR_SUCCESS)
{
if(IsValidMpqHandle(ha) == FALSE)
nError = ERROR_INVALID_PARAMETER;
if(dwSearchScope != SFILE_OPEN_BY_INDEX && *szFileName == 0)
nError = ERROR_INVALID_PARAMETER;
}
// Do not allow to remove listfile
if(nError == ERROR_SUCCESS)
{
if(dwSearchScope != SFILE_OPEN_BY_INDEX && !_stricmp(szFileName, LISTFILE_NAME))
nError = ERROR_ACCESS_DENIED;
}
// Get hash entry belonging to this file
if(nError == ERROR_SUCCESS)
{
if((pHash = GetHashEntryEx(ha, (char *)szFileName, lcLocale)) == NULL)
nError = ERROR_FILE_NOT_FOUND;
}
// If index was not found, or is greater than number of files, exit.
if(nError == ERROR_SUCCESS)
{
if((dwBlockIndex = pHash->dwBlockIndex) > ha->pHeader->dwBlockTableSize)
nError = ERROR_FILE_NOT_FOUND;
}
// Get block and test if the file is not already deleted
if(nError == ERROR_SUCCESS)
{
pBlockEx = ha->pExtBlockTable + dwBlockIndex;
pBlock = ha->pBlockTable + dwBlockIndex;
if((pBlock->dwFlags & MPQ_FILE_EXISTS) == 0)
nError = ERROR_FILE_NOT_FOUND;
}
// Now invalidate the block entry and the hash entry. Do not make any
// relocations and file copying, use SFileCompactArchive for it.
if(nError == ERROR_SUCCESS)
{
pBlockEx->wFilePosHigh = 0;
pBlock->dwFilePos = 0;
pBlock->dwFSize = 0;
pBlock->dwCSize = 0;
pBlock->dwFlags = 0;
pHash->dwName1 = 0xFFFFFFFF;
pHash->dwName2 = 0xFFFFFFFF;
pHash->lcLocale = 0xFFFF;
pHash->wPlatform = 0xFFFF;
pHash->dwBlockIndex = HASH_ENTRY_DELETED;
// Update MPQ archive
ha->dwFlags |= MPQ_FLAG_CHANGED;
}
// Remove the file from the list file
if(nError == ERROR_SUCCESS && lcLocale == LANG_NEUTRAL)
nError = SListFileRemoveNode(ha, szFileName);
// Resolve error and exit
if(nError != ERROR_SUCCESS)
SetLastError(nError);
return (nError == ERROR_SUCCESS);
}
// Renames the file within the archive.
// TODO: Test for archives > 4GB
BOOL WINAPI SFileRenameFile(HANDLE hMPQ, const char * szFileName, const char * szNewFileName)
{
TMPQArchive * ha = (TMPQArchive *)hMPQ;
TMPQHash * pOldHash = NULL; // Hash entry for the original file
TMPQHash * pNewHash = NULL; // Hash entry for the renamed file
DWORD dwBlockIndex = 0;
int nError = ERROR_SUCCESS;
// Test the valid parameters
if(nError == ERROR_SUCCESS)
{
if(hMPQ == NULL || szNewFileName == NULL || *szNewFileName == 0)
nError = ERROR_INVALID_PARAMETER;
if(szFileName == NULL || *szFileName == 0)
nError = ERROR_INVALID_PARAMETER;
}
// Do not allow to rename listfile
if(nError == ERROR_SUCCESS)
{
if(!_stricmp(szFileName, LISTFILE_NAME))
nError = ERROR_ACCESS_DENIED;
}
// Test if the file already exists in the archive
if(nError == ERROR_SUCCESS)
{
if((pNewHash = GetHashEntryEx(ha, szNewFileName, lcLocale)) != NULL)
nError = ERROR_ALREADY_EXISTS;
}
// Get the hash table entry for the original file
if(nError == ERROR_SUCCESS)
{
if((pOldHash = GetHashEntryEx(ha, szFileName, lcLocale)) == NULL)
nError = ERROR_FILE_NOT_FOUND;
}
// Get the hash table entry for the renamed file
if(nError == ERROR_SUCCESS)
{
// Save block table index and remove the hash table entry
dwBlockIndex = pOldHash->dwBlockIndex;
pOldHash->dwName1 = 0xFFFFFFFF;
pOldHash->dwName2 = 0xFFFFFFFF;
pOldHash->lcLocale = 0xFFFF;
pOldHash->wPlatform = 0xFFFF;
pOldHash->dwBlockIndex = HASH_ENTRY_DELETED;
if((pNewHash = FindFreeHashEntry(ha, szNewFileName)) == NULL)
nError = ERROR_CAN_NOT_COMPLETE;
}
// Save the block index and clear the hash entry
if(nError == ERROR_SUCCESS)
{
// Copy the block table index
pNewHash->dwBlockIndex = dwBlockIndex;
ha->dwFlags |= MPQ_FLAG_CHANGED;
}
// Rename the file in the list file
if(nError == ERROR_SUCCESS)
nError = SListFileRenameNode(ha, szFileName, szNewFileName);
// Resolve error and return
if(nError != ERROR_SUCCESS)
SetLastError(nError);
return (nError == ERROR_SUCCESS);
}
@@ -1,63 +0,0 @@
/*****************************************************************************/
/* SFileExtractFile.cpp Copyright (c) Ladislav Zezula 2003 */
/*---------------------------------------------------------------------------*/
/* Simple extracting utility */
/*---------------------------------------------------------------------------*/
/* Date Ver Who Comment */
/* -------- ---- --- ------- */
/* 20.06.03 1.00 Lad The first version of SFileExtractFile.cpp */
/*****************************************************************************/
#define __STORMLIB_SELF__
#include "StormLib.h"
#include "SCommon.h"
// TODO: Test for archives > 4GB
BOOL WINAPI SFileExtractFile(HANDLE hMpq, const char * szToExtract, const char * szExtracted)
{
HANDLE hLocalFile = INVALID_HANDLE_VALUE;
HANDLE hMpqFile = NULL;
int nError = ERROR_SUCCESS;
// Create the local file
if(nError == ERROR_SUCCESS)
{
hLocalFile = CreateFile(szExtracted, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL);
if(hLocalFile == INVALID_HANDLE_VALUE)
nError = GetLastError();
}
// Open the MPQ file
if(nError == ERROR_SUCCESS)
{
if(!SFileOpenFileEx(hMpq, szToExtract, 0, &hMpqFile))
nError = GetLastError();
}
// Copy the file's content
if(nError == ERROR_SUCCESS)
{
char szBuffer[0x1000];
DWORD dwTransferred = 1;
while(dwTransferred > 0)
{
SFileReadFile(hMpqFile, szBuffer, sizeof(szBuffer), &dwTransferred, NULL);
if(dwTransferred == 0)
break;
WriteFile(hLocalFile, szBuffer, dwTransferred, &dwTransferred, NULL);
if(dwTransferred == 0)
break;
}
}
// Close the files
if(hMpqFile != NULL)
SFileCloseFile(hMpqFile);
if(hLocalFile != INVALID_HANDLE_VALUE)
CloseHandle(hLocalFile);
if(nError != ERROR_SUCCESS)
SetLastError(nError);
return (BOOL)(nError == ERROR_SUCCESS);
}
@@ -1,291 +0,0 @@
/*****************************************************************************/
/* SFileFindFile.cpp Copyright (c) Ladislav Zezula 2003 */
/*---------------------------------------------------------------------------*/
/* A module for file searching within MPQs */
/*---------------------------------------------------------------------------*/
/* Date Ver Who Comment */
/* -------- ---- --- ------- */
/* 25.03.03 1.00 Lad The first version of SFileFindFile.cpp */
/*****************************************************************************/
#define __STORMLIB_SELF__
#include "StormLib.h"
#include "SCommon.h"
//-----------------------------------------------------------------------------
// Defines
#define LISTFILE_CACHE_SIZE 0x1000
//-----------------------------------------------------------------------------
// Local functions
static BOOL IsValidSearchHandle(TMPQSearch * hs)
{
if(hs == NULL || IsBadReadPtr(hs, sizeof(TMPQSearch)))
return FALSE;
if(!IsValidMpqHandle(hs->ha))
return FALSE;
return TRUE;
}
// This function compares a string with a wildcard search string.
// returns TRUE, when the string matches with the wildcard.
BOOL CheckWildCard(const char * szString, const char * szWildCard)
{
char * szTemp; // Temporary helper pointer
int nResult = 0; // For memcmp return values
int nMustNotMatch = 0; // Number of following chars int szString,
// which must not match with szWildCard
int nMustMatch = 0; // Number of the following characters,
// which must match
// When the string is empty, it does not match with every wildcard
if(*szString == 0)
return FALSE;
// When the mask is empty, it matches to every wildcard
if(szWildCard == NULL || *szWildCard == 0)
return FALSE;
// Do normal test
for(;;)
{
switch(*szWildCard)
{
case '*': // Means "every number of characters"
// Skip all asterisks
while(*szWildCard == '*')
szWildCard++;
// When no more characters in wildcard, it means that the strings match
if(*szWildCard == 0)
return TRUE;
// The next N characters must not agree
nMustNotMatch |= 0x70000000;
break;
case '?': // Means "One or no character"
while(*szWildCard == '?')
{
nMustNotMatch++;
szWildCard++;
}
break;
default:
// If the two characters match
if(toupper(*szString) == toupper(*szWildCard))
{
// When end of string, they agree
if(*szString == 0)
return TRUE;
nMustNotMatch = 0;
szWildCard++;
szString++;
break;
}
// If the next character must match, the string does not match
if(nMustNotMatch == 0)
return FALSE;
// Count the characters which must match after characters
// that must not match
szTemp = (char *)szWildCard;
nMustMatch = 0;
while(*szTemp != 0 && *szTemp != '*' && *szTemp != '?')
{
nMustMatch++;
szTemp++;
}
// Now skip characters from szString up to number of chars
// that must not match
nResult = -1;
while(nMustNotMatch > 0 && *szString != 0)
{
if((nResult = _strnicmp(szString, szWildCard, nMustMatch)) == 0)
break;
szString++;
nMustNotMatch--;
}
// Make one more comparison
if(nMustNotMatch == 0)
nResult = _strnicmp(szString, szWildCard, nMustMatch);
// If a match has been found, continue the search
if(nResult == 0)
{
nMustNotMatch = 0;
szWildCard += nMustMatch;
szString += nMustMatch;
break;
}
return FALSE;
}
}
}
// Performs one MPQ search
// TODO: Test for archives > 4GB
static int DoMPQSearch(TMPQSearch * hs, SFILE_FIND_DATA * lpFindFileData)
{
TMPQArchive * ha = hs->ha;
TFileNode * pNode;
TMPQHash * pHashEnd = ha->pHashTable + ha->pHeader->dwHashTableSize;
TMPQHash * pHash = ha->pHashTable + hs->dwNextIndex;
// Do until some file found or no more files
while(pHash < pHashEnd)
{
pNode = ha->pListFile[hs->dwNextIndex++];
// If this entry is free, do nothing
if(pHash->dwBlockIndex < HASH_ENTRY_FREE && (DWORD_PTR)pNode < HASH_ENTRY_FREE)
{
// Check the file name.
if(CheckWildCard(pNode->szFileName, hs->szSearchMask))
{
TMPQBlock * pBlock = ha->pBlockTable + pHash->dwBlockIndex;
lpFindFileData->lcLocale = pHash->lcLocale;
lpFindFileData->dwFileSize = pBlock->dwFSize;
lpFindFileData->dwFileFlags = pBlock->dwFlags;
lpFindFileData->dwBlockIndex = pHash->dwBlockIndex;
lpFindFileData->dwCompSize = pBlock->dwCSize;
// Fill the file name and plain file name
strcpy(lpFindFileData->cFileName, pNode->szFileName);
lpFindFileData->szPlainName = strrchr(lpFindFileData->cFileName, '\\');
if(lpFindFileData->szPlainName == NULL)
lpFindFileData->szPlainName = lpFindFileData->cFileName;
else
lpFindFileData->szPlainName++;
// Fill the next entry
return ERROR_SUCCESS;
}
}
pHash++;
}
// No more files found, return error
return ERROR_NO_MORE_FILES;
}
// TODO: Test for archives > 4GB
static void FreeMPQSearch(TMPQSearch *& hs)
{
if(hs != NULL)
{
FREEMEM(hs);
hs = NULL;
}
}
//-----------------------------------------------------------------------------
// Public functions
// TODO: Test for archives > 4GB
HANDLE WINAPI SFileFindFirstFile(HANDLE hMPQ, const char * szMask, SFILE_FIND_DATA * lpFindFileData, const char * szListFile)
{
TMPQArchive * ha = (TMPQArchive *)hMPQ;
TMPQSearch * hs = NULL; // Search object handle
size_t nSize = 0;
int nError = ERROR_SUCCESS;
// Check for the valid parameters
if(nError == ERROR_SUCCESS)
{
if(!IsValidMpqHandle(ha))
nError = ERROR_INVALID_PARAMETER;
if(szMask == NULL || lpFindFileData == NULL)
nError = ERROR_INVALID_PARAMETER;
if(szListFile == NULL && !IsValidMpqHandle(ha))
nError = ERROR_INVALID_PARAMETER;
}
// Include the listfile into the MPQ's internal listfile
// Note that if the listfile name is NULL, do nothing because the
// internal listfile is always included.
if(nError == ERROR_SUCCESS && szListFile != NULL)
nError = SFileAddListFile((HANDLE)ha, szListFile);
// Allocate the structure for MPQ search
if(nError == ERROR_SUCCESS)
{
nSize = sizeof(TMPQSearch) + strlen(szMask) + 1;
if((hs = (TMPQSearch *)ALLOCMEM(char, nSize)) == NULL)
nError = ERROR_NOT_ENOUGH_MEMORY;
}
// Perform the first search
if(nError == ERROR_SUCCESS)
{
memset(hs, 0, sizeof(TMPQSearch));
hs->ha = ha;
hs->dwNextIndex = 0;
strcpy(hs->szSearchMask, szMask);
nError = DoMPQSearch(hs, lpFindFileData);
}
// Cleanup
if(nError != ERROR_SUCCESS)
{
FreeMPQSearch(hs);
SetLastError(nError);
}
// Return the result value
return (HANDLE)hs;
}
// TODO: Test for archives > 4GB
BOOL WINAPI SFileFindNextFile(HANDLE hFind, SFILE_FIND_DATA * lpFindFileData)
{
TMPQSearch * hs = (TMPQSearch *)hFind;
int nError = ERROR_SUCCESS;
// Check the parameters
if(nError == ERROR_SUCCESS)
{
if(!IsValidSearchHandle(hs) || lpFindFileData == NULL)
nError = ERROR_INVALID_PARAMETER;
}
if(nError == ERROR_SUCCESS)
nError = DoMPQSearch(hs, lpFindFileData);
if(nError != ERROR_SUCCESS)
{
SetLastError(nError);
return FALSE;
}
return TRUE;
}
// TODO: Test for archives > 4GB
BOOL WINAPI SFileFindClose(HANDLE hFind)
{
TMPQSearch * hs = (TMPQSearch *)hFind;
// Check the parameters
if(!IsValidSearchHandle(hs))
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
FreeMPQSearch(hs);
return TRUE;
}
@@ -1,497 +0,0 @@
/*****************************************************************************/
/* SFileOpenArchive.cpp Copyright Ladislav Zezula 1999 */
/* */
/* Author : Ladislav Zezula */
/* E-mail : [email protected] */
/* WWW : www.zezula.net */
/*---------------------------------------------------------------------------*/
/* Archive functions of Storm.dll */
/*---------------------------------------------------------------------------*/
/* Date Ver Who Comment */
/* -------- ---- --- ------- */
/* xx.xx.xx 1.00 Lad The first version of SFileOpenArchive.cpp */
/* 19.11.03 1.01 Dan Big endian handling */
/*****************************************************************************/
#define __STORMLIB_SELF__
#include "StormLib.h"
#include "SCommon.h"
/*****************************************************************************/
/* Local functions */
/*****************************************************************************/
static BOOL IsAviFile(TMPQHeader * pHeader)
{
DWORD * AviHdr = (DWORD *)pHeader;
// Test for 'RIFF', 'AVI ' or 'LIST'
return (AviHdr[0] == 'FFIR' && AviHdr[2] == ' IVA' && AviHdr[3] == 'TSIL');
}
// This function gets the right positions of the hash table and the block table.
// TODO: Test for archives > 4GB
static int RelocateMpqTablePositions(TMPQArchive * ha)
{
TMPQHeader2 * pHeader = ha->pHeader;
LARGE_INTEGER FileSize;
LARGE_INTEGER TempSize;
// Get the size of the file
FileSize.LowPart = GetFileSize(ha->hFile, (LPDWORD)&FileSize.HighPart);
// Set the proper hash table position
ha->HashTablePos.HighPart = pHeader->wHashTablePosHigh;
ha->HashTablePos.LowPart = pHeader->dwHashTablePos;
ha->HashTablePos.QuadPart += ha->MpqPos.QuadPart;
if(ha->HashTablePos.QuadPart > FileSize.QuadPart)
return ERROR_BAD_FORMAT;
// Set the proper block table position
ha->BlockTablePos.HighPart = pHeader->wBlockTablePosHigh;
ha->BlockTablePos.LowPart = pHeader->dwBlockTablePos;
ha->BlockTablePos.QuadPart += ha->MpqPos.QuadPart;
if(ha->BlockTablePos.QuadPart > FileSize.QuadPart)
return ERROR_BAD_FORMAT;
// Set the proper position of the extended block table
if(pHeader->ExtBlockTablePos.QuadPart != 0)
{
ha->ExtBlockTablePos = pHeader->ExtBlockTablePos;
ha->ExtBlockTablePos.QuadPart += ha->MpqPos.QuadPart;
if(ha->ExtBlockTablePos.QuadPart > FileSize.QuadPart)
return ERROR_BAD_FORMAT;
}
// Size of MPQ archive is computed as the biggest of
// (EndOfBlockTable, EndOfHashTable, EndOfExtBlockTable)
TempSize.QuadPart = ha->HashTablePos.QuadPart + (pHeader->dwHashTableSize * sizeof(TMPQHash));
if(TempSize.QuadPart > ha->MpqSize.QuadPart)
ha->MpqSize = TempSize;
TempSize.QuadPart = ha->BlockTablePos.QuadPart + (pHeader->dwBlockTableSize * sizeof(TMPQBlock));
if(TempSize.QuadPart > ha->MpqSize.QuadPart)
ha->MpqSize = TempSize;
TempSize.QuadPart = ha->ExtBlockTablePos.QuadPart + (pHeader->dwBlockTableSize * sizeof(TMPQBlockEx));
if(TempSize.QuadPart > ha->MpqSize.QuadPart)
ha->MpqSize = TempSize;
// MPQ size does not include the bytes before MPQ header
ha->MpqSize.QuadPart -= ha->MpqPos.QuadPart;
return ERROR_SUCCESS;
}
/*****************************************************************************/
/* Public functions */
/*****************************************************************************/
//-----------------------------------------------------------------------------
// SFileGetLocale and SFileSetLocale
// Set the locale for all neewly opened archives and files
LCID WINAPI SFileGetLocale()
{
return lcLocale;
}
LCID WINAPI SFileSetLocale(LCID lcNewLocale)
{
lcLocale = lcNewLocale;
return lcLocale;
}
//-----------------------------------------------------------------------------
// SFileOpenArchiveEx (not a public function !!!)
//
// szFileName - MPQ archive file name to open
// dwPriority - When SFileOpenFileEx called, this contains the search priority for searched archives
// dwFlags - If contains MPQ_OPEN_NO_LISTFILE, then the internal list file will not be used.
// phMPQ - Pointer to store open archive handle
BOOL SFileOpenArchiveEx(
const char * szMpqName,
DWORD dwPriority,
DWORD dwFlags,
HANDLE * phMPQ,
DWORD dwAccessMode)
{
LARGE_INTEGER TempPos;
TMPQArchive * ha = NULL; // Archive handle
HANDLE hFile = INVALID_HANDLE_VALUE;// Opened archive file handle
DWORD dwMaxBlockIndex = 0; // Maximum value of block entry
DWORD dwBlockTableSize = 0; // Block table size.
DWORD dwTransferred; // Number of bytes read
DWORD dwBytes = 0; // Number of bytes to read
int nError = ERROR_SUCCESS;
// Check the right parameters
if(nError == ERROR_SUCCESS)
{
if(szMpqName == NULL || *szMpqName == 0 || phMPQ == NULL)
nError = ERROR_INVALID_PARAMETER;
}
// Ensure that StormBuffer is allocated
if(nError == ERROR_SUCCESS)
nError = PrepareStormBuffer();
// Open the MPQ archive file
if(nError == ERROR_SUCCESS)
{
hFile = CreateFile(szMpqName, dwAccessMode, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if(hFile == INVALID_HANDLE_VALUE)
nError = GetLastError();
}
// Allocate the MPQhandle
if(nError == ERROR_SUCCESS)
{
if((ha = ALLOCMEM(TMPQArchive, 1)) == NULL)
nError = ERROR_NOT_ENOUGH_MEMORY;
}
// Initialize handle structure and allocate structure for MPQ header
if(nError == ERROR_SUCCESS)
{
memset(ha, 0, sizeof(TMPQArchive));
strncpy(ha->szFileName, szMpqName, strlen(szMpqName));
ha->hFile = hFile;
ha->dwPriority = dwPriority;
ha->pHeader = &ha->Header;
ha->pListFile = NULL;
hFile = INVALID_HANDLE_VALUE;
}
// Find the offset of MPQ header within the file
if(nError == ERROR_SUCCESS)
{
LARGE_INTEGER SearchPos = {0};
LARGE_INTEGER MpqPos = {0};
DWORD dwHeaderID;
for(;;)
{
// Invalidate the MPQ ID and read the eventual header
SetFilePointer(ha->hFile, MpqPos.LowPart, &MpqPos.HighPart, FILE_BEGIN);
ReadFile(ha->hFile, ha->pHeader, sizeof(TMPQHeader2), &dwTransferred, NULL);
dwHeaderID = BSWAP_INT32_UNSIGNED(ha->pHeader->dwID);
// Special check : Some MPQs are actually AVI files, only with
// changed extension.
if(MpqPos.QuadPart == 0 && IsAviFile(ha->pHeader))
{
nError = ERROR_AVI_FILE;
break;
}
// If different number of bytes read, break the loop
if(dwTransferred != sizeof(TMPQHeader2))
{
nError = ERROR_BAD_FORMAT;
break;
}
// If there is the MPQ shunt signature, process it
if(dwHeaderID == ID_MPQ_SHUNT && ha->pShunt == NULL)
{
// Fill the shunt header
ha->ShuntPos = MpqPos;
ha->pShunt = &ha->Shunt;
memcpy(ha->pShunt, ha->pHeader, sizeof(TMPQShunt));
BSWAP_TMPQSHUNT(ha->pShunt);
// Set the MPQ pos and repeat the search
MpqPos.QuadPart = SearchPos.QuadPart + ha->pShunt->dwHeaderPos;
continue;
}
// There must be MPQ header signature
if(dwHeaderID == ID_MPQ)
{
BSWAP_TMPQHEADER(ha->pHeader);
// Save the position where the MPQ header has been found
ha->MpqPos = MpqPos;
// If valid signature has been found, break the loop
if(ha->pHeader->wFormatVersion == MPQ_FORMAT_VERSION_1)
{
// W3M Map Protectors set some garbage value into the "dwHeaderSize"
// field of MPQ header. This value is apparently ignored by Storm.dll
if(ha->pHeader->dwHeaderSize != sizeof(TMPQHeader) &&
ha->pHeader->dwHeaderSize != sizeof(TMPQHeader2))
{
ha->dwFlags |= MPQ_FLAG_PROTECTED;
ha->pHeader->dwHeaderSize = sizeof(TMPQHeader);
}
if(ha->pHeader->dwHashTablePos < ha->pHeader->dwArchiveSize &&
ha->pHeader->dwBlockTablePos < ha->pHeader->dwArchiveSize)
{
break;
}
}
if(ha->pHeader->wFormatVersion == MPQ_FORMAT_VERSION_2)
{
break;
}
nError = ERROR_NOT_SUPPORTED;
break;
}
// If a MPQ shunt already has been found,
// and no MPQ header was at potision pointed by the shunt,
// then the archive is corrupt
if(ha->pShunt != NULL)
{
nError = ERROR_BAD_FORMAT;
break;
}
// Move to the next possible offset
SearchPos.QuadPart += 0x200;
MpqPos = SearchPos;
}
}
// Relocate tables position
if(nError == ERROR_SUCCESS)
{
// Clear the fields not supported in older formats
if(ha->pHeader->wFormatVersion < MPQ_FORMAT_VERSION_2)
{
ha->pHeader->ExtBlockTablePos.QuadPart = 0;
ha->pHeader->wBlockTablePosHigh = 0;
ha->pHeader->wHashTablePosHigh = 0;
}
ha->dwBlockSize = (0x200 << ha->pHeader->wBlockSize);
nError = RelocateMpqTablePositions(ha);
}
// Allocate buffers
if(nError == ERROR_SUCCESS)
{
//
// Note that the block table should be as large as the hash table
// (For later file additions).
//
// I have found a MPQ which has the block table larger than
// the hash table. We should avoid buffer overruns caused by that.
//
dwBlockTableSize = max(ha->pHeader->dwHashTableSize, ha->pHeader->dwBlockTableSize);
ha->pHashTable = ALLOCMEM(TMPQHash, ha->pHeader->dwHashTableSize);
ha->pBlockTable = ALLOCMEM(TMPQBlock, dwBlockTableSize);
ha->pExtBlockTable = ALLOCMEM(TMPQBlockEx, dwBlockTableSize);
ha->pbBlockBuffer = ALLOCMEM(BYTE, ha->dwBlockSize);
if(!ha->pHashTable || !ha->pBlockTable || !ha->pExtBlockTable || !ha->pbBlockBuffer)
nError = ERROR_NOT_ENOUGH_MEMORY;
}
// Read the hash table into memory
if(nError == ERROR_SUCCESS)
{
dwBytes = ha->pHeader->dwHashTableSize * sizeof(TMPQHash);
SetFilePointer(ha->hFile, ha->HashTablePos.LowPart, &ha->HashTablePos.HighPart, FILE_BEGIN);
ReadFile(ha->hFile, ha->pHashTable, dwBytes, &dwTransferred, NULL);
if(dwTransferred != dwBytes)
nError = ERROR_FILE_CORRUPT;
}
// Decrypt hash table and check if it is correctly decrypted
if(nError == ERROR_SUCCESS)
{
TMPQHash * pHashEnd = ha->pHashTable + ha->pHeader->dwHashTableSize;
TMPQHash * pHash;
// We have to convert the hash table from LittleEndian
BSWAP_ARRAY32_UNSIGNED((DWORD *)ha->pHashTable, (dwBytes / sizeof(DWORD)));
DecryptHashTable((DWORD *)ha->pHashTable, (BYTE *)"(hash table)", (ha->pHeader->dwHashTableSize * 4));
// Check hash table if is correctly decrypted
for(pHash = ha->pHashTable; pHash < pHashEnd; pHash++)
{
// Note: Some MPQs from World of Warcraft have wPlatform set to 0x0100.
// If not free or deleted hash entry, check for valid values
if(pHash->dwBlockIndex < HASH_ENTRY_DELETED)
{
// The block index should not be larger than size of the block table
if(pHash->dwBlockIndex > ha->pHeader->dwBlockTableSize)
{
nError = ERROR_BAD_FORMAT;
break;
}
// Remember the highest block table entry
if(pHash->dwBlockIndex > dwMaxBlockIndex)
dwMaxBlockIndex = pHash->dwBlockIndex;
}
}
}
// Now, read the block table
if(nError == ERROR_SUCCESS)
{
memset(ha->pBlockTable, 0, dwBlockTableSize * sizeof(TMPQBlock));
dwBytes = ha->pHeader->dwBlockTableSize * sizeof(TMPQBlock);
SetFilePointer(ha->hFile, ha->BlockTablePos.LowPart, &ha->BlockTablePos.HighPart, FILE_BEGIN);
ReadFile(ha->hFile, ha->pBlockTable, dwBytes, &dwTransferred, NULL);
// We have to convert every DWORD in ha->block from LittleEndian
BSWAP_ARRAY32_UNSIGNED((DWORD *)ha->pBlockTable, dwBytes / sizeof(DWORD));
if(dwTransferred != dwBytes)
nError = ERROR_FILE_CORRUPT;
}
// Decrypt block table.
// Some MPQs don't have Decrypted block table, e.g. cracked Diablo version
// We have to check if block table is really encrypted
if(nError == ERROR_SUCCESS)
{
TMPQBlock * pBlockEnd = ha->pBlockTable + ha->pHeader->dwBlockTableSize;
TMPQBlock * pBlock = ha->pBlockTable;
BOOL bBlockTableEncrypted = FALSE;
// Verify all blocks entries in the table
// The loop usually stops at the first entry
while(pBlock < pBlockEnd)
{
// The lower 8 bits of the MPQ flags are always zero.
// Note that this may change in next MPQ versions
if(pBlock->dwFlags & 0x000000FF)
{
bBlockTableEncrypted = TRUE;
break;
}
// Move to the next block table entry
pBlock++;
}
if(bBlockTableEncrypted)
{
DecryptBlockTable((DWORD *)ha->pBlockTable,
(BYTE *)"(block table)",
(ha->pHeader->dwBlockTableSize * 4));
}
}
// Now, read the extended block table.
// For V1 archives, we still will maintain the extended block table
// (it will be filled with zeros)
// TODO: Test with >4GB
if(nError == ERROR_SUCCESS)
{
memset(ha->pExtBlockTable, 0, dwBlockTableSize * sizeof(TMPQBlockEx));
if(ha->pHeader->ExtBlockTablePos.QuadPart != 0)
{
dwBytes = ha->pHeader->dwBlockTableSize * sizeof(TMPQBlockEx);
SetFilePointer(ha->hFile,
ha->ExtBlockTablePos.LowPart,
&ha->ExtBlockTablePos.HighPart,
FILE_BEGIN);
ReadFile(ha->hFile, ha->pExtBlockTable, dwBytes, &dwTransferred, NULL);
// We have to convert every DWORD in ha->block from LittleEndian
BSWAP_ARRAY16_UNSIGNED((USHORT *)ha->pExtBlockTable, dwBytes / sizeof(USHORT));
// The extended block table is not encrypted (so far)
if(dwTransferred != dwBytes)
nError = ERROR_FILE_CORRUPT;
}
}
// Verify the both block tables (If the MPQ file is not protected)
if(nError == ERROR_SUCCESS && (ha->dwFlags & MPQ_FLAG_PROTECTED) == 0)
{
TMPQBlockEx * pBlockEx = ha->pExtBlockTable;
TMPQBlock * pBlockEnd = ha->pBlockTable + dwMaxBlockIndex + 1;
TMPQBlock * pBlock = ha->pBlockTable;
// If the MPQ file is not protected,
// we will check if all sizes in the block table is correct.
// Note that we will not relocate the block table (change from previous versions)
for(; pBlock < pBlockEnd; pBlock++, pBlockEx++)
{
if(pBlock->dwFlags & MPQ_FILE_EXISTS)
{
// Get the 64-bit file position
TempPos.HighPart = pBlockEx->wFilePosHigh;
TempPos.LowPart = pBlock->dwFilePos;
if(TempPos.QuadPart > ha->MpqSize.QuadPart || pBlock->dwCSize > ha->MpqSize.QuadPart)
{
nError = ERROR_BAD_FORMAT;
break;
}
}
}
}
// If the user didn't specified otherwise,
// include the internal listfile to the TMPQArchive structure
if((dwFlags & MPQ_OPEN_NO_LISTFILE) == 0)
{
if(nError == ERROR_SUCCESS)
SListFileCreateListFile(ha);
// Add the internal listfile
if(nError == ERROR_SUCCESS)
SFileAddListFile((HANDLE)ha, NULL);
}
// Cleanup and exit
if(nError != ERROR_SUCCESS)
{
FreeMPQArchive(ha);
if(hFile != INVALID_HANDLE_VALUE)
CloseHandle(hFile);
SetLastError(nError);
}
else
{
if(pFirstOpen == NULL)
pFirstOpen = ha;
}
*phMPQ = ha;
return (nError == ERROR_SUCCESS);
}
BOOL WINAPI SFileOpenArchive(const char * szMpqName, DWORD dwPriority, DWORD dwFlags, HANDLE * phMPQ)
{
return SFileOpenArchiveEx(szMpqName, dwPriority, dwFlags, phMPQ, GENERIC_READ);
}
//-----------------------------------------------------------------------------
// BOOL SFileCloseArchive(HANDLE hMPQ);
//
// TODO: Test for archives > 4GB
BOOL WINAPI SFileCloseArchive(HANDLE hMPQ)
{
TMPQArchive * ha = (TMPQArchive *)hMPQ;
if(!IsValidMpqHandle(ha))
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
if(ha->dwFlags & MPQ_FLAG_CHANGED)
{
SListFileSaveToMpq(ha);
SaveMPQTables(ha);
}
FreeMPQArchive(ha);
return TRUE;
}
@@ -1,403 +0,0 @@
/*****************************************************************************/
/* SFileOpenFileEx.cpp Copyright (c) Ladislav Zezula 2003 */
/*---------------------------------------------------------------------------*/
/* Description : */
/*---------------------------------------------------------------------------*/
/* Date Ver Who Comment */
/* -------- ---- --- ------- */
/* xx.xx.99 1.00 Lad The first version of SFileOpenFileEx.cpp */
/*****************************************************************************/
#define __STORMLIB_SELF__
#include "StormLib.h"
#include "SCommon.h"
/*****************************************************************************/
/* Local functions */
/*****************************************************************************/
// TODO: Test for archives > 4GB
static BOOL OpenLocalFile(const char * szFileName, HANDLE * phFile)
{
TMPQFile * hf = NULL;
HANDLE hFile = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if(hFile != INVALID_HANDLE_VALUE)
{
// Allocate and initialize file handle
size_t nHandleSize = sizeof(TMPQFile) + strlen(szFileName);
if((hf = (TMPQFile *)ALLOCMEM(char, nHandleSize)) != NULL)
{
memset(hf, 0, nHandleSize);
strcpy(hf->szFileName, szFileName);
hf->hFile = hFile;
*phFile = hf;
return TRUE;
}
else
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
}
*phFile = NULL;
return FALSE;
}
// TODO: Test for archives > 4GB
static void FreeMPQFile(TMPQFile *& hf)
{
if(hf != NULL)
{
if(hf->hFile != INVALID_HANDLE_VALUE)
CloseHandle(hf->hFile);
if(hf->pdwBlockPos != NULL)
FREEMEM(hf->pdwBlockPos);
if(hf->pbFileBuffer != NULL)
FREEMEM(hf->pbFileBuffer);
FREEMEM(hf);
hf = NULL;
}
}
/*****************************************************************************/
/* Public functions */
/*****************************************************************************/
//-----------------------------------------------------------------------------
// SFileEnumLocales enums all locale versions within MPQ.
// Functions fills all available language identifiers on a file into the buffer
// pointed by plcLocales. There must be enough entries to copy the localed,
// otherwise the function returns ERROR_INSUFFICIENT_BUFFER.
// TODO: Test for archives > 4GB
int WINAPI SFileEnumLocales(
HANDLE hMPQ,
const char * szFileName,
LCID * plcLocales,
DWORD * pdwMaxLocales,
DWORD dwSearchScope)
{
TMPQArchive * ha = (TMPQArchive *)hMPQ;
TMPQHash * pHash = NULL;
TMPQHash * pHashEnd = NULL;
DWORD dwLocales = 0;
int nError = ERROR_SUCCESS;
// Test the parameters
if(nError == ERROR_SUCCESS)
{
if(!IsValidMpqHandle(ha) || pdwMaxLocales == NULL)
nError = ERROR_INVALID_PARAMETER;
if(dwSearchScope == SFILE_OPEN_BY_INDEX && (DWORD_PTR)szFileName > ha->pHeader->dwBlockTableSize)
nError = ERROR_INVALID_PARAMETER;
if(dwSearchScope != SFILE_OPEN_BY_INDEX && *szFileName == 0)
nError = ERROR_INVALID_PARAMETER;
}
// Retrieve the hash entry for the required file
if(nError == ERROR_SUCCESS)
{
pHashEnd = ha->pHashTable + ha->pHeader->dwHashTableSize;
if(dwSearchScope == SFILE_OPEN_BY_INDEX)
{
for(pHash = ha->pHashTable; pHash < pHashEnd; pHash++)
{
if(pHash->dwBlockIndex == (DWORD_PTR)szFileName)
break;
}
if(pHash == pHashEnd)
pHash = NULL;
}
else
pHash = GetHashEntry(ha, szFileName);
}
// If the file was not found, sorry
if(nError == ERROR_SUCCESS)
{
if(pHash == NULL)
nError = ERROR_FILE_NOT_FOUND;
}
// Count the entries which correspond to the same file name
if(nError == ERROR_SUCCESS)
{
TMPQHash * pSaveHash = pHash;
DWORD dwName1 = pHash->dwName1;
DWORD dwName2 = pHash->dwName2;
// For nameless access, return 1 locale always
if(dwSearchScope == SFILE_OPEN_BY_INDEX)
dwLocales++;
else
{
while(pHash < pHashEnd && pHash->dwName1 == dwName1 && pHash->dwName2 == dwName2)
{
dwLocales++;
pHash++;
}
}
pHash = pSaveHash;
}
// Test if there is enough space to copy the locales
if(nError == ERROR_SUCCESS)
{
DWORD dwMaxLocales = *pdwMaxLocales;
*pdwMaxLocales = dwLocales;
if(dwMaxLocales < dwLocales)
nError = ERROR_INSUFFICIENT_BUFFER;
}
// Fill all the locales
if(nError == ERROR_SUCCESS)
{
for(DWORD i = 0; i < dwLocales; i++, pHash++)
*plcLocales++ = (LCID)pHash->lcLocale;
}
return nError;
}
//-----------------------------------------------------------------------------
// SFileHasFile
//
// hMPQ - Handle of opened MPQ archive
// szFileName - Name of file to look for
// TODO: Test for archives > 4GB
BOOL WINAPI SFileHasFile(HANDLE hMPQ, char * szFileName)
{
TMPQArchive * ha = (TMPQArchive *)hMPQ;
int nError = ERROR_SUCCESS;
if(nError == ERROR_SUCCESS)
{
if(ha == NULL)
nError = ERROR_INVALID_PARAMETER;
if(*szFileName == 0)
nError = ERROR_INVALID_PARAMETER;
}
// Prepare the file opening
if(nError == ERROR_SUCCESS)
{
if(GetHashEntryEx(ha, szFileName, lcLocale) == NULL)
{
nError = ERROR_FILE_NOT_FOUND;
}
}
// Cleanup
if(nError != ERROR_SUCCESS)
{
SetLastError(nError);
}
return (nError == ERROR_SUCCESS);
}
//-----------------------------------------------------------------------------
// SFileOpenFileEx
//
// hMPQ - Handle of opened MPQ archive
// szFileName - Name of file to open
// dwSearchScope - Where to search
// phFile - Pointer to store opened file handle
// TODO: Test for archives > 4GB
BOOL WINAPI SFileOpenFileEx(HANDLE hMPQ, const char * szFileName, DWORD dwSearchScope, HANDLE * phFile)
{
LARGE_INTEGER FilePos;
TMPQArchive * ha = (TMPQArchive *)hMPQ;
TMPQFile * hf = NULL;
TMPQHash * pHash = NULL; // Hash table index
TMPQBlock * pBlock = NULL; // File block
TMPQBlockEx * pBlockEx = NULL;
DWORD dwHashIndex = 0; // Hash table index
DWORD dwBlockIndex = (DWORD)-1; // Found table index
size_t nHandleSize = 0; // Memory space necessary to allocate TMPQHandle
int nError = ERROR_SUCCESS;
#ifdef _DEBUG
// Due to increasing numbers of files in MPQs, I had to change the behavior
// of opening by file index. Now, the SFILE_OPEN_BY_INDEX value of dwSearchScope
// must be entered. This check will allow to find code places that are incompatible
// with the new behavior.
if(dwSearchScope != SFILE_OPEN_BY_INDEX && szFileName != NULL)
{
assert((DWORD_PTR)szFileName > 0x10000);
}
#endif
if(nError == ERROR_SUCCESS)
{
if(ha == NULL && dwSearchScope == SFILE_OPEN_FROM_MPQ)
nError = ERROR_INVALID_PARAMETER;
if(phFile == NULL)
nError = ERROR_INVALID_PARAMETER;
if(dwSearchScope == SFILE_OPEN_BY_INDEX && (DWORD_PTR)szFileName > ha->pHeader->dwBlockTableSize)
nError = ERROR_INVALID_PARAMETER;
if(dwSearchScope != SFILE_OPEN_BY_INDEX && (szFileName == NULL || *szFileName == 0))
nError = ERROR_INVALID_PARAMETER;
}
// Prepare the file opening
if(nError == ERROR_SUCCESS)
{
// When the file is given by number, ...
if(dwSearchScope == SFILE_OPEN_BY_INDEX)
{
TMPQHash * pHashEnd = ha->pHashTable + ha->pHeader->dwHashTableSize;
// Set handle size to be sizeof(TMPQFile) + length of FileXXXXXXXX.xxx
nHandleSize = sizeof(TMPQFile) + 20;
for(pHash = ha->pHashTable; pHash < pHashEnd; pHash++)
{
if((DWORD_PTR)szFileName == pHash->dwBlockIndex)
{
dwHashIndex = (DWORD)(pHash - ha->pHashTable);
dwBlockIndex = pHash->dwBlockIndex;
break;
}
}
}
else
{
// If we have to open a disk file
if(dwSearchScope == SFILE_OPEN_LOCAL_FILE)
return OpenLocalFile(szFileName, phFile);
nHandleSize = sizeof(TMPQFile) + strlen(szFileName);
if((pHash = GetHashEntryEx(ha, szFileName, lcLocale)) != NULL)
{
dwHashIndex = (DWORD)(pHash - ha->pHashTable);
dwBlockIndex = pHash->dwBlockIndex;
}
}
}
// Get block index from file name and test it
if(nError == ERROR_SUCCESS)
{
// If index was not found, or is greater than number of files, exit.
if(dwBlockIndex == (DWORD)-1 || dwBlockIndex > ha->pHeader->dwBlockTableSize)
nError = ERROR_FILE_NOT_FOUND;
}
// Get block and test if the file was not already deleted.
if(nError == ERROR_SUCCESS)
{
// Get both block tables and file position
pBlockEx = ha->pExtBlockTable + dwBlockIndex;
pBlock = ha->pBlockTable + dwBlockIndex;
FilePos.HighPart = pBlockEx->wFilePosHigh;
FilePos.LowPart = pBlock->dwFilePos;
if(FilePos.QuadPart > ha->MpqSize.QuadPart ||
pBlock->dwCSize > ha->MpqSize.QuadPart)
nError = ERROR_FILE_CORRUPT;
if((pBlock->dwFlags & MPQ_FILE_EXISTS) == 0)
nError = ERROR_FILE_NOT_FOUND;
if(pBlock->dwFlags & ~MPQ_FILE_VALID_FLAGS)
nError = ERROR_NOT_SUPPORTED;
}
// Allocate file handle
if(nError == ERROR_SUCCESS)
{
if((hf = (TMPQFile *)ALLOCMEM(char, nHandleSize)) == NULL)
nError = ERROR_NOT_ENOUGH_MEMORY;
}
// Initialize file handle
if(nError == ERROR_SUCCESS)
{
memset(hf, 0, nHandleSize);
hf->hFile = INVALID_HANDLE_VALUE;
hf->ha = ha;
hf->pBlockEx = pBlockEx;
hf->pBlock = pBlock;
hf->nBlocks = (hf->pBlock->dwFSize + ha->dwBlockSize - 1) / ha->dwBlockSize;
hf->pHash = pHash;
hf->MpqFilePos.HighPart = pBlockEx->wFilePosHigh;
hf->MpqFilePos.LowPart = pBlock->dwFilePos;
hf->MpqFilePos.QuadPart += ha->MpqPos.QuadPart;
hf->dwHashIndex = dwHashIndex;
hf->dwFileIndex = dwBlockIndex;
// Allocate buffers for decompression.
if(hf->pBlock->dwFlags & MPQ_FILE_COMPRESSED)
{
// Allocate buffer for block positions. At the begin of file are stored
// DWORDs holding positions of each block relative from begin of file in the archive
// As for newer MPQs, there may be one additional entry in the block table
// (if the MPQ_FILE_HAS_EXTRA flag is set).
// Allocate the buffer to include this DWORD as well
if((hf->pdwBlockPos = ALLOCMEM(DWORD, hf->nBlocks + 2)) == NULL)
nError = ERROR_NOT_ENOUGH_MEMORY;
}
// Decrypt file seed. Cannot be used if the file is given by index
if(dwSearchScope != SFILE_OPEN_BY_INDEX)
{
if(hf->pBlock->dwFlags & MPQ_FILE_ENCRYPTED)
{
const char * szTemp = strrchr(szFileName, '\\');
strcpy(hf->szFileName, szFileName);
if(szTemp != NULL)
szFileName = szTemp + 1;
hf->dwSeed1 = DecryptFileSeed((char *)szFileName);
if(hf->pBlock->dwFlags & MPQ_FILE_FIXSEED)
{
hf->dwSeed1 = (hf->dwSeed1 + hf->pBlock->dwFilePos) ^ hf->pBlock->dwFSize;
}
}
}
else
{
// If the file is encrypted and not compressed, we cannot detect the file seed
if(SFileGetFileName(hf, hf->szFileName) == FALSE)
nError = GetLastError();
}
}
// Cleanup
if(nError != ERROR_SUCCESS)
{
FreeMPQFile(hf);
SetLastError(nError);
}
*phFile = hf;
return (nError == ERROR_SUCCESS);
}
//-----------------------------------------------------------------------------
// BOOL SFileCloseFile(HANDLE hFile);
// TODO: Test for archives > 4GB
BOOL WINAPI SFileCloseFile(HANDLE hFile)
{
TMPQFile * hf = (TMPQFile *)hFile;
if(!IsValidFileHandle(hf))
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
// Set the last accessed file in the archive
if(hf->ha != NULL)
hf->ha->pLastFile = NULL;
// Free the structure
FreeMPQFile(hf);
return TRUE;
}

Some files were not shown because too many files have changed in this diff Show More