From 41974ae5265fbc23a06f276f9e008d5dad020e0b Mon Sep 17 00:00:00 2001 From: Ben Longbons Date: Thu, 30 Aug 2012 16:16:25 -0700 Subject: Rename files for C++ conversion. Does not compile. After updating, you can remove these files, as shown in 'git status': Untracked files: (use "git add ..." to include in what will be committed) src/map/magic-interpreter-lexer.c src/map/magic-interpreter-parser.c src/map/magic-interpreter-parser.h --- src/common/grfio.cpp | 212 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 212 insertions(+) create mode 100644 src/common/grfio.cpp (limited to 'src/common/grfio.cpp') diff --git a/src/common/grfio.cpp b/src/common/grfio.cpp new file mode 100644 index 0000000..1b89b18 --- /dev/null +++ b/src/common/grfio.cpp @@ -0,0 +1,212 @@ +// Reads .gat files by name-mapping .wlk files +#include +#include +#include +#include + +#include "utils.hpp" +#include "grfio.hpp" +#include "mmo.hpp" +#include "socket.hpp" + +//---------------------------- +// file entry table struct +//---------------------------- +typedef struct +{ + size_t declen; + int16_t next; // next index into the filelist[] array, or -1 + char fn[128 - 4 - 2]; // file name +} FILELIST; + +#define FILELIST_LIMIT 32768 // limit to number of filelists - if you increase this, change all shorts to int +#define FILELIST_ADDS 1024 // amount to increment when reallocing + +static FILELIST *filelist = NULL; +/// Number of entries used +static uint16_t filelist_entrys = 0; +/// Number of FILELIST entries actually allocated +static uint16_t filelist_maxentry = 0; + +/// First index of the given hash, into the filelist[] array +static int16_t filelist_hash[256] = {[0 ... 255] = -1}; + +/// Hash a filename +static uint8_t filehash (const char *fname) +{ + // Larger than the return type - upper bits are used in the process + uint32_t hash = 0; + while (*fname) + { + hash = (hash << 1) + (hash >> 7) * 9 + (unsigned char)*fname; + fname++; + } + return hash; +} + +/// Find the filelist entry for the given filename, or NULL if it is not +FILELIST *filelist_find (const char *fname) +{ + int16_t index = filelist_hash[filehash (fname)]; + while (index >= 0) + { + if (strcmp (filelist[index].fn, fname) == 0) + return &filelist[index]; + index = filelist[index].next; + } + return NULL; +} + +/// Copy a temporary entry into the hash map +static FILELIST *filelist_add (FILELIST * entry) +{ + if (filelist_entrys >= FILELIST_LIMIT) + { + fprintf (stderr, "filelist limit : filelist_add\n"); + exit (1); + } + + if (filelist_entrys >= filelist_maxentry) + { + RECREATE(filelist, FILELIST, filelist_maxentry + FILELIST_ADDS); + memset (filelist + filelist_maxentry, '\0', + FILELIST_ADDS * sizeof (FILELIST)); + filelist_maxentry += FILELIST_ADDS; + } + + uint16_t new_index = filelist_entrys++; + uint8_t hash = filehash (entry->fn); + entry->next = filelist_hash[hash]; + filelist_hash[hash] = new_index; + + filelist[new_index] = *entry; + + return &filelist[new_index]; +} + +static FILELIST *filelist_modify (FILELIST * entry) +{ + FILELIST *fentry = filelist_find (entry->fn); + if (fentry) + { + entry->next = fentry->next; + *fentry = *entry; + return fentry; + } + return filelist_add (entry); +} + +/// Change fname data/*.gat to lfname data/*.wlk +// TODO even if the file exists, don't keep reopening it every time one loads +void grfio_resnametable (const char *fname, char *lfname) +{ + char restable[] = "data/resnametable.txt"; + + FILE *fp = fopen_ (restable, "rb"); + if (fp == NULL) + { + fprintf(stderr, "No resnametable, can't look for %s\n", fname); + strcpy(lfname, fname); + char* ext = lfname + strlen(lfname) - 4; + if (!strcmp(ext, ".gat")) + strcpy(ext, ".wlk"); + return; + } + + char line[512]; + while (fgets (line, sizeof (line), fp)) + { + char w1[256], w2[256]; + if ( + // line is of the form foo.gat#foo.wlk# + (sscanf (line, "%[^#]#%[^#]#", w1, w2) == 2) + // strip data/ from foo.gat before comparing + && (!strcmp (w1, fname + 5))) + { + strcpy (lfname, "data/"); + strcpy (lfname + 5, w2); + fclose_ (fp); + return; + } + } + fprintf(stderr, "Unable to find resource: %s\n", fname); + fclose_ (fp); + + strcpy(lfname, fname); + char* ext = lfname + strlen(lfname) - 4; + if (!strcmp(ext, ".gat")) + strcpy(ext, ".wlk"); + return; +} + +/// Size of resource +size_t grfio_size (const char *fname) +{ + FILELIST *entry = filelist_find (fname); + if (entry) + return entry->declen; + + char lfname[256]; + FILELIST lentry; + struct stat st; + + grfio_resnametable (fname, lfname); + + for (char *p = lfname; *p; p++) + if (*p == '\\') + *p = '/'; + + if (stat (lfname, &st) == 0) + { + strncpy (lentry.fn, fname, sizeof (lentry.fn) - 1); + lentry.declen = st.st_size; + entry = filelist_modify (&lentry); + } + else + { + printf ("%s not found\n", fname); + return 0; + } + return entry->declen; +} + +void *grfio_reads (const char *fname, size_t *size) +{ + char lfname[256]; + grfio_resnametable (fname, lfname); + + for (char *p = &lfname[0]; *p != 0; p++) + if (*p == '\\') + *p = '/'; // * At the time of Unix + + FILE *in = fopen_ (lfname, "rb"); + if (!in) + { + fprintf (stderr, "%s not found\n", fname); + return NULL; + } + FILELIST lentry; + FILELIST *entry = filelist_find (fname); + if (entry) + { + lentry.declen = entry->declen; + } + else + { + fseek (in, 0, SEEK_END); + lentry.declen = ftell (in); + fseek (in, 0, SEEK_SET); + strncpy (lentry.fn, fname, sizeof (lentry.fn) - 1); + entry = filelist_modify (&lentry); + } + uint8_t *buf2; + CREATE (buf2, uint8_t, lentry.declen + 1024); + if (fread (buf2, 1, lentry.declen, in) != lentry.declen) + exit(1); + fclose_ (in); + in = NULL; + + if (size) + *size = entry->declen; + return buf2; +} -- cgit v1.2.3-70-g09d2