Fix loading DLC using IOCTL_ES_OPENTITLECONTENT & /dev/es state save.
(Intertwined enough that's it's easier to do in one patch.) (1) /dev/es did not support state save, which could cause crashes and incorrect behavior after loading. (2) NANDContentLoader tried to read all of a title's contents into memory when it was first opened. Two issues: - If any contents were missing, it bailed out. However, with DLC, only some of the contents may be downloaded, as determined by the permission bits in the ticket. Instead, return an appropriate error when a content is accessed that doesn't exist on the filesystem (don't bother checking the permission bits though). - Everything was loaded into memory - even if it consisted of 3 GB of songs, which caused Dolphin to lag out for quite a while (and would fail on 32-bit). Instead, open content on demand.
This commit is contained in:
parent
4d6d4a97e4
commit
04c41c1d38
|
@ -143,7 +143,7 @@ bool ReadFileToString(bool text_file, const char *filename, std::string &str);
|
||||||
// simple wrapper for cstdlib file functions to
|
// simple wrapper for cstdlib file functions to
|
||||||
// hopefully will make error checking easier
|
// hopefully will make error checking easier
|
||||||
// and make forgetting an fclose() harder
|
// and make forgetting an fclose() harder
|
||||||
class IOFile
|
class IOFile : public NonCopyable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
IOFile();
|
IOFile();
|
||||||
|
@ -209,10 +209,6 @@ public:
|
||||||
// clear error state
|
// clear error state
|
||||||
void Clear() { m_good = true; std::clearerr(m_file); }
|
void Clear() { m_good = true; std::clearerr(m_file); }
|
||||||
|
|
||||||
private:
|
|
||||||
IOFile(const IOFile&) /*= delete*/;
|
|
||||||
IOFile& operator=(const IOFile&) /*= delete*/;
|
|
||||||
|
|
||||||
std::FILE* m_file;
|
std::FILE* m_file;
|
||||||
bool m_good;
|
bool m_good;
|
||||||
};
|
};
|
||||||
|
|
|
@ -60,7 +60,7 @@ CWII_IPC_HLE_Device_es::CWII_IPC_HLE_Device_es(u32 _DeviceID, const std::string&
|
||||||
: IWII_IPC_HLE_Device(_DeviceID, _rDeviceName)
|
: IWII_IPC_HLE_Device(_DeviceID, _rDeviceName)
|
||||||
, m_pContentLoader(NULL)
|
, m_pContentLoader(NULL)
|
||||||
, m_TitleID(-1)
|
, m_TitleID(-1)
|
||||||
, AccessIdentID(0x6000000)
|
, m_AccessIdentID(0x6000000)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ void CWII_IPC_HLE_Device_es::LoadWAD(const std::string& _rContentFile)
|
||||||
m_ContentFile = _rContentFile;
|
m_ContentFile = _rContentFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWII_IPC_HLE_Device_es::Open(u32 _CommandAddress, u32 _Mode)
|
void CWII_IPC_HLE_Device_es::OpenInternal()
|
||||||
{
|
{
|
||||||
m_pContentLoader = &DiscIO::CNANDContentManager::Access().GetNANDLoader(m_ContentFile);
|
m_pContentLoader = &DiscIO::CNANDContentManager::Access().GetNANDLoader(m_ContentFile);
|
||||||
|
|
||||||
|
@ -119,6 +119,57 @@ bool CWII_IPC_HLE_Device_es::Open(u32 _CommandAddress, u32 _Mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
INFO_LOG(WII_IPC_ES, "Set default title to %08x/%08x", (u32)(m_TitleID>>32), (u32)m_TitleID);
|
INFO_LOG(WII_IPC_ES, "Set default title to %08x/%08x", (u32)(m_TitleID>>32), (u32)m_TitleID);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWII_IPC_HLE_Device_es::DoState(PointerWrap& p)
|
||||||
|
{
|
||||||
|
IWII_IPC_HLE_Device::DoState(p);
|
||||||
|
p.Do(m_ContentFile);
|
||||||
|
OpenInternal();
|
||||||
|
p.Do(m_AccessIdentID);
|
||||||
|
p.Do(m_TitleIDs);
|
||||||
|
|
||||||
|
u32 Count = m_ContentAccessMap.size();
|
||||||
|
p.Do(Count);
|
||||||
|
|
||||||
|
u32 CFD, Position;
|
||||||
|
u64 TitleID;
|
||||||
|
u16 Index;
|
||||||
|
if (p.GetMode() == PointerWrap::MODE_READ)
|
||||||
|
{
|
||||||
|
for (u32 i = 0; i < Count; i++)
|
||||||
|
{
|
||||||
|
p.Do(CFD);
|
||||||
|
p.Do(Position);
|
||||||
|
p.Do(TitleID);
|
||||||
|
p.Do(Index);
|
||||||
|
CFD = OpenTitleContent(CFD, TitleID, Index);
|
||||||
|
if (CFD != 0xffffffff)
|
||||||
|
{
|
||||||
|
m_ContentAccessMap[CFD].m_Position = Position;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (auto itr = m_ContentAccessMap.begin(); itr != m_ContentAccessMap.end(); ++itr)
|
||||||
|
{
|
||||||
|
CFD = itr->first;
|
||||||
|
SContentAccess& Access = itr->second;
|
||||||
|
Position = Access.m_Position;
|
||||||
|
TitleID = Access.m_TitleID;
|
||||||
|
Index = Access.m_pContent->m_Index;
|
||||||
|
p.Do(CFD);
|
||||||
|
p.Do(Position);
|
||||||
|
p.Do(TitleID);
|
||||||
|
p.Do(Index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CWII_IPC_HLE_Device_es::Open(u32 _CommandAddress, u32 _Mode)
|
||||||
|
{
|
||||||
|
OpenInternal();
|
||||||
|
|
||||||
Memory::Write_U32(GetDeviceID(), _CommandAddress+4);
|
Memory::Write_U32(GetDeviceID(), _CommandAddress+4);
|
||||||
if (m_Active)
|
if (m_Active)
|
||||||
|
@ -135,7 +186,7 @@ bool CWII_IPC_HLE_Device_es::Close(u32 _CommandAddress, bool _bForce)
|
||||||
m_pContentLoader = NULL;
|
m_pContentLoader = NULL;
|
||||||
m_TitleIDs.clear();
|
m_TitleIDs.clear();
|
||||||
m_TitleID = -1;
|
m_TitleID = -1;
|
||||||
AccessIdentID = 0x6000000;
|
m_AccessIdentID = 0x6000000;
|
||||||
|
|
||||||
INFO_LOG(WII_IPC_ES, "ES: Close");
|
INFO_LOG(WII_IPC_ES, "ES: Close");
|
||||||
if (!_bForce)
|
if (!_bForce)
|
||||||
|
@ -144,6 +195,37 @@ bool CWII_IPC_HLE_Device_es::Close(u32 _CommandAddress, bool _bForce)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 CWII_IPC_HLE_Device_es::OpenTitleContent(u32 CFD, u64 TitleID, u16 Index)
|
||||||
|
{
|
||||||
|
const DiscIO::SNANDContent* pContent = AccessContentDevice(TitleID).GetContentByIndex(Index);
|
||||||
|
|
||||||
|
if (pContent == NULL)
|
||||||
|
{
|
||||||
|
return 0xffffffff; //TODO: what is the correct error value here?
|
||||||
|
}
|
||||||
|
|
||||||
|
SContentAccess Access;
|
||||||
|
Access.m_Position = 0;
|
||||||
|
Access.m_pContent = pContent;
|
||||||
|
Access.m_TitleID = TitleID;
|
||||||
|
|
||||||
|
if (!pContent->m_pData)
|
||||||
|
{
|
||||||
|
std::string Filename = pContent->m_Filename;
|
||||||
|
INFO_LOG(WII_IPC_ES, "ES: load %s", Filename.c_str());
|
||||||
|
|
||||||
|
Access.m_File.Open(Filename, "rb");
|
||||||
|
if (!Access.m_File.IsGood())
|
||||||
|
{
|
||||||
|
WARN_LOG(WII_IPC_ES, "ES: couldn't load %s", Filename.c_str());
|
||||||
|
return 0xffffffff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_ContentAccessMap[CFD] = std::move(Access);
|
||||||
|
return CFD;
|
||||||
|
}
|
||||||
|
|
||||||
bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
|
bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
|
||||||
{
|
{
|
||||||
SIOCtlVBuffer Buffer(_CommandAddress);
|
SIOCtlVBuffer Buffer(_CommandAddress);
|
||||||
|
@ -242,16 +324,11 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
|
||||||
u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address);
|
u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address);
|
||||||
u32 Index = Memory::Read_U32(Buffer.InBuffer[2].m_Address);
|
u32 Index = Memory::Read_U32(Buffer.InBuffer[2].m_Address);
|
||||||
|
|
||||||
u32 CFD = AccessIdentID++;
|
u32 CFD = OpenTitleContent(m_AccessIdentID++, TitleID, Index);
|
||||||
m_ContentAccessMap[CFD].m_Position = 0;
|
|
||||||
m_ContentAccessMap[CFD].m_pContent = AccessContentDevice(TitleID).GetContentByIndex(Index);
|
|
||||||
_dbg_assert_msg_(WII_IPC_ES, m_ContentAccessMap[CFD].m_pContent != NULL, "No Content for TitleID: %08x/%08x at Index %x", (u32)(TitleID>>32), (u32)TitleID, Index);
|
|
||||||
// Fix for DLC by itsnotmailmail
|
|
||||||
if (m_ContentAccessMap[CFD].m_pContent == NULL)
|
|
||||||
CFD = 0xffffffff; //TODO: what is the correct error value here?
|
|
||||||
Memory::Write_U32(CFD, _CommandAddress + 0x4);
|
Memory::Write_U32(CFD, _CommandAddress + 0x4);
|
||||||
|
|
||||||
INFO_LOG(WII_IPC_ES, "IOCTL_ES_OPENTITLECONTENT: TitleID: %08x/%08x Index %i -> got CFD %x", (u32)(TitleID>>32), (u32)TitleID, Index, CFD);
|
INFO_LOG(WII_IPC_ES, "IOCTL_ES_OPENTITLECONTENT: TitleID: %08x/%08x Index %i -> got CFD %x", (u32)(TitleID>>32), (u32)TitleID, Index, CFD);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -260,19 +337,12 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
|
||||||
{
|
{
|
||||||
_dbg_assert_(WII_IPC_ES, Buffer.NumberInBuffer == 1);
|
_dbg_assert_(WII_IPC_ES, Buffer.NumberInBuffer == 1);
|
||||||
_dbg_assert_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 0);
|
_dbg_assert_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 0);
|
||||||
|
|
||||||
u32 CFD = AccessIdentID++;
|
|
||||||
u32 Index = Memory::Read_U32(Buffer.InBuffer[0].m_Address);
|
u32 Index = Memory::Read_U32(Buffer.InBuffer[0].m_Address);
|
||||||
|
|
||||||
m_ContentAccessMap[CFD].m_Position = 0;
|
u32 CFD = OpenTitleContent(m_AccessIdentID++, m_TitleID, Index);
|
||||||
m_ContentAccessMap[CFD].m_pContent = AccessContentDevice(m_TitleID).GetContentByIndex(Index);
|
|
||||||
|
|
||||||
if (m_ContentAccessMap[CFD].m_pContent == NULL)
|
|
||||||
CFD = 0xffffffff; //TODO: what is the correct error value here?
|
|
||||||
|
|
||||||
Memory::Write_U32(CFD, _CommandAddress + 0x4);
|
Memory::Write_U32(CFD, _CommandAddress + 0x4);
|
||||||
|
|
||||||
INFO_LOG(WII_IPC_ES, "IOCTL_ES_OPENCONTENT: Index %i -> got CFD %x", Index, CFD);
|
INFO_LOG(WII_IPC_ES, "IOCTL_ES_OPENCONTENT: Index %i -> got CFD %x", Index, CFD);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -286,12 +356,16 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
|
||||||
u32 Size = Buffer.PayloadBuffer[0].m_Size;
|
u32 Size = Buffer.PayloadBuffer[0].m_Size;
|
||||||
u32 Addr = Buffer.PayloadBuffer[0].m_Address;
|
u32 Addr = Buffer.PayloadBuffer[0].m_Address;
|
||||||
|
|
||||||
_dbg_assert_(WII_IPC_ES, m_ContentAccessMap.find(CFD) != m_ContentAccessMap.end());
|
auto itr = m_ContentAccessMap.find(CFD);
|
||||||
SContentAccess& rContent = m_ContentAccessMap[CFD];
|
if (itr == m_ContentAccessMap.end())
|
||||||
|
{
|
||||||
|
Memory::Write_U32(-1, _CommandAddress + 0x4);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
SContentAccess& rContent = itr->second;
|
||||||
|
|
||||||
_dbg_assert_(WII_IPC_ES, rContent.m_pContent->m_pData != NULL);
|
_dbg_assert_(WII_IPC_ES, rContent.m_pContent->m_pData != NULL);
|
||||||
|
|
||||||
u8* pSrc = &rContent.m_pContent->m_pData[rContent.m_Position];
|
|
||||||
u8* pDest = Memory::GetPointer(Addr);
|
u8* pDest = Memory::GetPointer(Addr);
|
||||||
|
|
||||||
if (rContent.m_Position + Size > rContent.m_pContent->m_Size)
|
if (rContent.m_Position + Size > rContent.m_pContent->m_Size)
|
||||||
|
@ -302,7 +376,17 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
|
||||||
if (Size > 0)
|
if (Size > 0)
|
||||||
{
|
{
|
||||||
if (pDest) {
|
if (pDest) {
|
||||||
|
if (rContent.m_pContent->m_pData)
|
||||||
|
{
|
||||||
|
u8* pSrc = &rContent.m_pContent->m_pData[rContent.m_Position];
|
||||||
memcpy(pDest, pSrc, Size);
|
memcpy(pDest, pSrc, Size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
File::IOFile* pFile = &rContent.m_File;
|
||||||
|
pFile->Seek(rContent.m_Position, SEEK_SET);
|
||||||
|
pFile->ReadBytes(pDest, Size);
|
||||||
|
}
|
||||||
rContent.m_Position += Size;
|
rContent.m_Position += Size;
|
||||||
} else {
|
} else {
|
||||||
PanicAlertT("IOCTL_ES_READCONTENT - bad destination");
|
PanicAlertT("IOCTL_ES_READCONTENT - bad destination");
|
||||||
|
@ -323,8 +407,7 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
|
||||||
|
|
||||||
u32 CFD = Memory::Read_U32(Buffer.InBuffer[0].m_Address);
|
u32 CFD = Memory::Read_U32(Buffer.InBuffer[0].m_Address);
|
||||||
|
|
||||||
CContentAccessMap::iterator itr = m_ContentAccessMap.find(CFD);
|
m_ContentAccessMap.erase(CFD);
|
||||||
m_ContentAccessMap.erase(itr);
|
|
||||||
|
|
||||||
INFO_LOG(WII_IPC_ES, "IOCTL_ES_CLOSECONTENT: CFD %x", CFD);
|
INFO_LOG(WII_IPC_ES, "IOCTL_ES_CLOSECONTENT: CFD %x", CFD);
|
||||||
|
|
||||||
|
@ -342,8 +425,13 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
|
||||||
u32 Addr = Memory::Read_U32(Buffer.InBuffer[1].m_Address);
|
u32 Addr = Memory::Read_U32(Buffer.InBuffer[1].m_Address);
|
||||||
u32 Mode = Memory::Read_U32(Buffer.InBuffer[2].m_Address);
|
u32 Mode = Memory::Read_U32(Buffer.InBuffer[2].m_Address);
|
||||||
|
|
||||||
_dbg_assert_(WII_IPC_ES, m_ContentAccessMap.find(CFD) != m_ContentAccessMap.end());
|
auto itr = m_ContentAccessMap.find(CFD);
|
||||||
SContentAccess& rContent = m_ContentAccessMap[CFD];
|
if (itr == m_ContentAccessMap.end())
|
||||||
|
{
|
||||||
|
Memory::Write_U32(-1, _CommandAddress + 0x4);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
SContentAccess& rContent = itr->second;
|
||||||
|
|
||||||
switch (Mode)
|
switch (Mode)
|
||||||
{
|
{
|
||||||
|
@ -908,7 +996,7 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
|
||||||
const DiscIO::INANDContentLoader& CWII_IPC_HLE_Device_es::AccessContentDevice(u64 _TitleID)
|
const DiscIO::INANDContentLoader& CWII_IPC_HLE_Device_es::AccessContentDevice(u64 _TitleID)
|
||||||
{
|
{
|
||||||
if (m_pContentLoader->IsValid() && m_pContentLoader->GetTitleID() == _TitleID)
|
if (m_pContentLoader->IsValid() && m_pContentLoader->GetTitleID() == _TitleID)
|
||||||
return* m_pContentLoader;
|
return *m_pContentLoader;
|
||||||
|
|
||||||
CTitleToContentMap::iterator itr = m_NANDContent.find(_TitleID);
|
CTitleToContentMap::iterator itr = m_NANDContent.find(_TitleID);
|
||||||
if (itr != m_NANDContent.end())
|
if (itr != m_NANDContent.end())
|
||||||
|
|
|
@ -19,6 +19,10 @@ public:
|
||||||
|
|
||||||
void LoadWAD(const std::string& _rContentFile);
|
void LoadWAD(const std::string& _rContentFile);
|
||||||
|
|
||||||
|
void OpenInternal();
|
||||||
|
|
||||||
|
virtual void DoState(PointerWrap& p);
|
||||||
|
|
||||||
virtual bool Open(u32 _CommandAddress, u32 _Mode);
|
virtual bool Open(u32 _CommandAddress, u32 _Mode);
|
||||||
|
|
||||||
virtual bool Close(u32 _CommandAddress, bool _bForce);
|
virtual bool Close(u32 _CommandAddress, bool _bForce);
|
||||||
|
@ -108,10 +112,12 @@ private:
|
||||||
ES_HASH_SIZE_WRONG = -2014, // HASH !=20
|
ES_HASH_SIZE_WRONG = -2014, // HASH !=20
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SContentAccess
|
struct SContentAccess : public NonCopyable
|
||||||
{
|
{
|
||||||
u32 m_Position;
|
u32 m_Position;
|
||||||
|
u64 m_TitleID;
|
||||||
const DiscIO::SNANDContent* m_pContent;
|
const DiscIO::SNANDContent* m_pContent;
|
||||||
|
File::IOFile m_File;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::map<u32, SContentAccess> CContentAccessMap;
|
typedef std::map<u32, SContentAccess> CContentAccessMap;
|
||||||
|
@ -124,13 +130,14 @@ private:
|
||||||
|
|
||||||
std::vector<u64> m_TitleIDs;
|
std::vector<u64> m_TitleIDs;
|
||||||
u64 m_TitleID;
|
u64 m_TitleID;
|
||||||
u32 AccessIdentID;
|
u32 m_AccessIdentID;
|
||||||
|
|
||||||
static u8 *keyTable[11];
|
static u8 *keyTable[11];
|
||||||
|
|
||||||
u64 GetCurrentTitleID() const;
|
u64 GetCurrentTitleID() const;
|
||||||
|
|
||||||
const DiscIO::INANDContentLoader& AccessContentDevice(u64 _TitleID);
|
const DiscIO::INANDContentLoader& AccessContentDevice(u64 _TitleID);
|
||||||
|
u32 OpenTitleContent(u32 CFD, u64 TitleID, u16 Index);
|
||||||
|
|
||||||
bool IsValid(u64 _TitleID) const;
|
bool IsValid(u64 _TitleID) const;
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ void CSharedContent::UpdateLocation()
|
||||||
CSharedContent::~CSharedContent()
|
CSharedContent::~CSharedContent()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
std::string CSharedContent::GetFilenameFromSHA1(u8* _pHash)
|
std::string CSharedContent::GetFilenameFromSHA1(const u8* _pHash)
|
||||||
{
|
{
|
||||||
for (size_t i=0; i<m_Elements.size(); i++)
|
for (size_t i=0; i<m_Elements.size(); i++)
|
||||||
{
|
{
|
||||||
|
@ -58,7 +58,7 @@ std::string CSharedContent::GetFilenameFromSHA1(u8* _pHash)
|
||||||
return "unk";
|
return "unk";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string CSharedContent::AddSharedContent(u8* _pHash)
|
std::string CSharedContent::AddSharedContent(const u8* _pHash)
|
||||||
{
|
{
|
||||||
std::string szFilename = GetFilenameFromSHA1(_pHash);
|
std::string szFilename = GetFilenameFromSHA1(_pHash);
|
||||||
if (strcasecmp(szFilename.c_str(), "unk") == 0)
|
if (strcasecmp(szFilename.c_str(), "unk") == 0)
|
||||||
|
@ -170,8 +170,11 @@ const SNANDContent* CNANDContentLoader::GetContentByIndex(int _Index) const
|
||||||
{
|
{
|
||||||
for (size_t i=0; i<m_Content.size(); i++)
|
for (size_t i=0; i<m_Content.size(); i++)
|
||||||
{
|
{
|
||||||
if (m_Content[i].m_Index == _Index)
|
const SNANDContent* pContent = &m_Content[i];
|
||||||
return &m_Content[i];
|
if (pContent->m_Index == _Index)
|
||||||
|
{
|
||||||
|
return pContent;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -262,36 +265,18 @@ bool CNANDContentLoader::Initialize(const std::string& _rName)
|
||||||
}
|
}
|
||||||
|
|
||||||
rContent.m_pData = NULL;
|
rContent.m_pData = NULL;
|
||||||
char szFilename[1024];
|
|
||||||
|
|
||||||
if (rContent.m_Type & 0x8000) // shared app
|
if (rContent.m_Type & 0x8000) // shared app
|
||||||
{
|
{
|
||||||
std::string Filename = CSharedContent::AccessInstance().GetFilenameFromSHA1(rContent.m_SHA1Hash);
|
rContent.m_Filename = CSharedContent::AccessInstance().GetFilenameFromSHA1(rContent.m_SHA1Hash);
|
||||||
strcpy(szFilename, Filename.c_str());
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sprintf(szFilename, "%s/%08x.app", m_Path.c_str(), rContent.m_ContentID);
|
rContent.m_Filename = StringFromFormat("%s/%08x.app", m_Path.c_str(), rContent.m_ContentID);
|
||||||
}
|
}
|
||||||
|
|
||||||
INFO_LOG(DISCIO, "NANDContentLoader: load %s", szFilename);
|
// Be graceful about incorrect tmds.
|
||||||
|
rContent.m_Size = (u32) File::GetSize(rContent.m_Filename);
|
||||||
File::IOFile pFile(szFilename, "rb");
|
|
||||||
if (pFile)
|
|
||||||
{
|
|
||||||
const u64 ContentSize = File::GetSize(szFilename);
|
|
||||||
rContent.m_pData = new u8[(u32)ContentSize];
|
|
||||||
|
|
||||||
_dbg_assert_msg_(BOOT, rContent.m_Size==ContentSize, "TMDLoader: Incorrect filesize (%s %i). Your NAND dump may be corrupt.", szFilename, i);
|
|
||||||
|
|
||||||
pFile.ReadBytes(rContent.m_pData, (size_t)ContentSize);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ERROR_LOG(DISCIO, "NANDContentLoader: error opening %s", szFilename);
|
|
||||||
delete [] pTMD;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
delete [] pTMD;
|
delete [] pTMD;
|
||||||
|
@ -493,7 +478,7 @@ u64 CNANDContentManager::Install_WiiWAD(std::string &fileName)
|
||||||
|
|
||||||
for (u32 i = 0; i < ContentLoader.GetContentSize(); i++)
|
for (u32 i = 0; i < ContentLoader.GetContentSize(); i++)
|
||||||
{
|
{
|
||||||
SNANDContent Content = ContentLoader.GetContent()[i];
|
const SNANDContent& Content = ContentLoader.GetContent()[i];
|
||||||
|
|
||||||
pTMDFile.WriteBytes(Content.m_Header, INANDContentLoader::CONTENT_HEADER_SIZE);
|
pTMDFile.WriteBytes(Content.m_Header, INANDContentLoader::CONTENT_HEADER_SIZE);
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "Blob.h"
|
#include "Blob.h"
|
||||||
#include "Volume.h"
|
#include "Volume.h"
|
||||||
#include "NandPaths.h"
|
#include "NandPaths.h"
|
||||||
|
#include "FileUtil.h"
|
||||||
|
|
||||||
namespace DiscIO
|
namespace DiscIO
|
||||||
{
|
{
|
||||||
|
@ -26,6 +27,7 @@ struct SNANDContent
|
||||||
u8 m_SHA1Hash[20];
|
u8 m_SHA1Hash[20];
|
||||||
u8 m_Header[36]; //all of the above
|
u8 m_Header[36]; //all of the above
|
||||||
|
|
||||||
|
std::string m_Filename;
|
||||||
u8* m_pData;
|
u8* m_pData;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -95,8 +97,8 @@ public:
|
||||||
|
|
||||||
static CSharedContent& AccessInstance() { return m_Instance; }
|
static CSharedContent& AccessInstance() { return m_Instance; }
|
||||||
|
|
||||||
std::string GetFilenameFromSHA1(u8* _pHash);
|
std::string GetFilenameFromSHA1(const u8* _pHash);
|
||||||
std::string AddSharedContent(u8* _pHash);
|
std::string AddSharedContent(const u8* _pHash);
|
||||||
void UpdateLocation();
|
void UpdateLocation();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
Loading…
Reference in New Issue