Only open file once when detecting blob type
This commit is contained in:
parent
3fdcbbdd92
commit
d1ea00ed88
|
@ -177,23 +177,31 @@ std::unique_ptr<IBlobReader> 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
|
||||
|
|
|
@ -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> 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<CISOFileReader>(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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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> 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<TGCFileReader>(new TGCFileReader(std::move(file)));
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
namespace DiscIO
|
||||
{
|
||||
bool IsTGCBlob(const std::string& path);
|
||||
static constexpr u32 TGC_MAGIC = 0xA2380FAE;
|
||||
|
||||
struct TGCHeader
|
||||
{
|
||||
|
|
|
@ -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> 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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue