diff options
| author | cirakg <cirakg@cirakg.xyz> | 2026-11-02 19:32:20 +0100 |
|---|---|---|
| committer | failaip12 <86018517+failaip12@users.noreply.github.com> | 2026-11-02 23:28:10 +0100 |
| commit | b504f4e82bb0b675d953d14b67e307eac58226d3 (patch) | |
| tree | 7b5c56a968de21f324ac0866b06d768fb4e76f77 /src/core | |
| parent | 155bf34fc297b6b8e4c281ecf7ea5d9ce3140762 (diff) | |
core: detect Switch 2 programs in NSP containers
Read the selected program metadata before kernel initialization so NSP launches receive the Switch 2 memory layout and clock. This fixes Mario Kart World 1.8.0 crashing during startup while its loose 1.0 dump already boots.
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/core.cpp | 25 |
1 files changed, 22 insertions, 3 deletions
diff --git a/src/core/core.cpp b/src/core/core.cpp index 3842ee25a8..00ee551ef8 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -24,6 +24,7 @@ #include "core/cpu_manager.h" #include "core/debugger/debugger.h" #include "core/device_memory.h" +#include "core/file_sys/content_archive.h" #include "core/file_sys/fs_filesystem.h" #include "core/file_sys/nup_container.h" #include "core/file_sys/patch_manager.h" @@ -31,6 +32,7 @@ #include "core/file_sys/registered_cache.h" #include "core/file_sys/romfs_factory.h" #include "core/file_sys/savedata_factory.h" +#include "core/file_sys/submission_package.h" #include "core/file_sys/vfs/vfs_concat.h" #include "core/file_sys/vfs/vfs_real.h" #include "core/gpu_dirty_memory_manager.h" @@ -115,8 +117,8 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs, namespace { -// Switch 2 titles boot as a loose ExeFS, with main.npdm next to main. -bool IsSwitch2Program(const FileSys::VirtualFile& file) { +// Detect the platform before initializing the kernel memory layout and guest clock. +bool IsSwitch2Program(const FileSys::VirtualFile& file, u64 program_id, std::size_t program_index) { FileSys::ProgramMetadata metadata; if (FileSys::NupContainer::IsNupFile(file)) { FileSys::NupContainer nup{file}; @@ -136,6 +138,22 @@ bool IsSwitch2Program(const FileSys::VirtualFile& file) { return npdm != nullptr && metadata.Load(npdm) == Loader::ResultStatus::Success && metadata.IsSwitch2(); } + const auto type = file != nullptr ? Loader::IdentifyFile(file) : Loader::FileType::Unknown; + if (type == Loader::FileType::NSP || type == Loader::FileType::NSZ) { + const FileSys::NSP nsp{file, program_id, program_index}; + if (nsp.GetStatus() != Loader::ResultStatus::Success) { + return false; + } + auto exefs = nsp.GetExeFS(); + if (!nsp.IsExtractedType()) { + const auto program = + nsp.GetNCA(nsp.GetProgramTitleID(), FileSys::ContentRecordType::Program); + exefs = program != nullptr ? program->GetExeFS() : nullptr; + } + const auto npdm = exefs != nullptr ? exefs->GetFile("main.npdm") : nullptr; + return npdm != nullptr && metadata.Load(npdm) == Loader::ResultStatus::Success && + metadata.IsSwitch2(); + } const auto dir = file != nullptr ? file->GetContainingDirectory() : nullptr; const auto npdm = dir != nullptr ? dir->GetFile("main.npdm") : nullptr; return npdm != nullptr && metadata.Load(npdm) == Loader::ResultStatus::Success && @@ -336,7 +354,8 @@ struct System::Impl { const bool switch2_program = virtual_filesystem != nullptr && - IsSwitch2Program(GetGameFileFromPath(virtual_filesystem, filepath)); + IsSwitch2Program(GetGameFileFromPath(virtual_filesystem, filepath), params.program_id, + params.program_index); Settings::SetCurrentProgramIsSwitch2(switch2_program); Settings::SetAstcRecompressionOverride(std::nullopt); |
