Compare commits

...

67 Commits

Author SHA1 Message Date
Chloe Marcec c5f109bc50 video_core: Delete morton
moron.h & morton.cpp are not used anywhere and are just empty files
2021-02-08 10:20:21 +11:00
bunnei 4a01812ebe Merge pull request #5885 from MerryMage/ring_buffer-granularity
ring_buffer: Remove granularity template argument
2021-02-06 13:18:41 -08:00
bunnei 9078f4a9c7 Merge pull request #5871 from lioncash/address-arb
k_address_arbiter: Minor cleanup
2021-02-06 13:05:19 -08:00
MerryMage 8d00265998 ring_buffer: Remove granularity template argument
Non-obvious bug in RingBuffer::Push(std::vector<T>&) when granularity != 1

Just remove it altogether because we do not have a use for granularity != 1
2021-02-06 19:16:00 +00:00
bunnei 61bf850f3d Merge pull request #5326 from german77/hidUpdate1
HID: Update the HID service to match more closely to switchbrew part 1
2021-02-06 02:40:11 -08:00
Lioncash 40ab2b9348 k_address_arbiter: Unfold R_UNLESS macros
Allows for more descriptive error messages and also doesn't hide
control-path exit returns from the reader.
2021-02-06 04:08:27 -05:00
Lioncash b8fc74d74d k_address_arbiter: Remove unnecessary usages of std::addressof
This is a useful function in a generic context or with types that
overload unary operator&. However, primitives and pointers will never do
this, so we can opt for a more straightforward syntax.
2021-02-06 04:06:33 -05:00
Lioncash 7b9c58880f k_address_arbiter: Remove dead code
This code is never used, so we can remove it. It's in version control,
so it can always be brought back when needed.
2021-02-06 04:06:33 -05:00
bunnei 1498a7c9a8 Merge pull request #5862 from bunnei/kevent
Kernel Rework: Refactor KEvent/KReadableEvent/KWritableEvent
2021-02-05 23:00:43 -08:00
bunnei 3a804752cb Merge pull request #5875 from lioncash/identifier
k_priority_queue: Minor cleanup
2021-02-05 17:02:13 -08:00
bunnei ea4f62615e hle: kernel: Drop R_UNLESS_NOLOG in favor of expanded if-statement. 2021-02-05 14:03:36 -08:00
bunnei 546af64340 hle: kernel: KAddressArbiter: Remove noisy error log. 2021-02-05 14:03:36 -08:00
bunnei eba3c59a61 hle: kernel: svc: Cleanup KEvent/KReadableEvent/KWritableEvent SVCs. 2021-02-05 14:03:36 -08:00
bunnei 18175c71ed common: scope_exit: Add a cancellable ScopeExit macro. 2021-02-05 14:03:36 -08:00
bunnei ff3c7c068b hle: kernel: Reimplement KReadableEvent and KWritableEvent. 2021-02-05 14:03:32 -08:00
bunnei 6bf80dfee0 hle: kernel: Implement KEvent. 2021-02-05 14:00:36 -08:00
bunnei e9446d232f hle: kernel: KAddressArbiter: Use R_UNLESS_NOLOG where applicable. 2021-02-05 14:00:36 -08:00
bunnei 4577dcd5f9 common: common_funcs: Add R_UNLESS_NOLOG for scenarios that should not log. 2021-02-05 14:00:36 -08:00
bunnei 3f942c01f0 hle: kernel: Rename WritableEvent to KWritableEvent. 2021-02-05 14:00:36 -08:00
bunnei e86a7e3691 hle: kernel: Rename ReadableEvent to KReadableEvent. 2021-02-05 14:00:36 -08:00
bunnei b0727c90c5 Merge pull request #5867 from Morph1984/am-GetHealthWarningDisappearedSystemEvent
IApplicationFunctions: Implement GetHealthWarningDisappearedSystemEvent
2021-02-05 13:49:49 -08:00
bunnei 741dc13c5a Merge pull request #5865 from lat9nq/conditionally-quiet
video_core: host_shaders: Don't pass --quiet to glslangValidator if unavailable
2021-02-04 17:07:17 -08:00
bunnei 00cb631b2f Merge pull request #5876 from lioncash/truncation
k_affinity_mask: Avoid implicit truncation to bool
2021-02-04 14:44:11 -08:00
Lioncash 756365386a k_affinity_mask: Avoid implicit truncation to bool
This can cause compiler warnings. Instead, we can explicitly add a
boolean expression around it to naturally turn the result into a bool.
2021-02-04 15:35:46 -05:00
Lioncash b944edc85d k_priority_queue: Unfold several declval usages
Given these are only used as function existence checks, we can simplify
some usages of declval, given they aren't particularly useful here.

Reduces a few template instantiations, which at most reduces compile
times a tiny bit.
2021-02-04 15:18:58 -05:00
Lioncash 31e6e58101 k_priority_queue: Simplify affinity mask type alias
We can make use of the _t variants of the templates to cut down on a
little bit of verbosity.
2021-02-04 14:57:41 -05:00
Lioncash 53aec1fe2d k_priority_queue: Resolved reserved identifier
An identifier containing a starting underscore followed by a capital
letter is reserved by the standard. It's trivial to avoid this by moving
the underscore to the end of the identifier.

While the likelihood of clashing here being minimal, we can turn a
"should not break" scenario into a definitive "will not break" one, so
why not?.
2021-02-04 14:55:08 -05:00
bunnei eb3afd30b1 Merge pull request #5874 from Morph1984/create-keys-dir
key_manager: Create the keys directory if it does not exist
2021-02-04 11:47:14 -08:00
Morph 806e2d7900 key_manager: Create the keys directory if it does not exist 2021-02-04 06:05:50 -05:00
bunnei b331bb5210 Merge pull request #5870 from german77/hanheldfix2
config: Always update handheld config
2021-02-03 19:02:59 -08:00
german 8019b2b9b5 Add footer types and address comments 2021-02-03 20:17:08 -06:00
german 9a9e81f2e9 Fix npad struct to match switchbrew 2021-02-03 20:17:08 -06:00
german f30ef98761 Adds missing controller types and properties 2021-02-03 20:17:08 -06:00
bunnei cde532cc52 Merge pull request #5863 from ogniK5377/disable-reverb
audren: Disable reverb for the time being
2021-02-03 18:05:54 -08:00
german c1b81f776c Always update handheld config 2021-02-03 17:48:04 -06:00
bunnei b0c9752663 Merge pull request #5848 from ogniK5377/k-resourcelimit
kernel: Rewrite resource limit to be more accurate
2021-02-03 14:53:25 -08:00
Chloe Marcec 2c6e940493 Simplify limitableresource names 2021-02-03 12:55:16 +11:00
bunnei 48d040fded Merge pull request #5842 from german77/userfix
acc: Fix error when second user is selected
2021-02-02 15:43:51 -08:00
bunnei e5a76d728f Merge pull request #5841 from german77/username
Avoid overwriting username
2021-02-02 15:04:09 -08:00
LC 82d232db46 Merge pull request #5866 from Morph1984/log-all-paths
settings: Log the cache, config and mod load directories
2021-02-02 11:07:42 -05:00
Morph 13b08376b7 IApplicationFunctions: Implement GetHealthWarningDisappearedSystemEvent 2021-02-02 10:47:38 -05:00
Morph 9137f3ec68 settings: Log the cache, config, and mod load directories 2021-02-02 04:01:05 -05:00
lat9nq fc43eac82a video_core: host_shaders: Don't pass --quiet to glslangValidator if unavailable
Prevents CMake from calling `glslangValidator` with `--quiet` when it is
not available, i.e. on older downstream versions from Ubuntu.
2021-02-01 23:39:54 -05:00
bunnei d4ebc9a120 Merge pull request #5861 from german77/HandheldFix
hid: Only update motion for npad and prevent over scheduling events
2021-02-01 18:46:26 -08:00
Chloe Marcec 64c3582705 Compile error 2021-02-02 13:23:34 +11:00
Chloe Marcec 9e4b2d60bc Address issues 2021-02-02 13:23:00 +11:00
LC 5e49b81d4d Merge pull request #5864 from MerryMage/is-thumb
arm_dynarmic_32: Print out CPSR.T on exception
2021-02-01 13:36:55 -05:00
MerryMage 821fc4a7b6 arm_dynarmic_32: Print out CPSR.T on exception 2021-02-01 18:35:33 +00:00
bunnei f317b0d354 Merge pull request #5859 from Morph1984/nifm
nifm: Stub GetCurrentNetworkProfile and GetCurrentIpConfigInfo
2021-01-31 21:31:14 -08:00
Ameer J f614d7d887 Merge pull request #5856 from Morph1984/nifm-fix-getappletinfo-stub
nifm: Fix GetAppletInfo stub
2021-01-31 23:33:11 -05:00
Chloe Marcec 9fc7f60b94 audren: Disable reverb for the time being
As this is causing issues in a few games, it's best to have it disabled until it's completely implemented
2021-02-01 14:41:58 +11:00
bunnei 67d08f14af Merge pull request #5858 from Morph1984/IsGamePlayRecordingSupported-stub
am/IApplicationFunctions: Stub IsGamePlayRecordingSupported
2021-01-31 18:04:04 -08:00
german 2489547dc5 Only update motion for npad and prevent over scheduling events 2021-01-31 18:52:38 -06:00
bunnei 1498ece290 Merge pull request #5860 from Morph1984/prepo-transmission-stub
prepo: Stub RequestImmediateTransmission and GetTransmissionStatus
2021-01-31 12:26:00 -08:00
Morph f7dc77e03a Merge pull request #5846 from ameerj/analog-join
analog_from_button: Fix update_thread.join exception
2021-01-31 23:06:06 +08:00
Morph 7d9465d47a prepo: Stub GetTransmissionStatus 2021-01-31 07:07:11 -05:00
Morph 2394807b42 prepo: Stub RequestImmediateTransmission
- Used by Animal Crossing: New Horizons
2021-01-31 07:04:35 -05:00
Morph 9f6b35e61f am/IApplicationFunctions: Stub IsGamePlayRecordingSupported
Used by RetroArch
2021-01-31 03:11:03 -05:00
Morph 9914db8daa nifm: Fix GetAppletInfo stub 2021-01-31 02:19:36 -05:00
Chloe Marcec ee333e063d fix compile error 2021-01-30 21:51:22 +11:00
Chloe Marcec 56742c6222 cleanup commenting 2021-01-30 21:20:35 +11:00
Chloe Marcec 7791cfd960 Drop m_ from lock 2021-01-30 21:19:49 +11:00
Chloe Marcec 3bf62c7a8a Move to GetGlobalTimeNs, fix GetTotalPhysicalMemoryAvailable 2021-01-30 21:03:10 +11:00
Chloe Marcec 3be1a565f8 kernel: Rewrite resource limit to be more accurate
Matches closer to hardware
2021-01-30 20:40:49 +11:00
ameerj ef8b3623f5 analog_from_button: Fix update_thread.join exception
This commit aims to address an exception that occurs when trying to join the Analog object's update_thread.

By using an atomic bool for the status of the update thread, we ensure its value is consistent across the threads accessing it.
2021-01-29 18:41:22 -05:00
german 8ba0cac71c Fix user changing to 0 if valid 2021-01-28 21:02:25 -06:00
german 7b8fa78c65 Avoid overwritting username 2021-01-28 16:58:53 -06:00
97 changed files with 1664 additions and 1075 deletions
+4 -1
View File
@@ -383,11 +383,14 @@ void CommandGenerator::GenerateI3dl2ReverbEffectCommand(s32 mix_buffer_offset, E
const auto channel_count = params.channel_count;
for (s32 i = 0; i < channel_count; i++) {
// TODO(ogniK): Actually implement reverb
/*
if (params.input[i] != params.output[i]) {
const auto* input = GetMixBuffer(mix_buffer_offset + params.input[i]);
auto* output = GetMixBuffer(mix_buffer_offset + params.output[i]);
ApplyMix<1>(output, input, 32768, worker_params.sample_count);
}
}*/
auto* output = GetMixBuffer(mix_buffer_offset + params.output[i]);
std::memset(output, 0, worker_params.sample_count * sizeof(s32));
}
}
+10 -11
View File
@@ -19,15 +19,14 @@ namespace Common {
/// SPSC ring buffer
/// @tparam T Element type
/// @tparam capacity Number of slots in ring buffer
/// @tparam granularity Slot size in terms of number of elements
template <typename T, std::size_t capacity, std::size_t granularity = 1>
template <typename T, std::size_t capacity>
class RingBuffer {
/// A "slot" is made of `granularity` elements of `T`.
static constexpr std::size_t slot_size = granularity * sizeof(T);
/// A "slot" is made of a single `T`.
static constexpr std::size_t slot_size = sizeof(T);
// T must be safely memcpy-able and have a trivial default constructor.
static_assert(std::is_trivial_v<T>);
// Ensure capacity is sensible.
static_assert(capacity < std::numeric_limits<std::size_t>::max() / 2 / granularity);
static_assert(capacity < std::numeric_limits<std::size_t>::max() / 2);
static_assert((capacity & (capacity - 1)) == 0, "capacity must be a power of two");
// Ensure lock-free.
static_assert(std::atomic_size_t::is_always_lock_free);
@@ -47,7 +46,7 @@ public:
const std::size_t second_copy = push_count - first_copy;
const char* in = static_cast<const char*>(new_slots);
std::memcpy(m_data.data() + pos * granularity, in, first_copy * slot_size);
std::memcpy(m_data.data() + pos, in, first_copy * slot_size);
in += first_copy * slot_size;
std::memcpy(m_data.data(), in, second_copy * slot_size);
@@ -74,7 +73,7 @@ public:
const std::size_t second_copy = pop_count - first_copy;
char* out = static_cast<char*>(output);
std::memcpy(out, m_data.data() + pos * granularity, first_copy * slot_size);
std::memcpy(out, m_data.data() + pos, first_copy * slot_size);
out += first_copy * slot_size;
std::memcpy(out, m_data.data(), second_copy * slot_size);
@@ -84,9 +83,9 @@ public:
}
std::vector<T> Pop(std::size_t max_slots = ~std::size_t(0)) {
std::vector<T> out(std::min(max_slots, capacity) * granularity);
const std::size_t count = Pop(out.data(), out.size() / granularity);
out.resize(count * granularity);
std::vector<T> out(std::min(max_slots, capacity));
const std::size_t count = Pop(out.data(), out.size());
out.resize(count);
return out;
}
@@ -113,7 +112,7 @@ private:
alignas(128) std::atomic_size_t m_write_index{0};
#endif
std::array<T, granularity * capacity> m_data;
std::array<T, capacity> m_data;
};
} // namespace Common
+6
View File
@@ -49,3 +49,9 @@ ScopeExitHelper<Func> ScopeExit(Func&& func) {
* \endcode
*/
#define SCOPE_EXIT(body) auto CONCAT2(scope_exit_helper_, __LINE__) = detail::ScopeExit([&]() body)
/**
* This macro is similar to SCOPE_EXIT, except the object is caller managed. This is intended to be
* used when the caller might want to cancel the ScopeExit.
*/
#define SCOPE_GUARD(body) detail::ScopeExit([&]() body)
+9 -6
View File
@@ -160,9 +160,16 @@ add_library(core STATIC
hle/kernel/k_affinity_mask.h
hle/kernel/k_condition_variable.cpp
hle/kernel/k_condition_variable.h
hle/kernel/k_event.cpp
hle/kernel/k_event.h
hle/kernel/k_light_condition_variable.h
hle/kernel/k_light_lock.cpp
hle/kernel/k_light_lock.h
hle/kernel/k_priority_queue.h
hle/kernel/k_readable_event.cpp
hle/kernel/k_readable_event.h
hle/kernel/k_resource_limit.cpp
hle/kernel/k_resource_limit.h
hle/kernel/k_scheduler.cpp
hle/kernel/k_scheduler.h
hle/kernel/k_scheduler_lock.h
@@ -173,6 +180,8 @@ add_library(core STATIC
hle/kernel/k_thread.cpp
hle/kernel/k_thread.h
hle/kernel/k_thread_queue.h
hle/kernel/k_writable_event.cpp
hle/kernel/k_writable_event.h
hle/kernel/kernel.cpp
hle/kernel/kernel.h
hle/kernel/memory/address_space_info.cpp
@@ -201,10 +210,6 @@ add_library(core STATIC
hle/kernel/process.h
hle/kernel/process_capability.cpp
hle/kernel/process_capability.h
hle/kernel/readable_event.cpp
hle/kernel/readable_event.h
hle/kernel/resource_limit.cpp
hle/kernel/resource_limit.h
hle/kernel/server_port.cpp
hle/kernel/server_port.h
hle/kernel/server_session.cpp
@@ -225,8 +230,6 @@ add_library(core STATIC
hle/kernel/time_manager.h
hle/kernel/transfer_memory.cpp
hle/kernel/transfer_memory.h
hle/kernel/writable_event.cpp
hle/kernel/writable_event.h
hle/lock.cpp
hle/lock.h
hle/result.h
+3 -2
View File
@@ -71,8 +71,9 @@ public:
}
void ExceptionRaised(u32 pc, Dynarmic::A32::Exception exception) override {
LOG_CRITICAL(Core_ARM, "ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X})",
exception, pc, MemoryReadCode(pc));
LOG_CRITICAL(Core_ARM,
"ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X}, thumb = {})",
exception, pc, MemoryReadCode(pc), parent.IsInThumbMode());
UNIMPLEMENTED();
}
+4
View File
@@ -50,6 +50,10 @@ public:
u64 GetTPIDR_EL0() const override;
void ChangeProcessorID(std::size_t new_core_id) override;
bool IsInThumbMode() const {
return (GetPSTATE() & 0x20) != 0;
}
void SaveContext(ThreadContext32& ctx) override;
void SaveContext(ThreadContext64& ctx) override {}
void LoadContext(const ThreadContext32& ctx) override;
+5
View File
@@ -568,6 +568,11 @@ KeyManager::KeyManager() {
// Initialize keys
const std::string hactool_keys_dir = Common::FS::GetHactoolConfigurationPath();
const std::string yuzu_keys_dir = Common::FS::GetUserPath(Common::FS::UserPath::KeysDir);
if (!Common::FS::Exists(yuzu_keys_dir)) {
Common::FS::CreateDir(yuzu_keys_dir);
}
if (Settings::values.use_dev_keys) {
dev_mode = true;
AttemptLoadKeyFile(yuzu_keys_dir, hactool_keys_dir, "dev.keys", false);
+2 -2
View File
@@ -17,16 +17,16 @@
#include "core/hle/kernel/errors.h"
#include "core/hle/kernel/handle_table.h"
#include "core/hle/kernel/hle_ipc.h"
#include "core/hle/kernel/k_readable_event.h"
#include "core/hle/kernel/k_scheduler.h"
#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"
#include "core/hle/kernel/k_thread.h"
#include "core/hle/kernel/k_writable_event.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/object.h"
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/server_session.h"
#include "core/hle/kernel/time_manager.h"
#include "core/hle/kernel/writable_event.h"
#include "core/memory.h"
namespace Kernel {
+2 -2
View File
@@ -41,8 +41,8 @@ class KernelCore;
class Process;
class ServerSession;
class KThread;
class ReadableEvent;
class WritableEvent;
class KReadableEvent;
class KWritableEvent;
enum class ThreadWakeupReason;
+36 -54
View File
@@ -118,9 +118,13 @@ ResultCode KAddressArbiter::SignalAndIncrementIfEqual(VAddr addr, s32 value, s32
// Check the userspace value.
s32 user_value{};
R_UNLESS(UpdateIfEqual(system, std::addressof(user_value), addr, value, value + 1),
Svc::ResultInvalidCurrentMemory);
R_UNLESS(user_value == value, Svc::ResultInvalidState);
if (!UpdateIfEqual(system, &user_value, addr, value, value + 1)) {
LOG_ERROR(Kernel, "Invalid current memory!");
return Svc::ResultInvalidCurrentMemory;
}
if (user_value != value) {
return Svc::ResultInvalidState;
}
auto it = thread_tree.nfind_light({addr, -1});
while ((it != thread_tree.end()) && (count <= 0 || num_waiters < count) &&
@@ -143,61 +147,34 @@ ResultCode KAddressArbiter::SignalAndModifyByWaitingCountIfEqual(VAddr addr, s32
// Perform signaling.
s32 num_waiters{};
{
KScopedSchedulerLock sl(kernel);
[[maybe_unused]] const KScopedSchedulerLock sl(kernel);
auto it = thread_tree.nfind_light({addr, -1});
// Determine the updated value.
s32 new_value{};
if (/*GetTargetFirmware() >= TargetFirmware_7_0_0*/ true) {
if (count <= 0) {
if ((it != thread_tree.end()) && (it->GetAddressArbiterKey() == addr)) {
new_value = value - 2;
} else {
new_value = value + 1;
}
if (count <= 0) {
if (it != thread_tree.end() && it->GetAddressArbiterKey() == addr) {
new_value = value - 2;
} else {
if ((it != thread_tree.end()) && (it->GetAddressArbiterKey() == addr)) {
auto tmp_it = it;
s32 tmp_num_waiters{};
while ((++tmp_it != thread_tree.end()) &&
(tmp_it->GetAddressArbiterKey() == addr)) {
if ((tmp_num_waiters++) >= count) {
break;
}
}
if (tmp_num_waiters < count) {
new_value = value - 1;
} else {
new_value = value;
}
} else {
new_value = value + 1;
}
new_value = value + 1;
}
} else {
if (count <= 0) {
if ((it != thread_tree.end()) && (it->GetAddressArbiterKey() == addr)) {
new_value = value - 1;
} else {
new_value = value + 1;
}
} else {
if (it != thread_tree.end() && it->GetAddressArbiterKey() == addr) {
auto tmp_it = it;
s32 tmp_num_waiters{};
while ((tmp_it != thread_tree.end()) && (tmp_it->GetAddressArbiterKey() == addr) &&
(tmp_num_waiters < count + 1)) {
++tmp_num_waiters;
++tmp_it;
while (++tmp_it != thread_tree.end() && tmp_it->GetAddressArbiterKey() == addr) {
if (tmp_num_waiters++ >= count) {
break;
}
}
if (tmp_num_waiters == 0) {
new_value = value + 1;
} else if (tmp_num_waiters <= count) {
if (tmp_num_waiters < count) {
new_value = value - 1;
} else {
new_value = value;
}
} else {
new_value = value + 1;
}
}
@@ -205,13 +182,18 @@ ResultCode KAddressArbiter::SignalAndModifyByWaitingCountIfEqual(VAddr addr, s32
s32 user_value{};
bool succeeded{};
if (value != new_value) {
succeeded = UpdateIfEqual(system, std::addressof(user_value), addr, value, new_value);
succeeded = UpdateIfEqual(system, &user_value, addr, value, new_value);
} else {
succeeded = ReadFromUser(system, std::addressof(user_value), addr);
succeeded = ReadFromUser(system, &user_value, addr);
}
R_UNLESS(succeeded, Svc::ResultInvalidCurrentMemory);
R_UNLESS(user_value == value, Svc::ResultInvalidState);
if (!succeeded) {
LOG_ERROR(Kernel, "Invalid current memory!");
return Svc::ResultInvalidCurrentMemory;
}
if (user_value != value) {
return Svc::ResultInvalidState;
}
while ((it != thread_tree.end()) && (count <= 0 || num_waiters < count) &&
(it->GetAddressArbiterKey() == addr)) {
@@ -249,9 +231,9 @@ ResultCode KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement
s32 user_value{};
bool succeeded{};
if (decrement) {
succeeded = DecrementIfLessThan(system, std::addressof(user_value), addr, value);
succeeded = DecrementIfLessThan(system, &user_value, addr, value);
} else {
succeeded = ReadFromUser(system, std::addressof(user_value), addr);
succeeded = ReadFromUser(system, &user_value, addr);
}
if (!succeeded) {
@@ -272,7 +254,7 @@ ResultCode KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement
}
// Set the arbiter.
cur_thread->SetAddressArbiter(std::addressof(thread_tree), addr);
cur_thread->SetAddressArbiter(&thread_tree, addr);
thread_tree.insert(*cur_thread);
cur_thread->SetState(ThreadState::Waiting);
cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration);
@@ -293,7 +275,7 @@ ResultCode KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement
// Get the result.
KSynchronizationObject* dummy{};
return cur_thread->GetWaitResult(std::addressof(dummy));
return cur_thread->GetWaitResult(&dummy);
}
ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) {
@@ -314,7 +296,7 @@ ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) {
// Read the value from userspace.
s32 user_value{};
if (!ReadFromUser(system, std::addressof(user_value), addr)) {
if (!ReadFromUser(system, &user_value, addr)) {
slp.CancelSleep();
return Svc::ResultInvalidCurrentMemory;
}
@@ -332,7 +314,7 @@ ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) {
}
// Set the arbiter.
cur_thread->SetAddressArbiter(std::addressof(thread_tree), addr);
cur_thread->SetAddressArbiter(&thread_tree, addr);
thread_tree.insert(*cur_thread);
cur_thread->SetState(ThreadState::Waiting);
cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration);
@@ -353,7 +335,7 @@ ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) {
// Get the result.
KSynchronizationObject* dummy{};
return cur_thread->GetWaitResult(std::addressof(dummy));
return cur_thread->GetWaitResult(&dummy);
}
} // namespace Kernel
+1 -1
View File
@@ -27,7 +27,7 @@ public:
}
[[nodiscard]] constexpr bool GetAffinity(s32 core) const {
return this->mask & GetCoreBit(core);
return (this->mask & GetCoreBit(core)) != 0;
}
constexpr void SetAffinity(s32 core, bool set) {
+32
View File
@@ -0,0 +1,32 @@
// Copyright 2021 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "core/hle/kernel/k_event.h"
#include "core/hle/kernel/k_readable_event.h"
#include "core/hle/kernel/k_writable_event.h"
namespace Kernel {
KEvent::KEvent(KernelCore& kernel, std::string&& name) : Object{kernel, std::move(name)} {}
KEvent::~KEvent() = default;
std::shared_ptr<KEvent> KEvent::Create(KernelCore& kernel, std::string&& name) {
return std::make_shared<KEvent>(kernel, std::move(name));
}
void KEvent::Initialize() {
// Create our sub events.
readable_event = std::make_shared<KReadableEvent>(kernel, GetName() + ":Readable");
writable_event = std::make_shared<KWritableEvent>(kernel, GetName() + ":Writable");
// Initialize our sub sessions.
readable_event->Initialize(this);
writable_event->Initialize(this);
// Mark initialized.
initialized = true;
}
} // namespace Kernel
+57
View File
@@ -0,0 +1,57 @@
// Copyright 2021 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include "core/hle/kernel/object.h"
namespace Kernel {
class KernelCore;
class KReadableEvent;
class KWritableEvent;
class KEvent final : public Object {
public:
explicit KEvent(KernelCore& kernel, std::string&& name);
~KEvent() override;
static std::shared_ptr<KEvent> Create(KernelCore& kernel, std::string&& name);
void Initialize();
void Finalize() override {}
std::string GetTypeName() const override {
return "KEvent";
}
static constexpr HandleType HANDLE_TYPE = HandleType::Event;
HandleType GetHandleType() const override {
return HANDLE_TYPE;
}
std::shared_ptr<KReadableEvent>& GetReadableEvent() {
return readable_event;
}
std::shared_ptr<KWritableEvent>& GetWritableEvent() {
return writable_event;
}
const std::shared_ptr<KReadableEvent>& GetReadableEvent() const {
return readable_event;
}
const std::shared_ptr<KWritableEvent>& GetWritableEvent() const {
return writable_event;
}
private:
std::shared_ptr<KReadableEvent> readable_event;
std::shared_ptr<KWritableEvent> writable_event;
bool initialized{};
};
} // namespace Kernel
@@ -0,0 +1,57 @@
// Copyright 2020 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
// This file references various implementation details from Atmosphere, an open-source firmware for
// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX.
#pragma once
#include "common/common_types.h"
#include "core/hle/kernel/k_scheduler.h"
#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"
#include "core/hle/kernel/k_thread_queue.h"
#include "core/hle/kernel/time_manager.h"
namespace Kernel {
class KernelCore;
class KLightConditionVariable {
public:
explicit KLightConditionVariable(KernelCore& kernel) : thread_queue(kernel), kernel(kernel) {}
void Wait(KLightLock* lock, s64 timeout = -1) {
WaitImpl(lock, timeout);
lock->Lock();
}
void Broadcast() {
KScopedSchedulerLock lk{kernel};
while (thread_queue.WakeupFrontThread() != nullptr) {
// We want to signal all threads, and so should continue waking up until there's nothing
// to wake.
}
}
private:
void WaitImpl(KLightLock* lock, s64 timeout) {
KThread* owner = GetCurrentThreadPointer(kernel);
// Sleep the thread.
{
KScopedSchedulerLockAndSleep lk(kernel, owner, timeout);
lock->Unlock();
if (!thread_queue.SleepThread(owner)) {
lk.CancelSleep();
return;
}
}
// Cancel the task that the sleep setup.
kernel.TimeManager().UnscheduleTimeEvent(owner);
}
KThreadQueue thread_queue;
KernelCore& kernel;
};
} // namespace Kernel
+9 -9
View File
@@ -24,11 +24,11 @@ template <typename T>
concept KPriorityQueueAffinityMask = !std::is_reference_v<T> && requires(T & t) {
{ t.GetAffinityMask() }
->Common::ConvertibleTo<u64>;
{t.SetAffinityMask(std::declval<u64>())};
{t.SetAffinityMask(0)};
{ t.GetAffinity(std::declval<int32_t>()) }
{ t.GetAffinity(0) }
->std::same_as<bool>;
{t.SetAffinity(std::declval<int32_t>(), std::declval<bool>())};
{t.SetAffinity(0, false)};
{t.SetAll()};
};
@@ -42,11 +42,11 @@ concept KPriorityQueueMember = !std::is_reference_v<T> && requires(T & t) {
->std::same_as<T*>;
{ (typename T::QueueEntry()).GetPrev() }
->std::same_as<T*>;
{ t.GetPriorityQueueEntry(std::declval<s32>()) }
{ t.GetPriorityQueueEntry(0) }
->std::same_as<typename T::QueueEntry&>;
{t.GetAffinityMask()};
{ typename std::remove_cvref<decltype(t.GetAffinityMask())>::type() }
{ std::remove_cvref_t<decltype(t.GetAffinityMask())>() }
->KPriorityQueueAffinityMask;
{ t.GetActiveCore() }
@@ -55,17 +55,17 @@ concept KPriorityQueueMember = !std::is_reference_v<T> && requires(T & t) {
->Common::ConvertibleTo<s32>;
};
template <typename Member, size_t _NumCores, int LowestPriority, int HighestPriority>
template <typename Member, size_t NumCores_, int LowestPriority, int HighestPriority>
requires KPriorityQueueMember<Member> class KPriorityQueue {
public:
using AffinityMaskType = typename std::remove_cv_t<
typename std::remove_reference<decltype(std::declval<Member>().GetAffinityMask())>::type>;
using AffinityMaskType = std::remove_cv_t<
std::remove_reference_t<decltype(std::declval<Member>().GetAffinityMask())>>;
static_assert(LowestPriority >= 0);
static_assert(HighestPriority >= 0);
static_assert(LowestPriority >= HighestPriority);
static constexpr size_t NumPriority = LowestPriority - HighestPriority + 1;
static constexpr size_t NumCores = _NumCores;
static constexpr size_t NumCores = NumCores_;
static constexpr bool IsValidCore(s32 core) {
return 0 <= core && core < static_cast<s32>(NumCores);
+57
View File
@@ -0,0 +1,57 @@
// Copyright 2021 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <algorithm>
#include "common/assert.h"
#include "common/common_funcs.h"
#include "common/logging/log.h"
#include "core/hle/kernel/errors.h"
#include "core/hle/kernel/k_readable_event.h"
#include "core/hle/kernel/k_scheduler.h"
#include "core/hle/kernel/k_thread.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/object.h"
#include "core/hle/kernel/svc_results.h"
namespace Kernel {
KReadableEvent::KReadableEvent(KernelCore& kernel, std::string&& name)
: KSynchronizationObject{kernel, std::move(name)} {}
KReadableEvent::~KReadableEvent() = default;
bool KReadableEvent::IsSignaled() const {
ASSERT(kernel.GlobalSchedulerContext().IsLocked());
return is_signaled;
}
ResultCode KReadableEvent::Signal() {
KScopedSchedulerLock lk{kernel};
if (!is_signaled) {
is_signaled = true;
NotifyAvailable();
}
return RESULT_SUCCESS;
}
ResultCode KReadableEvent::Clear() {
Reset();
return RESULT_SUCCESS;
}
ResultCode KReadableEvent::Reset() {
KScopedSchedulerLock lk{kernel};
if (!is_signaled) {
return Svc::ResultInvalidState;
}
is_signaled = false;
return RESULT_SUCCESS;
}
} // namespace Kernel
+51
View File
@@ -0,0 +1,51 @@
// Copyright 2021 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include "core/hle/kernel/k_synchronization_object.h"
#include "core/hle/kernel/object.h"
#include "core/hle/result.h"
namespace Kernel {
class KernelCore;
class KEvent;
class KReadableEvent final : public KSynchronizationObject {
public:
explicit KReadableEvent(KernelCore& kernel, std::string&& name);
~KReadableEvent() override;
std::string GetTypeName() const override {
return "KReadableEvent";
}
static constexpr HandleType HANDLE_TYPE = HandleType::ReadableEvent;
HandleType GetHandleType() const override {
return HANDLE_TYPE;
}
KEvent* GetParent() const {
return parent;
}
void Initialize(KEvent* parent_) {
is_signaled = false;
parent = parent_;
}
bool IsSignaled() const override;
void Finalize() override {}
ResultCode Signal();
ResultCode Clear();
ResultCode Reset();
private:
bool is_signaled{};
KEvent* parent{};
};
} // namespace Kernel
+152
View File
@@ -0,0 +1,152 @@
// Copyright 2020 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
// This file references various implementation details from Atmosphere, an open-source firmware for
// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX.
#include "common/assert.h"
#include "core/core.h"
#include "core/core_timing.h"
#include "core/core_timing_util.h"
#include "core/hle/kernel/k_resource_limit.h"
#include "core/hle/kernel/svc_results.h"
namespace Kernel {
constexpr s64 DefaultTimeout = 10000000000; // 10 seconds
KResourceLimit::KResourceLimit(KernelCore& kernel, Core::System& system)
: Object{kernel}, lock{kernel}, cond_var{kernel}, kernel{kernel}, system(system) {}
KResourceLimit::~KResourceLimit() = default;
s64 KResourceLimit::GetLimitValue(LimitableResource which) const {
const auto index = static_cast<std::size_t>(which);
s64 value{};
{
KScopedLightLock lk{lock};
value = limit_values[index];
ASSERT(value >= 0);
ASSERT(current_values[index] <= limit_values[index]);
ASSERT(current_hints[index] <= current_values[index]);
}
return value;
}
s64 KResourceLimit::GetCurrentValue(LimitableResource which) const {
const auto index = static_cast<std::size_t>(which);
s64 value{};
{
KScopedLightLock lk{lock};
value = current_values[index];
ASSERT(value >= 0);
ASSERT(current_values[index] <= limit_values[index]);
ASSERT(current_hints[index] <= current_values[index]);
}
return value;
}
s64 KResourceLimit::GetPeakValue(LimitableResource which) const {
const auto index = static_cast<std::size_t>(which);
s64 value{};
{
KScopedLightLock lk{lock};
value = peak_values[index];
ASSERT(value >= 0);
ASSERT(current_values[index] <= limit_values[index]);
ASSERT(current_hints[index] <= current_values[index]);
}
return value;
}
s64 KResourceLimit::GetFreeValue(LimitableResource which) const {
const auto index = static_cast<std::size_t>(which);
s64 value{};
{
KScopedLightLock lk(lock);
ASSERT(current_values[index] >= 0);
ASSERT(current_values[index] <= limit_values[index]);
ASSERT(current_hints[index] <= current_values[index]);
value = limit_values[index] - current_values[index];
}
return value;
}
ResultCode KResourceLimit::SetLimitValue(LimitableResource which, s64 value) {
const auto index = static_cast<std::size_t>(which);
KScopedLightLock lk(lock);
R_UNLESS(current_values[index] <= value, Svc::ResultInvalidState);
limit_values[index] = value;
return RESULT_SUCCESS;
}
bool KResourceLimit::Reserve(LimitableResource which, s64 value) {
return Reserve(which, value, system.CoreTiming().GetGlobalTimeNs().count() + DefaultTimeout);
}
bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) {
ASSERT(value >= 0);
const auto index = static_cast<std::size_t>(which);
KScopedLightLock lk(lock);
ASSERT(current_hints[index] <= current_values[index]);
if (current_hints[index] >= limit_values[index]) {
return false;
}
// Loop until we reserve or run out of time.
while (true) {
ASSERT(current_values[index] <= limit_values[index]);
ASSERT(current_hints[index] <= current_values[index]);
// If we would overflow, don't allow to succeed.
if (current_values[index] + value <= current_values[index]) {
break;
}
if (current_values[index] + value <= limit_values[index]) {
current_values[index] += value;
current_hints[index] += value;
peak_values[index] = std::max(peak_values[index], current_values[index]);
return true;
}
if (current_hints[index] + value <= limit_values[index] &&
(timeout < 0 || system.CoreTiming().GetGlobalTimeNs().count() < timeout)) {
waiter_count++;
cond_var.Wait(&lock, timeout);
waiter_count--;
} else {
break;
}
}
return false;
}
void KResourceLimit::Release(LimitableResource which, s64 value) {
Release(which, value, value);
}
void KResourceLimit::Release(LimitableResource which, s64 value, s64 hint) {
ASSERT(value >= 0);
ASSERT(hint >= 0);
const auto index = static_cast<std::size_t>(which);
KScopedLightLock lk(lock);
ASSERT(current_values[index] <= limit_values[index]);
ASSERT(current_hints[index] <= current_values[index]);
ASSERT(value <= current_values[index]);
ASSERT(hint <= current_hints[index]);
current_values[index] -= value;
current_hints[index] -= hint;
if (waiter_count != 0) {
cond_var.Broadcast();
}
}
} // namespace Kernel
+81
View File
@@ -0,0 +1,81 @@
// Copyright 2020 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
// This file references various implementation details from Atmosphere, an open-source firmware for
// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX.
#pragma once
#include <array>
#include "common/common_types.h"
#include "core/hle/kernel/k_light_condition_variable.h"
#include "core/hle/kernel/k_light_lock.h"
#include "core/hle/kernel/object.h"
union ResultCode;
namespace Core {
class System;
}
namespace Kernel {
class KernelCore;
enum class LimitableResource : u32 {
PhysicalMemory = 0,
Threads = 1,
Events = 2,
TransferMemory = 3,
Sessions = 4,
Count,
};
constexpr bool IsValidResourceType(LimitableResource type) {
return type < LimitableResource::Count;
}
class KResourceLimit final : public Object {
public:
explicit KResourceLimit(KernelCore& kernel, Core::System& system);
~KResourceLimit();
s64 GetLimitValue(LimitableResource which) const;
s64 GetCurrentValue(LimitableResource which) const;
s64 GetPeakValue(LimitableResource which) const;
s64 GetFreeValue(LimitableResource which) const;
ResultCode SetLimitValue(LimitableResource which, s64 value);
bool Reserve(LimitableResource which, s64 value);
bool Reserve(LimitableResource which, s64 value, s64 timeout);
void Release(LimitableResource which, s64 value);
void Release(LimitableResource which, s64 value, s64 hint);
std::string GetTypeName() const override {
return "KResourceLimit";
}
std::string GetName() const override {
return GetTypeName();
}
static constexpr HandleType HANDLE_TYPE = HandleType::ResourceLimit;
HandleType GetHandleType() const override {
return HANDLE_TYPE;
}
virtual void Finalize() override {}
private:
using ResourceArray = std::array<s64, static_cast<std::size_t>(LimitableResource::Count)>;
ResourceArray limit_values{};
ResourceArray current_values{};
ResourceArray current_hints{};
ResourceArray peak_values{};
mutable KLightLock lock;
s32 waiter_count{};
KLightConditionVariable cond_var;
KernelCore& kernel;
Core::System& system;
};
} // namespace Kernel
@@ -132,6 +132,9 @@ ResultCode KSynchronizationObject::Wait(KernelCore& kernel, s32* out_index,
KSynchronizationObject::KSynchronizationObject(KernelCore& kernel) : Object{kernel} {}
KSynchronizationObject::KSynchronizationObject(KernelCore& kernel, std::string&& name)
: Object{kernel, std::move(name)} {}
KSynchronizationObject::~KSynchronizationObject() = default;
void KSynchronizationObject::NotifyAvailable(ResultCode result) {
@@ -33,6 +33,7 @@ public:
protected:
explicit KSynchronizationObject(KernelCore& kernel);
explicit KSynchronizationObject(KernelCore& kernel, std::string&& name);
virtual ~KSynchronizationObject();
void NotifyAvailable(ResultCode result);
+2 -2
View File
@@ -21,6 +21,7 @@
#include "core/hle/kernel/errors.h"
#include "core/hle/kernel/handle_table.h"
#include "core/hle/kernel/k_condition_variable.h"
#include "core/hle/kernel/k_resource_limit.h"
#include "core/hle/kernel/k_scheduler.h"
#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"
#include "core/hle/kernel/k_thread.h"
@@ -29,7 +30,6 @@
#include "core/hle/kernel/memory/memory_layout.h"
#include "core/hle/kernel/object.h"
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/resource_limit.h"
#include "core/hle/kernel/svc_results.h"
#include "core/hle/kernel/time_manager.h"
#include "core/hle/result.h"
@@ -247,7 +247,7 @@ void KThread::Finalize() {
// Decrement the parent process's thread count.
if (parent != nullptr) {
parent->DecrementThreadCount();
parent->GetResourceLimit()->Release(ResourceType::Threads, 1);
parent->GetResourceLimit()->Release(LimitableResource::Threads, 1);
}
}
+27
View File
@@ -0,0 +1,27 @@
// Copyright 2021 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "core/hle/kernel/k_event.h"
#include "core/hle/kernel/k_readable_event.h"
#include "core/hle/kernel/k_writable_event.h"
namespace Kernel {
KWritableEvent::KWritableEvent(KernelCore& kernel, std::string&& name)
: Object{kernel, std::move(name)} {}
KWritableEvent::~KWritableEvent() = default;
void KWritableEvent::Initialize(KEvent* parent_) {
parent = parent_;
}
ResultCode KWritableEvent::Signal() {
return parent->GetReadableEvent()->Signal();
}
ResultCode KWritableEvent::Clear() {
return parent->GetReadableEvent()->Clear();
}
} // namespace Kernel
+44
View File
@@ -0,0 +1,44 @@
// Copyright 2021 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include "core/hle/kernel/object.h"
#include "core/hle/result.h"
namespace Kernel {
class KernelCore;
class KEvent;
class KWritableEvent final : public Object {
public:
explicit KWritableEvent(KernelCore& kernel, std::string&& name);
~KWritableEvent() override;
std::string GetTypeName() const override {
return "KWritableEvent";
}
static constexpr HandleType HANDLE_TYPE = HandleType::WritableEvent;
HandleType GetHandleType() const override {
return HANDLE_TYPE;
}
void Initialize(KEvent* parent_);
void Finalize() override {}
ResultCode Signal();
ResultCode Clear();
KEvent* GetParent() const {
return parent;
}
private:
KEvent* parent{};
};
} // namespace Kernel
+13 -13
View File
@@ -28,6 +28,7 @@
#include "core/hle/kernel/client_port.h"
#include "core/hle/kernel/errors.h"
#include "core/hle/kernel/handle_table.h"
#include "core/hle/kernel/k_resource_limit.h"
#include "core/hle/kernel/k_scheduler.h"
#include "core/hle/kernel/k_thread.h"
#include "core/hle/kernel/kernel.h"
@@ -36,7 +37,6 @@
#include "core/hle/kernel/memory/slab_heap.h"
#include "core/hle/kernel/physical_core.h"
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/resource_limit.h"
#include "core/hle/kernel/service_thread.h"
#include "core/hle/kernel/shared_memory.h"
#include "core/hle/kernel/time_manager.h"
@@ -66,7 +66,7 @@ struct KernelCore::Impl {
is_phantom_mode_for_singlecore = false;
InitializePhysicalCores();
InitializeSystemResourceLimit(kernel);
InitializeSystemResourceLimit(kernel, system);
InitializeMemoryLayout();
InitializePreemption(kernel);
InitializeSchedulers();
@@ -131,19 +131,19 @@ struct KernelCore::Impl {
}
// Creates the default system resource limit
void InitializeSystemResourceLimit(KernelCore& kernel) {
system_resource_limit = ResourceLimit::Create(kernel);
void InitializeSystemResourceLimit(KernelCore& kernel, Core::System& system) {
system_resource_limit = std::make_shared<KResourceLimit>(kernel, system);
// If setting the default system values fails, then something seriously wrong has occurred.
ASSERT(system_resource_limit->SetLimitValue(ResourceType::PhysicalMemory, 0x100000000)
ASSERT(system_resource_limit->SetLimitValue(LimitableResource::PhysicalMemory, 0x100000000)
.IsSuccess());
ASSERT(system_resource_limit->SetLimitValue(ResourceType::Threads, 800).IsSuccess());
ASSERT(system_resource_limit->SetLimitValue(ResourceType::Events, 700).IsSuccess());
ASSERT(system_resource_limit->SetLimitValue(ResourceType::TransferMemory, 200).IsSuccess());
ASSERT(system_resource_limit->SetLimitValue(ResourceType::Sessions, 900).IsSuccess());
ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Threads, 800).IsSuccess());
ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Events, 700).IsSuccess());
ASSERT(system_resource_limit->SetLimitValue(LimitableResource::TransferMemory, 200)
.IsSuccess());
ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Sessions, 900).IsSuccess());
if (!system_resource_limit->Reserve(ResourceType::PhysicalMemory, 0) ||
!system_resource_limit->Reserve(ResourceType::PhysicalMemory, 0x60000)) {
if (!system_resource_limit->Reserve(LimitableResource::PhysicalMemory, 0x60000)) {
UNREACHABLE();
}
}
@@ -320,7 +320,7 @@ struct KernelCore::Impl {
std::unique_ptr<Kernel::GlobalSchedulerContext> global_scheduler_context;
Kernel::TimeManager time_manager;
std::shared_ptr<ResourceLimit> system_resource_limit;
std::shared_ptr<KResourceLimit> system_resource_limit;
std::shared_ptr<Core::Timing::EventType> preemption_event;
@@ -390,7 +390,7 @@ void KernelCore::Shutdown() {
impl->Shutdown();
}
std::shared_ptr<ResourceLimit> KernelCore::GetSystemResourceLimit() const {
std::shared_ptr<KResourceLimit> KernelCore::GetSystemResourceLimit() const {
return impl->system_resource_limit;
}
+2 -2
View File
@@ -38,7 +38,7 @@ class GlobalSchedulerContext;
class HandleTable;
class PhysicalCore;
class Process;
class ResourceLimit;
class KResourceLimit;
class KScheduler;
class SharedMemory;
class ServiceThread;
@@ -85,7 +85,7 @@ public:
void Shutdown();
/// Retrieves a shared pointer to the system resource limit instance.
std::shared_ptr<ResourceLimit> GetSystemResourceLimit() const;
std::shared_ptr<KResourceLimit> GetSystemResourceLimit() const;
/// Retrieves a shared pointer to a Thread instance within the thread wakeup handle table.
std::shared_ptr<KThread> RetrieveThreadFromGlobalHandleTable(Handle handle) const;
+5 -5
View File
@@ -7,6 +7,7 @@
#include "common/scope_exit.h"
#include "core/core.h"
#include "core/hle/kernel/errors.h"
#include "core/hle/kernel/k_resource_limit.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/memory/address_space_info.h"
#include "core/hle/kernel/memory/memory_block.h"
@@ -15,7 +16,6 @@
#include "core/hle/kernel/memory/page_table.h"
#include "core/hle/kernel/memory/system_control.h"
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/resource_limit.h"
#include "core/memory.h"
namespace Kernel::Memory {
@@ -414,7 +414,7 @@ ResultCode PageTable::MapPhysicalMemory(VAddr addr, std::size_t size) {
const std::size_t remaining_pages{remaining_size / PageSize};
if (process->GetResourceLimit() &&
!process->GetResourceLimit()->Reserve(ResourceType::PhysicalMemory, remaining_size)) {
!process->GetResourceLimit()->Reserve(LimitableResource::PhysicalMemory, remaining_size)) {
return ERR_RESOURCE_LIMIT_EXCEEDED;
}
@@ -422,7 +422,7 @@ ResultCode PageTable::MapPhysicalMemory(VAddr addr, std::size_t size) {
{
auto block_guard = detail::ScopeExit([&] {
system.Kernel().MemoryManager().Free(page_linked_list, remaining_pages, memory_pool);
process->GetResourceLimit()->Release(ResourceType::PhysicalMemory, remaining_size);
process->GetResourceLimit()->Release(LimitableResource::PhysicalMemory, remaining_size);
});
CASCADE_CODE(system.Kernel().MemoryManager().Allocate(page_linked_list, remaining_pages,
@@ -474,7 +474,7 @@ ResultCode PageTable::UnmapPhysicalMemory(VAddr addr, std::size_t size) {
CASCADE_CODE(UnmapMemory(addr, size));
auto process{system.Kernel().CurrentProcess()};
process->GetResourceLimit()->Release(ResourceType::PhysicalMemory, mapped_size);
process->GetResourceLimit()->Release(LimitableResource::PhysicalMemory, mapped_size);
physical_memory_usage -= mapped_size;
return RESULT_SUCCESS;
@@ -783,7 +783,7 @@ ResultVal<VAddr> PageTable::SetHeapSize(std::size_t size) {
auto process{system.Kernel().CurrentProcess()};
if (process->GetResourceLimit() && delta != 0 &&
!process->GetResourceLimit()->Reserve(ResourceType::PhysicalMemory, delta)) {
!process->GetResourceLimit()->Reserve(LimitableResource::PhysicalMemory, delta)) {
return ERR_RESOURCE_LIMIT_EXCEEDED;
}
+5 -1
View File
@@ -8,7 +8,10 @@
namespace Kernel {
Object::Object(KernelCore& kernel) : kernel{kernel}, object_id{kernel.CreateNewObjectID()} {}
Object::Object(KernelCore& kernel_)
: kernel{kernel_}, object_id{kernel_.CreateNewObjectID()}, name{"[UNKNOWN KERNEL OBJECT]"} {}
Object::Object(KernelCore& kernel_, std::string&& name_)
: kernel{kernel_}, object_id{kernel_.CreateNewObjectID()}, name{std::move(name_)} {}
Object::~Object() = default;
bool Object::IsWaitable() const {
@@ -21,6 +24,7 @@ bool Object::IsWaitable() const {
return true;
case HandleType::Unknown:
case HandleType::Event:
case HandleType::WritableEvent:
case HandleType::SharedMemory:
case HandleType::TransferMemory:
+5 -2
View File
@@ -18,6 +18,7 @@ using Handle = u32;
enum class HandleType : u32 {
Unknown,
Event,
WritableEvent,
ReadableEvent,
SharedMemory,
@@ -34,7 +35,8 @@ enum class HandleType : u32 {
class Object : NonCopyable, public std::enable_shared_from_this<Object> {
public:
explicit Object(KernelCore& kernel);
explicit Object(KernelCore& kernel_);
explicit Object(KernelCore& kernel_, std::string&& name_);
virtual ~Object();
/// Returns a unique identifier for the object. For debugging purposes only.
@@ -46,7 +48,7 @@ public:
return "[BAD KERNEL OBJECT TYPE]";
}
virtual std::string GetName() const {
return "[UNKNOWN KERNEL OBJECT]";
return name;
}
virtual HandleType GetHandleType() const = 0;
@@ -69,6 +71,7 @@ protected:
private:
std::atomic<u32> object_id{0};
std::string name;
};
template <typename T>
+21 -22
View File
@@ -15,6 +15,7 @@
#include "core/file_sys/program_metadata.h"
#include "core/hle/kernel/code_set.h"
#include "core/hle/kernel/errors.h"
#include "core/hle/kernel/k_resource_limit.h"
#include "core/hle/kernel/k_scheduler.h"
#include "core/hle/kernel/k_thread.h"
#include "core/hle/kernel/kernel.h"
@@ -22,7 +23,7 @@
#include "core/hle/kernel/memory/page_table.h"
#include "core/hle/kernel/memory/slab_heap.h"
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/resource_limit.h"
#include "core/hle/kernel/svc_results.h"
#include "core/hle/lock.h"
#include "core/memory.h"
#include "core/settings.h"
@@ -116,7 +117,7 @@ std::shared_ptr<Process> Process::Create(Core::System& system, std::string name,
std::shared_ptr<Process> process = std::make_shared<Process>(system);
process->name = std::move(name);
process->resource_limit = ResourceLimit::Create(kernel);
process->resource_limit = std::make_shared<KResourceLimit>(kernel, system);
process->status = ProcessStatus::Created;
process->program_id = 0;
process->process_id = type == ProcessType::KernelInternal ? kernel.CreateNewKernelProcessID()
@@ -132,7 +133,7 @@ std::shared_ptr<Process> Process::Create(Core::System& system, std::string name,
return process;
}
std::shared_ptr<ResourceLimit> Process::GetResourceLimit() const {
std::shared_ptr<KResourceLimit> Process::GetResourceLimit() const {
return resource_limit;
}
@@ -154,7 +155,7 @@ void Process::DecrementThreadCount() {
}
u64 Process::GetTotalPhysicalMemoryAvailable() const {
const u64 capacity{resource_limit->GetCurrentResourceValue(ResourceType::PhysicalMemory) +
const u64 capacity{resource_limit->GetFreeValue(LimitableResource::PhysicalMemory) +
page_table->GetTotalHeapSize() + GetSystemResourceSize() + image_size +
main_thread_stack_size};
@@ -241,18 +242,16 @@ void Process::UnregisterThread(const KThread* thread) {
thread_list.remove(thread);
}
ResultCode Process::ClearSignalState() {
KScopedSchedulerLock lock(system.Kernel());
if (status == ProcessStatus::Exited) {
LOG_ERROR(Kernel, "called on a terminated process instance.");
return ERR_INVALID_STATE;
}
ResultCode Process::Reset() {
// Lock the process and the scheduler.
KScopedLightLock lk(state_lock);
KScopedSchedulerLock sl{kernel};
if (!is_signaled) {
LOG_ERROR(Kernel, "called on a process instance that isn't signaled.");
return ERR_INVALID_STATE;
}
// Validate that we're in a state that we can reset.
R_UNLESS(status != ProcessStatus::Exited, Svc::ResultInvalidState);
R_UNLESS(is_signaled, Svc::ResultInvalidState);
// Clear signaled.
is_signaled = false;
return RESULT_SUCCESS;
}
@@ -308,13 +307,13 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata,
// Set initial resource limits
resource_limit->SetLimitValue(
ResourceType::PhysicalMemory,
LimitableResource::PhysicalMemory,
kernel.MemoryManager().GetSize(Memory::MemoryManager::Pool::Application));
resource_limit->SetLimitValue(ResourceType::Threads, 608);
resource_limit->SetLimitValue(ResourceType::Events, 700);
resource_limit->SetLimitValue(ResourceType::TransferMemory, 128);
resource_limit->SetLimitValue(ResourceType::Sessions, 894);
ASSERT(resource_limit->Reserve(ResourceType::PhysicalMemory, code_size));
resource_limit->SetLimitValue(LimitableResource::Threads, 608);
resource_limit->SetLimitValue(LimitableResource::Events, 700);
resource_limit->SetLimitValue(LimitableResource::TransferMemory, 128);
resource_limit->SetLimitValue(LimitableResource::Sessions, 894);
ASSERT(resource_limit->Reserve(LimitableResource::PhysicalMemory, code_size));
// Create TLS region
tls_region_address = CreateTLSRegion();
@@ -331,8 +330,8 @@ void Process::Run(s32 main_thread_priority, u64 stack_size) {
ChangeStatus(ProcessStatus::Running);
SetupMainThread(system, *this, main_thread_priority, main_thread_stack_top);
resource_limit->Reserve(ResourceType::Threads, 1);
resource_limit->Reserve(ResourceType::PhysicalMemory, main_thread_stack_size);
resource_limit->Reserve(LimitableResource::Threads, 1);
resource_limit->Reserve(LimitableResource::PhysicalMemory, main_thread_stack_size);
}
void Process::PrepareForTermination() {
+4 -4
View File
@@ -29,7 +29,7 @@ class ProgramMetadata;
namespace Kernel {
class KernelCore;
class ResourceLimit;
class KResourceLimit;
class KThread;
class TLSPage;
@@ -170,7 +170,7 @@ public:
}
/// Gets the resource limit descriptor for this process
std::shared_ptr<ResourceLimit> GetResourceLimit() const;
std::shared_ptr<KResourceLimit> GetResourceLimit() const;
/// Gets the ideal CPU core ID for this process
u8 GetIdealCoreId() const {
@@ -312,7 +312,7 @@ public:
/// @pre The process must be in a signaled state. If this is called on a
/// process instance that is not signaled, ERR_INVALID_STATE will be
/// returned.
ResultCode ClearSignalState();
ResultCode Reset();
/**
* Loads process-specifics configuration info with metadata provided
@@ -402,7 +402,7 @@ private:
u32 system_resource_size = 0;
/// Resource limit descriptor for this process
std::shared_ptr<ResourceLimit> resource_limit;
std::shared_ptr<KResourceLimit> resource_limit;
/// The ideal CPU core for this process, threads are scheduled on this core by default.
u8 ideal_core = 0;
-52
View File
@@ -1,52 +0,0 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <algorithm>
#include "common/assert.h"
#include "common/logging/log.h"
#include "core/hle/kernel/errors.h"
#include "core/hle/kernel/k_scheduler.h"
#include "core/hle/kernel/k_thread.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/object.h"
#include "core/hle/kernel/readable_event.h"
namespace Kernel {
ReadableEvent::ReadableEvent(KernelCore& kernel) : KSynchronizationObject{kernel} {}
ReadableEvent::~ReadableEvent() = default;
void ReadableEvent::Signal() {
if (is_signaled) {
return;
}
is_signaled = true;
NotifyAvailable();
}
bool ReadableEvent::IsSignaled() const {
ASSERT(kernel.GlobalSchedulerContext().IsLocked());
return is_signaled;
}
void ReadableEvent::Clear() {
is_signaled = false;
}
ResultCode ReadableEvent::Reset() {
KScopedSchedulerLock lock(kernel);
if (!is_signaled) {
LOG_TRACE(Kernel, "Handle is not signaled! object_id={}, object_type={}, object_name={}",
GetObjectId(), GetTypeName(), GetName());
return ERR_INVALID_STATE;
}
Clear();
return RESULT_SUCCESS;
}
} // namespace Kernel
-59
View File
@@ -1,59 +0,0 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include "core/hle/kernel/k_synchronization_object.h"
#include "core/hle/kernel/object.h"
union ResultCode;
namespace Kernel {
class KernelCore;
class WritableEvent;
class ReadableEvent final : public KSynchronizationObject {
friend class WritableEvent;
public:
~ReadableEvent() override;
std::string GetTypeName() const override {
return "ReadableEvent";
}
std::string GetName() const override {
return name;
}
static constexpr HandleType HANDLE_TYPE = HandleType::ReadableEvent;
HandleType GetHandleType() const override {
return HANDLE_TYPE;
}
/// Unconditionally clears the readable event's state.
void Clear();
/// Clears the readable event's state if and only if it
/// has already been signaled.
///
/// @pre The event must be in a signaled state. If this event
/// is in an unsignaled state and this function is called,
/// then ERR_INVALID_STATE will be returned.
ResultCode Reset();
void Signal();
bool IsSignaled() const override;
void Finalize() override {}
private:
explicit ReadableEvent(KernelCore& kernel);
bool is_signaled{};
std::string name; ///< Name of event (optional)
};
} // namespace Kernel
-73
View File
@@ -1,73 +0,0 @@
// Copyright 2015 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "core/hle/kernel/errors.h"
#include "core/hle/kernel/resource_limit.h"
#include "core/hle/result.h"
namespace Kernel {
namespace {
constexpr std::size_t ResourceTypeToIndex(ResourceType type) {
return static_cast<std::size_t>(type);
}
} // Anonymous namespace
ResourceLimit::ResourceLimit(KernelCore& kernel) : Object{kernel} {}
ResourceLimit::~ResourceLimit() = default;
bool ResourceLimit::Reserve(ResourceType resource, s64 amount) {
return Reserve(resource, amount, 10000000000);
}
bool ResourceLimit::Reserve(ResourceType resource, s64 amount, u64 timeout) {
const std::size_t index{ResourceTypeToIndex(resource)};
s64 new_value = current[index] + amount;
if (new_value > limit[index] && available[index] + amount <= limit[index]) {
// TODO(bunnei): This is wrong for multicore, we should wait the calling thread for timeout
new_value = current[index] + amount;
}
if (new_value <= limit[index]) {
current[index] = new_value;
return true;
}
return false;
}
void ResourceLimit::Release(ResourceType resource, u64 amount) {
Release(resource, amount, amount);
}
void ResourceLimit::Release(ResourceType resource, u64 used_amount, u64 available_amount) {
const std::size_t index{ResourceTypeToIndex(resource)};
current[index] -= used_amount;
available[index] -= available_amount;
}
std::shared_ptr<ResourceLimit> ResourceLimit::Create(KernelCore& kernel) {
return std::make_shared<ResourceLimit>(kernel);
}
s64 ResourceLimit::GetCurrentResourceValue(ResourceType resource) const {
return limit.at(ResourceTypeToIndex(resource)) - current.at(ResourceTypeToIndex(resource));
}
s64 ResourceLimit::GetMaxResourceValue(ResourceType resource) const {
return limit.at(ResourceTypeToIndex(resource));
}
ResultCode ResourceLimit::SetLimitValue(ResourceType resource, s64 value) {
const std::size_t index{ResourceTypeToIndex(resource)};
if (current[index] <= value) {
limit[index] = value;
return RESULT_SUCCESS;
} else {
LOG_ERROR(Kernel, "Limit value is too large! resource={}, value={}, index={}", resource,
value, index);
return ERR_INVALID_STATE;
}
}
} // namespace Kernel
-106
View File
@@ -1,106 +0,0 @@
// Copyright 2015 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <array>
#include <memory>
#include "common/common_types.h"
#include "core/hle/kernel/object.h"
union ResultCode;
namespace Kernel {
class KernelCore;
enum class ResourceType : u32 {
PhysicalMemory,
Threads,
Events,
TransferMemory,
Sessions,
// Used as a count, not an actual type.
ResourceTypeCount
};
constexpr bool IsValidResourceType(ResourceType type) {
return type < ResourceType::ResourceTypeCount;
}
class ResourceLimit final : public Object {
public:
explicit ResourceLimit(KernelCore& kernel);
~ResourceLimit() override;
/// Creates a resource limit object.
static std::shared_ptr<ResourceLimit> Create(KernelCore& kernel);
std::string GetTypeName() const override {
return "ResourceLimit";
}
std::string GetName() const override {
return GetTypeName();
}
static constexpr HandleType HANDLE_TYPE = HandleType::ResourceLimit;
HandleType GetHandleType() const override {
return HANDLE_TYPE;
}
bool Reserve(ResourceType resource, s64 amount);
bool Reserve(ResourceType resource, s64 amount, u64 timeout);
void Release(ResourceType resource, u64 amount);
void Release(ResourceType resource, u64 used_amount, u64 available_amount);
/**
* Gets the current value for the specified resource.
* @param resource Requested resource type
* @returns The current value of the resource type
*/
s64 GetCurrentResourceValue(ResourceType resource) const;
/**
* Gets the max value for the specified resource.
* @param resource Requested resource type
* @returns The max value of the resource type
*/
s64 GetMaxResourceValue(ResourceType resource) const;
/**
* Sets the limit value for a given resource type.
*
* @param resource The resource type to apply the limit to.
* @param value The limit to apply to the given resource type.
*
* @return A result code indicating if setting the limit value
* was successful or not.
*
* @note The supplied limit value *must* be greater than or equal to
* the current resource value for the given resource type,
* otherwise ERR_INVALID_STATE will be returned.
*/
ResultCode SetLimitValue(ResourceType resource, s64 value);
void Finalize() override {}
private:
// TODO(Subv): Increment resource limit current values in their respective Kernel::T::Create
// functions
//
// Currently we have no way of distinguishing if a Create was called by the running application,
// or by a service module. Approach this once we have separated the service modules into their
// own processes
using ResourceArray =
std::array<s64, static_cast<std::size_t>(ResourceType::ResourceTypeCount)>;
ResourceArray limit{};
ResourceArray current{};
ResourceArray available{};
};
} // namespace Kernel
+103 -80
View File
@@ -14,6 +14,7 @@
#include "common/fiber.h"
#include "common/logging/log.h"
#include "common/microprofile.h"
#include "common/scope_exit.h"
#include "common/string_util.h"
#include "core/arm/exclusive_monitor.h"
#include "core/core.h"
@@ -26,18 +27,20 @@
#include "core/hle/kernel/handle_table.h"
#include "core/hle/kernel/k_address_arbiter.h"
#include "core/hle/kernel/k_condition_variable.h"
#include "core/hle/kernel/k_event.h"
#include "core/hle/kernel/k_readable_event.h"
#include "core/hle/kernel/k_resource_limit.h"
#include "core/hle/kernel/k_scheduler.h"
#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"
#include "core/hle/kernel/k_synchronization_object.h"
#include "core/hle/kernel/k_thread.h"
#include "core/hle/kernel/k_writable_event.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/memory/memory_block.h"
#include "core/hle/kernel/memory/memory_layout.h"
#include "core/hle/kernel/memory/page_table.h"
#include "core/hle/kernel/physical_core.h"
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/resource_limit.h"
#include "core/hle/kernel/shared_memory.h"
#include "core/hle/kernel/svc.h"
#include "core/hle/kernel/svc_results.h"
@@ -45,7 +48,6 @@
#include "core/hle/kernel/svc_wrap.h"
#include "core/hle/kernel/time_manager.h"
#include "core/hle/kernel/transfer_memory.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/lock.h"
#include "core/hle/result.h"
#include "core/hle/service/service.h"
@@ -141,7 +143,7 @@ enum class ResourceLimitValueType {
ResultVal<s64> RetrieveResourceLimitValue(Core::System& system, Handle resource_limit,
u32 resource_type, ResourceLimitValueType value_type) {
std::lock_guard lock{HLE::g_hle_lock};
const auto type = static_cast<ResourceType>(resource_type);
const auto type = static_cast<LimitableResource>(resource_type);
if (!IsValidResourceType(type)) {
LOG_ERROR(Kernel_SVC, "Invalid resource limit type: '{}'", resource_type);
return ERR_INVALID_ENUM_VALUE;
@@ -151,7 +153,7 @@ ResultVal<s64> RetrieveResourceLimitValue(Core::System& system, Handle resource_
ASSERT(current_process != nullptr);
const auto resource_limit_object =
current_process->GetHandleTable().Get<ResourceLimit>(resource_limit);
current_process->GetHandleTable().Get<KResourceLimit>(resource_limit);
if (!resource_limit_object) {
LOG_ERROR(Kernel_SVC, "Handle to non-existent resource limit instance used. Handle={:08X}",
resource_limit);
@@ -159,10 +161,10 @@ ResultVal<s64> RetrieveResourceLimitValue(Core::System& system, Handle resource_
}
if (value_type == ResourceLimitValueType::CurrentValue) {
return MakeResult(resource_limit_object->GetCurrentResourceValue(type));
return MakeResult(resource_limit_object->GetCurrentValue(type));
}
return MakeResult(resource_limit_object->GetMaxResourceValue(type));
return MakeResult(resource_limit_object->GetLimitValue(type));
}
} // Anonymous namespace
@@ -312,7 +314,7 @@ static ResultCode ConnectToNamedPort(Core::System& system, Handle* out_handle,
return ERR_NOT_FOUND;
}
ASSERT(kernel.CurrentProcess()->GetResourceLimit()->Reserve(ResourceType::Sessions, 1));
ASSERT(kernel.CurrentProcess()->GetResourceLimit()->Reserve(LimitableResource::Sessions, 1));
auto client_port = it->second;
@@ -1450,7 +1452,8 @@ static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr e
Svc::ResultInvalidPriority);
R_UNLESS(process.CheckThreadPriority(priority), Svc::ResultInvalidPriority);
ASSERT(process.GetResourceLimit()->Reserve(ResourceType::Threads, 1));
ASSERT(process.GetResourceLimit()->Reserve(
LimitableResource::Threads, 1, system.CoreTiming().GetGlobalTimeNs().count() + 100000000));
std::shared_ptr<KThread> thread;
{
@@ -1724,20 +1727,28 @@ static ResultCode CloseHandle32(Core::System& system, Handle handle) {
static ResultCode ResetSignal(Core::System& system, Handle handle) {
LOG_DEBUG(Kernel_SVC, "called handle 0x{:08X}", handle);
// Get the current handle table.
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
auto event = handle_table.Get<ReadableEvent>(handle);
if (event) {
return event->Reset();
// Try to reset as readable event.
{
auto readable_event = handle_table.Get<KReadableEvent>(handle);
if (readable_event) {
return readable_event->Reset();
}
}
auto process = handle_table.Get<Process>(handle);
if (process) {
return process->ClearSignalState();
// Try to reset as process.
{
auto process = handle_table.Get<Process>(handle);
if (process) {
return process->Reset();
}
}
LOG_ERROR(Kernel_SVC, "Invalid handle (0x{:08X})", handle);
return ERR_INVALID_HANDLE;
LOG_ERROR(Kernel_SVC, "invalid handle (0x{:08X})", handle);
return Svc::ResultInvalidHandle;
}
static ResultCode ResetSignal32(Core::System& system, Handle handle) {
@@ -1865,80 +1876,92 @@ static ResultCode SetThreadCoreMask32(Core::System& system, Handle thread_handle
return SetThreadCoreMask(system, thread_handle, core_id, affinity_mask);
}
static ResultCode CreateEvent(Core::System& system, Handle* write_handle, Handle* read_handle) {
static ResultCode SignalEvent(Core::System& system, Handle event_handle) {
LOG_DEBUG(Kernel_SVC, "called, event_handle=0x{:08X}", event_handle);
// Get the current handle table.
const HandleTable& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
// Get the writable event.
auto writable_event = handle_table.Get<KWritableEvent>(event_handle);
R_UNLESS(writable_event, Svc::ResultInvalidHandle);
return writable_event->Signal();
}
static ResultCode SignalEvent32(Core::System& system, Handle event_handle) {
return SignalEvent(system, event_handle);
}
static ResultCode ClearEvent(Core::System& system, Handle event_handle) {
LOG_TRACE(Kernel_SVC, "called, event_handle=0x{:08X}", event_handle);
// Get the current handle table.
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
// Try to clear the writable event.
{
auto writable_event = handle_table.Get<KWritableEvent>(event_handle);
if (writable_event) {
return writable_event->Clear();
}
}
// Try to clear the readable event.
{
auto readable_event = handle_table.Get<KReadableEvent>(event_handle);
if (readable_event) {
return readable_event->Clear();
}
}
LOG_ERROR(Kernel_SVC, "Event handle does not exist, event_handle=0x{:08X}", event_handle);
return Svc::ResultInvalidHandle;
}
static ResultCode ClearEvent32(Core::System& system, Handle event_handle) {
return ClearEvent(system, event_handle);
}
static ResultCode CreateEvent(Core::System& system, Handle* out_write, Handle* out_read) {
LOG_DEBUG(Kernel_SVC, "called");
// Get the kernel reference and handle table.
auto& kernel = system.Kernel();
const auto [readable_event, writable_event] =
WritableEvent::CreateEventPair(kernel, "CreateEvent");
HandleTable& handle_table = kernel.CurrentProcess()->GetHandleTable();
const auto write_create_result = handle_table.Create(writable_event);
// Create a new event.
const auto event = KEvent::Create(kernel, "CreateEvent");
R_UNLESS(event != nullptr, Svc::ResultOutOfResource);
// Initialize the event.
event->Initialize();
// Add the writable event to the handle table.
const auto write_create_result = handle_table.Create(event->GetWritableEvent());
if (write_create_result.Failed()) {
return write_create_result.Code();
}
*write_handle = *write_create_result;
*out_write = *write_create_result;
const auto read_create_result = handle_table.Create(readable_event);
// Add the writable event to the handle table.
auto handle_guard = SCOPE_GUARD({ handle_table.Close(*write_create_result); });
// Add the readable event to the handle table.
const auto read_create_result = handle_table.Create(event->GetReadableEvent());
if (read_create_result.Failed()) {
handle_table.Close(*write_create_result);
return read_create_result.Code();
}
*read_handle = *read_create_result;
*out_read = *read_create_result;
LOG_DEBUG(Kernel_SVC,
"successful. Writable event handle=0x{:08X}, Readable event handle=0x{:08X}",
*write_create_result, *read_create_result);
// We succeeded.
handle_guard.Cancel();
return RESULT_SUCCESS;
}
static ResultCode CreateEvent32(Core::System& system, Handle* write_handle, Handle* read_handle) {
return CreateEvent(system, write_handle, read_handle);
}
static ResultCode ClearEvent(Core::System& system, Handle handle) {
LOG_TRACE(Kernel_SVC, "called, event=0x{:08X}", handle);
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
auto writable_event = handle_table.Get<WritableEvent>(handle);
if (writable_event) {
writable_event->Clear();
return RESULT_SUCCESS;
}
auto readable_event = handle_table.Get<ReadableEvent>(handle);
if (readable_event) {
readable_event->Clear();
return RESULT_SUCCESS;
}
LOG_ERROR(Kernel_SVC, "Event handle does not exist, handle=0x{:08X}", handle);
return ERR_INVALID_HANDLE;
}
static ResultCode ClearEvent32(Core::System& system, Handle handle) {
return ClearEvent(system, handle);
}
static ResultCode SignalEvent(Core::System& system, Handle handle) {
LOG_DEBUG(Kernel_SVC, "called. Handle=0x{:08X}", handle);
HandleTable& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
auto writable_event = handle_table.Get<WritableEvent>(handle);
if (!writable_event) {
LOG_ERROR(Kernel_SVC, "Non-existent writable event handle used (0x{:08X})", handle);
return ERR_INVALID_HANDLE;
}
writable_event->Signal();
return RESULT_SUCCESS;
}
static ResultCode SignalEvent32(Core::System& system, Handle handle) {
return SignalEvent(system, handle);
static ResultCode CreateEvent32(Core::System& system, Handle* out_write, Handle* out_read) {
return CreateEvent(system, out_write, out_read);
}
static ResultCode GetProcessInfo(Core::System& system, u64* out, Handle process_handle, u32 type) {
@@ -1972,7 +1995,7 @@ static ResultCode CreateResourceLimit(Core::System& system, Handle* out_handle)
LOG_DEBUG(Kernel_SVC, "called");
auto& kernel = system.Kernel();
auto resource_limit = ResourceLimit::Create(kernel);
auto resource_limit = std::make_shared<KResourceLimit>(kernel, system);
auto* const current_process = kernel.CurrentProcess();
ASSERT(current_process != nullptr);
@@ -2019,7 +2042,7 @@ static ResultCode SetResourceLimitLimitValue(Core::System& system, Handle resour
LOG_DEBUG(Kernel_SVC, "called. Handle={:08X}, Resource type={}, Value={}", resource_limit,
resource_type, value);
const auto type = static_cast<ResourceType>(resource_type);
const auto type = static_cast<LimitableResource>(resource_type);
if (!IsValidResourceType(type)) {
LOG_ERROR(Kernel_SVC, "Invalid resource limit type: '{}'", resource_type);
return ERR_INVALID_ENUM_VALUE;
@@ -2029,7 +2052,7 @@ static ResultCode SetResourceLimitLimitValue(Core::System& system, Handle resour
ASSERT(current_process != nullptr);
auto resource_limit_object =
current_process->GetHandleTable().Get<ResourceLimit>(resource_limit);
current_process->GetHandleTable().Get<KResourceLimit>(resource_limit);
if (!resource_limit_object) {
LOG_ERROR(Kernel_SVC, "Handle to non-existent resource limit instance used. Handle={:08X}",
resource_limit);
@@ -2041,8 +2064,8 @@ static ResultCode SetResourceLimitLimitValue(Core::System& system, Handle resour
LOG_ERROR(
Kernel_SVC,
"Attempted to lower resource limit ({}) for category '{}' below its current value ({})",
resource_limit_object->GetMaxResourceValue(type), resource_type,
resource_limit_object->GetCurrentResourceValue(type));
resource_limit_object->GetLimitValue(type), resource_type,
resource_limit_object->GetCurrentValue(type));
return set_result;
}
+1
View File
@@ -11,6 +11,7 @@ namespace Kernel::Svc {
constexpr ResultCode ResultNoSynchronizationObject{ErrorModule::Kernel, 57};
constexpr ResultCode ResultTerminationRequested{ErrorModule::Kernel, 59};
constexpr ResultCode ResultInvalidAddress{ErrorModule::Kernel, 102};
constexpr ResultCode ResultOutOfResource{ErrorModule::Kernel, 103};
constexpr ResultCode ResultInvalidCurrentMemory{ErrorModule::Kernel, 106};
constexpr ResultCode ResultInvalidPriority{ErrorModule::Kernel, 112};
constexpr ResultCode ResultInvalidCoreId{ErrorModule::Kernel, 113};
-41
View File
@@ -1,41 +0,0 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <algorithm>
#include "common/assert.h"
#include "core/hle/kernel/k_thread.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/object.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/writable_event.h"
namespace Kernel {
WritableEvent::WritableEvent(KernelCore& kernel) : Object{kernel} {}
WritableEvent::~WritableEvent() = default;
EventPair WritableEvent::CreateEventPair(KernelCore& kernel, std::string name) {
std::shared_ptr<WritableEvent> writable_event(new WritableEvent(kernel));
std::shared_ptr<ReadableEvent> readable_event(new ReadableEvent(kernel));
writable_event->name = name + ":Writable";
writable_event->readable = readable_event;
readable_event->name = name + ":Readable";
return {std::move(readable_event), std::move(writable_event)};
}
std::shared_ptr<ReadableEvent> WritableEvent::GetReadableEvent() const {
return readable;
}
void WritableEvent::Signal() {
readable->Signal();
}
void WritableEvent::Clear() {
readable->Clear();
}
} // namespace Kernel
-60
View File
@@ -1,60 +0,0 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <memory>
#include "core/hle/kernel/object.h"
namespace Kernel {
class KernelCore;
class ReadableEvent;
class WritableEvent;
struct EventPair {
std::shared_ptr<ReadableEvent> readable;
std::shared_ptr<WritableEvent> writable;
};
class WritableEvent final : public Object {
public:
~WritableEvent() override;
/**
* Creates an event
* @param kernel The kernel instance to create this event under.
* @param name Optional name of event
*/
static EventPair CreateEventPair(KernelCore& kernel, std::string name = "Unknown");
std::string GetTypeName() const override {
return "WritableEvent";
}
std::string GetName() const override {
return name;
}
static constexpr HandleType HANDLE_TYPE = HandleType::WritableEvent;
HandleType GetHandleType() const override {
return HANDLE_TYPE;
}
std::shared_ptr<ReadableEvent> GetReadableEvent() const;
void Signal();
void Clear();
void Finalize() override {}
private:
explicit WritableEvent(KernelCore& kernel);
std::shared_ptr<ReadableEvent> readable;
std::string name; ///< Name of event (optional)
};
} // namespace Kernel
+8 -2
View File
@@ -41,12 +41,18 @@ constexpr char ACC_SAVE_AVATORS_BASE_PATH[] = "/system/save/8000000000000010/su/
ProfileManager::ProfileManager() {
ParseUserSaveFile();
if (user_count == 0)
// Create an user if none are present
if (user_count == 0) {
CreateNewUser(UUID::Generate(), "yuzu");
}
auto current = std::clamp<int>(Settings::values.current_user, 0, MAX_USERS - 1);
if (UserExistsIndex(current))
// If user index don't exist. Load the first user and change the active user
if (!UserExistsIndex(current)) {
current = 0;
Settings::values.current_user = 0;
}
OpenUser(*GetUser(current));
}
+59 -33
View File
@@ -13,11 +13,12 @@
#include "core/file_sys/registered_cache.h"
#include "core/file_sys/savedata_factory.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/k_event.h"
#include "core/hle/kernel/k_readable_event.h"
#include "core/hle/kernel/k_writable_event.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/transfer_memory.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/service/acc/profile_manager.h"
#include "core/hle/service/am/am.h"
#include "core/hle/service/am/applet_ae.h"
@@ -303,17 +304,18 @@ ISelfController::ISelfController(Core::System& system_, NVFlinger::NVFlinger& nv
RegisterHandlers(functions);
auto& kernel = system.Kernel();
launchable_event =
Kernel::WritableEvent::CreateEventPair(kernel, "ISelfController:LaunchableEvent");
launchable_event = Kernel::KEvent::Create(kernel, "ISelfController:LaunchableEvent");
launchable_event->Initialize();
// This event is created by AM on the first time GetAccumulatedSuspendedTickChangedEvent() is
// called. Yuzu can just create it unconditionally, since it doesn't need to support multiple
// ISelfControllers. The event is signaled on creation, and on transition from suspended -> not
// suspended if the event has previously been created by a call to
// GetAccumulatedSuspendedTickChangedEvent.
accumulated_suspended_tick_changed_event = Kernel::WritableEvent::CreateEventPair(
kernel, "ISelfController:AccumulatedSuspendedTickChangedEvent");
accumulated_suspended_tick_changed_event.writable->Signal();
accumulated_suspended_tick_changed_event =
Kernel::KEvent::Create(kernel, "ISelfController:AccumulatedSuspendedTickChangedEvent");
accumulated_suspended_tick_changed_event->Initialize();
accumulated_suspended_tick_changed_event->GetWritableEvent()->Signal();
}
ISelfController::~ISelfController() = default;
@@ -372,11 +374,11 @@ void ISelfController::LeaveFatalSection(Kernel::HLERequestContext& ctx) {
void ISelfController::GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
launchable_event.writable->Signal();
launchable_event->GetWritableEvent()->Signal();
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(launchable_event.readable);
rb.PushCopyObjects(launchable_event->GetReadableEvent());
}
void ISelfController::SetScreenShotPermission(Kernel::HLERequestContext& ctx) {
@@ -555,41 +557,42 @@ void ISelfController::GetAccumulatedSuspendedTickChangedEvent(Kernel::HLERequest
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(accumulated_suspended_tick_changed_event.readable);
rb.PushCopyObjects(accumulated_suspended_tick_changed_event->GetReadableEvent());
}
AppletMessageQueue::AppletMessageQueue(Kernel::KernelCore& kernel) {
on_new_message =
Kernel::WritableEvent::CreateEventPair(kernel, "AMMessageQueue:OnMessageReceived");
on_new_message = Kernel::KEvent::Create(kernel, "AMMessageQueue:OnMessageReceived");
on_new_message->Initialize();
on_operation_mode_changed =
Kernel::WritableEvent::CreateEventPair(kernel, "AMMessageQueue:OperationModeChanged");
Kernel::KEvent::Create(kernel, "AMMessageQueue:OperationModeChanged");
on_operation_mode_changed->Initialize();
}
AppletMessageQueue::~AppletMessageQueue() = default;
const std::shared_ptr<Kernel::ReadableEvent>& AppletMessageQueue::GetMessageReceiveEvent() const {
return on_new_message.readable;
const std::shared_ptr<Kernel::KReadableEvent>& AppletMessageQueue::GetMessageReceiveEvent() const {
return on_new_message->GetReadableEvent();
}
const std::shared_ptr<Kernel::ReadableEvent>& AppletMessageQueue::GetOperationModeChangedEvent()
const std::shared_ptr<Kernel::KReadableEvent>& AppletMessageQueue::GetOperationModeChangedEvent()
const {
return on_operation_mode_changed.readable;
return on_operation_mode_changed->GetReadableEvent();
}
void AppletMessageQueue::PushMessage(AppletMessage msg) {
messages.push(msg);
on_new_message.writable->Signal();
on_new_message->GetWritableEvent()->Signal();
}
AppletMessageQueue::AppletMessage AppletMessageQueue::PopMessage() {
if (messages.empty()) {
on_new_message.writable->Clear();
on_new_message->GetWritableEvent()->Clear();
return AppletMessage::NoMessage;
}
auto msg = messages.front();
messages.pop();
if (messages.empty()) {
on_new_message.writable->Clear();
on_new_message->GetWritableEvent()->Clear();
}
return msg;
}
@@ -601,7 +604,7 @@ std::size_t AppletMessageQueue::GetMessageCount() const {
void AppletMessageQueue::OperationModeChanged() {
PushMessage(AppletMessage::OperationModeChanged);
PushMessage(AppletMessage::PerformanceModeChanged);
on_operation_mode_changed.writable->Signal();
on_operation_mode_changed->GetWritableEvent()->Signal();
}
void AppletMessageQueue::RequestExit() {
@@ -1192,7 +1195,7 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_)
{40, &IApplicationFunctions::NotifyRunning, "NotifyRunning"},
{50, &IApplicationFunctions::GetPseudoDeviceId, "GetPseudoDeviceId"},
{60, nullptr, "SetMediaPlaybackStateForApplication"},
{65, nullptr, "IsGamePlayRecordingSupported"},
{65, &IApplicationFunctions::IsGamePlayRecordingSupported, "IsGamePlayRecordingSupported"},
{66, &IApplicationFunctions::InitializeGamePlayRecording, "InitializeGamePlayRecording"},
{67, &IApplicationFunctions::SetGamePlayRecordingState, "SetGamePlayRecordingState"},
{68, nullptr, "RequestFlushGamePlayingMovieForDebug"},
@@ -1216,7 +1219,7 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_)
{141, &IApplicationFunctions::TryPopFromFriendInvitationStorageChannel, "TryPopFromFriendInvitationStorageChannel"},
{150, nullptr, "GetNotificationStorageChannelEvent"},
{151, nullptr, "TryPopFromNotificationStorageChannel"},
{160, nullptr, "GetHealthWarningDisappearedSystemEvent"},
{160, &IApplicationFunctions::GetHealthWarningDisappearedSystemEvent, "GetHealthWarningDisappearedSystemEvent"},
{170, nullptr, "SetHdcpAuthenticationActivated"},
{180, nullptr, "GetLaunchRequiredVersion"},
{181, nullptr, "UpgradeLaunchRequiredVersion"},
@@ -1229,11 +1232,15 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_)
RegisterHandlers(functions);
auto& kernel = system.Kernel();
gpu_error_detected_event = Kernel::WritableEvent::CreateEventPair(
kernel, "IApplicationFunctions:GpuErrorDetectedSystemEvent");
friend_invitation_storage_channel_event = Kernel::WritableEvent::CreateEventPair(
kernel, "IApplicationFunctions:FriendInvitationStorageChannelEvent");
gpu_error_detected_event =
Kernel::KEvent::Create(kernel, "IApplicationFunctions:GpuErrorDetectedSystemEvent");
gpu_error_detected_event->Initialize();
friend_invitation_storage_channel_event =
Kernel::KEvent::Create(kernel, "IApplicationFunctions:FriendInvitationStorageChannelEvent");
friend_invitation_storage_channel_event->Initialize();
health_warning_disappeared_system_event =
Kernel::KEvent::Create(kernel, "IApplicationFunctions:HealthWarningDisappearedSystemEvent");
health_warning_disappeared_system_event->Initialize();
}
IApplicationFunctions::~IApplicationFunctions() = default;
@@ -1480,6 +1487,16 @@ void IApplicationFunctions::GetDesiredLanguage(Kernel::HLERequestContext& ctx) {
rb.Push(*res_code);
}
void IApplicationFunctions::IsGamePlayRecordingSupported(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
constexpr bool gameplay_recording_supported = false;
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push(gameplay_recording_supported);
}
void IApplicationFunctions::InitializeGamePlayRecording(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
@@ -1620,7 +1637,7 @@ void IApplicationFunctions::GetGpuErrorDetectedSystemEvent(Kernel::HLERequestCon
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(gpu_error_detected_event.readable);
rb.PushCopyObjects(gpu_error_detected_event->GetReadableEvent());
}
void IApplicationFunctions::GetFriendInvitationStorageChannelEvent(Kernel::HLERequestContext& ctx) {
@@ -1628,7 +1645,7 @@ void IApplicationFunctions::GetFriendInvitationStorageChannelEvent(Kernel::HLERe
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(friend_invitation_storage_channel_event.readable);
rb.PushCopyObjects(friend_invitation_storage_channel_event->GetReadableEvent());
}
void IApplicationFunctions::TryPopFromFriendInvitationStorageChannel(
@@ -1639,6 +1656,14 @@ void IApplicationFunctions::TryPopFromFriendInvitationStorageChannel(
rb.Push(ERR_NO_DATA_IN_CHANNEL);
}
void IApplicationFunctions::GetHealthWarningDisappearedSystemEvent(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(health_warning_disappeared_system_event->GetReadableEvent());
}
void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nvflinger,
Core::System& system) {
auto message_queue = std::make_shared<AppletMessageQueue>(system.Kernel());
@@ -1672,8 +1697,9 @@ IHomeMenuFunctions::IHomeMenuFunctions(Core::System& system_)
RegisterHandlers(functions);
pop_from_general_channel_event = Kernel::WritableEvent::CreateEventPair(
system.Kernel(), "IHomeMenuFunctions:PopFromGeneralChannelEvent");
pop_from_general_channel_event =
Kernel::KEvent::Create(system.Kernel(), "IHomeMenuFunctions:PopFromGeneralChannelEvent");
pop_from_general_channel_event->Initialize();
}
IHomeMenuFunctions::~IHomeMenuFunctions() = default;
@@ -1690,7 +1716,7 @@ void IHomeMenuFunctions::GetPopFromGeneralChannelEvent(Kernel::HLERequestContext
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(pop_from_general_channel_event.readable);
rb.PushCopyObjects(pop_from_general_channel_event->GetReadableEvent());
}
IGlobalStateController::IGlobalStateController(Core::System& system_)
+14 -10
View File
@@ -7,11 +7,12 @@
#include <chrono>
#include <memory>
#include <queue>
#include "core/hle/kernel/writable_event.h"
#include "core/hle/service/service.h"
namespace Kernel {
class KernelCore;
class KEvent;
class TransferMemory;
} // namespace Kernel
@@ -55,8 +56,8 @@ public:
explicit AppletMessageQueue(Kernel::KernelCore& kernel);
~AppletMessageQueue();
const std::shared_ptr<Kernel::ReadableEvent>& GetMessageReceiveEvent() const;
const std::shared_ptr<Kernel::ReadableEvent>& GetOperationModeChangedEvent() const;
const std::shared_ptr<Kernel::KReadableEvent>& GetMessageReceiveEvent() const;
const std::shared_ptr<Kernel::KReadableEvent>& GetOperationModeChangedEvent() const;
void PushMessage(AppletMessage msg);
AppletMessage PopMessage();
std::size_t GetMessageCount() const;
@@ -65,8 +66,8 @@ public:
private:
std::queue<AppletMessage> messages;
Kernel::EventPair on_new_message;
Kernel::EventPair on_operation_mode_changed;
std::shared_ptr<Kernel::KEvent> on_new_message;
std::shared_ptr<Kernel::KEvent> on_operation_mode_changed;
};
class IWindowController final : public ServiceFramework<IWindowController> {
@@ -153,8 +154,8 @@ private:
};
NVFlinger::NVFlinger& nvflinger;
Kernel::EventPair launchable_event;
Kernel::EventPair accumulated_suspended_tick_changed_event;
std::shared_ptr<Kernel::KEvent> launchable_event;
std::shared_ptr<Kernel::KEvent> accumulated_suspended_tick_changed_event;
u32 idle_time_detection_extension = 0;
u64 num_fatal_sections_entered = 0;
@@ -266,6 +267,7 @@ private:
void SetTerminateResult(Kernel::HLERequestContext& ctx);
void GetDisplayVersion(Kernel::HLERequestContext& ctx);
void GetDesiredLanguage(Kernel::HLERequestContext& ctx);
void IsGamePlayRecordingSupported(Kernel::HLERequestContext& ctx);
void InitializeGamePlayRecording(Kernel::HLERequestContext& ctx);
void SetGamePlayRecordingState(Kernel::HLERequestContext& ctx);
void NotifyRunning(Kernel::HLERequestContext& ctx);
@@ -289,12 +291,14 @@ private:
void GetGpuErrorDetectedSystemEvent(Kernel::HLERequestContext& ctx);
void GetFriendInvitationStorageChannelEvent(Kernel::HLERequestContext& ctx);
void TryPopFromFriendInvitationStorageChannel(Kernel::HLERequestContext& ctx);
void GetHealthWarningDisappearedSystemEvent(Kernel::HLERequestContext& ctx);
bool launch_popped_application_specific = false;
bool launch_popped_account_preselect = false;
s32 previous_program_index{-1};
Kernel::EventPair gpu_error_detected_event;
Kernel::EventPair friend_invitation_storage_channel_event;
std::shared_ptr<Kernel::KEvent> gpu_error_detected_event;
std::shared_ptr<Kernel::KEvent> friend_invitation_storage_channel_event;
std::shared_ptr<Kernel::KEvent> health_warning_disappeared_system_event;
};
class IHomeMenuFunctions final : public ServiceFramework<IHomeMenuFunctions> {
@@ -306,7 +310,7 @@ private:
void RequestToGetForeground(Kernel::HLERequestContext& ctx);
void GetPopFromGeneralChannelEvent(Kernel::HLERequestContext& ctx);
Kernel::EventPair pop_from_general_channel_event;
std::shared_ptr<Kernel::KEvent> pop_from_general_channel_event;
};
class IGlobalStateController final : public ServiceFramework<IGlobalStateController> {
+22 -18
View File
@@ -3,6 +3,7 @@
// Refer to the license.txt file included.
#include <cstring>
#include "common/assert.h"
#include "core/core.h"
#include "core/frontend/applets/controller.h"
@@ -11,9 +12,10 @@
#include "core/frontend/applets/profile_select.h"
#include "core/frontend/applets/software_keyboard.h"
#include "core/frontend/applets/web_browser.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/k_event.h"
#include "core/hle/kernel/k_readable_event.h"
#include "core/hle/kernel/k_writable_event.h"
#include "core/hle/kernel/server_session.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/service/am/am.h"
#include "core/hle/service/am/applets/applets.h"
#include "core/hle/service/am/applets/controller.h"
@@ -27,11 +29,13 @@ namespace Service::AM::Applets {
AppletDataBroker::AppletDataBroker(Kernel::KernelCore& kernel) {
state_changed_event =
Kernel::WritableEvent::CreateEventPair(kernel, "ILibraryAppletAccessor:StateChangedEvent");
pop_out_data_event =
Kernel::WritableEvent::CreateEventPair(kernel, "ILibraryAppletAccessor:PopDataOutEvent");
pop_interactive_out_data_event = Kernel::WritableEvent::CreateEventPair(
kernel, "ILibraryAppletAccessor:PopInteractiveDataOutEvent");
Kernel::KEvent::Create(kernel, "ILibraryAppletAccessor:StateChangedEvent");
state_changed_event->Initialize();
pop_out_data_event = Kernel::KEvent::Create(kernel, "ILibraryAppletAccessor:PopDataOutEvent");
pop_out_data_event->Initialize();
pop_interactive_out_data_event =
Kernel::KEvent::Create(kernel, "ILibraryAppletAccessor:PopInteractiveDataOutEvent");
pop_interactive_out_data_event->Initialize();
}
AppletDataBroker::~AppletDataBroker() = default;
@@ -58,7 +62,7 @@ std::shared_ptr<IStorage> AppletDataBroker::PopNormalDataToGame() {
auto out = std::move(out_channel.front());
out_channel.pop_front();
pop_out_data_event.writable->Clear();
pop_out_data_event->GetWritableEvent()->Clear();
return out;
}
@@ -77,7 +81,7 @@ std::shared_ptr<IStorage> AppletDataBroker::PopInteractiveDataToGame() {
auto out = std::move(out_interactive_channel.front());
out_interactive_channel.pop_front();
pop_interactive_out_data_event.writable->Clear();
pop_interactive_out_data_event->GetWritableEvent()->Clear();
return out;
}
@@ -96,7 +100,7 @@ void AppletDataBroker::PushNormalDataFromGame(std::shared_ptr<IStorage>&& storag
void AppletDataBroker::PushNormalDataFromApplet(std::shared_ptr<IStorage>&& storage) {
out_channel.emplace_back(std::move(storage));
pop_out_data_event.writable->Signal();
pop_out_data_event->GetWritableEvent()->Signal();
}
void AppletDataBroker::PushInteractiveDataFromGame(std::shared_ptr<IStorage>&& storage) {
@@ -105,23 +109,23 @@ void AppletDataBroker::PushInteractiveDataFromGame(std::shared_ptr<IStorage>&& s
void AppletDataBroker::PushInteractiveDataFromApplet(std::shared_ptr<IStorage>&& storage) {
out_interactive_channel.emplace_back(std::move(storage));
pop_interactive_out_data_event.writable->Signal();
pop_interactive_out_data_event->GetWritableEvent()->Signal();
}
void AppletDataBroker::SignalStateChanged() const {
state_changed_event.writable->Signal();
state_changed_event->GetWritableEvent()->Signal();
}
std::shared_ptr<Kernel::ReadableEvent> AppletDataBroker::GetNormalDataEvent() const {
return pop_out_data_event.readable;
std::shared_ptr<Kernel::KReadableEvent> AppletDataBroker::GetNormalDataEvent() const {
return pop_out_data_event->GetReadableEvent();
}
std::shared_ptr<Kernel::ReadableEvent> AppletDataBroker::GetInteractiveDataEvent() const {
return pop_interactive_out_data_event.readable;
std::shared_ptr<Kernel::KReadableEvent> AppletDataBroker::GetInteractiveDataEvent() const {
return pop_interactive_out_data_event->GetReadableEvent();
}
std::shared_ptr<Kernel::ReadableEvent> AppletDataBroker::GetStateChangedEvent() const {
return state_changed_event.readable;
std::shared_ptr<Kernel::KReadableEvent> AppletDataBroker::GetStateChangedEvent() const {
return state_changed_event->GetReadableEvent();
}
Applet::Applet(Kernel::KernelCore& kernel_) : broker{kernel_} {}
+10 -8
View File
@@ -6,9 +6,9 @@
#include <memory>
#include <queue>
#include "common/swap.h"
#include "core/hle/kernel/object.h"
#include "core/hle/kernel/writable_event.h"
union ResultCode;
@@ -29,7 +29,9 @@ class WebBrowserApplet;
namespace Kernel {
class KernelCore;
}
class KEvent;
class KReadableEvent;
} // namespace Kernel
namespace Service::AM {
@@ -87,9 +89,9 @@ public:
void SignalStateChanged() const;
std::shared_ptr<Kernel::ReadableEvent> GetNormalDataEvent() const;
std::shared_ptr<Kernel::ReadableEvent> GetInteractiveDataEvent() const;
std::shared_ptr<Kernel::ReadableEvent> GetStateChangedEvent() const;
std::shared_ptr<Kernel::KReadableEvent> GetNormalDataEvent() const;
std::shared_ptr<Kernel::KReadableEvent> GetInteractiveDataEvent() const;
std::shared_ptr<Kernel::KReadableEvent> GetStateChangedEvent() const;
private:
// Queues are named from applet's perspective
@@ -106,13 +108,13 @@ private:
// PopInteractiveDataToGame and PushInteractiveDataFromApplet
std::deque<std::shared_ptr<IStorage>> out_interactive_channel;
Kernel::EventPair state_changed_event;
std::shared_ptr<Kernel::KEvent> state_changed_event;
// Signaled on PushNormalDataFromApplet
Kernel::EventPair pop_out_data_event;
std::shared_ptr<Kernel::KEvent> pop_out_data_event;
// Signaled on PushInteractiveDataFromApplet
Kernel::EventPair pop_interactive_out_data_event;
std::shared_ptr<Kernel::KEvent> pop_interactive_out_data_event;
};
class Applet {
@@ -37,7 +37,7 @@ static Core::Frontend::ControllerParameters ConvertToFrontendParameters(
.border_colors = std::move(identification_colors),
.enable_explain_text = enable_text,
.explain_text = std::move(text),
.allow_pro_controller = npad_style_set.pro_controller == 1,
.allow_pro_controller = npad_style_set.fullkey == 1,
.allow_handheld = npad_style_set.handheld == 1,
.allow_dual_joycons = npad_style_set.joycon_dual == 1,
.allow_left_joycon = npad_style_set.joycon_left == 1,
+11 -9
View File
@@ -5,6 +5,7 @@
#include <algorithm>
#include <numeric>
#include <vector>
#include "common/logging/log.h"
#include "core/core.h"
#include "core/file_sys/common_funcs.h"
@@ -14,10 +15,10 @@
#include "core/file_sys/patch_manager.h"
#include "core/file_sys/registered_cache.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/k_event.h"
#include "core/hle/kernel/k_readable_event.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/service/aoc/aoc_u.h"
#include "core/loader/loader.h"
#include "core/settings.h"
@@ -62,8 +63,9 @@ public:
RegisterHandlers(functions);
purchased_event = Kernel::WritableEvent::CreateEventPair(
system.Kernel(), "IPurchaseEventManager:PurchasedEvent");
purchased_event =
Kernel::KEvent::Create(system.Kernel(), "IPurchaseEventManager:PurchasedEvent");
purchased_event->Initialize();
}
private:
@@ -96,10 +98,10 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(purchased_event.readable);
rb.PushCopyObjects(purchased_event->GetReadableEvent());
}
Kernel::EventPair purchased_event;
std::shared_ptr<Kernel::KEvent> purchased_event;
};
AOC_U::AOC_U(Core::System& system_)
@@ -124,8 +126,8 @@ AOC_U::AOC_U(Core::System& system_)
RegisterHandlers(functions);
auto& kernel = system.Kernel();
aoc_change_event =
Kernel::WritableEvent::CreateEventPair(kernel, "GetAddOnContentListChanged:Event");
aoc_change_event = Kernel::KEvent::Create(kernel, "GetAddOnContentListChanged:Event");
aoc_change_event->Initialize();
}
AOC_U::~AOC_U() = default;
@@ -252,7 +254,7 @@ void AOC_U::GetAddOnContentListChangedEvent(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(aoc_change_event.readable);
rb.PushCopyObjects(aoc_change_event->GetReadableEvent());
}
void AOC_U::CreateEcPurchasedEventManager(Kernel::HLERequestContext& ctx) {
+2 -2
View File
@@ -11,7 +11,7 @@ class System;
}
namespace Kernel {
class WritableEvent;
class KEvent;
}
namespace Service::AOC {
@@ -31,7 +31,7 @@ private:
void CreatePermanentEcPurchasedEventManager(Kernel::HLERequestContext& ctx);
std::vector<u64> add_on_content;
Kernel::EventPair aoc_change_event;
std::shared_ptr<Kernel::KEvent> aoc_change_event;
};
/// Registers all AOC services with the specified service manager.
+8 -7
View File
@@ -14,9 +14,10 @@
#include "core/core.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/hle_ipc.h"
#include "core/hle/kernel/k_event.h"
#include "core/hle/kernel/k_readable_event.h"
#include "core/hle/kernel/k_writable_event.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/service/audio/audout_u.h"
#include "core/hle/service/audio/errors.h"
#include "core/memory.h"
@@ -66,13 +67,13 @@ public:
RegisterHandlers(functions);
// This is the event handle used to check if the audio buffer was released
buffer_event =
Kernel::WritableEvent::CreateEventPair(system.Kernel(), "IAudioOutBufferReleased");
buffer_event = Kernel::KEvent::Create(system.Kernel(), "IAudioOutBufferReleased");
buffer_event->Initialize();
stream = audio_core.OpenStream(system.CoreTiming(), audio_params.sample_rate,
audio_params.channel_count, std::move(unique_name), [this] {
const auto guard = LockService();
buffer_event.writable->Signal();
buffer_event->GetWritableEvent()->Signal();
});
}
@@ -125,7 +126,7 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(buffer_event.readable);
rb.PushCopyObjects(buffer_event->GetReadableEvent());
}
void AppendAudioOutBufferImpl(Kernel::HLERequestContext& ctx) {
@@ -219,7 +220,7 @@ private:
[[maybe_unused]] AudoutParams audio_params{};
/// This is the event handle used to check if the audio buffer was released
Kernel::EventPair buffer_event;
std::shared_ptr<Kernel::KEvent> buffer_event;
Core::Memory::Memory& main_memory;
};
+23 -20
View File
@@ -16,9 +16,10 @@
#include "core/core.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/hle_ipc.h"
#include "core/hle/kernel/k_event.h"
#include "core/hle/kernel/k_readable_event.h"
#include "core/hle/kernel/k_writable_event.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/service/audio/audren_u.h"
#include "core/hle/service/audio/errors.h"
@@ -47,13 +48,13 @@ public:
// clang-format on
RegisterHandlers(functions);
system_event =
Kernel::WritableEvent::CreateEventPair(system.Kernel(), "IAudioRenderer:SystemEvent");
system_event = Kernel::KEvent::Create(system.Kernel(), "IAudioRenderer:SystemEvent");
system_event->Initialize();
renderer = std::make_unique<AudioCore::AudioRenderer>(
system.CoreTiming(), system.Memory(), audren_params,
[this]() {
const auto guard = LockService();
system_event.writable->Signal();
system_event->GetWritableEvent()->Signal();
},
instance_number);
}
@@ -126,7 +127,7 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(system_event.readable);
rb.PushCopyObjects(system_event->GetReadableEvent());
}
void SetRenderingTimeLimit(Kernel::HLERequestContext& ctx) {
@@ -160,7 +161,7 @@ private:
rb.Push(ERR_NOT_SUPPORTED);
}
Kernel::EventPair system_event;
std::shared_ptr<Kernel::KEvent> system_event;
std::unique_ptr<AudioCore::AudioRenderer> renderer;
u32 rendering_time_limit_percent = 100;
};
@@ -187,17 +188,19 @@ public:
RegisterHandlers(functions);
auto& kernel = system.Kernel();
buffer_event =
Kernel::WritableEvent::CreateEventPair(kernel, "IAudioOutBufferReleasedEvent");
buffer_event = Kernel::KEvent::Create(kernel, "IAudioOutBufferReleasedEvent");
buffer_event->Initialize();
// Should be similar to audio_output_device_switch_event
audio_input_device_switch_event = Kernel::WritableEvent::CreateEventPair(
kernel, "IAudioDevice:AudioInputDeviceSwitchedEvent");
audio_input_device_switch_event =
Kernel::KEvent::Create(kernel, "IAudioDevice:AudioInputDeviceSwitchedEvent");
audio_input_device_switch_event->Initialize();
// Should only be signalled when an audio output device has been changed, example: speaker
// to headset
audio_output_device_switch_event = Kernel::WritableEvent::CreateEventPair(
kernel, "IAudioDevice:AudioOutputDeviceSwitchedEvent");
audio_output_device_switch_event =
Kernel::KEvent::Create(kernel, "IAudioDevice:AudioOutputDeviceSwitchedEvent");
audio_output_device_switch_event->Initialize();
}
private:
@@ -286,11 +289,11 @@ private:
void QueryAudioDeviceSystemEvent(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Audio, "(STUBBED) called");
buffer_event.writable->Signal();
buffer_event->GetWritableEvent()->Signal();
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(buffer_event.readable);
rb.PushCopyObjects(buffer_event->GetReadableEvent());
}
void GetActiveChannelCount(Kernel::HLERequestContext& ctx) {
@@ -307,7 +310,7 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(audio_input_device_switch_event.readable);
rb.PushCopyObjects(audio_input_device_switch_event->GetReadableEvent());
}
void QueryAudioDeviceOutputEvent(Kernel::HLERequestContext& ctx) {
@@ -315,13 +318,13 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(audio_output_device_switch_event.readable);
rb.PushCopyObjects(audio_output_device_switch_event->GetReadableEvent());
}
u32_le revision = 0;
Kernel::EventPair buffer_event;
Kernel::EventPair audio_input_device_switch_event;
Kernel::EventPair audio_output_device_switch_event;
std::shared_ptr<Kernel::KEvent> buffer_event;
std::shared_ptr<Kernel::KEvent> audio_input_device_switch_event;
std::shared_ptr<Kernel::KEvent> audio_output_device_switch_event;
}; // namespace Audio
+10 -6
View File
@@ -5,6 +5,9 @@
#include "common/hex_util.h"
#include "common/logging/log.h"
#include "core/core.h"
#include "core/hle/kernel/k_event.h"
#include "core/hle/kernel/k_readable_event.h"
#include "core/hle/kernel/k_writable_event.h"
#include "core/hle/lock.h"
#include "core/hle/service/bcat/backend/backend.h"
@@ -12,12 +15,13 @@ namespace Service::BCAT {
ProgressServiceBackend::ProgressServiceBackend(Kernel::KernelCore& kernel,
std::string_view event_name) {
event = Kernel::WritableEvent::CreateEventPair(
kernel, std::string("ProgressServiceBackend:UpdateEvent:").append(event_name));
event = Kernel::KEvent::Create(kernel,
"ProgressServiceBackend:UpdateEvent:" + std::string(event_name));
event->Initialize();
}
std::shared_ptr<Kernel::ReadableEvent> ProgressServiceBackend::GetEvent() const {
return event.readable;
std::shared_ptr<Kernel::KReadableEvent> ProgressServiceBackend::GetEvent() const {
return event->GetReadableEvent();
}
DeliveryCacheProgressImpl& ProgressServiceBackend::GetImpl() {
@@ -85,9 +89,9 @@ void ProgressServiceBackend::FinishDownload(ResultCode result) {
void ProgressServiceBackend::SignalUpdate() const {
if (need_hle_lock) {
std::lock_guard lock(HLE::g_hle_lock);
event.writable->Signal();
event->GetWritableEvent()->Signal();
} else {
event.writable->Signal();
event->GetWritableEvent()->Signal();
}
}
+5 -5
View File
@@ -11,8 +11,6 @@
#include "common/common_types.h"
#include "core/file_sys/vfs_types.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/result.h"
namespace Core {
@@ -21,7 +19,9 @@ class System;
namespace Kernel {
class KernelCore;
}
class KEvent;
class KReadableEvent;
} // namespace Kernel
namespace Service::BCAT {
@@ -98,13 +98,13 @@ public:
private:
explicit ProgressServiceBackend(Kernel::KernelCore& kernel, std::string_view event_name);
std::shared_ptr<Kernel::ReadableEvent> GetEvent() const;
std::shared_ptr<Kernel::KReadableEvent> GetEvent() const;
DeliveryCacheProgressImpl& GetImpl();
void SignalUpdate() const;
DeliveryCacheProgressImpl impl{};
Kernel::EventPair event;
std::shared_ptr<Kernel::KEvent> event;
bool need_hle_lock = false;
};
+4 -4
View File
@@ -11,9 +11,9 @@
#include "core/core.h"
#include "core/file_sys/vfs.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/k_readable_event.h"
#include "core/hle/kernel/k_writable_event.h"
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/service/bcat/backend/backend.h"
#include "core/hle/service/bcat/bcat.h"
#include "core/hle/service/bcat/module.h"
@@ -89,7 +89,7 @@ struct DeliveryCacheDirectoryEntry {
class IDeliveryCacheProgressService final : public ServiceFramework<IDeliveryCacheProgressService> {
public:
explicit IDeliveryCacheProgressService(Core::System& system_,
std::shared_ptr<Kernel::ReadableEvent> event_,
std::shared_ptr<Kernel::KReadableEvent> event_,
const DeliveryCacheProgressImpl& impl_)
: ServiceFramework{system_, "IDeliveryCacheProgressService"}, event{std::move(event_)},
impl{impl_} {
@@ -121,7 +121,7 @@ private:
rb.Push(RESULT_SUCCESS);
}
std::shared_ptr<Kernel::ReadableEvent> event;
std::shared_ptr<Kernel::KReadableEvent> event;
const DeliveryCacheProgressImpl& impl;
};
+6 -5
View File
@@ -6,9 +6,9 @@
#include "core/core.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/hle_ipc.h"
#include "core/hle/kernel/k_event.h"
#include "core/hle/kernel/k_readable_event.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/service/btdrv/btdrv.h"
#include "core/hle/service/service.h"
#include "core/hle/service/sm/sm.h"
@@ -35,7 +35,8 @@ public:
RegisterHandlers(functions);
auto& kernel = system.Kernel();
register_event = Kernel::WritableEvent::CreateEventPair(kernel, "BT:RegisterEvent");
register_event = Kernel::KEvent::Create(kernel, "BT:RegisterEvent");
register_event->Initialize();
}
private:
@@ -44,10 +45,10 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(register_event.readable);
rb.PushCopyObjects(register_event->GetReadableEvent());
}
Kernel::EventPair register_event;
std::shared_ptr<Kernel::KEvent> register_event;
};
class BtDrv final : public ServiceFramework<BtDrv> {
+18 -16
View File
@@ -8,9 +8,9 @@
#include "core/core.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/hle_ipc.h"
#include "core/hle/kernel/k_event.h"
#include "core/hle/kernel/k_readable_event.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/service/btm/btm.h"
#include "core/hle/service/service.h"
@@ -58,12 +58,14 @@ public:
RegisterHandlers(functions);
auto& kernel = system.Kernel();
scan_event = Kernel::WritableEvent::CreateEventPair(kernel, "IBtmUserCore:ScanEvent");
connection_event =
Kernel::WritableEvent::CreateEventPair(kernel, "IBtmUserCore:ConnectionEvent");
service_discovery =
Kernel::WritableEvent::CreateEventPair(kernel, "IBtmUserCore:Discovery");
config_event = Kernel::WritableEvent::CreateEventPair(kernel, "IBtmUserCore:ConfigEvent");
scan_event = Kernel::KEvent::Create(kernel, "IBtmUserCore:ScanEvent");
scan_event->Initialize();
connection_event = Kernel::KEvent::Create(kernel, "IBtmUserCore:ConnectionEvent");
connection_event->Initialize();
service_discovery = Kernel::KEvent::Create(kernel, "IBtmUserCore:Discovery");
service_discovery->Initialize();
config_event = Kernel::KEvent::Create(kernel, "IBtmUserCore:ConfigEvent");
config_event->Initialize();
}
private:
@@ -72,7 +74,7 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(scan_event.readable);
rb.PushCopyObjects(scan_event->GetReadableEvent());
}
void AcquireBleConnectionEvent(Kernel::HLERequestContext& ctx) {
@@ -80,7 +82,7 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(connection_event.readable);
rb.PushCopyObjects(connection_event->GetReadableEvent());
}
void AcquireBleServiceDiscoveryEvent(Kernel::HLERequestContext& ctx) {
@@ -88,7 +90,7 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(service_discovery.readable);
rb.PushCopyObjects(service_discovery->GetReadableEvent());
}
void AcquireBleMtuConfigEvent(Kernel::HLERequestContext& ctx) {
@@ -96,13 +98,13 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(config_event.readable);
rb.PushCopyObjects(config_event->GetReadableEvent());
}
Kernel::EventPair scan_event;
Kernel::EventPair connection_event;
Kernel::EventPair service_discovery;
Kernel::EventPair config_event;
std::shared_ptr<Kernel::KEvent> scan_event;
std::shared_ptr<Kernel::KEvent> connection_event;
std::shared_ptr<Kernel::KEvent> service_discovery;
std::shared_ptr<Kernel::KEvent> config_event;
};
class BTM_USR final : public ServiceFramework<BTM_USR> {
+8 -6
View File
@@ -7,8 +7,9 @@
#include "common/uuid.h"
#include "core/core.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/kernel/k_event.h"
#include "core/hle/kernel/k_readable_event.h"
#include "core/hle/kernel/k_writable_event.h"
#include "core/hle/service/friend/errors.h"
#include "core/hle/service/friend/friend.h"
#include "core/hle/service/friend/interface.h"
@@ -183,8 +184,9 @@ public:
RegisterHandlers(functions);
notification_event = Kernel::WritableEvent::CreateEventPair(
system.Kernel(), "INotificationService:NotifyEvent");
notification_event =
Kernel::KEvent::Create(system.Kernel(), "INotificationService:NotifyEvent");
notification_event->Initialize();
}
private:
@@ -193,7 +195,7 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(notification_event.readable);
rb.PushCopyObjects(notification_event->GetReadableEvent());
}
void Clear(Kernel::HLERequestContext& ctx) {
@@ -258,7 +260,7 @@ private:
};
Common::UUID uuid{Common::INVALID_UUID};
Kernel::EventPair notification_event;
std::shared_ptr<Kernel::KEvent> notification_event;
std::queue<SizedNotificationInfo> notifications;
States states{};
};
@@ -39,16 +39,25 @@ void Controller_Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing,
cur_entry.sampling_number2 = cur_entry.sampling_number;
cur_entry.key.fill(0);
cur_entry.modifier = 0;
if (Settings::values.keyboard_enabled) {
for (std::size_t i = 0; i < keyboard_keys.size(); ++i) {
auto& entry = cur_entry.key[i / KEYS_PER_BYTE];
entry = static_cast<u8>(entry | (keyboard_keys[i]->GetStatus() << (i % KEYS_PER_BYTE)));
}
for (std::size_t i = 0; i < keyboard_mods.size(); ++i) {
cur_entry.modifier |= (keyboard_mods[i]->GetStatus() << i);
}
using namespace Settings::NativeKeyboard;
// TODO: Assign the correct key to all modifiers
cur_entry.modifier.control.Assign(keyboard_mods[LeftControl]->GetStatus());
cur_entry.modifier.shift.Assign(keyboard_mods[LeftShift]->GetStatus());
cur_entry.modifier.left_alt.Assign(keyboard_mods[LeftAlt]->GetStatus());
cur_entry.modifier.right_alt.Assign(keyboard_mods[RightAlt]->GetStatus());
cur_entry.modifier.gui.Assign(0);
cur_entry.modifier.caps_lock.Assign(keyboard_mods[CapsLock]->GetStatus());
cur_entry.modifier.scroll_lock.Assign(keyboard_mods[ScrollLock]->GetStatus());
cur_entry.modifier.num_lock.Assign(keyboard_mods[NumLock]->GetStatus());
cur_entry.modifier.katakana.Assign(0);
cur_entry.modifier.hiragana.Assign(0);
}
std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(SharedMemory));
}
@@ -5,6 +5,7 @@
#pragma once
#include <array>
#include "common/bit_field.h"
#include "common/common_funcs.h"
#include "common/common_types.h"
#include "common/swap.h"
@@ -31,12 +32,28 @@ public:
void OnLoadInputDevices() override;
private:
struct Modifiers {
union {
u32_le raw{};
BitField<0, 1, u32> control;
BitField<1, 1, u32> shift;
BitField<2, 1, u32> left_alt;
BitField<3, 1, u32> right_alt;
BitField<4, 1, u32> gui;
BitField<8, 1, u32> caps_lock;
BitField<9, 1, u32> scroll_lock;
BitField<10, 1, u32> num_lock;
BitField<11, 1, u32> katakana;
BitField<12, 1, u32> hiragana;
};
};
static_assert(sizeof(Modifiers) == 0x4, "Modifiers is an invalid size");
struct KeyboardState {
s64_le sampling_number;
s64_le sampling_number2;
s32_le modifier;
s32_le attribute;
Modifiers modifier;
std::array<u8, 32> key;
};
static_assert(sizeof(KeyboardState) == 0x38, "KeyboardState is an invalid size");
@@ -36,6 +36,7 @@ void Controller_Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
cur_entry.sampling_number = last_entry.sampling_number + 1;
cur_entry.sampling_number2 = cur_entry.sampling_number;
cur_entry.attribute.raw = 0;
if (Settings::values.mouse_enabled) {
const auto [px, py, sx, sy] = mouse_device->GetStatus();
const auto x = static_cast<s32>(px * Layout::ScreenUndocked::Width);
@@ -46,10 +47,14 @@ void Controller_Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
cur_entry.delta_y = y - last_entry.y;
cur_entry.mouse_wheel_x = sx;
cur_entry.mouse_wheel_y = sy;
cur_entry.attribute.is_connected.Assign(1);
for (std::size_t i = 0; i < mouse_button_devices.size(); ++i) {
cur_entry.button |= (mouse_button_devices[i]->GetStatus() << i);
}
using namespace Settings::NativeMouseButton;
cur_entry.button.left.Assign(mouse_button_devices[Left]->GetStatus());
cur_entry.button.right.Assign(mouse_button_devices[Right]->GetStatus());
cur_entry.button.middle.Assign(mouse_button_devices[Middle]->GetStatus());
cur_entry.button.forward.Assign(mouse_button_devices[Forward]->GetStatus());
cur_entry.button.back.Assign(mouse_button_devices[Back]->GetStatus());
}
std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(SharedMemory));
+24 -2
View File
@@ -5,6 +5,7 @@
#pragma once
#include <array>
#include "common/bit_field.h"
#include "common/common_types.h"
#include "common/swap.h"
#include "core/frontend/input.h"
@@ -30,6 +31,27 @@ public:
void OnLoadInputDevices() override;
private:
struct Buttons {
union {
u32_le raw{};
BitField<0, 1, u32> left;
BitField<1, 1, u32> right;
BitField<2, 1, u32> middle;
BitField<3, 1, u32> forward;
BitField<4, 1, u32> back;
};
};
static_assert(sizeof(Buttons) == 0x4, "Buttons is an invalid size");
struct Attributes {
union {
u32_le raw{};
BitField<0, 1, u32> transferable;
BitField<1, 1, u32> is_connected;
};
};
static_assert(sizeof(Attributes) == 0x4, "Attributes is an invalid size");
struct MouseState {
s64_le sampling_number;
s64_le sampling_number2;
@@ -39,8 +61,8 @@ private:
s32_le delta_y;
s32_le mouse_wheel_x;
s32_le mouse_wheel_y;
s32_le button;
s32_le attribute;
Buttons button;
Attributes attribute;
};
static_assert(sizeof(MouseState) == 0x30, "MouseState is an invalid size");
+127 -100
View File
@@ -12,9 +12,10 @@
#include "core/core.h"
#include "core/core_timing.h"
#include "core/frontend/input.h"
#include "core/hle/kernel/k_event.h"
#include "core/hle/kernel/k_readable_event.h"
#include "core/hle/kernel/k_writable_event.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/service/hid/controllers/npad.h"
#include "core/settings.h"
@@ -153,79 +154,86 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
const auto controller_type = connected_controllers[controller_idx].type;
auto& controller = shared_memory_entries[controller_idx];
if (controller_type == NPadControllerType::None) {
styleset_changed_events[controller_idx].writable->Signal();
styleset_changed_events[controller_idx]->GetWritableEvent()->Signal();
return;
}
controller.joy_styles.raw = 0; // Zero out
controller.style_set.raw = 0; // Zero out
controller.device_type.raw = 0;
controller.properties.raw = 0;
controller.system_properties.raw = 0;
switch (controller_type) {
case NPadControllerType::None:
UNREACHABLE();
break;
case NPadControllerType::ProController:
controller.joy_styles.pro_controller.Assign(1);
controller.device_type.pro_controller.Assign(1);
controller.properties.is_vertical.Assign(1);
controller.properties.use_plus.Assign(1);
controller.properties.use_minus.Assign(1);
controller.pad_assignment = NpadAssignments::Single;
controller.style_set.fullkey.Assign(1);
controller.device_type.fullkey.Assign(1);
controller.system_properties.is_vertical.Assign(1);
controller.system_properties.use_plus.Assign(1);
controller.system_properties.use_minus.Assign(1);
controller.assignment_mode = NpadAssignments::Single;
controller.footer_type = AppletFooterUiType::SwitchProController;
break;
case NPadControllerType::Handheld:
controller.joy_styles.handheld.Assign(1);
controller.device_type.handheld.Assign(1);
controller.properties.is_vertical.Assign(1);
controller.properties.use_plus.Assign(1);
controller.properties.use_minus.Assign(1);
controller.pad_assignment = NpadAssignments::Dual;
controller.style_set.handheld.Assign(1);
controller.device_type.handheld_left.Assign(1);
controller.device_type.handheld_right.Assign(1);
controller.system_properties.is_vertical.Assign(1);
controller.system_properties.use_plus.Assign(1);
controller.system_properties.use_minus.Assign(1);
controller.assignment_mode = NpadAssignments::Dual;
controller.footer_type = AppletFooterUiType::HandheldJoyConLeftJoyConRight;
break;
case NPadControllerType::JoyDual:
controller.joy_styles.joycon_dual.Assign(1);
controller.style_set.joycon_dual.Assign(1);
controller.device_type.joycon_left.Assign(1);
controller.device_type.joycon_right.Assign(1);
controller.properties.is_vertical.Assign(1);
controller.properties.use_plus.Assign(1);
controller.properties.use_minus.Assign(1);
controller.pad_assignment = NpadAssignments::Dual;
controller.system_properties.is_vertical.Assign(1);
controller.system_properties.use_plus.Assign(1);
controller.system_properties.use_minus.Assign(1);
controller.assignment_mode = NpadAssignments::Dual;
controller.footer_type = AppletFooterUiType::JoyDual;
break;
case NPadControllerType::JoyLeft:
controller.joy_styles.joycon_left.Assign(1);
controller.style_set.joycon_left.Assign(1);
controller.device_type.joycon_left.Assign(1);
controller.properties.is_horizontal.Assign(1);
controller.properties.use_minus.Assign(1);
controller.pad_assignment = NpadAssignments::Single;
controller.system_properties.is_horizontal.Assign(1);
controller.system_properties.use_minus.Assign(1);
controller.assignment_mode = NpadAssignments::Single;
controller.footer_type = AppletFooterUiType::JoyLeftHorizontal;
break;
case NPadControllerType::JoyRight:
controller.joy_styles.joycon_right.Assign(1);
controller.style_set.joycon_right.Assign(1);
controller.device_type.joycon_right.Assign(1);
controller.properties.is_horizontal.Assign(1);
controller.properties.use_plus.Assign(1);
controller.pad_assignment = NpadAssignments::Single;
controller.system_properties.is_horizontal.Assign(1);
controller.system_properties.use_plus.Assign(1);
controller.assignment_mode = NpadAssignments::Single;
controller.footer_type = AppletFooterUiType::JoyRightHorizontal;
break;
case NPadControllerType::Pokeball:
controller.joy_styles.pokeball.Assign(1);
controller.device_type.pokeball.Assign(1);
controller.pad_assignment = NpadAssignments::Single;
controller.style_set.palma.Assign(1);
controller.device_type.palma.Assign(1);
controller.assignment_mode = NpadAssignments::Single;
break;
}
controller.single_color_error = ColorReadError::ReadOk;
controller.single_color.body_color = 0;
controller.single_color.button_color = 0;
controller.fullkey_color.attribute = ColorAttributes::Ok;
controller.fullkey_color.fullkey.body = 0;
controller.fullkey_color.fullkey.button = 0;
controller.dual_color_error = ColorReadError::ReadOk;
controller.left_color.body_color =
controller.joycon_color.attribute = ColorAttributes::Ok;
controller.joycon_color.left.body =
Settings::values.players.GetValue()[controller_idx].body_color_left;
controller.left_color.button_color =
controller.joycon_color.left.button =
Settings::values.players.GetValue()[controller_idx].button_color_left;
controller.right_color.body_color =
controller.joycon_color.right.body =
Settings::values.players.GetValue()[controller_idx].body_color_right;
controller.right_color.button_color =
controller.joycon_color.right.button =
Settings::values.players.GetValue()[controller_idx].button_color_right;
controller.battery_level[0] = BATTERY_FULL;
controller.battery_level[1] = BATTERY_FULL;
controller.battery_level[2] = BATTERY_FULL;
// TODO: Investigate when we should report all batery types
controller.battery_level_dual = BATTERY_FULL;
controller.battery_level_left = BATTERY_FULL;
controller.battery_level_right = BATTERY_FULL;
SignalStyleSetChangedEvent(IndexToNPad(controller_idx));
}
@@ -233,8 +241,9 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
void Controller_NPad::OnInit() {
auto& kernel = system.Kernel();
for (std::size_t i = 0; i < styleset_changed_events.size(); ++i) {
styleset_changed_events[i] = Kernel::WritableEvent::CreateEventPair(
kernel, fmt::format("npad:NpadStyleSetChanged_{}", i));
styleset_changed_events[i] =
Kernel::KEvent::Create(kernel, fmt::format("npad:NpadStyleSetChanged_{}", i));
styleset_changed_events[i]->Initialize();
}
if (!IsControllerActivated()) {
@@ -249,8 +258,8 @@ void Controller_NPad::OnInit() {
style.joycon_left.Assign(1);
style.joycon_right.Assign(1);
style.joycon_dual.Assign(1);
style.pro_controller.Assign(1);
style.pokeball.Assign(1);
style.fullkey.Assign(1);
style.palma.Assign(1);
}
std::transform(Settings::values.players.GetValue().begin(),
@@ -404,13 +413,10 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
}
for (std::size_t i = 0; i < shared_memory_entries.size(); ++i) {
auto& npad = shared_memory_entries[i];
const std::array<NPadGeneric*, 7> controller_npads{&npad.main_controller_states,
&npad.handheld_states,
&npad.dual_states,
&npad.left_joy_states,
&npad.right_joy_states,
&npad.pokeball_states,
&npad.libnx};
const std::array<NPadGeneric*, 7> controller_npads{
&npad.fullkey_states, &npad.handheld_states, &npad.joy_dual_states,
&npad.joy_left_states, &npad.joy_right_states, &npad.palma_states,
&npad.system_ext_states};
for (auto* main_controller : controller_npads) {
main_controller->common.entry_count = 16;
@@ -440,19 +446,19 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
auto& pad_state = npad_pad_states[npad_index];
auto& main_controller =
npad.main_controller_states.npad[npad.main_controller_states.common.last_entry_index];
npad.fullkey_states.npad[npad.fullkey_states.common.last_entry_index];
auto& handheld_entry =
npad.handheld_states.npad[npad.handheld_states.common.last_entry_index];
auto& dual_entry = npad.dual_states.npad[npad.dual_states.common.last_entry_index];
auto& left_entry = npad.left_joy_states.npad[npad.left_joy_states.common.last_entry_index];
auto& dual_entry = npad.joy_dual_states.npad[npad.joy_dual_states.common.last_entry_index];
auto& left_entry = npad.joy_left_states.npad[npad.joy_left_states.common.last_entry_index];
auto& right_entry =
npad.right_joy_states.npad[npad.right_joy_states.common.last_entry_index];
auto& pokeball_entry =
npad.pokeball_states.npad[npad.pokeball_states.common.last_entry_index];
auto& libnx_entry = npad.libnx.npad[npad.libnx.common.last_entry_index];
npad.joy_right_states.npad[npad.joy_right_states.common.last_entry_index];
auto& pokeball_entry = npad.palma_states.npad[npad.palma_states.common.last_entry_index];
auto& libnx_entry =
npad.system_ext_states.npad[npad.system_ext_states.common.last_entry_index];
libnx_entry.connection_status.raw = 0;
libnx_entry.connection_status.IsConnected.Assign(1);
libnx_entry.connection_status.is_connected.Assign(1);
switch (controller_type) {
case NPadControllerType::None:
@@ -460,67 +466,67 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
break;
case NPadControllerType::ProController:
main_controller.connection_status.raw = 0;
main_controller.connection_status.IsConnected.Assign(1);
main_controller.connection_status.IsWired.Assign(1);
main_controller.connection_status.is_connected.Assign(1);
main_controller.connection_status.is_wired.Assign(1);
main_controller.pad.pad_states.raw = pad_state.pad_states.raw;
main_controller.pad.l_stick = pad_state.l_stick;
main_controller.pad.r_stick = pad_state.r_stick;
libnx_entry.connection_status.IsWired.Assign(1);
libnx_entry.connection_status.is_wired.Assign(1);
break;
case NPadControllerType::Handheld:
handheld_entry.connection_status.raw = 0;
handheld_entry.connection_status.IsConnected.Assign(1);
handheld_entry.connection_status.IsWired.Assign(1);
handheld_entry.connection_status.IsLeftJoyConnected.Assign(1);
handheld_entry.connection_status.IsRightJoyConnected.Assign(1);
handheld_entry.connection_status.IsLeftJoyWired.Assign(1);
handheld_entry.connection_status.IsRightJoyWired.Assign(1);
handheld_entry.connection_status.is_connected.Assign(1);
handheld_entry.connection_status.is_wired.Assign(1);
handheld_entry.connection_status.is_left_connected.Assign(1);
handheld_entry.connection_status.is_right_connected.Assign(1);
handheld_entry.connection_status.is_left_wired.Assign(1);
handheld_entry.connection_status.is_right_wired.Assign(1);
handheld_entry.pad.pad_states.raw = pad_state.pad_states.raw;
handheld_entry.pad.l_stick = pad_state.l_stick;
handheld_entry.pad.r_stick = pad_state.r_stick;
libnx_entry.connection_status.IsWired.Assign(1);
libnx_entry.connection_status.IsLeftJoyConnected.Assign(1);
libnx_entry.connection_status.IsRightJoyConnected.Assign(1);
libnx_entry.connection_status.IsLeftJoyWired.Assign(1);
libnx_entry.connection_status.IsRightJoyWired.Assign(1);
libnx_entry.connection_status.is_wired.Assign(1);
libnx_entry.connection_status.is_left_connected.Assign(1);
libnx_entry.connection_status.is_right_connected.Assign(1);
libnx_entry.connection_status.is_left_wired.Assign(1);
libnx_entry.connection_status.is_right_wired.Assign(1);
break;
case NPadControllerType::JoyDual:
dual_entry.connection_status.raw = 0;
dual_entry.connection_status.IsConnected.Assign(1);
dual_entry.connection_status.IsLeftJoyConnected.Assign(1);
dual_entry.connection_status.IsRightJoyConnected.Assign(1);
dual_entry.connection_status.is_connected.Assign(1);
dual_entry.connection_status.is_left_connected.Assign(1);
dual_entry.connection_status.is_right_connected.Assign(1);
dual_entry.pad.pad_states.raw = pad_state.pad_states.raw;
dual_entry.pad.l_stick = pad_state.l_stick;
dual_entry.pad.r_stick = pad_state.r_stick;
libnx_entry.connection_status.IsLeftJoyConnected.Assign(1);
libnx_entry.connection_status.IsRightJoyConnected.Assign(1);
libnx_entry.connection_status.is_left_connected.Assign(1);
libnx_entry.connection_status.is_right_connected.Assign(1);
break;
case NPadControllerType::JoyLeft:
left_entry.connection_status.raw = 0;
left_entry.connection_status.IsConnected.Assign(1);
left_entry.connection_status.IsLeftJoyConnected.Assign(1);
left_entry.connection_status.is_connected.Assign(1);
left_entry.connection_status.is_left_connected.Assign(1);
left_entry.pad.pad_states.raw = pad_state.pad_states.raw;
left_entry.pad.l_stick = pad_state.l_stick;
left_entry.pad.r_stick = pad_state.r_stick;
libnx_entry.connection_status.IsLeftJoyConnected.Assign(1);
libnx_entry.connection_status.is_left_connected.Assign(1);
break;
case NPadControllerType::JoyRight:
right_entry.connection_status.raw = 0;
right_entry.connection_status.IsConnected.Assign(1);
right_entry.connection_status.IsRightJoyConnected.Assign(1);
right_entry.connection_status.is_connected.Assign(1);
right_entry.connection_status.is_right_connected.Assign(1);
right_entry.pad.pad_states.raw = pad_state.pad_states.raw;
right_entry.pad.l_stick = pad_state.l_stick;
right_entry.pad.r_stick = pad_state.r_stick;
libnx_entry.connection_status.IsRightJoyConnected.Assign(1);
libnx_entry.connection_status.is_right_connected.Assign(1);
break;
case NPadControllerType::Pokeball:
pokeball_entry.connection_status.raw = 0;
pokeball_entry.connection_status.IsConnected.Assign(1);
pokeball_entry.connection_status.is_connected.Assign(1);
pokeball_entry.pad.pad_states.raw = pad_state.pad_states.raw;
pokeball_entry.pad.l_stick = pad_state.l_stick;
pokeball_entry.pad.r_stick = pad_state.r_stick;
@@ -554,7 +560,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
}
const std::array<SixAxisGeneric*, 6> controller_sixaxes{
&npad.sixaxis_full, &npad.sixaxis_handheld, &npad.sixaxis_dual_left,
&npad.sixaxis_fullkey, &npad.sixaxis_handheld, &npad.sixaxis_dual_left,
&npad.sixaxis_dual_right, &npad.sixaxis_left, &npad.sixaxis_right,
};
@@ -592,7 +598,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
}
auto& full_sixaxis_entry =
npad.sixaxis_full.sixaxis[npad.sixaxis_full.common.last_entry_index];
npad.sixaxis_fullkey.sixaxis[npad.sixaxis_fullkey.common.last_entry_index];
auto& handheld_sixaxis_entry =
npad.sixaxis_handheld.sixaxis[npad.sixaxis_handheld.common.last_entry_index];
auto& dual_left_sixaxis_entry =
@@ -609,7 +615,9 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
UNREACHABLE();
break;
case NPadControllerType::ProController:
full_sixaxis_entry.attribute.raw = 0;
if (sixaxis_sensors_enabled && motions[i][0]) {
full_sixaxis_entry.attribute.is_connected.Assign(1);
full_sixaxis_entry.accel = motion_devices[0].accel;
full_sixaxis_entry.gyro = motion_devices[0].gyro;
full_sixaxis_entry.rotation = motion_devices[0].rotation;
@@ -617,7 +625,9 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
}
break;
case NPadControllerType::Handheld:
handheld_sixaxis_entry.attribute.raw = 0;
if (sixaxis_sensors_enabled && motions[i][0]) {
handheld_sixaxis_entry.attribute.is_connected.Assign(1);
handheld_sixaxis_entry.accel = motion_devices[0].accel;
handheld_sixaxis_entry.gyro = motion_devices[0].gyro;
handheld_sixaxis_entry.rotation = motion_devices[0].rotation;
@@ -625,8 +635,11 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
}
break;
case NPadControllerType::JoyDual:
dual_left_sixaxis_entry.attribute.raw = 0;
dual_right_sixaxis_entry.attribute.raw = 0;
if (sixaxis_sensors_enabled && motions[i][0]) {
// Set motion for the left joycon
dual_left_sixaxis_entry.attribute.is_connected.Assign(1);
dual_left_sixaxis_entry.accel = motion_devices[0].accel;
dual_left_sixaxis_entry.gyro = motion_devices[0].gyro;
dual_left_sixaxis_entry.rotation = motion_devices[0].rotation;
@@ -634,6 +647,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
}
if (sixaxis_sensors_enabled && motions[i][1]) {
// Set motion for the right joycon
dual_right_sixaxis_entry.attribute.is_connected.Assign(1);
dual_right_sixaxis_entry.accel = motion_devices[1].accel;
dual_right_sixaxis_entry.gyro = motion_devices[1].gyro;
dual_right_sixaxis_entry.rotation = motion_devices[1].rotation;
@@ -641,7 +655,9 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
}
break;
case NPadControllerType::JoyLeft:
left_sixaxis_entry.attribute.raw = 0;
if (sixaxis_sensors_enabled && motions[i][0]) {
left_sixaxis_entry.attribute.is_connected.Assign(1);
left_sixaxis_entry.accel = motion_devices[0].accel;
left_sixaxis_entry.gyro = motion_devices[0].gyro;
left_sixaxis_entry.rotation = motion_devices[0].rotation;
@@ -649,7 +665,9 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
}
break;
case NPadControllerType::JoyRight:
right_sixaxis_entry.attribute.raw = 0;
if (sixaxis_sensors_enabled && motions[i][1]) {
right_sixaxis_entry.attribute.is_connected.Assign(1);
right_sixaxis_entry.accel = motion_devices[1].accel;
right_sixaxis_entry.gyro = motion_devices[1].gyro;
right_sixaxis_entry.rotation = motion_devices[1].rotation;
@@ -715,8 +733,8 @@ Controller_NPad::NpadCommunicationMode Controller_NPad::GetNpadCommunicationMode
void Controller_NPad::SetNpadMode(u32 npad_id, NpadAssignments assignment_mode) {
const std::size_t npad_index = NPadIdToIndex(npad_id);
ASSERT(npad_index < shared_memory_entries.size());
if (shared_memory_entries[npad_index].pad_assignment != assignment_mode) {
shared_memory_entries[npad_index].pad_assignment = assignment_mode;
if (shared_memory_entries[npad_index].assignment_mode != assignment_mode) {
shared_memory_entries[npad_index].assignment_mode = assignment_mode;
}
}
@@ -872,13 +890,14 @@ bool Controller_NPad::IsVibrationDeviceMounted(const DeviceHandle& vibration_dev
return vibration_devices_mounted[npad_index][device_index];
}
std::shared_ptr<Kernel::ReadableEvent> Controller_NPad::GetStyleSetChangedEvent(u32 npad_id) const {
std::shared_ptr<Kernel::KReadableEvent> Controller_NPad::GetStyleSetChangedEvent(
u32 npad_id) const {
const auto& styleset_event = styleset_changed_events[NPadIdToIndex(npad_id)];
return styleset_event.readable;
return styleset_event->GetReadableEvent();
}
void Controller_NPad::SignalStyleSetChangedEvent(u32 npad_id) const {
styleset_changed_events[NPadIdToIndex(npad_id)].writable->Signal();
styleset_changed_events[NPadIdToIndex(npad_id)]->GetWritableEvent()->Signal();
}
void Controller_NPad::AddNewControllerAt(NPadControllerType controller, std::size_t npad_index) {
@@ -923,9 +942,17 @@ void Controller_NPad::DisconnectNpadAtIndex(std::size_t npad_index) {
connected_controllers[npad_index].is_connected = false;
auto& controller = shared_memory_entries[npad_index];
controller.joy_styles.raw = 0; // Zero out
controller.style_set.raw = 0; // Zero out
controller.device_type.raw = 0;
controller.properties.raw = 0;
controller.system_properties.raw = 0;
controller.button_properties.raw = 0;
controller.battery_level_dual = 0;
controller.battery_level_left = 0;
controller.battery_level_right = 0;
controller.fullkey_color = {};
controller.joycon_color = {};
controller.assignment_mode = NpadAssignments::Dual;
controller.footer_type = AppletFooterUiType::None;
SignalStyleSetChangedEvent(IndexToNPad(npad_index));
}
@@ -1101,7 +1128,7 @@ bool Controller_NPad::IsControllerSupported(NPadControllerType controller) const
[](u32 npad_id) { return npad_id <= MAX_NPAD_ID; })) {
switch (controller) {
case NPadControllerType::ProController:
return style.pro_controller;
return style.fullkey;
case NPadControllerType::JoyDual:
return style.joycon_dual;
case NPadControllerType::JoyLeft:
@@ -1109,7 +1136,7 @@ bool Controller_NPad::IsControllerSupported(NPadControllerType controller) const
case NPadControllerType::JoyRight:
return style.joycon_right;
case NPadControllerType::Pokeball:
return style.pokeball;
return style.palma;
default:
return false;
}
+148 -53
View File
@@ -10,10 +10,14 @@
#include "common/common_types.h"
#include "core/frontend/input.h"
#include "core/hle/kernel/object.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/service/hid/controllers/controller_base.h"
#include "core/settings.h"
namespace Kernel {
class KEvent;
class KReadableEvent;
} // namespace Kernel
namespace Service::HID {
constexpr u32 NPAD_HANDHELD = 32;
@@ -90,10 +94,10 @@ public:
};
enum class NpadCommunicationMode : u64 {
Unknown0 = 0,
Unknown1 = 1,
Unknown2 = 2,
Unknown3 = 3,
Mode_5ms = 0,
Mode_10ms = 1,
Mode_15ms = 2,
Default = 3,
};
struct DeviceHandle {
@@ -108,13 +112,18 @@ public:
union {
u32_le raw{};
BitField<0, 1, u32> pro_controller;
BitField<0, 1, u32> fullkey;
BitField<1, 1, u32> handheld;
BitField<2, 1, u32> joycon_dual;
BitField<3, 1, u32> joycon_left;
BitField<4, 1, u32> joycon_right;
BitField<6, 1, u32> pokeball; // TODO(ogniK): Confirm when possible
BitField<5, 1, u32> gamecube;
BitField<6, 1, u32> palma;
BitField<7, 1, u32> lark;
BitField<8, 1, u32> handheld_lark;
BitField<9, 1, u32> lucia;
BitField<29, 1, u32> system_ext;
BitField<30, 1, u32> system;
};
};
static_assert(sizeof(NpadStyleSet) == 4, "NpadStyleSet is an invalid size");
@@ -187,7 +196,7 @@ public:
bool IsVibrationDeviceMounted(const DeviceHandle& vibration_device_handle) const;
std::shared_ptr<Kernel::ReadableEvent> GetStyleSetChangedEvent(u32 npad_id) const;
std::shared_ptr<Kernel::KReadableEvent> GetStyleSetChangedEvent(u32 npad_id) const;
void SignalStyleSetChangedEvent(u32 npad_id) const;
// Adds a new controller at an index.
@@ -238,12 +247,32 @@ private:
};
static_assert(sizeof(CommonHeader) == 0x20, "CommonHeader is an invalid size");
enum class ColorAttributes : u32_le {
Ok = 0,
ReadError = 1,
NoController = 2,
};
static_assert(sizeof(ColorAttributes) == 4, "ColorAttributes is an invalid size");
struct ControllerColor {
u32_le body_color;
u32_le button_color;
u32_le body;
u32_le button;
};
static_assert(sizeof(ControllerColor) == 8, "ControllerColor is an invalid size");
struct FullKeyColor {
ColorAttributes attribute;
ControllerColor fullkey;
};
static_assert(sizeof(FullKeyColor) == 0xC, "FullKeyColor is an invalid size");
struct JoyconColor {
ColorAttributes attribute;
ControllerColor left;
ControllerColor right;
};
static_assert(sizeof(JoyconColor) == 0x14, "JoyconColor is an invalid size");
struct ControllerPadState {
union {
u64_le raw{};
@@ -285,6 +314,9 @@ private:
BitField<26, 1, u64> right_sl;
BitField<27, 1, u64> right_sr;
BitField<28, 1, u64> palma;
BitField<30, 1, u64> handheld_left_b;
};
};
static_assert(sizeof(ControllerPadState) == 8, "ControllerPadState is an invalid size");
@@ -298,12 +330,12 @@ private:
struct ConnectionState {
union {
u32_le raw{};
BitField<0, 1, u32> IsConnected;
BitField<1, 1, u32> IsWired;
BitField<2, 1, u32> IsLeftJoyConnected;
BitField<3, 1, u32> IsLeftJoyWired;
BitField<4, 1, u32> IsRightJoyConnected;
BitField<5, 1, u32> IsRightJoyWired;
BitField<0, 1, u32> is_connected;
BitField<1, 1, u32> is_wired;
BitField<2, 1, u32> is_left_connected;
BitField<3, 1, u32> is_left_wired;
BitField<4, 1, u32> is_right_connected;
BitField<5, 1, u32> is_right_wired;
};
};
static_assert(sizeof(ConnectionState) == 4, "ConnectionState is an invalid size");
@@ -329,6 +361,15 @@ private:
};
static_assert(sizeof(NPadGeneric) == 0x350, "NPadGeneric is an invalid size");
struct SixAxisAttributes {
union {
u32_le raw{};
BitField<0, 1, u32> is_connected;
BitField<1, 1, u32> is_interpolated;
};
};
static_assert(sizeof(SixAxisAttributes) == 4, "SixAxisAttributes is an invalid size");
struct SixAxisStates {
s64_le timestamp{};
INSERT_PADDING_WORDS(2);
@@ -337,7 +378,8 @@ private:
Common::Vec3f gyro{};
Common::Vec3f rotation{};
std::array<Common::Vec3f, 3> orientation{};
s64_le always_one{1};
SixAxisAttributes attribute;
INSERT_PADDING_BYTES(4); // Reserved
};
static_assert(sizeof(SixAxisStates) == 0x68, "SixAxisStates is an invalid size");
@@ -347,32 +389,54 @@ private:
};
static_assert(sizeof(SixAxisGeneric) == 0x708, "SixAxisGeneric is an invalid size");
enum class ColorReadError : u32_le {
ReadOk = 0,
ColorDoesntExist = 1,
NoController = 2,
};
struct NPadProperties {
struct NPadSystemProperties {
union {
s64_le raw{};
BitField<0, 1, s64> is_charging_joy_dual;
BitField<1, 1, s64> is_charging_joy_left;
BitField<2, 1, s64> is_charging_joy_right;
BitField<3, 1, s64> is_powered_joy_dual;
BitField<4, 1, s64> is_powered_joy_left;
BitField<5, 1, s64> is_powered_joy_right;
BitField<9, 1, s64> is_system_unsupported_button;
BitField<10, 1, s64> is_system_ext_unsupported_button;
BitField<11, 1, s64> is_vertical;
BitField<12, 1, s64> is_horizontal;
BitField<13, 1, s64> use_plus;
BitField<14, 1, s64> use_minus;
BitField<15, 1, s64> use_directional_buttons;
};
};
static_assert(sizeof(NPadSystemProperties) == 0x8, "NPadSystemProperties is an invalid size");
struct NPadButtonProperties {
union {
s32_le raw{};
BitField<0, 1, s32> is_home_button_protection_enabled;
};
};
static_assert(sizeof(NPadButtonProperties) == 0x4, "NPadButtonProperties is an invalid size");
struct NPadDevice {
union {
u32_le raw{};
BitField<0, 1, s32> pro_controller;
BitField<1, 1, s32> handheld;
BitField<0, 1, s32> fullkey;
BitField<1, 1, s32> debug_pad;
BitField<2, 1, s32> handheld_left;
BitField<3, 1, s32> handheld_right;
BitField<4, 1, s32> joycon_left;
BitField<5, 1, s32> joycon_right;
BitField<6, 1, s32> pokeball;
BitField<6, 1, s32> palma;
BitField<7, 1, s32> lark_hvc_left;
BitField<8, 1, s32> lark_hvc_right;
BitField<9, 1, s32> lark_nes_left;
BitField<10, 1, s32> lark_nes_right;
BitField<11, 1, s32> handheld_lark_hvc_left;
BitField<12, 1, s32> handheld_lark_hvc_right;
BitField<13, 1, s32> handheld_lark_nes_left;
BitField<14, 1, s32> handheld_lark_nes_right;
BitField<15, 1, s32> lucia;
BitField<31, 1, s32> system;
};
};
@@ -383,37 +447,69 @@ private:
std::array<Common::Vec3f, 3> orientation;
};
struct NfcXcdHandle {
INSERT_PADDING_BYTES(0x60);
};
struct AppletFooterUiAttributes {
INSERT_PADDING_BYTES(0x4);
};
enum class AppletFooterUiType : u8 {
None = 0,
HandheldNone = 1,
HandheldJoyConLeftOnly = 1,
HandheldJoyConRightOnly = 3,
HandheldJoyConLeftJoyConRight = 4,
JoyDual = 5,
JoyDualLeftOnly = 6,
JoyDualRightOnly = 7,
JoyLeftHorizontal = 8,
JoyLeftVertical = 9,
JoyRightHorizontal = 10,
JoyRightVertical = 11,
SwitchProController = 12,
CompatibleProController = 13,
CompatibleJoyCon = 14,
LarkHvc1 = 15,
LarkHvc2 = 16,
LarkNesLeft = 17,
LarkNesRight = 18,
Lucia = 19,
Verification = 20,
};
struct NPadEntry {
NpadStyleSet joy_styles;
NpadAssignments pad_assignment;
NpadStyleSet style_set;
NpadAssignments assignment_mode;
FullKeyColor fullkey_color;
JoyconColor joycon_color;
ColorReadError single_color_error;
ControllerColor single_color;
ColorReadError dual_color_error;
ControllerColor left_color;
ControllerColor right_color;
NPadGeneric main_controller_states;
NPadGeneric fullkey_states;
NPadGeneric handheld_states;
NPadGeneric dual_states;
NPadGeneric left_joy_states;
NPadGeneric right_joy_states;
NPadGeneric pokeball_states;
NPadGeneric libnx; // TODO(ogniK): Find out what this actually is, libnx seems to only be
// relying on this for the time being
SixAxisGeneric sixaxis_full;
NPadGeneric joy_dual_states;
NPadGeneric joy_left_states;
NPadGeneric joy_right_states;
NPadGeneric palma_states;
NPadGeneric system_ext_states;
SixAxisGeneric sixaxis_fullkey;
SixAxisGeneric sixaxis_handheld;
SixAxisGeneric sixaxis_dual_left;
SixAxisGeneric sixaxis_dual_right;
SixAxisGeneric sixaxis_left;
SixAxisGeneric sixaxis_right;
NPadDevice device_type;
NPadProperties properties;
INSERT_PADDING_WORDS(1);
std::array<u32, 3> battery_level;
INSERT_PADDING_BYTES(0x5c);
INSERT_PADDING_BYTES(0xdf8);
INSERT_PADDING_BYTES(0x4); // reserved
NPadSystemProperties system_properties;
NPadButtonProperties button_properties;
u32 battery_level_dual;
u32 battery_level_left;
u32 battery_level_right;
AppletFooterUiAttributes footer_attributes;
AppletFooterUiType footer_type;
// nfc_states needs to be checked switchbrew does not match with HW
NfcXcdHandle nfc_states;
INSERT_PADDING_BYTES(0xdef);
};
static_assert(sizeof(NPadEntry) == 0x5000, "NPadEntry is an invalid size");
@@ -449,10 +545,9 @@ private:
std::vector<u32> supported_npad_id_types{};
NpadHoldType hold_type{NpadHoldType::Vertical};
NpadHandheldActivationMode handheld_activation_mode{NpadHandheldActivationMode::Dual};
// NpadCommunicationMode is unknown, default value is 1
NpadCommunicationMode communication_mode{NpadCommunicationMode::Unknown1};
NpadCommunicationMode communication_mode{NpadCommunicationMode::Default};
// Each controller should have their own styleset changed event
std::array<Kernel::EventPair, 10> styleset_changed_events;
std::array<std::shared_ptr<Kernel::KEvent>, 10> styleset_changed_events;
std::array<std::array<std::chrono::steady_clock::time_point, 2>, 10> last_vibration_timepoints;
std::array<std::array<VibrationValue, 2>, 10> latest_vibration_values{};
bool permit_vibration_session_enabled{false};
+66 -4
View File
@@ -4,6 +4,7 @@
#pragma once
#include "common/bit_field.h"
#include "common/common_funcs.h"
#include "common/common_types.h"
#include "common/swap.h"
@@ -28,6 +29,67 @@ public:
void OnLoadInputDevices() override;
private:
struct Attributes {
union {
u32_le raw{};
BitField<0, 1, u32> is_connected;
BitField<1, 1, u32> is_wired;
BitField<2, 1, u32> is_left_connected;
BitField<3, 1, u32> is_left_wired;
BitField<4, 1, u32> is_right_connected;
BitField<5, 1, u32> is_right_wired;
};
};
static_assert(sizeof(Attributes) == 4, "Attributes is an invalid size");
struct Buttons {
union {
u32_le raw{};
// Button states
BitField<0, 1, u32> a;
BitField<1, 1, u32> b;
BitField<2, 1, u32> x;
BitField<3, 1, u32> y;
BitField<4, 1, u32> l_stick;
BitField<5, 1, u32> r_stick;
BitField<6, 1, u32> l;
BitField<7, 1, u32> r;
BitField<8, 1, u32> zl;
BitField<9, 1, u32> zr;
BitField<10, 1, u32> plus;
BitField<11, 1, u32> minus;
// D-Pad
BitField<12, 1, u32> d_left;
BitField<13, 1, u32> d_up;
BitField<14, 1, u32> d_right;
BitField<15, 1, u32> d_down;
// Left JoyStick
BitField<16, 1, u32> l_stick_left;
BitField<17, 1, u32> l_stick_up;
BitField<18, 1, u32> l_stick_right;
BitField<19, 1, u32> l_stick_down;
// Right JoyStick
BitField<20, 1, u32> r_stick_left;
BitField<21, 1, u32> r_stick_up;
BitField<22, 1, u32> r_stick_right;
BitField<23, 1, u32> r_stick_down;
// Not always active?
BitField<24, 1, u32> left_sl;
BitField<25, 1, u32> left_sr;
BitField<26, 1, u32> right_sl;
BitField<27, 1, u32> right_sr;
BitField<28, 1, u32> palma;
BitField<30, 1, u32> handheld_left_b;
};
};
static_assert(sizeof(Buttons) == 4, "Buttons is an invalid size");
struct AnalogStick {
s32_le x;
s32_le y;
@@ -37,10 +99,10 @@ private:
struct XPadState {
s64_le sampling_number;
s64_le sampling_number2;
s32_le attributes;
u32_le pad_states;
AnalogStick x_stick;
AnalogStick y_stick;
Attributes attributes;
Buttons pad_states;
AnalogStick l_stick;
AnalogStick r_stick;
};
static_assert(sizeof(XPadState) == 0x28, "XPadState is an invalid size");
+26 -11
View File
@@ -14,10 +14,10 @@
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/client_port.h"
#include "core/hle/kernel/client_session.h"
#include "core/hle/kernel/k_readable_event.h"
#include "core/hle/kernel/k_writable_event.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/shared_memory.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/service/hid/errors.h"
#include "core/hle/service/hid/hid.h"
#include "core/hle/service/hid/irs.h"
@@ -59,20 +59,26 @@ IAppletResource::IAppletResource(Core::System& system_)
MakeController<Controller_Mouse>(HidController::Mouse);
MakeController<Controller_Keyboard>(HidController::Keyboard);
MakeController<Controller_XPad>(HidController::XPad);
MakeController<Controller_Stubbed>(HidController::Unknown1);
MakeController<Controller_Stubbed>(HidController::Unknown2);
MakeController<Controller_Stubbed>(HidController::Unknown3);
MakeController<Controller_Stubbed>(HidController::SixAxisSensor);
MakeController<Controller_Stubbed>(HidController::HomeButton);
MakeController<Controller_Stubbed>(HidController::SleepButton);
MakeController<Controller_Stubbed>(HidController::CaptureButton);
MakeController<Controller_Stubbed>(HidController::InputDetector);
MakeController<Controller_Stubbed>(HidController::UniquePad);
MakeController<Controller_NPad>(HidController::NPad);
MakeController<Controller_Gesture>(HidController::Gesture);
MakeController<Controller_Stubbed>(HidController::ConsoleSixAxisSensor);
// Homebrew doesn't try to activate some controllers, so we activate them by default
GetController<Controller_NPad>(HidController::NPad).ActivateController();
GetController<Controller_Touchscreen>(HidController::Touchscreen).ActivateController();
GetController<Controller_Stubbed>(HidController::Unknown1).SetCommonHeaderOffset(0x4c00);
GetController<Controller_Stubbed>(HidController::Unknown2).SetCommonHeaderOffset(0x4e00);
GetController<Controller_Stubbed>(HidController::Unknown3).SetCommonHeaderOffset(0x5000);
GetController<Controller_Stubbed>(HidController::HomeButton).SetCommonHeaderOffset(0x4C00);
GetController<Controller_Stubbed>(HidController::SleepButton).SetCommonHeaderOffset(0x4E00);
GetController<Controller_Stubbed>(HidController::CaptureButton).SetCommonHeaderOffset(0x5000);
GetController<Controller_Stubbed>(HidController::InputDetector).SetCommonHeaderOffset(0x5200);
GetController<Controller_Stubbed>(HidController::UniquePad).SetCommonHeaderOffset(0x5A00);
GetController<Controller_Stubbed>(HidController::ConsoleSixAxisSensor)
.SetCommonHeaderOffset(0x3C200);
// Register update callbacks
pad_update_event = Core::Timing::CreateEvent(
@@ -126,14 +132,23 @@ void IAppletResource::UpdateControllers(std::uintptr_t user_data,
controller->OnUpdate(core_timing, shared_mem->GetPointer(), SHARED_MEMORY_SIZE);
}
// If ns_late is higher than the update rate ignore the delay
if (ns_late > motion_update_ns) {
ns_late = {};
}
core_timing.ScheduleEvent(pad_update_ns - ns_late, pad_update_event);
}
void IAppletResource::UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
auto& core_timing = system.CoreTiming();
for (const auto& controller : controllers) {
controller->OnMotionUpdate(core_timing, shared_mem->GetPointer(), SHARED_MEMORY_SIZE);
controllers[static_cast<size_t>(HidController::NPad)]->OnMotionUpdate(
core_timing, shared_mem->GetPointer(), SHARED_MEMORY_SIZE);
// If ns_late is higher than the update rate ignore the delay
if (ns_late > motion_update_ns) {
ns_late = {};
}
core_timing.ScheduleEvent(motion_update_ns - ns_late, motion_update_event);
+6 -4
View File
@@ -29,12 +29,14 @@ enum class HidController : std::size_t {
Mouse,
Keyboard,
XPad,
Unknown1,
Unknown2,
Unknown3,
SixAxisSensor,
HomeButton,
SleepButton,
CaptureButton,
InputDetector,
UniquePad,
NPad,
Gesture,
ConsoleSixAxisSensor,
MaxControllers,
};
+17 -14
View File
@@ -8,10 +8,11 @@
#include "common/logging/log.h"
#include "core/core.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/k_event.h"
#include "core/hle/kernel/k_readable_event.h"
#include "core/hle/kernel/k_thread.h"
#include "core/hle/kernel/k_writable_event.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/lock.h"
#include "core/hle/service/nfp/nfp.h"
#include "core/hle/service/nfp/nfp_user.h"
@@ -25,7 +26,8 @@ Module::Interface::Interface(std::shared_ptr<Module> module_, Core::System& syst
const char* name)
: ServiceFramework{system_, name}, module{std::move(module_)} {
auto& kernel = system.Kernel();
nfc_tag_load = Kernel::WritableEvent::CreateEventPair(kernel, "IUser:NFCTagDetected");
nfc_tag_load = Kernel::KEvent::Create(kernel, "IUser:NFCTagDetected");
nfc_tag_load->Initialize();
}
Module::Interface::~Interface() = default;
@@ -64,9 +66,10 @@ public:
RegisterHandlers(functions);
auto& kernel = system.Kernel();
deactivate_event = Kernel::WritableEvent::CreateEventPair(kernel, "IUser:DeactivateEvent");
availability_change_event =
Kernel::WritableEvent::CreateEventPair(kernel, "IUser:AvailabilityChangeEvent");
deactivate_event = Kernel::KEvent::Create(kernel, "IUser:DeactivateEvent");
deactivate_event->Initialize();
availability_change_event = Kernel::KEvent::Create(kernel, "IUser:AvailabilityChangeEvent");
availability_change_event->Initialize();
}
private:
@@ -164,7 +167,7 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(deactivate_event.readable);
rb.PushCopyObjects(deactivate_event->GetReadableEvent());
}
void StopDetection(Kernel::HLERequestContext& ctx) {
@@ -173,7 +176,7 @@ private:
switch (device_state) {
case DeviceState::TagFound:
case DeviceState::TagNearby:
deactivate_event.writable->Signal();
deactivate_event->GetWritableEvent()->Signal();
device_state = DeviceState::Initialized;
break;
case DeviceState::SearchingForTag:
@@ -262,7 +265,7 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(availability_change_event.readable);
rb.PushCopyObjects(availability_change_event->GetReadableEvent());
}
void GetRegisterInfo(Kernel::HLERequestContext& ctx) {
@@ -316,8 +319,8 @@ private:
const u32 npad_id{0}; // Player 1 controller
State state{State::NonInitialized};
DeviceState device_state{DeviceState::Initialized};
Kernel::EventPair deactivate_event;
Kernel::EventPair availability_change_event;
std::shared_ptr<Kernel::KEvent> deactivate_event;
std::shared_ptr<Kernel::KEvent> availability_change_event;
const Module::Interface& nfp_interface;
};
@@ -336,12 +339,12 @@ bool Module::Interface::LoadAmiibo(const std::vector<u8>& buffer) {
}
std::memcpy(&amiibo, buffer.data(), sizeof(amiibo));
nfc_tag_load.writable->Signal();
nfc_tag_load->GetWritableEvent()->Signal();
return true;
}
const std::shared_ptr<Kernel::ReadableEvent>& Module::Interface::GetNFCEvent() const {
return nfc_tag_load.readable;
const std::shared_ptr<Kernel::KReadableEvent>& Module::Interface::GetNFCEvent() const {
return nfc_tag_load->GetReadableEvent();
}
const Module::Interface::AmiiboFile& Module::Interface::GetAmiiboBuffer() const {
+7 -4
View File
@@ -6,10 +6,13 @@
#include <array>
#include <vector>
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/service/service.h"
namespace Kernel {
class KEvent;
}
namespace Service::NFP {
class Module final {
@@ -35,11 +38,11 @@ public:
void CreateUserInterface(Kernel::HLERequestContext& ctx);
bool LoadAmiibo(const std::vector<u8>& buffer);
const std::shared_ptr<Kernel::ReadableEvent>& GetNFCEvent() const;
const std::shared_ptr<Kernel::KReadableEvent>& GetNFCEvent() const;
const AmiiboFile& GetAmiiboBuffer() const;
private:
Kernel::EventPair nfc_tag_load{};
std::shared_ptr<Kernel::KEvent> nfc_tag_load;
AmiiboFile amiibo{};
protected:
+14 -7
View File
@@ -4,9 +4,9 @@
#include "core/core.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/k_event.h"
#include "core/hle/kernel/k_readable_event.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/service/nifm/nifm.h"
#include "core/hle/service/service.h"
#include "core/network/network.h"
@@ -158,8 +158,11 @@ public:
RegisterHandlers(functions);
auto& kernel = system.Kernel();
event1 = Kernel::WritableEvent::CreateEventPair(kernel, "IRequest:Event1");
event2 = Kernel::WritableEvent::CreateEventPair(kernel, "IRequest:Event2");
event1 = Kernel::KEvent::Create(kernel, "IRequest:Event1");
event1->Initialize();
event2 = Kernel::KEvent::Create(kernel, "IRequest:Event2");
event2->Initialize();
}
private:
@@ -195,7 +198,7 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 2};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(event1.readable, event2.readable);
rb.PushCopyObjects(event1->GetReadableEvent(), event2->GetReadableEvent());
}
void Cancel(Kernel::HLERequestContext& ctx) {
@@ -215,14 +218,18 @@ private:
void GetAppletInfo(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_NIFM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 8};
std::vector<u8> out_buffer(ctx.GetWriteBufferSize());
ctx.WriteBuffer(out_buffer);
IPC::ResponseBuilder rb{ctx, 5};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(0);
rb.Push<u32>(0);
rb.Push<u32>(0);
}
Kernel::EventPair event1, event2;
std::shared_ptr<Kernel::KEvent> event1, event2;
};
class INetworkProfile final : public ServiceFramework<INetworkProfile> {
+10 -8
View File
@@ -6,9 +6,10 @@
#include <ctime>
#include "core/core.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/k_event.h"
#include "core/hle/kernel/k_readable_event.h"
#include "core/hle/kernel/k_writable_event.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/service/nim/nim.h"
#include "core/hle/service/service.h"
#include "core/hle/service/sm/sm.h"
@@ -301,17 +302,18 @@ public:
RegisterHandlers(functions);
auto& kernel = system.Kernel();
finished_event = Kernel::WritableEvent::CreateEventPair(
kernel, "IEnsureNetworkClockAvailabilityService:FinishEvent");
finished_event =
Kernel::KEvent::Create(kernel, "IEnsureNetworkClockAvailabilityService:FinishEvent");
finished_event->Initialize();
}
private:
Kernel::EventPair finished_event;
std::shared_ptr<Kernel::KEvent> finished_event;
void StartTask(Kernel::HLERequestContext& ctx) {
// No need to connect to the internet, just finish the task straight away.
LOG_DEBUG(Service_NIM, "called");
finished_event.writable->Signal();
finished_event->GetWritableEvent()->Signal();
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
@@ -321,7 +323,7 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(finished_event.readable);
rb.PushCopyObjects(finished_event->GetReadableEvent());
}
void GetResult(Kernel::HLERequestContext& ctx) {
@@ -333,7 +335,7 @@ private:
void Cancel(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_NIM, "called");
finished_event.writable->Clear();
finished_event->GetWritableEvent()->Clear();
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
@@ -8,8 +8,8 @@
#include "common/assert.h"
#include "common/logging/log.h"
#include "core/core.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/kernel/k_event.h"
#include "core/hle/kernel/k_writable_event.h"
#include "core/hle/service/nvdrv/devices/nvhost_ctrl.h"
#include "video_core/gpu.h"
@@ -103,14 +103,14 @@ NvResult nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector
// This is mostly to take into account unimplemented features. As synced
// gpu is always synced.
if (!gpu.IsAsync()) {
event.event.writable->Signal();
event.event->GetWritableEvent()->Signal();
return NvResult::Success;
}
auto lock = gpu.LockSync();
const u32 current_syncpoint_value = event.fence.value;
const s32 diff = current_syncpoint_value - params.threshold;
if (diff >= 0) {
event.event.writable->Signal();
event.event->GetWritableEvent()->Signal();
params.value = current_syncpoint_value;
std::memcpy(output.data(), &params, sizeof(params));
return NvResult::Success;
@@ -137,7 +137,7 @@ NvResult nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector
params.value = ((params.syncpt_id & 0xfff) << 16) | 0x10000000;
}
params.value |= event_id;
event.event.writable->Clear();
event.event->GetWritableEvent()->Clear();
gpu.RegisterSyncptInterrupt(params.syncpt_id, target_value);
std::memcpy(output.data(), &params, sizeof(params));
return NvResult::Timeout;
+2 -2
View File
@@ -6,10 +6,10 @@
#include "common/logging/log.h"
#include "core/core.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/k_readable_event.h"
#include "core/hle/kernel/k_thread.h"
#include "core/hle/kernel/k_writable_event.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/service/nvdrv/interface.h"
#include "core/hle/service/nvdrv/nvdata.h"
#include "core/hle/service/nvdrv/nvdrv.h"
+1 -1
View File
@@ -9,7 +9,7 @@
#include "core/hle/service/service.h"
namespace Kernel {
class WritableEvent;
class KWritableEvent;
}
namespace Service::Nvidia {
+10 -8
View File
@@ -7,8 +7,9 @@
#include <fmt/format.h>
#include "core/core.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/kernel/k_event.h"
#include "core/hle/kernel/k_readable_event.h"
#include "core/hle/kernel/k_writable_event.h"
#include "core/hle/service/nvdrv/devices/nvdevice.h"
#include "core/hle/service/nvdrv/devices/nvdisp_disp0.h"
#include "core/hle/service/nvdrv/devices/nvhost_as_gpu.h"
@@ -42,7 +43,8 @@ Module::Module(Core::System& system) : syncpoint_manager{system.GPU()} {
auto& kernel = system.Kernel();
for (u32 i = 0; i < MaxNvEvents; i++) {
std::string event_label = fmt::format("NVDRV::NvEvent_{}", i);
events_interface.events[i] = {Kernel::WritableEvent::CreateEventPair(kernel, event_label)};
events_interface.events[i] = {Kernel::KEvent::Create(kernel, std::move(event_label))};
events_interface.events[i].event->Initialize();
events_interface.status[i] = EventState::Free;
events_interface.registered[i] = false;
}
@@ -166,17 +168,17 @@ void Module::SignalSyncpt(const u32 syncpoint_id, const u32 value) {
if (events_interface.assigned_syncpt[i] == syncpoint_id &&
events_interface.assigned_value[i] == value) {
events_interface.LiberateEvent(i);
events_interface.events[i].event.writable->Signal();
events_interface.events[i].event->GetWritableEvent()->Signal();
}
}
}
std::shared_ptr<Kernel::ReadableEvent> Module::GetEvent(const u32 event_id) const {
return events_interface.events[event_id].event.readable;
std::shared_ptr<Kernel::KReadableEvent> Module::GetEvent(const u32 event_id) const {
return events_interface.events[event_id].event->GetReadableEvent();
}
std::shared_ptr<Kernel::WritableEvent> Module::GetEventWriteable(const u32 event_id) const {
return events_interface.events[event_id].event.writable;
std::shared_ptr<Kernel::KWritableEvent> Module::GetEventWriteable(const u32 event_id) const {
return events_interface.events[event_id].event->GetWritableEvent();
}
} // namespace Service::Nvidia
+8 -4
View File
@@ -7,8 +7,8 @@
#include <memory>
#include <unordered_map>
#include <vector>
#include "common/common_types.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/service/nvdrv/nvdata.h"
#include "core/hle/service/nvdrv/syncpoint_manager.h"
#include "core/hle/service/service.h"
@@ -17,6 +17,10 @@ namespace Core {
class System;
}
namespace Kernel {
class KEvent;
}
namespace Service::NVFlinger {
class NVFlinger;
}
@@ -31,7 +35,7 @@ class nvdevice;
/// Represents an Nvidia event
struct NvEvent {
Kernel::EventPair event;
std::shared_ptr<Kernel::KEvent> event;
Fence fence{};
};
@@ -132,9 +136,9 @@ public:
void SignalSyncpt(const u32 syncpoint_id, const u32 value);
std::shared_ptr<Kernel::ReadableEvent> GetEvent(u32 event_id) const;
std::shared_ptr<Kernel::KReadableEvent> GetEvent(u32 event_id) const;
std::shared_ptr<Kernel::WritableEvent> GetEventWriteable(u32 event_id) const;
std::shared_ptr<Kernel::KWritableEvent> GetEventWriteable(u32 event_id) const;
private:
/// Manages syncpoints on the host
+12 -11
View File
@@ -7,16 +7,17 @@
#include "common/assert.h"
#include "common/logging/log.h"
#include "core/core.h"
#include "core/hle/kernel/k_event.h"
#include "core/hle/kernel/k_writable_event.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/service/nvflinger/buffer_queue.h"
namespace Service::NVFlinger {
BufferQueue::BufferQueue(Kernel::KernelCore& kernel, u32 id, u64 layer_id)
: id(id), layer_id(layer_id) {
buffer_wait_event = Kernel::WritableEvent::CreateEventPair(kernel, "BufferQueue NativeHandle");
buffer_wait_event = Kernel::KEvent::Create(kernel, "BufferQueue:WaitEvent");
buffer_wait_event->Initialize();
}
BufferQueue::~BufferQueue() = default;
@@ -41,7 +42,7 @@ void BufferQueue::SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer)
.multi_fence = {},
};
buffer_wait_event.writable->Signal();
buffer_wait_event->GetWritableEvent()->Signal();
}
std::optional<std::pair<u32, Service::Nvidia::MultiFence*>> BufferQueue::DequeueBuffer(u32 width,
@@ -119,7 +120,7 @@ void BufferQueue::CancelBuffer(u32 slot, const Service::Nvidia::MultiFence& mult
}
free_buffers_condition.notify_one();
buffer_wait_event.writable->Signal();
buffer_wait_event->GetWritableEvent()->Signal();
}
std::optional<std::reference_wrapper<const BufferQueue::Buffer>> BufferQueue::AcquireBuffer() {
@@ -154,7 +155,7 @@ void BufferQueue::ReleaseBuffer(u32 slot) {
}
free_buffers_condition.notify_one();
buffer_wait_event.writable->Signal();
buffer_wait_event->GetWritableEvent()->Signal();
}
void BufferQueue::Connect() {
@@ -169,7 +170,7 @@ void BufferQueue::Disconnect() {
std::unique_lock lock{queue_sequence_mutex};
queue_sequence.clear();
}
buffer_wait_event.writable->Signal();
buffer_wait_event->GetWritableEvent()->Signal();
is_connect = false;
free_buffers_condition.notify_one();
}
@@ -188,12 +189,12 @@ u32 BufferQueue::Query(QueryType type) {
return 0;
}
std::shared_ptr<Kernel::WritableEvent> BufferQueue::GetWritableBufferWaitEvent() const {
return buffer_wait_event.writable;
std::shared_ptr<Kernel::KWritableEvent> BufferQueue::GetWritableBufferWaitEvent() const {
return buffer_wait_event->GetWritableEvent();
}
std::shared_ptr<Kernel::ReadableEvent> BufferQueue::GetBufferWaitEvent() const {
return buffer_wait_event.readable;
std::shared_ptr<Kernel::KReadableEvent> BufferQueue::GetBufferWaitEvent() const {
return buffer_wait_event->GetReadableEvent();
}
} // namespace Service::NVFlinger
@@ -14,12 +14,14 @@
#include "common/math_util.h"
#include "common/swap.h"
#include "core/hle/kernel/object.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/service/nvdrv/nvdata.h"
namespace Kernel {
class KernelCore;
}
class KEvent;
class KReadableEvent;
class KWritableEvent;
} // namespace Kernel
namespace Service::NVFlinger {
@@ -113,9 +115,9 @@ public:
return is_connect;
}
std::shared_ptr<Kernel::WritableEvent> GetWritableBufferWaitEvent() const;
std::shared_ptr<Kernel::KWritableEvent> GetWritableBufferWaitEvent() const;
std::shared_ptr<Kernel::ReadableEvent> GetBufferWaitEvent() const;
std::shared_ptr<Kernel::KReadableEvent> GetBufferWaitEvent() const;
private:
BufferQueue(const BufferQueue&) = delete;
@@ -127,7 +129,7 @@ private:
std::list<u32> free_buffers;
std::array<Buffer, buffer_slots> buffers;
std::list<u32> queue_sequence;
Kernel::EventPair buffer_wait_event;
std::shared_ptr<Kernel::KEvent> buffer_wait_event;
std::mutex free_buffers_mutex;
std::condition_variable free_buffers_condition;
+2 -2
View File
@@ -14,8 +14,8 @@
#include "core/core_timing.h"
#include "core/core_timing_util.h"
#include "core/hardware_properties.h"
#include "core/hle/kernel/k_readable_event.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/service/nvdrv/devices/nvdisp_disp0.h"
#include "core/hle/service/nvdrv/nvdrv.h"
#include "core/hle/service/nvflinger/buffer_queue.h"
@@ -165,7 +165,7 @@ std::optional<u32> NVFlinger::FindBufferQueueId(u64 display_id, u64 layer_id) co
return layer->GetBufferQueue().GetId();
}
std::shared_ptr<Kernel::ReadableEvent> NVFlinger::FindVsyncEvent(u64 display_id) const {
std::shared_ptr<Kernel::KReadableEvent> NVFlinger::FindVsyncEvent(u64 display_id) const {
const auto guard = Lock();
auto* const display = FindDisplay(display_id);
+3 -3
View File
@@ -26,8 +26,8 @@ struct EventType;
} // namespace Core::Timing
namespace Kernel {
class ReadableEvent;
class WritableEvent;
class KReadableEvent;
class KWritableEvent;
} // namespace Kernel
namespace Service::Nvidia {
@@ -72,7 +72,7 @@ public:
/// Gets the vsync event for the specified display.
///
/// If an invalid display ID is provided, then nullptr is returned.
[[nodiscard]] std::shared_ptr<Kernel::ReadableEvent> FindVsyncEvent(u64 display_id) const;
[[nodiscard]] std::shared_ptr<Kernel::KReadableEvent> FindVsyncEvent(u64 display_id) const;
/// Obtains a buffer queue identified by the ID.
[[nodiscard]] BufferQueue* FindBufferQueue(u32 id);
+19 -2
View File
@@ -25,8 +25,8 @@ public:
{10103, &PlayReport::SaveReportWithUser<Core::Reporter::PlayReportType::Old2>, "SaveReportWithUserOld2"},
{10104, &PlayReport::SaveReport<Core::Reporter::PlayReportType::New>, "SaveReport"},
{10105, &PlayReport::SaveReportWithUser<Core::Reporter::PlayReportType::New>, "SaveReportWithUser"},
{10200, nullptr, "RequestImmediateTransmission"},
{10300, nullptr, "GetTransmissionStatus"},
{10200, &PlayReport::RequestImmediateTransmission, "RequestImmediateTransmission"},
{10300, &PlayReport::GetTransmissionStatus, "GetTransmissionStatus"},
{10400, &PlayReport::GetSystemSessionId, "GetSystemSessionId"},
{20100, &PlayReport::SaveSystemReport, "SaveSystemReport"},
{20101, &PlayReport::SaveSystemReportWithUser, "SaveSystemReportWithUser"},
@@ -108,6 +108,23 @@ private:
rb.Push(RESULT_SUCCESS);
}
void RequestImmediateTransmission(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_PREPO, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void GetTransmissionStatus(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_PREPO, "(STUBBED) called");
constexpr s32 status = 0;
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push(status);
}
void GetSystemSessionId(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_PREPO, "(STUBBED) called");
+11 -9
View File
@@ -7,9 +7,10 @@
#include "common/logging/log.h"
#include "core/core.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/k_event.h"
#include "core/hle/kernel/k_readable_event.h"
#include "core/hle/kernel/k_writable_event.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/service/ptm/psm.h"
#include "core/hle/service/service.h"
#include "core/hle/service/sm/sm.h"
@@ -31,27 +32,28 @@ public:
RegisterHandlers(functions);
state_change_event = Kernel::WritableEvent::CreateEventPair(
system_.Kernel(), "IPsmSession::state_change_event");
state_change_event =
Kernel::KEvent::Create(system_.Kernel(), "IPsmSession::state_change_event");
state_change_event->Initialize();
}
~IPsmSession() override = default;
void SignalChargerTypeChanged() {
if (should_signal && should_signal_charger_type) {
state_change_event.writable->Signal();
state_change_event->GetWritableEvent()->Signal();
}
}
void SignalPowerSupplyChanged() {
if (should_signal && should_signal_power_supply) {
state_change_event.writable->Signal();
state_change_event->GetWritableEvent()->Signal();
}
}
void SignalBatteryVoltageStateChanged() {
if (should_signal && should_signal_battery_voltage) {
state_change_event.writable->Signal();
state_change_event->GetWritableEvent()->Signal();
}
}
@@ -63,7 +65,7 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(state_change_event.readable);
rb.PushCopyObjects(state_change_event->GetReadableEvent());
}
void UnbindStateChangeEvent(Kernel::HLERequestContext& ctx) {
@@ -112,7 +114,7 @@ private:
bool should_signal_power_supply{};
bool should_signal_battery_voltage{};
bool should_signal{};
Kernel::EventPair state_change_event;
std::shared_ptr<Kernel::KEvent> state_change_event;
};
class PSM final : public ServiceFramework<PSM> {
@@ -4,7 +4,7 @@
#include "common/assert.h"
#include "core/core.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/kernel/k_event.h"
#include "core/hle/service/time/standard_local_system_clock_core.h"
#include "core/hle/service/time/standard_network_system_clock_core.h"
#include "core/hle/service/time/standard_user_system_clock_core.h"
@@ -18,8 +18,10 @@ StandardUserSystemClockCore::StandardUserSystemClockCore(
local_system_clock_core{local_system_clock_core},
network_system_clock_core{network_system_clock_core}, auto_correction_enabled{},
auto_correction_time{SteadyClockTimePoint::GetRandom()},
auto_correction_event{Kernel::WritableEvent::CreateEventPair(
system.Kernel(), "StandardUserSystemClockCore:AutoCorrectionEvent")} {}
auto_correction_event{Kernel::KEvent::Create(
system.Kernel(), "StandardUserSystemClockCore:AutoCorrectionEvent")} {
auto_correction_event->Initialize();
}
ResultCode StandardUserSystemClockCore::SetAutomaticCorrectionEnabled(Core::System& system,
bool value) {
@@ -4,7 +4,6 @@
#pragma once
#include "core/hle/kernel/writable_event.h"
#include "core/hle/service/time/clock_types.h"
#include "core/hle/service/time/system_clock_core.h"
@@ -12,6 +11,10 @@ namespace Core {
class System;
}
namespace Kernel {
class KEvent;
}
namespace Service::Time::Clock {
class StandardLocalSystemClockCore;
@@ -51,7 +54,7 @@ private:
StandardNetworkSystemClockCore& network_system_clock_core;
bool auto_correction_enabled{};
SteadyClockTimePoint auto_correction_time;
Kernel::EventPair auto_correction_event;
std::shared_ptr<Kernel::KEvent> auto_correction_event;
};
} // namespace Service::Time::Clock
@@ -2,7 +2,7 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "core/hle/kernel/writable_event.h"
#include "core/hle/kernel/k_writable_event.h"
#include "core/hle/service/time/errors.h"
#include "core/hle/service/time/system_clock_context_update_callback.h"
@@ -21,7 +21,7 @@ bool SystemClockContextUpdateCallback::NeedUpdate(const SystemClockContext& valu
}
void SystemClockContextUpdateCallback::RegisterOperationEvent(
std::shared_ptr<Kernel::WritableEvent>&& writable_event) {
std::shared_ptr<Kernel::KWritableEvent>&& writable_event) {
operation_event_list.emplace_back(std::move(writable_event));
}
@@ -9,7 +9,7 @@
#include "core/hle/service/time/clock_types.h"
namespace Kernel {
class WritableEvent;
class KWritableEvent;
}
namespace Service::Time::Clock {
@@ -24,7 +24,7 @@ public:
bool NeedUpdate(const SystemClockContext& value) const;
void RegisterOperationEvent(std::shared_ptr<Kernel::WritableEvent>&& writable_event);
void RegisterOperationEvent(std::shared_ptr<Kernel::KWritableEvent>&& writable_event);
void BroadcastOperationEvent();
@@ -37,7 +37,7 @@ protected:
private:
bool has_context{};
std::vector<std::shared_ptr<Kernel::WritableEvent>> operation_event_list;
std::vector<std::shared_ptr<Kernel::KWritableEvent>> operation_event_list;
};
} // namespace Service::Time::Clock
@@ -9,7 +9,9 @@
#include "common/assert.h"
#include "core/core.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/k_event.h"
#include "core/hle/kernel/k_readable_event.h"
#include "core/hle/kernel/k_writable_event.h"
#include "core/hle/service/vi/display/vi_display.h"
#include "core/hle/service/vi/layer/vi_layer.h"
@@ -17,8 +19,8 @@ namespace Service::VI {
Display::Display(u64 id, std::string name, Core::System& system) : id{id}, name{std::move(name)} {
auto& kernel = system.Kernel();
vsync_event =
Kernel::WritableEvent::CreateEventPair(kernel, fmt::format("Display VSync Event {}", id));
vsync_event = Kernel::KEvent::Create(kernel, fmt::format("Display VSync Event {}", id));
vsync_event->Initialize();
}
Display::~Display() = default;
@@ -31,12 +33,12 @@ const Layer& Display::GetLayer(std::size_t index) const {
return *layers.at(index);
}
std::shared_ptr<Kernel::ReadableEvent> Display::GetVSyncEvent() const {
return vsync_event.readable;
std::shared_ptr<Kernel::KReadableEvent> Display::GetVSyncEvent() const {
return vsync_event->GetReadableEvent();
}
void Display::SignalVSyncEvent() {
vsync_event.writable->Signal();
vsync_event->GetWritableEvent()->Signal();
}
void Display::CreateLayer(u64 id, NVFlinger::BufferQueue& buffer_queue) {
+6 -3
View File
@@ -9,7 +9,10 @@
#include <vector>
#include "common/common_types.h"
#include "core/hle/kernel/writable_event.h"
namespace Kernel {
class KEvent;
}
namespace Service::NVFlinger {
class BufferQueue;
@@ -58,7 +61,7 @@ public:
const Layer& GetLayer(std::size_t index) const;
/// Gets the readable vsync event.
std::shared_ptr<Kernel::ReadableEvent> GetVSyncEvent() const;
std::shared_ptr<Kernel::KReadableEvent> GetVSyncEvent() const;
/// Signals the internal vsync event.
void SignalVSyncEvent();
@@ -99,7 +102,7 @@ private:
std::string name;
std::vector<std::shared_ptr<Layer>> layers;
Kernel::EventPair vsync_event;
std::shared_ptr<Kernel::KEvent> vsync_event;
};
} // namespace Service::VI
+2 -2
View File
@@ -18,9 +18,9 @@
#include "common/swap.h"
#include "core/core_timing.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/k_readable_event.h"
#include "core/hle/kernel/k_thread.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/kernel/k_writable_event.h"
#include "core/hle/service/nvdrv/nvdata.h"
#include "core/hle/service/nvdrv/nvdrv.h"
#include "core/hle/service/nvflinger/buffer_queue.h"
+3
View File
@@ -70,6 +70,9 @@ void LogSettings() {
log_setting("Audio_EnableAudioStretching", values.enable_audio_stretching.GetValue());
log_setting("Audio_OutputDevice", values.audio_device_id);
log_setting("DataStorage_UseVirtualSd", values.use_virtual_sd);
log_setting("DataStorage_CacheDir", Common::FS::GetUserPath(Common::FS::UserPath::CacheDir));
log_setting("DataStorage_ConfigDir", Common::FS::GetUserPath(Common::FS::UserPath::ConfigDir));
log_setting("DataStorage_LoadDir", Common::FS::GetUserPath(Common::FS::UserPath::LoadDir));
log_setting("DataStorage_NandDir", Common::FS::GetUserPath(Common::FS::UserPath::NANDDir));
log_setting("DataStorage_SdmcDir", Common::FS::GetUserPath(Common::FS::UserPath::SDMCDir));
log_setting("Debugging_ProgramArgs", values.program_args);
+9 -5
View File
@@ -2,6 +2,7 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <atomic>
#include <chrono>
#include <cmath>
#include <thread>
@@ -20,13 +21,16 @@ public:
: up(std::move(up_)), down(std::move(down_)), left(std::move(left_)),
right(std::move(right_)), modifier(std::move(modifier_)), modifier_scale(modifier_scale_),
modifier_angle(modifier_angle_) {
update_thread_running.store(true);
update_thread = std::thread(&Analog::UpdateStatus, this);
}
~Analog() override {
update_thread_running = false;
if (update_thread.joinable()) {
update_thread.join();
if (update_thread_running.load()) {
update_thread_running.store(false);
if (update_thread.joinable()) {
update_thread.join();
}
}
}
@@ -58,7 +62,7 @@ public:
}
void UpdateStatus() {
while (update_thread_running) {
while (update_thread_running.load()) {
const float coef = modifier->GetStatus() ? modifier_scale : 1.0f;
bool r = right->GetStatus();
@@ -160,7 +164,7 @@ private:
float angle{};
float amplitude{};
std::thread update_thread;
bool update_thread_running{true};
std::atomic<bool> update_thread_running{};
};
std::unique_ptr<Input::AnalogDevice> AnalogFromButton::Create(const Common::ParamPackage& params) {
+5 -5
View File
@@ -14,7 +14,7 @@
namespace Common {
TEST_CASE("RingBuffer: Basic Tests", "[common]") {
RingBuffer<char, 4, 1> buf;
RingBuffer<char, 4> buf;
// Pushing values into a ring buffer with space should succeed.
for (std::size_t i = 0; i < 4; i++) {
@@ -77,7 +77,7 @@ TEST_CASE("RingBuffer: Basic Tests", "[common]") {
}
TEST_CASE("RingBuffer: Threaded Test", "[common]") {
RingBuffer<char, 4, 2> buf;
RingBuffer<char, 8> buf;
const char seed = 42;
const std::size_t count = 1000000;
std::size_t full = 0;
@@ -92,8 +92,8 @@ TEST_CASE("RingBuffer: Threaded Test", "[common]") {
std::array<char, 2> value = {seed, seed};
std::size_t i = 0;
while (i < count) {
if (const std::size_t c = buf.Push(&value[0], 1); c > 0) {
REQUIRE(c == 1U);
if (const std::size_t c = buf.Push(&value[0], 2); c > 0) {
REQUIRE(c == 2U);
i++;
next_value(value);
} else {
@@ -107,7 +107,7 @@ TEST_CASE("RingBuffer: Threaded Test", "[common]") {
std::array<char, 2> value = {seed, seed};
std::size_t i = 0;
while (i < count) {
if (const std::vector<char> v = buf.Pop(1); v.size() > 0) {
if (const std::vector<char> v = buf.Pop(2); v.size() > 0) {
REQUIRE(v.size() == 2U);
REQUIRE(v[0] == value[0]);
REQUIRE(v[1] == value[1]);
-2
View File
@@ -67,8 +67,6 @@ add_library(video_core STATIC
guest_driver.h
memory_manager.cpp
memory_manager.h
morton.cpp
morton.h
query_cache.h
rasterizer_accelerated.cpp
rasterizer_accelerated.h
+19 -1
View File
@@ -20,6 +20,7 @@ set(SHADER_FILES
find_program(GLSLANGVALIDATOR "glslangValidator" REQUIRED)
set(GLSL_FLAGS "")
set(QUIET_FLAG "--quiet")
set(SHADER_INCLUDE ${CMAKE_CURRENT_BINARY_DIR}/include)
set(SHADER_DIR ${SHADER_INCLUDE}/video_core/host_shaders)
@@ -28,6 +29,23 @@ set(HOST_SHADERS_INCLUDE ${SHADER_INCLUDE} PARENT_SCOPE)
set(INPUT_FILE ${CMAKE_CURRENT_SOURCE_DIR}/source_shader.h.in)
set(HEADER_GENERATOR ${CMAKE_CURRENT_SOURCE_DIR}/StringShaderHeader.cmake)
# Check if `--quiet` is available on host's glslangValidator version
# glslangValidator prints to STDERR iff an unrecognized flag is passed to it
execute_process(
COMMAND
${GLSLANGVALIDATOR} ${QUIET_FLAG}
ERROR_VARIABLE
GLSLANG_ERROR
# STDOUT variable defined to silence unnecessary output during CMake configuration
OUTPUT_VARIABLE
GLSLANG_OUTPUT
)
if (NOT GLSLANG_ERROR STREQUAL "")
message(WARNING "Refusing to use unavailable flag `${QUIET_FLAG}` on `${GLSLANGVALIDATOR}`")
set(QUIET_FLAG "")
endif()
foreach(FILENAME IN ITEMS ${SHADER_FILES})
string(REPLACE "." "_" SHADER_NAME ${FILENAME})
set(SOURCE_FILE ${CMAKE_CURRENT_SOURCE_DIR}/${FILENAME})
@@ -55,7 +73,7 @@ foreach(FILENAME IN ITEMS ${SHADER_FILES})
OUTPUT
${SPIRV_HEADER_FILE}
COMMAND
${GLSLANGVALIDATOR} -V --quiet ${GLSL_FLAGS} --variable-name ${SPIRV_VARIABLE_NAME} -o ${SPIRV_HEADER_FILE} ${SOURCE_FILE}
${GLSLANGVALIDATOR} -V ${QUIET_FLAG} ${GLSL_FLAGS} --variable-name ${SPIRV_VARIABLE_NAME} -o ${SPIRV_HEADER_FILE} ${SOURCE_FILE}
MAIN_DEPENDENCY
${SOURCE_FILE}
)
View File
View File
@@ -580,9 +580,7 @@ void ConfigureInputPlayer::ApplyConfiguration() {
if (player_index == 0) {
auto& handheld = Settings::values.players.GetValue()[HANDHELD_INDEX];
const auto handheld_connected = handheld.connected;
if (player.controller_type == Settings::ControllerType::Handheld) {
handheld = player;
}
handheld = player;
handheld.connected = handheld_connected;
}
}
@@ -596,7 +594,7 @@ void ConfigureInputPlayer::TryConnectSelectedController() {
controller_type != Settings::ControllerType::Handheld;
// Connect Handheld depending on Player 1's controller configuration.
if (player_index == 0 && controller_type == Settings::ControllerType::Handheld) {
if (player_index == 0) {
auto& handheld = Settings::values.players.GetValue()[HANDHELD_INDEX];
const auto handheld_connected = ui->groupConnectedController->isChecked() &&
controller_type == Settings::ControllerType::Handheld;
@@ -886,7 +884,7 @@ void ConfigureInputPlayer::SetConnectableControllers() {
index_controller_type_pairs.clear();
ui->comboControllerType->clear();
if (enable_all || npad_style_set.pro_controller == 1) {
if (enable_all || npad_style_set.fullkey == 1) {
index_controller_type_pairs.emplace_back(ui->comboControllerType->count(),
Settings::ControllerType::ProController);
ui->comboControllerType->addItem(tr("Pro Controller"));
@@ -116,8 +116,8 @@ ConfigureProfileManager ::ConfigureProfileManager(QWidget* parent)
scene = new QGraphicsScene;
ui->current_user_icon->setScene(scene);
SetConfiguration();
RetranslateUI();
SetConfiguration();
}
ConfigureProfileManager::~ConfigureProfileManager() = default;
+3 -3
View File
@@ -13,11 +13,11 @@
#include "core/arm/arm_interface.h"
#include "core/core.h"
#include "core/hle/kernel/handle_table.h"
#include "core/hle/kernel/k_readable_event.h"
#include "core/hle/kernel/k_scheduler.h"
#include "core/hle/kernel/k_synchronization_object.h"
#include "core/hle/kernel/k_thread.h"
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/svc_common.h"
#include "core/hle/kernel/svc_types.h"
#include "core/memory.h"
@@ -193,7 +193,7 @@ std::unique_ptr<WaitTreeSynchronizationObject> WaitTreeSynchronizationObject::ma
const Kernel::KSynchronizationObject& object) {
switch (object.GetHandleType()) {
case Kernel::HandleType::ReadableEvent:
return std::make_unique<WaitTreeEvent>(static_cast<const Kernel::ReadableEvent&>(object));
return std::make_unique<WaitTreeEvent>(static_cast<const Kernel::KReadableEvent&>(object));
case Kernel::HandleType::Thread:
return std::make_unique<WaitTreeThread>(static_cast<const Kernel::KThread&>(object));
default:
@@ -373,7 +373,7 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeThread::GetChildren() const {
return list;
}
WaitTreeEvent::WaitTreeEvent(const Kernel::ReadableEvent& object)
WaitTreeEvent::WaitTreeEvent(const Kernel::KReadableEvent& object)
: WaitTreeSynchronizationObject(object) {}
WaitTreeEvent::~WaitTreeEvent() = default;
+2 -2
View File
@@ -18,9 +18,9 @@ class EmuThread;
namespace Kernel {
class HandleTable;
class KReadableEvent;
class KSynchronizationObject;
class KThread;
class ReadableEvent;
} // namespace Kernel
class WaitTreeThread;
@@ -142,7 +142,7 @@ public:
class WaitTreeEvent : public WaitTreeSynchronizationObject {
Q_OBJECT
public:
explicit WaitTreeEvent(const Kernel::ReadableEvent& object);
explicit WaitTreeEvent(const Kernel::KReadableEvent& object);
~WaitTreeEvent() override;
};