diff --git a/src/RTC.cpp b/src/RTC.cpp index c0ab99db..8d3fb401 100644 --- a/src/RTC.cpp +++ b/src/RTC.cpp @@ -20,7 +20,6 @@ #define _POSIX_THREAD_SAFE_FUNCTIONS #include -#include #include "NDS.h" #include "RTC.h" #include "Platform.h" @@ -57,6 +56,13 @@ void WriteDateTime(int num, u8 val); bool Init() { + State.MinuteCount = 0; + ResetState(); + + // indicate the power was off + // this will be changed if a previously saved RTC state is loaded + State.StatusReg1 = 0x80; + return true; } @@ -75,13 +81,6 @@ void Reset() CurCmd = 0; - State.MinuteCount = 0; - ResetState(); - - // indicate the power was off - // this will be changed if a previously saved RTC state is loaded - State.StatusReg1 = 0x80; - ClockCount = 0; ScheduleTimer(true); } @@ -152,6 +151,38 @@ void SetState(StateData& state) WriteDateTime(i+1, State.DateTime[i]); } +void GetDateTime(int& year, int& month, int& day, int& hour, int& minute, int& second) +{ + int val; + + val = State.DateTime[0]; + year = (val & 0xF) + ((val >> 4) * 10); + year += 2000; + + val = State.DateTime[1] & 0x3F; + month = (val & 0xF) + ((val >> 4) * 10); + + val = State.DateTime[2] & 0x3F; + day = (val & 0xF) + ((val >> 4) * 10); + + val = State.DateTime[4] & 0x3F; + hour = (val & 0xF) + ((val >> 4) * 10); + + if (!(State.StatusReg1 & (1<<1))) + { + // 12-hour mode + + if (State.DateTime[4] & 0x40) + hour += 12; + } + + val = State.DateTime[5] & 0x7F; + minute = (val & 0xF) + ((val >> 4) * 10); + + val = State.DateTime[6] & 0x7F; + second = (val & 0xF) + ((val >> 4) * 10); +} + void SetDateTime(int year, int month, int day, int hour, int minute, int second) { int monthdays[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; diff --git a/src/RTC.h b/src/RTC.h index f34ac7e2..8c92ab63 100644 --- a/src/RTC.h +++ b/src/RTC.h @@ -50,6 +50,7 @@ void DoSavestate(Savestate* file); void GetState(StateData& state); void SetState(StateData& state); +void GetDateTime(int& year, int& month, int& day, int& hour, int& minute, int& second); void SetDateTime(int year, int month, int day, int hour, int minute, int second); void ResetState(); diff --git a/src/frontend/qt_sdl/Config.cpp b/src/frontend/qt_sdl/Config.cpp index da08c285..ba91068d 100644 --- a/src/frontend/qt_sdl/Config.cpp +++ b/src/frontend/qt_sdl/Config.cpp @@ -140,6 +140,11 @@ int MouseHideSeconds; bool PauseLostFocus; +int RTCMode; +std::string RTCLastTime; +std::string RTCLastHostTime; +std::string RTCNewTime; + bool DSBatteryLevelOkay; int DSiBatteryLevel; bool DSiBatteryCharging; @@ -339,6 +344,11 @@ ConfigEntry ConfigFile[] = {"MouseHideSeconds", 0, &MouseHideSeconds, 5, false}, {"PauseLostFocus", 1, &PauseLostFocus, false, false}, + {"RTCMode", 0, &RTCMode, 0, true}, + {"RTCLastTime", 2, &RTCLastTime, (std::string)"", true}, + {"RTCLastHostTime", 2, &RTCLastHostTime, (std::string)"", true}, + {"RTCNewTime", 2, &RTCNewTime, (std::string)"", true}, + {"DSBatteryLevelOkay", 1, &DSBatteryLevelOkay, true, true}, {"DSiBatteryLevel", 0, &DSiBatteryLevel, 0xF, true}, {"DSiBatteryCharging", 1, &DSiBatteryCharging, true, true}, diff --git a/src/frontend/qt_sdl/Config.h b/src/frontend/qt_sdl/Config.h index b1d9532e..daa69c8b 100644 --- a/src/frontend/qt_sdl/Config.h +++ b/src/frontend/qt_sdl/Config.h @@ -185,6 +185,11 @@ extern bool MouseHide; extern int MouseHideSeconds; extern bool PauseLostFocus; +extern int RTCMode; +extern std::string RTCLastTime; +extern std::string RTCLastHostTime; +extern std::string RTCNewTime; + extern bool DSBatteryLevelOkay; extern int DSiBatteryLevel; extern bool DSiBatteryCharging; diff --git a/src/frontend/qt_sdl/DateTimeDialog.cpp b/src/frontend/qt_sdl/DateTimeDialog.cpp index 9520a9e0..49ef5545 100644 --- a/src/frontend/qt_sdl/DateTimeDialog.cpp +++ b/src/frontend/qt_sdl/DateTimeDialog.cpp @@ -32,7 +32,46 @@ DateTimeDialog::DateTimeDialog(QWidget* parent) : QDialog(parent), ui(new Ui::Da ui->setupUi(this); setAttribute(Qt::WA_DeleteOnClose); - // + grpTimeMode = new QButtonGroup(this); + grpTimeMode->addButton(ui->rbSystemTime, 0); + grpTimeMode->addButton(ui->rbCustomTime, 1); + connect(grpTimeMode, SIGNAL(buttonClicked(int)), this, SLOT(onChangeTimeMode(int))); + grpTimeMode->button(Config::RTCMode)->setChecked(true); + + QDateTime now = QDateTime::currentDateTime(); + customTime = now; + + ui->chkChangeTime->setChecked(false); + + if (Config::RTCNewTime != "") + { + QDateTime newtime = QDateTime::fromString(QString::fromStdString(Config::RTCNewTime), Qt::ISODate); + + if (newtime.isValid()) + { + ui->chkChangeTime->setChecked(true); + ui->txtNewCustomTime->setDateTime(newtime); + } + } + + if (Config::RTCLastTime != "" && Config::RTCLastHostTime != "") + { + QDateTime lasttime = QDateTime::fromString(QString::fromStdString(Config::RTCLastTime), Qt::ISODate); + QDateTime lasthost = QDateTime::fromString(QString::fromStdString(Config::RTCLastHostTime), Qt::ISODate); + + if (lasttime.isValid() && lasthost.isValid()) + { + qint64 offset = lasthost.secsTo(now); + customTime = lasttime.addSecs(offset); + } + } + + ui->lblCustomTime->setText(customTime.toString(ui->txtNewCustomTime->displayFormat())); + startTimer(1000); + + bool iscustom = (Config::RTCMode == 1); + ui->chkChangeTime->setEnabled(iscustom); + ui->txtNewCustomTime->setEnabled(iscustom && ui->chkChangeTime->isChecked()); } DateTimeDialog::~DateTimeDialog() @@ -40,12 +79,48 @@ DateTimeDialog::~DateTimeDialog() delete ui; } +void DateTimeDialog::timerEvent(QTimerEvent* event) +{ + customTime = customTime.addSecs(1); + ui->lblCustomTime->setText(customTime.toString(ui->txtNewCustomTime->displayFormat())); +} + void DateTimeDialog::done(int r) { + if (r == QDialog::Accepted) + { + Config::RTCMode = grpTimeMode->checkedId(); + + if (ui->chkChangeTime->isChecked()) + Config::RTCNewTime = ui->txtNewCustomTime->dateTime().toString(Qt::ISODate).toStdString(); + else + Config::RTCNewTime = ""; + + Config::Save(); + } + QDialog::done(r); closeDlg(); } -// +void DateTimeDialog::on_chkChangeTime_clicked(bool checked) +{ + bool iscustom = (grpTimeMode->checkedId() == 1); + + ui->txtNewCustomTime->setEnabled(iscustom && checked); +} + +void DateTimeDialog::onChangeTimeMode(int mode) +{ + bool iscustom = (mode == 1); + + ui->chkChangeTime->setEnabled(iscustom); + ui->txtNewCustomTime->setEnabled(iscustom && ui->chkChangeTime->isChecked()); +} + +void setCustomTimeLabel() +{ + // +} diff --git a/src/frontend/qt_sdl/DateTimeDialog.h b/src/frontend/qt_sdl/DateTimeDialog.h index c2c0dc7e..3e48f380 100644 --- a/src/frontend/qt_sdl/DateTimeDialog.h +++ b/src/frontend/qt_sdl/DateTimeDialog.h @@ -20,6 +20,8 @@ #define DATETIMEDIALOG_H #include +#include +#include namespace Ui {class DateTimeDialog; } class DateTimeDialog; @@ -50,15 +52,21 @@ public: currentDlg = nullptr; } +protected: + void timerEvent(QTimerEvent* event) override; + private slots: void done(int r); - // slots here + void on_chkChangeTime_clicked(bool checked); + void onChangeTimeMode(int mode); private: Ui::DateTimeDialog* ui; - // + QButtonGroup* grpTimeMode; + + QDateTime customTime; }; #endif // DATETIMEDIALOG_H diff --git a/src/frontend/qt_sdl/DateTimeDialog.ui b/src/frontend/qt_sdl/DateTimeDialog.ui index fb400553..f4b6eb8b 100644 --- a/src/frontend/qt_sdl/DateTimeDialog.ui +++ b/src/frontend/qt_sdl/DateTimeDialog.ui @@ -65,7 +65,7 @@ - + Change @@ -86,7 +86,7 @@ - + 0 @@ -117,6 +117,9 @@ 1 + + dd/MM/yyyy HH:mm:ss + true diff --git a/src/frontend/qt_sdl/ROMManager.cpp b/src/frontend/qt_sdl/ROMManager.cpp index cc65dfd8..e7c55504 100644 --- a/src/frontend/qt_sdl/ROMManager.cpp +++ b/src/frontend/qt_sdl/ROMManager.cpp @@ -28,6 +28,8 @@ #include #include +#include + #include #ifdef ARCHIVE_SUPPORT_ENABLED #include "ArchiveUtil.h" @@ -39,6 +41,7 @@ #include "NDS.h" #include "DSi.h" #include "SPI.h" +#include "RTC.h" #include "DSi_I2C.h" #include "FreeBIOS.h" @@ -589,6 +592,54 @@ void SetBatteryLevels() } } +void SetDateTime() +{ + QDateTime hosttime = QDateTime::currentDateTime(); + QDateTime time; + + if (Config::RTCMode == 0) + { + // use current system time + + time = hosttime; + } + else + { + // use custom time + + if (Config::RTCNewTime != "") + { + // assign a new custom time + + time = QDateTime::fromString(QString::fromStdString(Config::RTCNewTime), Qt::ISODate); + if (!time.isValid()) + return; + } + else if (Config::RTCLastTime != "" && Config::RTCLastHostTime != "") + { + // deduce the custom time based on the last saved times + + QDateTime lasttime = QDateTime::fromString(QString::fromStdString(Config::RTCLastTime), Qt::ISODate); + QDateTime lasthost = QDateTime::fromString(QString::fromStdString(Config::RTCLastHostTime), Qt::ISODate); + + if (lasttime.isValid() && lasthost.isValid()) + { + qint64 offset = lasthost.secsTo(hosttime); + time = lasttime.addSecs(offset); + } + else + return; + } + } + + RTC::SetDateTime(time.date().year(), time.date().month(), time.date().day(), + time.time().hour(), time.time().minute(), time.time().second()); + + Config::RTCLastTime = time.toString(Qt::ISODate).toStdString(); + Config::RTCLastHostTime = hosttime.toString(Qt::ISODate).toStdString(); + Config::RTCNewTime = ""; +} + void Reset() { NDS::SetConsoleType(Config::ConsoleType); @@ -602,6 +653,7 @@ void Reset() } NDS::Reset(); SetBatteryLevels(); + SetDateTime(); if ((CartType != -1) && NDSSave) { @@ -678,6 +730,7 @@ bool LoadBIOS() NDS::Reset(); SetBatteryLevels(); + SetDateTime(); return true; } @@ -1204,6 +1257,7 @@ bool LoadROM(QStringList filepath, bool reset) NDS::Reset(); SetBatteryLevels(); + SetDateTime(); } u32 savelen = 0; diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 33808bc6..7088f303 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -91,6 +91,7 @@ #include "LocalMP.h" #include "Config.h" #include "DSi_I2C.h" +#include "RTC.h" #include "Savestate.h" @@ -314,6 +315,8 @@ void EmuThread::deinitOpenGL() void EmuThread::run() { u32 mainScreenPos[3]; + Platform::FileHandle* file; + bool hasrun = false; NDS::Init(); @@ -353,6 +356,15 @@ void EmuThread::run() u32 winUpdateCount = 0, winUpdateFreq = 1; u8 dsiVolumeLevel = 0x1F; + file = Platform::OpenLocalFile("rtc.bin", Platform::FileMode::Read); + if (file) + { + RTC::StateData state; + Platform::FileRead(&state, sizeof(state), 1, file); + Platform::CloseFile(file); + RTC::SetState(state); + } + char melontitle[100]; while (EmuRunning != emuStatus_Exit) @@ -429,6 +441,8 @@ void EmuThread::run() if (EmuRunning == emuStatus_Running || EmuRunning == emuStatus_FrameStep) { + hasrun = true; + EmuStatus = emuStatus_Running; if (EmuRunning == emuStatus_FrameStep) EmuRunning = emuStatus_Paused; @@ -651,6 +665,26 @@ void EmuThread::run() } } + file = Platform::OpenLocalFile("rtc.bin", Platform::FileMode::Write); + if (file) + { + RTC::StateData state; + RTC::GetState(state); + Platform::FileWrite(&state, sizeof(state), 1, file); + Platform::CloseFile(file); + } + if (hasrun) + { + int y, m, d, h, i, s; + RTC::GetDateTime(y, m, d, h, i, s); + + QDateTime hosttime = QDateTime::currentDateTime(); + QDateTime time = QDateTime(QDate(y, m, d), QTime(h, i, s)); + + Config::RTCLastTime = time.toString(Qt::ISODate).toStdString(); + Config::RTCLastHostTime = hosttime.toString(Qt::ISODate).toStdString(); + } + EmuStatus = emuStatus_Exit; GPU::DeInitRenderer(); @@ -3305,6 +3339,7 @@ int main(int argc, char** argv) SANITIZE(Config::ScreenSizing, 0, (int)Frontend::screenSizing_MAX); SANITIZE(Config::ScreenAspectTop, 0, AspectRatiosNum); SANITIZE(Config::ScreenAspectBot, 0, AspectRatiosNum); + SANITIZE(Config::RTCMode, 0, 1); #undef SANITIZE AudioInOut::Init();