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>
This commit is contained in:
厄災ガノンの史家 2022-10-09 00:19:00 -05:00 committed by GitHub
parent a427a80446
commit 2c40b2aa72
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 92 additions and 4 deletions

View file

@ -21,6 +21,7 @@ public class Settings {
public static final String SECTION_CONTROLS = "Controls"; public static final String SECTION_CONTROLS = "Controls";
public static final String SECTION_RENDERER = "Renderer"; public static final String SECTION_RENDERER = "Renderer";
public static final String SECTION_LAYOUT = "Layout"; 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_AUDIO = "Audio";
public static final String SECTION_DEBUG = "Debug"; public static final String SECTION_DEBUG = "Debug";
@ -29,7 +30,7 @@ public class Settings {
private static final Map<String, List<String>> configFileSectionsMap = new HashMap<>(); private static final Map<String, List<String>> configFileSectionsMap = new HashMap<>();
static { 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));
} }
/** /**

View file

@ -357,11 +357,14 @@ public final class SettingsFragmentPresenter {
Setting render3dMode = rendererSection.getSetting(SettingsFile.KEY_RENDER_3D); Setting render3dMode = rendererSection.getSetting(SettingsFile.KEY_RENDER_3D);
Setting factor3d = rendererSection.getSetting(SettingsFile.KEY_FACTOR_3D); Setting factor3d = rendererSection.getSetting(SettingsFile.KEY_FACTOR_3D);
Setting useDiskShaderCache = rendererSection.getSetting(SettingsFile.KEY_USE_DISK_SHADER_CACHE); Setting useDiskShaderCache = rendererSection.getSetting(SettingsFile.KEY_USE_DISK_SHADER_CACHE);
SettingSection layoutSection = mSettings.getSection(Settings.SECTION_LAYOUT); SettingSection layoutSection = mSettings.getSection(Settings.SECTION_LAYOUT);
Setting cardboardScreenSize = layoutSection.getSetting(SettingsFile.KEY_CARDBOARD_SCREEN_SIZE); Setting cardboardScreenSize = layoutSection.getSetting(SettingsFile.KEY_CARDBOARD_SCREEN_SIZE);
Setting cardboardXShift = layoutSection.getSetting(SettingsFile.KEY_CARDBOARD_X_SHIFT); Setting cardboardXShift = layoutSection.getSetting(SettingsFile.KEY_CARDBOARD_X_SHIFT);
Setting cardboardYShift = layoutSection.getSetting(SettingsFile.KEY_CARDBOARD_Y_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 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)); 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_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_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 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<SettingsItem> sl) { private void addAudioSettings(ArrayList<SettingsItem> sl) {

View file

@ -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_X_SHIFT = "cardboard_x_shift";
public static final String KEY_CARDBOARD_Y_SHIFT = "cardboard_y_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_AUDIO_OUTPUT_ENGINE = "output_engine";
public static final String KEY_ENABLE_AUDIO_STRETCHING = "enable_audio_stretching"; public static final String KEY_ENABLE_AUDIO_STRETCHING = "enable_audio_stretching";
public static final String KEY_VOLUME = "volume"; public static final String KEY_VOLUME = "volume";

View file

@ -25,6 +25,8 @@ add_library(citra-android SHARED
game_settings.h game_settings.h
id_cache.cpp id_cache.cpp
id_cache.h id_cache.h
lodepng_image_interface.cpp
lodepng_image_interface.h
mic.cpp mic.cpp
mic.h mic.h
native.cpp 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 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) set(CPACK_PACKAGE_EXECUTABLES ${CPACK_PACKAGE_EXECUTABLES} citra-android)

View file

@ -179,6 +179,12 @@ void Config::ReadValues() {
Settings::values.cardboard_y_shift = Settings::values.cardboard_y_shift =
static_cast<int>(sdl2_config->GetInteger("Layout", "cardboard_y_shift", 0)); static_cast<int>(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 // Audio
Settings::values.enable_dsp_lle = sdl2_config->GetBoolean("Audio", "enable_dsp_lle", false); Settings::values.enable_dsp_lle = sdl2_config->GetBoolean("Audio", "enable_dsp_lle", false);
Settings::values.enable_dsp_lle_multithread = Settings::values.enable_dsp_lle_multithread =

View file

@ -209,6 +209,19 @@ cardboard_x_shift =
# -100 - 100: Screen Y-Coordinate shift as a percentage of empty space. 0 (default) # -100 - 100: Screen Y-Coordinate shift as a percentage of empty space. 0 (default)
cardboard_y_shift = 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] [Audio]
# Whether or not to enable DSP LLE # Whether or not to enable DSP LLE
# 0 (default): No, 1: Yes # 0 (default): No, 1: Yes

View file

@ -0,0 +1,29 @@
// Copyright 2019 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <lodepng.h>
#include "common/logging/log.h"
#include "jni/lodepng_image_interface.h"
bool LodePNGImageInterface::DecodePNG(std::vector<u8>& 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<u8>& 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;
}

View file

@ -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<u8>& dst, u32& width, u32& height, const std::string& path) override;
bool EncodePNG(const std::string& path, const std::vector<u8>& src, u32 width,
u32 height) override;
};

View file

@ -38,6 +38,7 @@
#include "jni/game_settings.h" #include "jni/game_settings.h"
#include "jni/id_cache.h" #include "jni/id_cache.h"
#include "jni/input_manager.h" #include "jni/input_manager.h"
#include "jni/lodepng_image_interface.h"
#include "jni/mic.h" #include "jni/mic.h"
#include "jni/native.h" #include "jni/native.h"
#include "jni/ndk_motion.h" #include "jni/ndk_motion.h"
@ -174,6 +175,9 @@ static Core::System::ResultStatus RunCitra(const std::string& filepath) {
system.RegisterMiiSelector(std::make_shared<MiiSelector::AndroidMiiSelector>()); system.RegisterMiiSelector(std::make_shared<MiiSelector::AndroidMiiSelector>());
system.RegisterSoftwareKeyboard(std::make_shared<SoftwareKeyboard::AndroidKeyboard>()); system.RegisterSoftwareKeyboard(std::make_shared<SoftwareKeyboard::AndroidKeyboard>());
// Register generic image interface
Core::System::GetInstance().RegisterImageInterface(std::make_shared<LodePNGImageInterface>());
// Register real Mic factory // Register real Mic factory
Frontend::Mic::RegisterRealMicFactory(std::make_unique<Mic::AndroidFactory>()); Frontend::Mic::RegisterRealMicFactory(std::make_unique<Mic::AndroidFactory>());

View file

@ -103,7 +103,13 @@
<string name="use_shader_jit">Use shader JIT</string> <string name="use_shader_jit">Use shader JIT</string>
<string name="use_disk_shader_cache">Use disk shader cache</string> <string name="use_disk_shader_cache">Use disk shader cache</string>
<string name="use_disk_shader_cache_description">Reduce stuttering by storing and loading generated shaders to disk. It cannot be used without Enabling Hardware Shader.</string> <string name="use_disk_shader_cache_description">Reduce stuttering by storing and loading generated shaders to disk. It cannot be used without Enabling Hardware Shader.</string>
<string name="utility">Utility</string>
<string name="dump_textures">Dump textures</string>
<string name="dump_textures_description">Dumps textures to dump/textures/[GAME ID]</string>
<string name="custom_textures">Use custom textures</string>
<string name="custom_textures_description">Uses custom textures found in load/textures/[GAME ID]</string>
<string name="preload_textures">Preload custom textures</string>
<string name="preload_textures_description">Loads all custom textures into memory. This feature can use a lot of memory.</string>
<!-- Premium strings --> <!-- Premium strings -->
<string name="premium_text">Premium</string> <string name="premium_text">Premium</string>
<string name="premium_settings_upsell">Upgrade to Premium and support Citra!</string> <string name="premium_settings_upsell">Upgrade to Premium and support Citra!</string>