zlib support; also internal compression changes

o Add support for zlib compression via ZLIB_COMP in config.h (ZLIB_COMP
  and COMPRESS are mutually exclusive).
o rlecomp and zerocomp are run time options available if RLECOMP and
  ZEROCOMP are defined, but not turned on by default if either COMPRESS
  or ZLIB_COMP are defined.
o Add information to the save file about internal compression options
  used when writing the save file, particularly rlecomp and zerocomp
  support.
o Automatically adjust rlecomp and zerocomp (if support compiled in)
  when reading in an existing savefile that was saved with those options
  turned on.  Still allows writing out of savefile in preferred format.
o In order to support zlib and not conflict with compress and uncompress
  routines there, the NetHack internal functions were changed to
  nh_uncompress and nh_compress as done in the zlib contribution received
  in 1999 from <Someone>.

I tagged the sources NETHACK_3_5_0_PREZLIB prior to applying these
changes.
This commit is contained in:
nethack.allison
2005-01-22 15:28:15 +00:00
parent c40d876c3b
commit ab1872b928
20 changed files with 982 additions and 263 deletions
+8
View File
@@ -2086,6 +2086,10 @@ of specifying your role. Normally only the first letter of the
value is examined; `r' is an exception with ``Rogue'', ``Ranger'', value is examined; `r' is an exception with ``Rogue'', ``Ranger'',
and ``random'' values. If you prefix a `!' or ``no'' to the value, you can and ``random'' values. If you prefix a `!' or ``no'' to the value, you can
exclude that role from being picked randomly. 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 .lp runmode
Controls the amount of screen updating for the map window when engaged Controls the amount of screen updating for the map window when engaged
in multi-turn movement (running via shift+direction or control+direction in multi-turn movement (running via shift+direction or control+direction
@@ -2173,6 +2177,10 @@ Provide more commentary during the game (default on).
Select which windowing system to use, such as ``tty'' or ``X11'' Select which windowing system to use, such as ``tty'' or ``X11''
(default depends on version). (default depends on version).
Cannot be set with the `O' command. 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 .hn 2
Window Port Customization options Window Port Customization options
.pg .pg
+11 -1
View File
@@ -27,7 +27,7 @@
\begin{document} \begin{document}
% %
% input file: guidebook.mn % 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 h0 "
%.ds h1 %.ds h2 \% %.ds h1 %.ds h2 \%
@@ -2554,6 +2554,11 @@ value is examined; `r' is an exception with ``{\tt Rogue}'', {\tt Ranger}'',
and ``{\tt random}'' values. If you prefix `{\tt !}' or ``{\tt no}'' to the and ``{\tt random}'' values. If you prefix `{\tt !}' or ``{\tt no}'' to the
value, you can exclude that role from being picked randomly. value, you can exclude that role from being picked randomly.
%.lp %.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}] \item[\ib{runmode}]
Controls the amount of screen updating for the map window when engaged Controls the amount of screen updating for the map window when engaged
in multi-turn movement (running via {\tt shift}+direction in multi-turn movement (running via {\tt shift}+direction
@@ -2658,6 +2663,11 @@ Provide more commentary during the game (default on).
Select which windowing system to use, such as ``{\tt tty}'' or ``{\tt X11}'' Select which windowing system to use, such as ``{\tt tty}'' or ``{\tt X11}''
(default depends on version). (default depends on version).
Cannot be set with the `{\tt O}' command. 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 \elist
%.hn 2 %.hn 2
+46 -10
View File
@@ -159,18 +159,22 @@
/* /*
* If COMPRESS is defined, it should contain the full path name of your * If COMPRESS is defined, it should contain the full path name of your
* 'compress' program. Defining INTERNAL_COMP causes NetHack to do * 'compress' program.
* 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.
* If you define COMPRESS, you must also define COMPRESS_EXTENSION * If you define COMPRESS, you must also define COMPRESS_EXTENSION
* as the extension your compressor appends to filenames after * 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 */ /* path and file name extension for compression program */
#define COMPRESS "/usr/bin/compress" /* Lempel-Ziv compression */ #define COMPRESS "/usr/bin/compress" /* Lempel-Ziv compression */
#define COMPRESS_EXTENSION ".Z" /* compress's extension */ #define COMPRESS_EXTENSION ".Z" /* compress's extension */
@@ -180,9 +184,41 @@
#endif #endif
#ifndef COMPRESS #ifndef COMPRESS
# define INTERNAL_COMP /* control use of NetHack's compression routines */ # define ZLIB_COMP /* ZLIB for compression */
#endif #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 * Data librarian. Defining DLB places most of the support files into
* a tar-like file, thus making a neater installation. See *conf.h * a tar-like file, thus making a neater installation. See *conf.h
+2
View File
@@ -381,6 +381,8 @@ E char *fqn_prefix[PREFIX_COUNT];
E char *fqn_prefix_names[PREFIX_COUNT]; E char *fqn_prefix_names[PREFIX_COUNT];
#endif #endif
E NEARDATA struct savefile_info sfcap, sfrestinfo, sfsaveinfo;
#ifdef AUTOPICKUP_EXCEPTIONS #ifdef AUTOPICKUP_EXCEPTIONS
struct autopickup_exception { struct autopickup_exception {
char *pattern; char *pattern;
+11 -6
View File
@@ -673,8 +673,8 @@ E int NDECL(create_savefile);
E int NDECL(open_savefile); E int NDECL(open_savefile);
E int NDECL(delete_savefile); E int NDECL(delete_savefile);
E int NDECL(restore_saved_game); E int NDECL(restore_saved_game);
E void FDECL(compress, (const char *)); E void FDECL(nh_compress, (const char *));
E void FDECL(uncompress, (const char *)); E void FDECL(nh_uncompress, (const char *));
E boolean FDECL(lock_file, (const char *,int,int)); E boolean FDECL(lock_file, (const char *,int,int));
E void FDECL(unlock_file, (const char *)); E void FDECL(unlock_file, (const char *));
#ifdef USER_SOUNDS #ifdef USER_SOUNDS
@@ -1751,14 +1751,14 @@ E void FDECL(getlev, (int,int,XCHAR_P,BOOLEAN_P));
E void FDECL(get_plname_from_file, (int, char *)); E void FDECL(get_plname_from_file, (int, char *));
E void NDECL(minit); E void NDECL(minit);
E boolean FDECL(lookup_id_mapping, (unsigned, unsigned *)); 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)); E void FDECL(mread, (int,genericptr_t,unsigned int));
#endif
#ifndef GOLDOBJ #ifndef GOLDOBJ
E void FDECL(put_gold_back, (struct obj **,long *)); E void FDECL(put_gold_back, (struct obj **,long *));
#endif #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 ### */ /* ### rip.c ### */
@@ -1835,10 +1835,15 @@ E void FDECL(bufoff, (int));
E void FDECL(bflush, (int)); E void FDECL(bflush, (int));
E void FDECL(bwrite, (int,genericptr_t,unsigned int)); E void FDECL(bwrite, (int,genericptr_t,unsigned int));
E void FDECL(bclose, (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(savefruitchn, (int,int));
E void FDECL(store_plname_in_file, (int)); E void FDECL(store_plname_in_file, (int));
E void NDECL(free_dungeons); E void NDECL(free_dungeons);
E void NDECL(freedynamicdata); E void NDECL(freedynamicdata);
E void FDECL(store_savefileinfo, (int));
/* ### shk.c ### */ /* ### shk.c ### */
+2
View File
@@ -164,6 +164,8 @@ struct instance_flags {
boolean menu_tab_sep; /* Use tabs to separate option menu fields */ boolean menu_tab_sep; /* Use tabs to separate option menu fields */
boolean menu_requested; /* Flag for overloaded use of 'm' prefix boolean menu_requested; /* Flag for overloaded use of 'm' prefix
* on some non-move commands */ * 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; uchar num_pad_mode;
int menu_headings; /* ATR for menu headings */ int menu_headings; /* ATR for menu headings */
int purge_monsters; /* # of dead monsters still on fmon list */ int purge_monsters; /* # of dead monsters still on fmon list */
+14
View File
@@ -305,6 +305,20 @@ struct version_info {
unsigned long struct_sizes2; /* size of more key structs */ 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. * Configurable internal parameters.
+3 -1
View File
@@ -427,12 +427,14 @@ getbones()
fd = open_bonesfile(&u.uz, &bonesid); fd = open_bonesfile(&u.uz, &bonesid);
if (fd < 0) return(0); if (fd < 0) return(0);
if ((ok = uptodate(fd, bones)) == 0) { if (validate(fd, bones) != 0) {
#ifdef WIZARD #ifdef WIZARD
if (!wizard) if (!wizard)
#endif #endif
pline("Discarding unuseable bones; no need to panic..."); pline("Discarding unuseable bones; no need to panic...");
ok = FALSE;
} else { } else {
ok = TRUE;
#ifdef WIZARD #ifdef WIZARD
if(wizard) { if(wizard) {
if(yn("Get bones?") == 'n') { if(yn("Get bones?") == 'n') {
+46
View File
@@ -275,6 +275,52 @@ char *fqn_prefix_names[PREFIX_COUNT] = { "hackdir", "leveldir", "savedir",
"lockdir", "configdir", "troubledir" }; "lockdir", "configdir", "troubledir" };
#endif #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 */ /* dummy routine used to force linkage */
void void
decl_init() decl_init()
+193 -12
View File
@@ -1,4 +1,4 @@
/* 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. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -32,6 +32,13 @@ const
extern int errno; extern int errno;
#endif #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) #if defined(UNIX) && defined(QT_GRAPHICS)
#include <sys/types.h> #include <sys/types.h>
#include <dirent.h> #include <dirent.h>
@@ -158,6 +165,8 @@ STATIC_DCL char *FDECL(set_bonesfile_name, (char *,d_level*));
STATIC_DCL char *NDECL(set_bonestemp_name); STATIC_DCL char *NDECL(set_bonestemp_name);
#ifdef COMPRESS #ifdef COMPRESS
STATIC_DCL void FDECL(redirect, (const char *,const char *,FILE *,BOOLEAN_P)); 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)); STATIC_DCL void FDECL(docompress_file, (const char *,BOOLEAN_P));
#endif #endif
STATIC_DCL char *FDECL(make_lockname, (const char *,char *)); STATIC_DCL char *FDECL(make_lockname, (const char *,char *));
@@ -770,7 +779,7 @@ char **bonesid;
*bonesid = set_bonesfile_name(bones, lev); *bonesid = set_bonesfile_name(bones, lev);
fq_bones = fqname(bones, BONESPREFIX, 0); fq_bones = fqname(bones, BONESPREFIX, 0);
uncompress(fq_bones); /* no effect if nonexistent */ nh_uncompress(fq_bones); /* no effect if nonexistent */
#ifdef MAC #ifdef MAC
fd = macopen(fq_bones, O_RDONLY | O_BINARY, BONE_TYPE); fd = macopen(fq_bones, O_RDONLY | O_BINARY, BONE_TYPE);
#else #else
@@ -794,7 +803,7 @@ d_level *lev;
void void
compress_bonesfile() compress_bonesfile()
{ {
compress(fqname(bones, BONESPREFIX, 0)); nh_compress(fqname(bones, BONESPREFIX, 0));
} }
/* ---------- END BONES FILE HANDLING ----------- */ /* ---------- END BONES FILE HANDLING ----------- */
@@ -945,6 +954,7 @@ restore_saved_game()
const char *fq_save; const char *fq_save;
int fd; int fd;
reset_restpref();
set_savefile_name(); set_savefile_name();
#ifdef MFLOPPY #ifdef MFLOPPY
if (!saveDiskPrompt(1)) if (!saveDiskPrompt(1))
@@ -952,10 +962,10 @@ restore_saved_game()
#endif /* MFLOPPY */ #endif /* MFLOPPY */
fq_save = fqname(SAVEF, SAVEPREFIX, 0); fq_save = fqname(SAVEF, SAVEPREFIX, 0);
uncompress(fq_save); nh_uncompress(fq_save);
if ((fd = open_savefile()) < 0) return fd; if ((fd = open_savefile()) < 0) return fd;
if (!uptodate(fd, fq_save)) { if (validate(fd, fq_save) != 0) {
(void) close(fd), fd = -1; (void) close(fd), fd = -1;
(void) delete_savefile(); (void) delete_savefile();
} }
@@ -975,16 +985,16 @@ const char* filename;
# ifdef COMPRESS_EXTENSION # ifdef COMPRESS_EXTENSION
SAVEF[strlen(SAVEF)-strlen(COMPRESS_EXTENSION)] = '\0'; SAVEF[strlen(SAVEF)-strlen(COMPRESS_EXTENSION)] = '\0';
# endif # endif
uncompress(SAVEF); nh_uncompress(SAVEF);
if ((fd = open_savefile()) >= 0) { if ((fd = open_savefile()) >= 0) {
if (uptodate(fd, filename)) { if (validate(fd, filename)==0) {
char tplname[PL_NSIZ]; char tplname[PL_NSIZ];
get_plname_from_file(fd, tplname); get_plname_from_file(fd, tplname);
result = strdup(tplname); result = strdup(tplname);
} }
(void) close(fd); (void) close(fd);
} }
compress(SAVEF); nh_compress(SAVEF);
return result; return result;
# if 0 # if 0
@@ -1033,6 +1043,9 @@ get_saved_games()
(void)fname_encode("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-.", (void)fname_encode("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-.",
'%', fnamebuf, encodedfnamebuf, BUFSZ); '%', fnamebuf, encodedfnamebuf, BUFSZ);
Sprintf(SAVEF, "%s*.NetHack-saved-game", encodedfnamebuf); Sprintf(SAVEF, "%s*.NetHack-saved-game", encodedfnamebuf);
#if defined(ZLIB_COMP)
Strcat(SAVEF, COMPRESS_EXTENSION);
#endif
fq_save = fqname(SAVEF, SAVEPREFIX, 0); fq_save = fqname(SAVEF, SAVEPREFIX, 0);
n = 0; n = 0;
@@ -1278,10 +1291,10 @@ boolean uncomp;
/* compress file */ /* compress file */
void void
compress(filename) nh_compress(filename)
const char *filename; const char *filename;
{ {
#ifndef COMPRESS #if !defined(COMPRESS) && !defined(ZLIB_COMP)
#if (defined(macintosh) && (defined(__SC__) || defined(__MRC__))) || defined(__MWERKS__) #if (defined(macintosh) && (defined(__SC__) || defined(__MRC__))) || defined(__MWERKS__)
# pragma unused(filename) # pragma unused(filename)
#endif #endif
@@ -1293,10 +1306,10 @@ const char *filename;
/* uncompress file if it exists */ /* uncompress file if it exists */
void void
uncompress(filename) nh_uncompress(filename)
const char *filename; const char *filename;
{ {
#ifndef COMPRESS #if !defined(COMPRESS) && !defined(ZLIB_COMP)
#if (defined(macintosh) && (defined(__SC__) || defined(__MRC__))) || defined(__MWERKS__) #if (defined(macintosh) && (defined(__SC__) || defined(__MRC__))) || defined(__MWERKS__)
# pragma unused(filename) # pragma unused(filename)
#endif #endif
@@ -1305,6 +1318,174 @@ const char *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 ----------- */ /* ---------- END FILE COMPRESSION HANDLING ----------- */
+51 -1
View File
@@ -165,6 +165,15 @@ static struct Bool_Opt
{"rawio", (boolean *)0, FALSE, SET_IN_FILE}, {"rawio", (boolean *)0, FALSE, SET_IN_FILE},
#endif #endif
{"rest_on_space", &flags.rest_on_space, FALSE, SET_IN_GAME}, {"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}, {"safe_pet", &flags.safe_dog, TRUE, SET_IN_GAME},
#ifdef WIZARD #ifdef WIZARD
{"sanity_check", &iflags.sanity_check, FALSE, SET_IN_GAME}, {"sanity_check", &iflags.sanity_check, FALSE, SET_IN_GAME},
@@ -206,6 +215,15 @@ static struct Bool_Opt
#endif #endif
{"verbose", &flags.verbose, TRUE, SET_IN_GAME}, {"verbose", &flags.verbose, TRUE, SET_IN_GAME},
{"wraptext", &iflags.wc2_wraptext, FALSE, 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} {(char *)0, (boolean *)0, FALSE, 0}
}; };
@@ -515,6 +533,23 @@ initoptions()
if (boolopt[i].addr) if (boolopt[i].addr)
*(boolopt[i].addr) = boolopt[i].initvalue; *(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 #ifdef SYSFLAGS
Strcpy(sysflags.sysflagsid, "sysflags"); Strcpy(sysflags.sysflagsid, "sysflags");
sysflags.sysflagsid[9] = (char)sizeof(struct sysflag); sysflags.sysflagsid[9] = (char)sizeof(struct sysflag);
@@ -2328,7 +2363,22 @@ goodfruit:
# endif # endif
} }
#endif /* TERMLIB || ASCIIGRAPH || MAC_GRAPHICS_ENV */ #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() */ /* only do processing below if setting with doset() */
if (initial) return; if (initial) return;
+238 -57
View File
@@ -1,4 +1,4 @@
/* 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. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -16,8 +16,14 @@ extern void FDECL(substitute_tiles, (d_level *)); /* from tile.c */
#endif #endif
#ifdef ZEROCOMP #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 #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 NDECL(find_lev_obj);
STATIC_DCL void FDECL(restlevchn, (int)); STATIC_DCL void FDECL(restlevchn, (int));
STATIC_DCL void FDECL(restdamage, (int,BOOLEAN_P)); STATIC_DCL void FDECL(restdamage, (int,BOOLEAN_P));
@@ -34,6 +40,27 @@ STATIC_DCL void FDECL(reset_oattached_mids, (BOOLEAN_P));
#ifndef GOLDOBJ #ifndef GOLDOBJ
STATIC_DCL struct obj *FDECL(gold_in, (struct obj *)); STATIC_DCL struct obj *FDECL(gold_in, (struct obj *));
#endif #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 * Save a mapping of IDs from ghost levels to the current level. This
@@ -547,7 +574,7 @@ xchar ltmp;
playwoRAMdisk(); playwoRAMdisk();
/* Rewind save file and try again */ /* Rewind save file and try again */
(void) lseek(fd, (off_t)0, 0); (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 */ return dorecover(fd); /* 0 or 1 */
} else { } else {
# endif # endif
@@ -624,12 +651,10 @@ register int fd;
if (strncmpi("X11", windowprocs.name, 3)) if (strncmpi("X11", windowprocs.name, 3))
putstr(WIN_MAP, 0, "Restoring:"); putstr(WIN_MAP, 0, "Restoring:");
#endif #endif
restoreprocs.mread_flags = 1; /* return despite error */
while(1) { while(1) {
#ifdef ZEROCOMP mread(fd, (genericptr_t) &ltmp, sizeof ltmp);
if(mread(fd, (genericptr_t) &ltmp, sizeof ltmp) < 0) if (restoreprocs.mread_flags == -1)
#else
if(read(fd, (genericptr_t) &ltmp, sizeof ltmp) != sizeof ltmp)
#endif
break; break;
getlev(fd, 0, ltmp, FALSE); getlev(fd, 0, ltmp, FALSE);
#ifdef MICRO #ifdef MICRO
@@ -646,18 +671,24 @@ register int fd;
rtmp = restlevelfile(fd, ltmp); rtmp = restlevelfile(fd, ltmp);
if (rtmp < 2) return(rtmp); /* dorecover called recursively */ if (rtmp < 2) return(rtmp); /* dorecover called recursively */
} }
restoreprocs.mread_flags = 0;
#ifdef BSD #ifdef BSD
(void) lseek(fd, 0L, 0); (void) lseek(fd, 0L, 0);
#else #else
(void) lseek(fd, (off_t)0, 0); (void) lseek(fd, (off_t)0, 0);
#endif #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); get_plname_from_file(fd, plname);
getlev(fd, 0, (xchar)0, FALSE); getlev(fd, 0, (xchar)0, FALSE);
(void) close(fd); (void) close(fd);
/* Now set the restore settings to match the
* settings used by the save file output routines
*/
reset_restpref();
if (!wizard && !discover) if (!wizard && !discover)
(void) delete_savefile(); (void) delete_savefile();
#ifdef REINCARNATION #ifdef REINCARNATION
@@ -700,6 +731,41 @@ register int fd;
return(1); 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 void
trickery(reason) trickery(reason)
char *reason; char *reason;
@@ -760,37 +826,7 @@ boolean ghostly;
#endif #endif
trickery(trickbuf); trickery(trickbuf);
} }
rest_levl(fd, (boolean)((sfrestinfo.sfi1 & SFI1_RLECOMP) == SFI1_RLECOMP));
#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 */
mread(fd, (genericptr_t)&omoves, sizeof(omoves)); mread(fd, (genericptr_t)&omoves, sizeof(omoves));
mread(fd, (genericptr_t)&upstair, sizeof(stairway)); mread(fd, (genericptr_t)&upstair, sizeof(stairway));
mread(fd, (genericptr_t)&dnstair, sizeof(stairway)); mread(fd, (genericptr_t)&dnstair, sizeof(stairway));
@@ -1051,6 +1087,145 @@ boolean ghostly;
} }
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 #ifdef ZEROCOMP
#define RLESC '\0' /* Leading character for run of RLESC's */ #define RLESC '\0' /* Leading character for run of RLESC's */
@@ -1063,8 +1238,8 @@ static NEARDATA unsigned short inbufsz = 0;
static NEARDATA short inrunlength = -1; static NEARDATA short inrunlength = -1;
static NEARDATA int mreadfd; static NEARDATA int mreadfd;
static int STATIC_OVL int
mgetc() zerocomp_mgetc()
{ {
if (inbufp >= inbufsz) { if (inbufp >= inbufsz) {
inbufsz = read(mreadfd, (genericptr_t)inbuf, sizeof inbuf); inbufsz = read(mreadfd, (genericptr_t)inbuf, sizeof inbuf);
@@ -1079,16 +1254,16 @@ mgetc()
return inbuf[inbufp++]; return inbuf[inbufp++];
} }
void STATIC_OVL void
minit() zerocomp_minit()
{ {
inbufsz = 0; inbufsz = 0;
inbufp = 0; inbufp = 0;
inrunlength = -1; inrunlength = -1;
} }
int STATIC_OVL void
mread(fd, buf, len) zerocomp_mread(fd, buf, len)
int fd; int fd;
genericptr_t buf; genericptr_t buf;
register unsigned len; register unsigned len;
@@ -1101,27 +1276,28 @@ register unsigned len;
inrunlength--; inrunlength--;
*(*((char **)&buf))++ = '\0'; *(*((char **)&buf))++ = '\0';
} else { } else {
register short ch = mgetc(); register short ch = zerocomp_mgetc();
if (ch < 0) return -1; /*readlen;*/ if (ch < 0) {
restoreprocs.mread_flags = -1;
return;
}
if ((*(*(char **)&buf)++ = (char)ch) == RLESC) { if ((*(*(char **)&buf)++ = (char)ch) == RLESC) {
inrunlength = mgetc(); inrunlength = zerocomp_mgetc();
} }
} }
/*readlen++;*/ /*readlen++;*/
} }
return 0; /*readlen;*/
} }
#endif /* ZEROCOMP */
#else /* ZEROCOMP */ STATIC_OVL void
def_minit()
void
minit()
{ {
return; return;
} }
void STATIC_OVL void
mread(fd, buf, len) def_mread(fd, buf, len)
register int fd; register int fd;
register genericptr_t buf; register genericptr_t buf;
register unsigned int len; register unsigned int len;
@@ -1135,6 +1311,10 @@ register unsigned int len;
rlen = read(fd, buf, (unsigned) len); rlen = read(fd, buf, (unsigned) len);
if((unsigned)rlen != len){ if((unsigned)rlen != len){
#endif #endif
if (restoreprocs.mread_flags == 1) { /* means "return anyway" */
restoreprocs.mread_flags = -1;
return;
} else {
pline("Read %d instead of %u bytes.", rlen, len); pline("Read %d instead of %u bytes.", rlen, len);
if(restoring) { if(restoring) {
(void) close(fd); (void) close(fd);
@@ -1142,9 +1322,10 @@ register unsigned int len;
error("Error restoring old game."); error("Error restoring old game.");
} }
panic("Error reading level file."); panic("Error reading level file.");
}
} }
} }
#endif /* ZEROCOMP */
#ifndef GOLDOBJ #ifndef GOLDOBJ
/* /*
* Takes all of the gold objects out of the invent or * Takes all of the gold objects out of the invent or
+313 -167
View File
@@ -1,4 +1,4 @@
/* 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. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -22,9 +22,6 @@ static int count_only;
int dotcnt, dotrow; /* also used in restore */ int dotcnt, dotrow; /* also used in restore */
#endif #endif
#ifdef ZEROCOMP
STATIC_DCL void FDECL(bputc, (int));
#endif
STATIC_DCL void FDECL(savelevchn, (int,int)); STATIC_DCL void FDECL(savelevchn, (int,int));
STATIC_DCL void FDECL(savedamage, (int,int)); STATIC_DCL void FDECL(savedamage, (int,int));
STATIC_DCL void FDECL(saveobjchn, (int,struct obj *,int)); STATIC_DCL void FDECL(saveobjchn, (int,struct obj *,int));
@@ -37,6 +34,44 @@ STATIC_DCL void FDECL(savelev0, (int,XCHAR_P,int));
STATIC_DCL boolean NDECL(swapout_oldest); STATIC_DCL boolean NDECL(swapout_oldest);
STATIC_DCL void FDECL(copyfile, (char *,char *)); STATIC_DCL void FDECL(copyfile, (char *,char *));
#endif /* MFLOPPY */ #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 #ifdef GCC_WARN
static long nulls[10]; static long nulls[10];
#else #else
@@ -140,14 +175,14 @@ dosave0()
#endif #endif
HUP if (iflags.window_inited) { HUP if (iflags.window_inited) {
uncompress(fq_save); nh_uncompress(fq_save);
fd = open_savefile(); fd = open_savefile();
if (fd > 0) { if (fd > 0) {
(void) close(fd); (void) close(fd);
clear_nhwindow(WIN_MESSAGE); clear_nhwindow(WIN_MESSAGE);
There("seems to be an old save file."); There("seems to be an old save file.");
if (yn("Overwrite the old file?") == 'n') { if (yn("Overwrite the old file?") == 'n') {
compress(fq_save); nh_compress(fq_save);
return 0; return 0;
} }
} }
@@ -209,6 +244,7 @@ dosave0()
#endif /* MFLOPPY */ #endif /* MFLOPPY */
store_version(fd); store_version(fd);
store_savefileinfo(fd);
store_plname_in_file(fd); store_plname_in_file(fd);
ustuck_id = (u.ustuck ? u.ustuck->m_id : 0); ustuck_id = (u.ustuck ? u.ustuck->m_id : 0);
#ifdef STEED #ifdef STEED
@@ -269,7 +305,7 @@ dosave0()
/* get rid of current level --jgm */ /* get rid of current level --jgm */
delete_levelfile(ledger_no(&u.uz)); delete_levelfile(ledger_no(&u.uz));
delete_levelfile(0); delete_levelfile(0);
compress(fq_save); nh_compress(fq_save);
return(1); return(1);
} }
@@ -405,6 +441,7 @@ savestateinlock()
(void) write(fd, (genericptr_t) &currlev, sizeof(currlev)); (void) write(fd, (genericptr_t) &currlev, sizeof(currlev));
save_savefile_name(fd); save_savefile_name(fd);
store_version(fd); store_version(fd);
store_savefileinfo(fd);
store_plname_in_file(fd); store_plname_in_file(fd);
ustuck_id = (u.ustuck ? u.ustuck->m_id : 0); ustuck_id = (u.ustuck ? u.ustuck->m_id : 0);
@@ -489,54 +526,7 @@ int mode;
#else #else
bwrite(fd,(genericptr_t) &lev,sizeof(lev)); bwrite(fd,(genericptr_t) &lev,sizeof(lev));
#endif #endif
#ifdef RLECOMP savelevl(fd, (boolean)((sfsaveinfo.sfi1 & SFI1_RLECOMP) == SFI1_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;
for (y = 0; y < ROWNO; y++) {
for (x = 0; x < COLNO; x++) {
prm = &levl[x][y];
if (prm->glyph == rgrm->glyph
&& prm->typ == rgrm->typ
&& prm->seenv == rgrm->seenv
&& prm->horizontal == rgrm->horizontal
&& prm->flags == rgrm->flags
&& prm->lit == rgrm->lit
&& prm->waslit == rgrm->waslit
&& prm->roomno == rgrm->roomno
&& prm->edge == rgrm->edge) {
match++;
if (match > 254) {
match = 254; /* undo this match */
goto writeout;
}
} else {
/* the run has been broken,
* write out run-length encoding */
writeout:
bwrite(fd, (genericptr_t)&match, sizeof(uchar));
bwrite(fd, (genericptr_t)rgrm, sizeof(struct rm));
/* start encoding again. we have at least 1 rm
* in the next run, viz. this one. */
match = 1;
rgrm = prm;
}
}
}
if (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));
#endif /* RLECOMP */
bwrite(fd,(genericptr_t) &monstermoves,sizeof(monstermoves)); bwrite(fd,(genericptr_t) &monstermoves,sizeof(monstermoves));
bwrite(fd,(genericptr_t) &upstair,sizeof(stairway)); bwrite(fd,(genericptr_t) &upstair,sizeof(stairway));
@@ -575,6 +565,202 @@ int mode;
if (mode != FREE_SAVE) bflush(fd); 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 */
rgrm = &levl[0][0]; /* start matching at first rm */
match = 0;
for (y = 0; y < ROWNO; y++) {
for (x = 0; x < COLNO; x++) {
prm = &levl[x][y];
if (prm->glyph == rgrm->glyph
&& prm->typ == rgrm->typ
&& prm->seenv == rgrm->seenv
&& prm->horizontal == rgrm->horizontal
&& prm->flags == rgrm->flags
&& prm->lit == rgrm->lit
&& prm->waslit == rgrm->waslit
&& prm->roomno == rgrm->roomno
&& prm->edge == rgrm->edge) {
match++;
if (match > 254) {
match = 254; /* undo this match */
goto writeout;
}
} else {
/* the run has been broken,
* write out run-length encoding */
writeout:
bwrite(fd, (genericptr_t)&match, sizeof(uchar));
bwrite(fd, (genericptr_t)rgrm, sizeof(struct rm));
/* start encoding again. we have at least 1 rm
* in the next run, viz. this one. */
match = 1;
rgrm = prm;
}
}
}
if (match > 0) {
bwrite(fd, (genericptr_t)&match, sizeof(uchar));
bwrite(fd, (genericptr_t)rgrm, sizeof(struct rm));
}
} else
#endif /* RLECOMP */
bwrite(fd,(genericptr_t) levl,sizeof(levl));
}
/*ARGSUSED*/
void
bufon(fd)
int fd;
{
(*saveprocs.save_bufon)(fd);
return;
}
/*ARGSUSED*/
void
bufoff(fd)
int fd;
{
(*saveprocs.save_bufoff)(fd);
return;
}
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);
}
}
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 #ifdef ZEROCOMP
/* The runs of zero-run compression are flushed after the game state or a /* The runs of zero-run compression are flushed after the game state or a
* level is written out. This adds a couple bytes to a save file, where * level is written out. This adds a couple bytes to a save file, where
@@ -585,7 +771,7 @@ int mode;
*/ */
#define RLESC '\0' /* Leading character for run of LRESC's */ #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 #ifndef ZEROCOMP_BUFSIZ
# define ZEROCOMP_BUFSIZ BUFSZ # define ZEROCOMP_BUFSIZ BUFSZ
@@ -602,7 +788,7 @@ static NEARDATA boolean compressing = FALSE;
}*/ }*/
STATIC_OVL void STATIC_OVL void
bputc(c) zerocomp_bputc(c)
int c; int c;
{ {
#ifdef MFLOPPY #ifdef MFLOPPY
@@ -619,7 +805,7 @@ int c;
/*ARGSUSED*/ /*ARGSUSED*/
void void
bufon(fd) STATIC_OVL zerocomp_bufon(fd)
int fd; int fd;
{ {
compressing = TRUE; compressing = TRUE;
@@ -627,8 +813,8 @@ int fd;
} }
/*ARGSUSED*/ /*ARGSUSED*/
void STATIC_OVL void
bufoff(fd) zerocomp_bufoff(fd)
int fd; int fd;
{ {
if (outbufp) { if (outbufp) {
@@ -640,8 +826,8 @@ int fd;
return; return;
} }
void STATIC_OVL void
bflush(fd) /* flush run and buffer */ zerocomp_bflush(fd) /* flush run and buffer */
register int fd; register int fd;
{ {
bwritefd = fd; bwritefd = fd;
@@ -659,14 +845,14 @@ register int fd;
terminate(EXIT_FAILURE); terminate(EXIT_FAILURE);
else else
#endif #endif
bclose(fd); /* panic (outbufp != 0) */ zerocomp_bclose(fd); /* panic (outbufp != 0) */
} }
outbufp = 0; outbufp = 0;
} }
} }
void STATIC_OVL void
bwrite(fd, loc, num) zerocomp_bwrite(fd, loc, num)
int fd; int fd;
genericptr_t loc; genericptr_t loc;
register unsigned num; register unsigned num;
@@ -697,119 +883,20 @@ register unsigned num;
if (outrunlength >= 0) { /* flush run */ if (outrunlength >= 0) { /* flush run */
flushoutrun(outrunlength); flushoutrun(outrunlength);
} }
bputc(*bp); zerocomp_bputc(*bp);
} }
} }
} }
} }
void void
bclose(fd) zerocomp_bclose(fd)
int fd; int fd;
{ {
bufoff(fd); zerocomp_bufoff(fd);
(void) close(fd); (void) close(fd);
return; 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 */ #endif /* ZEROCOMP */
STATIC_OVL void STATIC_OVL void
@@ -1048,6 +1135,65 @@ register int fd, mode;
pline("Stored %d messages into savefile.", msgcount); pline("Stored %d messages into savefile.", msgcount);
#endif #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... */ /* also called by prscore(); this probably belongs in dungeon.c... */
void void
+1 -1
View File
@@ -106,7 +106,7 @@ int MAIN(int argc, char **argv)
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(); (void) delete_savefile();
else { else {
compress(fqname(SAVEF, SAVEPREFIX, 0)); nh_compress(fqname(SAVEF, SAVEPREFIX, 0));
} }
} }
+1 -1
View File
@@ -117,7 +117,7 @@ main (void)
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(); (void) delete_savefile();
else { else {
compress(fqname(SAVEF, SAVEPREFIX, 0)); nh_compress(fqname(SAVEF, SAVEPREFIX, 0));
} }
} }
} }
+4 -1
View File
@@ -423,9 +423,12 @@ char *argv[];
update_inventory(); update_inventory();
if (discover || wizard) { 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(); (void) delete_savefile();
else {
nh_compress(fqname(SAVEF, SAVEPREFIX, 0));
} }
} }
context.move = 0; context.move = 0;
+3
View File
@@ -282,6 +282,9 @@ WINLIB = $(WINTTYLIB)
# IRIX 4.0.x needs -lsun if NIS (YP) is being used for passwd file lookup # IRIX 4.0.x needs -lsun if NIS (YP) is being used for passwd file lookup
# LIBS = -lsun # LIBS = -lsun
# #
# If ZLIB_COMP is defined in config.h this is necessary to link with zlib.
# LIBS = -lz
#
LIBS = LIBS =
# make NetHack # make NetHack
+1 -1
View File
@@ -287,7 +287,7 @@ char *argv[];
(void) delete_savefile(); (void) delete_savefile();
else { else {
(void) chmod(fq_save,FCMASK); /* back to readable */ (void) chmod(fq_save,FCMASK); /* back to readable */
compress(fq_save); nh_compress(fq_save);
} }
} }
context.move = 0; context.move = 0;
+11 -2
View File
@@ -1,5 +1,5 @@
# SCCS Id: @(#)Makefile.msc 3.5 $Date$ # 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 # NetHack 3.5.x Makefile for MS Visual C++ V6.x and above and MS NMAKE
# #
@@ -127,6 +127,15 @@ RANDOM = $(OBJ)\random.o
PRECOMPHEAD = N # set to Y if you want to use precomp. headers 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 =========== #======= End of Modification Section ===========
#=============================================== #===============================================
@@ -578,7 +587,7 @@ $(NHRES): $(NTSYS)\console.rc $(NTSYS)\NetHack.ico
$(GAMEFILE) : $(ALLOBJ) $(NHRES) $(O)gamedir.tag $(WINDLLS) $(GAMEFILE) : $(ALLOBJ) $(NHRES) $(O)gamedir.tag $(WINDLLS)
@if not exist $(GAMEDIR)\*.* mkdir $(GAMEDIR) @if not exist $(GAMEDIR)\*.* mkdir $(GAMEDIR)
@echo Linking.... @echo Linking....
$(link) $(LFLAGS) user32.lib winmm.lib -out:$@ @<<$(GAME).lnk $(link) $(LFLAGS) $(ZLIB) user32.lib winmm.lib -out:$@ @<<$(GAME).lnk
$(ALLOBJ:^ =^ $(ALLOBJ:^ =^
) $(NHRES) ) $(NHRES)
<< <<
+23 -2
View File
@@ -1,4 +1,4 @@
/* 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) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* Copyright (c) M. Stephenson, 1990, 1991. */ /* Copyright (c) M. Stephenson, 1990, 1991. */
/* Copyright (c) Dean Luick, 1990. */ /* Copyright (c) Dean Luick, 1990. */
@@ -411,11 +411,24 @@ do_rumors()
/* /*
* Use this to explicitly mask out features during version checks. * 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 \ #define IGNORED_FEATURES ( 0L \
| (1L << 12) /* GOLDOBJ */ \ | (1L << 12) /* GOLDOBJ */ \
| (1L << 20) /* EXP_ON_BOTL */ \ | (1L << 20) /* EXP_ON_BOTL */ \
| (1L << 21) /* SCORE_ON_BOTL */ \ | (1L << 21) /* SCORE_ON_BOTL */ \
| (1L << 27) /* ZEROCOMP */ \
| (1L << 28) /* RLECOMP */ \
) )
static void static void
@@ -478,7 +491,9 @@ make_version()
#ifdef SCORE_ON_BOTL #ifdef SCORE_ON_BOTL
| (1L << 21) | (1L << 21)
#endif #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 #ifdef ZEROCOMP
| (1L << 27) | (1L << 27)
#endif #endif
@@ -653,6 +668,9 @@ static const char *build_opts[] = {
#ifdef COMPRESS #ifdef COMPRESS
"data file compression", "data file compression",
#endif #endif
#ifdef ZLIB_COMP
"ZLIB data file compression",
#endif
#ifdef DLB #ifdef DLB
"data librarian", "data librarian",
#endif #endif
@@ -783,6 +801,9 @@ static const char *build_opts[] = {
#endif #endif
#ifdef ZEROCOMP #ifdef ZEROCOMP
"zero-compressed save files", "zero-compressed save files",
#endif
#ifdef RLECOMP
"run-length compression of levl array in save files",
#endif #endif
save_bones_compat_buf, save_bones_compat_buf,
"basic NetHack features" "basic NetHack features"