Merge branch 'master' into videosoftware-xfb
Conflicts: Source/Core/VideoBackends/Software/Src/EfbCopy.cpp Source/Core/VideoBackends/Software/Src/SWRenderer.cpp Source/Core/VideoBackends/Software/Src/SWRenderer.h Source/Core/VideoBackends/Software/Src/SWVideoConfig.cpp Source/Core/VideoBackends/Software/Src/SWmain.cpp
@ -1,4 +1,4 @@
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
|
||||
org.eclipse.jdt.core.compiler.compliance=1.5
|
||||
org.eclipse.jdt.core.compiler.source=1.5
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
||||
org.eclipse.jdt.core.compiler.compliance=1.6
|
||||
org.eclipse.jdt.core.compiler.source=1.6
|
||||
|
@ -1,49 +1,47 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.dolphinemu.dolphinemu"
|
||||
android:versionCode="10"
|
||||
android:versionName="0.10" >
|
||||
android:versionCode="12"
|
||||
android:versionName="0.12"
|
||||
android:installLocation="auto">
|
||||
|
||||
<uses-sdk android:minSdkVersion="14" android:targetSdkVersion="14"/>
|
||||
|
||||
<uses-feature android:glEsVersion="0x00020000"></uses-feature>
|
||||
<uses-feature android:name="android.hardware.screen.landscape" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||
|
||||
<application
|
||||
android:icon="@drawable/launcher"
|
||||
android:label="@string/app_name">
|
||||
<uses-sdk
|
||||
android:minSdkVersion="14"
|
||||
android:targetSdkVersion="18" />
|
||||
|
||||
<uses-feature android:glEsVersion="0x00020000" />
|
||||
|
||||
<uses-feature android:name="android.hardware.screen.landscape" />
|
||||
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
|
||||
<application
|
||||
android:icon="@drawable/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:allowBackup="true">
|
||||
<activity
|
||||
android:name=".DolphinEmulator"
|
||||
android:name="org.dolphinemu.dolphinemu.DolphinEmulator"
|
||||
android:configChanges="locale|keyboard|keyboardHidden|navigation|fontScale|uiMode"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
|
||||
android:screenOrientation="landscape"
|
||||
android:configChanges="locale|keyboard|keyboardHidden|navigation|fontScale|uiMode" >
|
||||
android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
|
||||
<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.gamelist.GameListActivity" />
|
||||
|
||||
<activity android:name="org.dolphinemu.dolphinemu.emulation.EmulationActivity"
|
||||
android:screenOrientation="landscape" />
|
||||
|
||||
<activity
|
||||
android:name="org.dolphinemu.dolphinemu.FolderBrowser"
|
||||
android:label="@string/app_name"
|
||||
android:configChanges="orientation|locale|keyboard|keyboardHidden|navigation|fontScale|uiMode" >
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".InputConfigFragment"
|
||||
android:label="@string/app_name"
|
||||
android:configChanges="orientation|locale|keyboard|keyboardHidden|navigation|fontScale|uiMode" >
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".PrefsFragment" >
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".GameListActivity" >
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".AboutFragment" >
|
||||
</activity>
|
||||
android:name="org.dolphinemu.dolphinemu.settings.PrefsActivity"
|
||||
android:label="@string/settings" />
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
@ -119,7 +119,7 @@
|
||||
# libraries. Automatically turned for NDK r5x and r6x due to GLESv2
|
||||
# problems.
|
||||
#
|
||||
# LIBRARY_OUTPUT_PATH_ROOT=${CMAKE_SOURCE_DIR} - where to output binary
|
||||
# LIBRARY_OUTPUT_PATH_ROOT=${CMAKE_CURRENT_BINARY_DIR} - where to output binary
|
||||
# files. See additional details below.
|
||||
#
|
||||
# ANDROID_SET_OBSOLETE_VARIABLES=ON - if set, then toolchain defines some
|
||||
@ -187,7 +187,7 @@
|
||||
#
|
||||
# LIBRARY_OUTPUT_PATH_ROOT should be set in cache to determine where Android
|
||||
# libraries will be installed.
|
||||
# Default is ${CMAKE_SOURCE_DIR}, and the android libs will always be
|
||||
# Default is ${CMAKE_CURRENT_BINARY_DIR}, and the android libs will always be
|
||||
# under the ${LIBRARY_OUTPUT_PATH_ROOT}/libs/${ANDROID_NDK_ABI_NAME}
|
||||
# (depending on the target ABI). This is convenient for Android packaging.
|
||||
#
|
||||
@ -1431,7 +1431,7 @@ include_directories( SYSTEM "${ANDROID_SYSROOT}/usr/include" ${ANDROID_STL_INCLU
|
||||
link_directories( "${CMAKE_INSTALL_PREFIX}/libs/${ANDROID_NDK_ABI_NAME}" )
|
||||
|
||||
# setup output directories
|
||||
set( LIBRARY_OUTPUT_PATH_ROOT ${CMAKE_SOURCE_DIR} CACHE PATH "root for library output, set this to change where android libs are installed to" )
|
||||
set( LIBRARY_OUTPUT_PATH_ROOT ${CMAKE_CURRENT_BINARY_DIR} CACHE PATH "root for library output, set this to change where android libs are installed to" )
|
||||
set( CMAKE_INSTALL_PREFIX "${ANDROID_TOOLCHAIN_ROOT}/user" CACHE STRING "path for installing" )
|
||||
|
||||
if(NOT _CMAKE_IN_TRY_COMPILE)
|
||||
|
@ -10,7 +10,7 @@ CPUCore = 3
|
||||
CPUThread = False
|
||||
GFXBackend = Software Renderer
|
||||
HLE_BS2 = False
|
||||
Fastmem = True
|
||||
Fastmem = False
|
||||
DSPThread = False
|
||||
DSPHLE = True
|
||||
SkipIdle = True
|
||||
@ -56,7 +56,7 @@ ShowStatusbar = True
|
||||
ShowLogWindow = False
|
||||
ShowLogConfigWindow = False
|
||||
ShowConsole = False
|
||||
ThemeName = Boomy
|
||||
ThemeName40 = Clean
|
||||
[Hotkeys]
|
||||
Open = 79
|
||||
OpenModifier = 2
|
||||
|
@ -8,7 +8,7 @@
|
||||
<copy todir="${jar.libs.dir}/armeabi-v7a">
|
||||
<fileset
|
||||
dir="../../libs/armeabi-v7a"
|
||||
includes="libdolphin-emu-nogui.so" />
|
||||
includes="libmain.so" />
|
||||
</copy>
|
||||
</target>
|
||||
<target name="clean" depends="android_rules.clean">
|
||||
|
BIN
Source/Android/res/drawable-hdpi/ic_drawer.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
Source/Android/res/drawable-hdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 14 KiB |
BIN
Source/Android/res/drawable-mdpi/ic_drawer.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
Source/Android/res/drawable-mdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 8.4 KiB |
BIN
Source/Android/res/drawable-xhdpi/ic_drawer.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
BIN
Source/Android/res/drawable-xhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 22 KiB |
BIN
Source/Android/res/drawable-xxhdpi/ic_drawer.png
Normal file
After Width: | Height: | Size: 202 B |
BIN
Source/Android/res/drawable-xxhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 5.9 KiB |
BIN
Source/Android/res/drawable-xxhdpi/ic_menu_file.png
Normal file
After Width: | Height: | Size: 823 B |
BIN
Source/Android/res/drawable-xxhdpi/ic_menu_folder.png
Normal file
After Width: | Height: | Size: 640 B |
Before Width: | Height: | Size: 80 KiB |
Before Width: | Height: | Size: 178 B |
@ -1,29 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:orientation="vertical" >
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical" >
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/FolderTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="5dip"
|
||||
android:layout_marginTop="5dip"
|
||||
android:singleLine="true"
|
||||
android:text="Title"
|
||||
android:textStyle="bold" />
|
||||
<TextView
|
||||
android:id="@+id/AboutItemTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="15dip"
|
||||
android:layout_marginTop="6dip"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/FolderSubTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="10dip"
|
||||
android:text="Subtitle" />
|
||||
<TextView
|
||||
android:id="@+id/AboutItemSubTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="15dip"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"/>
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
14
Source/Android/res/layout/emulation_view.xml
Normal file
@ -0,0 +1,14 @@
|
||||
<?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"/>
|
||||
|
||||
</merge>
|
@ -1,53 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="?android:attr/listPreferredItemHeight"
|
||||
android:padding="3dip">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ImageIcon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="fill_parent"
|
||||
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_marginRight="6dip"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/FolderSubTitle"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="26dip"
|
||||
|
||||
android:layout_toRightOf="@id/ImageIcon"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentRight="true"
|
||||
|
||||
android:singleLine="true"
|
||||
android:ellipsize="marquee"
|
||||
android:text="Subtitle" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/FolderTitle"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
||||
android:layout_toRightOf="@id/ImageIcon"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_above="@id/FolderSubTitle"
|
||||
android:layout_alignWithParentIfMissing="true"
|
||||
|
||||
android:gravity="center_vertical"
|
||||
android:text="Title"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<ImageView
|
||||
android:src="@android:drawable/divider_horizontal_dark"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:scaleType="fitXY"
|
||||
android:paddingLeft="5dp"
|
||||
android:paddingRight="5dp"
|
||||
android:paddingBottom="2dp"
|
||||
android:paddingTop="2dp" />
|
||||
</RelativeLayout>
|
@ -2,53 +2,41 @@
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="?android:attr/listPreferredItemHeight"
|
||||
android:padding="3dp" >
|
||||
android:padding="3dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/GameItemIcon"
|
||||
android:id="@+id/ListItemIcon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="fill_parent"
|
||||
|
||||
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_marginRight="6dip" />
|
||||
android:layout_marginRight="6dip"/>
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/GameItemSubText"
|
||||
android:id="@+id/ListItemSubTitle"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="26dip"
|
||||
|
||||
android:layout_toRightOf="@id/GameItemIcon"
|
||||
|
||||
android:layout_toRightOf="@id/ListItemIcon"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentRight="true"
|
||||
|
||||
|
||||
android:singleLine="true"
|
||||
android:ellipsize="marquee"/>
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/GameItemTitle"
|
||||
android:id="@+id/ListItemTitle"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
||||
android:layout_toRightOf="@id/GameItemIcon"
|
||||
|
||||
android:layout_toRightOf="@id/ListItemIcon"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_above="@id/GameItemSubText"
|
||||
android:layout_above="@id/ListItemSubTitle"
|
||||
android:layout_alignWithParentIfMissing="true"
|
||||
|
||||
|
||||
android:gravity="center_vertical"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<ImageView
|
||||
android:src="@android:drawable/divider_horizontal_dark"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:scaleType="fitXY"
|
||||
android:paddingLeft="5dp"
|
||||
android:paddingRight="5dp"
|
||||
android:paddingBottom="2dp"
|
||||
android:paddingTop="2dp" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
@ -3,5 +3,4 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:choiceMode="singleChoice"
|
||||
android:divider="@android:color/transparent"
|
||||
android:dividerHeight="0dp"/>
|
||||
android:dividerHeight="1dp"/>
|
@ -1,30 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<!-- CPU Settings -->
|
||||
<PreferenceScreen
|
||||
android:title="@string/cpu_settings">
|
||||
|
||||
<CheckBoxPreference
|
||||
android:key="dualCorePref"
|
||||
android:summary="@string/on_off"
|
||||
android:title="@string/dual_core" />
|
||||
|
||||
<ListPreference
|
||||
android:key="cpuCorePref"
|
||||
android:summary="@string/emu_core_to_use"
|
||||
android:title="@string/cpu_core" />
|
||||
|
||||
</PreferenceScreen>
|
||||
|
||||
<!-- Video Settings -->
|
||||
<PreferenceScreen
|
||||
android:title="@string/video_settings">
|
||||
|
||||
<ListPreference
|
||||
android:key="gpuPref"
|
||||
android:summary="@string/video_backend_to_use"
|
||||
android:title="@string/video_backend" />
|
||||
|
||||
</PreferenceScreen>
|
||||
</PreferenceScreen>
|
5
Source/Android/res/layout/prefs_viewpager.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<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" />
|
@ -1,26 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="left"
|
||||
android:orientation="vertical" >
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical" >
|
||||
|
||||
<TextView
|
||||
android:id="@+id/SideMenuTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="5dip"
|
||||
android:layout_marginTop="5dip"
|
||||
android:singleLine="true"
|
||||
android:text="@+id/TextView01"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:textStyle="bold" />
|
||||
|
||||
</LinearLayout>
|
||||
<TextView
|
||||
android:id="@+id/SideMenuTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="5dip"
|
||||
android:layout_marginTop="5dip"
|
||||
android:singleLine="true"
|
||||
android:text="@+id/TextView01"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:textStyle="bold" />
|
||||
|
||||
</LinearLayout>
|
||||
|
55
Source/Android/res/menu/emuwindow_overlay.xml
Normal file
@ -0,0 +1,55 @@
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<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>
|
||||
|
||||
<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="always"
|
||||
android:title="@string/overlay_exit_emulation">
|
||||
</item>
|
||||
</menu>
|
7
Source/Android/res/menu/gamelist_menu.xml
Normal file
@ -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>
|
@ -3,34 +3,52 @@
|
||||
|
||||
<!-- 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="build_revision">ビルドのバージョン</string>
|
||||
<string name="supports_gles3">サポートのOpenGL ES 3</string>
|
||||
<string name="supports_neon">サポートのNEON</string>
|
||||
|
||||
<!-- Folder Browser -->
|
||||
<string name="current_dir">現在のディレクトリ: </string>
|
||||
<string name="current_dir">現在のディレクトリ: %1$s</string>
|
||||
<string name="parent_directory">親ディレクトリ</string>
|
||||
<string name="folder">フォルダ</string>
|
||||
<string name="file_size">ファイルサイズ: </string>
|
||||
<string name="cant_use_compressed_filetypes">圧縮ファイル形式はサポートされていません</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="gamepad_config">ゲームパッド設定</string>
|
||||
<string name="about">について</string>
|
||||
|
||||
<!-- Game List Activity - Device Compatibility AlertDialog -->
|
||||
<string name="device_compat_warning">デバイスの互換性の警告</string>
|
||||
<string name="device_compat_warning_msg">この電話は、NEON拡張をサポートしていません。 おそらくDolphinを実行することはできません。\nあなたはとにかくそれを実行してみますか?</string>
|
||||
|
||||
<!-- Game List Fragment -->
|
||||
<string name="file_clicked">クリックされたファイル: </string>
|
||||
|
||||
<string name="file_clicked">クリックされたファイル: %1$s</string>
|
||||
|
||||
<!-- Emulation Window Overlay -->
|
||||
<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="draw_onscreen_controls">画面上のコントロールを描画</string>
|
||||
<string name="input_settings">入力</string>
|
||||
<string name="input_binding">入力バインディング</string>
|
||||
<string name="input_binding_descrip">%1$sにバインドするための入力を移動または押してください。</string>
|
||||
<string name="button_a">Aボタン</string>
|
||||
<string name="button_b">Bボタン</string>
|
||||
<string name="button_start">スタートボタン</string>
|
||||
@ -51,30 +69,80 @@
|
||||
<string name="c_stick_right">C-スティック: →</string>
|
||||
<string name="trigger_left">左のトリガー</string>
|
||||
<string name="trigger_right">右のトリガー</string>
|
||||
|
||||
<string name="not_drawing_onscreen_controls">コントロールは画面上に描画されていない</string>
|
||||
<string name="drawing_onscreen_controls">コントロールは画面上に描画されています</string>
|
||||
<string name="press_button_to_config">%1$sを設定するにはボタンを押して</string>
|
||||
|
||||
<!-- Prefs Fragment -->
|
||||
|
||||
<!-- 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="jitil_arm_recompiler">JITIL ARM Recompiler</string>
|
||||
<string name="cpu_settings">CPU</string>
|
||||
<string name="cpu_core">CPUコア</string>
|
||||
<string name="cpu_settings">CPU設定</string>
|
||||
<string name="emu_core_to_use">使用するエミュレーションコア</string>
|
||||
<string name="cpu_core_desc">%s</string>
|
||||
<string name="dual_core">デュアルコア</string>
|
||||
<string name="on_off">有効/無効</string>
|
||||
|
||||
<string name="video_settings">ビデオ設定</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 3</string>
|
||||
<string name="opengl_es3">OpenGL ES</string>
|
||||
<string name="video_backend">ビデオレンダラ</string>
|
||||
<string name="video_backend_to_use">使用するビデオレンダラー</string>
|
||||
|
||||
<string name="video_backend_desc">%s</string>
|
||||
<string name="show_fps">FPSを表示</string>
|
||||
<string name="show_fps_descrip">エミュレーション速度の指標として、画面左上に毎秒レンダリングされた フレーム数を表示します。</string>
|
||||
<string name="draw_onscreen_controls">画面上のコントロールを描画</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="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="cache_display_lists">Cache Display Lists</string>
|
||||
<string name="cache_display_lists_descrip">ディスプレイリストをキャッシュすることによりエミュレーション速度を向上。</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>
|
||||
|
@ -19,10 +19,12 @@
|
||||
<string-array name="emuCoreEntriesARM" translatable="false">
|
||||
<item>@string/interpreter</item>
|
||||
<item>@string/jit_arm_recompiler</item>
|
||||
<item>@string/jitil_arm_recompiler</item>
|
||||
</string-array>
|
||||
<string-array name="emuCoreValuesARM" translatable="false">
|
||||
<item>0</item>
|
||||
<item>3</item>
|
||||
<item>4</item>
|
||||
</string-array>
|
||||
|
||||
<!-- CPU core selection - Other -->
|
||||
@ -45,11 +47,96 @@
|
||||
</string-array>
|
||||
|
||||
<!-- Video Backend Selection - No OpenGL ES 3 support -->
|
||||
<string-array name="videoBackendEntriesNoGLES3">
|
||||
<string-array name="videoBackendEntriesNoGLES3" translatable="false">
|
||||
<item>@string/software_renderer</item>
|
||||
</string-array>
|
||||
<string-array name="videoBackendValuesNoGLES3">
|
||||
<string-array name="videoBackendValuesNoGLES3" translatable="false">
|
||||
<item>Software Renderer</item>
|
||||
</string-array>
|
||||
|
||||
</resources>
|
||||
|
||||
<!-- 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>
|
||||
|
||||
</resources>
|
||||
|
@ -3,34 +3,52 @@
|
||||
|
||||
<!-- 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="build_revision">Build Revision</string>
|
||||
<string name="supports_gles3">Supports OpenGL ES 3</string>
|
||||
<string name="supports_neon">Supports NEON</string>
|
||||
|
||||
<!-- Folder Browser -->
|
||||
<string name="current_dir">Current Dir: </string>
|
||||
<string name="current_dir">Current Dir: %1$s</string>
|
||||
<string name="parent_directory">Parent Directory</string>
|
||||
<string name="folder">Folder</string>
|
||||
<string name="file_size">File Size: </string>
|
||||
<string name="cant_use_compressed_filetypes">Can not use compressed file types</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="gamepad_config">Gamepad Config</string>
|
||||
<string name="about">About</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>
|
||||
|
||||
<!-- Game List Fragment -->
|
||||
<string name="file_clicked">File clicked: </string>
|
||||
|
||||
<string name="file_clicked">File clicked: %1$s</string>
|
||||
|
||||
<!-- Emulation Overlay -->
|
||||
<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="draw_onscreen_controls">Draw on-screen controls</string>
|
||||
<string name="input_settings">Input</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>
|
||||
<string name="button_a">Button A</string>
|
||||
<string name="button_b">Button B</string>
|
||||
<string name="button_start">Button Start</string>
|
||||
@ -51,30 +69,81 @@
|
||||
<string name="c_stick_right">C Stick Right</string>
|
||||
<string name="trigger_left">Trigger L</string>
|
||||
<string name="trigger_right">Trigger R</string>
|
||||
|
||||
<string name="not_drawing_onscreen_controls">Not drawing on-screen controls</string>
|
||||
<string name="drawing_onscreen_controls">Drawing on-screen controls</string>
|
||||
<string name="press_button_to_config">Press button to configure %1$s</string>
|
||||
|
||||
<!-- Prefs Fragment -->
|
||||
|
||||
<!-- 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="jitil_arm_recompiler">JITIL ARM Recompiler</string>
|
||||
<string name="cpu_settings">CPU</string>
|
||||
<string name="cpu_core">CPU Core</string>
|
||||
<string name="cpu_settings">CPU Settings</string>
|
||||
<string name="emu_core_to_use">Emulation core to use</string>
|
||||
<string name="cpu_core_desc">%s</string>
|
||||
<string name="dual_core">Dual Core</string>
|
||||
<string name="on_off">On/Off</string>
|
||||
|
||||
<string name="video_settings">Video Settings</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 3</string>
|
||||
<string name="opengl_es3">OpenGL ES</string>
|
||||
<string name="video_backend">Video Backend</string>
|
||||
<string name="video_backend_to_use">Video backend to use</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="draw_onscreen_controls">Draw on-screen controls</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="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="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="cache_display_lists">Cache Display Lists</string>
|
||||
<string name="cache_display_lists_descrip">Speeds up emulation a bit by caching display lists.</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>
|
||||
|
||||
<!-- 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>
|
||||
|
21
Source/Android/res/xml/cpu_prefs.xml
Normal file
@ -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>
|
83
Source/Android/res/xml/input_prefs.xml
Normal file
@ -0,0 +1,83 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<Preference
|
||||
android:key="InputA"
|
||||
android:title="@string/button_a" />
|
||||
|
||||
<Preference
|
||||
android:key="InputB"
|
||||
android:title="@string/button_b" />
|
||||
|
||||
<Preference
|
||||
android:key="InputX"
|
||||
android:title="@string/button_x" />
|
||||
|
||||
<Preference
|
||||
android:key="InputY"
|
||||
android:title="@string/button_y" />
|
||||
|
||||
<Preference
|
||||
android:key="InputZ"
|
||||
android:title="@string/button_z" />
|
||||
|
||||
<Preference
|
||||
android:key="InputStart"
|
||||
android:title="@string/button_start" />
|
||||
|
||||
<Preference
|
||||
android:key="DPadUp"
|
||||
android:title="@string/dpad_up" />
|
||||
|
||||
<Preference
|
||||
android:key="DPadDown"
|
||||
android:title="@string/dpad_down" />
|
||||
|
||||
<Preference
|
||||
android:key="DPadLeft"
|
||||
android:title="@string/dpad_left" />
|
||||
|
||||
<Preference
|
||||
android:key="DPadRight"
|
||||
android:title="@string/dpad_right" />
|
||||
|
||||
<Preference
|
||||
android:key="MainUp"
|
||||
android:title="@string/main_stick_up" />
|
||||
|
||||
<Preference
|
||||
android:key="MainDown"
|
||||
android:title="@string/main_stick_down" />
|
||||
|
||||
<Preference
|
||||
android:key="MainLeft"
|
||||
android:title="@string/main_stick_left" />
|
||||
|
||||
<Preference
|
||||
android:key="MainRight"
|
||||
android:title="@string/main_stick_right" />
|
||||
|
||||
<Preference
|
||||
android:key="CStickUp"
|
||||
android:title="@string/c_stick_up" />
|
||||
|
||||
<Preference
|
||||
android:key="CStickDown"
|
||||
android:title="@string/c_stick_down" />
|
||||
|
||||
<Preference
|
||||
android:key="CStickLeft"
|
||||
android:title="@string/c_stick_left" />
|
||||
|
||||
<Preference
|
||||
android:key="CStickRight"
|
||||
android:title="@string/c_stick_right" />
|
||||
|
||||
<Preference
|
||||
android:key="InputL"
|
||||
android:title="@string/trigger_left" />
|
||||
|
||||
<Preference
|
||||
android:key="InputR"
|
||||
android:title="@string/trigger_right" />
|
||||
</PreferenceScreen>
|
145
Source/Android/res/xml/video_prefs.xml
Normal file
@ -0,0 +1,145 @@
|
||||
<?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"/>
|
||||
|
||||
<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>
|
||||
|
||||
<!-- 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="cacheDisplayLists"
|
||||
android:summary="@string/cache_display_lists_descrip"
|
||||
android:title="@string/cache_display_lists"/>
|
||||
|
||||
<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"/>
|
||||
|
||||
</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"/>
|
||||
<!--
|
||||
<CheckBoxPreference
|
||||
android:defaultValue="true"
|
||||
android:key="drawOnscreenControls"
|
||||
android:title="@string/draw_onscreen_controls"/>
|
||||
-->
|
||||
</PreferenceScreen>
|
@ -1,70 +1,119 @@
|
||||
package org.dolphinemu.dolphinemu;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Fragment;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Copyright 2013 Dolphin Emulator Project
|
||||
* Licensed under GPLv2
|
||||
* Refer to the license.txt file included.
|
||||
*/
|
||||
public final class AboutFragment extends Fragment
|
||||
|
||||
package org.dolphinemu.dolphinemu;
|
||||
|
||||
import android.app.ListFragment;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
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.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.dolphinemu.dolphinemu.settings.VideoSettingsFragment;
|
||||
|
||||
/**
|
||||
* Represents the about screen.
|
||||
*/
|
||||
public final class AboutFragment extends ListFragment
|
||||
{
|
||||
private static Activity m_activity;
|
||||
|
||||
private ListView mMainList;
|
||||
|
||||
private FolderBrowserAdapter adapter;
|
||||
boolean Configuring = false;
|
||||
boolean firstEvent = true;
|
||||
|
||||
public AboutFragment()
|
||||
{
|
||||
// Empty constructor required for fragment subclasses
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
|
||||
{
|
||||
View rootView = inflater.inflate(R.layout.gamelist_listview, container, false);
|
||||
mMainList = (ListView) rootView.findViewById(R.id.gamelist);
|
||||
|
||||
String yes = getString(R.string.yes);
|
||||
String no = getString(R.string.no);
|
||||
ListView rootView = (ListView) inflater.inflate(R.layout.gamelist_listview, container, false);
|
||||
|
||||
List<FolderBrowserItem> Input = new ArrayList<FolderBrowserItem>();
|
||||
Input.add(new FolderBrowserItem(getString(R.string.build_revision), NativeLibrary.GetVersionString(), "", true));
|
||||
Input.add(new FolderBrowserItem(getString(R.string.supports_gles3), PrefsFragment.SupportsGLES3() ? yes : no, "", true));
|
||||
final String yes = getString(R.string.yes);
|
||||
final String no = getString(R.string.no);
|
||||
|
||||
adapter = new FolderBrowserAdapter(m_activity, R.layout.about_layout, Input);
|
||||
mMainList.setAdapter(adapter);
|
||||
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), VideoSettingsFragment.SupportsGLES3() ? yes : no));
|
||||
Input.add(new AboutFragmentItem(getString(R.string.supports_neon), NativeLibrary.SupportsNEON() ? yes : no));
|
||||
|
||||
return mMainList;
|
||||
AboutFragmentAdapter adapter = new AboutFragmentAdapter(getActivity(), R.layout.about_layout, Input);
|
||||
rootView.setAdapter(adapter);
|
||||
rootView.setEnabled(false); // Makes the list view non-clickable.
|
||||
|
||||
return rootView;
|
||||
}
|
||||
|
||||
@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
|
||||
// Represents an item in the AboutFragment.
|
||||
private static final class AboutFragmentItem
|
||||
{
|
||||
private final String title;
|
||||
private final String subtitle;
|
||||
|
||||
public AboutFragmentItem(String title, String subtitle)
|
||||
{
|
||||
m_activity = activity;
|
||||
this.title = title;
|
||||
this.subtitle = subtitle;
|
||||
}
|
||||
catch (ClassCastException e)
|
||||
|
||||
public String getTitle()
|
||||
{
|
||||
throw new ClassCastException(activity.toString()
|
||||
+ " must implement OnGameListZeroListener");
|
||||
return title;
|
||||
}
|
||||
|
||||
public String getSubTitle()
|
||||
{
|
||||
return subtitle;
|
||||
}
|
||||
}
|
||||
|
||||
// The adapter that manages the displaying of items in this AboutFragment.
|
||||
private static final class AboutFragmentAdapter extends ArrayAdapter<AboutFragmentItem>
|
||||
{
|
||||
private final Context ctx;
|
||||
private final int id;
|
||||
private final List<AboutFragmentItem> items;
|
||||
|
||||
public AboutFragmentAdapter(Context ctx, int id, List<AboutFragmentItem> items)
|
||||
{
|
||||
super(ctx, id, items);
|
||||
|
||||
this.ctx = ctx;
|
||||
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(ctx);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,115 +1,74 @@
|
||||
/**
|
||||
* Copyright 2013 Dolphin Emulator Project
|
||||
* Licensed under GPLv2
|
||||
* Refer to the license.txt file included.
|
||||
*/
|
||||
|
||||
package org.dolphinemu.dolphinemu;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
import android.view.InputDevice;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.WindowManager;
|
||||
import org.dolphinemu.dolphinemu.gamelist.GameListActivity;
|
||||
import org.dolphinemu.dolphinemu.settings.UserPreferences;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.List;
|
||||
|
||||
public final class DolphinEmulator<MainActivity> extends Activity
|
||||
{
|
||||
static private NativeGLSurfaceView GLview = null;
|
||||
static private boolean Running = false;
|
||||
|
||||
private float screenWidth;
|
||||
private float screenHeight;
|
||||
|
||||
/**
|
||||
* The main activity of this emulator front-end.
|
||||
*/
|
||||
public final class DolphinEmulator extends Activity
|
||||
{
|
||||
private void CopyAsset(String asset, String 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("DolphinEmulator", "Failed to copy asset file: " + asset, e);
|
||||
}
|
||||
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("DolphinEmulator", "Failed to copy asset file: " + asset, 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);
|
||||
}
|
||||
}
|
||||
|
||||
@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();
|
||||
byte[] buffer = new byte[1024];
|
||||
int read;
|
||||
|
||||
while ((read = in.read(buffer)) != -1)
|
||||
{
|
||||
out.write(buffer, 0, read);
|
||||
}
|
||||
}
|
||||
|
||||
/** Called when the activity is first created. */
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
if (savedInstanceState == null)
|
||||
{
|
||||
Intent ListIntent = new Intent(this, GameListActivity.class);
|
||||
startActivityForResult(ListIntent, 1);
|
||||
|
||||
// Make the assets directory
|
||||
Intent GameListIntent = new Intent(this, GameListActivity.class);
|
||||
startActivity(GameListIntent);
|
||||
|
||||
String BaseDir = Environment.getExternalStorageDirectory()+File.separator+"dolphin-emu";
|
||||
File directory = new File(BaseDir);
|
||||
directory.mkdirs();
|
||||
|
||||
String ConfigDir = BaseDir + File.separator + "Config";
|
||||
directory = new File(ConfigDir);
|
||||
directory.mkdirs();
|
||||
|
||||
String GCDir = BaseDir + File.separator + "GC";
|
||||
directory = new File(GCDir);
|
||||
directory.mkdirs();
|
||||
|
||||
String WiiDir = BaseDir + File.separator + "Wii";
|
||||
directory = new File(WiiDir);
|
||||
directory.mkdirs();
|
||||
|
||||
// Copy assets if needed
|
||||
File file = new File(WiiDir + File.separator + "setting-usa.txt");
|
||||
File file = new File(GCDir + File.separator + "font_sjis.bin");
|
||||
if(!file.exists())
|
||||
{
|
||||
NativeLibrary.CreateUserFolders();
|
||||
CopyAsset("ButtonA.png", BaseDir + File.separator + "ButtonA.png");
|
||||
CopyAsset("ButtonB.png", BaseDir + File.separator + "ButtonB.png");
|
||||
CopyAsset("ButtonStart.png", BaseDir + File.separator + "ButtonStart.png");
|
||||
@ -120,120 +79,16 @@ public final class DolphinEmulator<MainActivity> extends Activity
|
||||
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");
|
||||
CopyAsset("setting-eur.txt", WiiDir + File.separator + "setting-eur.txt");
|
||||
CopyAsset("setting-jpn.txt", WiiDir + File.separator + "setting-jpn.txt");
|
||||
CopyAsset("setting-kor.txt", WiiDir + File.separator + "setting-kor.txt");
|
||||
CopyAsset("setting-usa.txt", WiiDir + File.separator + "setting-usa.txt");
|
||||
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
SharedPreferences.Editor editor = prefs.edit();
|
||||
editor.putString("cpuCorePref", NativeLibrary.GetConfig("Dolphin.ini", "Core", "CPUCore", "3"));
|
||||
editor.putBoolean("dualCorePref", NativeLibrary.GetConfig("Dolphin.ini", "Core", "CPUThread", "False").equals("True") ? true : false);
|
||||
editor.putString("gpuPref", NativeLibrary.GetConfig("Dolphin.ini", "Core", "GFXBackend ", "Software Renderer"));
|
||||
editor.commit();
|
||||
}
|
||||
|
||||
// Load the configuration keys set in the Dolphin ini and gfx ini files
|
||||
// into the application's shared preferences.
|
||||
UserPreferences.LoadIniToPrefs(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data)
|
||||
protected void onRestart()
|
||||
{
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
|
||||
if (resultCode == Activity.RESULT_OK)
|
||||
{
|
||||
DisplayMetrics displayMetrics = new DisplayMetrics();
|
||||
WindowManager wm = (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE); // the results will be higher than using the activity context object or the getWindowManager() shortcut
|
||||
wm.getDefaultDisplay().getMetrics(displayMetrics);
|
||||
screenWidth = displayMetrics.widthPixels;
|
||||
screenHeight = displayMetrics.heightPixels;
|
||||
|
||||
String FileName = data.getStringExtra("Select");
|
||||
GLview = new NativeGLSurfaceView(this);
|
||||
this.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
String backend = NativeLibrary.GetConfig("Dolphin.ini", "Core", "GFXBackend", "Software Renderer");
|
||||
NativeLibrary.SetDimensions((int)screenWidth, (int)screenHeight);
|
||||
NativeLibrary.SetFilename(FileName);
|
||||
setContentView(GLview);
|
||||
Running = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event)
|
||||
{
|
||||
float X = event.getX();
|
||||
float Y = event.getY();
|
||||
int Action = event.getActionMasked();
|
||||
|
||||
// Converts button locations 0 - 1 to OGL screen coords -1.0 - 1.0
|
||||
float ScreenX = ((X / screenWidth) * 2.0f) - 1.0f;
|
||||
float ScreenY = ((Y / screenHeight) * -2.0f) + 1.0f;
|
||||
|
||||
NativeLibrary.onTouchEvent(Action, ScreenX, ScreenY);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Gets button presses
|
||||
@Override
|
||||
public boolean dispatchKeyEvent(KeyEvent event)
|
||||
{
|
||||
int action = 0;
|
||||
|
||||
// Special catch for the back key
|
||||
// Currently disabled because stopping and starting emulation is broken.
|
||||
/*
|
||||
if ( event.getSource() == InputDevice.SOURCE_KEYBOARD
|
||||
&& event.getKeyCode() == KeyEvent.KEYCODE_BACK
|
||||
&& event.getAction() == KeyEvent.ACTION_UP
|
||||
)
|
||||
{
|
||||
if (Running)
|
||||
NativeLibrary.StopEmulation();
|
||||
Running = false;
|
||||
Intent ListIntent = new Intent(this, GameListActivity.class);
|
||||
startActivityForResult(ListIntent, 1);
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
|
||||
if (Running)
|
||||
{
|
||||
switch (event.getAction())
|
||||
{
|
||||
case KeyEvent.ACTION_DOWN:
|
||||
action = 0;
|
||||
break;
|
||||
case KeyEvent.ACTION_UP:
|
||||
action = 1;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
InputDevice input = event.getDevice();
|
||||
NativeLibrary.onGamePadEvent(InputConfigFragment.getInputDesc(input), event.getKeyCode(), action);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchGenericMotionEvent(MotionEvent event)
|
||||
{
|
||||
if (((event.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) == 0) || !Running)
|
||||
{
|
||||
return super.dispatchGenericMotionEvent(event);
|
||||
}
|
||||
|
||||
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;
|
||||
super.onRestart();
|
||||
finish(); // If we are ever returning to this activity then we are exiting.
|
||||
}
|
||||
}
|
@ -1,141 +0,0 @@
|
||||
package org.dolphinemu.dolphinemu;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Fragment;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ListView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
|
||||
public final class FolderBrowser extends Fragment
|
||||
{
|
||||
private Activity m_activity;
|
||||
private FolderBrowserAdapter adapter;
|
||||
private ListView mDrawerList;
|
||||
private View rootView;
|
||||
private static File currentDir = null;
|
||||
|
||||
// Populates the FolderView with the given currDir's contents.
|
||||
private void Fill(File currDir)
|
||||
{
|
||||
m_activity.setTitle(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(".gcm", ".iso", ".wbfs", ".gcz", ".dol", ".elf", ".dff"));
|
||||
Set<String> invalidExts = new HashSet<String>(Arrays.asList(".zip", ".rar", ".7z"));
|
||||
|
||||
// Search for any directories or supported files within the current dir.
|
||||
try
|
||||
{
|
||||
for(File entry : dirs)
|
||||
{
|
||||
String entryName = entry.getName();
|
||||
|
||||
if (entryName.charAt(0) != '.')
|
||||
{
|
||||
if(entry.isDirectory())
|
||||
{
|
||||
dir.add(new FolderBrowserItem(entryName, entry.getAbsolutePath(), true));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (validExts.contains(entryName.toLowerCase().substring(entryName.lastIndexOf('.'))))
|
||||
{
|
||||
fls.add(new FolderBrowserItem(entryName, getString(R.string.file_size)+entry.length(), entry.getAbsolutePath(), true));
|
||||
}
|
||||
else if (invalidExts.contains(entryName.toLowerCase().substring(entryName.lastIndexOf('.'))))
|
||||
{
|
||||
fls.add(new FolderBrowserItem(entryName, getString(R.string.file_size)+entry.length(), entry.getAbsolutePath(), false));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(Exception ignored)
|
||||
{
|
||||
}
|
||||
|
||||
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(), true));
|
||||
|
||||
adapter = new FolderBrowserAdapter(m_activity, R.layout.folderbrowser, dir);
|
||||
mDrawerList = (ListView) rootView.findViewById(R.id.gamelist);
|
||||
mDrawerList.setAdapter(adapter);
|
||||
mDrawerList.setOnItemClickListener(mMenuItemClickListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
|
||||
{
|
||||
if(currentDir == null)
|
||||
currentDir = new File(Environment.getExternalStorageDirectory().getPath());
|
||||
|
||||
rootView = inflater.inflate(R.layout.gamelist_listview, container, false);
|
||||
|
||||
Fill(currentDir);
|
||||
return mDrawerList;
|
||||
}
|
||||
|
||||
private AdapterView.OnItemClickListener mMenuItemClickListener = new AdapterView.OnItemClickListener()
|
||||
{
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
|
||||
{
|
||||
FolderBrowserItem item = adapter.getItem(position);
|
||||
if(item.isDirectory())
|
||||
{
|
||||
currentDir = new File(item.getPath());
|
||||
Fill(currentDir);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (item.isValid())
|
||||
FolderSelected();
|
||||
else
|
||||
Toast.makeText(m_activity, getString(R.string.cant_use_compressed_filetypes), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onAttach(Activity activity)
|
||||
{
|
||||
super.onAttach(activity);
|
||||
|
||||
// This makes sure that the container activity has implemented
|
||||
// the callback interface. If not, it throws an exception
|
||||
try
|
||||
{
|
||||
m_activity = activity;
|
||||
}
|
||||
catch (ClassCastException e)
|
||||
{
|
||||
throw new ClassCastException(activity.toString()
|
||||
+ " must implement OnGameListZeroListener");
|
||||
}
|
||||
}
|
||||
private void FolderSelected()
|
||||
{
|
||||
String Directories = NativeLibrary.GetConfig("Dolphin.ini", "General", "GCMPathes", "0");
|
||||
int intDirectories = Integer.parseInt(Directories);
|
||||
Directories = Integer.toString(intDirectories + 1);
|
||||
NativeLibrary.SetConfig("Dolphin.ini", "General", "GCMPathes", Directories);
|
||||
NativeLibrary.SetConfig("Dolphin.ini", "General", "GCMPath" + Integer.toString(intDirectories), currentDir.getPath());
|
||||
|
||||
((GameListActivity)m_activity).SwitchPage(0);
|
||||
}
|
||||
}
|
@ -1,87 +0,0 @@
|
||||
package org.dolphinemu.dolphinemu;
|
||||
|
||||
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 java.util.List;
|
||||
|
||||
public final class FolderBrowserAdapter extends ArrayAdapter<FolderBrowserItem>
|
||||
{
|
||||
private final Context c;
|
||||
private final int id;
|
||||
private final List<FolderBrowserItem> items;
|
||||
|
||||
public FolderBrowserAdapter(Context context, int textViewResourceId, List<FolderBrowserItem> objects)
|
||||
{
|
||||
super(context, textViewResourceId, objects);
|
||||
c = context;
|
||||
id = textViewResourceId;
|
||||
items = objects;
|
||||
}
|
||||
|
||||
public FolderBrowserItem getItem(int i)
|
||||
{
|
||||
return items.get(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent)
|
||||
{
|
||||
View v = convertView;
|
||||
if (v == null)
|
||||
{
|
||||
LayoutInflater vi = (LayoutInflater) c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
v = vi.inflate(id, parent, false);
|
||||
}
|
||||
|
||||
final FolderBrowserItem item = items.get(position);
|
||||
if (item != null)
|
||||
{
|
||||
ImageView iconView = (ImageView) v.findViewById(R.id.ImageIcon);
|
||||
TextView mainText = (TextView) v.findViewById(R.id.FolderTitle);
|
||||
TextView subtitleText = (TextView) v.findViewById(R.id.FolderSubTitle);
|
||||
|
||||
if(mainText != null)
|
||||
{
|
||||
mainText.setText(item.getName());
|
||||
|
||||
if (!item.isValid())
|
||||
{
|
||||
mainText.setTextColor(0xFFFF0000);
|
||||
}
|
||||
}
|
||||
|
||||
if(subtitleText != null)
|
||||
{
|
||||
// Remove the subtitle for all folders, except for the parent directory folder.
|
||||
if (item.isDirectory() && !item.getSubtitle().equals(c.getResources().getString(R.string.parent_directory)))
|
||||
{
|
||||
subtitleText.setVisibility(View.GONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
subtitleText.setText(item.getSubtitle());
|
||||
}
|
||||
}
|
||||
|
||||
if (iconView != null)
|
||||
{
|
||||
if (item.isDirectory())
|
||||
{
|
||||
iconView.setImageResource(R.drawable.ic_menu_folder);
|
||||
}
|
||||
else
|
||||
{
|
||||
iconView.setImageResource(R.drawable.ic_menu_file);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return v;
|
||||
}
|
||||
}
|
@ -1,123 +0,0 @@
|
||||
package org.dolphinemu.dolphinemu;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* Represents an item in the folder browser list.
|
||||
*/
|
||||
public final class FolderBrowserItem implements Comparable<FolderBrowserItem>
|
||||
{
|
||||
private final String name;
|
||||
private final String subtitle;
|
||||
private final String path;
|
||||
private final boolean isValid;
|
||||
private final File underlyingFile;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param name The name of the file/folder represented by this item.
|
||||
* @param subtitle The subtitle of this FolderBrowserItem to display.
|
||||
* @param path The path of the file/folder represented by this item.
|
||||
* @param isValid Whether or not this item represents a file type that can be handled.
|
||||
*/
|
||||
public FolderBrowserItem(String name, String subtitle, String path, boolean isValid)
|
||||
{
|
||||
this.name = name;
|
||||
this.subtitle = subtitle;
|
||||
this.path = path;
|
||||
this.isValid = isValid;
|
||||
this.underlyingFile = new File(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor. Initializes a FolderBrowserItem with an empty subtitle.
|
||||
*
|
||||
* @param ctx Context this FolderBrowserItem is being used in.
|
||||
* @param name The name of the file/folder represented by this item.
|
||||
* @param path The path of the file/folder represented by this item.
|
||||
* @param isValid Whether or not this item represents a file type that can be handled.
|
||||
*/
|
||||
public FolderBrowserItem(String name, String path, boolean isValid)
|
||||
{
|
||||
this.name = name;
|
||||
this.subtitle = "";
|
||||
this.path = path;
|
||||
this.isValid = isValid;
|
||||
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 whether or not the file represented
|
||||
* by this FolderBrowserItem is supported
|
||||
* and can be handled correctly.
|
||||
*
|
||||
* @return whether or not the file represented
|
||||
* by this FolderBrowserItem is supported
|
||||
* and can be handled correctly.
|
||||
*/
|
||||
public boolean isValid()
|
||||
{
|
||||
return isValid;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
|
||||
public int compareTo(FolderBrowserItem other)
|
||||
{
|
||||
if(this.name != null)
|
||||
return this.name.toLowerCase().compareTo(other.getName().toLowerCase());
|
||||
else
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
@ -1,265 +0,0 @@
|
||||
package org.dolphinemu.dolphinemu;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Fragment;
|
||||
import android.app.FragmentManager;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.ActionBarDrawerToggle;
|
||||
import android.support.v4.widget.DrawerLayout;
|
||||
import android.view.*;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ListView;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Copyright 2013 Dolphin Emulator Project
|
||||
* Licensed under GPLv2
|
||||
* Refer to the license.txt file included.
|
||||
*/
|
||||
public final class GameListActivity extends Activity
|
||||
implements GameListFragment.OnGameListZeroListener
|
||||
{
|
||||
private int mCurFragmentNum = 0;
|
||||
private Fragment mCurFragment;
|
||||
|
||||
private ActionBarDrawerToggle mDrawerToggle;
|
||||
private DrawerLayout mDrawerLayout;
|
||||
private SideMenuAdapter mDrawerAdapter;
|
||||
private ListView mDrawerList;
|
||||
|
||||
// Called from the game list fragment
|
||||
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);
|
||||
|
||||
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.gamepad_config), 3));
|
||||
dir.add(new SideMenuItem(getString(R.string.about), 4));
|
||||
|
||||
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, /* nav 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);
|
||||
|
||||
recreateFragment();
|
||||
}
|
||||
|
||||
private void recreateFragment()
|
||||
{
|
||||
mCurFragment = new GameListFragment();
|
||||
FragmentManager fragmentManager = getFragmentManager();
|
||||
fragmentManager.beginTransaction().replace(R.id.content_frame, mCurFragment).commit();
|
||||
}
|
||||
|
||||
public void SwitchPage(int toPage)
|
||||
{
|
||||
if (mCurFragmentNum == toPage)
|
||||
return;
|
||||
|
||||
switch (mCurFragmentNum)
|
||||
{
|
||||
// Folder browser
|
||||
case 1:
|
||||
recreateFragment();
|
||||
break;
|
||||
|
||||
case 3: // Gamepad settings
|
||||
{
|
||||
InputConfigAdapter adapter = ((InputConfigFragment)mCurFragment).getAdapter();
|
||||
for (int a = 0; a < adapter.getCount(); ++a)
|
||||
{
|
||||
InputConfigItem o = adapter.getItem(a);
|
||||
String config = o.getConfig();
|
||||
String bind = o.getBind();
|
||||
String ConfigValues[] = config.split("-");
|
||||
String Key = ConfigValues[0];
|
||||
String Value = ConfigValues[1];
|
||||
NativeLibrary.SetConfig("Dolphin.ini", Key, Value, bind);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 0: // Game List
|
||||
case 2: // Settings
|
||||
case 4: // About
|
||||
/* Do Nothing */
|
||||
break;
|
||||
}
|
||||
|
||||
switch(toPage)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
mCurFragmentNum = 0;
|
||||
mCurFragment = new GameListFragment();
|
||||
FragmentManager fragmentManager = getFragmentManager();
|
||||
fragmentManager.beginTransaction().replace(R.id.content_frame, mCurFragment).commit();
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
{
|
||||
mCurFragmentNum = 1;
|
||||
mCurFragment = new FolderBrowser();
|
||||
FragmentManager fragmentManager = getFragmentManager();
|
||||
fragmentManager.beginTransaction().replace(R.id.content_frame, mCurFragment).commit();
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
{
|
||||
mCurFragmentNum = 2;
|
||||
mCurFragment = new PrefsFragment();
|
||||
FragmentManager fragmentManager = getFragmentManager();
|
||||
fragmentManager.beginTransaction().replace(R.id.content_frame, mCurFragment).commit();
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
{
|
||||
mCurFragmentNum = 3;
|
||||
mCurFragment = new InputConfigFragment();
|
||||
FragmentManager fragmentManager = getFragmentManager();
|
||||
fragmentManager.beginTransaction().replace(R.id.content_frame, mCurFragment).commit();
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
{
|
||||
mCurFragmentNum = 4;
|
||||
mCurFragment = new AboutFragment();
|
||||
FragmentManager fragmentManager = getFragmentManager();
|
||||
fragmentManager.beginTransaction().replace(R.id.content_frame, mCurFragment).commit();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private 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);
|
||||
}
|
||||
|
||||
/* Called whenever we call invalidateOptionsMenu() */
|
||||
@Override
|
||||
public boolean onPrepareOptionsMenu(Menu menu)
|
||||
{
|
||||
return super.onPrepareOptionsMenu(menu);
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
public void onBackPressed()
|
||||
{
|
||||
SwitchPage(0);
|
||||
}
|
||||
|
||||
public interface OnGameConfigListener
|
||||
{
|
||||
public boolean onMotionEvent(MotionEvent event);
|
||||
public boolean onKeyEvent(KeyEvent event);
|
||||
}
|
||||
|
||||
// Gets move(triggers, joystick) events
|
||||
@Override
|
||||
public boolean dispatchGenericMotionEvent(MotionEvent event)
|
||||
{
|
||||
if (mCurFragmentNum == 3)
|
||||
{
|
||||
if (((OnGameConfigListener)mCurFragment).onMotionEvent(event))
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.dispatchGenericMotionEvent(event);
|
||||
}
|
||||
|
||||
// Gets button presses
|
||||
@Override
|
||||
public boolean dispatchKeyEvent(KeyEvent event)
|
||||
{
|
||||
if (mCurFragmentNum == 3)
|
||||
{
|
||||
if (((OnGameConfigListener)mCurFragment).onKeyEvent(event))
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.dispatchKeyEvent(event);
|
||||
}
|
||||
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
package org.dolphinemu.dolphinemu;
|
||||
|
||||
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 java.util.List;
|
||||
|
||||
public final class GameListAdapter extends ArrayAdapter<GameListItem>
|
||||
{
|
||||
private final Context c;
|
||||
private final int id;
|
||||
private final List<GameListItem>items;
|
||||
|
||||
public GameListAdapter(Context context, int textViewResourceId, List<GameListItem> objects)
|
||||
{
|
||||
super(context, textViewResourceId, objects);
|
||||
c = context;
|
||||
id = textViewResourceId;
|
||||
items = objects;
|
||||
}
|
||||
|
||||
public GameListItem getItem(int i)
|
||||
{
|
||||
return items.get(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent)
|
||||
{
|
||||
View v = convertView;
|
||||
if (v == null)
|
||||
{
|
||||
LayoutInflater vi = (LayoutInflater)c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
v = vi.inflate(id, parent, false);
|
||||
}
|
||||
|
||||
final GameListItem item = items.get(position);
|
||||
if (item != null)
|
||||
{
|
||||
TextView title = (TextView) v.findViewById(R.id.GameItemTitle);
|
||||
TextView subtitle = (TextView) v.findViewById(R.id.GameItemSubText);
|
||||
ImageView icon = (ImageView) v.findViewById(R.id.GameItemIcon);
|
||||
|
||||
if(title != null)
|
||||
title.setText(item.getName());
|
||||
|
||||
if(subtitle != null)
|
||||
subtitle.setText(item.getData());
|
||||
|
||||
if(icon != null)
|
||||
{
|
||||
icon.setImageBitmap(item.getImage());
|
||||
icon.getLayoutParams().width = (int) ((860 / c.getResources().getDisplayMetrics().density) + 0.5);
|
||||
icon.getLayoutParams().height = (int)((340 / c.getResources().getDisplayMetrics().density) + 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
@ -1,153 +0,0 @@
|
||||
package org.dolphinemu.dolphinemu;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Fragment;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Copyright 2013 Dolphin Emulator Project
|
||||
* Licensed under GPLv2
|
||||
* Refer to the license.txt file included.
|
||||
*/
|
||||
public final class GameListFragment extends Fragment
|
||||
{
|
||||
private ListView mMainList;
|
||||
private GameListAdapter mGameAdapter;
|
||||
private static GameListActivity mMe;
|
||||
OnGameListZeroListener mCallback;
|
||||
|
||||
public interface OnGameListZeroListener
|
||||
{
|
||||
public void onZeroFiles();
|
||||
}
|
||||
|
||||
public GameListFragment()
|
||||
{
|
||||
// Empty constructor required for fragment subclasses
|
||||
}
|
||||
|
||||
private void Fill()
|
||||
{
|
||||
List<GameListItem> fls = new ArrayList<GameListItem>();
|
||||
String Directories = NativeLibrary.GetConfig("Dolphin.ini", "General", "GCMPathes", "0");
|
||||
int intDirectories = Integer.parseInt(Directories);
|
||||
|
||||
// Extensions to filter by.
|
||||
Set<String> exts = new HashSet<String>(Arrays.asList(".gcm", ".iso", ".wbfs", ".gcz", ".dol", ".elf", ".dff"));
|
||||
|
||||
for (int a = 0; a < intDirectories; ++a)
|
||||
{
|
||||
String BrowseDir = NativeLibrary.GetConfig("Dolphin.ini", "General", "GCMPath" + a, "");
|
||||
File currentDir = new File(BrowseDir);
|
||||
File[] dirs = currentDir.listFiles();
|
||||
try
|
||||
{
|
||||
for(File entry : dirs)
|
||||
{
|
||||
String entryName = entry.getName();
|
||||
|
||||
if (entryName.charAt(0) != '.')
|
||||
{
|
||||
if(!entry.isDirectory())
|
||||
{
|
||||
if (exts.contains(entryName.toLowerCase().substring(entryName.lastIndexOf('.'))))
|
||||
fls.add(new GameListItem(mMe.getApplicationContext(), entryName, getString(R.string.file_size)+entry.length(),entry.getAbsolutePath(), true));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(Exception ignored)
|
||||
{
|
||||
}
|
||||
}
|
||||
Collections.sort(fls);
|
||||
|
||||
// Remove any duplicate items from the list.
|
||||
// We don't need to index these in the game list more than once.
|
||||
//
|
||||
// This works by comparing the paths of items in the file list for equality,
|
||||
// so there should be no worries about accidentally removing a valid game.
|
||||
for (int i = 0; i < fls.size(); i++)
|
||||
{
|
||||
int indexNext = i+1;
|
||||
|
||||
if (indexNext < fls.size() && fls.get(indexNext).getPath().contains(fls.get(i).getPath()))
|
||||
{
|
||||
fls.remove(indexNext);
|
||||
}
|
||||
}
|
||||
|
||||
mGameAdapter = new GameListAdapter(mMe, R.layout.gamelist_layout, fls);
|
||||
mMainList.setAdapter(mGameAdapter);
|
||||
if (fls.size() == 0)
|
||||
mCallback.onZeroFiles();
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
|
||||
{
|
||||
View rootView = inflater.inflate(R.layout.gamelist_listview, container, false);
|
||||
mMainList = (ListView) rootView.findViewById(R.id.gamelist);
|
||||
mMainList.setOnItemClickListener(mGameItemClickListener);
|
||||
|
||||
Fill();
|
||||
|
||||
return mMainList;
|
||||
}
|
||||
|
||||
private AdapterView.OnItemClickListener mGameItemClickListener = new AdapterView.OnItemClickListener()
|
||||
{
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
|
||||
{
|
||||
GameListItem o = mGameAdapter.getItem(position);
|
||||
if(!(o.getData().equalsIgnoreCase(getString(R.string.folder))||o.getData().equalsIgnoreCase(getString(R.string.parent_directory))))
|
||||
{
|
||||
onFileClick(o.getPath());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private void onFileClick(String o)
|
||||
{
|
||||
Toast.makeText(mMe, getString(R.string.file_clicked) + o, Toast.LENGTH_SHORT).show();
|
||||
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra("Select", o);
|
||||
mMe.setResult(Activity.RESULT_OK, intent);
|
||||
mMe.finish();
|
||||
}
|
||||
|
||||
@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;
|
||||
mMe = (GameListActivity) activity;
|
||||
}
|
||||
catch (ClassCastException e)
|
||||
{
|
||||
throw new ClassCastException(activity.toString()
|
||||
+ " must implement OnGameListZeroListener");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,92 +0,0 @@
|
||||
package org.dolphinemu.dolphinemu;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
public final class GameListItem implements Comparable<GameListItem>
|
||||
{
|
||||
private String name;
|
||||
private final String data;
|
||||
private final String path;
|
||||
private final boolean isValid;
|
||||
private Bitmap image;
|
||||
|
||||
public GameListItem(Context ctx, String name, String data, String path, boolean isValid)
|
||||
{
|
||||
this.name = name;
|
||||
this.data = data;
|
||||
this.path = path;
|
||||
this.isValid = isValid;
|
||||
|
||||
File file = new File(path);
|
||||
if (!file.isDirectory() && !path.equals(""))
|
||||
{
|
||||
int[] Banner = NativeLibrary.GetBanner(path);
|
||||
if (Banner[0] == 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Open the no banner icon.
|
||||
InputStream noBannerPath = ctx.getAssets().open("NoBanner.png");
|
||||
|
||||
// Decode the bitmap.
|
||||
image = BitmapFactory.decodeStream(noBannerPath);
|
||||
|
||||
// Scale the bitmap to match other banners.
|
||||
image = Bitmap.createScaledBitmap(image, 96, 32, false);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
image = Bitmap.createBitmap(Banner, 96, 32, Bitmap.Config.ARGB_8888);
|
||||
}
|
||||
|
||||
this.name = NativeLibrary.GetTitle(path);
|
||||
}
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getData()
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
public String getPath()
|
||||
{
|
||||
return path;
|
||||
}
|
||||
|
||||
public Bitmap getImage()
|
||||
{
|
||||
return image;
|
||||
}
|
||||
|
||||
public boolean isValid()
|
||||
{
|
||||
return isValid;
|
||||
}
|
||||
|
||||
public int compareTo(GameListItem o)
|
||||
{
|
||||
if(this.name != null)
|
||||
return this.name.toLowerCase().compareTo(o.getName().toLowerCase());
|
||||
else
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
|
@ -1,61 +0,0 @@
|
||||
package org.dolphinemu.dolphinemu;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Copyright 2013 Dolphin Emulator Project
|
||||
* Licensed under GPLv2
|
||||
* Refer to the license.txt file included.
|
||||
*/
|
||||
public final class InputConfigAdapter extends ArrayAdapter<InputConfigItem>
|
||||
{
|
||||
private final Context c;
|
||||
private final int id;
|
||||
private final List<InputConfigItem> items;
|
||||
|
||||
public InputConfigAdapter(Context context, int textViewResourceId, List<InputConfigItem> objects)
|
||||
{
|
||||
super(context, textViewResourceId, objects);
|
||||
c = context;
|
||||
id = textViewResourceId;
|
||||
items = objects;
|
||||
}
|
||||
|
||||
public InputConfigItem getItem(int i)
|
||||
{
|
||||
return items.get(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent)
|
||||
{
|
||||
View v = convertView;
|
||||
if (v == null)
|
||||
{
|
||||
LayoutInflater vi = (LayoutInflater)c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
v = vi.inflate(id, parent, false);
|
||||
}
|
||||
|
||||
final InputConfigItem item = items.get(position);
|
||||
if (item != null)
|
||||
{
|
||||
TextView title = (TextView) v.findViewById(R.id.FolderTitle);
|
||||
TextView subtitle = (TextView) v.findViewById(R.id.FolderSubTitle);
|
||||
|
||||
if(title != null)
|
||||
title.setText(item.getName());
|
||||
|
||||
if(subtitle != null)
|
||||
subtitle.setText(item.getBind());
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
}
|
@ -1,218 +0,0 @@
|
||||
package org.dolphinemu.dolphinemu;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Fragment;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.*;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ListView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Copyright 2013 Dolphin Emulator Project
|
||||
* Licensed under GPLv2
|
||||
* Refer to the license.txt file included.
|
||||
*/
|
||||
public final class InputConfigFragment extends Fragment
|
||||
implements GameListActivity.OnGameConfigListener
|
||||
{
|
||||
private Activity m_activity;
|
||||
private ListView mDrawerList;
|
||||
private InputConfigAdapter adapter;
|
||||
private int configPosition = 0;
|
||||
boolean Configuring = false;
|
||||
boolean firstEvent = true;
|
||||
|
||||
static public 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();
|
||||
String fakeid = "";
|
||||
|
||||
for (InputDevice.MotionRange range : motions)
|
||||
fakeid += range.getAxis();
|
||||
|
||||
return fakeid;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
|
||||
{
|
||||
List<InputConfigItem> Input = new ArrayList<InputConfigItem>();
|
||||
Input.add(new InputConfigItem(getString(R.string.draw_onscreen_controls), "Android-ScreenControls", "True"));
|
||||
Input.add(new InputConfigItem(getString(R.string.button_a), "Android-InputA"));
|
||||
Input.add(new InputConfigItem(getString(R.string.button_b), "Android-InputB"));
|
||||
Input.add(new InputConfigItem(getString(R.string.button_start), "Android-InputStart"));
|
||||
Input.add(new InputConfigItem(getString(R.string.button_x), "Android-InputX"));
|
||||
Input.add(new InputConfigItem(getString(R.string.button_y), "Android-InputY"));
|
||||
Input.add(new InputConfigItem(getString(R.string.button_z), "Android-InputZ"));
|
||||
Input.add(new InputConfigItem(getString(R.string.dpad_up), "Android-DPadUp"));
|
||||
Input.add(new InputConfigItem(getString(R.string.dpad_down), "Android-DPadDown"));
|
||||
Input.add(new InputConfigItem(getString(R.string.dpad_left), "Android-DPadLeft"));
|
||||
Input.add(new InputConfigItem(getString(R.string.dpad_right), "Android-DPadRight"));
|
||||
Input.add(new InputConfigItem(getString(R.string.main_stick_up), "Android-MainUp"));
|
||||
Input.add(new InputConfigItem(getString(R.string.main_stick_down), "Android-MainDown"));
|
||||
Input.add(new InputConfigItem(getString(R.string.main_stick_left), "Android-MainLeft"));
|
||||
Input.add(new InputConfigItem(getString(R.string.main_stick_right), "Android-MainRight"));
|
||||
Input.add(new InputConfigItem(getString(R.string.c_stick_up), "Android-CStickUp"));
|
||||
Input.add(new InputConfigItem(getString(R.string.c_stick_down), "Android-CStickDown"));
|
||||
Input.add(new InputConfigItem(getString(R.string.c_stick_left), "Android-CStickLeft"));
|
||||
Input.add(new InputConfigItem(getString(R.string.c_stick_right), "Android-CStickRight"));
|
||||
Input.add(new InputConfigItem(getString(R.string.trigger_left), "Android-InputL"));
|
||||
Input.add(new InputConfigItem(getString(R.string.trigger_right), "Android-InputR"));
|
||||
|
||||
adapter = new InputConfigAdapter(m_activity, R.layout.folderbrowser, Input);
|
||||
View rootView = inflater.inflate(R.layout.gamelist_listview, container, false);
|
||||
mDrawerList = (ListView) rootView.findViewById(R.id.gamelist);
|
||||
|
||||
mDrawerList.setAdapter(adapter);
|
||||
mDrawerList.setOnItemClickListener(mMenuItemClickListener);
|
||||
return mDrawerList;
|
||||
}
|
||||
|
||||
private AdapterView.OnItemClickListener mMenuItemClickListener = new AdapterView.OnItemClickListener()
|
||||
{
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
|
||||
{
|
||||
InputConfigItem o = adapter.getItem(position);
|
||||
switch(position)
|
||||
{
|
||||
case 0: // On screen controls
|
||||
String newBind;
|
||||
if (o.getBind().equals("True"))
|
||||
{
|
||||
Toast.makeText(m_activity, getString(R.string.not_drawing_onscreen_controls), Toast.LENGTH_SHORT).show();
|
||||
newBind = "False";
|
||||
}
|
||||
else
|
||||
{
|
||||
Toast.makeText(m_activity, getString(R.string.drawing_onscreen_controls), Toast.LENGTH_SHORT).show();
|
||||
newBind = "True";
|
||||
}
|
||||
adapter.remove(o);
|
||||
o.setBind(newBind);
|
||||
adapter.insert(o, position);
|
||||
break;
|
||||
|
||||
default: // gamepad controls
|
||||
|
||||
Toast.makeText(m_activity, getString(R.string.press_button_to_config, o.getName()), Toast.LENGTH_SHORT).show();
|
||||
configPosition = position;
|
||||
Configuring = true;
|
||||
firstEvent = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private static ArrayList<Float> m_values = new ArrayList<Float>();
|
||||
|
||||
private void AssignBind(String bind)
|
||||
{
|
||||
InputConfigItem o = adapter.getItem(configPosition);
|
||||
adapter.remove(o);
|
||||
o.setBind(bind);
|
||||
adapter.insert(o, configPosition);
|
||||
}
|
||||
|
||||
public InputConfigAdapter getAdapter()
|
||||
{
|
||||
return adapter;
|
||||
}
|
||||
|
||||
// Called from GameListActivity
|
||||
public boolean onMotionEvent(MotionEvent event)
|
||||
{
|
||||
if (((event.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) == 0))
|
||||
return false;
|
||||
|
||||
InputDevice input = event.getDevice();
|
||||
List<InputDevice.MotionRange> motions = input.getMotionRanges();
|
||||
if (Configuring)
|
||||
{
|
||||
if (firstEvent)
|
||||
{
|
||||
m_values.clear();
|
||||
|
||||
for (InputDevice.MotionRange range : motions)
|
||||
{
|
||||
m_values.add(event.getAxisValue(range.getAxis()));
|
||||
}
|
||||
|
||||
firstEvent = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int a = 0; a < motions.size(); ++a)
|
||||
{
|
||||
InputDevice.MotionRange range = motions.get(a);
|
||||
|
||||
if (m_values.get(a) > (event.getAxisValue(range.getAxis()) + 0.5f))
|
||||
{
|
||||
AssignBind("Device '" + InputConfigFragment.getInputDesc(input) + "'-Axis " + range.getAxis() + "-");
|
||||
Configuring = false;
|
||||
}
|
||||
else if (m_values.get(a) < (event.getAxisValue(range.getAxis()) - 0.5f))
|
||||
{
|
||||
AssignBind("Device '" + InputConfigFragment.getInputDesc(input) + "'-Axis " + range.getAxis() + "+");
|
||||
Configuring = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean onKeyEvent(KeyEvent event)
|
||||
{
|
||||
Log.w("InputConfigFragment", "Got Event " + event.getAction());
|
||||
switch (event.getAction())
|
||||
{
|
||||
case KeyEvent.ACTION_DOWN:
|
||||
case KeyEvent.ACTION_UP:
|
||||
if (Configuring)
|
||||
{
|
||||
InputDevice input = event.getDevice();
|
||||
AssignBind("Device '" + InputConfigFragment.getInputDesc(input) + "'-Button " + event.getKeyCode());
|
||||
Configuring = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Activity activity)
|
||||
{
|
||||
super.onAttach(activity);
|
||||
|
||||
// This makes sure that the container activity has implemented
|
||||
// the callback interface. If not, it throws an exception
|
||||
try
|
||||
{
|
||||
m_activity = activity;
|
||||
}
|
||||
catch (ClassCastException e)
|
||||
{
|
||||
throw new ClassCastException(activity.toString()
|
||||
+ " must implement OnGameListZeroListener");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,99 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013 Dolphin Emulator Project
|
||||
* Licensed under GPLv2
|
||||
* Refer to the license.txt file included.
|
||||
*/
|
||||
|
||||
package org.dolphinemu.dolphinemu;
|
||||
|
||||
/**
|
||||
* Represents a controller input item (button, stick, etc).
|
||||
*/
|
||||
public final class InputConfigItem implements Comparable<InputConfigItem>
|
||||
{
|
||||
private String m_name;
|
||||
private String m_Config;
|
||||
private String m_bind;
|
||||
|
||||
private void Init(String name, String config, String defaultBind)
|
||||
{
|
||||
m_name = name;
|
||||
m_Config = config;
|
||||
String ConfigValues[] = m_Config.split("-");
|
||||
String Key = ConfigValues[0];
|
||||
String Value = ConfigValues[1];
|
||||
m_bind = NativeLibrary.GetConfig("Dolphin.ini", Key, Value, defaultBind);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param name Name of the input config item.
|
||||
* @param config Name of the key in the configuration file that this control modifies.
|
||||
* @param defaultBind Default binding to fall back upon if binding fails.
|
||||
*/
|
||||
public InputConfigItem(String name, String config, String defaultBind)
|
||||
{
|
||||
Init(name, config, defaultBind);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor that creates an InputConfigItem
|
||||
* that has a default binding of "None"
|
||||
*
|
||||
* @param name Name of the input config item.
|
||||
* @param config Name of the key in the configuration file that this control modifies.
|
||||
*/
|
||||
public InputConfigItem(String name, String config)
|
||||
{
|
||||
Init(name, config, "None");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of this InputConfigItem.
|
||||
*
|
||||
* @return the name of this InputConfigItem
|
||||
*/
|
||||
public String getName()
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the config key this InputConfigItem modifies.
|
||||
*
|
||||
* @return the config key this InputConfigItem modifies.
|
||||
*/
|
||||
public String getConfig()
|
||||
{
|
||||
return m_Config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the currently set binding of this InputConfigItem
|
||||
*
|
||||
* @return the currently set binding of this InputConfigItem
|
||||
*/
|
||||
public String getBind()
|
||||
{
|
||||
return m_bind;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a new binding for this InputConfigItem.
|
||||
*
|
||||
* @param bind The new binding.
|
||||
*/
|
||||
public void setBind(String bind)
|
||||
{
|
||||
m_bind = bind;
|
||||
}
|
||||
|
||||
public int compareTo(InputConfigItem o)
|
||||
{
|
||||
if(this.m_name != null)
|
||||
return this.m_name.toLowerCase().compareTo(o.getName().toLowerCase());
|
||||
else
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
package org.dolphinemu.dolphinemu;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.SurfaceView;
|
||||
|
||||
public final class NativeGLSurfaceView extends SurfaceView
|
||||
{
|
||||
static private Thread myRun;
|
||||
static private boolean Running = false;
|
||||
static private boolean Created = false;
|
||||
|
||||
public NativeGLSurfaceView(Context context)
|
||||
{
|
||||
super(context);
|
||||
if (!Created)
|
||||
{
|
||||
myRun = new Thread()
|
||||
{
|
||||
@Override
|
||||
public void run() {
|
||||
NativeLibrary.Run(getHolder().getSurface());
|
||||
}
|
||||
};
|
||||
|
||||
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 arg0, int arg1, int arg2, int arg3)
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
|
||||
public void surfaceDestroyed(SurfaceHolder arg0)
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
});
|
||||
|
||||
Created = true;
|
||||
}
|
||||
}
|
||||
}
|
@ -15,20 +15,141 @@ import android.view.Surface;
|
||||
*/
|
||||
public final class NativeLibrary
|
||||
{
|
||||
/**
|
||||
* Handles touch events.
|
||||
*
|
||||
* @param Action Mask for the action being performed.
|
||||
* @param X Location on the screen's X-axis that the touch event occurred.
|
||||
* @param Y Location on the screen's Y-axis that the touch event occurred.
|
||||
*/
|
||||
public static native void onTouchEvent(int Action, float X, float Y);
|
||||
|
||||
/**
|
||||
* Handles button press events for a gamepad.
|
||||
*
|
||||
* @param Device The input descriptor of the gamepad.
|
||||
* @param Button Key code identifying which button was pressed.
|
||||
* @param Action Mask identifying which action is happing (button pressed down, or button released).
|
||||
*/
|
||||
public static native void onGamePadEvent(String Device, int Button, int Action);
|
||||
|
||||
/**
|
||||
* Handles gamepad movement events.
|
||||
*
|
||||
* @param Device The device ID of the gamepad.
|
||||
* @param Axis The axis ID
|
||||
* @param Value The value of the axis represented by the given ID.
|
||||
*/
|
||||
public static native void onGamePadMoveEvent(String Device, int Axis, float Value);
|
||||
public static native String GetConfig(String configFile, String Key, String Value, String Default);
|
||||
public static native void SetConfig(String configFile, String Key, String Value, String Default);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* Sets the dimensions of the rendering window.
|
||||
*
|
||||
* @param width The new width of the rendering window (in pixels).
|
||||
* @param height The new height of the rendering window (in pixels).
|
||||
*/
|
||||
public static native void SetDimensions(int width, int height);
|
||||
|
||||
/**
|
||||
* Gets the embedded banner within the given ISO/ROM.
|
||||
*
|
||||
* @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();
|
||||
|
||||
/**
|
||||
* 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();
|
||||
|
||||
static
|
||||
@ -39,7 +160,7 @@ public final class NativeLibrary
|
||||
}
|
||||
catch (UnsatisfiedLinkError ex)
|
||||
{
|
||||
Log.w("NativeLibrary", ex.toString());
|
||||
Log.e("NativeLibrary", ex.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,214 +0,0 @@
|
||||
package org.dolphinemu.dolphinemu;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.preference.ListPreference;
|
||||
import android.preference.PreferenceFragment;
|
||||
import javax.microedition.khronos.egl.*;
|
||||
import javax.microedition.khronos.opengles.GL10;
|
||||
|
||||
/**
|
||||
* Copyright 2013 Dolphin Emulator Project
|
||||
* Licensed under GPLv2
|
||||
* Refer to the license.txt file included.
|
||||
*/
|
||||
public final class PrefsFragment extends PreferenceFragment
|
||||
{
|
||||
private Activity m_activity;
|
||||
|
||||
static public class VersionCheck
|
||||
{
|
||||
EGL10 mEGL;
|
||||
EGLDisplay mEGLDisplay;
|
||||
EGLConfig[] mEGLConfigs;
|
||||
EGLConfig mEGLConfig;
|
||||
EGLContext mEGLContext;
|
||||
EGLSurface mEGLSurface;
|
||||
GL10 mGL;
|
||||
|
||||
String mThreadOwner;
|
||||
|
||||
public VersionCheck()
|
||||
{
|
||||
int[] version = new int[2];
|
||||
int[] attribList = new int[] {
|
||||
EGL10.EGL_WIDTH, 1,
|
||||
EGL10.EGL_HEIGHT, 1,
|
||||
EGL10.EGL_RENDERABLE_TYPE, 4,
|
||||
EGL10.EGL_NONE
|
||||
};
|
||||
int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
|
||||
int[] ctx_attribs = new int[] {
|
||||
EGL_CONTEXT_CLIENT_VERSION, 2,
|
||||
EGL10.EGL_NONE
|
||||
};
|
||||
|
||||
// No error checking performed, minimum required code to elucidate logic
|
||||
mEGL = (EGL10) EGLContext.getEGL();
|
||||
mEGLDisplay = mEGL.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
|
||||
mEGL.eglInitialize(mEGLDisplay, version);
|
||||
mEGLConfig = chooseConfig(); // Choosing a config is a little more complicated
|
||||
mEGLContext = mEGL.eglCreateContext(mEGLDisplay, mEGLConfig, EGL10.EGL_NO_CONTEXT, ctx_attribs);
|
||||
mEGLSurface = mEGL.eglCreatePbufferSurface(mEGLDisplay, mEGLConfig, attribList);
|
||||
mEGL.eglMakeCurrent(mEGLDisplay, mEGLSurface, mEGLSurface, mEGLContext);
|
||||
mGL = (GL10) mEGLContext.getGL();
|
||||
|
||||
// Record thread owner of OpenGL context
|
||||
mThreadOwner = Thread.currentThread().getName();
|
||||
}
|
||||
|
||||
public String getVersion()
|
||||
{
|
||||
return mGL.glGetString(GL10.GL_VERSION);
|
||||
}
|
||||
|
||||
public String getVendor()
|
||||
{
|
||||
return mGL.glGetString(GL10.GL_VENDOR);
|
||||
}
|
||||
|
||||
public String getRenderer()
|
||||
{
|
||||
return mGL.glGetString(GL10.GL_RENDERER);
|
||||
}
|
||||
|
||||
private EGLConfig chooseConfig()
|
||||
{
|
||||
int[] attribList = new int[] {
|
||||
EGL10.EGL_DEPTH_SIZE, 0,
|
||||
EGL10.EGL_STENCIL_SIZE, 0,
|
||||
EGL10.EGL_RED_SIZE, 8,
|
||||
EGL10.EGL_GREEN_SIZE, 8,
|
||||
EGL10.EGL_BLUE_SIZE, 8,
|
||||
EGL10.EGL_ALPHA_SIZE, 8,
|
||||
EGL10.EGL_NONE
|
||||
};
|
||||
|
||||
// No error checking performed, minimum required code to elucidate logic
|
||||
// Expand on this logic to be more selective in choosing a configuration
|
||||
int[] numConfig = new int[1];
|
||||
mEGL.eglChooseConfig(mEGLDisplay, attribList, null, 0, numConfig);
|
||||
int configSize = numConfig[0];
|
||||
mEGLConfigs = new EGLConfig[configSize];
|
||||
mEGL.eglChooseConfig(mEGLDisplay, attribList, mEGLConfigs, configSize, numConfig);
|
||||
|
||||
return mEGLConfigs[0]; // Best match is probably the first configuration
|
||||
}
|
||||
}
|
||||
|
||||
static public boolean SupportsGLES3()
|
||||
{
|
||||
VersionCheck mbuffer = new VersionCheck();
|
||||
String m_GLVersion = mbuffer.getVersion();
|
||||
String m_GLVendor = mbuffer.getVendor();
|
||||
String m_GLRenderer = mbuffer.getRenderer();
|
||||
|
||||
boolean mSupportsGLES3 = false;
|
||||
|
||||
// Check for OpenGL ES 3 support (General case).
|
||||
if (m_GLVersion != null && (m_GLVersion.contains("OpenGL ES 3.0") || m_GLVersion.equals("OpenGL ES 3.0")))
|
||||
mSupportsGLES3 = true;
|
||||
|
||||
// Checking for OpenGL ES 3 support for certain Qualcomm devices.
|
||||
if (!mSupportsGLES3 && m_GLVendor != null && m_GLVendor.equals("Qualcomm"))
|
||||
{
|
||||
if (m_GLRenderer.contains("Adreno (TM) 3"))
|
||||
{
|
||||
int mVStart = m_GLVersion.indexOf("V@") + 2;
|
||||
int mVEnd = 0;
|
||||
float mVersion;
|
||||
|
||||
for (int a = mVStart; a < m_GLVersion.length(); ++a)
|
||||
{
|
||||
if (m_GLVersion.charAt(a) == ' ')
|
||||
{
|
||||
mVEnd = a;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mVersion = Float.parseFloat(m_GLVersion.substring(mVStart, mVEnd));
|
||||
|
||||
if (mVersion >= 14.0f)
|
||||
mSupportsGLES3 = true;
|
||||
}
|
||||
}
|
||||
return mSupportsGLES3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
// Load the preferences from an XML resource
|
||||
addPreferencesFromResource(R.layout.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"))
|
||||
{
|
||||
cpuCores.setEntries(R.array.emuCoreEntriesX86);
|
||||
cpuCores.setEntryValues(R.array.emuCoreValuesX86);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
//
|
||||
// Setting valid video backends.
|
||||
//
|
||||
final ListPreference videoBackends = (ListPreference) findPreference("gpuPref");
|
||||
final boolean deviceSupportsGLES3 = SupportsGLES3();
|
||||
|
||||
if (deviceSupportsGLES3)
|
||||
{
|
||||
videoBackends.setEntries(R.array.videoBackendEntriesGLES3);
|
||||
videoBackends.setEntryValues(R.array.videoBackendValuesGLES3);
|
||||
}
|
||||
else
|
||||
{
|
||||
videoBackends.setEntries(R.array.videoBackendEntriesNoGLES3);
|
||||
videoBackends.setEntryValues(R.array.videoBackendValuesNoGLES3);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Activity activity)
|
||||
{
|
||||
super.onAttach(activity);
|
||||
|
||||
// This makes sure that the container activity has implemented
|
||||
// the callback interface. If not, it throws an exception
|
||||
try
|
||||
{
|
||||
m_activity = activity;
|
||||
}
|
||||
catch (ClassCastException e)
|
||||
{
|
||||
throw new ClassCastException(activity.toString()
|
||||
+ " must implement OnGameListZeroListener");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy()
|
||||
{
|
||||
super.onDestroy();
|
||||
|
||||
// When the fragment is done being used, save the settings to the Dolphin ini file.
|
||||
UserPreferences.SaveConfigToDolphinIni(m_activity);
|
||||
}
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
package org.dolphinemu.dolphinemu;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public final class SideMenuAdapter extends ArrayAdapter<SideMenuItem>
|
||||
{
|
||||
private final Context c;
|
||||
private final int id;
|
||||
private final List<SideMenuItem>items;
|
||||
|
||||
public SideMenuAdapter(Context context, int textViewResourceId, List<SideMenuItem> objects)
|
||||
{
|
||||
super(context, textViewResourceId, objects);
|
||||
c = context;
|
||||
id = textViewResourceId;
|
||||
items = objects;
|
||||
}
|
||||
|
||||
public SideMenuItem getItem(int i)
|
||||
{
|
||||
return items.get(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent)
|
||||
{
|
||||
View v = convertView;
|
||||
if (v == null)
|
||||
{
|
||||
LayoutInflater vi = (LayoutInflater)c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
v = vi.inflate(id, null);
|
||||
}
|
||||
|
||||
final SideMenuItem item = items.get(position);
|
||||
if (item != null)
|
||||
{
|
||||
TextView title = (TextView) v.findViewById(R.id.SideMenuTitle);
|
||||
|
||||
if(title != null)
|
||||
title.setText(item.getName());
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
@ -1,58 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013 Dolphin Emulator Project
|
||||
* Licensed under GPLv2
|
||||
* Refer to the license.txt file included.
|
||||
*/
|
||||
|
||||
package org.dolphinemu.dolphinemu;
|
||||
|
||||
|
||||
/**
|
||||
* Represents an item that goes in the sidemenu of the app.
|
||||
*/
|
||||
public final class SideMenuItem implements Comparable<SideMenuItem>
|
||||
{
|
||||
private final String m_name;
|
||||
private final int m_id;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param name The name of the SideMenuItem.
|
||||
* @param id ID number of this specific SideMenuItem.
|
||||
*/
|
||||
public SideMenuItem(String name, int id)
|
||||
{
|
||||
m_name = name;
|
||||
m_id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of this SideMenuItem.
|
||||
*
|
||||
* @return the name of this SideMenuItem.
|
||||
*/
|
||||
public String getName()
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ID of this SideMenuItem.
|
||||
*
|
||||
* @return the ID of this SideMenuItem.
|
||||
*/
|
||||
public int getID()
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
public int compareTo(SideMenuItem o)
|
||||
{
|
||||
if(this.m_name != null)
|
||||
return this.m_name.toLowerCase().compareTo(o.getName().toLowerCase());
|
||||
else
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
|
@ -1,39 +0,0 @@
|
||||
package org.dolphinemu.dolphinemu;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
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
|
||||
{
|
||||
/**
|
||||
* Writes the config to the Dolphin ini file.
|
||||
*
|
||||
* @param ctx The context used to retrieve the user settings.
|
||||
* */
|
||||
public static void SaveConfigToDolphinIni(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");
|
||||
|
||||
// Current video backend being used. Falls back to software rendering upon error
|
||||
String currentVideoBackend = prefs.getString("gpuPref", "Software Rendering");
|
||||
|
||||
|
||||
NativeLibrary.SetConfig("Dolphin.ini", "Core", "CPUCore", currentEmuCore);
|
||||
NativeLibrary.SetConfig("Dolphin.ini", "Core", "CPUThread", isUsingDualCore ? "True" : "False");
|
||||
NativeLibrary.SetConfig("Dolphin.ini", "Core", "GFXBackend", currentVideoBackend);
|
||||
}
|
||||
}
|
@ -0,0 +1,304 @@
|
||||
/**
|
||||
* 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.util.DisplayMetrics;
|
||||
import android.view.*;
|
||||
import android.view.WindowManager.LayoutParams;
|
||||
|
||||
import org.dolphinemu.dolphinemu.NativeLibrary;
|
||||
import org.dolphinemu.dolphinemu.R;
|
||||
import org.dolphinemu.dolphinemu.settings.InputConfigFragment;
|
||||
import org.dolphinemu.dolphinemu.settings.VideoSettingsFragment;
|
||||
|
||||
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 float screenWidth;
|
||||
private float screenHeight;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
// Retrieve screen dimensions.
|
||||
DisplayMetrics displayMetrics = new DisplayMetrics();
|
||||
WindowManager wm = getWindowManager();
|
||||
wm.getDefaultDisplay().getMetrics(displayMetrics);
|
||||
this.screenHeight = displayMetrics.heightPixels;
|
||||
this.screenWidth = displayMetrics.widthPixels;
|
||||
|
||||
// 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);
|
||||
|
||||
// Set the native rendering screen width/height.
|
||||
// Also 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();
|
||||
|
||||
// Due to a bug in Adreno, it renders the screen rotated 90 degrees when using OpenGL
|
||||
// Flip the width and height when on Adreno to work around this.
|
||||
// This bug is fixed in Qualcomm driver v53
|
||||
// Mali isn't affected by this bug.
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
if (prefs.getString("gpuPref", "Software Rendering").equals("OGL")
|
||||
&& VideoSettingsFragment.SupportsGLES3()
|
||||
&& VideoSettingsFragment.m_GLVendor != null
|
||||
&& VideoSettingsFragment.m_GLVendor.equals("Qualcomm")
|
||||
&& VideoSettingsFragment.m_QualcommVersion < 53.0f)
|
||||
NativeLibrary.SetDimensions((int)screenHeight, (int)screenWidth);
|
||||
else
|
||||
NativeLibrary.SetDimensions((int)screenWidth, (int)screenHeight);
|
||||
NativeLibrary.SetFilename(gameToEmulate.getStringExtra("SelectedGame"));
|
||||
Running = true;
|
||||
|
||||
// Set the emulation window.
|
||||
setContentView(R.layout.emulation_view);
|
||||
|
||||
// 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 boolean onTouchEvent(MotionEvent event)
|
||||
{
|
||||
float X = event.getX();
|
||||
float Y = event.getY();
|
||||
int Action = event.getActionMasked();
|
||||
|
||||
// Converts button locations 0 - 1 to OGL screen coords -1.0 - 1.0
|
||||
float ScreenX = ((X / screenWidth) * 2.0f) - 1.0f;
|
||||
float ScreenY = ((Y / screenHeight) * -2.0f) + 1.0f;
|
||||
|
||||
NativeLibrary.onTouchEvent(Action, ScreenX, ScreenY);
|
||||
|
||||
return 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 onMenuItemSelected(int itemId, MenuItem item)
|
||||
{
|
||||
switch(item.getItemId())
|
||||
{
|
||||
// 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 slot
|
||||
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(getString(R.string.overlay_exit_emulation));
|
||||
builder.setMessage(R.string.overlay_exit_emulation_confirm);
|
||||
builder.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which)
|
||||
{
|
||||
finish();
|
||||
}
|
||||
});
|
||||
builder.setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which)
|
||||
{
|
||||
// Do nothing. Just makes the No button appear.
|
||||
}
|
||||
});
|
||||
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 = 0;
|
||||
break;
|
||||
case KeyEvent.ACTION_UP:
|
||||
action = 1;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
InputDevice input = event.getDevice();
|
||||
NativeLibrary.onGamePadEvent(InputConfigFragment.getInputDesc(input), event.getKeyCode(), action);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchGenericMotionEvent(MotionEvent event)
|
||||
{
|
||||
if (((event.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) == 0) || !Running)
|
||||
{
|
||||
return super.dispatchGenericMotionEvent(event);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,166 @@
|
||||
/**
|
||||
* 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.gamelist_listview, container, false);
|
||||
adapter = new FolderBrowserAdapter(getActivity(), R.layout.gamelist_folderbrowser_list_item);
|
||||
rootView.setAdapter(adapter);
|
||||
|
||||
Fill(currentDir);
|
||||
return rootView;
|
||||
}
|
||||
|
||||
private void FolderSelected()
|
||||
{
|
||||
String Directories = NativeLibrary.GetConfig("Dolphin.ini", "General", "GCMPathes", "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 gcmPath = NativeLibrary.GetConfig("Dolphin.ini", "General", "GCMPath" + i, "");
|
||||
|
||||
if (gcmPath.equals(currentDir.getPath()))
|
||||
{
|
||||
pathNotPresent = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
pathNotPresent = true;
|
||||
}
|
||||
}
|
||||
|
||||
// User doesn't have this path in the config, so add it.
|
||||
if (pathNotPresent)
|
||||
{
|
||||
NativeLibrary.SetConfig("Dolphin.ini", "General", "GCMPathes", Integer.toString(intDirectories+1));
|
||||
NativeLibrary.SetConfig("Dolphin.ini", "General", "GCMPath" + Integer.toString(intDirectories), currentDir.getPath());
|
||||
}
|
||||
|
||||
((GameListActivity)getActivity()).SwitchPage(0);
|
||||
}
|
||||
}
|
@ -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.ListItemTitle);
|
||||
viewHolder.subtitle = (TextView) convertView.findViewById(R.id.ListItemSubTitle);
|
||||
viewHolder.icon = (ImageView) convertView.findViewById(R.id.ListItemIcon);
|
||||
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;
|
||||
}
|
||||
}
|
@ -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");
|
||||
}
|
||||
}
|
@ -0,0 +1,317 @@
|
||||
/**
|
||||
* 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.res.Configuration;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.ActionBarDrawerToggle;
|
||||
import android.support.v4.widget.DrawerLayout;
|
||||
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.AboutFragment;
|
||||
import org.dolphinemu.dolphinemu.NativeLibrary;
|
||||
import org.dolphinemu.dolphinemu.R;
|
||||
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.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;
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
// Display the game list fragment on activity creation,
|
||||
// but only if no previous states have been saved.
|
||||
if (savedInstanceState == null)
|
||||
{
|
||||
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, new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
// Do Nothing. Just create the Yes button
|
||||
}
|
||||
});
|
||||
builder.setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which)
|
||||
{
|
||||
finish();
|
||||
}
|
||||
});
|
||||
builder.show();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
{
|
||||
mCurFragmentNum = 3;
|
||||
final AboutFragment aboutFragment = new AboutFragment();
|
||||
FragmentTransaction ft = getFragmentManager().beginTransaction();
|
||||
ft.replace(R.id.content_frame, aboutFragment);
|
||||
ft.addToBackStack(null);
|
||||
ft.commit();
|
||||
invalidateOptionsMenu();
|
||||
}
|
||||
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.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener(){
|
||||
public void onClick(DialogInterface dialog, int which)
|
||||
{
|
||||
String directories = NativeLibrary.GetConfig("Dolphin.ini", "General", "GCMPathes", "0");
|
||||
int intDirs = Integer.parseInt(directories);
|
||||
|
||||
for (int i = 0; i < intDirs; i++)
|
||||
{
|
||||
NativeLibrary.SetConfig("Dolphin.ini", "General", "GCMPath" + i, "");
|
||||
}
|
||||
|
||||
// Since we flushed all paths, we signify this in the ini.
|
||||
NativeLibrary.SetConfig("Dolphin.ini", "General", "GCMPathes", "0");
|
||||
|
||||
// Now finally, clear the game list.
|
||||
((GameListFragment) getFragmentManager().findFragmentById(R.id.content_frame)).clearGameList();
|
||||
}
|
||||
});
|
||||
builder.setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which)
|
||||
{
|
||||
// Do nothing. This just make "No" appear.
|
||||
}
|
||||
});
|
||||
|
||||
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()
|
||||
{
|
||||
SwitchPage(0);
|
||||
}
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
/**
|
||||
* 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.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 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 convertView, ViewGroup parent)
|
||||
{
|
||||
if (convertView == null)
|
||||
{
|
||||
LayoutInflater vi = LayoutInflater.from(context);
|
||||
convertView = vi.inflate(id, parent, false);
|
||||
}
|
||||
|
||||
final GameListItem item = getItem(position);
|
||||
if (item != null)
|
||||
{
|
||||
TextView title = (TextView) convertView.findViewById(R.id.ListItemTitle);
|
||||
TextView subtitle = (TextView) convertView.findViewById(R.id.ListItemSubTitle);
|
||||
ImageView icon = (ImageView) convertView.findViewById(R.id.ListItemIcon);
|
||||
|
||||
if (title != null)
|
||||
title.setText(item.getName());
|
||||
|
||||
if (subtitle != null)
|
||||
subtitle.setText(item.getData());
|
||||
|
||||
if (icon != null)
|
||||
{
|
||||
icon.setImageBitmap(item.getImage());
|
||||
icon.getLayoutParams().width = (int) ((860 / context.getResources().getDisplayMetrics().density) + 0.5);
|
||||
icon.getLayoutParams().height = (int)((340 / context.getResources().getDisplayMetrics().density) + 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
return convertView;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,149 @@
|
||||
/**
|
||||
* 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", "GCMPathes", "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", "GCMPath" + 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, String.format(getString(R.string.file_size), 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_folderbrowser_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");
|
||||
}
|
||||
}
|
||||
}
|
@ -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.graphics.BitmapFactory;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.dolphinemu.dolphinemu.NativeLibrary;
|
||||
|
||||
/**
|
||||
* Represents an item in the game list.
|
||||
*/
|
||||
public final class GameListItem implements Comparable<GameListItem>
|
||||
{
|
||||
private String name;
|
||||
private final String data;
|
||||
private final String path;
|
||||
private Bitmap image;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param ctx The current {@link Context}
|
||||
* @param name The name of this GameListItem.
|
||||
* @param data The subtitle for this GameListItem
|
||||
* @param path The file path for the game represented by this GameListItem.
|
||||
*/
|
||||
public GameListItem(Context ctx, String name, String data, String path)
|
||||
{
|
||||
this.name = name;
|
||||
this.data = data;
|
||||
this.path = path;
|
||||
|
||||
File file = new File(path);
|
||||
if (!file.isDirectory() && !path.isEmpty())
|
||||
{
|
||||
int[] Banner = NativeLibrary.GetBanner(path);
|
||||
if (Banner[0] == 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Open the no banner icon.
|
||||
InputStream noBannerPath = ctx.getAssets().open("NoBanner.png");
|
||||
|
||||
// Decode the bitmap.
|
||||
image = BitmapFactory.decodeStream(noBannerPath);
|
||||
|
||||
// Scale the bitmap to match other banners.
|
||||
image = Bitmap.createScaledBitmap(image, 96, 32, false);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
Log.e("GameListItem", e.toString());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
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 subtitle of this GameListItem.
|
||||
*
|
||||
* @return the subtitle of this GameListItem.
|
||||
*/
|
||||
public String getData()
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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");
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,51 @@
|
||||
/**
|
||||
* 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 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"))
|
||||
{
|
||||
cpuCores.setEntries(R.array.emuCoreEntriesX86);
|
||||
cpuCores.setEntryValues(R.array.emuCoreValuesX86);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,270 @@
|
||||
/**
|
||||
* Copyright 2013 Dolphin Emulator Project
|
||||
* Licensed under GPLv2
|
||||
* Refer to the license.txt file included.
|
||||
*/
|
||||
|
||||
package org.dolphinemu.dolphinemu.settings;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Fragment;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceFragment;
|
||||
import android.preference.PreferenceScreen;
|
||||
import android.util.Log;
|
||||
import android.view.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.dolphinemu.dolphinemu.NativeLibrary;
|
||||
import org.dolphinemu.dolphinemu.R;
|
||||
|
||||
/**
|
||||
* The {@link Fragment} responsible for implementing the functionality
|
||||
* within the input control mapping config.
|
||||
*/
|
||||
public final class InputConfigFragment extends PreferenceFragment
|
||||
{
|
||||
private Activity m_activity;
|
||||
private boolean firstEvent = true;
|
||||
private static final ArrayList<Float> m_values = new ArrayList<Float>();
|
||||
|
||||
/**
|
||||
* 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();
|
||||
String fakeid = "";
|
||||
|
||||
for (InputDevice.MotionRange range : motions)
|
||||
fakeid += range.getAxis();
|
||||
|
||||
return fakeid;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
// Expand the preferences from the XML.
|
||||
addPreferencesFromResource(R.xml.input_prefs);
|
||||
|
||||
// Set the summary messages of the preferences to whatever binding
|
||||
// is currently set within the Dolphin config.
|
||||
final String[] keys =
|
||||
{
|
||||
"InputA", "InputB", "InputX", "InputY", "InputZ", "InputStart",
|
||||
"DPadUp", "DPadDown", "DPadLeft", "DPadRight",
|
||||
"MainUp", "MainDown", "MainLeft", "MainRight",
|
||||
"CStickUp", "CStickDown", "CStickLeft", "CStickRight",
|
||||
"InputL", "InputR",
|
||||
};
|
||||
|
||||
Preference pref;
|
||||
for (String key : keys)
|
||||
{
|
||||
String binding = NativeLibrary.GetConfig("Dolphin.ini", "Android", key, "None");
|
||||
pref = findPreference(key);
|
||||
pref.setSummary(binding);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceTreeClick(final PreferenceScreen screen, final Preference pref)
|
||||
{
|
||||
// Begin the creation of the input alert.
|
||||
final MotionAlertDialog dialog = new MotionAlertDialog(m_activity);
|
||||
|
||||
// Set the key listener
|
||||
dialog.setOnKeyListener(new AlertDialog.OnKeyListener()
|
||||
{
|
||||
public boolean onKey(DialogInterface dlg, int keyCode, KeyEvent event)
|
||||
{
|
||||
Log.d("InputConfigFragment", "Received key event: " + event.getAction());
|
||||
switch (event.getAction())
|
||||
{
|
||||
case KeyEvent.ACTION_DOWN:
|
||||
case KeyEvent.ACTION_UP:
|
||||
InputDevice input = event.getDevice();
|
||||
String bindStr = "Device '" + getInputDesc(input) + "'-Button " + event.getKeyCode();
|
||||
NativeLibrary.SetConfig("Dolphin.ini", "Android", pref.getKey(), bindStr);
|
||||
pref.setSummary(bindStr);
|
||||
dialog.dismiss();
|
||||
return true;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// Set the motion event listener.
|
||||
dialog.setOnMotionEventListener(new MotionAlertDialog.OnMotionEventListener()
|
||||
{
|
||||
public boolean onMotion(MotionEvent event)
|
||||
{
|
||||
if (event == null || (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", pref.getKey(), bindStr);
|
||||
pref.setSummary(bindStr);
|
||||
dialog.dismiss();
|
||||
}
|
||||
else if (m_values.get(a) < (event.getAxisValue(range.getAxis()) - 0.5f))
|
||||
{
|
||||
String bindStr = "Device '" + InputConfigFragment.getInputDesc(input) + "'-Axis " + range.getAxis() + "+";
|
||||
NativeLibrary.SetConfig("Dolphin.ini", "Android", pref.getKey(), bindStr);
|
||||
pref.setSummary(bindStr);
|
||||
dialog.dismiss();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
// Set the cancel button.
|
||||
dialog.setButton(AlertDialog.BUTTON_NEGATIVE, getString(R.string.cancel), new AlertDialog.OnClickListener()
|
||||
{
|
||||
public void onClick(DialogInterface dialog, int which)
|
||||
{
|
||||
// Do nothing. This just makes the cancel button appear.
|
||||
}
|
||||
});
|
||||
|
||||
// Set the title and description message.
|
||||
dialog.setTitle(R.string.input_binding);
|
||||
dialog.setMessage(String.format(getString(R.string.input_binding_descrip), pref.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();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Activity activity)
|
||||
{
|
||||
super.onAttach(activity);
|
||||
|
||||
// Cache the activity instance.
|
||||
m_activity = activity;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link AlertDialog} class derivative that allows the motion listener
|
||||
* to be set anonymously, so the creation of an explicit class for
|
||||
* providing functionality is not necessary.
|
||||
*/
|
||||
private static final class MotionAlertDialog extends AlertDialog
|
||||
{
|
||||
private OnMotionEventListener motionListener;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param ctx context to use this dialog in.
|
||||
*/
|
||||
public MotionAlertDialog(Context ctx)
|
||||
{
|
||||
super(ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface which defines a callback method for general
|
||||
* motion events. This allows motion event code to be set
|
||||
* in the event anonymous classes of this dialog are used.
|
||||
*/
|
||||
public interface OnMotionEventListener
|
||||
{
|
||||
/**
|
||||
* Denotes the behavior that should happen when a motion event occurs.
|
||||
*
|
||||
* @param event Reference to the {@link MotionEvent} that occurred.
|
||||
*
|
||||
* @return true if the {@link MotionEvent} is consumed in this call; false otherwise.
|
||||
*/
|
||||
boolean onMotion(MotionEvent event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the motion listener.
|
||||
*
|
||||
* @param listener The motion listener to set.
|
||||
*/
|
||||
public void setOnMotionEventListener(OnMotionEventListener listener)
|
||||
{
|
||||
this.motionListener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchKeyEvent(KeyEvent event)
|
||||
{
|
||||
if (onKeyDown(event.getKeyCode(), event))
|
||||
return true;
|
||||
|
||||
return super.dispatchKeyEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchGenericMotionEvent(MotionEvent event)
|
||||
{
|
||||
if (motionListener.onMotion(event))
|
||||
return true;
|
||||
|
||||
return super.dispatchGenericMotionEvent(event);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,151 @@
|
||||
/**
|
||||
* 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 android.app.ActionBar;
|
||||
import android.app.ActionBar.Tab;
|
||||
import android.app.Activity;
|
||||
import android.app.Fragment;
|
||||
import android.app.FragmentManager;
|
||||
import android.app.FragmentTransaction;
|
||||
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 ActionBar.TabListener, OnSharedPreferenceChangeListener
|
||||
{
|
||||
/**
|
||||
* The {@link ViewPager} that will host the section contents.
|
||||
*/
|
||||
private ViewPager mViewPager;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
// Set the ViewPager.
|
||||
setContentView(R.layout.prefs_viewpager);
|
||||
mViewPager = (ViewPager) findViewById(R.id.pager);
|
||||
|
||||
// Set the ViewPager adapter.
|
||||
final ViewPagerAdapter mSectionsPagerAdapter = new ViewPagerAdapter(getFragmentManager());
|
||||
mViewPager.setAdapter(mSectionsPagerAdapter);
|
||||
|
||||
// Register the preference change listener.
|
||||
final SharedPreferences sPrefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
sPrefs.registerOnSharedPreferenceChangeListener(this);
|
||||
|
||||
// Set up the action bar.
|
||||
final ActionBar actionBar = getActionBar();
|
||||
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
|
||||
actionBar.addTab(actionBar.newTab().setText(R.string.cpu_settings).setTabListener(this));
|
||||
actionBar.addTab(actionBar.newTab().setText(R.string.input_settings).setTabListener(this));
|
||||
actionBar.addTab(actionBar.newTab().setText(R.string.video_settings).setTabListener(this));
|
||||
|
||||
// When swiping between different sections, select the corresponding
|
||||
// tab. We can also use ActionBar.Tab#select() to do this if we have
|
||||
// a reference to the Tab.
|
||||
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener()
|
||||
{
|
||||
@Override
|
||||
public void onPageSelected(int position)
|
||||
{
|
||||
actionBar.setSelectedNavigationItem(position);
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
public void onTabSelected(Tab tab, FragmentTransaction ft)
|
||||
{
|
||||
// When the given tab is selected, switch to the corresponding page in the ViewPager.
|
||||
mViewPager.setCurrentItem(tab.getPosition());
|
||||
}
|
||||
|
||||
public void onTabReselected(Tab tab, FragmentTransaction ft)
|
||||
{
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
public void onTabUnselected(Tab tab, FragmentTransaction ft)
|
||||
{
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
@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
|
||||
{
|
||||
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)
|
||||
{
|
||||
switch(position)
|
||||
{
|
||||
case 0:
|
||||
return getString(R.string.cpu_settings);
|
||||
|
||||
case 1:
|
||||
return getString(R.string.input_settings);
|
||||
|
||||
case 2:
|
||||
return getString(R.string.video_settings);
|
||||
|
||||
default: // Should never happen.
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,250 @@
|
||||
/**
|
||||
* 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.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
|
||||
{
|
||||
/**
|
||||
* 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.
|
||||
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", "Software Renderer"));
|
||||
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.putBoolean("scaledEFBCopy", getConfig("gfx_opengl.ini", "Hacks", "EFBScaleCopy", "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("False"));
|
||||
|
||||
String efbCopyOn = getConfig("gfx_opengl.ini", "Hacks", "EFBCopyEnable", "False");
|
||||
String efbToTexture = getConfig("gfx_opengl.ini", "Hacks", "EFBToTextureEnable", "False");
|
||||
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("cacheDisplayLists", getConfig("gfx_opengl.ini", "Hacks", "DlistCachingEnable", "False").equals("True"));
|
||||
editor.putBoolean("disableDestinationAlpha", getConfig("gfx_opengl.ini", "Settings", "DstAlphaPass", "False").equals("True"));
|
||||
editor.putBoolean("fastDepthCalculation", getConfig("gfx_opengl.ini", "Settings", "FastDepthCalc", "True").equals("True"));
|
||||
|
||||
// Apply the changes.
|
||||
editor.commit();
|
||||
}
|
||||
|
||||
// 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", "Off");
|
||||
|
||||
// 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 display list caching is enabled.
|
||||
boolean dlistCachingEnabled = prefs.getBoolean("cacheDisplayLists", false);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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");
|
||||
|
||||
// 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);
|
||||
|
||||
|
||||
// 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");
|
||||
|
||||
// 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", "Hacks", "DlistCachingEnable", dlistCachingEnabled ? "True" : "False");
|
||||
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", "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");
|
||||
}
|
||||
}
|
@ -0,0 +1,282 @@
|
||||
/**
|
||||
* Copyright 2013 Dolphin Emulator Project
|
||||
* Licensed under GPLv2
|
||||
* Refer to the license.txt file included.
|
||||
*/
|
||||
|
||||
package org.dolphinemu.dolphinemu.settings;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
||||
import android.os.Bundle;
|
||||
import android.preference.ListPreference;
|
||||
import android.preference.PreferenceFragment;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.preference.PreferenceScreen;
|
||||
import org.dolphinemu.dolphinemu.R;
|
||||
|
||||
import javax.microedition.khronos.egl.*;
|
||||
import javax.microedition.khronos.opengles.GL10;
|
||||
|
||||
/**
|
||||
* Responsible for handling the loading of the video preferences.
|
||||
*/
|
||||
public final class VideoSettingsFragment extends PreferenceFragment
|
||||
{
|
||||
public static String m_GLVersion;
|
||||
public static String m_GLVendor;
|
||||
public static String m_GLRenderer;
|
||||
public static String m_GLExtensions;
|
||||
public static float m_QualcommVersion;
|
||||
private Activity m_activity;
|
||||
|
||||
/**
|
||||
* Class which provides a means to retrieve various
|
||||
* info about the OpenGL ES support/features within a device.
|
||||
*/
|
||||
public static final class VersionCheck
|
||||
{
|
||||
private EGL10 mEGL;
|
||||
private EGLDisplay mEGLDisplay;
|
||||
private EGLConfig[] mEGLConfigs;
|
||||
private EGLConfig mEGLConfig;
|
||||
private EGLContext mEGLContext;
|
||||
private EGLSurface mEGLSurface;
|
||||
private GL10 mGL;
|
||||
|
||||
String mThreadOwner;
|
||||
|
||||
public VersionCheck()
|
||||
{
|
||||
int[] version = new int[2];
|
||||
int[] attribList = new int[] {
|
||||
EGL10.EGL_WIDTH, 1,
|
||||
EGL10.EGL_HEIGHT, 1,
|
||||
EGL10.EGL_RENDERABLE_TYPE, 4,
|
||||
EGL10.EGL_NONE
|
||||
};
|
||||
int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
|
||||
int[] ctx_attribs = new int[] {
|
||||
EGL_CONTEXT_CLIENT_VERSION, 2,
|
||||
EGL10.EGL_NONE
|
||||
};
|
||||
|
||||
// No error checking performed, minimum required code to elucidate logic
|
||||
mEGL = (EGL10) EGLContext.getEGL();
|
||||
mEGLDisplay = mEGL.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
|
||||
mEGL.eglInitialize(mEGLDisplay, version);
|
||||
mEGLConfig = chooseConfig(); // Choosing a config is a little more complicated
|
||||
mEGLContext = mEGL.eglCreateContext(mEGLDisplay, mEGLConfig, EGL10.EGL_NO_CONTEXT, ctx_attribs);
|
||||
mEGLSurface = mEGL.eglCreatePbufferSurface(mEGLDisplay, mEGLConfig, attribList);
|
||||
mEGL.eglMakeCurrent(mEGLDisplay, mEGLSurface, mEGLSurface, mEGLContext);
|
||||
mGL = (GL10) mEGLContext.getGL();
|
||||
|
||||
// Record thread owner of OpenGL context
|
||||
mThreadOwner = Thread.currentThread().getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the OpenGL ES version string.
|
||||
*
|
||||
* @return the OpenGL ES version string.
|
||||
*/
|
||||
public String getVersion()
|
||||
{
|
||||
return mGL.glGetString(GL10.GL_VERSION);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the OpenGL ES vendor string.
|
||||
*
|
||||
* @return the OpenGL ES vendor string.
|
||||
*/
|
||||
public String getVendor()
|
||||
{
|
||||
return mGL.glGetString(GL10.GL_VENDOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the OpenGL ES renderer.
|
||||
*
|
||||
* @return the name of the OpenGL ES renderer.
|
||||
*/
|
||||
public String getRenderer()
|
||||
{
|
||||
return mGL.glGetString(GL10.GL_RENDERER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the extension that the device supports
|
||||
*
|
||||
* @return String containing the extensions
|
||||
*/
|
||||
public String getExtensions()
|
||||
{
|
||||
return mGL.glGetString(GL10.GL_EXTENSIONS);
|
||||
}
|
||||
|
||||
private EGLConfig chooseConfig()
|
||||
{
|
||||
int[] attribList = new int[] {
|
||||
EGL10.EGL_DEPTH_SIZE, 0,
|
||||
EGL10.EGL_STENCIL_SIZE, 0,
|
||||
EGL10.EGL_RED_SIZE, 8,
|
||||
EGL10.EGL_GREEN_SIZE, 8,
|
||||
EGL10.EGL_BLUE_SIZE, 8,
|
||||
EGL10.EGL_ALPHA_SIZE, 8,
|
||||
EGL10.EGL_NONE
|
||||
};
|
||||
|
||||
// No error checking performed, minimum required code to elucidate logic
|
||||
// Expand on this logic to be more selective in choosing a configuration
|
||||
int[] numConfig = new int[1];
|
||||
mEGL.eglChooseConfig(mEGLDisplay, attribList, null, 0, numConfig);
|
||||
int configSize = numConfig[0];
|
||||
mEGLConfigs = new EGLConfig[configSize];
|
||||
mEGL.eglChooseConfig(mEGLDisplay, attribList, mEGLConfigs, configSize, numConfig);
|
||||
|
||||
return mEGLConfigs[0]; // Best match is probably the first configuration
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this device supports OpenGL ES 3.
|
||||
*
|
||||
* @return true if this device supports OpenGL ES 3; false otherwise.
|
||||
*/
|
||||
public static boolean SupportsGLES3()
|
||||
{
|
||||
VersionCheck mbuffer = new VersionCheck();
|
||||
m_GLVersion = mbuffer.getVersion();
|
||||
m_GLVendor = mbuffer.getVendor();
|
||||
m_GLRenderer = mbuffer.getRenderer();
|
||||
m_GLExtensions = mbuffer.getExtensions();
|
||||
|
||||
boolean mSupportsGLES3 = false;
|
||||
|
||||
// Check for OpenGL ES 3 support (General case).
|
||||
if (m_GLVersion != null && m_GLVersion.contains("OpenGL ES 3.0"))
|
||||
mSupportsGLES3 = true;
|
||||
|
||||
// Checking for OpenGL ES 3 support for certain Qualcomm devices.
|
||||
if (!mSupportsGLES3 && m_GLVendor != null && m_GLVendor.equals("Qualcomm"))
|
||||
{
|
||||
if (m_GLRenderer.contains("Adreno (TM) 3"))
|
||||
{
|
||||
int mVStart = m_GLVersion.indexOf("V@") + 2;
|
||||
int mVEnd = 0;
|
||||
|
||||
for (int a = mVStart; a < m_GLVersion.length(); ++a)
|
||||
{
|
||||
if (m_GLVersion.charAt(a) == ' ')
|
||||
{
|
||||
mVEnd = a;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_QualcommVersion = Float.parseFloat(m_GLVersion.substring(mVStart, mVEnd));
|
||||
|
||||
if (m_QualcommVersion >= 14.0f)
|
||||
mSupportsGLES3 = true;
|
||||
}
|
||||
}
|
||||
if (!mSupportsGLES3 &&
|
||||
m_GLVendor != null && m_GLVendor.equals("NVIDIA Corporation") &&
|
||||
m_GLRenderer != null && m_GLRenderer.equals("NVIDIA Tegra") &&
|
||||
m_GLExtensions != null && m_GLExtensions.contains("GL_OES_depth24"))
|
||||
{
|
||||
// Is a Tegra 4 since it supports 24bit depth
|
||||
mSupportsGLES3 = true;
|
||||
}
|
||||
return mSupportsGLES3;
|
||||
}
|
||||
|
||||
@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 deviceSupportsGLES3 = SupportsGLES3();
|
||||
|
||||
if (deviceSupportsGLES3)
|
||||
{
|
||||
videoBackends.setEntries(R.array.videoBackendEntriesGLES3);
|
||||
videoBackends.setEntryValues(R.array.videoBackendValuesGLES3);
|
||||
}
|
||||
else
|
||||
{
|
||||
videoBackends.setEntries(R.array.videoBackendEntriesNoGLES3);
|
||||
videoBackends.setEntryValues(R.array.videoBackendValuesNoGLES3);
|
||||
}
|
||||
|
||||
//
|
||||
// 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(m_activity);
|
||||
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);
|
||||
//mainScreen.getPreference(4).setEnabled(true);
|
||||
}
|
||||
else if (videoBackends.getValue().equals("OGL"))
|
||||
{
|
||||
mainScreen.getPreference(0).setEnabled(true);
|
||||
mainScreen.getPreference(1).setEnabled(true);
|
||||
mainScreen.getPreference(3).setEnabled(true);
|
||||
//mainScreen.getPreference(4).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);
|
||||
//mainScreen.getPreference(4).setEnabled(true);
|
||||
}
|
||||
else if (preference.getString(key, "Software Renderer").equals("OGL"))
|
||||
{
|
||||
mainScreen.getPreference(0).setEnabled(true);
|
||||
mainScreen.getPreference(1).setEnabled(true);
|
||||
mainScreen.getPreference(3).setEnabled(true);
|
||||
//mainScreen.getPreference(4).setEnabled(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Activity activity)
|
||||
{
|
||||
super.onAttach(activity);
|
||||
|
||||
// Cache the activity instance.
|
||||
m_activity = activity;
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,52 @@
|
||||
set(CMAKE_FAKELANG_CREATE_STATIC_LIBRARY "touch <TARGET>")
|
||||
if(ENABLE_PCH)
|
||||
# This is actually a .h file, but trick cmake into compiling it as a source file
|
||||
set(pch_out_filename "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/pch.dir/pch.h")
|
||||
if (ANDROID)
|
||||
set(pch_lib_filename "${LIBRARY_OUTPUT_PATH}/libpch.a")
|
||||
else()
|
||||
set(pch_lib_filename "${CMAKE_CURRENT_BINARY_DIR}/libpch.a")
|
||||
endif()
|
||||
set(pch_src_filename "${CMAKE_CURRENT_SOURCE_DIR}/pch.h")
|
||||
|
||||
if(APPLE)
|
||||
set(type objective-c++-header)
|
||||
else()
|
||||
set(type c++-header)
|
||||
endif()
|
||||
|
||||
set_source_files_properties(
|
||||
pch.h PROPERTIES
|
||||
COMPILE_FLAGS "-x ${type}"
|
||||
HEADER_FILE_ONLY 0
|
||||
LANGUAGE CXX)
|
||||
|
||||
add_library(pch STATIC pch.h)
|
||||
|
||||
add_custom_command(
|
||||
TARGET pch
|
||||
PRE_LINK
|
||||
COMMAND ln -fs "${pch_out_filename}.o" "${pch_out_filename}.gch"
|
||||
COMMAND ln -fs "${pch_out_filename}.o" "${pch_out_filename}.pch"
|
||||
COMMAND cp "${pch_src_filename}" "${pch_out_filename}")
|
||||
|
||||
set_target_properties(
|
||||
pch PROPERTIES
|
||||
LINKER_LANGUAGE FAKELANG)
|
||||
endif(ENABLE_PCH)
|
||||
macro(add_dolphin_library lib srcs libs)
|
||||
add_library(${lib} STATIC ${srcs})
|
||||
target_link_libraries(${lib} ${libs})
|
||||
if(ENABLE_PCH)
|
||||
add_dependencies(${lib} pch)
|
||||
set_source_files_properties(
|
||||
${srcs} PROPERTIES
|
||||
COMPILE_FLAGS "-include ${pch_out_filename}"
|
||||
OBJECT_DEPENDS "${pch_lib_filename}")
|
||||
endif(ENABLE_PCH)
|
||||
endmacro(add_dolphin_library)
|
||||
|
||||
add_subdirectory(Core)
|
||||
add_subdirectory(Plugins)
|
||||
|
||||
if (DSPTOOL)
|
||||
add_subdirectory(DSPTool)
|
||||
@ -9,4 +56,7 @@ if (UNITTESTS)
|
||||
add_subdirectory(UnitTests)
|
||||
endif()
|
||||
|
||||
|
||||
|
||||
|
||||
# TODO: Add DSPSpy and TestSuite. Preferrably make them option()s and cpack components
|
||||
|
@ -1,14 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="DebugFast|Win32">
|
||||
<Configuration>DebugFast</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="DebugFast|x64">
|
||||
<Configuration>DebugFast</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
@ -27,210 +19,74 @@
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{37D007BD-D66C-4EAF-B56C-BD1AAC340A05}</ProjectGuid>
|
||||
<RootNamespace>AudioCommon</RootNamespace>
|
||||
<ProjectGuid>{54AA7840-5BEB-4A0C-9452-74BA4CC7FD44}</ProjectGuid>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<PropertyGroup Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\..\VSProps\Base.props" />
|
||||
<Import Project="..\..\VSProps\CodeGen_Debug.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\..\VSProps\Base.props" />
|
||||
<Import Project="..\..\VSProps\CodeGen_Debug.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\..\VSProps\Base.props" />
|
||||
<Import Project="..\..\VSProps\CodeGen_Release.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\..\VSProps\Base.props" />
|
||||
<Import Project="..\..\VSProps\CodeGen_DebugFast.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\..\VSProps\Base.props" />
|
||||
<Import Project="..\..\VSProps\CodeGen_Release.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\..\VSProps\Base.props" />
|
||||
<Import Project="..\..\VSProps\CodeGen_DebugFast.props" />
|
||||
<Import Project="..\..\VSProps\PrecompiledHeader.props" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|Win32'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|Win32'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|x64'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|x64'" />
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>..\Core\Src;..\Common\Src;..\..\..\Externals;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
<Lib>
|
||||
<AdditionalDependencies>SoundTouchD.lib;OpenAL32.lib;dsound.lib;dxerr.lib</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>..\..\..\Externals\OpenAL\Win32;..\..\..\Externals\SoundTouch\Win32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>..\Core\Src;..\Common\Src;..\..\..\Externals;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
<Lib>
|
||||
<AdditionalDependencies>SoundTouchD.lib;OpenAL32.lib;dsound.lib;dxerr.lib</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>..\..\..\Externals\OpenAL\Win64;..\..\..\Externals\SoundTouch\Win64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>..\Core\Src;..\Common\Src;..\..\..\Externals;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
<Lib>
|
||||
<AdditionalDependencies>SoundTouch.lib;OpenAL32.lib;dsound.lib;dxerr.lib</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>..\..\..\Externals\OpenAL\Win32;..\..\..\Externals\SoundTouch\Win32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|Win32'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>..\Core\Src;..\Common\Src;..\..\..\Externals;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
<Lib>
|
||||
<AdditionalDependencies>SoundTouch.lib;OpenAL32.lib;dsound.lib;dxerr.lib</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>..\..\..\Externals\OpenAL\Win32;..\..\..\Externals\SoundTouch\Win32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>..\Core\Src;..\Common\Src;..\..\..\Externals;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
<Lib>
|
||||
<AdditionalDependencies>SoundTouch.lib;OpenAL32.lib;dsound.lib;dxerr.lib</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>..\..\..\Externals\OpenAL\Win64;..\..\..\Externals\SoundTouch\Win64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|x64'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>..\Core\Src;..\Common\Src;..\..\..\Externals;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
<Lib>
|
||||
<AdditionalDependencies>SoundTouch.lib;OpenAL32.lib;dsound.lib;dxerr.lib</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>..\..\..\Externals\OpenAL\Win64;..\..\..\Externals\SoundTouch\Win64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Src\aldlist.cpp" />
|
||||
<ClCompile Include="Src\AOSoundStream.cpp" />
|
||||
<ClCompile Include="Src\AudioCommon.cpp" />
|
||||
<ClCompile Include="Src\DPL2Decoder.cpp" />
|
||||
<ClCompile Include="Src\DSoundStream.cpp" />
|
||||
<ClCompile Include="Src\Mixer.cpp" />
|
||||
<ClCompile Include="Src\NullSoundStream.cpp" />
|
||||
<ClCompile Include="Src\OpenALStream.cpp" />
|
||||
<ClCompile Include="Src\stdafx.cpp">
|
||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Src\WaveFile.cpp" />
|
||||
<ClCompile Include="Src\XAudio2Stream.cpp" />
|
||||
<ClCompile Include="Src\XAudio2_7Stream.cpp">
|
||||
<AdditionalIncludeDirectories Condition="Exists('$(DXSDK_DIR)')">$(DXSDK_DIR)Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Src\aldlist.h" />
|
||||
<ClInclude Include="Src\AlsaSoundStream.h" />
|
||||
<ClInclude Include="Src\AOSoundStream.h" />
|
||||
<ClInclude Include="Src\AudioCommon.h" />
|
||||
<ClInclude Include="Src\CoreAudioSoundStream.h" />
|
||||
<ClInclude Include="Src\DPL2Decoder.h" />
|
||||
<ClInclude Include="Src\DSoundStream.h" />
|
||||
<ClInclude Include="Src\Mixer.h" />
|
||||
<ClInclude Include="Src\NullSoundStream.h" />
|
||||
<ClInclude Include="Src\OpenALStream.h" />
|
||||
<ClInclude Include="Src\OpenSLESStream.h" />
|
||||
<ClInclude Include="Src\PulseAudioStream.h" />
|
||||
<ClInclude Include="Src\SoundStream.h" />
|
||||
<ClInclude Include="Src\stdafx.h" />
|
||||
<ClInclude Include="Src\WaveFile.h" />
|
||||
<ClInclude Include="Src\XAudio2Stream.h" />
|
||||
<ClInclude Include="Src\XAudio2_7Stream.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="CMakeLists.txt" />
|
||||
<Text Include="CMakeLists.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\Externals\SoundTouch\SoundTouch.vcxproj">
|
||||
<Project>{68a5dd20-7057-448b-8fe0-b6ac8d205509}</Project>
|
||||
<Private>true</Private>
|
||||
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
|
||||
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
|
||||
<LinkLibraryDependencies>true</LinkLibraryDependencies>
|
||||
<UseLibraryDependencyInputs>false</UseLibraryDependencyInputs>
|
||||
<ProjectReference Include="..\..\..\Externals\soundtouch\SoundTouch.vcxproj">
|
||||
<Project>{ec082900-b4d8-42e9-9663-77f02f6936ae}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Common\Common.vcxproj">
|
||||
<Project>{c87a4178-44f6-49b2-b7aa-c79af1b8c534}</Project>
|
||||
<Private>true</Private>
|
||||
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
|
||||
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
|
||||
<LinkLibraryDependencies>true</LinkLibraryDependencies>
|
||||
<UseLibraryDependencyInputs>false</UseLibraryDependencyInputs>
|
||||
<Project>{2e6c348c-c75c-4d94-8d1e-9c1fcbf3efe4}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
|
@ -1,14 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="SoundStreams">
|
||||
<UniqueIdentifier>{25ec8f16-fc60-4a63-bc3e-ad0272fd5942}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Src\aldlist.cpp" />
|
||||
<ClCompile Include="Src\AudioCommon.cpp" />
|
||||
<ClCompile Include="Src\DPL2Decoder.cpp" />
|
||||
<ClCompile Include="Src\Mixer.cpp" />
|
||||
<ClCompile Include="Src\WaveFile.cpp" />
|
||||
<ClCompile Include="Src\AOSoundStream.cpp">
|
||||
<ClCompile Include="Src\DSoundStream.cpp">
|
||||
<Filter>SoundStreams</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Src\DSoundStream.cpp">
|
||||
<ClCompile Include="Src\NullSoundStream.cpp">
|
||||
<Filter>SoundStreams</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Src\OpenALStream.cpp">
|
||||
@ -17,14 +23,15 @@
|
||||
<ClCompile Include="Src\XAudio2Stream.cpp">
|
||||
<Filter>SoundStreams</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Src\NullSoundStream.cpp">
|
||||
<ClCompile Include="Src\stdafx.cpp" />
|
||||
<ClCompile Include="Src\XAudio2_7Stream.cpp">
|
||||
<Filter>SoundStreams</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Src\DPL2Decoder.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Src\aldlist.h" />
|
||||
<ClInclude Include="Src\AudioCommon.h" />
|
||||
<ClInclude Include="Src\DPL2Decoder.h" />
|
||||
<ClInclude Include="Src\Mixer.h" />
|
||||
<ClInclude Include="Src\SoundStream.h" />
|
||||
<ClInclude Include="Src\WaveFile.h" />
|
||||
@ -43,14 +50,24 @@
|
||||
<ClInclude Include="Src\XAudio2Stream.h">
|
||||
<Filter>SoundStreams</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Src\DPL2Decoder.h" />
|
||||
<ClInclude Include="Src\stdafx.h" />
|
||||
<ClInclude Include="Src\XAudio2_7Stream.h">
|
||||
<Filter>SoundStreams</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Src\PulseAudioStream.h">
|
||||
<Filter>SoundStreams</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Src\OpenSLESStream.h">
|
||||
<Filter>SoundStreams</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Src\CoreAudioSoundStream.h">
|
||||
<Filter>SoundStreams</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Src\AlsaSoundStream.h">
|
||||
<Filter>SoundStreams</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="CMakeLists.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="SoundStreams">
|
||||
<UniqueIdentifier>{efb9f5b5-ab0c-455d-b78b-26df725386af}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Text Include="CMakeLists.txt" />
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -40,5 +40,4 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||
set(SRCS ${SRCS} Src/CoreAudioSoundStream.cpp)
|
||||
endif()
|
||||
|
||||
add_library(audiocommon STATIC ${SRCS})
|
||||
target_link_libraries(audiocommon ${LIBS})
|
||||
add_dolphin_library(audiocommon "${SRCS}" "${LIBS}")
|
||||
|
@ -6,13 +6,12 @@
|
||||
#define _AOSOUNDSTREAM_H_
|
||||
|
||||
#include "SoundStream.h"
|
||||
#include "Thread.h"
|
||||
|
||||
#if defined(HAVE_AO) && HAVE_AO
|
||||
#include <ao/ao.h>
|
||||
#endif
|
||||
|
||||
#include "Thread.h"
|
||||
|
||||
class AOSound : public SoundStream
|
||||
{
|
||||
#if defined(HAVE_AO) && HAVE_AO
|
||||
@ -43,8 +42,8 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool usesMixer() const {
|
||||
return true;
|
||||
virtual bool usesMixer() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void Update();
|
||||
|
@ -57,7 +57,7 @@ void AlsaSound::SoundLoop()
|
||||
// Underrun
|
||||
snd_pcm_prepare(handle);
|
||||
}
|
||||
else if (rc < 0)
|
||||
else if (rc < 0)
|
||||
{
|
||||
ERROR_LOG(AUDIO, "writei fail: %s", snd_strerror(rc));
|
||||
}
|
||||
@ -77,7 +77,7 @@ bool AlsaSound::AlsaInit()
|
||||
unsigned int periods;
|
||||
|
||||
err = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0);
|
||||
if (err < 0)
|
||||
if (err < 0)
|
||||
{
|
||||
ERROR_LOG(AUDIO, "Audio open error: %s\n", snd_strerror(err));
|
||||
return false;
|
||||
@ -86,21 +86,21 @@ bool AlsaSound::AlsaInit()
|
||||
snd_pcm_hw_params_alloca(&hwparams);
|
||||
|
||||
err = snd_pcm_hw_params_any(handle, hwparams);
|
||||
if (err < 0)
|
||||
if (err < 0)
|
||||
{
|
||||
ERROR_LOG(AUDIO, "Broken configuration for this PCM: %s\n", snd_strerror(err));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
err = snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED);
|
||||
if (err < 0)
|
||||
if (err < 0)
|
||||
{
|
||||
ERROR_LOG(AUDIO, "Access type not available: %s\n", snd_strerror(err));
|
||||
return false;
|
||||
}
|
||||
|
||||
err = snd_pcm_hw_params_set_format(handle, hwparams, SND_PCM_FORMAT_S16_LE);
|
||||
if (err < 0)
|
||||
if (err < 0)
|
||||
{
|
||||
ERROR_LOG(AUDIO, "Sample format not available: %s\n", snd_strerror(err));
|
||||
return false;
|
||||
@ -108,14 +108,14 @@ bool AlsaSound::AlsaInit()
|
||||
|
||||
dir = 0;
|
||||
err = snd_pcm_hw_params_set_rate_near(handle, hwparams, &sample_rate, &dir);
|
||||
if (err < 0)
|
||||
if (err < 0)
|
||||
{
|
||||
ERROR_LOG(AUDIO, "Rate not available: %s\n", snd_strerror(err));
|
||||
return false;
|
||||
}
|
||||
|
||||
err = snd_pcm_hw_params_set_channels(handle, hwparams, 2);
|
||||
if (err < 0)
|
||||
if (err < 0)
|
||||
{
|
||||
ERROR_LOG(AUDIO, "Channels count not available: %s\n", snd_strerror(err));
|
||||
return false;
|
||||
@ -123,7 +123,7 @@ bool AlsaSound::AlsaInit()
|
||||
|
||||
periods = BUFFER_SIZE_MAX / FRAME_COUNT_MIN;
|
||||
err = snd_pcm_hw_params_set_periods_max(handle, hwparams, &periods, &dir);
|
||||
if (err < 0)
|
||||
if (err < 0)
|
||||
{
|
||||
ERROR_LOG(AUDIO, "Cannot set Minimum periods: %s\n", snd_strerror(err));
|
||||
return false;
|
||||
@ -131,34 +131,34 @@ bool AlsaSound::AlsaInit()
|
||||
|
||||
buffer_size_max = BUFFER_SIZE_MAX;
|
||||
err = snd_pcm_hw_params_set_buffer_size_max(handle, hwparams, &buffer_size_max);
|
||||
if (err < 0)
|
||||
if (err < 0)
|
||||
{
|
||||
ERROR_LOG(AUDIO, "Cannot set minimum buffer size: %s\n", snd_strerror(err));
|
||||
return false;
|
||||
}
|
||||
|
||||
err = snd_pcm_hw_params(handle, hwparams);
|
||||
if (err < 0)
|
||||
if (err < 0)
|
||||
{
|
||||
ERROR_LOG(AUDIO, "Unable to install hw params: %s\n", snd_strerror(err));
|
||||
return false;
|
||||
}
|
||||
|
||||
err = snd_pcm_hw_params_get_buffer_size(hwparams, &buffer_size);
|
||||
if (err < 0)
|
||||
if (err < 0)
|
||||
{
|
||||
ERROR_LOG(AUDIO, "Cannot get buffer size: %s\n", snd_strerror(err));
|
||||
return false;
|
||||
}
|
||||
|
||||
err = snd_pcm_hw_params_get_periods_max(hwparams, &periods, &dir);
|
||||
if (err < 0)
|
||||
if (err < 0)
|
||||
{
|
||||
ERROR_LOG(AUDIO, "Cannot get periods: %s\n", snd_strerror(err));
|
||||
return false;
|
||||
}
|
||||
|
||||
//periods is the number of fragments alsa can wait for during one
|
||||
//periods is the number of fragments alsa can wait for during one
|
||||
//buffer_size
|
||||
frames_to_deliver = buffer_size / periods;
|
||||
//limit the minimum size. pulseaudio advertises a minimum of 32 samples.
|
||||
@ -172,28 +172,28 @@ bool AlsaSound::AlsaInit()
|
||||
snd_pcm_sw_params_alloca(&swparams);
|
||||
|
||||
err = snd_pcm_sw_params_current(handle, swparams);
|
||||
if (err < 0)
|
||||
if (err < 0)
|
||||
{
|
||||
ERROR_LOG(AUDIO, "cannot init sw params: %s\n", snd_strerror(err));
|
||||
return false;
|
||||
}
|
||||
|
||||
err = snd_pcm_sw_params_set_start_threshold(handle, swparams, 0U);
|
||||
if (err < 0)
|
||||
if (err < 0)
|
||||
{
|
||||
ERROR_LOG(AUDIO, "cannot set start thresh: %s\n", snd_strerror(err));
|
||||
return false;
|
||||
}
|
||||
|
||||
err = snd_pcm_sw_params(handle, swparams);
|
||||
if (err < 0)
|
||||
if (err < 0)
|
||||
{
|
||||
ERROR_LOG(AUDIO, "cannot set sw params: %s\n", snd_strerror(err));
|
||||
return false;
|
||||
}
|
||||
|
||||
err = snd_pcm_prepare(handle);
|
||||
if (err < 0)
|
||||
if (err < 0)
|
||||
{
|
||||
ERROR_LOG(AUDIO, "Unable to prepare: %s\n", snd_strerror(err));
|
||||
return false;
|
||||
|
@ -28,8 +28,8 @@ public:
|
||||
static bool isValid() {
|
||||
return true;
|
||||
}
|
||||
virtual bool usesMixer() const {
|
||||
return true;
|
||||
virtual bool usesMixer() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void Update();
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "Mixer.h"
|
||||
#include "NullSoundStream.h"
|
||||
#include "DSoundStream.h"
|
||||
#include "XAudio2_7Stream.h"
|
||||
#include "XAudio2Stream.h"
|
||||
#include "AOSoundStream.h"
|
||||
#include "AlsaSoundStream.h"
|
||||
@ -18,34 +19,47 @@
|
||||
#include "../../Core/Src/ConfigManager.h"
|
||||
|
||||
// This shouldn't be a global, at least not here.
|
||||
SoundStream *soundStream;
|
||||
SoundStream *soundStream = nullptr;
|
||||
|
||||
namespace AudioCommon
|
||||
{
|
||||
SoundStream *InitSoundStream(CMixer *mixer, void *hWnd)
|
||||
{
|
||||
SoundStream *InitSoundStream(CMixer *mixer, void *hWnd)
|
||||
{
|
||||
// TODO: possible memleak with mixer
|
||||
|
||||
std::string backend = SConfig::GetInstance().sBackend;
|
||||
if (backend == BACKEND_OPENAL && OpenALStream::isValid())
|
||||
if (backend == BACKEND_OPENAL && OpenALStream::isValid())
|
||||
soundStream = new OpenALStream(mixer);
|
||||
else if (backend == BACKEND_NULLSOUND && NullSound::isValid())
|
||||
soundStream = new NullSound(mixer, hWnd);
|
||||
else if (backend == BACKEND_DIRECTSOUND && DSound::isValid())
|
||||
else if (backend == BACKEND_NULLSOUND && NullSound::isValid())
|
||||
soundStream = new NullSound(mixer);
|
||||
else if (backend == BACKEND_DIRECTSOUND && DSound::isValid())
|
||||
soundStream = new DSound(mixer, hWnd);
|
||||
else if (backend == BACKEND_XAUDIO2 && XAudio2::isValid())
|
||||
soundStream = new XAudio2(mixer);
|
||||
else if (backend == BACKEND_AOSOUND && AOSound::isValid())
|
||||
else if (backend == BACKEND_XAUDIO2)
|
||||
{
|
||||
if (XAudio2::isValid())
|
||||
soundStream = new XAudio2(mixer);
|
||||
else if (XAudio2_7::isValid())
|
||||
soundStream = new XAudio2_7(mixer);
|
||||
}
|
||||
else if (backend == BACKEND_AOSOUND && AOSound::isValid())
|
||||
soundStream = new AOSound(mixer);
|
||||
else if (backend == BACKEND_ALSA && AlsaSound::isValid())
|
||||
soundStream = new AlsaSound(mixer);
|
||||
else if (backend == BACKEND_COREAUDIO && CoreAudioSound::isValid())
|
||||
else if (backend == BACKEND_COREAUDIO && CoreAudioSound::isValid())
|
||||
soundStream = new CoreAudioSound(mixer);
|
||||
else if (backend == BACKEND_PULSEAUDIO && PulseAudio::isValid())
|
||||
soundStream = new PulseAudio(mixer);
|
||||
else if (backend == BACKEND_OPENSLES && OpenSLESStream::isValid())
|
||||
soundStream = new OpenSLESStream(mixer);
|
||||
if (soundStream != NULL)
|
||||
|
||||
if (!soundStream && NullSound::isValid())
|
||||
{
|
||||
WARN_LOG(DSPHLE, "Could not initialize backend %s, using %s instead.",
|
||||
backend.c_str(), BACKEND_NULLSOUND);
|
||||
soundStream = new NullSound(mixer);
|
||||
}
|
||||
|
||||
if (soundStream)
|
||||
{
|
||||
UpdateSoundStream();
|
||||
if (soundStream->Start())
|
||||
@ -61,31 +75,32 @@ namespace AudioCommon
|
||||
}
|
||||
PanicAlertT("Could not initialize backend %s.", backend.c_str());
|
||||
}
|
||||
|
||||
PanicAlertT("Sound backend %s is not valid.", backend.c_str());
|
||||
|
||||
delete soundStream;
|
||||
soundStream = NULL;
|
||||
return NULL;
|
||||
soundStream = nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ShutdownSoundStream()
|
||||
void ShutdownSoundStream()
|
||||
{
|
||||
INFO_LOG(DSPHLE, "Shutting down sound stream");
|
||||
|
||||
if (soundStream)
|
||||
if (soundStream)
|
||||
{
|
||||
soundStream->Stop();
|
||||
if (SConfig::GetInstance().m_DumpAudio)
|
||||
soundStream->GetMixer()->StopLogAudio();
|
||||
//soundStream->StopLogAudio();
|
||||
delete soundStream;
|
||||
soundStream = NULL;
|
||||
soundStream = nullptr;
|
||||
}
|
||||
|
||||
INFO_LOG(DSPHLE, "Done shutting down sound stream");
|
||||
INFO_LOG(DSPHLE, "Done shutting down sound stream");
|
||||
}
|
||||
|
||||
std::vector<std::string> GetSoundBackends()
|
||||
std::vector<std::string> GetSoundBackends()
|
||||
{
|
||||
std::vector<std::string> backends;
|
||||
|
||||
@ -93,7 +108,7 @@ namespace AudioCommon
|
||||
backends.push_back(BACKEND_NULLSOUND);
|
||||
if (DSound::isValid())
|
||||
backends.push_back(BACKEND_DIRECTSOUND);
|
||||
if (XAudio2::isValid())
|
||||
if (XAudio2_7::isValid() || XAudio2::isValid())
|
||||
backends.push_back(BACKEND_XAUDIO2);
|
||||
if (AOSound::isValid())
|
||||
backends.push_back(BACKEND_AOSOUND);
|
||||
@ -110,7 +125,7 @@ namespace AudioCommon
|
||||
return backends;
|
||||
}
|
||||
|
||||
bool UseJIT()
|
||||
bool UseJIT()
|
||||
{
|
||||
if (!Movie::IsDSPHLE() && Movie::IsPlayingInput() && Movie::IsConfigSaved())
|
||||
{
|
||||
|
@ -38,7 +38,7 @@ union UDSPControl
|
||||
UDSPControl(u16 _Hex = 0) : Hex(_Hex) {}
|
||||
};
|
||||
|
||||
namespace AudioCommon
|
||||
namespace AudioCommon
|
||||
{
|
||||
SoundStream *InitSoundStream(CMixer *mixer, void *hWnd);
|
||||
void ShutdownSoundStream();
|
||||
|
@ -14,8 +14,12 @@
|
||||
#include <string.h>
|
||||
#include "DPL2Decoder.h"
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
#ifndef M_SQRT1_2
|
||||
#define M_SQRT1_2 0.70710678118654752440
|
||||
#endif
|
||||
|
||||
int olddelay = -1;
|
||||
unsigned int oldfreq = 0;
|
||||
|
@ -6,7 +6,6 @@
|
||||
#include <functional>
|
||||
|
||||
#include <windows.h>
|
||||
#include <dxerr.h>
|
||||
|
||||
#include "AudioCommon.h"
|
||||
#include "DSoundStream.h"
|
||||
@ -43,7 +42,7 @@ bool DSound::CreateBuffer()
|
||||
else
|
||||
{
|
||||
// Failed.
|
||||
PanicAlertT("Sound buffer creation failed: %s", DXGetErrorString(res));
|
||||
PanicAlertT("Sound buffer creation failed: %08x", res);
|
||||
dsBuffer = NULL;
|
||||
return false;
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "Thread.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
#include <mmsystem.h>
|
||||
#include <dsound.h>
|
||||
|
||||
@ -47,7 +48,7 @@ class DSound : public SoundStream
|
||||
bool WriteDataToBuffer(DWORD dwOffset, char* soundData, DWORD dwSoundBytes);
|
||||
|
||||
public:
|
||||
DSound(CMixer *mixer, void *_hWnd = NULL)
|
||||
DSound(CMixer *mixer, void *_hWnd)
|
||||
: SoundStream(mixer)
|
||||
, bufferSize(0)
|
||||
, currentPos(0)
|
||||
@ -58,7 +59,7 @@ public:
|
||||
{}
|
||||
|
||||
virtual ~DSound() {}
|
||||
|
||||
|
||||
virtual bool Start();
|
||||
virtual void SoundLoop();
|
||||
virtual void SetVolume(int volume);
|
||||
@ -70,7 +71,7 @@ public:
|
||||
|
||||
#else
|
||||
public:
|
||||
DSound(CMixer *mixer, void *hWnd = NULL)
|
||||
DSound(CMixer *mixer, void *_hWnd)
|
||||
: SoundStream(mixer)
|
||||
{}
|
||||
#endif
|
||||
|
@ -52,7 +52,7 @@ unsigned int CMixer::Mix(short* samples, unsigned int numSamples)
|
||||
// interpolation loop.
|
||||
u32 indexR = Common::AtomicLoad(m_indexR);
|
||||
u32 indexW = Common::AtomicLoad(m_indexW);
|
||||
|
||||
|
||||
if (m_AIplaying) {
|
||||
numLeft = (numLeft > numSamples) ? numSamples : numLeft;
|
||||
|
||||
@ -125,8 +125,8 @@ unsigned int CMixer::Mix(short* samples, unsigned int numSamples)
|
||||
*(u32*)(samples+i) = *(u32*)(s);
|
||||
// memset(&samples[numLeft * 2], 0, (numSamples - numLeft) * 4);
|
||||
}
|
||||
|
||||
// Flush cached variable
|
||||
|
||||
// Flush cached variable
|
||||
Common::AtomicStore(m_indexR, indexR);
|
||||
|
||||
//when logging, also throttle HLE audio
|
||||
@ -158,13 +158,13 @@ void CMixer::PushSamples(const short *samples, unsigned int num_samples)
|
||||
// indexR isn't allowed to cache in the audio throttling loop as it
|
||||
// needs to get updates to not deadlock.
|
||||
u32 indexW = Common::AtomicLoad(m_indexW);
|
||||
|
||||
|
||||
if (m_throttle)
|
||||
{
|
||||
// The auto throttle function. This loop will put a ceiling on the CPU MHz.
|
||||
while (num_samples * 2 + ((indexW - Common::AtomicLoad(m_indexR)) & INDEX_MASK) >= MAX_SAMPLES * 2)
|
||||
{
|
||||
if (*PowerPC::GetStatePtr() != PowerPC::CPU_RUNNING || soundStream->IsMuted())
|
||||
if (*PowerPC::GetStatePtr() != PowerPC::CPU_RUNNING || soundStream->IsMuted())
|
||||
break;
|
||||
// Shortcut key for Throttle Skipping
|
||||
if (Host_GetKeyState('\t'))
|
||||
@ -192,9 +192,9 @@ void CMixer::PushSamples(const short *samples, unsigned int num_samples)
|
||||
{
|
||||
memcpy(&m_buffer[indexW & INDEX_MASK], samples, num_samples * 4);
|
||||
}
|
||||
|
||||
|
||||
Common::AtomicAdd(m_indexW, num_samples * 2);
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -206,11 +206,11 @@ unsigned int CMixer::GetNumSamples()
|
||||
// We also can't say the current interpolation state (specially
|
||||
// the frac), so to be sure, subtract one again to be sure not
|
||||
// to underflow the fifo.
|
||||
|
||||
|
||||
u32 numSamples = ((Common::AtomicLoad(m_indexW) - Common::AtomicLoad(m_indexR)) & INDEX_MASK) / 2;
|
||||
|
||||
if (AudioInterface::GetAIDSampleRate() == m_sampleRate)
|
||||
numSamples = numSamples; // 1:1
|
||||
; //numSamples = numSamples; // 1:1
|
||||
else if (m_sampleRate == 48000 && AudioInterface::GetAIDSampleRate() == 32000)
|
||||
numSamples = numSamples * 3 / 2 - 2; // most common case
|
||||
else
|
||||
|
@ -14,7 +14,7 @@
|
||||
#define RESERVED_SAMPLES (256)
|
||||
|
||||
class CMixer {
|
||||
|
||||
|
||||
public:
|
||||
CMixer(unsigned int AISampleRate = 48000, unsigned int DACSampleRate = 48000, unsigned int BackendSampleRate = 32000)
|
||||
: m_aiSampleRate(AISampleRate)
|
||||
@ -89,7 +89,7 @@ protected:
|
||||
int m_channels;
|
||||
|
||||
WaveFileWriter g_wave_writer;
|
||||
|
||||
|
||||
bool m_HLEready;
|
||||
bool m_logAudio;
|
||||
|
||||
|
@ -2,7 +2,6 @@
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "AudioCommon.h"
|
||||
#include "NullSoundStream.h"
|
||||
#include "../../Core/Src/HW/SystemTimers.h"
|
||||
#include "../../Core/Src/HW/AudioInterface.h"
|
||||
|
@ -5,8 +5,8 @@
|
||||
#ifndef _NULLSOUNDSTREAM_H_
|
||||
#define _NULLSOUNDSTREAM_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "SoundStream.h"
|
||||
#include "Thread.h"
|
||||
|
||||
#define BUF_SIZE (48000 * 4 / 32)
|
||||
|
||||
@ -16,7 +16,7 @@ class NullSound : public SoundStream
|
||||
short realtimeBuffer[BUF_SIZE / sizeof(short)];
|
||||
|
||||
public:
|
||||
NullSound(CMixer *mixer, void *hWnd = NULL)
|
||||
NullSound(CMixer *mixer)
|
||||
: SoundStream(mixer)
|
||||
{}
|
||||
|
||||
|
@ -5,7 +5,6 @@
|
||||
#ifndef _OPENALSTREAM_H_
|
||||
#define _OPENALSTREAM_H_
|
||||
|
||||
#include "Common.h"
|
||||
#include "SoundStream.h"
|
||||
#include "Thread.h"
|
||||
|
||||
@ -49,9 +48,9 @@ public:
|
||||
OpenALStream(CMixer *mixer, void *hWnd = NULL)
|
||||
: SoundStream(mixer)
|
||||
, uiSource(0)
|
||||
{};
|
||||
{}
|
||||
|
||||
virtual ~OpenALStream() {};
|
||||
virtual ~OpenALStream() {}
|
||||
|
||||
virtual bool Start();
|
||||
virtual void SoundLoop();
|
||||
@ -75,7 +74,9 @@ private:
|
||||
u8 numBuffers;
|
||||
#else
|
||||
public:
|
||||
OpenALStream(CMixer *mixer, void *hWnd = NULL): SoundStream(mixer) {}
|
||||
OpenALStream(CMixer *mixer)
|
||||
: SoundStream(mixer)
|
||||
{}
|
||||
#endif // HAVE_OPENAL
|
||||
};
|
||||
|
||||
|
@ -21,7 +21,7 @@ static SLPlayItf bqPlayerPlay;
|
||||
static SLAndroidSimpleBufferQueueItf bqPlayerBufferQueue;
|
||||
static SLMuteSoloItf bqPlayerMuteSolo;
|
||||
static SLVolumeItf bqPlayerVolume;
|
||||
static CMixer *g_mixer;
|
||||
static CMixer *g_mixer;
|
||||
#define BUFFER_SIZE 512
|
||||
#define BUFFER_SIZE_IN_SAMPLES (BUFFER_SIZE / 2)
|
||||
|
||||
|
@ -24,7 +24,7 @@ public:
|
||||
PulseAudio(CMixer *mixer);
|
||||
|
||||
virtual bool Start();
|
||||
virtual void Stop();
|
||||
virtual void Stop();
|
||||
|
||||
static bool isValid() {return true;}
|
||||
|
||||
|
@ -21,11 +21,11 @@ protected:
|
||||
WaveFileWriter g_wave_writer;
|
||||
bool m_muted;
|
||||
|
||||
public:
|
||||
SoundStream(CMixer *mixer) : m_mixer(mixer), threadData(0), m_logAudio(false), m_muted(false) {}
|
||||
virtual ~SoundStream() { delete m_mixer;}
|
||||
public:
|
||||
SoundStream(CMixer *mixer) : m_mixer(mixer), threadData(0), m_logAudio(false), m_muted(false) {}
|
||||
virtual ~SoundStream() { delete m_mixer; }
|
||||
|
||||
static bool isValid() { return false; }
|
||||
static bool isValid() { return false; }
|
||||
virtual CMixer *GetMixer() const { return m_mixer; }
|
||||
virtual bool Start() { return false; }
|
||||
virtual void SetVolume(int) {}
|
||||
|
@ -121,7 +121,7 @@ void WaveFileWriter::AddStereoSamplesBE(const short *sample_data, u32 count)
|
||||
if (count > BUF_SIZE * 2)
|
||||
PanicAlert("WaveFileWriter - buffer too small (count = %u).", count);
|
||||
|
||||
if (skip_silence)
|
||||
if (skip_silence)
|
||||
{
|
||||
bool all_zero = true;
|
||||
|
||||
|
@ -2,9 +2,42 @@
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <xaudio2.h>
|
||||
#include "AudioCommon.h"
|
||||
#include "XAudio2Stream.h"
|
||||
|
||||
#ifndef XAUDIO2_DLL
|
||||
#error You are building this module against the wrong version of DirectX. You probably need to remove DXSDK_DIR from your include path.
|
||||
#endif
|
||||
|
||||
struct StreamingVoiceContext : public IXAudio2VoiceCallback
|
||||
{
|
||||
private:
|
||||
CMixer* const m_mixer;
|
||||
Common::Event& m_sound_sync_event;
|
||||
IXAudio2SourceVoice* m_source_voice;
|
||||
std::unique_ptr<BYTE[]> xaudio_buffer;
|
||||
|
||||
void SubmitBuffer(PBYTE buf_data);
|
||||
|
||||
public:
|
||||
StreamingVoiceContext(IXAudio2 *pXAudio2, CMixer *pMixer, Common::Event& pSyncEvent);
|
||||
|
||||
~StreamingVoiceContext();
|
||||
|
||||
void StreamingVoiceContext::Stop();
|
||||
void StreamingVoiceContext::Play();
|
||||
|
||||
STDMETHOD_(void, OnVoiceError) (THIS_ void* pBufferContext, HRESULT Error) {}
|
||||
STDMETHOD_(void, OnVoiceProcessingPassStart) (UINT32) {}
|
||||
STDMETHOD_(void, OnVoiceProcessingPassEnd) () {}
|
||||
STDMETHOD_(void, OnBufferStart) (void*) {}
|
||||
STDMETHOD_(void, OnLoopEnd) (void*) {}
|
||||
STDMETHOD_(void, OnStreamEnd) () {}
|
||||
|
||||
STDMETHOD_(void, OnBufferEnd) (void* context);
|
||||
};
|
||||
|
||||
const int NUM_BUFFERS = 3;
|
||||
const int SAMPLES_PER_BUFFER = 96;
|
||||
|
||||
@ -90,13 +123,59 @@ void StreamingVoiceContext::OnBufferEnd(void* context)
|
||||
SubmitBuffer(static_cast<BYTE*>(context));
|
||||
}
|
||||
|
||||
HMODULE XAudio2::m_xaudio2_dll = nullptr;
|
||||
typedef decltype(&XAudio2Create) XAudio2Create_t;
|
||||
void *XAudio2::PXAudio2Create = nullptr;
|
||||
|
||||
bool XAudio2::InitLibrary()
|
||||
{
|
||||
if (m_xaudio2_dll)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
m_xaudio2_dll = ::LoadLibrary(XAUDIO2_DLL);
|
||||
if (!m_xaudio2_dll)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!PXAudio2Create)
|
||||
{
|
||||
PXAudio2Create = (XAudio2Create_t)::GetProcAddress(m_xaudio2_dll, "XAudio2Create");
|
||||
if (!PXAudio2Create)
|
||||
{
|
||||
::FreeLibrary(m_xaudio2_dll);
|
||||
m_xaudio2_dll = nullptr;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
XAudio2::XAudio2(CMixer *mixer)
|
||||
: SoundStream(mixer)
|
||||
, m_mastering_voice(nullptr)
|
||||
, m_volume(1.0f)
|
||||
, m_cleanup_com(SUCCEEDED(CoInitializeEx(NULL, COINIT_MULTITHREADED)))
|
||||
{
|
||||
}
|
||||
|
||||
XAudio2::~XAudio2()
|
||||
{
|
||||
Stop();
|
||||
if (m_cleanup_com)
|
||||
CoUninitialize();
|
||||
}
|
||||
|
||||
bool XAudio2::Start()
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
// callback doesn't seem to run on a specific cpu anyways
|
||||
IXAudio2* xaudptr;
|
||||
if (FAILED(hr = XAudio2Create(&xaudptr, 0, XAUDIO2_DEFAULT_PROCESSOR)))
|
||||
if (FAILED(hr = ((XAudio2Create_t)PXAudio2Create)(&xaudptr, 0, XAUDIO2_DEFAULT_PROCESSOR)))
|
||||
{
|
||||
PanicAlertT("XAudio2 init failed: %#X", hr);
|
||||
Stop();
|
||||
@ -172,4 +251,11 @@ void XAudio2::Stop()
|
||||
}
|
||||
|
||||
m_xaudio2.reset(); // release interface
|
||||
|
||||
if (m_xaudio2_dll)
|
||||
{
|
||||
::FreeLibrary(m_xaudio2_dll);
|
||||
m_xaudio2_dll = nullptr;
|
||||
PXAudio2Create = nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -2,43 +2,21 @@
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#ifndef _XAUDIO2STREAM_H_
|
||||
#define _XAUDIO2STREAM_H_
|
||||
// This audio backend uses XAudio2 via XAUDIO2_DLL
|
||||
// It works on Windows 8+, where it is included as an OS component.
|
||||
// This backend is always compiled, but only available if running on Win8+
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include "Thread.h"
|
||||
#include "SoundStream.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "Thread.h"
|
||||
#include <xaudio2.h>
|
||||
#include <memory>
|
||||
|
||||
struct StreamingVoiceContext : public IXAudio2VoiceCallback
|
||||
{
|
||||
private:
|
||||
CMixer* const m_mixer;
|
||||
Common::Event& m_sound_sync_event;
|
||||
IXAudio2SourceVoice* m_source_voice;
|
||||
std::unique_ptr<BYTE[]> xaudio_buffer;
|
||||
|
||||
void SubmitBuffer(PBYTE buf_data);
|
||||
|
||||
public:
|
||||
StreamingVoiceContext(IXAudio2 *pXAudio2, CMixer *pMixer, Common::Event& pSyncEvent);
|
||||
|
||||
~StreamingVoiceContext();
|
||||
|
||||
void StreamingVoiceContext::Stop();
|
||||
void StreamingVoiceContext::Play();
|
||||
|
||||
STDMETHOD_(void, OnVoiceError) (THIS_ void* pBufferContext, HRESULT Error) {}
|
||||
STDMETHOD_(void, OnVoiceProcessingPassStart) (UINT32) {}
|
||||
STDMETHOD_(void, OnVoiceProcessingPassEnd) () {}
|
||||
STDMETHOD_(void, OnBufferStart) (void*) {}
|
||||
STDMETHOD_(void, OnLoopEnd) (void*) {}
|
||||
STDMETHOD_(void, OnStreamEnd) () {}
|
||||
|
||||
STDMETHOD_(void, OnBufferEnd) (void* context);
|
||||
};
|
||||
struct StreamingVoiceContext;
|
||||
struct IXAudio2;
|
||||
struct IXAudio2MasteringVoice;
|
||||
|
||||
#endif
|
||||
|
||||
@ -46,6 +24,7 @@ class XAudio2 : public SoundStream
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
||||
private:
|
||||
class Releaser
|
||||
{
|
||||
public:
|
||||
@ -56,7 +35,6 @@ class XAudio2 : public SoundStream
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
std::unique_ptr<IXAudio2, Releaser> m_xaudio2;
|
||||
std::unique_ptr<StreamingVoiceContext> m_voice_context;
|
||||
IXAudio2MasteringVoice *m_mastering_voice;
|
||||
@ -66,21 +44,15 @@ private:
|
||||
|
||||
const bool m_cleanup_com;
|
||||
|
||||
public:
|
||||
XAudio2(CMixer *mixer)
|
||||
: SoundStream(mixer)
|
||||
, m_mastering_voice(nullptr)
|
||||
, m_volume(1.0f)
|
||||
, m_cleanup_com(SUCCEEDED(CoInitializeEx(NULL, COINIT_MULTITHREADED)))
|
||||
{}
|
||||
static HMODULE m_xaudio2_dll;
|
||||
static void *PXAudio2Create;
|
||||
|
||||
static bool InitLibrary();
|
||||
|
||||
public:
|
||||
XAudio2(CMixer *mixer);
|
||||
virtual ~XAudio2();
|
||||
|
||||
virtual ~XAudio2()
|
||||
{
|
||||
Stop();
|
||||
if (m_cleanup_com)
|
||||
CoUninitialize();
|
||||
}
|
||||
|
||||
virtual bool Start();
|
||||
virtual void Stop();
|
||||
|
||||
@ -89,15 +61,14 @@ public:
|
||||
virtual void SetVolume(int volume);
|
||||
virtual bool usesMixer() const { return true; }
|
||||
|
||||
static bool isValid() { return true; }
|
||||
static bool isValid() { return InitLibrary(); }
|
||||
|
||||
#else
|
||||
|
||||
public:
|
||||
XAudio2(CMixer *mixer, void *hWnd = NULL)
|
||||
XAudio2(CMixer *mixer)
|
||||
: SoundStream(mixer)
|
||||
{}
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif //_XAUDIO2STREAM_H_
|
||||
|
289
Source/Core/AudioCommon/Src/XAudio2_7Stream.cpp
Normal file
@ -0,0 +1,289 @@
|
||||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
// Note that this file *and this file only* must also have %DXSDK_DIR%/Include prepended
|
||||
// to its include path in order fetch dxsdkver.h and XAudio2.h from the DXSDK
|
||||
// instead of other possible places. This may be accomplished by adding the path to
|
||||
// the AdditionalIncludeDirectories for this file via msbuild.
|
||||
|
||||
#include "AudioCommon.h"
|
||||
#include "XAudio2_7Stream.h"
|
||||
|
||||
#ifdef HAVE_DXSDK
|
||||
#include <dxsdkver.h>
|
||||
#if (_DXSDK_PRODUCT_MAJOR == 9) && (_DXSDK_PRODUCT_MINOR == 29) && (_DXSDK_BUILD_MAJOR == 1962) && (_DXSDK_BUILD_MINOR == 0)
|
||||
#define HAVE_DXSDK_JUNE_2010
|
||||
#else
|
||||
#pragma message("You have DirectX SDK installed, but it is not the expected version (June 2010). Update it to build this module.")
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DXSDK_JUNE_2010
|
||||
|
||||
#include <XAudio2.h>
|
||||
|
||||
struct StreamingVoiceContext2_7 : public IXAudio2VoiceCallback
|
||||
{
|
||||
private:
|
||||
CMixer* const m_mixer;
|
||||
Common::Event& m_sound_sync_event;
|
||||
IXAudio2SourceVoice* m_source_voice;
|
||||
std::unique_ptr<BYTE[]> xaudio_buffer;
|
||||
|
||||
void SubmitBuffer(PBYTE buf_data);
|
||||
|
||||
public:
|
||||
StreamingVoiceContext2_7(IXAudio2 *pXAudio2, CMixer *pMixer, Common::Event& pSyncEvent);
|
||||
|
||||
~StreamingVoiceContext2_7();
|
||||
|
||||
void StreamingVoiceContext2_7::Stop();
|
||||
void StreamingVoiceContext2_7::Play();
|
||||
|
||||
STDMETHOD_(void, OnVoiceError) (THIS_ void* pBufferContext, HRESULT Error) {}
|
||||
STDMETHOD_(void, OnVoiceProcessingPassStart) (UINT32) {}
|
||||
STDMETHOD_(void, OnVoiceProcessingPassEnd) () {}
|
||||
STDMETHOD_(void, OnBufferStart) (void*) {}
|
||||
STDMETHOD_(void, OnLoopEnd) (void*) {}
|
||||
STDMETHOD_(void, OnStreamEnd) () {}
|
||||
|
||||
STDMETHOD_(void, OnBufferEnd) (void* context);
|
||||
};
|
||||
|
||||
const int NUM_BUFFERS = 3;
|
||||
const int SAMPLES_PER_BUFFER = 96;
|
||||
|
||||
const int NUM_CHANNELS = 2;
|
||||
const int BUFFER_SIZE = SAMPLES_PER_BUFFER * NUM_CHANNELS;
|
||||
const int BUFFER_SIZE_BYTES = BUFFER_SIZE * sizeof(s16);
|
||||
|
||||
void StreamingVoiceContext2_7::SubmitBuffer(PBYTE buf_data)
|
||||
{
|
||||
XAUDIO2_BUFFER buf = {};
|
||||
buf.AudioBytes = BUFFER_SIZE_BYTES;
|
||||
buf.pContext = buf_data;
|
||||
buf.pAudioData = buf_data;
|
||||
|
||||
m_source_voice->SubmitSourceBuffer(&buf);
|
||||
}
|
||||
|
||||
StreamingVoiceContext2_7::StreamingVoiceContext2_7(IXAudio2 *pXAudio2, CMixer *pMixer, Common::Event& pSyncEvent)
|
||||
: m_mixer(pMixer)
|
||||
, m_sound_sync_event(pSyncEvent)
|
||||
, xaudio_buffer(new BYTE[NUM_BUFFERS * BUFFER_SIZE_BYTES]())
|
||||
{
|
||||
WAVEFORMATEXTENSIBLE wfx = {};
|
||||
|
||||
wfx.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
|
||||
wfx.Format.nSamplesPerSec = m_mixer->GetSampleRate();
|
||||
wfx.Format.nChannels = 2;
|
||||
wfx.Format.wBitsPerSample = 16;
|
||||
wfx.Format.nBlockAlign = wfx.Format.nChannels*wfx.Format.wBitsPerSample / 8;
|
||||
wfx.Format.nAvgBytesPerSec = wfx.Format.nSamplesPerSec * wfx.Format.nBlockAlign;
|
||||
wfx.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
|
||||
wfx.Samples.wValidBitsPerSample = 16;
|
||||
wfx.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
|
||||
wfx.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
|
||||
|
||||
// create source voice
|
||||
HRESULT hr;
|
||||
if (FAILED(hr = pXAudio2->CreateSourceVoice(&m_source_voice, &wfx.Format, XAUDIO2_VOICE_NOSRC, 1.0f, this)))
|
||||
{
|
||||
PanicAlertT("XAudio2_7 CreateSourceVoice failed: %#X", hr);
|
||||
return;
|
||||
}
|
||||
|
||||
m_source_voice->Start();
|
||||
|
||||
// start buffers with silence
|
||||
for (int i = 0; i != NUM_BUFFERS; ++i)
|
||||
SubmitBuffer(xaudio_buffer.get() + (i * BUFFER_SIZE_BYTES));
|
||||
}
|
||||
|
||||
StreamingVoiceContext2_7::~StreamingVoiceContext2_7()
|
||||
{
|
||||
if (m_source_voice)
|
||||
{
|
||||
m_source_voice->Stop();
|
||||
m_source_voice->DestroyVoice();
|
||||
}
|
||||
}
|
||||
|
||||
void StreamingVoiceContext2_7::Stop()
|
||||
{
|
||||
if (m_source_voice)
|
||||
m_source_voice->Stop();
|
||||
}
|
||||
|
||||
void StreamingVoiceContext2_7::Play()
|
||||
{
|
||||
if (m_source_voice)
|
||||
m_source_voice->Start();
|
||||
}
|
||||
|
||||
void StreamingVoiceContext2_7::OnBufferEnd(void* context)
|
||||
{
|
||||
// buffer end callback; gets SAMPLES_PER_BUFFER samples for a new buffer
|
||||
|
||||
if (!m_source_voice || !context)
|
||||
return;
|
||||
|
||||
//m_sound_sync_event->Wait(); // sync
|
||||
//m_sound_sync_event->Spin(); // or tight sync
|
||||
|
||||
m_mixer->Mix(static_cast<short*>(context), SAMPLES_PER_BUFFER);
|
||||
SubmitBuffer(static_cast<BYTE*>(context));
|
||||
}
|
||||
|
||||
HMODULE XAudio2_7::m_xaudio2_dll = nullptr;
|
||||
|
||||
void XAudio2_7::ReleaseIXAudio2(IXAudio2* ptr)
|
||||
{
|
||||
ptr->Release();
|
||||
}
|
||||
|
||||
bool XAudio2_7::InitLibrary()
|
||||
{
|
||||
if (m_xaudio2_dll)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
m_xaudio2_dll = ::LoadLibrary(TEXT("xaudio2_7.dll"));
|
||||
|
||||
return m_xaudio2_dll != nullptr;
|
||||
}
|
||||
|
||||
XAudio2_7::XAudio2_7(CMixer *mixer)
|
||||
: SoundStream(mixer)
|
||||
, m_mastering_voice(nullptr)
|
||||
, m_volume(1.0f)
|
||||
, m_cleanup_com(SUCCEEDED(CoInitializeEx(NULL, COINIT_MULTITHREADED)))
|
||||
{
|
||||
}
|
||||
|
||||
XAudio2_7::~XAudio2_7()
|
||||
{
|
||||
Stop();
|
||||
if (m_cleanup_com)
|
||||
CoUninitialize();
|
||||
}
|
||||
|
||||
bool XAudio2_7::Start()
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
// callback doesn't seem to run on a specific cpu anyways
|
||||
IXAudio2* xaudptr;
|
||||
if (FAILED(hr = XAudio2Create(&xaudptr, 0, XAUDIO2_DEFAULT_PROCESSOR)))
|
||||
{
|
||||
PanicAlertT("XAudio2_7 init failed: %#X", hr);
|
||||
Stop();
|
||||
return false;
|
||||
}
|
||||
m_xaudio2 = std::unique_ptr<IXAudio2, Releaser>(xaudptr);
|
||||
|
||||
// XAudio2 master voice
|
||||
// XAUDIO2_DEFAULT_CHANNELS instead of 2 for expansion?
|
||||
if (FAILED(hr = m_xaudio2->CreateMasteringVoice(&m_mastering_voice, 2, m_mixer->GetSampleRate())))
|
||||
{
|
||||
PanicAlertT("XAudio2_7 master voice creation failed: %#X", hr);
|
||||
Stop();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Volume
|
||||
m_mastering_voice->SetVolume(m_volume);
|
||||
|
||||
m_voice_context = std::unique_ptr<StreamingVoiceContext2_7>
|
||||
(new StreamingVoiceContext2_7(m_xaudio2.get(), m_mixer, m_sound_sync_event));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void XAudio2_7::SetVolume(int volume)
|
||||
{
|
||||
//linear 1- .01
|
||||
m_volume = (float)volume / 100.f;
|
||||
|
||||
if (m_mastering_voice)
|
||||
m_mastering_voice->SetVolume(m_volume);
|
||||
}
|
||||
|
||||
void XAudio2_7::Update()
|
||||
{
|
||||
//m_sound_sync_event.Set();
|
||||
|
||||
//static int xi = 0;
|
||||
//if (100000 == ++xi)
|
||||
//{
|
||||
// xi = 0;
|
||||
// XAUDIO2_PERFORMANCE_DATA perfData;
|
||||
// pXAudio2->GetPerformanceData(&perfData);
|
||||
// NOTICE_LOG(DSPHLE, "XAudio2_7 latency (samples): %i", perfData.CurrentLatencyInSamples);
|
||||
// NOTICE_LOG(DSPHLE, "XAudio2_7 total glitches: %i", perfData.GlitchesSinceEngineStarted);
|
||||
//}
|
||||
}
|
||||
|
||||
void XAudio2_7::Clear(bool mute)
|
||||
{
|
||||
m_muted = mute;
|
||||
|
||||
if (m_voice_context)
|
||||
{
|
||||
if (m_muted)
|
||||
m_voice_context->Stop();
|
||||
else
|
||||
m_voice_context->Play();
|
||||
}
|
||||
}
|
||||
|
||||
void XAudio2_7::Stop()
|
||||
{
|
||||
//m_sound_sync_event.Set();
|
||||
|
||||
m_voice_context.reset();
|
||||
|
||||
if (m_mastering_voice)
|
||||
{
|
||||
m_mastering_voice->DestroyVoice();
|
||||
m_mastering_voice = nullptr;
|
||||
}
|
||||
|
||||
m_xaudio2.reset(); // release interface
|
||||
|
||||
if (m_xaudio2_dll)
|
||||
{
|
||||
::FreeLibrary(m_xaudio2_dll);
|
||||
m_xaudio2_dll = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool XAudio2_7::usesMixer() const { return true; }
|
||||
|
||||
#else
|
||||
|
||||
struct StreamingVoiceContext2_7 {};
|
||||
struct IXAudio2 {};
|
||||
struct IXAudio2MasteringVoice {};
|
||||
void XAudio2_7::ReleaseIXAudio2(IXAudio2* ptr) {}
|
||||
|
||||
XAudio2_7::XAudio2_7(CMixer *mixer)
|
||||
: SoundStream(mixer)
|
||||
, m_mastering_voice(nullptr)
|
||||
, m_volume(1.0f)
|
||||
, m_cleanup_com(false)
|
||||
{}
|
||||
|
||||
XAudio2_7::~XAudio2_7() {}
|
||||
|
||||
bool XAudio2_7::Start() { return SoundStream::Start(); }
|
||||
void XAudio2_7::Stop() {}
|
||||
void XAudio2_7::Update() {}
|
||||
void XAudio2_7::Clear(bool mute) {}
|
||||
void XAudio2_7::SetVolume(int volume) {}
|
||||
bool XAudio2_7::usesMixer() const { return false; }
|
||||
bool XAudio2_7::InitLibrary() { return false; }
|
||||
|
||||
#endif
|
81
Source/Core/AudioCommon/Src/XAudio2_7Stream.h
Normal file
@ -0,0 +1,81 @@
|
||||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
// This audio backend uses XAudio2 via XAudio2_7.dll
|
||||
// This version of the library is included in the June 2010 DirectX SDK and
|
||||
// works on all versions of Windows, however the SDK and/or redist must be
|
||||
// seperately installed.
|
||||
// Therefore this backend is available iff:
|
||||
// * SDK is available at compile-time
|
||||
// * runtime dll is available at runtime
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include "Thread.h"
|
||||
#include "SoundStream.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
struct StreamingVoiceContext2_7;
|
||||
struct IXAudio2;
|
||||
struct IXAudio2MasteringVoice;
|
||||
|
||||
#endif
|
||||
|
||||
class XAudio2_7 : public SoundStream
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
||||
private:
|
||||
static void ReleaseIXAudio2(IXAudio2 *ptr);
|
||||
|
||||
class Releaser
|
||||
{
|
||||
public:
|
||||
template <typename R>
|
||||
void operator()(R *ptr)
|
||||
{
|
||||
ReleaseIXAudio2(ptr);
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<IXAudio2, Releaser> m_xaudio2;
|
||||
std::unique_ptr<StreamingVoiceContext2_7> m_voice_context;
|
||||
IXAudio2MasteringVoice *m_mastering_voice;
|
||||
|
||||
Common::Event m_sound_sync_event;
|
||||
float m_volume;
|
||||
|
||||
const bool m_cleanup_com;
|
||||
|
||||
static HMODULE m_xaudio2_dll;
|
||||
|
||||
static bool InitLibrary();
|
||||
|
||||
public:
|
||||
XAudio2_7(CMixer *mixer);
|
||||
virtual ~XAudio2_7();
|
||||
|
||||
virtual bool Start();
|
||||
virtual void Stop();
|
||||
|
||||
virtual void Update();
|
||||
virtual void Clear(bool mute);
|
||||
virtual void SetVolume(int volume);
|
||||
virtual bool usesMixer() const;
|
||||
|
||||
static bool isValid() { return InitLibrary(); }
|
||||
|
||||
#else
|
||||
|
||||
public:
|
||||
XAudio2_7(CMixer *mixer)
|
||||
: SoundStream(mixer)
|
||||
{}
|
||||
|
||||
#endif
|
||||
};
|
@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright (c) 2006, Creative Labs Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
* that the following conditions are met:
|
||||
*
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
|
||||
* the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
|
||||
* and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of Creative Labs Inc. nor the names of its contributors may be used to endorse or
|
||||
* promote products derived from this software without specific prior written permission.
|
||||
*
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
@ -36,7 +36,7 @@
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
/*
|
||||
* Init call
|
||||
*/
|
||||
ALDeviceList::ALDeviceList()
|
||||
@ -61,30 +61,30 @@ ALDeviceList::ALDeviceList()
|
||||
defaultDeviceName = (char *)alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER);
|
||||
index = 0;
|
||||
// go through device list (each device terminated with a single NULL, list terminated with double NULL)
|
||||
while (devices != NULL && strlen(devices) > 0)
|
||||
while (devices != NULL && strlen(devices) > 0)
|
||||
{
|
||||
if (strcmp(defaultDeviceName, devices) == 0)
|
||||
if (strcmp(defaultDeviceName, devices) == 0)
|
||||
{
|
||||
defaultDeviceIndex = index;
|
||||
}
|
||||
ALCdevice *device = alcOpenDevice(devices);
|
||||
if (device)
|
||||
if (device)
|
||||
{
|
||||
ALCcontext *context = alcCreateContext(device, NULL);
|
||||
if (context)
|
||||
if (context)
|
||||
{
|
||||
alcMakeContextCurrent(context);
|
||||
// if new actual device name isn't already in the list, then add it...
|
||||
actualDeviceName = alcGetString(device, ALC_DEVICE_SPECIFIER);
|
||||
bool bNewName = true;
|
||||
for (s32 i = 0; i < GetNumDevices(); i++)
|
||||
for (s32 i = 0; i < GetNumDevices(); i++)
|
||||
{
|
||||
if (strcmp(GetDeviceName(i), actualDeviceName) == 0)
|
||||
if (strcmp(GetDeviceName(i), actualDeviceName) == 0)
|
||||
{
|
||||
bNewName = false;
|
||||
}
|
||||
}
|
||||
if ((bNewName) && (actualDeviceName != NULL) && (strlen(actualDeviceName) > 0))
|
||||
if ((bNewName) && (actualDeviceName != NULL) && (strlen(actualDeviceName) > 0))
|
||||
{
|
||||
ALDeviceInfo.bSelected = true;
|
||||
ALDeviceInfo.strDeviceName = actualDeviceName;
|
||||
@ -107,7 +107,7 @@ ALDeviceList::ALDeviceList()
|
||||
ALDeviceInfo.pvstrExtensions->push_back("AL_EXT_LINEAR_DISTANCE");
|
||||
if (alIsExtensionPresent("AL_EXT_EXPONENT_DISTANCE") == AL_TRUE)
|
||||
ALDeviceInfo.pvstrExtensions->push_back("AL_EXT_EXPONENT_DISTANCE");
|
||||
|
||||
|
||||
if (alIsExtensionPresent("EAX2.0") == AL_TRUE)
|
||||
ALDeviceInfo.pvstrExtensions->push_back("EAX2.0");
|
||||
if (alIsExtensionPresent("EAX3.0") == AL_TRUE)
|
||||
@ -139,15 +139,15 @@ ALDeviceList::ALDeviceList()
|
||||
ResetFilters();
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* Exit call
|
||||
*/
|
||||
ALDeviceList::~ALDeviceList()
|
||||
{
|
||||
for (u32 i = 0; i < vDeviceInfo.size(); i++) {
|
||||
if (vDeviceInfo[i].pvstrExtensions) {
|
||||
vDeviceInfo[i].pvstrExtensions->clear();
|
||||
delete vDeviceInfo[i].pvstrExtensions;
|
||||
for (auto& di : vDeviceInfo) {
|
||||
if (di.pvstrExtensions) {
|
||||
di.pvstrExtensions->clear();
|
||||
delete di.pvstrExtensions;
|
||||
}
|
||||
}
|
||||
|
||||
@ -159,10 +159,10 @@ ALDeviceList::~ALDeviceList()
|
||||
*/
|
||||
s32 ALDeviceList::GetNumDevices()
|
||||
{
|
||||
return (s32)vDeviceInfo.size();
|
||||
return (s32)vDeviceInfo.size();
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* Returns the device name at an index in the complete device list
|
||||
*/
|
||||
char * ALDeviceList::GetDeviceName(s32 index)
|
||||
@ -206,11 +206,11 @@ bool ALDeviceList::IsExtensionSupported(s32 index, char *szExtName)
|
||||
bool bReturn = false;
|
||||
|
||||
if (index < GetNumDevices()) {
|
||||
for (u32 i = 0; i < vDeviceInfo[index].pvstrExtensions->size(); i++) {
|
||||
if (!strcasecmp(vDeviceInfo[index].pvstrExtensions->at(i).c_str(), szExtName)) {
|
||||
for (auto& ext : *vDeviceInfo[index].pvstrExtensions) {
|
||||
if (!strcasecmp(ext.c_str(), szExtName)) {
|
||||
bReturn = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -225,7 +225,7 @@ s32 ALDeviceList::GetDefaultDevice()
|
||||
return defaultDeviceIndex;
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* Deselects devices which don't have the specified minimum version
|
||||
*/
|
||||
void ALDeviceList::FilterDevicesMinVer(s32 major, s32 minor)
|
||||
@ -239,7 +239,7 @@ void ALDeviceList::FilterDevicesMinVer(s32 major, s32 minor)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* Deselects devices which don't have the specified maximum version
|
||||
*/
|
||||
void ALDeviceList::FilterDevicesMaxVer(s32 major, s32 minor)
|
||||
@ -260,16 +260,16 @@ void ALDeviceList::FilterDevicesExtension(char *szExtName)
|
||||
{
|
||||
bool bFound;
|
||||
|
||||
for (u32 i = 0; i < vDeviceInfo.size(); i++) {
|
||||
for (auto& di : vDeviceInfo) {
|
||||
bFound = false;
|
||||
for (u32 j = 0; j < vDeviceInfo[i].pvstrExtensions->size(); j++) {
|
||||
if (!strcasecmp(vDeviceInfo[i].pvstrExtensions->at(j).c_str(), szExtName)) {
|
||||
for (auto& ext : *di.pvstrExtensions) {
|
||||
if (!strcasecmp(ext.c_str(), szExtName)) {
|
||||
bFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!bFound)
|
||||
vDeviceInfo[i].bSelected = false;
|
||||
di.bSelected = false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -339,9 +339,9 @@ u32 ALDeviceList::GetMaxNumSources()
|
||||
alDeleteSources(iSourceCount, uiSources);
|
||||
if (alGetError() != AL_NO_ERROR)
|
||||
{
|
||||
for (u32 i = 0; i < 256; i++)
|
||||
for (auto& uiSource : uiSources)
|
||||
{
|
||||
alDeleteSources(1, &uiSources[i]);
|
||||
alDeleteSources(1, &uiSource);
|
||||
}
|
||||
}
|
||||
|
||||
|
17
Source/Core/AudioCommon/Src/stdafx.h
Normal file
@ -0,0 +1,17 @@
|
||||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
/*
|
||||
#ifdef HAVE_DXSDK_JUNE_2010
|
||||
#define _WIN32_WINNT 0x501
|
||||
#else
|
||||
#pragma message("Resulting binary will be compatible with DirectX >= Windows 8. Install the June 2010 DirectX SDK if you want to build for older environments.")
|
||||
#define _WIN32_WINNT 0x602
|
||||
#endif
|
||||
*/
|
||||
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
@ -5,3 +5,4 @@ add_subdirectory(DiscIO)
|
||||
add_subdirectory(DolphinWX)
|
||||
add_subdirectory(InputCommon)
|
||||
add_subdirectory(VideoCommon)
|
||||
add_subdirectory(VideoBackends)
|
||||
|