From 7cafb8c5151e1017888a2749dcd0280082e249ec Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Thu, 6 Aug 2020 19:33:02 +1000 Subject: [PATCH] Common: Add MinizipHelpers (RAM and UTF-8 compatible fopen) --- src/common/CMakeLists.txt | 4 +- src/common/common.vcxproj | 18 ++-- src/common/common.vcxproj.filters | 2 + src/common/minizip_helpers.cpp | 90 +++++++++++++++++++ src/common/minizip_helpers.h | 9 ++ src/duckstation-qt/gamelistsettingswidget.cpp | 49 +--------- 6 files changed, 116 insertions(+), 56 deletions(-) create mode 100644 src/common/minizip_helpers.cpp create mode 100644 src/common/minizip_helpers.h 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";