From a0c5eb1ed8a54d8041c9664424f377ce95f731c6 Mon Sep 17 00:00:00 2001 From: zeromus Date: Wed, 21 Apr 2010 06:20:12 +0000 Subject: [PATCH] add a more stable mkgmtime and otherwise straighten out some rtc stuff --- desmume/src/GPU_osd.cpp | 9 +- desmume/src/Makefile.am | 1 + desmume/src/movie.cpp | 45 ++--- desmume/src/rtc.cpp | 55 ++---- desmume/src/rtc.h | 9 +- desmume/src/utils/mkgmtime.cpp | 251 ++++++++++++++++++++++++ desmume/src/utils/mkgmtime.h | 28 +++ desmume/src/windows/DeSmuME_2005.vcproj | 40 ++++ desmume/src/windows/DeSmuME_2008.vcproj | 8 + desmume/src/windows/replay.cpp | 8 +- 10 files changed, 378 insertions(+), 76 deletions(-) create mode 100644 desmume/src/utils/mkgmtime.cpp create mode 100644 desmume/src/utils/mkgmtime.h diff --git a/desmume/src/GPU_osd.cpp b/desmume/src/GPU_osd.cpp index ca3147ea9..6e893fb74 100644 --- a/desmume/src/GPU_osd.cpp +++ b/desmume/src/GPU_osd.cpp @@ -1,8 +1,5 @@ /* Copyright (C) 2006 yopyop - yopyop156@ifrance.com - yopyop156.ifrance.com - - Copyright (C) 2006-2008 DeSmuME team + Copyright (C) 2006-2010 DeSmuME team This file is part of DeSmuME @@ -565,9 +562,9 @@ void DrawHUD() if (CommonSettings.hud.ShowRTC) { - struct tm *tm = rtcGetTime(); + struct tm tm = rtcGetTime(); const char *wday[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; - osd->addFixed(Hud.RTCDisplay.x, Hud.RTCDisplay.y, "%04d-%02d-%02d %s %02d:%02d:%02d", 1900 + tm->tm_year, 1 + tm->tm_mon, tm->tm_mday, wday[tm->tm_wday%7], tm->tm_hour, tm->tm_min, tm->tm_sec); + osd->addFixed(Hud.RTCDisplay.x, Hud.RTCDisplay.y, "%04d-%02d-%02d %s %02d:%02d:%02d", 1900 + tm.tm_year, 1 + tm.tm_mon, tm.tm_mday, wday[tm.tm_wday%7], tm.tm_hour, tm.tm_min, tm.tm_sec); } DrawStateSlots(); diff --git a/desmume/src/Makefile.am b/desmume/src/Makefile.am index a36759749..9bb9034c0 100644 --- a/desmume/src/Makefile.am +++ b/desmume/src/Makefile.am @@ -41,6 +41,7 @@ libdesmume_a_SOURCES = \ shaders.h \ movie.cpp movie.h \ PACKED.h PACKED_END.h \ + utils/mkgmtime.cpp utils/mkgmtime.h \ utils/ConvertUTF.c utils/ConvertUTF.h utils/guid.cpp utils/guid.h \ utils/md5.cpp utils/md5.h utils/valuearray.h utils/xstring.cpp utils/xstring.h \ utils/decrypt/crc.cpp utils/decrypt/crc.h utils/decrypt/decrypt.cpp \ diff --git a/desmume/src/movie.cpp b/desmume/src/movie.cpp index e37e7e5f0..57ad88392 100644 --- a/desmume/src/movie.cpp +++ b/desmume/src/movie.cpp @@ -1,22 +1,20 @@ -/* movie.cpp - * - * Copyright (C) 2006-2009 DeSmuME team - * - * This file is part of DeSmuME - * - * DeSmuME is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * DeSmuME is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with DeSmuME; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +/* Copyright 2008-2010 DeSmuME team + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #define WIN32_LEAN_AND_MEAN @@ -26,6 +24,7 @@ #include #include "utils/guid.h" #include "utils/xstring.h" +#include "utils/mkgmtime.h" #include "movie.h" #include "NDSSystem.h" #include "readwrite.h" @@ -181,13 +180,12 @@ time_t FCEUI_MovieGetRTCDefault() t.tm_hour = 0; //12 AM t.tm_min = 0; t.tm_sec = 0; - t.tm_isdst= -1; - timer = gmmktime(&t); + timer = mkgmtime(&t); // current time //timer = time(NULL); //struct tm *tp = localtime(&timer); - //timer = gmmktime(tp); + //timer = mkgmtime(tp); return timer; } @@ -246,8 +244,7 @@ void MovieData::installValue(std::string& key, std::string& val) t.tm_hour = atoi(&s[11]); t.tm_min = atoi(&s[14]); t.tm_sec = atoi(&s[17]); - t.tm_isdst= -1; - rtcStart = gmmktime(&t); + rtcStart = mkgmtime(&t); } } else if(key == "comment") diff --git a/desmume/src/rtc.cpp b/desmume/src/rtc.cpp index 1df1ca56d..0b04b14e7 100644 --- a/desmume/src/rtc.cpp +++ b/desmume/src/rtc.cpp @@ -1,9 +1,6 @@ /* Copyright (C) 2006 yopyop - yopyop156@ifrance.com - yopyop156.ifrance.com - Copyright 2008 CrazyMax - Copyright 2008-2009 DeSmuME team + Copyright 2008-2010 DeSmuME team This file is part of DeSmuME @@ -35,22 +32,8 @@ #endif #include "movie.h" -static time_t CalcTimeDifference(void) -{ - time_t t1, t2; - tm *tm_tmp; +#include "utils/mkgmtime.h" - time(&t1); - tm_tmp = gmtime(&t1); - t2 = mktime(tm_tmp); - - return (t2 - t1); -} - -time_t gmmktime(struct tm *timeptr) -{ - return mktime(timeptr) - CalcTimeDifference(); -} typedef struct { @@ -115,7 +98,7 @@ static inline u8 toBCD(u8 x) bool moviemode=false; -struct tm* rtcGetTime(void) +struct tm rtcGetTime(void) { struct tm *tm = NULL; if(movieMode == MOVIEMODE_INACTIVE) { @@ -143,11 +126,11 @@ struct tm* rtcGetTime(void) // advance it according to the frame counter t.tm_sec += totalseconds; // then, normalize it - timer = gmmktime(&t); + timer = mkgmtime(&t); tm = gmtime(&timer); } tm->tm_year = 100 + (tm->tm_year % 100); // 20XX - return tm; + return *tm; } static void rtcRecv() @@ -170,26 +153,26 @@ static void rtcRecv() case 2: // date & time { //INFO("RTC: read date & time\n"); - struct tm *tm = rtcGetTime(); - rtc.data[0] = toBCD(tm->tm_year % 100); - rtc.data[1] = toBCD(tm->tm_mon + 1); - rtc.data[2] = toBCD(tm->tm_mday); - rtc.data[3] = (tm->tm_wday + 7) & 7; + struct tm tm = rtcGetTime(); + rtc.data[0] = toBCD(tm.tm_year % 100); + rtc.data[1] = toBCD(tm.tm_mon + 1); + rtc.data[2] = toBCD(tm.tm_mday); + rtc.data[3] = (tm.tm_wday + 7) & 7; if (rtc.data[3] == 7) rtc.data[3] = 6; - if (!(rtc.regStatus1 & 0x02)) tm->tm_hour %= 12; - rtc.data[4] = ((tm->tm_hour < 12) ? 0x00 : 0x40) | toBCD(tm->tm_hour); - rtc.data[5] = toBCD(tm->tm_min); - rtc.data[6] = toBCD(tm->tm_sec); + if (!(rtc.regStatus1 & 0x02)) tm.tm_hour %= 12; + rtc.data[4] = ((tm.tm_hour < 12) ? 0x00 : 0x40) | toBCD(tm.tm_hour); + rtc.data[5] = toBCD(tm.tm_min); + rtc.data[6] = toBCD(tm.tm_sec); break; } case 3: // time { //INFO("RTC: read time\n"); - struct tm *tm = rtcGetTime(); - if (!(rtc.regStatus1 & 0x02)) tm->tm_hour %= 12; - rtc.data[0] = ((tm->tm_hour < 12) ? 0x00 : 0x40) | toBCD(tm->tm_hour); - rtc.data[1] = toBCD(tm->tm_min); - rtc.data[2] = toBCD(tm->tm_sec); + struct tm tm = rtcGetTime(); + if (!(rtc.regStatus1 & 0x02)) tm.tm_hour %= 12; + rtc.data[0] = ((tm.tm_hour < 12) ? 0x00 : 0x40) | toBCD(tm.tm_hour); + rtc.data[1] = toBCD(tm.tm_min); + rtc.data[2] = toBCD(tm.tm_sec); break; } case 4: // freq/alarm 1 diff --git a/desmume/src/rtc.h b/desmume/src/rtc.h index 1248503de..f8e924bac 100644 --- a/desmume/src/rtc.h +++ b/desmume/src/rtc.h @@ -1,9 +1,6 @@ /* Copyright (C) 2006 yopyop - yopyop156@ifrance.com - yopyop156.ifrance.com - Copyright 2008 CrazyMax - Copyright 2008-2009 DeSmuME team + Copyright 2008-2010 DeSmuME team This file is part of DeSmuME @@ -28,9 +25,7 @@ #include #include "types.h" -extern time_t gmmktime(struct tm *timeptr); - -struct tm* rtcGetTime(void); +struct tm rtcGetTime(void); extern void rtcInit(); extern u16 rtcRead(); diff --git a/desmume/src/utils/mkgmtime.cpp b/desmume/src/utils/mkgmtime.cpp new file mode 100644 index 000000000..253ef050f --- /dev/null +++ b/desmume/src/utils/mkgmtime.cpp @@ -0,0 +1,251 @@ +/* utils/mkgmtime.cpp + + Copyright (C) 2010 DeSmuME team + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +//Taken from newlib 1.18.0 which is licensed under GPL 2 and modified for desmume + +/* + * mktime.c + * Original Author: G. Haley + * + * Converts the broken-down time, expressed as local time, in the structure + * pointed to by tim_p into a calendar time value. The original values of the + * tm_wday and tm_yday fields of the structure are ignored, and the original + * values of the other fields have no restrictions. On successful completion + * the fields of the structure are set to represent the specified calendar + * time. Returns the specified calendar time. If the calendar time can not be + * represented, returns the value (time_t) -1. + * + * Modifications: Fixed tm_isdst usage - 27 August 2008 Craig Howland. + */ + +#include +#include + +#define _SEC_IN_MINUTE 60L +#define _SEC_IN_HOUR 3600L +#define _SEC_IN_DAY 86400L + +static const int DAYS_IN_MONTH[12] = +{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + +#define _DAYS_IN_MONTH(x) ((x == 1) ? days_in_feb : DAYS_IN_MONTH[x]) + +static const int _DAYS_BEFORE_MONTH[12] = +{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; + +#define _ISLEAP(y) (((y) % 4) == 0 && (((y) % 100) != 0 || (((y)+1900) % 400) == 0)) +#define _DAYS_IN_YEAR(year) (_ISLEAP(year) ? 366 : 365) + +static void validate_structure(tm *tim_p) +{ + div_t res; + int days_in_feb = 28; + + /* calculate time & date to account for out of range values */ + if (tim_p->tm_sec < 0 || tim_p->tm_sec > 59) + { + res = div (tim_p->tm_sec, 60); + tim_p->tm_min += res.quot; + if ((tim_p->tm_sec = res.rem) < 0) + { + tim_p->tm_sec += 60; + --tim_p->tm_min; + } + } + + if (tim_p->tm_min < 0 || tim_p->tm_min > 59) + { + res = div (tim_p->tm_min, 60); + tim_p->tm_hour += res.quot; + if ((tim_p->tm_min = res.rem) < 0) + { + tim_p->tm_min += 60; + --tim_p->tm_hour; + } + } + + if (tim_p->tm_hour < 0 || tim_p->tm_hour > 23) + { + res = div (tim_p->tm_hour, 24); + tim_p->tm_mday += res.quot; + if ((tim_p->tm_hour = res.rem) < 0) + { + tim_p->tm_hour += 24; + --tim_p->tm_mday; + } + } + + if (tim_p->tm_mon > 11) + { + res = div (tim_p->tm_mon, 12); + tim_p->tm_year += res.quot; + if ((tim_p->tm_mon = res.rem) < 0) + { + tim_p->tm_mon += 12; + --tim_p->tm_year; + } + } + + if (_DAYS_IN_YEAR (tim_p->tm_year) == 366) + days_in_feb = 29; + + if (tim_p->tm_mday <= 0) + { + while (tim_p->tm_mday <= 0) + { + if (--tim_p->tm_mon == -1) + { + tim_p->tm_year--; + tim_p->tm_mon = 11; + days_in_feb = + ((_DAYS_IN_YEAR (tim_p->tm_year) == 366) ? + 29 : 28); + } + tim_p->tm_mday += _DAYS_IN_MONTH (tim_p->tm_mon); + } + } + else + { + while (tim_p->tm_mday > _DAYS_IN_MONTH (tim_p->tm_mon)) + { + tim_p->tm_mday -= _DAYS_IN_MONTH (tim_p->tm_mon); + if (++tim_p->tm_mon == 12) + { + tim_p->tm_year++; + tim_p->tm_mon = 0; + days_in_feb = + ((_DAYS_IN_YEAR (tim_p->tm_year) == 366) ? + 29 : 28); + } + } + } +} + +time_t mkgmtime(tm *tim_p) +{ + time_t tim = 0; + long days = 0; + int year, isdst, tm_isdst; + + /* validate structure */ + validate_structure (tim_p); + + /* compute hours, minutes, seconds */ + tim += tim_p->tm_sec + (tim_p->tm_min * _SEC_IN_MINUTE) + + (tim_p->tm_hour * _SEC_IN_HOUR); + + /* compute days in year */ + days += tim_p->tm_mday - 1; + days += _DAYS_BEFORE_MONTH[tim_p->tm_mon]; + if (tim_p->tm_mon > 1 && _DAYS_IN_YEAR (tim_p->tm_year) == 366) + days++; + + /* compute day of the year */ + tim_p->tm_yday = days; + + if (tim_p->tm_year > 10000 + || tim_p->tm_year < -10000) + { + return (time_t) -1; + } + + /* compute days in other years */ + if (tim_p->tm_year > 70) + { + for (year = 70; year < tim_p->tm_year; year++) + days += _DAYS_IN_YEAR (year); + } + else if (tim_p->tm_year < 70) + { + for (year = 69; year > tim_p->tm_year; year--) + days -= _DAYS_IN_YEAR (year); + days -= _DAYS_IN_YEAR (year); + } + + /* compute day of the week */ + if ((tim_p->tm_wday = (days + 4) % 7) < 0) + tim_p->tm_wday += 7; + + /* compute total seconds */ + tim += (days * _SEC_IN_DAY); + + /* Convert user positive into 1 */ + tm_isdst = tim_p->tm_isdst > 0 ? 1 : tim_p->tm_isdst; + isdst = tm_isdst; + + //screw this! + + // if (_daylight) + // { + // int y = tim_p->tm_year + YEAR_BASE; + // if (y == tz->__tzyear || __tzcalc_limits (y)) + //{ + // /* calculate start of dst in dst local time and + // start of std in both std local time and dst local time */ + // time_t startdst_dst = tz->__tzrule[0].change + // - (time_t) tz->__tzrule[1].offset; + // time_t startstd_dst = tz->__tzrule[1].change + // - (time_t) tz->__tzrule[1].offset; + // time_t startstd_std = tz->__tzrule[1].change + // - (time_t) tz->__tzrule[0].offset; + // /* if the time is in the overlap between dst and std local times */ + // if (tim >= startstd_std && tim < startstd_dst) + // ; /* we let user decide or leave as -1 */ + // else + // { + // isdst = (tz->__tznorth + // ? (tim >= startdst_dst && tim < startstd_std) + // : (tim >= startdst_dst || tim < startstd_std)); + // /* if user committed and was wrong, perform correction, but not + // * if the user has given a negative value (which + // * asks mktime() to determine if DST is in effect or not) */ + // if (tm_isdst >= 0 && (isdst ^ tm_isdst) == 1) + // { + // /* we either subtract or add the difference between + // time zone offsets, depending on which way the user got it + // wrong. The diff is typically one hour, or 3600 seconds, + // and should fit in a 16-bit int, even though offset + // is a long to accomodate 12 hours. */ + // int diff = (int) (tz->__tzrule[0].offset + // - tz->__tzrule[1].offset); + // if (!isdst) + // diff = -diff; + // tim_p->tm_sec += diff; + // validate_structure (tim_p); + // tim += diff; /* we also need to correct our current time calculation */ + // } + // } + //} + // } + + //screw this also + /* add appropriate offset to put time in gmt format */ + //if (isdst == 1) + // tim += (time_t) tz->__tzrule[1].offset; + //else /* otherwise assume std time */ + // tim += (time_t) tz->__tzrule[0].offset; + + //and screw this too + /* reset isdst flag to what we have calculated */ + tim_p->tm_isdst = isdst; + + return tim; +} diff --git a/desmume/src/utils/mkgmtime.h b/desmume/src/utils/mkgmtime.h new file mode 100644 index 000000000..bf211987d --- /dev/null +++ b/desmume/src/utils/mkgmtime.h @@ -0,0 +1,28 @@ +/* utils/mkgmtime.h + + Copyright (C) 2010 DeSmuME team + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef _MKGMTIME_H_ +#define _MKGMTIME_H_ + +#include +time_t mkgmtime(tm *tim_p); + +#endif //_MKGMTIME_H_ diff --git a/desmume/src/windows/DeSmuME_2005.vcproj b/desmume/src/windows/DeSmuME_2005.vcproj index df910d0df..a2c166495 100644 --- a/desmume/src/windows/DeSmuME_2005.vcproj +++ b/desmume/src/windows/DeSmuME_2005.vcproj @@ -1252,6 +1252,14 @@ RelativePath="..\utils\md5.h" > + + + + @@ -1747,6 +1755,38 @@ RelativePath="..\GPU_osd.h" > + + + + + + + + + + + + + + + + diff --git a/desmume/src/windows/DeSmuME_2008.vcproj b/desmume/src/windows/DeSmuME_2008.vcproj index 0b771baec..2eed7535b 100644 --- a/desmume/src/windows/DeSmuME_2008.vcproj +++ b/desmume/src/windows/DeSmuME_2008.vcproj @@ -1039,6 +1039,14 @@ RelativePath="..\utils\md5.h" > + + + + diff --git a/desmume/src/windows/replay.cpp b/desmume/src/windows/replay.cpp index b4a9e75a2..70ec3ef85 100644 --- a/desmume/src/windows/replay.cpp +++ b/desmume/src/windows/replay.cpp @@ -1,4 +1,5 @@ -/* Copyright (C) 2008-2009 DeSmuME team +/* windows/replay.cpp + Copyright (C) 2008-2010 DeSmuME team This file is part of DeSmuME @@ -28,6 +29,7 @@ #include "movie.h" #include "rtc.h" #include "utils/xstring.h" +#include "utils/mkgmtime.h" bool replayreadonly=1; @@ -273,7 +275,7 @@ static INT_PTR CALLBACK RecordDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, union { struct { SYSTEMTIME rtcMin, rtcMax; }; - SYSTEMTIME rtcMinMax[]; + SYSTEMTIME rtcMinMax[2]; }; ZeroMemory(&rtcMin, sizeof(SYSTEMTIME)); ZeroMemory(&rtcMax, sizeof(SYSTEMTIME)); @@ -312,7 +314,7 @@ static INT_PTR CALLBACK RecordDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, t.tm_min = systime.wMinute; t.tm_sec = systime.wSecond; t.tm_isdst= -1; - rtcstart = gmmktime(&t); + rtcstart = mkgmtime(&t); FCEUI_SaveMovie(fname.c_str(), author, flag, sramfname, rtcstart); EndDialog(hwndDlg, 0);