value is examined; `r' is an exception with ``Rogue'', ``Ranger'',
and ``random'' values. If you prefix a `!' or ``no'' to the value, you can
exclude that role from being picked randomly.
+.lp rlecomp
+When writing out a save file, perform run length compression of level
+structures. Not all ports support run length compression. It has no
+effect on reading an existing save file.
.lp runmode
Controls the amount of screen updating for the map window when engaged
in multi-turn movement (running via shift+direction or control+direction
Select which windowing system to use, such as ``tty'' or ``X11''
(default depends on version).
Cannot be set with the `O' command.
+.lp zerocomp
+When writing out a save file, perform zero-comp compression of the
+contents. Not all ports support zero-comp compression. It has no effect
+on reading an existing save file.
.hn 2
Window Port Customization options
.pg
\begin{document}
%
% input file: guidebook.mn
-% $Revision: 1.89 $ $Date: 2005/01/09 21:40:02 $
+% $Revision: 1.90 $ $Date: 2005/01/16 03:57:39 $
%
%.ds h0 "
%.ds h1 %.ds h2 \%
and ``{\tt random}'' values. If you prefix `{\tt !}' or ``{\tt no}'' to the
value, you can exclude that role from being picked randomly.
%.lp
+\item[\ib{rlecomp}]
+When writing out a save file, perform run length compression of level
+structures. Not all ports support run length compression. It has no
+effect on reading an existing save file.
+%.lp
\item[\ib{runmode}]
Controls the amount of screen updating for the map window when engaged
in multi-turn movement (running via {\tt shift}+direction
Select which windowing system to use, such as ``{\tt tty}'' or ``{\tt X11}''
(default depends on version).
Cannot be set with the `{\tt O}' command.
+%.lp
+\item[\ib{zerocomp}]
+When writing out a save file, perform zero-comp compression of the
+contents. Not all ports support zero-comp compression. It has no effect
+on reading an existing save file.
\elist
%.hn 2
/*
* If COMPRESS is defined, it should contain the full path name of your
- * 'compress' program. Defining INTERNAL_COMP causes NetHack to do
- * simpler byte-stream compression internally. Both COMPRESS and
- * INTERNAL_COMP create smaller bones/level/save files, but require
- * additional code and time. Currently, only UNIX fully implements
- * COMPRESS; other ports should be able to uncompress save files a
- * la unixmain.c if so inclined.
+ * 'compress' program.
+ *
* If you define COMPRESS, you must also define COMPRESS_EXTENSION
* as the extension your compressor appends to filenames after
- * compression.
+ * compression. Currently, only UNIX fully implements
+ * COMPRESS; other ports should be able to uncompress save files a
+ * la unixmain.c if so inclined.
+ *
+ * Defining ZLIB_COMP builds in support for zlib compression. If you
+ * define ZLIB_COMP, you must link with a zlib library.
+ *
+ * COMPRESS and ZLIB_COMP are mutually exclusive.
+ *
*/
-
-#ifdef UNIX
+
+#if defined(UNIX) && !defined(ZLIB_COMP) && !defined(COMPRESS)
/* path and file name extension for compression program */
#define COMPRESS "/usr/bin/compress" /* Lempel-Ziv compression */
#define COMPRESS_EXTENSION ".Z" /* compress's extension */
#endif
#ifndef COMPRESS
-# define INTERNAL_COMP /* control use of NetHack's compression routines */
+# define ZLIB_COMP /* ZLIB for compression */
#endif
+/*
+ * Internal Compression Options
+ *
+ * Internal compression options RLECOMP and ZEROCOMP alter the data
+ * that gets written to the save file by NetHack, in contrast
+ * to COMPRESS or ZLIB_COMP which compress the entire file after
+ * the NetHack data is written out.
+ *
+ * Defining RLECOMP builds in support for internal run-length
+ * compression of level structures. If RLECOMP support is included
+ * it can be toggled on/off at runtime via the config file option
+ * rlecomp.
+ *
+ * Defining ZEROCOMP builds in support for internal zero-comp
+ * compression of data. If ZEROCOMP support is included it can still
+ * be toggled on/off at runtime via the config file option zerocomp.
+ *
+ * RLECOMP and ZEROCOMP support can be included even if
+ * COMPRESS or ZLIB_COMP support is included. One reason for doing
+ * so would be to provide savefile read compatibility with a savefile
+ * where those options were in effect. With RLECOMP and/or ZEROCOMP
+ * defined, NetHack can read an rlecomp or zerocomp savefile in, yet
+ * re-save without them.
+ *
+ * Using any compression option will create smaller bones/level/save
+ * files at the cost of additional code and time.
+ */
+
+/* # define INTERNAL_COMP */ /* Forces both ZEROCOMP and RLECOMP */
+/* # define ZEROCOMP */ /* Support ZEROCOMP compression */
+/* # define RLECOMP */ /* Support RLECOMP compression */
+
/*
* Data librarian. Defining DLB places most of the support files into
* a tar-like file, thus making a neater installation. See *conf.h
E char *fqn_prefix_names[PREFIX_COUNT];
#endif
+E NEARDATA struct savefile_info sfcap, sfrestinfo, sfsaveinfo;
+
#ifdef AUTOPICKUP_EXCEPTIONS
struct autopickup_exception {
char *pattern;
E int NDECL(open_savefile);
E int NDECL(delete_savefile);
E int NDECL(restore_saved_game);
-E void FDECL(compress, (const char *));
-E void FDECL(uncompress, (const char *));
+E void FDECL(nh_compress, (const char *));
+E void FDECL(nh_uncompress, (const char *));
E boolean FDECL(lock_file, (const char *,int,int));
E void FDECL(unlock_file, (const char *));
#ifdef USER_SOUNDS
E void FDECL(get_plname_from_file, (int, char *));
E void NDECL(minit);
E boolean FDECL(lookup_id_mapping, (unsigned, unsigned *));
-#ifdef ZEROCOMP
-E int FDECL(mread, (int,genericptr_t,unsigned int));
-#else
E void FDECL(mread, (int,genericptr_t,unsigned int));
-#endif
#ifndef GOLDOBJ
E void FDECL(put_gold_back, (struct obj **,long *));
#endif
+E int FDECL(validate, (int,const char *));
+E void NDECL(reset_restpref);
+E void FDECL(set_restpref, (const char *));
+E void FDECL(set_savepref, (const char *));
/* ### rip.c ### */
E void FDECL(bflush, (int));
E void FDECL(bwrite, (int,genericptr_t,unsigned int));
E void FDECL(bclose, (int));
+E void FDECL(def_bclose, (int));
+#if defined(ZEROCOMP)
+E void FDECL(zerocomp_bclose, (int));
+#endif
E void FDECL(savefruitchn, (int,int));
E void FDECL(store_plname_in_file, (int));
E void NDECL(free_dungeons);
E void NDECL(freedynamicdata);
+E void FDECL(store_savefileinfo, (int));
/* ### shk.c ### */
boolean menu_tab_sep; /* Use tabs to separate option menu fields */
boolean menu_requested; /* Flag for overloaded use of 'm' prefix
* on some non-move commands */
+ boolean zerocomp; /* write zero-compressed save files */
+ boolean rlecomp; /* run-length comp of levels when writing savefile */
uchar num_pad_mode;
int menu_headings; /* ATR for menu headings */
int purge_monsters; /* # of dead monsters still on fmon list */
unsigned long struct_sizes2; /* size of more key structs */
};
+struct savefile_info {
+ unsigned long sfi1; /* compression etc. */
+ unsigned long sfi2; /* miscellaneous */
+ unsigned long sfi3; /* thirdparty */
+};
+#ifdef NHSTDC
+#define SFI1_EXTERNALCOMP (1UL)
+#define SFI1_RLECOMP (1UL << 1)
+#define SFI1_ZEROCOMP (1UL << 2)
+#else
+#define SFI1_EXTERNALCOMP (1L)
+#define SFI1_RLECOMP (1L << 1)
+#define SFI1_ZEROCOMP (1L << 2)
+#endif
/*
* Configurable internal parameters.
fd = open_bonesfile(&u.uz, &bonesid);
if (fd < 0) return(0);
- if ((ok = uptodate(fd, bones)) == 0) {
+ if (validate(fd, bones) != 0) {
#ifdef WIZARD
if (!wizard)
#endif
pline("Discarding unuseable bones; no need to panic...");
+ ok = FALSE;
} else {
+ ok = TRUE;
#ifdef WIZARD
if(wizard) {
if(yn("Get bones?") == 'n') {
"lockdir", "configdir", "troubledir" };
#endif
+NEARDATA struct savefile_info sfcap = {
+#ifdef NHSTDC
+ 0x00000000UL
+#else
+ 0x00000000L
+#endif
+#if defined(COMPRESS) || defined(ZLIB_COMP)
+ | SFI1_EXTERNALCOMP
+#endif
+#if defined(ZEROCOMP)
+ | SFI1_ZEROCOMP
+#endif
+#if defined(RLECOMP)
+ | SFI1_RLECOMP
+#endif
+ ,
+#ifdef NHSTDC
+ 0x00000000UL, 0x00000000UL
+#else
+ 0x00000000L, 0x00000000L
+#endif
+};
+
+NEARDATA struct savefile_info sfrestinfo, sfsaveinfo = {
+#ifdef NHSTDC
+ 0x00000000UL
+#else
+ 0x00000000L
+#endif
+#if defined(COMPRESS) || defined(ZLIB_COMP)
+ | SFI1_EXTERNALCOMP
+#endif
+#if defined(ZEROCOMP)
+ | SFI1_ZEROCOMP
+#endif
+#if defined(RLECOMP)
+ | SFI1_RLECOMP
+#endif
+ ,
+#ifdef NHSTDC
+ 0x00000000UL, 0x00000000UL
+#else
+ 0x00000000L, 0x00000000L
+#endif
+};
+
/* dummy routine used to force linkage */
void
decl_init()
-/* SCCS Id: @(#)files.c 3.5 2004/11/22 */
+/* SCCS Id: @(#)files.c 3.5 2005/01/04 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
extern int errno;
#endif
+#ifdef ZLIB_COMP /* RLC 09 Mar 1999: Support internal ZLIB */
+#include "zlib.h"
+# ifndef COMPRESS_EXTENSION
+#define COMPRESS_EXTENSION ".gz"
+# endif
+#endif
+
#if defined(UNIX) && defined(QT_GRAPHICS)
#include <sys/types.h>
#include <dirent.h>
STATIC_DCL char *NDECL(set_bonestemp_name);
#ifdef COMPRESS
STATIC_DCL void FDECL(redirect, (const char *,const char *,FILE *,BOOLEAN_P));
+#endif
+#if defined(COMPRESS) || defined(ZLIB_COMP)
STATIC_DCL void FDECL(docompress_file, (const char *,BOOLEAN_P));
#endif
STATIC_DCL char *FDECL(make_lockname, (const char *,char *));
*bonesid = set_bonesfile_name(bones, lev);
fq_bones = fqname(bones, BONESPREFIX, 0);
- uncompress(fq_bones); /* no effect if nonexistent */
+ nh_uncompress(fq_bones); /* no effect if nonexistent */
#ifdef MAC
fd = macopen(fq_bones, O_RDONLY | O_BINARY, BONE_TYPE);
#else
void
compress_bonesfile()
{
- compress(fqname(bones, BONESPREFIX, 0));
+ nh_compress(fqname(bones, BONESPREFIX, 0));
}
/* ---------- END BONES FILE HANDLING ----------- */
const char *fq_save;
int fd;
+ reset_restpref();
set_savefile_name();
#ifdef MFLOPPY
if (!saveDiskPrompt(1))
#endif /* MFLOPPY */
fq_save = fqname(SAVEF, SAVEPREFIX, 0);
- uncompress(fq_save);
+ nh_uncompress(fq_save);
if ((fd = open_savefile()) < 0) return fd;
- if (!uptodate(fd, fq_save)) {
+ if (validate(fd, fq_save) != 0) {
(void) close(fd), fd = -1;
(void) delete_savefile();
}
# ifdef COMPRESS_EXTENSION
SAVEF[strlen(SAVEF)-strlen(COMPRESS_EXTENSION)] = '\0';
# endif
- uncompress(SAVEF);
+ nh_uncompress(SAVEF);
if ((fd = open_savefile()) >= 0) {
- if (uptodate(fd, filename)) {
+ if (validate(fd, filename)==0) {
char tplname[PL_NSIZ];
get_plname_from_file(fd, tplname);
result = strdup(tplname);
}
(void) close(fd);
}
- compress(SAVEF);
+ nh_compress(SAVEF);
return result;
# if 0
(void)fname_encode("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-.",
'%', fnamebuf, encodedfnamebuf, BUFSZ);
Sprintf(SAVEF, "%s*.NetHack-saved-game", encodedfnamebuf);
+#if defined(ZLIB_COMP)
+ Strcat(SAVEF, COMPRESS_EXTENSION);
+#endif
fq_save = fqname(SAVEF, SAVEPREFIX, 0);
n = 0;
/* compress file */
void
-compress(filename)
+nh_compress(filename)
const char *filename;
{
-#ifndef COMPRESS
+#if !defined(COMPRESS) && !defined(ZLIB_COMP)
#if (defined(macintosh) && (defined(__SC__) || defined(__MRC__))) || defined(__MWERKS__)
# pragma unused(filename)
#endif
/* uncompress file if it exists */
void
-uncompress(filename)
+nh_uncompress(filename)
const char *filename;
{
-#ifndef COMPRESS
+#if !defined(COMPRESS) && !defined(ZLIB_COMP)
#if (defined(macintosh) && (defined(__SC__) || defined(__MRC__))) || defined(__MWERKS__)
# pragma unused(filename)
#endif
#endif
}
+#ifdef ZLIB_COMP /* RLC 09 Mar 1999: Support internal ZLIB */
+static int
+make_compressed_name(filename,cfn)
+const char *filename;
+char *cfn;
+{
+#ifndef SHORT_FILENAMES
+ /* Assume free-form filename */
+
+ strcpy(cfn, filename);
+ strcat(cfn, COMPRESS_EXTENSION);
+ return TRUE;
+#else
+ /* Accomodates 8.3 restriction, but otherwise assumes free-form filenames.
+ This may need to be revised for some systems. If a name cannot be
+ generated, this function may return FALSE and the file will then remain
+ uncompressed. */
+ unsigned len;
+
+ /* Assume DOS style filename */
+
+ strcpy(cfn, filename);
+ len = strlen(cfn);
+ if (len>4 && stricmp(cfn+len-4,".sav")==0) {
+ /* Save file; change .SAV extension to .SAZ */
+ /* EMX/GCC (for OS/2) seems to miscompile cfn[len-1] */
+
+ cfn[strlen(cfn)-1]='z';
+ return TRUE;
+ } else if (strnicmp(cfn,"bones",5)==0) {
+ /* Bones file; change BONES prefix to BONEZ */
+
+ cfn[4]='z';
+ return TRUE;
+ } else {
+ /* Don't know how to convert this filename */
+
+ return FALSE;
+ }
+#endif /* !MSDOS */
+}
+
+STATIC_OVL void
+docompress_file(filename, uncomp)
+const char *filename;
+boolean uncomp;
+{
+ gzFile *compressedfile;
+ FILE *uncompressedfile;
+ char cfn[256];
+ char buf[1024];
+ unsigned len, len2;
+
+ if (!make_compressed_name(filename, cfn)) {
+ /* Can't generate a name for the compressed file
+ due to 8.3 restriction */
+ return;
+ }
+
+ if (!uncomp) {
+ /* Open the input and output files */
+ /* Note that gzopen takes "wb" as its mode, even on systems where
+ fopen takes "r" and "w" */
+
+ uncompressedfile = fopen(filename, RDBMODE);
+ if (uncompressedfile == NULL) {
+ perror(filename);
+ return;
+ }
+ compressedfile = gzopen(cfn, "wb");
+ if (compressedfile == NULL) {
+ if (errno == 0) {
+ pline("zlib failed to allocate memory");
+ } else {
+ perror(filename);
+ }
+ fclose(uncompressedfile);
+ return;
+ }
+
+ /* Copy from the uncompressed to the compressed file */
+
+ while (1) {
+ len = fread(buf, 1, sizeof(buf), uncompressedfile);
+ if (ferror(uncompressedfile)) {
+ pline("Failure reading uncompressed file");
+ pline("Can't compress %s.", filename);
+ fclose(uncompressedfile);
+ gzclose(compressedfile);
+ (void)unlink(cfn);
+ return;
+ }
+ if (len == 0) break; /* End of file */
+
+ len2 = gzwrite(compressedfile, buf, len);
+ if (len2 == 0) {
+ pline("Failure writing compressed file");
+ pline("Can't compress %s.", filename);
+ fclose(uncompressedfile);
+ gzclose(compressedfile);
+ (void)unlink(cfn);
+ return;
+ }
+ }
+
+ fclose(uncompressedfile);
+ gzclose(compressedfile);
+
+ /* Delete the file left behind */
+
+ (void)unlink(filename);
+
+ } else { /* uncomp */
+
+ /* Open the input and output files */
+ /* Note that gzopen takes "rb" as its mode, even on systems where
+ fopen takes "r" and "w" */
+
+ compressedfile = gzopen(cfn, "rb");
+ if (compressedfile == NULL) {
+ if (errno == 0) {
+ pline("zlib failed to allocate memory");
+ } else if (errno != ENOENT) {
+ perror(filename);
+ }
+ return;
+ }
+ uncompressedfile = fopen(filename, WRBMODE);
+ if (uncompressedfile == NULL) {
+ perror(filename);
+ gzclose(compressedfile);
+ return;
+ }
+
+ /* Copy from the compressed to the uncompressed file */
+
+ while (1) {
+ len = gzread(compressedfile, buf, sizeof(buf));
+ if (len == (unsigned)-1) {
+ pline("Failure reading compressed file");
+ pline("Can't uncompress %s.", filename);
+ fclose(uncompressedfile);
+ gzclose(compressedfile);
+ (void)unlink(filename);
+ return;
+ }
+ if (len == 0) break; /* End of file */
+
+ fwrite(buf, 1, len, uncompressedfile);
+ if (ferror(uncompressedfile)) {
+ pline("Failure writing uncompressed file");
+ pline("Can't uncompress %s.", filename);
+ fclose(uncompressedfile);
+ gzclose(compressedfile);
+ (void)unlink(filename);
+ return;
+ }
+ }
+
+ fclose(uncompressedfile);
+ gzclose(compressedfile);
+
+ /* Delete the file left behind */
+ (void)unlink(cfn);
+ }
+}
+#endif /* RLC 09 Mar 1999: End ZLIB patch */
+
/* ---------- END FILE COMPRESSION HANDLING ----------- */
{"rawio", (boolean *)0, FALSE, SET_IN_FILE},
#endif
{"rest_on_space", &flags.rest_on_space, FALSE, SET_IN_GAME},
+#ifdef RLECOMP
+ {"rlecomp", &iflags.rlecomp,
+# if defined(COMPRESS) || defined(ZLIB_COMP)
+ FALSE,
+# else
+ TRUE,
+# endif
+ DISP_IN_GAME},
+#endif
{"safe_pet", &flags.safe_dog, TRUE, SET_IN_GAME},
#ifdef WIZARD
{"sanity_check", &iflags.sanity_check, FALSE, SET_IN_GAME},
#endif
{"verbose", &flags.verbose, TRUE, SET_IN_GAME},
{"wraptext", &iflags.wc2_wraptext, FALSE, SET_IN_GAME},
+#ifdef ZEROCOMP
+ {"zerocomp", &iflags.zerocomp,
+# if defined(COMPRESS) || defined(ZLIB_COMP)
+ FALSE,
+# else
+ TRUE,
+# endif
+ DISP_IN_GAME},
+#endif
{(char *)0, (boolean *)0, FALSE, 0}
};
if (boolopt[i].addr)
*(boolopt[i].addr) = boolopt[i].initvalue;
}
+#if defined(COMPRESS) || defined(ZLIB_COMP)
+ set_savepref("externalcomp");
+ set_restpref("externalcomp");
+# ifdef RLECOMP
+ set_savepref("!rlecomp");
+ set_restpref("!rlecomp");
+# endif
+#else
+# ifdef ZEROCOMP
+ set_savepref("zerocomp");
+ set_restpref("zerocomp");
+# endif
+# ifdef RLECOMP
+ set_savepref("rlecomp");
+ set_restpref("rlecomp");
+# endif
+#endif
#ifdef SYSFLAGS
Strcpy(sysflags.sysflagsid, "sysflags");
sysflags.sysflagsid[9] = (char)sizeof(struct sysflag);
# endif
}
#endif /* TERMLIB || ASCIIGRAPH || MAC_GRAPHICS_ENV */
-
+#ifdef RLECOMP
+ if ((boolopt[i].addr) == &iflags.rlecomp) {
+ if (*boolopt[i].addr)
+ set_savepref("rlecomp");
+ else
+ set_savepref("!rlecomp");
+ }
+#endif
+#ifdef ZEROCOMP
+ if ((boolopt[i].addr) == &iflags.zerocomp) {
+ if (*boolopt[i].addr)
+ set_savepref("zerocomp");
+ else
+ set_savepref("externalcomp");
+ }
+#endif
/* only do processing below if setting with doset() */
if (initial) return;
-/* SCCS Id: @(#)restore.c 3.5 2003/09/06 */
+/* SCCS Id: @(#)restore.c 3.5 2005/01/04 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
#endif
#ifdef ZEROCOMP
-static int NDECL(mgetc);
+STATIC_DCL void NDECL(zerocomp_minit);
+STATIC_DCL void FDECL(zerocomp_mread, (int,genericptr_t,unsigned int));
+STATIC_DCL int NDECL(zerocomp_mgetc);
#endif
+
+STATIC_DCL void NDECL(def_minit);
+STATIC_DCL void FDECL(def_mread, (int,genericptr_t,unsigned int));
+
STATIC_DCL void NDECL(find_lev_obj);
STATIC_DCL void FDECL(restlevchn, (int));
STATIC_DCL void FDECL(restdamage, (int,BOOLEAN_P));
#ifndef GOLDOBJ
STATIC_DCL struct obj *FDECL(gold_in, (struct obj *));
#endif
+STATIC_DCL void FDECL(rest_levl, (int,BOOLEAN_P));
+
+static struct restore_procs {
+ const char *name;
+ int mread_flags;
+ void NDECL((*restore_minit));
+ void FDECL((*restore_mread), (int,genericptr_t,unsigned int));
+ void FDECL((*restore_bclose), (int));
+} restoreprocs = {
+#if !defined(ZEROCOMP) || (defined(COMPRESS) || defined(ZLIB_COMP))
+ "externalcomp", 0,
+ def_minit,
+ def_mread,
+ def_bclose,
+#else
+ "zerocomp", 0,
+ zerocomp_minit,
+ zerocomp_mread,
+ zerocomp_bclose,
+#endif
+};
/*
* Save a mapping of IDs from ghost levels to the current level. This
playwoRAMdisk();
/* Rewind save file and try again */
(void) lseek(fd, (off_t)0, 0);
- (void) uptodate(fd, (char *)0); /* skip version */
+ (void) validate(fd, (char *)0); /* skip version etc */
return dorecover(fd); /* 0 or 1 */
} else {
# endif
if (strncmpi("X11", windowprocs.name, 3))
putstr(WIN_MAP, 0, "Restoring:");
#endif
+ restoreprocs.mread_flags = 1; /* return despite error */
while(1) {
-#ifdef ZEROCOMP
- if(mread(fd, (genericptr_t) <mp, sizeof ltmp) < 0)
-#else
- if(read(fd, (genericptr_t) <mp, sizeof ltmp) != sizeof ltmp)
-#endif
+ mread(fd, (genericptr_t) <mp, sizeof ltmp);
+ if (restoreprocs.mread_flags == -1)
break;
getlev(fd, 0, ltmp, FALSE);
#ifdef MICRO
rtmp = restlevelfile(fd, ltmp);
if (rtmp < 2) return(rtmp); /* dorecover called recursively */
}
+ restoreprocs.mread_flags = 0;
#ifdef BSD
(void) lseek(fd, 0L, 0);
#else
(void) lseek(fd, (off_t)0, 0);
#endif
- (void) uptodate(fd, (char *)0); /* skip version info */
+ (void) validate(fd, (char *)0); /* skip version and savefile info */
get_plname_from_file(fd, plname);
getlev(fd, 0, (xchar)0, FALSE);
(void) close(fd);
+ /* Now set the restore settings to match the
+ * settings used by the save file output routines
+ */
+ reset_restpref();
+
if (!wizard && !discover)
(void) delete_savefile();
#ifdef REINCARNATION
return(1);
}
+STATIC_OVL void
+rest_levl(fd, rlecomp)
+int fd;
+boolean rlecomp;
+{
+#ifdef RLECOMP
+ short i, j;
+ uchar len;
+ struct rm r;
+
+ if (rlecomp) {
+# if defined(MAC)
+ /* Suppress warning about used before set */
+ (void) memset((genericptr_t) &r, 0, sizeof(r));
+# endif
+ i = 0; j = 0; len = 0;
+ while(i < ROWNO) {
+ while(j < COLNO) {
+ if(len > 0) {
+ levl[j][i] = r;
+ len -= 1;
+ j += 1;
+ } else {
+ mread(fd, (genericptr_t)&len, sizeof(uchar));
+ mread(fd, (genericptr_t)&r, sizeof(struct rm));
+ }
+ }
+ j = 0;
+ i += 1;
+ }
+ } else
+#endif /* RLECOMP */
+ mread(fd, (genericptr_t) levl, sizeof(levl));
+}
+
void
trickery(reason)
char *reason;
#endif
trickery(trickbuf);
}
-
-#ifdef RLECOMP
- {
- short i, j;
- uchar len;
- struct rm r;
-
-#if defined(MAC)
- /* Suppress warning about used before set */
- (void) memset((genericptr_t) &r, 0, sizeof(r));
-#endif
- i = 0; j = 0; len = 0;
- while(i < ROWNO) {
- while(j < COLNO) {
- if(len > 0) {
- levl[j][i] = r;
- len -= 1;
- j += 1;
- } else {
- mread(fd, (genericptr_t)&len, sizeof(uchar));
- mread(fd, (genericptr_t)&r, sizeof(struct rm));
- }
- }
- j = 0;
- i += 1;
- }
- }
-#else
- mread(fd, (genericptr_t) levl, sizeof(levl));
-#endif /* RLECOMP */
-
+ rest_levl(fd, (boolean)((sfrestinfo.sfi1 & SFI1_RLECOMP) == SFI1_RLECOMP));
mread(fd, (genericptr_t)&omoves, sizeof(omoves));
mread(fd, (genericptr_t)&upstair, sizeof(stairway));
mread(fd, (genericptr_t)&dnstair, sizeof(stairway));
}
+void
+minit()
+{
+ (*restoreprocs.restore_minit)();
+ return;
+}
+
+void
+mread(fd, buf, len)
+register int fd;
+register genericptr_t buf;
+register unsigned int len;
+{
+ (*restoreprocs.restore_mread)(fd, buf, len);
+ return;
+}
+
+/* examine the version info and the savefile_info data
+ that immediately follows it.
+ Return 0 if it passed the checks.
+ Return 1 if it failed the version check.
+ Return 2 if it failed the savefile feature check.
+ Return -1 if it failed for some unknown reason.
+ */
+int
+validate(fd, name)
+int fd;
+const char *name;
+{
+ int rlen;
+ struct savefile_info sfi;
+ unsigned long compatible;
+ boolean verbose = name ? TRUE : FALSE, reslt = FALSE;
+
+ if (!(reslt = uptodate(fd, name))) return 1;
+
+ rlen = read(fd, (genericptr_t) &sfi, sizeof sfi);
+ minit(); /* ZEROCOMP */
+ if (rlen == 0) {
+ if (verbose) {
+ pline("File \"%s\" is empty during save file feature check?", name);
+ wait_synch();
+ }
+ return -1;
+ }
+
+ compatible = (sfi.sfi1 & sfcap.sfi1);
+
+ if ((sfi.sfi1 & SFI1_ZEROCOMP) == SFI1_ZEROCOMP) {
+ if ((compatible & SFI1_ZEROCOMP) != SFI1_ZEROCOMP) {
+ if (verbose) {
+ pline("File \"%s\" has incompatible ZEROCOMP compression.", name);
+ wait_synch();
+ }
+ return 2;
+ } else if ((sfrestinfo.sfi1 & SFI1_ZEROCOMP) != SFI1_ZEROCOMP) {
+ set_restpref("zerocomp");
+ }
+ }
+
+ if ((sfi.sfi1 & SFI1_EXTERNALCOMP) == SFI1_EXTERNALCOMP) {
+ if ((compatible & SFI1_EXTERNALCOMP) != SFI1_EXTERNALCOMP) {
+ if (verbose) {
+ pline("File \"%s\" lacks required internal compression.", name);
+ wait_synch();
+ }
+ return 2;
+ } else if ((sfrestinfo.sfi1 & SFI1_EXTERNALCOMP) != SFI1_EXTERNALCOMP) {
+ set_restpref("externalcomp");
+ }
+ }
+
+ /* RLECOMP check must be last, after ZEROCOMP or INTERNALCOMP adjustments */
+ if ((sfi.sfi1 & SFI1_RLECOMP) == SFI1_RLECOMP) {
+ if ((compatible & SFI1_RLECOMP) != SFI1_RLECOMP) {
+ if (verbose) {
+ pline("File \"%s\" has incompatible run-length compression.", name);
+ wait_synch();
+ }
+ return 2;
+ } else if ((sfrestinfo.sfi1 & SFI1_RLECOMP) != SFI1_RLECOMP) {
+ set_restpref("rlecomp");
+ }
+ }
+ /* savefile does not have RLECOMP level location compression, so adjust */
+ else set_restpref("!rlecomp");
+
+ return 0;
+}
+
+void
+reset_restpref()
+{
+#ifdef ZEROCOMP
+ if (iflags.zerocomp)
+ set_restpref("zerocomp");
+ else
+#endif
+ set_restpref("externalcomp");
+#ifdef RLECOMP
+ if (iflags.rlecomp)
+ set_restpref("rlecomp");
+ else
+#endif
+ set_restpref("!rlecomp");
+}
+
+void
+set_restpref(suitename)
+const char *suitename;
+{
+ if (!strcmpi(suitename, "externalcomp")) {
+ restoreprocs.name = "externalcomp";
+ restoreprocs.restore_mread = def_mread;
+ restoreprocs.restore_minit = def_minit;
+ sfrestinfo.sfi1 |= SFI1_EXTERNALCOMP;
+ sfrestinfo.sfi1 &= ~SFI1_ZEROCOMP;
+ def_minit();
+ }
+ if (!strcmpi(suitename, "!rlecomp")) {
+ sfrestinfo.sfi1 &= ~SFI1_RLECOMP;
+ }
+#ifdef ZEROCOMP
+ if (!strcmpi(suitename, "zerocomp")) {
+ restoreprocs.name = "zerocomp";
+ restoreprocs.restore_mread = zerocomp_mread;
+ restoreprocs.restore_minit = zerocomp_minit;
+ sfrestinfo.sfi1 |= SFI1_ZEROCOMP;
+ sfrestinfo.sfi1 &= ~SFI1_EXTERNALCOMP;
+ zerocomp_minit();
+ }
+#endif
+#ifdef RLECOMP
+ if (!strcmpi(suitename, "rlecomp")) {
+ sfrestinfo.sfi1 |= SFI1_RLECOMP;
+ }
+#endif
+}
+
#ifdef ZEROCOMP
#define RLESC '\0' /* Leading character for run of RLESC's */
static NEARDATA short inrunlength = -1;
static NEARDATA int mreadfd;
-static int
-mgetc()
+STATIC_OVL int
+zerocomp_mgetc()
{
if (inbufp >= inbufsz) {
inbufsz = read(mreadfd, (genericptr_t)inbuf, sizeof inbuf);
return inbuf[inbufp++];
}
-void
-minit()
+STATIC_OVL void
+zerocomp_minit()
{
inbufsz = 0;
inbufp = 0;
inrunlength = -1;
}
-int
-mread(fd, buf, len)
+STATIC_OVL void
+zerocomp_mread(fd, buf, len)
int fd;
genericptr_t buf;
register unsigned len;
inrunlength--;
*(*((char **)&buf))++ = '\0';
} else {
- register short ch = mgetc();
- if (ch < 0) return -1; /*readlen;*/
+ register short ch = zerocomp_mgetc();
+ if (ch < 0) {
+ restoreprocs.mread_flags = -1;
+ return;
+ }
if ((*(*(char **)&buf)++ = (char)ch) == RLESC) {
- inrunlength = mgetc();
+ inrunlength = zerocomp_mgetc();
}
}
/*readlen++;*/
}
- return 0; /*readlen;*/
}
+#endif /* ZEROCOMP */
-#else /* ZEROCOMP */
-
-void
-minit()
+STATIC_OVL void
+def_minit()
{
return;
}
-void
-mread(fd, buf, len)
+STATIC_OVL void
+def_mread(fd, buf, len)
register int fd;
register genericptr_t buf;
register unsigned int len;
rlen = read(fd, buf, (unsigned) len);
if((unsigned)rlen != len){
#endif
+ if (restoreprocs.mread_flags == 1) { /* means "return anyway" */
+ restoreprocs.mread_flags = -1;
+ return;
+ } else {
pline("Read %d instead of %u bytes.", rlen, len);
if(restoring) {
(void) close(fd);
error("Error restoring old game.");
}
panic("Error reading level file.");
+ }
}
}
-#endif /* ZEROCOMP */
+
#ifndef GOLDOBJ
/*
* Takes all of the gold objects out of the invent or
-/* SCCS Id: @(#)save.c 3.5 2003/11/14 */
+/* SCCS Id: @(#)save.c 3.5 2005/01/04 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
int dotcnt, dotrow; /* also used in restore */
#endif
-#ifdef ZEROCOMP
-STATIC_DCL void FDECL(bputc, (int));
-#endif
STATIC_DCL void FDECL(savelevchn, (int,int));
STATIC_DCL void FDECL(savedamage, (int,int));
STATIC_DCL void FDECL(saveobjchn, (int,struct obj *,int));
STATIC_DCL boolean NDECL(swapout_oldest);
STATIC_DCL void FDECL(copyfile, (char *,char *));
#endif /* MFLOPPY */
+STATIC_DCL void FDECL(savelevl, (int fd, BOOLEAN_P));
+STATIC_DCL void FDECL(def_bufon, (int));
+STATIC_DCL void FDECL(def_bufoff, (int));
+STATIC_DCL void FDECL(def_bflush, (int));
+STATIC_DCL void FDECL(def_bwrite, (int,genericptr_t,unsigned int));
+#ifdef ZEROCOMP
+STATIC_DCL void FDECL(zerocomp_bufon, (int));
+STATIC_DCL void FDECL(zerocomp_bufoff, (int));
+STATIC_DCL void FDECL(zerocomp_bflush, (int));
+STATIC_DCL void FDECL(zerocomp_bwrite, (int,genericptr_t,unsigned int));
+STATIC_DCL void FDECL(zerocomp_bputc, (int));
+#endif
+
+static struct save_procs {
+ const char *name;
+ void FDECL((*save_bufon), (int));
+ void FDECL((*save_bufoff), (int));
+ void FDECL((*save_bflush), (int));
+ void FDECL((*save_bwrite), (int,genericptr_t,unsigned int));
+ void FDECL((*save_bclose), (int));
+} saveprocs = {
+#if !defined(ZEROCOMP) || (defined(COMPRESS) || defined(ZLIB_COMP))
+ "externalcomp",
+ def_bufon,
+ def_bufoff,
+ def_bflush,
+ def_bwrite,
+ def_bclose,
+#else
+ "zerocomp",
+ zerocomp_bufon,
+ zerocomp_bufoff,
+ zerocomp_bflush,
+ zerocomp_bwrite,
+ zerocomp_bclose,
+#endif
+};
+
#ifdef GCC_WARN
static long nulls[10];
#else
#endif
HUP if (iflags.window_inited) {
- uncompress(fq_save);
+ nh_uncompress(fq_save);
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(fq_save);
+ nh_compress(fq_save);
return 0;
}
}
#endif /* MFLOPPY */
store_version(fd);
+ store_savefileinfo(fd);
store_plname_in_file(fd);
ustuck_id = (u.ustuck ? u.ustuck->m_id : 0);
#ifdef STEED
/* get rid of current level --jgm */
delete_levelfile(ledger_no(&u.uz));
delete_levelfile(0);
- compress(fq_save);
+ nh_compress(fq_save);
return(1);
}
(void) write(fd, (genericptr_t) &currlev, sizeof(currlev));
save_savefile_name(fd);
store_version(fd);
+ store_savefileinfo(fd);
store_plname_in_file(fd);
ustuck_id = (u.ustuck ? u.ustuck->m_id : 0);
#else
bwrite(fd,(genericptr_t) &lev,sizeof(lev));
#endif
+ savelevl(fd, (boolean)((sfsaveinfo.sfi1 & SFI1_RLECOMP) == SFI1_RLECOMP));
+
+ bwrite(fd,(genericptr_t) &monstermoves,sizeof(monstermoves));
+ bwrite(fd,(genericptr_t) &upstair,sizeof(stairway));
+ bwrite(fd,(genericptr_t) &dnstair,sizeof(stairway));
+ bwrite(fd,(genericptr_t) &upladder,sizeof(stairway));
+ bwrite(fd,(genericptr_t) &dnladder,sizeof(stairway));
+ bwrite(fd,(genericptr_t) &sstairs,sizeof(stairway));
+ bwrite(fd,(genericptr_t) &updest,sizeof(dest_area));
+ bwrite(fd,(genericptr_t) &dndest,sizeof(dest_area));
+ bwrite(fd,(genericptr_t) &level.flags,sizeof(level.flags));
+ bwrite(fd, (genericptr_t) doors, sizeof(doors));
+ save_rooms(fd); /* no dynamic memory to reclaim */
+
+ /* from here on out, saving also involves allocated memory cleanup */
+ skip_lots:
+ /* must be saved before mons, objs, and buried objs */
+ save_timers(fd, mode, RANGE_LEVEL);
+ save_light_sources(fd, mode, RANGE_LEVEL);
+
+ savemonchn(fd, fmon, mode);
+ save_worm(fd, mode); /* save worm information */
+ savetrapchn(fd, ftrap, mode);
+ saveobjchn(fd, fobj, mode);
+ saveobjchn(fd, level.buriedobjlist, mode);
+ saveobjchn(fd, billobjs, mode);
+ if (release_data(mode)) {
+ fmon = 0;
+ ftrap = 0;
+ fobj = 0;
+ level.buriedobjlist = 0;
+ billobjs = 0;
+ }
+ save_engravings(fd, mode);
+ savedamage(fd, mode);
+ save_regions(fd, mode);
+ if (mode != FREE_SAVE) bflush(fd);
+}
+
+STATIC_OVL void
+savelevl(fd, rlecomp)
+int fd;
+boolean rlecomp;
+{
#ifdef RLECOMP
- {
+ struct rm *prm, *rgrm;
+ int x, y;
+ uchar match;
+
+ if (rlecomp) {
/* perform run-length encoding of rm structs */
- struct rm *prm, *rgrm;
- int x, y;
- uchar match;
rgrm = &levl[0][0]; /* start matching at first rm */
match = 0;
bwrite(fd, (genericptr_t)&match, sizeof(uchar));
bwrite(fd, (genericptr_t)rgrm, sizeof(struct rm));
}
- }
-#else
- bwrite(fd,(genericptr_t) levl,sizeof(levl));
+ } else
#endif /* RLECOMP */
+ bwrite(fd,(genericptr_t) levl,sizeof(levl));
+}
- bwrite(fd,(genericptr_t) &monstermoves,sizeof(monstermoves));
- bwrite(fd,(genericptr_t) &upstair,sizeof(stairway));
- bwrite(fd,(genericptr_t) &dnstair,sizeof(stairway));
- bwrite(fd,(genericptr_t) &upladder,sizeof(stairway));
- bwrite(fd,(genericptr_t) &dnladder,sizeof(stairway));
- bwrite(fd,(genericptr_t) &sstairs,sizeof(stairway));
- bwrite(fd,(genericptr_t) &updest,sizeof(dest_area));
- bwrite(fd,(genericptr_t) &dndest,sizeof(dest_area));
- bwrite(fd,(genericptr_t) &level.flags,sizeof(level.flags));
- bwrite(fd, (genericptr_t) doors, sizeof(doors));
- save_rooms(fd); /* no dynamic memory to reclaim */
+/*ARGSUSED*/
+void
+bufon(fd)
+int fd;
+{
+ (*saveprocs.save_bufon)(fd);
+ return;
+}
- /* from here on out, saving also involves allocated memory cleanup */
- skip_lots:
- /* must be saved before mons, objs, and buried objs */
- save_timers(fd, mode, RANGE_LEVEL);
- save_light_sources(fd, mode, RANGE_LEVEL);
+/*ARGSUSED*/
+void
+bufoff(fd)
+int fd;
+{
+ (*saveprocs.save_bufoff)(fd);
+ return;
+}
- savemonchn(fd, fmon, mode);
- save_worm(fd, mode); /* save worm information */
- savetrapchn(fd, ftrap, mode);
- saveobjchn(fd, fobj, mode);
- saveobjchn(fd, level.buriedobjlist, mode);
- saveobjchn(fd, billobjs, mode);
- if (release_data(mode)) {
- fmon = 0;
- ftrap = 0;
- fobj = 0;
- level.buriedobjlist = 0;
- billobjs = 0;
+void
+bflush(fd) /* flush run and buffer */
+register int fd;
+{
+ (*saveprocs.save_bflush)(fd);
+ return;
+}
+
+void
+bwrite(fd, loc, num)
+int fd;
+genericptr_t loc;
+register unsigned num;
+{
+ (*saveprocs.save_bwrite)(fd, loc, num);
+ return;
+}
+
+void
+bclose(fd)
+int fd;
+{
+ (*saveprocs.save_bclose)(fd);
+ return;
+}
+
+static int bw_fd = -1;
+static FILE *bw_FILE = 0;
+static boolean buffering = FALSE;
+
+STATIC_OVL void
+def_bufon(fd)
+ int fd;
+{
+#ifdef UNIX
+ if(bw_fd != fd) {
+ if(bw_fd >= 0)
+ panic("double buffering unexpected");
+ bw_fd = fd;
+ if((bw_FILE = fdopen(fd, "w")) == 0)
+ panic("buffering of file %d failed", fd);
+ }
+#endif
+ buffering = TRUE;
+}
+
+STATIC_OVL void
+def_bufoff(fd)
+int fd;
+{
+ def_bflush(fd);
+ buffering = FALSE;
+}
+
+STATIC_OVL void
+def_bflush(fd)
+ int fd;
+{
+#ifdef UNIX
+ if(fd == bw_fd) {
+ if(fflush(bw_FILE) == EOF)
+ panic("flush of savefile failed!");
+ }
+#endif
+ return;
+}
+
+STATIC_OVL void
+def_bwrite(fd,loc,num)
+register int fd;
+register genericptr_t loc;
+register unsigned num;
+{
+ boolean failed;
+
+#ifdef MFLOPPY
+ bytes_counted += num;
+ if (count_only) return;
+#endif
+
+#ifdef UNIX
+ if (buffering) {
+ if(fd != bw_fd)
+ panic("unbuffered write to fd %d (!= %d)", fd, bw_fd);
+
+ failed = (fwrite(loc, (int)num, 1, bw_FILE) != 1);
+ } else
+#endif /* UNIX */
+ {
+/* lint wants the 3rd arg of write to be an int; lint -p an unsigned */
+#if defined(BSD) || defined(ULTRIX) || defined(WIN32)
+ failed = (write(fd, loc, (int)num) != (int)num);
+#else /* e.g. SYSV, __TURBOC__ */
+ failed = (write(fd, loc, num) != num);
+#endif
+ }
+
+ if (failed) {
+#if defined(UNIX) || defined(VMS) || defined(__EMX__)
+ if (program_state.done_hup)
+ terminate(EXIT_FAILURE);
+ else
+#endif
+ panic("cannot write %u bytes to file #%d", num, fd);
}
- save_engravings(fd, mode);
- savedamage(fd, mode);
- save_regions(fd, mode);
- if (mode != FREE_SAVE) bflush(fd);
+}
+
+void
+def_bclose(fd)
+ int fd;
+{
+ bufoff(fd);
+#ifdef UNIX
+ if (fd == bw_fd) {
+ (void) fclose(bw_FILE);
+ bw_fd = -1;
+ bw_FILE = 0;
+ } else
+#endif
+ (void) close(fd);
+ return;
}
#ifdef ZEROCOMP
*/
#define RLESC '\0' /* Leading character for run of LRESC's */
-#define flushoutrun(ln) (bputc(RLESC), bputc(ln), ln = -1)
+#define flushoutrun(ln) (zerocomp_bputc(RLESC), zerocomp_bputc(ln), ln = -1)
#ifndef ZEROCOMP_BUFSIZ
# define ZEROCOMP_BUFSIZ BUFSZ
}*/
STATIC_OVL void
-bputc(c)
+zerocomp_bputc(c)
int c;
{
#ifdef MFLOPPY
/*ARGSUSED*/
void
-bufon(fd)
+STATIC_OVL zerocomp_bufon(fd)
int fd;
{
compressing = TRUE;
}
/*ARGSUSED*/
-void
-bufoff(fd)
+STATIC_OVL void
+zerocomp_bufoff(fd)
int fd;
{
if (outbufp) {
return;
}
-void
-bflush(fd) /* flush run and buffer */
+STATIC_OVL void
+zerocomp_bflush(fd) /* flush run and buffer */
register int fd;
{
bwritefd = fd;
terminate(EXIT_FAILURE);
else
#endif
- bclose(fd); /* panic (outbufp != 0) */
+ zerocomp_bclose(fd); /* panic (outbufp != 0) */
}
outbufp = 0;
}
}
-void
-bwrite(fd, loc, num)
+STATIC_OVL void
+zerocomp_bwrite(fd, loc, num)
int fd;
genericptr_t loc;
register unsigned num;
if (outrunlength >= 0) { /* flush run */
flushoutrun(outrunlength);
}
- bputc(*bp);
+ zerocomp_bputc(*bp);
}
}
}
}
void
-bclose(fd)
+zerocomp_bclose(fd)
int fd;
{
- bufoff(fd);
+ zerocomp_bufoff(fd);
(void) close(fd);
return;
}
-
-#else /* ZEROCOMP */
-
-static int bw_fd = -1;
-static FILE *bw_FILE = 0;
-static boolean buffering = FALSE;
-
-void
-bufon(fd)
- int fd;
-{
-#ifdef UNIX
- if(bw_fd != fd) {
- if(bw_fd >= 0)
- panic("double buffering unexpected");
- bw_fd = fd;
- if((bw_FILE = fdopen(fd, "w")) == 0)
- panic("buffering of file %d failed", fd);
- }
-#endif
- buffering = TRUE;
-}
-
-void
-bufoff(fd)
-int fd;
-{
- bflush(fd);
- buffering = FALSE;
-}
-
-void
-bflush(fd)
- int fd;
-{
-#ifdef UNIX
- if(fd == bw_fd) {
- if(fflush(bw_FILE) == EOF)
- panic("flush of savefile failed!");
- }
-#endif
- return;
-}
-
-void
-bwrite(fd,loc,num)
-register int fd;
-register genericptr_t loc;
-register unsigned num;
-{
- boolean failed;
-
-#ifdef MFLOPPY
- bytes_counted += num;
- if (count_only) return;
-#endif
-
-#ifdef UNIX
- if (buffering) {
- if(fd != bw_fd)
- panic("unbuffered write to fd %d (!= %d)", fd, bw_fd);
-
- failed = (fwrite(loc, (int)num, 1, bw_FILE) != 1);
- } else
-#endif /* UNIX */
- {
-/* lint wants the 3rd arg of write to be an int; lint -p an unsigned */
-#if defined(BSD) || defined(ULTRIX)
- failed = (write(fd, loc, (int)num) != (int)num);
-#else /* e.g. SYSV, __TURBOC__ */
- failed = (write(fd, loc, num) != num);
-#endif
- }
-
- if (failed) {
-#if defined(UNIX) || defined(VMS) || defined(__EMX__)
- if (program_state.done_hup)
- terminate(EXIT_FAILURE);
- else
-#endif
- panic("cannot write %u bytes to file #%d", num, fd);
- }
-}
-
-void
-bclose(fd)
- int fd;
-{
- bufoff(fd);
-#ifdef UNIX
- if (fd == bw_fd) {
- (void) fclose(bw_FILE);
- bw_fd = -1;
- bw_FILE = 0;
- } else
-#endif
- (void) close(fd);
- return;
-}
#endif /* ZEROCOMP */
STATIC_OVL void
pline("Stored %d messages into savefile.", msgcount);
#endif
}
+
+void
+store_savefileinfo(fd)
+int fd;
+{
+ /* sfcap (decl.c) describes the savefile feature capabilities
+ * that are supported by this port/platform build.
+ *
+ * sfsaveinfo (decl.c) describes the savefile info that actually
+ * gets written into the savefile, and is used to determine the
+ * save file being written.
+
+ * sfrestinfo (decl.c) describes the savefile info that is
+ * being used to read the information from an existing savefile.
+ *
+ */
+
+ bufoff(fd);
+ /* bwrite() before bufon() uses plain write() */
+ bwrite(fd,(genericptr_t)&sfsaveinfo, (unsigned)(sizeof sfsaveinfo));
+ bufon(fd);
+ return;
+}
+
+void
+set_savepref(suitename)
+const char *suitename;
+{
+ if (!strcmpi(suitename, "externalcomp")) {
+ saveprocs.name = "externalcomp";
+ saveprocs.save_bufon = def_bufon;
+ saveprocs.save_bufoff = def_bufoff;
+ saveprocs.save_bflush = def_bflush;
+ saveprocs.save_bwrite = def_bwrite;
+ saveprocs.save_bclose = def_bclose;
+ sfsaveinfo.sfi1 |= SFI1_EXTERNALCOMP;
+ sfsaveinfo.sfi1 &= ~SFI1_ZEROCOMP;
+ }
+ if (!strcmpi(suitename, "!rlecomp")) {
+ sfsaveinfo.sfi1 &= ~SFI1_RLECOMP;
+ }
+#ifdef ZEROCOMP
+ if (!strcmpi(suitename, "zerocomp")) {
+ saveprocs.name = "zerocomp";
+ saveprocs.save_bufon = zerocomp_bufon;
+ saveprocs.save_bufoff = zerocomp_bufoff;
+ saveprocs.save_bflush = zerocomp_bflush;
+ saveprocs.save_bwrite = zerocomp_bwrite;
+ saveprocs.save_bclose = zerocomp_bclose;
+ sfsaveinfo.sfi1 |= SFI1_ZEROCOMP;
+ sfsaveinfo.sfi1 &= ~SFI1_EXTERNALCOMP;
+ }
+#endif
+#ifdef RLECOMP
+ if (!strcmpi(suitename, "rlecomp")) {
+ sfsaveinfo.sfi1 |= SFI1_RLECOMP;
+ }
+#endif
+}
/* also called by prscore(); this probably belongs in dungeon.c... */
void
if(yn("Do you want to keep the save file?") == 'n')
(void) delete_savefile();
else {
- compress(fqname(SAVEF, SAVEPREFIX, 0));
+ nh_compress(fqname(SAVEF, SAVEPREFIX, 0));
}
}
if(yn("Do you want to keep the save file?") == 'n')
(void) delete_savefile();
else {
- compress(fqname(SAVEF, SAVEPREFIX, 0));
+ nh_compress(fqname(SAVEF, SAVEPREFIX, 0));
}
}
}
update_inventory();
if (discover || wizard) {
- if(yn("Do you want to keep the save file?") == 'n'){
+ if(yn("Do you want to keep the save file?") == 'n')
(void) delete_savefile();
+ else {
+ nh_compress(fqname(SAVEF, SAVEPREFIX, 0));
}
+
}
context.move = 0;
# IRIX 4.0.x needs -lsun if NIS (YP) is being used for passwd file lookup
# LIBS = -lsun
#
+# If ZLIB_COMP is defined in config.h this is necessary to link with zlib.
+# LIBS = -lz
+#
LIBS =
# make NetHack
(void) delete_savefile();
else {
(void) chmod(fq_save,FCMASK); /* back to readable */
- compress(fq_save);
+ nh_compress(fq_save);
}
}
context.move = 0;
# SCCS Id: @(#)Makefile.msc 3.5 $Date$
-# Copyright (c) NetHack PC Development Team 1993-2003
+# Copyright (c) NetHack PC Development Team 1993-2005
#
# NetHack 3.5.x Makefile for MS Visual C++ V6.x and above and MS NMAKE
#
PRECOMPHEAD = N # set to Y if you want to use precomp. headers
+#
+# If you defined ZLIB_COMP in include/config.h and you need
+# to link with the zlib.lib library, uncomment the line below.
+# If necessary, prefix explicit path information to the file name
+# otherwise it assumes the NetHack src directory.
+#
+
+#ZLIB = zlib.lib
+
#===============================================
#======= End of Modification Section ===========
#===============================================
$(GAMEFILE) : $(ALLOBJ) $(NHRES) $(O)gamedir.tag $(WINDLLS)
@if not exist $(GAMEDIR)\*.* mkdir $(GAMEDIR)
@echo Linking....
- $(link) $(LFLAGS) user32.lib winmm.lib -out:$@ @<<$(GAME).lnk
+ $(link) $(LFLAGS) $(ZLIB) user32.lib winmm.lib -out:$@ @<<$(GAME).lnk
$(ALLOBJ:^ =^
) $(NHRES)
<<
-/* SCCS Id: @(#)makedefs.c 3.5 2002/08/14 */
+/* SCCS Id: @(#)makedefs.c 3.5 2005/01/04 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* Copyright (c) M. Stephenson, 1990, 1991. */
/* Copyright (c) Dean Luick, 1990. */
/*
* Use this to explicitly mask out features during version checks.
+ *
+ * ZEROCOMP, RLECOMP, and ZLIB_COMP describe compression features
+ * that the port/plaform which wrote the savefile was capable of
+ * dealing with. Don't reject a savefile just because the port
+ * reading the savefile doesn't match on all/some of them.
+ * The actual compression features used to produce the savefile are
+ * recorded in the savefile_info structure immediately following the
+ * version_info, and that is what needs to be checked against the
+ * feature set of the port that is reading the savefile back in.
+ * That check is done in src/restore.c now.
+ *
*/
#define IGNORED_FEATURES ( 0L \
| (1L << 12) /* GOLDOBJ */ \
| (1L << 20) /* EXP_ON_BOTL */ \
| (1L << 21) /* SCORE_ON_BOTL */ \
+ | (1L << 27) /* ZEROCOMP */ \
+ | (1L << 28) /* RLECOMP */ \
)
static void
#ifdef SCORE_ON_BOTL
| (1L << 21)
#endif
- /* data format [COMPRESS excluded] (27..31) */
+ /* data format (27..31)
+ * External compression methods such as COMPRESS and ZLIB_COMP
+ * do not affect the contents and are thus excluded from here */
#ifdef ZEROCOMP
| (1L << 27)
#endif
#ifdef COMPRESS
"data file compression",
#endif
+#ifdef ZLIB_COMP
+ "ZLIB data file compression",
+#endif
#ifdef DLB
"data librarian",
#endif
#endif
#ifdef ZEROCOMP
"zero-compressed save files",
+#endif
+#ifdef RLECOMP
+ "run-length compression of levl array in save files",
#endif
save_bones_compat_buf,
"basic NetHack features"