diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/Settings.java b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/Settings.java index 0a9fa0868..f5456d2ff 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/Settings.java +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/Settings.java @@ -71,7 +71,7 @@ public class Settings { } } else { // custom game settings - sections.putAll(SettingsFile.readFile("../GameSettings/" + gameId, view)); + sections.putAll(SettingsFile.readCustomGameSettings(gameId, view)); } } @@ -98,8 +98,7 @@ public class Settings { // custom game settings view.showToastMessage("Saved settings for " + gameId, false); - TreeMap iniSections = new TreeMap<>(sections); - SettingsFile.saveFile("../GameSettings/" + gameId, iniSections, view); + SettingsFile.saveCustomGameSettings(gameId, sections); } } diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/utils/SettingsFile.java b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/utils/SettingsFile.java index d8e700408..038dbe040 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/utils/SettingsFile.java +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/utils/SettingsFile.java @@ -2,6 +2,7 @@ package org.citra.citra_emu.features.settings.utils; import androidx.annotation.NonNull; +import org.citra.citra_emu.NativeLibrary; import org.citra.citra_emu.features.settings.model.FloatSetting; import org.citra.citra_emu.features.settings.model.IntSetting; import org.citra.citra_emu.features.settings.model.Setting; @@ -9,6 +10,7 @@ import org.citra.citra_emu.features.settings.model.SettingSection; import org.citra.citra_emu.features.settings.model.Settings; import org.citra.citra_emu.features.settings.model.StringSetting; import org.citra.citra_emu.features.settings.ui.SettingsActivityView; +import org.citra.citra_emu.utils.BiMap; import org.citra.citra_emu.utils.DirectoryInitialization; import org.citra.citra_emu.utils.Log; import org.ini4j.Wini; @@ -21,6 +23,7 @@ import java.io.IOException; import java.util.HashMap; import java.util.Set; import java.util.TreeMap; +import java.util.TreeSet; /** * Contains static methods for interacting with .ini files in which settings are stored. @@ -99,6 +102,13 @@ public final class SettingsFile { public static final String KEY_LOG_FILTER = "log_filter"; + private static BiMap sectionsMap = new BiMap<>(); + + static { + //TODO: Add members to sectionsMap when game-specific settings are added + } + + private SettingsFile() { } @@ -107,12 +117,12 @@ public final class SettingsFile { * effectively a HashMap of key/value settings. If unsuccessful, outputs an error telling why it * failed. * - * @param fileName The name of the settings file without a path or extension. - * @param view The current view. + * @param fileName The name of the settings file without a path or extension. + * @param isCustomGame + * @param view The current view. * @return An Observable that emits a HashMap of the file's contents, then completes. */ - public static HashMap readFile(final String fileName, - SettingsActivityView view) { + static HashMap readFile(final String fileName, boolean isCustomGame, SettingsActivityView view) { HashMap sections = new Settings.SettingsSectionMap(); File ini = getSettingsFile(fileName); @@ -125,7 +135,7 @@ public final class SettingsFile { SettingSection current = null; for (String line; (line = reader.readLine()) != null; ) { if (line.startsWith("[") && line.endsWith("]")) { - current = sectionFromLine(line); + current = sectionFromLine(line, isCustomGame); sections.put(current.getName(), current); } else if ((current != null)) { Setting setting = settingFromLine(current, line); @@ -153,6 +163,23 @@ public final class SettingsFile { return sections; } + public static HashMap readFile(final String fileName, SettingsActivityView view) { + return readFile(fileName, false, view); + } + + /** + * Reads a given .ini file from disk and returns it as a HashMap of SettingSections, themselves + * effectively a HashMap of key/value settings. If unsuccessful, outputs an error telling why it + * failed. + * + * @param gameId the id of the game to load it's settings. + * @param view The current view. + */ + public static HashMap readCustomGameSettings(final String gameId, SettingsActivityView view) { + String fileName = "../GameSettings/" + gameId; + return readFile(fileName, true, view); + } + /** * Saves a Settings HashMap to a given .ini file on disk. If unsuccessful, outputs an error * telling why it failed. @@ -180,14 +207,50 @@ public final class SettingsFile { } } + + public static void saveCustomGameSettings(final String gameId, final HashMap sections) { + Set sortedSections = new TreeSet<>(sections.keySet()); + + for (String sectionKey : sortedSections) { + SettingSection section = sections.get(sectionKey); + + HashMap settings = section.getSettings(); + Set sortedKeySet = new TreeSet<>(settings.keySet()); + + for (String settingKey : sortedKeySet) { + Setting setting = settings.get(settingKey); + NativeLibrary.SetUserSetting(gameId, mapSectionNameFromIni(section.getName()), setting.getKey(), setting.getValueAsString()); + } + } + } + + private static String mapSectionNameFromIni(String generalSectionName) { + if (sectionsMap.getForward(generalSectionName) != null) { + return sectionsMap.getForward(generalSectionName); + } + + return generalSectionName; + } + + private static String mapSectionNameToIni(String generalSectionName) { + if (sectionsMap.getBackward(generalSectionName) != null) { + return sectionsMap.getBackward(generalSectionName); + } + + return generalSectionName; + } + @NonNull private static File getSettingsFile(String fileName) { return new File( DirectoryInitialization.getUserDirectory() + "/config/" + fileName + ".ini"); } - private static SettingSection sectionFromLine(String line) { + private static SettingSection sectionFromLine(String line, boolean isCustomGame) { String sectionName = line.substring(1, line.length() - 1); + if (isCustomGame) { + sectionName = mapSectionNameToIni(sectionName); + } return new SettingSection(sectionName); } diff --git a/src/android/app/src/main/java/org/citra/citra_emu/utils/BiMap.java b/src/android/app/src/main/java/org/citra/citra_emu/utils/BiMap.java new file mode 100644 index 000000000..dfbab1780 --- /dev/null +++ b/src/android/app/src/main/java/org/citra/citra_emu/utils/BiMap.java @@ -0,0 +1,22 @@ +package org.citra.citra_emu.utils; + +import java.util.HashMap; +import java.util.Map; + +public class BiMap { + private Map forward = new HashMap(); + private Map backward = new HashMap(); + + public synchronized void add(K key, V value) { + forward.put(key, value); + backward.put(value, key); + } + + public synchronized V getForward(K key) { + return forward.get(key); + } + + public synchronized K getBackward(V key) { + return backward.get(key); + } +}