From 98e28178024decb67fa6bd844d2188d8c2b5017d Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sat, 23 Jul 2022 17:20:57 +0200 Subject: [PATCH 1/5] Android: Add setting for enabling graphics mods --- .../dolphinemu/features/settings/model/BooleanSetting.java | 1 + .../features/settings/ui/SettingsFragmentPresenter.java | 4 +++- Source/Android/app/src/main/res/values/strings.xml | 4 +++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/BooleanSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/BooleanSetting.java index 44ee61ed7124..d09aaa75b103 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/BooleanSetting.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/BooleanSetting.java @@ -200,6 +200,7 @@ public enum BooleanSetting implements AbstractBooleanSetting "WaitForShadersBeforeStarting", false), GFX_SAVE_TEXTURE_CACHE_TO_STATE(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "SaveTextureCacheToState", true), + GFX_MODS_ENABLE(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "EnableMods", false), GFX_ENHANCE_FORCE_FILTERING(Settings.FILE_GFX, Settings.SECTION_GFX_ENHANCEMENTS, "ForceFiltering", false), diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.java index 8dda6b64c629..137d2e3dc5cc 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.java @@ -756,7 +756,9 @@ private void addHackSettings(ArrayList sl) private void addAdvancedGraphicsSettings(ArrayList sl) { - sl.add(new HeaderSetting(mContext, R.string.custom_textures, 0)); + sl.add(new HeaderSetting(mContext, R.string.gfx_mods_and_custom_textures, 0)); + sl.add(new CheckBoxSetting(mContext, BooleanSetting.GFX_MODS_ENABLE, + R.string.gfx_mods, R.string.gfx_mods_description)); sl.add(new CheckBoxSetting(mContext, BooleanSetting.GFX_HIRES_TEXTURES, R.string.load_custom_texture, R.string.load_custom_texture_description)); sl.add(new CheckBoxSetting(mContext, BooleanSetting.GFX_CACHE_HIRES_TEXTURES, diff --git a/Source/Android/app/src/main/res/values/strings.xml b/Source/Android/app/src/main/res/values/strings.xml index 78278fb96ba2..8ae9374a50b5 100644 --- a/Source/Android/app/src/main/res/values/strings.xml +++ b/Source/Android/app/src/main/res/values/strings.xml @@ -319,7 +319,9 @@ This causes a delay when launching games, but will reduce stuttering early on. Advanced - Custom Textures + Graphics Mods and Custom Textures + Graphics Mods + Loads graphics mods from User/Load/GraphicsMods/. Load Custom Textures Loads custom textures from User/Load/Textures/<game_id>/ and User/Load/DynamicInputTextures/<game_id>/. Prefetch Custom Textures From 41a26f76fae1e580f99c471dc70ea420f3d598e6 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sat, 23 Jul 2022 14:45:26 +0200 Subject: [PATCH 2/5] Android: Add Cheat.supportsCode method Patches, AR codes and Gecko codes have an associated code that the GUI can show, but graphics mods don't. --- .../dolphinemu/features/cheats/model/AbstractCheat.java | 5 +++++ .../dolphinemu/dolphinemu/features/cheats/model/Cheat.java | 7 ++++++- .../features/cheats/ui/CheatDetailsFragment.java | 5 +++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/model/AbstractCheat.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/model/AbstractCheat.java index 9a86d585330f..2c33ccc61633 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/model/AbstractCheat.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/model/AbstractCheat.java @@ -9,6 +9,11 @@ public abstract class AbstractCheat implements Cheat { private Runnable mChangedCallback = null; + public boolean supportsCode() + { + return true; + } + public int trySet(@NonNull String name, @NonNull String creator, @NonNull String notes, @NonNull String code) { diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/model/Cheat.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/model/Cheat.java index 75a3befc6f9a..142931b9cba5 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/model/Cheat.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/model/Cheat.java @@ -17,6 +17,8 @@ public interface Cheat boolean supportsNotes(); + boolean supportsCode(); + @NonNull String getName(); @@ -33,7 +35,10 @@ default String getNotes() } @NonNull - String getCode(); + default String getCode() + { + return ""; + } int trySet(@NonNull String name, @NonNull String creator, @NonNull String notes, @NonNull String code); diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/ui/CheatDetailsFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/ui/CheatDetailsFragment.java index e5a027f64ba5..9c207996bb02 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/ui/CheatDetailsFragment.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/ui/CheatDetailsFragment.java @@ -31,6 +31,7 @@ public class CheatDetailsFragment extends Fragment private EditText mEditCreator; private TextView mLabelNotes; private EditText mEditNotes; + private TextView mLabelCode; private EditText mEditCode; private Button mButtonDelete; private Button mButtonEdit; @@ -59,6 +60,7 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat mEditCreator = view.findViewById(R.id.edit_creator); mLabelNotes = view.findViewById(R.id.label_notes); mEditNotes = view.findViewById(R.id.edit_notes); + mLabelCode = view.findViewById(R.id.label_code); mEditCode = view.findViewById(R.id.edit_code); mButtonDelete = view.findViewById(R.id.button_delete); mButtonEdit = view.findViewById(R.id.button_edit); @@ -158,10 +160,13 @@ private void onSelectedCheatUpdated(@Nullable Cheat cheat) int creatorVisibility = cheat != null && cheat.supportsCreator() ? View.VISIBLE : View.GONE; int notesVisibility = cheat != null && cheat.supportsNotes() ? View.VISIBLE : View.GONE; + int codeVisibility = cheat != null && cheat.supportsCode() ? View.VISIBLE : View.GONE; mLabelCreator.setVisibility(creatorVisibility); mEditCreator.setVisibility(creatorVisibility); mLabelNotes.setVisibility(notesVisibility); mEditNotes.setVisibility(notesVisibility); + mLabelCode.setVisibility(codeVisibility); + mEditCode.setVisibility(codeVisibility); boolean userDefined = cheat != null && cheat.getUserDefined(); mButtonDelete.setEnabled(userDefined); From 45f6d36c4581b37d6b3eff0a8004301d685adf55 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sat, 23 Jul 2022 14:51:18 +0200 Subject: [PATCH 3/5] Android: Split AbstractCheat into ReadOnlyCheat and AbstractCheat ReadOnlyCheat will be used by graphics mods. --- .../features/cheats/model/AbstractCheat.java | 24 +------------ .../features/cheats/model/ReadOnlyCheat.java | 36 +++++++++++++++++++ 2 files changed, 37 insertions(+), 23 deletions(-) create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/model/ReadOnlyCheat.java diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/model/AbstractCheat.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/model/AbstractCheat.java index 2c33ccc61633..d672013b4e79 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/model/AbstractCheat.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/model/AbstractCheat.java @@ -3,12 +3,9 @@ package org.dolphinemu.dolphinemu.features.cheats.model; import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -public abstract class AbstractCheat implements Cheat +public abstract class AbstractCheat extends ReadOnlyCheat { - private Runnable mChangedCallback = null; - public boolean supportsCode() { return true; @@ -43,25 +40,6 @@ public int trySet(@NonNull String name, @NonNull String creator, @NonNull String return result; } - public void setEnabled(boolean enabled) - { - setEnabledImpl(enabled); - onChanged(); - } - - public void setChangedCallback(@Nullable Runnable callback) - { - mChangedCallback = callback; - } - - protected void onChanged() - { - if (mChangedCallback != null) - mChangedCallback.run(); - } - protected abstract int trySetImpl(@NonNull String name, @NonNull String creator, @NonNull String notes, @NonNull String code); - - protected abstract void setEnabledImpl(boolean enabled); } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/model/ReadOnlyCheat.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/model/ReadOnlyCheat.java new file mode 100644 index 000000000000..9751c414f851 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/model/ReadOnlyCheat.java @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +package org.dolphinemu.dolphinemu.features.cheats.model; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +public abstract class ReadOnlyCheat implements Cheat +{ + private Runnable mChangedCallback = null; + + public int trySet(@NonNull String name, @NonNull String creator, @NonNull String notes, + @NonNull String code) + { + throw new UnsupportedOperationException(); + } + + public void setEnabled(boolean enabled) + { + setEnabledImpl(enabled); + onChanged(); + } + + public void setChangedCallback(@Nullable Runnable callback) + { + mChangedCallback = callback; + } + + protected void onChanged() + { + if (mChangedCallback != null) + mChangedCallback.run(); + } + + protected abstract void setEnabledImpl(boolean enabled); +} From 8f410bff15e1549a3f54e33ec0f4cf511ebea7df Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sat, 23 Jul 2022 17:14:26 +0200 Subject: [PATCH 4/5] Android: Add graphics mods support to CheatsActivity --- .../cheats/model/CheatsViewModel.java | 24 +++++ .../features/cheats/model/GraphicsMod.java | 61 ++++++++++++ .../cheats/model/GraphicsModGroup.java | 27 ++++++ .../features/cheats/ui/CheatsAdapter.java | 16 +++- .../app/src/main/res/values/strings.xml | 1 + Source/Android/jni/AndroidCommon/IDCache.cpp | 57 ++++++++++++ Source/Android/jni/AndroidCommon/IDCache.h | 8 ++ Source/Android/jni/CMakeLists.txt | 2 + Source/Android/jni/Cheats/GraphicsMod.cpp | 53 +++++++++++ .../Android/jni/Cheats/GraphicsModGroup.cpp | 92 +++++++++++++++++++ .../Config/GraphicsModListWidget.cpp | 17 +--- .../Config/GraphicsModGroup.cpp | 5 + .../Config/GraphicsModGroup.h | 1 + 13 files changed, 349 insertions(+), 15 deletions(-) create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/model/GraphicsMod.java create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/model/GraphicsModGroup.java create mode 100644 Source/Android/jni/Cheats/GraphicsMod.cpp create mode 100644 Source/Android/jni/Cheats/GraphicsModGroup.cpp diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/model/CheatsViewModel.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/model/CheatsViewModel.java index 023862831901..4d9900c16869 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/model/CheatsViewModel.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/model/CheatsViewModel.java @@ -24,10 +24,13 @@ public class CheatsViewModel extends ViewModel private final MutableLiveData mGeckoCheatsDownloadedEvent = new MutableLiveData<>(null); private final MutableLiveData mOpenDetailsViewEvent = new MutableLiveData<>(false); + private GraphicsModGroup mGraphicsModGroup; + private ArrayList mGraphicsMods; private ArrayList mPatchCheats; private ArrayList mARCheats; private ArrayList mGeckoCheats; + private boolean mGraphicsModsNeedSaving = false; private boolean mPatchCheatsNeedSaving = false; private boolean mARCheatsNeedSaving = false; private boolean mGeckoCheatsNeedSaving = false; @@ -37,13 +40,23 @@ public void load(String gameID, int revision) if (mLoaded) return; + mGraphicsModGroup = GraphicsModGroup.load(gameID); + mGraphicsMods = new ArrayList<>(); + Collections.addAll(mGraphicsMods, mGraphicsModGroup.getMods()); + mPatchCheats = new ArrayList<>(); Collections.addAll(mPatchCheats, PatchCheat.loadCodes(gameID, revision)); + mARCheats = new ArrayList<>(); Collections.addAll(mARCheats, ARCheat.loadCodes(gameID, revision)); + mGeckoCheats = new ArrayList<>(); Collections.addAll(mGeckoCheats, GeckoCheat.loadCodes(gameID, revision)); + for (GraphicsMod mod : mGraphicsMods) + { + mod.setChangedCallback(() -> mGraphicsModsNeedSaving = true); + } for (PatchCheat cheat : mPatchCheats) { cheat.setChangedCallback(() -> mPatchCheatsNeedSaving = true); @@ -62,6 +75,12 @@ public void load(String gameID, int revision) public void saveIfNeeded(String gameID, int revision) { + if (mGraphicsModsNeedSaving) + { + mGraphicsModGroup.save(); + mGraphicsModsNeedSaving = false; + } + if (mPatchCheatsNeedSaving) { PatchCheat.saveCodes(gameID, revision, mPatchCheats.toArray(new PatchCheat[0])); @@ -280,6 +299,11 @@ public void openDetailsView() mOpenDetailsViewEvent.setValue(false); } + public ArrayList getGraphicsMods() + { + return mGraphicsMods; + } + public ArrayList getPatchCheats() { return mPatchCheats; diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/model/GraphicsMod.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/model/GraphicsMod.java new file mode 100644 index 000000000000..241d15093fbe --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/model/GraphicsMod.java @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +package org.dolphinemu.dolphinemu.features.cheats.model; + +import androidx.annotation.Keep; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +public class GraphicsMod extends ReadOnlyCheat +{ + @Keep + private final long mPointer; + + // When a C++ GraphicsModGroup object is destroyed, it also destroys the GraphicsMods it owns. + // To avoid getting dangling pointers, we keep a reference to the GraphicsModGroup here. + @Keep + private final GraphicsModGroup mParent; + + @Keep + private GraphicsMod(long pointer, GraphicsModGroup parent) + { + mPointer = pointer; + mParent = parent; + } + + public boolean supportsCreator() + { + return true; + } + + public boolean supportsNotes() + { + return true; + } + + public boolean supportsCode() + { + return false; + } + + @NonNull + public native String getName(); + + @NonNull + public native String getCreator(); + + @NonNull + public native String getNotes(); + + public boolean getUserDefined() + { + // Technically graphics mods can be user defined, but we don't support editing graphics mods + // in the GUI, and editability is what this really controls + return false; + } + + public native boolean getEnabled(); + + @Override + protected native void setEnabledImpl(boolean enabled); +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/model/GraphicsModGroup.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/model/GraphicsModGroup.java new file mode 100644 index 000000000000..0cb0a3c456c8 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/model/GraphicsModGroup.java @@ -0,0 +1,27 @@ +package org.dolphinemu.dolphinemu.features.cheats.model; + +import androidx.annotation.Keep; +import androidx.annotation.NonNull; + +public class GraphicsModGroup +{ + @Keep + private final long mPointer; + + @Keep + private GraphicsModGroup(long pointer) + { + mPointer = pointer; + } + + @Override + public native void finalize(); + + @NonNull + public native GraphicsMod[] getMods(); + + public native void save(); + + @NonNull + public static native GraphicsModGroup load(String gameId); +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/ui/CheatsAdapter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/ui/CheatsAdapter.java index ec256cf6e2a6..e5be47a3f156 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/ui/CheatsAdapter.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/ui/CheatsAdapter.java @@ -13,6 +13,7 @@ import org.dolphinemu.dolphinemu.features.cheats.model.ARCheat; import org.dolphinemu.dolphinemu.features.cheats.model.CheatsViewModel; import org.dolphinemu.dolphinemu.features.cheats.model.GeckoCheat; +import org.dolphinemu.dolphinemu.features.cheats.model.GraphicsMod; import org.dolphinemu.dolphinemu.features.cheats.model.PatchCheat; import java.util.ArrayList; @@ -90,8 +91,8 @@ public void onBindViewHolder(@NonNull CheatItemViewHolder holder, int position) @Override public int getItemCount() { - return mViewModel.getARCheats().size() + mViewModel.getGeckoCheats().size() + - mViewModel.getPatchCheats().size() + 7; + return mViewModel.getGraphicsMods().size() + mViewModel.getPatchCheats().size() + + mViewModel.getARCheats().size() + mViewModel.getGeckoCheats().size() + 8; } @Override @@ -108,6 +109,17 @@ private void addViewListeners(View view) private CheatItem getItemAt(int position) { + // Graphics mods + + if (position == 0) + return new CheatItem(CheatItem.TYPE_HEADER, R.string.cheats_header_graphics_mod); + position -= 1; + + ArrayList graphicsMods = mViewModel.getGraphicsMods(); + if (position < graphicsMods.size()) + return new CheatItem(graphicsMods.get(position)); + position -= graphicsMods.size(); + // Patches if (position == 0) diff --git a/Source/Android/app/src/main/res/values/strings.xml b/Source/Android/app/src/main/res/values/strings.xml index 8ae9374a50b5..7b1d1b7bf4a8 100644 --- a/Source/Android/app/src/main/res/values/strings.xml +++ b/Source/Android/app/src/main/res/values/strings.xml @@ -490,6 +490,7 @@ AR Codes Gecko Codes Patches + Graphics Mods Add New AR Code Add New Gecko Code Add New Patch diff --git a/Source/Android/jni/AndroidCommon/IDCache.cpp b/Source/Android/jni/AndroidCommon/IDCache.cpp index b125babb81a0..31511b485cbc 100644 --- a/Source/Android/jni/AndroidCommon/IDCache.cpp +++ b/Source/Android/jni/AndroidCommon/IDCache.cpp @@ -70,6 +70,14 @@ static jclass s_patch_cheat_class; static jfieldID s_patch_cheat_pointer; static jmethodID s_patch_cheat_constructor; +static jclass s_graphics_mod_group_class; +static jfieldID s_graphics_mod_group_pointer; +static jmethodID s_graphics_mod_group_constructor; + +static jclass s_graphics_mod_class; +static jfieldID s_graphics_mod_pointer; +static jmethodID s_graphics_mod_constructor; + static jclass s_riivolution_patches_class; static jfieldID s_riivolution_patches_pointer; @@ -331,6 +339,36 @@ jmethodID GetPatchCheatConstructor() return s_patch_cheat_constructor; } +jclass GetGraphicsModClass() +{ + return s_graphics_mod_class; +} + +jfieldID GetGraphicsModPointer() +{ + return s_graphics_mod_pointer; +} + +jmethodID GetGraphicsModConstructor() +{ + return s_graphics_mod_constructor; +} + +jclass GetGraphicsModGroupClass() +{ + return s_graphics_mod_group_class; +} + +jfieldID GetGraphicsModGroupPointer() +{ + return s_graphics_mod_group_pointer; +} + +jmethodID GetGraphicsModGroupConstructor() +{ + return s_graphics_mod_group_constructor; +} + jclass GetRiivolutionPatchesClass() { return s_riivolution_patches_class; @@ -480,6 +518,23 @@ JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) s_patch_cheat_constructor = env->GetMethodID(patch_cheat_class, "", "(J)V"); env->DeleteLocalRef(patch_cheat_class); + const jclass graphics_mod_group_class = + env->FindClass("org/dolphinemu/dolphinemu/features/cheats/model/GraphicsModGroup"); + s_graphics_mod_group_class = + reinterpret_cast(env->NewGlobalRef(graphics_mod_group_class)); + s_graphics_mod_group_pointer = env->GetFieldID(graphics_mod_group_class, "mPointer", "J"); + s_graphics_mod_group_constructor = env->GetMethodID(graphics_mod_group_class, "", "(J)V"); + env->DeleteLocalRef(graphics_mod_group_class); + + const jclass graphics_mod_class = + env->FindClass("org/dolphinemu/dolphinemu/features/cheats/model/GraphicsMod"); + s_graphics_mod_class = reinterpret_cast(env->NewGlobalRef(graphics_mod_class)); + s_graphics_mod_pointer = env->GetFieldID(graphics_mod_class, "mPointer", "J"); + s_graphics_mod_constructor = + env->GetMethodID(graphics_mod_class, "", + "(JLorg/dolphinemu/dolphinemu/features/cheats/model/GraphicsModGroup;)V"); + env->DeleteLocalRef(graphics_mod_class); + const jclass riivolution_patches_class = env->FindClass("org/dolphinemu/dolphinemu/features/riivolution/model/RiivolutionPatches"); s_riivolution_patches_class = @@ -516,6 +571,8 @@ JNIEXPORT void JNI_OnUnload(JavaVM* vm, void* reserved) env->DeleteGlobalRef(s_ar_cheat_class); env->DeleteGlobalRef(s_gecko_cheat_class); env->DeleteGlobalRef(s_patch_cheat_class); + env->DeleteGlobalRef(s_graphics_mod_group_class); + env->DeleteGlobalRef(s_graphics_mod_class); env->DeleteGlobalRef(s_riivolution_patches_class); env->DeleteGlobalRef(s_wii_update_cb_class); } diff --git a/Source/Android/jni/AndroidCommon/IDCache.h b/Source/Android/jni/AndroidCommon/IDCache.h index 83eaa85894ca..58a0aa17bd06 100644 --- a/Source/Android/jni/AndroidCommon/IDCache.h +++ b/Source/Android/jni/AndroidCommon/IDCache.h @@ -69,6 +69,14 @@ jclass GetPatchCheatClass(); jfieldID GetPatchCheatPointer(); jmethodID GetPatchCheatConstructor(); +jclass GetGraphicsModGroupClass(); +jfieldID GetGraphicsModGroupPointer(); +jmethodID GetGraphicsModGroupConstructor(); + +jclass GetGraphicsModClass(); +jfieldID GetGraphicsModPointer(); +jmethodID GetGraphicsModConstructor(); + jclass GetRiivolutionPatchesClass(); jfieldID GetRiivolutionPatchesPointer(); diff --git a/Source/Android/jni/CMakeLists.txt b/Source/Android/jni/CMakeLists.txt index 74d9d90e037c..146019501ec3 100644 --- a/Source/Android/jni/CMakeLists.txt +++ b/Source/Android/jni/CMakeLists.txt @@ -2,6 +2,8 @@ add_library(main SHARED Cheats/ARCheat.cpp Cheats/Cheats.h Cheats/GeckoCheat.cpp + Cheats/GraphicsMod.cpp + Cheats/GraphicsModGroup.cpp Cheats/PatchCheat.cpp Config/NativeConfig.cpp Config/PostProcessing.cpp diff --git a/Source/Android/jni/Cheats/GraphicsMod.cpp b/Source/Android/jni/Cheats/GraphicsMod.cpp new file mode 100644 index 000000000000..627351f54661 --- /dev/null +++ b/Source/Android/jni/Cheats/GraphicsMod.cpp @@ -0,0 +1,53 @@ +// Copyright 2022 Dolphin Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include + +#include + +#include "VideoCommon/GraphicsModSystem/Config/GraphicsMod.h" +#include "jni/AndroidCommon/AndroidCommon.h" +#include "jni/AndroidCommon/IDCache.h" + +static GraphicsModConfig* GetPointer(JNIEnv* env, jobject obj) +{ + return reinterpret_cast( + env->GetLongField(obj, IDCache::GetGraphicsModPointer())); +} + +extern "C" { + +JNIEXPORT jstring JNICALL +Java_org_dolphinemu_dolphinemu_features_cheats_model_GraphicsMod_getName(JNIEnv* env, jobject obj) +{ + return ToJString(env, GetPointer(env, obj)->m_title); +} + +JNIEXPORT jstring JNICALL +Java_org_dolphinemu_dolphinemu_features_cheats_model_GraphicsMod_getCreator(JNIEnv* env, + jobject obj) +{ + return ToJString(env, GetPointer(env, obj)->m_author); +} + +JNIEXPORT jstring JNICALL +Java_org_dolphinemu_dolphinemu_features_cheats_model_GraphicsMod_getNotes(JNIEnv* env, jobject obj) +{ + return ToJString(env, GetPointer(env, obj)->m_description); +} + +JNIEXPORT jboolean JNICALL +Java_org_dolphinemu_dolphinemu_features_cheats_model_GraphicsMod_getEnabled(JNIEnv* env, + jobject obj) +{ + return static_cast(GetPointer(env, obj)->m_enabled); +} + +JNIEXPORT void JNICALL +Java_org_dolphinemu_dolphinemu_features_cheats_model_GraphicsMod_setEnabledImpl(JNIEnv* env, + jobject obj, + jboolean enabled) +{ + GetPointer(env, obj)->m_enabled = static_cast(enabled); +} +} diff --git a/Source/Android/jni/Cheats/GraphicsModGroup.cpp b/Source/Android/jni/Cheats/GraphicsModGroup.cpp new file mode 100644 index 000000000000..e7a9329b539b --- /dev/null +++ b/Source/Android/jni/Cheats/GraphicsModGroup.cpp @@ -0,0 +1,92 @@ +// Copyright 2022 Dolphin Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include + +#include +#include + +#include "VideoCommon/GraphicsModSystem/Config/GraphicsMod.h" +#include "VideoCommon/GraphicsModSystem/Config/GraphicsModGroup.h" +#include "jni/AndroidCommon/AndroidCommon.h" +#include "jni/AndroidCommon/IDCache.h" + +static GraphicsModGroupConfig* GetPointer(JNIEnv* env, jobject obj) +{ + return reinterpret_cast( + env->GetLongField(obj, IDCache::GetGraphicsModGroupPointer())); +} + +jobject GraphicsModToJava(JNIEnv* env, GraphicsModConfig* mod, jobject jGraphicsModGroup) +{ + return env->NewObject(IDCache::GetGraphicsModClass(), IDCache::GetGraphicsModConstructor(), + reinterpret_cast(mod), jGraphicsModGroup); +} + +extern "C" { + +JNIEXPORT void JNICALL +Java_org_dolphinemu_dolphinemu_features_cheats_model_GraphicsModGroup_finalize(JNIEnv* env, + jobject obj) +{ + delete GetPointer(env, obj); +} + +JNIEXPORT jobjectArray JNICALL +Java_org_dolphinemu_dolphinemu_features_cheats_model_GraphicsModGroup_getMods(JNIEnv* env, + jobject obj) +{ + GraphicsModGroupConfig* mod_group = GetPointer(env, obj); + + std::set groups; + + for (const GraphicsModConfig& mod : mod_group->GetMods()) + { + for (const GraphicsTargetGroupConfig& group : mod.m_groups) + groups.insert(group.m_name); + } + + std::vector mods; + + for (GraphicsModConfig& mod : mod_group->GetMods()) + { + // If no group matches the mod's features, or if the mod has no features, skip it + if (std::none_of(mod.m_features.begin(), mod.m_features.end(), + [&groups](const GraphicsModFeatureConfig& feature) { + return groups.count(feature.m_group) == 1; + })) + { + continue; + } + + mods.push_back(&mod); + } + + const jobjectArray array = + env->NewObjectArray(static_cast(mods.size()), IDCache::GetGraphicsModClass(), nullptr); + + jsize i = 0; + for (GraphicsModConfig* mod : mods) + env->SetObjectArrayElement(array, i++, GraphicsModToJava(env, mod, obj)); + + return array; +} + +JNIEXPORT void JNICALL +Java_org_dolphinemu_dolphinemu_features_cheats_model_GraphicsModGroup_save(JNIEnv* env, jobject obj) +{ + GetPointer(env, obj)->Save(); +} + +JNIEXPORT jobject JNICALL +Java_org_dolphinemu_dolphinemu_features_cheats_model_GraphicsModGroup_load(JNIEnv* env, jclass, + jstring jGameId) +{ + auto* mod_group = new GraphicsModGroupConfig(GetJString(env, jGameId)); + + mod_group->Load(); + + return env->NewObject(IDCache::GetGraphicsModGroupClass(), + IDCache::GetGraphicsModGroupConstructor(), mod_group); +} +} diff --git a/Source/Core/DolphinQt/Config/GraphicsModListWidget.cpp b/Source/Core/DolphinQt/Config/GraphicsModListWidget.cpp index cb9569d1d1c3..ac01158b2f6e 100644 --- a/Source/Core/DolphinQt/Config/GraphicsModListWidget.cpp +++ b/Source/Core/DolphinQt/Config/GraphicsModListWidget.cpp @@ -120,24 +120,15 @@ void GraphicsModListWidget::RefreshModList() std::set groups; - for (const auto& mod : m_mod_group.GetMods()) + for (const GraphicsModConfig& mod : m_mod_group.GetMods()) { - if (mod.m_groups.empty()) - continue; - - for (const auto& group : mod.m_groups) - { + for (const GraphicsTargetGroupConfig& group : mod.m_groups) groups.insert(group.m_name); - } } - for (const auto& mod : m_mod_group.GetMods()) + for (const GraphicsModConfig& mod : m_mod_group.GetMods()) { - // Group only mods shouldn't be shown - if (mod.m_features.empty()) - continue; - - // If the group doesn't exist in the available mod's features, skip + // If no group matches the mod's features, or if the mod has no features, skip it if (std::none_of(mod.m_features.begin(), mod.m_features.end(), [&groups](const GraphicsModFeatureConfig& feature) { return groups.count(feature.m_group) == 1; diff --git a/Source/Core/VideoCommon/GraphicsModSystem/Config/GraphicsModGroup.cpp b/Source/Core/VideoCommon/GraphicsModSystem/Config/GraphicsModGroup.cpp index 0d1ae30fb6d7..40685dff1b29 100644 --- a/Source/Core/VideoCommon/GraphicsModSystem/Config/GraphicsModGroup.cpp +++ b/Source/Core/VideoCommon/GraphicsModSystem/Config/GraphicsModGroup.cpp @@ -168,6 +168,11 @@ const std::vector& GraphicsModGroupConfig::GetMods() const return m_graphics_mods; } +std::vector& GraphicsModGroupConfig::GetMods() +{ + return m_graphics_mods; +} + GraphicsModConfig* GraphicsModGroupConfig::GetMod(const std::string& absolute_path) const { if (const auto iter = m_path_to_graphics_mod.find(absolute_path); diff --git a/Source/Core/VideoCommon/GraphicsModSystem/Config/GraphicsModGroup.h b/Source/Core/VideoCommon/GraphicsModSystem/Config/GraphicsModGroup.h index ace5127c5834..721c8e5c2c03 100644 --- a/Source/Core/VideoCommon/GraphicsModSystem/Config/GraphicsModGroup.h +++ b/Source/Core/VideoCommon/GraphicsModSystem/Config/GraphicsModGroup.h @@ -32,6 +32,7 @@ class GraphicsModGroupConfig u32 GetChangeCount() const; const std::vector& GetMods() const; + std::vector& GetMods(); GraphicsModConfig* GetMod(const std::string& absolute_path) const; From 3bd2bca38508965348bff45e4a77baa945abf33d Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sat, 23 Jul 2022 17:38:32 +0200 Subject: [PATCH 5/5] Android: Add warning if graphics mods are not enabled --- .../ui/CheatsDisabledWarningFragment.java | 16 ++++++++++++ .../GraphicsModsDisabledWarningFragment.java | 16 ++++++++++++ ...va => SettingDisabledWarningFragment.java} | 25 ++++++++++++++++--- .../main/res/layout/fragment_cheat_list.xml | 16 +++++++++--- .../res/layout/fragment_cheat_warning.xml | 3 ++- .../app/src/main/res/values/strings.xml | 1 + 6 files changed, 69 insertions(+), 8 deletions(-) create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/ui/CheatsDisabledWarningFragment.java create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/ui/GraphicsModsDisabledWarningFragment.java rename Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/ui/{CheatWarningFragment.java => SettingDisabledWarningFragment.java} (68%) diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/ui/CheatsDisabledWarningFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/ui/CheatsDisabledWarningFragment.java new file mode 100644 index 000000000000..f2dfd7b34148 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/ui/CheatsDisabledWarningFragment.java @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +package org.dolphinemu.dolphinemu.features.cheats.ui; + +import org.dolphinemu.dolphinemu.R; +import org.dolphinemu.dolphinemu.features.settings.model.BooleanSetting; +import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag; + +public class CheatsDisabledWarningFragment extends SettingDisabledWarningFragment +{ + public CheatsDisabledWarningFragment() + { + super(BooleanSetting.MAIN_ENABLE_CHEATS, MenuTag.CONFIG_GENERAL, + R.string.cheats_disabled_warning); + } +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/ui/GraphicsModsDisabledWarningFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/ui/GraphicsModsDisabledWarningFragment.java new file mode 100644 index 000000000000..eaf26f094b9b --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/ui/GraphicsModsDisabledWarningFragment.java @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +package org.dolphinemu.dolphinemu.features.cheats.ui; + +import org.dolphinemu.dolphinemu.R; +import org.dolphinemu.dolphinemu.features.settings.model.BooleanSetting; +import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag; + +public class GraphicsModsDisabledWarningFragment extends SettingDisabledWarningFragment +{ + public GraphicsModsDisabledWarningFragment() + { + super(BooleanSetting.GFX_MODS_ENABLE, MenuTag.ADVANCED_GRAPHICS, + R.string.gfx_mods_disabled_warning); + } +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/ui/CheatWarningFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/ui/SettingDisabledWarningFragment.java similarity index 68% rename from Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/ui/CheatWarningFragment.java rename to Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/ui/SettingDisabledWarningFragment.java index df6d9d94b06a..c239c5c9afb7 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/ui/CheatWarningFragment.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/ui/SettingDisabledWarningFragment.java @@ -7,21 +7,35 @@ import android.view.View; import android.view.ViewGroup; import android.widget.Button; +import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import org.dolphinemu.dolphinemu.R; -import org.dolphinemu.dolphinemu.features.settings.model.BooleanSetting; +import org.dolphinemu.dolphinemu.features.settings.model.AbstractBooleanSetting; import org.dolphinemu.dolphinemu.features.settings.model.Settings; import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag; import org.dolphinemu.dolphinemu.features.settings.ui.SettingsActivity; -public class CheatWarningFragment extends Fragment implements View.OnClickListener +public abstract class SettingDisabledWarningFragment extends Fragment + implements View.OnClickListener { private View mView; + private final AbstractBooleanSetting mSetting; + private final MenuTag mSettingShortcut; + private final int mText; + + public SettingDisabledWarningFragment(AbstractBooleanSetting setting, MenuTag settingShortcut, + int text) + { + mSetting = setting; + mSettingShortcut = settingShortcut; + mText = text; + } + @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @@ -35,6 +49,9 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat { mView = view; + TextView textView = view.findViewById(R.id.text_warning); + textView.setText(mText); + Button settingsButton = view.findViewById(R.id.button_settings); settingsButton.setOnClickListener(this); @@ -51,13 +68,13 @@ public void onResume() CheatsActivity activity = (CheatsActivity) requireActivity(); try (Settings settings = activity.loadGameSpecificSettings()) { - boolean cheatsEnabled = BooleanSetting.MAIN_ENABLE_CHEATS.getBoolean(settings); + boolean cheatsEnabled = mSetting.getBoolean(settings); mView.setVisibility(cheatsEnabled ? View.GONE : View.VISIBLE); } } public void onClick(View view) { - SettingsActivity.launch(requireContext(), MenuTag.CONFIG_GENERAL); + SettingsActivity.launch(requireContext(), mSettingShortcut); } } diff --git a/Source/Android/app/src/main/res/layout/fragment_cheat_list.xml b/Source/Android/app/src/main/res/layout/fragment_cheat_list.xml index 9c976ac40824..ad8ec880af39 100644 --- a/Source/Android/app/src/main/res/layout/fragment_cheat_list.xml +++ b/Source/Android/app/src/main/res/layout/fragment_cheat_list.xml @@ -6,13 +6,23 @@ android:layout_height="match_parent"> + + diff --git a/Source/Android/app/src/main/res/layout/fragment_cheat_warning.xml b/Source/Android/app/src/main/res/layout/fragment_cheat_warning.xml index d56a1160b640..6ed47961e2a0 100644 --- a/Source/Android/app/src/main/res/layout/fragment_cheat_warning.xml +++ b/Source/Android/app/src/main/res/layout/fragment_cheat_warning.xml @@ -1,5 +1,6 @@ File contained no codes. Downloaded %1$d codes. (added %2$d) Dolphin\'s cheat system is currently disabled. + Graphics mods are currently disabled. Settings