diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index b732f8194..cf26df141 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -51,6 +51,8 @@ add_library(common
log.h
md5_digest.cpp
md5_digest.h
+ minizip_helpers.cpp
+ minizip_helpers.h
null_audio_stream.cpp
null_audio_stream.h
rectangle.h
@@ -94,7 +96,7 @@ add_library(common
target_include_directories(common PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/..")
target_include_directories(common PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/..")
-target_link_libraries(common PRIVATE glad libcue stb Threads::Threads cubeb libchdr glslang vulkan-loader)
+target_link_libraries(common PRIVATE glad libcue stb Threads::Threads cubeb libchdr glslang vulkan-loader zlib minizip)
if(WIN32)
target_sources(common PRIVATE
diff --git a/src/common/common.vcxproj b/src/common/common.vcxproj
index ac71178a3..f1bec7b94 100644
--- a/src/common/common.vcxproj
+++ b/src/common/common.vcxproj
@@ -79,6 +79,7 @@
+
@@ -122,6 +123,7 @@
+
@@ -303,7 +305,7 @@
WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)
true
ProgramDatabase
- $(SolutionDir)dep\glad\include;$(SolutionDir)dep\cubeb\include;$(SolutionDir)dep\libcue\include;$(SolutionDir)dep\libchdr\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)dep\glslang;$(SolutionDir)src;%(AdditionalIncludeDirectories)
+ $(SolutionDir)dep\glad\include;$(SolutionDir)dep\cubeb\include;$(SolutionDir)dep\libcue\include;$(SolutionDir)dep\libchdr\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)dep\glslang;$(SolutionDir)dep\zlib\include;$(SolutionDir)dep\minizip\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)
true
stdcpp17
true
@@ -329,7 +331,7 @@
_ITERATOR_DEBUG_LEVEL=1;WIN32;_DEBUGFAST;_DEBUG;_LIB;%(PreprocessorDefinitions)
true
ProgramDatabase
- $(SolutionDir)dep\glad\include;$(SolutionDir)dep\cubeb\include;$(SolutionDir)dep\libcue\include;$(SolutionDir)dep\libchdr\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)dep\glslang;$(SolutionDir)src;%(AdditionalIncludeDirectories)
+ $(SolutionDir)dep\glad\include;$(SolutionDir)dep\cubeb\include;$(SolutionDir)dep\libcue\include;$(SolutionDir)dep\libchdr\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)dep\glslang;$(SolutionDir)dep\zlib\include;$(SolutionDir)dep\minizip\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)
Default
false
true
@@ -358,7 +360,7 @@
WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)
true
ProgramDatabase
- $(SolutionDir)dep\glad\include;$(SolutionDir)dep\cubeb\include;$(SolutionDir)dep\libcue\include;$(SolutionDir)dep\libchdr\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)dep\glslang;$(SolutionDir)src;%(AdditionalIncludeDirectories)
+ $(SolutionDir)dep\glad\include;$(SolutionDir)dep\cubeb\include;$(SolutionDir)dep\libcue\include;$(SolutionDir)dep\libchdr\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)dep\glslang;$(SolutionDir)dep\zlib\include;$(SolutionDir)dep\minizip\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)
true
stdcpp17
true
@@ -384,7 +386,7 @@
_ITERATOR_DEBUG_LEVEL=1;WIN32;_DEBUGFAST;_DEBUG;_LIB;%(PreprocessorDefinitions)
true
ProgramDatabase
- $(SolutionDir)dep\glad\include;$(SolutionDir)dep\cubeb\include;$(SolutionDir)dep\libcue\include;$(SolutionDir)dep\libchdr\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)dep\glslang;$(SolutionDir)src;%(AdditionalIncludeDirectories)
+ $(SolutionDir)dep\glad\include;$(SolutionDir)dep\cubeb\include;$(SolutionDir)dep\libcue\include;$(SolutionDir)dep\libchdr\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)dep\glslang;$(SolutionDir)dep\zlib\include;$(SolutionDir)dep\minizip\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)
Default
false
true
@@ -414,7 +416,7 @@
true
WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)
true
- $(SolutionDir)dep\glad\include;$(SolutionDir)dep\cubeb\include;$(SolutionDir)dep\libcue\include;$(SolutionDir)dep\libchdr\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)dep\glslang;$(SolutionDir)src;%(AdditionalIncludeDirectories)
+ $(SolutionDir)dep\glad\include;$(SolutionDir)dep\cubeb\include;$(SolutionDir)dep\libcue\include;$(SolutionDir)dep\libchdr\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)dep\glslang;$(SolutionDir)dep\zlib\include;$(SolutionDir)dep\minizip\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)
true
stdcpp17
false
@@ -444,7 +446,7 @@
true
WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)
true
- $(SolutionDir)dep\glad\include;$(SolutionDir)dep\cubeb\include;$(SolutionDir)dep\libcue\include;$(SolutionDir)dep\libchdr\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)dep\glslang;$(SolutionDir)src;%(AdditionalIncludeDirectories)
+ $(SolutionDir)dep\glad\include;$(SolutionDir)dep\cubeb\include;$(SolutionDir)dep\libcue\include;$(SolutionDir)dep\libchdr\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)dep\glslang;$(SolutionDir)dep\zlib\include;$(SolutionDir)dep\minizip\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)
true
true
stdcpp17
@@ -474,7 +476,7 @@
true
WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)
true
- $(SolutionDir)dep\glad\include;$(SolutionDir)dep\cubeb\include;$(SolutionDir)dep\libcue\include;$(SolutionDir)dep\libchdr\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)dep\glslang;$(SolutionDir)src;%(AdditionalIncludeDirectories)
+ $(SolutionDir)dep\glad\include;$(SolutionDir)dep\cubeb\include;$(SolutionDir)dep\libcue\include;$(SolutionDir)dep\libchdr\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)dep\glslang;$(SolutionDir)dep\zlib\include;$(SolutionDir)dep\minizip\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)
true
stdcpp17
false
@@ -504,7 +506,7 @@
true
WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)
true
- $(SolutionDir)dep\glad\include;$(SolutionDir)dep\cubeb\include;$(SolutionDir)dep\libcue\include;$(SolutionDir)dep\libchdr\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)dep\glslang;$(SolutionDir)src;%(AdditionalIncludeDirectories)
+ $(SolutionDir)dep\glad\include;$(SolutionDir)dep\cubeb\include;$(SolutionDir)dep\libcue\include;$(SolutionDir)dep\libchdr\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)dep\glslang;$(SolutionDir)dep\zlib\include;$(SolutionDir)dep\minizip\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)
true
true
stdcpp17
diff --git a/src/common/common.vcxproj.filters b/src/common/common.vcxproj.filters
index 20566df9f..d59115d98 100644
--- a/src/common/common.vcxproj.filters
+++ b/src/common/common.vcxproj.filters
@@ -99,6 +99,7 @@
vulkan
+
@@ -191,6 +192,7 @@
+
diff --git a/src/common/minizip_helpers.cpp b/src/common/minizip_helpers.cpp
new file mode 100644
index 000000000..ffa885d79
--- /dev/null
+++ b/src/common/minizip_helpers.cpp
@@ -0,0 +1,90 @@
+#include "minizip_helpers.h"
+#include "file_system.h"
+#include "ioapi.h"
+#include "types.h"
+#include
+
+namespace MinizipHelpers {
+
+unzFile OpenUnzMemoryFile(const void* memory, size_t memory_size)
+{
+ struct MemoryFileInfo
+ {
+ const u8* data;
+ ZPOS64_T data_size;
+ ZPOS64_T position;
+ };
+
+ MemoryFileInfo* fi = new MemoryFileInfo;
+ fi->data = static_cast(memory);
+ fi->data_size = static_cast(memory_size);
+ fi->position = 0;
+
+#define FI static_cast(stream)
+
+ zlib_filefunc64_def funcs = {
+ [](voidpf opaque, const void* filename, int mode) -> voidpf { return opaque; }, // open
+ [](voidpf opaque, voidpf stream, void* buf, uLong size) -> uLong { // read
+ const ZPOS64_T remaining = FI->data_size - FI->position;
+ const ZPOS64_T to_read = std::min(remaining, static_cast(size));
+ if (to_read > 0)
+ {
+ std::memcpy(buf, FI->data + FI->position, to_read);
+ FI->position += to_read;
+ }
+
+ return static_cast(to_read);
+ },
+ [](voidpf opaque, voidpf stream, const void* buf, uLong size) -> uLong { return 0; }, // write
+ [](voidpf opaque, voidpf stream) -> ZPOS64_T { return static_cast(FI->position); }, // tell
+ [](voidpf opaque, voidpf stream, ZPOS64_T offset, int origin) -> long { // seek
+ ZPOS64_T new_position = FI->position;
+ if (origin == SEEK_SET)
+ new_position = static_cast(offset);
+ else if (origin == SEEK_CUR)
+ new_position += static_cast(offset);
+ else
+ new_position = FI->data_size;
+ if (new_position < 0 || new_position > FI->data_size)
+ return -1;
+
+ FI->position = new_position;
+ return 0;
+ },
+ [](voidpf opaque, voidpf stream) -> int {
+ delete FI;
+ return 0;
+ }, // close
+ [](voidpf opaque, voidpf stream) -> int { return 0; }, // testerror
+ static_cast(fi)};
+
+#undef FI
+
+ unzFile zf = unzOpen2_64("", &funcs);
+ if (!zf)
+ delete fi;
+
+ return zf;
+}
+
+unzFile OpenUnzFile(const char* filename)
+{
+ zlib_filefunc64_def funcs;
+ fill_fopen64_filefunc(&funcs);
+
+ funcs.zopen64_file = [](voidpf opaque, const void* filename, int mode) -> voidpf {
+ const char* mode_fopen = NULL;
+ if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER) == ZLIB_FILEFUNC_MODE_READ)
+ mode_fopen = "rb";
+ else if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
+ mode_fopen = "r+b";
+ else if (mode & ZLIB_FILEFUNC_MODE_CREATE)
+ mode_fopen = "wb";
+
+ return FileSystem::OpenCFile(static_cast(filename), mode_fopen);
+ };
+
+ return unzOpen2_64(filename, &funcs);
+}
+
+} // namespace MinizipHelpers
\ No newline at end of file
diff --git a/src/common/minizip_helpers.h b/src/common/minizip_helpers.h
new file mode 100644
index 000000000..15a78b02b
--- /dev/null
+++ b/src/common/minizip_helpers.h
@@ -0,0 +1,9 @@
+#pragma once
+#include "unzip.h"
+
+namespace MinizipHelpers {
+
+unzFile OpenUnzMemoryFile(const void* memory, size_t memory_size);
+unzFile OpenUnzFile(const char* filename);
+
+} // namespace MinizipHelpers
\ No newline at end of file
diff --git a/src/duckstation-qt/gamelistsettingswidget.cpp b/src/duckstation-qt/gamelistsettingswidget.cpp
index 43bf75435..c298d3527 100644
--- a/src/duckstation-qt/gamelistsettingswidget.cpp
+++ b/src/duckstation-qt/gamelistsettingswidget.cpp
@@ -1,5 +1,6 @@
#include "gamelistsettingswidget.h"
#include "common/assert.h"
+#include "common/minizip_helpers.h"
#include "common/string_util.h"
#include "core/game_list.h"
#include "gamelistsearchdirectoriesmodel.h"
@@ -18,7 +19,6 @@
#include
#include
#include
-#include
static constexpr char REDUMP_DOWNLOAD_URL[] = "http://redump.org/datfile/psx/serial,version,description";
@@ -153,52 +153,7 @@ static bool ExtractRedumpDatabase(const QByteArray& data, const QString& destina
if (data.isEmpty())
return false;
- struct MemoryFileInfo
- {
- const QByteArray& data;
- int position;
- };
-
- MemoryFileInfo fi{data, 0};
-
-#define FI static_cast(stream)
-
- zlib_filefunc64_def funcs = {
- [](voidpf opaque, const void* filename, int mode) -> voidpf { return opaque; }, // open
- [](voidpf opaque, voidpf stream, void* buf, uLong size) -> uLong { // read
- const int remaining = FI->data.size() - FI->position;
- const int to_read = std::min(remaining, static_cast(size));
- if (to_read > 0)
- {
- std::memcpy(buf, FI->data.constData() + FI->position, to_read);
- FI->position += to_read;
- }
-
- return static_cast(to_read);
- },
- [](voidpf opaque, voidpf stream, const void* buf, uLong size) -> uLong { return 0; }, // write
- [](voidpf opaque, voidpf stream) -> ZPOS64_T { return static_cast(FI->position); }, // tell
- [](voidpf opaque, voidpf stream, ZPOS64_T offset, int origin) -> long { // seek
- int new_position = FI->position;
- if (origin == SEEK_SET)
- new_position = static_cast(offset);
- else if (origin == SEEK_CUR)
- new_position += static_cast(offset);
- else
- new_position = FI->data.size();
- if (new_position < 0 || new_position > FI->data.size())
- return -1;
-
- FI->position = new_position;
- return 0;
- },
- [](voidpf opaque, voidpf stream) -> int { return 0; }, // close
- [](voidpf opaque, voidpf stream) -> int { return 0; }, // testerror
- static_cast(&fi)};
-
-#undef FI
-
- unzFile zf = unzOpen2_64("", &funcs);
+ unzFile zf = MinizipHelpers::OpenUnzMemoryFile(data.constData(), data.size());
if (!zf)
{
qCritical() << "unzOpen2_64() failed";