mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	core: Detect and return error if GBA virtual console is loaded. (#6257)
This commit is contained in:
		
							parent
							
								
									d704c6a3ac
								
							
						
					
					
						commit
						84e54a52a6
					
				
					 6 changed files with 33 additions and 6 deletions
				
			
		|  | @ -1015,6 +1015,11 @@ bool GMainWindow::LoadROM(const QString& filename) { | ||||||
|                    "titles</a>.")); |                    "titles</a>.")); | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|  |         case Core::System::ResultStatus::ErrorLoader_ErrorGbaTitle: | ||||||
|  |             QMessageBox::critical(this, tr("Unsupported ROM"), | ||||||
|  |                                   tr("GBA Virtual Console ROMs are not supported by Citra.")); | ||||||
|  |             break; | ||||||
|  | 
 | ||||||
|         case Core::System::ResultStatus::ErrorVideoCore: |         case Core::System::ResultStatus::ErrorVideoCore: | ||||||
|             QMessageBox::critical( |             QMessageBox::critical( | ||||||
|                 this, tr("Video Core Error"), |                 this, tr("Video Core Error"), | ||||||
|  |  | ||||||
|  | @ -268,6 +268,8 @@ System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::st | ||||||
|             return ResultStatus::ErrorLoader_ErrorEncrypted; |             return ResultStatus::ErrorLoader_ErrorEncrypted; | ||||||
|         case Loader::ResultStatus::ErrorInvalidFormat: |         case Loader::ResultStatus::ErrorInvalidFormat: | ||||||
|             return ResultStatus::ErrorLoader_ErrorInvalidFormat; |             return ResultStatus::ErrorLoader_ErrorInvalidFormat; | ||||||
|  |         case Loader::ResultStatus::ErrorGbaTitle: | ||||||
|  |             return ResultStatus::ErrorLoader_ErrorGbaTitle; | ||||||
|         default: |         default: | ||||||
|             return ResultStatus::ErrorSystemMode; |             return ResultStatus::ErrorSystemMode; | ||||||
|         } |         } | ||||||
|  | @ -292,7 +294,6 @@ System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::st | ||||||
|     telemetry_session->AddInitialInfo(*app_loader); |     telemetry_session->AddInitialInfo(*app_loader); | ||||||
|     std::shared_ptr<Kernel::Process> process; |     std::shared_ptr<Kernel::Process> process; | ||||||
|     const Loader::ResultStatus load_result{app_loader->Load(process)}; |     const Loader::ResultStatus load_result{app_loader->Load(process)}; | ||||||
|     kernel->SetCurrentProcess(process); |  | ||||||
|     if (Loader::ResultStatus::Success != load_result) { |     if (Loader::ResultStatus::Success != load_result) { | ||||||
|         LOG_CRITICAL(Core, "Failed to load ROM (Error {})!", load_result); |         LOG_CRITICAL(Core, "Failed to load ROM (Error {})!", load_result); | ||||||
|         System::Shutdown(); |         System::Shutdown(); | ||||||
|  | @ -302,10 +303,13 @@ System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::st | ||||||
|             return ResultStatus::ErrorLoader_ErrorEncrypted; |             return ResultStatus::ErrorLoader_ErrorEncrypted; | ||||||
|         case Loader::ResultStatus::ErrorInvalidFormat: |         case Loader::ResultStatus::ErrorInvalidFormat: | ||||||
|             return ResultStatus::ErrorLoader_ErrorInvalidFormat; |             return ResultStatus::ErrorLoader_ErrorInvalidFormat; | ||||||
|  |         case Loader::ResultStatus::ErrorGbaTitle: | ||||||
|  |             return ResultStatus::ErrorLoader_ErrorGbaTitle; | ||||||
|         default: |         default: | ||||||
|             return ResultStatus::ErrorLoader; |             return ResultStatus::ErrorLoader; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |     kernel->SetCurrentProcess(process); | ||||||
|     cheat_engine = std::make_unique<Cheats::CheatEngine>(*this); |     cheat_engine = std::make_unique<Cheats::CheatEngine>(*this); | ||||||
|     title_id = 0; |     title_id = 0; | ||||||
|     if (app_loader->ReadProgramId(title_id) != Loader::ResultStatus::Success) { |     if (app_loader->ReadProgramId(title_id) != Loader::ResultStatus::Success) { | ||||||
|  | @ -539,7 +543,8 @@ void System::Shutdown(bool is_deserializing) { | ||||||
|                                 perf_results.emulation_speed * 100.0); |                                 perf_results.emulation_speed * 100.0); | ||||||
|     telemetry_session->AddField(performance, "Shutdown_Framerate", perf_results.game_fps); |     telemetry_session->AddField(performance, "Shutdown_Framerate", perf_results.game_fps); | ||||||
|     telemetry_session->AddField(performance, "Shutdown_Frametime", perf_results.frametime * 1000.0); |     telemetry_session->AddField(performance, "Shutdown_Frametime", perf_results.frametime * 1000.0); | ||||||
|     telemetry_session->AddField(performance, "Mean_Frametime_MS", perf_stats->GetMeanFrametime()); |     telemetry_session->AddField(performance, "Mean_Frametime_MS", | ||||||
|  |                                 perf_stats ? perf_stats->GetMeanFrametime() : 0); | ||||||
| 
 | 
 | ||||||
|     // Shutdown emulation session
 |     // Shutdown emulation session
 | ||||||
|     VideoCore::Shutdown(); |     VideoCore::Shutdown(); | ||||||
|  |  | ||||||
|  | @ -82,10 +82,12 @@ public: | ||||||
|         ErrorSystemMode,            ///< Error determining the system mode
 |         ErrorSystemMode,            ///< Error determining the system mode
 | ||||||
|         ErrorLoader,                ///< Error loading the specified application
 |         ErrorLoader,                ///< Error loading the specified application
 | ||||||
|         ErrorLoader_ErrorEncrypted, ///< Error loading the specified application due to encryption
 |         ErrorLoader_ErrorEncrypted, ///< Error loading the specified application due to encryption
 | ||||||
|         ErrorLoader_ErrorInvalidFormat,     ///< Error loading the specified application due to an
 |         ErrorLoader_ErrorInvalidFormat, ///< Error loading the specified application due to an
 | ||||||
|                                             /// invalid format
 |                                         /// invalid format
 | ||||||
|         ErrorSystemFiles,                   ///< Error in finding system files
 |         ErrorLoader_ErrorGbaTitle, ///< Error loading the specified application as it is GBA Virtual
 | ||||||
|         ErrorVideoCore,                     ///< Error in the video core
 |                                    ///< Console
 | ||||||
|  |         ErrorSystemFiles,          ///< Error in finding system files
 | ||||||
|  |         ErrorVideoCore,            ///< Error in the video core
 | ||||||
|         ErrorVideoCore_ErrorGenericDrivers, ///< Error in the video core due to the user having
 |         ErrorVideoCore_ErrorGenericDrivers, ///< Error in the video core due to the user having
 | ||||||
|                                             /// generic drivers installed
 |                                             /// generic drivers installed
 | ||||||
|         ErrorVideoCore_ErrorBelowGL43,      ///< Error in the video core due to the user not having
 |         ErrorVideoCore_ErrorBelowGL43,      ///< Error in the video core due to the user not having
 | ||||||
|  |  | ||||||
|  | @ -75,6 +75,7 @@ enum class ResultStatus { | ||||||
|     ErrorAlreadyLoaded, |     ErrorAlreadyLoaded, | ||||||
|     ErrorMemoryAllocationFailed, |     ErrorMemoryAllocationFailed, | ||||||
|     ErrorEncrypted, |     ErrorEncrypted, | ||||||
|  |     ErrorGbaTitle, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| constexpr u32 MakeMagic(char a, char b, char c, char d) { | constexpr u32 MakeMagic(char a, char b, char c, char d) { | ||||||
|  |  | ||||||
|  | @ -85,6 +85,11 @@ ResultStatus AppLoader_NCCH::LoadExec(std::shared_ptr<Kernel::Process>& process) | ||||||
|     u64_le program_id; |     u64_le program_id; | ||||||
|     if (ResultStatus::Success == ReadCode(code) && |     if (ResultStatus::Success == ReadCode(code) && | ||||||
|         ResultStatus::Success == ReadProgramId(program_id)) { |         ResultStatus::Success == ReadProgramId(program_id)) { | ||||||
|  |         if (IsGbaVirtualConsole(code)) { | ||||||
|  |             LOG_ERROR(Loader, "Encountered unsupported GBA Virtual Console code section."); | ||||||
|  |             return ResultStatus::ErrorGbaTitle; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         std::string process_name = Common::StringFromFixedZeroTerminatedBuffer( |         std::string process_name = Common::StringFromFixedZeroTerminatedBuffer( | ||||||
|             (const char*)overlay_ncch->exheader_header.codeset_info.name, 8); |             (const char*)overlay_ncch->exheader_header.codeset_info.name, 8); | ||||||
| 
 | 
 | ||||||
|  | @ -177,6 +182,12 @@ void AppLoader_NCCH::ParseRegionLockoutInfo() { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | bool AppLoader_NCCH::IsGbaVirtualConsole(const std::vector<u8>& code) { | ||||||
|  |     const u32* gbaVcHeader = reinterpret_cast<const u32*>(code.data() + code.size() - 0x10); | ||||||
|  |     return code.size() >= 0x10 && gbaVcHeader[0] == MakeMagic('.', 'C', 'A', 'A') && | ||||||
|  |            gbaVcHeader[1] == 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| ResultStatus AppLoader_NCCH::Load(std::shared_ptr<Kernel::Process>& process) { | ResultStatus AppLoader_NCCH::Load(std::shared_ptr<Kernel::Process>& process) { | ||||||
|     u64_le ncch_program_id; |     u64_le ncch_program_id; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -78,6 +78,9 @@ private: | ||||||
|     /// Reads the region lockout info in the SMDH and send it to CFG service
 |     /// Reads the region lockout info in the SMDH and send it to CFG service
 | ||||||
|     void ParseRegionLockoutInfo(); |     void ParseRegionLockoutInfo(); | ||||||
| 
 | 
 | ||||||
|  |     /// Detects whether the NCCH contains GBA Virtual Console.
 | ||||||
|  |     bool IsGbaVirtualConsole(const std::vector<u8>& code); | ||||||
|  | 
 | ||||||
|     FileSys::NCCHContainer base_ncch; |     FileSys::NCCHContainer base_ncch; | ||||||
|     FileSys::NCCHContainer update_ncch; |     FileSys::NCCHContainer update_ncch; | ||||||
|     FileSys::NCCHContainer* overlay_ncch; |     FileSys::NCCHContainer* overlay_ncch; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue