WbfsBlob: Only open each file once

The first file used to be opened once by
CreateBlobReader and once inside WbfsFileReader.
This commit is contained in:
JosJuice 2016-12-21 14:01:00 +01:00
parent 8d54bbc528
commit 5c02795af0
3 changed files with 44 additions and 33 deletions

View File

@ -199,7 +199,7 @@ std::unique_ptr<IBlobReader> CreateBlobReader(const std::string& filename)
case TGC_MAGIC:
return TGCFileReader::Create(std::move(file));
case WBFS_MAGIC:
return WbfsFileReader::Create(filename);
return WbfsFileReader::Create(std::move(file), filename);
default:
return PlainFileReader::Create(std::move(file));
}

View File

@ -7,9 +7,11 @@
#include <cstring>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "Common/Align.h"
#include "Common/Assert.h"
#include "Common/CommonFuncs.h"
#include "Common/CommonTypes.h"
#include "Common/FileUtil.h"
@ -23,14 +25,15 @@ static const u64 WII_SECTOR_SIZE = 0x8000;
static const u64 WII_SECTOR_COUNT = 143432 * 2;
static const u64 WII_DISC_HEADER_SIZE = 256;
WbfsFileReader::WbfsFileReader(const std::string& filename)
: m_total_files(0), m_size(0), m_good(true)
WbfsFileReader::WbfsFileReader(File::IOFile file, const std::string& path)
: m_total_files(0), m_size(0), m_good(false)
{
if (filename.length() < 4 || !OpenFiles(filename) || !ReadHeader())
{
m_good = false;
if (!AddFileToList(std::move(file)))
return;
}
OpenAdditionalFiles(path);
if (!ReadHeader())
return;
m_good = true;
// Grab disc info (assume slot 0, checked in ReadHeader())
m_wlba_table.resize(m_blocks_per_disc);
@ -50,38 +53,40 @@ u64 WbfsFileReader::GetDataSize() const
return WII_SECTOR_COUNT * WII_SECTOR_SIZE;
}
bool WbfsFileReader::OpenFiles(const std::string& filename)
void WbfsFileReader::OpenAdditionalFiles(const std::string& path)
{
m_total_files = 0;
if (path.length() < 4)
return;
_assert_(m_total_files > 0); // The code below gives .wbf0 for index 0, but it should be .wbfs
while (true)
{
auto new_entry = std::make_unique<file_entry>();
// Replace last character with index (e.g. wbfs = wbf1)
std::string path = filename;
if (m_total_files != 0)
{
path[path.length() - 1] = '0' + m_total_files;
}
if (!new_entry->file.Open(path, "rb"))
{
return m_total_files != 0;
}
new_entry->base_address = m_size;
new_entry->size = new_entry->file.GetSize();
m_size += new_entry->size;
m_total_files++;
m_files.emplace_back(std::move(new_entry));
std::string current_path = path;
current_path.back() = '0' + m_total_files;
if (!AddFileToList(File::IOFile(current_path, "rb")))
return;
}
}
bool WbfsFileReader::AddFileToList(File::IOFile file)
{
if (!file.IsOpen())
return false;
const u64 file_size = file.GetSize();
m_files.emplace_back(std::make_unique<file_entry>(std::move(file), m_size, file_size));
m_size += file_size;
m_total_files++;
return true;
}
bool WbfsFileReader::ReadHeader()
{
// Read hd size info
m_files[0]->file.Seek(0, SEEK_SET);
m_files[0]->file.ReadBytes(&m_header, sizeof(WbfsHeader));
if (m_header.magic != WBFS_MAGIC)
return false;
@ -164,9 +169,9 @@ File::IOFile& WbfsFileReader::SeekToCluster(u64 offset, u64* available)
return m_files[0]->file;
}
std::unique_ptr<WbfsFileReader> WbfsFileReader::Create(const std::string& filename)
std::unique_ptr<WbfsFileReader> WbfsFileReader::Create(File::IOFile file, const std::string& path)
{
auto reader = std::unique_ptr<WbfsFileReader>(new WbfsFileReader(filename));
auto reader = std::unique_ptr<WbfsFileReader>(new WbfsFileReader(std::move(file), path));
if (!reader->IsGood())
reader.reset();

View File

@ -21,7 +21,7 @@ class WbfsFileReader : public IBlobReader
public:
~WbfsFileReader();
static std::unique_ptr<WbfsFileReader> Create(const std::string& filename);
static std::unique_ptr<WbfsFileReader> Create(File::IOFile file, const std::string& path);
BlobType GetBlobType() const override { return BlobType::WBFS; }
// The WBFS format does not save the original file size.
@ -33,15 +33,21 @@ public:
bool Read(u64 offset, u64 nbytes, u8* out_ptr) override;
private:
WbfsFileReader(const std::string& filename);
WbfsFileReader(File::IOFile file, const std::string& path);
bool OpenFiles(const std::string& filename);
void OpenAdditionalFiles(const std::string& path);
bool AddFileToList(File::IOFile file);
bool ReadHeader();
File::IOFile& SeekToCluster(u64 offset, u64* available);
bool IsGood() { return m_good; }
struct file_entry
{
file_entry(File::IOFile file_, u64 base_address_, u64 size_)
: file(std::move(file_)), base_address(base_address_), size(size_)
{
}
File::IOFile file;
u64 base_address;
u64 size;