2 FUJITSU FMR-30 Emulator 'eFMR-30'
4 Author : Takeda.Toshiya
26 void RTC::initialize()
28 // load rtc regs image
29 memset(regs, 0, sizeof(regs));
30 regs[POWON] = 0x10; // cleared
32 FILEIO* fio = new FILEIO();
33 if(fio->Fopen(emu->bios_path(_T("RTC.BIN")), FILEIO_READ_BINARY)) {
34 fio->Fread(regs + 8, 32, 1);
40 // regs[POWON] &= 0x1f; // local power on
41 // regs[POWOF] = 0x80; // program power off
42 regs[POWON] = 0x10; // cleared
43 regs[POWOF] = 0x20; // illegal power off
50 emu->get_host_time(&cur_time);
54 register_event_by_clock(this, EVENT_1HZ, CPU_CLOCKS, true, ®ister_id);
55 register_event_by_clock(this, EVENT_32HZ, CPU_CLOCKS >> 5, true, NULL);
61 regs[POFMI] = TO_BCD(cur_time.minute);
62 regs[POFH] = TO_BCD(cur_time.hour);
63 regs[POFD] = TO_BCD(cur_time.day);
65 // save rtc regs image
66 FILEIO* fio = new FILEIO();
67 if(fio->Fopen(emu->bios_path(_T("RTC.BIN")), FILEIO_WRITE_BINARY)) {
68 fio->Fwrite(regs + 8, 32, 1);
74 void RTC::write_io16(uint32 addr, uint32 data)
82 rtdsr &= ~(data & 0xe);
90 register_event(this, EVENT_DONE, 100, false, NULL);
99 uint32 RTC::read_io16(uint32 addr)
110 void RTC::event_callback(int event_id, int err)
112 if(event_id == EVENT_1HZ) {
114 if(cur_time.initialized) {
115 cur_time.increment();
117 emu->get_host_time(&cur_time); // resync
118 cur_time.initialized = true;
120 read_from_cur_time();
125 } else if(event_id == EVENT_32HZ) {
128 } else if(event_id == EVENT_DONE) {
129 int ch = (rtadr >> 1) & 0x3f;
132 } else if(rtadr & 0x80) {
135 regs[ch] = (uint8)rtobr;
137 } else if(ch == POWON) {
138 regs[ch] = (regs[ch] & 0xe0) | (rtobr & 0x1f);
139 if((rtobr & 0xe0) == 0xc0) {
141 regs[ch] = (regs[ch] & 0x1f) | 0xc0;
143 } else if((rtobr & 0xe0) == 0xe0) {
148 } else if(7 <= ch && ch < 32) {
149 regs[ch] = (uint8)rtobr;
165 void RTC::read_from_cur_time()
167 regs[0] = TO_BCD(cur_time.second);
168 regs[1] = TO_BCD(cur_time.minute);
169 regs[2] = TO_BCD(cur_time.hour);
170 regs[3] = cur_time.day_of_week;
171 regs[4] = TO_BCD(cur_time.day);
172 regs[5] = TO_BCD(cur_time.month);
173 regs[6] = TO_BCD(cur_time.year);
176 void RTC::write_to_cur_time()
178 cur_time.second = FROM_BCD(regs[0]);
179 cur_time.minute = FROM_BCD(regs[1]);
180 cur_time.hour = FROM_BCD(regs[2]);
181 // cur_time.day_of_week = regs[3];
182 cur_time.day = FROM_BCD(regs[4]);
183 cur_time.month = FROM_BCD(regs[5]);
184 cur_time.year = FROM_BCD(regs[6]);
185 cur_time.update_year();
186 cur_time.update_day_of_week();
189 cancel_event(this, register_id);
190 register_event_by_clock(this, EVENT_1HZ, CPU_CLOCKS, true, ®ister_id);
193 void RTC::update_checksum()
196 for(int i = 8; i < 32; i++) {
197 sum += regs[i] & 0xf;
198 sum += (regs[i] >> 4) & 0xf;
200 uint8 ckh = (sum >> 6) & 0xf;
201 uint8 ckm = (sum >> 2) & 0xf;
202 uint8 ckl = (sum >> 0) & 3;
204 regs[CKHM] = ckh | (ckm << 4);
205 regs[CKL] = (regs[CKL] & 0xf0) | ckl | 0xc;
208 void RTC::update_intr()
210 d_pic->write_signal(SIG_I8259_CHIP0 | SIG_I8259_IR1, (rtcmr & rtdsr & 0xe) ? 1 : 0, 1);
213 #define STATE_VERSION 1
215 void RTC::save_state(FILEIO* state_fio)
217 state_fio->FputUint32(STATE_VERSION);
218 state_fio->FputInt32(this_device_id);
220 cur_time.save_state((void *)state_fio);
221 state_fio->FputInt32(register_id);
222 state_fio->FputUint16(rtcmr);
223 state_fio->FputUint16(rtdsr);
224 state_fio->FputUint16(rtadr);
225 state_fio->FputUint16(rtobr);
226 state_fio->FputUint16(rtibr);
227 state_fio->Fwrite(regs, sizeof(regs), 1);
230 bool RTC::load_state(FILEIO* state_fio)
232 if(state_fio->FgetUint32() != STATE_VERSION) {
235 if(state_fio->FgetInt32() != this_device_id) {
238 if(!cur_time.load_state((void *)state_fio)) {
241 register_id = state_fio->FgetInt32();
242 rtcmr = state_fio->FgetUint16();
243 rtdsr = state_fio->FgetUint16();
244 rtadr = state_fio->FgetUint16();
245 rtobr = state_fio->FgetUint16();
246 rtibr = state_fio->FgetUint16();
247 state_fio->Fread(regs, sizeof(regs), 1);