From 232217c1cd98d015f970180eeb48e8214e4e4d6b Mon Sep 17 00:00:00 2001 From: itsnotmailmail Date: Wed, 17 Jun 2009 02:50:54 +0000 Subject: [PATCH] Added the ability to install WADs (such as DLC WADs). Currently it just installs a WAD when booting it fails (when it's not bootable), I'm not sure whether there should be a menu option specially for installing WADS... note: If you previously manually installed WADS by creating a *file* called "CONTENT", trying to reinstall that WAD automatically will fail unless you delete the file. Added some empty log files that some games require for DLC to be recognized. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@3474 8ced0084-cf51-0410-be5f-012b33b47a6e --- Data/User/Wii/shared2/ec/shopsetu.log | Bin 0 -> 32 bytes Data/User/Wii/shared2/succession/shop.log | Bin 0 -> 32 bytes Source/Core/Core/Src/Boot/Boot.h | 2 + Source/Core/Core/Src/Boot/Boot_WiiWAD.cpp | 82 ++++++++- Source/Core/Core/Src/CoreParameter.cpp | 10 ++ .../Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp | 149 ++++++++--------- Source/Core/DiscIO/DiscIO.vcproj | 8 + Source/Core/DiscIO/Src/NANDContentLoader.cpp | 116 +------------ Source/Core/DiscIO/Src/NANDContentLoader.h | 9 +- Source/Core/DiscIO/Src/WiiWad.cpp | 156 ++++++++++++++++++ Source/Core/DiscIO/Src/WiiWad.h | 78 +++++++++ Source/Core/DolphinWX/Src/BootManager.cpp | 2 +- 12 files changed, 421 insertions(+), 191 deletions(-) create mode 100644 Data/User/Wii/shared2/ec/shopsetu.log create mode 100644 Data/User/Wii/shared2/succession/shop.log create mode 100644 Source/Core/DiscIO/Src/WiiWad.cpp create mode 100644 Source/Core/DiscIO/Src/WiiWad.h diff --git a/Data/User/Wii/shared2/ec/shopsetu.log b/Data/User/Wii/shared2/ec/shopsetu.log new file mode 100644 index 0000000000000000000000000000000000000000..4e4e4935707a596987ec1cc32e3d0d587dbe4f04 GIT binary patch literal 32 KcmZQzzz+ZbAOHaX literal 0 HcmV?d00001 diff --git a/Data/User/Wii/shared2/succession/shop.log b/Data/User/Wii/shared2/succession/shop.log new file mode 100644 index 0000000000000000000000000000000000000000..4e4e4935707a596987ec1cc32e3d0d587dbe4f04 GIT binary patch literal 32 KcmZQzzz+ZbAOHaX literal 0 HcmV?d00001 diff --git a/Source/Core/Core/Src/Boot/Boot.h b/Source/Core/Core/Src/Boot/Boot.h index fb97fb5f7a..ce75fe1b49 100644 --- a/Source/Core/Core/Src/Boot/Boot.h +++ b/Source/Core/Core/Src/Boot/Boot.h @@ -32,6 +32,8 @@ public: static bool IsWiiWAD(const char *filename); static std::string GenerateMapFilename(); + + static bool Install_WiiWAD(const char *filename); private: enum { BIOS_SIZE = 2*1024*1024 }; diff --git a/Source/Core/Core/Src/Boot/Boot_WiiWAD.cpp b/Source/Core/Core/Src/Boot/Boot_WiiWAD.cpp index 1e31fdfc57..ab53e00aa4 100644 --- a/Source/Core/Core/Src/Boot/Boot_WiiWAD.cpp +++ b/Source/Core/Core/Src/Boot/Boot_WiiWAD.cpp @@ -23,6 +23,7 @@ #include "../PatchEngine.h" #include "../IPC_HLE/WII_IPC_HLE.h" +#include "WiiWAD.h" #include "NANDContentLoader.h" #include "FileUtil.h" #include "Boot_DOL.h" @@ -32,7 +33,7 @@ bool CBoot::IsWiiWAD(const char *filename) { - return DiscIO::CNANDContentManager::IsWiiWAD(filename); + return DiscIO::WiiWAD::IsWiiWAD(filename); } bool CBoot::Boot_WiiWAD(const char* _pFilename) @@ -57,7 +58,7 @@ bool CBoot::Boot_WiiWAD(const char* _pFilename) // DOL const DiscIO::SNANDContent* pContent = ContentLoader.GetContentByIndex(ContentLoader.GetBootIndex()); if (pContent == NULL) - return false; + return false; WII_IPC_HLE_Interface::SetDefaultContentFile(_pFilename); @@ -83,3 +84,80 @@ bool CBoot::Boot_WiiWAD(const char* _pFilename) } +bool CBoot::Install_WiiWAD(const char* _pFilename) +{ + if (!IsWiiWAD(_pFilename)) + return false; + const DiscIO::INANDContentLoader& ContentLoader = DiscIO::CNANDContentManager::Access().GetNANDLoader(_pFilename); + if (ContentLoader.IsValid() == false) + return false; + + u64 TitleID = ContentLoader.GetTitleID(); + u32 TitleID_HI = (u32)(TitleID >> 32); + u32 TitleID_LO = (u32)(TitleID); + + //copy WAD's tmd header and contents to content directory + + char ContentPath[260+1]; + sprintf(ContentPath, FULL_WII_USER_DIR "title/%08x/%08x/content/", TitleID_HI, TitleID_LO); + File::CreateFullPath(ContentPath); + + std::string TMDFileName(ContentPath); + TMDFileName += "title.tmd"; + + FILE* pTMDFile = fopen(TMDFileName.c_str(), "wb"); + if (pTMDFile == NULL) { + PanicAlert("WAD installation failed: error creating %s", TMDFileName.c_str()); + return false; + } + + fwrite(ContentLoader.GetTmdHeader(), DiscIO::INANDContentLoader::TMD_HEADER_SIZE, 1, pTMDFile); + + for (u32 i = 0; i < ContentLoader.GetContentSize(); i++) + { + DiscIO::SNANDContent Content = ContentLoader.GetContent()[i]; + + fwrite(Content.m_Header, DiscIO::INANDContentLoader::CONTENT_HEADER_SIZE, 1, pTMDFile); + + char APPFileName[1024]; + sprintf(APPFileName, "%s%08x.app", ContentPath, Content.m_ContentID); + + FILE* pAPPFile = fopen(APPFileName, "wb"); + if (pAPPFile == NULL) { + PanicAlert("WAD installation failed: error creating %s", APPFileName); + return false; + } + + fwrite(Content.m_pData, Content.m_Size, 1, pAPPFile); + fclose(pAPPFile); + } + + fclose(pTMDFile); + + //Extract and copy WAD's ticket to ticket directory + + char TicketPath[260+1]; + sprintf(TicketPath, FULL_WII_USER_DIR "ticket/%08x/", TitleID_HI); + File::CreateFullPath(TicketPath); + + char TicketFileName[260+1]; + sprintf(TicketFileName, FULL_WII_USER_DIR "ticket/%08x/%08x.tik", TitleID_HI, TitleID_LO); + + FILE* pTicketFile = fopen(TicketFileName, "wb"); + if (pTicketFile == NULL) { + PanicAlert("WAD installation failed: error creating %s", TicketFileName); + return false; + } + + DiscIO::WiiWAD Wad(_pFilename); + if (!Wad.IsValid()) + return false; + + fwrite(Wad.GetTicket(), Wad.GetTicketSize(), 1, pTicketFile); + + fclose(pTicketFile); + + return true; +} + + diff --git a/Source/Core/Core/Src/CoreParameter.cpp b/Source/Core/Core/Src/CoreParameter.cpp index f6c4462180..d04d17b9dc 100644 --- a/Source/Core/Core/Src/CoreParameter.cpp +++ b/Source/Core/Core/Src/CoreParameter.cpp @@ -151,6 +151,16 @@ bool SCoreStartupParameter::AutoSetup(EBootBios _BootBios) { const DiscIO::IVolume* pVolume = DiscIO::CreateVolumeFromFilename(m_strFilename.c_str()); const DiscIO::INANDContentLoader& ContentLoader = DiscIO::CNANDContentManager::Access().GetNANDLoader(m_strFilename); + + if (ContentLoader.GetContentByIndex(ContentLoader.GetBootIndex()) == NULL) + { + //WAD is valid yet cannot be booted. Install instead. + bool installed = CBoot::Install_WiiWAD(m_strFilename.c_str()); + if (installed) + SuccessAlert("The WAD has been installed successfully"); + return false; //do not boot + } + u64 TitleID = ContentLoader.GetTitleID(); char* pTitleID = (char*)&TitleID; 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 4129aedcf1..790bda898b 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 @@ -200,8 +200,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); - const DiscIO::INANDContentLoader& Loader = DiscIO::CNANDContentManager::Access().GetNANDLoader(TitleFilename); + std::string TitlePath = CreateTitleContentPath(TitleID); + const DiscIO::INANDContentLoader& Loader = DiscIO::CNANDContentManager::Access().GetNANDLoader(TitlePath); ERROR_LOG(WII_IPC_ES, "IOCTL_ES_GETTITLECONTENTS: title: %08x/%08x MaxCount: %i (just content in private directory)", (u32)(TitleID >> 32), (u32)TitleID, MaxCount); @@ -240,7 +240,7 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress) _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; + CFD = 0xffffffff; //TODO: what is the correct error value here? Memory::Write_U32(CFD, _CommandAddress + 0x4); INFO_LOG(WII_IPC_ES, "ES: IOCTL_ES_OPENTITLECONTENT: TitleID: %08x/%08x Index %i -> got CFD %x", (u32)(TitleID>>32), (u32)TitleID, Index, CFD); @@ -517,8 +517,8 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress) _dbg_assert_msg_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 1, "CWII_IPC_HLE_Device_es: IOCTL_ES_GETTMDVIEWCNT no out buffer"); u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address); - std::string TitleFilename = CreateTitleContentPath(TitleID); - const DiscIO::INANDContentLoader& Loader = DiscIO::CNANDContentManager::Access().GetNANDLoader(TitleFilename); + std::string TitlePath = CreateTitleContentPath(TitleID); + const DiscIO::INANDContentLoader& Loader = DiscIO::CNANDContentManager::Access().GetNANDLoader(TitlePath); _dbg_assert_(WII_IPC_ES, Loader.IsValid()); u32 TMDViewCnt = 0; @@ -545,8 +545,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); - const DiscIO::INANDContentLoader& Loader = DiscIO::CNANDContentManager::Access().GetNANDLoader(TitleFilename); + std::string TitlePath = CreateTitleContentPath(TitleID); + const DiscIO::INANDContentLoader& Loader = DiscIO::CNANDContentManager::Access().GetNANDLoader(TitlePath); INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETTMDVIEWCNT: title: %08x/%08x buffersize: %i", (u32)(TitleID >> 32), (u32)TitleID, MaxCount); @@ -557,7 +557,7 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress) { u32 Address = Buffer.PayloadBuffer[0].m_Address; - Memory::WriteBigEData(Loader.GetTicket(), Address, DiscIO::INANDContentLoader::TICKET_VIEW_SIZE); + Memory::WriteBigEData(Loader.GetTicketView(), Address, DiscIO::INANDContentLoader::TICKET_VIEW_SIZE); Address += DiscIO::INANDContentLoader::TICKET_VIEW_SIZE; Memory::Write_U16(Loader.GetTitleVersion(), Address); Address += 2; @@ -581,6 +581,68 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress) } break; + case IOCTL_ES_GETSTOREDTMD: + { + _dbg_assert_msg_(WII_IPC_ES, Buffer.NumberInBuffer == 2, "CWII_IPC_HLE_Device_es: IOCTL_ES_GETSTOREDTMD no in buffer"); + _dbg_assert_msg_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 1, "CWII_IPC_HLE_Device_es: IOCTL_ES_GETSTOREDTMD no out buffer"); + + u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address); + u32 MaxCount = Memory::Read_U32(Buffer.InBuffer[1].m_Address); + std::string TitlePath = CreateTitleContentPath(TitleID); + const DiscIO::INANDContentLoader& Loader = DiscIO::CNANDContentManager::Access().GetNANDLoader(TitlePath); + + + INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETSTOREDTMD: title: %08x/%08x buffersize: %i", (u32)(TitleID >> 32), (u32)TitleID, MaxCount); + + u32 Count = 0; + if (Loader.IsValid()) + { + u32 Address = Buffer.PayloadBuffer[0].m_Address; + + Memory::WriteBigEData(Loader.GetTmdHeader(), Address, DiscIO::INANDContentLoader::TMD_HEADER_SIZE); + Address += DiscIO::INANDContentLoader::TMD_HEADER_SIZE; + + const std::vector& rContent = Loader.GetContent(); + for (size_t i=0; i> 32), (u32)TitleID, MaxCount); + return true; + } + break; + + case IOCTL_ES_GETSTOREDTMDSIZE: + { + _dbg_assert_msg_(WII_IPC_ES, Buffer.NumberInBuffer == 1, "CWII_IPC_HLE_Device_es: IOCTL_ES_GETSTOREDTMDSIZE no in buffer"); + _dbg_assert_msg_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 1, "CWII_IPC_HLE_Device_es: IOCTL_ES_ES_GETSTOREDTMDSIZE no out buffer"); + + u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address); + std::string TitlePath = CreateTitleContentPath(TitleID); + const DiscIO::INANDContentLoader& Loader = DiscIO::CNANDContentManager::Access().GetNANDLoader(TitlePath); + + _dbg_assert_(WII_IPC_ES, Loader.IsValid()); + u32 TMDCnt = 0; + if (Loader.IsValid()) + { + TMDCnt += DiscIO::INANDContentLoader::TMD_HEADER_SIZE; + TMDCnt += (u32)Loader.GetContentSize() * DiscIO::INANDContentLoader::CONTENT_HEADER_SIZE; + } + Memory::Write_U32(TMDCnt, Buffer.PayloadBuffer[0].m_Address); + + Memory::Write_U32(0, _CommandAddress + 0x4); + + INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETSTOREDTMDSIZE: title: %08x/%08x (view size %i)", (u32)(TitleID >> 32), (u32)TitleID, TMDCnt); + return true; + } + break; + case IOCTL_ES_ENCRYPT: { u32 keyIndex = Memory::Read_U32(Buffer.InBuffer[0].m_Address); @@ -644,71 +706,6 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress) } break; - case IOCTL_ES_GETSTOREDTMD: - { - _dbg_assert_msg_(WII_IPC_ES, Buffer.NumberInBuffer == 2, "CWII_IPC_HLE_Device_es: IOCTL_ES_GETSTOREDTMD no in buffer"); - _dbg_assert_msg_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 1, "CWII_IPC_HLE_Device_es: IOCTL_ES_GETSTOREDTMD no out buffer"); - - 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); - const DiscIO::INANDContentLoader& Loader = DiscIO::CNANDContentManager::Access().GetNANDLoader(TitleFilename); - - - INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETSTOREDTMD: title: %08x/%08x buffersize: %i", (u32)(TitleID >> 32), (u32)TitleID, MaxCount); - - u32 Count = 0; - if (Loader.IsValid()) - { - u32 Address = Buffer.PayloadBuffer[0].m_Address; - - Memory::WriteBigEData(Loader.GetTmdHeader(), Address, DiscIO::INANDContentLoader::TMD_HEADER_SIZE); - Address += DiscIO::INANDContentLoader::TMD_HEADER_SIZE; - - const std::vector& rContent = Loader.GetContent(); - for (size_t i=0; i> 32), (u32)TitleID, MaxCount); - return true; - } - break; - - case IOCTL_ES_GETSTOREDTMDSIZE: - { - _dbg_assert_msg_(WII_IPC_ES, Buffer.NumberInBuffer == 1, "CWII_IPC_HLE_Device_es: IOCTL_ES_GETSTOREDTMDSIZE no in buffer"); - _dbg_assert_msg_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 1, "CWII_IPC_HLE_Device_es: IOCTL_ES_ES_GETSTOREDTMDSIZE no out buffer"); - - u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address); - std::string TitleFilename = CreateTitleContentPath(TitleID); - const DiscIO::INANDContentLoader& Loader = DiscIO::CNANDContentManager::Access().GetNANDLoader(TitleFilename); - - _dbg_assert_(WII_IPC_ES, Loader.IsValid()); - u32 TMDCnt = 0; - if (Loader.IsValid()) - { - TMDCnt += DiscIO::INANDContentLoader::TMD_HEADER_SIZE; - TMDCnt += (u32)Loader.GetContentSize() * (4 + 2 + 2 + 8 + 20); //id, index, type, size, hash - } - Memory::Write_U32(TMDCnt, Buffer.PayloadBuffer[0].m_Address); - - Memory::Write_U32(0, _CommandAddress + 0x4); - - INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETSTOREDTMDSIZE: title: %08x/%08x (view size %i)", (u32)(TitleID >> 32), (u32)TitleID, TMDCnt); - return true; - } - break; - case IOCTL_ES_GETCONSUMPTION: // (Input: 8 bytes, Output: 0 bytes, 4 bytes) _dbg_assert_msg_(WII_IPC_ES, 0, "IOCTL_ES_GETCONSUMPTION: this looks really wrong..."); break; @@ -717,7 +714,7 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress) _dbg_assert_msg_(WII_IPC_ES, 0, "IOCTL_ES_DIGETTICKETVIEW: this looks really wrong..."); break; - case IOCTL_ES_GETDEVICECERT: // + case IOCTL_ES_GETDEVICECERT: // (Input: none, Output: 384 bytes) _dbg_assert_msg_(WII_IPC_ES, 0, "IOCTL_ES_GETDEVICECERT: this looks really wrong..."); break; @@ -744,8 +741,8 @@ const DiscIO::INANDContentLoader& CWII_IPC_HLE_Device_es::AccessContentDevice(u6 if (itr != m_NANDContent.end()) return *itr->second; - std::string TitleFilename = CreateTitleContentPath(_TitleID); - m_NANDContent[_TitleID] = &DiscIO::CNANDContentManager::Access().GetNANDLoader(TitleFilename); + std::string TitlePath = CreateTitleContentPath(_TitleID); + m_NANDContent[_TitleID] = &DiscIO::CNANDContentManager::Access().GetNANDLoader(TitlePath); _dbg_assert_(WII_IPC_ES, m_NANDContent[_TitleID]->IsValid()); return *m_NANDContent[_TitleID]; diff --git a/Source/Core/DiscIO/DiscIO.vcproj b/Source/Core/DiscIO/DiscIO.vcproj index 503f26b77d..049bb90a08 100644 --- a/Source/Core/DiscIO/DiscIO.vcproj +++ b/Source/Core/DiscIO/DiscIO.vcproj @@ -1160,6 +1160,14 @@ RelativePath=".\Src\NANDContentLoader.h" > + + + + & GetContent() const { return m_Content; } @@ -153,12 +137,8 @@ private: 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); @@ -208,13 +188,11 @@ const SNANDContent* CNANDContentLoader::GetContentByIndex(int _Index) const bool CNANDContentLoader::CreateFromWAD(const std::string& _rName) { - DiscIO::IBlobReader* pReader = DiscIO::CreateBlobReader(_rName.c_str()); - if (pReader == NULL) + WiiWAD Wad(_rName); + if (!Wad.IsValid()) return false; - bool Result = ParseWAD(*pReader); - delete pReader; - return Result; + return ParseTMD(Wad.GetDataApp(), Wad.GetDataAppSize(), Wad.GetTicket(), Wad.GetTMD()); } bool CNANDContentLoader::CreateFromDirectory(const std::string& _rPath) @@ -254,6 +232,7 @@ bool CNANDContentLoader::CreateFromDirectory(const std::string& _rPath) 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); rContent.m_pData = NULL; char szFilename[1024]; @@ -298,23 +277,6 @@ void CNANDContentLoader::AESDecode(u8* _pKey, u8* _IV, u8* _pSrc, u32 _Size, u8* AES_cbc_encrypt(_pSrc, _pDest, _Size, &AESKey, _IV, AES_DECRYPT); } -u8* CNANDContentLoader::CreateWADEntry(DiscIO::IBlobReader& _rReader, u32 _Size, u64 _Offset) -{ - if (_Size > 0) - { - u8* pTmpBuffer = new u8[_Size]; - _dbg_assert_msg_(BOOT, pTmpBuffer!=0, "WiiWAD: Cant allocate memory for WAD entry"); - - if (!_rReader.Read(_Offset, _Size, pTmpBuffer)) - { - ERROR_LOG(DISCIO, "WiiWAD: Could not read from file"); - PanicAlert("WiiWAD: Could not read from file"); - } - return pTmpBuffer; - } - return NULL; -} - void CNANDContentLoader::GetKeyFromTicket(u8* pTicket, u8* pTicketKey) { u8 CommonKey[16] = {0xeb,0xe4,0x2a,0x22,0x5e,0x85,0x93,0xe4,0x48,0xd9,0xc5,0x45,0x73,0x81,0xaa,0xf7}; @@ -352,6 +314,8 @@ bool CNANDContentLoader::ParseTMD(u8* pDataApp, u32 pDataAppSize, u8* pTicket, u 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); u32 RoundedSize = ROUND_UP(rContent.m_Size, 0x40); rContent.m_pData = new u8[RoundedSize]; @@ -426,44 +390,6 @@ const DiscIO::IVolume::ECountry CNANDContentLoader::GetCountry() const return(country); } -bool CNANDContentLoader::ParseWAD(DiscIO::IBlobReader& _rReader) -{ - CBlobBigEndianReader ReaderBig(_rReader); - - // get header size - u32 HeaderSize = ReaderBig.Read32(0); - if (HeaderSize != 0x20) - { - _dbg_assert_msg_(BOOT, (HeaderSize==0x20), "WiiWAD: Header size != 0x20"); - return false; - } - - // get header - u8 Header[0x20]; - _rReader.Read(0, HeaderSize, Header); - u32 HeaderType = ReaderBig.Read32(0x4); - if ((0x49730000 != HeaderType) && (0x69620000 != HeaderType)) - return false; - - u32 CertificateChainSize = ReaderBig.Read32(0x8); - u32 Reserved = ReaderBig.Read32(0xC); - u32 TicketSize = ReaderBig.Read32(0x10); - u32 TMDSize = ReaderBig.Read32(0x14); - u32 DataAppSize = ReaderBig.Read32(0x18); - u32 FooterSize = ReaderBig.Read32(0x1C); - _dbg_assert_msg_(BOOT, Reserved==0x00, "WiiWAD: Reserved must be 0x00"); - - u32 Offset = 0x40; - u8* pCertificateChain = CreateWADEntry(_rReader, CertificateChainSize, Offset); Offset += ROUND_UP(CertificateChainSize, 0x40); - u8* pTicket = CreateWADEntry(_rReader, TicketSize, Offset); Offset += ROUND_UP(TicketSize, 0x40); - u8* pTMD = CreateWADEntry(_rReader, TMDSize, Offset); Offset += ROUND_UP(TMDSize, 0x40); - u8* pDataApp = CreateWADEntry(_rReader, DataAppSize, Offset); Offset += ROUND_UP(DataAppSize, 0x40); - u8* pFooter = CreateWADEntry(_rReader, FooterSize, Offset); Offset += ROUND_UP(FooterSize, 0x40); - - bool Result = ParseTMD(pDataApp, DataAppSize, pTicket, pTMD); - - return Result; -} /////////////////// @@ -499,32 +425,6 @@ const INANDContentLoader& CNANDContentManager::GetNANDLoader(const std::string& } -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; -} - diff --git a/Source/Core/DiscIO/Src/NANDContentLoader.h b/Source/Core/DiscIO/Src/NANDContentLoader.h index c324bdbc7c..0494eba5c7 100644 --- a/Source/Core/DiscIO/Src/NANDContentLoader.h +++ b/Source/Core/DiscIO/Src/NANDContentLoader.h @@ -36,6 +36,8 @@ struct SNANDContent u16 m_Type; u32 m_Size; u8 m_SHA1Hash[20]; + u8 m_Header[36]; //all of the above + u8* m_pData; }; @@ -54,7 +56,7 @@ public: virtual u32 GetBootIndex() const = 0; virtual size_t GetContentSize() const = 0; virtual const SNANDContent* GetContentByIndex(int _Index) const = 0; - virtual const u8* GetTicket() const = 0; + virtual const u8* GetTicketView() const = 0; virtual const u8* GetTmdHeader() const = 0; virtual const std::vector& GetContent() const = 0; virtual const u16 GetTitleVersion() const = 0; @@ -64,7 +66,8 @@ public: enum { TICKET_VIEW_SIZE = 0x58, - TMD_HEADER_SIZE = 0x1e4 + TMD_HEADER_SIZE = 0x1e4, + CONTENT_HEADER_SIZE = 0x24 }; }; @@ -78,8 +81,6 @@ public: const INANDContentLoader& GetNANDLoader(const std::string& _rName); - static bool IsWiiWAD(const std::string& _rName); - private: CNANDContentManager() {}; diff --git a/Source/Core/DiscIO/Src/WiiWad.cpp b/Source/Core/DiscIO/Src/WiiWad.cpp new file mode 100644 index 0000000000..73f22f31b5 --- /dev/null +++ b/Source/Core/DiscIO/Src/WiiWad.cpp @@ -0,0 +1,156 @@ +// Copyright (C) 2003-2009 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 "stdafx.h" +#include "NANDContentLoader.h" + +#include +#include +#include "MathUtil.h" +#include "FileUtil.h" +#include "Log.h" +#include "WiiWad.h" + +namespace DiscIO +{ + +class CBlobBigEndianReader +{ +public: + CBlobBigEndianReader(DiscIO::IBlobReader& _rReader) : m_rReader(_rReader) {} + + u32 Read32(u64 _Offset) + { + u32 Temp; + m_rReader.Read(_Offset, 4, (u8*)&Temp); + return(Common::swap32(Temp)); + } + +private: + DiscIO::IBlobReader& m_rReader; +}; + +WiiWAD::WiiWAD(const std::string& _rName) +{ + DiscIO::IBlobReader* pReader = DiscIO::CreateBlobReader(_rName.c_str()); + if (pReader == NULL) + { + m_Valid = false; + return; + } + + m_Valid = ParseWAD(*pReader); + delete pReader; +} + +WiiWAD::~WiiWAD() +{ + if (m_Valid) + { + delete m_pCertificateChain; + delete m_pTicket; + delete m_pTMD; + delete m_pDataApp; + delete m_pFooter; + } +} + +u8* WiiWAD::CreateWADEntry(DiscIO::IBlobReader& _rReader, u32 _Size, u64 _Offset) +{ + if (_Size > 0) + { + u8* pTmpBuffer = new u8[_Size]; + _dbg_assert_msg_(BOOT, pTmpBuffer!=0, "WiiWAD: Cant allocate memory for WAD entry"); + + if (!_rReader.Read(_Offset, _Size, pTmpBuffer)) + { + ERROR_LOG(DISCIO, "WiiWAD: Could not read from file"); + PanicAlert("WiiWAD: Could not read from file"); + } + return pTmpBuffer; + } + return NULL; +} + + +bool WiiWAD::ParseWAD(DiscIO::IBlobReader& _rReader) +{ + CBlobBigEndianReader ReaderBig(_rReader); + + // get header size + u32 HeaderSize = ReaderBig.Read32(0); + if (HeaderSize != 0x20) + { + _dbg_assert_msg_(BOOT, (HeaderSize==0x20), "WiiWAD: Header size != 0x20"); + return false; + } + + // get header + u8 Header[0x20]; + _rReader.Read(0, HeaderSize, Header); + u32 HeaderType = ReaderBig.Read32(0x4); + if ((0x49730000 != HeaderType) && (0x69620000 != HeaderType)) + return false; + + m_CertificateChainSize = ReaderBig.Read32(0x8); + u32 Reserved = ReaderBig.Read32(0xC); + m_TicketSize = ReaderBig.Read32(0x10); + m_TMDSize = ReaderBig.Read32(0x14); + m_DataAppSize = ReaderBig.Read32(0x18); + m_FooterSize = ReaderBig.Read32(0x1C); + _dbg_assert_msg_(BOOT, Reserved==0x00, "WiiWAD: Reserved must be 0x00"); + + u32 Offset = 0x40; + m_pCertificateChain = CreateWADEntry(_rReader, m_CertificateChainSize, Offset); Offset += ROUND_UP(m_CertificateChainSize, 0x40); + m_pTicket = CreateWADEntry(_rReader, m_TicketSize, Offset); Offset += ROUND_UP(m_TicketSize, 0x40); + m_pTMD = CreateWADEntry(_rReader, m_TMDSize, Offset); Offset += ROUND_UP(m_TMDSize, 0x40); + m_pDataApp = CreateWADEntry(_rReader, m_DataAppSize, Offset); Offset += ROUND_UP(m_DataAppSize, 0x40); + m_pFooter = CreateWADEntry(_rReader, m_FooterSize, Offset); Offset += ROUND_UP(m_FooterSize, 0x40); + + return true; +} + +bool WiiWAD::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 + diff --git a/Source/Core/DiscIO/Src/WiiWad.h b/Source/Core/DiscIO/Src/WiiWad.h new file mode 100644 index 0000000000..10b2ad867e --- /dev/null +++ b/Source/Core/DiscIO/Src/WiiWad.h @@ -0,0 +1,78 @@ +// Copyright (C) 2003-2009 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/ + +#ifndef _WII_WAD_H +#define _WII_WAD_H + +#include +#include +#include + +#include "Common.h" +#include "Blob.h" +#include "Volume.h" + +namespace DiscIO +{ + +class WiiWAD +{ +public: + + WiiWAD(const std::string& _rName); + + ~WiiWAD(); + + bool IsValid() const { return m_Valid; } + u32 GetCertificateChainSize() const { return m_CertificateChainSize; } + u32 GetTicketSize() const { return m_TicketSize; } + u32 GetTMDSize() const { return m_TMDSize; } + u32 GetDataAppSize() const { return m_DataAppSize; } + u32 GetFooterSize() const { return m_FooterSize; } + + u8* GetCertificateChain() const { return m_pCertificateChain; } + u8* GetTicket() const { return m_pTicket; } + u8* GetTMD() const { return m_pTMD; } + u8* GetDataApp() const { return m_pDataApp; } + u8* GetFooter() const { return m_pFooter; } + + static bool IsWiiWAD(const std::string& _rName); + +private: + + bool m_Valid; + + u32 m_CertificateChainSize; + u32 m_TicketSize; + u32 m_TMDSize; + u32 m_DataAppSize; + u32 m_FooterSize; + + u8* m_pCertificateChain; + u8* m_pTicket; + u8* m_pTMD; + u8* m_pDataApp; + u8* m_pFooter; + + u8* CreateWADEntry(DiscIO::IBlobReader& _rReader, u32 _Size, u64 _Offset); + bool ParseWAD(DiscIO::IBlobReader& _rReader); +}; + +} + +#endif + diff --git a/Source/Core/DolphinWX/Src/BootManager.cpp b/Source/Core/DolphinWX/Src/BootManager.cpp index 2cf50f2830..258001f6b3 100644 --- a/Source/Core/DolphinWX/Src/BootManager.cpp +++ b/Source/Core/DolphinWX/Src/BootManager.cpp @@ -23,7 +23,7 @@ // ------------- /* Purpose of this file: Collect boot settings for Core::Init() - Call sequenc: This file has one of the first function called when a game is booted, + Call sequence: This file has one of the first function called when a game is booted, the boot sequence in the code is: DolphinWX: GameListCtrl.cpp OnActivated