Only open file once when detecting blob type

This commit is contained in:
JosJuice 2016-12-21 11:30:12 +01:00
parent 3fdcbbdd92
commit d1ea00ed88
9 changed files with 40 additions and 61 deletions

View File

@ -177,23 +177,31 @@ std::unique_ptr<IBlobReader> CreateBlobReader(const std::string& filename)
if (cdio_is_cdrom(filename)) if (cdio_is_cdrom(filename))
return DriveReader::Create(filename); return DriveReader::Create(filename);
if (!File::Exists(filename)) File::IOFile file(filename, "rb");
u32 magic;
if (!file.ReadArray(&magic, 1))
return nullptr; return nullptr;
if (IsWbfsBlob(filename)) // Conveniently, every supported file format (except for plain disc images) starts
return WbfsFileReader::Create(filename); // 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)) switch (magic)
return CompressedBlobReader::Create(filename); {
case CISO_MAGIC:
if (IsCISOBlob(filename))
return CISOFileReader::Create(filename); return CISOFileReader::Create(filename);
case GCZ_MAGIC:
if (IsTGCBlob(filename)) return CompressedBlobReader::Create(filename);
case TGC_MAGIC:
return TGCFileReader::Create(filename); return TGCFileReader::Create(filename);
case WBFS_MAGIC:
// Still here? Assume plain file - since we know it exists due to the File::Exists check above. return WbfsFileReader::Create(filename);
return PlainFileReader::Create(filename); default:
return PlainFileReader::Create(filename);
}
} }
} // namespace } // namespace

View File

@ -12,8 +12,6 @@
namespace DiscIO namespace DiscIO
{ {
static const char CISO_MAGIC[] = "CISO";
CISOFileReader::CISOFileReader(std::FILE* file) : m_file(file) CISOFileReader::CISOFileReader(std::FILE* file) : m_file(file)
{ {
m_size = m_file.GetSize(); m_size = m_file.GetSize();
@ -30,11 +28,10 @@ CISOFileReader::CISOFileReader(std::FILE* file) : m_file(file)
std::unique_ptr<CISOFileReader> CISOFileReader::Create(const std::string& filename) std::unique_ptr<CISOFileReader> CISOFileReader::Create(const std::string& filename)
{ {
if (IsCISOBlob(filename)) File::IOFile f(filename, "rb");
{ CISOHeader header;
File::IOFile f(filename, "rb"); if (f.ReadArray(&header, 1) && header.magic == CISO_MAGIC)
return std::unique_ptr<CISOFileReader>(new CISOFileReader(f.ReleaseHandle())); return std::unique_ptr<CISOFileReader>(new CISOFileReader(f.ReleaseHandle()));
}
return nullptr; return nullptr;
} }
@ -81,13 +78,4 @@ bool CISOFileReader::Read(u64 offset, u64 nbytes, u8* out_ptr)
return true; 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 } // namespace

View File

@ -14,7 +14,7 @@
namespace DiscIO 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_HEADER_SIZE = 0x8000;
static const u32 CISO_MAP_SIZE = CISO_HEADER_SIZE - sizeof(u32) - sizeof(char) * 4; 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 struct CISOHeader
{ {
// "CISO" // "CISO"
char magic[4]; u32 magic;
// little endian // little endian
u32 block_size; u32 block_size;

View File

@ -28,6 +28,8 @@
namespace DiscIO namespace DiscIO
{ {
bool IsGCZBlob(const std::string& filename);
CompressedBlobReader::CompressedBlobReader(const std::string& filename) : m_file_name(filename) CompressedBlobReader::CompressedBlobReader(const std::string& filename) : m_file_name(filename)
{ {
m_file.Open(filename, "rb"); 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); callback(GetStringT("Files opened, ready to compress."), 0, arg);
CompressedBlobHeader header; CompressedBlobHeader header;
header.magic_cookie = kBlobCookie; header.magic_cookie = GCZ_MAGIC;
header.sub_type = sub_type; header.sub_type = sub_type;
header.block_size = block_size; header.block_size = block_size;
header.data_size = File::GetSize(infile); header.data_size = File::GetSize(infile);
@ -401,7 +403,7 @@ bool IsGCZBlob(const std::string& filename)
File::IOFile f(filename, "rb"); File::IOFile f(filename, "rb");
CompressedBlobHeader header; CompressedBlobHeader header;
return f.ReadArray(&header, 1) && (header.magic_cookie == kBlobCookie); return f.ReadArray(&header, 1) && (header.magic_cookie == GCZ_MAGIC);
} }
} // namespace } // namespace

View File

@ -23,9 +23,7 @@
namespace DiscIO namespace DiscIO
{ {
bool IsGCZBlob(const std::string& filename); static constexpr u32 GCZ_MAGIC = 0xB10BC001;
const u32 kBlobCookie = 0xB10BC001;
// GCZ file structure: // GCZ file structure:
// BlobHeader // BlobHeader

View File

@ -56,21 +56,12 @@ void Replace32(u64 offset, u64 nbytes, u8* out_ptr, u64 replace_offset, u32 repl
namespace DiscIO 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> TGCFileReader::Create(const std::string& path) std::unique_ptr<TGCFileReader> TGCFileReader::Create(const std::string& path)
{ {
if (IsTGCBlob(path)) File::IOFile file(path, "rb");
{ TGCHeader header;
File::IOFile file(path, "rb"); if (file.ReadArray(&header, 1) && header.magic == TGC_MAGIC)
return std::unique_ptr<TGCFileReader>(new TGCFileReader(std::move(file))); return std::unique_ptr<TGCFileReader>(new TGCFileReader(std::move(file)));
}
return nullptr; return nullptr;
} }

View File

@ -14,7 +14,7 @@
namespace DiscIO namespace DiscIO
{ {
bool IsTGCBlob(const std::string& path); static constexpr u32 TGC_MAGIC = 0xA2380FAE;
struct TGCHeader struct TGCHeader
{ {

View File

@ -83,8 +83,10 @@ bool WbfsFileReader::ReadHeader()
{ {
// Read hd size info // Read hd size info
m_files[0]->file.ReadBytes(&m_header, sizeof(WbfsHeader)); 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; m_hd_sector_size = 1ull << m_header.hd_sector_shift;
if (m_size != (m_header.hd_sector_count * m_hd_sector_size)) if (m_size != (m_header.hd_sector_count * m_hd_sector_size))
@ -172,14 +174,4 @@ std::unique_ptr<WbfsFileReader> WbfsFileReader::Create(const std::string& filena
return reader; 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 } // namespace

View File

@ -14,6 +14,8 @@
namespace DiscIO namespace DiscIO
{ {
static constexpr u32 WBFS_MAGIC = 0x53464257; // "WBFS" (byteswapped to little endian)
class WbfsFileReader : public IBlobReader class WbfsFileReader : public IBlobReader
{ {
public: public:
@ -58,7 +60,7 @@ private:
#pragma pack(1) #pragma pack(1)
struct WbfsHeader struct WbfsHeader
{ {
char magic[4]; u32 magic;
u32 hd_sector_count; u32 hd_sector_count;
u8 hd_sector_shift; u8 hd_sector_shift;
u8 wbfs_sector_shift; u8 wbfs_sector_shift;
@ -73,6 +75,4 @@ private:
bool m_good; bool m_good;
}; };
bool IsWbfsBlob(const std::string& filename);
} // namespace } // namespace