Move contrib/libmpq into dep as an external dependency + remove extra libmpq-source found in map-extractor

--HG--
branch : trunk
rename : contrib/libmpq/AUTHORS => dep/libmpq/AUTHORS
rename : contrib/libmpq/COPYING => dep/libmpq/COPYING
rename : contrib/libmpq/FAQ => dep/libmpq/FAQ
rename : contrib/libmpq/Makefile.am => dep/libmpq/Makefile.am
rename : contrib/libmpq/NEWS => dep/libmpq/NEWS
rename : contrib/libmpq/README => dep/libmpq/README
rename : contrib/libmpq/THANKS => dep/libmpq/THANKS
rename : contrib/libmpq/TODO => dep/libmpq/TODO
rename : contrib/libmpq/autogen.sh => dep/libmpq/autogen.sh
rename : contrib/libmpq/bindings/Makefile.am => dep/libmpq/bindings/Makefile.am
rename : contrib/libmpq/bindings/d/Makefile.am => dep/libmpq/bindings/d/Makefile.am
rename : contrib/libmpq/bindings/d/dsss.conf => dep/libmpq/bindings/d/dsss.conf
rename : contrib/libmpq/bindings/d/mpq.d => dep/libmpq/bindings/d/mpq.d
rename : contrib/libmpq/bindings/python/Makefile.am => dep/libmpq/bindings/python/Makefile.am
rename : contrib/libmpq/bindings/python/mpq-info => dep/libmpq/bindings/python/mpq-info
rename : contrib/libmpq/bindings/python/mpq.py => dep/libmpq/bindings/python/mpq.py
rename : contrib/libmpq/configure.ac => dep/libmpq/configure.ac
rename : contrib/libmpq/debian/changelog => dep/libmpq/debian/changelog
rename : contrib/libmpq/debian/compat => dep/libmpq/debian/compat
rename : contrib/libmpq/debian/control => dep/libmpq/debian/control
rename : contrib/libmpq/debian/copyright => dep/libmpq/debian/copyright
rename : contrib/libmpq/debian/libmpq-dev.dirs => dep/libmpq/debian/libmpq-dev.dirs
rename : contrib/libmpq/debian/libmpq-dev.install => dep/libmpq/debian/libmpq-dev.install
rename : contrib/libmpq/debian/libmpq0.dirs => dep/libmpq/debian/libmpq0.dirs
rename : contrib/libmpq/debian/libmpq0.docs => dep/libmpq/debian/libmpq0.docs
rename : contrib/libmpq/debian/libmpq0.install => dep/libmpq/debian/libmpq0.install
rename : contrib/libmpq/debian/python-mpq.install => dep/libmpq/debian/python-mpq.install
rename : contrib/libmpq/debian/rules => dep/libmpq/debian/rules
rename : contrib/libmpq/doc/Makefile.am => dep/libmpq/doc/Makefile.am
rename : contrib/libmpq/doc/man1/Makefile.am => dep/libmpq/doc/man1/Makefile.am
rename : contrib/libmpq/doc/man1/libmpq-config.1 => dep/libmpq/doc/man1/libmpq-config.1
rename : contrib/libmpq/doc/man3/Makefile.am => dep/libmpq/doc/man3/Makefile.am
rename : contrib/libmpq/doc/man3/libmpq.3 => dep/libmpq/doc/man3/libmpq.3
rename : contrib/libmpq/doc/man3/libmpq__archive_close.3 => dep/libmpq/doc/man3/libmpq__archive_close.3
rename : contrib/libmpq/doc/man3/libmpq__archive_files.3 => dep/libmpq/doc/man3/libmpq__archive_files.3
rename : contrib/libmpq/doc/man3/libmpq__archive_offset.3 => dep/libmpq/doc/man3/libmpq__archive_offset.3
rename : contrib/libmpq/doc/man3/libmpq__archive_open.3 => dep/libmpq/doc/man3/libmpq__archive_open.3
rename : contrib/libmpq/doc/man3/libmpq__archive_packed_size.3 => dep/libmpq/doc/man3/libmpq__archive_packed_size.3
rename : contrib/libmpq/doc/man3/libmpq__archive_unpacked_size.3 => dep/libmpq/doc/man3/libmpq__archive_unpacked_size.3
rename : contrib/libmpq/doc/man3/libmpq__archive_version.3 => dep/libmpq/doc/man3/libmpq__archive_version.3
rename : contrib/libmpq/doc/man3/libmpq__block_close_offset.3 => dep/libmpq/doc/man3/libmpq__block_close_offset.3
rename : contrib/libmpq/doc/man3/libmpq__block_open_offset.3 => dep/libmpq/doc/man3/libmpq__block_open_offset.3
rename : contrib/libmpq/doc/man3/libmpq__block_read.3 => dep/libmpq/doc/man3/libmpq__block_read.3
rename : contrib/libmpq/doc/man3/libmpq__block_unpacked_size.3 => dep/libmpq/doc/man3/libmpq__block_unpacked_size.3
rename : contrib/libmpq/doc/man3/libmpq__file_blocks.3 => dep/libmpq/doc/man3/libmpq__file_blocks.3
rename : contrib/libmpq/doc/man3/libmpq__file_compressed.3 => dep/libmpq/doc/man3/libmpq__file_compressed.3
rename : contrib/libmpq/doc/man3/libmpq__file_encrypted.3 => dep/libmpq/doc/man3/libmpq__file_encrypted.3
rename : contrib/libmpq/doc/man3/libmpq__file_imploded.3 => dep/libmpq/doc/man3/libmpq__file_imploded.3
rename : contrib/libmpq/doc/man3/libmpq__file_number.3 => dep/libmpq/doc/man3/libmpq__file_number.3
rename : contrib/libmpq/doc/man3/libmpq__file_offset.3 => dep/libmpq/doc/man3/libmpq__file_offset.3
rename : contrib/libmpq/doc/man3/libmpq__file_packed_size.3 => dep/libmpq/doc/man3/libmpq__file_packed_size.3
rename : contrib/libmpq/doc/man3/libmpq__file_read.3 => dep/libmpq/doc/man3/libmpq__file_read.3
rename : contrib/libmpq/doc/man3/libmpq__file_unpacked_size.3 => dep/libmpq/doc/man3/libmpq__file_unpacked_size.3
rename : contrib/libmpq/doc/man3/libmpq__version.3 => dep/libmpq/doc/man3/libmpq__version.3
rename : contrib/libmpq/libmpq-config.in => dep/libmpq/libmpq-config.in
rename : contrib/libmpq/libmpq.pc.in => dep/libmpq/libmpq.pc.in
rename : contrib/libmpq/libmpq/Makefile.am => dep/libmpq/libmpq/Makefile.am
rename : contrib/libmpq/libmpq/common.c => dep/libmpq/libmpq/common.c
rename : contrib/libmpq/libmpq/common.h => dep/libmpq/libmpq/common.h
rename : contrib/libmpq/libmpq/crypt_buf.h => dep/libmpq/libmpq/crypt_buf.h
rename : contrib/libmpq/libmpq/explode.c => dep/libmpq/libmpq/explode.c
rename : contrib/libmpq/libmpq/explode.h => dep/libmpq/libmpq/explode.h
rename : contrib/libmpq/libmpq/extract.c => dep/libmpq/libmpq/extract.c
rename : contrib/libmpq/libmpq/extract.h => dep/libmpq/libmpq/extract.h
rename : contrib/libmpq/libmpq/huffman.c => dep/libmpq/libmpq/huffman.c
rename : contrib/libmpq/libmpq/huffman.h => dep/libmpq/libmpq/huffman.h
rename : contrib/libmpq/libmpq/mpq-internal.h => dep/libmpq/libmpq/mpq-internal.h
rename : contrib/libmpq/libmpq/mpq.c => dep/libmpq/libmpq/mpq.c
rename : contrib/libmpq/libmpq/mpq.h => dep/libmpq/libmpq/mpq.h
rename : contrib/libmpq/libmpq/wave.c => dep/libmpq/libmpq/wave.c
rename : contrib/libmpq/libmpq/wave.h => dep/libmpq/libmpq/wave.h
rename : contrib/libmpq/tools/Makefile.am => dep/libmpq/tools/Makefile.am
rename : contrib/libmpq/tools/crypt_buf_gen.c => dep/libmpq/tools/crypt_buf_gen.c
rename : contrib/libmpq/win/VS100/libmpq.vcxproj => dep/libmpq/win/VS100/libmpq.vcxproj
rename : contrib/libmpq/win/config.h => dep/libmpq/win/config.h
rename : contrib/libmpq/win/libmpq_VC90.sln => dep/libmpq/win/libmpq_VC90.sln
rename : contrib/libmpq/win/stdint.h => dep/libmpq/win/stdint.h
This commit is contained in:
click committed 2010-06-05 23:00:30 +02:00
1 parent fd28bc6aff
commit 6a9357b13d
96 files changed
-5507

No files matched your search

File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,13 +0,0 @@
# 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.
add_library (libmpq common.cpp explode.cpp extract.cpp huffman.cpp mpq.cpp parser.cpp wave.cpp )
# link libmpq with zlib
target_link_libraries (libmpq z)
-802
View File
@@ -1,802 +0,0 @@
/*
* common.c -- shared functions used by mpq-tools.
*
* Copyright (C) 2003 Maik Broemme <mbroemme@plusserver.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Id: common.c,v 1.12 2004/02/12 00:42:54 mbroemme Exp $
*/
#define _CRT_SECURE_NO_DEPRECATE
//#include <dirent.h>
#include <sys/stat.h>
//#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "mpq.h"
#include "common.h"
#include <ctype.h>
/*
* This function decrypts a MPQ block.
*/
int libmpq_decrypt_block(mpq_archive *mpq_a, unsigned int *block, unsigned int length, unsigned int seed1) {
unsigned int seed2 = 0xEEEEEEEE;
unsigned int ch;
/* Round to unsigned int's */
length >>= 2;
while (length-- > 0) {
seed2 += mpq_a->buf[0x400 + (seed1 & 0xFF)];
ch = *block ^ (seed1 + seed2);
seed1 = ((~seed1 << 0x15) + 0x11111111) | (seed1 >> 0x0B);
seed2 = ch + seed2 + (seed2 << 5) + 3;
*block++ = ch;
}
return LIBMPQ_TOOLS_SUCCESS;
}
/*
* This function decrypts the hashtable for the
* file informations.
*/
int libmpq_decrypt_hashtable(mpq_archive *mpq_a, unsigned char *pbKey) {
unsigned int seed1 = 0x7FED7FED;
unsigned int seed2 = 0xEEEEEEEE;
unsigned int ch; /* One key character */
unsigned int *pdwTable = (unsigned int *)(mpq_a->hashtable);
unsigned int length = mpq_a->header->hashtablesize * 4;
/* Prepare seeds */
while (*pbKey != 0) {
ch = toupper(*pbKey++);
seed1 = mpq_a->buf[0x300 + ch] ^ (seed1 + seed2);
seed2 = ch + seed1 + seed2 + (seed2 << 5) + 3;
}
/* Decrypt it */
seed2 = 0xEEEEEEEE;
while (length-- > 0) {
seed2 += mpq_a->buf[0x400 + (seed1 & 0xFF)];
ch = *pdwTable ^ (seed1 + seed2);
seed1 = ((~seed1 << 0x15) + 0x11111111) | (seed1 >> 0x0B);
seed2 = ch + seed2 + (seed2 << 5) + 3;
*pdwTable++ = ch;
}
return LIBMPQ_TOOLS_SUCCESS;
}
/*
* This function decrypts the blocktable.
*/
int libmpq_decrypt_blocktable(mpq_archive *mpq_a, unsigned char *pbKey) {
unsigned int seed1 = 0x7FED7FED;
unsigned int seed2 = 0xEEEEEEEE;
unsigned int ch; /* One key character */
unsigned int *pdwTable = (unsigned int *)(mpq_a->blocktable);
unsigned int length = mpq_a->header->blocktablesize * 4;
/* Prepare seeds */
while(*pbKey != 0) {
ch = toupper(*pbKey++);
seed1 = mpq_a->buf[0x300 + ch] ^ (seed1 + seed2);
seed2 = ch + seed1 + seed2 + (seed2 << 5) + 3;
}
/* Decrypt it */
seed2 = 0xEEEEEEEE;
while(length-- > 0) {
seed2 += mpq_a->buf[0x400 + (seed1 & 0xFF)];
ch = *pdwTable ^ (seed1 + seed2);
seed1 = ((~seed1 << 0x15) + 0x11111111) | (seed1 >> 0x0B);
seed2 = ch + seed2 + (seed2 << 5) + 3;
*pdwTable++ = ch;
}
return LIBMPQ_TOOLS_SUCCESS;
}
int libmpq_read_listfile(mpq_archive *mpq_a, FILE *fp) {
int mpq_size;
int mpq_ht_size;
int mpq_bt_size;
int mpq_blocksize;
int mpq_files;
int mpq_csize;
int mpq_fsize;
int entries;
char listdb_version[10];
char libmpq_version[10];
int listdb_temp_version = 0;
int libmpq_temp_version = 0;
/* first check header and version */
if (libmpq_conf_get_value(fp, "LIBMPQ_VERSION", mpq_a->mpq_l->mpq_version, LIBMPQ_CONF_TYPE_CHAR, sizeof(mpq_a->mpq_l->mpq_version))) {
return LIBMPQ_CONF_EFILE_CORRUPT;
} else {
/* copy to temp buffer for removing . characters */
sprintf(listdb_version, (char *)mpq_a->mpq_l->mpq_version);
/* remove . characters from listfile version */
libmpq_conf_delete_char(listdb_version, ".");
/* get libmpq version */
sprintf(libmpq_version, "%i%i%i",LIBMPQ_MAJOR_VERSION, LIBMPQ_MINOR_VERSION, LIBMPQ_PATCH_VERSION);
/* convert to number */
listdb_temp_version = atoi(listdb_version);
libmpq_temp_version = atoi(libmpq_version);
/* check if installed libmpq version is valid for listfile version */
if ((libmpq_temp_version < listdb_temp_version) || (libmpq_temp_version == 0) || (listdb_temp_version == 0)) {
return LIBMPQ_CONF_EFILE_VERSION;
}
}
/* check listfile header, the following entries must be set */
if (libmpq_conf_get_value(fp, "MPQ_SIZE", &mpq_size, LIBMPQ_CONF_TYPE_INT, 0)) {
return LIBMPQ_CONF_EFILE_CORRUPT;
}
if (libmpq_conf_get_value(fp, "MPQ_HASHTABLE_SIZE", &mpq_ht_size, LIBMPQ_CONF_TYPE_INT, 0)) {
return LIBMPQ_CONF_EFILE_CORRUPT;
}
if (libmpq_conf_get_value(fp, "MPQ_BLOCKTABLE_SIZE", &mpq_bt_size, LIBMPQ_CONF_TYPE_INT, 0)) {
return LIBMPQ_CONF_EFILE_CORRUPT;
}
if (libmpq_conf_get_value(fp, "MPQ_BLOCKSIZE", &mpq_blocksize, LIBMPQ_CONF_TYPE_INT, 0)) {
return LIBMPQ_CONF_EFILE_CORRUPT;
}
if (libmpq_conf_get_value(fp, "MPQ_FILES", &mpq_files, LIBMPQ_CONF_TYPE_INT, 0)) {
return LIBMPQ_CONF_EFILE_CORRUPT;
}
if (libmpq_conf_get_value(fp, "MPQ_COMPRESSED_SIZE", &mpq_csize, LIBMPQ_CONF_TYPE_INT, 0)) {
return LIBMPQ_CONF_EFILE_CORRUPT;
}
if (libmpq_conf_get_value(fp, "MPQ_UNCOMPRESSED_SIZE", &mpq_fsize, LIBMPQ_CONF_TYPE_INT, 0)) {
return LIBMPQ_CONF_EFILE_CORRUPT;
}
if (libmpq_conf_get_value(fp, "MPQ_NAME", mpq_a->mpq_l->mpq_name, LIBMPQ_CONF_TYPE_CHAR, PATH_MAX)) {
return LIBMPQ_CONF_EFILE_CORRUPT;
}
if (libmpq_conf_get_value(fp, "MPQ_TYPE", mpq_a->mpq_l->mpq_type, LIBMPQ_CONF_TYPE_CHAR, sizeof(mpq_a->mpq_l->mpq_type))) {
return LIBMPQ_CONF_EFILE_CORRUPT;
}
/* these are optional parameters, if they are empty we set the struct members empty */
libmpq_conf_get_value(fp, "MPQ_GAME", mpq_a->mpq_l->mpq_game, LIBMPQ_CONF_TYPE_CHAR, sizeof(mpq_a->mpq_l->mpq_game));
libmpq_conf_get_value(fp, "MPQ_GAME_VERSION", mpq_a->mpq_l->mpq_game_version, LIBMPQ_CONF_TYPE_CHAR, sizeof(mpq_a->mpq_l->mpq_game_version));
/* check if we found a valid listfile for the given archive */
if (mpq_a->header->hashtablesize == mpq_ht_size && mpq_a->header->blocktablesize == mpq_bt_size && mpq_a->blocksize == mpq_blocksize && libmpq_archive_info(mpq_a, LIBMPQ_MPQ_ARCHIVE_SIZE) == mpq_size && libmpq_archive_info(mpq_a, LIBMPQ_MPQ_NUMFILES) == mpq_files && libmpq_archive_info(mpq_a, LIBMPQ_MPQ_COMPRESSED_SIZE) == mpq_csize && libmpq_archive_info(mpq_a, LIBMPQ_MPQ_UNCOMPRESSED_SIZE) == mpq_fsize) {
/* check if the filelist is correct */
if (!libmpq_conf_get_array(fp, "FILE_NAMES", (char ***)&mpq_a->mpq_l->mpq_files, &entries)) {
/* we have a corrupt filelist, so return */
return LIBMPQ_CONF_EFILE_LIST_CORRUPT;
} else {
/* now check if filelist entries matches number of files in the archive. */
if (entries != libmpq_archive_info(mpq_a, LIBMPQ_MPQ_NUMFILES)) {
libmpq_free_listfile((char **)mpq_a->mpq_l->mpq_files);
mpq_a->mpq_l->mpq_files = NULL;
return LIBMPQ_CONF_EFILE_LIST_CORRUPT;
}
}
}
return LIBMPQ_TOOLS_SUCCESS;
}
/*
* This function frees up the space reserved by libmpq_get_listfile()
*/
int libmpq_free_listfile(char **filelist) {
int i = 0;
while (filelist[i]) {
free(filelist[i++]);
}
free(filelist);
return LIBMPQ_TOOLS_SUCCESS;
}
/*
* This function reads the directory and the subdirectories
* of the listfile database and adds a entry to the lisfile
* array.
*/
/*int libmpq_detect_listfile_rec(char path[PATH_MAX], char ***filelist, int *fl_count, int *fl_size) {
char nextpath[PATH_MAX];
DIR *dp = opendir(path);
FILE *fp;
struct dirent *entry;
struct stat statbuf;
char buf[LIBMPQ_CONF_BUFSIZE];
if (dp == NULL) {
return LIBMPQ_CONF_EOPEN_DIR;
} else {
while ((entry = readdir(dp)) != NULL) {
if (strncmp(entry->d_name, ".", 1) == 0 || strncmp(entry->d_name, "..", 2) == 0) {
continue;
}
if (strnlen(path, PATH_MAX) + strnlen(entry->d_name, PATH_MAX) + 2 > sizeof nextpath) {
continue;
}
snprintf(nextpath, PATH_MAX, "%s/%s", path, entry->d_name);
// check if file extension matches listdb file extension
if (strncmp(&entry->d_name[strlen(entry->d_name) - strlen(LIBMPQ_CONF_EXT)], LIBMPQ_CONF_EXT, strlen(LIBMPQ_CONF_EXT)) == 0) {
// check if it is really a listdb file
if ((fp = fopen(nextpath, "r")) != NULL ) {
while (fgets(buf, LIBMPQ_CONF_BUFSIZE, fp) != NULL) {
char *line;
buf[strlen(buf) - 1] = '\0';
// skip whitespace
for (line = buf; isspace(*line); line++) {
continue;
}
// skip empty line
if (line[0] == '\0') {
continue;
}
// skip comments
if (line[0] == '#') {
continue;
}
//search for listdb header; dirty but works :)
if (!strncasecmp(line, LIBMPQ_CONF_HEADER, strlen(LIBMPQ_CONF_HEADER))) {
// set the next filelist entry to a copy of the file path
(*filelist)[(*fl_count)++] = strdup(nextpath);
// increase the array size
if ((*fl_count) == (*fl_size)) {
(*filelist) = realloc((*filelist), ((*fl_size) + LIBMPQ_CONF_FL_INCREMENT) * sizeof(char *));
(*fl_size) += LIBMPQ_CONF_FL_INCREMENT;
}
// header found so we could stop reading the file.
break;
}
}
fclose(fp);
}
}
if (stat(nextpath, &statbuf) < 0) {
continue;
}
// if entry ia a subdirectory, read it
if (S_ISDIR(statbuf.st_mode)) {
libmpq_detect_listfile_rec(nextpath, filelist, fl_count, fl_size);
}
}
closedir(dp);
}
return LIBMPQ_TOOLS_SUCCESS;
}
*/
/*
* This functions tries to get file decryption key. The trick comes from block
* positions which are stored at the begin of each compressed file. We know the
* file size, that means we know number of blocks that means we know the first
* int value in block position. And if we know encrypted and decrypted value,
* we can find the decryption key.
*/
int libmpq_detect_fileseed(mpq_archive *mpq_a, unsigned int *block, unsigned int decrypted) {
unsigned int saveseed1;
unsigned int temp = *block ^ decrypted; /* temp = seed1 + seed2 */
int i = 0;
temp -= 0xEEEEEEEE; /* temp = seed1 + mpq_a->buf[0x400 + (seed1 & 0xFF)] */
for (i = 0; i < 0x100; i++) { /* Try all 255 possibilities */
unsigned int seed1;
unsigned int seed2 = 0xEEEEEEEE;
unsigned int ch;
/* Try the first unsigned int's (We exactly know the value) */
seed1 = temp - mpq_a->buf[0x400 + i];
seed2 += mpq_a->buf[0x400 + (seed1 & 0xFF)];
ch = block[0] ^ (seed1 + seed2);
if (ch != decrypted) {
continue;
}
/* Add 1 because we are decrypting block positions */
saveseed1 = seed1 + 1;
/*
* If OK, continue and test the second value. We don't know exactly the value,
* but we know that the second one has lower 16 bits set to zero
* (no compressed block is larger than 0xFFFF bytes)
*/
seed1 = ((~seed1 << 0x15) + 0x11111111) | (seed1 >> 0x0B);
seed2 = ch + seed2 + (seed2 << 5) + 3;
seed2 += mpq_a->buf[0x400 + (seed1 & 0xFF)];
ch = block[1] ^ (seed1 + seed2);
if ((ch & 0xFFFF0000) == 0) {
return saveseed1;
}
}
return LIBMPQ_TOOLS_SUCCESS;
}
/*
* This function initialize the decryption buffer
*/
int libmpq_init_buffer(mpq_archive *mpq_a) {
unsigned int seed = 0x00100001;
unsigned int index1 = 0;
unsigned int index2 = 0;
int i;
memset(mpq_a->buf, 0, sizeof(mpq_a->buf));
/* Initialize the decryption buffer. */
for (index1 = 0; index1 < 0x100; index1++) {
for(index2 = index1, i = 0; i < 5; i++, index2 += 0x100) {
unsigned int temp1, temp2;
seed = (seed * 125 + 3) % 0x2AAAAB;
temp1 = (seed & 0xFFFF) << 0x10;
seed = (seed * 125 + 3) % 0x2AAAAB;
temp2 = (seed & 0xFFFF);
mpq_a->buf[index2] = (temp1 | temp2);
}
}
return LIBMPQ_TOOLS_SUCCESS;
}
/*
* This functions fills the mpq_hash structure with the
* hashtable found in the MPQ file. The hashtable will
* be decrypted for later use.
*/
int libmpq_read_hashtable(mpq_archive *mpq_a) {
unsigned int bytes = 0;
int rb = 0;
/*
* Allocate memory. Note that the block table should be as large as the
* hash table. (for later file additions)
*/
mpq_a->hashtable = (mpq_hash *)malloc(sizeof(mpq_hash) * mpq_a->header->hashtablesize);
if (!mpq_a->hashtable) {
return LIBMPQ_EALLOCMEM;
}
/* Read the hash table into the buffer */
bytes = mpq_a->header->hashtablesize * sizeof(mpq_hash);
#ifdef WIN32
_lseeki64(mpq_a->fd, mpq_a->header->hashtablepos, SEEK_SET);
#else
lseek64(mpq_a->fd, mpq_a->header->hashtablepos, SEEK_SET);
#endif
rb = _read(mpq_a->fd, mpq_a->hashtable, bytes);
if (rb != bytes) {
return LIBMPQ_EFILE_CORRUPT;
}
/* Decrypt hash table and check if it is correctly decrypted */
mpq_hash *mpq_h_end = mpq_a->hashtable + mpq_a->header->hashtablesize;
mpq_hash *mpq_h = NULL;
libmpq_decrypt_hashtable(mpq_a, (unsigned char *)"(hash table)");
/* Check hash table if is correctly decrypted */
for (mpq_h = mpq_a->hashtable; mpq_h < mpq_h_end; mpq_h++) {
if (mpq_h->locale != 0xFFFFFFFF && (mpq_h->locale & 0xFFFF0000) != 0) {
return LIBMPQ_EFILE_FORMAT;
}
/* Remember the highest block table entry */
if (mpq_h->blockindex < LIBMPQ_HASH_ENTRY_DELETED && mpq_h->blockindex > 0) {
mpq_a->maxblockindex = mpq_h->blockindex;
}
}
return LIBMPQ_TOOLS_SUCCESS;
}
/*
* This functions fills the mpq_block structure with the
* blocktable found in the MPQ file. The blocktable will
* be decrypted for later use.
*
* NOTICE: Some MPQs have decrypted block table, e.g.
* cracked Diablo versions.
*/
int libmpq_read_blocktable(mpq_archive *mpq_a) {
unsigned int bytes = 0;
int rb = 0;
/*
* Allocate memory. Note that the block table should be as large as the
* hash table. (for later file additions)
*/
mpq_a->blocktable = (mpq_block *)malloc(sizeof(mpq_block) * mpq_a->header->hashtablesize);
mpq_a->blockbuf = (unsigned char *)malloc(mpq_a->blocksize);
if (!mpq_a->blocktable || !mpq_a->blockbuf) {
return LIBMPQ_EALLOCMEM;
}
/* Read the block table into the buffer */
bytes = mpq_a->header->blocktablesize * sizeof(mpq_block);
memset(mpq_a->blocktable, 0, mpq_a->header->blocktablesize * sizeof(mpq_block));
#ifdef WIN32
_lseeki64(mpq_a->fd, mpq_a->header->blocktablepos, SEEK_SET);
#else
lseek64(mpq_a->fd, mpq_a->header->blocktablepos, SEEK_SET);
#endif
rb = _read(mpq_a->fd, mpq_a->blocktable, bytes);
if (rb != bytes) {
return LIBMPQ_EFILE_CORRUPT;
}
/*
* Decrypt block table. Some MPQs don't have encrypted block table,
* e.g. cracked Diablo version. We have to check if block table is
* already decrypted
*/
mpq_block *mpq_b_end = mpq_a->blocktable + mpq_a->maxblockindex + 1;
mpq_block *mpq_b = NULL;
unsigned int archivesize = mpq_a->header->archivesize + mpq_a->mpqpos;
if (mpq_a->header->offset != mpq_a->blocktable->filepos) {
libmpq_decrypt_blocktable(mpq_a, (unsigned char *)"(block table)");
}
for (mpq_b = mpq_a->blocktable; mpq_b < mpq_b_end; mpq_b++) {
if (mpq_b->filepos > archivesize || mpq_b->csize > archivesize) {
if ((mpq_a->flags & LIBMPQ_FLAG_PROTECTED) == 0) {
return LIBMPQ_EFILE_FORMAT;
}
}
mpq_b->filepos += mpq_a->mpqpos;
}
return LIBMPQ_TOOLS_SUCCESS;
}
int libmpq_file_read_block(mpq_archive *mpq_a, mpq_file *mpq_f, unsigned int blockpos, char *buffer, unsigned int blockbytes) {
unsigned char *tempbuf = NULL; /* Buffer for reading compressed data from the file */
unsigned int readpos; /* Reading position from the file */
unsigned int toread = 0; /* Number of bytes to read */
unsigned int blocknum; /* Block number (needed for decrypt) */
unsigned int bytesread = 0; /* Total number of bytes read */
unsigned int nblocks; /* Number of blocks to load */
unsigned int i;
/* Test parameters. Block position and block size must be block-aligned, block size nonzero */
if ((blockpos & (mpq_a->blocksize - 1)) || blockbytes == 0) {
return 0;
}
/* Check the end of file */
if ((blockpos + blockbytes) > mpq_f->mpq_b->fsize) {
blockbytes = mpq_f->mpq_b->fsize - blockpos;
}
blocknum = blockpos / mpq_a->blocksize;
nblocks = blockbytes / mpq_a->blocksize;
if (blockbytes % mpq_a->blocksize) {
nblocks++;
}
/* If file has variable block positions, we have to load them */
if ((mpq_f->mpq_b->flags & LIBMPQ_FILE_COMPRESSED) && mpq_f->blockposloaded == FALSE) {
unsigned int nread;
if (mpq_f->mpq_b->filepos != mpq_a->filepos) {
#ifdef WIN32
_lseeki64(mpq_a->fd, mpq_f->mpq_b->filepos, SEEK_SET);
#else
lseek64(mpq_a->fd, mpq_f->mpq_b->filepos, SEEK_SET);
#endif
}
/* Read block positions from begin of file. */
nread = (mpq_f->nblocks + 1) * sizeof(int);
nread = _read(mpq_a->fd, mpq_f->blockpos, nread);
/*
* If the archive is protected some way, perform additional check
* Sometimes, the file appears not to be encrypted, but it is.
*/
/*if (mpq_f->blockpos[0] != nread) {
mpq_f->mpq_b->flags |= LIBMPQ_FILE_ENCRYPTED;
}*/
if ((mpq_f->mpq_b->flags & LIBMPQ_FILE_HAS_METADATA) == 0) {
if (mpq_f->blockpos[0] != nread) {
mpq_f->mpq_b->flags |= LIBMPQ_FILE_ENCRYPTED;
}
}
/* Decrypt loaded block positions if necessary */
if (mpq_f->mpq_b->flags & LIBMPQ_FILE_ENCRYPTED) {
/* If we don't know the file seed, try to find it. */
if (mpq_f->seed == 0) {
mpq_f->seed = libmpq_detect_fileseed(mpq_a, mpq_f->blockpos, nread);
}
/* If we don't know the file seed, sorry but we cannot extract the file. */
if (mpq_f->seed == 0) {
return 0;
}
/* Decrypt block positions */
libmpq_decrypt_block(mpq_a, mpq_f->blockpos, nread, mpq_f->seed - 1);
/*
* Check if the block positions are correctly decrypted
* I don't know why, but sometimes it will result invalid
* block positions on some files.
*/
if (mpq_f->blockpos[0] != nread) {
/* Try once again to detect file seed and decrypt the blocks */
#ifdef WIN32
_lseeki64(mpq_a->fd, mpq_f->mpq_b->filepos, SEEK_SET);
#else
lseek64(mpq_a->fd, mpq_f->mpq_b->filepos, SEEK_SET);
#endif
nread = _read(mpq_a->fd, mpq_f->blockpos, (mpq_f->nblocks + 1) * sizeof(int));
mpq_f->seed = libmpq_detect_fileseed(mpq_a, mpq_f->blockpos, nread);
libmpq_decrypt_block(mpq_a, mpq_f->blockpos, nread, mpq_f->seed - 1);
/* Check if the block positions are correctly decrypted. */
if (mpq_f->blockpos[0] != nread) {
return 0;
}
}
}
/* Update mpq_f's variables */
mpq_f->blockposloaded = TRUE;
mpq_a->filepos = mpq_f->mpq_b->filepos + nread;
}
/* Get file position and number of bytes to read */
readpos = blockpos;
toread = blockbytes;
if (mpq_f->mpq_b->flags & LIBMPQ_FILE_COMPRESSED) {
readpos = mpq_f->blockpos[blocknum];
toread = mpq_f->blockpos[blocknum + nblocks] - readpos;
}
readpos += mpq_f->mpq_b->filepos;
/* Get work buffer for store read data */
if ((tempbuf = (unsigned char *)malloc(toread)) == NULL) {
/* Hmmm... We should add a better error handling here :) */
return 0;
}
/* Set file pointer, if necessary. */
if (mpq_a->filepos != readpos) {
#ifdef WIN32
mpq_a->filepos = _lseeki64(mpq_a->fd, readpos, SEEK_SET);
#else
mpq_a->filepos = lseek64(mpq_a->fd, readpos, SEEK_SET);
#endif
}
/* 15018F87 - Read all requested blocks. */
bytesread = _read(mpq_a->fd, tempbuf, toread);
mpq_a->filepos = readpos + bytesread;
/* Block processing part. */
unsigned int blockstart = 0; /* Index of block start in work buffer. */
unsigned int blocksize = min(blockbytes, mpq_a->blocksize);
unsigned int index = blocknum; /* Current block index. */
bytesread = 0; /* Clear read byte counter */
/* Walk through all blocks. */
for (i = 0; i < nblocks; i++, index++) {
int outlength = mpq_a->blocksize;
/* Get current block length */
if (mpq_f->mpq_b->flags & LIBMPQ_FILE_COMPRESSED) {
blocksize = mpq_f->blockpos[index + 1] - mpq_f->blockpos[index];
}
/* If block is encrypted, we have to decrypt it. */
if (mpq_f->mpq_b->flags & LIBMPQ_FILE_ENCRYPTED) {
if (mpq_f->seed == 0) {
return 0;
}
libmpq_decrypt_block(mpq_a, (unsigned int *)&tempbuf[blockstart], blocksize, mpq_f->seed + index);
}
/*
* If the block is really compressed, recompress it.
* WARNING: Some block may not be compressed, it can
* only be determined by comparing uncompressed and
* compressed size!
*/
if (blocksize < blockbytes) {
/* Is the file compressed with PKWARE Data Compression Library? */
if (mpq_f->mpq_b->flags & LIBMPQ_FILE_COMPRESS_PKWARE) {
libmpq_pkzip_decompress(buffer, &outlength, (char *)&tempbuf[blockstart], blocksize);
}
/*
* Is it a file compressed by Blizzard's multiple compression ?
* Note that Storm.dll v 1.0.9 distributed with Warcraft III
* passes the full path name of the opened archive as the new
* last parameter.
*/
if (mpq_f->mpq_b->flags & LIBMPQ_FILE_COMPRESS_MULTI) {
libmpq_multi_decompress(buffer, &outlength, (char *)&tempbuf[blockstart], blocksize);
}
bytesread += outlength;
buffer += outlength;
} else {
memcpy(buffer, tempbuf, blocksize);
bytesread += blocksize;
buffer += blocksize;
}
blockstart += blocksize;
}
/* Delete input buffer, if necessary. */
free(tempbuf);
return bytesread;
}
int libmpq_file_read_file(mpq_archive *mpq_a, mpq_file *mpq_f, unsigned int filepos, char *buffer, unsigned int toread) {
unsigned int bytesread = 0; /* Number of bytes read from the file */
unsigned int blockpos; /* Position in the file aligned to the whole blocks */
unsigned int loaded = 0;
/* File position is greater or equal to file size? */
if (filepos >= mpq_f->mpq_b->fsize) {
return 0;
}
/* If to few bytes in the file remaining, cut them */
if ((mpq_f->mpq_b->fsize - filepos) < toread) {
toread = (mpq_f->mpq_b->fsize - filepos);
}
/* Block position in the file */
blockpos = filepos & ~(mpq_a->blocksize - 1);
/*
* Load the first block, if noncomplete. It may be loaded in the cache buffer.
* We have to check if this block is loaded. If not, load it.
*/
if ((filepos % mpq_a->blocksize) != 0) {
/* Number of bytes remaining in the buffer */
unsigned int tocopy;
unsigned int loaded = mpq_a->blocksize;
/* Check if data are loaded in the cache */
if (mpq_f->accessed == FALSE || blockpos != mpq_a->blockpos) {
/* Load one MPQ block into archive buffer */
loaded = libmpq_file_read_block(mpq_a, mpq_f, blockpos, (char *)mpq_a->blockbuf, mpq_a->blocksize);
if (loaded == 0) {
return 0;
}
/* Save lastly accessed file and block position for later use */
mpq_f->accessed = TRUE;
mpq_a->blockpos = blockpos;
mpq_a->bufpos = filepos % mpq_a->blocksize;
}
tocopy = loaded - mpq_a->bufpos;
if (tocopy > toread) {
tocopy = toread;
}
/* Copy data from block buffer into target buffer */
memcpy(buffer, mpq_a->blockbuf + mpq_a->bufpos, tocopy);
/* Update pointers */
toread -= tocopy;
bytesread += tocopy;
buffer += tocopy;
blockpos += mpq_a->blocksize;
mpq_a->bufpos += tocopy;
/* If all, return. */
if (toread == 0) {
return bytesread;
}
}
/* Load the whole ("middle") blocks only if there are more or equal one block */
if (toread > mpq_a->blocksize) {
unsigned int blockbytes = toread & ~(mpq_a->blocksize - 1);
loaded = libmpq_file_read_block(mpq_a, mpq_f, blockpos, buffer, blockbytes);
if (loaded == 0) {
return 0;
}
/* Update pointers */
toread -= loaded;
bytesread += loaded;
buffer += loaded;
blockpos += loaded;
/* If all, return. */
if (toread == 0) {
return bytesread;
}
}
/* Load the terminating block */
if (toread > 0) {
unsigned int tocopy = mpq_a->blocksize;
/* Check if data are loaded in the cache */
if (mpq_f->accessed == FALSE || blockpos != mpq_a->blockpos) {
/* Load one MPQ block into archive buffer */
tocopy = libmpq_file_read_block(mpq_a, mpq_f, blockpos, (char *)mpq_a->blockbuf, mpq_a->blocksize);
if (tocopy == 0) {
return 0;
}
/* Save lastly accessed file and block position for later use */
mpq_f->accessed = TRUE;
mpq_a->blockpos = blockpos;
}
mpq_a->bufpos = 0;
/* Check number of bytes read */
if (tocopy > toread) {
tocopy = toread;
}
memcpy(buffer, mpq_a->blockbuf, tocopy);
bytesread += tocopy;
mpq_a->bufpos = tocopy;
}
/* Return what we've read */
return bytesread;
}
-73
View File
@@ -1,73 +0,0 @@
/*
* common.h -- defines and structs used by the config files.
*
* Copyright (C) 2003 Maik Broemme <mbroemme@plusserver.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Id: common.h,v 1.4 2004/02/12 00:41:55 mbroemme Exp $
*/
#define LIBMPQ_CONF_FL_INCREMENT 512 /* i hope we did not need more :) */
#define LIBMPQ_CONF_EXT ".conf" /* listdb file seems to be valid with this extension */
#define LIBMPQ_CONF_HEADER "LIBMPQ_VERSION" /* listdb file must include this entry to be valid */
#define LIBMPQ_CONF_BUFSIZE 4096 /* maximum number of bytes a line in the file could contain */
#define LIBMPQ_CONF_TYPE_CHAR 1 /* value in config file is from type char */
#define LIBMPQ_CONF_TYPE_INT 2 /* value in config file is from type int */
#define LIBMPQ_CONF_EOPEN_DIR -1 /* error on open directory */
#define LIBMPQ_CONF_EVALUE_NOT_FOUND -2 /* value for the option was not found */
#if defined( __GNUC__ )
#include <sys/types.h>
#include <unistd.h>
#define _lseek lseek
#define _read read
#define _open open
#define _write write
#define _close close
#define _strdup strdup
#ifndef O_BINARY
#define O_BINARY 0
#endif
#else
#include <io.h>
#endif
#ifdef O_LARGEFILE
#define MPQ_FILE_OPEN_FLAGS (O_RDONLY | O_BINARY | O_LARGEFILE)
#else
#define MPQ_FILE_OPEN_FLAGS (O_RDONLY | O_BINARY)
#endif
#ifndef min
#define min(a, b) ((a < b) ? a : b)
#endif
int libmpq_init_buffer(mpq_archive *mpq_a);
int libmpq_read_hashtable(mpq_archive *mpq_a);
int libmpq_read_blocktable(mpq_archive *mpq_a);
int libmpq_file_read_file(mpq_archive *mpq_a, mpq_file *mpq_f, unsigned int filepos, char *buffer, unsigned int toread);
int libmpq_read_listfile(mpq_archive *mpq_a, FILE *fp);
int libmpq_conf_get_value(FILE *fp, char *search_value, void *return_value, int type, int size);
char *libmpq_conf_delete_char(char *buf, char *chars);
int libmpq_conf_get_array(FILE *fp, char *search_value, char ***filelist, int *entries);
int libmpq_free_listfile(char **filelist);
int libmpq_read_listfile(mpq_archive *mpq_a, FILE *fp);
-429
View File
@@ -1,429 +0,0 @@
/*
* explode.c -- explode function of PKWARE data compression library.
*
* Copyright (C) 2003 Maik Broemme <mbroemme@plusserver.de>
*
* This source was adepted from the C++ version of pkware.cpp included
* in stormlib. The C++ version belongs to the following authors,
*
* Ladislav Zezula <ladik.zezula.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <assert.h>
#include <string.h>
#include "mpq.h"
#include "explode.h"
/* Tables */
static unsigned char pkzip_dist_bits[] = {
0x02, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
};
static unsigned char pkzip_dist_code[] = {
0x03, 0x0D, 0x05, 0x19, 0x09, 0x11, 0x01, 0x3E, 0x1E, 0x2E, 0x0E, 0x36, 0x16, 0x26, 0x06, 0x3A,
0x1A, 0x2A, 0x0A, 0x32, 0x12, 0x22, 0x42, 0x02, 0x7C, 0x3C, 0x5C, 0x1C, 0x6C, 0x2C, 0x4C, 0x0C,
0x74, 0x34, 0x54, 0x14, 0x64, 0x24, 0x44, 0x04, 0x78, 0x38, 0x58, 0x18, 0x68, 0x28, 0x48, 0x08,
0xF0, 0x70, 0xB0, 0x30, 0xD0, 0x50, 0x90, 0x10, 0xE0, 0x60, 0xA0, 0x20, 0xC0, 0x40, 0x80, 0x00
};
static unsigned char pkzip_clen_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08
};
static unsigned short pkzip_len_base[] = {
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
0x0008, 0x000A, 0x000E, 0x0016, 0x0026, 0x0046, 0x0086, 0x0106
};
static unsigned char pkzip_slen_bits[] = {
0x03, 0x02, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x07, 0x07
};
static unsigned char pkzip_len_code[] = {
0x05, 0x03, 0x01, 0x06, 0x0A, 0x02, 0x0C, 0x14, 0x04, 0x18, 0x08, 0x30, 0x10, 0x20, 0x40, 0x00
};
static unsigned char pkzip_bits_asc[] = {
0x0B, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x08, 0x07, 0x0C, 0x0C, 0x07, 0x0C, 0x0C,
0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
0x04, 0x0A, 0x08, 0x0C, 0x0A, 0x0C, 0x0A, 0x08, 0x07, 0x07, 0x08, 0x09, 0x07, 0x06, 0x07, 0x08,
0x07, 0x06, 0x07, 0x07, 0x07, 0x07, 0x08, 0x07, 0x07, 0x08, 0x08, 0x0C, 0x0B, 0x07, 0x09, 0x0B,
0x0C, 0x06, 0x07, 0x06, 0x06, 0x05, 0x07, 0x08, 0x08, 0x06, 0x0B, 0x09, 0x06, 0x07, 0x06, 0x06,
0x07, 0x0B, 0x06, 0x06, 0x06, 0x07, 0x09, 0x08, 0x09, 0x09, 0x0B, 0x08, 0x0B, 0x09, 0x0C, 0x08,
0x0C, 0x05, 0x06, 0x06, 0x06, 0x05, 0x06, 0x06, 0x06, 0x05, 0x0B, 0x07, 0x05, 0x06, 0x05, 0x05,
0x06, 0x0A, 0x05, 0x05, 0x05, 0x05, 0x08, 0x07, 0x08, 0x08, 0x0A, 0x0B, 0x0B, 0x0C, 0x0C, 0x0C,
0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D,
0x0D, 0x0D, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D
};
static unsigned short pkzip_code_asc[] = {
0x0490, 0x0FE0, 0x07E0, 0x0BE0, 0x03E0, 0x0DE0, 0x05E0, 0x09E0,
0x01E0, 0x00B8, 0x0062, 0x0EE0, 0x06E0, 0x0022, 0x0AE0, 0x02E0,
0x0CE0, 0x04E0, 0x08E0, 0x00E0, 0x0F60, 0x0760, 0x0B60, 0x0360,
0x0D60, 0x0560, 0x1240, 0x0960, 0x0160, 0x0E60, 0x0660, 0x0A60,
0x000F, 0x0250, 0x0038, 0x0260, 0x0050, 0x0C60, 0x0390, 0x00D8,
0x0042, 0x0002, 0x0058, 0x01B0, 0x007C, 0x0029, 0x003C, 0x0098,
0x005C, 0x0009, 0x001C, 0x006C, 0x002C, 0x004C, 0x0018, 0x000C,
0x0074, 0x00E8, 0x0068, 0x0460, 0x0090, 0x0034, 0x00B0, 0x0710,
0x0860, 0x0031, 0x0054, 0x0011, 0x0021, 0x0017, 0x0014, 0x00A8,
0x0028, 0x0001, 0x0310, 0x0130, 0x003E, 0x0064, 0x001E, 0x002E,
0x0024, 0x0510, 0x000E, 0x0036, 0x0016, 0x0044, 0x0030, 0x00C8,
0x01D0, 0x00D0, 0x0110, 0x0048, 0x0610, 0x0150, 0x0060, 0x0088,
0x0FA0, 0x0007, 0x0026, 0x0006, 0x003A, 0x001B, 0x001A, 0x002A,
0x000A, 0x000B, 0x0210, 0x0004, 0x0013, 0x0032, 0x0003, 0x001D,
0x0012, 0x0190, 0x000D, 0x0015, 0x0005, 0x0019, 0x0008, 0x0078,
0x00F0, 0x0070, 0x0290, 0x0410, 0x0010, 0x07A0, 0x0BA0, 0x03A0,
0x0240, 0x1C40, 0x0C40, 0x1440, 0x0440, 0x1840, 0x0840, 0x1040,
0x0040, 0x1F80, 0x0F80, 0x1780, 0x0780, 0x1B80, 0x0B80, 0x1380,
0x0380, 0x1D80, 0x0D80, 0x1580, 0x0580, 0x1980, 0x0980, 0x1180,
0x0180, 0x1E80, 0x0E80, 0x1680, 0x0680, 0x1A80, 0x0A80, 0x1280,
0x0280, 0x1C80, 0x0C80, 0x1480, 0x0480, 0x1880, 0x0880, 0x1080,
0x0080, 0x1F00, 0x0F00, 0x1700, 0x0700, 0x1B00, 0x0B00, 0x1300,
0x0DA0, 0x05A0, 0x09A0, 0x01A0, 0x0EA0, 0x06A0, 0x0AA0, 0x02A0,
0x0CA0, 0x04A0, 0x08A0, 0x00A0, 0x0F20, 0x0720, 0x0B20, 0x0320,
0x0D20, 0x0520, 0x0920, 0x0120, 0x0E20, 0x0620, 0x0A20, 0x0220,
0x0C20, 0x0420, 0x0820, 0x0020, 0x0FC0, 0x07C0, 0x0BC0, 0x03C0,
0x0DC0, 0x05C0, 0x09C0, 0x01C0, 0x0EC0, 0x06C0, 0x0AC0, 0x02C0,
0x0CC0, 0x04C0, 0x08C0, 0x00C0, 0x0F40, 0x0740, 0x0B40, 0x0340,
0x0300, 0x0D40, 0x1D00, 0x0D00, 0x1500, 0x0540, 0x0500, 0x1900,
0x0900, 0x0940, 0x1100, 0x0100, 0x1E00, 0x0E00, 0x0140, 0x1600,
0x0600, 0x1A00, 0x0E40, 0x0640, 0x0A40, 0x0A00, 0x1200, 0x0200,
0x1C00, 0x0C00, 0x1400, 0x0400, 0x1800, 0x0800, 0x1000, 0x0000
};
/* Local variables */
static char copyright[] = "PKWARE Data Compression Library for Win32\r\n"
"Copyright 1989-1995 PKWARE Inc. All Rights Reserved\r\n"
"Patent No. 5,051,745\r\n"
"PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off.\r\n"
"Version 1.11\r\n";
/* Local functions */
static void libmpq_pkzip_gen_decode_tabs(long count, unsigned char *bits, unsigned char *code, unsigned char *buf2) {
long i;
for (i = count-1; i >= 0; i--) { /* EBX - count */
unsigned long idx1 = code[i];
unsigned long idx2 = 1 << bits[i];
do {
buf2[idx1] = (unsigned char)i;
idx1 += idx2;
} while (idx1 < 0x100);
}
}
static void libmpq_pkzip_gen_asc_tabs(pkzip_data_cmp *mpq_pkzip) {
unsigned short *code_asc = &pkzip_code_asc[0xFF];
unsigned long acc, add;
unsigned short count;
for (count = 0x00FF; code_asc >= pkzip_code_asc; code_asc--, count--) {
unsigned char *bits_asc = mpq_pkzip->bits_asc + count;
unsigned char bits_tmp = *bits_asc;
if (bits_tmp <= 8) {
add = (1 << bits_tmp);
acc = *code_asc;
do {
mpq_pkzip->offs_2c34[acc] = (unsigned char)count;
acc += add;
} while (acc < 0x100);
} else {
if ((acc = (*code_asc & 0xFF)) != 0) {
mpq_pkzip->offs_2c34[acc] = 0xFF;
if (*code_asc & 0x3F) {
bits_tmp -= 4;
*bits_asc = bits_tmp;
add = (1 << bits_tmp);
acc = *code_asc >> 4;
do {
mpq_pkzip->offs_2d34[acc] = (unsigned char)count;
acc += add;
} while (acc < 0x100);
} else {
bits_tmp -= 6;
*bits_asc = bits_tmp;
add = (1 << bits_tmp);
acc = *code_asc >> 6;
do {
mpq_pkzip->offs_2e34[acc] = (unsigned char)count;
acc += add;
} while (acc < 0x80);
}
} else {
bits_tmp -= 8;
*bits_asc = bits_tmp;
add = (1 << bits_tmp);
acc = *code_asc >> 8;
do {
mpq_pkzip->offs_2eb4[acc] = (unsigned char)count;
acc += add;
} while (acc < 0x100);
}
}
}
}
/*
* Skips given number of bits in bit buffer. Result is stored in mpq_pkzip->bit_buf
* If no data in input buffer, returns true
*/
static int libmpq_pkzip_skip_bits(pkzip_data_cmp *mpq_pkzip, unsigned long bits) {
/* If number of bits required is less than number of (bits in the buffer) ? */
if (bits <= mpq_pkzip->extra_bits) {
mpq_pkzip->extra_bits -= bits;
mpq_pkzip->bit_buf >>= bits;
return 0;
}
/* Load input buffer if necessary */
mpq_pkzip->bit_buf >>= mpq_pkzip->extra_bits;
if (mpq_pkzip->in_pos == mpq_pkzip->in_bytes) {
mpq_pkzip->in_pos = sizeof(mpq_pkzip->in_buf);
if ((mpq_pkzip->in_bytes = mpq_pkzip->read_buf((char *)mpq_pkzip->in_buf, &mpq_pkzip->in_pos, mpq_pkzip->param)) == 0) {
return 1;
}
mpq_pkzip->in_pos = 0;
}
/* Update bit buffer */
mpq_pkzip->bit_buf |= (mpq_pkzip->in_buf[mpq_pkzip->in_pos++] << 8);
mpq_pkzip->bit_buf >>= (bits - mpq_pkzip->extra_bits);
mpq_pkzip->extra_bits = (mpq_pkzip->extra_bits - bits) + 8;
return 0;
}
/*
* Decompress the imploded data using coded literals.
* Returns: 0x000 - 0x0FF : One byte from compressed file.
* 0x100 - 0x305 : Copy previous block (0x100 = 1 byte)
* 0x306 : Out of buffer (?)
*/
static unsigned long libmpq_pkzip_explode_lit(pkzip_data_cmp *mpq_pkzip) {
unsigned long bits; /* Number of bits to skip */
unsigned long value; /* Position in buffers */
/* Test the current bit in byte buffer. If is not set, simply return the next byte. */
if (mpq_pkzip->bit_buf & 1) {
/* Skip current bit in the buffer. */
if (libmpq_pkzip_skip_bits(mpq_pkzip, 1)) {
return 0x306;
}
/* The next bits are position in buffers. */
value = mpq_pkzip->pos2[(mpq_pkzip->bit_buf & 0xFF)];
/* Get number of bits to skip */
if (libmpq_pkzip_skip_bits(mpq_pkzip, mpq_pkzip->slen_bits[value])) {
return 0x306;
}
if ((bits = mpq_pkzip->clen_bits[value]) != 0) {
unsigned long val2 = mpq_pkzip->bit_buf & ((1 << bits) - 1);
if (libmpq_pkzip_skip_bits(mpq_pkzip, bits)) {
if ((value + val2) != 0x10E) {
return 0x306;
}
}
value = mpq_pkzip->len_base[value] + val2;
}
return value + 0x100; /* Return number of bytes to repeat */
}
/* Skip one bit */
if (libmpq_pkzip_skip_bits(mpq_pkzip, 1)) {
return 0x306;
}
/* If the binary compression type, read 8 bits and return them as one byte. */
if (mpq_pkzip->cmp_type == LIBMPQ_PKZIP_CMP_BINARY) {
value = mpq_pkzip->bit_buf & 0xFF;
if (libmpq_pkzip_skip_bits(mpq_pkzip, 8)) {
return 0x306;
}
return value;
}
/* When ASCII compression ... */
if (mpq_pkzip->bit_buf & 0xFF) {
value = mpq_pkzip->offs_2c34[mpq_pkzip->bit_buf & 0xFF];
if (value == 0xFF) {
if (mpq_pkzip->bit_buf & 0x3F) {
if (libmpq_pkzip_skip_bits(mpq_pkzip, 4)) {
return 0x306;
}
value = mpq_pkzip->offs_2d34[mpq_pkzip->bit_buf & 0xFF];
} else {
if (libmpq_pkzip_skip_bits(mpq_pkzip, 6)) {
return 0x306;
}
value = mpq_pkzip->offs_2e34[mpq_pkzip->bit_buf & 0x7F];
}
}
} else {
if (libmpq_pkzip_skip_bits(mpq_pkzip, 8)) {
return 0x306;
}
value = mpq_pkzip->offs_2eb4[mpq_pkzip->bit_buf & 0xFF];
}
return libmpq_pkzip_skip_bits(mpq_pkzip, mpq_pkzip->bits_asc[value]) ? 0x306 : value;
}
/*
* Retrieves the number of bytes to move back.
*/
static unsigned long libmpq_pkzip_explode_dist(pkzip_data_cmp *mpq_pkzip, unsigned long length) {
unsigned long pos = mpq_pkzip->pos1[(mpq_pkzip->bit_buf & 0xFF)];
unsigned long skip = mpq_pkzip->dist_bits[pos]; /* Number of bits to skip */
/* Skip the appropriate number of bits */
if (libmpq_pkzip_skip_bits(mpq_pkzip, skip) == 1) {
return 0;
}
if (length == 2) {
pos = (pos << 2) | (mpq_pkzip->bit_buf & 0x03);
if (libmpq_pkzip_skip_bits(mpq_pkzip, 2) == 1) {
return 0;
}
} else {
pos = (pos << mpq_pkzip->dsize_bits) | (mpq_pkzip->bit_buf & mpq_pkzip->dsize_mask);
/* Skip the bits */
if (libmpq_pkzip_skip_bits(mpq_pkzip, mpq_pkzip->dsize_bits) == 1) {
return 0;
}
}
return pos + 1;
}
static unsigned long libmpq_pkzip_expand(pkzip_data_cmp *mpq_pkzip) {
unsigned int copy_bytes; /* Number of bytes to copy */
unsigned long one_byte; /* One byte from compressed file */
unsigned long result;
mpq_pkzip->out_pos = 0x1000; /* Initialize output buffer position */
/* If end of data or error, terminate decompress */
while ((result = one_byte = libmpq_pkzip_explode_lit(mpq_pkzip)) < 0x305) {
/* If one byte is greater than 0x100, means "Repeat n - 0xFE bytes" */
if (one_byte >= 0x100) {
unsigned char *source; /* ECX */
unsigned char *target; /* EDX */
unsigned long copy_length = one_byte - 0xFE;
unsigned long move_back;
/* Get length of data to copy */
if ((move_back = libmpq_pkzip_explode_dist(mpq_pkzip, copy_length)) == 0) {
result = 0x306;
break;
}
/* Target and source pointer */
target = &mpq_pkzip->out_buf[mpq_pkzip->out_pos];
source = target - move_back;
mpq_pkzip->out_pos += copy_length;
while (copy_length-- > 0) {
*target++ = *source++;
}
} else {
mpq_pkzip->out_buf[mpq_pkzip->out_pos++] = (unsigned char)one_byte;
}
/*
* If number of extracted bytes has reached 1/2 of output buffer,
* flush output buffer.
*/
if (mpq_pkzip->out_pos >= 0x2000) {
/* Copy decompressed data into user buffer. */
copy_bytes = 0x1000;
mpq_pkzip->write_buf((char *)&mpq_pkzip->out_buf[0x1000], &copy_bytes, mpq_pkzip->param);
/* If there are some data left, keep them alive */
memcpy(mpq_pkzip->out_buf, &mpq_pkzip->out_buf[0x1000], mpq_pkzip->out_pos - 0x1000);
mpq_pkzip->out_pos -= 0x1000;
}
}
copy_bytes = mpq_pkzip->out_pos - 0x1000;
mpq_pkzip->write_buf((char *)&mpq_pkzip->out_buf[0x1000], &copy_bytes, mpq_pkzip->param);
return result;
}
/*
* Main exploding function.
*/
unsigned int libmpq_pkzip_explode(
unsigned int (*read_buf)(char *buf, unsigned int *size, void *param),
void (*write_buf)(char *buf, unsigned int *size, void *param),
char *work_buf,
void *param) {
pkzip_data_cmp *mpq_pkzip = (pkzip_data_cmp *)work_buf;
/* Set the whole work buffer to zeros */
memset(mpq_pkzip, 0, sizeof(pkzip_data_cmp));
/* Initialize work struct and load compressed data */
mpq_pkzip->read_buf = read_buf;
mpq_pkzip->write_buf = write_buf;
mpq_pkzip->param = param;
mpq_pkzip->in_pos = sizeof(mpq_pkzip->in_buf);
mpq_pkzip->in_bytes = mpq_pkzip->read_buf((char *)mpq_pkzip->in_buf, &mpq_pkzip->in_pos, mpq_pkzip->param);
if (mpq_pkzip->in_bytes <= 4) {
return LIBMPQ_PKZIP_CMP_BAD_DATA;
}
mpq_pkzip->cmp_type = mpq_pkzip->in_buf[0]; /* Get the compression type */
mpq_pkzip->dsize_bits = mpq_pkzip->in_buf[1]; /* Get the dictionary size */
mpq_pkzip->bit_buf = mpq_pkzip->in_buf[2]; /* Initialize 16-bit bit buffer */
mpq_pkzip->extra_bits = 0; /* Extra (over 8) bits */
mpq_pkzip->in_pos = 3; /* Position in input buffer */
/* Test for the valid dictionary size */
if (4 > mpq_pkzip->dsize_bits || mpq_pkzip->dsize_bits > 6) {
return LIBMPQ_PKZIP_CMP_INV_DICTSIZE;
}
mpq_pkzip->dsize_mask = 0xFFFF >> (0x10 - mpq_pkzip->dsize_bits); /* Shifted by 'sar' instruction */
if (mpq_pkzip->cmp_type != LIBMPQ_PKZIP_CMP_BINARY) {
if (mpq_pkzip->cmp_type != LIBMPQ_PKZIP_CMP_ASCII) {
return LIBMPQ_PKZIP_CMP_INV_MODE;
}
memcpy(mpq_pkzip->bits_asc, pkzip_bits_asc, sizeof(mpq_pkzip->bits_asc));
libmpq_pkzip_gen_asc_tabs(mpq_pkzip);
}
memcpy(mpq_pkzip->slen_bits, pkzip_slen_bits, sizeof(mpq_pkzip->slen_bits));
libmpq_pkzip_gen_decode_tabs(0x10, mpq_pkzip->slen_bits, pkzip_len_code, mpq_pkzip->pos2);
memcpy(mpq_pkzip->clen_bits, pkzip_clen_bits, sizeof(mpq_pkzip->clen_bits));
memcpy(mpq_pkzip->len_base, pkzip_len_base, sizeof(mpq_pkzip->len_base));
memcpy(mpq_pkzip->dist_bits, pkzip_dist_bits, sizeof(mpq_pkzip->dist_bits));
libmpq_pkzip_gen_decode_tabs(0x40, mpq_pkzip->dist_bits, pkzip_dist_code, mpq_pkzip->pos1);
if (libmpq_pkzip_expand(mpq_pkzip) != 0x306) {
return LIBMPQ_PKZIP_CMP_NO_ERROR;
}
return LIBMPQ_PKZIP_CMP_ABORT;
}
-87
View File
@@ -1,87 +0,0 @@
/*
* explode.h -- header file for PKWARE data decompression library
* used by mpq-tools.
*
* Copyright (C) 2003 Maik Broemme <mbroemme@plusserver.de>
*
* This source was adepted from the C++ version of pklib.h included
* in stormlib. The C++ version belongs to the following authors,
*
* Ladislav Zezula <ladik.zezula.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _EXPLODE_H
#define _EXPLODE_H
#define LIBMPQ_PKZIP_EXP_BUFFER_SIZE 12596 /* Size of decompress buffer */
#define LIBMPQ_PKZIP_CMP_BINARY 0 /* Binary compression */
#define LIBMPQ_PKZIP_CMP_ASCII 1 /* Ascii compression */
#define LIBMPQ_PKZIP_CMP_NO_ERROR 0
#define LIBMPQ_PKZIP_CMP_INV_DICTSIZE 1
#define LIBMPQ_PKZIP_CMP_INV_MODE 2
#define LIBMPQ_PKZIP_CMP_BAD_DATA 3
#define LIBMPQ_PKZIP_CMP_ABORT 4
/* Compression structure (size: 12596 bytes on x86-32) */
typedef struct {
unsigned long offs0000; /* 0000 */
unsigned long cmp_type; /* 0004 - Compression type (LIBMPQ_PZIP_CMP_BINARY or LIBMPQ_PKZIP_CMP_ASCII) */
unsigned long out_pos; /* 0008 - Position in output buffer */
unsigned long dsize_bits; /* 000C - Dict size (4, 5, 6 for 0x400, 0x800, 0x1000) */
unsigned long dsize_mask; /* 0010 - Dict size bitmask (0x0F, 0x1F, 0x3F for 0x400, 0x800, 0x1000) */
unsigned long bit_buf; /* 0014 - 16-bit buffer for processing input data */
unsigned long extra_bits; /* 0018 - Number of extra (above 8) bits in bit buffer */
unsigned int in_pos; /* 001C - Position in in_buf */
unsigned long in_bytes; /* 0020 - Number of bytes in input buffer */
void *param; /* 0024 - Custom parameter */
unsigned int (*read_buf)(char *buf, unsigned int *size, void *param); /* 0028 */
void (*write_buf)(char *buf, unsigned int *size, void *param); /* 002C */
unsigned char out_buf[0x2000]; /* 0030 - Output circle buffer. Starting position is 0x1000 */
unsigned char offs_2030[0x204]; /* 2030 - ??? */
unsigned char in_buf[0x800]; /* 2234 - Buffer for data to be decompressed */
unsigned char pos1[0x100]; /* 2A34 - Positions in buffers */
unsigned char pos2[0x100]; /* 2B34 - Positions in buffers */
unsigned char offs_2c34[0x100]; /* 2C34 - Buffer for */
unsigned char offs_2d34[0x100]; /* 2D34 - Buffer for */
unsigned char offs_2e34[0x80]; /* 2EB4 - Buffer for */
unsigned char offs_2eb4[0x100]; /* 2EB4 - Buffer for */
unsigned char bits_asc[0x100]; /* 2FB4 - Buffer for */
unsigned char dist_bits[0x40]; /* 30B4 - Numbers of bytes to skip copied block length */
unsigned char slen_bits[0x10]; /* 30F4 - Numbers of bits for skip copied block length */
unsigned char clen_bits[0x10]; /* 3104 - Number of valid bits for copied block */
unsigned short len_base[0x10]; /* 3114 - Buffer for */
} pkzip_data_cmp;
// __attribute__ ((packed)) pkzip_data_cmp;
typedef struct {
char *in_buf; /* Pointer to input data buffer */
unsigned int in_pos; /* Current offset in input data buffer */
int in_bytes; /* Number of bytes in the input buffer */
char *out_buf; /* Pointer to output data buffer */
unsigned int out_pos; /* Position in the output buffer */
int max_out; /* Maximum number of bytes in the output buffer */
} pkzip_data;
extern unsigned int libmpq_pkzip_explode(
unsigned int (*read_buf)(char *buf, unsigned int *size, void *param),
void (*write_buf)(char *buf, unsigned int *size, void *param),
char *work_buf,
void *param
);
#endif /* _EXPLODE_H */
-263
View File
@@ -1,263 +0,0 @@
/*
* extract.c -- global extracting function for all known file compressions
* in a MPQ archive.
*
* Copyright (C) 2003 Maik Broemme <mbroemme@plusserver.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define HAVE_LIBZ
#ifdef HAVE_LIBZ
#include <zlib.h>
#endif
#include "mpq.h"
#include "explode.h"
#include "huffman.h"
#include "wave.h"
/*
* Support functions for PKWARE data compression library.
*
* Function loads data from the input buffer. Used by mpq_pkzip
* "implode" and "explode" function as user-defined callback.
* Returns number of bytes loaded.
*
* char * buf - Pointer to a buffer where to store loaded data
* unsigned int * size - Max. number of bytes to read
* void * param - Custom pointer, parameter of implode/explode
*/
static unsigned int libmpq_pkzip_read_input_data(char *buf, unsigned int *size, void *param) {
pkzip_data *info = (pkzip_data *)param;
unsigned int max_avail = (info->in_bytes - info->in_pos);
unsigned int to_read = *size;
/* Check the case when not enough data available */
if (to_read > max_avail) {
to_read = max_avail;
}
/* Load data and increment offsets */
memcpy(buf, info->in_buf + info->in_pos, to_read);
info->in_pos += to_read;
return to_read;
}
/*
* Support functions for PKWARE data compression library.
*
* Function for store output data. Used by mpq_pkzip "implode" and
* "explode" as user-defined callback.
*
* char * buf - Pointer to data to be written
* unsigned int * size - Number of bytes to write
* void * param - Custom pointer, parameter of implode/explode
*/
static void libmpq_pkzip_write_output_data(char *buf, unsigned int *size, void *param) {
pkzip_data *info = (pkzip_data *)param;
unsigned int max_write = (info->max_out - info->out_pos);
unsigned int to_write = *size;
/* Check the case when not enough space in the output buffer */
if (to_write > max_write) {
to_write = max_write;
}
/* Write output data and increments offsets */
memcpy(info->out_buf + info->out_pos, buf, to_write);
info->out_pos += to_write;
}
int libmpq_pkzip_decompress(char *out_buf, int *out_length, char *in_buf, int in_length) {
pkzip_data info; /* Data information */
char *work_buf = (char *)malloc(LIBMPQ_PKZIP_EXP_BUFFER_SIZE); /* mpq_pkzip work buffer */
/* Fill data information structure */
info.in_buf = in_buf;
info.in_pos = 0;
info.in_bytes = in_length;
info.out_buf = out_buf;
info.out_pos = 0;
info.max_out = *out_length;
/* Do the decompression */
libmpq_pkzip_explode(libmpq_pkzip_read_input_data, libmpq_pkzip_write_output_data, work_buf, &info);
*out_length = info.out_pos;
free(work_buf);
return 0;
}
int libmpq_wave_decompress_mono(char *out_buf, int *out_length, char *in_buf, int in_length) {
*out_length = libmpq_wave_decompress((unsigned char *)out_buf, *out_length, (unsigned char *)in_buf, in_length, 1);
return 1;
}
int libmpq_wave_decompress_stereo(char *out_buf, int *out_length, char *in_buf, int in_length) {
*out_length = libmpq_wave_decompress((unsigned char *)out_buf, *out_length, (unsigned char *)in_buf, in_length, 2);
return 1;
}
int libmpq_zlib_decompress(char *out_buf, int *out_length, char *in_buf, int in_length) {
#ifdef HAVE_LIBZ
z_stream z; /* Stream information for zlib */
int result;
/* Fill the stream structure for zlib */
z.next_in = (Bytef *)in_buf;
z.avail_in = (uInt)in_length;
z.total_in = in_length;
z.next_out = (Bytef *)out_buf;
z.avail_out = *out_length;
z.total_out = 0;
z.zalloc = NULL;
z.zfree = NULL;
/* Initialize the decompression structure. Storm.dll uses zlib version 1.1.3 */
if ((result = inflateInit(&z)) == 0) {
/* Call zlib to decompress the data */
result = inflate(&z, Z_FINISH);
*out_length = z.total_out;
inflateEnd(&z);
}
return result;
#else
memset(out_buf, '0', *out_length);
return 0;
#endif
}
/*
* Huffmann decompression routine. The in_length parameter is not used, but needs
* to be specified due to compatibility reasons.
*
* 1500F5F0
*/
int libmpq_huff_decompress(char *out_buf, int *out_length, char *in_buf, int in_length) {
struct huffman_tree *ht = (huffman_tree *)malloc(sizeof(struct huffman_tree));
struct huffman_input_stream *is = (huffman_input_stream *)malloc(sizeof(struct huffman_input_stream));
struct huffman_tree_item *hi = (huffman_tree_item *)malloc(sizeof(struct huffman_tree_item));
memset(ht, 0, sizeof(struct huffman_tree));
memset(is, 0, sizeof(struct huffman_input_stream));
memset(hi, 0, sizeof(struct huffman_tree_item));
/* Initialize input stream */
is->bit_buf = *(unsigned long *)in_buf;
in_buf += sizeof(unsigned long);
is->in_buf = (unsigned char *)in_buf;
is->bits = 32;
/* Initialize the Huffmann tree for decompression */
libmpq_huff_init_tree(ht, hi, LIBMPQ_HUFF_DECOMPRESS);
*out_length = libmpq_huff_do_decompress(ht, is, (unsigned char *)out_buf, *out_length);
free(hi);
free(is);
free(ht);
return 0;
}
int libmpq_multi_decompress(char *out_buf, int *pout_length, char *in_buf, int in_length) {
char *temp_buf = NULL; /* Temporary storage for decompressed data */
char *work_buf = NULL; /* Where to store decompressed data */
int out_length = *pout_length; /* For storage number of output bytes */
unsigned fDecompressions1; /* Decompressions applied to the block */
unsigned fDecompressions2; /* Just another copy of decompressions applied to the block */
int count = 0; /* Counter for every use */
int entries = (sizeof(dcmp_table) / sizeof(decompress_table));
int i;
/* If the input length is the same as output, do nothing. */
if (in_length == out_length) {
if (in_buf == out_buf) {
return 1;
}
memcpy(out_buf, in_buf, in_length);
return 1;
}
/* Get applied compression types and decrement data length */
fDecompressions1 = fDecompressions2 = (unsigned char)*in_buf++;
in_length--;
/* Search decompression table type and get all types of compression */
for (i = 0; i < entries; i++) {
/* We have to apply this decompression? */
if (fDecompressions1 & dcmp_table[i].mask) {
count++;
}
/* Clear this flag from temporary variable. */
fDecompressions2 &= ~dcmp_table[i].mask;
}
/*
* Check if there is some method unhandled
* (E.g. compressed by future versions)
*/
if (fDecompressions2 != 0) {
printf("Unknown Compression\n");
return 0;
}
/* If there is more than only one compression, we have to allocate extra buffer */
if (count >= 2) {
temp_buf = (char *)malloc(out_length);
}
/* Apply all decompressions */
for (i = 0, count = 0; i < entries; i++) {
/* If not used this kind of compression, skip the loop */
if (fDecompressions1 & dcmp_table[i].mask) {
/* If odd case, use target buffer for output, otherwise use allocated tempbuf */
work_buf = (count++ & 1) ? temp_buf : out_buf;
out_length = *pout_length;
/* Decompress buffer using corresponding function */
dcmp_table[i].decompress(work_buf, &out_length, in_buf, in_length);
/* Move output length to src length for next compression */
in_length = out_length;
in_buf = work_buf;
}
}
/* If output buffer is not the same like target buffer, we have to copy data */
if (work_buf != out_buf) {
memcpy(out_buf, in_buf, out_length);
}
*pout_length = out_length;
/* Delete temporary buffer, if necessary */
if (temp_buf != NULL) {
free(temp_buf);
}
return 1;
}
-834
View File
@@ -1,834 +0,0 @@
/*
* huffman.c -- functions do decompress files in MPQ files which
* uses a modified huffman version.
*
* Copyright (C) 2003 Maik Broemme <mbroemme@plusserver.de>
*
* Differences between C++ and C version:
*
* - Removed the object oriented stuff.
* - Replaced the goto things with some better C code.
*
* This source was adepted from the C++ version of huffman.cpp included
* in stormlib. The C++ version belongs to the following authors,
*
* Ladislav Zezula <ladik.zezula.net>
* ShadowFlare <BlakFlare@hotmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdlib.h>
#include <string.h>
#include "mpq.h"
#include "huffman.h"
unsigned char table1502A630[] = {
/* Data for compression type 0x00 */
0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
0x00, 0x00,
/* Data for compression type 0x01 */
0x54, 0x16, 0x16, 0x0D, 0x0C, 0x08, 0x06, 0x05, 0x06, 0x05, 0x06, 0x03, 0x04, 0x04, 0x03, 0x05,
0x0E, 0x0B, 0x14, 0x13, 0x13, 0x09, 0x0B, 0x06, 0x05, 0x04, 0x03, 0x02, 0x03, 0x02, 0x02, 0x02,
0x0D, 0x07, 0x09, 0x06, 0x06, 0x04, 0x03, 0x02, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02,
0x09, 0x06, 0x04, 0x04, 0x04, 0x04, 0x03, 0x02, 0x03, 0x02, 0x02, 0x02, 0x02, 0x03, 0x02, 0x04,
0x08, 0x03, 0x04, 0x07, 0x09, 0x05, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x03, 0x02, 0x02,
0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02,
0x06, 0x0A, 0x08, 0x08, 0x06, 0x07, 0x04, 0x03, 0x04, 0x04, 0x02, 0x02, 0x04, 0x02, 0x03, 0x03,
0x04, 0x03, 0x07, 0x07, 0x09, 0x06, 0x04, 0x03, 0x03, 0x02, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02,
0x0A, 0x02, 0x02, 0x03, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x06, 0x03, 0x05, 0x02, 0x03,
0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x03, 0x01, 0x01, 0x01,
0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x04, 0x04, 0x04, 0x07, 0x09, 0x08, 0x0C, 0x02,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x03,
0x04, 0x01, 0x02, 0x04, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01,
0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x06, 0x4B,
0x00, 0x00,
/* Data for compression type 0x02 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x27, 0x00, 0x00, 0x23, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xFF, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x06, 0x0E, 0x10, 0x04,
0x06, 0x08, 0x05, 0x04, 0x04, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03, 0x01, 0x01, 0x02, 0x01, 0x01,
0x01, 0x04, 0x02, 0x04, 0x02, 0x02, 0x02, 0x01, 0x01, 0x04, 0x01, 0x01, 0x02, 0x03, 0x03, 0x02,
0x03, 0x01, 0x03, 0x06, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x01, 0x01,
0x01, 0x29, 0x07, 0x16, 0x12, 0x40, 0x0A, 0x0A, 0x11, 0x25, 0x01, 0x03, 0x17, 0x10, 0x26, 0x2A,
0x10, 0x01, 0x23, 0x23, 0x2F, 0x10, 0x06, 0x07, 0x02, 0x09, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00,
/* Data for compression type 0x03 */
0xFF, 0x0B, 0x07, 0x05, 0x0B, 0x02, 0x02, 0x02, 0x06, 0x02, 0x02, 0x01, 0x04, 0x02, 0x01, 0x03,
0x09, 0x01, 0x01, 0x01, 0x03, 0x04, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01,
0x05, 0x01, 0x01, 0x01, 0x0D, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01,
0x0A, 0x04, 0x02, 0x01, 0x06, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x01,
0x05, 0x02, 0x03, 0x04, 0x03, 0x03, 0x03, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x03, 0x03,
0x01, 0x03, 0x01, 0x01, 0x02, 0x05, 0x01, 0x01, 0x04, 0x03, 0x05, 0x01, 0x03, 0x01, 0x03, 0x03,
0x02, 0x01, 0x04, 0x03, 0x0A, 0x06, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x02, 0x02, 0x01, 0x0A, 0x02, 0x05, 0x01, 0x01, 0x02, 0x07, 0x02, 0x17, 0x01, 0x05, 0x01, 0x01,
0x0E, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x06, 0x02, 0x01, 0x04, 0x05, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01,
0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x11,
0x00, 0x00,
/* Data for compression type 0x04 */
0xFF, 0xFB, 0x98, 0x9A, 0x84, 0x85, 0x63, 0x64, 0x3E, 0x3E, 0x22, 0x22, 0x13, 0x13, 0x18, 0x17,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00,
/* Data for compression type 0x05 */
0xFF, 0xF1, 0x9D, 0x9E, 0x9A, 0x9B, 0x9A, 0x97, 0x93, 0x93, 0x8C, 0x8E, 0x86, 0x88, 0x80, 0x82,
0x7C, 0x7C, 0x72, 0x73, 0x69, 0x6B, 0x5F, 0x60, 0x55, 0x56, 0x4A, 0x4B, 0x40, 0x41, 0x37, 0x37,
0x2F, 0x2F, 0x27, 0x27, 0x21, 0x21, 0x1B, 0x1C, 0x17, 0x17, 0x13, 0x13, 0x10, 0x10, 0x0D, 0x0D,
0x0B, 0x0B, 0x09, 0x09, 0x08, 0x08, 0x07, 0x07, 0x06, 0x05, 0x05, 0x04, 0x04, 0x04, 0x19, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00,
/* Data for compression type 0x06 */
0xC3, 0xCB, 0xF5, 0x41, 0xFF, 0x7B, 0xF7, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xBF, 0xCC, 0xF2, 0x40, 0xFD, 0x7C, 0xF7, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x7A, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00,
/* Data for compression type 0x07 */
0xC3, 0xD9, 0xEF, 0x3D, 0xF9, 0x7C, 0xE9, 0x1E, 0xFD, 0xAB, 0xF1, 0x2C, 0xFC, 0x5B, 0xFE, 0x17,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xBD, 0xD9, 0xEC, 0x3D, 0xF5, 0x7D, 0xE8, 0x1D, 0xFB, 0xAE, 0xF0, 0x2C, 0xFB, 0x5C, 0xFF, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x70, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00,
/* Data for compression type 0x08 */
0xBA, 0xC5, 0xDA, 0x33, 0xE3, 0x6D, 0xD8, 0x18, 0xE5, 0x94, 0xDA, 0x23, 0xDF, 0x4A, 0xD1, 0x10,
0xEE, 0xAF, 0xE4, 0x2C, 0xEA, 0x5A, 0xDE, 0x15, 0xF4, 0x87, 0xE9, 0x21, 0xF6, 0x43, 0xFC, 0x12,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xB0, 0xC7, 0xD8, 0x33, 0xE3, 0x6B, 0xD6, 0x18, 0xE7, 0x95, 0xD8, 0x23, 0xDB, 0x49, 0xD0, 0x11,
0xE9, 0xB2, 0xE2, 0x2B, 0xE8, 0x5C, 0xDD, 0x15, 0xF1, 0x87, 0xE7, 0x20, 0xF7, 0x44, 0xFF, 0x13,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x5F, 0x9E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00
};
/* Gets previous Huffman tree item (?) */
struct huffman_tree_item *libmpq_huff_get_prev_item(struct huffman_tree_item *hi, long value) {
if (PTR_INT(hi->prev) < 0) {
return PTR_NOT(hi->prev);
}
if (value < 0) {
value = hi - hi->next->prev;
}
return hi->prev + value;
}
/* 1500BC90 */
static void libmpq_huff_remove_item(struct huffman_tree_item *hi) {
struct huffman_tree_item *temp; /* EDX */
if (hi->next != NULL) {
temp = hi->prev;
if (PTR_INT(temp) <= 0) {
temp = PTR_NOT(temp);
} else {
temp += (hi - hi->next->prev);
}
temp->next = hi->next;
hi->next->prev = hi->prev;
hi->next = hi->prev = NULL;
}
}
static void libmpq_huff_insert_item(struct huffman_tree_item **p_item, struct huffman_tree_item *item, unsigned long where, struct huffman_tree_item *item2) {
struct huffman_tree_item *next = item->next; /* EDI - next to the first item */
struct huffman_tree_item *prev = item->prev; /* ESI - prev to the first item */
struct huffman_tree_item *prev2; /* Pointer to previous item */
long next2; /* Pointer to the next item */
/* The same code like in mpq_huff_remove_item(); */
if (next != 0) { /* If the first item already has next one */
if (PTR_INT(prev) < 0) {
prev = PTR_NOT(prev);
} else {
prev += (item - next->prev);
}
/*
* 150083C1
* Remove the item from the tree
*/
prev->next = next;
next->prev = prev;
/* Invalidate 'prev' and 'next' pointer */
item->next = 0;
item->prev = 0;
}
if (item2 == NULL) { /* EDX - If the second item is not entered, */
item2 = PTR_PTR(&p_item[1]); /* take the first tree item */
}
switch (where) {
case SWITCH_ITEMS: /* Switch the two items */
item->next = item2->next; /* item2->next (Pointer to pointer to first) */
item->prev = item2->next->prev;
item2->next->prev = item;
item2->next = item; /* Set the first item */
return;
case INSERT_ITEM: /* Insert as the last item */
item->next = item2; /* Set next item (or pointer to pointer to first item) */
item->prev = item2->prev; /* Set prev item (or last item in the tree) */
next2 = PTR_INT(p_item[0]); /* Usually NULL */
prev2 = item2->prev; /* Prev item to the second (or last tree item) */
if (PTR_INT(prev2) < 0) {
prev2 = PTR_NOT(prev);
prev2->next = item;
item2->prev = item; /* Next after last item */
return;
}
if (next2 < 0) {
next2 = item2 - item2->next->prev;
}
prev2 += next2;
prev2->next = item;
item2->prev = item; /* Set the next/last item */
return;
default:
return;
}
}
/* Builds Huffman tree. Called with the first 8 bits loaded from input stream. */
static void libmpq_huff_build_tree(struct huffman_tree *ht, unsigned int cmp_type) {
unsigned long max_byte; /* [ESP+10] - The greatest character found in table */
unsigned char *byte_array; /* [ESP+1C] - Pointer to unsigned char in table1502A630 */
unsigned long i; /* egcs in linux doesn't like multiple for loops without an explicit i */
unsigned int found; /* Thats needed to replace the goto stuff from original source :) */
struct huffman_tree_item **p_item; /* [ESP+14] - Pointer to Huffman tree item pointer array */
struct huffman_tree_item *child1;
/* Loop while pointer has a negative value. */
while (PTR_INT(ht->last) > 0) { /* ESI - Last entry */
struct huffman_tree_item *temp; /* EAX */
if (ht->last->next != NULL) { /* ESI->next */
libmpq_huff_remove_item(ht->last);
}
ht->item3058 = PTR_PTR(&ht->item3054);/* [EDI+4] */
ht->last->prev = ht->item3058; /* EAX */
temp = libmpq_huff_get_prev_item(PTR_PTR(&ht->item3054), PTR_INT(&ht->item3050));
temp->next = ht->last;
ht->item3054 = ht->last;
}
/* Clear all pointers in huffman tree item array. */
memset(ht->items306C, 0, sizeof(ht->items306C));
max_byte = 0; /* Greatest character found init to zero. */
p_item = (struct huffman_tree_item **)&ht->items306C; /* Pointer to current entry in huffman tree item pointer array */
/* Ensure we have low 8 bits only */
cmp_type &= 0xFF;
byte_array = table1502A630 + cmp_type * 258; /* EDI also */
for (i = 0; i < 0x100; i++, p_item++) {
struct huffman_tree_item *item = ht->item3058; /* Item to be created */
struct huffman_tree_item *p_item3 = ht->item3058;
unsigned char one_byte = byte_array[i];
/* Skip all the bytes which are zero. */
if (byte_array[i] == 0) {
continue;
}
/* If not valid pointer, take the first available item in the array. */
if (PTR_INT(item) <= 0) {
item = &ht->items0008[ht->items++];
}
/* Insert this item as the top of the tree. */
libmpq_huff_insert_item(&ht->item305C, item, SWITCH_ITEMS, NULL);
item->parent = NULL; /* Invalidate child and parent */
item->child = NULL;
*p_item = item; /* Store pointer into pointer array */
item->dcmp_byte = i; /* Store counter */
item->byte_value = one_byte; /* Store byte value */
if (one_byte >= max_byte) {
max_byte = one_byte;
continue;
}
/* Find the first item which has byte value greater than current one byte */
found = 0;
if (PTR_INT((p_item3 = ht->last)) > 0) {/* EDI - Pointer to the last item */
/* 15006AF7 */
if (p_item3 != NULL) {
do { /* 15006AFB */
if (p_item3->byte_value >= one_byte) {
found = 1;
break;
}
p_item3 = p_item3->prev;
} while (PTR_INT(p_item3) > 0);
}
}
if (found == 0) {
p_item3 = NULL;
}
/* 15006B09 */
if (item->next != NULL) {
libmpq_huff_remove_item(item);
}
/* 15006B15 */
if (p_item3 == NULL) {
p_item3 = PTR_PTR(&ht->first);
}
/* 15006B1F */
item->next = p_item3->next;
item->prev = p_item3->next->prev;
p_item3->next->prev = item;
p_item3->next = item;
}
/* 15006B4A */
for (; i < 0x102; i++) {
struct huffman_tree_item **p_item2 = &ht->items306C[i]; /* EDI */
/* 15006B59 */
struct huffman_tree_item *item2 = ht->item3058; /* ESI */
if (PTR_INT(item2) <= 0) {
item2 = &ht->items0008[ht->items++];
}
libmpq_huff_insert_item(&ht->item305C, item2, INSERT_ITEM, NULL);
/* 15006B89 */
item2->dcmp_byte = i;
item2->byte_value = 1;
item2->parent = NULL;
item2->child = NULL;
*p_item2++ = item2;
}
/* 15006BAA */
if (PTR_INT((child1 = ht->last)) > 0) { /* EDI - last item (first child to item */
struct huffman_tree_item *child2; /* EBP */
struct huffman_tree_item *item; /* ESI */
/* 15006BB8 */
while (PTR_INT((child2 = child1->prev)) > 0) {
if (PTR_INT((item = ht->item3058)) <= 0) {
item = &ht->items0008[ht->items++];
}
/* 15006BE3 */
libmpq_huff_insert_item(&ht->item305C, item, SWITCH_ITEMS, NULL);
/* 15006BF3 */
item->parent = NULL;
item->child = NULL;
/*
* EDX = child2->byte_value + child1->byte_value;
* EAX = child1->byte_value;
* ECX = max_byte; The greatest character (0xFF usually)
*/
item->byte_value = child1->byte_value + child2->byte_value; /* 0x02 */
item->child = child1; /* Prev item in the */
child1->parent = item;
child2->parent = item;
/* EAX = item->byte_value; */
if (item->byte_value >= max_byte) {
max_byte = item->byte_value;
} else {
struct huffman_tree_item *p_item2 = child2->prev; /* EDI */
found = 0;
if (PTR_INT(p_item2) > 0) {
/* 15006C2D */
do {
if (p_item2->byte_value >= item->byte_value) {
found = 1;
break;
}
p_item2 = p_item2->prev;
} while (PTR_INT(p_item2) > 0);
}
if (found == 0) {
p_item2 = NULL;
}
if (item->next != 0) {
struct huffman_tree_item *temp4 = libmpq_huff_get_prev_item(item, -1);
temp4->next = item->next; /* The first item changed */
item->next->prev = item->prev; /* First->prev changed to negative value */
item->next = NULL;
item->prev = NULL;
}
/* 15006C62 */
if (p_item2 == NULL) {
p_item2 = PTR_PTR(&ht->first);
}
item->next = p_item2->next; /* Set item with 0x100 byte value */
item->prev = p_item2->next->prev; /* Set item with 0x17 byte value */
p_item2->next->prev = item; /* Changed prev of item with */
p_item2->next = item;
}
/* 15006C7B */
if (PTR_INT((child1 = child2->prev)) <= 0) {
break;
}
}
}
/* 15006C88 */
ht->offs0004 = 1;
}
/* Gets the whole byte from the input stream. */
static unsigned long libmpq_huff_get_8bits(struct huffman_input_stream *is) {
unsigned long one_byte;
if (is->bits <= 8) {
is->bit_buf |= *(unsigned short *)is->in_buf << is->bits;
is->in_buf += sizeof(unsigned short);
is->bits += 16;
}
one_byte = (is->bit_buf & 0xFF);
is->bit_buf >>= 8;
is->bits -= 8;
return one_byte;
}
/* Gets 7 bits from the stream. */
static unsigned long libmpq_huff_get_7bits(struct huffman_input_stream *is) {
if (is->bits <= 7) {
is->bit_buf |= *(unsigned short *)is->in_buf << is->bits;
is->in_buf += sizeof(unsigned short);
is->bits += 16;
}
/* Get 7 bits from input stream. */
return (is->bit_buf & 0x7F);
}
/* Gets one bit from input stream. */
unsigned long libmpq_huff_get_bit(struct huffman_input_stream *is) {
unsigned long bit = (is->bit_buf & 1);
is->bit_buf >>= 1;
if (--is->bits == 0) {
is->bit_buf = *(unsigned long *)is->in_buf;
is->in_buf += sizeof(unsigned long);
is->bits = 32;
}
return bit;
}
static struct huffman_tree_item *libmpq_huff_call1500E740(struct huffman_tree *ht, unsigned int value) {
struct huffman_tree_item *p_item1 = ht->item3058; /* EDX */
struct huffman_tree_item *p_item2; /* EAX */
struct huffman_tree_item *p_next;
struct huffman_tree_item *p_prev;
struct huffman_tree_item **pp_item;
if (PTR_INT(p_item1) <= 0 || (p_item2 = p_item1) == NULL) {
if((p_item2 = &ht->items0008[ht->items++]) != NULL) {
p_item1 = p_item2;
} else {
p_item1 = ht->first;
}
} else {
p_item1 = p_item2;
}
p_next = p_item1->next;
if (p_next != NULL) {
p_prev = p_item1->prev;
if (PTR_INT(p_prev) <= 0) {
p_prev = PTR_NOT(p_prev);
} else {
p_prev += (p_item1 - p_item1->next->prev);
}
p_prev->next = p_next;
p_next->prev = p_prev;
p_item1->next = NULL;
p_item1->prev = NULL;
}
pp_item = &ht->first; /* ESI */
if (value > 1) {
/* ECX = ht->first->next; */
p_item1->next = *pp_item;
p_item1->prev = (*pp_item)->prev;
(*pp_item)->prev = p_item2;
*pp_item = p_item1;
p_item2->parent = NULL;
p_item2->child = NULL;
} else {
p_item1->next = (struct huffman_tree_item *)pp_item;
p_item1->prev = pp_item[1];
/* EDI = ht->item305C; */
p_prev = pp_item[1]; /* ECX */
if (p_prev <= 0) {
p_prev = PTR_NOT(p_prev);
p_prev->next = p_item1;
p_prev->prev = p_item2;
p_item2->parent = NULL;
p_item2->child = NULL;
} else {
if (PTR_INT(ht->item305C) < 0) {
p_prev += (struct huffman_tree_item *)pp_item - (*pp_item)->prev;
} else {
p_prev += PTR_INT(ht->item305C);
}
p_prev->next = p_item1;
pp_item[1] = p_item2;
p_item2->parent = NULL;
p_item2->child = NULL;
}
}
return p_item2;
}
static void libmpq_huff_call1500E820(struct huffman_tree *ht, struct huffman_tree_item *p_item) {
struct huffman_tree_item *p_item1; /* EDI */
struct huffman_tree_item *p_item2 = NULL; /* EAX */
struct huffman_tree_item *p_item3; /* EDX */
struct huffman_tree_item *p_prev; /* EBX */
for (; p_item != NULL; p_item = p_item->parent) {
p_item->byte_value++;
for (p_item1 = p_item; ; p_item1 = p_prev) {
p_prev = p_item1->prev;
if (PTR_INT(p_prev) <= 0) {
p_prev = NULL;
break;
}
if (p_prev->byte_value >= p_item->byte_value) {
break;
}
}
if (p_item1 == p_item) {
continue;
}
if (p_item1->next != NULL) {
p_item2 = libmpq_huff_get_prev_item(p_item1, -1);
p_item2->next = p_item1->next;
p_item1->next->prev = p_item1->prev;
p_item1->next = NULL;
p_item1->prev = NULL;
}
p_item2 = p_item->next;
p_item1->next = p_item2;
p_item1->prev = p_item2->prev;
p_item2->prev = p_item1;
p_item->next = p_item1;
if ((p_item2 = p_item1) != NULL) {
p_item2 = libmpq_huff_get_prev_item(p_item, -1);
p_item2->next = p_item->next;
p_item->next->prev = p_item->prev;
p_item->next = NULL;
p_item->prev = NULL;
}
if (p_prev == NULL) {
p_prev = PTR_PTR(&ht->first);
}
p_item2 = p_prev->next;
p_item->next = p_item2;
p_item->prev = p_item2->prev;
p_item2->prev = p_item;
p_prev->next = p_item;
p_item3 = p_item1->parent->child;
p_item2 = p_item->parent;
if (p_item2->child == p_item) {
p_item2->child = p_item1;
}
if (p_item3 == p_item1) {
p_item1->parent->child = p_item;
}
p_item2 = p_item->parent;
p_item->parent = p_item1->parent;
p_item1->parent = p_item2;
ht->offs0004++;
}
}
int libmpq_huff_do_decompress(struct huffman_tree *ht, struct huffman_input_stream *is, unsigned char *out_buf, unsigned int out_length) {
unsigned int n8bits; /* 8 bits loaded from input stream */
unsigned int n7bits; /* 7 bits loaded from input stream */
unsigned int found; /* Thats needed to replace the goto stuff from original source :) */
unsigned int dcmp_byte = 0;
unsigned long bit_count;
struct huffman_decompress *qd;
unsigned int has_qd; /* Can we use quick decompression? */
struct huffman_tree_item *p_item1;
struct huffman_tree_item *p_item2;
unsigned char *out_pos = out_buf;
/* Test the output length. Must not be non zero. */
if (out_length == 0) {
return 0;
}
/* Get the compression type from the input stream. */
n8bits = libmpq_huff_get_8bits(is);
/* Build the Huffman tree */
libmpq_huff_build_tree(ht, n8bits);
ht->cmp0 = (n8bits == 0) ? TRUE : FALSE;
for(;;) {
n7bits = libmpq_huff_get_7bits(is); /* Get 7 bits from input stream */
/*
* Try to use quick decompression. Check huffman_decompress array for corresponding item.
* If found, use the result byte instead.
*/
qd = &ht->qd3474[n7bits];
/* If there is a quick-pass possible (ebx) */
has_qd = (qd->offs00 >= ht->offs0004) ? TRUE : FALSE;
/* If we can use quick decompress, use it. */
if (has_qd) {
found = 0;
if (qd->bits > 7) {
is->bit_buf >>= 7;
is->bits -= 7;
p_item1 = qd->p_item;
found = 1;
}
if (found == 0) {
is->bit_buf >>= qd->bits;
is->bits -= qd->bits;
dcmp_byte = qd->dcmp_byte;
}
} else {
found = 1;
p_item1 = ht->first->next->prev;
if (PTR_INT(p_item1) <= 0) {
p_item1 = NULL;
}
}
if (found == 1) {
bit_count = 0;
p_item2 = NULL;
do {
p_item1 = p_item1->child; /* Move down by one level */
if (libmpq_huff_get_bit(is)) { /* If current bit is set, move to previous */
p_item1 = p_item1->prev;
}
if (++bit_count == 7) { /* If we are at 7th bit, save current huffman tree item. */
p_item2 = p_item1;
}
} while (p_item1->child != NULL); /* Walk until tree has no deeper level */
if (has_qd == FALSE) {
if (bit_count > 7) {
qd->offs00 = ht->offs0004;
qd->bits = bit_count;
qd->p_item = p_item2;
} else {
unsigned long index = n7bits & (0xFFFFFFFF >> (32 - bit_count));
unsigned long add = (1 << bit_count);
for (qd = &ht->qd3474[index]; index <= 0x7F; index += add, qd += add) {
qd->offs00 = ht->offs0004;
qd->bits = bit_count;
qd->dcmp_byte = p_item1->dcmp_byte;
}
}
}
dcmp_byte = p_item1->dcmp_byte;
}
if (dcmp_byte == 0x101) { /* Huffman tree needs to be modified */
n8bits = libmpq_huff_get_8bits(is);
p_item1 = (ht->last <= 0) ? NULL : ht->last;
p_item2 = libmpq_huff_call1500E740(ht, 1);
p_item2->parent = p_item1;
p_item2->dcmp_byte = p_item1->dcmp_byte;
p_item2->byte_value = p_item1->byte_value;
ht->items306C[p_item2->dcmp_byte] = p_item2;
p_item2 = libmpq_huff_call1500E740(ht, 1);
p_item2->parent = p_item1;
p_item2->dcmp_byte = n8bits;
p_item2->byte_value = 0;
ht->items306C[p_item2->dcmp_byte] = p_item2;
p_item1->child = p_item2;
libmpq_huff_call1500E820(ht, p_item2);
if (ht->cmp0 == 0) {
libmpq_huff_call1500E820(ht, ht->items306C[n8bits]);
}
dcmp_byte = n8bits;
}
if (dcmp_byte == 0x100) {
break;
}
*out_pos++ = (unsigned char)dcmp_byte;
if (--out_length == 0) {
break;
}
if (ht->cmp0) {
libmpq_huff_call1500E820(ht, ht->items306C[dcmp_byte]);
}
}
return (out_pos - out_buf);
}
int libmpq_huff_init_tree(struct huffman_tree *ht, struct huffman_tree_item *hi, unsigned int cmp) {
int count;
/* Clear links for all the items in the tree */
for (hi = ht->items0008, count = 0x203; count != 0; hi++, count--) {
hi->next = hi->prev = NULL;
}
ht->item3050 = NULL;
ht->item3054 = PTR_PTR(&ht->item3054);
ht->item3058 = PTR_NOT(ht->item3054);
ht->item305C = NULL;
ht->first = PTR_PTR(&ht->first);
ht->last = PTR_NOT(ht->first);
ht->offs0004 = 1;
ht->items = 0;
/* Clear all huffman_decompress items. Do this only if preparing for decompression */
if (cmp == LIBMPQ_HUFF_DECOMPRESS) {
for (count = 0; count < sizeof(ht->qd3474) / sizeof(struct huffman_decompress); count++) {
ht->qd3474[count].offs00 = 0;
}
}
return 0;
}
-106
View File
@@ -1,106 +0,0 @@
/*
* huffman.h -- structures used for huffman compression.
*
* Copyright (C) 2003 Maik Broemme <mbroemme@plusserver.de>
*
* This source was adepted from the C++ version of huffman.h included
* in stormlib. The C++ version belongs to the following authors,
*
* Ladislav Zezula <ladik.zezula.net>
* ShadowFlare <BlakFlare@hotmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _HUFFMAN_H
#define _HUFFMAN_H
#define PTR_NOT(ptr) (struct huffman_tree_item *)(~(unsigned long)(ptr))
#define PTR_PTR(ptr) ((struct huffman_tree_item *)(ptr))
#define PTR_INT(ptr) (long)(ptr)
#define INSERT_ITEM 1
#define SWITCH_ITEMS 2 /* Switch the item1 and item2 */
/*
* Input stream for Huffmann decompression
*/
struct huffman_input_stream {
unsigned char *in_buf; /* 00 - Input data */
unsigned long bit_buf; /* 04 - Input bit buffer */
unsigned int bits; /* 08 - Number of bits remaining in 'byte' */
};
/*
* Huffmann tree item.
*/
struct huffman_tree_item {
struct huffman_tree_item *next; /* 00 - Pointer to next huffman_tree_item */
struct huffman_tree_item *prev; /* 04 - Pointer to prev huffman_tree_item (< 0 if none) */
unsigned long dcmp_byte; /* 08 - Index of this item in item pointer array, decompressed byte value */
unsigned long byte_value; /* 0C - Some byte value */
struct huffman_tree_item *parent; /* 10 - Pointer to parent huffman_tree_item (NULL if none) */
struct huffman_tree_item *child; /* 14 - Pointer to child huffman_tree_item */
};
/*
* Structure used for quick decompress. The 'bits' contains
* number of bits and dcmp_byte contains result decompressed byte
* value. After each walk through Huffman tree are filled all entries
* which are multiplies of number of bits loaded from input stream.
* These entries contain number of bits and result value. At the next
* 7 bits is tested this structure first. If corresponding entry found,
* decompression routine will not walk through Huffman tree and
* directly stores output byte to output stream.
*/
struct huffman_decompress {
unsigned long offs00; /* 00 - 1 if resolved */
unsigned long bits; /* 04 - Bit count */
union {
unsigned long dcmp_byte; /* 08 - Byte value for decompress (if bitCount <= 7) */
struct huffman_tree_item *p_item; /* 08 - THTreeItem (if number of bits is greater than 7 */
};
};
/*
* Structure for Huffman tree.
*/
struct huffman_tree {
unsigned long cmp0; /* 0000 - 1 if compression type 0 */
unsigned long offs0004; /* 0004 - Some flag */
struct huffman_tree_item items0008[0x203]; /* 0008 - huffman tree items */
/* Sometimes used as huffman tree item */
struct huffman_tree_item *item3050; /* 3050 - Always NULL (?) */
struct huffman_tree_item *item3054; /* 3054 - Pointer to huffman_tree_item */
struct huffman_tree_item *item3058; /* 3058 - Pointer to huffman_tree_item (< 0 if invalid) */
/* Sometimes used as huffman tree item */
struct huffman_tree_item *item305C; /* 305C - Usually NULL */
struct huffman_tree_item *first; /* 3060 - Pointer to top (first) Huffman tree item */
struct huffman_tree_item *last; /* 3064 - Pointer to bottom (last) Huffman tree item (< 0 if invalid) */
unsigned long items; /* 3068 - Number of used huffman tree items */
struct huffman_tree_item *items306C[0x102]; /* 306C - huffman_tree_item pointer array */
struct huffman_decompress qd3474[0x80]; /* 3474 - Array for quick decompression */
//unsigned char table1502A630[]; /* Some table to make struct size flexible */
};
int libmpq_huff_init_tree(struct huffman_tree *ht, struct huffman_tree_item *hi, unsigned int cmp);
int libmpq_huff_do_decompress(struct huffman_tree *ht, struct huffman_input_stream *is, unsigned char *out_buf, unsigned int out_length);
#endif /* _HUFFMAN_H */
-627
View File
@@ -1,627 +0,0 @@
/*
* mpq.c -- functions for developers using libmpq.
*
* Copyright (C) 2003 Maik Broemme <mbroemme@plusserver.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Id: mpq.c,v 1.6 2004/02/12 00:49:00 mbroemme Exp $
*/
#define _CRT_SECURE_NO_DEPRECATE
#include <stdlib.h>
#include <sys/stat.h>
//#include <unistd.h>
//#include <io.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include "mpq.h"
#include "common.h"
/*
* This function returns version information.
* format: MAJOR.MINOR.PATCH
*/
char *libmpq_version() {
static char version[10];
sprintf(version, "%i.%i.%i", LIBMPQ_MAJOR_VERSION, LIBMPQ_MINOR_VERSION, LIBMPQ_PATCH_VERSION);
return version;
}
/*
* This function reads a file and verify if it is a legit MPQ archive
* or not. Then it fills the mpq_header structure and reads the hash
* table.
*/
int libmpq_archive_open(mpq_archive *mpq_a, unsigned char *mpq_filename) {
int fd = 0;
int rb = 0;
int ncnt = FALSE;
struct stat fileinfo;
/* allocate memory */
mpq_a->mpq_l = (mpq_list *)malloc(sizeof(mpq_list));
memset(mpq_a->mpq_l, 0, sizeof(mpq_list));
mpq_a->header = (mpq_header *)malloc(sizeof(mpq_header));
memset(mpq_a->header, 0, sizeof(mpq_header));
/* Check if file exists and is readable */
fd = _open((char *)mpq_filename, MPQ_FILE_OPEN_FLAGS);
if (fd == LIBMPQ_EFILE) {
return LIBMPQ_EFILE;
}
/* fill the structures with informations */
strcpy((char *)mpq_a->filename, (char *)mpq_filename);
libmpq_init_buffer(mpq_a);
mpq_a->fd = fd;
mpq_a->header->id = 0;
mpq_a->maxblockindex = 0;
mpq_a->mpq_l->mpq_files = NULL;
mpq_a->mpqpos = 0; //k
while (!ncnt) {
mpq_a->header->id = 0;
#ifdef WIN32
_lseeki64(mpq_a->fd, mpq_a->mpqpos, SEEK_SET);
#else
lseek64(mpq_a->fd, mpq_a->mpqpos, SEEK_SET);
#endif
rb = _read(mpq_a->fd, mpq_a->header, sizeof(mpq_header));
/* if different number of bytes read, break the loop */
if (rb != sizeof(mpq_header)) {
return LIBMPQ_EFILE_FORMAT;
}
/* special offset for protected MPQs */
if (mpq_a->header->offset == LIBMPQ_HEADER_W3M) {
mpq_a->flags |= LIBMPQ_FLAG_PROTECTED;
mpq_a->header->offset = sizeof(mpq_header);
}
/* if valid signature has been found, break the loop */
if (mpq_a->header->id == LIBMPQ_ID_MPQ) {
ncnt = true;
}
/*if (mpq_a->header->id == LIBMPQ_ID_MPQ &&
mpq_a->header->offset == sizeof(mpq_header) &&
mpq_a->header->hashtablepos < mpq_a->header->archivesize &&
mpq_a->header->blocktablepos < mpq_a->header->archivesize) {
ncnt = TRUE;
}*/
/* move to the next possible offset */
if (!ncnt) {
mpq_a->mpqpos += 0x200;
}
}
/* get the right positions of the hash table and the block table. */
mpq_a->blocksize = (0x200 << mpq_a->header->blocksize);
fstat(mpq_a->fd, &fileinfo);
/* Normal MPQs must have position of */
/*if (mpq_a->header->hashtablepos + mpq_a->mpqpos < fileinfo.st_size &&
mpq_a->header->blocktablepos + mpq_a->mpqpos < fileinfo.st_size) {
mpq_a->header->hashtablepos += mpq_a->mpqpos;
mpq_a->header->blocktablepos += mpq_a->mpqpos;
} else {
return LIBMPQ_EFILE_FORMAT;
}*/
/* Try to read and decrypt the hashtable */
if (libmpq_read_hashtable(mpq_a) != 0) {
return LIBMPQ_EHASHTABLE;
}
/* Try to read and decrypt the blocktable */
if (libmpq_read_blocktable(mpq_a) != 0) {
return LIBMPQ_EBLOCKTABLE;
}
return LIBMPQ_TOOLS_SUCCESS;
}
/*
* This function closes the file descriptor opened by
* mpq_open_archive(); and frees the decryption buffer.
*/
int libmpq_archive_close(mpq_archive *mpq_a) {
memset(mpq_a->buf, 0, sizeof(mpq_a->buf));
/* free the allocated memory. */
free(mpq_a->header);
free(mpq_a->mpq_l);
/* Check if file descriptor is valid. */
if ((_close(mpq_a->fd)) == LIBMPQ_EFILE) {
return LIBMPQ_EFILE;
}
return LIBMPQ_TOOLS_SUCCESS;
}
/*
* This function returns the value for the given infotype.
* If an error occurs something < 0 is returned.
*/
int libmpq_archive_info(mpq_archive *mpq_a, unsigned int infotype) {
unsigned int filecount = 0;
unsigned int fsize = 0;
unsigned int csize = 0;
mpq_block *mpq_b_end = mpq_a->blocktable + mpq_a->header->blocktablesize;
mpq_block *mpq_b = NULL;
switch (infotype) {
case LIBMPQ_MPQ_ARCHIVE_SIZE:
return mpq_a->header->archivesize;
case LIBMPQ_MPQ_HASHTABLE_SIZE:
return mpq_a->header->hashtablesize;
case LIBMPQ_MPQ_BLOCKTABLE_SIZE:
return mpq_a->header->blocktablesize;
case LIBMPQ_MPQ_BLOCKSIZE:
return mpq_a->blocksize;
case LIBMPQ_MPQ_NUMFILES:
for (mpq_b = mpq_a->blocktable; mpq_b < mpq_b_end; mpq_b++) {
filecount++;
}
return filecount;
case LIBMPQ_MPQ_COMPRESSED_SIZE:
for (mpq_b = mpq_a->blocktable; mpq_b < mpq_b_end; mpq_b++) {
csize += mpq_b->csize;
}
return csize;
case LIBMPQ_MPQ_UNCOMPRESSED_SIZE:
for (mpq_b = mpq_a->blocktable; mpq_b < mpq_b_end; mpq_b++) {
fsize += mpq_b->fsize;
}
return fsize;
default:
return LIBMPQ_TOOLS_SUCCESS;
}
}
/*
* This function returns some useful file information.
*/
int libmpq_file_info(mpq_archive *mpq_a, unsigned int infotype, const unsigned int number) {
int blockindex = number; //-1;
int i = 0;
mpq_block *mpq_b = NULL;
mpq_hash *mpq_h = NULL;
/* check if given number is not out of range */
if (number < 1 || number > mpq_a->header->blocktablesize) {
return LIBMPQ_EINV_RANGE;
}
/* search for correct hashtable */
/*for (i = 0; i < mpq_a->header->hashtablesize; i++) {
if ((number - 1) == (mpq_a->hashtable[i]).blockindex) {
blockindex = (mpq_a->hashtable[i]).blockindex;
mpq_h = &(mpq_a->hashtable[i]);
break;
}
}*/
/* check if file was found */
/*if (blockindex == -1 || blockindex > mpq_a->header->blocktablesize) {
return LIBMPQ_EFILE_NOT_FOUND;
}*/
/* check if sizes are correct */
mpq_b = mpq_a->blocktable + blockindex;
if (mpq_b->filepos > (mpq_a->header->archivesize + mpq_a->mpqpos) || mpq_b->csize > mpq_a->header->archivesize) {
return LIBMPQ_EFILE_CORRUPT;
}
/* check if file exists */
if ((mpq_b->flags & LIBMPQ_FILE_EXISTS) == 0) {
return LIBMPQ_EFILE_NOT_FOUND;
}
switch (infotype) {
case LIBMPQ_FILE_COMPRESSED_SIZE:
return mpq_b->csize;
case LIBMPQ_FILE_UNCOMPRESSED_SIZE:
return mpq_b->fsize;
case LIBMPQ_FILE_COMPRESSION_TYPE:
if (mpq_b->flags & LIBMPQ_FILE_COMPRESS_PKWARE) {
return LIBMPQ_FILE_COMPRESS_PKWARE;
}
if (mpq_b->flags & LIBMPQ_FILE_COMPRESS_MULTI) {
return LIBMPQ_FILE_COMPRESS_MULTI;
}
default:
return LIBMPQ_TOOLS_SUCCESS;
}
}
/*
* This function searches the listfile for the filename.
* On success it returns the filename, otherwiese a name
* like file000001.xxx and if number is out of range it
* returns NULL.
*/
char *libmpq_file_name(mpq_archive *mpq_a, const int number) {
static char tempfile[PATH_MAX];
/* check if we are in the range of available files. */
if (number > libmpq_archive_info(mpq_a, LIBMPQ_MPQ_NUMFILES) || number < 1) {
return NULL;
}
/* this is safe because we built a fallback filelist, if something was wrong. */
sprintf(tempfile, (char *)mpq_a->mpq_l->mpq_files[number - 1], number);
return tempfile;
}
/*
* This function returns the number to the given
* filename.
*/
int libmpq_file_number(mpq_archive *mpq_a, const char *name) {
int i;
char tempfile[PATH_MAX];
for (i = 0; mpq_a->mpq_l->mpq_files[i]; i++) {
sprintf(tempfile, (char *)mpq_a->mpq_l->mpq_files[i], i + 1);
if (strncmp(tempfile, name, strlen(name)) == 0) {
/* if file found return the number */
return i + 1;
}
}
/* if no matching entry found return LIBMPQ_EFILE_NOT_FOUND */
return LIBMPQ_EFILE_NOT_FOUND;
}
/*
* This function verifies if a given file (by number
* or name) is in the opened mpq archive. On success
* it returns 0, otherwise LIBMPQ_EFILE_NOT_FOUND.
*/
int libmpq_file_check(mpq_archive *mpq_a, void *file, int type) {
int found = 0;
int i;
char tempfile[PATH_MAX];
switch (type) {
case LIBMPQ_FILE_TYPE_INT:
/* check if we are in the range of available files. */
if (*(int *)file > libmpq_archive_info(mpq_a, LIBMPQ_MPQ_NUMFILES) || *(int *)file < 1) {
return LIBMPQ_EFILE_NOT_FOUND;
} else {
return LIBMPQ_TOOLS_SUCCESS;
}
case LIBMPQ_FILE_TYPE_CHAR:
for (i = 0; mpq_a->mpq_l->mpq_files[i]; i++) {
sprintf(tempfile, (char *)mpq_a->mpq_l->mpq_files[i], i);
if (strncmp(tempfile, (char *)file, strlen((char *)file)) == 0) {
/* if file found break */
found = 1;
break;
}
}
/* if a file was found return 0 */
if (found == 1) {
return LIBMPQ_TOOLS_SUCCESS;
} else {
return LIBMPQ_EFILE_NOT_FOUND;
}
default:
return LIBMPQ_TOOLS_SUCCESS;
}
}
/*
* This function extracts a file from a MPQ archive
* by the given number.
*/
int libmpq_file_extract(mpq_archive *mpq_a, const int number, const char *filename) {
int blockindex = number; //-1;
int fd = 0;
int i = 0;
char buffer[0x1000];
//char tempfile[PATH_MAX];
unsigned int transferred = 1;
mpq_file *mpq_f = NULL;
mpq_block *mpq_b = NULL;
mpq_hash *mpq_h = NULL;
/* if (number < 1 || number > mpq_a->header->blocktablesize) {
return LIBMPQ_EINV_RANGE;
}*/
/*
sprintf(tempfile, libmpq_file_name(mpq_a, number));
*/
/* check if mpq_f->filename could be written here. */
fd = _open(filename, O_RDWR|O_CREAT|O_TRUNC, 0644);
if (fd == LIBMPQ_EFILE) {
return LIBMPQ_EFILE;
}
/* search for correct hashtable */
/*for (i = 0; i < mpq_a->header->hashtablesize; i++) {
if ((number - 1) == (mpq_a->hashtable[i]).blockindex) {
blockindex = (mpq_a->hashtable[i]).blockindex;
mpq_h = &(mpq_a->hashtable[i]);
break;
}
}*/
/* check if file was found */
if (blockindex == -1 || blockindex > mpq_a->header->blocktablesize) {
return LIBMPQ_EFILE_NOT_FOUND;
}
/* check if sizes are correct */
mpq_b = mpq_a->blocktable + blockindex;
if (mpq_b->filepos > (mpq_a->header->archivesize + mpq_a->mpqpos) || mpq_b->csize > mpq_a->header->archivesize) {
return LIBMPQ_EFILE_CORRUPT;
}
/* check if file exists */
if ((mpq_b->flags & LIBMPQ_FILE_EXISTS) == 0) {
return LIBMPQ_EFILE_NOT_FOUND;
}
/* allocate memory for file structure */
mpq_f = (mpq_file *)malloc(sizeof(mpq_file));
if (!mpq_f) {
return LIBMPQ_EALLOCMEM;
}
/* initialize file structure */
memset(mpq_f, 0, sizeof(mpq_file));
mpq_f->fd = fd;
mpq_f->mpq_b = mpq_b;
mpq_f->nblocks = (mpq_f->mpq_b->fsize + mpq_a->blocksize - 1) / mpq_a->blocksize;
mpq_f->mpq_h = mpq_h;
mpq_f->accessed = FALSE;
mpq_f->blockposloaded = FALSE;
sprintf((char *)mpq_f->filename, filename);
/* allocate buffers for decompression. */
if (mpq_f->mpq_b->flags & LIBMPQ_FILE_COMPRESSED) {
/*
* Allocate buffer for block positions. At the begin of file are stored
* unsigned ints holding positions of each block relative from begin of
* file in the archive.
*/
if ((mpq_f->blockpos = (unsigned int *)malloc(sizeof(int) * mpq_f->nblocks + 1)) == NULL) {
return LIBMPQ_EALLOCMEM;
}
}
while (transferred > 0) {
transferred = libmpq_file_read_file(mpq_a, mpq_f, mpq_f->filepos, buffer, sizeof(buffer));
if (transferred == 0) {
break;
} else {
mpq_f->accessed = TRUE;
mpq_f->filepos += transferred;
}
transferred = _write(mpq_f->fd, buffer, transferred);
if (transferred == 0) {
break;
}
}
_close(fd);
/* freeing the file structure */
free(mpq_f);
return LIBMPQ_TOOLS_SUCCESS;
}
/*
* This function tries to get the filenames for the hashes. It uses
* an internal listfile database and gets the correct listfile from
* some specific archive informations.
*/
int libmpq_listfile_open(mpq_archive *mpq_a, char file[PATH_MAX]) {
FILE *fp;
//char **filelist;
int i = 0;
//int fl_count;
//int fl_size;
int fl_count_fb;
int fl_size_fb;
int result = LIBMPQ_TOOLS_SUCCESS;
struct stat statbuf;
/* get file status */
if (stat(file, &statbuf) < 0) {
result = LIBMPQ_CONF_EFILE_NOT_FOUND;
}
/* check if file is a filename or directory */
/*if (S_ISDIR(statbuf.st_mode)) {
// allocate memory for the file list
filelist = (char **)malloc(LIBMPQ_CONF_FL_INCREMENT * sizeof(char *));
fl_count = 0;
fl_size = LIBMPQ_CONF_FL_INCREMENT;
// check if it is a valid listfile
if (libmpq_detect_listfile_rec(file, &filelist, &fl_count, &fl_size)) {
filelist == NULL;
}
filelist[fl_count] = NULL;
// return if no listfile was found
if (filelist == NULL) {
result = LIBMPQ_CONF_EFILE_NOT_FOUND;
}
for (i = 0; filelist[i]; i++) {
if ((fp = fopen(filelist[i], "r")) != NULL ) {
result = libmpq_read_listfile(mpq_a, fp);
fclose(fp);
}
}
// freeing the listfile struct
libmpq_free_listfile(filelist);
}*/
/* if file is a regular file use it */
//if (S_ISREG(statbuf.st_mode)) {
/* if specific listfile was forced. */
if ((fp = fopen(file, "r")) != NULL ) {
result = libmpq_read_listfile(mpq_a, fp);
fclose(fp);
} else {
result = LIBMPQ_CONF_EFILE_OPEN;
}
//}
/* if error occured we need to create a fallback filelist. */
if (mpq_a->mpq_l->mpq_files == NULL) {
/* allocate memory for the file list */
mpq_a->mpq_l->mpq_files = (unsigned char **)malloc(LIBMPQ_CONF_FL_INCREMENT * sizeof(char *));
fl_count_fb = 0;
fl_size_fb = LIBMPQ_CONF_FL_INCREMENT;
for (i = 0; i < libmpq_archive_info(mpq_a, LIBMPQ_MPQ_NUMFILES); i++) {
/* set the next filelist entry to a copy of the file */
mpq_a->mpq_l->mpq_files[fl_count_fb++] = (unsigned char *)_strdup("file%06lu.xxx");
/* increase the array size */
if (fl_count_fb == fl_size_fb) {
mpq_a->mpq_l->mpq_files = (unsigned char **)realloc(mpq_a->mpq_l->mpq_files, (fl_size_fb + LIBMPQ_CONF_FL_INCREMENT) * sizeof(char *));
fl_size_fb += LIBMPQ_CONF_FL_INCREMENT;
}
}
mpq_a->mpq_l->mpq_files[fl_count_fb] = NULL;
/* if no error occurs and no listfile was assigned, we think there was no matching listfile. */
if (result == 0) {
result = LIBMPQ_CONF_EFILE_NOT_FOUND;
}
}
return result;
}
/*
* This function frees the allocated memory for the listfile.
*/
int libmpq_listfile_close(mpq_archive *mpq_a) {
int i = 0;
/* safety check if we really have a filelist. */
if (mpq_a->mpq_l->mpq_files != NULL) {
/* freeing the filelist */
while (mpq_a->mpq_l->mpq_files[i]) {
free(mpq_a->mpq_l->mpq_files[i++]);
}
free(mpq_a->mpq_l->mpq_files);
}
return 0;
}
int libmpq_file_getdata(mpq_archive *mpq_a, mpq_hash mpq_h, const int number, unsigned char *dest) {
int blockindex = number; //-1;
int i = 0;
mpq_file *mpq_f = NULL;
mpq_block *mpq_b = NULL;
int success = 0;
/*if (number < 1 || number > mpq_a->header->blocktablesize) {
return LIBMPQ_EINV_RANGE;
}*/
/* search for correct hashtable */
/*for (i = 0; i < mpq_a->header->hashtablesize; i++) {
if ((number - 1) == (mpq_a->hashtable[i]).blockindex) {
blockindex = (mpq_a->hashtable[i]).blockindex;
mpq_h = &(mpq_a->hashtable[i]);
break;
}
}*/
/* check if file was found */
if (blockindex == -1 || blockindex > mpq_a->header->blocktablesize) {
return LIBMPQ_EFILE_NOT_FOUND;
}
/* check if sizes are correct */
mpq_b = mpq_a->blocktable + blockindex;
if (mpq_b->filepos > (mpq_a->header->archivesize + mpq_a->mpqpos) || mpq_b->csize > mpq_a->header->archivesize) {
return LIBMPQ_EFILE_CORRUPT;
}
/* check if file exists */
if ((mpq_b->flags & LIBMPQ_FILE_EXISTS) == 0) {
return LIBMPQ_EFILE_NOT_FOUND;
}
/* allocate memory for file structure */
mpq_f = (mpq_file*)malloc(sizeof(mpq_file));
if (!mpq_f) {
return LIBMPQ_EALLOCMEM;
}
/* initialize file structure */
memset(mpq_f, 0, sizeof(mpq_file));
mpq_f->mpq_b = mpq_b;
mpq_f->nblocks = (mpq_f->mpq_b->fsize + mpq_a->blocksize - 1) / mpq_a->blocksize;
mpq_f->mpq_h = &mpq_h;
mpq_f->accessed = FALSE;
mpq_f->blockposloaded = FALSE;
/* allocate buffers for decompression. */
if (mpq_f->mpq_b->flags & LIBMPQ_FILE_COMPRESSED) {
/*
* Allocate buffer for block positions. At the begin of file are stored
* unsigned ints holding positions of each block relative from begin of
* file in the archive.
*/
if ((mpq_f->blockpos = (unsigned int*)malloc(sizeof(int) * (mpq_f->nblocks + 1))) == NULL) {
return LIBMPQ_EALLOCMEM;
}
}
if(libmpq_file_read_file(mpq_a, mpq_f, 0, (char*)dest, mpq_b->fsize) == mpq_b->fsize)
success = 1;
if (mpq_f->mpq_b->flags & LIBMPQ_FILE_COMPRESSED) {
// Free buffer for block positions
free(mpq_f->blockpos);
}
/* freeing the file structure */
free(mpq_f);
return success?LIBMPQ_TOOLS_SUCCESS:LIBMPQ_EFILE_CORRUPT;
}
-229
View File
@@ -1,229 +0,0 @@
/*
* mpq.h -- some default types and defines.
*
* Copyright (C) 2003 Maik Broemme <mbroemme@plusserver.de>
*
* This source was adepted from the C++ version of StormLib.h and
* StormPort.h included in stormlib. The C++ version belongs to
* the following authors,
*
* Ladislav Zezula <ladik.zezula.net>
* Marko Friedemann <marko.friedemann@bmx-chemnitz.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Id: mpq.h,v 1.8 2004/02/12 00:45:50 mbroemme Exp $
*/
#ifndef _MPQ_H
#define _MPQ_H
#include <limits.h>
#ifndef PATH_MAX
#define PATH_MAX 260
#endif
#if defined(__APPLE_CC__)
#define lseek64 lseek
#endif
#define LIBMPQ_MAJOR_VERSION 0 /* Major version number... maybe sometimes we reach version 1 :) */
#define LIBMPQ_MINOR_VERSION 3 /* Minor version number - increased only for small changes */
#define LIBMPQ_PATCH_VERSION 0 /* Patchlevel - changed on bugfixes etc... */
#define LIBMPQ_TOOLS_SUCCESS 0 /* return value for all functions which success */
#define LIBMPQ_TOOLS_BUFSIZE 0x500 /* buffer size for the decryption engine */
#define LIBMPQ_EFILE -1 /* error on file operation */
#define LIBMPQ_EFILE_FORMAT -2 /* bad file format */
#define LIBMPQ_EFILE_CORRUPT -3 /* file corrupt */
#define LIBMPQ_EFILE_NOT_FOUND -4 /* file in archive not found */
#define LIBMPQ_EFILE_READ -5 /* Read error in archive */
#define LIBMPQ_EALLOCMEM -6 /* maybe not enough memory? :) */
#define LIBMPQ_EFREEMEM -7 /* can not free memory */
#define LIBMPQ_EINV_RANGE -8 /* Given filenumber is out of range */
#define LIBMPQ_EHASHTABLE -9 /* error in reading hashtable */
#define LIBMPQ_EBLOCKTABLE -10 /* error in reading blocktable */
#define LIBMPQ_ID_MPQ 0x1A51504D /* MPQ archive header ID ('MPQ\x1A') */
#define LIBMPQ_HEADER_W3M 0x6D9E4B86 /* special value used by W3M Map Protector */
#define LIBMPQ_FLAG_PROTECTED 0x00000002 /* Set on protected MPQs (like W3M maps) */
#define LIBMPQ_HASH_ENTRY_DELETED 0xFFFFFFFE /* Block index for deleted hash entry */
#define LIBMPQ_FILE_COMPRESS_PKWARE 0x00000100 /* Compression made by PKWARE Data Compression Library */
#define LIBMPQ_FILE_COMPRESS_MULTI 0x00000200 /* Multiple compressions */
#define LIBMPQ_FILE_COMPRESSED 0x0000FF00 /* File is compressed */
#define LIBMPQ_FILE_EXISTS 0x80000000 /* Set if file exists, reset when the file was deleted */
#define LIBMPQ_FILE_ENCRYPTED 0x00010000 /* Indicates whether file is encrypted */
#define LIBMPQ_FILE_HAS_METADATA 0x04000000
#define LIBMPQ_FILE_COMPRESSED_SIZE 1 /* MPQ compressed filesize of given file */
#define LIBMPQ_FILE_UNCOMPRESSED_SIZE 2 /* MPQ uncompressed filesize of given file */
#define LIBMPQ_FILE_COMPRESSION_TYPE 3 /* MPQ compression type of given file */
#define LIBMPQ_FILE_TYPE_INT 4 /* file is given by number */
#define LIBMPQ_FILE_TYPE_CHAR 5 /* file is given by name */
#define LIBMPQ_MPQ_ARCHIVE_SIZE 1 /* MPQ archive size */
#define LIBMPQ_MPQ_HASHTABLE_SIZE 2 /* MPQ archive hashtable size */
#define LIBMPQ_MPQ_BLOCKTABLE_SIZE 3 /* MPQ archive blocktable size */
#define LIBMPQ_MPQ_BLOCKSIZE 4 /* MPQ archive blocksize */
#define LIBMPQ_MPQ_NUMFILES 5 /* Number of files in the MPQ archive */
#define LIBMPQ_MPQ_COMPRESSED_SIZE 6 /* Compressed archive size */
#define LIBMPQ_MPQ_UNCOMPRESSED_SIZE 7 /* Uncompressed archive size */
#define LIBMPQ_HUFF_DECOMPRESS 0 /* Defines that we want to decompress using huffman trees. */
#define LIBMPQ_CONF_EFILE_OPEN -1 /* error if a specific listfile was forced and could not be opened. */
#define LIBMPQ_CONF_EFILE_CORRUPT -2 /* listfile seems to be corrupt */
#define LIBMPQ_CONF_EFILE_LIST_CORRUPT -3 /* listfile seems correct, but filelist is broken */
#define LIBMPQ_CONF_EFILE_NOT_FOUND -4 /* error if no matching listfile found */
#define LIBMPQ_CONF_EFILE_VERSION -5 /* libmpq version does not match required listfile version */
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
/*
#ifndef min
#define min(a, b) ((a < b) ? a : b)
#endif
*/
typedef unsigned int mpq_buffer[LIBMPQ_TOOLS_BUFSIZE];
typedef int (*DECOMPRESS)(char *, int *, char *, int);
typedef struct {
unsigned long mask; /* Decompression bit */
DECOMPRESS decompress; /* Decompression function */
} decompress_table;
/* MPQ file header */
typedef struct {
unsigned int id; /* The 0x1A51504D ('MPQ\x1A') signature */
unsigned int offset; /* Offset of the first file (Relative to MPQ start) */
unsigned int archivesize; /* Size of MPQ archive */
unsigned short offsetsc; /* 0000 for SC and BW */
unsigned short blocksize; /* Size of file block is (0x200 << blockSize) */
unsigned int hashtablepos; /* File position of hashTable */
unsigned int blocktablepos; /* File position of blockTable. Each entry has 16 bytes */
unsigned int hashtablesize; /* Number of entries in hash table */
unsigned int blocktablesize; /* Number of entries in the block table */
} mpq_header;
//} __attribute__ ((packed)) mpq_header;
/* Hash entry. All files in the archive are searched by their hashes. */
typedef struct {
unsigned int name1; /* The first two unsigned ints */
unsigned int name2; /* are the encrypted file name */
unsigned int locale; /* Locale information. */
unsigned int blockindex; /* Index to file description block */
} mpq_hash;
/* File description block contains informations about the file */
typedef struct {
unsigned int filepos; /* Block file starting position in the archive */
unsigned int csize; /* Compressed file size */
unsigned int fsize; /* Uncompressed file size */
unsigned int flags; /* Flags */
} mpq_block;
/* File handle structure used since Diablo 1.00 (0x38 bytes) */
typedef struct {
unsigned char filename[PATH_MAX]; /* filename of the actual file in the archive */
int fd; /* File handle */
unsigned int seed; /* Seed used for file decrypt */
unsigned int filepos; /* Current file position */
unsigned int offset;
unsigned int nblocks; /* Number of blocks in the file (incl. the last noncomplete one) */
unsigned int *blockpos; /* Position of each file block (only for compressed files) */
int blockposloaded; /* TRUE if block positions loaded */
unsigned int offset2; /* (Number of bytes somewhere ?) */
mpq_hash *mpq_h; /* Hash table entry */
mpq_block *mpq_b; /* File block pointer */
/* Non-Storm.dll members */
unsigned int accessed; /* Was something from the file already read? */
} mpq_file;
/* List handle structure */
typedef struct {
unsigned char mpq_version[10]; /* libmpq version required by the listfile */
unsigned char mpq_name[PATH_MAX]; /* mpq archive name without full path */
unsigned char mpq_type[20]; /* mpq archive type */
unsigned char mpq_game[40]; /* blizzard title the file matches */
unsigned char mpq_game_version[10]; /* game version */
unsigned char **mpq_files; /* filelist */
} mpq_list;
/* Archive handle structure used since Diablo 1.00 */
typedef struct {
unsigned char filename[PATH_MAX]; /* Opened archive file name */
int fd; /* File handle */
unsigned int blockpos; /* Position of loaded block in the file */
unsigned int blocksize; /* Size of file block */
unsigned char *blockbuf; /* Buffer (cache) for file block */
unsigned int bufpos; /* Position in block buffer */
unsigned int mpqpos; /* MPQ archive position in the file */
unsigned int filepos; /* Current file pointer */
unsigned int openfiles; /* Number of open files + 1 */
mpq_buffer buf; /* MPQ buffer */
mpq_header *header; /* MPQ file header */
mpq_hash *hashtable; /* Hash table */
mpq_block *blocktable; /* Block table */
/* Non-Storm.dll members */
mpq_list *mpq_l; /* Handle to file list from database */
unsigned int flags; /* See LIBMPQ_TOOLS_FLAG_XXXXX */
unsigned int maxblockindex; /* The highest block table entry */
} mpq_archive;
extern char *libmpq_version();
extern int libmpq_archive_open(mpq_archive *mpq_a, unsigned char *mpq_filename);
extern int libmpq_archive_close(mpq_archive *mpq_a);
extern int libmpq_archive_info(mpq_archive *mpq_a, unsigned int infotype);
//extern int libmpq_file_extract(mpq_archive *mpq_a, const int number);
extern int libmpq_file_info(mpq_archive *mpq_a, unsigned int infotype, const unsigned int number);
extern char *libmpq_file_name(mpq_archive *mpq_a, const int number);
extern int libmpq_file_number(mpq_archive *mpq_a, const char *name);
extern int libmpq_file_check(mpq_archive *mpq_a, void *file, int type);
extern int libmpq_listfile_open(mpq_archive *mpq_a, char file[PATH_MAX]);
extern int libmpq_listfile_close(mpq_archive *mpq_a);
extern int libmpq_pkzip_decompress(char *out_buf, int *out_length, char *in_buf, int in_length);
extern int libmpq_zlib_decompress(char *out_buf, int *out_length, char *in_buf, int in_length);
extern int libmpq_huff_decompress(char *out_buf, int *out_length, char *in_buf, int in_length);
extern int libmpq_wave_decompress_stereo(char *out_buf, int *out_length, char *in_buf, int in_length);
extern int libmpq_wave_decompress_mono(char *out_buf, int *out_length, char *in_buf, int in_length);
extern int libmpq_multi_decompress(char *out_buf, int *pout_length, char *in_buf, int in_length);
static decompress_table dcmp_table[] = {
{0x08, libmpq_pkzip_decompress}, /* Decompression with Pkware Data Compression Library */
{0x02, libmpq_zlib_decompress}, /* Decompression with the "zlib" library */
{0x01, libmpq_huff_decompress}, /* Huffmann decompression */
{0x80, libmpq_wave_decompress_stereo}, /* WAVE decompression for stereo waves */
{0x40, libmpq_wave_decompress_mono} /* WAVE decompression for mono waves */
};
int libmpq_file_extract(mpq_archive *mpq_a, const int number, const char *filename);
int libmpq_file_getdata(mpq_archive *mpq_a, mpq_hash mpq_h, const int number, unsigned char *dest);
#endif /* _MPQ_H */
-295
View File
@@ -1,295 +0,0 @@
/*
* parser.c -- functions used to parse list or config file.
*
* Copyright (C) 2003 Maik Broemme <mbroemme@plusserver.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Id: parser.c,v 1.5 2004/02/12 00:47:53 mbroemme Exp $
*/
#define _CRT_SECURE_NO_DEPRECATE
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "mpq.h"
#include "common.h"
#include <ctype.h>
/*
* This function deletes the specified characters, but leaves
* escape sequences unaffected. This means that " would be
* deleted but \" would not.
*/
char *libmpq_conf_delete_char(char *buf, char *chars) {
static char *temp;
char ch;
temp = buf;
/* strip out special chars like " */
while (temp = strpbrk(temp, chars)) {
ch = temp[0];
memmove(&temp[0], &temp[1], strlen(temp));
if (ch == '\\') {
temp++;
}
}
return buf;
}
/*
* This function parses a line for the value to the given option. It
* return 1 on success and the byte array or 0 and null.
*/
int libmpq_conf_parse_line(char *line, char *search_value, char *return_value, int size) {
int level = 0;
int found = 0;
int i = 0;
int pos = 0;
/* search value */
while (*(++line)) {
/* check for spaces */
if (!isspace(*line) && level == 1) {
/* we found our value so break */
found = 1;
break;
}
/* check for '=' so the value follows as next parameter */
if (*line == '=' && level == 0) {
level = 1;
}
}
/* now search for comment in this line */
for (i = 0; i < int(strlen(line)); i++) {
if (line[i] == '#') {
pos = i - 1;
break;
}
}
/* now set end of byte array behind value, but only if comment was found */
if (pos != 0) {
for (i = pos; i >= 0; i--) {
if (line[i] != ' ' && line[i] != '\t') {
line[i + 1] = '\0';
break;
}
}
}
/* now check if line has trailing spaces */
for (i = strlen(line); i >= 0; i--) {
if (line[i] != ' ' && line[i] != '\t') {
line[i + 1] = '\0';
break;
}
}
/* now check if value is quoted with "" and if there is a char behind. */
for (i = strlen(line); i >= 0; i--) {
if (line[i] == '"') {
line[i + 1] = '\0';
break;
}
}
/* return the values */
strncpy(return_value, line, size);
return found;
}
/*
* This function returns the value for a given option in the
* listdb or config file. On success it returns 1, otherwise 0.
*/
int libmpq_conf_get_value(FILE *fp, char *search_value, void *return_value, int type, int size) {
char buf[LIBMPQ_CONF_BUFSIZE];
int found = 0;
int result = LIBMPQ_TOOLS_SUCCESS;
while (fgets(buf, LIBMPQ_CONF_BUFSIZE, fp) != NULL) {
char *line;
buf[strlen(buf) - 1] = '\0';
/* skip whitespace */
for (line = buf; isspace(*line); line++) {
continue;
}
/* skip empty line */
if (line[0] == '\0') {
continue;
}
/* skip comments */
if (line[0] == '#') {
continue;
}
/* process the line */
//if (!strncasecmp(line, search_value, strlen(search_value))) {
if (!strcmp(line, search_value)) {
found = libmpq_conf_parse_line(line, search_value, line, LIBMPQ_CONF_BUFSIZE);
if (found == 1) {
libmpq_conf_delete_char(line, "\"\\");
switch (type) {
case LIBMPQ_CONF_TYPE_INT:
/* if it is no valid number it is safe to return 0 */
*(int *)return_value = atoi(line);
break;
default:
strncpy((char *)return_value, line, size);
break;
}
/* value found, so rewind stream */
break;
}
}
}
/* if value was not found */
if (found == 0) {
switch (type) {
case LIBMPQ_CONF_TYPE_INT:
*(int *)return_value = 0;
result = LIBMPQ_CONF_EVALUE_NOT_FOUND;
break;
default:
strncpy((char *)return_value, "", size);
result = LIBMPQ_CONF_EVALUE_NOT_FOUND;
break;
}
}
fseek(fp, 0L, SEEK_SET);
return result;
}
/*
* This function returns a pointer to a byte array, with all values
* found in the config file. As second value it returns th number of
* entries in the byte array. On success it returns 1, otherwise 0.
*/
int libmpq_conf_get_array(FILE *fp, char *search_value, char ***filelist, int *entries) {
char buf[LIBMPQ_CONF_BUFSIZE];
char temp[LIBMPQ_CONF_BUFSIZE];
int level = 0;
int array_start = 0;
int array_end = 0;
int fl_count;
int fl_size;
int found = 0;
int i = 0;
*entries = 0;
/* allocate memory for the file list */
(*filelist) = (char **)malloc(LIBMPQ_CONF_FL_INCREMENT * sizeof(char *));
fl_count = 0;
fl_size = LIBMPQ_CONF_FL_INCREMENT;
while (fgets(buf, LIBMPQ_CONF_BUFSIZE, fp) != NULL) {
char *line;
buf[strlen(buf) - 1] = '\0';
/* skip whitespace */
for (line = buf; isspace(*line); line++) {
continue;
}
/* skip empty line */
if (line[0] == '\0') {
continue;
}
/* skip comments */
if (line[0] == '#') {
continue;
}
/* check for array end ) */
if (*line == ')') {
array_end = 1;
break;
}
/* process entries between () */
if (array_start == 1 && array_end == 0) {
/* add dummy option to use with libmpq_conf_parse_line() */
strncpy(temp, "MPQ_BUFFER = ", LIBMPQ_CONF_BUFSIZE);
strncat(temp, line, LIBMPQ_CONF_BUFSIZE);
found = libmpq_conf_parse_line(temp, "MPQ_BUFFER", temp, LIBMPQ_CONF_BUFSIZE);
if (found == 1) {
libmpq_conf_delete_char(temp, "\"\\");
/* set the next filelist entry to a copy of the file */
(*filelist)[fl_count++] = _strdup(temp);
/* increase the array size */
if (fl_count == fl_size) {
(*filelist) = (char **)realloc((*filelist), (fl_size + LIBMPQ_CONF_FL_INCREMENT) * sizeof(char *));
fl_size += LIBMPQ_CONF_FL_INCREMENT;
}
/* increase number of entries */
(*entries)++;
}
}
/* process the line and search array start */
//if (!strncasecmp(line, search_value, strlen(search_value))) {
if (!strcmp(line, search_value)) {
/* search value */
while (*(++line)) {
/* check for array start ( */
if (*line == '(' && level == 1) {
/* we found our value so break */
array_start = 1;
break;
}
/* check for '=' so the value follows as next parameter */
if (*line == '=' && level == 0) {
level = 1;
}
}
}
}
/* we got all files, so rewind stream */
fseek(fp, 0L, SEEK_SET);
(*filelist)[fl_count] = NULL;
return found;
}
-186
View File
@@ -1,186 +0,0 @@
/*
* wave.c -- this file contains decompression methods used by Storm.dll
* to decompress wave files.
*
* Copyright (C) 2003 Maik Broemme <mbroemme@plusserver.de>
*
* This source was adepted from the C++ version of wave.cpp included
* in stormlib. The C++ version belongs to the following authors,
*
* Ladislav Zezula <ladik.zezula.net>
* Tom Amigo <tomamigo@apexmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "wave.h"
/* Tables necessary dor decompression */
static unsigned long wave_table_1503f120[] = {
0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000004, 0xFFFFFFFF, 0x00000002, 0xFFFFFFFF, 0x00000006,
0xFFFFFFFF, 0x00000001, 0xFFFFFFFF, 0x00000005, 0xFFFFFFFF, 0x00000003, 0xFFFFFFFF, 0x00000007,
0xFFFFFFFF, 0x00000001, 0xFFFFFFFF, 0x00000005, 0xFFFFFFFF, 0x00000003, 0xFFFFFFFF, 0x00000007,
0xFFFFFFFF, 0x00000002, 0xFFFFFFFF, 0x00000004, 0xFFFFFFFF, 0x00000006, 0xFFFFFFFF, 0x00000008
};
static unsigned long wave_table_1503f1a0[] = {
0x00000007, 0x00000008, 0x00000009, 0x0000000A, 0x0000000B, 0x0000000C, 0x0000000D, 0x0000000E,
0x00000010, 0x00000011, 0x00000013, 0x00000015, 0x00000017, 0x00000019, 0x0000001C, 0x0000001F,
0x00000022, 0x00000025, 0x00000029, 0x0000002D, 0x00000032, 0x00000037, 0x0000003C, 0x00000042,
0x00000049, 0x00000050, 0x00000058, 0x00000061, 0x0000006B, 0x00000076, 0x00000082, 0x0000008F,
0x0000009D, 0x000000AD, 0x000000BE, 0x000000D1, 0x000000E6, 0x000000FD, 0x00000117, 0x00000133,
0x00000151, 0x00000173, 0x00000198, 0x000001C1, 0x000001EE, 0x00000220, 0x00000256, 0x00000292,
0x000002D4, 0x0000031C, 0x0000036C, 0x000003C3, 0x00000424, 0x0000048E, 0x00000502, 0x00000583,
0x00000610, 0x000006AB, 0x00000756, 0x00000812, 0x000008E0, 0x000009C3, 0x00000ABD, 0x00000BD0,
0x00000CFF, 0x00000E4C, 0x00000FBA, 0x0000114C, 0x00001307, 0x000014EE, 0x00001706, 0x00001954,
0x00001BDC, 0x00001EA5, 0x000021B6, 0x00002515, 0x000028CA, 0x00002CDF, 0x0000315B, 0x0000364B,
0x00003BB9, 0x000041B2, 0x00004844, 0x00004F7E, 0x00005771, 0x0000602F, 0x000069CE, 0x00007462,
0x00007FFF
};
/*
* Decompress a wave file, mono or stereo
*
* Offset: 1500F230
*/
int libmpq_wave_decompress(unsigned char *out_buf, int out_length, unsigned char *in_buf, int in_length, int channels) {
byte_and_short out;
byte_and_short in;
unsigned char *in_end = in_buf + in_length; /* End on input buffer */
unsigned long index;
long nr_array1[2];
long nr_array2[2];
int count = 0;
out.pb = out_buf;
in.pb = in_buf;
nr_array1[0] = 0x2C;
nr_array1[1] = 0x2C;
in.pw++;
/* 15007AD7 */
for (count = 0; count < channels; count++) {
long temp;
temp = *(short *)in.pw++;
nr_array2[count] = temp;
if (out_length < 2) {
return out.pb - out_buf;
}
*out.pw++ = (unsigned short)temp;
out_length -= 2;
}
index = channels - 1;
while (in.pb < in_end) {
unsigned char one_byte = *in.pb++;
if (channels == 2) {
index = (index == 0) ? 1 : 0;
}
/*
* Get one byte from input buffer
* 15007B25
*/
if (one_byte & 0x80) {
/* 15007B32 */
switch(one_byte & 0x7F) {
case 0: /* 15007B8E */
if (nr_array1[index] != 0) {
nr_array1[index]--;
}
if (out_length < 2) {
break;
}
*out.pw++ = (unsigned short)nr_array2[index];
out_length -= 2;
continue;
case 1: /* 15007B72 */
nr_array1[index] += 8; /* EBX also */
if (nr_array1[index] > 0x58) {
nr_array1[index] = 0x58;
}
if (channels == 2) {
index = (index == 0) ? 1 : 0;
}
continue;
case 2:
continue;
default:
nr_array1[index] -= 8;
if (nr_array1[index] < 0) {
nr_array1[index] = 0;
}
if (channels != 2) {
continue;
}
index = (index == 0) ? 1 : 0;
continue;
}
} else {
unsigned long temp1 = wave_table_1503f1a0[nr_array1[index]]; /* EDI */
unsigned long temp2 = temp1 >> in_buf[1]; /* ESI */
long temp3 = nr_array2[index]; /* ECX */
if (one_byte & 0x01) { /* EBX = one_byte */
temp2 += (temp1 >> 0);
}
if (one_byte & 0x02) {
temp2 += (temp1 >> 1);
}
if (one_byte & 0x04) {
temp2 += (temp1 >> 2);
}
if (one_byte & 0x08) {
temp2 += (temp1 >> 3);
}
if (one_byte & 0x10) {
temp2 += (temp1 >> 4);
}
if (one_byte & 0x20) {
temp2 += (temp1 >> 5);
}
if(one_byte & 0x40) {
temp3 -= temp2;
if (temp3 <= (long)0xFFFF8000) {
temp3 = (long)0xFFFF8000;
}
} else {
temp3 += temp2;
if (temp3 >= 0x7FFF) {
temp3 = 0x7FFF;
}
}
nr_array2[index] = temp3;
if (out_length < 2) {
break;
}
temp2 = nr_array1[index];
one_byte &= 0x1F;
*out.pw++ = (unsigned short)temp3;
out_length -= 2;
temp2 += wave_table_1503f120[one_byte];
nr_array1[index] = temp2;
if (nr_array1[index] < 0) {
nr_array1[index] = 0;
} else {
if (nr_array1[index] > 0x58) {
nr_array1[index] = 0x58;
}
}
}
}
return (out.pb - out_buf);
}
-38
View File
@@ -1,38 +0,0 @@
/*
* wave.h -- header file for WAVe unplode functions used by mpq-tools.
*
* Copyright (C) 2003 Maik Broemme <mbroemme@plusserver.de>
*
* This source was adepted from the C++ version of wave.h included
* in stormlib. The C++ version belongs to the following authors,
*
* Ladislav Zezula <ladik.zezula.net>
* Tom Amigo <tomamigo@apexmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _WAVE_H
#define _WAVE_H
typedef union {
unsigned short *pw;
unsigned char *pb;
} byte_and_short;
int libmpq_wave_decompress(unsigned char *out_buf, int out_length, unsigned char *in_buf, int in_length, int channels);
#endif /* _WAVE_H */
-324
View File
@@ -1,324 +0,0 @@
/* zconf.h -- configuration of the zlib compression library
* Copyright (C) 1995-2003 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* @(#) $Id$ */
#ifndef ZCONF_H
#define ZCONF_H
/*
* If you *really* need a unique prefix for all types and library functions,
* compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
*/
#ifdef Z_PREFIX
# define deflateInit_ z_deflateInit_
# define deflate z_deflate
# define deflateEnd z_deflateEnd
# define inflateInit_ z_inflateInit_
# define inflate z_inflate
# define inflateEnd z_inflateEnd
# define deflateInit2_ z_deflateInit2_
# define deflateSetDictionary z_deflateSetDictionary
# define deflateCopy z_deflateCopy
# define deflateReset z_deflateReset
# define deflatePrime z_deflatePrime
# define deflateParams z_deflateParams
# define deflateBound z_deflateBound
# define inflateInit2_ z_inflateInit2_
# define inflateSetDictionary z_inflateSetDictionary
# define inflateSync z_inflateSync
# define inflateSyncPoint z_inflateSyncPoint
# define inflateCopy z_inflateCopy
# define inflateReset z_inflateReset
# define compress z_compress
# define compress2 z_compress2
# define compressBound z_compressBound
# define uncompress z_uncompress
# define adler32 z_adler32
# define crc32 z_crc32
# define get_crc_table z_get_crc_table
# define Byte z_Byte
# define uInt z_uInt
# define uLong z_uLong
# define Bytef z_Bytef
# define charf z_charf
# define intf z_intf
# define uIntf z_uIntf
# define uLongf z_uLongf
# define voidpf z_voidpf
# define voidp z_voidp
#endif
#if defined(__MSDOS__) && !defined(MSDOS)
# define MSDOS
#endif
#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
# define OS2
#endif
#if defined(_WINDOWS) && !defined(WINDOWS)
# define WINDOWS
#endif
#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
# define WIN32
#endif
#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
# ifndef SYS16BIT
# define SYS16BIT
# endif
# endif
#endif
/*
* Compile with -DMAXSEG_64K if the alloc function cannot allocate more
* than 64k bytes at a time (needed on systems with 16-bit int).
*/
#ifdef SYS16BIT
# define MAXSEG_64K
#endif
#ifdef MSDOS
# define UNALIGNED_OK
#endif
#ifdef __STDC_VERSION__
# ifndef STDC
# define STDC
# endif
# if __STDC_VERSION__ >= 199901L
# ifndef STDC99
# define STDC99
# endif
# endif
#endif
#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
# define STDC
#endif
#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
# define STDC
#endif
#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
# define STDC
#endif
#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
# define STDC
#endif
#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */
# define STDC
#endif
#ifndef STDC
# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
# define const /* note: need a more gentle solution here */
# endif
#endif
/* Some Mac compilers merge all .h files incorrectly: */
#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__)
# define NO_DUMMY_DECL
#endif
/* Maximum value for memLevel in deflateInit2 */
#ifndef MAX_MEM_LEVEL
# ifdef MAXSEG_64K
# define MAX_MEM_LEVEL 8
# else
# define MAX_MEM_LEVEL 9
# endif
#endif
/* Maximum value for windowBits in deflateInit2 and inflateInit2.
* WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
* created by gzip. (Files created by minigzip can still be extracted by
* gzip.)
*/
#ifndef MAX_WBITS
# define MAX_WBITS 15 /* 32K LZ77 window */
#endif
/* The memory requirements for deflate are (in bytes):
(1 << (windowBits+2)) + (1 << (memLevel+9))
that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
plus a few kilobytes for small objects. For example, if you want to reduce
the default memory requirements from 256K to 128K, compile with
make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
Of course this will generally degrade compression (there's no free lunch).
The memory requirements for inflate are (in bytes) 1 << windowBits
that is, 32K for windowBits=15 (default value) plus a few kilobytes
for small objects.
*/
/* Type declarations */
#ifndef OF /* function prototypes */
# ifdef STDC
# define OF(args) args
# else
# define OF(args) ()
# endif
#endif
/* The following definitions for FAR are needed only for MSDOS mixed
* model programming (small or medium model with some far allocations).
* This was tested only with MSC; for other MSDOS compilers you may have
* to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
* just define FAR to be empty.
*/
#ifdef SYS16BIT
# if defined(M_I86SM) || defined(M_I86MM)
/* MSC small or medium model */
# define SMALL_MEDIUM
# ifdef _MSC_VER
# define FAR _far
# else
# define FAR far
# endif
# endif
# if (defined(__SMALL__) || defined(__MEDIUM__))
/* Turbo C small or medium model */
# define SMALL_MEDIUM
# ifdef __BORLANDC__
# define FAR _far
# else
# define FAR far
# endif
# endif
#endif
#if defined(WINDOWS) || defined(WIN32)
/* If building or using zlib as a DLL, define ZLIB_DLL.
* This is not mandatory, but it offers a little performance increase.
*/
# ifdef ZLIB_DLL
# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
# ifdef ZLIB_INTERNAL
# define ZEXTERN extern __declspec(dllexport)
# else
# define ZEXTERN extern __declspec(dllimport)
# endif
# endif
# endif /* ZLIB_DLL */
/* If building or using zlib with the WINAPI/WINAPIV calling convention,
* define ZLIB_WINAPI.
* Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
*/
# ifdef ZLIB_WINAPI
# ifdef FAR
# undef FAR
# endif
# include <windows.h>
/* No need for _export, use ZLIB.DEF instead. */
/* For complete Windows compatibility, use WINAPI, not __stdcall. */
# define ZEXPORT WINAPI
# ifdef WIN32
# define ZEXPORTVA WINAPIV
# else
# define ZEXPORTVA FAR CDECL
# endif
# endif
#endif
#if defined (__BEOS__)
# ifdef ZLIB_DLL
# ifdef ZLIB_INTERNAL
# define ZEXPORT __declspec(dllexport)
# define ZEXPORTVA __declspec(dllexport)
# else
# define ZEXPORT __declspec(dllimport)
# define ZEXPORTVA __declspec(dllimport)
# endif
# endif
#endif
#ifndef ZEXTERN
# define ZEXTERN extern
#endif
#ifndef ZEXPORT
# define ZEXPORT
#endif
#ifndef ZEXPORTVA
# define ZEXPORTVA
#endif
#ifndef FAR
# define FAR
#endif
#if !defined(__MACTYPES__)
typedef unsigned char Byte; /* 8 bits */
#endif
typedef unsigned int uInt; /* 16 bits or more */
typedef unsigned long uLong; /* 32 bits or more */
#ifdef SMALL_MEDIUM
/* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
# define Bytef Byte FAR
#else
typedef Byte FAR Bytef;
#endif
typedef char FAR charf;
typedef int FAR intf;
typedef uInt FAR uIntf;
typedef uLong FAR uLongf;
#ifdef STDC
typedef void const *voidpc;
typedef void FAR *voidpf;
typedef void *voidp;
#else
typedef Byte const *voidpc;
typedef Byte FAR *voidpf;
typedef Byte *voidp;
#endif
#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */
# include <sys/types.h> /* for off_t */
# include <unistd.h> /* for SEEK_* and off_t */
# ifdef VMS
# include <unixio.h> /* for off_t */
# endif
# define z_off_t off_t
#endif
#ifndef SEEK_SET
# define SEEK_SET 0 /* Seek from beginning of file. */
# define SEEK_CUR 1 /* Seek from current position. */
# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
#endif
#ifndef z_off_t
# define z_off_t long
#endif
#if defined(__OS400__)
#define NO_vsnprintf
#endif
#if defined(__MVS__)
# define NO_vsnprintf
# ifdef FAR
# undef FAR
# endif
#endif
/* MVS linker does not support external names larger than 8 bytes */
#if defined(__MVS__)
# pragma map(deflateInit_,"DEIN")
# pragma map(deflateInit2_,"DEIN2")
# pragma map(deflateEnd,"DEEND")
# pragma map(deflateBound,"DEBND")
# pragma map(inflateInit_,"ININ")
# pragma map(inflateInit2_,"ININ2")
# pragma map(inflateEnd,"INEND")
# pragma map(inflateSync,"INSY")
# pragma map(inflateSetDictionary,"INSEDI")
# pragma map(compressBound,"CMBND")
# pragma map(inflate_table,"INTABL")
# pragma map(inflate_fast,"INFA")
# pragma map(inflate_copyright,"INCOPY")
#endif
#endif /* ZCONF_H */
File diff suppressed because it is too large. Load diff
Binary file not shown.