Browse Source

Reorder mpqapi.cpp

pull/911/head
Anders Jenbo 5 years ago
parent
commit
f2f4de8e33
  1. 532
      Source/mpqapi.cpp
  2. 27
      Source/mpqapi.h

532
Source/mpqapi.cpp

@ -21,39 +21,23 @@ BOOLEAN save_archive_open;
HANDLE sghArchive = INVALID_HANDLE_VALUE;
BOOL mpqapi_set_hidden(const char *pszArchive, BOOL hidden)
static void mpqapi_xor_buf(char *pbData)
{
DWORD dwFileAttributes;
DWORD dwFileAttributesToSet;
dwFileAttributes = GetFileAttributes(pszArchive);
if (dwFileAttributes == INVALID_FILE_ATTRIBUTES)
return GetLastError() == ERROR_FILE_NOT_FOUND;
dwFileAttributesToSet = hidden ? FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN : 0;
if (dwFileAttributes == dwFileAttributesToSet)
return TRUE;
else
return SetFileAttributes(pszArchive, dwFileAttributesToSet);
}
DWORD mask;
char *pbCurrentData;
int i;
void mpqapi_store_creation_time(const char *pszArchive, DWORD dwChar)
{
HANDLE handle;
struct _WIN32_FIND_DATAA FindFileData;
char dst[160];
mask = 0xF0761AB;
pbCurrentData = pbData;
if (gbMaxPlayers != 1) {
mpqapi_reg_load_modification_time(dst, 160);
handle = FindFirstFile(pszArchive, &FindFileData);
if (handle != INVALID_HANDLE_VALUE) {
FindClose(handle);
*((FILETIME *)(dst) + dwChar * 2) = FindFileData.ftCreationTime;
mpqapi_reg_store_modification_time(dst, 160);
}
for (i = 0; i < 8; i++) {
*pbCurrentData ^= mask;
pbCurrentData++;
mask = _rotl(mask, 1);
}
}
BOOL mpqapi_reg_load_modification_time(char *dst, int size)
static BOOL mpqapi_reg_load_modification_time(char *dst, int size)
{
char *pszDst;
char *pbData;
@ -81,20 +65,42 @@ BOOL mpqapi_reg_load_modification_time(char *dst, int size)
return TRUE;
}
void mpqapi_xor_buf(char *pbData)
static BOOLEAN mpqapi_reg_store_modification_time(char *pbData, DWORD dwLen)
{
DWORD mask;
char *pbCurrentData;
int i;
char *pbCurrentData, *pbDataToXor;
DWORD i;
mask = 0xF0761AB;
pbCurrentData = pbData;
for (i = 0; i < 8; i++) {
*pbCurrentData ^= mask;
pbCurrentData++;
mask = _rotl(mask, 1);
if (dwLen >= 8) {
i = dwLen >> 3;
do {
pbDataToXor = pbCurrentData;
pbCurrentData += 8;
mpqapi_xor_buf(pbDataToXor);
i--;
} while (i);
}
#ifdef SPAWN
return SRegSaveData(APP_NAME, "Audio Playback ", 0, (BYTE *)pbData, dwLen);
#else
return SRegSaveData(APP_NAME, "Video Player ", 0, (BYTE *)pbData, dwLen);
#endif
}
BOOL mpqapi_set_hidden(const char *pszArchive, BOOL hidden)
{
DWORD dwFileAttributes;
DWORD dwFileAttributesToSet;
dwFileAttributes = GetFileAttributes(pszArchive);
if (dwFileAttributes == INVALID_FILE_ATTRIBUTES)
return GetLastError() == ERROR_FILE_NOT_FOUND;
dwFileAttributesToSet = hidden ? FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN : 0;
if (dwFileAttributes == dwFileAttributesToSet)
return TRUE;
else
return SetFileAttributes(pszArchive, dwFileAttributesToSet);
}
void mpqapi_store_default_time(DWORD dwChar)
@ -115,49 +121,63 @@ void mpqapi_store_default_time(DWORD dwChar)
*/
}
BOOLEAN mpqapi_reg_store_modification_time(char *pbData, DWORD dwLen)
static void mpqapi_store_modified_time(const char *pszArchive, DWORD dwChar)
{
char *pbCurrentData, *pbDataToXor;
DWORD i;
HANDLE handle;
struct _WIN32_FIND_DATAA FindFileData;
char dst[160];
pbCurrentData = pbData;
if (dwLen >= 8) {
i = dwLen >> 3;
do {
pbDataToXor = pbCurrentData;
pbCurrentData += 8;
mpqapi_xor_buf(pbDataToXor);
i--;
} while (i);
if (gbMaxPlayers != 1) {
mpqapi_reg_load_modification_time(dst, 160);
handle = FindFirstFile(pszArchive, &FindFileData);
if (handle != INVALID_HANDLE_VALUE) {
FindClose(handle);
*((FILETIME *)(dst) + dwChar * 2 + 1) = FindFileData.ftLastWriteTime;
mpqapi_reg_store_modification_time(dst, 160);
}
}
}
#ifdef SPAWN
return SRegSaveData(APP_NAME, "Audio Playback ", 0, (BYTE *)pbData, dwLen);
#else
return SRegSaveData(APP_NAME, "Video Player ", 0, (BYTE *)pbData, dwLen);
#endif
void mpqapi_store_creation_time(const char *pszArchive, DWORD dwChar)
{
HANDLE handle;
struct _WIN32_FIND_DATAA FindFileData;
char dst[160];
if (gbMaxPlayers != 1) {
mpqapi_reg_load_modification_time(dst, 160);
handle = FindFirstFile(pszArchive, &FindFileData);
if (handle != INVALID_HANDLE_VALUE) {
FindClose(handle);
*((FILETIME *)(dst) + dwChar * 2) = FindFileData.ftCreationTime;
mpqapi_reg_store_modification_time(dst, 160);
}
}
}
void mpqapi_remove_hash_entry(const char *pszName)
static _BLOCKENTRY *mpqapi_new_block(int *block_index)
{
_HASHENTRY *pHashTbl;
_BLOCKENTRY *blockEntry;
int hIdx, block_offset, block_size;
DWORD i;
hIdx = FetchHandle(pszName);
if (hIdx != -1) {
pHashTbl = &sgpHashTbl[hIdx];
blockEntry = &sgpBlockTbl[pHashTbl->block];
pHashTbl->block = -2;
block_offset = blockEntry->offset;
block_size = blockEntry->sizealloc;
memset(blockEntry, 0, sizeof(*blockEntry));
mpqapi_alloc_block(block_offset, block_size);
save_archive_modified = TRUE;
blockEntry = sgpBlockTbl;
i = 0;
while (blockEntry->offset || blockEntry->sizealloc || blockEntry->flags || blockEntry->sizefile) {
i++;
blockEntry++;
if (i >= 2048) {
app_fatal("Out of free block entries");
return NULL;
}
}
if (block_index)
*block_index = i;
return blockEntry;
}
void mpqapi_alloc_block(int block_offset, int block_size)
static void mpqapi_alloc_block(int block_offset, int block_size)
{
_BLOCKENTRY *block;
int i;
@ -196,34 +216,38 @@ void mpqapi_alloc_block(int block_offset, int block_size)
}
}
_BLOCKENTRY *mpqapi_new_block(int *block_index)
static int mpqapi_find_free_block(int size, int *block_size)
{
_BLOCKENTRY *blockEntry;
DWORD i;
blockEntry = sgpBlockTbl;
_BLOCKENTRY *pBlockTbl;
int i, result;
i = 0;
while (blockEntry->offset || blockEntry->sizealloc || blockEntry->flags || blockEntry->sizefile) {
i++;
blockEntry++;
if (i >= 2048) {
app_fatal("Out of free block entries");
return NULL;
pBlockTbl = sgpBlockTbl;
i = 2048;
while (1) {
i--;
if (pBlockTbl->offset && !pBlockTbl->flags && !pBlockTbl->sizefile && (DWORD)pBlockTbl->sizealloc >= size)
break;
pBlockTbl++;
if (!i) {
*block_size = size;
result = sgdwMpqOffset;
sgdwMpqOffset += size;
return result;
}
}
if (block_index)
*block_index = i;
return blockEntry;
}
result = pBlockTbl->offset;
*block_size = size;
pBlockTbl->offset += size;
pBlockTbl->sizealloc -= size;
int FetchHandle(const char *pszName)
{
return mpqapi_get_hash_index(Hash(pszName, 0), Hash(pszName, 1), Hash(pszName, 2), 0);
if (!pBlockTbl->sizealloc)
memset(pBlockTbl, 0, sizeof(*pBlockTbl));
return result;
}
int mpqapi_get_hash_index(short index, int hash_a, int hash_b, int locale)
static int mpqapi_get_hash_index(short index, int hash_a, int hash_b, int locale)
{
int idx, i;
@ -238,32 +262,141 @@ int mpqapi_get_hash_index(short index, int hash_a, int hash_b, int locale)
return -1;
}
void mpqapi_remove_hash_entries(BOOL(__stdcall *fnGetName)(DWORD, char *))
static BOOL WriteMPQHeader()
{
DWORD dwIndex, i;
char pszFileName[MAX_PATH];
_FILEHEADER fhdr;
DWORD NumberOfBytesWritten;
dwIndex = 1;
for (i = fnGetName(0, pszFileName); i; i = fnGetName(dwIndex++, pszFileName)) {
mpqapi_remove_hash_entry(pszFileName);
}
memset(&fhdr, 0, sizeof(fhdr));
fhdr.signature = '\x1AQPM';
fhdr.headersize = 32;
fhdr.filesize = GetFileSize(sghArchive, 0);
fhdr.version = 0;
fhdr.sectorsizeid = 3;
fhdr.hashoffset = 32872;
fhdr.blockoffset = 104;
fhdr.hashcount = 2048;
fhdr.blockcount = 2048;
if (SetFilePointer(sghArchive, 0, NULL, FILE_BEGIN) == -1)
return FALSE;
if (!WriteFile(sghArchive, &fhdr, sizeof(fhdr), &NumberOfBytesWritten, 0))
return FALSE;
return NumberOfBytesWritten == 104;
}
BOOL mpqapi_write_file(const char *pszName, const BYTE *pbData, DWORD dwLen)
static BOOL mpqapi_write_block_table()
{
_BLOCKENTRY *blockEntry;
BOOL success;
DWORD NumberOfBytesWritten;
save_archive_modified = TRUE;
mpqapi_remove_hash_entry(pszName);
blockEntry = mpqapi_add_file(pszName, 0, 0);
if (!mpqapi_write_file_contents(pszName, pbData, dwLen, blockEntry)) {
mpqapi_remove_hash_entry(pszName);
if (SetFilePointer(sghArchive, 104, NULL, FILE_BEGIN) == -1)
return FALSE;
Encrypt((DWORD *)sgpBlockTbl, 0x8000, Hash("(block table)", 3));
success = WriteFile(sghArchive, sgpBlockTbl, 0x8000, &NumberOfBytesWritten, 0);
Decrypt((DWORD *)sgpBlockTbl, 0x8000, Hash("(block table)", 3));
return success && NumberOfBytesWritten == 0x8000;
}
static BOOL mpqapi_write_hash_table()
{
BOOL success;
DWORD NumberOfBytesWritten;
if (SetFilePointer(sghArchive, 32872, NULL, FILE_BEGIN) == -1)
return FALSE;
Encrypt((DWORD *)sgpHashTbl, 0x8000, Hash("(hash table)", 3));
success = WriteFile(sghArchive, sgpHashTbl, 0x8000, &NumberOfBytesWritten, 0);
Decrypt((DWORD *)sgpHashTbl, 0x8000, Hash("(hash table)", 3));
return success && NumberOfBytesWritten == 0x8000;
}
static BOOL mpqapi_can_seek()
{
if (SetFilePointer(sghArchive, sgdwMpqOffset, NULL, FILE_BEGIN) == -1)
return FALSE;
return SetEndOfFile(sghArchive);
}
static BOOL ParseMPQHeader(_FILEHEADER *pHdr, DWORD *pdwNextFileStart)
{
DWORD size;
DWORD NumberOfBytesRead;
size = GetFileSize(sghArchive, 0);
*pdwNextFileStart = size;
if (size == -1
|| size < sizeof(*pHdr)
|| !ReadFile(sghArchive, pHdr, sizeof(*pHdr), &NumberOfBytesRead, NULL)
|| NumberOfBytesRead != 104
|| pHdr->signature != '\x1AQPM'
|| pHdr->headersize != 32
|| pHdr->version > 0
|| pHdr->sectorsizeid != 3
|| pHdr->filesize != size
|| pHdr->hashoffset != 32872
|| pHdr->blockoffset != 104
|| pHdr->hashcount != 2048
|| pHdr->blockcount != 2048) {
if (SetFilePointer(sghArchive, 0, NULL, FILE_BEGIN) == -1)
return FALSE;
if (!SetEndOfFile(sghArchive))
return FALSE;
memset(pHdr, 0, sizeof(*pHdr));
pHdr->signature = '\x1AQPM';
pHdr->headersize = 32;
pHdr->sectorsizeid = 3;
pHdr->version = 0;
*pdwNextFileStart = 0x10068;
save_archive_modified = TRUE;
save_archive_open = TRUE;
}
return TRUE;
}
_BLOCKENTRY *mpqapi_add_file(const char *pszName, _BLOCKENTRY *pBlk, int block_index)
static int FetchHandle(const char *pszName)
{
return mpqapi_get_hash_index(Hash(pszName, 0), Hash(pszName, 1), Hash(pszName, 2), 0);
}
void mpqapi_remove_hash_entry(const char *pszName)
{
_HASHENTRY *pHashTbl;
_BLOCKENTRY *blockEntry;
int hIdx, block_offset, block_size;
hIdx = FetchHandle(pszName);
if (hIdx != -1) {
pHashTbl = &sgpHashTbl[hIdx];
blockEntry = &sgpBlockTbl[pHashTbl->block];
pHashTbl->block = -2;
block_offset = blockEntry->offset;
block_size = blockEntry->sizealloc;
memset(blockEntry, 0, sizeof(*blockEntry));
mpqapi_alloc_block(block_offset, block_size);
save_archive_modified = TRUE;
}
}
void mpqapi_remove_hash_entries(BOOL(__stdcall *fnGetName)(DWORD, char *))
{
DWORD dwIndex, i;
char pszFileName[MAX_PATH];
dwIndex = 1;
for (i = fnGetName(0, pszFileName); i; i = fnGetName(dwIndex++, pszFileName)) {
mpqapi_remove_hash_entry(pszFileName);
}
}
static _BLOCKENTRY *mpqapi_add_file(const char *pszName, _BLOCKENTRY *pBlk, int block_index)
{
DWORD h1, h2, h3;
int i, hIdx;
@ -293,7 +426,7 @@ _BLOCKENTRY *mpqapi_add_file(const char *pszName, _BLOCKENTRY *pBlk, int block_i
return pBlk;
}
BOOL mpqapi_write_file_contents(const char *pszName, const BYTE *pbData, DWORD dwLen, _BLOCKENTRY *pBlk)
static BOOL mpqapi_write_file_contents(const char *pszName, const BYTE *pbData, DWORD dwLen, _BLOCKENTRY *pBlk)
{
DWORD *sectoroffsettable;
DWORD destsize, num_bytes, block_size, nNumberOfBytesToWrite;
@ -379,35 +512,18 @@ on_error:
return FALSE;
}
int mpqapi_find_free_block(int size, int *block_size)
BOOL mpqapi_write_file(const char *pszName, const BYTE *pbData, DWORD dwLen)
{
_BLOCKENTRY *pBlockTbl;
int i, result;
_BLOCKENTRY *blockEntry;
pBlockTbl = sgpBlockTbl;
i = 2048;
while (1) {
i--;
if (pBlockTbl->offset && !pBlockTbl->flags && !pBlockTbl->sizefile && (DWORD)pBlockTbl->sizealloc >= size)
break;
pBlockTbl++;
if (!i) {
*block_size = size;
result = sgdwMpqOffset;
sgdwMpqOffset += size;
return result;
}
save_archive_modified = TRUE;
mpqapi_remove_hash_entry(pszName);
blockEntry = mpqapi_add_file(pszName, 0, 0);
if (!mpqapi_write_file_contents(pszName, pbData, dwLen, blockEntry)) {
mpqapi_remove_hash_entry(pszName);
return FALSE;
}
result = pBlockTbl->offset;
*block_size = size;
pBlockTbl->offset += size;
pBlockTbl->sizealloc -= size;
if (!pBlockTbl->sizealloc)
memset(pBlockTbl, 0, sizeof(*pBlockTbl));
return result;
return TRUE;
}
void mpqapi_rename(char *pszOld, char *pszNew)
@ -432,6 +548,26 @@ BOOL mpqapi_has_file(const char *pszName)
return FetchHandle(pszName) != -1;
}
static void CloseMPQ(const char *pszArchive, BOOL bFree, DWORD dwChar)
{
if (bFree) {
MemFreeDbg(sgpBlockTbl);
MemFreeDbg(sgpHashTbl);
}
if (sghArchive != INVALID_HANDLE_VALUE) {
CloseHandle(sghArchive);
sghArchive = INVALID_HANDLE_VALUE;
}
if (save_archive_modified) {
save_archive_modified = FALSE;
mpqapi_store_modified_time(pszArchive, dwChar);
}
if (save_archive_open) {
save_archive_open = FALSE;
mpqapi_store_creation_time(pszArchive, dwChar);
}
}
BOOL OpenMPQ(const char *pszArchive, BOOL hidden, DWORD dwChar)
{
DWORD dwFlagsAndAttributes;
@ -486,83 +622,6 @@ on_error:
return FALSE;
}
BOOL ParseMPQHeader(_FILEHEADER *pHdr, DWORD *pdwNextFileStart)
{
DWORD size;
DWORD NumberOfBytesRead;
size = GetFileSize(sghArchive, 0);
*pdwNextFileStart = size;
if (size == -1
|| size < sizeof(*pHdr)
|| !ReadFile(sghArchive, pHdr, sizeof(*pHdr), &NumberOfBytesRead, NULL)
|| NumberOfBytesRead != 104
|| pHdr->signature != '\x1AQPM'
|| pHdr->headersize != 32
|| pHdr->version > 0
|| pHdr->sectorsizeid != 3
|| pHdr->filesize != size
|| pHdr->hashoffset != 32872
|| pHdr->blockoffset != 104
|| pHdr->hashcount != 2048
|| pHdr->blockcount != 2048) {
if (SetFilePointer(sghArchive, 0, NULL, FILE_BEGIN) == -1)
return FALSE;
if (!SetEndOfFile(sghArchive))
return FALSE;
memset(pHdr, 0, sizeof(*pHdr));
pHdr->signature = '\x1AQPM';
pHdr->headersize = 32;
pHdr->sectorsizeid = 3;
pHdr->version = 0;
*pdwNextFileStart = 0x10068;
save_archive_modified = TRUE;
save_archive_open = TRUE;
}
return TRUE;
}
void CloseMPQ(const char *pszArchive, BOOL bFree, DWORD dwChar)
{
if (bFree) {
MemFreeDbg(sgpBlockTbl);
MemFreeDbg(sgpHashTbl);
}
if (sghArchive != INVALID_HANDLE_VALUE) {
CloseHandle(sghArchive);
sghArchive = INVALID_HANDLE_VALUE;
}
if (save_archive_modified) {
save_archive_modified = FALSE;
mpqapi_store_modified_time(pszArchive, dwChar);
}
if (save_archive_open) {
save_archive_open = FALSE;
mpqapi_store_creation_time(pszArchive, dwChar);
}
}
void mpqapi_store_modified_time(const char *pszArchive, DWORD dwChar)
{
HANDLE handle;
struct _WIN32_FIND_DATAA FindFileData;
char dst[160];
if (gbMaxPlayers != 1) {
mpqapi_reg_load_modification_time(dst, 160);
handle = FindFirstFile(pszArchive, &FindFileData);
if (handle != INVALID_HANDLE_VALUE) {
FindClose(handle);
*((FILETIME *)(dst) + dwChar * 2 + 1) = FindFileData.ftLastWriteTime;
mpqapi_reg_store_modification_time(dst, 160);
}
}
}
BOOL mpqapi_flush_and_close(const char *pszArchive, BOOL bFree, DWORD dwChar)
{
BOOL ret = FALSE;
@ -582,62 +641,3 @@ BOOL mpqapi_flush_and_close(const char *pszArchive, BOOL bFree, DWORD dwChar)
CloseMPQ(pszArchive, bFree, dwChar);
return ret;
}
BOOL WriteMPQHeader()
{
_FILEHEADER fhdr;
DWORD NumberOfBytesWritten;
memset(&fhdr, 0, sizeof(fhdr));
fhdr.signature = '\x1AQPM';
fhdr.headersize = 32;
fhdr.filesize = GetFileSize(sghArchive, 0);
fhdr.version = 0;
fhdr.sectorsizeid = 3;
fhdr.hashoffset = 32872;
fhdr.blockoffset = 104;
fhdr.hashcount = 2048;
fhdr.blockcount = 2048;
if (SetFilePointer(sghArchive, 0, NULL, FILE_BEGIN) == -1)
return FALSE;
if (!WriteFile(sghArchive, &fhdr, sizeof(fhdr), &NumberOfBytesWritten, 0))
return FALSE;
return NumberOfBytesWritten == 104;
}
BOOL mpqapi_write_block_table()
{
BOOL success;
DWORD NumberOfBytesWritten;
if (SetFilePointer(sghArchive, 104, NULL, FILE_BEGIN) == -1)
return FALSE;
Encrypt((DWORD *)sgpBlockTbl, 0x8000, Hash("(block table)", 3));
success = WriteFile(sghArchive, sgpBlockTbl, 0x8000, &NumberOfBytesWritten, 0);
Decrypt((DWORD *)sgpBlockTbl, 0x8000, Hash("(block table)", 3));
return success && NumberOfBytesWritten == 0x8000;
}
BOOL mpqapi_write_hash_table()
{
BOOL success;
DWORD NumberOfBytesWritten;
if (SetFilePointer(sghArchive, 32872, NULL, FILE_BEGIN) == -1)
return FALSE;
Encrypt((DWORD *)sgpHashTbl, 0x8000, Hash("(hash table)", 3));
success = WriteFile(sghArchive, sgpHashTbl, 0x8000, &NumberOfBytesWritten, 0);
Decrypt((DWORD *)sgpHashTbl, 0x8000, Hash("(hash table)", 3));
return success && NumberOfBytesWritten == 0x8000;
}
BOOL mpqapi_can_seek()
{
if (SetFilePointer(sghArchive, sgdwMpqOffset, NULL, FILE_BEGIN) == -1)
return FALSE;
return SetEndOfFile(sghArchive);
}

27
Source/mpqapi.h

@ -6,40 +6,13 @@
#ifndef __MPQAPI_H__
#define __MPQAPI_H__
extern BYTE mpq_buf[4096];
extern BOOL save_archive_modified;
extern BOOLEAN save_archive_open;
BOOL mpqapi_set_hidden(const char *pszArchive, BOOL hidden);
void mpqapi_store_creation_time(const char *pszArchive, DWORD dwChar);
BOOL mpqapi_reg_load_modification_time(char *dst, int size);
void mpqapi_xor_buf(char *pbData);
void mpqapi_store_default_time(DWORD dwChar);
BOOLEAN mpqapi_reg_store_modification_time(char *pbData, DWORD dwLen);
void mpqapi_remove_hash_entry(const char *pszName);
void mpqapi_alloc_block(int block_offset, int block_size);
_BLOCKENTRY *mpqapi_new_block(int *block_index);
int FetchHandle(const char *pszName);
int mpqapi_get_hash_index(short index, int hash_a, int hash_b, int locale);
void mpqapi_remove_hash_entries(BOOL(__stdcall *fnGetName)(DWORD, char *));
BOOL mpqapi_write_file(const char *pszName, const BYTE *pbData, DWORD dwLen);
_BLOCKENTRY *mpqapi_add_file(const char *pszName, _BLOCKENTRY *pBlk, int block_index);
BOOL mpqapi_write_file_contents(const char *pszName, const BYTE *pbData, DWORD dwLen, _BLOCKENTRY *pBlk);
int mpqapi_find_free_block(int size, int *block_size);
void mpqapi_rename(char *pszOld, char *pszNew);
BOOL mpqapi_has_file(const char *pszName);
BOOL OpenMPQ(const char *pszArchive, BOOL hidden, DWORD dwChar);
BOOL ParseMPQHeader(_FILEHEADER *pHdr, DWORD *pdwNextFileStart);
void CloseMPQ(const char *pszArchive, BOOL bFree, DWORD dwChar);
void mpqapi_store_modified_time(const char *pszArchive, DWORD dwChar);
BOOL mpqapi_flush_and_close(const char *pszArchive, BOOL bFree, DWORD dwChar);
BOOL WriteMPQHeader();
BOOL mpqapi_write_block_table();
BOOL mpqapi_write_hash_table();
BOOL mpqapi_can_seek();
/* rdata */
/* data */
#endif /* __MPQAPI_H__ */

Loading…
Cancel
Save