OSDN Git Service

patch aligns
[jnethack/source.git] / sys / share / pcmain.c
1 /* NetHack 3.6  pcmain.c        $NHDT-Date: 1449116336 2015/12/03 04:18:56 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.66 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed.  See license for details. */
4
5 /* main.c - MSDOS, OS/2, ST, Amiga, and Windows NetHack */
6
7 #include "hack.h"
8 #include "dlb.h"
9
10 #ifndef NO_SIGNAL
11 #include <signal.h>
12 #endif
13
14 #include <ctype.h>
15
16 #if !defined(AMIGA) && !defined(GNUDOS)
17 #include <sys\stat.h>
18 #else
19 #ifdef GNUDOS
20 #include <sys/stat.h>
21 #endif
22 #endif
23
24 #ifdef WIN32
25 #include "win32api.h" /* for GetModuleFileName */
26 #endif
27
28 #ifdef __DJGPP__
29 #include <unistd.h> /* for getcwd() prototype */
30 #endif
31
32 char orgdir[PATHLEN]; /* also used in pcsys.c, amidos.c */
33
34 #ifdef TOS
35 boolean run_from_desktop = TRUE; /* should we pause before exiting?? */
36 #ifdef __GNUC__
37 long _stksize = 16 * 1024;
38 #endif
39 #endif
40
41 #ifdef AMIGA
42 extern int bigscreen;
43 void NDECL(preserve_icon);
44 #endif
45
46 STATIC_DCL void FDECL(process_options, (int argc, char **argv));
47 STATIC_DCL void NDECL(nhusage);
48
49 #if defined(MICRO) || defined(WIN32) || defined(OS2)
50 extern void FDECL(nethack_exit, (int));
51 #else
52 #define nethack_exit exit
53 #endif
54
55 #ifdef WIN32
56 extern boolean getreturn_enabled; /* from sys/share/pcsys.c */
57 extern int redirect_stdout;       /* from sys/share/pcsys.c */
58 char *NDECL(exename);
59 char default_window_sys[] = "mswin";
60 #endif
61
62 #if defined(MSWIN_GRAPHICS)
63 extern void NDECL(mswin_destroy_reg);
64 #endif
65
66 #ifdef EXEPATH
67 STATIC_DCL char *FDECL(exepath, (char *));
68 #endif
69
70 int FDECL(main, (int, char **));
71
72 extern boolean FDECL(pcmain, (int, char **));
73
74 #if defined(__BORLANDC__) && !defined(_WIN32)
75 void NDECL(startup);
76 unsigned _stklen = STKSIZ;
77 #endif
78
79 /* If the graphics version is built, we don't need a main; it is skipped
80  * to help MinGW decide which entry point to choose. If both main and
81  * WinMain exist, the resulting executable won't work correctly.
82  */
83 #ifndef __MINGW32__
84 int
85 main(argc, argv)
86 int argc;
87 char *argv[];
88 {
89     boolean resuming;
90
91     sys_early_init();
92 #ifdef WIN32
93     Strcpy(default_window_sys, "tty");
94 #endif
95
96     resuming = pcmain(argc, argv);
97 #ifdef LAN_FEATURES
98     init_lan_features();
99 #endif
100     moveloop(resuming);
101     nethack_exit(EXIT_SUCCESS);
102     /*NOTREACHED*/
103     return 0;
104 }
105 #endif
106
107 boolean
108 pcmain(argc, argv)
109 int argc;
110 char *argv[];
111 {
112     register int fd;
113     register char *dir;
114 #if defined(WIN32)
115     char *envp = NULL;
116     char *sptr = NULL;
117     char fnamebuf[BUFSZ], encodedfnamebuf[BUFSZ];
118     boolean save_getreturn_status = getreturn_enabled;
119 #endif
120 #ifdef NOCWD_ASSUMPTIONS
121     char failbuf[BUFSZ];
122 #endif
123     boolean resuming = FALSE; /* assume new game */
124
125 #ifdef _MSC_VER
126 # ifdef DEBUG
127     /* set these appropriately for VS debugging */
128     _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG);
129     _CrtSetReportMode(_CRT_ERROR,
130                       _CRTDBG_MODE_DEBUG); /* | _CRTDBG_MODE_FILE);*/
131     _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);
132 /*| _CRTDBG_MODE_FILE | _CRTDBG_MODE_WNDW);*/
133 /* use STDERR by default
134 _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
135 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/
136 # endif
137 #endif
138
139 #if defined(__BORLANDC__) && !defined(_WIN32)
140     startup();
141 #endif
142
143 #ifdef TOS
144     long clock_time;
145     if (*argv[0]) { /* only a CLI can give us argv[0] */
146         hname = argv[0];
147         run_from_desktop = FALSE;
148     } else
149 #endif
150         hname = "NetHack"; /* used for syntax messages */
151
152 #ifndef WIN32
153     choose_windows(DEFAULT_WINDOW_SYS);
154 #else
155     choose_windows(default_window_sys);
156 #endif
157
158 #if !defined(AMIGA) && !defined(GNUDOS)
159     /* Save current directory and make sure it gets restored when
160      * the game is exited.
161      */
162     if (getcwd(orgdir, sizeof orgdir) == (char *) 0)
163         error("NetHack: current directory path too long");
164 #ifndef NO_SIGNAL
165     signal(SIGINT,
166            (SIG_RET_TYPE) nethack_exit); /* restore original directory */
167 #endif
168 #endif /* !AMIGA && !GNUDOS */
169
170     dir = nh_getenv("NETHACKDIR");
171     if (dir == (char *) 0)
172         dir = nh_getenv("HACKDIR");
173 #ifdef EXEPATH
174     if (dir == (char *) 0)
175         dir = exepath(argv[0]);
176 #endif
177     if (dir != (char *) 0) {
178         (void) strncpy(hackdir, dir, PATHLEN - 1);
179         hackdir[PATHLEN - 1] = '\0';
180 #ifdef NOCWD_ASSUMPTIONS
181         {
182             int prefcnt;
183
184             fqn_prefix[0] = (char *) alloc(strlen(hackdir) + 2);
185             Strcpy(fqn_prefix[0], hackdir);
186             append_slash(fqn_prefix[0]);
187             for (prefcnt = 1; prefcnt < PREFIX_COUNT; prefcnt++)
188                 fqn_prefix[prefcnt] = fqn_prefix[0];
189
190 #if defined(WIN32) || defined(MSDOS)
191             /* sysconf should be searched for in this location */
192             envp = nh_getenv("COMMONPROGRAMFILES");
193             if (envp) {
194                 if ((sptr = index(envp, ';')) != 0)
195                     *sptr = '\0';
196                 if (strlen(envp) > 0) {
197                     fqn_prefix[SYSCONFPREFIX] =
198                         (char *) alloc(strlen(envp) + 10);
199                     Strcpy(fqn_prefix[SYSCONFPREFIX], envp);
200                     append_slash(fqn_prefix[SYSCONFPREFIX]);
201                     Strcat(fqn_prefix[SYSCONFPREFIX], "NetHack\\");
202                 }
203             }
204
205             /* user's home directory should default to this - unless
206              * overridden */
207             envp = nh_getenv("USERPROFILE");
208             if (envp) {
209                 if ((sptr = index(envp, ';')) != 0)
210                     *sptr = '\0';
211                 if (strlen(envp) > 0) {
212                     fqn_prefix[CONFIGPREFIX] =
213                         (char *) alloc(strlen(envp) + 2);
214                     Strcpy(fqn_prefix[CONFIGPREFIX], envp);
215                     append_slash(fqn_prefix[CONFIGPREFIX]);
216                 }
217             }
218 #endif
219         }
220 #endif
221 #if defined(CHDIR) && !defined(NOCWD_ASSUMPTIONS)
222         chdirx(dir, 1);
223 #endif
224     }
225 #ifdef AMIGA
226 #ifdef CHDIR
227     /*
228      * If we're dealing with workbench, change the directory.  Otherwise
229      * we could get "Insert disk in drive 0" messages. (Must be done
230      * before initoptions())....
231      */
232     if (argc == 0)
233         chdirx(HACKDIR, 1);
234 #endif
235     ami_wininit_data();
236 #endif
237 #ifdef WIN32
238     save_getreturn_status = getreturn_enabled;
239     raw_clear_screen();
240     getreturn_enabled = TRUE;
241 #endif
242     initoptions();
243
244 #ifdef NOCWD_ASSUMPTIONS
245     if (!validate_prefix_locations(failbuf)) {
246         raw_printf("Some invalid directory locations were specified:\n\t%s\n",
247                    failbuf);
248         nethack_exit(EXIT_FAILURE);
249     }
250 #endif
251
252 #if defined(TOS) && defined(TEXTCOLOR)
253     if (iflags.BIOS && iflags.use_color)
254         set_colors();
255 #endif
256     if (!hackdir[0])
257 #if !defined(LATTICE) && !defined(AMIGA)
258         Strcpy(hackdir, orgdir);
259 #else
260         Strcpy(hackdir, HACKDIR);
261 #endif
262     if (argc > 1) {
263         if (!strncmp(argv[1], "-d", 2) && argv[1][2] != 'e') {
264             /* avoid matching "-dec" for DECgraphics; since the man page
265              * says -d directory, hope nobody's using -desomething_else
266              */
267             argc--;
268             argv++;
269             dir = argv[0] + 2;
270             if (*dir == '=' || *dir == ':')
271                 dir++;
272             if (!*dir && argc > 1) {
273                 argc--;
274                 argv++;
275                 dir = argv[0];
276             }
277             if (!*dir)
278                 error("Flag -d must be followed by a directory name.");
279             Strcpy(hackdir, dir);
280         }
281         if (argc > 1) {
282             /*
283              * Now we know the directory containing 'record' and
284              * may do a prscore().
285              */
286             if (!strncmp(argv[1], "-s", 2)) {
287 #if defined(WIN32)
288                 int sfd = (int) _fileno(stdout);
289                 redirect_stdout = (sfd >= 0) ? !isatty(sfd) : 0;
290
291                 if (!redirect_stdout) {
292                     raw_printf(
293                         "-s is not supported for the Graphical Interface\n");
294                     nethack_exit(EXIT_SUCCESS);
295                 }
296 #endif
297
298 #if defined(CHDIR) && !defined(NOCWD_ASSUMPTIONS)
299                 chdirx(hackdir, 0);
300 #endif
301 #ifdef SYSCF
302                 initoptions();
303 #endif
304                 prscore(argc, argv);
305                 nethack_exit(EXIT_SUCCESS);
306             }
307
308 #ifdef MSWIN_GRAPHICS
309             if (!strncmpi(argv[1], "-clearreg", 6)) { /* clear registry */
310                 mswin_destroy_reg();
311                 nethack_exit(EXIT_SUCCESS);
312             }
313 #endif
314             /* Don't initialize the window system just to print usage */
315             if (!strncmp(argv[1], "-?", 2) || !strncmp(argv[1], "/?", 2)) {
316                 nhusage();
317                 nethack_exit(EXIT_SUCCESS);
318             }
319         }
320     }
321
322 #ifdef WIN32
323     getreturn_enabled = save_getreturn_status;
324 #endif
325 /*
326  * It seems you really want to play.
327  */
328 #ifdef TOS
329     if (comp_times((long) time(&clock_time)))
330         error("Your clock is incorrectly set!");
331 #endif
332     if (!dlb_init()) {
333         pline(
334             "%s\n%s\n%s\n%s\n\nNetHack was unable to open the required file "
335             "\"%s\".%s",
336             copyright_banner_line(1), copyright_banner_line(2),
337             copyright_banner_line(3), copyright_banner_line(4), DLBFILE,
338 #ifdef WIN32
339             "\nAre you perhaps trying to run NetHack within a zip utility?");
340 #else
341             "");
342 #endif
343         error("dlb_init failure.");
344     }
345
346     u.uhp = 1; /* prevent RIP on early quits */
347     u.ux = 0;  /* prevent flush_screen() */
348
349 /* chdir shouldn't be called before this point to keep the
350  * code parallel to other ports.
351  */
352 #if defined(CHDIR) && !defined(NOCWD_ASSUMPTIONS)
353     chdirx(hackdir, 1);
354 #endif
355
356 #if defined(MSDOS) || defined(WIN32)
357     /* In 3.6.0, several ports process options before they init
358      * the window port. This allows settings that impact window
359      * ports to be specified or read from the sys or user config files.
360      */
361     process_options(argc, argv);
362
363 #ifdef WIN32
364     /*
365         if (!strncmpi(windowprocs.name, "mswin", 5))
366             NHWinMainInit();
367         else
368     */
369     if (!strncmpi(windowprocs.name, "tty", 3)) {
370         iflags.use_background_glyph = FALSE;
371         nttty_open(1);
372     } else {
373         iflags.use_background_glyph = TRUE;
374     }
375 #endif
376 #endif
377
378 #if defined(MSDOS) || defined(WIN32)
379     /* Player didn't specify any symbol set so use IBM defaults */
380     if (!symset[PRIMARY].name) {
381         load_symset("IBMGraphics_2", PRIMARY);
382     }
383     if (!symset[ROGUESET].name) {
384         load_symset("RogueEpyx", ROGUESET);
385     }
386 #endif
387
388 #if defined(MSDOS) || defined(WIN32)
389     init_nhwindows(&argc, argv);
390 #else
391     init_nhwindows(&argc, argv);
392     process_options(argc, argv);
393 #endif
394
395 #ifdef WIN32
396     toggle_mouse_support(); /* must come after process_options */
397 #endif
398
399 #ifdef MFLOPPY
400     set_lock_and_bones();
401 #ifndef AMIGA
402     copybones(FROMPERM);
403 #endif
404 #endif
405
406     /* strip role,race,&c suffix; calls askname() if plname[] is empty
407        or holds a generic user name like "player" or "games" */
408     plnamesuffix();
409     set_playmode(); /* sets plname to "wizard" for wizard mode */
410 #if 0
411     /* unlike Unix where the game might be invoked with a script
412        which forces a particular character name for each player
413        using a shared account, we always allow player to rename
414        the character during role/race/&c selection */
415     iflags.renameallowed = TRUE;
416 #else
417     /* until the getlock code is resolved, override askname()'s
418        setting of renameallowed; when False, player_selection()
419        won't resent renaming as an option */
420     iflags.renameallowed = FALSE;
421 #endif
422
423 #if defined(PC_LOCKING)
424 /* 3.3.0 added this to support detection of multiple games
425  * under the same plname on the same machine in a windowed
426  * or multitasking environment.
427  *
428  * That allows user confirmation prior to overwriting the
429  * level files of a game in progress.
430  *
431  * Also prevents an aborted game's level files from being
432  * overwritten without confirmation when a user starts up
433  * another game with the same player name.
434  */
435 #if defined(WIN32)
436     /* Obtain the name of the logged on user and incorporate
437      * it into the name. */
438     Sprintf(fnamebuf, "%s-%s", get_username(0), plname);
439     (void) fname_encode(
440         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-.", '%',
441         fnamebuf, encodedfnamebuf, BUFSZ);
442     Sprintf(lock, "%s", encodedfnamebuf);
443     /* regularize(lock); */ /* we encode now, rather than substitute */
444 #else
445     Strcpy(lock, plname);
446     regularize(lock);
447 #endif
448     getlock();
449 #else        /* What follows is !PC_LOCKING */
450 #ifdef AMIGA /* We'll put the bones & levels in the user specified directory \
451                 -jhsa */
452     Strcat(lock, plname);
453     Strcat(lock, ".99");
454 #else
455 #ifndef MFLOPPY
456     /* I'm not sure what, if anything, is left here, but MFLOPPY has
457      * conflicts with set_lock_and_bones() in files.c.
458      */
459     Strcpy(lock, plname);
460     Strcat(lock, ".99");
461     regularize(lock); /* is this necessary? */
462                       /* not compatible with full path a la AMIGA */
463 #endif
464 #endif
465 #endif /* PC_LOCKING */
466
467     /* Set up level 0 file to keep the game state.
468      */
469     fd = create_levelfile(0, (char *) 0);
470     if (fd < 0) {
471         raw_print("Cannot create lock file");
472     } else {
473 #ifdef WIN32
474         hackpid = GetCurrentProcessId();
475 #else
476         hackpid = 1;
477 #endif
478         write(fd, (genericptr_t) &hackpid, sizeof(hackpid));
479         nhclose(fd);
480     }
481 #ifdef MFLOPPY
482     level_info[0].where = ACTIVE;
483 #endif
484
485     /*
486      *  Initialize the vision system.  This must be before mklev() on a
487      *  new game or before a level restore on a saved game.
488      */
489     vision_init();
490
491     display_gamewindows();
492 #ifdef WIN32
493     getreturn_enabled = TRUE;
494 #endif
495
496 /*
497  * First, try to find and restore a save file for specified character.
498  * We'll return here if new game player_selection() renames the hero.
499  */
500 attempt_restore:
501     if ((fd = restore_saved_game()) >= 0) {
502 #ifndef NO_SIGNAL
503         (void) signal(SIGINT, (SIG_RET_TYPE) done1);
504 #endif
505 #ifdef NEWS
506         if (iflags.news) {
507             display_file(NEWS, FALSE);
508             iflags.news = FALSE;
509         }
510 #endif
511 /*JP
512         pline("Restoring save file...");
513 */
514         pline("\83Z\81[\83u\83t\83@\83C\83\8b\82ð\95\9c\8c³\92\86\81D\81D\81D");
515         mark_synch(); /* flush output */
516
517         if (dorecover(fd)) {
518             resuming = TRUE; /* not starting new game */
519             if (discover)
520 /*JP
521                 You("are in non-scoring discovery mode.");
522 */
523                 pline("\94­\8c©\83\82\81[\83h\82Å\82Í\83X\83R\83A\82Í\82Ì\82ç\82È\82¢\82æ\81D");
524             if (discover || wizard) {
525 /*JP
526                 if (yn("Do you want to keep the save file?") == 'n')
527 */
528                 if (yn("\83Z\81[\83u\83t\83@\83C\83\8b\82ð\8ec\82µ\82Ä\82¨\82«\82Ü\82·\82©\81H") == 'n')
529                     (void) delete_savefile();
530                 else {
531                     nh_compress(fqname(SAVEF, SAVEPREFIX, 0));
532                 }
533             }
534         }
535     }
536
537     if (!resuming) {
538         /* new game:  start by choosing role, race, etc;
539            player might change the hero's name while doing that,
540            in which case we try to restore under the new name
541            and skip selection this time if that didn't succeed */
542         if (!iflags.renameinprogress) {
543             player_selection();
544             if (iflags.renameinprogress) {
545 /* player has renamed the hero while selecting role;
546    discard current lock file and create another for
547    the new character name */
548 #if 0 /* this needs to be reconciled with the getlock mess above... */
549             delete_levelfile(0); /* remove empty lock file */
550             getlock();
551 #endif
552                 goto attempt_restore;
553             }
554         }
555         newgame();
556         if (discover)
557 /*JP
558             You("are in non-scoring discovery mode.");
559 */
560             pline("\94­\8c©\83\82\81[\83h\82Å\82Í\83X\83R\83A\82Í\82Ì\82ç\82È\82¢\82æ\81D");
561     }
562
563 #ifndef NO_SIGNAL
564     (void) signal(SIGINT, SIG_IGN);
565 #endif
566 #ifdef OS2
567     gettty(); /* somehow ctrl-P gets turned back on during startup ... */
568 #endif
569     return resuming;
570 }
571
572 STATIC_OVL void
573 process_options(argc, argv)
574 int argc;
575 char *argv[];
576 {
577     int i;
578
579     /*
580      * Process options.
581      */
582     while (argc > 1 && argv[1][0] == '-') {
583         argv++;
584         argc--;
585         switch (argv[0][1]) {
586         case 'a':
587             if (argv[0][2]) {
588                 if ((i = str2align(&argv[0][2])) >= 0)
589                     flags.initalign = i;
590             } else if (argc > 1) {
591                 argc--;
592                 argv++;
593                 if ((i = str2align(argv[0])) >= 0)
594                     flags.initalign = i;
595             }
596             break;
597         case 'D':
598             wizard = TRUE, discover = FALSE;
599             break;
600         case 'X':
601             discover = TRUE, wizard = FALSE;
602             break;
603 #ifdef NEWS
604         case 'n':
605             iflags.news = FALSE;
606             break;
607 #endif
608         case 'u':
609             if (argv[0][2])
610                 (void) strncpy(plname, argv[0] + 2, sizeof(plname) - 1);
611             else if (argc > 1) {
612                 argc--;
613                 argv++;
614                 (void) strncpy(plname, argv[0], sizeof(plname) - 1);
615             } else
616                 raw_print("Player name expected after -u");
617             break;
618 #ifndef AMIGA
619         case 'I':
620         case 'i':
621             if (!strncmpi(argv[0] + 1, "IBM", 3)) {
622                 load_symset("IBMGraphics", PRIMARY);
623                 load_symset("RogueIBM", ROGUESET);
624                 switch_symbols(TRUE);
625             }
626             break;
627         /*      case 'D': */
628         case 'd':
629             if (!strncmpi(argv[0] + 1, "DEC", 3)) {
630                 load_symset("DECGraphics", PRIMARY);
631                 switch_symbols(TRUE);
632             }
633             break;
634 #endif
635         case 'g':
636             if (argv[0][2]) {
637                 if ((i = str2gend(&argv[0][2])) >= 0)
638                     flags.initgend = i;
639             } else if (argc > 1) {
640                 argc--;
641                 argv++;
642                 if ((i = str2gend(argv[0])) >= 0)
643                     flags.initgend = i;
644             }
645             break;
646         case 'p': /* profession (role) */
647             if (argv[0][2]) {
648                 if ((i = str2role(&argv[0][2])) >= 0)
649                     flags.initrole = i;
650             } else if (argc > 1) {
651                 argc--;
652                 argv++;
653                 if ((i = str2role(argv[0])) >= 0)
654                     flags.initrole = i;
655             }
656             break;
657         case 'r': /* race */
658             if (argv[0][2]) {
659                 if ((i = str2race(&argv[0][2])) >= 0)
660                     flags.initrace = i;
661             } else if (argc > 1) {
662                 argc--;
663                 argv++;
664                 if ((i = str2race(argv[0])) >= 0)
665                     flags.initrace = i;
666             }
667             break;
668 #ifdef MFLOPPY
669 #ifndef AMIGA
670         /* Player doesn't want to use a RAM disk
671          */
672         case 'R':
673             ramdisk = FALSE;
674             break;
675 #endif
676 #endif
677 #ifdef AMIGA
678         /* interlaced and non-interlaced screens */
679         case 'L':
680             bigscreen = 1;
681             break;
682         case 'l':
683             bigscreen = -1;
684             break;
685 #endif
686 #ifdef WIN32
687         case 'w': /* windowtype */
688             if (strncmpi(&argv[0][2], "tty", 3)) {
689                 nttty_open(1);
690             }
691             /*
692                         else {
693                             NHWinMainInit();
694                         }
695             */
696             choose_windows(&argv[0][2]);
697             break;
698 #endif
699         case '@':
700             flags.randomall = 1;
701             break;
702         default:
703             if ((i = str2role(&argv[0][1])) >= 0) {
704                 flags.initrole = i;
705                 break;
706             } else
707                 raw_printf("\nUnknown switch: %s", argv[0]);
708         /* FALL THROUGH */
709         case '?':
710             nhusage();
711             nethack_exit(EXIT_SUCCESS);
712         }
713     }
714 }
715
716 STATIC_OVL void
717 nhusage()
718 {
719     char buf1[BUFSZ], buf2[BUFSZ], *bufptr;
720
721     buf1[0] = '\0';
722     bufptr = buf1;
723
724 #define ADD_USAGE(s)                              \
725     if ((strlen(buf1) + strlen(s)) < (BUFSZ - 1)) \
726         Strcat(bufptr, s);
727
728     /* -role still works for those cases which aren't already taken, but
729      * is deprecated and will not be listed here.
730      */
731     (void) Sprintf(buf2, "\nUsage:\n%s [-d dir] -s [-r race] [-p profession] "
732                          "[maxrank] [name]...\n       or",
733                    hname);
734     ADD_USAGE(buf2);
735
736     (void) Sprintf(
737         buf2, "\n%s [-d dir] [-u name] [-r race] [-p profession] [-[DX]]",
738         hname);
739     ADD_USAGE(buf2);
740 #ifdef NEWS
741     ADD_USAGE(" [-n]");
742 #endif
743 #ifndef AMIGA
744     ADD_USAGE(" [-I] [-i] [-d]");
745 #endif
746 #ifdef MFLOPPY
747 #ifndef AMIGA
748     ADD_USAGE(" [-R]");
749 #endif
750 #endif
751 #ifdef AMIGA
752     ADD_USAGE(" [-[lL]]");
753 #endif
754     if (!iflags.window_inited)
755         raw_printf("%s\n", buf1);
756     else
757         (void) printf("%s\n", buf1);
758 #undef ADD_USAGE
759 }
760
761 #ifdef CHDIR
762 void
763 chdirx(dir, wr)
764 char *dir;
765 boolean wr;
766 {
767 #ifdef AMIGA
768     static char thisdir[] = "";
769 #else
770     static char thisdir[] = ".";
771 #endif
772     if (dir && chdir(dir) < 0) {
773         error("Cannot chdir to %s.", dir);
774     }
775
776 #ifndef AMIGA
777     /* Change the default drive as well.
778      */
779     chdrive(dir);
780 #endif
781
782     /* warn the player if we can't write the record file */
783     /* perhaps we should also test whether . is writable */
784     /* unfortunately the access system-call is worthless */
785     if (wr)
786         check_recordfile(dir ? dir : thisdir);
787 }
788 #endif /* CHDIR */
789
790 #ifdef PORT_HELP
791 #if defined(MSDOS) || defined(WIN32)
792 void
793 port_help()
794 {
795     /* display port specific help file */
796     display_file(PORT_HELP, 1);
797 }
798 #endif /* MSDOS || WIN32 */
799 #endif /* PORT_HELP */
800
801 /* validate wizard mode if player has requested access to it */
802 boolean
803 authorize_wizard_mode()
804 {
805     if (!strcmp(plname, WIZARD_NAME))
806         return TRUE;
807     return FALSE;
808 }
809
810 #ifdef EXEPATH
811 #ifdef __DJGPP__
812 #define PATH_SEPARATOR '/'
813 #else
814 #define PATH_SEPARATOR '\\'
815 #endif
816
817 #ifdef WIN32
818 static char exenamebuf[PATHLEN];
819
820 char *
821 exename()
822 {
823     int bsize = PATHLEN;
824     char *tmp = exenamebuf, *tmp2;
825
826 #ifdef UNICODE
827     {
828         TCHAR wbuf[PATHLEN * 4];
829         GetModuleFileName((HANDLE) 0, wbuf, PATHLEN * 4);
830         WideCharToMultiByte(CP_ACP, 0, wbuf, -1, tmp, bsize, NULL, NULL);
831     }
832 #else
833     *(tmp + GetModuleFileName((HANDLE) 0, tmp, bsize)) = '\0';
834 #endif
835     tmp2 = strrchr(tmp, PATH_SEPARATOR);
836     if (tmp2)
837         *tmp2 = '\0';
838     tmp2++;
839     return tmp2;
840 }
841 #endif
842
843 #define EXEPATHBUFSZ 256
844 char exepathbuf[EXEPATHBUFSZ];
845
846 char *
847 exepath(str)
848 char *str;
849 {
850     char *tmp, *tmp2;
851     int bsize;
852
853     if (!str)
854         return (char *) 0;
855     bsize = EXEPATHBUFSZ;
856     tmp = exepathbuf;
857 #ifndef WIN32
858     Strcpy(tmp, str);
859 #else
860 #ifdef UNICODE
861     {
862         TCHAR wbuf[BUFSZ];
863         GetModuleFileName((HANDLE) 0, wbuf, BUFSZ);
864         WideCharToMultiByte(CP_ACP, 0, wbuf, -1, tmp, bsize, NULL, NULL);
865     }
866 #else
867     *(tmp + GetModuleFileName((HANDLE) 0, tmp, bsize)) = '\0';
868 #endif
869 #endif
870     tmp2 = strrchr(tmp, PATH_SEPARATOR);
871     if (tmp2)
872         *tmp2 = '\0';
873     return tmp;
874 }
875 #endif /* EXEPATH */
876
877 /*pcmain.c*/