diff --git a/.gitignore b/.gitignore index f7849967c..f5a18b7e3 100644 --- a/.gitignore +++ b/.gitignore @@ -56,6 +56,7 @@ Makefile.gcc-orig *.lastcodeanalysissucceeded # VS 2017 caches data into the hidden directory .vs .vs +win/win32/vs/obj/* # Win32-specific ignores end .DS_Store # ms-dos diff --git a/doc/Guidebook.mn b/doc/Guidebook.mn index e852ff559..dae3b6713 100644 --- a/doc/Guidebook.mn +++ b/doc/Guidebook.mn @@ -6118,20 +6118,6 @@ the message as the only parameter. MAXPLAYERS\ =\ Limit the maximum number of games that can be running at the same time. .lp -SAVEFORMAT\ =\ A list of up to two save file formats separated by space. -The first format in the list will written as well as read. The second format -will be read only if no save file in the first format exists. -Valid choices are \(lqhistorical\(rq for binary writing of entire structs, -\(lqlendian\(rq for binary writing of each field in little-endian order, -\(lqascii\(rq for writing the save file content in ascii text. -.lp -BONESFORMAT\ =\ A list of up to two bones file formats separated by space. -The first format in the list will written as well as read. The second format -will be read only if no bones files in the first format exist. -Valid choices are \(lqhistorical\(rq for binary writing of entire structs, -\(lqlendian\(rq for binary writing of each field in little-endian order, -\(lqascii\(rq for writing the bones file content in ascii text. -.lp SUPPORT\ =\ A string explaining how to get local support (no default value). .lp RECOVER\ =\ A string explaining how to recover a game on this system diff --git a/doc/Guidebook.tex b/doc/Guidebook.tex index f590cefa3..a54d02b68 100644 --- a/doc/Guidebook.tex +++ b/doc/Guidebook.tex @@ -6768,22 +6768,6 @@ the message as the only parameter. \item[\ib{MAXPLAYERS}] Limit the maximum number of games that can be running at the same time. %.lp -\item[\ib{SAVEFORMAT}] -A list of up to two save file formats separated by space. -The first format in the list will written as well as read. The second format -will be read only if no save file in the first format exists. -Valid choices are ``{\tt historical}'' for binary writing of entire structs, -``{\tt lendian}'' for binary writing of each field in little-endian order, -``{\tt ascii}'' for writing the save file content in ascii text. -%.lp -\item[\ib{BONESFORMAT}] -A list of up to two bones file formats separated by space. -The first format in the list will written as well as read. The second -format will be read only if no bones files in the first format exist. -Valid choices are ``{\tt historical}'' for binary writing of entire structs, -``{\tt lendian}'' for binary writing of each field in little-endian order, -``{\tt ascii}'' for writing the bones file content in ascii text. -%.lp \item[\ib{SUPPORT}] A string explaining how to get local support (no default value). %.lp diff --git a/include/config.h b/include/config.h index 14bfdc2e8..f14273810 100644 --- a/include/config.h +++ b/include/config.h @@ -259,7 +259,7 @@ # ifdef CRASHREPORT # undef CRASHREPORT # endif -# ifdef MSDOS +# if defined(MSDOS) || defined(NOPANICTRACE) # undef PANICTRACE # endif #endif diff --git a/include/decl.h b/include/decl.h index db9042445..54cf2f390 100644 --- a/include/decl.h +++ b/include/decl.h @@ -296,6 +296,9 @@ struct instance_globals_c { short corpsenm_digested; /* monster type being digested, set by gulpum */ /* zap.c */ + /* new */ + boolean converted_savefile_loaded; + boolean havestate; }; @@ -735,7 +738,6 @@ struct instance_globals_o { /* rumors.c */ int oracle_flg; /* -1=>don't use, 0=>need init, 1=>init done */ - unsigned long *oracle_loc; /* uhitm.c */ boolean override_confirmation; /* Used to flag attacks caused by @@ -1169,6 +1171,8 @@ struct instance_globals_saved_n { struct instance_globals_saved_o { /* rumors.c */ unsigned oracle_cnt; /* oracles are handled differently from rumors... */ + unsigned long *oracle_loc; + /* other */ long omoves; /* level timestamp */ }; diff --git a/include/extern.h b/include/extern.h index 63c6800fc..42e47a3d4 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1969,6 +1969,7 @@ extern int dosuspend(void); extern void nt_regularize(char *); extern int(*nt_kbhit)(void); extern void Delay(int); +extern boolean contains_directory(const char *); # ifdef CRASHREPORT struct CRctxt; extern struct CRctxt *ctxp; @@ -1976,7 +1977,6 @@ extern int win32_cr_helper(char, struct CRctxt *, void *, int); extern int win32_cr_gettrace(int, char *, int); extern int *win32_cr_shellexecute(const char *); # endif -extern boolean contains_directory(const char *); #endif /* WIN32 */ #endif /* MICRO || WIN32 */ @@ -2675,7 +2675,6 @@ extern void get_plname_from_file(NHFILE *, char *, boolean) NONNULLARG12; extern int restore_menu(winid); #endif extern boolean lookup_id_mapping(unsigned, unsigned *) NONNULLARG2; -extern int validate(NHFILE *, const char *, boolean) NONNULLARG1; /* extern void reset_restpref(void); */ /* extern void set_restpref(const char *); */ /* extern void set_savepref(const char *); */ @@ -3496,8 +3495,7 @@ extern boolean comp_times(long); #endif extern boolean check_version(struct version_info *, const char *, boolean, unsigned long) NONNULLARG1; -extern boolean uptodate(NHFILE *, const char *, unsigned long) NONNULLARG1; -extern void store_formatindicator(NHFILE *) NONNULLARG1; +extern int uptodate(NHFILE *, const char *, unsigned long) NONNULLARG1; extern void store_version(NHFILE *) NONNULLARG1; extern unsigned long get_feature_notice_ver(char *) NO_NNARGS; extern unsigned long get_current_feature_ver(void); @@ -3505,8 +3503,9 @@ extern const char *copyright_banner_line(int) NONNULL; extern void early_version_info(boolean); extern void dump_version_info(void); extern void store_critical_bytes(NHFILE *) NONNULLARG1; -extern int compare_critical_bytes(NHFILE *); +extern int compare_critical_bytes(NHFILE *, int *, unsigned long) NONNULLARG1; extern int get_critical_size_count(void); +extern int validate(NHFILE *, const char *, boolean) NONNULLARG1; /* ### video.c ### */ diff --git a/include/global.h b/include/global.h index a38c7722b..727929d09 100644 --- a/include/global.h +++ b/include/global.h @@ -569,4 +569,5 @@ typedef enum NHL_pcall_action { NHLpa_impossible } NHL_pcall_action; +#define SFCTOOL_BIT (1UL << 30) /* needed for upcoming savefile handling */ #endif /* GLOBAL_H */ diff --git a/include/hack.h b/include/hack.h index bf50ff3d9..9960d223e 100644 --- a/include/hack.h +++ b/include/hack.h @@ -766,13 +766,6 @@ struct role_filter { }; #define NUM_RACES (5) -enum saveformats { - invalid = 0, - historical = 1, /* entire struct, binary, as-is */ - lendian = 2, /* each field, binary, little-endian */ - ascii = 3 /* each field, ascii text (just proof of concept) */ -}; - struct selectionvar { int wid, hei; boolean bounds_dirty; @@ -899,6 +892,19 @@ typedef struct { #define UTD_SKIP_SANITY1 0x04 #define UTD_SKIP_SAVEFILEINFO 0x08 #define UTD_WITHOUT_WAITSYNCH_PERFILE 0x10 +#define UTD_QUIETLY 0x20 + +/* Values for savefile status */ +#define SF_UPTODATE 0 +#define SF_OUTDATED 1 +#define SF_CRITICAL_BYTE_COUNT_MISMATCH 2 +#define SF_DM_IL32LLP64_ON_ILP32LL64 3 /* Wind x64 savefile on x86 */ +#define SF_DM_I32LP64_ON_ILP32LL64 4 /* Unix 64 savefile on x86 */ +#define SF_DM_ILP32LL64_ON_I32LP64 5 /* x86 savefile on Unix 64 */ +#define SF_DM_ILP32LL64_ON_IL32LLP64 6 /* x86 savefile on Wind x64 */ +#define SF_DM_I32LP64_ON_IL32LLP64 7 /* Unix 64 savefile on Wind x64 */ +#define SF_DM_IL32LLP64_ON_I32LP64 8 /* Wind x64 savefile on Unix 64 */ +#define SF_DM_MISMATCH 9 /* generic savefile byte mismatch */ #define ENTITIES 2 struct valuable_data { @@ -940,28 +946,43 @@ struct xlock_s { boolean magic_key; }; +#define MAX_BMASK 4 + /* NetHack ftypes */ #define NHF_LEVELFILE 1 #define NHF_SAVEFILE 2 #define NHF_BONESFILE 3 /* modes */ -#define READING 0x0 -#define COUNTING 0x1 -#define WRITING 0x2 -#define FREEING 0x4 -#define MAX_BMASK 4 +#define READING 0x0 +#define COUNTING 0x1 +#define WRITING 0x2 +#define FREEING 0x4 +#define CONVERTING 0x08 +#define UNCONVERTING 0x10 +#if 0 /* operations of the various saveXXXchn & co. routines */ #define perform_bwrite(nhfp) ((nhfp)->mode & (COUNTING | WRITING)) #define release_data(nhfp) ((nhfp)->mode & FREEING) +#endif + +/* operations of the various saveXXXchn & co. routines */ +#define update_file(nhfp) ((nhfp)->mode & (COUNTING | WRITING)) +#define release_data(nhfp) ((nhfp)->mode & FREEING) + +enum saveformats { + invalid = 0, + historical = 1, /* entire struct, binary, as-is */ + cnvascii = 2, /* each field, ascii text */ + NUM_SAVEFORMATS +}; /* Content types for fieldlevel files */ struct fieldlevel_content { boolean deflt; /* individual fields */ boolean binary; /* binary rather than text */ - boolean json; /* JSON */ }; -typedef struct { +struct nh_file { int fd; /* for traditional structlevel binary writes */ int mode; /* holds READING, WRITING, or FREEING modes */ int ftype; /* NHF_LEVELFILE, NHF_SAVEFILE, or NHF_BONESFILE */ @@ -978,7 +999,10 @@ typedef struct { FILE *fplog; /* file pointer logfile */ FILE *fpdebug; /* file pointer debug info */ struct fieldlevel_content style; -} NHFILE; + struct nh_file *nhfpconvert; +}; + +typedef struct nh_file NHFILE; /* Monster name articles */ #define ARTICLE_NONE 0 @@ -1534,8 +1558,13 @@ typedef uint32_t mmflags_nht; /* makemon MM_ flags */ #include "nhlua.h" #endif +#if !defined(RECOVER_C) + #include "extern.h" +#include "savefile.h" #include "decl.h" +#endif /* RECOVER_C */ + #endif /* HACK_H */ diff --git a/include/hacklib.h b/include/hacklib.h index 2912035a4..96b6bdf39 100644 --- a/include/hacklib.h +++ b/include/hacklib.h @@ -79,6 +79,8 @@ extern unsigned Strlen_(const char *, const char *, int) NONNULLPTRS; #endif extern int unicodeval_to_utf8str(int, uint8 *, size_t); extern boolean copy_bytes(int, int); +extern const char *datamodel(void); +extern const char *what_datamodel_is_this(int, int, int, int, int); #endif /* HACKLIB_H */ diff --git a/include/savefile.h b/include/savefile.h new file mode 100644 index 000000000..28cd24b23 --- /dev/null +++ b/include/savefile.h @@ -0,0 +1,605 @@ +/* NetHack 3.7 savefile.h $NHDT-Date: 1738638877 2025/02/03 19:14:37 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.1476 $ */ +/* Copyright (c) Michael Allison, 2025. */ +/* NetHack may be freely redistributed. See license for details. */ + +#ifndef SAVEFILE_H +#define SAVEFILE_H + +/* #define SAVEFILE_DEBUGGING */ + +extern void sf_init(void); +/* sfbase.c output functions */ +extern void sfo_aligntyp(NHFILE *, aligntyp *, const char *); +extern void sfo_any(NHFILE *, anything *, const char *); +extern void sfo_boolean(NHFILE *, boolean *, const char *); +extern void sfo_char(NHFILE *, char *, const char *, int); +extern void sfo_genericptr(NHFILE *, genericptr_t *, const char *); +extern void sfo_int16(NHFILE *, int16 *, const char *); +extern void sfo_int32(NHFILE *, int32 *, const char *); +extern void sfo_int64(NHFILE *, int64 *, const char *); +extern void sfo_uchar(NHFILE *, uchar *, const char *); +extern void sfo_uint16(NHFILE *, uint16 *, const char *); +extern void sfo_uint32(NHFILE *, uint32 *, const char *); +extern void sfo_uint64(NHFILE *, uint64 *, const char *); +extern void sfo_size_t(NHFILE *, size_t *, const char *); +extern void sfo_time_t(NHFILE *, time_t *, const char *); + +extern void sfo_arti_info(NHFILE *nhfp, + struct arti_info *d_arti_info, + const char *myname); +extern void sfo_dgn_topology(NHFILE *nhfp, + struct dgn_topology *d_dgn_topology, + const char *myname); +extern void sfo_dungeon(NHFILE *nhfp, struct dungeon *d_dungeon, + const char *myname); +extern void sfo_branch(NHFILE *nhfp, struct branch *d_branch, + const char *myname); +extern void sfo_linfo(NHFILE *nhfp, struct linfo *d_linfo, + const char *myname); +extern void sfo_nhcoord(NHFILE *nhfp, struct nhcoord *d_nhcoord, + const char *myname); +extern void sfo_d_level(NHFILE *nhfp, struct d_level *d_d_level, + const char *myname); +extern void sfo_mapseen_feat(NHFILE *nhfp, + struct mapseen_feat *d_mapseen_feat, + const char *myname); +extern void sfo_mapseen_flags(NHFILE *nhfp, + struct mapseen_flags *d_mapseen_flags, + const char *myname); +extern void sfo_mapseen_rooms(NHFILE *nhfp, + struct mapseen_rooms *d_mapseen_rooms, + const char *myname); +extern void sfo_kinfo(NHFILE *nhfp, + struct kinfo *d_kinfo, + const char *myname); +extern void sfo_engr(NHFILE *, struct engr *, const char *); +extern void sfo_ls_t(NHFILE *, struct ls_t *, const char *); +extern void sfo_bubble(NHFILE *, struct bubble *, const char *); +extern void sfo_mkroom(NHFILE *, struct mkroom *, const char *); +extern void sfo_objclass(NHFILE *, struct objclass *, const char *); +extern void sfo_nhrect(NHFILE *, struct nhrect *, const char *); +extern void sfo_fe(NHFILE *, struct fe *, const char *); +extern void sfo_version_info(NHFILE *, struct version_info *, + const char *); +extern void sfo_context_info(NHFILE *, struct context_info *, + const char *); +extern void sfo_flag(NHFILE *, struct flag *, const char *); +extern void sfo_you(NHFILE *, struct you *, const char *); +extern void sfo_mvitals(NHFILE *, struct mvitals *, const char *); +extern void sfo_q_score(NHFILE *, struct q_score *, const char *); +extern void sfo_spell(NHFILE *, struct spell *, const char *); +extern void sfo_dest_area(NHFILE *, struct dest_area *, const char *); +extern void sfo_levelflags(NHFILE *, struct levelflags *, const char *); +extern void sfo_rm(NHFILE *, struct rm *, const char *); +extern void sfo_cemetery(NHFILE *, struct cemetery *, const char *); +extern void sfo_damage(NHFILE *, struct damage *, const char *); +extern void sfo_stairway(NHFILE *, struct stairway *, const char *); +extern void sfo_obj(NHFILE *, struct obj *, const char *); +extern void sfo_monst(NHFILE *, struct monst *, const char *); +extern void sfo_ebones(NHFILE *, struct ebones *, const char *); +extern void sfo_edog(NHFILE *, struct edog *, const char *); +extern void sfo_egd(NHFILE *, struct egd *, const char *); +extern void sfo_emin(NHFILE *, struct emin *, const char *); +extern void sfo_engr(NHFILE *, struct engr *, const char *); +extern void sfo_epri(NHFILE *, struct epri *, const char *); +extern void sfo_eshk(NHFILE *, struct eshk *, const char *); +extern void sfo_trap(NHFILE *, struct trap *, const char *); +extern void sfo_gamelog_line(NHFILE *, struct gamelog_line *, const char *); +extern void sfo_fruit(NHFILE *, struct fruit *, const char *); +extern void sfo_s_level(NHFILE *, struct s_level *, const char *); +extern void sfo_xint8(NHFILE *, xint8 *, const char *); +extern void sfo_xint16(NHFILE *, xint16 *, const char *); +extern void sfo_schar(NHFILE *, schar *, const char *); +extern void sfo_short(NHFILE *, short *, const char *); +extern void sfo_ushort(NHFILE *, ushort *, const char *); +extern void sfo_int(NHFILE *, int *, const char *); +extern void sfo_unsigned(NHFILE *, unsigned *, const char *); +extern void sfo_long(NHFILE *, long *, const char *); +extern void sfo_ulong(NHFILE *, ulong *, const char *); +/* sfbase.c input functions */ +extern void sfi_addinfo(NHFILE *, const char *, const char *); +extern void sfi_aligntyp(NHFILE *, aligntyp *, const char *); +extern void sfi_any(NHFILE *, anything *, const char *); +extern void sfi_boolean(NHFILE *, boolean *, const char *); +extern void sfi_genericptr(NHFILE *, genericptr_t *, const char *); +extern void sfi_char(NHFILE *, char *, const char *, int); +extern void sfi_int16(NHFILE *, int16 *, const char *); +extern void sfi_int32(NHFILE *, int32 *, const char *); +extern void sfi_int64(NHFILE *, int64 *, const char *); +extern void sfi_uchar(NHFILE *, uchar *, const char *); +extern void sfi_uint16(NHFILE *, uint16 *, const char *); +extern void sfi_uint32(NHFILE *, uint32 *, const char *); +extern void sfi_uint64(NHFILE *, uint64 *, const char *); +extern void sfi_size_t(NHFILE *, size_t *, const char *); +extern void sfi_time_t(NHFILE *, time_t *, const char *); +extern void sfi_arti_info(NHFILE *nhfp, + struct arti_info *d_arti_info, + const char *myname); +extern void sfi_dungeon(NHFILE *nhfp, struct dungeon *d_dungeon, + const char *myname); +extern void sfi_dgn_topology(NHFILE *nhfp, + struct dgn_topology *d_dgn_topology, + const char *myname); +extern void sfi_branch(NHFILE *nhfp, struct branch *d_branch, + const char *myname); +extern void sfi_linfo(NHFILE *nhfp, struct linfo *d_linfo, + const char *myname); +extern void sfi_nhcoord(NHFILE *nhfp, struct nhcoord *d_nhcoord, + const char *myname); +extern void sfi_d_level(NHFILE *nhfp, struct d_level *d_d_level, + const char *myname); +extern void sfi_mapseen_feat(NHFILE *nhfp, + struct mapseen_feat *d_mapseen_feat, + const char *myname); +extern void sfi_mapseen_flags(NHFILE *nhfp, + struct mapseen_flags *d_mapseen_flags, + const char *myname); +extern void sfi_mapseen_rooms(NHFILE *nhfp, + struct mapseen_rooms *d_mapseen_rooms, + const char *myname); +extern void sfi_kinfo(NHFILE *nhfp, + struct kinfo *d_kinfo, + const char *myname); +extern void sfi_engr(NHFILE *, struct engr *, const char *); +extern void sfi_ls_t(NHFILE *, struct ls_t *, const char *); +extern void sfi_bubble(NHFILE *, struct bubble *, const char *); +extern void sfi_mkroom(NHFILE *, struct mkroom *, const char *); +extern void sfi_objclass(NHFILE *, struct objclass *, const char *); +extern void sfi_nhrect(NHFILE *, struct nhrect *, const char *); +extern void sfi_fe(NHFILE *, struct fe *, const char *); +extern void sfi_version_info(NHFILE *, struct version_info *, + const char *); +extern void sfi_context_info(NHFILE *, struct context_info *, + const char *); +extern void sfi_flag(NHFILE *, struct flag *, const char *); +extern void sfi_you(NHFILE *, struct you *, const char *); +extern void sfi_mvitals(NHFILE *, struct mvitals *, const char *); +extern void sfi_q_score(NHFILE *, struct q_score *, const char *); +extern void sfi_spell(NHFILE *, struct spell *, const char *); +extern void sfi_dest_area(NHFILE *, struct dest_area *, const char *); +extern void sfi_levelflags(NHFILE *, struct levelflags *, const char *); +extern void sfi_rm(NHFILE *, struct rm *, const char *); +extern void sfi_cemetery(NHFILE *, struct cemetery *, const char *); +extern void sfi_damage(NHFILE *, struct damage *, const char *); +extern void sfi_stairway(NHFILE *, struct stairway *, const char *); +extern void sfi_obj(NHFILE *, struct obj *, const char *); +extern void sfi_monst(NHFILE *, struct monst *, const char *); +extern void sfi_ebones(NHFILE *, struct ebones *, const char *); +extern void sfi_edog(NHFILE *, struct edog *, const char *); +extern void sfi_egd(NHFILE *, struct egd *, const char *); +extern void sfi_emin(NHFILE *, struct emin *, const char *); +extern void sfi_engr(NHFILE *, struct engr *, const char *); +extern void sfi_epri(NHFILE *, struct epri *, const char *); +extern void sfi_eshk(NHFILE *, struct eshk *, const char *); +extern void sfi_trap(NHFILE *, struct trap *, const char *); +extern void sfi_fruit(NHFILE *, struct fruit *, const char *); +extern void sfi_gamelog_line(NHFILE *, struct gamelog_line *, const char *); +extern void sfi_s_level(NHFILE *, struct s_level *, const char *); +extern void sfi_xint8(NHFILE *, xint8 *, const char *); +extern void sfi_xint16(NHFILE *, xint16 *, const char *); +extern void sfi_schar(NHFILE *, schar *, const char *); +extern void sfi_short(NHFILE *, short *, const char *); +extern void sfi_ushort(NHFILE *, ushort *, const char *); +extern void sfi_int(NHFILE *, int *, const char *); +extern void sfi_unsigned(NHFILE *, unsigned *, const char *); +extern void sfi_long(NHFILE *, long *, const char *); +extern void sfi_ulong(NHFILE *, ulong *, const char *); +#if NH_C < 202300L +#define Sfo_aligntyp(a,b,c) sfo_aligntyp(a, b, c) +#define Sfo_any(a,b,c) sfo_any(a, b, c) +#define Sfo_genericptr(a,b,c) sfo_genericptr(a, b, c) +#define Sfo_coordxy(a,b,c) sfo_int16(a, b, c) +#define Sfo_char(a,b,c,d) sfo_char(a, b, c, d) +#define Sfo_int16(a,b,c) sfo_int16(a, b, c) +#define Sfo_int32(a,b,c) sfo_int32(a, b, c) +#define Sfo_int64(a,b,c) sfo_int64(a, b, c) +#define Sfo_uchar(a,b,c) sfo_uchar(a, b, c) +#define Sfo_uint16(a,b,c) sfo_uint16(a, b, c) +#define Sfo_uint32(a,b,c) sfo_uint32(a, b, c) +#define Sfo_uint64(a,b,c) sfo_uint64(a, b, c) +#define Sfo_size_t(a,b,c) sfo_size_t(a, b, c) +#define Sfo_time_t(a,b,c) sfo_time_t(a, b, c) + +#define Sfo_arti_info(a,b,c) sfo_arti_info(a, b, c) +#define Sfo_dgn_topology(a,b,c) sfo_dgn_topology(a, b, c) +#define Sfo_dungeon(a,b,c) sfo_dungeon(a, b, c) +#define Sfo_branch(a,b,c) sfo_branch(a, b, c) +#define Sfo_linfo(a,b,c) sfo_linfo(a, b, c) +#define Sfo_nhcoord(a,b,c) sfo_nhcoord(a, b, c) +#define Sfo_d_level(a,b,c) sfo_d_level(a, b, c) +#define Sfo_mapseen_feat(a,b,c) sfo_mapseen_feat(a, b, c) +#define Sfo_mapseen_flags(a,b,c) sfo_mapseen_flags(a, b, c) +#define Sfo_mapseen_rooms(a,b,c) sfo_mapseen_rooms(a, b, c) +#define Sfo_kinfo(a,b,c) sfo_kinfo(a, b, c) +#define Sfo_engr(a,b,c) sfo_engr(a, b, c) +#define Sfo_ls_t(a,b,c) sfo_ls_t(a, b, c) +#define Sfo_bubble(a,b,c) sfo_bubble(a, b, c) +#define Sfo_mkroom(a,b,c) sfo_mkroom(a, b, c) +#define Sfo_objclass(a,b,c) sfo_objclass(a, b, c) +#define Sfo_nhrect(a,b,c) sfo_nhrect(a, b, c) +#define Sfo_fe(a,b,c) sfo_fe(a, b, c) +#define Sfo_version_info(a,b,c) sfo_version_info(a, b, c) +#define Sfo_context_info(a,b,c) sfo_context_info(a, b, c) +#define Sfo_flag(a,b,c) sfo_flag(a, b, c) +#define Sfo_you(a,b,c) sfo_you(a, b, c) +#define Sfo_mvitals(a,b,c) sfo_mvitals(a, b, c) +#define Sfo_q_score(a,b,c) sfo_q_score(a, b, c) +#define Sfo_spell(a,b,c) sfo_spell(a, b, c) +#define Sfo_dest_area(a,b,c) sfo_dest_area(a, b, c) +#define Sfo_levelflags(a,b,c) sfo_levelflags(a, b, c) +#define Sfo_rm(a,b,c) sfo_rm(a, b, c) +#define Sfo_cemetery(a,b,c) sfo_cemetery(a, b, c) +#define Sfo_damage(a,b,c) sfo_damage(a, b, c) +#define Sfo_stairway(a,b,c) sfo_stairway(a, b, c) +#define Sfo_obj(a,b,c) sfo_obj(a, b, c) +#define Sfo_monst(a,b,c) sfo_monst(a, b, c) +#define Sfo_ebones(a,b,c) sfo_ebones(a, b, c) +#define Sfo_edog(a,b,c) sfo_edog(a, b, c) +#define Sfo_egd(a,b,c) sfo_egd(a, b, c) +#define Sfo_emin(a,b,c) sfo_emin(a, b, c) +#define Sfo_engr(a,b,c) sfo_engr(a, b, c) +#define Sfo_epri(a,b,c) sfo_epri(a, b, c) +#define Sfo_eshk(a,b,c) sfo_eshk(a, b, c) +#define Sfo_trap(a,b,c) sfo_trap(a, b, c) +#define Sfo_gamelog_line(a,b,c) sfo_gamelog_line(a, b, c) +#define Sfo_fruit(a,b,c) sfo_fruit(a, b, c) +#define Sfo_s_level(a,b,c) sfo_s_level(a, b, c) +#define Sfo_schar(a,b,c) sfo_schar(a, b, c); +#define Sfo_short(a, b, c) sfo_short(a, b, c) +#define Sfo_ushort(a, b, c) sfo_ushort(a, b, c) +#define Sfo_int(a, b, c) sfo_int(a, b, c) +#define Sfo_unsigned(a, b, c) sfo_unsigned(a, b, c) +#define Sfo_long(a,b,c) sfo_long(a, b, c); +#define Sfo_ulong(a,b,c) sfo_ulong(a, b, c); +#define Sfo_boolean(a,b,c) sfo_boolean(a, b, c); +#define Sfo_xint8(a, b, c) sfo_xint8(a, b, c); +#define Sfo_xint16(a, b, c) sfo_xint16(a, b, c) +/* sfbase.c input functions */ +#define Sfi_addinfo(a,b,c) sfi_addinfo(a, b, c) +#define Sfi_aligntyp(a,b,c) sfi_aligntyp(a, b, c) +#define Sfi_any(a,b,c) sfi_any(a, b, c) +#define Sfi_genericptr(a,b,c) sfi_genericptr(a, b, c) +#define Sfi_coordxy(a,b,c) sfi_int16(a, b, c) +#define Sfi_char(a,b,c,d) sfi_char(a, b, c, d) +#define Sfi_int16(a,b,c) sfi_int16(a, b, c) +#define Sfi_int32(a,b,c) sfi_int32(a, b, c) +#define Sfi_int64(a,b,c) sfi_int64(a, b, c) +#define Sfi_uchar(a,b,c) sfi_uchar(a, b, c) +#define Sfi_uint16(a,b,c) sfi_uint16(a, b, c) +#define Sfi_uint32(a,b,c) sfi_uint32(a, b, c) +#define Sfi_uint64(a,b,c) sfi_uint64(a, b, c) +#define Sfi_size_t(a,b,c) sfi_size_t(a, b, c) +#define Sfi_time_t(a,b,c) sfi_time_t(a, b, c) +#define Sfi_arti_info(a,b,c) sfi_arti_info(a, b, c) +#define Sfi_dungeon(a,b,c) sfi_dungeon(a, b, c) +#define Sfi_dgn_topology(a,b,c) sfi_dgn_topology(a, b, c) +#define Sfi_branch(a,b,c) sfi_branch(a, b, c) +#define Sfi_linfo(a,b,c) sfi_linfo(a, b, c) +#define Sfi_nhcoord(a,b,c) sfi_nhcoord(a, b, c) +#define Sfi_d_level(a,b,c) sfi_d_level(a, b, c) +#define Sfi_mapseen_feat(a,b,c) sfi_mapseen_feat(a, b, c) +#define Sfi_mapseen_flags(a,b,c) sfi_mapseen_flags(a, b, c) +#define Sfi_mapseen_rooms(a,b,c) sfi_mapseen_rooms(a, b, c) +#define Sfi_kinfo(a,b,c) sfi_kinfo(a, b, c) +#define Sfi_engr(a,b,c) sfi_engr(a, b, c) +#define Sfi_ls_t(a,b,c) sfi_ls_t(a, b, c) +#define Sfi_bubble(a,b,c) sfi_bubble(a, b, c) +#define Sfi_mkroom(a,b,c) sfi_mkroom(a, b, c) +#define Sfi_objclass(a,b,c) sfi_objclass(a, b, c) +#define Sfi_nhrect(a,b,c) sfi_nhrect(a, b, c) +#define Sfi_fe(a,b,c) sfi_fe(a, b, c) +#define Sfi_version_info(a,b,c) sfi_version_info(a, b, c) +#define Sfi_context_info(a,b,c) sfi_context_info(a, b, c) +#define Sfi_flag(a,b,c) sfi_flag(a, b, c) +#define Sfi_you(a,b,c) sfi_you(a, b, c) +#define Sfi_mvitals(a,b,c) sfi_mvitals(a, b, c) +#define Sfi_q_score(a,b,c) sfi_q_score(a, b, c) +#define Sfi_spell(a,b,c) sfi_spell(a, b, c) +#define Sfi_dest_area(a,b,c) sfi_dest_area(a, b, c) +#define Sfi_levelflags(a,b,c) sfi_levelflags(a, b, c) +#define Sfi_rm(a,b,c) sfi_rm(a, b, c) +#define Sfi_cemetery(a,b,c) sfi_cemetery(a, b, c) +#define Sfi_damage(a,b,c) sfi_damage(a, b, c) +#define Sfi_stairway(a,b,c) sfi_stairway(a, b, c) +#define Sfi_obj(a,b,c) sfi_obj(a, b, c) +#define Sfi_monst(a,b,c) sfi_monst(a, b, c) +#define Sfi_ebones(a,b,c) sfi_ebones(a, b, c) +#define Sfi_edog(a,b,c) sfi_edog(a, b, c) +#define Sfi_egd(a,b,c) sfi_egd(a, b, c) +#define Sfi_emin(a,b,c) sfi_emin(a, b, c) +#define Sfi_engr(a,b,c) sfi_engr(a, b, c) +#define Sfi_epri(a,b,c) sfi_epri(a, b, c) +#define Sfi_eshk(a,b,c) sfi_eshk(a, b, c) +#define Sfi_trap(a,b,c) sfi_trap(a, b, c) +#define Sfi_fruit(a,b,c) sfi_fruit(a, b, c) +#define Sfi_gamelog_line(a,b,c) sfi_gamelog_line(a, b, c) +#define Sfi_s_level(a,b,c) sfi_s_level(a, b, c) +#define Sfi_schar(a,b,c) sfi_schar(a, b, c); +#define Sfi_short(a, b, c) sfi_short(a, b, c) +#define Sfi_ushort(a, b, c) sfi_ushort(a, b, c) +#define Sfi_int(a, b, c) sfi_int(a, b, c); +#define Sfi_unsigned(a, b, c) sfi_unsigned(a, b, c); +#define Sfi_long(a,b,c) sfi_long(a, b, c); +#define Sfi_ulong(a,b,c) sfi_ulong(a, b, c); +#define Sfi_boolean(a,b,c) sfi_boolean(a, b, c); +#define Sfi_xint8(a, b, c) sfi_xint8(a, b, c); +#define Sfi_xint16(a, b, c) sfi_xint16(a, b, c); +#else + +#define sfo(nhfp, dt, tag) \ + _Generic( (dt), \ + anything * : sfo_any, \ + int16_t * : sfo_int16, \ + int32_t * : sfo_int32, \ + int64_t * : sfo_int64, \ + uchar * : sfo_uchar, \ + uint16_t * : sfo_uint16, \ + uint32_t * : sfo_uint32, \ + uint64_t * : sfo_uint64, \ + long * : sfo_long, \ + unsigned long * : sfo_ulong, \ + xint8 * : sfo_xint8, \ + struct arti_info * : sfo_arti_info, \ + struct nhrect * : sfo_nhrect, \ + struct branch * : sfo_branch, \ + struct bubble * : sfo_bubble, \ + struct cemetery * : sfo_cemetery, \ + struct context_info * : sfo_context_info, \ + coord * : sfo_nhcoord, \ + struct damage * : sfo_damage, \ + struct dgn_topology * : sfo_dgn_topology, \ + dungeon * : sfo_dungeon, \ + d_level * : sfo_d_level, \ + struct levelflags * : sfo_levelflags, \ + light_source * : sfo_ls_t, \ + struct dest_area * : sfo_dest_area, \ + struct ebones * : sfo_ebones, \ + struct edog * : sfo_edog, \ + struct egd * : sfo_egd, \ + struct emin * : sfo_emin, \ + struct engr * : sfo_engr, \ + struct epri * : sfo_epri, \ + struct eshk * : sfo_eshk, \ + struct fe * : sfo_fe, \ + struct flag * : sfo_flag, \ + struct fruit * : sfo_fruit, \ + struct gamelog_line * : sfo_gamelog_line, \ + struct kinfo * : sfo_kinfo, \ + struct linfo * : sfo_linfo, \ + struct mapseen_feat * : sfo_mapseen_feat, \ + struct mapseen_flags *: sfo_mapseen_flags, \ + struct mapseen_rooms *: sfo_mapseen_rooms, \ + struct mkroom * : sfo_mkroom, \ + struct monst * : sfo_monst, \ + struct mvitals * : sfo_mvitals, \ + struct obj * : sfo_obj, \ + struct objclass * : sfo_objclass, \ + struct q_score * : sfo_q_score, \ + struct rm * : sfo_rm, \ + struct spell * : sfo_spell, \ + struct stairway * : sfo_stairway, \ + struct s_level * : sfo_s_level, \ + struct trap * : sfo_trap, \ + struct version_info * : sfo_version_info, \ + struct you * : sfo_you \ + ) (nhfp, dt, tag) + +/* struct container * : sfo_container, */ +/* struct mapseen * : sfo_mapseen, */ +/* struct mextra * : sfo_mextra, */ +/* struct oextra * : sfo_oextra, */ +/* struct permonst * : sfo_permonst, */ + +#define sfi(nhfp, dt, tag) \ + _Generic( (dt), \ + anything * : sfi_any, \ + int16_t * : sfi_int16, \ + int32_t * : sfi_int32, \ + int64_t * : sfi_int64, \ + uchar * : sfi_uchar, \ + uint16_t * : sfi_uint16, \ + uint32_t * : sfi_uint32, \ + uint64_t * : sfi_uint64, \ + long * : sfi_long, \ + unsigned long * : sfi_ulong, \ + xint8 * : sfi_xint8, \ + struct arti_info * : sfi_arti_info, \ + struct nhrect * : sfi_nhrect, \ + struct branch * : sfi_branch, \ + struct bubble * : sfi_bubble, \ + struct cemetery * : sfi_cemetery, \ + struct context_info * : sfi_context_info, \ + coord * : sfi_nhcoord, \ + struct damage * : sfi_damage, \ + struct dgn_topology * : sfi_dgn_topology, \ + dungeon * : sfi_dungeon, \ + d_level * : sfi_d_level, \ + struct levelflags * : sfi_levelflags, \ + light_source * : sfi_ls_t, \ + struct dest_area * : sfi_dest_area, \ + struct ebones * : sfi_ebones, \ + struct edog * : sfi_edog, \ + struct egd * : sfi_egd, \ + struct emin * : sfi_emin, \ + struct engr * : sfi_engr, \ + struct epri * : sfi_epri, \ + struct eshk * : sfi_eshk, \ + struct fe * : sfi_fe, \ + struct flag * : sfi_flag, \ + struct fruit * : sfi_fruit, \ + struct gamelog_line * : sfi_gamelog_line, \ + struct kinfo * : sfi_kinfo, \ + struct linfo * : sfi_linfo, \ + struct mapseen_feat * : sfi_mapseen_feat, \ + struct mapseen_flags *: sfi_mapseen_flags, \ + struct mapseen_rooms *: sfi_mapseen_rooms, \ + struct mkroom * : sfi_mkroom, \ + struct monst * : sfi_monst, \ + struct mvitals * : sfi_mvitals, \ + struct obj * : sfi_obj, \ + struct objclass * : sfi_objclass, \ + struct q_score * : sfi_q_score, \ + struct rm * : sfi_rm, \ + struct spell * : sfi_spell, \ + struct stairway * : sfi_stairway, \ + struct s_level * : sfi_s_level, \ + struct trap * : sfi_trap, \ + struct version_info * : sfi_version_info, \ + struct you * : sfi_you \ + ) (nhfp, dt, tag) + +/* char * : sfo_char, */ +/* char * : sfi_char, */ +/* struct container * : sfi_container, */ +/* struct mapseen * : sfi_mapseen, */ +/* struct mextra * : sfi_mextra, */ +/* struct oextra * : sfi_oextra, */ +/* struct permonst * : sfi_permonst, */ + +#define Sfo_any(a,b,c) sfo(a, b, c) +#define Sfo_aligntyp(a,b,c) sfo(a, b, c) +#define Sfo_genericptr(a,b,c) sfo(a, b, c) +#define Sfo_coordxy(a,b,c) sfo(a, b, c) +#define Sfo_int16(a,b,c) sfo(a, b, c) +#define Sfo_int32(a,b,c) sfo(a, b, c) +#define Sfo_int64(a,b,c) sfo(a, b, c) +#define Sfo_uchar(a,b,c) sfo(a, b, c) +#define Sfo_unsigned(a,b,c) sfo(a, b, c) +#define Sfo_uchar(a,b,c) sfo(a, b, c) +#define Sfo_uint16(a,b,c) sfo(a, b, c) +#define Sfo_uint32(a,b,c) sfo(a, b, c) +#define Sfo_uint64(a,b,c) sfo(a, b, c) +#define Sfo_size_t(a,b,c) sfo(a, b, c) +#define Sfo_time_t(a,b,c) sfo(a, b, c) + +#define Sfo_arti_info(a,b,c) sfo(a, b, c) +#define Sfo_dgn_topology(a,b,c) sfo(a, b, c) +#define Sfo_dungeon(a,b,c) sfo(a, b, c) +#define Sfo_branch(a,b,c) sfo(a, b, c) +#define Sfo_linfo(a,b,c) sfo(a, b, c) +#define Sfo_nhcoord(a,b,c) sfo(a, b, c) +#define Sfo_d_level(a,b,c) sfo(a, b, c) +#define Sfo_mapseen_feat(a,b,c) sfo(a, b, c) +#define Sfo_mapseen_flags(a,b,c) sfo(a, b, c) +#define Sfo_mapseen_rooms(a,b,c) sfo(a, b, c) +#define Sfo_kinfo(a,b,c) sfo(a, b, c) +#define Sfo_engr(a,b,c) sfo(a, b, c) +#define Sfo_ls_t(a,b,c) sfo(a, b, c) +#define Sfo_bubble(a,b,c) sfo(a, b, c) +#define Sfo_mkroom(a,b,c) sfo(a, b, c) +#define Sfo_objclass(a,b,c) sfo(a, b, c) +#define Sfo_nhrect(a,b,c) sfo(a, b, c) +#define Sfo_fe(a,b,c) sfo(a, b, c) +#define Sfo_version_info(a,b,c) sfo(a, b, c) +#define Sfo_context_info(a,b,c) sfo(a, b, c) +#define Sfo_flag(a,b,c) sfo(a, b, c) +#define Sfo_you(a,b,c) sfo(a, b, c) +#define Sfo_mvitals(a,b,c) sfo(a, b, c) +#define Sfo_q_score(a,b,c) sfo(a, b, c) +#define Sfo_spell(a,b,c) sfo(a, b, c) +#define Sfo_dest_area(a,b,c) sfo(a, b, c) +#define Sfo_levelflags(a,b,c) sfo(a, b, c) +#define Sfo_rm(a,b,c) sfo(a, b, c) +#define Sfo_cemetery(a,b,c) sfo(a, b, c) +#define Sfo_damage(a,b,c) sfo(a, b, c) +#define Sfo_stairway(a,b,c) sfo(a, b, c) +#define Sfo_obj(a,b,c) sfo(a, b, c) +#define Sfo_monst(a,b,c) sfo(a, b, c) +#define Sfo_ebones(a,b,c) sfo(a, b, c) +#define Sfo_edog(a,b,c) sfo(a, b, c) +#define Sfo_egd(a,b,c) sfo(a, b, c) +#define Sfo_emin(a,b,c) sfo(a, b, c) +#define Sfo_engr(a,b,c) sfo(a, b, c) +#define Sfo_epri(a,b,c) sfo(a, b, c) +#define Sfo_eshk(a,b,c) sfo(a, b, c) +#define Sfo_trap(a,b,c) sfo(a, b, c) +#define Sfo_gamelog_line(a,b,c) sfo(a, b, c) +#define Sfo_fruit(a,b,c) sfo(a, b, c) +#define Sfo_s_level(a,b,c) sfo(a, b, c) +#define Sfo_short(a, b, c) sfo(a, b, c) +#define Sfo_ushort(a, b, c) sfo(a, b, c) +#define Sfo_int(a, b, c) sfo(a, b, c) +#define Sfo_unsigned(a, b, c) sfo(a, b, c) +#define Sfo_long(a,b,c) sfo(a, b, c) +#define Sfo_ulong(a,b,c) sfo(a, b, c) +#define Sfo_xint8(a, b, c) sfo(a, b, c) +#define Sfo_xint16(a, b, c) sfo(a, b, c) +/* not in _Generic */ +#define Sfo_char(a,b,c,d) sfo_char(a, b, c, d) +#define Sfo_boolean(a,b,c) sfo_boolean(a, b, c) +#define Sfo_schar(a,b,c) sfo_schar(a, b, c) +/* sfbase.c input functions */ +#define Sfi_addinfo(a,b,c) sfi(a, b, c) +#define Sfi_aligntyp(a,b,c) sfi(a, b, c) +#define Sfi_any(a,b,c) sfi(a, b, c) +#define Sfi_genericptr(a,b,c) sfi(a, b, c) +#define Sfi_coordxy(a,b,c) sfi(a, b, c) +#define Sfi_int16(a,b,c) sfi(a, b, c) +#define Sfi_int32(a,b,c) sfi(a, b, c) +#define Sfi_int64(a,b,c) sfi(a, b, c) +#define Sfi_uchar(a,b,c) sfi(a, b, c) +#define Sfi_uint16(a,b,c) sfi(a, b, c) +#define Sfi_uint32(a,b,c) sfi(a, b, c) +#define Sfi_uint64(a,b,c) sfi(a, b, c) +#define Sfi_size_t(a,b,c) sfi(a, b, c) +#define Sfi_time_t(a,b,c) sfi(a, b, c) +#define Sfi_arti_info(a,b,c) sfi(a, b, c) +#define Sfi_dungeon(a,b,c) sfi(a, b, c) +#define Sfi_dgn_topology(a,b,c) sfi(a, b, c) +#define Sfi_branch(a,b,c) sfi(a, b, c) +#define Sfi_linfo(a,b,c) sfi(a, b, c) +#define Sfi_nhcoord(a,b,c) sfi(a, b, c) +#define Sfi_d_level(a,b,c) sfi(a, b, c) +#define Sfi_mapseen_feat(a,b,c) sfi(a, b, c) +#define Sfi_mapseen_flags(a,b,c) sfi(a, b, c) +#define Sfi_mapseen_rooms(a,b,c) sfi(a, b, c) +#define Sfi_kinfo(a,b,c) sfi(a, b, c) +#define Sfi_engr(a,b,c) sfi(a, b, c) +#define Sfi_ls_t(a,b,c) sfi(a, b, c) +#define Sfi_bubble(a,b,c) sfi(a, b, c) +#define Sfi_mkroom(a,b,c) sfi(a, b, c) +#define Sfi_objclass(a,b,c) sfi(a, b, c) +#define Sfi_nhrect(a,b,c) sfi(a, b, c) +#define Sfi_fe(a,b,c) sfi(a, b, c) +#define Sfi_version_info(a,b,c) sfi(a, b, c) +#define Sfi_context_info(a,b,c) sfi(a, b, c) +#define Sfi_flag(a,b,c) sfi(a, b, c) +#define Sfi_you(a,b,c) sfi(a, b, c) +#define Sfi_mvitals(a,b,c) sfi(a, b, c) +#define Sfi_q_score(a,b,c) sfi(a, b, c) +#define Sfi_spell(a,b,c) sfi(a, b, c) +#define Sfi_dest_area(a,b,c) sfi(a, b, c) +#define Sfi_levelflags(a,b,c) sfi(a, b, c) +#define Sfi_rm(a,b,c) sfi(a, b, c) +#define Sfi_cemetery(a,b,c) sfi(a, b, c) +#define Sfi_damage(a,b,c) sfi(a, b, c) +#define Sfi_stairway(a,b,c) sfi(a, b, c) +#define Sfi_obj(a,b,c) sfi(a, b, c) +#define Sfi_monst(a,b,c) sfi(a, b, c) +#define Sfi_ebones(a,b,c) sfi(a, b, c) +#define Sfi_edog(a,b,c) sfi(a, b, c) +#define Sfi_egd(a,b,c) sfi(a, b, c) +#define Sfi_emin(a,b,c) sfi(a, b, c) +#define Sfi_engr(a,b,c) sfi(a, b, c) +#define Sfi_epri(a,b,c) sfi(a, b, c) +#define Sfi_eshk(a,b,c) sfi(a, b, c) +#define Sfi_trap(a,b,c) sfi(a, b, c) +#define Sfi_fruit(a,b,c) sfi(a, b, c) +#define Sfi_gamelog_line(a,b,c) sfi(a, b, c) +#define Sfi_s_level(a,b,c) sfi(a, b, c) +#define Sfi_short(a, b, c) sfi(a, b, c) +#define Sfi_ushort(a, b, c) sfi(a, b, c) +#define Sfi_int(a,b,c) sfi(a, b, c) +#define Sfi_unsigned(a, b, c) sfi(a, b, c) +#define Sfi_long(a,b,c) sfi(a, b, c) +#define Sfi_ulong(a,b,c) sfi(a, b, c) +#define Sfi_xint8(a, b, c) sfi(a, b, c) +#define Sfi_xint16(a, b, c) sfi(a, b, c) +/* not in _Generic */ +#define Sfi_char(a,b,c,d) sfi_char(a, b, c, d) +#define Sfi_boolean(a,b,c) sfi_boolean(a, b, c) +#define Sfi_schar(a,b,c) sfi_schar(a, b, c) +#endif + +#endif /* SAVEFILE_H */ + diff --git a/include/sfprocs.h b/include/sfprocs.h new file mode 100644 index 000000000..661d1a40a --- /dev/null +++ b/include/sfprocs.h @@ -0,0 +1,199 @@ +/* NetHack 3.6 sfprocs.h Tue Nov 6 19:38:48 2018 */ +/* Copyright (c) NetHack Development Team 2025. */ +/* NetHack may be freely redistributed. See license for details. */ + +#ifndef SFPROCS_H +#define SFPROCS_H + +#define NHTYPE_SIMPLE 1 +#define NHTYPE_COMPLEX 2 + +#define SF_PROTO(dtyp) \ + extern void sfo_##dtyp(NHFILE *, dtyp *, const char *); \ + extern void sfi_##dtyp(NHFILE *, dtyp *, const char *); \ + extern void sfo_x_##dtyp(NHFILE *, dtyp *, const char *); \ + extern void sfi_x_##dtyp(NHFILE *, dtyp *, const char *) +#define SF_PROTO_C(keyw, dtyp) \ + extern void sfo_##dtyp(NHFILE *, keyw dtyp *, const char *); \ + extern void sfi_##dtyp(NHFILE *, keyw dtyp *, const char *); \ + extern void sfo_x_##dtyp(NHFILE *, keyw dtyp *, const char *); \ + extern void sfi_x_##dtyp(NHFILE *, keyw dtyp *, const char *) +#define SF_PROTO_X(xxx, dtyp) \ + extern void sfo_##dtyp(NHFILE *, xxx *, const char *, int bfsz); \ + extern void sfi_##dtyp(NHFILE *, xxx *, const char *, int bfsz); \ + extern void sfo_x_##dtyp(NHFILE *, xxx *, const char *, int bfsz); \ + extern void sfi_x_##dtyp(NHFILE *, xxx *, const char *, int bfsz) + +SF_PROTO_C(struct, arti_info); +SF_PROTO_C(struct, nhrect); +SF_PROTO_C(struct, branch); +SF_PROTO_C(struct, bubble); +SF_PROTO_C(struct, cemetery); +SF_PROTO_C(struct, context_info); +SF_PROTO_C(struct, nhcoord); +SF_PROTO_C(struct, damage); +SF_PROTO_C(struct, dest_area); +SF_PROTO_C(struct, dgn_topology); +SF_PROTO_C(struct, dungeon); +SF_PROTO_C(struct, d_level); +SF_PROTO_C(struct, ebones); +SF_PROTO_C(struct, edog); +SF_PROTO_C(struct, egd); +SF_PROTO_C(struct, emin); +SF_PROTO_C(struct, engr); +SF_PROTO_C(struct, epri); +SF_PROTO_C(struct, eshk); +SF_PROTO_C(struct, fe); +SF_PROTO_C(struct, flag); +SF_PROTO_C(struct, fruit); +SF_PROTO_C(struct, gamelog_line); +SF_PROTO_C(struct, kinfo); +SF_PROTO_C(struct, levelflags); +SF_PROTO_C(struct, ls_t); +SF_PROTO_C(struct, linfo); +SF_PROTO_C(struct, mapseen_feat); +SF_PROTO_C(struct, mapseen_flags); +SF_PROTO_C(struct, mapseen_rooms); +SF_PROTO_C(struct, mkroom); +SF_PROTO_C(struct, monst); +SF_PROTO_C(struct, mvitals); +SF_PROTO_C(struct, obj); +SF_PROTO_C(struct, objclass); +SF_PROTO_C(struct, q_score); +SF_PROTO_C(struct, rm); +SF_PROTO_C(struct, spell); +SF_PROTO_C(struct, stairway); +SF_PROTO_C(struct, s_level); +SF_PROTO_C(struct, trap); +SF_PROTO_C(struct, version_info); +SF_PROTO_C(struct, you); +SF_PROTO_C(union, any); +SF_PROTO(int16); +SF_PROTO(int32); +SF_PROTO(int64); +SF_PROTO(uchar); +SF_PROTO(uint16); +SF_PROTO(uint32); +SF_PROTO(uint64); +SF_PROTO(long); +SF_PROTO(ulong); +SF_PROTO(xint8); +SF_PROTO(boolean); +SF_PROTO(schar); +SF_PROTO(aligntyp); +SF_PROTO(genericptr); +SF_PROTO(size_t); +SF_PROTO(time_t); +SF_PROTO(int); +SF_PROTO(unsigned); +SF_PROTO(coordxy); +SF_PROTO(short); +SF_PROTO(xint16); +SF_PROTO(ushort); +SF_PROTO_X(uint8_t, bitfield); +SF_PROTO_X(char, char); + +#undef SF_PROTO +#undef SF_PROTO_C +#undef SF_PROTO_X + +#define SF_ENTRY(dtyp) \ + void (*sf_##dtyp)(NHFILE *, dtyp *, const char *) +#define SF_ENTRY_C(keyw, dtyp) \ + void (*sf_##dtyp)(NHFILE *, keyw dtyp *, const char *) +#define SF_ENTRY_X(xxx, dtyp) \ + void (*sf_##dtyp)(NHFILE *, xxx *, const char *, int bfsz) + +struct sf_procs { + SF_ENTRY_C(struct, arti_info); + SF_ENTRY_C(struct, nhrect); + SF_ENTRY_C(struct, branch); + SF_ENTRY_C(struct, bubble); + SF_ENTRY_C(struct, cemetery); + SF_ENTRY_C(struct, context_info); + SF_ENTRY_C(struct, nhcoord); + SF_ENTRY_C(struct, damage); + SF_ENTRY_C(struct, dest_area); + SF_ENTRY_C(struct, dgn_topology); + SF_ENTRY_C(struct, dungeon); + SF_ENTRY_C(struct, d_level); + SF_ENTRY_C(struct, ebones); + SF_ENTRY_C(struct, edog); + SF_ENTRY_C(struct, egd); + SF_ENTRY_C(struct, emin); + SF_ENTRY_C(struct, engr); + SF_ENTRY_C(struct, epri); + SF_ENTRY_C(struct, eshk); + SF_ENTRY_C(struct, fe); + SF_ENTRY_C(struct, flag); + SF_ENTRY_C(struct, fruit); + SF_ENTRY_C(struct, gamelog_line); + SF_ENTRY_C(struct, kinfo); + SF_ENTRY_C(struct, levelflags); + SF_ENTRY_C(struct, ls_t); + SF_ENTRY_C(struct, linfo); + SF_ENTRY_C(struct, mapseen_feat); + SF_ENTRY_C(struct, mapseen_flags); + SF_ENTRY_C(struct, mapseen_rooms); + SF_ENTRY_C(struct, mkroom); + SF_ENTRY_C(struct, monst); + SF_ENTRY_C(struct, mvitals); + SF_ENTRY_C(struct, obj); + SF_ENTRY_C(struct, objclass); + SF_ENTRY_C(struct, q_score); + SF_ENTRY_C(struct, rm); + SF_ENTRY_C(struct, spell); + SF_ENTRY_C(struct, stairway); + SF_ENTRY_C(struct, s_level); + SF_ENTRY_C(struct, trap); + SF_ENTRY_C(struct, version_info); + SF_ENTRY_C(struct, you); + SF_ENTRY_C(union, any); + + SF_ENTRY(aligntyp); + SF_ENTRY(boolean); + SF_ENTRY(coordxy); + SF_ENTRY(genericptr); + SF_ENTRY(int); + SF_ENTRY(int16); + SF_ENTRY(int32); + SF_ENTRY(int64); + SF_ENTRY(long); + SF_ENTRY(schar); + SF_ENTRY(short); + SF_ENTRY(size_t); + SF_ENTRY(time_t); + SF_ENTRY(uchar); + SF_ENTRY(uint16); + SF_ENTRY(uint32); + SF_ENTRY(uint64); + SF_ENTRY(ulong); + SF_ENTRY(unsigned); + SF_ENTRY(ushort); + SF_ENTRY(xint16); + SF_ENTRY(xint8); + SF_ENTRY_X(char, char); + SF_ENTRY_X(uint8_t, bitfield); +}; + +#undef SF_ENTRY +#undef SF_ENTRY_C +#undef SF_ENTRY_X + +struct sf_structlevel_procs { + const char *ext; + struct sf_procs fn; /* called for structlevel (historical) */ +}; +struct sf_fieldlevel_procs { + const char *ext; + struct sf_procs fn_x; /* called for fieldlevel */ +}; +extern struct sf_structlevel_procs sfoprocs[NUM_SAVEFORMATS], sfiprocs[NUM_SAVEFORMATS]; +extern struct sf_fieldlevel_procs sfoflprocs[NUM_SAVEFORMATS], sfiflprocs[NUM_SAVEFORMATS]; +extern struct sf_structlevel_procs historical_sfo_procs; +extern struct sf_structlevel_procs historical_sfi_procs; +extern struct sf_fieldlevel_procs cnv_sfo_procs; +extern struct sf_fieldlevel_procs cnv_sfi_procs; + +#endif /* SFPROCS_H */ + diff --git a/src/artifact.c b/src/artifact.c index cd0c37bdd..ddd254285 100644 --- a/src/artifact.c +++ b/src/artifact.c @@ -71,6 +71,7 @@ static xint16 artidisco[NROFARTIFACTS]; * bulk re-init if game restart ever gets implemented. They are saved * and restored but that is done through this file so they can be local. */ + static const struct arti_info zero_artiexist = {0}; /* all bits zero */ staticfn void hack_artifacts(void); @@ -113,16 +114,11 @@ save_artifacts(NHFILE *nhfp) { int i; - for (i = 0; i < (NROFARTIFACTS + 1); ++i) { - if (nhfp->structlevel) - bwrite(nhfp->fd, (genericptr_t) &artiexist[i], - sizeof (struct arti_info)); - } - for (i = 0; i < (NROFARTIFACTS); ++i) { - if (nhfp->structlevel) - bwrite(nhfp->fd, (genericptr_t) &artidisco[i], - sizeof (xint16)); - } + for (i = 0; i < (NROFARTIFACTS + 1); ++i) + Sfo_arti_info(nhfp, &artiexist[i], "artiexist"); + + for (i = 0; i < NROFARTIFACTS; ++i) + Sfo_xint16(nhfp, &artidisco[i], "artidisco"); } void @@ -130,16 +126,10 @@ restore_artifacts(NHFILE *nhfp) { int i; - for (i = 0; i < (NROFARTIFACTS + 1); ++i) { - if (nhfp->structlevel) - mread(nhfp->fd, (genericptr_t) &artiexist[i], - sizeof (struct arti_info)); - } - for (i = 0; i < (NROFARTIFACTS); ++i) { - if (nhfp->structlevel) - mread(nhfp->fd, (genericptr_t) &artidisco[i], - sizeof (xint16)); - } + for (i = 0; i < (NROFARTIFACTS + 1); ++i) + Sfi_arti_info(nhfp, &artiexist[i], "artiexist"); + for (i = 0; i < NROFARTIFACTS; ++i) + Sfi_short(nhfp, &artidisco[i], "artidisco"); hack_artifacts(); /* redo non-saved special cases */ } @@ -2799,4 +2789,5 @@ permapoisoned(struct obj *obj) { return (obj && is_art(obj, ART_GRIMTOOTH)); } + /*artifact.c*/ diff --git a/src/bones.c b/src/bones.c index f165e71ea..31185dd28 100644 --- a/src/bones.c +++ b/src/bones.c @@ -610,13 +610,10 @@ savebones(int how, time_t when, struct obj *corpse) nhfp->mode = WRITING; store_version(nhfp); - /* if a bones pool digit is in use, it precedes the bonesid - string and isn't recorded in the file */ - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &c, sizeof c); - bwrite(nhfp->fd, (genericptr_t) bonesid, (unsigned) c); /* DD.nn */ - } + string and isn't recorded in the file */ + Sfo_char(nhfp, &c, "bones_count", 1); + Sfo_char(nhfp, bonesid, "bonesid", (int) c); /* DD.nnn */ savefruitchn(nhfp); update_mlstmv(); /* update monsters for eventual restoration */ savelev(nhfp, ledger_no(&u.uz)); @@ -655,7 +652,7 @@ getbones(void) return 0; } - if (validate(nhfp, gb.bones, FALSE) != 0) { + if (validate(nhfp, gb.bones, FALSE) != SF_UPTODATE) { if (!wizard) pline("Discarding unusable bones; no need to panic..."); ok = FALSE; @@ -668,26 +665,18 @@ getbones(void) return 0; } } - /* if a bones pool digit is in use, it precedes the bonesid - string and wasn't recorded in the file */ - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) &c, - sizeof c); /* length including terminating '\0' */ - } - if ((unsigned) c <= sizeof oldbonesid) { - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) oldbonesid, - (unsigned) c); /* DD.nn or Qrrr.n for role rrr */ + Sfi_char(nhfp, &c, "bones_count", 1); /* length incl. '\0' */ + if ((unsigned) c <= sizeof oldbonesid) { + Sfi_char(nhfp, oldbonesid, "bonesid", (int) c); + } else { + if (wizard) + debugpline2("Abandoning bones , %u > %u.", + (unsigned) c, (unsigned) sizeof oldbonesid); + close_nhfile(nhfp); + compress_bonesfile(); + /* ToDo: maybe unlink these problematic bones? */ + return 0; } - } else { - if (wizard) - debugpline2("Abandoning bones , %u > %u.", (unsigned) c, - (unsigned) sizeof oldbonesid); - close_nhfile(nhfp); - compress_bonesfile(); - /* ToDo: maybe unlink these problematic bones? */ - return 0; - } if (strcmp(bonesid, oldbonesid) != 0) { char errbuf[BUFSZ]; diff --git a/src/cfgfiles.c b/src/cfgfiles.c index 3e1197a4e..52f45a7a4 100644 --- a/src/cfgfiles.c +++ b/src/cfgfiles.c @@ -1133,7 +1133,6 @@ cnf_line_PORTABLE_DEVICE_PATHS(char *bufp) #endif return TRUE; } - #endif /* SYSCF */ staticfn boolean @@ -1863,9 +1862,9 @@ vconfig_error_add(const char *str, va_list the_args) staticfn void parseformat(int *arr, char *str) { - const char *legal[] = { "historical", "lendian", "ascii" }; + const char *legal[] = { "historical", "cnv" }; int i, kwi = 0, words = 0; - char *p = str, *keywords[2]; + char *p = str, *keywords[2] = { NULL }; while (*p) { while (*p && isspace((uchar) *p)) { @@ -1937,3 +1936,4 @@ assure_syscf_file(void) /* ---------- END CONFIG FILE HANDLING ----------- */ /*cfgfiles.c*/ + diff --git a/src/decl.c b/src/decl.c index e4dc3c6e8..3430cd3a5 100644 --- a/src/decl.c +++ b/src/decl.c @@ -282,6 +282,7 @@ static const struct instance_globals_c g_init_c = { UNDEFINED_PTR, /* coder */ /* uhitm.c */ NON_PM, /* corpsenm_digested */ + FALSE, /* converted_savefile_loaded */ TRUE, /* havestate*/ }; @@ -602,7 +603,6 @@ static const struct instance_globals_o g_init_o = { UNDEFINED_PTR, /* oldfruit */ /* rumors.c */ 0, /* oracle_flag */ - UNDEFINED_PTR, /* oracle_loc */ /* uhitm.c */ FALSE, /* override_confirmation */ /* zap.c */ @@ -930,6 +930,8 @@ static const struct instance_globals_saved_n init_svn = { static const struct instance_globals_saved_o init_svo = { /* rumors.c */ 0U, /* oracle_cnt */ + UNDEFINED_PTR, /* oracle_loc */ + /* other */ 0L /* omoves */ }; diff --git a/src/dungeon.c b/src/dungeon.c index 9a43ed7ac..cbc2abd8f 100644 --- a/src/dungeon.c +++ b/src/dungeon.c @@ -32,6 +32,8 @@ struct lchoice { char menuletter; }; +static mapseen *load_mapseen(NHFILE *); + #if 0 staticfn void Fread(genericptr_t, int, int, dlb *); #endif @@ -152,49 +154,31 @@ save_dungeon( mapseen *curr_ms, *next_ms; if (perform_write) { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &svn.n_dgns, sizeof svn.n_dgns); - } + Sfo_int(nhfp, &svn.n_dgns, "dungeon_count"); for (i = 0; i < svn.n_dgns; ++i) { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &svd.dungeons[i], - sizeof (dungeon)); - } - } - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &svd.dungeon_topology, - sizeof svd.dungeon_topology); - bwrite(nhfp->fd, (genericptr_t) svt.tune, sizeof tune); + Sfo_dungeon(nhfp, &svd.dungeons[i], "dungeon"); } + Sfo_dgn_topology(nhfp, &svd.dungeon_topology, "svd.dungeon_topology"); + Sfo_char(nhfp, svt.tune, "tune", (int) sizeof tune); for (count = 0, curr = svb.branches; curr; curr = curr->next) count++; - if (nhfp->structlevel) - bwrite(nhfp->fd, (genericptr_t) &count, sizeof count); + Sfo_int(nhfp, &count, "branch_count"); for (curr = svb.branches; curr; curr = curr->next) { - if (nhfp->structlevel) - bwrite(nhfp->fd, (genericptr_t) curr, sizeof *curr); + Sfo_branch(nhfp, curr, "branch"); } count = maxledgerno(); - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &count, sizeof count); - } + Sfo_int(nhfp, &count, "level_info_count"); for (i = 0; i < count; ++i) { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &svl.level_info[i], - sizeof (struct linfo)); - } - } - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &svi.inv_pos, sizeof svi.inv_pos); + Sfo_linfo(nhfp, &svl.level_info[i], "svl.level_info"); } + Sfo_nhcoord(nhfp, &svi.inv_pos, "svi.inv_pos"); + for (count = 0, curr_ms = svm.mapseenchn; curr_ms; curr_ms = curr_ms->next) count++; - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &count, sizeof count); - } + Sfo_int(nhfp, &count, "mapseen_count"); for (curr_ms = svm.mapseenchn; curr_ms; curr_ms = curr_ms->next) { save_mapseen(nhfp, curr_ms); @@ -224,35 +208,24 @@ void restore_dungeon(NHFILE *nhfp) { branch *curr, *last; - int count = 0, i; + int count = 0; + int i; mapseen *curr_ms, *last_ms; - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) &svn.n_dgns, sizeof svn.n_dgns); - } + Sfi_int(nhfp, &svn.n_dgns, "dungeon_count"); for (i = 0; i < svn.n_dgns; ++i) { - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) &svd.dungeons[i], sizeof(dungeon)); - } - } - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) &svd.dungeon_topology, - sizeof svd.dungeon_topology); - } - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) svt.tune, sizeof tune); + Sfi_dungeon(nhfp, &svd.dungeons[i], "dungeon"); } + Sfi_dgn_topology(nhfp, &svd.dungeon_topology, "svd.dungeon_topology"); + Sfi_char(nhfp, svt.tune, "tune", (int) sizeof tune); + last = svb.branches = (branch *) 0; - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) &count, sizeof count); - } + Sfi_int(nhfp, &count, "branch_count"); for (i = 0; i < count; i++) { curr = (branch *) alloc(sizeof *curr); - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) curr, sizeof *curr); - } + Sfi_branch(nhfp, curr, "branch"); curr->next = (branch *) 0; if (last) last->next = curr; @@ -261,23 +234,19 @@ restore_dungeon(NHFILE *nhfp) last = curr; } - if (nhfp->structlevel) - mread(nhfp->fd, (genericptr_t) &count, sizeof count); + Sfi_int(nhfp, &count, "level_info_count"); if (count >= MAXLINFO) panic("level information count larger (%d) than allocated size", count); for (i = 0; i < count; ++i) { - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) &svl.level_info[i], - sizeof (struct linfo)); - } - } - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) &svi.inv_pos, sizeof svi.inv_pos); - mread(nhfp->fd, (genericptr_t) &count, sizeof count); + Sfi_linfo(nhfp, &svl.level_info[i], "svl.level_info"); } + Sfi_nhcoord(nhfp, &svi.inv_pos, "svi.inv_pos"); + + Sfi_int(nhfp, &count, "mapseen_count"); + last_ms = (mapseen *) 0; for (i = 0; i < count; i++) { curr_ms = load_mapseen(nhfp); @@ -2592,19 +2561,14 @@ save_exclusions(NHFILE *nhfp) for (nez = 0, ez = sve.exclusion_zones; ez; ez = ez->next, ++nez) ; - if (perform_bwrite(nhfp)) { - if (nhfp->structlevel) - bwrite(nhfp->fd, (genericptr_t) &nez, sizeof nez); - + if (update_file(nhfp)) { + Sfo_int(nhfp, &nez, "exclusion-count"); for (ez = sve.exclusion_zones; ez; ez = ez->next) { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &ez->zonetype, - sizeof ez->zonetype); - bwrite(nhfp->fd, (genericptr_t) &ez->lx, sizeof ez->lx); - bwrite(nhfp->fd, (genericptr_t) &ez->ly, sizeof ez->ly); - bwrite(nhfp->fd, (genericptr_t) &ez->hx, sizeof ez->hx); - bwrite(nhfp->fd, (genericptr_t) &ez->hy, sizeof ez->hy); - } + Sfo_xint16(nhfp, &ez->zonetype, "exclusion-zonetype"); + Sfo_coordxy(nhfp, &ez->lx, "exclusion-lx"); + Sfo_coordxy(nhfp, &ez->ly, "exclusion-ly"); + Sfo_coordxy(nhfp, &ez->hx, "exclusion-hx"); + Sfo_coordxy(nhfp, &ez->hy, "exclusion-hy"); } } } @@ -2615,20 +2579,15 @@ load_exclusions(NHFILE *nhfp) struct exclusion_zone *ez; int nez = 0; - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) &nez, sizeof nez); - } + Sfi_int(nhfp, &nez, "exclusion_count"); while (nez-- > 0) { ez = (struct exclusion_zone *) alloc(sizeof *ez); - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) &ez->zonetype, - sizeof ez->zonetype); - mread(nhfp->fd, (genericptr_t) &ez->lx, sizeof ez->lx); - mread(nhfp->fd, (genericptr_t) &ez->ly, sizeof ez->ly); - mread(nhfp->fd, (genericptr_t) &ez->hx, sizeof ez->hx); - mread(nhfp->fd, (genericptr_t) &ez->hy, sizeof ez->hy); - } + Sfi_xint16(nhfp, &ez->zonetype, "exclusion-zonetype"); + Sfi_coordxy(nhfp, &ez->lx, "exclusion-lx"); + Sfi_coordxy(nhfp, &ez->ly, "exclusion-ly"); + Sfi_coordxy(nhfp, &ez->hx, "exclusion-hx"); + Sfi_coordxy(nhfp, &ez->hy, "exclusion-hy"); ez->next = sve.exclusion_zones; sve.exclusion_zones = ez; } @@ -2699,27 +2658,18 @@ save_mapseen(NHFILE *nhfp, mapseen *mptr) for (brindx = 0, curr = svb.branches; curr; curr = curr->next, ++brindx) if (curr == mptr->br) break; - - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &brindx, sizeof brindx); - bwrite(nhfp->fd, (genericptr_t) &mptr->lev, sizeof mptr->lev); - bwrite(nhfp->fd, (genericptr_t) &mptr->feat, sizeof mptr->feat); - bwrite(nhfp->fd, (genericptr_t) &mptr->flags, sizeof mptr->flags); - bwrite(nhfp->fd, (genericptr_t) &mptr->custom_lth, - sizeof mptr->custom_lth); - } + Sfo_int(nhfp, &brindx, "mapseen-branch_index"); + Sfo_d_level(nhfp, &mptr->lev, "mapseen-d_level"); + Sfo_mapseen_feat(nhfp, &mptr->feat, "mapseen-feat"); + Sfo_mapseen_flags(nhfp, &mptr->flags, "mapseen-flags"); + Sfo_unsigned(nhfp, &mptr->custom_lth, "mapseen-custom_lth"); if (mptr->custom_lth) { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) mptr->custom, - mptr->custom_lth); - } + Sfo_char(nhfp, mptr->custom, "mapseen-custom", + (int) mptr->custom_lth); } for (i = 0; i < ((MAXNROFROOMS + 1) * 2); ++i) { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &mptr->msrooms[i], - sizeof (struct mapseen_rooms)); - } + Sfo_mapseen_rooms(nhfp, &mptr->msrooms[i], "mapseen-msrooms"); } savecemetery(nhfp, &mptr->final_resting_place); } @@ -2733,38 +2683,28 @@ load_mapseen(NHFILE *nhfp) load = (mapseen *) alloc(sizeof *load); - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) &branchnum, sizeof branchnum); - } + Sfi_int(nhfp, &branchnum, "mapseen-branch_index"); for (brindx = 0, curr = svb.branches; curr; curr = curr->next, ++brindx) if (brindx == branchnum) break; load->br = curr; - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) &load->lev, sizeof load->lev); - mread(nhfp->fd, (genericptr_t) &load->feat, sizeof load->feat); - mread(nhfp->fd, (genericptr_t) &load->flags, sizeof load->flags); - mread(nhfp->fd, (genericptr_t) &load->custom_lth, - sizeof load->custom_lth); - } + Sfi_d_level(nhfp, &load->lev, "mapseen-d_level"); + Sfi_mapseen_feat(nhfp, &load->feat, "mapseen-feat"); + Sfi_mapseen_flags(nhfp, &load->flags, "mapseen-flags"); + Sfi_unsigned(nhfp, &load->custom_lth, "mapseen-custom_lth"); if (load->custom_lth) { /* length doesn't include terminator (which isn't saved & restored) */ load->custom = (char *) alloc(load->custom_lth + 1); - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) load->custom, - load->custom_lth); - } + Sfi_char(nhfp, load->custom, "mapseen-custom", + (int) load->custom_lth); load->custom[load->custom_lth] = '\0'; } else { load->custom = 0; } for (i = 0; i < ((MAXNROFROOMS + 1) * 2); ++i) { - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) &load->msrooms[i], - sizeof (struct mapseen_rooms)); - } + Sfi_mapseen_rooms(nhfp, &load->msrooms[i], "mapseen-msrooms"); } restcemetery(nhfp, &load->final_resting_place); return load; @@ -3742,7 +3682,6 @@ print_mapseen( } } } - #undef OF_INTEREST #undef ADDNTOBUF #undef ADDTOBUF diff --git a/src/end.c b/src/end.c index 57b189d12..e17c17517 100644 --- a/src/end.c +++ b/src/end.c @@ -1754,11 +1754,9 @@ save_killers(NHFILE *nhfp) { struct kinfo *kptr; - if (perform_bwrite(nhfp)) { + if (update_file(nhfp)) { for (kptr = &svk.killer; kptr; kptr = kptr->next) { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) kptr, sizeof (struct kinfo)); - } + Sfo_kinfo(nhfp, kptr, "kinfo"); } } if (release_data(nhfp)) { @@ -1776,9 +1774,7 @@ restore_killers(NHFILE *nhfp) struct kinfo *kptr; for (kptr = &svk.killer; kptr != (struct kinfo *) 0; kptr = kptr->next) { - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) kptr, sizeof (struct kinfo)); - } + Sfi_kinfo(nhfp, kptr, "kinfo"); if (kptr->next) { kptr->next = (struct kinfo *) alloc(sizeof (struct kinfo)); } @@ -1933,12 +1929,12 @@ NH_abort(char *why USED_FOR_CRASHREPORT) panictrace_setsignals(FALSE); #endif #endif /* PANICTRACE */ -#ifdef WIN32 +#if defined(WIN32) win32_abort(); #else abort(); #endif } -#undef USED_FOR_CRASHREPORT +#undef USED_FOR_CRASHREPORT /*end.c*/ diff --git a/src/engrave.c b/src/engrave.c index 2a300cfac..00602e0fc 100644 --- a/src/engrave.c +++ b/src/engrave.c @@ -1515,27 +1515,29 @@ void save_engravings(NHFILE *nhfp) { struct engr *ep, *ep2; - unsigned no_more_engr = 0; + unsigned no_more_engr = 0, engr_alloc; + unsigned szeach; for (ep = head_engr; ep; ep = ep2) { ep2 = ep->nxt_engr; if (ep->engr_alloc - && ep->engr_txt[actual_text][0] && perform_bwrite(nhfp)) { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &(ep->engr_alloc), - sizeof ep->engr_alloc); - bwrite(nhfp->fd, (genericptr_t) ep, - sizeof (struct engr) + ep->engr_alloc); - } + && ep->engr_txt[actual_text][0] && update_file(nhfp)) { + engr_alloc = (unsigned) ep->engr_alloc; + szeach = ep->engr_szeach; + Sfo_unsigned(nhfp, &engr_alloc, "engraving-engr_alloc"); + Sfo_engr(nhfp, ep, "engraving"); + ep->engr_txt[actual_text] = (char *)(ep + 1); + ep->engr_txt[remembered_text] = ep->engr_txt[actual_text] + szeach; + ep->engr_txt[pristine_text] = ep->engr_txt[remembered_text] + szeach; + Sfo_char(nhfp, ep->engr_txt[actual_text], "engraving-actual_text", szeach); + Sfo_char(nhfp, ep->engr_txt[remembered_text], "engraving-remembered_text", szeach); + Sfo_char(nhfp, ep->engr_txt[pristine_text], "engraving-pristine_text", szeach); } if (release_data(nhfp)) dealloc_engr(ep); } - if (perform_bwrite(nhfp)) { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &no_more_engr, - sizeof no_more_engr); - } + if (update_file(nhfp)) { + Sfo_unsigned(nhfp, &no_more_engr, "engraving-engr_alloc"); } if (release_data(nhfp)) head_engr = 0; @@ -1546,25 +1548,28 @@ rest_engravings(NHFILE *nhfp) { struct engr *ep; unsigned lth = 0; + unsigned szeach; head_engr = 0; while (1) { - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) <h, sizeof(unsigned)); - } + Sfi_unsigned(nhfp, <h, "engraving-engr_alloc"); if (lth == 0) return; ep = newengr(lth); - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) ep, sizeof (struct engr) + lth); - } + Sfi_engr(nhfp, ep, "engraving"); + szeach = ep->engr_szeach; ep->nxt_engr = head_engr; head_engr = ep; ep->engr_txt[actual_text] = (char *) (ep + 1); /* Andreas Bormann */ - ep->engr_txt[remembered_text] = ep->engr_txt[actual_text] - + ep->engr_szeach; - ep->engr_txt[pristine_text] = ep->engr_txt[remembered_text] - + ep->engr_szeach; + ep->engr_txt[remembered_text] = ep->engr_txt[actual_text] + szeach; + ep->engr_txt[pristine_text] = ep->engr_txt[remembered_text] + szeach; + Sfi_char(nhfp, ep->engr_txt[actual_text], + "engraving-actual_text", (int) szeach); + Sfi_char(nhfp, ep->engr_txt[remembered_text], + "engraving-remembered_text", (int) szeach); + Sfi_char(nhfp, ep->engr_txt[pristine_text], + "engraving-pristine_text", (int) szeach); + while (ep->engr_txt[actual_text][0] == ' ') ep->engr_txt[actual_text]++; while (ep->engr_txt[remembered_text][0] == ' ') diff --git a/src/files.c b/src/files.c index 90ab61076..238d03662 100644 --- a/src/files.c +++ b/src/files.c @@ -5,6 +5,10 @@ #define NEED_VARARGS +#if defined(WIN32) +#include "win32api.h" +#endif + #include "hack.h" #include "dlb.h" @@ -77,6 +81,9 @@ static char fqn_filename_buffer[FQN_NUMBUF][FQN_MAX_FILENAME]; #if defined(WIN32) #include +#include +#define F_OK 0 +#define access _access #endif #ifdef AMIGA @@ -96,11 +103,15 @@ extern void amii_set_text_font(char *, int); #endif #define Close close #ifndef WIN_CE +#ifdef DeleteFile +#undef DeleteFile +#endif #define DeleteFile unlink #endif #ifdef WIN32 -/*from windmain.c */ +/*from windsys.c */ extern char *translate_path_variables(const char *, char *); +extern boolean get_user_home_folder(char *, size_t); #endif #endif @@ -116,6 +127,7 @@ extern char *translate_path_variables(const char *, char *); staticfn NHFILE *new_nhfile(void); staticfn void free_nhfile(NHFILE *); + #ifdef SELECTSAVED staticfn int QSORTCALLBACK strcmp_wrap(const void *, const void *); #endif @@ -130,10 +142,17 @@ staticfn void docompress_file(const char *, boolean); #if defined(ZLIB_COMP) staticfn boolean make_compressed_name(const char *, char *); #endif + +staticfn NHFILE *problematic_savefile(int, const char *); +staticfn NHFILE *viable_nhfile(NHFILE *); +#ifdef SELECTSAVED +staticfn int QSORTCALLBACK strcmp_wrap(const void *, const void *); +#endif +staticfn char *set_bonesfile_name(char *, d_level *); +staticfn char *set_bonestemp_name(void); #ifndef USE_FCNTL staticfn char *make_lockname(const char *, char *); #endif - staticfn FILE *fopen_wizkit_file(void); staticfn void wizkit_addinv(struct obj *); boolean proc_wizkit_line(char *buf); @@ -407,7 +426,7 @@ zero_nhfile(NHFILE *nhfp) { nhfp->fd = -1; nhfp->mode = COUNTING; - nhfp->structlevel = FALSE; + nhfp->structlevel = TRUE; nhfp->fieldlevel = FALSE; nhfp->addinfo = FALSE; nhfp->bendian = IS_BIGENDIAN(); @@ -417,6 +436,9 @@ zero_nhfile(NHFILE *nhfp) nhfp->count = 0; nhfp->eof = FALSE; nhfp->fnidx = 0; + nhfp->style.deflt = FALSE; + nhfp->style.binary = TRUE; + nhfp->nhfpconvert = 0; } staticfn NHFILE * @@ -442,6 +464,12 @@ close_nhfile(NHFILE *nhfp) { if (nhfp->structlevel && nhfp->fd != -1) (void) nhclose(nhfp->fd), nhfp->fd = -1; + if (nhfp->fplog) + (void) fprintf(nhfp->fplog, "# closing\n"); + if (nhfp->fplog) + (void) fclose(nhfp->fplog); + if (nhfp->fpdebug) + (void) fclose(nhfp->fpdebug); zero_nhfile(nhfp); free_nhfile(nhfp); } @@ -449,13 +477,11 @@ close_nhfile(NHFILE *nhfp) void rewind_nhfile(NHFILE *nhfp) { - if (nhfp->structlevel) { #ifdef BSD - (void) lseek(nhfp->fd, 0L, 0); + (void) lseek(nhfp->fd, 0L, 0); #else - (void) lseek(nhfp->fd, (off_t) 0, 0); + (void) lseek(nhfp->fd, (off_t) 0, 0); #endif - } } staticfn NHFILE * @@ -465,10 +491,25 @@ viable_nhfile(NHFILE *nhfp) the pointer to the nethack file descriptor */ if (nhfp) { /* check for no open file at all, - * not a structlevel legacy file + * not a structlevel legacy file, + * nor a fieldlevel file. */ - if (nhfp->structlevel && nhfp->fd < 0) { + if (((nhfp->fd == -1) && !nhfp->fpdef) + || (nhfp->structlevel && nhfp->fd < 0) + || (nhfp->fieldlevel && !nhfp->fpdef)) { /* not viable, start the cleanup */ + if (nhfp->fieldlevel) { + if (nhfp->fpdef) { + (void) fclose(nhfp->fpdef); + nhfp->fpdef = (FILE *) 0; + } + if (nhfp->fplog) { + (void) fprintf(nhfp->fplog, "# closing, not viable\n"); + (void) fclose(nhfp->fplog); + } + if (nhfp->fpdebug) + (void) fclose(nhfp->fpdebug); + } zero_nhfile(nhfp); free_nhfile(nhfp); nhfp = (NHFILE *) 0; @@ -477,6 +518,20 @@ viable_nhfile(NHFILE *nhfp) return nhfp; } +int +nhclose(int fd) +{ + int retval = 0; + + if (fd >= 0) { + if (close_check(fd)) + bclose(fd); + else + retval = close(fd); + } + return retval; +} + /* ---------- BEGIN LEVEL FILE HANDLING ----------- */ /* Construct a file name for a level-type file, which is of the form @@ -520,6 +575,7 @@ create_levelfile(int lev, char errbuf[]) nhfp->addinfo = FALSE; nhfp->style.deflt = FALSE; nhfp->style.binary = TRUE; + nhfp->fnidx = historical; nhfp->fd = -1; nhfp->fpdef = (FILE *) 0; #if defined(MICRO) || defined(WIN32) @@ -542,6 +598,9 @@ create_levelfile(int lev, char errbuf[]) Sprintf(errbuf, "Cannot create file \"%s\" for level %d (errno %d).", gl.lock, lev, errno); +#if defined(MSDOS) + setmode(nhfp->fd, O_BINARY); +#endif } nhfp = viable_nhfile(nhfp); return nhfp; @@ -566,6 +625,7 @@ open_levelfile(int lev, char errbuf[]) nhfp->style.deflt = FALSE; nhfp->style.binary = TRUE; nhfp->ftype = NHF_LEVELFILE; + nhfp->fnidx = historical; nhfp->fd = -1; nhfp->fpdef = (FILE *) 0; } @@ -583,6 +643,9 @@ open_levelfile(int lev, char errbuf[]) Sprintf(errbuf, "Cannot open file \"%s\" for level %d (errno %d).", gl.lock, lev, errno); +#if defined(MSDOS) + setmode(nhfp->fd, O_BINARY); +#endif } nhfp = viable_nhfile(nhfp); return nhfp; @@ -631,20 +694,6 @@ strcmp_wrap(const void *p, const void *q) } #endif -int -nhclose(int fd) -{ - int retval = 0; - - if (fd >= 0) { - if (close_check(fd)) - bclose(fd); - else - retval = close(fd); - } - return retval; -} - /* ---------- END LEVEL FILE HANDLING ----------- */ /* ---------- BEGIN BONES FILE HANDLING ----------- */ @@ -731,10 +780,23 @@ create_bonesfile(d_level *lev, char **bonesid, char errbuf[]) nhfp = new_nhfile(); if (nhfp) { - nhfp->structlevel = TRUE; - nhfp->fieldlevel = FALSE; nhfp->ftype = NHF_BONESFILE; nhfp->mode = WRITING; + nhfp->structlevel = TRUE; + nhfp->fieldlevel = FALSE; + nhfp->addinfo = TRUE; + nhfp->style.deflt = TRUE; + nhfp->style.binary = TRUE; + nhfp->fnidx = historical; + nhfp->fd = -1; + nhfp->fpdef = fopen(file, nhfp->style.binary ? WRBMODE : WRTMODE); + if (nhfp->fpdef) { +#ifdef SAVEFILE_DEBUGGING + nhfp->fpdebug = fopen("create_bonesfile-debug.log", "a"); +#endif + } else { + failed = errno; + } if (nhfp->structlevel) { #if defined(MICRO) || defined(WIN32) /* Use O_TRUNC to force the file to be shortened if it already @@ -751,6 +813,9 @@ create_bonesfile(d_level *lev, char **bonesid, char errbuf[]) #endif if (nhfp->fd < 0) failed = errno; +#if defined(MSDOS) + setmode(nhfp->fd, O_BINARY); +#endif } if (failed && errbuf) /* failure explanation */ Sprintf(errbuf, "Cannot create bones \"%s\", id %s (errno %d).", @@ -814,11 +879,25 @@ open_bonesfile(d_level *lev, char **bonesid) nhfp->fieldlevel = FALSE; nhfp->ftype = NHF_BONESFILE; nhfp->mode = READING; + nhfp->addinfo = TRUE; + nhfp->style.deflt = TRUE; + nhfp->style.binary = (sysopt.bonesformat[0] != cnvascii); + nhfp->fnidx = sysopt.bonesformat[0]; + nhfp->fd = -1; + nhfp->fpdef = fopen(fq_bones, nhfp->style.binary ? RDBMODE : RDTMODE); + if (nhfp->fpdef) { +#ifdef SAVEFILE_DEBUGGING + nhfp->fpdebug = fopen("open_bonesfile-debug.log", "a"); +#endif + } if (nhfp->structlevel) { #ifdef MAC nhfp->fd = macopen(fq_bones, O_RDONLY | O_BINARY, BONE_TYPE); #else nhfp->fd = open(fq_bones, O_RDONLY | O_BINARY, 0); +#endif +#if defined(MSDOS) + setmode(nhfp->fd, O_BINARY); #endif } } @@ -829,8 +908,11 @@ open_bonesfile(d_level *lev, char **bonesid) int delete_bonesfile(d_level *lev) { + int reslt; + (void) set_bonesfile_name(gb.bones, lev); - return !(unlink(fqname(gb.bones, BONESPREFIX, 0)) < 0); + reslt = unlink(fqname(gb.bones, BONESPREFIX, 0)); + return !(reslt < 0); } /* assume we're compressing the recently read or created bonesfile, so the @@ -929,9 +1011,6 @@ set_savefile_name(boolean regularize_it) if (strlen(SAVE_EXTENSION) > (0) && !overflow) { if (strlen(gs.SAVEF) + strlen(SAVE_EXTENSION) < (SAVESIZE - 1)) { Strcat(gs.SAVEF, SAVE_EXTENSION); -#ifdef MSDOS - sfindicator = ""; -#endif } else overflow = 3; } @@ -960,8 +1039,7 @@ set_savefile_name(boolean regularize_it) void save_savefile_name(NHFILE *nhfp) { - if (nhfp->structlevel) - (void) write(nhfp->fd, (genericptr_t) gs.SAVEF, sizeof(gs.SAVEF)); + Sfo_char(nhfp, gs.SAVEF, "savefile_name", sizeof(gs.SAVEF)); } #endif @@ -999,12 +1077,9 @@ create_savefile(void) fq_save = fqname(gs.SAVEF, SAVEPREFIX, 0); nhfp = new_nhfile(); if (nhfp) { - nhfp->structlevel = TRUE; - nhfp->fieldlevel = FALSE; nhfp->ftype = NHF_SAVEFILE; nhfp->mode = WRITING; if (program_state.in_self_recover || do_historical) { - do_historical = TRUE; /* force it */ nhUse(do_historical); nhfp->structlevel = TRUE; nhfp->fieldlevel = FALSE; @@ -1014,19 +1089,24 @@ create_savefile(void) nhfp->fnidx = historical; nhfp->fd = -1; nhfp->fpdef = (FILE *) 0; - } - if (nhfp->structlevel) { +#ifdef SAVEFILE_DEBUGGING + nhfp->fplog = fopen("create-savefile.log", "w"); +#endif + } #if defined(MICRO) || defined(WIN32) nhfp->fd = open(fq_save, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, FCMASK); #else #ifdef MAC - nhfp->fd = maccreat(fq_save, SAVE_TYPE); + nhfp->fd = maccreat(fq_save, SAVE_TYPE); #else - nhfp->fd = creat(fq_save, FCMASK); + nhfp->fd = creat(fq_save, FCMASK); #endif #endif /* MICRO || WIN32 */ - } +#if defined(MSDOS) || defined(WIN32) + if (nhfp->fd >= 0) + (void) setmode(nhfp->fd, O_BINARY); +#endif } #if defined(VMS) && !defined(SECURE) /* @@ -1054,8 +1134,6 @@ open_savefile(void) fq_save = fqname(gs.SAVEF, SAVEPREFIX, 0); nhfp = new_nhfile(); if (nhfp) { - nhfp->structlevel = TRUE; - nhfp->fieldlevel = FALSE; nhfp->ftype = NHF_SAVEFILE; nhfp->mode = READING; if (program_state.in_self_recover || do_historical) { @@ -1069,14 +1147,19 @@ open_savefile(void) nhfp->fnidx = historical; nhfp->fd = -1; nhfp->fpdef = (FILE *) 0; - } - if (nhfp->structlevel) { -#ifdef MAC - nhfp->fd = macopen(fq_save, O_RDONLY | O_BINARY, SAVE_TYPE); -#else - nhfp->fd = open(fq_save, O_RDONLY | O_BINARY, 0); +#ifdef SAVEFILE_DEBUGGING + nhfp->fplog = fopen("open-savefile.log", "w"); +#endif + } +#ifdef MAC + nhfp->fd = macopen(fq_save, O_RDONLY | O_BINARY, SAVE_TYPE); +#else + nhfp->fd = open(fq_save, O_RDONLY | O_BINARY, 0); +#endif +#if defined(MSDOS) || defined(WIN32) + if (nhfp->fd >= 0) + (void) setmode(nhfp->fd, O_BINARY); #endif - } } nhfp = viable_nhfile(nhfp); return nhfp; @@ -1086,7 +1169,9 @@ open_savefile(void) int delete_savefile(void) { - (void) unlink(fqname(gs.SAVEF, SAVEPREFIX, 0)); + const char *sfname = fqname(gs.SAVEF, SAVEPREFIX, 0); + + (void) unlink(sfname); return 0; /* for restore_saved_game() (ex-xxxmain.c) test */ } @@ -1096,16 +1181,16 @@ restore_saved_game(void) { const char *fq_save; NHFILE *nhfp = (NHFILE *) 0; + int sfstatus = 0; set_savefile_name(TRUE); fq_save = fqname(gs.SAVEF, SAVEPREFIX, 0); nh_uncompress(fq_save); if ((nhfp = open_savefile()) != 0) { - if (validate(nhfp, fq_save, FALSE) != 0) { + if ((sfstatus = validate(nhfp, fq_save, FALSE)) != SF_UPTODATE) { close_nhfile(nhfp); - nhfp = (NHFILE *) 0; - (void) delete_savefile(); + nhfp = problematic_savefile(sfstatus, fq_save); } } return nhfp; @@ -1165,6 +1250,7 @@ plname_from_file( NHFILE *nhfp; unsigned ln; char *result = 0; + int sfstatus = 0; Strcpy(gs.SAVEF, filename); #ifdef COMPRESS_EXTENSION @@ -1179,7 +1265,8 @@ plname_from_file( #endif nh_uncompress(gs.SAVEF); if ((nhfp = open_savefile()) != 0) { - if (validate(nhfp, filename, without_wait_synch_per_file) == 0) { + if ((sfstatus = validate(nhfp, filename, + without_wait_synch_per_file)) == SF_UPTODATE) { /* room for "name+role+race+gend+algn X" where the space before X is actually NUL and X is playmode: one of '-', 'X', or 'D' */ ln = (unsigned) PL_NSIZ_PLUS; @@ -1403,7 +1490,6 @@ docompress_file(const char *filename, boolean uncomp) #ifdef TTY_GRAPHICS boolean istty = WINDOWPORT(tty); #endif - #ifdef COMPRESS_EXTENSION xtra = COMPRESS_EXTENSION; #else @@ -1752,6 +1838,60 @@ docompress_file(const char *filename, boolean uncomp) /* ---------- END FILE COMPRESSION HANDLING ----------- */ + +/* ---------- BEGIN PROBLEMATIC SAVEFILE HANDLING ----------- */ + +static struct sfstatus_to_msg { + int sfstatus; + const char *msg; +} sf2msg[] = { + { SF_UPTODATE, "everything matches" }, + { SF_OUTDATED, "outdated savefile" }, + { SF_CRITICAL_BYTE_COUNT_MISMATCH, + "savefile critical byte-count mismatch" }, + { SF_DM_IL32LLP64_ON_ILP32LL64, "Windows x64 savefile on x86" }, + { SF_DM_I32LP64_ON_ILP32LL64, "Unix 64 savefile on x86" }, + { SF_DM_ILP32LL64_ON_I32LP64, "x86 savefile on Unix 64" }, + { SF_DM_ILP32LL64_ON_IL32LLP64, "x86 savefile on Windows x64" }, + { SF_DM_I32LP64_ON_IL32LLP64, "Unix 64 savefile on Windows x64" }, + { SF_DM_IL32LLP64_ON_I32LP64, "Windows x64 savefile on Unix 64" }, + { SF_DM_MISMATCH, "generic savefile mismatch" }, +}; + +staticfn NHFILE * +problematic_savefile(int sfstatus, const char *savefilenm) +{ + int i; + NHFILE *nhfp = (NHFILE *) 0; + + switch (sfstatus) { + case SF_UPTODATE: + break; + case SF_DM_IL32LLP64_ON_ILP32LL64: + case SF_DM_I32LP64_ON_ILP32LL64: + case SF_DM_ILP32LL64_ON_I32LP64: + case SF_DM_ILP32LL64_ON_IL32LLP64: + case SF_DM_I32LP64_ON_IL32LLP64: + case SF_DM_IL32LLP64_ON_I32LP64: + case SF_DM_MISMATCH: + case SF_OUTDATED: + case SF_CRITICAL_BYTE_COUNT_MISMATCH: + default: + for (i = 0; i < SIZE(sf2msg); ++i) { + if (sf2msg[i].sfstatus == sfstatus) { + raw_printf("\n%s is %s %s\n", + savefilenm, + (sfstatus == SF_OUTDATED) ? "an" : "a", + sf2msg[i].msg); + break; + } + } + } + return nhfp; +} + +/* ---------- END PROBLEMATIC SAVEFILE HANDLING ----------- */ + /* ---------- BEGIN FILE LOCKING HANDLING ----------- */ #if defined(NO_FILE_LINKS) || defined(USE_FCNTL) /* implies UNIX */ @@ -2413,18 +2553,22 @@ testinglog(const char *filenm, /* ad hoc file name */ #ifdef SELF_RECOVER /* ---------- BEGIN INTERNAL RECOVER ----------- */ + +extern uchar critical_sizes[], cscbuf[]; /* version.c */ + boolean recover_savefile(void) { NHFILE *gnhfp, *lnhfp, *snhfp; - int lev, savelev, hpid, pltmpsiz; + int lev, savelev, hpid, + pltmpsiz, cscount = get_critical_size_count(); xint8 levc; struct version_info version_data; int processed[256]; - char savename[SAVESIZE], errbuf[BUFSZ], indicator; + char savename[SAVESIZE], errbuf[BUFSZ], indicator, file_cscount; char tmpplbuf[PL_NSIZ_PLUS]; const char *savewrite_failure = (const char *) 0; - int ccbresult = 0; + off_t filesz = 0; for (lev = 0; lev < 256; lev++) processed[lev] = 0; @@ -2442,6 +2586,30 @@ recover_savefile(void) raw_printf("%s\n", errbuf); return FALSE; } + filesz = lseek(gnhfp->fd, 0L, SEEK_END); + (void) lseek(gnhfp->fd, 0L, SEEK_SET); + if ((size_t) filesz < (sizeof hpid + + sizeof lev + + sizeof savename + + sizeof indicator + + sizeof file_cscount + + sizeof version_data + sizeof pltmpsiz)) { + const char *fq_save; + + /* this indicates a .0 file that was created as part of + * recover that did not complete. There could be an intact + * savefile already there. Check for that and return TRUE + * if there is. */ + set_savefile_name(TRUE); + fq_save = fqname(gs.SAVEF, SAVEPREFIX, 0); + if (access(fq_save, F_OK) == 0) { + close_nhfile(gnhfp); + delete_levelfile(0); + return TRUE; + } else { + /* savefile doesn't exist, so fall through */ + } + } if (read(gnhfp->fd, (genericptr_t) &hpid, sizeof hpid) != sizeof hpid) { raw_printf("\n%s\n%s\n", "Checkpoint data incompletely written" @@ -2463,7 +2631,11 @@ recover_savefile(void) != sizeof savename) || (read(gnhfp->fd, (genericptr_t) &indicator, sizeof indicator) != sizeof indicator) - || ((ccbresult = compare_critical_bytes(gnhfp)) != 0) + || (read(gnhfp->fd, (genericptr_t) &file_cscount, sizeof file_cscount) + != sizeof file_cscount) + || (file_cscount <= cscount + && read(gnhfp->fd, (genericptr_t) &cscbuf, file_cscount) + != file_cscount) || (read(gnhfp->fd, (genericptr_t) &version_data, sizeof version_data) != sizeof version_data) || (read(gnhfp->fd, (genericptr_t) &pltmpsiz, sizeof pltmpsiz) @@ -2476,7 +2648,9 @@ recover_savefile(void) } /* save file should contain: - * format indicator and critical_bytes + * format indicator (1 byte) + * n = count of critical size list (1 byte) + * n bytes of critical sizes (n bytes) * version info * plnametmp = player name size (int, 2 bytes) * player name (PL_NSIZ_PLUS) @@ -2486,6 +2660,7 @@ recover_savefile(void) */ /* + * * Set a flag for the savefile routines to know the * circumstances and act accordingly: * program_state.in_self_recover @@ -2509,21 +2684,19 @@ recover_savefile(void) } store_version(snhfp); + if (savewrite_failure) goto cleanup; - if (snhfp->structlevel) { - if (write(snhfp->fd, (genericptr_t) &pltmpsiz, sizeof pltmpsiz) - != sizeof pltmpsiz) - savewrite_failure = "player name size"; - } + /* TODO: this is not a single byte, so a big-endian byte swap + * might be necessary here, if anyone is concerned about big-endian */ + Sfo_int(snhfp, &pltmpsiz, "plname-size"); + savewrite_failure = (const char *) 0; if (savewrite_failure) goto cleanup; - if (snhfp->structlevel) { - if (write(snhfp->fd, (genericptr_t) &tmpplbuf, pltmpsiz) != pltmpsiz) - savewrite_failure = "player name"; - } + Sfo_char(snhfp, tmpplbuf, "plname", pltmpsiz); + savewrite_failure = (const char *) 0; if (savewrite_failure) goto cleanup; @@ -3173,7 +3346,6 @@ Death_quote(char *buf, int bufsz) } /* ---------- END TRIBUTE ----------- */ - #ifdef LIVELOG #define LLOG_SEP "\t" /* livelog field separator, as a string literal */ #define LLOG_EOL "\n" /* end-of-line, for abstraction consistency */ diff --git a/src/hacklib.c b/src/hacklib.c index 1fb76c37a..fd8f20c91 100644 --- a/src/hacklib.c +++ b/src/hacklib.c @@ -953,5 +953,54 @@ copy_bytes(int ifd, int ofd) } while (nfrom == BUFSIZ); return TRUE; } +#define MAX_D 5 +struct datamodel_information { + int sz[MAX_D]; + const char *datamodel; +}; +static struct datamodel_information dm[] = { + { { (int) sizeof(short), (int) sizeof(int), (int) sizeof(long), + (int) sizeof(long long), (int) sizeof(genericptr_t) }, + "" }, + { { 2, 4, 4, 8, 4 }, "ILP32LL64" }, /* Windows, Unix x86 */ + { { 2, 4, 4, 8, 8 }, "IL32LLP64" }, /* Windows x64 */ + { { 2, 4, 8, 8, 8 }, "I32LP64" }, /* Unix 64-bit */ + { { 2, 8, 8, 8, 8 }, "ILP64" }, /* HAL, SPARC64 */ +}; + +const char * +datamodel(void) +{ + int i, j, matchcount; + static const char *unknown = "Unknown"; + + for (i = 1; i < SIZE(dm); ++i) { + matchcount = 0; + for (j = 0; j < MAX_D; ++j) { + if (dm[0].sz[j] == dm[i].sz[j]) + ++matchcount; + } + if (matchcount == MAX_D) + return dm[i].datamodel; + } + return unknown; +} + +const char * +what_datamodel_is_this(int szshort, int szint, int szlong, int szll, + int szptr) +{ + int i; + static const char *unknown = "Unknown"; + + for (i = 1; i < SIZE(dm); ++i) { + if (szshort == dm[i].sz[0] && szint == dm[i].sz[1] + && szlong == dm[i].sz[2] && szll == dm[i].sz[3] + && szptr == dm[i].sz[4]) + return dm[i].datamodel; + } + return unknown; +} +#undef MAX_D /*hacklib.c*/ diff --git a/src/light.c b/src/light.c index f783855eb..618ba5684 100644 --- a/src/light.c +++ b/src/light.c @@ -429,11 +429,9 @@ save_light_sources(NHFILE *nhfp, int range) discard_flashes(); gv.vision_full_recalc = 0; - if (perform_bwrite(nhfp)) { + if (update_file(nhfp)) { count = maybe_write_ls(nhfp, range, FALSE); - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &count, sizeof count); - } + Sfo_int(nhfp, &count, "lightsource-count"); actual = maybe_write_ls(nhfp, range, TRUE); if (actual != count) panic("counted %d light sources, wrote %d! [range=%d]", count, @@ -482,20 +480,17 @@ restore_light_sources(NHFILE *nhfp) light_source *ls; /* restore elements */ - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) &count, sizeof count); - } + Sfi_int(nhfp, &count, "lightsource-count"); while (count-- > 0) { ls = (light_source *) alloc(sizeof(light_source)); - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) ls, sizeof(light_source)); - } + Sfi_ls_t(nhfp, ls, "lightsource"); ls->next = gl.light_base; gl.light_base = ls; } } + DISABLE_WARNING_FORMAT_NONLITERAL /* to support '#stats' wizard-mode command */ @@ -641,9 +636,7 @@ write_ls(NHFILE *nhfp, light_source *ls) if (ls->type == LS_OBJECT || ls->type == LS_MONSTER) { if (ls->flags & LSF_NEEDS_FIXUP) { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) ls, sizeof(light_source)); - } + Sfo_ls_t(nhfp, ls, "lightsource"); } else { /* replace object pointer with id for write, then put back */ arg_save = ls->id; @@ -695,9 +688,7 @@ write_ls(NHFILE *nhfp, light_source *ls) /* TODO: cleanup this ls, or skip writing it */ } ls->flags |= LSF_NEEDS_FIXUP; - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) ls, sizeof(light_source)); - } + Sfo_ls_t(nhfp, ls, "lightsource"); ls->id = arg_save; ls->flags &= ~LSF_NEEDS_FIXUP; ls->flags &= ~LSF_IS_PROBLEMATIC; @@ -985,5 +976,4 @@ wiz_light_sources(void) #undef LSF_SHOW #undef LSF_NEEDS_FIXUP #undef mon_is_local - /*light.c*/ diff --git a/src/mdlib.c b/src/mdlib.c index dc69e8a28..95d4f1f2a 100644 --- a/src/mdlib.c +++ b/src/mdlib.c @@ -56,6 +56,7 @@ static boolean date_via_env = FALSE; extern unsigned long md_ignored_features(void); +extern const char *datamodel(void); char *version_id_string(char *, size_t, const char *) NONNULL NONNULLPTRS; char *bannerc_string(char *, size_t, const char *) NONNULL NONNULLPTRS; int case_insensitive_comp(const char *, const char *) NONNULLPTRS; @@ -87,7 +88,6 @@ staticfn void build_options(void); staticfn int count_and_validate_winopts(void); staticfn void opt_out_words(char *, int *) NONNULLPTRS; staticfn void build_savebones_compat_string(void); -staticfn const char *datamodel(void); static int idxopttext, done_runtime_opt_init_once = 0; #define MAXOPT 60 /* 3.7: currently 40 lines get inserted into opttext[] */ @@ -237,41 +237,6 @@ md_ignored_features(void) ); } -#define MAX_D 5 -struct datamodel_information { - int sz[MAX_D]; - const char *datamodel; -}; - -static struct datamodel_information dm[] = { - { { (int) sizeof(short), (int) sizeof(int), (int) sizeof(long), - (int) sizeof(long long), (int) sizeof(genericptr_t) }, - "" }, - { { 2, 4, 4, 8, 4 }, "ILP32LL64" }, /* Windows, Unix x86 */ - { { 2, 4, 4, 8, 8 }, "IL32LLP64" }, /* Windows x64 */ - { { 2, 4, 8, 8, 8 }, "I32LP64" }, /* Unix 64-bit */ - { { 2, 8, 8, 8, 8 }, "ILP64" }, /* HAL, SPARC64 */ -}; - -staticfn const char * -datamodel(void) -{ - int i, j, matchcount; - static const char *unknown = "Unknown"; - - for (i = 1; i < SIZE(dm); ++i) { - matchcount = 0; - for (j = 0; j < MAX_D; ++j) { - if (dm[0].sz[j] == dm[i].sz[j]) - ++matchcount; - } - if (matchcount == MAX_D) - return dm[i].datamodel; - } - return unknown; -} -#undef MAX_D - staticfn void make_version(void) { diff --git a/src/mkmaze.c b/src/mkmaze.c index 8e09bbf79..af12ba15e 100644 --- a/src/mkmaze.c +++ b/src/mkmaze.c @@ -1720,21 +1720,17 @@ save_waterlevel(NHFILE *nhfp) if (!svb.bbubbles) return; - if (perform_bwrite(nhfp)) { + if (update_file(nhfp)) { int n = 0; for (b = svb.bbubbles; b; b = b->next) ++n; - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &n, sizeof(int)); - bwrite(nhfp->fd, (genericptr_t) &svx.xmin, sizeof(int)); - bwrite(nhfp->fd, (genericptr_t) &svy.ymin, sizeof(int)); - bwrite(nhfp->fd, (genericptr_t) &svx.xmax, sizeof(int)); - bwrite(nhfp->fd, (genericptr_t) &svy.ymax, sizeof(int)); - } + Sfo_int(nhfp, &n, "waterlevel-bubble_count"); + Sfo_int(nhfp, &svx.xmin, "waterlevel-xmin"); + Sfo_int(nhfp, &svy.ymin, "waterlevel-ymin"); + Sfo_int(nhfp, &svx.xmax, "waterlevel-xmax"); + Sfo_int(nhfp, &svy.ymax, "waterlevel-ymax"); for (b = svb.bbubbles; b; b = b->next) { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) b, sizeof(struct bubble)); - } + Sfo_bubble(nhfp, b, "waterlevel-bubble"); } } if (release_data(nhfp)) @@ -1748,21 +1744,15 @@ restore_waterlevel(NHFILE *nhfp) struct bubble *b = (struct bubble *) 0, *btmp; int i, n = 0; - svb.bbubbles = (struct bubble *) 0; - set_wportal(); - if (nhfp->structlevel) { - mread(nhfp->fd,(genericptr_t) &n, sizeof (int)); - mread(nhfp->fd,(genericptr_t) &svx.xmin, sizeof (int)); - mread(nhfp->fd,(genericptr_t) &svy.ymin, sizeof (int)); - mread(nhfp->fd,(genericptr_t) &svx.xmax, sizeof (int)); - mread(nhfp->fd,(genericptr_t) &svy.ymax, sizeof (int)); - } + Sfi_int(nhfp, &n, "waterlevel-bubble_count"); + Sfi_int(nhfp, &svx.xmin, "waterlevel-xmin"); + Sfi_int(nhfp, &svy.ymin, "waterlevel-ymin"); + Sfi_int(nhfp, &svx.xmax, "waterlevel-xmax"); + Sfi_int(nhfp, &svy.ymax, "waterlevel-ymax"); for (i = 0; i < n; i++) { btmp = b; b = (struct bubble *) alloc((unsigned) sizeof *b); - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) b, (unsigned) sizeof *b); - } + Sfi_bubble(nhfp, b, "waterlevel-bubble"); if (btmp) { btmp->next = b; b->prev = btmp; diff --git a/src/mkroom.c b/src/mkroom.c index d96eca758..21dd56912 100644 --- a/src/mkroom.c +++ b/src/mkroom.c @@ -25,8 +25,10 @@ staticfn void mktemple(void); staticfn coord *shrine_pos(int); staticfn struct permonst *morguemon(void); staticfn struct permonst *squadmon(void); + staticfn void save_room(NHFILE *, struct mkroom *); staticfn void rest_room(NHFILE *, struct mkroom *); + staticfn boolean invalid_shop_shape(struct mkroom *sroom); #define sq(x) ((x) * (x)) @@ -845,9 +847,7 @@ save_room(NHFILE *nhfp, struct mkroom *r) * of writing the whole structure. That is I should not write * the gs.subrooms pointers, but who cares ? */ - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) r, sizeof (struct mkroom)); - } + Sfo_mkroom(nhfp, r, "room-mkroom"); for (i = 0; i < r->nsubrooms; i++) { save_room(nhfp, r->sbrooms[i]); } @@ -862,9 +862,7 @@ save_rooms(NHFILE *nhfp) short i; /* First, write the number of rooms */ - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &svn.nroom, sizeof svn.nroom); - } + Sfo_int(nhfp, &svn.nroom, "room-nroom"); for (i = 0; i < svn.nroom; i++) save_room(nhfp, &svr.rooms[i]); } @@ -874,9 +872,7 @@ rest_room(NHFILE *nhfp, struct mkroom *r) { short i; - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) r, sizeof (struct mkroom)); - } + Sfi_mkroom(nhfp, r, "room-mkroom"); for (i = 0; i < r->nsubrooms; i++) { r->sbrooms[i] = &gs.subrooms[gn.nsubroom]; @@ -894,9 +890,7 @@ rest_rooms(NHFILE *nhfp) { short i; - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) &svn.nroom, sizeof svn.nroom); - } + Sfi_int(nhfp, &svn.nroom, "room-nroom"); gn.nsubroom = 0; for (i = 0; i < svn.nroom; i++) { diff --git a/src/muse.c b/src/muse.c index b044af098..42243c832 100644 --- a/src/muse.c +++ b/src/muse.c @@ -3115,7 +3115,7 @@ muse_unslime( * Monsters don't start with oil and don't actively pick up oil * so this may never occur in a real game. (Possible though; * nymph can steal potions of oil; shapechanger could take on - * nymph form or vacuum up stuff as a g.cube and then eventually + * nymph form or vacuum up stuff as a gel.cube and then eventually * engage with a green slime.) */ diff --git a/src/nhlua.c b/src/nhlua.c index 080cf1552..0a77eb108 100644 --- a/src/nhlua.c +++ b/src/nhlua.c @@ -1264,6 +1264,8 @@ get_nh_lua_variables(void) RESTORE_WARNING_UNREACHABLE_CODE +/* char *lua_data; */ + /* save nh_lua_variables table to file */ void save_luadata(NHFILE *nhfp) @@ -1274,11 +1276,8 @@ save_luadata(NHFILE *nhfp) if (!lua_data) lua_data = dupstr(emptystr); lua_data_len = Strlen(lua_data) + 1; /* +1: include the terminator */ - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &lua_data_len, - (unsigned) sizeof lua_data_len); - bwrite(nhfp->fd, (genericptr_t) lua_data, lua_data_len); - } + Sfo_unsigned(nhfp, &lua_data_len, "luadata-lua_data_len"); + Sfo_char(nhfp, lua_data, "lua_data", lua_data_len); free(lua_data); } @@ -1288,14 +1287,10 @@ restore_luadata(NHFILE *nhfp) { unsigned lua_data_len = 0; char *lua_data; - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) &lua_data_len, - (unsigned) sizeof lua_data_len); - } + + Sfi_unsigned(nhfp, &lua_data_len, "luadata-lua_data_len"); lua_data = (char *) alloc(lua_data_len); - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) lua_data, lua_data_len); - } + Sfi_char(nhfp, lua_data, "luadata", lua_data_len); if (!gl.luacore) l_nhcore_init(); luaL_loadstring(gl.luacore, lua_data); diff --git a/src/o_init.c b/src/o_init.c index 42fbf73a1..04730e3a2 100644 --- a/src/o_init.c +++ b/src/o_init.c @@ -375,22 +375,15 @@ savenames(NHFILE *nhfp) int i; unsigned int len; - if (perform_bwrite(nhfp)) { - for (i = 0; i < (MAXOCLASSES + 2); ++i) { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &svb.bases[i], sizeof (int)); - } + if (update_file(nhfp)) { + for (i = 0; i < (MAXOCLASSES + 2); ++i) { + Sfo_int(nhfp, &svb.bases[i], "names-bases"); } for (i = 0; i < NUM_OBJECTS; ++i) { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &svd.disco[i], sizeof (short)); - } + Sfo_short(nhfp, &svd.disco[i], "names-disco"); } for (i = 0; i < NUM_OBJECTS; ++i) { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &objects[i], - sizeof (struct objclass)); - } + Sfo_objclass(nhfp, &objects[i], "names-objclass"); } } /* as long as we use only one version of Hack we @@ -398,12 +391,11 @@ savenames(NHFILE *nhfp) oc_uname for all objects */ for (i = 0; i < NUM_OBJECTS; i++) if (objects[i].oc_uname) { - if (perform_bwrite(nhfp)) { + if (update_file(nhfp)) { len = Strlen(objects[i].oc_uname) + 1; - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &len, sizeof len); - bwrite(nhfp->fd, (genericptr_t) &objects[i].oc_uname[0], len); - } + Sfo_unsigned(nhfp, &len, "names-len"); + Sfo_char(nhfp, objects[i].oc_uname, "names-oc_uname", + (int) len); } if (release_data(nhfp)) { free((genericptr_t) objects[i].oc_uname); @@ -419,30 +411,19 @@ restnames(NHFILE *nhfp) unsigned int len = 0; for (i = 0; i < (MAXOCLASSES + 2); ++i) { - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) &svb.bases[i], sizeof(int)); - } + Sfi_int(nhfp, &svb.bases[i], "names-bases"); } for (i = 0; i < NUM_OBJECTS; ++i) { - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) &svd.disco[i], sizeof(short)); - } + Sfi_short(nhfp, &svd.disco[i], "names-disco"); } for (i = 0; i < NUM_OBJECTS; ++i) { - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) &objects[i], - sizeof(struct objclass)); - } + Sfi_objclass(nhfp, &objects[i], "names-objclass"); } for (i = 0; i < NUM_OBJECTS; i++) { if (objects[i].oc_uname) { - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) &len, sizeof len); - } + Sfi_unsigned(nhfp, &len, "names-len"); objects[i].oc_uname = (char *) alloc(len); - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) &objects[i].oc_uname[0], len); - } + Sfi_char(nhfp, objects[i].oc_uname, "names-oc_uname", (int) len); } } #ifdef TILES_IN_GLYPHMAP diff --git a/src/options.c b/src/options.c index 82e1bafbb..090300fe1 100644 --- a/src/options.c +++ b/src/options.c @@ -814,7 +814,7 @@ freeroleoptvals(void) void saveoptvals(NHFILE *nhfp) { - if (perform_bwrite(nhfp)) { + if (update_file(nhfp)) { char *val; unsigned len; int i, j; @@ -823,11 +823,9 @@ saveoptvals(NHFILE *nhfp) for (j = 0; j < num_opt_phases; ++j) { val = roleoptvals[i][j]; len = val ? Strlen(val) + 1 : 0; - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &len, sizeof len); - if (val) - bwrite(nhfp->fd, (genericptr_t) val, len); - } + Sfo_unsigned(nhfp, &len, "optvals-len"); + if (val) + Sfo_char(nhfp, val, "optvals-val", len); } } if (release_data(nhfp)) @@ -846,10 +844,10 @@ restoptvals(NHFILE *nhfp) for (i = 0; i < 4; ++i) for (j = 0; j < num_opt_phases; ++j) { /* len includes terminating '\0' for non-Null values */ - mread(nhfp->fd, (genericptr_t) &len, sizeof len); + Sfi_unsigned(nhfp, &len, "optvals-len"); if (len) { val = roleoptvals[i][j] = (char *) alloc(len); - mread(nhfp->fd, (genericptr_t) val, len); + Sfi_char(nhfp, val, "opvals-val", (int) len); } else { roleoptvals[i][j] = NULL; } @@ -7127,6 +7125,8 @@ initoptions_init(void) boolean have_branch = (nomakedefs.git_branch && *nomakedefs.git_branch); go.opt_phase = builtin_opt; /* Did I need to move this here? */ + /* initialize the function pointers for saving the game */ + sf_init(); memcpy(allopt, allopt_init, sizeof(allopt)); determine_ambiguities(); @@ -7777,6 +7777,7 @@ msgtype_free(void) tmp2 = tmp->next; free((genericptr_t) tmp->pattern); regex_free(tmp->regex); + tmp->regex = 0; free((genericptr_t) tmp); } gp.plinemsg_types = (struct plinemsg_type *) 0; diff --git a/src/region.c b/src/region.c index b38ba0d7c..b0aeb1127 100644 --- a/src/region.c +++ b/src/region.c @@ -12,6 +12,7 @@ #define NO_CALLBACK (-1) +void free_region(NhRegion *); boolean inside_gas_cloud(genericptr, genericptr); boolean expire_gas_cloud(genericptr, genericptr); boolean inside_rect(NhRect *, int, int); @@ -24,7 +25,6 @@ boolean mon_in_region(NhRegion *, struct monst *); #if 0 NhRegion *clone_region(NhRegion *); #endif -void free_region(NhRegion *); void add_region(NhRegion *); void remove_region(NhRegion *); @@ -739,72 +739,49 @@ save_regions(NHFILE *nhfp) int i, j; unsigned n; - if (!perform_bwrite(nhfp)) + if (!update_file(nhfp)) goto skip_lots; - if (nhfp->structlevel) { - /* timestamp */ - bwrite(nhfp->fd, (genericptr_t) &svm.moves, sizeof svm.moves); - bwrite(nhfp->fd, (genericptr_t) &svn.n_regions, sizeof svn.n_regions); - } + /* timestamp */ + Sfo_long(nhfp, &svm.moves, "region-tmstamp"); + Sfo_int(nhfp, &svn.n_regions, "region-region_count"); + for (i = 0; i < svn.n_regions; i++) { r = gr.regions[i]; - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &r->bounding_box, - sizeof (NhRect)); - bwrite(nhfp->fd, (genericptr_t) &r->nrects, sizeof (short)); - } + Sfo_nhrect(nhfp, &r->bounding_box, "region-bounding_box"); + Sfo_short(nhfp, &r->nrects, "region-nrects"); for (j = 0; j < r->nrects; j++) { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &r->rects[j], - sizeof (NhRect)); - } + Sfo_nhrect(nhfp, &r->rects[j], "region-rect"); } - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &r->attach_2_u, sizeof (boolean)); - bwrite(nhfp->fd, (genericptr_t) &r->attach_2_m, sizeof (unsigned)); - } - + Sfo_boolean(nhfp, &r->attach_2_u, "region-attach_2_u"); + Sfo_unsigned(nhfp, &r->attach_2_m, "region-attach_2_m"); + n = 0; n = !r->enter_msg ? 0U : (unsigned) strlen(r->enter_msg); - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &n, sizeof n); - } + Sfo_unsigned(nhfp, &n, "region-enter_msg_length"); if (n > 0) { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) r->enter_msg, n); - } + Sfo_char(nhfp, (char *) r->enter_msg, + "region-enter_msg", (int) n); } n = !r->leave_msg ? 0U : (unsigned) strlen(r->leave_msg); - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &n, sizeof n); - } + Sfo_unsigned(nhfp, &n, "region-leave_msg_length"); if (n > 0) { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) r->leave_msg, n); - } - } - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &r->ttl, sizeof (long)); - bwrite(nhfp->fd, (genericptr_t) &r->expire_f, sizeof (short)); - bwrite(nhfp->fd, (genericptr_t) &r->can_enter_f, sizeof (short)); - bwrite(nhfp->fd, (genericptr_t) &r->enter_f, sizeof (short)); - bwrite(nhfp->fd, (genericptr_t) &r->can_leave_f, sizeof (short)); - bwrite(nhfp->fd, (genericptr_t) &r->leave_f, sizeof (short)); - bwrite(nhfp->fd, (genericptr_t) &r->inside_f, sizeof (short)); - bwrite(nhfp->fd, (genericptr_t) &r->player_flags, - sizeof (unsigned)); - bwrite(nhfp->fd, (genericptr_t) &r->n_monst, sizeof (short)); + Sfo_char(nhfp, (char *) r->leave_msg, "region-leave_msg", (int) n); } + Sfo_long(nhfp, &r->ttl, "region-ttl"); + Sfo_short(nhfp, &r->expire_f, "region-expire_f"); + Sfo_short(nhfp, &r->can_enter_f, "region-can_enter_f"); + Sfo_short(nhfp, &r->enter_f, "region-enter_f"); + Sfo_short(nhfp, &r->can_leave_f, "region-can_leave_f"); + Sfo_short(nhfp, &r->leave_f, "region-leave_f"); + Sfo_short(nhfp, &r->inside_f, "region-inside_f"); + Sfo_unsigned(nhfp, &r->player_flags, "region-player_flags"); + Sfo_short(nhfp, &r->n_monst, "region-monster_count"); + for (j = 0; j < r->n_monst; j++) { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &r->monsters[j], - sizeof (unsigned)); - } - } - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &r->visible, sizeof (boolean)); - bwrite(nhfp->fd, (genericptr_t) &r->glyph, sizeof (int)); - bwrite(nhfp->fd, (genericptr_t) &r->arg, sizeof (anything)); + Sfo_unsigned(nhfp, &r->monsters[j], "region-monster"); } + Sfo_boolean(nhfp, &r->visible, "region-visible"); + Sfo_int(nhfp, &r->glyph, "region-glyph"); + Sfo_any(nhfp, &r->arg, "region-arg"); } skip_lots: @@ -823,105 +800,77 @@ rest_regions(NHFILE *nhfp) boolean ghostly = (nhfp->ftype == NHF_BONESFILE); clear_regions(); /* Just for security */ - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) &tmstamp, sizeof(tmstamp)); - } + Sfi_long(nhfp, &tmstamp, "region-tmstamp"); if (ghostly) tmstamp = 0; else tmstamp = (svm.moves - tmstamp); - - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) &svn.n_regions, sizeof svn.n_regions); - } - + Sfi_int(nhfp, &svn.n_regions, "region-region_count"); gm.max_regions = svn.n_regions; if (svn.n_regions > 0) gr.regions = (NhRegion **) alloc(svn.n_regions * sizeof (NhRegion *)); for (i = 0; i < svn.n_regions; i++) { r = gr.regions[i] = (NhRegion *) alloc(sizeof (NhRegion)); - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) &r->bounding_box, sizeof (NhRect)); - mread(nhfp->fd, (genericptr_t) &r->nrects, sizeof (short)); - } + Sfi_nhrect(nhfp, &r->bounding_box, "region-bounding box"); + Sfi_short(nhfp, &r->nrects, "region-nrects"); if (r->nrects > 0) r->rects = (NhRect *) alloc(r->nrects * sizeof (NhRect)); else r->rects = (NhRect *) 0; for (j = 0; j < r->nrects; j++) { - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) &r->rects[j], sizeof(NhRect)); - } - } - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) &r->attach_2_u, sizeof (boolean)); - mread(nhfp->fd, (genericptr_t) &r->attach_2_m, sizeof (unsigned)); - mread(nhfp->fd, (genericptr_t) &n, sizeof n); + Sfi_nhrect(nhfp, &r->rects[j], "region-rect"); } + + Sfi_boolean(nhfp, &r->attach_2_u, "region-attach_2_u"); + Sfi_unsigned(nhfp, &r->attach_2_m, "region-attach_2_m"); + Sfi_unsigned(nhfp, &n, "region-enter_msg_length"); if (n > 0) { msg_buf = (char *) alloc(n + 1); - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) msg_buf, n); - } + Sfi_char(nhfp, msg_buf, "region-enter_msg", n); msg_buf[n] = '\0'; } else { msg_buf = (char *) 0; } r->enter_msg = (const char *) msg_buf; - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) &n, sizeof n); - } - if (n > 0) { + Sfi_unsigned(nhfp, &n, "region-leave_msg_length"); + if (n > 0) { msg_buf = (char *) alloc(n + 1); - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) msg_buf, n); - } + Sfi_char(nhfp, msg_buf, "region-leave_msg", n); msg_buf[n] = '\0'; - } else { - msg_buf = (char *) 0; - } - r->leave_msg = (const char *) msg_buf; + r->leave_msg = (const char *) msg_buf; + } else { + msg_buf = (char *) 0; + } + r->leave_msg = (const char *) msg_buf; - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) &r->ttl, sizeof(long)); - } + Sfi_long(nhfp, &r->ttl, "region-ttl"); /* check for expired region */ if (r->ttl >= 0L) r->ttl = (r->ttl > tmstamp) ? r->ttl - tmstamp : 0L; - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) &r->expire_f, sizeof (short)); - mread(nhfp->fd, (genericptr_t) &r->can_enter_f, sizeof (short)); - mread(nhfp->fd, (genericptr_t) &r->enter_f, sizeof (short)); - mread(nhfp->fd, (genericptr_t) &r->can_leave_f, sizeof (short)); - mread(nhfp->fd, (genericptr_t) &r->leave_f, sizeof (short)); - mread(nhfp->fd, (genericptr_t) &r->inside_f, sizeof (short)); - mread(nhfp->fd, (genericptr_t) &r->player_flags, - sizeof (unsigned)); - } + Sfi_short(nhfp, &r->expire_f, "region-expire_f"); + Sfi_short(nhfp, &r->can_enter_f, "region-can_enter_f"); + Sfi_short(nhfp, &r->enter_f, "region-enter_f"); + Sfi_short(nhfp, &r->can_leave_f, "region-can_leave_f"); + Sfi_short(nhfp, &r->leave_f, "region-leave_f"); + Sfi_short(nhfp, &r->inside_f, "region-inside_f"); + Sfi_unsigned(nhfp, &r->player_flags, "region-player_flags"); if (ghostly) { /* settings pertained to old player */ clear_hero_inside(r); clear_heros_fault(r); } - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) &r->n_monst, sizeof (short)); - } + Sfi_short(nhfp, &r->n_monst, "region-monster_count"); if (r->n_monst > 0) r->monsters = (unsigned *) alloc(r->n_monst * sizeof (unsigned)); else r->monsters = (unsigned *) 0; r->max_monst = r->n_monst; for (j = 0; j < r->n_monst; j++) { - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) &r->monsters[j], - sizeof(unsigned)); - } - } - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) &r->visible, sizeof (boolean)); - mread(nhfp->fd, (genericptr_t) &r->glyph, sizeof (int)); - mread(nhfp->fd, (genericptr_t) &r->arg, sizeof (anything)); + Sfi_unsigned(nhfp, &r->monsters[j], "region-monster"); } + Sfi_boolean(nhfp, &r->visible, "region-visible"); + Sfi_int(nhfp, &r->glyph, "region-glyph"); + Sfi_any(nhfp, &r->arg, "region-arg"); } /* remove expired regions, do not trigger the expire_f callback (yet!); also update monster lists if this data is coming from a bones file */ diff --git a/src/restore.c b/src/restore.c index dc89bd33d..77e4e2383 100644 --- a/src/restore.c +++ b/src/restore.c @@ -59,12 +59,8 @@ extern int amii_numcolors; #define Is_IceBox(o) ((o)->otyp == ICE_BOX ? TRUE : FALSE) -/* third arg passed to mread() should be 'unsigned' but most calls use - sizeof so are attempting to pass 'size_t'; mread()'s prototype results - in an implicit conversion; this macro does it explicitly */ -#define Mread(fd,adr,siz) mread((fd), (genericptr_t) (adr), (unsigned) (siz)) - /* Recalculate svl.level.objects[x][y], since this info was not saved. */ + staticfn void find_lev_obj(void) { @@ -129,14 +125,10 @@ restlevchn(NHFILE *nhfp) s_level *tmplev, *x; svs.sp_levchn = (s_level *) 0; - if (nhfp->structlevel) { - Mread(nhfp->fd, &cnt, sizeof cnt); - } + Sfi_int(nhfp, &cnt, "levchn-lev_count"); for (; cnt > 0; cnt--) { tmplev = (s_level *) alloc(sizeof(s_level)); - if (nhfp->structlevel) { - Mread(nhfp->fd, tmplev, sizeof *tmplev); - } + Sfi_s_level(nhfp, tmplev, "levchn-s_level"); if (!svs.sp_levchn) svs.sp_levchn = tmplev; @@ -157,19 +149,15 @@ restdamage(NHFILE *nhfp) struct damage *tmp_dam; boolean ghostly = (nhfp->ftype == NHF_BONESFILE); - if (nhfp->structlevel) { - Mread(nhfp->fd, &dmgcount, sizeof dmgcount); - } + Sfi_unsigned(nhfp, &dmgcount, "damage-damage_count"); counter = (int) dmgcount; if (!counter) return; do { tmp_dam = (struct damage *) alloc(sizeof *tmp_dam); - if (nhfp->structlevel) { - Mread(nhfp->fd, tmp_dam, sizeof *tmp_dam); - } + Sfi_damage(nhfp, tmp_dam, "damage"); if (ghostly) tmp_dam->when += (svm.moves - svo.omoves); @@ -183,11 +171,9 @@ staticfn void restobj(NHFILE *nhfp, struct obj *otmp) { int buflen = 0; + unsigned omid = 0; - if (nhfp->structlevel) { - Mread(nhfp->fd, otmp, sizeof *otmp); - } - + Sfi_obj(nhfp, otmp, "obj"); otmp->lua_ref_cnt = 0; /* next object pointers are invalid; otmp->cobj needs to be left as is--being non-null is key to restoring container contents */ @@ -197,20 +183,14 @@ restobj(NHFILE *nhfp, struct obj *otmp) otmp->oextra = newoextra(); /* oname - object's name */ - if (nhfp->structlevel) { - Mread(nhfp->fd, &buflen, sizeof buflen); - } + Sfi_int(nhfp, &buflen, "obj-oname_length"); if (buflen > 0) { /* includes terminating '\0' */ new_oname(otmp, buflen); - if (nhfp->structlevel) { - Mread(nhfp->fd, ONAME(otmp), buflen); - } + Sfi_char(nhfp, ONAME(otmp), "obj-oname", buflen); } /* omonst - corpse or statue might retain full monster details */ - if (nhfp->structlevel) { - Mread(nhfp->fd, &buflen, sizeof buflen); - } + Sfi_int(nhfp, &buflen, "obj-omonst_length"); if (buflen > 0) { newomonst(otmp); /* this is actually a monst struct, so we @@ -219,24 +199,19 @@ restobj(NHFILE *nhfp, struct obj *otmp) } /* omailcmd - feedback mechanism for scroll of mail */ - if (nhfp->structlevel) { - Mread(nhfp->fd, &buflen, sizeof buflen); - } + Sfi_int(nhfp, &buflen, "obj-omail_length"); if (buflen > 0) { char *omailcmd = (char *) alloc(buflen); - if (nhfp->structlevel) { - Mread(nhfp->fd, omailcmd, buflen); - } + Sfi_char(nhfp, omailcmd, "obj-omailcmd", buflen); new_omailcmd(otmp, omailcmd); free((genericptr_t) omailcmd); } /* omid - monster id number, connecting corpse to ghost */ newomid(otmp); /* superfluous; we're already allocated otmp->oextra */ - if (nhfp->structlevel) { - Mread(nhfp->fd, &OMID(otmp), sizeof OMID(otmp)); - } + Sfi_unsigned(nhfp, &omid, "obj-omid_length"); + OMID(otmp) = omid; } } @@ -249,9 +224,7 @@ restobjchn(NHFILE *nhfp, boolean frozen) boolean ghostly = (nhfp->ftype == NHF_BONESFILE); while (1) { - if (nhfp->structlevel) { - Mread(nhfp->fd, &buflen, sizeof buflen); - } + Sfi_int(nhfp, &buflen, "obj-obj_length"); if (buflen == -1) break; @@ -287,6 +260,7 @@ restobjchn(NHFILE *nhfp, boolean frozen) for (otmp3 = otmp->cobj; otmp3; otmp3 = otmp3->nobj) otmp3->ocontainer = otmp; } + if (otmp->bypass) otmp->bypass = 0; if (!ghostly) { @@ -304,7 +278,6 @@ restobjchn(NHFILE *nhfp, boolean frozen) impossible("Restobjchn: error reading objchn."); otmp2->nobj = 0; } - return first; } @@ -314,9 +287,7 @@ restmon(NHFILE *nhfp, struct monst *mtmp) { int buflen = 0, mc = 0; - if (nhfp->structlevel) { - Mread(nhfp->fd, mtmp, sizeof *mtmp); - } + Sfi_monst(nhfp, mtmp, "monst"); /* next monster pointer is invalid */ mtmp->nmon = (struct monst *) 0; @@ -325,84 +296,54 @@ restmon(NHFILE *nhfp, struct monst *mtmp) mtmp->mextra = newmextra(); /* mgivenname - monster's name */ - if (nhfp->structlevel) { - Mread(nhfp->fd, &buflen, sizeof buflen); - } + Sfi_int(nhfp, &buflen, "monst-mgivenname_length"); if (buflen > 0) { /* includes terminating '\0' */ new_mgivenname(mtmp, buflen); - if (nhfp->structlevel) { - Mread(nhfp->fd, MGIVENNAME(mtmp), buflen); - } + Sfi_char(nhfp, MGIVENNAME(mtmp), "monst-mgivenname", (int) buflen); } /* egd - vault guard */ - if (nhfp->structlevel) { - Mread(nhfp->fd, &buflen, sizeof buflen); - } + Sfi_int(nhfp, &buflen, "monst-egd_length"); if (buflen > 0) { newegd(mtmp); - if (nhfp->structlevel) { - Mread(nhfp->fd, EGD(mtmp), sizeof(struct egd)); - } + Sfi_egd(nhfp, EGD(mtmp), "monst-egd"); } /* epri - temple priest */ - if (nhfp->structlevel) { - Mread(nhfp->fd, &buflen, sizeof buflen); - } + Sfi_int(nhfp, &buflen, "monst-epri_length"); if (buflen > 0) { newepri(mtmp); - if (nhfp->structlevel) { - Mread(nhfp->fd, EPRI(mtmp), sizeof(struct epri)); - } + Sfi_epri(nhfp, EPRI(mtmp), "monst-epri"); } /* eshk - shopkeeper */ - if (nhfp->structlevel) { - Mread(nhfp->fd, &buflen, sizeof buflen); - } + Sfi_int(nhfp, &buflen, "monst-eshk_length"); if (buflen > 0) { neweshk(mtmp); - if (nhfp->structlevel) { - Mread(nhfp->fd, ESHK(mtmp), sizeof(struct eshk)); - } + Sfi_eshk(nhfp, ESHK(mtmp), "monst-eshk"); } /* emin - minion */ - if (nhfp->structlevel) { - Mread(nhfp->fd, &buflen, sizeof buflen); - } + Sfi_int(nhfp, &buflen, "monst-emin_length"); if (buflen > 0) { newemin(mtmp); - if (nhfp->structlevel) { - Mread(nhfp->fd, EMIN(mtmp), sizeof(struct emin)); - } + Sfi_emin(nhfp, EMIN(mtmp), "monst-emin"); } /* edog - pet */ - if (nhfp->structlevel) { - Mread(nhfp->fd, &buflen, sizeof buflen); - } + Sfi_int(nhfp, &buflen, "monst-edog_length"); if (buflen > 0) { newedog(mtmp); - if (nhfp->structlevel) { - Mread(nhfp->fd, EDOG(mtmp), sizeof(struct edog)); - } + Sfi_edog(nhfp, EDOG(mtmp), "monst-edog"); /* sanity check to prevent rn2(0) */ if (EDOG(mtmp)->apport <= 0) { EDOG(mtmp)->apport = 1; } } /* ebones */ - if (nhfp->structlevel) { - Mread(nhfp->fd, &buflen, sizeof buflen); - } + Sfi_int(nhfp, &buflen, "monst-ebones_length"); if (buflen > 0) { newebones(mtmp); - if (nhfp->structlevel) { - Mread(nhfp->fd, EBONES(mtmp), sizeof(struct ebones)); - } + Sfi_ebones(nhfp, EBONES(mtmp), "monst-ebones"); } /* mcorpsenm - obj->corpsenm for mimic posing as corpse or statue (inline int rather than pointer to something) */ - if (nhfp->structlevel) { - Mread(nhfp->fd, &mc, sizeof mc); - } + Sfi_int(nhfp, &mc, "monst-mcorpsenm"); MCORPSENM(mtmp) = mc; } /* mextra */ } @@ -416,9 +357,7 @@ restmonchn(NHFILE *nhfp) boolean ghostly = (nhfp->ftype == NHF_BONESFILE); while (1) { - if (nhfp->structlevel) { - Mread(nhfp->fd, &buflen, sizeof buflen); - } + Sfi_int(nhfp, &buflen, "monst-monst_length"); if (buflen == -1) break; @@ -494,9 +433,7 @@ loadfruitchn(NHFILE *nhfp) flist = 0; for (;;) { fnext = newfruit(); - if (nhfp->structlevel) { - Mread(nhfp->fd, fnext, sizeof *fnext); - } + Sfi_fruit(nhfp, fnext, "fruit"); if (fnext->fid != 0) { fnext->nextf = flist; flist = fnext; @@ -546,29 +483,29 @@ restgamestate(NHFILE *nhfp) int i; struct flag newgameflags; struct context_info newgamecontext; /* all 0, but has some pointers */ - struct obj *otmp; struct obj *bc_obj; char timebuf[15]; unsigned long uid = 0; boolean defer_perm_invent, restoring_special; + struct obj *otmp; - if (nhfp->structlevel) { - Mread(nhfp->fd, &uid, sizeof uid); - } - + Sfi_ulong(nhfp, &uid, "gamestate-uid"); if (SYSOPT_CHECK_SAVE_UID && uid != (unsigned long) getuid()) { /* strange ... */ - /* for wizard mode, issue a reminder; for others, treat it - as an attempt to cheat and refuse to restore this file */ - pline("Saved game was not yours."); - if (!wizard) + if (!gc.converted_savefile_loaded) + /* for wizard mode, issue a reminder; for others, treat it + as an attempt to cheat and refuse to restore this file */ + pline("Saved game was not yours."); + if (wizard || gc.converted_savefile_loaded) { + if (gc.converted_savefile_loaded) + gc.converted_savefile_loaded = FALSE; + } else { return FALSE; + } } newgamecontext = svc.context; /* copy statically init'd context */ - if (nhfp->structlevel) { - Mread(nhfp->fd, &svc.context, sizeof svc.context); - } + Sfi_context_info(nhfp, &svc.context, "gamestate-context"); svc.context.warntype.species = (ismnum(svc.context.warntype.speciesidx)) ? &mons[svc.context.warntype.speciesidx] : (struct permonst *) 0; @@ -580,9 +517,7 @@ restgamestate(NHFILE *nhfp) file option values instead of keeping old save file option values if partial restore fails and we resort to starting a new game */ newgameflags = flags; - if (nhfp->structlevel) { - Mread(nhfp->fd, &flags, sizeof flags); - } + Sfi_flag(nhfp, &flags, "gamestate-flags"); /* avoid keeping permanent inventory window up to date during restore (setworn() calls update_inventory); attempting to include the cost @@ -610,9 +545,8 @@ restgamestate(NHFILE *nhfp) #ifdef AMII_GRAPHICS amii_setpens(amii_numcolors); /* use colors from save file */ #endif - if (nhfp->structlevel) { - Mread(nhfp->fd, &u, sizeof u); - } + + Sfi_you(nhfp, &u, "gamestate-you"); gy.youmonst.cham = u.mcham; if (restoring_special && iflags.explore_error_flag) { @@ -622,17 +556,11 @@ restgamestate(NHFILE *nhfp) u.uhp = 0; } - if (nhfp->structlevel) { - Mread(nhfp->fd, timebuf, 14); - } + Sfi_char(nhfp, timebuf, "gamestate-ubirthday", 14); timebuf[14] = '\0'; ubirthday = time_from_yyyymmddhhmmss(timebuf); - if (nhfp->structlevel) { - Mread(nhfp->fd, &urealtime.realtime, sizeof urealtime.realtime); - } - if (nhfp->structlevel) { - Mread(nhfp->fd, timebuf, 14); - } + Sfi_long(nhfp, &urealtime.realtime, "gamestate-realtime"); + Sfi_char(nhfp, timebuf, "gamestate-start_timing", 14); timebuf[14] = '\0'; urealtime.start_timing = time_from_yyyymmddhhmmss(timebuf); @@ -672,6 +600,7 @@ restgamestate(NHFILE *nhfp) /* restore dangling (not on floor or in inventory) ball and/or chain */ bc_obj = restobjchn(nhfp, FALSE); + while (bc_obj) { struct obj *nobj = bc_obj->nobj; @@ -680,13 +609,12 @@ restgamestate(NHFILE *nhfp) setworn(bc_obj, bc_obj->owornmask); bc_obj = nobj; } + gm.migrating_objs = restobjchn(nhfp, FALSE); gm.migrating_mons = restmonchn(nhfp); for (i = 0; i < NUMMONS; ++i) { - if (nhfp->structlevel) { - Mread(nhfp->fd, &svm.mvitals[i], sizeof (struct mvitals)); - } + Sfi_mvitals(nhfp, &svm.mvitals[i], "gamestate-mvitals"); } /* * There are some things after this that can have unintended display @@ -712,26 +640,19 @@ restgamestate(NHFILE *nhfp) restore_dungeon(nhfp); restlevchn(nhfp); - if (nhfp->structlevel) { - Mread(nhfp->fd, &svm.moves, sizeof svm.moves); - } + Sfi_long(nhfp, &svm.moves, "gamestate-moves"); /* hero_seq isn't saved and restored because it can be recalculated */ gh.hero_seq = svm.moves << 3; /* normally handled in moveloop() */ - if (nhfp->structlevel) { - Mread(nhfp->fd, &svq.quest_status, sizeof svq.quest_status); - } + Sfi_q_score(nhfp, &svq.quest_status, "gamestate-quest_status"); + for (i = 0; i < (MAXSPELL + 1); ++i) { - if (nhfp->structlevel) { - Mread(nhfp->fd, &svs.spl_book[i], - sizeof (struct spell)); - } + Sfi_spell(nhfp, &svs.spl_book[i], "gamestate-spl_book"); } restore_artifacts(nhfp); restore_oracles(nhfp); - if (nhfp->structlevel) { - Mread(nhfp->fd, svp.pl_character, sizeof svp.pl_character); - Mread(nhfp->fd, svp.pl_fruit, sizeof svp.pl_fruit); - } + Sfi_char(nhfp, svp.pl_character, + "gamestate-pl_character", sizeof svp.pl_character); + Sfi_char(nhfp, svp.pl_fruit, "gamestate-pl_fruit", sizeof svp.pl_fruit); freefruitchn(gf.ffruit); /* clean up fruit(s) made by initoptions() */ gf.ffruit = loadfruitchn(nhfp); @@ -782,6 +703,21 @@ restlevelfile(xint8 ltmp) return 2; } +/* + * restore_saved_game() prior to this left us at this position in + * the savefile for dorecover(): + * + * format indicator (1 byte) + * n = count of critical size list (1 byte) + * n bytes of critical sizes (n bytes) + * version info + * --> plnametmp = player name size (int, 2 bytes) + * player name (PL_NSIZ_PLUS) + * current level (including pets) + * (non-level-based) game state + * other levels + */ + int dorecover(NHFILE *nhfp) { @@ -792,6 +728,19 @@ dorecover(NHFILE *nhfp) program_state.restoring = REST_GSTATE; get_plname_from_file(nhfp, svp.plname, TRUE); + /* + * The position in the save file is now here: + * + * format indicator (1 byte) + * n = count of critical size list (1 byte) + * n bytes of critical sizes (n bytes) + * version info + * plnametmp = player name size (int, 2 bytes) + * player name (PL_NSIZ_PLUS) + * --> current level (including pets) + * (non-level-based) game state + * other levels + */ getlev(nhfp, 0, (xint8) 0); if (!restgamestate(nhfp)) { NHFILE tnhfp; @@ -855,10 +804,8 @@ dorecover(NHFILE *nhfp) #endif restoreinfo.mread_flags = 1; /* return despite error */ while (1) { - if (nhfp->structlevel) { - Mread(nhfp->fd, <mp, sizeof ltmp); - } - if (restoreinfo.mread_flags == -1) + Sfi_xint8(nhfp, <mp, "gamestate-level_number"); + if (nhfp->eof) break; getlev(nhfp, 0, ltmp); #ifdef MICRO @@ -949,16 +896,11 @@ rest_stairs(NHFILE *nhfp) stairway_free_all(); while (1) { - if (nhfp->structlevel) { - Mread(nhfp->fd, &buflen, sizeof buflen); - } - + Sfi_int(nhfp, &buflen, "stairs-staircount"); if (buflen == -1) break; - if (nhfp->structlevel) { - Mread(nhfp->fd, &stway, sizeof stway); - } + Sfi_stairway(nhfp, &stway, "stairs-stairway"); if (program_state.restoring != REST_GSTATE && stway.tolev.dnum == u.uz.dnum) { /* stairway dlevel is relative, make it absolute */ @@ -978,22 +920,29 @@ restcemetery(NHFILE *nhfp, struct cemetery **cemeteryaddr) struct cemetery *bonesinfo, **bonesaddr; int cflag = 0; - if (nhfp->structlevel) { - Mread(nhfp->fd, &cflag, sizeof cflag); - } + Sfi_int(nhfp, &cflag, "cemetery-cemetery_flag"); if (cflag == 0) { bonesaddr = cemeteryaddr; do { bonesinfo = (struct cemetery *) alloc(sizeof *bonesinfo); - if (nhfp->structlevel) { - Mread(nhfp->fd, bonesinfo, sizeof *bonesinfo); - } + Sfi_cemetery(nhfp, bonesinfo, "cemetery-bonesinfo"); *bonesaddr = bonesinfo; bonesaddr = &(*bonesaddr)->next; } while (*bonesaddr); } else { *cemeteryaddr = 0; } + if ((nhfp->mode & CONVERTING) != 0) { + struct cemetery *thisbones, *nextbones; + + /* free the memory */ + nextbones = *cemeteryaddr; + while ((thisbones = nextbones) != 0) { + nextbones = thisbones->next; + free((genericptr_t)thisbones); + } + *cemeteryaddr = 0; + } } /*ARGSUSED*/ @@ -1004,9 +953,7 @@ rest_levl(NHFILE *nhfp) for (c = 0; c < COLNO; ++c) { for (r = 0; r < ROWNO; ++r) { - if (nhfp->structlevel) { - Mread(nhfp->fd, &levl[c][r], sizeof (struct rm)); - } + Sfi_rm(nhfp, &levl[c][r], "location-rm"); } } } @@ -1043,10 +990,13 @@ getlev(NHFILE *nhfp, int pid, xint8 lev) if (ghostly) clear_id_mapping(); +#if 0 #if defined(MSDOS) || defined(OS2) if (nhfp->structlevel) setmode(nhfp->fd, O_BINARY); #endif +#endif + /* Load the old fruit info. We have to do it first, so the * information is available when restoring the objects. */ @@ -1054,13 +1004,9 @@ getlev(NHFILE *nhfp, int pid, xint8 lev) go.oldfruit = loadfruitchn(nhfp); /* First some sanity checks */ - if (nhfp->structlevel) { - Mread(nhfp->fd, &hpid, sizeof hpid); - } - - if (nhfp->structlevel) { - Mread(nhfp->fd, &dlvl, sizeof dlvl); - } + Sfi_int(nhfp, &hpid, "gamestate-hackpid"); +/* CHECK: This may prevent restoration */ + Sfi_xint8(nhfp, &dlvl, "gamestate-dlvl"); if ((pid && pid != hpid) || (lev && dlvl != lev)) { char trickbuf[BUFSZ]; @@ -1075,42 +1021,38 @@ getlev(NHFILE *nhfp, int pid, xint8 lev) } restcemetery(nhfp, &svl.level.bonesinfo); rest_levl(nhfp); - for (c = 0; c < COLNO; ++c) + + for (c = 0; c < COLNO; ++c) { for (r = 0; r < ROWNO; ++r) { - if (nhfp->structlevel) { - Mread(nhfp->fd, &svl.lastseentyp[c][r], sizeof (schar)); - } - } - Mread(nhfp->fd, &svo.omoves, sizeof svo.omoves); - elapsed = svm.moves - svo.omoves; + Sfi_schar(nhfp, &svl.lastseentyp[c][r], "lastseentyp"); + } + } + Sfi_long(nhfp, &svo.omoves, "lev-timestmp"); + elapsed = (svm.moves - svo.omoves); rest_stairs(nhfp); - if (nhfp->structlevel) { - Mread(nhfp->fd, &svu.updest, sizeof svu.updest); - Mread(nhfp->fd, &svd.dndest, sizeof svd.dndest); - Mread(nhfp->fd, &svl.level.flags, sizeof svl.level.flags); - } + Sfi_dest_area(nhfp, &svu.updest, "lev-updest"); + Sfi_dest_area(nhfp, &svd.dndest, "lev-dndest"); + Sfi_levelflags(nhfp, &svl.level.flags, "lev-level_flags"); + if (svd.doors) { free(svd.doors); svd.doors = 0; } - if (nhfp->structlevel) { - Mread(nhfp->fd, &svd.doors_alloc, sizeof svd.doors_alloc); - } + + Sfi_int(nhfp, &svd.doors_alloc, "lev-doors_alloc"); if (svd.doors_alloc) { /* avoid pointless alloc(0) */ - svd.doors = (coord *) alloc(svd.doors_alloc * sizeof(coord)); + svd.doors = (coord *) alloc(svd.doors_alloc * sizeof (coord)); tmpc = svd.doors; for (i = 0; i < svd.doors_alloc; ++i) { - if (nhfp->structlevel) { - Mread(nhfp->fd, tmpc, sizeof (coord)); - } + Sfi_nhcoord(nhfp, tmpc, "lev-doors"); tmpc++; } } rest_rooms(nhfp); /* No joke :-) */ if (svn.nroom) { gd.doorindex = svr.rooms[svn.nroom - 1].fdoor - + svr.rooms[svn.nroom - 1].doorct; + + svr.rooms[svn.nroom - 1].doorct; } else { gd.doorindex = 0; } @@ -1123,9 +1065,7 @@ getlev(NHFILE *nhfp, int pid, xint8 lev) gf.ftrap = 0; for (;;) { trap = newtrap(); - if (nhfp->structlevel) { - Mread(nhfp->fd, trap, sizeof *trap); - } + Sfi_trap(nhfp, trap, "trap"); if (trap->tx != 0) { if (program_state.restoring != REST_GSTATE && trap->dst.dnum == u.uz.dnum) { @@ -1147,6 +1087,7 @@ getlev(NHFILE *nhfp, int pid, xint8 lev) gb.billobjs = restobjchn(nhfp, FALSE); rest_engravings(nhfp); + /* reset level.monsters for new level */ for (x = 0; x < COLNO; x++) for (y = 0; y < ROWNO; y++) @@ -1192,6 +1133,7 @@ getlev(NHFILE *nhfp, int pid, xint8 lev) if (ghostly || (elapsed > 00 && elapsed > (long) rnd(10))) hide_monst(mtmp); } + restdamage(nhfp); rest_regions(nhfp); rest_bubbles(nhfp); /* for water and air; empty marker on other levels */ @@ -1265,7 +1207,6 @@ getlev(NHFILE *nhfp, int pid, xint8 lev) } } } - /* must come after all mons & objs are restored */ relink_timers(ghostly); relink_light_sources(ghostly); @@ -1288,13 +1229,12 @@ get_plname_from_file( int pltmpsiz = 0; plbuf[0] = '\0'; - if (nhfp->structlevel) { - (void) read(nhfp->fd, (genericptr_t) &pltmpsiz, sizeof pltmpsiz); - /* pltmpsiz should now be PL_NSIZ_PLUS */ - (void) read(nhfp->fd, (genericptr_t) plbuf, pltmpsiz); - /* plbuf[PL_NSIZ_PLUS-2] should be '\0'; - plbuf[PL_NSIZ_PLUS-1] should be '-' or 'X' or 'D' */ - } + + Sfi_int(nhfp, &pltmpsiz, "plname-size"); + /* pltmpsiz should now be PL_NSIZ_PLUS */ + Sfi_char(nhfp, plbuf, "plname", pltmpsiz); + /* plbuf[PL_NSIZ_PLUS-2] should be '\0'; + plbuf[PL_NSIZ_PLUS-1] should be '-' or 'X' or 'D' */ /* "-race-role-gend-algn" is already present except that it has been hidden by replacing the initial dash with NUL; if we want that information, replace the NUL with a dash */ @@ -1316,10 +1256,11 @@ rest_bubbles(NHFILE *nhfp) clouds are present is recorded during save so that we don't have to know what level is being restored */ bbubbly = 0; - if (nhfp->structlevel) { - Mread(nhfp->fd, &bbubbly, sizeof bbubbly); - } - + Sfi_xint8(nhfp, &bbubbly, "bubbles-bbubbly"); +#if 0 + if (nhfp->structlevel) + xxread(nhfp->fd, &bbubbly, sizeof bbubbly); +#endif if (bbubbly) restore_waterlevel(nhfp); } @@ -1332,20 +1273,14 @@ restore_gamelog(NHFILE *nhfp) struct gamelog_line tmp = { 0 }; while (1) { - if (nhfp->structlevel) { - Mread(nhfp->fd, &slen, sizeof slen); - } + Sfi_int(nhfp, &slen, "gamelog-length"); if (slen == -1) break; if (slen > ((BUFSZ*2) - 1)) panic("restore_gamelog: msg too big (%d)", slen); - if (nhfp->structlevel) { - Mread(nhfp->fd, msg, slen); - } + Sfi_char(nhfp, msg, "gamelog-gamelog_text", slen); msg[slen] = '\0'; - if (nhfp->structlevel) { - Mread(nhfp->fd, &tmp, sizeof tmp); - } + Sfi_gamelog_line(nhfp, &tmp, "gamelog-gamelog_line"); gamelog_add(tmp.flags, tmp.turn, msg); } } @@ -1353,20 +1288,17 @@ restore_gamelog(NHFILE *nhfp) staticfn void restore_msghistory(NHFILE *nhfp) { - int msgsize = 0, msgcount = 0; + int msgsize = 0; + int msgcount = 0; char msg[BUFSZ]; while (1) { - if (nhfp->structlevel) { - Mread(nhfp->fd, &msgsize, sizeof msgsize); - } + Sfi_int(nhfp, &msgsize, "msghistory-length"); if (msgsize == -1) break; if (msgsize > BUFSZ - 1) panic("restore_msghistory: msg too big (%d)", msgsize); - if (nhfp->structlevel) { - Mread(nhfp->fd, msg, msgsize); - } + Sfi_char(nhfp, msg, "msghistory-msg", msgsize); msg[msgsize] = '\0'; putmsghistory(msg, TRUE); ++msgcount; @@ -1552,22 +1484,4 @@ restore_menu( } #endif /* SELECTSAVED */ -int -validate(NHFILE *nhfp, const char *name, boolean without_waitsynch_perfile) -{ - unsigned long utdflags = 0L; - boolean reslt = FALSE; - - if (nhfp->structlevel) - utdflags |= UTD_CHECKSIZES; - if (without_waitsynch_perfile) - utdflags |= UTD_WITHOUT_WAITSYNCH_PERFILE; - if (!(reslt = uptodate(nhfp, name, utdflags))) - return 1; - - return 0; -} - -#undef Mread - /*restore.c*/ diff --git a/src/rumors.c b/src/rumors.c index d1d709516..2e58d6225 100644 --- a/src/rumors.c +++ b/src/rumors.c @@ -584,10 +584,10 @@ init_oracles(dlb *fp) (void) dlb_fgets(line, sizeof line, fp); if (sscanf(line, "%5d\n", &cnt) == 1 && cnt > 0) { svo.oracle_cnt = (unsigned) cnt; - go.oracle_loc = (unsigned long *) alloc((unsigned) cnt * sizeof(long)); + svo.oracle_loc = (unsigned long *) alloc((unsigned) cnt * sizeof(long)); for (i = 0; i < cnt; i++) { (void) dlb_fgets(line, sizeof line, fp); - (void) sscanf(line, "%5lx\n", &go.oracle_loc[i]); + (void) sscanf(line, "%5lx\n", &svo.oracle_loc[i]); } } return; @@ -598,17 +598,11 @@ save_oracles(NHFILE *nhfp) { int i; - if (perform_bwrite(nhfp)) { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &svo.oracle_cnt, - sizeof svo.oracle_cnt); - } + if (update_file(nhfp)) { + Sfo_unsigned(nhfp, &svo.oracle_cnt, "oracle-oracle_cnt"); if (svo.oracle_cnt) { for (i = 0; (unsigned) i < svo.oracle_cnt; ++i) { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &go.oracle_loc[i], - sizeof (unsigned long)); - } + Sfo_ulong(nhfp, &svo.oracle_loc[i], "oracle-oracle_loc"); } } } @@ -616,9 +610,8 @@ save_oracles(NHFILE *nhfp) if (svo.oracle_cnt) { svo.oracle_cnt = 0, go.oracle_flg = 0; } - if (go.oracle_loc) { - free((genericptr_t) go.oracle_loc); - go.oracle_loc = 0; + if (svo.oracle_loc) { + free((genericptr_t) svo.oracle_loc); } } } @@ -628,18 +621,12 @@ restore_oracles(NHFILE *nhfp) { int i; - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) &svo.oracle_cnt, - sizeof svo.oracle_cnt); - } + Sfi_unsigned(nhfp, &svo.oracle_cnt, "oracle-oracle_cnt"); if (svo.oracle_cnt) { - go.oracle_loc = + svo.oracle_loc = (unsigned long *) alloc(svo.oracle_cnt * sizeof (unsigned long)); for (i = 0; (unsigned) i < svo.oracle_cnt; ++i) { - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) &go.oracle_loc[i], - sizeof (unsigned long)); - } + Sfi_ulong(nhfp, &svo.oracle_loc[i], "oracle-oracle_loc"); } go.oracle_flg = 1; /* no need to call init_oracles() */ } @@ -672,9 +659,9 @@ outoracle(boolean special, boolean delphi) if (svo.oracle_cnt <= 1 && !special) goto close_oracles; /*(shouldn't happen)*/ oracle_idx = special ? 0 : rnd((int) svo.oracle_cnt - 1); - (void) dlb_fseek(oracles, (long) go.oracle_loc[oracle_idx], SEEK_SET); + (void) dlb_fseek(oracles, (long) svo.oracle_loc[oracle_idx], SEEK_SET); if (!special) /* move offset of very last one into this slot */ - go.oracle_loc[oracle_idx] = go.oracle_loc[--svo.oracle_cnt]; + svo.oracle_loc[oracle_idx] = svo.oracle_loc[--svo.oracle_cnt]; tmpwin = create_nhwindow(NHW_TEXT); if (delphi) diff --git a/src/save.c b/src/save.c index 69b9de6cb..4e4f568a3 100644 --- a/src/save.c +++ b/src/save.c @@ -115,6 +115,7 @@ dosave0(void) clear_nhwindow(WIN_MESSAGE); There("seems to be an old save file."); if (y_n("Overwrite the old file?") == 'n') { + //nh_sfconvert(fq_save); nh_compress(fq_save); goto done; } @@ -129,6 +130,10 @@ dosave0(void) (void) delete_savefile(); /* ab@unido */ goto done; } + if (nhfp && nhfp->fplog) { + /* (void) fprintf(nhfp->fplog, "# just opened\n"); */ + nhfp->count = 0L; + } vision_recalc(2); /* shut down vision to prevent problems in the event of an impossible() call */ @@ -150,8 +155,6 @@ dosave0(void) #endif nhfp->mode = WRITING | FREEING; store_version(nhfp); - if (nhfp && nhfp->fplog) - (void) fprintf(nhfp->fplog, "# post-validation\n"); store_plname_in_file(nhfp); /* savelev() might save uball and uchain, releasing their memory if FREEING, so we need to check their status now; if hero is swallowed, @@ -206,9 +209,7 @@ dosave0(void) } getlev(onhfp, svh.hackpid, ltmp); close_nhfile(onhfp); - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) <mp, sizeof ltmp); /* lvl no. */ - } + Sfo_xint8(nhfp, <mp, "gamestate-level_number"); savelev(nhfp, ltmp); /* actual level*/ delete_levelfile(ltmp); } @@ -220,6 +221,7 @@ dosave0(void) /* get rid of current level --jgm */ delete_levelfile(ledger_no(&u.uz)); delete_levelfile(0); + ///nh_sfconvert(fq_save); nh_compress(fq_save); /* this should probably come sooner... */ program_state.something_worth_saving = 0; @@ -239,28 +241,23 @@ save_gamelog(NHFILE *nhfp) while (tmp) { tmp2 = tmp->next; - if (perform_bwrite(nhfp)) { + if (nhfp->mode & (COUNTING | WRITING)) { slen = Strlen(tmp->text); - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &slen, sizeof slen); - bwrite(nhfp->fd, (genericptr_t) tmp->text, slen); - bwrite(nhfp->fd, (genericptr_t) tmp, - sizeof (struct gamelog_line)); - } + Sfo_int(nhfp, &slen, "gamelog-length"); + Sfo_char(nhfp, tmp->text, "gamelog-gamelog_text", slen); + Sfo_gamelog_line(nhfp, tmp, "gamelog-gamelog_line"); } - if (release_data(nhfp)) { + if (nhfp->mode & FREEING) { free((genericptr_t) tmp->text); free((genericptr_t) tmp); } tmp = tmp2; } - if (perform_bwrite(nhfp)) { + if (nhfp->mode & (COUNTING | WRITING)) { slen = -1; - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &slen, sizeof slen); - } + Sfo_int(nhfp, &slen, "gamelog-length"); } - if (release_data(nhfp)) + if (nhfp->mode & FREEING) gg.gamelog = NULL; } @@ -272,21 +269,16 @@ savegamestate(NHFILE *nhfp) program_state.saving++; /* caller should/did already set this... */ uid = (unsigned long) getuid(); - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &uid, sizeof uid); - bwrite(nhfp->fd, (genericptr_t) &svc.context, sizeof svc.context); - bwrite(nhfp->fd, (genericptr_t) &flags, sizeof flags); - } + Sfo_ulong(nhfp, &uid, "gamestate-uid"); + Sfo_context_info(nhfp, &svc.context, "gamestate-context"); + Sfo_flag(nhfp, &flags, "gamestate-flags"); urealtime.finish_time = getnow(); urealtime.realtime += timet_delta(urealtime.finish_time, urealtime.start_timing); - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &u, sizeof u); - bwrite(nhfp->fd, yyyymmddhhmmss(ubirthday), 14); - bwrite(nhfp->fd, (genericptr_t) &urealtime.realtime, - sizeof urealtime.realtime); - bwrite(nhfp->fd, yyyymmddhhmmss(urealtime.start_timing), 14); - } + Sfo_you(nhfp, &u, "gamestate-you"); + Sfo_char(nhfp, yyyymmddhhmmss(ubirthday), "gamestate-ubirthday", 14); + Sfo_long(nhfp, &urealtime.realtime, "gamestate-realtime"); + Sfo_char(nhfp, yyyymmddhhmmss(urealtime.start_timing), "gamestate-start_timing", 14); /* this is the value to use for the next update of urealtime.realtime */ urealtime.start_timing = urealtime.finish_time; save_killers(nhfp); @@ -307,32 +299,20 @@ savegamestate(NHFILE *nhfp) if (release_data(nhfp)) gm.migrating_mons = (struct monst *) 0; for (i = 0; i < NUMMONS; ++i) { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &svm.mvitals[i], - sizeof (struct mvitals)); - } + Sfo_mvitals(nhfp, &svm.mvitals[i], "gamestate-mvitals"); } - save_dungeon(nhfp, (boolean) !!perform_bwrite(nhfp), + save_dungeon(nhfp, (boolean) !!update_file(nhfp), (boolean) !!release_data(nhfp)); savelevchn(nhfp); - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &svm.moves, sizeof svm.moves); - bwrite(nhfp->fd, (genericptr_t) &svq.quest_status, - sizeof svq.quest_status); - } + Sfo_long(nhfp, &svm.moves, "gamestate-moves"); + Sfo_q_score(nhfp, &svq.quest_status, "gamestate-quest_status"); for (i = 0; i < (MAXSPELL + 1); ++i) { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &svs.spl_book[i], - sizeof(struct spell)); - } + Sfo_spell(nhfp, &svs.spl_book[i], "gamestate-spl_book"); } save_artifacts(nhfp); save_oracles(nhfp); - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) svp.pl_character, - sizeof svp.pl_character); - bwrite(nhfp->fd, (genericptr_t) svp.pl_fruit, sizeof svp.pl_fruit); - } + Sfo_char(nhfp, svp.pl_character, "gamestate-pl_character", sizeof svp.pl_character); + Sfo_char(nhfp, svp.pl_fruit, "gamestate-pl_fruit", sizeof svp.pl_fruit); savefruitchn(nhfp); savenames(nhfp); save_msghistory(nhfp); @@ -391,9 +371,7 @@ savestateinlock(void) return; } - if (nhfp->structlevel) { - (void) read(nhfp->fd, (genericptr_t) &hpid, sizeof hpid); - } + Sfi_int(nhfp, &hpid, "gamestate-hackpid"); if (svh.hackpid != hpid) { Sprintf(whynot, "Level #0 pid (%d) doesn't match ours (%d)!", hpid, svh.hackpid); @@ -416,16 +394,11 @@ savestateinlock(void) return; } nhfp->mode = WRITING; - if (nhfp->structlevel) - (void) write(nhfp->fd, (genericptr_t) &svh.hackpid, - sizeof svh.hackpid); + Sfo_int(nhfp, &svh.hackpid, "gamestate-hackpid"); if (flags.ins_chkpt) { int currlev = ledger_no(&u.uz); - if (nhfp->structlevel) { - (void) write(nhfp->fd, (genericptr_t) &currlev, - sizeof currlev); - } + Sfo_int(nhfp, &currlev, "gamestate-savestateinlock"); save_savefile_name(nhfp); store_version(nhfp); store_plname_in_file(nhfp); @@ -453,7 +426,7 @@ savelev(NHFILE *nhfp, xint8 lev) if not, we need to set it for save_bubbles(); caveat: if the player quits during character selection, u.uz won't be set yet but we'll be called during run-down */ - if (set_uz_save && perform_bwrite(nhfp)) { + if (set_uz_save && (nhfp->mode & (COUNTING | WRITING))) { if (u.uz.dnum == 0 && u.uz.dlevel == 0) { program_state.something_worth_saving = 0; panic("savelev: where are we?"); @@ -511,10 +484,8 @@ savelev_core(NHFILE *nhfp, xint8 lev) if (lev >= 0 && lev <= maxledgerno()) svl.level_info[lev].flags |= VISITED; - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &svh.hackpid, sizeof svh.hackpid); - bwrite(nhfp->fd, (genericptr_t) &lev, sizeof lev); - } + Sfo_int(nhfp, &svh.hackpid, "gamestate-hackpid"); + Sfo_xint8(nhfp, &lev, "gamestate-dlvl"); } /* bones info comes before level data; the intent is for an external @@ -528,35 +499,25 @@ savelev_core(NHFILE *nhfp, xint8 lev) goto skip_lots; savelevl(nhfp); - for (c = 0; c < COLNO; ++c) + for (c = 0; c < COLNO; ++c) { for (r = 0; r < ROWNO; ++r) { - bwrite(nhfp->fd, (genericptr_t) &svl.lastseentyp[c][r], - sizeof(schar)); + Sfo_schar(nhfp, &svl.lastseentyp[c][r], "lastseentyp"); } - /* svm.moves below will actually be read back into svo.omoves on restore */ - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &svm.moves, sizeof svm.moves); } + /* svm.moves will actually be read back into svo.omoves on restore */ + Sfo_long(nhfp, &svm.moves, "lev-timestmp"); save_stairs(nhfp); - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &svu.updest, sizeof(dest_area)); - bwrite(nhfp->fd, (genericptr_t) &svd.dndest, sizeof(dest_area)); - bwrite(nhfp->fd, (genericptr_t) &svl.level.flags, - sizeof svl.level.flags); - } - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &svd.doors_alloc, - sizeof svd.doors_alloc); - } + Sfo_dest_area(nhfp, &svu.updest, "lev-updest"); + Sfo_dest_area(nhfp, &svd.dndest, "lev-dndest"); + Sfo_levelflags(nhfp, &svl.level.flags, "lev-level_flags"); + + Sfo_int(nhfp, &svd.doors_alloc, "lev-doors_alloc"); /* don't rely on underlying write() behavior to write - * nothing if count arg is 0, just skip it */ + * nothing if count arg is 0, just skip it */ if (svd.doors_alloc) { tmpc = svd.doors; for (i = 0; i < svd.doors_alloc; ++i) { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) tmpc, - sizeof (coord)); - } + Sfo_nhcoord(nhfp, tmpc, "lev-doors"); tmpc++; } } @@ -602,11 +563,8 @@ savelevl(NHFILE *nhfp) for (x = 0; x < COLNO; x++) { for (y = 0; y < ROWNO; y++) { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &levl[x][y], - sizeof(struct rm)); - } - } + Sfo_rm(nhfp, &levl[x][y], "location-rm"); + } } return; } @@ -626,9 +584,12 @@ save_bubbles(NHFILE *nhfp, xint8 lev) bbubbly = 0; if (lev == ledger_no(&water_level) || lev == ledger_no(&air_level)) bbubbly = lev; /* non-zero */ - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &bbubbly, sizeof bbubbly); - } + if (update_file(nhfp)) + Sfo_xint8(nhfp, &bbubbly, "bubbles-bbubbly"); +#if 0 + if (nhfp->structlevel) + xxwrite(nhfp->fd, (genericptr_t) &bbubbly, sizeof bbubbly); +#endif if (bbubbly) save_waterlevel(nhfp); /* save air bubbles or clouds */ @@ -642,18 +603,14 @@ savecemetery(NHFILE *nhfp, struct cemetery **cemeteryaddr) int flag; flag = *cemeteryaddr ? 0 : -1; - if (perform_bwrite(nhfp)) { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &flag, sizeof flag); - } + if (update_file(nhfp)) { + Sfo_int(nhfp, &flag, "cemetery-cemetery_flag"); } nextbones = *cemeteryaddr; while ((thisbones = nextbones) != 0) { nextbones = thisbones->next; - if (perform_bwrite(nhfp)) { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) thisbones, sizeof *thisbones); - } + if (update_file(nhfp)) { + Sfo_cemetery(nhfp, thisbones, "cemetery-bonesinfo"); } if (release_data(nhfp)) free((genericptr_t) thisbones); @@ -671,16 +628,12 @@ savedamage(NHFILE *nhfp) damageptr = svl.level.damagelist; for (tmp_dam = damageptr; tmp_dam; tmp_dam = tmp_dam->next) xl++; - if (perform_bwrite(nhfp)) { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &xl, sizeof xl); - } + if (update_file(nhfp)) { + Sfo_unsigned(nhfp, &xl, "damage-damage_count"); } while (damageptr) { - if (perform_bwrite(nhfp)) { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) damageptr, sizeof *damageptr); - } + if (update_file(nhfp)) { + Sfo_damage(nhfp, damageptr, "damage"); } tmp_dam = damageptr; damageptr = damageptr->next; @@ -698,17 +651,15 @@ save_stairs(NHFILE *nhfp) int buflen = (int) sizeof *stway; while (stway) { - if (perform_bwrite(nhfp)) { + if (update_file(nhfp)) { boolean use_relative = (program_state.restoring != REST_GSTATE && stway->tolev.dnum == u.uz.dnum); if (use_relative) { /* make dlevel relative to current level */ stway->tolev.dlevel -= u.uz.dlevel; } - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &buflen, sizeof buflen); - bwrite(nhfp->fd, (genericptr_t) stway, sizeof *stway); - } + Sfo_int(nhfp, &buflen, "stairs-staircount"); + Sfo_stairway(nhfp, stway, "stairs-stairway"); if (use_relative) { /* reset stairway dlevel back to absolute */ stway->tolev.dlevel += u.uz.dlevel; @@ -716,11 +667,9 @@ save_stairs(NHFILE *nhfp) } stway = stway->next; } - if (perform_bwrite(nhfp)) { + if (update_file(nhfp)) { buflen = -1; - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &buflen, sizeof buflen); - } + Sfo_int(nhfp, &buflen, "stairs-staircount"); } } @@ -755,51 +704,38 @@ save_bc(NHFILE *nhfp) } /* save one object; - caveat: this is only for perform_bwrite(); caller handles release_data() */ + caveat: this is only for update_file(); caller handles release_data() */ staticfn void saveobj(NHFILE *nhfp, struct obj *otmp) { int buflen, zerobuf = 0; buflen = (int) sizeof (struct obj); - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &buflen, sizeof buflen); - bwrite(nhfp->fd, (genericptr_t) otmp, buflen); - } + Sfo_int(nhfp, &buflen, "obj-obj_length"); + Sfo_obj(nhfp, otmp, "obj"); if (otmp->oextra) { buflen = ONAME(otmp) ? (int) strlen(ONAME(otmp)) + 1 : 0; - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &buflen, sizeof buflen); - } + Sfo_int(nhfp, &buflen, "obj-oname_length"); + if (buflen > 0) { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) ONAME(otmp), buflen); - } + Sfo_char(nhfp, ONAME(otmp), "obj-oname", buflen); } /* defer to savemon() for this one */ if (OMONST(otmp)) { savemon(nhfp, OMONST(otmp)); } else { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &zerobuf, sizeof zerobuf); - } + Sfo_int(nhfp, &zerobuf, "obj-omonst_length"); } /* extra info about scroll of mail */ buflen = OMAILCMD(otmp) ? (int) strlen(OMAILCMD(otmp)) + 1 : 0; - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &buflen, sizeof buflen); - } + Sfo_int(nhfp, &buflen, "obj-omailcmd_length"); if (buflen > 0) { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) OMAILCMD(otmp), buflen); - } + Sfo_char(nhfp, OMAILCMD(otmp), "obj-omailcmd", buflen); } /* omid used to be indirect via a pointer in oextra but has become part of oextra itself; 0 means not applicable and gets saved/restored whenever any other oextra components do */ - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &OMID(otmp), sizeof OMID(otmp)); - } + Sfo_unsigned(nhfp, &OMID(otmp), "obj-omid"); } } @@ -815,7 +751,7 @@ saveobjchn(NHFILE *nhfp, struct obj **obj_p) while (otmp) { otmp2 = otmp->nobj; - if (perform_bwrite(nhfp)) { + if (update_file(nhfp)) { saveobj(nhfp, otmp); } if (Has_contents(otmp)) @@ -859,10 +795,8 @@ saveobjchn(NHFILE *nhfp, struct obj **obj_p) } otmp = otmp2; } - if (perform_bwrite(nhfp)) { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &minusone, sizeof(int)); - } + if (update_file(nhfp)) { + Sfo_int(nhfp, &minusone, "obj-obj_length"); } if (release_data(nhfp)) { if (is_invent) @@ -879,80 +813,48 @@ savemon(NHFILE *nhfp, struct monst *mtmp) mtmp->mtemplit = 0; /* normally clear; if set here then a panic save * is being written while bhit() was executing */ buflen = (int) sizeof (struct monst); - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &buflen, sizeof buflen); - bwrite(nhfp->fd, (genericptr_t) mtmp, buflen); - } + Sfo_int(nhfp, &buflen, "monst-monst_length"); + Sfo_monst(nhfp, mtmp, "monst"); if (mtmp->mextra) { buflen = MGIVENNAME(mtmp) ? (int) strlen(MGIVENNAME(mtmp)) + 1 : 0; - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &buflen, sizeof buflen); - } + Sfo_int(nhfp, &buflen, "monst-mgivenname_length"); if (buflen > 0) { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) MGIVENNAME(mtmp), buflen); - } + Sfo_char(nhfp, MGIVENNAME(mtmp), "monst-mgivenname", buflen); } buflen = EGD(mtmp) ? (int) sizeof (struct egd) : 0; - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &buflen, sizeof buflen); - } + Sfo_int(nhfp, &buflen, "monst-egd_length"); if (buflen > 0) { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) EGD(mtmp), buflen); - } + Sfo_egd(nhfp, EGD(mtmp), "monst-egd"); } buflen = EPRI(mtmp) ? (int) sizeof (struct epri) : 0; - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &buflen, sizeof buflen); - } + Sfo_int(nhfp, &buflen, "monst-epri_length"); if (buflen > 0) { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) EPRI(mtmp), buflen); - } + Sfo_epri(nhfp, EPRI(mtmp), "monst-epri"); } buflen = ESHK(mtmp) ? (int) sizeof (struct eshk) : 0; - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &buflen, sizeof(int)); - } + Sfo_int(nhfp, &buflen, "monst-eshk_length"); if (buflen > 0) { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) ESHK(mtmp), buflen); - } + Sfo_eshk(nhfp, ESHK(mtmp), "monst-eshk"); } buflen = EMIN(mtmp) ? (int) sizeof (struct emin) : 0; - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &buflen, sizeof(int)); - } + Sfo_int(nhfp, &buflen, "monst-emin_length"); if (buflen > 0) { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) EMIN(mtmp), buflen); - } + Sfo_emin(nhfp, EMIN(mtmp), "monst-emin"); } buflen = EDOG(mtmp) ? (int) sizeof (struct edog) : 0; - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &buflen, sizeof(int)); - } + Sfo_int(nhfp, &buflen, "monst-edog_length"); if (buflen > 0) { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) EDOG(mtmp), buflen); - } + Sfo_edog(nhfp, EDOG(mtmp), "monst-edog"); } buflen = EBONES(mtmp) ? (int) sizeof (struct ebones) : 0; - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &buflen, sizeof(int)); - } + Sfo_int(nhfp, &buflen, "monst-ebones_length"); if (buflen > 0) { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) EBONES(mtmp), buflen); - } + Sfo_ebones(nhfp, EBONES(mtmp), "monst-ebones"); } /* mcorpsenm is inline int rather than pointer to something, so doesn't need to be preceded by a length field */ buflen = (int) MCORPSENM(mtmp); - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &buflen, sizeof (int)); - } + Sfo_int(nhfp, &buflen, "monst-mcorpsenm"); } } @@ -964,7 +866,7 @@ savemonchn(NHFILE *nhfp, struct monst *mtmp) while (mtmp) { mtmp2 = mtmp->nmon; - if (perform_bwrite(nhfp)) { + if (update_file(nhfp)) { mtmp->mnum = monsndx(mtmp->data); if (mtmp->ispriest) forget_temple_entry(mtmp); /* EPRI() */ @@ -986,10 +888,8 @@ savemonchn(NHFILE *nhfp, struct monst *mtmp) } mtmp = mtmp2; } - if (perform_bwrite(nhfp)) { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &minusone, sizeof(int)); - } + if (update_file(nhfp)) { + Sfo_int(nhfp, &minusone, "monst-monst_length"); } } @@ -1006,10 +906,8 @@ savetrapchn(NHFILE *nhfp, struct trap *trap) trap2 = trap->ntrap; if (use_relative) trap->dst.dlevel -= u.uz.dlevel; /* make it relative */ - if (perform_bwrite(nhfp)) { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) trap, sizeof *trap); - } + if (update_file(nhfp)) { + Sfo_trap(nhfp, trap, "trap"); } if (use_relative) trap->dst.dlevel += u.uz.dlevel; /* reset back to absolute */ @@ -1017,10 +915,8 @@ savetrapchn(NHFILE *nhfp, struct trap *trap) dealloc_trap(trap); trap = trap2; } - if (perform_bwrite(nhfp)) { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &zerotrap, sizeof zerotrap); - } + if (update_file(nhfp)) { + Sfo_trap(nhfp, &zerotrap, "trap"); } } @@ -1038,19 +934,15 @@ savefruitchn(NHFILE *nhfp) f1 = gf.ffruit; while (f1) { f2 = f1->nextf; - if (f1->fid >= 0 && perform_bwrite(nhfp)) { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) f1, sizeof *f1); - } + if (f1->fid >= 0 && update_file(nhfp)) { + Sfo_fruit(nhfp, f1, "fruit"); } if (release_data(nhfp)) dealloc_fruit(f1); f1 = f2; } - if (perform_bwrite(nhfp)) { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &zerofruit, sizeof zerofruit); - } + if (update_file(nhfp)) { + Sfo_fruit(nhfp, &zerofruit, "fruit"); } if (release_data(nhfp)) gf.ffruit = 0; @@ -1064,17 +956,13 @@ savelevchn(NHFILE *nhfp) for (tmplev = svs.sp_levchn; tmplev; tmplev = tmplev->next) cnt++; - if (perform_bwrite(nhfp)) { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &cnt, sizeof cnt); - } + if (update_file(nhfp)) { + Sfo_int(nhfp, &cnt, "levchn-lev_count"); } for (tmplev = svs.sp_levchn; tmplev; tmplev = tmplev2) { tmplev2 = tmplev->next; - if (perform_bwrite(nhfp)) { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) tmplev, sizeof *tmplev); - } + if (update_file(nhfp)) { + Sfo_s_level(nhfp, tmplev, "levchn-s_level"); } if (release_data(nhfp)) free((genericptr_t) tmplev); @@ -1107,13 +995,12 @@ store_plname_in_file(NHFILE *nhfp) assert(hero[PL_NSIZ_PLUS - 1 - 1] == '\0'); hero[PL_NSIZ_PLUS - 1] = wizard ? 'D' : discover ? 'X' : '-'; - if (nhfp->structlevel) { - bufoff(nhfp->fd); - /* bwrite() before bufon() uses plain write() */ - bwrite(nhfp->fd, (genericptr_t) &plsiztmp, sizeof plsiztmp); - bwrite(nhfp->fd, (genericptr_t) hero, plsiztmp); + if (nhfp->structlevel) + bufoff(nhfp->fd); /* bwrite() before bufon() uses plain write() */ + Sfo_int(nhfp, &plsiztmp, "plname-size"); + Sfo_char(nhfp, hero, "plname", plsiztmp); + if (nhfp->structlevel) bufon(nhfp->fd); - } return; } @@ -1121,11 +1008,11 @@ staticfn void save_msghistory(NHFILE *nhfp) { char *msg; - int msgcount = 0, msglen; - int minusone = -1; + int msgcount = 0; + int minusone = -1, msglen; boolean init = TRUE; - if (perform_bwrite(nhfp)) { + if (update_file(nhfp)) { /* ask window port for each message in sequence */ while ((msg = getmsghistory(init)) != 0) { init = FALSE; @@ -1136,15 +1023,11 @@ save_msghistory(NHFILE *nhfp) no need to modify msg[] since terminator isn't written */ if (msglen > BUFSZ - 1) msglen = BUFSZ - 1; - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &msglen, sizeof msglen); - bwrite(nhfp->fd, (genericptr_t) msg, msglen); - } + Sfo_int(nhfp, &msglen, "msghistory-length"); + Sfo_char(nhfp, msg, "msghistory-msg", msglen); ++msgcount; } - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &minusone, sizeof(int)); - } + Sfo_int(nhfp, &minusone, "msghistory-length"); } debugpline1("Stored %d messages into savefile.", msgcount); /* note: we don't attempt to handle release_data() here */ @@ -1261,6 +1144,7 @@ freedynamicdata(void) #endif discard_gamelog(); release_runtime_info(); /* build-time options and version stuff */ + //free_convert_filenames(); #endif /* FREE_ALL_MEMORY */ if (VIA_WINDOWPORT()) @@ -1275,7 +1159,6 @@ freedynamicdata(void) /* last, because it frees data that might be used by panic() to provide feedback to the user; conceivably other freeing might trigger panic */ sysopt_release(); /* SYSCF strings */ - return; } /*save.c*/ diff --git a/src/sfbase.c b/src/sfbase.c new file mode 100644 index 000000000..6a62865af --- /dev/null +++ b/src/sfbase.c @@ -0,0 +1,209 @@ +/* NetHack 3.7 sfbase.c.template $NHDT-Date$ $NHDT-Branch$:$NHDT-Revision$ */ +/* Copyright (c) Michael Allison, 2025. */ +/* NetHack may be freely redistributed. See license for details. */ + +#include "hack.h" +#include "sfprocs.h" + +/* #define DO_DEBUG */ + +struct sf_structlevel_procs sfoprocs[NUM_SAVEFORMATS], sfiprocs[NUM_SAVEFORMATS], + zerosfoprocs = {0}, zerosfiprocs = {0}; + +void sf_log(NHFILE *, const char *, size_t, int); + +#define SF_A(dtyp) \ +void sfo_##dtyp(NHFILE *nhfp, dtyp *d_##dtyp, const char *myname) \ +{ \ + if (nhfp->fplog) \ + sf_log(nhfp, myname, sizeof *d_##dtyp, 1); \ + if (nhfp->structlevel) { \ + (*sfoprocs[nhfp->fnidx].fn.sf_##dtyp)(nhfp, d_##dtyp, myname); \ + } \ +} \ + \ +void sfi_##dtyp(NHFILE *nhfp, dtyp *d_##dtyp, const char *myname) \ +{ \ + if (nhfp->structlevel) { \ + (*sfiprocs[nhfp->fnidx].fn.sf_##dtyp)(nhfp, d_##dtyp, myname); \ + } \ + if (nhfp->fplog && !nhfp->eof) \ + sf_log(nhfp, myname, sizeof *d_##dtyp, 1); \ + if (nhfp->eof) \ + return; \ + if (((nhfp->mode & CONVERTING) != 0) && nhfp->nhfpconvert) \ + sfo_##dtyp(nhfp->nhfpconvert, d_##dtyp, myname); \ +} + +#define SF_C(keyw, dtyp) \ +void sfo_##dtyp(NHFILE *nhfp, keyw dtyp *d_##dtyp, const char *myname) \ +{ \ + \ + if (nhfp->structlevel) { \ + (*sfoprocs[nhfp->fnidx].fn.sf_##dtyp)(nhfp, d_##dtyp, myname); \ + } \ + if (nhfp->fplog && !nhfp->eof) \ + sf_log(nhfp, myname, sizeof *d_##dtyp, 1); \ +} \ + \ +void sfi_##dtyp(NHFILE *nhfp, keyw dtyp *d_##dtyp, const char *myname) \ +{ \ + if (nhfp->structlevel) { \ + (*sfiprocs[nhfp->fnidx].fn.sf_##dtyp)(nhfp, d_##dtyp, myname); \ + } \ + if (nhfp->fplog && !nhfp->eof) \ + sf_log(nhfp, myname, sizeof *d_##dtyp, 1); \ + if (nhfp->eof) \ + return; \ + if (((nhfp->mode & CONVERTING) != 0) && nhfp->nhfpconvert) \ + sfo_##dtyp(nhfp->nhfpconvert, d_##dtyp, myname); \ +} + +#define SF_X(xxx, dtyp) \ +void sfo_##dtyp(NHFILE *nhfp, xxx *d_##dtyp, const char *myname, int bfsz) \ +{ \ + if (nhfp->structlevel) { \ + (*sfoprocs[nhfp->fnidx].fn.sf_##dtyp)(nhfp, d_##dtyp, myname, bfsz); \ + } \ + if (nhfp->fplog && !nhfp->eof) \ + sf_log(nhfp, myname, sizeof *d_##dtyp, 1); \ +} \ + \ +void sfi_##dtyp(NHFILE *nhfp, xxx *d_##dtyp, const char *myname, int bfsz) \ +{ \ + if (nhfp->structlevel) { \ + (*sfiprocs[nhfp->fnidx].fn.sf_##dtyp)(nhfp, d_##dtyp, myname, bfsz); \ + } \ + if (nhfp->fplog && !nhfp->eof) \ + sf_log(nhfp, myname, sizeof *d_##dtyp, 1); \ + if (nhfp->eof) \ + return; \ + if (((nhfp->mode & CONVERTING) != 0) && nhfp->nhfpconvert) \ + sfo_##dtyp(nhfp->nhfpconvert, d_##dtyp, myname, bfsz); \ +} + +SF_C(struct, arti_info) +SF_C(struct, nhrect) +SF_C(struct, branch) +SF_C(struct, bubble) +SF_C(struct, cemetery) +SF_C(struct, context_info) +SF_C(struct, nhcoord) +SF_C(struct, damage) +SF_C(struct, dest_area) +SF_C(struct, dgn_topology) +SF_C(struct, dungeon) +SF_C(struct, d_level) +SF_C(struct, ebones) +SF_C(struct, edog) +SF_C(struct, egd) +SF_C(struct, emin) +SF_C(struct, engr) +SF_C(struct, epri) +SF_C(struct, eshk) +SF_C(struct, fe) +SF_C(struct, flag) +SF_C(struct, fruit) +SF_C(struct, gamelog_line) +SF_C(struct, kinfo) +SF_C(struct, levelflags) +SF_C(struct, ls_t) +SF_C(struct, linfo) +SF_C(struct, mapseen_feat) +SF_C(struct, mapseen_flags) +SF_C(struct, mapseen_rooms) +SF_C(struct, mkroom) +SF_C(struct, monst) +SF_C(struct, mvitals) +SF_C(struct, obj) +SF_C(struct, objclass) +SF_C(struct, q_score) +SF_C(struct, rm) +SF_C(struct, spell) +SF_C(struct, stairway) +SF_C(struct, s_level) +SF_C(struct, trap) +SF_C(struct, version_info) +SF_C(struct, you) +SF_C(union, any) + +SF_A(aligntyp) +SF_A(boolean) +SF_A(coordxy) +SF_A(genericptr) +SF_A(int) +SF_A(int16) +SF_A(int32) +SF_A(int64) +SF_A(long) +SF_A(schar) +SF_A(short) +SF_A(size_t) +SF_A(time_t) +SF_A(uchar) +SF_A(uint16) +SF_A(uint32) +SF_A(uint64) +SF_A(ulong) +SF_A(unsigned) +SF_A(ushort) +SF_A(xint16) +SF_A(xint8) + +void +sfo_char(NHFILE *nhfp, char *d_char, const char *myname, int cnt) +{ + if (nhfp->structlevel) { + (*sfoprocs[nhfp->fnidx].fn.sf_char)(nhfp, d_char, myname, cnt); + } + if (nhfp->fplog && !nhfp->eof) + sf_log(nhfp, myname, sizeof (char), cnt); +} + +void +sfi_char(NHFILE *nhfp, char *d_char, const char *myname, int cnt) +{ + if (nhfp->structlevel) { + (*sfiprocs[nhfp->fnidx].fn.sf_char)(nhfp, d_char, myname, cnt); + } + if (nhfp->fplog && !nhfp->eof) + sf_log(nhfp, myname, sizeof (char), cnt); + if (nhfp->eof) + return; + if (((nhfp->mode & CONVERTING) != 0) && nhfp->nhfpconvert) + sfo_char(nhfp->nhfpconvert, d_char, myname, cnt); +} +SF_X(uint8_t, bitfield) + +/* ---------------------------------------------------------------*/ + +void +sf_log(NHFILE *nhfp, const char *t1, size_t sz, int cnt) +{ + FILE *fp = nhfp->fplog; + + if (fp) { + (void) fprintf(fp, "%ld %s sz=%zu cnt=%d\n", + nhfp->count++, + t1, sz, cnt); + fflush(fp); + } +} + +/* + *---------------------------------------------------------------------------- + * initialize the function pointers. These are called from initoptions_init(). + *---------------------------------------------------------------------------- + */ + +void +sf_init(void) +{ + sfoprocs[invalid] = zerosfoprocs; + sfiprocs[invalid] = zerosfiprocs; + sfoprocs[historical] = historical_sfo_procs; + sfiprocs[historical] = historical_sfi_procs; +} + + + diff --git a/src/sfstruct.c b/src/sfstruct.c index f4a09163f..c4eda5418 100644 --- a/src/sfstruct.c +++ b/src/sfstruct.c @@ -1,9 +1,326 @@ /* NetHack 3.7 sfstruct.c $NHDT-Date: 1606765215 2020/11/30 19:40:15 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.4 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ -/*-Copyright (c) Michael Allison, 2009. */ +/*-Copyright (c) Michael Allison, 2025. */ /* NetHack may be freely redistributed. See license for details. */ #include "hack.h" +#include "sfprocs.h" + +/* #define SFLOGGING */ /* debugging */ + +/* historical full struct savings */ + +#ifdef SAVEFILE_DEBUGGING +#if defined(__GNUC__) +#define DEBUGFORMATSTR64 "%s %s %ld %ld %d\n" +#elif defined(_MSC_VER) +#define DEBUGFORMATSTR64 "%s %s %lld %ld %d\n" +#endif +#endif + +#ifdef SFLOGGING +staticfn void logging_finish(void); +#endif + +#define SFO_BODY(dt) \ +{ \ + bwrite(nhfp->fd, (genericptr_t) d_##dt, sizeof *d_##dt); \ +} + +#define SFI_BODY(dt) \ +{ \ + mread(nhfp->fd, (genericptr_t) d_##dt, sizeof *d_##dt); \ + if (restoreinfo.mread_flags == -1) \ + nhfp->eof = TRUE; \ +} + +#define SF_A(dtyp) \ +void historical_sfo_##dtyp(NHFILE *, dtyp *d_##dtyp, const char *); \ +void historical_sfi_##dtyp(NHFILE *, dtyp *d_##dtyp, const char *); \ + \ +void historical_sfo_##dtyp(NHFILE *nhfp, dtyp *d_##dtyp, \ + const char *myname UNUSED) \ + SFO_BODY(dtyp) \ + \ +void historical_sfi_##dtyp(NHFILE *nhfp, dtyp *d_##dtyp, \ + const char *myname UNUSED) \ + SFI_BODY(dtyp) + + +#define SF_C(keyw, dtyp) \ +void historical_sfo_##dtyp(NHFILE *, keyw dtyp *d_##dtyp, \ + const char *); \ +void historical_sfi_##dtyp(NHFILE *, keyw dtyp *d_##dtyp, \ + const char *); \ + \ +void historical_sfo_##dtyp(NHFILE *nhfp, keyw dtyp *d_##dtyp, \ + const char *myname UNUSED) \ + SFO_BODY(dtyp) \ + \ +void historical_sfi_##dtyp(NHFILE *nhfp, keyw dtyp *d_##dtyp, \ + const char *myname UNUSED) \ + SFI_BODY(dtyp) + +#define SF_X(xxx, dtyp) \ +void historical_sfo_##dtyp(NHFILE *, xxx *d_##dtyp, const char *, int); \ +void historical_sfi_##dtyp(NHFILE *, xxx *d_##dtyp, const char *, int); \ + \ +void historical_sfo_##dtyp(NHFILE *nhfp, xxx *d_##dtyp, \ + const char *myname UNUSED, int bflen UNUSED) \ + SFO_BODY(dtyp) \ + \ +void historical_sfi_##dtyp(NHFILE *nhfp, xxx *d_##dtyp, \ + const char *myname UNUSED, int bflen UNUSED) \ + SFI_BODY(dtyp) + +SF_C(struct, arti_info) +SF_C(struct, nhrect) +SF_C(struct, branch) +SF_C(struct, bubble) +SF_C(struct, cemetery) +SF_C(struct, context_info) +SF_C(struct, nhcoord) +SF_C(struct, damage) +SF_C(struct, dest_area) +SF_C(struct, dgn_topology) +SF_C(struct, dungeon) +SF_C(struct, d_level) +SF_C(struct, ebones) +SF_C(struct, edog) +SF_C(struct, egd) +SF_C(struct, emin) +SF_C(struct, engr) +SF_C(struct, epri) +SF_C(struct, eshk) +SF_C(struct, fe) +SF_C(struct, flag) +SF_C(struct, fruit) +SF_C(struct, gamelog_line) +SF_C(struct, kinfo) +SF_C(struct, levelflags) +SF_C(struct, ls_t) +SF_C(struct, linfo) +SF_C(struct, mapseen_feat) +SF_C(struct, mapseen_flags) +SF_C(struct, mapseen_rooms) +SF_C(struct, mkroom) +SF_C(struct, monst) +SF_C(struct, mvitals) +SF_C(struct, obj) +SF_C(struct, objclass) +SF_C(struct, q_score) +SF_C(struct, rm) +SF_C(struct, spell) +SF_C(struct, stairway) +SF_C(struct, s_level) +SF_C(struct, trap) +SF_C(struct, version_info) +SF_C(struct, you) + +SF_C(union, any) +SF_A(aligntyp) +SF_A(boolean) +SF_A(coordxy) +SF_A(genericptr_t) +SF_A(int) +SF_A(int16) +SF_A(int32) +SF_A(int64) +SF_A(long) +SF_A(schar) +SF_A(short) +SF_A(size_t) +SF_A(time_t) +SF_A(uchar) +SF_A(uint16) +SF_A(uint32) +SF_A(uint64) +SF_A(ulong) +SF_A(unsigned) +SF_A(ushort) +SF_A(xint16) +SF_A(xint8) + +void historical_sfo_char(NHFILE *, char *d_char, const char *, int); +void historical_sfi_char(NHFILE *, char *d_char, const char *, int); + +void +historical_sfo_char(NHFILE *nhfp, char *d_char, + const char *myname UNUSED, int cnt) +{ + bwrite(nhfp->fd, (genericptr_t) d_char, cnt * sizeof (char)); +} + +void +historical_sfi_char(NHFILE *nhfp, char *d_char, + const char *myname UNUSED, int cnt) +{ + mread(nhfp->fd, (genericptr_t) d_char, cnt * sizeof (char)); + if (restoreinfo.mread_flags == -1) + nhfp->eof = TRUE; +} + +SF_X(uint8_t, bitfield) + +struct sf_structlevel_procs historical_sfo_procs = { + "", + /* sf */ + { + historical_sfo_arti_info, + historical_sfo_nhrect, + historical_sfo_branch, + historical_sfo_bubble, + historical_sfo_cemetery, + historical_sfo_context_info, + historical_sfo_nhcoord, + historical_sfo_damage, + historical_sfo_dest_area, + historical_sfo_dgn_topology, + historical_sfo_dungeon, + historical_sfo_d_level, + historical_sfo_ebones, + historical_sfo_edog, + historical_sfo_egd, + historical_sfo_emin, + historical_sfo_engr, + historical_sfo_epri, + historical_sfo_eshk, + historical_sfo_fe, + historical_sfo_flag, + historical_sfo_fruit, + historical_sfo_gamelog_line, + historical_sfo_kinfo, + historical_sfo_levelflags, + historical_sfo_ls_t, + historical_sfo_linfo, + historical_sfo_mapseen_feat, + historical_sfo_mapseen_flags, + historical_sfo_mapseen_rooms, + historical_sfo_mkroom, + historical_sfo_monst, + historical_sfo_mvitals, + historical_sfo_obj, + historical_sfo_objclass, + historical_sfo_q_score, + historical_sfo_rm, + historical_sfo_spell, + historical_sfo_stairway, + historical_sfo_s_level, + historical_sfo_trap, + historical_sfo_version_info, + historical_sfo_you, + historical_sfo_any, + + historical_sfo_aligntyp, + historical_sfo_boolean, + historical_sfo_coordxy, + historical_sfo_genericptr_t, + historical_sfo_int, + historical_sfo_int16, + historical_sfo_int32, + historical_sfo_int64, + historical_sfo_long, + historical_sfo_schar, + historical_sfo_short, + historical_sfo_size_t, + historical_sfo_time_t, + historical_sfo_uchar, + historical_sfo_uint16, + historical_sfo_uint32, + historical_sfo_uint64, + historical_sfo_ulong, + historical_sfo_unsigned, + historical_sfo_ushort, + historical_sfo_xint16, + historical_sfo_xint8, + historical_sfo_char, + historical_sfo_bitfield, + } +}; + +struct sf_structlevel_procs historical_sfi_procs = { + "", + /* sf */ + { + historical_sfi_arti_info, + historical_sfi_nhrect, + historical_sfi_branch, + historical_sfi_bubble, + historical_sfi_cemetery, + historical_sfi_context_info, + historical_sfi_nhcoord, + historical_sfi_damage, + historical_sfi_dest_area, + historical_sfi_dgn_topology, + historical_sfi_dungeon, + historical_sfi_d_level, + historical_sfi_ebones, + historical_sfi_edog, + historical_sfi_egd, + historical_sfi_emin, + historical_sfi_engr, + historical_sfi_epri, + historical_sfi_eshk, + historical_sfi_fe, + historical_sfi_flag, + historical_sfi_fruit, + historical_sfi_gamelog_line, + historical_sfi_kinfo, + historical_sfi_levelflags, + historical_sfi_ls_t, + historical_sfi_linfo, + historical_sfi_mapseen_feat, + historical_sfi_mapseen_flags, + historical_sfi_mapseen_rooms, + historical_sfi_mkroom, + historical_sfi_monst, + historical_sfi_mvitals, + historical_sfi_obj, + historical_sfi_objclass, + historical_sfi_q_score, + historical_sfi_rm, + historical_sfi_spell, + historical_sfi_stairway, + historical_sfi_s_level, + historical_sfi_trap, + historical_sfi_version_info, + historical_sfi_you, + historical_sfi_any, + + historical_sfi_aligntyp, + historical_sfi_boolean, + historical_sfi_coordxy, + historical_sfi_genericptr_t, + historical_sfi_int, + historical_sfi_int16, + historical_sfi_int32, + historical_sfi_int64, + historical_sfi_long, + historical_sfi_schar, + historical_sfi_short, + historical_sfi_size_t, + historical_sfi_time_t, + historical_sfi_uchar, + historical_sfi_uint16, + historical_sfi_uint32, + historical_sfi_uint64, + historical_sfi_ulong, + historical_sfi_unsigned, + historical_sfi_ushort, + historical_sfi_xint16, + historical_sfi_xint8, + historical_sfi_char, + historical_sfi_bitfield, + } +}; + +/* + * The historical bwrite() and mread() functions follow + */ + +#ifdef SAVEFILE_DEBUGGING +static long floc = 0L; +#endif /* * historical structlevel savefile writing and reading routines follow. @@ -28,6 +345,19 @@ static int bw_buffered[MAXFD] = {0,0,0,0,0}; static FILE *bw_FILE[MAXFD] = {0,0,0,0,0}; #endif +#ifdef SFLOGGING +static FILE *ofp[20] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + char ofnamebuf[80]; + static long ocnt = 0L; + + static FILE *ifp[20] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + char ifnamebuf[80]; + static long icnt = 0L; +#endif + + /* * Presumably, the fdopen() to allow use of stdio fwrite() * over write() was done for performance or functionality @@ -146,6 +476,17 @@ bclose(int fd) /* return the idx to the pool */ bw_sticky[idx] = -1; } +#ifdef SFLOGGING + if (fd >= 0 && fd <= SIZE(ofp)) { + if (ofp[fd]) { + fclose(ofp[fd]); + ofp[fd] = 0; + } else if (ifp[fd]) { + fclose(ifp[fd]); + ifp[fd] = 0; + } + } +#endif return; } @@ -171,6 +512,20 @@ bwrite(int fd, const genericptr_t loc, unsigned num) boolean failed; int idx = getidx(fd, NOFLG); +#ifdef SFLOGGING + if (fd >= 0 && fd < SIZE(ofp)) { + if (!ofp[fd]) { + Snprintf(ofnamebuf, sizeof ofnamebuf, "bwrite_%02d.log", fd); + ofp[fd] = fopen(ofnamebuf, "w"); + } + if (ofp[fd]) { + fprintf(ofp[fd], "%08ld, %08ld, %d\n", ocnt, + ftell(ofp[fd]), num); + ocnt++; + } + } +#endif + if (idx >= 0) { if (num == 0) { /* nothing to do; we need a special case to exit early @@ -209,7 +564,22 @@ bwrite(int fd, const genericptr_t loc, unsigned num) void mread(int fd, genericptr_t buf, unsigned len) { -#if defined(BSD) || defined(ULTRIX) + +#ifdef SFLOGGING + if (fd >= 0 && fd < 9) { + if (!ifp[fd]) { + Snprintf(ifnamebuf, sizeof ifnamebuf, "mread_%02d.log", fd); + ifp[fd] = fopen(ifnamebuf, "w"); + } + if (ifp[fd]) { + fprintf(ifp[fd], "%08ld, %08ld, %d\n", icnt, + ftell(ifp[fd]), (int) len); + icnt++; + } + } +#endif + +#if defined(BSD) || defined(ULTRIX) || defined(WIN32) #define readLenType int #else /* e.g. SYSV, __TURBOC__ */ #define readLenType unsigned @@ -235,3 +605,27 @@ mread(int fd, genericptr_t buf, unsigned len) } +#ifdef SFLOGGING +staticfn void +logging_finish(void) +{ + int i; + + for (i = 0; i < SIZE(ofp); ++i) { + if (ofp[i]) { + fclose(ofp[i]); + ofp[i] = 0; + } + } + ocnt = 0L; + + for (i = 0; i < SIZE(ifp); ++i) { + if (ifp[i]) { + fclose(ifp[i]); + ifp[i] = 0; + } + } + icnt = 0L; +} +#endif + diff --git a/src/sys.c b/src/sys.c index 9cdead0ba..4d8ad2dcf 100644 --- a/src/sys.c +++ b/src/sys.c @@ -99,8 +99,7 @@ sys_early_init(void) sysopt.check_plname = 0; sysopt.seduce = 1; /* if it's compiled in, default to on */ sysopt_seduce_set(sysopt.seduce); - /* default to little-endian in 3.7 */ - sysopt.saveformat[0] = sysopt.bonesformat[0] = lendian; + sysopt.saveformat[0] = sysopt.bonesformat[0] = historical; sysopt.accessibility = 0; #ifdef WIN32 sysopt.portable_device_paths = 0; diff --git a/src/timeout.c b/src/timeout.c index 34e95806a..dbfa90762 100644 --- a/src/timeout.c +++ b/src/timeout.c @@ -2022,7 +2022,7 @@ print_queue(winid win, timer_element *base) for (curr = base; curr; curr = curr->next) { #ifdef VERBOSE_TIMER Sprintf(buf, " %4ld %4ld %-6s %s(%s)", curr->timeout, - curr->tid, kind_name(curr->kind), + (long) curr->tid, kind_name(curr->kind), timeout_funcs[curr->func_index].name, fmt_ptr((genericptr_t) curr->arg.a_void)); #else @@ -2496,25 +2496,19 @@ write_timer(NHFILE *nhfp, timer_element *timer) case TIMER_GLOBAL: case TIMER_LEVEL: /* assume no pointers in arg */ - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) timer, sizeof(timer_element)); - } + Sfo_fe(nhfp, timer, "timer"); break; case TIMER_OBJECT: if (timer->needs_fixup) { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) timer, sizeof(timer_element)); - } + Sfo_fe(nhfp, timer, "timer"); } else { /* replace object pointer with id */ arg_save.a_obj = timer->arg.a_obj; timer->arg = cg.zeroany; timer->arg.a_uint = (arg_save.a_obj)->o_id; timer->needs_fixup = 1; - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) timer, sizeof(timer_element)); - } + Sfo_fe(nhfp, timer, "timer"); timer->arg.a_obj = arg_save.a_obj; timer->needs_fixup = 0; } @@ -2522,18 +2516,14 @@ write_timer(NHFILE *nhfp, timer_element *timer) case TIMER_MONSTER: if (timer->needs_fixup) { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) timer, sizeof(timer_element)); - } + Sfo_fe(nhfp, timer, "timer"); } else { /* replace monster pointer with id */ arg_save.a_monst = timer->arg.a_monst; timer->arg = cg.zeroany; timer->arg.a_uint = (arg_save.a_monst)->m_id; timer->needs_fixup = 1; - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) timer, sizeof(timer_element)); - } + Sfo_fe(nhfp, timer, "timer"); timer->arg.a_monst = arg_save.a_monst; timer->needs_fixup = 0; } @@ -2665,17 +2655,12 @@ save_timers(NHFILE *nhfp, int range) timer_element *curr, *prev, *next_timer = 0; int count; - if (perform_bwrite(nhfp)) { + if (update_file(nhfp)) { if (range == RANGE_GLOBAL) { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &svt.timer_id, - sizeof svt.timer_id); - } + Sfo_ulong(nhfp, &svt.timer_id, "timer-timer_id"); } count = maybe_write_timer(nhfp, range, FALSE); - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &count, sizeof count); - } + Sfo_int(nhfp, &count, "timer-timer_count"); (void) maybe_write_timer(nhfp, range, TRUE); } @@ -2710,22 +2695,14 @@ restore_timers(NHFILE *nhfp, int range, long adjust) boolean ghostly = (nhfp->ftype == NHF_BONESFILE); /* from a ghost level */ if (range == RANGE_GLOBAL) { - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) &svt.timer_id, - sizeof svt.timer_id); - } + Sfi_ulong(nhfp, &svt.timer_id, "timer-timer_id"); } /* restore elements */ - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) &count, sizeof count); - } - + Sfi_int(nhfp, &count, "timer-timer_count"); while (count-- > 0) { curr = (timer_element *) alloc(sizeof(timer_element)); - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) curr, sizeof(timer_element)); - } + Sfi_fe(nhfp, curr, "timer"); if (ghostly) curr->timeout += adjust; insert_timer(curr); diff --git a/src/track.c b/src/track.c index 60a0d382b..6f455a694 100644 --- a/src/track.c +++ b/src/track.c @@ -69,20 +69,13 @@ hastrack(coordxy x, coordxy y) void save_track(NHFILE *nhfp) { - if (perform_bwrite(nhfp)) { + if (update_file(nhfp)) { int i; - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &utcnt, sizeof utcnt); - bwrite(nhfp->fd, (genericptr_t) &utpnt, sizeof utpnt); - } + Sfo_int(nhfp, &utcnt, "track-utcnt"); + Sfo_int(nhfp, &utpnt, "track-utpnt"); for (i = 0; i < utcnt; i++) { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &utrack[i].x, - sizeof utrack[i].x); - bwrite(nhfp->fd, (genericptr_t) &utrack[i].y, - sizeof utrack[i].y); - } + Sfo_nhcoord(nhfp, &utrack[i], "utrack"); } } if (release_data(nhfp)) @@ -95,17 +88,13 @@ rest_track(NHFILE *nhfp) { int i; - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) &utcnt, sizeof utcnt); - mread(nhfp->fd, (genericptr_t) &utpnt, sizeof utpnt); - } + Sfi_int(nhfp, &utcnt, "track-utcnt"); + Sfi_int(nhfp, &utpnt, "track-utpnt"); + if (utcnt > UTSZ || utpnt > UTSZ) panic("rest_track: impossible pt counts"); for (i = 0; i < utcnt; i++) { - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) &utrack[i].x, sizeof utrack[i].x); - mread(nhfp->fd, (genericptr_t) &utrack[i].y, sizeof utrack[i].y); - } + Sfi_nhcoord(nhfp, &utrack[i], "utrack"); } } diff --git a/src/version.c b/src/version.c index f1303744d..dc1d0e654 100644 --- a/src/version.c +++ b/src/version.c @@ -373,6 +373,10 @@ check_version( #endif complain = FALSE; /* 'complain' requires 'filename' for pline("%s") */ } + if ((version_data->feature_set & SFCTOOL_BIT) != 0) { + gc.converted_savefile_loaded = TRUE; + version_data->feature_set &= ~(SFCTOOL_BIT); + } if ( #ifdef VERSION_COMPATIBILITY /* patchlevel.h */ version_data->incarnation < VERSION_COMPATIBILITY @@ -421,13 +425,11 @@ store_version(NHFILE *nhfp) bufoff(nhfp->fd); store_critical_bytes(nhfp); - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &version_data, - (unsigned) (sizeof version_data)); - } + Sfo_version_info(nhfp, (struct version_info *) &version_data, + "version_info"); if (nhfp->structlevel) - bufon(nhfp->fd); + bufon(nhfp->fd); return; } @@ -661,90 +663,170 @@ store_critical_bytes(NHFILE *nhfp) if (nhfp->mode & WRITING) { indicate = (nhfp->structlevel) ? 'h' - : (nhfp->fnidx == ascii) ? 'a' - : 'l'; - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &indicate, - (unsigned) sizeof indicate); - } - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &csc_count, - (unsigned) sizeof csc_count); - } + : (nhfp->fnidx == cnvascii) ? 'a' + : '?'; + Sfo_char(nhfp, &indicate, "indicate-format", 1); + Sfo_char(nhfp, &csc_count, "count-critical_sizes", 1); cnt = (int) csc_count; for (i = 0; i < cnt; ++i) { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &critical_sizes[i].ucsize, - (unsigned) sizeof (uchar)); - } + Sfo_uchar(nhfp, &critical_sizes[i].ucsize, "critical_sizes"); } } } /* this used to be based on file date and somewhat OS-dependent, - but now examines the initial part of the file's contents */ -boolean + * but now examines the initial part of the file's contents. + * + * returns: + * + * SF_UPTODATE (0) everything matched and looks good + * SF_OUTDATED (1) savefile is outdated + * SF_CRITICAL_BYTE_COUNT_MISMATCH (2) critical size count mismatch + * SF_DM_IL32LLP64_ON_ILP32LL64 (3) Windows x64 savefile on x86 + * SF_DM_I32LP64_ON_ILP32LL64 (4) Unix 64 savefile on x86 + * SF_DM_ILP32LL64_ON_I32LP64 (5) x86 savefile on Unix 64 + * SF_DM_ILP32LL64_ON_IL32LLP64 (6) x86 savefile on Windows x64 + * SF_DM_I32LP64_ON_IL32LLP64 (7) Unix 64 savefile on Windows x64 + * SF_DM_IL32LLP64_ON_I32LP64 (8) Windows x64 savefile on Unix 64 + * SF_DM_MISMATCH (9) some other mismatch + */ +int uptodate(NHFILE *nhfp, const char *name, unsigned long utdflags) { struct version_info vers_info; char indicator; + int sfstatus = 0, idx_1st_mismatch = 0; + boolean quietly = (utdflags & UTD_QUIETLY) != 0; boolean verbose = name ? TRUE : FALSE; - int ccbresult = 0; - /* int you_size = (int) sizeof (struct you); */ - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) &indicator, sizeof indicator); - } - if ((ccbresult = compare_critical_bytes(nhfp)) != 0) { - if (ccbresult > 0) { - raw_printf("compare of critical bytes failed at %d (%s).", - critical_sizes[ccbresult].ucsize, - critical_sizes[ccbresult].nm); + Sfi_char(nhfp, &indicator, "indicate-format", 1); + if ((sfstatus = compare_critical_bytes(nhfp, &idx_1st_mismatch, utdflags)) + != SF_UPTODATE) { + if (sfstatus > 0 && idx_1st_mismatch) { + if (!quietly) + raw_printf("comparison of critical bytes mismatched at %d (%s).", + critical_sizes[idx_1st_mismatch].ucsize, + critical_sizes[idx_1st_mismatch].nm); } - return FALSE; + return sfstatus; } - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) &vers_info, sizeof vers_info); - } + Sfi_version_info(nhfp, &vers_info, "version_info"); if (!check_version(&vers_info, name, verbose, utdflags)) { if (verbose) { if ((utdflags & UTD_WITHOUT_WAITSYNCH_PERFILE) == 0) wait_synch(); } - return FALSE; + return SF_OUTDATED; } - return TRUE; + + return SF_UPTODATE; } +/* + * returns: + * + * SF_UPTODATE (0) everything matched and looks good + * SF_OUTDATED (1) savefile is outdated + * SF_CRITICAL_BYTE_COUNT_MISMATCH (2) critical size count mismatch + * SF_DM_IL32LLP64_ON_ILP32LL64 (3) Windows x64 savefile on x86 + * SF_DM_I32LP64_ON_ILP32LL64 (4) Unix 64 savefile on x86 + * SF_DM_ILP32LL64_ON_I32LP64 (5) x86 savefile on Unix 64 + * SF_DM_ILP32LL64_ON_IL32LLP64 (6) x86 savefile on Windows x64 + * SF_DM_I32LP64_ON_IL32LLP64 (7) Unix 64 savefile on Windows x64 + * SF_DM_IL32LLP64_ON_I32LP64 (8) Windows x64 savefile on Unix 64 + * SF_DM_MISMATCH (9) some other mismatch + */ int -compare_critical_bytes(NHFILE *nhfp) +compare_critical_bytes(NHFILE *nhfp, int *idx_1st_mismatch, unsigned long utdflags) { char active_csc_count = (char) SIZE(critical_sizes), - file_csc_count = 0; - int i, cnt = (int) active_csc_count; + file_csc_count; + int i, cnt = (int) active_csc_count, + dmmismatch = SF_DM_MISMATCH; + boolean quietly = (utdflags & UTD_QUIETLY) != 0; - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) &file_csc_count, - sizeof file_csc_count); - } + Sfi_char(nhfp, &file_csc_count, "count-critical_sizes", 1); if (file_csc_count > cnt) { - raw_printf("critical byte counts do not match" - ", file:%d, critical_sizes:%d.", - file_csc_count, SIZE(critical_sizes)); - return -1; + if (!quietly) + raw_printf("critical byte counts do not match" + ", file:%d, critical_sizes:%d.", + file_csc_count, SIZE(critical_sizes)); + return SF_CRITICAL_BYTE_COUNT_MISMATCH; } for (i = 0; i < (int) file_csc_count; ++i) { - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) &cscbuf[i], - sizeof (uchar)); - } + Sfi_uchar(nhfp, &cscbuf[i], "critical_sizes"); } for (i = 1; i < cnt; ++i) { - if (cscbuf[i] != critical_sizes[i].ucsize) - return i; + if (cscbuf[i] != critical_sizes[i].ucsize) { + const char *dm = datamodel(), *dmfile; + + dmfile = what_datamodel_is_this(cscbuf[1], /* short */ + cscbuf[2], /* int */ + cscbuf[3], /* long */ + cscbuf[4], /* long long */ + cscbuf[5]); /* ptr */ + + if (!strcmp(dmfile, "IL32LLP64") && !strcmp(dm, "ILP32LL64")) { + /* Windows x64 savefile on x86 */ + dmmismatch = SF_DM_IL32LLP64_ON_ILP32LL64; + } else if (!strcmp(dmfile, "I32LP64") + && !strcmp(dm, "ILP32LL64")) { + /* Unix 64 savefile on x86*/ + dmmismatch = SF_DM_I32LP64_ON_ILP32LL64; + } else if (!strcmp(dmfile, "ILP32LL64") + && !strcmp(dm, "I32LP64")) { + /* x86 savefile on Unix 64 */ + dmmismatch = SF_DM_ILP32LL64_ON_I32LP64; + } else if (!strcmp(dmfile, "ILP32LL64") + && !strcmp(dm, "IL32LLP64")) { + /* x86 savefile on Windows x64 */ + dmmismatch = SF_DM_ILP32LL64_ON_IL32LLP64; + } else if (!strcmp(dmfile, "I32LP64") + && !strcmp(dm, "IL32LLP64")) { + /* Unix 64 savefile on Windows x64 */ + dmmismatch = SF_DM_I32LP64_ON_IL32LLP64; + } else if (!strcmp(dmfile, "IL32LLP64") + && !strcmp(dm, "I32LP64")) { + /* Windows x64 savefile on Unix 64 */ + dmmismatch = SF_DM_IL32LLP64_ON_I32LP64; + } + if (idx_1st_mismatch) + *idx_1st_mismatch = i; + return dmmismatch; + } } - return 0; /* everything matched */ + return SF_UPTODATE; /* everything matched */ +} + +/* + * returns: + * + * SF_UPTODATE (0) everything matched and looks good + * SF_OUTDATED (1) savefile is outdated + * SF_CRITICAL_BYTE_COUNT_MISMATCH (2) critical size count mismatch + * SF_DM_IL32LLP64_ON_ILP32LL64 (3) Windows x64 savefile on x86 + * SF_DM_I32LP64_ON_ILP32LL64 (4) Unix 64 savefile on x86 + * SF_DM_ILP32LL64_ON_I32LP64 (5) x86 savefile on Unix 64 + * SF_DM_ILP32LL64_ON_IL32LLP64 (6) x86 savefile on Windows x64 + * SF_DM_I32LP64_ON_IL32LLP64 (7) Unix 64 savefile on Windows x64 + * SF_DM_IL32LLP64_ON_I32LP64 (8) Windows x64 savefile on Unix 64 + * SF_DM_MISMATCH (9) some other mismatch + */ +int +validate(NHFILE *nhfp, const char *name, boolean without_waitsynch_perfile) +{ + unsigned long utdflags = 0L; + int validsf = 0; + + if (nhfp->structlevel) + utdflags |= UTD_CHECKSIZES; + if (without_waitsynch_perfile) + utdflags |= UTD_WITHOUT_WAITSYNCH_PERFILE; + if (nhfp->fieldlevel) + utdflags |= UTD_CHECKFIELDCOUNTS | UTD_SKIP_SANITY1 | UTD_QUIETLY; + validsf = uptodate(nhfp, name, utdflags); + return validsf; } #endif /* MINIMAL_FOR_RECOVER */ diff --git a/src/worm.c b/src/worm.c index c760bc3a3..af68084d1 100644 --- a/src/worm.c +++ b/src/worm.c @@ -16,6 +16,7 @@ struct wseg { staticfn void toss_wsegs(struct wseg *, boolean) NO_NNARGS; staticfn void shrink_worm(int); + #if 0 staticfn void random_dir(int, int, int *, int *); #endif @@ -527,31 +528,22 @@ save_worm(NHFILE *nhfp) int count; struct wseg *curr, *temp; - if (perform_bwrite(nhfp)) { + if (update_file(nhfp)) { for (i = 1; i < MAX_NUM_WORMS; i++) { for (count = 0, curr = wtails[i]; curr; curr = curr->nseg) count++; /* Save number of segments */ - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &count, sizeof count); - } + Sfo_int(nhfp, &count, "worm-segment_count"); /* Save segment locations of the monster. */ if (count) { for (curr = wtails[i]; curr; curr = curr->nseg) { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &(curr->wx), - sizeof curr->wx); - bwrite(nhfp->fd, (genericptr_t) &(curr->wy), - sizeof curr->wy); - } + Sfo_coordxy(nhfp, &(curr->wx), "worm-wx"); + Sfo_coordxy(nhfp, &(curr->wy), "worm-wy"); } } } - for (i = 0; i < MAX_NUM_WORMS; ++i) { - if (nhfp->structlevel) { - bwrite(nhfp->fd, (genericptr_t) &wgrowtime[i], sizeof (long)); - } - } + for (i = 0; i < MAX_NUM_WORMS; ++i) + Sfo_long(nhfp, &wgrowtime[i], "worm-wgrowtime"); } if (release_data(nhfp)) { @@ -580,22 +572,19 @@ save_worm(NHFILE *nhfp) void rest_worm(NHFILE *nhfp) { - int i, j, count = 0; + int i, j; + int count = 0; struct wseg *curr, *temp; for (i = 1; i < MAX_NUM_WORMS; i++) { - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) &count, sizeof count); - } + Sfi_int(nhfp, &count, "worm-segment_count"); /* Get the segments. */ for (curr = (struct wseg *) 0, j = 0; j < count; j++) { temp = newseg(); temp->nseg = (struct wseg *) 0; - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) &(temp->wx), sizeof temp->wx); - mread(nhfp->fd, (genericptr_t) &(temp->wy), sizeof temp->wy); - } + Sfi_coordxy(nhfp, &(temp->wx), "worm-wx"); + Sfi_coordxy(nhfp, &(temp->wy), "worm-wy"); if (curr) curr->nseg = temp; else @@ -605,9 +594,7 @@ rest_worm(NHFILE *nhfp) wheads[i] = curr; } for (i = 0; i < MAX_NUM_WORMS; ++i) { - if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) &wgrowtime[i], sizeof (long)); - } + Sfi_long(nhfp, &wgrowtime[i], "worm-wgrowtime"); } } diff --git a/sys/share/pcmain.c b/sys/share/pcmain.c index cad2bc69a..4093eff48 100644 --- a/sys/share/pcmain.c +++ b/sys/share/pcmain.c @@ -7,6 +7,7 @@ #include "hack.h" #include "dlb.h" +#include "sfproto.h" #ifndef NO_SIGNAL #include @@ -429,9 +430,7 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/ raw_print("Cannot create lock file"); } else { svh.hackpid = 1; - if (nhfp->structlevel) { - write(nhfp->fd, (genericptr_t) &svh.hackpid, sizeof svh.hackpid); - } + Sfo_int(nhfp, &svh.hackpid, "svh.hackpid"); close_nhfile(nhfp); } diff --git a/sys/unix/Makefile.src b/sys/unix/Makefile.src index d2e3c8e91..89836554a 100644 --- a/sys/unix/Makefile.src +++ b/sys/unix/Makefile.src @@ -518,7 +518,7 @@ HACKCSRC = allmain.c alloc.c apply.c artifact.c attrib.c ball.c bones.c \ nhlua.c nhlsel.c nhlobj.c nhmd4.c o_init.c objects.c objnam.c \ options.c pager.c pickup.c pline.c polyself.c potion.c pray.c \ priest.c quest.c questpgr.c read.c rect.c region.c report.c restore.c \ - rip.c rnd.c role.c rumors.c save.c selvar.c sfstruct.c \ + rip.c rnd.c role.c rumors.c save.c selvar.c sfbase.c sfstruct.c \ shk.c shknam.c sit.c sounds.c sp_lev.c spell.c stairs.c steal.c steed.c \ strutil.c symbols.c sys.c teleport.c \ timeout.c topten.c track.c trap.c u_init.c utf8map.c \ @@ -561,14 +561,15 @@ CSOURCES = $(HACKCSRC) $(HACKLIBSRC) $(SYSCSRC) $(WINCSRC) $(CHAINSRC) $(GENCSRC # HACKINCL = align.h artifact.h artilist.h attrib.h botl.h \ color.h config.h config1.h context.h coord.h cstd.h decl.h \ - display.h dlb.h dungeon.h engrave.h extern.h flag.h fnamesiz.h \ - func_tab.h global.h warnings.h hack.h lint.h mextra.h mfndpos.h \ - micro.h mkroom.h monattk.h mondata.h monflag.h monst.h monsters.h \ - nhmd4.h obj.h objects.h objclass.h optlist.h patchlevel.h \ - pcconf.h permonst.h prop.h rect.h region.h selvar.h sym.h defsym.h \ - rm.h sp_lev.h spell.h sndprocs.h seffects.h stairs.h sys.h tcap.h \ - timeout.h tradstdc.h trap.h unixconf.h vision.h vmsconf.h wintty.h \ - wincurs.h winX.h winprocs.h wintype.h you.h youprop.h weight.h + defsym.h display.h dlb.h dungeon.h engrave.h extern.h flag.h \ + fnamesiz.h func_tab.h global.h warnings.h hack.h lint.h mextra.h \ + micro.h mfndpos.h mkroom.h monattk.h mondata.h monflag.h monst.h \ + monsters.h nhmd4.h obj.h objects.h objclass.h optlist.h patchlevel.h \ + pcconf.h permonst.h prop.h rect.h region.h savefile.h selvar.h sym.h \ + rm.h sp_lev.h spell.h sndprocs.h seffects.h stairs.h sys.h \ + tcap.h timeout.h tradstdc.h trap.h unixconf.h vision.h vmsconf.h \ + wintty.h wincurs.h winX.h winprocs.h wintype.h you.h youprop.h \ + weight.h HSOURCES = $(HACKINCL) dgn_file.h @@ -610,7 +611,7 @@ HOBJ = $(TARGETPFX)allmain.o $(TARGETPFX)alloc.o \ $(TARGETPFX)rect.o $(TARGETPFX)region.o $(TARGETPFX)report.o \ $(TARGETPFX)restore.o $(TARGETPFX)rip.o $(TARGETPFX)rnd.o \ $(TARGETPFX)role.o $(TARGETPFX)rumors.o $(TARGETPFX)save.o \ - $(TARGETPFX)selvar.o $(TARGETPFX)sfstruct.o \ + $(TARGETPFX)selvar.o $(TARGETPFX)sfbase.o $(TARGETPFX)sfstruct.o \ $(TARGETPFX)shk.o $(TARGETPFX)shknam.o $(TARGETPFX)sit.o \ $(TARGETPFX)sounds.o $(TARGETPFX)sp_lev.o $(TARGETPFX)spell.o \ $(TARGETPFX)stairs.o $(TARGETPFX)symbols.o $(TARGETPFX)sys.o \ @@ -760,7 +761,7 @@ hacklib.a: hacklib.o ../win/gnome/gn_rip.h: ../win/X11/rip.xpm cp ../win/X11/rip.xpm ../win/gnome/gn_rip.h -$(TARGETPFX)sfstruct.o: sfstruct.c $(HACK_H) +$(TARGETPFX)sfbase.o: sfbase.c $(HACK_H) ../include/sfprocs.h # date.c should be recompiled any time any of the source or include code # is modified. @@ -1232,7 +1233,7 @@ $(TARGETPFX)role.o: role.c $(HACK_H) $(TARGETPFX)rumors.o: rumors.c $(HACK_H) ../include/dlb.h $(TARGETPFX)save.o: save.c $(HACK_H) $(TARGETPFX)selvar.o: selvar.c $(HACK_H) ../include/sp_lev.h -$(TARGETPFX)sfstruct.o: sfstruct.c $(HACK_H) +$(TARGETPFX)sfstruct.o: sfstruct.c $(HACK_H) ../include/sfprocs.h $(TARGETPFX)shk.o: shk.c $(HACK_H) $(TARGETPFX)shknam.o: shknam.c $(HACK_H) $(TARGETPFX)sit.o: sit.c $(HACK_H) ../include/artifact.h diff --git a/sys/unix/Makefile.utl b/sys/unix/Makefile.utl index c63caea3b..11a50aa1b 100644 --- a/sys/unix/Makefile.utl +++ b/sys/unix/Makefile.utl @@ -168,6 +168,7 @@ AT_V1 := @ AT = $(AT_V$(QUIETCC)) # Verbosity, end +GAME=nethack # timestamps for primary header files, matching src/Makefile CONFIG_H = ../src/config.h-t HACK_H = ../src/hack.h-t @@ -220,6 +221,7 @@ TARGET_CXX = $(CXX) TARGET_CXXFLAGS = $(CXXFLAGS) TARGET_AR = $(AR) +# # dependencies for makedefs # makedefs: $(HACKLIB) $(MAKEOBJS) mdgrep.h diff --git a/sys/vms/Makefile.src b/sys/vms/Makefile.src index f2efc62bb..dee166f8e 100644 --- a/sys/vms/Makefile.src +++ b/sys/vms/Makefile.src @@ -174,15 +174,18 @@ VERSOURCES = $(HACKCSRC) $(SYSSRC) $(WINSRC) $(RANDSRC) $(GENCSRC) # all .h files except date.h which would # cause dependency loops if run through "make depend" # -HACKINCL = align.h artifact.h artilist.h attrib.h color.h \ - config.h config1.h context.h coord.h decl.h defsym.h display.h \ - dlb.h dungeon.h engrave.h extern.h flag.h func_tab.h global.h \ - hack.h hacklib.h mextra.h mfndpos.h micro.h mkroom.h \ - monattk.h mondata.h monflag.h monst.h sym.h obj.h objclass.h \ - patchlevel.h pcconf.h permonst.h prop.h rect.h \ - region.h sym.h defsym.h rm.h sp_lev.h spell.h sys.h system.h \ - tcap.h timeout.h tradstdc.h trap.h unixconf.h vision.h \ - vmsconf.h wintty.h winX.h winprocs.h wintype.h you.h youprop.h +HACKINCL = align.h artifact.h artilist.h attrib.h botl.h \ + color.h config.h config1.h context.h coord.h cstd.h decl.h \ + defsym.h display.h dlb.h dungeon.h engrave.h extern.h flag.h \ + fnamesiz.h func_tab.h global.h warnings.h hack.h lint.h mextra.h \ + micro.h mkroom.h monattk.h mondata.h monflag.h monst.h monsters.h \ + mfndpos.h nhmd4.h obj.h objects.h objclass.h optlist.h patchlevel.h \ + pcconf.h permonst.h prop.h rect.h region.h savefile.h selvar.h sym.h \ + rm.h sp_lev.h spell.h sndprocs.h seffects.h stairs.h sys.h \ + tcap.h timeout.h tradstdc.h trap.h unixconf.h vision.h vmsconf.h \ + wintty.h wincurs.h winX.h winprocs.h wintype.h you.h youprop.h \ + weight.h + #HSOURCES = $(HACKINCL) date.h onames.h pm.h diff --git a/sys/windows/Makefile.nmake b/sys/windows/Makefile.nmake index 14273dd61..10c35a454 100644 --- a/sys/windows/Makefile.nmake +++ b/sys/windows/Makefile.nmake @@ -665,7 +665,7 @@ HACKCSRC = \ $(SRC)potion.c $(SRC)pray.c $(SRC)priest.c $(SRC)quest.c \ $(SRC)questpgr.c $(SRC)read.c $(SRC)rect.c $(SRC)region.c \ $(SRC)restore.c $(SRC)rip.c $(SRC)rnd.c $(SRC)role.c \ - $(SRC)rumors.c $(SRC)save.c $(SRC)selvar.c $(SRC)sfstruct.c \ + $(SRC)rumors.c $(SRC)save.c $(SRC)selvar.c $(SRC)sfstruct.c sfbase.c \ $(SRC)shk.c $(SRC)shknam.c $(SRC)sit.c $(SRC)sounds.c \ $(SRC)sp_lev.c $(SRC)spell.c $(SRC)stairs.c $(SRC)steal.c \ $(SRC)steed.c $(SRC)symbols.c $(SRC)sys.c $(SRC)teleport.c \ @@ -677,29 +677,30 @@ HACKCSRC = \ # all .h files except date.h HACKINCL = \ - $(INCL)align.h $(INCL)artifact.h $(INCL)artilist.h \ - $(INCL)attrib.h $(INCL)botl.h $(INCL)color.h \ - $(INCL)config.h $(INCL)config1.h $(INCL)context.h \ - $(INCL)coord.h $(INCL)cstd.h $(INCL)decl.h \ - $(INCL)display.h $(INCL)dlb.h $(INCL)dungeon.h \ - $(INCL)engrave.h $(INCL)extern.h $(INCL)flag.h \ - $(INCL)fnamesiz.h $(INCL)func_tab.h $(INCL)global.h \ - $(INCL)warnings.h $(INCL)hack.h $(INCL)lint.h \ - $(INCL)mextra.h $(INCL)mfndpos.h $(INCL)micro.h \ - $(INCL)mkroom.h $(INCL)monattk.h $(INCL)mondata.h \ - $(INCL)monflag.h $(INCL)monst.h $(INCL)monsters.h \ - $(INCL)nhmd4.h $(INCL)obj.h $(INCL)objects.h \ - $(INCL)objclass.h $(INCL)optlist.h $(INCL)patchlevel.h \ - $(INCL)pcconf.h $(INCL)permonst.h $(INCL)prop.h \ - $(INCL)rect.h $(INCL)region.h $(INCL)selvar.h \ - $(INCL)sym.h $(INCL)defsym.h $(INCL)rm.h \ - $(INCL)sp_lev.h $(INCL)spell.h $(INCL)sndprocs.h \ - $(INCL)seffects.h $(INCL)stairs.h $(INCL)sys.h \ - $(INCL)tcap.h $(INCL)timeout.h $(INCL)tradstdc.h \ - $(INCL)trap.h $(INCL)unixconf.h $(INCL)vision.h \ - $(INCL)vmsconf.h $(INCL)wintty.h $(INCL)wincurs.h \ - $(INCL)winX.h $(INCL)winprocs.h $(INCL)wintype.h \ - $(INCL)you.h $(INCL)youprop.h + $(INCL)align.h $(INCL)artifact.h $(INCL)artilist.h \ + $(INCL)attrib.h $(INCL)botl.h $(INCL)color.h \ + $(INCL)config.h $(INCL)config1.h $(INCL)context.h \ + $(INCL)coord.h $(INCL)cstd.h $(INCL)decl.h \ + $(INCL)defsym.h $(INCL)display.h $(INCL)dlb.h \ + $(INCL)dungeon.h $(INCL)engrave.h $(INCL)extern.h \ + $(INCL)flag.h $(INCL)fnamesiz.h $(INCL)func_tab.h \ + $(INCL)global.h $(INCL)warnings.h $(INCL)hack.h \ + $(INCL)lint.h $(INCL)mextra.h $(INCL)micro.h \ + $(INCL)mfndpos.h $(INCL)mkroom.h $(INCL)monattk.h \ + $(INCL)mondata.h $(INCL)monflag.h $(INCL)monst.h \ + $(INCL)monsters.h $(INCL)nhmd4.h $(INCL)obj.h \ + $(INCL)objects.h $(INCL)objclass.h $(INCL)optlist.h \ + $(INCL)patchlevel.h $(INCL)pcconf.h $(INCL)permonst.h \ + $(INCL)prop.h $(INCL)rect.h $(INCL)region.h \ + $(INCL)savefile.h $(INCL)selvar.h $(INCL)sym.h \ + $(INCL)rm.h $(INCL)sp_lev.h $(INCL)spell.h \ + $(INCL)sndprocs.h $(INCL)seffects.h $(INCL)stairs.h \ + $(INCL)sys.h $(INCL)tcap.h $(INCL)timeout.h \ + $(INCL)tradstdc.h $(INCL)trap.h $(INCL)unixconf.h \ + $(INCL)vision.h $(INCL)vmsconf.h $(INCL)wintty.h \ + $(INCL)wincurs.h $(INCL)winX.h $(INCL)winprocs.h \ + $(INCL)wintype.h $(INCL)you.h $(INCL)youprop.h \ + $(INCL)weight.h LUA_FILES = $(DAT)asmodeus.lua $(DAT)baalz.lua $(DAT)bigrm-1.lua \ $(DAT)bigrm-10.lua $(DAT)bigrm-11.lua $(DAT)bigrm-12.lua \ @@ -873,7 +874,7 @@ COREOBJTTY = \ $(OTTY)uhitm.o $(OTTY)utf8map.o $(OTTY)vault.o $(OTTY)vision.o \ $(OTTY)weapon.o $(OTTY)were.o $(OTTY)wield.o $(OTTY)windows.o \ $(OTTY)wizard.o $(OTTY)wizcmds.o $(OTTY)worm.o $(OTTY)worn.o \ - $(OTTY)write.o $(OTTY)zap.o + $(OTTY)write.o $(OTTY)zap.o $(OTTY)sfbase.o OBJSTTY = $(MDLIBTTY) $(COREOBJTTY) $(REGEXTTY) $(RANDOMTTY) @@ -936,7 +937,7 @@ COREOBJGUI = \ $(OGUI)uhitm.o $(OGUI)utf8map.o $(OGUI)vault.o $(OGUI)vision.o \ $(OGUI)weapon.o $(OGUI)were.o $(OGUI)wield.o $(OGUI)windows.o \ $(OGUI)wizard.o $(OGUI)wizcmds.o $(OGUI)worm.o $(OGUI)worn.o \ - $(OGUI)write.o $(OGUI)zap.o + $(OGUI)write.o $(OGUI)zap.o $(OGUI)sfbase.o OBJSGUI = $(MDLIBGUI) $(COREOBJGUI) $(REGEXGUI) $(RANDOMGUI) @@ -1458,6 +1459,8 @@ DLB = #========================================== {$(R_UTIL)}.c{$(R_OBJUTIL)}.o: + echo R_UTIL=$(R_UTIL) + echo R_OBJUTIL=$(R_OBJUTIL) $(Q)$(CC) $(CFLAGS) -Fo$@ $< #========================================== @@ -1864,6 +1867,14 @@ $(OGUI)date.o: $(HACKINCL) $(HACKSRC) $(HACKOBJ) $(ALLOBJGUI) @$(MAKE) /NOLOGO /A -f date.nmk !ENDIF +$(OGUI)sfbase.o: sfbase.c $(HACK_H) + $(Q)$(CC) $(CFLAGS) /EP $(@B).c > $(OGUI)$(@B).c.preproc + $(Q)$(CC) $(CFLAGS) -Fo$@ $(@B).c + +$(OTTY)sfbase.o: sfbase.c $(HACK_H) + $(Q)$(CC) $(CFLAGS) /EP $(@B).c > $(OTTY)$(@B).c.preproc + $(Q)$(CC) $(CFLAGS) -Fo$@ $(@B).c + # # date.h is not used with NetHack 3.7 # onames.h is not used with NetHack 3.7 @@ -3069,6 +3080,8 @@ $(OTTY)rumors.o: rumors.c $(HACK_H) $(INCL)dlb.h $(OTTY)save.o: save.c $(HACK_H) $(OTTY)selvar.o: selvar.c $(HACK_H) $(INCL)sp_lev.h $(OTTY)sfstruct.o: sfstruct.c $(HACK_H) + $(Q)$(CC) $(CFLAGS) /EP $(@B).c > $(OTTY)$(@B).c.preproc + $(Q)$(CC) $(CFLAGS) -Fo$@ $(@B).c $(OTTY)shk.o: shk.c $(HACK_H) $(OTTY)shknam.o: shknam.c $(HACK_H) $(OTTY)sit.o: sit.c $(HACK_H) $(INCL)artifact.h @@ -3445,6 +3458,8 @@ $(OGUI)rumors.o: rumors.c $(HACK_H) $(INCL)dlb.h $(OGUI)save.o: save.c $(HACK_H) $(OGUI)selvar.o: selvar.c $(HACK_H) $(INCL)sp_lev.h $(OGUI)sfstruct.o: sfstruct.c $(HACK_H) + $(Q)$(CC) $(CFLAGS) /EP $(@B).c > $(OGUI)$(@B).c.preproc + $(Q)$(CC) $(CFLAGS) -Fo$@ $(@B).c $(OGUI)shk.o: shk.c $(HACK_H) $(OGUI)shknam.o: shknam.c $(HACK_H) $(OGUI)sit.o: sit.c $(HACK_H) $(INCL)artifact.h diff --git a/sys/windows/vs/NetHack/NetHack.vcxproj b/sys/windows/vs/NetHack/NetHack.vcxproj index 7dfa0cf6b..bdc5d771f 100644 --- a/sys/windows/vs/NetHack/NetHack.vcxproj +++ b/sys/windows/vs/NetHack/NetHack.vcxproj @@ -220,6 +220,7 @@ + @@ -294,6 +295,8 @@ + + @@ -314,4 +317,4 @@ - + \ No newline at end of file diff --git a/sys/windows/vs/NetHackW/NetHackW.vcxproj b/sys/windows/vs/NetHackW/NetHackW.vcxproj index 78a43906d..5ba44b3dc 100644 --- a/sys/windows/vs/NetHackW/NetHackW.vcxproj +++ b/sys/windows/vs/NetHackW/NetHackW.vcxproj @@ -252,6 +252,7 @@ + @@ -353,6 +354,8 @@ + + @@ -376,4 +379,4 @@ - + \ No newline at end of file diff --git a/sys/windows/windmain.c b/sys/windows/windmain.c index 04b4668ac..a2fe2da5e 100644 --- a/sys/windows/windmain.c +++ b/sys/windows/windmain.c @@ -366,6 +366,9 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/ nethack_exit(EXIT_SUCCESS); if (getlock_result < 0) { + if (program_state.in_self_recover) { + program_state.in_self_recover = FALSE; + } set_savefile_name(TRUE); } /* Set up level 0 file to keep the game state. diff --git a/sys/windows/windsys.c b/sys/windows/windsys.c index ea425ce26..d7178cffa 100644 --- a/sys/windows/windsys.c +++ b/sys/windows/windsys.c @@ -505,20 +505,6 @@ get_port_id(char *buf) extern void free_winmain_stuff(void); #endif -/* return TRUE if s contains a directory, not just a filespec */ -boolean -contains_directory(const char *s) -{ - int i, slen = strlen(s); - const char *cp = s; - - for (i = 0; i < slen; ++i) { - if (*cp == '\\' || *cp == '/' || *cp == ':') - return TRUE; - } - return FALSE; -} - void nethack_exit(int code) { diff --git a/util/.gitignore b/util/.gitignore index 56d768999..11fa8a1f0 100644 --- a/util/.gitignore +++ b/util/.gitignore @@ -30,4 +30,5 @@ heaputil heaputil.c tilemappings.lst clang_rt.asan*.dll +*.sln diff --git a/util/recover.c b/util/recover.c index 07481cbc5..f43d1132c 100644 --- a/util/recover.c +++ b/util/recover.c @@ -12,9 +12,16 @@ #include "win32api.h" #endif +#define RECOVER_C + #include "config.h" #include "hacklib.h" +#include "artifact.h" +#include "rect.h" +#include "dungeon.h" +#include "hack.h" + #if !defined(O_WRONLY) && !defined(LSC) && !defined(AZTEC_C) #include #endif @@ -267,10 +274,12 @@ restore_savefile(char *basename) } /* save file should contain: - * format indicator and cmc + * format indicator (1 byte) + * n = count of critical size list (1 byte) + * n bytes of critical sizes (n bytes) * version info - * savefile info - * player name + * plnametmp = player name size (int, 2 bytes) + * player name (PL_NSIZ_PLUS) * current level (including pets) * (non-level-based) game state * other levels