示例#1
0
bool CNANDContentLoader::Initialize(const std::string& name)
{
	if (name.empty())
		return false;

	m_Path = name;

	WiiWAD wad(name);
	std::vector<u8> data_app;
	std::vector<u8> tmd;
	std::vector<u8> decrypted_title_key;

	if (wad.IsValid())
	{
		m_IsWAD = true;
		m_Ticket = wad.GetTicket();
		decrypted_title_key = GetKeyFromTicket(m_Ticket);
		tmd = wad.GetTMD();
		data_app = wad.GetDataApp();
	}
	else
	{
		std::string tmd_filename(m_Path);

		if (tmd_filename.back() == '/')
			tmd_filename += "title.tmd";
		else
			m_Path = tmd_filename.substr(0, tmd_filename.find("title.tmd"));

		File::IOFile tmd_file(tmd_filename, "rb");
		if (!tmd_file)
		{
			WARN_LOG(DISCIO, "CreateFromDirectory: error opening %s", tmd_filename.c_str());
			return false;
		}

		tmd.resize(static_cast<size_t>(File::GetSize(tmd_filename)));
		tmd_file.ReadBytes(tmd.data(), tmd.size());
	}

	std::copy(&tmd[0],     &tmd[TMD_HEADER_SIZE], m_TMDHeader);
	std::copy(&tmd[0x180], &tmd[0x180 + TMD_VIEW_SIZE], m_TMDView);

	m_TitleVersion = Common::swap16(&tmd[0x01DC]);
	m_NumEntries   = Common::swap16(&tmd[0x01DE]);
	m_BootIndex    = Common::swap16(&tmd[0x01E0]);
	m_TitleID      = Common::swap64(&tmd[0x018C]);
	m_IosVersion   = Common::swap16(&tmd[0x018A]);
	m_Country      = static_cast<u8>(m_TitleID & 0xFF);

	if (m_Country == 2) // SYSMENU
		m_Country = GetSysMenuRegion(m_TitleVersion);

	InitializeContentEntries(tmd, decrypted_title_key, data_app);
	return true;
}
示例#2
0
bool CNANDContentLoader::Initialize(const std::string& _rName)
{
	if (_rName.empty())
		return false;
	m_Path = _rName;
	WiiWAD Wad(_rName);
	u8* pDataApp = nullptr;
	u8* pTMD = nullptr;
	u8 DecryptTitleKey[16];
	u8 IV[16];
	if (Wad.IsValid())
	{
		m_isWAD = true;
		m_TIKSize = Wad.GetTicketSize();
		m_TIK = new u8[m_TIKSize];
		memcpy(m_TIK, Wad.GetTicket(), m_TIKSize);
		GetKeyFromTicket(m_TIK, DecryptTitleKey);
		u32 pTMDSize = Wad.GetTMDSize();
		pTMD = new u8[pTMDSize];
		memcpy(pTMD, Wad.GetTMD(), pTMDSize);
		pDataApp = Wad.GetDataApp();
	}
	else
	{
		std::string TMDFileName(m_Path);

		if ('/' == *TMDFileName.rbegin())
			TMDFileName += "title.tmd";
		else
			m_Path = TMDFileName.substr(0, TMDFileName.find("title.tmd"));

		File::IOFile pTMDFile(TMDFileName, "rb");
		if (!pTMDFile)
		{
			WARN_LOG(DISCIO, "CreateFromDirectory: error opening %s",
					 TMDFileName.c_str());
			return false;
		}
		u32 pTMDSize = (u32)File::GetSize(TMDFileName);
		pTMD = new u8[pTMDSize];
		pTMDFile.ReadBytes(pTMD, (size_t)pTMDSize);
		pTMDFile.Close();
	}

	memcpy(m_TMDView, pTMD + 0x180, TMD_VIEW_SIZE);
	memcpy(m_TMDHeader, pTMD, TMD_HEADER_SIZE);


	m_TitleVersion = Common::swap16(pTMD + 0x01dc);
	m_numEntries = Common::swap16(pTMD + 0x01de);
	m_BootIndex = Common::swap16(pTMD + 0x01e0);
	m_TitleID = Common::swap64(pTMD + 0x018c);
	m_IosVersion = Common::swap16(pTMD + 0x018a);
	m_Country = *(u8*)&m_TitleID;
	if (m_Country == 2) // SYSMENU
		m_Country = GetSysMenuRegion(m_TitleVersion);

	m_Content.resize(m_numEntries);


	for (u32 i=0; i<m_numEntries; i++)
	{
		SNANDContent& rContent = m_Content[i];

		rContent.m_ContentID = Common::swap32(pTMD + 0x01e4 + 0x24*i);
		rContent.m_Index = Common::swap16(pTMD + 0x01e8 + 0x24*i);
		rContent.m_Type = Common::swap16(pTMD + 0x01ea + 0x24*i);
		rContent.m_Size= (u32)Common::swap64(pTMD + 0x01ec + 0x24*i);
		memcpy(rContent.m_SHA1Hash, pTMD + 0x01f4 + 0x24*i, 20);
		memcpy(rContent.m_Header, pTMD + 0x01e4 + 0x24*i, 36);

		if (m_isWAD)
		{
			u32 RoundedSize = ROUND_UP(rContent.m_Size, 0x40);
			rContent.m_pData = new u8[RoundedSize];

			memset(IV, 0, sizeof IV);
			memcpy(IV, pTMD + 0x01e8 + 0x24*i, 2);
			AESDecode(DecryptTitleKey, IV, pDataApp, RoundedSize, rContent.m_pData);

			pDataApp += RoundedSize;
			continue;
		}

		rContent.m_pData = nullptr;

		if (rContent.m_Type & 0x8000)  // shared app
		{
			rContent.m_Filename = CSharedContent::AccessInstance().GetFilenameFromSHA1(rContent.m_SHA1Hash);
		}
		else
		{
			rContent.m_Filename = StringFromFormat("%s/%08x.app", m_Path.c_str(), rContent.m_ContentID);
		}

		// Be graceful about incorrect tmds.
		if (File::Exists(rContent.m_Filename))
		{
			rContent.m_Size = (u32) File::GetSize(rContent.m_Filename);
		}
	}

	delete [] pTMD;
	return true;
}