added saving native BDCFF file with cheat code ":save-native-level"
[rocksndiamonds.git] / src / game_bd / bd_caveset.c
index 40078e329b33c9ca2be8693624adb07c66bb64c0..cce3692d34bd28d49fc70938d71ccdf01806ec89 100644 (file)
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <glib.h>
-#include <glib/gi18n.h>
-#include <glib/gstdio.h>
+#include <sys/stat.h>
 
 #include "main_bd.h"
 
 
 /* this stores the caves. */
-GList *gd_caveset;
+List *gd_caveset;
 
 /* the data of the caveset: name, highscore, max number of lives, etc. */
 GdCavesetData *gd_caveset_data;
@@ -99,7 +97,7 @@ void gd_caveset_data_free(GdCavesetData *data)
   /* free strings */
   for (i = 0; gd_caveset_properties[i].identifier != NULL; i++)
     if (gd_caveset_properties[i].type == GD_TYPE_LONGSTRING)
-      checked_free(G_STRUCT_MEMBER(char *, data, gd_caveset_properties[i].offset));
+      checked_free(STRUCT_MEMBER(char *, data, gd_caveset_properties[i].offset));
 
   free(data);
 }
@@ -115,8 +113,8 @@ void gd_caveset_clear(void)
 {
   if (gd_caveset)
   {
-    g_list_foreach(gd_caveset, (GFunc) gd_cave_free, NULL);
-    g_list_free(gd_caveset);
+    list_foreach(gd_caveset, (list_fn) gd_cave_free, NULL);
+    list_free(gd_caveset);
     gd_caveset = NULL;
   }
 
@@ -135,13 +133,13 @@ void gd_caveset_clear(void)
 /* return number of caves currently in memory. */
 int gd_caveset_count(void)
 {
-  return g_list_length(gd_caveset);
+  return list_length(gd_caveset);
 }
 
 /* return index of first selectable cave */
 static int caveset_first_selectable_cave_index(void)
 {
-  GList *iter;
+  List *iter;
   int i;
 
   for (i = 0, iter = gd_caveset; iter != NULL; i++, iter = iter->next)
@@ -161,7 +159,7 @@ static int caveset_first_selectable_cave_index(void)
 /* return a cave identified by its index */
 GdCave *gd_return_nth_cave(const int cave)
 {
-  return g_list_nth_data(gd_caveset, cave);
+  return list_nth_data(gd_caveset, cave);
 }
 
 /* get a selected cave from the loaded caveset (original, unmodified cave) */
@@ -257,9 +255,9 @@ static GdColor brc_color_table_comp[] =
   0x3526ff,
 };
 
-static GdElement brc_effect(guint8 byt)
+static GdElement brc_effect(byte byt)
 {
-  if (byt >= G_N_ELEMENTS(brc_effect_table))
+  if (byt >= ARRAY_SIZE(brc_effect_table))
   {
     Warn("invalid element identifier for brc effect: %02x", byt);
 
@@ -269,7 +267,7 @@ static GdElement brc_effect(guint8 byt)
   return brc_effect_table[byt];
 }
 
-static void brc_import(guint8 *data)
+static void brc_import(byte *data)
 {
   int x, y;
   int level;
@@ -318,11 +316,11 @@ static void brc_import(guint8 *data)
       imported[level * 20 + cavenum] = cave;
 
       if (cavenum < 16)
-       g_snprintf(cave->name, sizeof(GdString), "Cave %c/%d", 'A' + cavenum,
-                  level + 1);
+       snprintf(cave->name, sizeof(GdString), "Cave %c/%d", 'A' + cavenum,
+                level + 1);
       else
-       g_snprintf(cave->name, sizeof(GdString), "Intermission %d/%d",
-                  cavenum - 15, level + 1);
+       snprintf(cave->name, sizeof(GdString), "Intermission %d/%d",
+                cavenum - 15, level + 1);
 
       /* fixed intermission caves; are smaller. */
       if (cavenum >= 16)
@@ -337,12 +335,12 @@ static void brc_import(guint8 *data)
       {
        for (x = 0; x < cave->w; x++)
        {
-         guint8 import;
+         byte import;
 
          import = data[y + level * 24 + cavenum * 24 * 5 + x * 24 * 5 * 20];
 
          // if (i == printcave) g_print("%2x", import);
-         if (import < G_N_ELEMENTS(brc_import_table))
+         if (import < ARRAY_SIZE(brc_import_table))
            cave->map[y][x] = brc_import_table[import];
          else
            cave->map[y][x] = O_UNKNOWN;
@@ -410,7 +408,7 @@ static void brc_import(guint8 *data)
       cave->intermission = (cavenum >= 16 || data[14 * c + datapos + 1] != 0);
 
       /* colors */
-      colind = data[31 * c + datapos] % G_N_ELEMENTS(brc_color_table);
+      colind = data[31 * c + datapos] % ARRAY_SIZE(brc_color_table);
       cave->colorb = 0x000000;    /* fixed rgb black */
       cave->color0 = 0x000000;    /* fixed rgb black */
       cave->color1 = brc_color_table[colind];
@@ -469,20 +467,20 @@ static void brc_import(guint8 *data)
 
       /* append to caveset or forget it. */
       if (!only_dirt)
-       gd_caveset = g_list_append(gd_caveset, cave);
+       gd_caveset = list_append(gd_caveset, cave);
       else
        gd_cave_free(cave);
     }
   }
 }
 
-static void caveset_name_set_from_filename(const char *filename)
+static void caveset_name_set_from_filename(char *filename)
 {
   char *name;
   char *c;
 
   /* make up a caveset name from the filename. */
-  name = g_path_get_basename(filename);
+  name = getBaseName(filename);
   gd_strcpy(gd_caveset_data->name, name);
   free(name);
 
@@ -504,14 +502,13 @@ static void caveset_name_set_from_filename(const char *filename)
 */
 boolean gd_caveset_load_from_file(char *filename)
 {
-  GError *error = NULL;
-  gsize length;
+  size_t length;
   char *buf;
-  boolean read;
-  GList *new_caveset;
+  List *new_caveset;
   struct stat st;
+  File *file;
 
-  if (g_stat(filename, &st) != 0)
+  if (stat(filename, &st) != 0)
   {
     Warn("cannot stat() file");
 
@@ -525,12 +522,22 @@ boolean gd_caveset_load_from_file(char *filename)
     return FALSE;
   }
 
-  read = g_file_get_contents (filename, &buf, &length, &error);
-  if (!read)
+  if (!(file = openFile(filename, MODE_READ)))
   {
-    Warn("%s", error->message);
+    Warn("cannot open file '%s'", filename);
 
-    g_error_free(error);
+    return FALSE;
+  }
+
+  buf = checked_malloc(st.st_size + 1);
+  length = readFile(file, buf, 1, st.st_size);
+  buf[length] = '\0';
+
+  closeFile(file);
+
+  if (length < st.st_size)
+  {
+    Warn("cannot read file '%s'", filename);
 
     return FALSE;
   }
@@ -550,7 +557,7 @@ boolean gd_caveset_load_from_file(char *filename)
   if (strSuffix(filename, ".brc") ||
       strSuffix(filename, "*.BRC"))
   {
-    brc_import((guint8 *) buf);
+    brc_import((byte *) buf);
     gd_caveset_edited = FALSE;    /* newly loaded cave is not edited */
     gd_caveset_last_selected = caveset_first_selectable_cave_index();
     gd_caveset_last_selected_level = 0;
@@ -561,7 +568,7 @@ boolean gd_caveset_load_from_file(char *filename)
   }
 
   /* BDCFF */
-  if (gd_caveset_imported_get_format((guint8 *) buf) == GD_FORMAT_UNKNOWN)
+  if (gd_caveset_imported_get_format((byte *) buf) == GD_FORMAT_UNKNOWN)
   {
     /* try to load as bdcff */
     boolean result;
@@ -580,7 +587,7 @@ boolean gd_caveset_load_from_file(char *filename)
   }
 
   /* try to load as a binary file, as we know the format */
-  new_caveset = gd_caveset_import_from_buffer ((guint8 *) buf, length);
+  new_caveset = gd_caveset_import_from_buffer ((byte *) buf, length);
   free(buf);
 
   /* if unable to load, exit here. error was reported by import_from_buffer() */
@@ -604,18 +611,53 @@ boolean gd_caveset_load_from_file(char *filename)
   return TRUE;
 }
 
+boolean gd_caveset_save_to_file(const char *filename)
+{
+  GdPtrArray *saved = gd_caveset_save_to_bdcff();
+  boolean success;
+  File *file;
+  int i;
+
+  if ((file = openFile(filename, MODE_WRITE)) != NULL)
+  {
+    for (i = 0; i < saved->size; i++)
+    {
+      writeFile(file, saved->data[i], 1, strlen(saved->data[i]));
+      writeFile(file, "\n", 1, 1);
+    }
+
+    closeFile(file);
+
+    /* remember that it is saved */
+    gd_caveset_edited = FALSE;
+
+    success = TRUE;
+  }
+  else
+  {
+    Warn("cannot open file '%s'", filename);
+
+    success = FALSE;
+  }
+
+  gd_ptr_array_free(saved, TRUE);
+
+  return success;
+}
+
+
 int gd_cave_check_replays(GdCave *cave, boolean report, boolean remove, boolean repair)
 {
-  GList *riter;
+  List *riter;
   int wrong = 0;
 
   riter = cave->replays;
   while (riter != NULL)
   {
     GdReplay *replay = (GdReplay *)riter->data;
-    guint32 checksum;
+    unsigned int checksum;
     GdCave *rendered;
-    GList *next = riter->next;
+    List *next = riter->next;
 
     rendered = gd_cave_new_rendered(cave, replay->level, replay->seed);
     checksum = gd_cave_adler_checksum(rendered);
@@ -646,7 +688,7 @@ int gd_cave_check_replays(GdCave *cave, boolean report, boolean remove, boolean
        if (remove)
        {
          /* may remove */
-         cave->replays = g_list_remove_link(cave->replays, riter);
+         cave->replays = list_remove_link(cave->replays, riter);
          gd_replay_free(replay);
        }
       }
@@ -661,7 +703,7 @@ int gd_cave_check_replays(GdCave *cave, boolean report, boolean remove, boolean
 
 boolean gd_caveset_has_replays(void)
 {
-  GList *citer;
+  List *citer;
 
   /* for all caves */
   for (citer = gd_caveset; citer != NULL; citer = citer->next)