From 9a450f5f28969cfa601ceda5f225cc1f03243374 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Mon, 30 Oct 2023 18:37:49 +0100 Subject: RTC revamp (#1867) * get this started * implement DSi RTC commands * set up RTC clock timer. lay down basic idea of a clock. * make the date/time registers writable * move RTC state to its own structure, to make it easier to deal with * more RTC work lay base for date/time dialog * get the bulk of the RTC functionality going * much simpler design for RTC stuff * aha, that is what it is * start working on the RTC IRQ * implement all types of RTC IRQ * start refining sleep mode. code still kinda sucks. * implement keypad IRQ * refine it some more * shut the fuck uuuuuupppppppppppppp --- src/frontend/qt_sdl/CMakeLists.txt | 1 + src/frontend/qt_sdl/Config.cpp | 8 ++ src/frontend/qt_sdl/Config.h | 6 +- src/frontend/qt_sdl/DateTimeDialog.cpp | 91 ++++++++++++++++++++ src/frontend/qt_sdl/DateTimeDialog.h | 70 ++++++++++++++++ src/frontend/qt_sdl/DateTimeDialog.ui | 148 +++++++++++++++++++++++++++++++++ src/frontend/qt_sdl/Platform.cpp | 10 +++ src/frontend/qt_sdl/ROMManager.cpp | 15 ++++ src/frontend/qt_sdl/main.cpp | 42 ++++++++-- src/frontend/qt_sdl/main.h | 6 +- 10 files changed, 388 insertions(+), 9 deletions(-) create mode 100644 src/frontend/qt_sdl/DateTimeDialog.cpp create mode 100644 src/frontend/qt_sdl/DateTimeDialog.h create mode 100644 src/frontend/qt_sdl/DateTimeDialog.ui (limited to 'src/frontend/qt_sdl') diff --git a/src/frontend/qt_sdl/CMakeLists.txt b/src/frontend/qt_sdl/CMakeLists.txt index 3923f37..cdc96dd 100644 --- a/src/frontend/qt_sdl/CMakeLists.txt +++ b/src/frontend/qt_sdl/CMakeLists.txt @@ -7,6 +7,7 @@ set(SOURCES_QT_SDL main_shaders.h CheatsDialog.cpp Config.cpp + DateTimeDialog.cpp EmuSettingsDialog.cpp PowerManagement/PowerManagementDialog.cpp PowerManagement/resources/battery.qrc diff --git a/src/frontend/qt_sdl/Config.cpp b/src/frontend/qt_sdl/Config.cpp index da08c28..c28f63a 100644 --- a/src/frontend/qt_sdl/Config.cpp +++ b/src/frontend/qt_sdl/Config.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include "Platform.h" #include "Config.h" @@ -140,6 +141,8 @@ int MouseHideSeconds; bool PauseLostFocus; +int64_t RTCOffset; + bool DSBatteryLevelOkay; int DSiBatteryLevel; bool DSiBatteryCharging; @@ -339,6 +342,8 @@ ConfigEntry ConfigFile[] = {"MouseHideSeconds", 0, &MouseHideSeconds, 5, false}, {"PauseLostFocus", 1, &PauseLostFocus, false, false}, + {"RTCOffset", 3, &RTCOffset, (int64_t)0, true}, + {"DSBatteryLevelOkay", 1, &DSBatteryLevelOkay, true, true}, {"DSiBatteryLevel", 0, &DSiBatteryLevel, 0xF, true}, {"DSiBatteryCharging", 1, &DSiBatteryCharging, true, true}, @@ -406,6 +411,7 @@ void LoadFile(int inst) case 0: *(int*)entry->Value = strtol(entryval, NULL, 10); break; case 1: *(bool*)entry->Value = strtol(entryval, NULL, 10) ? true:false; break; case 2: *(std::string*)entry->Value = entryval; break; + case 3: *(int64_t*)entry->Value = strtoll(entryval, NULL, 10); break; } break; @@ -426,6 +432,7 @@ void Load() case 0: *(int*)entry->Value = std::get(entry->Default); break; case 1: *(bool*)entry->Value = std::get(entry->Default); break; case 2: *(std::string*)entry->Value = std::get(entry->Default); break; + case 3: *(int64_t*)entry->Value = std::get(entry->Default); break; } } @@ -462,6 +469,7 @@ void Save() case 0: Platform::FileWriteFormatted(f, "%s=%d\r\n", entry->Name, *(int*)entry->Value); break; case 1: Platform::FileWriteFormatted(f, "%s=%d\r\n", entry->Name, *(bool*)entry->Value ? 1:0); break; case 2: Platform::FileWriteFormatted(f, "%s=%s\r\n", entry->Name, (*(std::string*)entry->Value).c_str()); break; + case 3: Platform::FileWriteFormatted(f, "%s=%" PRId64 "\r\n", entry->Name, *(int64_t*)entry->Value); break; } } diff --git a/src/frontend/qt_sdl/Config.h b/src/frontend/qt_sdl/Config.h index b1d9532..fba9bfb 100644 --- a/src/frontend/qt_sdl/Config.h +++ b/src/frontend/qt_sdl/Config.h @@ -57,9 +57,9 @@ namespace Config struct ConfigEntry { char Name[32]; - int Type; // 0=int 1=bool 2=string + int Type; // 0=int 1=bool 2=string 3=64bit int void* Value; // pointer to the value variable - std::variant Default; + std::variant Default; bool InstanceUnique; // whether the setting can exist individually for each instance in multiplayer }; @@ -185,6 +185,8 @@ extern bool MouseHide; extern int MouseHideSeconds; extern bool PauseLostFocus; +extern int64_t RTCOffset; + 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 new file mode 100644 index 0000000..2ef9688 --- /dev/null +++ b/src/frontend/qt_sdl/DateTimeDialog.cpp @@ -0,0 +1,91 @@ +/* + Copyright 2016-2022 melonDS team + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#include + +#include "types.h" +#include "Config.h" + +#include "DateTimeDialog.h" +#include "ui_DateTimeDialog.h" + +DateTimeDialog* DateTimeDialog::currentDlg = nullptr; + + +DateTimeDialog::DateTimeDialog(QWidget* parent) : QDialog(parent), ui(new Ui::DateTimeDialog) +{ + ui->setupUi(this); + setAttribute(Qt::WA_DeleteOnClose); + + QDateTime now = QDateTime::currentDateTime(); + customTime = now.addSecs(Config::RTCOffset); + + ui->chkChangeTime->setChecked(false); + ui->chkResetTime->setChecked(false); + + ui->lblCustomTime->setText(customTime.toString(ui->txtNewCustomTime->displayFormat())); + startTimer(1000); + + ui->txtNewCustomTime->setEnabled(ui->chkChangeTime->isChecked()); +} + +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) + { + if (ui->chkChangeTime->isChecked()) + { + QDateTime now = QDateTime::currentDateTime(); + Config::RTCOffset = now.secsTo(ui->txtNewCustomTime->dateTime()); + } + else if (ui->chkResetTime->isChecked()) + Config::RTCOffset = 0; + + Config::Save(); + } + + QDialog::done(r); + + closeDlg(); +} + +void DateTimeDialog::on_chkChangeTime_clicked(bool checked) +{ + if (checked) ui->chkResetTime->setChecked(false); + ui->txtNewCustomTime->setEnabled(checked); +} + +void DateTimeDialog::on_chkResetTime_clicked(bool checked) +{ + if (checked) + { + ui->chkChangeTime->setChecked(false); + ui->txtNewCustomTime->setEnabled(false); + } +} diff --git a/src/frontend/qt_sdl/DateTimeDialog.h b/src/frontend/qt_sdl/DateTimeDialog.h new file mode 100644 index 0000000..f13dbd0 --- /dev/null +++ b/src/frontend/qt_sdl/DateTimeDialog.h @@ -0,0 +1,70 @@ +/* + Copyright 2016-2022 melonDS team + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#ifndef DATETIMEDIALOG_H +#define DATETIMEDIALOG_H + +#include +#include +#include + +namespace Ui {class DateTimeDialog; } +class DateTimeDialog; + +class DateTimeDialog : public QDialog +{ + Q_OBJECT + +public: + explicit DateTimeDialog(QWidget* parent); + ~DateTimeDialog(); + + static DateTimeDialog* currentDlg; + static DateTimeDialog* openDlg(QWidget* parent) + { + if (currentDlg) + { + currentDlg->activateWindow(); + return currentDlg; + } + + currentDlg = new DateTimeDialog(parent); + currentDlg->open(); + return currentDlg; + } + static void closeDlg() + { + currentDlg = nullptr; + } + +protected: + void timerEvent(QTimerEvent* event) override; + +private slots: + void done(int r); + + void on_chkChangeTime_clicked(bool checked); + void on_chkResetTime_clicked(bool checked); + +private: + Ui::DateTimeDialog* ui; + + QDateTime customTime; +}; + +#endif // DATETIMEDIALOG_H diff --git a/src/frontend/qt_sdl/DateTimeDialog.ui b/src/frontend/qt_sdl/DateTimeDialog.ui new file mode 100644 index 0000000..59eb677 --- /dev/null +++ b/src/frontend/qt_sdl/DateTimeDialog.ui @@ -0,0 +1,148 @@ + + + DateTimeDialog + + + + 0 + 0 + 357 + 161 + + + + Date and time - melonDS + + + + + + Date and time + + + + + + Current value: + + + + + + + [placeholder] + + + + + + + + + + + + + + Change to: + + + + + + + + 0 + 0 + 0 + 2000 + 1 + 1 + + + + + 23 + 59 + 59 + 2099 + 12 + 31 + + + + + 0 + 0 + 0 + 2000 + 1 + 1 + + + + dd/MM/yyyy HH:mm:ss + + + true + + + + + + + Reset to system date and time + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + DateTimeDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + DateTimeDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/frontend/qt_sdl/Platform.cpp b/src/frontend/qt_sdl/Platform.cpp index 0cb9574..252594c 100644 --- a/src/frontend/qt_sdl/Platform.cpp +++ b/src/frontend/qt_sdl/Platform.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -610,6 +611,15 @@ void WriteFirmware(const SPI_Firmware::Firmware& firmware, u32 writeoffset, u32 } +void WriteDateTime(int year, int month, int day, int hour, int minute, int second) +{ + QDateTime hosttime = QDateTime::currentDateTime(); + QDateTime time = QDateTime(QDate(year, month, day), QTime(hour, minute, second)); + + Config::RTCOffset = hosttime.secsTo(time); + Config::Save(); +} + bool MP_Init() { return LocalMP::Init(); diff --git a/src/frontend/qt_sdl/ROMManager.cpp b/src/frontend/qt_sdl/ROMManager.cpp index cc65dfd..648ab67 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,15 @@ void SetBatteryLevels() } } +void SetDateTime() +{ + QDateTime hosttime = QDateTime::currentDateTime(); + QDateTime time = hosttime.addSecs(Config::RTCOffset); + + RTC::SetDateTime(time.date().year(), time.date().month(), time.date().day(), + time.time().hour(), time.time().minute(), time.time().second()); +} + void Reset() { NDS::SetConsoleType(Config::ConsoleType); @@ -602,6 +614,7 @@ void Reset() } NDS::Reset(); SetBatteryLevels(); + SetDateTime(); if ((CartType != -1) && NDSSave) { @@ -678,6 +691,7 @@ bool LoadBIOS() NDS::Reset(); SetBatteryLevels(); + SetDateTime(); return true; } @@ -1204,6 +1218,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 a6cc248..f670477 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -58,6 +58,7 @@ #include "main.h" #include "Input.h" #include "CheatsDialog.h" +#include "DateTimeDialog.h" #include "EmuSettingsDialog.h" #include "InputConfig/InputConfigDialog.h" #include "VideoSettingsDialog.h" @@ -90,6 +91,7 @@ #include "LocalMP.h" #include "Config.h" #include "DSi_I2C.h" +#include "RTC.h" #include "Savestate.h" @@ -313,6 +315,7 @@ void EmuThread::deinitOpenGL() void EmuThread::run() { u32 mainScreenPos[3]; + Platform::FileHandle* file; NDS::Init(); @@ -352,6 +355,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) @@ -650,6 +662,15 @@ 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); + } + EmuStatus = emuStatus_Exit; GPU::DeInitRenderer(); @@ -1525,6 +1546,9 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) actPowerManagement = menu->addAction("Power management"); connect(actPowerManagement, &QAction::triggered, this, &MainWindow::onOpenPowerManagement); + actDateTime = menu->addAction("Date and time"); + connect(actDateTime, &QAction::triggered, this, &MainWindow::onOpenDateTime); + menu->addSeparator(); actEnableCheats = menu->addAction("Enable cheats"); @@ -1787,6 +1811,7 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) actStop->setEnabled(false); actFrameStep->setEnabled(false); + actDateTime->setEnabled(true); actPowerManagement->setEnabled(false); actSetupCheats->setEnabled(false); @@ -2737,6 +2762,16 @@ void MainWindow::onFrameStep() emuThread->emuFrameStep(); } +void MainWindow::onOpenDateTime() +{ + DateTimeDialog* dlg = DateTimeDialog::openDlg(this); +} + +void MainWindow::onOpenPowerManagement() +{ + PowerManagementDialog* dlg = PowerManagementDialog::openDlg(this); +} + void MainWindow::onEnableCheats(bool checked) { Config::EnableCheats = checked?1:0; @@ -2824,11 +2859,6 @@ void MainWindow::onEmuSettingsDialogFinished(int res) actTitleManager->setEnabled(!Config::DSiNANDPath.empty()); } -void MainWindow::onOpenPowerManagement() -{ - PowerManagementDialog* dlg = PowerManagementDialog::openDlg(this); -} - void MainWindow::onOpenInputConfig() { emuThread->emuPause(); @@ -3148,6 +3178,7 @@ void MainWindow::onEmuStart() actStop->setEnabled(true); actFrameStep->setEnabled(true); + actDateTime->setEnabled(false); actPowerManagement->setEnabled(true); actTitleManager->setEnabled(false); @@ -3169,6 +3200,7 @@ void MainWindow::onEmuStop() actStop->setEnabled(false); actFrameStep->setEnabled(false); + actDateTime->setEnabled(true); actPowerManagement->setEnabled(false); actTitleManager->setEnabled(!Config::DSiNANDPath.empty()); diff --git a/src/frontend/qt_sdl/main.h b/src/frontend/qt_sdl/main.h index 073a4da..5832ed3 100644 --- a/src/frontend/qt_sdl/main.h +++ b/src/frontend/qt_sdl/main.h @@ -299,6 +299,8 @@ private slots: void onReset(); void onStop(); void onFrameStep(); + void onOpenPowerManagement(); + void onOpenDateTime(); void onEnableCheats(bool checked); void onSetupCheats(); void onCheatsDialogFinished(int res); @@ -309,7 +311,6 @@ private slots: void onOpenEmuSettings(); void onEmuSettingsDialogFinished(int res); - void onOpenPowerManagement(); void onOpenInputConfig(); void onInputConfigFinished(int res); void onOpenVideoSettings(); @@ -397,6 +398,8 @@ public: QAction* actReset; QAction* actStop; QAction* actFrameStep; + QAction* actPowerManagement; + QAction* actDateTime; QAction* actEnableCheats; QAction* actSetupCheats; QAction* actROMInfo; @@ -408,7 +411,6 @@ public: #ifdef __APPLE__ QAction* actPreferences; #endif - QAction* actPowerManagement; QAction* actInputConfig; QAction* actVideoSettings; QAction* actCameraSettings; -- cgit v1.2.3