From dc1e2da35995ac8a8a008cbcbd7b66e60ded5e9b Mon Sep 17 00:00:00 2001 From: nhmall Date: Sat, 8 Dec 2018 17:56:20 -0500 Subject: [PATCH 01/21] Windows startup modifications Changes to be committed: modified: include/winprocs.h modified: src/options.c modified: sys/share/pcmain.c new file: sys/share/safeproc.c modified: sys/winnt/Makefile.msc modified: sys/winnt/stubs.c new file: sys/winnt/windmain.c modified: sys/winnt/winnt.c modified: win/win32/vs2017/NetHack.vcxproj modified: win/win32/vs2017/NetHackW.vcxproj modified: win/win32/winhack.c Because multiple window ports are supported on Windows now, even in the same executable and selectable via config file in some cases, some adjustments became necessary. There will likely be some further refining of this over the next day or two. List of changes: Move Windows startup from sys/share/pcmain.c and into its own sys/winnt/windmain.c so that it can be modified to fix some current breakage, and allow altering the order of some things. There is startup processing code that is common to all of the Windows WindowPorts, but that startup processing code needs to have no dependency on any one of those WindowPorts. Yet, during startup processing, some of the initialization routines can end up calling NetHack functions that expect an active Window port underneath, and if there isn't one, routines like pline, impossible, panic can end up invoking null function pointers. Place a new file sys/share/safeproc.c, in which a complete window port is available for early startup processing purposes. It's WindowPort name field is set to "safe-startup" just for reference. The prototypes in include/winprocs.h require that SAFEPROCS be Usage: windowprocs = get_safe_procs(0); initializes a set of winprocs function pointers that ensure none of the function pointers are left null, but that's all it does. windowprocs = get_safe_procs(1); initializes a set of winprocs functions pointers that ensure none of the function pointers are left null, but also provides some basic output and input functionality using nothing other than C stdio routines (no platform or OS specific code). The conditional code related to WIN32 has been removed from sys/share/pcmain.c The code common to all of the Windows WindowPorts calls get_safe_procs() almost immediately to ensure that there is a set of WindowPort winprocs available. --- include/winprocs.h | 73 +++ src/options.c | 13 +- sys/share/pcmain.c | 270 +---------- sys/share/safeproc.c | 550 ++++++++++++++++++++++ sys/winnt/Makefile.msc | 14 +- sys/winnt/stubs.c | 2 - sys/winnt/windmain.c | 757 ++++++++++++++++++++++++++++++ sys/winnt/winnt.c | 3 + win/win32/vs2017/NetHack.vcxproj | 5 +- win/win32/vs2017/NetHackW.vcxproj | 5 +- win/win32/winhack.c | 39 +- 11 files changed, 1447 insertions(+), 284 deletions(-) create mode 100644 sys/share/safeproc.c create mode 100644 sys/winnt/windmain.c diff --git a/include/winprocs.h b/include/winprocs.h index ddfef409d..85ece4a7d 100644 --- a/include/winprocs.h +++ b/include/winprocs.h @@ -375,4 +375,77 @@ struct chain_procs { }; #endif /* WINCHAIN */ +#ifdef SAFEPROCS +/* + * window port routines available in sys/share/safeproc.c + */ +extern struct window_procs *FDECL(get_safe_procs, (int)); +extern void FDECL(safe_init_nhwindows, (int *, char **)); +extern void NDECL(safe_player_selection); +extern void NDECL(safe_askname); +extern void NDECL(safe_get_nh_event); +extern void FDECL(safe_exit_nhwindows, (const char *)); +extern void FDECL(safe_suspend_nhwindows, (const char *)); +extern void NDECL(safe_resume_nhwindows); +extern winid FDECL(safe_create_nhwindow, (int)); +extern void FDECL(safe_clear_nhwindow, (winid)); +extern void FDECL(safe_display_nhwindow, (winid, BOOLEAN_P)); +extern void FDECL(safe_destroy_nhwindow, (winid)); +extern void FDECL(safe_curs, (winid, int, int)); +extern void FDECL(safe_putstr, (winid, int, const char *)); +extern void FDECL(safe_putmixed, (winid, int, const char *)); +extern void FDECL(safe_display_file, (const char *, BOOLEAN_P)); +extern void FDECL(safe_start_menu, (winid)); +extern void FDECL(safe_add_menu, (winid, int, const ANY_P *, CHAR_P, CHAR_P, + int, const char *, BOOLEAN_P)); +extern void FDECL(safe_end_menu, (winid, const char *)); +extern int FDECL(safe_select_menu, (winid, int, MENU_ITEM_P **)); +extern char FDECL(safe_message_menu, (CHAR_P, int, const char *)); +extern void NDECL(safe_update_inventory); +extern void NDECL(safe_mark_synch); +extern void NDECL(safe_wait_synch); +#ifdef CLIPPING +extern void FDECL(safe_cliparound, (int, int)); +#endif +#ifdef POSITIONBAR +extern void FDECL(safe_update_positionbar, (char *)); +#endif +extern void FDECL(safe_print_glyph, (winid, XCHAR_P, XCHAR_P, int, int)); +extern void FDECL(safe_raw_print, (const char *)); +extern void FDECL(safe_raw_print_bold, (const char *)); +extern int NDECL(safe_nhgetch); +extern int FDECL(safe_nh_poskey, (int *, int *, int *)); +extern void NDECL(safe_nhbell); +extern int NDECL(safe_doprev_message); +extern char FDECL(safe_yn_function, (const char *, const char *, CHAR_P)); +extern void FDECL(safe_getlin, (const char *, char *)); +extern int NDECL(safe_get_ext_cmd); +extern void FDECL(safe_number_pad, (int)); +extern void NDECL(safe_delay_output); +#ifdef CHANGE_COLOR +extern void FDECL(safe_change_color, (int, long, int)); +#ifdef MAC +extern void FDECL(safe_change_background, (int)); +extern short FDECL(safe_set_font_name, (winid, char *)); +#endif +extern char *NDECL(safe_get_color_string); +#endif +extern void NDECL(safe_start_screen); +extern void NDECL(safe_end_screen); +extern void FDECL(safe_outrip, (winid, int, time_t)); +extern void FDECL(safe_preference_update, (const char *)); +extern char *FDECL(safe_getmsghistory, (BOOLEAN_P)); +extern void FDECL(safe_putmsghistory, (const char *, BOOLEAN_P)); +extern void NDECL(safe_status_init); +extern void NDECL(safe_status_finish); +extern void FDECL(safe_status_enablefield, + (int, const char *, const char *, BOOLEAN_P)); +extern void FDECL(safe_status_update, (int, genericptr_t, int, int, int, unsigned long *)); +extern boolean NDECL(safe_can_suspend); +extern void FDECL(stdio_raw_print, (const char *)); +extern void FDECL(stdio_raw_print_bold, (const char *)); +extern void NDECL(stdio_wait_synch); +extern int NDECL(stdio_nhgetch); +#endif /* SAFEPROCS */ #endif /* WINPROCS_H */ + diff --git a/src/options.c b/src/options.c index b3595a6ad..9dafa31bf 100644 --- a/src/options.c +++ b/src/options.c @@ -873,11 +873,16 @@ initoptions_finish() * A multi-interface binary might only support status highlighting * for some of the interfaces; check whether we asked for it but are * using one which doesn't. + * + * Option processing can take place before a user-decided WindowPort + * is even initialized, so check for that too. */ - if (iflags.hilite_delta && !wc2_supported("statushilites")) { - raw_printf("Status highlighting not supported for %s interface.", - windowprocs.name); - iflags.hilite_delta = 0; + if (!WINDOWPORT("safe-startup")) { + if (iflags.hilite_delta && !wc2_supported("statushilites")) { + raw_printf("Status highlighting not supported for %s interface.", + windowprocs.name); + iflags.hilite_delta = 0; + } } #endif return; diff --git a/sys/share/pcmain.c b/sys/share/pcmain.c index 8651ae8fe..1f67b0efb 100644 --- a/sys/share/pcmain.c +++ b/sys/share/pcmain.c @@ -3,11 +3,7 @@ /*-Copyright (c) Derek S. Ray, 2015. */ /* NetHack may be freely redistributed. See license for details. */ -/* main.c - MSDOS, OS/2, ST, Amiga, and Windows NetHack */ - -#ifdef WIN32 -#include "win32api.h" /* for GetModuleFileName */ -#endif +/* main.c - MSDOS, OS/2, ST, Amiga NetHack */ #include "hack.h" #include "dlb.h" @@ -47,29 +43,12 @@ void NDECL(preserve_icon); STATIC_DCL void FDECL(process_options, (int argc, char **argv)); STATIC_DCL void NDECL(nhusage); -#if defined(MICRO) || defined(WIN32) || defined(OS2) +#if defined(MICRO) || defined(OS2) extern void FDECL(nethack_exit, (int)); #else #define nethack_exit exit #endif -#ifdef WIN32 -extern boolean getreturn_enabled; /* from sys/share/pcsys.c */ -extern int redirect_stdout; /* from sys/share/pcsys.c */ -extern int GUILaunched; -char *NDECL(exename); -char default_window_sys[] = "mswin"; -#ifndef WIN32CON -HANDLE hStdOut; -boolean NDECL(fakeconsole); -void NDECL(freefakeconsole); -#endif -#endif - -#if defined(MSWIN_GRAPHICS) -extern void NDECL(mswin_destroy_reg); -#endif - #ifdef EXEPATH STATIC_DCL char *FDECL(exepath, (char *)); #endif @@ -78,7 +57,7 @@ int FDECL(main, (int, char **)); extern boolean FDECL(pcmain, (int, char **)); -#if defined(__BORLANDC__) && !defined(_WIN32) +#if defined(__BORLANDC__) void NDECL(startup); unsigned _stklen = STKSIZ; #endif @@ -98,21 +77,8 @@ char *argv[]; { boolean resuming; - nethack_enter(argc, argv); - sys_early_init(); -#if defined(WIN32) && defined(TTY_GRAPHICS) - Strcpy(default_window_sys, "tty"); -#else -#if defined(CURSES_GRAPHICS) - Strcpy(default_window_sys, "curses"); -#endif -#endif - resuming = pcmain(argc, argv); -#ifdef LAN_FEATURES - init_lan_features(); -#endif moveloop(resuming); nethack_exit(EXIT_SUCCESS); /*NOTREACHED*/ @@ -126,14 +92,10 @@ char *argv[]; { register int fd; register char *dir; -#if defined(WIN32) || defined(MSDOS) +#if defined(MSDOS) char *envp = NULL; char *sptr = NULL; #endif -#if defined(WIN32) - char fnamebuf[BUFSZ], encodedfnamebuf[BUFSZ]; - boolean save_getreturn_status = getreturn_enabled; -#endif #ifdef NOCWD_ASSUMPTIONS char failbuf[BUFSZ]; #endif @@ -162,7 +124,7 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/ # endif #endif -#if defined(__BORLANDC__) && !defined(_WIN32) +#if defined(__BORLANDC__) startup(); #endif @@ -175,15 +137,7 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/ #endif hname = "NetHack"; /* used for syntax messages */ -#ifndef WIN32 choose_windows(DEFAULT_WINDOW_SYS); -#else - choose_windows(default_window_sys); - if (argc >= 1 - && !strcmpi(default_window_sys, "mswin") - && strstri(argv[0], "nethackw.exe")) - iflags.windowtype_locked = TRUE; -#endif #if !defined(AMIGA) && !defined(GNUDOS) /* Save current directory and make sure it gets restored when @@ -243,7 +197,7 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/ for (prefcnt = 1; prefcnt < PREFIX_COUNT; prefcnt++) fqn_prefix[prefcnt] = fqn_prefix[0]; -#if defined(WIN32) || defined(MSDOS) +#if defined(MSDOS) /* sysconf should be searched for in this location */ envp = nh_getenv("COMMONPROGRAMFILES"); if (envp) { @@ -317,14 +271,6 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/ chdirx(HACKDIR, 1); #endif ami_wininit_data(); -#endif -#ifdef WIN32 - save_getreturn_status = getreturn_enabled; -#ifdef TTY_GRAPHICS - raw_clear_screen(); -#endif - getreturn_enabled = TRUE; - check_recordfile((char *) 0); #endif initoptions(); @@ -355,13 +301,6 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/ argv++; } -#ifdef WIN32 - if (argcheck(argc, argv, ARG_WINDOWS) == 1) { - argc--; - argv++; - } -#endif - if (argc > 1 && !strncmp(argv[1], "-d", 2) && argv[1][2] != 'e') { /* avoid matching "-dec" for DECgraphics; since the man page * says -d directory, hope nobody's using -desomething_else @@ -381,36 +320,11 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/ Strcpy(hackdir, dir); } if (argc > 1) { -#if defined(WIN32) && !defined(WIN32CON) - int sfd = 0; - boolean tmpconsole = FALSE; - hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); -#endif /* * Now we know the directory containing 'record' and * may do a prscore(). */ if (!strncmp(argv[1], "-s", 2)) { -#if defined(WIN32) && !defined(WIN32CON) - -#if 0 - if (!hStdOut) { - tmpconsole = fakeconsole(); - } -#endif - /* - * Check to see if we're redirecting to a file. - */ - sfd = (int) _fileno(stdout); - redirect_stdout = (sfd >= 0) ? !isatty(sfd) : 0; - - if (!redirect_stdout && !hStdOut) { - raw_printf( - "-s is not supported for the Graphical Interface\n"); - nethack_exit(EXIT_SUCCESS); - } -#endif - #if defined(CHDIR) && !defined(NOCWD_ASSUMPTIONS) chdirx(hackdir, 0); #endif @@ -418,47 +332,16 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/ initoptions(); #endif prscore(argc, argv); -#if defined(WIN32) && !defined(WIN32CON) - if (tmpconsole) { - getreturn("to exit"); - freefakeconsole(); - tmpconsole = FALSE; - } -#endif nethack_exit(EXIT_SUCCESS); } -#ifdef MSWIN_GRAPHICS - if (!strncmpi(argv[1], "-clearreg", 6)) { /* clear registry */ - mswin_destroy_reg(); - nethack_exit(EXIT_SUCCESS); - } -#endif /* Don't initialize the window system just to print usage */ if (!strncmp(argv[1], "-?", 2) || !strncmp(argv[1], "/?", 2)) { -#if 0 - if (!hStdOut) { - GUILaunched = 0; - tmpconsole = fakeconsole(); - } -#endif nhusage(); - -#if defined(WIN32) && !defined(WIN32CON) - if (tmpconsole) { - getreturn("to exit"); - freefakeconsole(); - tmpconsole = FALSE; - } -#endif nethack_exit(EXIT_SUCCESS); } } } - -#ifdef WIN32 - getreturn_enabled = save_getreturn_status; -#endif /* * It seems you really want to play. */ @@ -472,11 +355,7 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/ "\"%s\".%s", copyright_banner_line(1), copyright_banner_line(2), copyright_banner_line(3), copyright_banner_line(4), DLBFILE, -#ifdef WIN32 - "\nAre you perhaps trying to run NetHack within a zip utility?"); -#else ""); -#endif error("dlb_init failure."); } @@ -490,41 +369,22 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/ chdirx(hackdir, 1); #endif -#if defined(MSDOS) || defined(WIN32) +#if defined(MSDOS) /* In 3.6.0, several ports process options before they init * the window port. This allows settings that impact window * ports to be specified or read from the sys or user config files. */ process_options(argc, argv); -#ifdef WIN32 - /* - if (WINDOWPORT("mswin")) - NHWinMainInit(); - else - */ -#ifdef TTY_GRAPHICS - if (WINDOWPORT("tty")) { - iflags.use_background_glyph = FALSE; - nttty_open(1); - } else { - iflags.use_background_glyph = TRUE; - } -#endif /* TTY_GRAPHICS */ -#endif /* WIN32 */ -#endif /* MSDOS || WIN32 */ +#endif /* MSDOS */ -#if defined(MSDOS) || defined(WIN32) +#if defined(MSDOS) init_nhwindows(&argc, argv); #else init_nhwindows(&argc, argv); process_options(argc, argv); #endif -#if defined(WIN32) && defined(TTY_GRAPHICS) - toggle_mouse_support(); /* must come after process_options */ -#endif - #ifdef MFLOPPY set_lock_and_bones(); #ifndef AMIGA @@ -561,19 +421,8 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/ * overwritten without confirmation when a user starts up * another game with the same player name. */ -#if defined(WIN32) - /* Obtain the name of the logged on user and incorporate - * it into the name. */ - Sprintf(fnamebuf, "%s-%s", get_username(0), plname); - (void) fname_encode( - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-.", '%', - fnamebuf, encodedfnamebuf, BUFSZ); - Sprintf(lock, "%s", encodedfnamebuf); - /* regularize(lock); */ /* we encode now, rather than substitute */ -#else Strcpy(lock, plname); regularize(lock); -#endif getlock(); #else /* What follows is !PC_LOCKING */ #ifdef AMIGA /* We'll put the bones & levels in the user specified directory \ @@ -599,11 +448,7 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/ if (fd < 0) { raw_print("Cannot create lock file"); } else { -#ifdef WIN32 - hackpid = GetCurrentProcessId(); -#else hackpid = 1; -#endif write(fd, (genericptr_t) &hackpid, sizeof(hackpid)); nhclose(fd); } @@ -618,10 +463,6 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/ vision_init(); display_gamewindows(); -#ifdef WIN32 - getreturn_enabled = TRUE; -#endif - /* * First, try to find and restore a save file for specified character. * We'll return here if new game player_selection() renames the hero. @@ -799,18 +640,6 @@ char *argv[]; case 'l': bigscreen = -1; break; -#endif -#ifdef WIN32 - case 'w': /* windowtype */ -#ifdef TTY_GRAPHICS - if (strncmpi(&argv[0][2], "tty", 3)) { - nttty_open(1); - } -#endif - config_error_init(FALSE, "command line", FALSE); - choose_windows(&argv[0][2]); - config_error_done(); - break; #endif case '@': flags.randomall = 1; @@ -904,14 +733,14 @@ boolean wr; #endif /* CHDIR */ #ifdef PORT_HELP -#if defined(MSDOS) || defined(WIN32) +#if defined(MSDOS) void port_help() { /* display port specific help file */ display_file(PORT_HELP, 1); } -#endif /* MSDOS || WIN32 */ +#endif /* MSDOS */ #endif /* PORT_HELP */ /* validate wizard mode if player has requested access to it */ @@ -930,71 +759,6 @@ authorize_wizard_mode() #define PATH_SEPARATOR '\\' #endif -#if defined(WIN32) && !defined(WIN32CON) -static char exenamebuf[PATHLEN]; -extern HANDLE hConIn; -extern HANDLE hConOut; -boolean has_fakeconsole; - -char * -exename() -{ - int bsize = PATHLEN; - char *tmp = exenamebuf, *tmp2; - -#ifdef UNICODE - { - TCHAR wbuf[PATHLEN * 4]; - GetModuleFileName((HANDLE) 0, wbuf, PATHLEN * 4); - WideCharToMultiByte(CP_ACP, 0, wbuf, -1, tmp, bsize, NULL, NULL); - } -#else - *(tmp + GetModuleFileName((HANDLE) 0, tmp, bsize)) = '\0'; -#endif - tmp2 = strrchr(tmp, PATH_SEPARATOR); - if (tmp2) - *tmp2 = '\0'; - tmp2++; - return tmp2; -} - -boolean -fakeconsole(void) -{ - if (!hStdOut) { - HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); - HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE); - - if (!hStdOut && !hStdIn) { - /* Bool rval; */ - AllocConsole(); - AttachConsole(GetCurrentProcessId()); - /* rval = SetStdHandle(STD_OUTPUT_HANDLE, hWrite); */ - freopen("CON", "w", stdout); - freopen("CON", "r", stdin); - } - has_fakeconsole = TRUE; - } - - /* Obtain handles for the standard Console I/O devices */ - hConIn = GetStdHandle(STD_INPUT_HANDLE); - hConOut = GetStdHandle(STD_OUTPUT_HANDLE); -#if 0 - if (!SetConsoleCtrlHandler((PHANDLER_ROUTINE) CtrlHandler, TRUE)) { - /* Unable to set control handler */ - cmode = 0; /* just to have a statement to break on for debugger */ - } -#endif - return has_fakeconsole; -} -void freefakeconsole() -{ - if (has_fakeconsole) { - FreeConsole(); - } -} -#endif - #define EXEPATHBUFSZ 256 char exepathbuf[EXEPATHBUFSZ]; @@ -1009,19 +773,7 @@ char *str; return (char *) 0; bsize = EXEPATHBUFSZ; tmp = exepathbuf; -#ifndef WIN32 Strcpy(tmp, str); -#else -#ifdef UNICODE - { - TCHAR wbuf[BUFSZ]; - GetModuleFileName((HANDLE) 0, wbuf, BUFSZ); - WideCharToMultiByte(CP_ACP, 0, wbuf, -1, tmp, bsize, NULL, NULL); - } -#else - *(tmp + GetModuleFileName((HANDLE) 0, tmp, bsize)) = '\0'; -#endif -#endif tmp2 = strrchr(tmp, PATH_SEPARATOR); if (tmp2) *tmp2 = '\0'; diff --git a/sys/share/safeproc.c b/sys/share/safeproc.c new file mode 100644 index 000000000..b3b991a7c --- /dev/null +++ b/sys/share/safeproc.c @@ -0,0 +1,550 @@ +/* NetHack 3.6 safeproc.c */ +/* Copyright (c) Michael Allison, 2018 */ +/* NetHack may be freely redistributed. See license for details. */ + +#include "hack.h" +#include + +/* + * *********************************************************** + * This is a complete WindowPort implementation that can be + * assigned to the windowproc function pointers very early + * in the startup initialization, perhaps immediately even. + * It requires only the following call: + * windowprocs = get_safe_procs(0); + * + * The game startup can trigger functions in other modules + * that make assumptions on a WindowPort being available + * and bad things can happen if any function pointers are + * null at that time. + * + * Some ports prior to 3.6.2 made attempts to early init + * various pieces of one of their WindowPorts, but that + * caused conflicts if that particular WindowPort wasn't + * the one that the user ended up selecting in their + * config file later. The WindowPort interfaced was designed + * to allow multiple WindowPorts to be linked into the same + * game binary. + * + * The base functions established by a call to get_safe_procs() + * accomplish the goal of preventing crashes, but not much + * else. + * + * There are also a few additional functions provided in here + * that can be selected optionally to provide some startup + * functionality for getting messages out to the user about + * issues that are being experienced during startup in + * general or during options parsing. The ones in here are + * deliberately free from any platforms or OS specific code. + * Please leave them using stdio C routines as much as + * possible. That isn't to say you can't do fancier functions + * prior to initialization of the primary WindowPort, but you + * can provide those platform-specific functions elsewhere, + * and assign them the same way that these more generic versions + * are assigned. + * + * The additional platform-independent, but more functional + * routines provided in here should be assigned after the + * windowprocs = get_safe_procs() + * call. Here's a list of them: + * + * + * + * + * *********************************************************** + */ + +struct window_procs safe_procs = { + "safe-startup", 0L, 0L, + safe_init_nhwindows, safe_player_selection, safe_askname, safe_get_nh_event, + safe_exit_nhwindows, safe_suspend_nhwindows, safe_resume_nhwindows, + safe_create_nhwindow, safe_clear_nhwindow, safe_display_nhwindow, + safe_destroy_nhwindow, safe_curs, safe_putstr, genl_putmixed, + safe_display_file, safe_start_menu, safe_add_menu, safe_end_menu, + safe_select_menu, safe_message_menu, safe_update_inventory, safe_mark_synch, + safe_wait_synch, +#ifdef CLIPPING + safe_cliparound, +#endif +#ifdef POSITIONBAR + safe_update_positionbar, +#endif + safe_print_glyph, safe_raw_print, safe_raw_print_bold, safe_nhgetch, + safe_nh_poskey, safe_nhbell, safe_doprev_message, safe_yn_function, + safe_getlin, safe_get_ext_cmd, safe_number_pad, safe_delay_output, +#ifdef CHANGE_COLOR /* the Mac uses a palette device */ + safe_change_color, +#ifdef MAC + safe_change_background, set_safe_font_name, +#endif + safe_get_color_string, +#endif + safe_start_screen, safe_end_screen, genl_outrip, + safe_preference_update, + safe_getmsghistory, safe_putmsghistory, + safe_status_init, + safe_status_finish, safe_status_enablefield, +#ifdef STATUS_HILITES + safe_status_update, +#else + safe_status_update, +#endif + safe_can_suspend, +}; + +struct window_procs * +get_safe_procs(optn) +int optn; +{ + if (optn) { + /* include the slightly more functional stdc versions */ + safe_procs.win_raw_print = stdio_raw_print; + safe_procs.win_raw_print_bold = stdio_raw_print_bold; + safe_procs.win_nhgetch = stdio_nhgetch; + safe_procs.win_wait_synch = stdio_wait_synch; + } + return &safe_procs; +} + +/*ARGSUSED*/ +void +safe_init_nhwindows(argcp, argv) +int *argcp UNUSED; +char **argv UNUSED; +{ + return; +} + +void +safe_player_selection() +{ + return; +} + +void +safe_askname() +{ + return; +} + +void +safe_get_nh_event() +{ + return; +} + +void +safe_suspend_nhwindows(str) +const char *str; +{ + return; +} + +void +safe_resume_nhwindows() +{ + return; +} + +void +safe_exit_nhwindows(str) +const char *str; +{ + return; +} + +winid +safe_create_nhwindow(type) +int type; +{ + return WIN_ERR; +} + +void +safe_clear_nhwindow(window) +winid window; +{ + return; +} + +/*ARGSUSED*/ +void +safe_display_nhwindow(window, blocking) +winid window; +boolean blocking; +{ + return; +} + +void +safe_dismiss_nhwindow(window) +winid window; +{ + return; +} + +void +safe_destroy_nhwindow(window) +winid window; +{ + return; +} + +void +safe_curs(window, x, y) +winid window; +int x, y; +{ + return; +} + +void +safe_putstr(window, attr, str) +winid window; +int attr; +const char *str; +{ + return; +} + +void +safe_display_file(fname, complain) +const char *fname; +boolean complain; +{ + return; +} + +void +safe_start_menu(window) +winid window; +{ + return; +} + +/*ARGSUSED*/ +/* + * Add a menu item to the beginning of the menu list. This list is reversed + * later. + */ +void +safe_add_menu(window, glyph, identifier, ch, gch, attr, str, preselected) +winid window; /* window to use, must be of type NHW_MENU */ +int glyph UNUSED; /* glyph to display with item (not used) */ +const anything *identifier; /* what to return if selected */ +char ch; /* keyboard accelerator (0 = pick our own) */ +char gch; /* group accelerator (0 = no group) */ +int attr; /* attribute for string (like safe_putstr()) */ +const char *str; /* menu string */ +boolean preselected; /* item is marked as selected */ +{ + return; +} + +/* + * End a menu in this window, window must a type NHW_MENU. + */ +void +safe_end_menu(window, prompt) +winid window; /* menu to use */ +const char *prompt; /* prompt to for menu */ +{ + return; +} + +int +safe_select_menu(window, how, menu_list) +winid window; +int how; +menu_item **menu_list; +{ + return 0; +} + +/* special hack for treating top line --More-- as a one item menu */ +char +safe_message_menu(let, how, mesg) +char let; +int how; +const char *mesg; +{ + return '\033'; +} + +void +safe_update_inventory() +{ + return; +} + +void +safe_mark_synch() +{ +} + +void +safe_wait_synch() +{ +} + +#ifdef CLIPPING +void +safe_cliparound(x, y) +int x, y; +{ +} +#endif /* CLIPPING */ + +/* + * safe_print_glyph + * + * Print the glyph to the output device. Don't flush the output device. + */ +void +safe_print_glyph(window, x, y, glyph, bkglyph) +winid window; +xchar x, y; +int glyph; +int bkglyph UNUSED; +{ + return; +} + +void +safe_raw_print(str) +const char *str; +{ + return; +} + +void +safe_raw_print_bold(str) +const char *str; +{ + return; +} + +int +safe_nhgetch() +{ + return '\033'; +} + +/* + * return a key, or 0, in which case a mouse button was pressed + * mouse events should be returned as character postitions in the map window. + * Since normal tty's don't have mice, just return a key. + */ +/*ARGSUSED*/ +int +safe_nh_poskey(x, y, mod) +int *x, *y, *mod; +{ + return '\033'; +} + +void +win_safe_init(dir) +int dir; +{ + return; +} + +#ifdef POSITIONBAR +void +safe_update_positionbar(posbar) +char *posbar; +{ + return; +} +#endif /* POSITIONBAR */ + +/* + * safe_status_init() + * -- initialize the port-specific data structures. + */ +void +safe_status_init() +{ + return; +} + +void +safe_can_suspend() +{ + return; +} + +void +safe_nhbell() +{ + return; +} + +int +safe_doprev_message() +{ + return 0; +} + +char +safe_yn_function(query, resp, def) +const char *query; +const char *resp; +char def; +{ + return '\033'; +} + +/*ARGSUSED*/ +static void +safe_getlin(prompt, outbuf) +const char *prompt UNUSED; +char *outbuf; +{ + Strcpy(outbuf, "\033"); +} + +int +safe_get_ext_cmd() +{ + return '\033'; +} + +void +safe_number_pad(mode) +int mode; +{ + return; +} + +void +safe_delay_output() +{ + return; +} + +void +safe_start_screen() +{ + return; +} + +void +safe_end_screen() +{ + return; +} + +void +safe_outrip(tmpwin, how, when) +winid tmpwin; +int how; +time_t when; +{ + return; +} + +/*ARGSUSED*/ +void +safe_preference_update(pref) +const char *pref UNUSED; +{ + return; +} + +char * +safe_getmsghistory(init) +boolean init UNUSED; +{ + return (char *) 0; +} + +void +safe_putmsghistory(msg, is_restoring) +const char *msg; +boolean is_restoring; +{ +} + +void +safe_status_finish() +{ +} + +void +safe_status_enablefield(fieldidx, nm, fmt, enable) +int fieldidx; +const char *nm; +const char *fmt; +boolean enable; +{ +} + +#ifdef STATUS_HILITES +/* call once for each field, then call with BL_FLUSH to output the result */ +void +safe_status_update(idx, ptr, chg, percent, color, colormasks) +int idx; +genericptr_t ptr; +int chg UNUSED, percent UNUSED, color UNUSED; +unsigned long *colormasks UNUSED; +{ +} +#endif /* STATUS_HILITES */ + +/************************************************************** + * These are some optionally selectable routines that add + * some base functionality over the safe_* versions above. + * The safe_* versions are primarily designed to ensure that + * there are no null function pointers remaining at early + * game startup/initialization time. + * + * The slightly more functional versions in here should be kept + * free of platform-specific code or OS-specific code. If you + * want to use versions that involve platform-specific or + * OS-specific code, go right ahead but use your own replacement + * version of the functions in a platform-specific or + * OS-specific source file, not in here. + ***************************************************************/ + +/* Add to your code: windowprocs.win_raw_print = stdio_wait_synch; */ +void +stdio_wait_synch() +{ + char valid[] = {' ', '\n', '\r', '\033', '\0'}; + + fprintf(stdout, "--More--"); + (void) fflush(stdout); + while (!index(valid, stdio_nhgetch())) + ; +} + +/* Add to your code: windowprocs.win_raw_print = stdio_raw_print; */ +void +stdio_raw_print(str) +const char *str; +{ + if (str) + fprintf(stdout, "%s\n", str); + return; +} + +/* Add to your code: windowprocs.win_raw_print_bold = stdio_raw_print_bold; */ +void +stdio_raw_print_bold(str) +const char *str; +{ + stdio_raw_print(str); + return; +} + +/* Add to your code: windowprocs.win_nhgetch = stdio_nhgetch; */ +int +stdio_nhgetch() +{ + return getchar(); +} + + +/* safeprocs.c */ diff --git a/sys/winnt/Makefile.msc b/sys/winnt/Makefile.msc index 3bc520282..e8b4e22d3 100644 --- a/sys/winnt/Makefile.msc +++ b/sys/winnt/Makefile.msc @@ -215,7 +215,7 @@ VOBJ06 = $(O)dothrow.o $(O)drawing.o $(O)dungeon.o $(O)eat.o VOBJ07 = $(O)end.o $(O)engrave.o $(O)exper.o $(O)explode.o VOBJ08 = $(O)extralev.o $(O)files.o $(O)fountain.o $(O)hack.o VOBJ09 = $(O)hacklib.o $(O)invent.o $(O)light.o $(O)lock.o -VOBJ10 = $(O)mail.o $(O)pcmain.o $(O)makemon.o $(O)mapglyph.o $(O)mcastu.o +VOBJ10 = $(O)mail.o $(O)makemon.o $(O)mapglyph.o $(O)mcastu.o VOBJ11 = $(O)mhitm.o $(O)mhitu.o $(O)minion.o $(O)mklev.o VOBJ12 = $(O)mkmap.o $(O)mkmaze.o $(O)mkobj.o $(O)mkroom.o VOBJ13 = $(O)mon.o $(O)mondata.o $(O)monmove.o $(O)monst.o @@ -233,7 +233,7 @@ VOBJ24 = $(O)track.o $(O)trap.o $(O)u_init.o $(O)uhitm.o VOBJ25 = $(O)vault.o $(O)vis_tab.o $(O)vision.o $(O)weapon.o VOBJ26 = $(O)were.o $(O)wield.o $(O)windows.o $(O)wizard.o VOBJ27 = $(O)worm.o $(O)worn.o $(O)write.o $(O)zap.o -VOBJ28 = $(O)win10.o +VOBJ28 = $(O)win10.o $(O)safeproc.o $(O)windmain.o DLBOBJ = $(O)dlb.o @@ -535,7 +535,7 @@ INCLDIR= /I..\include /I..\sys\winnt # Util builds #========================================== -cflagsBuild = $(cflags) $(INCLDIR) $(WINPFLAG) $(DLBFLG) +cflagsBuild = $(cflags) $(INCLDIR) $(WINPFLAG) $(DLBFLG) -DSAFEPROCS lflagsBuild = $(lflags) $(conlibs) $(MACHINE) #========================================== @@ -1461,7 +1461,7 @@ $(O)guistub.o: $(HACK_H) $(MSWSYS)\stubs.c # $(O)winhack.o: $(HACK_H) $(MSWIN)\winhack.c - @$(cc) $(cflagsBuild) -I$(MSWSYS) -I$(MSWIN) -Fo$@ $(MSWIN)\winhack.c + @$(cc) $(cflagsBuild) -DSAFEPROCS -I$(MSWSYS) -I$(MSWIN) -Fo$@ $(MSWIN)\winhack.c #if you aren't linking in the full tty then #include the following stub for proper linkage. @@ -1511,9 +1511,9 @@ $(O)\curswins.c: $(WCURSES)\curswins.c $(WCURSES)\curswins.h $(INCL)\wincurs.h $(O)tos.o: ..\sys\atari\tos.c $(HACK_H) $(INCL)\tcap.h @$(CC) $(cflagsBuild) -Fo$@ ..\sys\atari\tos.c -$(O)pcmain.o: ..\sys\share\pcmain.c $(HACK_H) $(INCL)\dlb.h \ - $(MSWSYS)\win32api.h - @$(CC) $(cflagsBuild) -Fo$@ ..\sys\share\pcmain.c +$(O)pcmain.o: ..\sys\share\pcmain.c $(HACK_H) $(INCL)\dlb.h +$(O)safeprocs.o: ..\sys\share\safeprocs.c $(HACK_H) $(MSWSYS)\win32api.h + @$(CC) $(cflagsBuild) -Fo$@ ..\sys\share\safeprocs.c $(O)pcsys.o: ..\sys\share\pcsys.c $(HACK_H) @$(CC) $(cflagsBuild) -Fo$@ ..\sys\share\pcsys.c $(O)pctty.o: ..\sys\share\pctty.c $(HACK_H) diff --git a/sys/winnt/stubs.c b/sys/winnt/stubs.c index 3e7fa4c20..af10a7fc0 100644 --- a/sys/winnt/stubs.c +++ b/sys/winnt/stubs.c @@ -96,13 +96,11 @@ clear_screen() return; } -#ifdef TTY_GRAPHICS void backsp() { return; } -#endif int has_color(int color) diff --git a/sys/winnt/windmain.c b/sys/winnt/windmain.c new file mode 100644 index 000000000..9768a8e6f --- /dev/null +++ b/sys/winnt/windmain.c @@ -0,0 +1,757 @@ +/* NetHack 3.6 windmain.c $NHDT-Date: 1543465755 2018/11/29 04:29:15 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.101 $ */ +/* Copyright (c) Derek S. Ray, 2015. */ +/* NetHack may be freely redistributed. See license for details. */ + +/* main.c - Windows */ + +#include "win32api.h" /* for GetModuleFileName */ +#include "hack.h" +#include "dlb.h" +#include +#include + +#if !defined(SAFEPROCS) +#error You must #define SAFEPROCS to build windmain.c +#endif + +#define E extern +static void FDECL(process_options, (int argc, char **argv)); +static void NDECL(nhusage); +static char *FDECL(exepath, (char *)); +char *NDECL(exename); +boolean NDECL(fakeconsole); +void NDECL(freefakeconsole); +E void FDECL(nethack_exit, (int)); +#if defined(MSWIN_GRAPHICS) +E void NDECL(mswin_destroy_reg); +#endif +#undef E + +int NDECL(windows_nhgetch); +void NDECL(windows_nhbell); +int FDECL(windows_nh_poskey, (int *, int *, int *)); +void FDECL(windows_raw_print, (const char *)); +char FDECL(windows_yn_function, (const char *, const char *, CHAR_P)); +void FDECL(windows_getlin, (const char *, char *)); + +char orgdir[PATHLEN]; +extern boolean getreturn_enabled; /* from sys/share/pcsys.c */ +extern int redirect_stdout; /* from sys/share/pcsys.c */ +extern int GUILaunched; +HANDLE hStdOut; +#if defined(MSWIN_GRAPHICS) +char default_window_sys[] = "mswin"; +#endif + +/* + * __MINGW32__ Note + * If the graphics version is built, we don't need a main; it is skipped + * to help MinGW decide which entry point to choose. If both main and + * WinMain exist, the resulting executable won't work correctly. + */ +int +#ifndef __MINGW32__ +main(argc, argv) +#else +mingw_main(argc, argv) +#endif +int argc; +char *argv[]; +{ + boolean save_getreturn_status = getreturn_enabled; + boolean resuming = FALSE; /* assume new game */ + register int fd; + register char *dir; + char *envp = NULL; + char *sptr = NULL; + char fnamebuf[BUFSZ], encodedfnamebuf[BUFSZ]; + char failbuf[BUFSZ]; + + /* + * Get a set of valid safe windowport function + * pointers during early startup initialization. + */ + if (!WINDOWPORT("safe-startup")) + windowprocs = *get_safe_procs(1); + sys_early_init(); +#ifdef _MSC_VER +# ifdef DEBUG + /* set these appropriately for VS debugging */ + _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG); + _CrtSetReportMode(_CRT_ERROR, + _CRTDBG_MODE_DEBUG); /* | _CRTDBG_MODE_FILE);*/ + _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG); +/*| _CRTDBG_MODE_FILE | _CRTDBG_MODE_WNDW);*/ +/* use STDERR by default +_CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); +_CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/ +/* Heap Debugging + _CrtSetDbgFlag( _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) + | _CRTDBG_ALLOC_MEM_DF + | _CRTDBG_CHECK_ALWAYS_DF + | _CRTDBG_CHECK_CRT_DF + | _CRTDBG_DELAY_FREE_MEM_DF + | _CRTDBG_LEAK_CHECK_DF); + _CrtSetBreakAlloc(1423); +*/ +# endif +#endif + + hname = "NetHack"; /* used for syntax messages */ + /* Save current directory and make sure it gets restored when + * the game is exited. + */ + if (getcwd(orgdir, sizeof orgdir) == (char *) 0) + error("NetHack: current directory path too long"); + dir = nh_getenv("NETHACKDIR"); + if (dir == (char *) 0) + dir = nh_getenv("HACKDIR"); + if (dir == (char *) 0) + dir = exepath(argv[0]); +#ifdef _MSC_VER + if (IsDebuggerPresent()) { + static char exepath[_MAX_PATH]; + /* check if we're running under the debugger so we can get to the right folder anyway */ + if (dir != (char *)0) { + char *top = (char *)0; + + if (strlen(dir) < (_MAX_PATH - 1)) + strcpy(exepath, dir); + top = strstr(exepath, "\\build\\.\\Debug"); + if (!top) top = strstr(exepath, "\\build\\.\\Release"); + if (top) { + *top = '\0'; + if (strlen(exepath) < (_MAX_PATH - (strlen("\\binary\\") + 1))) { + Strcat(exepath, "\\binary\\"); + if (strlen(exepath) < (PATHLEN - 1)) { + dir = exepath; + } + } + } + } + } +#endif + if (dir != (char *)0) { + int prefcnt; + int fd; + boolean have_syscf = FALSE; + + (void) strncpy(hackdir, dir, PATHLEN - 1); + hackdir[PATHLEN - 1] = '\0'; + fqn_prefix[0] = (char *) alloc(strlen(hackdir) + 2); + Strcpy(fqn_prefix[0], hackdir); + append_slash(fqn_prefix[0]); + for (prefcnt = 1; prefcnt < PREFIX_COUNT; prefcnt++) + fqn_prefix[prefcnt] = fqn_prefix[0]; + /* sysconf should be searched for in this location */ + envp = nh_getenv("COMMONPROGRAMFILES"); + if (envp) { + if ((sptr = index(envp, ';')) != 0) + *sptr = '\0'; + if (strlen(envp) > 0) { + fqn_prefix[SYSCONFPREFIX] = + (char *) alloc(strlen(envp) + 10); + Strcpy(fqn_prefix[SYSCONFPREFIX], envp); + append_slash(fqn_prefix[SYSCONFPREFIX]); + Strcat(fqn_prefix[SYSCONFPREFIX], "NetHack\\"); + } + } + + /* okay so we have the overriding and definitive locaton + for sysconf, but only in the event that there is not a + sysconf file there (for whatever reason), check a secondary + location rather than abort. */ + + /* Is there a SYSCF_FILE there? */ + fd = open(fqname(SYSCF_FILE, SYSCONFPREFIX, 0), O_RDONLY); + if (fd >= 0) { + /* readable */ + close(fd); + have_syscf = TRUE; + } + + if (!have_syscf) { + /* No SYSCF_FILE where there should be one, and + without an installer, a user may not be able + to place one there. So, let's try somewhere else... */ + fqn_prefix[SYSCONFPREFIX] = fqn_prefix[0]; + + /* Is there a SYSCF_FILE there? */ + fd = open(fqname(SYSCF_FILE, SYSCONFPREFIX, 0), O_RDONLY); + if (fd >= 0) { + /* readable */ + close(fd); + have_syscf = TRUE; + } + } + + /* user's home directory should default to this - unless + * overridden */ + envp = nh_getenv("USERPROFILE"); + if (envp) { + if ((sptr = index(envp, ';')) != 0) + *sptr = '\0'; + if (strlen(envp) > 0) { + fqn_prefix[CONFIGPREFIX] = + (char *) alloc(strlen(envp) + 2); + Strcpy(fqn_prefix[CONFIGPREFIX], envp); + append_slash(fqn_prefix[CONFIGPREFIX]); + } + } + } + save_getreturn_status = getreturn_enabled; + getreturn_enabled = TRUE; + check_recordfile((char *) 0); + initoptions(); + if (!validate_prefix_locations(failbuf)) { + raw_printf("Some invalid directory locations were specified:\n\t%s\n", + failbuf); + nethack_exit(EXIT_FAILURE); + } + if (!hackdir[0]) + Strcpy(hackdir, orgdir); + if (argc > 1) { + if (argcheck(argc, argv, ARG_VERSION) == 2) + nethack_exit(EXIT_SUCCESS); + + if (argcheck(argc, argv, ARG_DEBUG) == 1) { + argc--; + argv++; + } + if (argcheck(argc, argv, ARG_WINDOWS) == 1) { + argc--; + argv++; + } + if (argc > 1 && !strncmp(argv[1], "-d", 2) && argv[1][2] != 'e') { + /* avoid matching "-dec" for DECgraphics; since the man page + * says -d directory, hope nobody's using -desomething_else + */ + argc--; + argv++; + dir = argv[0] + 2; + if (*dir == '=' || *dir == ':') + dir++; + if (!*dir && argc > 1) { + argc--; + argv++; + dir = argv[0]; + } + if (!*dir) + error("Flag -d must be followed by a directory name."); + Strcpy(hackdir, dir); + } + if (argc > 1) { +#if !defined(TTY_GRAPHICS) + int sfd = 0; + boolean tmpconsole = FALSE; + hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); +#endif + /* + * Now we know the directory containing 'record' and + * may do a prscore(). + */ + if (!strncmp(argv[1], "-s", 2)) { +#if !defined(TTY_GRAPHICS) + /* + * Check to see if we're redirecting to a file. + */ + sfd = (int) _fileno(stdout); + redirect_stdout = (sfd >= 0) ? !isatty(sfd) : 0; + + if (!redirect_stdout && !hStdOut) { + raw_printf( + "-s is not supported for the Graphical Interface\n"); + nethack_exit(EXIT_SUCCESS); + } +#endif +#ifdef SYSCF + initoptions(); +#endif + prscore(argc, argv); + +#if !defined(TTY_GRAPHICS) + if (tmpconsole) { + getreturn("to exit"); + freefakeconsole(); + tmpconsole = FALSE; + } +#endif + nethack_exit(EXIT_SUCCESS); + } + +#if defined(MSWIN_GRAPHICS) + if (!strncmpi(argv[1], "-clearreg", 6)) { /* clear registry */ + mswin_destroy_reg(); + nethack_exit(EXIT_SUCCESS); + } +#endif + /* Don't initialize the window system just to print usage */ + if (!strncmp(argv[1], "-?", 2) || !strncmp(argv[1], "/?", 2)) { + nhusage(); + +#if !defined(TTY_GRAPHICS) + if (tmpconsole) { + getreturn("to exit"); + freefakeconsole(); + tmpconsole = FALSE; + } +#endif + nethack_exit(EXIT_SUCCESS); + } + } + } + getreturn_enabled = save_getreturn_status; + +/* + * It seems you really want to play. + */ + /* In 3.6.0, several ports process options before they init + * the window port. This allows settings that impact window + * ports to be specified or read from the sys or user config files. + */ + process_options(argc, argv); + + if (argc >= 1 + && !strcmpi(default_window_sys, "mswin") + && strstri(argv[0], "nethackw.exe")) + iflags.windowtype_locked = TRUE; + +#if defined(TTY_GRAPHICS) + if (!iflags.windowtype_locked) + Strcpy(default_window_sys, "tty"); +#else +#if defined(CURSES_GRAPHICS) + if (!iflags.windowtype_locked) + Strcpy(default_window_sys, "curses"); +#endif +#endif + choose_windows(default_window_sys); + if (!dlb_init()) { + pline( + "%s\n%s\n%s\n%s\n\nNetHack was unable to open the required file " + "\"%s\".%s", + copyright_banner_line(1), copyright_banner_line(2), + copyright_banner_line(3), copyright_banner_line(4), DLBFILE, + "\nAre you perhaps trying to run NetHack within a zip utility?"); + error("dlb_init failure."); + } + + u.uhp = 1; /* prevent RIP on early quits */ + u.ux = 0; /* prevent flush_screen() */ + + nethack_enter(argc, argv); + iflags.use_background_glyph = FALSE; + if (WINDOWPORT("mswin")) + iflags.use_background_glyph = TRUE; + if (WINDOWPORT("tty")) + nttty_open(1); + + init_nhwindows(&argc, argv); + + if (WINDOWPORT("tty")) + toggle_mouse_support(); + + /* strip role,race,&c suffix; calls askname() if plname[] is empty + or holds a generic user name like "player" or "games" */ + plnamesuffix(); + set_playmode(); /* sets plname to "wizard" for wizard mode */ + /* until the getlock code is resolved, override askname()'s + setting of renameallowed; when False, player_selection() + won't resent renaming as an option */ + iflags.renameallowed = FALSE; + /* Obtain the name of the logged on user and incorporate + * it into the name. */ + Sprintf(fnamebuf, "%s-%s", get_username(0), plname); + (void) fname_encode( + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-.", '%', + fnamebuf, encodedfnamebuf, BUFSZ); + Sprintf(lock, "%s", encodedfnamebuf); + /* regularize(lock); */ /* we encode now, rather than substitute */ + getlock(); + + /* Set up level 0 file to keep the game state. + */ + fd = create_levelfile(0, (char *) 0); + if (fd < 0) { + raw_print("Cannot create lock file"); + } else { + hackpid = GetCurrentProcessId(); + write(fd, (genericptr_t) &hackpid, sizeof(hackpid)); + nhclose(fd); + } + /* + * Initialize the vision system. This must be before mklev() on a + * new game or before a level restore on a saved game. + */ + vision_init(); + display_gamewindows(); + getreturn_enabled = TRUE; + /* + * First, try to find and restore a save file for specified character. + * We'll return here if new game player_selection() renames the hero. + */ +attempt_restore: + if ((fd = restore_saved_game()) >= 0) { +#ifdef NEWS + if (iflags.news) { + display_file(NEWS, FALSE); + iflags.news = FALSE; + } +#endif + pline("Restoring save file..."); + mark_synch(); /* flush output */ + if (dorecover(fd)) { + resuming = TRUE; /* not starting new game */ + if (discover) + You("are in non-scoring discovery mode."); + if (discover || wizard) { + if (yn("Do you want to keep the save file?") == 'n') + (void) delete_savefile(); + else { + nh_compress(fqname(SAVEF, SAVEPREFIX, 0)); + } + } + } + } + + if (!resuming) { + /* new game: start by choosing role, race, etc; + player might change the hero's name while doing that, + in which case we try to restore under the new name + and skip selection this time if that didn't succeed */ + if (!iflags.renameinprogress) { + player_selection(); + if (iflags.renameinprogress) { + /* player has renamed the hero while selecting role; + discard current lock file and create another for + the new character name */ + goto attempt_restore; + } + } + newgame(); + if (discover) + You("are in non-scoring discovery mode."); + } + moveloop(resuming); + nethack_exit(EXIT_SUCCESS); + /*NOTREACHED*/ + return 0; +} + +STATIC_OVL void +process_options(argc, argv) +int argc; +char *argv[]; +{ + int i; + + /* + * Process options. + */ + while (argc > 1 && argv[1][0] == '-') { + argv++; + argc--; + switch (argv[0][1]) { + case 'a': + if (argv[0][2]) { + if ((i = str2align(&argv[0][2])) >= 0) + flags.initalign = i; + } else if (argc > 1) { + argc--; + argv++; + if ((i = str2align(argv[0])) >= 0) + flags.initalign = i; + } + break; + case 'D': + wizard = TRUE, discover = FALSE; + break; + case 'X': + discover = TRUE, wizard = FALSE; + break; +#ifdef NEWS + case 'n': + iflags.news = FALSE; + break; +#endif + case 'u': + if (argv[0][2]) + (void) strncpy(plname, argv[0] + 2, sizeof(plname) - 1); + else if (argc > 1) { + argc--; + argv++; + (void) strncpy(plname, argv[0], sizeof(plname) - 1); + } else + raw_print("Player name expected after -u"); + break; + case 'g': + if (argv[0][2]) { + if ((i = str2gend(&argv[0][2])) >= 0) + flags.initgend = i; + } else if (argc > 1) { + argc--; + argv++; + if ((i = str2gend(argv[0])) >= 0) + flags.initgend = i; + } + break; + case 'p': /* profession (role) */ + if (argv[0][2]) { + if ((i = str2role(&argv[0][2])) >= 0) + flags.initrole = i; + } else if (argc > 1) { + argc--; + argv++; + if ((i = str2role(argv[0])) >= 0) + flags.initrole = i; + } + break; + case 'r': /* race */ + if (argv[0][2]) { + if ((i = str2race(&argv[0][2])) >= 0) + flags.initrace = i; + } else if (argc > 1) { + argc--; + argv++; + if ((i = str2race(argv[0])) >= 0) + flags.initrace = i; + } + break; +#if 0 + case 'w': /* windowtype */ +#if defined(TTY_GRAPHICS) + if (!strncmpi(&argv[0][2], "tty", 3)) { + nttty_open(1); + } +#endif + config_error_init(FALSE, "command line", FALSE); + choose_windows(&argv[0][2]); + config_error_done(); + break; +#endif + case '@': + flags.randomall = 1; + break; + default: + if ((i = str2role(&argv[0][1])) >= 0) { + flags.initrole = i; + break; + } else + raw_printf("\nUnknown switch: %s", argv[0]); + /* FALL THROUGH */ + case '?': + nhusage(); + nethack_exit(EXIT_SUCCESS); + } + } +} + +STATIC_OVL void +nhusage() +{ + char buf1[BUFSZ], buf2[BUFSZ], *bufptr; + + buf1[0] = '\0'; + bufptr = buf1; + +#define ADD_USAGE(s) \ + if ((strlen(buf1) + strlen(s)) < (BUFSZ - 1)) \ + Strcat(bufptr, s); + + /* -role still works for those cases which aren't already taken, but + * is deprecated and will not be listed here. + */ + (void) Sprintf(buf2, "\nUsage:\n%s [-d dir] -s [-r race] [-p profession] " + "[maxrank] [name]...\n or", + hname); + ADD_USAGE(buf2); + + (void) Sprintf( + buf2, "\n%s [-d dir] [-u name] [-r race] [-p profession] [-[DX]]", + hname); + ADD_USAGE(buf2); +#ifdef NEWS + ADD_USAGE(" [-n]"); +#endif + if (!iflags.window_inited) + raw_printf("%s\n", buf1); + else + (void) printf("%s\n", buf1); +#undef ADD_USAGE +} + +#ifdef PORT_HELP +void +port_help() +{ + /* display port specific help file */ + display_file(PORT_HELP, 1); +} +#endif /* PORT_HELP */ + +/* validate wizard mode if player has requested access to it */ +boolean +authorize_wizard_mode() +{ + if (!strcmp(plname, WIZARD_NAME)) + return TRUE; + return FALSE; +} + +#define PATH_SEPARATOR '\\' + +#if defined(WIN32) && !defined(WIN32CON) +static char exenamebuf[PATHLEN]; +extern HANDLE hConIn; +extern HANDLE hConOut; +boolean has_fakeconsole; + +char * +exename() +{ + int bsize = PATHLEN; + char *tmp = exenamebuf, *tmp2; + +#ifdef UNICODE + { + TCHAR wbuf[PATHLEN * 4]; + GetModuleFileName((HANDLE) 0, wbuf, PATHLEN * 4); + WideCharToMultiByte(CP_ACP, 0, wbuf, -1, tmp, bsize, NULL, NULL); + } +#else + *(tmp + GetModuleFileName((HANDLE) 0, tmp, bsize)) = '\0'; +#endif + tmp2 = strrchr(tmp, PATH_SEPARATOR); + if (tmp2) + *tmp2 = '\0'; + tmp2++; + return tmp2; +} + +boolean +fakeconsole(void) +{ + if (!hStdOut) { + HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); + HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE); + + if (!hStdOut && !hStdIn) { + /* Bool rval; */ + AllocConsole(); + AttachConsole(GetCurrentProcessId()); + /* rval = SetStdHandle(STD_OUTPUT_HANDLE, hWrite); */ + freopen("CON", "w", stdout); + freopen("CON", "r", stdin); + } + has_fakeconsole = TRUE; + } + + /* Obtain handles for the standard Console I/O devices */ + hConIn = GetStdHandle(STD_INPUT_HANDLE); + hConOut = GetStdHandle(STD_OUTPUT_HANDLE); +#if 0 + if (!SetConsoleCtrlHandler((PHANDLER_ROUTINE) CtrlHandler, TRUE)) { + /* Unable to set control handler */ + cmode = 0; /* just to have a statement to break on for debugger */ + } +#endif + return has_fakeconsole; +} +void freefakeconsole() +{ + if (has_fakeconsole) { + FreeConsole(); + } +} +#endif + +#define EXEPATHBUFSZ 256 +char exepathbuf[EXEPATHBUFSZ]; + +char * +exepath(str) +char *str; +{ + char *tmp, *tmp2; + int bsize; + + if (!str) + return (char *) 0; + bsize = EXEPATHBUFSZ; + tmp = exepathbuf; +#ifdef UNICODE + { + TCHAR wbuf[BUFSZ]; + GetModuleFileName((HANDLE) 0, wbuf, BUFSZ); + WideCharToMultiByte(CP_ACP, 0, wbuf, -1, tmp, bsize, NULL, NULL); + } +#else + *(tmp + GetModuleFileName((HANDLE) 0, tmp, bsize)) = '\0'; +#endif + tmp2 = strrchr(tmp, PATH_SEPARATOR); + if (tmp2) + *tmp2 = '\0'; + return tmp; +} + +/*ARGSUSED*/ +void +windows_raw_print(str) +const char *str; +{ + if (str) + fprintf(stdout, "%s\n", str); + windows_nhgetch(); + return; +} + +/*ARGSUSED*/ +void +windows_raw_print_bold(str) +const char *str; +{ + windows_raw_print(str); + return; +} + +int +windows_nhgetch() +{ + return getchar(); +} + + +void +windows_nhbell() +{ + return; +} + +/*ARGSUSED*/ +int +windows_nh_poskey(x, y, mod) +int *x, *y, *mod; +{ + return '\033'; +} + +/*ARGSUSED*/ +char +windows_yn_function(query, resp, def) +const char *query; +const char *resp; +char def; +{ + return '\033'; +} + +/*ARGSUSED*/ +static void +windows_getlin(prompt, outbuf) +const char *prompt UNUSED; +char *outbuf; +{ + Strcpy(outbuf, "\033"); +} + +/*pcmain.c*/ diff --git a/sys/winnt/winnt.c b/sys/winnt/winnt.c index 0be1da094..f5121bddc 100644 --- a/sys/winnt/winnt.c +++ b/sys/winnt/winnt.c @@ -47,6 +47,9 @@ WIN32_FIND_DATA ffd; typedef HWND(WINAPI *GETCONSOLEWINDOW)(); static HWND GetConsoleHandle(void); static HWND GetConsoleHwnd(void); +#if !defined(TTY_GRAPHICS) +extern void NDECL(backsp); +#endif /* The function pointer nt_kbhit contains a kbhit() equivalent * which varies depending on which window port is active. diff --git a/win/win32/vs2017/NetHack.vcxproj b/win/win32/vs2017/NetHack.vcxproj index e51474a65..84daa8434 100644 --- a/win/win32/vs2017/NetHack.vcxproj +++ b/win/win32/vs2017/NetHack.vcxproj @@ -151,15 +151,16 @@ - + GUISTUB;%(PreprocessorDefinitions) + @@ -254,4 +255,4 @@ - \ No newline at end of file + diff --git a/win/win32/vs2017/NetHackW.vcxproj b/win/win32/vs2017/NetHackW.vcxproj index af28761da..c54c8e9f5 100644 --- a/win/win32/vs2017/NetHackW.vcxproj +++ b/win/win32/vs2017/NetHackW.vcxproj @@ -146,14 +146,15 @@ - + TTYSTUB; + @@ -200,4 +201,4 @@ - \ No newline at end of file + diff --git a/win/win32/winhack.c b/win/win32/winhack.c index 9dcbb4e4b..6796a5ce6 100644 --- a/win/win32/winhack.c +++ b/win/win32/winhack.c @@ -15,6 +15,10 @@ #include "mhmain.h" #include "mhmap.h" +#if !defined(SAFEPROCS) +#error You must #define SAFEPROCS to build winhack.c +#endif + /* Borland and MinGW redefine "boolean" in shlwapi.h, so just use the little bit we need */ typedef struct _DLLVERSIONINFO { @@ -66,7 +70,7 @@ NHWinApp _nethack_app; #endif // Foward declarations of functions included in this code module: -extern boolean FDECL(pcmain, (int, char **)); +extern boolean FDECL(main, (int, char **)); static void __cdecl mswin_moveloop(void *); #define MAX_CMDLINE_PARAM 255 @@ -82,24 +86,44 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, TCHAR *p; TCHAR wbuf[BUFSZ]; char buf[BUFSZ]; + DWORD major, minor; - boolean resuming; /* OSVERSIONINFO osvi; */ UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); UNREFERENCED_PARAMETER(nCmdShow); - /* We must initialize state sufficiently to support calls to panic */ + /* + * Get a set of valid safe windowport function + * pointers during early startup initialization. + * + * When get_safe_procs is called with 0 as the param, + * non-functional, but safe function pointers are set + * for all windowport routines. + * + * When get_safe_procs is called with 1 as the param, + * raw_print, raw_print_bold, and wait_synch, and nhgetch + * are set to use C stdio routines via stdio_raw_print, + * stdio_raw_print_bold, stdio_wait_synch, and + * stdio_nhgetch. + */ + windowprocs = *get_safe_procs(0); + + /* + * Now we are going to override a couple + * of the windowprocs functions so that + * error messages are handled in a suitable + * way for the graphical version. + */ windowprocs.win_raw_print = mswin_raw_print; windowprocs.win_raw_print_bold = mswin_raw_print_bold; windowprocs.win_wait_synch = mswin_wait_synch; win10_init(); - sys_early_init(); - /* init applicatio structure */ + /* init application structure */ _nethack_app.hApp = hInstance; _nethack_app.hAccelTable = LoadAccelerators(hInstance, (LPCTSTR) IDC_NETHACKW); @@ -209,10 +233,9 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, } free(savefile); } - resuming = pcmain(argc, argv); - - moveloop(resuming); + /* let main do the argument processing */ + (void) main(argc, argv); return 0; } From b853c6a75b0782ebd66c5a98ebb85182ac47160a Mon Sep 17 00:00:00 2001 From: nhmall Date: Sat, 8 Dec 2018 18:45:48 -0500 Subject: [PATCH 02/21] Makefile.msc update --- sys/winnt/Makefile.msc | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sys/winnt/Makefile.msc b/sys/winnt/Makefile.msc index e8b4e22d3..4cfd29d6b 100644 --- a/sys/winnt/Makefile.msc +++ b/sys/winnt/Makefile.msc @@ -1503,7 +1503,6 @@ $(O)\curswins.c: $(WCURSES)\curswins.c $(WCURSES)\curswins.h $(INCL)\wincurs.h # * $(CFLAGS) replaced with $(cflagsBuild) # * $(CC) replaced with @$(CC) # * targets prefixed with $(O) -# * the single win32api.h reference uncommented # but otherwise untouched. # That means that there is some irrelevant stuff # in here, but maintenance should be easier. @@ -1512,8 +1511,7 @@ $(O)\curswins.c: $(WCURSES)\curswins.c $(WCURSES)\curswins.h $(INCL)\wincurs.h $(O)tos.o: ..\sys\atari\tos.c $(HACK_H) $(INCL)\tcap.h @$(CC) $(cflagsBuild) -Fo$@ ..\sys\atari\tos.c $(O)pcmain.o: ..\sys\share\pcmain.c $(HACK_H) $(INCL)\dlb.h -$(O)safeprocs.o: ..\sys\share\safeprocs.c $(HACK_H) $(MSWSYS)\win32api.h - @$(CC) $(cflagsBuild) -Fo$@ ..\sys\share\safeprocs.c + @$(CC) $(cflagsBuild) -Fo$@ ..\sys\share\pcmain.c $(O)pcsys.o: ..\sys\share\pcsys.c $(HACK_H) @$(CC) $(cflagsBuild) -Fo$@ ..\sys\share\pcsys.c $(O)pctty.o: ..\sys\share\pctty.c $(HACK_H) From a9342107c8dee746bd2f23e9714ea433323009bc Mon Sep 17 00:00:00 2001 From: nhmall Date: Sat, 8 Dec 2018 20:09:58 -0500 Subject: [PATCH 03/21] relocate safeproc.c from sys/share to win/share --- {sys => win}/share/safeproc.c | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {sys => win}/share/safeproc.c (100%) diff --git a/sys/share/safeproc.c b/win/share/safeproc.c similarity index 100% rename from sys/share/safeproc.c rename to win/share/safeproc.c From 4d2abbe23f00b92863a081eea8cd620a9fcddc26 Mon Sep 17 00:00:00 2001 From: nhmall Date: Sat, 8 Dec 2018 20:11:25 -0500 Subject: [PATCH 04/21] Makefile.msc bit --- sys/winnt/Makefile.msc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/winnt/Makefile.msc b/sys/winnt/Makefile.msc index 4cfd29d6b..c207f254c 100644 --- a/sys/winnt/Makefile.msc +++ b/sys/winnt/Makefile.msc @@ -1461,7 +1461,7 @@ $(O)guistub.o: $(HACK_H) $(MSWSYS)\stubs.c # $(O)winhack.o: $(HACK_H) $(MSWIN)\winhack.c - @$(cc) $(cflagsBuild) -DSAFEPROCS -I$(MSWSYS) -I$(MSWIN) -Fo$@ $(MSWIN)\winhack.c + @$(cc) $(cflagsBuild) -I$(MSWSYS) -I$(MSWIN) -Fo$@ $(MSWIN)\winhack.c #if you aren't linking in the full tty then #include the following stub for proper linkage. From 547f0a32ccf4bd92c83a970db3ba581f42dfcc19 Mon Sep 17 00:00:00 2001 From: nhmall Date: Sat, 8 Dec 2018 20:24:24 -0500 Subject: [PATCH 05/21] Update Visual Studio projects to reflect recent change --- win/win32/vs2017/NetHack.vcxproj | 4 ++-- win/win32/vs2017/NetHackW.vcxproj | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/win/win32/vs2017/NetHack.vcxproj b/win/win32/vs2017/NetHack.vcxproj index 84daa8434..9f193832a 100644 --- a/win/win32/vs2017/NetHack.vcxproj +++ b/win/win32/vs2017/NetHack.vcxproj @@ -34,7 +34,7 @@ Speed true $(WinWin32Dir);$(IncDir);$(SysWinntDir);$(SysShareDir);$(WinShareDir);%(AdditionalIncludeDirectories) - TILES;WIN32CON;DLB;MSWIN_GRAPHICS;_LIB;%(PreprocessorDefinitions) + TILES;WIN32CON;DLB;MSWIN_GRAPHICS;SAFEPROCS;_LIB;%(PreprocessorDefinitions) kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;winmm.lib;Winmm.lib;%(AdditionalDependencies) @@ -154,7 +154,6 @@ - @@ -162,6 +161,7 @@ + diff --git a/win/win32/vs2017/NetHackW.vcxproj b/win/win32/vs2017/NetHackW.vcxproj index c54c8e9f5..d1ede9f0a 100644 --- a/win/win32/vs2017/NetHackW.vcxproj +++ b/win/win32/vs2017/NetHackW.vcxproj @@ -20,7 +20,7 @@ Disabled true $(WinWin32Dir);$(IncDir);$(SysWinntDir);$(SysShareDir);$(WinShareDir);%(AdditionalIncludeDirectories) - TILES;_WINDOWS;DLB;MSWIN_GRAPHICS;NOTTYGRAPHICS;%(PreprocessorDefinitions) + TILES;_WINDOWS;DLB;MSWIN_GRAPHICS;SAFEPROCS;NOTTYGRAPHICS;%(PreprocessorDefinitions) NDEBUG;%(PreprocessorDefinitions) @@ -149,7 +149,6 @@ - TTYSTUB; @@ -157,6 +156,7 @@ + From 01625455d975f05d41f051d0256cf4ae32f154e2 Mon Sep 17 00:00:00 2001 From: nhmall Date: Sat, 8 Dec 2018 21:17:34 -0500 Subject: [PATCH 06/21] more startup tweaking for Windows --- sys/winnt/windmain.c | 34 +++++++++++++++++++++------------- sys/winnt/winnt.c | 8 ++++---- win/win32/winhack.c | 4 +++- 3 files changed, 28 insertions(+), 18 deletions(-) diff --git a/sys/winnt/windmain.c b/sys/winnt/windmain.c index 9768a8e6f..72bf24c11 100644 --- a/sys/winnt/windmain.c +++ b/sys/winnt/windmain.c @@ -241,16 +241,20 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/ Strcpy(hackdir, dir); } if (argc > 1) { +#if 0 #if !defined(TTY_GRAPHICS) int sfd = 0; boolean tmpconsole = FALSE; hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); #endif +#endif /* 0 */ + /* * Now we know the directory containing 'record' and * may do a prscore(). */ if (!strncmp(argv[1], "-s", 2)) { +#if 0 #if !defined(TTY_GRAPHICS) /* * Check to see if we're redirecting to a file. @@ -264,11 +268,13 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/ nethack_exit(EXIT_SUCCESS); } #endif +#endif /* 0 */ #ifdef SYSCF initoptions(); #endif prscore(argc, argv); +#if 0 #if !defined(TTY_GRAPHICS) if (tmpconsole) { getreturn("to exit"); @@ -276,25 +282,26 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/ tmpconsole = FALSE; } #endif +#endif /* 0 */ nethack_exit(EXIT_SUCCESS); } - -#if defined(MSWIN_GRAPHICS) - if (!strncmpi(argv[1], "-clearreg", 6)) { /* clear registry */ - mswin_destroy_reg(); - nethack_exit(EXIT_SUCCESS); + if (GUILaunched) { + if (!strncmpi(argv[1], "-clearreg", 6)) { /* clear registry */ + mswin_destroy_reg(); + nethack_exit(EXIT_SUCCESS); + } } -#endif - /* Don't initialize the window system just to print usage */ + /* Don't initialize the full window system just to print usage */ if (!strncmp(argv[1], "-?", 2) || !strncmp(argv[1], "/?", 2)) { nhusage(); - +#if 0 #if !defined(TTY_GRAPHICS) if (tmpconsole) { getreturn("to exit"); freefakeconsole(); tmpconsole = FALSE; } +#endif #endif nethack_exit(EXIT_SUCCESS); } @@ -313,18 +320,19 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/ if (argc >= 1 && !strcmpi(default_window_sys, "mswin") - && strstri(argv[0], "nethackw.exe")) + && (strstri(argv[0], "nethackw.exe") || GUILaunched)) iflags.windowtype_locked = TRUE; + if (!iflags.windowtype_locked) { #if defined(TTY_GRAPHICS) - if (!iflags.windowtype_locked) Strcpy(default_window_sys, "tty"); #else #if defined(CURSES_GRAPHICS) - if (!iflags.windowtype_locked) Strcpy(default_window_sys, "curses"); -#endif -#endif +#endif /* CURSES */ +#endif /* TTY */ + } + choose_windows(default_window_sys); if (!dlb_init()) { pline( diff --git a/sys/winnt/winnt.c b/sys/winnt/winnt.c index f5121bddc..c5c214f19 100644 --- a/sys/winnt/winnt.c +++ b/sys/winnt/winnt.c @@ -495,12 +495,12 @@ void nhassert_failed(const char * exp, const char * file, int line) error(message); } -/* nethack_enter_winnt() is the first thing called from main */ +/* nethack_enter_winnt() is called from main immediately after + initializing the window port */ void nethack_enter_winnt() { -#ifdef TTY_GRAPHICS - nethack_enter_nttty(); -#endif + if (WINDOWPORT("tty")) + nethack_enter_nttty(); } /* CP437 to Unicode mapping according to the Unicode Consortium */ diff --git a/win/win32/winhack.c b/win/win32/winhack.c index 6796a5ce6..c6941d7c0 100644 --- a/win/win32/winhack.c +++ b/win/win32/winhack.c @@ -63,6 +63,8 @@ _nhapply_image_transparent(HDC hDC, int x, int y, int width, int height, // Global Variables: NHWinApp _nethack_app; +extern int GUILaunched; /* We tell shared startup code in windmain.c + that the GUI was launched via this */ #ifdef __BORLANDC__ #define _stricmp(s1, s2) stricmp(s1, s2) @@ -233,7 +235,7 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, } free(savefile); } - + GUILaunched = 1; /* let main do the argument processing */ (void) main(argc, argv); return 0; From afc34d30163740313120df4a7b3fa25d6ec7c725 Mon Sep 17 00:00:00 2001 From: nhmall Date: Sat, 8 Dec 2018 22:08:55 -0500 Subject: [PATCH 07/21] a late bot() call was observed on GUI Windows so prevent such a crash --- src/botl.c | 3 ++- win/share/safeproc.c | 21 ++++++++++++++++----- win/win32/mswproc.c | 7 +++++++ 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/src/botl.c b/src/botl.c index 2fa84afe0..db96c160b 100644 --- a/src/botl.c +++ b/src/botl.c @@ -234,7 +234,8 @@ do_statusline2() void bot() { - if (youmonst.data && iflags.status_updates) { + /* dosave() flags completion by setting u.uhp to -1 */ + if ((u.uhp != -1) && youmonst.data && iflags.status_updates) { #ifdef STATUS_HILITES bot_via_windowport(); #else diff --git a/win/share/safeproc.c b/win/share/safeproc.c index b3b991a7c..1f268ee16 100644 --- a/win/share/safeproc.c +++ b/win/share/safeproc.c @@ -11,7 +11,7 @@ * assigned to the windowproc function pointers very early * in the startup initialization, perhaps immediately even. * It requires only the following call: - * windowprocs = get_safe_procs(0); + * windowprocs = *get_safe_procs(0); * * The game startup can trigger functions in other modules * that make assumptions on a WindowPort being available @@ -45,12 +45,23 @@ * * The additional platform-independent, but more functional * routines provided in here should be assigned after the - * windowprocs = get_safe_procs() - * call. Here's a list of them: + * windowprocs = *get_safe_procs(n) + * call. * - * + * Usage: + * + * windowprocs = *get_safe_procs(0); + * initializes a set of winprocs function pointers that ensure + * none of the function pointers are left null, but that's all + * it does. + * + * windowprocs = *get_safe_procs(1); + * initializes a set of winprocs functions pointers that ensure + * none of the function pointers are left null, but also + * provides some basic output and input functionality using + * nothing other than C stdio routines (no platform-specific + * or OS-specific code). * - * * *********************************************************** */ diff --git a/win/win32/mswproc.c b/win/win32/mswproc.c index 3cfcc95bf..85f427725 100644 --- a/win/win32/mswproc.c +++ b/win/win32/mswproc.c @@ -718,6 +718,13 @@ mswin_exit_nhwindows(const char *str) /* Write Window settings to the registry */ mswin_write_reg(); + /* set things back to failsafes */ + windowprocs = *get_safe_procs(0); + + /* and make sure there is still a way to communicate something */ + windowprocs.win_raw_print = mswin_raw_print; + windowprocs.win_raw_print_bold = mswin_raw_print_bold; + windowprocs.win_wait_synch = mswin_wait_synch; } /* Prepare the window to be suspended. */ From 8d516d4358586b3df01da56ae1c9400d52ad1d0e Mon Sep 17 00:00:00 2001 From: nhmall Date: Sat, 8 Dec 2018 22:34:50 -0500 Subject: [PATCH 08/21] clean up Windows exit routines --- sys/share/pcsys.c | 15 +++------------ sys/winnt/winnt.c | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/sys/share/pcsys.c b/sys/share/pcsys.c index 0286ad50b..8a99b181e 100644 --- a/sys/share/pcsys.c +++ b/sys/share/pcsys.c @@ -391,19 +391,11 @@ char *name; return; } -#ifdef WIN32 -boolean getreturn_enabled; -int redirect_stdout; -#endif - +#ifndef WIN32 void getreturn(str) const char *str; { -#ifdef WIN32 - if (!getreturn_enabled) - return; -#endif #ifdef TOS msmsg("Hit %s.", str); #else @@ -414,7 +406,6 @@ const char *str; return; } -#ifndef WIN32 void msmsg VA_DECL(const char *, fmt) { @@ -492,7 +483,7 @@ const char *name, *mode; return (FILE *) 0; } -#if defined(MICRO) || defined(WIN32) || defined(OS2) +#if defined(MICRO) || defined(OS2) void nethack_exit(code) int code; @@ -551,4 +542,4 @@ msexit() wait_synch(); return; } -#endif /* MICRO || WIN32 || OS2 */ +#endif /* MICRO || OS2 */ diff --git a/sys/winnt/winnt.c b/sys/winnt/winnt.c index c5c214f19..86432e028 100644 --- a/sys/winnt/winnt.c +++ b/sys/winnt/winnt.c @@ -43,6 +43,9 @@ boolean win32_cursorblink; /* globals required within here */ HANDLE ffhandle = (HANDLE) 0; WIN32_FIND_DATA ffd; +extern int GUILaunched; +boolean getreturn_enabled; +int redirect_stdout; typedef HWND(WINAPI *GETCONSOLEWINDOW)(); static HWND GetConsoleHandle(void); @@ -495,6 +498,38 @@ void nhassert_failed(const char * exp, const char * file, int line) error(message); } +void +nethack_exit(code) +int code; +{ + /* Only if we started from the GUI, not the command prompt, + * we need to get one last return, so the score board does + * not vanish instantly after being created. + * GUILaunched is defined and set in nttty.c. + */ + synch_cursor(); + if (GUILaunched) + getreturn("to end"); + synch_cursor(); + getreturn_enabled = TRUE; + wait_synch(); + exit(code); +} + +void +getreturn(str) +const char *str; +{ + char buf[BUFSZ]; + + if (!getreturn_enabled) + return; + Sprintf(buf,"Hit %s.", str); + raw_print(buf); + wait_synch(); + return; +} + /* nethack_enter_winnt() is called from main immediately after initializing the window port */ void nethack_enter_winnt() From f706ba094cc805a6be5c3d4377ba4a1c7831f388 Mon Sep 17 00:00:00 2001 From: nhmall Date: Sat, 8 Dec 2018 23:04:53 -0500 Subject: [PATCH 09/21] clean up some tear-down Windows continued to use function pointers belonging to particular window ports that were still assigned even after that port (tty) had gone through its shutdown procedures when requested by the core. Fix that and return to the minimal function pointers that are not part of any of the actual WindowPorts. --- sys/winnt/winnt.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/sys/winnt/winnt.c b/sys/winnt/winnt.c index 86432e028..75dda292d 100644 --- a/sys/winnt/winnt.c +++ b/sys/winnt/winnt.c @@ -507,12 +507,13 @@ int code; * not vanish instantly after being created. * GUILaunched is defined and set in nttty.c. */ - synch_cursor(); + if (GUILaunched) - getreturn("to end"); - synch_cursor(); - getreturn_enabled = TRUE; - wait_synch(); + getreturn_enabled = TRUE; + else + windowprocs = *get_safe_procs(1); + if (getreturn_enabled) + wait_synch(); exit(code); } From cb191e6a0e7d548453747a4ffe7f39db002c382d Mon Sep 17 00:00:00 2001 From: nhmall Date: Sun, 9 Dec 2018 10:14:19 -0500 Subject: [PATCH 10/21] more windmain --- sys/winnt/windmain.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/sys/winnt/windmain.c b/sys/winnt/windmain.c index 72bf24c11..21a2fa1e2 100644 --- a/sys/winnt/windmain.c +++ b/sys/winnt/windmain.c @@ -35,7 +35,7 @@ char FDECL(windows_yn_function, (const char *, const char *, CHAR_P)); void FDECL(windows_getlin, (const char *, char *)); char orgdir[PATHLEN]; -extern boolean getreturn_enabled; /* from sys/share/pcsys.c */ +boolean getreturn_enabled; extern int redirect_stdout; /* from sys/share/pcsys.c */ extern int GUILaunched; HANDLE hStdOut; @@ -58,7 +58,6 @@ mingw_main(argc, argv) int argc; char *argv[]; { - boolean save_getreturn_status = getreturn_enabled; boolean resuming = FALSE; /* assume new game */ register int fd; register char *dir; @@ -199,8 +198,9 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/ } } } - save_getreturn_status = getreturn_enabled; - getreturn_enabled = TRUE; + if (GUILaunched || IsDebuggerPresent()) { + getreturn_enabled = TRUE; + } check_recordfile((char *) 0); initoptions(); if (!validate_prefix_locations(failbuf)) { @@ -307,7 +307,6 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/ } } } - getreturn_enabled = save_getreturn_status; /* * It seems you really want to play. @@ -393,7 +392,6 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/ */ vision_init(); display_gamewindows(); - getreturn_enabled = TRUE; /* * First, try to find and restore a save file for specified character. * We'll return here if new game player_selection() renames the hero. From 46d2724f584a7422388c36bfcd4a378fc63a0705 Mon Sep 17 00:00:00 2001 From: nhmall Date: Sun, 9 Dec 2018 13:09:30 -0500 Subject: [PATCH 11/21] some early startup adjustments --- sys/winnt/windmain.c | 5 +++++ sys/winnt/winnt.c | 20 +++++++++++++++++--- win/share/safeproc.c | 2 +- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/sys/winnt/windmain.c b/sys/winnt/windmain.c index 21a2fa1e2..6b4b0491c 100644 --- a/sys/winnt/windmain.c +++ b/sys/winnt/windmain.c @@ -33,6 +33,7 @@ int FDECL(windows_nh_poskey, (int *, int *, int *)); void FDECL(windows_raw_print, (const char *)); char FDECL(windows_yn_function, (const char *, const char *, CHAR_P)); void FDECL(windows_getlin, (const char *, char *)); +extern int NDECL(windows_console_custom_nhgetch); char orgdir[PATHLEN]; boolean getreturn_enabled; @@ -72,6 +73,9 @@ char *argv[]; */ if (!WINDOWPORT("safe-startup")) windowprocs = *get_safe_procs(1); + if (!GUILaunched) + windowprocs.win_nhgetch = windows_console_custom_nhgetch; + sys_early_init(); #ifdef _MSC_VER # ifdef DEBUG @@ -311,6 +315,7 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/ /* * It seems you really want to play. */ + /* In 3.6.0, several ports process options before they init * the window port. This allows settings that impact window * ports to be specified or read from the sys or user config files. diff --git a/sys/winnt/winnt.c b/sys/winnt/winnt.c index 75dda292d..c75e53c47 100644 --- a/sys/winnt/winnt.c +++ b/sys/winnt/winnt.c @@ -53,6 +53,7 @@ static HWND GetConsoleHwnd(void); #if !defined(TTY_GRAPHICS) extern void NDECL(backsp); #endif +int NDECL(windows_console_custom_nhgetch); /* The function pointer nt_kbhit contains a kbhit() equivalent * which varies depending on which window port is active. @@ -508,15 +509,28 @@ int code; * GUILaunched is defined and set in nttty.c. */ - if (GUILaunched) - getreturn_enabled = TRUE; - else + + if (!GUILaunched) { windowprocs = *get_safe_procs(1); + /* use our custom version which works + a little cleaner than the stdio one */ + windowprocs.win_nhgetch = windows_console_custom_nhgetch; + } if (getreturn_enabled) wait_synch(); exit(code); } +#undef kbhit +#include + +int +windows_console_custom_nhgetch(VOID_ARGS) +{ + return _getch(); +} + + void getreturn(str) const char *str; diff --git a/win/share/safeproc.c b/win/share/safeproc.c index 1f268ee16..671ee1822 100644 --- a/win/share/safeproc.c +++ b/win/share/safeproc.c @@ -527,7 +527,7 @@ stdio_wait_synch() fprintf(stdout, "--More--"); (void) fflush(stdout); - while (!index(valid, stdio_nhgetch())) + while (!index(valid, nhgetch())) ; } From fccc3cbee663cafdd46c57070ba4a6f3cab5410c Mon Sep 17 00:00:00 2001 From: Bart House Date: Sun, 9 Dec 2018 11:30:29 -0800 Subject: [PATCH 12/21] Render the two block glyphs using FillRect instead of DrawText. --- win/win32/mhmap.c | 58 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 42 insertions(+), 16 deletions(-) diff --git a/win/win32/mhmap.c b/win/win32/mhmap.c index d401c4c3c..445299af1 100644 --- a/win/win32/mhmap.c +++ b/win/win32/mhmap.c @@ -160,25 +160,33 @@ mswin_map_stretch(HWND hWnd, LPSIZE map_size, BOOL redraw) // calculate back buffer scale data->monitorScale = win10_monitor_scale(hWnd); - if (data->bAsciiMode || Is_rogue_level(&u.uz)) { + boolean bText = data->bAsciiMode || (u.uz.dlevel != 0 && Is_rogue_level(&u.uz)); + + if (bText && !data->bFitToScreenMode) data->backScale = data->monitorScale; - } else { + else data->backScale = 1.0; - } /* set back buffer tile size */ - data->xBackTile = (int) (data->tileWidth * data->backScale); - data->yBackTile = (int) (data->tileHeight * data->backScale); + if (bText && data->bFitToScreenMode) { + data->xBackTile = wnd_size.cx / COLNO; + data->yBackTile = wnd_size.cy / ROWNO; + data->yBackTile = max(data->yBackTile, 12); + } else { + data->xBackTile = (int)(data->tileWidth * data->backScale); + data->yBackTile = (int)(data->tileHeight * data->backScale); + } - if (data->bAsciiMode || Is_rogue_level(&u.uz)) { + if (bText) { LOGFONT lgfnt; ZeroMemory(&lgfnt, sizeof(lgfnt)); - lgfnt.lfHeight = -data->yBackTile; // height of font - lgfnt.lfWidth = -data->xBackTile; // average character width + lgfnt.lfHeight = -data->yBackTile; // height of font + lgfnt.lfWidth = 0; // average character width lgfnt.lfEscapement = 0; // angle of escapement lgfnt.lfOrientation = 0; // base-line orientation angle - lgfnt.lfWeight = FW_NORMAL; // font weight + lgfnt.lfWeight = FW_SEMIBOLD; // font weight +// lgfnt.lfWeight = FW_NORMAL; // font weight lgfnt.lfItalic = FALSE; // italic attribute option lgfnt.lfUnderline = FALSE; // underline attribute option lgfnt.lfStrikeOut = FALSE; // strikeout attribute option @@ -191,13 +199,18 @@ mswin_map_stretch(HWND hWnd, LPSIZE map_size, BOOL redraw) NH_A2W(iflags.wc_font_map, lgfnt.lfFaceName, LF_FACESIZE); } else { lgfnt.lfPitchAndFamily = FIXED_PITCH; // pitch and family - NH_A2W(NHMAP_FONT_NAME, lgfnt.lfFaceName, LF_FACESIZE); +// NH_A2W(NHMAP_FONT_NAME, lgfnt.lfFaceName, LF_FACESIZE); + NH_A2W("Courier New", lgfnt.lfFaceName, LF_FACESIZE); } TEXTMETRIC textMetrics; - HFONT font; + HFONT font = NULL; while (1) { + + if (font != NULL) + DeleteObject(font); + font = CreateFontIndirect(&lgfnt); SelectObject(data->backBufferDC, font); @@ -210,7 +223,7 @@ mswin_map_stretch(HWND hWnd, LPSIZE map_size, BOOL redraw) } if (textMetrics.tmAveCharWidth > data->xBackTile) { - lgfnt.lfWidth++; + lgfnt.lfHeight++; continue; } @@ -256,7 +269,7 @@ mswin_map_stretch(HWND hWnd, LPSIZE map_size, BOOL redraw) /* calculate front buffer tile size */ - if (wnd_size.cx > 0 && wnd_size.cy > 0 && data->bFitToScreenMode) { + if (wnd_size.cx > 0 && wnd_size.cy > 0 && !bText && data->bFitToScreenMode) { double windowAspectRatio = (double) wnd_size.cx / (double) wnd_size.cy; @@ -893,9 +906,22 @@ paintGlyph(PNHMapWindow data, int i, int j, RECT * rect) #endif if (data->bUnicodeFont) { wch = winos_ascii_to_wide(ch); - DrawTextW(data->backBufferDC, &wch, 1, rect, - DT_CENTER | DT_VCENTER | DT_NOPREFIX - | DT_SINGLELINE); + if (wch == 0x2591 || wch == 0x2592) { + int level = 80; + HBRUSH brush = CreateSolidBrush(RGB(level, level, level)); + FillRect(data->backBufferDC, rect, brush); + DeleteObject(brush); + level = (wch == 0x2591 ? 100 : 200); + brush = CreateSolidBrush(RGB(level, level, level)); + RECT smallRect = { rect->left + 1, rect->top + 1, + rect->right - 1, rect->bottom - 1 }; + FillRect(data->backBufferDC, &smallRect, brush); + DeleteObject(brush); + } else { + DrawTextW(data->backBufferDC, &wch, 1, rect, + DT_CENTER | DT_VCENTER | DT_NOPREFIX + | DT_SINGLELINE); + } } else { DrawTextA(data->backBufferDC, &ch, 1, rect, DT_CENTER | DT_VCENTER | DT_NOPREFIX From 88bbf781d146c022ecad1790b01e85bbb4ba0958 Mon Sep 17 00:00:00 2001 From: Bart House Date: Sun, 9 Dec 2018 11:57:50 -0800 Subject: [PATCH 13/21] Three fixes to NetHackW font handling. Check that player level is valid before checking if it is rogue. Prevent attempting to pick a font that is too small. Don't leak fonts when trying to find a font that fits. --- win/win32/mhfont.h | 3 +++ win/win32/mhmap.c | 21 +++++++++++++++------ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/win/win32/mhfont.h b/win/win32/mhfont.h index 20b5d1400..9402d54a9 100644 --- a/win/win32/mhfont.h +++ b/win/win32/mhfont.h @@ -9,6 +9,9 @@ #include "winMS.h" +#define MIN_FONT_WIDTH 9 +#define MIN_FONT_HEIGHT 12 + typedef struct cached_font { int code; HFONT hFont; diff --git a/win/win32/mhmap.c b/win/win32/mhmap.c index d401c4c3c..067d9a6e9 100644 --- a/win/win32/mhmap.c +++ b/win/win32/mhmap.c @@ -160,7 +160,10 @@ mswin_map_stretch(HWND hWnd, LPSIZE map_size, BOOL redraw) // calculate back buffer scale data->monitorScale = win10_monitor_scale(hWnd); - if (data->bAsciiMode || Is_rogue_level(&u.uz)) { + boolean bText = data->bAsciiMode || + (u.uz.dlevel != 0 && Is_rogue_level(&u.uz)); + + if (bText) { data->backScale = data->monitorScale; } else { data->backScale = 1.0; @@ -170,7 +173,7 @@ mswin_map_stretch(HWND hWnd, LPSIZE map_size, BOOL redraw) data->xBackTile = (int) (data->tileWidth * data->backScale); data->yBackTile = (int) (data->tileHeight * data->backScale); - if (data->bAsciiMode || Is_rogue_level(&u.uz)) { + if (bText) { LOGFONT lgfnt; ZeroMemory(&lgfnt, sizeof(lgfnt)); @@ -195,21 +198,27 @@ mswin_map_stretch(HWND hWnd, LPSIZE map_size, BOOL redraw) } TEXTMETRIC textMetrics; - HFONT font; + HFONT font = NULL; while (1) { + + if (font != NULL) + DeleteObject(font); + font = CreateFontIndirect(&lgfnt); SelectObject(data->backBufferDC, font); GetTextMetrics(data->backBufferDC, &textMetrics); - if (textMetrics.tmHeight > data->yBackTile) { + if (textMetrics.tmHeight > data->yBackTile && + lgfnt.lfHeight < -MIN_FONT_HEIGHT) { lgfnt.lfHeight++; continue; } - if (textMetrics.tmAveCharWidth > data->xBackTile) { + if (textMetrics.tmAveCharWidth > data->xBackTile && + lgfnt.lfWeight < -MIN_FONT_WIDTH) { lgfnt.lfWidth++; continue; } @@ -270,7 +279,7 @@ mswin_map_stretch(HWND hWnd, LPSIZE map_size, BOOL redraw) } else { - if (data->bAsciiMode || Is_rogue_level(&u.uz)) { + if (bText) { data->frontScale = 1.0; } else { data->frontScale = data->monitorScale; From 1aec267c0914278a3d65da399b4d847fa5057a4c Mon Sep 17 00:00:00 2001 From: Bart House Date: Sun, 9 Dec 2018 14:06:25 -0800 Subject: [PATCH 14/21] NetHackW default font changed from "Terminal" to "Courier New" --- win/win32/mhmap.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/win/win32/mhmap.c b/win/win32/mhmap.c index ba82b261a..75155a73f 100644 --- a/win/win32/mhmap.c +++ b/win/win32/mhmap.c @@ -15,7 +15,7 @@ #include "color.h" #include "patchlevel.h" -#define NHMAP_FONT_NAME TEXT("Terminal") +#define NHMAP_FONT_NAME TEXT("Courier New") #define MAXWINDOWTEXT 255 #define CURSOR_BLINK_INTERVAL 1000 // milliseconds @@ -187,7 +187,6 @@ mswin_map_stretch(HWND hWnd, LPSIZE map_size, BOOL redraw) lgfnt.lfEscapement = 0; // angle of escapement lgfnt.lfOrientation = 0; // base-line orientation angle lgfnt.lfWeight = FW_SEMIBOLD; // font weight -// lgfnt.lfWeight = FW_NORMAL; // font weight lgfnt.lfItalic = FALSE; // italic attribute option lgfnt.lfUnderline = FALSE; // underline attribute option lgfnt.lfStrikeOut = FALSE; // strikeout attribute option @@ -200,8 +199,7 @@ mswin_map_stretch(HWND hWnd, LPSIZE map_size, BOOL redraw) NH_A2W(iflags.wc_font_map, lgfnt.lfFaceName, LF_FACESIZE); } else { lgfnt.lfPitchAndFamily = FIXED_PITCH; // pitch and family -// NH_A2W(NHMAP_FONT_NAME, lgfnt.lfFaceName, LF_FACESIZE); - NH_A2W("Courier New", lgfnt.lfFaceName, LF_FACESIZE); + NH_A2W(NHMAP_FONT_NAME, lgfnt.lfFaceName, LF_FACESIZE); } TEXTMETRIC textMetrics; From 04d3be930bd97fd590136c4e313be227ccc48f6e Mon Sep 17 00:00:00 2001 From: Bart House Date: Sun, 9 Dec 2018 14:37:07 -0800 Subject: [PATCH 15/21] Changes to font size and vary_msgcount options for Windows nethack ports. --- sys/winnt/defaults.nh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sys/winnt/defaults.nh b/sys/winnt/defaults.nh index 8c9994284..39b7924cf 100644 --- a/sys/winnt/defaults.nh +++ b/sys/winnt/defaults.nh @@ -108,16 +108,16 @@ OPTIONS=suppress_alert:3.3.1 OPTIONS=map_mode:tiles,scroll_margin:10 # Message window settings -OPTIONS=font_message:Arial,font_size_message:9,align_message:top +OPTIONS=font_message:Arial,font_size_message:14,align_message:top # Menu settings -OPTIONS=font_menu:Arial,font_size_menu:9 +OPTIONS=font_menu:Arial,font_size_menu:14 # Text settings -OPTIONS=font_text:Courier New,font_size_text:9 +OPTIONS=font_text:Courier New,font_size_text:14 # Status window settings -OPTIONS=font_status:Courier New,font_size_status:9 +OPTIONS=font_status:Courier New,font_size_status:14 # Other OPTIONS=hilite_pet,!toptenwin @@ -136,7 +136,7 @@ OPTIONS=hilite_pet,!toptenwin # "Nethack mode" colors OPTIONS=windowcolors:status white/#000000 message white/#000000 text white/#000000 menu white/#000000 menutext white/#000000 -OPTIONS=vary_msgcount:1 +OPTIONS=vary_msgcount:4 # *** LOCATIONS *** # IMPORTANT: If you change any of these locations, the directories they From fe1b27e7741553c7d9d17333e924c75ad77c2db9 Mon Sep 17 00:00:00 2001 From: PatR Date: Sun, 9 Dec 2018 15:03:13 -0800 Subject: [PATCH 16/21] fix #H7702 - named fruit warning: singular of null Some code added for 3.6.1 tries to find the longest matching prefix when comparing a user-supplied with previously set up fruit names. It does so by temporarily replacing space with NUL then passing that to makesingular(). After already having named a fruit (resulting in something to try to compare with), attempting to assign a name beginning with two or more spaces would yield an impossible "singular of null?" warning. After the warning, the name minus its leading spaces got successfully assigned. I'm not sure why a single leading space didn't trigger it too, nor where the leading (and trailing, if any) spaces are going away when the name is assigned. Fix by removing all leading and trailing spaces from a new fruit name, and combine consecutive internal spaces to one, before any other manipulations. (This can result in names that used to work as-is now being simplified a bit--when consecutive internal spaces have been given--but that shouldn't be a problem.) Also, don't complain about "missing parameter for 'fruit:'" if user hits when prompted for fruit name by 'O'. An empty fruit name at that stage is just a no-op. --- doc/fixes36.2 | 8 +++++--- src/options.c | 17 +++++++++++------ 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/doc/fixes36.2 b/doc/fixes36.2 index ac5e5af87..7cd1f75f1 100644 --- a/doc/fixes36.2 +++ b/doc/fixes36.2 @@ -252,12 +252,14 @@ hero hit by something that causes inventory items to be destroyed with loss of similar problem with more obvious symptom, an "object lost" panic when the unholy water was wielded; the fix for that wasn't general enough] add MM_ASLEEP makemon() flag and honor it when creating group for fill_zoo -at start of session (new game or restore), HILITE_STATUS for gold was ignored -if player creates any menu colors via 'O' while menucolors is off, issue a - reminder that it needs to be on in order for those to become effective add MM_NOGRP makemon() flag as a means of suppressing groups of monsters in a couple places that warrant it when a specific monster type isn't specified on the call to makemon() +at start of session (new game or restore), HILITE_STATUS for gold was ignored +if player creates any menu colors via 'O' while menucolors is off, issue a + reminder that it needs to be on in order for those to become effective +setting second or later named fruit to value beginning with two or more spaces + followed by non-space gave "singular of null?" warning Fixes to Post-3.6.1 Problems that Were Exposed Via git Repository diff --git a/src/options.c b/src/options.c index b3595a6ad..1bf7f7024 100644 --- a/src/options.c +++ b/src/options.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 options.c $NHDT-Date: 1544174413 2018/12/07 09:20:13 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.339 $ */ +/* NetHack 3.6 options.c $NHDT-Date: 1544396581 2018/12/09 23:03:01 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.340 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Michael Allison, 2008. */ /* NetHack may be freely redistributed. See license for details. */ @@ -883,6 +883,8 @@ initoptions_finish() return; } +/* copy up to maxlen-1 characters; 'dest' must be able to hold maxlen; + treat comma as alternate end of 'src' */ STATIC_OVL void nmcpy(dest, src, maxlen) char *dest; @@ -896,7 +898,7 @@ int maxlen; break; /*exit on \0 terminator*/ *dest++ = *src++; } - *dest = 0; + *dest = '\0'; } /* @@ -2583,7 +2585,7 @@ boolean tinitial, tfrom_file; if (duplicate) complain_about_duplicate(opts, 1); - op = string_for_opt(opts, negated); + op = string_for_opt(opts, negated || !initial); if (negated) { if (op) { bad_negation("fruit", TRUE); @@ -2594,6 +2596,8 @@ boolean tinitial, tfrom_file; } if (!op) return FALSE; + /* 3.6.2: strip leading and trailing spaces, condense internal ones */ + mungspaces(op); if (!initial) { struct fruit *f; int fnum = 0; @@ -4465,7 +4469,7 @@ doset() /* changing options via menu by Per Liboriussen */ /* boolean option */ Sprintf(buf, "%s%s", *boolopt[opt_indx].addr ? "!" : "", boolopt[opt_indx].name); - parseoptions(buf, setinitial, fromfile); + (void) parseoptions(buf, setinitial, fromfile); if (wc_supported(boolopt[opt_indx].name) || wc2_supported(boolopt[opt_indx].name)) preference_update(boolopt[opt_indx].name); @@ -4481,7 +4485,7 @@ doset() /* changing options via menu by Per Liboriussen */ continue; Sprintf(buf, "%s:%s", compopt[opt_indx].name, buf2); /* pass the buck */ - parseoptions(buf, setinitial, fromfile); + (void) parseoptions(buf, setinitial, fromfile); } if (wc_supported(compopt[opt_indx].name) || wc2_supported(compopt[opt_indx].name)) @@ -4639,7 +4643,8 @@ boolean setinitial, setfromfile; destroy_nhwindow(tmpwin); } else if (!strcmp("pickup_types", optname)) { /* parseoptions will prompt for the list of types */ - parseoptions(strcpy(buf, "pickup_types"), setinitial, setfromfile); + (void) parseoptions(strcpy(buf, "pickup_types"), + setinitial, setfromfile); } else if (!strcmp("disclose", optname)) { /* order of disclose_names[] must correspond to disclosure_options in decl.c */ From b40868a74fd4b0da78a1a9f88433df4127275450 Mon Sep 17 00:00:00 2001 From: PatR Date: Sun, 9 Dec 2018 16:22:27 -0800 Subject: [PATCH 17/21] fix #H7708 - change in terrain not noticed Jumping or teleporting while levitating in xorn form wouldn't toggle blocking of levitation when moving from open spots to wall/stone and unblocking of same when moving the opposite way. This handles those cases but there are no doubt others. The only other one I checked was when failed #untrap moves hero onto trap. That case works correctly--at least after this fix is in place. Noticed while working on it: change of terrain didn't always update the status line. When levitation became blocked, it still said Lev and when unblocked, didn't say that. Next status update got status condition back in sync. --- doc/fixes36.2 | 6 ++++++ include/extern.h | 3 ++- src/dothrow.c | 7 ++++++- src/hack.c | 13 ++++++++----- src/teleport.c | 7 ++++++- 5 files changed, 28 insertions(+), 8 deletions(-) diff --git a/doc/fixes36.2 b/doc/fixes36.2 index 7cd1f75f1..ae20cf33c 100644 --- a/doc/fixes36.2 +++ b/doc/fixes36.2 @@ -260,6 +260,12 @@ if player creates any menu colors via 'O' while menucolors is off, issue a reminder that it needs to be on in order for those to become effective setting second or later named fruit to value beginning with two or more spaces followed by non-space gave "singular of null?" warning +when blocking/unblocking of levitation or flying was updated due to walking + onto different terrain, the relevant status condition wasn't updated + on the screen until some other status update happened +if levitating hero poly'd into pass-wall creature jumped or teleported from + terrain that allowed levitation to terrain that didn't or vice versa, + blocking of levitation wasn't updated properly Fixes to Post-3.6.1 Problems that Were Exposed Via git Repository diff --git a/include/extern.h b/include/extern.h index 4f1c8d6fa..81b792aa9 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1,4 +1,4 @@ -/* NetHack 3.6 extern.h $NHDT-Date: 1543892214 2018/12/04 02:56:54 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.665 $ */ +/* NetHack 3.6 extern.h $NHDT-Date: 1544401264 2018/12/10 00:21:04 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.666 $ */ /* Copyright (c) Steve Creps, 1988. */ /* NetHack may be freely redistributed. See license for details. */ @@ -854,6 +854,7 @@ E boolean NDECL(u_rooted); E void NDECL(domove); E boolean NDECL(overexertion); E void NDECL(invocation_message); +E void NDECL(switch_terrain); E boolean FDECL(pooleffects, (BOOLEAN_P)); E void FDECL(spoteffects, (BOOLEAN_P)); E char *FDECL(in_rooms, (XCHAR_P, XCHAR_P, int)); diff --git a/src/dothrow.c b/src/dothrow.c index e55c9b7d6..48220a4fb 100644 --- a/src/dothrow.c +++ b/src/dothrow.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 dothrow.c $NHDT-Date: 1543892215 2018/12/04 02:56:55 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.152 $ */ +/* NetHack 3.6 dothrow.c $NHDT-Date: 1544401268 2018/12/10 00:21:08 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.153 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2013. */ /* NetHack may be freely redistributed. See license for details. */ @@ -707,6 +707,11 @@ int x, y; newsym(ox, oy); /* update old position */ vision_recalc(1); /* update for new position */ flush_screen(1); + /* if terrain type changes, levitation or flying might become blocked + or unblocked; might issue message, so do this after map+vision has + been updated for new location instead of right after u_on_newpos() */ + if (levl[u.ux][u.uy].typ != levl[ox][oy].typ) + switch_terrain(); if (is_pool(x, y) && !u.uinwater) { if ((Is_waterlevel(&u.uz) && levl[x][y].typ == WATER) diff --git a/src/hack.c b/src/hack.c index c0c0313f2..362a4c78a 100644 --- a/src/hack.c +++ b/src/hack.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 hack.c $NHDT-Date: 1543972190 2018/12/05 01:09:50 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.200 $ */ +/* NetHack 3.6 hack.c $NHDT-Date: 1544401269 2018/12/10 00:21:09 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.201 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Derek S. Ray, 2015. */ /* NetHack may be freely redistributed. See license for details. */ @@ -13,7 +13,6 @@ STATIC_DCL int FDECL(still_chewing, (XCHAR_P, XCHAR_P)); STATIC_DCL void NDECL(dosinkfall); STATIC_DCL boolean FDECL(findtravelpath, (int)); STATIC_DCL boolean FDECL(trapmove, (int, int, struct trap *)); -STATIC_DCL void NDECL(switch_terrain); STATIC_DCL struct monst *FDECL(monstinroom, (struct permonst *, int)); STATIC_DCL boolean FDECL(doorless_door, (int, int)); STATIC_DCL void FDECL(move_update, (BOOLEAN_P)); @@ -1935,12 +1934,13 @@ invocation_message() /* moving onto different terrain; might be going into solid rock, inhibiting levitation or flight, or coming back out of such, reinstating levitation/flying */ -STATIC_OVL void +void switch_terrain() { struct rm *lev = &levl[u.ux][u.uy]; boolean blocklev = (IS_ROCK(lev->typ) || closed_door(u.ux, u.uy) - || (Is_waterlevel(&u.uz) && lev->typ == WATER)); + || (Is_waterlevel(&u.uz) && lev->typ == WATER)), + was_levitating = !!Levitation, was_flying = !!Flying; if (blocklev) { /* called from spoteffects(), stop levitating but skip float_down() */ @@ -1968,6 +1968,8 @@ switch_terrain() if (Flying) You("start flying."); } + if ((!Levitation ^ was_levitating) || (!Flying ^ was_flying)) + context.botl = TRUE; /* update Lev/Fly status condition */ } /* extracted from spoteffects; called by spoteffects to check for entering or @@ -2828,12 +2830,13 @@ const char *msg_override; else if (!nomovemsg) nomovemsg = You_can_move_again; if (*nomovemsg) - pline1(nomovemsg); + pline("%s", nomovemsg); nomovemsg = 0; u.usleep = 0; multi_reason = NULL; if (afternmv) { int NDECL((*f)) = afternmv; + /* clear afternmv before calling it (to override the encumbrance hack for levitation--see weight_cap()) */ afternmv = (int NDECL((*))) 0; diff --git a/src/teleport.c b/src/teleport.c index a7901e3d9..9aedc0c3e 100644 --- a/src/teleport.c +++ b/src/teleport.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 teleport.c $NHDT-Date: 1523306912 2018/04/09 20:48:32 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.73 $ */ +/* NetHack 3.6 teleport.c $NHDT-Date: 1544401270 2018/12/10 00:21:10 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.81 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2011. */ /* NetHack may be freely redistributed. See license for details. */ @@ -340,6 +340,11 @@ boolean allow_drag; vision_full_recalc = 1; nomul(0); vision_recalc(0); /* vision before effects */ + /* if terrain type changes, levitation or flying might become blocked + or unblocked; might issue message, so do this after map+vision has + been updated for new location instead of right after u_on_newpos() */ + if (levl[u.ux][u.uy].typ != levl[u.ux0][u.uy0].typ) + switch_terrain(); if (telescroll) { /* when teleporting by scroll, we need to handle discovery now before getting feedback about any objects at our From 56dc7e150c472af9ab7c616460205b60b3e74c5c Mon Sep 17 00:00:00 2001 From: nhmall Date: Mon, 10 Dec 2018 00:44:18 -0500 Subject: [PATCH 18/21] allow a deferred windowport init during options processing When options processing encountered OPTIONS=windowtype:X, the code would immediately attempt to switch over to that windowtype right in the midst of options processing. This stores the chosen option into chosen_window[WINTYPELEN] thus allowing the startup code to choose it after options processing has been completed. --- include/flag.h | 7 ++ src/options.c | 11 ++- sys/winnt/windmain.c | 188 +++++++++++++++++-------------------------- 3 files changed, 86 insertions(+), 120 deletions(-) diff --git a/include/flag.h b/include/flag.h index a459c5bb9..6a8ce3da2 100644 --- a/include/flag.h +++ b/include/flag.h @@ -221,6 +221,10 @@ enum getloc_filters { NUM_GFILTER }; +/* max size of a windowtype option */ +#define WINTYPELEN 16 +char chosen_windowtype[WINTYPELEN]; + struct debug_flags { boolean test; #ifdef TTY_GRAPHICS @@ -445,6 +449,9 @@ struct instance_flags { short soko_prize_type2; /* amulet of reflection */ struct debug_flags debug; boolean windowtype_locked; /* windowtype can't change from configfile */ + boolean windowtype_deferred; /* pick a windowport and store it in + chosen_windowport[], but do not switch to + it in the midst of options processing */ }; /* diff --git a/src/options.c b/src/options.c index 9dafa31bf..922acce12 100644 --- a/src/options.c +++ b/src/options.c @@ -20,7 +20,6 @@ NEARDATA struct instance_flags iflags; /* provide linkage */ #endif #define BACKWARD_COMPAT -#define WINTYPELEN 16 #ifdef DEFAULT_WC_TILED_MAP #define PREFER_TILED TRUE @@ -3519,10 +3518,14 @@ boolean tinitial, tfrom_file; bad_negation(fullname, FALSE); return FALSE; } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) { - char buf[WINTYPELEN]; + if (!iflags.windowtype_deferred) { + char buf[WINTYPELEN]; - nmcpy(buf, op, WINTYPELEN); - choose_windows(buf); + nmcpy(buf, op, WINTYPELEN); + choose_windows(buf); + } else { + nmcpy(chosen_windowtype, op, WINTYPELEN); + } } else return FALSE; return retval; diff --git a/sys/winnt/windmain.c b/sys/winnt/windmain.c index 6b4b0491c..d8b7c8056 100644 --- a/sys/winnt/windmain.c +++ b/sys/winnt/windmain.c @@ -22,6 +22,7 @@ char *NDECL(exename); boolean NDECL(fakeconsole); void NDECL(freefakeconsole); E void FDECL(nethack_exit, (int)); +E char chosen_windowtype[WINTYPELEN]; /* flag.h */ #if defined(MSWIN_GRAPHICS) E void NDECL(mswin_destroy_reg); #endif @@ -36,6 +37,7 @@ void FDECL(windows_getlin, (const char *, char *)); extern int NDECL(windows_console_custom_nhgetch); char orgdir[PATHLEN]; +char *dir; boolean getreturn_enabled; extern int redirect_stdout; /* from sys/share/pcsys.c */ extern int GUILaunched; @@ -60,8 +62,8 @@ int argc; char *argv[]; { boolean resuming = FALSE; /* assume new game */ - register int fd; - register char *dir; + int fd; + char *windowtype = NULL; char *envp = NULL; char *sptr = NULL; char fnamebuf[BUFSZ], encodedfnamebuf[BUFSZ]; @@ -205,8 +207,10 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/ if (GUILaunched || IsDebuggerPresent()) { getreturn_enabled = TRUE; } + check_recordfile((char *) 0); - initoptions(); + iflags.windowtype_deferred = TRUE; + initoptions(); if (!validate_prefix_locations(failbuf)) { raw_printf("Some invalid directory locations were specified:\n\t%s\n", failbuf); @@ -214,119 +218,18 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/ } if (!hackdir[0]) Strcpy(hackdir, orgdir); - if (argc > 1) { - if (argcheck(argc, argv, ARG_VERSION) == 2) - nethack_exit(EXIT_SUCCESS); - - if (argcheck(argc, argv, ARG_DEBUG) == 1) { - argc--; - argv++; - } - if (argcheck(argc, argv, ARG_WINDOWS) == 1) { - argc--; - argv++; - } - if (argc > 1 && !strncmp(argv[1], "-d", 2) && argv[1][2] != 'e') { - /* avoid matching "-dec" for DECgraphics; since the man page - * says -d directory, hope nobody's using -desomething_else - */ - argc--; - argv++; - dir = argv[0] + 2; - if (*dir == '=' || *dir == ':') - dir++; - if (!*dir && argc > 1) { - argc--; - argv++; - dir = argv[0]; - } - if (!*dir) - error("Flag -d must be followed by a directory name."); - Strcpy(hackdir, dir); - } - if (argc > 1) { -#if 0 -#if !defined(TTY_GRAPHICS) - int sfd = 0; - boolean tmpconsole = FALSE; - hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); -#endif -#endif /* 0 */ - - /* - * Now we know the directory containing 'record' and - * may do a prscore(). - */ - if (!strncmp(argv[1], "-s", 2)) { -#if 0 -#if !defined(TTY_GRAPHICS) - /* - * Check to see if we're redirecting to a file. - */ - sfd = (int) _fileno(stdout); - redirect_stdout = (sfd >= 0) ? !isatty(sfd) : 0; - - if (!redirect_stdout && !hStdOut) { - raw_printf( - "-s is not supported for the Graphical Interface\n"); - nethack_exit(EXIT_SUCCESS); - } -#endif -#endif /* 0 */ -#ifdef SYSCF - initoptions(); -#endif - prscore(argc, argv); - -#if 0 -#if !defined(TTY_GRAPHICS) - if (tmpconsole) { - getreturn("to exit"); - freefakeconsole(); - tmpconsole = FALSE; - } -#endif -#endif /* 0 */ - nethack_exit(EXIT_SUCCESS); - } - if (GUILaunched) { - if (!strncmpi(argv[1], "-clearreg", 6)) { /* clear registry */ - mswin_destroy_reg(); - nethack_exit(EXIT_SUCCESS); - } - } - /* Don't initialize the full window system just to print usage */ - if (!strncmp(argv[1], "-?", 2) || !strncmp(argv[1], "/?", 2)) { - nhusage(); -#if 0 -#if !defined(TTY_GRAPHICS) - if (tmpconsole) { - getreturn("to exit"); - freefakeconsole(); - tmpconsole = FALSE; - } -#endif -#endif - nethack_exit(EXIT_SUCCESS); - } - } - } - + process_options(argc, argv); + /* * It seems you really want to play. */ - /* In 3.6.0, several ports process options before they init - * the window port. This allows settings that impact window - * ports to be specified or read from the sys or user config files. - */ - process_options(argc, argv); - if (argc >= 1 && !strcmpi(default_window_sys, "mswin") && (strstri(argv[0], "nethackw.exe") || GUILaunched)) iflags.windowtype_locked = TRUE; + windowtype = default_window_sys; if (!iflags.windowtype_locked) { #if defined(TTY_GRAPHICS) Strcpy(default_window_sys, "tty"); @@ -335,9 +238,11 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/ Strcpy(default_window_sys, "curses"); #endif /* CURSES */ #endif /* TTY */ + if (iflags.windowtype_deferred && chosen_windowtype[0]) + windowtype = chosen_windowtype; } + choose_windows(windowtype); - choose_windows(default_window_sys); if (!dlb_init()) { pline( "%s\n%s\n%s\n%s\n\nNetHack was unable to open the required file " @@ -459,6 +364,63 @@ char *argv[]; /* * Process options. */ + if (argc > 1) { + if (argcheck(argc, argv, ARG_VERSION) == 2) + nethack_exit(EXIT_SUCCESS); + + if (argcheck(argc, argv, ARG_DEBUG) == 1) { + argc--; + argv++; + } + if (argcheck(argc, argv, ARG_WINDOWS) == 1) { + argc--; + argv++; + } + if (argc > 1 && !strncmp(argv[1], "-d", 2) && argv[1][2] != 'e') { + /* avoid matching "-dec" for DECgraphics; since the man page + * says -d directory, hope nobody's using -desomething_else + */ + argc--; + argv++; + dir = argv[0] + 2; + if (*dir == '=' || *dir == ':') + dir++; + if (!*dir && argc > 1) { + argc--; + argv++; + dir = argv[0]; + } + if (!*dir) + error("Flag -d must be followed by a directory name."); + Strcpy(hackdir, dir); + } + + if (argc > 1) { + /* + * Now we know the directory containing 'record' and + * may do a prscore(). + */ + if (!strncmp(argv[1], "-s", 2)) { +#ifdef SYSCF + initoptions(); +#endif + prscore(argc, argv); + + nethack_exit(EXIT_SUCCESS); + } + if (GUILaunched) { + if (!strncmpi(argv[1], "-clearreg", 6)) { /* clear registry */ + mswin_destroy_reg(); + nethack_exit(EXIT_SUCCESS); + } + } + /* Don't initialize the full window system just to print usage */ + if (!strncmp(argv[1], "-?", 2) || !strncmp(argv[1], "/?", 2)) { + nhusage(); + nethack_exit(EXIT_SUCCESS); + } + } + } while (argc > 1 && argv[1][0] == '-') { argv++; argc--; @@ -528,18 +490,12 @@ char *argv[]; flags.initrace = i; } break; -#if 0 case 'w': /* windowtype */ -#if defined(TTY_GRAPHICS) - if (!strncmpi(&argv[0][2], "tty", 3)) { - nttty_open(1); - } -#endif config_error_init(FALSE, "command line", FALSE); - choose_windows(&argv[0][2]); + if (strlen(&argv[0][2]) < (WINTYPELEN - 1)) + Strcpy(chosen_windowtype, &argv[0][2]); config_error_done(); break; -#endif case '@': flags.randomall = 1; break; From d6800663435123024393f872b5d4df206cced979 Mon Sep 17 00:00:00 2001 From: PatR Date: Mon, 10 Dec 2018 02:21:31 -0800 Subject: [PATCH 19/21] fix #H7704 - clairvoyance: objects vs pools When clairvoyance revealed an underwater object and the player wasn't being given a chance to browse for some other reason, the map didn't get refreshed and the object stayed displayed with the water hidden under it. Force a chance to browse when revealing underwater objects despite that being intrusive when clairvoyance kicks in while walking around. --- doc/fixes36.2 | 2 ++ src/detect.c | 11 ++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/doc/fixes36.2 b/doc/fixes36.2 index ae20cf33c..9e6b004bb 100644 --- a/doc/fixes36.2 +++ b/doc/fixes36.2 @@ -266,6 +266,8 @@ when blocking/unblocking of levitation or flying was updated due to walking if levitating hero poly'd into pass-wall creature jumped or teleported from terrain that allowed levitation to terrain that didn't or vice versa, blocking of levitation wasn't updated properly +clairvoyance revealing underwater or under-lava objects left object displayed + instead of restoring the water or lava Fixes to Post-3.6.1 Problems that Were Exposed Via git Repository diff --git a/src/detect.c b/src/detect.c index 416c2611f..e6c5778af 100644 --- a/src/detect.c +++ b/src/detect.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 detect.c $NHDT-Date: 1542853884 2018/11/22 02:31:24 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.87 $ */ +/* NetHack 3.6 detect.c $NHDT-Date: 1544437284 2018/12/10 10:21:24 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.91 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2018. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1308,7 +1308,8 @@ struct obj *sobj; /* scroll--actually fake spellbook--object */ struct obj *otmp; long save_EDetect_mons; char save_viz_uyux; - boolean unconstrained, refresh = FALSE, mdetected = FALSE, + boolean unconstrained, refresh = FALSE, + mdetected = FALSE, odetected = FALSE, /* fake spellbook 'sobj' implies hero has cast the spell; when book is blessed, casting is skilled or expert level; if already clairvoyant, non-skilled spell acts like skilled */ @@ -1363,6 +1364,10 @@ struct obj *sobj; /* scroll--actually fake spellbook--object */ if (extended) otmp->dknown = 1; map_object(otmp, TRUE); + newglyph = glyph_at(zx, zy); + /* if otmp is underwater, we'll need to redisplay the water */ + if (newglyph != oldglyph && covers_objects(zx, zy)) + odetected = TRUE; } /* if there is a monster here, see or detect it, possibly as "remembered, unseen monster" */ @@ -1385,7 +1390,7 @@ struct obj *sobj; /* scroll--actually fake spellbook--object */ } } - if (!level.flags.hero_memory || unconstrained || mdetected) { + if (!level.flags.hero_memory || unconstrained || mdetected || odetected) { flush_screen(1); /* flush temp screen */ /* the getpos() prompt from browse_map() is only shown when flags.verbose is set, but make this unconditional so that From 9c422f2c1f4f450c7f8b67c9fa3a6aaa00a58db4 Mon Sep 17 00:00:00 2001 From: PatR Date: Mon, 10 Dec 2018 03:52:00 -0800 Subject: [PATCH 20/21] fix #H7707 - terrain change leaving stale flags struct rm.flags in overloaded for a bunch of rm.typ -dependent things (doormask, altarmask, throne/fountain/sink looted, a few others) and wasn't being reset for various cases where rm.typ gets changed. I've changed a lot, some no doubt unnecessarily, and probably missed plenty. This compiles but has not been thoroughly tested. --- src/apply.c | 6 ++--- src/dig.c | 72 +++++++++++++++++++++++++------------------------- src/do.c | 13 ++++++--- src/fountain.c | 15 +++++------ src/lock.c | 4 +-- src/monmove.c | 3 ++- src/music.c | 4 +-- src/sit.c | 4 +-- src/zap.c | 15 +++++------ 9 files changed, 71 insertions(+), 65 deletions(-) diff --git a/src/apply.c b/src/apply.c index d202acc77..edb3940e6 100644 --- a/src/apply.c +++ b/src/apply.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 apply.c $NHDT-Date: 1542765339 2018/11/21 01:55:39 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.254 $ */ +/* NetHack 3.6 apply.c $NHDT-Date: 1544442708 2018/12/10 11:51:48 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.269 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -418,7 +418,7 @@ register struct obj *obj; return res; case SCORR: You_hear(hollow_str, "passage"); - lev->typ = CORR; + lev->typ = CORR, lev->flags = 0; unblock_point(rx, ry); feel_newsym(rx, ry); return res; @@ -3394,7 +3394,7 @@ struct obj *obj; */ typ = fillholetyp(x, y, FALSE); if (typ != ROOM) { - levl[x][y].typ = typ; + levl[x][y].typ = typ, levl[x][y].flags = 0; liquid_flow(x, y, typ, t_at(x, y), fillmsg ? (char *) 0 diff --git a/src/dig.c b/src/dig.c index 3f5e74bc0..29d0941d4 100644 --- a/src/dig.c +++ b/src/dig.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 dig.c $NHDT-Date: 1542765354 2018/11/21 01:55:54 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.115 $ */ +/* NetHack 3.6 dig.c $NHDT-Date: 1544442710 2018/12/10 11:51:50 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.116 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Michael Allison, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -81,7 +81,7 @@ boolean waslit, rockit; lev->horizontal = FALSE; /* short-circuit vision recalc */ viz_array[y][x] = (dist < 3) ? (IN_SIGHT | COULD_SEE) : COULD_SEE; - lev->typ = (rockit ? STONE : ROOM); + lev->typ = (rockit ? STONE : ROOM); /* flags set via doormask above */ if (dist >= 3) impossible("mkcavepos called with dist %d", dist); feel_newsym(x, y); @@ -129,7 +129,7 @@ register boolean rockit; } if (!rockit && levl[u.ux][u.uy].typ == CORR) { - levl[u.ux][u.uy].typ = ROOM; + levl[u.ux][u.uy].typ = ROOM; /* flags for CORR already 0 */ if (waslit) levl[u.ux][u.uy].waslit = TRUE; newsym(u.ux, u.uy); /* in case player is invisible */ @@ -361,9 +361,9 @@ dig(VOID_ARGS) } if (context.digging.effort > 100) { - register const char *digtxt, *dmgtxt = (const char *) 0; - register struct obj *obj; - register boolean shopedge = *in_rooms(dpx, dpy, SHOPBASE); + const char *digtxt, *dmgtxt = (const char *) 0; + struct obj *obj; + boolean shopedge = *in_rooms(dpx, dpy, SHOPBASE); if ((obj = sobj_at(STATUE, dpx, dpy)) != 0) { if (break_statue(obj)) @@ -397,12 +397,12 @@ dig(VOID_ARGS) } if (IS_TREE(lev->typ)) { digtxt = "You cut down the tree."; - lev->typ = ROOM; + lev->typ = ROOM, lev->flags = 0; if (!rn2(5)) (void) rnd_treefruit_at(dpx, dpy); } else { digtxt = "You succeed in cutting away some rock."; - lev->typ = CORR; + lev->typ = CORR, lev->flags = 0; } } else if (IS_WALL(lev->typ)) { if (shopedge) { @@ -410,12 +410,11 @@ dig(VOID_ARGS) dmgtxt = "damage"; } if (level.flags.is_maze_lev) { - lev->typ = ROOM; + lev->typ = ROOM, lev->flags = 0; } else if (level.flags.is_cavernous_lev && !in_town(dpx, dpy)) { - lev->typ = CORR; + lev->typ = CORR, lev->flags = 0; } else { - lev->typ = DOOR; - lev->doormask = D_NODOOR; + lev->typ = DOOR, lev->doormask = D_NODOOR; } digtxt = "You make an opening in the wall."; } else if (lev->typ == SDOOR) { @@ -573,6 +572,7 @@ int ttyp; } else if (lev->typ == DRAWBRIDGE_DOWN || (is_drawbridge_wall(x, y) >= 0)) { int bx = x, by = y; + /* if under the portcullis, the bridge is adjacent */ (void) find_drawbridge(&bx, &by); destroy_drawbridge(bx, by); @@ -853,6 +853,7 @@ coord *cc; } else { typ = fillholetyp(dig_x, dig_y, FALSE); + lev->flags = 0; if (typ != ROOM) { lev->typ = typ; liquid_flow(dig_x, dig_y, typ, ttmp, @@ -935,7 +936,7 @@ coord *cc; pline_The("grave seems unused. Strange...."); break; } - levl[dig_x][dig_y].typ = ROOM; + levl[dig_x][dig_y].typ = ROOM, levl[dig_x][dig_y].flags = 0; del_engr_at(dig_x, dig_y); newsym(dig_x, dig_y); return; @@ -1272,7 +1273,7 @@ register struct monst *mtmp; newsym(mtmp->mx, mtmp->my); return FALSE; } else if (here->typ == SCORR) { - here->typ = CORR; + here->typ = CORR, here->flags = 0; unblock_point(mtmp->mx, mtmp->my); newsym(mtmp->mx, mtmp->my); draft_message(FALSE); /* "You feel a draft." */ @@ -1297,20 +1298,19 @@ register struct monst *mtmp; if (*in_rooms(mtmp->mx, mtmp->my, SHOPBASE)) add_damage(mtmp->mx, mtmp->my, 0L); if (level.flags.is_maze_lev) { - here->typ = ROOM; + here->typ = ROOM, here->flags = 0; } else if (level.flags.is_cavernous_lev && !in_town(mtmp->mx, mtmp->my)) { - here->typ = CORR; + here->typ = CORR, here->flags = 0; } else { - here->typ = DOOR; - here->doormask = D_NODOOR; + here->typ = DOOR, here->doormask = D_NODOOR; } } else if (IS_TREE(here->typ)) { - here->typ = ROOM; + here->typ = ROOM, here->flags = 0; if (pile && pile < 5) (void) rnd_treefruit_at(mtmp->mx, mtmp->my); } else { - here->typ = CORR; + here->typ = CORR, here->flags = 0; if (pile && pile < 5) (void) mksobj_at((pile == 1) ? BOULDER : ROCK, mtmp->mx, mtmp->my, TRUE, FALSE); @@ -1495,7 +1495,7 @@ zap_dig() shopdoor = TRUE; } if (room->typ == SDOOR) - room->typ = DOOR; + room->typ = DOOR; /* doormask set below */ else if (cansee(zx, zy)) pline_The("door is razed!"); watch_dig((struct monst *) 0, zx, zy, TRUE); @@ -1511,21 +1511,21 @@ zap_dig() add_damage(zx, zy, SHOP_WALL_COST); shopwall = TRUE; } - room->typ = ROOM; + room->typ = ROOM, room->flags = 0; unblock_point(zx, zy); /* vision */ } else if (!Blind) pline_The("wall glows then fades."); break; } else if (IS_TREE(room->typ)) { /* check trees before stone */ if (!(room->wall_info & W_NONDIGGABLE)) { - room->typ = ROOM; + room->typ = ROOM, room->flags = 0; unblock_point(zx, zy); /* vision */ } else if (!Blind) pline_The("tree shudders but is unharmed."); break; } else if (room->typ == STONE || room->typ == SCORR) { if (!(room->wall_info & W_NONDIGGABLE)) { - room->typ = CORR; + room->typ = CORR, room->flags = 0; unblock_point(zx, zy); /* vision */ } else if (!Blind) pline_The("rock glows then fades."); @@ -1541,17 +1541,16 @@ zap_dig() } watch_dig((struct monst *) 0, zx, zy, TRUE); if (level.flags.is_cavernous_lev && !in_town(zx, zy)) { - room->typ = CORR; + room->typ = CORR, room->flags = 0; } else { - room->typ = DOOR; - room->doormask = D_NODOOR; + room->typ = DOOR, room->doormask = D_NODOOR; } digdepth -= 2; } else if (IS_TREE(room->typ)) { - room->typ = ROOM; + room->typ = ROOM, room->flags = 0; digdepth -= 2; } else { /* IS_ROCK but not IS_WALL or SDOOR */ - room->typ = CORR; + room->typ = CORR, room->flags = 0; digdepth--; } unblock_point(zx, zy); /* vision */ @@ -1563,8 +1562,10 @@ zap_dig() if (pitflow && isok(flow_x, flow_y)) { struct trap *ttmp = t_at(flow_x, flow_y); + if (ttmp && is_pit(ttmp->ttyp)) { schar filltyp = fillholetyp(ttmp->tx, ttmp->ty, TRUE); + if (filltyp != ROOM) pit_flow(ttmp, filltyp); } @@ -1589,7 +1590,7 @@ char *msg; int ltyp; struct rm *room; const char *foundation_msg = - "The foundation is too hard to dig through from this angle."; + "The foundation is too hard to dig through from this angle."; if (!cc) return FALSE; @@ -1597,7 +1598,7 @@ char *msg; return FALSE; *msg = '\0'; room = &levl[cc->x][cc->y]; - ltyp = room->typ; + ltyp = room->typ, room->flags = 0; if (is_pool(cc->x, cc->y) || is_lava(cc->x, cc->y)) { /* this is handled by the caller after we return FALSE */ @@ -1677,15 +1678,14 @@ pit_flow(trap, filltyp) struct trap *trap; schar filltyp; { - if (trap && (filltyp != ROOM) - && is_pit(trap->ttyp)) { + if (trap && filltyp != ROOM && is_pit(trap->ttyp)) { struct trap t; int idx; t = *trap; - levl[trap->tx][trap->ty].typ = filltyp; - liquid_flow(trap->tx, trap->ty, filltyp, trap, - (trap->tx == u.ux && trap->ty == u.uy) + levl[t.tx][t.ty].typ = filltyp, levl[t.tx][t.ty].flags = 0; + liquid_flow(t.tx, t.ty, filltyp, trap, + (t.tx == u.ux && t.ty == u.uy) ? "Suddenly %s flows in from the adjacent pit!" : (char *) 0); for (idx = 0; idx < 8; ++idx) { diff --git a/src/do.c b/src/do.c index febfcf9b5..87cbe86c4 100644 --- a/src/do.c +++ b/src/do.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 do.c $NHDT-Date: 1543972190 2018/12/05 01:09:50 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.176 $ */ +/* NetHack 3.6 do.c $NHDT-Date: 1544442710 2018/12/10 11:51:50 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.177 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Derek S. Ray, 2015. */ /* NetHack may be freely redistributed. See license for details. */ @@ -67,7 +67,7 @@ boolean pushing; levl[rx][ry].drawbridgemask &= ~DB_UNDER; /* clear lava */ levl[rx][ry].drawbridgemask |= DB_FLOOR; } else - levl[rx][ry].typ = ROOM; + levl[rx][ry].typ = ROOM, levl[rx][ry].flags = 0; if (ttmp) (void) delfloortrap(ttmp); @@ -276,22 +276,29 @@ STATIC_DCL void polymorph_sink() { uchar sym = S_sink; + boolean sinklooted; if (levl[u.ux][u.uy].typ != SINK) return; + sinklooted = levl[u.ux][u.uy].looted != 0; level.flags.nsinks--; - levl[u.ux][u.uy].doormask = 0; + levl[u.ux][u.uy].doormask = 0; /* levl[][].flags */ switch (rn2(4)) { default: case 0: sym = S_fountain; levl[u.ux][u.uy].typ = FOUNTAIN; + levl[u.ux][u.uy].blessedftn = 0; + if (sinklooted) + SET_FOUNTAIN_LOOTED(u.ux, u.uy); level.flags.nfountains++; break; case 1: sym = S_throne; levl[u.ux][u.uy].typ = THRONE; + if (sinklooted) + levl[u.ux][u.uy].looted = T_LOOTED; break; case 2: sym = S_altar; diff --git a/src/fountain.c b/src/fountain.c index 616d42b47..57e914559 100644 --- a/src/fountain.c +++ b/src/fountain.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 fountain.c $NHDT-Date: 1455402364 2016/02/13 22:26:04 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.56 $ */ +/* NetHack 3.6 fountain.c $NHDT-Date: 1544442711 2018/12/10 11:51:51 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.60 $ */ /* Copyright Scott R. Turner, srt@ucla, 10/27/86 */ /* NetHack may be freely redistributed. See license for details. */ @@ -137,7 +137,7 @@ genericptr_t poolcnt; pline("Water gushes forth from the overflowing fountain!"); /* Put a pool at x, y */ - levl[x][y].typ = POOL; + levl[x][y].typ = POOL, levl[x][y].flags = 0; /* No kelp! */ del_engr_at(x, y); water_damage_chain(level.objects[x][y], TRUE); @@ -205,8 +205,7 @@ boolean isyou; return; } /* replace the fountain with ordinary floor */ - levl[x][y].typ = ROOM; - levl[x][y].looted = 0; + levl[x][y].typ = ROOM, levl[x][y].flags = 0; levl[x][y].blessedftn = 0; if (cansee(x, y)) pline_The("fountain dries up!"); @@ -397,8 +396,7 @@ register struct obj *obj; exercise(A_WIS, TRUE); } update_inventory(); - levl[u.ux][u.uy].typ = ROOM; - levl[u.ux][u.uy].looted = 0; + levl[u.ux][u.uy].typ = ROOM, levl[u.ux][u.uy].flags = 0; newsym(u.ux, u.uy); level.flags.nfountains--; if (in_town(u.ux, u.uy)) @@ -511,8 +509,9 @@ int x, y; if (cansee(x, y) || (x == u.ux && y == u.uy)) pline_The("pipes break! Water spurts out!"); level.flags.nsinks--; - levl[x][y].doormask = 0; - levl[x][y].typ = FOUNTAIN; + levl[x][y].typ = FOUNTAIN, levl[x][y].looted = 0; + levl[x][y].blessedftn = 0; + SET_FOUNTAIN_LOOTED(x, y); level.flags.nfountains++; newsym(x, y); } diff --git a/src/lock.c b/src/lock.c index 067eb6c99..5c52532b9 100644 --- a/src/lock.c +++ b/src/lock.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 lock.c $NHDT-Date: 1521499715 2018/03/19 22:48:35 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.80 $ */ +/* NetHack 3.6 lock.c $NHDT-Date: 1544442712 2018/12/10 11:51:52 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.82 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2011. */ /* NetHack may be freely redistributed. See license for details. */ @@ -950,7 +950,7 @@ int x, y; return FALSE; } block_point(x, y); - door->typ = SDOOR; + door->typ = SDOOR, door->doormask = D_NODOOR; if (vis) pline_The("doorway vanishes!"); newsym(x, y); diff --git a/src/monmove.c b/src/monmove.c index c501cf421..fbc2d419d 100644 --- a/src/monmove.c +++ b/src/monmove.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 monmove.c $NHDT-Date: 1517877380 2018/02/06 00:36:20 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.96 $ */ +/* NetHack 3.6 monmove.c $NHDT-Date: 1544442712 2018/12/10 11:51:52 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.109 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Michael Allison, 2006. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1474,6 +1474,7 @@ dissolve_bars(x, y) register int x, y; { levl[x][y].typ = (Is_special(&u.uz) || *in_rooms(x, y, 0)) ? ROOM : CORR; + levl[x][y].flags = 0; newsym(x, y); } diff --git a/src/music.c b/src/music.c index 6b5d3330f..bcaae3f83 100644 --- a/src/music.c +++ b/src/music.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 music.c $NHDT-Date: 1542765361 2018/11/21 01:56:01 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.56 $ */ +/* NetHack 3.6 music.c $NHDT-Date: 1544442713 2018/12/10 11:51:53 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.57 $ */ /* Copyright (c) 1989 by Jean-Christophe Collet */ /* NetHack may be freely redistributed. See license for details. */ @@ -320,7 +320,7 @@ int force; */ filltype = fillholetyp(x, y, FALSE); if (filltype != ROOM) { - levl[x][y].typ = filltype; + levl[x][y].typ = filltype; /* flags set via doormask */ liquid_flow(x, y, filltype, chasm, (char *) 0); } diff --git a/src/sit.c b/src/sit.c index 1aa8085bf..5f85bb13e 100644 --- a/src/sit.c +++ b/src/sit.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 sit.c $NHDT-Date: 1458341129 2016/03/18 22:45:29 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.53 $ */ +/* NetHack 3.6 sit.c $NHDT-Date: 1544442714 2018/12/10 11:51:54 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.59 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -281,7 +281,7 @@ dosit() if (!rn2(3) && IS_THRONE(levl[u.ux][u.uy].typ)) { /* may have teleported */ - levl[u.ux][u.uy].typ = ROOM; + levl[u.ux][u.uy].typ = ROOM, levl[u.ux][u.uy].flags = 0; pline_The("throne vanishes in a puff of logic."); newsym(u.ux, u.uy); } diff --git a/src/zap.c b/src/zap.c index 1e6e3b1b3..6907880e4 100644 --- a/src/zap.c +++ b/src/zap.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 zap.c $NHDT-Date: 1544230271 2018/12/08 00:51:11 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.301 $ */ +/* NetHack 3.6 zap.c $NHDT-Date: 1544442714 2018/12/10 11:51:54 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.302 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2013. */ /* NetHack may be freely redistributed. See license for details. */ @@ -4374,7 +4374,7 @@ short exploding_wand_typ; msgtxt = "Some water evaporates."; } else { rangemod -= 3; - lev->typ = ROOM; + lev->typ = ROOM, lev->flags = 0; t = maketrap(x, y, PIT); if (t) t->tseen = 1; @@ -4413,9 +4413,9 @@ short exploding_wand_typ; lev->drawbridgemask &= ~DB_UNDER; /* clear lava */ lev->drawbridgemask |= (lava ? DB_FLOOR : DB_ICE); } else { - if (!lava) - lev->icedpool = (lev->typ == POOL) ? ICED_POOL - : ICED_MOAT; + lev->icedpool = lava ? 0 + : (lev->typ == POOL) ? ICED_POOL + : ICED_MOAT; lev->typ = lava ? ROOM : ICE; } bury_objs(x, y); @@ -4490,15 +4490,14 @@ short exploding_wand_typ; Norep("The %s melt.", defsyms[S_bars].explanation); if (*in_rooms(x, y, SHOPBASE)) { /* in case we ever have a shop bounded by bars */ - lev->typ = ROOM; + lev->typ = ROOM, lev->flags = 0; if (see_it) newsym(x, y); add_damage(x, y, (type >= 0) ? SHOP_BARS_COST : 0L); if (type >= 0) *shopdamage = TRUE; } else { - lev->typ = DOOR; - lev->doormask = D_NODOOR; + lev->typ = DOOR, lev->doormask = D_NODOOR; if (see_it) newsym(x, y); } From 3837df12215696ab4d0acbd6b51c43318ce6177c Mon Sep 17 00:00:00 2001 From: nhmall Date: Mon, 10 Dec 2018 09:00:50 -0500 Subject: [PATCH 21/21] Qt build --- include/decl.h | 4 ++++ include/flag.h | 4 ---- src/decl.c | 1 + 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/include/decl.h b/include/decl.h index 992e86ad5..c93091a73 100644 --- a/include/decl.h +++ b/include/decl.h @@ -25,6 +25,10 @@ E char SAVEF[]; E char SAVEP[]; #endif +/* max size of a windowtype option */ +#define WINTYPELEN 16 +E char chosen_windowtype[WINTYPELEN]; + E NEARDATA int bases[MAXOCLASSES]; E NEARDATA int multi; diff --git a/include/flag.h b/include/flag.h index 6a8ce3da2..1306356c4 100644 --- a/include/flag.h +++ b/include/flag.h @@ -221,10 +221,6 @@ enum getloc_filters { NUM_GFILTER }; -/* max size of a windowtype option */ -#define WINTYPELEN 16 -char chosen_windowtype[WINTYPELEN]; - struct debug_flags { boolean test; #ifdef TTY_GRAPHICS diff --git a/src/decl.c b/src/decl.c index ffd9ef974..e9ab7fcb5 100644 --- a/src/decl.c +++ b/src/decl.c @@ -17,6 +17,7 @@ int locknum = 0; /* max num of simultaneous users */ #ifdef DEF_PAGER char *catmore = 0; /* default pager */ #endif +char chosen_windowtype[WINTYPELEN]; NEARDATA int bases[MAXOCLASSES] = DUMMY;