Android: Implement game-specific settings overrides UI

This commit is contained in:
Greg Wicks 2018-02-16 13:47:52 -05:00
parent f3826b4e92
commit e19922c5de
14 changed files with 235 additions and 37 deletions

View File

@ -96,7 +96,6 @@ dependencies {
// Allows FRP-style asynchronous operations in Android. // Allows FRP-style asynchronous operations in Android.
implementation 'io.reactivex:rxandroid:1.2.1' implementation 'io.reactivex:rxandroid:1.2.1'
implementation 'com.nononsenseapps:filepicker:4.1.0' implementation 'com.nononsenseapps:filepicker:4.1.0'
} }

View File

@ -11,6 +11,7 @@ import android.content.Context;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.os.Message; import android.os.Message;
import android.content.res.AssetManager;
import android.view.Surface; import android.view.Surface;
import android.widget.Toast; import android.widget.Toast;
@ -231,6 +232,12 @@ public final class NativeLibrary
*/ */
public static native void onGamePadMoveEvent(String Device, int Axis, float Value); public static native void onGamePadMoveEvent(String Device, int Axis, float Value);
public static native String GetUserSetting(String gameID, String Section, String Key);
public static native void SetUserSetting(String gameID, String Section, String Key, String Value);
public static native void InitGameIni(String gameID);
/** /**
* Gets a value from a key in the given ini-based config file. * Gets a value from a key in the given ini-based config file.
* *

View File

@ -1,5 +1,7 @@
package org.dolphinemu.dolphinemu.adapters; package org.dolphinemu.dolphinemu.adapters;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.database.Cursor; import android.database.Cursor;
import android.database.DataSetObserver; import android.database.DataSetObserver;
import android.graphics.Rect; import android.graphics.Rect;
@ -8,15 +10,20 @@ import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Toast;
import org.dolphinemu.dolphinemu.R; import org.dolphinemu.dolphinemu.R;
import org.dolphinemu.dolphinemu.activities.EmulationActivity; import org.dolphinemu.dolphinemu.activities.EmulationActivity;
import org.dolphinemu.dolphinemu.dialogs.GameDetailsDialog;
import org.dolphinemu.dolphinemu.model.GameDatabase; import org.dolphinemu.dolphinemu.model.GameDatabase;
import org.dolphinemu.dolphinemu.services.DirectoryInitializationService;
import org.dolphinemu.dolphinemu.ui.settings.SettingsActivity;
import org.dolphinemu.dolphinemu.utils.Log; import org.dolphinemu.dolphinemu.utils.Log;
import org.dolphinemu.dolphinemu.utils.PicassoUtils; import org.dolphinemu.dolphinemu.utils.PicassoUtils;
import org.dolphinemu.dolphinemu.utils.SettingsFile;
import org.dolphinemu.dolphinemu.viewholders.GameViewHolder; import org.dolphinemu.dolphinemu.viewholders.GameViewHolder;
import java.io.File;
/** /**
* This adapter gets its information from a database Cursor. This fact, paired with the usage of * This adapter gets its information from a database Cursor. This fact, paired with the usage of
* ContentProviders and Loaders, allows for efficient display of a limited view into a (possibly) * ContentProviders and Loaders, allows for efficient display of a limited view into a (possibly)
@ -222,17 +229,46 @@ public final class GameAdapter extends RecyclerView.Adapter<GameViewHolder> impl
GameViewHolder holder = (GameViewHolder) view.getTag(); GameViewHolder holder = (GameViewHolder) view.getTag();
// Get the ID of the game we want to look at. // Get the ID of the game we want to look at.
// TODO This should be all we need to pass in, eventually. String gameId = (String) holder.gameId;
// String gameId = (String) holder.gameId;
FragmentActivity activity = (FragmentActivity) view.getContext(); FragmentActivity activity = (FragmentActivity) view.getContext();
GameDetailsDialog.newInstance(holder.title,
holder.description,
holder.country,
holder.company,
holder.path,
holder.screenshotPath).show(activity.getSupportFragmentManager(), "game_details");
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle("Game Settings")
.setItems(R.array.gameSettingsMenus, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case 0:
SettingsActivity.launch(activity, SettingsFile.FILE_NAME_DOLPHIN, gameId);
break;
case 1:
SettingsActivity.launch(activity, SettingsFile.FILE_NAME_GFX, gameId);
break;
case 2:
String path = DirectoryInitializationService.getUserDirectory() + "/GameSettings/" + gameId + ".ini";
File gameSettingsFile = new File(path);
if (gameSettingsFile.exists())
{
if (gameSettingsFile.delete())
{
Toast.makeText(view.getContext(), "Cleared settings for " + gameId, Toast.LENGTH_SHORT).show();
}
else
{
Toast.makeText(view.getContext(), "Unable to clear settings for " + gameId, Toast.LENGTH_SHORT).show();
}
}
else
{
Toast.makeText(view.getContext(), "No game settings to delete", Toast.LENGTH_SHORT).show();
}
break;
}
}
});
builder.show();
return true; return true;
} }

View File

@ -1,18 +1,28 @@
package org.dolphinemu.dolphinemu.adapters; package org.dolphinemu.dolphinemu.adapters;
import android.app.AlertDialog;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.support.v17.leanback.widget.ImageCardView; import android.support.v17.leanback.widget.ImageCardView;
import android.support.v17.leanback.widget.Presenter; import android.support.v17.leanback.widget.Presenter;
import android.support.v4.app.FragmentActivity;
import android.support.v4.content.ContextCompat; import android.support.v4.content.ContextCompat;
import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.Toast;
import org.dolphinemu.dolphinemu.R; import org.dolphinemu.dolphinemu.R;
import org.dolphinemu.dolphinemu.model.Game; import org.dolphinemu.dolphinemu.model.Game;
import org.dolphinemu.dolphinemu.services.DirectoryInitializationService;
import org.dolphinemu.dolphinemu.ui.settings.SettingsActivity;
import org.dolphinemu.dolphinemu.utils.PicassoUtils; import org.dolphinemu.dolphinemu.utils.PicassoUtils;
import org.dolphinemu.dolphinemu.utils.SettingsFile;
import org.dolphinemu.dolphinemu.viewholders.TvGameViewHolder; import org.dolphinemu.dolphinemu.viewholders.TvGameViewHolder;
import java.io.File;
/** /**
* The Leanback library / docs call this a Presenter, but it works very * The Leanback library / docs call this a Presenter, but it works very
* similarly to a RecyclerView.Adapter. * similarly to a RecyclerView.Adapter.
@ -78,8 +88,54 @@ public final class GameRowPresenter extends Presenter
Context context = holder.cardParent.getContext(); Context context = holder.cardParent.getContext();
Drawable background = ContextCompat.getDrawable(context, backgroundId); Drawable background = ContextCompat.getDrawable(context, backgroundId);
holder.cardParent.setInfoAreaBackground(background); holder.cardParent.setInfoAreaBackground(background);
holder.cardParent.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view)
{
FragmentActivity activity = (FragmentActivity) view.getContext();
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle("Game Settings")
.setItems(R.array.gameSettingsMenus, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case 0:
SettingsActivity.launch(activity, SettingsFile.FILE_NAME_DOLPHIN, game.getGameId());
break;
case 1:
SettingsActivity.launch(activity, SettingsFile.FILE_NAME_GFX, game.getGameId());
break;
case 2:
String path = DirectoryInitializationService.getUserDirectory() + "/GameSettings/" + game.getGameId() + ".ini";
File gameSettingsFile = new File(path);
if (gameSettingsFile.exists())
{
if (gameSettingsFile.delete())
{
Toast.makeText(view.getContext(), "Cleared settings for " + game.getGameId(), Toast.LENGTH_SHORT).show();
}
else
{
Toast.makeText(view.getContext(), "Unable to clear settings for " + game.getGameId(), Toast.LENGTH_SHORT).show();
}
}
else
{
Toast.makeText(view.getContext(), "No game settings to delete", Toast.LENGTH_SHORT).show();
}
break;
}
}
});
builder.show();
return true;
}
});
} }
@Override @Override
public void onUnbindViewHolder(ViewHolder viewHolder) public void onUnbindViewHolder(ViewHolder viewHolder)
{ {

View File

@ -129,7 +129,7 @@ public final class MainActivity extends AppCompatActivity implements MainView
@Override @Override
public void launchSettingsActivity(String menuTag) public void launchSettingsActivity(String menuTag)
{ {
SettingsActivity.launch(this, menuTag); SettingsActivity.launch(this, menuTag, "");
} }
@Override @Override

View File

@ -123,7 +123,7 @@ public final class TvMainActivity extends FragmentActivity implements MainView
@Override @Override
public void launchSettingsActivity(String menuTag) public void launchSettingsActivity(String menuTag)
{ {
SettingsActivity.launch(this, menuTag); SettingsActivity.launch(this, menuTag, "");
} }
@Override @Override

View File

@ -18,6 +18,7 @@ import org.dolphinemu.dolphinemu.R;
import org.dolphinemu.dolphinemu.model.settings.SettingSection; import org.dolphinemu.dolphinemu.model.settings.SettingSection;
import org.dolphinemu.dolphinemu.services.DirectoryInitializationService; import org.dolphinemu.dolphinemu.services.DirectoryInitializationService;
import org.dolphinemu.dolphinemu.utils.DirectoryStateReceiver; import org.dolphinemu.dolphinemu.utils.DirectoryStateReceiver;
import org.dolphinemu.dolphinemu.utils.Log;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
@ -25,15 +26,19 @@ import java.util.HashMap;
public final class SettingsActivity extends AppCompatActivity implements SettingsActivityView public final class SettingsActivity extends AppCompatActivity implements SettingsActivityView
{ {
private static final String ARG_FILE_NAME = "file_name"; private static final String ARG_FILE_NAME = "file_name";
private static final String ARG_GAME_ID = "game_id";
private static final String FRAGMENT_TAG = "settings"; private static final String FRAGMENT_TAG = "settings";
private SettingsActivityPresenter mPresenter = new SettingsActivityPresenter(this); private SettingsActivityPresenter mPresenter = new SettingsActivityPresenter(this);
private ProgressDialog dialog; private ProgressDialog dialog;
public static void launch(Context context, String menuTag) public static void launch(Context context, String menuTag, String gameId)
{ {
Intent settings = new Intent(context, SettingsActivity.class); Intent settings = new Intent(context, SettingsActivity.class);
settings.putExtra(ARG_FILE_NAME, menuTag); settings.putExtra(ARG_FILE_NAME, menuTag);
settings.putExtra(ARG_GAME_ID, gameId);
context.startActivity(settings); context.startActivity(settings);
} }
@ -46,8 +51,9 @@ public final class SettingsActivity extends AppCompatActivity implements Setting
Intent launcher = getIntent(); Intent launcher = getIntent();
String filename = launcher.getStringExtra(ARG_FILE_NAME); String filename = launcher.getStringExtra(ARG_FILE_NAME);
String gameID = launcher.getStringExtra(ARG_GAME_ID);
mPresenter.onCreate(savedInstanceState, filename); mPresenter.onCreate(savedInstanceState, filename, gameID);
} }
@Override @Override
@ -101,7 +107,7 @@ public final class SettingsActivity extends AppCompatActivity implements Setting
@Override @Override
public void showSettingsFragment(String menuTag, boolean addToStack) public void showSettingsFragment(String menuTag, boolean addToStack, String gameID)
{ {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
@ -119,7 +125,7 @@ public final class SettingsActivity extends AppCompatActivity implements Setting
transaction.addToBackStack(null); transaction.addToBackStack(null);
mPresenter.addToStack(); mPresenter.addToStack();
} }
transaction.replace(R.id.frame_content, SettingsFragment.newInstance(menuTag), FRAGMENT_TAG); transaction.replace(R.id.frame_content, SettingsFragment.newInstance(menuTag, gameID), FRAGMENT_TAG);
transaction.commit(); transaction.commit();
} }

View File

@ -2,6 +2,7 @@ package org.dolphinemu.dolphinemu.ui.settings;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.os.Bundle; import android.os.Bundle;
import android.text.TextUtils;
import org.dolphinemu.dolphinemu.R; import org.dolphinemu.dolphinemu.R;
import org.dolphinemu.dolphinemu.model.settings.SettingSection; import org.dolphinemu.dolphinemu.model.settings.SettingSection;
@ -31,17 +32,19 @@ public final class SettingsActivityPresenter
private DirectoryStateReceiver directoryStateReceiver; private DirectoryStateReceiver directoryStateReceiver;
private String menuTag; private String menuTag;
private String gameId;
public SettingsActivityPresenter(SettingsActivityView view) public SettingsActivityPresenter(SettingsActivityView view)
{ {
mView = view; mView = view;
} }
public void onCreate(Bundle savedInstanceState, String menuTag) public void onCreate(Bundle savedInstanceState, String menuTag, String gameId)
{ {
if (savedInstanceState == null) if (savedInstanceState == null)
{ {
this.menuTag = menuTag; this.menuTag = menuTag;
this.gameId = gameId;
} }
else else
{ {
@ -58,12 +61,21 @@ public final class SettingsActivityPresenter
{ {
if (mSettings.isEmpty()) if (mSettings.isEmpty())
{ {
mSettings.add(SettingsFile.SETTINGS_DOLPHIN, SettingsFile.readFile(SettingsFile.FILE_NAME_DOLPHIN, mView)); if (!TextUtils.isEmpty(gameId))
mSettings.add(SettingsFile.SETTINGS_GFX, SettingsFile.readFile(SettingsFile.FILE_NAME_GFX, mView)); {
mSettings.add(SettingsFile.SETTINGS_WIIMOTE, SettingsFile.readFile(SettingsFile.FILE_NAME_WIIMOTE, mView)); mSettings.add(SettingsFile.SETTINGS_DOLPHIN, SettingsFile.readFile("../GameSettings/" + gameId, mView));
mSettings.add(SettingsFile.SETTINGS_GFX, SettingsFile.readFile("../GameSettings/" + gameId, mView));
mSettings.add(SettingsFile.SETTINGS_WIIMOTE, SettingsFile.readFile("../GameSettings/" + gameId, mView));
}
else
{
mSettings.add(SettingsFile.SETTINGS_DOLPHIN, SettingsFile.readFile(SettingsFile.FILE_NAME_DOLPHIN, mView));
mSettings.add(SettingsFile.SETTINGS_GFX, SettingsFile.readFile(SettingsFile.FILE_NAME_GFX, mView));
mSettings.add(SettingsFile.SETTINGS_WIIMOTE, SettingsFile.readFile(SettingsFile.FILE_NAME_WIIMOTE, mView));
}
} }
mView.showSettingsFragment(menuTag, false); mView.showSettingsFragment(menuTag, false, gameId);
mView.onSettingsFileLoaded(mSettings); mView.onSettingsFileLoaded(mSettings);
} }
@ -120,11 +132,25 @@ public final class SettingsActivityPresenter
if (mSettings != null && finishing && mShouldSave) if (mSettings != null && finishing && mShouldSave)
{ {
Log.debug("[SettingsActivity] Settings activity stopping. Saving settings to INI..."); if (!TextUtils.isEmpty(gameId)) {
SettingsFile.saveFile(SettingsFile.FILE_NAME_DOLPHIN, mSettings.get(SettingsFile.SETTINGS_DOLPHIN), mView); Log.debug("[SettingsActivity] Settings activity stopping. Saving settings to INI...");
SettingsFile.saveFile(SettingsFile.FILE_NAME_GFX, mSettings.get(SettingsFile.SETTINGS_GFX), mView); // Needed workaround for now due to an odd bug in how it handles saving two different settings sections to the same file. It won't save GFX settings if it follows the normal saving pattern
SettingsFile.saveFile(SettingsFile.FILE_NAME_WIIMOTE, mSettings.get(SettingsFile.SETTINGS_WIIMOTE), mView); if (menuTag.equals("Dolphin"))
mView.showToastMessage("Saved settings to INI files"); {
SettingsFile.saveFile("../GameSettings/" + gameId, mSettings.get(SettingsFile.SETTINGS_DOLPHIN), mView);
}
else if (menuTag.equals("GFX"))
{
SettingsFile.saveFile("../GameSettings/" + gameId, mSettings.get(SettingsFile.SETTINGS_GFX), mView);
}
mView.showToastMessage("Saved settings for " + gameId);
} else {
Log.debug("[SettingsActivity] Settings activity stopping. Saving settings to INI...");
SettingsFile.saveFile(SettingsFile.FILE_NAME_DOLPHIN, mSettings.get(SettingsFile.SETTINGS_DOLPHIN), mView);
SettingsFile.saveFile(SettingsFile.FILE_NAME_GFX, mSettings.get(SettingsFile.SETTINGS_GFX), mView);
SettingsFile.saveFile(SettingsFile.FILE_NAME_WIIMOTE, mSettings.get(SettingsFile.SETTINGS_WIIMOTE), mView);
mView.showToastMessage("Saved settings to INI files");
}
} }
} }
@ -172,7 +198,7 @@ public final class SettingsActivityPresenter
{ {
if (value != 0) // Not disabled if (value != 0) // Not disabled
{ {
mView.showSettingsFragment(key + (value / 6), true); mView.showSettingsFragment(key + (value / 6), true, gameId);
} }
} }
@ -181,7 +207,7 @@ public final class SettingsActivityPresenter
switch (value) switch (value)
{ {
case 1: case 1:
mView.showSettingsFragment(section, true); mView.showSettingsFragment(section, true, gameId);
break; break;
case 2: case 2:
@ -194,7 +220,7 @@ public final class SettingsActivityPresenter
{ {
if (value != 0) // None if (value != 0) // None
{ {
mView.showSettingsFragment(key + value, true); mView.showSettingsFragment(key + value, true, gameId);
} }
} }
} }

View File

@ -19,7 +19,7 @@ public interface SettingsActivityView
* @param menuTag Identifier for the settings group that should be displayed. * @param menuTag Identifier for the settings group that should be displayed.
* @param addToStack Whether or not this fragment should replace a previous one. * @param addToStack Whether or not this fragment should replace a previous one.
*/ */
void showSettingsFragment(String menuTag, boolean addToStack); void showSettingsFragment(String menuTag, boolean addToStack, String gameId);
/** /**
* Called by a contained Fragment to get access to the Setting HashMap * Called by a contained Fragment to get access to the Setting HashMap

View File

@ -24,18 +24,20 @@ import java.util.HashMap;
public final class SettingsFragment extends Fragment implements SettingsFragmentView public final class SettingsFragment extends Fragment implements SettingsFragmentView
{ {
private static final String ARGUMENT_MENU_TAG = "menu_tag"; private static final String ARGUMENT_MENU_TAG = "menu_tag";
private static final String ARGUMENT_GAME_ID = "game_id";
private SettingsFragmentPresenter mPresenter = new SettingsFragmentPresenter(this); private SettingsFragmentPresenter mPresenter = new SettingsFragmentPresenter(this);
private SettingsActivityView mActivity; private SettingsActivityView mActivity;
private SettingsAdapter mAdapter; private SettingsAdapter mAdapter;
public static Fragment newInstance(String menuTag) public static Fragment newInstance(String menuTag, String gameId)
{ {
SettingsFragment fragment = new SettingsFragment(); SettingsFragment fragment = new SettingsFragment();
Bundle arguments = new Bundle(); Bundle arguments = new Bundle();
arguments.putString(ARGUMENT_MENU_TAG, menuTag); arguments.putString(ARGUMENT_MENU_TAG, menuTag);
arguments.putString(ARGUMENT_GAME_ID, gameId);
fragment.setArguments(arguments); fragment.setArguments(arguments);
return fragment; return fragment;
@ -71,10 +73,11 @@ public final class SettingsFragment extends Fragment implements SettingsFragment
setRetainInstance(true); setRetainInstance(true);
String menuTag = getArguments().getString(ARGUMENT_MENU_TAG); String menuTag = getArguments().getString(ARGUMENT_MENU_TAG);
String gameId = getArguments().getString(ARGUMENT_GAME_ID);
mAdapter = new SettingsAdapter(this, getActivity()); mAdapter = new SettingsAdapter(this, getActivity());
mPresenter.onCreate(menuTag); mPresenter.onCreate(menuTag, gameId);
} }
@Nullable @Nullable
@ -147,7 +150,7 @@ public final class SettingsFragment extends Fragment implements SettingsFragment
@Override @Override
public void loadSubMenu(String menuKey) public void loadSubMenu(String menuKey)
{ {
mActivity.showSettingsFragment(menuKey, true); mActivity.showSettingsFragment(menuKey, true, getArguments().getString(ARGUMENT_GAME_ID));
} }
@Override @Override

View File

@ -1,5 +1,7 @@
package org.dolphinemu.dolphinemu.ui.settings; package org.dolphinemu.dolphinemu.ui.settings;
import android.text.TextUtils;
import org.dolphinemu.dolphinemu.NativeLibrary; import org.dolphinemu.dolphinemu.NativeLibrary;
import org.dolphinemu.dolphinemu.R; import org.dolphinemu.dolphinemu.R;
import org.dolphinemu.dolphinemu.model.settings.BooleanSetting; import org.dolphinemu.dolphinemu.model.settings.BooleanSetting;
@ -25,6 +27,7 @@ public final class SettingsFragmentPresenter
private SettingsFragmentView mView; private SettingsFragmentView mView;
private String mMenuTag; private String mMenuTag;
private String mGameID;
private ArrayList<HashMap<String, SettingSection>> mSettings; private ArrayList<HashMap<String, SettingSection>> mSettings;
private ArrayList<SettingsItem> mSettingsList; private ArrayList<SettingsItem> mSettingsList;
@ -37,8 +40,10 @@ public final class SettingsFragmentPresenter
mView = view; mView = view;
} }
public void onCreate(String menuTag) public void onCreate(String menuTag, String gameId)
{ {
mGameID = gameId;
if (menuTag.startsWith(SettingsFile.KEY_GCPAD_TYPE)) if (menuTag.startsWith(SettingsFile.KEY_GCPAD_TYPE))
{ {
mMenuTag = SettingsFile.KEY_GCPAD_TYPE; mMenuTag = SettingsFile.KEY_GCPAD_TYPE;
@ -106,6 +111,10 @@ public final class SettingsFragmentPresenter
private void loadSettingsList() private void loadSettingsList()
{ {
if (!TextUtils.isEmpty(mGameID))
{
mView.getActivity().setTitle("Game Settings: " + mGameID);
}
ArrayList<SettingsItem> sl = new ArrayList<>(); ArrayList<SettingsItem> sl = new ArrayList<>();
switch (mMenuTag) switch (mMenuTag)
@ -151,7 +160,7 @@ public final class SettingsFragmentPresenter
break; break;
default: default:
mView.showToastMessage("Unimplemented menu."); mView.showToastMessage("Unimplemented menu");
return; return;
} }

View File

@ -286,4 +286,9 @@
<item>Right Stick</item> <item>Right Stick</item>
</string-array> </string-array>
<string-array name="gameSettingsMenus">
<item>Core Settings</item>
<item>GFX Settings</item>
<item>Clear Game Settings</item>
</string-array>
</resources> </resources>

View File

@ -211,6 +211,7 @@
<!-- Preferences Screen --> <!-- Preferences Screen -->
<string name="preferences_save_exit">Save and Exit</string> <string name="preferences_save_exit">Save and Exit</string>
<string name="preferences_settings">Settings</string> <string name="preferences_settings">Settings</string>
<string name="preferences_game_settings">Game Settings</string>
<string name="preferences_extensions">Extension Bindings</string> <string name="preferences_extensions">Extension Bindings</string>
<!-- Emulation Menu --> <!-- Emulation Menu -->
@ -247,9 +248,7 @@
<string name="header_controllers">Controllers</string> <string name="header_controllers">Controllers</string>
<string name="write_permission_needed">You need to allow write access to external storage for the emulator to work</string> <string name="write_permission_needed">You need to allow write access to external storage for the emulator to work</string>
<string name="load_settings">Loading Settings...</string> <string name="load_settings">Loading Settings...</string>
<string name="emulation_change_disc">Change Disc</string> <string name="emulation_change_disc">Change Disc</string>
<string name="external_storage_not_mounted">The external storage needs to be available in order to use Dolphin</string> <string name="external_storage_not_mounted">The external storage needs to be available in order to use Dolphin</string>

View File

@ -30,6 +30,7 @@
#include "Core/Boot/Boot.h" #include "Core/Boot/Boot.h"
#include "Core/BootManager.h" #include "Core/BootManager.h"
#include "Core/ConfigLoaders/GameConfigLoader.h"
#include "Core/ConfigManager.h" #include "Core/ConfigManager.h"
#include "Core/Core.h" #include "Core/Core.h"
#include "Core/HW/DVD/DVDInterface.h" #include "Core/HW/DVD/DVDInterface.h"
@ -640,6 +641,57 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_eglBindAPI(J
eglBindAPI(api); eglBindAPI(api);
} }
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_InitGameIni(JNIEnv* env,
jobject obj,
jstring jGameID)
{
// Initialize an empty INI file
IniFile ini;
std::string gameid = GetJString(env, jGameID);
__android_log_print(ANDROID_LOG_DEBUG, "InitGameIni", "Initializing base game config file");
ini.Save(File::GetUserPath(D_GAMESETTINGS_IDX) + gameid + ".ini");
}
JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetUserSetting(
JNIEnv* env, jobject obj, jstring jGameID, jstring jSection, jstring jKey)
{
IniFile ini;
std::string gameid = GetJString(env, jGameID);
std::string section = GetJString(env, jSection);
std::string key = GetJString(env, jKey);
ini = SConfig::GetInstance().LoadGameIni(gameid, 0);
std::string value;
ini.GetOrCreateSection(section)->Get(key, &value, "-1");
return env->NewStringUTF(value.c_str());
}
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SetUserSetting(
JNIEnv* env, jobject obj, jstring jGameID, jstring jSection, jstring jKey, jstring jValue)
{
IniFile ini;
std::string gameid = GetJString(env, jGameID);
std::string section = GetJString(env, jSection);
std::string key = GetJString(env, jKey);
std::string val = GetJString(env, jValue);
ini.Load(File::GetUserPath(D_GAMESETTINGS_IDX) + gameid + ".ini");
if (val != "-1")
{
ini.GetOrCreateSection(section)->Set(key, val);
}
else
{
ini.GetOrCreateSection(section)->Delete(key);
}
ini.Save(File::GetUserPath(D_GAMESETTINGS_IDX) + gameid + ".ini");
}
JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetConfig( JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetConfig(
JNIEnv* env, jobject obj, jstring jFile, jstring jSection, jstring jKey, jstring jDefault) JNIEnv* env, jobject obj, jstring jFile, jstring jSection, jstring jKey, jstring jDefault)
{ {