1 /* Cygne
2  *
3  * Copyright notice for this file:
4  *  Copyright (C) 2002 Dox dox@space.pl
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20 
21 #include "wswan.h"
22 #include <time.h>
23 
24 static uint64 CurrentTime;
25 static uint32 ClockCycleCounter;
26 static uint8 wsCA15;
27 static uint8 Command, Data;
28 
WSwan_RTCWrite(uint32 A,uint8 V)29 void WSwan_RTCWrite(uint32 A, uint8 V)
30 {
31    switch(A)
32    {
33       case 0xca:
34          if(V==0x15)
35             wsCA15=0;
36          Command = V;
37          break;
38       case 0xcb:
39          Data = V;
40          break;
41    }
42 }
43 
WSwan_RTCRead(uint32 A)44 uint8 WSwan_RTCRead(uint32 A)
45 {
46    time_t long_time;
47    struct tm *newtime;
48 
49    switch(A)
50    {
51       case 0xca:
52          return (Command|0x80);
53       case 0xcb:
54          if(Command != 0x15)
55             return Data | 0x80;
56 
57          long_time = CurrentTime;
58          newtime = gmtime( &long_time );
59 
60          switch(wsCA15)
61          {
62             case 0:
63                wsCA15++;
64                return mBCD(newtime->tm_year-100);
65             case 1:
66                wsCA15++;
67                return mBCD(newtime->tm_mon);
68             case 2:
69                wsCA15++;
70                return mBCD(newtime->tm_mday);
71             case 3:
72                wsCA15++;
73                return mBCD(newtime->tm_wday);
74             case 4:
75                wsCA15++;
76                return mBCD(newtime->tm_hour);
77             case 5:
78                wsCA15++;
79                return mBCD(newtime->tm_min);
80             case 6:
81                wsCA15=0;
82                return mBCD(newtime->tm_sec);
83          }
84          break;
85    }
86 
87    return 0;
88 }
89 
WSwan_RTCReset(void)90 void WSwan_RTCReset(void)
91 {
92    time_t happy_time = time(NULL);
93 
94    CurrentTime = mktime(localtime(&happy_time));
95    ClockCycleCounter = 0;
96    wsCA15 = 0;
97 }
98 
WSwan_RTCClock(uint32 cycles)99 void WSwan_RTCClock(uint32 cycles)
100 {
101    ClockCycleCounter += cycles;
102    while(ClockCycleCounter >= 3072000)
103    {
104       ClockCycleCounter -= 3072000;
105       CurrentTime++;
106    }
107 }
108 
WSwan_RTCStateAction(StateMem * sm,int load,int data_only)109 int WSwan_RTCStateAction(StateMem *sm, int load, int data_only)
110 {
111    SFORMAT StateRegs[] =
112    {
113       SFVAR(CurrentTime),
114       SFVAR(ClockCycleCounter),
115       SFVAR(wsCA15),
116       SFVAR(Command),
117       SFVAR(Data),
118       SFEND
119    };
120 
121    if(!MDFNSS_StateAction(sm, load, data_only, StateRegs, "RTC", false))
122       return(0);
123 
124    return(1);
125 }
126