summaryrefslogtreecommitdiff
path: root/src/loadsave.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/loadsave.c')
-rw-r--r--src/loadsave.c3288
1 files changed, 0 insertions, 3288 deletions
diff --git a/src/loadsave.c b/src/loadsave.c
deleted file mode 100644
index 8cdb9f72..00000000
--- a/src/loadsave.c
+++ /dev/null
@@ -1,3288 +0,0 @@
-/* File: loadsave.c */
-
-/* Purpose: interact with savefiles. This file was made by
- unifying load2.c and save.c from the old codebase. Doing it
- this way makes maintenance easier and lets us share code. */
-
-#include "angband.h"
-
-static void do_byte(byte *, 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(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 */
-
-/*
- * Basic byte-level reading from savefile. This provides a single point
- * of interface to the pseudoencryption that ToME (and Angband)
- * uses. I'm thinking about if it might be faster/better to modify all
- * the do_* functions to directly do this stuff -- it'd make the code
- * somewhat uglier to maintain, but concievably might be much faster. Or
- * is it better maybe to scrap the pseudoencryption entirely and adopt
- * some other means of obfuscation, should it still prove useful in any
- * way? -- Improv
- *
- * What's the point of encryption on savefiles anyway? If I wanted to
- * make a cheater savefile, I'd activate debug mode, and hack the game
- * not to save it. There's no point. -- takkaria
- */
-
-static byte sf_get(void)
-{
- byte c;
-
- /* Get a character, decode the value */
- c = getc(fff) & 0xFF;
-
- /* Return the value */
- return (c);
-}
-
-
-static void sf_put(byte v)
-{
- (void)putc((int)v, fff);
-}
-
-/*
- * Do object memory and similar stuff
- */
-static void do_xtra(int k_idx, int flag)
-{
- byte tmp8u = 0;
- object_kind *k_ptr = &k_info[k_idx];
-
- if (flag == LS_SAVE)
- {
- if (k_ptr->aware) tmp8u |= 0x01;
- if (k_ptr->tried) tmp8u |= 0x02;
- if (k_ptr->know) tmp8u |= 0x04;
- if (k_ptr->artifact) tmp8u |= 0x80;
-
- do_byte(&tmp8u, flag);
- }
- if (flag == LS_LOAD)
- {
- do_byte(&tmp8u, flag);
- k_ptr->aware = ((tmp8u & 0x01) ? TRUE : FALSE);
- k_ptr->tried = ((tmp8u & 0x02) ? TRUE : FALSE);
- k_ptr->know = ((tmp8u & 0x04) ? TRUE : FALSE);
- k_ptr->artifact = ((tmp8u & 0x80) ? TRUE : FALSE);
- }
-}
-
-/*
- * Load/Save quick start data
- */
-void do_quick_start(int flag)
-{
- int i;
-
- do_s16b(&previous_char.sex, flag);
- do_s16b(&previous_char.race, flag);
- do_s16b(&previous_char.rmod, flag);
- do_s16b(&previous_char.pclass, flag);
- do_s16b(&previous_char.spec, flag);
- do_byte(&previous_char.quests, flag);
- do_byte(&previous_char.god, flag);
- do_s32b(&previous_char.grace, flag);
- do_s16b(&previous_char.age, flag);
- do_s16b(&previous_char.wt, flag);
- do_s16b(&previous_char.ht, flag);
- do_s16b(&previous_char.sc, flag);
- do_s32b(&previous_char.au, flag);
-
- for (i = 0; i < 6; i++) do_s16b(&(previous_char.stat[i]), flag);
- do_s16b(&previous_char.luck, flag);
-
- do_s16b(&previous_char.chaos_patron, flag);
- do_u32b(&previous_char.weapon, flag);
- do_byte((byte*)&previous_char.quick_ok, flag);
-
- for (i = 0; i < 4; i++) do_string(previous_char.history[i], 60, flag);
-}
-
-/*
- * The special saved subrace
- */
-static void do_subrace(int flag)
-{
- player_race_mod *sr_ptr = &race_mod_info[SUBRACE_SAVE];
- int i;
- char buf[81];
-
- if (flag == LS_SAVE)
- strncpy(buf, sr_ptr->title + rmp_name, 80);
- do_string(buf, 80, flag);
- if (flag == LS_LOAD)
- strncpy(sr_ptr->title + rmp_name, buf, 80);
-
- if (flag == LS_SAVE)
- strncpy(buf, sr_ptr->desc + rmp_text, 80);
- do_string(buf, 80, flag);
- if (flag == LS_LOAD)
- strncpy(sr_ptr->desc + rmp_text, buf, 80);
-
- do_byte((byte*)&sr_ptr->place, flag);
-
- for (i = 0; i < 6; i++)
- do_s16b(&sr_ptr->r_adj[i], flag);
-
- do_byte((byte*)&sr_ptr->luck, flag);
- do_s16b(&sr_ptr->mana, flag);
-
- do_s16b(&sr_ptr->r_dis, flag);
- do_s16b(&sr_ptr->r_dev, flag);
- do_s16b(&sr_ptr->r_sav, flag);
- do_s16b(&sr_ptr->r_stl, flag);
- do_s16b(&sr_ptr->r_srh, flag);
- do_s16b(&sr_ptr->r_fos, flag);
- do_s16b(&sr_ptr->r_thn, flag);
- do_s16b(&sr_ptr->r_thb, flag);
-
- do_byte((byte*)&sr_ptr->r_mhp, flag);
- do_s16b(&sr_ptr->r_exp, flag);
-
- do_byte((byte*)&sr_ptr->b_age, flag);
- do_byte((byte*)&sr_ptr->m_age, flag);
-
- do_byte((byte*)&sr_ptr->m_b_ht, flag);
- do_byte((byte*)&sr_ptr->m_m_ht, flag);
- do_byte((byte*)&sr_ptr->f_b_ht, flag);
- do_byte((byte*)&sr_ptr->f_m_ht, flag);
-
- do_byte((byte*)&sr_ptr->m_b_wt, flag);
- do_byte((byte*)&sr_ptr->m_m_wt, flag);
- do_byte((byte*)&sr_ptr->f_b_wt, flag);
- do_byte((byte*)&sr_ptr->f_m_wt, flag);
-
- do_byte((byte*)&sr_ptr->infra, flag);
-
- for (i = 0; i < 4; i++)
- do_s16b(&sr_ptr->powers[i], flag);
-
- for (i = 0; i < BODY_MAX; i++)
- do_byte((byte*)&sr_ptr->body_parts[i], flag);
-
- do_u32b(&sr_ptr->flags1, flag);
- do_u32b(&sr_ptr->flags2, flag);
-
- for (i = 0; i < PY_MAX_LEVEL + 1; i++)
- {
- do_u32b(&sr_ptr->oflags1[i], flag);
- do_u32b(&sr_ptr->oflags2[i], flag);
- do_u32b(&sr_ptr->oflags3[i], flag);
- do_u32b(&sr_ptr->oflags4[i], flag);
- do_u32b(&sr_ptr->oflags5[i], flag);
- do_u32b(&sr_ptr->oesp[i], flag);
- do_s16b(&sr_ptr->opval[i], flag);
- }
-
- do_byte(&sr_ptr->g_attr, flag);
- do_byte((byte*)&sr_ptr->g_char, flag);
-
- for (i = 0; i < MAX_SKILLS; i++)
- {
- do_byte((byte*)&sr_ptr->skill_basem[i], flag);
- do_u32b(&sr_ptr->skill_base[i], flag);
- do_byte((byte*)&sr_ptr->skill_modm[i], flag);
- do_s16b(&sr_ptr->skill_mod[i], flag);
- }
-}
-
-/*
- * Misc. other data
- */
-static char loaded_game_module[80];
-static bool_ do_extra(int flag)
-{
- int i, j;
- byte tmp8u;
- s16b tmp16s;
- u32b tmp32u;
- u16b tmp16b;
- u32b dummy32u = 0;
-
- do_string(player_name, 32, flag);
-
- do_string(died_from, 80, flag);
-
- for (i = 0; i < 4; i++)
- {
- do_string(history[i], 60, flag);
- }
-
- /* Handle the special levels info */
- if (flag == LS_SAVE)
- {
- tmp8u = max_d_idx;
- tmp16s = MAX_DUNGEON_DEPTH;
- }
- do_byte(&tmp8u, flag);
-
- if (flag == LS_LOAD)
- {
- if (tmp8u > max_d_idx)
- {
- note(format("Too many (%d) dungeon types!", tmp8u));
- }
- }
-
- do_s16b(&tmp16s, flag);
-
- if (flag == LS_LOAD)
- {
- if (tmp16s > MAX_DUNGEON_DEPTH)
- {
- note(format("Too many (%d) max level by dungeon type!", tmp16s));
- }
- }
-
- /* Load the special levels history */
- for (i = 0; i < tmp8u; i++)
- {
- for (j = 0; j < tmp16s; j++)
- {
- do_byte((byte*)&special_lvl[j][i], flag);
- }
- }
-
- do_byte((byte*)&generate_special_feeling, flag);
-
- /* Load the quick start data */
- do_quick_start(flag);
-
- /* Load/save the special subrace */
- do_subrace(flag);
-
- /* Race/Class/Gender/Spells */
- do_s32b(&p_ptr->lives, flag);
- do_byte(&p_ptr->prace, flag);
- do_byte(&p_ptr->pracem, flag);
- do_byte(&p_ptr->pclass, flag);
- do_byte(&p_ptr->pspec, flag);
- do_byte(&p_ptr->psex, flag);
- do_u16b(&tmp16b, 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;
-
- do_byte(&p_ptr->hitdie, flag);
- do_u16b(&p_ptr->expfact, flag);
-
- do_s16b(&p_ptr->age, flag);
- do_s16b(&p_ptr->ht, flag);
- do_s16b(&p_ptr->wt, flag);
-
- /* Dump the stats (maximum and current) */
- for (i = 0; i < 6; ++i) do_s16b(&p_ptr->stat_max[i], flag);
- for (i = 0; i < 6; ++i) do_s16b(&p_ptr->stat_cur[i], flag);
- for (i = 0; i < 6; ++i) do_s16b(&p_ptr->stat_cnt[i], flag);
- for (i = 0; i < 6; ++i) do_s16b(&p_ptr->stat_los[i], flag);
-
- /* Dump the skills */
- do_s16b(&p_ptr->skill_points, flag);
- do_s16b(&p_ptr->skill_last_level, flag);
- do_s16b(&p_ptr->melee_style, flag);
- do_s16b(&p_ptr->use_piercing_shots, flag);
-
- tmp16s = MAX_SKILLS;
- do_s16b(&tmp16s, flag);
-
- if ((flag == LS_LOAD) && (tmp16s > MAX_SKILLS))
- {
- quit("Too many skills");
- }
-
- if (flag == LS_SAVE) old_max_s_idx = max_s_idx;
- do_u16b(&old_max_s_idx, flag);
- for (i = 0; i < tmp16s; ++i)
- {
- if (i < old_max_s_idx)
- {
- do_s32b(&s_info[i].value, flag);
- do_s32b(&s_info[i].mod, flag);
- do_byte((byte*)&s_info[i].dev, flag);
- do_byte((byte*)&s_info[i].hidden, flag);
- do_u32b(&s_info[i].uses, flag);
- }
- else
- {
- do_u32b(&tmp32u, flag);
- do_s16b(&tmp16s, flag);
- do_byte(&tmp8u, flag);
- do_byte(&tmp8u, flag);
- do_u32b(&tmp32u, flag);
- }
- }
-
- tmp16s = max_ab_idx;
- do_s16b(&tmp16s, flag);
-
- if ((flag == LS_LOAD) && (tmp16s > max_ab_idx))
- {
- quit("Too many abilities");
- }
-
- for (i = 0; i < tmp16s; ++i)
- {
- do_byte((byte*)&ab_info[i].acquired, flag);
- }
-
- do_s16b(&p_ptr->luck_base, flag);
- do_s16b(&p_ptr->luck_max, flag);
-
- /* Found 24 unused bytes here...
- Converted it to be the alchemist's
- known artifact flags.
- Note that the ego flags and the gained levels
- record are recorded here too, but we use the
- _ver_ format to protect save file compatablity.
- Note that the other alchemist knowledge (item types known)
- is stored in do_aux, and is a bit flag in a previously
- unused bit.
- */
- for (i = 0; i < 6 ; ++i)
- do_u32b(&alchemist_known_artifacts[i], flag);
-
- for (i = 0; i < 32 ; ++i)
- do_u32b(&alchemist_known_egos[i], flag);
-
- do_u32b(&alchemist_gained, flag);
-
- do_s32b(&p_ptr->au, flag);
-
- do_s32b(&p_ptr->max_exp, flag);
- do_s32b(&p_ptr->exp, flag);
- do_u16b(&p_ptr->exp_frac, flag);
- do_s16b(&p_ptr->lev, flag);
-
- do_s16b(&p_ptr->town_num, flag); /* -KMW- */
-
- /* Write arena and rewards information -KMW- */
- do_s16b(&p_ptr->arena_number, flag);
- do_s16b(&p_ptr->inside_arena, flag);
- do_s16b(&p_ptr->inside_quest, flag);
- do_byte((byte*)&p_ptr->exit_bldg, flag);
-
-
- /* Save/load spellbinder */
- do_byte(&p_ptr->spellbinder_num, flag);
- do_byte(&p_ptr->spellbinder_trigger, flag);
- for (i = 0; i < 4; i++)
- do_u32b(&p_ptr->spellbinder[i], flag);
-
-
- do_byte(&tmp8u, flag); /* tmp8u should be 0 at this point */
-
- if (flag == LS_SAVE) tmp8u = MAX_PLOTS;
- do_byte(&tmp8u, flag);
-
- if ((flag == LS_LOAD) && (tmp8u > MAX_PLOTS))
- {
- quit(format("Too many plots, %d %d", tmp8u, MAX_PLOTS));
- }
-
- for (i = 0; i < tmp8u; i++)
- {
- do_s16b(&plots[i], flag);
- }
-
- if (flag == LS_SAVE)
- {
- tmp8u = MAX_RANDOM_QUEST;
- }
- do_byte(&tmp8u, flag);
-
- if ((flag == LS_LOAD) &&
- (tmp8u > MAX_RANDOM_QUEST)) quit("Too many random quests");
- for (i = 0; i < tmp8u; i++)
- {
- do_byte(&random_quests[i].type, flag);
- do_s16b(&random_quests[i].r_idx, flag);
- do_byte((byte*)&random_quests[i].done, flag);
- }
-
- do_s16b(&p_ptr->oldpx, flag);
- do_s16b(&p_ptr->oldpy, flag);
-
- do_s16b(&p_ptr->mhp, flag);
- do_s16b(&p_ptr->chp, flag);
- do_u16b(&p_ptr->chp_frac, flag);
- do_s16b(&p_ptr->hp_mod, flag);
-
- do_s16b(&p_ptr->msane, flag);
- do_s16b(&p_ptr->csane, flag);
- do_u16b(&p_ptr->csane_frac, flag);
-
- do_s16b(&p_ptr->msp, flag);
- do_s16b(&p_ptr->csp, flag);
- do_u16b(&p_ptr->csp_frac, flag);
-
- /* XXX
- Here's where tank points were.
- Those who run the estate of you-know-who is really stupid.
- I'll never even consider reading her books now. -- neil */
- do_s16b(&tmp16s, flag);
- do_s16b(&tmp16s, flag);
- do_s16b(&tmp16s, flag);
- do_s16b(&tmp16s, flag);
-
- /* Gods */
- do_s32b(&p_ptr->grace, flag);
- do_byte((byte*)&p_ptr->praying, flag);
- do_s16b(&p_ptr->melkor_sacrifice, flag);
- do_byte(&p_ptr->pgod, flag);
-
- /* Max Player and Dungeon Levels */
- do_s16b(&p_ptr->max_plv, flag);
-
- if (flag == LS_SAVE)
- tmp8u = max_d_idx;
- do_byte(&tmp8u, flag);
- for (i = 0; i < tmp8u; i++)
- {
- if (flag == LS_SAVE)
- tmp16s = max_dlv[i];
- do_s16b(&tmp16s, flag);
- if ((flag == LS_LOAD) && (i <= max_d_idx))
- max_dlv[i] = tmp16s;
- }
- /* Repair max player level??? */
- if ((flag == LS_LOAD) && (p_ptr->max_plv < p_ptr->lev))
- p_ptr->max_plv = p_ptr->lev;
-
- do_byte((byte*)&(p_ptr->help.enabled), flag);
- do_u32b(&(p_ptr->help.help1), flag);
-
- /* More info */
- tmp16s = 0;
- do_s16b(&p_ptr->sc, flag);
- do_s16b(&p_ptr->blind, flag);
- do_s16b(&p_ptr->paralyzed, flag);
- do_s16b(&p_ptr->confused, flag);
- do_s16b(&p_ptr->food, flag);
- do_s32b(&p_ptr->energy, flag);
- do_s16b(&p_ptr->fast, flag);
- do_s16b(&p_ptr->speed_factor, flag);
- do_s16b(&p_ptr->slow, flag);
- do_s16b(&p_ptr->afraid, flag);
- do_s16b(&p_ptr->cut, flag);
- do_s16b(&p_ptr->stun, flag);
- do_s16b(&p_ptr->poisoned, flag);
- do_s16b(&p_ptr->image, flag);
- do_s16b(&p_ptr->protevil, flag);
- do_s16b(&p_ptr->protundead, flag);
- do_s16b(&p_ptr->invuln, flag);
- do_s16b(&p_ptr->hero, flag);
- do_s16b(&p_ptr->shero, flag);
- do_s16b(&p_ptr->shield, flag);
- do_s16b(&p_ptr->shield_power, flag);
- do_s16b(&p_ptr->shield_power_opt, flag);
- do_s16b(&p_ptr->shield_power_opt2, flag);
- do_s16b(&p_ptr->shield_opt, flag);
- do_s16b(&p_ptr->blessed, flag);
- do_s16b(&p_ptr->control, flag);
- do_byte(&p_ptr->control_dir, flag);
- do_s16b(&p_ptr->tim_thunder, flag);
- do_s16b(&p_ptr->tim_thunder_p1, flag);
- do_s16b(&p_ptr->tim_thunder_p2, flag);
- do_s16b(&p_ptr->tim_project, flag);
- do_s16b(&p_ptr->tim_project_dam, flag);
- do_s16b(&p_ptr->tim_project_gf, flag);
- do_s16b(&p_ptr->tim_project_rad, flag);
- do_s16b(&p_ptr->tim_project_flag, flag);
-
- do_s16b(&p_ptr->tim_magic_breath, flag);
- do_s16b(&p_ptr->tim_water_breath, flag);
-
- do_s16b(&p_ptr->tim_roots, flag);
- do_s16b(&p_ptr->tim_roots_ac, flag);
- do_s16b(&p_ptr->tim_roots_dam, flag);
-
- do_s16b(&p_ptr->tim_invis, flag);
- do_s16b(&p_ptr->word_recall, flag);
- do_s16b(&p_ptr->recall_dungeon, flag);
- do_s16b(&p_ptr->see_infra, flag);
- do_s16b(&p_ptr->tim_infra, flag);
- do_s16b(&p_ptr->oppose_fire, flag);
- do_s16b(&p_ptr->oppose_cold, flag);
- do_s16b(&p_ptr->oppose_acid, flag);
- do_s16b(&p_ptr->oppose_elec, flag);
- do_s16b(&p_ptr->oppose_pois, flag);
- do_s16b(&p_ptr->oppose_ld, flag);
- do_s16b(&p_ptr->oppose_cc, flag);
- do_s16b(&p_ptr->oppose_ss, flag);
- do_s16b(&p_ptr->oppose_nex, flag);
-
- do_s16b(&p_ptr->tim_esp, flag);
- do_s16b(&p_ptr->tim_wraith, flag);
- do_s16b(&p_ptr->tim_ffall, flag);
- do_ver_s16b(&p_ptr->tim_fly, SAVEFILE_VERSION, 0, flag);
- do_s16b(&p_ptr->tim_fire_aura, flag);
- do_ver_s16b(&p_ptr->tim_poison, SAVEFILE_VERSION, 0, flag);
- do_s16b(&p_ptr->resist_magic, flag);
- do_s16b(&p_ptr->tim_invisible, flag);
- do_s16b(&p_ptr->tim_inv_pow, flag);
- do_s16b(&p_ptr->tim_mimic, flag);
- do_s16b(&p_ptr->lightspeed, flag);
- do_s16b(&p_ptr->tim_lite, flag);
- do_ver_s16b(&p_ptr->tim_regen, SAVEFILE_VERSION, 0, flag);
- do_ver_s16b(&p_ptr->tim_regen_pow, SAVEFILE_VERSION, 0, flag);
- do_s16b(&p_ptr->holy, flag);
- do_s16b(&p_ptr->walk_water, flag);
- do_s16b(&p_ptr->tim_mental_barrier, flag);
- do_s16b(&p_ptr->immov_cntr, flag);
- do_s16b(&p_ptr->strike, flag);
- do_s16b(&p_ptr->meditation, flag);
- do_s16b(&p_ptr->tim_reflect, flag);
- do_s16b(&p_ptr->tim_res_time, flag);
- do_s16b(&p_ptr->tim_deadly, flag);
- do_s16b(&p_ptr->prob_travel, flag);
- do_s16b(&p_ptr->disrupt_shield, flag);
- do_s16b(&p_ptr->parasite, flag);
- do_s16b(&p_ptr->parasite_r_idx, flag);
- do_s32b(&p_ptr->loan, flag);
- do_s32b(&p_ptr->loan_time, flag);
- do_s16b(&p_ptr->absorb_soul, flag);
-
- do_s16b(&p_ptr->chaos_patron, flag);
-
- if (flag == LS_SAVE) tmp16s = max_corruptions;
- do_s16b(&tmp16s, flag);
-
- for (i = 0; i < tmp16s; i++)
- {
- if ((flag == LS_SAVE) && (i < max_corruptions))
- tmp8u = p_ptr->corruptions[i];
-
- do_byte(&tmp8u, flag);
-
- if ((flag == LS_LOAD) && (i < max_corruptions))
- p_ptr->corruptions[i] = tmp8u;
- }
-
- do_byte(&p_ptr->confusing, flag);
- do_byte((byte*)&p_ptr->black_breath, flag);
- do_byte((byte*)&fate_flag, flag);
- do_byte(&p_ptr->searching, flag);
- do_byte(&p_ptr->maximize, flag);
- do_byte(&p_ptr->preserve, flag);
- do_byte(&p_ptr->special, flag);
- do_byte((byte*)&ambush_flag, flag);
- do_byte(&p_ptr->allow_one_death, flag);
- do_s16b(&p_ptr->xtra_spells, flag);
-
- do_byte(&tmp8u, flag);
-
- do_s16b(&no_breeds, flag);
- do_s16b(&p_ptr->protgood, flag);
-
- /* Auxilliary variables */
- do_u32b(&p_ptr->mimic_extra, flag);
- do_u32b(&p_ptr->antimagic_extra, flag);
- do_u32b(&p_ptr->druid_extra, flag);
- do_u32b(&p_ptr->druid_extra2, flag);
- do_u32b(&p_ptr->druid_extra3, flag);
- do_u32b(&p_ptr->music_extra, flag);
- do_u32b(&p_ptr->music_extra2, flag);
- do_u32b(&p_ptr->necro_extra, flag);
- do_u32b(&p_ptr->necro_extra2, flag);
-
- do_u32b(&p_ptr->race_extra1, flag);
- do_u32b(&p_ptr->race_extra2, flag);
- do_u32b(&p_ptr->race_extra3, flag);
- do_u32b(&p_ptr->race_extra4, flag);
- do_u32b(&p_ptr->race_extra5, flag);
- do_u32b(&p_ptr->race_extra6, flag);
- do_u32b(&p_ptr->race_extra7, flag);
-
- do_u16b(&p_ptr->body_monster, flag);
- do_byte((byte*)&p_ptr->disembodied, flag);
-
- /* Are we in astral mode? */
- do_byte((byte*)&p_ptr->astral, flag);
-
- if (flag == LS_SAVE) tmp16s = POWER_MAX_INIT;
- do_s16b(&tmp16s, flag);
- if ((flag == LS_LOAD) && (tmp16s > POWER_MAX_INIT))
- note(format("Too many (%u) powers!", tmp16s));
- if (flag == LS_SAVE) tmp16s = POWER_MAX_INIT;
- for (i = 0; i < tmp16s; i++)
- do_byte((byte*)&p_ptr->powers_mod[i], flag);
-
- skip_ver_byte(100, flag);
-
- /* The tactic */
- do_byte((byte*)&p_ptr->tactic, flag);
-
- /* The movement */
- do_byte((byte*)&p_ptr->movement, flag);
-
- /* The comapnions killed */
- do_s16b(&p_ptr->companion_killed, flag);
-
- /* The fate */
- do_byte((byte*)&p_ptr->no_mortal, flag);
-
- /* The bounties */
- for (i = 0; i < MAX_BOUNTIES; i++)
- {
- do_s16b(&bounties[i][0], flag);
- do_s16b(&bounties[i][1], flag);
- }
- do_u32b(&total_bounties, flag);
- do_s16b(&spell_num, flag);
- for (i = 0; i < MAX_SPELLS; i++)
- do_spells(i, flag);
- do_s16b(&rune_num, flag);
- for (i = 0; i < MAX_RUNES; i++)
- {
- do_string(rune_spells[i].name, 30, flag);
- do_s16b(&rune_spells[i].type, flag);
- do_s16b(&rune_spells[i].rune2, flag);
- do_s16b(&rune_spells[i].mana, flag);
- }
-
- /* Load random seeds */
- do_u32b(&dummy32u, flag); /* Load-compatibility with old savefiles. */
- do_u32b(&seed_flavor, flag); /* For consistent object flavors. */
- do_u32b(&dummy32u, flag); /* Load-compatibility with old savefiles. */
-
- /* Special stuff */
- do_u16b(&tmp16b, flag); /* Dummy */
- do_u16b(&total_winner, flag);
- do_u16b(&has_won, flag);
- do_u16b(&noscore, flag);
-
- /* Write death */
- if (flag == LS_SAVE) tmp8u = death;
- do_byte(&tmp8u, flag);
- if (flag == LS_LOAD) death = tmp8u;
-
- /* Incompatible module? */
- if (flag == LS_LOAD)
- {
- s32b ok;
-
- call_lua("module_savefile_loadable", "(s,d)", "d", loaded_game_module, death, &ok);
-
- /* Argh bad game module! */
- if (!ok)
- {
- note(format("Bad game module. Savefile was saved with module '%s' but game is '%s'.", loaded_game_module, game_module));
- return (FALSE);
- }
- }
-
- /* Write feeling */
- if (flag == LS_SAVE) tmp8u = feeling;
- do_byte(&tmp8u, flag);
- if (flag == LS_LOAD) feeling = tmp8u;
-
- /* Turn of last "feeling" */
- do_s32b(&old_turn, flag);
-
- /* Current turn */
- do_s32b(&turn, 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);
-
- /* Successful save */
- character_saved = TRUE;
-
- /* 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(char *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)
- {
- /* 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(&sf_extra, LS_LOAD);
-
- /* 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;
- sf_extra = VERSION_EXTRA;
-
- /* 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)
- {
- /* Maybe the scripts want to resurrect char */
- if (process_hooks_ret(HOOK_LOAD_END, "d", "(d)", death))
- {
- character_loaded = process_hooks_return[0].num;
- death = process_hooks_return[1].num;
- return TRUE;
- }
-
- /* 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.
- */
-
-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_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)
-{
- if (flag == LS_LOAD)
- {
- do_u16b((u16b *)ip, flag);
- return;
- }
- if (flag == LS_SAVE)
- {
- do_u16b((u16b *)ip, flag);
- return;
- }
- /* Blah blah, never should reach here, die */
- printf("FATAL: do_s16b passed %d\n", flag);
- exit(0);
-}
-
-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)
-{
- if (flag == LS_LOAD)
- {
- do_u32b((u32b *)ip, flag);
- return;
- }
- if (flag == LS_SAVE)
- {
- do_u32b((u32b *)ip, flag);
- return;
- }
- /* Raus! Schnell! */
- printf("FATAL: do_s32b passed %d\n", flag);
- exit(0);
-}
-
-static void do_string(char *str, int max, int flag)
-/* Max is ignored for writing */
-{
- if (flag == LS_LOAD)
- {
- int i;
-
- /* Read the string */
- for (i = 0; TRUE; i++)
- {
- byte tmp8u;
-
- /* Read a byte */
- do_byte(&tmp8u, LS_LOAD);
-
- /* Collect string while legal */
- if (i < max) str[i] = tmp8u;
-
- /* End of string */
- if (!tmp8u) break;
- }
- /* Terminate */
- str[max - 1] = '\0';
- return;
- }
- if (flag == LS_SAVE)
- {
- while (*str)
- {
- do_byte((byte*)str, flag);
- str++;
- }
- do_byte((byte*)str, flag); /* Output a terminator */
- return;
- }
- printf("FATAL: do_string passed flag %d\n", flag);
- exit(0);
-}
-
-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;
-}
-
-static void do_ver_s16b(s16b *v, u32b version, s16b defval, int flag)
-{
- if ((flag == LS_LOAD) && (vernum < version))
- {
- *v = defval;
- return;
- }
- 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();
-}
-
-
-/*
- * Determine if an item can be wielded/worn (e.g. helmet, sword, bow, arrow)
- */
-static bool_ wearable_p(object_type *o_ptr)
-{
- /* Valid "tval" codes */
- switch (o_ptr->tval)
- {
- case TV_WAND:
- case TV_STAFF:
- case TV_ROD:
- case TV_ROD_MAIN:
- case TV_SHOT:
- case TV_ARROW:
- case TV_BOLT:
- case TV_BOOMERANG:
- case TV_BOW:
- case TV_DIGGING:
- case TV_HAFTED:
- case TV_POLEARM:
- case TV_MSTAFF:
- case TV_SWORD:
- case TV_AXE:
- case TV_BOOTS:
- case TV_GLOVES:
- case TV_HELM:
- case TV_CROWN:
- case TV_SHIELD:
- case TV_CLOAK:
- case TV_SOFT_ARMOR:
- case TV_HARD_ARMOR:
- case TV_DRAG_ARMOR:
- case TV_SCROLL:
- case TV_LITE:
- case TV_POTION:
- case TV_POTION2:
- case TV_AMULET:
- case TV_RING:
- case TV_HYPNOS:
- case TV_INSTRUMENT:
- case TV_DAEMON_BOOK:
- case TV_TRAPKIT:
- case TV_TOOL:
- {
- return (TRUE);
- }
- }
-
- /* Nope */
- return (FALSE);
-}
-
-
-/*
- * rd/wr an object
- *
- * 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)
-{
- byte old_dd;
- byte old_ds;
-
- u32b f1, f2, f3, f4, f5, esp;
-
- object_kind *k_ptr;
-
- /* Kind */
- do_s16b(&o_ptr->k_idx, flag);
-
- /* Location */
- do_byte(&o_ptr->iy, flag);
- do_byte(&o_ptr->ix, flag);
-
- /* Type/Subtype */
- do_byte(&o_ptr->tval, flag);
- do_byte(&o_ptr->sval, flag);
-
- /* Special pval */
- do_s32b(&o_ptr->pval, flag);
-
- /* Special pval */
- do_s16b(&o_ptr->pval2, flag);
-
- /* Special pval */
- do_s32b(&o_ptr->pval3, flag);
-
- do_byte(&o_ptr->discount, flag);
- do_byte(&o_ptr->number, flag);
- do_s32b(&o_ptr->weight, flag);
-
- do_byte(&o_ptr->name1, flag);
- do_s16b(&o_ptr->name2, flag);
- do_s16b(&o_ptr->name2b, flag);
- do_s16b(&o_ptr->timeout, flag);
-
- do_s16b(&o_ptr->to_h, flag);
- do_s16b(&o_ptr->to_d, flag);
- do_s16b(&o_ptr->to_a, flag);
-
- do_s16b(&o_ptr->ac, flag);
-
- /* We do special processing of this flag when reading */
- if (flag == LS_LOAD)
- {
- do_byte(&old_dd, LS_LOAD);
- do_byte(&old_ds, LS_LOAD);
- }
- if (flag == LS_SAVE)
- {
- do_byte(&o_ptr->dd, LS_SAVE);
- do_byte(&o_ptr->ds, LS_SAVE);
- }
-
- do_byte(&o_ptr->ident, flag);
-
- do_byte(&o_ptr->marked, flag);
-
- /* flags */
- do_u32b(&o_ptr->art_flags1, flag);
- do_u32b(&o_ptr->art_flags2, flag);
- do_u32b(&o_ptr->art_flags3, flag);
- do_u32b(&o_ptr->art_flags4, flag);
- do_u32b(&o_ptr->art_flags5, flag);
- do_u32b(&o_ptr->art_esp, flag);
-
- /* obvious flags */
- do_u32b(&o_ptr->art_oflags1, flag);
- do_u32b(&o_ptr->art_oflags2, flag);
- do_u32b(&o_ptr->art_oflags3, flag);
- do_u32b(&o_ptr->art_oflags4, flag);
- do_u32b(&o_ptr->art_oflags5, flag);
- do_u32b(&o_ptr->art_oesp, flag);
-
- /* Monster holding object */
- do_s16b(&o_ptr->held_m_idx, flag);
-
- /* Special powers */
- do_byte(&o_ptr->xtra1, flag);
- do_s16b(&o_ptr->xtra2, flag);
-
- do_byte(&o_ptr->elevel, flag);
- do_s32b(&o_ptr->exp, flag);
-
- /* Read the pseudo-id */
- do_byte(&o_ptr->sense, flag);
-
- /* Read the found info */
- do_byte(&o_ptr->found, flag);
- do_s16b(&o_ptr->found_aux1, flag);
- do_s16b(&o_ptr->found_aux2, flag);
- do_s16b(&o_ptr->found_aux3, flag);
- do_s16b(&o_ptr->found_aux4, flag);
-
- if (flag == LS_LOAD)
- {
- char buf[128];
- /* Inscription */
- do_string(buf, 128, LS_LOAD);
- /* Save the inscription */
- if (buf[0]) o_ptr->note = quark_add(buf);
-
- do_string(buf, 128, LS_LOAD);
- if (buf[0]) o_ptr->art_name = quark_add(buf);
- }
- if (flag == LS_SAVE)
- {
- /* Save the inscription (if any) */
- if (o_ptr->note)
- {
- do_string((char *)quark_str(o_ptr->note), 0, LS_SAVE);
- }
- else
- {
- do_string("", 0, LS_SAVE);
- }
- if (o_ptr->art_name)
- {
- do_string((char *)quark_str(o_ptr->art_name), 0, LS_SAVE);
- }
- else
- {
- do_string("", 0, LS_SAVE);
- }
- }
-
- if (flag == LS_SAVE) return ; /* Stick any more shared code before this. The rest
- of this function is reserved for LS_LOAD's
- cleanup functions */
- /*********** END OF LS_SAVE ***************/
-
- /* Obtain the "kind" template */
- k_ptr = &k_info[o_ptr->k_idx];
-
- /* Obtain tval/sval from k_info */
- o_ptr->tval = k_ptr->tval;
- if (o_ptr->tval != TV_RANDART) o_ptr->sval = k_ptr->sval;
-
-
- /* Repair non "wearable" items */
- if (!wearable_p(o_ptr))
- {
- /* Acquire correct fields */
- o_ptr->to_h = k_ptr->to_h;
- o_ptr->to_d = k_ptr->to_d;
- o_ptr->to_a = k_ptr->to_a;
-
- /* Acquire correct fields */
- o_ptr->ac = k_ptr->ac;
- o_ptr->dd = k_ptr->dd;
- o_ptr->ds = k_ptr->ds;
-
- /* All done */
- return;
- }
-
-
- /* Extract the flags */
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
-
- /* Paranoia */
- if (o_ptr->name1)
- {
- artifact_type *a_ptr;
-
- /* Obtain the artifact info */
- a_ptr = &a_info[o_ptr->name1];
-
- /* Verify that artifact */
- if (!a_ptr->name) o_ptr->name1 = 0;
- }
-
- /* Paranoia */
- if (o_ptr->name2)
- {
- ego_item_type *e_ptr;
-
- /* Obtain the ego-item info */
- e_ptr = &e_info[o_ptr->name2];
-
- /* Verify that ego-item */
- if (!e_ptr->name) o_ptr->name2 = 0;
- }
-
-
- /* Acquire standard fields */
- o_ptr->ac = k_ptr->ac;
- o_ptr->dd = k_ptr->dd;
- o_ptr->ds = k_ptr->ds;
-
- /* Artifacts */
- if (o_ptr->name1)
- {
- artifact_type *a_ptr;
-
- /* Obtain the artifact info */
- a_ptr = &a_info[o_ptr->name1];
-
- /* Acquire new artifact fields */
- o_ptr->ac = a_ptr->ac;
- o_ptr->dd = a_ptr->dd;
- o_ptr->ds = a_ptr->ds;
-
- /* Acquire new artifact weight */
- o_ptr->weight = a_ptr->weight;
- }
-
- /* Ego items */
- if (o_ptr->name2)
- {
- o_ptr->dd = old_dd;
- o_ptr->ds = old_ds;
- }
-
- if (o_ptr->art_name) /* A random artifact */
- {
- o_ptr->dd = old_dd;
- o_ptr->ds = old_ds;
- }
-}
-
-
-
-
-/*
- * Read a monster
- */
-static void do_monster(monster_type *m_ptr, int flag)
-{
- int i;
- bool_ tmp;
-
- /* Read the monster race */
- do_s16b(&m_ptr->r_idx, flag);
-
- do_u16b(&m_ptr->ego, flag);
-
- /* Read the other information */
- do_byte(&m_ptr->fy, flag);
- do_byte(&m_ptr->fx, flag);
-
- do_s32b(&m_ptr->hp, flag);
- do_s32b(&m_ptr->maxhp, 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_u32b(&m_ptr->exp, flag);
- do_s16b(&m_ptr->target, flag);
-
- do_s16b(&m_ptr->bleeding, flag);
- do_s16b(&m_ptr->poisoned, flag);
-
- do_s32b(&m_ptr->mflag, flag);
-
- if (flag == LS_LOAD) m_ptr->mflag &= PERM_MFLAG_MASK;
-
- /* Attacks */
- for (i = 0; i < 4; 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);
- }
-
- /* Mind */
- tmp = (m_ptr->mind) ? TRUE : FALSE;
- do_byte((byte*)&tmp, flag);
- if (tmp)
- {
- if (flag == LS_LOAD)
- {
- MAKE(m_ptr->mind, monster_mind);
- }
- }
-
- /* Special race */
- tmp = (m_ptr->sr_ptr) ? TRUE : FALSE;
- do_byte((byte*)&tmp, flag);
- if (tmp)
- {
- if (flag == LS_LOAD)
- {
- MAKE(m_ptr->sr_ptr, monster_race);
- }
- do_u32b(&m_ptr->sr_ptr->name, flag);
- do_u32b(&m_ptr->sr_ptr->text, flag);
-
- do_u16b(&m_ptr->sr_ptr->hdice, flag);
- do_u16b(&m_ptr->sr_ptr->hside, flag);
-
- do_s16b(&m_ptr->sr_ptr->ac, flag);
-
- do_s16b(&m_ptr->sr_ptr->sleep, flag);
- do_byte(&m_ptr->sr_ptr->aaf, flag);
- do_byte(&m_ptr->sr_ptr->speed, flag);
-
- do_s32b(&m_ptr->sr_ptr->mexp, flag);
-
- do_s32b(&m_ptr->sr_ptr->weight, flag);
-
- do_byte(&m_ptr->sr_ptr->freq_inate, flag);
- do_byte(&m_ptr->sr_ptr->freq_spell, flag);
-
- do_u32b(&m_ptr->sr_ptr->flags1, flag);
- do_u32b(&m_ptr->sr_ptr->flags2, flag);
- do_u32b(&m_ptr->sr_ptr->flags3, flag);
- do_u32b(&m_ptr->sr_ptr->flags4, flag);
- do_u32b(&m_ptr->sr_ptr->flags5, flag);
- do_u32b(&m_ptr->sr_ptr->flags6, flag);
- do_u32b(&m_ptr->sr_ptr->flags7, flag);
- do_u32b(&m_ptr->sr_ptr->flags8, flag);
- do_u32b(&m_ptr->sr_ptr->flags9, flag);
-
- /* Attacks */
- for (i = 0; i < 4; i++)
- {
- do_byte(&m_ptr->sr_ptr->blow[i].method, flag);
- do_byte(&m_ptr->sr_ptr->blow[i].effect, flag);
- do_byte(&m_ptr->sr_ptr->blow[i].d_dice, flag);
- do_byte(&m_ptr->sr_ptr->blow[i].d_side, flag);
- }
-
- for (i = 0; i < BODY_MAX; i++)
- do_byte(&m_ptr->sr_ptr->body_parts[i], flag);
-
- do_byte(&m_ptr->sr_ptr->level, flag);
- do_byte(&m_ptr->sr_ptr->rarity, flag);
-
- do_byte((byte*)&m_ptr->sr_ptr->d_char, flag);
- do_byte(&m_ptr->sr_ptr->d_attr, flag);
-
- do_byte((byte*)&m_ptr->sr_ptr->x_char, flag);
- do_byte(&m_ptr->sr_ptr->x_attr, flag);
-
- do_s16b(&m_ptr->sr_ptr->max_num, flag);
- do_byte(&m_ptr->sr_ptr->cur_num, flag);
- }
-}
-
-
-
-
-
-/*
- * Handle monster lore
- */
-static void do_lore(int r_idx, int flag)
-{
- monster_race *r_ptr = &r_info[r_idx];
-
- /* Count sights/deaths/kills */
- do_s16b(&r_ptr->r_sights, flag);
- do_s16b(&r_ptr->r_deaths, flag);
- do_s16b(&r_ptr->r_pkills, flag);
- do_s16b(&r_ptr->r_tkills, flag);
-
- /* Count wakes and ignores */
- do_byte(&r_ptr->r_wake, flag);
- do_byte(&r_ptr->r_ignore, flag);
-
- /* Extra stuff */
- do_byte(&r_ptr->r_xtra1, flag);
- do_byte(&r_ptr->r_xtra2, flag);
-
- /* Count drops */
- do_byte(&r_ptr->r_drop_gold, flag);
- do_byte(&r_ptr->r_drop_item, flag);
-
- /* Count spells */
- do_byte(&r_ptr->r_cast_inate, flag);
- do_byte(&r_ptr->r_cast_spell, flag);
-
- /* Count blows of each type */
- do_byte(&r_ptr->r_blows[0], flag);
- do_byte(&r_ptr->r_blows[1], flag);
- do_byte(&r_ptr->r_blows[2], flag);
- do_byte(&r_ptr->r_blows[3], flag);
-
- /* Memorize flags */
- do_u32b(&r_ptr->r_flags1, flag); /* Just to remind you */
- do_u32b(&r_ptr->r_flags2, flag); /* flag is unrelated to */
- do_u32b(&r_ptr->r_flags3, flag); /* the other argument */
- do_u32b(&r_ptr->r_flags4, flag);
- do_u32b(&r_ptr->r_flags5, flag);
- do_u32b(&r_ptr->r_flags6, flag);
- do_u32b(&r_ptr->r_flags7, flag);
- do_u32b(&r_ptr->r_flags8, flag);
- do_u32b(&r_ptr->r_flags9, flag);
-
- /* Read the "Racial" monster tmp16b per level */
- do_s16b(&r_ptr->max_num, flag);
-
- do_byte((byte*)&r_ptr->on_saved, flag);
-
- if (flag == LS_LOAD)
- {
- /* Lore flag repair? */
- r_ptr->r_flags1 &= r_ptr->flags1;
- r_ptr->r_flags2 &= r_ptr->flags2;
- r_ptr->r_flags3 &= r_ptr->flags3;
- r_ptr->r_flags4 &= r_ptr->flags4;
- r_ptr->r_flags5 &= r_ptr->flags5;
- r_ptr->r_flags6 &= r_ptr->flags6;
- }
-}
-
-
-
-
-/*
- * Read a store
- */
-static bool_ do_store(store_type *str, int flag)
-/* FIXME! Why does this return anything when
- it always returns the same thing? */
-{
- int j;
-
- byte num;
-
- byte store_inven_max = STORE_INVEN_MAX;
-
- /* Some basic info */
- do_s32b(&str->store_open, flag);
- do_s16b(&str->insult_cur, flag);
- do_u16b(&str->owner, flag);
- if (flag == LS_SAVE) num = str->stock_num;
-
- /* Could be cleaner, done this way for benefit of the for loop later on */
- do_byte(&num, flag);
-
- do_s16b(&str->good_buy, flag);
- do_s16b(&str->bad_buy, flag);
-
- /* Last visit */
- do_s32b(&str->last_visit, flag);
-
- /* Items */
- for (j = 0; j < num; j++)
- {
- if (flag == LS_LOAD)
- /* Can't this be cleaner? */
- {
- object_type forge;
- /* Wipe the object */
- object_wipe(&forge);
- /* Read the item */
- do_item(&forge, LS_LOAD);
- /* Acquire valid items */
- if ((str->stock_num < store_inven_max) && (str->stock_num < str->stock_size))
- {
- int k = str->stock_num++;
-
- /* Acquire the item */
- object_copy(&str->stock[k], &forge);
- }
- }
- if (flag == LS_SAVE) do_item(&str->stock[j], flag);
- }
-
- /* Success */
- return (TRUE);
-}
-
-/*
- * RNG state
- */
-static void do_randomizer(int flag)
-{
- int i;
-
- u16b tmp16u = 0;
-
- /* Tmp */
- do_u16b(&tmp16u, flag);
-
- /* Place */
- do_u16b(&Rand_place, flag);
-
- /* State */
- for (i = 0; i < RAND_DEG; i++)
- {
- do_u32b(&Rand_state[i], flag);
- }
-
- /* Accept */
- if (flag == LS_LOAD)
- {
- Rand_quick = FALSE;
- }
-}
-
-/*
- * Handle options
- *
- * Normal options are stored as a set of 256 bit flags,
- * plus a set of 256 bit masks to indicate which bit flags were defined
- * at the time the savefile was created. This will allow new options
- * to be added, and old options to be removed, at any time, without
- * hurting old savefiles.
- *
- * 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)
-{
- int i, n;
-
- u32b oflag[8];
- u32b mask[8];
-
- /*** Special info */
-
- /* Read "delay_factor" */
- do_byte(&delay_factor, flag);
-
- /* Read "hitpoint_warn" */
- do_byte(&hitpoint_warn, flag);
-
- /*** Cheating options ***/
- if (flag == LS_LOAD) /* There *MUST* be some nice way to unify this! */
- {
- u16b c;
- do_u16b(&c, LS_LOAD);
- if (c & 0x0002) wizard = TRUE;
- cheat_peek = (c & 0x0100) ? TRUE : FALSE;
- cheat_hear = (c & 0x0200) ? TRUE : FALSE;
- cheat_room = (c & 0x0400) ? TRUE : FALSE;
- cheat_xtra = (c & 0x0800) ? TRUE : FALSE;
- cheat_know = (c & 0x1000) ? TRUE : FALSE;
- cheat_live = (c & 0x2000) ? TRUE : FALSE;
- }
- if (flag == LS_SAVE)
- {
- u16b c = 0;
- if (wizard) c |= 0x0002;
- if (cheat_peek) c |= 0x0100;
- if (cheat_hear) c |= 0x0200;
- if (cheat_room) c |= 0x0400;
- if (cheat_xtra) c |= 0x0800;
- if (cheat_know) c |= 0x1000;
- if (cheat_live) c |= 0x2000;
- do_u16b(&c, LS_SAVE);
- }
-
- do_byte((byte*)&autosave_l, flag);
- do_byte((byte*)&autosave_t, flag);
- do_s16b(&autosave_freq, flag);
-
- if (flag == LS_LOAD)
- {
- /* Read the option flags */
- for (n = 0; n < 8; n++) do_u32b(&oflag[n], flag);
-
- /* Read the option masks */
- for (n = 0; n < 8; n++) do_u32b(&mask[n], flag);
-
- /* Analyze the options */
- for (n = 0; n < 8; n++)
- {
- /* Analyze the options */
- for (i = 0; i < 32; i++)
- {
- /* Process valid flags */
- if (mask[n] & (1L << i))
- {
- /* Process valid flags */
- if (option_mask[n] & (1L << i))
- {
- /* Set */
- if (oflag[n] & (1L << i))
- {
- /* Set */
- option_flag[n] |= (1L << i);
- }
-
- /* Clear */
- else
- {
- /* Clear */
- option_flag[n] &= ~(1L << i);
- }
- }
- }
- }
- }
-
-
- /*** Window Options ***/
-
- /* Read the window flags */
- for (n = 0; n < 8; n++) do_u32b(&oflag[n], flag);
-
- /* Read the window masks */
- for (n = 0; n < 8; n++) do_u32b(&mask[n], flag);
-
- /* Analyze the options */
- for (n = 0; n < 8; n++)
- {
- /* Analyze the options */
- for (i = 0; i < 32; i++)
- {
- /* Process valid flags */
- if (mask[n] & (1L << i))
- {
- /* Process valid flags */
- if (window_mask[n] & (1L << i))
- {
- /* Set */
- if (oflag[n] & (1L << i))
- {
- /* Set */
- window_flag[n] |= (1L << i);
- }
-
- /* Clear */
- else
- {
- /* Clear */
- window_flag[n] &= ~(1L << i);
- }
- }
- }
- }
- }
- }
- if (flag == LS_SAVE)
- {
- /* Analyze the options */
- for (i = 0; option_info[i].o_desc; i++)
- {
- int os = option_info[i].o_page;
- int ob = option_info[i].o_bit;
-
- /* Process real entries */
- if (option_info[i].o_var)
- {
- /* Set */
- if (*option_info[i].o_var)
- {
- /* Set */
- option_flag[os] |= (1L << ob);
- }
-
- /* Clear */
- else
- {
- /* Clear */
- option_flag[os] &= ~(1L << ob);
- }
- }
- }
-
-
- /*** Normal options ***/
-
- /* Dump the flags */
- for (i = 0; i < 8; i++) do_u32b(&option_flag[i], flag);
-
- /* Dump the masks */
- for (i = 0; i < 8; i++) do_u32b(&option_mask[i], flag);
-
- /*** Window options ***/
-
- /* Dump the flags */
- for (i = 0; i < 8; i++) do_u32b(&window_flag[i], flag);
-
- /* Dump the masks */
- for (i = 0; i < 8; i++) do_u32b(&window_mask[i], 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)
-{
- if (flag == LS_LOAD)
- {
- int slot = 0;
-
- object_type forge;
- object_type *q_ptr;
-
- /* No items */
- inven_cnt = 0;
- equip_cnt = 0;
-
- /* Read until done */
- while (1)
- {
- u16b n;
-
- /* Get the next item index */
- do_u16b(&n, LS_LOAD);
-
- /* Nope, we reached the end */
- if (n == 0xFFFF) break;
-
- /* Get local object */
- q_ptr = &forge;
-
- /* Wipe the object */
- object_wipe(q_ptr);
-
- /* Read the item */
- do_item(q_ptr, LS_LOAD);
-
- /* Hack -- verify item */
- if (!q_ptr->k_idx) return (FALSE);
-
- /* Wield equipment */
- if (n >= INVEN_WIELD)
- {
- /* Copy object */
- object_copy(&p_ptr->inventory[n], q_ptr);
-
- /* Take care of item sets */
- if (q_ptr->name1)
- {
- wield_set(q_ptr->name1, a_info[q_ptr->name1].set, TRUE);
- }
-
- /* One more item */
- equip_cnt++;
- }
-
- /* Warning -- backpack is full */
- else if (inven_cnt == INVEN_PACK)
- {
- /* Oops */
- note("Too many items in the inventory!");
-
- /* Fail */
- return (FALSE);
- }
-
- /* Carry inventory */
- else
- {
- /* Get a slot */
- n = slot++;
-
- /* Copy object */
- object_copy(&p_ptr->inventory[n], q_ptr);
-
- /* One more item */
- inven_cnt++;
- }
- }
- }
- if (flag == LS_SAVE)
- {
- u16b i;
- u16b sent = 0xFFFF;
- for (i = 0; i < INVEN_TOTAL; i++)
- {
- object_type *o_ptr = &p_ptr->inventory[i];
- if (!o_ptr->k_idx) continue;
- do_u16b(&i, flag);
- do_item(o_ptr, flag);
- }
- do_u16b(&sent, LS_SAVE); /* Sentinel */
- }
- /* Success */
- return (TRUE);
-}
-
-
-
-/*
- * Read the saved messages
- */
-static void do_messages(int flag) /* FIXME! We should be able to unify this better */
-{
- int i;
- char buf[128];
- byte color, type;
-
- s16b num;
-
- if (flag == LS_SAVE) num = message_num();
-
- /* Total */
- do_s16b(&num, flag);
-
- /* Read the messages */
- if (flag == LS_LOAD)
- {
- for (i = 0; i < num; i++)
- {
- /* Read the message */
- do_string(buf, 128, LS_LOAD);
- do_byte(&color, flag);
- do_byte(&type, flag);
-
- /* Save the message */
- message_add(type, buf, color);
- }
- }
- if (flag == LS_SAVE)
- {
- byte holder;
- for (i = num - 1; i >= 0; i--)
- {
- do_string((char *)message_str((s16b)i), 0, LS_SAVE);
- holder = message_color((s16b)i);
- do_byte(&holder, flag);
- holder = message_type((s16b)i);
- do_byte(&holder, flag);
- }
- }
-}
-
-/*
- * 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)
-{
- char tmp[16];
- char name[1024];
- byte old_dungeon_type = dungeon_type;
- s16b old_dun = dun_level;
-
- /* Construct name */
- sprintf(tmp, "%s.%s", player_base, ext);
- path_build(name, 1024, ANGBAND_DIR_SAVE, tmp);
-
- /* Open the file */
- fff = my_fopen(name, "rb");
-
- if (fff == NULL)
- {
- dun_level = old_dun;
- dungeon_type = old_dungeon_type;
-
- my_fclose(fff);
- return (FALSE);
- }
-
- /* Read the dungeon */
- if (!do_dungeon(LS_LOAD, FALSE))
- {
- dun_level = old_dun;
- dungeon_type = old_dungeon_type;
-
- my_fclose(fff);
- return (FALSE);
- }
-
- dun_level = old_dun;
- dungeon_type = old_dungeon_type;
-
- /* Done */
- my_fclose(fff);
- 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)
-{
- if ((flag == LS_LOAD) && (i >= MAX_FATES)) i = MAX_FATES - 1;
-
- do_byte(&fates[i].fate, flag);
- do_byte(&fates[i].level, flag);
- do_byte(&fates[i].serious, flag);
- do_s16b(&fates[i].o_idx, flag);
- do_s16b(&fates[i].e_idx, flag);
- do_s16b(&fates[i].a_idx, flag);
- do_s16b(&fates[i].v_idx, flag);
- do_s16b(&fates[i].r_idx, flag);
- do_s16b(&fates[i].count, flag);
- do_s16b(&fates[i].time, flag);
- do_byte((byte*)&fates[i].know, flag);
-}
-
-/*
- * Actually read the savefile
- */
-static bool_ do_savefile_aux(int flag)
-{
- int i, j;
-
- byte tmp8u;
- u16b tmp16u;
- u32b tmp32u;
-
- bool_ *reals;
- u16b real_max = 0;
-
- /* Mention the savefile version */
- if (flag == LS_LOAD)
- {
- if (vernum < 100)
- {
- note(format("Savefile version %lu too old! ", vernum));
- return FALSE;
- }
- else
- {
- note(format("Loading version %lu savefile... ", vernum));
- }
- }
- if (flag == LS_SAVE)
- {
- sf_when = time((time_t *) 0); /* Note when file was saved */
- sf_xtra = 0L; /* What the hell is this? */
- sf_saves++; /* Increment the saves ctr */
- }
-
- /* Handle version bytes. FIXME! DG wants me to change this all around */
- if (flag == LS_LOAD)
- {
- u32b mt32b;
- byte mtbyte;
-
- /* Discard all this, we've already read it */
- do_u32b(&mt32b, flag);
- do_byte(&mtbyte, flag);
- }
- if (flag == LS_SAVE)
- {
- u32b saver;
- saver = SAVEFILE_VERSION;
- do_u32b(&saver, flag);
- tmp8u = (byte)rand_int(256);
- do_byte(&tmp8u, flag); /* 'encryption' */
- }
-
- /* Operating system info? Not really. This is just set to 0L */
- do_u32b(&sf_xtra, flag);
-
- /* Time of last save */
- do_u32b(&sf_when, flag);
-
- /* Number of past lives */
- do_u16b(&sf_lives, flag);
-
- /* Number of times saved */
- do_u16b(&sf_saves, flag);
-
- /* Game module */
- if (flag == LS_SAVE)
- strcpy(loaded_game_module, game_module);
- do_string(loaded_game_module, 80, flag);
-
- /* Read RNG state */
- do_randomizer(flag);
- if ((flag == LS_LOAD) && (arg_fiddle)) note("Loaded Randomizer Info");
-
- /* Automatizer state */
- do_byte((byte*)&automatizer_enabled, flag);
-
- /* Then the options */
- do_options(flag);
- if ((flag == LS_LOAD) && (arg_fiddle)) note("Loaded Option Flags");
-
- /* Then the "messages" */
- do_messages(flag);
- if ((flag == LS_LOAD) && (arg_fiddle)) note("Loaded Messages");
-
- /* Monster Memory */
- if (flag == LS_SAVE) tmp16u = max_r_idx;
- do_u16b(&tmp16u, flag);
-
- /* Incompatible save files */
- if ((flag == LS_LOAD) && (tmp16u > max_r_idx))
- {
- note(format("Too many (%u) monster races!", tmp16u));
- return (FALSE);
- }
-
- /* Read the available records */
- for (i = 0; i < tmp16u; i++)
- {
- /* Read the lore */
- do_lore(i, flag);
- }
-
- if ((flag == LS_LOAD) && (arg_fiddle)) note("Loaded Monster Memory");
- /* Object Memory */
- if (flag == LS_SAVE) tmp16u = max_k_idx;
- do_u16b(&tmp16u, flag);
-
- /* Incompatible save files */
- if ((flag == LS_LOAD) && (tmp16u > max_k_idx))
- {
- note(format("Too many (%u) object kinds!", tmp16u));
- return (FALSE);
- }
-
- /* Read the object memory */
- for (i = 0; i < tmp16u; i++) do_xtra(i, flag);
- if ((flag == LS_LOAD) && (arg_fiddle)) note("Loaded Object Memory");
- if (flag == LS_LOAD) junkinit();
-
- {
- u16b max_towns_ldsv;
- u16b max_quests_ldsv;
- if (flag == LS_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))
- {
- note(format("Too many (%u) towns!", max_towns_ldsv));
- return (FALSE);
- }
- /* Min of random towns */
- if (flag == LS_SAVE) max_towns_ldsv = TOWN_RANDOM;
- do_u16b(&max_towns_ldsv, flag);
- /* Incompatible save files */
- if ((flag == LS_LOAD) && (max_towns_ldsv != TOWN_RANDOM))
- {
- note(format("Different random towns base (%u)!", max_towns_ldsv));
- return (FALSE);
- }
-
- for (i = 0; i < max_towns; i++)
- {
- do_byte((byte*)&town_info[i].destroyed, flag);
-
- if (i >= TOWN_RANDOM)
- {
- do_u32b(&town_info[i].seed, flag);
- do_byte(&town_info[i].numstores, 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))
- {
- create_stores_stock(i);
- }
- }
- }
-
- /* Number of dungeon */
- if (flag == LS_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))
- {
- 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;
- do_u16b(&max_quests_ldsv, flag);
- /* Incompatible save files */
- if ((flag == LS_LOAD) && (max_quests_ldsv > TOWN_DUNGEON))
- {
- note(format("Too many town per dungeons (%u)!", max_quests_ldsv));
- return (FALSE);
- }
-
- for (i = 0; i < max_towns_ldsv; i++)
- {
- for (j = 0; j < max_quests_ldsv; j++)
- {
- do_s16b(&(d_info[i].t_idx[j]), flag);
- do_s16b(&(d_info[i].t_level[j]), flag);
- }
- do_s16b(&(d_info[i].t_num), flag);
- }
-
- if (flag == LS_SAVE) max_quests_ldsv = MAX_Q_IDX_INIT;
- /* Number of quests */
- do_u16b(&max_quests_ldsv, flag);
-
- /* Incompatible save files */
- if ((flag == LS_LOAD) && (max_quests_ldsv > MAX_Q_IDX_INIT))
- {
- note(format("Too many (%u) quests!", max_quests_ldsv));
- return (FALSE);
- }
-
- for (i = 0; i < max_quests_ldsv; i++)
- {
- do_s16b(&quest[i].status, flag);
- for (j = 0; j < 4; j++)
- {
- do_s32b(&(quest[i].data[j]), flag);
- }
-
- /* Init the hooks */
- if ((flag == LS_LOAD) && (quest[i].type == HOOK_TYPE_C)) quest[i].init(i);
- }
-
- /* Position in the wilderness */
- do_s32b(&p_ptr->wilderness_x, flag);
- do_s32b(&p_ptr->wilderness_y, flag);
- do_byte((byte*)&p_ptr->wild_mode, flag);
- do_byte((byte*)&p_ptr->old_wild_mode, flag);
-
- {
- s32b wild_x_size, wild_y_size;
- if (flag == LS_SAVE)
- {
- wild_x_size = max_wild_x;
- wild_y_size = max_wild_y;
- }
- /* Size of the wilderness */
- 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)))
- {
- note(format("Wilderness is too big (%u/%u)!",
- wild_x_size, wild_y_size));
- return (FALSE);
- }
- /* Wilderness seeds */
- for (i = 0; i < wild_x_size; i++)
- {
- for (j = 0; j < wild_y_size; j++)
- {
- do_u32b(&wild_map[j][i].seed, flag);
- do_u16b(&wild_map[j][i].entrance, flag);
- do_byte((byte*)&wild_map[j][i].known, flag);
- }
- }
- }
- }
- if ((flag == LS_LOAD) && (arg_fiddle)) note("Loaded Quests");
-
- /* Load the random artifacts. */
- if (flag == LS_SAVE) tmp16u = MAX_RANDARTS;
- do_u16b(&tmp16u, flag);
- if ((flag == LS_LOAD) && (tmp16u > MAX_RANDARTS))
- {
- note(format("Too many (%u) random artifacts!", tmp16u));
- return (FALSE);
- }
- for (i = 0; i < tmp16u; i++)
- {
- random_artifact *ra_ptr = &random_artifacts[i];
-
- do_string(ra_ptr->name_full, 80, flag);
- do_string(ra_ptr->name_short, 80, flag);
- do_byte(&ra_ptr->level, flag);
- do_byte(&ra_ptr->attr, flag);
- do_u32b(&ra_ptr->cost, flag);
- do_byte(&ra_ptr->activation, flag);
- do_byte(&ra_ptr->generated, flag);
- }
-
- /* Load the Artifacts */
- if (flag == LS_SAVE) tmp16u = max_a_idx;
- do_u16b(&tmp16u, flag);
- /* Incompatible save files */
- if ((flag == LS_LOAD) && (tmp16u > max_a_idx))
- {
- note(format("Too many (%u) artifacts!", tmp16u));
- return (FALSE);
- }
-
- /* Read the artifact flags */
- for (i = 0; i < tmp16u; i++)
- {
- do_byte(&(&a_info[i])->cur_num, flag);
- }
- if ((flag == LS_LOAD) && arg_fiddle) note("Loaded Artifacts");
-
- /* Fates */
- if (flag == LS_SAVE) tmp16u = MAX_FATES;
- do_u16b(&tmp16u, flag);
-
- /* Incompatible save files */
- if ((flag == LS_LOAD) && (tmp16u > MAX_FATES))
- {
- note(format("Too many (%u) fates!", tmp16u));
- return (FALSE);
- }
-
- /* Read the fate flags */
- for (i = 0; i < tmp16u; i++)
- {
- do_fate(i, flag);
- }
- if ((flag == LS_LOAD) && arg_fiddle) note("Loaded Fates");
-
- /* Load the Traps */
- if (flag == LS_SAVE) tmp16u = max_t_idx;
- do_u16b(&tmp16u, flag);
-
- /* Incompatible save files */
- if ((flag == LS_LOAD) && (tmp16u > max_t_idx))
- {
- note(format("Too many (%u) traps!", tmp16u));
- return (FALSE);
- }
-
- /* fate flags */
- for (i = 0; i < tmp16u; i++)
- {
- do_byte((byte*)&t_info[i].ident, flag);
- }
- if ((flag == LS_LOAD) && (arg_fiddle)) note("Loaded Traps");
-
- /* inscription knowledge */
- if (flag == LS_SAVE) tmp16u = MAX_INSCRIPTIONS;
- do_u16b(&tmp16u, flag);
-
- /* Incompatible save files */
- if ((flag == LS_LOAD) && (tmp16u > MAX_INSCRIPTIONS))
- {
- note(format("Too many (%u) inscriptions!", tmp16u));
- return (FALSE);
- }
-
- /* Read the inscription flag */
- for (i = 0; i < tmp16u; i++)
- do_byte((byte*)&inscription_info[i].know, flag);
- if ((flag == LS_LOAD) && arg_fiddle) note("Loaded Inscriptions");
-
-
- /* Read the extra stuff */
- if (!do_extra(flag))
- return FALSE;
- if ((flag == LS_LOAD) && arg_fiddle) note("Loaded extra information");
-
-
- /* player_hp array */
- if (flag == LS_SAVE) tmp16u = PY_MAX_LEVEL;
- do_u16b(&tmp16u, flag);
- /* Incompatible save files */
- if ((flag == LS_LOAD) && (tmp16u > PY_MAX_LEVEL))
- {
- note(format("Too many (%u) hitpoint entries!", tmp16u));
- return (FALSE);
- }
-
- /* Read the player_hp array */
- for (i = 0; i < tmp16u; i++)
- {
- do_s16b(&player_hp[i], flag);
- }
-
- if (flag == LS_LOAD) morejunk();
-
- /* Read the pet command settings */
- do_byte(&p_ptr->pet_follow_distance, flag);
- do_byte(&p_ptr->pet_open_doors, flag);
- do_byte(&p_ptr->pet_pickup_items, flag);
-
- /* Read the inventory */
- if (!do_inventory(flag) && (flag == LS_LOAD)) /* do NOT reverse this ordering */
- {
- note("Unable to read inventory");
- return (FALSE);
- }
-
- /* Note that this forbids max_towns from shrinking, but that is fine */
- C_MAKE(reals, max_towns, bool_);
-
- /* Find the real towns */
- if (flag == LS_SAVE)
- {
- for (i = 1; i < max_towns; i++)
- {
- if (!(town_info[i].flags & (TOWN_REAL))) continue;
- reals[real_max++] = i;
- }
- }
- do_u16b(&real_max, flag);
- for (i = 0; i < real_max; i++)
- {
- do_byte((byte*)&reals[i], flag);
- }
-
- /* Read the stores */
- if (flag == LS_SAVE) tmp16u = max_st_idx;
- do_u16b(&tmp16u, flag);
-
- /* Ok now read the real towns */
- for (i = 0; i < real_max; i++)
- {
- int z = reals[i];
-
- /* Ultra paranoia */
- if (!town_info[z].stocked) create_stores_stock(z);
-
- for (j = 0; j < tmp16u; j++)
- do_store(&town_info[z].store[j], flag);
- }
-
- C_FREE(reals, max_towns, bool_);
-
- if (flag == LS_SAVE) tmp32u = extra_savefile_parts;
- do_u32b(&tmp32u, flag);
- if (flag == LS_SAVE)
- {
- /* Save the stuff */
- process_hooks(HOOK_SAVE_GAME, "()");
- }
-
- if (flag == LS_LOAD)
- {
- u32b len = tmp32u;
-
- while (len)
- {
- char key_buf[100];
-
- /* Load a key */
- load_number_key(key_buf, &tmp32u);
-
- /* Process it -- the hooks can use it or ignore it */
- process_hooks(HOOK_LOAD_GAME, "(s,l)", key_buf, tmp32u);
- len--;
- }
- }
-
- /* I'm not dead yet... */
- if (!death)
- {
- /* Dead players have no dungeon */
- if (flag == LS_LOAD) note("Restoring Dungeon...");
- if ((flag == LS_LOAD) && (!do_dungeon(LS_LOAD, FALSE)))
- {
- note("Error reading dungeon data");
- return (FALSE);
- }
- if (flag == LS_SAVE) do_dungeon(LS_SAVE, FALSE);
- my_sentinel("Before ghost data", 435, flag);
- my_sentinel("After ghost data", 320, flag);
- }
-
- {
- byte foo = 0;
- if (flag == LS_SAVE)
- {
- /*
- * Safety Padding. It's there
- * for a good reason. Trust me on
- * this. Keep this at the *END*
- * of the file, and do *NOT* try to
- * read it. Insert any new stuff before
- * this position.
- */
- do_byte(&foo, LS_SAVE);
- }
- }
-
- /* Success */
- return (TRUE);
-}
-
-
-/*
- * Actually read the savefile
- */
-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);
-
- /* Check for errors */
- if (ferror(fff)) err = -1;
-
- /* Close the file */
- my_fclose(fff);
-
- /* Result */
- return (err);
-}
-
-/*
- * 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->arena_number = 0;
- p_ptr->inside_arena = 0;
- p_ptr->inside_quest = 0;
- p_ptr->exit_bldg = TRUE;
- p_ptr->exit_bldg = TRUE;
- 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];
-}
-
-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;
-
- 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_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_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;
-
- 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)
- {
- 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;
-
- case 1:
- case 2:
- case 7:
- do_byte(&prev_char, LS_SAVE);
- break;
- }
- }
- }
- if (flag == LS_LOAD)
- {
- 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;
-
- 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;
-
- 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(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 */
-{
- if (flag == LS_SAVE)
- {
- do_u16b(&value, flag);
- return;
- }
- if (flag == LS_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);
-}
-
-/********** Variable savefile stuff **************/
-
-/*
- * Add num slots to the savefile
- */
-void register_savefile(int num)
-{
- extra_savefile_parts += (num > 0) ? num : 0;
-}
-
-void save_number_key(char *key, u32b val)
-{
- byte len = strlen(key);
-
- do_byte(&len, LS_SAVE);
- while (*key)
- {
- do_byte((byte*)key, LS_SAVE);
- key++;
- }
- do_u32b(&val, LS_SAVE);
-}
-
-void load_number_key(char *key, u32b *val)
-{
- byte len, i = 0;
-
- do_byte(&len, LS_LOAD);
- while (i < len)
- {
- do_byte((byte*)&key[i], LS_LOAD);
- i++;
- }
- key[i] = '\0';
- do_u32b(val, LS_LOAD);
-}