mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 13:50:03 +00:00 
			
		
		
		
	savestates: save the build name to be displayed when there's a version mismatch (#6493)
* savestates: add a build_name field to the header * savestates: display build name on save/load menu * savestates: add zero member to header just in case of UB from an older save state * savestates: add legacy hash lookup * savestate_data: update hash database
This commit is contained in:
		
							parent
							
								
									af78268dd5
								
							
						
					
					
						commit
						eb8d2941c9
					
				
					 5 changed files with 1470 additions and 11 deletions
				
			
		|  | @ -463,6 +463,7 @@ add_library(citra_core STATIC | |||
|     precompiled_headers.h | ||||
|     savestate.cpp | ||||
|     savestate.h | ||||
|     savestate_data.h | ||||
|     system_titles.cpp | ||||
|     system_titles.h | ||||
|     telemetry_session.cpp | ||||
|  |  | |||
|  | @ -15,18 +15,21 @@ | |||
| #include "core/core.h" | ||||
| #include "core/movie.h" | ||||
| #include "core/savestate.h" | ||||
| #include "core/savestate_data.h" | ||||
| #include "network/network.h" | ||||
| 
 | ||||
| namespace Core { | ||||
| 
 | ||||
| #pragma pack(push, 1) | ||||
| struct CSTHeader { | ||||
|     std::array<u8, 4> filetype;  /// Unique Identifier to check the file type (always "CST"0x1B)
 | ||||
|     u64_le program_id;           /// ID of the ROM being executed. Also called title_id
 | ||||
|     std::array<u8, 20> revision; /// Git hash of the revision this savestate was created with
 | ||||
|     u64_le time;                 /// The time when this save state was created
 | ||||
|     std::array<u8, 4> filetype;    /// Unique Identifier to check the file type (always "CST"0x1B)
 | ||||
|     u64_le program_id;             /// ID of the ROM being executed. Also called title_id
 | ||||
|     std::array<u8, 20> revision;   /// Git hash of the revision this savestate was created with
 | ||||
|     u64_le time;                   /// The time when this save state was created
 | ||||
|     std::array<u8, 20> build_name; /// The build name (Canary/Nightly) with the version number
 | ||||
|     u32_le zero = 0;               /// Should be zero, just in case.
 | ||||
| 
 | ||||
|     std::array<u8, 216> reserved{}; /// Make heading 256 bytes so it has consistent size
 | ||||
|     std::array<u8, 192> reserved{}; /// Make heading 256 bytes so it has consistent size
 | ||||
| }; | ||||
| static_assert(sizeof(CSTHeader) == 256, "CSTHeader should be 256 bytes"); | ||||
| #pragma pack(pop) | ||||
|  | @ -58,11 +61,26 @@ static bool ValidateSaveState(const CSTHeader& header, SaveStateInfo& info, u64 | |||
|         return false; | ||||
|     } | ||||
|     const std::string revision = fmt::format("{:02x}", fmt::join(header.revision, "")); | ||||
|     const std::string build_name = | ||||
|         header.zero == 0 ? reinterpret_cast<const char*>(header.build_name.data()) : ""; | ||||
| 
 | ||||
|     if (revision == Common::g_scm_rev) { | ||||
|         info.status = SaveStateInfo::ValidationStatus::OK; | ||||
|     } else { | ||||
|         LOG_WARNING(Core, "Save state file {} created from a different revision {}", path, | ||||
|                     revision); | ||||
|         if (!build_name.empty()) { | ||||
|             info.build_name = build_name; | ||||
|         } else if (hash_to_version.find(revision) != hash_to_version.end()) { | ||||
|             info.build_name = hash_to_version.at(revision); | ||||
|         } | ||||
|         if (info.build_name.empty()) { | ||||
|             LOG_WARNING(Core, "Save state file {} created from a different revision {}", path, | ||||
|                         revision); | ||||
|         } else { | ||||
|             LOG_WARNING(Core, | ||||
|                         "Save state file {} created from a different build {} with revision {}", | ||||
|                         path, info.build_name, revision); | ||||
|         } | ||||
| 
 | ||||
|         info.status = SaveStateInfo::ValidationStatus::RevisionDismatch; | ||||
|     } | ||||
|     return true; | ||||
|  | @ -134,6 +152,10 @@ void System::SaveState(u32 slot) const { | |||
|     header.time = std::chrono::duration_cast<std::chrono::seconds>( | ||||
|                       std::chrono::system_clock::now().time_since_epoch()) | ||||
|                       .count(); | ||||
|     const std::string build_fullname = Common::g_build_fullname; | ||||
|     std::memset(header.build_name.data(), 0, sizeof(header.build_name)); | ||||
|     std::memcpy(header.build_name.data(), build_fullname.c_str(), | ||||
|                 std::min(build_fullname.length(), sizeof(header.build_name) - 1)); | ||||
| 
 | ||||
|     if (file.WriteBytes(&header, sizeof(header)) != sizeof(header) || | ||||
|         file.WriteBytes(buffer.data(), buffer.size()) != buffer.size()) { | ||||
|  |  | |||
|  | @ -4,6 +4,7 @@ | |||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <string> | ||||
| #include <vector> | ||||
| #include "common/common_types.h" | ||||
| 
 | ||||
|  | @ -16,6 +17,7 @@ struct SaveStateInfo { | |||
|         OK, | ||||
|         RevisionDismatch, | ||||
|     } status; | ||||
|     std::string build_name; | ||||
| }; | ||||
| 
 | ||||
| constexpr u32 SaveStateSlotCount = 10; // Maximum count of savestate slots
 | ||||
|  |  | |||
							
								
								
									
										1427
									
								
								src/core/savestate_data.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1427
									
								
								src/core/savestate_data.h
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue