Implement parts of DIVerify that can be useful. (copy tmd to emulated nand for disc titles)

correct some parts of uid.sys as disc title ids are included
title in uid + tmd on nand is how the sysmenu knows which save files to look for.
IE games that are displayed in the disc channel at least once and have a save file will be
viewable in the sysmenu save manager

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6189 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
LPFaint99 2010-09-07 06:06:08 +00:00
parent dee24e5695
commit e0383634d3
9 changed files with 126 additions and 76 deletions

View File

@ -21,20 +21,68 @@
namespace Common namespace Common
{ {
std::string CreateTicketFileName(u64 _TitleID) std::string CreateTicketFileName(u64 _titleID)
{ {
char TicketFilename[1024]; char TicketFilename[1024];
sprintf(TicketFilename, "%sticket/%08x/%08x.tik", File::GetUserPath(D_WIIUSER_IDX), (u32)(_TitleID >> 32), (u32)_TitleID); sprintf(TicketFilename, "%sticket/%08x/%08x.tik", File::GetUserPath(D_WIIUSER_IDX), (u32)(_titleID >> 32), (u32)_titleID);
return TicketFilename; return TicketFilename;
} }
std::string CreateTitleContentPath(u64 _TitleID) std::string CreateTitleDataPath(u64 _titleID)
{
char path[1024];
sprintf(path, "%stitle/%08x/%08x/data", File::GetUserPath(D_WIIUSER_IDX), (u32)(_titleID >> 32), (u32)_titleID);
return path;
}
std::string CreateTitleContentPath(u64 _titleID)
{ {
char ContentPath[1024]; char ContentPath[1024];
sprintf(ContentPath, "%stitle/%08x/%08x/content", File::GetUserPath(D_WIIUSER_IDX), (u32)(_TitleID >> 32), (u32)_TitleID); sprintf(ContentPath, "%stitle/%08x/%08x/content", File::GetUserPath(D_WIIUSER_IDX), (u32)(_titleID >> 32), (u32)_titleID);
return ContentPath; return ContentPath;
} }
bool CheckTitleTMD(u64 _titleID)
{
std::string TitlePath;
TitlePath = CreateTitleContentPath(_titleID) + "/title.tmd";
if (File::Exists(TitlePath.c_str()))
{
FILE* pTMDFile = fopen(TitlePath.c_str(), "rb");
if(pTMDFile)
{
u64 TitleID = 0xDEADBEEFDEADBEEFULL;
fseek(pTMDFile, 0x18C, SEEK_SET);
fread(&TitleID, 8, 1, pTMDFile);
fclose(pTMDFile);
if (_titleID == Common::swap64(TitleID))
return true;
}
}
INFO_LOG(DISCIO, "Invalid or no tmd for title %08x %08x", (u32)(_titleID >> 32), (u32)(_titleID & 0xFFFFFFFF));
return false;
}
bool CheckTitleTIK(u64 _titleID)
{
std::string TikPath = Common::CreateTicketFileName(_titleID);
if (File::Exists(TikPath.c_str()))
{
FILE* pTIKFile = fopen(TikPath.c_str(), "rb");
if(pTIKFile)
{
u64 TitleID = 0xDEADBEEFDEADBEEFULL;
fseek(pTIKFile, 0x1dC, SEEK_SET);
fread(&TitleID, 8, 1, pTIKFile);
fclose(pTIKFile);
if (_titleID == Common::swap64(TitleID))
return true;
}
}
INFO_LOG(DISCIO, "Invalid or no tik for title %08x %08x", (u32)(_titleID >> 32), (u32)(_titleID & 0xFFFFFFFF));
return false;
}
}; };

View File

@ -25,7 +25,11 @@
namespace Common namespace Common
{ {
std::string CreateTicketFileName(u64 _TitleID); std::string CreateTicketFileName(u64 _titleID);
std::string CreateTitleContentPath(u64 _TitleID); std::string CreateTitleDataPath(u64 _titleID);
std::string CreateTitleContentPath(u64 _titleID);
bool CheckTitleTMD(u64 _titleID);
bool CheckTitleTIK(u64 _titleID);
} }
#endif #endif

View File

@ -137,6 +137,14 @@ void SetDefaultContentFile(const std::string& _rFilename)
if (pDevice) if (pDevice)
pDevice->LoadWAD(_rFilename); pDevice->LoadWAD(_rFilename);
} }
void ES_DIVerify(u8 *_pTMD, u32 _sz)
{
CWII_IPC_HLE_Device_es* pDevice = (CWII_IPC_HLE_Device_es*)AccessDeviceByID(GetDeviceIDByName(std::string("/dev/es")));
if (pDevice)
pDevice->ES_DIVerify(_pTMD, _sz);
else
ERROR_LOG(WII_IPC_ES, "DIVerify called but /dev/es is not available");
}
int GetDeviceIDByName(const std::string& _rDeviceName) int GetDeviceIDByName(const std::string& _rDeviceName)
{ {

View File

@ -42,6 +42,7 @@ void DoState(PointerWrap &p);
// Set default content file // Set default content file
void SetDefaultContentFile(const std::string& _rFilename); void SetDefaultContentFile(const std::string& _rFilename);
void ES_DIVerify(u8 *_pTMD, u32 _sz);
int GetDeviceIDByName(const std::string& _rDeviceName); int GetDeviceIDByName(const std::string& _rDeviceName);

View File

@ -18,6 +18,7 @@
#include "Common.h" #include "Common.h"
#include "WII_IPC_HLE_Device_DI.h" #include "WII_IPC_HLE_Device_DI.h"
#include "WII_IPC_HLE.h"
#include "../HW/DVDInterface.h" #include "../HW/DVDInterface.h"
#include "../HW/CPU.h" #include "../HW/CPU.h"
@ -122,10 +123,17 @@ bool CWII_IPC_HLE_Device_di::IOCtlV(u32 _CommandAddress)
INFO_LOG(WII_IPC_DVD, "DVDLowOpenPartition: TMDOffset 0x%016llx", TMDOffset); INFO_LOG(WII_IPC_DVD, "DVDLowOpenPartition: TMDOffset 0x%016llx", TMDOffset);
u32 TMDsz = CommandBuffer.PayloadBuffer[0].m_Size;
u8 *pTMD = new u8[TMDsz];
if (pTMD)
{
// Read TMD to the buffer // Read TMD to the buffer
readOK |= VolumeHandler::RAWReadToPtr(Memory::GetPointer(CommandBuffer.PayloadBuffer[0].m_Address), VolumeHandler::RAWReadToPtr(pTMD, TMDOffset, TMDsz);
TMDOffset, CommandBuffer.PayloadBuffer[0].m_Size);
memcpy(Memory::GetPointer(CommandBuffer.PayloadBuffer[0].m_Address), pTMD, TMDsz);
readOK |= true;
WII_IPC_HLE_Interface::ES_DIVerify(pTMD, TMDsz);
}
ReturnValue = readOK ? 1 : 0; ReturnValue = readOK ? 1 : 0;
} }
break; break;

View File

@ -55,7 +55,7 @@
#include "../Boot/Boot_DOL.h" #include "../Boot/Boot_DOL.h"
#include "NandPaths.h" #include "NandPaths.h"
#include "CommonPaths.h"
CWII_IPC_HLE_Device_es::CWII_IPC_HLE_Device_es(u32 _DeviceID, const std::string& _rDeviceName) CWII_IPC_HLE_Device_es::CWII_IPC_HLE_Device_es(u32 _DeviceID, const std::string& _rDeviceName)
: IWII_IPC_HLE_Device(_DeviceID, _rDeviceName) : IWII_IPC_HLE_Device(_DeviceID, _rDeviceName)
, m_pContentLoader(NULL) , m_pContentLoader(NULL)
@ -82,9 +82,12 @@ bool CWII_IPC_HLE_Device_es::Open(u32 _CommandAddress, u32 _Mode)
m_TitleID = m_pContentLoader->GetTitleID(); m_TitleID = m_pContentLoader->GetTitleID();
// System menu versions about 0xE0 will indicate that system files are corrupted if there is more than one title // System menu versions about 0xE0 will indicate that system files are corrupted if there is more than one title
// TODO: fix System menu versions above this and remove this check // TODO: fix System menu versions above this and remove this check
if (m_pContentLoader->GetTitleVersion() <= 0xE0) if (m_pContentLoader->GetTitleVersion() <= 0xE0)
{ {
DiscIO::cUIDsys::AccessInstance().GetTitleIDs(m_TitleIDs); DiscIO::cUIDsys::AccessInstance().GetTitleIDs(m_TitleIDs);
// uncomment if ES_GetOwnedTitlesCount / ES_GetOwnedTitles is implemented
// DiscIO::cUIDsys::AccessInstance().GetTitleIDs(m_TitleIDsOwned, true);
} }
else else
{ {
@ -387,7 +390,7 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
{ {
_dbg_assert_msg_(WII_IPC_ES, Buffer.NumberInBuffer == 1, "IOCTL_ES_SETUID no in buffer"); _dbg_assert_msg_(WII_IPC_ES, Buffer.NumberInBuffer == 1, "IOCTL_ES_SETUID no in buffer");
_dbg_assert_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 0); _dbg_assert_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 0);
// TODO: fs permissions based on this
u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address); u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address);
INFO_LOG(WII_IPC_ES, "IOCTL_ES_SETUID titleID: %08x/%08x", (u32)(TitleID>>32), (u32)TitleID); INFO_LOG(WII_IPC_ES, "IOCTL_ES_SETUID titleID: %08x/%08x", (u32)(TitleID>>32), (u32)TitleID);
} }
@ -788,3 +791,35 @@ bool CWII_IPC_HLE_Device_es::IsValid(u64 _TitleID) const
} }
u32 CWII_IPC_HLE_Device_es::ES_DIVerify(u8* _pTMD, u32 _sz)
{
u64 titleID = 0xDEADBEEFDEADBEEFull;
u64 tmdTitleID = Common::swap64(*(u64*)(_pTMD+0x18c));
VolumeHandler::GetVolume()->GetTitleID((u8*)&titleID);
if (Common::swap64(titleID) != tmdTitleID)
{
return -1;
}
std::string contentPath,
dataPath,
tmdPath;
contentPath = Common::CreateTitleContentPath(tmdTitleID) + DIR_SEP;
dataPath = Common::CreateTitleDataPath(tmdTitleID) + DIR_SEP;
tmdPath = contentPath + "/title.tmd";
File::CreateFullPath(contentPath.c_str());
File::CreateFullPath(dataPath.c_str());
if(!File::Exists(tmdPath.c_str()))
{
FILE* _pTMDFile = fopen(tmdPath.c_str(), "wb");
if (_pTMDFile)
{
if (fwrite(_pTMD, _sz, 1, _pTMDFile) != 1)
ERROR_LOG(WII_IPC_ES, "DIVerify failed to write disc tmd to nand");
fclose(_pTMDFile);
}
}
DiscIO::cUIDsys::AccessInstance().AddTitle(tmdTitleID);
return 0;
}

View File

@ -37,7 +37,7 @@ public:
virtual bool Close(u32 _CommandAddress, bool _bForce); virtual bool Close(u32 _CommandAddress, bool _bForce);
virtual bool IOCtlV(u32 _CommandAddress); virtual bool IOCtlV(u32 _CommandAddress);
u32 ES_DIVerify(u8 *_pTMD, u32 _sz);
private: private:
enum enum

View File

@ -264,6 +264,7 @@ bool CNANDContentLoader::CreateFromDirectory(const std::string& _rPath)
else else
{ {
ERROR_LOG(DISCIO, "NANDContentLoader: error opening %s", szFilename); ERROR_LOG(DISCIO, "NANDContentLoader: error opening %s", szFilename);
delete [] pTMD;
return false; return false;
} }
} }
@ -374,7 +375,6 @@ const INANDContentLoader& CNANDContentManager::GetNANDLoader(const std::string&
const INANDContentLoader& CNANDContentManager::GetNANDLoader(u64 _titleId) const INANDContentLoader& CNANDContentManager::GetNANDLoader(u64 _titleId)
{ {
std::string _rName = Common::CreateTitleContentPath(_titleId); std::string _rName = Common::CreateTitleContentPath(_titleId);
return GetNANDLoader(_rName); return GetNANDLoader(_rName);
} }
@ -383,8 +383,6 @@ cUIDsys::cUIDsys()
{ {
sprintf(uidSys, "%ssys/uid.sys", File::GetUserPath(D_WIIUSER_IDX)); sprintf(uidSys, "%ssys/uid.sys", File::GetUserPath(D_WIIUSER_IDX));
lastUID = 0x00001000; lastUID = 0x00001000;
bool validTMD;
bool validTIK;
if (File::Exists(uidSys)) if (File::Exists(uidSys))
{ {
FILE* pFile = fopen(uidSys, "rb"); FILE* pFile = fopen(uidSys, "rb");
@ -392,20 +390,14 @@ cUIDsys::cUIDsys()
{ {
SElement Element; SElement Element;
if (fread(&Element, sizeof(SElement), 1, pFile) == 1) if (fread(&Element, sizeof(SElement), 1, pFile) == 1)
{
validTMD = CheckTitleTMD(Common::swap64(Element.titleID));
validTIK = CheckTitleTIK(Common::swap64(Element.titleID));
if (validTMD && validTIK)
{ {
*(u32*)&(Element.UID) = Common::swap32(lastUID++); *(u32*)&(Element.UID) = Common::swap32(lastUID++);
m_Elements.push_back(Element); m_Elements.push_back(Element);
}
} }
} }
fclose(pFile); fclose(pFile);
} }
else if(!m_Elements.size())
{ {
SElement Element; SElement Element;
*(u64*)&(Element.titleID) = Common::swap64(TITLEID_SYSMENU); *(u64*)&(Element.titleID) = Common::swap64(TITLEID_SYSMENU);
@ -428,7 +420,7 @@ u32 cUIDsys::GetUIDFromTitle(u64 _Title)
{ {
for (size_t i=0; i<m_Elements.size(); i++) for (size_t i=0; i<m_Elements.size(); i++)
{ {
if (Common::swap64(_Title) == (u64)m_Elements[i].titleID) if (Common::swap64(_Title) == *(u64*)&(m_Elements[i].titleID))
{ {
return Common::swap32(m_Elements[i].UID); return Common::swap32(m_Elements[i].UID);
} }
@ -458,59 +450,15 @@ bool cUIDsys::AddTitle(u64 _TitleID)
} }
} }
void cUIDsys::GetTitleIDs(std::vector<u64>& _TitleIDs) void cUIDsys::GetTitleIDs(std::vector<u64>& _TitleIDs, bool _owned)
{ {
for (size_t i = 0; i < m_Elements.size(); i++) for (size_t i = 0; i < m_Elements.size(); i++)
{ {
if ((_owned && Common::CheckTitleTIK(Common::swap64(m_Elements[i].titleID))) ||
(!_owned && Common::CheckTitleTMD(Common::swap64(m_Elements[i].titleID))))
_TitleIDs.push_back(Common::swap64(m_Elements[i].titleID)); _TitleIDs.push_back(Common::swap64(m_Elements[i].titleID));
} }
} }
bool cUIDsys::CheckTitleTMD(u64 _TitleID)
{
char TitlePath[1024];
sprintf(TitlePath, "%stitle/%08x/%08x/content/title.tmd", File::GetUserPath(D_WIIUSER_IDX),
(u32)(_TitleID >> 32), (u32)(_TitleID & 0xFFFFFFFF));
if (File::Exists(TitlePath))
{
FILE* pTMDFile = fopen(TitlePath, "rb");
if(pTMDFile)
{
u64 TitleID = 0xDEADBEEFDEADBEEFULL;
fseek(pTMDFile, 0x18C, SEEK_SET);
fread(&TitleID, 8, 1, pTMDFile);
fclose(pTMDFile);
if (_TitleID == Common::swap64(TitleID))
return true;
}
}
INFO_LOG(DISCIO, "Invalid or no tmd for title %08x %08x", (u32)(_TitleID >> 32), (u32)(_TitleID & 0xFFFFFFFF));
return false;
}
bool cUIDsys::CheckTitleTIK(u64 _TitleID)
{
char TitlePath[1024];
sprintf(TitlePath, "%sticket/%08x/%08x.tik", File::GetUserPath(D_WIIUSER_IDX),
(u32)(_TitleID >> 32), (u32)(_TitleID & 0xFFFFFFFF));
if (File::Exists(TitlePath))
{
FILE* pTIKFile = fopen(TitlePath, "rb");
if(pTIKFile)
{
u64 TitleID = 0xDEADBEEFDEADBEEFULL;
fseek(pTIKFile, 0x1dC, SEEK_SET);
fread(&TitleID, 8, 1, pTIKFile);
fclose(pTIKFile);
if (_TitleID == Common::swap64(TitleID))
return true;
}
}
INFO_LOG(DISCIO, "Invalid or no tik for title %08x %08x", (u32)(_TitleID >> 32), (u32)(_TitleID & 0xFFFFFFFF));
return false;
}
} // namespace end } // namespace end

View File

@ -133,9 +133,7 @@ public:
u32 GetUIDFromTitle(u64 _Title); u32 GetUIDFromTitle(u64 _Title);
bool AddTitle(u64 _Title); bool AddTitle(u64 _Title);
bool CheckTitleTMD(u64 _TitleID); void GetTitleIDs(std::vector<u64>& _TitleIDs, bool _owned = false);
bool CheckTitleTIK(u64 _TitleID);
void GetTitleIDs(std::vector<u64>& _TitleIDs);
private: private: