summaryrefslogtreecommitdiff
path: root/mpq-bios.c
diff options
context:
space:
mode:
Diffstat (limited to 'mpq-bios.c')
-rw-r--r--mpq-bios.c31
1 files changed, 31 insertions, 0 deletions
diff --git a/mpq-bios.c b/mpq-bios.c
index 88da2ac..8251b95 100644
--- a/mpq-bios.c
+++ b/mpq-bios.c
@@ -14,6 +14,10 @@
#include "errors.h"
#include "inttypes.h"
+/*
+ * MPQ header.
+ */
+
typedef struct {
/* basic version of the header. */
char magic[4];
@@ -33,6 +37,10 @@ typedef struct {
uint16_t block_table_offset_high;
} __attribute__ ((packed)) mpq_header_t;
+/*
+ * One hash entry.
+ */
+
typedef struct {
uint32_t file_path_hasha;
uint32_t file_path_hashb;
@@ -41,6 +49,10 @@ typedef struct {
uint32_t file_block_index;
} __attribute__ ((packed)) mpq_hash_t;
+/*
+ * One block entry.
+ */
+
typedef struct {
uint32_t block_offset;
uint32_t block_size;
@@ -48,6 +60,11 @@ typedef struct {
uint32_t flags;
} __attribute__ ((packed)) mpq_block_t;
+
+/*
+ * This are our internal structures.
+ */
+
typedef struct {
uint32_t file_path_hasha;
uint32_t file_path_hashb;
@@ -169,15 +186,18 @@ struct mpq_archive_t * mpqlib_reopen_archive(int fd) {
mpq_a->closeit = 0;
mpq_a->fd = fd;
+ /* Reading the main header, and doing basic checks. */
if (read(fd, &mpq_h, STD_HEADER_SIZE) != STD_HEADER_SIZE)
no_mpq();
if (strncmp(mpq_h.magic, "MPQ\x1a", 4))
no_mpq();
+ /* format_version can only be 0 or 1 - the latter beeing for Burning Crusade */
if ((mpq_h.format_version | 1) != 1)
no_mpq();
+ /* If the format is extended, let's read the extra data, otherwise let's fill it with zeroes */
if (mpq_h.format_version == 1) {
if (!read_data(mpq_a, ((char *)(&mpq_h)) + STD_HEADER_SIZE, EXT_HEADER_SIZE))
no_mpq();
@@ -187,6 +207,7 @@ struct mpq_archive_t * mpqlib_reopen_archive(int fd) {
mpq_h.block_table_offset_high = 0;
}
+ /* Let's start copying / interpreting / rebuilding basic header data */
mpq_a->header_size = mpq_h.header_size;
mpq_a->archive_size = mpq_h.archive_size;
mpq_a->format_version = mpq_h.format_version;
@@ -198,6 +219,7 @@ struct mpq_archive_t * mpqlib_reopen_archive(int fd) {
mpq_a->block_table_entries = mpq_h.block_table_entries;
mpq_a->extended_block_table_offset = mpq_h.extended_block_table_offset;
+ /* Allocation and reading of our hash and block tables */
if (!(mpq_a->hashs = (hash_t *) malloc(mpq_a->hash_table_entries * sizeof(hash_t)))) {
__mpqlib_errno = MPQLIB_ERROR_MEMORY;
free(mpq_a);
@@ -252,9 +274,11 @@ struct mpq_archive_t * mpqlib_reopen_archive(int fd) {
}
}
+ /* Hash and block table are (easily) encrypted - let's decrypt them before going on any further */
__mpqlib_decrypt(mpq_hashs, mpq_a->hash_table_entries * sizeof(mpq_block_t), __mpqlib_hash_cstring("(hash table)", 3), 1);
__mpqlib_decrypt(mpq_blocks, mpq_a->block_table_entries * sizeof(mpq_block_t), __mpqlib_hash_cstring("(block table)", 3), 1);
+ /* Copying / interpreting / rebuilding of the hash table. */
for (i = 0; i < mpq_a->hash_table_entries; i++) {
/****TODO****/
/* Implement various checks of the hash table. */
@@ -265,6 +289,7 @@ struct mpq_archive_t * mpqlib_reopen_archive(int fd) {
mpq_a->hashs[i].file_block_index = mpq_hashs[i].file_block_index;
}
+ /* Copying / interpreting / rebuilding of the block table. */
for (i = 0; i < mpq_a->block_table_entries; i++) {
/****TODO****/
/* Implement various checks of the block table. */
@@ -274,6 +299,7 @@ struct mpq_archive_t * mpqlib_reopen_archive(int fd) {
mpq_a->blocks[i].flags = mpq_blocks[i].flags;
}
+ /* All done, let's clean up and exit. */
if (mpq_extblocks)
free(mpq_extblocks);
@@ -283,6 +309,10 @@ struct mpq_archive_t * mpqlib_reopen_archive(int fd) {
return mpq_a;
}
+/*
+ * Verbose display of an archive.
+ */
+
void mpqlib_printtables(struct mpq_archive_t * mpq_a) {
int i;
@@ -327,6 +357,7 @@ int mpqlib_find_hash_entry_by_name(struct mpq_archive_t * mpq_a, const char * na
int mpqlib_find_hash_entry_by_hash(struct mpq_archive_t * mpq_a, uint32_t h, uint32_t hA, uint32_t hB, uint32_t language, uint32_t platform) {
int i;
+ /* The hash table is a true one, pre-built. We can access it as-it, speeding up the searches drastically. */
for (i = h & (mpq_a->hash_table_entries - 1); i < mpq_a->hash_table_entries; i++) {
if ((mpq_a->hashs[i].file_path_hasha == hA) &&
(mpq_a->hashs[i].file_path_hashb == hB) &&