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:
78
src/mdlib.c
78
src/mdlib.c
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user