From b662cd93cec27540c15c3ab58bc9831863b9291b Mon Sep 17 00:00:00 2001 From: LillyJadeKatrin Date: Thu, 24 Apr 2025 07:51:01 -0400 Subject: [PATCH] Add Achievements submenu to Android settings --- .../settings/model/AchievementModel.kt | 11 +++ .../features/settings/model/BooleanSetting.kt | 43 +++++++++- .../features/settings/model/Settings.kt | 2 + .../features/settings/ui/MenuTag.kt | 1 + .../features/settings/ui/SettingsFragment.kt | 1 + .../settings/ui/SettingsFragmentPresenter.kt | 82 +++++++++++++++++++ .../app/src/main/res/values/strings.xml | 9 ++ Source/Android/jni/AchievementAdapter.cpp | 24 ++++++ Source/Android/jni/CMakeLists.txt | 1 + Source/Android/jni/Config/NativeConfig.cpp | 4 + 10 files changed, 177 insertions(+), 1 deletion(-) create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AchievementModel.kt create mode 100644 Source/Android/jni/AchievementAdapter.cpp diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AchievementModel.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AchievementModel.kt new file mode 100644 index 00000000000..345daf54a16 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AchievementModel.kt @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +package org.dolphinemu.dolphinemu.features.settings.model + +object AchievementModel { + @JvmStatic + external fun init() + + @JvmStatic + external fun shutdown() +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/BooleanSetting.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/BooleanSetting.kt index 0b6945ff130..1f8ef6e94bc 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/BooleanSetting.kt +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/BooleanSetting.kt @@ -883,6 +883,42 @@ enum class BooleanSetting( Settings.SECTION_LOGGER_OPTIONS, "WriteToFile", false + ), + ACHIEVEMENTS_ENABLED( + Settings.FILE_ACHIEVEMENTS, + Settings.SECTION_ACHIEVEMENTS, + "Enabled", + false + ), + ACHIEVEMENTS_HARDCORE_ENABLED( + Settings.FILE_ACHIEVEMENTS, + Settings.SECTION_ACHIEVEMENTS, + "HardcoreEnabled", + false + ), + ACHIEVEMENTS_UNOFFICIAL_ENABLED( + Settings.FILE_ACHIEVEMENTS, + Settings.SECTION_ACHIEVEMENTS, + "UnofficialEnabled", + false + ), + ACHIEVEMENTS_ENCORE_ENABLED( + Settings.FILE_ACHIEVEMENTS, + Settings.SECTION_ACHIEVEMENTS, + "EncoreEnabled", + false + ), + ACHIEVEMENTS_SPECTATOR_ENABLED( + Settings.FILE_ACHIEVEMENTS, + Settings.SECTION_ACHIEVEMENTS, + "SpectatorEnabled", + false + ), + ACHIEVEMENTS_PROGRESS_ENABLED( + Settings.FILE_ACHIEVEMENTS, + Settings.SECTION_ACHIEVEMENTS, + "ProgressEnabled", + true ); override val isOverridden: Boolean @@ -943,7 +979,12 @@ enum class BooleanSetting( MAIN_TIME_TRACKING, MAIN_EMULATE_SKYLANDER_PORTAL, MAIN_EMULATE_INFINITY_BASE, - MAIN_EMULATE_WII_SPEAK + MAIN_EMULATE_WII_SPEAK, + ACHIEVEMENTS_ENABLED, + ACHIEVEMENTS_HARDCORE_ENABLED, + ACHIEVEMENTS_UNOFFICIAL_ENABLED, + ACHIEVEMENTS_ENCORE_ENABLED, + ACHIEVEMENTS_SPECTATOR_ENABLED ) private val NOT_RUNTIME_EDITABLE: Set = HashSet(listOf(*NOT_RUNTIME_EDITABLE_ARRAY)) diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/Settings.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/Settings.kt index 32ad11b3e1f..9f91a4244c9 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/Settings.kt +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/Settings.kt @@ -104,6 +104,7 @@ class Settings : Closeable { const val FILE_GFX = "GFX" const val FILE_LOGGER = "Logger" const val FILE_WIIMOTE = "WiimoteNew" + const val FILE_ACHIEVEMENTS = "RetroAchievements" const val FILE_GAME_SETTINGS_ONLY = "GameSettingsOnly" const val SECTION_INI_ANDROID = "Android" const val SECTION_INI_ANDROID_OVERLAY_BUTTONS = "AndroidOverlayButtons" @@ -122,5 +123,6 @@ class Settings : Closeable { const val SECTION_EMULATED_USB_DEVICES = "EmulatedUSBDevices" const val SECTION_STEREOSCOPY = "Stereoscopy" const val SECTION_ANALYTICS = "Analytics" + const val SECTION_ACHIEVEMENTS = "Achievements" } } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/MenuTag.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/MenuTag.kt index 0bfcb96d6ce..74556b07d97 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/MenuTag.kt +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/MenuTag.kt @@ -14,6 +14,7 @@ enum class MenuTag { CONFIG_GAME_CUBE("config_gamecube"), CONFIG_SERIALPORT1("config_serialport1"), CONFIG_WII("config_wii"), + CONFIG_ACHIEVEMENTS("config_achievements"), CONFIG_ADVANCED("config_advanced"), CONFIG_LOG("config_log"), DEBUG("debug"), diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragment.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragment.kt index 991d3c3c2b9..513769a50da 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragment.kt +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragment.kt @@ -268,6 +268,7 @@ class SettingsFragment : Fragment(), SettingsFragmentView { titles[MenuTag.CONFIG_GAME_CUBE] = R.string.gamecube_submenu titles[MenuTag.CONFIG_SERIALPORT1] = R.string.serialport1_submenu titles[MenuTag.CONFIG_WII] = R.string.wii_submenu + titles[MenuTag.CONFIG_ACHIEVEMENTS] = R.string.achievements_submenu titles[MenuTag.CONFIG_ADVANCED] = R.string.advanced_submenu titles[MenuTag.DEBUG] = R.string.debug_submenu titles[MenuTag.GRAPHICS] = R.string.graphics_settings diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.kt index 25acccb2fc8..a5ee2f28df0 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.kt +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.kt @@ -111,6 +111,7 @@ class SettingsFragmentPresenter( MenuTag.CONFIG_PATHS -> addPathsSettings(sl) MenuTag.CONFIG_GAME_CUBE -> addGameCubeSettings(sl) MenuTag.CONFIG_WII -> addWiiSettings(sl) + MenuTag.CONFIG_ACHIEVEMENTS -> addAchievementSettings(sl); MenuTag.CONFIG_ADVANCED -> addAdvancedSettings(sl) MenuTag.GRAPHICS -> addGraphicsSettings(sl) MenuTag.CONFIG_SERIALPORT1 -> addSerialPortSubSettings(sl, serialPort1Type) @@ -200,6 +201,7 @@ class SettingsFragmentPresenter( sl.add(SubmenuSetting(context, R.string.paths_submenu, MenuTag.CONFIG_PATHS)) sl.add(SubmenuSetting(context, R.string.gamecube_submenu, MenuTag.CONFIG_GAME_CUBE)) sl.add(SubmenuSetting(context, R.string.wii_submenu, MenuTag.CONFIG_WII)) + sl.add(SubmenuSetting(context, R.string.achievements_submenu, MenuTag.CONFIG_ACHIEVEMENTS)) sl.add(SubmenuSetting(context, R.string.advanced_submenu, MenuTag.CONFIG_ADVANCED)) sl.add(SubmenuSetting(context, R.string.log_submenu, MenuTag.CONFIG_LOG)) sl.add(SubmenuSetting(context, R.string.debug_submenu, MenuTag.DEBUG)) @@ -914,6 +916,86 @@ class SettingsFragmentPresenter( ) } + private fun addAchievementSettings(sl: ArrayList) { + val achievementsEnabledSetting: AbstractBooleanSetting = object : AbstractBooleanSetting { + override val boolean: Boolean + get() = BooleanSetting.ACHIEVEMENTS_ENABLED.boolean + + override fun setBoolean(settings: Settings, newValue: Boolean) { + BooleanSetting.ACHIEVEMENTS_ENABLED.setBoolean(settings, newValue) + if (newValue) + AchievementModel.init() + else + AchievementModel.shutdown() + loadSettingsList() + } + + override val isOverridden: Boolean + get() = BooleanSetting.ACHIEVEMENTS_ENABLED.isOverridden + + override val isRuntimeEditable: Boolean + get() = BooleanSetting.ACHIEVEMENTS_ENABLED.isRuntimeEditable + + override fun delete(settings: Settings): Boolean { + val result = BooleanSetting.ACHIEVEMENTS_ENABLED.delete(settings) + AchievementModel.shutdown() + loadSettingsList() + return result + } + } + + sl.add( + SwitchSetting( + context, + achievementsEnabledSetting, + R.string.achievements_enabled, + 0 + ) + ) + if (BooleanSetting.ACHIEVEMENTS_ENABLED.boolean) { + sl.add( + SwitchSetting( + context, + BooleanSetting.ACHIEVEMENTS_HARDCORE_ENABLED, + R.string.achievements_hardcore_enabled, + 0 + ) + ) + sl.add( + SwitchSetting( + context, + BooleanSetting.ACHIEVEMENTS_UNOFFICIAL_ENABLED, + R.string.achievements_unofficial_enabled, + 0 + ) + ) + sl.add( + SwitchSetting( + context, + BooleanSetting.ACHIEVEMENTS_ENCORE_ENABLED, + R.string.achievements_encore_enabled, + 0 + ) + ) + sl.add( + SwitchSetting( + context, + BooleanSetting.ACHIEVEMENTS_SPECTATOR_ENABLED, + R.string.achievements_spectator_enabled, + 0 + ) + ) + sl.add( + SwitchSetting( + context, + BooleanSetting.ACHIEVEMENTS_PROGRESS_ENABLED, + R.string.achievements_progress_enabled, + 0 + ) + ) + } + } + private fun addAdvancedSettings(sl: ArrayList) { val SYNC_GPU_NEVER = 0 val SYNC_GPU_ON_IDLE_SKIP = 1 diff --git a/Source/Android/app/src/main/res/values/strings.xml b/Source/Android/app/src/main/res/values/strings.xml index 6342e35cb02..67ac68f75ef 100644 --- a/Source/Android/app/src/main/res/values/strings.xml +++ b/Source/Android/app/src/main/res/values/strings.xml @@ -75,6 +75,7 @@ Enable Cheats Speed Limit (0% = Unlimited) WARNING: Changing this from the default (100%) WILL break games and cause glitches. Please do not report bugs that occur with a non-default clock. + RetroAchievements GameCube IPL Settings Skip Main Menu @@ -953,4 +954,12 @@ It can efficiently compress both junk data and encrypted Wii data. Mute Wii Speak Missing Microphone Permission Wii Speak emulation requires microphone permission. You might need to restart the game for the permission to be effective. + + + Enable Achievements + Enable Hardcore Mode + Enable Unofficial Achievements + Enable Encore Mode + Enable Spectator Mode + Enable Progress Notifications diff --git a/Source/Android/jni/AchievementAdapter.cpp b/Source/Android/jni/AchievementAdapter.cpp new file mode 100644 index 00000000000..119ecbbd6fb --- /dev/null +++ b/Source/Android/jni/AchievementAdapter.cpp @@ -0,0 +1,24 @@ +// Copyright 2025 Dolphin Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include + +#include "Core/AchievementManager.h" +#include "jni/AndroidCommon/AndroidCommon.h" + +extern "C" { + +JNIEXPORT void JNICALL +Java_org_dolphinemu_dolphinemu_features_settings_model_AchievementModel_init(JNIEnv* env, jclass) +{ + AchievementManager::GetInstance().Init(nullptr); +} + +JNIEXPORT void JNICALL +Java_org_dolphinemu_dolphinemu_features_settings_model_AchievementModel_shutdown(JNIEnv* env, + jclass) +{ + AchievementManager::GetInstance().Shutdown(); +} + +} // extern "C" diff --git a/Source/Android/jni/CMakeLists.txt b/Source/Android/jni/CMakeLists.txt index be200affa9b..b825fa314b6 100644 --- a/Source/Android/jni/CMakeLists.txt +++ b/Source/Android/jni/CMakeLists.txt @@ -1,4 +1,5 @@ add_library(main SHARED + AchievementAdapter.cpp ActivityTracker.cpp Cheats/ARCheat.cpp Cheats/Cheats.h diff --git a/Source/Android/jni/Config/NativeConfig.cpp b/Source/Android/jni/Config/NativeConfig.cpp index f367c5e1627..8478174dae2 100644 --- a/Source/Android/jni/Config/NativeConfig.cpp +++ b/Source/Android/jni/Config/NativeConfig.cpp @@ -48,6 +48,10 @@ static Config::Location GetLocation(JNIEnv* env, jstring file, jstring section, { system = Config::System::GameSettingsOnly; } + else if (decoded_file == "RetroAchievements") + { + system = Config::System::Achievements; + } else { ASSERT(false);