mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 22:00:05 +00:00 
			
		
		
		
	Merge pull request #2196 from Subv/system_mode
Kernel/Loader: Grab the system mode from the NCCH ExHeader.
This commit is contained in:
		
						commit
						3174bfd50c
					
				
					 10 changed files with 66 additions and 21 deletions
				
			
		|  | @ -129,15 +129,22 @@ int main(int argc, char** argv) { | |||
| 
 | ||||
|     std::unique_ptr<EmuWindow_SDL2> emu_window = std::make_unique<EmuWindow_SDL2>(); | ||||
| 
 | ||||
|     System::Init(emu_window.get()); | ||||
|     SCOPE_EXIT({ System::Shutdown(); }); | ||||
| 
 | ||||
|     std::unique_ptr<Loader::AppLoader> loader = Loader::GetLoader(boot_filename); | ||||
|     if (!loader) { | ||||
|         LOG_CRITICAL(Frontend, "Failed to obtain loader for %s!", boot_filename.c_str()); | ||||
|         return -1; | ||||
|     } | ||||
| 
 | ||||
|     boost::optional<u32> system_mode = loader->LoadKernelSystemMode(); | ||||
| 
 | ||||
|     if (!system_mode) { | ||||
|         LOG_CRITICAL(Frontend, "Failed to load ROM (Could not determine system mode)!"); | ||||
|         return -1; | ||||
|     } | ||||
| 
 | ||||
|     System::Init(emu_window.get(), system_mode.get()); | ||||
|     SCOPE_EXIT({ System::Shutdown(); }); | ||||
| 
 | ||||
|     Loader::ResultStatus load_result = loader->Load(); | ||||
|     if (Loader::ResultStatus::Success != load_result) { | ||||
|         LOG_CRITICAL(Frontend, "Failed to load ROM (Error %i)!", load_result); | ||||
|  |  | |||
|  | @ -253,7 +253,7 @@ void GMainWindow::OnDisplayTitleBars(bool show) { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| bool GMainWindow::InitializeSystem() { | ||||
| bool GMainWindow::InitializeSystem(u32 system_mode) { | ||||
|     // Shutdown previous session if the emu thread is still active...
 | ||||
|     if (emu_thread != nullptr) | ||||
|         ShutdownGame(); | ||||
|  | @ -270,7 +270,7 @@ bool GMainWindow::InitializeSystem() { | |||
|     } | ||||
| 
 | ||||
|     // Initialize the core emulation
 | ||||
|     System::Result system_result = System::Init(render_window); | ||||
|     System::Result system_result = System::Init(render_window, system_mode); | ||||
|     if (System::Result::Success != system_result) { | ||||
|         switch (system_result) { | ||||
|         case System::Result::ErrorInitVideoCore: | ||||
|  | @ -299,8 +299,20 @@ bool GMainWindow::LoadROM(const std::string& filename) { | |||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     boost::optional<u32> system_mode = app_loader->LoadKernelSystemMode(); | ||||
|     if (!system_mode) { | ||||
|         LOG_CRITICAL(Frontend, "Failed to load ROM!"); | ||||
|         QMessageBox::critical(this, tr("Error while loading ROM!"), | ||||
|                               tr("Could not determine the system mode.")); | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     if (!InitializeSystem(system_mode.get())) | ||||
|         return false; | ||||
| 
 | ||||
|     Loader::ResultStatus result = app_loader->Load(); | ||||
|     if (Loader::ResultStatus::Success != result) { | ||||
|         System::Shutdown(); | ||||
|         LOG_CRITICAL(Frontend, "Failed to load ROM!"); | ||||
| 
 | ||||
|         switch (result) { | ||||
|  | @ -338,14 +350,9 @@ void GMainWindow::BootGame(const std::string& filename) { | |||
|     LOG_INFO(Frontend, "Citra starting..."); | ||||
|     StoreRecentFile(filename); // Put the filename on top of the list
 | ||||
| 
 | ||||
|     if (!InitializeSystem()) | ||||
|     if (!LoadROM(filename)) | ||||
|         return; | ||||
| 
 | ||||
|     if (!LoadROM(filename)) { | ||||
|         System::Shutdown(); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     // Create and start the emulation thread
 | ||||
|     emu_thread = std::make_unique<EmuThread>(render_window); | ||||
|     emit EmulationStarting(emu_thread.get()); | ||||
|  |  | |||
|  | @ -60,7 +60,12 @@ signals: | |||
|     void EmulationStopping(); | ||||
| 
 | ||||
| private: | ||||
|     bool InitializeSystem(); | ||||
|     /**
 | ||||
|      * Initializes the emulation system. | ||||
|      * @param system_mode The system mode with which to intialize the kernel. | ||||
|      * @returns Whether the system was properly initialized. | ||||
|      */ | ||||
|     bool InitializeSystem(u32 system_mode); | ||||
|     bool LoadROM(const std::string& filename); | ||||
|     void BootGame(const std::string& filename); | ||||
|     void ShutdownGame(); | ||||
|  |  | |||
|  | @ -124,13 +124,11 @@ void HandleTable::Clear() { | |||
| } | ||||
| 
 | ||||
| /// Initialize the kernel
 | ||||
| void Init() { | ||||
| void Init(u32 system_mode) { | ||||
|     ConfigMem::Init(); | ||||
|     SharedPage::Init(); | ||||
| 
 | ||||
|     // TODO(yuriks): The memory type parameter needs to be determined by the ExHeader field instead
 | ||||
|     // For now it defaults to the one with a largest allocation to the app
 | ||||
|     Kernel::MemoryInit(2); // Allocates 96MB to the application
 | ||||
|     Kernel::MemoryInit(system_mode); | ||||
| 
 | ||||
|     Kernel::ResourceLimitsInit(); | ||||
|     Kernel::ThreadingInit(); | ||||
|  |  | |||
|  | @ -286,8 +286,8 @@ private: | |||
| 
 | ||||
| extern HandleTable g_handle_table; | ||||
| 
 | ||||
| /// Initialize the kernel
 | ||||
| void Init(); | ||||
| /// Initialize the kernel with the specified system mode.
 | ||||
| void Init(u32 system_mode); | ||||
| 
 | ||||
| /// Shutdown the kernel
 | ||||
| void Shutdown(); | ||||
|  |  | |||
|  | @ -9,6 +9,7 @@ | |||
| #include <memory> | ||||
| #include <string> | ||||
| #include <vector> | ||||
| #include <boost/optional.hpp> | ||||
| #include "common/common_types.h" | ||||
| #include "common/file_util.h" | ||||
| 
 | ||||
|  | @ -95,6 +96,17 @@ public: | |||
|      */ | ||||
|     virtual ResultStatus Load() = 0; | ||||
| 
 | ||||
|     /**
 | ||||
|      * Loads the system mode that this application needs. | ||||
|      * This function defaults to 2 (96MB allocated to the application) if it can't read the | ||||
|      * information. | ||||
|      * @returns Optional with the kernel system mode | ||||
|      */ | ||||
|     virtual boost::optional<u32> LoadKernelSystemMode() { | ||||
|         // 96MB allocated to the application.
 | ||||
|         return 2; | ||||
|     } | ||||
| 
 | ||||
|     /**
 | ||||
|      * Get the code (typically .code section) of the application | ||||
|      * @param buffer Reference to buffer to store data | ||||
|  |  | |||
|  | @ -117,6 +117,14 @@ FileType AppLoader_NCCH::IdentifyType(FileUtil::IOFile& file) { | |||
|     return FileType::Error; | ||||
| } | ||||
| 
 | ||||
| boost::optional<u32> AppLoader_NCCH::LoadKernelSystemMode() { | ||||
|     if (!is_loaded) { | ||||
|         if (LoadExeFS() != ResultStatus::Success) | ||||
|             return boost::none; | ||||
|     } | ||||
|     return exheader_header.arm11_system_local_caps.system_mode.Value(); | ||||
| } | ||||
| 
 | ||||
| ResultStatus AppLoader_NCCH::LoadExec() { | ||||
|     using Kernel::SharedPtr; | ||||
|     using Kernel::CodeSet; | ||||
|  | @ -277,6 +285,8 @@ ResultStatus AppLoader_NCCH::LoadExeFS() { | |||
|     LOG_DEBUG(Loader, "Core version:                %d", core_version); | ||||
|     LOG_DEBUG(Loader, "Thread priority:             0x%X", priority); | ||||
|     LOG_DEBUG(Loader, "Resource limit category:     %d", resource_limit_category); | ||||
|     LOG_DEBUG(Loader, "System Mode:                 %d", | ||||
|               exheader_header.arm11_system_local_caps.system_mode); | ||||
| 
 | ||||
|     if (exheader_header.arm11_system_local_caps.program_id != ncch_header.program_id) { | ||||
|         LOG_ERROR(Loader, "ExHeader Program ID mismatch: the ROM is probably encrypted."); | ||||
|  |  | |||
|  | @ -185,6 +185,12 @@ public: | |||
|      */ | ||||
|     ResultStatus Load() override; | ||||
| 
 | ||||
|     /**
 | ||||
|      * Loads the Exheader and returns the system mode for this application. | ||||
|      * @return Optional with the kernel system mode | ||||
|      */ | ||||
|     boost::optional<u32> LoadKernelSystemMode(); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Get the code (typically .code section) of the application | ||||
|      * @param buffer Reference to buffer to store data | ||||
|  |  | |||
|  | @ -17,12 +17,12 @@ namespace System { | |||
| 
 | ||||
| static bool is_powered_on{false}; | ||||
| 
 | ||||
| Result Init(EmuWindow* emu_window) { | ||||
| Result Init(EmuWindow* emu_window, u32 system_mode) { | ||||
|     Core::Init(); | ||||
|     CoreTiming::Init(); | ||||
|     Memory::Init(); | ||||
|     HW::Init(); | ||||
|     Kernel::Init(); | ||||
|     Kernel::Init(system_mode); | ||||
|     HLE::Init(); | ||||
|     if (!VideoCore::Init(emu_window)) { | ||||
|         return Result::ErrorInitVideoCore; | ||||
|  |  | |||
|  | @ -15,7 +15,7 @@ enum class Result { | |||
|     ErrorInitVideoCore, ///< Something went wrong during video core init
 | ||||
| }; | ||||
| 
 | ||||
| Result Init(EmuWindow* emu_window); | ||||
| Result Init(EmuWindow* emu_window, u32 system_mode); | ||||
| bool IsPoweredOn(); | ||||
| void Shutdown(); | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue