diff options
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | int-bios.h | 26 | ||||
-rw-r--r-- | mpq-bios.c | 64 | ||||
-rw-r--r-- | mpq-bios.h | 4 | ||||
-rw-r--r-- | mpq-misc.c | 10 | ||||
-rw-r--r-- | mpq-misc.h | 17 |
6 files changed, 122 insertions, 3 deletions
@@ -4,11 +4,13 @@ AR = ar rcs CPPFLAGS = -g -Wall -Werror SOURCE_LIST = \ +MPQCryptography.c \ errors.c \ extract.c \ mpq-bios.c \ -MPQCryptography.c \ mpq-errors.c \ +mpq-misc.c \ + TARGET = mpqlib.a diff --git a/int-bios.h b/int-bios.h new file mode 100644 index 0000000..1c05d29 --- /dev/null +++ b/int-bios.h @@ -0,0 +1,26 @@ +#ifndef __INT_BIOS_H__ +#define __INT_BIOS_H__ + +#include <unistd.h> +#include <sys/types.h> + +#include "mpq-bios.h" + +typedef struct { + uint64_t block_offset; + uint32_t block_size; + uint32_t file_size; + uint32_t flags; +} block_t; + +#define FLAGS_FILE_COMP_IMPLODE 0x00000100 +#define FLAGS_FILE_COMP_MULTI 0x00000200 +#define FLAGS_FILE_COMPRESSED 0x0000FF00 +#define FLAGS_FILE_ENCRYPTED 0x00010000 +#define FLAGS_FILE_EXISTS 0x80000000 + +const block_t * __mpqlib_get_block_entry(mpq_archive_t *, int); +int __mpqlib_seek(mpq_archive_t *, off_t); +int __mpqlib_read(mpq_archive_t *, void *, size_t); + +#endif @@ -9,6 +9,8 @@ #include "MPQCryptography.h" #include "mpq-bios.h" #include "mpq-errors.h" +#include "mpq-misc.h" +#include "int-bios.h" #include "errors.h" #include "inttypes.h" @@ -54,6 +56,8 @@ typedef struct { uint32_t file_block_index; } hash_t; +/* Defined in int-bios.h + typedef struct { uint64_t block_offset; uint32_t block_size; @@ -61,6 +65,8 @@ typedef struct { uint32_t flags; } block_t; +*/ + struct mpq_internals_t { int fd; int closeit; @@ -89,7 +95,7 @@ mpq_archive_t * mpqlib_open_archive(const char * fname) { int fd; mpq_archive_t * r; - if ((fd = open(fname, O_RDONLY | O_BINARY)) == -1) { + if ((fd = open(fname, O_RDONLY | O_LARGEFILE | O_BINARY)) == -1) { __mpqlib_errno = MPQLIB_ERROR_OPEN; return NULL; } @@ -185,7 +191,7 @@ mpq_archive_t * mpqlib_reopen_archive(int fd) { no_mpq(); if (mpq_h.format_version == 1) { - if (read(fd, ((char *)(&mpq_h)) + STD_HEADER_SIZE, EXT_HEADER_SIZE) != EXT_HEADER_SIZE) + if (!read_data(mpq_a, ((char *)(&mpq_h)) + STD_HEADER_SIZE, EXT_HEADER_SIZE)) no_mpq(); } else { mpq_h.extended_block_table_offset = 0; @@ -290,3 +296,57 @@ mpq_archive_t * mpqlib_reopen_archive(int fd) { return mpq_a; } + +void mpqlib_printtables(mpq_archive_t * mpq_a) { + int i; + + printf("Hash table dump.\n"); + printf("HashA HashB language platform index\n"); + printf("-------- -------- -------- -------- -----\n"); + for (i = 0; i < mpq_a->mpq_i->hash_table_entries; i++) { + printf("%08X %08X %08X %08X %d\n", mpq_a->mpq_i->hashs[i].file_path_hasha, mpq_a->mpq_i->hashs[i].file_path_hashb, mpq_a->mpq_i->hashs[i].language, mpq_a->mpq_i->hashs[i].platform, mpq_a->mpq_i->hashs[i].file_block_index); + } + + printf("\n\nBlock table dump.\n"); + printf("Entry Block offset size filesize flags\n"); + printf("-------- ---------------- -------- -------- --------\n"); + for (i = 0; i < mpq_a->mpq_i->block_table_entries; i++) { + printf("%8d %016llX %8d %8d %08X\n", i, mpq_a->mpq_i->blocks[i].block_offset, mpq_a->mpq_i->blocks[i].block_size, mpq_a->mpq_i->blocks[i].file_size, mpq_a->mpq_i->blocks[i].flags); + } +} + +int mpqlib_find_hash_entry(mpq_archive_t * mpq_a, const char * name, uint32_t language, uint32_t platform) { + int i; + uint32_t hA, hB; + + hA = mpqlib_hashA_filename(name); + hB = mpqlib_hashB_filename(name); + + for (i = 0; i < mpq_a->mpq_i->hash_table_entries; i++) { + if ((mpq_a->mpq_i->hashs[i].file_path_hasha == hA) && + (mpq_a->mpq_i->hashs[i].file_path_hashb == hB) && + (mpq_a->mpq_i->hashs[i].language == language) && + (mpq_a->mpq_i->hashs[i].platform == platform)) { + return mpq_a->mpq_i->hashs[i].file_block_index; + } + } + + return -1; +} + +const block_t * __mpqlib_get_block_entry(mpq_archive_t * mpq_a, int entry) { + if ((entry >= mpq_a->mpq_i->block_table_entries) || (entry < 0)) + return NULL; + + return mpq_a->mpq_i->blocks + entry; +} + +int __mpqlib_seek(mpq_archive_t * mpq_a, off_t off) { + if (lseek64(mpq_a->mpq_i->fd, off, SEEK_SET) != off) + return 0; + return 1; +} + +int __mpqlib_read(mpq_archive_t * mpq_a, void * buffer, size_t size) { + return read_data(mpq_a, buffer, size); +} @@ -1,6 +1,8 @@ #ifndef __MPQ_BIOS_H__ #define __MPQ_BIOS_H__ +#include "inttypes.h" + struct mpq_internals_t; typedef struct { @@ -16,7 +18,9 @@ extern "C" { void mpqlib_init(); mpq_archive_t * mpqlib_open_archive(const char * fname); mpq_archive_t * mpqlib_reopen_archive(int fd); +void mpqlib_printtables(mpq_archive_t *); void mpqlib_close_archive(mpq_archive_t *); +int mpqlib_find_hash_entry(mpq_archive_t *, const char * name, uint32_t language, uint32_t platform); #ifdef __cplusplus } diff --git a/mpq-misc.c b/mpq-misc.c new file mode 100644 index 0000000..1e81659 --- /dev/null +++ b/mpq-misc.c @@ -0,0 +1,10 @@ +#include "mpq-misc.h" +#include "MPQCryptography.h" + +uint32_t mpqlib_hashA_filename(const char * str) { + return __mpqlib_hash_cstring(str, 1); +} + +uint32_t mpqlib_hashB_filename(const char * str) { + return __mpqlib_hash_cstring(str, 2); +} diff --git a/mpq-misc.h b/mpq-misc.h new file mode 100644 index 0000000..f4fe6f2 --- /dev/null +++ b/mpq-misc.h @@ -0,0 +1,17 @@ +#ifndef __MPQ_MISC_H__ +#define __MPQ_MISC_H__ + +#include <inttypes.h> + +#ifdef __cplusplus +extern "C" { +#endif + +uint32_t mpqlib_hashA_filename(const char * str); +uint32_t mpqlib_hashB_filename(const char * str); + +#ifdef __cplusplus +} +#endif + +#endif |