aboutsummaryrefslogtreecommitdiff
path: root/contrib/extractor/libmpq/mpq.h
blob: 58eef6bead284f49eca8d94a755d8ad5fe084fcc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
/*
 *  mpq.h -- some default types and defines.
 *
 *  Copyright (C) 2003 Maik Broemme <mbroemme@plusserver.de>
 *
 *  This source was adepted from the C++ version of StormLib.h and
 *  StormPort.h included in stormlib. The C++ version belongs to
 *  the following authors,
 *
 *  Ladislav Zezula <ladik.zezula.net>
 *  Marko Friedemann <marko.friedemann@bmx-chemnitz.de>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 *  $Id: mpq.h,v 1.8 2004/02/12 00:45:50 mbroemme Exp $
 */

#ifndef _MPQ_H
#define _MPQ_H

#include <limits.h>

#ifndef PATH_MAX
    #define PATH_MAX 260
#endif


#define LIBMPQ_MAJOR_VERSION        0       /* Major version number... maybe sometimes we reach version 1 :) */
#define LIBMPQ_MINOR_VERSION        3       /* Minor version number - increased only for small changes */
#define LIBMPQ_PATCH_VERSION        0       /* Patchlevel - changed on bugfixes etc... */

#define LIBMPQ_TOOLS_SUCCESS        0       /* return value for all functions which success */
#define LIBMPQ_TOOLS_BUFSIZE        0x500       /* buffer size for the decryption engine */

#define LIBMPQ_EFILE            -1      /* error on file operation */
#define LIBMPQ_EFILE_FORMAT     -2      /* bad file format */
#define LIBMPQ_EFILE_CORRUPT        -3      /* file corrupt */
#define LIBMPQ_EFILE_NOT_FOUND      -4      /* file in archive not found */
#define LIBMPQ_EFILE_READ       -5      /* Read error in archive */
#define LIBMPQ_EALLOCMEM        -6      /* maybe not enough memory? :) */
#define LIBMPQ_EFREEMEM         -7      /* can not free memory */
#define LIBMPQ_EINV_RANGE       -8      /* Given filenumber is out of range */
#define LIBMPQ_EHASHTABLE       -9      /* error in reading hashtable */
#define LIBMPQ_EBLOCKTABLE      -10     /* error in reading blocktable */

#define LIBMPQ_ID_MPQ           0x1A51504D  /* MPQ archive header ID ('MPQ\x1A') */
#define LIBMPQ_HEADER_W3M       0x6D9E4B86  /* special value used by W3M Map Protector */
#define LIBMPQ_FLAG_PROTECTED       0x00000002  /* Set on protected MPQs (like W3M maps) */
#define LIBMPQ_HASH_ENTRY_DELETED   0xFFFFFFFE  /* Block index for deleted hash entry */

#define LIBMPQ_FILE_COMPRESS_PKWARE 0x00000100  /* Compression made by PKWARE Data Compression Library */
#define LIBMPQ_FILE_COMPRESS_MULTI  0x00000200  /* Multiple compressions */
#define LIBMPQ_FILE_COMPRESSED      0x0000FF00  /* File is compressed */
#define LIBMPQ_FILE_EXISTS      0x80000000  /* Set if file exists, reset when the file was deleted */
#define LIBMPQ_FILE_ENCRYPTED       0x00010000  /* Indicates whether file is encrypted */
#define LIBMPQ_FILE_HAS_METADATA    0x04000000

#define LIBMPQ_FILE_COMPRESSED_SIZE 1       /* MPQ compressed filesize of given file */
#define LIBMPQ_FILE_UNCOMPRESSED_SIZE   2       /* MPQ uncompressed filesize of given file */
#define LIBMPQ_FILE_COMPRESSION_TYPE    3       /* MPQ compression type of given file */
#define LIBMPQ_FILE_TYPE_INT        4       /* file is given by number */
#define LIBMPQ_FILE_TYPE_CHAR       5       /* file is given by name */

#define LIBMPQ_MPQ_ARCHIVE_SIZE     1       /* MPQ archive size */
#define LIBMPQ_MPQ_HASHTABLE_SIZE   2       /* MPQ archive hashtable size */
#define LIBMPQ_MPQ_BLOCKTABLE_SIZE  3       /* MPQ archive blocktable size */
#define LIBMPQ_MPQ_BLOCKSIZE        4       /* MPQ archive blocksize */
#define LIBMPQ_MPQ_NUMFILES     5       /* Number of files in the MPQ archive */
#define LIBMPQ_MPQ_COMPRESSED_SIZE  6       /* Compressed archive size */
#define LIBMPQ_MPQ_UNCOMPRESSED_SIZE    7       /* Uncompressed archive size */

#define LIBMPQ_HUFF_DECOMPRESS      0       /* Defines that we want to decompress using huffman trees. */

#define LIBMPQ_CONF_EFILE_OPEN      -1      /* error if a specific listfile was forced and could not be opened. */
#define LIBMPQ_CONF_EFILE_CORRUPT   -2      /* listfile seems to be corrupt */
#define LIBMPQ_CONF_EFILE_LIST_CORRUPT  -3      /* listfile seems correct, but filelist is broken */
#define LIBMPQ_CONF_EFILE_NOT_FOUND -4      /* error if no matching listfile found */
#define LIBMPQ_CONF_EFILE_VERSION   -5      /* libmpq version does not match required listfile version */

#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif

/*
#ifndef min
#define min(a, b) ((a < b) ? a : b)
#endif
*/

typedef unsigned int    mpq_buffer[LIBMPQ_TOOLS_BUFSIZE];
typedef int     (*DECOMPRESS)(char *, int *, char *, int);
typedef struct {
    unsigned long   mask;       /* Decompression bit */
    DECOMPRESS  decompress; /* Decompression function */
} decompress_table;

/* MPQ file header */
typedef struct {
    unsigned int    id;     /* The 0x1A51504D ('MPQ\x1A') signature */
    unsigned int    offset;     /* Offset of the first file (Relative to MPQ start) */
    unsigned int    archivesize;    /* Size of MPQ archive */
    unsigned short  offsetsc;   /* 0000 for SC and BW */
    unsigned short  blocksize;  /* Size of file block is (0x200 << blockSize) */
    unsigned int    hashtablepos;   /* File position of hashTable */
    unsigned int    blocktablepos;  /* File position of blockTable. Each entry has 16 bytes */
    unsigned int    hashtablesize;  /* Number of entries in hash table */
    unsigned int    blocktablesize; /* Number of entries in the block table */
} mpq_header;
//} __attribute__ ((packed)) mpq_header;


/* Hash entry. All files in the archive are searched by their hashes. */
typedef struct {
    unsigned int    name1;      /* The first two unsigned ints */
    unsigned int    name2;      /* are the encrypted file name */
    unsigned int    locale;     /* Locale information. */
    unsigned int    blockindex; /* Index to file description block */
} mpq_hash;

/* File description block contains informations about the file */
typedef struct {
    unsigned int    filepos;    /* Block file starting position in the archive */
    unsigned int    csize;      /* Compressed file size */
    unsigned int    fsize;      /* Uncompressed file size */
    unsigned int    flags;      /* Flags */
} mpq_block;

/* File handle structure used since Diablo 1.00 (0x38 bytes) */
typedef struct {
    unsigned char   filename[PATH_MAX]; /* filename of the actual file in the archive */
    int     fd;     /* File handle */
    unsigned int    seed;       /* Seed used for file decrypt */
    unsigned int    filepos;    /* Current file position */
    unsigned int    offset;
    unsigned int    nblocks;    /* Number of blocks in the file (incl. the last noncomplete one) */
    unsigned int    *blockpos;  /* Position of each file block (only for compressed files) */
    int     blockposloaded; /* TRUE if block positions loaded */
    unsigned int    offset2;    /* (Number of bytes somewhere ?) */
    mpq_hash    *mpq_h;     /* Hash table entry */
    mpq_block   *mpq_b;     /* File block pointer */

    /* Non-Storm.dll members */

    unsigned int    accessed;   /* Was something from the file already read? */
} mpq_file;

/* List handle structure */
typedef struct {
    unsigned char   mpq_version[10];    /* libmpq version required by the listfile */
    unsigned char   mpq_name[PATH_MAX]; /* mpq archive name without full path */
    unsigned char   mpq_type[20];       /* mpq archive type */
    unsigned char   mpq_game[40];       /* blizzard title the file matches */
    unsigned char   mpq_game_version[10];   /* game version */
    unsigned char   **mpq_files;        /* filelist */
} mpq_list;

/* Archive handle structure used since Diablo 1.00 */
typedef struct {
    unsigned char   filename[PATH_MAX]; /* Opened archive file name */
    int     fd;     /* File handle */
    unsigned int    blockpos;   /* Position of loaded block in the file */
    unsigned int    blocksize;  /* Size of file block */
    unsigned char   *blockbuf;  /* Buffer (cache) for file block */
    unsigned int    bufpos;     /* Position in block buffer */
    unsigned int    mpqpos;     /* MPQ archive position in the file */
    unsigned int    filepos;    /* Current file pointer */
    unsigned int    openfiles;  /* Number of open files + 1 */
    mpq_buffer  buf;        /* MPQ buffer */
    mpq_header  *header;    /* MPQ file header */
    mpq_hash    *hashtable; /* Hash table */
    mpq_block   *blocktable;    /* Block table */

    /* Non-Storm.dll members */

    mpq_list    *mpq_l;     /* Handle to file list from database */

    unsigned int    flags;      /* See LIBMPQ_TOOLS_FLAG_XXXXX */
    unsigned int    maxblockindex;  /* The highest block table entry */
} mpq_archive;

extern char *libmpq_version();
extern int libmpq_archive_open(mpq_archive *mpq_a, unsigned char *mpq_filename);
extern int libmpq_archive_close(mpq_archive *mpq_a);
extern int libmpq_archive_info(mpq_archive *mpq_a, unsigned int infotype);
//extern int libmpq_file_extract(mpq_archive *mpq_a, const int number);
extern int libmpq_file_info(mpq_archive *mpq_a, unsigned int infotype, const 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 */