diff options
author | Bardur Arantsson <bardur@scientician.net> | 2015-03-07 18:36:59 +0100 |
---|---|---|
committer | Bardur Arantsson <bardur@scientician.net> | 2015-03-07 19:42:45 +0100 |
commit | fb2a78c52a32026a57fd9cc7763a783456199dd7 (patch) | |
tree | 52a67b2ba0df2d75bd046b52afc9af36fa55ed03 /src | |
parent | 77cfd35e4f2b2e1d43fd3aa45133742f91676e3e (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.h | 9 | ||||
-rw-r--r-- | src/loadsave.cc | 2366 |
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); } |