diff --git a/Source/Core/Common/Src/FileUtil.h b/Source/Core/Common/Src/FileUtil.h index 1147bbdaad..b0391f4b74 100644 --- a/Source/Core/Common/Src/FileUtil.h +++ b/Source/Core/Common/Src/FileUtil.h @@ -143,7 +143,7 @@ bool ReadFileToString(bool text_file, const char *filename, std::string &str); // simple wrapper for cstdlib file functions to // hopefully will make error checking easier // and make forgetting an fclose() harder -class IOFile +class IOFile : public NonCopyable { public: IOFile(); @@ -209,10 +209,6 @@ public: // clear error state void Clear() { m_good = true; std::clearerr(m_file); } -private: - IOFile(const IOFile&) /*= delete*/; - IOFile& operator=(const IOFile&) /*= delete*/; - std::FILE* m_file; bool m_good; }; diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp index aa1df13536..3bbd4296e8 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp @@ -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) , m_pContentLoader(NULL) , 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; } -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); @@ -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); +} + +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); if (m_Active) @@ -135,7 +186,7 @@ bool CWII_IPC_HLE_Device_es::Close(u32 _CommandAddress, bool _bForce) m_pContentLoader = NULL; m_TitleIDs.clear(); m_TitleID = -1; - AccessIdentID = 0x6000000; + m_AccessIdentID = 0x6000000; INFO_LOG(WII_IPC_ES, "ES: Close"); if (!_bForce) @@ -144,6 +195,37 @@ bool CWII_IPC_HLE_Device_es::Close(u32 _CommandAddress, bool _bForce) 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) { 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); u32 Index = Memory::Read_U32(Buffer.InBuffer[2].m_Address); - u32 CFD = AccessIdentID++; - 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? + u32 CFD = OpenTitleContent(m_AccessIdentID++, TitleID, Index); 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); + return true; } 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.NumberPayloadBuffer == 0); - - u32 CFD = AccessIdentID++; u32 Index = Memory::Read_U32(Buffer.InBuffer[0].m_Address); - m_ContentAccessMap[CFD].m_Position = 0; - 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? - + u32 CFD = OpenTitleContent(m_AccessIdentID++, m_TitleID, Index); Memory::Write_U32(CFD, _CommandAddress + 0x4); - INFO_LOG(WII_IPC_ES, "IOCTL_ES_OPENCONTENT: Index %i -> got CFD %x", Index, CFD); + return true; } break; @@ -286,12 +356,16 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress) u32 Size = Buffer.PayloadBuffer[0].m_Size; u32 Addr = Buffer.PayloadBuffer[0].m_Address; - _dbg_assert_(WII_IPC_ES, m_ContentAccessMap.find(CFD) != m_ContentAccessMap.end()); - SContentAccess& rContent = m_ContentAccessMap[CFD]; + auto itr = m_ContentAccessMap.find(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); - u8* pSrc = &rContent.m_pContent->m_pData[rContent.m_Position]; u8* pDest = Memory::GetPointer(Addr); 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 (pDest) { - memcpy(pDest, pSrc, Size); + if (rContent.m_pContent->m_pData) + { + u8* pSrc = &rContent.m_pContent->m_pData[rContent.m_Position]; + 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; } else { 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); - CContentAccessMap::iterator itr = m_ContentAccessMap.find(CFD); - m_ContentAccessMap.erase(itr); + m_ContentAccessMap.erase(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 Mode = Memory::Read_U32(Buffer.InBuffer[2].m_Address); - _dbg_assert_(WII_IPC_ES, m_ContentAccessMap.find(CFD) != m_ContentAccessMap.end()); - SContentAccess& rContent = m_ContentAccessMap[CFD]; + auto itr = m_ContentAccessMap.find(CFD); + if (itr == m_ContentAccessMap.end()) + { + Memory::Write_U32(-1, _CommandAddress + 0x4); + return true; + } + SContentAccess& rContent = itr->second; 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) { if (m_pContentLoader->IsValid() && m_pContentLoader->GetTitleID() == _TitleID) - return* m_pContentLoader; + return *m_pContentLoader; CTitleToContentMap::iterator itr = m_NANDContent.find(_TitleID); if (itr != m_NANDContent.end()) diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.h b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.h index a407ea4742..f77cea969c 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.h +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.h @@ -19,6 +19,10 @@ public: void LoadWAD(const std::string& _rContentFile); + void OpenInternal(); + + virtual void DoState(PointerWrap& p); + virtual bool Open(u32 _CommandAddress, u32 _Mode); virtual bool Close(u32 _CommandAddress, bool _bForce); @@ -108,10 +112,12 @@ private: ES_HASH_SIZE_WRONG = -2014, // HASH !=20 }; - struct SContentAccess + struct SContentAccess : public NonCopyable { u32 m_Position; + u64 m_TitleID; const DiscIO::SNANDContent* m_pContent; + File::IOFile m_File; }; typedef std::map CContentAccessMap; @@ -124,13 +130,14 @@ private: std::vector m_TitleIDs; u64 m_TitleID; - u32 AccessIdentID; + u32 m_AccessIdentID; static u8 *keyTable[11]; u64 GetCurrentTitleID() const; const DiscIO::INANDContentLoader& AccessContentDevice(u64 _TitleID); + u32 OpenTitleContent(u32 CFD, u64 TitleID, u16 Index); bool IsValid(u64 _TitleID) const; diff --git a/Source/Core/DiscIO/Src/NANDContentLoader.cpp b/Source/Core/DiscIO/Src/NANDContentLoader.cpp index 0cc71bafb8..b0dcd302f7 100644 --- a/Source/Core/DiscIO/Src/NANDContentLoader.cpp +++ b/Source/Core/DiscIO/Src/NANDContentLoader.cpp @@ -5,7 +5,7 @@ #include "NANDContentLoader.h" #include -#include +#include #include "Crypto/aes.h" #include "MathUtil.h" #include "FileUtil.h" @@ -42,7 +42,7 @@ void CSharedContent::UpdateLocation() CSharedContent::~CSharedContent() {} -std::string CSharedContent::GetFilenameFromSHA1(u8* _pHash) +std::string CSharedContent::GetFilenameFromSHA1(const u8* _pHash) { for (size_t i=0; im_Index == _Index) + { + return pContent; + } } return NULL; } @@ -262,36 +265,18 @@ bool CNANDContentLoader::Initialize(const std::string& _rName) } rContent.m_pData = NULL; - char szFilename[1024]; if (rContent.m_Type & 0x8000) // shared app { - std::string Filename = CSharedContent::AccessInstance().GetFilenameFromSHA1(rContent.m_SHA1Hash); - strcpy(szFilename, Filename.c_str()); + rContent.m_Filename = CSharedContent::AccessInstance().GetFilenameFromSHA1(rContent.m_SHA1Hash); } 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); - - 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; - } + // Be graceful about incorrect tmds. + rContent.m_Size = (u32) File::GetSize(rContent.m_Filename); } delete [] pTMD; @@ -493,7 +478,7 @@ u64 CNANDContentManager::Install_WiiWAD(std::string &fileName) 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); diff --git a/Source/Core/DiscIO/Src/NANDContentLoader.h b/Source/Core/DiscIO/Src/NANDContentLoader.h index 66d6a4880c..9172c85338 100644 --- a/Source/Core/DiscIO/Src/NANDContentLoader.h +++ b/Source/Core/DiscIO/Src/NANDContentLoader.h @@ -13,6 +13,7 @@ #include "Blob.h" #include "Volume.h" #include "NandPaths.h" +#include "FileUtil.h" namespace DiscIO { @@ -26,6 +27,7 @@ struct SNANDContent u8 m_SHA1Hash[20]; u8 m_Header[36]; //all of the above + std::string m_Filename; u8* m_pData; }; @@ -95,8 +97,8 @@ public: static CSharedContent& AccessInstance() { return m_Instance; } - std::string GetFilenameFromSHA1(u8* _pHash); - std::string AddSharedContent(u8* _pHash); + std::string GetFilenameFromSHA1(const u8* _pHash); + std::string AddSharedContent(const u8* _pHash); void UpdateLocation(); private: