2 Skelton for retropc emulator
4 Author : Takeda.Toshiya
15 DLL_PREFIX_I struct cur_time_s cur_time;
18 void RP5C01::initialize()
21 __HAS_RP5C15 = osd->check_feature(_T("HAS_RP5C15"));
22 if(__HAS_RP5C15) set_device_name(_T("RP-5C15 RTC"));
26 memset(ram, 0, sizeof(ram));
29 // FIXME: we need to consider the multiple chips case
30 FILEIO* fio = new FILEIO();
31 if(fio->Fopen(create_local_path(_T("RP5C01.BIN")), FILEIO_READ_BINARY)) {
32 fio->Fread(ram, sizeof(ram), 1);
40 memset(regs, 0, sizeof(regs));
44 alarm = pulse_1hz = pulse_16hz = false;
47 get_host_time(&cur_time);
51 register_event(this, EVENT_1SEC, 1000000, true, ®ister_id);
52 register_event(this, EVENT_16HZ, 1000000 / 32, true, NULL);
55 void RP5C01::release()
61 // FIXME: we need to consider the multiple chips case
62 FILEIO* fio = new FILEIO();
63 if(fio->Fopen(create_local_path(_T("RP5C01.BIN")), FILEIO_WRITE_BINARY)) {
64 fio->Fwrite(ram, sizeof(ram), 1);
73 void RP5C01::write_io8(uint32_t addr, uint32_t data)
84 // switch(regs[0x0d] & 3) {
86 switch(regs[0x0d] & nmask) {
89 if(time[addr] != data) {
96 if(__HAS_RP5C15) break;
97 if(ram[addr] != data) {
103 if(__HAS_RP5C15) break;
104 if(ram[addr + 13] != data) {
105 ram[addr + 13] = data;
113 uint8_t tmp = regs[addr] ^ data;
119 read_from_cur_time();
121 } else if(addr == 0x0f) {
129 // switch(regs[0x0d] & 3) {
131 switch(regs[0x0d] & nmask) {
143 if(__HAS_RP5C15) break;
158 uint32_t RP5C01::read_io8(uint32_t addr)
169 // switch(regs[0x0d] & 3) {
171 switch(regs[0x0d] & nmask) {
177 if(__HAS_RP5C15) return regs[addr];
180 if(__HAS_RP5C15) return regs[addr];
181 return ram[addr + 13];
186 for(int i = 0; i < 3; i++) {
187 if(LEAP_YEAR(cur_time.year - i)) {
196 void RP5C01::event_callback(int event_id, int err)
198 if(event_id == EVENT_1SEC) {
199 if(cur_time.initialized) {
200 cur_time.increment();
202 get_host_time(&cur_time); // resync
203 cur_time.initialized = true;
206 read_from_cur_time();
211 } else if(event_id == EVENT_16HZ) {
214 if(++count_16hz == 16) {
215 pulse_1hz = !pulse_1hz;
216 if(!(regs[0x0f] & 8)) {
222 pulse_16hz = !pulse_16hz;
223 if(!(regs[0x0f] & 4)) {
234 void RP5C01::update_pulse()
241 if(!(regs[0x0f] & 8)) {
244 if(!(regs[0x0f] & 4)) {
247 write_signals(&outputs_pulse, pulse ? 0 : 0xffffffff);
250 #define MODE_12H !(regs[0x0a] & 1)
252 void RP5C01::read_from_cur_time()
254 int hour = MODE_12H ? (cur_time.hour % 12) : cur_time.hour;
255 int ampm = (MODE_12H && cur_time.hour >= 12) ? 2 : 0;
257 time[ 0] = TO_BCD_LO(cur_time.second);
258 time[ 1] = TO_BCD_HI(cur_time.second);
259 time[ 2] = TO_BCD_LO(cur_time.minute);
260 time[ 3] = TO_BCD_HI(cur_time.minute);
261 time[ 4] = TO_BCD_LO(hour);
262 time[ 5] = TO_BCD_HI(hour) | ampm;
263 time[ 6] = cur_time.day_of_week;
264 time[ 7] = TO_BCD_LO(cur_time.day);
265 time[ 8] = TO_BCD_HI(cur_time.day);
266 time[ 9] = TO_BCD_LO(cur_time.month);
267 time[10] = TO_BCD_HI(cur_time.month);
268 time[11] = TO_BCD_LO(cur_time.year);
269 time[12] = TO_BCD_HI(cur_time.year);
272 static const uint8_t mask[9] = {0, 0, 0x0f, 0x07, 0x0f, 0x03, 0x07, 0x0f, 0x03};
275 for(int i = 3; i < 9; i++) {
276 if((time[i] & mask[i]) != (regs[i] & mask[i])) {
286 void RP5C01::write_to_cur_time()
288 cur_time.second = time[0] + (time[1] & 7) * 10;
289 cur_time.minute = time[2] + (time[3] & 7) * 10;
291 cur_time.hour = time[4] + (time[5] & 1) * 10 + (time[5] & 2 ? 12 : 0);
293 cur_time.hour = time[4] + (time[5] & 3) * 10;
295 // cur_time.day_of_week = time[6];
296 cur_time.day = time[7] + (time[8] & 3) * 10;
297 cur_time.month = time[9] + (time[10] & 1) * 10;
298 cur_time.year = time[11] + time[12] * 10;
299 cur_time.update_year();
300 cur_time.update_day_of_week();
303 cancel_event(this, register_id);
304 register_event(this, EVENT_1SEC, 1000000, true, ®ister_id);
307 #define STATE_VERSION 1
309 void RP5C01::save_state(FILEIO* state_fio)
311 state_fio->FputUint32(STATE_VERSION);
312 state_fio->FputInt32(this_device_id);
314 cur_time.save_state((void *)state_fio);
315 state_fio->FputInt32(register_id);
316 state_fio->Fwrite(regs, sizeof(regs), 1);
317 state_fio->Fwrite(time, sizeof(time), 1);
320 state_fio->Fwrite(ram, sizeof(ram), 1);
321 state_fio->FputBool(modified);
324 state_fio->FputBool(alarm);
325 state_fio->FputBool(pulse_1hz);
326 state_fio->FputBool(pulse_16hz);
327 state_fio->FputInt32(count_16hz);
330 bool RP5C01::load_state(FILEIO* state_fio)
332 if(state_fio->FgetUint32() != STATE_VERSION) {
335 if(state_fio->FgetInt32() != this_device_id) {
338 if(!cur_time.load_state((void *)state_fio)) {
341 register_id = state_fio->FgetInt32();
342 state_fio->Fread(regs, sizeof(regs), 1);
343 state_fio->Fread(time, sizeof(time), 1);
346 state_fio->Fread(ram, sizeof(ram), 1);
347 modified = state_fio->FgetBool();
350 alarm = state_fio->FgetBool();
351 pulse_1hz = state_fio->FgetBool();
352 pulse_16hz = state_fio->FgetBool();
353 count_16hz = state_fio->FgetInt32();