more RTC work

lay base for date/time dialog
This commit is contained in:
Arisotura 2023-10-27 14:20:41 +02:00
parent 5d8b1b5a19
commit e822dfbd4f
8 changed files with 436 additions and 18 deletions

View File

@ -52,6 +52,9 @@ s32 TimerError;
u32 ClockCount; u32 ClockCount;
void WriteDateTime(int num, u8 val);
bool Init() bool Init()
{ {
return true; 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) u8 BCD(u8 val)
{ {
return (val % 10) | ((val / 10) << 4); return (val % 10) | ((val / 10) << 4);
@ -141,6 +136,80 @@ u8 BCDSanitize(u8 val, u8 vmin, u8 vmax)
return val; 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 DaysInMonth()
{ {
u8 numdays; u8 numdays;
@ -449,8 +518,46 @@ void CmdWrite(u8 val)
State.StatusReg1 = (State.StatusReg1 & 0xF0) | (val & 0x0E); State.StatusReg1 = (State.StatusReg1 & 0xF0) | (val & 0x0E);
if ((State.StatusReg1 ^ oldval) & (1<<1)) // AM/PM changed if ((State.StatusReg1 ^ oldval) & (1<<1))
WriteDateTime(5, State.DateTime[4]); {
// 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; break;
@ -459,7 +566,10 @@ void CmdWrite(u8 val)
{ {
State.StatusReg2 = val; State.StatusReg2 = val;
if (State.StatusReg2 & 0x4F) 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; break;

View File

@ -48,6 +48,9 @@ void DeInit();
void Reset(); void Reset();
void DoSavestate(Savestate* file); 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 ResetState();
void ScheduleTimer(bool first); void ScheduleTimer(bool first);

View File

@ -7,6 +7,7 @@ set(SOURCES_QT_SDL
main_shaders.h main_shaders.h
CheatsDialog.cpp CheatsDialog.cpp
Config.cpp Config.cpp
DateTimeDialog.cpp
EmuSettingsDialog.cpp EmuSettingsDialog.cpp
PowerManagement/PowerManagementDialog.cpp PowerManagement/PowerManagementDialog.cpp
PowerManagement/resources/battery.qrc PowerManagement/resources/battery.qrc

View File

@ -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 <stdio.h>
#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();
}
//

View File

@ -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 <QDialog>
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

View File

@ -0,0 +1,175 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DateTimeDialog</class>
<widget class="QDialog" name="DateTimeDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>357</width>
<height>259</height>
</rect>
</property>
<property name="windowTitle">
<string>Date and time - melonDS</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>General settings</string>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="1" column="0" colspan="2">
<widget class="QRadioButton" name="rbCustomTime">
<property name="text">
<string>Use custom date and time</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QRadioButton" name="rbSystemTime">
<property name="text">
<string>Always use system date and time</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Custom date and time</string>
</property>
<layout class="QFormLayout" name="formLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Current value:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="lblCustomTime">
<property name="text">
<string>[placeholder]</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QCheckBox" name="cbChangeTime">
<property name="text">
<string>Change</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>New value:</string>
</property>
</widget>
</item>
<item row="4" column="0" colspan="2">
<widget class="QLabel" name="label_5">
<property name="text">
<string>The new value will be applied on the next boot.</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QDateTimeEdit" name="txtNewCustomDate">
<property name="dateTime">
<datetime>
<hour>0</hour>
<minute>0</minute>
<second>0</second>
<year>2000</year>
<month>1</month>
<day>1</day>
</datetime>
</property>
<property name="maximumDateTime">
<datetime>
<hour>23</hour>
<minute>59</minute>
<second>59</second>
<year>2099</year>
<month>12</month>
<day>31</day>
</datetime>
</property>
<property name="minimumDateTime">
<datetime>
<hour>0</hour>
<minute>0</minute>
<second>0</second>
<year>2000</year>
<month>1</month>
<day>1</day>
</datetime>
</property>
<property name="calendarPopup">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>DateTimeDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>DateTimeDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -58,6 +58,7 @@
#include "main.h" #include "main.h"
#include "Input.h" #include "Input.h"
#include "CheatsDialog.h" #include "CheatsDialog.h"
#include "DateTimeDialog.h"
#include "EmuSettingsDialog.h" #include "EmuSettingsDialog.h"
#include "InputConfig/InputConfigDialog.h" #include "InputConfig/InputConfigDialog.h"
#include "VideoSettingsDialog.h" #include "VideoSettingsDialog.h"
@ -1525,6 +1526,9 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent)
actPowerManagement = menu->addAction("Power management"); actPowerManagement = menu->addAction("Power management");
connect(actPowerManagement, &QAction::triggered, this, &MainWindow::onOpenPowerManagement); connect(actPowerManagement, &QAction::triggered, this, &MainWindow::onOpenPowerManagement);
actDateTime = menu->addAction("Date and time");
connect(actDateTime, &QAction::triggered, this, &MainWindow::onOpenDateTime);
menu->addSeparator(); menu->addSeparator();
actEnableCheats = menu->addAction("Enable cheats"); actEnableCheats = menu->addAction("Enable cheats");
@ -1787,6 +1791,7 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent)
actStop->setEnabled(false); actStop->setEnabled(false);
actFrameStep->setEnabled(false); actFrameStep->setEnabled(false);
actDateTime->setEnabled(true);
actPowerManagement->setEnabled(false); actPowerManagement->setEnabled(false);
actSetupCheats->setEnabled(false); actSetupCheats->setEnabled(false);
@ -2737,6 +2742,16 @@ void MainWindow::onFrameStep()
emuThread->emuFrameStep(); emuThread->emuFrameStep();
} }
void MainWindow::onOpenDateTime()
{
DateTimeDialog* dlg = DateTimeDialog::openDlg(this);
}
void MainWindow::onOpenPowerManagement()
{
PowerManagementDialog* dlg = PowerManagementDialog::openDlg(this);
}
void MainWindow::onEnableCheats(bool checked) void MainWindow::onEnableCheats(bool checked)
{ {
Config::EnableCheats = checked?1:0; Config::EnableCheats = checked?1:0;
@ -2824,11 +2839,6 @@ void MainWindow::onEmuSettingsDialogFinished(int res)
actTitleManager->setEnabled(!Config::DSiNANDPath.empty()); actTitleManager->setEnabled(!Config::DSiNANDPath.empty());
} }
void MainWindow::onOpenPowerManagement()
{
PowerManagementDialog* dlg = PowerManagementDialog::openDlg(this);
}
void MainWindow::onOpenInputConfig() void MainWindow::onOpenInputConfig()
{ {
emuThread->emuPause(); emuThread->emuPause();
@ -3148,6 +3158,7 @@ void MainWindow::onEmuStart()
actStop->setEnabled(true); actStop->setEnabled(true);
actFrameStep->setEnabled(true); actFrameStep->setEnabled(true);
actDateTime->setEnabled(false);
actPowerManagement->setEnabled(true); actPowerManagement->setEnabled(true);
actTitleManager->setEnabled(false); actTitleManager->setEnabled(false);
@ -3169,6 +3180,7 @@ void MainWindow::onEmuStop()
actStop->setEnabled(false); actStop->setEnabled(false);
actFrameStep->setEnabled(false); actFrameStep->setEnabled(false);
actDateTime->setEnabled(true);
actPowerManagement->setEnabled(false); actPowerManagement->setEnabled(false);
actTitleManager->setEnabled(!Config::DSiNANDPath.empty()); actTitleManager->setEnabled(!Config::DSiNANDPath.empty());

View File

@ -299,6 +299,8 @@ private slots:
void onReset(); void onReset();
void onStop(); void onStop();
void onFrameStep(); void onFrameStep();
void onOpenPowerManagement();
void onOpenDateTime();
void onEnableCheats(bool checked); void onEnableCheats(bool checked);
void onSetupCheats(); void onSetupCheats();
void onCheatsDialogFinished(int res); void onCheatsDialogFinished(int res);
@ -309,7 +311,6 @@ private slots:
void onOpenEmuSettings(); void onOpenEmuSettings();
void onEmuSettingsDialogFinished(int res); void onEmuSettingsDialogFinished(int res);
void onOpenPowerManagement();
void onOpenInputConfig(); void onOpenInputConfig();
void onInputConfigFinished(int res); void onInputConfigFinished(int res);
void onOpenVideoSettings(); void onOpenVideoSettings();
@ -397,6 +398,8 @@ public:
QAction* actReset; QAction* actReset;
QAction* actStop; QAction* actStop;
QAction* actFrameStep; QAction* actFrameStep;
QAction* actPowerManagement;
QAction* actDateTime;
QAction* actEnableCheats; QAction* actEnableCheats;
QAction* actSetupCheats; QAction* actSetupCheats;
QAction* actROMInfo; QAction* actROMInfo;
@ -408,7 +411,6 @@ public:
#ifdef __APPLE__ #ifdef __APPLE__
QAction* actPreferences; QAction* actPreferences;
#endif #endif
QAction* actPowerManagement;
QAction* actInputConfig; QAction* actInputConfig;
QAction* actVideoSettings; QAction* actVideoSettings;
QAction* actCameraSettings; QAction* actCameraSettings;