]> git.sesse.net Git - pistorm/blob - platforms/shared/rtc.c
Fix silly RTC and emulator.c mistakes
[pistorm] / platforms / shared / rtc.c
1 #include <time.h>
2 #include <stdio.h>
3 #include <stdint.h>
4 #include "rtc.h"
5
6 static unsigned char rtc_mystery_reg[3];
7 unsigned char ricoh_memory[0x0F];
8 unsigned char ricoh_alarm[0x0F];
9
10 void put_rtc_byte(uint32_t address_, uint8_t value, uint8_t rtc_type) {
11   uint32_t address = address_ & 0x3F;
12   address >>= 2;
13   if (rtc_type == RTC_TYPE_MSM) {
14     switch(address) {
15       case 0x0D:
16         rtc_mystery_reg[address - 0x0D] = value & (0x01 | 0x08);
17         break;
18       case 0x0E:
19       case 0x0F:
20         rtc_mystery_reg[address - 0x0D] = value;
21         break;
22       default:
23         return;
24     }
25   }
26   else {
27     int rtc_bank = (rtc_mystery_reg[0] & 0x03);
28     if ((rtc_bank & 0x02) && address < 0x0D) {
29       if (rtc_bank & 0x01) {
30         // Low nibble of value -> high nibble in RTC memory
31         ricoh_memory[address] &= 0x0F;
32         ricoh_memory[address] |= ((value & 0x0F) << 4);
33       }
34       else {
35         // Low nibble of value -> low nibble in RTC memory
36         ricoh_memory[address] &= 0xF0;
37         ricoh_memory[address] |= (value & 0x0F);
38       }
39       return;
40     }
41     else if ((rtc_bank & 0x01) && address < 0x0D) {
42       // RTC alarm stuff, no idea what this is supposed to be for.
43       switch(address) {
44         case 0x00:
45         case 0x01:
46         case 0x09:
47         case 0x0C:
48           ricoh_alarm[address] = 0;
49           break;
50         case 0x03:
51         case 0x06:
52           ricoh_alarm[address] &= (value & (0x08 ^ 0xFF));
53           break;
54         case 0x05:
55         case 0x08:
56         case 0x0B:
57           ricoh_alarm[address] = (value & (0x0C ^ 0xFF));
58           break;
59         case 0x0A:
60           ricoh_alarm[address] = (value & (0x0E ^ 0xFF));
61           break;
62         default:
63           ricoh_alarm[address] = value;
64           break;
65       }
66       //printf("Write to Ricoh alarm @%.2X: %.2X -> %.2X\n", address, value, ricoh_alarm[address]);
67       return;
68     }
69     else if (address >= 0x0D) {
70       rtc_mystery_reg[address - 0x0D] = value;
71       return;
72     }
73   }
74 }
75
76 uint8_t get_rtc_byte(uint32_t address_, uint8_t rtc_type) {
77   uint32_t address = address_ & 0x3F;
78   address >>= 2;
79   time_t t;
80   time(&t);
81   struct tm *rtc_time = localtime(&t);
82
83   if (rtc_type == RTC_TYPE_RICOH) {
84     int rtc_bank = (rtc_mystery_reg[0] & 0x03);
85     if ((rtc_bank & 0x02) && address < 0x0D) {
86       // Get low/high nibble from memory (bank 2/3)
87       return ((ricoh_memory[address] >> (rtc_bank & 0x01) ? 4 : 0) & 0x0F);
88     }
89     else if ((rtc_bank & 0x01) && address < 0x0D) {
90       // Get byte from alarm
91       return ricoh_alarm[address];
92     }
93   }
94
95   switch (address) {
96     case 0x00: // Seconds low?
97       return rtc_time->tm_sec % 10;
98     case 0x01: // Seconds high?
99       return rtc_time->tm_sec / 10;
100     case 0x02: // Minutes low?
101       return rtc_time->tm_min % 10;
102     case 0x03: // Minutes high?
103       return rtc_time->tm_min / 10;
104     case 0x04: // Hours low?
105       return rtc_time->tm_hour % 10;
106     case 0x05: // Hours high?
107       if (rtc_type == RTC_TYPE_MSM) {
108         if (rtc_mystery_reg[2] & 4) {
109           return (((rtc_time->tm_hour % 12) / 10) | (rtc_time->tm_hour >= 12) ? 0x04 : 0x00);
110         }
111         else
112           return rtc_time->tm_hour / 10;
113       }
114       else {
115         if (ricoh_alarm[10] & 0x01) {
116           return rtc_time->tm_hour / 10;
117         }
118         else {
119           return (((rtc_time->tm_hour % 12) / 10) | (rtc_time->tm_hour >= 12) ? 0x02 : 0x00);
120         }
121         break;
122       }
123     case 0x06: // Day low?
124       if (rtc_type == RTC_TYPE_MSM)
125         return rtc_time->tm_mday % 10;
126       else
127         return rtc_time->tm_wday;
128     case 0x07: // Day high?
129       if (rtc_type == RTC_TYPE_MSM)
130         return rtc_time->tm_mday / 10;
131       else
132         return rtc_time->tm_mday % 10;
133     case 0x08: // Month low?
134       if (rtc_type == RTC_TYPE_MSM)
135         return (rtc_time->tm_mon + 1) % 10;
136       else
137         return rtc_time->tm_mday / 10;
138     case 0x09: // Month high?
139       if (rtc_type == RTC_TYPE_MSM)
140         return (rtc_time->tm_mon + 1) / 10;
141       else
142         return (rtc_time->tm_mon + 1) % 10;
143     case 0x0A: // Year low?
144       if (rtc_type == RTC_TYPE_MSM)
145         return rtc_time->tm_year % 10;
146       else
147         return (rtc_time->tm_mon + 1) / 10;
148     case 0x0B: // Year high?
149       if (rtc_type == RTC_TYPE_MSM)
150         return rtc_time->tm_year / 10;
151       else
152         return rtc_time->tm_year % 10;
153     case 0x0C: // Day of week?
154       if (rtc_type == RTC_TYPE_MSM)
155         return rtc_time->tm_wday;
156       else
157         return rtc_time->tm_year / 10;
158     case 0x0D: // Mystery register D-F?
159     case 0x0E:
160     case 0x0F:
161       if (rtc_type == RTC_TYPE_MSM) {
162         return rtc_mystery_reg[address - 0x0D];
163       }
164       else {
165         if (address == 0x0D) return rtc_mystery_reg[address - 0x0D];
166         return 0;
167       }
168     default:
169       break;
170   }
171
172   return 0x00;
173 }