summaryrefslogtreecommitdiffstats
path: root/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/Settings.kt
blob: a6251bafddfcc2d00cf0e763c5711c49df2a8161 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

package org.yuzu.yuzu_emu.features.settings.model

import android.text.TextUtils
import java.util.*
import org.yuzu.yuzu_emu.R
import org.yuzu.yuzu_emu.YuzuApplication
import org.yuzu.yuzu_emu.features.settings.ui.SettingsActivityView
import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile

class Settings {
    private var gameId: String? = null

    var isLoaded = false

    /**
     * A HashMap<String></String>, SettingSection> that constructs a new SettingSection instead of returning null
     * when getting a key not already in the map
     */
    class SettingsSectionMap : HashMap<String, SettingSection?>() {
        override operator fun get(key: String): SettingSection? {
            if (!super.containsKey(key)) {
                val section = SettingSection(key)
                super.put(key, section)
                return section
            }
            return super.get(key)
        }
    }

    var sections: HashMap<String, SettingSection?> = SettingsSectionMap()

    fun getSection(sectionName: String): SettingSection? {
        return sections[sectionName]
    }

    val isEmpty: Boolean
        get() = sections.isEmpty()

    fun loadSettings(view: SettingsActivityView? = null) {
        sections = SettingsSectionMap()
        loadYuzuSettings(view)
        if (!TextUtils.isEmpty(gameId)) {
            loadCustomGameSettings(gameId!!, view)
        }
        isLoaded = true
    }

    private fun loadYuzuSettings(view: SettingsActivityView?) {
        for ((fileName) in configFileSectionsMap) {
            sections.putAll(SettingsFile.readFile(fileName, view))
        }
    }

    private fun loadCustomGameSettings(gameId: String, view: SettingsActivityView?) {
        // Custom game settings
        mergeSections(SettingsFile.readCustomGameSettings(gameId, view))
    }

    private fun mergeSections(updatedSections: HashMap<String, SettingSection?>) {
        for ((key, updatedSection) in updatedSections) {
            if (sections.containsKey(key)) {
                val originalSection = sections[key]
                originalSection!!.mergeSection(updatedSection!!)
            } else {
                sections[key] = updatedSection
            }
        }
    }

    fun loadSettings(gameId: String, view: SettingsActivityView) {
        this.gameId = gameId
        loadSettings(view)
    }

    fun saveSettings(view: SettingsActivityView) {
        if (TextUtils.isEmpty(gameId)) {
            view.showToastMessage(
                YuzuApplication.appContext.getString(R.string.ini_saved),
                false
            )

            for ((fileName, sectionNames) in configFileSectionsMap) {
                val iniSections = TreeMap<String, SettingSection>()
                for (section in sectionNames) {
                    iniSections[section] = sections[section]!!
                }

                SettingsFile.saveFile(fileName, iniSections, view)
            }
        } else {
            // Custom game settings
            view.showToastMessage(
                YuzuApplication.appContext.getString(R.string.gameid_saved, gameId),
                false
            )

            SettingsFile.saveCustomGameSettings(gameId, sections)
        }
    }

    companion object {
        const val SECTION_GENERAL = "General"
        const val SECTION_SYSTEM = "System"
        const val SECTION_RENDERER = "Renderer"
        const val SECTION_AUDIO = "Audio"
        const val SECTION_CPU = "Cpu"
        const val SECTION_THEME = "Theme"
        const val SECTION_DEBUG = "Debug"

        const val PREF_MEMORY_WARNING_SHOWN = "MemoryWarningShown"

        const val PREF_OVERLAY_VERSION = "OverlayVersion"
        const val PREF_LANDSCAPE_OVERLAY_VERSION = "LandscapeOverlayVersion"
        const val PREF_PORTRAIT_OVERLAY_VERSION = "PortraitOverlayVersion"
        const val PREF_FOLDABLE_OVERLAY_VERSION = "FoldableOverlayVersion"
        val overlayLayoutPrefs = listOf(
            PREF_LANDSCAPE_OVERLAY_VERSION,
            PREF_PORTRAIT_OVERLAY_VERSION,
            PREF_FOLDABLE_OVERLAY_VERSION
        )

        const val PREF_CONTROL_SCALE = "controlScale"
        const val PREF_CONTROL_OPACITY = "controlOpacity"
        const val PREF_TOUCH_ENABLED = "isTouchEnabled"
        const val PREF_BUTTON_A = "buttonToggle0"
        const val PREF_BUTTON_B = "buttonToggle1"
        const val PREF_BUTTON_X = "buttonToggle2"
        const val PREF_BUTTON_Y = "buttonToggle3"
        const val PREF_BUTTON_L = "buttonToggle4"
        const val PREF_BUTTON_R = "buttonToggle5"
        const val PREF_BUTTON_ZL = "buttonToggle6"
        const val PREF_BUTTON_ZR = "buttonToggle7"
        const val PREF_BUTTON_PLUS = "buttonToggle8"
        const val PREF_BUTTON_MINUS = "buttonToggle9"
        const val PREF_BUTTON_DPAD = "buttonToggle10"
        const val PREF_STICK_L = "buttonToggle11"
        const val PREF_STICK_R = "buttonToggle12"
        const val PREF_BUTTON_STICK_L = "buttonToggle13"
        const val PREF_BUTTON_STICK_R = "buttonToggle14"
        const val PREF_BUTTON_HOME = "buttonToggle15"
        const val PREF_BUTTON_SCREENSHOT = "buttonToggle16"

        const val PREF_MENU_SETTINGS_JOYSTICK_REL_CENTER = "EmulationMenuSettings_JoystickRelCenter"
        const val PREF_MENU_SETTINGS_DPAD_SLIDE = "EmulationMenuSettings_DpadSlideEnable"
        const val PREF_MENU_SETTINGS_HAPTICS = "EmulationMenuSettings_Haptics"
        const val PREF_MENU_SETTINGS_SHOW_FPS = "EmulationMenuSettings_ShowFps"
        const val PREF_MENU_SETTINGS_SHOW_OVERLAY = "EmulationMenuSettings_ShowOverlay"

        const val PREF_FIRST_APP_LAUNCH = "FirstApplicationLaunch"
        const val PREF_THEME = "Theme"
        const val PREF_THEME_MODE = "ThemeMode"
        const val PREF_BLACK_BACKGROUNDS = "BlackBackgrounds"

        private val configFileSectionsMap: MutableMap<String, List<String>> = HashMap()

        val overlayPreferences = listOf(
            PREF_OVERLAY_VERSION,
            PREF_CONTROL_SCALE,
            PREF_CONTROL_OPACITY,
            PREF_TOUCH_ENABLED,
            PREF_BUTTON_A,
            PREF_BUTTON_B,
            PREF_BUTTON_X,
            PREF_BUTTON_Y,
            PREF_BUTTON_L,
            PREF_BUTTON_R,
            PREF_BUTTON_ZL,
            PREF_BUTTON_ZR,
            PREF_BUTTON_PLUS,
            PREF_BUTTON_MINUS,
            PREF_BUTTON_DPAD,
            PREF_STICK_L,
            PREF_STICK_R,
            PREF_BUTTON_HOME,
            PREF_BUTTON_SCREENSHOT,
            PREF_BUTTON_STICK_L,
            PREF_BUTTON_STICK_R
        )

        const val LayoutOption_Unspecified = 0
        const val LayoutOption_MobilePortrait = 4
        const val LayoutOption_MobileLandscape = 5

        init {
            configFileSectionsMap[SettingsFile.FILE_NAME_CONFIG] =
                listOf(
                    SECTION_GENERAL,
                    SECTION_SYSTEM,
                    SECTION_RENDERER,
                    SECTION_AUDIO,
                    SECTION_CPU
                )
        }
    }
}