fixed some ES problems and added cached for NANDContentLoader (we open this content files ways to often at the moment)

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2651 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
fires.gc 2009-03-13 16:15:15 +00:00
parent b3a6208fcc
commit 0b76db1c04
9 changed files with 255 additions and 132 deletions

View File

@ -90,7 +90,7 @@ std::string CBoot::GenerateMapFilename()
{
case SCoreStartupParameter::BOOT_WII_NAND:
{
DiscIO::CNANDContentLoader Loader( _StartupPara.m_strFilename);
const DiscIO::INANDContentLoader& Loader = DiscIO::CNANDContentManager::Access().GetNANDLoader(_StartupPara.m_strFilename);
if (Loader.IsValid())
{
u64 TitleID = Loader.GetTitleID();

View File

@ -86,12 +86,12 @@ void SetupWiiMem()
bool CBoot::IsWiiWAD(const char *filename)
{
return DiscIO::CNANDContentLoader::IsWiiWAD(filename);
return DiscIO::CNANDContentManager::IsWiiWAD(filename);
}
bool CBoot::Boot_WiiWAD(const char* _pFilename)
{
DiscIO::CNANDContentLoader ContentLoader(_pFilename);
const DiscIO::INANDContentLoader& ContentLoader = DiscIO::CNANDContentManager::Access().GetNANDLoader(_pFilename);
if (ContentLoader.IsValid() == false)
return false;
@ -109,7 +109,7 @@ bool CBoot::Boot_WiiWAD(const char* _pFilename)
Memory::Write_U64( ContentLoader.GetTitleID(), 0x0000318c); // NAND Load Title ID
// DOL
DiscIO::SNANDContent* pContent = ContentLoader.GetContentByIndex(ContentLoader.GetBootIndex());
const DiscIO::SNANDContent* pContent = ContentLoader.GetContentByIndex(ContentLoader.GetBootIndex());
if (pContent == NULL)
return false;

View File

@ -140,7 +140,7 @@ bool SCoreStartupParameter::AutoSetup(EBootBios _BootBios)
m_BootType = BOOT_DOL;
bNTSC = true;
}
else if (DiscIO::CNANDContentLoader(m_strFilename).IsValid())
else if (DiscIO::CNANDContentManager::Access().GetNANDLoader(m_strFilename).IsValid())
{
bWii = true;
Region = EUR_DIR;

View File

@ -203,6 +203,10 @@ IWII_IPC_HLE_Device* CreateDevice(u32 _DeviceID, const std::string& _rDeviceName
else if (_rDeviceName.find("/dev/usb/oh0") != std::string::npos)
{
pDevice = new CWII_IPC_HLE_Device_usb_oh0(_DeviceID, _rDeviceName);
}
else if (_rDeviceName.find("/dev/usb/kbd") != std::string::npos)
{
pDevice = new CWII_IPC_HLE_Device_usb_kbd(_DeviceID, _rDeviceName);
}
else if (_rDeviceName.find("/dev/sdio/slot0") != std::string::npos)
{

View File

@ -60,7 +60,7 @@ CWII_IPC_HLE_Device_es::CWII_IPC_HLE_Device_es(u32 _DeviceID, const std::string&
, m_TitleID(-1)
, AccessIdentID(0x6000000)
{
m_pContentLoader = new DiscIO::CNANDContentLoader(_rDefaultContentFile);
m_pContentLoader = &DiscIO::CNANDContentManager::Access().GetNANDLoader(_rDefaultContentFile);
// check for cd ...
if (m_pContentLoader->IsValid())
@ -79,43 +79,20 @@ CWII_IPC_HLE_Device_es::CWII_IPC_HLE_Device_es(u32 _DeviceID, const std::string&
// scan for the title ids listed in TMDs within /title/
m_TitleIDs.clear();
m_TitleIDs.push_back(0x0000000100000002ULL);
// m_TitleIDs.push_back(0x0001000248414741ULL);
// m_TitleIDs.push_back(0x0001000248414341ULL);
// m_TitleIDs.push_back(0x0001000248414241ULL);
// m_TitleIDs.push_back(0x0001000248414141ULL);
// FindValidTitleIDs();
// std::string titleDir(FULL_WII_USER_DIR + std::string("title"));
// File::FSTEntry parentEntry;
// u32 numEntries = ScanDirectoryTree(titleDir.c_str(), parentEntry);
//
// for(std::vector<File::FSTEntry>::iterator level1 = parentEntry.children.begin(); level1 != parentEntry.children.end(); ++level1)
// {
// if (level1->isDirectory)
// {
// for(std::vector<File::FSTEntry>::iterator level2 = level1->children.begin(); level2 != level1->children.end(); ++level2)
// {
// if (level2->isDirectory)
// {
// // finally at /title/*/*/
// // ...get titleID from content/title.tmd
// std::string currentTMD(level2->physicalName + DIR_SEP + "content" + DIR_SEP + "title.tmd");
// if (File::Exists(currentTMD.c_str()))
// {
// FILE *tmd = fopen(currentTMD.c_str(), "rb");
// u64 titleID = 0xDEADBEEFDEADBEEFULL;
// fseek(tmd, 0x18C, SEEK_SET);
// fread(&titleID, 8, 1, tmd);
// m_TitleIDs.push_back(Common::swap64(titleID));
// fclose(tmd);
// }
// }
// }
// }
// }
INFO_LOG(WII_IPC_ES, "Set default title to %08x/%08x", m_TitleID>>32, m_TitleID);
}
CWII_IPC_HLE_Device_es::~CWII_IPC_HLE_Device_es()
{
delete m_pContentLoader;
CTitleToContentMap::const_iterator itr = m_NANDContent.begin();
while(itr != m_NANDContent.end())
{
@ -162,12 +139,22 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address);
DiscIO::CNANDContentLoader& rNANDCOntent = AccessContentDevice(TitleID);
const DiscIO::INANDContentLoader& rNANDCOntent = AccessContentDevice(TitleID);
_dbg_assert_(WII_IPC_ES, rNANDCOntent.IsValid());
Memory::Write_U32((u32)rNANDCOntent.GetContentSize(), Buffer.PayloadBuffer[0].m_Address);
u32 NumberOfPrivateContent = 0;
const std::vector<DiscIO::SNANDContent>& rContent = rNANDCOntent.GetContent();
for (size_t i=0; i<rContent.size();i++)
{
if ((rContent[i].m_Type & 0x8000) == 0)
{
NumberOfPrivateContent++;
}
}
INFO_LOG(WII_IPC_ES, "ES: IOCTL_ES_GETTITLECONTENTSCNT: TitleID: %08x/%08x content count %i",
Memory::Write_U32(NumberOfPrivateContent, Buffer.PayloadBuffer[0].m_Address);
INFO_LOG(WII_IPC_ES, "ES: IOCTL_ES_GETTITLECONTENTSCNT: TitleID: %08x/%08x content count %i (just content in private directory)",
(u32)(TitleID>>32), (u32)TitleID, rNANDCOntent.GetContentSize());
Memory::Write_U32(0, _CommandAddress + 0x4);
@ -183,25 +170,25 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address);
u32 MaxCount = Memory::Read_U32(Buffer.InBuffer[1].m_Address);
std::string TitleFilename = CreateTitleContentPath(TitleID);
DiscIO::CNANDContentLoader Loader(TitleFilename);
const DiscIO::INANDContentLoader& Loader = DiscIO::CNANDContentManager::Access().GetNANDLoader(TitleFilename);
ERROR_LOG(WII_IPC_ES, "IOCTL_ES_GETTITLECONTENTS: title: %08x/%08x buffersize: %i", (u32)(TitleID >> 32), (u32)TitleID, MaxCount);
ERROR_LOG(WII_IPC_ES, "IOCTL_ES_GETTITLECONTENTS: title: %08x/%08x MaxCount: %i (just content in private directory)", (u32)(TitleID >> 32), (u32)TitleID, MaxCount);
u32 Count = 0;
_dbg_assert_(WII_IPC_ES, Loader.GetContentSize() == MaxCount);
if (Loader.IsValid())
{
const std::vector<DiscIO::SNANDContent>& rContent = Loader.GetContent();
for (size_t i=0; i<Loader.GetContentSize(); i++)
{
Memory::Write_U32(rContent[i].m_Index, Buffer.PayloadBuffer[0].m_Address+i*4);
if ((rContent[i].m_Type & 0x8000) == 0)
{
Memory::Write_U32(rContent[i].m_ContentID, Buffer.PayloadBuffer[0].m_Address+i*4);
ERROR_LOG(WII_IPC_ES, "IOCTL_ES_GETTITLECONTENTS: Index 0x%x", rContent[i].m_ContentID);
Count++;
if (Count>=MaxCount)
break;
}
}
}
Memory::Write_U32(0, _CommandAddress + 0x4);
ERROR_LOG(WII_IPC_ES, "IOCTL_ES_GETTITLECONTENTS: Count %i", Count);
ERROR_LOG(WII_IPC_ES, "IOCTL_ES_GETTITLECONTENTS: Count %i", Loader.GetContentSize());
return true;
}
break;
@ -494,23 +481,22 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address);
std::string TitleFilename = CreateTitleContentPath(TitleID);
DiscIO::CNANDContentLoader Loader(TitleFilename);
const DiscIO::INANDContentLoader& Loader = DiscIO::CNANDContentManager::Access().GetNANDLoader(TitleFilename);
_dbg_assert_(WII_IPC_ES, Loader.IsValid());
u32 TMDViewCnt = 0;
if (Loader.IsValid())
{
TMDViewCnt += DiscIO::CNANDContentLoader::TICKET_VIEW_SIZE;
TMDViewCnt += DiscIO::INANDContentLoader::TICKET_VIEW_SIZE;
TMDViewCnt += 2; // title version
TMDViewCnt += 2; // num entries
TMDViewCnt += Loader.GetContentSize() * (4+2+2+8); // content id, index, type, size
TMDViewCnt += (u32)Loader.GetContentSize() * (4+2+2+8); // content id, index, type, size
}
Memory::Write_U32(TMDViewCnt, Buffer.PayloadBuffer[0].m_Address);
Memory::Write_U32(0, _CommandAddress + 0x4);
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETTMDVIEWCNT: title: %08x/%08x -> count %i", (u32)(TitleID >> 32), (u32)TitleID, TMDViewCnt);
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETTMDVIEWCNT: title: %08x/%08x (view size %i)", (u32)(TitleID >> 32), (u32)TitleID, TMDViewCnt);
return true;
}
break;
@ -523,7 +509,8 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address);
u32 MaxCount = Memory::Read_U32(Buffer.InBuffer[1].m_Address);
std::string TitleFilename = CreateTitleContentPath(TitleID);
DiscIO::CNANDContentLoader Loader(TitleFilename);
const DiscIO::INANDContentLoader& Loader = DiscIO::CNANDContentManager::Access().GetNANDLoader(TitleFilename);
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETTMDVIEWCNT: title: %08x/%08x buffersize: %i", (u32)(TitleID >> 32), (u32)TitleID, MaxCount);
@ -533,8 +520,8 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
{
u32 Address = Buffer.PayloadBuffer[0].m_Address;
Memory::WriteBigEData(Loader.GetTicket(), Address, DiscIO::CNANDContentLoader::TICKET_VIEW_SIZE);
Address += DiscIO::CNANDContentLoader::TICKET_VIEW_SIZE;
Memory::WriteBigEData(Loader.GetTicket(), Address, DiscIO::INANDContentLoader::TICKET_VIEW_SIZE);
Address += DiscIO::INANDContentLoader::TICKET_VIEW_SIZE;
Memory::Write_U16(Loader.GetTitleVersion(), Address); Address += 2;
Memory::Write_U16(Loader.GetNumEntries(), Address); Address += 2;
@ -551,7 +538,8 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
_dbg_assert_(WII_IPC_ES, (Address-Buffer.PayloadBuffer[0].m_Address) == Buffer.PayloadBuffer[0].m_Size);
}
Memory::Write_U32(0, _CommandAddress + 0x4);
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETTMDVIEWCNT: Count %i", Count);
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETTMDVIEWS: title: %08x/%08x (buffer size: %i)", TitleID >> 32, TitleID, MaxCount);
return true;
}
break;
@ -616,7 +604,7 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
return true;
}
DiscIO::CNANDContentLoader& 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)
return* m_pContentLoader;
@ -626,7 +614,7 @@ DiscIO::CNANDContentLoader& CWII_IPC_HLE_Device_es::AccessContentDevice(u64 _Tit
return *itr->second;
std::string TitleFilename = CreateTitleContentPath(_TitleID);
m_NANDContent[_TitleID] = new DiscIO::CNANDContentLoader(TitleFilename);
m_NANDContent[_TitleID] = &DiscIO::CNANDContentManager::Access().GetNANDLoader(TitleFilename);
_dbg_assert_(WII_IPC_ES, m_NANDContent[_TitleID]->IsValid());
return *m_NANDContent[_TitleID];
@ -656,3 +644,35 @@ std::string CWII_IPC_HLE_Device_es::CreateTitleContentPath(u64 _TitleID) const
return TicketFilename;
}
void CWII_IPC_HLE_Device_es::FindValidTitleIDs()
{
m_TitleIDs.clear();
std::string TitlePath(FULL_WII_USER_DIR + std::string("title"));
File::FSTEntry ParentEntry;
u32 NumEntries = ScanDirectoryTree(TitlePath.c_str(), ParentEntry);
for(std::vector<File::FSTEntry>::iterator Level1 = ParentEntry.children.begin(); Level1 != ParentEntry.children.end(); ++Level1)
{
if (Level1->isDirectory)
{
for(std::vector<File::FSTEntry>::iterator Level2 = Level1->children.begin(); Level2 != Level1->children.end(); ++Level2)
{
if (Level2->isDirectory)
{
// finally at /title/*/*/
// ...get titleID from content/title.tmd
std::string CurrentTMD(Level2->physicalName + DIR_SEP + "content" + DIR_SEP + "title.tmd");
if (File::Exists(CurrentTMD.c_str()))
{
FILE* pTMDFile = fopen(CurrentTMD.c_str(), "rb");
u64 TitleID = 0xDEADBEEFDEADBEEFULL;
fseek(pTMDFile, 0x18C, SEEK_SET);
fread(&TitleID, 8, 1, pTMDFile);
m_TitleIDs.push_back(Common::swap64(TitleID));
fclose(pTMDFile);
}
}
}
}
}
}

View File

@ -97,19 +97,35 @@ private:
IOCTL_ES_GETSHAREDCONTENTS = 0x37,
};
enum EErrorCodes
{
ES_INVALID_TMD = -106, // or access denied
ES_READ_LESS_DATA_THAN_EXPECTED = -1009,
ES_UNK_1 = -1010,
ES_PARAMTER_SIZE_OR_ALIGNMENT = -1017,
ES_HASH_DOESNT_MATCH = -1022,
ES_MEM_ALLOC_FAILED = -1024,
ES_INCORRECT_ACCESS_RIGHT = -1026,
ES_NO_TICKET_INSTALLED = -1028,
ES_INSTALLED_TICKET_INVALID = -1029,
ES_INVALID_PARAMETR = -2008,
ES_SIGNATURE_CHECK_FAILED = -2011,
ES_HASH_SIZE_WRONG = -2014, // HASH !=20
};
struct SContentAccess
{
u32 m_Position;
DiscIO::SNANDContent* m_pContent;
const DiscIO::SNANDContent* m_pContent;
};
typedef std::map<u32, SContentAccess> CContentAccessMap;
CContentAccessMap m_ContentAccessMap;
typedef std::map<u64, DiscIO::CNANDContentLoader*> CTitleToContentMap;
typedef std::map<u64, const DiscIO::INANDContentLoader*> CTitleToContentMap;
CTitleToContentMap m_NANDContent;
DiscIO::CNANDContentLoader* m_pContentLoader;
const DiscIO::INANDContentLoader* m_pContentLoader;
std::vector<u64> m_TitleIDs;
u64 m_TitleID;
@ -117,12 +133,13 @@ private:
u64 GetCurrentTitleID() const;
DiscIO::CNANDContentLoader& AccessContentDevice(u64 _TitleID);
const DiscIO::INANDContentLoader& AccessContentDevice(u64 _TitleID);
bool IsValid(u64 _TitleID) const;
std::string CreateTicketFileName(u64 _TitleID) const;
std::string CreateTitleContentPath(u64 _TitleID) const;
void FindValidTitleIDs();
};
#endif

View File

@ -18,6 +18,8 @@
#include "stdafx.h"
#include "NANDContentLoader.h"
#include <algorithm>
#include <cctype>
#include "AES/aes.h"
#include "MathUtil.h"
#include "FileUtil.h"
@ -110,6 +112,53 @@ private:
};
// this classes must be created by the CNANDContentManager
class CNANDContentLoader : public INANDContentLoader
{
public:
CNANDContentLoader(const std::string& _rName);
virtual ~CNANDContentLoader();
bool IsValid() const { return m_Valid; }
u64 GetTitleID() const { return m_TitleID; }
u32 GetBootIndex() const { return m_BootIndex; }
size_t GetContentSize() const { return m_Content.size(); }
const SNANDContent* GetContentByIndex(int _Index) const;
const u8* GetTicket() const { return m_TicketView; }
const std::vector<SNANDContent>& GetContent() const { return m_Content; }
const u16 GetTitleVersion() const {return m_TileVersion;}
const u16 GetNumEntries() const {return m_numEntries;}
private:
bool m_Valid;
u64 m_TitleID;
u32 m_BootIndex;
u16 m_numEntries;
u16 m_TileVersion;
u8 m_TicketView[TICKET_VIEW_SIZE];
std::vector<SNANDContent> m_Content;
bool CreateFromDirectory(const std::string& _rPath);
bool CreateFromWAD(const std::string& _rName);
bool ParseWAD(DiscIO::IBlobReader& _rReader);
void AESDecode(u8* _pKey, u8* _IV, u8* _pSrc, u32 _Size, u8* _pDest);
u8* CreateWADEntry(DiscIO::IBlobReader& _rReader, u32 _Size, u64 _Offset);
void GetKeyFromTicket(u8* pTicket, u8* pTicketKey);
bool ParseTMD(u8* pDataApp, u32 pDataAppSize, u8* pTicket, u8* pTMD);
};
CNANDContentLoader::CNANDContentLoader(const std::string& _rName)
@ -140,7 +189,7 @@ CNANDContentLoader::~CNANDContentLoader()
m_Content.clear();
}
SNANDContent* CNANDContentLoader::GetContentByIndex(int _Index)
const SNANDContent* CNANDContentLoader::GetContentByIndex(int _Index) const
{
for (size_t i=0; i<m_Content.size(); i++)
{
@ -232,35 +281,6 @@ bool CNANDContentLoader::CreateFromDirectory(const std::string& _rPath)
return true;
}
bool CNANDContentLoader::IsWiiWAD(const std::string& _rName)
{
DiscIO::IBlobReader* pReader = DiscIO::CreateBlobReader(_rName.c_str());
if (pReader == NULL)
return false;
CBlobBigEndianReader Reader(*pReader);
bool Result = false;
// check for wii wad
if (Reader.Read32(0x00) == 0x20)
{
u32 WADTYpe = Reader.Read32(0x04);
switch(WADTYpe)
{
case 0x49730000:
case 0x69620000:
Result = true;
}
}
delete pReader;
return Result;
}
void CNANDContentLoader::AESDecode(u8* _pKey, u8* _IV, u8* _pSrc, u32 _Size, u8* _pDest)
{
AES_KEY AESKey;
@ -371,6 +391,70 @@ bool CNANDContentLoader::ParseWAD(DiscIO::IBlobReader& _rReader)
return Result;
}
///////////////////
CNANDContentManager CNANDContentManager::m_Instance;
CNANDContentManager::~CNANDContentManager()
{
CNANDContentMap::iterator itr = m_Map.begin();
while (itr != m_Map.end())
{
delete itr->second;
itr++;
}
m_Map.clear();
}
const INANDContentLoader& CNANDContentManager::GetNANDLoader(const std::string& _rName)
{
std::string KeyString(_rName);
std::transform(KeyString.begin(), KeyString.end(), KeyString.begin(),
(int(*)(int)) std::toupper);
CNANDContentMap::iterator itr = m_Map.find(KeyString);
if (itr != m_Map.end())
return *itr->second;
m_Map[KeyString] = new CNANDContentLoader(KeyString);
return *m_Map[KeyString];
}
bool CNANDContentManager::IsWiiWAD(const std::string& _rName)
{
DiscIO::IBlobReader* pReader = DiscIO::CreateBlobReader(_rName.c_str());
if (pReader == NULL)
return false;
CBlobBigEndianReader Reader(*pReader);
bool Result = false;
// check for wii wad
if (Reader.Read32(0x00) == 0x20)
{
u32 WADTYpe = Reader.Read32(0x04);
switch(WADTYpe)
{
case 0x49730000:
case 0x69620000:
Result = true;
}
}
delete pReader;
return Result;
}
} // namespace end

View File

@ -20,6 +20,8 @@
#include <string>
#include <vector>
#include <map>
#include "Common.h"
#include "Blob.h"
@ -36,58 +38,54 @@ struct SNANDContent
u8* m_pData;
};
class CNANDContentLoader
// pure virtual interface so just the NANDContentManager can create these files only
class INANDContentLoader
{
public:
CNANDContentLoader(const std::string& _rName);
INANDContentLoader() {}
virtual ~CNANDContentLoader();
bool IsValid() const { return m_Valid; }
u64 GetTitleID() const { return m_TitleID; }
u32 GetBootIndex() const { return m_BootIndex; }
size_t GetContentSize() const { return m_Content.size(); }
SNANDContent* GetContentByIndex(int _Index);
const u8* GetTicket() const { return m_TicketView; }
const std::vector<SNANDContent>& GetContent() const { return m_Content; }
static bool IsWiiWAD(const std::string& _rName);
const u16 GetTitleVersion() const {return m_TileVersion;}
const u16 GetNumEntries() const {return m_numEntries;}
virtual ~INANDContentLoader() {}
virtual bool IsValid() const = NULL;
virtual u64 GetTitleID() const = NULL;
virtual u32 GetBootIndex() const = NULL;
virtual size_t GetContentSize() const = NULL;
virtual const SNANDContent* GetContentByIndex(int _Index) const = NULL;;
virtual const u8* GetTicket() const = NULL;
virtual const std::vector<SNANDContent>& GetContent() const = NULL;
virtual const u16 GetTitleVersion() const = NULL;
virtual const u16 GetNumEntries() const = NULL;
enum
{
TICKET_VIEW_SIZE = 0x58
};
};
// we open the NAND Content files to often... lets cache them
class CNANDContentManager
{
public:
static CNANDContentManager& Access() { return m_Instance; }
const INANDContentLoader& GetNANDLoader(const std::string& _rName);
static bool IsWiiWAD(const std::string& _rName);
private:
bool m_Valid;
u64 m_TitleID;
u32 m_BootIndex;
u16 m_numEntries;
u16 m_TileVersion;
u8 m_TicketView[TICKET_VIEW_SIZE];
CNANDContentManager() {};
std::vector<SNANDContent> m_Content;
~CNANDContentManager();
bool CreateFromDirectory(const std::string& _rPath);
bool CreateFromWAD(const std::string& _rName);
static CNANDContentManager m_Instance;
bool ParseWAD(DiscIO::IBlobReader& _rReader);
typedef std::map<std::string, INANDContentLoader*> CNANDContentMap;
CNANDContentMap m_Map;
void AESDecode(u8* _pKey, u8* _IV, u8* _pSrc, u32 _Size, u8* _pDest);
u8* CreateWADEntry(DiscIO::IBlobReader& _rReader, u32 _Size, u64 _Offset);
void GetKeyFromTicket(u8* pTicket, u8* pTicketKey);
bool ParseTMD(u8* pDataApp, u32 pDataAppSize, u8* pTicket, u8* pTMD);
};
}

View File

@ -161,7 +161,7 @@ void CFrame::CreateMenu()
toolsMenu->Append(IDM_CHEATS, _T("Action &Replay Manager"));
// toolsMenu->Append(IDM_SDCARD, _T("Mount &SDCard")); // Disable for now
if (DiscIO::CNANDContentLoader(FULL_WII_MENU_DIR).IsValid())
if (DiscIO::CNANDContentManager::Access().GetNANDLoader(FULL_WII_MENU_DIR).IsValid())
{
toolsMenu->Append(IDM_LOAD_WII_MENU, _T("Load Wii Menu"));
}