int dosave() { #ifdef KEEP_SAVE /*WAC for reloading*/ register int fd; #endif clear_nhwindow(WIN_MESSAGE); if(yn("Really save?") == 'n') { clear_nhwindow(WIN_MESSAGE); if(multi > 0) nomul(0); } else { clear_nhwindow(WIN_MESSAGE); pline("Saving..."); #if defined(UNIX) || defined(VMS) || defined(__EMX__) program_state.done_hup = 0; #endif #ifdef KEEP_SAVE saverestore = FALSE; if (flags.keep_savefile) if(yn("Really quit?") == 'n') saverestore = TRUE; if(dosave0() && !saverestore) { #else if(dosave0()) { #endif program_state.something_worth_saving = 0; u.uhp = -1; /* universal game's over indicator */ /* make sure they see the Saving message */ display_nhwindow(WIN_MESSAGE, TRUE); exit_nhwindows("Be seeing you..."); terminate(EXIT_SUCCESS); } /*WAC redraw later else (void)doredraw();*/ } #ifdef KEEP_SAVE if (saverestore) { /*WAC pulled this from pcmain.c - restore game from the file just saved*/ fd = create_levelfile(0); if (fd < 0) { raw_print("Cannot create lock file"); } else { hackpid = 1; write(fd, (genericptr_t) &hackpid, sizeof(hackpid)); close(fd); } #ifdef MFLOPPY level_info[0].where = ACTIVE; #endif fd = restore_saved_game(); if (fd >= 0) dorecover(fd); check_special_room(FALSE); flags.move = 0; /*WAC correct these after restore*/ if(flags.moonphase == FULL_MOON) change_luck(1); if(flags.friday13) change_luck(-1); if(iflags.window_inited) clear_nhwindow(WIN_MESSAGE); } saverestore = FALSE; #endif (void)doredraw(); return 0; } #if defined(UNIX) || defined(VMS) || defined (__EMX__) || defined(WIN32) /*ARGSUSED*/ void hangup(sig_unused) /* called as signal() handler, so sent at least one arg */ int sig_unused; { # ifdef NOSAVEONHANGUP (void) signal(SIGINT, SIG_IGN); clearlocks(); # ifndef VMS terminate(EXIT_FAILURE); # endif # else /* SAVEONHANGUP */ if (!program_state.done_hup++) { if (program_state.something_worth_saving) (void) dosave0(); # ifdef VMS /* don't call exit when already within an exit handler; that would cancel any other pending user-mode handlers */ if (!program_state.exiting) # endif { clearlocks(); terminate(EXIT_FAILURE); } } # endif return; } #endif /* returns 1 if save successful */ int dosave0() { const char *fq_save; register int fd, ofd; xchar ltmp; d_level uz_save; char whynot[BUFSZ]; if (!SAVEF[0]) return 0; fq_save = fqname(SAVEF, SAVEPREFIX, 1); /* level files take 0 */ #if defined(UNIX) || defined(VMS) (void) signal(SIGHUP, SIG_IGN); #endif #ifndef NO_SIGNAL (void) signal(SIGINT, SIG_IGN); #endif #if defined(MICRO) && defined(MFLOPPY) if (!saveDiskPrompt(0)) return 0; #endif HUP if (iflags.window_inited) { uncompress_area(fq_save, SAVEF); fd = open_savefile(); if (fd > 0) { (void) close(fd); clear_nhwindow(WIN_MESSAGE); There("seems to be an old save file."); if (yn("Overwrite the old file?") == 'n') { compress_area(fq_save, SAVEF); #ifdef KEEP_SAVE /*WAC don't restore if you didn't save*/ saverestore = FALSE; #endif return 0; } } } HUP mark_synch(); /* flush any buffered screen output */ fd = create_savefile(); if(fd < 0) { HUP pline("Cannot open save file."); (void) delete_savefile(); /* ab@unido */ return(0); } vision_recalc(2); /* shut down vision to prevent problems in the event of an impossible() call */ /* undo date-dependent luck adjustments made at startup time */ if(flags.moonphase == FULL_MOON) /* ut-sally!fletcher */ change_luck(-1); /* and unido!ab */ if(flags.friday13) change_luck(1); if(iflags.window_inited) HUP clear_nhwindow(WIN_MESSAGE); #if defined(MICRO) && defined(TTY_GRAPHICS) if (!strncmpi("tty", windowprocs.name, 3)) { dotcnt = 0; dotrow = 2; curs(WIN_MAP, 1, 1); putstr(WIN_MAP, 0, "Saving:"); } #endif #ifdef MFLOPPY /* make sure there is enough disk space */ if (iflags.checkspace) { long fds, needed; savelev(fd, ledger_no(&u.uz), COUNT_SAVE); savegamestate(fd, COUNT_SAVE); needed = bytes_counted; for (ltmp = 1; ltmp <= maxledgerno(); ltmp++) if (ltmp != ledger_no(&u.uz) && level_info[ltmp].where) needed += level_info[ltmp].size + (sizeof ltmp); fds = freediskspace(fq_save); if (needed > fds) { HUP { There("is insufficient space on SAVE disk."); pline("Require %ld bytes but only have %ld.", needed, fds); } flushout(); (void) close(fd); (void) delete_savefile(); return 0; } co_false(); }
int restore_savefile(char *basename, const char *directory) { int gfd, lfd, sfd; int lev, savelev, hpid; xchar levc; struct version_info version_data; /* level 0 file contains: * pid of creating process (ignored here) * level number for current level of save file * name of save file nethack would have created * and game state */ (void) strcpy(lock, basename); gfd = open_levelfile(0, directory); if (gfd < 0) { #if defined(WIN32) && !defined(WIN_CE) if(errno == EACCES) { Fprintf(stderr, "\nThere are files from a game in progress under your name."); Fprintf(stderr,"\nThe files are locked or inaccessible."); Fprintf(stderr,"\nPerhaps the other game is still running?\n"); } else Fprintf(stderr, "\nTrouble accessing level 0 (errno = %d).\n", errno); #endif Fprintf(stderr, "Cannot open level 0 for %s.\n", basename); return(-1); } if (read(gfd, (genericptr_t) &hpid, sizeof hpid) != sizeof hpid) { Fprintf(stderr, "%s\n%s%s%s\n", "Checkpoint data incompletely written or subsequently clobbered;", "recovery for \"", basename, "\" impossible."); Close(gfd); return(-1); } if (read(gfd, (genericptr_t) &savelev, sizeof(savelev)) != sizeof(savelev)) { Fprintf(stderr, "Checkpointing was not in effect for %s -- recovery impossible.\n", basename); Close(gfd); return(-1); } if ((read(gfd, (genericptr_t) savename, sizeof savename) != sizeof savename) || (read(gfd, (genericptr_t) &version_data, sizeof version_data) != sizeof version_data)) { Fprintf(stderr, "Error reading %s -- can't recover.\n", lock); Close(gfd); return(-1); } /* save file should contain: * version info * current level (including pets) * (non-level-based) game state * other levels */ sfd = create_savefile(); if (sfd < 0) { Fprintf(stderr, "Cannot create savefile %s.\n", savename); Close(gfd); return(-1); } lfd = open_levelfile(savelev, directory); if (lfd < 0) { Fprintf(stderr, "Cannot open level of save for %s.\n", basename); Close(gfd); Close(sfd); return(-1); } if (write(sfd, (genericptr_t) &version_data, sizeof version_data) != sizeof version_data) { Fprintf(stderr, "Error writing %s; recovery failed.\n", savename); Close(gfd); Close(sfd); return(-1); } copy_bytes(lfd, sfd); Close(lfd); (void) unlink(lock); copy_bytes(gfd, sfd); Close(gfd); set_levelfile_name(0); (void) unlink(lock); for (lev = 1; lev < 256; lev++) { /* level numbers are kept in xchars in save.c, so the * maximum level number (for the endlevel) must be < 256 */ if (lev != savelev) { lfd = open_levelfile(lev, directory); if (lfd >= 0) { /* any or all of these may not exist */ levc = (xchar) lev; write(sfd, (genericptr_t) &levc, sizeof(levc)); copy_bytes(lfd, sfd); Close(lfd); (void) unlink(lock); } } } Close(sfd); #if 0 /* OBSOLETE, HackWB is no longer in use */ #ifdef AMIGA /* we need to create an icon for the saved game * or HackWB won't notice the file. */ { char iconfile[FILENAME]; int in, out; (void) sprintf(iconfile, "%s.info", savename); in = open("NetHack:default.icon", O_RDONLY); out = open(iconfile, O_WRONLY | O_TRUNC | O_CREAT); if(in > -1 && out > -1) { copy_bytes(in,out); } if(in > -1)close(in); if(out > -1)close(out); } #endif #endif return(0); }
/* returns 1 if save successful */ int dosave0(void) { const char *fq_save; register int fd, ofd; xchar ltmp; d_level uz_save; char whynot[BUFSZ]; #ifdef WHEREIS_FILE delete_whereis(); #endif if (!SAVEF[0]) return 0; fq_save = fqname(SAVEF, SAVEPREFIX, 1); /* level files take 0 */ #if defined(UNIX) || defined(VMS) (void) signal(SIGHUP, SIG_IGN); #endif #ifndef NO_SIGNAL (void) signal(SIGINT, SIG_IGN); #endif #if defined(MICRO) && defined(MFLOPPY) if (!saveDiskPrompt(0)) return 0; #endif HUP if (iflags.window_inited) { uncompress_area(fq_save, SAVEF); fd = open_savefile(); if (fd > 0) { (void) close(fd); clear_nhwindow(WIN_MESSAGE); There("seems to be an old save file."); if (yn("Overwrite the old file?") == 'n') { compress_area(fq_save, SAVEF); return 0; } } } HUP mark_synch(); /* flush any buffered screen output */ fd = create_savefile(); if(fd < 0) { HUP pline("Cannot open save file."); (void) delete_savefile(); /* ab@unido */ return(0); } vision_recalc(2); /* shut down vision to prevent problems in the event of an impossible() call */ /* undo date-dependent luck adjustments made at startup time */ if(flags.moonphase == FULL_MOON) /* ut-sally!fletcher */ change_luck(-1); /* and unido!ab */ if(flags.friday13) change_luck(1); if(iflags.window_inited) HUP clear_nhwindow(WIN_MESSAGE); #ifdef MICRO dotcnt = 0; dotrow = 2; curs(WIN_MAP, 1, 1); if (strncmpi("X11", windowprocs.name, 3)) putstr(WIN_MAP, 0, "Saving:"); #endif #ifdef MFLOPPY /* make sure there is enough disk space */ if (iflags.checkspace) { long fds, needed; savelev(fd, ledger_no(&u.uz), COUNT_SAVE); savegamestate(fd, COUNT_SAVE); needed = bytes_counted; for (ltmp = 1; ltmp <= maxledgerno(); ltmp++) if (ltmp != ledger_no(&u.uz) && level_info[ltmp].where) needed += level_info[ltmp].size + (sizeof ltmp); fds = freediskspace(fq_save); if (needed > fds) { HUP { There("is insufficient space on SAVE disk."); pline("Require %ld bytes but only have %ld.", needed, fds); } flushout(); (void) close(fd); (void) delete_savefile(); return 0; }