diff --git a/Source/Core/Common/CMakeLists.txt b/Source/Core/Common/CMakeLists.txt
index c7752540df..0dd69b6c43 100644
--- a/Source/Core/Common/CMakeLists.txt
+++ b/Source/Core/Common/CMakeLists.txt
@@ -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}
diff --git a/Source/Core/Common/Common.vcxproj b/Source/Core/Common/Common.vcxproj
index 4fd4119418..f1b56e99f1 100644
--- a/Source/Core/Common/Common.vcxproj
+++ b/Source/Core/Common/Common.vcxproj
@@ -139,6 +139,7 @@
+
diff --git a/Source/Core/Common/Common.vcxproj.filters b/Source/Core/Common/Common.vcxproj.filters
index 5849e34f66..6a0261032f 100644
--- a/Source/Core/Common/Common.vcxproj.filters
+++ b/Source/Core/Common/Common.vcxproj.filters
@@ -59,6 +59,7 @@
+
diff --git a/Source/Core/Common/MinizipUtil.h b/Source/Core/Common/MinizipUtil.h
new file mode 100644
index 0000000000..8d8bc7d692
--- /dev/null
+++ b/Source/Core/Common/MinizipUtil.h
@@ -0,0 +1,42 @@
+// Copyright 2019 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include
+
+#include
+
+#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
+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(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(bytes_read);
+ }
+
+ return true;
+}
+} // namespace Common
diff --git a/Source/Core/DiscIO/CMakeLists.txt b/Source/Core/DiscIO/CMakeLists.txt
index ca5fdd3ddd..bfeab923fb 100644
--- a/Source/Core/DiscIO/CMakeLists.txt
+++ b/Source/Core/DiscIO/CMakeLists.txt
@@ -45,6 +45,7 @@ add_library(discio
target_link_libraries(discio
PRIVATE
+ minizip
pugixml
ZLIB::ZLIB
)
diff --git a/Source/Core/DiscIO/VolumeVerifier.cpp b/Source/Core/DiscIO/VolumeVerifier.cpp
index b0d4e8c3c5..de100bfb76 100644
--- a/Source/Core/DiscIO/VolumeVerifier.cpp
+++ b/Source/Core/DiscIO/VolumeVerifier.cpp
@@ -16,6 +16,7 @@
#include
#include
+#include
#include
#include
@@ -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 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 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 ParseHash(const char* str)
return hash;
}
-std::vector RedumpVerifier::ScanXML()
+std::vector RedumpVerifier::ScanDatfile(const std::vector& 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 potential_matches;
diff --git a/Source/Core/DiscIO/VolumeVerifier.h b/Source/Core/DiscIO/VolumeVerifier.h
index 0b908811f5..d10c5c97ff 100644
--- a/Source/Core/DiscIO/VolumeVerifier.h
+++ b/Source/Core/DiscIO/VolumeVerifier.h
@@ -71,9 +71,10 @@ private:
Hashes> hashes;
};
- std::vector ScanXML();
+ std::vector ReadDatfile();
+ std::vector ScanDatfile(const std::vector& data);
- std::string m_dat_filename;
+ std::string m_platform;
std::string m_game_id;
u16 m_revision;
u8 m_disc_number;
diff --git a/Source/Core/UICommon/ResourcePack/ResourcePack.cpp b/Source/Core/UICommon/ResourcePack/ResourcePack.cpp
index 24c6f7c76e..b0587f3ca5 100644
--- a/Source/Core/UICommon/ResourcePack/ResourcePack.cpp
+++ b/Source/Core/UICommon/ResourcePack/ResourcePack.cpp
@@ -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
-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(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(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 data(texture_info.uncompressed_size);
- if (!ReadCurrentFileUnlimited(file, data))
+ if (!Common::ReadFileFromZip(file, &data))
{
m_error = "Failed to read texture " + texture;
return false;