mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +00:00 
			
		
		
		
	Add disk archive serialization (fix crash in driver renegade etc.)
This commit is contained in:
		
							parent
							
								
									a210e7e2bd
								
							
						
					
					
						commit
						e9ab8f82d4
					
				
					 3 changed files with 83 additions and 23 deletions
				
			
		|  | @ -16,6 +16,7 @@ | ||||||
| #include <vector> | #include <vector> | ||||||
| #include <boost/serialization/split_member.hpp> | #include <boost/serialization/split_member.hpp> | ||||||
| #include <boost/serialization/string.hpp> | #include <boost/serialization/string.hpp> | ||||||
|  | #include <boost/serialization/wrapper.hpp> | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #ifdef _MSC_VER | #ifdef _MSC_VER | ||||||
| #include "common/string_util.h" | #include "common/string_util.h" | ||||||
|  | @ -41,6 +42,34 @@ enum class UserPath { | ||||||
|     UserDir, |     UserDir, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | // Replaces install-specific paths with standard placeholders, and back again
 | ||||||
|  | std::string SerializePath(const std::string& input, bool is_saving); | ||||||
|  | 
 | ||||||
|  | // A serializable path string
 | ||||||
|  | struct Path : public boost::serialization::wrapper_traits<const Path> { | ||||||
|  |     std::string& str; | ||||||
|  | 
 | ||||||
|  |     explicit Path(std::string& _str) : str(_str) {} | ||||||
|  | 
 | ||||||
|  |     static const Path make(std::string& str) { | ||||||
|  |         return Path(str); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     template <class Archive> | ||||||
|  |     void save(Archive& ar, const unsigned int) const { | ||||||
|  |         auto s_path = SerializePath(str, true); | ||||||
|  |         ar << s_path; | ||||||
|  |     } | ||||||
|  |     template <class Archive> | ||||||
|  |     void load(Archive& ar, const unsigned int) const { | ||||||
|  |         ar >> str; | ||||||
|  |         str = SerializePath(str, false); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     BOOST_SERIALIZATION_SPLIT_MEMBER(); | ||||||
|  |     friend class boost::serialization::access; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| // FileSystem tree node/
 | // FileSystem tree node/
 | ||||||
| struct FSTEntry { | struct FSTEntry { | ||||||
|     bool isDirectory; |     bool isDirectory; | ||||||
|  | @ -48,6 +77,17 @@ struct FSTEntry { | ||||||
|     std::string physicalName; // name on disk
 |     std::string physicalName; // name on disk
 | ||||||
|     std::string virtualName;  // name in FST names table
 |     std::string virtualName;  // name in FST names table
 | ||||||
|     std::vector<FSTEntry> children; |     std::vector<FSTEntry> children; | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |     template <class Archive> | ||||||
|  |     void serialize(Archive& ar, const unsigned int) { | ||||||
|  |         ar& isDirectory; | ||||||
|  |         ar& size; | ||||||
|  |         ar& Path::make(physicalName); | ||||||
|  |         ar& Path::make(virtualName); | ||||||
|  |         ar& children; | ||||||
|  |     } | ||||||
|  |     friend class boost::serialization::access; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| // Returns true if file filename exists
 | // Returns true if file filename exists
 | ||||||
|  | @ -146,9 +186,6 @@ void SetCurrentRomPath(const std::string& path); | ||||||
| // directory. To be used in "multi-user" mode (that is, installed).
 | // directory. To be used in "multi-user" mode (that is, installed).
 | ||||||
| const std::string& GetUserPath(UserPath path); | const std::string& GetUserPath(UserPath path); | ||||||
| 
 | 
 | ||||||
| // Replaces install-specific paths with standard placeholders, and back again
 |  | ||||||
| std::string SerializePath(const std::string& input, bool is_saving); |  | ||||||
| 
 |  | ||||||
| // Returns the path to where the sys file are
 | // Returns the path to where the sys file are
 | ||||||
| std::string GetSysDirectory(); | std::string GetSysDirectory(); | ||||||
| 
 | 
 | ||||||
|  | @ -322,27 +359,20 @@ private: | ||||||
|     u32 flags; |     u32 flags; | ||||||
| 
 | 
 | ||||||
|     template <class Archive> |     template <class Archive> | ||||||
|     void save(Archive& ar, const unsigned int) const { |     void serialize(Archive& ar, const unsigned int) { | ||||||
|         auto s_filename = SerializePath(filename, true); |         ar& Path::make(filename); | ||||||
|         ar << s_filename; |         ar& openmode; | ||||||
|         ar << openmode; |         ar& flags; | ||||||
|         ar << flags; |  | ||||||
|         ar << Tell(); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     template <class Archive> |  | ||||||
|     void load(Archive& ar, const unsigned int) { |  | ||||||
|         ar >> filename; |  | ||||||
|         filename = SerializePath(filename, false); |  | ||||||
|         ar >> openmode; |  | ||||||
|         ar >> flags; |  | ||||||
|         u64 pos; |         u64 pos; | ||||||
|         ar >> pos; |         if (Archive::is_saving::value) { | ||||||
|         Open(); |             pos = Tell(); | ||||||
|         Seek(pos, SEEK_SET); |         } | ||||||
|  |         ar& pos; | ||||||
|  |         if (Archive::is_loading::value) { | ||||||
|  |             Open(); | ||||||
|  |             Seek(pos, SEEK_SET); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 |  | ||||||
|     BOOST_SERIALIZATION_SPLIT_MEMBER() |  | ||||||
|     friend class boost::serialization::access; |     friend class boost::serialization::access; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -5,6 +5,7 @@ | ||||||
| #include <algorithm> | #include <algorithm> | ||||||
| #include <cstdio> | #include <cstdio> | ||||||
| #include <memory> | #include <memory> | ||||||
|  | #include "common/archives.h" | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "common/file_util.h" | #include "common/file_util.h" | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
|  | @ -14,6 +15,9 @@ | ||||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||||
| // FileSys namespace
 | // FileSys namespace
 | ||||||
| 
 | 
 | ||||||
|  | SERIALIZE_EXPORT_IMPL(FileSys::DiskFile) | ||||||
|  | SERIALIZE_EXPORT_IMPL(FileSys::DiskDirectory) | ||||||
|  | 
 | ||||||
| namespace FileSys { | namespace FileSys { | ||||||
| 
 | 
 | ||||||
| ResultVal<std::size_t> DiskFile::Read(const u64 offset, const std::size_t length, | ResultVal<std::size_t> DiskFile::Read(const u64 offset, const std::size_t length, | ||||||
|  |  | ||||||
|  | @ -10,6 +10,7 @@ | ||||||
| #include <vector> | #include <vector> | ||||||
| #include <boost/serialization/base_object.hpp> | #include <boost/serialization/base_object.hpp> | ||||||
| #include <boost/serialization/unique_ptr.hpp> | #include <boost/serialization/unique_ptr.hpp> | ||||||
|  | #include <boost/serialization/vector.hpp> | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "common/file_util.h" | #include "common/file_util.h" | ||||||
| #include "core/file_sys/archive_backend.h" | #include "core/file_sys/archive_backend.h" | ||||||
|  | @ -46,12 +47,16 @@ protected: | ||||||
|     Mode mode; |     Mode mode; | ||||||
|     std::unique_ptr<FileUtil::IOFile> file; |     std::unique_ptr<FileUtil::IOFile> file; | ||||||
| 
 | 
 | ||||||
|  | private: | ||||||
|  |     DiskFile() = default; | ||||||
|  | 
 | ||||||
|     template <class Archive> |     template <class Archive> | ||||||
|     void serialize(Archive& ar, const unsigned int) { |     void serialize(Archive& ar, const unsigned int) { | ||||||
|         ar& boost::serialization::base_object<FileBackend>(*this); |         ar& boost::serialization::base_object<FileBackend>(*this); | ||||||
|         ar& mode; |         ar& mode.hex; | ||||||
|         ar& file; |         ar& file; | ||||||
|     } |     } | ||||||
|  |     friend class boost::serialization::access; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| class DiskDirectory : public DirectoryBackend { | class DiskDirectory : public DirectoryBackend { | ||||||
|  | @ -74,6 +79,27 @@ protected: | ||||||
|     // We need to remember the last entry we returned, so a subsequent call to Read will continue
 |     // We need to remember the last entry we returned, so a subsequent call to Read will continue
 | ||||||
|     // from the next one.  This iterator will always point to the next unread entry.
 |     // from the next one.  This iterator will always point to the next unread entry.
 | ||||||
|     std::vector<FileUtil::FSTEntry>::iterator children_iterator; |     std::vector<FileUtil::FSTEntry>::iterator children_iterator; | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |     DiskDirectory() = default; | ||||||
|  | 
 | ||||||
|  |     template <class Archive> | ||||||
|  |     void serialize(Archive& ar, const unsigned int) { | ||||||
|  |         ar& boost::serialization::base_object<DirectoryBackend>(*this); | ||||||
|  |         ar& directory; | ||||||
|  |         u64 child_index; | ||||||
|  |         if (Archive::is_saving::value) { | ||||||
|  |             child_index = children_iterator - directory.children.begin(); | ||||||
|  |         } | ||||||
|  |         ar& child_index; | ||||||
|  |         if (Archive::is_loading::value) { | ||||||
|  |             children_iterator = directory.children.begin() + child_index; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     friend class boost::serialization::access; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } // namespace FileSys
 | } // namespace FileSys
 | ||||||
|  | 
 | ||||||
|  | BOOST_CLASS_EXPORT_KEY(FileSys::DiskFile) | ||||||
|  | BOOST_CLASS_EXPORT_KEY(FileSys::DiskDirectory) | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue