From a3e12550eafda69685fdf24c9cd07a9ceb1967bd Mon Sep 17 00:00:00 2001 From: nhmall Date: Tue, 15 Apr 2025 15:35:17 -0400 Subject: [PATCH] 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. --- include/artifact.h | 18 +++ include/config.h | 32 ----- include/dungeon.h | 111 +++++++------- include/extern.h | 7 + include/global.h | 4 - include/integer.h | 5 + include/patchlevel.h | 2 +- include/wintype.h | 2 + src/artifact.c | 45 +++--- src/bones.c | 34 ++--- src/date.c | 4 - src/decl.c | 28 ---- src/dungeon.c | 109 +++++++++----- src/end.c | 8 +- src/engrave.c | 9 +- src/files.c | 17 +-- src/light.c | 12 +- src/mdlib.c | 78 +++++----- src/mkmaze.c | 6 +- src/mkroom.c | 18 ++- src/nhlua.c | 21 +-- src/o_init.c | 24 +++- src/region.c | 60 ++++---- src/restore.c | 334 ++++++++++++++++++++++--------------------- src/rumors.c | 40 ++++-- src/save.c | 283 +++++++++++++++++------------------- src/timeout.c | 30 ++-- src/track.c | 20 +-- src/version.c | 318 ++++++++++++++++++++++++++++++---------- src/worm.c | 18 ++- sys/share/pcmain.c | 5 +- util/makedefs.c | 12 -- 32 files changed, 962 insertions(+), 752 deletions(-) diff --git a/include/artifact.h b/include/artifact.h index 9d66ad33f..2db7270fb 100644 --- a/include/artifact.h +++ b/include/artifact.h @@ -5,6 +5,10 @@ #ifndef ARTIFACT_H #define ARTIFACT_H + +#include "permonst.h" +#include "prop.h" + /* clang-format off */ #define SPFX_NONE 0x00000000L /* no special effects, just a bonus */ @@ -73,5 +77,19 @@ enum invoke_prop_types { BLINDING_RAY }; +/* 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 */ +}; + /* clang-format on */ #endif /* ARTIFACT_H */ diff --git a/include/config.h b/include/config.h index a7097b363..14bfdc2e8 100644 --- a/include/config.h +++ b/include/config.h @@ -397,38 +397,6 @@ /* # define ZLIB_COMP */ /* ZLIB for compression */ #endif -/* - * Internal Compression Options - * - * Internal compression options RLECOMP and ZEROCOMP alter the data - * that gets written to the save file by NetHack, in contrast - * to COMPRESS or ZLIB_COMP which compress the entire file after - * the NetHack data is written out. - * - * Defining RLECOMP builds in support for internal run-length - * compression of level structures. If RLECOMP support is included - * it can be toggled on/off at runtime via the config file option - * rlecomp. - * - * Defining ZEROCOMP builds in support for internal zero-comp - * compression of data. If ZEROCOMP support is included it can still - * be toggled on/off at runtime via the config file option zerocomp. - * - * RLECOMP and ZEROCOMP support can be included even if - * COMPRESS or ZLIB_COMP support is included. One reason for doing - * so would be to provide savefile read compatibility with a savefile - * where those options were in effect. With RLECOMP and/or ZEROCOMP - * defined, NetHack can read an rlecomp or zerocomp savefile in, yet - * re-save without them. - * - * Using any compression option will create smaller bones/level/save - * files at the cost of additional code and time. - */ - -/* # define INTERNAL_COMP */ /* defines both ZEROCOMP and RLECOMP */ -/* # define ZEROCOMP */ /* Support ZEROCOMP compression */ -/* # define RLECOMP */ /* Support RLECOMP compression */ - /* * Data librarian. Defining DLB places most of the support files into * a tar-like file, thus making a neater installation. See *conf.h diff --git a/include/dungeon.h b/include/dungeon.h index 288b15b58..d4a1dcf62 100644 --- a/include/dungeon.h +++ b/include/dungeon.h @@ -188,66 +188,71 @@ struct linfo { /* what the player knows about a single dungeon level */ /* initialized in mklev() */ +struct mapseen_feat { + /* feature knowledge that must be calculated from levl array */ + Bitfield(nfount, 2); + Bitfield(nsink, 2); + Bitfield(naltar, 2); + Bitfield(nthrone, 2); + + Bitfield(ngrave, 2); + Bitfield(ntree, 2); + Bitfield(water, 2); + Bitfield(lava, 2); + + Bitfield(ice, 2); + /* calculated from rooms array */ + Bitfield(nshop, 2); + Bitfield(ntemple, 2); + /* altar alignment; MSA_NONE if there is more than one and + they aren't all the same */ + Bitfield(msalign, 2); + + Bitfield(shoptype, 5); +}; +struct mapseen_flags { + Bitfield(notreachable, 1); /* can't get back to this level */ + Bitfield(forgot, 1); /* player has forgotten about this level */ + Bitfield(knownbones, 1); /* player aware of bones */ + Bitfield(oracle, 1); + Bitfield(sokosolved, 1); + Bitfield(bigroom, 1); + Bitfield(castle, 1); + Bitfield(castletune, 1); /* add tune hint to castle annotation */ + + Bitfield(valley, 1); + Bitfield(msanctum, 1); + Bitfield(ludios, 1); + Bitfield(roguelevel, 1); + /* quest annotations: quest_summons is for main dungeon level + with entry portal and is reset once quest has been finished; + questing is for quest home (level 1) */ + Bitfield(quest_summons, 1); /* heard summons from leader */ + Bitfield(questing, 1); /* quest leader has unlocked quest stairs */ + /* "gateway to sanctum" */ + Bitfield(vibrating_square, 1); /* found vibrating square 'trap'; + * flag cleared once the msanctum + * annotation has been added (on + * the next dungeon level; temple + * entered or high altar mapped) */ + Bitfield(spare1, 1); /* not used */ +}; + +struct mapseen_rooms { + Bitfield(seen, 1); + Bitfield(untended, 1); /* flag for shop without shk */ +}; + typedef struct mapseen { struct mapseen *next; /* next map in the chain */ branch *br; /* knows about branch via taking it in goto_level */ d_level lev; /* corresponding dungeon level */ - struct mapseen_feat { - /* feature knowledge that must be calculated from levl array */ - Bitfield(nfount, 2); - Bitfield(nsink, 2); - Bitfield(naltar, 2); - Bitfield(nthrone, 2); - - Bitfield(ngrave, 2); - Bitfield(ntree, 2); - Bitfield(water, 2); - Bitfield(lava, 2); - - Bitfield(ice, 2); - /* calculated from rooms array */ - Bitfield(nshop, 2); - Bitfield(ntemple, 2); - /* altar alignment; MSA_NONE if there is more than one and - they aren't all the same */ - Bitfield(msalign, 2); - - Bitfield(shoptype, 5); - } feat; - struct mapseen_flags { - Bitfield(notreachable, 1); /* can't get back to this level */ - Bitfield(forgot, 1); /* player has forgotten about this level */ - Bitfield(knownbones, 1); /* player aware of bones */ - Bitfield(oracle, 1); - Bitfield(sokosolved, 1); - Bitfield(bigroom, 1); - Bitfield(castle, 1); - Bitfield(castletune, 1); /* add tune hint to castle annotation */ - - Bitfield(valley, 1); - Bitfield(msanctum, 1); - Bitfield(ludios, 1); - Bitfield(roguelevel, 1); - /* quest annotations: quest_summons is for main dungeon level - with entry portal and is reset once quest has been finished; - questing is for quest home (level 1) */ - Bitfield(quest_summons, 1); /* heard summons from leader */ - Bitfield(questing, 1); /* quest leader has unlocked quest stairs */ - /* "gateway to sanctum" */ - Bitfield(vibrating_square, 1); /* found vibrating square 'trap'; - * flag cleared once the msanctum - * annotation has been added (on - * the next dungeon level; temple - * entered or high altar mapped) */ - Bitfield(spare1, 1); /* not used */ - } flags; + struct mapseen_feat feat; + struct mapseen_flags flags; /* custom naming */ char *custom; unsigned custom_lth; - struct mapseen_rooms { - Bitfield(seen, 1); - Bitfield(untended, 1); /* flag for shop without shk */ - } msrooms[(MAXNROFROOMS + 1) * 2]; /* same size as svr.rooms[] */ + struct mapseen_rooms msrooms[(MAXNROFROOMS + 1) * 2]; /* same size as svr.rooms[] */ /* dead heroes; might not have graves or ghosts */ struct cemetery *final_resting_place; /* same as level.bonesinfo */ } mapseen; diff --git a/include/extern.h b/include/extern.h index 459b452c9..585b2273b 100644 --- a/include/extern.h +++ b/include/extern.h @@ -67,6 +67,10 @@ * */ +#ifndef ARTIFACT_H +#include "artifact.h" +#endif + /* ### alloc.c ### */ #if 0 @@ -3495,6 +3499,9 @@ extern unsigned long get_current_feature_ver(void); extern const char *copyright_banner_line(int) NONNULL; extern void early_version_info(boolean); extern void dump_version_info(void); +extern void store_critical_bytes(NHFILE *) NONNULLARG1; +extern int compare_critical_bytes(NHFILE *); +extern int get_critical_size_count(void); /* ### video.c ### */ diff --git a/include/global.h b/include/global.h index 77740213b..db6faa52d 100644 --- a/include/global.h +++ b/include/global.h @@ -357,8 +357,6 @@ struct version_info { unsigned long incarnation; /* actual version number */ unsigned long feature_set; /* bitmask of config settings */ unsigned long entity_count; /* # of monsters and objects */ - unsigned long struct_sizes1; /* size of key structs */ - unsigned long struct_sizes2; /* size of more key structs */ }; struct savefile_info { @@ -391,8 +389,6 @@ struct nomakedefs_s { unsigned long version_features; unsigned long ignored_features; unsigned long version_sanity1; - unsigned long version_sanity2; - unsigned long version_sanity3; unsigned long build_time; }; extern struct nomakedefs_s nomakedefs; diff --git a/include/integer.h b/include/integer.h index 32a3b3266..d38ea80ca 100644 --- a/include/integer.h +++ b/include/integer.h @@ -101,6 +101,11 @@ typedef uint32_t uint32; typedef int64_t int64; typedef uint64_t uint64; +/* Also provide ushort, uint, ulong */ +typedef unsigned short ushort; +typedef unsigned int uint; +typedef unsigned long ulong; + /* for non-negative L, calculate L * 10 + D, avoiding signed overflow; yields -1 if overflow would have happened; assumes compiler will optimize the constants */ diff --git a/include/patchlevel.h b/include/patchlevel.h index 9b6140a6d..1fcec2047 100644 --- a/include/patchlevel.h +++ b/include/patchlevel.h @@ -17,7 +17,7 @@ * Incrementing EDITLEVEL can be used to force invalidation of old bones * and save files. */ -#define EDITLEVEL 121 +#define EDITLEVEL 122 /* * Development status possibilities. diff --git a/include/wintype.h b/include/wintype.h index 6bf49aabb..6b94bef64 100644 --- a/include/wintype.h +++ b/include/wintype.h @@ -32,6 +32,8 @@ typedef union any { const char *a_string; int (*a_nfunc)(void); unsigned long a_mask32; /* used by status highlighting */ + int64 a_int64; + uint64 a_uint64; /* add types as needed */ } anything; #define ANY_P union any /* avoid typedef in prototypes diff --git a/src/artifact.c b/src/artifact.c index 7d9a082c6..dfb436c3d 100644 --- a/src/artifact.c +++ b/src/artifact.c @@ -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 */ } diff --git a/src/bones.c b/src/bones.c index e0a809de9..f165e71ea 100644 --- a/src/bones.c +++ b/src/bones.c @@ -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]; diff --git a/src/date.c b/src/date.c index f4b96fdb0..3ec4fbb3d 100644 --- a/src/date.c +++ b/src/date.c @@ -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)); diff --git a/src/decl.c b/src/decl.c index 617d62e86..3859f5a2f 100644 --- a/src/decl.c +++ b/src/decl.c @@ -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); diff --git a/src/dungeon.c b/src/dungeon.c index 47f6e2c49..f05c926ab 100644 --- a/src/dungeon.c +++ b/src/dungeon.c @@ -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; diff --git a/src/end.c b/src/end.c index 90ea4a3ea..35dfc1803 100644 --- a/src/end.c +++ b/src/end.c @@ -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)); } diff --git a/src/engrave.c b/src/engrave.c index 9db32403d..2a300cfac 100644 --- a/src/engrave.c +++ b/src/engrave.c @@ -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) <h, sizeof (unsigned)); - + if (nhfp->structlevel) { + mread(nhfp->fd, (genericptr_t) <h, sizeof(unsigned)); + } if (lth == 0) return; ep = newengr(lth); diff --git a/src/files.c b/src/files.c index f40385d4b..5489b0f41 100644 --- a/src/files.c +++ b/src/files.c @@ -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; diff --git a/src/light.c b/src/light.c index e89c316ca..f783855eb 100644 --- a/src/light.c +++ b/src/light.c @@ -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; diff --git a/src/mdlib.c b/src/mdlib.c index 9e7700cc8..dc69e8a28 100644 --- a/src/mdlib.c +++ b/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 diff --git a/src/mkmaze.c b/src/mkmaze.c index 903330cf3..799c2b6b8 100644 --- a/src/mkmaze.c +++ b/src/mkmaze.c @@ -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; diff --git a/src/mkroom.c b/src/mkroom.c index c9aecb15a..d96eca758 100644 --- a/src/mkroom.c +++ b/src/mkroom.c @@ -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++) { diff --git a/src/nhlua.c b/src/nhlua.c index 6bc523e7e..ed9b3d877 100644 --- a/src/nhlua.c +++ b/src/nhlua.c @@ -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); diff --git a/src/o_init.c b/src/o_init.c index 1538c298d..bebc4f866 100644 --- a/src/o_init.c +++ b/src/o_init.c @@ -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); } } } diff --git a/src/region.c b/src/region.c index 60001f866..b38ba0d7c 100644 --- a/src/region.c +++ b/src/region.c @@ -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)); diff --git a/src/restore.c b/src/restore.c index c15cce775..05292b5d9 100644 --- a/src/restore.c +++ b/src/restore.c @@ -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, <mp, 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; } diff --git a/src/rumors.c b/src/rumors.c index 31fb19a82..d1d709516 100644 --- a/src/rumors.c +++ b/src/rumors.c @@ -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() */ } diff --git a/src/save.c b/src/save.c index ad5f52773..bc8c55124 100644 --- a/src/save.c +++ b/src/save.c @@ -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) <mp, 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) diff --git a/src/timeout.c b/src/timeout.c index 81f62d531..34e95806a 100644 --- a/src/timeout.c +++ b/src/timeout.c @@ -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); diff --git a/src/track.c b/src/track.c index e9c4923f8..60a0d382b 100644 --- a/src/track.c +++ b/src/track.c @@ -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); } diff --git a/src/version.c b/src/version.c index e6b675ed3..83f119859 100644 --- a/src/version.c +++ b/src/version.c @@ -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*/ diff --git a/src/worm.c b/src/worm.c index 4b28790cd..c760bc3a3 100644 --- a/src/worm.c +++ b/src/worm.c @@ -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)); + } } } diff --git a/sys/share/pcmain.c b/sys/share/pcmain.c index 5d60053cd..cad2bc69a 100644 --- a/sys/share/pcmain.c +++ b/sys/share/pcmain.c @@ -429,8 +429,9 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/ raw_print("Cannot create lock file"); } else { svh.hackpid = 1; - if (nhfp->structlevel) - write(nhfp->fd, (genericptr_t) &svh.hackpid, sizeof(svh.hackpid)); + if (nhfp->structlevel) { + write(nhfp->fd, (genericptr_t) &svh.hackpid, sizeof svh.hackpid); + } close_nhfile(nhfp); } diff --git a/util/makedefs.c b/util/makedefs.c index 1af34cb2e..bc86614bd 100644 --- a/util/makedefs.c +++ b/util/makedefs.c @@ -1869,18 +1869,6 @@ do_date(void) } Fprintf(ofp, "#define VERSION_SANITY1 0x%08lx%s\n", version.entity_count, ul_sfx); -#ifndef __EMSCRIPTEN__ - Fprintf(ofp, "#define VERSION_SANITY2 0x%08lx%s\n", version.struct_sizes1, - ul_sfx); - Fprintf(ofp, "#define VERSION_SANITY3 0x%08lx%s\n", version.struct_sizes2, - ul_sfx); -#else /* __EMSCRIPTEN__ */ - Fprintf(ofp, "#define VERSION_SANITY2 0x%08llx%s\n", version.struct_sizes1, - ul_sfx); - Fprintf(ofp, "#define VERSION_SANITY3 0x%08llx%s\n", version.struct_sizes2, - ul_sfx); -#endif /* !__EMSCRIPTEN__ */ - Fprintf(ofp, "\n"); Fprintf(ofp, "#define VERSION_STRING \"%s\"\n", mdlib_version_string(buf, "."));