From 2c40b2aa7232df9ba201d6d616d3663d1fc31967 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8E=84=E7=81=BD=E3=82=AC=E3=83=8E=E3=83=B3=E3=81=AE?= =?UTF-8?q?=E5=8F=B2=E5=AE=B6?= Date: Sun, 9 Oct 2022 00:19:00 -0500 Subject: [PATCH] Android: Add support for custom textures and texture dumping (#6144) * Android: add app UI settings for custom textures and texture dumping. * Android: Bring lodepng_image_interface into jni directory, include it, and add lodepng to CMAKE for linker (Android version doesn't use the src/citra folder) * Android: Add custom texture and texture dumping config.ini settings * Register image interface line added. * Update src/android/app/src/main/res/values/strings.xml Co-authored-by: SachinVin <26602104+SachinVin@users.noreply.github.com> * Update src/android/app/src/main/jni/lodepng_image_interface.cpp Whoops Co-authored-by: SachinVin <26602104+SachinVin@users.noreply.github.com> * clang-format attempt #1 Co-authored-by: SachinVin <26602104+SachinVin@users.noreply.github.com> --- .../features/settings/model/Settings.java | 3 +- .../ui/SettingsFragmentPresenter.java | 11 ++++++- .../features/settings/utils/SettingsFile.java | 4 +++ src/android/app/src/main/jni/CMakeLists.txt | 4 ++- src/android/app/src/main/jni/config.cpp | 6 ++++ src/android/app/src/main/jni/default_ini.h | 13 +++++++++ .../src/main/jni/lodepng_image_interface.cpp | 29 +++++++++++++++++++ .../src/main/jni/lodepng_image_interface.h | 14 +++++++++ src/android/app/src/main/jni/native.cpp | 4 +++ .../app/src/main/res/values/strings.xml | 8 ++++- 10 files changed, 92 insertions(+), 4 deletions(-) create mode 100644 src/android/app/src/main/jni/lodepng_image_interface.cpp create mode 100644 src/android/app/src/main/jni/lodepng_image_interface.h diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/Settings.java b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/Settings.java index dc67784093..9684966f20 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/Settings.java +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/Settings.java @@ -21,6 +21,7 @@ public class Settings { public static final String SECTION_CONTROLS = "Controls"; public static final String SECTION_RENDERER = "Renderer"; public static final String SECTION_LAYOUT = "Layout"; + public static final String SECTION_UTILITY = "Utility"; public static final String SECTION_AUDIO = "Audio"; public static final String SECTION_DEBUG = "Debug"; @@ -29,7 +30,7 @@ public class Settings { private static final Map> configFileSectionsMap = new HashMap<>(); static { - configFileSectionsMap.put(SettingsFile.FILE_NAME_CONFIG, Arrays.asList(SECTION_PREMIUM, SECTION_CORE, SECTION_SYSTEM, SECTION_CAMERA, SECTION_CONTROLS, SECTION_RENDERER, SECTION_LAYOUT, SECTION_AUDIO, SECTION_DEBUG)); + configFileSectionsMap.put(SettingsFile.FILE_NAME_CONFIG, Arrays.asList(SECTION_PREMIUM, SECTION_CORE, SECTION_SYSTEM, SECTION_CAMERA, SECTION_CONTROLS, SECTION_RENDERER, SECTION_LAYOUT, SECTION_UTILITY, SECTION_AUDIO, SECTION_DEBUG)); } /** diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.java b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.java index ef4623914f..6107dd59b5 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.java +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.java @@ -357,11 +357,14 @@ public final class SettingsFragmentPresenter { Setting render3dMode = rendererSection.getSetting(SettingsFile.KEY_RENDER_3D); Setting factor3d = rendererSection.getSetting(SettingsFile.KEY_FACTOR_3D); Setting useDiskShaderCache = rendererSection.getSetting(SettingsFile.KEY_USE_DISK_SHADER_CACHE); - SettingSection layoutSection = mSettings.getSection(Settings.SECTION_LAYOUT); Setting cardboardScreenSize = layoutSection.getSetting(SettingsFile.KEY_CARDBOARD_SCREEN_SIZE); Setting cardboardXShift = layoutSection.getSetting(SettingsFile.KEY_CARDBOARD_X_SHIFT); Setting cardboardYShift = layoutSection.getSetting(SettingsFile.KEY_CARDBOARD_Y_SHIFT); + SettingSection utilitySection = mSettings.getSection(Settings.SECTION_UTILITY); + Setting dumpTextures = utilitySection.getSetting(SettingsFile.KEY_DUMP_TEXTURES); + Setting customTextures = utilitySection.getSetting(SettingsFile.KEY_CUSTOM_TEXTURES); + //Setting preloadTextures = utilitySection.getSetting(SettingsFile.KEY_PRELOAD_TEXTURES); sl.add(new HeaderSetting(null, null, R.string.renderer, 0)); sl.add(new SliderSetting(SettingsFile.KEY_RESOLUTION_FACTOR, Settings.SECTION_RENDERER, R.string.internal_resolution, R.string.internal_resolution_description, 1, 4, "x", 1, resolutionFactor)); @@ -377,6 +380,12 @@ public final class SettingsFragmentPresenter { sl.add(new SliderSetting(SettingsFile.KEY_CARDBOARD_SCREEN_SIZE, Settings.SECTION_LAYOUT, R.string.cardboard_screen_size, R.string.cardboard_screen_size_description, 30, 100, "%", 85, cardboardScreenSize)); sl.add(new SliderSetting(SettingsFile.KEY_CARDBOARD_X_SHIFT, Settings.SECTION_LAYOUT, R.string.cardboard_x_shift, R.string.cardboard_x_shift_description, -100, 100, "%", 0, cardboardXShift)); sl.add(new SliderSetting(SettingsFile.KEY_CARDBOARD_Y_SHIFT, Settings.SECTION_LAYOUT, R.string.cardboard_y_shift, R.string.cardboard_y_shift_description, -100, 100, "%", 0, cardboardYShift)); + + sl.add(new HeaderSetting(null, null, R.string.utility, 0)); + sl.add(new CheckBoxSetting(SettingsFile.KEY_DUMP_TEXTURES, Settings.SECTION_UTILITY, R.string.dump_textures, R.string.dump_textures_description, false, dumpTextures)); + sl.add(new CheckBoxSetting(SettingsFile.KEY_CUSTOM_TEXTURES, Settings.SECTION_UTILITY, R.string.custom_textures, R.string.custom_textures_description, false, customTextures)); + //Disabled until custom texture implementation gets rewrite, current one overloads RAM and crashes Citra. + //sl.add(new CheckBoxSetting(SettingsFile.KEY_PRELOAD_TEXTURES, Settings.SECTION_UTILITY, R.string.preload_textures, R.string.preload_textures_description, false, preloadTextures)); } private void addAudioSettings(ArrayList sl) { diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/utils/SettingsFile.java b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/utils/SettingsFile.java index 5403cd7e4a..8ae6b70d7f 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/utils/SettingsFile.java +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/utils/SettingsFile.java @@ -64,6 +64,10 @@ public final class SettingsFile { public static final String KEY_CARDBOARD_X_SHIFT = "cardboard_x_shift"; public static final String KEY_CARDBOARD_Y_SHIFT = "cardboard_y_shift"; + public static final String KEY_DUMP_TEXTURES = "dump_textures"; + public static final String KEY_CUSTOM_TEXTURES = "custom_textures"; + public static final String KEY_PRELOAD_TEXTURES = "preload_textures"; + public static final String KEY_AUDIO_OUTPUT_ENGINE = "output_engine"; public static final String KEY_ENABLE_AUDIO_STRETCHING = "enable_audio_stretching"; public static final String KEY_VOLUME = "volume"; diff --git a/src/android/app/src/main/jni/CMakeLists.txt b/src/android/app/src/main/jni/CMakeLists.txt index 6cc0cf9061..bb382dc7ae 100644 --- a/src/android/app/src/main/jni/CMakeLists.txt +++ b/src/android/app/src/main/jni/CMakeLists.txt @@ -25,6 +25,8 @@ add_library(citra-android SHARED game_settings.h id_cache.cpp id_cache.h + lodepng_image_interface.cpp + lodepng_image_interface.h mic.cpp mic.h native.cpp @@ -34,6 +36,6 @@ add_library(citra-android SHARED ) target_link_libraries(citra-android PRIVATE audio_core common core input_common network) -target_link_libraries(citra-android PRIVATE android camera2ndk EGL glad inih jnigraphics log mediandk yuv) +target_link_libraries(citra-android PRIVATE android camera2ndk EGL glad inih jnigraphics lodepng log mediandk yuv) set(CPACK_PACKAGE_EXECUTABLES ${CPACK_PACKAGE_EXECUTABLES} citra-android) diff --git a/src/android/app/src/main/jni/config.cpp b/src/android/app/src/main/jni/config.cpp index 37afae5a43..746c26e09c 100644 --- a/src/android/app/src/main/jni/config.cpp +++ b/src/android/app/src/main/jni/config.cpp @@ -179,6 +179,12 @@ void Config::ReadValues() { Settings::values.cardboard_y_shift = static_cast(sdl2_config->GetInteger("Layout", "cardboard_y_shift", 0)); + // Utility + Settings::values.dump_textures = sdl2_config->GetBoolean("Utility", "dump_textures", false); + Settings::values.custom_textures = sdl2_config->GetBoolean("Utility", "custom_textures", false); + Settings::values.preload_textures = + sdl2_config->GetBoolean("Utility", "preload_textures", false); + // Audio Settings::values.enable_dsp_lle = sdl2_config->GetBoolean("Audio", "enable_dsp_lle", false); Settings::values.enable_dsp_lle_multithread = diff --git a/src/android/app/src/main/jni/default_ini.h b/src/android/app/src/main/jni/default_ini.h index 56ab75e1a7..b07e13a396 100644 --- a/src/android/app/src/main/jni/default_ini.h +++ b/src/android/app/src/main/jni/default_ini.h @@ -209,6 +209,19 @@ cardboard_x_shift = # -100 - 100: Screen Y-Coordinate shift as a percentage of empty space. 0 (default) cardboard_y_shift = +[Utility] +# Dumps textures as PNG to dump/textures/[Title ID]/. +# 0 (default): Off, 1: On +dump_textures = + +# Reads PNG files from load/textures/[Title ID]/ and replaces textures. +# 0 (default): Off, 1: On +custom_textures = + +# Loads all custom textures into memory before booting. +# 0 (default): Off, 1: On +preload_textures = + [Audio] # Whether or not to enable DSP LLE # 0 (default): No, 1: Yes diff --git a/src/android/app/src/main/jni/lodepng_image_interface.cpp b/src/android/app/src/main/jni/lodepng_image_interface.cpp new file mode 100644 index 0000000000..e42c3a82cd --- /dev/null +++ b/src/android/app/src/main/jni/lodepng_image_interface.cpp @@ -0,0 +1,29 @@ +// Copyright 2019 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include +#include "common/logging/log.h" +#include "jni/lodepng_image_interface.h" + +bool LodePNGImageInterface::DecodePNG(std::vector& dst, u32& width, u32& height, + const std::string& path) { + u32 lodepng_ret = lodepng::decode(dst, width, height, path); + if (lodepng_ret) { + LOG_CRITICAL(Frontend, "Failed to decode {} because {}", path, + lodepng_error_text(lodepng_ret)); + return false; + } + return true; +} + +bool LodePNGImageInterface::EncodePNG(const std::string& path, const std::vector& src, + u32 width, u32 height) { + u32 lodepng_ret = lodepng::encode(path, src, width, height); + if (lodepng_ret) { + LOG_CRITICAL(Frontend, "Failed to encode {} because {}", path, + lodepng_error_text(lodepng_ret)); + return false; + } + return true; +} diff --git a/src/android/app/src/main/jni/lodepng_image_interface.h b/src/android/app/src/main/jni/lodepng_image_interface.h new file mode 100644 index 0000000000..6880b10a0b --- /dev/null +++ b/src/android/app/src/main/jni/lodepng_image_interface.h @@ -0,0 +1,14 @@ +// Copyright 2019 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "core/frontend/image_interface.h" + +class LodePNGImageInterface final : public Frontend::ImageInterface { +public: + bool DecodePNG(std::vector& dst, u32& width, u32& height, const std::string& path) override; + bool EncodePNG(const std::string& path, const std::vector& src, u32 width, + u32 height) override; +}; diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp index e876ecb3ec..04c38305ec 100644 --- a/src/android/app/src/main/jni/native.cpp +++ b/src/android/app/src/main/jni/native.cpp @@ -38,6 +38,7 @@ #include "jni/game_settings.h" #include "jni/id_cache.h" #include "jni/input_manager.h" +#include "jni/lodepng_image_interface.h" #include "jni/mic.h" #include "jni/native.h" #include "jni/ndk_motion.h" @@ -174,6 +175,9 @@ static Core::System::ResultStatus RunCitra(const std::string& filepath) { system.RegisterMiiSelector(std::make_shared()); system.RegisterSoftwareKeyboard(std::make_shared()); + // Register generic image interface + Core::System::GetInstance().RegisterImageInterface(std::make_shared()); + // Register real Mic factory Frontend::Mic::RegisterRealMicFactory(std::make_unique()); diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index d1bbe28560..8f741a354a 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml @@ -103,7 +103,13 @@ Use shader JIT Use disk shader cache Reduce stuttering by storing and loading generated shaders to disk. It cannot be used without Enabling Hardware Shader. - + Utility + Dump textures + Dumps textures to dump/textures/[GAME ID] + Use custom textures + Uses custom textures found in load/textures/[GAME ID] + Preload custom textures + Loads all custom textures into memory. This feature can use a lot of memory. Premium Upgrade to Premium and support Citra!