From 5e570b181fc6dcacbb4a9f9e91cb0007b353e773 Mon Sep 17 00:00:00 2001 From: PatR Date: Wed, 2 Dec 2020 14:49:09 -0800 Subject: [PATCH] saving followup If attempting to checkpoint when changing levels discovered that the alock.0 or 123wizard.0 file was missing and the game was running in wizard mode, play continued after reporting trickery but screen updating was left disabled. An early return in savegamestateinlock() wasn't resetting the program_state.saving flag to revert to normal screen updates. I added a few return statements at the ends of void routines, where they're optional, because it makes searching for early returns easier. (Without these then when no early return is present between current point and end of routine, the search would move past the routine looking for 'return' later in the file.) save_stairs() was placed in between saveobj() and saveobjchn() so I've moved it. (Has no effect on the recently reported stair anomalies.) It was also accumulating the total stairway data size in 'len' and never using that for anything, so I got rid of it. (Ditto about anomalies.) --- src/save.c | 85 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 44 insertions(+), 41 deletions(-) diff --git a/src/save.c b/src/save.c index c8f1865da..d1dcf15fd 100644 --- a/src/save.c +++ b/src/save.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 save.c $NHDT-Date: 1606919257 2020/12/02 14:27:37 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.163 $ */ +/* NetHack 3.7 save.c $NHDT-Date: 1606949327 2020/12/02 22:48:47 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.164 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Michael Allison, 2009. */ /* NetHack may be freely redistributed. See license for details. */ @@ -21,15 +21,12 @@ int dotcnt, dotrow; /* also used in restore */ #endif static void FDECL(savelevchn, (NHFILE *)); -static void FDECL(savedamage, (NHFILE *)); -/* static void FDECL(saveobj, (NHFILE *,struct obj *)); */ -/* static void FDECL(savemon, (NHFILE *,struct monst *)); */ -/* static void FDECL(savelevl, (NHFILE *, BOOLEAN_P)); */ -static void FDECL(saveobj, (NHFILE *,struct obj *)); -static void FDECL(savemon, (NHFILE *,struct monst *)); static void FDECL(savelevl, (NHFILE *,BOOLEAN_P)); +static void FDECL(savedamage, (NHFILE *)); static void FDECL(save_stairs, (NHFILE *)); +static void FDECL(saveobj, (NHFILE *,struct obj *)); static void FDECL(saveobjchn, (NHFILE *,struct obj **)); +static void FDECL(savemon, (NHFILE *,struct monst *)); static void FDECL(savemonchn, (NHFILE *,struct monst *)); static void FDECL(savetrapchn, (NHFILE *,struct trap *)); static void FDECL(savegamestate, (NHFILE *)); @@ -214,7 +211,7 @@ dosave0() getlev(onhfp, g.hackpid, ltmp); close_nhfile(onhfp); if (nhfp->structlevel) - bwrite(nhfp->fd, (genericptr_t) <mp, sizeof ltmp); /* level number*/ + bwrite(nhfp->fd, (genericptr_t) <mp, sizeof ltmp); /* lvl no. */ savelev(nhfp, ltmp); /* actual level*/ delete_levelfile(ltmp); } @@ -242,9 +239,7 @@ NHFILE *nhfp; unsigned long uid; struct obj *bc_objs = (struct obj *)0; - if (!g.program_state.saving) - impossible("savegamestate called when not saving or changing levels?"); - + g.program_state.saving++; /* caller should/did already set this... */ uid = (unsigned long) getuid(); if (nhfp->structlevel) { bwrite(nhfp->fd, (genericptr_t) &uid, sizeof uid); @@ -326,8 +321,11 @@ NHFILE *nhfp; save_msghistory(nhfp); if (nhfp->structlevel) bflush(nhfp->fd); + g.program_state.saving--; + return; } +/* potentially called from goto_level(do.c) as well as savestateinlock() */ boolean tricked_fileremoved(nhfp, whynot) NHFILE *nhfp; @@ -371,8 +369,10 @@ savestateinlock() * readable by an external utility */ nhfp = open_levelfile(0, whynot); - if (tricked_fileremoved(nhfp, whynot)) + if (tricked_fileremoved(nhfp, whynot)) { + g.program_state.saving--; return; + } if (nhfp->structlevel) (void) read(nhfp->fd, (genericptr_t) &hpid, sizeof hpid); @@ -420,6 +420,7 @@ savestateinlock() } g.program_state.saving--; g.havestate = flags.ins_chkpt; + return; } #endif @@ -537,6 +538,7 @@ xchar lev; bflush(nhfp->fd); } g.program_state.saving--; + return; } static void @@ -598,6 +600,7 @@ boolean rlecomp; if (nhfp->structlevel) { bwrite(nhfp->fd, (genericptr_t) levl, sizeof levl); } + return; } /* used when saving a level and also when saving dungeon overview data */ @@ -656,6 +659,32 @@ NHFILE *nhfp; g.level.damagelist = 0; } +static void +save_stairs(nhfp) +NHFILE *nhfp; +{ + stairway *stway = g.stairs; + int buflen = (int) sizeof *stway; + + while (stway) { + if (perform_bwrite(nhfp)) { + if (nhfp->structlevel) { + bwrite(nhfp->fd, (genericptr_t) &buflen, sizeof buflen); + bwrite(nhfp->fd, (genericptr_t) stway, sizeof *stway); + } + } + stway = stway->next; + } + if (perform_bwrite(nhfp)) { + if (nhfp->structlevel) { + buflen = -1; + bwrite(nhfp->fd, (genericptr_t) &buflen, sizeof buflen); + } + } +} + +/* save one object; + caveat: this is only for perform_bwrite(); caller handles release_data() */ static void saveobj(nhfp, otmp) NHFILE *nhfp; @@ -694,40 +723,14 @@ struct obj *otmp; } /* 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 oxtra components do */ + gets saved/restored whenever any other oextra components do */ if (nhfp->structlevel) bwrite(nhfp->fd, (genericptr_t) &OMID(otmp), sizeof OMID(otmp)); } } -static void -save_stairs(nhfp) -NHFILE *nhfp; -{ - stairway *stway = g.stairs; - int buflen = (int) sizeof (stairway); - int len = 0; - - while (stway) { - if (perform_bwrite(nhfp)) { - if (nhfp->structlevel) { - len += sizeof(buflen); - bwrite(nhfp->fd, (genericptr_t) &buflen, sizeof buflen); - len += sizeof(stairway); - bwrite(nhfp->fd, (genericptr_t) stway, sizeof(stairway)); - } - } - stway = stway->next; - } - if (perform_bwrite(nhfp)) { - if (nhfp->structlevel) { - buflen = -1; - len += sizeof(buflen); - bwrite(nhfp->fd, (genericptr_t) &buflen, sizeof buflen); - } - } -} - +/* save an object chain; sets head of list to Null when done; + handles release_data() for each object in the list */ static void saveobjchn(nhfp, obj_p) NHFILE *nhfp;