VolumeVerifier: Add zip support for datfile
This commit is contained in:
parent
22933d8502
commit
3eb360b818
|
@ -82,6 +82,7 @@ add_library(common
|
|||
MemArena.h
|
||||
MemoryUtil.cpp
|
||||
MemoryUtil.h
|
||||
MinizipUtil.h
|
||||
MsgHandler.cpp
|
||||
MsgHandler.h
|
||||
NandPaths.cpp
|
||||
|
@ -134,6 +135,7 @@ PUBLIC
|
|||
enet
|
||||
fmt::fmt
|
||||
${MBEDTLS_LIBRARIES}
|
||||
minizip
|
||||
|
||||
PRIVATE
|
||||
${CURL_LIBRARIES}
|
||||
|
|
|
@ -139,6 +139,7 @@
|
|||
<ClInclude Include="MD5.h" />
|
||||
<ClInclude Include="MemArena.h" />
|
||||
<ClInclude Include="MemoryUtil.h" />
|
||||
<ClInclude Include="MinizipUtil.h" />
|
||||
<ClInclude Include="MsgHandler.h" />
|
||||
<ClInclude Include="NandPaths.h" />
|
||||
<ClInclude Include="Network.h" />
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
<ClInclude Include="Matrix.h" />
|
||||
<ClInclude Include="MemArena.h" />
|
||||
<ClInclude Include="MemoryUtil.h" />
|
||||
<ClInclude Include="MinizipUtil.h" />
|
||||
<ClInclude Include="MsgHandler.h" />
|
||||
<ClInclude Include="NandPaths.h" />
|
||||
<ClInclude Include="Network.h" />
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
// Copyright 2019 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <minizip/unzip.h>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/ScopeGuard.h"
|
||||
|
||||
namespace Common
|
||||
{
|
||||
// Reads all of the current file. destination must be big enough to fit the whole file.
|
||||
template <typename ContiguousContainer>
|
||||
bool ReadFileFromZip(unzFile file, ContiguousContainer* destination)
|
||||
{
|
||||
const u32 MAX_BUFFER_SIZE = 65535;
|
||||
|
||||
if (unzOpenCurrentFile(file) != UNZ_OK)
|
||||
return false;
|
||||
|
||||
Common::ScopeGuard guard{[&] { unzCloseCurrentFile(file); }};
|
||||
|
||||
u32 bytes_to_go = static_cast<u32>(destination->size());
|
||||
while (bytes_to_go > 0)
|
||||
{
|
||||
const int bytes_read =
|
||||
unzReadCurrentFile(file, &(*destination)[destination->size() - bytes_to_go],
|
||||
std::min(bytes_to_go, MAX_BUFFER_SIZE));
|
||||
|
||||
if (bytes_read < 0)
|
||||
return false;
|
||||
|
||||
bytes_to_go -= static_cast<u32>(bytes_read);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
} // namespace Common
|
|
@ -45,6 +45,7 @@ add_library(discio
|
|||
|
||||
target_link_libraries(discio
|
||||
PRIVATE
|
||||
minizip
|
||||
pugixml
|
||||
ZLIB::ZLIB
|
||||
)
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include <mbedtls/md5.h>
|
||||
#include <mbedtls/sha1.h>
|
||||
#include <minizip/unzip.h>
|
||||
#include <pugixml.hpp>
|
||||
#include <zlib.h>
|
||||
|
||||
|
@ -25,7 +26,9 @@
|
|||
#include "Common/CommonTypes.h"
|
||||
#include "Common/FileUtil.h"
|
||||
#include "Common/Logging/Log.h"
|
||||
#include "Common/MinizipUtil.h"
|
||||
#include "Common/MsgHandler.h"
|
||||
#include "Common/ScopeGuard.h"
|
||||
#include "Common/StringUtil.h"
|
||||
#include "Common/Swap.h"
|
||||
#include "Core/IOS/Device.h"
|
||||
|
@ -46,9 +49,9 @@ namespace DiscIO
|
|||
void RedumpVerifier::Start(const Volume& volume)
|
||||
{
|
||||
if (volume.GetVolumeType() == Platform::GameCubeDisc)
|
||||
m_dat_filename = "gamecube.dat";
|
||||
m_platform = "gc";
|
||||
else if (volume.GetVolumeType() == Platform::WiiDisc)
|
||||
m_dat_filename = "wii.dat";
|
||||
m_platform = "wii";
|
||||
else
|
||||
m_result.status = Status::Error;
|
||||
|
||||
|
@ -62,7 +65,35 @@ void RedumpVerifier::Start(const Volume& volume)
|
|||
m_disc_number = volume.GetDiscNumber().value_or(0);
|
||||
m_size = volume.GetSize();
|
||||
|
||||
m_future = std::async(std::launch::async, [this] { return ScanXML(); });
|
||||
m_future = std::async(std::launch::async, [this] { return ScanDatfile(ReadDatfile()); });
|
||||
}
|
||||
|
||||
std::vector<u8> RedumpVerifier::ReadDatfile()
|
||||
{
|
||||
const std::string path = File::GetUserPath(D_REDUMPCACHE_IDX) + DIR_SEP + m_platform + ".zip";
|
||||
|
||||
unzFile file = unzOpen(path.c_str());
|
||||
if (!file)
|
||||
return {};
|
||||
|
||||
Common::ScopeGuard file_guard{[&] { unzClose(file); }};
|
||||
|
||||
// Check that the zip file contains exactly one file
|
||||
if (unzGoToFirstFile(file) != UNZ_OK)
|
||||
return {};
|
||||
if (unzGoToNextFile(file) != UNZ_END_OF_LIST_OF_FILE)
|
||||
return {};
|
||||
|
||||
// Read the file
|
||||
if (unzGoToFirstFile(file) != UNZ_OK)
|
||||
return {};
|
||||
unz_file_info file_info;
|
||||
unzGetCurrentFileInfo(file, &file_info, nullptr, 0, nullptr, 0, nullptr, 0);
|
||||
std::vector<u8> data(file_info.uncompressed_size);
|
||||
if (!Common::ReadFileFromZip(file, &data))
|
||||
return {};
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static u8 ParseHexDigit(char c)
|
||||
|
@ -93,18 +124,13 @@ static std::vector<u8> ParseHash(const char* str)
|
|||
return hash;
|
||||
}
|
||||
|
||||
std::vector<RedumpVerifier::PotentialMatch> RedumpVerifier::ScanXML()
|
||||
std::vector<RedumpVerifier::PotentialMatch> RedumpVerifier::ScanDatfile(const std::vector<u8>& data)
|
||||
{
|
||||
const std::string path = File::GetUserPath(D_REDUMPCACHE_IDX) + DIR_SEP + m_dat_filename;
|
||||
|
||||
pugi::xml_document doc;
|
||||
if (!doc.load_buffer(data.data(), data.size()))
|
||||
{
|
||||
std::string data;
|
||||
if (!File::ReadFileToString(path, data) || !doc.load_buffer(data.data(), data.size()))
|
||||
{
|
||||
m_result = {Status::Error, Common::GetStringT("Failed to parse Redump.org data")};
|
||||
return {};
|
||||
}
|
||||
m_result = {Status::Error, Common::GetStringT("Failed to parse Redump.org data")};
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<PotentialMatch> potential_matches;
|
||||
|
|
|
@ -71,9 +71,10 @@ private:
|
|||
Hashes<std::vector<u8>> hashes;
|
||||
};
|
||||
|
||||
std::vector<PotentialMatch> ScanXML();
|
||||
std::vector<u8> ReadDatfile();
|
||||
std::vector<PotentialMatch> ScanDatfile(const std::vector<u8>& data);
|
||||
|
||||
std::string m_dat_filename;
|
||||
std::string m_platform;
|
||||
std::string m_game_id;
|
||||
u16 m_revision;
|
||||
u8 m_disc_number;
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include "Common/FileSearch.h"
|
||||
#include "Common/FileUtil.h"
|
||||
#include "Common/MinizipUtil.h"
|
||||
#include "Common/ScopeGuard.h"
|
||||
#include "Common/StringUtil.h"
|
||||
|
||||
|
@ -20,35 +21,6 @@ namespace ResourcePack
|
|||
{
|
||||
constexpr char TEXTURE_PATH[] = "Load/Textures/";
|
||||
|
||||
// Since minzip doesn't provide a way to unzip a file of a length > 65535, we have to implement
|
||||
// this ourselves
|
||||
template <typename ContiguousContainer>
|
||||
static bool ReadCurrentFileUnlimited(unzFile file, ContiguousContainer& destination)
|
||||
{
|
||||
const u32 MAX_BUFFER_SIZE = 65535;
|
||||
|
||||
if (unzOpenCurrentFile(file) != UNZ_OK)
|
||||
return false;
|
||||
|
||||
Common::ScopeGuard guard{[&] { unzCloseCurrentFile(file); }};
|
||||
|
||||
auto bytes_to_go = static_cast<u32>(destination.size());
|
||||
while (bytes_to_go > 0)
|
||||
{
|
||||
const int bytes_read = unzReadCurrentFile(file, &destination[destination.size() - bytes_to_go],
|
||||
std::min(bytes_to_go, MAX_BUFFER_SIZE));
|
||||
|
||||
if (bytes_read < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bytes_to_go -= static_cast<u32>(bytes_read);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ResourcePack::ResourcePack(const std::string& path) : m_path(path)
|
||||
{
|
||||
auto file = unzOpen(path.c_str());
|
||||
|
@ -72,7 +44,7 @@ ResourcePack::ResourcePack(const std::string& path) : m_path(path)
|
|||
unzGetCurrentFileInfo(file, &manifest_info, nullptr, 0, nullptr, 0, nullptr, 0);
|
||||
|
||||
std::string manifest_contents(manifest_info.uncompressed_size, '\0');
|
||||
if (!ReadCurrentFileUnlimited(file, manifest_contents))
|
||||
if (!Common::ReadFileFromZip(file, &manifest_contents))
|
||||
{
|
||||
m_valid = false;
|
||||
m_error = "Failed to read manifest.json";
|
||||
|
@ -96,7 +68,7 @@ ResourcePack::ResourcePack(const std::string& path) : m_path(path)
|
|||
|
||||
m_logo_data.resize(logo_info.uncompressed_size);
|
||||
|
||||
if (!ReadCurrentFileUnlimited(file, m_logo_data))
|
||||
if (!Common::ReadFileFromZip(file, &m_logo_data))
|
||||
{
|
||||
m_valid = false;
|
||||
m_error = "Failed to read logo.png";
|
||||
|
@ -208,7 +180,7 @@ bool ResourcePack::Install(const std::string& path)
|
|||
unzGetCurrentFileInfo(file, &texture_info, nullptr, 0, nullptr, 0, nullptr, 0);
|
||||
|
||||
std::vector<char> data(texture_info.uncompressed_size);
|
||||
if (!ReadCurrentFileUnlimited(file, data))
|
||||
if (!Common::ReadFileFromZip(file, &data))
|
||||
{
|
||||
m_error = "Failed to read texture " + texture;
|
||||
return false;
|
||||
|
|
Loading…
Reference in New Issue