Source:NetHack 3.6.0/src/save.c

From NetHackWiki
Jump to: navigation, search

Below is the full text to save.c from the source code of NetHack 3.6.0. To link to a particular line, write [[Source:NetHack 3.6.0/src/save.c#line123]], for example.

The NetHack General Public License applies to screenshots, source code and other content from NetHack.

This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.

Top of file

  1.  /* NetHack 3.6	save.c	$NHDT-Date: 1448241784 2015/11/23 01:23:04 $  $NHDT-Branch: master $:$NHDT-Revision: 1.95 $ */
  2.  /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3.  /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5.  #include "hack.h"
  6.  #include "lev.h"
  7.  
  8.  #ifndef NO_SIGNAL
  9.  #include <signal.h>
  10.  #endif
  11.  #if !defined(LSC) && !defined(O_WRONLY) && !defined(AZTEC_C)
  12.  #include <fcntl.h>
  13.  #endif
  14.  
  15.  #ifdef MFLOPPY
  16.  long bytes_counted;
  17.  static int count_only;
  18.  #endif
  19.  
  20.  #ifdef MICRO
  21.  int dotcnt, dotrow; /* also used in restore */
  22.  #endif
  23.  
  24.  STATIC_DCL void FDECL(savelevchn, (int, int));
  25.  STATIC_DCL void FDECL(savedamage, (int, int));
  26.  STATIC_DCL void FDECL(saveobj, (int, struct obj *));
  27.  STATIC_DCL void FDECL(saveobjchn, (int, struct obj *, int));
  28.  STATIC_DCL void FDECL(savemon, (int, struct monst *));
  29.  STATIC_DCL void FDECL(savemonchn, (int, struct monst *, int));
  30.  STATIC_DCL void FDECL(savetrapchn, (int, struct trap *, int));
  31.  STATIC_DCL void FDECL(savegamestate, (int, int));
  32.  STATIC_OVL void FDECL(save_msghistory, (int, int));
  33.  #ifdef MFLOPPY
  34.  STATIC_DCL void FDECL(savelev0, (int, XCHAR_P, int));
  35.  STATIC_DCL boolean NDECL(swapout_oldest);
  36.  STATIC_DCL void FDECL(copyfile, (char *, char *));
  37.  #endif /* MFLOPPY */
  38.  STATIC_DCL void FDECL(savelevl, (int fd, BOOLEAN_P));
  39.  STATIC_DCL void FDECL(def_bufon, (int));
  40.  STATIC_DCL void FDECL(def_bufoff, (int));
  41.  STATIC_DCL void FDECL(def_bflush, (int));
  42.  STATIC_DCL void FDECL(def_bwrite, (int, genericptr_t, unsigned int));
  43.  #ifdef ZEROCOMP
  44.  STATIC_DCL void FDECL(zerocomp_bufon, (int));
  45.  STATIC_DCL void FDECL(zerocomp_bufoff, (int));
  46.  STATIC_DCL void FDECL(zerocomp_bflush, (int));
  47.  STATIC_DCL void FDECL(zerocomp_bwrite, (int, genericptr_t, unsigned int));
  48.  STATIC_DCL void FDECL(zerocomp_bputc, (int));
  49.  #endif
  50.  
  51.  static struct save_procs {
  52.      const char *name;
  53.      void FDECL((*save_bufon), (int));
  54.      void FDECL((*save_bufoff), (int));
  55.      void FDECL((*save_bflush), (int));
  56.      void FDECL((*save_bwrite), (int, genericptr_t, unsigned int));
  57.      void FDECL((*save_bclose), (int));
  58.  } saveprocs = {
  59.  #if !defined(ZEROCOMP) || (defined(COMPRESS) || defined(ZLIB_COMP))
  60.      "externalcomp", def_bufon, def_bufoff, def_bflush, def_bwrite, def_bclose,
  61.  #else
  62.      "zerocomp",      zerocomp_bufon,  zerocomp_bufoff,
  63.      zerocomp_bflush, zerocomp_bwrite, zerocomp_bclose,
  64.  #endif
  65.  };
  66.  
  67.  static long nulls[sizeof(struct trap) + sizeof(struct fruit)];
  68.  
  69.  #if defined(UNIX) || defined(VMS) || defined(__EMX__) || defined(WIN32)
  70.  #define HUP if (!program_state.done_hup)
  71.  #else
  72.  #define HUP
  73.  #endif
  74.  
  75.  /* need to preserve these during save to avoid accessing freed memory */
  76.  static unsigned ustuck_id = 0, usteed_id = 0;
  77.  

dosave

  1.  int
  2.  dosave()
  3.  {
  4.      clear_nhwindow(WIN_MESSAGE);
  5.      if (yn("Really save?") == 'n') {
  6.          clear_nhwindow(WIN_MESSAGE);
  7.          if (multi > 0)
  8.              nomul(0);
  9.      } else {
  10.          clear_nhwindow(WIN_MESSAGE);
  11.          pline("Saving...");
  12.  #if defined(UNIX) || defined(VMS) || defined(__EMX__)
  13.          program_state.done_hup = 0;
  14.  #endif
  15.          if (dosave0()) {
  16.              u.uhp = -1; /* universal game's over indicator */
  17.              /* make sure they see the Saving message */
  18.              display_nhwindow(WIN_MESSAGE, TRUE);
  19.              exit_nhwindows("Be seeing you...");
  20.              terminate(EXIT_SUCCESS);
  21.          } else
  22.              (void) doredraw();
  23.      }
  24.      return 0;
  25.  }
  26.  

dosave0

  1.  /* returns 1 if save successful */
  2.  int
  3.  dosave0()
  4.  {
  5.      const char *fq_save;
  6.      register int fd, ofd;
  7.      xchar ltmp;
  8.      d_level uz_save;
  9.      char whynot[BUFSZ];
  10.  
  11.      /* we may get here via hangup signal, in which case we want to fix up
  12.         a few of things before saving so that they won't be restored in
  13.         an improper state; these will be no-ops for normal save sequence */
  14.      u.uinvulnerable = 0;
  15.      if (iflags.save_uinwater)
  16.          u.uinwater = 1, iflags.save_uinwater = 0;
  17.      if (iflags.save_uburied)
  18.          u.uburied = 1, iflags.save_uburied = 0;
  19.  
  20.      if (!program_state.something_worth_saving || !SAVEF[0])
  21.          return 0;
  22.      fq_save = fqname(SAVEF, SAVEPREFIX, 1); /* level files take 0 */
  23.  
  24.  #if defined(UNIX) || defined(VMS)
  25.      sethanguphandler((void FDECL((*), (int) )) SIG_IGN);
  26.  #endif
  27.  #ifndef NO_SIGNAL
  28.      (void) signal(SIGINT, SIG_IGN);
  29.  #endif
  30.  
  31.  #if defined(MICRO) && defined(MFLOPPY)
  32.      if (!saveDiskPrompt(0))
  33.          return 0;
  34.  #endif
  35.  
  36.      HUP if (iflags.window_inited)
  37.      {
  38.          nh_uncompress(fq_save);
  39.          fd = open_savefile();
  40.          if (fd > 0) {
  41.              (void) nhclose(fd);
  42.              clear_nhwindow(WIN_MESSAGE);
  43.              There("seems to be an old save file.");
  44.              if (yn("Overwrite the old file?") == 'n') {
  45.                  nh_compress(fq_save);
  46.                  return 0;
  47.              }
  48.          }
  49.      }
  50.  
  51.      HUP mark_synch(); /* flush any buffered screen output */
  52.  
  53.      fd = create_savefile();
  54.      if (fd < 0) {
  55.          HUP pline("Cannot open save file.");
  56.          (void) delete_savefile(); /* ab@unido */
  57.          return 0;
  58.      }
  59.  
  60.      vision_recalc(2); /* shut down vision to prevent problems
  61.                           in the event of an impossible() call */
  62.  
  63.      /* undo date-dependent luck adjustments made at startup time */
  64.      if (flags.moonphase == FULL_MOON) /* ut-sally!fletcher */
  65.          change_luck(-1);              /* and unido!ab */
  66.      if (flags.friday13)
  67.          change_luck(1);
  68.      if (iflags.window_inited)
  69.          HUP clear_nhwindow(WIN_MESSAGE);
  70.  
  71.  #ifdef MICRO
  72.      dotcnt = 0;
  73.      dotrow = 2;
  74.      curs(WIN_MAP, 1, 1);
  75.      if (strncmpi("X11", windowprocs.name, 3))
  76.          putstr(WIN_MAP, 0, "Saving:");
  77.  #endif
  78.  #ifdef MFLOPPY
  79.      /* make sure there is enough disk space */
  80.      if (iflags.checkspace) {
  81.          long fds, needed;
  82.  
  83.          savelev(fd, ledger_no(&u.uz), COUNT_SAVE);
  84.          savegamestate(fd, COUNT_SAVE);
  85.          needed = bytes_counted;
  86.  
  87.          for (ltmp = 1; ltmp <= maxledgerno(); ltmp++)
  88.              if (ltmp != ledger_no(&u.uz) && level_info[ltmp].where)
  89.                  needed += level_info[ltmp].size + (sizeof ltmp);
  90.          fds = freediskspace(fq_save);
  91.          if (needed > fds) {
  92.              HUP
  93.              {
  94.                  There("is insufficient space on SAVE disk.");
  95.                  pline("Require %ld bytes but only have %ld.", needed, fds);
  96.              }
  97.              flushout();
  98.              (void) nhclose(fd);
  99.              (void) delete_savefile();
  100.              return 0;
  101.          }
  102.  
  103.          co_false();
  104.      }
  105.  #endif /* MFLOPPY */
  106.  
  107.      store_version(fd);
  108.      store_savefileinfo(fd);
  109.      store_plname_in_file(fd);
  110.      ustuck_id = (u.ustuck ? u.ustuck->m_id : 0);
  111.      usteed_id = (u.usteed ? u.usteed->m_id : 0);
  112.      savelev(fd, ledger_no(&u.uz), WRITE_SAVE | FREE_SAVE);
  113.      savegamestate(fd, WRITE_SAVE | FREE_SAVE);
  114.  
  115.      /* While copying level files around, zero out u.uz to keep
  116.       * parts of the restore code from completely initializing all
  117.       * in-core data structures, since all we're doing is copying.
  118.       * This also avoids at least one nasty core dump.
  119.       */
  120.      uz_save = u.uz;
  121.      u.uz.dnum = u.uz.dlevel = 0;
  122.      /* these pointers are no longer valid, and at least u.usteed
  123.       * may mislead place_monster() on other levels
  124.       */
  125.      u.ustuck = (struct monst *) 0;
  126.      u.usteed = (struct monst *) 0;
  127.  
  128.      for (ltmp = (xchar) 1; ltmp <= maxledgerno(); ltmp++) {
  129.          if (ltmp == ledger_no(&uz_save))
  130.              continue;
  131.          if (!(level_info[ltmp].flags & LFILE_EXISTS))
  132.              continue;
  133.  #ifdef MICRO
  134.          curs(WIN_MAP, 1 + dotcnt++, dotrow);
  135.          if (dotcnt >= (COLNO - 1)) {
  136.              dotrow++;
  137.              dotcnt = 0;
  138.          }
  139.          if (strncmpi("X11", windowprocs.name, 3)) {
  140.              putstr(WIN_MAP, 0, ".");
  141.          }
  142.          mark_synch();
  143.  #endif
  144.          ofd = open_levelfile(ltmp, whynot);
  145.          if (ofd < 0) {
  146.              HUP pline1(whynot);
  147.              (void) nhclose(fd);
  148.              (void) delete_savefile();
  149.              HUP Strcpy(killer.name, whynot);
  150.              HUP done(TRICKED);
  151.              return 0;
  152.          }
  153.          minit(); /* ZEROCOMP */
  154.          getlev(ofd, hackpid, ltmp, FALSE);
  155.          (void) nhclose(ofd);
  156.          bwrite(fd, (genericptr_t) &ltmp, sizeof ltmp); /* level number*/
  157.          savelev(fd, ltmp, WRITE_SAVE | FREE_SAVE);     /* actual level*/
  158.          delete_levelfile(ltmp);
  159.      }
  160.      bclose(fd);
  161.  
  162.      u.uz = uz_save;
  163.  
  164.      /* get rid of current level --jgm */
  165.      delete_levelfile(ledger_no(&u.uz));
  166.      delete_levelfile(0);
  167.      nh_compress(fq_save);
  168.      /* this should probably come sooner... */
  169.      program_state.something_worth_saving = 0;
  170.      return 1;
  171.  }
  172.  

savegamestate

  1.  STATIC_OVL void
  2.  savegamestate(fd, mode)
  3.  register int fd, mode;
  4.  {
  5.      unsigned long uid;
  6.  
  7.  #ifdef MFLOPPY
  8.      count_only = (mode & COUNT_SAVE);
  9.  #endif
  10.      uid = (unsigned long) getuid();
  11.      bwrite(fd, (genericptr_t) &uid, sizeof uid);
  12.      bwrite(fd, (genericptr_t) &context, sizeof(struct context_info));
  13.      bwrite(fd, (genericptr_t) &flags, sizeof(struct flag));
  14.  #ifdef SYSFLAGS
  15.      bwrite(fd, (genericptr_t) &sysflags, sizeof(struct sysflag));
  16.  #endif
  17.      urealtime.realtime += (long) (getnow() - urealtime.restored);
  18.      bwrite(fd, (genericptr_t) &u, sizeof(struct you));
  19.      bwrite(fd, yyyymmddhhmmss(ubirthday), 14);
  20.      bwrite(fd, (genericptr_t) &urealtime.realtime,
  21.             sizeof(urealtime.realtime));
  22.      bwrite(fd, yyyymmddhhmmss(urealtime.restored), 14);
  23.      save_killers(fd, mode);
  24.  
  25.      /* must come before migrating_objs and migrating_mons are freed */
  26.      save_timers(fd, mode, RANGE_GLOBAL);
  27.      save_light_sources(fd, mode, RANGE_GLOBAL);
  28.  
  29.      saveobjchn(fd, invent, mode);
  30.      if (BALL_IN_MON) {
  31.          /* prevent loss of ball & chain when swallowed */
  32.          uball->nobj = uchain;
  33.          uchain->nobj = (struct obj *) 0;
  34.          saveobjchn(fd, uball, mode);
  35.      } else {
  36.          saveobjchn(fd, (struct obj *) 0, mode);
  37.      }
  38.  
  39.      saveobjchn(fd, migrating_objs, mode);
  40.      savemonchn(fd, migrating_mons, mode);
  41.      if (release_data(mode)) {
  42.          invent = 0;
  43.          migrating_objs = 0;
  44.          migrating_mons = 0;
  45.      }
  46.      bwrite(fd, (genericptr_t) mvitals, sizeof(mvitals));
  47.  
  48.      save_dungeon(fd, (boolean) !!perform_bwrite(mode),
  49.                   (boolean) !!release_data(mode));
  50.      savelevchn(fd, mode);
  51.      bwrite(fd, (genericptr_t) &moves, sizeof moves);
  52.      bwrite(fd, (genericptr_t) &monstermoves, sizeof monstermoves);
  53.      bwrite(fd, (genericptr_t) &quest_status, sizeof(struct q_score));
  54.      bwrite(fd, (genericptr_t) spl_book,
  55.             sizeof(struct spell) * (MAXSPELL + 1));
  56.      save_artifacts(fd);
  57.      save_oracles(fd, mode);
  58.      if (ustuck_id)
  59.          bwrite(fd, (genericptr_t) &ustuck_id, sizeof ustuck_id);
  60.      if (usteed_id)
  61.          bwrite(fd, (genericptr_t) &usteed_id, sizeof usteed_id);
  62.      bwrite(fd, (genericptr_t) pl_character, sizeof pl_character);
  63.      bwrite(fd, (genericptr_t) pl_fruit, sizeof pl_fruit);
  64.      savefruitchn(fd, mode);
  65.      savenames(fd, mode);
  66.      save_waterlevel(fd, mode);
  67.      save_msghistory(fd, mode);
  68.      bflush(fd);
  69.  }
  70.  

tricked_fileremoved

  1.  boolean
  2.  tricked_fileremoved(fd, whynot)
  3.  int fd;
  4.  char *whynot;
  5.  {
  6.      if (fd < 0) {
  7.          pline1(whynot);
  8.          pline("Probably someone removed it.");
  9.          Strcpy(killer.name, whynot);
  10.          done(TRICKED);
  11.          return TRUE;
  12.      }
  13.      return FALSE;
  14.  }
  15.  

savestateinlock

  1.  #ifdef INSURANCE
  2.  void
  3.  savestateinlock()
  4.  {
  5.      int fd, hpid;
  6.      static boolean havestate = TRUE;
  7.      char whynot[BUFSZ];
  8.  
  9.      /* When checkpointing is on, the full state needs to be written
  10.       * on each checkpoint.  When checkpointing is off, only the pid
  11.       * needs to be in the level.0 file, so it does not need to be
  12.       * constantly rewritten.  When checkpointing is turned off during
  13.       * a game, however, the file has to be rewritten once to truncate
  14.       * it and avoid restoring from outdated information.
  15.       *
  16.       * Restricting havestate to this routine means that an additional
  17.       * noop pid rewriting will take place on the first "checkpoint" after
  18.       * the game is started or restored, if checkpointing is off.
  19.       */
  20.      if (flags.ins_chkpt || havestate) {
  21.          /* save the rest of the current game state in the lock file,
  22.           * following the original int pid, the current level number,
  23.           * and the current savefile name, which should not be subject
  24.           * to any internal compression schemes since they must be
  25.           * readable by an external utility
  26.           */
  27.          fd = open_levelfile(0, whynot);
  28.          if (tricked_fileremoved(fd, whynot))
  29.              return;
  30.  
  31.          (void) read(fd, (genericptr_t) &hpid, sizeof(hpid));
  32.          if (hackpid != hpid) {
  33.              Sprintf(whynot, "Level #0 pid (%d) doesn't match ours (%d)!",
  34.                      hpid, hackpid);
  35.              pline1(whynot);
  36.              Strcpy(killer.name, whynot);
  37.              done(TRICKED);
  38.          }
  39.          (void) nhclose(fd);
  40.  
  41.          fd = create_levelfile(0, whynot);
  42.          if (fd < 0) {
  43.              pline1(whynot);
  44.              Strcpy(killer.name, whynot);
  45.              done(TRICKED);
  46.              return;
  47.          }
  48.          (void) write(fd, (genericptr_t) &hackpid, sizeof(hackpid));
  49.          if (flags.ins_chkpt) {
  50.              int currlev = ledger_no(&u.uz);
  51.  
  52.              (void) write(fd, (genericptr_t) &currlev, sizeof(currlev));
  53.              save_savefile_name(fd);
  54.              store_version(fd);
  55.              store_savefileinfo(fd);
  56.              store_plname_in_file(fd);
  57.  
  58.              ustuck_id = (u.ustuck ? u.ustuck->m_id : 0);
  59.              usteed_id = (u.usteed ? u.usteed->m_id : 0);
  60.              savegamestate(fd, WRITE_SAVE);
  61.          }
  62.          bclose(fd);
  63.      }
  64.      havestate = flags.ins_chkpt;
  65.  }
  66.  #endif
  67.  

savelev / savelev0

  1.  #ifdef MFLOPPY
  2.  boolean
  3.  savelev(fd, lev, mode)
  4.  int fd;
  5.  xchar lev;
  6.  int mode;
  7.  {
  8.      if (mode & COUNT_SAVE) {
  9.          bytes_counted = 0;
  10.          savelev0(fd, lev, COUNT_SAVE);
  11.          /* probably bytes_counted will be filled in again by an
  12.           * immediately following WRITE_SAVE anyway, but we'll
  13.           * leave it out of checkspace just in case */
  14.          if (iflags.checkspace) {
  15.              while (bytes_counted > freediskspace(levels))
  16.                  if (!swapout_oldest())
  17.                      return FALSE;
  18.          }
  19.      }
  20.      if (mode & (WRITE_SAVE | FREE_SAVE)) {
  21.          bytes_counted = 0;
  22.          savelev0(fd, lev, mode);
  23.      }
  24.      if (mode != FREE_SAVE) {
  25.          level_info[lev].where = ACTIVE;
  26.          level_info[lev].time = moves;
  27.          level_info[lev].size = bytes_counted;
  28.      }
  29.      return TRUE;
  30.  }
  31.  
  32.  STATIC_OVL void
  33.  savelev0(fd, lev, mode)
  34.  #else
  35.  void
  36.  savelev(fd, lev, mode)
  37.  #endif
  38.  int fd;
  39.  xchar lev;
  40.  int mode;
  41.  {
  42.  #ifdef TOS
  43.      short tlev;
  44.  #endif
  45.  
  46.      /* if we're tearing down the current level without saving anything
  47.         (which happens upon entrance to the endgame or after an aborted
  48.         restore attempt) then we don't want to do any actual I/O */
  49.      if (mode == FREE_SAVE)
  50.          goto skip_lots;
  51.  
  52.      /* purge any dead monsters (necessary if we're starting
  53.         a panic save rather than a normal one, or sometimes
  54.         when changing levels without taking time -- e.g.
  55.         create statue trap then immediately level teleport) */
  56.      if (iflags.purge_monsters)
  57.          dmonsfree();
  58.  
  59.      if (fd < 0)
  60.          panic("Save on bad file!"); /* impossible */
  61.  #ifdef MFLOPPY
  62.      count_only = (mode & COUNT_SAVE);
  63.  #endif
  64.      if (lev >= 0 && lev <= maxledgerno())
  65.          level_info[lev].flags |= VISITED;
  66.      bwrite(fd, (genericptr_t) &hackpid, sizeof(hackpid));
  67.  #ifdef TOS
  68.      tlev = lev;
  69.      tlev &= 0x00ff;
  70.      bwrite(fd, (genericptr_t) &tlev, sizeof(tlev));
  71.  #else
  72.      bwrite(fd, (genericptr_t) &lev, sizeof(lev));
  73.  #endif
  74.      savecemetery(fd, mode, &level.bonesinfo);
  75.      savelevl(fd,
  76.               (boolean) ((sfsaveinfo.sfi1 & SFI1_RLECOMP) == SFI1_RLECOMP));
  77.      bwrite(fd, (genericptr_t) lastseentyp, sizeof(lastseentyp));
  78.      bwrite(fd, (genericptr_t) &monstermoves, sizeof(monstermoves));
  79.      bwrite(fd, (genericptr_t) &upstair, sizeof(stairway));
  80.      bwrite(fd, (genericptr_t) &dnstair, sizeof(stairway));
  81.      bwrite(fd, (genericptr_t) &upladder, sizeof(stairway));
  82.      bwrite(fd, (genericptr_t) &dnladder, sizeof(stairway));
  83.      bwrite(fd, (genericptr_t) &sstairs, sizeof(stairway));
  84.      bwrite(fd, (genericptr_t) &updest, sizeof(dest_area));
  85.      bwrite(fd, (genericptr_t) &dndest, sizeof(dest_area));
  86.      bwrite(fd, (genericptr_t) &level.flags, sizeof(level.flags));
  87.      bwrite(fd, (genericptr_t) doors, sizeof(doors));
  88.      save_rooms(fd); /* no dynamic memory to reclaim */
  89.  
  90.  /* from here on out, saving also involves allocated memory cleanup */
  91.  skip_lots:
  92.      /* this comes before the map, so need cleanup here if we skipped */
  93.      if (mode == FREE_SAVE)
  94.          savecemetery(fd, mode, &level.bonesinfo);
  95.      /* must be saved before mons, objs, and buried objs */
  96.      save_timers(fd, mode, RANGE_LEVEL);
  97.      save_light_sources(fd, mode, RANGE_LEVEL);
  98.  
  99.      savemonchn(fd, fmon, mode);
  100.      save_worm(fd, mode); /* save worm information */
  101.      savetrapchn(fd, ftrap, mode);
  102.      saveobjchn(fd, fobj, mode);
  103.      saveobjchn(fd, level.buriedobjlist, mode);
  104.      saveobjchn(fd, billobjs, mode);
  105.      if (release_data(mode)) {
  106.          fmon = 0;
  107.          ftrap = 0;
  108.          fobj = 0;
  109.          level.buriedobjlist = 0;
  110.          billobjs = 0;
  111.          /* level.bonesinfo = 0; -- handled by savecemetery() */
  112.      }
  113.      save_engravings(fd, mode);
  114.      savedamage(fd, mode);
  115.      save_regions(fd, mode);
  116.      if (mode != FREE_SAVE)
  117.          bflush(fd);
  118.  }
  119.  

savelevl

  1.  STATIC_OVL void
  2.  savelevl(fd, rlecomp)
  3.  int fd;
  4.  boolean rlecomp;
  5.  {
  6.  #ifdef RLECOMP
  7.      struct rm *prm, *rgrm;
  8.      int x, y;
  9.      uchar match;
  10.  
  11.      if (rlecomp) {
  12.          /* perform run-length encoding of rm structs */
  13.  
  14.          rgrm = &levl[0][0]; /* start matching at first rm */
  15.          match = 0;
  16.  
  17.          for (y = 0; y < ROWNO; y++) {
  18.              for (x = 0; x < COLNO; x++) {
  19.                  prm = &levl[x][y];
  20.                  if (prm->glyph == rgrm->glyph && prm->typ == rgrm->typ
  21.                      && prm->seenv == rgrm->seenv
  22.                      && prm->horizontal == rgrm->horizontal
  23.                      && prm->flags == rgrm->flags && prm->lit == rgrm->lit
  24.                      && prm->waslit == rgrm->waslit
  25.                      && prm->roomno == rgrm->roomno && prm->edge == rgrm->edge
  26.                      && prm->candig == rgrm->candig) {
  27.                      match++;
  28.                      if (match > 254) {
  29.                          match = 254; /* undo this match */
  30.                          goto writeout;
  31.                      }
  32.                  } else {
  33.                  /* the run has been broken,
  34.                   * write out run-length encoding */
  35.                  writeout:
  36.                      bwrite(fd, (genericptr_t) &match, sizeof(uchar));
  37.                      bwrite(fd, (genericptr_t) rgrm, sizeof(struct rm));
  38.                      /* start encoding again. we have at least 1 rm
  39.                       * in the next run, viz. this one. */
  40.                      match = 1;
  41.                      rgrm = prm;
  42.                  }
  43.              }
  44.          }
  45.          if (match > 0) {
  46.              bwrite(fd, (genericptr_t) &match, sizeof(uchar));
  47.              bwrite(fd, (genericptr_t) rgrm, sizeof(struct rm));
  48.          }
  49.          return;
  50.      }
  51.  #else /* !RLECOMP */
  52.      nhUse(rlecomp);
  53.  #endif /* ?RLECOMP */
  54.      bwrite(fd, (genericptr_t) levl, sizeof levl);
  55.  }
  56.  

bufon

  1.  /*ARGSUSED*/
  2.  void
  3.  bufon(fd)
  4.  int fd;
  5.  {
  6.      (*saveprocs.save_bufon)(fd);
  7.      return;
  8.  }
  9.  

bufoff

  1.  /*ARGSUSED*/
  2.  void
  3.  bufoff(fd)
  4.  int fd;
  5.  {
  6.      (*saveprocs.save_bufoff)(fd);
  7.      return;
  8.  }
  9.  

bflush

  1.  /* flush run and buffer */
  2.  void
  3.  bflush(fd)
  4.  register int fd;
  5.  {
  6.      (*saveprocs.save_bflush)(fd);
  7.      return;
  8.  }
  9.  

bwrite

  1.  void
  2.  bwrite(fd, loc, num)
  3.  int fd;
  4.  genericptr_t loc;
  5.  register unsigned num;
  6.  {
  7.      (*saveprocs.save_bwrite)(fd, loc, num);
  8.      return;
  9.  }
  10.  

bclose

  1.  void
  2.  bclose(fd)
  3.  int fd;
  4.  {
  5.      (*saveprocs.save_bclose)(fd);
  6.      return;
  7.  }
  8.  

def_bufon

  1.  static int bw_fd = -1;
  2.  static FILE *bw_FILE = 0;
  3.  static boolean buffering = FALSE;
  4.  
  5.  STATIC_OVL void
  6.  def_bufon(fd)
  7.  int fd;
  8.  {
  9.  #ifdef UNIX
  10.      if (bw_fd != fd) {
  11.          if (bw_fd >= 0)
  12.              panic("double buffering unexpected");
  13.          bw_fd = fd;
  14.          if ((bw_FILE = fdopen(fd, "w")) == 0)
  15.              panic("buffering of file %d failed", fd);
  16.      }
  17.  #endif
  18.      buffering = TRUE;
  19.  }
  20.  

def_bufoff

  1.  STATIC_OVL void
  2.  def_bufoff(fd)
  3.  int fd;
  4.  {
  5.      def_bflush(fd);
  6.      buffering = FALSE;
  7.  }
  8.  

def_bflush

  1.  STATIC_OVL void
  2.  def_bflush(fd)
  3.  int fd;
  4.  {
  5.  #ifdef UNIX
  6.      if (fd == bw_fd) {
  7.          if (fflush(bw_FILE) == EOF)
  8.              panic("flush of savefile failed!");
  9.      }
  10.  #endif
  11.      return;
  12.  }
  13.  

def_bwrite

  1.  STATIC_OVL void
  2.  def_bwrite(fd, loc, num)
  3.  register int fd;
  4.  register genericptr_t loc;
  5.  register unsigned num;
  6.  {
  7.      boolean failed;
  8.  
  9.  #ifdef MFLOPPY
  10.      bytes_counted += num;
  11.      if (count_only)
  12.          return;
  13.  #endif
  14.  
  15.  #ifdef UNIX
  16.      if (buffering) {
  17.          if (fd != bw_fd)
  18.              panic("unbuffered write to fd %d (!= %d)", fd, bw_fd);
  19.  
  20.          failed = (fwrite(loc, (int) num, 1, bw_FILE) != 1);
  21.      } else
  22.  #endif /* UNIX */
  23.      {
  24.          /* lint wants 3rd arg of write to be an int; lint -p an unsigned */
  25.  #if defined(BSD) || defined(ULTRIX) || defined(WIN32) || defined(_MSC_VER)
  26.          failed = ((long) write(fd, loc, (int) num) != (long) num);
  27.  #else /* e.g. SYSV, __TURBOC__ */
  28.          failed = ((long) write(fd, loc, num) != (long) num);
  29.  #endif
  30.      }
  31.  
  32.      if (failed) {
  33.  #if defined(UNIX) || defined(VMS) || defined(__EMX__)
  34.          if (program_state.done_hup)
  35.              terminate(EXIT_FAILURE);
  36.          else
  37.  #endif
  38.              panic("cannot write %u bytes to file #%d", num, fd);
  39.      }
  40.  }
  41.  

def_bclose

  1.  void
  2.  def_bclose(fd)
  3.  int fd;
  4.  {
  5.      bufoff(fd);
  6.  #ifdef UNIX
  7.      if (fd == bw_fd) {
  8.          (void) fclose(bw_FILE);
  9.          bw_fd = -1;
  10.          bw_FILE = 0;
  11.      } else
  12.  #endif
  13.          (void) nhclose(fd);
  14.      return;
  15.  }
  16.  

ZEROCOMP functions

  1.  #ifdef ZEROCOMP
  2.  /* The runs of zero-run compression are flushed after the game state or a
  3.   * level is written out.  This adds a couple bytes to a save file, where
  4.   * the runs could be mashed together, but it allows gluing together game
  5.   * state and level files to form a save file, and it means the flushing
  6.   * does not need to be specifically called for every other time a level
  7.   * file is written out.
  8.   */
  9.  
  10.  #define RLESC '\0' /* Leading character for run of LRESC's */
  11.  #define flushoutrun(ln) (zerocomp_bputc(RLESC), zerocomp_bputc(ln), ln = -1)
  12.  
  13.  #ifndef ZEROCOMP_BUFSIZ
  14.  #define ZEROCOMP_BUFSIZ BUFSZ
  15.  #endif
  16.  static NEARDATA unsigned char outbuf[ZEROCOMP_BUFSIZ];
  17.  static NEARDATA unsigned short outbufp = 0;
  18.  static NEARDATA short outrunlength = -1;
  19.  static NEARDATA int bwritefd;
  20.  static NEARDATA boolean compressing = FALSE;
  21.  
  22.  /*dbg()
  23.  {
  24.      HUP printf("outbufp %d outrunlength %d\n", outbufp,outrunlength);
  25.  }*/
  26.  

zerocomp_bputc

  1.  STATIC_OVL void
  2.  zerocomp_bputc(c)
  3.  int c;
  4.  {
  5.  #ifdef MFLOPPY
  6.      bytes_counted++;
  7.      if (count_only)
  8.          return;
  9.  #endif
  10.      if (outbufp >= sizeof outbuf) {
  11.          (void) write(bwritefd, outbuf, sizeof outbuf);
  12.          outbufp = 0;
  13.      }
  14.      outbuf[outbufp++] = (unsigned char) c;
  15.  }
  16.  

zerocomp_bufon

  1.  /*ARGSUSED*/
  2.  void STATIC_OVL
  3.  zerocomp_bufon(fd)
  4.  int fd;
  5.  {
  6.      compressing = TRUE;
  7.      return;
  8.  }
  9.  

zerocomp_bufoff

  1.  /*ARGSUSED*/
  2.  STATIC_OVL void
  3.  zerocomp_bufoff(fd)
  4.  int fd;
  5.  {
  6.      if (outbufp) {
  7.          outbufp = 0;
  8.          panic("closing file with buffered data still unwritten");
  9.      }
  10.      outrunlength = -1;
  11.      compressing = FALSE;
  12.      return;
  13.  }
  14.  

zerocomp_bflush

  1.  /* flush run and buffer */
  2.  STATIC_OVL void
  3.  zerocomp_bflush(fd)
  4.  register int fd;
  5.  {
  6.      bwritefd = fd;
  7.      if (outrunlength >= 0) { /* flush run */
  8.          flushoutrun(outrunlength);
  9.      }
  10.  #ifdef MFLOPPY
  11.      if (count_only)
  12.          outbufp = 0;
  13.  #endif
  14.  
  15.      if (outbufp) {
  16.          if (write(fd, outbuf, outbufp) != outbufp) {
  17.  #if defined(UNIX) || defined(VMS) || defined(__EMX__)
  18.              if (program_state.done_hup)
  19.                  terminate(EXIT_FAILURE);
  20.              else
  21.  #endif
  22.                  zerocomp_bclose(fd); /* panic (outbufp != 0) */
  23.          }
  24.          outbufp = 0;
  25.      }
  26.  }
  27.  

zerocomp_bwrite

  1.  STATIC_OVL void
  2.  zerocomp_bwrite(fd, loc, num)
  3.  int fd;
  4.  genericptr_t loc;
  5.  register unsigned num;
  6.  {
  7.      register unsigned char *bp = (unsigned char *) loc;
  8.  
  9.      if (!compressing) {
  10.  #ifdef MFLOPPY
  11.          bytes_counted += num;
  12.          if (count_only)
  13.              return;
  14.  #endif
  15.          if ((unsigned) write(fd, loc, num) != num) {
  16.  #if defined(UNIX) || defined(VMS) || defined(__EMX__)
  17.              if (program_state.done_hup)
  18.                  terminate(EXIT_FAILURE);
  19.              else
  20.  #endif
  21.                  panic("cannot write %u bytes to file #%d", num, fd);
  22.          }
  23.      } else {
  24.          bwritefd = fd;
  25.          for (; num; num--, bp++) {
  26.              if (*bp == RLESC) { /* One more char in run */
  27.                  if (++outrunlength == 0xFF) {
  28.                      flushoutrun(outrunlength);
  29.                  }
  30.              } else {                     /* end of run */
  31.                  if (outrunlength >= 0) { /* flush run */
  32.                      flushoutrun(outrunlength);
  33.                  }
  34.                  zerocomp_bputc(*bp);
  35.              }
  36.          }
  37.      }
  38.  }
  39.  

zerocomp_bclose

  1.  void
  2.  zerocomp_bclose(fd)
  3.  int fd;
  4.  {
  5.      zerocomp_bufoff(fd);
  6.      (void) nhclose(fd);
  7.      return;
  8.  }
  9.  #endif /* ZEROCOMP */
  10.  

savelevchn

  1.  STATIC_OVL void
  2.  savelevchn(fd, mode)
  3.  register int fd, mode;
  4.  {
  5.      s_level *tmplev, *tmplev2;
  6.      int cnt = 0;
  7.  
  8.      for (tmplev = sp_levchn; tmplev; tmplev = tmplev->next)
  9.          cnt++;
  10.      if (perform_bwrite(mode))
  11.          bwrite(fd, (genericptr_t) &cnt, sizeof(int));
  12.  
  13.      for (tmplev = sp_levchn; tmplev; tmplev = tmplev2) {
  14.          tmplev2 = tmplev->next;
  15.          if (perform_bwrite(mode))
  16.              bwrite(fd, (genericptr_t) tmplev, sizeof(s_level));
  17.          if (release_data(mode))
  18.              free((genericptr_t) tmplev);
  19.      }
  20.      if (release_data(mode))
  21.          sp_levchn = 0;
  22.  }
  23.  

savecemetery

  1.  /* used when saving a level and also when saving dungeon overview data */
  2.  void
  3.  savecemetery(fd, mode, cemeteryaddr)
  4.  int fd;
  5.  int mode;
  6.  struct cemetery **cemeteryaddr;
  7.  {
  8.      struct cemetery *thisbones, *nextbones;
  9.      int flag;
  10.  
  11.      flag = *cemeteryaddr ? 0 : -1;
  12.      if (perform_bwrite(mode))
  13.          bwrite(fd, (genericptr_t) &flag, sizeof flag);
  14.      nextbones = *cemeteryaddr;
  15.      while ((thisbones = nextbones) != 0) {
  16.          nextbones = thisbones->next;
  17.          if (perform_bwrite(mode))
  18.              bwrite(fd, (genericptr_t) thisbones, sizeof *thisbones);
  19.          if (release_data(mode))
  20.              free((genericptr_t) thisbones);
  21.      }
  22.      if (release_data(mode))
  23.          *cemeteryaddr = 0;
  24.  }
  25.  

savedamage

  1.  STATIC_OVL void
  2.  savedamage(fd, mode)
  3.  register int fd, mode;
  4.  {
  5.      register struct damage *damageptr, *tmp_dam;
  6.      unsigned int xl = 0;
  7.  
  8.      damageptr = level.damagelist;
  9.      for (tmp_dam = damageptr; tmp_dam; tmp_dam = tmp_dam->next)
  10.          xl++;
  11.      if (perform_bwrite(mode))
  12.          bwrite(fd, (genericptr_t) &xl, sizeof(xl));
  13.  
  14.      while (xl--) {
  15.          if (perform_bwrite(mode))
  16.              bwrite(fd, (genericptr_t) damageptr, sizeof(*damageptr));
  17.          tmp_dam = damageptr;
  18.          damageptr = damageptr->next;
  19.          if (release_data(mode))
  20.              free((genericptr_t) tmp_dam);
  21.      }
  22.      if (release_data(mode))
  23.          level.damagelist = 0;
  24.  }
  25.  

saveobj

  1.  STATIC_OVL void
  2.  saveobj(fd, otmp)
  3.  int fd;
  4.  struct obj *otmp;
  5.  {
  6.      int buflen, zerobuf = 0;
  7.  
  8.      buflen = sizeof(struct obj);
  9.      bwrite(fd, (genericptr_t) &buflen, sizeof(int));
  10.      bwrite(fd, (genericptr_t) otmp, buflen);
  11.      if (otmp->oextra) {
  12.          if (ONAME(otmp))
  13.              buflen = strlen(ONAME(otmp)) + 1;
  14.          else
  15.              buflen = 0;
  16.          bwrite(fd, (genericptr_t) &buflen, sizeof buflen);
  17.          if (buflen > 0)
  18.              bwrite(fd, (genericptr_t) ONAME(otmp), buflen);
  19.  
  20.          /* defer to savemon() for this one */
  21.          if (OMONST(otmp))
  22.              savemon(fd, OMONST(otmp));
  23.          else
  24.              bwrite(fd, (genericptr_t) &zerobuf, sizeof zerobuf);
  25.  
  26.          if (OMID(otmp))
  27.              buflen = sizeof(unsigned);
  28.          else
  29.              buflen = 0;
  30.          bwrite(fd, (genericptr_t) &buflen, sizeof buflen);
  31.          if (buflen > 0)
  32.              bwrite(fd, (genericptr_t) OMID(otmp), buflen);
  33.  
  34.          if (OLONG(otmp))
  35.              buflen = sizeof(long);
  36.          else
  37.              buflen = 0;
  38.          bwrite(fd, (genericptr_t) &buflen, sizeof buflen);
  39.          if (buflen > 0)
  40.              bwrite(fd, (genericptr_t) OLONG(otmp), buflen);
  41.  
  42.          if (OMAILCMD(otmp))
  43.              buflen = strlen(OMAILCMD(otmp)) + 1;
  44.          else
  45.              buflen = 0;
  46.          bwrite(fd, (genericptr_t) &buflen, sizeof buflen);
  47.          if (buflen > 0)
  48.              bwrite(fd, (genericptr_t) OMAILCMD(otmp), buflen);
  49.      }
  50.  }
  51.  

saveobjchn

  1.  STATIC_OVL void
  2.  saveobjchn(fd, otmp, mode)
  3.  register int fd, mode;
  4.  register struct obj *otmp;
  5.  {
  6.      register struct obj *otmp2;
  7.      int minusone = -1;
  8.  
  9.      while (otmp) {
  10.          otmp2 = otmp->nobj;
  11.          if (perform_bwrite(mode)) {
  12.              saveobj(fd, otmp);
  13.          }
  14.          if (Has_contents(otmp))
  15.              saveobjchn(fd, otmp->cobj, mode);
  16.          if (release_data(mode)) {
  17.              /*  if (otmp->oclass == FOOD_CLASS)
  18.               *      food_disappears(otmp);
  19.               */
  20.              /*
  21.               * If these are on the floor, the discarding could
  22.               * be because of a game save, or we could just be changing levels.
  23.               * Always invalidate the pointer, but ensure that we have
  24.               * the o_id in order to restore the pointer on reload.
  25.               */
  26.              if (otmp == context.victual.piece) {
  27.                  /* Store the o_id of the victual if mismatched */
  28.                  if (context.victual.o_id != otmp->o_id)
  29.                      context.victual.o_id = otmp->o_id;
  30.                  /* invalidate the pointer; on reload it will get restored */
  31.                  context.victual.piece = (struct obj *) 0;
  32.              }
  33.              if (otmp == context.tin.tin) {
  34.                  /* Store the o_id of your tin */
  35.                  if (context.tin.o_id != otmp->o_id)
  36.                      context.tin.o_id = otmp->o_id;
  37.                  /* invalidate the pointer; on reload it will get restored */
  38.                  context.tin.tin = (struct obj *) 0;
  39.              }
  40.              /*  if (otmp->oclass == SPBOOK_CLASS)
  41.               *      book_disappears(otmp);
  42.               */
  43.              if (otmp == context.spbook.book) {
  44.                  /* Store the o_id of your spellbook */
  45.                  if (context.spbook.o_id != otmp->o_id)
  46.                      context.spbook.o_id = otmp->o_id;
  47.                  /* invalidate the pointer; on reload it will get restored */
  48.                  context.spbook.book = (struct obj *) 0;
  49.              }
  50.              otmp->where = OBJ_FREE; /* set to free so dealloc will work */
  51.              otmp->nobj = NULL;      /* nobj saved into otmp2 */
  52.              otmp->cobj = NULL;      /* contents handled above */
  53.              otmp->timed = 0;        /* not timed any more */
  54.              otmp->lamplit = 0;      /* caller handled lights */
  55.              dealloc_obj(otmp);
  56.          }
  57.          otmp = otmp2;
  58.      }
  59.      if (perform_bwrite(mode))
  60.          bwrite(fd, (genericptr_t) &minusone, sizeof(int));
  61.  }
  62.  

savemon

  1.  STATIC_OVL void
  2.  savemon(fd, mtmp)
  3.  int fd;
  4.  struct monst *mtmp;
  5.  {
  6.      int buflen;
  7.  
  8.      buflen = sizeof(struct monst);
  9.      bwrite(fd, (genericptr_t) &buflen, sizeof(int));
  10.      bwrite(fd, (genericptr_t) mtmp, buflen);
  11.      if (mtmp->mextra) {
  12.          if (MNAME(mtmp))
  13.              buflen = strlen(MNAME(mtmp)) + 1;
  14.          else
  15.              buflen = 0;
  16.          bwrite(fd, (genericptr_t) &buflen, sizeof buflen);
  17.          if (buflen > 0)
  18.              bwrite(fd, (genericptr_t) MNAME(mtmp), buflen);
  19.  
  20.          if (EGD(mtmp))
  21.              buflen = sizeof(struct egd);
  22.          else
  23.              buflen = 0;
  24.          bwrite(fd, (genericptr_t) &buflen, sizeof(int));
  25.          if (buflen > 0)
  26.              bwrite(fd, (genericptr_t) EGD(mtmp), buflen);
  27.  
  28.          if (EPRI(mtmp))
  29.              buflen = sizeof(struct epri);
  30.          else
  31.              buflen = 0;
  32.          bwrite(fd, (genericptr_t) &buflen, sizeof(int));
  33.          if (buflen > 0)
  34.              bwrite(fd, (genericptr_t) EPRI(mtmp), buflen);
  35.  
  36.          if (ESHK(mtmp))
  37.              buflen = sizeof(struct eshk);
  38.          else
  39.              buflen = 0;
  40.          bwrite(fd, (genericptr_t) &buflen, sizeof(int));
  41.          if (buflen > 0)
  42.              bwrite(fd, (genericptr_t) ESHK(mtmp), buflen);
  43.  
  44.          if (EMIN(mtmp))
  45.              buflen = sizeof(struct emin);
  46.          else
  47.              buflen = 0;
  48.          bwrite(fd, (genericptr_t) &buflen, sizeof(int));
  49.          if (buflen > 0)
  50.              bwrite(fd, (genericptr_t) EMIN(mtmp), buflen);
  51.  
  52.          if (EDOG(mtmp))
  53.              buflen = sizeof(struct edog);
  54.          else
  55.              buflen = 0;
  56.          bwrite(fd, (genericptr_t) &buflen, sizeof(int));
  57.          if (buflen > 0)
  58.              bwrite(fd, (genericptr_t) EDOG(mtmp), buflen);
  59.  
  60.          /* mcorpsenm is inline int rather than pointer to something,
  61.             so doesn't need to be preceded by a length field */
  62.          bwrite(fd, (genericptr_t) &MCORPSENM(mtmp), sizeof MCORPSENM(mtmp));
  63.      }
  64.  }
  65.  

savemonchn

  1.  STATIC_OVL void
  2.  savemonchn(fd, mtmp, mode)
  3.  register int fd, mode;
  4.  register struct monst *mtmp;
  5.  {
  6.      register struct monst *mtmp2;
  7.      int minusone = -1;
  8.  
  9.      while (mtmp) {
  10.          mtmp2 = mtmp->nmon;
  11.          if (perform_bwrite(mode)) {
  12.              mtmp->mnum = monsndx(mtmp->data);
  13.              if (mtmp->ispriest)
  14.                  forget_temple_entry(mtmp); /* EPRI() */
  15.              savemon(fd, mtmp);
  16.          }
  17.          if (mtmp->minvent)
  18.              saveobjchn(fd, mtmp->minvent, mode);
  19.          if (release_data(mode)) {
  20.              if (mtmp == context.polearm.hitmon) {
  21.                  context.polearm.m_id = mtmp->m_id;
  22.                  context.polearm.hitmon = NULL;
  23.              }
  24.              mtmp->nmon = NULL;  /* nmon saved into mtmp2 */
  25.              dealloc_monst(mtmp);
  26.          }
  27.          mtmp = mtmp2;
  28.      }
  29.      if (perform_bwrite(mode))
  30.          bwrite(fd, (genericptr_t) &minusone, sizeof(int));
  31.  }
  32.  

savetrapchn

  1.  STATIC_OVL void
  2.  savetrapchn(fd, trap, mode)
  3.  register int fd, mode;
  4.  register struct trap *trap;
  5.  {
  6.      register struct trap *trap2;
  7.  
  8.      while (trap) {
  9.          trap2 = trap->ntrap;
  10.          if (perform_bwrite(mode))
  11.              bwrite(fd, (genericptr_t) trap, sizeof(struct trap));
  12.          if (release_data(mode))
  13.              dealloc_trap(trap);
  14.          trap = trap2;
  15.      }
  16.      if (perform_bwrite(mode))
  17.          bwrite(fd, (genericptr_t) nulls, sizeof(struct trap));
  18.  }
  19.  

savefruitchn

  1.  /* save all the fruit names and ID's; this is used only in saving whole games
  2.   * (not levels) and in saving bones levels.  When saving a bones level,
  3.   * we only want to save the fruits which exist on the bones level; the bones
  4.   * level routine marks nonexistent fruits by making the fid negative.
  5.   */
  6.  void
  7.  savefruitchn(fd, mode)
  8.  register int fd, mode;
  9.  {
  10.      register struct fruit *f2, *f1;
  11.  
  12.      f1 = ffruit;
  13.      while (f1) {
  14.          f2 = f1->nextf;
  15.          if (f1->fid >= 0 && perform_bwrite(mode))
  16.              bwrite(fd, (genericptr_t) f1, sizeof(struct fruit));
  17.          if (release_data(mode))
  18.              dealloc_fruit(f1);
  19.          f1 = f2;
  20.      }
  21.      if (perform_bwrite(mode))
  22.          bwrite(fd, (genericptr_t) nulls, sizeof(struct fruit));
  23.      if (release_data(mode))
  24.          ffruit = 0;
  25.  }
  26.  

store_plname_in_file

  1.  void
  2.  store_plname_in_file(fd)
  3.  int fd;
  4.  {
  5.      int plsiztmp = PL_NSIZ;
  6.      bufoff(fd);
  7.      /* bwrite() before bufon() uses plain write() */
  8.      bwrite(fd, (genericptr_t) &plsiztmp, sizeof(plsiztmp));
  9.      bwrite(fd, (genericptr_t) plname, plsiztmp);
  10.      bufon(fd);
  11.      return;
  12.  }
  13.  

save_msghistory

  1.  STATIC_OVL void
  2.  save_msghistory(fd, mode)
  3.  int fd, mode;
  4.  {
  5.      char *msg;
  6.      int msgcount = 0, msglen;
  7.      int minusone = -1;
  8.      boolean init = TRUE;
  9.  
  10.      if (perform_bwrite(mode)) {
  11.          /* ask window port for each message in sequence */
  12.          while ((msg = getmsghistory(init)) != 0) {
  13.              init = FALSE;
  14.              msglen = strlen(msg);
  15.              /* sanity: truncate if necessary (shouldn't happen);
  16.                 no need to modify msg[] since terminator isn't written */
  17.              if (msglen > BUFSZ - 1)
  18.                  msglen = BUFSZ - 1;
  19.              bwrite(fd, (genericptr_t) &msglen, sizeof(msglen));
  20.              bwrite(fd, (genericptr_t) msg, msglen);
  21.              ++msgcount;
  22.          }
  23.          bwrite(fd, (genericptr_t) &minusone, sizeof(int));
  24.      }
  25.      debugpline1("Stored %d messages into savefile.", msgcount);
  26.      /* note: we don't attempt to handle release_data() here */
  27.  }
  28.  

store_savefileinfo

  1.  void
  2.  store_savefileinfo(fd)
  3.  int fd;
  4.  {
  5.      /* sfcap (decl.c) describes the savefile feature capabilities
  6.       * that are supported by this port/platform build.
  7.       *
  8.       * sfsaveinfo (decl.c) describes the savefile info that actually
  9.       * gets written into the savefile, and is used to determine the
  10.       * save file being written.
  11.  
  12.       * sfrestinfo (decl.c) describes the savefile info that is
  13.       * being used to read the information from an existing savefile.
  14.       *
  15.       */
  16.  
  17.      bufoff(fd);
  18.      /* bwrite() before bufon() uses plain write() */
  19.      bwrite(fd, (genericptr_t) &sfsaveinfo, (unsigned) (sizeof sfsaveinfo));
  20.      bufon(fd);
  21.      return;
  22.  }
  23.  

set_savepref

  1.  void
  2.  set_savepref(suitename)
  3.  const char *suitename;
  4.  {
  5.      if (!strcmpi(suitename, "externalcomp")) {
  6.          saveprocs.name = "externalcomp";
  7.          saveprocs.save_bufon = def_bufon;
  8.          saveprocs.save_bufoff = def_bufoff;
  9.          saveprocs.save_bflush = def_bflush;
  10.          saveprocs.save_bwrite = def_bwrite;
  11.          saveprocs.save_bclose = def_bclose;
  12.          sfsaveinfo.sfi1 |= SFI1_EXTERNALCOMP;
  13.          sfsaveinfo.sfi1 &= ~SFI1_ZEROCOMP;
  14.      }
  15.      if (!strcmpi(suitename, "!rlecomp")) {
  16.          sfsaveinfo.sfi1 &= ~SFI1_RLECOMP;
  17.      }
  18.  #ifdef ZEROCOMP
  19.      if (!strcmpi(suitename, "zerocomp")) {
  20.          saveprocs.name = "zerocomp";
  21.          saveprocs.save_bufon = zerocomp_bufon;
  22.          saveprocs.save_bufoff = zerocomp_bufoff;
  23.          saveprocs.save_bflush = zerocomp_bflush;
  24.          saveprocs.save_bwrite = zerocomp_bwrite;
  25.          saveprocs.save_bclose = zerocomp_bclose;
  26.          sfsaveinfo.sfi1 |= SFI1_ZEROCOMP;
  27.          sfsaveinfo.sfi1 &= ~SFI1_EXTERNALCOMP;
  28.      }
  29.  #endif
  30.  #ifdef RLECOMP
  31.      if (!strcmpi(suitename, "rlecomp")) {
  32.          sfsaveinfo.sfi1 |= SFI1_RLECOMP;
  33.      }
  34.  #endif
  35.  }
  36.  

free_dungeons

  1.  /* also called by prscore(); this probably belongs in dungeon.c... */
  2.  void
  3.  free_dungeons()
  4.  {
  5.  #ifdef FREE_ALL_MEMORY
  6.      savelevchn(0, FREE_SAVE);
  7.      save_dungeon(0, FALSE, TRUE);
  8.  #endif
  9.      return;
  10.  }
  11.  

freedynamicdata

  1.  void
  2.  freedynamicdata()
  3.  {
  4.      unload_qtlist();
  5.      free_menu_coloring();
  6.      free_invbuf();           /* let_to_name (invent.c) */
  7.      free_youbuf();           /* You_buf,&c (pline.c) */
  8.      msgtype_free();
  9.      tmp_at(DISP_FREEMEM, 0); /* temporary display effects */
  10.  #ifdef FREE_ALL_MEMORY
  11.  #define freeobjchn(X) (saveobjchn(0, X, FREE_SAVE), X = 0)
  12.  #define freemonchn(X) (savemonchn(0, X, FREE_SAVE), X = 0)
  13.  #define freetrapchn(X) (savetrapchn(0, X, FREE_SAVE), X = 0)
  14.  #define freefruitchn() savefruitchn(0, FREE_SAVE)
  15.  #define freenames() savenames(0, FREE_SAVE)
  16.  #define free_killers() save_killers(0, FREE_SAVE)
  17.  #define free_oracles() save_oracles(0, FREE_SAVE)
  18.  #define free_waterlevel() save_waterlevel(0, FREE_SAVE)
  19.  #define free_worm() save_worm(0, FREE_SAVE)
  20.  #define free_timers(R) save_timers(0, FREE_SAVE, R)
  21.  #define free_light_sources(R) save_light_sources(0, FREE_SAVE, R);
  22.  #define free_engravings() save_engravings(0, FREE_SAVE)
  23.  #define freedamage() savedamage(0, FREE_SAVE)
  24.  #define free_animals() mon_animal_list(FALSE)
  25.  
  26.      /* move-specific data */
  27.      dmonsfree(); /* release dead monsters */
  28.  
  29.      /* level-specific data */
  30.      free_timers(RANGE_LEVEL);
  31.      free_light_sources(RANGE_LEVEL);
  32.      clear_regions();
  33.      freemonchn(fmon);
  34.      free_worm(); /* release worm segment information */
  35.      freetrapchn(ftrap);
  36.      freeobjchn(fobj);
  37.      freeobjchn(level.buriedobjlist);
  38.      freeobjchn(billobjs);
  39.      free_engravings();
  40.      freedamage();
  41.  
  42.      /* game-state data */
  43.      free_killers();
  44.      free_timers(RANGE_GLOBAL);
  45.      free_light_sources(RANGE_GLOBAL);
  46.      freeobjchn(invent);
  47.      freeobjchn(migrating_objs);
  48.      freemonchn(migrating_mons);
  49.      freemonchn(mydogs); /* ascension or dungeon escape */
  50.      /* freelevchn();  --  [folded into free_dungeons()] */
  51.      free_animals();
  52.      free_oracles();
  53.      freefruitchn();
  54.      freenames();
  55.      free_waterlevel();
  56.      free_dungeons();
  57.  
  58.      /* some pointers in iflags */
  59.      if (iflags.wc_font_map)
  60.          free(iflags.wc_font_map);
  61.      if (iflags.wc_font_message)
  62.          free(iflags.wc_font_message);
  63.      if (iflags.wc_font_text)
  64.          free(iflags.wc_font_text);
  65.      if (iflags.wc_font_menu)
  66.          free(iflags.wc_font_menu);
  67.      if (iflags.wc_font_status)
  68.          free(iflags.wc_font_status);
  69.      if (iflags.wc_tile_file)
  70.          free(iflags.wc_tile_file);
  71.      free_autopickup_exceptions();
  72.  
  73.      /* miscellaneous */
  74.      /* free_pickinv_cache();  --  now done from really_done()... */
  75.      free_symsets();
  76.  #endif /* FREE_ALL_MEMORY */
  77.  #ifdef STATUS_VIA_WINDOWPORT
  78.      status_finish();
  79.  #endif
  80.  
  81.      /* last, because it frees data that might be used by panic() to provide
  82.         feedback to the user; conceivably other freeing might trigger panic */
  83.      sysopt_release(); /* SYSCF strings */
  84.      return;
  85.  }
  86.  

swapin_file

  1.  #ifdef MFLOPPY
  2.  boolean
  3.  swapin_file(lev)
  4.  int lev;
  5.  {
  6.      char to[PATHLEN], from[PATHLEN];
  7.  
  8.      Sprintf(from, "%s%s", permbones, alllevels);
  9.      Sprintf(to, "%s%s", levels, alllevels);
  10.      set_levelfile_name(from, lev);
  11.      set_levelfile_name(to, lev);
  12.      if (iflags.checkspace) {
  13.          while (level_info[lev].size > freediskspace(to))
  14.              if (!swapout_oldest())
  15.                  return FALSE;
  16.      }
  17.      if (wizard) {
  18.          pline("Swapping in `%s'.", from);
  19.          wait_synch();
  20.      }
  21.      copyfile(from, to);
  22.      (void) unlink(from);
  23.      level_info[lev].where = ACTIVE;
  24.      return TRUE;
  25.  }
  26.  

swapout_oldest

  1.  STATIC_OVL boolean
  2.  swapout_oldest()
  3.  {
  4.      char to[PATHLEN], from[PATHLEN];
  5.      int i, oldest;
  6.      long oldtime;
  7.  
  8.      if (!ramdisk)
  9.          return FALSE;
  10.      for (i = 1, oldtime = 0, oldest = 0; i <= maxledgerno(); i++)
  11.          if (level_info[i].where == ACTIVE
  12.              && (!oldtime || level_info[i].time < oldtime)) {
  13.              oldest = i;
  14.              oldtime = level_info[i].time;
  15.          }
  16.      if (!oldest)
  17.          return FALSE;
  18.      Sprintf(from, "%s%s", levels, alllevels);
  19.      Sprintf(to, "%s%s", permbones, alllevels);
  20.      set_levelfile_name(from, oldest);
  21.      set_levelfile_name(to, oldest);
  22.      if (wizard) {
  23.          pline("Swapping out `%s'.", from);
  24.          wait_synch();
  25.      }
  26.      copyfile(from, to);
  27.      (void) unlink(from);
  28.      level_info[oldest].where = SWAPPED;
  29.      return TRUE;
  30.  }
  31.  

copyfile

  1.  STATIC_OVL void
  2.  copyfile(from, to)
  3.  char *from, *to;
  4.  {
  5.  #ifdef TOS
  6.      if (_copyfile(from, to))
  7.          panic("Can't copy %s to %s", from, to);
  8.  #else
  9.      char buf[BUFSIZ]; /* this is system interaction, therefore
  10.                         * BUFSIZ instead of NetHack's BUFSZ */
  11.      int nfrom, nto, fdfrom, fdto;
  12.  
  13.      if ((fdfrom = open(from, O_RDONLY | O_BINARY, FCMASK)) < 0)
  14.          panic("Can't copy from %s !?", from);
  15.      if ((fdto = open(to, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, FCMASK)) < 0)
  16.          panic("Can't copy to %s", to);
  17.      do {
  18.          nfrom = read(fdfrom, buf, BUFSIZ);
  19.          nto = write(fdto, buf, nfrom);
  20.          if (nto != nfrom)
  21.              panic("Copyfile failed!");
  22.      } while (nfrom == BUFSIZ);
  23.      (void) nhclose(fdfrom);
  24.      (void) nhclose(fdto);
  25.  #endif /* TOS */
  26.  }
  27.  

co_false

  1.  /* see comment in bones.c */
  2.  void
  3.  co_false()
  4.  {
  5.      count_only = FALSE;
  6.      return;
  7.  }
  8.  
  9.  #endif /* MFLOPPY */
  10.  
  11.  /*save.c*/