aboutsummaryrefslogtreecommitdiff
path: root/backends/platform/ps2/ps2time.cpp
blob: 2e7741bfed2e80c6df90521d3be43f4fee29108f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/* ScummVM - Graphic Adventure Engine
 *
 * ScummVM is the legal property of its developers, whose names
 * are too numerous to list here. Please refer to the COPYRIGHT
 * file distributed with this source distribution.
 *
 * This program 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.

 * This program 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 this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 * $URL$
 * $Id$
 *
 */

#include "backends/platform/ps2/systemps2.h"
#include "eecodyvdfs.h"
#include <osd_config.h>
#define FROM_BCD(a) ((a >> 4) * 10 + (a & 0xF))

static int	  g_timeSecs;
static int	  g_day, g_month, g_year;
static int	  g_lastTimeCheck;
extern volatile uint32 msecCount;

void buildNewDate(int dayDiff) {
	static int daysPerMonth[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
	if (((g_year % 4) == 0) && (((g_year % 100) != 0) || ((g_year % 1000) == 0)))
		daysPerMonth[1] = 29;
	else
		daysPerMonth[1] = 28;

	if (dayDiff == -1) {
		g_day--;
		if (g_day == 0) {
			g_month--;
			if (g_month == 0) {
				g_year--;
				g_month = 12;
			}
			g_day = daysPerMonth[g_month - 1];
		}
	} else if (dayDiff == 1) {
		g_day++;
		if (g_day > daysPerMonth[g_month - 1]) {
			g_day = 1;
			g_month++;
			if (g_month > 12) {
				g_month = 1;
				g_year++;
			}
		}
	}
}

#define SECONDS_PER_DAY (24 * 60 * 60)

void OSystem_PS2::readRtcTime(void) {
	struct CdClock cdClock;
	readRTC(&cdClock);

	g_lastTimeCheck = getMillis();

	if (cdClock.stat) {
		msgPrintf(5000, "Unable to read RTC time, EC: %d\n", cdClock.stat);
		g_day = g_month = 1;
		g_year = 0;
		g_timeSecs = 0;
	} else {
		int gmtOfs = configGetTimezone();
		if (configIsDaylightSavingEnabled())
			gmtOfs += 60;

		int timeSecs = (FROM_BCD(cdClock.hour) * 60 + FROM_BCD(cdClock.minute)) * 60 + FROM_BCD(cdClock.second);
		timeSecs -= 9 * 60 * 60; // minus 9 hours, JST -> GMT conversion
		timeSecs += gmtOfs * 60; // GMT -> timezone the user selected

		g_day = FROM_BCD(cdClock.day);
		g_month = FROM_BCD(cdClock.month);
		g_year = FROM_BCD(cdClock.year);

		if (timeSecs < 0) {
			buildNewDate(-1);
			timeSecs += SECONDS_PER_DAY;
		} else if (timeSecs >= SECONDS_PER_DAY) {
			buildNewDate(+1);
			timeSecs -= SECONDS_PER_DAY;
		}
		g_timeSecs = (uint32)timeSecs;
	}

	sioprintf("Time: %d:%02d:%02d - %d.%d.%4d", g_timeSecs / (60 * 60), (g_timeSecs / 60) % 60, g_timeSecs % 60,
		g_day, g_month, g_year + 2000);
}

extern "C" time_t time(time_t *p) {
	return (time_t)g_timeSecs;
}

extern "C" struct tm *localtime(const time_t *p) {
	uint32 currentSecs = g_timeSecs + (msecCount - g_lastTimeCheck) / 1000;
	if (currentSecs >= SECONDS_PER_DAY) {
		buildNewDate(+1);
		g_lastTimeCheck += SECONDS_PER_DAY * 1000;
		currentSecs = g_timeSecs + (msecCount - g_lastTimeCheck) / 1000;
	}

	static struct tm retStruct;
	memset(&retStruct, 0, sizeof(retStruct));

	retStruct.tm_hour = currentSecs / (60 * 60);
	retStruct.tm_min  = (currentSecs / 60) % 60;
	retStruct.tm_sec  = currentSecs % 60;
	retStruct.tm_year = g_year + 100;
	retStruct.tm_mday = g_day;
	retStruct.tm_mon  = g_month - 1;
	// tm_wday, tm_yday and tm_isdst are zero for now
    return &retStruct;
}