This commit is contained in:
Joshua Vandaële 2025-04-27 02:05:18 -04:00 committed by GitHub
commit ddfb464fd8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 114 additions and 77 deletions

View file

@ -691,8 +691,8 @@ dolphin_find_optional_system_library_pkgconfig(ZSTD libzstd>=1.4.0 zstd::zstd Ex
add_subdirectory(Externals/zlib-ng) add_subdirectory(Externals/zlib-ng)
dolphin_find_optional_system_library_pkgconfig(MINIZIP dolphin_find_optional_system_library_pkgconfig(minizip-ng
"minizip>=4.0.4" minizip::minizip Externals/minizip-ng "minizip-ng>=4.0.4" minizip-ng::minizip-ng Externals/minizip-ng
) )
dolphin_find_optional_system_library(LZO Externals/LZO) dolphin_find_optional_system_library(LZO Externals/LZO)

View file

@ -3,10 +3,10 @@ project(minizip C)
add_library(minizip STATIC add_library(minizip STATIC
minizip-ng/mz.h minizip-ng/mz.h
# minizip-ng/compat/crypt.h # minizip-ng/compat/crypt.h
minizip-ng/compat/ioapi.c # minizip-ng/compat/ioapi.c
minizip-ng/compat/ioapi.h # minizip-ng/compat/ioapi.h
minizip-ng/compat/unzip.c # minizip-ng/compat/unzip.c
minizip-ng/compat/unzip.h # minizip-ng/compat/unzip.h
# minizip-ng/compat/zip.c # minizip-ng/compat/zip.c
# minizip-ng/compat/zip.h # minizip-ng/compat/zip.h
minizip-ng/mz_crypt.c minizip-ng/mz_crypt.c
@ -90,4 +90,4 @@ endif()
target_link_libraries(minizip PUBLIC ZLIB::ZLIB) target_link_libraries(minizip PUBLIC ZLIB::ZLIB)
add_library(minizip::minizip ALIAS minizip) add_library(minizip-ng::minizip-ng ALIAS minizip)

View file

@ -23,8 +23,6 @@
</ClCompile> </ClCompile>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="minizip-ng\compat\ioapi.c" />
<ClCompile Include="minizip-ng\compat\unzip.c" />
<ClCompile Include="minizip-ng\mz_crypt.c" /> <ClCompile Include="minizip-ng\mz_crypt.c" />
<ClCompile Include="minizip-ng\mz_os.c" /> <ClCompile Include="minizip-ng\mz_os.c" />
<ClCompile Include="minizip-ng\mz_os_win32.c" /> <ClCompile Include="minizip-ng\mz_os_win32.c" />
@ -39,8 +37,6 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="minizip-ng\mz.h" /> <ClInclude Include="minizip-ng\mz.h" />
<ClCompile Include="minizip-ng\compat\ioapi.h" />
<ClCompile Include="minizip-ng\compat\unzip.h" />
<ClInclude Include="minizip-ng\mz_crypt.h" /> <ClInclude Include="minizip-ng\mz_crypt.h" />
<ClInclude Include="minizip-ng\mz_os.h" /> <ClInclude Include="minizip-ng\mz_os.h" />
<ClInclude Include="minizip-ng\mz_strm.h" /> <ClInclude Include="minizip-ng\mz_strm.h" />

View file

@ -175,7 +175,7 @@ PUBLIC
enet::enet enet::enet
fmt::fmt fmt::fmt
MbedTLS::mbedtls MbedTLS::mbedtls
minizip::minizip minizip-ng::minizip-ng
sfml-network sfml-network
PRIVATE PRIVATE

View file

@ -5,7 +5,9 @@
#include <algorithm> #include <algorithm>
#include <unzip.h> #include <mz.h>
#include <mz_zip.h>
#include <mz_zip_rw.h>
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "Common/ScopeGuard.h" #include "Common/ScopeGuard.h"
@ -13,14 +15,14 @@
namespace Common namespace Common
{ {
// Reads all of the current file. destination must be big enough to fit the whole file. // Reads all of the current file. destination must be big enough to fit the whole file.
inline bool ReadFileFromZip(unzFile file, u8* destination, u64 len) inline bool ReadFileFromZip(void* zip_reader, u8* destination, u64 len)
{ {
const u64 MAX_BUFFER_SIZE = 65535; const u64 MAX_BUFFER_SIZE = 65535;
if (unzOpenCurrentFile(file) != UNZ_OK) if (mz_zip_reader_entry_open(zip_reader) != MZ_OK)
return false; return false;
Common::ScopeGuard guard{[&] { unzCloseCurrentFile(file); }}; Common::ScopeGuard guard{[&] { mz_zip_reader_entry_close(zip_reader); }};
u64 bytes_to_go = len; u64 bytes_to_go = len;
while (bytes_to_go > 0) while (bytes_to_go > 0)
@ -28,7 +30,7 @@ inline bool ReadFileFromZip(unzFile file, u8* destination, u64 len)
// NOTE: multiples of 4G can't cause read_len == 0 && bytes_to_go > 0, as MAX_BUFFER_SIZE is // NOTE: multiples of 4G can't cause read_len == 0 && bytes_to_go > 0, as MAX_BUFFER_SIZE is
// small. // small.
const u32 read_len = static_cast<u32>(std::min(bytes_to_go, MAX_BUFFER_SIZE)); const u32 read_len = static_cast<u32>(std::min(bytes_to_go, MAX_BUFFER_SIZE));
const int rv = unzReadCurrentFile(file, destination, read_len); const int rv = mz_zip_reader_entry_read(zip_reader, destination, read_len);
if (rv < 0) if (rv < 0)
return false; return false;
@ -37,11 +39,11 @@ inline bool ReadFileFromZip(unzFile file, u8* destination, u64 len)
destination += bytes_read; destination += bytes_read;
} }
return unzEndOfFile(file) == 1; return bytes_to_go == 0;
} }
template <typename ContiguousContainer> template <typename ContiguousContainer>
bool ReadFileFromZip(unzFile file, ContiguousContainer* destination) bool ReadFileFromZip(void* file, ContiguousContainer* destination)
{ {
return ReadFileFromZip(file, reinterpret_cast<u8*>(destination->data()), destination->size()); return ReadFileFromZip(file, reinterpret_cast<u8*>(destination->data()), destination->size());
} }

View file

@ -12,6 +12,10 @@
#include <mgba/core/timing.h> #include <mgba/core/timing.h>
#include <mgba/internal/gb/gb.h> #include <mgba/internal/gb/gb.h>
#include <mgba/internal/gba/gba.h> #include <mgba/internal/gba/gba.h>
#include <mz.h>
#include <mz_strm.h>
#include <mz_zip.h>
#include <mz_zip_rw.h>
#include "AudioCommon/AudioCommon.h" #include "AudioCommon/AudioCommon.h"
#include "Common/ChunkFile.h" #include "Common/ChunkFile.h"
@ -88,21 +92,27 @@ static VFile* OpenROM_Archive(const char* path)
static VFile* OpenROM_Zip(const char* path) static VFile* OpenROM_Zip(const char* path)
{ {
VFile* vf{}; VFile* vf{};
unzFile zip = unzOpen(path); void* zip_reader = nullptr;
if (!zip) zip_reader = mz_zip_reader_create();
if (!zip_reader)
return {};
Common::ScopeGuard file_guard{[&] { mz_zip_reader_delete(&zip_reader); }};
if (mz_zip_reader_open_file(zip_reader, path) != MZ_OK)
return nullptr; return nullptr;
do do
{ {
unz_file_info info{}; mz_zip_file* info;
if (unzGetCurrentFileInfo(zip, &info, nullptr, 0, nullptr, 0, nullptr, 0) != UNZ_OK || if (mz_zip_reader_entry_get_info(zip_reader, &info) != MZ_OK || !info->uncompressed_size)
!info.uncompressed_size)
continue; continue;
std::vector<u8> buffer(info.uncompressed_size); std::vector<u8> buffer(info->uncompressed_size);
if (!Common::ReadFileFromZip(zip, &buffer)) if (!Common::ReadFileFromZip(zip_reader, &buffer))
continue; continue;
vf = VFileMemChunk(buffer.data(), info.uncompressed_size); vf = VFileMemChunk(buffer.data(), info->uncompressed_size);
if (mCoreIsCompatible(vf) == mPLATFORM_GBA) if (mCoreIsCompatible(vf) == mPLATFORM_GBA)
{ {
vf->seek(vf, 0, SEEK_SET); vf->seek(vf, 0, SEEK_SET);
@ -111,8 +121,7 @@ static VFile* OpenROM_Zip(const char* path)
vf->close(vf); vf->close(vf);
vf = nullptr; vf = nullptr;
} while (unzGoToNextFile(zip) == UNZ_OK); } while (mz_zip_reader_goto_next_entry(zip_reader) != MZ_END_OF_LIST);
unzClose(zip);
return vf; return vf;
} }

View file

@ -75,7 +75,7 @@ PUBLIC
PRIVATE PRIVATE
fmt::fmt fmt::fmt
minizip::minizip minizip-ng::minizip-ng
pugixml pugixml
ZLIB::ZLIB ZLIB::ZLIB
) )

View file

@ -13,8 +13,11 @@
#include <unordered_set> #include <unordered_set>
#include <mbedtls/md5.h> #include <mbedtls/md5.h>
#include <mz.h>
#include <mz_strm.h>
#include <mz_zip.h>
#include <mz_zip_rw.h>
#include <pugixml.hpp> #include <pugixml.hpp>
#include <unzip.h>
#include "Common/Align.h" #include "Common/Align.h"
#include "Common/Assert.h" #include "Common/Assert.h"
@ -157,25 +160,29 @@ RedumpVerifier::DownloadStatus RedumpVerifier::DownloadDatfile(const std::string
std::vector<u8> RedumpVerifier::ReadDatfile(const std::string& system) std::vector<u8> RedumpVerifier::ReadDatfile(const std::string& system)
{ {
unzFile file = unzOpen(GetPathForSystem(system).c_str()); void* zip_reader = nullptr;
if (!file) zip_reader = mz_zip_reader_create();
if (!zip_reader)
return {}; return {};
Common::ScopeGuard file_guard{[&] { unzClose(file); }}; Common::ScopeGuard file_guard{[&] { mz_zip_reader_delete(&zip_reader); }};
if (mz_zip_reader_open_file(zip_reader, GetPathForSystem(system).c_str()) != MZ_OK)
return {};
// Check that the zip file contains exactly one file // Check that the zip file contains exactly one file
if (unzGoToFirstFile(file) != UNZ_OK) if (mz_zip_reader_goto_first_entry(zip_reader) != MZ_OK)
return {}; return {};
if (unzGoToNextFile(file) != UNZ_END_OF_LIST_OF_FILE) if (mz_zip_reader_goto_next_entry(zip_reader) != MZ_END_OF_LIST)
return {}; return {};
// Read the file // Read the file
if (unzGoToFirstFile(file) != UNZ_OK) if (mz_zip_reader_goto_first_entry(zip_reader) != MZ_OK)
return {}; return {};
unz_file_info file_info; mz_zip_file* file_info;
unzGetCurrentFileInfo(file, &file_info, nullptr, 0, nullptr, 0, nullptr, 0); mz_zip_reader_entry_get_info(zip_reader, &file_info);
std::vector<u8> data(file_info.uncompressed_size); std::vector<u8> data(file_info->uncompressed_size);
if (!Common::ReadFileFromZip(file, &data)) if (!Common::ReadFileFromZip(zip_reader, data.data(), file_info->uncompressed_size))
return {}; return {};
return data; return data;

View file

@ -28,7 +28,7 @@ PUBLIC
common common
core core
cpp-optparse cpp-optparse
minizip::minizip minizip-ng::minizip-ng
pugixml pugixml
PRIVATE PRIVATE

View file

@ -8,7 +8,9 @@
#include <mz.h> #include <mz.h>
#include <mz_os.h> #include <mz_os.h>
#include <unzip.h> #include <mz_strm.h>
#include <mz_zip.h>
#include <mz_zip_rw.h>
#include "Common/CommonPaths.h" #include "Common/CommonPaths.h"
#include "Common/Contains.h" #include "Common/Contains.h"
@ -28,34 +30,47 @@ constexpr char TEXTURE_PATH[] = HIRES_TEXTURES_DIR DIR_SEP;
ResourcePack::ResourcePack(const std::string& path) : m_path(path) ResourcePack::ResourcePack(const std::string& path) : m_path(path)
{ {
auto file = unzOpen(path.c_str()); void* zip_reader = nullptr;
Common::ScopeGuard file_guard{[&] { unzClose(file); }}; zip_reader = mz_zip_reader_create();
if (!zip_reader)
{
m_valid = false;
m_error = "Failed to create zip reader";
return;
}
if (file == nullptr) Common::ScopeGuard file_guard{[&] { mz_zip_reader_delete(&zip_reader); }};
if (mz_zip_reader_open_file(zip_reader, path.c_str()) != MZ_OK)
{ {
m_valid = false; m_valid = false;
m_error = "Failed to open resource pack"; m_error = "Failed to open resource pack";
return; return;
} }
if (unzLocateFile(file, "manifest.json", 0) == UNZ_END_OF_LIST_OF_FILE) if (mz_zip_reader_locate_entry(zip_reader, "manifest.json", 0) != MZ_OK)
{ {
m_valid = false; m_valid = false;
m_error = "Resource pack is missing a manifest."; m_error = "Resource pack is missing a manifest.";
return; return;
} }
unz_file_info64 manifest_info{}; mz_zip_file* manifest_info;
unzGetCurrentFileInfo64(file, &manifest_info, nullptr, 0, nullptr, 0, nullptr, 0); if (mz_zip_reader_entry_get_info(zip_reader, &manifest_info) != MZ_OK)
{
m_valid = false;
m_error = "Failed to get manifest info";
return;
}
std::string manifest_contents(manifest_info.uncompressed_size, '\0'); std::string manifest_contents(manifest_info->uncompressed_size, '\0');
if (!Common::ReadFileFromZip(file, &manifest_contents)) if (!Common::ReadFileFromZip(zip_reader, &manifest_contents))
{ {
m_valid = false; m_valid = false;
m_error = "Failed to read manifest.json"; m_error = "Failed to read manifest.json";
return; return;
} }
unzCloseCurrentFile(file); mz_zip_reader_entry_close(zip_reader);
m_manifest = std::make_shared<Manifest>(manifest_contents); m_manifest = std::make_shared<Manifest>(manifest_contents);
if (!m_manifest->IsValid()) if (!m_manifest->IsValid())
@ -65,14 +80,14 @@ ResourcePack::ResourcePack(const std::string& path) : m_path(path)
return; return;
} }
if (unzLocateFile(file, "logo.png", 0) != UNZ_END_OF_LIST_OF_FILE) if (mz_zip_reader_locate_entry(zip_reader, "logo.png", 0) == MZ_OK)
{ {
unz_file_info64 logo_info{}; mz_zip_file* logo_info;
unzGetCurrentFileInfo64(file, &logo_info, nullptr, 0, nullptr, 0, nullptr, 0); mz_zip_reader_entry_get_info(zip_reader, &logo_info);
m_logo_data.resize(logo_info.uncompressed_size); m_logo_data.resize(logo_info->uncompressed_size);
if (!Common::ReadFileFromZip(file, &m_logo_data)) if (!Common::ReadFileFromZip(zip_reader, &m_logo_data))
{ {
m_valid = false; m_valid = false;
m_error = "Failed to read logo.png"; m_error = "Failed to read logo.png";
@ -80,21 +95,20 @@ ResourcePack::ResourcePack(const std::string& path) : m_path(path)
} }
} }
unzGoToFirstFile(file); mz_zip_reader_goto_first_entry(zip_reader);
do do
{ {
std::string filename(256, '\0'); std::string filename(256, '\0');
unz_file_info64 texture_info{}; mz_zip_file* texture_info;
unzGetCurrentFileInfo64(file, &texture_info, filename.data(), static_cast<u16>(filename.size()), mz_zip_reader_entry_get_info(zip_reader, &texture_info);
nullptr, 0, nullptr, 0);
if (!filename.starts_with("textures/") || texture_info.uncompressed_size == 0) if (!filename.starts_with("textures/") || texture_info->uncompressed_size == 0)
continue; continue;
// If a texture is compressed and the manifest doesn't state that, abort. // If a texture is compressed and the manifest doesn't state that, abort.
if (!m_manifest->IsCompressed() && texture_info.compression_method != 0) if (!m_manifest->IsCompressed() && texture_info->compression_method != 0)
{ {
m_valid = false; m_valid = false;
m_error = "Texture " + filename + " is compressed!"; m_error = "Texture " + filename + " is compressed!";
@ -102,7 +116,7 @@ ResourcePack::ResourcePack(const std::string& path) : m_path(path)
} }
m_textures.push_back(filename.substr(9)); m_textures.push_back(filename.substr(9));
} while (unzGoToNextFile(file) != UNZ_END_OF_LIST_OF_FILE); } while (mz_zip_reader_goto_next_entry(zip_reader) != MZ_END_OF_LIST);
} }
bool ResourcePack::IsValid() const bool ResourcePack::IsValid() const
@ -143,29 +157,36 @@ bool ResourcePack::Install(const std::string& path)
return false; return false;
} }
auto file = unzOpen(m_path.c_str()); void* zip_reader = nullptr;
if (file == nullptr) zip_reader = mz_zip_reader_create();
if (!zip_reader)
{
m_valid = false;
m_error = "Failed to read zip reader";
return false;
}
Common::ScopeGuard file_guard{[&] { mz_zip_reader_delete(&zip_reader); }};
if (mz_zip_reader_open_file(zip_reader, m_path.c_str()) != MZ_OK)
{ {
m_valid = false; m_valid = false;
m_error = "Failed to open resource pack"; m_error = "Failed to open resource pack";
return false; return false;
} }
Common::ScopeGuard file_guard{[&] { unzClose(file); }};
if (unzGoToFirstFile(file) != MZ_OK) if (mz_zip_reader_goto_first_entry(zip_reader) != MZ_OK)
return false; return false;
std::string texture_zip_path;
do do
{ {
texture_zip_path.resize(UINT16_MAX + 1, '\0'); mz_zip_file* texture_info{};
unz_file_info64 texture_info{}; if (mz_zip_reader_entry_get_info(zip_reader, &texture_info) != MZ_OK)
if (unzGetCurrentFileInfo64(file, &texture_info, texture_zip_path.data(), UINT16_MAX, nullptr,
0, nullptr, 0) != MZ_OK)
{ {
return false; return false;
} }
TruncateToCString(&texture_zip_path);
const std::string texture_zip_path = texture_info->filename;
const std::string texture_zip_path_prefix = "textures/"; const std::string texture_zip_path_prefix = "textures/";
if (!texture_zip_path.starts_with(texture_zip_path_prefix)) if (!texture_zip_path.starts_with(texture_zip_path_prefix))
@ -203,14 +224,15 @@ bool ResourcePack::Install(const std::string& path)
return false; return false;
} }
const size_t data_size = static_cast<size_t>(texture_info.uncompressed_size); const size_t data_size = static_cast<size_t>(texture_info->uncompressed_size);
auto data = std::make_unique<u8[]>(data_size); auto data = std::make_unique<u8[]>(data_size);
if (!Common::ReadFileFromZip(file, data.get(), data_size)) if (!Common::ReadFileFromZip(zip_reader, data.get(), data_size))
{ {
m_error = "Failed to read texture " + texture; m_error = "Failed to read texture " + texture;
return false; return false;
} }
mz_zip_reader_entry_close(zip_reader);
File::IOFile out(texture_path, "wb"); File::IOFile out(texture_path, "wb");
if (!out) if (!out)
{ {
@ -222,7 +244,8 @@ bool ResourcePack::Install(const std::string& path)
m_error = "Failed to write " + texture; m_error = "Failed to write " + texture;
return false; return false;
} }
} while (unzGoToNextFile(file) == MZ_OK);
} while (mz_zip_reader_goto_next_entry(zip_reader) == MZ_OK);
SetInstalled(*this, true); SetInstalled(*this, true);
return true; return true;