From 44db60f32baf00d775c4c8bc1c598fe4643aa0c4 Mon Sep 17 00:00:00 2001
From: Allanis <allanis@saracraft.net>
Date: Sun, 27 Apr 2014 14:31:21 +0100
Subject: [PATCH] [Add] Using the pack cache now, initial loading is a lot
 faster.

---
 src/ai.c       |  6 ++--
 src/ldata.c    | 95 +++++++++++++++++++++++++++-----------------------
 src/ldata.h    |  4 +--
 src/lephisto.c |  4 +--
 src/music.c    |  2 +-
 src/pack.c     | 80 +++++++++++++++++++++++++++++-------------
 src/pack.h     |  2 ++
 src/sound.c    |  6 ++--
 8 files changed, 120 insertions(+), 79 deletions(-)

diff --git a/src/ai.c b/src/ai.c
index cb79b5d..a100794 100644
--- a/src/ai.c
+++ b/src/ai.c
@@ -101,7 +101,7 @@ static int ai_accel(lua_State* L); /* Accelerate. */
 
 /* Internal C routines. */
 static void ai_run(lua_State* L, const char* funcname);
-static int ai_loadProfile(char* filename);
+static int ai_loadProfile(const char* filename);
 static void ai_freetask(Task* t);
 static void ai_setMemory(void);
 static void ai_create(Pilot* pilot, char* param);
@@ -383,7 +383,7 @@ void ai_destroy(Pilot* p) {
  *    @return 0 on no errors.
  */
 int ai_init(void) {
-  char** files;
+  const char** files;
   uint32_t nfiles, i;
 
   /* Get the file list. */
@@ -412,7 +412,7 @@ int ai_init(void) {
  *    @param[in] filename File to create the profile from.
  *    @return 0 on no error.
  */
-static int ai_loadProfile(char* filename) {
+static int ai_loadProfile(const char* filename) {
   char* buf = NULL;
   uint32_t bufsize = 0;
   lua_State* L;
diff --git a/src/ldata.c b/src/ldata.c
index 466df24..bd2c4a9 100644
--- a/src/ldata.c
+++ b/src/ldata.c
@@ -22,13 +22,13 @@
 #define START_DATA      "../dat/start.xml" /**< Path to module start file. */
 
 /* Packfile. */
-static char* ldata_filename   = NULL; /**< Packfile name. */
-static Packfile_t* ldata_pack = NULL; /**< Actual packfile. */
-static char* ldata_packName   = NULL; /**< Name of the ldata module. */
+static char* ldata_filename     = NULL; /**< Packfile name. */
+static Packcache_t* ldata_cache = NULL; /**< Actual packfile. */
+static char* ldata_packName     = NULL; /**< Name of the ldata module. */
 
 /* File list. */
-static char** ldata_fileList    = NULL; /**< List of the files in the packfile. */
-static uint32_t ldata_fileNList = 0;    /**< Number of files in ldata_fileList. */
+static const char** ldata_fileList = NULL; /**< List of the files in the packfile. */
+static uint32_t ldata_fileNList    = 0;    /**< Number of files in ldata_fileList. */
 
 /**
  * @brief Check to see if path is a ldata file.
@@ -59,30 +59,43 @@ static int ldata_openPackfile(void) {
   int nfiles;
   size_t len;
 
-  if(lfile_fileExists("%s-%d.%d.%d", LDATA_FILENAME, VMAJOR, VMINOR, VREV)) {
-    ldata_filename = malloc(PATH_MAX);
-    snprintf(ldata_filename, PATH_MAX, "%s-%d.%d.%d", LDATA_FILENAME, VMAJOR,
-        VMINOR, VREV);
-  }
-  else if(lfile_fileExists(LDATA_DEF))
-    ldata_filename = strdup(LDATA_DEF);
-  else {
-    files = lfile_readDir(&nfiles, ".");
-    len = strlen(LDATA_FILENAME);
-    for(i = 0; i < nfiles; i++) {
-      if(strncmp(files[i], LDATA_FILENAME, len)==0) {
-        /* Must be packed. */
-        if(pack_check(files[i]))
-          continue;
-
-        ldata_filename = strdup(files[i]);
-        break;
-      }
+  /* Try to find the ldata file. */
+  if(ldata_filename == NULL) {
+    /* Check ldata with version appended. */
+    if(lfile_fileExists("%s-%d.%d.%d", LDATA_FILENAME, VMAJOR, VMINOR, VREV)) {
+      ldata_filename = malloc(PATH_MAX);
+      snprintf(ldata_filename, PATH_MAX, "%s-%d.%d.%d",
+          LDATA_FILENAME, VMAJOR, VMINOR, VREV);
+    }
+    /* Check default ldata. */
+    else if(lfile_fileExists(LDATA_DEF))
+      ldata_filename = strdup(LDATA_DEF);
+    /* Try to open any ldata in path. */
+    else {
+      files = lfile_readDir(&nfiles, ".");
+      len = strlen(LDATA_FILENAME);
+      for(i = 0; i < nfiles; i++) {
+        if(strncmp(files[i], LDATA_FILENAME, len)==0) {
+          /* Must be a packfile. */
+          if(pack_check(files[i]))
+            continue;
+
+          ldata_filename = strdup(files[i]);
+          break;
+        }
+      }
+      /* Clean up. */
+      for(i = 0; i < nfiles; i++)
+        free(files[i]);
+      free(files);
     }
-    for(i = 0; i < nfiles; i++)
-      free(files[i]);
-    free(files);
   }
+
+  /* Open the cache. */
+  ldata_cache = pack_openCache(ldata_filename);
+  if(ldata_cache == NULL)
+    WARN("Unalbe to create Packcache from '%s'.", ldata_filename);
+
   return 0;
 }
 
@@ -98,8 +111,6 @@ int ldata_open(void) {
  * @brief Close and clean up the ldata file.
  */
 void ldata_close(void) {
-  unsigned int i;
-
   /* Destroy the name. */
   if(ldata_packName != NULL) {
     free(ldata_packName);
@@ -108,26 +119,23 @@ void ldata_close(void) {
 
   /* Destroy the list. */
   if(ldata_fileList != NULL) {
-    for(i = 0; i < ldata_fileNList; i++)
-      free(ldata_fileList[i]);
-
-    free(ldata_fileList);
+    /* No need to free memory since cache does that. */
     ldata_fileList = NULL;
     ldata_fileNList = 0;
   }
 
   /* Close the packfile. */
-  /*
-  pack_close(ldata_pack);
-  ldata_pack = NULL;
-  */
+  if(ldata_cache) {
+    pack_closeCache(ldata_cache);
+    ldata_cache = NULL;
+  }
 }
 
 /**
  * @brief Get the ldata's name.
  *    @return The ldata's name.
  */
-char* ldata_name(void) {
+const char* ldata_name(void) {
   char* buf;
   uint32_t size;
   xmlNodePtr node;
@@ -172,15 +180,16 @@ char* ldata_name(void) {
  * @brief Read a file from the ldata.
  */
 void* ldata_read(const char* filename, uint32_t* filesize) {
-  if(ldata_filename == NULL)
+  if(ldata_cache == NULL)
     ldata_openPackfile();
-  return pack_readfile(ldata_filename, filename, filesize);
+
+  return pack_readfileCached(ldata_cache, filename, filesize);
 }
 
 /**
  * @brief Get the list of files in the ldata.
  */
-char** ldata_list(const char* path, uint32_t* nfiles) {
+const char** ldata_list(const char* path, uint32_t* nfiles) {
   (void)path;
 
   if(ldata_fileList != NULL) {
@@ -188,10 +197,10 @@ char** ldata_list(const char* path, uint32_t* nfiles) {
     return ldata_fileList;
   }
 
-  if(ldata_filename == NULL)
+  if(ldata_cache == NULL)
     ldata_openPackfile();
 
-  ldata_fileList = pack_listfiles(ldata_filename, &ldata_fileNList);
+  ldata_fileList = pack_listfilesCached(ldata_cache, &ldata_fileNList);
   *nfiles = ldata_fileNList;
   return ldata_fileList;
 }
diff --git a/src/ldata.h b/src/ldata.h
index e108a53..9af08d2 100644
--- a/src/ldata.h
+++ b/src/ldata.h
@@ -8,9 +8,9 @@ void ldata_close(void);
 /* General. */
 int ldata_check(char* path);
 int ldata_setPath(char* path);
-char* ldata_name(void);
+const char* ldata_name(void);
 
 /* Individual file functions. */
 void* ldata_read(const char* filename, uint32_t* filesize);
-char** ldata_list(const char* path, uint32_t* nfiles);
+const char** ldata_list(const char* path, uint32_t* nfiles);
 
diff --git a/src/lephisto.c b/src/lephisto.c
index 85df593..61d27b0 100644
--- a/src/lephisto.c
+++ b/src/lephisto.c
@@ -285,8 +285,8 @@ int main(int argc, char** argv) {
 void loadscreen_load(void) {
   int i;
   char file_path[PATH_MAX];
-  char** loadscreens;
-  char** files;
+  const char** loadscreens;
+  const char** files;
   uint32_t nfiles;
   size_t len;
   int nload;
diff --git a/src/music.c b/src/music.c
index d5fb29c..3c3d770 100644
--- a/src/music.c
+++ b/src/music.c
@@ -164,7 +164,7 @@ static void music_free(void) {
  *    @return 0 on success.
  */
 static int music_find(void) {
-  char** files;
+  const char** files;
   uint32_t nfiles, i;
   char tmp[64];
   int len;
diff --git a/src/pack.c b/src/pack.c
index 3d2581c..ac38eda 100644
--- a/src/pack.c
+++ b/src/pack.c
@@ -144,7 +144,6 @@ Packcache_t* pack_openCache(const char* packfile) {
     cache->index[i] = strdup(buf);
     READ(cache, &cache->start[i], 4);
     DEBUG("'%s' found at %d", filename, cache->start[i]);
-    break;
   }
   /* Return the built cache. */
   return cache;
@@ -220,7 +219,7 @@ Packfile_t* pack_openFromCache(Packcache_t* cache, const char* filename) {
     }
   }
 
-    return NULL;
+  return file;
 }
 
 /**
@@ -599,32 +598,14 @@ long pack_tell(Packfile_t* file) {
 }
 
 /**
- * @fn void* pack_readfile(const char* packfile, const char* filename, uint32_t* filesize)
- *
- * @brief Read an entire file into memory.
- *    @param packfile Name of the packfile to read from.
- *    @param filename Name of the packed file to read.
- *    @param filesize Is set to the size of the file.
- *    @return A pointer to the sata in the file or NULL if an error accured.
+ * @brief Read a file from a packfile.
  */
-void* pack_readfile(const char* packfile, const char* filename, uint32_t* filesize) {
-  Packfile_t* file;
+static void* pack_readfilePack(Packfile_t* file,
+    const char* filename, uint32_t* filesize) {
   void* buf;
   char* str;
   int size, bytes;
 
-  /* Initialize size to 0. */
-  if(filesize)
-    *filesize = 0;
-
-  /* Open the packfile. */
-  file = pack_open(packfile, filename);
-  if(file == NULL) {
-    ERR("Opening packfile '%s'.", packfile);
-    return NULL;
-  }
-  DEBUG("Opened file '%s' from '%s'", filename, packfile);
-
   /* Read the entire file. */
   size = file->end - file->start;
   buf = malloc(size+1);
@@ -634,8 +615,8 @@ void* pack_readfile(const char* packfile, const char* filename, uint32_t* filesi
     return NULL;
   }
   if((bytes = pack_read(file, buf, size)) != size) {
-    ERR("Reading '%s' from packfile '%s'. Expected %d bytes got %d bytes",
-        filename, packfile, size, bytes);
+    ERR("Reading '%s' from packfile. Expected %d bytes got %d bytes",
+        filename, size, bytes);
     free(buf);
     free(file);
     return NULL;
@@ -675,6 +656,32 @@ void* pack_readfile(const char* packfile, const char* filename, uint32_t* filesi
   return buf;
 }
 
+/**
+ * @brief Read an entire file into memory.
+ *    @param packfile Name of the packfile to read from.
+ *    @param filename Name of the packed file to read.
+ *    @param filesize Is set to the size of the file.
+ *    @return A pointer to the sata in the file or NULL if an error accured.
+ */
+void* pack_readfile(const char* packfile, const char* filename, uint32_t* filesize) {
+  Packfile_t* file;
+
+  /* Initialize size to 0. */
+  if(filesize)
+    *filesize = 0;
+
+  /* Open the packfile. */
+  file = pack_open(packfile, filename);
+  if(file == NULL) {
+    ERR("Opening packfile '%s'.", packfile);
+    return NULL;
+  }
+
+  DEBUG("Opened file '%s' from '%s'", filename, packfile);
+
+  return pack_readfilePack(file, filename, filesize);
+}
+
 /**
  * @fn char** pack_listfiles(const char* packfile, uint32_t* nfiles)
  *
@@ -732,6 +739,29 @@ char** pack_listfiles(const char* packfile, uint32_t* nfiles) {
   return filenames;
 }
 
+/**
+ * @brief Read an entire file from the cache.
+ */
+void* pack_readfileCached(Packcache_t* cache, const char* filename, uint32_t* filesize) {
+  Packfile_t* file;
+
+  file = pack_openFromCache(cache, filename);
+  if(file == NULL)
+    ERR("Unable to create packfile from packcache.");
+  return pack_readfilePack(file, filename, filesize);
+}
+
+/**
+ * @brief Get the list of files in a packcache.
+ *    @param cache Cache to get list of files from.
+ *    @param nfiles Number of files in the list.
+ *    @return A read only list of the files from the pack cache.
+ */
+const char** pack_listfilesCached(Packcache_t* cache, uint32_t* nfiles) {
+  *nfiles = cache->nindex;
+  return (const char**)cache->index;
+}
+
 /**
  * @brief Closes a packfile.
  *    @param file Packfile to close.
diff --git a/src/pack.h b/src/pack.h
index 22e7372..768b118 100644
--- a/src/pack.h
+++ b/src/pack.h
@@ -33,4 +33,6 @@ int pack_close(Packfile_t* file);
 /* Fancy stuff. */
 void* pack_readfile(const char* packfile, const char* filename, uint32_t* filesize);
 char** pack_listfiles(const char* packfile, uint32_t* nfiles);
+void* pack_readfileCached(Packcache_t* cache, const char* filename, uint32_t* filesize);
+const char** pack_listfilesCached(Packcache_t* cache, uint32_t* nfiles);
 
diff --git a/src/sound.c b/src/sound.c
index 3061ff7..50ef24c 100644
--- a/src/sound.c
+++ b/src/sound.c
@@ -80,7 +80,7 @@ static alVoice* voice_pool   = NULL;       /**< Pool of free voices. */
 /* General prototypes. */
 static void print_MixerVersion(void);
 static int  sound_makeList(void);
-static Mix_Chunk* sound_load(char* filename);
+static Mix_Chunk* sound_load(const char* filename);
 static void sound_free(alSound* snd);
 /* Voices. */
 static void voice_markStopped(int channel);
@@ -425,7 +425,7 @@ int sound_updateListener(double dir, double x, double y) {
  * @brief Make the list of available sounds.
  */
 static int sound_makeList(void) {
-  char** files;
+  const char** files;
   uint32_t nfiles, i;
   char tmp[64];
   int len;
@@ -489,7 +489,7 @@ int sound_volume(const double vol) {
  *
  * @sa sound_makeList
  */
-static Mix_Chunk* sound_load(char* filename) {
+static Mix_Chunk* sound_load(const char* filename) {
   void* wavdata;
   unsigned int size;
   SDL_RWops* rw;