From 455d2769e084c368912a86c3d30b745b3e165ab3 Mon Sep 17 00:00:00 2001 From: Bart House Date: Thu, 22 Nov 2018 13:01:58 -0800 Subject: [PATCH] Initial check-in of icontext work. --- include/config.h | 8 ++ include/decl.h | 18 +++ include/extern.h | 3 + src/decl.c | 275 +++++++++++++++++++++++++++++++++++++++++++ src/dog.c | 1 - src/pickup.c | 7 +- sys/share/pcmain.c | 2 + sys/winnt/stubs.c | 1 + util/lev_main.c | 7 ++ win/share/tile2bmp.c | 7 ++ win/win32/winhack.c | 1 + 11 files changed, 325 insertions(+), 5 deletions(-) diff --git a/include/config.h b/include/config.h index 4f242679a..d4f67e1ac 100644 --- a/include/config.h +++ b/include/config.h @@ -552,6 +552,14 @@ typedef unsigned char uchar; #endif +/* 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 */ diff --git a/include/decl.h b/include/decl.h index 992e86ad5..2cc7f965c 100644 --- a/include/decl.h +++ b/include/decl.h @@ -192,6 +192,8 @@ E NEARDATA char dogname[]; E NEARDATA char catname[]; E NEARDATA char horsename[]; E char preferred_pet; +E int petname_used; + E const char *occtxt; /* defined when occupation != NULL */ E const char *nomovemsg; E char lock[]; @@ -437,6 +439,22 @@ struct early_opt { boolean valallowed; }; +/* instance_context holds per game instance data that does not need to be + * persisted upon game exit. This game instance data is one of the first + * things initialized during the initialization of the game engine. + * It is initialized with icontext_initial_state found in decl.c */ + +#define PLAYAGAIN + +struct instance_context { + int oldcap; /* encumberance - pickup.c */ +}; + +E struct instance_context icontext; + +E void icontext_init(); + + #undef E #endif /* DECL_H */ diff --git a/include/extern.h b/include/extern.h index 89910b0bb..d3a251b83 100644 --- a/include/extern.h +++ b/include/extern.h @@ -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 ### */ diff --git a/src/decl.c b/src/decl.c index ffd9ef974..edfeb3a60 100644 --- a/src/decl.c +++ b/src/decl.c @@ -207,6 +207,7 @@ NEARDATA char dogname[PL_PSIZ] = DUMMY; NEARDATA char catname[PL_PSIZ] = DUMMY; NEARDATA char horsename[PL_PSIZ] = DUMMY; char preferred_pet; /* '\0', 'c', 'd', 'n' (none) */ +int petname_used = 0; /* monsters that went down/up together with @ */ NEARDATA struct monst *mydogs = (struct monst *) 0; /* monsters that are moving to another dungeon level */ @@ -284,6 +285,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 +372,253 @@ 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); + ZERO(preferred_pet); + ZERO(petname_used); + 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 + +const struct instance_context icontext_initial_state = { + 0, /* oldcap - last encumberance in pickup.c */ +}; + +struct instance_context icontext; + +void +icontext_init() +{ + icontext = icontext_initial_state; + + decl_early_init(); +}; + /*decl.c*/ diff --git a/src/dog.c b/src/dog.c index 0d967195e..7c1b62e8b 100644 --- a/src/dog.c +++ b/src/dog.c @@ -160,7 +160,6 @@ makedog() register struct obj *otmp; const char *petname; int pettype; - static int petname_used = 0; if (preferred_pet == 'n') return ((struct monst *) 0); diff --git a/src/pickup.c b/src/pickup.c index d68def38d..83d5eb273 100644 --- a/src/pickup.c +++ b/src/pickup.c @@ -1556,10 +1556,9 @@ struct obj *otmp; int encumber_msg() { - static int oldcap = UNENCUMBERED; int newcap = near_capacity(); - if (oldcap < newcap) { + if (icontext.oldcap < newcap) { switch (newcap) { case 1: Your("movements are slowed slightly because of your load."); @@ -1577,7 +1576,7 @@ encumber_msg() break; } context.botl = 1; - } else if (oldcap > newcap) { + } else if (icontext.oldcap > newcap) { switch (newcap) { case 0: Your("movements are now unencumbered."); @@ -1596,7 +1595,7 @@ encumber_msg() context.botl = 1; } - oldcap = newcap; + icontext.oldcap = newcap; return newcap; } diff --git a/sys/share/pcmain.c b/sys/share/pcmain.c index 93674ab34..932ec971e 100644 --- a/sys/share/pcmain.c +++ b/sys/share/pcmain.c @@ -97,7 +97,9 @@ char *argv[]; nethack_enter(argc, argv); + icontext_init(); sys_early_init(); + #if defined(WIN32) && defined(TTY_GRAPHICS) Strcpy(default_window_sys, "tty"); #else diff --git a/sys/winnt/stubs.c b/sys/winnt/stubs.c index bb5ad82e4..9e16c6dce 100644 --- a/sys/winnt/stubs.c +++ b/sys/winnt/stubs.c @@ -37,6 +37,7 @@ char *argv[]; { boolean resuming; + icontext_init(); sys_early_init(); Strcpy(default_window_sys, "tty"); resuming = pcmain(argc, argv); diff --git a/util/lev_main.c b/util/lev_main.c index ecf7a444c..729549791 100644 --- a/util/lev_main.c +++ b/util/lev_main.c @@ -1637,4 +1637,11 @@ short ospeed; #endif #endif /* STRICT_REF_DEF */ +/* nhassert_failed is called when an nhassert's condition is false */ +void nhassert_failed(const char * exp, const char * file, int line) +{ + fprintf(stderr, "NHASSERT(%s) in '%s' at line %d\n", exp, file, line); + exit(EXIT_FAILURE); +} + /*lev_main.c*/ diff --git a/win/share/tile2bmp.c b/win/share/tile2bmp.c index ca2c7dd73..6722bbc26 100644 --- a/win/share/tile2bmp.c +++ b/win/share/tile2bmp.c @@ -360,3 +360,10 @@ pixel (*pixels)[TILE_X]; } } } + +/* nhassert_failed is called when an nhassert's condition is false */ +void nhassert_failed(const char * exp, const char * file, int line) +{ + Fprintf(stderr, "NHASSERT(%s) in '%s' at line %d\n", exp, file, line); + exit(EXIT_FAILURE); +} diff --git a/win/win32/winhack.c b/win/win32/winhack.c index 9dcbb4e4b..ef48d6b63 100644 --- a/win/win32/winhack.c +++ b/win/win32/winhack.c @@ -97,6 +97,7 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, win10_init(); + icontext_init(); sys_early_init(); /* init applicatio structure */