From 6105688c32a7944a51031ed74235fcaa1a9a72e5 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 30 Oct 2022 12:18:43 -0700 Subject: [PATCH 1/2] UI: Install textures as a zip if supported. --- Core/Util/GameManager.cpp | 57 +++++++++++++++++++++++++++++++++++++++ Core/Util/GameManager.h | 1 + 2 files changed, 58 insertions(+) diff --git a/Core/Util/GameManager.cpp b/Core/Util/GameManager.cpp index e808f07b6c0c..63952a5d8111 100644 --- a/Core/Util/GameManager.cpp +++ b/Core/Util/GameManager.cpp @@ -325,6 +325,9 @@ bool GameManager::InstallGame(Path url, Path fileName, bool deleteAfter) { if (DetectTexturePackDest(z, info.textureIniIndex, dest)) { INFO_LOG(HLE, "Installing '%s' into '%s'", fileName.c_str(), dest.c_str()); File::CreateFullPath(dest); + // Install as a zip file if textures.ini is in the root. Performs better on Android. + if (info.stripChars == 0) + return InstallMemstickZip(z, fileName, dest / "textures.zip", info, deleteAfter); File::CreateEmptyFile(dest / ".nomedia"); return InstallMemstickGame(z, fileName, dest, info, true, deleteAfter); } else { @@ -617,6 +620,60 @@ bool GameManager::InstallMemstickGame(struct zip *z, const Path &zipfile, const return false; } +bool GameManager::InstallMemstickZip(struct zip *z, const Path &zipfile, const Path &dest, const ZipFileInfo &info, bool deleteAfter) { + size_t allBytes = 0; + size_t bytesCopied = 0; + + auto sy = GetI18NCategory("System"); + + // We don't need the zip anymore, as we're going to copy it as-is. + zip_close(z); + z = nullptr; + + // Not using File::Copy() so we can report progress. + FILE *inf = File::OpenCFile(zipfile, "rb"); + if (!inf) + return false; + + allBytes = (size_t)File::GetFileSize(inf); + FILE *outf = File::OpenCFile(dest, "wb"); + if (!outf) { + SetInstallError(sy->T("Storage full")); + fclose(inf); + return false; + } + + const size_t blockSize = 1024 * 128; + u8 *buffer = new u8[blockSize]; + while (bytesCopied < allBytes) { + size_t readSize = std::min(blockSize, allBytes - bytesCopied); + if (fread(buffer, readSize, 1, inf) != 1) + break; + if (fwrite(buffer, readSize, 1, outf) != 1) + break; + bytesCopied += readSize; + installProgress_ = (float)allBytes / (float)allBytes; + } + + delete[] buffer; + fclose(inf); + fclose(outf); + + if (bytesCopied < allBytes) { + File::Delete(dest); + SetInstallError(sy->T("Storage full")); + return false; + } + + installProgress_ = 1.0f; + if (deleteAfter) { + File::Delete(zipfile); + } + InstallDone(); + ResetInstallError(); + return true; +} + bool GameManager::InstallZippedISO(struct zip *z, int isoFileIndex, const Path &zipfile, bool deleteAfter) { // Let's place the output file in the currently selected Games directory. diff --git a/Core/Util/GameManager.h b/Core/Util/GameManager.h index df74af2fd77b..f7fc8ff7b51e 100644 --- a/Core/Util/GameManager.h +++ b/Core/Util/GameManager.h @@ -79,6 +79,7 @@ class GameManager { private: bool InstallGame(Path url, Path tempFileName, bool deleteAfter); bool InstallMemstickGame(struct zip *z, const Path &zipFile, const Path &dest, const ZipFileInfo &info, bool allowRoot, bool deleteAfter); + bool InstallMemstickZip(struct zip *z, const Path &zipFile, const Path &dest, const ZipFileInfo &info, bool deleteAfter); bool InstallZippedISO(struct zip *z, int isoFileIndex, const Path &zipfile, bool deleteAfter); bool InstallRawISO(const Path &zipFile, const std::string &originalName, bool deleteAfter); void InstallDone(); From 15645ca480044b5eec20bcf680e60ac3258b6224 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 31 Oct 2022 20:17:18 -0700 Subject: [PATCH 2/2] Replacement: Avoid issues with c++14 data(). --- Core/TextureReplacer.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Core/TextureReplacer.cpp b/Core/TextureReplacer.cpp index a234ada34774..dcd413ff2b70 100644 --- a/Core/TextureReplacer.cpp +++ b/Core/TextureReplacer.cpp @@ -642,10 +642,10 @@ bool TextureReplacer::PopulateLevelFromZip(ReplacedTextureLevel &level, bool ign if (zsize != INVALID_ZIP_SIZE) pngdata.resize(zsize); if (!pngdata.empty()) { - pngdata.resize(zip_fread(zf, pngdata.data(), pngdata.size())); + pngdata.resize(zip_fread(zf, &pngdata[0], pngdata.size())); } - if (png_image_begin_read_from_memory(&png, pngdata.data(), pngdata.size())) { + if (png_image_begin_read_from_memory(&png, &pngdata[0], pngdata.size())) { // We pad files that have been hashrange'd so they are the same texture size. level.w = png.width; level.h = png.height; @@ -1168,10 +1168,10 @@ void ReplacedTexture::PrepareData(int level) { if (zsize != INVALID_ZIP_SIZE) pngdata.resize(zsize); if (!pngdata.empty()) { - pngdata.resize(zip_fread(zf, pngdata.data(), pngdata.size())); + pngdata.resize(zip_fread(zf, &pngdata[0], pngdata.size())); } - if (!png_image_begin_read_from_memory(&png, pngdata.data(), pngdata.size())) { + if (!png_image_begin_read_from_memory(&png, &pngdata[0], pngdata.size())) { ERROR_LOG(G3D, "Could not load texture replacement info: %s - %s (zip)", info.file.c_str(), png.message); cleanup(); return;