early-access version 2359
This commit is contained in:
parent
7232173690
commit
a0076b154a
16 changed files with 164 additions and 32 deletions
|
@ -1,7 +1,7 @@
|
||||||
yuzu emulator early access
|
yuzu emulator early access
|
||||||
=============
|
=============
|
||||||
|
|
||||||
This is the source code for early-access 2358.
|
This is the source code for early-access 2359.
|
||||||
|
|
||||||
## Legal Notice
|
## Legal Notice
|
||||||
|
|
||||||
|
|
|
@ -187,6 +187,8 @@ add_library(core STATIC
|
||||||
hle/kernel/k_event.h
|
hle/kernel/k_event.h
|
||||||
hle/kernel/k_handle_table.cpp
|
hle/kernel/k_handle_table.cpp
|
||||||
hle/kernel/k_handle_table.h
|
hle/kernel/k_handle_table.h
|
||||||
|
hle/kernel/k_interrupt_manager.cpp
|
||||||
|
hle/kernel/k_interrupt_manager.h
|
||||||
hle/kernel/k_light_condition_variable.cpp
|
hle/kernel/k_light_condition_variable.cpp
|
||||||
hle/kernel/k_light_condition_variable.h
|
hle/kernel/k_light_condition_variable.h
|
||||||
hle/kernel/k_light_lock.cpp
|
hle/kernel/k_light_lock.cpp
|
||||||
|
|
|
@ -45,26 +45,26 @@ void DefaultControllerApplet::ReconfigureControllers(std::function<void()> callb
|
||||||
// Pro Controller -> Dual Joycons -> Left Joycon/Right Joycon -> Handheld
|
// Pro Controller -> Dual Joycons -> Left Joycon/Right Joycon -> Handheld
|
||||||
if (parameters.allow_pro_controller) {
|
if (parameters.allow_pro_controller) {
|
||||||
controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::ProController);
|
controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::ProController);
|
||||||
controller->Connect();
|
controller->Connect(true);
|
||||||
} else if (parameters.allow_dual_joycons) {
|
} else if (parameters.allow_dual_joycons) {
|
||||||
controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::JoyconDual);
|
controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::JoyconDual);
|
||||||
controller->Connect();
|
controller->Connect(true);
|
||||||
} else if (parameters.allow_left_joycon && parameters.allow_right_joycon) {
|
} else if (parameters.allow_left_joycon && parameters.allow_right_joycon) {
|
||||||
// Assign left joycons to even player indices and right joycons to odd player indices.
|
// Assign left joycons to even player indices and right joycons to odd player indices.
|
||||||
// We do this since Captain Toad Treasure Tracker expects a left joycon for Player 1 and
|
// We do this since Captain Toad Treasure Tracker expects a left joycon for Player 1 and
|
||||||
// a right Joycon for Player 2 in 2 Player Assist mode.
|
// a right Joycon for Player 2 in 2 Player Assist mode.
|
||||||
if (index % 2 == 0) {
|
if (index % 2 == 0) {
|
||||||
controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::JoyconLeft);
|
controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::JoyconLeft);
|
||||||
controller->Connect();
|
controller->Connect(true);
|
||||||
} else {
|
} else {
|
||||||
controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::JoyconRight);
|
controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::JoyconRight);
|
||||||
controller->Connect();
|
controller->Connect(true);
|
||||||
}
|
}
|
||||||
} else if (index == 0 && parameters.enable_single_mode && parameters.allow_handheld &&
|
} else if (index == 0 && parameters.enable_single_mode && parameters.allow_handheld &&
|
||||||
!Settings::values.use_docked_mode.GetValue()) {
|
!Settings::values.use_docked_mode.GetValue()) {
|
||||||
// We should *never* reach here under any normal circumstances.
|
// We should *never* reach here under any normal circumstances.
|
||||||
controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::Handheld);
|
controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::Handheld);
|
||||||
controller->Connect();
|
controller->Connect(true);
|
||||||
} else {
|
} else {
|
||||||
UNREACHABLE_MSG("Unable to add a new controller based on the given parameters!");
|
UNREACHABLE_MSG("Unable to add a new controller based on the given parameters!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -908,8 +908,9 @@ void EmulatedController::SetSupportedNpadStyleTag(NpadStyleTag supported_styles)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EmulatedController::IsControllerSupported() const {
|
bool EmulatedController::IsControllerSupported(bool use_temporary_value) const {
|
||||||
switch (npad_type) {
|
const auto type = is_configuring && use_temporary_value ? tmp_npad_type : npad_type;
|
||||||
|
switch (type) {
|
||||||
case NpadStyleIndex::ProController:
|
case NpadStyleIndex::ProController:
|
||||||
return supported_style_tag.fullkey;
|
return supported_style_tag.fullkey;
|
||||||
case NpadStyleIndex::Handheld:
|
case NpadStyleIndex::Handheld:
|
||||||
|
@ -937,9 +938,10 @@ bool EmulatedController::IsControllerSupported() const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmulatedController::Connect() {
|
void EmulatedController::Connect(bool use_temporary_value) {
|
||||||
if (!IsControllerSupported()) {
|
if (!IsControllerSupported(use_temporary_value)) {
|
||||||
LOG_ERROR(Service_HID, "Controller type {} is not supported", npad_type);
|
const auto type = is_configuring && use_temporary_value ? tmp_npad_type : npad_type;
|
||||||
|
LOG_ERROR(Service_HID, "Controller type {} is not supported", type);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
|
|
@ -169,8 +169,11 @@ public:
|
||||||
*/
|
*/
|
||||||
void SetSupportedNpadStyleTag(NpadStyleTag supported_styles);
|
void SetSupportedNpadStyleTag(NpadStyleTag supported_styles);
|
||||||
|
|
||||||
/// Sets the connected status to true
|
/**
|
||||||
void Connect();
|
* Sets the connected status to true
|
||||||
|
* @param use_temporary_value If true tmp_npad_type will be used
|
||||||
|
*/
|
||||||
|
void Connect(bool use_temporary_value = false);
|
||||||
|
|
||||||
/// Sets the connected status to false
|
/// Sets the connected status to false
|
||||||
void Disconnect();
|
void Disconnect();
|
||||||
|
@ -336,9 +339,10 @@ private:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks the current controller type against the supported_style_tag
|
* Checks the current controller type against the supported_style_tag
|
||||||
|
* @param use_temporary_value If true tmp_npad_type will be used
|
||||||
* @return true if the controller is supported
|
* @return true if the controller is supported
|
||||||
*/
|
*/
|
||||||
bool IsControllerSupported() const;
|
bool IsControllerSupported(bool use_temporary_value = false) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the button status of the controller
|
* Updates the button status of the controller
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "core/hle/kernel/global_scheduler_context.h"
|
#include "core/hle/kernel/global_scheduler_context.h"
|
||||||
#include "core/hle/kernel/k_scheduler.h"
|
#include "core/hle/kernel/k_scheduler.h"
|
||||||
#include "core/hle/kernel/kernel.h"
|
#include "core/hle/kernel/kernel.h"
|
||||||
|
#include "core/hle/kernel/physical_core.h"
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
|
|
||||||
|
@ -42,6 +43,11 @@ void GlobalSchedulerContext::PreemptThreads() {
|
||||||
for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) {
|
for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) {
|
||||||
const u32 priority = preemption_priorities[core_id];
|
const u32 priority = preemption_priorities[core_id];
|
||||||
kernel.Scheduler(core_id).RotateScheduledQueue(core_id, priority);
|
kernel.Scheduler(core_id).RotateScheduledQueue(core_id, priority);
|
||||||
|
|
||||||
|
// Signal an interrupt occurred. For core 3, this is a certainty, as preemption will result
|
||||||
|
// in the rotator thread being scheduled. For cores 0-2, this is to simulate or system
|
||||||
|
// interrupts that may have occurred.
|
||||||
|
kernel.PhysicalCore(core_id).Interrupt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
34
src/core/hle/kernel/k_interrupt_manager.cpp
Executable file
34
src/core/hle/kernel/k_interrupt_manager.cpp
Executable file
|
@ -0,0 +1,34 @@
|
||||||
|
// Copyright 2021 yuzu Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include "core/hle/kernel/k_interrupt_manager.h"
|
||||||
|
#include "core/hle/kernel/k_process.h"
|
||||||
|
#include "core/hle/kernel/k_scheduler.h"
|
||||||
|
#include "core/hle/kernel/k_thread.h"
|
||||||
|
#include "core/hle/kernel/kernel.h"
|
||||||
|
|
||||||
|
namespace Kernel::KInterruptManager {
|
||||||
|
|
||||||
|
void HandleInterrupt(KernelCore& kernel, s32 core_id) {
|
||||||
|
auto* process = kernel.CurrentProcess();
|
||||||
|
if (!process) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& scheduler = kernel.Scheduler(core_id);
|
||||||
|
auto& current_thread = *scheduler.GetCurrentThread();
|
||||||
|
|
||||||
|
// If the user disable count is set, we may need to pin the current thread.
|
||||||
|
if (current_thread.GetUserDisableCount() && !process->GetPinnedThread(core_id)) {
|
||||||
|
KScopedSchedulerLock sl{kernel};
|
||||||
|
|
||||||
|
// Pin the current thread.
|
||||||
|
process->PinCurrentThread(core_id);
|
||||||
|
|
||||||
|
// Set the interrupt flag for the thread.
|
||||||
|
scheduler.GetCurrentThread()->SetInterruptFlag();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Kernel::KInterruptManager
|
17
src/core/hle/kernel/k_interrupt_manager.h
Executable file
17
src/core/hle/kernel/k_interrupt_manager.h
Executable file
|
@ -0,0 +1,17 @@
|
||||||
|
// Copyright 2021 yuzu Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common/common_types.h"
|
||||||
|
|
||||||
|
namespace Kernel {
|
||||||
|
|
||||||
|
class KernelCore;
|
||||||
|
|
||||||
|
namespace KInterruptManager {
|
||||||
|
void HandleInterrupt(KernelCore& kernel, s32 core_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Kernel
|
|
@ -220,30 +220,28 @@ bool KProcess::ReleaseUserException(KThread* thread) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void KProcess::PinCurrentThread() {
|
void KProcess::PinCurrentThread(s32 core_id) {
|
||||||
ASSERT(kernel.GlobalSchedulerContext().IsLocked());
|
ASSERT(kernel.GlobalSchedulerContext().IsLocked());
|
||||||
|
|
||||||
// Get the current thread.
|
// Get the current thread.
|
||||||
const s32 core_id = GetCurrentCoreId(kernel);
|
KThread* cur_thread = kernel.Scheduler(static_cast<std::size_t>(core_id)).GetCurrentThread();
|
||||||
KThread* cur_thread = GetCurrentThreadPointer(kernel);
|
|
||||||
|
|
||||||
// If the thread isn't terminated, pin it.
|
// If the thread isn't terminated, pin it.
|
||||||
if (!cur_thread->IsTerminationRequested()) {
|
if (!cur_thread->IsTerminationRequested()) {
|
||||||
// Pin it.
|
// Pin it.
|
||||||
PinThread(core_id, cur_thread);
|
PinThread(core_id, cur_thread);
|
||||||
cur_thread->Pin();
|
cur_thread->Pin(core_id);
|
||||||
|
|
||||||
// An update is needed.
|
// An update is needed.
|
||||||
KScheduler::SetSchedulerUpdateNeeded(kernel);
|
KScheduler::SetSchedulerUpdateNeeded(kernel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void KProcess::UnpinCurrentThread() {
|
void KProcess::UnpinCurrentThread(s32 core_id) {
|
||||||
ASSERT(kernel.GlobalSchedulerContext().IsLocked());
|
ASSERT(kernel.GlobalSchedulerContext().IsLocked());
|
||||||
|
|
||||||
// Get the current thread.
|
// Get the current thread.
|
||||||
const s32 core_id = GetCurrentCoreId(kernel);
|
KThread* cur_thread = kernel.Scheduler(static_cast<std::size_t>(core_id)).GetCurrentThread();
|
||||||
KThread* cur_thread = GetCurrentThreadPointer(kernel);
|
|
||||||
|
|
||||||
// Unpin it.
|
// Unpin it.
|
||||||
cur_thread->Unpin();
|
cur_thread->Unpin();
|
||||||
|
|
|
@ -345,8 +345,8 @@ public:
|
||||||
|
|
||||||
bool IsSignaled() const override;
|
bool IsSignaled() const override;
|
||||||
|
|
||||||
void PinCurrentThread();
|
void PinCurrentThread(s32 core_id);
|
||||||
void UnpinCurrentThread();
|
void UnpinCurrentThread(s32 core_id);
|
||||||
void UnpinThread(KThread* thread);
|
void UnpinThread(KThread* thread);
|
||||||
|
|
||||||
KLightLock& GetStateLock() {
|
KLightLock& GetStateLock() {
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/core_timing.h"
|
#include "core/core_timing.h"
|
||||||
#include "core/cpu_manager.h"
|
#include "core/cpu_manager.h"
|
||||||
|
#include "core/hle/kernel/k_interrupt_manager.h"
|
||||||
#include "core/hle/kernel/k_process.h"
|
#include "core/hle/kernel/k_process.h"
|
||||||
#include "core/hle/kernel/k_scheduler.h"
|
#include "core/hle/kernel/k_scheduler.h"
|
||||||
#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"
|
#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"
|
||||||
|
@ -53,6 +54,13 @@ void KScheduler::RescheduleCores(KernelCore& kernel, u64 cores_pending_reschedul
|
||||||
}
|
}
|
||||||
cores_pending_reschedule &= ~(1ULL << core);
|
cores_pending_reschedule &= ~(1ULL << core);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (std::size_t core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; ++core_id) {
|
||||||
|
if (kernel.PhysicalCore(core_id).IsInterrupted()) {
|
||||||
|
KInterruptManager::HandleInterrupt(kernel, static_cast<s32>(core_id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (must_context_switch) {
|
if (must_context_switch) {
|
||||||
auto core_scheduler = kernel.CurrentScheduler();
|
auto core_scheduler = kernel.CurrentScheduler();
|
||||||
kernel.ExitSVCProfile();
|
kernel.ExitSVCProfile();
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <atomic>
|
||||||
#include <cinttypes>
|
#include <cinttypes>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -33,6 +34,7 @@
|
||||||
#include "core/hle/kernel/svc_results.h"
|
#include "core/hle/kernel/svc_results.h"
|
||||||
#include "core/hle/kernel/time_manager.h"
|
#include "core/hle/kernel/time_manager.h"
|
||||||
#include "core/hle/result.h"
|
#include "core/hle/result.h"
|
||||||
|
#include "core/memory.h"
|
||||||
|
|
||||||
#ifdef ARCHITECTURE_x86_64
|
#ifdef ARCHITECTURE_x86_64
|
||||||
#include "core/arm/dynarmic/arm_dynarmic_32.h"
|
#include "core/arm/dynarmic/arm_dynarmic_32.h"
|
||||||
|
@ -63,6 +65,13 @@ namespace Kernel {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
struct ThreadLocalRegion {
|
||||||
|
static constexpr std::size_t MessageBufferSize = 0x100;
|
||||||
|
std::array<u32, MessageBufferSize / sizeof(u32)> message_buffer;
|
||||||
|
std::atomic_uint16_t disable_count;
|
||||||
|
std::atomic_uint16_t interrupt_flag;
|
||||||
|
};
|
||||||
|
|
||||||
class ThreadQueueImplForKThreadSleep final : public KThreadQueueWithoutEndWait {
|
class ThreadQueueImplForKThreadSleep final : public KThreadQueueWithoutEndWait {
|
||||||
public:
|
public:
|
||||||
explicit ThreadQueueImplForKThreadSleep(KernelCore& kernel_)
|
explicit ThreadQueueImplForKThreadSleep(KernelCore& kernel_)
|
||||||
|
@ -346,7 +355,7 @@ void KThread::StartTermination() {
|
||||||
if (parent != nullptr) {
|
if (parent != nullptr) {
|
||||||
parent->ReleaseUserException(this);
|
parent->ReleaseUserException(this);
|
||||||
if (parent->GetPinnedThread(GetCurrentCoreId(kernel)) == this) {
|
if (parent->GetPinnedThread(GetCurrentCoreId(kernel)) == this) {
|
||||||
parent->UnpinCurrentThread();
|
parent->UnpinCurrentThread(core_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -372,7 +381,7 @@ void KThread::StartTermination() {
|
||||||
this->Close();
|
this->Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void KThread::Pin() {
|
void KThread::Pin(s32 current_core) {
|
||||||
ASSERT(kernel.GlobalSchedulerContext().IsLocked());
|
ASSERT(kernel.GlobalSchedulerContext().IsLocked());
|
||||||
|
|
||||||
// Set ourselves as pinned.
|
// Set ourselves as pinned.
|
||||||
|
@ -389,7 +398,6 @@ void KThread::Pin() {
|
||||||
|
|
||||||
// Bind ourselves to this core.
|
// Bind ourselves to this core.
|
||||||
const s32 active_core = GetActiveCore();
|
const s32 active_core = GetActiveCore();
|
||||||
const s32 current_core = GetCurrentCoreId(kernel);
|
|
||||||
|
|
||||||
SetActiveCore(current_core);
|
SetActiveCore(current_core);
|
||||||
physical_ideal_core_id = current_core;
|
physical_ideal_core_id = current_core;
|
||||||
|
@ -482,6 +490,36 @@ void KThread::Unpin() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u16 KThread::GetUserDisableCount() const {
|
||||||
|
if (!IsUserThread()) {
|
||||||
|
// We only emulate TLS for user threads
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& memory = kernel.System().Memory();
|
||||||
|
return memory.Read16(tls_address + offsetof(ThreadLocalRegion, disable_count));
|
||||||
|
}
|
||||||
|
|
||||||
|
void KThread::SetInterruptFlag() {
|
||||||
|
if (!IsUserThread()) {
|
||||||
|
// We only emulate TLS for user threads
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& memory = kernel.System().Memory();
|
||||||
|
memory.Write16(tls_address + offsetof(ThreadLocalRegion, interrupt_flag), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KThread::ClearInterruptFlag() {
|
||||||
|
if (!IsUserThread()) {
|
||||||
|
// We only emulate TLS for user threads
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& memory = kernel.System().Memory();
|
||||||
|
memory.Write16(tls_address + offsetof(ThreadLocalRegion, interrupt_flag), 0);
|
||||||
|
}
|
||||||
|
|
||||||
ResultCode KThread::GetCoreMask(s32* out_ideal_core, u64* out_affinity_mask) {
|
ResultCode KThread::GetCoreMask(s32* out_ideal_core, u64* out_affinity_mask) {
|
||||||
KScopedSchedulerLock sl{kernel};
|
KScopedSchedulerLock sl{kernel};
|
||||||
|
|
||||||
|
|
|
@ -307,6 +307,10 @@ public:
|
||||||
return parent != nullptr;
|
return parent != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u16 GetUserDisableCount() const;
|
||||||
|
void SetInterruptFlag();
|
||||||
|
void ClearInterruptFlag();
|
||||||
|
|
||||||
[[nodiscard]] KThread* GetLockOwner() const {
|
[[nodiscard]] KThread* GetLockOwner() const {
|
||||||
return lock_owner;
|
return lock_owner;
|
||||||
}
|
}
|
||||||
|
@ -490,7 +494,7 @@ public:
|
||||||
this->GetStackParameters().disable_count--;
|
this->GetStackParameters().disable_count--;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Pin();
|
void Pin(s32 current_core);
|
||||||
|
|
||||||
void Unpin();
|
void Unpin();
|
||||||
|
|
||||||
|
|
|
@ -2027,6 +2027,25 @@ static ResultCode SignalToAddress(Core::System& system, VAddr address, Svc::Sign
|
||||||
count);
|
count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void SynchronizePreemptionState(Core::System& system) {
|
||||||
|
auto& kernel = system.Kernel();
|
||||||
|
|
||||||
|
// Lock the scheduler.
|
||||||
|
KScopedSchedulerLock sl{kernel};
|
||||||
|
|
||||||
|
// If the current thread is pinned, unpin it.
|
||||||
|
KProcess* cur_process = system.Kernel().CurrentProcess();
|
||||||
|
const auto core_id = GetCurrentCoreId(kernel);
|
||||||
|
|
||||||
|
if (cur_process->GetPinnedThread(core_id) == GetCurrentThreadPointer(kernel)) {
|
||||||
|
// Clear the current thread's interrupt flag.
|
||||||
|
GetCurrentThread(kernel).ClearInterruptFlag();
|
||||||
|
|
||||||
|
// Unpin the current thread.
|
||||||
|
cur_process->UnpinCurrentThread(core_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static ResultCode SignalToAddress32(Core::System& system, u32 address, Svc::SignalType signal_type,
|
static ResultCode SignalToAddress32(Core::System& system, u32 address, Svc::SignalType signal_type,
|
||||||
s32 value, s32 count) {
|
s32 value, s32 count) {
|
||||||
return SignalToAddress(system, address, signal_type, value, count);
|
return SignalToAddress(system, address, signal_type, value, count);
|
||||||
|
@ -2797,7 +2816,7 @@ static const FunctionDef SVC_Table_64[] = {
|
||||||
{0x33, SvcWrap64<GetThreadContext>, "GetThreadContext"},
|
{0x33, SvcWrap64<GetThreadContext>, "GetThreadContext"},
|
||||||
{0x34, SvcWrap64<WaitForAddress>, "WaitForAddress"},
|
{0x34, SvcWrap64<WaitForAddress>, "WaitForAddress"},
|
||||||
{0x35, SvcWrap64<SignalToAddress>, "SignalToAddress"},
|
{0x35, SvcWrap64<SignalToAddress>, "SignalToAddress"},
|
||||||
{0x36, nullptr, "SynchronizePreemptionState"},
|
{0x36, SvcWrap64<SynchronizePreemptionState>, "SynchronizePreemptionState"},
|
||||||
{0x37, nullptr, "Unknown"},
|
{0x37, nullptr, "Unknown"},
|
||||||
{0x38, nullptr, "Unknown"},
|
{0x38, nullptr, "Unknown"},
|
||||||
{0x39, nullptr, "Unknown"},
|
{0x39, nullptr, "Unknown"},
|
||||||
|
|
|
@ -33,7 +33,7 @@ void UpdateController(Core::HID::EmulatedController* controller,
|
||||||
}
|
}
|
||||||
controller->SetNpadStyleIndex(controller_type);
|
controller->SetNpadStyleIndex(controller_type);
|
||||||
if (connected) {
|
if (connected) {
|
||||||
controller->Connect();
|
controller->Connect(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -599,11 +599,11 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
||||||
if (is_connected) {
|
if (is_connected) {
|
||||||
if (type == Core::HID::NpadStyleIndex::Handheld) {
|
if (type == Core::HID::NpadStyleIndex::Handheld) {
|
||||||
emulated_controller_p1->Disconnect();
|
emulated_controller_p1->Disconnect();
|
||||||
emulated_controller_handheld->Connect();
|
emulated_controller_handheld->Connect(true);
|
||||||
emulated_controller = emulated_controller_handheld;
|
emulated_controller = emulated_controller_handheld;
|
||||||
} else {
|
} else {
|
||||||
emulated_controller_handheld->Disconnect();
|
emulated_controller_handheld->Disconnect();
|
||||||
emulated_controller_p1->Connect();
|
emulated_controller_p1->Connect(true);
|
||||||
emulated_controller = emulated_controller_p1;
|
emulated_controller = emulated_controller_p1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -718,7 +718,7 @@ void ConfigureInputPlayer::LoadConfiguration() {
|
||||||
void ConfigureInputPlayer::ConnectPlayer(bool connected) {
|
void ConfigureInputPlayer::ConnectPlayer(bool connected) {
|
||||||
ui->groupConnectedController->setChecked(connected);
|
ui->groupConnectedController->setChecked(connected);
|
||||||
if (connected) {
|
if (connected) {
|
||||||
emulated_controller->Connect();
|
emulated_controller->Connect(true);
|
||||||
} else {
|
} else {
|
||||||
emulated_controller->Disconnect();
|
emulated_controller->Disconnect();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue