summaryrefslogtreecommitdiff
path: root/Source/Android/app/src
diff options
context:
space:
mode:
authorEder Bastos <bastos.eder@gmail.com>2015-04-30 18:15:10 -0400
committerEder Bastos <bastos.eder@gmail.com>2015-05-02 21:49:17 -0400
commitc80225ea4d023ed91503521b74951db3a302ca20 (patch)
treed69c8493aedf1226b9d4e9b447ef09364aaace84 /Source/Android/app/src
parent4b00ccbe4ed79a3fd3369ca1b2972f0b8e4224ef (diff)
Convert the Android source code to the directory structure of a Gradle-based Android Studio project.
Diffstat (limited to 'Source/Android/app/src')
-rw-r--r--Source/Android/app/src/androidTest/java/org/dolphinemu/dolphinemu/ApplicationTest.java13
-rw-r--r--Source/Android/app/src/main/AndroidManifest.xml50
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/AssetCopyService.java115
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java213
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/about/AboutActivity.java122
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/about/AboutFragmentItem.java48
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/about/AboutInfoFragmentAdapter.java67
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/about/CPUInfoFragment.java52
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/about/DolphinInfoFragment.java48
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/about/GLES2InfoFragment.java82
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/about/GLES3InfoFragment.java114
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/about/GLInfoFragment.java69
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/about/Limit.java71
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/emulation/EmulationActivity.java316
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/emulation/NativeGLSurfaceView.java74
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/emulation/overlay/InputOverlay.java288
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/emulation/overlay/InputOverlayDrawableButton.java45
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/emulation/overlay/InputOverlayDrawableJoystick.java137
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowser.java159
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowserAdapter.java112
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowserItem.java110
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/gamelist/GameListActivity.java374
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/gamelist/GameListAdapter.java124
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/gamelist/GameListFragment.java150
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/gamelist/GameListItem.java102
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/settings/PrefsActivity.java101
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/settings/UserPreferences.java284
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/settings/cpu/CPUSettingsFragment.java56
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/settings/custom/UpdatingListPreference.java39
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/settings/input/InputBindingPreference.java55
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/settings/input/InputConfigFragment.java102
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/settings/input/MotionAlertDialog.java127
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/settings/input/overlayconfig/OverlayConfigActivity.java51
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/settings/input/overlayconfig/OverlayConfigButton.java166
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/settings/video/VideoSettingsFragment.java202
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/sidemenu/SideMenuAdapter.java75
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/sidemenu/SideMenuItem.java50
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/CPUHelper.java395
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/EGLHelper.java393
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/SliderPreference.java94
-rw-r--r--Source/Android/app/src/main/res/drawable-hdpi/gcpad_a.pngbin0 -> 37740 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-hdpi/gcpad_a_pressed.pngbin0 -> 32001 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-hdpi/gcpad_b.pngbin0 -> 39303 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-hdpi/gcpad_b_pressed.pngbin0 -> 31478 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-hdpi/gcpad_c.pngbin0 -> 38151 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-hdpi/gcpad_c_pressed.pngbin0 -> 31939 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-hdpi/gcpad_dpad.pngbin0 -> 20707 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-hdpi/gcpad_dpad_pressed_down.pngbin0 -> 19145 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-hdpi/gcpad_dpad_pressed_downleft.pngbin0 -> 19569 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-hdpi/gcpad_dpad_pressed_downright.pngbin0 -> 18788 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-hdpi/gcpad_dpad_pressed_left.pngbin0 -> 19556 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-hdpi/gcpad_dpad_pressed_right.pngbin0 -> 19301 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-hdpi/gcpad_dpad_pressed_up.pngbin0 -> 19362 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-hdpi/gcpad_dpad_pressed_upleft.pngbin0 -> 19132 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-hdpi/gcpad_dpad_upright.pngbin0 -> 19336 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-hdpi/gcpad_joystick.pngbin0 -> 47629 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-hdpi/gcpad_joystick_pressed.pngbin0 -> 43463 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-hdpi/gcpad_joystick_range.pngbin0 -> 15037 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-hdpi/gcpad_l.pngbin0 -> 23165 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-hdpi/gcpad_l_pressed.pngbin0 -> 20373 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-hdpi/gcpad_r.pngbin0 -> 25198 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-hdpi/gcpad_r_pressed.pngbin0 -> 22168 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-hdpi/gcpad_start.pngbin0 -> 43905 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-hdpi/gcpad_start_pressed.pngbin0 -> 36079 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-hdpi/gcpad_x.pngbin0 -> 24854 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-hdpi/gcpad_x_pressed.pngbin0 -> 21630 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-hdpi/gcpad_y.pngbin0 -> 25120 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-hdpi/gcpad_y_pressed.pngbin0 -> 22248 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-hdpi/gcpad_z.pngbin0 -> 19089 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-hdpi/gcpad_z_pressed.pngbin0 -> 15880 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-hdpi/ic_drawer.pngbin0 -> 2826 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-hdpi/ic_launcher.pngbin0 -> 2675 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-hdpi/ic_menu_file.pngbin0 -> 408 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-hdpi/ic_menu_folder.pngbin0 -> 788 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-ldpi/gcpad_a.pngbin0 -> 12743 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-ldpi/gcpad_a_pressed.pngbin0 -> 11105 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-ldpi/gcpad_b.pngbin0 -> 13455 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-ldpi/gcpad_b_pressed.pngbin0 -> 11077 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-ldpi/gcpad_c.pngbin0 -> 12987 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-ldpi/gcpad_c_pressed.pngbin0 -> 11044 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-ldpi/gcpad_dpad.pngbin0 -> 7375 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-ldpi/gcpad_dpad_pressed_down.pngbin0 -> 6946 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-ldpi/gcpad_dpad_pressed_downleft.pngbin0 -> 6990 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-ldpi/gcpad_dpad_pressed_downright.pngbin0 -> 6778 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-ldpi/gcpad_dpad_pressed_left.pngbin0 -> 7115 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-ldpi/gcpad_dpad_pressed_right.pngbin0 -> 7003 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-ldpi/gcpad_dpad_pressed_up.pngbin0 -> 7101 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-ldpi/gcpad_dpad_pressed_upleft.pngbin0 -> 6954 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-ldpi/gcpad_dpad_upright.pngbin0 -> 7077 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-ldpi/gcpad_joystick.pngbin0 -> 16916 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-ldpi/gcpad_joystick_pressed.pngbin0 -> 15960 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-ldpi/gcpad_joystick_range.pngbin0 -> 5846 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-ldpi/gcpad_l.pngbin0 -> 8536 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-ldpi/gcpad_l_pressed.pngbin0 -> 7615 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-ldpi/gcpad_r.pngbin0 -> 9201 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-ldpi/gcpad_r_pressed.pngbin0 -> 8111 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-ldpi/gcpad_start.pngbin0 -> 15577 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-ldpi/gcpad_start_pressed.pngbin0 -> 13384 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-ldpi/gcpad_x.pngbin0 -> 9007 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-ldpi/gcpad_x_pressed.pngbin0 -> 7886 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-ldpi/gcpad_y.pngbin0 -> 9212 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-ldpi/gcpad_y_pressed.pngbin0 -> 8424 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-ldpi/gcpad_z.pngbin0 -> 7164 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-ldpi/gcpad_z_pressed.pngbin0 -> 6125 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-mdpi/gcpad_a.pngbin0 -> 19722 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-mdpi/gcpad_a_pressed.pngbin0 -> 17153 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-mdpi/gcpad_b.pngbin0 -> 20756 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-mdpi/gcpad_b_pressed.pngbin0 -> 17079 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-mdpi/gcpad_c.pngbin0 -> 20054 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-mdpi/gcpad_c_pressed.pngbin0 -> 17167 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-mdpi/gcpad_dpad.pngbin0 -> 11024 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-mdpi/gcpad_dpad_pressed_down.pngbin0 -> 10393 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-mdpi/gcpad_dpad_pressed_downleft.pngbin0 -> 10473 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-mdpi/gcpad_dpad_pressed_downright.pngbin0 -> 10101 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-mdpi/gcpad_dpad_pressed_left.pngbin0 -> 10491 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-mdpi/gcpad_dpad_pressed_right.pngbin0 -> 10346 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-mdpi/gcpad_dpad_pressed_up.pngbin0 -> 10525 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-mdpi/gcpad_dpad_pressed_upleft.pngbin0 -> 10295 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-mdpi/gcpad_dpad_upright.pngbin0 -> 10337 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-mdpi/gcpad_joystick.pngbin0 -> 25754 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-mdpi/gcpad_joystick_pressed.pngbin0 -> 23969 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-mdpi/gcpad_joystick_range.pngbin0 -> 8969 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-mdpi/gcpad_l.pngbin0 -> 12702 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-mdpi/gcpad_l_pressed.pngbin0 -> 11338 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-mdpi/gcpad_r.pngbin0 -> 13824 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-mdpi/gcpad_r_pressed.pngbin0 -> 12038 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-mdpi/gcpad_start.pngbin0 -> 23849 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-mdpi/gcpad_start_pressed.pngbin0 -> 19932 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-mdpi/gcpad_x.pngbin0 -> 13645 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-mdpi/gcpad_x_pressed.pngbin0 -> 12167 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-mdpi/gcpad_y.pngbin0 -> 13800 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-mdpi/gcpad_y_pressed.pngbin0 -> 12699 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-mdpi/gcpad_z.pngbin0 -> 10808 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-mdpi/gcpad_z_pressed.pngbin0 -> 8964 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-mdpi/ic_drawer.pngbin0 -> 2816 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-mdpi/ic_launcher.pngbin0 -> 1665 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-mdpi/ic_menu_file.pngbin0 -> 462 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-mdpi/ic_menu_folder.pngbin0 -> 635 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xhdpi/gcpad_a.pngbin0 -> 60837 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xhdpi/gcpad_a_pressed.pngbin0 -> 50279 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xhdpi/gcpad_b.pngbin0 -> 62811 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xhdpi/gcpad_b_pressed.pngbin0 -> 49193 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xhdpi/gcpad_c.pngbin0 -> 61223 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xhdpi/gcpad_c_pressed.pngbin0 -> 50681 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xhdpi/gcpad_dpad.pngbin0 -> 34079 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xhdpi/gcpad_dpad_pressed_down.pngbin0 -> 31524 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xhdpi/gcpad_dpad_pressed_downleft.pngbin0 -> 32210 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xhdpi/gcpad_dpad_pressed_downright.pngbin0 -> 31165 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xhdpi/gcpad_dpad_pressed_left.pngbin0 -> 32178 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xhdpi/gcpad_dpad_pressed_right.pngbin0 -> 31948 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xhdpi/gcpad_dpad_pressed_up.pngbin0 -> 32333 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xhdpi/gcpad_dpad_pressed_upleft.pngbin0 -> 31611 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xhdpi/gcpad_dpad_upright.pngbin0 -> 32311 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xhdpi/gcpad_joystick.pngbin0 -> 73831 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xhdpi/gcpad_joystick_pressed.pngbin0 -> 67676 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xhdpi/gcpad_joystick_range.pngbin0 -> 27278 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xhdpi/gcpad_l.pngbin0 -> 36339 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xhdpi/gcpad_l_pressed.pngbin0 -> 32156 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xhdpi/gcpad_r.pngbin0 -> 39279 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xhdpi/gcpad_r_pressed.pngbin0 -> 34559 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xhdpi/gcpad_start.pngbin0 -> 68893 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xhdpi/gcpad_start_pressed.pngbin0 -> 56305 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xhdpi/gcpad_x.pngbin0 -> 39348 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xhdpi/gcpad_x_pressed.pngbin0 -> 33260 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xhdpi/gcpad_y.pngbin0 -> 39342 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xhdpi/gcpad_y_pressed.pngbin0 -> 34645 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xhdpi/gcpad_z.pngbin0 -> 30020 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xhdpi/gcpad_z_pressed.pngbin0 -> 24424 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xhdpi/ic_drawer.pngbin0 -> 1038 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xhdpi/ic_launcher.pngbin0 -> 3828 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xhdpi/ic_menu_file.pngbin0 -> 450 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xhdpi/ic_menu_folder.pngbin0 -> 932 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_a.pngbin0 -> 113162 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_a_pressed.pngbin0 -> 90650 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_b.pngbin0 -> 115107 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_b_pressed.pngbin0 -> 87472 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_c.pngbin0 -> 113853 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_c_pressed.pngbin0 -> 90983 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_dpad.pngbin0 -> 63766 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_dpad_pressed_down.pngbin0 -> 59090 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_dpad_pressed_downleft.pngbin0 -> 60888 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_dpad_pressed_downright.pngbin0 -> 58804 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_dpad_pressed_left.pngbin0 -> 59414 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_dpad_pressed_right.pngbin0 -> 59185 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_dpad_pressed_up.pngbin0 -> 60162 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_dpad_pressed_upleft.pngbin0 -> 59512 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_dpad_upright.pngbin0 -> 60969 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_joystick.pngbin0 -> 137325 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_joystick_pressed.pngbin0 -> 122628 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_joystick_range.pngbin0 -> 47320 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_l.pngbin0 -> 66726 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_l_pressed.pngbin0 -> 57364 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_r.pngbin0 -> 71391 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_r_pressed.pngbin0 -> 61315 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_start.pngbin0 -> 126544 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_start_pressed.pngbin0 -> 101349 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_x.pngbin0 -> 70950 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_x_pressed.pngbin0 -> 58261 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_y.pngbin0 -> 70866 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_y_pressed.pngbin0 -> 60531 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_z.pngbin0 -> 53011 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_z_pressed.pngbin0 -> 42900 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxhdpi/ic_drawer.pngbin0 -> 202 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxhdpi/ic_launcher.pngbin0 -> 6063 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxhdpi/ic_menu_file.pngbin0 -> 243 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxhdpi/ic_menu_folder.pngbin0 -> 462 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_a.pngbin0 -> 170200 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_a_pressed.pngbin0 -> 127729 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_b.pngbin0 -> 171702 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_b_pressed.pngbin0 -> 126035 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_c.pngbin0 -> 171841 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_c_pressed.pngbin0 -> 130763 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_dpad.pngbin0 -> 100422 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_dpad_pressed_down.pngbin0 -> 93187 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_dpad_pressed_downleft.pngbin0 -> 98656 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_dpad_pressed_downright.pngbin0 -> 97518 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_dpad_pressed_left.pngbin0 -> 93574 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_dpad_pressed_right.pngbin0 -> 93954 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_dpad_pressed_up.pngbin0 -> 93133 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_dpad_pressed_upleft.pngbin0 -> 96620 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_dpad_upright.pngbin0 -> 97579 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_joystick.pngbin0 -> 178852 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_joystick_pressed.pngbin0 -> 150018 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_joystick_range.pngbin0 -> 70537 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_l.pngbin0 -> 100769 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_l_pressed.pngbin0 -> 80900 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_r.pngbin0 -> 103351 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_r_pressed.pngbin0 -> 83819 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_start.pngbin0 -> 175622 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_start_pressed.pngbin0 -> 133783 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_x.pngbin0 -> 106229 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_x_pressed.pngbin0 -> 84332 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_y.pngbin0 -> 97383 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_y_pressed.pngbin0 -> 77398 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_z.pngbin0 -> 75310 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_z_pressed.pngbin0 -> 60839 bytes
-rw-r--r--Source/Android/app/src/main/res/drawable/no_banner.pngbin0 -> 1653 bytes
-rw-r--r--Source/Android/app/src/main/res/layout/about_layout.xml24
-rw-r--r--Source/Android/app/src/main/res/layout/emulation_view.xml22
-rw-r--r--Source/Android/app/src/main/res/layout/folderbrowser_list_item.xml57
-rw-r--r--Source/Android/app/src/main/res/layout/folderbrowser_listview.xml8
-rw-r--r--Source/Android/app/src/main/res/layout/gamelist_activity.xml20
-rw-r--r--Source/Android/app/src/main/res/layout/gamelist_list_item.xml57
-rw-r--r--Source/Android/app/src/main/res/layout/gamelist_listview.xml8
-rw-r--r--Source/Android/app/src/main/res/layout/sidemenu.xml20
-rw-r--r--Source/Android/app/src/main/res/layout/slider_layout.xml23
-rw-r--r--Source/Android/app/src/main/res/layout/viewpager.xml15
-rw-r--r--Source/Android/app/src/main/res/menu/emuwindow_overlay.xml64
-rw-r--r--Source/Android/app/src/main/res/menu/gamelist_menu.xml7
-rw-r--r--Source/Android/app/src/main/res/values-ja/strings.xml210
-rw-r--r--Source/Android/app/src/main/res/values/arrays.xml186
-rw-r--r--Source/Android/app/src/main/res/values/strings.xml223
-rw-r--r--Source/Android/app/src/main/res/xml/cpu_prefs.xml21
-rw-r--r--Source/Android/app/src/main/res/xml/input_prefs.xml1057
-rw-r--r--Source/Android/app/src/main/res/xml/video_prefs.xml178
255 files changed, 7445 insertions, 0 deletions
diff --git a/Source/Android/app/src/androidTest/java/org/dolphinemu/dolphinemu/ApplicationTest.java b/Source/Android/app/src/androidTest/java/org/dolphinemu/dolphinemu/ApplicationTest.java
new file mode 100644
index 0000000000..cf1848ddd5
--- /dev/null
+++ b/Source/Android/app/src/androidTest/java/org/dolphinemu/dolphinemu/ApplicationTest.java
@@ -0,0 +1,13 @@
+package org.dolphinemu.dolphinemu;
+
+import android.app.Application;
+import android.test.ApplicationTestCase;
+
+/**
+ * <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
+ */
+public class ApplicationTest extends ApplicationTestCase<Application> {
+ public ApplicationTest() {
+ super(Application.class);
+ }
+} \ No newline at end of file
diff --git a/Source/Android/app/src/main/AndroidManifest.xml b/Source/Android/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000..5187f65691
--- /dev/null
+++ b/Source/Android/app/src/main/AndroidManifest.xml
@@ -0,0 +1,50 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="org.dolphinemu.dolphinemu">
+
+ <uses-feature android:glEsVersion="0x00030000" />
+
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.INTERNET" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name"
+ android:allowBackup="true"
+ android:supportsRtl="true">
+ <activity
+ android:name="org.dolphinemu.dolphinemu.gamelist.GameListActivity"
+ android:label="@string/app_name"
+ android:theme="@android:style/Theme.Holo.Light" >
+
+ <!-- This intentfilter marks this Activity as the one that gets launched from Home screen. -->
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+ <activity
+ android:name="org.dolphinemu.dolphinemu.about.AboutActivity"
+ android:theme="@android:style/Theme.Holo.Light" />
+
+ <activity
+ android:name="org.dolphinemu.dolphinemu.emulation.EmulationActivity"
+ android:screenOrientation="landscape" />
+
+ <activity
+ android:name="org.dolphinemu.dolphinemu.settings.input.overlayconfig.OverlayConfigActivity"
+ android:screenOrientation="landscape"
+ android:theme="@android:style/Theme.NoTitleBar.Fullscreen"/>
+
+ <activity
+ android:name="org.dolphinemu.dolphinemu.settings.PrefsActivity"
+ android:label="@string/settings"
+ android:theme="@android:style/Theme.Holo.Light" />
+
+ <service android:name=".AssetCopyService"/>
+
+ </application>
+
+</manifest>
+
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/AssetCopyService.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/AssetCopyService.java
new file mode 100644
index 0000000000..d39bbec59f
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/AssetCopyService.java
@@ -0,0 +1,115 @@
+/**
+ * Copyright 2014 Dolphin Emulator Project
+ * Licensed under GPLv2
+ * Refer to the license.txt file included.
+ */
+
+package org.dolphinemu.dolphinemu;
+
+import android.app.IntentService;
+import android.content.Intent;
+import android.os.Environment;
+import android.util.Log;
+
+import org.dolphinemu.dolphinemu.settings.UserPreferences;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * A service that spawns its own thread in order to copy several binary and shader files
+ * from the Dolphin APK to the external file system.
+ */
+public final class AssetCopyService extends IntentService
+{
+ private static final String TAG = "DolphinEmulator";
+
+ public AssetCopyService()
+ {
+ // Superclass constructor is called to name the thread on which this service executes.
+ super("AssetCopyService");
+ }
+
+ @Override
+ protected void onHandleIntent(Intent intent)
+ {
+ String BaseDir = NativeLibrary.GetUserDirectory();
+ String ConfigDir = BaseDir + File.separator + "Config";
+ String GCDir = BaseDir + File.separator + "GC";
+
+ // Copy assets if needed
+ File file = new File(GCDir + File.separator + "font_sjis.bin");
+ if(!file.exists())
+ {
+ NativeLibrary.CreateUserFolders();
+ copyAsset("dsp_coef.bin", GCDir + File.separator + "dsp_coef.bin");
+ copyAsset("dsp_rom.bin", GCDir + File.separator + "dsp_rom.bin");
+ copyAsset("font_ansi.bin", GCDir + File.separator + "font_ansi.bin");
+ copyAsset("font_sjis.bin", GCDir + File.separator + "font_sjis.bin");
+ copyAssetFolder("Shaders", BaseDir + File.separator + "Shaders");
+ }
+ else
+ {
+ Log.v(TAG, "Skipping asset copy operation.");
+ }
+
+ // Always copy over the GCPad config in case of change or corruption.
+ // Not a user configurable file.
+ copyAsset("GCPadNew.ini", ConfigDir + File.separator + "GCPadNew.ini");
+
+ // Load the configuration keys set in the Dolphin ini and gfx ini files
+ // into the application's shared preferences.
+ UserPreferences.LoadIniToPrefs(this);
+ }
+
+ private void copyAsset(String asset, String output)
+ {
+ Log.v(TAG, "Copying " + asset + " to " + output);
+ InputStream in = null;
+ OutputStream out = null;
+
+ try
+ {
+ in = getAssets().open(asset);
+ out = new FileOutputStream(output);
+ copyFile(in, out);
+ in.close();
+ out.close();
+ }
+ catch (IOException e)
+ {
+ Log.e(TAG, "Failed to copy asset file: " + asset, e);
+ }
+ }
+
+ private void copyAssetFolder(String assetFolder, String outputFolder)
+ {
+ Log.v(TAG, "Copying " + assetFolder + " to " + outputFolder);
+
+ try
+ {
+ for (String file : getAssets().list(assetFolder))
+ {
+ copyAsset(assetFolder + File.separator + file, outputFolder + File.separator + file);
+ }
+ }
+ catch (IOException e)
+ {
+ Log.e(TAG, "Failed to copy asset folder: " + assetFolder, e);
+ }
+ }
+
+ private void copyFile(InputStream in, OutputStream out) throws IOException
+ {
+ byte[] buffer = new byte[1024];
+ int read;
+
+ while ((read = in.read(buffer)) != -1)
+ {
+ out.write(buffer, 0, read);
+ }
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java
new file mode 100644
index 0000000000..ab9f25b306
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java
@@ -0,0 +1,213 @@
+/*
+ * Copyright 2013 Dolphin Emulator Project
+ * Licensed under GPLv2
+ * Refer to the license.txt file included.
+ */
+
+package org.dolphinemu.dolphinemu;
+
+import android.util.Log;
+import android.view.Surface;
+
+/**
+ * Class which contains methods that interact
+ * with the native side of the Dolphin code.
+ */
+public final class NativeLibrary
+{
+ /**
+ * Button type for use in onTouchEvent
+ */
+ public static final class ButtonType
+ {
+ public static final int BUTTON_A = 0;
+ public static final int BUTTON_B = 1;
+ public static final int BUTTON_START = 2;
+ public static final int BUTTON_X = 3;
+ public static final int BUTTON_Y = 4;
+ public static final int BUTTON_Z = 5;
+ public static final int BUTTON_UP = 6;
+ public static final int BUTTON_DOWN = 7;
+ public static final int BUTTON_LEFT = 8;
+ public static final int BUTTON_RIGHT = 9;
+ public static final int STICK_MAIN = 10;
+ public static final int STICK_MAIN_UP = 11;
+ public static final int STICK_MAIN_DOWN = 12;
+ public static final int STICK_MAIN_LEFT = 13;
+ public static final int STICK_MAIN_RIGHT = 14;
+ public static final int STICK_C = 15;
+ public static final int STICK_C_UP = 16;
+ public static final int STICK_C_DOWN = 17;
+ public static final int STICK_C_LEFT = 18;
+ public static final int STICK_C_RIGHT = 19;
+ public static final int TRIGGER_L = 20;
+ public static final int TRIGGER_R = 21;
+ }
+
+ /**
+ * Button states
+ */
+ public static final class ButtonState
+ {
+ public static final int RELEASED = 0;
+ public static final int PRESSED = 1;
+ }
+
+ private NativeLibrary()
+ {
+ // Disallows instantiation.
+ }
+
+ /**
+ * Default touchscreen device
+ */
+ public static final String TouchScreenDevice = "Touchscreen";
+
+ /**
+ * 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).
+ *
+ * @return If we handled the button press.
+ */
+ public static native boolean 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.
+ *
+ * @param configFile The ini-based config file to get the value from.
+ * @param Section The section key that the actual key is in.
+ * @param Key The key to get the value from.
+ * @param Default The value to return in the event the given key doesn't exist.
+ *
+ * @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.
+ *
+ * @param configFile The ini-based config file to add the value to.
+ * @param Section The section key for the ini key
+ * @param Key The actual ini key to set.
+ * @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);
+
+ /**
+ * Gets the embedded banner within the given ISO/ROM.
+ *
+ * @param filename the file path to the ISO/ROM.
+ *
+ * @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.
+ *
+ * @param filename The file path to the ISO/ROM.
+ *
+ * @return the embedded title of the ISO/ROM.
+ */
+ public static native String GetTitle(String filename);
+
+ /**
+ * Gets the Dolphin version string.
+ *
+ * @return the Dolphin version string.
+ */
+ public static native String GetVersionString();
+
+ /**
+ * Returns if the phone supports NEON or not
+ *
+ * @return true if it supports NEON, false otherwise.
+ */
+ public static native boolean SupportsNEON();
+
+ /**
+ * Saves a screen capture of the game
+ *
+ */
+ public static native void SaveScreenShot();
+
+ /**
+ * Saves a game state to the slot number.
+ *
+ * @param slot The slot location to save state to.
+ */
+ public static native void SaveState(int slot);
+
+ /**
+ * Loads a game state from the slot number.
+ *
+ * @param slot The slot location to load state from.
+ */
+ public static native void LoadState(int slot);
+
+ /**
+ * Creates the initial folder structure in /sdcard/dolphin-emu/
+ */
+ public static native void CreateUserFolders();
+
+ /**
+ * Sets the current working user directory
+ * If not set, it auto-detects a location
+ */
+ public static native void SetUserDirectory(String directory);
+
+ /**
+ * Returns the current working user directory
+ */
+ public static native String GetUserDirectory();
+
+ /**
+ * Begins emulation.
+ *
+ * @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();
+
+ /** Native EGL functions not exposed by Java bindings **/
+ public static native void eglBindAPI(int api);
+
+ static
+ {
+ try
+ {
+ System.loadLibrary("main");
+ }
+ catch (UnsatisfiedLinkError ex)
+ {
+ Log.e("NativeLibrary", ex.toString());
+ }
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/about/AboutActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/about/AboutActivity.java
new file mode 100644
index 0000000000..33b30d9a43
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/about/AboutActivity.java
@@ -0,0 +1,122 @@
+/**
+ * Copyright 2014 Dolphin Emulator Project
+ * Licensed under GPLv2
+ * Refer to the license.txt file included.
+ */
+
+package org.dolphinemu.dolphinemu.about;
+
+import org.dolphinemu.dolphinemu.R;
+import org.dolphinemu.dolphinemu.utils.EGLHelper;
+
+import android.app.Activity;
+import android.app.Fragment;
+import android.app.FragmentManager;
+import android.os.Bundle;
+import android.support.v13.app.FragmentPagerAdapter;
+import android.support.v4.view.ViewPager;
+
+
+/**
+ * Activity for the about menu, which displays info
+ * related to the CPU and GPU. Along with misc other info.
+ */
+public final class AboutActivity extends Activity
+{
+ private final EGLHelper eglHelper = new EGLHelper(EGLHelper.EGL_OPENGL_ES2_BIT);
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+
+ // Set the view pager
+ setContentView(R.layout.viewpager);
+
+ // Initialize the viewpager.
+ final ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
+ viewPager.setAdapter(new ViewPagerAdapter(getFragmentManager()));
+ }
+
+ @Override
+ public void onDestroy()
+ {
+ super.onDestroy();
+
+ eglHelper.closeHelper();
+ }
+
+ /**
+ * {@link FragmentPagerAdapter} subclass responsible for handling
+ * the individual {@link Fragment}s within the {@link ViewPager}.
+ */
+ private final class ViewPagerAdapter extends FragmentPagerAdapter
+ {
+ private final String[] pageTitles = {
+ getString(R.string.general),
+ getString(R.string.cpu),
+ getString(R.string.gles_two),
+ getString(R.string.gles_three),
+ getString(R.string.desktop_gl),
+ };
+
+ public ViewPagerAdapter(FragmentManager fm)
+ {
+ super(fm);
+ }
+
+ @Override
+ public Fragment getItem(int position)
+ {
+ if (position == 0)
+ {
+ return new DolphinInfoFragment();
+ }
+ else if (position == 1)
+ {
+ return new CPUInfoFragment(); // CPU
+ }
+ else if (position == 2) // GLES 2
+ {
+ return new GLES2InfoFragment();
+ }
+ else if (position == 3) // GLES 3 or OpenGL (depending on circumstances)
+ {
+ if (eglHelper.supportsGLES3())
+ return new GLES3InfoFragment();
+ else
+ return new GLInfoFragment(); // GLES3 not supported, but OpenGL is.
+ }
+ else if (position == 4) // OpenGL fragment
+ {
+ return new GLInfoFragment();
+ }
+
+ // This should never happen.
+ return null;
+ }
+
+ @Override
+ public int getCount()
+ {
+ if (eglHelper.supportsGLES3() && eglHelper.supportsOpenGL())
+ {
+ return 5;
+ }
+ else if (!eglHelper.supportsGLES3() && !eglHelper.supportsOpenGL())
+ {
+ return 3;
+ }
+ else // Either regular OpenGL or GLES3 isn't supported
+ {
+ return 4;
+ }
+ }
+
+ @Override
+ public CharSequence getPageTitle(int position)
+ {
+ return pageTitles[position];
+ }
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/about/AboutFragmentItem.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/about/AboutFragmentItem.java
new file mode 100644
index 0000000000..ffc6c51c5a
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/about/AboutFragmentItem.java
@@ -0,0 +1,48 @@
+/**
+ * Copyright 2014 Dolphin Emulator Project
+ * Licensed under GPLv2
+ * Refer to the license.txt file included.
+ */
+
+package org.dolphinemu.dolphinemu.about;
+
+/**
+ * Represents an item within an info fragment in the About menu.
+ */
+final class AboutFragmentItem
+{
+ private final String title;
+ private final String subtitle;
+
+ /**
+ * Constructor
+ *
+ * @param title The title of this item.
+ * @param subtitle The subtitle for this item.
+ */
+ public AboutFragmentItem(String title, String subtitle)
+ {
+ this.title = title;
+ this.subtitle = subtitle;
+ }
+
+ /**
+ * Gets the title of this item.
+ *
+ * @return the title of this item.
+ */
+ public String getTitle()
+ {
+ return title;
+ }
+
+ /**
+ * Gets the subtitle of this item.
+ *
+ * @return the subtitle of this item.
+ */
+ public String getSubTitle()
+ {
+ return subtitle;
+ }
+} \ No newline at end of file
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/about/AboutInfoFragmentAdapter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/about/AboutInfoFragmentAdapter.java
new file mode 100644
index 0000000000..abf2fd26cc
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/about/AboutInfoFragmentAdapter.java
@@ -0,0 +1,67 @@
+/**
+ * Copyright 2014 Dolphin Emulator Project
+ * Licensed under GPLv2
+ * Refer to the license.txt file included.
+ */
+
+package org.dolphinemu.dolphinemu.about;
+
+import java.util.List;
+
+import org.dolphinemu.dolphinemu.R;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.TextView;
+
+/**
+ * {@link ArrayAdapter} subclass specifically for the
+ * information fragments within the about menu.
+ */
+final class AboutInfoFragmentAdapter extends ArrayAdapter<AboutFragmentItem>
+{
+ private final int id;
+ private final List<AboutFragmentItem> items;
+
+ public AboutInfoFragmentAdapter(Context ctx, int id, List<AboutFragmentItem> items)
+ {
+ super(ctx, id, items);
+
+ this.id = id;
+ this.items = items;
+ }
+
+ @Override
+ public AboutFragmentItem getItem(int index)
+ {
+ return items.get(index);
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent)
+ {
+ if (convertView == null)
+ {
+ LayoutInflater vi = LayoutInflater.from(getContext());
+ convertView = vi.inflate(id, parent, false);
+ }
+
+ final AboutFragmentItem item = items.get(position);
+ if (item != null)
+ {
+ TextView title = (TextView) convertView.findViewById(R.id.AboutItemTitle);
+ TextView subtitle = (TextView) convertView.findViewById(R.id.AboutItemSubTitle);
+
+ if (title != null)
+ title.setText(item.getTitle());
+
+ if (subtitle != null)
+ subtitle.setText(item.getSubTitle());
+ }
+
+ return convertView;
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/about/CPUInfoFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/about/CPUInfoFragment.java
new file mode 100644
index 0000000000..4183740c24
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/about/CPUInfoFragment.java
@@ -0,0 +1,52 @@
+/**
+ * Copyright 2014 Dolphin Emulator Project
+ * Licensed under GPLv2
+ * Refer to the license.txt file included.
+ */
+
+package org.dolphinemu.dolphinemu.about;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.dolphinemu.dolphinemu.R;
+import org.dolphinemu.dolphinemu.utils.CPUHelper;
+
+import android.app.ListFragment;
+import android.os.Build;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ListView;
+
+/**
+ * {@link ListFragment class that is responsible
+ * for displaying information related to the CPU.
+ */
+public final class CPUInfoFragment extends ListFragment
+{
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
+ {
+ ListView rootView = (ListView) inflater.inflate(R.layout.gamelist_listview, container, false);
+ List<AboutFragmentItem> items = new ArrayList<AboutFragmentItem>();
+
+ CPUHelper cpuHelper = new CPUHelper(getActivity());
+
+ items.add(new AboutFragmentItem(getString(R.string.cpu_info), cpuHelper.getProcessorInfo()));
+ items.add(new AboutFragmentItem(getString(R.string.cpu_type), cpuHelper.getProcessorType()));
+ items.add(new AboutFragmentItem(getString(R.string.cpu_abi_one), Build.CPU_ABI));
+ items.add(new AboutFragmentItem(getString(R.string.cpu_abi_two), Build.CPU_ABI2));
+ items.add(new AboutFragmentItem(getString(R.string.num_cores), Integer.toString(cpuHelper.getNumCores())));
+ items.add(new AboutFragmentItem(getString(R.string.cpu_features), cpuHelper.getFeatures()));
+ items.add(new AboutFragmentItem(getString(R.string.cpu_hardware), Build.HARDWARE));
+ if (CPUHelper.isARM())
+ items.add(new AboutFragmentItem(getString(R.string.cpu_implementer), cpuHelper.getImplementer()));
+
+ AboutInfoFragmentAdapter adapter = new AboutInfoFragmentAdapter(getActivity(), R.layout.about_layout, items);
+ rootView.setAdapter(adapter);
+
+ return rootView;
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/about/DolphinInfoFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/about/DolphinInfoFragment.java
new file mode 100644
index 0000000000..69f8961f25
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/about/DolphinInfoFragment.java
@@ -0,0 +1,48 @@
+/**
+ * Copyright 2014 Dolphin Emulator Project
+ * Licensed under GPLv2
+ * Refer to the license.txt file included.
+ */
+
+package org.dolphinemu.dolphinemu.about;
+
+import android.app.ListFragment;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ListView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.dolphinemu.dolphinemu.NativeLibrary;
+import org.dolphinemu.dolphinemu.R;
+import org.dolphinemu.dolphinemu.utils.EGLHelper;
+
+/**
+ * Represents the about screen.
+ */
+public final class DolphinInfoFragment extends ListFragment
+{
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
+ {
+ ListView rootView = (ListView) inflater.inflate(R.layout.gamelist_listview, container, false);
+ EGLHelper eglHelper = new EGLHelper(EGLHelper.EGL_OPENGL_ES2_BIT);
+
+ final String yes = getString(R.string.yes);
+ final String no = getString(R.string.no);
+
+ List<AboutFragmentItem> Input = new ArrayList<AboutFragmentItem>();
+ Input.add(new AboutFragmentItem(getString(R.string.build_revision), NativeLibrary.GetVersionString()));
+ Input.add(new AboutFragmentItem(getString(R.string.supports_gles3), eglHelper.supportsGLES3() ? yes : no));
+ Input.add(new AboutFragmentItem(getString(R.string.supports_neon), NativeLibrary.SupportsNEON() ? yes : no));
+
+ AboutInfoFragmentAdapter adapter = new AboutInfoFragmentAdapter(getActivity(), R.layout.about_layout, Input);
+ rootView.setAdapter(adapter);
+ rootView.setEnabled(false); // Makes the list view non-clickable.
+
+ return rootView;
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/about/GLES2InfoFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/about/GLES2InfoFragment.java
new file mode 100644
index 0000000000..08784dbd7d
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/about/GLES2InfoFragment.java
@@ -0,0 +1,82 @@
+/**
+ * Copyright 2014 Dolphin Emulator Project
+ * Licensed under GPLv2
+ * Refer to the license.txt file included.
+ */
+
+package org.dolphinemu.dolphinemu.about;
+
+import android.app.ListFragment;
+import android.opengl.GLES20;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ListView;
+
+import org.dolphinemu.dolphinemu.R;
+import org.dolphinemu.dolphinemu.about.Limit.Type;
+import org.dolphinemu.dolphinemu.utils.EGLHelper;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * {@link ListFragment} responsible for displaying
+ * information relating to OpenGL ES 2.
+ */
+public final class GLES2InfoFragment extends ListFragment
+{
+ private final Limit[] Limits = {
+ new Limit("Vendor", GLES20.GL_VENDOR, Type.STRING),
+ new Limit("Version", GLES20.GL_VERSION, Type.STRING),
+ new Limit("Renderer", GLES20.GL_RENDERER, Type.STRING),
+ new Limit("GLSL version", GLES20.GL_SHADING_LANGUAGE_VERSION, Type.STRING),
+ // GLES 2.0 Limits
+ new Limit("Aliased Point Size", GLES20.GL_ALIASED_POINT_SIZE_RANGE, Type.INTEGER_RANGE),
+ new Limit("Aliased Line Width ", GLES20.GL_ALIASED_LINE_WIDTH_RANGE, Type.INTEGER_RANGE),
+ new Limit("Max Texture Size", GLES20.GL_MAX_TEXTURE_SIZE, Type.INTEGER),
+ new Limit("Viewport Dimensions", GLES20.GL_MAX_VIEWPORT_DIMS, Type.INTEGER_RANGE),
+ new Limit("Subpixel Bits", GLES20.GL_SUBPIXEL_BITS, Type.INTEGER),
+ new Limit("Max Vertex Attributes", GLES20.GL_MAX_VERTEX_ATTRIBS, Type.INTEGER),
+ new Limit("Max Vertex Uniform Vectors", GLES20.GL_MAX_VERTEX_UNIFORM_VECTORS, Type.INTEGER),
+ new Limit("Max Varying Vectors", GLES20.GL_MAX_VARYING_VECTORS, Type.INTEGER),
+ new Limit("Max Combined Texture Units", GLES20.GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, Type.INTEGER),
+ new Limit("Max Vertex Texture Units", GLES20.GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, Type.INTEGER),
+ new Limit("Max Texture Units", GLES20.GL_MAX_TEXTURE_IMAGE_UNITS, Type.INTEGER),
+ new Limit("Max Fragment Uniform Vectors", GLES20.GL_MAX_FRAGMENT_UNIFORM_VECTORS, Type.INTEGER),
+ new Limit("Max Cubemap Texture Size", GLES20.GL_MAX_CUBE_MAP_TEXTURE_SIZE, Type.INTEGER),
+ new Limit("Shader Binary Formats", GLES20.GL_NUM_SHADER_BINARY_FORMATS, Type.INTEGER),
+ new Limit("Max Framebuffer Size", GLES20.GL_MAX_RENDERBUFFER_SIZE, Type.INTEGER),
+ };
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
+ {
+ final EGLHelper eglHelper = new EGLHelper(EGLHelper.EGL_OPENGL_ES2_BIT);
+
+ ListView rootView = (ListView) inflater.inflate(R.layout.gamelist_listview, container, false);
+ List<AboutFragmentItem> Input = new ArrayList<AboutFragmentItem>();
+
+ for (Limit limit : Limits)
+ {
+ Log.i("GLES2InfoFragment", "Getting enum " + limit.name);
+ Input.add(new AboutFragmentItem(limit.name, limit.GetValue(eglHelper)));
+ }
+
+ // Get extensions manually
+ String[] extensions = eglHelper.glGetString(GLES20.GL_EXTENSIONS).split(" ");
+ StringBuilder extensionsBuilder = new StringBuilder();
+ for (String extension : extensions)
+ {
+ extensionsBuilder.append(extension).append('\n');
+ }
+ Input.add(new AboutFragmentItem("OpenGL ES 2.0 Extensions", extensionsBuilder.toString()));
+
+ AboutInfoFragmentAdapter adapter = new AboutInfoFragmentAdapter(getActivity(), R.layout.about_layout, Input);
+ rootView.setAdapter(adapter);
+
+ return rootView;
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/about/GLES3InfoFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/about/GLES3InfoFragment.java
new file mode 100644
index 0000000000..2c4649fdfa
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/about/GLES3InfoFragment.java
@@ -0,0 +1,114 @@
+/**
+ * Copyright 2014 Dolphin Emulator Project
+ * Licensed under GPLv2
+ * Refer to the license.txt file included.
+ */
+
+package org.dolphinemu.dolphinemu.about;
+
+import android.app.ListFragment;
+import android.opengl.GLES30;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ListView;
+
+import org.dolphinemu.dolphinemu.R;
+import org.dolphinemu.dolphinemu.about.Limit.Type;
+import org.dolphinemu.dolphinemu.utils.EGLHelper;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * {@link ListFragment} responsible for displaying
+ * information relating to OpenGL ES 3.
+ */
+public final class GLES3InfoFragment extends ListFragment
+{
+ private final Limit[] Limits = {
+ new Limit("Vendor", GLES30.GL_VENDOR, Type.STRING),
+ new Limit("Version", GLES30.GL_VERSION, Type.STRING),
+ new Limit("Renderer", GLES30.GL_RENDERER, Type.STRING),
+ new Limit("GLSL version", GLES30.GL_SHADING_LANGUAGE_VERSION, Type.STRING),
+ // GLES 2.0 Limits
+ new Limit("Aliased Point Size", GLES30.GL_ALIASED_POINT_SIZE_RANGE, Type.INTEGER_RANGE),
+ new Limit("Aliased Line Width ", GLES30.GL_ALIASED_LINE_WIDTH_RANGE, Type.INTEGER_RANGE),
+ new Limit("Max Texture Size", GLES30.GL_MAX_TEXTURE_SIZE, Type.INTEGER),
+ new Limit("Viewport Dimensions", GLES30.GL_MAX_VIEWPORT_DIMS, Type.INTEGER_RANGE),
+ new Limit("Subpixel Bits", GLES30.GL_SUBPIXEL_BITS, Type.INTEGER),
+ new Limit("Max Vertex Attributes", GLES30.GL_MAX_VERTEX_ATTRIBS, Type.INTEGER),
+ new Limit("Max Vertex Uniform Vectors", GLES30.GL_MAX_VERTEX_UNIFORM_VECTORS, Type.INTEGER),
+ new Limit("Max Varying Vectors", GLES30.GL_MAX_VARYING_VECTORS, Type.INTEGER),
+ new Limit("Max Combined Texture Units", GLES30.GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, Type.INTEGER),
+ new Limit("Max Vertex Texture Units", GLES30.GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, Type.INTEGER),
+ new Limit("Max Texture Units", GLES30.GL_MAX_TEXTURE_IMAGE_UNITS, Type.INTEGER),
+ new Limit("Max Fragment Uniform Vectors", GLES30.GL_MAX_FRAGMENT_UNIFORM_VECTORS, Type.INTEGER),
+ new Limit("Max Cubemap Texture Size", GLES30.GL_MAX_CUBE_MAP_TEXTURE_SIZE, Type.INTEGER),
+ new Limit("Shader Binary Formats", GLES30.GL_NUM_SHADER_BINARY_FORMATS, Type.INTEGER),
+ new Limit("Max Framebuffer Size", GLES30.GL_MAX_RENDERBUFFER_SIZE, Type.INTEGER),
+ // GLES 3.0 limits
+ new Limit("Max 3D Texture size", GLES30.GL_MAX_3D_TEXTURE_SIZE, Type.INTEGER),
+ new Limit("Max Element Vertices", GLES30.GL_MAX_ELEMENTS_VERTICES, Type.INTEGER),
+ new Limit("Max Element Indices", GLES30.GL_MAX_ELEMENTS_INDICES, Type.INTEGER),
+ new Limit("Max Draw Buffers", GLES30.GL_MAX_DRAW_BUFFERS, Type.INTEGER),
+ new Limit("Max Fragment Uniform Components", GLES30.GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, Type.INTEGER),
+ new Limit("Max Vertex Uniform Components", GLES30.GL_MAX_VERTEX_UNIFORM_COMPONENTS, Type.INTEGER),
+ new Limit("Number of Extensions", GLES30.GL_NUM_EXTENSIONS, Type.INTEGER),
+ new Limit("Max Array Texture Layers", GLES30.GL_MAX_ARRAY_TEXTURE_LAYERS, Type.INTEGER),
+ new Limit("Min Program Texel Offset", GLES30.GL_MIN_PROGRAM_TEXEL_OFFSET, Type.INTEGER),
+ new Limit("Max Program Texel Offset", GLES30.GL_MAX_PROGRAM_TEXEL_OFFSET, Type.INTEGER),
+ new Limit("Max Varying Components", GLES30.GL_MAX_VARYING_COMPONENTS, Type.INTEGER),
+ new Limit("Max TF Varying Length", GLES30.GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, Type.INTEGER),
+ new Limit("Max TF Separate Components", GLES30.GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS, Type.INTEGER),
+ new Limit("Max TF Interleaved Components", GLES30.GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, Type.INTEGER),
+ new Limit("Max TF Separate Attributes", GLES30.GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, Type.INTEGER),
+ new Limit("Max Color Attachments", GLES30.GL_MAX_COLOR_ATTACHMENTS, Type.INTEGER),
+ new Limit("Max Samples", GLES30.GL_MAX_SAMPLES, Type.INTEGER),
+ new Limit("Max Vertex UBOs", GLES30.GL_MAX_VERTEX_UNIFORM_BLOCKS, Type.INTEGER),
+ new Limit("Max Fragment UBOs", GLES30.GL_MAX_FRAGMENT_UNIFORM_BLOCKS, Type.INTEGER),
+ new Limit("Max Combined UBOs", GLES30.GL_MAX_COMBINED_UNIFORM_BLOCKS, Type.INTEGER),
+ new Limit("Max Uniform Buffer Bindings", GLES30.GL_MAX_UNIFORM_BUFFER_BINDINGS, Type.INTEGER),
+ new Limit("Max UBO Size", GLES30.GL_MAX_UNIFORM_BLOCK_SIZE, Type.INTEGER),
+ new Limit("Max Combined Vertex Uniform Components", GLES30.GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS, Type.INTEGER),
+ new Limit("Max Combined Fragment Uniform Components", GLES30.GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS, Type.INTEGER),
+ new Limit("UBO Alignment", GLES30.GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, Type.INTEGER),
+ new Limit("Max Vertex Output Components", GLES30.GL_MAX_VERTEX_OUTPUT_COMPONENTS, Type.INTEGER),
+ new Limit("Max Fragment Input Components", GLES30.GL_MAX_FRAGMENT_INPUT_COMPONENTS, Type.INTEGER),
+ new Limit("Max Server Wait Timeout", GLES30.GL_MAX_SERVER_WAIT_TIMEOUT, Type.INTEGER),
+ new Limit("Program Binary Formats", GLES30.GL_NUM_PROGRAM_BINARY_FORMATS, Type.INTEGER),
+ new Limit("Max Element Index", GLES30.GL_MAX_ELEMENT_INDEX, Type.INTEGER),
+ new Limit("Sample Counts", GLES30.GL_NUM_SAMPLE_COUNTS, Type.INTEGER),
+ };
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
+ {
+ final EGLHelper eglHelper = new EGLHelper(EGLHelper.EGL_OPENGL_ES3_BIT_KHR);
+
+ ListView rootView = (ListView) inflater.inflate(R.layout.gamelist_listview, container, false);
+ List<AboutFragmentItem> Input = new ArrayList<AboutFragmentItem>();
+
+ for (Limit limit : Limits)
+ {
+ Log.i("GLES3InfoFragment", "Getting enum " + limit.name);
+ Input.add(new AboutFragmentItem(limit.name, limit.GetValue(eglHelper)));
+ }
+
+ // Get extensions manually
+ int numExtensions = eglHelper.glGetInteger(GLES30.GL_NUM_EXTENSIONS);
+ StringBuilder extensionsBuilder = new StringBuilder();
+ for (int i = 0; i < numExtensions; i++)
+ {
+ extensionsBuilder.append(eglHelper.glGetStringi(GLES30.GL_EXTENSIONS, i)).append('\n');
+ }
+ Input.add(new AboutFragmentItem("OpenGL ES 3.0 Extensions", extensionsBuilder.toString()));
+
+ AboutInfoFragmentAdapter adapter = new AboutInfoFragmentAdapter(getActivity(), R.layout.about_layout, Input);
+ rootView.setAdapter(adapter);
+
+ return rootView;
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/about/GLInfoFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/about/GLInfoFragment.java
new file mode 100644
index 0000000000..828b8dce92
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/about/GLInfoFragment.java
@@ -0,0 +1,69 @@
+/**
+ * Copyright 2014 Dolphin Emulator Project
+ * Licensed under GPLv2
+ * Refer to the license.txt file included.
+ */
+
+package org.dolphinemu.dolphinemu.about;
+
+import android.app.ListFragment;
+import android.opengl.GLES20;
+import android.opengl.GLES30;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ListView;
+
+import org.dolphinemu.dolphinemu.R;
+import org.dolphinemu.dolphinemu.about.Limit.Type;
+import org.dolphinemu.dolphinemu.utils.EGLHelper;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.microedition.khronos.opengles.GL10;
+
+/**
+ * {@link ListFragment} responsible for displaying
+ * information relating to OpenGL.
+ */
+public final class GLInfoFragment extends ListFragment
+{
+ private final Limit[] Limits = {
+ new Limit("Vendor", GL10.GL_VENDOR, Type.STRING),
+ new Limit("Version", GL10.GL_VERSION, Type.STRING),
+ new Limit("Renderer", GL10.GL_RENDERER, Type.STRING),
+ new Limit("GLSL version", GLES20.GL_SHADING_LANGUAGE_VERSION, Type.STRING),
+ };
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
+ {
+ final EGLHelper eglHelper = new EGLHelper(EGLHelper.EGL_OPENGL_BIT);
+
+ ListView rootView = (ListView) inflater.inflate(R.layout.gamelist_listview, container, false);
+ List<AboutFragmentItem> Input = new ArrayList<AboutFragmentItem>();
+
+ for (Limit limit : Limits)
+ {
+ Log.i("GLInfoFragment", "Getting enum " + limit.name);
+ Input.add(new AboutFragmentItem(limit.name, limit.GetValue(eglHelper)));
+ }
+
+ // Get extensions manually
+ int numExtensions = eglHelper.glGetInteger(GLES30.GL_NUM_EXTENSIONS);
+ StringBuilder extensionsBuilder = new StringBuilder();
+ for (int i = 0; i < numExtensions; i++)
+ {
+ extensionsBuilder.append(eglHelper.glGetStringi(GL10.GL_EXTENSIONS, i)).append('\n');
+ }
+ Input.add(new AboutFragmentItem("OpenGL Extensions", extensionsBuilder.toString()));
+
+ AboutInfoFragmentAdapter adapter = new AboutInfoFragmentAdapter(getActivity(), R.layout.about_layout, Input);
+ rootView.setAdapter(adapter);
+
+ return rootView;
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/about/Limit.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/about/Limit.java
new file mode 100644
index 0000000000..9cbd15f62d
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/about/Limit.java
@@ -0,0 +1,71 @@
+/**
+ * Copyright 2014 Dolphin Emulator Project
+ * Licensed under GPLv2
+ * Refer to the license.txt file included.
+ */
+
+package org.dolphinemu.dolphinemu.about;
+
+import org.dolphinemu.dolphinemu.utils.EGLHelper;
+
+final class Limit
+{
+ /**
+ * Possible types a Limit can be.
+ */
+ enum Type
+ {
+ /** Generic string */
+ STRING,
+ /** Integer constant */
+ INTEGER,
+ /** Range of integers */
+ INTEGER_RANGE,
+ }
+
+ /** Name of this limit */
+ public final String name;
+ /** The GL constant that represents this limit.*/
+ public final int glEnum;
+ /** The {@link Type} of this limit. */
+ public final Type type;
+
+ /**
+ * Constructor
+ *
+ * @param name Name of the limit.
+ * @param glEnum The GL constant that represents this limit.
+ * @param type The {@link Type} of this limit.
+ */
+ public Limit(String name, int glEnum, Type type)
+ {
+ this.name = name;
+ this.glEnum = glEnum;
+ this.type = type;
+ }
+
+ /**
+ * Retrieves the information represented by this limit.
+ *
+ * @param context {@link EGLHelper} context to retrieve the limit with.
+ *
+ * @return the information represented by this limit.
+ */
+ public String GetValue(EGLHelper context)
+ {
+ if (type == Type.INTEGER)
+ {
+ return Integer.toString(context.glGetInteger(glEnum));
+ }
+ else if (type == Type.INTEGER_RANGE)
+ {
+ int[] data = new int[2];
+ context.getGL().glGetIntegerv(glEnum, data, 0);
+
+ return String.format("[%d, %d]", data[0], data[1]);
+ }
+
+ // If neither of the above type, assume it's a string.
+ return context.glGetString(glEnum);
+ }
+} \ No newline at end of file
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/emulation/EmulationActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/emulation/EmulationActivity.java
new file mode 100644
index 0000000000..7775e2124c
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/emulation/EmulationActivity.java
@@ -0,0 +1,316 @@
+/**
+ * Copyright 2013 Dolphin Emulator Project
+ * Licensed under GPLv2
+ * Refer to the license.txt file included.
+ */
+
+package org.dolphinemu.dolphinemu.emulation;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.graphics.Color;
+import android.graphics.drawable.ColorDrawable;
+import android.os.Bundle;
+import android.preference.PreferenceManager;
+import android.view.InputDevice;
+import android.view.KeyEvent;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowManager.LayoutParams;
+
+import org.dolphinemu.dolphinemu.NativeLibrary;
+import org.dolphinemu.dolphinemu.R;
+import org.dolphinemu.dolphinemu.settings.input.InputConfigFragment;
+
+import java.util.List;
+
+/**
+ * This is the activity where all of the emulation handling happens.
+ * This activity is responsible for displaying the SurfaceView that we render to.
+ */
+public final class EmulationActivity extends Activity
+{
+ private boolean Running;
+ private boolean IsActionBarHidden = false;
+ private SharedPreferences sharedPrefs;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+
+ sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
+
+ // Request window features for the emulation view.
+ getWindow().addFlags(LayoutParams.FLAG_KEEP_SCREEN_ON);
+ getWindow().addFlags(LayoutParams.FLAG_FULLSCREEN);
+ getWindow().requestFeature(Window.FEATURE_ACTION_BAR_OVERLAY);
+
+ // Set the transparency for the action bar.
+ ColorDrawable actionBarBackground = new ColorDrawable(Color.parseColor("#303030"));
+ actionBarBackground.setAlpha(175);
+ getActionBar().setBackgroundDrawable(actionBarBackground);
+
+ // Get the intent passed from the GameList when the game
+ // was selected. This is so the path of the game can be retrieved
+ // and set on the native side of the code so the emulator can actually
+ // load the game.
+ Intent gameToEmulate = getIntent();
+ NativeLibrary.SetFilename(gameToEmulate.getStringExtra("SelectedGame"));
+ Running = true;
+
+ // Set the emulation window.
+ setContentView(R.layout.emulation_view);
+
+ // If the input overlay was previously disabled, then don't show it.
+ if (!sharedPrefs.getBoolean("showInputOverlay", true))
+ {
+ findViewById(R.id.emulationControlOverlay).setVisibility(View.INVISIBLE);
+ }
+
+ // Hide the action bar by default so it doesn't get in the way.
+ getActionBar().hide();
+ IsActionBarHidden = true;
+ }
+
+ @Override
+ public void onStop()
+ {
+ super.onStop();
+
+ if (Running)
+ NativeLibrary.StopEmulation();
+ }
+
+ @Override
+ public void onPause()
+ {
+ super.onPause();
+
+ if (Running)
+ NativeLibrary.PauseEmulation();
+ }
+
+ @Override
+ public void onResume()
+ {
+ super.onResume();
+
+ if (Running)
+ NativeLibrary.UnPauseEmulation();
+ }
+
+ @Override
+ public void onDestroy()
+ {
+ super.onDestroy();
+
+ if (Running)
+ {
+ NativeLibrary.StopEmulation();
+ Running = false;
+ }
+ }
+
+ @Override
+ public void onBackPressed()
+ {
+ // The back button in the emulation
+ // window is the toggle for the action bar.
+ if (IsActionBarHidden)
+ {
+ IsActionBarHidden = false;
+ getActionBar().show();
+ }
+ else
+ {
+ IsActionBarHidden = true;
+ getActionBar().hide();
+ }
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu)
+ {
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.emuwindow_overlay, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu)
+ {
+ // Determine which string the "Enable Input Overlay" menu item should have
+ // depending on its visibility at the time of preparing the options menu.
+ if (!sharedPrefs.getBoolean("showInputOverlay", true))
+ {
+ menu.findItem(R.id.enableInputOverlay).setTitle(R.string.enable_input_overlay);
+ }
+ else
+ {
+ menu.findItem(R.id.enableInputOverlay).setTitle(R.string.disable_input_overlay);
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean onMenuItemSelected(int itemId, MenuItem item)
+ {
+ switch(item.getItemId())
+ {
+ // Enable/Disable input overlay.
+ case R.id.enableInputOverlay:
+ {
+ View overlay = findViewById(R.id.emulationControlOverlay);
+
+ // Show the overlay
+ if (item.getTitle().equals(getString(R.string.enable_input_overlay)))
+ {
+ overlay.setVisibility(View.VISIBLE);
+ item.setTitle(R.string.disable_input_overlay);
+ sharedPrefs.edit().putBoolean("showInputOverlay", true).apply();
+ }
+ else // Hide the overlay
+ {
+ overlay.setVisibility(View.INVISIBLE);
+ item.setTitle(R.string.enable_input_overlay);
+ sharedPrefs.edit().putBoolean("showInputOverlay", false).apply();
+ }
+
+ return true;
+ }
+
+ // Screenshot capturing
+ case R.id.takeScreenshot:
+ NativeLibrary.SaveScreenShot();
+ return true;
+
+ // Save state slots
+ case R.id.saveSlot1:
+ NativeLibrary.SaveState(0);
+ return true;
+
+ case R.id.saveSlot2:
+ NativeLibrary.SaveState(1);
+ return true;
+
+ case R.id.saveSlot3:
+ NativeLibrary.SaveState(2);
+ return true;
+
+ case R.id.saveSlot4:
+ NativeLibrary.SaveState(3);
+ return true;
+
+ case R.id.saveSlot5:
+ NativeLibrary.SaveState(4);
+ return true;
+
+ // Load state slots
+ case R.id.loadSlot1:
+ NativeLibrary.LoadState(0);
+ return true;
+
+ case R.id.loadSlot2:
+ NativeLibrary.LoadState(1);
+ return true;
+
+ case R.id.loadSlot3:
+ NativeLibrary.LoadState(2);
+ return true;
+
+ case R.id.loadSlot4:
+ NativeLibrary.LoadState(3);
+ return true;
+
+ case R.id.loadSlot5:
+ NativeLibrary.LoadState(4);
+ return true;
+
+ case R.id.exitEmulation:
+ {
+ // Create a confirmation method for quitting the current emulation instance.
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setTitle(R.string.overlay_exit_emulation);
+ builder.setMessage(R.string.overlay_exit_emulation_confirm);
+ builder.setNegativeButton(R.string.no, null);
+ builder.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which)
+ {
+ onDestroy();
+ }
+ });
+ builder.show();
+ return true;
+ }
+
+ default:
+ return super.onMenuItemSelected(itemId, item);
+ }
+ }
+
+ // Gets button presses
+ @Override
+ public boolean dispatchKeyEvent(KeyEvent event)
+ {
+ int action = 0;
+
+ if (Running)
+ {
+ switch (event.getAction())
+ {
+ case KeyEvent.ACTION_DOWN:
+ // Handling the case where the back button is pressed.
+ if (event.getKeyCode() == KeyEvent.KEYCODE_BACK)
+ {
+ onBackPressed();
+ return true;
+ }
+
+ // Normal key events.
+ action = NativeLibrary.ButtonState.PRESSED;
+ break;
+ case KeyEvent.ACTION_UP:
+ action = NativeLibrary.ButtonState.RELEASED;
+ break;
+ default:
+ return false;
+ }
+ InputDevice input = event.getDevice();
+ boolean handled = NativeLibrary.onGamePadEvent(InputConfigFragment.getInputDesc(input), event.getKeyCode(), action);
+ return handled;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean dispatchGenericMotionEvent(MotionEvent event)
+ {
+ if (((event.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) == 0) || !Running)
+ {
+ return super.dispatchGenericMotionEvent(event);
+ }
+
+ // Don't attempt to do anything if we are disconnecting a device.
+ if (event.getActionMasked() == MotionEvent.ACTION_CANCEL)
+ return true;
+
+ InputDevice input = event.getDevice();
+ List<InputDevice.MotionRange> motions = input.getMotionRanges();
+
+ for (InputDevice.MotionRange range : motions)
+ {
+ NativeLibrary.onGamePadMoveEvent(InputConfigFragment.getInputDesc(input), range.getAxis(), event.getAxisValue(range.getAxis()));
+ }
+
+ return true;
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/emulation/NativeGLSurfaceView.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/emulation/NativeGLSurfaceView.java
new file mode 100644
index 0000000000..90acf05e8e
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/emulation/NativeGLSurfaceView.java
@@ -0,0 +1,74 @@
+/**
+ * Copyright 2013 Dolphin Emulator Project
+ * Licensed under GPLv2
+ * Refer to the license.txt file included.
+ */
+
+package org.dolphinemu.dolphinemu.emulation;
+
+import org.dolphinemu.dolphinemu.NativeLibrary;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+
+/**
+ * The {@link SurfaceView} that rendering is performed on.
+ */
+public final class NativeGLSurfaceView extends SurfaceView
+{
+ private static Thread myRun;
+ private static boolean Running = false;
+ private static boolean Created = false;
+
+ /**
+ * Constructor.
+ *
+ * @param context The current {@link Context}.
+ * @param attribs An AttributeSet for retrieving data from XML files.
+ */
+ public NativeGLSurfaceView(Context context, AttributeSet attribs)
+ {
+ super(context, attribs);
+
+ if (!Created)
+ {
+ myRun = new Thread()
+ {
+ @Override
+ public void run() {
+
+ NativeLibrary.Run(getHolder().getSurface());
+ Created = false;
+ Running = false;
+ }
+ };
+
+ getHolder().addCallback(new SurfaceHolder.Callback()
+ {
+ public void surfaceCreated(SurfaceHolder holder)
+ {
+ // TODO Auto-generated method stub
+ if (!Running)
+ {
+ myRun.start();
+ Running = true;
+ }
+ }
+
+ public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
+ {
+ // TODO Auto-generated method stub
+ }
+
+ public void surfaceDestroyed(SurfaceHolder holder)
+ {
+ // TODO Auto-generated method stub
+ }
+ });
+
+ Created = true;
+ }
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/emulation/overlay/InputOverlay.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/emulation/overlay/InputOverlay.java
new file mode 100644
index 0000000000..2a4cb10383
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/emulation/overlay/InputOverlay.java
@@ -0,0 +1,288 @@
+/**
+ * Copyright 2013 Dolphin Emulator Project
+ * Licensed under GPLv2
+ * Refer to the license.txt file included.
+ */
+
+package org.dolphinemu.dolphinemu.emulation.overlay;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.preference.PreferenceManager;
+import android.util.AttributeSet;
+import android.util.DisplayMetrics;
+import android.view.MotionEvent;
+import android.view.SurfaceView;
+import android.view.View;
+import android.view.View.OnTouchListener;
+import org.dolphinemu.dolphinemu.NativeLibrary;
+import org.dolphinemu.dolphinemu.NativeLibrary.ButtonState;
+import org.dolphinemu.dolphinemu.NativeLibrary.ButtonType;
+import org.dolphinemu.dolphinemu.R;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Draws the interactive input overlay on top of the
+ * {@link NativeGLSurfaceView} that is rendering emulation.
+ */
+public final class InputOverlay extends SurfaceView implements OnTouchListener
+{
+ private final Set<InputOverlayDrawableButton> overlayButtons = new HashSet<InputOverlayDrawableButton>();
+ private final Set<InputOverlayDrawableJoystick> overlayJoysticks = new HashSet<InputOverlayDrawableJoystick>();
+
+ /**
+ * Resizes a {@link Bitmap} by a given scale factor
+ *
+ * @param context The current {@link Context}
+ * @param bitmap The {@link Bitmap} to scale.
+ * @param scale The scale factor for the bitmap.
+ *
+ * @return The scaled {@link Bitmap}
+ */
+ public static Bitmap resizeBitmap(Context context, Bitmap bitmap, float scale)
+ {
+ // Retrieve screen dimensions.
+ DisplayMetrics dm = context.getResources().getDisplayMetrics();
+
+ Bitmap bitmapResized = Bitmap.createScaledBitmap(bitmap,
+ (int)(dm.heightPixels * scale),
+ (int)(dm.heightPixels * scale),
+ true);
+ return bitmapResized;
+ }
+
+ /**
+ * Constructor
+ *
+ * @param context The current {@link Context}.
+ * @param attrs {@link AttributeSet} for parsing XML attributes.
+ */
+ public InputOverlay(Context context, AttributeSet attrs)
+ {
+ super(context, attrs);
+
+ // Add all the overlay items to the HashSet.
+ overlayButtons.add(initializeOverlayButton(context, R.drawable.gcpad_a, ButtonType.BUTTON_A));
+ overlayButtons.add(initializeOverlayButton(context, R.drawable.gcpad_b, ButtonType.BUTTON_B));
+ overlayButtons.add(initializeOverlayButton(context, R.drawable.gcpad_x, ButtonType.BUTTON_X));
+ overlayButtons.add(initializeOverlayButton(context, R.drawable.gcpad_y, ButtonType.BUTTON_Y));
+ overlayButtons.add(initializeOverlayButton(context, R.drawable.gcpad_z, ButtonType.BUTTON_Z));
+ overlayButtons.add(initializeOverlayButton(context, R.drawable.gcpad_start, ButtonType.BUTTON_START));
+ overlayButtons.add(initializeOverlayButton(context, R.drawable.gcpad_l, ButtonType.TRIGGER_L));
+ overlayButtons.add(initializeOverlayButton(context, R.drawable.gcpad_r, ButtonType.TRIGGER_R));
+ overlayJoysticks.add(initializeOverlayJoystick(context,
+ R.drawable.gcpad_joystick_range, R.drawable.gcpad_joystick,
+ ButtonType.STICK_MAIN));
+
+ // Set the on touch listener.
+ setOnTouchListener(this);
+
+ // Force draw
+ setWillNotDraw(false);
+
+ // Request focus for the overlay so it has priority on presses.
+ requestFocus();
+ }
+
+ @Override
+ public void draw(Canvas canvas)
+ {
+ super.draw(canvas);
+
+ for (InputOverlayDrawableButton button : overlayButtons)
+ {
+ button.draw(canvas);
+ }
+
+ for (InputOverlayDrawableJoystick joystick: overlayJoysticks)
+ {
+ joystick.draw(canvas);
+ }
+ }
+
+ @Override
+ public boolean onTouch(View v, MotionEvent event)
+ {
+ int pointerIndex = event.getActionIndex();
+
+ for (InputOverlayDrawableButton button : overlayButtons)
+ {
+ // Determine the button state to apply based on the MotionEvent action flag.
+ switch(event.getAction() & MotionEvent.ACTION_MASK)
+ {
+ case MotionEvent.ACTION_DOWN:
+ case MotionEvent.ACTION_POINTER_DOWN:
+ case MotionEvent.ACTION_MOVE:
+ // If a pointer enters the bounds of a button, press that button.
+ if (button.getBounds().contains((int)event.getX(pointerIndex), (int)event.getY(pointerIndex)))
+ NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, button.getId(), ButtonState.PRESSED);
+ break;
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_POINTER_UP:
+ // If a pointer ends, release the button it was pressing.
+ if (button.getBounds().contains((int)event.getX(pointerIndex), (int)event.getY(pointerIndex)))
+ NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, button.getId(), ButtonState.RELEASED);
+ break;
+ }
+ }
+
+
+ for (InputOverlayDrawableJoystick joystick : overlayJoysticks)
+ {
+ joystick.TrackEvent(event);
+ int[] axisIDs = joystick.getAxisIDs();
+ float[] axises = joystick.getAxisValues();
+
+ for (int i = 0; i < 4; i++)
+ NativeLibrary.onGamePadMoveEvent(NativeLibrary.TouchScreenDevice, axisIDs[i], axises[i]);
+ }
+
+ return true;
+ }
+
+ /**
+ * Initializes an InputOverlayDrawableButton, given by resId, with all of the
+ * parameters set for it to be properly shown on the InputOverlay.
+ * <p>
+ * This works due to the way the X and Y coordinates are stored within
+ * the {@link SharedPreferences}.
+ * <p>
+ * In the input overlay configuration menu,
+ * once a touch event begins and then ends (ie. Organizing the buttons to one's own liking for the overlay).
+ * the X and Y coordinates of the button at the END of its touch event
+ * (when you remove your finger/stylus from the touchscreen) are then stored
+ * within a SharedPreferences instance so that those values can be retrieved here.
+ * <p>
+ * This has a few benefits over the conventional way of storing the values
+ * (ie. within the Dolphin ini file).
+ * <ul>
+ * <li>No native calls</li>
+ * <li>Keeps Android-only values inside the Android environment</li>
+ * </ul>
+ * <p>
+ * Technically no modifications should need to be performed on the returned
+ * InputOverlayDrawableButton. Simply add it to the HashSet of overlay items and wait
+ * for Android to call the onDraw method.
+ *
+ * @param context The current {@link Context}.
+ * @param resId The resource ID of the {@link Drawable} to get the {@link Bitmap} of.
+ * @param buttonId Identifier for determining what type of button the initialized InputOverlayDrawableButton represents.
+ *
+ * @return An {@link InputOverlayDrawableButton} with the correct drawing bounds set.
+ *
+ */
+ private static InputOverlayDrawableButton initializeOverlayButton(Context context, int resId, int buttonId)
+ {
+ // Resources handle for fetching the initial Drawable resource.
+ final Resources res = context.getResources();
+
+ // SharedPreference to retrieve the X and Y coordinates for the InputOverlayDrawableButton.
+ final SharedPreferences sPrefs = PreferenceManager.getDefaultSharedPreferences(context);
+
+ // Decide scale based on button ID
+ float scale;
+ float overlaySize = sPrefs.getInt("controls_size", 25);
+ overlaySize += 25;
+ overlaySize /= 50;
+
+ switch (resId)
+ {
+ case R.drawable.gcpad_b:
+ scale = 0.13f * overlaySize;
+ break;
+ case R.drawable.gcpad_x:
+ case R.drawable.gcpad_y:
+ scale = 0.18f * overlaySize;
+ break;
+ case R.drawable.gcpad_start:
+ scale = 0.12f * overlaySize;
+ break;
+ default:
+ scale = 0.20f * overlaySize;
+ break;
+ }
+
+ // Initialize the InputOverlayDrawableButton.
+ final Bitmap bitmap = resizeBitmap(context, BitmapFactory.decodeResource(res, resId), scale);
+ final InputOverlayDrawableButton overlayDrawable = new InputOverlayDrawableButton(res, bitmap, buttonId);
+
+ // String ID of the Drawable. This is what is passed into SharedPreferences
+ // to check whether or not a value has been set.
+ final String drawableId = res.getResourceEntryName(resId);
+
+ // The X and Y coordinates of the InputOverlayDrawableButton on the InputOverlay.
+ // These were set in the input overlay configuration menu.
+ int drawableX = (int) sPrefs.getFloat(drawableId+"-X", 0f);
+ int drawableY = (int) sPrefs.getFloat(drawableId+"-Y", 0f);
+
+ // Intrinsic width and height of the InputOverlayDrawableButton.
+ // For any who may not know, intrinsic width/height
+ // are the original unmodified width and height of the image.
+ int intrinWidth = overlayDrawable.getIntrinsicWidth();
+ int intrinHeight = overlayDrawable.getIntrinsicHeight();
+
+ // Now set the bounds for the InputOverlayDrawableButton.
+ // This will dictate where on the screen (and the what the size) the InputOverlayDrawableButton will be.
+ overlayDrawable.setBounds(drawableX, drawableY, drawableX+intrinWidth, drawableY+intrinHeight);
+
+ return overlayDrawable;
+ }
+
+ /**
+ * Initializes an {@link InputOverlayDrawableJoystick}
+ *
+ * @param context The current {@link Context}
+ * @param resOuter Resource ID for the outer image of the joystick (the static image that shows the circular bounds).
+ * @param resInner Resource ID for the inner image of the joystick (the one you actually move around).
+ * @param joystick Identifier for which joystick this is.
+ *
+ * @return the initialized {@link InputOverlayDrawableJoystick}.
+ */
+ private static InputOverlayDrawableJoystick initializeOverlayJoystick(Context context, int resOuter, int resInner, int joystick)
+ {
+ // Resources handle for fetching the initial Drawable resource.
+ final Resources res = context.getResources();
+
+ // SharedPreference to retrieve the X and Y coordinates for the InputOverlayDrawableJoystick.
+ final SharedPreferences sPrefs = PreferenceManager.getDefaultSharedPreferences(context);
+
+ // Initialize the InputOverlayDrawableJoystick.
+ float overlaySize = sPrefs.getInt("controls_size", 20);
+ overlaySize += 30;
+ overlaySize /= 50;
+ final Bitmap bitmapOuter = resizeBitmap(context, BitmapFactory.decodeResource(res, resOuter), 0.30f * overlaySize);
+ final Bitmap bitmapInner = BitmapFactory.decodeResource(res, resInner);
+
+ // String ID of the Drawable. This is what is passed into SharedPreferences
+ // to check whether or not a value has been set.
+ final String drawableId = res.getResourceEntryName(resOuter);
+
+ // The X and Y coordinates of the InputOverlayDrawableButton on the InputOverlay.
+ // These were set in the input overlay configuration menu.
+ int drawableX = (int) sPrefs.getFloat(drawableId+"-X", 0f);
+ int drawableY = (int) sPrefs.getFloat(drawableId+"-Y", 0f);
+
+ // Now set the bounds for the InputOverlayDrawableJoystick.
+ // This will dictate where on the screen (and the what the size) the InputOverlayDrawableJoystick will be.
+ int outerSize = bitmapOuter.getWidth();
+ Rect outerRect = new Rect(drawableX, drawableY, drawableX + outerSize, drawableY + outerSize);
+ Rect innerRect = new Rect(0, 0, outerSize / 4, outerSize / 4);
+
+ final InputOverlayDrawableJoystick overlayDrawable
+ = new InputOverlayDrawableJoystick(res,
+ bitmapOuter, bitmapInner,
+ outerRect, innerRect,
+ joystick);
+
+
+ return overlayDrawable;
+ }
+
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/emulation/overlay/InputOverlayDrawableButton.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/emulation/overlay/InputOverlayDrawableButton.java
new file mode 100644
index 0000000000..4c63f9541b
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/emulation/overlay/InputOverlayDrawableButton.java
@@ -0,0 +1,45 @@
+/**
+ * Copyright 2013 Dolphin Emulator Project
+ * Licensed under GPLv2
+ * Refer to the license.txt file included.
+ */
+
+package org.dolphinemu.dolphinemu.emulation.overlay;
+
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
+
+/**
+ * Custom {@link BitmapDrawable} that is capable
+ * of storing it's own ID.
+ */
+public final class InputOverlayDrawableButton extends BitmapDrawable
+{
+ // The ID identifying what type of button this Drawable represents.
+ private int buttonType;
+
+ /**
+ * Constructor
+ *
+ * @param res {@link Resources} instance.
+ * @param bitmap {@link Bitmap} to use with this Drawable.
+ * @param buttonType Identifier for this type of button.
+ */
+ public InputOverlayDrawableButton(Resources res, Bitmap bitmap, int buttonType)
+ {
+ super(res, bitmap);
+
+ this.buttonType = buttonType;
+ }
+
+ /**
+ * Gets this InputOverlayDrawableButton's button ID.
+ *
+ * @return this InputOverlayDrawableButton's button ID.
+ */
+ public int getId()
+ {
+ return buttonType;
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/emulation/overlay/InputOverlayDrawableJoystick.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/emulation/overlay/InputOverlayDrawableJoystick.java
new file mode 100644
index 0000000000..a74211eabe
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/emulation/overlay/InputOverlayDrawableJoystick.java
@@ -0,0 +1,137 @@
+/**
+ * Copyright 2013 Dolphin Emulator Project
+ * Licensed under GPLv2
+ * Refer to the license.txt file included.
+ */
+
+package org.dolphinemu.dolphinemu.emulation.overlay;
+
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.graphics.drawable.BitmapDrawable;
+import android.view.MotionEvent;
+
+/**
+ * Custom {@link BitmapDrawable} that is capable
+ * of storing it's own ID.
+ */
+public final class InputOverlayDrawableJoystick extends BitmapDrawable
+{
+ private final int[] axisIDs = {0, 0, 0, 0};
+ private final float[] axises = {0f, 0f};
+ private final BitmapDrawable ringInner;
+ private int trackId = -1;
+
+ /**
+ * Constructor
+ *
+ * @param res {@link Resources} instance.
+ * @param bitmapOuter {@link Bitmap} which represents the outer non-movable part of the joystick.
+ * @param bitmapInner {@link Bitmap} which represents the inner movable part of the joystick.
+ * @param rectOuter {@link Rect} which represents the outer joystick bounds.
+ * @param rectInner {@link Rect} which represents the inner joystick bounds.
+ * @param joystick Identifier for which joystick this is.
+ */
+ public InputOverlayDrawableJoystick(Resources res,
+ Bitmap bitmapOuter, Bitmap bitmapInner,
+ Rect rectOuter, Rect rectInner,
+ int joystick)
+ {
+ super(res, bitmapOuter);
+ this.setBounds(rectOuter);
+
+ this.ringInner = new BitmapDrawable(res, bitmapInner);
+ this.ringInner.setBounds(rectInner);
+ SetInnerBounds();
+ this.axisIDs[0] = joystick + 1;
+ this.axisIDs[1] = joystick + 2;
+ this.axisIDs[2] = joystick + 3;
+ this.axisIDs[3] = joystick + 4;
+ }
+
+ @Override
+ public void draw(Canvas canvas)
+ {
+ super.draw(canvas);
+
+ ringInner.draw(canvas);
+ }
+
+ public void TrackEvent(MotionEvent event)
+ {
+ int pointerIndex = event.getActionIndex();
+
+ switch(event.getAction() & MotionEvent.ACTION_MASK)
+ {
+ case MotionEvent.ACTION_DOWN:
+ case MotionEvent.ACTION_POINTER_DOWN:
+ if (getBounds().contains((int)event.getX(pointerIndex), (int)event.getY(pointerIndex)))
+ trackId = event.getPointerId(pointerIndex);
+ break;
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_POINTER_UP:
+ if (trackId == event.getPointerId(pointerIndex))
+ {
+ axises[0] = axises[1] = 0.0f;
+ SetInnerBounds();
+ trackId = -1;
+ }
+ break;
+ }
+
+ if (trackId == -1)
+ return;
+
+ for (int i = 0; i < event.getPointerCount(); i++)
+ {
+ if (trackId == event.getPointerId(i))
+ {
+ float touchX = event.getX(i);
+ float touchY = event.getY(i);
+ float maxY = getBounds().bottom;
+ float maxX = getBounds().right;
+ touchX -= getBounds().centerX();
+ maxX -= getBounds().centerX();
+ touchY -= getBounds().centerY();
+ maxY -= getBounds().centerY();
+ final float AxisX = touchX / maxX;
+ final float AxisY = touchY / maxY;
+ axises[0] = AxisY;
+ axises[1] = AxisX;
+
+ SetInnerBounds();
+ }
+ }
+ }
+
+ public float[] getAxisValues()
+ {
+ float[] joyaxises = {0f, 0f, 0f, 0f};
+ joyaxises[1] = Math.min(axises[0], 1.0f);
+ joyaxises[0] = Math.min(axises[0], 0.0f);
+ joyaxises[3] = Math.min(axises[1], 1.0f);
+ joyaxises[2] = Math.min(axises[1], 0.0f);
+ return joyaxises;
+ }
+
+ public int[] getAxisIDs()
+ {
+ return axisIDs;
+ }
+
+ private void SetInnerBounds()
+ {
+ float floatX = this.getBounds().centerX();
+ float floatY = this.getBounds().centerY();
+ floatY += axises[0] * (this.getBounds().height() / 2);
+ floatX += axises[1] * (this.getBounds().width() / 2);
+ int X = (int)(floatX);
+ int Y = (int)(floatY);
+ int width = this.ringInner.getBounds().width() / 2;
+ int height = this.ringInner.getBounds().height() / 2;
+ this.ringInner.setBounds(X - width, Y - height,
+ X + width, Y + height);
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowser.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowser.java
new file mode 100644
index 0000000000..669ffe0094
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowser.java
@@ -0,0 +1,159 @@
+/**
+ * Copyright 2013 Dolphin Emulator Project
+ * Licensed under GPLv2
+ * Refer to the license.txt file included.
+ */
+
+package org.dolphinemu.dolphinemu.folderbrowser;
+
+import android.app.ListFragment;
+import android.os.Bundle;
+import android.os.Environment;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ListView;
+
+import java.io.File;
+import java.util.*;
+
+import org.dolphinemu.dolphinemu.NativeLibrary;
+import org.dolphinemu.dolphinemu.R;
+import org.dolphinemu.dolphinemu.gamelist.GameListActivity;
+
+/**
+ * A basic folder browser {@link ListFragment} that allows
+ * the user to select ISOs/ROMs for playing within the
+ * emulator.
+ * <p>
+ * Any valid ISO/ROM selected in this will be added to
+ * the game list for easy browsing the next time the
+ * application is used.
+ * <p>
+ * Note that this file browser does not display files
+ * or directories that are hidden
+ */
+public final class FolderBrowser extends ListFragment
+{
+ private FolderBrowserAdapter adapter;
+ private static File currentDir = null;
+
+ // Populates the FolderView with the given currDir's contents.
+ private void Fill(File currDir)
+ {
+ // Clear the adapter of previous items.
+ adapter.clear();
+
+ // Set the activity title to the current directory the FolderBrowser is in.
+ getActivity().setTitle(String.format(getString(R.string.current_dir), currDir.getName()));
+
+ File[] dirs = currDir.listFiles();
+ List<FolderBrowserItem> dir = new ArrayList<FolderBrowserItem>();
+ List<FolderBrowserItem> fls = new ArrayList<FolderBrowserItem>();
+
+ // Supported extensions to filter by
+ Set<String> validExts = new HashSet<String>(Arrays.asList(".dff", ".dol", ".elf", ".gcm", ".gcz", ".iso", ".wad", ".wbfs"));
+
+ // If dirs is null, then we don't have access permissions to the selected folder.
+ if (dirs != null)
+ {
+ // Search for any directories or files within the current dir.
+ for(File entry : dirs)
+ {
+ try
+ {
+ String entryName = entry.getName();
+ boolean hasExtension = (entryName.lastIndexOf(".") != -1);
+
+ // Skip hidden folders/files.
+ if (!entry.isHidden())
+ {
+ if(entry.isDirectory())
+ {
+ dir.add(new FolderBrowserItem(entryName, entry.getAbsolutePath()));
+ }
+ else if (entry.isFile() && hasExtension)
+ {
+ if (validExts.contains(entryName.toLowerCase().substring(entryName.lastIndexOf('.'))))
+ {
+ fls.add(new FolderBrowserItem(entryName, String.format(getString(R.string.file_size), entry.length()), entry.getAbsolutePath()));
+ }
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ Log.e("FolderBrowser", ex.toString());
+ }
+ }
+ }
+
+ Collections.sort(dir);
+ Collections.sort(fls);
+ dir.addAll(fls);
+
+ // Check for a parent directory to the one we're currently in.
+ if (!currDir.getPath().equalsIgnoreCase("/"))
+ dir.add(0, new FolderBrowserItem("..", getString(R.string.parent_directory), currDir.getParent()));
+
+ // Add the items to the adapter and notify the adapter users of its new contents.
+ adapter.addAll(dir);
+ adapter.notifyDataSetChanged();
+ }
+
+ @Override
+ public void onListItemClick(ListView lv, View v, int position, long id)
+ {
+ FolderBrowserItem item = adapter.getItem(position);
+ if(item.isDirectory())
+ {
+ currentDir = new File(item.getPath());
+ Fill(currentDir);
+ }
+ else
+ {
+ FolderSelected();
+ }
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
+ {
+ if(currentDir == null)
+ currentDir = new File(Environment.getExternalStorageDirectory().getPath());
+
+ ListView rootView = (ListView) inflater.inflate(R.layout.folderbrowser_listview, container, false);
+ adapter = new FolderBrowserAdapter(getActivity(), R.layout.folderbrowser_list_item);
+ rootView.setAdapter(adapter);
+
+ Fill(currentDir);
+ return rootView;
+ }
+
+ private void FolderSelected()
+ {
+ String Directories = NativeLibrary.GetConfig("Dolphin.ini", "General", "ISOPaths", "0");
+ int intDirectories = Integer.parseInt(Directories);
+
+ // Check to see if a path set in the Dolphin config
+ // matches the one the user is trying to add. If it's
+ // already set, then don't add it to the list again.
+ boolean pathNotPresent = true;
+ for (int i = 0; i < intDirectories; i++)
+ {
+ String isoPath = NativeLibrary.GetConfig("Dolphin.ini", "General", "ISOPath" + i, "");
+
+ pathNotPresent = !isoPath.equals(currentDir.getPath());
+ }
+
+ // User doesn't have this path in the config, so add it.
+ if (pathNotPresent)
+ {
+ NativeLibrary.SetConfig("Dolphin.ini", "General", "ISOPaths", Integer.toString(intDirectories+1));
+ NativeLibrary.SetConfig("Dolphin.ini", "General", "ISOPath" + Integer.toString(intDirectories), currentDir.getPath());
+ }
+
+ ((GameListActivity)getActivity()).SwitchPage(0);
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowserAdapter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowserAdapter.java
new file mode 100644
index 0000000000..d248554919
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowserAdapter.java
@@ -0,0 +1,112 @@
+/**
+ * Copyright 2013 Dolphin Emulator Project
+ * Licensed under GPLv2
+ * Refer to the license.txt file included.
+ */
+
+package org.dolphinemu.dolphinemu.folderbrowser;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import org.dolphinemu.dolphinemu.R;
+
+/**
+ * The {@link ArrayAdapter} that backs the file browser.
+ * <p>
+ * This is responsible for correctly handling the display
+ * of the items for the {@link FolderBrowser} UI.
+ */
+public final class FolderBrowserAdapter extends ArrayAdapter<FolderBrowserItem>
+{
+ // ViewHolder which is used to hold onto
+ // items within a listview. This is done
+ // so that findViewById is not needed to
+ // be excessively called over and over.
+ private static final class ViewHolder
+ {
+ TextView title;
+ TextView subtitle;
+ ImageView icon;
+ }
+
+ private final Context context;
+ private final int id;
+ private ViewHolder viewHolder;
+
+ /**
+ * Constructor
+ *
+ * @param context The current {@link Context}.
+ * @param resourceId The resource ID for a layout file containing a layout to use when instantiating views.
+ */
+ public FolderBrowserAdapter(Context context, int resourceId)
+ {
+ super(context, resourceId);
+
+ this.context = context;
+ this.id = resourceId;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent)
+ {
+ if (convertView == null)
+ {
+ LayoutInflater vi = LayoutInflater.from(context);
+ convertView = vi.inflate(id, parent, false);
+
+ // Initialize the ViewHolder and store it.
+ viewHolder = new ViewHolder();
+ viewHolder.title = (TextView) convertView.findViewById(R.id.BrowserItemTitle);
+ viewHolder.subtitle = (TextView) convertView.findViewById(R.id.BrowserItemSubTitle);
+ viewHolder.icon = (ImageView) convertView.findViewById(R.id.BrowserItemIcon);
+ convertView.setTag(viewHolder);
+ }
+ else // Can recover the holder.
+ {
+ viewHolder = (ViewHolder) convertView.getTag();
+ }
+
+ final FolderBrowserItem item = getItem(position);
+ if (item != null)
+ {
+ if (viewHolder.title != null)
+ {
+ viewHolder.title.setText(item.getName());
+ }
+
+ if (viewHolder.subtitle != null)
+ {
+ // Remove the subtitle for all folders, except for the parent directory folder.
+ if (item.isDirectory() && !item.getSubtitle().equals(context.getString(R.string.parent_directory)))
+ {
+ viewHolder.subtitle.setVisibility(View.GONE);
+ }
+ else
+ {
+ viewHolder.subtitle.setVisibility(View.VISIBLE);
+ viewHolder.subtitle.setText(item.getSubtitle());
+ }
+ }
+
+ if (viewHolder.icon != null)
+ {
+ if (item.isDirectory())
+ {
+ viewHolder.icon.setImageResource(R.drawable.ic_menu_folder);
+ }
+ else
+ {
+ viewHolder.icon.setImageResource(R.drawable.ic_menu_file);
+ }
+ }
+ }
+ return convertView;
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowserItem.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowserItem.java
new file mode 100644
index 0000000000..e419162ed3
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowserItem.java
@@ -0,0 +1,110 @@
+/**
+ * Copyright 2013 Dolphin Emulator Project
+ * Licensed under GPLv2
+ * Refer to the license.txt file included.
+ */
+
+package org.dolphinemu.dolphinemu.folderbrowser;
+
+import java.io.File;
+
+/**
+ * Represents an item in the {@link FolderBrowser} list.
+ */
+public final class FolderBrowserItem implements Comparable<FolderBrowserItem>
+{
+ private final String name;
+ private final String subtitle;
+ private final String path;
+ private final File underlyingFile;
+
+ /**
+ * Constructor
+ *
+ * @param name The name of the file/folder represented by this item.
+ * @param subtitle The subtitle of this FolderBrowserItem.
+ * @param path The path of the file/folder represented by this item.
+ */
+ public FolderBrowserItem(String name, String subtitle, String path)
+ {
+ this.name = name;
+ this.subtitle = subtitle;
+ this.path = path;
+ this.underlyingFile = new File(path);
+ }
+
+ /**
+ * Constructor. Initializes a FolderBrowserItem with an empty subtitle.
+ *
+ * @param name The name of the file/folder represented by this item.
+ * @param path The path of the file/folder represented by this item.
+ */
+ public FolderBrowserItem(String name, String path)
+ {
+ this.name = name;
+ this.subtitle = "";
+ this.path = path;
+ this.underlyingFile = new File(path);
+ }
+
+ /**
+ * Gets the name of the file/folder represented by this FolderBrowserItem.
+ *
+ * @return the name of the file/folder represented by this FolderBrowserItem.
+ */
+ public String getName()
+ {
+ return name;
+ }
+
+ /**
+ * Gets the subtitle text of this FolderBrowserItem.
+ *
+ * @return the subtitle text of this FolderBrowserItem.
+ */
+ public String getSubtitle()
+ {
+ return subtitle;
+ }
+
+ /**
+ * Gets the path of the file/folder represented by this FolderBrowserItem.
+ *
+ * @return the path of the file/folder represented by this FolderBrowserItem.
+ */
+ public String getPath()
+ {
+ return path;
+ }
+
+ /**
+ * Gets the {@link File} representation of the underlying file/folder
+ * represented by this FolderBrowserItem.
+ *
+ * @return the {@link File} representation of the underlying file/folder
+ * represented by this FolderBrowserItem.
+ */
+ public File getUnderlyingFile()
+ {
+ return underlyingFile;
+ }
+
+ /**
+ * Gets whether or not this FolderBrowserItem represents a directory.
+ *
+ * @return true if this FolderBrowserItem represents a directory, false otherwise.
+ */
+ public boolean isDirectory()
+ {
+ return underlyingFile.isDirectory();
+ }
+
+ @Override
+ public int compareTo(FolderBrowserItem other)
+ {
+ if(name != null)
+ return name.toLowerCase().compareTo(other.getName().toLowerCase());
+ else
+ throw new NullPointerException("The name of this FolderBrowserItem is null");
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/gamelist/GameListActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/gamelist/GameListActivity.java
new file mode 100644
index 0000000000..3accec11de
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/gamelist/GameListActivity.java
@@ -0,0 +1,374 @@
+/**
+ * Copyright 2013 Dolphin Emulator Project
+ * Licensed under GPLv2
+ * Refer to the license.txt file included.
+ */
+
+package org.dolphinemu.dolphinemu.gamelist;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Fragment;
+import android.app.FragmentTransaction;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.res.Configuration;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Environment;
+import android.preference.PreferenceManager;
+import android.support.v4.app.ActionBarDrawerToggle;
+import android.support.v4.widget.DrawerLayout;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ListView;
+
+import org.dolphinemu.dolphinemu.AssetCopyService;
+import org.dolphinemu.dolphinemu.NativeLibrary;
+import org.dolphinemu.dolphinemu.R;
+import org.dolphinemu.dolphinemu.about.AboutActivity;
+import org.dolphinemu.dolphinemu.emulation.EmulationActivity;
+import org.dolphinemu.dolphinemu.folderbrowser.FolderBrowser;
+import org.dolphinemu.dolphinemu.settings.PrefsActivity;
+import org.dolphinemu.dolphinemu.sidemenu.SideMenuAdapter;
+import org.dolphinemu.dolphinemu.sidemenu.SideMenuItem;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * The activity that implements all of the functions
+ * for the game list.
+ */
+public final class GameListActivity extends Activity
+ implements GameListFragment.OnGameListZeroListener
+{
+ private int mCurFragmentNum = 0;
+
+ private ActionBarDrawerToggle mDrawerToggle;
+ private DrawerLayout mDrawerLayout;
+ private SideMenuAdapter mDrawerAdapter;
+ private ListView mDrawerList;
+ private boolean mAutoStart = false;
+ private String mAutoStartFile = "";
+
+ /**
+ * Called from the {@link GameListFragment}.
+ * <p>
+ * This is called when there are no games
+ * currently present within the game list.
+ */
+ public void onZeroFiles()
+ {
+ mDrawerLayout.openDrawer(mDrawerList);
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.gamelist_activity);
+
+ mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
+ mDrawerList = (ListView) findViewById(R.id.left_drawer);
+
+ // Construct list of items to add to the side menu.
+ List<SideMenuItem> dir = new ArrayList<SideMenuItem>();
+ 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.about), 3));
+
+ mDrawerAdapter = new SideMenuAdapter(this, R.layout.sidemenu, dir);
+ mDrawerList.setAdapter(mDrawerAdapter);
+ mDrawerList.setOnItemClickListener(mMenuItemClickListener);
+
+ // Enable ActionBar app icon to behave as action to toggle nav drawer
+ getActionBar().setDisplayHomeAsUpEnabled(true);
+ getActionBar().setHomeButtonEnabled(true);
+
+ // ActionBarDrawerToggle ties together the the proper interactions
+ // between the sliding drawer and the action bar app icon
+ mDrawerToggle = new ActionBarDrawerToggle(
+ this, /* Host Activity */
+ mDrawerLayout, /* DrawerLayout object */
+ R.drawable.ic_drawer, /* Navigation drawer image to replace 'Up' caret */
+ R.string.drawer_open, /* "open drawer" description for accessibility */
+ R.string.drawer_close /* "close drawer" description for accessibility */
+ ) {
+ public void onDrawerClosed(View view) {
+ invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
+ }
+
+ public void onDrawerOpened(View drawerView) {
+ invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
+ }
+ };
+ mDrawerLayout.setDrawerListener(mDrawerToggle);
+
+ CheckForIntent();
+
+ String BaseDir = NativeLibrary.GetUserDirectory();
+ final String DefaultDir = Environment.getExternalStorageDirectory() + File.separator + "dolphin-emu";
+ if (BaseDir.isEmpty())
+ BaseDir = DefaultDir;
+ NativeLibrary.SetUserDirectory(BaseDir);
+
+ // Stuff in this block only happens when this activity is newly created (i.e. not a rotation)
+ if (savedInstanceState == null)
+ {
+ // Copy assets into appropriate locations.
+ Intent copyAssets = new Intent(this, AssetCopyService.class);
+ startService(copyAssets);
+
+ // Display the game list fragment.
+ final GameListFragment gameList = new GameListFragment();
+ FragmentTransaction ft = getFragmentManager().beginTransaction();
+ ft.replace(R.id.content_frame, gameList);
+ ft.commit();
+ }
+
+ // Create an alert telling them that their phone sucks
+ if (Build.CPU_ABI.contains("arm") && !NativeLibrary.SupportsNEON())
+ {
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setTitle(R.string.device_compat_warning);
+ builder.setMessage(R.string.device_compat_warning_msg);
+ builder.setPositiveButton(R.string.yes, null);
+ builder.setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which)
+ {
+ finish();
+ }
+ });
+ builder.show();
+ }
+
+ if (mAutoStart)
+ {
+ // Start the emulation activity
+ Intent intent = new Intent(this, EmulationActivity.class);
+ intent.putExtra("SelectedGame", mAutoStartFile);
+ startActivity(intent);
+ }
+ }
+
+ private void CheckForIntent()
+ {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ boolean handled = prefs.getBoolean("HandledIntent", false);
+
+ // Get an editor.
+ SharedPreferences.Editor editor = prefs.edit();
+
+ Bundle extras = getIntent().getExtras();
+
+ if (!handled && extras != null)
+ {
+ // Application got passed extra data
+ editor.putBoolean("HandledIntent", true);
+ editor.apply();
+
+ // Did we get passed a new user directory?
+ String user_dir = extras.getString("UserDir");
+ if (user_dir != null && user_dir.length() != 0)
+ NativeLibrary.SetUserDirectory(user_dir);
+
+ // Did we get passed a file?
+ String start_file = extras.getString("AutoStartFile");
+ if (start_file != null && start_file.length() != 0)
+ {
+ mAutoStart = true;
+ mAutoStartFile = start_file;
+ }
+ return;
+ }
+
+ editor.putBoolean("HandledIntent", false);
+ editor.apply();
+ }
+
+ /**
+ * Switches to the {@link Fragment} represented
+ * by the given ID number.
+ *
+ * @param toPage the number representing the {@link Fragment} to switch to.
+ */
+ public void SwitchPage(int toPage)
+ {
+ if (mCurFragmentNum == toPage)
+ return;
+
+ switch(toPage)
+ {
+ case 0: // Game list
+ {
+ // We use the title section as the browser directory tracker in the folder browser.
+ // Make sure we flip the title back if we're coming from that fragment.
+ if (mCurFragmentNum == 1)
+ setTitle(R.string.app_name);
+
+ mCurFragmentNum = 0;
+ final GameListFragment gameList = new GameListFragment();
+ FragmentTransaction ft = getFragmentManager().beginTransaction();
+ ft.replace(R.id.content_frame, gameList);
+ ft.commit();
+ invalidateOptionsMenu();
+ }
+ break;
+
+ case 1: // Folder Browser
+ {
+ mCurFragmentNum = 1;
+ final FolderBrowser folderBrowser = new FolderBrowser();
+ FragmentTransaction ft = getFragmentManager().beginTransaction();
+ ft.replace(R.id.content_frame, folderBrowser);
+ ft.addToBackStack(null);
+ ft.commit();
+ invalidateOptionsMenu();
+ }
+ break;
+
+ case 2: // Settings
+ {
+ Intent intent = new Intent(this, PrefsActivity.class);
+ startActivity(intent);
+ }
+ break;
+
+ case 3: // About
+ {
+ Intent intent = new Intent(this, AboutActivity.class);
+ startActivity(intent);
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ private final AdapterView.OnItemClickListener mMenuItemClickListener = new AdapterView.OnItemClickListener()
+ {
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id)
+ {
+ SideMenuItem o = mDrawerAdapter.getItem(position);
+ mDrawerLayout.closeDrawer(mDrawerList);
+ SwitchPage(o.getID());
+ }
+ };
+
+ /**
+ * When using the ActionBarDrawerToggle, you must call it during
+ * onPostCreate() and onConfigurationChanged()...
+ */
+ @Override
+ protected void onPostCreate(Bundle savedInstanceState)
+ {
+ super.onPostCreate(savedInstanceState);
+
+ // Sync the toggle state after onRestoreInstanceState has occurred.
+ mDrawerToggle.syncState();
+ }
+
+ @Override
+ public void onConfigurationChanged(Configuration newConfig)
+ {
+ super.onConfigurationChanged(newConfig);
+
+ // Pass any configuration change to the drawer toggle
+ mDrawerToggle.onConfigurationChanged(newConfig);
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu)
+ {
+ // Only show this in the game list.
+ if (mCurFragmentNum == 0)
+ {
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.gamelist_menu, menu);
+ return true;
+ }
+
+ return false;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item)
+ {
+ // The action bar home/up action should open or close the drawer.
+ // ActionBarDrawerToggle will take care of this.
+ if (mDrawerToggle.onOptionsItemSelected(item))
+ {
+ return true;
+ }
+
+ // If clear game list is pressed.
+ if (item.getItemId() == R.id.clearGameList)
+ {
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setTitle(R.string.clear_game_list);
+ builder.setMessage(getString(R.string.clear_game_list_confirm));
+ builder.setNegativeButton(R.string.no, null);
+ builder.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which)
+ {
+ String directories = NativeLibrary.GetConfig("Dolphin.ini", "General", "ISOPaths", "0");
+ int intDirs = Integer.parseInt(directories);
+
+ for (int i = 0; i < intDirs; i++)
+ {
+ NativeLibrary.SetConfig("Dolphin.ini", "General", "ISOPath" + i, "");
+ }
+
+ // Since we flushed all paths, we signify this in the ini.
+ NativeLibrary.SetConfig("Dolphin.ini", "General", "ISOPaths", "0");
+
+ // Now finally, clear the game list.
+ ((GameListFragment) getFragmentManager().findFragmentById(R.id.content_frame)).clearGameList();
+ }
+ });
+
+ builder.show();
+ }
+
+ return super.onOptionsItemSelected(item);
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState)
+ {
+ super.onSaveInstanceState(outState);
+
+ outState.putInt("currentFragmentNum", mCurFragmentNum);
+ }
+
+ @Override
+ public void onRestoreInstanceState(Bundle savedInstanceState)
+ {
+ super.onRestoreInstanceState(savedInstanceState);
+
+ mCurFragmentNum = savedInstanceState.getInt("currentFragmentNum");
+ }
+
+ @Override
+ public void onBackPressed()
+ {
+ if (mCurFragmentNum == 0)
+ {
+ finish();
+ }
+ else
+ {
+ SwitchPage(0);
+ }
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/gamelist/GameListAdapter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/gamelist/GameListAdapter.java
new file mode 100644
index 0000000000..4ca43f6250
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/gamelist/GameListAdapter.java
@@ -0,0 +1,124 @@
+/**
+ * Copyright 2013 Dolphin Emulator Project
+ * Licensed under GPLv2
+ * Refer to the license.txt file included.
+ */
+
+package org.dolphinemu.dolphinemu.gamelist;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import org.dolphinemu.dolphinemu.R;
+
+/**
+ * The adapter backing the game list.
+ * <p>
+ * Responsible for handling each game list item individually.
+ */
+public final class GameListAdapter extends ArrayAdapter<GameListItem>
+{
+ private static final float BYTES_PER_GIB = 1024 * 1024 * 1024;
+ private static final float BYTES_PER_MIB = 1024 * 1024;
+
+ private final Context context;
+ private final int id;
+
+ /**
+ * Constructor
+ *
+ * @param context The current {@link Context}.
+ * @param resourceId The resource ID for a layout file containing a layout to use when instantiating views.
+ */
+ public GameListAdapter(Context context, int resourceId)
+ {
+ super(context, resourceId);
+
+ this.context = context;
+ this.id = resourceId;
+ }
+
+ @Override
+ public View getView(int position, View gameView, ViewGroup parent)
+ {
+ ViewHolder holder;
+
+ // If getView() was called without passing in a recycled view,
+ if (gameView == null)
+ {
+ // Inflate a new view using the appropriate XML layout.
+ LayoutInflater inflater = LayoutInflater.from(context);
+ gameView = inflater.inflate(id, parent, false);
+
+ // Instantiate a holder to contain references to the game's views.
+ holder = new ViewHolder();
+ holder.title = (TextView) gameView.findViewById(R.id.GameListItemTitle);
+ holder.subtitle = (TextView) gameView.findViewById(R.id.GameListItemSubTitle);
+ holder.icon = (ImageView) gameView.findViewById(R.id.GameListItemIcon);
+
+ // Attach this list of references to the view.
+ gameView.setTag(holder);
+ }
+ // If we do have a recycled view, we can use the references it already contains.
+ else
+ {
+ holder = (ViewHolder) gameView.getTag();
+ }
+
+ // Get a reference to the game represented by this row.
+ final GameListItem item = getItem(position);
+
+ // Whether this row's view is newly created or not, set the children to contain the game's data.
+ if (item != null)
+ {
+ holder.title.setText(item.getName());
+
+ Bitmap icon = item.getImage();
+
+ if (icon != null)
+ {
+ holder.icon.setImageBitmap(icon);
+ }
+ else
+ {
+ holder.icon.setImageResource(R.drawable.no_banner);
+ }
+
+ float fileSize = item.getFilesize() / BYTES_PER_GIB;
+
+ String subtitle;
+
+ if (fileSize >= 1.0f)
+ {
+ subtitle = String.format(context.getString(R.string.file_size_gib), fileSize);
+ }
+ else
+ {
+ fileSize = item.getFilesize() / BYTES_PER_MIB;
+ subtitle = String.format(context.getString(R.string.file_size_mib), fileSize);
+ }
+
+ holder.subtitle.setText(subtitle);
+ }
+
+ // Make every other game in the list grey
+ if (position % 2 == 1)
+ gameView.setBackgroundColor(0xFFE3E3E3);
+
+ return gameView;
+ }
+
+ private final class ViewHolder
+ {
+ public TextView title;
+ public TextView subtitle;
+ public ImageView icon;
+ }
+}
+
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/gamelist/GameListFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/gamelist/GameListFragment.java
new file mode 100644
index 0000000000..7dd5d0e14d
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/gamelist/GameListFragment.java
@@ -0,0 +1,150 @@
+/**
+ * Copyright 2013 Dolphin Emulator Project
+ * Licensed under GPLv2
+ * Refer to the license.txt file included.
+ */
+
+package org.dolphinemu.dolphinemu.gamelist;
+
+import android.app.Activity;
+import android.app.ListFragment;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ListView;
+import android.widget.Toast;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.dolphinemu.dolphinemu.NativeLibrary;
+import org.dolphinemu.dolphinemu.R;
+import org.dolphinemu.dolphinemu.emulation.EmulationActivity;
+
+
+/**
+ * The {@link ListFragment} responsible for displaying the game list.
+ */
+public final class GameListFragment extends ListFragment
+{
+ private GameListAdapter mGameAdapter;
+ private OnGameListZeroListener mCallback;
+
+ /**
+ * Interface that defines how to handle the case
+ * when there are zero games in the game list.
+ */
+ public interface OnGameListZeroListener
+ {
+ /**
+ * This is called when there are no games
+ * currently present within the game list.
+ */
+ void onZeroFiles();
+ }
+
+ /**
+ * Clears all entries from the {@link GameListAdapter}
+ * backing this GameListFragment.
+ */
+ public void clearGameList()
+ {
+ mGameAdapter.clear();
+ mGameAdapter.notifyDataSetChanged();
+ }
+
+ private void fill()
+ {
+ List<GameListItem> fls = new ArrayList<GameListItem>();
+ String Directories = NativeLibrary.GetConfig("Dolphin.ini", "General", "ISOPaths", "0");
+ int intDirectories = Integer.parseInt(Directories);
+
+ // Extensions to filter by.
+ Set<String> exts = new HashSet<String>(Arrays.asList(".dff", ".dol", ".elf", ".gcm", ".gcz", ".iso", ".wad", ".wbfs"));
+
+ for (int a = 0; a < intDirectories; ++a)
+ {
+ String BrowseDir = NativeLibrary.GetConfig("Dolphin.ini", "General", "ISOPath" + a, "");
+ File currentDir = new File(BrowseDir);
+ File[] dirs = currentDir.listFiles();
+ try
+ {
+ for (File entry : dirs)
+ {
+ String entryName = entry.getName();
+
+ if (!entry.isHidden() && !entry.isDirectory())
+ {
+ if (exts.contains(entryName.toLowerCase().substring(entryName.lastIndexOf('.'))))
+ fls.add(new GameListItem(getActivity(), entryName, entry.length(), entry.getAbsolutePath()));
+ }
+
+ }
+ }
+ catch (Exception ignored)
+ {
+ }
+ }
+ Collections.sort(fls);
+
+ // Add all the items to the adapter
+ mGameAdapter.addAll(fls);
+ mGameAdapter.notifyDataSetChanged();
+
+ if (fls.isEmpty())
+ {
+ mCallback.onZeroFiles();
+ }
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
+ {
+ ListView rootView = (ListView) inflater.inflate(R.layout.gamelist_listview, container, false);
+ mGameAdapter = new GameListAdapter(getActivity(), R.layout.gamelist_list_item);
+ rootView.setAdapter(mGameAdapter);
+
+ fill();
+
+ return rootView;
+ }
+
+ @Override
+ public void onListItemClick(ListView listView, View view, int position, long id)
+ {
+ GameListItem item = mGameAdapter.getItem(position);
+
+ // Show a toast indicating which game was clicked.
+ Toast.makeText(getActivity(), String.format(getString(R.string.file_clicked), item.getPath()), Toast.LENGTH_SHORT).show();
+
+ // Start the emulation activity and send the path of the clicked ROM to it.
+ Intent intent = new Intent(getActivity(), EmulationActivity.class);
+ intent.putExtra("SelectedGame", item.getPath());
+ startActivity(intent);
+ }
+
+ @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
+ {
+ mCallback = (OnGameListZeroListener) activity;
+ }
+ catch (ClassCastException e)
+ {
+ throw new ClassCastException(activity.toString()
+ + " must implement OnGameListZeroListener");
+ }
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/gamelist/GameListItem.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/gamelist/GameListItem.java
new file mode 100644
index 0000000000..6e25a33804
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/gamelist/GameListItem.java
@@ -0,0 +1,102 @@
+/**
+ * Copyright 2013 Dolphin Emulator Project
+ * Licensed under GPLv2
+ * Refer to the license.txt file included.
+ */
+
+package org.dolphinemu.dolphinemu.gamelist;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+
+import java.io.File;
+
+import org.dolphinemu.dolphinemu.NativeLibrary;
+
+/**
+ * Represents an item in the game list.
+ */
+public final class GameListItem implements Comparable<GameListItem>
+{
+ private String name;
+ private long filesize;
+ private final String path;
+ private Bitmap image;
+
+ /**
+ * Constructor.
+ *
+ * @param ctx The current {@link Context}
+ * @param name The name of this GameListItem.
+ * @param filesize The filesize for this GameListItem, in GiB
+ * @param path The file path for the game represented by this GameListItem.
+ */
+ public GameListItem(Context ctx, String name, long filesize, String path)
+ {
+ this.name = name;
+ this.filesize = filesize;
+ this.path = path;
+
+ File file = new File(path);
+ if (!file.isDirectory() && !path.isEmpty())
+ {
+ int[] Banner = NativeLibrary.GetBanner(path);
+ if (Banner[0] != 0)
+ {
+ image = Bitmap.createBitmap(Banner, 96, 32, Bitmap.Config.ARGB_8888);
+ }
+
+ this.name = NativeLibrary.GetTitle(path);
+ }
+ }
+
+ /**
+ * Gets the name of this GameListItem.
+ *
+ * @return the name of this GameListItem.
+ */
+ public String getName()
+ {
+ return name;
+ }
+
+ /**
+ * Gets the filesize of this GameListItem, in GiB.
+ *
+ * @return the filesize of this GameListItem.
+ */
+ public long getFilesize()
+ {
+ return filesize;
+ }
+
+ /**
+ * Gets the file path of the game represented by this GameListItem.
+ *
+ * @return the file path of the game represented by this GameListItem.
+ */
+ public String getPath()
+ {
+ return path;
+ }
+
+ /**
+ * Gets the image data for this game as a {@link Bitmap}.
+ *
+ * @return the image data for this game as a {@link Bitmap}.
+ */
+ public Bitmap getImage()
+ {
+ return image;
+ }
+
+ @Override
+ public int compareTo(GameListItem o)
+ {
+ if (name != null)
+ return name.toLowerCase().compareTo(o.getName().toLowerCase());
+ else
+ throw new NullPointerException("The name of this GameListItem is null");
+ }
+}
+
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/settings/PrefsActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/settings/PrefsActivity.java
new file mode 100644
index 0000000000..0ffac65db9
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/settings/PrefsActivity.java
@@ -0,0 +1,101 @@
+/**
+ * Copyright 2013 Dolphin Emulator Project
+ * Licensed under GPLv2
+ * Refer to the license.txt file included.
+ */
+
+package org.dolphinemu.dolphinemu.settings;
+
+import org.dolphinemu.dolphinemu.R;
+import org.dolphinemu.dolphinemu.settings.cpu.CPUSettingsFragment;
+import org.dolphinemu.dolphinemu.settings.input.InputConfigFragment;
+import org.dolphinemu.dolphinemu.settings.video.VideoSettingsFragment;
+
+import android.app.Activity;
+import android.app.Fragment;
+import android.app.FragmentManager;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
+import android.os.Bundle;
+import android.preference.PreferenceManager;
+import android.support.v13.app.FragmentPagerAdapter;
+import android.support.v4.view.ViewPager;
+
+/**
+ * Main activity that manages all of the preference fragments used to display
+ * the settings to the user.
+ */
+public final class PrefsActivity extends Activity implements OnSharedPreferenceChangeListener
+{
+ @Override
+ protected void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.viewpager);
+
+ // Set the ViewPager adapter.
+ final ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
+ viewPager.setAdapter(new ViewPagerAdapter(getFragmentManager()));
+
+ // Register the preference change listener.
+ final SharedPreferences sPrefs = PreferenceManager.getDefaultSharedPreferences(this);
+ sPrefs.registerOnSharedPreferenceChangeListener(this);
+ }
+
+ @Override
+ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key)
+ {
+ // If any change is made to the preferences in the front-end, immediately save them.
+ UserPreferences.SavePrefsToIni(this);
+ }
+
+ /**
+ * A {@link FragmentPagerAdapter} that returns a fragment
+ * corresponding to one of the sections/tabs/pages.
+ */
+ private final class ViewPagerAdapter extends FragmentPagerAdapter
+ {
+ private final String[] pageTitles = {
+ getString(R.string.cpu_settings),
+ getString(R.string.input_settings),
+ getString(R.string.video_settings)
+ };
+
+ public ViewPagerAdapter(FragmentManager fm)
+ {
+ super(fm);
+ }
+
+ @Override
+ public Fragment getItem(int position)
+ {
+ switch(position)
+ {
+ case 0:
+ return new CPUSettingsFragment();
+
+ case 1:
+ return new InputConfigFragment();
+
+ case 2:
+ return new VideoSettingsFragment();
+
+ default: // Should never happen.
+ return null;
+ }
+ }
+
+ @Override
+ public int getCount()
+ {
+ // Show total pages.
+ return 3;
+ }
+
+ @Override
+ public CharSequence getPageTitle(int position)
+ {
+ return pageTitles[position];
+ }
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/settings/UserPreferences.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/settings/UserPreferences.java
new file mode 100644
index 0000000000..da46daeccf
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/settings/UserPreferences.java
@@ -0,0 +1,284 @@
+/**
+ * Copyright 2013 Dolphin Emulator Project
+ * Licensed under GPLv2
+ * Refer to the license.txt file included.
+ */
+
+package org.dolphinemu.dolphinemu.settings;
+
+import org.dolphinemu.dolphinemu.NativeLibrary;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.os.Build;
+import android.preference.PreferenceManager;
+
+/**
+ * A class that retrieves all of the set user preferences in Android, in a safe way.
+ * <p>
+ * If any preferences are added to this emulator, an accessor for that preference
+ * should be added here. This way lengthy calls to getters from SharedPreferences
+ * aren't made necessary.
+ */
+public final class UserPreferences
+{
+ private UserPreferences()
+ {
+ // Disallows instantiation.
+ }
+
+ /**
+ * Loads the settings stored in the Dolphin ini config files to the shared preferences of this front-end.
+ *
+ * @param ctx The context used to retrieve the SharedPreferences instance.
+ */
+ public static void LoadIniToPrefs(Context ctx)
+ {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ctx);
+
+ // Get an editor.
+ SharedPreferences.Editor editor = prefs.edit();
+
+ // Add the settings.
+ if (Build.CPU_ABI.contains("arm64"))
+ editor.putString("cpuCorePref", getConfig("Dolphin.ini", "Core", "CPUCore", "4"));
+ else
+ editor.putString("cpuCorePref", getConfig("Dolphin.ini", "Core", "CPUCore", "3"));
+
+ editor.putBoolean("dualCorePref", getConfig("Dolphin.ini", "Core", "CPUThread", "False").equals("True"));
+ editor.putBoolean("fastmemPref", getConfig("Dolphin.ini", "Core", "Fastmem", "False").equals("True"));
+
+ editor.putString("gpuPref", getConfig("Dolphin.ini", "Core", "GFXBackend", "OGL"));
+ editor.putBoolean("showFPS", getConfig("gfx_opengl.ini", "Settings", "ShowFPS", "False").equals("True"));
+ editor.putBoolean("drawOnscreenControls", getConfig("Dolphin.ini", "Android", "ScreenControls", "True").equals("True"));
+
+ editor.putString("internalResolution", getConfig("gfx_opengl.ini", "Settings", "EFBScale", "2") );
+ editor.putString("FSAA", getConfig("gfx_opengl.ini", "Settings", "MSAA", "0"));
+ editor.putString("anisotropicFiltering", getConfig("gfx_opengl.ini", "Enhancements", "MaxAnisotropy", "0"));
+ editor.putString("postProcessingShader", getConfig("gfx_opengl.ini", "Enhancements", "PostProcessingShader", ""));
+ editor.putBoolean("scaledEFBCopy", getConfig("gfx_opengl.ini", "Hacks", "EFBScaledCopy", "True").equals("True"));
+ editor.putBoolean("perPixelLighting", getConfig("gfx_opengl.ini", "Settings", "EnablePixelLighting", "False").equals("True"));
+ editor.putBoolean("forceTextureFiltering", getConfig("gfx_opengl.ini", "Enhancements", "ForceFiltering", "False").equals("True"));
+ editor.putBoolean("disableFog", getConfig("gfx_opengl.ini", "Settings", "DisableFog", "False").equals("True"));
+ editor.putBoolean("skipEFBAccess", getConfig("gfx_opengl.ini", "Hacks", "EFBAccessEnable", "False").equals("True"));
+ editor.putBoolean("ignoreFormatChanges", getConfig("gfx_opengl.ini", "Hacks", "EFBEmulateFormatChanges", "False").equals("True"));
+ editor.putString("stereoscopyMode", getConfig("gfx_opengl.ini", "Enhancements", "StereoMode", "0"));
+ editor.putBoolean("stereoSwapEyes", getConfig("gfx_opengl.ini", "Enhancements", "StereoSwapEyes", "False").equals("True"));
+ editor.putString("stereoDepth", getConfig("gfx_opengl.ini", "Enhancements", "StereoDepth", "20"));
+ editor.putString("stereoConvergence", getConfig("gfx_opengl.ini", "Enhancements", "StereoConvergence", "20"));
+
+ String efbCopyOn = getConfig("gfx_opengl.ini", "Hacks", "EFBCopyEnable", "True");
+ String efbToTexture = getConfig("gfx_opengl.ini", "Hacks", "EFBToTextureEnable", "True");
+ String efbCopyCache = getConfig("gfx_opengl.ini", "Hacks", "EFBCopyCacheEnable", "False");
+
+ if (efbCopyOn.equals("False"))
+ {
+ editor.putString("efbCopyMethod", "Off");
+ }
+ else if (efbCopyOn.equals("True") && efbToTexture.equals("True"))
+ {
+ editor.putString("efbCopyMethod", "Texture");
+ }
+ else if(efbCopyOn.equals("True") && efbToTexture.equals("False") && efbCopyCache.equals("False"))
+ {
+ editor.putString("efbCopyMethod", "RAM (uncached)");
+ }
+ else if(efbCopyOn.equals("True") && efbToTexture.equals("False") && efbCopyCache.equals("True"))
+ {
+ editor.putString("efbCopyMethod", "RAM (cached)");
+ }
+
+ editor.putString("textureCacheAccuracy", getConfig("gfx_opengl.ini", "Settings", "SafeTextureCacheColorSamples", "128"));
+
+ String usingXFB = getConfig("gfx_opengl.ini", "Settings", "UseXFB", "False");
+ String usingRealXFB = getConfig("gfx_opengl.ini", "Settings", "UseRealXFB", "False");
+
+ if (usingXFB.equals("False"))
+ {
+ editor.putString("externalFrameBuffer", "Disabled");
+ }
+ else if (usingXFB.equals("True") && usingRealXFB.equals("False"))
+ {
+ editor.putString("externalFrameBuffer", "Virtual");
+ }
+ else if (usingXFB.equals("True") && usingRealXFB.equals("True"))
+ {
+ editor.putString("externalFrameBuffer", "Real");
+ }
+
+ editor.putBoolean("disableDestinationAlpha", getConfig("gfx_opengl.ini", "Settings", "DstAlphaPass", "False").equals("True"));
+ editor.putBoolean("fastDepthCalculation", getConfig("gfx_opengl.ini", "Settings", "FastDepthCalc", "True").equals("True"));
+ editor.putString("aspectRatio", getConfig("gfx_opengl.ini", "Settings", "AspectRatio", "0"));
+
+ // Apply the changes.
+ editor.apply();
+ }
+
+ // Small utility method that shortens calls to NativeLibrary.GetConfig.
+ private static String getConfig(String ini, String section, String key, String defaultValue)
+ {
+ return NativeLibrary.GetConfig(ini, section, key, defaultValue);
+ }
+
+ /**
+ * Writes the preferences set in the front-end to the Dolphin ini files.
+ *
+ * @param ctx The context used to retrieve the user settings.
+ * */
+ public static void SavePrefsToIni(Context ctx)
+ {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ctx);
+
+ // Whether or not the user is using dual core.
+ boolean isUsingDualCore = prefs.getBoolean("dualCorePref", true);
+
+ // Current CPU core being used. Falls back to interpreter upon error.
+ String currentEmuCore = prefs.getString("cpuCorePref", "0");
+
+ // Fastmem JIT core usage
+ boolean isUsingFastmem = prefs.getBoolean("fastmemPref", false);
+
+ // Current video backend being used. Falls back to software rendering upon error.
+ String currentVideoBackend = prefs.getString("gpuPref", "Software Rendering");
+
+ // Whether or not FPS will be displayed on-screen.
+ boolean showingFPS = prefs.getBoolean("showFPS", false);
+
+ // Whether or not to draw on-screen controls.
+ boolean drawingOnscreenControls = prefs.getBoolean("drawOnscreenControls", true);
+
+ // Whether or not to ignore all EFB access requests from the CPU.
+ boolean skipEFBAccess = prefs.getBoolean("skipEFBAccess", false);
+
+ // Whether or not to ignore changes to the EFB format.
+ boolean ignoreFormatChanges = prefs.getBoolean("ignoreFormatChanges", false);
+
+ // EFB copy method to use.
+ String efbCopyMethod = prefs.getString("efbCopyMethod", "Texture");
+
+ // Texture cache accuracy. Falls back to "Fast" up error.
+ String textureCacheAccuracy = prefs.getString("textureCacheAccuracy", "128");
+
+ // External frame buffer emulation. Falls back to disabled upon error.
+ String externalFrameBuffer = prefs.getString("externalFrameBuffer", "Disabled");
+
+ // Whether or not to disable destination alpha.
+ boolean disableDstAlphaPass = prefs.getBoolean("disableDestinationAlpha", false);
+
+ // Whether or not to use fast depth calculation.
+ boolean useFastDepthCalc = prefs.getBoolean("fastDepthCalculation", true);
+
+ // Aspect ratio selection
+ String aspectRatio = prefs.getString("aspectRatio", "0");
+
+ // Internal resolution. Falls back to 1x Native upon error.
+ String internalResolution = prefs.getString("internalResolution", "2");
+
+ // FSAA Level. Falls back to 1x upon error.
+ String FSAALevel = prefs.getString("FSAA", "0");
+
+ // Anisotropic Filtering Level. Falls back to 1x upon error.
+ String anisotropicFiltLevel = prefs.getString("anisotropicFiltering", "0");
+
+ // Post processing shader setting
+ String postProcessing = prefs.getString("postProcessingShader", "");
+
+ // Whether or not Scaled EFB copies are used.
+ boolean usingScaledEFBCopy = prefs.getBoolean("scaledEFBCopy", true);
+
+ // Whether or not per-pixel lighting is used.
+ boolean usingPerPixelLighting = prefs.getBoolean("perPixelLighting", false);
+
+ // Whether or not texture filtering is being forced.
+ boolean isForcingTextureFiltering = prefs.getBoolean("forceTextureFiltering", false);
+
+ // Whether or not fog is disabled.
+ boolean fogIsDisabled = prefs.getBoolean("disableFog", false);
+
+ // Stereoscopy setting
+ String stereoscopyMode = prefs.getString("stereoscopyMode", "0");
+
+ // Stereoscopy swap eyes
+ boolean stereoscopyEyeSwap = prefs.getBoolean("stereoSwapEyes", false);
+
+ // Stereoscopy separation
+ String stereoscopySeparation = prefs.getString("stereoDepth", "20");
+
+ // Stereoscopy convergence
+ String stereoscopyConvergence = prefs.getString("stereoConvergence", "20");
+
+ // CPU related Settings
+ NativeLibrary.SetConfig("Dolphin.ini", "Core", "CPUCore", currentEmuCore);
+ NativeLibrary.SetConfig("Dolphin.ini", "Core", "CPUThread", isUsingDualCore ? "True" : "False");
+ NativeLibrary.SetConfig("Dolphin.ini", "Core", "Fastmem", isUsingFastmem ? "True" : "False");
+
+ // General Video Settings
+ NativeLibrary.SetConfig("Dolphin.ini", "Core", "GFXBackend", currentVideoBackend);
+ NativeLibrary.SetConfig("gfx_opengl.ini", "Settings", "ShowFPS", showingFPS ? "True" : "False");
+ NativeLibrary.SetConfig("Dolphin.ini", "Android", "ScreenControls", drawingOnscreenControls ? "True" : "False");
+
+ // Video Hack Settings
+ NativeLibrary.SetConfig("gfx_opengl.ini", "Hacks", "EFBAccessEnable", skipEFBAccess ? "False" : "True");
+ NativeLibrary.SetConfig("gfx_opengl.ini", "Hacks", "EFBEmulateFormatChanges", ignoreFormatChanges ? "True" : "False");
+ NativeLibrary.SetConfig("gfx_opengl.ini", "Settings", "AspectRatio", aspectRatio);
+
+ // Set EFB Copy Method
+ if (efbCopyMethod.equals("Off"))
+ {
+ NativeLibrary.SetConfig("gfx_opengl.ini", "Hacks", "EFBCopyEnable", "False");
+ }
+ else if (efbCopyMethod.equals("Texture"))
+ {
+ NativeLibrary.SetConfig("gfx_opengl.ini", "Hacks", "EFBCopyEnable", "True");
+ NativeLibrary.SetConfig("gfx_opengl.ini", "Hacks", "EFBToTextureEnable", "True");
+ }
+ else if (efbCopyMethod.equals("RAM (uncached)"))
+ {
+ NativeLibrary.SetConfig("gfx_opengl.ini", "Hacks", "EFBCopyEnable", "True");
+ NativeLibrary.SetConfig("gfx_opengl.ini", "Hacks", "EFBToTextureEnable", "False");
+ NativeLibrary.SetConfig("gfx_opengl.ini", "Hacks", "EFBCopyCacheEnable", "False");
+ }
+ else if (efbCopyMethod.equals("RAM (cached)"))
+ {
+ NativeLibrary.SetConfig("gfx_opengl.ini", "Hacks", "EFBCopyEnable", "True");
+ NativeLibrary.SetConfig("gfx_opengl.ini", "Hacks", "EFBToTextureEnable", "False");
+ NativeLibrary.SetConfig("gfx_opengl.ini", "Hacks", "EFBCopyCacheEnable", "True");
+ }
+
+ // Set texture cache accuracy
+ NativeLibrary.SetConfig("gfx_opengl.ini", "Settings", "SafeTextureCacheColorSamples", textureCacheAccuracy);
+
+ // Set external frame buffer.
+ if (externalFrameBuffer.equals("Disabled"))
+ {
+ NativeLibrary.SetConfig("gfx_opengl.ini", "Settings", "UseXFB", "False");
+ }
+ else if (externalFrameBuffer.equals("Virtual"))
+ {
+ NativeLibrary.SetConfig("gfx_opengl.ini", "Settings", "UseXFB", "True");
+ NativeLibrary.SetConfig("gfx_opengl.ini", "Settings", "UseRealXFB", "False");
+ }
+ else if (externalFrameBuffer.equals("Real"))
+ {
+ NativeLibrary.SetConfig("gfx_opengl.ini", "Settings", "UseXFB", "True");
+ NativeLibrary.SetConfig("gfx_opengl.ini", "Settings", "UseRealXFB", "True");
+ }
+
+ NativeLibrary.SetConfig("gfx_opengl.ini", "Settings", "DstAlphaPass", disableDstAlphaPass ? "True" : "False");
+ NativeLibrary.SetConfig("gfx_opengl.ini", "Settings", "FastDepthCalc", useFastDepthCalc ? "True" : "False");
+
+ //-- Enhancement Settings --//
+ NativeLibrary.SetConfig("gfx_opengl.ini", "Settings", "EFBScale", internalResolution);
+ NativeLibrary.SetConfig("gfx_opengl.ini", "Settings", "MSAA", FSAALevel);
+ NativeLibrary.SetConfig("gfx_opengl.ini", "Enhancements", "MaxAnisotropy", anisotropicFiltLevel);
+ NativeLibrary.SetConfig("gfx_opengl.ini", "Enhancements", "PostProcessingShader", postProcessing);
+ NativeLibrary.SetConfig("gfx_opengl.ini", "Hacks", "EFBScaledCopy", usingScaledEFBCopy ? "True" : "False");
+ NativeLibrary.SetConfig("gfx_opengl.ini", "Settings", "EnablePixelLighting", usingPerPixelLighting ? "True" : "False");
+ NativeLibrary.SetConfig("gfx_opengl.ini", "Enhancements", "ForceFiltering", isForcingTextureFiltering ? "True" : "False");
+ NativeLibrary.SetConfig("gfx_opengl.ini", "Settings", "DisableFog", fogIsDisabled ? "True" : "False");
+ NativeLibrary.SetConfig("gfx_opengl.ini", "Enhancements", "StereoMode", stereoscopyMode);
+ NativeLibrary.SetConfig("gfx_opengl.ini", "Enhancements", "StereoSwapEyes", stereoscopyEyeSwap ? "True" : "False");
+ NativeLibrary.SetConfig("gfx_opengl.ini", "Enhancements", "StereoDepth", stereoscopySeparation);
+ NativeLibrary.SetConfig("gfx_opengl.ini", "Enhancements", "StereoConvergence", stereoscopyConvergence);
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/settings/cpu/CPUSettingsFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/settings/cpu/CPUSettingsFragment.java
new file mode 100644
index 0000000000..134e1cdb65
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/settings/cpu/CPUSettingsFragment.java
@@ -0,0 +1,56 @@
+/**
+ * Copyright 2013 Dolphin Emulator Project
+ * Licensed under GPLv2
+ * Refer to the license.txt file included.
+ */
+
+package org.dolphinemu.dolphinemu.settings.cpu;
+
+import org.dolphinemu.dolphinemu.R;
+
+import android.os.Build;
+import android.os.Bundle;
+import android.preference.ListPreference;
+import android.preference.PreferenceFragment;
+
+/**
+ * Responsible for the loading of the CPU preferences.
+ */
+public final class CPUSettingsFragment extends PreferenceFragment
+{
+ @Override
+ public void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+
+ // Load the preferences from an XML resource
+ addPreferencesFromResource(R.xml.cpu_prefs);
+
+ final ListPreference cpuCores = (ListPreference) findPreference("cpuCorePref");
+
+ //
+ // Set valid emulation cores depending on the CPU architecture
+ // that the Android device is running on.
+ //
+ if (Build.CPU_ABI.contains("x86-64"))
+ {
+ cpuCores.setEntries(R.array.emuCoreEntriesX86_64);
+ cpuCores.setEntryValues(R.array.emuCoreValuesX86_64);
+ }
+ else if (Build.CPU_ABI.contains("arm64"))
+ {
+ cpuCores.setEntries(R.array.emuCoreEntriesARM64);
+ cpuCores.setEntryValues(R.array.emuCoreValuesARM64);
+ }
+ else if (Build.CPU_ABI.contains("arm"))
+ {
+ cpuCores.setEntries(R.array.emuCoreEntriesARM);
+ cpuCores.setEntryValues(R.array.emuCoreValuesARM);
+ }
+ else
+ {
+ cpuCores.setEntries(R.array.emuCoreEntriesOther);
+ cpuCores.setEntryValues(R.array.emuCoreValuesOther);
+ }
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/settings/custom/UpdatingListPreference.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/settings/custom/UpdatingListPreference.java
new file mode 100644
index 0000000000..273b5fe547
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/settings/custom/UpdatingListPreference.java
@@ -0,0 +1,39 @@
+/**
+ * Copyright 2013 Dolphin Emulator Project
+ * Licensed under GPLv2
+ * Refer to the license.txt file included.
+ */
+
+package org.dolphinemu.dolphinemu.settings.custom;
+
+import android.content.Context;
+import android.preference.ListPreference;
+import android.util.AttributeSet;
+
+/**
+ * A {@link ListPreference} that updates its summary upon it's selection being changed.
+ */
+public final class UpdatingListPreference extends ListPreference
+{
+ /**
+ * Constructor
+ *
+ * @param context the current {@link Context}.
+ */
+ public UpdatingListPreference(Context context, AttributeSet attribs)
+ {
+ super(context, attribs);
+ }
+
+ @Override
+ public void onDialogClosed(boolean positiveResult)
+ {
+ super.onDialogClosed(positiveResult);
+
+ // If an entry was selected
+ if (positiveResult)
+ {
+ setSummary(getEntry());
+ }
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/settings/input/InputBindingPreference.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/settings/input/InputBindingPreference.java
new file mode 100644
index 0000000000..e182f93a5c
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/settings/input/InputBindingPreference.java
@@ -0,0 +1,55 @@
+package org.dolphinemu.dolphinemu.settings.input;
+
+import org.dolphinemu.dolphinemu.R;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.preference.Preference;
+import android.util.AttributeSet;
+
+/**
+ * {@link Preference} subclass that represents a preference
+ * used for assigning a key bind.
+ */
+public final class InputBindingPreference extends Preference
+{
+ /**
+ * Constructor that is called when inflating an InputBindingPreference from XML.
+ *
+ * @param context The current {@link Context}.
+ * @param attrs The attributes of the XML tag that is inflating the preference.
+ */
+ public InputBindingPreference(Context context, AttributeSet attrs)
+ {
+ super(context, attrs);
+ }
+
+ @Override
+ protected void onClick()
+ {
+ // Begin the creation of the input alert.
+ final MotionAlertDialog dialog = new MotionAlertDialog(getContext(), this);
+
+ // Set the cancel button.
+ dialog.setButton(AlertDialog.BUTTON_NEGATIVE, getContext().getString(R.string.cancel), new AlertDialog.OnClickListener()
+ {
+ @Override
+ public void onClick(DialogInterface dialog, int which)
+ {
+ // Do nothing. Just makes the cancel button show up.
+ }
+ });
+
+ // Set the title and description message.
+ dialog.setTitle(R.string.input_binding);
+ dialog.setMessage(String.format(getContext().getString(R.string.input_binding_descrip), getTitle()));
+
+ // 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();
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/settings/input/InputConfigFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/settings/input/InputConfigFragment.java
new file mode 100644
index 0000000000..82e2ffc44f
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/settings/input/InputConfigFragment.java
@@ -0,0 +1,102 @@
+/**
+ * Copyright 2013 Dolphin Emulator Project
+ * Licensed under GPLv2
+ * Refer to the license.txt file included.
+ */
+
+package org.dolphinemu.dolphinemu.settings.input;
+
+import android.app.Fragment;
+import android.os.Build;
+import android.os.Bundle;
+import android.preference.Preference;
+import android.preference.PreferenceFragment;
+import android.view.InputDevice;
+import org.dolphinemu.dolphinemu.NativeLibrary;
+import org.dolphinemu.dolphinemu.R;
+
+import java.util.List;
+
+/**
+ * The {@link Fragment} responsible for implementing the functionality
+ * within the input control mapping config.
+ */
+public final class InputConfigFragment extends PreferenceFragment
+{
+ @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[] gamecubeKeys =
+ {
+ "InputA", "InputB", "InputX", "InputY", "InputZ", "InputStart",
+ "DPadUp", "DPadDown", "DPadLeft", "DPadRight",
+ "MainUp", "MainDown", "MainLeft", "MainRight",
+ "CStickUp", "CStickDown", "CStickLeft", "CStickRight",
+ "InputL", "InputR"
+ };
+
+ final String[] wiimoteKeys =
+ {
+ "WiimoteInputA", "WiimoteInputB", "WiimoteInputOne", "WiimoteInputTwo", "WiimoteInputPlus", "WiimoteInputMinus", "WiimoteInputHome",
+ "WiimoteIRUp", "WiimoteIRDown", "WiimoteIRLeft", "WiimoteIRRight", "WiimoteIRForward", "WiimoteIRBackward",
+ "WiimoteSwingUp", "WiimoteSwingDown", "WiimoteSwingLeft", "WiimoteSwingRight",
+ "WiimoteTiltForward", "WiimoteTiltBackward", "WiimoteTiltLeft", "WiimoteTiltRight",
+ "WiimoteShakeX", "WiimoteShakeY", "WiimoteShakeZ",
+ "WiimoteDPadUp", "WiimoteDPadDown", "WiimoteDPadLeft", "WiimoteDPadRight"
+ };
+
+ for (int i = 0; i < 4; i++)
+ {
+ // Loop through the keys for all 4 GameCube controllers.
+ for (String key : gamecubeKeys)
+ {
+ final String binding = NativeLibrary.GetConfig("Dolphin.ini", "Android", key+"_"+i, "None");
+ final Preference pref = findPreference(key+"_"+i);
+ pref.setSummary(binding);
+ }
+
+ // Loop through the keys for the Wiimote
+ /*for (String key : wiimoteKeys)
+ {
+ final String binding = NativeLibrary.GetConfig("Dolphin.ini", "Android", key+"_"+i, "None");
+ final Preference pref = findPreference(key+"_"+i);
+ pref.setSummary(binding);
+ }*/
+ }
+ }
+
+ /**
+ * 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<InputDevice.MotionRange> motions = input.getMotionRanges();
+ StringBuilder fakeid = new StringBuilder();
+
+ for (InputDevice.MotionRange range : motions)
+ fakeid.append(range.getAxis());
+
+ return fakeid.toString();
+ }
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/settings/input/MotionAlertDialog.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/settings/input/MotionAlertDialog.java
new file mode 100644
index 0000000000..58d3a933a1
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/settings/input/MotionAlertDialog.java
@@ -0,0 +1,127 @@
+package org.dolphinemu.dolphinemu.settings.input;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.dolphinemu.dolphinemu.NativeLibrary;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.preference.Preference;
+import android.util.Log;
+import android.view.InputDevice;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+
+/**
+ * {@link AlertDialog} derivative that listens for
+ * motion events from controllers and joysticks.
+ */
+final class MotionAlertDialog extends AlertDialog
+{
+ // The selected input preference
+ private final Preference inputPref;
+
+ private boolean firstEvent = true;
+ private final ArrayList<Float> m_values = new ArrayList<Float>();
+
+ /**
+ * Constructor
+ *
+ * @param ctx The current {@link Context}.
+ * @param inputPref The Preference to show this dialog for.
+ */
+ public MotionAlertDialog(Context ctx, Preference inputPref)
+ {
+ super(ctx);
+
+ this.inputPref = inputPref;
+ }
+
+ @Override
+ public boolean onKeyDown(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 '" + InputConfigFragment.getInputDesc(input) + "'-Button " + event.getKeyCode();
+ NativeLibrary.SetConfig("Dolphin.ini", "Android", inputPref.getKey(), bindStr);
+ inputPref.setSummary(bindStr);
+ dismiss();
+ return true;
+
+ default:
+ return false;
+ }
+ }
+
+
+ // Method that will be called within dispatchGenericMotionEvent
+ // that handles joystick/controller movements.
+ private boolean onMotionEvent(MotionEvent event)
+ {
+ if ((event.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) == 0)
+ return false;
+
+ Log.d("InputConfigFragment", "Received motion event: " + event.getAction());
+
+ InputDevice input = event.getDevice();
+ List<InputDevice.MotionRange> 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", inputPref.getKey(), bindStr);
+ inputPref.setSummary(bindStr);
+ 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", inputPref.getKey(), bindStr);
+ inputPref.setSummary(bindStr);
+ dismiss();
+ }
+ }
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean dispatchKeyEvent(KeyEvent event)
+ {
+ if (onKeyDown(event.getKeyCode(), event))
+ return true;
+
+ return super.dispatchKeyEvent(event);
+ }
+
+ @Override
+ public boolean dispatchGenericMotionEvent(MotionEvent event)
+ {
+ if (onMotionEvent(event))
+ return true;
+
+ return super.dispatchGenericMotionEvent(event);
+ }
+} \ No newline at end of file
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/settings/input/overlayconfig/OverlayConfigActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/settings/input/overlayconfig/OverlayConfigActivity.java
new file mode 100644
index 0000000000..b5e4fc8086
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/settings/input/overlayconfig/OverlayConfigActivity.java
@@ -0,0 +1,51 @@
+/**
+ * Copyright 2013 Dolphin Emulator Project
+ * Licensed under GPLv2
+ * Refer to the license.txt file included.
+ */
+
+package org.dolphinemu.dolphinemu.settings.input.overlayconfig;
+
+import org.dolphinemu.dolphinemu.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.RelativeLayout;
+
+/**
+ * {@link Activity} used for configuring the input overlay.
+ */
+public final class OverlayConfigActivity extends Activity
+{
+ @Override
+ public void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+
+ // Initialize all of the buttons to add.
+ final OverlayConfigButton buttonA = new OverlayConfigButton(this, "gcpad_a", R.drawable.gcpad_a);
+ final OverlayConfigButton buttonB = new OverlayConfigButton(this, "gcpad_b", R.drawable.gcpad_b);
+ final OverlayConfigButton buttonX = new OverlayConfigButton(this, "gcpad_x", R.drawable.gcpad_x);
+ final OverlayConfigButton buttonY = new OverlayConfigButton(this, "gcpad_y", R.drawable.gcpad_y);
+ final OverlayConfigButton buttonZ = new OverlayConfigButton(this, "gcpad_z", R.drawable.gcpad_z);
+ final OverlayConfigButton buttonS = new OverlayConfigButton(this, "gcpad_start", R.drawable.gcpad_start);
+ final OverlayConfigButton buttonL = new OverlayConfigButton(this, "gcpad_l", R.drawable.gcpad_l);
+ final OverlayConfigButton buttonR = new OverlayConfigButton(this, "gcpad_r", R.drawable.gcpad_r);
+ final OverlayConfigButton joystick = new OverlayConfigButton(this, "gcpad_joystick_range", R.drawable.gcpad_joystick_range);
+
+ // Add the buttons to the layout
+ final RelativeLayout configLayout = new RelativeLayout(this);
+ configLayout.addView(buttonA);
+ configLayout.addView(buttonB);
+ configLayout.addView(buttonX);
+ configLayout.addView(buttonY);
+ configLayout.addView(buttonZ);
+ configLayout.addView(buttonS);
+ configLayout.addView(buttonL);
+ configLayout.addView(buttonR);
+ configLayout.addView(joystick);
+
+ // Now set the layout
+ setContentView(configLayout);
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/settings/input/overlayconfig/OverlayConfigButton.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/settings/input/overlayconfig/OverlayConfigButton.java
new file mode 100644
index 0000000000..0d4767eec4
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/settings/input/overlayconfig/OverlayConfigButton.java
@@ -0,0 +1,166 @@
+/**
+ * Copyright 2013 Dolphin Emulator Project
+ * Licensed under GPLv2
+ * Refer to the license.txt file included.
+ */
+
+package org.dolphinemu.dolphinemu.settings.input.overlayconfig;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.preference.PreferenceManager;
+import android.util.DisplayMetrics;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.View.OnTouchListener;
+import android.widget.Button;
+import org.dolphinemu.dolphinemu.R;
+
+/**
+ * A movable {@link Button} for use within the
+ * input overlay configuration screen.
+ */
+public final class OverlayConfigButton extends Button implements OnTouchListener
+{
+ // SharedPreferences instance that the button positions are cached to.
+ private final SharedPreferences sharedPrefs;
+
+ // The String ID for this button.
+ //
+ // This ID is used upon releasing this button as the key for saving
+ // the X and Y coordinates of this button. This same key is also used
+ // for setting the coordinates of the button on the actual overlay during emulation.
+ //
+ // They can be accessed through SharedPreferences respectively as follows:
+ //
+ // SharedPreferences sPrefs = PreferenceManager.getDefaultSharedPreferences(this);
+ // float buttonX = sPrefs.getFloat(buttonId+"-X", -1f);
+ // float buttonY = sPrefs.getFloat(buttonId+"-Y", -1f);
+ //
+ private final String buttonId;
+
+ // The offset of the press while moving the button
+ private float moveOffsetX, moveOffsetY;
+
+ private Drawable resizeDrawable(Drawable image, float scale)
+ {
+ // Retrieve screen dimensions.
+ DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
+
+ Bitmap b = ((BitmapDrawable)image).getBitmap();
+ Bitmap bitmapResized = Bitmap.createScaledBitmap(b,
+ (int)(displayMetrics.heightPixels * scale),
+ (int)(displayMetrics.heightPixels * scale),
+ true);
+
+ return new BitmapDrawable(getResources(), bitmapResized);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param context the current {@link Context}.
+ * @param buttonId the String ID for this button.
+ * @param drawableId the Drawable ID for the image to represent this OverlayConfigButton.
+ */
+ public OverlayConfigButton(Context context, String buttonId, int drawableId)
+ {
+ super(context);
+
+ // Set the button ID.
+ this.buttonId = buttonId;
+
+ // Set the button as its own OnTouchListener.
+ setOnTouchListener(this);
+
+ // Get the SharedPreferences instance.
+ sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
+
+ // Decide scale based on button ID
+
+ // SeekBars are not able to set a minimum value, only a maximum value, which complicates
+ // things a bit. What happens here is after the SeekBar's value is retrieved, 25 is
+ // added so the value will never go below 25. It is then divided by 50 (25 + 25) so the
+ // default value will be 100%.
+ float scale;
+ float overlaySize = sharedPrefs.getInt("controls_size", 25);
+ overlaySize += 25;
+ overlaySize /= 50;
+
+ switch (drawableId)
+ {
+ case R.drawable.gcpad_b:
+ scale = 0.13f * overlaySize;
+ break;
+ case R.drawable.gcpad_x:
+ case R.drawable.gcpad_y:
+ scale = 0.18f * overlaySize;
+ break;
+ case R.drawable.gcpad_start:
+ scale = 0.12f * overlaySize;
+ break;
+ case R.drawable.gcpad_joystick_range:
+ scale = 0.30f * overlaySize;
+ break;
+ default:
+ scale = 0.20f * overlaySize;
+ break;
+ }
+
+ // Set the button's icon that represents it.
+ setBackground(resizeDrawable(getResources().getDrawable(drawableId), scale));
+
+ // Check if this button has previous values set that aren't the default.
+ final float x = sharedPrefs.getFloat(buttonId+"-X", -1f);
+ final float y = sharedPrefs.getFloat(buttonId+"-Y", -1f);
+
+ // If they are not -1, then they have a previous value set.
+ // Thus, we set those coordinate values.
+ if (x != -1f && y != -1f)
+ {
+ setX(x);
+ setY(y);
+ }
+ }
+
+ @Override
+ public boolean onTouch(View v, MotionEvent event)
+ {
+ switch(event.getAction())
+ {
+ // Get the offset of the press within the button
+ // The event X and Y locations are the offset within the button, not the screen
+ case MotionEvent.ACTION_DOWN:
+ {
+ moveOffsetX = event.getX();
+ moveOffsetY = event.getY();
+ return true;
+ }
+
+ // Only change the X/Y coordinates when we move the button.
+ case MotionEvent.ACTION_MOVE:
+ {
+ setX(getX() + event.getX() - moveOffsetX);
+ setY(getY() + event.getY() - moveOffsetY);
+ return true;
+ }
+
+ // Whenever the press event has ended
+ // is when we save all of the information.
+ case MotionEvent.ACTION_UP:
+ {
+ // Add the current X and Y positions of this button into SharedPreferences.
+ SharedPreferences.Editor editor = sharedPrefs.edit();
+ editor.putFloat(buttonId+"-X", getX());
+ editor.putFloat(buttonId+"-Y", getY());
+ editor.apply();
+ return true;
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/settings/video/VideoSettingsFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/settings/video/VideoSettingsFragment.java
new file mode 100644
index 0000000000..214612f895
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/settings/video/VideoSettingsFragment.java
@@ -0,0 +1,202 @@
+/**
+ * Copyright 2013 Dolphin Emulator Project
+ * Licensed under GPLv2
+ * Refer to the license.txt file included.
+ */
+
+package org.dolphinemu.dolphinemu.settings.video;
+
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
+import android.os.Bundle;
+import android.os.Environment;
+import android.preference.ListPreference;
+import android.preference.PreferenceFragment;
+import android.preference.PreferenceManager;
+import android.preference.PreferenceScreen;
+
+import org.dolphinemu.dolphinemu.R;
+import org.dolphinemu.dolphinemu.utils.EGLHelper;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.microedition.khronos.opengles.GL10;
+
+/**
+ * Responsible for handling the loading of the video preferences.
+ */
+public final class VideoSettingsFragment extends PreferenceFragment
+{
+ private final EGLHelper eglHelper = new EGLHelper(EGLHelper.EGL_OPENGL_ES2_BIT);
+ private final String vendor = eglHelper.getGL().glGetString(GL10.GL_VENDOR);
+ private final String version = eglHelper.getGL().glGetString(GL10.GL_VERSION);
+
+ @Override
+ public void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+
+ // Load the preferences from an XML resource
+ addPreferencesFromResource(R.xml.video_prefs);
+
+ //
+ // Setting valid video backends.
+ //
+ final ListPreference videoBackends = (ListPreference) findPreference("gpuPref");
+ final boolean deviceSupportsGL = eglHelper.supportsOpenGL();
+ final boolean deviceSupportsGLES3 = eglHelper.supportsGLES3();
+
+ if (deviceSupportsGL)
+ {
+ videoBackends.setEntries(R.array.videoBackendEntriesGL);
+ videoBackends.setEntryValues(R.array.videoBackendValuesGL);
+ }
+ else if (deviceSupportsGLES3)
+ {
+ videoBackends.setEntries(R.array.videoBackendEntriesGLES3);
+ videoBackends.setEntryValues(R.array.videoBackendValuesGLES3);
+ }
+ else
+ {
+ videoBackends.setEntries(R.array.videoBackendEntriesNoGLES3);
+ videoBackends.setEntryValues(R.array.videoBackendValuesNoGLES3);
+ }
+
+ //
+ // Set available post processing shaders
+ //
+
+ List<CharSequence> shader_names = new ArrayList<CharSequence>();
+ List<CharSequence> shader_values = new ArrayList<CharSequence>();
+
+ // Disabled option
+ shader_names.add("Disabled");
+ shader_values.add("");
+
+ File shaders_folder = new File(Environment.getExternalStorageDirectory()+ File.separator+"dolphin-emu"+ File.separator+"Shaders");
+ if (shaders_folder.exists())
+ {
+ File[] shaders = shaders_folder.listFiles();
+ for (File file : shaders)
+ {
+ if (file.isFile())
+ {
+ String filename = file.getName();
+ if (filename.contains(".glsl"))
+ {
+ // Strip the extension and put it in to the list
+ shader_names.add(filename.substring(0, filename.lastIndexOf('.')));
+ shader_values.add(filename.substring(0, filename.lastIndexOf('.')));
+ }
+ }
+ }
+ }
+
+ final ListPreference shader_preference = (ListPreference) findPreference("postProcessingShader");
+ shader_preference.setEntries(shader_names.toArray(new CharSequence[shader_names.size()]));
+ shader_preference.setEntryValues(shader_values.toArray(new CharSequence[shader_values.size()]));
+
+ //
+ // Disable all options if Software Rendering is used.
+ //
+ // Note that the numeric value in 'getPreference()'
+ // denotes the placement on the UI. So if more elements are
+ // added to the video settings, these may need to change.
+ //
+ final SharedPreferences sPrefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
+ final PreferenceScreen mainScreen = getPreferenceScreen();
+
+ if (videoBackends.getValue().equals("Software Renderer"))
+ {
+ mainScreen.getPreference(0).setEnabled(false);
+ mainScreen.getPreference(1).setEnabled(false);
+ mainScreen.getPreference(3).setEnabled(false);
+ }
+ else if (videoBackends.getValue().equals("OGL"))
+ {
+ mainScreen.getPreference(0).setEnabled(true);
+ mainScreen.getPreference(1).setEnabled(true);
+ mainScreen.getPreference(3).setEnabled(true);
+
+ // Check if we support stereo
+ // If we support desktop GL then we must support at least OpenGL 3.2
+ // If we only support OpenGLES then we need both OpenGLES 3.1 and AEP
+ if ((eglHelper.supportsOpenGL() && eglHelper.GetVersion() >= 320) ||
+ (eglHelper.supportsGLES3() && eglHelper.GetVersion() >= 310 && eglHelper.SupportsExtension("GL_ANDROID_extension_pack_es31a")))
+ mainScreen.findPreference("StereoscopyScreen").setEnabled(true);
+ else
+ mainScreen.findPreference("StereoscopyScreen").setEnabled(false);
+ }
+
+ // Also set a listener, so that if someone changes the video backend, it will disable
+ // the video settings, upon the user choosing "Software Rendering".
+ sPrefs.registerOnSharedPreferenceChangeListener(new OnSharedPreferenceChangeListener()
+ {
+ @Override
+ public void onSharedPreferenceChanged(SharedPreferences preference, String key)
+ {
+ if (key.equals("gpuPref"))
+ {
+ if (preference.getString(key, "Software Renderer").equals("Software Renderer"))
+ {
+ mainScreen.getPreference(0).setEnabled(false);
+ mainScreen.getPreference(1).setEnabled(false);
+ mainScreen.getPreference(3).setEnabled(false);
+ }
+ else if (preference.getString(key, "Software Renderer").equals("OGL"))
+ {
+ mainScreen.getPreference(0).setEnabled(true);
+ mainScreen.getPreference(1).setEnabled(true);
+ mainScreen.getPreference(3).setEnabled(true);
+
+ // Create an alert telling them that their phone sucks
+ if (eglHelper.supportsGLES3()
+ && vendor.equals("Qualcomm")
+ && getQualcommVersion() == 14.0f)
+ {
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ builder.setTitle(R.string.device_compat_warning);
+ builder.setMessage(R.string.device_gles3compat_warning_msg);
+ builder.setPositiveButton(R.string.yes, null);
+ builder.setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which)
+ {
+ // Get an editor.
+ SharedPreferences.Editor editor = sPrefs.edit();
+ editor.putString("gpuPref", "Software Renderer");
+ editor.apply();
+ videoBackends.setValue("Software Renderer");
+ videoBackends.setSummary("Software Renderer");
+ }
+ });
+ builder.show();
+ }
+ }
+ }
+ }
+ });
+ }
+
+ private float getQualcommVersion()
+ {
+ final int start = version.indexOf("V@") + 2;
+ final StringBuilder versionBuilder = new StringBuilder();
+
+ for (int i = start; i < version.length(); i++)
+ {
+ char c = version.charAt(i);
+
+ // End of numeric portion of version string.
+ if (c == ' ')
+ break;
+
+ versionBuilder.append(c);
+ }
+
+ return Float.parseFloat(versionBuilder.toString());
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/sidemenu/SideMenuAdapter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/sidemenu/SideMenuAdapter.java
new file mode 100644
index 0000000000..60fd8b56f3
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/sidemenu/SideMenuAdapter.java
@@ -0,0 +1,75 @@
+/**
+ * Copyright 2013 Dolphin Emulator Project
+ * Licensed under GPLv2
+ * Refer to the license.txt file included.
+ */
+
+package org.dolphinemu.dolphinemu.sidemenu;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import java.util.List;
+
+import org.dolphinemu.dolphinemu.R;
+
+/**
+ * Adapter that backs the sidebar menu.
+ * <p>
+ * Responsible for handling the elements of each sidebar item.
+ */
+public final class SideMenuAdapter extends ArrayAdapter<SideMenuItem>
+{
+ private final Context context;
+ private final int id;
+ private final List<SideMenuItem>items;
+
+ /**
+ * Constructor
+ *
+ * @param context The current {@link Context}.
+ * @param resourceId The resource ID for a layout file containing a layout to use when instantiating views.
+ * @param objects The objects to represent in the {@link ListView}.
+ */
+ public SideMenuAdapter(Context context, int resourceId, List<SideMenuItem> objects)
+ {
+ super(context, resourceId, objects);
+
+ this.context = context;
+ this.id = resourceId;
+ this.items = objects;
+ }
+
+ @Override
+ public SideMenuItem getItem(int i)
+ {
+ return items.get(i);
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent)
+ {
+ if (convertView == null)
+ {
+ LayoutInflater vi = LayoutInflater.from(context);
+ convertView = vi.inflate(id, null);
+ }
+
+ final SideMenuItem item = items.get(position);
+ if (item != null)
+ {
+ TextView title = (TextView) convertView.findViewById(R.id.SideMenuTitle);
+
+ if (title != null)
+ title.setText(item.getName());
+ }
+
+ return convertView;
+ }
+}
+
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/sidemenu/SideMenuItem.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/sidemenu/SideMenuItem.java
new file mode 100644
index 0000000000..402fad094c
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/sidemenu/SideMenuItem.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2013 Dolphin Emulator Project
+ * Licensed under GPLv2
+ * Refer to the license.txt file included.
+ */
+
+package org.dolphinemu.dolphinemu.sidemenu;
+
+
+/**
+ * Represents an item that goes in the sidemenu of the app.
+ */
+public final class SideMenuItem
+{
+ private final String name;
+ private final int id;
+
+ /**
+ * Constructor
+ *
+ * @param name The name of the SideMenuItem.
+ * @param id ID number of this specific SideMenuItem.
+ */
+ public SideMenuItem(String name, int id)
+ {
+ this.name = name;
+ this.id = id;
+ }
+
+ /**
+ * Gets the name of this SideMenuItem.
+ *
+ * @return the name of this SideMenuItem.
+ */
+ public String getName()
+ {
+ return name;
+ }
+
+ /**
+ * Gets the ID of this SideMenuItem.
+ *
+ * @return the ID of this SideMenuItem.
+ */
+ public int getID()
+ {
+ return id;
+ }
+}
+
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/CPUHelper.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/CPUHelper.java
new file mode 100644
index 0000000000..30be6e2213
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/CPUHelper.java
@@ -0,0 +1,395 @@
+package org.dolphinemu.dolphinemu.utils;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+
+import org.dolphinemu.dolphinemu.R;
+
+import android.content.Context;
+import android.os.Build;
+import android.util.Log;
+
+/**
+ * Utility class for retrieving information
+ * from a device's CPU.
+ */
+public final class CPUHelper
+{
+ private int revision;
+ private int variant;
+ private int numCores;
+ private String implementerID = "N/A";
+ private String part = "N/A";
+ private String hardware = "N/A";
+ private String processorInfo = "N/A";
+ private String features = "N/A";
+
+ private final Context ctx;
+
+ /**
+ * Constructor
+ *
+ * @param ctx The current {@link Context}.
+ */
+ public CPUHelper(Context ctx)
+ {
+ this.ctx = ctx;
+
+ try
+ {
+ // TODO: Should do other architectures as well (x86 and MIPS).
+ // Can do differentiating between platforms by using
+ // android.os.Build.CPU_ABI.
+ //
+ // CPU_ABI.contains("armeabi") == get ARM info.
+ // CPU_ABI.contains("x86") == get x86 info.
+ // CPU_ABI.contains("mips") == get MIPS info.
+ //
+ // However additional testing should be done across devices,
+ // I highly doubt /proc/cpuinfo retains the same formatting
+ // on different architectures.
+ //
+ // If push comes to shove, we can simply spit out the cpuinfo
+ // contents. I would like to avoid this if possible, however.
+
+ if (Build.CPU_ABI.contains("arm"))
+ {
+ getARMInfo();
+ }
+ else
+ {
+ Log.e("CPUHelper", "CPU architecture not supported yet.");
+ }
+ }
+ catch (IOException ioe)
+ {
+ Log.e("CPUHelper", ioe.getMessage());
+ }
+ }
+
+ /**
+ * Gets the revision number of the CPU.
+ *
+ * @return the revision number of the CPU.
+ */
+ public int getRevision()
+ {
+ return revision;
+ }
+
+
+ /**
+ * Gets the CPU variant number.
+ *
+ * @return the CPU variant number.
+ */
+ public int getVariant()
+ {
+ return variant;
+ }
+
+ /**
+ * Gets the total number of cores in the CPU.
+ *
+ * @return the total number of cores in the CPU.
+ */
+ public int getNumCores()
+ {
+ return numCores;
+ }
+
+ /**
+ * Gets the name of the implementer of the CPU.
+ *
+ * @return the name of the implementer of the CPU.
+ */
+ public String getImplementer()
+ {
+ return implementerID;
+ }
+
+ /**
+ * Gets the specific processor type of the CPU.
+ *
+ * @return the specific processor type.
+ */
+ public String getProcessorType()
+ {
+ return part;
+ }
+
+ /**
+ * Gets the internal name of the hardware.
+ *
+ * @return the internal name of the hardware.
+ */
+ public String getHardware()
+ {
+ return hardware;
+ }
+
+ /**
+ * Get the processor info string.
+ *
+ * @return the processor info string.
+ */
+ public String getProcessorInfo()
+ {
+ return processorInfo;
+ }
+
+ /**
+ * Gets the features supported by the CPU.
+ *
+ * @return the features supported by the CPU.
+ */
+ public String getFeatures()
+ {
+ return features;
+ }
+
+ /**
+ * Whether or not this CPU is using the ARM architecture.
+ *
+ * @return true if this CPU uses the ARM architecture; false otherwise.
+ */
+ public static boolean isARM()
+ {
+ return Build.CPU_ABI.contains("arm");
+ }
+
+ /**
+ * Whether or not this CPU is using the ARM64 architecture.
+ *
+ * @return true if this CPU uses the ARM64 architecture; false otherwise.
+ */
+ public static boolean isARM64() { return Build.CPU_ABI.contains("arm64"); }
+
+ /**
+ * Whether or not this CPU is using the x86 architecture.
+ *
+ * @return true if this CPU uses the x86 architecture; false otherwise.
+ */
+ public static boolean isX86()
+ {
+ return Build.CPU_ABI.contains("x86");
+ }
+
+ /**
+ * Whether or not this CPU is using the MIPS architecture.
+ *
+ * @return true if this CPU uses the MIPS architecture; false otherwise.
+ */
+ public static boolean isMIPS()
+ {
+ return Build.CPU_ABI.contains("mips");
+ }
+
+ // Retrieves information for ARM CPUs.
+ private void getARMInfo() throws IOException
+ {
+ File info = new File("/proc/cpuinfo");
+ if (info.exists())
+ {
+ BufferedReader br = new BufferedReader(new FileReader(info));
+
+ String line;
+ while ((line = br.readLine()) != null)
+ {
+ if (line.contains("Processor\t:"))
+ {
+ this.processorInfo = parseLine(line);
+ }
+ else if (line.contains("Hardware\t:"))
+ {
+ this.hardware = parseLine(line);
+ }
+ else if (line.contains("Features\t:"))
+ {
+ this.features = parseLine(line);
+ }
+ else if (line.contains("CPU implementer\t:"))
+ {
+ this.implementerID = parseArmID(Integer.decode(parseLine(line)));
+ }
+ else if (line.contains("CPU part\t:"))
+ {
+ this.part = parseArmPartNumber(Integer.decode(parseLine(line)));
+ }
+ else if (line.contains("CPU revision\t:"))
+ {
+ this.revision = Integer.decode(parseLine(line));
+ }
+ else if (line.contains("CPU variant\t:"))
+ {
+ this.variant = Integer.decode(parseLine(line));
+ }
+ else if (line.contains("processor\t:")) // Lower case indicates a specific core number
+ {
+ this.numCores++;
+ }
+ }
+
+ br.close();
+ }
+ }
+
+ // Basic function for parsing cpuinfo format strings.
+ // cpuinfo format strings consist of [label:info] parts.
+ // We only want to retrieve the info portion so we split
+ // them using ':' as a delimeter.
+ private String parseLine(String line)
+ {
+ String[] temp = line.split(":");
+ if (temp.length != 2)
+ return "N/A";
+
+ return temp[1].trim();
+ }
+
+ // Parses an ARM CPU ID.
+ private String parseArmID(int id)
+ {
+ switch (id)
+ {
+ case 0x41:
+ return "ARM Limited";
+
+ case 0x44:
+ return "Digital Equipment Corporation";
+
+ case 0x4D:
+ return "Freescale Semiconductor Inc.";
+
+ case 0x4E:
+ return "Nvidia Corporation";
+
+ case 0x51:
+ return "Qualcomm Inc.";
+
+ case 0x56:
+ return "Marvell Semiconductor Inc.";
+
+ case 0x69:
+ return "Intel Corporation";
+
+ default:
+ return "N/A";
+ }
+ }
+
+ // Parses the ARM CPU Part number.
+ private String parseArmPartNumber(int partNum)
+ {
+ switch (partNum)
+ {
+ // Qualcomm part numbers.
+ case 0x00F:
+ return "Qualcomm Scorpion";
+
+ case 0x02D:
+ return "Qualcomm Dual Scorpion";
+
+ case 0x04D:
+ return "Qualcomm Dual Krait";
+
+ case 0x06F:
+ return "Qualcomm Quad Krait";
+
+ // Marvell Semiconductor part numbers
+ case 0x131:
+ return "Marvell Feroceon";
+
+ case 0x581:
+ return "Marvell PJ4/PJ4b";
+
+ case 0x584:
+ return "Marvell Dual PJ4/PJ4b";
+
+ // Official ARM part numbers.
+ case 0x920:
+ return "ARM920";
+
+ case 0x922:
+ return "ARM922";
+
+ case 0x926:
+ return "ARM926";
+
+ case 0x940:
+ return "ARM940";
+
+ case 0x946:
+ return "ARM946";
+
+ case 0x966:
+ return "ARM966";
+
+ case 0x968:
+ return "ARM968";
+
+ case 0xB02:
+ return "ARM11 MPCore";
+
+ case 0xB36:
+ return "ARM1136";
+
+ case 0xB56:
+ return "ARM1156";
+
+ case 0xB76:
+ return "ARM1176";
+
+ case 0xC05:
+ return "ARM Cortex A5";
+
+ case 0xC07:
+ return "ARM Cortex-A7 MPCore";
+
+ case 0xC08:
+ return "ARM Cortex A8";
+
+ case 0xC09:
+ return "ARM Cortex A9";
+
+ case 0xC0C:
+ return "ARM Cortex A12";
+
+ case 0xC0F:
+ return "ARM Cortex A15";
+
+ case 0xC14:
+ return "ARM Cortex R4";
+
+ case 0xC15:
+ return "ARM Cortex R5";
+
+ case 0xC20:
+ return "ARM Cortex M0";
+
+ case 0xC21:
+ return "ARM Cortex M1";
+
+ case 0xC23:
+ return "ARM Cortex M3";
+
+ case 0xC24:
+ return "ARM Cortex M4";
+
+ case 0xC60:
+ return "ARM Cortex M0+";
+
+ case 0xD03:
+ return "ARM Cortex A53";
+
+ case 0xD07:
+ return "ARM Cortex A57 MPCore";
+
+
+ default: // Unknown/Not yet added to list.
+ return String.format(ctx.getString(R.string.unknown_part_num), partNum);
+ }
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/EGLHelper.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/EGLHelper.java
new file mode 100644
index 0000000000..4eef5f6a3d
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/EGLHelper.java
@@ -0,0 +1,393 @@
+/**
+ * Copyright 2013 Dolphin Emulator Project
+ * Licensed under GPLv2
+ * Refer to the license.txt file included.
+ */
+
+package org.dolphinemu.dolphinemu.utils;
+
+import javax.microedition.khronos.egl.EGL10;
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.egl.EGLContext;
+import javax.microedition.khronos.egl.EGLDisplay;
+import javax.microedition.khronos.egl.EGLSurface;
+import javax.microedition.khronos.opengles.GL10;
+
+import android.opengl.GLES30;
+import android.util.Log;
+
+import org.dolphinemu.dolphinemu.NativeLibrary;
+
+/**
+ * Utility class that abstracts all the stuff about
+ * EGL initialization out of the way if all that is
+ * wanted is to query the underlying GL API for information.
+ */
+public final class EGLHelper
+{
+ private final EGL10 mEGL;
+ private final EGLDisplay mDisplay;
+ private EGLConfig[] mEGLConfigs;
+ private EGLContext mEGLContext;
+ private EGLSurface mEGLSurface;
+ private GL10 mGL;
+
+ // GL support flags
+ private boolean supportGL;
+ private boolean supportGLES2;
+ private boolean supportGLES3;
+
+ // Renderable type bitmasks
+ public static final int EGL_OPENGL_ES_BIT = 0x0001;
+ public static final int EGL_OPENGL_ES2_BIT = 0x0004;
+ public static final int EGL_OPENGL_BIT = 0x0008;
+ public static final int EGL_OPENGL_ES3_BIT_KHR = 0x0040;
+
+ // API types
+ public static final int EGL_OPENGL_ES_API = 0x30A0;
+ public static final int EGL_OPENGL_API = 0x30A2;
+
+ /**
+ * Constructor
+ * <p>
+ * Initializes the underlying {@link EGLSurface} with a width and height of 1.
+ * This is useful if all you need to use this class for is to query information
+ * from specific API contexts.
+ *
+ * @param renderableType Bitmask indicating which types of client API contexts
+ * the framebuffer config must support.
+ */
+ public EGLHelper(int renderableType)
+ {
+ this(1, 1, renderableType);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param width Width of the underlying {@link EGLSurface}.
+ * @param height Height of the underlying {@link EGLSurface}.
+ * @param renderableType Bitmask indicating which types of client API contexts
+ * the framebuffer config must support.
+ */
+ public EGLHelper(int width, int height, int renderableType)
+ {
+ // Initialize handle to an EGL display.
+ mEGL = (EGL10) EGLContext.getEGL();
+ mDisplay = mEGL.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
+
+ // If a display is present, initialize EGL.
+ if (mDisplay != EGL10.EGL_NO_DISPLAY)
+ {
+ int[] version = new int[2];
+ if (mEGL.eglInitialize(mDisplay, version))
+ {
+ // Detect supported GL APIs, initialize configs, etc.
+ detect();
+
+ // Create context and surface
+ create(width, height, renderableType);
+ }
+ else
+ {
+ Log.e("EGLHelper", "Error initializing EGL.");
+ }
+ }
+ else
+ {
+ Log.e("EGLHelper", "Error initializing EGL display.");
+ }
+ }
+
+ /**
+ * Releases all resources associated with this helper.
+ * <p>
+ * This should be called whenever this helper is no longer needed.
+ */
+ public void closeHelper()
+ {
+ mEGL.eglTerminate(mDisplay);
+ }
+
+ /**
+ * Gets information through EGL.<br/>
+ * <p>
+ * Index 0: Vendor <br/>
+ * Index 1: Version <br/>
+ * Index 2: Renderer <br/>
+ * Index 3: Extensions <br/>
+ *
+ * @return information retrieved through EGL.
+ */
+ public String[] getEGLInfo()
+ {
+ String[] info = {
+ mGL.glGetString(GL10.GL_VENDOR),
+ mGL.glGetString(GL10.GL_VERSION),
+ mGL.glGetString(GL10.GL_RENDERER),
+ mGL.glGetString(GL10.GL_EXTENSIONS),
+ };
+
+ return info;
+ }
+
+ /**
+ * Whether or not this device supports OpenGL.
+ *
+ * @return true if this device supports OpenGL; false otherwise.
+ */
+ public boolean supportsOpenGL()
+ {
+ return supportGL;
+ }
+
+ /**
+ * Whether or not this device supports OpenGL ES 2.
+ * <br/>
+ * Note that if this returns true, then OpenGL ES 1 is also supported.
+ *
+ * @return true if this device supports OpenGL ES 2; false otherwise.
+ */
+ public boolean supportsGLES2()
+ {
+ return supportGLES2;
+ }
+
+ /**
+ * Whether or not this device supports OpenGL ES 3.
+ * <br/>
+ * Note that if this returns true, then OpenGL ES 1 and 2 are also supported.
+ *
+ * @return true if this device supports OpenGL ES 3; false otherwise.
+ */
+ public boolean supportsGLES3()
+ {
+ return supportGLES3;
+ }
+
+ /**
+ * Gets the underlying {@link EGL10} instance.
+ *
+ * @return the underlying {@link EGL10} instance.
+ */
+ public EGL10 getEGL()
+ {
+ return mEGL;
+ }
+
+ /**
+ * Gets the underlying {@link GL10} instance.
+ *
+ * @return the underlying {@link GL10} instance.
+ */
+ public GL10 getGL()
+ {
+ return mGL;
+ }
+
+ /**
+ * Gets the underlying {@link EGLDisplay}.
+ *
+ * @return the underlying {@link EGLDisplay}
+ */
+ public EGLDisplay getDisplay()
+ {
+ return mDisplay;
+ }
+
+ /**
+ * Gets all supported framebuffer configurations for this device.
+ *
+ * @return all supported framebuffer configurations for this device.
+ */
+ public EGLConfig[] getConfigs()
+ {
+ return mEGLConfigs;
+ }
+
+ /**
+ * Gets the underlying {@link EGLContext}.
+ *
+ * @return the underlying {@link EGLContext}.
+ */
+ public EGLContext getContext()
+ {
+ return mEGLContext;
+ }
+
+ /**
+ * Gets the underlying {@link EGLSurface}.
+ *
+ * @return the underlying {@link EGLSurface}.
+ */
+ public EGLSurface getSurface()
+ {
+ return mEGLSurface;
+ }
+
+ // Detects the specific kind of GL modes that are supported
+ private boolean detect()
+ {
+ // Get total number of configs available.
+ int[] numConfigs = new int[1];
+ if (!mEGL.eglGetConfigs(mDisplay, null, 0, numConfigs))
+ {
+ Log.e("EGLHelper", "Error retrieving number of EGL configs available.");
+ return false;
+ }
+
+ // Now get all the configurations
+ mEGLConfigs = new EGLConfig[numConfigs[0]];
+ if (!mEGL.eglGetConfigs(mDisplay, mEGLConfigs, mEGLConfigs.length, numConfigs))
+ {
+ Log.e("EGLHelper", "Error retrieving all EGL configs.");
+ return false;
+ }
+
+ for (int i = 0; i < mEGLConfigs.length; i++)
+ {
+ int[] attribVal = new int[1];
+ boolean ret = mEGL.eglGetConfigAttrib(mDisplay, mEGLConfigs[i], EGL10.EGL_RENDERABLE_TYPE, attribVal);
+ if (ret)
+ {
+ if ((attribVal[0] & EGL_OPENGL_BIT) != 0)
+ supportGL = true;
+
+ if ((attribVal[0] & EGL_OPENGL_ES2_BIT) != 0)
+ supportGLES2 = true;
+
+ if ((attribVal[0] & EGL_OPENGL_ES3_BIT_KHR) != 0)
+ supportGLES3 = true;
+ }
+ }
+
+ return true;
+ }
+
+ // Creates the context and surface.
+ private void create(int width, int height, int renderableType)
+ {
+ int[] attribs = {
+ EGL10.EGL_WIDTH, width,
+ EGL10.EGL_HEIGHT, height,
+ EGL10.EGL_NONE
+ };
+
+ // Initially we just assume GLES2 will be the default context.
+ int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
+ int[] ctx_attribs = {
+ EGL_CONTEXT_CLIENT_VERSION, 2,
+ EGL10.EGL_NONE
+ };
+
+ // Determine the type of context that will be created
+ // and change the attribute arrays accordingly.
+ switch (renderableType)
+ {
+ case EGL_OPENGL_ES_BIT:
+ ctx_attribs[1] = 1;
+ break;
+
+ case EGL_OPENGL_BIT:
+ ctx_attribs[0] = EGL10.EGL_NONE;
+ break;
+
+ case EGL_OPENGL_ES3_BIT_KHR:
+ ctx_attribs[1] = 3;
+ break;
+
+ case EGL_OPENGL_ES2_BIT:
+ default: // Fall-back to GLES 2.
+ ctx_attribs[1] = 2;
+ break;
+ }
+ if (renderableType == EGL_OPENGL_BIT)
+ NativeLibrary.eglBindAPI(EGL_OPENGL_API);
+ else
+ NativeLibrary.eglBindAPI(EGL_OPENGL_ES_API);
+
+ mEGLContext = mEGL.eglCreateContext(mDisplay, mEGLConfigs[0], EGL10.EGL_NO_CONTEXT, ctx_attribs);
+ mEGLSurface = mEGL.eglCreatePbufferSurface(mDisplay, mEGLConfigs[0], attribs);
+ mEGL.eglMakeCurrent(mDisplay, mEGLSurface, mEGLSurface, mEGLContext);
+ mGL = (GL10) mEGLContext.getGL();
+ }
+
+ /**
+ * Simplified call to {@link GL10#glGetString(int)}
+ * <p>
+ * Accepts the following constants:
+ * <ul>
+ * <li>GL_VENDOR - Company responsible for the GL implementation.</li>
+ * <li>GL_VERSION - Version or release number.</li>
+ * <li>GL_RENDERER - Name of the renderer</li>
+ * <li>GL_SHADING_LANGUAGE_VERSION - Version or release number of the shading language </li>
+ * </ul>
+ *
+ * @param glEnum A symbolic constant within {@link GL10}.
+ *
+ * @return the string information represented by {@code glEnum}.
+ */
+ public String glGetString(int glEnum)
+ {
+ return mGL.glGetString(glEnum);
+ }
+
+ /**
+ * Simplified call to {@link GLES30#glGetStringi(int, int)}
+ * <p>
+ * Accepts the following constants:
+ * <ul>
+ * <li>GL_VENDOR - Company responsible for the GL implementation.</li>
+ * <li>GL_VERSION - Version or release number.</li>
+ * <li>GL_RENDERER - Name of the renderer</li>
+ * <li>GL_SHADING_LANGUAGE_VERSION - Version or release number of the shading language </li>
+ * <li>GL_EXTENSIONS - Extension string supported by the implementation at {@code index}.</li>
+ * </ul>
+ *
+ * @param glEnum A symbolic GL constant
+ * @param index The index of the string to return.
+ *
+ * @return the string information represented by {@code glEnum} and {@code index}.
+ */
+ public String glGetStringi(int glEnum, int index)
+ {
+ return GLES30.glGetStringi(glEnum, index);
+ }
+
+ public boolean SupportsExtension(String extension)
+ {
+ int[] num_ext = new int[1];
+ GLES30.glGetIntegerv(GLES30.GL_NUM_EXTENSIONS, num_ext, 0);
+
+ for (int i = 0; i < num_ext[0]; ++i)
+ {
+ String ext = GLES30.glGetStringi(GLES30.GL_EXTENSIONS, i);
+ if (ext.equals(extension))
+ return true;
+ }
+ return false;
+ }
+
+ public int GetVersion()
+ {
+ int[] major = new int[1];
+ int[] minor = new int[1];
+ GLES30.glGetIntegerv(GLES30.GL_MAJOR_VERSION, major, 0);
+ GLES30.glGetIntegerv(GLES30.GL_MINOR_VERSION, minor, 0);
+ return major[0] * 100 + minor[0] * 10;
+ }
+
+ /**
+ * Simplified call to {@link GL10#glGetIntegerv(int, int[], int)
+ *
+ * @param glEnum A symbolic GL constant.
+ *
+ * @return the integer information represented by {@code glEnum}.
+ */
+ public int glGetInteger(int glEnum)
+ {
+ int[] val = new int[1];
+ mGL.glGetIntegerv(glEnum, val, 0);
+ return val[0];
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/SliderPreference.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/SliderPreference.java
new file mode 100644
index 0000000000..eab6f74ff0
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/SliderPreference.java
@@ -0,0 +1,94 @@
+package org.dolphinemu.dolphinemu.utils;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.os.Bundle;
+import android.preference.DialogPreference;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+import org.dolphinemu.dolphinemu.R;
+
+public class SliderPreference extends DialogPreference implements SeekBar.OnSeekBarChangeListener, View.OnClickListener
+{
+ private static final String androidns = "http://schemas.android.com/apk/res/android";
+
+ // SeekBar
+ private int m_max, m_value;
+ private SeekBar m_seekbar;
+
+ // TextView
+ private TextView m_textview;
+
+ public SliderPreference(Context context, AttributeSet attrs)
+ {
+ super(context, attrs);
+
+ // Seekbar values
+ m_value = attrs.getAttributeIntValue(androidns, "defaultValue", 0);
+ m_max = attrs.getAttributeIntValue(androidns, "max", 100);
+ }
+
+ @Override
+ protected View onCreateDialogView()
+ {
+ LayoutInflater inflater = LayoutInflater.from(getContext());
+ LinearLayout layout = (LinearLayout)inflater.inflate(R.layout.slider_layout, null, false);
+
+ m_seekbar = (SeekBar)layout.findViewById(R.id.sliderSeekBar);
+ m_textview = (TextView)layout.findViewById(R.id.sliderTextView);
+
+ if (shouldPersist())
+ m_value = Integer.valueOf(getPersistedString(Integer.toString(m_value)));
+
+ m_seekbar.setMax(m_max);
+ m_seekbar.setProgress(m_value);
+ setProgressText(m_value);
+ m_seekbar.setOnSeekBarChangeListener(this);
+
+ return layout;
+ }
+
+ // SeekBar overrides
+ @Override
+ public void onProgressChanged(SeekBar seek, int value, boolean fromTouch)
+ {
+ m_value = value;
+ setProgressText(value);
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seek) {}
+ @Override
+ public void onStopTrackingTouch(SeekBar seek) {}
+
+ void setProgressText(int value)
+ {
+ m_textview.setText(String.valueOf(value));
+ }
+
+ @Override
+ public void showDialog(Bundle state)
+ {
+ super.showDialog(state);
+
+ Button positiveButton = ((AlertDialog) getDialog()).getButton(AlertDialog.BUTTON_POSITIVE);
+ positiveButton.setOnClickListener(this);
+ }
+
+ @Override
+ public void onClick(View v)
+ {
+ if (shouldPersist())
+ {
+ persistString(Integer.toString(m_seekbar.getProgress()));
+ callChangeListener(m_seekbar.getProgress());
+ }
+ ((AlertDialog) getDialog()).dismiss();
+ }
+}
diff --git a/Source/Android/app/src/main/res/drawable-hdpi/gcpad_a.png b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_a.png
new file mode 100644
index 0000000000..1b06c02e91
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_a.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-hdpi/gcpad_a_pressed.png b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_a_pressed.png
new file mode 100644
index 0000000000..281e2cce8b
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_a_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-hdpi/gcpad_b.png b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_b.png
new file mode 100644
index 0000000000..4a2fce33e2
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_b.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-hdpi/gcpad_b_pressed.png b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_b_pressed.png
new file mode 100644
index 0000000000..38903deeaf
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_b_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-hdpi/gcpad_c.png b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_c.png
new file mode 100644
index 0000000000..941e808d0b
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_c.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-hdpi/gcpad_c_pressed.png b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_c_pressed.png
new file mode 100644
index 0000000000..033bbb413a
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_c_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-hdpi/gcpad_dpad.png b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_dpad.png
new file mode 100644
index 0000000000..bef4bd338a
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_dpad.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-hdpi/gcpad_dpad_pressed_down.png b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_dpad_pressed_down.png
new file mode 100644
index 0000000000..f917478275
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_dpad_pressed_down.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-hdpi/gcpad_dpad_pressed_downleft.png b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_dpad_pressed_downleft.png
new file mode 100644
index 0000000000..955ad245c7
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_dpad_pressed_downleft.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-hdpi/gcpad_dpad_pressed_downright.png b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_dpad_pressed_downright.png
new file mode 100644
index 0000000000..268f5aed18
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_dpad_pressed_downright.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-hdpi/gcpad_dpad_pressed_left.png b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_dpad_pressed_left.png
new file mode 100644
index 0000000000..18ec98bbe5
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_dpad_pressed_left.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-hdpi/gcpad_dpad_pressed_right.png b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_dpad_pressed_right.png
new file mode 100644
index 0000000000..80b2a3bb65
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_dpad_pressed_right.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-hdpi/gcpad_dpad_pressed_up.png b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_dpad_pressed_up.png
new file mode 100644
index 0000000000..5c084fb6ad
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_dpad_pressed_up.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-hdpi/gcpad_dpad_pressed_upleft.png b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_dpad_pressed_upleft.png
new file mode 100644
index 0000000000..9d4971cdcd
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_dpad_pressed_upleft.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-hdpi/gcpad_dpad_upright.png b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_dpad_upright.png
new file mode 100644
index 0000000000..6ae73c47b9
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_dpad_upright.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-hdpi/gcpad_joystick.png b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_joystick.png
new file mode 100644
index 0000000000..7d76fe18a6
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_joystick.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-hdpi/gcpad_joystick_pressed.png b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_joystick_pressed.png
new file mode 100644
index 0000000000..0efcec37b7
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_joystick_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-hdpi/gcpad_joystick_range.png b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_joystick_range.png
new file mode 100644
index 0000000000..50908e35ca
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_joystick_range.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-hdpi/gcpad_l.png b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_l.png
new file mode 100644
index 0000000000..a39e4b163c
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_l.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-hdpi/gcpad_l_pressed.png b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_l_pressed.png
new file mode 100644
index 0000000000..511b8ea382
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_l_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-hdpi/gcpad_r.png b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_r.png
new file mode 100644
index 0000000000..89d7a75497
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_r.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-hdpi/gcpad_r_pressed.png b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_r_pressed.png
new file mode 100644
index 0000000000..940ea44b58
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_r_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-hdpi/gcpad_start.png b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_start.png
new file mode 100644
index 0000000000..8685c69999
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_start.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-hdpi/gcpad_start_pressed.png b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_start_pressed.png
new file mode 100644
index 0000000000..1385fbf20d
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_start_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-hdpi/gcpad_x.png b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_x.png
new file mode 100644
index 0000000000..ae6152009d
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_x.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-hdpi/gcpad_x_pressed.png b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_x_pressed.png
new file mode 100644
index 0000000000..b18ee63095
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_x_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-hdpi/gcpad_y.png b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_y.png
new file mode 100644
index 0000000000..d17b3d6997
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_y.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-hdpi/gcpad_y_pressed.png b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_y_pressed.png
new file mode 100644
index 0000000000..5c2d2084b5
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_y_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-hdpi/gcpad_z.png b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_z.png
new file mode 100644
index 0000000000..3fbb99cb03
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_z.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-hdpi/gcpad_z_pressed.png b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_z_pressed.png
new file mode 100644
index 0000000000..a180a1520c
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-hdpi/gcpad_z_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-hdpi/ic_drawer.png b/Source/Android/app/src/main/res/drawable-hdpi/ic_drawer.png
new file mode 100644
index 0000000000..6614ea4f4d
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-hdpi/ic_drawer.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-hdpi/ic_launcher.png b/Source/Android/app/src/main/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000000..3b9af56e5d
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-hdpi/ic_menu_file.png b/Source/Android/app/src/main/res/drawable-hdpi/ic_menu_file.png
new file mode 100644
index 0000000000..c90a3b6b43
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-hdpi/ic_menu_file.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-hdpi/ic_menu_folder.png b/Source/Android/app/src/main/res/drawable-hdpi/ic_menu_folder.png
new file mode 100644
index 0000000000..5df998b9fe
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-hdpi/ic_menu_folder.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-ldpi/gcpad_a.png b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_a.png
new file mode 100644
index 0000000000..10ec9b1120
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_a.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-ldpi/gcpad_a_pressed.png b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_a_pressed.png
new file mode 100644
index 0000000000..f8f19736c7
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_a_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-ldpi/gcpad_b.png b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_b.png
new file mode 100644
index 0000000000..848364cfd7
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_b.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-ldpi/gcpad_b_pressed.png b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_b_pressed.png
new file mode 100644
index 0000000000..f6372ad45f
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_b_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-ldpi/gcpad_c.png b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_c.png
new file mode 100644
index 0000000000..80bbd89a7b
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_c.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-ldpi/gcpad_c_pressed.png b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_c_pressed.png
new file mode 100644
index 0000000000..1a4e364590
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_c_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-ldpi/gcpad_dpad.png b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_dpad.png
new file mode 100644
index 0000000000..1e21661f4f
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_dpad.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-ldpi/gcpad_dpad_pressed_down.png b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_dpad_pressed_down.png
new file mode 100644
index 0000000000..92bbf38b8f
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_dpad_pressed_down.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-ldpi/gcpad_dpad_pressed_downleft.png b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_dpad_pressed_downleft.png
new file mode 100644
index 0000000000..6df60a536c
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_dpad_pressed_downleft.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-ldpi/gcpad_dpad_pressed_downright.png b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_dpad_pressed_downright.png
new file mode 100644
index 0000000000..4ca6bb3fdb
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_dpad_pressed_downright.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-ldpi/gcpad_dpad_pressed_left.png b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_dpad_pressed_left.png
new file mode 100644
index 0000000000..42c5792a8a
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_dpad_pressed_left.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-ldpi/gcpad_dpad_pressed_right.png b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_dpad_pressed_right.png
new file mode 100644
index 0000000000..68355c1036
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_dpad_pressed_right.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-ldpi/gcpad_dpad_pressed_up.png b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_dpad_pressed_up.png
new file mode 100644
index 0000000000..4955dea697
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_dpad_pressed_up.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-ldpi/gcpad_dpad_pressed_upleft.png b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_dpad_pressed_upleft.png
new file mode 100644
index 0000000000..7d6850811c
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_dpad_pressed_upleft.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-ldpi/gcpad_dpad_upright.png b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_dpad_upright.png
new file mode 100644
index 0000000000..49aa077114
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_dpad_upright.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-ldpi/gcpad_joystick.png b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_joystick.png
new file mode 100644
index 0000000000..c5e6b3a990
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_joystick.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-ldpi/gcpad_joystick_pressed.png b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_joystick_pressed.png
new file mode 100644
index 0000000000..751bd76900
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_joystick_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-ldpi/gcpad_joystick_range.png b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_joystick_range.png
new file mode 100644
index 0000000000..230a577975
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_joystick_range.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-ldpi/gcpad_l.png b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_l.png
new file mode 100644
index 0000000000..fcffa64f6b
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_l.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-ldpi/gcpad_l_pressed.png b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_l_pressed.png
new file mode 100644
index 0000000000..9d65af8cdc
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_l_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-ldpi/gcpad_r.png b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_r.png
new file mode 100644
index 0000000000..beacd4f0e1
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_r.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-ldpi/gcpad_r_pressed.png b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_r_pressed.png
new file mode 100644
index 0000000000..99c381f32b
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_r_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-ldpi/gcpad_start.png b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_start.png
new file mode 100644
index 0000000000..b71409464e
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_start.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-ldpi/gcpad_start_pressed.png b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_start_pressed.png
new file mode 100644
index 0000000000..24da90413c
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_start_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-ldpi/gcpad_x.png b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_x.png
new file mode 100644
index 0000000000..8bdff55027
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_x.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-ldpi/gcpad_x_pressed.png b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_x_pressed.png
new file mode 100644
index 0000000000..cb7d423448
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_x_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-ldpi/gcpad_y.png b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_y.png
new file mode 100644
index 0000000000..ebb9c20fab
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_y.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-ldpi/gcpad_y_pressed.png b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_y_pressed.png
new file mode 100644
index 0000000000..ddc68febc6
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_y_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-ldpi/gcpad_z.png b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_z.png
new file mode 100644
index 0000000000..d65d4d3d10
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_z.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-ldpi/gcpad_z_pressed.png b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_z_pressed.png
new file mode 100644
index 0000000000..3c74a2a679
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-ldpi/gcpad_z_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-mdpi/gcpad_a.png b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_a.png
new file mode 100644
index 0000000000..bd996107e6
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_a.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-mdpi/gcpad_a_pressed.png b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_a_pressed.png
new file mode 100644
index 0000000000..7837e46058
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_a_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-mdpi/gcpad_b.png b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_b.png
new file mode 100644
index 0000000000..6d8c40dd6c
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_b.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-mdpi/gcpad_b_pressed.png b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_b_pressed.png
new file mode 100644
index 0000000000..3ceb1ad24f
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_b_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-mdpi/gcpad_c.png b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_c.png
new file mode 100644
index 0000000000..b7cff6224b
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_c.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-mdpi/gcpad_c_pressed.png b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_c_pressed.png
new file mode 100644
index 0000000000..939fc8b22f
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_c_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-mdpi/gcpad_dpad.png b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_dpad.png
new file mode 100644
index 0000000000..b1bb74dc5d
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_dpad.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-mdpi/gcpad_dpad_pressed_down.png b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_dpad_pressed_down.png
new file mode 100644
index 0000000000..c403bfe4d4
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_dpad_pressed_down.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-mdpi/gcpad_dpad_pressed_downleft.png b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_dpad_pressed_downleft.png
new file mode 100644
index 0000000000..f00c5241a5
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_dpad_pressed_downleft.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-mdpi/gcpad_dpad_pressed_downright.png b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_dpad_pressed_downright.png
new file mode 100644
index 0000000000..ce76ba3ec9
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_dpad_pressed_downright.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-mdpi/gcpad_dpad_pressed_left.png b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_dpad_pressed_left.png
new file mode 100644
index 0000000000..56f2955a26
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_dpad_pressed_left.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-mdpi/gcpad_dpad_pressed_right.png b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_dpad_pressed_right.png
new file mode 100644
index 0000000000..a8aea3e726
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_dpad_pressed_right.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-mdpi/gcpad_dpad_pressed_up.png b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_dpad_pressed_up.png
new file mode 100644
index 0000000000..7bff06a932
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_dpad_pressed_up.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-mdpi/gcpad_dpad_pressed_upleft.png b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_dpad_pressed_upleft.png
new file mode 100644
index 0000000000..71d634411b
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_dpad_pressed_upleft.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-mdpi/gcpad_dpad_upright.png b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_dpad_upright.png
new file mode 100644
index 0000000000..9a6c65f76c
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_dpad_upright.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-mdpi/gcpad_joystick.png b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_joystick.png
new file mode 100644
index 0000000000..0a580b7bb0
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_joystick.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-mdpi/gcpad_joystick_pressed.png b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_joystick_pressed.png
new file mode 100644
index 0000000000..54ef0252ea
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_joystick_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-mdpi/gcpad_joystick_range.png b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_joystick_range.png
new file mode 100644
index 0000000000..8159402fd6
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_joystick_range.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-mdpi/gcpad_l.png b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_l.png
new file mode 100644
index 0000000000..1b5e4d93e2
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_l.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-mdpi/gcpad_l_pressed.png b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_l_pressed.png
new file mode 100644
index 0000000000..2dda917a6e
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_l_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-mdpi/gcpad_r.png b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_r.png
new file mode 100644
index 0000000000..3b13ccc86a
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_r.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-mdpi/gcpad_r_pressed.png b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_r_pressed.png
new file mode 100644
index 0000000000..8769c5c657
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_r_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-mdpi/gcpad_start.png b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_start.png
new file mode 100644
index 0000000000..6b032d26bf
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_start.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-mdpi/gcpad_start_pressed.png b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_start_pressed.png
new file mode 100644
index 0000000000..1db374ff1e
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_start_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-mdpi/gcpad_x.png b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_x.png
new file mode 100644
index 0000000000..7f560abc73
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_x.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-mdpi/gcpad_x_pressed.png b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_x_pressed.png
new file mode 100644
index 0000000000..68b1c49874
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_x_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-mdpi/gcpad_y.png b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_y.png
new file mode 100644
index 0000000000..5c37451987
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_y.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-mdpi/gcpad_y_pressed.png b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_y_pressed.png
new file mode 100644
index 0000000000..23a2b0fae8
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_y_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-mdpi/gcpad_z.png b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_z.png
new file mode 100644
index 0000000000..7e569fa572
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_z.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-mdpi/gcpad_z_pressed.png b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_z_pressed.png
new file mode 100644
index 0000000000..44a2720a40
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-mdpi/gcpad_z_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-mdpi/ic_drawer.png b/Source/Android/app/src/main/res/drawable-mdpi/ic_drawer.png
new file mode 100644
index 0000000000..b05c026c18
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-mdpi/ic_drawer.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-mdpi/ic_launcher.png b/Source/Android/app/src/main/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000000..065f08541d
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-mdpi/ic_menu_file.png b/Source/Android/app/src/main/res/drawable-mdpi/ic_menu_file.png
new file mode 100644
index 0000000000..aad03cbf38
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-mdpi/ic_menu_file.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-mdpi/ic_menu_folder.png b/Source/Android/app/src/main/res/drawable-mdpi/ic_menu_folder.png
new file mode 100644
index 0000000000..a15687a8cd
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-mdpi/ic_menu_folder.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_a.png b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_a.png
new file mode 100644
index 0000000000..e0f9e0dd20
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_a.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_a_pressed.png b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_a_pressed.png
new file mode 100644
index 0000000000..0ced23c378
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_a_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_b.png b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_b.png
new file mode 100644
index 0000000000..409e010127
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_b.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_b_pressed.png b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_b_pressed.png
new file mode 100644
index 0000000000..a0e5dbb681
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_b_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_c.png b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_c.png
new file mode 100644
index 0000000000..9a10b58201
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_c.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_c_pressed.png b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_c_pressed.png
new file mode 100644
index 0000000000..d9630b5de0
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_c_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_dpad.png b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_dpad.png
new file mode 100644
index 0000000000..7eda219a9e
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_dpad.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_dpad_pressed_down.png b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_dpad_pressed_down.png
new file mode 100644
index 0000000000..febfed7d85
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_dpad_pressed_down.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_dpad_pressed_downleft.png b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_dpad_pressed_downleft.png
new file mode 100644
index 0000000000..d07e5d3288
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_dpad_pressed_downleft.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_dpad_pressed_downright.png b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_dpad_pressed_downright.png
new file mode 100644
index 0000000000..144ed158d9
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_dpad_pressed_downright.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_dpad_pressed_left.png b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_dpad_pressed_left.png
new file mode 100644
index 0000000000..486091add2
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_dpad_pressed_left.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_dpad_pressed_right.png b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_dpad_pressed_right.png
new file mode 100644
index 0000000000..175c7e2b7b
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_dpad_pressed_right.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_dpad_pressed_up.png b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_dpad_pressed_up.png
new file mode 100644
index 0000000000..a883e372bc
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_dpad_pressed_up.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_dpad_pressed_upleft.png b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_dpad_pressed_upleft.png
new file mode 100644
index 0000000000..3192e0c1e9
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_dpad_pressed_upleft.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_dpad_upright.png b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_dpad_upright.png
new file mode 100644
index 0000000000..1137e07168
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_dpad_upright.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_joystick.png b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_joystick.png
new file mode 100644
index 0000000000..63b0572577
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_joystick.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_joystick_pressed.png b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_joystick_pressed.png
new file mode 100644
index 0000000000..79efdcd57c
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_joystick_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_joystick_range.png b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_joystick_range.png
new file mode 100644
index 0000000000..5ea2425e22
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_joystick_range.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_l.png b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_l.png
new file mode 100644
index 0000000000..f93b5d3f40
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_l.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_l_pressed.png b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_l_pressed.png
new file mode 100644
index 0000000000..625674419c
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_l_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_r.png b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_r.png
new file mode 100644
index 0000000000..dbcfbcad91
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_r.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_r_pressed.png b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_r_pressed.png
new file mode 100644
index 0000000000..9698caf33b
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_r_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_start.png b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_start.png
new file mode 100644
index 0000000000..d5e10def25
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_start.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_start_pressed.png b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_start_pressed.png
new file mode 100644
index 0000000000..ed5da5b815
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_start_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_x.png b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_x.png
new file mode 100644
index 0000000000..f4b21f2ae5
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_x.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_x_pressed.png b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_x_pressed.png
new file mode 100644
index 0000000000..d1551ab79d
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_x_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_y.png b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_y.png
new file mode 100644
index 0000000000..2dd41ad424
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_y.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_y_pressed.png b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_y_pressed.png
new file mode 100644
index 0000000000..a897ec5b78
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_y_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_z.png b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_z.png
new file mode 100644
index 0000000000..21e1209f38
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_z.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_z_pressed.png b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_z_pressed.png
new file mode 100644
index 0000000000..b47b53255e
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xhdpi/gcpad_z_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xhdpi/ic_drawer.png b/Source/Android/app/src/main/res/drawable-xhdpi/ic_drawer.png
new file mode 100644
index 0000000000..bcf49dd73c
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xhdpi/ic_drawer.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xhdpi/ic_launcher.png b/Source/Android/app/src/main/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000000..06fdfa1d92
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xhdpi/ic_menu_file.png b/Source/Android/app/src/main/res/drawable-xhdpi/ic_menu_file.png
new file mode 100644
index 0000000000..38e94fd104
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xhdpi/ic_menu_file.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xhdpi/ic_menu_folder.png b/Source/Android/app/src/main/res/drawable-xhdpi/ic_menu_folder.png
new file mode 100644
index 0000000000..653847bde9
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xhdpi/ic_menu_folder.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_a.png b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_a.png
new file mode 100644
index 0000000000..0c5b2b2c38
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_a.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_a_pressed.png b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_a_pressed.png
new file mode 100644
index 0000000000..790d9cd83c
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_a_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_b.png b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_b.png
new file mode 100644
index 0000000000..f5c723c9ab
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_b.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_b_pressed.png b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_b_pressed.png
new file mode 100644
index 0000000000..3792c93628
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_b_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_c.png b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_c.png
new file mode 100644
index 0000000000..995a87b9bf
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_c.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_c_pressed.png b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_c_pressed.png
new file mode 100644
index 0000000000..c495cf6f0d
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_c_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_dpad.png b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_dpad.png
new file mode 100644
index 0000000000..f12421c762
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_dpad.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_dpad_pressed_down.png b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_dpad_pressed_down.png
new file mode 100644
index 0000000000..720a04f24d
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_dpad_pressed_down.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_dpad_pressed_downleft.png b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_dpad_pressed_downleft.png
new file mode 100644
index 0000000000..d238e2cb0d
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_dpad_pressed_downleft.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_dpad_pressed_downright.png b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_dpad_pressed_downright.png
new file mode 100644
index 0000000000..fd9af958f8
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_dpad_pressed_downright.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_dpad_pressed_left.png b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_dpad_pressed_left.png
new file mode 100644
index 0000000000..6f69894628
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_dpad_pressed_left.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_dpad_pressed_right.png b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_dpad_pressed_right.png
new file mode 100644
index 0000000000..5ecb6820bf
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_dpad_pressed_right.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_dpad_pressed_up.png b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_dpad_pressed_up.png
new file mode 100644
index 0000000000..c09c608848
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_dpad_pressed_up.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_dpad_pressed_upleft.png b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_dpad_pressed_upleft.png
new file mode 100644
index 0000000000..04e5352495
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_dpad_pressed_upleft.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_dpad_upright.png b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_dpad_upright.png
new file mode 100644
index 0000000000..b7b22dd7b8
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_dpad_upright.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_joystick.png b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_joystick.png
new file mode 100644
index 0000000000..226f3a131c
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_joystick.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_joystick_pressed.png b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_joystick_pressed.png
new file mode 100644
index 0000000000..1764b71d85
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_joystick_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_joystick_range.png b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_joystick_range.png
new file mode 100644
index 0000000000..240ec5006b
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_joystick_range.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_l.png b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_l.png
new file mode 100644
index 0000000000..a763b046a7
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_l.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_l_pressed.png b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_l_pressed.png
new file mode 100644
index 0000000000..0999a962ff
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_l_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_r.png b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_r.png
new file mode 100644
index 0000000000..eb4c73da87
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_r.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_r_pressed.png b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_r_pressed.png
new file mode 100644
index 0000000000..a7d95a9742
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_r_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_start.png b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_start.png
new file mode 100644
index 0000000000..819c514bf3
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_start.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_start_pressed.png b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_start_pressed.png
new file mode 100644
index 0000000000..a01537bad9
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_start_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_x.png b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_x.png
new file mode 100644
index 0000000000..4e0642d897
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_x.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_x_pressed.png b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_x_pressed.png
new file mode 100644
index 0000000000..190a138790
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_x_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_y.png b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_y.png
new file mode 100644
index 0000000000..0454149ac4
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_y.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_y_pressed.png b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_y_pressed.png
new file mode 100644
index 0000000000..b83e3013d0
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_y_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_z.png b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_z.png
new file mode 100644
index 0000000000..1533adda30
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_z.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_z_pressed.png b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_z_pressed.png
new file mode 100644
index 0000000000..801760e403
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxhdpi/gcpad_z_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxhdpi/ic_drawer.png b/Source/Android/app/src/main/res/drawable-xxhdpi/ic_drawer.png
new file mode 100644
index 0000000000..f7e3b3079d
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxhdpi/ic_drawer.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxhdpi/ic_launcher.png b/Source/Android/app/src/main/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000000..1f7e577295
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxhdpi/ic_menu_file.png b/Source/Android/app/src/main/res/drawable-xxhdpi/ic_menu_file.png
new file mode 100644
index 0000000000..34efa40606
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxhdpi/ic_menu_file.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxhdpi/ic_menu_folder.png b/Source/Android/app/src/main/res/drawable-xxhdpi/ic_menu_folder.png
new file mode 100644
index 0000000000..c0e71acba6
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxhdpi/ic_menu_folder.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_a.png b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_a.png
new file mode 100644
index 0000000000..7229b7bcb2
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_a.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_a_pressed.png b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_a_pressed.png
new file mode 100644
index 0000000000..d1012a7692
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_a_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_b.png b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_b.png
new file mode 100644
index 0000000000..7445a3cb34
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_b.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_b_pressed.png b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_b_pressed.png
new file mode 100644
index 0000000000..bcd1097253
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_b_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_c.png b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_c.png
new file mode 100644
index 0000000000..918ac0efe7
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_c.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_c_pressed.png b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_c_pressed.png
new file mode 100644
index 0000000000..83f2272fe1
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_c_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_dpad.png b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_dpad.png
new file mode 100644
index 0000000000..ae2262f786
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_dpad.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_dpad_pressed_down.png b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_dpad_pressed_down.png
new file mode 100644
index 0000000000..b992c33f42
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_dpad_pressed_down.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_dpad_pressed_downleft.png b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_dpad_pressed_downleft.png
new file mode 100644
index 0000000000..1875c08811
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_dpad_pressed_downleft.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_dpad_pressed_downright.png b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_dpad_pressed_downright.png
new file mode 100644
index 0000000000..01cd286234
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_dpad_pressed_downright.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_dpad_pressed_left.png b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_dpad_pressed_left.png
new file mode 100644
index 0000000000..30c25b944b
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_dpad_pressed_left.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_dpad_pressed_right.png b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_dpad_pressed_right.png
new file mode 100644
index 0000000000..2249c3240e
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_dpad_pressed_right.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_dpad_pressed_up.png b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_dpad_pressed_up.png
new file mode 100644
index 0000000000..fa01bb9c2d
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_dpad_pressed_up.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_dpad_pressed_upleft.png b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_dpad_pressed_upleft.png
new file mode 100644
index 0000000000..6b69dc10ab
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_dpad_pressed_upleft.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_dpad_upright.png b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_dpad_upright.png
new file mode 100644
index 0000000000..b386bc6f47
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_dpad_upright.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_joystick.png b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_joystick.png
new file mode 100644
index 0000000000..5e065adfcd
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_joystick.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_joystick_pressed.png b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_joystick_pressed.png
new file mode 100644
index 0000000000..97238ac989
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_joystick_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_joystick_range.png b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_joystick_range.png
new file mode 100644
index 0000000000..57417a1c4b
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_joystick_range.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_l.png b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_l.png
new file mode 100644
index 0000000000..7a883fc012
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_l.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_l_pressed.png b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_l_pressed.png
new file mode 100644
index 0000000000..71e673de23
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_l_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_r.png b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_r.png
new file mode 100644
index 0000000000..0f619c8d0d
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_r.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_r_pressed.png b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_r_pressed.png
new file mode 100644
index 0000000000..b3c83d5289
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_r_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_start.png b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_start.png
new file mode 100644
index 0000000000..819dece06e
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_start.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_start_pressed.png b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_start_pressed.png
new file mode 100644
index 0000000000..135375c803
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_start_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_x.png b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_x.png
new file mode 100644
index 0000000000..2f2e2db89a
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_x.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_x_pressed.png b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_x_pressed.png
new file mode 100644
index 0000000000..a636227f77
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_x_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_y.png b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_y.png
new file mode 100644
index 0000000000..bd9a13cdf0
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_y.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_y_pressed.png b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_y_pressed.png
new file mode 100644
index 0000000000..28588af109
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_y_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_z.png b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_z.png
new file mode 100644
index 0000000000..f00a80d6e4
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_z.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_z_pressed.png b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_z_pressed.png
new file mode 100644
index 0000000000..d4912af7f7
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcpad_z_pressed.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/drawable/no_banner.png b/Source/Android/app/src/main/res/drawable/no_banner.png
new file mode 100644
index 0000000000..e15ae972c8
--- /dev/null
+++ b/Source/Android/app/src/main/res/drawable/no_banner.png
Binary files differ
diff --git a/Source/Android/app/src/main/res/layout/about_layout.xml b/Source/Android/app/src/main/res/layout/about_layout.xml
new file mode 100644
index 0000000000..b3110331a5
--- /dev/null
+++ b/Source/Android/app/src/main/res/layout/about_layout.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ android:orientation="vertical">
+
+ <TextView
+ android:id="@+id/AboutItemTitle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="15dip"
+ android:layout_marginTop="6dip"
+ android:singleLine="true"
+ android:textAppearance="?android:attr/textAppearanceMedium"/>
+
+ <TextView
+ android:id="@+id/AboutItemSubTitle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="15dip"
+ android:textAppearance="?android:attr/textAppearanceSmall"/>
+
+</LinearLayout> \ No newline at end of file
diff --git a/Source/Android/app/src/main/res/layout/emulation_view.xml b/Source/Android/app/src/main/res/layout/emulation_view.xml
new file mode 100644
index 0000000000..1d0472d527
--- /dev/null
+++ b/Source/Android/app/src/main/res/layout/emulation_view.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<merge xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent">
+
+ <!-- This is what everything is rendered to during emulation -->
+ <org.dolphinemu.dolphinemu.emulation.NativeGLSurfaceView
+ android:id="@+id/emulationView"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:focusable="false"
+ android:focusableInTouchMode="false"/>
+
+ <!-- This is the onscreen input overlay -->
+ <org.dolphinemu.dolphinemu.emulation.overlay.InputOverlay
+ android:id="@+id/emulationControlOverlay"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:focusable="true"
+ android:focusableInTouchMode="true"/>
+
+</merge> \ No newline at end of file
diff --git a/Source/Android/app/src/main/res/layout/folderbrowser_list_item.xml b/Source/Android/app/src/main/res/layout/folderbrowser_list_item.xml
new file mode 100644
index 0000000000..318efc75ec
--- /dev/null
+++ b/Source/Android/app/src/main/res/layout/folderbrowser_list_item.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="fill_parent"
+ android:layout_height="?android:attr/listPreferredItemHeight"
+ android:padding="3dp">
+
+ <ImageView
+ android:id="@+id/BrowserItemIcon"
+ android:layout_width="wrap_content"
+ android:layout_height="fill_parent"
+
+ tools:src="@drawable/ic_launcher"
+
+ android:layout_alignParentTop="true"
+ android:layout_alignParentBottom="true"
+ android:layout_marginEnd="6dip"/>
+
+ <!-- Properties in the 'tools' namespace are only visible in the UI editor, not at runtime. -->
+ <TextView tools:text="@string/file_size"
+ android:id="@+id/BrowserItemSubTitle"
+ android:layout_width="fill_parent"
+ android:layout_height="26dip"
+
+ android:textColor="#bbbbbb"
+
+ android:layout_toEndOf="@id/BrowserItemIcon"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentEnd="true"
+
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ />
+
+ <!-- Properties in the 'tools' namespace are only visible in the UI editor, not at runtime. -->
+ <TextView tools:text="Name of Game"
+ android:id="@+id/BrowserItemTitle"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+
+ android:fontFamily="sans-serif-light"
+ android:textSize="22sp"
+ android:textColor="#555555"
+
+ android:singleLine="true"
+ android:ellipsize="end"
+
+ android:layout_toEndOf="@id/BrowserItemIcon"
+ android:layout_alignParentEnd="true"
+ android:layout_alignParentTop="true"
+ android:layout_above="@id/BrowserItemSubTitle"
+ android:layout_alignWithParentIfMissing="true"
+
+ android:gravity="center_vertical"
+ />
+
+</RelativeLayout>
diff --git a/Source/Android/app/src/main/res/layout/folderbrowser_listview.xml b/Source/Android/app/src/main/res/layout/folderbrowser_listview.xml
new file mode 100644
index 0000000000..3e213ed72f
--- /dev/null
+++ b/Source/Android/app/src/main/res/layout/folderbrowser_listview.xml
@@ -0,0 +1,8 @@
+<ListView xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:id="@+id/gamelist"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:choiceMode="singleChoice"
+ android:dividerHeight="1dp"
+ tools:listitem="@layout/folderbrowser_list_item"/> \ No newline at end of file
diff --git a/Source/Android/app/src/main/res/layout/gamelist_activity.xml b/Source/Android/app/src/main/res/layout/gamelist_activity.xml
new file mode 100644
index 0000000000..2c22d36afa
--- /dev/null
+++ b/Source/Android/app/src/main/res/layout/gamelist_activity.xml
@@ -0,0 +1,20 @@
+<android.support.v4.widget.DrawerLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/drawer_layout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <FrameLayout
+ android:id="@+id/content_frame"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+ <ListView
+ android:id="@+id/left_drawer"
+ android:layout_width="240dp"
+ android:layout_height="match_parent"
+ android:layout_gravity="start"
+ android:choiceMode="singleChoice"
+ android:divider="@android:color/transparent"
+ android:dividerHeight="0dp"
+ android:background="#333"/>
+</android.support.v4.widget.DrawerLayout>
diff --git a/Source/Android/app/src/main/res/layout/gamelist_list_item.xml b/Source/Android/app/src/main/res/layout/gamelist_list_item.xml
new file mode 100644
index 0000000000..c2d722c31c
--- /dev/null
+++ b/Source/Android/app/src/main/res/layout/gamelist_list_item.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="fill_parent"
+ android:layout_height="?android:attr/listPreferredItemHeight"
+ android:padding="3dp">
+
+ <ImageView
+ android:id="@+id/GameListItemIcon"
+ android:layout_width="100dp"
+ android:layout_height="wrap_content"
+
+ tools:src="@drawable/ic_launcher"
+
+ android:layout_alignParentTop="true"
+ android:layout_alignParentBottom="true"
+ android:layout_marginEnd="6dip"/>
+
+ <!-- Properties in the 'tools' namespace are only visible in the UI editor, not at runtime. -->
+ <TextView tools:text="@string/file_size"
+ android:id="@+id/GameListItemSubTitle"
+ android:layout_width="fill_parent"
+ android:layout_height="26dip"
+
+ android:textColor="#bbbbbb"
+
+ android:layout_toEndOf="@id/GameListItemIcon"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentEnd="true"
+
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ />
+
+ <!-- Properties in the 'tools' namespace are only visible in the UI editor, not at runtime. -->
+ <TextView tools:text="Name of Game"
+ android:id="@+id/GameListItemTitle"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+
+ android:fontFamily="sans-serif-light"
+ android:textSize="22sp"
+ android:textColor="#555555"
+
+ android:singleLine="true"
+ android:ellipsize="end"
+
+ android:layout_toEndOf="@id/GameListItemIcon"
+ android:layout_alignParentEnd="true"
+ android:layout_alignParentTop="true"
+ android:layout_above="@id/GameListItemSubTitle"
+ android:layout_alignWithParentIfMissing="true"
+
+ android:gravity="center_vertical"
+ />
+
+</RelativeLayout>
diff --git a/Source/Android/app/src/main/res/layout/gamelist_listview.xml b/Source/Android/app/src/main/res/layout/gamelist_listview.xml
new file mode 100644
index 0000000000..d52b319df6
--- /dev/null
+++ b/Source/Android/app/src/main/res/layout/gamelist_listview.xml
@@ -0,0 +1,8 @@
+<ListView xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:id="@+id/gamelist"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:choiceMode="singleChoice"
+ android:dividerHeight="1dp"
+ tools:listitem="@layout/gamelist_list_item"/> \ No newline at end of file
diff --git a/Source/Android/app/src/main/res/layout/sidemenu.xml b/Source/Android/app/src/main/res/layout/sidemenu.xml
new file mode 100644
index 0000000000..f844630928
--- /dev/null
+++ b/Source/Android/app/src/main/res/layout/sidemenu.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="wrap_content"
+ android:layout_height="48dp"
+ android:gravity="start"
+ android:orientation="vertical" >
+
+ <TextView
+ android:id="@+id/SideMenuTitle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_margin="4dp"
+ android:singleLine="true"
+ tools:text="Menu Option"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:fontFamily="sans-serif-light"
+ android:textColor="#FFFFFF" />
+
+</LinearLayout>
diff --git a/Source/Android/app/src/main/res/layout/slider_layout.xml b/Source/Android/app/src/main/res/layout/slider_layout.xml
new file mode 100644
index 0000000000..a667ff6489
--- /dev/null
+++ b/Source/Android/app/src/main/res/layout/slider_layout.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:weightSum="1"
+ android:gravity="center_horizontal">
+
+ <SeekBar
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:id="@+id/sliderSeekBar"
+ />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ tools:text="Sample Text"
+ android:id="@+id/sliderTextView"
+ android:textStyle="bold"/>
+
+</LinearLayout> \ No newline at end of file
diff --git a/Source/Android/app/src/main/res/layout/viewpager.xml b/Source/Android/app/src/main/res/layout/viewpager.xml
new file mode 100644
index 0000000000..b231974405
--- /dev/null
+++ b/Source/Android/app/src/main/res/layout/viewpager.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/pager"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <android.support.v4.view.PagerTabStrip
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="top"
+ android:paddingBottom="10dp"
+ android:paddingTop="10dp" />
+
+</android.support.v4.view.ViewPager>
+
diff --git a/Source/Android/app/src/main/res/menu/emuwindow_overlay.xml b/Source/Android/app/src/main/res/menu/emuwindow_overlay.xml
new file mode 100644
index 0000000000..7c103d831f
--- /dev/null
+++ b/Source/Android/app/src/main/res/menu/emuwindow_overlay.xml
@@ -0,0 +1,64 @@
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <!-- Enable/Disabe Input Overlay -->
+ <item
+ android:id="@+id/enableInputOverlay"
+ android:showAsAction="ifRoom"
+ android:title="@string/disable_input_overlay"/>
+
+ <!-- Save State Slots -->
+ <item
+ android:id="@+id/takeScreenshot"
+ android:showAsAction="ifRoom"
+ android:title="@string/overlay_screenshot"/>
+ <item
+ android:id="@+id/saveStateRoot"
+ android:showAsAction="never"
+ android:title="@string/overlay_savestate">
+ <menu>
+ <item android:id="@+id/saveSlot1"
+ android:title="@string/overlay_slot1"/>
+
+ <item android:id="@+id/saveSlot2"
+ android:title="@string/overlay_slot2"/>
+
+ <item android:id="@+id/saveSlot3"
+ android:title="@string/overlay_slot3"/>
+
+ <item android:id="@+id/saveSlot4"
+ android:title="@string/overlay_slot4"/>
+
+ <item android:id="@+id/saveSlot5"
+ android:title="@string/overlay_slot5"/>
+ </menu>
+ </item>
+
+ <!-- Load State Slots -->
+ <item
+ android:id="@+id/loadStateRoot"
+ android:showAsAction="never"
+ android:title="@string/overlay_loadstate">
+ <menu>
+ <item android:id="@+id/loadSlot1"
+ android:title="@string/overlay_slot1"/>
+
+ <item android:id="@+id/loadSlot2"
+ android:title="@string/overlay_slot2"/>
+
+ <item android:id="@+id/loadSlot3"
+ android:title="@string/overlay_slot3"/>
+
+ <item android:id="@+id/loadSlot4"
+ android:title="@string/overlay_slot4"/>
+
+ <item android:id="@+id/loadSlot5"
+ android:title="@string/overlay_slot5"/>
+ </menu>
+ </item>
+
+ <item
+ android:id="@+id/exitEmulation"
+ android:showAsAction="ifRoom"
+ android:title="@string/overlay_exit_emulation">
+ </item>
+</menu>
diff --git a/Source/Android/app/src/main/res/menu/gamelist_menu.xml b/Source/Android/app/src/main/res/menu/gamelist_menu.xml
new file mode 100644
index 0000000000..dbec1a65f3
--- /dev/null
+++ b/Source/Android/app/src/main/res/menu/gamelist_menu.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+ <item
+ android:id="@+id/clearGameList"
+ android:title="@string/clear_game_list"
+ android:showAsAction="ifRoom|withText" />
+</menu> \ No newline at end of file
diff --git a/Source/Android/app/src/main/res/values-ja/strings.xml b/Source/Android/app/src/main/res/values-ja/strings.xml
new file mode 100644
index 0000000000..59e72d1819
--- /dev/null
+++ b/Source/Android/app/src/main/res/values-ja/strings.xml
@@ -0,0 +1,210 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <!-- Title of the app -->
+ <string name="app_name">Dolphin Emulator</string>
+
+ <!-- Navigation-related Strings -->
+ <string name="drawer_open">ナビゲーションウィンドウを開く</string>
+ <string name="drawer_close">ナビゲーションウィンドウを閉じる</string>
+
+ <!-- About Fragment -->
+ <string name="build_revision">ビルドのバージョン</string>
+ <string name="supports_gles3">サポートのOpenGL ES 3</string>
+ <string name="supports_neon">サポートのNEON</string>
+ <string name="general">一般</string>
+ <string name="cpu">CPU</string>
+ <string name="gles_two">GLES 2</string>
+ <string name="gles_three">GLES 3</string>
+ <string name="desktop_gl">OpenGL</string>
+
+ <!-- About Menu - CPU Info -->
+ <string name="cpu_abi_one">CPU ABI 1</string>
+ <string name="cpu_abi_two">CPU ABI 2</string>
+ <string name="cpu_info">CPU情報</string>
+ <string name="cpu_type">CPUタイプ</string>
+ <string name="cpu_features">CPUの命令セットと機能</string>
+ <string name="num_cores">CPUコア</string>
+ <string name="cpu_implementer">CPUの実装</string>
+ <string name="cpu_hardware">ハードウェア</string>
+ <string name="unknown_part_num">不明 (%1$d)。 我々はそれを文書化することができますので、この番号を報告してください。 </string>
+
+ <!-- Folder Browser -->
+ <string name="current_dir">現在のディレクトリ: %1$s</string>
+ <string name="parent_directory">親ディレクトリ</string>
+ <string name="file_size">ファイルサイズ: %1$s</string>
+
+ <!-- Game List Activity -->
+ <string name="clear_game_list">クリア</string>
+ <string name="clear_game_list_confirm">ゲームリストからすべての項目を削除しますか?</string>
+ <string name="game_list">ゲームリスト</string>
+ <string name="browse_folder">フォルダの参照</string>
+ <string name="settings">設定</string>
+ <string name="about">について</string>
+ <string name="file_size_gib">ファイルサイズ: %.2f GiB</string>
+ <string name="file_size_mib">ファイルサイズ: %.2f MiB</string>
+
+ <!-- Game List Activity - Device Compatibility AlertDialog -->
+ <string name="device_compat_warning">デバイスの互換性の警告</string>
+ <string name="device_compat_warning_msg">この電話は、NEON拡張をサポートしていません。 おそらくDolphinを実行することはできません。\nあなたはとにかくそれを実行してみますか?</string>
+ <string name="device_gles3compat_warning_msg">デバイスはOpenGLES3のビデオドライバのバグがあります。\nあなたはとにかくそれを使用してみたいのですか?</string>
+
+ <!-- Game List Fragment -->
+ <string name="file_clicked">クリックされたファイル: %1$s</string>
+
+ <!-- Emulation Window Overlay -->
+ <string name="enable_input_overlay">入力オーバーレイを有効</string>
+ <string name="disable_input_overlay">入力オーバーレイを無効</string>
+ <string name="overlay_screenshot">スクリーンショットを撮る</string>
+ <string name="overlay_savestate">ステートセーブ</string>
+ <string name="overlay_loadstate">ステートロード</string>
+ <string name="overlay_exit_emulation">終了</string>
+ <string name="overlay_exit_emulation_confirm">このゲームを終了してもよろしいですか?</string>
+ <string name="overlay_slot1">スロット 1</string>
+ <string name="overlay_slot2">スロット 2</string>
+ <string name="overlay_slot3">スロット 3</string>
+ <string name="overlay_slot4">スロット 4</string>
+ <string name="overlay_slot5">スロット 5</string>
+
+ <!-- Input Config Fragment -->
+ <string name="input_settings">入力</string>
+ <string name="input_overlay">入力オーバーレイ</string>
+ <string name="input_overlay_desc">画面上の入力のオーバーレイを設定し。</string>
+ <string name="input_overlay_layout">入力オーバーレイレイアウト</string>
+ <string name="input_overlay_layout_desc">入力オーバーレイのためのボタンのレイアウト。</string>
+ <string name="controls_size">コントロールのサイズを調整し</string>
+ <string name="gamecube_bindings">ゲームキューブコントローラの入力バインディング</string>
+ <string name="controller_0">コントローラ1</string>
+ <string name="controller_1">コントローラ2</string>
+ <string name="controller_2">コントローラ3</string>
+ <string name="controller_3">コントローラ4</string>
+ <string name="enable_controller">コントローラを有効</string>
+ <string name="wiimote_bindings">Wiiリモコンの入力バインディング</string>
+ <string name="wiimote_1">Wiiリモコン1</string>
+ <string name="wiimote_2">Wiiリモコン2</string>
+ <string name="wiimote_3">Wiiリモコン3</string>
+ <string name="wiimote_4">Wiiリモコン4</string>
+ <string name="enable_wiimote">Wiiリモコンを有効</string>
+ <string name="input_binding">入力バインディング</string>
+ <string name="input_binding_descrip">%1$sにバインドするための入力を移動または押してください。</string>
+ <!-- GameCube buttons (May be shared with Wiimote stuff too) -->
+ <string name="button_a">Aボタン</string>
+ <string name="button_b">Bボタン</string>
+ <string name="button_start">スタートボタン</string>
+ <string name="button_x">Xボタン</string>
+ <string name="button_y">Yボタン</string>
+ <string name="button_z">Zボタン</string>
+ <string name="dpad_up">D-Pad: ↑</string>
+ <string name="dpad_down">D-Pad: ↓</string>
+ <string name="dpad_left">D-Pad: ←</string>
+ <string name="dpad_right">D-Pad: →</string>
+ <string name="main_stick_up">コントロールスティック: ↑</string>
+ <string name="main_stick_down">コントロールスティック: ↓</string>
+ <string name="main_stick_left">コントロールスティック: ←</string>
+ <string name="main_stick_right">コントロールスティック: →</string>
+ <string name="c_stick_up">C-スティック: ↑</string>
+ <string name="c_stick_down">C-スティック: ↓</string>
+ <string name="c_stick_left">C-スティック: ←</string>
+ <string name="c_stick_right">C-スティック: →</string>
+ <string name="trigger_left">左のトリガー</string>
+ <string name="trigger_right">右のトリガー</string>
+ <!-- Wiimote (+ extension) only buttons -->
+ <string name="button_one">ボタン1</string>
+ <string name="button_two">ボタン2</string>
+ <string name="button_plus">ボタン+</string>
+ <string name="button_minus">ボタン-</string>
+ <string name="button_home">ホームボタン</string>
+ <string name="ir_up">IR ↑</string>
+ <string name="ir_down">IR ↓</string>
+ <string name="ir_left">IR ←</string>
+ <string name="ir_right">IR →</string>
+ <string name="ir_forward">IR前方</string>
+ <string name="ir_backward">IR後方</string>
+ <string name="swing_up">スイング ↑</string>
+ <string name="swing_down">スイング ↓</string>
+ <string name="swing_left">スイング ←</string>
+ <string name="swing_right">スイング →</string>
+ <string name="tilt_forward">前方を傾</string>
+ <string name="tilt_backward">後方を傾</string>
+ <string name="tilt_left">左を傾</string>
+ <string name="tilt_right">右を傾</string>
+ <string name="shake_x">Xを振る</string>
+ <string name="shake_y">Yを振る</string>
+ <string name="shake_z">Zを振る</string>
+
+ <!-- CPU Preference Fragment -->
+ <string name="interpreter">Interpreter</string>
+ <string name="jit64_recompiler">JIT64 Recompiler</string>
+ <string name="jitil_recompiler">JITIL Recompiler</string>
+ <string name="jit_arm_recompiler">JIT ARM Recompiler</string>
+ <string name="jit_arm64_recompiler">JIT ARM64 Recompiler</string>
+ <string name="cpu_settings">CPU</string>
+ <string name="cpu_core">CPUコア</string>
+ <string name="cpu_core_desc">%s</string>
+ <string name="dual_core">デュアルコア</string>
+ <string name="dual_core_descrip">処理のための2つのCPUコアを使用して。速度が向上します。</string>
+ <string name="fastmem">Fastmem</string>
+ <string name="fastmem_desc">メモリアクセスのために潜在的に危険な最適化を使用して。</string>
+
+ <!-- Video Preference Fragment -->
+ <string name="video_settings">ビデオ</string>
+ <string name="software_renderer">Software Renderer</string>
+ <string name="opengl_es3">OpenGL ES</string>
+ <string name="opengl">OpenGL</string>
+ <string name="video_backend">ビデオレンダラ</string>
+ <string name="video_backend_desc">%s</string>
+ <string name="show_fps">FPSを表示</string>
+ <string name="show_fps_descrip">エミュレーション速度の指標として、画面左上に毎秒レンダリングされた フレーム数を表示します。</string>
+
+ <string name="enhancements">画質向上の設定</string>
+ <string name="internal_resolution">内部解像度の変更</string>
+ <string name="internal_resolution_descrip">内部解像度の計算方式を設定します。高解像度に設定することで大きく 画質が向上します。 しかし、ゲームによっては非常に重くなったり描画バグの原因となります。 【ゲーム解像度の倍数】は【ウィンドウサイズに拡大】より少し重くなり ますが、描画バグは発生しにくくなります。 また一般的に内部解像度が低いほど、動作速度は向上します。</string>
+ <string name="FSAA">フルシーンアンチエイリアシング</string>
+ <string name="FSAA_descrip">3Dグラフィックスをラスタライズによって生じるエイリアシングの量が減少。 レンダリングされた画像はあまりギザギザになります。 抽選でエミュレーション速度を下げます。問題を引き起こす可能性があります。</string>
+ <string name="anisotropic_filtering">異方性フィルタリング</string>
+ <string name="anisotropic_filtering_descrip">異方性フィルタリングを適用します。 奥行きのあるテクスチャをより精細に描画することが出来ます。 特定のゲームでは描画バグの原因になることがあります。</string>
+ <string name="postprocessing_shader">ポストプロセッシングシェーダー</string>
+ <string name="postprocessing_shader_descrip">フレーム終了後の後処理効果を適用する。</string>
+ <string name="scaled_efb_copy">Scaled EFB Copy</string>
+ <string name="scaled_efb_copy_descrip">テクスチャエフェクトを表示するために作成されたテクスチャの品質を著しく向上させます。 特に高解像度出力時に効果が大きく出ます。 動作速度は少々低下し、まれに描画バグの原因にもなることもあります。</string>
+ <string name="per_pixel_lighting">Per-Pixel Lighting</string>
+ <string name="per_pixel_lighting_descrip">ピクセル単位での光源処理を行います。 GPUの性能にもよりますが、数パーセント程度、動作速度が低下します。 このオプションは通常安全ですが、時に描画バグを引き起こすこともあります</string>
+ <string name="force_texture_filtering">Force Texture Filtering</string>
+ <string name="force_texture_filtering_descrip">ゲーム側でフィルタ無効を明示している場面でも、強制的にフィルタリングを行います。 特に高解像度出力時にテクスチャが綺麗になりますが、いくつかのゲームで描画バグを引き起こします。</string>
+ <string name="disable_fog">霧を無効</string>
+ <string name="disable_fog_descrip">フォグ処理を無効化します。これにより遠景の高精細化が期待できます。いくつかのタイトルではフォグ処理に頼った画面効果が正しく表示 されなくなります。</string>
+
+ <string name="hacks">高速化(Hacks)</string>
+ <string name="embedded_frame_buffer">内蔵フレームバッファ</string>
+ <string name="skip_efb_access">CPUからEFBアクセスをスキップ</string>
+ <string name="skip_efb_access_descrip">EFBへの読み取り/書き込みにCPUから作られたすべての要求を無視。</string>
+ <string name="ignore_format_changes">フォーマットの変更を無視</string>
+ <string name="ignore_format_changes_descrip">EFB形式への変更を無視。</string>
+ <string name="efb_copy_method">EFBコピー方法</string>
+ <string name="efb_copy_method_descrip">EFBコピーをエミュレート方法を決定。</string>
+ <string name="efb_copy_texture">テクスチャ</string>
+ <string name="efb_copy_ram_uncached">RAM (キャッシュない)</string>
+ <string name="efb_copy_ram_cached">RAM (キャッシュ)</string>
+ <string name="texture_cache">テクスチャキャッシュ</string>
+ <string name="texture_cache_accuracy">テクスチャキャッシュ確度</string>
+ <string name="texture_cache_accuracy_descrip">この選択をSafe設定しておくと、RAMからのテクスチャ更新に 失敗しにくなります。</string>
+ <string name="texture_cache_accuracy_low">低</string>
+ <string name="texture_cache_accuracy_medium">平</string>
+ <string name="texture_cache_accuracy_high">高</string>
+ <string name="external_frame_buffer">外部フレームバッファ</string>
+ <string name="external_frame_buffer_descrip">XFBをエミュレート方法を決定。</string>
+ <string name="external_frame_buffer_virtual">バーチャル</string>
+ <string name="external_frame_buffer_real">実機</string>
+ <string name="disable_destination_alpha">Disable Destination Alpha</string>
+ <string name="disable_destination_alpha_descrip">多くのタイトルで画面効果に使用されている、アルファ透過処理をスキップ 。</string>
+ <string name="fast_depth_calculation">高速奥行き計算</string>
+ <string name="fast_depth_calculation_descrip">深度値を計算するために精度の低いアルゴリズムを使用します。</string>
+
+ <!-- Miscellaneous -->
+ <string name="yes">はい</string>
+ <string name="no">いいえ</string>
+ <string name="cancel">キャンセル</string>
+ <string name="disabled">無効</string>
+ <string name="other">その他</string>
+
+</resources>
diff --git a/Source/Android/app/src/main/res/values/arrays.xml b/Source/Android/app/src/main/res/values/arrays.xml
new file mode 100644
index 0000000000..0ea284c71e
--- /dev/null
+++ b/Source/Android/app/src/main/res/values/arrays.xml
@@ -0,0 +1,186 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- All lists for ListPreference keys/values are placed here -->
+<resources>
+
+ <!-- CPU core selection - X86_64 -->
+ <string-array name="emuCoreEntriesX86_64" translatable="false">
+ <item>@string/interpreter</item>
+ <item>@string/jit64_recompiler</item>
+ <item>@string/jitil_recompiler</item>
+ </string-array>
+ <string-array name="emuCoreValuesX86_64" translatable="false">
+ <item>0</item>
+ <item>1</item>
+ <item>2</item>
+ </string-array>
+
+ <!-- CPU core selection - ARM -->
+ <string-array name="emuCoreEntriesARM" translatable="false">
+ <item>@string/interpreter</item>
+ <item>@string/jit_arm_recompiler</item>
+ </string-array>
+ <string-array name="emuCoreValuesARM" translatable="false">
+ <item>0</item>
+ <item>3</item>
+ </string-array>
+
+ <!-- CPU core selection - ARM64 -->
+ <string-array name="emuCoreEntriesARM64" translatable="false">
+ <item>@string/interpreter</item>
+ <item>@string/jit_arm64_recompiler</item>
+ </string-array>
+ <string-array name="emuCoreValuesARM64" translatable="false">
+ <item>0</item>
+ <item>4</item>
+ </string-array>
+
+ <!-- CPU core selection - Other -->
+ <string-array name="emuCoreEntriesOther" translatable="false">
+ <item>@string/interpreter</item>
+ </string-array>
+ <string-array name="emuCoreValuesOther" translatable="false">
+ <item>0</item>
+ </string-array>
+
+
+ <!-- Video Backend Selection - Supports OpenGL ES 3 -->
+ <string-array name="videoBackendEntriesGLES3" translatable="false">
+ <item>@string/software_renderer</item>
+ <item>@string/opengl_es3</item>
+ </string-array>
+ <string-array name="videoBackendValuesGLES3" translatable="false">
+ <item>Software Renderer</item>
+ <item>OGL</item>
+ </string-array>
+
+ <!-- Video Backend Selection - Supports desktop OpenGL -->
+ <string-array name="videoBackendEntriesGL" translatable="false">
+ <item>@string/software_renderer</item>
+ <item>@string/opengl</item>
+ </string-array>
+ <string-array name="videoBackendValuesGL" translatable="false">
+ <item>Software Renderer</item>
+ <item>OGL</item>
+ </string-array>
+
+ <!-- Video Backend Selection - No OpenGL ES 3 support -->
+ <string-array name="videoBackendEntriesNoGLES3" translatable="false">
+ <item>@string/software_renderer</item>
+ </string-array>
+ <string-array name="videoBackendValuesNoGLES3" translatable="false">
+ <item>Software Renderer</item>
+ </string-array>
+
+ <!-- EFB Copy Method Preference -->
+ <string-array name="efbCopyMethodEntries" translatable="false">
+ <item>@string/disabled</item>
+ <item>@string/efb_copy_texture</item>
+ <item>@string/efb_copy_ram_uncached</item>
+ <item>@string/efb_copy_ram_cached</item>
+ </string-array>
+ <string-array name="efbCopyMethodValues" translatable="false">
+ <item>Off</item>
+ <item>Texture</item>
+ <item>RAM (cached)</item>
+ <item>RAM (uncached)</item>
+ </string-array>
+
+ <!-- Texture Cache Accuracy Preference -->
+ <string-array name="textureCacheAccuracyEntries" translatable="false">
+ <item>@string/texture_cache_accuracy_low</item>
+ <item>@string/texture_cache_accuracy_medium</item>
+ <item>@string/texture_cache_accuracy_high</item>
+ </string-array>
+ <string-array name="textureCacheAccuracyValues" translatable="false">
+ <item>128</item>
+ <item>512</item>
+ <item>0</item>
+ </string-array>
+
+ <!-- External Frame Buffer Preference -->
+ <string-array name="externalFrameBufferEntries" translatable="false">
+ <item>@string/disabled</item>
+ <item>@string/external_frame_buffer_virtual</item>
+ <item>@string/external_frame_buffer_real</item>
+ </string-array>
+ <string-array name="externalFrameBufferValues" translatable="false">
+ <item>Disabled</item>
+ <item>Virtual</item>
+ <item>Real</item>
+ </string-array>
+
+ <!-- Internal Resolution Preference -->
+ <string-array name="internalResolutionEntries" translatable="false">
+ <item>1x Native (640x528)</item>
+ <item>1.5x Native (960x792)</item>
+ <item>2x Native (1280x1056)</item>
+ <item>2.5x Native (1600x1320)</item>
+ <item>3x Native (1920x1584)</item>
+ <item>4x Native (2560x2112)</item>
+ </string-array>
+ <string-array name="internalResolutionValues" translatable="false">
+ <item>2</item>
+ <item>3</item>
+ <item>4</item>
+ <item>5</item>
+ <item>6</item>
+ <item>7</item>
+ </string-array>
+
+ <!-- FSAA Preference -->
+ <string-array name="FSAAEntries" translatable="false">
+ <item>1x</item>
+ <item>2x</item>
+ <item>4x</item>
+ </string-array>
+ <string-array name="FSAAValues" translatable="false">
+ <item>0</item>
+ <item>1</item>
+ <item>2</item>
+ </string-array>
+
+ <!-- Anisotropic Filtering Preference -->
+ <string-array name="anisotropicFilteringEntries" translatable="false">
+ <item>1x</item>
+ <item>2x</item>
+ <item>4x</item>
+ <item>8x</item>
+ <item>16x</item>
+ </string-array>
+ <string-array name="anisotropicFilteringValues" translatable="false">
+ <item>0</item>
+ <item>1</item>
+ <item>2</item>
+ <item>3</item>
+ <item>4</item>
+ </string-array>
+
+ <!-- Stereoscopy Preference -->
+ <string-array name="stereoscopyEntries" translatable="false">
+ <item>Off</item>
+ <item>Side-by-Side</item>
+ <item>Top-and-Bottom</item>
+ <item>Anaglyph</item>
+ </string-array>
+ <string-array name="stereoscopyValues" translatable="false">
+ <item>0</item>
+ <item>1</item>
+ <item>2</item>
+ <item>3</item>
+ </string-array>
+
+ <!-- Aspect Ratio Preference -->
+ <string-array name="aspectRatioEntries" translatable="false">
+ <item>Auto</item>
+ <item>Force 16:9</item>
+ <item>Force 4:3</item>
+ <item>Stretch To Window</item>
+ </string-array>
+ <string-array name="aspectRatioValues" translatable="false">
+ <item>0</item>
+ <item>1</item>
+ <item>2</item>
+ <item>3</item>
+ </string-array>
+</resources>
diff --git a/Source/Android/app/src/main/res/values/strings.xml b/Source/Android/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000000..f321d08df2
--- /dev/null
+++ b/Source/Android/app/src/main/res/values/strings.xml
@@ -0,0 +1,223 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <!-- Title of the app -->
+ <string name="app_name">Dolphin Emulator</string>
+
+ <!-- Navigation-related Strings -->
+ <string name="drawer_open">Open navigation drawer</string>
+ <string name="drawer_close">Close navigation drawer</string>
+
+ <!-- About Fragment -->
+ <string name="build_revision">Build Revision</string>
+ <string name="supports_gles3">Supports OpenGL ES 3</string>
+ <string name="supports_neon">Supports NEON</string>
+ <string name="general">General</string>
+ <string name="cpu">CPU</string>
+ <string name="gles_two">GLES 2</string>
+ <string name="gles_three">GLES 3</string>
+ <string name="desktop_gl">OpenGL</string>
+
+ <!-- About Menu - CPU Info -->
+ <string name="cpu_abi_one">CPU ABI 1</string>
+ <string name="cpu_abi_two">CPU ABI 2</string>
+ <string name="cpu_info">CPU Info</string>
+ <string name="cpu_type">CPU Type</string>
+ <string name="cpu_features">CPU Features</string>
+ <string name="num_cores">Number of Cores</string>
+ <string name="cpu_implementer">CPU Implementer</string>
+ <string name="cpu_hardware">Hardware</string>
+ <string name="unknown_part_num">Unknown (%1$d). Please report this number so it can be documented!</string>
+
+ <!-- Folder Browser -->
+ <string name="current_dir">Current Dir: %1$s</string>
+ <string name="parent_directory">Parent Directory</string>
+ <string name="file_size">File Size: %1$s</string>
+
+
+ <!-- Game List Activity -->
+ <string name="clear_game_list">Clear game list</string>
+ <string name="clear_game_list_confirm">Do you want to clear the game list?</string>
+ <string name="game_list">Game List</string>
+ <string name="browse_folder">Browse Folder</string>
+ <string name="settings">Settings</string>
+ <string name="about">About</string>
+ <string name="file_size_gib">File Size: %.2f GiB</string>
+ <string name="file_size_mib">File Size: %.2f MiB</string>
+
+ <!-- Game List Activity - Device Compatibility AlertDialog -->
+ <string name="device_compat_warning">Device Compatibility Warning</string>
+ <string name="device_compat_warning_msg">Your phone doesn\'t support NEON which makes it incapable of running Dolphin Mobile?\nDo you want to try anyway?</string>
+ <string name="device_gles3compat_warning_msg">Your device has known buggy video drivers for OpenGL ES 3.\nDo you want to try anyway?</string>
+
+ <!-- Game List Fragment -->
+ <string name="file_clicked">File clicked: %1$s</string>
+
+ <!-- Emulation Overlay -->
+ <string name="enable_input_overlay">Enable Input Overlay</string>
+ <string name="disable_input_overlay">Disable Input Overlay</string>
+ <string name="overlay_screenshot">Take Screenshot</string>
+ <string name="overlay_savestate">Save State</string>
+ <string name="overlay_loadstate">Load State</string>
+ <string name="overlay_exit_emulation">Exit</string>
+ <string name="overlay_exit_emulation_confirm">Are you sure you wish to exit this game?</string>
+ <string name="overlay_slot1">Slot 1</string>
+ <string name="overlay_slot2">Slot 2</string>
+ <string name="overlay_slot3">Slot 3</string>
+ <string name="overlay_slot4">Slot 4</string>
+ <string name="overlay_slot5">Slot 5</string>
+
+ <!-- Input Config Fragment -->
+ <string name="input_settings">Input</string>
+ <string name="input_overlay">Input Overlay</string>
+ <string name="input_overlay_desc">Configure the onscreen input overlay.</string>
+ <string name="input_overlay_layout">Input Overlay Layout</string>
+ <string name="input_overlay_layout_desc">Button layout for the input overlay.</string>
+ <string name="controls_size">Adjust the control size</string>
+ <string name="gamecube_bindings">GameCube Controller Bindings</string>
+ <string name="controller_0">Controller 1</string>
+ <string name="controller_1">Controller 2</string>
+ <string name="controller_2">Controller 3</string>
+ <string name="controller_3">Controller 4</string>
+ <string name="enable_controller">Enable controller</string>
+ <string name="wiimote_bindings">Wiimote Bindings</string>
+ <string name="wiimote_1">Wiimote 1</string>
+ <string name="wiimote_2">Wiimote 2</string>
+ <string name="wiimote_3">Wiimote 3</string>
+ <string name="wiimote_4">Wiimote 4</string>
+ <string name="enable_wiimote">Enable Wiimote</string>
+ <string name="input_binding">Input Binding</string>
+ <string name="input_binding_descrip">Press or move an input to bind it to %1$s.</string>
+ <!-- GameCube buttons (May be shared with Wiimote stuff too) -->
+ <string name="button_a">Button A</string>
+ <string name="button_b">Button B</string>
+ <string name="button_start">Button Start</string>
+ <string name="button_x">Button X</string>
+ <string name="button_y">Button Y</string>
+ <string name="button_z">Button Z</string>
+ <string name="dpad_up">D-Pad Up</string>
+ <string name="dpad_down">D-Pad Down</string>
+ <string name="dpad_left">D-Pad Left</string>
+ <string name="dpad_right">D-Pad Right</string>
+ <string name="main_stick_up">Main Stick Up</string>
+ <string name="main_stick_down">Main Stick Down</string>
+ <string name="main_stick_left">Main Stick Left</string>
+ <string name="main_stick_right">Main Stick Right</string>
+ <string name="c_stick_up">C Stick Up</string>
+ <string name="c_stick_down">C Stick Down</string>
+ <string name="c_stick_left">C Stick Left</string>
+ <string name="c_stick_right">C Stick Right</string>
+ <string name="trigger_left">Trigger L</string>
+ <string name="trigger_right">Trigger R</string>
+ <!-- Wiimote (+ extension) only buttons -->
+ <string name="button_one">Button 1</string>
+ <string name="button_two">Button 2</string>
+ <string name="button_plus">Button +</string>
+ <string name="button_minus">Button -</string>
+ <string name="button_home">Button Home</string>
+ <string name="ir_up">IR Up</string>
+ <string name="ir_down">IR Down</string>
+ <string name="ir_left">IR Left</string>
+ <string name="ir_right">IR Right</string>
+ <string name="ir_forward">IR Forward</string>
+ <string name="ir_backward">IR Backward</string>
+ <string name="swing_up">Swing Up</string>
+ <string name="swing_down">Swing Down</string>
+ <string name="swing_left">Swing Left</string>
+ <string name="swing_right">Swing Right</string>
+ <string name="tilt_forward">Tilt Forward</string>
+ <string name="tilt_backward">Tilt Backward</string>
+ <string name="tilt_left">Tilt Left</string>
+ <string name="tilt_right">Tilt Right</string>
+ <string name="shake_x">Shake X</string>
+ <string name="shake_y">Shake Y</string>
+ <string name="shake_z">Shake Z</string>
+
+ <!-- CPU Preference Fragment -->
+ <string name="interpreter">Interpreter</string>
+ <string name="jit64_recompiler">JIT64 Recompiler</string>
+ <string name="jitil_recompiler">JITIL Recompiler</string>
+ <string name="jit_arm_recompiler">JIT ARM Recompiler</string>
+ <string name="jit_arm64_recompiler">JIT ARM64 Recompiler</string>
+ <string name="cpu_settings">CPU</string>
+ <string name="cpu_core">CPU Core</string>
+ <string name="cpu_core_desc">%s</string>
+ <string name="dual_core">Dual Core</string>
+ <string name="dual_core_descrip">Split workload to two CPU cores instead of one. Increases speed.</string>
+ <string name="fastmem">Fastmem</string>
+ <string name="fastmem_desc">Uses potentially unsafe optimizations for memory access.</string>
+
+ <!-- Video Preference Fragment -->
+ <string name="video_settings">Video</string>
+ <string name="software_renderer">Software Renderer</string>
+ <string name="opengl_es3">OpenGL ES</string>
+ <string name="opengl">OpenGL</string>
+ <string name="video_backend">Video Backend</string>
+ <string name="video_backend_desc">%s</string>
+ <string name="show_fps">Show FPS</string>
+ <string name="show_fps_descrip">Show the number of frames rendered per second as a measure of emulation speed.</string>
+
+ <string name="enhancements">Enhancements</string>
+ <string name="internal_resolution">Internal Resolution</string>
+ <string name="internal_resolution_descrip">Specifies the resolution used to render at. A high resolution will improve visual quality a lot but is also quite heavy on performance and might cause glitches in certain games.</string>
+ <string name="FSAA">Full-scene Anti-aliasing</string>
+ <string name="FSAA_descrip">Reduces the amount of aliasing caused by rasterizing 3D graphics. This makes the rendered picture look less blocky. Heavily decreases emulation speed and sometimes causes issues.</string>
+ <string name="anisotropic_filtering">Anisotropic Filtering</string>
+ <string name="anisotropic_filtering_descrip">Enhances visual quality of textures that are at oblique viewing angles. Might cause issues in a small number of games.</string>
+ <string name="postprocessing_shader">Post Processing Shader</string>
+ <string name="postprocessing_shader_descrip">Apply a post-processing effect after finishing a frame.</string>
+ <string name="scaled_efb_copy">Scaled EFB Copy</string>
+ <string name="scaled_efb_copy_descrip">Greatly increases quality of textures generated using render to texture effects. Raising the internal resolution will improve the effect of this setting. Slightly decreases performance and possibly causes issues (although unlikely).</string>
+ <string name="per_pixel_lighting">Per-Pixel Lighting</string>
+ <string name="per_pixel_lighting_descrip">Calculate lighting of 3D graphics per-pixel rather than per vertex. Decreases emulation speed by some percent (depending on your GPU). This usually is a safe enhancement, but might cause issues sometimes.</string>
+ <string name="force_texture_filtering">Force Texture Filtering</string>
+ <string name="force_texture_filtering_descrip">Force texture filtering even if the emulated game explicitly disabled it. Improves texture quality slightly but causes glitches in some games.</string>
+ <string name="disable_fog">Disable Fog</string>
+ <string name="disable_fog_descrip">Makes distant objects more visible by removing fog, thus increasing the overall detail. Disabling fog will break some games which rely on proper fog emulation.</string>
+ <string name="stereoscopy">Stereoscopy</string>
+ <string name="stereoscopy_descrip">Stereoscopy allows you to get a better feeling of depth if you have the necessary hardware.\nHeavily decreases emulation speed and sometimes causes issues</string>
+ <string name="stereoscopy_mode">Stereoscopy Mode</string>
+ <string name="stereoscopy_mode_descrip">Select the stereoscopic 3D mode.</string>
+ <string name="sterescopy_depth">Depth</string>
+ <string name="sterescopy_depth_descrip">Control the distance between the virtual cameras.\nA higher value creates a stronger feeling of depth while a lower value is more comfortable.</string>
+ <string name="convergence">Convergence</string>
+ <string name="convergence_descrip">Control the distance of the convergence plane, this is the distance at which objects will appear to be in front of the screen.\nA higher value creates stronger out-of-screen effects while a lower value is more comfortable.</string>
+ <string name="swap_eyes">Swap Eyes</string>
+ <string name="swap_eyes_descrip">Swap the left and right eye, mostly useful if you want to view side-by-side cross-eyed.</string>
+
+ <string name="hacks">Hacks</string>
+ <string name="embedded_frame_buffer">Embedded Frame Buffer</string>
+ <string name="skip_efb_access">Skip EFB Access from CPU</string>
+ <string name="skip_efb_access_descrip">Ignore any requests from the CPU to read/write to the EFB.</string>
+ <string name="ignore_format_changes">Ignore Format Changes</string>
+ <string name="ignore_format_changes_descrip">Ignore any changes to the EFB format.</string>
+ <string name="efb_copy_method">EFB Copy Method</string>
+ <string name="efb_copy_method_descrip">Determines how EFB copies will be emulated.</string>
+ <string name="efb_copy_texture">Texture</string>
+ <string name="efb_copy_ram_uncached">RAM (uncached)</string>
+ <string name="efb_copy_ram_cached">RAM (cached)</string>
+ <string name="texture_cache">Texture Cache</string>
+ <string name="texture_cache_accuracy">Texture Cache Accuracy</string>
+ <string name="texture_cache_accuracy_descrip">The safer the selection, the less likely the emulator will be missing any texture updates from RAM.</string>
+ <string name="texture_cache_accuracy_low">Low</string>
+ <string name="texture_cache_accuracy_medium">Medium</string>
+ <string name="texture_cache_accuracy_high">High</string>
+ <string name="external_frame_buffer">External Frame Buffer</string>
+ <string name="external_frame_buffer_descrip">Determines how the XFB will be emulated.</string>
+ <string name="external_frame_buffer_virtual">Virtual</string>
+ <string name="external_frame_buffer_real">Real</string>
+ <string name="disable_destination_alpha">Disable Destination Alpha</string>
+ <string name="disable_destination_alpha_descrip">Disables emulation of a hardware feature called destination alpha, which is used in many games for various effects.</string>
+ <string name="fast_depth_calculation">Fast Depth Calculation</string>
+ <string name="fast_depth_calculation_descrip">Uses a less accurate algorithm to calculate depth values.</string>
+ <string name="aspect_ratio">Aspect Ratio</string>
+ <string name="aspect_ratio_descrip">Select what aspect ratio to use when rendering</string>
+
+ <!-- Miscellaneous -->
+ <string name="yes">Yes</string>
+ <string name="no">No</string>
+ <string name="cancel">Cancel</string>
+ <string name="disabled">Disabled</string>
+ <string name="other">Other</string>
+
+</resources>
diff --git a/Source/Android/app/src/main/res/xml/cpu_prefs.xml b/Source/Android/app/src/main/res/xml/cpu_prefs.xml
new file mode 100644
index 0000000000..59ef76ed46
--- /dev/null
+++ b/Source/Android/app/src/main/res/xml/cpu_prefs.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
+ <!-- CPU Settings -->
+ <CheckBoxPreference
+ android:defaultValue="false"
+ android:key="dualCorePref"
+ android:summary="@string/dual_core_descrip"
+ android:title="@string/dual_core" />
+
+ <org.dolphinemu.dolphinemu.settings.custom.UpdatingListPreference
+ android:key="cpuCorePref"
+ android:summary="@string/cpu_core_desc"
+ android:title="@string/cpu_core" />
+
+ <CheckBoxPreference
+ android:defaultValue="false"
+ android:key="fastmemPref"
+ android:summary="@string/fastmem_desc"
+ android:title="@string/fastmem" />
+
+</PreferenceScreen> \ No newline at end of file
diff --git a/Source/Android/app/src/main/res/xml/input_prefs.xml b/Source/Android/app/src/main/res/xml/input_prefs.xml
new file mode 100644
index 0000000000..f6d8842f89
--- /dev/null
+++ b/Source/Android/app/src/main/res/xml/input_prefs.xml
@@ -0,0 +1,1057 @@
+<?xml version="1.0" encoding="utf-8"?>
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+ android:title="@string/input_settings">
+ <PreferenceScreen
+ android:key="input_overlay"
+ android:title="@string/input_overlay"
+ android:summary="@string/input_overlay_desc">
+ <Preference
+ android:key="inputOverlayConfigPref"
+ android:summary="@string/input_overlay_layout_desc"
+ android:title="@string/input_overlay_layout">
+ <intent
+ android:targetPackage="org.dolphinemu.dolphinemu"
+ android:targetClass="org.dolphinemu.dolphinemu.settings.input.overlayconfig.OverlayConfigActivity"/>
+ </Preference>
+ <SeekBarPreference
+ android:key="controls_size"
+ android:title="@string/controls_size"
+ android:defaultValue="25"
+ android:max="75">
+ </SeekBarPreference>
+ </PreferenceScreen>
+
+ <!-- GameCube controller bindings -->
+ <PreferenceScreen
+ android:key="gamecube_bindings"
+ android:title="@string/gamecube_bindings">
+ <PreferenceScreen
+ android:key="gamecube_bindings_control_0"
+ android:title="@string/controller_0">
+ <CheckBoxPreference
+ android:key="enableController1"
+ android:title="@string/enable_controller"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController1"
+ android:key="InputA_0"
+ android:title="@string/button_a" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController1"
+ android:key="InputB_0"
+ android:title="@string/button_b" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController1"
+ android:key="InputX_0"
+ android:title="@string/button_x" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController1"
+ android:key="InputY_0"
+ android:title="@string/button_y" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController1"
+ android:key="InputZ_0"
+ android:title="@string/button_z" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController1"
+ android:key="InputStart_0"
+ android:title="@string/button_start" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController1"
+ android:key="DPadUp_0"
+ android:title="@string/dpad_up" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController1"
+ android:key="DPadDown_0"
+ android:title="@string/dpad_down" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController1"
+ android:key="DPadLeft_0"
+ android:title="@string/dpad_left" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController1"
+ android:key="DPadRight_0"
+ android:title="@string/dpad_right" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController1"
+ android:key="MainUp_0"
+ android:title="@string/main_stick_up" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController1"
+ android:key="MainDown_0"
+ android:title="@string/main_stick_down" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController1"
+ android:key="MainLeft_0"
+ android:title="@string/main_stick_left" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController1"
+ android:key="MainRight_0"
+ android:title="@string/main_stick_right" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController1"
+ android:key="CStickUp_0"
+ android:title="@string/c_stick_up" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController1"
+ android:key="CStickDown_0"
+ android:title="@string/c_stick_down" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController1"
+ android:key="CStickLeft_0"
+ android:title="@string/c_stick_left" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController1"
+ android:key="CStickRight_0"
+ android:title="@string/c_stick_right" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController1"
+ android:key="InputL_0"
+ android:title="@string/trigger_left" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController1"
+ android:key="InputR_0"
+ android:title="@string/trigger_right" />
+ </PreferenceScreen>
+ <PreferenceScreen
+ android:key="gamecube_bindings_control_1"
+ android:title="@string/controller_1">
+ <CheckBoxPreference
+ android:key="enableController2"
+ android:title="@string/enable_controller"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController2"
+ android:key="InputA_1"
+ android:title="@string/button_a" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController2"
+ android:key="InputB_1"
+ android:title="@string/button_b" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController2"
+ android:key="InputX_1"
+ android:title="@string/button_x" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController2"
+ android:key="InputY_1"
+ android:title="@string/button_y" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController2"
+ android:key="InputZ_1"
+ android:title="@string/button_z" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController2"
+ android:key="InputStart_1"
+ android:title="@string/button_start" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController2"
+ android:key="DPadUp_1"
+ android:title="@string/dpad_up" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController2"
+ android:key="DPadDown_1"
+ android:title="@string/dpad_down" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController2"
+ android:key="DPadLeft_1"
+ android:title="@string/dpad_left" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController2"
+ android:key="DPadRight_1"
+ android:title="@string/dpad_right" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController2"
+ android:key="MainUp_1"
+ android:title="@string/main_stick_up" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController2"
+ android:key="MainDown_1"
+ android:title="@string/main_stick_down" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController2"
+ android:key="MainLeft_1"
+ android:title="@string/main_stick_left" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController2"
+ android:key="MainRight_1"
+ android:title="@string/main_stick_right" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController2"
+ android:key="CStickUp_1"
+ android:title="@string/c_stick_up" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController2"
+ android:key="CStickDown_1"
+ android:title="@string/c_stick_down" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController2"
+ android:key="CStickLeft_1"
+ android:title="@string/c_stick_left" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController2"
+ android:key="CStickRight_1"
+ android:title="@string/c_stick_right" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController2"
+ android:key="InputL_1"
+ android:title="@string/trigger_left" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController2"
+ android:key="InputR_1"
+ android:title="@string/trigger_right" />
+ </PreferenceScreen>
+ <PreferenceScreen
+ android:key="gamecube_bindings_control_2"
+ android:title="@string/controller_2">
+ <CheckBoxPreference
+ android:key="enableController3"
+ android:title="@string/enable_controller"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController3"
+ android:key="InputA_2"
+ android:title="@string/button_a" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController3"
+ android:key="InputB_2"
+ android:title="@string/button_b" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController3"
+ android:key="InputX_2"
+ android:title="@string/button_x" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController3"
+ android:key="InputY_2"
+ android:title="@string/button_y" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController3"
+ android:key="InputZ_2"
+ android:title="@string/button_z" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController3"
+ android:key="InputStart_2"
+ android:title="@string/button_start" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController3"
+ android:key="DPadUp_2"
+ android:title="@string/dpad_up" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController3"
+ android:key="DPadDown_2"
+ android:title="@string/dpad_down" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController3"
+ android:key="DPadLeft_2"
+ android:title="@string/dpad_left" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController3"
+ android:key="DPadRight_2"
+ android:title="@string/dpad_right" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController3"
+ android:key="MainUp_2"
+ android:title="@string/main_stick_up" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController3"
+ android:key="MainDown_2"
+ android:title="@string/main_stick_down" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController3"
+ android:key="MainLeft_2"
+ android:title="@string/main_stick_left" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController3"
+ android:key="MainRight_2"
+ android:title="@string/main_stick_right" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController3"
+ android:key="CStickUp_2"
+ android:title="@string/c_stick_up" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController3"
+ android:key="CStickDown_2"
+ android:title="@string/c_stick_down" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController3"
+ android:key="CStickLeft_2"
+ android:title="@string/c_stick_left" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController3"
+ android:key="CStickRight_2"
+ android:title="@string/c_stick_right" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController3"
+ android:key="InputL_2"
+ android:title="@string/trigger_left" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController3"
+ android:key="InputR_2"
+ android:title="@string/trigger_right" />
+ </PreferenceScreen>
+ <PreferenceScreen
+ android:key="gamecube_bindings_control_3"
+ android:title="@string/controller_3">
+ <CheckBoxPreference
+ android:key="enableController4"
+ android:title="@string/enable_controller"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController4"
+ android:key="InputA_3"
+ android:title="@string/button_a" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController4"
+ android:key="InputB_3"
+ android:title="@string/button_b" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController4"
+ android:key="InputX_3"
+ android:title="@string/button_x" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController4"
+ android:key="InputY_3"
+ android:title="@string/button_y" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController4"
+ android:key="InputZ_3"
+ android:title="@string/button_z" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController4"
+ android:key="InputStart_3"
+ android:title="@string/button_start" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController4"
+ android:key="DPadUp_3"
+ android:title="@string/dpad_up" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController4"
+ android:key="DPadDown_3"
+ android:title="@string/dpad_down" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController4"
+ android:key="DPadLeft_3"
+ android:title="@string/dpad_left" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController4"
+ android:key="DPadRight_3"
+ android:title="@string/dpad_right" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController4"
+ android:key="MainUp_3"
+ android:title="@string/main_stick_up" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController4"
+ android:key="MainDown_3"
+ android:title="@string/main_stick_down" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController4"
+ android:key="MainLeft_3"
+ android:title="@string/main_stick_left" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController4"
+ android:key="MainRight_3"
+ android:title="@string/main_stick_right" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController4"
+ android:key="CStickUp_3"
+ android:title="@string/c_stick_up" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController4"
+ android:key="CStickDown_3"
+ android:title="@string/c_stick_down" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController4"
+ android:key="CStickLeft_3"
+ android:title="@string/c_stick_left" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController4"
+ android:key="CStickRight_3"
+ android:title="@string/c_stick_right" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController4"
+ android:key="InputL_3"
+ android:title="@string/trigger_left" />
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableController4"
+ android:key="InputR_3"
+ android:title="@string/trigger_right" />
+ </PreferenceScreen>
+ </PreferenceScreen>
+
+ <!-- Wiimote controller bindings -->
+ <!--
+ <PreferenceScreen
+ android:key="wiimote_bindings"
+ android:title="@string/wiimote_bindings">
+
+ <PreferenceScreen
+ android:key="wiimote_bindings_control_0"
+ android:title="@string/wiimote_0">
+
+ <CheckBoxPreference
+ android:key="enableWiimote1"
+ android:title="@string/enable_wiimote"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote1"
+ android:key="WiimoteInputA_0"
+ android:title="@string/button_a"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote1"
+ android:key="WiimoteInputB_0"
+ android:title="@string/button_b"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote1"
+ android:key="WiimoteInputOne_0"
+ android:title="@string/button_one"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote1"
+ android:key="WiimoteInputTwo_0"
+ android:title="@string/button_two"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote1"
+ android:key="WiimoteInputPlus_0"
+ android:title="@string/button_plus"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote1"
+ android:key="WiimoteInputMinus_0"
+ android:title="@string/button_minus"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote1"
+ android:key="WiimoteInputHome_0"
+ android:title="@string/button_home"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote1"
+ android:key="WiimoteDPadUp_0"
+ android:title="@string/dpad_up"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote1"
+ android:key="WiimoteDPadDown_0"
+ android:title="@string/dpad_down"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote1"
+ android:key="WiimoteDPadLeft_0"
+ android:title="@string/dpad_left"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote1"
+ android:key="WiimoteDPadRight_0"
+ android:title="@string/dpad_right"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote1"
+ android:key="WiimoteIRUp_0"
+ android:title="@string/ir_up"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote1"
+ android:key="WiimoteIRDown_0"
+ android:title="@string/ir_down"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote1"
+ android:key="WiimoteIRLeft_0"
+ android:title="@string/ir_left"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote1"
+ android:key="WiimoteIRRight_0"
+ android:title="@string/ir_right"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote1"
+ android:key="WiimoteIRForward_0"
+ android:title="@string/ir_forward"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote1"
+ android:key="WiimoteIRBackward_0"
+ android:title="@string/ir_backward"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote1"
+ android:key="WiimoteSwingUp_0"
+ android:title="@string/swing_up"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote1"
+ android:key="WiimoteSwingDown_0"
+ android:title="@string/swing_down"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote1"
+ android:key="WiimoteSwingLeft_0"
+ android:title="@string/swing_left"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote1"
+ android:key="WiimoteSwingRight_0"
+ android:title="@string/swing_right"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote1"
+ android:key="WiimoteTiltForward_0"
+ android:title="@string/tilt_forward"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote1"
+ android:key="WiimoteTiltBackward_0"
+ android:title="@string/tilt_backward"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote1"
+ android:key="WiimoteTiltLeft_0"
+ android:title="@string/tilt_left"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote1"
+ android:key="WiimoteTiltRight_0"
+ android:title="@string/tilt_right"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote1"
+ android:key="WiimoteShakeX_0"
+ android:title="@string/shake_x"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote1"
+ android:key="WiimoteShakeY_0"
+ android:title="@string/shake_y"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote1"
+ android:key="WiimoteShakeZ_0"
+ android:title="@string/shake_z"/>
+ </PreferenceScreen>
+ <PreferenceScreen
+ android:key="wiimote_bindings_control_1"
+ android:title="@string/wiimote_1">
+
+ <CheckBoxPreference
+ android:key="enableWiimote2"
+ android:title="@string/enable_wiimote"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote2"
+ android:key="WiimoteInputA_1"
+ android:title="@string/button_a"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote2"
+ android:key="WiimoteInputB_1"
+ android:title="@string/button_b"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote2"
+ android:key="WiimoteInputOne_1"
+ android:title="@string/button_one"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote2"
+ android:key="WiimoteInputTwo_1"
+ android:title="@string/button_two"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote2"
+ android:key="WiimoteInputPlus_1"
+ android:title="@string/button_plus"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote2"
+ android:key="WiimoteInputMinus_1"
+ android:title="@string/button_minus"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote2"
+ android:key="WiimoteInputHome_1"
+ android:title="@string/button_home"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote2"
+ android:key="WiimoteDPadUp_1"
+ android:title="@string/dpad_up"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote2"
+ android:key="WiimoteDPadDown_1"
+ android:title="@string/dpad_down"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote2"
+ android:key="WiimoteDPadLeft_1"
+ android:title="@string/dpad_left"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote2"
+ android:key="WiimoteDPadRight_1"
+ android:title="@string/dpad_right"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote2"
+ android:key="WiimoteIRUp_1"
+ android:title="@string/ir_up"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote2"
+ android:key="WiimoteIRDown_1"
+ android:title="@string/ir_down"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote2"
+ android:key="WiimoteIRLeft_1"
+ android:title="@string/ir_left"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote2"
+ android:key="WiimoteIRRight_1"
+ android:title="@string/ir_right"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote2"
+ android:key="WiimoteIRForward_1"
+ android:title="@string/ir_forward"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote2"
+ android:key="WiimoteIRBackward_1"
+ android:title="@string/ir_backward"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote2"
+ android:key="WiimoteSwingUp_1"
+ android:title="@string/swing_up"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote2"
+ android:key="WiimoteSwingDown_1"
+ android:title="@string/swing_down"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote2"
+ android:key="WiimoteSwingLeft_1"
+ android:title="@string/swing_left"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote2"
+ android:key="WiimoteSwingRight_1"
+ android:title="@string/swing_right"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote2"
+ android:key="WiimoteTiltForward_1"
+ android:title="@string/tilt_forward"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote2"
+ android:key="WiimoteTiltBackward_1"
+ android:title="@string/tilt_backward"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote2"
+ android:key="WiimoteTiltLeft_1"
+ android:title="@string/tilt_left"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote2"
+ android:key="WiimoteTiltRight_1"
+ android:title="@string/tilt_right"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote2"
+ android:key="WiimoteShakeX_1"
+ android:title="@string/shake_x"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote2"
+ android:key="WiimoteShakeY_1"
+ android:title="@string/shake_y"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote2"
+ android:key="WiimoteShakeZ_1"
+ android:title="@string/shake_z"/>
+ </PreferenceScreen>
+ <PreferenceScreen
+ android:key="wiimote_bindings_control_2"
+ android:title="@string/wiimote_2">
+
+ <CheckBoxPreference
+ android:key="enableWiimote3"
+ android:title="@string/enable_wiimote"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote3"
+ android:key="WiimoteInputA_2"
+ android:title="@string/button_a"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote3"
+ android:key="WiimoteInputB_2"
+ android:title="@string/button_b"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote3"
+ android:key="WiimoteInputOne_2"
+ android:title="@string/button_one"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote3"
+ android:key="WiimoteInputTwo_2"
+ android:title="@string/button_two"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote3"
+ android:key="WiimoteInputPlus_2"
+ android:title="@string/button_plus"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote3"
+ android:key="WiimoteInputMinus_2"
+ android:title="@string/button_minus"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote3"
+ android:key="WiimoteInputHome_2"
+ android:title="@string/button_home"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote3"
+ android:key="WiimoteDPadUp_2"
+ android:title="@string/dpad_up"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote3"
+ android:key="WiimoteDPadDown_2"
+ android:title="@string/dpad_down"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote3"
+ android:key="WiimoteDPadLeft_2"
+ android:title="@string/dpad_left"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote3"
+ android:key="WiimoteDPadRight_2"
+ android:title="@string/dpad_right"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote3"
+ android:key="WiimoteIRUp_2"
+ android:title="@string/ir_up"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote3"
+ android:key="WiimoteIRDown_2"
+ android:title="@string/ir_down"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote3"
+ android:key="WiimoteIRLeft_2"
+ android:title="@string/ir_left"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote3"
+ android:key="WiimoteIRRight_2"
+ android:title="@string/ir_right"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote3"
+ android:key="WiimoteIRForward_2"
+ android:title="@string/ir_forward"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote3"
+ android:key="WiimoteIRBackward_2"
+ android:title="@string/ir_backward"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote3"
+ android:key="WiimoteSwingUp_2"
+ android:title="@string/swing_up"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote3"
+ android:key="WiimoteSwingDown_2"
+ android:title="@string/swing_down"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote3"
+ android:key="WiimoteSwingLeft_2"
+ android:title="@string/swing_left"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote3"
+ android:key="WiimoteSwingRight_2"
+ android:title="@string/swing_right"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote3"
+ android:key="WiimoteTiltForward_2"
+ android:title="@string/tilt_forward"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote3"
+ android:key="WiimoteTiltBackward_2"
+ android:title="@string/tilt_backward"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote3"
+ android:key="WiimoteTiltLeft_2"
+ android:title="@string/tilt_left"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote3"
+ android:key="WiimoteTiltRight_2"
+ android:title="@string/tilt_right"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote3"
+ android:key="WiimoteShakeX_2"
+ android:title="@string/shake_x"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote3"
+ android:key="WiimoteShakeY_2"
+ android:title="@string/shake_y"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote3"
+ android:key="WiimoteShakeZ_2"
+ android:title="@string/shake_z"/>
+ </PreferenceScreen>
+ <PreferenceScreen
+ android:key="wiimote_bindings_control_3"
+ android:title="@string/wiimote_3">
+
+ <CheckBoxPreference
+ android:key="enableWiimote4"
+ android:title="@string/enable_wiimote"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote4"
+ android:key="WiimoteInputA_3"
+ android:title="@string/button_a"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote4"
+ android:key="WiimoteInputB_3"
+ android:title="@string/button_b"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote4"
+ android:key="WiimoteInputOne_3"
+ android:title="@string/button_one"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote4"
+ android:key="WiimoteInputTwo_3"
+ android:title="@string/button_two"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote4"
+ android:key="WiimoteInputPlus_3"
+ android:title="@string/button_plus"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote4"
+ android:key="WiimoteInputMinus_3"
+ android:title="@string/button_minus"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote4"
+ android:key="WiimoteInputHome_3"
+ android:title="@string/button_home"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote4"
+ android:key="WiimoteDPadUp_3"
+ android:title="@string/dpad_up"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote4"
+ android:key="WiimoteDPadDown_3"
+ android:title="@string/dpad_down"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote4"
+ android:key="WiimoteDPadLeft_3"
+ android:title="@string/dpad_left"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote4"
+ android:key="WiimoteDPadRight_3"
+ android:title="@string/dpad_right"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote4"
+ android:key="WiimoteIRUp_3"
+ android:title="@string/ir_up"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote4"
+ android:key="WiimoteIRDown_3"
+ android:title="@string/ir_down"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote4"
+ android:key="WiimoteIRLeft_3"
+ android:title="@string/ir_left"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote4"
+ android:key="WiimoteIRRight_3"
+ android:title="@string/ir_right"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote4"
+ android:key="WiimoteIRForward_3"
+ android:title="@string/ir_forward"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote4"
+ android:key="WiimoteIRBackward_3"
+ android:title="@string/ir_backward"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote4"
+ android:key="WiimoteSwingUp_3"
+ android:title="@string/swing_up"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote4"
+ android:key="WiimoteSwingDown_3"
+ android:title="@string/swing_down"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote4"
+ android:key="WiimoteSwingLeft_3"
+ android:title="@string/swing_left"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote4"
+ android:key="WiimoteSwingRight_3"
+ android:title="@string/swing_right"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote4"
+ android:key="WiimoteTiltForward_3"
+ android:title="@string/tilt_forward"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote4"
+ android:key="WiimoteTiltBackward_3"
+ android:title="@string/tilt_backward"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote4"
+ android:key="WiimoteTiltLeft_3"
+ android:title="@string/tilt_left"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote4"
+ android:key="WiimoteTiltRight_3"
+ android:title="@string/tilt_right"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote4"
+ android:key="WiimoteShakeX_3"
+ android:title="@string/shake_x"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote4"
+ android:key="WiimoteShakeY_3"
+ android:title="@string/shake_y"/>
+
+ <org.dolphinemu.dolphinemu.settings.input.InputBindingPreference
+ android:dependency="enableWiimote4"
+ android:key="WiimoteShakeZ_3"
+ android:title="@string/shake_z"/>
+ </PreferenceScreen>
+ </PreferenceScreen> -->
+</PreferenceScreen> \ No newline at end of file
diff --git a/Source/Android/app/src/main/res/xml/video_prefs.xml b/Source/Android/app/src/main/res/xml/video_prefs.xml
new file mode 100644
index 0000000000..57c02e5944
--- /dev/null
+++ b/Source/Android/app/src/main/res/xml/video_prefs.xml
@@ -0,0 +1,178 @@
+<?xml version="1.0" encoding="utf-8"?>
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <!-- Video Settings -->
+
+
+ <!-- Video Enhancements -->
+ <PreferenceScreen android:title="@string/enhancements">
+
+ <ListPreference
+ android:entries="@array/internalResolutionEntries"
+ android:entryValues="@array/internalResolutionValues"
+ android:key="internalResolution"
+ android:summary="@string/internal_resolution_descrip"
+ android:title="@string/internal_resolution"/>
+
+ <ListPreference
+ android:entries="@array/FSAAEntries"
+ android:entryValues="@array/FSAAValues"
+ android:key="FSAA"
+ android:summary="@string/FSAA_descrip"
+ android:title="@string/FSAA"/>
+
+ <ListPreference
+ android:entries="@array/anisotropicFilteringEntries"
+ android:entryValues="@array/anisotropicFilteringValues"
+ android:key="anisotropicFiltering"
+ android:summary="@string/anisotropic_filtering_descrip"
+ android:title="@string/anisotropic_filtering"/>
+
+ <ListPreference
+ android:key="postProcessingShader"
+ android:summary="@string/postprocessing_shader_descrip"
+ android:title="@string/postprocessing_shader"/>
+
+ <CheckBoxPreference
+ android:defaultValue="true"
+ android:key="scaledEFBCopy"
+ android:summary="@string/scaled_efb_copy_descrip"
+ android:title="@string/scaled_efb_copy"/>
+
+ <CheckBoxPreference
+ android:defaultValue="false"
+ android:key="perPixelLighting"
+ android:summary="@string/per_pixel_lighting_descrip"
+ android:title="@string/per_pixel_lighting"/>
+
+ <CheckBoxPreference
+ android:defaultValue="false"
+ android:key="forceTextureFiltering"
+ android:summary="@string/force_texture_filtering_descrip"
+ android:title="@string/force_texture_filtering"/>
+
+ <CheckBoxPreference
+ android:defaultValue="false"
+ android:key="disableFog"
+ android:summary="@string/disable_fog_descrip"
+ android:title="@string/disable_fog"/>
+
+ <PreferenceScreen
+ android:title="@string/stereoscopy"
+ android:key="StereoscopyScreen"
+ android:summary="@string/stereoscopy_descrip">
+
+ <ListPreference
+ android:entries="@array/stereoscopyEntries"
+ android:entryValues="@array/stereoscopyValues"
+ android:key="stereoscopyMode"
+ android:summary="@string/stereoscopy_mode_descrip"
+ android:title="@string/stereoscopy_mode"/>
+
+ <org.dolphinemu.dolphinemu.utils.SliderPreference
+ android:defaultValue="20"
+ android:key="stereoDepth"
+ android:max="100"
+ android:summary="@string/sterescopy_depth_descrip"
+ android:title="@string/sterescopy_depth" />
+
+ <org.dolphinemu.dolphinemu.utils.SliderPreference
+ android:defaultValue="20"
+ android:key="stereoConvergence"
+ android:max="500"
+ android:summary="@string/convergence_descrip"
+ android:title="@string/convergence" />
+
+ <CheckBoxPreference
+ android:defaultValue="false"
+ android:key="stereoSwapEyes"
+ android:summary="@string/swap_eyes_descrip"
+ android:title="@string/swap_eyes"/>
+ </PreferenceScreen>
+ </PreferenceScreen>
+
+ <!-- Video Hacks -->
+ <PreferenceScreen android:title="@string/hacks">
+ <PreferenceCategory android:title="@string/embedded_frame_buffer">
+
+ <CheckBoxPreference
+ android:defaultValue="false"
+ android:key="skipEFBAccess"
+ android:summary="@string/skip_efb_access_descrip"
+ android:title="@string/skip_efb_access"/>
+
+ <CheckBoxPreference
+ android:defaultValue="true"
+ android:key="ignoreFormatChanges"
+ android:summary="@string/ignore_format_changes_descrip"
+ android:title="@string/ignore_format_changes"/>
+
+ <ListPreference
+ android:defaultValue="Texture"
+ android:entries="@array/efbCopyMethodEntries"
+ android:entryValues="@array/efbCopyMethodValues"
+ android:key="efbCopyMethod"
+ android:summary="@string/efb_copy_method_descrip"
+ android:title="@string/efb_copy_method"/>
+
+ </PreferenceCategory>
+
+ <!-- Texture Cache -->
+ <PreferenceCategory android:title="@string/texture_cache">
+ <ListPreference
+ android:defaultValue="Low"
+ android:entries="@array/textureCacheAccuracyEntries"
+ android:entryValues="@array/textureCacheAccuracyValues"
+ android:key="textureCacheAccuracy"
+ android:summary="@string/texture_cache_accuracy_descrip"
+ android:title="@string/texture_cache_accuracy"/>
+ </PreferenceCategory>
+
+ <!-- External Frame Buffer -->
+ <PreferenceCategory android:title="@string/external_frame_buffer">
+ <ListPreference
+ android:defaultValue="Disabled"
+ android:entries="@array/externalFrameBufferEntries"
+ android:entryValues="@array/externalFrameBufferValues"
+ android:key="externalFrameBuffer"
+ android:summary="@string/external_frame_buffer_descrip"
+ android:title="@string/external_frame_buffer"/>
+ </PreferenceCategory>
+
+
+ <!-- Other Hacks -->
+ <PreferenceCategory android:title="@string/other">
+
+ <CheckBoxPreference
+ android:defaultValue="false"
+ android:key="disableDestinationAlpha"
+ android:summary="@string/disable_destination_alpha_descrip"
+ android:title="@string/disable_destination_alpha"/>
+
+ <CheckBoxPreference
+ android:defaultValue="true"
+ android:key="fastDepthCalculation"
+ android:summary="@string/fast_depth_calculation_descrip"
+ android:title="@string/fast_depth_calculation"/>
+
+ <ListPreference
+ android:defaultValue="0"
+ android:entries="@array/aspectRatioEntries"
+ android:entryValues="@array/aspectRatioValues"
+ android:key="aspectRatio"
+ android:summary="@string/aspect_ratio_descrip"
+ android:title="@string/aspect_ratio"/>
+
+ </PreferenceCategory>
+ </PreferenceScreen>
+
+ <org.dolphinemu.dolphinemu.settings.custom.UpdatingListPreference
+ android:key="gpuPref"
+ android:summary="@string/video_backend_desc"
+ android:title="@string/video_backend" />
+
+ <CheckBoxPreference
+ android:key="showFPS"
+ android:summary="@string/show_fps_descrip"
+ android:title="@string/show_fps"/>
+</PreferenceScreen> \ No newline at end of file