summaryrefslogtreecommitdiffstats
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/file_sys/control_metadata.cpp24
-rw-r--r--src/core/file_sys/registered_cache.cpp44
-rw-r--r--src/core/file_sys/registered_cache.h10
-rw-r--r--src/core/gdbstub/gdbstub.cpp2
-rw-r--r--src/core/hle/kernel/resource_limit.h6
-rw-r--r--src/core/hle/kernel/svc.cpp121
-rw-r--r--src/core/hle/kernel/svc_wrap.h8
-rw-r--r--src/core/hle/service/acc/acc.cpp17
-rw-r--r--src/core/hle/service/acc/profile_manager.cpp5
-rw-r--r--src/core/hle/service/acc/profile_manager.h14
-rw-r--r--src/core/hle/service/hid/controllers/npad.h6
11 files changed, 196 insertions, 61 deletions
diff --git a/src/core/file_sys/control_metadata.cpp b/src/core/file_sys/control_metadata.cpp
index c8fa912bf..e065e592f 100644
--- a/src/core/file_sys/control_metadata.cpp
+++ b/src/core/file_sys/control_metadata.cpp
@@ -8,13 +8,23 @@
namespace FileSys {
-const std::array<const char*, 15> LANGUAGE_NAMES = {
- "AmericanEnglish", "BritishEnglish", "Japanese",
- "French", "German", "LatinAmericanSpanish",
- "Spanish", "Italian", "Dutch",
- "CanadianFrench", "Portugese", "Russian",
- "Korean", "Taiwanese", "Chinese",
-};
+const std::array<const char*, 15> LANGUAGE_NAMES{{
+ "AmericanEnglish",
+ "BritishEnglish",
+ "Japanese",
+ "French",
+ "German",
+ "LatinAmericanSpanish",
+ "Spanish",
+ "Italian",
+ "Dutch",
+ "CanadianFrench",
+ "Portuguese",
+ "Russian",
+ "Korean",
+ "Taiwanese",
+ "Chinese",
+}};
std::string LanguageEntry::GetApplicationName() const {
return Common::StringFromFixedZeroTerminatedBuffer(application_name.data(),
diff --git a/src/core/file_sys/registered_cache.cpp b/src/core/file_sys/registered_cache.cpp
index a3f8f2f73..07c3af64a 100644
--- a/src/core/file_sys/registered_cache.cpp
+++ b/src/core/file_sys/registered_cache.cpp
@@ -381,22 +381,22 @@ std::vector<RegisteredCacheEntry> RegisteredCache::ListEntriesFilter(
return out;
}
-static std::shared_ptr<NCA> GetNCAFromNSPForID(std::shared_ptr<NSP> nsp, const NcaID& id) {
- const auto file = nsp->GetFile(fmt::format("{}.nca", Common::HexArrayToString(id, false)));
+static std::shared_ptr<NCA> GetNCAFromNSPForID(const NSP& nsp, const NcaID& id) {
+ const auto file = nsp.GetFile(fmt::format("{}.nca", Common::HexArrayToString(id, false)));
if (file == nullptr)
return nullptr;
return std::make_shared<NCA>(file);
}
-InstallResult RegisteredCache::InstallEntry(std::shared_ptr<XCI> xci, bool overwrite_if_exists,
+InstallResult RegisteredCache::InstallEntry(const XCI& xci, bool overwrite_if_exists,
const VfsCopyFunction& copy) {
- return InstallEntry(xci->GetSecurePartitionNSP(), overwrite_if_exists, copy);
+ return InstallEntry(*xci.GetSecurePartitionNSP(), overwrite_if_exists, copy);
}
-InstallResult RegisteredCache::InstallEntry(std::shared_ptr<NSP> nsp, bool overwrite_if_exists,
+InstallResult RegisteredCache::InstallEntry(const NSP& nsp, bool overwrite_if_exists,
const VfsCopyFunction& copy) {
- const auto& ncas = nsp->GetNCAsCollapsed();
- const auto& meta_iter = std::find_if(ncas.begin(), ncas.end(), [](std::shared_ptr<NCA> nca) {
+ const auto ncas = nsp.GetNCAsCollapsed();
+ const auto meta_iter = std::find_if(ncas.begin(), ncas.end(), [](const auto& nca) {
return nca->GetType() == NCAContentType::Meta;
});
@@ -410,7 +410,7 @@ InstallResult RegisteredCache::InstallEntry(std::shared_ptr<NSP> nsp, bool overw
const auto meta_id_raw = (*meta_iter)->GetName().substr(0, 32);
const auto meta_id = Common::HexStringToArray<16>(meta_id_raw);
- const auto res = RawInstallNCA(*meta_iter, copy, overwrite_if_exists, meta_id);
+ const auto res = RawInstallNCA(**meta_iter, copy, overwrite_if_exists, meta_id);
if (res != InstallResult::Success)
return res;
@@ -422,7 +422,7 @@ InstallResult RegisteredCache::InstallEntry(std::shared_ptr<NSP> nsp, bool overw
const auto nca = GetNCAFromNSPForID(nsp, record.nca_id);
if (nca == nullptr)
return InstallResult::ErrorCopyFailed;
- const auto res2 = RawInstallNCA(nca, copy, overwrite_if_exists, record.nca_id);
+ const auto res2 = RawInstallNCA(*nca, copy, overwrite_if_exists, record.nca_id);
if (res2 != InstallResult::Success)
return res2;
}
@@ -431,21 +431,21 @@ InstallResult RegisteredCache::InstallEntry(std::shared_ptr<NSP> nsp, bool overw
return InstallResult::Success;
}
-InstallResult RegisteredCache::InstallEntry(std::shared_ptr<NCA> nca, TitleType type,
+InstallResult RegisteredCache::InstallEntry(const NCA& nca, TitleType type,
bool overwrite_if_exists, const VfsCopyFunction& copy) {
CNMTHeader header{
- nca->GetTitleId(), ///< Title ID
- 0, ///< Ignore/Default title version
- type, ///< Type
- {}, ///< Padding
- 0x10, ///< Default table offset
- 1, ///< 1 Content Entry
- 0, ///< No Meta Entries
- {}, ///< Padding
+ nca.GetTitleId(), ///< Title ID
+ 0, ///< Ignore/Default title version
+ type, ///< Type
+ {}, ///< Padding
+ 0x10, ///< Default table offset
+ 1, ///< 1 Content Entry
+ 0, ///< No Meta Entries
+ {}, ///< Padding
};
OptionalHeader opt_header{0, 0};
- ContentRecord c_rec{{}, {}, {}, GetCRTypeFromNCAType(nca->GetType()), {}};
- const auto& data = nca->GetBaseFile()->ReadBytes(0x100000);
+ ContentRecord c_rec{{}, {}, {}, GetCRTypeFromNCAType(nca.GetType()), {}};
+ const auto& data = nca.GetBaseFile()->ReadBytes(0x100000);
mbedtls_sha256(data.data(), data.size(), c_rec.hash.data(), 0);
memcpy(&c_rec.nca_id, &c_rec.hash, 16);
const CNMT new_cnmt(header, opt_header, {c_rec}, {});
@@ -454,10 +454,10 @@ InstallResult RegisteredCache::InstallEntry(std::shared_ptr<NCA> nca, TitleType
return RawInstallNCA(nca, copy, overwrite_if_exists, c_rec.nca_id);
}
-InstallResult RegisteredCache::RawInstallNCA(std::shared_ptr<NCA> nca, const VfsCopyFunction& copy,
+InstallResult RegisteredCache::RawInstallNCA(const NCA& nca, const VfsCopyFunction& copy,
bool overwrite_if_exists,
std::optional<NcaID> override_id) {
- const auto in = nca->GetBaseFile();
+ const auto in = nca.GetBaseFile();
Core::Crypto::SHA256Hash hash{};
// Calculate NcaID
diff --git a/src/core/file_sys/registered_cache.h b/src/core/file_sys/registered_cache.h
index 6b89db8de..3b77af4e0 100644
--- a/src/core/file_sys/registered_cache.h
+++ b/src/core/file_sys/registered_cache.h
@@ -6,7 +6,6 @@
#include <array>
#include <functional>
-#include <map>
#include <memory>
#include <string>
#include <vector>
@@ -104,17 +103,16 @@ public:
// Raw copies all the ncas from the xci/nsp to the csache. Does some quick checks to make sure
// there is a meta NCA and all of them are accessible.
- InstallResult InstallEntry(std::shared_ptr<XCI> xci, bool overwrite_if_exists = false,
+ InstallResult InstallEntry(const XCI& xci, bool overwrite_if_exists = false,
const VfsCopyFunction& copy = &VfsRawCopy);
- InstallResult InstallEntry(std::shared_ptr<NSP> nsp, bool overwrite_if_exists = false,
+ InstallResult InstallEntry(const NSP& nsp, bool overwrite_if_exists = false,
const VfsCopyFunction& copy = &VfsRawCopy);
// Due to the fact that we must use Meta-type NCAs to determine the existance of files, this
// poses quite a challenge. Instead of creating a new meta NCA for this file, yuzu will create a
// dir inside the NAND called 'yuzu_meta' and store the raw CNMT there.
// TODO(DarkLordZach): Author real meta-type NCAs and install those.
- InstallResult InstallEntry(std::shared_ptr<NCA> nca, TitleType type,
- bool overwrite_if_exists = false,
+ InstallResult InstallEntry(const NCA& nca, TitleType type, bool overwrite_if_exists = false,
const VfsCopyFunction& copy = &VfsRawCopy);
private:
@@ -128,7 +126,7 @@ private:
std::optional<NcaID> GetNcaIDFromMetadata(u64 title_id, ContentRecordType type) const;
VirtualFile GetFileAtID(NcaID id) const;
VirtualFile OpenFileOrDirectoryConcat(const VirtualDir& dir, std::string_view path) const;
- InstallResult RawInstallNCA(std::shared_ptr<NCA> nca, const VfsCopyFunction& copy,
+ InstallResult RawInstallNCA(const NCA& nca, const VfsCopyFunction& copy,
bool overwrite_if_exists, std::optional<NcaID> override_id = {});
bool RawInstallYuzuMeta(const CNMT& cnmt);
diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp
index 687dea409..e6b5171ee 100644
--- a/src/core/gdbstub/gdbstub.cpp
+++ b/src/core/gdbstub/gdbstub.cpp
@@ -282,7 +282,7 @@ static void FpuWrite(std::size_t id, u128 val, Kernel::Thread* thread = nullptr)
if (id >= UC_ARM64_REG_Q0 && id < FPCR_REGISTER) {
thread_context.vector_registers[id - UC_ARM64_REG_Q0] = val;
} else if (id == FPCR_REGISTER) {
- thread_context.fpcr = val[0];
+ thread_context.fpcr = static_cast<u32>(val[0]);
}
}
diff --git a/src/core/hle/kernel/resource_limit.h b/src/core/hle/kernel/resource_limit.h
index bec065543..59dc11c22 100644
--- a/src/core/hle/kernel/resource_limit.h
+++ b/src/core/hle/kernel/resource_limit.h
@@ -14,7 +14,7 @@ namespace Kernel {
class KernelCore;
-enum class ResourceType {
+enum class ResourceType : u32 {
PhysicalMemory,
Threads,
Events,
@@ -25,6 +25,10 @@ enum class ResourceType {
ResourceTypeCount
};
+constexpr bool IsValidResourceType(ResourceType type) {
+ return type < ResourceType::ResourceTypeCount;
+}
+
class ResourceLimit final : public Object {
public:
/**
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index f287f7c97..1f19d5576 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -105,6 +105,38 @@ ResultCode MapUnmapMemorySanityChecks(const VMManager& vm_manager, VAddr dst_add
return RESULT_SUCCESS;
}
+
+enum class ResourceLimitValueType {
+ CurrentValue,
+ LimitValue,
+};
+
+ResultVal<s64> RetrieveResourceLimitValue(Handle resource_limit, u32 resource_type,
+ ResourceLimitValueType value_type) {
+ const auto type = static_cast<ResourceType>(resource_type);
+ if (!IsValidResourceType(type)) {
+ LOG_ERROR(Kernel_SVC, "Invalid resource limit type: '{}'", resource_type);
+ return ERR_INVALID_ENUM_VALUE;
+ }
+
+ const auto& kernel = Core::System::GetInstance().Kernel();
+ const auto* const current_process = kernel.CurrentProcess();
+ ASSERT(current_process != nullptr);
+
+ const auto resource_limit_object =
+ current_process->GetHandleTable().Get<ResourceLimit>(resource_limit);
+ if (!resource_limit_object) {
+ LOG_ERROR(Kernel_SVC, "Handle to non-existent resource limit instance used. Handle={:08X}",
+ resource_limit);
+ return ERR_INVALID_HANDLE;
+ }
+
+ if (value_type == ResourceLimitValueType::CurrentValue) {
+ return MakeResult(resource_limit_object->GetCurrentResourceValue(type));
+ }
+
+ return MakeResult(resource_limit_object->GetMaxResourceValue(type));
+}
} // Anonymous namespace
/// Set the process heap to a given Size. It can both extend and shrink the heap.
@@ -1346,6 +1378,87 @@ static ResultCode GetProcessInfo(u64* out, Handle process_handle, u32 type) {
return RESULT_SUCCESS;
}
+static ResultCode CreateResourceLimit(Handle* out_handle) {
+ LOG_DEBUG(Kernel_SVC, "called");
+
+ auto& kernel = Core::System::GetInstance().Kernel();
+ auto resource_limit = ResourceLimit::Create(kernel);
+
+ auto* const current_process = kernel.CurrentProcess();
+ ASSERT(current_process != nullptr);
+
+ const auto handle = current_process->GetHandleTable().Create(std::move(resource_limit));
+ if (handle.Failed()) {
+ return handle.Code();
+ }
+
+ *out_handle = *handle;
+ return RESULT_SUCCESS;
+}
+
+static ResultCode GetResourceLimitLimitValue(u64* out_value, Handle resource_limit,
+ u32 resource_type) {
+ LOG_DEBUG(Kernel_SVC, "called. Handle={:08X}, Resource type={}", resource_limit, resource_type);
+
+ const auto limit_value = RetrieveResourceLimitValue(resource_limit, resource_type,
+ ResourceLimitValueType::LimitValue);
+ if (limit_value.Failed()) {
+ return limit_value.Code();
+ }
+
+ *out_value = static_cast<u64>(*limit_value);
+ return RESULT_SUCCESS;
+}
+
+static ResultCode GetResourceLimitCurrentValue(u64* out_value, Handle resource_limit,
+ u32 resource_type) {
+ LOG_DEBUG(Kernel_SVC, "called. Handle={:08X}, Resource type={}", resource_limit, resource_type);
+
+ const auto current_value = RetrieveResourceLimitValue(resource_limit, resource_type,
+ ResourceLimitValueType::CurrentValue);
+ if (current_value.Failed()) {
+ return current_value.Code();
+ }
+
+ *out_value = static_cast<u64>(*current_value);
+ return RESULT_SUCCESS;
+}
+
+static ResultCode SetResourceLimitLimitValue(Handle resource_limit, u32 resource_type, u64 value) {
+ LOG_DEBUG(Kernel_SVC, "called. Handle={:08X}, Resource type={}, Value={}", resource_limit,
+ resource_type, value);
+
+ const auto type = static_cast<ResourceType>(resource_type);
+ if (!IsValidResourceType(type)) {
+ LOG_ERROR(Kernel_SVC, "Invalid resource limit type: '{}'", resource_type);
+ return ERR_INVALID_ENUM_VALUE;
+ }
+
+ auto& kernel = Core::System::GetInstance().Kernel();
+ auto* const current_process = kernel.CurrentProcess();
+ ASSERT(current_process != nullptr);
+
+ auto resource_limit_object =
+ current_process->GetHandleTable().Get<ResourceLimit>(resource_limit);
+ if (!resource_limit_object) {
+ LOG_ERROR(Kernel_SVC, "Handle to non-existent resource limit instance used. Handle={:08X}",
+ resource_limit);
+ return ERR_INVALID_HANDLE;
+ }
+
+ const auto set_result = resource_limit_object->SetLimitValue(type, static_cast<s64>(value));
+ if (set_result.IsError()) {
+ 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));
+ return set_result;
+ }
+
+ return RESULT_SUCCESS;
+}
+
namespace {
struct FunctionDef {
using Func = void();
@@ -1405,8 +1518,8 @@ static const FunctionDef SVC_Table[] = {
{0x2D, nullptr, "UnmapPhysicalMemory"},
{0x2E, nullptr, "GetFutureThreadInfo"},
{0x2F, nullptr, "GetLastThreadInfo"},
- {0x30, nullptr, "GetResourceLimitLimitValue"},
- {0x31, nullptr, "GetResourceLimitCurrentValue"},
+ {0x30, SvcWrap<GetResourceLimitLimitValue>, "GetResourceLimitLimitValue"},
+ {0x31, SvcWrap<GetResourceLimitCurrentValue>, "GetResourceLimitCurrentValue"},
{0x32, SvcWrap<SetThreadActivity>, "SetThreadActivity"},
{0x33, SvcWrap<GetThreadContext>, "GetThreadContext"},
{0x34, SvcWrap<WaitForAddress>, "WaitForAddress"},
@@ -1482,8 +1595,8 @@ static const FunctionDef SVC_Table[] = {
{0x7A, nullptr, "StartProcess"},
{0x7B, nullptr, "TerminateProcess"},
{0x7C, SvcWrap<GetProcessInfo>, "GetProcessInfo"},
- {0x7D, nullptr, "CreateResourceLimit"},
- {0x7E, nullptr, "SetResourceLimitLimitValue"},
+ {0x7D, SvcWrap<CreateResourceLimit>, "CreateResourceLimit"},
+ {0x7E, SvcWrap<SetResourceLimitLimitValue>, "SetResourceLimitLimitValue"},
{0x7F, nullptr, "CallSecureMonitor"},
};
diff --git a/src/core/hle/kernel/svc_wrap.h b/src/core/hle/kernel/svc_wrap.h
index 233a99fb0..fa1116624 100644
--- a/src/core/hle/kernel/svc_wrap.h
+++ b/src/core/hle/kernel/svc_wrap.h
@@ -43,6 +43,14 @@ void SvcWrap() {
FuncReturn(func(static_cast<u32>(Param(0)), static_cast<u32>(Param(1))).raw);
}
+template <ResultCode func(u32*)>
+void SvcWrap() {
+ u32 param = 0;
+ const u32 retval = func(&param).raw;
+ Core::CurrentArmInterface().SetReg(1, param);
+ FuncReturn(retval);
+}
+
template <ResultCode func(u32*, u32)>
void SvcWrap() {
u32 param_1 = 0;
diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp
index c629f9357..9521431bb 100644
--- a/src/core/hle/service/acc/acc.cpp
+++ b/src/core/hle/service/acc/acc.cpp
@@ -21,17 +21,6 @@
namespace Service::Account {
-// TODO: RE this structure
-struct UserData {
- INSERT_PADDING_WORDS(1);
- u32 icon_id;
- u8 bg_color_id;
- INSERT_PADDING_BYTES(0x7);
- INSERT_PADDING_BYTES(0x10);
- INSERT_PADDING_BYTES(0x60);
-};
-static_assert(sizeof(UserData) == 0x80, "UserData structure has incorrect size");
-
// Smallest JPEG https://github.com/mathiasbynens/small/blob/master/jpeg.jpg
// used as a backup should the one on disk not exist
constexpr u32 backup_jpeg_size = 107;
@@ -72,9 +61,11 @@ private:
void Get(Kernel::HLERequestContext& ctx) {
LOG_INFO(Service_ACC, "called user_id={}", user_id.Format());
ProfileBase profile_base{};
- std::array<u8, MAX_DATA> data{};
+ ProfileData data{};
if (profile_manager.GetProfileBaseAndData(user_id, profile_base, data)) {
- ctx.WriteBuffer(data);
+ std::array<u8, sizeof(ProfileData)> raw_data;
+ std::memcpy(raw_data.data(), &data, sizeof(ProfileData));
+ ctx.WriteBuffer(raw_data);
IPC::ResponseBuilder rb{ctx, 16};
rb.Push(RESULT_SUCCESS);
rb.PushRaw(profile_base);
diff --git a/src/core/hle/service/acc/profile_manager.cpp b/src/core/hle/service/acc/profile_manager.cpp
index 968263846..1316d0b07 100644
--- a/src/core/hle/service/acc/profile_manager.cpp
+++ b/src/core/hle/service/acc/profile_manager.cpp
@@ -18,7 +18,7 @@ struct UserRaw {
UUID uuid2;
u64 timestamp;
ProfileUsername username;
- INSERT_PADDING_BYTES(0x80);
+ ProfileData extra_data;
};
static_assert(sizeof(UserRaw) == 0xC8, "UserRaw has incorrect size.");
@@ -346,7 +346,7 @@ void ProfileManager::ParseUserSaveFile() {
continue;
}
- AddUser({user.uuid, user.username, user.timestamp, {}, false});
+ AddUser({user.uuid, user.username, user.timestamp, user.extra_data, false});
}
std::stable_partition(profiles.begin(), profiles.end(),
@@ -361,6 +361,7 @@ void ProfileManager::WriteUserSaveFile() {
raw.users[i].uuid2 = profiles[i].user_uuid;
raw.users[i].uuid = profiles[i].user_uuid;
raw.users[i].timestamp = profiles[i].creation_time;
+ raw.users[i].extra_data = profiles[i].data;
}
const auto raw_path =
diff --git a/src/core/hle/service/acc/profile_manager.h b/src/core/hle/service/acc/profile_manager.h
index d2d8e6c6b..c4ce2e0b3 100644
--- a/src/core/hle/service/acc/profile_manager.h
+++ b/src/core/hle/service/acc/profile_manager.h
@@ -13,7 +13,6 @@
namespace Service::Account {
constexpr std::size_t MAX_USERS = 8;
-constexpr std::size_t MAX_DATA = 128;
constexpr u128 INVALID_UUID{{0, 0}};
struct UUID {
@@ -50,9 +49,20 @@ static_assert(sizeof(UUID) == 16, "UUID is an invalid size!");
constexpr std::size_t profile_username_size = 32;
using ProfileUsername = std::array<u8, profile_username_size>;
-using ProfileData = std::array<u8, MAX_DATA>;
using UserIDArray = std::array<UUID, MAX_USERS>;
+/// Contains extra data related to a user.
+/// TODO: RE this structure
+struct ProfileData {
+ INSERT_PADDING_WORDS(1);
+ u32 icon_id;
+ u8 bg_color_id;
+ INSERT_PADDING_BYTES(0x7);
+ INSERT_PADDING_BYTES(0x10);
+ INSERT_PADDING_BYTES(0x60);
+};
+static_assert(sizeof(ProfileData) == 0x80, "ProfileData structure has incorrect size");
+
/// This holds general information about a users profile. This is where we store all the information
/// based on a specific user
struct ProfileInfo {
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index ea8057b80..abff6544d 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -80,9 +80,9 @@ public:
struct LedPattern {
explicit LedPattern(u64 light1, u64 light2, u64 light3, u64 light4) {
position1.Assign(light1);
- position1.Assign(light2);
- position1.Assign(light3);
- position1.Assign(light4);
+ position2.Assign(light2);
+ position3.Assign(light3);
+ position4.Assign(light4);
}
union {
u64 raw{};