/* File: save.c */
-/* Purpose: interact with savefiles */
-
-#include "angband.h"
-
-
-#ifdef FUTURE_SAVEFILES
-
/*
- * XXX XXX XXX Ignore this for now...
- *
- * The basic format of Angband 2.8.0 (and later) savefiles is simple.
- *
- * The savefile itself is a "header" (4 bytes) plus a series of "blocks",
- * plus, perhaps, some form of "footer" at the end.
- *
- * The "header" contains information about the "version" of the savefile.
- * Conveniently, pre-2.8.0 savefiles also use a 4 byte header, though the
- * interpretation of the "sf_extra" byte is very different. Unfortunately,
- * savefiles from Angband 2.5.X reverse the sf_major and sf_minor fields,
- * and must be handled specially, until we decide to start ignoring them.
- *
- * Each "block" is a "type" (2 bytes), plus a "size" (2 bytes), plus "data",
- * plus a "check" (2 bytes), plus a "stamp" (2 bytes). The format of the
- * "check" and "stamp" bytes is still being contemplated, but it would be
- * nice for one to be a simple byte-checksum, and the other to be a complex
- * additive checksum of some kind. Both should be zero if the block is empty.
- *
- * Standard types:
- * TYPE_BIRTH --> creation info
- * TYPE_OPTIONS --> option settings
- * TYPE_MESSAGES --> message recall
- * TYPE_PLAYER --> player information
- * TYPE_SPELLS --> spell information
- * TYPE_INVEN --> player inven/equip
- * TYPE_STORES --> store information
- * TYPE_RACES --> monster race data
- * TYPE_KINDS --> object kind data
- * TYPE_UNIQUES --> unique info
- * TYPE_ARTIFACTS --> artifact info
- * TYPE_QUESTS --> quest info
- *
- * Dungeon information:
- * TYPE_DUNGEON --> dungeon info
- * TYPE_FEATURES --> dungeon features
- * TYPE_OBJECTS --> dungeon objects
- * TYPE_MONSTERS --> dungeon monsters
+ * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke
*
- * Conversions:
- * Break old "races" into normals/uniques
- * Extract info about the "unique" monsters
- *
- * Question:
- * Should there be a single "block" for info about all the stores, or one
- * "block" for each store? Or one "block", which contains "sub-blocks" of
- * some kind? Should we dump every "sub-block", or just the "useful" ones?
- *
- * Question:
- * Should the normals/uniques be broken for 2.8.0, or should 2.8.0 simply
- * be a "fixed point" into which older savefiles are converted, and then
- * future versions could ignore older savefiles, and the "conversions"
- * would be much simpler.
- */
-
-
-/*
- * XXX XXX XXX
+ * This software may be copied and distributed for educational, research,
+ * and not for profit purposes provided that this copyright and statement
+ * are included in all such copies. Other copyrights may also apply.
*/
-#define TYPE_OPTIONS 17362
-
-
-/*
- * Hack -- current savefile
- */
-static int data_fd = -1;
-
-
-/*
- * Hack -- current block type
- */
-static u16b data_type;
-
-/*
- * Hack -- current block size
- */
-static u16b data_size;
-
-/*
- * Hack -- pointer to the data buffer
- */
-static byte *data_head;
-
-/*
- * Hack -- pointer into the data buffer
- */
-static byte *data_next;
-
-
-
-/*
- * Hack -- write the current "block" to the savefile
- */
-static errr wr_block(void)
-{
- errr err;
-
- byte fake[4];
-
- /* Save the type and size */
- fake[0] = (byte)(data_type);
- fake[1] = (byte)(data_type >> 8);
- fake[2] = (byte)(data_size);
- fake[3] = (byte)(data_size >> 8);
-
- /* Dump the head */
- err = fd_write(data_fd, (char*)&fake, 4);
-
- /* Dump the actual data */
- err = fd_write(data_fd, (char*)data_head, data_size);
-
- /* XXX XXX XXX */
- fake[0] = 0;
- fake[1] = 0;
- fake[2] = 0;
- fake[3] = 0;
-
- /* Dump the tail */
- err = fd_write(data_fd, (char*)&fake, 4);
-
- /* Hack -- reset */
- data_next = data_head;
-
- /* Wipe the data block */
- C_WIPE(data_head, 65535, byte);
-
- /* Success */
- return (0);
-}
-
-
-
-/*
- * Hack -- add data to the current block
- */
-static void put_byte(byte v)
-{
- *data_next++ = v;
-}
-
-/*
- * Hack -- add data to the current block
- */
-static void put_char(char v)
-{
- put_byte((byte)(v));
-}
-
-/*
- * Hack -- add data to the current block
- */
-static void put_u16b(u16b v)
-{
- *data_next++ = (byte)(v);
- *data_next++ = (byte)(v >> 8);
-}
-
-/*
- * Hack -- add data to the current block
- */
-static void put_s16b(s16b v)
-{
- put_u16b((u16b)(v));
-}
-
-/*
- * Hack -- add data to the current block
- */
-static void put_u32b(u32b v)
-{
- *data_next++ = (byte)(v);
- *data_next++ = (byte)(v >> 8);
- *data_next++ = (byte)(v >> 16);
- *data_next++ = (byte)(v >> 24);
-}
-
-/*
- * Hack -- add data to the current block
- */
-static void put_s32b(s32b v)
-{
- put_u32b((u32b)(v));
-}
-
-/*
- * Hack -- add data to the current block
- */
-static void put_string(char *str)
-{
- while ((*data_next++ = *str++) != '\0');
-}
-
-
-
-/*
- * Write a savefile for Angband 2.8.0
- */
-static errr wr_savefile(void)
-{
- int i;
-
- u32b now;
-
- byte tmp8u;
- u16b tmp16u;
-
- errr err;
-
- byte fake[4];
-
-
- /*** Hack -- extract some data ***/
-
- /* Hack -- Acquire the current time */
- now = time((time_t*)(NULL));
-
- /* Note the operating system */
- sf_xtra = 0L;
-
- /* Note when the file was saved */
- sf_when = now;
-
- /* Note the number of saves */
- sf_saves++;
-
-
- /*** Actually write the file ***/
-
- /* Open the file XXX XXX XXX */
- data_fd = -1;
-
- /* Dump the version */
- fake[0] = (byte)(FAKE_VER_MAJOR);
- fake[1] = (byte)(FAKE_VER_MINOR);
- fake[2] = (byte)(FAKE_VER_PATCH);
- fake[3] = (byte)(VERSION_EXTRA);
-
-
- /* Dump the data */
- err = fd_write(data_fd, (char*)&fake, 4);
-
-
- /* Make array XXX XXX XXX */
- C_MAKE(data_head, 65535, byte);
-
- /* Hack -- reset */
- data_next = data_head;
-
- /* Dump the "options" */
- put_options();
-
- /* Set the type */
- data_type = TYPE_OPTIONS;
-
- /* Set the "options" size */
- data_size = (data_next - data_head);
-
- /* Write the block */
- wr_block();
-
- /* XXX XXX XXX */
-
- /* Dump the "final" marker XXX XXX XXX */
- /* Type zero, Size zero, Contents zero, etc */
-
-
- /* XXX XXX XXX Check for errors */
-
-
- /* Kill array XXX XXX XXX */
- C_KILL(data_head, 65535, byte);
-
-
- /* Success */
- return (0);
-}
-
-
-
-
-
-/*
- * Hack -- read the next "block" from the savefile
- */
-static errr rd_block(void)
-{
- errr err;
-
- byte fake[4];
-
- /* Read the head data */
- err = fd_read(data_fd, (char*)&fake, 4);
-
- /* Extract the type and size */
- data_type = (fake[0] | ((u16b)fake[1] << 8));
- data_size = (fake[2] | ((u16b)fake[3] << 8));
-
- /* Wipe the data block */
- C_WIPE(data_head, 65535, byte);
-
- /* Read the actual data */
- err = fd_read(data_fd, (char*)data_head, data_size);
-
- /* Read the tail data */
- err = fd_read(data_fd, (char*)&fake, 4);
-
- /* XXX XXX XXX Verify */
-
- /* Hack -- reset */
- data_next = data_head;
-
- /* Success */
- return (0);
-}
-
-
-/*
- * Hack -- get data from the current block
- */
-static void get_byte(byte *ip)
-{
- byte d1;
- d1 = (*data_next++);
- (*ip) = (d1);
-}
-
-/*
- * Hack -- get data from the current block
- */
-static void get_char(char *ip)
-{
- get_byte((byte*)ip);
-}
-
-/*
- * Hack -- get data from the current block
- */
-static void get_u16b(u16b *ip)
-{
- u16b d0, d1;
- d0 = (*data_next++);
- d1 = (*data_next++);
- (*ip) = (d0 | (d1 << 8));
-}
-
-/*
- * Hack -- get data from the current block
- */
-static void get_s16b(s16b *ip)
-{
- get_u16b((u16b*)ip);
-}
-/*
- * Hack -- get data from the current block
- */
-static void get_u32b(u32b *ip)
-{
- u32b d0, d1, d2, d3;
- d0 = (*data_next++);
- d1 = (*data_next++);
- d2 = (*data_next++);
- d3 = (*data_next++);
- (*ip) = (d0 | (d1 << 8) | (d2 << 16) | (d3 << 24));
-}
-
-/*
- * Hack -- get data from the current block
- */
-static void get_s32b(s32b *ip)
-{
- get_u32b((u32b*)ip);
-}
-
-
-
-/*
- * Read a savefile for Angband 2.8.0
- */
-static errr rd_savefile(void)
-{
- bool done = FALSE;
-
- byte fake[4];
-
-
- /* Open the savefile */
- data_fd = fd_open(savefile, O_RDONLY);
-
- /* No file */
- if (data_fd < 0) return (1);
-
- /* Strip the first four bytes (see below) */
- if (fd_read(data_fd, (char*)(fake), 4)) return (1);
-
-
- /* Make array XXX XXX XXX */
- C_MAKE(data_head, 65535, byte);
-
- /* Hack -- reset */
- data_next = data_head;
-
-
- /* Read blocks */
- while (!done)
- {
- /* Read the block */
- if (rd_block()) break;
-
- /* Analyze the type */
- switch (data_type)
- {
- /* Done XXX XXX XXX */
- case 0:
- {
- done = TRUE;
- break;
- }
-
- /* Grab the options */
- case TYPE_OPTIONS:
- {
- if (get_options()) err = -1;
- break;
- }
- }
-
- /* XXX XXX XXX verify "data_next" */
- if (data_next - data_head > data_size) break;
- }
-
-
- /* XXX XXX XXX Check for errors */
-
-
- /* Kill array XXX XXX XXX */
- C_KILL(data_head, 65535, byte);
-
-
- /* Success */
- return (0);
-}
-
-
-#endif /* FUTURE_SAVEFILES */
+/* Purpose: interact with savefiles */
+#include "angband.h"
*/
static void wr_item(object_type *o_ptr)
{
+ u32b flags = 0x00000000;
+
+ if (o_ptr->pval) flags |= SAVE_ITEM_PVAL;
+ if (o_ptr->discount) flags |= SAVE_ITEM_DISCOUNT;
+ if (o_ptr->number != 1) flags |= SAVE_ITEM_NUMBER;
+ if (o_ptr->name1) flags |= SAVE_ITEM_NAME1;
+ if (o_ptr->name2) flags |= SAVE_ITEM_NAME2;
+ if (o_ptr->timeout) flags |= SAVE_ITEM_TIMEOUT;
+ if (o_ptr->to_h) flags |= SAVE_ITEM_TO_H;
+ if (o_ptr->to_d) flags |= SAVE_ITEM_TO_D;
+ if (o_ptr->to_a) flags |= SAVE_ITEM_TO_A;
+ if (o_ptr->ac) flags |= SAVE_ITEM_AC;
+ if (o_ptr->dd) flags |= SAVE_ITEM_DD;
+ if (o_ptr->ds) flags |= SAVE_ITEM_DS;
+ if (o_ptr->ident) flags |= SAVE_ITEM_IDENT;
+ if (o_ptr->marked) flags |= SAVE_ITEM_MARKED;
+ if (o_ptr->art_flags[0]) flags |= SAVE_ITEM_ART_FLAGS0;
+ if (o_ptr->art_flags[1]) flags |= SAVE_ITEM_ART_FLAGS1;
+ if (o_ptr->art_flags[2]) flags |= SAVE_ITEM_ART_FLAGS2;
+ if (o_ptr->art_flags[3]) flags |= SAVE_ITEM_ART_FLAGS3;
+ if (o_ptr->curse_flags) flags |= SAVE_ITEM_CURSE_FLAGS;
+ if (o_ptr->held_m_idx) flags |= SAVE_ITEM_HELD_M_IDX;
+ if (o_ptr->xtra1) flags |= SAVE_ITEM_XTRA1;
+ if (o_ptr->xtra2) flags |= SAVE_ITEM_XTRA2;
+ if (o_ptr->xtra3) flags |= SAVE_ITEM_XTRA3;
+ if (o_ptr->xtra4) flags |= SAVE_ITEM_XTRA4;
+ if (o_ptr->xtra5) flags |= SAVE_ITEM_XTRA5;
+ if (o_ptr->feeling) flags |= SAVE_ITEM_FEELING;
+ if (o_ptr->inscription) flags |= SAVE_ITEM_INSCRIPTION;
+ if (o_ptr->art_name) flags |= SAVE_ITEM_ART_NAME;
+
+ /*** Item save flags ***/
+ wr_u32b(flags);
+
+ /*** Write only un-obvious elements ***/
wr_s16b(o_ptr->k_idx);
/* Location */
wr_byte(o_ptr->iy);
wr_byte(o_ptr->ix);
- wr_byte(o_ptr->tval);
- wr_byte(o_ptr->sval);
- wr_s16b(o_ptr->pval);
+ if (flags & SAVE_ITEM_PVAL) wr_s16b(o_ptr->pval);
+
+ if (flags & SAVE_ITEM_DISCOUNT) wr_byte(o_ptr->discount);
+ if (flags & SAVE_ITEM_NUMBER) wr_byte(o_ptr->number);
- wr_byte(o_ptr->discount);
- wr_byte(o_ptr->number);
wr_s16b(o_ptr->weight);
- wr_byte(o_ptr->name1);
- wr_byte(o_ptr->name2);
- wr_s16b(o_ptr->timeout);
+ if (flags & SAVE_ITEM_NAME1) wr_byte(o_ptr->name1);
+ if (flags & SAVE_ITEM_NAME2) wr_byte(o_ptr->name2);
+ if (flags & SAVE_ITEM_TIMEOUT) wr_s16b(o_ptr->timeout);
- wr_s16b(o_ptr->to_h);
- wr_s16b(o_ptr->to_d);
- wr_s16b(o_ptr->to_a);
- wr_s16b(o_ptr->ac);
- wr_byte(o_ptr->dd);
- wr_byte(o_ptr->ds);
+ if (flags & SAVE_ITEM_TO_H) wr_s16b(o_ptr->to_h);
+ if (flags & SAVE_ITEM_TO_D) wr_s16b(o_ptr->to_d);
+ if (flags & SAVE_ITEM_TO_A) wr_s16b(o_ptr->to_a);
+ if (flags & SAVE_ITEM_AC) wr_s16b(o_ptr->ac);
+ if (flags & SAVE_ITEM_DD) wr_byte(o_ptr->dd);
+ if (flags & SAVE_ITEM_DS) wr_byte(o_ptr->ds);
- wr_byte(o_ptr->ident);
+ if (flags & SAVE_ITEM_IDENT) wr_byte(o_ptr->ident);
- wr_byte(o_ptr->marked);
+ if (flags & SAVE_ITEM_MARKED) wr_byte(o_ptr->marked);
- wr_u32b(o_ptr->art_flags1);
- wr_u32b(o_ptr->art_flags2);
- wr_u32b(o_ptr->art_flags3);
+ if (flags & SAVE_ITEM_ART_FLAGS0) wr_u32b(o_ptr->art_flags[0]);
+ if (flags & SAVE_ITEM_ART_FLAGS1) wr_u32b(o_ptr->art_flags[1]);
+ if (flags & SAVE_ITEM_ART_FLAGS2) wr_u32b(o_ptr->art_flags[2]);
+ if (flags & SAVE_ITEM_ART_FLAGS3) wr_u32b(o_ptr->art_flags[3]);
- wr_u32b(o_ptr->curse_flags);
+ if (flags & SAVE_ITEM_CURSE_FLAGS) wr_u32b(o_ptr->curse_flags);
/* Held by monster index */
- wr_s16b(o_ptr->held_m_idx);
+ if (flags & SAVE_ITEM_HELD_M_IDX) wr_s16b(o_ptr->held_m_idx);
/* Extra information */
- wr_byte(o_ptr->xtra1);
- wr_byte(o_ptr->xtra2);
- wr_byte(o_ptr->xtra3);
- wr_s16b(o_ptr->xtra4);
- wr_s16b(o_ptr->xtra5);
+ if (flags & SAVE_ITEM_XTRA1) wr_byte(o_ptr->xtra1);
+ if (flags & SAVE_ITEM_XTRA2) wr_byte(o_ptr->xtra2);
+ if (flags & SAVE_ITEM_XTRA3) wr_byte(o_ptr->xtra3);
+ if (flags & SAVE_ITEM_XTRA4) wr_s16b(o_ptr->xtra4);
+ if (flags & SAVE_ITEM_XTRA5) wr_s16b(o_ptr->xtra5);
/* Feelings */
- wr_byte(o_ptr->feeling);
-
- /* Save the inscription (if any) */
- if (o_ptr->inscription)
- {
- wr_string(quark_str(o_ptr->inscription));
- }
- else
- {
- wr_string("");
- }
+ if (flags & SAVE_ITEM_FEELING) wr_byte(o_ptr->feeling);
- /* If it is a "new" named artifact, save the name */
- if (o_ptr->art_name)
- {
- wr_string(quark_str(o_ptr->art_name));
- }
- else
- {
- wr_string("");
- }
-
- /* No Python object */
- wr_s32b(0);
+ if (flags & SAVE_ITEM_INSCRIPTION) wr_string(quark_str(o_ptr->inscription));
+ if (flags & SAVE_ITEM_ART_NAME) wr_string(quark_str(o_ptr->art_name));
}
*/
static void wr_monster(monster_type *m_ptr)
{
+ u32b flags = 0x00000000;
+ byte tmp8u;
+
+ if (!is_original_ap(m_ptr)) flags |= SAVE_MON_AP_R_IDX;
+ if (m_ptr->sub_align) flags |= SAVE_MON_SUB_ALIGN;
+ if (MON_CSLEEP(m_ptr)) flags |= SAVE_MON_CSLEEP;
+ if (MON_FAST(m_ptr)) flags |= SAVE_MON_FAST;
+ if (MON_SLOW(m_ptr)) flags |= SAVE_MON_SLOW;
+ if (MON_STUNNED(m_ptr)) flags |= SAVE_MON_STUNNED;
+ if (MON_CONFUSED(m_ptr)) flags |= SAVE_MON_CONFUSED;
+ if (MON_MONFEAR(m_ptr)) flags |= SAVE_MON_MONFEAR;
+ if (m_ptr->target_y) flags |= SAVE_MON_TARGET_Y;
+ if (m_ptr->target_x) flags |= SAVE_MON_TARGET_X;
+ if (MON_INVULNER(m_ptr)) flags |= SAVE_MON_INVULNER;
+ if (m_ptr->smart) flags |= SAVE_MON_SMART;
+ if (m_ptr->exp) flags |= SAVE_MON_EXP;
+ if (m_ptr->mflag2) flags |= SAVE_MON_MFLAG2;
+ if (m_ptr->nickname) flags |= SAVE_MON_NICKNAME;
+ if (m_ptr->parent_m_idx) flags |= SAVE_MON_PARENT;
+
+ /*** Monster save flags ***/
+ wr_u32b(flags);
+
+ /*** Write only un-obvious elements ***/
wr_s16b(m_ptr->r_idx);
- wr_s16b(m_ptr->ap_r_idx);
- wr_byte(m_ptr->sub_align);
wr_byte(m_ptr->fy);
wr_byte(m_ptr->fx);
wr_s16b(m_ptr->hp);
wr_s16b(m_ptr->maxhp);
wr_s16b(m_ptr->max_maxhp);
- wr_s16b(m_ptr->csleep);
+
+ /* Monster race index of its appearance */
+ if (flags & SAVE_MON_AP_R_IDX) wr_s16b(m_ptr->ap_r_idx);
+
+ if (flags & SAVE_MON_SUB_ALIGN) wr_byte(m_ptr->sub_align);
+ if (flags & SAVE_MON_CSLEEP) wr_s16b(m_ptr->mtimed[MTIMED_CSLEEP]);
+
wr_byte(m_ptr->mspeed);
wr_s16b(m_ptr->energy_need);
- wr_byte(m_ptr->fast);
- wr_byte(m_ptr->slow);
- wr_byte(m_ptr->stunned);
- wr_byte(m_ptr->confused);
- wr_byte(m_ptr->monfear);
- wr_s16b(m_ptr->target_y);
- wr_s16b(m_ptr->target_x);
- wr_byte(m_ptr->invulner);
- wr_u32b(m_ptr->smart);
- wr_u32b(m_ptr->exp);
- wr_byte(m_ptr->mflag2);
- if (m_ptr->nickname)
+
+ if (flags & SAVE_MON_FAST)
{
- wr_string(quark_str(m_ptr->nickname));
+ tmp8u = (byte)m_ptr->mtimed[MTIMED_FAST];
+ wr_byte(tmp8u);
}
- else
+ if (flags & SAVE_MON_SLOW)
{
- wr_string("");
+ tmp8u = (byte)m_ptr->mtimed[MTIMED_SLOW];
+ wr_byte(tmp8u);
}
- wr_byte(0);
+ if (flags & SAVE_MON_STUNNED)
+ {
+ tmp8u = (byte)m_ptr->mtimed[MTIMED_STUNNED];
+ wr_byte(tmp8u);
+ }
+ if (flags & SAVE_MON_CONFUSED)
+ {
+ tmp8u = (byte)m_ptr->mtimed[MTIMED_CONFUSED];
+ wr_byte(tmp8u);
+ }
+ if (flags & SAVE_MON_MONFEAR)
+ {
+ tmp8u = (byte)m_ptr->mtimed[MTIMED_MONFEAR];
+ wr_byte(tmp8u);
+ }
+ if (flags & SAVE_MON_TARGET_Y) wr_s16b(m_ptr->target_y);
+ if (flags & SAVE_MON_TARGET_X) wr_s16b(m_ptr->target_x);
+ if (flags & SAVE_MON_INVULNER)
+ {
+ tmp8u = (byte)m_ptr->mtimed[MTIMED_INVULNER];
+ wr_byte(tmp8u);
+ }
+ if (flags & SAVE_MON_SMART) wr_u32b(m_ptr->smart);
+ if (flags & SAVE_MON_EXP) wr_u32b(m_ptr->exp);
+ if (flags & SAVE_MON_MFLAG2) wr_byte(m_ptr->mflag2);
+ if (flags & SAVE_MON_NICKNAME) wr_string(quark_str(m_ptr->nickname));
+ if (flags & SAVE_MON_PARENT) wr_s16b(m_ptr->parent_m_idx);
}
wr_s16b(r_ptr->r_sights);
wr_s16b(r_ptr->r_deaths);
wr_s16b(r_ptr->r_pkills);
+ wr_s16b(r_ptr->r_akills);
wr_s16b(r_ptr->r_tkills);
/* Count wakes and ignores */
wr_byte(r_ptr->r_drop_item);
/* Count spells */
- wr_byte(r_ptr->r_cast_inate);
+ wr_byte(0); /* unused now */
wr_byte(r_ptr->r_cast_spell);
/* Count blows of each type */
wr_u32b(r_ptr->r_flags4);
wr_u32b(r_ptr->r_flags5);
wr_u32b(r_ptr->r_flags6);
+ wr_u32b(r_ptr->r_flagsr);
/* Monster limit per level */
wr_byte(r_ptr->max_num);
+ /* Location in saved floor */
+ wr_s16b(r_ptr->floor_id);
+
/* Later (?) */
wr_byte(0);
- wr_byte(0);
- wr_byte(0);
}
/* Write "hitpoint_warn" */
wr_byte(hitpoint_warn);
+ /* Write "mana_warn" */
+ wr_byte(mana_warn);
/*** Cheating options ***/
c = 0;
- if (wizard) c |= 0x0002;
+ if (p_ptr->wizard) c |= 0x0002;
if (cheat_peek) c |= 0x0100;
if (cheat_hear) c |= 0x0200;
if (cheat_xtra) c |= 0x0800;
if (cheat_know) c |= 0x1000;
if (cheat_live) c |= 0x2000;
+ if (cheat_save) c |= 0x4000;
wr_u16b(c);
for (i = 0; i < 4; i++) wr_string(previous_char.history[i]);
- wr_byte(previous_char.quests);
+ /* UNUSED : Was number of random quests */
+ wr_byte(0);
+
+ /* No quick start after using debug mode or cheat options */
+ if (p_ptr->noscore) previous_char.quick_ok = FALSE;
+
wr_byte((byte)previous_char.quick_ok);
}
wr_string(player_name);
- wr_string(died_from);
+ wr_string(p_ptr->died_from);
+
+ wr_string(p_ptr->last_message ? p_ptr->last_message : "");
save_quick_start();
for (i = 0; i < 4; i++)
{
- wr_string(history[i]);
+ wr_string(p_ptr->history[i]);
}
/* Race/Class/Gender/Spells */
wr_u32b(p_ptr->au);
wr_u32b(p_ptr->max_exp);
+ wr_u32b(p_ptr->max_max_exp);
wr_u32b(p_ptr->exp);
- wr_u16b(p_ptr->exp_frac);
+ wr_u32b(p_ptr->exp_frac);
wr_s16b(p_ptr->lev);
- for (i = 0; i < 64; i++) wr_s16b(spell_exp[i]);
- for (i = 0; i < 5; i++) for (j = 0; j < 64; j++) wr_s16b(weapon_exp[i][j]);
- for (i = 0; i < 10; i++) wr_s16b(skill_exp[i]);
+ for (i = 0; i < 64; i++) wr_s16b(p_ptr->spell_exp[i]);
+ for (i = 0; i < 5; i++) for (j = 0; j < 64; j++) wr_s16b(p_ptr->weapon_exp[i][j]);
+ for (i = 0; i < 10; i++) wr_s16b(p_ptr->skill_exp[i]);
for (i = 0; i < 108; i++) wr_s32b(p_ptr->magic_num1[i]);
for (i = 0; i < 108; i++) wr_byte(p_ptr->magic_num2[i]);
for (i = 0; i < MAX_MANE; i++)
{
- wr_s16b(mane_spell[i]);
- wr_s16b(mane_dam[i]);
+ wr_s16b(p_ptr->mane_spell[i]);
+ wr_s16b(p_ptr->mane_dam[i]);
}
- wr_s16b(mane_num);
+ wr_s16b(p_ptr->mane_num);
for (i = 0; i < MAX_KUBI; i++)
{
wr_s16b(p_ptr->inside_quest);
wr_s16b(p_ptr->inside_battle);
wr_byte(p_ptr->exit_bldg);
- wr_byte(p_ptr->leftbldg); /* save building leave status -KMW- */
+ wr_byte(0); /* Unused */
wr_s16b(p_ptr->oldpx);
wr_s16b(p_ptr->oldpy);
- /* Save builing rewards */
- wr_s16b(MAX_BACT);
+ /* Was number of p_ptr->rewards[] */
+ wr_s16b(0);
- for (i = 0; i < MAX_BACT; i++) wr_s16b(p_ptr->rewards[i]);
+ wr_s32b(p_ptr->mhp);
+ wr_s32b(p_ptr->chp);
+ wr_u32b(p_ptr->chp_frac);
- wr_s16b(p_ptr->mhp);
- wr_s16b(p_ptr->chp);
- wr_u16b(p_ptr->chp_frac);
-
- wr_s16b(p_ptr->msp);
- wr_s16b(p_ptr->csp);
- wr_u16b(p_ptr->csp_frac);
+ wr_s32b(p_ptr->msp);
+ wr_s32b(p_ptr->csp);
+ wr_u32b(p_ptr->csp_frac);
/* Max Player and Dungeon Levels */
wr_s16b(p_ptr->max_plv);
- tmp8u = (byte)max_d_idx;
- wr_byte(tmp8u);
- for (i = 0; i < tmp8u; i++)
- wr_s16b(max_dlv[i]);
+ tmp8u = (byte)max_d_idx;
+ wr_byte(tmp8u);
+ for (i = 0; i < tmp8u; i++)
+ wr_s16b(max_dlv[i]);
/* More info */
wr_s16b(0); /* oops */
wr_s16b(p_ptr->blessed);
wr_s16b(p_ptr->tim_invis);
wr_s16b(p_ptr->word_recall);
- wr_s16b(p_ptr->recall_dungeon);
+ wr_s16b(p_ptr->recall_dungeon);
+ wr_s16b(p_ptr->alter_reality);
wr_s16b(p_ptr->see_infra);
wr_s16b(p_ptr->tim_infra);
wr_s16b(p_ptr->oppose_fire);
wr_s16b(p_ptr->tim_regen);
wr_s16b(p_ptr->kabenuke);
wr_s16b(p_ptr->tim_stealth);
- wr_s16b(p_ptr->tim_ffall);
+ wr_s16b(p_ptr->tim_levitation);
wr_s16b(p_ptr->tim_sh_touki);
wr_s16b(p_ptr->lightspeed);
wr_s16b(p_ptr->tsubureru);
wr_s16b(p_ptr->ele_immune);
wr_u32b(p_ptr->special_defense);
wr_byte(p_ptr->knowledge);
- wr_byte(0); /* oops */
+ wr_byte(p_ptr->autopick_autoregister);
wr_byte(0); /* oops */
wr_byte(p_ptr->action);
wr_byte(0);
wr_byte(preserve_mode);
- wr_byte(wait_report_score);
+ wr_byte(p_ptr->wait_report_score);
/* Future use */
for (i = 0; i < 12; i++) wr_u32b(0L);
/* Special stuff */
- wr_u16b(panic_save);
- wr_u16b(total_winner);
- wr_u16b(noscore);
+ wr_u16b(p_ptr->panic_save);
+ wr_u16b(p_ptr->total_winner);
+ wr_u16b(p_ptr->noscore);
/* Write death */
- wr_byte(death);
+ wr_byte(p_ptr->is_dead);
/* Write feeling */
- wr_byte(feeling);
+ wr_byte(p_ptr->feeling);
- /* Turn of last "feeling" */
+ /* Turn when level began */
wr_s32b(old_turn);
+ /* Turn of last "feeling" */
+ wr_s32b(p_ptr->feeling_turn);
+
/* Current turn */
wr_s32b(turn);
wr_s16b(p_ptr->today_mon);
wr_s16b(p_ptr->riding);
+ /* Current floor_id */
+ wr_s16b(p_ptr->floor_id);
+
+ /* Save temporary preserved pets (obsolated) */
+ wr_s16b(0);
+
wr_u32b(playtime);
wr_s32b(p_ptr->visit);
/*
- * Write the current dungeon
+ * hook function to sort monsters by level
*/
-static void wr_dungeon(void)
+static bool ang_sort_comp_cave_temp(vptr u, vptr v, int a, int b)
{
- int i, y, x;
-
- byte tmp8u;
- u16b tmp16u;
+ cave_template_type *who = (cave_template_type *)(u);
- byte count;
- byte prev_char;
- s16b prev_s16b;
+ u16b o1 = who[a].occurrence;
+ u16b o2 = who[b].occurrence;
- cave_type *c_ptr;
+ /* Unused */
+ (void)v;
+ return o2 <= o1;
+}
- /*** Basic info ***/
- /* Dungeon specific info follows */
- wr_u16b(dun_level);
- wr_byte(dungeon_type);
- wr_u16b(base_level);
- wr_u16b(num_repro);
- wr_u16b((u16b)py);
- wr_u16b((u16b)px);
- wr_u16b(cur_hgt);
- wr_u16b(cur_wid);
- wr_u16b(0); /* max_panel_rows */
- wr_u16b(0); /* max_panel_cols */
+/*
+ * Sorting hook -- Swap function
+ */
+static void ang_sort_swap_cave_temp(vptr u, vptr v, int a, int b)
+{
+ cave_template_type *who = (cave_template_type *)(u);
+ cave_template_type holder;
- /*** Simple "Run-Length-Encoding" of cave ***/
+ /* Unused */
+ (void)v;
- /* Note that this will induce two wasted bytes */
- count = 0;
- prev_s16b = 0;
+ /* Swap */
+ holder = who[a];
+ who[a] = who[b];
+ who[b] = holder;
+}
- /* Dump the cave */
- for (y = 0; y < cur_hgt; y++)
- {
- for (x = 0; x < cur_wid; x++)
- {
- /* Get the cave */
- c_ptr = &cave[y][x];
- /* Extract a byte */
- tmp16u = c_ptr->info;
+/*
+ * Actually write a saved floor data
+ * using effectively compressed format.
+ */
+static void wr_saved_floor(saved_floor_type *sf_ptr)
+{
+ cave_template_type *template;
+ u16b max_num_temp;
+ u16b num_temp = 0;
+ int dummy_why;
- /* If the run is broken, or too full, flush it */
- if ((tmp16u != prev_s16b) || (count == MAX_UCHAR))
- {
- wr_byte((byte)count);
- wr_u16b((u16b)prev_s16b);
- prev_s16b = tmp16u;
- count = 1;
- }
+ int i, y, x;
- /* Continue the run */
- else
- {
- count++;
- }
- }
- }
+ u16b tmp16u;
- /* Flush the data (if any) */
- if (count)
- {
- wr_byte((byte)count);
- wr_u16b((byte)prev_s16b);
- }
+ byte count;
+ u16b prev_u16b;
- /*** Simple "Run-Length-Encoding" of cave ***/
+ /*** Basic info ***/
- /* Note that this will induce two wasted bytes */
- count = 0;
- prev_char = 0;
+ /* Dungeon floor specific info follows */
- /* Dump the cave */
- for (y = 0; y < cur_hgt; y++)
+ if (!sf_ptr)
{
- for (x = 0; x < cur_wid; x++)
- {
- /* Get the cave */
- c_ptr = &cave[y][x];
-
- /* Extract a byte */
- tmp8u = c_ptr->feat;
-
- /* If the run is broken, or too full, flush it */
- if ((tmp8u != prev_char) || (count == MAX_UCHAR))
- {
- wr_byte((byte)count);
- wr_byte((byte)prev_char);
- prev_char = tmp8u;
- count = 1;
- }
+ /*** Not a saved floor ***/
- /* Continue the run */
- else
- {
- count++;
- }
- }
+ wr_s16b(dun_level);
}
-
- /* Flush the data (if any) */
- if (count)
+ else
{
- wr_byte((byte)count);
- wr_byte((byte)prev_char);
+ /*** The saved floor ***/
+
+ wr_s16b(sf_ptr->floor_id);
+ wr_byte(sf_ptr->savefile_id);
+ wr_s16b(sf_ptr->dun_level);
+ wr_s32b(sf_ptr->last_visit);
+ wr_u32b(sf_ptr->visit_mark);
+ wr_s16b(sf_ptr->upper_floor_id);
+ wr_s16b(sf_ptr->lower_floor_id);
}
+ wr_u16b(base_level);
+ wr_u16b(num_repro);
+ wr_u16b((u16b)py);
+ wr_u16b((u16b)px);
+ wr_u16b(cur_hgt);
+ wr_u16b(cur_wid);
+ wr_byte(p_ptr->feeling);
+
- /*** Simple "Run-Length-Encoding" of cave ***/
- /* Note that this will induce two wasted bytes */
- count = 0;
- prev_char = 0;
+ /*********** Make template for cave_type **********/
- /* Dump the cave */
+ /*
+ * Usually number of templates are fewer than 255. Even if
+ * more than 254 are exist, the occurrence of each template
+ * with larger ID is very small when we sort templates by
+ * occurrence. So we will use two (or more) bytes for
+ * templete ID larger than 254.
+ *
+ * Ex: 256 will be "0xff" "0x01".
+ * 515 will be "0xff" "0xff" "0x03"
+ */
+
+ /* Fake max number */
+ max_num_temp = 255;
+
+ /* Allocate the "template" array */
+ C_MAKE(template, max_num_temp, cave_template_type);
+
+ /* Extract template array */
for (y = 0; y < cur_hgt; y++)
{
for (x = 0; x < cur_wid; x++)
{
- /* Get the cave */
- c_ptr = &cave[y][x];
+ cave_type *c_ptr = &cave[y][x];
- /* Extract a byte */
- tmp8u = c_ptr->mimic;
-
- /* If the run is broken, or too full, flush it */
- if ((tmp8u != prev_char) || (count == MAX_UCHAR))
+ for (i = 0; i < num_temp; i++)
{
- wr_byte((byte)count);
- wr_byte((byte)prev_char);
- prev_char = tmp8u;
- count = 1;
+ if (template[i].info == c_ptr->info &&
+ template[i].feat == c_ptr->feat &&
+ template[i].mimic == c_ptr->mimic &&
+ template[i].special == c_ptr->special)
+ {
+ /* Same terrain is exist */
+ template[i].occurrence++;
+ break;
+ }
}
- /* Continue the run */
- else
+ /* Are there same one? */
+ if (i < num_temp) continue;
+
+ /* If the max_num_temp is too small, increase it. */
+ if (num_temp >= max_num_temp)
{
- count++;
+ cave_template_type *old_template = template;
+
+ /* Re-allocate the "template" array */
+ C_MAKE(template, max_num_temp + 255, cave_template_type);
+ C_COPY(template, old_template, max_num_temp, cave_template_type);
+ C_FREE(old_template, max_num_temp, cave_template_type);
+ max_num_temp += 255;
}
+
+ /* Add new template */
+ template[num_temp].info = c_ptr->info;
+ template[num_temp].feat = c_ptr->feat;
+ template[num_temp].mimic = c_ptr->mimic;
+ template[num_temp].special = c_ptr->special;
+ template[num_temp].occurrence = 1;
+
+ /* Increase number of template */
+ num_temp++;
}
}
- /* Flush the data (if any) */
- if (count)
+ /* Select the sort method */
+ ang_sort_comp = ang_sort_comp_cave_temp;
+ ang_sort_swap = ang_sort_swap_cave_temp;
+
+ /* Sort by occurrence */
+ ang_sort(template, &dummy_why, num_temp);
+
+
+ /*** Dump templates ***/
+
+ /* Total templates */
+ wr_u16b(num_temp);
+
+ /* Dump the templates */
+ for (i = 0; i < num_temp; i++)
{
- wr_byte((byte)count);
- wr_byte((byte)prev_char);
+ cave_template_type *ct_ptr = &template[i];
+
+ /* Dump it */
+ wr_u16b(ct_ptr->info);
+ wr_s16b(ct_ptr->feat);
+ wr_s16b(ct_ptr->mimic);
+ wr_s16b(ct_ptr->special);
}
- /*** Simple "Run-Length-Encoding" of cave ***/
+
+ /*** "Run-Length-Encoding" of cave ***/
/* Note that this will induce two wasted bytes */
count = 0;
- prev_s16b = 0;
+ prev_u16b = 0;
/* Dump the cave */
for (y = 0; y < cur_hgt; y++)
{
for (x = 0; x < cur_wid; x++)
{
- /* Get the cave */
- c_ptr = &cave[y][x];
+ cave_type *c_ptr = &cave[y][x];
- /* Extract a byte */
- tmp16u = c_ptr->special;
+ for (i = 0; i < num_temp; i++)
+ {
+ if (template[i].info == c_ptr->info &&
+ template[i].feat == c_ptr->feat &&
+ template[i].mimic == c_ptr->mimic &&
+ template[i].special == c_ptr->special)
+ break;
+ }
+
+ /* Extract an ID */
+ tmp16u = i;
/* If the run is broken, or too full, flush it */
- if ((tmp16u != prev_s16b) || (count == MAX_UCHAR))
+ if ((tmp16u != prev_u16b) || (count == MAX_UCHAR))
{
wr_byte((byte)count);
- wr_u16b(prev_s16b);
- prev_s16b = tmp16u;
+
+ while (prev_u16b >= MAX_UCHAR)
+ {
+ /* Mark as actual data is larger than 254 */
+ wr_byte(MAX_UCHAR);
+ prev_u16b -= MAX_UCHAR;
+ }
+
+ wr_byte((byte)prev_u16b);
+ prev_u16b = tmp16u;
count = 1;
}
if (count)
{
wr_byte((byte)count);
- wr_u16b(prev_s16b);
+
+ while (prev_u16b >= MAX_UCHAR)
+ {
+ /* Mark as actual data is larger than 254 */
+ wr_byte(MAX_UCHAR);
+ prev_u16b -= MAX_UCHAR;
+ }
+ wr_byte((byte)prev_u16b);
}
+ /* Free the "template" array */
+ C_FREE(template, max_num_temp, cave_template_type);
+
+
/*** Dump objects ***/
/* Total objects */
/*** Dump the monsters ***/
-
/* Total monsters */
wr_u16b(m_max);
}
+/*
+ * Write the current dungeon (new method)
+ */
+static bool wr_dungeon(void)
+{
+ saved_floor_type *cur_sf_ptr;
+ int i;
+
+ /* Forget the lite */
+ forget_lite();
+
+ /* Forget the view */
+ forget_view();
+
+ /* Forget the view */
+ clear_mon_lite();
+
+ /* Update lite/view */
+ p_ptr->update |= (PU_VIEW | PU_LITE | PU_MON_LITE);
+
+ /* Update monsters */
+ p_ptr->update |= (PU_MONSTERS | PU_DISTANCE | PU_FLOW);
+
+
+ /*** Meta info ***/
+
+ /* Number of floor_id used from birth */
+ wr_s16b(max_floor_id);
+
+ /* Current dungeon type */
+ wr_byte(dungeon_type);
+
+
+ /*** No saved floor (On the surface etc.) ***/
+ if (!p_ptr->floor_id)
+ {
+ /* No array elements */
+ wr_byte(0);
+
+ /* Write the current floor data */
+ wr_saved_floor(NULL);
+
+ /* Success */
+ return TRUE;
+ }
+
+
+ /*** In the dungeon ***/
+
+ /* Number of array elements */
+ wr_byte(MAX_SAVED_FLOORS);
+
+ /* Write the saved_floors array */
+ for (i = 0; i < MAX_SAVED_FLOORS; i++)
+ {
+ saved_floor_type *sf_ptr = &saved_floors[i];
+
+ wr_s16b(sf_ptr->floor_id);
+ wr_byte(sf_ptr->savefile_id);
+ wr_s16b(sf_ptr->dun_level);
+ wr_s32b(sf_ptr->last_visit);
+ wr_u32b(sf_ptr->visit_mark);
+ wr_s16b(sf_ptr->upper_floor_id);
+ wr_s16b(sf_ptr->lower_floor_id);
+ }
+
+ /* Extract pointer to current floor */
+ cur_sf_ptr = get_sf_ptr(p_ptr->floor_id);
+
+ /* Save current floor to temporal file */
+ if (!save_floor(cur_sf_ptr, (SLF_SECOND))) return FALSE;
+
+ /* Move data in temporal files to the savefile */
+ for (i = 0; i < MAX_SAVED_FLOORS; i++)
+ {
+ saved_floor_type *sf_ptr = &saved_floors[i];
+
+ /* Unused element */
+ if (!sf_ptr->floor_id) continue;
+
+ /* Load temporal saved floor file */
+ if (load_floor(sf_ptr, (SLF_SECOND | SLF_NO_KILL)))
+ {
+ /* Mark success */
+ wr_byte(0);
+
+ /* Write saved floor data to the save file */
+ wr_saved_floor(sf_ptr);
+ }
+ else
+ {
+ /* Mark failure */
+ wr_byte(1);
+ }
+ }
+
+ /* Restore current floor */
+ if (!load_floor(cur_sf_ptr, (SLF_SECOND))) return FALSE;
+
+ /* Success */
+ return TRUE;
+}
+
+
/*
* Actually write a save-file
/* Note the operating system */
- sf_xtra = 0L;
+ sf_system = 0L;
/* Note when the file was saved */
sf_when = now;
wr_byte(FAKE_VER_PATCH);
xor_byte = 0;
+ /* Initial value of xor_byte */
tmp8u = (byte)randint0(256);
wr_byte(tmp8u);
v_stamp = 0L;
x_stamp = 0L;
- /* Write the savefile version */
- wr_u32b(SAVEFILE_VERSION);
+ /* Write the savefile version for Hengband 1.1.1 and later */
+ wr_byte(H_VER_EXTRA);
+ wr_byte(H_VER_PATCH);
+ wr_byte(H_VER_MINOR);
+ wr_byte(H_VER_MAJOR);
/* Operating system */
- wr_u32b(sf_xtra);
+ wr_u32b(sf_system);
/* Time file last saved */
/* Space */
wr_u32b(0L);
- wr_u32b(0L);
+ wr_u16b(0);
+ wr_byte(0);
+#ifdef JP
+# ifdef EUC
+ /* EUC kanji code */
+ wr_byte(2);
+# endif
+# ifdef SJIS
+ /* SJIS kanji code */
+ wr_byte(3);
+# endif
+#else
+ /* ASCII */
+ wr_byte(1);
+#endif
/* Write the RNG state */
wr_randomizer();
wr_byte(quest[i].complev);
/* Save quest status if quest is running */
- if (quest[i].status == QUEST_STATUS_TAKEN || quest[i].status == QUEST_STATUS_COMPLETED || ((i >= MIN_RANDOM_QUEST) && (i <= MAX_RANDOM_QUEST)))
+ if (quest[i].status == QUEST_STATUS_TAKEN || quest[i].status == QUEST_STATUS_COMPLETED || !is_fixed_quest_idx(i))
{
wr_s16b(quest[i].cur_num);
wr_s16b(quest[i].max_num);
{
artifact_type *a_ptr = &a_info[i];
wr_byte(a_ptr->cur_num);
- wr_byte(0);
- wr_byte(0);
- wr_byte(0);
+ wr_s16b(a_ptr->floor_id);
}
wr_u16b(tmp16u);
for (i = 0; i < tmp16u; i++)
{
- wr_s16b(player_hp[i]);
+ wr_s16b(p_ptr->player_hp[i]);
}
/* Write spell data */
- wr_u32b(spell_learned1);
- wr_u32b(spell_learned2);
- wr_u32b(spell_worked1);
- wr_u32b(spell_worked2);
- wr_u32b(spell_forgotten1);
- wr_u32b(spell_forgotten2);
+ wr_u32b(p_ptr->spell_learned1);
+ wr_u32b(p_ptr->spell_learned2);
+ wr_u32b(p_ptr->spell_worked1);
+ wr_u32b(p_ptr->spell_worked2);
+ wr_u32b(p_ptr->spell_forgotten1);
+ wr_u32b(p_ptr->spell_forgotten2);
wr_s16b(p_ptr->learned_spells);
wr_s16b(p_ptr->add_spells);
/* Dump the ordered spells */
for (i = 0; i < 64; i++)
{
- wr_byte(spell_order[i]);
+ wr_byte(p_ptr->spell_order[i]);
}
wr_s16b(p_ptr->pet_extra_flags);
/* Write screen dump for sending score */
- if (screen_dump && (wait_report_score || !death))
+ if (screen_dump && (p_ptr->wait_report_score || !p_ptr->is_dead))
{
wr_string(screen_dump);
}
}
/* Player is not dead, write the dungeon */
- if (!death)
+ if (!p_ptr->is_dead)
{
/* Dump the dungeon */
- wr_dungeon();
+ if (!wr_dungeon()) return FALSE;
/* Dump the ghost */
wr_ghost();
FILE_TYPE(FILE_TYPE_SAVE);
+ /* Grab permissions */
+ safe_setuid_grab();
+
/* Create the savefile */
fd = fd_make(name, mode);
+ /* Drop permissions */
+ safe_setuid_drop();
+
/* File is okay */
if (fd >= 0)
{
/* Close the "fd" */
(void)fd_close(fd);
+ /* Grab permissions */
+ safe_setuid_grab();
+
/* Open the savefile */
fff = my_fopen(name, "wb");
+ /* Drop permissions */
+ safe_setuid_drop();
+
/* Successful open */
if (fff)
{
if (my_fclose(fff)) ok = FALSE;
}
+ /* Grab permissions */
+ safe_setuid_grab();
+
/* Remove "broken" files */
if (!ok) (void)fd_kill(name);
+
+ /* Drop permissions */
+ safe_setuid_drop();
}
strcat(safe, "n");
#endif /* VM */
+ /* Grab permissions */
+ safe_setuid_grab();
+
/* Remove it */
fd_kill(safe);
+ /* Drop permissions */
+ safe_setuid_drop();
+
update_playtime();
/* Attempt to save the player */
strcat(temp, "o");
#endif /* VM */
+ /* Grab permissions */
+ safe_setuid_grab();
+
/* Remove it */
fd_kill(temp);
/* Remove preserved savefile */
fd_kill(temp);
+ /* Drop permissions */
+ safe_setuid_drop();
+
/* Hack -- Pretend the character was loaded */
character_loaded = TRUE;
strcpy(temp, savefile);
strcat(temp, ".lok");
+ /* Grab permissions */
+ safe_setuid_grab();
+
/* Remove lock file */
fd_kill(temp);
+ /* Drop permissions */
+ safe_setuid_drop();
+
#endif
/* Success */
#endif
-
/* Return the result */
return (result);
}
turn = 0;
/* Paranoia */
- death = FALSE;
+ p_ptr->is_dead = FALSE;
/* Allow empty savefile name */
z_minor = vvv[1];
z_patch = vvv[2];
sf_extra = vvv[3];
- sf_major = 2;
- sf_minor = 8;
- sf_patch = 1;
-
- /* Pre-2.1.0: Assume 2.0.6 (same as 2.0.0 - 2.0.5) */
- if ((z_major == sf_major) &&
- (z_minor == sf_minor) &&
- (z_patch == sf_patch))
- {
- z_major = 2;
- z_minor = 0;
- z_patch = 6;
- }
-
- /* Very old savefiles */
- if ((sf_major == 5) && (sf_minor == 2))
- {
- sf_major = 2;
- sf_minor = 5;
- }
-
- /* Extremely old savefiles */
- if (sf_major > 2)
- {
- sf_major = 1;
- }
/* Clear screen */
Term_clear();
- /* Parse "new" savefiles */
- if ((sf_major == 2) && (sf_minor >= 7))
- {
- /* Attempt to load */
- err = rd_savefile_new();
- }
-
- /* Parse "future" savefiles */
- else
- {
- /* Error XXX XXX XXX */
- err = -1;
- }
+ /* Attempt to load */
+ err = rd_savefile_new();
/* Message (below) */
#ifdef JP
/* Message */
#ifdef JP
msg_format("¥Ð¡¼¥¸¥ç¥ó %d.%d.%d ÍѤΥ»¡¼¥Ö¡¦¥Õ¥¡¥¤¥ë¤òÊÑ´¹¤·¤Þ¤·¤¿¡£",
+ (z_major > 9) ? z_major-10 : z_major , z_minor, z_patch);
#else
msg_format("Converted a %d.%d.%d savefile.",
-#endif
-
(z_major > 9) ? z_major-10 : z_major , z_minor, z_patch);
+#endif
}
msg_print(NULL);
}
/* Player is dead */
- if (death)
+ if (p_ptr->is_dead)
{
- /* Player is no longer "dead" */
- death = FALSE;
-
/* Cheat death */
if (arg_wizard)
{
return (TRUE);
}
+ /* Player is no longer "dead" */
+ p_ptr->is_dead = FALSE;
+
/* Count lives */
sf_lives++;
- /* Forget turns */
- turn = old_turn = 0;
-
/* Done */
return (TRUE);
}
/* Message */
#ifdef JP
msg_format("¥¨¥é¡¼(%s)¤¬¥Ð¡¼¥¸¥ç¥ó%d.%d.%d ÍÑ¥»¡¼¥Ö¥Õ¥¡¥¤¥ëÆɤ߹þÃæ¤ËȯÀ¸¡£",
+ what, (z_major>9) ? z_major - 10 : z_major, z_minor, z_patch);
#else
msg_format("Error (%s) reading %d.%d.%d savefile.",
-#endif
-
what, (z_major>9) ? z_major - 10 : z_major, z_minor, z_patch);
+#endif
msg_print(NULL);
/* Oops */
#endif /* SET_UID */
}
+
+
+/*
+ * Actually write a temporal saved floor file
+ */
+static bool save_floor_aux(saved_floor_type *sf_ptr)
+{
+ byte tmp8u;
+
+ /* Compact the objects */
+ compact_objects(0);
+ /* Compact the monsters */
+ compact_monsters(0);
+
+
+ /*** Actually write the file ***/
+
+ /* Initial value of xor_byte */
+ tmp8u = (byte)randint0(256);
+ xor_byte = 0;
+ wr_byte(tmp8u);
+
+
+ /* Reset the checksum */
+ v_stamp = 0L;
+ x_stamp = 0L;
+
+ /* Write the sign of this process */
+ wr_u32b(saved_floor_file_sign);
+
+ /* Dump the dungeon floor */
+ wr_saved_floor(sf_ptr);
+
+
+ /* Write the "value check-sum" */
+ wr_u32b(v_stamp);
+
+ /* Write the "encoded checksum" */
+ wr_u32b(x_stamp);
+
+
+ /* Error in save */
+ if (ferror(fff) || (fflush(fff) == EOF)) return FALSE;
+
+ /* Successful save */
+ return TRUE;
+}
+
+
+/*
+ * Attempt to save the temporally saved-floor data
+ */
+bool save_floor(saved_floor_type *sf_ptr, u32b mode)
+{
+ FILE *old_fff = NULL;
+ byte old_xor_byte = 0;
+ u32b old_v_stamp = 0;
+ u32b old_x_stamp = 0;
+
+ char floor_savefile[1024];
+ int fd = -1;
+ bool ok = FALSE;
+
+ if (!(mode & SLF_SECOND))
+ {
+#ifdef SET_UID
+# ifdef SECURE
+ /* Get "games" permissions */
+ beGames();
+# endif
+#endif
+ }
+
+ /* We have one file already opened */
+ else
+ {
+ /* Backup original values */
+ old_fff = fff;
+ old_xor_byte = xor_byte;
+ old_v_stamp = v_stamp;
+ old_x_stamp = x_stamp;
+ }
+
+ /* New savefile */
+ sprintf(floor_savefile, "%s.F%02d", savefile, (int)sf_ptr->savefile_id);
+
+ /* Grab permissions */
+ safe_setuid_grab();
+
+ /* Remove it */
+ fd_kill(floor_savefile);
+
+ /* Drop permissions */
+ safe_setuid_drop();
+
+
+ /* Attempt to save the player */
+
+ /* No file yet */
+ fff = NULL;
+
+ /* File type is "SAVE" */
+ FILE_TYPE(FILE_TYPE_SAVE);
+
+ /* Grab permissions */
+ safe_setuid_grab();
+
+ /* Create the savefile */
+ fd = fd_make(floor_savefile, 0644);
+
+ /* Drop permissions */
+ safe_setuid_drop();
+
+ /* File is okay */
+ if (fd >= 0)
+ {
+ /* Close the "fd" */
+ (void)fd_close(fd);
+
+ /* Grab permissions */
+ safe_setuid_grab();
+
+ /* Open the savefile */
+ fff = my_fopen(floor_savefile, "wb");
+
+ /* Drop permissions */
+ safe_setuid_drop();
+
+ /* Successful open */
+ if (fff)
+ {
+ /* Write the savefile */
+ if (save_floor_aux(sf_ptr)) ok = TRUE;
+
+ /* Attempt to close it */
+ if (my_fclose(fff)) ok = FALSE;
+ }
+
+ /* Remove "broken" files */
+ if (!ok)
+ {
+ /* Grab permissions */
+ safe_setuid_grab();
+
+ (void)fd_kill(floor_savefile);
+
+ /* Drop permissions */
+ safe_setuid_drop();
+ }
+ }
+
+ if (!(mode & SLF_SECOND))
+ {
+#ifdef SET_UID
+# ifdef SECURE
+ /* Drop "games" permissions */
+ bePlayer();
+# endif
+#endif
+ }
+
+ /* We have one file already opened */
+ else
+ {
+ /* Restore original values */
+ fff = old_fff;
+ xor_byte = old_xor_byte;
+ v_stamp = old_v_stamp;
+ x_stamp = old_x_stamp;
+ }
+
+ /* Return the result */
+ return ok;
+}