| 1 | /* |
|---|
| 2 | * mpq.h -- some default types and defines. |
|---|
| 3 | * |
|---|
| 4 | * Copyright (C) 2003 Maik Broemme <mbroemme@plusserver.de> |
|---|
| 5 | * |
|---|
| 6 | * This source was adepted from the C++ version of StormLib.h and |
|---|
| 7 | * StormPort.h included in stormlib. The C++ version belongs to |
|---|
| 8 | * the following authors, |
|---|
| 9 | * |
|---|
| 10 | * Ladislav Zezula <ladik.zezula.net> |
|---|
| 11 | * Marko Friedemann <marko.friedemann@bmx-chemnitz.de> |
|---|
| 12 | * |
|---|
| 13 | * This program is free software; you can redistribute it and/or modify |
|---|
| 14 | * it under the terms of the GNU General Public License as published by |
|---|
| 15 | * the Free Software Foundation; either version 2 of the License, or |
|---|
| 16 | * (at your option) any later version. |
|---|
| 17 | * |
|---|
| 18 | * This program is distributed in the hope that it will be useful, |
|---|
| 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 21 | * GNU General Public License for more details. |
|---|
| 22 | * |
|---|
| 23 | * You should have received a copy of the GNU General Public License |
|---|
| 24 | * along with this program; if not, write to the Free Software |
|---|
| 25 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
|---|
| 26 | * |
|---|
| 27 | * $Id: mpq.h,v 1.8 2004/02/12 00:45:50 mbroemme Exp $ |
|---|
| 28 | */ |
|---|
| 29 | |
|---|
| 30 | #ifndef _MPQ_H |
|---|
| 31 | #define _MPQ_H |
|---|
| 32 | |
|---|
| 33 | #include <limits.h> |
|---|
| 34 | |
|---|
| 35 | #ifndef PATH_MAX |
|---|
| 36 | #define PATH_MAX 260 |
|---|
| 37 | #endif |
|---|
| 38 | |
|---|
| 39 | |
|---|
| 40 | #define LIBMPQ_MAJOR_VERSION 0 /* Major version number... maybe sometimes we reach version 1 :) */ |
|---|
| 41 | #define LIBMPQ_MINOR_VERSION 3 /* Minor version number - increased only for small changes */ |
|---|
| 42 | #define LIBMPQ_PATCH_VERSION 0 /* Patchlevel - changed on bugfixes etc... */ |
|---|
| 43 | |
|---|
| 44 | #define LIBMPQ_TOOLS_SUCCESS 0 /* return value for all functions which success */ |
|---|
| 45 | #define LIBMPQ_TOOLS_BUFSIZE 0x500 /* buffer size for the decryption engine */ |
|---|
| 46 | |
|---|
| 47 | #define LIBMPQ_EFILE -1 /* error on file operation */ |
|---|
| 48 | #define LIBMPQ_EFILE_FORMAT -2 /* bad file format */ |
|---|
| 49 | #define LIBMPQ_EFILE_CORRUPT -3 /* file corrupt */ |
|---|
| 50 | #define LIBMPQ_EFILE_NOT_FOUND -4 /* file in archive not found */ |
|---|
| 51 | #define LIBMPQ_EFILE_READ -5 /* Read error in archive */ |
|---|
| 52 | #define LIBMPQ_EALLOCMEM -6 /* maybe not enough memory? :) */ |
|---|
| 53 | #define LIBMPQ_EFREEMEM -7 /* can not free memory */ |
|---|
| 54 | #define LIBMPQ_EINV_RANGE -8 /* Given filenumber is out of range */ |
|---|
| 55 | #define LIBMPQ_EHASHTABLE -9 /* error in reading hashtable */ |
|---|
| 56 | #define LIBMPQ_EBLOCKTABLE -10 /* error in reading blocktable */ |
|---|
| 57 | |
|---|
| 58 | #define LIBMPQ_ID_MPQ 0x1A51504D /* MPQ archive header ID ('MPQ\x1A') */ |
|---|
| 59 | #define LIBMPQ_HEADER_W3M 0x6D9E4B86 /* special value used by W3M Map Protector */ |
|---|
| 60 | #define LIBMPQ_FLAG_PROTECTED 0x00000002 /* Set on protected MPQs (like W3M maps) */ |
|---|
| 61 | #define LIBMPQ_HASH_ENTRY_DELETED 0xFFFFFFFE /* Block index for deleted hash entry */ |
|---|
| 62 | |
|---|
| 63 | #define LIBMPQ_FILE_COMPRESS_PKWARE 0x00000100 /* Compression made by PKWARE Data Compression Library */ |
|---|
| 64 | #define LIBMPQ_FILE_COMPRESS_MULTI 0x00000200 /* Multiple compressions */ |
|---|
| 65 | #define LIBMPQ_FILE_COMPRESSED 0x0000FF00 /* File is compressed */ |
|---|
| 66 | #define LIBMPQ_FILE_EXISTS 0x80000000 /* Set if file exists, reset when the file was deleted */ |
|---|
| 67 | #define LIBMPQ_FILE_ENCRYPTED 0x00010000 /* Indicates whether file is encrypted */ |
|---|
| 68 | #define LIBMPQ_FILE_HAS_METADATA 0x04000000 |
|---|
| 69 | |
|---|
| 70 | #define LIBMPQ_FILE_COMPRESSED_SIZE 1 /* MPQ compressed filesize of given file */ |
|---|
| 71 | #define LIBMPQ_FILE_UNCOMPRESSED_SIZE 2 /* MPQ uncompressed filesize of given file */ |
|---|
| 72 | #define LIBMPQ_FILE_COMPRESSION_TYPE 3 /* MPQ compression type of given file */ |
|---|
| 73 | #define LIBMPQ_FILE_TYPE_INT 4 /* file is given by number */ |
|---|
| 74 | #define LIBMPQ_FILE_TYPE_CHAR 5 /* file is given by name */ |
|---|
| 75 | |
|---|
| 76 | #define LIBMPQ_MPQ_ARCHIVE_SIZE 1 /* MPQ archive size */ |
|---|
| 77 | #define LIBMPQ_MPQ_HASHTABLE_SIZE 2 /* MPQ archive hashtable size */ |
|---|
| 78 | #define LIBMPQ_MPQ_BLOCKTABLE_SIZE 3 /* MPQ archive blocktable size */ |
|---|
| 79 | #define LIBMPQ_MPQ_BLOCKSIZE 4 /* MPQ archive blocksize */ |
|---|
| 80 | #define LIBMPQ_MPQ_NUMFILES 5 /* Number of files in the MPQ archive */ |
|---|
| 81 | #define LIBMPQ_MPQ_COMPRESSED_SIZE 6 /* Compressed archive size */ |
|---|
| 82 | #define LIBMPQ_MPQ_UNCOMPRESSED_SIZE 7 /* Uncompressed archive size */ |
|---|
| 83 | |
|---|
| 84 | #define LIBMPQ_HUFF_DECOMPRESS 0 /* Defines that we want to decompress using huffman trees. */ |
|---|
| 85 | |
|---|
| 86 | #define LIBMPQ_CONF_EFILE_OPEN -1 /* error if a specific listfile was forced and could not be opened. */ |
|---|
| 87 | #define LIBMPQ_CONF_EFILE_CORRUPT -2 /* listfile seems to be corrupt */ |
|---|
| 88 | #define LIBMPQ_CONF_EFILE_LIST_CORRUPT -3 /* listfile seems correct, but filelist is broken */ |
|---|
| 89 | #define LIBMPQ_CONF_EFILE_NOT_FOUND -4 /* error if no matching listfile found */ |
|---|
| 90 | #define LIBMPQ_CONF_EFILE_VERSION -5 /* libmpq version does not match required listfile version */ |
|---|
| 91 | |
|---|
| 92 | #ifndef FALSE |
|---|
| 93 | #define FALSE 0 |
|---|
| 94 | #endif |
|---|
| 95 | #ifndef TRUE |
|---|
| 96 | #define TRUE 1 |
|---|
| 97 | #endif |
|---|
| 98 | |
|---|
| 99 | /* |
|---|
| 100 | #ifndef min |
|---|
| 101 | #define min(a, b) ((a < b) ? a : b) |
|---|
| 102 | #endif |
|---|
| 103 | */ |
|---|
| 104 | |
|---|
| 105 | typedef unsigned int mpq_buffer[LIBMPQ_TOOLS_BUFSIZE]; |
|---|
| 106 | typedef int (*DECOMPRESS)(char *, int *, char *, int); |
|---|
| 107 | typedef struct { |
|---|
| 108 | unsigned long mask; /* Decompression bit */ |
|---|
| 109 | DECOMPRESS decompress; /* Decompression function */ |
|---|
| 110 | } decompress_table; |
|---|
| 111 | |
|---|
| 112 | /* MPQ file header */ |
|---|
| 113 | typedef struct { |
|---|
| 114 | unsigned int id; /* The 0x1A51504D ('MPQ\x1A') signature */ |
|---|
| 115 | unsigned int offset; /* Offset of the first file (Relative to MPQ start) */ |
|---|
| 116 | unsigned int archivesize; /* Size of MPQ archive */ |
|---|
| 117 | unsigned short offsetsc; /* 0000 for SC and BW */ |
|---|
| 118 | unsigned short blocksize; /* Size of file block is (0x200 << blockSize) */ |
|---|
| 119 | unsigned int hashtablepos; /* File position of hashTable */ |
|---|
| 120 | unsigned int blocktablepos; /* File position of blockTable. Each entry has 16 bytes */ |
|---|
| 121 | unsigned int hashtablesize; /* Number of entries in hash table */ |
|---|
| 122 | unsigned int blocktablesize; /* Number of entries in the block table */ |
|---|
| 123 | } mpq_header; |
|---|
| 124 | //} __attribute__ ((packed)) mpq_header; |
|---|
| 125 | |
|---|
| 126 | |
|---|
| 127 | /* Hash entry. All files in the archive are searched by their hashes. */ |
|---|
| 128 | typedef struct { |
|---|
| 129 | unsigned int name1; /* The first two unsigned ints */ |
|---|
| 130 | unsigned int name2; /* are the encrypted file name */ |
|---|
| 131 | unsigned int locale; /* Locale information. */ |
|---|
| 132 | unsigned int blockindex; /* Index to file description block */ |
|---|
| 133 | } mpq_hash; |
|---|
| 134 | |
|---|
| 135 | /* File description block contains informations about the file */ |
|---|
| 136 | typedef struct { |
|---|
| 137 | unsigned int filepos; /* Block file starting position in the archive */ |
|---|
| 138 | unsigned int csize; /* Compressed file size */ |
|---|
| 139 | unsigned int fsize; /* Uncompressed file size */ |
|---|
| 140 | unsigned int flags; /* Flags */ |
|---|
| 141 | } mpq_block; |
|---|
| 142 | |
|---|
| 143 | /* File handle structure used since Diablo 1.00 (0x38 bytes) */ |
|---|
| 144 | typedef struct { |
|---|
| 145 | unsigned char filename[PATH_MAX]; /* filename of the actual file in the archive */ |
|---|
| 146 | int fd; /* File handle */ |
|---|
| 147 | unsigned int seed; /* Seed used for file decrypt */ |
|---|
| 148 | unsigned int filepos; /* Current file position */ |
|---|
| 149 | unsigned int offset; |
|---|
| 150 | unsigned int nblocks; /* Number of blocks in the file (incl. the last noncomplete one) */ |
|---|
| 151 | unsigned int *blockpos; /* Position of each file block (only for compressed files) */ |
|---|
| 152 | int blockposloaded; /* TRUE if block positions loaded */ |
|---|
| 153 | unsigned int offset2; /* (Number of bytes somewhere ?) */ |
|---|
| 154 | mpq_hash *mpq_h; /* Hash table entry */ |
|---|
| 155 | mpq_block *mpq_b; /* File block pointer */ |
|---|
| 156 | |
|---|
| 157 | /* Non-Storm.dll members */ |
|---|
| 158 | |
|---|
| 159 | unsigned int accessed; /* Was something from the file already read? */ |
|---|
| 160 | } mpq_file; |
|---|
| 161 | |
|---|
| 162 | /* List handle structure */ |
|---|
| 163 | typedef struct { |
|---|
| 164 | unsigned char mpq_version[10]; /* libmpq version required by the listfile */ |
|---|
| 165 | unsigned char mpq_name[PATH_MAX]; /* mpq archive name without full path */ |
|---|
| 166 | unsigned char mpq_type[20]; /* mpq archive type */ |
|---|
| 167 | unsigned char mpq_game[40]; /* blizzard title the file matches */ |
|---|
| 168 | unsigned char mpq_game_version[10]; /* game version */ |
|---|
| 169 | unsigned char **mpq_files; /* filelist */ |
|---|
| 170 | } mpq_list; |
|---|
| 171 | |
|---|
| 172 | /* Archive handle structure used since Diablo 1.00 */ |
|---|
| 173 | typedef struct { |
|---|
| 174 | unsigned char filename[PATH_MAX]; /* Opened archive file name */ |
|---|
| 175 | int fd; /* File handle */ |
|---|
| 176 | unsigned int blockpos; /* Position of loaded block in the file */ |
|---|
| 177 | unsigned int blocksize; /* Size of file block */ |
|---|
| 178 | unsigned char *blockbuf; /* Buffer (cache) for file block */ |
|---|
| 179 | unsigned int bufpos; /* Position in block buffer */ |
|---|
| 180 | unsigned int mpqpos; /* MPQ archive position in the file */ |
|---|
| 181 | unsigned int filepos; /* Current file pointer */ |
|---|
| 182 | unsigned int openfiles; /* Number of open files + 1 */ |
|---|
| 183 | mpq_buffer buf; /* MPQ buffer */ |
|---|
| 184 | mpq_header *header; /* MPQ file header */ |
|---|
| 185 | mpq_hash *hashtable; /* Hash table */ |
|---|
| 186 | mpq_block *blocktable; /* Block table */ |
|---|
| 187 | |
|---|
| 188 | /* Non-Storm.dll members */ |
|---|
| 189 | |
|---|
| 190 | mpq_list *mpq_l; /* Handle to file list from database */ |
|---|
| 191 | |
|---|
| 192 | unsigned int flags; /* See LIBMPQ_TOOLS_FLAG_XXXXX */ |
|---|
| 193 | unsigned int maxblockindex; /* The highest block table entry */ |
|---|
| 194 | } mpq_archive; |
|---|
| 195 | |
|---|
| 196 | extern char *libmpq_version(); |
|---|
| 197 | extern int libmpq_archive_open(mpq_archive *mpq_a, unsigned char *mpq_filename); |
|---|
| 198 | extern int libmpq_archive_close(mpq_archive *mpq_a); |
|---|
| 199 | extern int libmpq_archive_info(mpq_archive *mpq_a, unsigned int infotype); |
|---|
| 200 | //extern int libmpq_file_extract(mpq_archive *mpq_a, const int number); |
|---|
| 201 | extern int libmpq_file_info(mpq_archive *mpq_a, unsigned int infotype, const unsigned int number); |
|---|
| 202 | extern char *libmpq_file_name(mpq_archive *mpq_a, const int number); |
|---|
| 203 | extern int libmpq_file_number(mpq_archive *mpq_a, const char *name); |
|---|
| 204 | extern int libmpq_file_check(mpq_archive *mpq_a, void *file, int type); |
|---|
| 205 | extern int libmpq_listfile_open(mpq_archive *mpq_a, char file[PATH_MAX]); |
|---|
| 206 | extern int libmpq_listfile_close(mpq_archive *mpq_a); |
|---|
| 207 | |
|---|
| 208 | extern int libmpq_pkzip_decompress(char *out_buf, int *out_length, char *in_buf, int in_length); |
|---|
| 209 | extern int libmpq_zlib_decompress(char *out_buf, int *out_length, char *in_buf, int in_length); |
|---|
| 210 | extern int libmpq_huff_decompress(char *out_buf, int *out_length, char *in_buf, int in_length); |
|---|
| 211 | extern int libmpq_wave_decompress_stereo(char *out_buf, int *out_length, char *in_buf, int in_length); |
|---|
| 212 | extern int libmpq_wave_decompress_mono(char *out_buf, int *out_length, char *in_buf, int in_length); |
|---|
| 213 | extern int libmpq_multi_decompress(char *out_buf, int *pout_length, char *in_buf, int in_length); |
|---|
| 214 | |
|---|
| 215 | static decompress_table dcmp_table[] = { |
|---|
| 216 | {0x08, libmpq_pkzip_decompress}, /* Decompression with Pkware Data Compression Library */ |
|---|
| 217 | {0x02, libmpq_zlib_decompress}, /* Decompression with the "zlib" library */ |
|---|
| 218 | {0x01, libmpq_huff_decompress}, /* Huffmann decompression */ |
|---|
| 219 | {0x80, libmpq_wave_decompress_stereo}, /* WAVE decompression for stereo waves */ |
|---|
| 220 | {0x40, libmpq_wave_decompress_mono} /* WAVE decompression for mono waves */ |
|---|
| 221 | }; |
|---|
| 222 | |
|---|
| 223 | int libmpq_file_extract(mpq_archive *mpq_a, const int number, const char *filename); |
|---|
| 224 | int libmpq_file_getdata(mpq_archive *mpq_a, mpq_hash mpq_h, const int number, unsigned char *dest); |
|---|
| 225 | #endif /* _MPQ_H */ |
|---|