Compare commits
1 Commits
__refs_pul
...
__refs_pul
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8832446730 |
@@ -11,7 +11,6 @@ ccache -s
|
||||
mkdir build || true && cd build
|
||||
cmake .. \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_CXX_FLAGS="-march=x86-64-v2" \
|
||||
-DCMAKE_CXX_COMPILER=/usr/lib/ccache/clang++ \
|
||||
-DCMAKE_C_COMPILER=/usr/lib/ccache/clang \
|
||||
-DCMAKE_INSTALL_PREFIX="/usr" \
|
||||
|
||||
@@ -12,7 +12,6 @@ mkdir build || true && cd build
|
||||
cmake .. \
|
||||
-DBoost_USE_STATIC_LIBS=ON \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_CXX_FLAGS="-march=x86-64-v2" \
|
||||
-DCMAKE_CXX_COMPILER=/usr/lib/ccache/g++ \
|
||||
-DCMAKE_C_COMPILER=/usr/lib/ccache/gcc \
|
||||
-DCMAKE_INSTALL_PREFIX="/usr" \
|
||||
|
||||
@@ -9,7 +9,7 @@ parameters:
|
||||
steps:
|
||||
- script: choco install vulkan-sdk
|
||||
displayName: 'Install vulkan-sdk'
|
||||
- script: refreshenv && mkdir build && cd build && cmake -E env CXXFLAGS="/Gw /GA /Gr /Ob2" cmake -G "Visual Studio 17 2022" -A x64 -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON -DCMAKE_POLICY_DEFAULT_CMP0069=NEW -DYUZU_USE_BUNDLED_QT=1 -DYUZU_USE_BUNDLED_SDL2=1 -DYUZU_USE_QT_WEB_ENGINE=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${COMPAT} -DYUZU_TESTS=OFF -DUSE_DISCORD_PRESENCE=ON -DENABLE_QT_TRANSLATION=ON -DDISPLAY_VERSION=${{ parameters['version'] }} -DCMAKE_BUILD_TYPE=Release -DYUZU_CRASH_DUMPS=ON .. && cd ..
|
||||
- script: refreshenv && mkdir build && cd build && cmake -G "Visual Studio 17 2022" -A x64 -DYUZU_USE_BUNDLED_QT=1 -DYUZU_USE_BUNDLED_SDL2=1 -DYUZU_USE_QT_WEB_ENGINE=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${COMPAT} -DYUZU_TESTS=OFF -DUSE_DISCORD_PRESENCE=ON -DENABLE_QT_TRANSLATION=ON -DDISPLAY_VERSION=${{ parameters['version'] }} -DCMAKE_BUILD_TYPE=Release -DYUZU_CRASH_DUMPS=ON .. && cd ..
|
||||
displayName: 'Configure CMake'
|
||||
- task: MSBuild@1
|
||||
displayName: 'Build'
|
||||
|
||||
@@ -208,7 +208,7 @@ find_package(libusb 1.0.24)
|
||||
find_package(lz4 REQUIRED)
|
||||
find_package(nlohmann_json 3.8 REQUIRED)
|
||||
find_package(Opus 1.3)
|
||||
find_package(Vulkan 1.3.238)
|
||||
find_package(Vulkan 1.3.213)
|
||||
find_package(ZLIB 1.2 REQUIRED)
|
||||
find_package(zstd 1.5 REQUIRED)
|
||||
|
||||
|
||||
2
externals/Vulkan-Headers
vendored
2
externals/Vulkan-Headers
vendored
Submodule externals/Vulkan-Headers updated: 00671c64ba...2826791bed
@@ -69,7 +69,7 @@ void assert_fail_impl();
|
||||
#define ASSERT_OR_EXECUTE(_a_, _b_) \
|
||||
do { \
|
||||
ASSERT(_a_); \
|
||||
if (!(_a_)) [[unlikely]] { \
|
||||
if (!(_a_)) { \
|
||||
_b_ \
|
||||
} \
|
||||
} while (0)
|
||||
@@ -78,7 +78,7 @@ void assert_fail_impl();
|
||||
#define ASSERT_OR_EXECUTE_MSG(_a_, _b_, ...) \
|
||||
do { \
|
||||
ASSERT_MSG(_a_, __VA_ARGS__); \
|
||||
if (!(_a_)) [[unlikely]] { \
|
||||
if (!(_a_)) { \
|
||||
_b_ \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
@@ -201,9 +201,6 @@ add_library(core STATIC
|
||||
hle/kernel/k_event_info.h
|
||||
hle/kernel/k_handle_table.cpp
|
||||
hle/kernel/k_handle_table.h
|
||||
hle/kernel/k_hardware_timer_base.h
|
||||
hle/kernel/k_hardware_timer.cpp
|
||||
hle/kernel/k_hardware_timer.h
|
||||
hle/kernel/k_interrupt_manager.cpp
|
||||
hle/kernel/k_interrupt_manager.h
|
||||
hle/kernel/k_light_condition_variable.cpp
|
||||
@@ -271,7 +268,6 @@ add_library(core STATIC
|
||||
hle/kernel/k_thread_local_page.h
|
||||
hle/kernel/k_thread_queue.cpp
|
||||
hle/kernel/k_thread_queue.h
|
||||
hle/kernel/k_timer_task.h
|
||||
hle/kernel/k_trace.h
|
||||
hle/kernel/k_transfer_memory.cpp
|
||||
hle/kernel/k_transfer_memory.h
|
||||
@@ -294,6 +290,8 @@ add_library(core STATIC
|
||||
hle/kernel/svc_common.h
|
||||
hle/kernel/svc_types.h
|
||||
hle/kernel/svc_wrap.h
|
||||
hle/kernel/time_manager.cpp
|
||||
hle/kernel/time_manager.h
|
||||
hle/result.h
|
||||
hle/service/acc/acc.cpp
|
||||
hle/service/acc/acc.h
|
||||
|
||||
@@ -183,20 +183,26 @@ struct System::Impl {
|
||||
Initialize(system);
|
||||
}
|
||||
|
||||
void Run() {
|
||||
SystemResultStatus Run() {
|
||||
std::unique_lock<std::mutex> lk(suspend_guard);
|
||||
status = SystemResultStatus::Success;
|
||||
|
||||
kernel.Suspend(false);
|
||||
core_timing.SyncPause(false);
|
||||
is_paused.store(false, std::memory_order_relaxed);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void Pause() {
|
||||
SystemResultStatus Pause() {
|
||||
std::unique_lock<std::mutex> lk(suspend_guard);
|
||||
status = SystemResultStatus::Success;
|
||||
|
||||
core_timing.SyncPause(true);
|
||||
kernel.Suspend(true);
|
||||
is_paused.store(true, std::memory_order_relaxed);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
bool IsPaused() const {
|
||||
@@ -547,12 +553,12 @@ void System::Initialize() {
|
||||
impl->Initialize(*this);
|
||||
}
|
||||
|
||||
void System::Run() {
|
||||
impl->Run();
|
||||
SystemResultStatus System::Run() {
|
||||
return impl->Run();
|
||||
}
|
||||
|
||||
void System::Pause() {
|
||||
impl->Pause();
|
||||
SystemResultStatus System::Pause() {
|
||||
return impl->Pause();
|
||||
}
|
||||
|
||||
bool System::IsPaused() const {
|
||||
|
||||
@@ -152,13 +152,13 @@ public:
|
||||
* Run the OS and Application
|
||||
* This function will start emulation and run the relevant devices
|
||||
*/
|
||||
void Run();
|
||||
[[nodiscard]] SystemResultStatus Run();
|
||||
|
||||
/**
|
||||
* Pause the OS and Application
|
||||
* This function will pause emulation and stop the relevant devices
|
||||
*/
|
||||
void Pause();
|
||||
[[nodiscard]] SystemResultStatus Pause();
|
||||
|
||||
/// Check if the core is currently paused.
|
||||
[[nodiscard]] bool IsPaused() const;
|
||||
|
||||
@@ -145,7 +145,6 @@ void EmulatedController::LoadDevices() {
|
||||
output_params[3].Set("output", true);
|
||||
|
||||
LoadTASParams();
|
||||
LoadVirtualGamepadParams();
|
||||
|
||||
std::ranges::transform(button_params, button_devices.begin(), Common::Input::CreateInputDevice);
|
||||
std::ranges::transform(stick_params, stick_devices.begin(), Common::Input::CreateInputDevice);
|
||||
@@ -164,12 +163,6 @@ void EmulatedController::LoadDevices() {
|
||||
Common::Input::CreateInputDevice);
|
||||
std::ranges::transform(tas_stick_params, tas_stick_devices.begin(),
|
||||
Common::Input::CreateInputDevice);
|
||||
|
||||
// Initialize virtual gamepad devices
|
||||
std::ranges::transform(virtual_button_params, virtual_button_devices.begin(),
|
||||
Common::Input::CreateInputDevice);
|
||||
std::ranges::transform(virtual_stick_params, virtual_stick_devices.begin(),
|
||||
Common::Input::CreateInputDevice);
|
||||
}
|
||||
|
||||
void EmulatedController::LoadTASParams() {
|
||||
@@ -212,46 +205,6 @@ void EmulatedController::LoadTASParams() {
|
||||
tas_stick_params[Settings::NativeAnalog::RStick].Set("axis_y", 3);
|
||||
}
|
||||
|
||||
void EmulatedController::LoadVirtualGamepadParams() {
|
||||
const auto player_index = NpadIdTypeToIndex(npad_id_type);
|
||||
Common::ParamPackage common_params{};
|
||||
common_params.Set("engine", "virtual_gamepad");
|
||||
common_params.Set("port", static_cast<int>(player_index));
|
||||
for (auto& param : virtual_button_params) {
|
||||
param = common_params;
|
||||
}
|
||||
for (auto& param : virtual_stick_params) {
|
||||
param = common_params;
|
||||
}
|
||||
|
||||
// TODO(german77): Replace this with an input profile or something better
|
||||
virtual_button_params[Settings::NativeButton::A].Set("button", 0);
|
||||
virtual_button_params[Settings::NativeButton::B].Set("button", 1);
|
||||
virtual_button_params[Settings::NativeButton::X].Set("button", 2);
|
||||
virtual_button_params[Settings::NativeButton::Y].Set("button", 3);
|
||||
virtual_button_params[Settings::NativeButton::LStick].Set("button", 4);
|
||||
virtual_button_params[Settings::NativeButton::RStick].Set("button", 5);
|
||||
virtual_button_params[Settings::NativeButton::L].Set("button", 6);
|
||||
virtual_button_params[Settings::NativeButton::R].Set("button", 7);
|
||||
virtual_button_params[Settings::NativeButton::ZL].Set("button", 8);
|
||||
virtual_button_params[Settings::NativeButton::ZR].Set("button", 9);
|
||||
virtual_button_params[Settings::NativeButton::Plus].Set("button", 10);
|
||||
virtual_button_params[Settings::NativeButton::Minus].Set("button", 11);
|
||||
virtual_button_params[Settings::NativeButton::DLeft].Set("button", 12);
|
||||
virtual_button_params[Settings::NativeButton::DUp].Set("button", 13);
|
||||
virtual_button_params[Settings::NativeButton::DRight].Set("button", 14);
|
||||
virtual_button_params[Settings::NativeButton::DDown].Set("button", 15);
|
||||
virtual_button_params[Settings::NativeButton::SL].Set("button", 16);
|
||||
virtual_button_params[Settings::NativeButton::SR].Set("button", 17);
|
||||
virtual_button_params[Settings::NativeButton::Home].Set("button", 18);
|
||||
virtual_button_params[Settings::NativeButton::Screenshot].Set("button", 19);
|
||||
|
||||
virtual_stick_params[Settings::NativeAnalog::LStick].Set("axis_x", 0);
|
||||
virtual_stick_params[Settings::NativeAnalog::LStick].Set("axis_y", 1);
|
||||
virtual_stick_params[Settings::NativeAnalog::RStick].Set("axis_x", 2);
|
||||
virtual_stick_params[Settings::NativeAnalog::RStick].Set("axis_y", 3);
|
||||
}
|
||||
|
||||
void EmulatedController::ReloadInput() {
|
||||
// If you load any device here add the equivalent to the UnloadInput() function
|
||||
LoadDevices();
|
||||
@@ -369,35 +322,6 @@ void EmulatedController::ReloadInput() {
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Use a common UUID for Virtual Gamepad
|
||||
static constexpr Common::UUID VIRTUAL_UUID = Common::UUID{
|
||||
{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xFF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
|
||||
|
||||
// Register virtual devices. No need to force update
|
||||
for (std::size_t index = 0; index < virtual_button_devices.size(); ++index) {
|
||||
if (!virtual_button_devices[index]) {
|
||||
continue;
|
||||
}
|
||||
virtual_button_devices[index]->SetCallback({
|
||||
.on_change =
|
||||
[this, index](const Common::Input::CallbackStatus& callback) {
|
||||
SetButton(callback, index, VIRTUAL_UUID);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
for (std::size_t index = 0; index < virtual_stick_devices.size(); ++index) {
|
||||
if (!virtual_stick_devices[index]) {
|
||||
continue;
|
||||
}
|
||||
virtual_stick_devices[index]->SetCallback({
|
||||
.on_change =
|
||||
[this, index](const Common::Input::CallbackStatus& callback) {
|
||||
SetStick(callback, index, VIRTUAL_UUID);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void EmulatedController::UnloadInput() {
|
||||
@@ -425,12 +349,6 @@ void EmulatedController::UnloadInput() {
|
||||
for (auto& stick : tas_stick_devices) {
|
||||
stick.reset();
|
||||
}
|
||||
for (auto& button : virtual_button_devices) {
|
||||
button.reset();
|
||||
}
|
||||
for (auto& stick : virtual_stick_devices) {
|
||||
stick.reset();
|
||||
}
|
||||
camera_devices.reset();
|
||||
nfc_devices.reset();
|
||||
}
|
||||
|
||||
@@ -385,9 +385,6 @@ private:
|
||||
/// Set the params for TAS devices
|
||||
void LoadTASParams();
|
||||
|
||||
/// Set the params for virtual pad devices
|
||||
void LoadVirtualGamepadParams();
|
||||
|
||||
/**
|
||||
* @param use_temporary_value If true tmp_npad_type will be used
|
||||
* @return true if the controller style is fullkey
|
||||
@@ -503,12 +500,6 @@ private:
|
||||
ButtonDevices tas_button_devices;
|
||||
StickDevices tas_stick_devices;
|
||||
|
||||
// Virtual gamepad related variables
|
||||
ButtonParams virtual_button_params;
|
||||
StickParams virtual_stick_params;
|
||||
ButtonDevices virtual_button_devices;
|
||||
StickDevices virtual_stick_devices;
|
||||
|
||||
mutable std::mutex mutex;
|
||||
mutable std::mutex callback_mutex;
|
||||
std::unordered_map<int, ControllerUpdateCallback> callback_list;
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "core/hle/kernel/k_thread_queue.h"
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
#include "core/hle/kernel/svc_results.h"
|
||||
#include "core/hle/kernel/time_manager.h"
|
||||
#include "core/memory.h"
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "core/core.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/hle/kernel/k_hardware_timer.h"
|
||||
#include "core/hle/kernel/k_scheduler.h"
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
void KHardwareTimer::Initialize() {
|
||||
// Create the timing callback to register with CoreTiming.
|
||||
m_event_type = Core::Timing::CreateEvent(
|
||||
"KHardwareTimer::Callback", [](std::uintptr_t timer_handle, s64, std::chrono::nanoseconds) {
|
||||
reinterpret_cast<KHardwareTimer*>(timer_handle)->DoTask();
|
||||
return std::nullopt;
|
||||
});
|
||||
}
|
||||
|
||||
void KHardwareTimer::Finalize() {
|
||||
this->DisableInterrupt();
|
||||
m_event_type.reset();
|
||||
}
|
||||
|
||||
void KHardwareTimer::DoTask() {
|
||||
// Handle the interrupt.
|
||||
{
|
||||
KScopedSchedulerLock slk{m_kernel};
|
||||
KScopedSpinLock lk(this->GetLock());
|
||||
|
||||
//! Ignore this event if needed.
|
||||
if (!this->GetInterruptEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Disable the timer interrupt while we handle this.
|
||||
this->DisableInterrupt();
|
||||
|
||||
if (const s64 next_time = this->DoInterruptTaskImpl(GetTick());
|
||||
0 < next_time && next_time <= m_wakeup_time) {
|
||||
// We have a next time, so we should set the time to interrupt and turn the interrupt
|
||||
// on.
|
||||
this->EnableInterrupt(next_time);
|
||||
}
|
||||
}
|
||||
|
||||
// Clear the timer interrupt.
|
||||
// Kernel::GetInterruptManager().ClearInterrupt(KInterruptName_NonSecurePhysicalTimer,
|
||||
// GetCurrentCoreId());
|
||||
}
|
||||
|
||||
void KHardwareTimer::EnableInterrupt(s64 wakeup_time) {
|
||||
this->DisableInterrupt();
|
||||
|
||||
m_wakeup_time = wakeup_time;
|
||||
m_kernel.System().CoreTiming().ScheduleEvent(std::chrono::nanoseconds{m_wakeup_time},
|
||||
m_event_type, reinterpret_cast<uintptr_t>(this),
|
||||
true);
|
||||
}
|
||||
|
||||
void KHardwareTimer::DisableInterrupt() {
|
||||
m_kernel.System().CoreTiming().UnscheduleEvent(m_event_type, reinterpret_cast<uintptr_t>(this));
|
||||
m_wakeup_time = std::numeric_limits<s64>::max();
|
||||
}
|
||||
|
||||
s64 KHardwareTimer::GetTick() const {
|
||||
return m_kernel.System().CoreTiming().GetGlobalTimeNs().count();
|
||||
}
|
||||
|
||||
bool KHardwareTimer::GetInterruptEnabled() {
|
||||
return m_wakeup_time != std::numeric_limits<s64>::max();
|
||||
}
|
||||
|
||||
} // namespace Kernel
|
||||
@@ -1,54 +0,0 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/kernel/k_hardware_timer_base.h"
|
||||
|
||||
namespace Core::Timing {
|
||||
struct EventType;
|
||||
} // namespace Core::Timing
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
class KHardwareTimer : /* public KInterruptTask, */ public KHardwareTimerBase {
|
||||
public:
|
||||
explicit KHardwareTimer(KernelCore& kernel) : KHardwareTimerBase{kernel} {}
|
||||
|
||||
// Public API.
|
||||
void Initialize();
|
||||
void Finalize();
|
||||
|
||||
s64 GetCount() const {
|
||||
return GetTick();
|
||||
}
|
||||
|
||||
void RegisterTask(KTimerTask* task, s64 time_from_now) {
|
||||
this->RegisterAbsoluteTask(task, GetTick() + time_from_now);
|
||||
}
|
||||
|
||||
void RegisterAbsoluteTask(KTimerTask* task, s64 task_time) {
|
||||
KScopedDisableDispatch dd{m_kernel};
|
||||
KScopedSpinLock lk{this->GetLock()};
|
||||
|
||||
if (this->RegisterAbsoluteTaskImpl(task, task_time)) {
|
||||
if (task_time <= m_wakeup_time) {
|
||||
this->EnableInterrupt(task_time);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void EnableInterrupt(s64 wakeup_time);
|
||||
void DisableInterrupt();
|
||||
bool GetInterruptEnabled();
|
||||
s64 GetTick() const;
|
||||
void DoTask();
|
||||
|
||||
private:
|
||||
// Absolute time in nanoseconds
|
||||
s64 m_wakeup_time{std::numeric_limits<s64>::max()};
|
||||
std::shared_ptr<Core::Timing::EventType> m_event_type{};
|
||||
};
|
||||
|
||||
} // namespace Kernel
|
||||
@@ -1,92 +0,0 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/kernel/k_spin_lock.h"
|
||||
#include "core/hle/kernel/k_thread.h"
|
||||
#include "core/hle/kernel/k_timer_task.h"
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
class KHardwareTimerBase {
|
||||
public:
|
||||
explicit KHardwareTimerBase(KernelCore& kernel) : m_kernel{kernel} {}
|
||||
|
||||
void CancelTask(KTimerTask* task) {
|
||||
KScopedDisableDispatch dd{m_kernel};
|
||||
KScopedSpinLock lk{m_lock};
|
||||
|
||||
if (const s64 task_time = task->GetTime(); task_time > 0) {
|
||||
this->RemoveTaskFromTree(task);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
KSpinLock& GetLock() {
|
||||
return m_lock;
|
||||
}
|
||||
|
||||
s64 DoInterruptTaskImpl(s64 cur_time) {
|
||||
// We want to handle all tasks, returning the next time that a task is scheduled.
|
||||
while (true) {
|
||||
// Get the next task. If there isn't one, return 0.
|
||||
KTimerTask* task = m_next_task;
|
||||
if (task == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// If the task needs to be done in the future, do it in the future and not now.
|
||||
if (const s64 task_time = task->GetTime(); task_time > cur_time) {
|
||||
return task_time;
|
||||
}
|
||||
|
||||
// Remove the task from the tree of tasks, and update our next task.
|
||||
this->RemoveTaskFromTree(task);
|
||||
|
||||
// Handle the task.
|
||||
task->OnTimer();
|
||||
}
|
||||
}
|
||||
|
||||
bool RegisterAbsoluteTaskImpl(KTimerTask* task, s64 task_time) {
|
||||
ASSERT(task_time > 0);
|
||||
|
||||
// Set the task's time, and insert it into our tree.
|
||||
task->SetTime(task_time);
|
||||
m_task_tree.insert(*task);
|
||||
|
||||
// Update our next task if relevant.
|
||||
if (m_next_task != nullptr && m_next_task->GetTime() <= task_time) {
|
||||
return false;
|
||||
}
|
||||
m_next_task = task;
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
void RemoveTaskFromTree(KTimerTask* task) {
|
||||
// Erase from the tree.
|
||||
auto it = m_task_tree.erase(m_task_tree.iterator_to(*task));
|
||||
|
||||
// Clear the task's scheduled time.
|
||||
task->SetTime(0);
|
||||
|
||||
// Update our next task if relevant.
|
||||
if (m_next_task == task) {
|
||||
m_next_task = (it != m_task_tree.end()) ? std::addressof(*it) : nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
KernelCore& m_kernel;
|
||||
|
||||
private:
|
||||
using TimerTaskTree = Common::IntrusiveRedBlackTreeBaseTraits<KTimerTask>::TreeType<KTimerTask>;
|
||||
|
||||
KSpinLock m_lock{};
|
||||
TimerTaskTree m_task_tree{};
|
||||
KTimerTask* m_next_task{};
|
||||
};
|
||||
|
||||
} // namespace Kernel
|
||||
@@ -5,9 +5,9 @@
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "core/hle/kernel/global_scheduler_context.h"
|
||||
#include "core/hle/kernel/k_hardware_timer.h"
|
||||
#include "core/hle/kernel/k_thread.h"
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
#include "core/hle/kernel/time_manager.h"
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
@@ -22,7 +22,7 @@ public:
|
||||
~KScopedSchedulerLockAndSleep() {
|
||||
// Register the sleep.
|
||||
if (timeout_tick > 0) {
|
||||
kernel.HardwareTimer().RegisterTask(thread, timeout_tick);
|
||||
kernel.TimeManager().ScheduleTimeEvent(thread, timeout_tick);
|
||||
}
|
||||
|
||||
// Unlock the scheduler.
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#include "core/hle/kernel/k_light_lock.h"
|
||||
#include "core/hle/kernel/k_spin_lock.h"
|
||||
#include "core/hle/kernel/k_synchronization_object.h"
|
||||
#include "core/hle/kernel/k_timer_task.h"
|
||||
#include "core/hle/kernel/k_worker_task.h"
|
||||
#include "core/hle/kernel/slab_helpers.h"
|
||||
#include "core/hle/kernel/svc_common.h"
|
||||
@@ -113,8 +112,7 @@ void SetCurrentThread(KernelCore& kernel, KThread* thread);
|
||||
[[nodiscard]] s32 GetCurrentCoreId(KernelCore& kernel);
|
||||
|
||||
class KThread final : public KAutoObjectWithSlabHeapAndContainer<KThread, KWorkerTask>,
|
||||
public boost::intrusive::list_base_hook<>,
|
||||
public KTimerTask {
|
||||
public boost::intrusive::list_base_hook<> {
|
||||
KERNEL_AUTOOBJECT_TRAITS(KThread, KSynchronizationObject);
|
||||
|
||||
private:
|
||||
@@ -842,8 +840,4 @@ private:
|
||||
KernelCore& kernel;
|
||||
};
|
||||
|
||||
inline void KTimerTask::OnTimer() {
|
||||
static_cast<KThread*>(this)->OnTimer();
|
||||
}
|
||||
|
||||
} // namespace Kernel
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "core/hle/kernel/k_hardware_timer.h"
|
||||
#include "core/hle/kernel/k_thread_queue.h"
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
#include "core/hle/kernel/time_manager.h"
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
@@ -22,7 +22,7 @@ void KThreadQueue::EndWait(KThread* waiting_thread, Result wait_result) {
|
||||
waiting_thread->ClearWaitQueue();
|
||||
|
||||
// Cancel the thread task.
|
||||
kernel.HardwareTimer().CancelTask(waiting_thread);
|
||||
kernel.TimeManager().UnscheduleTimeEvent(waiting_thread);
|
||||
}
|
||||
|
||||
void KThreadQueue::CancelWait(KThread* waiting_thread, Result wait_result, bool cancel_timer_task) {
|
||||
@@ -37,7 +37,7 @@ void KThreadQueue::CancelWait(KThread* waiting_thread, Result wait_result, bool
|
||||
|
||||
// Cancel the thread task.
|
||||
if (cancel_timer_task) {
|
||||
kernel.HardwareTimer().CancelTask(waiting_thread);
|
||||
kernel.TimeManager().UnscheduleTimeEvent(waiting_thread);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/intrusive_red_black_tree.h"
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
class KTimerTask : public Common::IntrusiveRedBlackTreeBaseNode<KTimerTask> {
|
||||
public:
|
||||
static constexpr int Compare(const KTimerTask& lhs, const KTimerTask& rhs) {
|
||||
if (lhs.GetTime() < rhs.GetTime()) {
|
||||
return -1;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr explicit KTimerTask() = default;
|
||||
|
||||
constexpr void SetTime(s64 t) {
|
||||
m_time = t;
|
||||
}
|
||||
|
||||
constexpr s64 GetTime() const {
|
||||
return m_time;
|
||||
}
|
||||
|
||||
// NOTE: This is virtual in Nintendo's kernel. Prior to 13.0.0, KWaitObject was also a
|
||||
// TimerTask; this is no longer the case. Since this is now KThread exclusive, we have
|
||||
// devirtualized (see inline declaration for this inside k_thread.h).
|
||||
void OnTimer();
|
||||
|
||||
private:
|
||||
// Absolute time in nanoseconds
|
||||
s64 m_time{};
|
||||
};
|
||||
|
||||
} // namespace Kernel
|
||||
@@ -26,7 +26,6 @@
|
||||
#include "core/hle/kernel/k_client_port.h"
|
||||
#include "core/hle/kernel/k_dynamic_resource_manager.h"
|
||||
#include "core/hle/kernel/k_handle_table.h"
|
||||
#include "core/hle/kernel/k_hardware_timer.h"
|
||||
#include "core/hle/kernel/k_memory_layout.h"
|
||||
#include "core/hle/kernel/k_memory_manager.h"
|
||||
#include "core/hle/kernel/k_page_buffer.h"
|
||||
@@ -40,6 +39,7 @@
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
#include "core/hle/kernel/physical_core.h"
|
||||
#include "core/hle/kernel/service_thread.h"
|
||||
#include "core/hle/kernel/time_manager.h"
|
||||
#include "core/hle/result.h"
|
||||
#include "core/hle/service/sm/sm.h"
|
||||
#include "core/memory.h"
|
||||
@@ -55,7 +55,7 @@ struct KernelCore::Impl {
|
||||
static constexpr size_t ReservedDynamicPageCount = 64;
|
||||
|
||||
explicit Impl(Core::System& system_, KernelCore& kernel_)
|
||||
: service_threads_manager{1, "ServiceThreadsManager"},
|
||||
: time_manager{system_}, service_threads_manager{1, "ServiceThreadsManager"},
|
||||
service_thread_barrier{2}, system{system_} {}
|
||||
|
||||
void SetMulticore(bool is_multi) {
|
||||
@@ -63,9 +63,6 @@ struct KernelCore::Impl {
|
||||
}
|
||||
|
||||
void Initialize(KernelCore& kernel) {
|
||||
hardware_timer = std::make_unique<Kernel::KHardwareTimer>(kernel);
|
||||
hardware_timer->Initialize();
|
||||
|
||||
global_object_list_container = std::make_unique<KAutoObjectWithListContainer>(kernel);
|
||||
global_scheduler_context = std::make_unique<Kernel::GlobalSchedulerContext>(kernel);
|
||||
global_handle_table = std::make_unique<Kernel::KHandleTable>(kernel);
|
||||
@@ -196,9 +193,6 @@ struct KernelCore::Impl {
|
||||
// Ensure that the object list container is finalized and properly shutdown.
|
||||
global_object_list_container->Finalize();
|
||||
global_object_list_container.reset();
|
||||
|
||||
hardware_timer->Finalize();
|
||||
hardware_timer.reset();
|
||||
}
|
||||
|
||||
void CloseServices() {
|
||||
@@ -838,7 +832,7 @@ struct KernelCore::Impl {
|
||||
std::vector<KProcess*> process_list;
|
||||
std::atomic<KProcess*> current_process{};
|
||||
std::unique_ptr<Kernel::GlobalSchedulerContext> global_scheduler_context;
|
||||
std::unique_ptr<Kernel::KHardwareTimer> hardware_timer;
|
||||
Kernel::TimeManager time_manager;
|
||||
|
||||
Init::KSlabResourceCounts slab_resource_counts{};
|
||||
KResourceLimit* system_resource_limit{};
|
||||
@@ -1025,8 +1019,12 @@ Kernel::KScheduler* KernelCore::CurrentScheduler() {
|
||||
return impl->schedulers[core_id].get();
|
||||
}
|
||||
|
||||
Kernel::KHardwareTimer& KernelCore::HardwareTimer() {
|
||||
return *impl->hardware_timer;
|
||||
Kernel::TimeManager& KernelCore::TimeManager() {
|
||||
return impl->time_manager;
|
||||
}
|
||||
|
||||
const Kernel::TimeManager& KernelCore::TimeManager() const {
|
||||
return impl->time_manager;
|
||||
}
|
||||
|
||||
Core::ExclusiveMonitor& KernelCore::GetExclusiveMonitor() {
|
||||
|
||||
@@ -39,7 +39,6 @@ class KDynamicPageManager;
|
||||
class KEvent;
|
||||
class KEventInfo;
|
||||
class KHandleTable;
|
||||
class KHardwareTimer;
|
||||
class KLinkedListNode;
|
||||
class KMemoryLayout;
|
||||
class KMemoryManager;
|
||||
@@ -64,6 +63,7 @@ class KCodeMemory;
|
||||
class PhysicalCore;
|
||||
class ServiceThread;
|
||||
class Synchronization;
|
||||
class TimeManager;
|
||||
|
||||
using ServiceInterfaceFactory =
|
||||
std::function<KClientPort&(Service::SM::ServiceManager&, Core::System&)>;
|
||||
@@ -175,8 +175,11 @@ public:
|
||||
/// Gets the an instance of the current physical CPU core.
|
||||
const Kernel::PhysicalCore& CurrentPhysicalCore() const;
|
||||
|
||||
/// Gets the an instance of the hardware timer.
|
||||
Kernel::KHardwareTimer& HardwareTimer();
|
||||
/// Gets the an instance of the TimeManager Interface.
|
||||
Kernel::TimeManager& TimeManager();
|
||||
|
||||
/// Gets the an instance of the TimeManager Interface.
|
||||
const Kernel::TimeManager& TimeManager() const;
|
||||
|
||||
/// Stops execution of 'id' core, in order to reschedule a new thread.
|
||||
void PrepareReschedule(std::size_t id);
|
||||
|
||||
44
src/core/hle/kernel/time_manager.cpp
Normal file
44
src/core/hle/kernel/time_manager.cpp
Normal file
@@ -0,0 +1,44 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "core/core.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/hle/kernel/k_scheduler.h"
|
||||
#include "core/hle/kernel/k_thread.h"
|
||||
#include "core/hle/kernel/time_manager.h"
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
TimeManager::TimeManager(Core::System& system_) : system{system_} {
|
||||
time_manager_event_type = Core::Timing::CreateEvent(
|
||||
"Kernel::TimeManagerCallback",
|
||||
[this](std::uintptr_t thread_handle, s64 time,
|
||||
std::chrono::nanoseconds) -> std::optional<std::chrono::nanoseconds> {
|
||||
KThread* thread = reinterpret_cast<KThread*>(thread_handle);
|
||||
{
|
||||
KScopedSchedulerLock sl(system.Kernel());
|
||||
thread->OnTimer();
|
||||
}
|
||||
return std::nullopt;
|
||||
});
|
||||
}
|
||||
|
||||
void TimeManager::ScheduleTimeEvent(KThread* thread, s64 nanoseconds) {
|
||||
std::scoped_lock lock{mutex};
|
||||
if (nanoseconds > 0) {
|
||||
ASSERT(thread);
|
||||
ASSERT(thread->GetState() != ThreadState::Runnable);
|
||||
system.CoreTiming().ScheduleEvent(std::chrono::nanoseconds{nanoseconds},
|
||||
time_manager_event_type,
|
||||
reinterpret_cast<uintptr_t>(thread));
|
||||
}
|
||||
}
|
||||
|
||||
void TimeManager::UnscheduleTimeEvent(KThread* thread) {
|
||||
std::scoped_lock lock{mutex};
|
||||
system.CoreTiming().UnscheduleEvent(time_manager_event_type,
|
||||
reinterpret_cast<uintptr_t>(thread));
|
||||
}
|
||||
|
||||
} // namespace Kernel
|
||||
41
src/core/hle/kernel/time_manager.h
Normal file
41
src/core/hle/kernel/time_manager.h
Normal file
@@ -0,0 +1,41 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
} // namespace Core
|
||||
|
||||
namespace Core::Timing {
|
||||
struct EventType;
|
||||
} // namespace Core::Timing
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
class KThread;
|
||||
|
||||
/**
|
||||
* The `TimeManager` takes care of scheduling time events on threads and executes their TimeUp
|
||||
* method when the event is triggered.
|
||||
*/
|
||||
class TimeManager {
|
||||
public:
|
||||
explicit TimeManager(Core::System& system);
|
||||
|
||||
/// Schedule a time event on `timetask` thread that will expire in 'nanoseconds'
|
||||
void ScheduleTimeEvent(KThread* time_task, s64 nanoseconds);
|
||||
|
||||
/// Unschedule an existing time event
|
||||
void UnscheduleTimeEvent(KThread* thread);
|
||||
|
||||
private:
|
||||
Core::System& system;
|
||||
std::shared_ptr<Core::Timing::EventType> time_manager_event_type;
|
||||
std::mutex mutex;
|
||||
};
|
||||
|
||||
} // namespace Kernel
|
||||
@@ -97,7 +97,7 @@ void IUser::IsNfcEnabled(Kernel::HLERequestContext& ctx) {
|
||||
}
|
||||
|
||||
void IUser::ListDevices(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_NFC, "called");
|
||||
LOG_INFO(Service_NFC, "called");
|
||||
|
||||
if (state == State::NonInitialized) {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
|
||||
@@ -83,7 +83,7 @@ void IUser::Finalize(Kernel::HLERequestContext& ctx) {
|
||||
}
|
||||
|
||||
void IUser::ListDevices(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_NFP, "called");
|
||||
LOG_INFO(Service_NFP, "called");
|
||||
|
||||
if (state == State::NonInitialized) {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
|
||||
@@ -20,8 +20,6 @@ add_library(input_common STATIC
|
||||
drivers/udp_client.h
|
||||
drivers/virtual_amiibo.cpp
|
||||
drivers/virtual_amiibo.h
|
||||
drivers/virtual_gamepad.cpp
|
||||
drivers/virtual_gamepad.h
|
||||
helpers/stick_from_buttons.cpp
|
||||
helpers/stick_from_buttons.h
|
||||
helpers/touch_from_buttons.cpp
|
||||
|
||||
@@ -25,7 +25,6 @@ public:
|
||||
Common::Input::CameraError SetCameraFormat(const PadIdentifier& identifier_,
|
||||
Common::Input::CameraFormat camera_format) override;
|
||||
|
||||
private:
|
||||
Common::Input::CameraStatus status{};
|
||||
};
|
||||
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "input_common/drivers/virtual_gamepad.h"
|
||||
|
||||
namespace InputCommon {
|
||||
constexpr std::size_t PlayerIndexCount = 10;
|
||||
|
||||
VirtualGamepad::VirtualGamepad(std::string input_engine_) : InputEngine(std::move(input_engine_)) {
|
||||
for (std::size_t i = 0; i < PlayerIndexCount; i++) {
|
||||
PreSetController(GetIdentifier(i));
|
||||
}
|
||||
}
|
||||
|
||||
void VirtualGamepad::SetButtonState(std::size_t player_index, int button_id, bool value) {
|
||||
if (player_index > PlayerIndexCount) {
|
||||
return;
|
||||
}
|
||||
const auto identifier = GetIdentifier(player_index);
|
||||
SetButton(identifier, button_id, value);
|
||||
}
|
||||
|
||||
void VirtualGamepad::SetButtonState(std::size_t player_index, VirtualButton button_id, bool value) {
|
||||
SetButtonState(player_index, static_cast<int>(button_id), value);
|
||||
}
|
||||
|
||||
void VirtualGamepad::SetStickPosition(std::size_t player_index, int axis_id, float x_value,
|
||||
float y_value) {
|
||||
if (player_index > PlayerIndexCount) {
|
||||
return;
|
||||
}
|
||||
const auto identifier = GetIdentifier(player_index);
|
||||
SetAxis(identifier, axis_id * 2, x_value);
|
||||
SetAxis(identifier, (axis_id * 2) + 1, y_value);
|
||||
}
|
||||
|
||||
void VirtualGamepad::SetStickPosition(std::size_t player_index, VirtualStick axis_id, float x_value,
|
||||
float y_value) {
|
||||
SetStickPosition(player_index, static_cast<int>(axis_id), x_value, y_value);
|
||||
}
|
||||
|
||||
void VirtualGamepad::ResetControllers() {
|
||||
for (std::size_t i = 0; i < PlayerIndexCount; i++) {
|
||||
SetStickPosition(i, VirtualStick::Left, 0.0f, 0.0f);
|
||||
SetStickPosition(i, VirtualStick::Right, 0.0f, 0.0f);
|
||||
|
||||
SetButtonState(i, VirtualButton::ButtonA, false);
|
||||
SetButtonState(i, VirtualButton::ButtonB, false);
|
||||
SetButtonState(i, VirtualButton::ButtonX, false);
|
||||
SetButtonState(i, VirtualButton::ButtonY, false);
|
||||
SetButtonState(i, VirtualButton::StickL, false);
|
||||
SetButtonState(i, VirtualButton::StickR, false);
|
||||
SetButtonState(i, VirtualButton::TriggerL, false);
|
||||
SetButtonState(i, VirtualButton::TriggerR, false);
|
||||
SetButtonState(i, VirtualButton::TriggerZL, false);
|
||||
SetButtonState(i, VirtualButton::TriggerZR, false);
|
||||
SetButtonState(i, VirtualButton::ButtonPlus, false);
|
||||
SetButtonState(i, VirtualButton::ButtonMinus, false);
|
||||
SetButtonState(i, VirtualButton::ButtonLeft, false);
|
||||
SetButtonState(i, VirtualButton::ButtonUp, false);
|
||||
SetButtonState(i, VirtualButton::ButtonRight, false);
|
||||
SetButtonState(i, VirtualButton::ButtonDown, false);
|
||||
SetButtonState(i, VirtualButton::ButtonSL, false);
|
||||
SetButtonState(i, VirtualButton::ButtonSR, false);
|
||||
SetButtonState(i, VirtualButton::ButtonHome, false);
|
||||
SetButtonState(i, VirtualButton::ButtonCapture, false);
|
||||
}
|
||||
}
|
||||
|
||||
PadIdentifier VirtualGamepad::GetIdentifier(std::size_t player_index) const {
|
||||
return {
|
||||
.guid = Common::UUID{},
|
||||
.port = player_index,
|
||||
.pad = 0,
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace InputCommon
|
||||
@@ -1,73 +0,0 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "input_common/input_engine.h"
|
||||
|
||||
namespace InputCommon {
|
||||
|
||||
/**
|
||||
* A virtual controller that is always assigned to the game input
|
||||
*/
|
||||
class VirtualGamepad final : public InputEngine {
|
||||
public:
|
||||
enum class VirtualButton {
|
||||
ButtonA,
|
||||
ButtonB,
|
||||
ButtonX,
|
||||
ButtonY,
|
||||
StickL,
|
||||
StickR,
|
||||
TriggerL,
|
||||
TriggerR,
|
||||
TriggerZL,
|
||||
TriggerZR,
|
||||
ButtonPlus,
|
||||
ButtonMinus,
|
||||
ButtonLeft,
|
||||
ButtonUp,
|
||||
ButtonRight,
|
||||
ButtonDown,
|
||||
ButtonSL,
|
||||
ButtonSR,
|
||||
ButtonHome,
|
||||
ButtonCapture,
|
||||
};
|
||||
|
||||
enum class VirtualStick {
|
||||
Left = 0,
|
||||
Right = 1,
|
||||
};
|
||||
|
||||
explicit VirtualGamepad(std::string input_engine_);
|
||||
|
||||
/**
|
||||
* Sets the status of all buttons bound with the key to pressed
|
||||
* @param player_index the player number that will take this action
|
||||
* @param button_id the id of the button
|
||||
* @param value indicates if the button is pressed or not
|
||||
*/
|
||||
void SetButtonState(std::size_t player_index, int button_id, bool value);
|
||||
void SetButtonState(std::size_t player_index, VirtualButton button_id, bool value);
|
||||
|
||||
/**
|
||||
* Sets the status of all buttons bound with the key to released
|
||||
* @param player_index the player number that will take this action
|
||||
* @param axis_id the id of the axis to move
|
||||
* @param x_value the position of the stick in the x axis
|
||||
* @param y_value the position of the stick in the y axis
|
||||
*/
|
||||
void SetStickPosition(std::size_t player_index, int axis_id, float x_value, float y_value);
|
||||
void SetStickPosition(std::size_t player_index, VirtualStick axis_id, float x_value,
|
||||
float y_value);
|
||||
|
||||
/// Restores all inputs into the neutral position
|
||||
void ResetControllers();
|
||||
|
||||
private:
|
||||
/// Returns the correct identifier corresponding to the player index
|
||||
PadIdentifier GetIdentifier(std::size_t player_index) const;
|
||||
};
|
||||
|
||||
} // namespace InputCommon
|
||||
@@ -200,6 +200,12 @@ bool MappingFactory::IsDriverValid(const MappingData& data) const {
|
||||
return false;
|
||||
}
|
||||
// The following drivers don't need to be mapped
|
||||
if (data.engine == "tas") {
|
||||
return false;
|
||||
}
|
||||
if (data.engine == "touch") {
|
||||
return false;
|
||||
}
|
||||
if (data.engine == "touch_from_button") {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
#include "input_common/drivers/touch_screen.h"
|
||||
#include "input_common/drivers/udp_client.h"
|
||||
#include "input_common/drivers/virtual_amiibo.h"
|
||||
#include "input_common/drivers/virtual_gamepad.h"
|
||||
#include "input_common/helpers/stick_from_buttons.h"
|
||||
#include "input_common/helpers/touch_from_buttons.h"
|
||||
#include "input_common/input_engine.h"
|
||||
@@ -26,33 +25,73 @@
|
||||
namespace InputCommon {
|
||||
|
||||
struct InputSubsystem::Impl {
|
||||
template <typename Engine>
|
||||
void RegisterEngine(std::string name, std::shared_ptr<Engine>& engine) {
|
||||
MappingCallback mapping_callback{[this](const MappingData& data) { RegisterInput(data); }};
|
||||
|
||||
engine = std::make_shared<Engine>(name);
|
||||
engine->SetMappingCallback(mapping_callback);
|
||||
|
||||
std::shared_ptr<InputFactory> input_factory = std::make_shared<InputFactory>(engine);
|
||||
std::shared_ptr<OutputFactory> output_factory = std::make_shared<OutputFactory>(engine);
|
||||
Common::Input::RegisterInputFactory(engine->GetEngineName(), std::move(input_factory));
|
||||
Common::Input::RegisterOutputFactory(engine->GetEngineName(), std::move(output_factory));
|
||||
}
|
||||
|
||||
void Initialize() {
|
||||
mapping_factory = std::make_shared<MappingFactory>();
|
||||
MappingCallback mapping_callback{[this](const MappingData& data) { RegisterInput(data); }};
|
||||
|
||||
keyboard = std::make_shared<Keyboard>("keyboard");
|
||||
keyboard->SetMappingCallback(mapping_callback);
|
||||
keyboard_factory = std::make_shared<InputFactory>(keyboard);
|
||||
keyboard_output_factory = std::make_shared<OutputFactory>(keyboard);
|
||||
Common::Input::RegisterInputFactory(keyboard->GetEngineName(), keyboard_factory);
|
||||
Common::Input::RegisterOutputFactory(keyboard->GetEngineName(), keyboard_output_factory);
|
||||
|
||||
mouse = std::make_shared<Mouse>("mouse");
|
||||
mouse->SetMappingCallback(mapping_callback);
|
||||
mouse_factory = std::make_shared<InputFactory>(mouse);
|
||||
mouse_output_factory = std::make_shared<OutputFactory>(mouse);
|
||||
Common::Input::RegisterInputFactory(mouse->GetEngineName(), mouse_factory);
|
||||
Common::Input::RegisterOutputFactory(mouse->GetEngineName(), mouse_output_factory);
|
||||
|
||||
touch_screen = std::make_shared<TouchScreen>("touch");
|
||||
touch_screen_factory = std::make_shared<InputFactory>(touch_screen);
|
||||
Common::Input::RegisterInputFactory(touch_screen->GetEngineName(), touch_screen_factory);
|
||||
|
||||
gcadapter = std::make_shared<GCAdapter>("gcpad");
|
||||
gcadapter->SetMappingCallback(mapping_callback);
|
||||
gcadapter_input_factory = std::make_shared<InputFactory>(gcadapter);
|
||||
gcadapter_output_factory = std::make_shared<OutputFactory>(gcadapter);
|
||||
Common::Input::RegisterInputFactory(gcadapter->GetEngineName(), gcadapter_input_factory);
|
||||
Common::Input::RegisterOutputFactory(gcadapter->GetEngineName(), gcadapter_output_factory);
|
||||
|
||||
udp_client = std::make_shared<CemuhookUDP::UDPClient>("cemuhookudp");
|
||||
udp_client->SetMappingCallback(mapping_callback);
|
||||
udp_client_input_factory = std::make_shared<InputFactory>(udp_client);
|
||||
udp_client_output_factory = std::make_shared<OutputFactory>(udp_client);
|
||||
Common::Input::RegisterInputFactory(udp_client->GetEngineName(), udp_client_input_factory);
|
||||
Common::Input::RegisterOutputFactory(udp_client->GetEngineName(),
|
||||
udp_client_output_factory);
|
||||
|
||||
tas_input = std::make_shared<TasInput::Tas>("tas");
|
||||
tas_input->SetMappingCallback(mapping_callback);
|
||||
tas_input_factory = std::make_shared<InputFactory>(tas_input);
|
||||
tas_output_factory = std::make_shared<OutputFactory>(tas_input);
|
||||
Common::Input::RegisterInputFactory(tas_input->GetEngineName(), tas_input_factory);
|
||||
Common::Input::RegisterOutputFactory(tas_input->GetEngineName(), tas_output_factory);
|
||||
|
||||
camera = std::make_shared<Camera>("camera");
|
||||
camera->SetMappingCallback(mapping_callback);
|
||||
camera_input_factory = std::make_shared<InputFactory>(camera);
|
||||
camera_output_factory = std::make_shared<OutputFactory>(camera);
|
||||
Common::Input::RegisterInputFactory(camera->GetEngineName(), camera_input_factory);
|
||||
Common::Input::RegisterOutputFactory(camera->GetEngineName(), camera_output_factory);
|
||||
|
||||
virtual_amiibo = std::make_shared<VirtualAmiibo>("virtual_amiibo");
|
||||
virtual_amiibo->SetMappingCallback(mapping_callback);
|
||||
virtual_amiibo_input_factory = std::make_shared<InputFactory>(virtual_amiibo);
|
||||
virtual_amiibo_output_factory = std::make_shared<OutputFactory>(virtual_amiibo);
|
||||
Common::Input::RegisterInputFactory(virtual_amiibo->GetEngineName(),
|
||||
virtual_amiibo_input_factory);
|
||||
Common::Input::RegisterOutputFactory(virtual_amiibo->GetEngineName(),
|
||||
virtual_amiibo_output_factory);
|
||||
|
||||
RegisterEngine("keyboard", keyboard);
|
||||
RegisterEngine("mouse", mouse);
|
||||
RegisterEngine("touch", touch_screen);
|
||||
RegisterEngine("gcpad", gcadapter);
|
||||
RegisterEngine("cemuhookudp", udp_client);
|
||||
RegisterEngine("tas", tas_input);
|
||||
RegisterEngine("camera", camera);
|
||||
RegisterEngine("virtual_amiibo", virtual_amiibo);
|
||||
RegisterEngine("virtual_gamepad", virtual_gamepad);
|
||||
#ifdef HAVE_SDL2
|
||||
RegisterEngine("sdl", sdl);
|
||||
sdl = std::make_shared<SDLDriver>("sdl");
|
||||
sdl->SetMappingCallback(mapping_callback);
|
||||
sdl_input_factory = std::make_shared<InputFactory>(sdl);
|
||||
sdl_output_factory = std::make_shared<OutputFactory>(sdl);
|
||||
Common::Input::RegisterInputFactory(sdl->GetEngineName(), sdl_input_factory);
|
||||
Common::Input::RegisterOutputFactory(sdl->GetEngineName(), sdl_output_factory);
|
||||
#endif
|
||||
|
||||
Common::Input::RegisterInputFactory("touch_from_button",
|
||||
@@ -61,25 +100,42 @@ struct InputSubsystem::Impl {
|
||||
std::make_shared<StickFromButton>());
|
||||
}
|
||||
|
||||
template <typename Engine>
|
||||
void UnregisterEngine(std::shared_ptr<Engine>& engine) {
|
||||
Common::Input::UnregisterInputFactory(engine->GetEngineName());
|
||||
Common::Input::UnregisterOutputFactory(engine->GetEngineName());
|
||||
engine.reset();
|
||||
}
|
||||
|
||||
void Shutdown() {
|
||||
UnregisterEngine(keyboard);
|
||||
UnregisterEngine(mouse);
|
||||
UnregisterEngine(touch_screen);
|
||||
UnregisterEngine(gcadapter);
|
||||
UnregisterEngine(udp_client);
|
||||
UnregisterEngine(tas_input);
|
||||
UnregisterEngine(camera);
|
||||
UnregisterEngine(virtual_amiibo);
|
||||
UnregisterEngine(virtual_gamepad);
|
||||
Common::Input::UnregisterInputFactory(keyboard->GetEngineName());
|
||||
Common::Input::UnregisterOutputFactory(keyboard->GetEngineName());
|
||||
keyboard.reset();
|
||||
|
||||
Common::Input::UnregisterInputFactory(mouse->GetEngineName());
|
||||
Common::Input::UnregisterOutputFactory(mouse->GetEngineName());
|
||||
mouse.reset();
|
||||
|
||||
Common::Input::UnregisterInputFactory(touch_screen->GetEngineName());
|
||||
touch_screen.reset();
|
||||
|
||||
Common::Input::UnregisterInputFactory(gcadapter->GetEngineName());
|
||||
Common::Input::UnregisterOutputFactory(gcadapter->GetEngineName());
|
||||
gcadapter.reset();
|
||||
|
||||
Common::Input::UnregisterInputFactory(udp_client->GetEngineName());
|
||||
Common::Input::UnregisterOutputFactory(udp_client->GetEngineName());
|
||||
udp_client.reset();
|
||||
|
||||
Common::Input::UnregisterInputFactory(tas_input->GetEngineName());
|
||||
Common::Input::UnregisterOutputFactory(tas_input->GetEngineName());
|
||||
tas_input.reset();
|
||||
|
||||
Common::Input::UnregisterInputFactory(camera->GetEngineName());
|
||||
Common::Input::UnregisterOutputFactory(camera->GetEngineName());
|
||||
camera.reset();
|
||||
|
||||
Common::Input::UnregisterInputFactory(virtual_amiibo->GetEngineName());
|
||||
Common::Input::UnregisterOutputFactory(virtual_amiibo->GetEngineName());
|
||||
virtual_amiibo.reset();
|
||||
|
||||
#ifdef HAVE_SDL2
|
||||
UnregisterEngine(sdl);
|
||||
Common::Input::UnregisterInputFactory(sdl->GetEngineName());
|
||||
Common::Input::UnregisterOutputFactory(sdl->GetEngineName());
|
||||
sdl.reset();
|
||||
#endif
|
||||
|
||||
Common::Input::UnregisterInputFactory("touch_from_button");
|
||||
@@ -107,86 +163,117 @@ struct InputSubsystem::Impl {
|
||||
return devices;
|
||||
}
|
||||
|
||||
[[nodiscard]] std::shared_ptr<InputEngine> GetInputEngine(
|
||||
[[nodiscard]] AnalogMapping GetAnalogMappingForDevice(
|
||||
const Common::ParamPackage& params) const {
|
||||
if (!params.Has("engine") || params.Get("engine", "") == "any") {
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
const std::string engine = params.Get("engine", "");
|
||||
if (engine == keyboard->GetEngineName()) {
|
||||
return keyboard;
|
||||
}
|
||||
if (engine == mouse->GetEngineName()) {
|
||||
return mouse;
|
||||
return mouse->GetAnalogMappingForDevice(params);
|
||||
}
|
||||
if (engine == gcadapter->GetEngineName()) {
|
||||
return gcadapter;
|
||||
return gcadapter->GetAnalogMappingForDevice(params);
|
||||
}
|
||||
if (engine == udp_client->GetEngineName()) {
|
||||
return udp_client;
|
||||
return udp_client->GetAnalogMappingForDevice(params);
|
||||
}
|
||||
if (engine == tas_input->GetEngineName()) {
|
||||
return tas_input->GetAnalogMappingForDevice(params);
|
||||
}
|
||||
#ifdef HAVE_SDL2
|
||||
if (engine == sdl->GetEngineName()) {
|
||||
return sdl;
|
||||
return sdl->GetAnalogMappingForDevice(params);
|
||||
}
|
||||
#endif
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
[[nodiscard]] AnalogMapping GetAnalogMappingForDevice(
|
||||
const Common::ParamPackage& params) const {
|
||||
const auto input_engine = GetInputEngine(params);
|
||||
|
||||
if (input_engine == nullptr) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return input_engine->GetAnalogMappingForDevice(params);
|
||||
return {};
|
||||
}
|
||||
|
||||
[[nodiscard]] ButtonMapping GetButtonMappingForDevice(
|
||||
const Common::ParamPackage& params) const {
|
||||
const auto input_engine = GetInputEngine(params);
|
||||
|
||||
if (input_engine == nullptr) {
|
||||
if (!params.Has("engine") || params.Get("engine", "") == "any") {
|
||||
return {};
|
||||
}
|
||||
|
||||
return input_engine->GetButtonMappingForDevice(params);
|
||||
const std::string engine = params.Get("engine", "");
|
||||
if (engine == gcadapter->GetEngineName()) {
|
||||
return gcadapter->GetButtonMappingForDevice(params);
|
||||
}
|
||||
if (engine == udp_client->GetEngineName()) {
|
||||
return udp_client->GetButtonMappingForDevice(params);
|
||||
}
|
||||
if (engine == tas_input->GetEngineName()) {
|
||||
return tas_input->GetButtonMappingForDevice(params);
|
||||
}
|
||||
#ifdef HAVE_SDL2
|
||||
if (engine == sdl->GetEngineName()) {
|
||||
return sdl->GetButtonMappingForDevice(params);
|
||||
}
|
||||
#endif
|
||||
return {};
|
||||
}
|
||||
|
||||
[[nodiscard]] MotionMapping GetMotionMappingForDevice(
|
||||
const Common::ParamPackage& params) const {
|
||||
const auto input_engine = GetInputEngine(params);
|
||||
|
||||
if (input_engine == nullptr) {
|
||||
if (!params.Has("engine") || params.Get("engine", "") == "any") {
|
||||
return {};
|
||||
}
|
||||
|
||||
return input_engine->GetMotionMappingForDevice(params);
|
||||
const std::string engine = params.Get("engine", "");
|
||||
if (engine == udp_client->GetEngineName()) {
|
||||
return udp_client->GetMotionMappingForDevice(params);
|
||||
}
|
||||
#ifdef HAVE_SDL2
|
||||
if (engine == sdl->GetEngineName()) {
|
||||
return sdl->GetMotionMappingForDevice(params);
|
||||
}
|
||||
#endif
|
||||
return {};
|
||||
}
|
||||
|
||||
Common::Input::ButtonNames GetButtonName(const Common::ParamPackage& params) const {
|
||||
if (!params.Has("engine") || params.Get("engine", "") == "any") {
|
||||
return Common::Input::ButtonNames::Undefined;
|
||||
}
|
||||
const auto input_engine = GetInputEngine(params);
|
||||
|
||||
if (input_engine == nullptr) {
|
||||
return Common::Input::ButtonNames::Invalid;
|
||||
const std::string engine = params.Get("engine", "");
|
||||
if (engine == mouse->GetEngineName()) {
|
||||
return mouse->GetUIName(params);
|
||||
}
|
||||
|
||||
return input_engine->GetUIName(params);
|
||||
if (engine == gcadapter->GetEngineName()) {
|
||||
return gcadapter->GetUIName(params);
|
||||
}
|
||||
if (engine == udp_client->GetEngineName()) {
|
||||
return udp_client->GetUIName(params);
|
||||
}
|
||||
if (engine == tas_input->GetEngineName()) {
|
||||
return tas_input->GetUIName(params);
|
||||
}
|
||||
#ifdef HAVE_SDL2
|
||||
if (engine == sdl->GetEngineName()) {
|
||||
return sdl->GetUIName(params);
|
||||
}
|
||||
#endif
|
||||
return Common::Input::ButtonNames::Invalid;
|
||||
}
|
||||
|
||||
bool IsStickInverted(const Common::ParamPackage& params) {
|
||||
const auto input_engine = GetInputEngine(params);
|
||||
|
||||
if (input_engine == nullptr) {
|
||||
return false;
|
||||
const std::string engine = params.Get("engine", "");
|
||||
if (engine == mouse->GetEngineName()) {
|
||||
return mouse->IsStickInverted(params);
|
||||
}
|
||||
|
||||
return input_engine->IsStickInverted(params);
|
||||
if (engine == gcadapter->GetEngineName()) {
|
||||
return gcadapter->IsStickInverted(params);
|
||||
}
|
||||
if (engine == udp_client->GetEngineName()) {
|
||||
return udp_client->IsStickInverted(params);
|
||||
}
|
||||
if (engine == tas_input->GetEngineName()) {
|
||||
return tas_input->IsStickInverted(params);
|
||||
}
|
||||
#ifdef HAVE_SDL2
|
||||
if (engine == sdl->GetEngineName()) {
|
||||
return sdl->IsStickInverted(params);
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsController(const Common::ParamPackage& params) {
|
||||
@@ -203,9 +290,6 @@ struct InputSubsystem::Impl {
|
||||
if (engine == tas_input->GetEngineName()) {
|
||||
return true;
|
||||
}
|
||||
if (engine == virtual_gamepad->GetEngineName()) {
|
||||
return true;
|
||||
}
|
||||
#ifdef HAVE_SDL2
|
||||
if (engine == sdl->GetEngineName()) {
|
||||
return true;
|
||||
@@ -254,10 +338,28 @@ struct InputSubsystem::Impl {
|
||||
std::shared_ptr<CemuhookUDP::UDPClient> udp_client;
|
||||
std::shared_ptr<Camera> camera;
|
||||
std::shared_ptr<VirtualAmiibo> virtual_amiibo;
|
||||
std::shared_ptr<VirtualGamepad> virtual_gamepad;
|
||||
|
||||
std::shared_ptr<InputFactory> keyboard_factory;
|
||||
std::shared_ptr<InputFactory> mouse_factory;
|
||||
std::shared_ptr<InputFactory> gcadapter_input_factory;
|
||||
std::shared_ptr<InputFactory> touch_screen_factory;
|
||||
std::shared_ptr<InputFactory> udp_client_input_factory;
|
||||
std::shared_ptr<InputFactory> tas_input_factory;
|
||||
std::shared_ptr<InputFactory> camera_input_factory;
|
||||
std::shared_ptr<InputFactory> virtual_amiibo_input_factory;
|
||||
|
||||
std::shared_ptr<OutputFactory> keyboard_output_factory;
|
||||
std::shared_ptr<OutputFactory> mouse_output_factory;
|
||||
std::shared_ptr<OutputFactory> gcadapter_output_factory;
|
||||
std::shared_ptr<OutputFactory> udp_client_output_factory;
|
||||
std::shared_ptr<OutputFactory> tas_output_factory;
|
||||
std::shared_ptr<OutputFactory> camera_output_factory;
|
||||
std::shared_ptr<OutputFactory> virtual_amiibo_output_factory;
|
||||
|
||||
#ifdef HAVE_SDL2
|
||||
std::shared_ptr<SDLDriver> sdl;
|
||||
std::shared_ptr<InputFactory> sdl_input_factory;
|
||||
std::shared_ptr<OutputFactory> sdl_output_factory;
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -321,14 +423,6 @@ const VirtualAmiibo* InputSubsystem::GetVirtualAmiibo() const {
|
||||
return impl->virtual_amiibo.get();
|
||||
}
|
||||
|
||||
VirtualGamepad* InputSubsystem::GetVirtualGamepad() {
|
||||
return impl->virtual_gamepad.get();
|
||||
}
|
||||
|
||||
const VirtualGamepad* InputSubsystem::GetVirtualGamepad() const {
|
||||
return impl->virtual_gamepad.get();
|
||||
}
|
||||
|
||||
std::vector<Common::ParamPackage> InputSubsystem::GetInputDevices() const {
|
||||
return impl->GetInputDevices();
|
||||
}
|
||||
|
||||
@@ -34,7 +34,6 @@ class Keyboard;
|
||||
class Mouse;
|
||||
class TouchScreen;
|
||||
class VirtualAmiibo;
|
||||
class VirtualGamepad;
|
||||
struct MappingData;
|
||||
} // namespace InputCommon
|
||||
|
||||
@@ -109,12 +108,6 @@ public:
|
||||
/// Retrieves the underlying virtual amiibo input device.
|
||||
[[nodiscard]] const VirtualAmiibo* GetVirtualAmiibo() const;
|
||||
|
||||
/// Retrieves the underlying virtual gamepad input device.
|
||||
[[nodiscard]] VirtualGamepad* GetVirtualGamepad();
|
||||
|
||||
/// Retrieves the underlying virtual gamepad input device.
|
||||
[[nodiscard]] const VirtualGamepad* GetVirtualGamepad() const;
|
||||
|
||||
/**
|
||||
* Returns all available input devices that this Factory can create a new device with.
|
||||
* Each returned ParamPackage should have a `display` field used for display, a `engine` field
|
||||
|
||||
@@ -314,18 +314,6 @@ const char* ToString(VkResult result) noexcept {
|
||||
return "VK_ERROR_VALIDATION_FAILED_EXT";
|
||||
case VkResult::VK_ERROR_INVALID_SHADER_NV:
|
||||
return "VK_ERROR_INVALID_SHADER_NV";
|
||||
case VkResult::VK_ERROR_IMAGE_USAGE_NOT_SUPPORTED_KHR:
|
||||
return "VK_ERROR_IMAGE_USAGE_NOT_SUPPORTED_KHR";
|
||||
case VkResult::VK_ERROR_VIDEO_PICTURE_LAYOUT_NOT_SUPPORTED_KHR:
|
||||
return "VK_ERROR_VIDEO_PICTURE_LAYOUT_NOT_SUPPORTED_KHR";
|
||||
case VkResult::VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR:
|
||||
return "VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR";
|
||||
case VkResult::VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR:
|
||||
return "VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR";
|
||||
case VkResult::VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR:
|
||||
return "VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR";
|
||||
case VkResult::VK_ERROR_VIDEO_STD_VERSION_NOT_SUPPORTED_KHR:
|
||||
return "VK_ERROR_VIDEO_STD_VERSION_NOT_SUPPORTED_KHR";
|
||||
case VkResult::VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT:
|
||||
return "VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT";
|
||||
case VkResult::VK_ERROR_FRAGMENTATION_EXT:
|
||||
|
||||
@@ -46,28 +46,30 @@
|
||||
|
||||
static Core::Frontend::WindowSystemType GetWindowSystemType();
|
||||
|
||||
EmuThread::EmuThread(Core::System& system) : m_system{system} {}
|
||||
EmuThread::EmuThread(Core::System& system_) : system{system_} {}
|
||||
|
||||
EmuThread::~EmuThread() = default;
|
||||
|
||||
void EmuThread::run() {
|
||||
const char* name = "EmuControlThread";
|
||||
MicroProfileOnThreadCreate(name);
|
||||
Common::SetCurrentThreadName(name);
|
||||
std::string name = "EmuControlThread";
|
||||
MicroProfileOnThreadCreate(name.c_str());
|
||||
Common::SetCurrentThreadName(name.c_str());
|
||||
|
||||
auto& gpu = m_system.GPU();
|
||||
auto stop_token = m_stop_source.get_token();
|
||||
auto& gpu = system.GPU();
|
||||
auto stop_token = stop_source.get_token();
|
||||
bool debugger_should_start = system.DebuggerEnabled();
|
||||
|
||||
m_system.RegisterHostThread();
|
||||
system.RegisterHostThread();
|
||||
|
||||
// Main process has been loaded. Make the context current to this thread and begin GPU and CPU
|
||||
// execution.
|
||||
gpu.ObtainContext();
|
||||
|
||||
emit LoadProgress(VideoCore::LoadCallbackStage::Prepare, 0, 0);
|
||||
|
||||
if (Settings::values.use_disk_shader_cache.GetValue()) {
|
||||
m_system.Renderer().ReadRasterizer()->LoadDiskResources(
|
||||
m_system.GetCurrentProcessProgramID(), stop_token,
|
||||
system.Renderer().ReadRasterizer()->LoadDiskResources(
|
||||
system.GetCurrentProcessProgramID(), stop_token,
|
||||
[this](VideoCore::LoadCallbackStage stage, std::size_t value, std::size_t total) {
|
||||
emit LoadProgress(stage, value, total);
|
||||
});
|
||||
@@ -77,34 +79,57 @@ void EmuThread::run() {
|
||||
gpu.ReleaseContext();
|
||||
gpu.Start();
|
||||
|
||||
m_system.GetCpuManager().OnGpuReady();
|
||||
system.GetCpuManager().OnGpuReady();
|
||||
|
||||
if (m_system.DebuggerEnabled()) {
|
||||
m_system.InitializeDebugger();
|
||||
}
|
||||
system.RegisterExitCallback([this]() {
|
||||
stop_source.request_stop();
|
||||
SetRunning(false);
|
||||
});
|
||||
|
||||
// Holds whether the cpu was running during the last iteration,
|
||||
// so that the DebugModeLeft signal can be emitted before the
|
||||
// next execution step
|
||||
bool was_active = false;
|
||||
while (!stop_token.stop_requested()) {
|
||||
std::unique_lock lk{m_should_run_mutex};
|
||||
if (m_should_run) {
|
||||
m_system.Run();
|
||||
m_is_running.store(true);
|
||||
m_is_running.notify_all();
|
||||
if (running) {
|
||||
if (was_active) {
|
||||
emit DebugModeLeft();
|
||||
}
|
||||
|
||||
Common::CondvarWait(m_should_run_cv, lk, stop_token, [&] { return !m_should_run; });
|
||||
running_guard = true;
|
||||
Core::SystemResultStatus result = system.Run();
|
||||
if (result != Core::SystemResultStatus::Success) {
|
||||
running_guard = false;
|
||||
this->SetRunning(false);
|
||||
emit ErrorThrown(result, system.GetStatusDetails());
|
||||
}
|
||||
|
||||
if (debugger_should_start) {
|
||||
system.InitializeDebugger();
|
||||
debugger_should_start = false;
|
||||
}
|
||||
|
||||
running_wait.Wait();
|
||||
result = system.Pause();
|
||||
if (result != Core::SystemResultStatus::Success) {
|
||||
running_guard = false;
|
||||
this->SetRunning(false);
|
||||
emit ErrorThrown(result, system.GetStatusDetails());
|
||||
}
|
||||
running_guard = false;
|
||||
|
||||
if (!stop_token.stop_requested()) {
|
||||
was_active = true;
|
||||
emit DebugModeEntered();
|
||||
}
|
||||
} else {
|
||||
m_system.Pause();
|
||||
m_is_running.store(false);
|
||||
m_is_running.notify_all();
|
||||
|
||||
emit DebugModeEntered();
|
||||
Common::CondvarWait(m_should_run_cv, lk, stop_token, [&] { return m_should_run; });
|
||||
emit DebugModeLeft();
|
||||
std::unique_lock lock{running_mutex};
|
||||
Common::CondvarWait(running_cv, lock, stop_token, [&] { return IsRunning(); });
|
||||
}
|
||||
}
|
||||
|
||||
// Shutdown the main emulated process
|
||||
m_system.DetachDebugger();
|
||||
m_system.ShutdownMainProcess();
|
||||
system.ShutdownMainProcess();
|
||||
|
||||
#if MICROPROFILE_ENABLED
|
||||
MicroProfileOnThreadExit();
|
||||
@@ -739,9 +764,7 @@ void GRenderWindow::InitializeCamera() {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto camera_width = input_subsystem->GetCamera()->getImageWidth();
|
||||
const auto camera_height = input_subsystem->GetCamera()->getImageHeight();
|
||||
camera_data.resize(camera_width * camera_height);
|
||||
camera_data.resize(CAMERA_WIDTH * CAMERA_HEIGHT);
|
||||
camera_capture->setCaptureDestination(QCameraImageCapture::CaptureDestination::CaptureToBuffer);
|
||||
connect(camera_capture.get(), &QCameraImageCapture::imageCaptured, this,
|
||||
&GRenderWindow::OnCameraCapture);
|
||||
@@ -797,22 +820,14 @@ void GRenderWindow::RequestCameraCapture() {
|
||||
}
|
||||
|
||||
void GRenderWindow::OnCameraCapture(int requestId, const QImage& img) {
|
||||
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) && YUZU_USE_QT_MULTIMEDIA
|
||||
// TODO: Capture directly in the format and resolution needed
|
||||
const auto camera_width = input_subsystem->GetCamera()->getImageWidth();
|
||||
const auto camera_height = input_subsystem->GetCamera()->getImageHeight();
|
||||
const auto converted =
|
||||
img.scaled(static_cast<int>(camera_width), static_cast<int>(camera_height),
|
||||
Qt::AspectRatioMode::IgnoreAspectRatio,
|
||||
img.scaled(CAMERA_WIDTH, CAMERA_HEIGHT, Qt::AspectRatioMode::IgnoreAspectRatio,
|
||||
Qt::TransformationMode::SmoothTransformation)
|
||||
.mirrored(false, true);
|
||||
if (camera_data.size() != camera_width * camera_height) {
|
||||
camera_data.resize(camera_width * camera_height);
|
||||
}
|
||||
std::memcpy(camera_data.data(), converted.bits(), camera_width * camera_height * sizeof(u32));
|
||||
input_subsystem->GetCamera()->SetCameraData(camera_width, camera_height, camera_data);
|
||||
std::memcpy(camera_data.data(), converted.bits(), CAMERA_WIDTH * CAMERA_HEIGHT * sizeof(u32));
|
||||
input_subsystem->GetCamera()->SetCameraData(CAMERA_WIDTH, CAMERA_HEIGHT, camera_data);
|
||||
pending_camera_snapshots = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool GRenderWindow::event(QEvent* event) {
|
||||
|
||||
@@ -47,7 +47,7 @@ class EmuThread final : public QThread {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit EmuThread(Core::System& system);
|
||||
explicit EmuThread(Core::System& system_);
|
||||
~EmuThread() override;
|
||||
|
||||
/**
|
||||
@@ -57,30 +57,30 @@ public:
|
||||
void run() override;
|
||||
|
||||
/**
|
||||
* Sets whether the emulation thread should run or not
|
||||
* @param should_run Boolean value, set the emulation thread to running if true
|
||||
* Sets whether the emulation thread is running or not
|
||||
* @param running_ Boolean value, set the emulation thread to running if true
|
||||
* @note This function is thread-safe
|
||||
*/
|
||||
void SetRunning(bool should_run) {
|
||||
// TODO: Prevent other threads from modifying the state until we finish.
|
||||
{
|
||||
// Notify the running thread to change state.
|
||||
std::unique_lock run_lk{m_should_run_mutex};
|
||||
m_should_run = should_run;
|
||||
m_should_run_cv.notify_one();
|
||||
}
|
||||
|
||||
// Wait until paused, if pausing.
|
||||
if (!should_run) {
|
||||
m_is_running.wait(true);
|
||||
void SetRunning(bool running_) {
|
||||
std::unique_lock lock{running_mutex};
|
||||
running = running_;
|
||||
lock.unlock();
|
||||
running_cv.notify_all();
|
||||
if (!running) {
|
||||
running_wait.Set();
|
||||
/// Wait until effectively paused
|
||||
while (running_guard)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the emulation thread is running or not
|
||||
* @return True if the emulation thread is running, otherwise false
|
||||
* @note This function is thread-safe
|
||||
*/
|
||||
bool IsRunning() const {
|
||||
return m_is_running.load() || m_should_run;
|
||||
return running;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -88,17 +88,18 @@ public:
|
||||
*/
|
||||
void ForceStop() {
|
||||
LOG_WARNING(Frontend, "Force stopping EmuThread");
|
||||
m_stop_source.request_stop();
|
||||
stop_source.request_stop();
|
||||
SetRunning(false);
|
||||
}
|
||||
|
||||
private:
|
||||
Core::System& m_system;
|
||||
|
||||
std::stop_source m_stop_source;
|
||||
std::mutex m_should_run_mutex;
|
||||
std::condition_variable_any m_should_run_cv;
|
||||
std::atomic<bool> m_is_running{false};
|
||||
bool m_should_run{true};
|
||||
bool running = false;
|
||||
std::stop_source stop_source;
|
||||
std::mutex running_mutex;
|
||||
std::condition_variable_any running_cv;
|
||||
Common::Event running_wait{};
|
||||
std::atomic_bool running_guard{false};
|
||||
Core::System& system;
|
||||
|
||||
signals:
|
||||
/**
|
||||
@@ -119,6 +120,8 @@ signals:
|
||||
*/
|
||||
void DebugModeLeft();
|
||||
|
||||
void ErrorThrown(Core::SystemResultStatus, std::string);
|
||||
|
||||
void LoadProgress(VideoCore::LoadCallbackStage stage, std::size_t value, std::size_t total);
|
||||
};
|
||||
|
||||
@@ -239,14 +242,16 @@ private:
|
||||
bool first_frame = false;
|
||||
InputCommon::TasInput::TasState last_tas_state;
|
||||
|
||||
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) && YUZU_USE_QT_MULTIMEDIA
|
||||
bool is_virtual_camera;
|
||||
int pending_camera_snapshots;
|
||||
std::vector<u32> camera_data;
|
||||
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) && YUZU_USE_QT_MULTIMEDIA
|
||||
std::unique_ptr<QCamera> camera;
|
||||
std::unique_ptr<QCameraImageCapture> camera_capture;
|
||||
std::unique_ptr<QTimer> camera_timer;
|
||||
static constexpr std::size_t CAMERA_WIDTH = 320;
|
||||
static constexpr std::size_t CAMERA_HEIGHT = 240;
|
||||
std::vector<u32> camera_data;
|
||||
#endif
|
||||
std::unique_ptr<QTimer> camera_timer;
|
||||
|
||||
Core::System& system;
|
||||
|
||||
|
||||
@@ -783,6 +783,8 @@ void Config::ReadSystemValues() {
|
||||
}
|
||||
}
|
||||
|
||||
ReadBasicSetting(Settings::values.device_name);
|
||||
|
||||
if (global) {
|
||||
ReadBasicSetting(Settings::values.current_user);
|
||||
Settings::values.current_user = std::clamp<int>(Settings::values.current_user.GetValue(), 0,
|
||||
@@ -795,7 +797,6 @@ void Config::ReadSystemValues() {
|
||||
} else {
|
||||
Settings::values.custom_rtc = std::nullopt;
|
||||
}
|
||||
ReadBasicSetting(Settings::values.device_name);
|
||||
}
|
||||
|
||||
ReadGlobalSetting(Settings::values.sound_index);
|
||||
@@ -1406,6 +1407,7 @@ void Config::SaveSystemValues() {
|
||||
Settings::values.rng_seed.UsingGlobal());
|
||||
WriteSetting(QStringLiteral("rng_seed"), Settings::values.rng_seed.GetValue(global).value_or(0),
|
||||
0, Settings::values.rng_seed.UsingGlobal());
|
||||
WriteBasicSetting(Settings::values.device_name);
|
||||
|
||||
if (global) {
|
||||
WriteBasicSetting(Settings::values.current_user);
|
||||
@@ -1414,7 +1416,6 @@ void Config::SaveSystemValues() {
|
||||
false);
|
||||
WriteSetting(QStringLiteral("custom_rtc"),
|
||||
QVariant::fromValue<long long>(Settings::values.custom_rtc.value_or(0)), 0);
|
||||
WriteBasicSetting(Settings::values.device_name);
|
||||
}
|
||||
|
||||
WriteGlobalSetting(Settings::values.sound_index);
|
||||
|
||||
@@ -269,7 +269,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
||||
InputCommon::InputSubsystem* input_subsystem_,
|
||||
InputProfiles* profiles_, Core::HID::HIDCore& hid_core_,
|
||||
bool is_powered_on_, bool debug_)
|
||||
: QWidget(parent),
|
||||
: QScrollArea(parent),
|
||||
ui(std::make_unique<Ui::ConfigureInputPlayer>()), player_index{player_index_}, debug{debug_},
|
||||
is_powered_on{is_powered_on_}, input_subsystem{input_subsystem_}, profiles(profiles_),
|
||||
timeout_timer(std::make_unique<QTimer>()),
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <QWidget>
|
||||
#include <QScrollArea>
|
||||
|
||||
#include "common/param_package.h"
|
||||
#include "common/settings.h"
|
||||
@@ -46,7 +46,7 @@ class EmulatedController;
|
||||
enum class NpadStyleIndex : u8;
|
||||
} // namespace Core::HID
|
||||
|
||||
class ConfigureInputPlayer : public QWidget {
|
||||
class ConfigureInputPlayer : public QScrollArea {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1498,7 +1498,7 @@ void GMainWindow::SetupSigInterrupts() {
|
||||
|
||||
void GMainWindow::HandleSigInterrupt(int sig) {
|
||||
if (sig == SIGINT) {
|
||||
_exit(1);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Calling into Qt directly from a signal handler is not safe,
|
||||
@@ -1550,9 +1550,8 @@ void GMainWindow::AllowOSSleep() {
|
||||
|
||||
bool GMainWindow::LoadROM(const QString& filename, u64 program_id, std::size_t program_index) {
|
||||
// Shutdown previous session if the emu thread is still active...
|
||||
if (emu_thread != nullptr) {
|
||||
if (emu_thread != nullptr)
|
||||
ShutdownGame();
|
||||
}
|
||||
|
||||
if (!render_window->InitRenderTarget()) {
|
||||
return false;
|
||||
@@ -1711,11 +1710,6 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t
|
||||
system->RegisterExecuteProgramCallback(
|
||||
[this](std::size_t program_index_) { render_window->ExecuteProgram(program_index_); });
|
||||
|
||||
system->RegisterExitCallback([this] {
|
||||
emu_thread->ForceStop();
|
||||
render_window->Exit();
|
||||
});
|
||||
|
||||
connect(render_window, &GRenderWindow::Closed, this, &GMainWindow::OnStopGame);
|
||||
connect(render_window, &GRenderWindow::MouseActivity, this, &GMainWindow::OnMouseActivity);
|
||||
// BlockingQueuedConnection is important here, it makes sure we've finished refreshing our views
|
||||
@@ -1785,9 +1779,9 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t
|
||||
OnStartGame();
|
||||
}
|
||||
|
||||
bool GMainWindow::OnShutdownBegin() {
|
||||
void GMainWindow::ShutdownGame() {
|
||||
if (!emulation_running) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ui->action_Fullscreen->isChecked()) {
|
||||
@@ -1799,55 +1793,21 @@ bool GMainWindow::OnShutdownBegin() {
|
||||
// Disable unlimited frame rate
|
||||
Settings::values.use_speed_limit.SetValue(true);
|
||||
|
||||
if (system->IsShuttingDown()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
system->SetShuttingDown(true);
|
||||
system->DetachDebugger();
|
||||
discord_rpc->Pause();
|
||||
|
||||
RequestGameExit();
|
||||
emu_thread->disconnect();
|
||||
emu_thread->SetRunning(true);
|
||||
|
||||
emit EmulationStopping();
|
||||
|
||||
shutdown_timer.setSingleShot(true);
|
||||
shutdown_timer.start(system->DebuggerEnabled() ? 0 : 5000);
|
||||
connect(&shutdown_timer, &QTimer::timeout, this, &GMainWindow::OnEmulationStopTimeExpired);
|
||||
connect(emu_thread.get(), &QThread::finished, this, &GMainWindow::OnEmulationStopped);
|
||||
|
||||
// Disable everything to prevent anything from being triggered here
|
||||
ui->action_Pause->setEnabled(false);
|
||||
ui->action_Restart->setEnabled(false);
|
||||
ui->action_Stop->setEnabled(false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GMainWindow::OnShutdownBeginDialog() {
|
||||
shutdown_dialog = new OverlayDialog(this, *system, QString{}, tr("Closing software..."),
|
||||
QString{}, QString{}, Qt::AlignHCenter | Qt::AlignVCenter);
|
||||
shutdown_dialog->open();
|
||||
}
|
||||
|
||||
void GMainWindow::OnEmulationStopTimeExpired() {
|
||||
if (emu_thread) {
|
||||
// Wait for emulation thread to complete and delete it
|
||||
if (!emu_thread->wait(5000)) {
|
||||
emu_thread->ForceStop();
|
||||
emu_thread->wait();
|
||||
}
|
||||
}
|
||||
|
||||
void GMainWindow::OnEmulationStopped() {
|
||||
shutdown_timer.stop();
|
||||
emu_thread->disconnect();
|
||||
emu_thread->wait();
|
||||
emu_thread = nullptr;
|
||||
|
||||
if (shutdown_dialog) {
|
||||
shutdown_dialog->deleteLater();
|
||||
shutdown_dialog = nullptr;
|
||||
}
|
||||
|
||||
emulation_running = false;
|
||||
|
||||
discord_rpc->Update();
|
||||
@@ -1893,20 +1853,6 @@ void GMainWindow::OnEmulationStopped() {
|
||||
|
||||
// When closing the game, destroy the GLWindow to clear the context after the game is closed
|
||||
render_window->ReleaseRenderTarget();
|
||||
|
||||
Settings::RestoreGlobalState(system->IsPoweredOn());
|
||||
system->HIDCore().ReloadInputDevices();
|
||||
UpdateStatusButtons();
|
||||
}
|
||||
|
||||
void GMainWindow::ShutdownGame() {
|
||||
if (!emulation_running) {
|
||||
return;
|
||||
}
|
||||
|
||||
OnShutdownBegin();
|
||||
OnEmulationStopTimeExpired();
|
||||
OnEmulationStopped();
|
||||
}
|
||||
|
||||
void GMainWindow::StoreRecentFile(const QString& filename) {
|
||||
@@ -2715,9 +2661,6 @@ void GMainWindow::OnMenuInstallToNAND() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Save folder location of the first selected file
|
||||
UISettings::values.roms_path = QFileInfo(filenames[0]).path();
|
||||
|
||||
int remaining = filenames.size();
|
||||
|
||||
// This would only overflow above 2^43 bytes (8.796 TB)
|
||||
@@ -2973,6 +2916,8 @@ void GMainWindow::OnStartGame() {
|
||||
|
||||
emu_thread->SetRunning(true);
|
||||
|
||||
connect(emu_thread.get(), &EmuThread::ErrorThrown, this, &GMainWindow::OnCoreError);
|
||||
|
||||
UpdateMenuState();
|
||||
OnTasStateChanged();
|
||||
|
||||
@@ -3009,9 +2954,11 @@ void GMainWindow::OnStopGame() {
|
||||
return;
|
||||
}
|
||||
|
||||
if (OnShutdownBegin()) {
|
||||
OnShutdownBeginDialog();
|
||||
}
|
||||
ShutdownGame();
|
||||
|
||||
Settings::RestoreGlobalState(system->IsPoweredOn());
|
||||
system->HIDCore().ReloadInputDevices();
|
||||
UpdateStatusButtons();
|
||||
}
|
||||
|
||||
void GMainWindow::OnLoadComplete() {
|
||||
@@ -3954,6 +3901,79 @@ void GMainWindow::OnMouseActivity() {
|
||||
mouse_center_timer.stop();
|
||||
}
|
||||
|
||||
void GMainWindow::OnCoreError(Core::SystemResultStatus result, std::string details) {
|
||||
QMessageBox::StandardButton answer;
|
||||
QString status_message;
|
||||
const QString common_message =
|
||||
tr("The game you are trying to load requires additional files from your Switch to be "
|
||||
"dumped "
|
||||
"before playing.<br/><br/>For more information on dumping these files, please see the "
|
||||
"following wiki page: <a "
|
||||
"href='https://yuzu-emu.org/wiki/"
|
||||
"dumping-system-archives-and-the-shared-fonts-from-a-switch-console/'>Dumping System "
|
||||
"Archives and the Shared Fonts from a Switch Console</a>.<br/><br/>Would you like to "
|
||||
"quit "
|
||||
"back to the game list? Continuing emulation may result in crashes, corrupted save "
|
||||
"data, or other bugs.");
|
||||
switch (result) {
|
||||
case Core::SystemResultStatus::ErrorSystemFiles: {
|
||||
QString message;
|
||||
if (details.empty()) {
|
||||
message =
|
||||
tr("yuzu was unable to locate a Switch system archive. %1").arg(common_message);
|
||||
} else {
|
||||
message = tr("yuzu was unable to locate a Switch system archive: %1. %2")
|
||||
.arg(QString::fromStdString(details), common_message);
|
||||
}
|
||||
|
||||
answer = QMessageBox::question(this, tr("System Archive Not Found"), message,
|
||||
QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
|
||||
status_message = tr("System Archive Missing");
|
||||
break;
|
||||
}
|
||||
|
||||
case Core::SystemResultStatus::ErrorSharedFont: {
|
||||
const QString message =
|
||||
tr("yuzu was unable to locate the Switch shared fonts. %1").arg(common_message);
|
||||
answer = QMessageBox::question(this, tr("Shared Fonts Not Found"), message,
|
||||
QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
|
||||
status_message = tr("Shared Font Missing");
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
answer = QMessageBox::question(
|
||||
this, tr("Fatal Error"),
|
||||
tr("yuzu has encountered a fatal error, please see the log for more details. "
|
||||
"For more information on accessing the log, please see the following page: "
|
||||
"<a href='https://community.citra-emu.org/t/how-to-upload-the-log-file/296'>How "
|
||||
"to "
|
||||
"Upload the Log File</a>.<br/><br/>Would you like to quit back to the game "
|
||||
"list? "
|
||||
"Continuing emulation may result in crashes, corrupted save data, or other "
|
||||
"bugs."),
|
||||
QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
|
||||
status_message = tr("Fatal Error encountered");
|
||||
break;
|
||||
}
|
||||
|
||||
if (answer == QMessageBox::Yes) {
|
||||
if (emu_thread) {
|
||||
ShutdownGame();
|
||||
|
||||
Settings::RestoreGlobalState(system->IsPoweredOn());
|
||||
system->HIDCore().ReloadInputDevices();
|
||||
UpdateStatusButtons();
|
||||
}
|
||||
} else {
|
||||
// Only show the message if the game is still running.
|
||||
if (emu_thread) {
|
||||
emu_thread->SetRunning(true);
|
||||
message_label->setText(status_message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GMainWindow::OnReinitializeKeys(ReinitializeKeyBehavior behavior) {
|
||||
if (behavior == ReinitializeKeyBehavior::Warning) {
|
||||
const auto res = QMessageBox::information(
|
||||
@@ -4098,6 +4118,10 @@ void GMainWindow::closeEvent(QCloseEvent* event) {
|
||||
// Shutdown session if the emu thread is active...
|
||||
if (emu_thread != nullptr) {
|
||||
ShutdownGame();
|
||||
|
||||
Settings::RestoreGlobalState(system->IsPoweredOn());
|
||||
system->HIDCore().ReloadInputDevices();
|
||||
UpdateStatusButtons();
|
||||
}
|
||||
|
||||
render_window->close();
|
||||
@@ -4190,10 +4214,6 @@ bool GMainWindow::ConfirmForceLockedExit() {
|
||||
}
|
||||
|
||||
void GMainWindow::RequestGameExit() {
|
||||
if (!system->IsPoweredOn()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto& sm{system->ServiceManager()};
|
||||
auto applet_oe = sm.GetService<Service::AM::AppletOE>("appletOE");
|
||||
auto applet_ae = sm.GetService<Service::AM::AppletAE>("appletAE");
|
||||
|
||||
@@ -29,7 +29,6 @@ class GImageInfo;
|
||||
class GRenderWindow;
|
||||
class LoadingScreen;
|
||||
class MicroProfileDialog;
|
||||
class OverlayDialog;
|
||||
class ProfilerWidget;
|
||||
class ControllerDialog;
|
||||
class QLabel;
|
||||
@@ -333,13 +332,10 @@ private slots:
|
||||
void ResetWindowSize900();
|
||||
void ResetWindowSize1080();
|
||||
void OnCaptureScreenshot();
|
||||
void OnCoreError(Core::SystemResultStatus, std::string);
|
||||
void OnReinitializeKeys(ReinitializeKeyBehavior behavior);
|
||||
void OnLanguageChanged(const QString& locale);
|
||||
void OnMouseActivity();
|
||||
bool OnShutdownBegin();
|
||||
void OnShutdownBeginDialog();
|
||||
void OnEmulationStopped();
|
||||
void OnEmulationStopTimeExpired();
|
||||
|
||||
private:
|
||||
QString GetGameListErrorRemoving(InstalledEntryType type) const;
|
||||
@@ -389,8 +385,6 @@ private:
|
||||
GRenderWindow* render_window;
|
||||
GameList* game_list;
|
||||
LoadingScreen* loading_screen;
|
||||
QTimer shutdown_timer;
|
||||
OverlayDialog* shutdown_dialog{};
|
||||
|
||||
GameListPlaceholder* game_list_placeholder;
|
||||
|
||||
|
||||
@@ -186,7 +186,7 @@ pid_t SpawnChild(const char* arg0) {
|
||||
return pid;
|
||||
} else if (pid == 0) {
|
||||
// child
|
||||
execlp(arg0, arg0, nullptr);
|
||||
execl(arg0, arg0, nullptr);
|
||||
const int err = errno;
|
||||
fmt::print(stderr, "execl failed with error {}\n", err);
|
||||
_exit(0);
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
#include <QKeyEvent>
|
||||
#include <QScreen>
|
||||
#include <QWindow>
|
||||
|
||||
#include "core/core.h"
|
||||
#include "core/hid/hid_types.h"
|
||||
@@ -43,7 +42,7 @@ OverlayDialog::OverlayDialog(QWidget* parent, Core::System& system, const QStrin
|
||||
MoveAndResizeWindow();
|
||||
|
||||
// TODO (Morph): Remove this when InputInterpreter no longer relies on the HID backend
|
||||
if (system.IsPoweredOn() && !ui->buttonsDialog->isHidden()) {
|
||||
if (system.IsPoweredOn()) {
|
||||
input_interpreter = std::make_unique<InputInterpreter>(system);
|
||||
|
||||
StartInputThread();
|
||||
@@ -84,11 +83,6 @@ void OverlayDialog::InitializeRegularTextDialog(const QString& title_text, const
|
||||
ui->button_ok_label->setEnabled(false);
|
||||
}
|
||||
|
||||
if (ui->button_cancel->isHidden() && ui->button_ok_label->isHidden()) {
|
||||
ui->buttonsDialog->hide();
|
||||
return;
|
||||
}
|
||||
|
||||
connect(
|
||||
ui->button_cancel, &QPushButton::clicked, this,
|
||||
[this](bool) {
|
||||
@@ -136,11 +130,6 @@ void OverlayDialog::InitializeRichTextDialog(const QString& title_text, const QS
|
||||
ui->button_ok_rich->setEnabled(false);
|
||||
}
|
||||
|
||||
if (ui->button_cancel_rich->isHidden() && ui->button_ok_rich->isHidden()) {
|
||||
ui->buttonsRichDialog->hide();
|
||||
return;
|
||||
}
|
||||
|
||||
connect(
|
||||
ui->button_cancel_rich, &QPushButton::clicked, this,
|
||||
[this](bool) {
|
||||
@@ -163,7 +152,7 @@ void OverlayDialog::MoveAndResizeWindow() {
|
||||
const auto height = static_cast<float>(parentWidget()->height());
|
||||
|
||||
// High DPI
|
||||
const float dpi_scale = parentWidget()->windowHandle()->screen()->logicalDotsPerInch() / 96.0f;
|
||||
const float dpi_scale = qApp->screenAt(pos)->logicalDotsPerInch() / 96.0f;
|
||||
|
||||
const auto title_text_font_size = BASE_TITLE_FONT_SIZE * (height / BASE_HEIGHT) / dpi_scale;
|
||||
const auto body_text_font_size =
|
||||
@@ -260,9 +249,3 @@ void OverlayDialog::InputThread() {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||
}
|
||||
}
|
||||
|
||||
void OverlayDialog::keyPressEvent(QKeyEvent* e) {
|
||||
if (!ui->buttonsDialog->isHidden() || e->key() != Qt::Key_Escape) {
|
||||
QDialog::keyPressEvent(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,7 +94,6 @@ private:
|
||||
|
||||
/// The thread where input is being polled and processed.
|
||||
void InputThread();
|
||||
void keyPressEvent(QKeyEvent* e) override;
|
||||
|
||||
std::unique_ptr<Ui::OverlayDialog> ui;
|
||||
|
||||
|
||||
@@ -49,15 +49,6 @@ if(UNIX AND NOT APPLE)
|
||||
install(TARGETS yuzu-cmd)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
# compile as a win32 gui application instead of a console application
|
||||
if(MSVC)
|
||||
set_target_properties(yuzu-cmd PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup")
|
||||
elseif(MINGW)
|
||||
set_target_properties(yuzu-cmd PROPERTIES LINK_FLAGS_RELEASE "-Wl,--subsystem,windows")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (MSVC)
|
||||
include(CopyYuzuSDLDeps)
|
||||
copy_yuzu_SDL_deps(yuzu-cmd)
|
||||
|
||||
@@ -174,13 +174,6 @@ static void OnStatusMessageReceived(const Network::StatusMessageEntry& msg) {
|
||||
|
||||
/// Application entry point
|
||||
int main(int argc, char** argv) {
|
||||
#ifdef _WIN32
|
||||
if (AttachConsole(ATTACH_PARENT_PROCESS)) {
|
||||
freopen("CONOUT$", "wb", stdout);
|
||||
freopen("CONOUT$", "wb", stderr);
|
||||
}
|
||||
#endif
|
||||
|
||||
Common::Log::Initialize();
|
||||
Common::Log::SetColorConsoleBackendEnabled(true);
|
||||
Common::Log::Start();
|
||||
|
||||
Reference in New Issue
Block a user