Merge pull request #877 from lioncash/voldir

DiscIO: Move VolumeDirectory off of raw pointers
This commit is contained in:
Lioncash 2014-08-28 04:11:33 -04:00
commit 6955e023a0
2 changed files with 49 additions and 93 deletions

View File

@ -6,6 +6,7 @@
#include <cstddef> #include <cstddef>
#include <cstring> #include <cstring>
#include <map> #include <map>
#include <memory>
#include <string> #include <string>
#include <utility> #include <utility>
#include <vector> #include <vector>
@ -25,20 +26,14 @@ CVolumeDirectory::CVolumeDirectory(const std::string& _rDirectory, bool _bIsWii,
const std::string& _rApploader, const std::string& _rDOL) const std::string& _rApploader, const std::string& _rDOL)
: m_totalNameSize(0) : m_totalNameSize(0)
, m_dataStartAddress(-1) , m_dataStartAddress(-1)
, m_fstSize(0) , m_diskHeader(DISKHEADERINFO_ADDRESS)
, m_FSTData(nullptr) , m_diskHeaderInfo(new SDiskHeaderInfo())
, m_apploaderSize(0)
, m_apploader(nullptr)
, m_DOLSize(0)
, m_DOL(nullptr)
, FST_ADDRESS(0) , FST_ADDRESS(0)
, DOL_ADDRESS(0) , DOL_ADDRESS(0)
{ {
m_rootDirectory = ExtractDirectoryName(_rDirectory); m_rootDirectory = ExtractDirectoryName(_rDirectory);
// create the default disk header // create the default disk header
m_diskHeader = new u8[DISKHEADERINFO_ADDRESS];
memset(m_diskHeader, 0, (size_t)DISKHEADERINFO_ADDRESS);
SetUniqueID("AGBJ01"); SetUniqueID("AGBJ01");
SetName("Default name"); SetName("Default name");
@ -51,8 +46,6 @@ CVolumeDirectory::CVolumeDirectory(const std::string& _rDirectory, bool _bIsWii,
SetDiskTypeGC(); SetDiskTypeGC();
} }
m_diskHeaderInfo = new SDiskHeaderInfo();
// Don't load the dol if we've no apploader... // Don't load the dol if we've no apploader...
if (SetApploader(_rApploader)) if (SetApploader(_rApploader))
SetDOL(_rDOL); SetDOL(_rDOL);
@ -62,20 +55,6 @@ CVolumeDirectory::CVolumeDirectory(const std::string& _rDirectory, bool _bIsWii,
CVolumeDirectory::~CVolumeDirectory() CVolumeDirectory::~CVolumeDirectory()
{ {
delete[] m_FSTData;
m_FSTData = nullptr;
delete[] m_diskHeader;
m_diskHeader = nullptr;
delete m_diskHeaderInfo;
m_diskHeaderInfo = nullptr;
delete[] m_DOL;
m_DOL = nullptr;
delete[] m_apploader;
m_apploader = nullptr;
} }
bool CVolumeDirectory::IsValidDirectory(const std::string& _rDirectory) bool CVolumeDirectory::IsValidDirectory(const std::string& _rDirectory)
@ -94,27 +73,27 @@ bool CVolumeDirectory::Read(u64 _Offset, u64 _Length, u8* _pBuffer) const
// header // header
if (_Offset < DISKHEADERINFO_ADDRESS) if (_Offset < DISKHEADERINFO_ADDRESS)
{ {
WriteToBuffer(DISKHEADER_ADDRESS, DISKHEADERINFO_ADDRESS, m_diskHeader, _Offset, _Length, _pBuffer); WriteToBuffer(DISKHEADER_ADDRESS, DISKHEADERINFO_ADDRESS, m_diskHeader.data(), _Offset, _Length, _pBuffer);
} }
// header info // header info
if (_Offset >= DISKHEADERINFO_ADDRESS && _Offset < APPLOADER_ADDRESS) if (_Offset >= DISKHEADERINFO_ADDRESS && _Offset < APPLOADER_ADDRESS)
{ {
WriteToBuffer(DISKHEADERINFO_ADDRESS, sizeof(m_diskHeaderInfo), (u8*)m_diskHeaderInfo, _Offset, _Length, _pBuffer); WriteToBuffer(DISKHEADERINFO_ADDRESS, sizeof(m_diskHeaderInfo), (u8*)m_diskHeaderInfo.get(), _Offset, _Length, _pBuffer);
} }
// apploader // apploader
if (_Offset >= APPLOADER_ADDRESS && _Offset < APPLOADER_ADDRESS + m_apploaderSize) if (_Offset >= APPLOADER_ADDRESS && _Offset < APPLOADER_ADDRESS + m_apploader.size())
{ {
WriteToBuffer(APPLOADER_ADDRESS, m_apploaderSize, m_apploader, _Offset, _Length, _pBuffer); WriteToBuffer(APPLOADER_ADDRESS, m_apploader.size(), m_apploader.data(), _Offset, _Length, _pBuffer);
} }
// dol // dol
if (_Offset >= DOL_ADDRESS && _Offset < DOL_ADDRESS + m_DOLSize) if (_Offset >= DOL_ADDRESS && _Offset < DOL_ADDRESS + m_DOL.size())
{ {
WriteToBuffer(DOL_ADDRESS, m_DOLSize, m_DOL, _Offset, _Length, _pBuffer); WriteToBuffer(DOL_ADDRESS, m_DOL.size(), m_DOL.data(), _Offset, _Length, _pBuffer);
} }
// fst // fst
if (_Offset >= FST_ADDRESS && _Offset < m_dataStartAddress) if (_Offset >= FST_ADDRESS && _Offset < m_dataStartAddress)
{ {
WriteToBuffer(FST_ADDRESS, m_fstSize, m_FSTData, _Offset, _Length, _pBuffer); WriteToBuffer(FST_ADDRESS, m_FSTData.size(), m_FSTData.data(), _Offset, _Length, _pBuffer);
} }
if (m_virtualDisk.empty()) if (m_virtualDisk.empty())
@ -169,10 +148,8 @@ bool CVolumeDirectory::Read(u64 _Offset, u64 _Length, u8* _pBuffer) const
std::string CVolumeDirectory::GetUniqueID() const std::string CVolumeDirectory::GetUniqueID() const
{ {
_dbg_assert_(DVDINTERFACE, m_diskHeader);
char buffer[7]; char buffer[7];
memcpy(buffer, m_diskHeader, 6); memcpy(buffer, m_diskHeader.data(), 6);
buffer[6] = 0; buffer[6] = 0;
std::string id = buffer; std::string id = buffer;
@ -181,19 +158,15 @@ std::string CVolumeDirectory::GetUniqueID() const
void CVolumeDirectory::SetUniqueID(std::string _ID) void CVolumeDirectory::SetUniqueID(std::string _ID)
{ {
_dbg_assert_(DVDINTERFACE, m_diskHeader);
u32 length = (u32)_ID.length(); u32 length = (u32)_ID.length();
if (length > 6) if (length > 6)
length = 6; length = 6;
memcpy(m_diskHeader, _ID.c_str(), length); memcpy(m_diskHeader.data(), _ID.c_str(), length);
} }
IVolume::ECountry CVolumeDirectory::GetCountry() const IVolume::ECountry CVolumeDirectory::GetCountry() const
{ {
_dbg_assert_(DVDINTERFACE, m_diskHeader);
u8 CountryCode = m_diskHeader[3]; u8 CountryCode = m_diskHeader[3];
return CountrySwitch(CountryCode); return CountrySwitch(CountryCode);
@ -206,19 +179,16 @@ std::string CVolumeDirectory::GetMakerID() const
std::vector<std::string> CVolumeDirectory::GetNames() const std::vector<std::string> CVolumeDirectory::GetNames() const
{ {
_dbg_assert_(DVDINTERFACE, m_diskHeader); return std::vector<std::string>(1, (char*)(&m_diskHeader[0x20]));
return std::vector<std::string>(1, (char*)(m_diskHeader + 0x20));
} }
void CVolumeDirectory::SetName(std::string _Name) void CVolumeDirectory::SetName(std::string _Name)
{ {
_dbg_assert_(DVDINTERFACE, m_diskHeader);
u32 length = (u32)_Name.length(); u32 length = (u32)_Name.length();
if (length > MAX_NAME_LENGTH) if (length > MAX_NAME_LENGTH)
length = MAX_NAME_LENGTH; length = MAX_NAME_LENGTH;
memcpy(m_diskHeader + 0x20, _Name.c_str(), length); memcpy(&m_diskHeader[0x20], _Name.c_str(), length);
m_diskHeader[length + 0x20] = 0; m_diskHeader[length + 0x20] = 0;
} }
@ -269,22 +239,18 @@ std::string CVolumeDirectory::ExtractDirectoryName(const std::string& _rDirector
void CVolumeDirectory::SetDiskTypeWii() void CVolumeDirectory::SetDiskTypeWii()
{ {
_dbg_assert_(DVDINTERFACE, m_diskHeader);
m_diskHeader[0x18] = 0x5d; m_diskHeader[0x18] = 0x5d;
m_diskHeader[0x19] = 0x1c; m_diskHeader[0x19] = 0x1c;
m_diskHeader[0x1a] = 0x9e; m_diskHeader[0x1a] = 0x9e;
m_diskHeader[0x1b] = 0xa3; m_diskHeader[0x1b] = 0xa3;
memset(m_diskHeader + 0x1c, 0, 4); memset(&m_diskHeader[0x1c], 0, 4);
m_addressShift = 2; m_addressShift = 2;
} }
void CVolumeDirectory::SetDiskTypeGC() void CVolumeDirectory::SetDiskTypeGC()
{ {
_dbg_assert_(DVDINTERFACE, m_diskHeader); memset(&m_diskHeader[0x18], 0, 4);
memset(m_diskHeader + 0x18, 0, 4);
m_diskHeader[0x1c] = 0xc2; m_diskHeader[0x1c] = 0xc2;
m_diskHeader[0x1d] = 0x33; m_diskHeader[0x1d] = 0x33;
m_diskHeader[0x1e] = 0x9f; m_diskHeader[0x1e] = 0x9f;
@ -303,23 +269,22 @@ bool CVolumeDirectory::SetApploader(const std::string& _rApploader)
PanicAlertT("Apploader unable to load from file"); PanicAlertT("Apploader unable to load from file");
return false; return false;
} }
m_apploaderSize = 0x20 + Common::swap32(*(u32*)&data.data()[0x14]) + Common::swap32(*(u32*)&data.data()[0x18]); size_t apploaderSize = 0x20 + Common::swap32(*(u32*)&data.data()[0x14]) + Common::swap32(*(u32*)&data.data()[0x18]);
if (m_apploaderSize != data.size()) if (apploaderSize != data.size())
{ {
PanicAlertT("Apploader is the wrong size...is it really an apploader?"); PanicAlertT("Apploader is the wrong size...is it really an apploader?");
return false; return false;
} }
m_apploader = new u8[m_apploaderSize]; m_apploader.resize(apploaderSize);
copy(data.begin(), data.end(), m_apploader); std::copy(data.begin(), data.end(), m_apploader.begin());
// 32byte aligned (plus 0x20 padding) // 32byte aligned (plus 0x20 padding)
DOL_ADDRESS = ROUND_UP(APPLOADER_ADDRESS + m_apploaderSize + 0x20, 0x20ull); DOL_ADDRESS = ROUND_UP(APPLOADER_ADDRESS + m_apploader.size() + 0x20, 0x20ull);
return true; return true;
} }
else else
{ {
m_apploaderSize = 0x20; m_apploader.resize(0x20);
m_apploader = new u8[m_apploaderSize];
// Make sure BS2 HLE doesn't try to run the apploader // Make sure BS2 HLE doesn't try to run the apploader
*(u32*)&m_apploader[0x10] = (u32)-1; *(u32*)&m_apploader[0x10] = (u32)-1;
return false; return false;
@ -332,23 +297,19 @@ void CVolumeDirectory::SetDOL(const std::string& rDOL)
{ {
std::string data; std::string data;
File::ReadFileToString(rDOL, data); File::ReadFileToString(rDOL, data);
m_DOLSize = data.size(); m_DOL.resize(data.size());
m_DOL = new u8[m_DOLSize]; std::copy(data.begin(), data.end(), m_DOL.begin());
copy(data.begin(), data.end(), m_DOL);
Write32((u32)(DOL_ADDRESS >> m_addressShift), 0x0420, m_diskHeader); Write32((u32)(DOL_ADDRESS >> m_addressShift), 0x0420, &m_diskHeader);
// 32byte aligned (plus 0x20 padding) // 32byte aligned (plus 0x20 padding)
FST_ADDRESS = ROUND_UP(DOL_ADDRESS + m_DOLSize + 0x20, 0x20ull); FST_ADDRESS = ROUND_UP(DOL_ADDRESS + m_DOL.size() + 0x20, 0x20ull);
} }
} }
void CVolumeDirectory::BuildFST() void CVolumeDirectory::BuildFST()
{ {
if (m_FSTData) m_FSTData.clear();
{
delete m_FSTData;
}
File::FSTEntry rootEntry; File::FSTEntry rootEntry;
@ -356,15 +317,14 @@ void CVolumeDirectory::BuildFST()
u32 totalEntries = AddDirectoryEntries(m_rootDirectory, rootEntry) + 1; u32 totalEntries = AddDirectoryEntries(m_rootDirectory, rootEntry) + 1;
m_fstNameOffset = totalEntries * ENTRY_SIZE; // offset in FST nameTable m_fstNameOffset = totalEntries * ENTRY_SIZE; // offset in FST nameTable
m_fstSize = m_fstNameOffset + m_totalNameSize; m_FSTData.resize(m_fstNameOffset + m_totalNameSize);
m_FSTData = new u8[(u32)m_fstSize];
// if FST hasn't been assigned (ie no apploader/dol setup), set to default // if FST hasn't been assigned (ie no apploader/dol setup), set to default
if (FST_ADDRESS == 0) if (FST_ADDRESS == 0)
FST_ADDRESS = APPLOADER_ADDRESS + 0x2000; FST_ADDRESS = APPLOADER_ADDRESS + 0x2000;
// 4 byte aligned start of data on disk // 4 byte aligned start of data on disk
m_dataStartAddress = ROUND_UP(FST_ADDRESS + m_fstSize, 0x8000ull); m_dataStartAddress = ROUND_UP(FST_ADDRESS + m_FSTData.size(), 0x8000ull);
u64 curDataAddress = m_dataStartAddress; u64 curDataAddress = m_dataStartAddress;
u32 fstOffset = 0; // Offset within FST data u32 fstOffset = 0; // Offset within FST data
@ -383,13 +343,12 @@ void CVolumeDirectory::BuildFST()
_dbg_assert_(DVDINTERFACE, nameOffset == m_totalNameSize); _dbg_assert_(DVDINTERFACE, nameOffset == m_totalNameSize);
// write FST size and location // write FST size and location
_dbg_assert_(DVDINTERFACE, m_diskHeader); Write32((u32)(FST_ADDRESS >> m_addressShift), 0x0424, &m_diskHeader);
Write32((u32)(FST_ADDRESS >> m_addressShift), 0x0424, m_diskHeader); Write32((u32)(m_FSTData.size() >> m_addressShift), 0x0428, &m_diskHeader);
Write32((u32)(m_fstSize >> m_addressShift), 0x0428, m_diskHeader); Write32((u32)(m_FSTData.size() >> m_addressShift), 0x042c, &m_diskHeader);
Write32((u32)(m_fstSize >> m_addressShift), 0x042c, m_diskHeader);
} }
void CVolumeDirectory::WriteToBuffer(u64 _SrcStartAddress, u64 _SrcLength, u8* _Src, void CVolumeDirectory::WriteToBuffer(u64 _SrcStartAddress, u64 _SrcLength, const u8* _Src,
u64& _Address, u64& _Length, u8*& _pBuffer) const u64& _Address, u64& _Length, u8*& _pBuffer) const
{ {
if (_Length == 0) if (_Length == 0)
@ -431,12 +390,12 @@ void CVolumeDirectory::PadToAddress(u64 _StartAddress, u64& _Address, u64& _Leng
} }
} }
void CVolumeDirectory::Write32(u32 data, u32 offset, u8* buffer) void CVolumeDirectory::Write32(u32 data, u32 offset, std::vector<u8>* const buffer)
{ {
buffer[offset++] = (data >> 24); (*buffer)[offset++] = (data >> 24);
buffer[offset++] = (data >> 16) & 0xff; (*buffer)[offset++] = (data >> 16) & 0xff;
buffer[offset++] = (data >> 8) & 0xff; (*buffer)[offset++] = (data >> 8) & 0xff;
buffer[offset] = (data) & 0xff; (*buffer)[offset] = (data) & 0xff;
} }
void CVolumeDirectory::WriteEntryData(u32& entryOffset, u8 type, u32 nameOffset, u64 dataOffset, u32 length) void CVolumeDirectory::WriteEntryData(u32& entryOffset, u8 type, u32 nameOffset, u64 dataOffset, u32 length)
@ -447,16 +406,16 @@ void CVolumeDirectory::WriteEntryData(u32& entryOffset, u8 type, u32 nameOffset,
m_FSTData[entryOffset++] = (nameOffset >> 8) & 0xff; m_FSTData[entryOffset++] = (nameOffset >> 8) & 0xff;
m_FSTData[entryOffset++] = (nameOffset) & 0xff; m_FSTData[entryOffset++] = (nameOffset) & 0xff;
Write32((u32)(dataOffset >> m_addressShift), entryOffset, m_FSTData); Write32((u32)(dataOffset >> m_addressShift), entryOffset, &m_FSTData);
entryOffset += 4; entryOffset += 4;
Write32((u32)length, entryOffset, m_FSTData); Write32((u32)length, entryOffset, &m_FSTData);
entryOffset += 4; entryOffset += 4;
} }
void CVolumeDirectory::WriteEntryName(u32& nameOffset, const std::string& name) void CVolumeDirectory::WriteEntryName(u32& nameOffset, const std::string& name)
{ {
strncpy((char*)(m_FSTData + nameOffset + m_fstNameOffset), name.c_str(), name.length() + 1); strncpy((char*)&m_FSTData[nameOffset + m_fstNameOffset], name.c_str(), name.length() + 1);
nameOffset += (u32)(name.length() + 1); nameOffset += (u32)(name.length() + 1);
} }

View File

@ -5,6 +5,7 @@
#pragma once #pragma once
#include <map> #include <map>
#include <memory>
#include <string> #include <string>
#include <vector> #include <vector>
@ -64,12 +65,12 @@ private:
void SetDOL(const std::string& _rDOL); void SetDOL(const std::string& _rDOL);
// writing to read buffer // writing to read buffer
void WriteToBuffer(u64 _SrcStartAddress, u64 _SrcLength, u8* _Src, void WriteToBuffer(u64 _SrcStartAddress, u64 _SrcLength, const u8* _Src,
u64& _Address, u64& _Length, u8*& _pBuffer) const; u64& _Address, u64& _Length, u8*& _pBuffer) const;
void PadToAddress(u64 _StartAddress, u64& _Address, u64& _Length, u8*& _pBuffer) const; void PadToAddress(u64 _StartAddress, u64& _Address, u64& _Length, u8*& _pBuffer) const;
void Write32(u32 data, u32 offset, u8* buffer); void Write32(u32 data, u32 offset, std::vector<u8>* const buffer);
// FST creation // FST creation
void WriteEntryData(u32& entryOffset, u8 type, u32 nameOffset, u64 dataOffset, u32 length); void WriteEntryData(u32& entryOffset, u8 type, u32 nameOffset, u64 dataOffset, u32 length);
@ -92,10 +93,9 @@ private:
u64 m_dataStartAddress; u64 m_dataStartAddress;
u64 m_fstNameOffset; u64 m_fstNameOffset;
u64 m_fstSize; std::vector<u8> m_FSTData;
u8* m_FSTData;
u8* m_diskHeader; std::vector<u8> m_diskHeader;
#pragma pack(push, 1) #pragma pack(push, 1)
struct SDiskHeaderInfo struct SDiskHeaderInfo
@ -124,13 +124,10 @@ private:
} }
}; };
#pragma pack(pop) #pragma pack(pop)
SDiskHeaderInfo* m_diskHeaderInfo; std::unique_ptr<SDiskHeaderInfo> m_diskHeaderInfo;
u64 m_apploaderSize; std::vector<u8> m_apploader;
u8* m_apploader; std::vector<u8> m_DOL;
u64 m_DOLSize;
u8* m_DOL;
static const u8 ENTRY_SIZE = 0x0c; static const u8 ENTRY_SIZE = 0x0c;
static const u8 FILE_ENTRY = 0; static const u8 FILE_ENTRY = 0;