hide the distinction between WAD and File from ES

instead, leave all the management with the NANDContentLoader.

for file data (directly on the NAND), this opens the file on-demand and
returns the requested chunk when asked for it.
for on-the-fly decrypted WAD data, we just keep the decoded buffer in
memory, like we've done before - except that we don't give away any objects
we don't want to.
This commit is contained in:
BhaaL
2016-03-16 20:08:37 +01:00
parent 8fd2f05741
commit 8a6d9e1e0b
5 changed files with 86 additions and 62 deletions

View File

@ -92,6 +92,46 @@ std::string CSharedContent::AddSharedContent(const u8* hash)
}
const std::vector<u8> CNANDContentDataFile::Get()
{
std::vector<u8> result;
File::IOFile file(m_filename, "rb");
if (!file.IsGood())
return result;
u64 size = file.GetSize();
if (size == 0)
return result;
result.resize(size);
file.ReadBytes(result.data(), result.size());
return result;
}
bool CNANDContentDataFile::GetRange(u32 start, u32 size, u8* buffer)
{
File::IOFile file(m_filename, "rb");
if (!file.IsGood())
return false;
if (!file.Seek(start, SEEK_SET))
return false;
return file.ReadBytes(buffer, static_cast<size_t>(size));
}
bool CNANDContentDataBuffer::GetRange(u32 start, u32 size, u8* buffer)
{
if (start + size > m_buffer.size())
return false;
std::copy(&m_buffer[start], &m_buffer[start + size], buffer);
return true;
}
CNANDContentLoader::CNANDContentLoader(const std::string& content_name)
: m_Valid(false)
, m_IsWAD(false)
@ -207,20 +247,23 @@ void CNANDContentLoader::InitializeContentEntries(const std::vector<u8>& tmd, co
iv.fill(0);
std::copy(&tmd[entry_offset + 0x01E8], &tmd[entry_offset + 0x01E8 + 2], iv.begin());
content.m_data = AESDecode(decrypted_title_key.data(), iv.data(), &data_app[data_app_offset], rounded_size);
content.m_Data = std::make_unique<CNANDContentDataBuffer>(AESDecode(decrypted_title_key.data(), iv.data(), &data_app[data_app_offset], rounded_size));
data_app_offset += rounded_size;
continue;
}
std::string filename;
if (content.m_Type & 0x8000) // shared app
content.m_Filename = CSharedContent::AccessInstance().GetFilenameFromSHA1(content.m_SHA1Hash);
filename = CSharedContent::AccessInstance().GetFilenameFromSHA1(content.m_SHA1Hash);
else
content.m_Filename = StringFromFormat("%s/%08x.app", m_Path.c_str(), content.m_ContentID);
filename = StringFromFormat("%s/%08x.app", m_Path.c_str(), content.m_ContentID);
content.m_Data = std::make_unique<CNANDContentDataFile>(filename);
// Be graceful about incorrect TMDs.
if (File::Exists(content.m_Filename))
content.m_Size = static_cast<u32>(File::GetSize(content.m_Filename));
if (File::Exists(filename))
content.m_Size = static_cast<u32>(File::GetSize(filename));
}
}
@ -429,7 +472,7 @@ u64 CNANDContentManager::Install_WiiWAD(const std::string& filename)
return 0;
}
app_file.WriteBytes(content.m_data.data(), content.m_Size);
app_file.WriteBytes(content.m_Data->Get().data(), content.m_Size);
}
else
{

View File

@ -17,6 +17,34 @@ namespace DiscIO
{
bool AddTicket(u64 title_id, const std::vector<u8>& ticket);
class CNANDContentData
{
public:
virtual const std::vector<u8> Get() = 0;
virtual bool GetRange(u32 start, u32 size, u8* buffer) = 0;
};
class CNANDContentDataFile final : public CNANDContentData
{
public:
CNANDContentDataFile(const std::string& filename) : m_filename(filename) { };
const std::vector<u8> Get() override;
bool GetRange(u32 start, u32 size, u8* buffer) override;
private:
const std::string m_filename;
};
class CNANDContentDataBuffer final : public CNANDContentData
{
public:
CNANDContentDataBuffer(const std::vector<u8>& buffer) : m_buffer(buffer) { };
const std::vector<u8> Get() override { return m_buffer; };
bool GetRange(u32 start, u32 size, u8* buffer) override;
private:
const std::vector<u8> m_buffer;
};
struct SNANDContent
{
u32 m_ContentID;
@ -26,8 +54,7 @@ struct SNANDContent
u8 m_SHA1Hash[20];
u8 m_Header[36]; //all of the above
std::string m_Filename;
std::vector<u8> m_data;
std::unique_ptr<CNANDContentData> m_Data;
};
// Instances of this class must be created by CNANDContentManager