From e822dfbd4f87e281334df595cce17cf62d3bd594 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Fri, 27 Oct 2023 14:20:41 +0200 Subject: [PATCH] more RTC work lay base for date/time dialog --- src/RTC.cpp | 132 +++++++++++++++++-- src/RTC.h | 3 + src/frontend/qt_sdl/CMakeLists.txt | 1 + src/frontend/qt_sdl/DateTimeDialog.cpp | 51 +++++++ src/frontend/qt_sdl/DateTimeDialog.h | 64 +++++++++ src/frontend/qt_sdl/DateTimeDialog.ui | 175 +++++++++++++++++++++++++ src/frontend/qt_sdl/main.cpp | 22 +++- src/frontend/qt_sdl/main.h | 6 +- 8 files changed, 436 insertions(+), 18 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 diff --git a/src/RTC.cpp b/src/RTC.cpp index 8f8994b0..c0ab99db 100644 --- a/src/RTC.cpp +++ b/src/RTC.cpp @@ -52,6 +52,9 @@ s32 TimerError; u32 ClockCount; +void WriteDateTime(int num, u8 val); + + bool Init() { return true; @@ -106,14 +109,6 @@ void DoSavestate(Savestate* file) } -void ResetState() -{ - memset(&State, 0, sizeof(State)); - State.DateTime[1] = 1; - State.DateTime[2] = 1; -} - - u8 BCD(u8 val) { return (val % 10) | ((val / 10) << 4); @@ -141,6 +136,80 @@ u8 BCDSanitize(u8 val, u8 vmin, u8 vmax) return val; } + +void GetState(StateData& state) +{ + memcpy(&state, &State, sizeof(State)); +} + +void SetState(StateData& state) +{ + memcpy(&State, &state, sizeof(State)); + + // sanitize the input state + + for (int i = 0; i < 7; i++) + WriteDateTime(i+1, State.DateTime[i]); +} + +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}; + + // the year range of the DS RTC is limited to 2000-2099 + year %= 100; + if (year < 0) year = 0; + + if (!(year & 3)) monthdays[2] = 29; + + if (month < 1 || month > 12) month = 1; + if (day < 1 || day > monthdays[month]) day = 1; + if (hour < 0 || hour > 23) hour = 0; + if (minute < 0 || minute > 59) minute = 0; + if (second < 0 || second > 59) second = 0; + + // note on day-of-week value + // that RTC register is a simple incrementing counter and the assignation is defined by software + // DS/DSi firmware counts from 0=Sunday + + int numdays = (year * 365) + ((year+3) / 4); // account for leap years + + for (int m = 1; m < month; m++) + { + numdays += monthdays[m]; + } + numdays += (day-1); + + // 01/01/2000 is a Saturday, so the starting value is 6 + int dayofweek = (6 + numdays) % 7; + + int pm = (hour >= 12) ? 0x40 : 0; + if (!(State.StatusReg1 & (1<<1))) + { + // 12-hour mode + + if (pm) hour -= 12; + } + + State.DateTime[0] = BCD(year); + State.DateTime[1] = BCD(month); + State.DateTime[2] = BCD(day); + State.DateTime[3] = dayofweek; + State.DateTime[4] = BCD(hour) | pm; + State.DateTime[5] = BCD(minute); + State.DateTime[6] = BCD(second); + + State.StatusReg1 &= ~0x80; +} + +void ResetState() +{ + memset(&State, 0, sizeof(State)); + State.DateTime[1] = 1; + State.DateTime[2] = 1; +} + + u8 DaysInMonth() { u8 numdays; @@ -449,8 +518,46 @@ void CmdWrite(u8 val) State.StatusReg1 = (State.StatusReg1 & 0xF0) | (val & 0x0E); - if ((State.StatusReg1 ^ oldval) & (1<<1)) // AM/PM changed - WriteDateTime(5, State.DateTime[4]); + if ((State.StatusReg1 ^ oldval) & (1<<1)) + { + // AM/PM changed + + u8 hour = State.DateTime[4] & 0x3F; + u8 pm = State.DateTime[4] & 0x40; + + if (State.StatusReg1 & (1<<1)) + { + // 24-hour mode + + if (pm) + { + hour += 0x12; + if ((hour & 0x0F) >= 0x0A) + hour += 0x06; + } + + hour = BCDSanitize(hour, 0x00, 0x23); + } + else + { + // 12-hour mode + + if (hour >= 0x12) + { + pm = 0x40; + + hour -= 0x12; + if ((hour & 0x0F) >= 0x0A) + hour -= 0x06; + } + else + pm = 0; + + hour = BCDSanitize(hour, 0x00, 0x11); + } + + State.DateTime[4] = hour | pm; + } } break; @@ -459,7 +566,10 @@ void CmdWrite(u8 val) { State.StatusReg2 = val; if (State.StatusReg2 & 0x4F) - Log(LogLevel::Debug, "RTC INTERRUPT ON: %02X\n", State.StatusReg2); + Log(LogLevel::Debug, "RTC INTERRUPT ON: %02X, %02X %02X %02X, %02X %02X %02X\n", + State.StatusReg2, + State.Alarm1[0], State.Alarm1[1], State.Alarm1[2], + State.Alarm2[0], State.Alarm2[1], State.Alarm2[2]); } break; diff --git a/src/RTC.h b/src/RTC.h index ab2fea07..f34ac7e2 100644 --- a/src/RTC.h +++ b/src/RTC.h @@ -48,6 +48,9 @@ void DeInit(); void Reset(); void DoSavestate(Savestate* file); +void GetState(StateData& state); +void SetState(StateData& state); +void SetDateTime(int year, int month, int day, int hour, int minute, int second); void ResetState(); void ScheduleTimer(bool first); diff --git a/src/frontend/qt_sdl/CMakeLists.txt b/src/frontend/qt_sdl/CMakeLists.txt index 3923f379..cdc96dd5 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/DateTimeDialog.cpp b/src/frontend/qt_sdl/DateTimeDialog.cpp new file mode 100644 index 00000000..9520a9e0 --- /dev/null +++ b/src/frontend/qt_sdl/DateTimeDialog.cpp @@ -0,0 +1,51 @@ +/* + 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); + + // +} + +DateTimeDialog::~DateTimeDialog() +{ + delete ui; +} + +void DateTimeDialog::done(int r) +{ + QDialog::done(r); + + closeDlg(); +} + +// + diff --git a/src/frontend/qt_sdl/DateTimeDialog.h b/src/frontend/qt_sdl/DateTimeDialog.h new file mode 100644 index 00000000..c2c0dc7e --- /dev/null +++ b/src/frontend/qt_sdl/DateTimeDialog.h @@ -0,0 +1,64 @@ +/* + 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 + +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; + } + +private slots: + void done(int r); + + // slots here + +private: + Ui::DateTimeDialog* ui; + + // +}; + +#endif // DATETIMEDIALOG_H diff --git a/src/frontend/qt_sdl/DateTimeDialog.ui b/src/frontend/qt_sdl/DateTimeDialog.ui new file mode 100644 index 00000000..fb400553 --- /dev/null +++ b/src/frontend/qt_sdl/DateTimeDialog.ui @@ -0,0 +1,175 @@ + + + DateTimeDialog + + + + 0 + 0 + 357 + 259 + + + + Date and time - melonDS + + + + + + General settings + + + + + + Use custom date and time + + + + + + + Always use system date and time + + + + + + + + + + Custom date and time + + + + + + Current value: + + + + + + + [placeholder] + + + + + + + + + + + + + + Change + + + + + + + New value: + + + + + + + The new value will be applied on the next boot. + + + + + + + + 0 + 0 + 0 + 2000 + 1 + 1 + + + + + 23 + 59 + 59 + 2099 + 12 + 31 + + + + + 0 + 0 + 0 + 2000 + 1 + 1 + + + + true + + + + + + + + + + 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/main.cpp b/src/frontend/qt_sdl/main.cpp index a6cc2482..33808bc6 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" @@ -1525,6 +1526,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 +1791,7 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) actStop->setEnabled(false); actFrameStep->setEnabled(false); + actDateTime->setEnabled(true); actPowerManagement->setEnabled(false); actSetupCheats->setEnabled(false); @@ -2737,6 +2742,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 +2839,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 +3158,7 @@ void MainWindow::onEmuStart() actStop->setEnabled(true); actFrameStep->setEnabled(true); + actDateTime->setEnabled(false); actPowerManagement->setEnabled(true); actTitleManager->setEnabled(false); @@ -3169,6 +3180,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 073a4da0..5832ed3b 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;