summaryrefslogtreecommitdiffstats
path: root/src/core/hle
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle')
-rw-r--r--src/core/hle/kernel/svc.cpp247
-rw-r--r--src/core/hle/service/am/applets/software_keyboard.cpp4
-rw-r--r--src/core/hle/service/hid/hid.cpp1
-rw-r--r--src/core/hle/service/lm/lm.cpp16
-rw-r--r--src/core/hle/service/ns/pl_u.cpp9
-rw-r--r--src/core/hle/service/olsc/olsc.cpp13
6 files changed, 221 insertions, 69 deletions
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index edf208eff..26650a513 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -368,7 +368,10 @@ static ResultCode GetThreadId(Core::System& system, u64* out_thread_id, Handle t
// Get the thread from its handle.
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle);
- R_UNLESS(thread, Svc::ResultInvalidHandle);
+ if (!thread) {
+ LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={:08X})", thread_handle);
+ return ResultInvalidHandle;
+ }
// Get the thread's id.
*out_thread_id = thread->GetThreadID();
@@ -478,7 +481,10 @@ static ResultCode CancelSynchronization(Core::System& system, Handle thread_hand
// Get the thread from its handle.
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle);
- R_UNLESS(thread, Svc::ResultInvalidHandle);
+ if (!thread) {
+ LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={:08X})", thread_handle);
+ return ResultInvalidHandle;
+ }
// Cancel the thread's wait.
thread->WaitCancel();
@@ -496,8 +502,15 @@ static ResultCode ArbitrateLock(Core::System& system, Handle thread_handle, VAdd
thread_handle, address, tag);
// Validate the input address.
- R_UNLESS(!Memory::IsKernelAddress(address), Svc::ResultInvalidCurrentMemory);
- R_UNLESS(Common::IsAligned(address, sizeof(u32)), Svc::ResultInvalidAddress);
+ if (Memory::IsKernelAddress(address)) {
+ LOG_ERROR(Kernel_SVC, "Attempting to arbitrate a lock on a kernel address (address={:08X})",
+ address);
+ return ResultInvalidCurrentMemory;
+ }
+ if (!Common::IsAligned(address, sizeof(u32))) {
+ LOG_ERROR(Kernel_SVC, "Input address must be 4 byte aligned (address: {:08X})", address);
+ return ResultInvalidAddress;
+ }
return system.Kernel().CurrentProcess()->WaitForAddress(thread_handle, address, tag);
}
@@ -512,8 +525,16 @@ static ResultCode ArbitrateUnlock(Core::System& system, VAddr address) {
LOG_TRACE(Kernel_SVC, "called address=0x{:X}", address);
// Validate the input address.
- R_UNLESS(!Memory::IsKernelAddress(address), Svc::ResultInvalidCurrentMemory);
- R_UNLESS(Common::IsAligned(address, sizeof(u32)), Svc::ResultInvalidAddress);
+ if (Memory::IsKernelAddress(address)) {
+ LOG_ERROR(Kernel_SVC,
+ "Attempting to arbitrate an unlock on a kernel address (address={:08X})",
+ address);
+ return ResultInvalidCurrentMemory;
+ }
+ if (!Common::IsAligned(address, sizeof(u32))) {
+ LOG_ERROR(Kernel_SVC, "Input address must be 4 byte aligned (address: {:08X})", address);
+ return ResultInvalidAddress;
+ }
return system.Kernel().CurrentProcess()->SignalToAddress(address);
}
@@ -1025,37 +1046,47 @@ static ResultCode UnmapPhysicalMemory32(Core::System& system, u32 addr, u32 size
return UnmapPhysicalMemory(system, addr, size);
}
-constexpr bool IsValidThreadActivity(Svc::ThreadActivity thread_activity) {
- switch (thread_activity) {
- case Svc::ThreadActivity::Runnable:
- case Svc::ThreadActivity::Paused:
- return true;
- default:
- return false;
- }
-}
-
/// Sets the thread activity
static ResultCode SetThreadActivity(Core::System& system, Handle thread_handle,
- Svc::ThreadActivity thread_activity) {
+ ThreadActivity thread_activity) {
LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, activity=0x{:08X}", thread_handle,
thread_activity);
// Validate the activity.
- R_UNLESS(IsValidThreadActivity(thread_activity), Svc::ResultInvalidEnumValue);
+ constexpr auto IsValidThreadActivity = [](ThreadActivity activity) {
+ return activity == ThreadActivity::Runnable || activity == ThreadActivity::Paused;
+ };
+ if (!IsValidThreadActivity(thread_activity)) {
+ LOG_ERROR(Kernel_SVC, "Invalid thread activity value provided (activity={})",
+ thread_activity);
+ return ResultInvalidEnumValue;
+ }
// Get the thread from its handle.
auto& kernel = system.Kernel();
const auto& handle_table = kernel.CurrentProcess()->GetHandleTable();
const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle);
- R_UNLESS(thread, Svc::ResultInvalidHandle);
+ if (!thread) {
+ LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={:08X})", thread_handle);
+ return ResultInvalidHandle;
+ }
// Check that the activity is being set on a non-current thread for the current process.
- R_UNLESS(thread->GetOwnerProcess() == kernel.CurrentProcess(), Svc::ResultInvalidHandle);
- R_UNLESS(thread.get() != GetCurrentThreadPointer(kernel), Svc::ResultBusy);
+ if (thread->GetOwnerProcess() != kernel.CurrentProcess()) {
+ LOG_ERROR(Kernel_SVC, "Invalid owning process for the created thread.");
+ return ResultInvalidHandle;
+ }
+ if (thread.get() == GetCurrentThreadPointer(kernel)) {
+ LOG_ERROR(Kernel_SVC, "Thread is busy");
+ return ResultBusy;
+ }
// Set the activity.
- R_TRY(thread->SetActivity(thread_activity));
+ const auto set_result = thread->SetActivity(thread_activity);
+ if (set_result.IsError()) {
+ LOG_ERROR(Kernel_SVC, "Failed to set thread activity.");
+ return set_result;
+ }
return RESULT_SUCCESS;
}
@@ -1074,16 +1105,29 @@ static ResultCode GetThreadContext(Core::System& system, VAddr out_context, Hand
const auto* current_process = system.Kernel().CurrentProcess();
const std::shared_ptr<KThread> thread =
current_process->GetHandleTable().Get<KThread>(thread_handle);
- R_UNLESS(thread, Svc::ResultInvalidHandle);
+ if (!thread) {
+ LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={})", thread_handle);
+ return ResultInvalidHandle;
+ }
// Require the handle be to a non-current thread in the current process.
- R_UNLESS(thread->GetOwnerProcess() == current_process, Svc::ResultInvalidHandle);
- R_UNLESS(thread.get() != system.Kernel().CurrentScheduler()->GetCurrentThread(),
- Svc::ResultBusy);
+ if (thread->GetOwnerProcess() != current_process) {
+ LOG_ERROR(Kernel_SVC, "Thread owning process is not the current process.");
+ return ResultInvalidHandle;
+ }
+ if (thread.get() == system.Kernel().CurrentScheduler()->GetCurrentThread()) {
+ LOG_ERROR(Kernel_SVC, "Current thread is busy.");
+ return ResultBusy;
+ }
// Get the thread context.
std::vector<u8> context;
- R_TRY(thread->GetThreadContext3(context));
+ const auto context_result = thread->GetThreadContext3(context);
+ if (context_result.IsError()) {
+ LOG_ERROR(Kernel_SVC, "Unable to successfully retrieve thread context (result: {})",
+ context_result.raw);
+ return context_result;
+ }
// Copy the thread context to user space.
system.Memory().WriteBlock(out_context, context.data(), context.size());
@@ -1102,7 +1146,10 @@ static ResultCode GetThreadPriority(Core::System& system, u32* out_priority, Han
// Get the thread from its handle.
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(handle);
- R_UNLESS(thread, Svc::ResultInvalidHandle);
+ if (!thread) {
+ LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={:08X})", handle);
+ return ResultInvalidHandle;
+ }
// Get the thread's priority.
*out_priority = thread->GetPriority();
@@ -1118,13 +1165,18 @@ static ResultCode SetThreadPriority(Core::System& system, Handle handle, u32 pri
LOG_TRACE(Kernel_SVC, "called");
// Validate the priority.
- R_UNLESS(Svc::HighestThreadPriority <= priority && priority <= Svc::LowestThreadPriority,
- Svc::ResultInvalidPriority);
+ if (HighestThreadPriority > priority || priority > LowestThreadPriority) {
+ LOG_ERROR(Kernel_SVC, "Invalid thread priority specified (priority={})", priority);
+ return ResultInvalidPriority;
+ }
// Get the thread from its handle.
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(handle);
- R_UNLESS(thread, Svc::ResultInvalidHandle);
+ if (!thread) {
+ LOG_ERROR(Kernel_SVC, "Invalid handle provided (handle={:08X})", handle);
+ return ResultInvalidHandle;
+ }
// Set the thread priority.
thread->SetBasePriority(priority);
@@ -1440,17 +1492,28 @@ static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr e
// Adjust core id, if it's the default magic.
auto& kernel = system.Kernel();
auto& process = *kernel.CurrentProcess();
- if (core_id == Svc::IdealCoreUseProcessValue) {
+ if (core_id == IdealCoreUseProcessValue) {
core_id = process.GetIdealCoreId();
}
// Validate arguments.
- R_UNLESS(IsValidCoreId(core_id), Svc::ResultInvalidCoreId);
- R_UNLESS(((1ULL << core_id) & process.GetCoreMask()) != 0, Svc::ResultInvalidCoreId);
+ if (!IsValidCoreId(core_id)) {
+ LOG_ERROR(Kernel_SVC, "Invalid Core ID specified (id={})", core_id);
+ return ResultInvalidCoreId;
+ }
+ if (((1ULL << core_id) & process.GetCoreMask()) == 0) {
+ LOG_ERROR(Kernel_SVC, "Core ID doesn't fall within allowable cores (id={})", core_id);
+ return ResultInvalidCoreId;
+ }
- R_UNLESS(Svc::HighestThreadPriority <= priority && priority <= Svc::LowestThreadPriority,
- Svc::ResultInvalidPriority);
- R_UNLESS(process.CheckThreadPriority(priority), Svc::ResultInvalidPriority);
+ if (HighestThreadPriority > priority || priority > LowestThreadPriority) {
+ LOG_ERROR(Kernel_SVC, "Invalid priority specified (priority={})", priority);
+ return ResultInvalidPriority;
+ }
+ if (!process.CheckThreadPriority(priority)) {
+ LOG_ERROR(Kernel_SVC, "Invalid allowable thread priority (priority={})", priority);
+ return ResultInvalidPriority;
+ }
ASSERT(process.GetResourceLimit()->Reserve(
LimitableResource::Threads, 1, system.CoreTiming().GetGlobalTimeNs().count() + 100000000));
@@ -1489,10 +1552,19 @@ static ResultCode StartThread(Core::System& system, Handle thread_handle) {
// Get the thread from its handle.
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle);
- R_UNLESS(thread, Svc::ResultInvalidHandle);
+ if (!thread) {
+ LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={:08X})", thread_handle);
+ return ResultInvalidHandle;
+ }
// Try to start the thread.
- R_TRY(thread->Run());
+ const auto run_result = thread->Run();
+ if (run_result.IsError()) {
+ LOG_ERROR(Kernel_SVC,
+ "Unable to successfuly start thread (thread handle={:08X}, result={})",
+ thread_handle, run_result.raw);
+ return run_result;
+ }
return RESULT_SUCCESS;
}
@@ -1553,8 +1625,14 @@ static ResultCode WaitProcessWideKeyAtomic(Core::System& system, VAddr address,
cv_key, tag, timeout_ns);
// Validate input.
- R_UNLESS(!Memory::IsKernelAddress(address), Svc::ResultInvalidCurrentMemory);
- R_UNLESS(Common::IsAligned(address, sizeof(int32_t)), Svc::ResultInvalidAddress);
+ if (Memory::IsKernelAddress(address)) {
+ LOG_ERROR(Kernel_SVC, "Attempted to wait on kernel address (address={:08X})", address);
+ return ResultInvalidCurrentMemory;
+ }
+ if (!Common::IsAligned(address, sizeof(s32))) {
+ LOG_ERROR(Kernel_SVC, "Address must be 4 byte aligned (address={:08X})", address);
+ return ResultInvalidAddress;
+ }
// Convert timeout from nanoseconds to ticks.
s64 timeout{};
@@ -1629,9 +1707,18 @@ static ResultCode WaitForAddress(Core::System& system, VAddr address, Svc::Arbit
address, arb_type, value, timeout_ns);
// Validate input.
- R_UNLESS(!Memory::IsKernelAddress(address), Svc::ResultInvalidCurrentMemory);
- R_UNLESS(Common::IsAligned(address, sizeof(int32_t)), Svc::ResultInvalidAddress);
- R_UNLESS(IsValidArbitrationType(arb_type), Svc::ResultInvalidEnumValue);
+ if (Memory::IsKernelAddress(address)) {
+ LOG_ERROR(Kernel_SVC, "Attempting to wait on kernel address (address={:08X})", address);
+ return ResultInvalidCurrentMemory;
+ }
+ if (!Common::IsAligned(address, sizeof(s32))) {
+ LOG_ERROR(Kernel_SVC, "Wait address must be 4 byte aligned (address={:08X})", address);
+ return ResultInvalidAddress;
+ }
+ if (!IsValidArbitrationType(arb_type)) {
+ LOG_ERROR(Kernel_SVC, "Invalid arbitration type specified (type={})", arb_type);
+ return ResultInvalidEnumValue;
+ }
// Convert timeout from nanoseconds to ticks.
s64 timeout{};
@@ -1665,9 +1752,18 @@ static ResultCode SignalToAddress(Core::System& system, VAddr address, Svc::Sign
address, signal_type, value, count);
// Validate input.
- R_UNLESS(!Memory::IsKernelAddress(address), Svc::ResultInvalidCurrentMemory);
- R_UNLESS(Common::IsAligned(address, sizeof(s32)), Svc::ResultInvalidAddress);
- R_UNLESS(IsValidSignalType(signal_type), Svc::ResultInvalidEnumValue);
+ if (Memory::IsKernelAddress(address)) {
+ LOG_ERROR(Kernel_SVC, "Attempting to signal to a kernel address (address={:08X})", address);
+ return ResultInvalidCurrentMemory;
+ }
+ if (!Common::IsAligned(address, sizeof(s32))) {
+ LOG_ERROR(Kernel_SVC, "Signaled address must be 4 byte aligned (address={:08X})", address);
+ return ResultInvalidAddress;
+ }
+ if (!IsValidSignalType(signal_type)) {
+ LOG_ERROR(Kernel_SVC, "Invalid signal type specified (type={})", signal_type);
+ return ResultInvalidEnumValue;
+ }
return system.Kernel().CurrentProcess()->SignalAddressArbiter(address, signal_type, value,
count);
@@ -1815,10 +1911,17 @@ static ResultCode GetThreadCoreMask(Core::System& system, Handle thread_handle,
// Get the thread from its handle.
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle);
- R_UNLESS(thread, Svc::ResultInvalidHandle);
+ if (!thread) {
+ LOG_ERROR(Kernel_SVC, "Invalid thread handle specified (handle={:08X})", thread_handle);
+ return ResultInvalidHandle;
+ }
// Get the core mask.
- R_TRY(thread->GetCoreMask(out_core_id, out_affinity_mask));
+ const auto result = thread->GetCoreMask(out_core_id, out_affinity_mask);
+ if (result.IsError()) {
+ LOG_ERROR(Kernel_SVC, "Unable to successfully retrieve core mask (result={})", result.raw);
+ return result;
+ }
return RESULT_SUCCESS;
}
@@ -1846,26 +1949,46 @@ static ResultCode SetThreadCoreMask(Core::System& system, Handle thread_handle,
} else {
// Validate the affinity mask.
const u64 process_core_mask = current_process.GetCoreMask();
- R_UNLESS((affinity_mask | process_core_mask) == process_core_mask,
- Svc::ResultInvalidCoreId);
- R_UNLESS(affinity_mask != 0, Svc::ResultInvalidCombination);
+ if ((affinity_mask | process_core_mask) != process_core_mask) {
+ LOG_ERROR(Kernel_SVC,
+ "Affinity mask does match the process core mask (affinity mask={:016X}, core "
+ "mask={:016X})",
+ affinity_mask, process_core_mask);
+ return ResultInvalidCoreId;
+ }
+ if (affinity_mask == 0) {
+ LOG_ERROR(Kernel_SVC, "Affinity mask is zero.");
+ return ResultInvalidCombination;
+ }
// Validate the core id.
if (IsValidCoreId(core_id)) {
- R_UNLESS(((1ULL << core_id) & affinity_mask) != 0, Svc::ResultInvalidCombination);
+ if (((1ULL << core_id) & affinity_mask) == 0) {
+ LOG_ERROR(Kernel_SVC, "Invalid core ID (ID={})", core_id);
+ return ResultInvalidCombination;
+ }
} else {
- R_UNLESS(core_id == Svc::IdealCoreNoUpdate || core_id == Svc::IdealCoreDontCare,
- Svc::ResultInvalidCoreId);
+ if (core_id != IdealCoreNoUpdate && core_id != IdealCoreDontCare) {
+ LOG_ERROR(Kernel_SVC, "Invalid core ID (ID={})", core_id);
+ return ResultInvalidCoreId;
+ }
}
}
// Get the thread from its handle.
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle);
- R_UNLESS(thread, Svc::ResultInvalidHandle);
+ if (!thread) {
+ LOG_ERROR(Kernel_SVC, "Invalid thread handle (handle={:08X})", thread_handle);
+ return ResultInvalidHandle;
+ }
// Set the core mask.
- R_TRY(thread->SetCoreMask(core_id, affinity_mask));
+ const auto set_result = thread->SetCoreMask(core_id, affinity_mask);
+ if (set_result.IsError()) {
+ LOG_ERROR(Kernel_SVC, "Unable to successfully set core mask (result={})", set_result.raw);
+ return set_result;
+ }
return RESULT_SUCCESS;
}
@@ -1884,7 +2007,10 @@ static ResultCode SignalEvent(Core::System& system, Handle event_handle) {
// Get the writable event.
auto writable_event = handle_table.Get<KWritableEvent>(event_handle);
- R_UNLESS(writable_event, Svc::ResultInvalidHandle);
+ if (!writable_event) {
+ LOG_ERROR(Kernel_SVC, "Invalid event handle provided (handle={:08X})", event_handle);
+ return ResultInvalidHandle;
+ }
return writable_event->Signal();
}
@@ -1933,7 +2059,10 @@ static ResultCode CreateEvent(Core::System& system, Handle* out_write, Handle* o
// Create a new event.
const auto event = KEvent::Create(kernel, "CreateEvent");
- R_UNLESS(event != nullptr, Svc::ResultOutOfResource);
+ if (!event) {
+ LOG_ERROR(Kernel_SVC, "Unable to create new events. Event creation limit reached.");
+ return ResultOutOfResource;
+ }
// Initialize the event.
event->Initialize();
diff --git a/src/core/hle/service/am/applets/software_keyboard.cpp b/src/core/hle/service/am/applets/software_keyboard.cpp
index 3022438b1..79b209c6b 100644
--- a/src/core/hle/service/am/applets/software_keyboard.cpp
+++ b/src/core/hle/service/am/applets/software_keyboard.cpp
@@ -121,6 +121,10 @@ void SoftwareKeyboard::ExecuteInteractive() {
std::memcpy(&request, data.data(), sizeof(Request));
switch (request) {
+ case Request::Finalize:
+ complete = true;
+ broker.SignalStateChanged();
+ break;
case Request::Calc: {
broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::vector<u8>{1}));
broker.SignalStateChanged();
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 51a010a55..1e2677320 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -110,6 +110,7 @@ void IAppletResource::DeactivateController(HidController controller) {
IAppletResource ::~IAppletResource() {
system.CoreTiming().UnscheduleEvent(pad_update_event, 0);
+ system.CoreTiming().UnscheduleEvent(motion_update_event, 0);
}
void IAppletResource::GetSharedMemoryHandle(Kernel::HLERequestContext& ctx) {
diff --git a/src/core/hle/service/lm/lm.cpp b/src/core/hle/service/lm/lm.cpp
index 2a6d43d2a..7d7542fc2 100644
--- a/src/core/hle/service/lm/lm.cpp
+++ b/src/core/hle/service/lm/lm.cpp
@@ -143,17 +143,19 @@ private:
rb.Push(RESULT_SUCCESS);
}
- u32 ReadLeb128(const std::vector<u8>& data, std::size_t& offset) {
- u32 result{};
+ u64 ReadLeb128(const std::vector<u8>& data, std::size_t& offset) {
+ u64 result{};
u32 shift{};
- do {
- result |= (data[offset] & 0x7f) << shift;
+
+ for (std::size_t i = 0; i < sizeof(u64); i++) {
+ const auto v = data[offset];
+ result |= (static_cast<u64>(v & 0x7f) << shift);
shift += 7;
offset++;
- if (offset >= data.size()) {
+ if (offset >= data.size() || ((v & 0x80) == 0)) {
break;
}
- } while ((data[offset] & 0x80) != 0);
+ }
return result;
}
@@ -262,7 +264,7 @@ private:
switch (entry.severity) {
case LogSeverity::Trace:
- LOG_DEBUG(Service_LM, "LogManager DEBUG ({}):\n{}", DestinationToString(destination),
+ LOG_DEBUG(Service_LM, "LogManager TRACE ({}):\n{}", DestinationToString(destination),
output_log);
break;
case LogSeverity::Info:
diff --git a/src/core/hle/service/ns/pl_u.cpp b/src/core/hle/service/ns/pl_u.cpp
index 71c7587db..b6ac0a81a 100644
--- a/src/core/hle/service/ns/pl_u.cpp
+++ b/src/core/hle/service/ns/pl_u.cpp
@@ -65,13 +65,18 @@ static void DecryptSharedFont(const std::vector<u32>& input, Kernel::PhysicalMem
void DecryptSharedFontToTTF(const std::vector<u32>& input, std::vector<u8>& output) {
ASSERT_MSG(input[0] == EXPECTED_MAGIC, "Failed to derive key, unexpected magic number");
+ if (input.size() < 2) {
+ LOG_ERROR(Service_NS, "Input font is empty");
+ return;
+ }
+
const u32 KEY = input[0] ^ EXPECTED_RESULT; // Derive key using an inverse xor
std::vector<u32> transformed_font(input.size());
// TODO(ogniK): Figure out a better way to do this
std::transform(input.begin(), input.end(), transformed_font.begin(),
[&KEY](u32 font_data) { return Common::swap32(font_data ^ KEY); });
- transformed_font[1] = Common::swap32(transformed_font[1]) ^ KEY; // "re-encrypt" the size
- std::memcpy(output.data(), transformed_font.data() + 2, transformed_font.size() * sizeof(u32));
+ std::memcpy(output.data(), transformed_font.data() + 2,
+ (transformed_font.size() - 2) * sizeof(u32));
}
void EncryptSharedFont(const std::vector<u32>& input, std::vector<u8>& output,
diff --git a/src/core/hle/service/olsc/olsc.cpp b/src/core/hle/service/olsc/olsc.cpp
index 4440135ed..e2ac71fa1 100644
--- a/src/core/hle/service/olsc/olsc.cpp
+++ b/src/core/hle/service/olsc/olsc.cpp
@@ -17,7 +17,7 @@ public:
static const FunctionInfo functions[] = {
{0, &OLSC::Initialize, "Initialize"},
{10, nullptr, "VerifySaveDataBackupLicenseAsync"},
- {13, nullptr, "GetSaveDataBackupSetting"},
+ {13, &OLSC::GetSaveDataBackupSetting, "GetSaveDataBackupSetting"},
{14, &OLSC::SetSaveDataBackupSettingEnabled, "SetSaveDataBackupSettingEnabled"},
{15, nullptr, "SetCustomData"},
{16, nullptr, "DeleteSaveDataBackupSetting"},
@@ -52,6 +52,17 @@ private:
rb.Push(RESULT_SUCCESS);
}
+ void GetSaveDataBackupSetting(Kernel::HLERequestContext& ctx) {
+ LOG_WARNING(Service_OLSC, "(STUBBED) called");
+
+ // backup_setting is set to 0 since real value is unknown
+ constexpr u64 backup_setting = 0;
+
+ IPC::ResponseBuilder rb{ctx, 4};
+ rb.Push(RESULT_SUCCESS);
+ rb.Push(backup_setting);
+ }
+
void SetSaveDataBackupSettingEnabled(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_OLSC, "(STUBBED) called");