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, "."));