mirror of https://github.com/PCSX2/pcsx2.git
Compare commits
4 Commits
7356be4b2b
...
f015bd96fa
Author | SHA1 | Date |
---|---|---|
TheTechnician27 | f015bd96fa | |
Ty | 4a57bd7fd4 | |
shockdude | fbe0c8b9cc | |
TheTechnician27 | 15fe65c964 |
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team
|
||||
// SPDX-FileCopyrightText: 2002-2025 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#pragma once
|
||||
|
@ -12,6 +12,7 @@
|
|||
#include <QtWidgets/QAbstractButton>
|
||||
#include <QtWidgets/QCheckBox>
|
||||
#include <QtWidgets/QComboBox>
|
||||
#include <QtWidgets/QDateTimeEdit>
|
||||
#include <QtWidgets/QDoubleSpinBox>
|
||||
#include <QtWidgets/QFileDialog>
|
||||
#include <QtWidgets/QLabel>
|
||||
|
@ -656,6 +657,26 @@ namespace SettingWidgetBinder
|
|||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct SettingAccessor<QDateTimeEdit>
|
||||
{
|
||||
static int getYear(const QDateTimeEdit* widget) { return widget->date().year(); }
|
||||
static int getMonth(const QDateTimeEdit* widget) { return widget->date().month(); }
|
||||
static int getDay(const QDateTimeEdit* widget) { return widget->date().day(); }
|
||||
|
||||
static int getHour(const QDateTimeEdit* widget) { return widget->time().hour(); }
|
||||
static int getMinute(const QDateTimeEdit* widget) { return widget->time().minute(); }
|
||||
static int getSecond(const QDateTimeEdit* widget) { return widget->time().second(); }
|
||||
|
||||
static void setDateTime(QDateTimeEdit* widget, const QDate date, const QTime time) { widget->setDateTime(QDateTime(date, time)); }
|
||||
|
||||
template <typename F>
|
||||
static void connectValueChanged(QDateTimeEdit* widget, F func)
|
||||
{
|
||||
widget->connect(widget, &QDateTimeEdit::dateTimeChanged, func);
|
||||
}
|
||||
};
|
||||
|
||||
/// Binds a widget's value to a setting, updating it when the value changes.
|
||||
|
||||
template <typename WidgetType>
|
||||
|
@ -1239,4 +1260,106 @@ namespace SettingWidgetBinder
|
|||
|
||||
widget->connect(widget, &QLineEdit::editingFinished, widget, std::move(value_changed));
|
||||
}
|
||||
|
||||
// No need to pass a section or key since this is only used once and has six keys associated with it
|
||||
static inline void BindWidgetToDateTimeSetting(SettingsInterface* sif, QDateTimeEdit* widget)
|
||||
{
|
||||
using Accessor = SettingAccessor<QDateTimeEdit>;
|
||||
|
||||
int YEAR_OFFSET = 2000;
|
||||
int DEFAULT_YEAR = 0;
|
||||
int DEFAULT_MONTH = 1;
|
||||
int DEFAULT_DAY = 1;
|
||||
int DEFAULT_HOUR = 0;
|
||||
int DEFAULT_MINUTE = 0;
|
||||
int DEFAULT_SECOND = 0;
|
||||
|
||||
std::string SECTION = "EmuCore";
|
||||
std::string YEAR_KEY = "RtcYear";
|
||||
std::string MONTH_KEY = "RtcMonth";
|
||||
std::string DAY_KEY = "RtcDay";
|
||||
std::string HOUR_KEY = "RtcHour";
|
||||
std::string MINUTE_KEY = "RtcMinute";
|
||||
std::string SECOND_KEY = "RtcSecond";
|
||||
|
||||
// Fetch settings from .ini
|
||||
const s32 year_value =
|
||||
Host::GetBaseIntSettingValue(SECTION.c_str(), YEAR_KEY.c_str(), static_cast<s32>(DEFAULT_YEAR));
|
||||
const s32 month_value =
|
||||
Host::GetBaseIntSettingValue(SECTION.c_str(), MONTH_KEY.c_str(), static_cast<s32>(DEFAULT_MONTH));
|
||||
const s32 day_value =
|
||||
Host::GetBaseIntSettingValue(SECTION.c_str(), DAY_KEY.c_str(), static_cast<s32>(DEFAULT_DAY));
|
||||
const s32 hour_value =
|
||||
Host::GetBaseIntSettingValue(SECTION.c_str(), HOUR_KEY.c_str(), static_cast<s32>(DEFAULT_HOUR));
|
||||
const s32 minute_value =
|
||||
Host::GetBaseIntSettingValue(SECTION.c_str(), MINUTE_KEY.c_str(), static_cast<s32>(DEFAULT_MINUTE));
|
||||
const s32 second_value =
|
||||
Host::GetBaseIntSettingValue(SECTION.c_str(), SECOND_KEY.c_str(), static_cast<s32>(DEFAULT_SECOND));
|
||||
|
||||
if (sif)
|
||||
{
|
||||
int sif_year_value = DEFAULT_YEAR;
|
||||
int sif_month_value = DEFAULT_MONTH;
|
||||
int sif_day_value = DEFAULT_DAY;
|
||||
int sif_hour_value = DEFAULT_HOUR;
|
||||
int sif_minute_value = DEFAULT_MINUTE;
|
||||
int sif_second_value = DEFAULT_SECOND;
|
||||
|
||||
// Get Settings Interface values or default if that fails
|
||||
if (!sif->GetIntValue(SECTION.c_str(), YEAR_KEY.c_str(), &sif_year_value)) { sif_year_value = DEFAULT_YEAR; }
|
||||
if (!sif->GetIntValue(SECTION.c_str(), MONTH_KEY.c_str(), &sif_month_value)) { sif_month_value = DEFAULT_MONTH; }
|
||||
if (!sif->GetIntValue(SECTION.c_str(), DAY_KEY.c_str(), &sif_day_value)) { sif_day_value = DEFAULT_DAY; }
|
||||
if (!sif->GetIntValue(SECTION.c_str(), HOUR_KEY.c_str(), &sif_hour_value)) { sif_hour_value = DEFAULT_HOUR; }
|
||||
if (!sif->GetIntValue(SECTION.c_str(), MINUTE_KEY.c_str(), &sif_minute_value)) { sif_minute_value = DEFAULT_MINUTE; }
|
||||
if (!sif->GetIntValue(SECTION.c_str(), SECOND_KEY.c_str(), &sif_second_value)) { sif_second_value = DEFAULT_SECOND; }
|
||||
|
||||
// No need to check for valid date since QDateTime resets to minimum upon becoming invalid
|
||||
Accessor::setDateTime(widget, QDate(static_cast<int>(sif_year_value + YEAR_OFFSET), static_cast<int>(sif_month_value), static_cast<int>(sif_day_value)),
|
||||
QTime(static_cast<int>(sif_hour_value), static_cast<int>(sif_minute_value), static_cast<int>(sif_second_value)));
|
||||
|
||||
// Update the settings interface and reload the game settings when changed
|
||||
Accessor::connectValueChanged(widget, [sif, widget, SECTION = std::move(SECTION), YEAR_KEY = std::move(YEAR_KEY), MONTH_KEY = std::move(MONTH_KEY),
|
||||
DAY_KEY = std::move(DAY_KEY), HOUR_KEY = std::move(HOUR_KEY), MINUTE_KEY = std::move(MINUTE_KEY), SECOND_KEY = std::move(SECOND_KEY), YEAR_OFFSET = std::move(YEAR_OFFSET)]() {
|
||||
|
||||
sif->SetIntValue(SECTION.c_str(), YEAR_KEY.c_str(), Accessor::getYear(widget) - YEAR_OFFSET);
|
||||
sif->SetIntValue(SECTION.c_str(), MONTH_KEY.c_str(), Accessor::getMonth(widget));
|
||||
sif->SetIntValue(SECTION.c_str(), DAY_KEY.c_str(), Accessor::getDay(widget));
|
||||
sif->SetIntValue(SECTION.c_str(), HOUR_KEY.c_str(), Accessor::getHour(widget));
|
||||
sif->SetIntValue(SECTION.c_str(), MINUTE_KEY.c_str(), Accessor::getMinute(widget));
|
||||
sif->SetIntValue(SECTION.c_str(), SECOND_KEY.c_str(), Accessor::getSecond(widget));
|
||||
|
||||
QtHost::SaveGameSettings(sif, true);
|
||||
g_emu_thread->reloadGameSettings();
|
||||
});
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
// No need to check for valid date since QDateTime resets to minimum upon becoming invalid
|
||||
Accessor::setDateTime(widget, QDate(static_cast<int>(year_value + YEAR_OFFSET), static_cast<int>(month_value), static_cast<int>(day_value)),
|
||||
QTime(static_cast<int>(hour_value), static_cast<int>(minute_value), static_cast<int>(second_value)));
|
||||
|
||||
// Update and apply base settings with values from widget when user changes it in UI
|
||||
Accessor::connectValueChanged(widget, [widget, SECTION = std::move(SECTION), YEAR_KEY = std::move(YEAR_KEY), MONTH_KEY = std::move(MONTH_KEY),
|
||||
DAY_KEY = std::move(DAY_KEY), HOUR_KEY = std::move(HOUR_KEY), MINUTE_KEY = std::move(MINUTE_KEY), SECOND_KEY = std::move(SECOND_KEY), YEAR_OFFSET = std::move(YEAR_OFFSET)]() {
|
||||
|
||||
const int new_year_value = Accessor::getYear(widget);
|
||||
const int new_month_value = Accessor::getMonth(widget);
|
||||
const int new_day_value = Accessor::getDay(widget);
|
||||
const int new_hour_value = Accessor::getHour(widget);
|
||||
const int new_minute_value = Accessor::getMinute(widget);
|
||||
const int new_second_value = Accessor::getSecond(widget);
|
||||
|
||||
Host::SetBaseIntSettingValue(SECTION.c_str(), YEAR_KEY.c_str(), new_year_value - YEAR_OFFSET);
|
||||
Host::SetBaseIntSettingValue(SECTION.c_str(), MONTH_KEY.c_str(), new_month_value);
|
||||
Host::SetBaseIntSettingValue(SECTION.c_str(), DAY_KEY.c_str(), new_day_value);
|
||||
Host::SetBaseIntSettingValue(SECTION.c_str(), HOUR_KEY.c_str(), new_hour_value);
|
||||
Host::SetBaseIntSettingValue(SECTION.c_str(), MINUTE_KEY.c_str(), new_minute_value);
|
||||
Host::SetBaseIntSettingValue(SECTION.c_str(), SECOND_KEY.c_str(), new_second_value);
|
||||
Host::CommitBaseSettingChanges();
|
||||
g_emu_thread->applySettings();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace SettingWidgetBinder
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team
|
||||
// SPDX-FileCopyrightText: 2002-2025 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#include <QtWidgets/QInputDialog>
|
||||
|
@ -48,6 +48,12 @@ EmulationSettingsWidget::EmulationSettingsWidget(SettingsWindow* dialog, QWidget
|
|||
|
||||
if (m_dialog->isPerGameSettings())
|
||||
{
|
||||
SettingWidgetBinder::BindWidgetToDateTimeSetting(sif, m_ui.rtcDateTime);
|
||||
m_ui.rtcDateTime->setDateRange(QDate(2000, 1, 1), QDate(2099, 12, 31));
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.manuallySetRealTimeClock, "EmuCore", "ManuallySetRealTimeClock", false);
|
||||
connect(m_ui.manuallySetRealTimeClock, &QCheckBox::checkStateChanged, this, &EmulationSettingsWidget::onManuallySetRealTimeClockChanged);
|
||||
EmulationSettingsWidget::onManuallySetRealTimeClockChanged();
|
||||
|
||||
m_ui.eeCycleRate->insertItem(
|
||||
0, tr("Use Global Setting [%1]")
|
||||
.arg(m_ui.eeCycleRate->itemText(
|
||||
|
@ -74,6 +80,8 @@ EmulationSettingsWidget::EmulationSettingsWidget(SettingsWindow* dialog, QWidget
|
|||
}
|
||||
else
|
||||
{
|
||||
m_ui.rtcGroup->hide();
|
||||
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.cheats, "EmuCore", "EnableCheats", false);
|
||||
|
||||
// Allow for FastCDVD for per-game settings only
|
||||
|
@ -146,6 +154,11 @@ EmulationSettingsWidget::EmulationSettingsWidget(SettingsWindow* dialog, QWidget
|
|||
dialog->registerWidgetHelp(m_ui.useVSyncForTiming, tr("Use Host VSync Timing"), tr("Unchecked"),
|
||||
tr("When synchronizing with the host refresh rate, this option disable's PCSX2's internal frame timing, and uses the host instead. "
|
||||
"Can result in smoother frame pacing, <strong>but at the cost of increased input latency</strong>."));
|
||||
dialog->registerWidgetHelp(m_ui.manuallySetRealTimeClock, tr("Manually Set Real-Time Clock"), tr("Unchecked"),
|
||||
tr("Manually set a real-time clock to use for the virtual PlayStation 2 instead of using your OS' system clock."));
|
||||
dialog->registerWidgetHelp(m_ui.rtcDateTime, tr("Real-Time Clock"), tr("Current date and time"),
|
||||
tr("Real-time clock (RTC) used by the virtual PlayStation 2. NOTE: This assumes you have your PS2 set to the default timezone of GMT+0 and default DST of Summer Time. "
|
||||
"Some games require an RTC date/time set after their release date."));
|
||||
|
||||
updateOptimalFramePacing();
|
||||
updateUseVSyncForTimingEnabled();
|
||||
|
@ -292,3 +305,9 @@ void EmulationSettingsWidget::updateUseVSyncForTimingEnabled()
|
|||
const bool sync_to_host_refresh = m_dialog->getEffectiveBoolValue("EmuCore/GS", "SyncToHostRefreshRate", false);
|
||||
m_ui.useVSyncForTiming->setEnabled(vsync && sync_to_host_refresh);
|
||||
}
|
||||
|
||||
void EmulationSettingsWidget::onManuallySetRealTimeClockChanged()
|
||||
{
|
||||
const bool enabled = m_dialog->getEffectiveBoolValue("EmuCore", "ManuallySetRealTimeClock", false);
|
||||
m_ui.rtcDateTime->setEnabled(enabled);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team
|
||||
// SPDX-FileCopyrightText: 2002-2025 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#pragma once
|
||||
|
@ -25,6 +25,7 @@ private:
|
|||
void handleSpeedComboChange(QComboBox* cb, const char* section, const char* key);
|
||||
void updateOptimalFramePacing();
|
||||
void updateUseVSyncForTimingEnabled();
|
||||
void onManuallySetRealTimeClockChanged();
|
||||
|
||||
SettingsWindow* m_dialog;
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_5">
|
||||
<widget class="QGroupBox" name="speedGroup">
|
||||
<property name="title">
|
||||
<string>Speed Control</string>
|
||||
</property>
|
||||
|
@ -195,7 +195,7 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="basicGroupBox">
|
||||
<widget class="QGroupBox" name="pacingGroup">
|
||||
<property name="title">
|
||||
<string>Frame Pacing / Latency Control</string>
|
||||
</property>
|
||||
|
@ -268,6 +268,26 @@
|
|||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="rtcGroup">
|
||||
<property name="title">
|
||||
<string>Real-Time Clock</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayoutRTC">
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="manuallySetRealTimeClock">
|
||||
<property name="text">
|
||||
<string>Manually Set Real-Time Clock</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QDateTimeEdit" name="rtcDateTime">
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team
|
||||
// SPDX-FileCopyrightText: 2002-2025 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#include "CDVD/CDVD.h"
|
||||
|
@ -28,6 +28,9 @@
|
|||
|
||||
#include <cctype>
|
||||
#include <ctime>
|
||||
#ifndef _WIN32
|
||||
#include <time.h>
|
||||
#endif
|
||||
#include <memory>
|
||||
|
||||
cdvdStruct cdvd;
|
||||
|
@ -917,9 +920,38 @@ void cdvdReset()
|
|||
cdvd.ReadTime = cdvdBlockReadTime(MODE_DVDROM);
|
||||
cdvd.RotSpeed = cdvdRotationTime(MODE_DVDROM);
|
||||
|
||||
if (EmuConfig.ManuallySetRealTimeClock)
|
||||
{
|
||||
// Convert to GMT+9 (assumes GMT+0)
|
||||
std::tm tm{};
|
||||
tm.tm_sec = EmuConfig.RtcSecond;
|
||||
tm.tm_min = EmuConfig.RtcMinute;
|
||||
tm.tm_hour = EmuConfig.RtcHour;
|
||||
tm.tm_mday = EmuConfig.RtcDay;
|
||||
tm.tm_mon = EmuConfig.RtcMonth - 1;
|
||||
tm.tm_year = EmuConfig.RtcYear + 100; // 2000 - 1900
|
||||
tm.tm_isdst = 1;
|
||||
|
||||
// Need this instead of mktime for timezone independence
|
||||
std::time_t t = 0;
|
||||
#if defined(_WIN32)
|
||||
t = _mkgmtime(&tm) + 32400; //60 * 60 * 9 for GMT+9
|
||||
gmtime_s(&tm, &t);
|
||||
#else
|
||||
t = timegm(&tm) + 32400;
|
||||
gmtime_r(&t, &tm);
|
||||
#endif
|
||||
|
||||
cdvd.RTC.second = tm.tm_sec;
|
||||
cdvd.RTC.minute = tm.tm_min;
|
||||
cdvd.RTC.hour = tm.tm_hour;
|
||||
cdvd.RTC.day = tm.tm_mday;
|
||||
cdvd.RTC.month = tm.tm_mon + 1;
|
||||
cdvd.RTC.year = tm.tm_year - 100;
|
||||
}
|
||||
// If we are recording, always use the same RTC setting
|
||||
// for games that use the RTC to seed their RNG -- this is very important to be the same everytime!
|
||||
if (g_InputRecording.isActive())
|
||||
else if (g_InputRecording.isActive())
|
||||
{
|
||||
Console.WriteLn("Input Recording Active - Using Constant RTC of 04-03-2020 (DD-MM-YYYY)");
|
||||
// Why not just 0 everything? Some games apparently require the date to be valid in terms of when
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team
|
||||
// SPDX-FileCopyrightText: 2002-2025 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#pragma once
|
||||
|
@ -1282,6 +1282,7 @@ struct Pcsx2Config
|
|||
InhibitScreensaver : 1,
|
||||
BackupSavestate : 1,
|
||||
McdFolderAutoManage : 1,
|
||||
ManuallySetRealTimeClock : 1,
|
||||
|
||||
HostFs : 1,
|
||||
|
||||
|
@ -1315,6 +1316,13 @@ struct Pcsx2Config
|
|||
|
||||
int PINESlot;
|
||||
|
||||
int RtcYear = 0;
|
||||
int RtcMonth = 1;
|
||||
int RtcDay = 1;
|
||||
int RtcHour = 0;
|
||||
int RtcMinute = 0;
|
||||
int RtcSecond = 0;
|
||||
|
||||
// Set at runtime, not loaded from config.
|
||||
std::string CurrentBlockdump;
|
||||
std::string CurrentIRX;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team
|
||||
// SPDX-FileCopyrightText: 2002-2025 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#include "common/CocoaTools.h"
|
||||
|
@ -1898,6 +1898,7 @@ Pcsx2Config::Pcsx2Config()
|
|||
InhibitScreensaver = true;
|
||||
BackupSavestate = true;
|
||||
WarnAboutUnsafeSettings = true;
|
||||
ManuallySetRealTimeClock = false;
|
||||
|
||||
// To be moved to FileMemoryCard pluign (someday)
|
||||
for (uint slot = 0; slot < 8; ++slot)
|
||||
|
@ -1910,6 +1911,12 @@ Pcsx2Config::Pcsx2Config()
|
|||
|
||||
GzipIsoIndexTemplate = "$(f).pindex.tmp";
|
||||
PINESlot = 28011;
|
||||
RtcYear = 0;
|
||||
RtcMonth = 1;
|
||||
RtcDay = 1;
|
||||
RtcHour = 0;
|
||||
RtcMinute = 0;
|
||||
RtcSecond = 0;
|
||||
}
|
||||
|
||||
void Pcsx2Config::LoadSaveCore(SettingsWrapper& wrap)
|
||||
|
@ -1940,6 +1947,8 @@ void Pcsx2Config::LoadSaveCore(SettingsWrapper& wrap)
|
|||
|
||||
SettingsWrapBitBool(WarnAboutUnsafeSettings);
|
||||
|
||||
SettingsWrapBitBool(ManuallySetRealTimeClock);
|
||||
|
||||
// Process various sub-components:
|
||||
|
||||
Speedhacks.LoadSave(wrap);
|
||||
|
@ -1959,6 +1968,12 @@ void Pcsx2Config::LoadSaveCore(SettingsWrapper& wrap)
|
|||
|
||||
SettingsWrapEntry(GzipIsoIndexTemplate);
|
||||
SettingsWrapEntry(PINESlot);
|
||||
SettingsWrapEntry(RtcYear);
|
||||
SettingsWrapEntry(RtcMonth);
|
||||
SettingsWrapEntry(RtcDay);
|
||||
SettingsWrapEntry(RtcHour);
|
||||
SettingsWrapEntry(RtcMinute);
|
||||
SettingsWrapEntry(RtcSecond);
|
||||
|
||||
// For now, this in the derived config for backwards ini compatibility.
|
||||
SettingsWrapEntryEx(CurrentBlockdump, "BlockDumpSaveDirectory");
|
||||
|
|
|
@ -93,19 +93,19 @@ namespace usb_pad
|
|||
u8 right_turntable = 0x80;
|
||||
if (data.left_turntable_ccw > 0)
|
||||
{
|
||||
left_turntable -= static_cast<u8>(std::min<int>(data.left_turntable_ccw * turntable_multiplier, 0x7F));
|
||||
left_turntable -= static_cast<u8>(std::min<int>(data.left_turntable_ccw, 0x7F));
|
||||
}
|
||||
else
|
||||
{
|
||||
left_turntable += static_cast<u8>(std::min<int>(data.left_turntable_cw * turntable_multiplier, 0x7F));
|
||||
left_turntable += static_cast<u8>(std::min<int>(data.left_turntable_cw, 0x7F));
|
||||
}
|
||||
if (data.right_turntable_ccw > 0)
|
||||
{
|
||||
right_turntable -= static_cast<u8>(std::min<int>(data.right_turntable_ccw * turntable_multiplier, 0x7F));
|
||||
right_turntable -= static_cast<u8>(std::min<int>(data.right_turntable_ccw, 0x7F));
|
||||
}
|
||||
else
|
||||
{
|
||||
right_turntable += static_cast<u8>(std::min<int>(data.right_turntable_cw * turntable_multiplier, 0x7F));
|
||||
right_turntable += static_cast<u8>(std::min<int>(data.right_turntable_cw, 0x7F));
|
||||
}
|
||||
buf[3] = 0x80;
|
||||
buf[4] = 0x80;
|
||||
|
@ -369,19 +369,19 @@ namespace usb_pad
|
|||
break;
|
||||
|
||||
case CID_DJ_LEFT_TURNTABLE_CW:
|
||||
s->data.left_turntable_cw = static_cast<u32>(std::clamp<long>(std::lroundf(value * 128.0f), 0, 128));
|
||||
s->data.left_turntable_cw = static_cast<u32>(std::clamp<long>(std::lroundf(value * s->turntable_multiplier * 128.0f), 0, 128));
|
||||
break;
|
||||
|
||||
case CID_DJ_LEFT_TURNTABLE_CCW:
|
||||
s->data.left_turntable_ccw = static_cast<u32>(std::clamp<long>(std::lroundf(value * 128.0f), 0, 128));
|
||||
s->data.left_turntable_ccw = static_cast<u32>(std::clamp<long>(std::lroundf(value * s->turntable_multiplier * 128.0f), 0, 128));
|
||||
break;
|
||||
|
||||
case CID_DJ_RIGHT_TURNTABLE_CW:
|
||||
s->data.right_turntable_cw = static_cast<u32>(std::clamp<long>(std::lroundf(value * 128.0f), 0, 128));
|
||||
s->data.right_turntable_cw = static_cast<u32>(std::clamp<long>(std::lroundf(value * s->turntable_multiplier * 128.0f), 0, 128));
|
||||
break;
|
||||
|
||||
case CID_DJ_RIGHT_TURNTABLE_CCW:
|
||||
s->data.right_turntable_ccw = static_cast<u32>(std::clamp<long>(std::lroundf(value * 128.0f), 0, 128));
|
||||
s->data.right_turntable_ccw = static_cast<u32>(std::clamp<long>(std::lroundf(value * s->turntable_multiplier * 128.0f), 0, 128));
|
||||
break;
|
||||
|
||||
case CID_DJ_DPAD_UP:
|
||||
|
@ -446,8 +446,8 @@ namespace usb_pad
|
|||
{"EffectsKnobRight", TRANSLATE_NOOP("USB", "Effects Knob Right"), nullptr, InputBindingInfo::Type::HalfAxis, CID_DJ_EFFECTSKNOB_RIGHT, GenericInputBinding::RightStickRight},
|
||||
{"LeftTurntableCW", TRANSLATE_NOOP("USB", "Left Turntable Clockwise"), nullptr, InputBindingInfo::Type::HalfAxis, CID_DJ_LEFT_TURNTABLE_CW, GenericInputBinding::LeftStickRight},
|
||||
{"LeftTurntableCCW", TRANSLATE_NOOP("USB", "Left Turntable Counterclockwise"), nullptr, InputBindingInfo::Type::HalfAxis, CID_DJ_LEFT_TURNTABLE_CCW, GenericInputBinding::LeftStickLeft},
|
||||
{"RightTurntableCW", TRANSLATE_NOOP("USB", "Right Turntable Clockwise"), nullptr, InputBindingInfo::Type::HalfAxis, CID_DJ_RIGHT_TURNTABLE_CW, GenericInputBinding::LeftStickDown},
|
||||
{"RightTurntableCCW", TRANSLATE_NOOP("USB", "Right Turntable Counterclockwise"), nullptr, InputBindingInfo::Type::HalfAxis, CID_DJ_RIGHT_TURNTABLE_CCW, GenericInputBinding::LeftStickUp},
|
||||
{"RightTurntableCW", TRANSLATE_NOOP("USB", "Right Turntable Clockwise"), nullptr, InputBindingInfo::Type::HalfAxis, CID_DJ_RIGHT_TURNTABLE_CW, GenericInputBinding::LeftStickUp},
|
||||
{"RightTurntableCCW", TRANSLATE_NOOP("USB", "Right Turntable Counterclockwise"), nullptr, InputBindingInfo::Type::HalfAxis, CID_DJ_RIGHT_TURNTABLE_CCW, GenericInputBinding::LeftStickDown},
|
||||
{"LeftTurntableGreen", TRANSLATE_NOOP("USB", "Left Turntable Green"), nullptr, InputBindingInfo::Type::Button, CID_DJ_LEFT_GREEN, GenericInputBinding::Unknown},
|
||||
{"LeftTurntableRed", TRANSLATE_NOOP("USB", "Left Turntable Red"), nullptr, InputBindingInfo::Type::Button, CID_DJ_LEFT_RED, GenericInputBinding::Unknown},
|
||||
{"LeftTurntableBlue", TRANSLATE_NOOP("USB", "Left Turntable Blue"), nullptr, InputBindingInfo::Type::Button, CID_DJ_LEFT_BLUE, GenericInputBinding::Unknown},
|
||||
|
@ -464,8 +464,8 @@ namespace usb_pad
|
|||
{
|
||||
static constexpr const SettingInfo info[] = {
|
||||
{SettingInfo::Type::Float, "TurntableMultiplier", TRANSLATE_NOOP("USB", "Turntable Multiplier"),
|
||||
TRANSLATE_NOOP("USB", "Apply a multiplier to the turntable"),
|
||||
"1.00", "0.00", "100.0", "1.0", "%.0fx", nullptr, nullptr, 1.0f}};
|
||||
TRANSLATE_NOOP("USB", "Apply a sensitivity multiplier to turntable rotation.\nXbox 360 turntables require a 256x multiplier, most other turntables can use the default 1x multiplier."),
|
||||
"1.00", "0.00", "512.0", "1.0", "%.0fx", nullptr, nullptr, 1.0f}};
|
||||
|
||||
return info;
|
||||
}
|
||||
|
|
|
@ -2561,6 +2561,11 @@ void VMManager::InitializeCPUProviders()
|
|||
|
||||
CpuMicroVU0.Reserve();
|
||||
CpuMicroVU1.Reserve();
|
||||
#else
|
||||
// Despite not having any VU recompilers on ARM64, therefore no MTVU,
|
||||
// we still need the thread alive. Otherwise the read and write positions
|
||||
// of the ring buffer wont match, and various systems in the emulator end up deadlocked.
|
||||
vu1Thread.Open();
|
||||
#endif
|
||||
|
||||
VifUnpackSSE_Init();
|
||||
|
@ -2580,6 +2585,11 @@ void VMManager::ShutdownCPUProviders()
|
|||
|
||||
psxRec.Shutdown();
|
||||
recCpu.Shutdown();
|
||||
#else
|
||||
// See the comment in the InitializeCPUProviders for an explaination why we
|
||||
// still need to manage the MTVU thread.
|
||||
if(vu1Thread.IsOpen())
|
||||
vu1Thread.WaitVU();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
|
||||
#include "common/Console.h"
|
||||
#include "MTVU.h"
|
||||
#include "SaveState.h"
|
||||
#include "vtlb.h"
|
||||
|
||||
|
@ -13,6 +15,16 @@ void vtlb_DynBackpatchLoadStore(uptr code_address, u32 code_size, u32 guest_pc,
|
|||
|
||||
bool SaveStateBase::vuJITFreeze()
|
||||
{
|
||||
pxFailRel("Not implemented.");
|
||||
return false;
|
||||
if(IsSaving())
|
||||
vu1Thread.WaitVU();
|
||||
|
||||
Console.Warning("recompiler state is stubbed in arm64!");
|
||||
|
||||
// HACK!!
|
||||
|
||||
// size of microRegInfo structure
|
||||
std::array<u8,96> empty_data{};
|
||||
Freeze(empty_data);
|
||||
Freeze(empty_data);
|
||||
return true;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue