diff --git a/Source/Core/Core/IOS/WFS/WFSI.cpp b/Source/Core/Core/IOS/WFS/WFSI.cpp index cb661b0f38..70f03b4281 100644 --- a/Source/Core/Core/IOS/WFS/WFSI.cpp +++ b/Source/Core/Core/IOS/WFS/WFSI.cpp @@ -98,6 +98,8 @@ IPCCommandResult WFSI::IOCtl(const IOCtlRequest& request) u32 tmd_addr = Memory::Read_U32(request.buffer_in); u32 tmd_size = Memory::Read_U32(request.buffer_in + 4); + m_continue_install = Memory::Read_U32(request.buffer_in + 36); + INFO_LOG(IOS_WFS, "IOCTL_WFSI_PREPARE_DEVICE"); constexpr u32 MAX_TMD_SIZE = 0x4000; @@ -122,6 +124,13 @@ IPCCommandResult WFSI::IOCtl(const IOCtlRequest& request) memcpy(m_aes_key, ticket.GetTitleKey(m_ios.GetIOSC()).data(), sizeof(m_aes_key)); mbedtls_aes_setkey_dec(&m_aes_ctx, m_aes_key, 128); + m_title_id = m_tmd.GetTitleId(); + m_title_id_str = StringFromFormat( + "%c%c%c%c", static_cast(m_title_id >> 24), static_cast(m_title_id >> 16), + static_cast(m_title_id >> 8), static_cast(m_title_id)); + m_group_id = m_tmd.GetGroupId(); + m_group_id_str = StringFromFormat("%c%c", m_group_id >> 8, m_group_id & 0xFF); + break; } @@ -205,6 +214,23 @@ IPCCommandResult WFSI::IOCtl(const IOCtlRequest& request) break; } + case IOCTL_WFSI_FINALIZE_IMPORT: + { + // TODO(wfs): Handle patches. + std::string title_install_dir = + StringFromFormat("/vol/%s/_install/%s", m_device_name.c_str(), m_title_id_str.c_str()); + std::string title_final_dir = StringFromFormat("/vol/%s/title/%s/%s", m_device_name.c_str(), + m_group_id_str.c_str(), m_title_id_str.c_str()); + File::Rename(WFS::NativePath(title_install_dir), WFS::NativePath(title_final_dir)); + + std::string tmd_path = + StringFromFormat("/vol/%s/title/%s/%s/meta/%016" PRIx64 ".tmd", m_device_name.c_str(), + m_group_id_str.c_str(), m_title_id_str.c_str(), m_title_id); + File::IOFile tmd_file(WFS::NativePath(tmd_path), "wb"); + tmd_file.WriteBytes(m_tmd.GetBytes().data(), m_tmd.GetBytes().size()); + break; + } + case IOCTL_WFSI_DELETE_TITLE: // Bytes 0-4: ?? // Bytes 4-8: game id @@ -226,8 +252,8 @@ IPCCommandResult WFSI::IOCtl(const IOCtlRequest& request) break; } m_title_id_str = StringFromFormat( - "%c%c%c%c", static_cast(m_title_id >> 56), static_cast(m_title_id >> 48), - static_cast(m_title_id >> 40), static_cast(m_title_id >> 32)); + "%c%c%c%c", static_cast(m_title_id >> 24), static_cast(m_title_id >> 16), + static_cast(m_title_id >> 8), static_cast(m_title_id)); IOS::ES::TMDReader tmd = GetIOS()->GetES()->FindInstalledTMD(m_title_id); m_group_id = tmd.GetGroupId(); @@ -241,10 +267,11 @@ IPCCommandResult WFSI::IOCtl(const IOCtlRequest& request) break; case IOCTL_WFSI_APPLY_TITLE_PROFILE: + { INFO_LOG(IOS_WFS, "IOCTL_WFSI_APPLY_TITLE_PROFILE"); std::string install_directory = StringFromFormat("/vol/%s/_install", m_device_name.c_str()); - if (File::IsDirectory(WFS::NativePath(install_directory))) + if (!m_continue_install && File::IsDirectory(WFS::NativePath(install_directory))) { File::DeleteDirRecursively(WFS::NativePath(install_directory)); } @@ -252,19 +279,22 @@ IPCCommandResult WFSI::IOCtl(const IOCtlRequest& request) m_base_extract_path = StringFromFormat("%s/%s/content", install_directory.c_str(), m_title_id_str.c_str()); File::CreateFullPath(WFS::NativePath(m_base_extract_path)); + File::CreateDir(WFS::NativePath(m_base_extract_path)); for (auto dir : {"work", "meta", "save"}) { std::string path = StringFromFormat("%s/%s/%s", install_directory.c_str(), m_title_id_str.c_str(), dir); - File::CreateFullPath(WFS::NativePath(path)); + File::CreateDir(WFS::NativePath(path)); } std::string group_path = StringFromFormat("/vol/%s/title/%s", m_device_name.c_str(), m_group_id_str.c_str()); File::CreateFullPath(WFS::NativePath(group_path)); + File::CreateDir(WFS::NativePath(group_path)); break; + } case IOCTL_WFSI_GET_TMD: { diff --git a/Source/Core/Core/IOS/WFS/WFSI.h b/Source/Core/Core/IOS/WFS/WFSI.h index 8945de1ce8..01f9e30831 100644 --- a/Source/Core/Core/IOS/WFS/WFSI.h +++ b/Source/Core/Core/IOS/WFS/WFSI.h @@ -58,6 +58,10 @@ private: u16 m_group_id; std::string m_group_id_str; + // Set on PREPARE_DEVICE when the next profile application should not delete + // temporary install files. + u32 m_continue_install = 0; + ARCUnpacker m_arc_unpacker; enum @@ -73,6 +77,8 @@ private: IOCTL_WFSI_IMPORT_CONTENT = 0x04, IOCTL_WFSI_FINALIZE_CONTENT = 0x05, + IOCTL_WFSI_FINALIZE_IMPORT = 0x06, + IOCTL_WFSI_DELETE_TITLE = 0x17, IOCTL_WFSI_IMPORT_TITLE = 0x2f,