summaryrefslogtreecommitdiffstats
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/crypto/key_manager.cpp3
-rw-r--r--src/core/file_sys/card_image.cpp4
-rw-r--r--src/core/file_sys/card_image.h3
-rw-r--r--src/core/file_sys/content_archive.cpp3
-rw-r--r--src/core/file_sys/content_archive.h3
-rw-r--r--src/core/file_sys/ips_layer.cpp2
-rw-r--r--src/core/file_sys/partition_filesystem.cpp16
-rw-r--r--src/core/file_sys/partition_filesystem.h4
-rw-r--r--src/core/file_sys/patch_manager.cpp13
-rw-r--r--src/core/file_sys/submission_package.cpp4
-rw-r--r--src/core/file_sys/submission_package.h3
-rw-r--r--src/core/file_sys/vfs.cpp8
-rw-r--r--src/core/file_sys/vfs.h28
-rw-r--r--src/core/file_sys/vfs_layered.cpp3
-rw-r--r--src/core/file_sys/vfs_layered.h3
-rw-r--r--src/core/file_sys/vfs_real.cpp3
-rw-r--r--src/core/file_sys/vfs_real.h3
-rw-r--r--src/core/file_sys/vfs_vector.cpp7
-rw-r--r--src/core/file_sys/vfs_vector.h3
-rw-r--r--src/core/file_sys/xts_archive.cpp3
-rw-r--r--src/core/file_sys/xts_archive.h3
-rw-r--r--src/core/hle/ipc.h5
-rw-r--r--src/core/hle/kernel/errors.h21
-rw-r--r--src/core/hle/kernel/process.cpp6
-rw-r--r--src/core/hle/kernel/server_port.cpp4
-rw-r--r--src/core/hle/kernel/shared_memory.cpp7
-rw-r--r--src/core/hle/kernel/svc.cpp13
-rw-r--r--src/core/hle/kernel/vm_manager.cpp20
-rw-r--r--src/core/hle/kernel/vm_manager.h8
-rw-r--r--src/core/hle/service/acc/acc.cpp52
-rw-r--r--src/core/hle/service/acc/profile_manager.cpp71
-rw-r--r--src/core/hle/service/acc/profile_manager.h18
-rw-r--r--src/core/hle/service/am/am.cpp2
-rw-r--r--src/core/hle/service/aoc/aoc_u.cpp6
-rw-r--r--src/core/hle/service/filesystem/fsp_srv.cpp28
-rw-r--r--src/core/hle/service/hid/controllers/npad.cpp5
-rw-r--r--src/core/hle/service/ldr/ldr.cpp52
-rw-r--r--src/core/hle/service/nfp/nfp.cpp6
-rw-r--r--src/core/hle/service/nfp/nfp.h2
-rw-r--r--src/core/hle/service/usb/usb.cpp43
-rw-r--r--src/core/loader/nro.cpp21
-rw-r--r--src/core/loader/nro.h3
-rw-r--r--src/core/loader/nsp.cpp37
-rw-r--r--src/core/perf_stats.cpp4
44 files changed, 286 insertions, 270 deletions
diff --git a/src/core/crypto/key_manager.cpp b/src/core/crypto/key_manager.cpp
index fd0786068..89ae79eb3 100644
--- a/src/core/crypto/key_manager.cpp
+++ b/src/core/crypto/key_manager.cpp
@@ -395,7 +395,7 @@ static bool ValidCryptoRevisionString(std::string_view base, size_t begin, size_
if (base.size() < begin + length)
return false;
return std::all_of(base.begin() + begin, base.begin() + begin + length,
- [](u8 c) { return std::isdigit(c); });
+ [](u8 c) { return std::isxdigit(c); });
}
void KeyManager::LoadFromFile(const std::string& filename, bool is_title_keys) {
@@ -713,7 +713,6 @@ void KeyManager::DeriveBase() {
const auto sbk = GetKey(S128KeyType::SecureBoot);
const auto tsec = GetKey(S128KeyType::TSEC);
- const auto master_source = GetKey(S128KeyType::Source, static_cast<u64>(SourceKeyType::Master));
for (size_t i = 0; i < revisions.size(); ++i) {
if (!revisions[i])
diff --git a/src/core/file_sys/card_image.cpp b/src/core/file_sys/card_image.cpp
index ecdd7505b..1ece55731 100644
--- a/src/core/file_sys/card_image.cpp
+++ b/src/core/file_sys/card_image.cpp
@@ -168,10 +168,6 @@ VirtualDir XCI::GetParentDirectory() const {
return file->GetContainingDirectory();
}
-bool XCI::ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) {
- return false;
-}
-
Loader::ResultStatus XCI::AddNCAFromPartition(XCIPartition part) {
if (partitions[static_cast<std::size_t>(part)] == nullptr) {
return Loader::ResultStatus::ErrorXCIMissingPartition;
diff --git a/src/core/file_sys/card_image.h b/src/core/file_sys/card_image.h
index 48cbef666..8f62571cf 100644
--- a/src/core/file_sys/card_image.h
+++ b/src/core/file_sys/card_image.h
@@ -94,9 +94,6 @@ public:
VirtualDir GetParentDirectory() const override;
-protected:
- bool ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) override;
-
private:
Loader::ResultStatus AddNCAFromPartition(XCIPartition part);
diff --git a/src/core/file_sys/content_archive.cpp b/src/core/file_sys/content_archive.cpp
index 6c356d85d..77e04704e 100644
--- a/src/core/file_sys/content_archive.cpp
+++ b/src/core/file_sys/content_archive.cpp
@@ -546,7 +546,4 @@ u64 NCA::GetBaseIVFCOffset() const {
return ivfc_offset;
}
-bool NCA::ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) {
- return false;
-}
} // namespace FileSys
diff --git a/src/core/file_sys/content_archive.h b/src/core/file_sys/content_archive.h
index 1c903cd3f..211946686 100644
--- a/src/core/file_sys/content_archive.h
+++ b/src/core/file_sys/content_archive.h
@@ -100,9 +100,6 @@ public:
// Returns the base ivfc offset used in BKTR patching.
u64 GetBaseIVFCOffset() const;
-protected:
- bool ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) override;
-
private:
bool CheckSupportedNCA(const NCAHeader& header);
bool HandlePotentialHeaderDecryption();
diff --git a/src/core/file_sys/ips_layer.cpp b/src/core/file_sys/ips_layer.cpp
index 554eae9bc..999939d5a 100644
--- a/src/core/file_sys/ips_layer.cpp
+++ b/src/core/file_sys/ips_layer.cpp
@@ -99,7 +99,7 @@ VirtualFile PatchIPS(const VirtualFile& in, const VirtualFile& ips) {
u16 rle_size{};
if (ips->ReadObject(&rle_size, offset) != sizeof(u16))
return nullptr;
- rle_size = Common::swap16(data_size);
+ rle_size = Common::swap16(rle_size);
offset += sizeof(u16);
const auto data = ips->ReadByte(offset++);
diff --git a/src/core/file_sys/partition_filesystem.cpp b/src/core/file_sys/partition_filesystem.cpp
index 5791c76ff..a5259a593 100644
--- a/src/core/file_sys/partition_filesystem.cpp
+++ b/src/core/file_sys/partition_filesystem.cpp
@@ -83,7 +83,7 @@ std::vector<std::shared_ptr<VfsFile>> PartitionFilesystem::GetFiles() const {
}
std::vector<std::shared_ptr<VfsDirectory>> PartitionFilesystem::GetSubdirectories() const {
- return pfs_dirs;
+ return {};
}
std::string PartitionFilesystem::GetName() const {
@@ -103,18 +103,4 @@ void PartitionFilesystem::PrintDebugInfo() const {
pfs_files[i]->GetName(), pfs_files[i]->GetSize());
}
}
-
-bool PartitionFilesystem::ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) {
- const auto iter = std::find(pfs_files.begin(), pfs_files.end(), file);
- if (iter == pfs_files.end())
- return false;
-
- const std::ptrdiff_t offset = std::distance(pfs_files.begin(), iter);
- pfs_files[offset] = std::move(pfs_files.back());
- pfs_files.pop_back();
-
- pfs_dirs.emplace_back(std::move(dir));
-
- return true;
-}
} // namespace FileSys
diff --git a/src/core/file_sys/partition_filesystem.h b/src/core/file_sys/partition_filesystem.h
index 739c63a7f..248fdfdeb 100644
--- a/src/core/file_sys/partition_filesystem.h
+++ b/src/core/file_sys/partition_filesystem.h
@@ -35,9 +35,6 @@ public:
std::shared_ptr<VfsDirectory> GetParentDirectory() const override;
void PrintDebugInfo() const;
-protected:
- bool ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) override;
-
private:
struct Header {
u32_le magic;
@@ -84,7 +81,6 @@ private:
std::size_t content_offset = 0;
std::vector<VirtualFile> pfs_files;
- std::vector<VirtualDir> pfs_dirs;
};
} // namespace FileSys
diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp
index 1f4928562..cb457b987 100644
--- a/src/core/file_sys/patch_manager.cpp
+++ b/src/core/file_sys/patch_manager.cpp
@@ -61,13 +61,12 @@ VirtualDir PatchManager::PatchExeFS(VirtualDir exefs) const {
// Game Updates
const auto update_tid = GetUpdateTitleID(title_id);
const auto update = installed->GetEntry(update_tid, ContentRecordType::Program);
- if (update != nullptr) {
- if (update->GetStatus() == Loader::ResultStatus::ErrorMissingBKTRBaseRomFS &&
- update->GetExeFS() != nullptr) {
- LOG_INFO(Loader, " ExeFS: Update ({}) applied successfully",
- FormatTitleVersion(installed->GetEntryVersion(update_tid).get_value_or(0)));
- exefs = update->GetExeFS();
- }
+
+ if (update != nullptr && update->GetExeFS() != nullptr &&
+ update->GetStatus() == Loader::ResultStatus::ErrorMissingBKTRBaseRomFS) {
+ LOG_INFO(Loader, " ExeFS: Update ({}) applied successfully",
+ FormatTitleVersion(installed->GetEntryVersion(update_tid).get_value_or(0)));
+ exefs = update->GetExeFS();
}
return exefs;
diff --git a/src/core/file_sys/submission_package.cpp b/src/core/file_sys/submission_package.cpp
index ab5dc900c..2aaba4179 100644
--- a/src/core/file_sys/submission_package.cpp
+++ b/src/core/file_sys/submission_package.cpp
@@ -205,10 +205,6 @@ VirtualDir NSP::GetParentDirectory() const {
return file->GetContainingDirectory();
}
-bool NSP::ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) {
- return false;
-}
-
void NSP::InitializeExeFSAndRomFS(const std::vector<VirtualFile>& files) {
exefs = pfs;
diff --git a/src/core/file_sys/submission_package.h b/src/core/file_sys/submission_package.h
index da3dc5e9f..338080b7e 100644
--- a/src/core/file_sys/submission_package.h
+++ b/src/core/file_sys/submission_package.h
@@ -55,9 +55,6 @@ public:
VirtualDir GetParentDirectory() const override;
-protected:
- bool ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) override;
-
private:
void InitializeExeFSAndRomFS(const std::vector<VirtualFile>& files);
void ReadNCAs(const std::vector<VirtualFile>& files);
diff --git a/src/core/file_sys/vfs.cpp b/src/core/file_sys/vfs.cpp
index bfe50da73..3824c74e0 100644
--- a/src/core/file_sys/vfs.cpp
+++ b/src/core/file_sys/vfs.cpp
@@ -472,10 +472,14 @@ bool VfsRawCopy(const VirtualFile& src, const VirtualFile& dest, std::size_t blo
std::vector<u8> temp(std::min(block_size, src->GetSize()));
for (std::size_t i = 0; i < src->GetSize(); i += block_size) {
const auto read = std::min(block_size, src->GetSize() - i);
- const auto block = src->Read(temp.data(), read, i);
- if (dest->Write(temp.data(), read, i) != read)
+ if (src->Read(temp.data(), read, i) != read) {
return false;
+ }
+
+ if (dest->Write(temp.data(), read, i) != read) {
+ return false;
+ }
}
return true;
diff --git a/src/core/file_sys/vfs.h b/src/core/file_sys/vfs.h
index 7f0d520ca..09dc9f288 100644
--- a/src/core/file_sys/vfs.h
+++ b/src/core/file_sys/vfs.h
@@ -262,36 +262,8 @@ public:
// item name -> type.
virtual std::map<std::string, VfsEntryType, std::less<>> GetEntries() const;
- // Interprets the file with name file instead as a directory of type directory.
- // The directory must have a constructor that takes a single argument of type
- // std::shared_ptr<VfsFile>. Allows to reinterpret container files (i.e NCA, zip, XCI, etc) as a
- // subdirectory in one call.
- template <typename Directory>
- bool InterpretAsDirectory(std::string_view file) {
- auto file_p = GetFile(file);
-
- if (file_p == nullptr) {
- return false;
- }
-
- return ReplaceFileWithSubdirectory(file_p, std::make_shared<Directory>(file_p));
- }
-
- bool InterpretAsDirectory(const std::function<VirtualDir(VirtualFile)>& function,
- const std::string& file) {
- auto file_p = GetFile(file);
- if (file_p == nullptr)
- return false;
- return ReplaceFileWithSubdirectory(file_p, function(file_p));
- }
-
// Returns the full path of this directory as a string, recursively
virtual std::string GetFullPath() const;
-
-protected:
- // Backend for InterpretAsDirectory.
- // Removes all references to file and adds a reference to dir in the directory's implementation.
- virtual bool ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) = 0;
};
// A convenience partial-implementation of VfsDirectory that stubs out methods that should only work
diff --git a/src/core/file_sys/vfs_layered.cpp b/src/core/file_sys/vfs_layered.cpp
index bfee01725..338e398da 100644
--- a/src/core/file_sys/vfs_layered.cpp
+++ b/src/core/file_sys/vfs_layered.cpp
@@ -126,7 +126,4 @@ bool LayeredVfsDirectory::Rename(std::string_view name_) {
return true;
}
-bool LayeredVfsDirectory::ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) {
- return false;
-}
} // namespace FileSys
diff --git a/src/core/file_sys/vfs_layered.h b/src/core/file_sys/vfs_layered.h
index d85310f57..8a25c3428 100644
--- a/src/core/file_sys/vfs_layered.h
+++ b/src/core/file_sys/vfs_layered.h
@@ -39,9 +39,6 @@ public:
bool DeleteFile(std::string_view name) override;
bool Rename(std::string_view name) override;
-protected:
- bool ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) override;
-
private:
std::vector<VirtualDir> dirs;
std::string name;
diff --git a/src/core/file_sys/vfs_real.cpp b/src/core/file_sys/vfs_real.cpp
index 9defad04c..e21300a7c 100644
--- a/src/core/file_sys/vfs_real.cpp
+++ b/src/core/file_sys/vfs_real.cpp
@@ -430,7 +430,4 @@ std::map<std::string, VfsEntryType, std::less<>> RealVfsDirectory::GetEntries()
return out;
}
-bool RealVfsDirectory::ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) {
- return false;
-}
} // namespace FileSys
diff --git a/src/core/file_sys/vfs_real.h b/src/core/file_sys/vfs_real.h
index 5b61db90d..a0a857a31 100644
--- a/src/core/file_sys/vfs_real.h
+++ b/src/core/file_sys/vfs_real.h
@@ -100,9 +100,6 @@ public:
std::string GetFullPath() const override;
std::map<std::string, VfsEntryType, std::less<>> GetEntries() const override;
-protected:
- bool ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) override;
-
private:
RealVfsDirectory(RealVfsFilesystem& base, const std::string& path, Mode perms = Mode::Read);
diff --git a/src/core/file_sys/vfs_vector.cpp b/src/core/file_sys/vfs_vector.cpp
index 389c7e003..808f31e81 100644
--- a/src/core/file_sys/vfs_vector.cpp
+++ b/src/core/file_sys/vfs_vector.cpp
@@ -132,11 +132,4 @@ void VectorVfsDirectory::AddFile(VirtualFile file) {
void VectorVfsDirectory::AddDirectory(VirtualDir dir) {
dirs.push_back(std::move(dir));
}
-
-bool VectorVfsDirectory::ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) {
- if (!DeleteFile(file->GetName()))
- return false;
- dirs.emplace_back(std::move(dir));
- return true;
-}
} // namespace FileSys
diff --git a/src/core/file_sys/vfs_vector.h b/src/core/file_sys/vfs_vector.h
index 48a414c98..3e3f790c3 100644
--- a/src/core/file_sys/vfs_vector.h
+++ b/src/core/file_sys/vfs_vector.h
@@ -57,9 +57,6 @@ public:
virtual void AddFile(VirtualFile file);
virtual void AddDirectory(VirtualDir dir);
-protected:
- bool ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) override;
-
private:
std::vector<VirtualFile> files;
std::vector<VirtualDir> dirs;
diff --git a/src/core/file_sys/xts_archive.cpp b/src/core/file_sys/xts_archive.cpp
index b2b164368..eec51c64e 100644
--- a/src/core/file_sys/xts_archive.cpp
+++ b/src/core/file_sys/xts_archive.cpp
@@ -163,7 +163,4 @@ std::shared_ptr<VfsDirectory> NAX::GetParentDirectory() const {
return file->GetContainingDirectory();
}
-bool NAX::ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) {
- return false;
-}
} // namespace FileSys
diff --git a/src/core/file_sys/xts_archive.h b/src/core/file_sys/xts_archive.h
index 8fedd8585..7704dee90 100644
--- a/src/core/file_sys/xts_archive.h
+++ b/src/core/file_sys/xts_archive.h
@@ -51,9 +51,6 @@ public:
std::shared_ptr<VfsDirectory> GetParentDirectory() const override;
-protected:
- bool ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) override;
-
private:
Loader::ResultStatus Parse(std::string_view path);
diff --git a/src/core/hle/ipc.h b/src/core/hle/ipc.h
index 419f45896..ed84197b3 100644
--- a/src/core/hle/ipc.h
+++ b/src/core/hle/ipc.h
@@ -14,11 +14,6 @@ namespace IPC {
/// Size of the command buffer area, in 32-bit words.
constexpr std::size_t COMMAND_BUFFER_LENGTH = 0x100 / sizeof(u32);
-// These errors are commonly returned by invalid IPC translations, so alias them here for
-// convenience.
-// TODO(yuriks): These will probably go away once translation is implemented inside the kernel.
-constexpr auto ERR_INVALID_HANDLE = Kernel::ERR_INVALID_HANDLE_OS;
-
enum class ControlCommand : u32 {
ConvertSessionToDomain = 0,
ConvertDomainToSession = 1,
diff --git a/src/core/hle/kernel/errors.h b/src/core/hle/kernel/errors.h
index 885259618..ee698c8a7 100644
--- a/src/core/hle/kernel/errors.h
+++ b/src/core/hle/kernel/errors.h
@@ -10,11 +10,6 @@ namespace Kernel {
namespace ErrCodes {
enum {
- // TODO(Subv): Remove these 3DS OS error codes.
- SessionClosedByRemote = 26,
- NoPendingSessions = 35,
- InvalidBufferDescriptor = 48,
-
// Confirmed Switch OS error codes
MaxConnectionsReached = 7,
InvalidSize = 101,
@@ -26,6 +21,7 @@ enum {
InvalidThreadPriority = 112,
InvalidProcessorId = 113,
InvalidHandle = 114,
+ InvalidPointer = 115,
InvalidCombination = 116,
Timeout = 117,
SynchronizationCanceled = 118,
@@ -33,6 +29,7 @@ enum {
InvalidEnumValue = 120,
NoSuchEntry = 121,
AlreadyRegistered = 122,
+ SessionClosed = 123,
InvalidState = 125,
ResourceLimitExceeded = 132,
};
@@ -41,18 +38,14 @@ enum {
// WARNING: The kernel is quite inconsistent in it's usage of errors code. Make sure to always
// double check that the code matches before re-using the constant.
-// TODO(bunnei): Replace -1 with correct errors for Switch OS
constexpr ResultCode ERR_HANDLE_TABLE_FULL(ErrorModule::Kernel, ErrCodes::HandleTableFull);
-constexpr ResultCode ERR_SESSION_CLOSED_BY_REMOTE(-1);
+constexpr ResultCode ERR_SESSION_CLOSED_BY_REMOTE(ErrorModule::Kernel, ErrCodes::SessionClosed);
constexpr ResultCode ERR_PORT_NAME_TOO_LONG(ErrorModule::Kernel, ErrCodes::TooLarge);
constexpr ResultCode ERR_MAX_CONNECTIONS_REACHED(ErrorModule::Kernel,
ErrCodes::MaxConnectionsReached);
constexpr ResultCode ERR_INVALID_ENUM_VALUE(ErrorModule::Kernel, ErrCodes::InvalidEnumValue);
-constexpr ResultCode ERR_INVALID_ENUM_VALUE_FND(-1);
-constexpr ResultCode ERR_INVALID_COMBINATION(-1);
constexpr ResultCode ERR_INVALID_COMBINATION_KERNEL(ErrorModule::Kernel,
ErrCodes::InvalidCombination);
-constexpr ResultCode ERR_OUT_OF_MEMORY(-1);
constexpr ResultCode ERR_INVALID_ADDRESS(ErrorModule::Kernel, ErrCodes::InvalidAddress);
constexpr ResultCode ERR_INVALID_ADDRESS_STATE(ErrorModule::Kernel, ErrCodes::InvalidMemoryState);
constexpr ResultCode ERR_INVALID_MEMORY_PERMISSIONS(ErrorModule::Kernel,
@@ -65,14 +58,8 @@ constexpr ResultCode ERR_ALREADY_REGISTERED(ErrorModule::Kernel, ErrCodes::Alrea
constexpr ResultCode ERR_INVALID_STATE(ErrorModule::Kernel, ErrCodes::InvalidState);
constexpr ResultCode ERR_INVALID_THREAD_PRIORITY(ErrorModule::Kernel,
ErrCodes::InvalidThreadPriority);
-constexpr ResultCode ERR_INVALID_POINTER(-1);
-constexpr ResultCode ERR_INVALID_OBJECT_ADDR(-1);
-constexpr ResultCode ERR_NOT_AUTHORIZED(-1);
-/// Alternate code returned instead of ERR_INVALID_HANDLE in some code paths.
-constexpr ResultCode ERR_INVALID_HANDLE_OS(-1);
+constexpr ResultCode ERR_INVALID_POINTER(ErrorModule::Kernel, ErrCodes::InvalidPointer);
constexpr ResultCode ERR_NOT_FOUND(ErrorModule::Kernel, ErrCodes::NoSuchEntry);
constexpr ResultCode RESULT_TIMEOUT(ErrorModule::Kernel, ErrCodes::Timeout);
-/// Returned when Accept() is called on a port with no sessions to be accepted.
-constexpr ResultCode ERR_NO_PENDING_SESSIONS(-1);
} // namespace Kernel
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index 073dd5a7d..420218d59 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -232,6 +232,12 @@ void Process::LoadModule(CodeSet module_, VAddr base_addr) {
MapSegment(module_.CodeSegment(), VMAPermission::ReadExecute, MemoryState::CodeStatic);
MapSegment(module_.RODataSegment(), VMAPermission::Read, MemoryState::CodeMutable);
MapSegment(module_.DataSegment(), VMAPermission::ReadWrite, MemoryState::CodeMutable);
+
+ // Clear instruction cache in CPU JIT
+ Core::System::GetInstance().ArmInterface(0).ClearInstructionCache();
+ Core::System::GetInstance().ArmInterface(1).ClearInstructionCache();
+ Core::System::GetInstance().ArmInterface(2).ClearInstructionCache();
+ Core::System::GetInstance().ArmInterface(3).ClearInstructionCache();
}
ResultVal<VAddr> Process::HeapAllocate(VAddr target, u64 size, VMAPermission perms) {
diff --git a/src/core/hle/kernel/server_port.cpp b/src/core/hle/kernel/server_port.cpp
index 3792e3e18..d6ceeb2da 100644
--- a/src/core/hle/kernel/server_port.cpp
+++ b/src/core/hle/kernel/server_port.cpp
@@ -18,7 +18,7 @@ ServerPort::~ServerPort() = default;
ResultVal<SharedPtr<ServerSession>> ServerPort::Accept() {
if (pending_sessions.empty()) {
- return ERR_NO_PENDING_SESSIONS;
+ return ERR_NOT_FOUND;
}
auto session = std::move(pending_sessions.back());
@@ -28,7 +28,7 @@ ResultVal<SharedPtr<ServerSession>> ServerPort::Accept() {
bool ServerPort::ShouldWait(Thread* thread) const {
// If there are no pending sessions, we wait until a new one is added.
- return pending_sessions.size() == 0;
+ return pending_sessions.empty();
}
void ServerPort::Acquire(Thread* thread) {
diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp
index d061e6155..a016a86b6 100644
--- a/src/core/hle/kernel/shared_memory.cpp
+++ b/src/core/hle/kernel/shared_memory.cpp
@@ -80,20 +80,19 @@ SharedPtr<SharedMemory> SharedMemory::CreateForApplet(
ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermission permissions,
MemoryPermission other_permissions) {
-
- MemoryPermission own_other_permissions =
+ const MemoryPermission own_other_permissions =
target_process == owner_process ? this->permissions : this->other_permissions;
// Automatically allocated memory blocks can only be mapped with other_permissions = DontCare
if (base_address == 0 && other_permissions != MemoryPermission::DontCare) {
- return ERR_INVALID_COMBINATION;
+ return ERR_INVALID_MEMORY_PERMISSIONS;
}
// Error out if the requested permissions don't match what the creator process allows.
if (static_cast<u32>(permissions) & ~static_cast<u32>(own_other_permissions)) {
LOG_ERROR(Kernel, "cannot map id={}, address=0x{:X} name={}, permissions don't match",
GetObjectId(), address, name);
- return ERR_INVALID_COMBINATION;
+ return ERR_INVALID_MEMORY_PERMISSIONS;
}
// Error out if the provided permissions are not compatible with what the creator process needs.
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 9a783d524..a5302d924 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -594,16 +594,17 @@ static ResultCode SetThreadPriority(Handle handle, u32 priority) {
}
const auto* const current_process = Core::CurrentProcess();
- SharedPtr<Thread> thread = current_process->GetHandleTable().Get<Thread>(handle);
- if (!thread) {
- return ERR_INVALID_HANDLE;
- }
// Note: The kernel uses the current process's resource limit instead of
// the one from the thread owner's resource limit.
const ResourceLimit& resource_limit = current_process->GetResourceLimit();
if (resource_limit.GetMaxResourceValue(ResourceType::Priority) > priority) {
- return ERR_NOT_AUTHORIZED;
+ return ERR_INVALID_THREAD_PRIORITY;
+ }
+
+ SharedPtr<Thread> thread = current_process->GetHandleTable().Get<Thread>(handle);
+ if (!thread) {
+ return ERR_INVALID_HANDLE;
}
thread->SetPriority(priority);
@@ -745,7 +746,7 @@ static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, V
auto* const current_process = Core::CurrentProcess();
const ResourceLimit& resource_limit = current_process->GetResourceLimit();
if (resource_limit.GetMaxResourceValue(ResourceType::Priority) > priority) {
- return ERR_NOT_AUTHORIZED;
+ return ERR_INVALID_THREAD_PRIORITY;
}
if (processor_id == THREADPROCESSORID_DEFAULT) {
diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp
index e1a34eef1..1a92c8f70 100644
--- a/src/core/hle/kernel/vm_manager.cpp
+++ b/src/core/hle/kernel/vm_manager.cpp
@@ -143,6 +143,26 @@ ResultVal<VMManager::VMAHandle> VMManager::MapBackingMemory(VAddr target, u8* me
return MakeResult<VMAHandle>(MergeAdjacent(vma_handle));
}
+ResultVal<VAddr> VMManager::FindFreeRegion(u64 size) const {
+ // Find the first Free VMA.
+ const VAddr base = GetASLRRegionBaseAddress();
+ const VMAHandle vma_handle = std::find_if(vma_map.begin(), vma_map.end(), [&](const auto& vma) {
+ if (vma.second.type != VMAType::Free)
+ return false;
+
+ const VAddr vma_end = vma.second.base + vma.second.size;
+ return vma_end > base && vma_end >= base + size;
+ });
+
+ if (vma_handle == vma_map.end()) {
+ // TODO(Subv): Find the correct error code here.
+ return ResultCode(-1);
+ }
+
+ const VAddr target = std::max(base, vma_handle->second.base);
+ return MakeResult<VAddr>(target);
+}
+
ResultVal<VMManager::VMAHandle> VMManager::MapMMIO(VAddr target, PAddr paddr, u64 size,
MemoryState state,
Memory::MemoryHookPointer mmio_handler) {
diff --git a/src/core/hle/kernel/vm_manager.h b/src/core/hle/kernel/vm_manager.h
index 84c890224..2447cbb8f 100644
--- a/src/core/hle/kernel/vm_manager.h
+++ b/src/core/hle/kernel/vm_manager.h
@@ -158,6 +158,14 @@ public:
ResultVal<VMAHandle> MapBackingMemory(VAddr target, u8* memory, u64 size, MemoryState state);
/**
+ * Finds the first free address that can hold a region of the desired size.
+ *
+ * @param size Size of the desired region.
+ * @return The found free address.
+ */
+ ResultVal<VAddr> FindFreeRegion(u64 size) const;
+
+ /**
* Maps a memory-mapped IO region at a given address.
*
* @param target The guest address to start the mapping at.
diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp
index cf065c2e0..c6437a671 100644
--- a/src/core/hle/service/acc/acc.cpp
+++ b/src/core/hle/service/acc/acc.cpp
@@ -21,8 +21,6 @@
namespace Service::Account {
-constexpr u32 MAX_JPEG_IMAGE_SIZE = 0x20000;
-
// TODO: RE this structure
struct UserData {
INSERT_PADDING_WORDS(1);
@@ -34,11 +32,29 @@ struct UserData {
};
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;
+constexpr std::array<u8, backup_jpeg_size> backup_jpeg{{
+ 0xff, 0xd8, 0xff, 0xdb, 0x00, 0x43, 0x00, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x02, 0x02,
+ 0x02, 0x03, 0x03, 0x03, 0x03, 0x04, 0x06, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08, 0x06, 0x06, 0x05,
+ 0x06, 0x09, 0x08, 0x0a, 0x0a, 0x09, 0x08, 0x09, 0x09, 0x0a, 0x0c, 0x0f, 0x0c, 0x0a, 0x0b, 0x0e,
+ 0x0b, 0x09, 0x09, 0x0d, 0x11, 0x0d, 0x0e, 0x0f, 0x10, 0x10, 0x11, 0x10, 0x0a, 0x0c, 0x12, 0x13,
+ 0x12, 0x10, 0x13, 0x0f, 0x10, 0x10, 0x10, 0xff, 0xc9, 0x00, 0x0b, 0x08, 0x00, 0x01, 0x00, 0x01,
+ 0x01, 0x01, 0x11, 0x00, 0xff, 0xcc, 0x00, 0x06, 0x00, 0x10, 0x10, 0x05, 0xff, 0xda, 0x00, 0x08,
+ 0x01, 0x01, 0x00, 0x00, 0x3f, 0x00, 0xd2, 0xcf, 0x20, 0xff, 0xd9,
+}};
+
static std::string GetImagePath(UUID uuid) {
return FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) +
"/system/save/8000000000000010/su/avators/" + uuid.FormatSwitch() + ".jpg";
}
+static constexpr u32 SanitizeJPEGSize(std::size_t size) {
+ constexpr std::size_t max_jpeg_image_size = 0x20000;
+ return static_cast<u32>(std::min(size, max_jpeg_image_size));
+}
+
class IProfile final : public ServiceFramework<IProfile> {
public:
explicit IProfile(UUID user_id, ProfileManager& profile_manager)
@@ -86,43 +102,29 @@ private:
void LoadImage(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_ACC, "called");
- // 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;
- static constexpr std::array<u8, backup_jpeg_size> backup_jpeg{
- 0xff, 0xd8, 0xff, 0xdb, 0x00, 0x43, 0x00, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03,
- 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x04, 0x06, 0x04, 0x04, 0x04, 0x04, 0x04,
- 0x08, 0x06, 0x06, 0x05, 0x06, 0x09, 0x08, 0x0a, 0x0a, 0x09, 0x08, 0x09, 0x09, 0x0a,
- 0x0c, 0x0f, 0x0c, 0x0a, 0x0b, 0x0e, 0x0b, 0x09, 0x09, 0x0d, 0x11, 0x0d, 0x0e, 0x0f,
- 0x10, 0x10, 0x11, 0x10, 0x0a, 0x0c, 0x12, 0x13, 0x12, 0x10, 0x13, 0x0f, 0x10, 0x10,
- 0x10, 0xff, 0xc9, 0x00, 0x0b, 0x08, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x11, 0x00,
- 0xff, 0xcc, 0x00, 0x06, 0x00, 0x10, 0x10, 0x05, 0xff, 0xda, 0x00, 0x08, 0x01, 0x01,
- 0x00, 0x00, 0x3f, 0x00, 0xd2, 0xcf, 0x20, 0xff, 0xd9,
- };
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
const FileUtil::IOFile image(GetImagePath(user_id), "rb");
-
if (!image.IsOpen()) {
LOG_WARNING(Service_ACC,
"Failed to load user provided image! Falling back to built-in backup...");
ctx.WriteBuffer(backup_jpeg);
rb.Push<u32>(backup_jpeg_size);
- } else {
- const auto size = std::min<u32>(image.GetSize(), MAX_JPEG_IMAGE_SIZE);
- std::vector<u8> buffer(size);
- image.ReadBytes(buffer.data(), buffer.size());
-
- ctx.WriteBuffer(buffer.data(), buffer.size());
- rb.Push<u32>(buffer.size());
+ return;
}
+
+ const u32 size = SanitizeJPEGSize(image.GetSize());
+ std::vector<u8> buffer(size);
+ image.ReadBytes(buffer.data(), buffer.size());
+
+ ctx.WriteBuffer(buffer.data(), buffer.size());
+ rb.Push<u32>(size);
}
void GetImageSize(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_ACC, "called");
- constexpr u32 backup_jpeg_size = 107;
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
@@ -133,7 +135,7 @@ private:
"Failed to load user provided image! Falling back to built-in backup...");
rb.Push<u32>(backup_jpeg_size);
} else {
- rb.Push<u32>(std::min<u32>(image.GetSize(), MAX_JPEG_IMAGE_SIZE));
+ rb.Push<u32>(SanitizeJPEGSize(image.GetSize()));
}
}
diff --git a/src/core/hle/service/acc/profile_manager.cpp b/src/core/hle/service/acc/profile_manager.cpp
index 06f7d1b15..3cac1b4ff 100644
--- a/src/core/hle/service/acc/profile_manager.cpp
+++ b/src/core/hle/service/acc/profile_manager.cpp
@@ -3,7 +3,7 @@
// Refer to the license.txt file included.
#include <random>
-#include <boost/optional.hpp>
+
#include "common/file_util.h"
#include "core/hle/service/acc/profile_manager.h"
#include "core/settings.h"
@@ -58,11 +58,11 @@ ProfileManager::~ProfileManager() {
/// After a users creation it needs to be "registered" to the system. AddToProfiles handles the
/// internal management of the users profiles
-boost::optional<std::size_t> ProfileManager::AddToProfiles(const ProfileInfo& user) {
+std::optional<std::size_t> ProfileManager::AddToProfiles(const ProfileInfo& profile) {
if (user_count >= MAX_USERS) {
- return boost::none;
+ return {};
}
- profiles[user_count] = user;
+ profiles[user_count] = profile;
return user_count++;
}
@@ -81,7 +81,7 @@ bool ProfileManager::RemoveProfileAtIndex(std::size_t index) {
/// Helper function to register a user to the system
ResultCode ProfileManager::AddUser(const ProfileInfo& user) {
- if (AddToProfiles(user) == boost::none) {
+ if (!AddToProfiles(user)) {
return ERROR_TOO_MANY_USERS;
}
return RESULT_SUCCESS;
@@ -126,37 +126,40 @@ ResultCode ProfileManager::CreateNewUser(UUID uuid, const std::string& username)
return CreateNewUser(uuid, username_output);
}
-boost::optional<UUID> ProfileManager::GetUser(std::size_t index) const {
- if (index >= MAX_USERS)
- return boost::none;
+std::optional<UUID> ProfileManager::GetUser(std::size_t index) const {
+ if (index >= MAX_USERS) {
+ return {};
+ }
+
return profiles[index].user_uuid;
}
/// Returns a users profile index based on their user id.
-boost::optional<std::size_t> ProfileManager::GetUserIndex(const UUID& uuid) const {
+std::optional<std::size_t> ProfileManager::GetUserIndex(const UUID& uuid) const {
if (!uuid) {
- return boost::none;
+ return {};
}
- auto iter = std::find_if(profiles.begin(), profiles.end(),
- [&uuid](const ProfileInfo& p) { return p.user_uuid == uuid; });
+
+ const auto iter = std::find_if(profiles.begin(), profiles.end(),
+ [&uuid](const ProfileInfo& p) { return p.user_uuid == uuid; });
if (iter == profiles.end()) {
- return boost::none;
+ return {};
}
+
return static_cast<std::size_t>(std::distance(profiles.begin(), iter));
}
/// Returns a users profile index based on their profile
-boost::optional<std::size_t> ProfileManager::GetUserIndex(const ProfileInfo& user) const {
+std::optional<std::size_t> ProfileManager::GetUserIndex(const ProfileInfo& user) const {
return GetUserIndex(user.user_uuid);
}
/// Returns the data structure used by the switch when GetProfileBase is called on acc:*
-bool ProfileManager::GetProfileBase(boost::optional<std::size_t> index,
- ProfileBase& profile) const {
- if (index == boost::none || index >= MAX_USERS) {
+bool ProfileManager::GetProfileBase(std::optional<std::size_t> index, ProfileBase& profile) const {
+ if (!index || index >= MAX_USERS) {
return false;
}
- const auto& prof_info = profiles[index.get()];
+ const auto& prof_info = profiles[*index];
profile.user_uuid = prof_info.user_uuid;
profile.username = prof_info.username;
profile.timestamp = prof_info.creation_time;
@@ -165,7 +168,7 @@ bool ProfileManager::GetProfileBase(boost::optional<std::size_t> index,
/// Returns the data structure used by the switch when GetProfileBase is called on acc:*
bool ProfileManager::GetProfileBase(UUID uuid, ProfileBase& profile) const {
- auto idx = GetUserIndex(uuid);
+ const auto idx = GetUserIndex(uuid);
return GetProfileBase(idx, profile);
}
@@ -192,7 +195,7 @@ std::size_t ProfileManager::GetOpenUserCount() const {
/// Checks if a user id exists in our profile manager
bool ProfileManager::UserExists(UUID uuid) const {
- return (GetUserIndex(uuid) != boost::none);
+ return GetUserIndex(uuid) != std::nullopt;
}
bool ProfileManager::UserExistsIndex(std::size_t index) const {
@@ -203,21 +206,23 @@ bool ProfileManager::UserExistsIndex(std::size_t index) const {
/// Opens a specific user
void ProfileManager::OpenUser(UUID uuid) {
- auto idx = GetUserIndex(uuid);
- if (idx == boost::none) {
+ const auto idx = GetUserIndex(uuid);
+ if (!idx) {
return;
}
- profiles[idx.get()].is_open = true;
+
+ profiles[*idx].is_open = true;
last_opened_user = uuid;
}
/// Closes a specific user
void ProfileManager::CloseUser(UUID uuid) {
- auto idx = GetUserIndex(uuid);
- if (idx == boost::none) {
+ const auto idx = GetUserIndex(uuid);
+ if (!idx) {
return;
}
- profiles[idx.get()].is_open = false;
+
+ profiles[*idx].is_open = false;
}
/// Gets all valid user ids on the system
@@ -247,10 +252,10 @@ UUID ProfileManager::GetLastOpenedUser() const {
}
/// Return the users profile base and the unknown arbitary data.
-bool ProfileManager::GetProfileBaseAndData(boost::optional<std::size_t> index, ProfileBase& profile,
+bool ProfileManager::GetProfileBaseAndData(std::optional<std::size_t> index, ProfileBase& profile,
ProfileData& data) const {
if (GetProfileBase(index, profile)) {
- data = profiles[index.get()].data;
+ data = profiles[*index].data;
return true;
}
return false;
@@ -259,7 +264,7 @@ bool ProfileManager::GetProfileBaseAndData(boost::optional<std::size_t> index, P
/// Return the users profile base and the unknown arbitary data.
bool ProfileManager::GetProfileBaseAndData(UUID uuid, ProfileBase& profile,
ProfileData& data) const {
- auto idx = GetUserIndex(uuid);
+ const auto idx = GetUserIndex(uuid);
return GetProfileBaseAndData(idx, profile, data);
}
@@ -277,8 +282,8 @@ bool ProfileManager::CanSystemRegisterUser() const {
}
bool ProfileManager::RemoveUser(UUID uuid) {
- auto index = GetUserIndex(uuid);
- if (index == boost::none) {
+ const auto index = GetUserIndex(uuid);
+ if (!index) {
return false;
}
@@ -289,8 +294,8 @@ bool ProfileManager::RemoveUser(UUID uuid) {
}
bool ProfileManager::SetProfileBase(UUID uuid, const ProfileBase& profile_new) {
- auto index = GetUserIndex(uuid);
- if (profile_new.user_uuid == UUID(INVALID_UUID) || index == boost::none) {
+ const auto index = GetUserIndex(uuid);
+ if (!index || profile_new.user_uuid == UUID(INVALID_UUID)) {
return false;
}
diff --git a/src/core/hle/service/acc/profile_manager.h b/src/core/hle/service/acc/profile_manager.h
index 235208d56..1cd2e51b2 100644
--- a/src/core/hle/service/acc/profile_manager.h
+++ b/src/core/hle/service/acc/profile_manager.h
@@ -5,8 +5,8 @@
#pragma once
#include <array>
+#include <optional>
-#include "boost/optional.hpp"
#include "common/common_types.h"
#include "common/swap.h"
#include "core/hle/result.h"
@@ -96,13 +96,13 @@ public:
ResultCode AddUser(const ProfileInfo& user);
ResultCode CreateNewUser(UUID uuid, const ProfileUsername& username);
ResultCode CreateNewUser(UUID uuid, const std::string& username);
- boost::optional<UUID> GetUser(std::size_t index) const;
- boost::optional<std::size_t> GetUserIndex(const UUID& uuid) const;
- boost::optional<std::size_t> GetUserIndex(const ProfileInfo& user) const;
- bool GetProfileBase(boost::optional<std::size_t> index, ProfileBase& profile) const;
+ std::optional<UUID> GetUser(std::size_t index) const;
+ std::optional<std::size_t> GetUserIndex(const UUID& uuid) const;
+ std::optional<std::size_t> GetUserIndex(const ProfileInfo& user) const;
+ bool GetProfileBase(std::optional<std::size_t> index, ProfileBase& profile) const;
bool GetProfileBase(UUID uuid, ProfileBase& profile) const;
bool GetProfileBase(const ProfileInfo& user, ProfileBase& profile) const;
- bool GetProfileBaseAndData(boost::optional<std::size_t> index, ProfileBase& profile,
+ bool GetProfileBaseAndData(std::optional<std::size_t> index, ProfileBase& profile,
ProfileData& data) const;
bool GetProfileBaseAndData(UUID uuid, ProfileBase& profile, ProfileData& data) const;
bool GetProfileBaseAndData(const ProfileInfo& user, ProfileBase& profile,
@@ -120,16 +120,16 @@ public:
bool CanSystemRegisterUser() const;
bool RemoveUser(UUID uuid);
- bool SetProfileBase(UUID uuid, const ProfileBase& profile);
+ bool SetProfileBase(UUID uuid, const ProfileBase& profile_new);
private:
void ParseUserSaveFile();
void WriteUserSaveFile();
+ std::optional<std::size_t> AddToProfiles(const ProfileInfo& profile);
+ bool RemoveProfileAtIndex(std::size_t index);
std::array<ProfileInfo, MAX_USERS> profiles{};
std::size_t user_count = 0;
- boost::optional<std::size_t> AddToProfiles(const ProfileInfo& profile);
- bool RemoveProfileAtIndex(std::size_t index);
UUID last_opened_user{INVALID_UUID};
};
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 4ed66d817..59aafd616 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -743,7 +743,7 @@ void IApplicationFunctions::PopLaunchParameter(Kernel::HLERequestContext& ctx) {
Account::ProfileManager profile_manager{};
const auto uuid = profile_manager.GetUser(Settings::values.current_user);
- ASSERT(uuid != boost::none);
+ ASSERT(uuid != std::nullopt);
params.current_user = uuid->uuid;
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
diff --git a/src/core/hle/service/aoc/aoc_u.cpp b/src/core/hle/service/aoc/aoc_u.cpp
index 428069df2..54305cf05 100644
--- a/src/core/hle/service/aoc/aoc_u.cpp
+++ b/src/core/hle/service/aoc/aoc_u.cpp
@@ -24,8 +24,8 @@ namespace Service::AOC {
constexpr u64 DLC_BASE_TITLE_ID_MASK = 0xFFFFFFFFFFFFE000;
constexpr u64 DLC_BASE_TO_AOC_ID = 0x1000;
-static bool CheckAOCTitleIDMatchesBase(u64 base, u64 aoc) {
- return (aoc & DLC_BASE_TITLE_ID_MASK) == base;
+static bool CheckAOCTitleIDMatchesBase(u64 title_id, u64 base) {
+ return (title_id & DLC_BASE_TITLE_ID_MASK) == base;
}
static std::vector<u64> AccumulateAOCTitleIDs() {
@@ -74,7 +74,7 @@ void AOC_U::CountAddOnContent(Kernel::HLERequestContext& ctx) {
const auto current = Core::System::GetInstance().CurrentProcess()->GetTitleID();
rb.Push<u32>(static_cast<u32>(
std::count_if(add_on_content.begin(), add_on_content.end(),
- [&current](u64 tid) { return (tid & DLC_BASE_TITLE_ID_MASK) == current; })));
+ [current](u64 tid) { return CheckAOCTitleIDMatchesBase(tid, current); })));
}
void AOC_U::ListAddOnContent(Kernel::HLERequestContext& ctx) {
diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp
index c87721c39..c1c83a11d 100644
--- a/src/core/hle/service/filesystem/fsp_srv.cpp
+++ b/src/core/hle/service/filesystem/fsp_srv.cpp
@@ -273,8 +273,8 @@ public:
{0, &IFileSystem::CreateFile, "CreateFile"},
{1, &IFileSystem::DeleteFile, "DeleteFile"},
{2, &IFileSystem::CreateDirectory, "CreateDirectory"},
- {3, nullptr, "DeleteDirectory"},
- {4, nullptr, "DeleteDirectoryRecursively"},
+ {3, &IFileSystem::DeleteDirectory, "DeleteDirectory"},
+ {4, &IFileSystem::DeleteDirectoryRecursively, "DeleteDirectoryRecursively"},
{5, &IFileSystem::RenameFile, "RenameFile"},
{6, nullptr, "RenameDirectory"},
{7, &IFileSystem::GetEntryType, "GetEntryType"},
@@ -329,6 +329,30 @@ public:
rb.Push(backend.CreateDirectory(name));
}
+ void DeleteDirectory(Kernel::HLERequestContext& ctx) {
+ const IPC::RequestParser rp{ctx};
+
+ const auto file_buffer = ctx.ReadBuffer();
+ std::string name = Common::StringFromBuffer(file_buffer);
+
+ LOG_DEBUG(Service_FS, "called directory {}", name);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(backend.DeleteDirectory(name));
+ }
+
+ void DeleteDirectoryRecursively(Kernel::HLERequestContext& ctx) {
+ const IPC::RequestParser rp{ctx};
+
+ const auto file_buffer = ctx.ReadBuffer();
+ std::string name = Common::StringFromBuffer(file_buffer);
+
+ LOG_DEBUG(Service_FS, "called directory {}", name);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(backend.DeleteDirectoryRecursively(name));
+ }
+
void RenameFile(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index b06e65a77..4b4d1324f 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -108,9 +108,10 @@ void Controller_NPad::OnInit() {
styleset_changed_event =
Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "npad:NpadStyleSetChanged");
- if (!IsControllerActivated())
+ if (!IsControllerActivated()) {
return;
- std::size_t controller{};
+ }
+
if (style.raw == 0) {
// We want to support all controllers
style.handheld.Assign(1);
diff --git a/src/core/hle/service/ldr/ldr.cpp b/src/core/hle/service/ldr/ldr.cpp
index ec32faf15..d607d985e 100644
--- a/src/core/hle/service/ldr/ldr.cpp
+++ b/src/core/hle/service/ldr/ldr.cpp
@@ -3,9 +3,13 @@
// Refer to the license.txt file included.
#include <memory>
+#include <fmt/format.h>
+#include "core/hle/ipc_helpers.h"
+#include "core/hle/kernel/process.h"
#include "core/hle/service/ldr/ldr.h"
#include "core/hle/service/service.h"
+#include "core/loader/nro.h"
namespace Service::LDR {
@@ -59,16 +63,58 @@ public:
explicit RelocatableObject() : ServiceFramework{"ldr:ro"} {
// clang-format off
static const FunctionInfo functions[] = {
- {0, nullptr, "LoadNro"},
+ {0, &RelocatableObject::LoadNro, "LoadNro"},
{1, nullptr, "UnloadNro"},
- {2, nullptr, "LoadNrr"},
+ {2, &RelocatableObject::LoadNrr, "LoadNrr"},
{3, nullptr, "UnloadNrr"},
- {4, nullptr, "Initialize"},
+ {4, &RelocatableObject::Initialize, "Initialize"},
};
// clang-format on
RegisterHandlers(functions);
}
+
+ void LoadNrr(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_SUCCESS);
+ LOG_WARNING(Service_LDR, "(STUBBED) called");
+ }
+
+ void LoadNro(Kernel::HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ rp.Skip(2, false);
+ const VAddr nro_addr{rp.Pop<VAddr>()};
+ const u64 nro_size{rp.Pop<u64>()};
+ const VAddr bss_addr{rp.Pop<VAddr>()};
+ const u64 bss_size{rp.Pop<u64>()};
+
+ // Read NRO data from memory
+ std::vector<u8> nro_data(nro_size);
+ Memory::ReadBlock(nro_addr, nro_data.data(), nro_size);
+
+ // Load NRO as new executable module
+ const VAddr addr{*Core::CurrentProcess()->VMManager().FindFreeRegion(nro_size + bss_size)};
+ Loader::AppLoader_NRO::LoadNro(nro_data, fmt::format("nro-{:08x}", addr), addr);
+
+ // TODO(bunnei): This is an incomplete implementation. It was tested with Super Mario Party.
+ // It is currently missing:
+ // - Signature checks with LoadNRR
+ // - Checking if a module has already been loaded
+ // - Using/validating BSS, etc. params (these are used from NRO header instead)
+ // - Error checking
+ // - ...Probably other things
+
+ IPC::ResponseBuilder rb{ctx, 4};
+ rb.Push(RESULT_SUCCESS);
+ rb.Push(addr);
+ LOG_WARNING(Service_LDR, "(STUBBED) called");
+ }
+
+ void Initialize(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_SUCCESS);
+ LOG_WARNING(Service_LDR, "(STUBBED) called");
+ }
};
void InstallInterfaces(SM::ServiceManager& sm) {
diff --git a/src/core/hle/service/nfp/nfp.cpp b/src/core/hle/service/nfp/nfp.cpp
index 9a4eb9301..c1af878fe 100644
--- a/src/core/hle/service/nfp/nfp.cpp
+++ b/src/core/hle/service/nfp/nfp.cpp
@@ -328,13 +328,15 @@ void Module::Interface::CreateUserInterface(Kernel::HLERequestContext& ctx) {
rb.PushIpcInterface<IUser>(*this);
}
-void Module::Interface::LoadAmiibo(const std::vector<u8>& buffer) {
+bool Module::Interface::LoadAmiibo(const std::vector<u8>& buffer) {
std::lock_guard<std::recursive_mutex> lock(HLE::g_hle_lock);
if (buffer.size() < sizeof(AmiiboFile)) {
- return; // Failed to load file
+ return false;
}
+
std::memcpy(&amiibo, buffer.data(), sizeof(amiibo));
nfc_tag_load->Signal();
+ return true;
}
const Kernel::SharedPtr<Kernel::Event>& Module::Interface::GetNFCEvent() const {
return nfc_tag_load;
diff --git a/src/core/hle/service/nfp/nfp.h b/src/core/hle/service/nfp/nfp.h
index 46370dedd..5c0ae8a54 100644
--- a/src/core/hle/service/nfp/nfp.h
+++ b/src/core/hle/service/nfp/nfp.h
@@ -32,7 +32,7 @@ public:
static_assert(sizeof(AmiiboFile) == 0x94, "AmiiboFile is an invalid size");
void CreateUserInterface(Kernel::HLERequestContext& ctx);
- void LoadAmiibo(const std::vector<u8>& buffer);
+ bool LoadAmiibo(const std::vector<u8>& buffer);
const Kernel::SharedPtr<Kernel::Event>& GetNFCEvent() const;
const AmiiboFile& GetAmiiboBuffer() const;
diff --git a/src/core/hle/service/usb/usb.cpp b/src/core/hle/service/usb/usb.cpp
index e7fb5a419..c489da071 100644
--- a/src/core/hle/service/usb/usb.cpp
+++ b/src/core/hle/service/usb/usb.cpp
@@ -67,15 +67,15 @@ public:
explicit IClientEpSession() : ServiceFramework{"IClientEpSession"} {
// clang-format off
static const FunctionInfo functions[] = {
- {0, nullptr, "Unknown1"},
- {1, nullptr, "Unknown2"},
- {2, nullptr, "Unknown3"},
- {3, nullptr, "Unknown4"},
+ {0, nullptr, "Open"},
+ {1, nullptr, "Close"},
+ {2, nullptr, "Unknown1"},
+ {3, nullptr, "Populate"},
{4, nullptr, "PostBufferAsync"},
- {5, nullptr, "Unknown5"},
- {6, nullptr, "Unknown6"},
- {7, nullptr, "Unknown7"},
- {8, nullptr, "Unknown8"},
+ {5, nullptr, "GetXferReport"},
+ {6, nullptr, "Unknown2"},
+ {7, nullptr, "Unknown3"},
+ {8, nullptr, "Unknown4"},
};
// clang-format on
@@ -89,15 +89,15 @@ public:
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "Unknown1"},
- {1, nullptr, "Unknown2"},
- {2, nullptr, "Unknown3"},
- {3, nullptr, "Unknown4"},
- {4, nullptr, "Unknown5"},
+ {1, nullptr, "SetInterface"},
+ {2, nullptr, "GetInterface"},
+ {3, nullptr, "GetAlternateInterface"},
+ {4, nullptr, "GetCurrentFrame"},
{5, nullptr, "CtrlXferAsync"},
- {6, nullptr, "Unknown6"},
+ {6, nullptr, "Unknown2"},
{7, nullptr, "GetCtrlXferReport"},
- {8, nullptr, "Unknown7"},
- {9, nullptr, "GetClientEpSession"},
+ {8, nullptr, "ResetDevice"},
+ {9, nullptr, "OpenUsbEp"},
};
// clang-format on
@@ -111,13 +111,14 @@ public:
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "BindClientProcess"},
- {1, nullptr, "Unknown1"},
- {2, nullptr, "Unknown2"},
- {3, nullptr, "Unknown3"},
- {4, nullptr, "Unknown4"},
- {5, nullptr, "Unknown5"},
+ {1, nullptr, "QueryAllInterfaces"},
+ {2, nullptr, "QueryAvailableInterfaces"},
+ {3, nullptr, "QueryAcquiredInterfaces"},
+ {4, nullptr, "CreateInterfaceAvailableEvent"},
+ {5, nullptr, "DestroyInterfaceAvailableEvent"},
{6, nullptr, "GetInterfaceStateChangeEvent"},
- {7, nullptr, "GetClientIfSession"},
+ {7, nullptr, "AcquireUsbIf"},
+ {8, nullptr, "Unknown1"},
};
// clang-format on
diff --git a/src/core/loader/nro.cpp b/src/core/loader/nro.cpp
index 243b499f2..bc8e402a8 100644
--- a/src/core/loader/nro.cpp
+++ b/src/core/loader/nro.cpp
@@ -127,18 +127,23 @@ static constexpr u32 PageAlignSize(u32 size) {
return (size + Memory::PAGE_MASK) & ~Memory::PAGE_MASK;
}
-bool AppLoader_NRO::LoadNro(const FileSys::VfsFile& file, VAddr load_base) {
- // Read NSO header
- NroHeader nro_header{};
- if (sizeof(NroHeader) != file.ReadObject(&nro_header)) {
+/*static*/ bool AppLoader_NRO::LoadNro(const std::vector<u8>& data, const std::string& name,
+ VAddr load_base) {
+
+ if (data.size() < sizeof(NroHeader)) {
return {};
}
+
+ // Read NSO header
+ NroHeader nro_header{};
+ std::memcpy(&nro_header, data.data(), sizeof(NroHeader));
if (nro_header.magic != Common::MakeMagic('N', 'R', 'O', '0')) {
return {};
}
// Build program image
- std::vector<u8> program_image = file.ReadBytes(PageAlignSize(nro_header.file_size));
+ std::vector<u8> program_image(PageAlignSize(nro_header.file_size));
+ std::memcpy(program_image.data(), data.data(), program_image.size());
if (program_image.size() != PageAlignSize(nro_header.file_size)) {
return {};
}
@@ -182,11 +187,15 @@ bool AppLoader_NRO::LoadNro(const FileSys::VfsFile& file, VAddr load_base) {
Core::CurrentProcess()->LoadModule(std::move(codeset), load_base);
// Register module with GDBStub
- GDBStub::RegisterModule(file.GetName(), load_base, load_base);
+ GDBStub::RegisterModule(name, load_base, load_base);
return true;
}
+bool AppLoader_NRO::LoadNro(const FileSys::VfsFile& file, VAddr load_base) {
+ return AppLoader_NRO::LoadNro(file.ReadAllBytes(), file.GetName(), load_base);
+}
+
ResultStatus AppLoader_NRO::Load(Kernel::Process& process) {
if (is_loaded) {
return ResultStatus::ErrorAlreadyLoaded;
diff --git a/src/core/loader/nro.h b/src/core/loader/nro.h
index 50ee5a78a..3e6959302 100644
--- a/src/core/loader/nro.h
+++ b/src/core/loader/nro.h
@@ -5,6 +5,7 @@
#pragma once
#include <string>
+#include <vector>
#include "common/common_types.h"
#include "core/loader/linker.h"
#include "core/loader/loader.h"
@@ -40,6 +41,8 @@ public:
ResultStatus ReadTitle(std::string& title) override;
bool IsRomFSUpdatable() const override;
+ static bool LoadNro(const std::vector<u8>& data, const std::string& name, VAddr load_base);
+
private:
bool LoadNro(const FileSys::VfsFile& file, VAddr load_base);
diff --git a/src/core/loader/nsp.cpp b/src/core/loader/nsp.cpp
index 13e57848d..080d89904 100644
--- a/src/core/loader/nsp.cpp
+++ b/src/core/loader/nsp.cpp
@@ -36,6 +36,16 @@ AppLoader_NSP::AppLoader_NSP(FileSys::VirtualFile file)
std::tie(nacp_file, icon_file) =
FileSys::PatchManager(nsp->GetProgramTitleID()).ParseControlNCA(*control_nca);
+
+ if (nsp->IsExtractedType()) {
+ secondary_loader = std::make_unique<AppLoader_DeconstructedRomDirectory>(nsp->GetExeFS());
+ } else {
+ if (title_id == 0)
+ return;
+
+ secondary_loader = std::make_unique<AppLoader_NCA>(
+ nsp->GetNCAFile(title_id, FileSys::ContentRecordType::Program));
+ }
}
AppLoader_NSP::~AppLoader_NSP() = default;
@@ -67,26 +77,19 @@ ResultStatus AppLoader_NSP::Load(Kernel::Process& process) {
return ResultStatus::ErrorAlreadyLoaded;
}
- if (nsp->IsExtractedType()) {
- secondary_loader = std::make_unique<AppLoader_DeconstructedRomDirectory>(nsp->GetExeFS());
- } else {
- if (title_id == 0)
- return ResultStatus::ErrorNSPMissingProgramNCA;
-
- secondary_loader = std::make_unique<AppLoader_NCA>(
- nsp->GetNCAFile(title_id, FileSys::ContentRecordType::Program));
+ if (title_id == 0)
+ return ResultStatus::ErrorNSPMissingProgramNCA;
- if (nsp->GetStatus() != ResultStatus::Success)
- return nsp->GetStatus();
+ if (nsp->GetStatus() != ResultStatus::Success)
+ return nsp->GetStatus();
- if (nsp->GetProgramStatus(title_id) != ResultStatus::Success)
- return nsp->GetProgramStatus(title_id);
+ if (nsp->GetProgramStatus(title_id) != ResultStatus::Success)
+ return nsp->GetProgramStatus(title_id);
- if (nsp->GetNCA(title_id, FileSys::ContentRecordType::Program) == nullptr) {
- if (!Core::Crypto::KeyManager::KeyFileExists(false))
- return ResultStatus::ErrorMissingProductionKeyFile;
- return ResultStatus::ErrorNSPMissingProgramNCA;
- }
+ if (nsp->GetNCA(title_id, FileSys::ContentRecordType::Program) == nullptr) {
+ if (!Core::Crypto::KeyManager::KeyFileExists(false))
+ return ResultStatus::ErrorMissingProductionKeyFile;
+ return ResultStatus::ErrorNSPMissingProgramNCA;
}
const auto result = secondary_loader->Load(process);
diff --git a/src/core/perf_stats.cpp b/src/core/perf_stats.cpp
index 7d95816fe..c716a462b 100644
--- a/src/core/perf_stats.cpp
+++ b/src/core/perf_stats.cpp
@@ -74,10 +74,6 @@ double PerfStats::GetLastFrameTimeScale() {
}
void FrameLimiter::DoFrameLimiting(microseconds current_system_time_us) {
- // Max lag caused by slow frames. Can be adjusted to compensate for too many slow frames. Higher
- // values increase the time needed to recover and limit framerate again after spikes.
- constexpr microseconds MAX_LAG_TIME_US = 25000us;
-
if (!Settings::values.use_frame_limit) {
return;
}