Added decl_early_init() which is called when PLAYAGAIN is supported.
authorBart House <bart@barthouse.com>
Thu, 22 Nov 2018 23:20:17 +0000 (15:20 -0800)
committerBart House <bart@barthouse.com>
Thu, 22 Nov 2018 23:20:17 +0000 (15:20 -0800)
decl_early_init() is called when we are starting a game.  On first
start, it validates that global state is in the expected state.
When called on subsequent starts, it initializes global state to
expected state.

include/config.h
include/extern.h
src/decl.c
sys/share/pcmain.c
sys/winnt/stubs.c
win/win32/winhack.c

index 761262c4bf786d38d1ee6ef875b3b212c7b1e589..d4f67e1ac150b2fa65085de4e5fa4a9647586cab 100644 (file)
@@ -552,10 +552,13 @@ typedef unsigned char uchar;
 
 #endif
 
-/* PLAYAGAIN is support for allowing the game shell to stay open after the player
-   saves or dies.  This requires that the game engine can be re-entered to start
-   another game.  This support is primarily about ensuring that game engine
-   state is cleaned up properly to allow the game engine to be re-initialized. */
+/* PLAYAGAIN support for allowing the game shell to stay open after the player
+ * saves or dies.  This requires that the game engine can be re-entered to
+ * start another game.
+ *
+ * This support does not include supporting playing another game when
+ * a panic has occured due to undetermined state the engine is left in after a
+ * panic */
 /* #define PLAYAGAIN */
 
 /* End of Section 4 */
index 89910b0bba91889ff9ffa71c67dbdce7456ff5f3..d3a251b83666e332cb009b4da3c3e2c1b8d8633d 100644 (file)
@@ -251,6 +251,9 @@ E void FDECL(destroy_drawbridge, (int, int));
 /* ### decl.c ### */
 
 E void NDECL(decl_init);
+#ifdef PLAYAGAIN
+E void NDECL(decl_early_init);
+#endif
 
 /* ### detect.c ### */
 
index ffd9ef97414dde2b972b20cae6856efc4bac9448..6c26b442219b594083a04844ce5932cc81a6250d 100644 (file)
@@ -284,6 +284,31 @@ char *fqn_prefix_names[PREFIX_COUNT] = {
 };
 #endif
 
+#ifdef PLAYAGAIN
+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
+};
+#endif
+
 NEARDATA struct savefile_info sfcap = {
 #ifdef NHSTDC
     0x00000000UL
@@ -346,4 +371,238 @@ decl_init()
     return;
 }
 
+#ifdef PLAYAGAIN
+
+static boolean s_firstStart = TRUE;
+
+static boolean
+decl_is_block_zero(p, n)
+unsigned char * p;
+int n;
+{
+    static unsigned char zeroblock[512] = { 0 };
+    unsigned char * sentinel = p + n;
+    while (p < sentinel) {
+        int c = (n < sizeof(zeroblock) ? n : sizeof(zeroblock));
+        if (memcmp(p, zeroblock, c) != 0) return FALSE;
+        p += c;
+    }
+    return TRUE;
+}
+
+static void
+decl_zero_block(p, n)
+unsigned char * p;
+int n;
+{
+    nhassert(!s_firstStart || decl_is_block_zero(p, n));
+    memset(p, 0, n);
+}
+
+#define ZEROARRAY(x) decl_zero_block((void *) &x[0], 0, sizeof(x))
+#define ZEROARRAYN(x,n) decl_zero_block((void *) &x[0], 0, sizeof(x[0])*(n))
+#define ZERO(x) decl_zero_block((void *) &x, 0, sizeof(x))
+#define ZEROPTR(x) { nhassert(x == NULL); x = NULL; }
+#define ZEROPTRNOCHECK(x) { x = NULL; }
+
+/* decl_early_init() is called when we are starting a game.  On first
+ * start, it validates that global state is in the expected state.
+ * When called on subsequent starts, it initializes global state to
+ * expected state.
+ *
+ * In the case that of global pointers, on subsequent starts it will
+ * panic if it finds a non-NULL pointer with the assumption that a
+ * pointer has leaked.  */
+
+void
+decl_early_init()
+{
+    hackpid = 0;
+#if defined(UNIX) || defined(VMS)
+    locknum = 0;
+#endif
+#ifdef DEF_PAGER
+    catmore = 0;
+#endif
+
+    ZEROARRAY(bases);
+
+    multi = 0;
+    multi_reason = NULL;
+    nroom = 0;
+    nsubroom = 0;
+    occtime = 0;
+
+    x_maze_max = (COLNO - 1) & ~1;
+    y_maze_max = (ROWNO - 1) & ~1;
+
+    otg_temp = 0;
+
+    ZERO(dungeon_topology);
+    ZERO(quest_status);
+
+    warn_obj_cnt = 0;
+    ZEROARRAYN(smeq, MAXNROFROOMS + 1);
+    doorindex = 0;
+    save_cm = NULL;
+
+    ZERO(killer);
+    done_money = 0;
+    nomovemsg = NULL;
+    ZEROARRAY(plname);
+    ZEROARRAY(pl_character);
+    pl_race = '\0';
+
+    ZEROARRAY(pl_fruit);
+    ffruit = NULL;
+
+    ZEROARRAY(tune);
+
+    occtxt = NULL;
+
+    yn_number = 0;
+
+#if defined(MICRO) || defined(WIN32)
+    ZEROARRAYN(hackdir, PATHLEN);
+#ifdef MICRO
+    ZEROARRAYN(levels, PATHLEN);
+#endif /* MICRO */
+#endif /* MICRO || WIN32 */
+
+#ifdef MFLOPPY
+    ZEROARRAYN(permbones, PATHLEN);
+    ramdisk = FALSE;
+    saveprompt = TRUE;
+#endif
+
+    ZEROARRAY(level_info);
+
+    ZERO(program_state);
+
+    tbx = 0;
+    tby = 0;
+
+    ZERO(m_shot);
+
+    ZEROARRAYN(dungeons, MAXDUNGEON);
+    ZEROPTR(sp_levchn);
+    ZERO(upstair);
+    ZERO(dnstair);
+    ZERO(upladder);
+    ZERO(dnladder);
+    ZERO(sstairs);
+    ZERO(updest);
+    ZERO(dndest);
+    ZERO(inv_pos);
+
+    defer_see_monsters = FALSE;
+    in_mklev = FALSE;
+    stoned = FALSE;
+    unweapon = FALSE;
+    mrg_to_wielded = FALSE;
+
+    in_steed_dismounting = FALSE;
+
+    ZERO(bhitpos);
+    ZEROARRAY(doors);
+
+    ZEROARRAY(rooms);
+    subrooms = &rooms[MAXNROFROOMS + 1];
+    upstairs_room = NULL;
+    dnstairs_room = NULL;
+    sstairs_room = NULL;
+
+    ZERO(level);
+    ZEROPTR(ftrap);
+    ZERO(youmonst);
+    ZERO(context);
+    ZERO(flags);
+#ifdef SYSFLAGS
+    ZERO(sysflags);
+#endif
+    ZERO(iflags);
+    ZERO(u);
+    ZERO(ubirthday);
+    ZERO(urealtime);
+
+    ZEROARRAY(lastseentyp);
+
+    ZEROPTR(invent);
+    ZEROPTRNOCHECK(uwep);
+    ZEROPTRNOCHECK(uarm);
+    ZEROPTRNOCHECK(uswapwep);
+    ZEROPTRNOCHECK(uquiver);
+    ZEROPTRNOCHECK(uarmu);
+    ZEROPTRNOCHECK(uskin);
+    ZEROPTRNOCHECK(uarmc);
+    ZEROPTRNOCHECK(uarmh);
+    ZEROPTRNOCHECK(uarms);
+    ZEROPTRNOCHECK(uarmg);
+    ZEROPTRNOCHECK(uarmf);
+    ZEROPTRNOCHECK(uamul);
+    ZEROPTRNOCHECK(uright);
+    ZEROPTRNOCHECK(uleft);
+    ZEROPTRNOCHECK(ublindf);
+    ZEROPTRNOCHECK(uchain);
+    ZEROPTRNOCHECK(uball);
+
+    ZEROPTR(current_wand);
+    ZEROPTR(thrownobj);
+    ZEROPTR(kickedobj);
+
+    ZEROARRAYN(spl_book, MAXSPELL + 1);
+
+    moves = 1;
+    monstermoves = 1;
+
+    wailmsg = 0L;
+
+    ZEROPTR(migrating_objs);
+    ZEROPTR(billobjs);
+
+    ZERO(zeroobj);
+    ZERO(zeromonst);
+    ZERO(zeroany);
+
+    ZEROARRAYN(dogname, PL_PSIZ);
+    ZEROARRAYN(catname, PL_PSIZ);
+    ZEROARRAYN(horsename, PL_PSIZ);
+    preferred_pet = 0;
+    ZEROPTR(mydogs);
+    ZEROPTR(migrating_mons);
+
+    ZEROARRAY(mvitals);
+
+    ZEROPTR(menu_colorings);
+
+    vision_full_recalc = 0;
+    viz_array = NULL;
+
+    WIN_MESSAGE = WIN_ERR;
+#ifndef STATUS_VIA_WINDOWPORT
+    WIN_STATUS = WIN_ERR;
+#endif
+    WIN_MAP = WIN_ERR;
+    WIN_INVEN = WIN_ERR;
+
+    ZEROARRAYN(toplines, TBUFSZ);
+    ZERO(tc_gbl_data);
+    ZEROARRAYN(fqn_prefix, PREFIX_COUNT);
+
+    sfcap = default_sfinfo;
+    sfrestinfo = default_sfinfo;
+    sfsaveinfo = default_sfinfo;
+
+    ZEROPTR(plinemsg_types);
+
+#ifdef PANICTRACE
+    ARGV0 = NULL;
+#endif
+
+    nhUse_dummy = 0;
+
+    s_firstStart = FALSE;
+}
+#endif
+
 /*decl.c*/
index 93674ab341dd2e7c191d0a6fb607bd061db87390..9ffbeca51c00f65939a3edd5130f646126e4e60a 100644 (file)
@@ -97,7 +97,11 @@ char *argv[];
 
     nethack_enter(argc, argv);
 
+#ifdef PLAYAGAIN
+    decl_early_init();
+#endif
     sys_early_init();
+
 #if defined(WIN32) && defined(TTY_GRAPHICS)
     Strcpy(default_window_sys, "tty");
 #else
index bb5ad82e432b246ea94bcf80a412f29f571af084..ff3cf591959eed4dbdc7fe8589bffecf89ceb931 100644 (file)
@@ -37,6 +37,9 @@ char *argv[];
 {
     boolean resuming;
 
+#ifdef PLAYAGAIN
+    decl_early_init();
+#endif
     sys_early_init();
     Strcpy(default_window_sys, "tty");
     resuming = pcmain(argc, argv);
index 9dcbb4e4b066078d681f5d22e55551e579cadd4c..6db66261e260eecca6e77d791cbd0d54de2575b2 100644 (file)
@@ -97,6 +97,9 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
 
     win10_init();
 
+#ifdef PLAYAGAIN
+    decl_early_init();
+#endif
     sys_early_init();
 
     /* init applicatio structure */