// Copyright (C) 2003 Dolphin Project. // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, version 2.0. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License 2.0 for more details. // A copy of the GPL 2.0 should have been included with the program. // If not, see http://www.gnu.org/licenses/ // Official SVN repository and contact information can be found at // http://code.google.com/p/dolphin-emu/ #include "NANDContentLoader.h" #include #include #include "Crypto/aes.h" #include "MathUtil.h" #include "FileUtil.h" #include "Log.h" #include "WiiWad.h" namespace DiscIO { CSharedContent CSharedContent::m_Instance; cUIDsys cUIDsys::m_Instance; CSharedContent::CSharedContent() { lastID = 0; sprintf(contentMap, "%sshared1/content.map", File::GetUserPath(D_WIIUSER_IDX).c_str()); if (File::Exists(contentMap)) { FILE* pFile = fopen(contentMap, "rb"); while(!feof(pFile)) { SElement Element; if (fread(&Element, sizeof(SElement), 1, pFile) == 1) { m_Elements.push_back(Element); lastID++; } } fclose(pFile); } } CSharedContent::~CSharedContent() {} std::string CSharedContent::GetFilenameFromSHA1(u8* _pHash) { for (size_t i=0; i& GetContent() const { return m_Content; } u16 GetTitleVersion() const {return m_TileVersion;} u16 GetNumEntries() const {return m_numEntries;} DiscIO::IVolume::ECountry GetCountry() const; u8 GetCountryChar() const {return m_Country; } private: bool m_Valid; u64 m_TitleID; u16 m_IosVersion; u32 m_BootIndex; u16 m_numEntries; u16 m_TileVersion; u8 m_TicketView[TICKET_VIEW_SIZE]; u8 m_TmdHeader[TMD_HEADER_SIZE]; u8 m_Country; std::vector m_Content; bool CreateFromDirectory(const std::string& _rPath); bool CreateFromWAD(const std::string& _rName); void AESDecode(u8* _pKey, u8* _IV, u8* _pSrc, u32 _Size, u8* _pDest); void GetKeyFromTicket(u8* pTicket, u8* pTicketKey); bool ParseTMD(u8* pDataApp, u32 pDataAppSize, u8* pTicket, u8* pTMD); }; CNANDContentLoader::CNANDContentLoader(const std::string& _rName) : m_Valid(false) , m_TitleID(-1) , m_IosVersion(0x09) , m_BootIndex(-1) { if (File::IsDirectory(_rName)) { m_Valid = CreateFromDirectory(_rName); } else if (File::Exists(_rName)) { m_Valid = CreateFromWAD(_rName); } else { // _dbg_assert_msg_(BOOT, 0, "CNANDContentLoader loads neither folder nor file"); } } CNANDContentLoader::~CNANDContentLoader() { for (size_t i=0; isecond; ++itr; } m_Map.clear(); } const INANDContentLoader& CNANDContentManager::GetNANDLoader(const std::string& _rName, bool forceReload) { CNANDContentMap::iterator lb = m_Map.lower_bound(_rName); if(lb == m_Map.end() || (m_Map.key_comp()(_rName, lb->first))) { m_Map.insert(lb, CNANDContentMap::value_type(_rName, new CNANDContentLoader(_rName))); } else { if (!lb->second->IsValid() || forceReload) { delete lb->second; lb->second = new CNANDContentLoader(_rName); } } return *m_Map[_rName]; } const INANDContentLoader& CNANDContentManager::GetNANDLoader(u64 _titleId, bool forceReload) { std::string _rName = Common::CreateTitleContentPath(_titleId); return GetNANDLoader(_rName, forceReload); } bool CNANDContentManager::RemoveTitle(u64 _titleID) { if (!GetNANDLoader(_titleID).IsValid()) return false; GetNANDLoader(_titleID).RemoveTitle(); return GetNANDLoader(_titleID, true).IsValid(); } void CNANDContentLoader::RemoveTitle() const { INFO_LOG(DISCIO, "RemoveTitle %08x/%08x", (u32)(m_TitleID >> 32), (u32)m_TitleID); if(IsValid()) { // remove tmd? for (u32 i = 0; i < m_numEntries; i++) { char szFilename[1024]; if (!(m_Content[i].m_Type & 0x8000)) // skip shared apps { sprintf(szFilename, "%s/%08x.app", Common::CreateTitleContentPath(m_TitleID).c_str(), m_Content[i].m_ContentID); INFO_LOG(DISCIO, "Delete %s", szFilename); File::Delete(szFilename); } } } } cUIDsys::cUIDsys() { sprintf(uidSys, "%ssys/uid.sys", File::GetUserPath(D_WIIUSER_IDX).c_str()); lastUID = 0x00001000; if (File::Exists(uidSys)) { FILE* pFile = fopen(uidSys, "rb"); while(!feof(pFile)) { SElement Element; if (fread(&Element, sizeof(SElement), 1, pFile) == 1) { *(u32*)&(Element.UID) = Common::swap32(lastUID++); m_Elements.push_back(Element); } } fclose(pFile); } if(!m_Elements.size()) { SElement Element; *(u64*)&(Element.titleID) = Common::swap64(TITLEID_SYSMENU); *(u32*)&(Element.UID) = Common::swap32(lastUID++); File::CreateFullPath(uidSys); FILE* pFile = fopen(uidSys, "wb"); if (pFile) { if (fwrite(&Element, sizeof(SElement), 1, pFile) != 1) ERROR_LOG(DISCIO, "Failed to write to %s", uidSys); fclose(pFile); } } } cUIDsys::~cUIDsys() {} u32 cUIDsys::GetUIDFromTitle(u64 _Title) { for (size_t i=0; i& _TitleIDs, bool _owned) { 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)); } } } // namespace end