From 7ae0c260beb958ea4f92de37ab0485d4fa438598 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 | 10 +++ Source/Android/jni/AchievementAdapter.cpp | 24 ++++++ Source/Android/jni/CMakeLists.txt | 1 + Source/Android/jni/Config/NativeConfig.cpp | 4 + 10 files changed, 178 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 0000000000..345daf54a1 --- /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 0b6945ff13..47545c5402 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", + true + ), + 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 cd5bdb51eb..a72d6f59f9 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 @@ -120,6 +120,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" @@ -138,5 +139,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 0bfcb96d6c..74556b07d9 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 6a294ee139..b9974f09e4 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 @@ -264,6 +264,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 25acccb2fc..a5ee2f28df 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 51406cd7e3..3bb90c8d31 100644 --- a/Source/Android/app/src/main/res/values/strings.xml +++ b/Source/Android/app/src/main/res/values/strings.xml @@ -77,6 +77,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 @@ -952,4 +953,13 @@ 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 Discord Presence + Enable Progress Notifications diff --git a/Source/Android/jni/AchievementAdapter.cpp b/Source/Android/jni/AchievementAdapter.cpp new file mode 100644 index 0000000000..119ecbbd6f --- /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 be200affa9..b825fa314b 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 f367c5e162..8478174dae 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);