remove time_t from struct you (trunk only)
There was an issue reported where save files between different versions of a manufacturer's compiler were incompatible because the time_t ubirthday field was changed from 32 bits to 64 bits. 32 bit time_t implementations will break at 19:14:07 on January 18, 2038. 64 bit time_t implementations will break at 23:59:59 on December 31, 3000. This removes the dependency on the size of time_t from the save file. The ubirthday field is no longer embedded in struct you. This also adds two general purpose routines to hacklib.c, one to convert a time value to a 14 character char representation and the other to convert that back to time_t. Those are used by the save/restore routines. This is a savefile breaking change, so editlevel in patchlevel.h was incremented.
This commit is contained in:
@@ -251,6 +251,7 @@ E NEARDATA anything zeroany; /* init'd and defined in decl.c */
|
||||
|
||||
#include "you.h"
|
||||
E NEARDATA struct you u;
|
||||
E NEARDATA time_t ubirthday;
|
||||
|
||||
#include "onames.h"
|
||||
#ifndef PM_H /* (pm.h has already been included via youprop.h) */
|
||||
|
||||
@@ -850,6 +850,8 @@ E char *FDECL(yymmdd, (time_t));
|
||||
#endif
|
||||
E long FDECL(yyyymmdd, (time_t));
|
||||
E long FDECL(hhmmss, (time_t));
|
||||
E char *FDECL(yyyymmddhhmmss,(time_t));
|
||||
E time_t FDECL(time_from_yyyymmddhhmmss, (char *));
|
||||
E int NDECL(phase_of_the_moon);
|
||||
E boolean NDECL(friday_13th);
|
||||
E int NDECL(night);
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* Incrementing EDITLEVEL can be used to force invalidation of old bones
|
||||
* and save files.
|
||||
*/
|
||||
#define EDITLEVEL 39
|
||||
#define EDITLEVEL 40
|
||||
|
||||
#define COPYRIGHT_BANNER_A \
|
||||
"NetHack, Copyright 1985-2007"
|
||||
|
||||
@@ -355,8 +355,6 @@ struct you {
|
||||
#endif
|
||||
int umortality; /* how many times you died */
|
||||
int ugrave_arise; /* you die and become something aside from a ghost */
|
||||
time_t ubirthday; /* real world time when game began */
|
||||
|
||||
int weapon_slots; /* unused skill slots */
|
||||
int skills_advanced; /* # of advances made so far */
|
||||
xchar skill_record[P_SKILL_LIMIT]; /* skill advancements */
|
||||
|
||||
@@ -137,6 +137,7 @@ NEARDATA struct sysflag sysflags = DUMMY;
|
||||
#endif
|
||||
NEARDATA struct instance_flags iflags = DUMMY;
|
||||
NEARDATA struct you u = DUMMY;
|
||||
NEARDATA time_t ubirthday = DUMMY;
|
||||
|
||||
NEARDATA struct obj *invent = (struct obj *)0,
|
||||
*uwep = (struct obj *)0, *uarm = (struct obj *)0,
|
||||
|
||||
@@ -45,6 +45,8 @@ NetHack, except that rounddiv may call panic().
|
||||
char * yymmdd (time_t)
|
||||
long yyyymmdd (time_t)
|
||||
long hhmmss (time_t)
|
||||
char * yyyymmddhhmmss (time_t)
|
||||
time_t time_from_yyyymmddhhmmss (char *)
|
||||
int phase_of_the_moon (void)
|
||||
boolean friday_13th (void)
|
||||
int night (void)
|
||||
@@ -638,6 +640,82 @@ time_t date;
|
||||
return timenum;
|
||||
}
|
||||
|
||||
char *
|
||||
yyyymmddhhmmss(date)
|
||||
time_t date;
|
||||
{
|
||||
long datenum;
|
||||
static char datestr[15];
|
||||
struct tm *lt;
|
||||
|
||||
if (date == 0)
|
||||
lt = getlt();
|
||||
else
|
||||
#if (defined(ULTRIX) && !(defined(ULTRIX_PROTO) || defined(NHSTDC))) || defined(BSD)
|
||||
lt = localtime((long *)(&date));
|
||||
#else
|
||||
lt = localtime(&date);
|
||||
#endif
|
||||
/* just in case somebody's localtime supplies (year % 100)
|
||||
rather than the expected (year - 1900) */
|
||||
if (lt->tm_year < 70)
|
||||
datenum = (long)lt->tm_year + 2000L;
|
||||
else
|
||||
datenum = (long)lt->tm_year + 1900L;
|
||||
Sprintf(datestr, "%04d%02d%02d%02d%02d%02d",
|
||||
datenum, lt->tm_mon + 1, lt->tm_mday,
|
||||
lt->tm_hour, lt->tm_min, lt->tm_sec);
|
||||
return(datestr);
|
||||
}
|
||||
|
||||
time_t
|
||||
time_from_yyyymmddhhmmss(buf)
|
||||
char *buf;
|
||||
{
|
||||
int k;
|
||||
struct tm t, *lt;
|
||||
char *g, *p, y[5],mo[3],d[3],h[3],mi[3],s[3];
|
||||
if (buf && strlen(buf) == 14) {
|
||||
g = buf;
|
||||
p = y; /* year */
|
||||
for (k = 0; k < 4; ++k)
|
||||
*p++ = *g++;
|
||||
*p = '\0';
|
||||
p = mo; /* month */
|
||||
for (k = 0; k < 2; ++k)
|
||||
*p++ = *g++;
|
||||
*p = '\0';
|
||||
p = d; /* day */
|
||||
for (k = 0; k < 2; ++k)
|
||||
*p++ = *g++;
|
||||
*p = '\0';
|
||||
p = h; /* hour */
|
||||
for (k = 0; k < 2; ++k)
|
||||
*p++ = *g++;
|
||||
*p = '\0';
|
||||
p = mi; /* minutes */
|
||||
for (k = 0; k < 2; ++k)
|
||||
*p++ = *g++;
|
||||
*p = '\0';
|
||||
p = s; /* seconds */
|
||||
for (k = 0; k < 2; ++k)
|
||||
*p++ = *g++;
|
||||
*p = '\0';
|
||||
lt = getlt();
|
||||
if (lt) {
|
||||
t = *lt;
|
||||
t.tm_year = atoi(y) - 1900;
|
||||
t.tm_mon = atoi(mo) - 1;
|
||||
t.tm_mday = atoi(d);
|
||||
t.tm_hour = atoi(h);
|
||||
t.tm_min = atoi(mi);
|
||||
t.tm_sec = atoi(s);
|
||||
return mktime(&t);
|
||||
}
|
||||
}
|
||||
return (time_t)0;
|
||||
}
|
||||
|
||||
/*
|
||||
* moon period = 29.53058 days ~= 30, year = 365.2422 days
|
||||
* days moon phase advances on first day of year compared to preceding year
|
||||
|
||||
@@ -431,7 +431,7 @@ antholemon()
|
||||
int mtyp, indx, trycnt = 0;
|
||||
|
||||
/* casts are for dealing with time_t */
|
||||
indx = (int)((long)u.ubirthday % 3L);
|
||||
indx = (int)((long)ubirthday % 3L);
|
||||
indx += level_difficulty();
|
||||
/* Same monsters within a level, different ones between levels */
|
||||
do {
|
||||
|
||||
@@ -104,7 +104,7 @@ doread()
|
||||
if (erosion)
|
||||
wipeout_text(buf,
|
||||
(int)(strlen(buf) * erosion / (2*MAX_ERODE)),
|
||||
scroll->o_id ^ (unsigned)u.ubirthday);
|
||||
scroll->o_id ^ (unsigned)ubirthday);
|
||||
pline("\"%s\"", buf);
|
||||
return 1;
|
||||
#endif /* TOURIST */
|
||||
|
||||
@@ -522,6 +522,7 @@ unsigned int *stuckid, *steedid; /* STEED */
|
||||
struct sysflag newgamesysflags;
|
||||
#endif
|
||||
struct obj *otmp, *tmp_bc;
|
||||
char timebuf[15];
|
||||
int uid;
|
||||
|
||||
mread(fd, (genericptr_t) &uid, sizeof uid);
|
||||
@@ -565,6 +566,9 @@ unsigned int *stuckid, *steedid; /* STEED */
|
||||
amii_setpens(amii_numcolors); /* use colors from save file */
|
||||
#endif
|
||||
mread(fd, (genericptr_t) &u, sizeof(struct you));
|
||||
mread(fd, (genericptr_t) timebuf, 14);
|
||||
ubirthday = time_from_yyyymmddhhmmss(timebuf);
|
||||
|
||||
set_uasmon();
|
||||
#ifdef CLIPPING
|
||||
cliparound(u.ux, u.uy);
|
||||
|
||||
@@ -310,6 +310,7 @@ register int fd, mode;
|
||||
if (u.ugold) (void)insert_gold_into_invent(FALSE);
|
||||
#endif
|
||||
bwrite(fd, (genericptr_t) &u, sizeof(struct you));
|
||||
bwrite(fd, yyyymmddhhmmss(ubirthday), 14);
|
||||
save_killers(fd, mode);
|
||||
|
||||
/* must come before migrating_objs and migrating_mons are freed */
|
||||
|
||||
@@ -1847,7 +1847,7 @@ register struct monst *shkp; /* if angry, impose a surcharge */
|
||||
/* get a value that's 'random' from game to game, but the
|
||||
same within the same game */
|
||||
boolean pseudorand =
|
||||
(((int)u.ubirthday % obj->otyp) >= obj->otyp/2);
|
||||
(((int)ubirthday % obj->otyp) >= obj->otyp/2);
|
||||
|
||||
/* all gems are priced high - real or not */
|
||||
switch(obj->otyp - LAST_GEM) {
|
||||
|
||||
@@ -412,7 +412,7 @@ const char * const *nlp;
|
||||
and restore support which would be necessary for randomization;
|
||||
try not to make too many assumptions about time_t's internals;
|
||||
use ledger_no rather than depth to keep mine town distinct. */
|
||||
int nseed = (int)((long)u.ubirthday / 257L);
|
||||
int nseed = (int)((long)ubirthday / 257L);
|
||||
|
||||
name_wanted = ledger_no(&u.uz) + (nseed % 13) - (nseed % 5);
|
||||
if (name_wanted < 0) name_wanted += (13 + 5);
|
||||
|
||||
@@ -362,7 +362,7 @@ int how;
|
||||
(void) strncat(t0->death, killer.name, DTHSZ);
|
||||
break;
|
||||
}
|
||||
t0->birthdate = yyyymmdd(u.ubirthday);
|
||||
t0->birthdate = yyyymmdd(ubirthday);
|
||||
t0->deathdate = yyyymmdd((time_t)0L);
|
||||
t0->tt_next = 0;
|
||||
#ifdef UPDATE_RECORD_IN_PLACE
|
||||
|
||||
@@ -524,6 +524,7 @@ u_init()
|
||||
* necessary when aborting from a failed restore */
|
||||
(void) memset((genericptr_t)&u, 0, sizeof(u));
|
||||
u.ustuck = (struct monst *)0;
|
||||
(void) memset((genericptr_t)&ubirthday, 0, sizeof(ubirthday));
|
||||
|
||||
#if 0 /* documentation of more zero values as desirable */
|
||||
u.usick_cause[0] = 0;
|
||||
@@ -578,9 +579,9 @@ u_init()
|
||||
u.ulycn = NON_PM;
|
||||
|
||||
#if defined(BSD) && !defined(POSIX_TYPES)
|
||||
(void) time((long *)&u.ubirthday);
|
||||
(void) time((long *)&ubirthday);
|
||||
#else
|
||||
(void) time(&u.ubirthday);
|
||||
(void) time(&ubirthday);
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
||||
@@ -218,7 +218,7 @@ cdebug = -Zi -Od
|
||||
# Util builds
|
||||
#==========================================
|
||||
|
||||
cflagsUtil = $(cdebug) $(cflags) /D_USE_32BIT_TIME_T $(INCLDIR) \
|
||||
cflagsUtil = $(cdebug) $(cflags) $(INCLDIR) \
|
||||
$(WINPFLAG) $(DLBFLG)
|
||||
lflagsUtil = $(ldebug) $(lflags) $(conlibs)
|
||||
|
||||
@@ -232,13 +232,13 @@ LIBS= user32.lib winmm.lib $(ZLIB)
|
||||
|
||||
!IF ("$(GRAPHICAL)"=="Y")
|
||||
|
||||
cflagsGame = $(cdebug) $(cflags) /D_USE_32BIT_TIME_T $(guiflags) $(INCLDIR) \
|
||||
cflagsGame = $(cdebug) $(cflags) $(guiflags) $(INCLDIR) \
|
||||
$(WINPFLAG) $(DLBFLG) $(GAMEPDBFILE) $(GAMEMAPFILE)
|
||||
lflagsGame = $(ldebug) $(lflags) $(guilibs)
|
||||
|
||||
!ELSE
|
||||
|
||||
cflagsGame = $(cdebug) $(cflags) /D_USE_32BIT_TIME_T $(conflags) $(INCLDIR) \
|
||||
cflagsGame = $(cdebug) $(cflags) $(conflags) $(INCLDIR) \
|
||||
$(WINPFLAG) $(DLBFLG) $(GAMEPDBFILE) $(GAMEMAPFILE)
|
||||
lflagsGame = $(ldebug) $(lflags) $(conlibs)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user