summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/common/grfio.c430
-rw-r--r--src/common/grfio.h88
-rw-r--r--src/map/map.c3
3 files changed, 332 insertions, 189 deletions
diff --git a/src/common/grfio.c b/src/common/grfio.c
index 4283529d6..0a9708f17 100644
--- a/src/common/grfio.c
+++ b/src/common/grfio.c
@@ -35,9 +35,11 @@
#include <sys/stat.h>
#include <zlib.h>
-//----------------------------
-// file entry table struct
-//----------------------------
+/** @file
+ * Implementation of the GRF I/O interface.
+ */
+
+/// File entry table struct.
struct grf_filelist {
int srclen; ///< compressed size
int srclen_aligned;
@@ -50,9 +52,11 @@ struct grf_filelist {
int8 gentry; ///< read grf file select
};
-#define FILELIST_TYPE_FILE 0x01 // entry is a file
-#define FILELIST_TYPE_ENCRYPT_MIXED 0x02 // encryption mode 0 (header DES + periodic DES/shuffle)
-#define FILELIST_TYPE_ENCRYPT_HEADER 0x04 // encryption mode 1 (header DES only)
+enum grf_filelist_type {
+ FILELIST_TYPE_FILE = 0x01, ///< entry is a file
+ FILELIST_TYPE_ENCRYPT_MIXED = 0x02, ///< encryption mode 0 (header DES + periodic DES/shuffle)
+ FILELIST_TYPE_ENCRYPT_HEADER = 0x04, ///< encryption mode 1 (header DES only)
+};
//gentry ... > 0 : data read from a grf file (gentry_table[gentry-1])
//gentry ... 0 : data read from a local file (data directory)
@@ -80,23 +84,26 @@ struct grfio_interface grfio_s;
struct grfio_interface *grfio;
// little endian char array to uint conversion
-static unsigned int getlong(unsigned char* p)
+static unsigned int getlong(unsigned char *p)
{
return (p[0] << 0 | p[1] << 8 | p[2] << 16 | p[3] << 24);
}
-static void NibbleSwap(unsigned char* src, int len)
+static void NibbleSwap(unsigned char *src, int len)
{
- while( len > 0 )
- {
+ while (len > 0) {
*src = (*src >> 4) | (*src << 4);
++src;
--len;
}
}
-/// Substitutes some specific values for others, leaves rest intact. Obfuscation.
-/// NOTE: Operation is symmetric (calling it twice gives back the original input).
+/**
+ * (De)-obfuscates data.
+ *
+ * Substitutes some specific values for others, leaves rest intact.
+ * NOTE: Operation is symmetric (calling it twice gives back the original input).
+ */
static uint8_t grf_substitution(uint8_t in)
{
uint8_t out;
@@ -157,20 +164,33 @@ static void grf_shuffle_dec(struct des_bit64 *src)
*src = out;
}
-static void grf_decode_header(unsigned char* buf, size_t len)
+/**
+ * Decodes header-encrypted grf data.
+ *
+ * @param[in,out] buf Data to decode (in-place).
+ * @param[in] len Length of the data.
+ */
+static void grf_decode_header(unsigned char *buf, size_t len)
{
struct des_bit64 *p = (struct des_bit64 *)buf;
size_t nblocks = len / sizeof(struct des_bit64);
size_t i;
// first 20 blocks are all des-encrypted
- for( i = 0; i < 20 && i < nblocks; ++i )
+ for (i = 0; i < 20 && i < nblocks; ++i)
des->decrypt_block(&p[i]);
// the rest is plaintext, done.
}
-static void grf_decode_full(unsigned char* buf, size_t len, int cycle)
+/**
+ * Decodes fully encrypted grf data
+ *
+ * @param[in,out] buf Data to decode (in-place).
+ * @param[in] len Length of the data.
+ * @param[in] cycle The current decoding cycle.
+ */
+static void grf_decode_full(unsigned char *buf, size_t len, int cycle)
{
struct des_bit64 *p = (struct des_bit64 *)buf;
size_t nblocks = len / sizeof(struct des_bit64);
@@ -178,7 +198,7 @@ static void grf_decode_full(unsigned char* buf, size_t len, int cycle)
size_t i, j;
// first 20 blocks are all des-encrypted
- for( i = 0; i < 20 && i < nblocks; ++i )
+ for (i = 0; i < 20 && i < nblocks; ++i)
des->decrypt_block(&p[i]);
// after that only one of every 'dcycle' blocks is des-encrypted
@@ -189,17 +209,16 @@ static void grf_decode_full(unsigned char* buf, size_t len, int cycle)
// so decrypt/de-shuffle periodically
j = (size_t)-1; // 0, adjusted to fit the ++j step
- for( i = 20; i < nblocks; ++i )
- {
- if( i % dcycle == 0 )
- {// decrypt block
+ for (i = 20; i < nblocks; ++i) {
+ if (i % dcycle == 0) {
+ // decrypt block
des->decrypt_block(&p[i]);
continue;
}
++j;
- if( j % scycle == 0 && j != 0 )
- {// de-shuffle block
+ if (j % scycle == 0 && j != 0) {
+ // de-shuffle block
grf_shuffle_dec(&p[i]);
continue;
}
@@ -208,22 +227,25 @@ static void grf_decode_full(unsigned char* buf, size_t len, int cycle)
}
}
-/// Decodes grf data.
-/// @param buf data to decode (in-place)
-/// @param len length of the data
-/// @param entry_type flags associated with the data
-/// @param entry_len true (unaligned) length of the data
-static void grf_decode(unsigned char* buf, size_t len, char entry_type, int entry_len)
+/**
+ * Decodes grf data.
+ *
+ * @param[in,out] buf Data to decode (in-place).
+ * @param[in] len Length of the data
+ * @param[in] entry_type Flags associated with the data.
+ * @param[in] entry_len True (unaligned) length of the data.
+ */
+static void grf_decode(unsigned char *buf, size_t len, char entry_type, int entry_len)
{
- if( entry_type & FILELIST_TYPE_ENCRYPT_MIXED )
- {// fully encrypted
+ if (entry_type & FILELIST_TYPE_ENCRYPT_MIXED) {
+ // fully encrypted
int digits;
int cycle;
int i;
// compute number of digits of the entry length
digits = 1;
- for( i = 10; i <= entry_len; i *= 10 )
+ for (i = 10; i <= entry_len; i *= 10)
++digits;
// choose size of gap between two encrypted blocks
@@ -235,51 +257,47 @@ static void grf_decode(unsigned char* buf, size_t len, char entry_type, int entr
: digits + 15;
grf_decode_full(buf, len, cycle);
- }
- else
- if( entry_type & FILELIST_TYPE_ENCRYPT_HEADER )
- {// header encrypted
+ } else if (entry_type & FILELIST_TYPE_ENCRYPT_HEADER) {
+ // header encrypted
grf_decode_header(buf, len);
}
- else
- {// plaintext
- ;
- }
+ /* else plaintext */
}
-/******************************************************
- *** Zlib Subroutines ***
- ******************************************************/
+/* Zlib Subroutines */
-/// zlib crc32
-unsigned long grfio_crc32(const unsigned char* buf, unsigned int len)
+/// @copydoc grfio_interface::crc32()
+unsigned long grfio_crc32(const unsigned char *buf, unsigned int len)
{
return crc32(crc32(0L, Z_NULL, 0), buf, len);
}
-/// zlib uncompress
-int decode_zip(void* dest, unsigned long* destLen, const void* source, unsigned long sourceLen)
+/// @copydoc grfio_interface::decode_zip
+int grfio_decode_zip(void *dest, unsigned long *dest_len, const void *source, unsigned long source_len)
{
- return uncompress((Bytef*)dest, destLen, (const Bytef*)source, sourceLen);
+ return uncompress(dest, dest_len, source, source_len);
}
-/// zlib compress
-int encode_zip(void* dest, unsigned long* destLen, const void* source, unsigned long sourceLen) {
- if( *destLen == 0 ) /* [Ind/Hercules] */
- *destLen = compressBound(sourceLen);
- if( dest == NULL ) { /* [Ind/Hercules] */
- CREATE(dest, unsigned char, *destLen);
+/// @copydoc grfio_interface::encode_zip
+int grfio_encode_zip(void *dest, unsigned long *dest_len, const void *source, unsigned long source_len)
+{
+ if (*dest_len == 0) /* [Ind/Hercules] */
+ *dest_len = compressBound(source_len);
+ if (dest == NULL) {
+ /* [Ind/Hercules] */
+ CREATE(dest, unsigned char, *dest_len);
}
- return compress((Bytef*)dest, destLen, (const Bytef*)source, sourceLen);
+ return compress(dest, dest_len, source, source_len);
}
-/***********************************************************
- *** File List Subroutines ***
- ***********************************************************/
-// file list hash table
+/* File List Subroutines */
+
+/// File list hash table
int filelist_hash[256];
-// initializes the table that holds the first elements of all hash chains
+/**
+ * Initializes the table that holds the first elements of all hash chains
+ */
static void hashinit(void)
{
int i;
@@ -287,26 +305,37 @@ static void hashinit(void)
filelist_hash[i] = -1;
}
-// hashes a filename string into a number from {0..255}
-static int filehash(const char* fname)
+/**
+ * Hashes a filename string into a number from {0..255}
+ *
+ * @param fname The filename to hash.
+ * @return The hash.
+ */
+static int grf_filehash(const char *fname)
{
- unsigned int hash = 0;
- while(*fname) {
+ uint32 hash = 0;
+ while (*fname != '\0') {
hash = (hash<<1) + (hash>>7)*9 + TOLOWER(*fname);
fname++;
}
return hash & 255;
}
-// finds a grf_filelist entry with the specified file name
-static struct grf_filelist *filelist_find(const char *fname)
+/**
+ * Finds a grf_filelist entry with the specified file name
+ *
+ * @param fname The file to find.
+ * @return The file entry.
+ * @retval NULL if the file wasn't found.
+ */
+static struct grf_filelist *grfio_filelist_find(const char *fname)
{
int hash, index;
- if (!filelist)
+ if (filelist == NULL)
return NULL;
- hash = filelist_hash[filehash(fname)];
+ hash = filelist_hash[grf_filehash(fname)];
for (index = hash; index != -1; index = filelist[index].next)
if(!strcmpi(filelist[index].fn, fname))
break;
@@ -314,17 +343,22 @@ static struct grf_filelist *filelist_find(const char *fname)
return (index >= 0) ? &filelist[index] : NULL;
}
-// returns the original file name
-char* grfio_find_file(const char* fname)
+/// @copydoc grfio_interface::find_file()
+const char *grfio_find_file(const char *fname)
{
- struct grf_filelist *flist = filelist_find(fname);
+ struct grf_filelist *flist = grfio_filelist_find(fname);
if (flist == NULL)
return NULL;
return (!flist->fnd ? flist->fn : flist->fnd);
}
-// adds a grf_filelist entry into the list of loaded files
-static struct grf_filelist *filelist_add(struct grf_filelist *entry)
+/**
+ * Adds a grf_filelist entry into the list of loaded files.
+ *
+ * @param entry The entry to add.
+ * @return A pointer to the added entry.
+ */
+static struct grf_filelist *grfio_filelist_add(struct grf_filelist *entry)
{
int hash;
nullpo_ret(entry);
@@ -345,7 +379,7 @@ static struct grf_filelist *filelist_add(struct grf_filelist *entry)
memcpy(&filelist[filelist_entrys], entry, sizeof(struct grf_filelist));
- hash = filehash(entry->fn);
+ hash = grf_filehash(entry->fn);
filelist[filelist_entrys].next = filelist_hash[hash];
filelist_hash[hash] = filelist_entrys;
@@ -354,22 +388,27 @@ static struct grf_filelist *filelist_add(struct grf_filelist *entry)
return &filelist[filelist_entrys - 1];
}
-// adds a new grf_filelist entry or overwrites an existing one
-static struct grf_filelist *filelist_modify(struct grf_filelist *entry)
+/**
+ * Adds a new grf_filelist entry or overwrites an existing one.
+ *
+ * @param entry The entry to add.
+ * @return A pointer to the added entry.
+ */
+static struct grf_filelist *grfio_filelist_modify(struct grf_filelist *entry)
{
- struct grf_filelist *fentry = filelist_find(entry->fn);
+ struct grf_filelist *fentry = grfio_filelist_find(entry->fn);
if (fentry != NULL) {
int tmp = fentry->next;
memcpy(fentry, entry, sizeof(struct grf_filelist));
fentry->next = tmp;
} else {
- fentry = filelist_add(entry);
+ fentry = grfio_filelist_add(entry);
}
return fentry;
}
-// shrinks the file list array if too long
-static void filelist_compact(void)
+/// Shrinks the file list array if too long.
+static void grfio_filelist_compact(void)
{
if (filelist == NULL)
return;
@@ -380,37 +419,38 @@ static void filelist_compact(void)
}
}
-/***********************************************************
- *** Grfio Subroutines ***
- ***********************************************************/
+/* GRF I/O Subroutines */
-/// Combines are resource path with the data folder location to create local resource path.
-static void grfio_localpath_create(char* buffer, size_t size, const char* filename)
+/**
+ * Combines a resource path with the data folder location to create local
+ * resource path.
+ *
+ * @param[out] buffer The output buffer.
+ * @param[in] size The size of the output buffer.
+ * @param[in] filename Resource path.
+ */
+static void grfio_localpath_create(char *buffer, size_t size, const char *filename)
{
- unsigned int i;
+ int i;
size_t len;
len = strlen(data_dir);
- if( data_dir[0] == '\0' || data_dir[len-1] == '/' || data_dir[len-1] == '\\' )
- {
+ if (data_dir[0] == '\0' || data_dir[len-1] == '/' || data_dir[len-1] == '\\')
safesnprintf(buffer, size, "%s%s", data_dir, filename);
- }
else
- {
safesnprintf(buffer, size, "%s/%s", data_dir, filename);
- }
// normalize path
- for( i = 0; buffer[i] != '\0'; ++i )
- if( buffer[i] == '\\' )
+ for (i = 0; buffer[i] != '\0'; ++i)
+ if (buffer[i] == '\\')
buffer[i] = '/';
}
-/// Reads a file into a newly allocated buffer (from grf or data directory).
+/// @copydoc grfio_interface::reads()
void *grfio_reads(const char *fname, int *size)
{
- struct grf_filelist *entry = filelist_find(fname);
+ struct grf_filelist *entry = grfio_filelist_find(fname);
if (entry == NULL || entry->gentry <= 0) {
// LocalFileCheck
char lfname[256];
@@ -429,7 +469,7 @@ void *grfio_reads(const char *fname, int *size)
return NULL;
}
fseek(in,0,SEEK_SET);
- buf = (unsigned char *)aMalloc(declen+1); // +1 for resnametable zero-termination
+ buf = aMalloc(declen+1); // +1 for resnametable zero-termination
buf[declen] = '\0';
if (fread(buf, 1, declen, in) != (size_t)declen) {
ShowError("An error occurred in fread grfio_reads, fname=%s \n",fname);
@@ -459,7 +499,7 @@ void *grfio_reads(const char *fname, int *size)
if (in != NULL) {
int fsize = entry->srclen_aligned;
- unsigned char *buf = (unsigned char *)aMalloc(fsize);
+ unsigned char *buf = aMalloc(fsize);
unsigned char *buf2 = NULL;
if (fseek(in, entry->srcpos, SEEK_SET) != 0
|| fread(buf, 1, fsize, in) != (size_t)fsize) {
@@ -470,7 +510,7 @@ void *grfio_reads(const char *fname, int *size)
}
fclose(in);
- buf2 = (unsigned char *)aMalloc(entry->declen+1); // +1 for resnametable zero-termination
+ buf2 = aMalloc(entry->declen+1); // +1 for resnametable zero-termination
buf2[entry->declen] = '\0';
if (entry->type & FILELIST_TYPE_FILE) {
// file
@@ -503,35 +543,51 @@ void *grfio_reads(const char *fname, int *size)
return NULL;
}
-/// Decodes encrypted filename from a version 01xx grf index.
-static char* decode_filename(unsigned char* buf, int len)
+/**
+ * Decodes encrypted filename from a version 01xx grf index.
+ *
+ * @param[in,out] buf The encrypted filename (decrypted in-place).
+ * @param[in] len The filename length.
+ * @return A pointer to the decrypted filename.
+ */
+static char *grfio_decode_filename(unsigned char *buf, int len)
{
- int lop;
- for(lop=0;lop<len;lop+=8) {
- NibbleSwap(&buf[lop],8);
- des->decrypt(&buf[lop],8);
+ int i;
+ for (i = 0; i < len; i += 8) {
+ NibbleSwap(&buf[i],8);
+ des->decrypt(&buf[i],8);
}
return (char*)buf;
}
-/// Compares file extension against known large file types.
-/// @return true if the file should undergo full mode 0 decryption, and true otherwise.
-static bool isFullEncrypt(const char* fname)
+/**
+ * Compares file extension against known large file types.
+ *
+ * @param fname The file name.
+ * @return true if the file should undergo full mode 0 decryption, and true otherwise.
+ */
+static bool grfio_is_full_encrypt(const char *fname)
{
- const char* ext = strrchr(fname, '.');
- if( ext != NULL ) {
- static const char extensions[4][5] = { ".gnd", ".gat", ".act", ".str" };
- size_t i;
- for( i = 0; i < ARRAYLENGTH(extensions); ++i )
- if( strcmpi(ext, extensions[i]) == 0 )
+ const char *ext = strrchr(fname, '.');
+ if (ext != NULL) {
+ static const char *extensions[] = { ".gnd", ".gat", ".act", ".str" };
+ int i;
+ for (i = 0; i < ARRAYLENGTH(extensions); ++i)
+ if (strcmpi(ext, extensions[i]) == 0)
return false;
}
return true;
}
-/// Loads all entries in the specified grf file into the filelist.
-/// @param gentry index of the grf file name in the gentry_table
+/**
+ * Loads all entries in the specified grf file into the filelist.
+ *
+ * @param grfname Name of the grf file.
+ * @param gentry Index of the grf file name in the gentry_table.
+ * @return Error code.
+ * @retval 0 in case of success.
+ */
static int grfio_entryread(const char *grfname, int gentry)
{
long grf_size;
@@ -540,12 +596,11 @@ static int grfio_entryread(const char *grfname, int gentry)
unsigned char *grf_filelist;
FILE *fp = fopen(grfname, "rb");
- if( fp == NULL ) {
- ShowWarning("GRF data file not found: '%s'\n",grfname);
+ if (fp == NULL) {
+ ShowWarning("GRF data file not found: '%s'\n", grfname);
return 1; // 1:not found error
- } else {
- ShowInfo("GRF data file found: '%s'\n",grfname);
}
+ ShowInfo("GRF data file found: '%s'\n", grfname);
fseek(fp,0,SEEK_END);
grf_size = ftell(fp);
@@ -556,7 +611,7 @@ static int grfio_entryread(const char *grfname, int gentry)
fclose(fp);
return 2; // 2:file format error
}
- if (strcmp((const char*)grf_header,"Master of Magic") != 0 || fseek(fp,getlong(grf_header+0x1e),SEEK_CUR) != 0) {
+ if (strcmp((const char*)grf_header, "Master of Magic") != 0 || fseek(fp, getlong(grf_header+0x1e), SEEK_CUR) != 0) {
fclose(fp);
ShowError("GRF %s read error\n", grfname);
return 2; // 2:file format error
@@ -566,9 +621,8 @@ static int grfio_entryread(const char *grfname, int gentry)
if (grf_version == 0x01) {
// ****** Grf version 01xx ******
- long list_size;
- list_size = grf_size - ftell(fp);
- grf_filelist = (unsigned char *)aMalloc(list_size);
+ long list_size = grf_size - ftell(fp);
+ grf_filelist = aMalloc(list_size);
if (fread(grf_filelist,1,list_size,fp) != (size_t)list_size) {
ShowError("Couldn't read all grf_filelist element of %s \n", grfname);
aFree(grf_filelist);
@@ -581,11 +635,11 @@ static int grfio_entryread(const char *grfname, int gentry)
// Get an entry
for (entry = 0, ofs = 0; entry < entrys; ++entry) {
- struct grf_filelist aentry;
+ struct grf_filelist aentry = { 0 };
int ofs2 = ofs+getlong(grf_filelist+ofs)+4;
unsigned char type = grf_filelist[ofs2+12];
if (type&FILELIST_TYPE_FILE) {
- char *fname = decode_filename(grf_filelist+ofs+6, grf_filelist[ofs]-6);
+ char *fname = grfio_decode_filename(grf_filelist+ofs+6, grf_filelist[ofs]-6);
int srclen = getlong(grf_filelist+ofs2+0) - getlong(grf_filelist+ofs2+8) - 715;
if (strlen(fname) > sizeof(aentry.fn) - 1) {
@@ -594,7 +648,7 @@ static int grfio_entryread(const char *grfname, int gentry)
return 5; // 5: file name too long
}
- type |= isFullEncrypt(fname) ? FILELIST_TYPE_ENCRYPT_MIXED : FILELIST_TYPE_ENCRYPT_HEADER;
+ type |= grfio_is_full_encrypt(fname) ? FILELIST_TYPE_ENCRYPT_MIXED : FILELIST_TYPE_ENCRYPT_HEADER;
aentry.srclen = srclen;
aentry.srclen_aligned = getlong(grf_filelist+ofs2+4)-37579;
@@ -608,7 +662,7 @@ static int grfio_entryread(const char *grfname, int gentry)
#else
aentry.gentry = (char)(gentry+1); // With no first time LocalFileCheck
#endif
- filelist_modify(&aentry);
+ grfio_filelist_modify(&aentry);
}
ofs = ofs2 + 17;
@@ -635,7 +689,7 @@ static int grfio_entryread(const char *grfname, int gentry)
return 4;
}
- rBuf = (unsigned char *)aMalloc(rSize); // Get a Read Size
+ rBuf = aMalloc(rSize); // Get a Read Size
if (fread(rBuf,1,rSize,fp) != rSize) {
ShowError("An error occurred in fread \n");
fclose(fp);
@@ -643,7 +697,7 @@ static int grfio_entryread(const char *grfname, int gentry)
return 4;
}
fclose(fp);
- grf_filelist = (unsigned char *)aMalloc(eSize); // Get a Extend Size
+ grf_filelist = aMalloc(eSize); // Get a Extend Size
grfio->decode_zip(grf_filelist, &eSize, rBuf, rSize); // Decode function
aFree(rBuf);
@@ -677,84 +731,89 @@ static int grfio_entryread(const char *grfname, int gentry)
#else
aentry.gentry = (char)(gentry+1); // With no first time LocalFileCheck
#endif
- filelist_modify(&aentry);
+ grfio_filelist_modify(&aentry);
}
ofs = ofs2 + 17;
}
aFree(grf_filelist);
- } else {// ****** Grf Other version ******
+ } else {
+ // ****** Grf Other version ******
fclose(fp);
ShowError("GRF version %04x not supported\n",getlong(grf_header+0x2a));
return 4;
}
- filelist_compact(); // Unnecessary area release of filelist
+ grfio_filelist_compact(); // Unnecessary area release of filelist
return 0; // 0:no error
}
-static bool grfio_parse_restable_row(const char* row)
+/**
+ * Parses a Resource file table row.
+ *
+ * @param row The row data.
+ * @return success state.
+ * @retval true in case of success.
+ */
+static bool grfio_parse_restable_row(const char *row)
{
char w1[256], w2[256];
char src[256], dst[256];
char local[256];
- struct grf_filelist *entry;
+ struct grf_filelist *entry = NULL;
if (sscanf(row, "%255[^#\r\n]#%255[^#\r\n]#", w1, w2) != 2)
return false;
- if( strstr(w2, ".gat") == NULL && strstr(w2, ".rsw") == NULL )
+ if (strstr(w2, ".gat") == NULL && strstr(w2, ".rsw") == NULL)
return false; // we only need the maps' GAT and RSW files
sprintf(src, "data\\%s", w1);
sprintf(dst, "data\\%s", w2);
- entry = filelist_find(dst);
- if( entry != NULL )
- {// alias for GRF resource
- struct grf_filelist fentry;
- memcpy(&fentry, entry, sizeof(struct grf_filelist));
+ entry = grfio_filelist_find(dst);
+ if (entry != NULL) {
+ // alias for GRF resource
+ struct grf_filelist fentry = *entry;
safestrncpy(fentry.fn, src, sizeof(fentry.fn));
fentry.fnd = aStrdup(dst);
- filelist_modify(&fentry);
+ grfio_filelist_modify(&fentry);
return true;
}
grfio_localpath_create(local, sizeof(local), dst);
- if( exists(local) )
- {// alias for local resource
- struct grf_filelist fentry;
- memset(&fentry, 0, sizeof(fentry));
+ if (exists(local)) {
+ // alias for local resource
+ struct grf_filelist fentry = { 0 };
safestrncpy(fentry.fn, src, sizeof(fentry.fn));
fentry.fnd = aStrdup(dst);
- filelist_modify(&fentry);
+ grfio_filelist_modify(&fentry);
return true;
}
return false;
}
-/// Grfio Resource file check.
+/**
+ * Grfio Resource file check.
+ */
static void grfio_resourcecheck(void)
{
char restable[256];
- char *buf;
- int size;
- FILE* fp;
- int i = 0;
+ char *buf = NULL;
+ FILE *fp = NULL;
+ int size = 0, i = 0;
// read resnametable from data directory and return if successful
grfio_localpath_create(restable, sizeof(restable), "data\\resnametable.txt");
fp = fopen(restable, "rb");
- if( fp != NULL )
- {
+ if (fp != NULL) {
char line[256];
- while( fgets(line, sizeof(line), fp) )
- {
- if( grfio_parse_restable_row(line) )
+ while (fgets(line, sizeof(line), fp)) {
+ if (grfio_parse_restable_row(line))
++i;
}
@@ -765,19 +824,18 @@ static void grfio_resourcecheck(void)
// read resnametable from loaded GRF's, only if it cannot be loaded from the data directory
buf = grfio->reads("data\\resnametable.txt", &size);
- if( buf != NULL )
- {
- char *ptr;
+ if (buf != NULL) {
+ char *ptr = NULL;
buf[size] = '\0';
ptr = buf;
- while( ptr - buf < size )
- {
- if( grfio_parse_restable_row(ptr) )
+ while (ptr - buf < size) {
+ if (grfio_parse_restable_row(ptr))
++i;
ptr = strchr(ptr, '\n');
- if( ptr == NULL ) break;
+ if (ptr == NULL)
+ break;
ptr++;
}
@@ -787,13 +845,19 @@ static void grfio_resourcecheck(void)
}
}
-/// Reads a grf file and adds it to the list.
-static int grfio_add(const char* fname)
+/**
+ * Reads a grf file and adds it to the list.
+ *
+ * @param fname The file name to read.
+ * @return Error code.
+ * @retval 0 in case of success.
+ */
+static int grfio_add(const char *fname)
{
if (gentry_entrys >= gentry_maxentry) {
#define GENTRY_ADDS 4 // The number increment of gentry_table entries
gentry_maxentry += GENTRY_ADDS;
- gentry_table = (char**)aRealloc(gentry_table, gentry_maxentry * sizeof(char*));
+ gentry_table = aRealloc(gentry_table, gentry_maxentry * sizeof(char*));
memset(gentry_table + (gentry_maxentry - GENTRY_ADDS), 0, sizeof(char*) * GENTRY_ADDS);
#undef GENTRY_ADDS
}
@@ -803,7 +867,7 @@ static int grfio_add(const char* fname)
return grfio_entryread(fname, gentry_entrys - 1);
}
-/// Finalizes grfio.
+/// @copydoc grfio_interface::final()
void grfio_final(void)
{
if (filelist != NULL) {
@@ -829,36 +893,33 @@ void grfio_final(void)
gentry_entrys = gentry_maxentry = 0;
}
-/// Initializes grfio.
-void grfio_init(const char* fname)
+/// @copydoc grfio_interface::init()
+void grfio_init(const char *fname)
{
- FILE* data_conf;
+ FILE *data_conf;
int grf_num = 0;
hashinit(); // hash table initialization
data_conf = fopen(fname, "r");
- if( data_conf != NULL )
- {
+ if (data_conf != NULL) {
char line[1024];
- while( fgets(line, sizeof(line), data_conf) )
- {
+ while (fgets(line, sizeof(line), data_conf)) {
char w1[1024], w2[1024];
- if( line[0] == '/' && line[1] == '/' )
+ if (line[0] == '/' && line[1] == '/')
continue; // skip comments
if (sscanf(line, "%1023[^:]: %1023[^\r\n]", w1, w2) != 2)
continue; // skip unrecognized lines
// Entry table reading
- if( strcmp(w1, "grf") == 0 ) // GRF file
- {
- if( grfio_add(w2) == 0 )
+ if (strcmp(w1, "grf") == 0) {
+ // GRF file
+ if (grfio_add(w2) == 0)
++grf_num;
- }
- else if( strcmp(w1,"data_dir") == 0 ) // Data directory
- {
+ } else if (strcmp(w1,"data_dir") == 0) {
+ // Data directory
safestrncpy(data_dir, w2, sizeof(data_dir));
}
}
@@ -867,16 +928,17 @@ void grfio_init(const char* fname)
ShowStatus("Done reading '"CL_WHITE"%s"CL_RESET"'.\n", fname);
}
- if( grf_num == 0 )
+ if (grf_num == 0)
ShowInfo("No GRF loaded, using default data directory\n");
// Unnecessary area release of filelist
- filelist_compact();
+ grfio_filelist_compact();
// Resource check
grfio_resourcecheck();
}
+/// Interface base initialization.
void grfio_defaults(void)
{
grfio = &grfio_s;
@@ -885,6 +947,6 @@ void grfio_defaults(void)
grfio->reads = grfio_reads;
grfio->find_file = grfio_find_file;
grfio->crc32 = grfio_crc32;
- grfio->decode_zip = decode_zip;
- grfio->encode_zip = encode_zip;
+ grfio->decode_zip = grfio_decode_zip;
+ grfio->encode_zip = grfio_encode_zip;
}
diff --git a/src/common/grfio.h b/src/common/grfio.h
index 72afad274..857bc507e 100644
--- a/src/common/grfio.h
+++ b/src/common/grfio.h
@@ -23,22 +23,102 @@
#include "common/hercules.h"
+/** @file
+ * GRF I/O library.
+ */
+
+/// The GRF I/O interface.
struct grfio_interface {
+ /**
+ * Interface initialization.
+ *
+ * @param fname Name of the configuration file.
+ */
void (*init) (const char *fname);
+
+ /// Interface finalization.
void (*final) (void);
+
+ /**
+ * Reads a file into a newly allocated buffer (from grf or data directory).
+ *
+ * @param[in] fname Name of the file to read.
+ * @param[out] size Buffer to return the size of the read file (optional).
+ * @return The file data.
+ * @retval NULL in case of error.
+ */
void *(*reads) (const char *fname, int *size);
- char *(*find_file) (const char *fname);
+ /**
+ * Finds a file in the grf or data directory
+ *
+ * @param fname The file to find.
+ * @return The original file name.
+ * @retval NULL if the file wasn't found.
+ */
+ const char *(*find_file) (const char *fname);
+
+ /**
+ * Calculates a CRC32 hash.
+ *
+ * @param buf The data to hash.
+ * @param len Data length.
+ *
+ * @return The CRC32 hash.
+ */
unsigned long (*crc32) (const unsigned char *buf, unsigned int len);
- int (*decode_zip) (void *dest, unsigned long *destLen, const void *source, unsigned long sourceLen);
- int (*encode_zip) (void *dest, unsigned long *destLen, const void *source, unsigned long sourceLen);
+
+ /**
+ * Decompresses ZIP data.
+ *
+ * Decompresses the source buffer into the destination buffer.
+ * source_len is the byte length of the source buffer. Upon entry,
+ * dest_len is the total size of the destination buffer, which must be
+ * large enough to hold the entire uncompressed data. (The size of the
+ * uncompressed data must have been saved previously by the compressor
+ * and transmitted to the decompressor by some mechanism outside the
+ * scope of this compression library.) Upon exit, dest_len is the
+ * actual size of the uncompressed buffer.
+ *
+ * @param[in,out] dest The destination (uncompressed) buffer.
+ * @param[in,out] dest_len Max length of the destination buffer, returns length of the decompressed data.
+ * @param[in] source The source (compressed) buffer.
+ * @param[in] source_len Source data length.
+ * @return error code.
+ * @retval Z_OK in case of success.
+ */
+ int (*decode_zip) (void *dest, unsigned long *dest_len, const void *source, unsigned long source_len);
+
+ /**
+ * Compresses data to ZIP format.
+ *
+ * Compresses the source buffer into the destination buffer.
+ * source_len is the byte length of the source buffer. Upon entry,
+ * dest_len is the total size of the destination buffer, which must be
+ * at least the value returned by compressBound(source_len). Upon
+ * exit, dest_len is the actual size of the compressed buffer.
+ *
+ * @param[in,out] dest The destination (compressed) buffer (if NULL, a new buffer will be created).
+ * @param[in,out] dest_len Max length of the destination buffer (if 0, it will be calculated).
+ * @param[in] source The source (uncompressed) buffer.
+ * @param[in] source_len Source data length.
+ */
+ int (*encode_zip) (void *dest, unsigned long *dest_len, const void *source, unsigned long source_len);
};
+/**
+ * Reads a file into a newly allocated buffer (from grf or data directory)
+ *
+ * @param fn The filename to read.
+ *
+ * @see grfio_interface::reads()
+ * @related grfio_interface
+ */
#define grfio_read(fn) grfio->reads((fn), NULL)
#ifdef HERCULES_CORE
void grfio_defaults(void);
#endif // HERCULES_CORE
-HPShared struct grfio_interface *grfio;
+HPShared struct grfio_interface *grfio; ///< Pointer to the grfio interface.
#endif /* COMMON_GRFIO_H */
diff --git a/src/map/map.c b/src/map/map.c
index 491f6fb59..c5ea7c1f3 100644
--- a/src/map/map.c
+++ b/src/map/map.c
@@ -3579,7 +3579,8 @@ void map_flags_init(void) {
int map_waterheight(char* mapname)
{
char fn[256];
- char *rsw, *found;
+ char *rsw = NULL;
+ const char *found;
nullpo_retr(NO_WATER, mapname);
//Look up for the rsw