aboutsummaryrefslogtreecommitdiff
path: root/src/core/hle/kernel
diff options
context:
space:
mode:
authorlizzie <lizzie@eden-emu.dev>2026-09-08 20:39:55 +0200
committercrueter <crueter@eden-emu.dev>2026-09-08 20:39:55 +0200
commit87e5d0b6e490d56fbbe4e770a80e2fbd31aff2ae (patch)
tree3274ca98337fbad75c0386dbcd2cae70431e1dad /src/core/hle/kernel
parentfdd8d4252c60b055cac2d792b414ba15046d484d (diff)
[hle] VirtualBoy classics fixes, QLaunch IPC fixes, implement extra ams SVCInfo (#4343)
Signed-off-by: lizzie <lizzie@eden-emu.dev> - [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions). - [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md) - [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability. ------------------- `OpenSystemApplicationProxy` `OpenSystemApplicationProxy` ALSO yes those cmds DO NOT take an attribute Implemented SVC infos to match Atmosphere's values Implement more stub I2C session cmds stub CMD2103 for rhythm groove better error handling on svc get info to match ams (see ams svc info) Virtual Boy classic fix adept from https://git.ryujinx.app/projects/Kenji-NX/commit/2288084b531b185f5840a696b23265014f07e2f2 by @Mythrax acc:u1 was missing the *Deprecated cmd Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4343 Reviewed-by: CamilleLaVey <camillelavey99@gmail.com> Reviewed-by: Maufeat <sahyno1996@gmail.com>
Diffstat (limited to 'src/core/hle/kernel')
-rw-r--r--src/core/hle/kernel/svc/svc_info.cpp128
1 files changed, 57 insertions, 71 deletions
diff --git a/src/core/hle/kernel/svc/svc_info.cpp b/src/core/hle/kernel/svc/svc_info.cpp
index 4487fa5cfd..e6190ac33a 100644
--- a/src/core/hle/kernel/svc/svc_info.cpp
+++ b/src/core/hle/kernel/svc/svc_info.cpp
@@ -10,17 +10,15 @@
#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/k_resource_limit.h"
#include "core/hle/kernel/svc.h"
+#include "core/hle/kernel/svc_results.h"
+#include "core/hle/kernel/svc_version.h"
namespace Kernel::Svc {
/// Gets system/memory information for the current process
-Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle handle,
- u64 info_sub_id) {
- LOG_TRACE(Kernel_SVC, "called info_id={:#x}, info_sub_id={:#x}, handle={:#08x}",
- info_id_type, info_sub_id, handle);
-
- u32 info_id = static_cast<u32>(info_id_type);
-
+Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle handle, u64 info_sub_id) {
+ LOG_TRACE(Kernel_SVC, "called info_id={:#x}, info_sub_id={:#x}, handle={:#08x}", info_id_type, info_sub_id, handle);
+ u32 info_id = u32(info_id_type);
switch (info_id_type) {
case InfoType::CoreMask:
case InfoType::PriorityMask:
@@ -53,152 +51,123 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle
case InfoType::CoreMask:
*result = process->GetCoreMask();
R_SUCCEED();
-
case InfoType::PriorityMask:
*result = process->GetPriorityMask();
R_SUCCEED();
-
case InfoType::AliasRegionAddress:
*result = GetInteger(process->GetPageTable().GetAliasRegionStart());
R_SUCCEED();
-
case InfoType::AliasRegionSize:
*result = process->GetPageTable().GetAliasRegionSize();
R_SUCCEED();
case InfoType::HeapRegionAddress:
*result = GetInteger(process->GetPageTable().GetHeapRegionStart());
R_SUCCEED();
-
case InfoType::HeapRegionSize:
*result = process->GetPageTable().GetHeapRegionSize();
R_SUCCEED();
-
case InfoType::AslrRegionAddress:
*result = GetInteger(process->GetPageTable().GetAliasCodeRegionStart());
R_SUCCEED();
-
case InfoType::AslrRegionSize:
*result = process->GetPageTable().GetAliasCodeRegionSize();
R_SUCCEED();
-
case InfoType::StackRegionAddress:
*result = GetInteger(process->GetPageTable().GetStackRegionStart());
R_SUCCEED();
-
case InfoType::StackRegionSize:
*result = process->GetPageTable().GetStackRegionSize();
R_SUCCEED();
-
case InfoType::TotalMemorySize:
*result = process->GetTotalUserPhysicalMemorySize(system.Kernel());
R_SUCCEED();
-
case InfoType::UsedMemorySize:
*result = process->GetUsedUserPhysicalMemorySize(system.Kernel());
R_SUCCEED();
-
case InfoType::SystemResourceSizeTotal:
*result = process->GetTotalSystemResourceSize();
R_SUCCEED();
-
case InfoType::SystemResourceSizeUsed:
*result = process->GetUsedSystemResourceSize();
R_SUCCEED();
-
case InfoType::ProgramId:
*result = process->GetProgramId();
R_SUCCEED();
-
case InfoType::UserExceptionContextAddress:
*result = GetInteger(process->GetProcessLocalRegionAddress());
R_SUCCEED();
-
case InfoType::TotalNonSystemMemorySize:
*result = process->GetTotalNonSystemUserPhysicalMemorySize(system.Kernel());
R_SUCCEED();
-
case InfoType::UsedNonSystemMemorySize:
*result = process->GetUsedNonSystemUserPhysicalMemorySize(system.Kernel());
R_SUCCEED();
-
case InfoType::IsApplication:
*result = process->IsApplication();
R_SUCCEED();
-
case InfoType::FreeThreadCount:
if (KResourceLimit* resource_limit = process->GetResourceLimit();
resource_limit != nullptr) {
- const auto current_value =
- resource_limit->GetCurrentValue(Svc::LimitableResource::ThreadCountMax);
- const auto limit_value =
- resource_limit->GetLimitValue(Svc::LimitableResource::ThreadCountMax);
+ const auto current_value = resource_limit->GetCurrentValue(Svc::LimitableResource::ThreadCountMax);
+ const auto limit_value = resource_limit->GetLimitValue(Svc::LimitableResource::ThreadCountMax);
*result = limit_value - current_value;
} else {
*result = 0;
}
R_SUCCEED();
-
case InfoType::AliasRegionExtraSize: {
- if (info_sub_id != 0) {
- return ResultInvalidCombination;
- }
-
+ R_UNLESS(info_sub_id == 0, ResultInvalidCombination);
KProcess* current_process = GetCurrentProcessPointer(system.Kernel());
*result = current_process->GetPageTable().GetAliasRegionExtraSize();
-
R_SUCCEED();
}
-
default:
break;
}
-
LOG_ERROR(Kernel_SVC, "Unimplemented svcGetInfo id={:#016x}", info_id);
R_THROW(ResultInvalidEnumValue);
}
-
case InfoType::DebuggerAttached:
*result = 0;
R_SUCCEED();
-
case InfoType::ResourceLimit: {
R_UNLESS(handle == 0, ResultInvalidHandle);
R_UNLESS(info_sub_id == 0, ResultInvalidCombination);
-
KProcess* const current_process = GetCurrentProcessPointer(system.Kernel());
KHandleTable& handle_table = current_process->GetHandleTable();
- const auto resource_limit = current_process->GetResourceLimit();
- if (!resource_limit) {
+ if (auto const resource_limit = current_process->GetResourceLimit(); resource_limit) {
+ Handle resource_handle{};
+ R_TRY(handle_table.Add(system.Kernel(), std::addressof(resource_handle), resource_limit));
+ *result = resource_handle;
+ } else {
*result = Svc::InvalidHandle;
- // Yes, the kernel considers this a successful operation.
- R_SUCCEED();
}
-
- Handle resource_handle{};
- R_TRY(handle_table.Add(system.Kernel(), std::addressof(resource_handle), resource_limit));
-
- *result = resource_handle;
+ // Yes, the kernel considers this a successful operation either way.
R_SUCCEED();
}
-
case InfoType::RandomEntropy:
R_UNLESS(handle == 0, ResultInvalidHandle);
R_UNLESS(info_sub_id < 4, ResultInvalidCombination);
-
*result = GetCurrentProcess(system.Kernel()).GetRandomEntropy(info_sub_id);
R_SUCCEED();
-
- case InfoType::InitialProcessIdRange:
- LOG_WARNING(Kernel_SVC,
- "(STUBBED) Attempted to query privileged process id bounds, returned 0");
- *result = 0;
- R_SUCCEED();
-
+ case InfoType::InitialProcessIdRange: {
+ LOG_WARNING(Kernel_SVC, "(STUBBED) Attempted to query privileged process id bounds, returned 0/64");
+ R_UNLESS(handle == InvalidHandle, ResultInvalidHandle);
+ switch (InitialProcessIdRangeInfo(info_sub_id)) {
+ case InitialProcessIdRangeInfo::Minimum:
+ *result = 0; //todo
+ R_SUCCEED();
+ case InitialProcessIdRangeInfo::Maximum:
+ *result = 64; //todo
+ R_SUCCEED();
+ default:
+ R_THROW(ResultInvalidCombination);
+ }
+ }
case InfoType::ThreadTickCount: {
constexpr u64 num_cpus = 4;
if (info_sub_id != 0xFFFFFFFFFFFFFFFF && info_sub_id >= num_cpus) {
- LOG_ERROR(Kernel_SVC, "Core count is out of range, expected {} but got {}", num_cpus,
- info_sub_id);
+ LOG_ERROR(Kernel_SVC, "Core count is out of range, expected {} but got {}", num_cpus, info_sub_id);
R_THROW(ResultInvalidCombination);
}
@@ -206,8 +175,7 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle
.GetHandleTable()
.GetObject<KThread>(system.Kernel(), Handle(handle));
if (thread.IsNull()) {
- LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle={:#08x}",
- static_cast<Handle>(handle));
+ LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle={:#08x}", Handle(handle));
R_THROW(ResultInvalidHandle);
}
@@ -220,7 +188,6 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle
u64 out_ticks = 0;
if (same_thread && info_sub_id == 0xFFFFFFFFFFFFFFFF) {
const u64 thread_ticks = current_thread->GetCpuTime();
-
out_ticks = thread_ticks + (core_timing.GetClockTicks() - prev_ctx_ticks);
} else if (same_thread && info_sub_id == system.Kernel().CurrentPhysicalCoreIndex()) {
out_ticks = core_timing.GetClockTicks() - prev_ctx_ticks;
@@ -230,19 +197,40 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle
R_SUCCEED();
}
case InfoType::IdleTickCount: {
- // Verify the input handle is invalid.
- R_UNLESS(handle == InvalidHandle, ResultInvalidHandle);
-
// Verify the requested core is valid.
const bool core_valid =
- (info_sub_id == 0xFFFFFFFFFFFFFFFF) ||
- (info_sub_id == static_cast<u64>(system.Kernel().CurrentPhysicalCoreIndex()));
+ (info_sub_id == 0xFFFFFFFFFFFFFFFF)
+ || (info_sub_id == u64(system.Kernel().CurrentPhysicalCoreIndex()));
R_UNLESS(core_valid, ResultInvalidCombination);
+ // Verify the input handle is invalid.
+ R_UNLESS(handle == InvalidHandle, ResultInvalidHandle);
+
// Get the idle tick count.
*result = system.Kernel().CurrentScheduler()->GetIdleThread()->GetCpuTime();
R_SUCCEED();
}
+ case InfoType::MesosphereMeta: {
+ enum MesosphereMetaInfo : u64 {
+ KernelVersion = 0,
+ IsKTraceEnabled = 1,
+ IsSingleStepEnabled = 2,
+ };
+ R_UNLESS(handle == InvalidHandle, ResultInvalidHandle);
+ switch (MesosphereMetaInfo(info_sub_id)) {
+ case MesosphereMetaInfo::KernelVersion:
+ *result = Kernel::Svc::SupportedKernelVersion;
+ R_SUCCEED();
+ case MesosphereMetaInfo::IsKTraceEnabled:
+ *result = 0;
+ R_SUCCEED();
+ case MesosphereMetaInfo::IsSingleStepEnabled:
+ *result = 0;
+ R_SUCCEED();
+ default:
+ R_THROW(ResultInvalidCombination);
+ }
+ }
case InfoType::MesosphereCurrentProcess: {
// Verify the input handle is invalid.
R_UNLESS(handle == InvalidHandle, ResultInvalidHandle);
@@ -255,13 +243,11 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle
KHandleTable& handle_table = current_process->GetHandleTable();
// Get a new handle for the current process.
- Handle tmp;
+ Handle tmp{};
R_TRY(handle_table.Add(system.Kernel(), std::addressof(tmp), current_process));
// Set the output.
*result = tmp;
-
- // We succeeded.
R_SUCCEED();
}
default: