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"
|
#include "you.h"
|
||||||
E NEARDATA struct you u;
|
E NEARDATA struct you u;
|
||||||
|
E NEARDATA time_t ubirthday;
|
||||||
|
|
||||||
#include "onames.h"
|
#include "onames.h"
|
||||||
#ifndef PM_H /* (pm.h has already been included via youprop.h) */
|
#ifndef PM_H /* (pm.h has already been included via youprop.h) */
|
||||||
|
|||||||
@@ -850,6 +850,8 @@ E char *FDECL(yymmdd, (time_t));
|
|||||||
#endif
|
#endif
|
||||||
E long FDECL(yyyymmdd, (time_t));
|
E long FDECL(yyyymmdd, (time_t));
|
||||||
E long FDECL(hhmmss, (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 int NDECL(phase_of_the_moon);
|
||||||
E boolean NDECL(friday_13th);
|
E boolean NDECL(friday_13th);
|
||||||
E int NDECL(night);
|
E int NDECL(night);
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
* Incrementing EDITLEVEL can be used to force invalidation of old bones
|
* Incrementing EDITLEVEL can be used to force invalidation of old bones
|
||||||
* and save files.
|
* and save files.
|
||||||
*/
|
*/
|
||||||
#define EDITLEVEL 39
|
#define EDITLEVEL 40
|
||||||
|
|
||||||
#define COPYRIGHT_BANNER_A \
|
#define COPYRIGHT_BANNER_A \
|
||||||
"NetHack, Copyright 1985-2007"
|
"NetHack, Copyright 1985-2007"
|
||||||
|
|||||||
@@ -355,8 +355,6 @@ struct you {
|
|||||||
#endif
|
#endif
|
||||||
int umortality; /* how many times you died */
|
int umortality; /* how many times you died */
|
||||||
int ugrave_arise; /* you die and become something aside from a ghost */
|
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 weapon_slots; /* unused skill slots */
|
||||||
int skills_advanced; /* # of advances made so far */
|
int skills_advanced; /* # of advances made so far */
|
||||||
xchar skill_record[P_SKILL_LIMIT]; /* skill advancements */
|
xchar skill_record[P_SKILL_LIMIT]; /* skill advancements */
|
||||||
|
|||||||
@@ -137,6 +137,7 @@ NEARDATA struct sysflag sysflags = DUMMY;
|
|||||||
#endif
|
#endif
|
||||||
NEARDATA struct instance_flags iflags = DUMMY;
|
NEARDATA struct instance_flags iflags = DUMMY;
|
||||||
NEARDATA struct you u = DUMMY;
|
NEARDATA struct you u = DUMMY;
|
||||||
|
NEARDATA time_t ubirthday = DUMMY;
|
||||||
|
|
||||||
NEARDATA struct obj *invent = (struct obj *)0,
|
NEARDATA struct obj *invent = (struct obj *)0,
|
||||||
*uwep = (struct obj *)0, *uarm = (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)
|
char * yymmdd (time_t)
|
||||||
long yyyymmdd (time_t)
|
long yyyymmdd (time_t)
|
||||||
long hhmmss (time_t)
|
long hhmmss (time_t)
|
||||||
|
char * yyyymmddhhmmss (time_t)
|
||||||
|
time_t time_from_yyyymmddhhmmss (char *)
|
||||||
int phase_of_the_moon (void)
|
int phase_of_the_moon (void)
|
||||||
boolean friday_13th (void)
|
boolean friday_13th (void)
|
||||||
int night (void)
|
int night (void)
|
||||||
@@ -638,6 +640,82 @@ time_t date;
|
|||||||
return timenum;
|
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
|
* moon period = 29.53058 days ~= 30, year = 365.2422 days
|
||||||
* days moon phase advances on first day of year compared to preceding year
|
* days moon phase advances on first day of year compared to preceding year
|
||||||
|
|||||||
+1
-1
@@ -431,7 +431,7 @@ antholemon()
|
|||||||
int mtyp, indx, trycnt = 0;
|
int mtyp, indx, trycnt = 0;
|
||||||
|
|
||||||
/* casts are for dealing with time_t */
|
/* casts are for dealing with time_t */
|
||||||
indx = (int)((long)u.ubirthday % 3L);
|
indx = (int)((long)ubirthday % 3L);
|
||||||
indx += level_difficulty();
|
indx += level_difficulty();
|
||||||
/* Same monsters within a level, different ones between levels */
|
/* Same monsters within a level, different ones between levels */
|
||||||
do {
|
do {
|
||||||
|
|||||||
+1
-1
@@ -104,7 +104,7 @@ doread()
|
|||||||
if (erosion)
|
if (erosion)
|
||||||
wipeout_text(buf,
|
wipeout_text(buf,
|
||||||
(int)(strlen(buf) * erosion / (2*MAX_ERODE)),
|
(int)(strlen(buf) * erosion / (2*MAX_ERODE)),
|
||||||
scroll->o_id ^ (unsigned)u.ubirthday);
|
scroll->o_id ^ (unsigned)ubirthday);
|
||||||
pline("\"%s\"", buf);
|
pline("\"%s\"", buf);
|
||||||
return 1;
|
return 1;
|
||||||
#endif /* TOURIST */
|
#endif /* TOURIST */
|
||||||
|
|||||||
@@ -522,6 +522,7 @@ unsigned int *stuckid, *steedid; /* STEED */
|
|||||||
struct sysflag newgamesysflags;
|
struct sysflag newgamesysflags;
|
||||||
#endif
|
#endif
|
||||||
struct obj *otmp, *tmp_bc;
|
struct obj *otmp, *tmp_bc;
|
||||||
|
char timebuf[15];
|
||||||
int uid;
|
int uid;
|
||||||
|
|
||||||
mread(fd, (genericptr_t) &uid, sizeof 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 */
|
amii_setpens(amii_numcolors); /* use colors from save file */
|
||||||
#endif
|
#endif
|
||||||
mread(fd, (genericptr_t) &u, sizeof(struct you));
|
mread(fd, (genericptr_t) &u, sizeof(struct you));
|
||||||
|
mread(fd, (genericptr_t) timebuf, 14);
|
||||||
|
ubirthday = time_from_yyyymmddhhmmss(timebuf);
|
||||||
|
|
||||||
set_uasmon();
|
set_uasmon();
|
||||||
#ifdef CLIPPING
|
#ifdef CLIPPING
|
||||||
cliparound(u.ux, u.uy);
|
cliparound(u.ux, u.uy);
|
||||||
|
|||||||
@@ -310,6 +310,7 @@ register int fd, mode;
|
|||||||
if (u.ugold) (void)insert_gold_into_invent(FALSE);
|
if (u.ugold) (void)insert_gold_into_invent(FALSE);
|
||||||
#endif
|
#endif
|
||||||
bwrite(fd, (genericptr_t) &u, sizeof(struct you));
|
bwrite(fd, (genericptr_t) &u, sizeof(struct you));
|
||||||
|
bwrite(fd, yyyymmddhhmmss(ubirthday), 14);
|
||||||
save_killers(fd, mode);
|
save_killers(fd, mode);
|
||||||
|
|
||||||
/* must come before migrating_objs and migrating_mons are freed */
|
/* 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
|
/* get a value that's 'random' from game to game, but the
|
||||||
same within the same game */
|
same within the same game */
|
||||||
boolean pseudorand =
|
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 */
|
/* all gems are priced high - real or not */
|
||||||
switch(obj->otyp - LAST_GEM) {
|
switch(obj->otyp - LAST_GEM) {
|
||||||
|
|||||||
+1
-1
@@ -412,7 +412,7 @@ const char * const *nlp;
|
|||||||
and restore support which would be necessary for randomization;
|
and restore support which would be necessary for randomization;
|
||||||
try not to make too many assumptions about time_t's internals;
|
try not to make too many assumptions about time_t's internals;
|
||||||
use ledger_no rather than depth to keep mine town distinct. */
|
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);
|
name_wanted = ledger_no(&u.uz) + (nseed % 13) - (nseed % 5);
|
||||||
if (name_wanted < 0) name_wanted += (13 + 5);
|
if (name_wanted < 0) name_wanted += (13 + 5);
|
||||||
|
|||||||
+1
-1
@@ -362,7 +362,7 @@ int how;
|
|||||||
(void) strncat(t0->death, killer.name, DTHSZ);
|
(void) strncat(t0->death, killer.name, DTHSZ);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
t0->birthdate = yyyymmdd(u.ubirthday);
|
t0->birthdate = yyyymmdd(ubirthday);
|
||||||
t0->deathdate = yyyymmdd((time_t)0L);
|
t0->deathdate = yyyymmdd((time_t)0L);
|
||||||
t0->tt_next = 0;
|
t0->tt_next = 0;
|
||||||
#ifdef UPDATE_RECORD_IN_PLACE
|
#ifdef UPDATE_RECORD_IN_PLACE
|
||||||
|
|||||||
+3
-2
@@ -524,6 +524,7 @@ u_init()
|
|||||||
* necessary when aborting from a failed restore */
|
* necessary when aborting from a failed restore */
|
||||||
(void) memset((genericptr_t)&u, 0, sizeof(u));
|
(void) memset((genericptr_t)&u, 0, sizeof(u));
|
||||||
u.ustuck = (struct monst *)0;
|
u.ustuck = (struct monst *)0;
|
||||||
|
(void) memset((genericptr_t)&ubirthday, 0, sizeof(ubirthday));
|
||||||
|
|
||||||
#if 0 /* documentation of more zero values as desirable */
|
#if 0 /* documentation of more zero values as desirable */
|
||||||
u.usick_cause[0] = 0;
|
u.usick_cause[0] = 0;
|
||||||
@@ -578,9 +579,9 @@ u_init()
|
|||||||
u.ulycn = NON_PM;
|
u.ulycn = NON_PM;
|
||||||
|
|
||||||
#if defined(BSD) && !defined(POSIX_TYPES)
|
#if defined(BSD) && !defined(POSIX_TYPES)
|
||||||
(void) time((long *)&u.ubirthday);
|
(void) time((long *)&ubirthday);
|
||||||
#else
|
#else
|
||||||
(void) time(&u.ubirthday);
|
(void) time(&ubirthday);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -218,7 +218,7 @@ cdebug = -Zi -Od
|
|||||||
# Util builds
|
# Util builds
|
||||||
#==========================================
|
#==========================================
|
||||||
|
|
||||||
cflagsUtil = $(cdebug) $(cflags) /D_USE_32BIT_TIME_T $(INCLDIR) \
|
cflagsUtil = $(cdebug) $(cflags) $(INCLDIR) \
|
||||||
$(WINPFLAG) $(DLBFLG)
|
$(WINPFLAG) $(DLBFLG)
|
||||||
lflagsUtil = $(ldebug) $(lflags) $(conlibs)
|
lflagsUtil = $(ldebug) $(lflags) $(conlibs)
|
||||||
|
|
||||||
@@ -232,13 +232,13 @@ LIBS= user32.lib winmm.lib $(ZLIB)
|
|||||||
|
|
||||||
!IF ("$(GRAPHICAL)"=="Y")
|
!IF ("$(GRAPHICAL)"=="Y")
|
||||||
|
|
||||||
cflagsGame = $(cdebug) $(cflags) /D_USE_32BIT_TIME_T $(guiflags) $(INCLDIR) \
|
cflagsGame = $(cdebug) $(cflags) $(guiflags) $(INCLDIR) \
|
||||||
$(WINPFLAG) $(DLBFLG) $(GAMEPDBFILE) $(GAMEMAPFILE)
|
$(WINPFLAG) $(DLBFLG) $(GAMEPDBFILE) $(GAMEMAPFILE)
|
||||||
lflagsGame = $(ldebug) $(lflags) $(guilibs)
|
lflagsGame = $(ldebug) $(lflags) $(guilibs)
|
||||||
|
|
||||||
!ELSE
|
!ELSE
|
||||||
|
|
||||||
cflagsGame = $(cdebug) $(cflags) /D_USE_32BIT_TIME_T $(conflags) $(INCLDIR) \
|
cflagsGame = $(cdebug) $(cflags) $(conflags) $(INCLDIR) \
|
||||||
$(WINPFLAG) $(DLBFLG) $(GAMEPDBFILE) $(GAMEMAPFILE)
|
$(WINPFLAG) $(DLBFLG) $(GAMEPDBFILE) $(GAMEMAPFILE)
|
||||||
lflagsGame = $(ldebug) $(lflags) $(conlibs)
|
lflagsGame = $(ldebug) $(lflags) $(conlibs)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user