summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/core/CMakeLists.txt5
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_32.cpp5
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_32.h4
-rw-r--r--src/core/hle/kernel/k_light_condition_variable.h57
-rw-r--r--src/core/hle/kernel/k_resource_limit.cpp152
-rw-r--r--src/core/hle/kernel/k_resource_limit.h81
-rw-r--r--src/core/hle/kernel/k_thread.cpp4
-rw-r--r--src/core/hle/kernel/kernel.cpp26
-rw-r--r--src/core/hle/kernel/kernel.h4
-rw-r--r--src/core/hle/kernel/memory/page_table.cpp10
-rw-r--r--src/core/hle/kernel/process.cpp24
-rw-r--r--src/core/hle/kernel/process.h6
-rw-r--r--src/core/hle/kernel/resource_limit.cpp73
-rw-r--r--src/core/hle/kernel/resource_limit.h106
-rw-r--r--src/core/hle/kernel/svc.cpp25
-rw-r--r--src/core/hle/service/acc/profile_manager.cpp10
-rw-r--r--src/core/hle/service/hid/hid.cpp13
-rw-r--r--src/core/hle/service/nifm/nifm.cpp165
-rw-r--r--src/core/settings.cpp3
-rw-r--r--src/yuzu/configuration/configure_profile_manager.cpp2
20 files changed, 535 insertions, 240 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 397cc028f..0ee02c81d 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -160,9 +160,12 @@ 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_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_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
@@ -203,8 +206,6 @@ add_library(core STATIC
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
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
index c650a4dfb..ec4407b6e 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
@@ -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();
}
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.h b/src/core/arm/dynarmic/arm_dynarmic_32.h
index 35e9ced48..f6c4d4db9 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_32.h
+++ b/src/core/arm/dynarmic/arm_dynarmic_32.h
@@ -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;
diff --git a/src/core/hle/kernel/k_light_condition_variable.h b/src/core/hle/kernel/k_light_condition_variable.h
new file mode 100644
index 000000000..362d0db28
--- /dev/null
+++ b/src/core/hle/kernel/k_light_condition_variable.h
@@ -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
diff --git a/src/core/hle/kernel/k_resource_limit.cpp b/src/core/hle/kernel/k_resource_limit.cpp
new file mode 100644
index 000000000..ab2ab683f
--- /dev/null
+++ b/src/core/hle/kernel/k_resource_limit.cpp
@@ -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
diff --git a/src/core/hle/kernel/k_resource_limit.h b/src/core/hle/kernel/k_resource_limit.h
new file mode 100644
index 000000000..58ae456f1
--- /dev/null
+++ b/src/core/hle/kernel/k_resource_limit.h
@@ -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
diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp
index aa100e139..b59259c4f 100644
--- a/src/core/hle/kernel/k_thread.cpp
+++ b/src/core/hle/kernel/k_thread.cpp
@@ -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);
}
}
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index df309d523..b20c2d13a 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -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;
}
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index e7c77727b..806a0d986 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -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;
diff --git a/src/core/hle/kernel/memory/page_table.cpp b/src/core/hle/kernel/memory/page_table.cpp
index 080886554..7de91c768 100644
--- a/src/core/hle/kernel/memory/page_table.cpp
+++ b/src/core/hle/kernel/memory/page_table.cpp
@@ -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;
}
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index 0edbfc4cc..afdb27c54 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -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,6 @@
#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/lock.h"
#include "core/memory.h"
#include "core/settings.h"
@@ -116,7 +116,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 +132,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 +154,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};
@@ -308,13 +308,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 +331,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() {
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h
index 26e647743..c8af76ce8 100644
--- a/src/core/hle/kernel/process.h
+++ b/src/core/hle/kernel/process.h
@@ -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 {
@@ -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;
diff --git a/src/core/hle/kernel/resource_limit.cpp b/src/core/hle/kernel/resource_limit.cpp
deleted file mode 100644
index 7bf50339d..000000000
--- a/src/core/hle/kernel/resource_limit.cpp
+++ /dev/null
@@ -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
diff --git a/src/core/hle/kernel/resource_limit.h b/src/core/hle/kernel/resource_limit.h
deleted file mode 100644
index 464d4f2a6..000000000
--- a/src/core/hle/kernel/resource_limit.h
+++ /dev/null
@@ -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
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 7fd514e9d..74eb90100 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -26,6 +26,7 @@
#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_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"
@@ -37,7 +38,6 @@
#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"
@@ -141,7 +141,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 +151,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 +159,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 +312,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 +1450,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;
{
@@ -1972,7 +1973,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 +2020,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 +2030,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 +2042,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;
}
diff --git a/src/core/hle/service/acc/profile_manager.cpp b/src/core/hle/service/acc/profile_manager.cpp
index d9865d56f..50b2c58e2 100644
--- a/src/core/hle/service/acc/profile_manager.cpp
+++ b/src/core/hle/service/acc/profile_manager.cpp
@@ -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));
}
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 5efc1237e..4cee4838c 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -126,14 +126,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);
diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp
index ef5176bea..8372e170c 100644
--- a/src/core/hle/service/nifm/nifm.cpp
+++ b/src/core/hle/service/nifm/nifm.cpp
@@ -21,6 +21,93 @@ enum class RequestState : u32 {
Connected = 3,
};
+struct IpAddressSetting {
+ bool is_automatic{};
+ Network::IPv4Address current_address{};
+ Network::IPv4Address subnet_mask{};
+ Network::IPv4Address gateway{};
+};
+static_assert(sizeof(IpAddressSetting) == 0xD, "IpAddressSetting has incorrect size.");
+
+struct DnsSetting {
+ bool is_automatic{};
+ Network::IPv4Address primary_dns{};
+ Network::IPv4Address secondary_dns{};
+};
+static_assert(sizeof(DnsSetting) == 0x9, "DnsSetting has incorrect size.");
+
+struct ProxySetting {
+ bool enabled{};
+ INSERT_PADDING_BYTES(1);
+ u16 port{};
+ std::array<char, 0x64> proxy_server{};
+ bool automatic_auth_enabled{};
+ std::array<char, 0x20> user{};
+ std::array<char, 0x20> password{};
+ INSERT_PADDING_BYTES(1);
+};
+static_assert(sizeof(ProxySetting) == 0xAA, "ProxySetting has incorrect size.");
+
+struct IpSettingData {
+ IpAddressSetting ip_address_setting{};
+ DnsSetting dns_setting{};
+ ProxySetting proxy_setting{};
+ u16 mtu{};
+};
+static_assert(sizeof(IpSettingData) == 0xC2, "IpSettingData has incorrect size.");
+
+struct SfWirelessSettingData {
+ u8 ssid_length{};
+ std::array<char, 0x20> ssid{};
+ u8 unknown_1{};
+ u8 unknown_2{};
+ u8 unknown_3{};
+ std::array<char, 0x41> passphrase{};
+};
+static_assert(sizeof(SfWirelessSettingData) == 0x65, "SfWirelessSettingData has incorrect size.");
+
+struct NifmWirelessSettingData {
+ u8 ssid_length{};
+ std::array<char, 0x21> ssid{};
+ u8 unknown_1{};
+ INSERT_PADDING_BYTES(1);
+ u32 unknown_2{};
+ u32 unknown_3{};
+ std::array<char, 0x41> passphrase{};
+ INSERT_PADDING_BYTES(3);
+};
+static_assert(sizeof(NifmWirelessSettingData) == 0x70,
+ "NifmWirelessSettingData has incorrect size.");
+
+#pragma pack(push, 1)
+struct SfNetworkProfileData {
+ IpSettingData ip_setting_data{};
+ u128 uuid{};
+ std::array<char, 0x40> network_name{};
+ u8 unknown_1{};
+ u8 unknown_2{};
+ u8 unknown_3{};
+ u8 unknown_4{};
+ SfWirelessSettingData wireless_setting_data{};
+ INSERT_PADDING_BYTES(1);
+};
+static_assert(sizeof(SfNetworkProfileData) == 0x17C, "SfNetworkProfileData has incorrect size.");
+
+struct NifmNetworkProfileData {
+ u128 uuid{};
+ std::array<char, 0x40> network_name{};
+ u32 unknown_1{};
+ u32 unknown_2{};
+ u8 unknown_3{};
+ u8 unknown_4{};
+ INSERT_PADDING_BYTES(2);
+ NifmWirelessSettingData wireless_setting_data{};
+ IpSettingData ip_setting_data{};
+};
+static_assert(sizeof(NifmNetworkProfileData) == 0x18E,
+ "NifmNetworkProfileData has incorrect size.");
+#pragma pack(pop)
+
class IScanRequest final : public ServiceFramework<IScanRequest> {
public:
explicit IScanRequest(Core::System& system_) : ServiceFramework{system_, "IScanRequest"} {
@@ -128,7 +215,11 @@ 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);
@@ -179,6 +270,46 @@ private:
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IRequest>(system);
}
+ void GetCurrentNetworkProfile(Kernel::HLERequestContext& ctx) {
+ LOG_WARNING(Service_NIFM, "(STUBBED) called");
+
+ const SfNetworkProfileData network_profile_data{
+ .ip_setting_data{
+ .ip_address_setting{
+ .is_automatic{true},
+ .current_address{192, 168, 1, 100},
+ .subnet_mask{255, 255, 255, 0},
+ .gateway{192, 168, 1, 1},
+ },
+ .dns_setting{
+ .is_automatic{true},
+ .primary_dns{1, 1, 1, 1},
+ .secondary_dns{1, 0, 0, 1},
+ },
+ .proxy_setting{
+ .enabled{false},
+ .port{},
+ .proxy_server{},
+ .automatic_auth_enabled{},
+ .user{},
+ .password{},
+ },
+ .mtu{1500},
+ },
+ .uuid{0xdeadbeef, 0xdeadbeef},
+ .network_name{"yuzu Network"},
+ .wireless_setting_data{
+ .ssid_length{12},
+ .ssid{"yuzu Network"},
+ .passphrase{"yuzupassword"},
+ },
+ };
+
+ ctx.WriteBuffer(network_profile_data);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_SUCCESS);
+ }
void RemoveNetworkProfile(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_NIFM, "(STUBBED) called");
@@ -210,6 +341,34 @@ private:
rb.PushIpcInterface<INetworkProfile>(system);
rb.PushRaw<u128>(uuid);
}
+ void GetCurrentIpConfigInfo(Kernel::HLERequestContext& ctx) {
+ LOG_WARNING(Service_NIFM, "(STUBBED) called");
+
+ struct IpConfigInfo {
+ IpAddressSetting ip_address_setting;
+ DnsSetting dns_setting;
+ };
+ static_assert(sizeof(IpConfigInfo) == sizeof(IpAddressSetting) + sizeof(DnsSetting),
+ "IpConfigInfo has incorrect size.");
+
+ const IpConfigInfo ip_config_info{
+ .ip_address_setting{
+ .is_automatic{true},
+ .current_address{192, 168, 1, 100},
+ .subnet_mask{255, 255, 255, 0},
+ .gateway{192, 168, 1, 1},
+ },
+ .dns_setting{
+ .is_automatic{true},
+ .primary_dns{1, 1, 1, 1},
+ .secondary_dns{1, 0, 0, 1},
+ },
+ };
+
+ IPC::ResponseBuilder rb{ctx, 2 + sizeof(IpConfigInfo) / sizeof(u32)};
+ rb.Push(RESULT_SUCCESS);
+ rb.PushRaw<IpConfigInfo>(ip_config_info);
+ }
void IsWirelessCommunicationEnabled(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_NIFM, "(STUBBED) called");
@@ -248,7 +407,7 @@ IGeneralService::IGeneralService(Core::System& system_)
{1, &IGeneralService::GetClientId, "GetClientId"},
{2, &IGeneralService::CreateScanRequest, "CreateScanRequest"},
{4, &IGeneralService::CreateRequest, "CreateRequest"},
- {5, nullptr, "GetCurrentNetworkProfile"},
+ {5, &IGeneralService::GetCurrentNetworkProfile, "GetCurrentNetworkProfile"},
{6, nullptr, "EnumerateNetworkInterfaces"},
{7, nullptr, "EnumerateNetworkProfiles"},
{8, nullptr, "GetNetworkProfile"},
@@ -258,7 +417,7 @@ IGeneralService::IGeneralService(Core::System& system_)
{12, &IGeneralService::GetCurrentIpAddress, "GetCurrentIpAddress"},
{13, nullptr, "GetCurrentAccessPointOld"},
{14, &IGeneralService::CreateTemporaryNetworkProfile, "CreateTemporaryNetworkProfile"},
- {15, nullptr, "GetCurrentIpConfigInfo"},
+ {15, &IGeneralService::GetCurrentIpConfigInfo, "GetCurrentIpConfigInfo"},
{16, nullptr, "SetWirelessCommunicationEnabled"},
{17, &IGeneralService::IsWirelessCommunicationEnabled, "IsWirelessCommunicationEnabled"},
{18, nullptr, "GetInternetConnectionStatus"},
diff --git a/src/core/settings.cpp b/src/core/settings.cpp
index 39306509a..2ae5196e0 100644
--- a/src/core/settings.cpp
+++ b/src/core/settings.cpp
@@ -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);
diff --git a/src/yuzu/configuration/configure_profile_manager.cpp b/src/yuzu/configuration/configure_profile_manager.cpp
index d102a43af..51647a028 100644
--- a/src/yuzu/configuration/configure_profile_manager.cpp
+++ b/src/yuzu/configuration/configure_profile_manager.cpp
@@ -116,8 +116,8 @@ ConfigureProfileManager ::ConfigureProfileManager(QWidget* parent)
scene = new QGraphicsScene;
ui->current_user_icon->setScene(scene);
- SetConfiguration();
RetranslateUI();
+ SetConfiguration();
}
ConfigureProfileManager::~ConfigureProfileManager() = default;