bsnes/sfc/coprocessor/sharprtc/sharprtc.cpp

141 lines
2.4 KiB
C++

#include <sfc/sfc.hpp>
namespace SuperFamicom {
#include "memory.cpp"
#include "time.cpp"
#include "serialization.cpp"
SharpRTC sharprtc;
void SharpRTC::Enter() {
sharprtc.enter();
}
void SharpRTC::enter() {
while(true) {
if(scheduler.sync == Scheduler::SynchronizeMode::All) {
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
}
tick_second();
step(1);
synchronize_cpu();
}
}
void SharpRTC::init() {
}
void SharpRTC::load() {
return;
second = 0;
minute = 0;
hour = 0;
day = 0;
month = 0;
year = 0;
weekday = 0;
}
void SharpRTC::unload() {
}
void SharpRTC::power() {
}
void SharpRTC::reset() {
create(SharpRTC::Enter, 1);
rtc_state = State::Read;
rtc_index = -1;
}
void SharpRTC::sync() {
time_t systime = time(0);
tm* timeinfo = localtime(&systime);
second = min(59, timeinfo->tm_sec);
minute = timeinfo->tm_min;
hour = timeinfo->tm_hour;
day = timeinfo->tm_mday;
month = 1 + timeinfo->tm_mon;
year = 900 + timeinfo->tm_year;
weekday = timeinfo->tm_wday;
}
uint8 SharpRTC::read(unsigned addr) {
addr &= 1;
if(addr == 0) {
if(rtc_state != State::Read) return 0;
if(rtc_index < 0) {
rtc_index++;
return 15;
} else if(rtc_index > 12) {
rtc_index = -1;
return 15;
} else {
return rtc_read(rtc_index++);
}
}
return cpu.regs.mdr;
}
void SharpRTC::write(unsigned addr, uint8 data) {
addr &= 1, data &= 15;
if(addr == 1) {
if(data == 0x0d) {
rtc_state = State::Read;
rtc_index = -1;
return;
}
if(data == 0x0e) {
rtc_state = State::Command;
return;
}
if(data == 0x0f) return; //unknown behavior
if(rtc_state == State::Command) {
if(data == 0) {
rtc_state = State::Write;
rtc_index = 0;
} else if(data == 4) {
rtc_state = State::Ready;
rtc_index = -1;
//reset time
second = 0;
minute = 0;
hour = 0;
day = 0;
month = 0;
year = 0;
weekday = 0;
} else {
//unknown behavior
rtc_state = State::Ready;
}
return;
}
if(rtc_state == State::Write) {
if(rtc_index >= 0 && rtc_index < 12) {
rtc_write(rtc_index++, data);
if(rtc_index == 12) {
//day of week is automatically calculated and written
weekday = calculate_weekday(1000 + year, month, day);
}
}
return;
}
}
}
}