savefile changes - part 1

This is the first of several savefile-related changes to
follow later. This one is groundwork for those later changes.

Remove internal compression schemes (RLECOMP and ZEROCOMP)
and discard the savefile_info struct that was primarily used to
convey which internal compression schemes had been in use.

Relocate some struct definitions into appropriate header files
for use by code to come in later changes.

Remove the two struct size-related fields from version_info and
from the nmakedefs_s. Instead, include a series of bytes near the
beginning of the savefile, representing the size of each
struct or base data type that impacts the historical savefile
content. Those are referred to as the "critical bytes".
(Related note: the "you" struct required two bytes, low and high,
due to its size).

Compare those critical bytes in a savefile against the NetHack
build that is reading the savefile. This allows mismatch detection
early in the savefile-reading process, and a clean exit, rather than
proceeding to read nonsensical values from the file. Include some
feedback on what the first mismatch was when encountering
one.

For arrays stored in the savefile, use loop-logic in the core
to write/read the array elements one at a time, rather than in
a single blob. This will be required for changes to follow later.
(impacts artiexist[], artidisco[], svd.dungeons[], svl.level_info[],
svl.level.locations[][], msrooms[] field of mapseen, svb.bases[],
svb.disco[] objects[], svm.mvitals[], svs.spl_book[], svd.doors[],
go.oracle_loc[], utrack[], wgrowtime[])

This also adds data model to the long version information.

This invalidates existing save and bones files due to the changes in
the information at the start of the file.
This commit is contained in:
nhmall
2025-04-15 15:35:17 -04:00
parent af3e601ff7
commit a3e12550ea
32 changed files with 962 additions and 752 deletions

View File

@@ -47,26 +47,15 @@ staticfn void dispose_of_orig_obj(struct obj *);
of hit points that will fit in a 15 bit integer. */
#define FATAL_DAMAGE_MODIFIER 200
/* artifact tracking; gift and wish imply found; it also gets set for items
seen on the floor, in containers, and wielded or dropped by monsters */
struct arti_info {
Bitfield(exists, 1); /* 1 if corresponding artifact has been created */
Bitfield(found, 1); /* 1 if artifact is known by hero to exist */
Bitfield(gift, 1); /* 1 iff artifact was created as a prayer reward */
Bitfield(wish, 1); /* 1 iff artifact was created via wish */
Bitfield(named, 1); /* 1 iff artifact was made by naming an item */
Bitfield(viadip, 1); /* 1 iff dipped long sword became Excalibur */
Bitfield(lvldef, 1); /* 1 iff created by special level definition */
Bitfield(bones, 1); /* 1 iff came from bones file */
Bitfield(rndm, 1); /* 1 iff randomly generated */
};
/* arti_info struct definition moved to artifact.h */
/* array of flags tracking which artifacts exist, indexed by ART_xx;
ART_xx values are 1..N, element [0] isn't used; no terminator needed */
static struct arti_info artiexist[1 + NROFARTIFACTS];
/* discovery list; for N discovered artifacts, the first N entries are ART_xx
values in discovery order, the remaining (NROFARTIFACTS-N) slots are 0 */
static xint16 artidisco[NROFARTIFACTS];
/* note: artiexist[] and artidisco[] don't need to be in struct g; they
/* note: artiexist[] and artidisco[] don't need to be in struct ga; they
* get explicitly initialized at game start so don't need to be part of
* bulk re-init if game restart ever gets implemented. They are saved
* and restored but that is done through this file so they can be local.
@@ -111,18 +100,34 @@ init_artifacts(void)
void
save_artifacts(NHFILE *nhfp)
{
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) artiexist, sizeof artiexist);
bwrite(nhfp->fd, (genericptr_t) artidisco, sizeof artidisco);
int i;
for (i = 0; i < (NROFARTIFACTS + 1); ++i) {
if (nhfp->structlevel)
bwrite(nhfp->fd, (genericptr_t) &artiexist[i],
sizeof (struct arti_info));
}
for (i = 0; i < (NROFARTIFACTS); ++i) {
if (nhfp->structlevel)
bwrite(nhfp->fd, (genericptr_t) &artidisco[i],
sizeof (xint16));
}
}
void
restore_artifacts(NHFILE *nhfp)
{
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) artiexist, sizeof artiexist);
mread(nhfp->fd, (genericptr_t) artidisco, sizeof artidisco);
int i;
for (i = 0; i < (NROFARTIFACTS + 1); ++i) {
if (nhfp->structlevel)
mread(nhfp->fd, (genericptr_t) &artiexist[i],
sizeof (struct arti_info));
}
for (i = 0; i < (NROFARTIFACTS); ++i) {
if (nhfp->structlevel)
mread(nhfp->fd, (genericptr_t) &artidisco[i],
sizeof (xint16));
}
hack_artifacts(); /* redo non-saved special cases */
}

View File

@@ -610,14 +610,14 @@ savebones(int how, time_t when, struct obj *corpse)
nhfp->mode = WRITING;
store_version(nhfp);
store_savefileinfo(nhfp);
/* if a bones pool digit is in use, it precedes the bonesid
string and isn't recorded in the file */
if (nhfp->structlevel) {
/* if a bones pool digit is in use, it precedes the bonesid
string and isn't recorded in the file */
bwrite(nhfp->fd, (genericptr_t) &c, sizeof c);
bwrite(nhfp->fd, (genericptr_t) bonesid, (unsigned) c); /* DD.nn */
savefruitchn(nhfp);
}
savefruitchn(nhfp);
update_mlstmv(); /* update monsters for eventual restoration */
savelev(nhfp, ledger_no(&u.uz));
close_nhfile(nhfp);
@@ -668,23 +668,25 @@ getbones(void)
return 0;
}
}
/* if a bones pool digit is in use, it precedes the bonesid
string and wasn't recorded in the file */
if (nhfp->structlevel) {
/* if a bones pool digit is in use, it precedes the bonesid
string and wasn't recorded in the file */
mread(nhfp->fd, (genericptr_t) &c,
sizeof c); /* length including terminating '\0' */
if ((unsigned) c <= sizeof oldbonesid) {
}
if ((unsigned) c <= sizeof oldbonesid) {
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) oldbonesid,
(unsigned) c); /* DD.nn or Qrrr.n for role rrr */
} else {
if (wizard)
debugpline2("Abandoning bones , %u > %u.",
(unsigned) c, (unsigned) sizeof oldbonesid);
close_nhfile(nhfp);
compress_bonesfile();
/* ToDo: maybe unlink these problematic bones? */
return 0;
(unsigned) c); /* DD.nn or Qrrr.n for role rrr */
}
} else {
if (wizard)
debugpline2("Abandoning bones , %u > %u.", (unsigned) c,
(unsigned) sizeof oldbonesid);
close_nhfile(nhfp);
compress_bonesfile();
/* ToDo: maybe unlink these problematic bones? */
return 0;
}
if (strcmp(bonesid, oldbonesid) != 0) {
char errbuf[BUFSZ];

View File

@@ -36,8 +36,6 @@ struct nomakedefs_s nomakedefs = {
0x00000000UL,
0x00000000UL,
0x00000000UL,
0x00000000UL,
0x00000000UL,
554476737UL,
};
@@ -113,8 +111,6 @@ populate_nomakedefs(struct version_info *version)
nomakedefs.version_features = version->feature_set;
nomakedefs.ignored_features = md_ignored_features();
nomakedefs.version_sanity1 = version->entity_count;
nomakedefs.version_sanity2 = version->struct_sizes1;
nomakedefs.version_sanity3 = version->struct_sizes2;
nomakedefs.version_string = dupstr(mdlib_version_string(tmpbuf2, "."));
nomakedefs.version_id = dupstr(
version_id_string(tmpbuf2, sizeof tmpbuf2, nomakedefs.build_date));

View File

@@ -51,29 +51,6 @@ const struct c_common_strings c_common_strings =
{ "mon", "you" }
};
static const struct savefile_info default_sfinfo = {
#ifdef NHSTDC
0x00000000UL
#else
0x00000000L
#endif
#if defined(COMPRESS) || defined(ZLIB_COMP)
| SFI1_EXTERNALCOMP
#endif
#if defined(ZEROCOMP)
| SFI1_ZEROCOMP
#endif
#if defined(RLECOMP)
| SFI1_RLECOMP
#endif
,
#ifdef NHSTDC
0x00000000UL, 0x00000000UL
#else
0x00000000L, 0x00000000L
#endif
};
const char disclosure_options[] = "iavgco";
char emptystr[] = {0}; /* non-const */
@@ -117,7 +94,6 @@ const char *materialnm[] = { "mysterious", "liquid", "wax", "organic",
"platinum", "mithril", "plastic", "glass",
"gemstone", "stone" };
const char quitchars[] = " \r\n\033";
NEARDATA struct savefile_info sfcap, sfrestinfo, sfsaveinfo;
const int shield_static[SHIELD_COUNT] = {
S_ss1, S_ss2, S_ss3, S_ss2, S_ss1, S_ss2, S_ss4, /* 7 per row */
S_ss1, S_ss2, S_ss3, S_ss2, S_ss1, S_ss2, S_ss4,
@@ -1166,10 +1142,6 @@ decl_globals_init(void)
MAGICCHECK(g_init_y);
MAGICCHECK(g_init_z);
sfcap = default_sfinfo;
sfrestinfo = default_sfinfo;
sfsaveinfo = default_sfinfo;
gs.subrooms = &svr.rooms[MAXNROFROOMS + 1];
ZERO(flags);

View File

@@ -147,15 +147,21 @@ save_dungeon(
boolean perform_write,
boolean free_data)
{
int count;
int i, count;
branch *curr, *next;
mapseen *curr_ms, *next_ms;
if (perform_write) {
if(nhfp->structlevel) {
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &svn.n_dgns, sizeof svn.n_dgns);
bwrite(nhfp->fd, (genericptr_t) svd.dungeons,
sizeof(dungeon) * (unsigned) svn.n_dgns);
}
for (i = 0; i < svn.n_dgns; ++i) {
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &svd.dungeons[i],
sizeof (dungeon));
}
}
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &svd.dungeon_topology,
sizeof svd.dungeon_topology);
bwrite(nhfp->fd, (genericptr_t) svt.tune, sizeof tune);
@@ -172,16 +178,23 @@ save_dungeon(
count = maxledgerno();
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &count, sizeof count);
bwrite(nhfp->fd, (genericptr_t) svl.level_info,
(unsigned) count * sizeof (struct linfo));
}
for (i = 0; i < count; ++i) {
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &svl.level_info[i],
sizeof (struct linfo));
}
}
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &svi.inv_pos, sizeof svi.inv_pos);
}
for (count = 0, curr_ms = svm.mapseenchn; curr_ms;
curr_ms = curr_ms->next)
count++;
if (nhfp->structlevel)
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &count, sizeof count);
}
for (curr_ms = svm.mapseenchn; curr_ms; curr_ms = curr_ms->next) {
save_mapseen(nhfp, curr_ms);
@@ -216,21 +229,30 @@ restore_dungeon(NHFILE *nhfp)
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) &svn.n_dgns, sizeof svn.n_dgns);
mread(nhfp->fd, (genericptr_t) svd.dungeons,
sizeof (dungeon) * (unsigned) svn.n_dgns);
}
for (i = 0; i < svn.n_dgns; ++i) {
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) &svd.dungeons[i], sizeof(dungeon));
}
}
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) &svd.dungeon_topology,
sizeof svd.dungeon_topology);
}
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) svt.tune, sizeof tune);
}
last = svb.branches = (branch *) 0;
if (nhfp->structlevel)
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) &count, sizeof count);
}
for (i = 0; i < count; i++) {
curr = (branch *) alloc(sizeof *curr);
if (nhfp->structlevel)
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) curr, sizeof *curr);
}
curr->next = (branch *) 0;
if (last)
last->next = curr;
@@ -245,10 +267,12 @@ restore_dungeon(NHFILE *nhfp)
if (count >= MAXLINFO)
panic("level information count larger (%d) than allocated size",
count);
if (nhfp->structlevel)
mread(nhfp->fd, (genericptr_t) svl.level_info,
(unsigned) count * sizeof (struct linfo));
for (i = 0; i < count; ++i) {
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) &svl.level_info[i],
sizeof (struct linfo));
}
}
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) &svi.inv_pos, sizeof svi.inv_pos);
mread(nhfp->fd, (genericptr_t) &count, sizeof count);
@@ -2566,17 +2590,19 @@ save_exclusions(NHFILE *nhfp)
for (nez = 0, ez = sve.exclusion_zones; ez; ez = ez->next, ++nez)
;
if (nhfp->structlevel)
bwrite(nhfp->fd, (genericptr_t) &nez, sizeof nez);
if (perform_bwrite(nhfp)) {
if (nhfp->structlevel)
bwrite(nhfp->fd, (genericptr_t) &nez, sizeof nez);
for (ez = sve.exclusion_zones; ez; ez = ez->next) {
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &ez->zonetype,
sizeof ez->zonetype);
bwrite(nhfp->fd, (genericptr_t) &ez->lx, sizeof ez->lx);
bwrite(nhfp->fd, (genericptr_t) &ez->ly, sizeof ez->ly);
bwrite(nhfp->fd, (genericptr_t) &ez->hx, sizeof ez->hx);
bwrite(nhfp->fd, (genericptr_t) &ez->hy, sizeof ez->hy);
for (ez = sve.exclusion_zones; ez; ez = ez->next) {
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &ez->zonetype,
sizeof ez->zonetype);
bwrite(nhfp->fd, (genericptr_t) &ez->lx, sizeof ez->lx);
bwrite(nhfp->fd, (genericptr_t) &ez->ly, sizeof ez->ly);
bwrite(nhfp->fd, (genericptr_t) &ez->hx, sizeof ez->hx);
bwrite(nhfp->fd, (genericptr_t) &ez->hy, sizeof ez->hy);
}
}
}
}
@@ -2587,8 +2613,9 @@ load_exclusions(NHFILE *nhfp)
struct exclusion_zone *ez;
int nez = 0;
if (nhfp->structlevel)
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) &nez, sizeof nez);
}
while (nez-- > 0) {
ez = (struct exclusion_zone *) alloc(sizeof *ez);
@@ -2668,15 +2695,14 @@ staticfn void
save_mapseen(NHFILE *nhfp, mapseen *mptr)
{
branch *curr;
int brindx;
int i, brindx;
for (brindx = 0, curr = svb.branches; curr; curr = curr->next, ++brindx)
if (curr == mptr->br)
break;
if (nhfp->structlevel)
bwrite(nhfp->fd, (genericptr_t) &brindx, sizeof brindx);
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &brindx, sizeof brindx);
bwrite(nhfp->fd, (genericptr_t) &mptr->lev, sizeof mptr->lev);
bwrite(nhfp->fd, (genericptr_t) &mptr->feat, sizeof mptr->feat);
bwrite(nhfp->fd, (genericptr_t) &mptr->flags, sizeof mptr->flags);
@@ -2686,11 +2712,15 @@ save_mapseen(NHFILE *nhfp, mapseen *mptr)
if (mptr->custom_lth) {
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) mptr->custom, mptr->custom_lth);
bwrite(nhfp->fd, (genericptr_t) mptr->custom,
mptr->custom_lth);
}
}
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &mptr->msrooms, sizeof mptr->msrooms);
for (i = 0; i < ((MAXNROFROOMS + 1) * 2); ++i) {
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &mptr->msrooms[i],
sizeof (struct mapseen_rooms));
}
}
savecemetery(nhfp, &mptr->final_resting_place);
}
@@ -2698,14 +2728,15 @@ save_mapseen(NHFILE *nhfp, mapseen *mptr)
staticfn mapseen *
load_mapseen(NHFILE *nhfp)
{
int branchnum = 0, brindx;
int i, branchnum = 0, brindx;
mapseen *load;
branch *curr;
load = (mapseen *) alloc(sizeof *load);
if (nhfp->structlevel)
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) &branchnum, sizeof branchnum);
}
for (brindx = 0, curr = svb.branches; curr; curr = curr->next, ++brindx)
if (brindx == branchnum)
break;
@@ -2723,14 +2754,18 @@ load_mapseen(NHFILE *nhfp)
/* length doesn't include terminator (which isn't saved & restored) */
load->custom = (char *) alloc(load->custom_lth + 1);
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) load->custom, load->custom_lth);
mread(nhfp->fd, (genericptr_t) load->custom,
load->custom_lth);
}
load->custom[load->custom_lth] = '\0';
} else {
load->custom = 0;
}
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) &load->msrooms, sizeof load->msrooms);
for (i = 0; i < ((MAXNROFROOMS + 1) * 2); ++i) {
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) &load->msrooms[i],
sizeof (struct mapseen_rooms));
}
}
restcemetery(nhfp, &load->final_resting_place);
return load;

View File

@@ -1755,8 +1755,9 @@ save_killers(NHFILE *nhfp)
if (perform_bwrite(nhfp)) {
for (kptr = &svk.killer; kptr; kptr = kptr->next) {
if (nhfp->structlevel)
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) kptr, sizeof (struct kinfo));
}
}
}
if (release_data(nhfp)) {
@@ -1774,8 +1775,9 @@ restore_killers(NHFILE *nhfp)
struct kinfo *kptr;
for (kptr = &svk.killer; kptr != (struct kinfo *) 0; kptr = kptr->next) {
if (nhfp->structlevel)
mread(nhfp->fd, (genericptr_t) kptr, sizeof(struct kinfo));
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) kptr, sizeof (struct kinfo));
}
if (kptr->next) {
kptr->next = (struct kinfo *) alloc(sizeof (struct kinfo));
}

View File

@@ -1532,9 +1532,10 @@ save_engravings(NHFILE *nhfp)
dealloc_engr(ep);
}
if (perform_bwrite(nhfp)) {
if (nhfp->structlevel)
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &no_more_engr,
sizeof no_more_engr);
}
}
if (release_data(nhfp))
head_engr = 0;
@@ -1548,9 +1549,9 @@ rest_engravings(NHFILE *nhfp)
head_engr = 0;
while (1) {
if (nhfp->structlevel)
mread(nhfp->fd, (genericptr_t) &lth, sizeof (unsigned));
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) &lth, sizeof(unsigned));
}
if (lth == 0)
return;
ep = newengr(lth);

View File

@@ -4258,7 +4258,6 @@ recover_savefile(void)
struct version_info version_data;
int processed[256];
char savename[SAVESIZE], errbuf[BUFSZ], indicator;
struct savefile_info sfi;
char tmpplbuf[PL_NSIZ_PLUS];
const char *savewrite_failure = (const char *) 0;
@@ -4269,7 +4268,6 @@ recover_savefile(void)
* pid of creating process (ignored here)
* level number for current level of save file
* name of save file nethack would have created
* savefile info
* player name
* and game state
*/
@@ -4304,7 +4302,6 @@ recover_savefile(void)
!= sizeof filecmc)
|| (read(gnhfp->fd, (genericptr_t) &version_data, sizeof version_data)
!= sizeof version_data)
|| (read(gnhfp->fd, (genericptr_t) &sfi, sizeof sfi) != sizeof sfi)
|| (read(gnhfp->fd, (genericptr_t) &pltmpsiz, sizeof pltmpsiz)
!= sizeof pltmpsiz) || (pltmpsiz > PL_NSIZ_PLUS)
|| (read(gnhfp->fd, (genericptr_t) &tmpplbuf, pltmpsiz)
@@ -4317,8 +4314,8 @@ recover_savefile(void)
/* save file should contain:
* format indicator and cmc
* version info
* savefile info
* player name
* plnametmp = player name size (int, 2 bytes)
* player name (PL_NSIZ_PLUS)
* current level (including pets)
* (non-level-based) game state
* other levels
@@ -4347,17 +4344,7 @@ recover_savefile(void)
return FALSE;
}
/*
* Our savefile output format might _not_ be structlevel.
* We have to check and use the correct output routine here.
*/
/*store_formatindicator(snhfp); */
store_version(snhfp);
if (snhfp->structlevel) {
if (write(snhfp->fd, (genericptr_t) &sfi, sizeof sfi) != sizeof sfi)
savewrite_failure = "savefileinfo";
}
if (savewrite_failure)
goto cleanup;

View File

@@ -482,13 +482,15 @@ restore_light_sources(NHFILE *nhfp)
light_source *ls;
/* restore elements */
if (nhfp->structlevel)
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) &count, sizeof count);
}
while (count-- > 0) {
ls = (light_source *) alloc(sizeof(light_source));
if (nhfp->structlevel)
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) ls, sizeof(light_source));
}
ls->next = gl.light_base;
gl.light_base = ls;
}
@@ -639,8 +641,9 @@ write_ls(NHFILE *nhfp, light_source *ls)
if (ls->type == LS_OBJECT || ls->type == LS_MONSTER) {
if (ls->flags & LSF_NEEDS_FIXUP) {
if (nhfp->structlevel)
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) ls, sizeof(light_source));
}
} else {
/* replace object pointer with id for write, then put back */
arg_save = ls->id;
@@ -692,8 +695,9 @@ write_ls(NHFILE *nhfp, light_source *ls)
/* TODO: cleanup this ls, or skip writing it */
}
ls->flags |= LSF_NEEDS_FIXUP;
if (nhfp->structlevel)
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) ls, sizeof(light_source));
}
ls->id = arg_save;
ls->flags &= ~LSF_NEEDS_FIXUP;
ls->flags &= ~LSF_IS_PROBLEMATIC;

View File

@@ -87,6 +87,7 @@ staticfn void build_options(void);
staticfn int count_and_validate_winopts(void);
staticfn void opt_out_words(char *, int *) NONNULLPTRS;
staticfn void build_savebones_compat_string(void);
staticfn const char *datamodel(void);
static int idxopttext, done_runtime_opt_init_once = 0;
#define MAXOPT 60 /* 3.7: currently 40 lines get inserted into opttext[] */
@@ -228,30 +229,49 @@ static struct soundlib_information soundlib_opts[] = {
};
#endif /* !MAKEDEFS_C */
/*
* Use this to explicitly mask out features during version checks.
*
* ZEROCOMP, RLECOMP, and ZLIB_COMP describe compression features
* that the port/platform which wrote the savefile was capable of
* dealing with. Don't reject a savefile just because the port
* reading the savefile doesn't match on all/some of them.
* The actual compression features used to produce the savefile are
* recorded in the savefile_info structure immediately following the
* version_info, and that is what needs to be checked against the
* feature set of the port that is reading the savefile back in.
* That check is done in src/restore.c now.
*
*/
unsigned long
md_ignored_features(void)
{
return (0UL
| (1UL << 19) /* SCORE_ON_BOTL */
| (1UL << 27) /* ZEROCOMP */
| (1UL << 28) /* RLECOMP */
);
}
#define MAX_D 5
struct datamodel_information {
int sz[MAX_D];
const char *datamodel;
};
static struct datamodel_information dm[] = {
{ { (int) sizeof(short), (int) sizeof(int), (int) sizeof(long),
(int) sizeof(long long), (int) sizeof(genericptr_t) },
"" },
{ { 2, 4, 4, 8, 4 }, "ILP32LL64" }, /* Windows, Unix x86 */
{ { 2, 4, 4, 8, 8 }, "IL32LLP64" }, /* Windows x64 */
{ { 2, 4, 8, 8, 8 }, "I32LP64" }, /* Unix 64-bit */
{ { 2, 8, 8, 8, 8 }, "ILP64" }, /* HAL, SPARC64 */
};
staticfn const char *
datamodel(void)
{
int i, j, matchcount;
static const char *unknown = "Unknown";
for (i = 1; i < SIZE(dm); ++i) {
matchcount = 0;
for (j = 0; j < MAX_D; ++j) {
if (dm[0].sz[j] == dm[i].sz[j])
++matchcount;
}
if (matchcount == MAX_D)
return dm[i].datamodel;
}
return unknown;
}
#undef MAX_D
staticfn void
make_version(void)
{
@@ -285,15 +305,6 @@ make_version(void)
#endif
#ifdef SCORE_ON_BOTL
| (1L << 19)
#endif
/* data format (27..31)
* External compression methods such as COMPRESS and ZLIB_COMP
* do not affect the contents and are thus excluded from here */
#ifdef ZEROCOMP
| (1L << 27)
#endif
#ifdef RLECOMP
| (1L << 28)
#endif
);
/*
@@ -307,15 +318,6 @@ make_version(void)
version.entity_count = (version.entity_count << 12) | (unsigned long) i;
i = NUMMONS;
version.entity_count = (version.entity_count << 12) | (unsigned long) i;
/*
* Value used for compiler (word size/field alignment/padding) check.
*/
version.struct_sizes1 =
(((unsigned long) sizeof(struct context_info) << 24)
| ((unsigned long) sizeof(struct obj) << 17)
| ((unsigned long) sizeof(struct monst) << 10)
| ((unsigned long) sizeof(struct you)));
version.struct_sizes2 = (((unsigned long) sizeof(struct flag) << 10));
/* free bits in here */
return;
}
@@ -611,12 +613,6 @@ static const char *const build_opts[] = {
#ifdef VISION_TABLES
"vision tables",
#endif
#ifdef ZEROCOMP
"zero-compressed save files",
#endif
#ifdef RLECOMP
"run-length compression of map in save files",
#endif
#ifdef SYSCF
"system configuration at run-time",
#endif
@@ -728,6 +724,8 @@ build_options(void)
STOREOPTTEXT(optbuf);
optbuf[0] = '\0';
length = COLNO + 1; /* force 1st item onto new line */
Strcat(strcpy(buf, datamodel()), " data model,");
opt_out_words(buf, &length);
for (i = 0; i < SIZE(build_opts); i++) {
#if !defined(MAKEDEFS_C) && defined(FOR_RUNTIME)
#ifdef WIN32

View File

@@ -1732,8 +1732,9 @@ save_waterlevel(NHFILE *nhfp)
bwrite(nhfp->fd, (genericptr_t) &svy.ymax, sizeof(int));
}
for (b = svb.bbubbles; b; b = b->next) {
if (nhfp->structlevel)
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) b, sizeof(struct bubble));
}
}
}
if (release_data(nhfp))
@@ -1759,8 +1760,9 @@ restore_waterlevel(NHFILE *nhfp)
for (i = 0; i < n; i++) {
btmp = b;
b = (struct bubble *) alloc((unsigned) sizeof *b);
if (nhfp->structlevel)
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) b, (unsigned) sizeof *b);
}
if (btmp) {
btmp->next = b;
b->prev = btmp;

View File

@@ -845,8 +845,9 @@ save_room(NHFILE *nhfp, struct mkroom *r)
* of writing the whole structure. That is I should not write
* the gs.subrooms pointers, but who cares ?
*/
if (nhfp->structlevel)
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) r, sizeof (struct mkroom));
}
for (i = 0; i < r->nsubrooms; i++) {
save_room(nhfp, r->sbrooms[i]);
}
@@ -861,8 +862,9 @@ save_rooms(NHFILE *nhfp)
short i;
/* First, write the number of rooms */
if (nhfp->structlevel)
bwrite(nhfp->fd, (genericptr_t) &svn.nroom, sizeof(svn.nroom));
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &svn.nroom, sizeof svn.nroom);
}
for (i = 0; i < svn.nroom; i++)
save_room(nhfp, &svr.rooms[i]);
}
@@ -872,8 +874,9 @@ rest_room(NHFILE *nhfp, struct mkroom *r)
{
short i;
if (nhfp->structlevel)
mread(nhfp->fd, (genericptr_t) r, sizeof(struct mkroom));
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) r, sizeof (struct mkroom));
}
for (i = 0; i < r->nsubrooms; i++) {
r->sbrooms[i] = &gs.subrooms[gn.nsubroom];
@@ -891,8 +894,9 @@ rest_rooms(NHFILE *nhfp)
{
short i;
if (nhfp->structlevel)
mread(nhfp->fd, (genericptr_t) &svn.nroom, sizeof(svn.nroom));
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) &svn.nroom, sizeof svn.nroom);
}
gn.nsubroom = 0;
for (i = 0; i < svn.nroom; i++) {

View File

@@ -1274,9 +1274,11 @@ save_luadata(NHFILE *nhfp)
if (!lua_data)
lua_data = dupstr(emptystr);
lua_data_len = Strlen(lua_data) + 1; /* +1: include the terminator */
bwrite(nhfp->fd, (genericptr_t) &lua_data_len,
(unsigned) sizeof lua_data_len);
bwrite(nhfp->fd, (genericptr_t) lua_data, lua_data_len);
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &lua_data_len,
(unsigned) sizeof lua_data_len);
bwrite(nhfp->fd, (genericptr_t) lua_data, lua_data_len);
}
free(lua_data);
}
@@ -1284,13 +1286,16 @@ save_luadata(NHFILE *nhfp)
void
restore_luadata(NHFILE *nhfp)
{
unsigned lua_data_len;
unsigned lua_data_len = 0;
char *lua_data;
mread(nhfp->fd, (genericptr_t) &lua_data_len,
(unsigned) sizeof lua_data_len);
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) &lua_data_len,
(unsigned) sizeof lua_data_len);
}
lua_data = (char *) alloc(lua_data_len);
mread(nhfp->fd, (genericptr_t) lua_data, lua_data_len);
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) lua_data, lua_data_len);
}
if (!gl.luacore)
l_nhcore_init();
luaL_loadstring(gl.luacore, lua_data);

View File

@@ -376,11 +376,21 @@ savenames(NHFILE *nhfp)
unsigned int len;
if (perform_bwrite(nhfp)) {
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) svb.bases, sizeof svb.bases);
bwrite(nhfp->fd, (genericptr_t) svd.disco, sizeof svd.disco);
bwrite(nhfp->fd, (genericptr_t) objects,
sizeof(struct objclass) * NUM_OBJECTS);
for (i = 0; i < (MAXOCLASSES + 2); ++i) {
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &svb.bases[i], sizeof (int));
}
}
for (i = 0; i < NUM_OBJECTS; ++i) {
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &svd.disco[i], sizeof (short));
}
}
for (i = 0; i < NUM_OBJECTS; ++i) {
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &objects[i],
sizeof (struct objclass));
}
}
}
/* as long as we use only one version of Hack we
@@ -392,7 +402,7 @@ savenames(NHFILE *nhfp)
len = Strlen(objects[i].oc_uname) + 1;
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &len, sizeof len);
bwrite(nhfp->fd, (genericptr_t) objects[i].oc_uname, len);
bwrite(nhfp->fd, (genericptr_t) &objects[i].oc_uname[0], len);
}
}
if (release_data(nhfp)) {
@@ -421,7 +431,7 @@ restnames(NHFILE *nhfp)
}
objects[i].oc_uname = (char *) alloc(len);
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) objects[i].oc_uname, len);
mread(nhfp->fd, (genericptr_t) &objects[i].oc_uname[0], len);
}
}
}

View File

@@ -754,25 +754,29 @@ save_regions(NHFILE *nhfp)
bwrite(nhfp->fd, (genericptr_t) &r->nrects, sizeof (short));
}
for (j = 0; j < r->nrects; j++) {
if (nhfp->structlevel)
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &r->rects[j],
sizeof (NhRect));
}
}
if (nhfp->structlevel)
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &r->attach_2_u, sizeof (boolean));
if (nhfp->structlevel)
bwrite(nhfp->fd, (genericptr_t) &r->attach_2_m, sizeof (unsigned));
}
n = !r->enter_msg ? 0U : (unsigned) strlen(r->enter_msg);
if (nhfp->structlevel)
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &n, sizeof n);
}
if (n > 0) {
if (nhfp->structlevel)
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) r->enter_msg, n);
}
}
n = !r->leave_msg ? 0U : (unsigned) strlen(r->leave_msg);
if (nhfp->structlevel)
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &n, sizeof n);
}
if (n > 0) {
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) r->leave_msg, n);
@@ -791,9 +795,10 @@ save_regions(NHFILE *nhfp)
bwrite(nhfp->fd, (genericptr_t) &r->n_monst, sizeof (short));
}
for (j = 0; j < r->n_monst; j++) {
if (nhfp->structlevel)
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &r->monsters[j],
sizeof (unsigned));
}
}
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &r->visible, sizeof (boolean));
@@ -818,15 +823,17 @@ rest_regions(NHFILE *nhfp)
boolean ghostly = (nhfp->ftype == NHF_BONESFILE);
clear_regions(); /* Just for security */
if (nhfp->structlevel)
mread(nhfp->fd, (genericptr_t) &tmstamp, sizeof (tmstamp));
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) &tmstamp, sizeof(tmstamp));
}
if (ghostly)
tmstamp = 0;
else
tmstamp = (svm.moves - tmstamp);
if (nhfp->structlevel)
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) &svn.n_regions, sizeof svn.n_regions);
}
gm.max_regions = svn.n_regions;
if (svn.n_regions > 0)
@@ -842,40 +849,43 @@ rest_regions(NHFILE *nhfp)
else
r->rects = (NhRect *) 0;
for (j = 0; j < r->nrects; j++) {
if (nhfp->structlevel)
mread(nhfp->fd, (genericptr_t) &r->rects[j], sizeof (NhRect));
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) &r->rects[j], sizeof(NhRect));
}
}
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) &r->attach_2_u, sizeof (boolean));
mread(nhfp->fd, (genericptr_t) &r->attach_2_m, sizeof (unsigned));
}
if (nhfp->structlevel)
mread(nhfp->fd, (genericptr_t) &n, sizeof n);
}
if (n > 0) {
msg_buf = (char *) alloc(n + 1);
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) msg_buf, n);
}
msg_buf[n] = '\0';
} else
} else {
msg_buf = (char *) 0;
}
r->enter_msg = (const char *) msg_buf;
if (nhfp->structlevel)
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) &n, sizeof n);
}
if (n > 0) {
msg_buf = (char *) alloc(n + 1);
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) msg_buf, n);
}
msg_buf[n] = '\0';
} else
msg_buf = (char *) 0;
} else {
msg_buf = (char *) 0;
}
r->leave_msg = (const char *) msg_buf;
if (nhfp->structlevel)
mread(nhfp->fd, (genericptr_t) &r->ttl, sizeof (long));
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) &r->ttl, sizeof(long));
}
/* check for expired region */
if (r->ttl >= 0L)
r->ttl = (r->ttl > tmstamp) ? r->ttl - tmstamp : 0L;
@@ -893,17 +903,19 @@ rest_regions(NHFILE *nhfp)
clear_hero_inside(r);
clear_heros_fault(r);
}
if (nhfp->structlevel)
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) &r->n_monst, sizeof (short));
}
if (r->n_monst > 0)
r->monsters = (unsigned *) alloc(r->n_monst * sizeof (unsigned));
else
r->monsters = (unsigned *) 0;
r->max_monst = r->n_monst;
for (j = 0; j < r->n_monst; j++) {
if (nhfp->structlevel)
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) &r->monsters[j],
sizeof (unsigned));
sizeof(unsigned));
}
}
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) &r->visible, sizeof (boolean));

View File

@@ -11,12 +11,6 @@ extern int dotcnt; /* shared with save */
extern int dotrow; /* shared with save */
#endif
#ifdef ZEROCOMP
staticfn void zerocomp_minit(void);
staticfn void zerocomp_mread(int, genericptr_t, unsigned int);
staticfn int zerocomp_mgetc(void);
#endif
staticfn void find_lev_obj(void);
staticfn void restlevchn(NHFILE *);
staticfn void restdamage(NHFILE *);
@@ -26,16 +20,19 @@ staticfn void restmon(NHFILE *, struct monst *);
staticfn struct monst *restmonchn(NHFILE *);
staticfn struct fruit *loadfruitchn(NHFILE *);
staticfn void freefruitchn(struct fruit *);
staticfn void rest_levl(NHFILE *);
staticfn void rest_stairs(NHFILE *);
staticfn void ghostfruit(struct obj *);
staticfn boolean restgamestate(NHFILE *);
staticfn void restlevelstate(void);
staticfn int restlevelfile(xint8);
staticfn void rest_bubbles(NHFILE *);
staticfn void restore_gamelog(NHFILE *);
staticfn void restore_msghistory(NHFILE *);
staticfn void reset_oattached_mids(boolean);
staticfn void rest_levl(NHFILE *, boolean);
staticfn void rest_stairs(NHFILE *);
staticfn boolean restgamestate(NHFILE *);
staticfn void rest_bubbles(NHFILE *);
staticfn void restore_gamelog(NHFILE *);
staticfn void restore_msghistory(NHFILE *);
/*
* Save a mapping of IDs from ghost levels to the current level. This
@@ -132,13 +129,14 @@ restlevchn(NHFILE *nhfp)
s_level *tmplev, *x;
svs.sp_levchn = (s_level *) 0;
if (nhfp->structlevel)
if (nhfp->structlevel) {
Mread(nhfp->fd, &cnt, sizeof cnt);
}
for (; cnt > 0; cnt--) {
tmplev = (s_level *) alloc(sizeof(s_level));
if (nhfp->structlevel)
if (nhfp->structlevel) {
Mread(nhfp->fd, tmplev, sizeof *tmplev);
}
if (!svs.sp_levchn)
svs.sp_levchn = tmplev;
@@ -159,16 +157,18 @@ restdamage(NHFILE *nhfp)
struct damage *tmp_dam;
boolean ghostly = (nhfp->ftype == NHF_BONESFILE);
if (nhfp->structlevel)
if (nhfp->structlevel) {
Mread(nhfp->fd, &dmgcount, sizeof dmgcount);
}
counter = (int) dmgcount;
if (!counter)
return;
do {
tmp_dam = (struct damage *) alloc(sizeof *tmp_dam);
if (nhfp->structlevel)
if (nhfp->structlevel) {
Mread(nhfp->fd, tmp_dam, sizeof *tmp_dam);
}
if (ghostly)
tmp_dam->when += (svm.moves - go.omoves);
@@ -184,8 +184,9 @@ restobj(NHFILE *nhfp, struct obj *otmp)
{
int buflen = 0;
if (nhfp->structlevel)
if (nhfp->structlevel) {
Mread(nhfp->fd, otmp, sizeof *otmp);
}
otmp->lua_ref_cnt = 0;
/* next object pointers are invalid; otmp->cobj needs to be left
@@ -196,18 +197,20 @@ restobj(NHFILE *nhfp, struct obj *otmp)
otmp->oextra = newoextra();
/* oname - object's name */
if (nhfp->structlevel)
if (nhfp->structlevel) {
Mread(nhfp->fd, &buflen, sizeof buflen);
}
if (buflen > 0) { /* includes terminating '\0' */
new_oname(otmp, buflen);
if (nhfp->structlevel)
if (nhfp->structlevel) {
Mread(nhfp->fd, ONAME(otmp), buflen);
}
}
/* omonst - corpse or statue might retain full monster details */
if (nhfp->structlevel)
if (nhfp->structlevel) {
Mread(nhfp->fd, &buflen, sizeof buflen);
}
if (buflen > 0) {
newomonst(otmp);
/* this is actually a monst struct, so we
@@ -216,21 +219,24 @@ restobj(NHFILE *nhfp, struct obj *otmp)
}
/* omailcmd - feedback mechanism for scroll of mail */
if (nhfp->structlevel)
if (nhfp->structlevel) {
Mread(nhfp->fd, &buflen, sizeof buflen);
}
if (buflen > 0) {
char *omailcmd = (char *) alloc(buflen);
if (nhfp->structlevel)
if (nhfp->structlevel) {
Mread(nhfp->fd, omailcmd, buflen);
}
new_omailcmd(otmp, omailcmd);
free((genericptr_t) omailcmd);
}
/* omid - monster id number, connecting corpse to ghost */
newomid(otmp); /* superfluous; we're already allocated otmp->oextra */
if (nhfp->structlevel)
if (nhfp->structlevel) {
Mread(nhfp->fd, &OMID(otmp), sizeof OMID(otmp));
}
}
}
@@ -243,9 +249,9 @@ restobjchn(NHFILE *nhfp, boolean frozen)
boolean ghostly = (nhfp->ftype == NHF_BONESFILE);
while (1) {
if (nhfp->structlevel)
if (nhfp->structlevel) {
Mread(nhfp->fd, &buflen, sizeof buflen);
}
if (buflen == -1)
break;
@@ -306,10 +312,11 @@ restobjchn(NHFILE *nhfp, boolean frozen)
staticfn void
restmon(NHFILE *nhfp, struct monst *mtmp)
{
int buflen = 0;
int buflen = 0, mc = 0;
if (nhfp->structlevel)
if (nhfp->structlevel) {
Mread(nhfp->fd, mtmp, sizeof *mtmp);
}
/* next monster pointer is invalid */
mtmp->nmon = (struct monst *) 0;
@@ -318,71 +325,85 @@ restmon(NHFILE *nhfp, struct monst *mtmp)
mtmp->mextra = newmextra();
/* mgivenname - monster's name */
if (nhfp->structlevel)
if (nhfp->structlevel) {
Mread(nhfp->fd, &buflen, sizeof buflen);
}
if (buflen > 0) { /* includes terminating '\0' */
new_mgivenname(mtmp, buflen);
if (nhfp->structlevel)
if (nhfp->structlevel) {
Mread(nhfp->fd, MGIVENNAME(mtmp), buflen);
}
}
/* egd - vault guard */
if (nhfp->structlevel)
if (nhfp->structlevel) {
Mread(nhfp->fd, &buflen, sizeof buflen);
}
if (buflen > 0) {
newegd(mtmp);
if (nhfp->structlevel)
Mread(nhfp->fd, EGD(mtmp), sizeof (struct egd));
if (nhfp->structlevel) {
Mread(nhfp->fd, EGD(mtmp), sizeof(struct egd));
}
}
/* epri - temple priest */
if (nhfp->structlevel)
if (nhfp->structlevel) {
Mread(nhfp->fd, &buflen, sizeof buflen);
}
if (buflen > 0) {
newepri(mtmp);
if (nhfp->structlevel)
Mread(nhfp->fd, EPRI(mtmp), sizeof (struct epri));
if (nhfp->structlevel) {
Mread(nhfp->fd, EPRI(mtmp), sizeof(struct epri));
}
}
/* eshk - shopkeeper */
if (nhfp->structlevel)
if (nhfp->structlevel) {
Mread(nhfp->fd, &buflen, sizeof buflen);
}
if (buflen > 0) {
neweshk(mtmp);
if (nhfp->structlevel)
Mread(nhfp->fd, ESHK(mtmp), sizeof (struct eshk));
if (nhfp->structlevel) {
Mread(nhfp->fd, ESHK(mtmp), sizeof(struct eshk));
}
}
/* emin - minion */
if (nhfp->structlevel)
if (nhfp->structlevel) {
Mread(nhfp->fd, &buflen, sizeof buflen);
}
if (buflen > 0) {
newemin(mtmp);
if (nhfp->structlevel)
Mread(nhfp->fd, EMIN(mtmp), sizeof (struct emin));
if (nhfp->structlevel) {
Mread(nhfp->fd, EMIN(mtmp), sizeof(struct emin));
}
}
/* edog - pet */
if (nhfp->structlevel)
if (nhfp->structlevel) {
Mread(nhfp->fd, &buflen, sizeof buflen);
}
if (buflen > 0) {
newedog(mtmp);
if (nhfp->structlevel)
Mread(nhfp->fd, EDOG(mtmp), sizeof (struct edog));
if (nhfp->structlevel) {
Mread(nhfp->fd, EDOG(mtmp), sizeof(struct edog));
}
/* sanity check to prevent rn2(0) */
if (EDOG(mtmp)->apport <= 0) {
EDOG(mtmp)->apport = 1;
}
}
/* ebones */
if (nhfp->structlevel)
if (nhfp->structlevel) {
Mread(nhfp->fd, &buflen, sizeof buflen);
}
if (buflen > 0) {
newebones(mtmp);
if (nhfp->structlevel)
Mread(nhfp->fd, EBONES(mtmp),
sizeof (struct ebones));
if (nhfp->structlevel) {
Mread(nhfp->fd, EBONES(mtmp), sizeof(struct ebones));
}
}
/* mcorpsenm - obj->corpsenm for mimic posing as corpse or
statue (inline int rather than pointer to something) */
if (nhfp->structlevel)
Mread(nhfp->fd, &MCORPSENM(mtmp), sizeof MCORPSENM(mtmp));
if (nhfp->structlevel) {
Mread(nhfp->fd, &mc, sizeof mc);
}
MCORPSENM(mtmp) = mc;
} /* mextra */
}
@@ -395,8 +416,9 @@ restmonchn(NHFILE *nhfp)
boolean ghostly = (nhfp->ftype == NHF_BONESFILE);
while (1) {
if (nhfp->structlevel)
if (nhfp->structlevel) {
Mread(nhfp->fd, &buflen, sizeof buflen);
}
if (buflen == -1)
break;
@@ -472,8 +494,9 @@ loadfruitchn(NHFILE *nhfp)
flist = 0;
for (;;) {
fnext = newfruit();
if (nhfp->structlevel)
if (nhfp->structlevel) {
Mread(nhfp->fd, fnext, sizeof *fnext);
}
if (fnext->fid != 0) {
fnext->nextf = flist;
flist = fnext;
@@ -520,6 +543,7 @@ ghostfruit(struct obj *otmp)
staticfn boolean
restgamestate(NHFILE *nhfp)
{
int i;
struct flag newgameflags;
struct context_info newgamecontext; /* all 0, but has some pointers */
struct obj *otmp;
@@ -528,8 +552,9 @@ restgamestate(NHFILE *nhfp)
unsigned long uid = 0;
boolean defer_perm_invent, restoring_special;
if (nhfp->structlevel)
if (nhfp->structlevel) {
Mread(nhfp->fd, &uid, sizeof uid);
}
if (SYSOPT_CHECK_SAVE_UID
&& uid != (unsigned long) getuid()) { /* strange ... */
@@ -541,8 +566,9 @@ restgamestate(NHFILE *nhfp)
}
newgamecontext = svc.context; /* copy statically init'd context */
if (nhfp->structlevel)
if (nhfp->structlevel) {
Mread(nhfp->fd, &svc.context, sizeof svc.context);
}
svc.context.warntype.species = (ismnum(svc.context.warntype.speciesidx))
? &mons[svc.context.warntype.speciesidx]
: (struct permonst *) 0;
@@ -554,8 +580,9 @@ restgamestate(NHFILE *nhfp)
file option values instead of keeping old save file option values
if partial restore fails and we resort to starting a new game */
newgameflags = flags;
if (nhfp->structlevel)
if (nhfp->structlevel) {
Mread(nhfp->fd, &flags, sizeof flags);
}
/* avoid keeping permanent inventory window up to date during restore
(setworn() calls update_inventory); attempting to include the cost
@@ -583,8 +610,9 @@ restgamestate(NHFILE *nhfp)
#ifdef AMII_GRAPHICS
amii_setpens(amii_numcolors); /* use colors from save file */
#endif
if (nhfp->structlevel)
if (nhfp->structlevel) {
Mread(nhfp->fd, &u, sizeof u);
}
gy.youmonst.cham = u.mcham;
if (restoring_special && iflags.explore_error_flag) {
@@ -594,15 +622,17 @@ restgamestate(NHFILE *nhfp)
u.uhp = 0;
}
if (nhfp->structlevel)
if (nhfp->structlevel) {
Mread(nhfp->fd, timebuf, 14);
}
timebuf[14] = '\0';
ubirthday = time_from_yyyymmddhhmmss(timebuf);
if (nhfp->structlevel)
if (nhfp->structlevel) {
Mread(nhfp->fd, &urealtime.realtime, sizeof urealtime.realtime);
if (nhfp->structlevel)
}
if (nhfp->structlevel) {
Mread(nhfp->fd, timebuf, 14);
}
timebuf[14] = '\0';
urealtime.start_timing = time_from_yyyymmddhhmmss(timebuf);
@@ -653,10 +683,11 @@ restgamestate(NHFILE *nhfp)
gm.migrating_objs = restobjchn(nhfp, FALSE);
gm.migrating_mons = restmonchn(nhfp);
if (nhfp->structlevel) {
Mread(nhfp->fd, &svm.mvitals[0], sizeof svm.mvitals);
for (i = 0; i < NUMMONS; ++i) {
if (nhfp->structlevel) {
Mread(nhfp->fd, &svm.mvitals[i], sizeof (struct mvitals));
}
}
/*
* There are some things after this that can have unintended display
* side-effects too early in the game.
@@ -683,10 +714,17 @@ restgamestate(NHFILE *nhfp)
restlevchn(nhfp);
if (nhfp->structlevel) {
Mread(nhfp->fd, &svm.moves, sizeof svm.moves);
/* hero_seq isn't saved and restored because it can be recalculated */
gh.hero_seq = svm.moves << 3; /* normally handled in moveloop() */
}
/* hero_seq isn't saved and restored because it can be recalculated */
gh.hero_seq = svm.moves << 3; /* normally handled in moveloop() */
if (nhfp->structlevel) {
Mread(nhfp->fd, &svq.quest_status, sizeof svq.quest_status);
Mread(nhfp->fd, svs.spl_book, (MAXSPELL + 1) * sizeof (struct spell));
}
for (i = 0; i < (MAXSPELL + 1); ++i) {
if (nhfp->structlevel) {
Mread(nhfp->fd, &svs.spl_book[i],
sizeof (struct spell));
}
}
restore_artifacts(nhfp);
restore_oracles(nhfp);
@@ -819,9 +857,9 @@ dorecover(NHFILE *nhfp)
while (1) {
if (nhfp->structlevel) {
Mread(nhfp->fd, &ltmp, sizeof ltmp);
if (restoreinfo.mread_flags == -1)
break;
}
if (restoreinfo.mread_flags == -1)
break;
getlev(nhfp, 0, ltmp);
#ifdef MICRO
curs(WIN_MAP, 1 + dotcnt++, dotrow);
@@ -839,6 +877,7 @@ dorecover(NHFILE *nhfp)
return rtmp; /* dorecover called recursively */
}
restoreinfo.mread_flags = 0;
rewind_nhfile(nhfp); /* return to beginning of file */
(void) validate(nhfp, (char *) 0, FALSE);
get_plname_from_file(nhfp, svp.plname, TRUE);
@@ -939,14 +978,16 @@ restcemetery(NHFILE *nhfp, struct cemetery **cemeteryaddr)
struct cemetery *bonesinfo, **bonesaddr;
int cflag = 0;
if (nhfp->structlevel)
if (nhfp->structlevel) {
Mread(nhfp->fd, &cflag, sizeof cflag);
}
if (cflag == 0) {
bonesaddr = cemeteryaddr;
do {
bonesinfo = (struct cemetery *) alloc(sizeof *bonesinfo);
if (nhfp->structlevel)
if (nhfp->structlevel) {
Mread(nhfp->fd, bonesinfo, sizeof *bonesinfo);
}
*bonesaddr = bonesinfo;
bonesaddr = &(*bonesaddr)->next;
} while (*bonesaddr);
@@ -957,46 +998,16 @@ restcemetery(NHFILE *nhfp, struct cemetery **cemeteryaddr)
/*ARGSUSED*/
staticfn void
rest_levl(
NHFILE *nhfp,
#ifdef RLECOMP
boolean rlecomp
#else
boolean rlecomp UNUSED
#endif
)
rest_levl(NHFILE *nhfp)
{
#ifdef RLECOMP
short i, j;
uchar len;
struct rm r;
int c, r;
if (rlecomp) {
(void) memset((genericptr_t) &r, 0, sizeof(r));
i = 0;
j = 0;
len = 0;
while (i < ROWNO) {
while (j < COLNO) {
if (len > 0) {
levl[j][i] = r;
len -= 1;
j += 1;
} else {
if (nhfp->structlevel) {
Mread(nhfp->fd, &len, sizeof len);
Mread(nhfp->fd, &r, sizeof r);
}
}
for (c = 0; c < COLNO; ++c) {
for (r = 0; r < ROWNO; ++r) {
if (nhfp->structlevel) {
Mread(nhfp->fd, &levl[c][r], sizeof (struct rm));
}
j = 0;
i += 1;
}
return;
}
#endif /* RLECOMP */
if (nhfp->structlevel) {
Mread(nhfp->fd, levl, sizeof levl);
}
}
@@ -1015,12 +1026,14 @@ getlev(NHFILE *nhfp, int pid, xint8 lev)
{
struct trap *trap;
struct monst *mtmp;
long elapsed;
branch *br;
int x, y;
long elapsed = 0L;
int hpid = 0;
xint8 dlvl = 0;
int x, y;
int i, c, r;
boolean ghostly = (nhfp->ftype == NHF_BONESFILE);
coord *tmpc = 0;
#ifdef TOS
short tlev;
#endif
@@ -1041,18 +1054,13 @@ getlev(NHFILE *nhfp, int pid, xint8 lev)
go.oldfruit = loadfruitchn(nhfp);
/* First some sanity checks */
if (nhfp->structlevel)
if (nhfp->structlevel) {
Mread(nhfp->fd, &hpid, sizeof hpid);
}
/* CHECK: This may prevent restoration */
#ifdef TOS
if (nhfp->structlevel)
Mread(nhfp->fd, &tlev, sizeof tlev);
dlvl = tlev & 0x00ff;
#else
if (nhfp->structlevel)
if (nhfp->structlevel) {
Mread(nhfp->fd, &dlvl, sizeof dlvl);
#endif
}
if ((pid && pid != hpid) || (lev && dlvl != lev)) {
char trickbuf[BUFSZ];
@@ -1066,48 +1074,58 @@ getlev(NHFILE *nhfp, int pid, xint8 lev)
trickery(trickbuf);
}
restcemetery(nhfp, &svl.level.bonesinfo);
rest_levl(nhfp,
(boolean) ((sfrestinfo.sfi1 & SFI1_RLECOMP) == SFI1_RLECOMP));
if (nhfp->structlevel) {
Mread(nhfp->fd, svl.lastseentyp, sizeof svl.lastseentyp);
Mread(nhfp->fd, &go.omoves, sizeof go.omoves);
}
rest_levl(nhfp);
for (c = 0; c < COLNO; ++c)
for (r = 0; r < ROWNO; ++r) {
if (nhfp->structlevel) {
Mread(nhfp->fd, &svl.lastseentyp[c][r], sizeof (schar));
}
}
Mread(nhfp->fd, &go.omoves, sizeof go.omoves);
elapsed = svm.moves - go.omoves;
rest_stairs(nhfp);
if (nhfp->structlevel) {
rest_stairs(nhfp);
Mread(nhfp->fd, &svu.updest, sizeof svu.updest);
Mread(nhfp->fd, &svd.dndest, sizeof svd.dndest);
Mread(nhfp->fd, &svl.level.flags, sizeof svl.level.flags);
if (svd.doors) {
free(svd.doors);
svd.doors = 0;
}
}
if (svd.doors) {
free(svd.doors);
svd.doors = 0;
}
if (nhfp->structlevel) {
Mread(nhfp->fd, &svd.doors_alloc, sizeof svd.doors_alloc);
if (svd.doors_alloc) { /* avoid pointless alloc(0) */
svd.doors = (coord *) alloc(svd.doors_alloc * sizeof (coord));
Mread(nhfp->fd, svd.doors, svd.doors_alloc * sizeof (coord));
}
if (svd.doors_alloc) { /* avoid pointless alloc(0) */
svd.doors = (coord *) alloc(svd.doors_alloc * sizeof(coord));
tmpc = svd.doors;
for (i = 0; i < svd.doors_alloc; ++i) {
if (nhfp->structlevel) {
Mread(nhfp->fd, tmpc, sizeof (coord));
}
tmpc++;
}
}
rest_rooms(nhfp); /* No joke :-) */
if (svn.nroom)
if (svn.nroom) {
gd.doorindex = svr.rooms[svn.nroom - 1].fdoor
+ svr.rooms[svn.nroom - 1].doorct;
else
} else {
gd.doorindex = 0;
}
restore_timers(nhfp, RANGE_LEVEL, elapsed);
restore_light_sources(nhfp);
fmon = restmonchn(nhfp);
/* rest_worm(fd); */ /* restore worm information */
rest_worm(nhfp); /* restore worm information */
gf.ftrap = 0;
for (;;) {
trap = newtrap();
if (nhfp->structlevel)
if (nhfp->structlevel) {
Mread(nhfp->fd, trap, sizeof *trap);
}
if (trap->tx != 0) {
if (program_state.restoring != REST_GSTATE
&& trap->dst.dnum == u.uz.dnum) {
@@ -1298,8 +1316,9 @@ rest_bubbles(NHFILE *nhfp)
clouds are present is recorded during save so that we don't have to
know what level is being restored */
bbubbly = 0;
if (nhfp->structlevel)
if (nhfp->structlevel) {
Mread(nhfp->fd, &bbubbly, sizeof bbubbly);
}
if (bbubbly)
restore_waterlevel(nhfp);
@@ -1310,21 +1329,24 @@ restore_gamelog(NHFILE *nhfp)
{
int slen = 0;
char msg[BUFSZ*2];
struct gamelog_line tmp;
struct gamelog_line tmp = { 0 };
while (1) {
if (nhfp->structlevel)
if (nhfp->structlevel) {
Mread(nhfp->fd, &slen, sizeof slen);
}
if (slen == -1)
break;
if (slen > ((BUFSZ*2) - 1))
panic("restore_gamelog: msg too big (%d)", slen);
if (nhfp->structlevel) {
Mread(nhfp->fd, msg, slen);
Mread(nhfp->fd, &tmp, sizeof tmp);
msg[slen] = '\0';
gamelog_add(tmp.flags, tmp.turn, msg);
}
msg[slen] = '\0';
if (nhfp->structlevel) {
Mread(nhfp->fd, &tmp, sizeof tmp);
}
gamelog_add(tmp.flags, tmp.turn, msg);
}
}
@@ -1335,14 +1357,16 @@ restore_msghistory(NHFILE *nhfp)
char msg[BUFSZ];
while (1) {
if (nhfp->structlevel)
if (nhfp->structlevel) {
Mread(nhfp->fd, &msgsize, sizeof msgsize);
}
if (msgsize == -1)
break;
if (msgsize > BUFSZ - 1)
panic("restore_msghistory: msg too big (%d)", msgsize);
if (nhfp->structlevel)
if (nhfp->structlevel) {
Mread(nhfp->fd, msg, msgsize);
}
msg[msgsize] = '\0';
putmsghistory(msg, TRUE);
++msgcount;
@@ -1531,10 +1555,8 @@ restore_menu(
int
validate(NHFILE *nhfp, const char *name, boolean without_waitsynch_perfile)
{
readLenType rlen = 0;
struct savefile_info sfi;
unsigned long utdflags = 0L;
boolean verbose = name ? TRUE : FALSE, reslt = FALSE;
boolean reslt = FALSE;
if (nhfp->structlevel)
utdflags |= UTD_CHECKSIZES;
@@ -1543,24 +1565,6 @@ validate(NHFILE *nhfp, const char *name, boolean without_waitsynch_perfile)
if (!(reslt = uptodate(nhfp, name, utdflags)))
return 1;
if ((nhfp->mode & WRITING) == 0) {
if (nhfp->structlevel)
rlen = (readLenType) read(nhfp->fd, (genericptr_t) &sfi,
sizeof sfi);
} else {
if (nhfp->structlevel)
rlen = (readLenType) read(nhfp->fd, (genericptr_t) &sfi,
sizeof sfi);
minit(); /* ZEROCOMP */
if (rlen == 0) {
if (verbose) {
pline("File \"%s\" is empty during save file feature check?",
name);
wait_synch();
}
return -1;
}
}
return 0;
}

View File

@@ -596,21 +596,29 @@ init_oracles(dlb *fp)
void
save_oracles(NHFILE *nhfp)
{
int i;
if (perform_bwrite(nhfp)) {
if (nhfp->structlevel)
bwrite(nhfp->fd, (genericptr_t) &svo.oracle_cnt,
sizeof svo.oracle_cnt);
if (svo.oracle_cnt) {
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &svo.oracle_cnt,
sizeof svo.oracle_cnt);
}
if (svo.oracle_cnt) {
for (i = 0; (unsigned) i < svo.oracle_cnt; ++i) {
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) go.oracle_loc,
svo.oracle_cnt * sizeof (long));
bwrite(nhfp->fd, (genericptr_t) &go.oracle_loc[i],
sizeof (unsigned long));
}
}
}
}
if (release_data(nhfp)) {
if (svo.oracle_cnt) {
svo.oracle_cnt = 0, go.oracle_flg = 0;
}
if (go.oracle_loc) {
free((genericptr_t) go.oracle_loc);
go.oracle_loc = 0, svo.oracle_cnt = 0, go.oracle_flg = 0;
go.oracle_loc = 0;
}
}
}
@@ -618,14 +626,20 @@ save_oracles(NHFILE *nhfp)
void
restore_oracles(NHFILE *nhfp)
{
if (nhfp->structlevel)
mread(nhfp->fd, (genericptr_t) &svo.oracle_cnt, sizeof svo.oracle_cnt);
int i;
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) &svo.oracle_cnt,
sizeof svo.oracle_cnt);
}
if (svo.oracle_cnt) {
go.oracle_loc = (unsigned long *) alloc(svo.oracle_cnt * sizeof(long));
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) go.oracle_loc,
svo.oracle_cnt * sizeof (long));
go.oracle_loc =
(unsigned long *) alloc(svo.oracle_cnt * sizeof (unsigned long));
for (i = 0; (unsigned) i < svo.oracle_cnt; ++i) {
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) &go.oracle_loc[i],
sizeof (unsigned long));
}
}
go.oracle_flg = 1; /* no need to call init_oracles() */
}

View File

@@ -17,7 +17,7 @@ int dotcnt, dotrow; /* also used in restore */
#endif
staticfn void savelevchn(NHFILE *);
staticfn void savelevl(NHFILE *, boolean);
staticfn void savelevl(NHFILE *);
staticfn void savedamage(NHFILE *);
staticfn void save_bubbles(NHFILE *, xint8);
staticfn void save_stairs(NHFILE *);
@@ -158,7 +158,6 @@ dosave0(void)
#endif
nhfp->mode = WRITING | FREEING;
store_version(nhfp);
store_savefileinfo(nhfp);
if (nhfp && nhfp->fplog)
(void) fprintf(nhfp->fplog, "# post-validation\n");
store_plname_in_file(nhfp);
@@ -216,8 +215,9 @@ dosave0(void)
minit(); /* ZEROCOMP */
getlev(onhfp, svh.hackpid, ltmp);
close_nhfile(onhfp);
if (nhfp->structlevel)
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &ltmp, sizeof ltmp); /* lvl no. */
}
savelev(nhfp, ltmp); /* actual level*/
delete_levelfile(ltmp);
}
@@ -249,8 +249,8 @@ save_gamelog(NHFILE *nhfp)
while (tmp) {
tmp2 = tmp->next;
if (perform_bwrite(nhfp)) {
slen = Strlen(tmp->text);
if (nhfp->structlevel) {
slen = Strlen(tmp->text);
bwrite(nhfp->fd, (genericptr_t) &slen, sizeof slen);
bwrite(nhfp->fd, (genericptr_t) tmp->text, slen);
bwrite(nhfp->fd, (genericptr_t) tmp,
@@ -264,8 +264,8 @@ save_gamelog(NHFILE *nhfp)
tmp = tmp2;
}
if (perform_bwrite(nhfp)) {
slen = -1;
if (nhfp->structlevel) {
slen = -1;
bwrite(nhfp->fd, (genericptr_t) &slen, sizeof slen);
}
}
@@ -276,6 +276,7 @@ save_gamelog(NHFILE *nhfp)
staticfn void
savegamestate(NHFILE *nhfp)
{
int i;
unsigned long uid;
program_state.saving++; /* caller should/did already set this... */
@@ -314,8 +315,12 @@ savegamestate(NHFILE *nhfp)
savemonchn(nhfp, gm.migrating_mons);
if (release_data(nhfp))
gm.migrating_mons = (struct monst *) 0;
if (nhfp->structlevel)
bwrite(nhfp->fd, (genericptr_t) svm.mvitals, sizeof svm.mvitals);
for (i = 0; i < NUMMONS; ++i) {
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &svm.mvitals[i],
sizeof (struct mvitals));
}
}
save_dungeon(nhfp, (boolean) !!perform_bwrite(nhfp),
(boolean) !!release_data(nhfp));
savelevchn(nhfp);
@@ -323,8 +328,12 @@ savegamestate(NHFILE *nhfp)
bwrite(nhfp->fd, (genericptr_t) &svm.moves, sizeof svm.moves);
bwrite(nhfp->fd, (genericptr_t) &svq.quest_status,
sizeof svq.quest_status);
bwrite(nhfp->fd, (genericptr_t) svs.spl_book,
sizeof (struct spell) * (MAXSPELL + 1));
}
for (i = 0; i < (MAXSPELL + 1); ++i) {
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &svs.spl_book[i],
sizeof(struct spell));
}
}
save_artifacts(nhfp);
save_oracles(nhfp);
@@ -391,8 +400,9 @@ savestateinlock(void)
return;
}
if (nhfp->structlevel)
if (nhfp->structlevel) {
(void) read(nhfp->fd, (genericptr_t) &hpid, sizeof hpid);
}
if (svh.hackpid != hpid) {
Sprintf(whynot, "Level #0 pid (%d) doesn't match ours (%d)!",
hpid, svh.hackpid);
@@ -421,12 +431,12 @@ savestateinlock(void)
if (flags.ins_chkpt) {
int currlev = ledger_no(&u.uz);
if (nhfp->structlevel)
if (nhfp->structlevel) {
(void) write(nhfp->fd, (genericptr_t) &currlev,
sizeof currlev);
}
save_savefile_name(nhfp);
store_version(nhfp);
store_savefileinfo(nhfp);
store_plname_in_file(nhfp);
/* if ball and/or chain aren't on floor or in invent, keep a copy
@@ -472,6 +482,8 @@ savelev_core(NHFILE *nhfp, xint8 lev)
#ifdef TOS
short tlev;
#endif
int i, c, r;
coord *tmpc;
program_state.saving++; /* even if current mode is FREEING */
@@ -505,17 +517,10 @@ savelev_core(NHFILE *nhfp, xint8 lev)
if (lev >= 0 && lev <= maxledgerno())
svl.level_info[lev].flags |= VISITED;
if (nhfp->structlevel)
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &svh.hackpid, sizeof svh.hackpid);
#ifdef TOS
tlev = lev;
tlev &= 0x00ff;
if (nhfp->structlevel)
bwrite(nhfp->fd, (genericptr_t) &tlev, sizeof tlev);
#else
if (nhfp->structlevel)
bwrite(nhfp->fd, (genericptr_t) &lev, sizeof lev);
#endif
}
}
/* bones info comes before level data; the intent is for an external
@@ -528,23 +533,35 @@ savelev_core(NHFILE *nhfp, xint8 lev)
if (nhfp->mode == FREEING) /* see above */
goto skip_lots;
savelevl(nhfp, ((sfsaveinfo.sfi1 & SFI1_RLECOMP) == SFI1_RLECOMP));
savelevl(nhfp);
for (c = 0; c < COLNO; ++c)
for (r = 0; r < ROWNO; ++r) {
bwrite(nhfp->fd, (genericptr_t) &svl.lastseentyp[c][r],
sizeof(schar));
}
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) svl.lastseentyp,
sizeof svl.lastseentyp);
bwrite(nhfp->fd, (genericptr_t) &svm.moves, sizeof svm.moves);
save_stairs(nhfp);
bwrite(nhfp->fd, (genericptr_t) &svu.updest, sizeof (dest_area));
bwrite(nhfp->fd, (genericptr_t) &svd.dndest, sizeof (dest_area));
bwrite(nhfp->fd, (genericptr_t) &svu.updest, sizeof(dest_area));
bwrite(nhfp->fd, (genericptr_t) &svd.dndest, sizeof(dest_area));
bwrite(nhfp->fd, (genericptr_t) &svl.level.flags,
sizeof svl.level.flags);
}
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &svd.doors_alloc,
sizeof svd.doors_alloc);
/* don't rely on underlying write() behavior to write
* nothing if count arg is 0, just skip it */
if (svd.doors_alloc)
bwrite(nhfp->fd, (genericptr_t) svd.doors,
svd.doors_alloc * sizeof (coord));
}
/* don't rely on underlying write() behavior to write
* nothing if count arg is 0, just skip it */
if (svd.doors_alloc) {
tmpc = svd.doors;
for (i = 0; i < svd.doors_alloc; ++i) {
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) tmpc,
sizeof (coord));
}
tmpc++;
}
}
save_rooms(nhfp); /* no dynamic memory to reclaim */
@@ -582,61 +599,17 @@ savelev_core(NHFILE *nhfp, xint8 lev)
}
staticfn void
savelevl(NHFILE *nhfp, boolean rlecomp)
savelevl(NHFILE *nhfp)
{
#ifdef RLECOMP
struct rm *prm, *rgrm;
int x, y;
uchar match;
if (rlecomp) {
/* perform run-length encoding of rm structs */
rgrm = &levl[0][0]; /* start matching at first rm */
match = 0;
for (x = 0; x < COLNO; x++) {
for (y = 0; y < ROWNO; y++) {
for (x = 0; x < COLNO; x++) {
prm = &levl[x][y];
if (prm->glyph == rgrm->glyph && prm->typ == rgrm->typ
&& prm->seenv == rgrm->seenv
&& prm->horizontal == rgrm->horizontal
&& prm->flags == rgrm->flags && prm->lit == rgrm->lit
&& prm->waslit == rgrm->waslit
&& prm->roomno == rgrm->roomno && prm->edge == rgrm->edge
&& prm->candig == rgrm->candig) {
match++;
if (match > 254) {
match = 254; /* undo this match */
goto writeout;
}
} else {
/* run has been broken, write out run-length encoding */
writeout:
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &match, sizeof match);
bwrite(nhfp->fd, (genericptr_t) rgrm, sizeof *rgrm);
}
/* start encoding again. we have at least 1 rm
in the next run, viz. this one. */
match = 1;
rgrm = prm;
}
}
}
if (match > 0) {
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &match, sizeof (uchar));
bwrite(nhfp->fd, (genericptr_t) rgrm, sizeof (struct rm));
bwrite(nhfp->fd, (genericptr_t) &levl[x][y],
sizeof(struct rm));
}
}
return;
}
#else /* !RLECOMP */
nhUse(rlecomp);
#endif /* ?RLECOMP */
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) levl, sizeof levl);
}
return;
}
@@ -656,8 +629,9 @@ save_bubbles(NHFILE *nhfp, xint8 lev)
bbubbly = 0;
if (lev == ledger_no(&water_level) || lev == ledger_no(&air_level))
bbubbly = lev; /* non-zero */
if (nhfp->structlevel)
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &bbubbly, sizeof bbubbly);
}
if (bbubbly)
save_waterlevel(nhfp); /* save air bubbles or clouds */
@@ -672,15 +646,17 @@ savecemetery(NHFILE *nhfp, struct cemetery **cemeteryaddr)
flag = *cemeteryaddr ? 0 : -1;
if (perform_bwrite(nhfp)) {
if (nhfp->structlevel)
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &flag, sizeof flag);
}
}
nextbones = *cemeteryaddr;
while ((thisbones = nextbones) != 0) {
nextbones = thisbones->next;
if (perform_bwrite(nhfp)) {
if (nhfp->structlevel)
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) thisbones, sizeof *thisbones);
}
}
if (release_data(nhfp))
free((genericptr_t) thisbones);
@@ -699,13 +675,15 @@ savedamage(NHFILE *nhfp)
for (tmp_dam = damageptr; tmp_dam; tmp_dam = tmp_dam->next)
xl++;
if (perform_bwrite(nhfp)) {
if (nhfp->structlevel)
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &xl, sizeof xl);
}
}
while (damageptr) {
if (perform_bwrite(nhfp)) {
if (nhfp->structlevel)
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) damageptr, sizeof *damageptr);
}
}
tmp_dam = damageptr;
damageptr = damageptr->next;
@@ -793,33 +771,38 @@ saveobj(NHFILE *nhfp, struct obj *otmp)
}
if (otmp->oextra) {
buflen = ONAME(otmp) ? (int) strlen(ONAME(otmp)) + 1 : 0;
if (nhfp->structlevel)
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &buflen, sizeof buflen);
}
if (buflen > 0) {
if (nhfp->structlevel)
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) ONAME(otmp), buflen);
}
}
/* defer to savemon() for this one */
if (OMONST(otmp)) {
savemon(nhfp, OMONST(otmp));
} else {
if (nhfp->structlevel)
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &zerobuf, sizeof zerobuf);
}
}
/* extra info about scroll of mail */
buflen = OMAILCMD(otmp) ? (int) strlen(OMAILCMD(otmp)) + 1 : 0;
if (nhfp->structlevel)
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &buflen, sizeof buflen);
}
if (buflen > 0) {
if (nhfp->structlevel)
bwrite(nhfp->fd, (genericptr_t) OMAILCMD(otmp), buflen);
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) OMAILCMD(otmp), buflen);
}
}
/* omid used to be indirect via a pointer in oextra but has
become part of oextra itself; 0 means not applicable and
gets saved/restored whenever any other oextra components do */
if (nhfp->structlevel)
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &OMID(otmp), sizeof OMID(otmp));
}
}
}
@@ -878,8 +861,9 @@ saveobjchn(NHFILE *nhfp, struct obj **obj_p)
otmp = otmp2;
}
if (perform_bwrite(nhfp)) {
if (nhfp->structlevel)
bwrite(nhfp->fd, (genericptr_t) &minusone, sizeof (int));
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &minusone, sizeof(int));
}
}
if (release_data(nhfp)) {
if (is_invent)
@@ -902,59 +886,74 @@ savemon(NHFILE *nhfp, struct monst *mtmp)
}
if (mtmp->mextra) {
buflen = MGIVENNAME(mtmp) ? (int) strlen(MGIVENNAME(mtmp)) + 1 : 0;
if (nhfp->structlevel)
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &buflen, sizeof buflen);
}
if (buflen > 0) {
if (nhfp->structlevel)
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) MGIVENNAME(mtmp), buflen);
}
}
buflen = EGD(mtmp) ? (int) sizeof (struct egd) : 0;
if (nhfp->structlevel)
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &buflen, sizeof buflen);
}
if (buflen > 0) {
if (nhfp->structlevel)
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) EGD(mtmp), buflen);
}
}
buflen = EPRI(mtmp) ? (int) sizeof (struct epri) : 0;
if (nhfp->structlevel)
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &buflen, sizeof buflen);
}
if (buflen > 0) {
if (nhfp->structlevel)
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) EPRI(mtmp), buflen);
}
}
buflen = ESHK(mtmp) ? (int) sizeof (struct eshk) : 0;
if (nhfp->structlevel)
bwrite(nhfp->fd, (genericptr_t) &buflen, sizeof (int));
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &buflen, sizeof(int));
}
if (buflen > 0) {
if (nhfp->structlevel)
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) ESHK(mtmp), buflen);
}
}
buflen = EMIN(mtmp) ? (int) sizeof (struct emin) : 0;
if (nhfp->structlevel)
bwrite(nhfp->fd, (genericptr_t) &buflen, sizeof (int));
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &buflen, sizeof(int));
}
if (buflen > 0) {
if (nhfp->structlevel)
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) EMIN(mtmp), buflen);
}
}
buflen = EDOG(mtmp) ? (int) sizeof (struct edog) : 0;
if (nhfp->structlevel)
bwrite(nhfp->fd, (genericptr_t) &buflen, sizeof (int));
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &buflen, sizeof(int));
}
if (buflen > 0) {
if (nhfp->structlevel)
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) EDOG(mtmp), buflen);
}
}
buflen = EBONES(mtmp) ? (int) sizeof (struct ebones) : 0;
if (nhfp->structlevel)
bwrite(nhfp->fd, (genericptr_t) &buflen, sizeof (int));
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &buflen, sizeof(int));
}
if (buflen > 0) {
if (nhfp->structlevel)
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) EBONES(mtmp), buflen);
}
}
/* mcorpsenm is inline int rather than pointer to something,
so doesn't need to be preceded by a length field */
if (nhfp->structlevel)
bwrite(nhfp->fd, (genericptr_t) &MCORPSENM(mtmp),
sizeof MCORPSENM(mtmp));
buflen = (int) MCORPSENM(mtmp);
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &buflen, sizeof (int));
}
}
}
@@ -989,8 +988,9 @@ savemonchn(NHFILE *nhfp, struct monst *mtmp)
mtmp = mtmp2;
}
if (perform_bwrite(nhfp)) {
if (nhfp->structlevel)
bwrite(nhfp->fd, (genericptr_t) &minusone, sizeof (int));
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &minusone, sizeof(int));
}
}
}
@@ -1008,8 +1008,9 @@ savetrapchn(NHFILE *nhfp, struct trap *trap)
if (use_relative)
trap->dst.dlevel -= u.uz.dlevel; /* make it relative */
if (perform_bwrite(nhfp)) {
if (nhfp->structlevel)
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) trap, sizeof *trap);
}
}
if (use_relative)
trap->dst.dlevel += u.uz.dlevel; /* reset back to absolute */
@@ -1018,8 +1019,9 @@ savetrapchn(NHFILE *nhfp, struct trap *trap)
trap = trap2;
}
if (perform_bwrite(nhfp)) {
if (nhfp->structlevel)
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &zerotrap, sizeof zerotrap);
}
}
}
@@ -1038,16 +1040,18 @@ savefruitchn(NHFILE *nhfp)
while (f1) {
f2 = f1->nextf;
if (f1->fid >= 0 && perform_bwrite(nhfp)) {
if (nhfp->structlevel)
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) f1, sizeof *f1);
}
}
if (release_data(nhfp))
dealloc_fruit(f1);
f1 = f2;
}
if (perform_bwrite(nhfp)) {
if (nhfp->structlevel)
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &zerofruit, sizeof zerofruit);
}
}
if (release_data(nhfp))
gf.ffruit = 0;
@@ -1062,14 +1066,16 @@ savelevchn(NHFILE *nhfp)
for (tmplev = svs.sp_levchn; tmplev; tmplev = tmplev->next)
cnt++;
if (perform_bwrite(nhfp)) {
if (nhfp->structlevel)
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &cnt, sizeof cnt);
}
}
for (tmplev = svs.sp_levchn; tmplev; tmplev = tmplev2) {
tmplev2 = tmplev->next;
if (perform_bwrite(nhfp)) {
if (nhfp->structlevel)
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) tmplev, sizeof *tmplev);
}
}
if (release_data(nhfp))
free((genericptr_t) tmplev);
@@ -1124,7 +1130,7 @@ save_msghistory(NHFILE *nhfp)
/* ask window port for each message in sequence */
while ((msg = getmsghistory(init)) != 0) {
init = FALSE;
msglen = Strlen(msg);
msglen = (int) Strlen(msg);
if (msglen < 1)
continue;
/* sanity: truncate if necessary (shouldn't happen);
@@ -1137,37 +1143,14 @@ save_msghistory(NHFILE *nhfp)
}
++msgcount;
}
if (nhfp->structlevel)
bwrite(nhfp->fd, (genericptr_t) &minusone, sizeof (int));
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &minusone, sizeof(int));
}
}
debugpline1("Stored %d messages into savefile.", msgcount);
/* note: we don't attempt to handle release_data() here */
}
void
store_savefileinfo(NHFILE *nhfp)
{
/* sfcap (decl.c) describes the savefile feature capabilities
* that are supported by this port/platform build.
*
* sfsaveinfo (decl.c) describes the savefile info that actually
* gets written into the savefile, and is used to determine the
* save file being written.
*
* sfrestinfo (decl.c) describes the savefile info that is
* being used to read the information from an existing savefile.
*/
if (nhfp->structlevel) {
bufoff(nhfp->fd);
/* bwrite() before bufon() uses plain write() */
bwrite(nhfp->fd, (genericptr_t) &sfsaveinfo,
(unsigned) sizeof sfsaveinfo);
bufon(nhfp->fd);
}
return;
}
/* also called by prscore(); this probably belongs in dungeon.c... */
void
free_dungeons(void)

View File

@@ -2496,22 +2496,25 @@ write_timer(NHFILE *nhfp, timer_element *timer)
case TIMER_GLOBAL:
case TIMER_LEVEL:
/* assume no pointers in arg */
if (nhfp->structlevel)
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) timer, sizeof(timer_element));
}
break;
case TIMER_OBJECT:
if (timer->needs_fixup) {
if (nhfp->structlevel)
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) timer, sizeof(timer_element));
}
} else {
/* replace object pointer with id */
arg_save.a_obj = timer->arg.a_obj;
timer->arg = cg.zeroany;
timer->arg.a_uint = (arg_save.a_obj)->o_id;
timer->needs_fixup = 1;
if (nhfp->structlevel)
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) timer, sizeof(timer_element));
}
timer->arg.a_obj = arg_save.a_obj;
timer->needs_fixup = 0;
}
@@ -2519,16 +2522,18 @@ write_timer(NHFILE *nhfp, timer_element *timer)
case TIMER_MONSTER:
if (timer->needs_fixup) {
if (nhfp->structlevel)
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) timer, sizeof(timer_element));
}
} else {
/* replace monster pointer with id */
arg_save.a_monst = timer->arg.a_monst;
timer->arg = cg.zeroany;
timer->arg.a_uint = (arg_save.a_monst)->m_id;
timer->needs_fixup = 1;
if (nhfp->structlevel)
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) timer, sizeof(timer_element));
}
timer->arg.a_monst = arg_save.a_monst;
timer->needs_fixup = 0;
}
@@ -2662,13 +2667,15 @@ save_timers(NHFILE *nhfp, int range)
if (perform_bwrite(nhfp)) {
if (range == RANGE_GLOBAL) {
if (nhfp->structlevel)
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &svt.timer_id,
sizeof svt.timer_id);
}
}
count = maybe_write_timer(nhfp, range, FALSE);
if (nhfp->structlevel)
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &count, sizeof count);
}
(void) maybe_write_timer(nhfp, range, TRUE);
}
@@ -2703,19 +2710,22 @@ restore_timers(NHFILE *nhfp, int range, long adjust)
boolean ghostly = (nhfp->ftype == NHF_BONESFILE); /* from a ghost level */
if (range == RANGE_GLOBAL) {
if (nhfp->structlevel)
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) &svt.timer_id,
sizeof svt.timer_id);
}
}
/* restore elements */
if (nhfp->structlevel)
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) &count, sizeof count);
}
while (count-- > 0) {
curr = (timer_element *) alloc(sizeof(timer_element));
if (nhfp->structlevel)
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) curr, sizeof(timer_element));
}
if (ghostly)
curr->timeout += adjust;
insert_timer(curr);

View File

@@ -70,12 +70,14 @@ void
save_track(NHFILE *nhfp)
{
if (perform_bwrite(nhfp)) {
if (nhfp->structlevel) {
int i;
int i;
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &utcnt, sizeof utcnt);
bwrite(nhfp->fd, (genericptr_t) &utpnt, sizeof utpnt);
for (i = 0; i < utcnt; i++) {
}
for (i = 0; i < utcnt; i++) {
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &utrack[i].x,
sizeof utrack[i].x);
bwrite(nhfp->fd, (genericptr_t) &utrack[i].y,
@@ -91,14 +93,16 @@ save_track(NHFILE *nhfp)
void
rest_track(NHFILE *nhfp)
{
if (nhfp->structlevel) {
int i;
int i;
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) &utcnt, sizeof utcnt);
mread(nhfp->fd, (genericptr_t) &utpnt, sizeof utpnt);
if (utcnt > UTSZ || utpnt > UTSZ)
panic("rest_track: impossible pt counts");
for (i = 0; i < utcnt; i++) {
}
if (utcnt > UTSZ || utpnt > UTSZ)
panic("rest_track: impossible pt counts");
for (i = 0; i < utcnt; i++) {
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) &utrack[i].x, sizeof utrack[i].x);
mread(nhfp->fd, (genericptr_t) &utrack[i].y, sizeof utrack[i].y);
}

View File

@@ -275,14 +275,14 @@ early_version_info(boolean pastebuf)
char buf1[BUFSZ], buf2[BUFSZ];
char *buf, *tmp;
Snprintf(buf1, sizeof(buf1), "test");
Snprintf(buf1, sizeof buf1, "test");
/* this is early enough that we have to do our own line-splitting */
getversionstring(buf1, sizeof buf1);
tmp = strstri(buf1, " ("); /* split at start of version info */
if (tmp) {
/* retain one buffer so that it all goes into the paste buffer */
*tmp++ = '\0';
Snprintf(buf2, sizeof(buf2), "%s\n%s", buf1, tmp);
Snprintf(buf2, sizeof (buf2),"%s\n%s", buf1, tmp);
buf = buf2;
} else {
buf = buf1;
@@ -389,10 +389,6 @@ check_version(
!= (nomakedefs.version_features & ~nomakedefs.ignored_features)
|| ((utdflags & UTD_SKIP_SANITY1) == 0
&& version_data->entity_count != nomakedefs.version_sanity1)
|| ((utdflags & UTD_CHECKSIZES) != 0
&& version_data->struct_sizes1 != nomakedefs.version_sanity2)
|| ((utdflags & UTD_CHECKSIZES) != 0
&& version_data->struct_sizes2 != nomakedefs.version_sanity3)
) {
if (complain) {
pline("Configuration incompatibility for file \"%s\".", filename);
@@ -403,69 +399,11 @@ check_version(
return TRUE;
}
/* this used to be based on file date and somewhat OS-dependent,
but now examines the initial part of the file's contents */
boolean
uptodate(NHFILE *nhfp, const char *name, unsigned long utdflags)
{
ssize_t rlen = 0;
int cmc = 0, filecmc = 0;
struct version_info vers_info;
boolean verbose = name ? TRUE : FALSE;
char indicator;
if (nhfp->structlevel) {
rlen = read(nhfp->fd, (genericptr_t) &indicator, sizeof indicator);
if (rlen != sizeof indicator)
return FALSE;
rlen = read(nhfp->fd, (genericptr_t) &filecmc, sizeof filecmc);
if (rlen == 0)
return FALSE;
}
if (cmc != filecmc)
return FALSE;
rlen = read(nhfp->fd, (genericptr_t) &vers_info, sizeof vers_info);
minit(); /* ZEROCOMP */
if (rlen == 0) {
if (verbose) {
pline("File \"%s\" is empty?", name);
if ((utdflags & UTD_WITHOUT_WAITSYNCH_PERFILE) == 0)
wait_synch();
}
return FALSE;
}
if (!check_version(&vers_info, name, verbose, utdflags)) {
if (verbose) {
if ((utdflags & UTD_WITHOUT_WAITSYNCH_PERFILE) == 0)
wait_synch();
}
return FALSE;
}
return TRUE;
}
void
store_formatindicator(NHFILE *nhfp)
{
char indicate = 'u';
int cmc = 0;
if (nhfp->mode & WRITING) {
if (nhfp->structlevel) {
indicate = 'h'; /* historical */
bwrite(nhfp->fd, (genericptr_t) &indicate, sizeof indicate);
bwrite(nhfp->fd, (genericptr_t) &cmc, sizeof cmc);
}
}
}
void
store_version(NHFILE *nhfp)
{
struct version_info version_data = {
0UL, 0UL, 0UL, 0UL, 0UL
0UL, 0UL, 0UL,
};
/* actual version number */
@@ -474,19 +412,19 @@ store_version(NHFILE *nhfp)
version_data.feature_set = nomakedefs.version_features;
/* # of monsters and objects */
version_data.entity_count = nomakedefs.version_sanity1;
/* size of key structs */
version_data.struct_sizes1 = nomakedefs.version_sanity2;
/* size of more key structs */
version_data.struct_sizes2 = nomakedefs.version_sanity3;
if (nhfp->structlevel) {
/* bwrite() before bufon() uses plain write() */
if (nhfp->structlevel)
bufoff(nhfp->fd);
/* bwrite() before bufon() uses plain write() */
store_formatindicator(nhfp);
store_critical_bytes(nhfp);
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &version_data,
(unsigned) (sizeof version_data));
bufon(nhfp->fd);
}
if (nhfp->structlevel)
bufon(nhfp->fd);
return;
}
@@ -566,16 +504,242 @@ dump_version_info(void)
if (strlen(hname) > 33)
hname = eos(nhStr(hname)) - 33; /* discard const for eos() */
runtime_info_init();
Snprintf(buf, sizeof buf, "%-12.33s %08lx %08lx %08lx %08lx %08lx",
Snprintf(buf, sizeof buf, "%-12.33s %08lx %08lx %08lx",
hname,
nomakedefs.version_number,
(nomakedefs.version_features & ~nomakedefs.ignored_features),
nomakedefs.version_sanity1,
nomakedefs.version_sanity2,
nomakedefs.version_sanity3);
nomakedefs.version_sanity1);
raw_print(buf);
release_runtime_info();
return;
}
struct critical_sizes_with_names {
uchar ucsize;
const char *nm;
};
struct critical_sizes_with_names critical_sizes[] = {
{ 0, "unused" },
/* simple types, that don't have subfields */
{ (uchar) sizeof(short), "short" },
{ (uchar) sizeof(int), "int" },
{ (uchar) sizeof(long), "long" },
{ (uchar) sizeof(long long), "long long" },
{ (uchar) sizeof(genericptr_t), "genericptr_t" },
{ (uchar) sizeof(aligntyp), "aligntyp" },
{ (uchar) sizeof(boolean), "boolean" },
{ (uchar) sizeof(coordxy), "coordxy" },
{ (uchar) sizeof(int16), "int16" },
{ (uchar) sizeof(int32), "int32" },
{ (uchar) sizeof(int64), "int64" },
{ (uchar) sizeof(schar), "schar" },
{ (uchar) sizeof(size_t), "size_t" },
{ (uchar) sizeof(uchar), "uchar" },
{ (uchar) sizeof(uint16), "uint16" },
{ (uchar) sizeof(uint32), "uint32" },
{ (uchar) sizeof(uint64), "uint64" },
{ (uchar) sizeof(ulong), "ulong" },
{ (uchar) sizeof(unsigned), "unsigned" },
{ (uchar) sizeof(ushort), "ushort" },
{ (uchar) sizeof(xint16), "xint16" },
{ (uchar) sizeof(xint8), "xint8" },
/* complex - they break down into one or more simple types */
{ (uchar) sizeof(struct arti_info), "struct arti_info" },
{ (uchar) sizeof(struct nhrect), "struct nhrect" },
{ (uchar) sizeof(struct branch), "struct branch" },
{ (uchar) sizeof(struct bubble), "struct bubble" },
{ (uchar) sizeof(struct cemetery), "struct cemetery" },
{ (uchar) sizeof(struct context_info), "struct context_info" },
{ (uchar) sizeof(struct nhcoord), "struct nhcoord" },
{ (uchar) sizeof(struct damage), "struct damage" },
{ (uchar) sizeof(struct dest_area), "struct dest_area" },
{ (uchar) sizeof(struct dgn_topology), "struct dgn_topology" },
{ (uchar) sizeof(struct dungeon), "struct dungeon" },
{ (uchar) sizeof(struct d_level), "struct d_level" },
{ (uchar) sizeof(struct ebones), "struct ebones" },
{ (uchar) sizeof(struct edog), "struct edog" },
{ (uchar) sizeof(struct egd), "struct egd" },
{ (uchar) sizeof(struct emin), "struct emin" },
{ (uchar) sizeof(struct engr), "struct engr" },
{ (uchar) sizeof(struct epri), "struct epri" },
{ (uchar) sizeof(struct eshk), "struct eshk" },
{ (uchar) sizeof(struct fe), "struct fe" },
{ (uchar) sizeof(struct flag), "struct flag" },
{ (uchar) sizeof(struct fruit), "struct fruit" },
{ (uchar) sizeof(struct gamelog_line), "struct gamelog_line" },
{ (uchar) sizeof(struct kinfo), "struct kinfo" },
{ (uchar) sizeof(struct levelflags), "struct levelflags" },
{ (uchar) sizeof(struct ls_t), "struct ls_t" },
{ (uchar) sizeof(struct linfo), "struct linfo" },
{ (uchar) sizeof(struct mapseen_feat), "struct mapseen_feat" },
{ (uchar) sizeof(struct mapseen_flags), "struct mapseen_flags" },
{ (uchar) sizeof(struct mapseen_rooms), "struct mapseen_rooms" },
{ (uchar) sizeof(struct mextra), "struct mextra" },
{ (uchar) sizeof(struct mkroom), "struct mkroom" },
{ (uchar) sizeof(struct monst), "struct monst" },
{ (uchar) sizeof(struct mvitals), "struct mvitals" },
{ (uchar) sizeof(struct obj), "struct obj" },
{ (uchar) sizeof(struct objclass), "struct objclass" },
{ (uchar) sizeof(struct q_score), "struct q_score" },
{ (uchar) sizeof(struct rm), "struct rm" },
{ (uchar) sizeof(struct spell), "struct spell" },
{ (uchar) sizeof(struct stairway), "struct stairway" },
{ (uchar) sizeof(struct s_level), "struct s_level" },
{ (uchar) sizeof(struct trap), "struct trap" },
{ (uchar) sizeof(struct version_info), "struct version_info" },
{ (uchar) sizeof(anything), "anything" },
/* struct you requires 2 bytes */
{ (uchar) ((sizeof(struct you) & 0x00FF)), "you_LO" },
{ (uchar) ((sizeof(struct you) & 0xFF00) >> 8), "you_HI" },
#ifdef SF_INCLUDE_SUBSTRUCTS
/*
* the ones below are substructures of the ones
* above, so there is no need to check these directly.
*/
{ (uchar) sizeof(struct attribs), "struct attribs" },
{ (uchar) sizeof(struct dig_info), "struct dig_info" },
{ (uchar) sizeof(struct tin_info), "struct tin_info" },
{ (uchar) sizeof(struct book_info), "struct book_info" },
{ (uchar) sizeof(struct takeoff_info), "struct takeoff_info" },
{ (uchar) sizeof(struct victual_info), "struct victual_info" },
{ (uchar) sizeof(struct engrave_info), "struct engrave_info" },
{ (uchar) sizeof(struct warntype_info), "struct warntype_info" },
{ (uchar) sizeof(struct polearm_info), "struct polearm_info" },
{ (uchar) sizeof(struct obj_split), "struct obj_split" },
{ (uchar) sizeof(struct tribute_info), "struct tribute_info" },
{ (uchar) sizeof(struct novel_tracking), "struct novel_tracking" },
{ (uchar) sizeof(struct achievement_tracking),
"struct achievement_tracking" },
{ (uchar) sizeof(struct d_flags), "struct d_flags" },
{ (uchar) sizeof(struct mapseen), "struct mapseen" },
{ (uchar) sizeof(struct fakecorridor), "struct fakecorridor" },
{ (uchar) sizeof(struct bill_x), "struct bill_x" },
{ (uchar) sizeof(union vptrs), "union vptrs" },
{ (uchar) sizeof(struct oextra), "struct oextra" },
{ (uchar) sizeof(struct prop), "struct prop" },
{ (uchar) sizeof(struct skills), "struct skills" },
{ (uchar) sizeof(union vlaunchinfo), "union vlaunchinfo" },
{ (uchar) sizeof(struct u_have), "struct u_have" },
{ (uchar) sizeof(struct u_event), "struct u_event" },
{ (uchar) sizeof(struct u_realtime), "struct u_realtime" },
{ (uchar) sizeof(struct u_conduct), "struct u_conduct" },
{ (uchar) sizeof(struct u_roleplay), "struct u_roleplay" },
#endif /* SF_INCLUDE_SUBSTRUCTS */
/* 10 for future expansion without changing array size */
{ 0, "" },
{ 0, "" },
{ 0, "" },
{ 0, "" },
{ 0, "" },
{ 0, "" },
{ 0, "" },
{ 0, "" },
{ 0, "" },
{ 0, "" },
};
uchar cscbuf[SIZE(critical_sizes)];
int
get_critical_size_count(void)
{
return SIZE(critical_sizes);
}
void
store_critical_bytes(NHFILE *nhfp)
{
int i, cnt;
char indicate = 'u', csc_count = (char) SIZE(critical_sizes);
/* int cmc = 0; */
if (nhfp->mode & WRITING) {
indicate = (nhfp->structlevel) ? 'h'
: (nhfp->fnidx == ascii) ? 'a'
: 'l';
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &indicate,
(unsigned) sizeof indicate);
}
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &csc_count,
(unsigned) sizeof csc_count);
}
cnt = (int) csc_count;
for (i = 0; i < cnt; ++i) {
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &critical_sizes[i].ucsize,
(unsigned) sizeof (uchar));
}
}
}
}
/* this used to be based on file date and somewhat OS-dependent,
but now examines the initial part of the file's contents */
boolean
uptodate(NHFILE *nhfp, const char *name, unsigned long utdflags)
{
struct version_info vers_info;
char indicator;
boolean verbose = name ? TRUE : FALSE;
int ccbresult = 0;
/* int you_size = (int) sizeof (struct you); */
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) &indicator, sizeof indicator);
}
if ((ccbresult = compare_critical_bytes(nhfp)) != 0) {
if (ccbresult > 0) {
raw_printf("compare of critical bytes failed at %d (%s).",
critical_sizes[ccbresult].ucsize,
critical_sizes[ccbresult].nm);
}
return FALSE;
}
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) &vers_info, sizeof vers_info);
}
if (!check_version(&vers_info, name, verbose, utdflags)) {
if (verbose) {
if ((utdflags & UTD_WITHOUT_WAITSYNCH_PERFILE) == 0)
wait_synch();
}
return FALSE;
}
return TRUE;
}
int
compare_critical_bytes(NHFILE *nhfp)
{
char active_csc_count = (char) SIZE(critical_sizes),
file_csc_count = 0;
int i, cnt = (int) active_csc_count;
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) &file_csc_count,
sizeof file_csc_count);
}
if (file_csc_count > cnt) {
raw_printf("critical byte counts do not match"
", file:%d, critical_sizes:%d.",
file_csc_count, SIZE(critical_sizes));
return -1;
}
for (i = 0; i < (int) file_csc_count; ++i) {
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) &cscbuf[i],
sizeof (uchar));
}
}
for (i = 1; i < cnt; ++i) {
if (cscbuf[i] != critical_sizes[i].ucsize)
return i;
}
return 0; /* everything matched */
}
/*version.c*/

View File

@@ -532,8 +532,9 @@ save_worm(NHFILE *nhfp)
for (count = 0, curr = wtails[i]; curr; curr = curr->nseg)
count++;
/* Save number of segments */
if (nhfp->structlevel)
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &count, sizeof count);
}
/* Save segment locations of the monster. */
if (count) {
for (curr = wtails[i]; curr; curr = curr->nseg) {
@@ -546,8 +547,10 @@ save_worm(NHFILE *nhfp)
}
}
}
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) wgrowtime, sizeof wgrowtime);
for (i = 0; i < MAX_NUM_WORMS; ++i) {
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &wgrowtime[i], sizeof (long));
}
}
}
@@ -581,8 +584,9 @@ rest_worm(NHFILE *nhfp)
struct wseg *curr, *temp;
for (i = 1; i < MAX_NUM_WORMS; i++) {
if (nhfp->structlevel)
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) &count, sizeof count);
}
/* Get the segments. */
for (curr = (struct wseg *) 0, j = 0; j < count; j++) {
@@ -600,8 +604,10 @@ rest_worm(NHFILE *nhfp)
}
wheads[i] = curr;
}
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) wgrowtime, sizeof wgrowtime);
for (i = 0; i < MAX_NUM_WORMS; ++i) {
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) &wgrowtime[i], sizeof (long));
}
}
}