core: loader: Implement support for loading indexed programs.
This commit is contained in:
		
							parent
							
								
									7791cc8c2e
								
							
						
					
					
						commit
						5f75d97125
					
				| @ -145,7 +145,7 @@ struct System::Impl { | ||||
|     } | ||||
| 
 | ||||
|     ResultStatus Init(System& system, Frontend::EmuWindow& emu_window) { | ||||
|         LOG_DEBUG(HW_Memory, "initialized OK"); | ||||
|         LOG_DEBUG(Core, "initialized OK"); | ||||
| 
 | ||||
|         device_memory = std::make_unique<Core::DeviceMemory>(); | ||||
| 
 | ||||
| @ -208,9 +208,11 @@ struct System::Impl { | ||||
|         return ResultStatus::Success; | ||||
|     } | ||||
| 
 | ||||
|     ResultStatus Load(System& system, Frontend::EmuWindow& emu_window, | ||||
|                       const std::string& filepath) { | ||||
|         app_loader = Loader::GetLoader(system, GetGameFileFromPath(virtual_filesystem, filepath)); | ||||
|     ResultStatus Load(System& system, Frontend::EmuWindow& emu_window, const std::string& filepath, | ||||
|                       std::size_t program_index) { | ||||
|         app_loader = Loader::GetLoader(system, GetGameFileFromPath(virtual_filesystem, filepath), | ||||
|                                        program_index); | ||||
| 
 | ||||
|         if (!app_loader) { | ||||
|             LOG_CRITICAL(Core, "Failed to obtain loader for {}!", filepath); | ||||
|             return ResultStatus::ErrorGetLoader; | ||||
| @ -416,6 +418,8 @@ struct System::Impl { | ||||
|     bool is_multicore{}; | ||||
|     bool is_async_gpu{}; | ||||
| 
 | ||||
|     ExecuteProgramCallback execute_program_callback; | ||||
| 
 | ||||
|     std::array<u64, Core::Hardware::NUM_CPU_CORES> dynarmic_ticks{}; | ||||
|     std::array<MicroProfileToken, Core::Hardware::NUM_CPU_CORES> microprofile_dynarmic{}; | ||||
| }; | ||||
| @ -451,8 +455,9 @@ void System::Shutdown() { | ||||
|     impl->Shutdown(); | ||||
| } | ||||
| 
 | ||||
| System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::string& filepath) { | ||||
|     return impl->Load(*this, emu_window, filepath); | ||||
| System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::string& filepath, | ||||
|                                   std::size_t program_index) { | ||||
|     return impl->Load(*this, emu_window, filepath, program_index); | ||||
| } | ||||
| 
 | ||||
| bool System::IsPoweredOn() const { | ||||
| @ -789,4 +794,16 @@ bool System::IsMulticore() const { | ||||
|     return impl->is_multicore; | ||||
| } | ||||
| 
 | ||||
| void System::RegisterExecuteProgramCallback(ExecuteProgramCallback&& callback) { | ||||
|     impl->execute_program_callback = std::move(callback); | ||||
| } | ||||
| 
 | ||||
| void System::ExecuteProgram(std::size_t program_index) { | ||||
|     if (impl->execute_program_callback) { | ||||
|         impl->execute_program_callback(program_index); | ||||
|     } else { | ||||
|         LOG_CRITICAL(Core, "execute_program_callback must be initialized by the frontend"); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| } // namespace Core
 | ||||
|  | ||||
| @ -5,6 +5,7 @@ | ||||
| #pragma once | ||||
| 
 | ||||
| #include <cstddef> | ||||
| #include <functional> | ||||
| #include <memory> | ||||
| #include <string> | ||||
| #include <vector> | ||||
| @ -173,9 +174,11 @@ public: | ||||
|      * @param emu_window Reference to the host-system window used for video output and keyboard | ||||
|      *                   input. | ||||
|      * @param filepath String path to the executable application to load on the host file system. | ||||
|      * @param program_index Specifies the index within the container of the program to launch. | ||||
|      * @returns ResultStatus code, indicating if the operation succeeded. | ||||
|      */ | ||||
|     [[nodiscard]] ResultStatus Load(Frontend::EmuWindow& emu_window, const std::string& filepath); | ||||
|     [[nodiscard]] ResultStatus Load(Frontend::EmuWindow& emu_window, const std::string& filepath, | ||||
|                                     std::size_t program_index = 0); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Indicates if the emulated system is powered on (all subsystems initialized and able to run an | ||||
| @ -385,6 +388,23 @@ public: | ||||
|     /// Tells if system is running on multicore.
 | ||||
|     [[nodiscard]] bool IsMulticore() const; | ||||
| 
 | ||||
|     /// Type used for the frontend to designate a callback for System to re-launch the application
 | ||||
|     /// using a specified program index.
 | ||||
|     using ExecuteProgramCallback = std::function<void(std::size_t)>; | ||||
| 
 | ||||
|     /**
 | ||||
|      * Registers a callback from the frontend for System to re-launch the application using a | ||||
|      * specified program index. | ||||
|      * @param callback Callback from the frontend to relaunch the application. | ||||
|      */ | ||||
|     void RegisterExecuteProgramCallback(ExecuteProgramCallback&& callback); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Instructs the frontend to re-launch the application using the specified program_index. | ||||
|      * @param program_index Specifies the index within the application of the program to launch. | ||||
|      */ | ||||
|     void ExecuteProgram(std::size_t program_index); | ||||
| 
 | ||||
| private: | ||||
|     System(); | ||||
| 
 | ||||
|  | ||||
| @ -29,7 +29,7 @@ constexpr std::array partition_names{ | ||||
|     "logo", | ||||
| }; | ||||
| 
 | ||||
| XCI::XCI(VirtualFile file_) | ||||
| XCI::XCI(VirtualFile file_, std::size_t program_index) | ||||
|     : file(std::move(file_)), program_nca_status{Loader::ResultStatus::ErrorXCIMissingProgramNCA}, | ||||
|       partitions(partition_names.size()), | ||||
|       partitions_raw(partition_names.size()), keys{Core::Crypto::KeyManager::Instance()} { | ||||
| @ -62,7 +62,8 @@ XCI::XCI(VirtualFile file_) | ||||
|     } | ||||
| 
 | ||||
|     secure_partition = std::make_shared<NSP>( | ||||
|         main_hfs.GetFile(partition_names[static_cast<std::size_t>(XCIPartition::Secure)])); | ||||
|         main_hfs.GetFile(partition_names[static_cast<std::size_t>(XCIPartition::Secure)]), | ||||
|         program_index); | ||||
| 
 | ||||
|     ncas = secure_partition->GetNCAsCollapsed(); | ||||
|     program = | ||||
|  | ||||
| @ -78,7 +78,7 @@ enum class XCIPartition : u8 { Update, Normal, Secure, Logo }; | ||||
| 
 | ||||
| class XCI : public ReadOnlyVfsDirectory { | ||||
| public: | ||||
|     explicit XCI(VirtualFile file); | ||||
|     explicit XCI(VirtualFile file, std::size_t program_index = 0); | ||||
|     ~XCI() override; | ||||
| 
 | ||||
|     Loader::ResultStatus GetStatus() const; | ||||
|  | ||||
| @ -20,8 +20,8 @@ | ||||
| 
 | ||||
| namespace FileSys { | ||||
| 
 | ||||
| NSP::NSP(VirtualFile file_) | ||||
|     : file(std::move(file_)), status{Loader::ResultStatus::Success}, | ||||
| NSP::NSP(VirtualFile file_, std::size_t program_index) | ||||
|     : file(std::move(file_)), program_index(program_index), status{Loader::ResultStatus::Success}, | ||||
|       pfs(std::make_shared<PartitionFilesystem>(file)), keys{Core::Crypto::KeyManager::Instance()} { | ||||
|     if (pfs->GetStatus() != Loader::ResultStatus::Success) { | ||||
|         status = pfs->GetStatus(); | ||||
| @ -146,7 +146,7 @@ std::shared_ptr<NCA> NSP::GetNCA(u64 title_id, ContentRecordType type, TitleType | ||||
|     if (extracted) | ||||
|         LOG_WARNING(Service_FS, "called on an NSP that is of type extracted."); | ||||
| 
 | ||||
|     const auto title_id_iter = ncas.find(title_id); | ||||
|     const auto title_id_iter = ncas.find(title_id + program_index); | ||||
|     if (title_id_iter == ncas.end()) | ||||
|         return nullptr; | ||||
| 
 | ||||
|  | ||||
| @ -27,7 +27,7 @@ enum class ContentRecordType : u8; | ||||
| 
 | ||||
| class NSP : public ReadOnlyVfsDirectory { | ||||
| public: | ||||
|     explicit NSP(VirtualFile file); | ||||
|     explicit NSP(VirtualFile file, std::size_t program_index = 0); | ||||
|     ~NSP() override; | ||||
| 
 | ||||
|     Loader::ResultStatus GetStatus() const; | ||||
| @ -69,6 +69,8 @@ private: | ||||
| 
 | ||||
|     VirtualFile file; | ||||
| 
 | ||||
|     const std::size_t program_index; | ||||
| 
 | ||||
|     bool extracted = false; | ||||
|     Loader::ResultStatus status; | ||||
|     std::map<u64, Loader::ResultStatus> program_status; | ||||
|  | ||||
| @ -198,10 +198,11 @@ AppLoader::~AppLoader() = default; | ||||
|  * @param system The system context to use. | ||||
|  * @param file   The file to retrieve the loader for | ||||
|  * @param type   The file type | ||||
|  * @param program_index Specifies the index within the container of the program to launch. | ||||
|  * @return std::unique_ptr<AppLoader> a pointer to a loader object;  nullptr for unsupported type | ||||
|  */ | ||||
| static std::unique_ptr<AppLoader> GetFileLoader(Core::System& system, FileSys::VirtualFile file, | ||||
|                                                 FileType type) { | ||||
|                                                 FileType type, std::size_t program_index) { | ||||
|     switch (type) { | ||||
|     // Standard ELF file format.
 | ||||
|     case FileType::ELF: | ||||
| @ -222,7 +223,7 @@ static std::unique_ptr<AppLoader> GetFileLoader(Core::System& system, FileSys::V | ||||
|     // NX XCI (nX Card Image) file format.
 | ||||
|     case FileType::XCI: | ||||
|         return std::make_unique<AppLoader_XCI>(std::move(file), system.GetFileSystemController(), | ||||
|                                                system.GetContentProvider()); | ||||
|                                                system.GetContentProvider(), program_index); | ||||
| 
 | ||||
|     // NX NAX (NintendoAesXts) file format.
 | ||||
|     case FileType::NAX: | ||||
| @ -231,7 +232,7 @@ static std::unique_ptr<AppLoader> GetFileLoader(Core::System& system, FileSys::V | ||||
|     // NX NSP (Nintendo Submission Package) file format
 | ||||
|     case FileType::NSP: | ||||
|         return std::make_unique<AppLoader_NSP>(std::move(file), system.GetFileSystemController(), | ||||
|                                                system.GetContentProvider()); | ||||
|                                                system.GetContentProvider(), program_index); | ||||
| 
 | ||||
|     // NX KIP (Kernel Internal Process) file format
 | ||||
|     case FileType::KIP: | ||||
| @ -246,7 +247,8 @@ static std::unique_ptr<AppLoader> GetFileLoader(Core::System& system, FileSys::V | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| std::unique_ptr<AppLoader> GetLoader(Core::System& system, FileSys::VirtualFile file) { | ||||
| std::unique_ptr<AppLoader> GetLoader(Core::System& system, FileSys::VirtualFile file, | ||||
|                                      std::size_t program_index) { | ||||
|     FileType type = IdentifyFile(file); | ||||
|     const FileType filename_type = GuessFromFilename(file->GetName()); | ||||
| 
 | ||||
| @ -260,7 +262,7 @@ std::unique_ptr<AppLoader> GetLoader(Core::System& system, FileSys::VirtualFile | ||||
| 
 | ||||
|     LOG_DEBUG(Loader, "Loading file {} as {}...", file->GetName(), GetFileTypeString(type)); | ||||
| 
 | ||||
|     return GetFileLoader(system, std::move(file), type); | ||||
|     return GetFileLoader(system, std::move(file), type, program_index); | ||||
| } | ||||
| 
 | ||||
| } // namespace Loader
 | ||||
|  | ||||
| @ -293,9 +293,11 @@ protected: | ||||
|  * | ||||
|  * @param system The system context. | ||||
|  * @param file   The bootable file. | ||||
|  * @param program_index Specifies the index within the container of the program to launch. | ||||
|  * | ||||
|  * @return the best loader for this file. | ||||
|  */ | ||||
| std::unique_ptr<AppLoader> GetLoader(Core::System& system, FileSys::VirtualFile file); | ||||
| std::unique_ptr<AppLoader> GetLoader(Core::System& system, FileSys::VirtualFile file, | ||||
|                                      std::size_t program_index = 0); | ||||
| 
 | ||||
| } // namespace Loader
 | ||||
|  | ||||
| @ -23,8 +23,9 @@ namespace Loader { | ||||
| 
 | ||||
| AppLoader_NSP::AppLoader_NSP(FileSys::VirtualFile file, | ||||
|                              const Service::FileSystem::FileSystemController& fsc, | ||||
|                              const FileSys::ContentProvider& content_provider) | ||||
|     : AppLoader(file), nsp(std::make_unique<FileSys::NSP>(file)), | ||||
|                              const FileSys::ContentProvider& content_provider, | ||||
|                              std::size_t program_index) | ||||
|     : AppLoader(file), nsp(std::make_unique<FileSys::NSP>(file, program_index)), | ||||
|       title_id(nsp->GetProgramTitleID()) { | ||||
| 
 | ||||
|     if (nsp->GetStatus() != ResultStatus::Success) { | ||||
|  | ||||
| @ -28,7 +28,8 @@ class AppLoader_NSP final : public AppLoader { | ||||
| public: | ||||
|     explicit AppLoader_NSP(FileSys::VirtualFile file, | ||||
|                            const Service::FileSystem::FileSystemController& fsc, | ||||
|                            const FileSys::ContentProvider& content_provider); | ||||
|                            const FileSys::ContentProvider& content_provider, | ||||
|                            std::size_t program_index); | ||||
|     ~AppLoader_NSP() override; | ||||
| 
 | ||||
|     /**
 | ||||
|  | ||||
| @ -22,8 +22,9 @@ namespace Loader { | ||||
| 
 | ||||
| AppLoader_XCI::AppLoader_XCI(FileSys::VirtualFile file, | ||||
|                              const Service::FileSystem::FileSystemController& fsc, | ||||
|                              const FileSys::ContentProvider& content_provider) | ||||
|     : AppLoader(file), xci(std::make_unique<FileSys::XCI>(file)), | ||||
|                              const FileSys::ContentProvider& content_provider, | ||||
|                              std::size_t program_index) | ||||
|     : AppLoader(file), xci(std::make_unique<FileSys::XCI>(file, program_index)), | ||||
|       nca_loader(std::make_unique<AppLoader_NCA>(xci->GetProgramNCAFile())) { | ||||
|     if (xci->GetStatus() != ResultStatus::Success) { | ||||
|         return; | ||||
|  | ||||
| @ -28,7 +28,8 @@ class AppLoader_XCI final : public AppLoader { | ||||
| public: | ||||
|     explicit AppLoader_XCI(FileSys::VirtualFile file, | ||||
|                            const Service::FileSystem::FileSystemController& fsc, | ||||
|                            const FileSys::ContentProvider& content_provider); | ||||
|                            const FileSys::ContentProvider& content_provider, | ||||
|                            std::size_t program_index); | ||||
|     ~AppLoader_XCI() override; | ||||
| 
 | ||||
|     /**
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 bunnei
						bunnei