1. Allow users to pick games dircetory from external storage.
2. Better UX experince to distinguish between selecting a directory or
a game. The later is needed when we implement change disk for android.
1) Most of the times the native heap is kept around even after the activity
is killed, we can ask the native code if it is still running and resume
the emulation if that is the case.
2) In case the native heap is freed and the emulation can't resume we used
a temporary state to load on the game boot.
I couldn't find a way to test this, if you want to test this schnario,
add this block to EmulationFragment.
public void onDestroy()
{
stopEmulation();
super.onDestroy();
}
onDestroy is only called if the acivity killed by the OS and not be rotation
change whihch in this case will make sure to kill the emulation and start
again when the activiy is re-created.
Note: By "HandleInit" in this commit message, I mean the code that is
in HandleInit in master except the part that launches EmulationActivity.
In other words, I mean the call to SetUserDirectory and the call to
DirectoryInitializationService.startService. Couldn't think of
something more accurate to call that than "HandleInit"...
In master, HandleInit only runs when the main activity is launched.
This is a problem if the app ends up being launched in some other way,
such as resuming EmulationActivity after the app has been killed in
order to reclaim memory. It's important that we run HandleInit, because
otherwise the native code won't know where the User and Sys folders are.
In order to implement this, I'm dropping the ability to set a custom
User folder in an intent. I don't think anyone is using that anyway.
It's not impossible to support it, but I can't see a way to support
it that doesn't involve something ugly like having code for calling
HandleInit in every activity (or at least MainActivity + TvMainActivity
+ EmulationActivity, with more activities potentially needing it in
the future if we expand the usage of native code for e.g. settings).
If we want to support setting a custom user directory, we should
consider another way to do it, such as a setting that's stored in
getFilesDir() or getExternalStorageDirectory(). Intents are intended
to control the behavior of a specific activity, not the whole app.
You will see an empty gc pad settings screen until you open any other
settings screen and change something, at that moment the Dolphin.ini will
be created and the gc pad settings will be loaded successfully the next
time you open the screen.
This fixes the bug by putting the default gc pad settings section even if
the Dolphin.ini file doesn't exist
This solves the following issues:
1. If user uninstall Dolphin and install it again the resources will
not be copied unless the user manually clear the app cache because we
are enabling the allowBackup flag in the manifest which will make the app
restore the settings saved in the shared prefernces including the flag
assetsCopied. This PR always copy the files everytime you open Dolphin.
2. If the AssetCopyService took long time and you tried to open the settings
screen or start a game the behaviour was not expected or the emulator will
crash, this PR make sure that whatever we add to the DirectoryInitializationService
or how long it will take will still work as expected by blocking both
the settings screen and the emulaion screen to wait untill all resources
needed are copied.
3. Better communication between the DirectoryInitializationService and the
UI screens using brocast messages.
This only works if GCPadNew.ini and Dolphin.ini files are not already in the dolphin config folder. Any advice would be helpful. I'd really like to tackle the UI and wiring for deadzones, radius, etc.
This has no effect now, as we've never bumped the database version.
Instead, it adds future proofing, and makes moving between a future
version with a bump and master clean.
Now that all inputs are corrected to zero-centered, we can use getFlat()
to ignore movements that are just noise.
This eliminates a lot of drift when the controller is at rest, notably
on the character select screen in Melee.
Android reports the same physical axis multiple times for analog
triggers, and this handles this case.
There are also some controllers with broken mappings (eg the analog
triggers on a PS4 DualShock 4). These axis don't center correctly.
There are also some controllers (again, the PS4) that send both a button
press and an axis movement. This ignores the buttons so we can use the
analog axis. Otherwise, since the button comes before the axis moves
far we would always take the button.
This reverts commit 1fc910b3ea,
replacing the old INI setting EFBScale with a new INI setting
called InternalResolution, which has a simpler mapping:
| EFBScale | InternalResolution
----------------- | -------------------- | --------------------
Auto (fractional) | 0 |
Auto (integral) | 1 | 0
1x | 2 | 1
1.5x | 3 |
2x | 4 | 2
2.5x | 5 |
3x | 6 | 3
4x | 7 | 4
5x | 8 | 5
6x | 9 | 6
All the fractional IRs were removed in f090a943.
Emulation needs to be running when the surface is destroyed, but we want
to pause in onStop. So call the surfaceDestroyed callback, as this
accomplished both.
The source Views don't need the transition name. We could get the name
from the sharedView via getTransitionName, but since the TV
ImageCardView isn't inflated in XML it would be to be manually set.
I'm not sure if that would be any cleaner than this.
called.
The user will get a brief system popup tutorial the first time it's
used, so we don't need to show them the menu every time. Once they
enable it by pulling down, hide again after 3s.
Move the parameter extraction earlier on in onCreate. Mostly this moves
setting sIsGameCubeGame to before setContentView, which means
EmulationFragment will always see it in a consistent state. Previously,
there was a race, which mean the controller overlay would randomly be
Wii controls for a GameCube game (since the default is false).
Use the correct support version of things, ActivityOptionsCompat and
transitions
Rename static var mIsGameCubeGame to sIsGameCubeGame. s is static, m is
member.
Make the MenuFragment added and removed by fragment transactions only,
instead of being initially present in the XML. This fixes a glitch where
it doesn't animate correctly the first time it's used.
The Activity is responsible for just its views and menus and such. It
signals the Fragment via setGamePath, StartEmulation and StopEmulation.
The Fragment manages the actual emulation lifecycle. It is solely
responsible for calling the NativeLibrary lifecycle methods.
With this lifecycle simplification, the NativeLibrary no longer needs to
kill the Activity. It happens normally now.
This simplifies a lot of things, live handling rotation.
Without this View, the emulation SurfaceView acts like it has the
highest Z-value, blocking any other View. This includes the menu
fragments and the screenshot ImageView.
This makes it clear that the Activity is being cleared and removes null as
a valid param. This improves readability (and logging slightly).
Fix spacing between [Tag] and message. This matches the rest of the log
messages.
In the support lib, the code comes from the SDK, not the device like the
framework version. This means we're shipping a more recent and less buggy
version.
It's also a good idea to keep the entire project on one version. We have a bit
of a mix now. I think some of the Fragment animation issues were because of
this mixing.
For the leanback activities, AppCompatActivity requires AppCompat themes, which
they don't ship for Theme.Leanback. So use FragmentActivity instead (that's the
parent of AppCompatActivity, but still in the support library). For passed
around Activities, use FragmentActivity to work with both.
Other than what action they send back to
EmulationActivity.handleMenuAction(), they are the same.
Change the menu-handling logic in EmulationActivity to keep track of a
boolean for whether the submenu is visible, rather than keeping the
fragment tag. There's only one fragment visible, so this makes more
sense.
Prefixing everything with a constant packagename is not needed for
internal keys, and just adds complexity.
Rename ARGUMENT_ prefix to ARG_ to match (most) of the rest of the
codebase.
Restrict visiblity of above as much as possible.
FRAGMENT_ID wasn't actually the fragment's ID (that's misleading, and
sounds like the tag). It's actually the layout resource ID. There's no point in making that a static constant.
If a SettingsFile had at least one section, it was assumed all sections
were correctly filled out. This caused crashes when opening the settings
menus if that was not the case - for example the GFX.ini settings empty
sections are removed by the main dolphin app, putting the .ini file in a
state that would crash the settings window if at least one setting was
changed in it from the default, some sections were left as default.
This adds a subclass of HashMap<String, SettingSection> that constructs a
new SettingSection instead of returning 'null' if the key isn't found,
so the mSettings.get(FILE).get(SECTION).get(SETTING) pattern can be
safely used.
It would fail on lines line "Value =" - IE a value set to emptystring.
This would cause the app to crash when trying to open the corresponding
settings window.
Since these button names are printed on all real controllers,
we should show them in the same way as they are printed on
the controllers, regardless of the user's language. It seems
like this was intended all along (except for "Start"), but the
_ markers in TASInputDlg.cpp (accidentally?) led to the button
names in the controller configs also becoming translatable.
I'm making exceptions for "L" and "R" because translators
may want to mark them in some way (for instance "L-Digital")
to clarify the difference from "L-Analog" and "R-Analog".
I'm also making an exception for START/PAUSE because it's
referred to as スタート in Japanese games.
I'm changing "Home" and "Start" to uppercase for consistency
with how Nintendo refers to those buttons, and because someone
who isn't familiar with the Latin script might not know the
connection between the lowercase and uppercase letters (most
users likely do know the connection, but we shouldn't assume it),
and because leaving "Start" as "Start" makes it "collide" with
unrelated strings, such as the string for the button that starts
a netplay session.
To rename "Start" and "Home" without breaking INI
compatibility, I added a ui_name variable like in f5c82ad.
Whenever the EmulationActivity crashes and the app gets back to the
TvMainActivity, dolphin will crash tring to restor the mBrowseFragment
since we don't save the adapter data in the bundle.
This is quick hack to avoid the crash. The proper fix would be to save the
adapter data in the bundle and restore it before restoring the fragment
when the activity gets recreated.
Crash Stacktrace:
Process: org.dolphinemu.dolphinemu.debug, PID: 30353
java.lang.RuntimeException: Unable to start activity ComponentInfo{org.dolphinemu.dolphinemu.debug/org.dolphinemu.dolphinemu.ui.main.TvMainActivity}: java.lang.IllegalArgumentException: Invalid position 1 requested
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2691)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2752)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1461)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6120)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
Caused by: java.lang.IllegalArgumentException: Invalid position 1 requested
at android.support.v17.leanback.app.BrowseFragment.createMainFragment(BrowseFragment.java:509)
at android.support.v17.leanback.app.BrowseFragment.replaceMainFragment(BrowseFragment.java:1454)
at android.support.v17.leanback.app.BrowseFragment.setAdapter(BrowseFragment.java:764)
at org.dolphinemu.dolphinemu.ui.main.TvMainActivity.buildRowsAdapter(TvMainActivity.java:183)
at org.dolphinemu.dolphinemu.ui.main.TvMainActivity.onCreate(TvMainActivity.java:59)
at android.app.Activity.performCreate(Activity.java:6664)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2644)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2752)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1461)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6120)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
Use Bitmap.setPixels() instead of Bitmap.copyPixelsFromBuffer() the former
use non pre-multiplied values of the colors which is what we expect to
come from the native code.
We can do this now that the x86-64 JIT supports PIE.
JITIL is deliberately excluded from the GUI because it
doesn't support PIE yet. (JITIL will be used if it's
set in the INI, though.)
Apparently the path was changed from using "/thump.png" to using
"/gameId-#.png". We will always use the first screenshot for the game
broswer wich will be "/gameId-1.png"
Saving screenshot was not working due to 2 problems. The first one is that
the view id of the save screenshot in the Android TV fragment doesnt match
the one declared inside the menu_emulation. Second Problem will be fixed
in another commit.
This commit chnage the code to not depend on reusing the ids of the menu
everywhere in the emulator inorder for the onMenuItemClicked to work.
Instead you need to call EmulationActivity.handleMenuAction passing
the action to handle regardless of the ids you are using in the view.
Load all the inis at once, choose which one to write to, and save them all
at the same time. This allows us to modify settings from different files
on the same settings page.
The usage of "Wii Remote" and "Wiimote" in the interface is inconsistent. "Wiimote" is also not a real word nor is it an official product name. Therefore I have changed instances of "Wiimote" in the UI to instead say "Wii Remote". I also made a couple of minor grammatical changes as well.
This is mostly a resubmission of #4338 but there are some minor other changes as well.
It's now possible to switch between a horizontal or vertical Wiimote
with no extension, a Wiimote with a Nunchuk, a Classic Controller,
or a GameCube Controller when running a Wii game.
These were made when the button images were first remade many months ago, but they were never committed since there was no use for them at the time (and laziness :P). BUT now there is a PR that finally has use for these images, so it's time to get this into Dolphin and available for use!
Under failure conditions of the GC Adapter, When interface count is zero and we can't open the device.
Then there were race conditions on shutdown of the threads which could result in crashing.
Make adapter opening more robust like the Mayflash DolphinBar.
Make shutdown more robust by making the read thread control the write thread.
Make sure that there is actual data to be written when kicking the write thread. So it doesn't attempt a write a shutdown.
Make a toast on screen to tell the user that the adapter needs to be unplugged and plugged back in again for it to work.
This is the only way to get Wiimotes working under Android now.
This, just like the Wii U Gamecube Controller Adapter, completely goes around Android's limitations and talks with the device directly through USBManager.
Couple notes.
Continuous scanning must be enabled otherwise the Wiimotes won't be seen.
The UI doesn't expose support for this yet. One must change the Wiimote source and continuous scanning settings manually.
Testing up to two wiimotes in Taiko No Tatsujin, no reason to believe all four won't work.