mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-01-30 21:32:50 +00:00
Core: Add date/time offset capability for console time
Provides a setting which can be applied per game, and allows for a custom date/time to be set. The console time will then apply this as an offset to the computer wallclock. This allows for games which look at the console time to determine their gameplay to be adjusted.
This commit is contained in:
parent
3372409590
commit
53212ba7a9
@ -207,7 +207,8 @@ error_code sys_time_get_current_time(vm::ptr<s64> sec, vm::ptr<s64> nsec)
|
||||
// get time since Epoch in nanoseconds
|
||||
const u64 time = s_time_aux_info.start_ftime * 100u + (diff * g_cfg.core.clocks_scale / 100u);
|
||||
|
||||
*sec = time / 1000000000ull;
|
||||
// scale to seconds, and add the console time offset (which might be negative)
|
||||
*sec = (time / 1000000000ull) + g_cfg.sys.console_time_offset;
|
||||
|
||||
if (!nsec)
|
||||
{
|
||||
@ -221,7 +222,8 @@ error_code sys_time_get_current_time(vm::ptr<s64> sec, vm::ptr<s64> nsec)
|
||||
|
||||
if (g_cfg.core.clocks_scale == 100)
|
||||
{
|
||||
*sec = ts.tv_sec;
|
||||
// get the seconds from the system clock, and add the console time offset (which might be negative)
|
||||
*sec = ts.tv_sec + g_cfg.sys.console_time_offset;
|
||||
|
||||
if (!nsec)
|
||||
{
|
||||
@ -252,8 +254,8 @@ error_code sys_time_get_current_time(vm::ptr<s64> sec, vm::ptr<s64> nsec)
|
||||
// Scale nanocseconds
|
||||
tv_nsec = stv_nsec + (tv_nsec * g_cfg.core.clocks_scale / 100);
|
||||
|
||||
// Scale seconds and add from nanoseconds / 1'000'000'000
|
||||
*sec = stv_sec + (tv_sec * g_cfg.core.clocks_scale / 100u) + (tv_nsec / 1000000000ull);
|
||||
// Scale seconds and add from nanoseconds / 1'000'000'000, and add the console time offset (which might be negative)
|
||||
*sec = stv_sec + (tv_sec * g_cfg.core.clocks_scale / 100u) + (tv_nsec / 1000000000ull) + g_cfg.sys.console_time_offset;
|
||||
|
||||
if (!nsec)
|
||||
{
|
||||
|
@ -249,6 +249,7 @@ struct cfg_root : cfg::node
|
||||
cfg::_enum<CellSysutilLang> language{ this, "Language", CellSysutilLang{1} }; // CELL_SYSUTIL_LANG_ENGLISH_US
|
||||
cfg::_enum<CellKbMappingType> keyboard_type{ this, "Keyboard Type", CellKbMappingType{0} }; // CELL_KB_MAPPING_101 = US
|
||||
cfg::_enum<enter_button_assign> enter_button_assignment{ this, "Enter button assignment", enter_button_assign::cross };
|
||||
cfg::_int<-60*60*24*365*100LL, 60*60*24*365*100LL> console_time_offset{ this, "Console time offset (s)", 0 }; //console time offset, limited to +/-100years
|
||||
|
||||
} sys{ this };
|
||||
|
||||
|
@ -3,6 +3,8 @@
|
||||
|
||||
#include <QMessageBox>
|
||||
#include <QLineEdit>
|
||||
#include <QTimer>
|
||||
#include <QCalendarWidget>
|
||||
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/system_config.h"
|
||||
@ -307,6 +309,123 @@ void emu_settings::EnhanceCheckBox(QCheckBox* checkbox, emu_settings_type type)
|
||||
});
|
||||
}
|
||||
|
||||
void emu_settings::EnhanceDateTimeEdit(QDateTimeEdit* date_time_edit, emu_settings_type type, const QString& format, bool use_calendar, bool as_offset_from_now, int offset_update_time)
|
||||
{
|
||||
if (!date_time_edit)
|
||||
{
|
||||
cfg_log.fatal("EnhanceDateTimeEdit '%s' was used with an invalid object", cfg_adapter::get_setting_name(type));
|
||||
return;
|
||||
}
|
||||
|
||||
date_time_edit->setDisplayFormat(format);
|
||||
date_time_edit->setCalendarPopup(use_calendar);
|
||||
|
||||
if (as_offset_from_now)
|
||||
{
|
||||
// If using offset from now, then we disable the keyboard tracking to reduce the numebr of events that occur (since for each event we will lose focus)
|
||||
date_time_edit->setKeyboardTracking(false);
|
||||
|
||||
bool ok_def = false, ok_min = false, ok_max = false;
|
||||
const QStringList range = GetSettingOptions(type);
|
||||
const s64 def = qstr(GetSettingDefault(type)).toLongLong(&ok_def);
|
||||
const s64 min = range.first().toLongLong(&ok_min);
|
||||
const s64 max = range.last().toLongLong(&ok_max);
|
||||
if (!ok_def || !ok_min || !ok_max)
|
||||
{
|
||||
cfg_log.fatal("EnhanceDateTimeEdit '%s' was used with an invalid emu_settings_type", cfg_adapter::get_setting_name(type));
|
||||
return;
|
||||
}
|
||||
|
||||
bool ok_sel = false;
|
||||
s64 val = qstr(GetSetting(type)).toLongLong(&ok_sel);
|
||||
if (!ok_sel || val < min || val > max)
|
||||
{
|
||||
cfg_log.error("EnhanceDateTimeEdit '%s' tried to set an invalid value: %d. Setting to default: %d. Allowed range: [%d, %d]", cfg_adapter::get_setting_name(type), val, def, min, max);
|
||||
val = def;
|
||||
m_broken_types.insert(type);
|
||||
SetSetting(type, std::to_string(def));
|
||||
}
|
||||
|
||||
// we'll capture the DateTime once, and apply the min/max and offset against it here.
|
||||
const QDateTime now = QDateTime::currentDateTime();
|
||||
|
||||
// we set the allowed limits
|
||||
date_time_edit->setDateTimeRange(now.addSecs(min), now.addSecs(max));
|
||||
|
||||
// we add the offset, and set the control to have this datetime value
|
||||
const QDateTime date_time = now.addSecs(val);
|
||||
date_time_edit->setDateTime(date_time);
|
||||
|
||||
// if we have an invalid update time then we won't run the update timer
|
||||
if (offset_update_time > 0)
|
||||
{
|
||||
QTimer* console_time_update = new QTimer(date_time_edit);
|
||||
connect(console_time_update, &QTimer::timeout, [this, date_time_edit, min, max]()
|
||||
{
|
||||
if (!date_time_edit->hasFocus() && (!date_time_edit->calendarPopup() || !date_time_edit->calendarWidget()->hasFocus()))
|
||||
{
|
||||
const auto now = QDateTime::currentDateTime();
|
||||
const s64 offset = qstr(GetSetting(emu_settings_type::ConsoleTimeOffset)).toLongLong();
|
||||
date_time_edit->setDateTime(now.addSecs(offset));
|
||||
date_time_edit->setDateTimeRange(now.addSecs(min), now.addSecs(max));
|
||||
}
|
||||
});
|
||||
|
||||
console_time_update->start(offset_update_time);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
auto str = qstr(GetSettingDefault(type));
|
||||
const QStringList range = GetSettingOptions(type);
|
||||
const auto def = QDateTime::fromString(str, Qt::ISODate);
|
||||
const auto min = QDateTime::fromString(range.first(), Qt::ISODate);
|
||||
const auto max = QDateTime::fromString(range.last(), Qt::ISODate);
|
||||
if (!def.isValid() || !min.isValid() || !max.isValid())
|
||||
{
|
||||
cfg_log.fatal("EnhanceDateTimeEdit '%s' was used with an invalid emu_settings_type", cfg_adapter::get_setting_name(type));
|
||||
return;
|
||||
}
|
||||
|
||||
str = qstr(GetSetting(type));
|
||||
auto val = QDateTime::fromString(str, Qt::ISODate);
|
||||
if (!val.isValid() || val < min || val > max)
|
||||
{
|
||||
cfg_log.error("EnhanceDateTimeEdit '%s' tried to set an invalid value: %s. Setting to default: %s Allowed range: [%s, %s]",
|
||||
cfg_adapter::get_setting_name(type), val.toString(Qt::ISODate).toStdString(), def.toString(Qt::ISODate).toStdString(),
|
||||
min.toString(Qt::ISODate).toStdString(), max.toString(Qt::ISODate).toStdString());
|
||||
val = def;
|
||||
m_broken_types.insert(type);
|
||||
SetSetting(type, sstr(def.toString(Qt::ISODate)));
|
||||
}
|
||||
|
||||
// we set the allowed limits
|
||||
date_time_edit->setDateTimeRange(min, max);
|
||||
|
||||
// set the date_time value to the control
|
||||
date_time_edit->setDateTime(val);
|
||||
}
|
||||
|
||||
connect(date_time_edit, &QDateTimeEdit::dateTimeChanged, [date_time_edit, type, as_offset_from_now, this](const QDateTime& datetime)
|
||||
{
|
||||
if (as_offset_from_now)
|
||||
{
|
||||
// offset will be applied in seconds
|
||||
const s64 offset = QDateTime::currentDateTime().secsTo(datetime);
|
||||
SetSetting(type, std::to_string(offset));
|
||||
|
||||
// HACK: We are only looking at whether the control has focus to prevent the time from updating dynamically, so we
|
||||
// clear the focus, so that this dynamic updating isn't suppressed.
|
||||
date_time_edit->clearFocus();
|
||||
}
|
||||
else
|
||||
{
|
||||
// date time will be written straight into settings
|
||||
SetSetting(type, sstr(datetime.toString(Qt::ISODate)));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void emu_settings::EnhanceSlider(QSlider* slider, emu_settings_type type)
|
||||
{
|
||||
if (!slider)
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <QStringList>
|
||||
#include <QComboBox>
|
||||
#include <QSpinBox>
|
||||
#include <QDateTimeEdit>
|
||||
|
||||
constexpr auto qstr = QString::fromStdString;
|
||||
|
||||
@ -37,6 +38,9 @@ public:
|
||||
/** Connects a check box with the target settings type*/
|
||||
void EnhanceCheckBox(QCheckBox* checkbox, emu_settings_type type);
|
||||
|
||||
/** Connects a date time edit box with the target settings type*/
|
||||
void EnhanceDateTimeEdit(QDateTimeEdit* date_time_edit, emu_settings_type type, const QString& format, bool use_calendar, bool as_offset_from_now, int offset_update_time=0);
|
||||
|
||||
/** Connects a slider with the target settings type*/
|
||||
void EnhanceSlider(QSlider* slider, emu_settings_type type);
|
||||
|
||||
|
@ -135,6 +135,7 @@ enum class emu_settings_type
|
||||
EnableHostRoot,
|
||||
LimitCacheSize,
|
||||
MaximumCacheSize,
|
||||
ConsoleTimeOffset,
|
||||
|
||||
// Virtual File System
|
||||
emulatorLocation,
|
||||
@ -275,6 +276,7 @@ static const QMap<emu_settings_type, cfg_location> settings_location =
|
||||
{ emu_settings_type::EnableHostRoot, { "VFS", "Enable /host_root/"}},
|
||||
{ emu_settings_type::LimitCacheSize, { "VFS", "Limit disk cache size"}},
|
||||
{ emu_settings_type::MaximumCacheSize, { "VFS", "Disk cache maximum size (MB)"}},
|
||||
{ emu_settings_type::ConsoleTimeOffset, { "System", "Console time offset (s)"}},
|
||||
|
||||
// Virtual File System
|
||||
{ emu_settings_type::emulatorLocation, { "VFS", "$(EmulatorDir)"}},
|
||||
|
@ -848,6 +848,14 @@ settings_dialog::settings_dialog(std::shared_ptr<gui_settings> gui_settings, std
|
||||
SubscribeTooltip(ui->gb_DiskCacheClearing, tooltips.settings.limit_cache_size);
|
||||
connect(ui->enableCacheClearing, &QCheckBox::stateChanged, ui->maximumCacheSize, &QSlider::setEnabled);
|
||||
|
||||
// Date Time Edit Box
|
||||
m_emu_settings->EnhanceDateTimeEdit(ui->console_time_edit, emu_settings_type::ConsoleTimeOffset, tr("dd MMM yyyy HH:mm"), true, true, 15000);
|
||||
connect(ui->console_time_reset, &QAbstractButton::clicked, [this]()
|
||||
{
|
||||
ui->console_time_edit->setDateTime(QDateTime::currentDateTime());
|
||||
});
|
||||
SubscribeTooltip(ui->gb_console_time, tooltips.settings.console_time_offset);
|
||||
|
||||
// Sliders
|
||||
|
||||
EnhanceSlider(emu_settings_type::MaximumCacheSize, ui->maximumCacheSize, ui->maximumCacheSizeLabel, tr("Maximum size: %0 MB", "Maximum cache size"));
|
||||
|
@ -1447,7 +1447,61 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="systemTabSpacerWidget1" native="true"/>
|
||||
<widget class="QGroupBox" name="gb_console_time">
|
||||
<property name="title">
|
||||
<string>Console Time</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QDateTimeEdit" name="console_time_edit">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>10</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::LeftToRight</enum>
|
||||
</property>
|
||||
<property name="wrapping">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="frame">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::UpDownArrows</enum>
|
||||
</property>
|
||||
<property name="accelerated">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="showGroupSeparator" stdset="0">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="calendarPopup">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="console_time_reset">
|
||||
<property name="text">
|
||||
<string>Set to Now</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="systemTabSpacerWidget2" native="true"/>
|
||||
|
@ -193,6 +193,7 @@ public:
|
||||
const QString enter_button_assignment = tr("The button used for enter/accept/confirm in system dialogs.\nChange this to use the Circle button instead, which is the default configuration on Japanese systems and in many Japanese games.\nIn these cases having the cross button assigned can often lead to confusion.");
|
||||
const QString enable_host_root = tr("Required for some Homebrew.\nIf unsure, don't use this option.");
|
||||
const QString limit_cache_size = tr("Automatically removes older files from disk cache on boot if it grows larger than the specified value.\nGames can use the cache folder to temporarily store data outside of system memory. It is not used for long-term storage.");
|
||||
const QString console_time_offset = tr("Sets the time to be used within the console. This will be applied as an offset that tracks wall clock time.\nCan be reset to current wallclock time by clicking \"Set to Now\".");
|
||||
} settings;
|
||||
|
||||
const struct gamepad_settings
|
||||
|
Loading…
x
Reference in New Issue
Block a user