Merge branch 'win-minor' into NetHack-3.6.2-beta01

This commit is contained in:
nhmall
2018-12-10 00:50:01 -05:00
18 changed files with 1559 additions and 334 deletions

View File

@@ -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 */
};
/*

View File

@@ -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 */

View File

@@ -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

View File

@@ -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
@@ -873,11 +872,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;
@@ -3518,10 +3522,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;

View File

@@ -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';

View File

@@ -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 <Return> %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 */

View File

@@ -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)
#==========================================
@@ -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.
@@ -1511,8 +1510,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 \
$(MSWSYS)\win32api.h
$(O)pcmain.o: ..\sys\share\pcmain.c $(HACK_H) $(INCL)\dlb.h
@$(CC) $(cflagsBuild) -Fo$@ ..\sys\share\pcmain.c
$(O)pcsys.o: ..\sys\share\pcsys.c $(HACK_H)
@$(CC) $(cflagsBuild) -Fo$@ ..\sys\share\pcsys.c

View File

@@ -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

View File

@@ -96,13 +96,11 @@ clear_screen()
return;
}
#ifdef TTY_GRAPHICS
void
backsp()
{
return;
}
#endif
int
has_color(int color)

724
sys/winnt/windmain.c Normal file
View File

@@ -0,0 +1,724 @@
/* 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 <ctype.h>
#include <sys\stat.h>
#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));
E char chosen_windowtype[WINTYPELEN]; /* flag.h */
#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 *));
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;
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 resuming = FALSE; /* assume new game */
int fd;
char *windowtype = NULL;
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);
if (!GUILaunched)
windowprocs.win_nhgetch = windows_console_custom_nhgetch;
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]);
}
}
}
if (GUILaunched || IsDebuggerPresent()) {
getreturn_enabled = TRUE;
}
check_recordfile((char *) 0);
iflags.windowtype_deferred = TRUE;
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);
process_options(argc, argv);
/*
* It seems you really want to play.
*/
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");
#else
#if defined(CURSES_GRAPHICS)
Strcpy(default_window_sys, "curses");
#endif /* CURSES */
#endif /* TTY */
if (iflags.windowtype_deferred && chosen_windowtype[0])
windowtype = chosen_windowtype;
}
choose_windows(windowtype);
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();
/*
* 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.
*/
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--;
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;
case 'w': /* windowtype */
config_error_init(FALSE, "command line", FALSE);
if (strlen(&argv[0][2]) < (WINTYPELEN - 1))
Strcpy(chosen_windowtype, &argv[0][2]);
config_error_done();
break;
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*/

View File

@@ -43,10 +43,17 @@ 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);
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.
@@ -492,12 +499,58 @@ void nhassert_failed(const char * exp, const char * file, int line)
error(message);
}
/* nethack_enter_winnt() is the first thing called from main */
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.
*/
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 <conio.h>
int
windows_console_custom_nhgetch(VOID_ARGS)
{
return _getch();
}
void
getreturn(str)
const char *str;
{
char buf[BUFSZ];
if (!getreturn_enabled)
return;
Sprintf(buf,"Hit <Enter> %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()
{
#ifdef TTY_GRAPHICS
nethack_enter_nttty();
#endif
if (WINDOWPORT("tty"))
nethack_enter_nttty();
}
/* CP437 to Unicode mapping according to the Unicode Consortium */

561
win/share/safeproc.c Normal file
View File

@@ -0,0 +1,561 @@
/* NetHack 3.6 safeproc.c */
/* Copyright (c) Michael Allison, 2018 */
/* NetHack may be freely redistributed. See license for details. */
#include "hack.h"
#include <stdio.h>
/*
* ***********************************************************
* 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(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).
*
* ***********************************************************
*/
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, 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 */

View File

@@ -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;

View File

@@ -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
@@ -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.lfItalic = FALSE; // italic attribute option
lgfnt.lfUnderline = FALSE; // underline attribute option
lgfnt.lfStrikeOut = FALSE; // strikeout attribute option
@@ -195,25 +203,26 @@ 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 ||
textMetrics.tmAveCharWidth > data->xBackTile) &&
lgfnt.lfHeight < -MIN_FONT_HEIGHT) {
lgfnt.lfHeight++;
continue;
}
if (textMetrics.tmAveCharWidth > data->xBackTile) {
lgfnt.lfWidth++;
continue;
}
break;
}
@@ -256,7 +265,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;
@@ -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;
@@ -893,9 +902,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

View File

@@ -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. */

View File

@@ -34,7 +34,7 @@
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<OmitFramePointers>true</OmitFramePointers>
<AdditionalIncludeDirectories>$(WinWin32Dir);$(IncDir);$(SysWinntDir);$(SysShareDir);$(WinShareDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>TILES;WIN32CON;DLB;MSWIN_GRAPHICS;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>TILES;WIN32CON;DLB;MSWIN_GRAPHICS;SAFEPROCS;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<AdditionalDependencies>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)</AdditionalDependencies>
@@ -151,7 +151,6 @@
<ClCompile Include="$(SrcDir)zap.c" />
<ClCompile Include="$(SysShareDir)cppregex.cpp" />
<ClCompile Include="$(SysShareDir)nhlan.c" />
<ClCompile Include="$(SysShareDir)pcmain.c" />
<ClCompile Include="$(SysShareDir)pcsys.c" />
<ClCompile Include="$(SysShareDir)pcunix.c" />
<ClCompile Include="$(SysShareDir)random.c" />
@@ -160,7 +159,9 @@
<ClCompile Include="$(SysWinntDir)stubs.c">
<PreprocessorDefinitions>GUISTUB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<ClCompile Include="$(SysWinntDir)windmain.c" />
<ClCompile Include="$(SysWinntDir)winnt.c" />
<ClCompile Include="$(WinShareDir)safeproc.c" />
<ClCompile Include="$(WinTtyDir)getline.c" />
<ClCompile Include="$(WinTtyDir)topl.c" />
<ClCompile Include="$(WinTtyDir)wintty.c" />
@@ -254,4 +255,4 @@
<Target Name="AfterRebuild">
<MSBuild Projects="afternethack.proj" Targets="Build" Properties="Configuration=$(Configuration)" />
</Target>
</Project>
</Project>

View File

@@ -20,7 +20,7 @@
<Optimization>Disabled</Optimization>
<OmitFramePointers>true</OmitFramePointers>
<AdditionalIncludeDirectories>$(WinWin32Dir);$(IncDir);$(SysWinntDir);$(SysShareDir);$(WinShareDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>TILES;_WINDOWS;DLB;MSWIN_GRAPHICS;NOTTYGRAPHICS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>TILES;_WINDOWS;DLB;MSWIN_GRAPHICS;SAFEPROCS;NOTTYGRAPHICS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
@@ -146,7 +146,6 @@
<ClCompile Include="$(SrcDir)zap.c" />
<ClCompile Include="$(SysShareDir)cppregex.cpp" />
<ClCompile Include="$(SysShareDir)nhlan.c" />
<ClCompile Include="$(SysShareDir)pcmain.c" />
<ClCompile Include="$(SysShareDir)pcsys.c" />
<ClCompile Include="$(SysShareDir)pcunix.c" />
<ClCompile Include="$(SysShareDir)random.c" />
@@ -154,8 +153,10 @@
<ClCompile Include="$(SysWinntDir)stubs.c">
<PreprocessorDefinitions>TTYSTUB;</PreprocessorDefinitions>
</ClCompile>
<ClCompile Include="$(SysWinntDir)windmain.c" />
<ClCompile Include="$(SysWinntDir)winnt.c" />
<ClCompile Include="$(SysWinntDir)win10.c" />
<ClCompile Include="$(WinShareDir)safeproc.c" />
<ClCompile Include="$(WinWin32Dir)mhaskyn.c" />
<ClCompile Include="$(WinWin32Dir)mhdlg.c" />
<ClCompile Include="$(WinWin32Dir)mhfont.c" />
@@ -200,4 +201,4 @@
<Target Name="AfterRebuild">
<MSBuild Projects="afternethack.proj" Targets="Build" Properties="Configuration=$(Configuration)" />
</Target>
</Project>
</Project>

View File

@@ -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 {
@@ -59,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)
@@ -66,7 +72,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 +88,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 +235,9 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
}
free(savefile);
}
resuming = pcmain(argc, argv);
moveloop(resuming);
GUILaunched = 1;
/* let main do the argument processing */
(void) main(argc, argv);
return 0;
}