diff --git a/Source/Android/res/values-ja/strings.xml b/Source/Android/res/values-ja/strings.xml index 12594ca2ac..73ef858a00 100644 --- a/Source/Android/res/values-ja/strings.xml +++ b/Source/Android/res/values-ja/strings.xml @@ -31,6 +31,9 @@ クリックされたファイル: + 入力設定 + 入力バインディング + このコントロールにバインドするための入力を移動または押してください。 Aボタン Bボタン スタートボタン @@ -115,6 +118,7 @@ はい いいえ + キャンセル 無効 その他 diff --git a/Source/Android/res/values/strings.xml b/Source/Android/res/values/strings.xml index dac787e4bc..1abeb4992d 100644 --- a/Source/Android/res/values/strings.xml +++ b/Source/Android/res/values/strings.xml @@ -31,6 +31,9 @@ File clicked: + Input + Input Binding + Press or move an input to bind it to this control. Button A Button B Button Start @@ -115,6 +118,7 @@ Yes No + Cancel Disabled Other diff --git a/Source/Android/res/xml/input_prefs.xml b/Source/Android/res/xml/input_prefs.xml new file mode 100644 index 0000000000..daddf93e3d --- /dev/null +++ b/Source/Android/res/xml/input_prefs.xml @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/DolphinEmulator.java b/Source/Android/src/org/dolphinemu/dolphinemu/DolphinEmulator.java index ca3c637bfb..b7bf23afe3 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/DolphinEmulator.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/DolphinEmulator.java @@ -22,7 +22,7 @@ import java.io.*; import java.util.List; import org.dolphinemu.dolphinemu.gamelist.GameListActivity; -import org.dolphinemu.dolphinemu.inputconfig.InputConfigFragment; +import org.dolphinemu.dolphinemu.settings.InputConfigFragment; import org.dolphinemu.dolphinemu.settings.UserPreferences; public final class DolphinEmulator extends Activity diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/NativeLibrary.java b/Source/Android/src/org/dolphinemu/dolphinemu/NativeLibrary.java index dedd824c87..6b61393166 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/NativeLibrary.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/NativeLibrary.java @@ -15,10 +15,33 @@ import android.view.Surface; */ public final class NativeLibrary { + /** + * Handles touch events. + * + * @param Action Mask for the action being performed. + * @param X Location on the screen's X-axis that the touch event occurred. + * @param Y Location on the screen's Y-axis that the touch event occurred. + */ public static native void onTouchEvent(int Action, float X, float Y); + + /** + * Handles button press events for a gamepad. + * + * @param Device The input descriptor of the gamepad. + * @param Button Key code identifying which button was pressed. + * @param Action Mask identifying which action is happing (button pressed down, or button released). + */ public static native void onGamePadEvent(String Device, int Button, int Action); + + /** + * Handles gamepad movement events. + * + * @param Device The device ID of the gamepad. + * @param Axis The axis ID + * @param Value The value of the axis represented by the given ID. + */ public static native void onGamePadMoveEvent(String Device, int Axis, float Value); - + /** * Gets a value from a key in the given ini-based config file. * @@ -30,7 +53,7 @@ public final class NativeLibrary * @return the value stored at the key, or a default value if it doesn't exist. */ public static native String GetConfig(String configFile, String Section, String Key, String Default); - + /** * Sets a value to a key in the given ini config file. * @@ -40,14 +63,14 @@ public final class NativeLibrary * @param Value The string to set the ini key to. */ public static native void SetConfig(String configFile, String Section, String Key, String Value); - + /** * Sets the filename to be run during emulation. * * @param filename The filename to be run during emulation. */ public static native void SetFilename(String filename); - + /** * Sets the dimensions of the rendering window. * @@ -55,7 +78,7 @@ public final class NativeLibrary * @param height The new height of the rendering window (in pixels). */ public static native void SetDimensions(int width, int height); - + /** * Gets the embedded banner within the given ISO/ROM. * @@ -64,7 +87,7 @@ public final class NativeLibrary * @return an integer array containing the color data for the banner. */ public static native int[] GetBanner(String filename); - + /** * Gets the embedded title of the given ISO/ROM. * @@ -73,7 +96,7 @@ public final class NativeLibrary * @return the embedded title of the ISO/ROM. */ public static native String GetTitle(String filename); - + /** * Gets the Dolphin version string. * @@ -87,13 +110,13 @@ public final class NativeLibrary * @param surf The surface to render to. */ public static native void Run(Surface surf); - + /** Unpauses emulation from a paused state. */ public static native void UnPauseEmulation(); - + /** Pauses emulation. */ public static native void PauseEmulation(); - + /** Stops emulation. */ public static native void StopEmulation(); diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowser.java b/Source/Android/src/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowser.java index 56fe57cb2e..4733cc18da 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowser.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowser.java @@ -54,7 +54,7 @@ public final class FolderBrowser extends Fragment Listfls = new ArrayList(); // Supported extensions to filter by - Set validExts = new HashSet(Arrays.asList(".gcm", ".iso", ".wbfs", ".gcz", ".dol", ".elf", ".dff")); + Set validExts = new HashSet(Arrays.asList(".gcm", ".iso", ".wbfs", ".gcz", ".dol", ".elf", ".dff", ".wad")); // Search for any directories or files within the current dir. for(File entry : dirs) diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListActivity.java b/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListActivity.java index b12bff7ebc..503d32ae66 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListActivity.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListActivity.java @@ -27,9 +27,6 @@ import org.dolphinemu.dolphinemu.AboutFragment; import org.dolphinemu.dolphinemu.NativeLibrary; import org.dolphinemu.dolphinemu.R; import org.dolphinemu.dolphinemu.folderbrowser.FolderBrowser; -import org.dolphinemu.dolphinemu.inputconfig.InputConfigAdapter; -import org.dolphinemu.dolphinemu.inputconfig.InputConfigFragment; -import org.dolphinemu.dolphinemu.inputconfig.InputConfigItem; import org.dolphinemu.dolphinemu.settings.PrefsActivity; import org.dolphinemu.dolphinemu.sidemenu.SideMenuAdapter; import org.dolphinemu.dolphinemu.sidemenu.SideMenuItem; @@ -49,16 +46,7 @@ public final class GameListActivity extends Activity private SideMenuAdapter mDrawerAdapter; private ListView mDrawerList; - /** - * Interface defining methods which handle - * the binding of specific key presses within - * the input mapping settings. - */ - public interface OnGameConfigListener - { - boolean onMotionEvent(MotionEvent event); - boolean onKeyEvent(KeyEvent event); - } + /** * Called from the {@link GameListFragment}. @@ -84,8 +72,7 @@ public final class GameListActivity extends Activity dir.add(new SideMenuItem(getString(R.string.game_list), 0)); dir.add(new SideMenuItem(getString(R.string.browse_folder), 1)); dir.add(new SideMenuItem(getString(R.string.settings), 2)); - dir.add(new SideMenuItem(getString(R.string.gamepad_config), 3)); - dir.add(new SideMenuItem(getString(R.string.about), 4)); + dir.add(new SideMenuItem(getString(R.string.about), 3)); mDrawerAdapter = new SideMenuAdapter(this, R.layout.sidemenu, dir); mDrawerList.setAdapter(mDrawerAdapter); @@ -142,25 +129,9 @@ public final class GameListActivity extends Activity recreateFragment(); break; - case 3: // Gamepad settings - { - InputConfigAdapter adapter = ((InputConfigFragment)mCurFragment).getAdapter(); - for (int a = 0; a < adapter.getCount(); ++a) - { - InputConfigItem o = adapter.getItem(a); - String config = o.getConfig(); - String bind = o.getBind(); - String ConfigValues[] = config.split("-"); - String Key = ConfigValues[0]; - String Value = ConfigValues[1]; - NativeLibrary.SetConfig("Dolphin.ini", Key, Value, bind); - } - } - break; - case 0: // Game List case 2: // Settings - case 4: // About + case 3: // About /* Do Nothing */ break; } @@ -197,16 +168,6 @@ public final class GameListActivity extends Activity case 3: { mCurFragmentNum = 3; - mCurFragment = new InputConfigFragment(); - FragmentManager fragmentManager = getFragmentManager(); - fragmentManager.beginTransaction().replace(R.id.content_frame, mCurFragment).commit(); - invalidateOptionsMenu(); - } - break; - - case 4: - { - mCurFragmentNum = 4; mCurFragment = new AboutFragment(); FragmentManager fragmentManager = getFragmentManager(); fragmentManager.beginTransaction().replace(R.id.content_frame, mCurFragment).commit(); @@ -322,30 +283,4 @@ public final class GameListActivity extends Activity { SwitchPage(0); } - - // Gets move(triggers, joystick) events - @Override - public boolean dispatchGenericMotionEvent(MotionEvent event) - { - if (mCurFragmentNum == 3) - { - if (((OnGameConfigListener)mCurFragment).onMotionEvent(event)) - return true; - } - - return super.dispatchGenericMotionEvent(event); - } - - // Gets button presses - @Override - public boolean dispatchKeyEvent(KeyEvent event) - { - if (mCurFragmentNum == 3) - { - if (((OnGameConfigListener)mCurFragment).onKeyEvent(event)) - return true; - } - - return super.dispatchKeyEvent(event); - } } diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListFragment.java b/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListFragment.java index 6d4a4bfe22..9c254f7b9d 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListFragment.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListFragment.java @@ -69,7 +69,7 @@ public final class GameListFragment extends Fragment int intDirectories = Integer.parseInt(Directories); // Extensions to filter by. - Set exts = new HashSet(Arrays.asList(".gcm", ".iso", ".wbfs", ".gcz", ".dol", ".elf", ".dff")); + Set exts = new HashSet(Arrays.asList(".gcm", ".iso", ".wbfs", ".gcz", ".dol", ".elf", ".dff", ".wad")); for (int a = 0; a < intDirectories; ++a) { @@ -159,4 +159,4 @@ public final class GameListFragment extends Fragment + " must implement OnGameListZeroListener"); } } -} \ No newline at end of file +} diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListItem.java b/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListItem.java index 9ecff70b9b..5e5b71da67 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListItem.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListItem.java @@ -34,7 +34,6 @@ public final class GameListItem implements Comparable * @param name The name of this GameListItem. * @param data The subtitle for this GameListItem * @param path The file path for the game represented by this GameListItem. - * @param isValid Whether or not the emulator can handle this file. */ public GameListItem(Context ctx, String name, String data, String path) { diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/inputconfig/InputConfigAdapter.java b/Source/Android/src/org/dolphinemu/dolphinemu/inputconfig/InputConfigAdapter.java deleted file mode 100644 index 318075ec40..0000000000 --- a/Source/Android/src/org/dolphinemu/dolphinemu/inputconfig/InputConfigAdapter.java +++ /dev/null @@ -1,70 +0,0 @@ -/** - * Copyright 2013 Dolphin Emulator Project - * Licensed under GPLv2 - * Refer to the license.txt file included. - */ - -package org.dolphinemu.dolphinemu.inputconfig; - -import android.content.Context; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ArrayAdapter; -import android.widget.TextView; - -import java.util.List; - -import org.dolphinemu.dolphinemu.R; - -/** - * The adapter backing the input mapping configuration. - *

- * Responsible for handling the list items. - */ -public final class InputConfigAdapter extends ArrayAdapter -{ - private final Context c; - private final int id; - private final List items; - - public InputConfigAdapter(Context context, int textViewResourceId, List objects) - { - super(context, textViewResourceId, objects); - c = context; - id = textViewResourceId; - items = objects; - } - - @Override - public InputConfigItem getItem(int i) - { - return items.get(i); - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) - { - View v = convertView; - if (v == null) - { - LayoutInflater vi = (LayoutInflater)c.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - v = vi.inflate(id, parent, false); - } - - final InputConfigItem item = items.get(position); - if (item != null) - { - TextView title = (TextView) v.findViewById(R.id.FolderTitle); - TextView subtitle = (TextView) v.findViewById(R.id.FolderSubTitle); - - if (title != null) - title.setText(item.getName()); - - if (subtitle != null) - subtitle.setText(item.getBind()); - } - - return v; - } -} diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/inputconfig/InputConfigFragment.java b/Source/Android/src/org/dolphinemu/dolphinemu/inputconfig/InputConfigFragment.java deleted file mode 100644 index dd91b952c7..0000000000 --- a/Source/Android/src/org/dolphinemu/dolphinemu/inputconfig/InputConfigFragment.java +++ /dev/null @@ -1,217 +0,0 @@ -/** - * Copyright 2013 Dolphin Emulator Project - * Licensed under GPLv2 - * Refer to the license.txt file included. - */ - -package org.dolphinemu.dolphinemu.inputconfig; - -import android.app.Activity; -import android.app.Fragment; -import android.os.Build; -import android.os.Bundle; -import android.util.Log; -import android.view.*; -import android.widget.AdapterView; -import android.widget.ListView; -import android.widget.Toast; - -import java.util.ArrayList; -import java.util.List; - -import org.dolphinemu.dolphinemu.R; -import org.dolphinemu.dolphinemu.gamelist.GameListActivity; - -/** - * The {@link Fragment} responsible for implementing the functionality - * within the input control mapping config. - */ -public final class InputConfigFragment extends Fragment - implements GameListActivity.OnGameConfigListener -{ - private Activity m_activity; - private ListView mDrawerList; - private InputConfigAdapter adapter; - private int configPosition = 0; - private boolean Configuring = false; - private boolean firstEvent = true; - - /** - * Gets the descriptor for the given {@link InputDevice}. - * - * @param input The {@link InputDevice} to get the descriptor of. - * - * @return the descriptor for the given {@link InputDevice}. - */ - public static String getInputDesc(InputDevice input) - { - if (input == null) - return "null"; // Happens when the inputdevice is from an unknown source - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) - { - return input.getDescriptor(); - } - else - { - List motions = input.getMotionRanges(); - String fakeid = ""; - - for (InputDevice.MotionRange range : motions) - fakeid += range.getAxis(); - - return fakeid; - } - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) - { - List Input = new ArrayList(); - Input.add(new InputConfigItem(getString(R.string.button_a), "Android-InputA")); - Input.add(new InputConfigItem(getString(R.string.button_b), "Android-InputB")); - Input.add(new InputConfigItem(getString(R.string.button_start), "Android-InputStart")); - Input.add(new InputConfigItem(getString(R.string.button_x), "Android-InputX")); - Input.add(new InputConfigItem(getString(R.string.button_y), "Android-InputY")); - Input.add(new InputConfigItem(getString(R.string.button_z), "Android-InputZ")); - Input.add(new InputConfigItem(getString(R.string.dpad_up), "Android-DPadUp")); - Input.add(new InputConfigItem(getString(R.string.dpad_down), "Android-DPadDown")); - Input.add(new InputConfigItem(getString(R.string.dpad_left), "Android-DPadLeft")); - Input.add(new InputConfigItem(getString(R.string.dpad_right), "Android-DPadRight")); - Input.add(new InputConfigItem(getString(R.string.main_stick_up), "Android-MainUp")); - Input.add(new InputConfigItem(getString(R.string.main_stick_down), "Android-MainDown")); - Input.add(new InputConfigItem(getString(R.string.main_stick_left), "Android-MainLeft")); - Input.add(new InputConfigItem(getString(R.string.main_stick_right), "Android-MainRight")); - Input.add(new InputConfigItem(getString(R.string.c_stick_up), "Android-CStickUp")); - Input.add(new InputConfigItem(getString(R.string.c_stick_down), "Android-CStickDown")); - Input.add(new InputConfigItem(getString(R.string.c_stick_left), "Android-CStickLeft")); - Input.add(new InputConfigItem(getString(R.string.c_stick_right), "Android-CStickRight")); - Input.add(new InputConfigItem(getString(R.string.trigger_left), "Android-InputL")); - Input.add(new InputConfigItem(getString(R.string.trigger_right), "Android-InputR")); - - adapter = new InputConfigAdapter(m_activity, R.layout.folderbrowser, Input); - View rootView = inflater.inflate(R.layout.gamelist_listview, container, false); - mDrawerList = (ListView) rootView.findViewById(R.id.gamelist); - - mDrawerList.setAdapter(adapter); - mDrawerList.setOnItemClickListener(mMenuItemClickListener); - return mDrawerList; - } - - private AdapterView.OnItemClickListener mMenuItemClickListener = new AdapterView.OnItemClickListener() - { - public void onItemClick(AdapterView parent, View view, int position, long id) - { - InputConfigItem o = adapter.getItem(position); - - Toast.makeText(m_activity, getString(R.string.press_button_to_config, o.getName()), Toast.LENGTH_SHORT).show(); - configPosition = position; - Configuring = true; - firstEvent = true; - } - }; - - private static ArrayList m_values = new ArrayList(); - - private void AssignBind(String bind) - { - InputConfigItem o = adapter.getItem(configPosition); - adapter.remove(o); - o.setBind(bind); - adapter.insert(o, configPosition); - } - - /** - * Gets the current {@link InputConfigAdapter} - * - * @return the current {@link InputConfigAdapter}. - */ - public InputConfigAdapter getAdapter() - { - return adapter; - } - - // Called from GameListActivity - public boolean onMotionEvent(MotionEvent event) - { - if ((event.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) == 0) - return false; - - InputDevice input = event.getDevice(); - List motions = input.getMotionRanges(); - if (Configuring) - { - if (firstEvent) - { - m_values.clear(); - - for (InputDevice.MotionRange range : motions) - { - m_values.add(event.getAxisValue(range.getAxis())); - } - - firstEvent = false; - } - else - { - for (int a = 0; a < motions.size(); ++a) - { - InputDevice.MotionRange range = motions.get(a); - - if (m_values.get(a) > (event.getAxisValue(range.getAxis()) + 0.5f)) - { - AssignBind("Device '" + InputConfigFragment.getInputDesc(input) + "'-Axis " + range.getAxis() + "-"); - Configuring = false; - } - else if (m_values.get(a) < (event.getAxisValue(range.getAxis()) - 0.5f)) - { - AssignBind("Device '" + InputConfigFragment.getInputDesc(input) + "'-Axis " + range.getAxis() + "+"); - Configuring = false; - } - } - } - } - return true; - } - - // Called from GameListActivity - public boolean onKeyEvent(KeyEvent event) - { - Log.w("InputConfigFragment", "Got Event " + event.getAction()); - switch (event.getAction()) - { - case KeyEvent.ACTION_DOWN: - case KeyEvent.ACTION_UP: - if (Configuring) - { - InputDevice input = event.getDevice(); - AssignBind("Device '" + InputConfigFragment.getInputDesc(input) + "'-Button " + event.getKeyCode()); - Configuring = false; - return true; - } - - default: - break; - } - - return false; - } - - @Override - public void onAttach(Activity activity) - { - super.onAttach(activity); - - // This makes sure that the container activity has implemented - // the callback interface. If not, it throws an exception - try - { - m_activity = activity; - } - catch (ClassCastException e) - { - throw new ClassCastException(activity.toString() - + " must implement OnGameListZeroListener"); - } - } -} diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/inputconfig/InputConfigItem.java b/Source/Android/src/org/dolphinemu/dolphinemu/inputconfig/InputConfigItem.java deleted file mode 100644 index fc11c7c347..0000000000 --- a/Source/Android/src/org/dolphinemu/dolphinemu/inputconfig/InputConfigItem.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2013 Dolphin Emulator Project - * Licensed under GPLv2 - * Refer to the license.txt file included. - */ - -package org.dolphinemu.dolphinemu.inputconfig; - -import org.dolphinemu.dolphinemu.NativeLibrary; - -/** - * Represents a controller input item (button, stick, etc). - */ -public final class InputConfigItem implements Comparable -{ - private String m_name; - private String m_Config; - private String m_bind; - - private void Init(String name, String config, String defaultBind) - { - m_name = name; - m_Config = config; - String ConfigValues[] = m_Config.split("-"); - String Key = ConfigValues[0]; - String Value = ConfigValues[1]; - m_bind = NativeLibrary.GetConfig("Dolphin.ini", Key, Value, defaultBind); - } - - /** - * Constructor - * - * @param name Name of the input config item. - * @param config Name of the key in the configuration file that this control modifies. - * @param defaultBind Default binding to fall back upon if binding fails. - */ - public InputConfigItem(String name, String config, String defaultBind) - { - Init(name, config, defaultBind); - } - - /** - * Constructor that creates an InputConfigItem - * that has a default binding of "None". - * - * @param name Name of the input config item. - * @param config Name of the key in the configuration file that this control modifies. - */ - public InputConfigItem(String name, String config) - { - Init(name, config, "None"); - } - - /** - * Gets the name of this InputConfigItem. - * - * @return the name of this InputConfigItem - */ - public String getName() - { - return m_name; - } - - /** - * Gets the config key this InputConfigItem modifies. - * - * @return the config key this InputConfigItem modifies. - */ - public String getConfig() - { - return m_Config; - } - - /** - * Gets the currently set binding of this InputConfigItem. - * - * @return the currently set binding of this InputConfigItem - */ - public String getBind() - { - return m_bind; - } - - /** - * Sets a new binding for this InputConfigItem. - * - * @param bind The new binding. - */ - public void setBind(String bind) - { - m_bind = bind; - } - - public int compareTo(InputConfigItem o) - { - if (this.m_name != null) - return this.m_name.toLowerCase().compareTo(o.getName().toLowerCase()); - else - throw new IllegalArgumentException(); - } -} diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/settings/CPUSettingsFragment.java b/Source/Android/src/org/dolphinemu/dolphinemu/settings/CPUSettingsFragment.java index e77725087e..e93cbce384 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/settings/CPUSettingsFragment.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/settings/CPUSettingsFragment.java @@ -57,16 +57,8 @@ public final class CPUSettingsFragment extends PreferenceFragment { super.onAttach(activity); - // This makes sure that the container activity has implemented - // the callback interface. If not, it throws an exception - try - { - m_activity = activity; - } - catch (ClassCastException e) - { - throw new ClassCastException(activity.toString()); - } + // Cache the activity instance. + m_activity = activity; } @Override diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/settings/InputConfigFragment.java b/Source/Android/src/org/dolphinemu/dolphinemu/settings/InputConfigFragment.java new file mode 100644 index 0000000000..8914c496b9 --- /dev/null +++ b/Source/Android/src/org/dolphinemu/dolphinemu/settings/InputConfigFragment.java @@ -0,0 +1,264 @@ +/** + * Copyright 2013 Dolphin Emulator Project + * Licensed under GPLv2 + * Refer to the license.txt file included. + */ + +package org.dolphinemu.dolphinemu.settings; + +import android.app.Activity; +import android.app.AlertDialog; +import android.app.Fragment; +import android.content.Context; +import android.content.DialogInterface; +import android.os.Build; +import android.os.Bundle; +import android.preference.Preference; +import android.preference.PreferenceFragment; +import android.preference.PreferenceScreen; +import android.util.Log; +import android.view.*; + +import java.util.ArrayList; +import java.util.List; + +import org.dolphinemu.dolphinemu.NativeLibrary; +import org.dolphinemu.dolphinemu.R; + +/** + * The {@link Fragment} responsible for implementing the functionality + * within the input control mapping config. + */ +public final class InputConfigFragment extends PreferenceFragment + //implements PrefsActivity.OnGameConfigListener +{ + private Activity m_activity; + private boolean firstEvent = true; + private static ArrayList m_values = new ArrayList(); + + /** + * Gets the descriptor for the given {@link InputDevice}. + * + * @param input The {@link InputDevice} to get the descriptor of. + * + * @return the descriptor for the given {@link InputDevice}. + */ + public static String getInputDesc(InputDevice input) + { + if (input == null) + return "null"; // Happens when the InputDevice is from an unknown source + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) + { + return input.getDescriptor(); + } + else + { + List motions = input.getMotionRanges(); + String fakeid = ""; + + for (InputDevice.MotionRange range : motions) + fakeid += range.getAxis(); + + return fakeid; + } + } + + @Override + public void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + + // Expand the preferences from the XML. + addPreferencesFromResource(R.xml.input_prefs); + + // Set the summary messages of the preferences to whatever binding + // is currently set within the Dolphin config. + final String[] keys = + { + "InputA", "InputB", "InputX", "InputY", "InputZ", "InputStart", + "DPadUp", "DPadDown", "DPadLeft", "DPadRight", + "MainUp", "MainDown", "MainLeft", "MainRight", + "CStickUp", "CStickDown", "CStickLeft", "CStickRight", + "InputL", "InputR", + }; + + Preference pref; + for (String key : keys) + { + String binding = NativeLibrary.GetConfig("Dolphin.ini", "Android", key, "None"); + pref = findPreference(key); + pref.setSummary(binding); + } + } + + @Override + public boolean onPreferenceTreeClick(final PreferenceScreen screen, final Preference pref) + { + // Begin the creation of the input alert. + final MotionAlertDialog dialog = new MotionAlertDialog(m_activity); + + // Set the key listener + dialog.setOnKeyListener(new AlertDialog.OnKeyListener() + { + public boolean onKey(DialogInterface dlg, int keyCode, KeyEvent event) + { + Log.d("InputConfigFragment", "Received key event: " + event.getAction()); + switch (event.getAction()) + { + case KeyEvent.ACTION_DOWN: + case KeyEvent.ACTION_UP: + InputDevice input = event.getDevice(); + String bindStr = "Device '" + getInputDesc(input) + "'-Button " + event.getKeyCode(); + NativeLibrary.SetConfig("Dolphin.ini", "Android", pref.getKey(), bindStr); + pref.setSummary(bindStr); + dialog.dismiss(); + return true; + + default: + break; + } + + return false; + } + }); + + // Set the motion event listener. + dialog.setOnMotionEventListener(new MotionAlertDialog.OnMotionEventListener() + { + public boolean onMotion(MotionEvent event) + { + Log.d("InputConfigFragment", "Received motion event: " + event.getAction()); + if (event == null || (event.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) == 0) + return false; + + InputDevice input = event.getDevice(); + List motions = input.getMotionRanges(); + if (firstEvent) + { + m_values.clear(); + + for (InputDevice.MotionRange range : motions) + { + m_values.add(event.getAxisValue(range.getAxis())); + } + + firstEvent = false; + } + else + { + for (int a = 0; a < motions.size(); ++a) + { + InputDevice.MotionRange range = motions.get(a); + + if (m_values.get(a) > (event.getAxisValue(range.getAxis()) + 0.5f)) + { + String bindStr = "Device '" + InputConfigFragment.getInputDesc(input) + "'-Axis " + range.getAxis() + "-"; + NativeLibrary.SetConfig("Dolphin.ini", "Android", pref.getKey(), bindStr); + pref.setSummary(bindStr); + dialog.dismiss(); + } + else if (m_values.get(a) < (event.getAxisValue(range.getAxis()) - 0.5f)) + { + String bindStr = "Device '" + InputConfigFragment.getInputDesc(input) + "'-Axis " + range.getAxis() + "+"; + NativeLibrary.SetConfig("Dolphin.ini", "Android", pref.getKey(), bindStr); + pref.setSummary(bindStr); + dialog.dismiss(); + } + } + } + + return true; + } + }); + + // Set the cancel button. + dialog.setButton(AlertDialog.BUTTON_NEGATIVE, getString(R.string.cancel), new AlertDialog.OnClickListener() + { + public void onClick(DialogInterface dialog, int which) + { + // Do nothing. This just makes the cancel button appear. + } + }); + + // Set the title and description message. + dialog.setTitle(R.string.input_binding); + dialog.setMessage(getString(R.string.input_binding_descrip)); + + // Don't allow the dialog to close when a user taps + // outside of it. They must press cancel or provide an input. + dialog.setCanceledOnTouchOutside(false); + + // Everything is set, show the dialog. + dialog.show(); + return true; + } + + @Override + public void onAttach(Activity activity) + { + super.onAttach(activity); + + // Cache the activity instance. + m_activity = activity; + } + + + /** + * {@link AlertDialog} class derivative that allows the motion listener + * to be set anonymously, so the creation of an explicit class for + * providing functionality is not necessary. + */ + protected static final class MotionAlertDialog extends AlertDialog + { + private OnMotionEventListener motionListener; + + /** + * Constructor + * + * @param ctx context to use this dialog in. + */ + public MotionAlertDialog(Context ctx) + { + super(ctx); + } + + /** + * Interface which defines a callback method for general + * motion events. This allows motion event code to be set + * in the event anonymous classes of this dialog are used. + */ + public interface OnMotionEventListener + { + boolean onMotion(MotionEvent event); + } + + /** + * Sets the motion listener. + * + * @param listener The motion listener to set. + */ + public void setOnMotionEventListener(OnMotionEventListener listener) + { + this.motionListener = listener; + } + + @Override + public boolean dispatchKeyEvent(KeyEvent event) + { + if (this.onKeyDown(event.getKeyCode(), event)) + return true; + + return super.dispatchKeyEvent(event); + } + + @Override + public boolean dispatchGenericMotionEvent(MotionEvent event) + { + if (motionListener.onMotion(event)) + return true; + + return super.dispatchGenericMotionEvent(event); + } + } +} diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/settings/PrefsActivity.java b/Source/Android/src/org/dolphinemu/dolphinemu/settings/PrefsActivity.java index 08685fa008..dc75de2550 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/settings/PrefsActivity.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/settings/PrefsActivity.java @@ -72,6 +72,7 @@ public final class PrefsActivity extends Activity implements ActionBar.TabListen // the TabListener interface, as the callback (listener) for when // this tab is selected. actionBar.addTab(actionBar.newTab().setText(R.string.cpu_settings).setTabListener(this)); + actionBar.addTab(actionBar.newTab().setText(R.string.input_settings).setTabListener(this)); actionBar.addTab(actionBar.newTab().setText(R.string.video_settings).setTabListener(this)); } @@ -111,6 +112,9 @@ public final class PrefsActivity extends Activity implements ActionBar.TabListen return new CPUSettingsFragment(); case 1: + return new InputConfigFragment(); + + case 2: return new VideoSettingsFragment(); default: // Should never happen. @@ -122,7 +126,7 @@ public final class PrefsActivity extends Activity implements ActionBar.TabListen public int getCount() { // Show total pages. - return 2; + return 3; } @Override @@ -134,6 +138,9 @@ public final class PrefsActivity extends Activity implements ActionBar.TabListen return getString(R.string.cpu_settings).toUpperCase(); case 1: + return getString(R.string.input_settings).toUpperCase(); + + case 2: return getString(R.string.video_settings).toUpperCase(); default: // Should never happen. diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/settings/VideoSettingsFragment.java b/Source/Android/src/org/dolphinemu/dolphinemu/settings/VideoSettingsFragment.java index 3d97f2cbca..b8e82f4dd0 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/settings/VideoSettingsFragment.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/settings/VideoSettingsFragment.java @@ -202,16 +202,8 @@ public final class VideoSettingsFragment extends PreferenceFragment { super.onAttach(activity); - // This makes sure that the container activity has implemented - // the callback interface. If not, it throws an exception - try - { - m_activity = activity; - } - catch (ClassCastException e) - { - throw new ClassCastException(activity.toString()); - } + // Cache the activity instance. + m_activity = activity; } @Override diff --git a/Source/Core/VideoCommon/Src/DriverDetails.cpp b/Source/Core/VideoCommon/Src/DriverDetails.cpp index 0a115e1354..cdecc71cd1 100644 --- a/Source/Core/VideoCommon/Src/DriverDetails.cpp +++ b/Source/Core/VideoCommon/Src/DriverDetails.cpp @@ -27,12 +27,15 @@ namespace DriverDetails // This is a list of all known bugs for each vendor // We use this to check if the device and driver has a issue BugInfo m_known_bugs[] = { - {VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, BUG_NODYNUBOACCESS, 14.0, -1.0, true}, - {VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, BUG_BROKENCENTROID, 14.0, -1.0, true}, - {VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, BUG_BROKENINFOLOG, -1.0, -1.0, true}, - {VENDOR_MESA, DRIVER_NOUVEAU, BUG_BROKENUBO, 900, 916, true}, - {VENDOR_MESA, DRIVER_R600, BUG_BROKENUBO, 900, 913, true}, - {VENDOR_MESA, DRIVER_I965, BUG_BROKENUBO, 900, 920, true}, + {VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, BUG_NODYNUBOACCESS, 14.0, -1.0, true}, + {VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, BUG_BROKENCENTROID, 14.0, -1.0, true}, + {VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, BUG_BROKENINFOLOG, -1.0, -1.0, true}, + {VENDOR_MESA, DRIVER_NOUVEAU, BUG_BROKENUBO, 900, 916, true}, + {VENDOR_MESA, DRIVER_R600, BUG_BROKENUBO, 900, 913, true}, + {VENDOR_MESA, DRIVER_I965, BUG_BROKENUBO, 900, 920, true}, + {VENDOR_ATI, DRIVER_ATI, BUG_BROKENHACKEDBUFFER, -1.0, -1.0, true}, + {VENDOR_MESA, DRIVER_NOUVEAU, BUG_BROKENHACKEDBUFFER, -1.0, -1.0, true}, + {VENDOR_ATI, DRIVER_ATI, BUG_BROKENPINNEDMEMORY, -1.0, -1.0, true} }; std::map m_bugs; diff --git a/Source/Core/VideoCommon/Src/DriverDetails.h b/Source/Core/VideoCommon/Src/DriverDetails.h index efb0c7c6c0..dc0d2900eb 100644 --- a/Source/Core/VideoCommon/Src/DriverDetails.h +++ b/Source/Core/VideoCommon/Src/DriverDetails.h @@ -83,6 +83,22 @@ namespace DriverDetails // Nouveau stored the offset as u16 which isn't enough for all cases with range until 9.1.6 // I965 has broken data fetches from uniform buffers which results in a dithering until 9.2.0 BUG_BROKENUBO, + // Bug: The hacked buffer upload method isn't working + // This isn't a bug as the hacked buffer itself isn't used to work. + // I'm still surprised that it works on so many drivers. + // Affected devices: - amd close sourced driver + // - nouveau + // - maybe also some others + // This hack is evil. It's like free(pointer); *pointer = data; + BUG_BROKENHACKEDBUFFER, + // Bug: The pinned memory extension isn't working for index buffers + // Affected devices: AMD as they are the only vendor providing this extension + // Started Version: ? + // Ended Version: -1 + // Pinned memory is disabled for index buffer as the amd driver (the only one with pinned memory support) seems + // to be broken. We just get flickering/black rendering when using pinned memory here -- degasus - 2013/08/20 + // Please see issue #6105 on google code. Let's hope buffer storage solves this issues. + BUG_BROKENPINNEDMEMORY, }; // Initializes our internal vendor, device family, and driver version diff --git a/Source/Plugins/Plugin_VideoOGL/Src/FramebufferManager.cpp b/Source/Plugins/Plugin_VideoOGL/Src/FramebufferManager.cpp index ceafb75dca..f3b8578b23 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/FramebufferManager.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/FramebufferManager.cpp @@ -5,6 +5,7 @@ #include "Globals.h" #include "FramebufferManager.h" #include "VertexShaderGen.h" +#include "OnScreenDisplay.h" #include "TextureConverter.h" #include "Render.h" @@ -366,6 +367,13 @@ void FramebufferManager::ReinterpretPixelData(unsigned int convtype) { if(g_ogl_config.eSupportedGLSLVersion == GLSL_120) { // This feature isn't supported by glsl120 + + // TODO: move this to InitBackendInfo + // We have to disable both the active and the stored config. Else we would either + // show this line per format change in one frame or once per frame. + OSD::AddMessage("Format Change Emulation isn't supported by your GPU.", 10000); + g_ActiveConfig.bEFBEmulateFormatChanges = false; + g_Config.bEFBEmulateFormatChanges = false; return; } @@ -435,6 +443,8 @@ void XFBSource::DecodeToTexture(u32 xfbAddr, u32 fbWidth, u32 fbHeight) void XFBSource::CopyEFB(float Gamma) { + g_renderer->ResetAPIState(); + // Copy EFB data to XFB and restore render target again glBindFramebuffer(GL_READ_FRAMEBUFFER, FramebufferManager::GetEFBFramebuffer()); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, FramebufferManager::GetXFBFramebuffer()); @@ -451,6 +461,8 @@ void XFBSource::CopyEFB(float Gamma) // Return to EFB. FramebufferManager::SetFramebuffer(0); + + g_renderer->RestoreAPIState(); } diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp index ee159929d1..504e58f85b 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp @@ -173,7 +173,8 @@ int GetNumMSAASamples(int MSAAMode) if(samples <= g_ogl_config.max_samples) return samples; - ERROR_LOG(VIDEO, "MSAA Bug: %d samples selected, but only %d supported by GPU.", samples, g_ogl_config.max_samples); + // TODO: move this to InitBackendInfo + OSD::AddMessage(StringFromFormat("%d Anti Aliasing samples selected, but only %d supported by your GPU.", samples, g_ogl_config.max_samples), 10000); return g_ogl_config.max_samples; } @@ -197,7 +198,8 @@ int GetNumMSAACoverageSamples(int MSAAMode) } if(g_ogl_config.bSupportCoverageMSAA || samples == 0) return samples; - ERROR_LOG(VIDEO, "MSAA Bug: CSAA selected, but not supported by GPU."); + // TODO: move this to InitBackendInfo + OSD::AddMessage("CSAA Anti Aliasing isn't supported by your GPU.", 10000); return 0; } @@ -209,7 +211,8 @@ void ApplySSAASettings() { glEnable(GL_SAMPLE_SHADING_ARB); glMinSampleShadingARB(s_MSAASamples); } else { - ERROR_LOG(VIDEO, "MSAA Bug: SSAA selected, but not supported by GPU."); + // TODO: move this to InitBackendInfo + OSD::AddMessage("SSAA Anti Aliasing isn't supported by your GPU.", 10000); } } else if(g_ogl_config.bSupportSampleShading) { glDisable(GL_SAMPLE_SHADING_ARB); @@ -958,9 +961,13 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) { if (s_MSAASamples > 1) { + g_renderer->ResetAPIState(); + // Resolve our rectangle. FramebufferManager::GetEFBDepthTexture(efbPixelRc); glBindFramebuffer(GL_READ_FRAMEBUFFER, FramebufferManager::GetResolvedFramebuffer()); + + g_renderer->RestoreAPIState(); } u32* depthMap = new u32[targetPixelRcWidth * targetPixelRcHeight]; @@ -1007,9 +1014,13 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) { if (s_MSAASamples > 1) { + g_renderer->ResetAPIState(); + // Resolve our rectangle. FramebufferManager::GetEFBColorTexture(efbPixelRc); glBindFramebuffer(GL_READ_FRAMEBUFFER, FramebufferManager::GetResolvedFramebuffer()); + + g_renderer->RestoreAPIState(); } u32* colorMap = new u32[targetPixelRcWidth * targetPixelRcHeight]; diff --git a/Source/Plugins/Plugin_VideoOGL/Src/StreamBuffer.cpp b/Source/Plugins/Plugin_VideoOGL/Src/StreamBuffer.cpp index af013467eb..5832a292ed 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/StreamBuffer.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/StreamBuffer.cpp @@ -7,6 +7,8 @@ #include "StreamBuffer.h" #include "MemoryUtil.h" #include "Render.h" +#include "DriverDetails.h" +#include "OnScreenDisplay.h" namespace OGL { @@ -23,13 +25,21 @@ StreamBuffer::StreamBuffer(u32 type, size_t size, StreamType uploadType) if(m_uploadtype & STREAM_DETECT) { + // TODO: move this to InitBackendInfo + if(g_ActiveConfig.bHackedBufferUpload && !DriverDetails::HasBug(DriverDetails::BUG_BROKENHACKEDBUFFER)) + { + OSD::AddMessage("Vertex Streaming Hack isn't supported by your GPU.", 10000); + g_ActiveConfig.bHackedBufferUpload = false; + g_Config.bHackedBufferUpload = false; + } + if(!g_ogl_config.bSupportsGLBaseVertex && (m_uploadtype & BUFFERDATA)) m_uploadtype = BUFFERDATA; else if(!g_ogl_config.bSupportsGLBaseVertex && (m_uploadtype & BUFFERSUBDATA)) m_uploadtype = BUFFERSUBDATA; - else if(g_ogl_config.bSupportsGLSync && g_Config.bHackedBufferUpload && (m_uploadtype & MAP_AND_RISK)) + else if(g_ogl_config.bSupportsGLSync && g_ActiveConfig.bHackedBufferUpload && (m_uploadtype & MAP_AND_RISK)) m_uploadtype = MAP_AND_RISK; - else if(g_ogl_config.bSupportsGLSync && g_ogl_config.bSupportsGLPinnedMemory && (m_uploadtype & PINNED_MEMORY)) + else if(g_ogl_config.bSupportsGLSync && g_ogl_config.bSupportsGLPinnedMemory && (!DriverDetails::HasBug(DriverDetails::BUG_BROKENPINNEDMEMORY) || type != GL_ELEMENT_ARRAY_BUFFER) && (m_uploadtype & PINNED_MEMORY)) m_uploadtype = PINNED_MEMORY; else if(nvidia && (m_uploadtype & BUFFERSUBDATA)) m_uploadtype = BUFFERSUBDATA; diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp index 8dc884ea63..3f4547a005 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp @@ -62,10 +62,7 @@ void VertexManager::CreateDeviceObjects() s_vertexBuffer = new StreamBuffer(GL_ARRAY_BUFFER, MAX_VBUFFER_SIZE); m_vertex_buffers = s_vertexBuffer->getBuffer(); - // Pinned memory is disabled for index buffer as the amd driver (the only one with pinned memory support) seems - // to be broken. We just get flickering/black rendering when using pinned memory here -- degasus - 2013/08/20 - // Please see issue #6105 on google code. Let's hope buffer storage solves this issues. - s_indexBuffer = new StreamBuffer(GL_ELEMENT_ARRAY_BUFFER, MAX_IBUFFER_SIZE, (StreamType)(DETECT_MASK & ~PINNED_MEMORY)); + s_indexBuffer = new StreamBuffer(GL_ELEMENT_ARRAY_BUFFER, MAX_IBUFFER_SIZE); m_index_buffers = s_indexBuffer->getBuffer(); m_CurrentVertexFmt = NULL;