diff options
Diffstat (limited to 'src/core/hle')
| -rw-r--r-- | src/core/hle/kernel/address_arbiter.cpp | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/object.cpp | 1 | ||||
| -rw-r--r-- | src/core/hle/kernel/object.h | 1 | ||||
| -rw-r--r-- | src/core/hle/kernel/process.cpp | 34 | ||||
| -rw-r--r-- | src/core/hle/kernel/process.h | 49 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 39 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc_wrap.h | 8 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.cpp | 16 | ||||
| -rw-r--r-- | src/core/hle/service/aoc/aoc_u.cpp | 18 | ||||
| -rw-r--r-- | src/core/hle/service/filesystem/filesystem.cpp | 29 | ||||
| -rw-r--r-- | src/core/hle/service/filesystem/filesystem.h | 12 | ||||
| -rw-r--r-- | src/core/hle/service/ns/pl_u.cpp | 2 | ||||
| -rw-r--r-- | src/core/hle/service/service.cpp | 4 | ||||
| -rw-r--r-- | src/core/hle/service/service.h | 3 | ||||
| -rw-r--r-- | src/core/hle/service/vi/vi.cpp | 50 |
15 files changed, 176 insertions, 92 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/object.cpp b/src/core/hle/kernel/object.cpp index d51562d92..d87a62bb9 100644 --- a/src/core/hle/kernel/object.cpp +++ b/src/core/hle/kernel/object.cpp @@ -25,7 +25,6 @@ bool Object::IsWaitable() const { case HandleType::Process: case HandleType::AddressArbiter: case HandleType::ResourceLimit: - case HandleType::CodeSet: case HandleType::ClientPort: case HandleType::ClientSession: return false; diff --git a/src/core/hle/kernel/object.h b/src/core/hle/kernel/object.h index 9eb72315c..c9f4d0bb3 100644 --- a/src/core/hle/kernel/object.h +++ b/src/core/hle/kernel/object.h @@ -26,7 +26,6 @@ enum class HandleType : u32 { AddressArbiter, Timer, ResourceLimit, - CodeSet, ClientPort, ServerPort, ClientSession, diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index fb0027a71..073dd5a7d 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp @@ -20,13 +20,7 @@ namespace Kernel { -SharedPtr<CodeSet> CodeSet::Create(KernelCore& kernel, std::string name) { - SharedPtr<CodeSet> codeset(new CodeSet(kernel)); - codeset->name = std::move(name); - return codeset; -} - -CodeSet::CodeSet(KernelCore& kernel) : Object{kernel} {} +CodeSet::CodeSet() = default; CodeSet::~CodeSet() = default; SharedPtr<Process> Process::Create(KernelCore& kernel, std::string&& name) { @@ -159,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()); } /** @@ -224,20 +218,20 @@ void Process::FreeTLSSlot(VAddr tls_address) { tls_slots[tls_page].reset(tls_slot); } -void Process::LoadModule(SharedPtr<CodeSet> module_, VAddr base_addr) { +void Process::LoadModule(CodeSet module_, VAddr base_addr) { const auto MapSegment = [&](CodeSet::Segment& segment, VMAPermission permissions, MemoryState memory_state) { - auto vma = vm_manager - .MapMemoryBlock(segment.addr + base_addr, module_->memory, segment.offset, - segment.size, memory_state) - .Unwrap(); + const auto vma = vm_manager + .MapMemoryBlock(segment.addr + base_addr, module_.memory, + segment.offset, segment.size, memory_state) + .Unwrap(); vm_manager.Reprotect(vma, permissions); }; // Map CodeSet segments - MapSegment(module_->CodeSegment(), VMAPermission::ReadExecute, MemoryState::CodeStatic); - MapSegment(module_->RODataSegment(), VMAPermission::Read, MemoryState::CodeMutable); - MapSegment(module_->DataSegment(), VMAPermission::ReadWrite, MemoryState::CodeMutable); + MapSegment(module_.CodeSegment(), VMAPermission::ReadExecute, MemoryState::CodeStatic); + MapSegment(module_.RODataSegment(), VMAPermission::Read, MemoryState::CodeMutable); + MapSegment(module_.DataSegment(), VMAPermission::ReadWrite, MemoryState::CodeMutable); } ResultVal<VAddr> Process::HeapAllocate(VAddr target, u64 size, VMAPermission perms) { diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h index 590e0c73d..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,30 +58,33 @@ 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 : public Object { +struct CodeSet final { struct Segment { std::size_t offset = 0; VAddr addr = 0; u32 size = 0; }; - static SharedPtr<CodeSet> Create(KernelCore& kernel, std::string name); - - std::string GetTypeName() const override { - return "CodeSet"; - } - std::string GetName() const override { - return name; - } - - static const HandleType HANDLE_TYPE = HandleType::CodeSet; - HandleType GetHandleType() const override { - return HANDLE_TYPE; - } + explicit CodeSet(); + ~CodeSet(); Segment& CodeSegment() { return segments[0]; @@ -109,14 +113,7 @@ struct CodeSet final : public Object { std::shared_ptr<std::vector<u8>> memory; std::array<Segment, 3> segments; - VAddr entrypoint; - - /// Name of the process - std::string name; - -private: - explicit CodeSet(KernelCore& kernel); - ~CodeSet() override; + VAddr entrypoint = 0; }; class Process final : public Object { @@ -219,7 +216,7 @@ public: */ void PrepareForTermination(); - void LoadModule(SharedPtr<CodeSet> module_, VAddr base_addr); + void LoadModule(CodeSet module_, VAddr base_addr); /////////////////////////////////////////////////////////////////////////////////////////////// // Memory Management diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 863ecfa74..3e5f11f2b 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -95,12 +95,12 @@ ResultCode MapUnmapMemorySanityChecks(const VMManager& vm_manager, VAddr dst_add const VAddr dst_end_address = dst_addr + size; if (dst_end_address > vm_manager.GetHeapRegionBaseAddress() && - dst_addr < vm_manager.GetHeapRegionEndAddress()) { + vm_manager.GetHeapRegionEndAddress() > dst_addr) { return ERR_INVALID_MEMORY_RANGE; } - if (dst_end_address > vm_manager.GetNewMapRegionBaseAddress() && - dst_addr < vm_manager.GetMapRegionEndAddress()) { + if (dst_end_address > vm_manager.GetMapRegionBaseAddress() && + vm_manager.GetMapRegionEndAddress() > dst_addr) { return ERR_INVALID_MEMORY_RANGE; } @@ -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(); } } @@ -803,7 +809,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 +1098,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 +1256,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_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(¶m_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/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"}, |
