From d1ea00ed884cf714a252d3194d3f8dbdc54ac937 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Wed, 21 Dec 2016 11:30:12 +0100 Subject: [PATCH] Only open file once when detecting blob type --- Source/Core/DiscIO/Blob.cpp | 32 +++++++++++++++++---------- Source/Core/DiscIO/CISOBlob.cpp | 18 +++------------ Source/Core/DiscIO/CISOBlob.h | 4 ++-- Source/Core/DiscIO/CompressedBlob.cpp | 6 +++-- Source/Core/DiscIO/CompressedBlob.h | 4 +--- Source/Core/DiscIO/TGCBlob.cpp | 15 +++---------- Source/Core/DiscIO/TGCBlob.h | 2 +- Source/Core/DiscIO/WbfsBlob.cpp | 14 +++--------- Source/Core/DiscIO/WbfsBlob.h | 6 ++--- 9 files changed, 40 insertions(+), 61 deletions(-) diff --git a/Source/Core/DiscIO/Blob.cpp b/Source/Core/DiscIO/Blob.cpp index d7aad9332a..d1dd0e7c1e 100644 --- a/Source/Core/DiscIO/Blob.cpp +++ b/Source/Core/DiscIO/Blob.cpp @@ -177,23 +177,31 @@ std::unique_ptr CreateBlobReader(const std::string& filename) if (cdio_is_cdrom(filename)) return DriveReader::Create(filename); - if (!File::Exists(filename)) + File::IOFile file(filename, "rb"); + u32 magic; + if (!file.ReadArray(&magic, 1)) return nullptr; - if (IsWbfsBlob(filename)) - return WbfsFileReader::Create(filename); + // Conveniently, every supported file format (except for plain disc images) starts + // with a 4-byte magic number that identifies the format, so we just need a simple + // switch statement to create the right blob type. If the magic number doesn't + // match any known magic number, we assume it's a plain disc image. If that + // assumption is wrong, the volume code that runs later will notice the error + // because the blob won't provide valid data when reading the GC/Wii disc header. - if (IsGCZBlob(filename)) - return CompressedBlobReader::Create(filename); - - if (IsCISOBlob(filename)) + switch (magic) + { + case CISO_MAGIC: return CISOFileReader::Create(filename); - - if (IsTGCBlob(filename)) + case GCZ_MAGIC: + return CompressedBlobReader::Create(filename); + case TGC_MAGIC: return TGCFileReader::Create(filename); - - // Still here? Assume plain file - since we know it exists due to the File::Exists check above. - return PlainFileReader::Create(filename); + case WBFS_MAGIC: + return WbfsFileReader::Create(filename); + default: + return PlainFileReader::Create(filename); + } } } // namespace diff --git a/Source/Core/DiscIO/CISOBlob.cpp b/Source/Core/DiscIO/CISOBlob.cpp index 37e427793b..388fd71d60 100644 --- a/Source/Core/DiscIO/CISOBlob.cpp +++ b/Source/Core/DiscIO/CISOBlob.cpp @@ -12,8 +12,6 @@ namespace DiscIO { -static const char CISO_MAGIC[] = "CISO"; - CISOFileReader::CISOFileReader(std::FILE* file) : m_file(file) { m_size = m_file.GetSize(); @@ -30,11 +28,10 @@ CISOFileReader::CISOFileReader(std::FILE* file) : m_file(file) std::unique_ptr CISOFileReader::Create(const std::string& filename) { - if (IsCISOBlob(filename)) - { - File::IOFile f(filename, "rb"); + File::IOFile f(filename, "rb"); + CISOHeader header; + if (f.ReadArray(&header, 1) && header.magic == CISO_MAGIC) return std::unique_ptr(new CISOFileReader(f.ReleaseHandle())); - } return nullptr; } @@ -81,13 +78,4 @@ bool CISOFileReader::Read(u64 offset, u64 nbytes, u8* out_ptr) return true; } -bool IsCISOBlob(const std::string& filename) -{ - File::IOFile f(filename, "rb"); - - CISOHeader header; - return (f.ReadArray(&header, 1) && - std::equal(header.magic, header.magic + sizeof(header.magic), CISO_MAGIC)); -} - } // namespace diff --git a/Source/Core/DiscIO/CISOBlob.h b/Source/Core/DiscIO/CISOBlob.h index 9eed0d992a..33791bab18 100644 --- a/Source/Core/DiscIO/CISOBlob.h +++ b/Source/Core/DiscIO/CISOBlob.h @@ -14,7 +14,7 @@ namespace DiscIO { -bool IsCISOBlob(const std::string& filename); +static constexpr u32 CISO_MAGIC = 0x4F534943; // "CISO" (byteswapped to little endian) static const u32 CISO_HEADER_SIZE = 0x8000; static const u32 CISO_MAP_SIZE = CISO_HEADER_SIZE - sizeof(u32) - sizeof(char) * 4; @@ -22,7 +22,7 @@ static const u32 CISO_MAP_SIZE = CISO_HEADER_SIZE - sizeof(u32) - sizeof(char) * struct CISOHeader { // "CISO" - char magic[4]; + u32 magic; // little endian u32 block_size; diff --git a/Source/Core/DiscIO/CompressedBlob.cpp b/Source/Core/DiscIO/CompressedBlob.cpp index 680ca8d179..4a749a7ebe 100644 --- a/Source/Core/DiscIO/CompressedBlob.cpp +++ b/Source/Core/DiscIO/CompressedBlob.cpp @@ -28,6 +28,8 @@ namespace DiscIO { +bool IsGCZBlob(const std::string& filename); + CompressedBlobReader::CompressedBlobReader(const std::string& filename) : m_file_name(filename) { m_file.Open(filename, "rb"); @@ -192,7 +194,7 @@ bool CompressFileToBlob(const std::string& infile, const std::string& outfile, u callback(GetStringT("Files opened, ready to compress."), 0, arg); CompressedBlobHeader header; - header.magic_cookie = kBlobCookie; + header.magic_cookie = GCZ_MAGIC; header.sub_type = sub_type; header.block_size = block_size; header.data_size = File::GetSize(infile); @@ -401,7 +403,7 @@ bool IsGCZBlob(const std::string& filename) File::IOFile f(filename, "rb"); CompressedBlobHeader header; - return f.ReadArray(&header, 1) && (header.magic_cookie == kBlobCookie); + return f.ReadArray(&header, 1) && (header.magic_cookie == GCZ_MAGIC); } } // namespace diff --git a/Source/Core/DiscIO/CompressedBlob.h b/Source/Core/DiscIO/CompressedBlob.h index 4c33cf85be..7769a9d8cd 100644 --- a/Source/Core/DiscIO/CompressedBlob.h +++ b/Source/Core/DiscIO/CompressedBlob.h @@ -23,9 +23,7 @@ namespace DiscIO { -bool IsGCZBlob(const std::string& filename); - -const u32 kBlobCookie = 0xB10BC001; +static constexpr u32 GCZ_MAGIC = 0xB10BC001; // GCZ file structure: // BlobHeader diff --git a/Source/Core/DiscIO/TGCBlob.cpp b/Source/Core/DiscIO/TGCBlob.cpp index 85a5a854aa..04ef3a1a9d 100644 --- a/Source/Core/DiscIO/TGCBlob.cpp +++ b/Source/Core/DiscIO/TGCBlob.cpp @@ -56,21 +56,12 @@ void Replace32(u64 offset, u64 nbytes, u8* out_ptr, u64 replace_offset, u32 repl namespace DiscIO { -bool IsTGCBlob(const std::string& path) -{ - File::IOFile file(path, "rb"); - - TGCHeader header; - return (file.ReadArray(&header, 1) && header.magic == Common::swap32(0xAE0F38A2)); -} - std::unique_ptr TGCFileReader::Create(const std::string& path) { - if (IsTGCBlob(path)) - { - File::IOFile file(path, "rb"); + File::IOFile file(path, "rb"); + TGCHeader header; + if (file.ReadArray(&header, 1) && header.magic == TGC_MAGIC) return std::unique_ptr(new TGCFileReader(std::move(file))); - } return nullptr; } diff --git a/Source/Core/DiscIO/TGCBlob.h b/Source/Core/DiscIO/TGCBlob.h index c1057afc27..62fd0cd759 100644 --- a/Source/Core/DiscIO/TGCBlob.h +++ b/Source/Core/DiscIO/TGCBlob.h @@ -14,7 +14,7 @@ namespace DiscIO { -bool IsTGCBlob(const std::string& path); +static constexpr u32 TGC_MAGIC = 0xA2380FAE; struct TGCHeader { diff --git a/Source/Core/DiscIO/WbfsBlob.cpp b/Source/Core/DiscIO/WbfsBlob.cpp index 6acbe5d0b3..58ec6fc4c7 100644 --- a/Source/Core/DiscIO/WbfsBlob.cpp +++ b/Source/Core/DiscIO/WbfsBlob.cpp @@ -83,8 +83,10 @@ bool WbfsFileReader::ReadHeader() { // Read hd size info m_files[0]->file.ReadBytes(&m_header, sizeof(WbfsHeader)); - m_header.hd_sector_count = Common::swap32(m_header.hd_sector_count); + if (m_header.magic != WBFS_MAGIC) + return false; + m_header.hd_sector_count = Common::swap32(m_header.hd_sector_count); m_hd_sector_size = 1ull << m_header.hd_sector_shift; if (m_size != (m_header.hd_sector_count * m_hd_sector_size)) @@ -172,14 +174,4 @@ std::unique_ptr WbfsFileReader::Create(const std::string& filena return reader; } -bool IsWbfsBlob(const std::string& filename) -{ - File::IOFile f(filename, "rb"); - - u8 magic[4] = {0, 0, 0, 0}; - f.ReadBytes(&magic, 4); - - return (magic[0] == 'W') && (magic[1] == 'B') && (magic[2] == 'F') && (magic[3] == 'S'); -} - } // namespace diff --git a/Source/Core/DiscIO/WbfsBlob.h b/Source/Core/DiscIO/WbfsBlob.h index b7b2323950..5012ccd174 100644 --- a/Source/Core/DiscIO/WbfsBlob.h +++ b/Source/Core/DiscIO/WbfsBlob.h @@ -14,6 +14,8 @@ namespace DiscIO { +static constexpr u32 WBFS_MAGIC = 0x53464257; // "WBFS" (byteswapped to little endian) + class WbfsFileReader : public IBlobReader { public: @@ -58,7 +60,7 @@ private: #pragma pack(1) struct WbfsHeader { - char magic[4]; + u32 magic; u32 hd_sector_count; u8 hd_sector_shift; u8 wbfs_sector_shift; @@ -73,6 +75,4 @@ private: bool m_good; }; -bool IsWbfsBlob(const std::string& filename); - } // namespace