summaryrefslogtreecommitdiffstats
path: root/src/core/hle
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle')
-rw-r--r--src/core/hle/kernel/address_arbiter.cpp2
-rw-r--r--src/core/hle/kernel/process.cpp10
-rw-r--r--src/core/hle/kernel/process.h21
-rw-r--r--src/core/hle/kernel/svc.cpp54
-rw-r--r--src/core/hle/kernel/svc.h4
-rw-r--r--src/core/hle/kernel/svc_wrap.h8
-rw-r--r--src/core/hle/kernel/thread.cpp16
-rw-r--r--src/core/hle/kernel/vm_manager.cpp35
-rw-r--r--src/core/hle/kernel/vm_manager.h12
-rw-r--r--src/core/hle/service/aoc/aoc_u.cpp18
-rw-r--r--src/core/hle/service/filesystem/filesystem.cpp29
-rw-r--r--src/core/hle/service/filesystem/filesystem.h12
-rw-r--r--src/core/hle/service/ns/pl_u.cpp2
-rw-r--r--src/core/hle/service/service.cpp4
-rw-r--r--src/core/hle/service/service.h3
-rw-r--r--src/core/hle/service/vi/vi.cpp50
16 files changed, 203 insertions, 77 deletions
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp
index ebf193930..57157beb4 100644
--- a/src/core/hle/kernel/address_arbiter.cpp
+++ b/src/core/hle/kernel/address_arbiter.cpp
@@ -39,7 +39,7 @@ static std::vector<SharedPtr<Thread>> GetThreadsWaitingOnAddress(VAddr address)
std::vector<SharedPtr<Thread>>& waiting_threads,
VAddr arb_addr) {
const auto& scheduler = Core::System::GetInstance().Scheduler(core_index);
- const auto& thread_list = scheduler->GetThreadList();
+ const auto& thread_list = scheduler.GetThreadList();
for (const auto& thread : thread_list) {
if (thread->GetArbiterWaitAddress() == arb_addr)
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index c80b2c507..073dd5a7d 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -153,11 +153,11 @@ void Process::PrepareForTermination() {
}
};
- auto& system = Core::System::GetInstance();
- stop_threads(system.Scheduler(0)->GetThreadList());
- stop_threads(system.Scheduler(1)->GetThreadList());
- stop_threads(system.Scheduler(2)->GetThreadList());
- stop_threads(system.Scheduler(3)->GetThreadList());
+ const auto& system = Core::System::GetInstance();
+ stop_threads(system.Scheduler(0).GetThreadList());
+ stop_threads(system.Scheduler(1).GetThreadList());
+ stop_threads(system.Scheduler(2).GetThreadList());
+ stop_threads(system.Scheduler(3).GetThreadList());
}
/**
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h
index 73ec01e11..f2816943a 100644
--- a/src/core/hle/kernel/process.h
+++ b/src/core/hle/kernel/process.h
@@ -24,6 +24,7 @@ class ProgramMetadata;
namespace Kernel {
class KernelCore;
+class ResourceLimit;
struct AddressMapping {
// Address and size must be page-aligned
@@ -57,9 +58,23 @@ union ProcessFlags {
BitField<12, 1, u16> loaded_high; ///< Application loaded high (not at 0x00100000).
};
-enum class ProcessStatus { Created, Running, Exited };
-
-class ResourceLimit;
+/**
+ * Indicates the status of a Process instance.
+ *
+ * @note These match the values as used by kernel,
+ * so new entries should only be added if RE
+ * shows that a new value has been introduced.
+ */
+enum class ProcessStatus {
+ Created,
+ CreatedWithDebuggerAttached,
+ Running,
+ WaitingForDebuggerToAttach,
+ DebuggerAttached,
+ Exiting,
+ Exited,
+ DebugBreak,
+};
struct CodeSet final {
struct Segment {
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index e406df829..d08b84bde 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -389,6 +389,12 @@ static void Break(u32 reason, u64 info1, u64 info2) {
"Emulated program broke execution! reason=0x{:016X}, info1=0x{:016X}, info2=0x{:016X}",
reason, info1, info2);
ASSERT(false);
+
+ Core::CurrentProcess()->PrepareForTermination();
+
+ // Kill the current thread
+ GetCurrentThread()->Stop();
+ Core::System::GetInstance().PrepareReschedule();
}
}
@@ -442,25 +448,12 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id)
case GetInfoType::RandomEntropy:
*result = 0;
break;
- case GetInfoType::AddressSpaceBaseAddr:
- *result = vm_manager.GetCodeRegionBaseAddress();
+ case GetInfoType::ASLRRegionBaseAddr:
+ *result = vm_manager.GetASLRRegionBaseAddress();
break;
- case GetInfoType::AddressSpaceSize: {
- const u64 width = vm_manager.GetAddressSpaceWidth();
-
- switch (width) {
- case 32:
- *result = 0xFFE00000;
- break;
- case 36:
- *result = 0xFF8000000;
- break;
- case 39:
- *result = 0x7FF8000000;
- break;
- }
+ case GetInfoType::ASLRRegionSize:
+ *result = vm_manager.GetASLRRegionSize();
break;
- }
case GetInfoType::NewMapRegionBaseAddr:
*result = vm_manager.GetNewMapRegionBaseAddress();
break;
@@ -803,7 +796,7 @@ static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target
std::vector<SharedPtr<Thread>>& waiting_threads,
VAddr condvar_addr) {
const auto& scheduler = Core::System::GetInstance().Scheduler(core_index);
- const auto& thread_list = scheduler->GetThreadList();
+ const auto& thread_list = scheduler.GetThreadList();
for (const auto& thread : thread_list) {
if (thread->GetCondVarWaitAddress() == condvar_addr)
@@ -1092,6 +1085,29 @@ static ResultCode ClearEvent(Handle handle) {
return RESULT_SUCCESS;
}
+static ResultCode GetProcessInfo(u64* out, Handle process_handle, u32 type) {
+ LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, type=0x{:X}", process_handle, type);
+
+ // This function currently only allows retrieving a process' status.
+ enum class InfoType {
+ Status,
+ };
+
+ const auto& kernel = Core::System::GetInstance().Kernel();
+ const auto process = kernel.HandleTable().Get<Process>(process_handle);
+ if (!process) {
+ return ERR_INVALID_HANDLE;
+ }
+
+ const auto info_type = static_cast<InfoType>(type);
+ if (info_type != InfoType::Status) {
+ return ERR_INVALID_ENUM_VALUE;
+ }
+
+ *out = static_cast<u64>(process->GetStatus());
+ return RESULT_SUCCESS;
+}
+
namespace {
struct FunctionDef {
using Func = void();
@@ -1227,7 +1243,7 @@ static const FunctionDef SVC_Table[] = {
{0x79, nullptr, "CreateProcess"},
{0x7A, nullptr, "StartProcess"},
{0x7B, nullptr, "TerminateProcess"},
- {0x7C, nullptr, "GetProcessInfo"},
+ {0x7C, SvcWrap<GetProcessInfo>, "GetProcessInfo"},
{0x7D, nullptr, "CreateResourceLimit"},
{0x7E, nullptr, "SetResourceLimitLimitValue"},
{0x7F, nullptr, "CallSecureMonitor"},
diff --git a/src/core/hle/kernel/svc.h b/src/core/hle/kernel/svc.h
index 70148c4fe..554a5e328 100644
--- a/src/core/hle/kernel/svc.h
+++ b/src/core/hle/kernel/svc.h
@@ -41,8 +41,8 @@ enum class GetInfoType : u64 {
RandomEntropy = 11,
PerformanceCounter = 0xF0000002,
// 2.0.0+
- AddressSpaceBaseAddr = 12,
- AddressSpaceSize = 13,
+ ASLRRegionBaseAddr = 12,
+ ASLRRegionSize = 13,
NewMapRegionBaseAddr = 14,
NewMapRegionSize = 15,
// 3.0.0+
diff --git a/src/core/hle/kernel/svc_wrap.h b/src/core/hle/kernel/svc_wrap.h
index cbb80c3c4..b09753c80 100644
--- a/src/core/hle/kernel/svc_wrap.h
+++ b/src/core/hle/kernel/svc_wrap.h
@@ -77,6 +77,14 @@ void SvcWrap() {
FuncReturn(retval);
}
+template <ResultCode func(u64*, u32, u32)>
+void SvcWrap() {
+ u64 param_1 = 0;
+ u32 retval = func(&param_1, static_cast<u32>(Param(1)), static_cast<u32>(Param(2))).raw;
+ Core::CurrentArmInterface().SetReg(1, param_1);
+ FuncReturn(retval);
+}
+
template <ResultCode func(u32, u64)>
void SvcWrap() {
FuncReturn(func(static_cast<u32>(Param(0)), Param(1)).raw);
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 352ce1725..35ec98c1a 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -97,7 +97,7 @@ void Thread::CancelWakeupTimer() {
static boost::optional<s32> GetNextProcessorId(u64 mask) {
for (s32 index = 0; index < Core::NUM_CPU_CORES; ++index) {
if (mask & (1ULL << index)) {
- if (!Core::System::GetInstance().Scheduler(index)->GetCurrentThread()) {
+ if (!Core::System::GetInstance().Scheduler(index).GetCurrentThread()) {
// Core is enabled and not running any threads, use this one
return index;
}
@@ -147,14 +147,14 @@ void Thread::ResumeFromWait() {
new_processor_id = processor_id;
}
if (ideal_core != -1 &&
- Core::System::GetInstance().Scheduler(ideal_core)->GetCurrentThread() == nullptr) {
+ Core::System::GetInstance().Scheduler(ideal_core).GetCurrentThread() == nullptr) {
new_processor_id = ideal_core;
}
ASSERT(*new_processor_id < 4);
// Add thread to new core's scheduler
- auto& next_scheduler = Core::System::GetInstance().Scheduler(*new_processor_id);
+ auto* next_scheduler = &Core::System::GetInstance().Scheduler(*new_processor_id);
if (*new_processor_id != processor_id) {
// Remove thread from previous core's scheduler
@@ -169,7 +169,7 @@ void Thread::ResumeFromWait() {
next_scheduler->ScheduleThread(this, current_priority);
// Change thread's scheduler
- scheduler = next_scheduler.get();
+ scheduler = next_scheduler;
Core::System::GetInstance().CpuCore(processor_id).PrepareReschedule();
}
@@ -230,7 +230,7 @@ ResultVal<SharedPtr<Thread>> Thread::Create(KernelCore& kernel, std::string name
thread->name = std::move(name);
thread->callback_handle = kernel.ThreadWakeupCallbackHandleTable().Create(thread).Unwrap();
thread->owner_process = &owner_process;
- thread->scheduler = Core::System::GetInstance().Scheduler(processor_id).get();
+ thread->scheduler = &Core::System::GetInstance().Scheduler(processor_id);
thread->scheduler->AddThread(thread, priority);
thread->tls_address = thread->owner_process->MarkNextAvailableTLSSlotAsUsed(*thread);
@@ -375,14 +375,14 @@ void Thread::ChangeCore(u32 core, u64 mask) {
new_processor_id = processor_id;
}
if (ideal_core != -1 &&
- Core::System::GetInstance().Scheduler(ideal_core)->GetCurrentThread() == nullptr) {
+ Core::System::GetInstance().Scheduler(ideal_core).GetCurrentThread() == nullptr) {
new_processor_id = ideal_core;
}
ASSERT(*new_processor_id < 4);
// Add thread to new core's scheduler
- auto& next_scheduler = Core::System::GetInstance().Scheduler(*new_processor_id);
+ auto* next_scheduler = &Core::System::GetInstance().Scheduler(*new_processor_id);
if (*new_processor_id != processor_id) {
// Remove thread from previous core's scheduler
@@ -397,7 +397,7 @@ void Thread::ChangeCore(u32 core, u64 mask) {
next_scheduler->ScheduleThread(this, current_priority);
// Change thread's scheduler
- scheduler = next_scheduler.get();
+ scheduler = next_scheduler;
Core::System::GetInstance().CpuCore(processor_id).PrepareReschedule();
}
diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp
index e412309fd..1e28ccbda 100644
--- a/src/core/hle/kernel/vm_manager.cpp
+++ b/src/core/hle/kernel/vm_manager.cpp
@@ -393,30 +393,35 @@ void VMManager::InitializeMemoryRegionRanges(FileSys::ProgramAddressSpaceType ty
switch (type) {
case FileSys::ProgramAddressSpaceType::Is32Bit:
+ case FileSys::ProgramAddressSpaceType::Is32BitNoMap:
address_space_width = 32;
code_region_base = 0x200000;
code_region_end = code_region_base + 0x3FE00000;
- map_region_size = 0x40000000;
- heap_region_size = 0x40000000;
+ aslr_region_base = 0x200000;
+ aslr_region_end = aslr_region_base + 0xFFE00000;
+ if (type == FileSys::ProgramAddressSpaceType::Is32Bit) {
+ map_region_size = 0x40000000;
+ heap_region_size = 0x40000000;
+ } else {
+ map_region_size = 0;
+ heap_region_size = 0x80000000;
+ }
break;
case FileSys::ProgramAddressSpaceType::Is36Bit:
address_space_width = 36;
code_region_base = 0x8000000;
code_region_end = code_region_base + 0x78000000;
+ aslr_region_base = 0x8000000;
+ aslr_region_end = aslr_region_base + 0xFF8000000;
map_region_size = 0x180000000;
heap_region_size = 0x180000000;
break;
- case FileSys::ProgramAddressSpaceType::Is32BitNoMap:
- address_space_width = 32;
- code_region_base = 0x200000;
- code_region_end = code_region_base + 0x3FE00000;
- map_region_size = 0;
- heap_region_size = 0x80000000;
- break;
case FileSys::ProgramAddressSpaceType::Is39Bit:
address_space_width = 39;
code_region_base = 0x8000000;
code_region_end = code_region_base + 0x80000000;
+ aslr_region_base = 0x8000000;
+ aslr_region_end = aslr_region_base + 0x7FF8000000;
map_region_size = 0x1000000000;
heap_region_size = 0x180000000;
new_map_region_size = 0x80000000;
@@ -490,6 +495,18 @@ u64 VMManager::GetAddressSpaceWidth() const {
return address_space_width;
}
+VAddr VMManager::GetASLRRegionBaseAddress() const {
+ return aslr_region_base;
+}
+
+VAddr VMManager::GetASLRRegionEndAddress() const {
+ return aslr_region_end;
+}
+
+u64 VMManager::GetASLRRegionSize() const {
+ return aslr_region_end - aslr_region_base;
+}
+
VAddr VMManager::GetCodeRegionBaseAddress() const {
return code_region_base;
}
diff --git a/src/core/hle/kernel/vm_manager.h b/src/core/hle/kernel/vm_manager.h
index 015559a64..4accde6b3 100644
--- a/src/core/hle/kernel/vm_manager.h
+++ b/src/core/hle/kernel/vm_manager.h
@@ -205,6 +205,15 @@ public:
/// Gets the address space width in bits.
u64 GetAddressSpaceWidth() const;
+ /// Gets the base address of the ASLR region.
+ VAddr GetASLRRegionBaseAddress() const;
+
+ /// Gets the end address of the ASLR region.
+ VAddr GetASLRRegionEndAddress() const;
+
+ /// Gets the size of the ASLR region
+ u64 GetASLRRegionSize() const;
+
/// Gets the base address of the code region.
VAddr GetCodeRegionBaseAddress() const;
@@ -306,6 +315,9 @@ private:
VAddr address_space_base = 0;
VAddr address_space_end = 0;
+ VAddr aslr_region_base = 0;
+ VAddr aslr_region_end = 0;
+
VAddr code_region_base = 0;
VAddr code_region_end = 0;
diff --git a/src/core/hle/service/aoc/aoc_u.cpp b/src/core/hle/service/aoc/aoc_u.cpp
index 0ecfb5af1..518161bf7 100644
--- a/src/core/hle/service/aoc/aoc_u.cpp
+++ b/src/core/hle/service/aoc/aoc_u.cpp
@@ -7,8 +7,10 @@
#include <vector>
#include "common/logging/log.h"
#include "core/file_sys/content_archive.h"
+#include "core/file_sys/control_metadata.h"
#include "core/file_sys/nca_metadata.h"
#include "core/file_sys/partition_filesystem.h"
+#include "core/file_sys/patch_manager.h"
#include "core/file_sys/registered_cache.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/process.h"
@@ -19,7 +21,7 @@
namespace Service::AOC {
constexpr u64 DLC_BASE_TITLE_ID_MASK = 0xFFFFFFFFFFFFE000;
-constexpr u64 DLC_BASE_TO_AOC_ID_MASK = 0x1000;
+constexpr u64 DLC_BASE_TO_AOC_ID = 0x1000;
static bool CheckAOCTitleIDMatchesBase(u64 base, u64 aoc) {
return (aoc & DLC_BASE_TITLE_ID_MASK) == base;
@@ -97,14 +99,24 @@ void AOC_U::ListAddOnContent(Kernel::HLERequestContext& ctx) {
ctx.WriteBuffer(out);
- IPC::ResponseBuilder rb{ctx, 2};
+ IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
+ rb.Push(count);
}
void AOC_U::GetAddOnContentBaseId(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
- rb.Push(Core::System::GetInstance().CurrentProcess()->GetTitleID() | DLC_BASE_TO_AOC_ID_MASK);
+ const auto title_id = Core::System::GetInstance().CurrentProcess()->GetTitleID();
+ FileSys::PatchManager pm{title_id};
+
+ const auto res = pm.GetControlMetadata();
+ if (res.first == nullptr) {
+ rb.Push(title_id + DLC_BASE_TO_AOC_ID);
+ return;
+ }
+
+ rb.Push(res.first->GetDLCBaseTitleId());
}
void AOC_U::PrepareAddOnContent(Kernel::HLERequestContext& ctx) {
diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp
index 439e62d27..e32a7c48e 100644
--- a/src/core/hle/service/filesystem/filesystem.cpp
+++ b/src/core/hle/service/filesystem/filesystem.cpp
@@ -319,13 +319,12 @@ ResultVal<FileSys::VirtualDir> OpenSDMC() {
return sdmc_factory->Open();
}
-std::shared_ptr<FileSys::RegisteredCacheUnion> GetUnionContents() {
- return std::make_shared<FileSys::RegisteredCacheUnion>(
- std::vector<std::shared_ptr<FileSys::RegisteredCache>>{
- GetSystemNANDContents(), GetUserNANDContents(), GetSDMCContents()});
+std::unique_ptr<FileSys::RegisteredCacheUnion> GetUnionContents() {
+ return std::make_unique<FileSys::RegisteredCacheUnion>(std::vector<FileSys::RegisteredCache*>{
+ GetSystemNANDContents(), GetUserNANDContents(), GetSDMCContents()});
}
-std::shared_ptr<FileSys::RegisteredCache> GetSystemNANDContents() {
+FileSys::RegisteredCache* GetSystemNANDContents() {
LOG_TRACE(Service_FS, "Opening System NAND Contents");
if (bis_factory == nullptr)
@@ -334,7 +333,7 @@ std::shared_ptr<FileSys::RegisteredCache> GetSystemNANDContents() {
return bis_factory->GetSystemNANDContents();
}
-std::shared_ptr<FileSys::RegisteredCache> GetUserNANDContents() {
+FileSys::RegisteredCache* GetUserNANDContents() {
LOG_TRACE(Service_FS, "Opening User NAND Contents");
if (bis_factory == nullptr)
@@ -343,7 +342,7 @@ std::shared_ptr<FileSys::RegisteredCache> GetUserNANDContents() {
return bis_factory->GetUserNANDContents();
}
-std::shared_ptr<FileSys::RegisteredCache> GetSDMCContents() {
+FileSys::RegisteredCache* GetSDMCContents() {
LOG_TRACE(Service_FS, "Opening SDMC Contents");
if (sdmc_factory == nullptr)
@@ -361,19 +360,19 @@ FileSys::VirtualDir GetModificationLoadRoot(u64 title_id) {
return bis_factory->GetModificationLoadRoot(title_id);
}
-void CreateFactories(const FileSys::VirtualFilesystem& vfs, bool overwrite) {
+void CreateFactories(FileSys::VfsFilesystem& vfs, bool overwrite) {
if (overwrite) {
bis_factory = nullptr;
save_data_factory = nullptr;
sdmc_factory = nullptr;
}
- auto nand_directory = vfs->OpenDirectory(FileUtil::GetUserPath(FileUtil::UserPath::NANDDir),
- FileSys::Mode::ReadWrite);
- auto sd_directory = vfs->OpenDirectory(FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir),
- FileSys::Mode::ReadWrite);
- auto load_directory = vfs->OpenDirectory(FileUtil::GetUserPath(FileUtil::UserPath::LoadDir),
- FileSys::Mode::ReadWrite);
+ auto nand_directory = vfs.OpenDirectory(FileUtil::GetUserPath(FileUtil::UserPath::NANDDir),
+ FileSys::Mode::ReadWrite);
+ auto sd_directory = vfs.OpenDirectory(FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir),
+ FileSys::Mode::ReadWrite);
+ auto load_directory = vfs.OpenDirectory(FileUtil::GetUserPath(FileUtil::UserPath::LoadDir),
+ FileSys::Mode::ReadWrite);
if (bis_factory == nullptr)
bis_factory = std::make_unique<FileSys::BISFactory>(nand_directory, load_directory);
@@ -383,7 +382,7 @@ void CreateFactories(const FileSys::VirtualFilesystem& vfs, bool overwrite) {
sdmc_factory = std::make_unique<FileSys::SDMCFactory>(std::move(sd_directory));
}
-void InstallInterfaces(SM::ServiceManager& service_manager, const FileSys::VirtualFilesystem& vfs) {
+void InstallInterfaces(SM::ServiceManager& service_manager, FileSys::VfsFilesystem& vfs) {
romfs_factory = nullptr;
CreateFactories(vfs, false);
std::make_shared<FSP_LDR>()->InstallAsService(service_manager);
diff --git a/src/core/hle/service/filesystem/filesystem.h b/src/core/hle/service/filesystem/filesystem.h
index 53b01bb01..6ca5c5636 100644
--- a/src/core/hle/service/filesystem/filesystem.h
+++ b/src/core/hle/service/filesystem/filesystem.h
@@ -47,19 +47,19 @@ ResultVal<FileSys::VirtualDir> OpenSaveData(FileSys::SaveDataSpaceId space,
FileSys::SaveDataDescriptor save_struct);
ResultVal<FileSys::VirtualDir> OpenSDMC();
-std::shared_ptr<FileSys::RegisteredCacheUnion> GetUnionContents();
+std::unique_ptr<FileSys::RegisteredCacheUnion> GetUnionContents();
-std::shared_ptr<FileSys::RegisteredCache> GetSystemNANDContents();
-std::shared_ptr<FileSys::RegisteredCache> GetUserNANDContents();
-std::shared_ptr<FileSys::RegisteredCache> GetSDMCContents();
+FileSys::RegisteredCache* GetSystemNANDContents();
+FileSys::RegisteredCache* GetUserNANDContents();
+FileSys::RegisteredCache* GetSDMCContents();
FileSys::VirtualDir GetModificationLoadRoot(u64 title_id);
// Creates the SaveData, SDMC, and BIS Factories. Should be called once and before any function
// above is called.
-void CreateFactories(const FileSys::VirtualFilesystem& vfs, bool overwrite = true);
+void CreateFactories(FileSys::VfsFilesystem& vfs, bool overwrite = true);
-void InstallInterfaces(SM::ServiceManager& service_manager, const FileSys::VirtualFilesystem& vfs);
+void InstallInterfaces(SM::ServiceManager& service_manager, FileSys::VfsFilesystem& vfs);
// A class that wraps a VfsDirectory with methods that return ResultVal and ResultCode instead of
// pointers and booleans. This makes using a VfsDirectory with switch services much easier and
diff --git a/src/core/hle/service/ns/pl_u.cpp b/src/core/hle/service/ns/pl_u.cpp
index 4b2f758a8..44accecb7 100644
--- a/src/core/hle/service/ns/pl_u.cpp
+++ b/src/core/hle/service/ns/pl_u.cpp
@@ -161,7 +161,7 @@ PL_U::PL_U() : ServiceFramework("pl:u"), impl{std::make_unique<Impl>()} {
};
RegisterHandlers(functions);
// Attempt to load shared font data from disk
- const auto nand = FileSystem::GetSystemNANDContents();
+ const auto* nand = FileSystem::GetSystemNANDContents();
std::size_t offset = 0;
// Rebuild shared fonts from data ncas
if (nand->HasEntry(static_cast<u64>(FontArchives::Standard),
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index 62f049660..a225cb4cb 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -197,7 +197,7 @@ ResultCode ServiceFrameworkBase::HandleSyncRequest(Kernel::HLERequestContext& co
// Module interface
/// Initialize ServiceManager
-void Init(std::shared_ptr<SM::ServiceManager>& sm, const FileSys::VirtualFilesystem& rfs) {
+void Init(std::shared_ptr<SM::ServiceManager>& sm, FileSys::VfsFilesystem& vfs) {
// NVFlinger needs to be accessed by several services like Vi and AppletOE so we instantiate it
// here and pass it into the respective InstallInterfaces functions.
auto nv_flinger = std::make_shared<NVFlinger::NVFlinger>();
@@ -220,7 +220,7 @@ void Init(std::shared_ptr<SM::ServiceManager>& sm, const FileSys::VirtualFilesys
EUPLD::InstallInterfaces(*sm);
Fatal::InstallInterfaces(*sm);
FGM::InstallInterfaces(*sm);
- FileSystem::InstallInterfaces(*sm, rfs);
+ FileSystem::InstallInterfaces(*sm, vfs);
Friend::InstallInterfaces(*sm);
GRC::InstallInterfaces(*sm);
HID::InstallInterfaces(*sm);
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h
index 2fc57a82e..98483ecf1 100644
--- a/src/core/hle/service/service.h
+++ b/src/core/hle/service/service.h
@@ -180,8 +180,7 @@ private:
};
/// Initialize ServiceManager
-void Init(std::shared_ptr<SM::ServiceManager>& sm,
- const std::shared_ptr<FileSys::VfsFilesystem>& vfs);
+void Init(std::shared_ptr<SM::ServiceManager>& sm, FileSys::VfsFilesystem& vfs);
/// Shutdown ServiceManager
void Shutdown();
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp
index bbc02abcc..184537daa 100644
--- a/src/core/hle/service/vi/vi.cpp
+++ b/src/core/hle/service/vi/vi.cpp
@@ -968,6 +968,54 @@ private:
rb.PushCopyObjects(vsync_event);
}
+ enum class ConvertedScaleMode : u64 {
+ None = 0, // VI seems to name this as "Unknown" but lots of games pass it, assume it's no
+ // scaling/default
+ Freeze = 1,
+ ScaleToWindow = 2,
+ Crop = 3,
+ NoCrop = 4,
+ };
+
+ // This struct is different, currently it's 1:1 but this might change in the future.
+ enum class NintendoScaleMode : u32 {
+ None = 0,
+ Freeze = 1,
+ ScaleToWindow = 2,
+ Crop = 3,
+ NoCrop = 4,
+ };
+
+ void ConvertScalingMode(Kernel::HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ auto mode = rp.PopEnum<NintendoScaleMode>();
+ LOG_DEBUG(Service_VI, "called mode={}", static_cast<u32>(mode));
+
+ IPC::ResponseBuilder rb{ctx, 4};
+ rb.Push(RESULT_SUCCESS);
+ switch (mode) {
+ case NintendoScaleMode::None:
+ rb.PushEnum(ConvertedScaleMode::None);
+ break;
+ case NintendoScaleMode::Freeze:
+ rb.PushEnum(ConvertedScaleMode::Freeze);
+ break;
+ case NintendoScaleMode::ScaleToWindow:
+ rb.PushEnum(ConvertedScaleMode::ScaleToWindow);
+ break;
+ case NintendoScaleMode::Crop:
+ rb.PushEnum(ConvertedScaleMode::Crop);
+ break;
+ case NintendoScaleMode::NoCrop:
+ rb.PushEnum(ConvertedScaleMode::NoCrop);
+ break;
+ default:
+ UNIMPLEMENTED_MSG("Unknown scaling mode {}", static_cast<u32>(mode));
+ rb.PushEnum(ConvertedScaleMode::None);
+ break;
+ }
+ }
+
std::shared_ptr<NVFlinger::NVFlinger> nv_flinger;
};
@@ -991,7 +1039,7 @@ IApplicationDisplayService::IApplicationDisplayService(
{2030, &IApplicationDisplayService::CreateStrayLayer, "CreateStrayLayer"},
{2031, &IApplicationDisplayService::DestroyStrayLayer, "DestroyStrayLayer"},
{2101, &IApplicationDisplayService::SetLayerScalingMode, "SetLayerScalingMode"},
- {2102, nullptr, "ConvertScalingMode"},
+ {2102, &IApplicationDisplayService::ConvertScalingMode, "ConvertScalingMode"},
{2450, nullptr, "GetIndirectLayerImageMap"},
{2451, nullptr, "GetIndirectLayerImageCropMap"},
{2460, nullptr, "GetIndirectLayerImageRequiredMemoryInfo"},