2 Skelton for retropc emulator
\r
4 Author : Takeda.Toshiya
\r
10 #include "upd4991a.h"
\r
11 #include "../fileio.h"
\r
13 void UPD4991A::initialize()
\r
16 memset(regs, 0, sizeof(regs));
\r
17 ctrl1 = ctrl2 = mode = 0;
\r
19 emu->get_host_time(&cur_time);
\r
20 read_from_cur_time();
\r
23 register_event(this, 0, 1000000.0, true, ®ister_id);
\r
26 void UPD4991A::write_io8(uint32 addr, uint32 data)
\r
30 if(mode == 0 || mode == 3) {
\r
31 if(regs[0][addr] != data) {
\r
32 regs[0][addr] = data;
\r
33 write_to_cur_time();
\r
35 } else if(mode == 1) {
\r
36 regs[1][addr] = data;
\r
37 } else if(mode == 2) {
\r
38 uint8 tmp = regs[2][addr] ^ data;
\r
39 regs[2][addr] = data;
\r
40 // am/pm is changed ?
\r
41 if(addr == 12 && (tmp & 8)) {
\r
42 read_from_cur_time();
\r
46 } else if(addr == 13) {
\r
48 } else if(addr == 14) {
\r
50 } else if(addr == 15) {
\r
55 uint32 UPD4991A::read_io8(uint32 addr)
\r
59 if(mode == 0 || mode == 3) {
\r
60 return regs[0][addr];
\r
61 } else if(mode == 1 || mode == 2) {
\r
62 return regs[mode][addr];
\r
64 } else if(addr == 14) {
\r
70 void UPD4991A::event_callback(int event_id, int err)
\r
73 if(cur_time.initialized) {
\r
74 cur_time.increment();
\r
76 emu->get_host_time(&cur_time); // resync
\r
77 cur_time.initialized = true;
\r
81 read_from_cur_time();
\r
85 #define MODE_12H !(regs[2][12] & 8)
\r
87 void UPD4991A::read_from_cur_time()
\r
89 int hour = MODE_12H ? (cur_time.hour % 12) : cur_time.hour;
\r
90 int ampm = (MODE_12H && cur_time.hour >= 12) ? 4 : 0;
\r
92 regs[0][ 0] = TO_BCD_LO(cur_time.second);
\r
93 regs[0][ 1] = TO_BCD_HI(cur_time.second);
\r
94 regs[0][ 2] = TO_BCD_LO(cur_time.minute);
\r
95 regs[0][ 3] = TO_BCD_HI(cur_time.minute);
\r
96 regs[0][ 4] = TO_BCD_LO(hour);
\r
97 regs[0][ 5] = TO_BCD_HI(hour) | ampm;
\r
98 regs[0][ 6] = cur_time.day_of_week;
\r
99 regs[0][ 7] = TO_BCD_LO(cur_time.day);
\r
100 regs[0][ 8] = TO_BCD_HI(cur_time.day);
\r
101 regs[0][ 9] = TO_BCD_LO(cur_time.month);
\r
102 regs[0][10] = TO_BCD_HI(cur_time.month);
\r
103 regs[0][11] = TO_BCD_LO(cur_time.year);
\r
104 regs[0][12] = TO_BCD_HI(cur_time.year);
\r
106 // TODO: check alarm
\r
109 void UPD4991A::write_to_cur_time()
\r
111 cur_time.second = regs[0][0] + (regs[0][1] & 7) * 10;
\r
112 cur_time.minute = regs[0][2] + (regs[0][3] & 7) * 10;
\r
114 cur_time.hour = regs[0][4] + (regs[0][5] & 1) * 10 + (regs[0][5] & 4 ? 12 : 0);
\r
116 cur_time.hour = regs[0][4] + (regs[0][5] & 3) * 10;
\r
118 // cur_time.day_of_week = regs[0][6];
\r
119 cur_time.day = regs[0][7] + (regs[0][8] & 3) * 10;
\r
120 cur_time.month = regs[0][9] + (regs[0][10] & 1) * 10;
\r
121 cur_time.year = regs[0][11] + regs[0][12] * 10;
\r
122 cur_time.update_year();
\r
123 cur_time.update_day_of_week();
\r
126 cancel_event(this, register_id);
\r
127 register_event(this, 0, 1000000.0, true, ®ister_id);
\r
131 #define STATE_VERSION 1
\r
133 void UPD4991A::save_state(FILEIO* state_fio)
\r
135 state_fio->FputUint32(STATE_VERSION);
\r
136 state_fio->FputInt32(this_device_id);
\r
138 cur_time.save_state((void *)state_fio);
\r
139 state_fio->FputInt32(register_id);
\r
140 state_fio->Fwrite(regs, sizeof(regs), 1);
\r
141 state_fio->FputUint8(ctrl1);
\r
142 state_fio->FputUint8(ctrl2);
\r
143 state_fio->FputUint8(mode);
\r
146 bool UPD4991A::load_state(FILEIO* state_fio)
\r
148 if(state_fio->FgetUint32() != STATE_VERSION) {
\r
151 if(state_fio->FgetInt32() != this_device_id) {
\r
154 if(!cur_time.load_state((void *)state_fio)) {
\r
157 register_id = state_fio->FgetInt32();
\r
158 state_fio->Fread(regs, sizeof(regs), 1);
\r
159 ctrl1 = state_fio->FgetUint8();
\r
160 ctrl2 = state_fio->FgetUint8();
\r
161 mode = state_fio->FgetUint8();
\r