diff options
Diffstat (limited to 'src/core/hle')
23 files changed, 521 insertions, 258 deletions
diff --git a/src/core/hle/config_mem.cpp b/src/core/hle/config_mem.cpp index 35dc9cf5..aea936d2 100644 --- a/src/core/hle/config_mem.cpp +++ b/src/core/hle/config_mem.cpp @@ -9,59 +9,14 @@ #include "common/common_funcs.h" #include "core/core.h" -#include "core/mem_map.h" +#include "core/memory.h" #include "core/hle/config_mem.h" //////////////////////////////////////////////////////////////////////////////////////////////////// namespace ConfigMem { -struct ConfigMemDef { - u8 kernel_unk; // 0 - u8 kernel_version_rev; // 1 - u8 kernel_version_min; // 2 - u8 kernel_version_maj; // 3 - u32 update_flag; // 4 - u64 ns_tid; // 8 - u32 sys_core_ver; // 10 - u8 unit_info; // 14 - u8 boot_firm; // 15 - u8 prev_firm; // 16 - INSERT_PADDING_BYTES(0x1); // 17 - u32 ctr_sdk_ver; // 18 - INSERT_PADDING_BYTES(0x30 - 0x1C); // 1C - u32 app_mem_type; // 30 - INSERT_PADDING_BYTES(0x40 - 0x34); // 34 - u32 app_mem_alloc; // 40 - u32 sys_mem_alloc; // 44 - u32 base_mem_alloc; // 48 - INSERT_PADDING_BYTES(0x60 - 0x4C); // 4C - u8 firm_unk; // 60 - u8 firm_version_rev; // 61 - u8 firm_version_min; // 62 - u8 firm_version_maj; // 63 - u32 firm_sys_core_ver; // 64 - u32 firm_ctr_sdk_ver; // 68 - INSERT_PADDING_BYTES(0x1000 - 0x6C); // 6C -}; - -static_assert(sizeof(ConfigMemDef) == Memory::CONFIG_MEMORY_SIZE, "Config Memory structure size is wrong"); - -static ConfigMemDef config_mem; - -template <typename T> -inline void Read(T &var, const u32 addr) { - u32 offset = addr - Memory::CONFIG_MEMORY_VADDR; - ASSERT(offset < Memory::CONFIG_MEMORY_SIZE); - var = *(reinterpret_cast<T*>(((uintptr_t)&config_mem) + offset)); -} - -// Explicitly instantiate template functions because we aren't defining this in the header: - -template void Read<u64>(u64 &var, const u32 addr); -template void Read<u32>(u32 &var, const u32 addr); -template void Read<u16>(u16 &var, const u32 addr); -template void Read<u8>(u8 &var, const u32 addr); +ConfigMemDef config_mem; void Init() { std::memset(&config_mem, 0, sizeof(config_mem)); diff --git a/src/core/hle/config_mem.h b/src/core/hle/config_mem.h index cbb478fb..9825a09e 100644 --- a/src/core/hle/config_mem.h +++ b/src/core/hle/config_mem.h @@ -9,17 +9,49 @@ // bootrom. Because we're not emulating this, and essentially just "stubbing" the functionality, I'm // putting this as a subset of HLE for now. +#include "common/common_funcs.h" #include "common/common_types.h" +#include "common/swap.h" + +#include "core/memory.h" //////////////////////////////////////////////////////////////////////////////////////////////////// namespace ConfigMem { -template <typename T> -void Read(T &var, const u32 addr); +struct ConfigMemDef { + u8 kernel_unk; // 0 + u8 kernel_version_rev; // 1 + u8 kernel_version_min; // 2 + u8 kernel_version_maj; // 3 + u32_le update_flag; // 4 + u64_le ns_tid; // 8 + u32_le sys_core_ver; // 10 + u8 unit_info; // 14 + u8 boot_firm; // 15 + u8 prev_firm; // 16 + INSERT_PADDING_BYTES(0x1); // 17 + u32_le ctr_sdk_ver; // 18 + INSERT_PADDING_BYTES(0x30 - 0x1C); // 1C + u32_le app_mem_type; // 30 + INSERT_PADDING_BYTES(0x40 - 0x34); // 34 + u32_le app_mem_alloc; // 40 + u32_le sys_mem_alloc; // 44 + u32_le base_mem_alloc; // 48 + INSERT_PADDING_BYTES(0x60 - 0x4C); // 4C + u8 firm_unk; // 60 + u8 firm_version_rev; // 61 + u8 firm_version_min; // 62 + u8 firm_version_maj; // 63 + u32_le firm_sys_core_ver; // 64 + u32_le firm_ctr_sdk_ver; // 68 + INSERT_PADDING_BYTES(0x1000 - 0x6C); // 6C +}; +static_assert(sizeof(ConfigMemDef) == Memory::CONFIG_MEMORY_SIZE, "Config Memory structure size is wrong"); + +extern ConfigMemDef config_mem; void Init(); - void Shutdown(); } // namespace diff --git a/src/core/hle/function_wrappers.h b/src/core/hle/function_wrappers.h index be2626ee..0e5ae29a 100644 --- a/src/core/hle/function_wrappers.h +++ b/src/core/hle/function_wrappers.h @@ -7,7 +7,7 @@ #include "common/common_types.h" #include "core/arm/arm_interface.h" -#include "core/mem_map.h" +#include "core/memory.h" #include "core/hle/hle.h" namespace HLE { @@ -102,14 +102,14 @@ template<ResultCode func(u32)> void Wrap() { FuncReturn(func(PARAM(0)).raw); } -template<ResultCode func(s64*, u32, void*, s32)> void Wrap(){ - FuncReturn(func((s64*)Memory::GetPointer(PARAM(0)), PARAM(1), Memory::GetPointer(PARAM(2)), +template<ResultCode func(s64*, u32, u32*, s32)> void Wrap(){ + FuncReturn(func((s64*)Memory::GetPointer(PARAM(0)), PARAM(1), (u32*)Memory::GetPointer(PARAM(2)), (s32)PARAM(3)).raw); } template<ResultCode func(u32*, const char*)> void Wrap() { u32 param_1 = 0; - u32 retval = func(¶m_1, Memory::GetCharPointer(PARAM(1))).raw; + u32 retval = func(¶m_1, (char*)Memory::GetPointer(PARAM(1))).raw; Core::g_app_core->SetReg(1, param_1); FuncReturn(retval); } @@ -163,7 +163,7 @@ template<void func(s64)> void Wrap() { } template<void func(const char*)> void Wrap() { - func(Memory::GetCharPointer(PARAM(0))); + func((char*)Memory::GetPointer(PARAM(0))); } #undef PARAM diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp index 9d7f6b28..a1221766 100644 --- a/src/core/hle/kernel/address_arbiter.cpp +++ b/src/core/hle/kernel/address_arbiter.cpp @@ -5,7 +5,7 @@ #include "common/common_types.h" #include "common/logging/log.h" -#include "core/mem_map.h" +#include "core/memory.h" #include "core/hle/hle.h" #include "core/hle/kernel/address_arbiter.h" diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index b5c98b24..726e4d2f 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -10,6 +10,7 @@ #include "core/arm/arm_interface.h" #include "core/core.h" #include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/resource_limit.h" #include "core/hle/kernel/process.h" #include "core/hle/kernel/thread.h" #include "core/hle/kernel/timer.h" @@ -134,6 +135,7 @@ void HandleTable::Clear() { /// Initialize the kernel void Init() { + Kernel::ResourceLimitsInit(); Kernel::ThreadingInit(); Kernel::TimersInit(); @@ -147,6 +149,7 @@ void Init() { void Shutdown() { Kernel::ThreadingShutdown(); Kernel::TimersShutdown(); + Kernel::ResourceLimitsShutdown(); g_handle_table.Clear(); // Free all kernel objects g_current_process = nullptr; } diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 7c106d37..28748c8f 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -46,7 +46,8 @@ enum class HandleType : u32 { Process = 8, AddressArbiter = 9, Semaphore = 10, - Timer = 11 + Timer = 11, + ResourceLimit = 12, }; enum { diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index 1e439db9..b5c87e88 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp @@ -7,8 +7,9 @@ #include "common/logging/log.h" #include "core/hle/kernel/process.h" +#include "core/hle/kernel/resource_limit.h" #include "core/hle/kernel/thread.h" -#include "core/mem_map.h" +#include "core/memory.h" namespace Kernel { diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h index 90881054..7b8a6861 100644 --- a/src/core/hle/kernel/process.h +++ b/src/core/hle/kernel/process.h @@ -45,6 +45,8 @@ union ProcessFlags { BitField<12, 1, u16> loaded_high; ///< Application loaded high (not at 0x00100000). }; +class ResourceLimit; + class Process final : public Object { public: static SharedPtr<Process> Create(std::string name, u64 program_id); @@ -61,6 +63,8 @@ public: std::string name; /// Title ID corresponding to the process u64 program_id; + /// Resource limit descriptor for this process + SharedPtr<ResourceLimit> resource_limit; /// The process may only call SVCs which have the corresponding bit set. std::bitset<0x80> svc_access_mask; diff --git a/src/core/hle/kernel/resource_limit.cpp b/src/core/hle/kernel/resource_limit.cpp new file mode 100644 index 00000000..94b3e329 --- /dev/null +++ b/src/core/hle/kernel/resource_limit.cpp @@ -0,0 +1,157 @@ +// Copyright 2015 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include <cstring> + +#include "common/logging/log.h" + +#include "core/mem_map.h" +#include "core/hle/kernel/resource_limit.h" + +namespace Kernel { + +static SharedPtr<ResourceLimit> resource_limits[4]; + +ResourceLimit::ResourceLimit() {} +ResourceLimit::~ResourceLimit() {} + +SharedPtr<ResourceLimit> ResourceLimit::Create(std::string name) { + SharedPtr<ResourceLimit> resource_limit(new ResourceLimit); + + resource_limit->name = std::move(name); + return resource_limit; +} + +SharedPtr<ResourceLimit> ResourceLimit::GetForCategory(ResourceLimitCategory category) { + switch (category) + { + case ResourceLimitCategory::APPLICATION: + case ResourceLimitCategory::SYS_APPLET: + case ResourceLimitCategory::LIB_APPLET: + case ResourceLimitCategory::OTHER: + return resource_limits[static_cast<u8>(category)]; + default: + LOG_CRITICAL(Kernel, "Unknown resource limit category"); + UNREACHABLE(); + } +} + +s32 ResourceLimit::GetCurrentResourceValue(u32 resource) const { + switch (resource) { + case COMMIT: + return current_commit; + case THREAD: + return current_threads; + case EVENT: + return current_events; + case MUTEX: + return current_mutexes; + case SEMAPHORE: + return current_semaphores; + case TIMER: + return current_timers; + case SHARED_MEMORY: + return current_shared_mems; + case ADDRESS_ARBITER: + return current_address_arbiters; + case CPU_TIME: + return current_cpu_time; + default: + LOG_ERROR(Kernel, "Unknown resource type=%08X", resource); + UNIMPLEMENTED(); + return 0; + } +} + +s32 ResourceLimit::GetMaxResourceValue(u32 resource) const { + switch (resource) { + case COMMIT: + return max_commit; + case THREAD: + return max_threads; + case EVENT: + return max_events; + case MUTEX: + return max_mutexes; + case SEMAPHORE: + return max_semaphores; + case TIMER: + return max_timers; + case SHARED_MEMORY: + return max_shared_mems; + case ADDRESS_ARBITER: + return max_address_arbiters; + case CPU_TIME: + return max_cpu_time; + default: + LOG_ERROR(Kernel, "Unknown resource type=%08X", resource); + UNIMPLEMENTED(); + return 0; + } +} + +void ResourceLimitsInit() { + // Create the four resource limits that the system uses + // Create the APPLICATION resource limit + SharedPtr<ResourceLimit> resource_limit = ResourceLimit::Create("Applications"); + resource_limit->max_priority = 0x18; + resource_limit->max_commit = 0x4000000; + resource_limit->max_threads = 0x20; + resource_limit->max_events = 0x20; + resource_limit->max_mutexes = 0x20; + resource_limit->max_semaphores = 0x8; + resource_limit->max_timers = 0x8; + resource_limit->max_shared_mems = 0x10; + resource_limit->max_address_arbiters = 0x2; + resource_limit->max_cpu_time = 0x1E; + resource_limits[static_cast<u8>(ResourceLimitCategory::APPLICATION)] = resource_limit; + + // Create the SYS_APPLET resource limit + resource_limit = ResourceLimit::Create("System Applets"); + resource_limit->max_priority = 0x4; + resource_limit->max_commit = 0x5E00000; + resource_limit->max_threads = 0x1D; + resource_limit->max_events = 0xB; + resource_limit->max_mutexes = 0x8; + resource_limit->max_semaphores = 0x4; + resource_limit->max_timers = 0x4; + resource_limit->max_shared_mems = 0x8; + resource_limit->max_address_arbiters = 0x3; + resource_limit->max_cpu_time = 0x2710; + resource_limits[static_cast<u8>(ResourceLimitCategory::SYS_APPLET)] = resource_limit; + + // Create the LIB_APPLET resource limit + resource_limit = ResourceLimit::Create("Library Applets"); + resource_limit->max_priority = 0x4; + resource_limit->max_commit = 0x600000; + resource_limit->max_threads = 0xE; + resource_limit->max_events = 0x8; + resource_limit->max_mutexes = 0x8; + resource_limit->max_semaphores = 0x4; + resource_limit->max_timers = 0x4; + resource_limit->max_shared_mems = 0x8; + resource_limit->max_address_arbiters = 0x1; + resource_limit->max_cpu_time = 0x2710; + resource_limits[static_cast<u8>(ResourceLimitCategory::LIB_APPLET)] = resource_limit; + + // Create the OTHER resource limit + resource_limit = ResourceLimit::Create("Others"); + resource_limit->max_priority = 0x4; + resource_limit->max_commit = 0x2180000; + resource_limit->max_threads = 0xE1; + resource_limit->max_events = 0x108; + resource_limit->max_mutexes = 0x25; + resource_limit->max_semaphores = 0x43; + resource_limit->max_timers = 0x2C; + resource_limit->max_shared_mems = 0x1F; + resource_limit->max_address_arbiters = 0x2D; + resource_limit->max_cpu_time = 0x3E8; + resource_limits[static_cast<u8>(ResourceLimitCategory::OTHER)] = resource_limit; +} + +void ResourceLimitsShutdown() { + +} + +} // namespace diff --git a/src/core/hle/kernel/resource_limit.h b/src/core/hle/kernel/resource_limit.h new file mode 100644 index 00000000..201ec0db --- /dev/null +++ b/src/core/hle/kernel/resource_limit.h @@ -0,0 +1,119 @@ +// Copyright 2015 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "common/common_types.h" + +#include "core/hle/kernel/kernel.h" + +namespace Kernel { + +enum class ResourceLimitCategory : u8 { + APPLICATION = 0, + SYS_APPLET = 1, + LIB_APPLET = 2, + OTHER = 3 +}; + +enum ResourceTypes { + PRIORITY = 0, + COMMIT = 1, + THREAD = 2, + EVENT = 3, + MUTEX = 4, + SEMAPHORE = 5, + TIMER = 6, + SHARED_MEMORY = 7, + ADDRESS_ARBITER = 8, + CPU_TIME = 9, +}; + +class ResourceLimit final : public Object { +public: + /** + * Creates a resource limit object. + */ + static SharedPtr<ResourceLimit> Create(std::string name = "Unknown"); + + /** + * Retrieves the resource limit associated with the specified resource limit category. + * @param category The resource limit category + * @returns The resource limit associated with the category + */ + static SharedPtr<ResourceLimit> GetForCategory(ResourceLimitCategory category); + + std::string GetTypeName() const override { return "ResourceLimit"; } + std::string GetName() const override { return name; } + + static const HandleType HANDLE_TYPE = HandleType::ResourceLimit; + HandleType GetHandleType() const override { return HANDLE_TYPE; } + + /** + * Gets the current value for the specified resource. + * @param resource Requested resource type + * @returns The current value of the resource type + */ + s32 GetCurrentResourceValue(u32 resource) const; + + /** + * Gets the max value for the specified resource. + * @param resource Requested resource type + * @returns The max value of the resource type + */ + s32 GetMaxResourceValue(u32 resource) const; + + /// Name of resource limit object. + std::string name; + + /// Max thread priority that a process in this category can create + s32 max_priority = 0; + + /// Max memory that processes in this category can use + s32 max_commit = 0; + + ///< Max number of objects that can be collectively created by the processes in this category + s32 max_threads = 0; + s32 max_events = 0; + s32 max_mutexes = 0; + s32 max_semaphores = 0; + s32 max_timers = 0; + s32 max_shared_mems = 0; + s32 max_address_arbiters = 0; + + /// Max CPU time that the processes in this category can utilize + s32 max_cpu_time = 0; + + // TODO(Subv): Increment these in their respective Kernel::T::Create functions, keeping in mind that + // APPLICATION resource limits should not be affected by the objects created by service modules. + // 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 + + /// Current memory that the processes in this category are using + s32 current_commit = 0; + + ///< Current number of objects among all processes in this category + s32 current_threads = 0; + s32 current_events = 0; + s32 current_mutexes = 0; + s32 current_semaphores = 0; + s32 current_timers = 0; + s32 current_shared_mems = 0; + s32 current_address_arbiters = 0; + + /// Current CPU time that the processes in this category are utilizing + s32 current_cpu_time = 0; + +private: + ResourceLimit(); + ~ResourceLimit() override; +}; + +/// Initializes the resource limits +void ResourceLimitsInit(); + +// Destroys the resource limits +void ResourceLimitsShutdown(); + +} // namespace diff --git a/src/core/hle/kernel/session.h b/src/core/hle/kernel/session.h index 8c3886ff..54a06297 100644 --- a/src/core/hle/kernel/session.h +++ b/src/core/hle/kernel/session.h @@ -6,7 +6,7 @@ #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/thread.h" -#include "core/mem_map.h" +#include "core/memory.h" namespace Kernel { diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp index 0c59f487..4137683b 100644 --- a/src/core/hle/kernel/shared_memory.cpp +++ b/src/core/hle/kernel/shared_memory.cpp @@ -6,7 +6,7 @@ #include "common/logging/log.h" -#include "core/mem_map.h" +#include "core/memory.h" #include "core/hle/kernel/shared_memory.h" namespace Kernel { diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index afaf0cd5..a5f1904d 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -21,7 +21,7 @@ #include "core/hle/kernel/thread.h" #include "core/hle/kernel/mutex.h" #include "core/hle/result.h" -#include "core/mem_map.h" +#include "core/memory.h" namespace Kernel { @@ -495,7 +495,7 @@ void Reschedule() { LOG_TRACE(Kernel, "context switch %u -> %u", cur->GetObjectId(), next->GetObjectId()); } else if (cur) { LOG_TRACE(Kernel, "context switch %u -> idle", cur->GetObjectId()); - } else { + } else if (next) { LOG_TRACE(Kernel, "context switch idle -> %u", next->GetObjectId()); } diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index 6b329c12..38992817 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -12,7 +12,6 @@ #include "common/common_types.h" #include "core/core.h" -#include "core/mem_map.h" #include "core/hle/kernel/kernel.h" #include "core/hle/result.h" diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp index c6252a03..c11c5fab 100644 --- a/src/core/hle/service/gsp_gpu.cpp +++ b/src/core/hle/service/gsp_gpu.cpp @@ -5,6 +5,7 @@ #include "common/bit_field.h" #include "core/mem_map.h" +#include "core/memory.h" #include "core/hle/kernel/event.h" #include "core/hle/kernel/shared_memory.h" #include "core/hle/result.h" diff --git a/src/core/hle/service/ptm/ptm.cpp b/src/core/hle/service/ptm/ptm.cpp index 6480a323..2c7d49c9 100644 --- a/src/core/hle/service/ptm/ptm.cpp +++ b/src/core/hle/service/ptm/ptm.cpp @@ -2,6 +2,8 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include "common/logging/log.h" + #include "core/file_sys/file_backend.h" #include "core/hle/service/fs/archive.h" #include "core/hle/service/ptm/ptm.h" @@ -23,20 +25,56 @@ static bool shell_open; static bool battery_is_charging; -u32 GetAdapterState() { +void GetAdapterState(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + // TODO(purpasmart96): This function is only a stub, // it returns a valid result without implementing full functionality. - return battery_is_charging ? 1 : 0; + + cmd_buff[1] = RESULT_SUCCESS.raw; + cmd_buff[2] = battery_is_charging ? 1 : 0; + + LOG_WARNING(Service_PTM, "(STUBBED) called"); } -u32 GetShellState() { - return shell_open ? 1 : 0; +void GetShellState(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + + cmd_buff[1] = RESULT_SUCCESS.raw; + cmd_buff[2] = shell_open ? 1 : 0; } -ChargeLevels GetBatteryLevel() { +void GetBatteryLevel(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + // TODO(purpasmart96): This function is only a stub, // it returns a valid result without implementing full functionality. - return ChargeLevels::CompletelyFull; // Set to a completely full battery + + cmd_buff[1] = RESULT_SUCCESS.raw; + cmd_buff[2] = static_cast<u32>(ChargeLevels::CompletelyFull); // Set to a completely full battery + + LOG_WARNING(Service_PTM, "(STUBBED) called"); +} + +void GetBatteryChargeState(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + + // TODO(purpasmart96): This function is only a stub, + // it returns a valid result without implementing full functionality. + + cmd_buff[1] = RESULT_SUCCESS.raw; + cmd_buff[2] = battery_is_charging ? 1 : 0; + + LOG_WARNING(Service_PTM, "(STUBBED) called"); +} + +void IsLegacyPowerOff(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + + cmd_buff[1] = RESULT_SUCCESS.raw; + cmd_buff[2] = 0; + + LOG_WARNING(Service_PTM, "(STUBBED) called"); } void Init() { diff --git a/src/core/hle/service/ptm/ptm.h b/src/core/hle/service/ptm/ptm.h index 3c776aa8..493e6a11 100644 --- a/src/core/hle/service/ptm/ptm.h +++ b/src/core/hle/service/ptm/ptm.h @@ -5,6 +5,7 @@ #pragma once #include <array> +#include "core/hle/service/service.h" #include "core/hle/result.h" namespace Service { @@ -35,25 +36,48 @@ struct GameCoin { }; /** - * Returns whether the battery is charging or not. * It is unknown if GetAdapterState is the same as GetBatteryChargeState, * it is likely to just be a duplicate function of GetBatteryChargeState * that controls another part of the HW. - * @returns 1 if the battery is charging, and 0 otherwise. + * PTM::GetAdapterState service function + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 2 : Output of function, 0 = not charging, 1 = charging. */ -u32 GetAdapterState(); +void GetAdapterState(Interface* self); /** - * Returns whether the 3DS's physical shell casing is open or closed - * @returns 1 if the shell is open, and 0 if otherwise + * PTM::GetShellState service function. + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 2 : Whether the 3DS's physical shell casing is open (1) or closed (0) */ -u32 GetShellState(); +void GetShellState(Interface* self); /** - * Get the current battery's charge level. - * @returns The battery's charge level. + * PTM::GetBatteryLevel service function + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 2 : Battery level, 5 = completely full battery, 4 = mostly full battery, + * 3 = half full battery, 2 = low battery, 1 = critical battery. */ -ChargeLevels GetBatteryLevel(); +void GetBatteryLevel(Interface* self); + +/** + * PTM::GetBatteryChargeState service function + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 2 : Output of function, 0 = not charging, 1 = charging. + */ +void GetBatteryChargeState(Interface* self); + +/** + * PTM::IsLegacyPowerOff service function + * Outputs: + * 1: Result code, 0 on success, otherwise error code + * 2: Whether the system is going through a power off + */ +void IsLegacyPowerOff(Interface* self); /// Initialize the PTM service void Init(); diff --git a/src/core/hle/service/ptm/ptm_play.cpp b/src/core/hle/service/ptm/ptm_play.cpp index 8e8ae855..48e68a3d 100644 --- a/src/core/hle/service/ptm/ptm_play.cpp +++ b/src/core/hle/service/ptm/ptm_play.cpp @@ -9,10 +9,10 @@ namespace Service { namespace PTM { const Interface::FunctionInfo FunctionTable[] = { - { 0x08070082, nullptr, "GetPlayHistory" }, - { 0x08080000, nullptr, "GetPlayHistoryStart" }, - { 0x08090000, nullptr, "GetPlayHistoryLength" }, - { 0x080B0080, nullptr, "CalcPlayHistoryStart" }, + {0x08070082, nullptr, "GetPlayHistory"}, + {0x08080000, nullptr, "GetPlayHistoryStart"}, + {0x08090000, nullptr, "GetPlayHistoryLength"}, + {0x080B0080, nullptr, "CalcPlayHistoryStart"}, }; PTM_Play_Interface::PTM_Play_Interface() { diff --git a/src/core/hle/service/ptm/ptm_sysm.cpp b/src/core/hle/service/ptm/ptm_sysm.cpp index 13322bdb..655658f3 100644 --- a/src/core/hle/service/ptm/ptm_sysm.cpp +++ b/src/core/hle/service/ptm/ptm_sysm.cpp @@ -2,57 +2,44 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include "common/make_unique.h" -#include "core/file_sys/archive_extsavedata.h" #include "core/hle/hle.h" +#include "core/hle/service/ptm/ptm.h" #include "core/hle/service/ptm/ptm_sysm.h" namespace Service { namespace PTM { -/** - * Returns whether the system is powering off (?) - * Outputs: - * 1: Result code, 0 on success, otherwise error code - * 2: Whether the system is going through a power off - */ -static void IsLegacyPowerOff(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = 0; -} - const Interface::FunctionInfo FunctionTable[] = { - {0x040100C0, nullptr, "SetRtcAlarmEx"}, - {0x04020042, nullptr, "ReplySleepQuery"}, - {0x04030042, nullptr, "NotifySleepPreparationComplete"}, - {0x04040102, nullptr, "SetWakeupTrigger"}, - {0x04050000, nullptr, "GetAwakeReason"}, - {0x04060000, nullptr, "RequestSleep"}, - {0x040700C0, nullptr, "ShutdownAsync"}, - {0x04080000, nullptr, "Awake"}, - {0x04090080, nullptr, "RebootAsync"}, - {0x040A0000, nullptr, "CheckNew3DS"}, - {0x08010640, nullptr, "SetInfoLEDPattern"}, - {0x08020040, nullptr, "SetInfoLEDPatternHeader"}, - {0x08030000, nullptr, "GetInfoLEDStatus"}, - {0x08040040, nullptr, "SetBatteryEmptyLEDPattern"}, - {0x08050000, nullptr, "ClearStepHistory"}, - {0x080600C2, nullptr, "SetStepHistory"}, - {0x08070082, nullptr, "GetPlayHistory"}, - {0x08080000, nullptr, "GetPlayHistoryStart"}, - {0x08090000, nullptr, "GetPlayHistoryLength"}, - {0x080A0000, nullptr, "ClearPlayHistory"}, - {0x080B0080, nullptr, "CalcPlayHistoryStart"}, - {0x080C0080, nullptr, "SetUserTime"}, - {0x080D0000, nullptr, "InvalidateSystemTime"}, - {0x080E0140, nullptr, "NotifyPlayEvent"}, - {0x080F0000, IsLegacyPowerOff, "IsLegacyPowerOff"}, - {0x08100000, nullptr, "ClearLegacyPowerOff"}, - {0x08110000, nullptr, "GetShellStatus"}, - {0x08120000, nullptr, "IsShutdownByBatteryEmpty"}, - {0x08130000, nullptr, "FormatSavedata"}, - {0x08140000, nullptr, "GetLegacyJumpProhibitedFlag"} + {0x040100C0, nullptr, "SetRtcAlarmEx"}, + {0x04020042, nullptr, "ReplySleepQuery"}, + {0x04030042, nullptr, "NotifySleepPreparationComplete"}, + {0x04040102, nullptr, "SetWakeupTrigger"}, + {0x04050000, nullptr, "GetAwakeReason"}, + {0x04060000, nullptr, "RequestSleep"}, + {0x040700C0, nullptr, "ShutdownAsync"}, + {0x04080000, nullptr, "Awake"}, + {0x04090080, nullptr, "RebootAsync"}, + {0x040A0000, nullptr, "CheckNew3DS"}, + {0x08010640, nullptr, "SetInfoLEDPattern"}, + {0x08020040, nullptr, "SetInfoLEDPatternHeader"}, + {0x08030000, nullptr, "GetInfoLEDStatus"}, + {0x08040040, nullptr, "SetBatteryEmptyLEDPattern"}, + {0x08050000, nullptr, "ClearStepHistory"}, + {0x080600C2, nullptr, "SetStepHistory"}, + {0x08070082, nullptr, "GetPlayHistory"}, + {0x08080000, nullptr, "GetPlayHistoryStart"}, + {0x08090000, nullptr, "GetPlayHistoryLength"}, + {0x080A0000, nullptr, "ClearPlayHistory"}, + {0x080B0080, nullptr, "CalcPlayHistoryStart"}, + {0x080C0080, nullptr, "SetUserTime"}, + {0x080D0000, nullptr, "InvalidateSystemTime"}, + {0x080E0140, nullptr, "NotifyPlayEvent"}, + {0x080F0000, IsLegacyPowerOff, "IsLegacyPowerOff"}, + {0x08100000, nullptr, "ClearLegacyPowerOff"}, + {0x08110000, nullptr, "GetShellStatus"}, + {0x08120000, nullptr, "IsShutdownByBatteryEmpty"}, + {0x08130000, nullptr, "FormatSavedata"}, + {0x08140000, nullptr, "GetLegacyJumpProhibitedFlag"} }; PTM_Sysm_Interface::PTM_Sysm_Interface() { diff --git a/src/core/hle/service/ptm/ptm_u.cpp b/src/core/hle/service/ptm/ptm_u.cpp index 9d6a5b0d..3f5e9c7c 100644 --- a/src/core/hle/service/ptm/ptm_u.cpp +++ b/src/core/hle/service/ptm/ptm_u.cpp @@ -11,68 +11,6 @@ namespace Service { namespace PTM { -/** - * PTM_U::GetAdapterState service function - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : Output of function, 0 = not charging, 1 = charging. - */ -static void GetAdapterState(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = GetAdapterState(); - - LOG_WARNING(Service_PTM, "(STUBBED) called"); -} - -/* - * PTM_User::GetShellState service function. - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : Whether the 3DS's physical shell casing is open (1) or closed (0) - */ -static void GetShellState(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = GetShellState(); -} - -/** - * PTM_U::GetBatteryLevel service function - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : Battery level, 5 = completely full battery, 4 = mostly full battery, - * 3 = half full battery, 2 = low battery, 1 = critical battery. - */ -static void GetBatteryLevel(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = static_cast<u32>(GetBatteryLevel()); - - LOG_WARNING(Service_PTM, "(STUBBED) called"); -} - -/** - * PTM_U::GetBatteryChargeState service function - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : Output of function, 0 = not charging, 1 = charging. - */ -static void GetBatteryChargeState(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - // TODO(purpasmart96): This function is only a stub, - // it returns a valid result without implementing full functionality. - - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = GetAdapterState(); - - LOG_WARNING(Service_PTM, "(STUBBED) called"); -} - const Interface::FunctionInfo FunctionTable[] = { {0x00010002, nullptr, "RegisterAlarmClient"}, {0x00020080, nullptr, "SetRtcAlarm"}, diff --git a/src/core/hle/shared_page.cpp b/src/core/hle/shared_page.cpp index 4f227a37..4014eee9 100644 --- a/src/core/hle/shared_page.cpp +++ b/src/core/hle/shared_page.cpp @@ -8,7 +8,7 @@ #include "common/common_funcs.h" #include "core/core.h" -#include "core/mem_map.h" +#include "core/memory.h" #include "core/hle/config_mem.h" #include "core/hle/shared_page.h" @@ -16,63 +16,12 @@ namespace SharedPage { -// see http://3dbrew.org/wiki/Configuration_Memory#Shared_Memory_Page_For_ARM11_Processes +SharedPageDef shared_page; -#pragma pack(1) -struct DateTime { - u64 date_time; // 0x0 - u64 update_tick; // 0x8 - INSERT_PADDING_BYTES(0x20 - 0x10); // 0x10 -}; - -struct SharedPageDef { - // most of these names are taken from the 3dbrew page linked above. - u32 date_time_selector; // 0x0 - u8 running_hw; // 0x4 - u8 mcu_hw_info; // 0x5: don't know what the acronyms mean - INSERT_PADDING_BYTES(0x20 - 0x6); // 0x6 - DateTime date_time_0; // 0x20 - DateTime date_time_1; // 0x40 - u8 wifi_macaddr[6]; // 0x60 - u8 wifi_unknown1; // 0x66: 3dbrew says these are "Likely wifi hardware related" - u8 wifi_unknown2; // 0x67 - INSERT_PADDING_BYTES(0x80 - 0x68); // 0x68 - float sliderstate_3d; // 0x80 - u8 ledstate_3d; // 0x84 - INSERT_PADDING_BYTES(0xA0 - 0x85); // 0x85 - u64 menu_title_id; // 0xA0 - u64 active_menu_title_id; // 0xA8 - INSERT_PADDING_BYTES(0x1000 - 0xB0); // 0xB0 -}; -#pragma pack() - -static_assert(sizeof(DateTime) == 0x20, "Datetime size is wrong"); -static_assert(sizeof(SharedPageDef) == Memory::SHARED_PAGE_SIZE, "Shared page structure size is wrong"); - -static SharedPageDef shared_page; - -template <typename T> -inline void Read(T &var, const u32 addr) { - u32 offset = addr - Memory::SHARED_PAGE_VADDR; - var = *(reinterpret_cast<T*>(((uintptr_t)&shared_page) + offset)); -} - -// Explicitly instantiate template functions because we aren't defining this in the header: -template void Read<u64>(u64 &var, const u32 addr); -template void Read<u32>(u32 &var, const u32 addr); -template void Read<u16>(u16 &var, const u32 addr); -template void Read<u8>(u8 &var, const u32 addr); - -void Set3DSlider(float amount) { +void Init() { std::memset(&shared_page, 0, sizeof(shared_page)); - shared_page.sliderstate_3d = amount; - shared_page.ledstate_3d = (amount == 0.0f); // off when non-zero -} - -void Init() { shared_page.running_hw = 0x1; // product - Set3DSlider(0.0f); } void Shutdown() { diff --git a/src/core/hle/shared_page.h b/src/core/hle/shared_page.h index 1b6e4e58..fd2ab66a 100644 --- a/src/core/hle/shared_page.h +++ b/src/core/hle/shared_page.h @@ -11,18 +11,46 @@ */ #include "common/common_types.h" +#include "common/swap.h" //////////////////////////////////////////////////////////////////////////////////////////////////// namespace SharedPage { -template <typename T> -void Read(T &var, const u32 addr); - -void Set3DSlider(float amount); +// See http://3dbrew.org/wiki/Configuration_Memory#Shared_Memory_Page_For_ARM11_Processes + +struct DateTime { + u64_le date_time; // 0 + u64_le update_tick; // 8 + INSERT_PADDING_BYTES(0x20 - 0x10); // 10 +}; +static_assert(sizeof(DateTime) == 0x20, "Datetime size is wrong"); + +struct SharedPageDef { + // Most of these names are taken from the 3dbrew page linked above. + u32_le date_time_selector; // 0 + u8 running_hw; // 4 + /// "Microcontroller hardware info" + u8 mcu_hw_info; // 5 + INSERT_PADDING_BYTES(0x20 - 0x6); // 6 + DateTime date_time_0; // 20 + DateTime date_time_1; // 40 + u8 wifi_macaddr[6]; // 60 + u8 wifi_unknown1; // 66 + u8 wifi_unknown2; // 67 + INSERT_PADDING_BYTES(0x80 - 0x68); // 68 + float_le sliderstate_3d; // 80 + u8 ledstate_3d; // 84 + INSERT_PADDING_BYTES(0xA0 - 0x85); // 85 + u64_le menu_title_id; // A0 + u64_le active_menu_title_id; // A8 + INSERT_PADDING_BYTES(0x1000 - 0xB0); // B0 +}; +static_assert(sizeof(SharedPageDef) == Memory::SHARED_PAGE_SIZE, "Shared page structure size is wrong"); + +extern SharedPageDef shared_page; void Init(); - void Shutdown(); } // namespace diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index e8159fbd..654ee2bf 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -17,6 +17,7 @@ #include "core/hle/kernel/event.h" #include "core/hle/kernel/mutex.h" #include "core/hle/kernel/process.h" +#include "core/hle/kernel/resource_limit.h" #include "core/hle/kernel/semaphore.h" #include "core/hle/kernel/shared_memory.h" #include "core/hle/kernel/thread.h" @@ -301,21 +302,47 @@ static void OutputDebugString(const char* string) { } /// Get resource limit -static ResultCode GetResourceLimit(Handle* resource_limit, Handle process) { - // With regards to proceess values: - // 0xFFFF8001 is a handle alias for the current KProcess, and 0xFFFF8000 is a handle alias for - // the current KThread. - *resource_limit = 0xDEADBEEF; - LOG_ERROR(Kernel_SVC, "(UNIMPLEMENTED) called process=0x%08X", process); +static ResultCode GetResourceLimit(Handle* resource_limit, Handle process_handle) { + LOG_TRACE(Kernel_SVC, "called process=0x%08X", process_handle); + + SharedPtr<Kernel::Process> process = Kernel::g_handle_table.Get<Kernel::Process>(process_handle); + if (process == nullptr) + return ERR_INVALID_HANDLE; + + CASCADE_RESULT(*resource_limit, Kernel::g_handle_table.Create(process->resource_limit)); + return RESULT_SUCCESS; } /// Get resource limit current values -static ResultCode GetResourceLimitCurrentValues(s64* values, Handle resource_limit, void* names, +static ResultCode GetResourceLimitCurrentValues(s64* values, Handle resource_limit_handle, u32* names, + s32 name_count) { + LOG_TRACE(Kernel_SVC, "called resource_limit=%08X, names=%p, name_count=%d", + resource_limit_handle, names, name_count); + + SharedPtr<Kernel::ResourceLimit> resource_limit = Kernel::g_handle_table.Get<Kernel::ResourceLimit>(resource_limit_handle); + if (resource_limit == nullptr) + return ERR_INVALID_HANDLE; + + for (unsigned int i = 0; i < name_count; ++i) + values[i] = resource_limit->GetCurrentResourceValue(names[i]); + + return RESULT_SUCCESS; +} + +/// Get resource limit max values +static ResultCode GetResourceLimitLimitValues(s64* values, Handle resource_limit_handle, u32* names, s32 name_count) { - LOG_ERROR(Kernel_SVC, "(UNIMPLEMENTED) called resource_limit=%08X, names=%p, name_count=%d", - resource_limit, names, name_count); - Memory::Write32(Core::g_app_core->GetReg(0), 0); // Normmatt: Set used memory to 0 for now + LOG_TRACE(Kernel_SVC, "called resource_limit=%08X, names=%p, name_count=%d", + resource_limit_handle, names, name_count); + + SharedPtr<Kernel::ResourceLimit> resource_limit = Kernel::g_handle_table.Get<Kernel::ResourceLimit>(resource_limit_handle); + if (resource_limit == nullptr) + return ERR_INVALID_HANDLE; + + for (unsigned int i = 0; i < name_count; ++i) + values[i] = resource_limit->GetMaxResourceValue(names[i]); + return RESULT_SUCCESS; } @@ -707,7 +734,7 @@ static const FunctionDef SVC_Table[] = { {0x36, HLE::Wrap<GetProcessIdOfThread>, "GetProcessIdOfThread"}, {0x37, HLE::Wrap<GetThreadId>, "GetThreadId"}, {0x38, HLE::Wrap<GetResourceLimit>, "GetResourceLimit"}, - {0x39, nullptr, "GetResourceLimitLimitValues"}, + {0x39, HLE::Wrap<GetResourceLimitLimitValues>, "GetResourceLimitLimitValues"}, {0x3A, HLE::Wrap<GetResourceLimitCurrentValues>, "GetResourceLimitCurrentValues"}, {0x3B, nullptr, "GetThreadContext"}, {0x3C, nullptr, "Break"}, |