1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #define FORBIDDEN_SYMBOL_EXCEPTION_time_h
24 
25 #include "backends/platform/ps2/systemps2.h"
26 #include "backends/platform/ps2/ps2debug.h"
27 #include "eecodyvdfs.h"
28 #include <osd_config.h>
29 #include <time.h>
30 
31 #define FROM_BCD(a) ((a >> 4) * 10 + (a & 0xF))
32 
33 static int g_timeSecs;
34 static int g_day, g_month, g_year;
35 static int g_lastTimeCheck;
36 extern volatile uint32 msecCount;
37 
buildNewDate(int dayDiff)38 void buildNewDate(int dayDiff) {
39 	static int daysPerMonth[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
40 	if (((g_year % 4) == 0) && (((g_year % 100) != 0) || ((g_year % 1000) == 0)))
41 		daysPerMonth[1] = 29;
42 	else
43 		daysPerMonth[1] = 28;
44 
45 	if (dayDiff == -1) {
46 		g_day--;
47 		if (g_day == 0) {
48 			g_month--;
49 			if (g_month == 0) {
50 				g_year--;
51 				g_month = 12;
52 			}
53 			g_day = daysPerMonth[g_month - 1];
54 		}
55 	} else if (dayDiff == 1) {
56 		g_day++;
57 		if (g_day > daysPerMonth[g_month - 1]) {
58 			g_day = 1;
59 			g_month++;
60 			if (g_month > 12) {
61 				g_month = 1;
62 				g_year++;
63 			}
64 		}
65 	}
66 }
67 
68 #define SECONDS_PER_DAY (24 * 60 * 60)
69 
readRtcTime(void)70 void OSystem_PS2::readRtcTime(void) {
71 	struct CdClock cdClock;
72 	readRTC(&cdClock);
73 
74 	g_lastTimeCheck = getMillis();
75 
76 	if (cdClock.stat) {
77 		msgPrintf(5000, "Unable to read RTC time, EC: %d\n", cdClock.stat);
78 		g_day = g_month = 1;
79 		g_year = 0;
80 		g_timeSecs = 0;
81 	} else {
82 		int gmtOfs = configGetTimezone();
83 		if (configIsDaylightSavingEnabled())
84 			gmtOfs += 60;
85 
86 		int timeSecs = (FROM_BCD(cdClock.hour) * 60 + FROM_BCD(cdClock.minute)) * 60 + FROM_BCD(cdClock.second);
87 		timeSecs -= 9 * 60 * 60; // minus 9 hours, JST -> GMT conversion
88 		timeSecs += gmtOfs * 60; // GMT -> timezone the user selected
89 
90 		g_day = FROM_BCD(cdClock.day);
91 		g_month = FROM_BCD(cdClock.month);
92 		g_year = FROM_BCD(cdClock.year);
93 
94 		if (timeSecs < 0) {
95 			buildNewDate(-1);
96 			timeSecs += SECONDS_PER_DAY;
97 		} else if (timeSecs >= SECONDS_PER_DAY) {
98 			buildNewDate(+1);
99 			timeSecs -= SECONDS_PER_DAY;
100 		}
101 		g_timeSecs = (uint32)timeSecs;
102 	}
103 
104 	sioprintf("Time: %d:%02d:%02d - %d.%d.%4d\n", g_timeSecs / (60 * 60), (g_timeSecs / 60) % 60, g_timeSecs % 60,
105 		g_day, g_month, g_year + 2000);
106 }
107 
108 // Tomohiko Sakamoto's 1993 algorithm for any Gregorian date
dayOfWeek(int y,int m,int d)109 static int dayOfWeek(int y, int m, int d) {
110 	static const int t[] = { 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4 };
111 	y -= m < 3;
112 	return (y + y / 4 - y / 100 + y / 400 + t[m - 1] + d) % 7;
113 }
114 
getTimeAndDate(TimeDate & t) const115 void OSystem_PS2::getTimeAndDate(TimeDate &t) const {
116 	uint32 currentSecs = g_timeSecs + (msecCount - g_lastTimeCheck) / 1000;
117 	if (currentSecs >= SECONDS_PER_DAY) {
118 		buildNewDate(+1);
119 		g_lastTimeCheck += SECONDS_PER_DAY * 1000;
120 		currentSecs = g_timeSecs + (msecCount - g_lastTimeCheck) / 1000;
121 	}
122 
123 	t.tm_hour = currentSecs / (60 * 60);
124 	t.tm_min  = (currentSecs / 60) % 60;
125 	t.tm_sec  = currentSecs % 60;
126 	t.tm_year = g_year + 100;
127 	t.tm_mday = g_day;
128 	t.tm_mon  = g_month - 1;
129 	t.tm_wday = dayOfWeek(t.tm_year, t.tm_mon, t.tm_mday);
130 }
131