From db8aaacb3500af14a83e0fc7a2585ff9a5d4c0e6 Mon Sep 17 00:00:00 2001 From: PabloMK7 Date: Sun, 13 Jul 2025 00:32:56 +0100 Subject: [PATCH] Z3DS: Fix minor issues and add Android cia compress setting --- .../features/settings/model/BooleanSetting.kt | 6 ++++-- .../citra_emu/features/settings/model/Settings.kt | 2 ++ .../features/settings/ui/SettingsFragmentPresenter.kt | 10 ++++++++++ src/android/app/src/main/jni/config.cpp | 3 +++ src/android/app/src/main/jni/default_ini.h | 5 +++++ src/android/app/src/main/res/values/strings.xml | 3 +++ src/citra_qt/citra_qt.cpp | 2 +- src/citra_qt/configuration/configure_storage.ui | 4 ++-- src/common/zstd_compression.cpp | 10 +++++++++- src/common/zstd_compression.h | 11 +++++++---- 10 files changed, 46 insertions(+), 10 deletions(-) diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/BooleanSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/BooleanSetting.kt index 3f6a14480..925e17805 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/BooleanSetting.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/BooleanSetting.kt @@ -48,7 +48,8 @@ enum class BooleanSetting( DEBUG_RENDERER("renderer_debug", Settings.SECTION_DEBUG, false), DISABLE_RIGHT_EYE_RENDER("disable_right_eye_render", Settings.SECTION_RENDERER, false), USE_ARTIC_BASE_CONTROLLER("use_artic_base_controller", Settings.SECTION_CONTROLS, false), - UPRIGHT_SCREEN("upright_screen", Settings.SECTION_LAYOUT, false); + UPRIGHT_SCREEN("upright_screen", Settings.SECTION_LAYOUT, false), + COMPRESS_INSTALLED_CIA_CONTENT("compress_cia_installs", Settings.SECTION_STORAGE, false); override var boolean: Boolean = defaultValue @@ -80,7 +81,8 @@ enum class BooleanSetting( CPU_JIT, ASYNC_CUSTOM_LOADING, SHADERS_ACCURATE_MUL, - USE_ARTIC_BASE_CONTROLLER + USE_ARTIC_BASE_CONTROLLER, + COMPRESS_INSTALLED_CIA_CONTENT, ) fun from(key: String): BooleanSetting? = diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/Settings.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/Settings.kt index b229ffe17..02d10cfe9 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/Settings.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/Settings.kt @@ -112,6 +112,7 @@ class Settings { const val SECTION_CUSTOM_LANDSCAPE = "Custom Landscape Layout" const val SECTION_CUSTOM_PORTRAIT = "Custom Portrait Layout" const val SECTION_PERFORMANCE_OVERLAY = "Performance Overlay" + const val SECTION_STORAGE = "Storage" const val KEY_BUTTON_A = "button_a" const val KEY_BUTTON_B = "button_b" @@ -237,6 +238,7 @@ class Settings { SECTION_CONTROLS, SECTION_RENDERER, SECTION_LAYOUT, + SECTION_STORAGE, SECTION_UTILITY, SECTION_AUDIO, SECTION_DEBUG diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt index e6b67e448..378a2cc66 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt @@ -565,6 +565,16 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) BooleanSetting.ALLOW_PLUGIN_LOADER.defaultValue ) ) + add(HeaderSetting(R.string.storage)) + add( + SwitchSetting( + BooleanSetting.COMPRESS_INSTALLED_CIA_CONTENT, + R.string.compress_cia_installs, + R.string.compress_cia_installs_description, + BooleanSetting.COMPRESS_INSTALLED_CIA_CONTENT.key, + BooleanSetting.COMPRESS_INSTALLED_CIA_CONTENT.defaultValue + ) + ) } } diff --git a/src/android/app/src/main/jni/config.cpp b/src/android/app/src/main/jni/config.cpp index b46333ada..d5c699924 100644 --- a/src/android/app/src/main/jni/config.cpp +++ b/src/android/app/src/main/jni/config.cpp @@ -218,6 +218,9 @@ void Config::ReadValues() { ReadSetting("Layout", Settings::values.custom_portrait_bottom_width); ReadSetting("Layout", Settings::values.custom_portrait_bottom_height); + // Storage + ReadSetting("Storage", Settings::values.compress_cia_installs); + // Utility ReadSetting("Utility", Settings::values.dump_textures); ReadSetting("Utility", Settings::values.custom_textures); diff --git a/src/android/app/src/main/jni/default_ini.h b/src/android/app/src/main/jni/default_ini.h index 83fa897fa..a34e4370e 100644 --- a/src/android/app/src/main/jni/default_ini.h +++ b/src/android/app/src/main/jni/default_ini.h @@ -210,6 +210,11 @@ disable_right_eye_render = # 5: Custom Layout layout_option = +[Storage] +# Whether to compress the installed CIA contents +# 0 (default): Do not compress, 1: Compress +compress_cia_installs = + # Position of the performance overlay # 0: Top Left # 1: Center Top diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index 3d47200be..86950bf5c 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml @@ -214,6 +214,9 @@ Region Mismatch Warning The country setting is not valid for the selected emulated region. The country setting is not valid for the current linked console. + Storage + Compress installed CIA content + Compresses the content of CIA files when installed to the emulated SD card. Only affects CIA content which is installed while the setting is enabled. Inner Camera diff --git a/src/citra_qt/citra_qt.cpp b/src/citra_qt/citra_qt.cpp index 8fd54ba54..da988cc0f 100644 --- a/src/citra_qt/citra_qt.cpp +++ b/src/citra_qt/citra_qt.cpp @@ -3081,7 +3081,7 @@ void GMainWindow::OnCompressFile() { compress_info.recommended_compressed_extension = "zcia"; compress_info.recommended_uncompressed_extension = "cia"; compress_info.underlying_magic = std::array({'C', 'I', 'A', '\0'}); - frame_size = FileUtil::Z3DSWriteIOFile::MAX_FRAME_SIZE; + frame_size = FileUtil::Z3DSWriteIOFile::DEFAULT_CIA_FRAME_SIZE; } } } diff --git a/src/citra_qt/configuration/configure_storage.ui b/src/citra_qt/configuration/configure_storage.ui index 83d7ba123..1c8358dbc 100644 --- a/src/citra_qt/configuration/configure_storage.ui +++ b/src/citra_qt/configuration/configure_storage.ui @@ -184,10 +184,10 @@ - Compress installed CIA contents + Compress installed CIA content - Enables compressing the contents of CIA files when they are installed to the emulated SD. + Compresses the content of CIA files when installed to the emulated SD card. Only affects CIA content which is installed while the setting is enabled. diff --git a/src/common/zstd_compression.cpp b/src/common/zstd_compression.cpp index e3d5dac5f..694b11011 100644 --- a/src/common/zstd_compression.cpp +++ b/src/common/zstd_compression.cpp @@ -115,9 +115,13 @@ Z3DSMetadata::Z3DSMetadata(const std::span& source_data) { while (!in.eof()) { Item item; ReadFromIStream(in, &item, sizeof(Item)); + // If end item is reached, stop processing + if (item.type == Item::TYPE_END) { + break; + } // Only binary type supported for now if (item.type != Item::TYPE_BINARY) { - break; + continue; } std::string name(item.name_len, '\0'); std::vector data(item.data_len); @@ -145,6 +149,10 @@ std::vector Z3DSMetadata::AsBinary() { WriteToOStream(out, it.second.data(), item.data_len); } + // Write end item + Item end{}; + WriteToOStream(out, &end, sizeof(end)); + std::string out_str = out.str(); return std::vector(out_str.begin(), out_str.end()); } diff --git a/src/common/zstd_compression.h b/src/common/zstd_compression.h index 03b9eb61e..590a40fcd 100644 --- a/src/common/zstd_compression.h +++ b/src/common/zstd_compression.h @@ -55,11 +55,12 @@ namespace FileUtil { struct Z3DSFileHeader { static constexpr std::array EXPECTED_MAGIC = {'Z', '3', 'D', 'S'}; - static constexpr u16 EXPECTED_VERSION = 1; + static constexpr u8 EXPECTED_VERSION = 1; std::array magic = EXPECTED_MAGIC; std::array underlying_magic{}; - u16 version = EXPECTED_VERSION; + u8 version = EXPECTED_VERSION; + u8 reserved = 0; u16 header_size = 0; u32 metadata_size = 0; u64 compressed_size = 0; @@ -70,6 +71,7 @@ struct Z3DSFileHeader { ar & magic; ar & underlying_magic; ar & version; + ar & reserved; ar & header_size; ar & metadata_size; ar & compressed_size; @@ -126,8 +128,9 @@ private: class Z3DSWriteIOFile : public IOFile { public: - static constexpr size_t DEFAULT_FRAME_SIZE = 256 * 1024; // 256KiB - static constexpr size_t MAX_FRAME_SIZE = 0; // Let the lib decide, usually 1GiB + static constexpr size_t DEFAULT_FRAME_SIZE = 256 * 1024; // 256KiB + static constexpr size_t DEFAULT_CIA_FRAME_SIZE = 32 * 1024 * 1024; // 32MiB + static constexpr size_t MAX_FRAME_SIZE = 0; // Let the lib decide, usually 1GiB Z3DSWriteIOFile();