summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBardur Arantsson <bardur@scientician.net>2015-03-07 18:36:59 +0100
committerBardur Arantsson <bardur@scientician.net>2015-03-07 19:42:45 +0100
commitfb2a78c52a32026a57fd9cc7763a783456199dd7 (patch)
tree52a67b2ba0df2d75bd046b52afc9af36fa55ed03 /src
parent77cfd35e4f2b2e1d43fd3aa45133742f91676e3e (diff)
Clean up loadsave.cc to eliminate LS_LOAD/LS_SAVE macros
In addition, topologically sort the functions in loadsave.cc to avoid the redundant static function declarations.
Diffstat (limited to 'src')
-rw-r--r--src/defines.h9
-rw-r--r--src/loadsave.cc2366
2 files changed, 1164 insertions, 1211 deletions
diff --git a/src/defines.h b/src/defines.h
index d4981d72..564eeceb 100644
--- a/src/defines.h
+++ b/src/defines.h
@@ -4000,15 +4000,6 @@
#define HOOK_FORBID_TRAVEL 75
/*
- * Defines for loadsave.c
- * Why 3 and 7? So if it's uninitialized, the code will be able to catch it, as
- * 0 is an invalid flag. Also, having them apart means that it being accidentally
- * modified will also result in an invalid value -- Improv
- */
-#define LS_LOAD 3
-#define LS_SAVE 7
-
-/*
* In game help
*/
#define HELP_MAX 64
diff --git a/src/loadsave.cc b/src/loadsave.cc
index 10582487..9c897c47 100644
--- a/src/loadsave.cc
+++ b/src/loadsave.cc
@@ -24,41 +24,16 @@
#include <memory>
static u32b vernum; /* Version flag */
-
-static void do_byte(byte *, int);
-static void do_bool(bool_ *, int);
-static void do_u16b(u16b *, int);
-static void do_s16b(s16b *, int);
-static void do_u32b(u32b *, int);
-static void do_s32b(s32b *, int);
-static void do_string(char *, int, int);
-static void do_lore(int, int);
-static void do_monster(monster_type *, int);
-static void do_randomizer(int flag);
-static void do_spells(int, int);
-static void note(cptr);
-static void do_fate(int, int);
-static void do_item(object_type *, int);
-static void do_options(int);
-static bool_ do_store(store_type *, int);
-static void do_messages(int flag);
-static void do_xtra(int, int);
-static bool_ do_savefile_aux(int);
-static void junkinit(void);
-static void morejunk(void);
-static bool_ do_inventory(int);
-static bool_ do_dungeon(int, bool_);
-static void do_grid(int);
-static void my_sentinel(const char *, u16b, int);
-
-static void do_ver_s16b(s16b *, u32b, s16b, int);
-
-static void skip_ver_byte(u32b, int);
-
-errr rd_savefile(void);
-
static FILE *fff; /* Local savefile ptr */
+/**
+ * Load/save flag
+ */
+enum class ls_flag_t {
+ LOAD = 3,
+ SAVE = 7
+};
+
/*
* Basic byte-level reading from savefile. This provides a single point
* of interface to the pseudoencryption that ToME (and Angband)
@@ -92,14 +67,101 @@ static void sf_put(byte v)
}
/*
+ * Size-aware read/write routines for the savefile, do all their
+ * work through sf_get and sf_put.
+ */
+static void do_byte(byte *v, ls_flag_t flag)
+{
+ if (flag == ls_flag_t::LOAD)
+ {
+ *v = sf_get();
+ return;
+ }
+ if (flag == ls_flag_t::SAVE)
+ {
+ byte val = *v;
+ sf_put(val);
+ return;
+ }
+ /* We should never reach here, so bail out */
+ printf("FATAL: do_byte passed %d\n", flag);
+ exit(0);
+}
+
+static void do_bool(bool_ *f, ls_flag_t flag)
+{
+ byte b = *f;
+ do_byte(&b, flag);
+ if (flag == ls_flag_t::LOAD)
+ {
+ *f = b;
+ }
+}
+
+static void do_u16b(u16b *v, ls_flag_t flag)
+{
+ if (flag == ls_flag_t::LOAD)
+ {
+ (*v) = sf_get();
+ (*v) |= ((u16b)(sf_get()) << 8);
+ return;
+ }
+ if (flag == ls_flag_t::SAVE)
+ {
+ u16b val;
+ val = *v;
+ sf_put((byte)(val & 0xFF));
+ sf_put((byte)((val >> 8) & 0xFF));
+ return;
+ }
+ /* Never should reach here, bail out */
+ printf("FATAL: do_u16b passed %d\n", flag);
+ exit(0);
+}
+
+static void do_s16b(s16b *ip, ls_flag_t flag)
+{
+ do_u16b((u16b *)ip, flag);
+}
+
+static void do_u32b(u32b *ip, ls_flag_t flag)
+{
+ if (flag == ls_flag_t::LOAD)
+ {
+ (*ip) = sf_get();
+ (*ip) |= ((u32b)(sf_get()) << 8);
+ (*ip) |= ((u32b)(sf_get()) << 16);
+ (*ip) |= ((u32b)(sf_get()) << 24);
+ return;
+ }
+ if (flag == ls_flag_t::SAVE)
+ {
+ u32b val = *ip;
+ sf_put((byte)(val & 0xFF));
+ sf_put((byte)((val >> 8) & 0xFF));
+ sf_put((byte)((val >> 16) & 0xFF));
+ sf_put((byte)((val >> 24) & 0xFF));
+ return;
+ }
+ /* Bad news if you're here, because you're going down */
+ printf("FATAL: do_u32b passed %d\n", flag);
+ exit(0);
+}
+
+static void do_s32b(s32b *ip, ls_flag_t flag)
+{
+ do_u32b((u32b *)ip, flag);
+}
+
+/*
* Do object memory and similar stuff
*/
-static void do_xtra(int k_idx, int flag)
+static void do_xtra(int k_idx, ls_flag_t flag)
{
byte tmp8u = 0;
object_kind *k_ptr = &k_info[k_idx];
- if (flag == LS_SAVE)
+ if (flag == ls_flag_t::SAVE)
{
if (k_ptr->aware) tmp8u |= 0x01;
if (k_ptr->tried) tmp8u |= 0x02;
@@ -108,7 +170,7 @@ static void do_xtra(int k_idx, int flag)
do_byte(&tmp8u, flag);
}
- if (flag == LS_LOAD)
+ if (flag == ls_flag_t::LOAD)
{
do_byte(&tmp8u, flag);
k_ptr->aware = ((tmp8u & 0x01) ? TRUE : FALSE);
@@ -118,10 +180,59 @@ static void do_xtra(int k_idx, int flag)
}
}
+static void save_string(const char *str)
+{
+ while (*str)
+ {
+ do_byte((byte*)str, ls_flag_t::SAVE);
+ str++;
+ }
+ do_byte((byte*)str, ls_flag_t::SAVE);
+}
+
+static void load_string(char *str, int max)
+{
+ int i;
+
+ /* Read the string */
+ for (i = 0; TRUE; i++)
+ {
+ byte tmp8u;
+
+ /* Read a byte */
+ do_byte(&tmp8u, ls_flag_t::LOAD);
+
+ /* Collect string while legal */
+ if (i < max) str[i] = tmp8u;
+
+ /* End of string */
+ if (!tmp8u) break;
+ }
+ /* Terminate */
+ str[max - 1] = '\0';
+}
+
+static void do_string(char *str, int max, ls_flag_t flag)
+/* Max is ignored for writing */
+{
+ if (flag == ls_flag_t::LOAD)
+ {
+ load_string(str, max);
+ return;
+ }
+ if (flag == ls_flag_t::SAVE)
+ {
+ save_string(str);
+ return;
+ }
+ printf("FATAL: do_string passed flag %d\n", flag);
+ exit(0);
+}
+
/*
* Load/Save quick start data
*/
-void do_quick_start(int flag)
+static void do_quick_start(ls_flag_t flag)
{
s16b tmp16s;
u32b tmp32u;
@@ -154,7 +265,7 @@ void do_quick_start(int flag)
/*
* The special saved subrace
*/
-static void do_subrace(int flag)
+static void do_subrace(ls_flag_t flag)
{
player_race_mod *sr_ptr = &race_mod_info[SUBRACE_SAVE];
int i;
@@ -162,22 +273,22 @@ static void do_subrace(int flag)
buf[80] = '\0'; // Make sure string is always NUL terminated
- if (flag == LS_SAVE)
+ if (flag == ls_flag_t::SAVE)
{
strncpy(buf, sr_ptr->title, 80);
}
do_string(buf, 80, flag);
- if (flag == LS_LOAD)
+ if (flag == ls_flag_t::LOAD)
{
set_subrace_title(sr_ptr, buf);
}
- if (flag == LS_SAVE)
+ if (flag == ls_flag_t::SAVE)
{
strncpy(buf, sr_ptr->desc, 80);
}
do_string(buf, 80, flag);
- if (flag == LS_LOAD)
+ if (flag == ls_flag_t::LOAD)
{
set_subrace_description(sr_ptr, buf);
}
@@ -249,11 +360,71 @@ static void do_subrace(int flag)
}
}
+
+/* Load/Save the random spells info */
+static void do_spells(int i, ls_flag_t flag)
+{
+ random_spell *s_ptr = &random_spells[i];
+ do_string(s_ptr->name, 30, flag);
+ do_string(s_ptr->desc, 30, flag);
+ do_s16b(&s_ptr->mana, flag);
+ do_s16b(&s_ptr->fail, flag);
+ do_u32b(&s_ptr->proj_flags, flag);
+ do_byte(&s_ptr->GF, flag);
+ do_byte(&s_ptr->radius, flag);
+ do_byte(&s_ptr->dam_sides, flag);
+ do_byte(&s_ptr->dam_dice, flag);
+ do_byte(&s_ptr->level, flag);
+ do_byte((byte*)&s_ptr->untried, flag);
+}
+
+
+/*
+ * Show information on the screen, one line at a time.
+ *
+ * Avoid the top two lines, to avoid interference with "msg_print()".
+ */
+static void note(cptr msg)
+{
+ static int y = 2;
+
+ /* Draw the message */
+ prt(msg, y, 0);
+
+ /* Advance one line (wrap if needed) */
+ if (++y >= 24) y = 2;
+
+ /* Flush it */
+ Term_fresh();
+}
+
+
+static void skip_ver_byte(u32b version, ls_flag_t flag)
+/* Reads and discards a byte if the savefile is as old as/older than version */
+{
+ if ((flag == ls_flag_t::LOAD) && (vernum <= version))
+ {
+ byte forget;
+ do_byte(&forget, flag);
+ }
+ return;
+}
+
+static void do_ver_s16b(s16b *v, u32b version, s16b defval, ls_flag_t flag)
+{
+ if ((flag == ls_flag_t::LOAD) && (vernum < version))
+ {
+ *v = defval;
+ return;
+ }
+ do_s16b(v, flag);
+}
+
/*
* Misc. other data
*/
static char loaded_game_module[80];
-static bool_ do_extra(int flag)
+static bool_ do_extra(ls_flag_t flag)
{
int i, j;
byte tmp8u = 0;
@@ -273,14 +444,14 @@ static bool_ do_extra(int flag)
}
/* Handle the special levels info */
- if (flag == LS_SAVE)
+ if (flag == ls_flag_t::SAVE)
{
tmp8u = max_d_idx;
tmp16s = MAX_DUNGEON_DEPTH;
}
do_byte(&tmp8u, flag);
- if (flag == LS_LOAD)
+ if (flag == ls_flag_t::LOAD)
{
if (tmp8u > max_d_idx)
{
@@ -290,7 +461,7 @@ static bool_ do_extra(int flag)
do_s16b(&tmp16s, flag);
- if (flag == LS_LOAD)
+ if (flag == ls_flag_t::LOAD)
{
if (tmp16s > MAX_DUNGEON_DEPTH)
{
@@ -326,7 +497,7 @@ static bool_ do_extra(int flag)
do_u16b(&tmp16b, flag);
do_byte(&p_ptr->mimic_form, flag);
do_s16b(&p_ptr->mimic_level, flag);
- if (flag == LS_SAVE) tmp8u = 0;
+ if (flag == ls_flag_t::SAVE) tmp8u = 0;
do_byte(&p_ptr->hitdie, flag);
do_u16b(&p_ptr->expfact, flag);
@@ -350,12 +521,12 @@ static bool_ do_extra(int flag)
tmp16s = MAX_SKILLS;
do_s16b(&tmp16s, flag);
- if ((flag == LS_LOAD) && (tmp16s > MAX_SKILLS))
+ if ((flag == ls_flag_t::LOAD) && (tmp16s > MAX_SKILLS))
{
quit("Too many skills");
}
- if (flag == LS_SAVE) old_max_s_idx = max_s_idx;
+ if (flag == ls_flag_t::SAVE) old_max_s_idx = max_s_idx;
do_u16b(&old_max_s_idx, flag);
for (i = 0; i < tmp16s; ++i)
{
@@ -380,7 +551,7 @@ static bool_ do_extra(int flag)
tmp16s = max_ab_idx;
do_s16b(&tmp16s, flag);
- if ((flag == LS_LOAD) && (tmp16s > max_ab_idx))
+ if ((flag == ls_flag_t::LOAD) && (tmp16s > max_ab_idx))
{
quit("Too many abilities");
}
@@ -436,10 +607,10 @@ static bool_ do_extra(int flag)
do_byte(&tmp8u, flag); /* tmp8u should be 0 at this point */
- if (flag == LS_SAVE) tmp8u = MAX_PLOTS;
+ if (flag == ls_flag_t::SAVE) tmp8u = MAX_PLOTS;
do_byte(&tmp8u, flag);
- if ((flag == LS_LOAD) && (tmp8u > MAX_PLOTS))
+ if ((flag == ls_flag_t::LOAD) && (tmp8u > MAX_PLOTS))
{
quit(format("Too many plots, %d %d", tmp8u, MAX_PLOTS));
}
@@ -449,13 +620,13 @@ static bool_ do_extra(int flag)
do_s16b(&plots[i], flag);
}
- if (flag == LS_SAVE)
+ if (flag == ls_flag_t::SAVE)
{
tmp8u = MAX_RANDOM_QUEST;
}
do_byte(&tmp8u, flag);
- if ((flag == LS_LOAD) &&
+ if ((flag == ls_flag_t::LOAD) &&
(tmp8u > MAX_RANDOM_QUEST)) quit("Too many random quests");
for (i = 0; i < tmp8u; i++)
{
@@ -499,19 +670,19 @@ static bool_ do_extra(int flag)
/* Max Player and Dungeon Levels */
do_s16b(&p_ptr->max_plv, flag);
- if (flag == LS_SAVE)
+ if (flag == ls_flag_t::SAVE)
tmp8u = max_d_idx;
do_byte(&tmp8u, flag);
for (i = 0; i < tmp8u; i++)
{
- if (flag == LS_SAVE)
+ if (flag == ls_flag_t::SAVE)
tmp16s = max_dlv[i];
do_s16b(&tmp16s, flag);
- if ((flag == LS_LOAD) && (i <= max_d_idx))
+ if ((flag == ls_flag_t::LOAD) && (i <= max_d_idx))
max_dlv[i] = tmp16s;
}
/* Repair max player level??? */
- if ((flag == LS_LOAD) && (p_ptr->max_plv < p_ptr->lev))
+ if ((flag == ls_flag_t::LOAD) && (p_ptr->max_plv < p_ptr->lev))
p_ptr->max_plv = p_ptr->lev;
do_byte((byte*)&(p_ptr->help.enabled), flag);
@@ -616,7 +787,7 @@ static bool_ do_extra(int flag)
do_s16b(&tmp16s, flag); /* compat */
- if (flag == LS_SAVE) { tmp16s = CORRUPTIONS_MAX; }
+ if (flag == ls_flag_t::SAVE) { tmp16s = CORRUPTIONS_MAX; }
do_s16b(&tmp16s, flag);
if (tmp16s > CORRUPTIONS_MAX) {
quit("Too many corruptions");
@@ -624,12 +795,12 @@ static bool_ do_extra(int flag)
for (i = 0; i < tmp16s; i++)
{
- if (flag == LS_SAVE)
+ if (flag == ls_flag_t::SAVE)
tmp8u = p_ptr->corruptions[i];
do_byte(&tmp8u, flag);
- if (flag == LS_LOAD)
+ if (flag == ls_flag_t::LOAD)
p_ptr->corruptions[i] = tmp8u;
}
@@ -676,9 +847,9 @@ static bool_ do_extra(int flag)
/* Are we in astral mode? */
do_byte((byte*)&p_ptr->astral, flag);
- if (flag == LS_SAVE) tmp16s = POWER_MAX;
+ if (flag == ls_flag_t::SAVE) tmp16s = POWER_MAX;
do_s16b(&tmp16s, flag);
- if ((flag == LS_LOAD) && (tmp16s > POWER_MAX))
+ if ((flag == ls_flag_t::LOAD) && (tmp16s > POWER_MAX))
note(format("Too many (%u) powers!", tmp16s));
for (i = 0; i < POWER_MAX; i++)
do_byte((byte*)&p_ptr->powers_mod[i], flag);
@@ -729,12 +900,12 @@ static bool_ do_extra(int flag)
do_u16b(&noscore, flag);
/* Write death */
- if (flag == LS_SAVE) tmp8u = death;
+ if (flag == ls_flag_t::SAVE) tmp8u = death;
do_byte(&tmp8u, flag);
- if (flag == LS_LOAD) death = tmp8u;
+ if (flag == ls_flag_t::LOAD) death = tmp8u;
/* Incompatible module? */
- if (flag == LS_LOAD)
+ if (flag == ls_flag_t::LOAD)
{
s32b ok;
@@ -749,9 +920,9 @@ static bool_ do_extra(int flag)
}
/* Write feeling */
- if (flag == LS_SAVE) tmp8u = feeling;
+ if (flag == ls_flag_t::SAVE) tmp8u = feeling;
do_byte(&tmp8u, flag);
- if (flag == LS_LOAD) feeling = tmp8u;
+ if (flag == ls_flag_t::LOAD) feeling = tmp8u;
/* Turn of last "feeling" */
do_s32b(&old_turn, flag);
@@ -762,489 +933,58 @@ static bool_ do_extra(int flag)
return TRUE;
}
-/* Save the current persistent dungeon -SC- */
-void save_dungeon(void)
-{
- char tmp[16];
- char name[1024], buf[5];
-
- /* Save only persistent dungeons */
- if (!get_dungeon_save(buf) || (!dun_level)) return;
-
- /* Construct filename */
- sprintf(tmp, "%s.%s", player_base, buf);
- path_build(name, 1024, ANGBAND_DIR_SAVE, tmp);
-
- /* Open the file */
- fff = my_fopen(name, "wb");
-
- /* Save the dungeon */
- do_dungeon(LS_SAVE, TRUE);
-
- my_fclose(fff);
-}
/*
- * Medium level player saver
- */
-static bool_ save_player_aux(char *name)
-{
- bool_ ok = FALSE;
- int fd = -1;
- int mode = 0644;
-
- /* No file yet */
- fff = NULL;
-
- /* File type is "SAVE" */
- FILE_TYPE(FILE_TYPE_SAVE);
-
- /* Create the savefile */
- fd = fd_make(name, mode);
-
- /* File is okay */
- if (fd >= 0)
- {
- /* Close the "fd" */
- (void)fd_close(fd);
-
- /* Open the savefile */
- fff = my_fopen(name, "wb");
-
- /* Successful open */
- if (fff)
- {
- /* Write the savefile */
- if (do_savefile_aux(LS_SAVE)) ok = TRUE;
-
- /* Attempt to close it */
- if (my_fclose(fff)) ok = FALSE;
- }
-
- /* "broken" savefile */
- if (!ok)
- {
- /* Remove "broken" files */
- (void)fd_kill(name);
- }
- }
-
- /* Failure */
- if (!ok) return (FALSE);
-
- /* Success */
- return (TRUE);
-}
-
-/*
- * Attempt to save the player in a savefile
- */
-bool_ save_player(void)
-{
- int result = FALSE;
- char safe[1024];
-
- /* New savefile */
- strcpy(safe, savefile);
- strcat(safe, ".new");
-
- /* Remove it */
- fd_kill(safe);
-
- /* Attempt to save the player */
- if (save_player_aux(safe))
- {
- char temp[1024];
-
- /* Old savefile */
- strcpy(temp, savefile);
- strcat(temp, ".old");
-
- /* Remove it */
- fd_kill(temp);
-
- /* Preserve old savefile */
- fd_move(savefile, temp);
-
- /* Activate new savefile */
- fd_move(safe, savefile);
-
- /* Remove preserved savefile */
- fd_kill(temp);
-
- /* Hack -- Pretend the character was loaded */
- character_loaded = TRUE;
-
- /* Success */
- result = TRUE;
- }
-
- save_savefile_names();
-
- /* Return the result */
- return (result);
-}
-
-bool_ file_exist(cptr buf)
-{
- int fd;
- bool_ result;
-
- /* Open savefile */
- fd = fd_open(buf, O_RDONLY);
-
- /* File exists */
- if (fd >= 0)
- {
- fd_close(fd);
- result = TRUE;
- }
- else
- result = FALSE;
-
- return result;
-}
-
-/*
- * Attempt to Load a "savefile"
- *
- * On multi-user systems, you may only "read" a savefile if you will be
- * allowed to "write" it later, this prevents painful situations in which
- * the player loads a savefile belonging to someone else, and then is not
- * allowed to save his game when he quits.
- *
- * We return "TRUE" if the savefile was usable, and we set the global
- * flag "character_loaded" if a real, living, character was loaded.
- *
- * Note that we always try to load the "current" savefile, even if
- * there is no such file, so we must check for "empty" savefile names.
- */
-bool_ load_player(void)
-{
- int fd = -1;
-
- errr err = 0;
-
- cptr what = "generic";
-
- /* Paranoia */
- turn = 0;
-
- /* Paranoia */
- death = FALSE;
-
-
- /* Allow empty savefile name */
- if (!savefile[0]) return (TRUE);
-
-
- /* XXX XXX XXX Fix this */
-
- /* Verify the existance of the savefile */
- if (!file_exist(savefile))
- {
- /* Give a message */
- msg_format("Savefile does not exist: %s", savefile);
- msg_print(NULL);
-
- /* Allow this */
- return (TRUE);
- }
-
- /* Okay */
- if (!err)
- {
- /* Open the savefile */
- fd = fd_open(savefile, O_RDONLY);
-
- /* No file */
- if (fd < 0) err = -1;
-
- /* Message (below) */
- if (err) what = "Cannot open savefile";
- }
-
- /* Process file */
- if (!err)
- {
- byte tmp8u = 0;
-
- /* Open the file XXX XXX XXX XXX Should use Angband file interface */
- fff = my_fopen(savefile, "rb");
-/* fff = fdopen(fd, "r"); */
-
- /* Read the first four bytes */
- do_u32b(&vernum, LS_LOAD);
- do_byte(&tmp8u, LS_LOAD); // For comatibility with old savefiles
-
- /* XXX XXX XXX XXX Should use Angband file interface */
- my_fclose(fff);
- /* fclose(fff) */
-
- /* Close the file */
- fd_close(fd);
- }
-
- /* Process file */
- if (!err)
- {
-
- /* Extract version */
- sf_major = VERSION_MAJOR;
- sf_minor = VERSION_MINOR;
- sf_patch = VERSION_PATCH;
-
- /* Clear screen */
- Term_clear();
-
- /* Attempt to load */
- err = rd_savefile();
-
- /* Message (below) */
- if (err) what = "Cannot parse savefile";
- }
-
- /* Paranoia */
- if (!err)
- {
- /* Invalid turn */
- if (!turn) err = -1;
-
- /* Message (below) */
- if (err) what = "Broken savefile";
- }
-
-
- /* Okay */
- if (!err)
- {
- /* Player is dead */
- if (death)
- {
- /* Player is no longer "dead" */
- death = FALSE;
-
- /* Cheat death (unless the character retired) */
- if (arg_wizard && !total_winner)
- {
- /* A character was loaded */
- character_loaded = TRUE;
-
- /* Done */
- return (TRUE);
- }
-
- /* Count lives */
- sf_lives++;
-
- /* Forget turns */
- turn = old_turn = 0;
-
- /* Done */
- return (TRUE);
- }
-
- /* A character was loaded */
- character_loaded = TRUE;
-
- /* Still alive */
- if (p_ptr->chp >= 0)
- {
- /* Reset cause of death */
- (void)strcpy(died_from, "(alive and well)");
- }
-
- /* Success */
- return (TRUE);
- }
-
-
- /* Message */
- msg_format("Error (%s) reading %d.%d.%d savefile.",
- what, sf_major, sf_minor, sf_patch);
- msg_print(NULL);
-
- /* Oops */
- return (FALSE);
-}
-
-
-/*
- * Size-aware read/write routines for the savefile, do all their
- * work through sf_get and sf_put.
+ * Read a monster
*/
-
-static void do_byte(byte *v, int flag)
-{
- if (flag == LS_LOAD)
- {
- *v = sf_get();
- return;
- }
- if (flag == LS_SAVE)
- {
- byte val = *v;
- sf_put(val);
- return;
- }
- /* We should never reach here, so bail out */
- printf("FATAL: do_byte passed %d\n", flag);
- exit(0);
-}
-
-static void do_bool(bool_ *f, int flag)
-{
- byte b = *f;
- do_byte(&b, flag);
- if (flag == LS_LOAD)
- {
- *f = b;
- }
-}
-
-static void do_u16b(u16b *v, int flag)
-{
- if (flag == LS_LOAD)
- {
- (*v) = sf_get();
- (*v) |= ((u16b)(sf_get()) << 8);
- return;
- }
- if (flag == LS_SAVE)
- {
- u16b val;
- val = *v;
- sf_put((byte)(val & 0xFF));
- sf_put((byte)((val >> 8) & 0xFF));
- return;
- }
- /* Never should reach here, bail out */
- printf("FATAL: do_u16b passed %d\n", flag);
- exit(0);
-}
-
-static void do_s16b(s16b *ip, int flag)
-{
- do_u16b((u16b *)ip, flag);
-}
-
-static void do_u32b(u32b *ip, int flag)
-{
- if (flag == LS_LOAD)
- {
- (*ip) = sf_get();
- (*ip) |= ((u32b)(sf_get()) << 8);
- (*ip) |= ((u32b)(sf_get()) << 16);
- (*ip) |= ((u32b)(sf_get()) << 24);
- return;
- }
- if (flag == LS_SAVE)
- {
- u32b val = *ip;
- sf_put((byte)(val & 0xFF));
- sf_put((byte)((val >> 8) & 0xFF));
- sf_put((byte)((val >> 16) & 0xFF));
- sf_put((byte)((val >> 24) & 0xFF));
- return;
- }
- /* Bad news if you're here, because you're going down */
- printf("FATAL: do_u32b passed %d\n", flag);
- exit(0);
-}
-
-static void do_s32b(s32b *ip, int flag)
+static void do_monster(monster_type *m_ptr, ls_flag_t flag)
{
- do_u32b((u32b *)ip, flag);
-}
+ int i;
-static void save_string(const char *str)
-{
- while (*str)
- {
- do_byte((byte*)str, LS_SAVE);
- str++;
- }
- do_byte((byte*)str, LS_SAVE);
-}
+ /* Read the monster race */
+ do_s16b(&m_ptr->r_idx, flag);
-static void load_string(char *str, int max)
-{
- int i;
+ do_u16b(&m_ptr->ego, flag);
- /* Read the string */
- for (i = 0; TRUE; i++)
- {
- byte tmp8u;
+ /* Read the other information */
+ do_byte(&m_ptr->fy, flag);
+ do_byte(&m_ptr->fx, flag);
- /* Read a byte */
- do_byte(&tmp8u, LS_LOAD);
+ do_s32b(&m_ptr->hp, flag);
+ do_s32b(&m_ptr->maxhp, flag);
- /* Collect string while legal */
- if (i < max) str[i] = tmp8u;
+ do_s16b(&m_ptr->csleep, flag);
+ do_byte(&m_ptr->mspeed, flag);
+ do_byte(&m_ptr->energy, flag);
+ do_byte(&m_ptr->stunned, flag);
+ do_byte(&m_ptr->confused, flag);
+ do_byte(&m_ptr->monfear, flag);
+ do_u32b(&m_ptr->smart, flag);
+ do_s16b(&m_ptr->status, flag);
+ do_s16b(&m_ptr->possessor, flag);
+ do_byte(&m_ptr->speed, flag);
+ do_byte(&m_ptr->level, flag);
+ do_s16b(&m_ptr->ac, flag);
+ do_s32b(&m_ptr->exp, flag);
+ do_s16b(&m_ptr->target, flag);
- /* End of string */
- if (!tmp8u) break;
- }
- /* Terminate */
- str[max - 1] = '\0';
-}
+ do_s16b(&m_ptr->bleeding, flag);
+ do_s16b(&m_ptr->poisoned, flag);
-static void do_string(char *str, int max, int flag)
-/* Max is ignored for writing */
-{
- if (flag == LS_LOAD)
- {
- load_string(str, max);
- return;
- }
- if (flag == LS_SAVE)
- {
- save_string(str);
- return;
- }
- printf("FATAL: do_string passed flag %d\n", flag);
- exit(0);
-}
+ do_s32b(&m_ptr->mflag, flag);
-static void skip_ver_byte(u32b version, int flag)
-/* Reads and discards a byte if the savefile is as old as/older than version */
-{
- if ((flag == LS_LOAD) && (vernum <= version))
- {
- byte forget;
- do_byte(&forget, flag);
- }
- return;
-}
+ if (flag == ls_flag_t::LOAD) m_ptr->mflag &= PERM_MFLAG_MASK;
-static void do_ver_s16b(s16b *v, u32b version, s16b defval, int flag)
-{
- if ((flag == LS_LOAD) && (vernum < version))
+ /* Attacks */
+ for (i = 0; i < 4; i++)
{
- *v = defval;
- return;
+ do_byte(&m_ptr->blow[i].method, flag);
+ do_byte(&m_ptr->blow[i].effect, flag);
+ do_byte(&m_ptr->blow[i].d_dice, flag);
+ do_byte(&m_ptr->blow[i].d_side, flag);
}
- do_s16b(v, flag);
}
-/*
- * Show information on the screen, one line at a time.
- *
- * Avoid the top two lines, to avoid interference with "msg_print()".
- */
-static void note(cptr msg)
-{
- static int y = 2;
-
- /* Draw the message */
- prt(msg, y, 0);
-
- /* Advance one line (wrap if needed) */
- if (++y >= 24) y = 2;
-
- /* Flush it */
- Term_fresh();
-}
/*
@@ -1306,7 +1046,7 @@ static bool_ wearable_p(object_type *o_ptr)
* FIXME! This code probably has a lot of cruft from the old Z/V codebase.
*
*/
-static void do_item(object_type *o_ptr, int flag)
+static void do_item(object_type *o_ptr, ls_flag_t flag)
{
byte old_dd;
byte old_ds;
@@ -1351,15 +1091,15 @@ static void do_item(object_type *o_ptr, int flag)
do_s16b(&o_ptr->ac, flag);
/* We do special processing of this flag when reading */
- if (flag == LS_LOAD)
+ if (flag == ls_flag_t::LOAD)
{
- do_byte(&old_dd, LS_LOAD);
- do_byte(&old_ds, LS_LOAD);
+ do_byte(&old_dd, ls_flag_t::LOAD);
+ do_byte(&old_ds, ls_flag_t::LOAD);
}
- if (flag == LS_SAVE)
+ if (flag == ls_flag_t::SAVE)
{
- do_byte(&o_ptr->dd, LS_SAVE);
- do_byte(&o_ptr->ds, LS_SAVE);
+ do_byte(&o_ptr->dd, ls_flag_t::SAVE);
+ do_byte(&o_ptr->ds, ls_flag_t::SAVE);
}
do_byte(&o_ptr->ident, flag);
@@ -1402,7 +1142,7 @@ static void do_item(object_type *o_ptr, int flag)
do_s16b(&o_ptr->found_aux3, flag);
do_s16b(&o_ptr->found_aux4, flag);
- if (flag == LS_LOAD)
+ if (flag == ls_flag_t::LOAD)
{
char buf[128];
/* Inscription */
@@ -1418,7 +1158,7 @@ static void do_item(object_type *o_ptr, int flag)
o_ptr->art_name = quark_add(buf);
}
}
- if (flag == LS_SAVE)
+ if (flag == ls_flag_t::SAVE)
{
/* Save the inscription (if any) */
if (o_ptr->note)
@@ -1439,10 +1179,10 @@ static void do_item(object_type *o_ptr, int flag)
}
}
- if (flag == LS_SAVE) return ; /* Stick any more shared code before this. The rest
- of this function is reserved for LS_LOAD's
+ if (flag == ls_flag_t::SAVE) return ; /* Stick any more shared code before this. The rest
+ of this function is reserved for ls_flag_t::LOAD's
cleanup functions */
- /*********** END OF LS_SAVE ***************/
+ /*********** END OF ls_flag_t::SAVE ***************/
/* Obtain the "kind" template */
k_ptr = &k_info[o_ptr->k_idx];
@@ -1535,67 +1275,572 @@ static void do_item(object_type *o_ptr, int flag)
}
+static void do_grid(ls_flag_t flag)
+/* Does the grid, RLE, blahblah. RLE sucks. I hate it. */
+{
+ int i = 0, y = 0, x = 0;
+ byte count = 0;
+ byte tmp8u = 0;
+ s16b tmp16s = 0;
+ cave_type *c_ptr;
+ byte prev_char = 0;
+ s16b prev_s16b = 0;
+ int ymax = cur_hgt, xmax = cur_wid;
+
+ int part; /* Which section of the grid we're on */
+
+ for (part = 0; part < 9; part++) /* There are 8 fields to the grid, each stored
+ in a seperate RLE data structure */
+ {
+ if (flag == ls_flag_t::SAVE)
+ {
+ count = 0;
+ prev_s16b = 0;
+ prev_char = 0; /* Clear, prepare for RLE */
+ for (y = 0; y < cur_hgt; y++)
+ {
+ for (x = 0; x < cur_wid; x++)
+ {
+ c_ptr = &cave[y][x];
+ switch (part)
+ {
+ case 0:
+ tmp16s = c_ptr->info;
+ break;
+
+ case 1:
+ tmp8u = c_ptr->feat;
+ break;
+
+ case 2:
+ tmp8u = c_ptr->mimic;
+ break;
+
+ case 3:
+ tmp16s = c_ptr->special;
+ break;
+
+ case 4:
+ tmp16s = c_ptr->special2;
+ break;
+
+ case 5:
+ tmp16s = c_ptr->t_idx;
+ break;
+
+ case 6:
+ tmp16s = c_ptr->inscription;
+ break;
+
+ case 7:
+ tmp8u = c_ptr->mana;
+ break;
+
+ case 8:
+ tmp16s = c_ptr->effect;
+ break;
+ }
+ /* Flush a full run */
+ if ((((part != 1) && (part != 2) && (part != 7)) &&
+ (tmp16s != prev_s16b)) || (((part == 1) || (part == 2)
+ || (part == 7)) &&
+ (tmp8u != prev_char)) ||
+ (count == MAX_UCHAR))
+ {
+ do_byte(&count, ls_flag_t::SAVE);
+ switch (part)
+ {
+ case 0:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 8:
+ do_s16b(&prev_s16b, ls_flag_t::SAVE);
+ prev_s16b = tmp16s;
+ break;
+
+ case 1:
+ case 2:
+ case 7:
+ do_byte(&prev_char, ls_flag_t::SAVE);
+ prev_char = tmp8u;
+ break;
+ }
+ count = 1; /* Reset RLE */
+ }
+ else
+ count++; /* Otherwise, keep going */
+ }
+ }
+ /* Fallen off the end of the world, flush anything left */
+ if (count)
+ {
+ do_byte(&count, ls_flag_t::SAVE);
+ switch (part)
+ {
+ case 0:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 8:
+ do_s16b(&prev_s16b, ls_flag_t::SAVE);
+ break;
+
+ case 1:
+ case 2:
+ case 7:
+ do_byte(&prev_char, ls_flag_t::SAVE);
+ break;
+ }
+ }
+ }
+ if (flag == ls_flag_t::LOAD)
+ {
+ x = 0;
+ for (y = 0; y < ymax; )
+ {
+ do_byte(&count, ls_flag_t::LOAD);
+ switch (part)
+ {
+ case 0:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 8:
+ do_s16b(&tmp16s, ls_flag_t::LOAD);
+ break;
+
+ case 1:
+ case 2:
+ case 7:
+ do_byte(&tmp8u, ls_flag_t::LOAD);
+ break;
+ }
+ for (i = count; i > 0; i--) /* RLE */
+ {
+ c_ptr = &cave[y][x];
+ switch (part)
+ {
+ case 0:
+ c_ptr->info = tmp16s;
+ break;
+
+ case 1:
+ c_ptr->feat = tmp8u;
+ break;
+
+ case 2:
+ c_ptr->mimic = tmp8u;
+ break;
+
+ case 3:
+ c_ptr->special = tmp16s;
+ break;
+
+ case 4:
+ c_ptr->special2 = tmp16s;
+ break;
+
+ case 5:
+ c_ptr->t_idx = tmp16s;
+ break;
+
+ case 6:
+ c_ptr->inscription = tmp16s;
+ break;
+
+ case 7:
+ c_ptr->mana = tmp8u;
+ break;
+
+ case 8:
+ c_ptr->effect = tmp16s;
+ break;
+ }
+ if (++x >= xmax)
+ {
+ /* Wrap */
+ x = 0;
+ if ((++y) >= ymax) break;
+ }
+ }
+ }
+ }
+ }
+}
+
+
+
+static void my_sentinel(const char *place, u16b value, ls_flag_t flag)
+/* This function lets us know exactly where a savefile is
+ broken by reading/writing conveniently a sentinel at this
+ spot */
+{
+ if (flag == ls_flag_t::SAVE)
+ {
+ do_u16b(&value, flag);
+ return;
+ }
+ if (flag == ls_flag_t::LOAD)
+ {
+ u16b found;
+ do_u16b(&found, flag);
+ if (found == value) /* All is good */
+ return;
+ /* All is bad */
+ note(format("Savefile broken %s", place));
+ return;
+ }
+ note(format("Impossible has occurred")); /* Programmer error */
+ exit(0);
+}
+
/*
- * Read a monster
+ * Handle dungeon
+ *
+ * The monsters/objects must be loaded in the same order
+ * that they were stored, since the actual indexes matter.
*/
-static void do_monster(monster_type *m_ptr, int flag)
+static bool_ do_dungeon(ls_flag_t flag, bool_ no_companions)
{
int i;
- /* Read the monster race */
- do_s16b(&m_ptr->r_idx, flag);
+ cave_type *c_ptr;
- do_u16b(&m_ptr->ego, flag);
+ /* Read specific */
+ u16b tmp16b = 0;
- /* Read the other information */
- do_byte(&m_ptr->fy, flag);
- do_byte(&m_ptr->fx, flag);
+ my_sentinel("Before do_dungeon", 324, flag);
- do_s32b(&m_ptr->hp, flag);
- do_s32b(&m_ptr->maxhp, flag);
+ /* Header info */
+ do_s16b(&dun_level, flag);
+ do_byte(&dungeon_type, flag);
+ do_s16b(&num_repro, flag);
+ do_s16b(&p_ptr->py, flag);
+ do_s16b(&p_ptr->px, flag);
+ do_s16b(&cur_hgt, flag);
+ do_s16b(&cur_wid, flag);
+ do_s16b(&max_panel_rows, flag);
+ do_s16b(&max_panel_cols, flag);
- do_s16b(&m_ptr->csleep, flag);
- do_byte(&m_ptr->mspeed, flag);
- do_byte(&m_ptr->energy, flag);
- do_byte(&m_ptr->stunned, flag);
- do_byte(&m_ptr->confused, flag);
- do_byte(&m_ptr->monfear, flag);
- do_u32b(&m_ptr->smart, flag);
- do_s16b(&m_ptr->status, flag);
- do_s16b(&m_ptr->possessor, flag);
- do_byte(&m_ptr->speed, flag);
- do_byte(&m_ptr->level, flag);
- do_s16b(&m_ptr->ac, flag);
- do_s32b(&m_ptr->exp, flag);
- do_s16b(&m_ptr->target, flag);
+ do_u32b(&dungeon_flags1, flag);
+ do_u32b(&dungeon_flags2, flag);
- do_s16b(&m_ptr->bleeding, flag);
- do_s16b(&m_ptr->poisoned, flag);
+ /* Last teleportation */
+ do_s16b(&last_teleportation_y, flag);
+ do_s16b(&last_teleportation_y, flag);
- do_s32b(&m_ptr->mflag, flag);
+ /* Spell effects */
+ tmp16b = MAX_EFFECTS;
+ do_u16b(&tmp16b, flag);
- if (flag == LS_LOAD) m_ptr->mflag &= PERM_MFLAG_MASK;
+ if ((flag == ls_flag_t::LOAD) && (tmp16b > MAX_EFFECTS))
+ {
+ quit("Too many spell effects");
+ }
- /* Attacks */
- for (i = 0; i < 4; i++)
+ for (i = 0; i < tmp16b; ++i)
{
- do_byte(&m_ptr->blow[i].method, flag);
- do_byte(&m_ptr->blow[i].effect, flag);
- do_byte(&m_ptr->blow[i].d_dice, flag);
- do_byte(&m_ptr->blow[i].d_side, flag);
+ do_s16b(&effects[i].type, flag);
+ do_s16b(&effects[i].dam, flag);
+ do_s16b(&effects[i].time, flag);
+ do_u32b(&effects[i].flags, flag);
+ do_s16b(&effects[i].cx, flag);
+ do_s16b(&effects[i].cy, flag);
+ do_s16b(&effects[i].rad, flag);
+ }
+
+ /* TO prevent bugs with evolving dungeons */
+ for (i = 0; i < 100; i++)
+ {
+ do_s16b(&floor_type[i], flag);
+ do_s16b(&fill_type[i], flag);
+ }
+
+ if ((flag == ls_flag_t::LOAD) && (!dun_level && !p_ptr->inside_quest))
+ {
+ int xstart = 0;
+ int ystart = 0;
+ /* Init the wilderness */
+ process_dungeon_file("w_info.txt", &ystart, &xstart, cur_hgt, cur_wid,
+ TRUE, FALSE);
+
+ /* Init the town */
+ xstart = 0;
+ ystart = 0;
+ init_flags = 0;
+ process_dungeon_file("t_info.txt", &ystart, &xstart, cur_hgt, cur_wid,
+ TRUE, FALSE);
+ }
+
+ do_grid(flag);
+
+ /*** Objects ***/
+
+ if (flag == ls_flag_t::SAVE) compact_objects(0);
+ if (flag == ls_flag_t::SAVE) compact_monsters(0);
+ if (flag == ls_flag_t::SAVE)
+ {
+ tmp16b = o_max;
+
+ if (no_companions)
+ {
+ for (i = 1; i < o_max; i++)
+ {
+ object_type *o_ptr = &o_list[i];
+
+ if (o_ptr->held_m_idx && (m_list[o_ptr->held_m_idx].status == MSTATUS_COMPANION)) tmp16b--;
+ }
+ }
+
+ /* Item count */
+ do_u16b(&tmp16b, flag);
+
+ tmp16b = o_max;
+ }
+ else
+ /* Read item count */
+ do_u16b(&tmp16b, flag);
+
+ /* Verify maximum */
+ if ((flag == ls_flag_t::LOAD) && (tmp16b > max_o_idx))
+ {
+ note(format("Too many (%d) object entries!", tmp16b));
+ return (FALSE);
+ }
+
+ /* Dungeon items */
+ for (i = 1; i < tmp16b; i++)
+ {
+ int o_idx;
+
+ object_type *o_ptr;
+
+ if (flag == ls_flag_t::SAVE)
+ {
+ o_ptr = &o_list[i];
+ /* Don't save objects held by companions when no_companions is set */
+ if (no_companions && o_ptr->held_m_idx && (m_list[o_ptr->held_m_idx].status == MSTATUS_COMPANION)) continue;
+
+ do_item(o_ptr, ls_flag_t::SAVE);
+ continue; /* Saving is easy */
+ }
+ /* Until the end of the loop, this is all ls_flag_t::LOAD */
+
+ /* Get a new record */
+ o_idx = o_pop();
+
+ /* Oops */
+ if (i != o_idx)
+ {
+ note(format("Object allocation error (%d <> %d)", i, o_idx));
+ return (FALSE);
+ }
+
+
+ /* Acquire place */
+ o_ptr = &o_list[o_idx];
+
+ /* Read the item */
+ do_item(o_ptr, ls_flag_t::LOAD);
+
+ /* Monster */
+ if (o_ptr->held_m_idx)
+ {
+ monster_type *m_ptr;
+
+ /* Monster */
+ m_ptr = &m_list[o_ptr->held_m_idx];
+
+ /* Build a stack */
+ o_ptr->next_o_idx = m_ptr->hold_o_idx;
+
+ /* Place the object */
+ m_ptr->hold_o_idx = o_idx;
+ }
+
+ /* Dungeon */
+ else
+ {
+ /* Access the item location */
+ c_ptr = &cave[o_ptr->iy][o_ptr->ix];
+
+ /* Build a stack */
+ o_ptr->next_o_idx = c_ptr->o_idx;
+
+ /* Place the object */
+ c_ptr->o_idx = o_idx;
+ }
+ }
+
+ /*** Monsters ***/
+
+ if (flag == ls_flag_t::SAVE)
+ {
+ tmp16b = m_max;
+
+ if (no_companions)
+ {
+ for (i = 1; i < m_max; i++)
+ {
+ monster_type *m_ptr = &m_list[i];
+
+ if (m_ptr->status == MSTATUS_COMPANION) tmp16b--;
+ }
+ }
+
+ /* Write the monster count */
+ do_u16b(&tmp16b, flag);
+
+ tmp16b = m_max;
+ }
+ else
+ /* Read the monster count */
+ do_u16b(&tmp16b, flag);
+
+ /* Validate */
+ if ((flag == ls_flag_t::LOAD) && (tmp16b > max_m_idx))
+ {
+ note(format("Too many (%d) monster entries!", tmp16b));
+ return (FALSE);
+ }
+
+ /* Read the monsters */
+ for (i = 1; i < tmp16b; i++)
+ {
+ int m_idx;
+ monster_type *m_ptr;
+ monster_race *r_ptr;
+
+ if (flag == ls_flag_t::SAVE)
+ {
+ m_ptr = &m_list[i];
+
+ /* Don't save companions when no_companions is set */
+ if (no_companions && m_ptr->status == MSTATUS_COMPANION) continue;
+
+ do_monster(m_ptr, ls_flag_t::SAVE);
+ continue; /* Easy to save a monster */
+ }
+ /* From here on, it's all ls_flag_t::LOAD */
+ /* Get a new record */
+ m_idx = m_pop();
+
+ /* Oops */
+ if (i != m_idx)
+ {
+ note(format("Monster allocation error (%d <> %d)", i, m_idx));
+ return (FALSE);
+ }
+
+ /* Acquire monster */
+ m_ptr = &m_list[m_idx];
+
+ /* Read the monster */
+ do_monster(m_ptr, ls_flag_t::LOAD);
+
+ /* Access grid */
+ c_ptr = &cave[m_ptr->fy][m_ptr->fx];
+
+ /* Mark the location */
+ c_ptr->m_idx = m_idx;
+
+ /* Controlled ? */
+ if (m_ptr->mflag & MFLAG_CONTROL)
+ p_ptr->control = m_idx;
+
+ /* Access race */
+ r_ptr = &r_info[m_ptr->r_idx];
+
+ /* Count XXX XXX XXX */
+ r_ptr->cur_num++;
+ }
+
+ /* Read the kept monsters */
+
+ tmp16b = (flag == ls_flag_t::SAVE && !no_companions) ? max_m_idx : 0;
+
+ /* Read the monster count */
+ do_u16b(&tmp16b, flag);
+
+ /* Hack -- verify */
+ if ((flag == ls_flag_t::LOAD) && (tmp16b > max_m_idx))
+ {
+ note(format("Too many (%d) monster entries!", tmp16b));
+ return (FALSE);
}
+ for (i = 1; i < tmp16b; i++)
+ {
+ monster_type *m_ptr;
+
+ /* Acquire monster */
+ m_ptr = &km_list[i];
+
+ /* Read the monster */
+ do_monster(m_ptr, flag);
+ }
+
+ /*** Success ***/
+
+ /* The dungeon is ready */
+ if (flag == ls_flag_t::LOAD) character_dungeon = TRUE;
+
+ /* Success */
+ return (TRUE);
+}
+
+/* Save the current persistent dungeon -SC- */
+void save_dungeon(void)
+{
+ char tmp[16];
+ char name[1024], buf[5];
+
+ /* Save only persistent dungeons */
+ if (!get_dungeon_save(buf) || (!dun_level)) return;
+
+ /* Construct filename */
+ sprintf(tmp, "%s.%s", player_base, buf);
+ path_build(name, 1024, ANGBAND_DIR_SAVE, tmp);
+
+ /* Open the file */
+ fff = my_fopen(name, "wb");
+
+ /* Save the dungeon */
+ do_dungeon(ls_flag_t::SAVE, TRUE);
+
+ my_fclose(fff);
}
+bool_ file_exist(cptr buf)
+{
+ int fd;
+ bool_ result;
+
+ /* Open savefile */
+ fd = fd_open(buf, O_RDONLY);
+ /* File exists */
+ if (fd >= 0)
+ {
+ fd_close(fd);
+ result = TRUE;
+ }
+ else
+ result = FALSE;
+ return result;
+}
/*
* Handle monster lore
*/
-static void do_lore(int r_idx, int flag)
+static void do_lore(int r_idx, ls_flag_t flag)
{
monster_race *r_ptr = &r_info[r_idx];
@@ -1643,7 +1888,7 @@ static void do_lore(int r_idx, int flag)
do_byte((byte*)&r_ptr->on_saved, flag);
- if (flag == LS_LOAD)
+ if (flag == ls_flag_t::LOAD)
{
/* Lore flag repair? */
r_ptr->r_flags1 &= r_ptr->flags1;
@@ -1661,7 +1906,7 @@ static void do_lore(int r_idx, int flag)
/*
* Read a store
*/
-static bool_ do_store(store_type *str, int flag)
+static bool_ do_store(store_type *str, ls_flag_t flag)
/* FIXME! Why does this return anything when
it always returns the same thing? */
{
@@ -1674,7 +1919,7 @@ static bool_ do_store(store_type *str, int flag)
/* Some basic info */
do_s32b(&str->store_open, flag);
do_u16b(&str->owner, flag);
- if (flag == LS_SAVE) num = str->stock_num;
+ if (flag == ls_flag_t::SAVE) num = str->stock_num;
/* Could be cleaner, done this way for benefit of the for loop later on */
do_byte(&num, flag);
@@ -1685,14 +1930,14 @@ static bool_ do_store(store_type *str, int flag)
/* Items */
for (j = 0; j < num; j++)
{
- if (flag == LS_LOAD)
+ if (flag == ls_flag_t::LOAD)
/* Can't this be cleaner? */
{
object_type forge;
/* Wipe the object */
object_wipe(&forge);
/* Read the item */
- do_item(&forge, LS_LOAD);
+ do_item(&forge, ls_flag_t::LOAD);
/* Acquire valid items */
if ((str->stock_num < store_inven_max) && (str->stock_num < str->stock_size))
{
@@ -1702,7 +1947,7 @@ static bool_ do_store(store_type *str, int flag)
object_copy(&str->stock[k], &forge);
}
}
- if (flag == LS_SAVE) do_item(&str->stock[j], flag);
+ if (flag == ls_flag_t::SAVE) do_item(&str->stock[j], flag);
}
/* Success */
@@ -1712,7 +1957,7 @@ static bool_ do_store(store_type *str, int flag)
/*
* RNG state
*/
-static void do_randomizer(int flag)
+static void do_randomizer(ls_flag_t flag)
{
int i;
@@ -1731,7 +1976,7 @@ static void do_randomizer(int flag)
}
/* Accept */
- if (flag == LS_LOAD)
+ if (flag == ls_flag_t::LOAD)
{
Rand_quick = FALSE;
}
@@ -1749,7 +1994,7 @@ static void do_randomizer(int flag)
* The window options are stored in the same way, but note that each
* window gets 32 options, and their order is fixed by certain defines.
*/
-static void do_options(int flag)
+static void do_options(ls_flag_t flag)
{
int i, n;
@@ -1765,10 +2010,10 @@ static void do_options(int flag)
do_byte(&hitpoint_warn, flag);
/*** Cheating options ***/
- if (flag == LS_LOAD) /* There *MUST* be some nice way to unify this! */
+ if (flag == ls_flag_t::LOAD) /* There *MUST* be some nice way to unify this! */
{
u16b c;
- do_u16b(&c, LS_LOAD);
+ do_u16b(&c, ls_flag_t::LOAD);
if (c & 0x0002) wizard = TRUE;
cheat_peek = (c & 0x0100) ? TRUE : FALSE;
cheat_hear = (c & 0x0200) ? TRUE : FALSE;
@@ -1777,7 +2022,7 @@ static void do_options(int flag)
cheat_know = (c & 0x1000) ? TRUE : FALSE;
cheat_live = (c & 0x2000) ? TRUE : FALSE;
}
- if (flag == LS_SAVE)
+ if (flag == ls_flag_t::SAVE)
{
u16b c = 0;
if (wizard) c |= 0x0002;
@@ -1787,14 +2032,14 @@ static void do_options(int flag)
if (cheat_xtra) c |= 0x0800;
if (cheat_know) c |= 0x1000;
if (cheat_live) c |= 0x2000;
- do_u16b(&c, LS_SAVE);
+ do_u16b(&c, ls_flag_t::SAVE);
}
do_byte((byte*)&autosave_l, flag);
do_byte((byte*)&autosave_t, flag);
do_s16b(&autosave_freq, flag);
- if (flag == LS_LOAD)
+ if (flag == ls_flag_t::LOAD)
{
/* Read the option flags */
for (n = 0; n < 8; n++) do_u32b(&oflag[n], flag);
@@ -1871,7 +2116,7 @@ static void do_options(int flag)
}
}
}
- if (flag == LS_SAVE)
+ if (flag == ls_flag_t::SAVE)
{
/* Analyze the options */
for (i = 0; option_info[i].o_desc; i++)
@@ -1918,33 +2163,15 @@ static void do_options(int flag)
}
-/* Load/Save the random spells info */
-static void do_spells(int i, int flag)
-{
- random_spell *s_ptr = &random_spells[i];
- do_string(s_ptr->name, 30, flag);
- do_string(s_ptr->desc, 30, flag);
- do_s16b(&s_ptr->mana, flag);
- do_s16b(&s_ptr->fail, flag);
- do_u32b(&s_ptr->proj_flags, flag);
- do_byte(&s_ptr->GF, flag);
- do_byte(&s_ptr->radius, flag);
- do_byte(&s_ptr->dam_sides, flag);
- do_byte(&s_ptr->dam_dice, flag);
- do_byte(&s_ptr->level, flag);
- do_byte((byte*)&s_ptr->untried, flag);
-}
-
-
/*
* Handle player inventory
*
* FIXME! This function probably could be unified better
* Note that the inventory is "re-sorted" later by "dungeon()".
*/
-static bool_ do_inventory(int flag)
+static bool_ do_inventory(ls_flag_t flag)
{
- if (flag == LS_LOAD)
+ if (flag == ls_flag_t::LOAD)
{
int slot = 0;
@@ -1961,7 +2188,7 @@ static bool_ do_inventory(int flag)
u16b n;
/* Get the next item index */
- do_u16b(&n, LS_LOAD);
+ do_u16b(&n, ls_flag_t::LOAD);
/* Nope, we reached the end */
if (n == 0xFFFF) break;
@@ -1973,7 +2200,7 @@ static bool_ do_inventory(int flag)
object_wipe(q_ptr);
/* Read the item */
- do_item(q_ptr, LS_LOAD);
+ do_item(q_ptr, ls_flag_t::LOAD);
/* Hack -- verify item */
if (!q_ptr->k_idx) return (FALSE);
@@ -2018,7 +2245,7 @@ static bool_ do_inventory(int flag)
}
}
}
- if (flag == LS_SAVE)
+ if (flag == ls_flag_t::SAVE)
{
u16b i;
u16b sent = 0xFFFF;
@@ -2029,7 +2256,7 @@ static bool_ do_inventory(int flag)
do_u16b(&i, flag);
do_item(o_ptr, flag);
}
- do_u16b(&sent, LS_SAVE); /* Sentinel */
+ do_u16b(&sent, ls_flag_t::SAVE); /* Sentinel */
}
/* Success */
return (TRUE);
@@ -2040,7 +2267,7 @@ static bool_ do_inventory(int flag)
/*
* Read the saved messages
*/
-static void do_messages(int flag) /* FIXME! We should be able to unify this better */
+static void do_messages(ls_flag_t flag) /* FIXME! We should be able to unify this better */
{
int i;
char buf[128];
@@ -2048,19 +2275,18 @@ static void do_messages(int flag) /* FIXME! We should be able to unify this be
s16b num;
- if (flag == LS_SAVE) num = message_num();
-
/* Total */
+ if (flag == ls_flag_t::SAVE) num = message_num();
do_s16b(&num, flag);
/* Read the messages */
- if (flag == LS_LOAD)
+ if (flag == ls_flag_t::LOAD)
{
byte tmp8u = 0;
for (i = 0; i < num; i++)
{
/* Read the message */
- do_string(buf, 128, LS_LOAD);
+ do_string(buf, 128, ls_flag_t::LOAD);
do_byte(&color, flag);
do_byte(&tmp8u, flag);
@@ -2068,13 +2294,13 @@ static void do_messages(int flag) /* FIXME! We should be able to unify this be
message_add(buf, color);
}
}
- if (flag == LS_SAVE)
+ if (flag == ls_flag_t::SAVE)
{
byte holder;
byte zero = 0;
for (i = num - 1; i >= 0; i--)
{
- do_string((char *)message_str((s16b)i), 0, LS_SAVE);
+ do_string((char *)message_str((s16b)i), 0, ls_flag_t::SAVE);
holder = message_color((s16b)i);
do_byte(&holder, flag);
do_byte(&zero, flag);
@@ -2082,300 +2308,6 @@ static void do_messages(int flag) /* FIXME! We should be able to unify this be
}
}
-/*
- * Handle dungeon
- *
- * The monsters/objects must be loaded in the same order
- * that they were stored, since the actual indexes matter.
- */
-static bool_ do_dungeon(int flag, bool_ no_companions)
-{
- int i;
-
- cave_type *c_ptr;
-
- /* Read specific */
- u16b tmp16b = 0;
-
- my_sentinel("Before do_dungeon", 324, flag);
-
- /* Header info */
- do_s16b(&dun_level, flag);
- do_byte(&dungeon_type, flag);
- do_s16b(&num_repro, flag);
- do_s16b(&p_ptr->py, flag);
- do_s16b(&p_ptr->px, flag);
- do_s16b(&cur_hgt, flag);
- do_s16b(&cur_wid, flag);
- do_s16b(&max_panel_rows, flag);
- do_s16b(&max_panel_cols, flag);
-
- do_u32b(&dungeon_flags1, flag);
- do_u32b(&dungeon_flags2, flag);
-
- /* Last teleportation */
- do_s16b(&last_teleportation_y, flag);
- do_s16b(&last_teleportation_y, flag);
-
- /* Spell effects */
- tmp16b = MAX_EFFECTS;
- do_u16b(&tmp16b, flag);
-
- if ((flag == LS_LOAD) && (tmp16b > MAX_EFFECTS))
- {
- quit("Too many spell effects");
- }
-
- for (i = 0; i < tmp16b; ++i)
- {
- do_s16b(&effects[i].type, flag);
- do_s16b(&effects[i].dam, flag);
- do_s16b(&effects[i].time, flag);
- do_u32b(&effects[i].flags, flag);
- do_s16b(&effects[i].cx, flag);
- do_s16b(&effects[i].cy, flag);
- do_s16b(&effects[i].rad, flag);
- }
-
- /* TO prevent bugs with evolving dungeons */
- for (i = 0; i < 100; i++)
- {
- do_s16b(&floor_type[i], flag);
- do_s16b(&fill_type[i], flag);
- }
-
- if ((flag == LS_LOAD) && (!dun_level && !p_ptr->inside_quest))
- {
- int xstart = 0;
- int ystart = 0;
- /* Init the wilderness */
- process_dungeon_file("w_info.txt", &ystart, &xstart, cur_hgt, cur_wid,
- TRUE, FALSE);
-
- /* Init the town */
- xstart = 0;
- ystart = 0;
- init_flags = 0;
- process_dungeon_file("t_info.txt", &ystart, &xstart, cur_hgt, cur_wid,
- TRUE, FALSE);
- }
-
- do_grid(flag);
-
- /*** Objects ***/
-
- if (flag == LS_SAVE) compact_objects(0);
- if (flag == LS_SAVE) compact_monsters(0);
- if (flag == LS_SAVE)
- {
- tmp16b = o_max;
-
- if (no_companions)
- {
- for (i = 1; i < o_max; i++)
- {
- object_type *o_ptr = &o_list[i];
-
- if (o_ptr->held_m_idx && (m_list[o_ptr->held_m_idx].status == MSTATUS_COMPANION)) tmp16b--;
- }
- }
-
- /* Item count */
- do_u16b(&tmp16b, flag);
-
- tmp16b = o_max;
- }
- else
- /* Read item count */
- do_u16b(&tmp16b, flag);
-
- /* Verify maximum */
- if ((flag == LS_LOAD) && (tmp16b > max_o_idx))
- {
- note(format("Too many (%d) object entries!", tmp16b));
- return (FALSE);
- }
-
- /* Dungeon items */
- for (i = 1; i < tmp16b; i++)
- {
- int o_idx;
-
- object_type *o_ptr;
-
- if (flag == LS_SAVE)
- {
- o_ptr = &o_list[i];
- /* Don't save objects held by companions when no_companions is set */
- if (no_companions && o_ptr->held_m_idx && (m_list[o_ptr->held_m_idx].status == MSTATUS_COMPANION)) continue;
-
- do_item(o_ptr, LS_SAVE);
- continue; /* Saving is easy */
- }
- /* Until the end of the loop, this is all LS_LOAD */
-
- /* Get a new record */
- o_idx = o_pop();
-
- /* Oops */
- if (i != o_idx)
- {
- note(format("Object allocation error (%d <> %d)", i, o_idx));
- return (FALSE);
- }
-
-
- /* Acquire place */
- o_ptr = &o_list[o_idx];
-
- /* Read the item */
- do_item(o_ptr, LS_LOAD);
-
- /* Monster */
- if (o_ptr->held_m_idx)
- {
- monster_type *m_ptr;
-
- /* Monster */
- m_ptr = &m_list[o_ptr->held_m_idx];
-
- /* Build a stack */
- o_ptr->next_o_idx = m_ptr->hold_o_idx;
-
- /* Place the object */
- m_ptr->hold_o_idx = o_idx;
- }
-
- /* Dungeon */
- else
- {
- /* Access the item location */
- c_ptr = &cave[o_ptr->iy][o_ptr->ix];
-
- /* Build a stack */
- o_ptr->next_o_idx = c_ptr->o_idx;
-
- /* Place the object */
- c_ptr->o_idx = o_idx;
- }
- }
-
- /*** Monsters ***/
-
- if (flag == LS_SAVE)
- {
- tmp16b = m_max;
-
- if (no_companions)
- {
- for (i = 1; i < m_max; i++)
- {
- monster_type *m_ptr = &m_list[i];
-
- if (m_ptr->status == MSTATUS_COMPANION) tmp16b--;
- }
- }
-
- /* Write the monster count */
- do_u16b(&tmp16b, flag);
-
- tmp16b = m_max;
- }
- else
- /* Read the monster count */
- do_u16b(&tmp16b, flag);
-
- /* Validate */
- if ((flag == LS_LOAD) && (tmp16b > max_m_idx))
- {
- note(format("Too many (%d) monster entries!", tmp16b));
- return (FALSE);
- }
-
- /* Read the monsters */
- for (i = 1; i < tmp16b; i++)
- {
- int m_idx;
- monster_type *m_ptr;
- monster_race *r_ptr;
-
- if (flag == LS_SAVE)
- {
- m_ptr = &m_list[i];
-
- /* Don't save companions when no_companions is set */
- if (no_companions && m_ptr->status == MSTATUS_COMPANION) continue;
-
- do_monster(m_ptr, LS_SAVE);
- continue; /* Easy to save a monster */
- }
- /* From here on, it's all LS_LOAD */
- /* Get a new record */
- m_idx = m_pop();
-
- /* Oops */
- if (i != m_idx)
- {
- note(format("Monster allocation error (%d <> %d)", i, m_idx));
- return (FALSE);
- }
-
- /* Acquire monster */
- m_ptr = &m_list[m_idx];
-
- /* Read the monster */
- do_monster(m_ptr, LS_LOAD);
-
- /* Access grid */
- c_ptr = &cave[m_ptr->fy][m_ptr->fx];
-
- /* Mark the location */
- c_ptr->m_idx = m_idx;
-
- /* Controlled ? */
- if (m_ptr->mflag & MFLAG_CONTROL)
- p_ptr->control = m_idx;
-
- /* Access race */
- r_ptr = &r_info[m_ptr->r_idx];
-
- /* Count XXX XXX XXX */
- r_ptr->cur_num++;
- }
-
- /* Read the kept monsters */
-
- tmp16b = (flag == LS_SAVE && !no_companions) ? max_m_idx : 0;
-
- /* Read the monster count */
- do_u16b(&tmp16b, flag);
-
- /* Hack -- verify */
- if ((flag == LS_LOAD) && (tmp16b > max_m_idx))
- {
- note(format("Too many (%d) monster entries!", tmp16b));
- return (FALSE);
- }
- for (i = 1; i < tmp16b; i++)
- {
- monster_type *m_ptr;
-
- /* Acquire monster */
- m_ptr = &km_list[i];
-
- /* Read the monster */
- do_monster(m_ptr, flag);
- }
-
- /*** Success ***/
-
- /* The dungeon is ready */
- if (flag == LS_LOAD) character_dungeon = TRUE;
-
- /* Success */
- return (TRUE);
-}
-
/* Returns TRUE if we successfully load the dungeon */
bool_ load_dungeon(char *ext)
{
@@ -2401,7 +2333,7 @@ bool_ load_dungeon(char *ext)
}
/* Read the dungeon */
- if (!do_dungeon(LS_LOAD, FALSE))
+ if (!do_dungeon(ls_flag_t::LOAD, FALSE))
{
dun_level = old_dun;
dungeon_type = old_dungeon_type;
@@ -2418,26 +2350,9 @@ bool_ load_dungeon(char *ext)
return (TRUE);
}
-void do_blocks(int flag)
-/* Handle blocked-allocation stuff for quests and lua stuff
- This depends on a dyn_tosave array of s32b's. Adjust as needed
- if other data structures are desirable. This also is not hooked
- in yet. Ideally, plug it near the end of the savefile.
- */
-{
- s16b numblks, n_iter = 0; /* How many blocks do we have? */
- do_s16b(&numblks, flag);
- while (n_iter < numblks)
- {
- /* do_s32b(dyn_tosave[n_iter], flag); */
- n_iter++;
- }
- my_sentinel("In blocked-allocation area", 37, flag);
-}
-
-void do_fate(int i, int flag)
+void do_fate(int i, ls_flag_t flag)
{
- if ((flag == LS_LOAD) && (i >= MAX_FATES)) i = MAX_FATES - 1;
+ if ((flag == ls_flag_t::LOAD) && (i >= MAX_FATES)) i = MAX_FATES - 1;
do_byte(&fates[i].fate, flag);
do_byte(&fates[i].level, flag);
@@ -2455,7 +2370,7 @@ void do_fate(int i, int flag)
/*
* Load/save timers.
*/
-static void do_timers(int flag)
+static void do_timers(ls_flag_t flag)
{
timer_type *t_ptr;
@@ -2470,7 +2385,7 @@ static void do_timers(int flag)
/*
* Load/save stores.
*/
-static void do_stores(int flag)
+static void do_stores(ls_flag_t flag)
{
u16b tmp16u;
u16b real_max = 0;
@@ -2479,7 +2394,7 @@ static void do_stores(int flag)
std::unique_ptr<byte[]> reals(new byte[max_towns]);
/* Find the real towns */
- if (flag == LS_SAVE)
+ if (flag == ls_flag_t::SAVE)
{
for (int i = 1; i < max_towns; i++)
{
@@ -2494,7 +2409,7 @@ static void do_stores(int flag)
}
/* Read the stores */
- if (flag == LS_SAVE) tmp16u = max_st_idx;
+ if (flag == ls_flag_t::SAVE) tmp16u = max_st_idx;
do_u16b(&tmp16u, flag);
assert(tmp16u <= max_st_idx);
@@ -2513,11 +2428,40 @@ static void do_stores(int flag)
}
}
+/*
+ * Note that this function may not be needed at all.
+ * It was taken out of load_player_aux(). Do we need it?
+ */
+static void junkinit(void)
+{
+ int i, j;
+ p_ptr->inside_quest = 0;
+ p_ptr->town_num = 1;
+ p_ptr->wilderness_x = 4;
+ p_ptr->wilderness_y = 4;
+ for (i = 0; i < max_wild_x; i++)
+ {
+ for (j = 0; j < max_wild_y; j++)
+ {
+ wild_map[j][i].seed = rand_int(0x10000000);
+ }
+ }
+}
+
+static void morejunk(void)
+{
+ sp_ptr = &sex_info[p_ptr->psex]; /* Sex */
+ rp_ptr = &race_info[p_ptr->prace]; /* Raceclass */
+ rmp_ptr = &race_mod_info[p_ptr->pracem];
+ cp_ptr = &class_info[p_ptr->pclass];
+ spp_ptr = &class_info[p_ptr->pclass].spec[p_ptr->pspec];
+}
+
/*
* Actually read the savefile
*/
-static bool_ do_savefile_aux(int flag)
+static bool_ do_savefile_aux(ls_flag_t flag)
{
int i, j;
@@ -2525,7 +2469,7 @@ static bool_ do_savefile_aux(int flag)
u16b tmp16u;
/* Mention the savefile version */
- if (flag == LS_LOAD)
+ if (flag == ls_flag_t::LOAD)
{
if (vernum < 100)
{
@@ -2537,14 +2481,14 @@ static bool_ do_savefile_aux(int flag)
note(format("Loading version %lu savefile... ", vernum));
}
}
- if (flag == LS_SAVE)
+ if (flag == ls_flag_t::SAVE)
{
sf_when = time((time_t *) 0); /* Note when file was saved */
sf_saves++; /* Increment the saves ctr */
}
/* Handle version bytes. FIXME! DG wants me to change this all around */
- if (flag == LS_LOAD)
+ if (flag == ls_flag_t::LOAD)
{
u32b mt32b;
byte mtbyte;
@@ -2553,7 +2497,7 @@ static bool_ do_savefile_aux(int flag)
do_u32b(&mt32b, flag);
do_byte(&mtbyte, flag);
}
- if (flag == LS_SAVE)
+ if (flag == ls_flag_t::SAVE)
{
u32b saver;
saver = SAVEFILE_VERSION;
@@ -2578,7 +2522,7 @@ static bool_ do_savefile_aux(int flag)
do_u16b(&sf_saves, flag);
/* Game module */
- if (flag == LS_SAVE)
+ if (flag == ls_flag_t::SAVE)
strcpy(loaded_game_module, game_module);
do_string(loaded_game_module, 80, flag);
@@ -2598,11 +2542,11 @@ static bool_ do_savefile_aux(int flag)
do_messages(flag);
/* Monster Memory */
- if (flag == LS_SAVE) tmp16u = max_r_idx;
+ if (flag == ls_flag_t::SAVE) tmp16u = max_r_idx;
do_u16b(&tmp16u, flag);
/* Incompatible save files */
- if ((flag == LS_LOAD) && (tmp16u > max_r_idx))
+ if ((flag == ls_flag_t::LOAD) && (tmp16u > max_r_idx))
{
note(format("Too many (%u) monster races!", tmp16u));
return (FALSE);
@@ -2616,11 +2560,11 @@ static bool_ do_savefile_aux(int flag)
}
/* Object Memory */
- if (flag == LS_SAVE) tmp16u = max_k_idx;
+ if (flag == ls_flag_t::SAVE) tmp16u = max_k_idx;
do_u16b(&tmp16u, flag);
/* Incompatible save files */
- if ((flag == LS_LOAD) && (tmp16u > max_k_idx))
+ if ((flag == ls_flag_t::LOAD) && (tmp16u > max_k_idx))
{
note(format("Too many (%u) object kinds!", tmp16u));
return (FALSE);
@@ -2628,25 +2572,25 @@ static bool_ do_savefile_aux(int flag)
/* Read the object memory */
for (i = 0; i < tmp16u; i++) do_xtra(i, flag);
- if (flag == LS_LOAD) junkinit();
+ if (flag == ls_flag_t::LOAD) junkinit();
{
u16b max_towns_ldsv;
u16b max_quests_ldsv;
- if (flag == LS_SAVE) max_towns_ldsv = max_towns;
+ if (flag == ls_flag_t::SAVE) max_towns_ldsv = max_towns;
/* Number of towns */
do_u16b(&max_towns_ldsv, flag);
/* Incompatible save files */
- if ((flag == LS_LOAD) && (max_towns_ldsv > max_towns))
+ if ((flag == ls_flag_t::LOAD) && (max_towns_ldsv > max_towns))
{
note(format("Too many (%u) towns!", max_towns_ldsv));
return (FALSE);
}
/* Min of random towns */
- if (flag == LS_SAVE) max_towns_ldsv = TOWN_RANDOM;
+ if (flag == ls_flag_t::SAVE) max_towns_ldsv = TOWN_RANDOM;
do_u16b(&max_towns_ldsv, flag);
/* Incompatible save files */
- if ((flag == LS_LOAD) && (max_towns_ldsv != TOWN_RANDOM))
+ if ((flag == ls_flag_t::LOAD) && (max_towns_ldsv != TOWN_RANDOM))
{
note(format("Different random towns base (%u)!", max_towns_ldsv));
return (FALSE);
@@ -2663,7 +2607,7 @@ static bool_ do_savefile_aux(int flag)
do_byte(&town_info[i].flags, flag);
/* If the town is realy used create a sock */
- if ((town_info[i].flags & (TOWN_REAL)) && (flag == LS_LOAD))
+ if ((town_info[i].flags & (TOWN_REAL)) && (flag == ls_flag_t::LOAD))
{
create_stores_stock(i);
}
@@ -2671,21 +2615,21 @@ static bool_ do_savefile_aux(int flag)
}
/* Number of dungeon */
- if (flag == LS_SAVE) max_towns_ldsv = max_d_idx;
+ if (flag == ls_flag_t::SAVE) max_towns_ldsv = max_d_idx;
do_u16b(&max_towns_ldsv, flag);
/* Incompatible save files */
- if ((flag == LS_LOAD) && (max_towns_ldsv > max_d_idx))
+ if ((flag == ls_flag_t::LOAD) && (max_towns_ldsv > max_d_idx))
{
note(format("Too many dungeon types (%u)!", max_towns_ldsv));
return (FALSE);
}
/* Number of towns per dungeon */
- if (flag == LS_SAVE) max_quests_ldsv = TOWN_DUNGEON;
+ if (flag == ls_flag_t::SAVE) max_quests_ldsv = TOWN_DUNGEON;
do_u16b(&max_quests_ldsv, flag);
/* Incompatible save files */
- if ((flag == LS_LOAD) && (max_quests_ldsv > TOWN_DUNGEON))
+ if ((flag == ls_flag_t::LOAD) && (max_quests_ldsv > TOWN_DUNGEON))
{
note(format("Too many town per dungeons (%u)!", max_quests_ldsv));
return (FALSE);
@@ -2702,11 +2646,11 @@ static bool_ do_savefile_aux(int flag)
}
/* Sanity check number of quests */
- if (flag == LS_SAVE) max_quests_ldsv = MAX_Q_IDX;
+ if (flag == ls_flag_t::SAVE) max_quests_ldsv = MAX_Q_IDX;
do_u16b(&max_quests_ldsv, flag);
/* Incompatible save files */
- if ((flag == LS_LOAD) && (max_quests_ldsv != MAX_Q_IDX))
+ if ((flag == ls_flag_t::LOAD) && (max_quests_ldsv != MAX_Q_IDX))
{
note(format("Invalid number of quests (%u)!", max_quests_ldsv));
return (FALSE);
@@ -2721,7 +2665,7 @@ static bool_ do_savefile_aux(int flag)
}
/* Init the hooks */
- if ((flag == LS_LOAD) && (quest[i].init != NULL))
+ if ((flag == ls_flag_t::LOAD) && (quest[i].init != NULL))
{
quest[i].init(i);
}
@@ -2735,7 +2679,7 @@ static bool_ do_savefile_aux(int flag)
{
s32b wild_x_size, wild_y_size;
- if (flag == LS_SAVE)
+ if (flag == ls_flag_t::SAVE)
{
wild_x_size = max_wild_x;
wild_y_size = max_wild_y;
@@ -2744,11 +2688,11 @@ static bool_ do_savefile_aux(int flag)
do_s32b(&wild_x_size, flag);
do_s32b(&wild_y_size, flag);
/* Incompatible save files */
- if ((flag == LS_LOAD) &&
- ((wild_x_size > max_wild_x) || (wild_y_size > max_wild_y)))
+ if ((flag == ls_flag_t::LOAD) &&
+ ((wild_x_size > max_wild_x) || (wild_y_size > max_wild_y)))
{
note(format("Wilderness is too big (%u/%u)!",
- wild_x_size, wild_y_size));
+ wild_x_size, wild_y_size));
return (FALSE);
}
/* Wilderness seeds */
@@ -2765,9 +2709,9 @@ static bool_ do_savefile_aux(int flag)
}
/* Load the random artifacts. */
- if (flag == LS_SAVE) tmp16u = MAX_RANDARTS;
+ if (flag == ls_flag_t::SAVE) tmp16u = MAX_RANDARTS;
do_u16b(&tmp16u, flag);
- if ((flag == LS_LOAD) && (tmp16u > MAX_RANDARTS))
+ if ((flag == ls_flag_t::LOAD) && (tmp16u > MAX_RANDARTS))
{
note(format("Too many (%u) random artifacts!", tmp16u));
return (FALSE);
@@ -2786,10 +2730,10 @@ static bool_ do_savefile_aux(int flag)
}
/* Load the Artifacts */
- if (flag == LS_SAVE) tmp16u = max_a_idx;
+ if (flag == ls_flag_t::SAVE) tmp16u = max_a_idx;
do_u16b(&tmp16u, flag);
/* Incompatible save files */
- if ((flag == LS_LOAD) && (tmp16u > max_a_idx))
+ if ((flag == ls_flag_t::LOAD) && (tmp16u > max_a_idx))
{
note(format("Too many (%u) artifacts!", tmp16u));
return (FALSE);
@@ -2802,11 +2746,11 @@ static bool_ do_savefile_aux(int flag)
}
/* Fates */
- if (flag == LS_SAVE) tmp16u = MAX_FATES;
+ if (flag == ls_flag_t::SAVE) tmp16u = MAX_FATES;
do_u16b(&tmp16u, flag);
/* Incompatible save files */
- if ((flag == LS_LOAD) && (tmp16u > MAX_FATES))
+ if ((flag == ls_flag_t::LOAD) && (tmp16u > MAX_FATES))
{
note(format("Too many (%u) fates!", tmp16u));
return (FALSE);
@@ -2819,11 +2763,11 @@ static bool_ do_savefile_aux(int flag)
}
/* Load the Traps */
- if (flag == LS_SAVE) tmp16u = max_t_idx;
+ if (flag == ls_flag_t::SAVE) tmp16u = max_t_idx;
do_u16b(&tmp16u, flag);
/* Incompatible save files */
- if ((flag == LS_LOAD) && (tmp16u > max_t_idx))
+ if ((flag == ls_flag_t::LOAD) && (tmp16u > max_t_idx))
{
note(format("Too many (%u) traps!", tmp16u));
return (FALSE);
@@ -2836,11 +2780,11 @@ static bool_ do_savefile_aux(int flag)
}
/* inscription knowledge */
- if (flag == LS_SAVE) tmp16u = MAX_INSCRIPTIONS;
+ if (flag == ls_flag_t::SAVE) tmp16u = MAX_INSCRIPTIONS;
do_u16b(&tmp16u, flag);
/* Incompatible save files */
- if ((flag == LS_LOAD) && (tmp16u > MAX_INSCRIPTIONS))
+ if ((flag == ls_flag_t::LOAD) && (tmp16u > MAX_INSCRIPTIONS))
{
note(format("Too many (%u) inscriptions!", tmp16u));
return (FALSE);
@@ -2857,10 +2801,10 @@ static bool_ do_savefile_aux(int flag)
/* player_hp array */
- if (flag == LS_SAVE) tmp16u = PY_MAX_LEVEL;
+ if (flag == ls_flag_t::SAVE) tmp16u = PY_MAX_LEVEL;
do_u16b(&tmp16u, flag);
/* Incompatible save files */
- if ((flag == LS_LOAD) && (tmp16u > PY_MAX_LEVEL))
+ if ((flag == ls_flag_t::LOAD) && (tmp16u > PY_MAX_LEVEL))
{
note(format("Too many (%u) hitpoint entries!", tmp16u));
return (FALSE);
@@ -2872,7 +2816,7 @@ static bool_ do_savefile_aux(int flag)
do_s16b(&player_hp[i], flag);
}
- if (flag == LS_LOAD) morejunk();
+ if (flag == ls_flag_t::LOAD) morejunk();
/* Read the pet command settings */
do_byte(&p_ptr->pet_follow_distance, flag);
@@ -2883,7 +2827,7 @@ static bool_ do_savefile_aux(int flag)
do_s16b(&p_ptr->dripping_tread, flag);
/* Read the inventory */
- if (!do_inventory(flag) && (flag == LS_LOAD)) /* do NOT reverse this ordering */
+ if (!do_inventory(flag) && (flag == ls_flag_t::LOAD)) /* do NOT reverse this ordering */
{
note("Unable to read inventory");
return (FALSE);
@@ -2896,20 +2840,20 @@ static bool_ do_savefile_aux(int flag)
if (!death)
{
/* Dead players have no dungeon */
- if (flag == LS_LOAD) note("Restoring Dungeon...");
- if ((flag == LS_LOAD) && (!do_dungeon(LS_LOAD, FALSE)))
+ if (flag == ls_flag_t::LOAD) note("Restoring Dungeon...");
+ if ((flag == ls_flag_t::LOAD) && (!do_dungeon(ls_flag_t::LOAD, FALSE)))
{
note("Error reading dungeon data");
return (FALSE);
}
- if (flag == LS_SAVE) do_dungeon(LS_SAVE, FALSE);
+ if (flag == ls_flag_t::SAVE) do_dungeon(ls_flag_t::SAVE, FALSE);
my_sentinel("Before ghost data", 435, flag);
my_sentinel("After ghost data", 320, flag);
}
{
byte foo = 0;
- if (flag == LS_SAVE)
+ if (flag == ls_flag_t::SAVE)
{
/*
* Safety Padding. It's there
@@ -2919,7 +2863,7 @@ static bool_ do_savefile_aux(int flag)
* read it. Insert any new stuff before
* this position.
*/
- do_byte(&foo, LS_SAVE);
+ do_byte(&foo, ls_flag_t::SAVE);
}
}
@@ -2928,21 +2872,22 @@ static bool_ do_savefile_aux(int flag)
}
+
/*
* Actually read the savefile
*/
-errr rd_savefile(void)
+static errr rd_savefile(void)
{
errr err = 0;
/* The savefile is a binary file */
fff = my_fopen(savefile, "rb");
-
+
/* Paranoia */
if (!fff) return ( -1);
/* Call the sub-function */
- err = !do_savefile_aux(LS_LOAD);
+ err = !do_savefile_aux(ls_flag_t::LOAD);
/* Check for errors */
if (ferror(fff)) err = -1;
@@ -2954,252 +2899,269 @@ errr rd_savefile(void)
return (err);
}
+
/*
- * Note that this function may not be needed at all.
- * It was taken out of load_player_aux(). Do we need it?
+ * Attempt to Load a "savefile"
+ *
+ * On multi-user systems, you may only "read" a savefile if you will be
+ * allowed to "write" it later, this prevents painful situations in which
+ * the player loads a savefile belonging to someone else, and then is not
+ * allowed to save his game when he quits.
+ *
+ * We return "TRUE" if the savefile was usable, and we set the global
+ * flag "character_loaded" if a real, living, character was loaded.
+ *
+ * Note that we always try to load the "current" savefile, even if
+ * there is no such file, so we must check for "empty" savefile names.
*/
-static void junkinit(void)
+bool_ load_player(void)
{
- int i, j;
- p_ptr->inside_quest = 0;
- p_ptr->town_num = 1;
- p_ptr->wilderness_x = 4;
- p_ptr->wilderness_y = 4;
- for (i = 0; i < max_wild_x; i++)
+ int fd = -1;
+
+ errr err = 0;
+
+ cptr what = "generic";
+
+ /* Paranoia */
+ turn = 0;
+
+ /* Paranoia */
+ death = FALSE;
+
+
+ /* Allow empty savefile name */
+ if (!savefile[0]) return (TRUE);
+
+
+ /* XXX XXX XXX Fix this */
+
+ /* Verify the existance of the savefile */
+ if (!file_exist(savefile))
{
- for (j = 0; j < max_wild_y; j++)
- {
- wild_map[j][i].seed = rand_int(0x10000000);
- }
+ /* Give a message */
+ msg_format("Savefile does not exist: %s", savefile);
+ msg_print(NULL);
+
+ /* Allow this */
+ return (TRUE);
}
-}
-static void morejunk(void)
-{
- sp_ptr = &sex_info[p_ptr->psex]; /* Sex */
- rp_ptr = &race_info[p_ptr->prace]; /* Raceclass */
- rmp_ptr = &race_mod_info[p_ptr->pracem];
- cp_ptr = &class_info[p_ptr->pclass];
- spp_ptr = &class_info[p_ptr->pclass].spec[p_ptr->pspec];
-}
+ /* Okay */
+ if (!err)
+ {
+ /* Open the savefile */
+ fd = fd_open(savefile, O_RDONLY);
-static void do_grid(int flag)
-/* Does the grid, RLE, blahblah. RLE sucks. I hate it. */
-{
- int i = 0, y = 0, x = 0;
- byte count = 0;
- byte tmp8u = 0;
- s16b tmp16s = 0;
- cave_type *c_ptr;
- byte prev_char = 0;
- s16b prev_s16b = 0;
- int ymax = cur_hgt, xmax = cur_wid;
+ /* No file */
+ if (fd < 0) err = -1;
- int part; /* Which section of the grid we're on */
+ /* Message (below) */
+ if (err) what = "Cannot open savefile";
+ }
- for (part = 0; part < 9; part++) /* There are 8 fields to the grid, each stored
- in a seperate RLE data structure */
+ /* Process file */
+ if (!err)
{
- if (flag == LS_SAVE)
- {
- count = 0;
- prev_s16b = 0;
- prev_char = 0; /* Clear, prepare for RLE */
- for (y = 0; y < cur_hgt; y++)
- {
- for (x = 0; x < cur_wid; x++)
- {
- c_ptr = &cave[y][x];
- switch (part)
- {
- case 0:
- tmp16s = c_ptr->info;
- break;
+ byte tmp8u = 0;
- case 1:
- tmp8u = c_ptr->feat;
- break;
+ /* Open the file XXX XXX XXX XXX Should use Angband file interface */
+ fff = my_fopen(savefile, "rb");
+/* fff = fdopen(fd, "r"); */
- case 2:
- tmp8u = c_ptr->mimic;
- break;
+ /* Read the first four bytes */
+ do_u32b(&vernum, ls_flag_t::LOAD);
+ do_byte(&tmp8u, ls_flag_t::LOAD); // For comatibility with old savefiles
- case 3:
- tmp16s = c_ptr->special;
- break;
+ /* XXX XXX XXX XXX Should use Angband file interface */
+ my_fclose(fff);
+ /* fclose(fff) */
- case 4:
- tmp16s = c_ptr->special2;
- break;
+ /* Close the file */
+ fd_close(fd);
+ }
- case 5:
- tmp16s = c_ptr->t_idx;
- break;
+ /* Process file */
+ if (!err)
+ {
- case 6:
- tmp16s = c_ptr->inscription;
- break;
+ /* Extract version */
+ sf_major = VERSION_MAJOR;
+ sf_minor = VERSION_MINOR;
+ sf_patch = VERSION_PATCH;
- case 7:
- tmp8u = c_ptr->mana;
- break;
+ /* Clear screen */
+ Term_clear();
- case 8:
- tmp16s = c_ptr->effect;
- break;
- }
- /* Flush a full run */
- if ((((part != 1) && (part != 2) && (part != 7)) &&
- (tmp16s != prev_s16b)) || (((part == 1) || (part == 2)
- || (part == 7)) &&
- (tmp8u != prev_char)) ||
- (count == MAX_UCHAR))
- {
- do_byte(&count, LS_SAVE);
- switch (part)
- {
- case 0:
- case 3:
- case 4:
- case 5:
- case 6:
- case 8:
- do_s16b(&prev_s16b, LS_SAVE);
- prev_s16b = tmp16s;
- break;
+ /* Attempt to load */
+ err = rd_savefile();
- case 1:
- case 2:
- case 7:
- do_byte(&prev_char, LS_SAVE);
- prev_char = tmp8u;
- break;
- }
- count = 1; /* Reset RLE */
- }
- else
- count++; /* Otherwise, keep going */
- }
- }
- /* Fallen off the end of the world, flush anything left */
- if (count)
+ /* Message (below) */
+ if (err) what = "Cannot parse savefile";
+ }
+
+ /* Paranoia */
+ if (!err)
+ {
+ /* Invalid turn */
+ if (!turn) err = -1;
+
+ /* Message (below) */
+ if (err) what = "Broken savefile";
+ }
+
+
+ /* Okay */
+ if (!err)
+ {
+ /* Player is dead */
+ if (death)
+ {
+ /* Player is no longer "dead" */
+ death = FALSE;
+
+ /* Cheat death (unless the character retired) */
+ if (arg_wizard && !total_winner)
{
- do_byte(&count, LS_SAVE);
- switch (part)
- {
- case 0:
- case 3:
- case 4:
- case 5:
- case 6:
- case 8:
- do_s16b(&prev_s16b, LS_SAVE);
- break;
+ /* A character was loaded */
+ character_loaded = TRUE;
- case 1:
- case 2:
- case 7:
- do_byte(&prev_char, LS_SAVE);
- break;
- }
+ /* Done */
+ return (TRUE);
}
+
+ /* Count lives */
+ sf_lives++;
+
+ /* Forget turns */
+ turn = old_turn = 0;
+
+ /* Done */
+ return (TRUE);
}
- if (flag == LS_LOAD)
+
+ /* A character was loaded */
+ character_loaded = TRUE;
+
+ /* Still alive */
+ if (p_ptr->chp >= 0)
{
- x = 0;
- for (y = 0; y < ymax; )
- {
- do_byte(&count, LS_LOAD);
- switch (part)
- {
- case 0:
- case 3:
- case 4:
- case 5:
- case 6:
- case 8:
- do_s16b(&tmp16s, LS_LOAD);
- break;
+ /* Reset cause of death */
+ (void)strcpy(died_from, "(alive and well)");
+ }
- case 1:
- case 2:
- case 7:
- do_byte(&tmp8u, LS_LOAD);
- break;
- }
- for (i = count; i > 0; i--) /* RLE */
- {
- c_ptr = &cave[y][x];
- switch (part)
- {
- case 0:
- c_ptr->info = tmp16s;
- break;
+ /* Success */
+ return (TRUE);
+ }
- case 1:
- c_ptr->feat = tmp8u;
- break;
- case 2:
- c_ptr->mimic = tmp8u;
- break;
+ /* Message */
+ msg_format("Error (%s) reading %d.%d.%d savefile.",
+ what, sf_major, sf_minor, sf_patch);
+ msg_print(NULL);
- case 3:
- c_ptr->special = tmp16s;
- break;
+ /* Oops */
+ return (FALSE);
+}
- case 4:
- c_ptr->special2 = tmp16s;
- break;
- case 5:
- c_ptr->t_idx = tmp16s;
- break;
- case 6:
- c_ptr->inscription = tmp16s;
- break;
+/*
+ * Medium level player saver
+ */
+static bool_ save_player_aux(char *name)
+{
+ bool_ ok = FALSE;
+ int fd = -1;
+ int mode = 0644;
- case 7:
- c_ptr->mana = tmp8u;
- break;
+ /* No file yet */
+ fff = NULL;
- case 8:
- c_ptr->effect = tmp16s;
- break;
- }
- if (++x >= xmax)
- {
- /* Wrap */
- x = 0;
- if ((++y) >= ymax) break;
- }
- }
- }
+ /* File type is "SAVE" */
+ FILE_TYPE(FILE_TYPE_SAVE);
+
+ /* Create the savefile */
+ fd = fd_make(name, mode);
+
+ /* File is okay */
+ if (fd >= 0)
+ {
+ /* Close the "fd" */
+ (void)fd_close(fd);
+
+ /* Open the savefile */
+ fff = my_fopen(name, "wb");
+
+ /* Successful open */
+ if (fff)
+ {
+ /* Write the savefile */
+ if (do_savefile_aux(ls_flag_t::SAVE)) ok = TRUE;
+
+ /* Attempt to close it */
+ if (my_fclose(fff)) ok = FALSE;
+ }
+
+ /* "broken" savefile */
+ if (!ok)
+ {
+ /* Remove "broken" files */
+ (void)fd_kill(name);
}
}
+
+ /* Failure */
+ if (!ok) return (FALSE);
+
+ /* Success */
+ return (TRUE);
}
-static void my_sentinel(const char *place, u16b value, int flag)
-/* This function lets us know exactly where a savefile is
- broken by reading/writing conveniently a sentinel at this
- spot */
+/*
+ * Attempt to save the player in a savefile
+ */
+bool_ save_player(void)
{
- if (flag == LS_SAVE)
- {
- do_u16b(&value, flag);
- return;
- }
- if (flag == LS_LOAD)
+ int result = FALSE;
+ char safe[1024];
+
+ /* New savefile */
+ strcpy(safe, savefile);
+ strcat(safe, ".new");
+
+ /* Remove it */
+ fd_kill(safe);
+
+ /* Attempt to save the player */
+ if (save_player_aux(safe))
{
- u16b found;
- do_u16b(&found, flag);
- if (found == value) /* All is good */
- return;
- /* All is bad */
- note(format("Savefile broken %s", place));
- return;
+ char temp[1024];
+
+ /* Old savefile */
+ strcpy(temp, savefile);
+ strcat(temp, ".old");
+
+ /* Remove it */
+ fd_kill(temp);
+
+ /* Preserve old savefile */
+ fd_move(savefile, temp);
+
+ /* Activate new savefile */
+ fd_move(safe, savefile);
+
+ /* Remove preserved savefile */
+ fd_kill(temp);
+
+ /* Hack -- Pretend the character was loaded */
+ character_loaded = TRUE;
+
+ /* Success */
+ result = TRUE;
}
- note(format("Impossible has occurred")); /* Programmer error */
- exit(0);
+
+ save_savefile_names();
+
+ /* Return the result */
+ return (result);
}