early-access version 3920
This commit is contained in:
parent
9d6e12aaf3
commit
c7233d4856
11 changed files with 239 additions and 9 deletions
|
@ -1,7 +1,7 @@
|
|||
yuzu emulator early access
|
||||
=============
|
||||
|
||||
This is the source code for early-access 3916.
|
||||
This is the source code for early-access 3920.
|
||||
|
||||
## Legal Notice
|
||||
|
||||
|
|
4
dist/qt_themes/default/style.qss
vendored
4
dist/qt_themes/default/style.qss
vendored
|
@ -120,6 +120,10 @@ QWidget#connectedControllers {
|
|||
background: transparent;
|
||||
}
|
||||
|
||||
QWidget#closeButtons {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
QWidget#playersSupported,
|
||||
QWidget#controllersSupported,
|
||||
QWidget#controllerSupported1,
|
||||
|
|
4
dist/qt_themes/qdarkstyle/style.qss
vendored
4
dist/qt_themes/qdarkstyle/style.qss
vendored
|
@ -1380,6 +1380,10 @@ QWidget#connectedControllers {
|
|||
background: transparent;
|
||||
}
|
||||
|
||||
QWidget#closeButtons {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
QWidget#playersSupported,
|
||||
QWidget#controllersSupported,
|
||||
QWidget#controllerSupported1,
|
||||
|
|
|
@ -2305,6 +2305,10 @@ QWidget#connectedControllers {
|
|||
background: transparent;
|
||||
}
|
||||
|
||||
QWidget#closeButtons {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
QWidget#playersSupported,
|
||||
QWidget#controllersSupported,
|
||||
QWidget#controllerSupported1,
|
||||
|
|
|
@ -189,6 +189,14 @@ if(ARCHITECTURE_x86_64)
|
|||
target_link_libraries(common PRIVATE xbyak::xbyak)
|
||||
endif()
|
||||
|
||||
if (ARCHITECTURE_arm64 AND (ANDROID OR LINUX))
|
||||
target_sources(common
|
||||
PRIVATE
|
||||
arm64/native_clock.cpp
|
||||
arm64/native_clock.h
|
||||
)
|
||||
endif()
|
||||
|
||||
if (MSVC)
|
||||
target_compile_definitions(common PRIVATE
|
||||
# The standard library doesn't provide any replacement for codecvt yet
|
||||
|
|
72
src/common/arm64/native_clock.cpp
Executable file
72
src/common/arm64/native_clock.cpp
Executable file
|
@ -0,0 +1,72 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/arm64/native_clock.h"
|
||||
|
||||
namespace Common::Arm64 {
|
||||
|
||||
namespace {
|
||||
|
||||
NativeClock::FactorType GetFixedPointFactor(u64 num, u64 den) {
|
||||
return (static_cast<NativeClock::FactorType>(num) << 64) / den;
|
||||
}
|
||||
|
||||
u64 MultiplyHigh(u64 m, NativeClock::FactorType factor) {
|
||||
return static_cast<u64>((m * factor) >> 64);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NativeClock::NativeClock() {
|
||||
const u64 host_cntfrq = GetHostCNTFRQ();
|
||||
ns_cntfrq_factor = GetFixedPointFactor(NsRatio::den, host_cntfrq);
|
||||
us_cntfrq_factor = GetFixedPointFactor(UsRatio::den, host_cntfrq);
|
||||
ms_cntfrq_factor = GetFixedPointFactor(MsRatio::den, host_cntfrq);
|
||||
guest_cntfrq_factor = GetFixedPointFactor(CNTFRQ, host_cntfrq);
|
||||
gputick_cntfrq_factor = GetFixedPointFactor(GPUTickFreq, host_cntfrq);
|
||||
}
|
||||
|
||||
std::chrono::nanoseconds NativeClock::GetTimeNS() const {
|
||||
return std::chrono::nanoseconds{MultiplyHigh(GetHostTicksElapsed(), ns_cntfrq_factor)};
|
||||
}
|
||||
|
||||
std::chrono::microseconds NativeClock::GetTimeUS() const {
|
||||
return std::chrono::microseconds{MultiplyHigh(GetHostTicksElapsed(), us_cntfrq_factor)};
|
||||
}
|
||||
|
||||
std::chrono::milliseconds NativeClock::GetTimeMS() const {
|
||||
return std::chrono::milliseconds{MultiplyHigh(GetHostTicksElapsed(), ms_cntfrq_factor)};
|
||||
}
|
||||
|
||||
u64 NativeClock::GetCNTPCT() const {
|
||||
return MultiplyHigh(GetHostTicksElapsed(), guest_cntfrq_factor);
|
||||
}
|
||||
|
||||
u64 NativeClock::GetGPUTick() const {
|
||||
return MultiplyHigh(GetHostTicksElapsed(), gputick_cntfrq_factor);
|
||||
}
|
||||
|
||||
u64 NativeClock::GetHostTicksNow() const {
|
||||
u64 cntvct_el0 = 0;
|
||||
asm volatile("dsb ish\n\t"
|
||||
"mrs %[cntvct_el0], cntvct_el0\n\t"
|
||||
"dsb ish\n\t"
|
||||
: [cntvct_el0] "=r"(cntvct_el0));
|
||||
return cntvct_el0;
|
||||
}
|
||||
|
||||
u64 NativeClock::GetHostTicksElapsed() const {
|
||||
return GetHostTicksNow();
|
||||
}
|
||||
|
||||
bool NativeClock::IsNative() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
u64 NativeClock::GetHostCNTFRQ() {
|
||||
u64 cntfrq_el0 = 0;
|
||||
asm("mrs %[cntfrq_el0], cntfrq_el0" : [cntfrq_el0] "=r"(cntfrq_el0));
|
||||
return cntfrq_el0;
|
||||
}
|
||||
|
||||
} // namespace Common::Arm64
|
47
src/common/arm64/native_clock.h
Executable file
47
src/common/arm64/native_clock.h
Executable file
|
@ -0,0 +1,47 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/wall_clock.h"
|
||||
|
||||
namespace Common::Arm64 {
|
||||
|
||||
class NativeClock final : public WallClock {
|
||||
public:
|
||||
explicit NativeClock();
|
||||
|
||||
std::chrono::nanoseconds GetTimeNS() const override;
|
||||
|
||||
std::chrono::microseconds GetTimeUS() const override;
|
||||
|
||||
std::chrono::milliseconds GetTimeMS() const override;
|
||||
|
||||
u64 GetCNTPCT() const override;
|
||||
|
||||
u64 GetGPUTick() const override;
|
||||
|
||||
u64 GetHostTicksNow() const override;
|
||||
|
||||
u64 GetHostTicksElapsed() const override;
|
||||
|
||||
bool IsNative() const override;
|
||||
|
||||
static u64 GetHostCNTFRQ();
|
||||
|
||||
public:
|
||||
using FactorType = unsigned __int128;
|
||||
|
||||
FactorType GetGuestCNTFRQFactor() const {
|
||||
return guest_cntfrq_factor;
|
||||
}
|
||||
|
||||
private:
|
||||
FactorType ns_cntfrq_factor;
|
||||
FactorType us_cntfrq_factor;
|
||||
FactorType ms_cntfrq_factor;
|
||||
FactorType guest_cntfrq_factor;
|
||||
FactorType gputick_cntfrq_factor;
|
||||
};
|
||||
|
||||
} // namespace Common::Arm64
|
|
@ -10,6 +10,10 @@
|
|||
#include "common/x64/rdtsc.h"
|
||||
#endif
|
||||
|
||||
#if defined(ARCHITECTURE_arm64) && defined(__linux__)
|
||||
#include "common/arm64/native_clock.h"
|
||||
#endif
|
||||
|
||||
namespace Common {
|
||||
|
||||
class StandardWallClock final : public WallClock {
|
||||
|
@ -53,7 +57,7 @@ private:
|
|||
};
|
||||
|
||||
std::unique_ptr<WallClock> CreateOptimalClock() {
|
||||
#ifdef ARCHITECTURE_x86_64
|
||||
#if defined(ARCHITECTURE_x86_64)
|
||||
const auto& caps = GetCPUCaps();
|
||||
|
||||
if (caps.invariant_tsc && caps.tsc_frequency >= std::nano::den) {
|
||||
|
@ -64,6 +68,8 @@ std::unique_ptr<WallClock> CreateOptimalClock() {
|
|||
// - Is not more precise than 1 GHz (1ns resolution)
|
||||
return std::make_unique<StandardWallClock>();
|
||||
}
|
||||
#elif defined(ARCHITECTURE_arm64) && defined(__linux__)
|
||||
return std::make_unique<Arm64::NativeClock>();
|
||||
#else
|
||||
return std::make_unique<StandardWallClock>();
|
||||
#endif
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "yuzu/configuration/configure_vibration.h"
|
||||
#include "yuzu/configuration/input_profiles.h"
|
||||
#include "yuzu/main.h"
|
||||
#include "yuzu/util/controller_navigation.h"
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -132,6 +133,8 @@ QtControllerSelectorDialog::QtControllerSelectorDialog(
|
|||
ui->checkboxPlayer7Connected, ui->checkboxPlayer8Connected,
|
||||
};
|
||||
|
||||
ui->labelError->setVisible(false);
|
||||
|
||||
// Setup/load everything prior to setting up connections.
|
||||
// This avoids unintentionally changing the states of elements while loading them in.
|
||||
SetSupportedControllers();
|
||||
|
@ -143,6 +146,8 @@ QtControllerSelectorDialog::QtControllerSelectorDialog(
|
|||
|
||||
LoadConfiguration();
|
||||
|
||||
controller_navigation = new ControllerNavigation(system.HIDCore(), this);
|
||||
|
||||
for (std::size_t i = 0; i < NUM_PLAYERS; ++i) {
|
||||
SetExplainText(i);
|
||||
UpdateControllerIcon(i);
|
||||
|
@ -151,6 +156,8 @@ QtControllerSelectorDialog::QtControllerSelectorDialog(
|
|||
|
||||
connect(player_groupboxes[i], &QGroupBox::toggled, [this, i](bool checked) {
|
||||
if (checked) {
|
||||
// Hide eventual error message about number of controllers
|
||||
ui->labelError->setVisible(false);
|
||||
for (std::size_t index = 0; index <= i; ++index) {
|
||||
connected_controller_checkboxes[index]->setChecked(checked);
|
||||
}
|
||||
|
@ -199,6 +206,12 @@ QtControllerSelectorDialog::QtControllerSelectorDialog(
|
|||
connect(ui->buttonBox, &QDialogButtonBox::accepted, this,
|
||||
&QtControllerSelectorDialog::ApplyConfiguration);
|
||||
|
||||
connect(controller_navigation, &ControllerNavigation::TriggerKeyboardEvent,
|
||||
[this](Qt::Key key) {
|
||||
QKeyEvent* event = new QKeyEvent(QEvent::KeyPress, key, Qt::NoModifier);
|
||||
QCoreApplication::postEvent(this, event);
|
||||
});
|
||||
|
||||
// Enhancement: Check if the parameters have already been met before disconnecting controllers.
|
||||
// If all the parameters are met AND only allows a single player,
|
||||
// stop the constructor here as we do not need to continue.
|
||||
|
@ -217,6 +230,7 @@ QtControllerSelectorDialog::QtControllerSelectorDialog(
|
|||
}
|
||||
|
||||
QtControllerSelectorDialog::~QtControllerSelectorDialog() {
|
||||
controller_navigation->UnloadController();
|
||||
system.HIDCore().DisableAllControllerConfiguration();
|
||||
}
|
||||
|
||||
|
@ -291,6 +305,31 @@ void QtControllerSelectorDialog::CallConfigureInputProfileDialog() {
|
|||
dialog.exec();
|
||||
}
|
||||
|
||||
void QtControllerSelectorDialog::keyPressEvent(QKeyEvent* evt) {
|
||||
const auto num_connected_players = static_cast<int>(
|
||||
std::count_if(player_groupboxes.begin(), player_groupboxes.end(),
|
||||
[](const QGroupBox* player) { return player->isChecked(); }));
|
||||
|
||||
const auto min_supported_players = parameters.enable_single_mode ? 1 : parameters.min_players;
|
||||
const auto max_supported_players = parameters.enable_single_mode ? 1 : parameters.max_players;
|
||||
|
||||
if ((evt->key() == Qt::Key_Enter || evt->key() == Qt::Key_Return) && !parameters_met) {
|
||||
// Display error message when trying to validate using "Enter" and "OK" button is disabled
|
||||
ui->labelError->setVisible(true);
|
||||
return;
|
||||
} else if (evt->key() == Qt::Key_Left && num_connected_players > min_supported_players) {
|
||||
// Remove a player if possible
|
||||
connected_controller_checkboxes[num_connected_players - 1]->setChecked(false);
|
||||
return;
|
||||
} else if (evt->key() == Qt::Key_Right && num_connected_players < max_supported_players) {
|
||||
// Add a player, if possible
|
||||
ui->labelError->setVisible(false);
|
||||
connected_controller_checkboxes[num_connected_players]->setChecked(true);
|
||||
return;
|
||||
}
|
||||
QDialog::keyPressEvent(evt);
|
||||
}
|
||||
|
||||
bool QtControllerSelectorDialog::CheckIfParametersMet() {
|
||||
// Here, we check and validate the current configuration against all applicable parameters.
|
||||
const auto num_connected_players = static_cast<int>(
|
||||
|
|
|
@ -34,6 +34,8 @@ class HIDCore;
|
|||
enum class NpadStyleIndex : u8;
|
||||
} // namespace Core::HID
|
||||
|
||||
class ControllerNavigation;
|
||||
|
||||
class QtControllerSelectorDialog final : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -46,6 +48,8 @@ public:
|
|||
|
||||
int exec() override;
|
||||
|
||||
void keyPressEvent(QKeyEvent* evt) override;
|
||||
|
||||
private:
|
||||
// Applies the current configuration.
|
||||
void ApplyConfiguration();
|
||||
|
@ -110,6 +114,8 @@ private:
|
|||
|
||||
Core::System& system;
|
||||
|
||||
ControllerNavigation* controller_navigation = nullptr;
|
||||
|
||||
// This is true if and only if all parameters are met. Otherwise, this is false.
|
||||
// This determines whether the "OK" button can be clicked to exit the applet.
|
||||
bool parameters_met{false};
|
||||
|
|
|
@ -2624,6 +2624,43 @@
|
|||
</spacer>
|
||||
</item>
|
||||
<item alignment="Qt::AlignBottom">
|
||||
<widget class="QWidget" name="closeButtons" native="true">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_46">
|
||||
<property name="spacing">
|
||||
<number>7</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelError">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QLabel { color : red; }</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Not enough controllers</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
|
@ -2641,6 +2678,9 @@
|
|||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
|
|
Loading…
Reference in a new issue