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 */
}