From 1236e584e0914b307016ac42143cf602e2e4cb23 Mon Sep 17 00:00:00 2001 From: LPFaint99 Date: Mon, 9 May 2011 05:47:29 +0000 Subject: [PATCH] NAND:Consolidate Wad/Directory loading in CNANDContentLoader to one function add ticket to CNANDContentLoader move wad installer to CNANDContentManager system menu can now be launched from a wad file without being installed first, (return to system menu from another title will still only work if system menu is installed) cdb.vff: flushed to disc immediately, creates if the file exists but is too small, moved creation to Boot_WiiWad git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@7530 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/Common/Src/NandPaths.cpp | 22 +- Source/Core/Common/Src/NandPaths.h | 7 +- Source/Core/Core/Core.vcxproj | 1 - Source/Core/Core/Core.vcxproj.filters | 3 - Source/Core/Core/Src/Boot/Boot.h | 4 - Source/Core/Core/Src/Boot/Boot_BS2Emu.cpp | 2 +- Source/Core/Core/Src/Boot/Boot_ELF.cpp | 1 - Source/Core/Core/Src/Boot/Boot_WiiWAD.cpp | 116 +------ Source/Core/Core/Src/CoreParameter.cpp | 2 +- .../Core/Core/Src/FifoPlayer/FifoDataFile.h | 2 +- .../Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp | 10 +- .../Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp | 124 +++++--- Source/Core/DiscIO/Src/NANDContentLoader.cpp | 299 +++++++++++------- Source/Core/DiscIO/Src/NANDContentLoader.h | 14 +- Source/Core/DolphinWX/Src/FrameTools.cpp | 7 +- 15 files changed, 306 insertions(+), 308 deletions(-) diff --git a/Source/Core/Common/Src/NandPaths.cpp b/Source/Core/Common/Src/NandPaths.cpp index 209bb25500..cec79414a7 100644 --- a/Source/Core/Common/Src/NandPaths.cpp +++ b/Source/Core/Common/Src/NandPaths.cpp @@ -23,7 +23,7 @@ namespace Common { -std::string CreateTicketFileName(u64 _titleID) +std::string GetTicketFileName(u64 _titleID) { char TicketFilename[1024]; sprintf(TicketFilename, "%sticket/%08x/%08x.tik", @@ -32,19 +32,23 @@ std::string CreateTicketFileName(u64 _titleID) return TicketFilename; } -std::string CreateTitleDataPath(u64 _titleID) +std::string GetTitleDataPath(u64 _titleID) { char path[1024]; - sprintf(path, "%stitle/%08x/%08x/data", + sprintf(path, "%stitle/%08x/%08x/data/", File::GetUserPath(D_WIIUSER_IDX).c_str(), (u32)(_titleID >> 32), (u32)_titleID); return path; } -std::string CreateTitleContentPath(u64 _titleID) +std::string GetTMDFileName(u64 _titleID) +{ + return GetTitleContentPath(_titleID) + "title.tmd"; +} +std::string GetTitleContentPath(u64 _titleID) { char ContentPath[1024]; - sprintf(ContentPath, "%stitle/%08x/%08x/content", + sprintf(ContentPath, "%stitle/%08x/%08x/content/", File::GetUserPath(D_WIIUSER_IDX).c_str(), (u32)(_titleID >> 32), (u32)_titleID); return ContentPath; @@ -52,7 +56,7 @@ std::string CreateTitleContentPath(u64 _titleID) bool CheckTitleTMD(u64 _titleID) { - const std::string TitlePath = CreateTitleContentPath(_titleID) + "/title.tmd"; + const std::string TitlePath = GetTMDFileName(_titleID); if (File::Exists(TitlePath)) { File::IOFile pTMDFile(TitlePath, "rb"); @@ -67,10 +71,10 @@ bool CheckTitleTMD(u64 _titleID) bool CheckTitleTIK(u64 _titleID) { - const std::string TikPath = Common::CreateTicketFileName(_titleID); - if (File::Exists(TikPath)) + const std::string ticketFileName = Common::GetTicketFileName(_titleID); + if (File::Exists(ticketFileName)) { - File::IOFile pTIKFile(TikPath, "rb"); + File::IOFile pTIKFile(ticketFileName, "rb"); u64 TitleID = 0; pTIKFile.Seek(0x1dC, SEEK_SET); if (pTIKFile.ReadArray(&TitleID, 1) && _titleID == Common::swap64(TitleID)) diff --git a/Source/Core/Common/Src/NandPaths.h b/Source/Core/Common/Src/NandPaths.h index b08e661e94..b45686976c 100644 --- a/Source/Core/Common/Src/NandPaths.h +++ b/Source/Core/Common/Src/NandPaths.h @@ -28,9 +28,10 @@ namespace Common typedef std::pair replace_t; typedef std::vector replace_v; - std::string CreateTicketFileName(u64 _titleID); - std::string CreateTitleDataPath(u64 _titleID); - std::string CreateTitleContentPath(u64 _titleID); + std::string GetTicketFileName(u64 _titleID); + std::string GetTMDFileName(u64 _titleID); + std::string GetTitleDataPath(u64 _titleID); + std::string GetTitleContentPath(u64 _titleID); bool CheckTitleTMD(u64 _titleID); bool CheckTitleTIK(u64 _titleID); void ReadReplacements(replace_v& replacements); diff --git a/Source/Core/Core/Core.vcxproj b/Source/Core/Core/Core.vcxproj index f7d7c97bf3..c9ccf22223 100644 --- a/Source/Core/Core/Core.vcxproj +++ b/Source/Core/Core/Core.vcxproj @@ -405,7 +405,6 @@ - diff --git a/Source/Core/Core/Core.vcxproj.filters b/Source/Core/Core/Core.vcxproj.filters index 06bae14d9b..2b122f3034 100644 --- a/Source/Core/Core/Core.vcxproj.filters +++ b/Source/Core/Core/Core.vcxproj.filters @@ -575,9 +575,6 @@ ActionReplay - - Boot - Boot diff --git a/Source/Core/Core/Src/Boot/Boot.h b/Source/Core/Core/Src/Boot/Boot.h index b03ae9afce..e1cf191672 100644 --- a/Source/Core/Core/Src/Boot/Boot.h +++ b/Source/Core/Core/Src/Boot/Boot.h @@ -29,11 +29,7 @@ public: static bool BootUp(); static bool IsElfWii(const char *filename); - static bool IsWiiWAD(const char *filename); - static std::string GenerateMapFilename(); - - static u64 Install_WiiWAD(const char *filename); private: static void RunFunction(u32 _iAddr); diff --git a/Source/Core/Core/Src/Boot/Boot_BS2Emu.cpp b/Source/Core/Core/Src/Boot/Boot_BS2Emu.cpp index 19d4783ba9..c04938ca65 100644 --- a/Source/Core/Core/Src/Boot/Boot_BS2Emu.cpp +++ b/Source/Core/Core/Src/Boot/Boot_BS2Emu.cpp @@ -183,7 +183,7 @@ bool CBoot::SetupWiiMemory(unsigned int _CountryCode) // SYSCONF file. The games also read it to 0x3800, what is a little strange // however is that it only reads the first 100 bytes of it. std::string region_filename, - settings_Filename(Common::CreateTitleDataPath(TITLEID_SYSMENU)+ DIR_SEP + WII_SETTING); + settings_Filename(Common::GetTitleDataPath(TITLEID_SYSMENU) + WII_SETTING); switch((DiscIO::IVolume::ECountry)_CountryCode) { diff --git a/Source/Core/Core/Src/Boot/Boot_ELF.cpp b/Source/Core/Core/Src/Boot/Boot_ELF.cpp index c26e4a70fe..c80bc0e7c8 100644 --- a/Source/Core/Core/Src/Boot/Boot_ELF.cpp +++ b/Source/Core/Core/Src/Boot/Boot_ELF.cpp @@ -19,7 +19,6 @@ #include "Boot.h" #include "../HLE/HLE.h" #include "Boot_ELF.h" -#include "Boot_WiiWAD.h" #include "ElfReader.h" #include "FileUtil.h" diff --git a/Source/Core/Core/Src/Boot/Boot_WiiWAD.cpp b/Source/Core/Core/Src/Boot/Boot_WiiWAD.cpp index 4f5af5cfdb..05559281c2 100644 --- a/Source/Core/Core/Src/Boot/Boot_WiiWAD.cpp +++ b/Source/Core/Core/Src/Boot/Boot_WiiWAD.cpp @@ -22,6 +22,7 @@ #include "../ConfigManager.h" #include "../PatchEngine.h" #include "../IPC_HLE/WII_IPC_HLE.h" +#include "../IPC_HLE/WII_IPC_HLE_Device_FileIO.h" #include "WiiWad.h" #include "NANDContentLoader.h" @@ -31,21 +32,18 @@ #include "VolumeCreator.h" #include "CommonPaths.h" - -bool CBoot::IsWiiWAD(const char *filename) -{ - return DiscIO::WiiWAD::IsWiiWAD(filename); -} - bool CBoot::Boot_WiiWAD(const char* _pFilename) { const DiscIO::INANDContentLoader& ContentLoader = DiscIO::CNANDContentManager::Access().GetNANDLoader(_pFilename); if (!ContentLoader.IsValid()) return false; + u64 titleID = ContentLoader.GetTitleID(); // create data directory - File::CreateFullPath(Common::CreateTitleDataPath(ContentLoader.GetTitleID()) + DIR_SEP); - + File::CreateFullPath(Common::GetTitleDataPath(titleID)); + + if (titleID == TITLEID_SYSMENU) + HLE_IPC_CreateVirtualFATFilesystem(); // setup wii mem if (!SetupWiiMemory(ContentLoader.GetCountry())) return false; @@ -79,105 +77,3 @@ bool CBoot::Boot_WiiWAD(const char* _pFilename) return true; } -u64 CBoot::Install_WiiWAD(const char* _pFilename) -{ - if (!IsWiiWAD(_pFilename)) - return 0; - const DiscIO::INANDContentLoader& ContentLoader = DiscIO::CNANDContentManager::Access().GetNANDLoader(_pFilename); - if (ContentLoader.IsValid() == false) - return 0; - - 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, "%stitle/%08x/%08x/content/", - File::GetUserPath(D_WIIUSER_IDX).c_str(), TitleID_HI, TitleID_LO); - File::CreateFullPath(ContentPath); - - std::string TMDFileName(ContentPath); - TMDFileName += "title.tmd"; - - File::IOFile pTMDFile(TMDFileName, "wb"); - if (!pTMDFile) - { - PanicAlertT("WAD installation failed: error creating %s", TMDFileName.c_str()); - return 0; - } - - pTMDFile.WriteBytes(ContentLoader.GetTmdHeader(), DiscIO::INANDContentLoader::TMD_HEADER_SIZE); - - for (u32 i = 0; i < ContentLoader.GetContentSize(); i++) - { - DiscIO::SNANDContent Content = ContentLoader.GetContent()[i]; - - pTMDFile.WriteBytes(Content.m_Header, DiscIO::INANDContentLoader::CONTENT_HEADER_SIZE); - - char APPFileName[1024]; - if (Content.m_Type & 0x8000) //shared - { - sprintf(APPFileName, "%s", - DiscIO::CSharedContent::AccessInstance().AddSharedContent(Content.m_SHA1Hash).c_str()); - } - else - { - sprintf(APPFileName, "%s%08x.app", ContentPath, Content.m_ContentID); - } - - if (!File::Exists(APPFileName)) - { - File::CreateFullPath(APPFileName); - File::IOFile pAPPFile(APPFileName, "wb"); - if (!pAPPFile) - { - PanicAlertT("WAD installation failed: error creating %s", APPFileName); - return 0; - } - - pAPPFile.WriteBytes(Content.m_pData, Content.m_Size); - } - else - { - INFO_LOG(DISCIO, "Content %s already exists.", APPFileName); - } - } - - pTMDFile.Close(); - - //Extract and copy WAD's ticket to ticket directory - - char TicketPath[260+1]; - sprintf(TicketPath, "%sticket/%08x/", File::GetUserPath(D_WIIUSER_IDX).c_str(), TitleID_HI); - File::CreateFullPath(TicketPath); - - char TicketFileName[260+1]; - sprintf(TicketFileName, "%sticket/%08x/%08x.tik", - File::GetUserPath(D_WIIUSER_IDX).c_str(), TitleID_HI, TitleID_LO); - - File::IOFile pTicketFile(TicketFileName, "wb"); - if (!pTicketFile) - { - PanicAlertT("WAD installation failed: error creating %s", TicketFileName); - return 0; - } - - DiscIO::WiiWAD Wad(_pFilename); - if (!Wad.IsValid()) - { - return 0; - } - - pTicketFile.WriteBytes(Wad.GetTicket(), Wad.GetTicketSize()); - - if (!DiscIO::cUIDsys::AccessInstance().AddTitle(TitleID)) - { - INFO_LOG(DISCIO, "Title %08x%08x, already exists in uid.sys", TitleID_HI, TitleID_LO); - } - - return TitleID; -} - - diff --git a/Source/Core/Core/Src/CoreParameter.cpp b/Source/Core/Core/Src/CoreParameter.cpp index c4b2e7ee20..7d4dec83d9 100644 --- a/Source/Core/Core/Src/CoreParameter.cpp +++ b/Source/Core/Core/Src/CoreParameter.cpp @@ -221,7 +221,7 @@ bool SCoreStartupParameter::AutoSetup(EBootBS2 _BootBS2) if (ContentLoader.GetContentByIndex(ContentLoader.GetBootIndex()) == NULL) { //WAD is valid yet cannot be booted. Install instead. - u64 installed = CBoot::Install_WiiWAD(m_strFilename.c_str()); + u64 installed = DiscIO::CNANDContentManager::Access().Install_WiiWAD(m_strFilename); if (installed) SuccessAlertT("The WAD has been installed successfully"); return false; //do not boot diff --git a/Source/Core/Core/Src/FifoPlayer/FifoDataFile.h b/Source/Core/Core/Src/FifoPlayer/FifoDataFile.h index 409b74ba8e..fc8ce516d6 100644 --- a/Source/Core/Core/Src/FifoPlayer/FifoDataFile.h +++ b/Source/Core/Core/Src/FifoPlayer/FifoDataFile.h @@ -79,7 +79,7 @@ public: void AddFrame(const FifoFrameInfo &frameInfo); const FifoFrameInfo &GetFrame(int frame) const { return m_Frames[frame]; } - int GetFrameCount() { return m_Frames.size(); } + int GetFrameCount() { return (int)m_Frames.size(); } bool Save(const char *filename); diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp index 333ebbcd0b..27df17956d 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp @@ -51,8 +51,9 @@ std::string HLE_IPC_BuildFilename(const char* _pFilename, int _size) void HLE_IPC_CreateVirtualFATFilesystem() { - const std::string cdbPath = Common::CreateTitleDataPath(TITLEID_SYSMENU) + "/cdb.vff"; - if (!File::Exists(cdbPath)) + const int cdbSize = 0x01400000; + const std::string cdbPath = Common::GetTitleDataPath(TITLEID_SYSMENU) + "cdb.vff"; + if (File::GetSize(cdbPath) < cdbSize) { // cdb.vff is a virtual Fat filesystem created on first launch of sysmenu // we create it here as it is faster ~3 minutes for me when sysmenu does it ~1 second created here @@ -67,15 +68,16 @@ void HLE_IPC_CreateVirtualFATFilesystem() cdbFile.Seek(0x14020, SEEK_SET); cdbFile.WriteBytes(cdbFAT, 0x4); // 20 MiB file - cdbFile.Seek(0x01400000 - 1, SEEK_SET); + cdbFile.Seek(cdbSize - 1, SEEK_SET); // write the final 0 to 0 file from the second FAT to 20 MiB cdbFile.WriteBytes(cdbHDR + 14, 1); - if (!cdbFile.IsGood()) { cdbFile.Close(); File::Delete(cdbPath); } + cdbFile.Flush(); + cdbFile.Close(); } } } 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 fe4c1b97be..d868e350cd 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 @@ -444,32 +444,41 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress) _dbg_assert_msg_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 1, "IOCTL_ES_GETVIEWCNT no out buffer"); u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address); - std::string TicketFilename = Common::CreateTicketFileName(TitleID); - u32 ViewCount = 0; - if (File::Exists(TicketFilename)) - { - const u32 SIZE_OF_ONE_TICKET = 676; + u32 retVal = 0; + std::string ContentPath = Common::GetTitleContentPath(TitleID); + if (m_TitleID == TitleID) + ContentPath = m_ContentFile; - u32 FileSize = (u32)(File::GetSize(TicketFilename)); - _dbg_assert_msg_(WII_IPC_ES, (FileSize % SIZE_OF_ONE_TICKET) == 0, "IOCTL_ES_GETVIEWCNT ticket file size seems to be wrong"); + const DiscIO::INANDContentLoader& Loader = DiscIO::CNANDContentManager::Access().GetNANDLoader(ContentPath); + u32 ViewCount = Loader.GetTIKSize() / DiscIO::INANDContentLoader::TICKET_SIZE; - ViewCount = FileSize / SIZE_OF_ONE_TICKET; - _dbg_assert_msg_(WII_IPC_ES, (ViewCount>0) && (ViewCount<=4), "IOCTL_ES_GETVIEWCNT ticket count seems to be wrong"); - } - else - { - if (TitleID == TITLEID_SYSMENU) - { - PanicAlertT("There must be a ticket for 00000001/00000002. Your NAND dump is probably incomplete."); - } - ViewCount = 0; - } + if (!ViewCount) + { + std::string TicketFilename = Common::GetTicketFileName(TitleID); + if (File::Exists(TicketFilename)) + { + u32 FileSize = (u32)File::GetSize(TicketFilename); + _dbg_assert_msg_(WII_IPC_ES, (FileSize % DiscIO::INANDContentLoader::TICKET_SIZE) == 0, "IOCTL_ES_GETVIEWCNT ticket file size seems to be wrong"); + + ViewCount = FileSize / DiscIO::INANDContentLoader::TICKET_SIZE; + _dbg_assert_msg_(WII_IPC_ES, (ViewCount>0) && (ViewCount<=4), "IOCTL_ES_GETVIEWCNT ticket count seems to be wrong"); + } + else + { + if (TitleID == TITLEID_SYSMENU) + { + PanicAlertT("There must be a ticket for 00000001/00000002. Your NAND dump is probably incomplete."); + } + ViewCount = 0; + //retVal = ES_NO_TICKET_INSTALLED; + } + } INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETVIEWCNT for titleID: %08x/%08x (View Count = %i)", (u32)(TitleID>>32), (u32)TitleID, ViewCount); Memory::Write_U32(ViewCount, Buffer.PayloadBuffer[0].m_Address); - Memory::Write_U32(0, _CommandAddress + 0x4); + Memory::Write_U32(retVal, _CommandAddress + 0x4); return true; } break; @@ -481,30 +490,49 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress) u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address); u32 maxViews = Memory::Read_U32(Buffer.InBuffer[1].m_Address); + u32 retVal = 0; + std::string ContentPath = Common::GetTitleContentPath(TitleID); + if (m_TitleID == TitleID) + ContentPath = m_ContentFile; - std::string TicketFilename = Common::CreateTicketFileName(TitleID); - if (File::Exists(TicketFilename)) + const DiscIO::INANDContentLoader& Loader = DiscIO::CNANDContentManager::Access().GetNANDLoader(ContentPath); + + const u8 *Ticket = Loader.GetTIK(); + if (Ticket) { - const u32 SIZE_OF_ONE_TICKET = 676; - File::IOFile pFile(TicketFilename, "rb"); - if (pFile) + u32 viewCnt = Loader.GetTIKSize() / DiscIO::INANDContentLoader::TICKET_SIZE; + for (unsigned int View = 0; View != maxViews && View < viewCnt; ++View) { - u8 Ticket[SIZE_OF_ONE_TICKET]; - for (unsigned int View = 0; View != maxViews && pFile.ReadBytes(Ticket, SIZE_OF_ONE_TICKET); ++View) - { - Memory::Write_U32(View, Buffer.PayloadBuffer[0].m_Address + View * 0xD8); - Memory::WriteBigEData(Ticket+0x1D0, Buffer.PayloadBuffer[0].m_Address + 4 + View * 0xD8, 212); - } + Memory::Write_U32(View, Buffer.PayloadBuffer[0].m_Address + View * 0xD8); + Memory::WriteBigEData(Ticket + 0x1D0 + (View * DiscIO::INANDContentLoader::TICKET_SIZE), + Buffer.PayloadBuffer[0].m_Address + 4 + View * 0xD8, 212); } } else { - PanicAlertT("IOCTL_ES_GETVIEWS: Tried to get data from an unknown ticket: %08x/%08x", (u32)(TitleID >> 32), (u32)TitleID); + std::string TicketFilename = Common::GetTicketFileName(TitleID); + if (File::Exists(TicketFilename)) + { + File::IOFile pFile(TicketFilename, "rb"); + if (pFile) + { + u8 Ticket[DiscIO::INANDContentLoader::TICKET_SIZE]; + for (unsigned int View = 0; View != maxViews && pFile.ReadBytes(Ticket, DiscIO::INANDContentLoader::TICKET_SIZE); ++View) + { + Memory::Write_U32(View, Buffer.PayloadBuffer[0].m_Address + View * 0xD8); + Memory::WriteBigEData(Ticket+0x1D0, Buffer.PayloadBuffer[0].m_Address + 4 + View * 0xD8, 212); + } + } + } + else + { + //retVal = ES_NO_TICKET_INSTALLED; + PanicAlertT("IOCTL_ES_GETVIEWS: Tried to get data from an unknown ticket: %08x/%08x", (u32)(TitleID >> 32), (u32)TitleID); + } } - INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETVIEWS for titleID: %08x/%08x (MaxViews = %i)", (u32)(TitleID >> 32), (u32)TitleID, maxViews); - Memory::Write_U32(0, _CommandAddress + 0x4); + Memory::Write_U32(retVal, _CommandAddress + 0x4); return true; } break; @@ -516,7 +544,11 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress) u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address); u32 TitleID_HI = (u32)(TitleID >> 32); - const DiscIO::INANDContentLoader& Loader = DiscIO::CNANDContentManager::Access().GetNANDLoader(TitleID); + + std::string ContentPath = Common::GetTitleContentPath(TitleID); + if (m_TitleID == TitleID) + ContentPath = m_ContentFile; + const DiscIO::INANDContentLoader& Loader = DiscIO::CNANDContentManager::Access().GetNANDLoader(ContentPath); // Assert if title is not a disc title and the loader is not valid _dbg_assert_msg_(WII_IPC_ES, (TitleID_HI == 0x00010000) || (TitleID_HI == 0x00010004) || Loader.IsValid(), "Loader not valid for TitleID %08x/%08x", TitleID_HI, (u32)TitleID); @@ -524,7 +556,7 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress) u32 TMDViewCnt = 0; if (Loader.IsValid()) { - TMDViewCnt += DiscIO::INANDContentLoader::TICKET_VIEW_SIZE; + TMDViewCnt += DiscIO::INANDContentLoader::TMD_VIEW_SIZE; TMDViewCnt += 2; // title version TMDViewCnt += 2; // num entries TMDViewCnt += (u32)Loader.GetContentSize() * (4+2+2+8); // content id, index, type, size @@ -545,7 +577,10 @@ 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); - const DiscIO::INANDContentLoader& Loader = DiscIO::CNANDContentManager::Access().GetNANDLoader(TitleID); + std::string ContentPath = Common::GetTitleContentPath(TitleID); + if (m_TitleID == TitleID) + ContentPath = m_ContentFile; + const DiscIO::INANDContentLoader& Loader = DiscIO::CNANDContentManager::Access().GetNANDLoader(ContentPath); INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETTMDVIEWCNT: title: %08x/%08x buffersize: %i", (u32)(TitleID >> 32), (u32)TitleID, MaxCount); @@ -554,8 +589,8 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress) { u32 Address = Buffer.PayloadBuffer[0].m_Address; - Memory::WriteBigEData(Loader.GetTicketView(), Address, DiscIO::INANDContentLoader::TICKET_VIEW_SIZE); - Address += DiscIO::INANDContentLoader::TICKET_VIEW_SIZE; + Memory::WriteBigEData(Loader.GetTMDView(), Address, DiscIO::INANDContentLoader::TMD_VIEW_SIZE); + Address += DiscIO::INANDContentLoader::TMD_VIEW_SIZE; Memory::Write_U16(Loader.GetTitleVersion(), Address); Address += 2; Memory::Write_U16(Loader.GetNumEntries(), Address); Address += 2; @@ -588,7 +623,7 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress) { u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address); INFO_LOG(WII_IPC_ES, "IOCTL_ES_DELETETICKET: title: %08x/%08x", (u32)(TitleID >> 32), (u32)TitleID); - if (File::Delete(Common::CreateTicketFileName(TitleID))) + if (File::Delete(Common::GetTicketFileName(TitleID))) { Memory::Write_U32(0, _CommandAddress + 0x4); } @@ -661,7 +696,7 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress) { u32 Address = Buffer.PayloadBuffer[0].m_Address; - Memory::WriteBigEData(Loader.GetTmdHeader(), Address, DiscIO::INANDContentLoader::TMD_HEADER_SIZE); + Memory::WriteBigEData(Loader.GetTMDHeader(), Address, DiscIO::INANDContentLoader::TMD_HEADER_SIZE); Address += DiscIO::INANDContentLoader::TMD_HEADER_SIZE; const std::vector& rContent = Loader.GetContent(); @@ -736,7 +771,7 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress) const DiscIO::SNANDContent* pContent = ContentLoader.GetContentByIndex(bootInd); if (pContent) { - LoadWAD(Common::CreateTitleContentPath(TitleID)); + LoadWAD(Common::GetTitleContentPath(TitleID)); CDolLoader DolLoader(pContent->m_pData, pContent->m_Size); DolLoader.Load(); // TODO: Check why sysmenu does not load the DOL correctly PC = DolLoader.GetEntryPoint() | 0x80000000; @@ -855,11 +890,8 @@ u32 CWII_IPC_HLE_Device_es::ES_DIVerify(u8* _pTMD, u32 _sz) { return -1; } - std::string tmdPath, - dataPath; - - tmdPath = Common::CreateTitleContentPath(tmdTitleID) + DIR_SEP + "title.tmd"; - dataPath = Common::CreateTitleDataPath(tmdTitleID) + DIR_SEP; + std::string tmdPath = Common::GetTMDFileName(tmdTitleID), + dataPath = Common::GetTitleDataPath(tmdTitleID); File::CreateFullPath(tmdPath); File::CreateFullPath(dataPath); diff --git a/Source/Core/DiscIO/Src/NANDContentLoader.cpp b/Source/Core/DiscIO/Src/NANDContentLoader.cpp index 1b77a2bfa3..732e58511f 100644 --- a/Source/Core/DiscIO/Src/NANDContentLoader.cpp +++ b/Source/Core/DiscIO/Src/NANDContentLoader.cpp @@ -24,6 +24,7 @@ #include "FileUtil.h" #include "Log.h" #include "WiiWad.h" +#include "StringUtil.h" namespace DiscIO { @@ -105,12 +106,14 @@ public: u32 GetBootIndex() const { return m_BootIndex; } size_t GetContentSize() const { return m_Content.size(); } const SNANDContent* GetContentByIndex(int _Index) const; - const u8* GetTicketView() const { return m_TicketView; } - const u8* GetTmdHeader() const { return m_TmdHeader; } + const u8* GetTMDView() const { return m_TMDView; } + const u8* GetTMDHeader() const { return m_TMDHeader; } + const u32 GetTIKSize() const { return m_TIKSize; } + const u8* GetTIK() const { return m_TIK; } const std::vector& GetContent() const { return m_Content; } - u16 GetTitleVersion() const {return m_TileVersion;} + u16 GetTitleVersion() const {return m_TitleVersion;} u16 GetNumEntries() const {return m_numEntries;} DiscIO::IVolume::ECountry GetCountry() const; u8 GetCountryChar() const {return m_Country; } @@ -118,26 +121,27 @@ public: private: bool m_Valid; + bool m_isWAD; + std::string m_Path; 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]; + u16 m_TitleVersion; + u8 m_TMDView[TMD_VIEW_SIZE]; + u8 m_TMDHeader[TMD_HEADER_SIZE]; + u32 m_TIKSize; + u8 *m_TIK; u8 m_Country; std::vector m_Content; - bool CreateFromDirectory(const std::string& _rPath); - bool CreateFromWAD(const std::string& _rName); + bool Initialize(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); }; @@ -145,22 +149,13 @@ private: CNANDContentLoader::CNANDContentLoader(const std::string& _rName) : m_Valid(false) + , m_isWAD(false) , m_TitleID(-1) , m_IosVersion(0x09) , m_BootIndex(-1) + , m_TIK(NULL) { - 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"); - } + m_Valid = Initialize(_rName); } CNANDContentLoader::~CNANDContentLoader() @@ -170,6 +165,11 @@ CNANDContentLoader::~CNANDContentLoader() delete [] m_Content[i].m_pData; } m_Content.clear(); + if (m_TIK) + { + delete []m_TIK; + m_TIK = NULL; + } } const SNANDContent* CNANDContentLoader::GetContentByIndex(int _Index) const @@ -182,57 +182,89 @@ const SNANDContent* CNANDContentLoader::GetContentByIndex(int _Index) const return NULL; } -bool CNANDContentLoader::CreateFromWAD(const std::string& _rName) +bool CNANDContentLoader::Initialize(const std::string& _rName) { + m_Path = _rName; WiiWAD Wad(_rName); - if (!Wad.IsValid()) - return false; - - return ParseTMD(Wad.GetDataApp(), Wad.GetDataAppSize(), Wad.GetTicket(), Wad.GetTMD()); -} - -bool CNANDContentLoader::CreateFromDirectory(const std::string& _rPath) -{ - std::string TMDFileName(_rPath); - TMDFileName += "/title.tmd"; - - File::IOFile pTMDFile(TMDFileName, "rb"); - if (!pTMDFile) + u8* pDataApp = NULL; + u8* pTMD = NULL; + u8 DecryptTitleKey[16]; + u8 IV[16]; + if (Wad.IsValid()) { - ERROR_LOG(DISCIO, "CreateFromDirectory: error opening %s", - TMDFileName.c_str()); - return false; + 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(); } - u64 Size = File::GetSize(TMDFileName); - u8* pTMD = new u8[(u32)Size]; - pTMDFile.ReadBytes(pTMD, (size_t)Size); - pTMDFile.Close(); + else + { + std::string TMDFileName(m_Path); + if (File::IsDirectory(TMDFileName)) + { + TMDFileName += "title.tmd"; + } + else + { + SplitPath(TMDFileName, &m_Path, NULL, NULL); + } + File::IOFile pTMDFile(TMDFileName, "rb"); + if (!pTMDFile) + { + ERROR_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(); + } + if (!pTMD) + return false; + memcpy(m_TMDView, pTMD + 0x180, TMD_VIEW_SIZE); + memcpy(m_TMDHeader, pTMD, TMD_HEADER_SIZE); - memcpy(m_TicketView, pTMD + 0x180, TICKET_VIEW_SIZE); - memcpy(m_TmdHeader, pTMD, TMD_HEADER_SIZE); - - m_TileVersion = Common::swap16(pTMD + 0x01dc); + 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_TileVersion); + m_Country = GetSysMenuRegion(m_TitleVersion); m_Content.resize(m_numEntries); - for (u32 i = 0; i < m_numEntries; i++) + + for (u32 i=0; i> 32), (u32)_TitleID); + return; + } - File::CreateFullPath(uidSys); - File::IOFile pFile(uidSys, "ab"); + SElement Element; + *(u64*)&(Element.titleID) = Common::swap64(_TitleID); + *(u32*)&(Element.UID) = Common::swap32(lastUID++); + m_Elements.push_back(Element); - if (pFile.WriteArray(&Element, 1)) - ERROR_LOG(DISCIO, "fwrite failed"); - - return true; - } + File::CreateFullPath(uidSys); + File::IOFile pFile(uidSys, "ab"); + + if (pFile.WriteArray(&Element, 1)) + ERROR_LOG(DISCIO, "fwrite failed"); } void cUIDsys::GetTitleIDs(std::vector& _TitleIDs, bool _owned) @@ -481,5 +465,90 @@ void cUIDsys::GetTitleIDs(std::vector& _TitleIDs, bool _owned) } } +u64 CNANDContentManager::Install_WiiWAD(std::string &fileName) +{ + if (fileName.find(".wad") == std::string::npos) + return 0; + const INANDContentLoader& ContentLoader = GetNANDLoader(fileName); + if (ContentLoader.IsValid() == false) + return 0; + + u64 TitleID = ContentLoader.GetTitleID(); + + //copy WAD's tmd header and contents to content directory + + std::string ContentPath(Common::GetTitleContentPath(TitleID)); + std::string TMDFileName(Common::GetTMDFileName(TitleID)); + File::CreateFullPath(TMDFileName); + + File::IOFile pTMDFile(TMDFileName, "wb"); + if (!pTMDFile) + { + PanicAlertT("WAD installation failed: error creating %s", TMDFileName.c_str()); + return 0; + } + + pTMDFile.WriteBytes(ContentLoader.GetTMDHeader(), INANDContentLoader::TMD_HEADER_SIZE); + + for (u32 i = 0; i < ContentLoader.GetContentSize(); i++) + { + SNANDContent Content = ContentLoader.GetContent()[i]; + + pTMDFile.WriteBytes(Content.m_Header, INANDContentLoader::CONTENT_HEADER_SIZE); + + char APPFileName[1024]; + if (Content.m_Type & 0x8000) //shared + { + sprintf(APPFileName, "%s", + CSharedContent::AccessInstance().AddSharedContent(Content.m_SHA1Hash).c_str()); + } + else + { + sprintf(APPFileName, "%s%08x.app", ContentPath.c_str(), Content.m_ContentID); + } + + if (!File::Exists(APPFileName)) + { + File::CreateFullPath(APPFileName); + File::IOFile pAPPFile(APPFileName, "wb"); + if (!pAPPFile) + { + PanicAlertT("WAD installation failed: error creating %s", APPFileName); + return 0; + } + + pAPPFile.WriteBytes(Content.m_pData, Content.m_Size); + } + else + { + INFO_LOG(DISCIO, "Content %s already exists.", APPFileName); + } + } + + pTMDFile.Close(); + + //Extract and copy WAD's ticket to ticket directory + std::string TicketFileName = Common::GetTicketFileName(TitleID); + + File::CreateFullPath(TicketFileName); + File::IOFile pTicketFile(TicketFileName, "wb"); + if (!pTicketFile) + { + PanicAlertT("WAD installation failed: error creating %s", TicketFileName); + return 0; + } + + if (ContentLoader.GetTIK()) + { + pTicketFile.WriteBytes(ContentLoader.GetTIK(), ContentLoader.GetTIKSize()); + } + + cUIDsys::AccessInstance().AddTitle(TitleID); + + + return TitleID; +} + + } // namespace end diff --git a/Source/Core/DiscIO/Src/NANDContentLoader.h b/Source/Core/DiscIO/Src/NANDContentLoader.h index 8f607be2b5..02fa4197ac 100644 --- a/Source/Core/DiscIO/Src/NANDContentLoader.h +++ b/Source/Core/DiscIO/Src/NANDContentLoader.h @@ -58,8 +58,10 @@ public: virtual u32 GetBootIndex() const = 0; virtual size_t GetContentSize() const = 0; virtual const SNANDContent* GetContentByIndex(int _Index) const = 0; - virtual const u8* GetTicketView() const = 0; - virtual const u8* GetTmdHeader() const = 0; + virtual const u8* GetTMDView() const = 0; + virtual const u8* GetTMDHeader() const = 0; + virtual const u32 GetTIKSize() const = 0; + virtual const u8* GetTIK() const = 0; virtual const std::vector& GetContent() const = 0; virtual u16 GetTitleVersion() const = 0; virtual u16 GetNumEntries() const = 0; @@ -68,9 +70,10 @@ public: enum { - TICKET_VIEW_SIZE = 0x58, + TMD_VIEW_SIZE = 0x58, TMD_HEADER_SIZE = 0x1e4, - CONTENT_HEADER_SIZE = 0x24 + CONTENT_HEADER_SIZE = 0x24, + TICKET_SIZE = 0x2A4 }; }; @@ -81,6 +84,7 @@ class CNANDContentManager public: static CNANDContentManager& Access() { return m_Instance; } + u64 Install_WiiWAD(std::string &fileName); const INANDContentLoader& GetNANDLoader(const std::string& _rName, bool forceReload = false); const INANDContentLoader& GetNANDLoader(u64 _titleId, bool forceReload = false); @@ -135,7 +139,7 @@ public: static cUIDsys& AccessInstance() { return m_Instance; } u32 GetUIDFromTitle(u64 _Title); - bool AddTitle(u64 _Title); + void AddTitle(u64 _Title); void GetTitleIDs(std::vector& _TitleIDs, bool _owned = false); private: diff --git a/Source/Core/DolphinWX/Src/FrameTools.cpp b/Source/Core/DolphinWX/Src/FrameTools.cpp index a3b45d40e0..5c1f236680 100644 --- a/Source/Core/DolphinWX/Src/FrameTools.cpp +++ b/Source/Core/DolphinWX/Src/FrameTools.cpp @@ -64,7 +64,7 @@ Core::GetWindowHandle(). #include "HW/GCPad.h" #include "HW/Wiimote.h" #include "IPC_HLE/WII_IPC_HLE_Device_usb.h" -#include "IPC_HLE/WII_IPC_HLE_Device_FileIO.h" +//#include "IPC_HLE/WII_IPC_HLE_Device_FileIO.h" #include "State.h" #include "VolumeHandler.h" #include "NANDContentLoader.h" @@ -1326,8 +1326,7 @@ void CFrame::OnShow_CheatsWindow(wxCommandEvent& WXUNUSED (event)) void CFrame::OnLoadWiiMenu(wxCommandEvent& WXUNUSED(event)) { - HLE_IPC_CreateVirtualFATFilesystem(); - BootGame(Common::CreateTitleContentPath(TITLEID_SYSMENU)); + BootGame(Common::GetTitleContentPath(TITLEID_SYSMENU)); } void CFrame::OnInstallWAD(wxCommandEvent& event) @@ -1372,7 +1371,7 @@ void CFrame::OnInstallWAD(wxCommandEvent& event) dialog.CenterOnParent(); - u64 titleID = CBoot::Install_WiiWAD(fileName.c_str()); + u64 titleID = DiscIO::CNANDContentManager::Access().Install_WiiWAD(fileName); if (titleID == TITLEID_SYSMENU) { const DiscIO::INANDContentLoader & SysMenu_Loader = DiscIO::CNANDContentManager::Access().GetNANDLoader(TITLEID_SYSMENU, true);