mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-24 23:11:14 +01:00
Merge pull request #2424 from sigmabeta/android-emulation-activity
Android: Implement new EmulationActivity.
This commit is contained in:
commit
08ce0ca5c0
@ -48,20 +48,24 @@
|
|||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="org.dolphinemu.dolphinemu.about.AboutActivity"
|
android:name=".activities.EmulationActivity"
|
||||||
|
android:theme="@style/DolphinEmulationGamecube"/>
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name=".about.AboutActivity"
|
||||||
android:theme="@android:style/Theme.Holo.Light" />
|
android:theme="@android:style/Theme.Holo.Light" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="org.dolphinemu.dolphinemu.emulation.EmulationActivity"
|
android:name=".emulation.EmulationActivity"
|
||||||
android:screenOrientation="landscape" />
|
android:screenOrientation="landscape" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="org.dolphinemu.dolphinemu.settings.input.overlayconfig.OverlayConfigActivity"
|
android:name=".settings.input.overlayconfig.OverlayConfigActivity"
|
||||||
android:screenOrientation="landscape"
|
android:screenOrientation="landscape"
|
||||||
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"/>
|
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"/>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="org.dolphinemu.dolphinemu.settings.PrefsActivity"
|
android:name=".settings.PrefsActivity"
|
||||||
android:label="@string/settings"
|
android:label="@string/settings"
|
||||||
android:theme="@android:style/Theme.Holo.Light" />
|
android:theme="@android:style/Theme.Holo.Light" />
|
||||||
|
|
||||||
@ -69,6 +73,13 @@
|
|||||||
|
|
||||||
<service android:name=".services.SettingsSaveService"/>
|
<service android:name=".services.SettingsSaveService"/>
|
||||||
|
|
||||||
|
<provider
|
||||||
|
android:name=".model.GameProvider"
|
||||||
|
android:authorities="${applicationId}.provider"
|
||||||
|
android:enabled="true"
|
||||||
|
android:exported="false">
|
||||||
|
</provider>
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
|
@ -132,9 +132,13 @@ public final class NativeLibrary
|
|||||||
|
|
||||||
public static native String GetDescription(String filename);
|
public static native String GetDescription(String filename);
|
||||||
public static native String GetGameId(String filename);
|
public static native String GetGameId(String filename);
|
||||||
public static native String GetDate(String filename);
|
|
||||||
|
public static native int GetCountry(String filename);
|
||||||
|
|
||||||
|
public static native String GetCompany(String filename);
|
||||||
public static native long GetFilesize(String filename);
|
public static native long GetFilesize(String filename);
|
||||||
public static native boolean IsWiiTitle(String filename);
|
|
||||||
|
public static native int GetPlatform(String filename);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the Dolphin version string.
|
* Gets the Dolphin version string.
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
package org.dolphinemu.dolphinemu.activities;
|
package org.dolphinemu.dolphinemu.activities;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
import android.content.AsyncQueryHandler;
|
||||||
|
import android.content.ContentValues;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
import android.support.v7.widget.LinearLayoutManager;
|
import android.support.v7.widget.LinearLayoutManager;
|
||||||
@ -14,6 +17,8 @@ import android.widget.Toolbar;
|
|||||||
import org.dolphinemu.dolphinemu.BuildConfig;
|
import org.dolphinemu.dolphinemu.BuildConfig;
|
||||||
import org.dolphinemu.dolphinemu.R;
|
import org.dolphinemu.dolphinemu.R;
|
||||||
import org.dolphinemu.dolphinemu.adapters.FileAdapter;
|
import org.dolphinemu.dolphinemu.adapters.FileAdapter;
|
||||||
|
import org.dolphinemu.dolphinemu.model.GameDatabase;
|
||||||
|
import org.dolphinemu.dolphinemu.model.GameProvider;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An Activity that shows a list of files and folders, allowing the user to tell the app which folder(s)
|
* An Activity that shows a list of files and folders, allowing the user to tell the app which folder(s)
|
||||||
@ -91,17 +96,36 @@ public class AddDirectoryActivity extends Activity implements FileAdapter.FileCl
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tell the GameGridActivity that launched this Activity that the user picked a folder.
|
* Add a directory to the library, and if successful, end the activity.
|
||||||
|
*
|
||||||
|
* @param path The target directory's path.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void finishSuccessfully()
|
public void addDirectory()
|
||||||
{
|
{
|
||||||
Intent resultData = new Intent();
|
// Set up a callback for when the addition is complete
|
||||||
|
// TODO This has a nasty warning on it; find a cleaner way to do this Insert asynchronously
|
||||||
|
AsyncQueryHandler handler = new AsyncQueryHandler(getContentResolver())
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
protected void onInsertComplete(int token, Object cookie, Uri uri)
|
||||||
|
{
|
||||||
|
Intent resultData = new Intent();
|
||||||
|
|
||||||
resultData.putExtra(KEY_CURRENT_PATH, mAdapter.getPath());
|
resultData.putExtra(KEY_CURRENT_PATH, mAdapter.getPath());
|
||||||
setResult(RESULT_OK, resultData);
|
setResult(RESULT_OK, resultData);
|
||||||
|
|
||||||
finish();
|
finish();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ContentValues file = new ContentValues();
|
||||||
|
file.put(GameDatabase.KEY_FOLDER_PATH, mAdapter.getPath());
|
||||||
|
|
||||||
|
handler.startInsert(0, // We don't need to identify this call to the handler
|
||||||
|
null, // We don't need to pass additional data to the handler
|
||||||
|
GameProvider.URI_FOLDER, // Tell the GameProvider we are adding a folder
|
||||||
|
file); // Tell the GameProvider what folder we are adding
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -0,0 +1,292 @@
|
|||||||
|
package org.dolphinemu.dolphinemu.activities;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Message;
|
||||||
|
import android.view.InputDevice;
|
||||||
|
import android.view.KeyEvent;
|
||||||
|
import android.view.Menu;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import org.dolphinemu.dolphinemu.NativeLibrary;
|
||||||
|
import org.dolphinemu.dolphinemu.R;
|
||||||
|
import org.dolphinemu.dolphinemu.fragments.EmulationFragment;
|
||||||
|
import org.dolphinemu.dolphinemu.settings.input.InputConfigFragment;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public final class EmulationActivity extends Activity
|
||||||
|
{
|
||||||
|
private View mDecorView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handlers are a way to pass a message to an Activity telling it to do something
|
||||||
|
* on the UI thread. This Handler responds to any message, even blank ones, by
|
||||||
|
* hiding the system UI.
|
||||||
|
*/
|
||||||
|
private Handler mSystemUiHider = new Handler()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void handleMessage(Message msg)
|
||||||
|
{
|
||||||
|
hideSystemUI();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState)
|
||||||
|
{
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
// Get a handle to the Window containing the UI.
|
||||||
|
mDecorView = getWindow().getDecorView();
|
||||||
|
|
||||||
|
// Set these options now so that the SurfaceView the game renders into is the right size.
|
||||||
|
mDecorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
|
||||||
|
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
|
||||||
|
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
|
||||||
|
|
||||||
|
// Set the ActionBar to follow the navigation/status bar's visibility changes.
|
||||||
|
mDecorView.setOnSystemUiVisibilityChangeListener(
|
||||||
|
new View.OnSystemUiVisibilityChangeListener()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void onSystemUiVisibilityChange(int flags)
|
||||||
|
{
|
||||||
|
boolean visible = (flags & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
|
||||||
|
|
||||||
|
if (visible)
|
||||||
|
{
|
||||||
|
getActionBar().show();
|
||||||
|
hideSystemUiAfterDelay();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
getActionBar().hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
setContentView(R.layout.activity_emulation);
|
||||||
|
|
||||||
|
Intent gameToEmulate = getIntent();
|
||||||
|
String path = gameToEmulate.getStringExtra("SelectedGame");
|
||||||
|
String title = gameToEmulate.getStringExtra("SelectedTitle");
|
||||||
|
|
||||||
|
setTitle(title);
|
||||||
|
|
||||||
|
// Instantiate an EmulationFragment.
|
||||||
|
EmulationFragment emulationFragment = EmulationFragment.newInstance(path);
|
||||||
|
|
||||||
|
// Add fragment to the activity - this triggers all its lifecycle callbacks.
|
||||||
|
getFragmentManager().beginTransaction()
|
||||||
|
.add(R.id.frame_content, emulationFragment, EmulationFragment.FRAGMENT_TAG)
|
||||||
|
.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostCreate(Bundle savedInstanceState)
|
||||||
|
{
|
||||||
|
super.onPostCreate(savedInstanceState);
|
||||||
|
|
||||||
|
// Give the user a few seconds to see what the controls look like, then hide them.
|
||||||
|
hideSystemUiAfterDelay();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onWindowFocusChanged(boolean hasFocus)
|
||||||
|
{
|
||||||
|
super.onWindowFocusChanged(hasFocus);
|
||||||
|
|
||||||
|
if (hasFocus)
|
||||||
|
{
|
||||||
|
hideSystemUiAfterDelay();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If the window loses focus (i.e. a dialog box, or a popup menu is on screen
|
||||||
|
// stop hiding the UI.
|
||||||
|
mSystemUiHider.removeMessages(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCreateOptionsMenu(Menu menu)
|
||||||
|
{
|
||||||
|
// Inflate the menu; this adds items to the action bar if it is present.
|
||||||
|
getMenuInflater().inflate(R.menu.menu_emulation, menu);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(MenuItem item)
|
||||||
|
{
|
||||||
|
switch (item.getItemId())
|
||||||
|
{
|
||||||
|
// Enable/Disable input overlay.
|
||||||
|
case R.id.enableInputOverlay:
|
||||||
|
{
|
||||||
|
EmulationFragment emulationFragment = (EmulationFragment) getFragmentManager()
|
||||||
|
.findFragmentByTag(EmulationFragment.FRAGMENT_TAG);
|
||||||
|
|
||||||
|
emulationFragment.toggleInputOverlayVisibility();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Screenshot capturing
|
||||||
|
case R.id.takeScreenshot:
|
||||||
|
NativeLibrary.SaveScreenShot();
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Save state slots
|
||||||
|
case R.id.saveSlot1:
|
||||||
|
NativeLibrary.SaveState(0);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case R.id.saveSlot2:
|
||||||
|
NativeLibrary.SaveState(1);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case R.id.saveSlot3:
|
||||||
|
NativeLibrary.SaveState(2);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case R.id.saveSlot4:
|
||||||
|
NativeLibrary.SaveState(3);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case R.id.saveSlot5:
|
||||||
|
NativeLibrary.SaveState(4);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Load state slots
|
||||||
|
case R.id.loadSlot1:
|
||||||
|
NativeLibrary.LoadState(0);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case R.id.loadSlot2:
|
||||||
|
NativeLibrary.LoadState(1);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case R.id.loadSlot3:
|
||||||
|
NativeLibrary.LoadState(2);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case R.id.loadSlot4:
|
||||||
|
NativeLibrary.LoadState(3);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case R.id.loadSlot5:
|
||||||
|
NativeLibrary.LoadState(4);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case R.id.exitEmulation:
|
||||||
|
{
|
||||||
|
// Create a confirmation method for quitting the current emulation instance.
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||||
|
builder.setTitle(R.string.overlay_exit_emulation);
|
||||||
|
builder.setMessage(R.string.overlay_exit_emulation_confirm);
|
||||||
|
builder.setNegativeButton(R.string.no, null);
|
||||||
|
builder.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener()
|
||||||
|
{
|
||||||
|
public void onClick(DialogInterface dialog, int which)
|
||||||
|
{
|
||||||
|
onDestroy();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
builder.show();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gets button presses
|
||||||
|
@Override
|
||||||
|
public boolean dispatchKeyEvent(KeyEvent event)
|
||||||
|
{
|
||||||
|
int action = 0;
|
||||||
|
|
||||||
|
switch (event.getAction())
|
||||||
|
{
|
||||||
|
case KeyEvent.ACTION_DOWN:
|
||||||
|
// Handling the case where the back button is pressed.
|
||||||
|
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK)
|
||||||
|
{
|
||||||
|
onBackPressed();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normal key events.
|
||||||
|
action = NativeLibrary.ButtonState.PRESSED;
|
||||||
|
break;
|
||||||
|
case KeyEvent.ACTION_UP:
|
||||||
|
action = NativeLibrary.ButtonState.RELEASED;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
InputDevice input = event.getDevice();
|
||||||
|
boolean handled = NativeLibrary.onGamePadEvent(InputConfigFragment.getInputDesc(input), event.getKeyCode(), action);
|
||||||
|
return handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean dispatchGenericMotionEvent(MotionEvent event)
|
||||||
|
{
|
||||||
|
if (((event.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) == 0))
|
||||||
|
{
|
||||||
|
return super.dispatchGenericMotionEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't attempt to do anything if we are disconnecting a device.
|
||||||
|
if (event.getActionMasked() == MotionEvent.ACTION_CANCEL)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
InputDevice input = event.getDevice();
|
||||||
|
List<InputDevice.MotionRange> motions = input.getMotionRanges();
|
||||||
|
|
||||||
|
for (InputDevice.MotionRange range : motions)
|
||||||
|
{
|
||||||
|
NativeLibrary.onGamePadMoveEvent(InputConfigFragment.getInputDesc(input), range.getAxis(), event.getAxisValue(range.getAxis()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void hideSystemUiAfterDelay()
|
||||||
|
{
|
||||||
|
// Clear any pending hide events.
|
||||||
|
mSystemUiHider.removeMessages(0);
|
||||||
|
|
||||||
|
// Add a new hide event, to occur 3 seconds from now.
|
||||||
|
mSystemUiHider.sendEmptyMessageDelayed(0, 3000);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void hideSystemUI()
|
||||||
|
{
|
||||||
|
mDecorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
|
||||||
|
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
|
||||||
|
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
|
||||||
|
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
|
||||||
|
View.SYSTEM_UI_FLAG_FULLSCREEN |
|
||||||
|
View.SYSTEM_UI_FLAG_IMMERSIVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showSystemUI()
|
||||||
|
{
|
||||||
|
mDecorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
|
||||||
|
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
|
||||||
|
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
|
||||||
|
}
|
||||||
|
}
|
@ -1,13 +1,15 @@
|
|||||||
package org.dolphinemu.dolphinemu.activities;
|
package org.dolphinemu.dolphinemu.activities;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
import android.app.LoaderManager;
|
||||||
|
import android.content.CursorLoader;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.Loader;
|
||||||
|
import android.database.Cursor;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Environment;
|
|
||||||
import android.preference.PreferenceManager;
|
|
||||||
import android.support.v7.widget.GridLayoutManager;
|
import android.support.v7.widget.GridLayoutManager;
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
@ -15,27 +17,23 @@ import android.view.View;
|
|||||||
import android.widget.ImageButton;
|
import android.widget.ImageButton;
|
||||||
import android.widget.Toolbar;
|
import android.widget.Toolbar;
|
||||||
|
|
||||||
import org.dolphinemu.dolphinemu.NativeLibrary;
|
|
||||||
import org.dolphinemu.dolphinemu.R;
|
import org.dolphinemu.dolphinemu.R;
|
||||||
import org.dolphinemu.dolphinemu.adapters.GameAdapter;
|
import org.dolphinemu.dolphinemu.adapters.GameAdapter;
|
||||||
import org.dolphinemu.dolphinemu.model.Game;
|
import org.dolphinemu.dolphinemu.model.GameDatabase;
|
||||||
import org.dolphinemu.dolphinemu.model.GcGame;
|
import org.dolphinemu.dolphinemu.model.GameProvider;
|
||||||
import org.dolphinemu.dolphinemu.services.AssetCopyService;
|
import org.dolphinemu.dolphinemu.services.AssetCopyService;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The main Activity of the Lollipop style UI. Shows a grid of games on tablets & landscape phones,
|
* The main Activity of the Lollipop style UI. Shows a grid of games on tablets & landscape phones,
|
||||||
* shows a list of games on portrait phones.
|
* shows a list of games on portrait phones.
|
||||||
*/
|
*/
|
||||||
public final class GameGridActivity extends Activity
|
public final class GameGridActivity extends Activity implements LoaderManager.LoaderCallbacks<Cursor>
|
||||||
{
|
{
|
||||||
private static final int REQUEST_ADD_DIRECTORY = 1;
|
private static final int REQUEST_ADD_DIRECTORY = 1;
|
||||||
|
|
||||||
|
private static final int LOADER_ID_GAMES = 1;
|
||||||
|
// TODO When each platform has its own tab, there should be a LOADER_ID for each platform.
|
||||||
|
|
||||||
private GameAdapter mAdapter;
|
private GameAdapter mAdapter;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -62,7 +60,8 @@ public final class GameGridActivity extends Activity
|
|||||||
recyclerView.addItemDecoration(new GameAdapter.SpacesItemDecoration(8));
|
recyclerView.addItemDecoration(new GameAdapter.SpacesItemDecoration(8));
|
||||||
|
|
||||||
// Create an adapter that will relate the dataset to the views on-screen.
|
// Create an adapter that will relate the dataset to the views on-screen.
|
||||||
mAdapter = new GameAdapter(getGameList());
|
getLoaderManager().initLoader(LOADER_ID_GAMES, null, this);
|
||||||
|
mAdapter = new GameAdapter();
|
||||||
recyclerView.setAdapter(mAdapter);
|
recyclerView.setAdapter(mAdapter);
|
||||||
|
|
||||||
buttonAddDirectory.setOnClickListener(new View.OnClickListener()
|
buttonAddDirectory.setOnClickListener(new View.OnClickListener()
|
||||||
@ -103,20 +102,7 @@ public final class GameGridActivity extends Activity
|
|||||||
// other activities might use this callback in the future (don't forget to change Javadoc!)
|
// other activities might use this callback in the future (don't forget to change Javadoc!)
|
||||||
if (requestCode == REQUEST_ADD_DIRECTORY)
|
if (requestCode == REQUEST_ADD_DIRECTORY)
|
||||||
{
|
{
|
||||||
// Get the path the user selected in AddDirectoryActivity.
|
getLoaderManager().restartLoader(LOADER_ID_GAMES, null, this);
|
||||||
String path = result.getStringExtra(AddDirectoryActivity.KEY_CURRENT_PATH);
|
|
||||||
|
|
||||||
// Store this path as a preference.
|
|
||||||
// TODO Use SQLite instead.
|
|
||||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
|
|
||||||
SharedPreferences.Editor editor = prefs.edit();
|
|
||||||
|
|
||||||
editor.putString(AddDirectoryActivity.KEY_CURRENT_PATH, path);
|
|
||||||
|
|
||||||
// Using commit, not apply, in order to block so the next method has the correct data to load.
|
|
||||||
editor.commit();
|
|
||||||
|
|
||||||
mAdapter.setGameList(getGameList());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -150,55 +136,75 @@ public final class GameGridActivity extends Activity
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Replace all of this with a SQLite database
|
|
||||||
private ArrayList<Game> getGameList()
|
/**
|
||||||
|
* Callback that's invoked when the system has initialized the Loader and
|
||||||
|
* is ready to start the query. This usually happens when initLoader() is
|
||||||
|
* called. Here, we use it to make a DB query for games.
|
||||||
|
*
|
||||||
|
* @param id The ID value passed to the initLoader() call that triggered this.
|
||||||
|
* @param args The args bundle supplied by the caller.
|
||||||
|
* @return A new Loader instance that is ready to start loading.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Loader<Cursor> onCreateLoader(int id, Bundle args)
|
||||||
{
|
{
|
||||||
ArrayList<Game> gameList = new ArrayList<Game>();
|
Log.d("DolphinEmu", "Creating loader with id: " + id);
|
||||||
|
|
||||||
final String DefaultDir = Environment.getExternalStorageDirectory() + File.separator + "dolphin-emu";
|
// Take action based on the ID of the Loader that's being created.
|
||||||
|
switch (id)
|
||||||
NativeLibrary.SetUserDirectory(DefaultDir);
|
|
||||||
|
|
||||||
// Extensions to filter by.
|
|
||||||
Set<String> exts = new HashSet<String>(Arrays.asList(".dff", ".dol", ".elf", ".gcm", ".gcz", ".iso", ".wad", ".wbfs"));
|
|
||||||
|
|
||||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
|
|
||||||
|
|
||||||
String path = prefs.getString(AddDirectoryActivity.KEY_CURRENT_PATH, "/");
|
|
||||||
|
|
||||||
File currentDir = new File(path);
|
|
||||||
File[] dirs = currentDir.listFiles();
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
for (File entry : dirs)
|
case LOADER_ID_GAMES:
|
||||||
{
|
// TODO Play some sort of load-starting animation; maybe fade the list out.
|
||||||
if (!entry.isHidden() && !entry.isDirectory())
|
|
||||||
{
|
|
||||||
String entryName = entry.getName();
|
|
||||||
|
|
||||||
// Check that the file has an appropriate extension before trying to read out of it.
|
return new CursorLoader(
|
||||||
if (exts.contains(entryName.toLowerCase().substring(entryName.lastIndexOf('.'))))
|
this, // Parent activity context
|
||||||
{
|
GameProvider.URI_GAME, // URI of table to query
|
||||||
GcGame game = new GcGame(NativeLibrary.GetTitle(entry.getAbsolutePath()),
|
null, // Return all columns
|
||||||
NativeLibrary.GetDescription(entry.getAbsolutePath()).replace("\n", " "),
|
null, // No selection clause
|
||||||
// TODO Some games might actually not be from this region, believe it or not.
|
null, // No selection arguments
|
||||||
"United States",
|
GameDatabase.KEY_GAME_TITLE + " asc" // Sort by game name, ascending order
|
||||||
entry.getAbsolutePath(),
|
);
|
||||||
NativeLibrary.GetGameId(entry.getAbsolutePath()),
|
|
||||||
NativeLibrary.GetDate(entry.getAbsolutePath()));
|
|
||||||
|
|
||||||
gameList.add(game);
|
default:
|
||||||
}
|
Log.e("DolphinEmu", "Bad ID passed in.");
|
||||||
|
return null;
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Exception ignored)
|
}
|
||||||
{
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback that's invoked when the Loader returned in onCreateLoader is finished
|
||||||
|
* with its task. In this case, the game DB query is finished, so we should put the results
|
||||||
|
* on screen.
|
||||||
|
*
|
||||||
|
* @param loader The loader that finished.
|
||||||
|
* @param data The data the Loader loaded.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void onLoadFinished(Loader<Cursor> loader, Cursor data)
|
||||||
|
{
|
||||||
|
int id = loader.getId();
|
||||||
|
Log.d("DolphinEmu", "Loader finished with id: " + id);
|
||||||
|
|
||||||
|
// TODO When each platform has its own tab, this should just call into those tabs instead.
|
||||||
|
switch (id)
|
||||||
|
{
|
||||||
|
case LOADER_ID_GAMES:
|
||||||
|
mAdapter.swapCursor(data);
|
||||||
|
// TODO Play some sort of load-finished animation; maybe fade the list in.
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
Log.e("DolphinEmu", "Bad ID passed in.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return gameList;
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoaderReset(Loader<Cursor> loader)
|
||||||
|
{
|
||||||
|
Log.d("DolphinEmu", "Loader resetting.");
|
||||||
|
|
||||||
|
// TODO ¯\_(ツ)_/¯
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ import java.io.File;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
public class FileAdapter extends RecyclerView.Adapter<FileViewHolder> implements View.OnClickListener
|
public final class FileAdapter extends RecyclerView.Adapter<FileViewHolder> implements View.OnClickListener
|
||||||
{
|
{
|
||||||
private ArrayList<FileListItem> mFileList;
|
private ArrayList<FileListItem> mFileList;
|
||||||
|
|
||||||
@ -146,7 +146,7 @@ public class FileAdapter extends RecyclerView.Adapter<FileViewHolder> implements
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Pass the activity the path of the parent directory of the clicked file.
|
// Pass the activity the path of the parent directory of the clicked file.
|
||||||
mListener.finishSuccessfully();
|
mListener.addDirectory();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,7 +154,7 @@ public class FileAdapter extends RecyclerView.Adapter<FileViewHolder> implements
|
|||||||
* For a given directory, return a list of Files it contains.
|
* For a given directory, return a list of Files it contains.
|
||||||
*
|
*
|
||||||
* @param directory A File representing the directory that should have its contents displayed.
|
* @param directory A File representing the directory that should have its contents displayed.
|
||||||
* @return
|
* @return The list of files contained in the directory.
|
||||||
*/
|
*/
|
||||||
private ArrayList<FileListItem> generateFileList(File directory)
|
private ArrayList<FileListItem> generateFileList(File directory)
|
||||||
{
|
{
|
||||||
@ -205,7 +205,7 @@ public class FileAdapter extends RecyclerView.Adapter<FileViewHolder> implements
|
|||||||
*/
|
*/
|
||||||
public interface FileClickListener
|
public interface FileClickListener
|
||||||
{
|
{
|
||||||
void finishSuccessfully();
|
void addDirectory();
|
||||||
|
|
||||||
void updateSubtitle(String path);
|
void updateSubtitle(String path);
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,11 @@ package org.dolphinemu.dolphinemu.adapters;
|
|||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.database.DataSetObserver;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
@ -11,27 +14,33 @@ import android.view.ViewGroup;
|
|||||||
import com.squareup.picasso.Picasso;
|
import com.squareup.picasso.Picasso;
|
||||||
|
|
||||||
import org.dolphinemu.dolphinemu.R;
|
import org.dolphinemu.dolphinemu.R;
|
||||||
|
import org.dolphinemu.dolphinemu.activities.EmulationActivity;
|
||||||
import org.dolphinemu.dolphinemu.dialogs.GameDetailsDialog;
|
import org.dolphinemu.dolphinemu.dialogs.GameDetailsDialog;
|
||||||
import org.dolphinemu.dolphinemu.emulation.EmulationActivity;
|
import org.dolphinemu.dolphinemu.model.GameDatabase;
|
||||||
import org.dolphinemu.dolphinemu.model.Game;
|
|
||||||
import org.dolphinemu.dolphinemu.viewholders.GameViewHolder;
|
import org.dolphinemu.dolphinemu.viewholders.GameViewHolder;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
/**
|
||||||
|
* This adapter, unlike {@link FileAdapter} which is backed by an ArrayList, gets its
|
||||||
public class GameAdapter extends RecyclerView.Adapter<GameViewHolder> implements
|
* information from a database Cursor. This fact, paired with the usage of ContentProviders
|
||||||
|
* and Loaders, allows for efficient display of a limited view into a (possibly) large dataset.
|
||||||
|
*/
|
||||||
|
public final class GameAdapter extends RecyclerView.Adapter<GameViewHolder> implements
|
||||||
View.OnClickListener,
|
View.OnClickListener,
|
||||||
View.OnLongClickListener
|
View.OnLongClickListener
|
||||||
{
|
{
|
||||||
private ArrayList<Game> mGameList;
|
private Cursor mCursor;
|
||||||
|
private GameDataSetObserver mObserver;
|
||||||
|
|
||||||
|
private boolean mDatasetValid;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mostly just initializes the dataset to be displayed.
|
* Initializes the adapter's observer, which watches for changes to the dataset. The adapter will
|
||||||
*
|
* display no data until a Cursor is supplied by a CursorLoader.
|
||||||
* @param gameList
|
|
||||||
*/
|
*/
|
||||||
public GameAdapter(ArrayList<Game> gameList)
|
public GameAdapter()
|
||||||
{
|
{
|
||||||
mGameList = gameList;
|
mDatasetValid = false;
|
||||||
|
mObserver = new GameDataSetObserver();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -52,8 +61,7 @@ public class GameAdapter extends RecyclerView.Adapter<GameViewHolder> implements
|
|||||||
gameCard.setOnLongClickListener(this);
|
gameCard.setOnLongClickListener(this);
|
||||||
|
|
||||||
// Use that view to create a ViewHolder.
|
// Use that view to create a ViewHolder.
|
||||||
GameViewHolder holder = new GameViewHolder(gameCard);
|
return new GameViewHolder(gameCard);
|
||||||
return holder;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -67,26 +75,41 @@ public class GameAdapter extends RecyclerView.Adapter<GameViewHolder> implements
|
|||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(GameViewHolder holder, int position)
|
public void onBindViewHolder(GameViewHolder holder, int position)
|
||||||
{
|
{
|
||||||
// Get a reference to the item from the dataset; we'll use this to fill in the view contents.
|
if (mDatasetValid)
|
||||||
final Game game = mGameList.get(position);
|
|
||||||
|
|
||||||
// Fill in the view contents.
|
|
||||||
Picasso.with(holder.imageScreenshot.getContext())
|
|
||||||
.load(game.getScreenPath())
|
|
||||||
.fit()
|
|
||||||
.centerCrop()
|
|
||||||
.error(R.drawable.no_banner)
|
|
||||||
.into(holder.imageScreenshot);
|
|
||||||
|
|
||||||
holder.textGameTitle.setText(game.getTitle());
|
|
||||||
if (game.getDescription() != null)
|
|
||||||
{
|
{
|
||||||
holder.textDescription.setText(game.getDescription());
|
if (mCursor.moveToPosition(position))
|
||||||
|
{
|
||||||
|
// Fill in the view contents.
|
||||||
|
Picasso.with(holder.imageScreenshot.getContext())
|
||||||
|
.load(mCursor.getString(GameDatabase.GAME_COLUMN_SCREENSHOT_PATH))
|
||||||
|
.fit()
|
||||||
|
.centerCrop()
|
||||||
|
.error(R.drawable.no_banner)
|
||||||
|
.into(holder.imageScreenshot);
|
||||||
|
|
||||||
|
holder.textGameTitle.setText(mCursor.getString(GameDatabase.GAME_COLUMN_TITLE));
|
||||||
|
holder.textCompany.setText(mCursor.getString(GameDatabase.GAME_COLUMN_COMPANY));
|
||||||
|
|
||||||
|
// TODO These shouldn't be necessary once the move to a DB-based model is complete.
|
||||||
|
holder.gameId = mCursor.getString(GameDatabase.GAME_COLUMN_GAME_ID);
|
||||||
|
holder.path = mCursor.getString(GameDatabase.GAME_COLUMN_PATH);
|
||||||
|
holder.title = mCursor.getString(GameDatabase.GAME_COLUMN_TITLE);
|
||||||
|
holder.description = mCursor.getString(GameDatabase.GAME_COLUMN_DESCRIPTION);
|
||||||
|
holder.country = mCursor.getInt(GameDatabase.GAME_COLUMN_COUNTRY);
|
||||||
|
holder.company = mCursor.getString(GameDatabase.GAME_COLUMN_COMPANY);
|
||||||
|
holder.screenshotPath = mCursor.getString(GameDatabase.GAME_COLUMN_SCREENSHOT_PATH);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log.e("DolphinEmu", "Can't bind view; Cursor is not valid.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log.e("DolphinEmu", "Can't bind view; dataset is not valid.");
|
||||||
}
|
}
|
||||||
|
|
||||||
holder.path = game.getPath();
|
|
||||||
holder.screenshotPath = game.getScreenPath();
|
|
||||||
holder.game = game;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -97,7 +120,85 @@ public class GameAdapter extends RecyclerView.Adapter<GameViewHolder> implements
|
|||||||
@Override
|
@Override
|
||||||
public int getItemCount()
|
public int getItemCount()
|
||||||
{
|
{
|
||||||
return mGameList.size();
|
if (mDatasetValid && mCursor != null)
|
||||||
|
{
|
||||||
|
return mCursor.getCount();
|
||||||
|
}
|
||||||
|
Log.e("DolphinEmu", "Dataset is not valid.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the contents of the _id column for a given row.
|
||||||
|
*
|
||||||
|
* @param position The row for which Android wants an ID.
|
||||||
|
* @return A valid ID from the database, or 0 if not available.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public long getItemId(int position)
|
||||||
|
{
|
||||||
|
if (mDatasetValid && mCursor != null)
|
||||||
|
{
|
||||||
|
if (mCursor.moveToPosition(position))
|
||||||
|
{
|
||||||
|
return mCursor.getLong(GameDatabase.COLUMN_DB_ID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.e("DolphinEmu", "Dataset is not valid.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tell Android whether or not each item in the dataset has a stable identifier.
|
||||||
|
* Which it does, because it's a database, so always tell Android 'true'.
|
||||||
|
*
|
||||||
|
* @param hasStableIds ignored.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setHasStableIds(boolean hasStableIds)
|
||||||
|
{
|
||||||
|
super.setHasStableIds(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When a load is finished, call this to replace the existing data with the newly-loaded
|
||||||
|
* data.
|
||||||
|
*
|
||||||
|
* @param cursor The newly-loaded Cursor.
|
||||||
|
*/
|
||||||
|
public void swapCursor(Cursor cursor)
|
||||||
|
{
|
||||||
|
// Sanity check.
|
||||||
|
if (cursor == mCursor)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Before getting rid of the old cursor, disassociate it from the Observer.
|
||||||
|
final Cursor oldCursor = mCursor;
|
||||||
|
if (oldCursor != null && mObserver != null)
|
||||||
|
{
|
||||||
|
oldCursor.unregisterDataSetObserver(mObserver);
|
||||||
|
}
|
||||||
|
|
||||||
|
mCursor = cursor;
|
||||||
|
if (mCursor != null)
|
||||||
|
{
|
||||||
|
// Attempt to associate the new Cursor with the Observer.
|
||||||
|
if (mObserver != null)
|
||||||
|
{
|
||||||
|
mCursor.registerDataSetObserver(mObserver);
|
||||||
|
}
|
||||||
|
|
||||||
|
mDatasetValid = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mDatasetValid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -114,6 +215,7 @@ public class GameAdapter extends RecyclerView.Adapter<GameViewHolder> implements
|
|||||||
Intent intent = new Intent(view.getContext(), EmulationActivity.class);
|
Intent intent = new Intent(view.getContext(), EmulationActivity.class);
|
||||||
|
|
||||||
intent.putExtra("SelectedGame", holder.path);
|
intent.putExtra("SelectedGame", holder.path);
|
||||||
|
intent.putExtra("SelectedTitle", holder.title);
|
||||||
|
|
||||||
view.getContext().startActivity(intent);
|
view.getContext().startActivity(intent);
|
||||||
}
|
}
|
||||||
@ -134,7 +236,12 @@ public class GameAdapter extends RecyclerView.Adapter<GameViewHolder> implements
|
|||||||
// String gameId = (String) holder.gameId;
|
// String gameId = (String) holder.gameId;
|
||||||
|
|
||||||
Activity activity = (Activity) view.getContext();
|
Activity activity = (Activity) view.getContext();
|
||||||
GameDetailsDialog.newInstance(holder.game).show(activity.getFragmentManager(), "game_details");
|
GameDetailsDialog.newInstance(holder.title,
|
||||||
|
holder.description,
|
||||||
|
holder.country,
|
||||||
|
holder.company,
|
||||||
|
holder.path,
|
||||||
|
holder.screenshotPath).show(activity.getFragmentManager(), "game_details");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -158,9 +265,24 @@ public class GameAdapter extends RecyclerView.Adapter<GameViewHolder> implements
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setGameList(ArrayList<Game> gameList)
|
private final class GameDataSetObserver extends DataSetObserver
|
||||||
{
|
{
|
||||||
mGameList = gameList;
|
@Override
|
||||||
notifyDataSetChanged();
|
public void onChanged()
|
||||||
|
{
|
||||||
|
super.onChanged();
|
||||||
|
|
||||||
|
mDatasetValid = true;
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onInvalidated()
|
||||||
|
{
|
||||||
|
super.onInvalidated();
|
||||||
|
|
||||||
|
mDatasetValid = false;
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,12 +16,11 @@ import com.squareup.picasso.Picasso;
|
|||||||
|
|
||||||
import org.dolphinemu.dolphinemu.BuildConfig;
|
import org.dolphinemu.dolphinemu.BuildConfig;
|
||||||
import org.dolphinemu.dolphinemu.R;
|
import org.dolphinemu.dolphinemu.R;
|
||||||
import org.dolphinemu.dolphinemu.emulation.EmulationActivity;
|
import org.dolphinemu.dolphinemu.activities.EmulationActivity;
|
||||||
import org.dolphinemu.dolphinemu.model.Game;
|
|
||||||
|
|
||||||
import de.hdodenhof.circleimageview.CircleImageView;
|
import de.hdodenhof.circleimageview.CircleImageView;
|
||||||
|
|
||||||
public class GameDetailsDialog extends DialogFragment
|
public final class GameDetailsDialog extends DialogFragment
|
||||||
{
|
{
|
||||||
public static final String ARGUMENT_GAME_TITLE = BuildConfig.APPLICATION_ID + ".game_title";
|
public static final String ARGUMENT_GAME_TITLE = BuildConfig.APPLICATION_ID + ".game_title";
|
||||||
public static final String ARGUMENT_GAME_DESCRIPTION = BuildConfig.APPLICATION_ID + ".game_description";
|
public static final String ARGUMENT_GAME_DESCRIPTION = BuildConfig.APPLICATION_ID + ".game_description";
|
||||||
@ -30,18 +29,18 @@ public class GameDetailsDialog extends DialogFragment
|
|||||||
public static final String ARGUMENT_GAME_PATH = BuildConfig.APPLICATION_ID + ".game_path";
|
public static final String ARGUMENT_GAME_PATH = BuildConfig.APPLICATION_ID + ".game_path";
|
||||||
public static final String ARGUMENT_GAME_SCREENSHOT_PATH = BuildConfig.APPLICATION_ID + ".game_screenshot_path";
|
public static final String ARGUMENT_GAME_SCREENSHOT_PATH = BuildConfig.APPLICATION_ID + ".game_screenshot_path";
|
||||||
|
|
||||||
|
// TODO Add all of this to the Loader in GameActivity.java
|
||||||
public static GameDetailsDialog newInstance(Game game)
|
public static GameDetailsDialog newInstance(String title, String description, int country, String company, String path, String screenshotPath)
|
||||||
{
|
{
|
||||||
GameDetailsDialog fragment = new GameDetailsDialog();
|
GameDetailsDialog fragment = new GameDetailsDialog();
|
||||||
|
|
||||||
Bundle arguments = new Bundle();
|
Bundle arguments = new Bundle();
|
||||||
arguments.putString(ARGUMENT_GAME_TITLE, game.getTitle());
|
arguments.putString(ARGUMENT_GAME_TITLE, title);
|
||||||
arguments.putString(ARGUMENT_GAME_DESCRIPTION, game.getDescription());
|
arguments.putString(ARGUMENT_GAME_DESCRIPTION, description);
|
||||||
arguments.putString(ARGUMENT_GAME_COUNTRY, game.getCountry());
|
arguments.putInt(ARGUMENT_GAME_COUNTRY, country);
|
||||||
arguments.putString(ARGUMENT_GAME_DATE, game.getDate());
|
arguments.putString(ARGUMENT_GAME_DATE, company);
|
||||||
arguments.putString(ARGUMENT_GAME_PATH, game.getPath());
|
arguments.putString(ARGUMENT_GAME_PATH, path);
|
||||||
arguments.putString(ARGUMENT_GAME_SCREENSHOT_PATH, game.getScreenPath());
|
arguments.putString(ARGUMENT_GAME_SCREENSHOT_PATH, screenshotPath);
|
||||||
fragment.setArguments(arguments);
|
fragment.setArguments(arguments);
|
||||||
|
|
||||||
return fragment;
|
return fragment;
|
||||||
@ -57,16 +56,19 @@ public class GameDetailsDialog extends DialogFragment
|
|||||||
CircleImageView circleBanner = (CircleImageView) contents.findViewById(R.id.circle_banner);
|
CircleImageView circleBanner = (CircleImageView) contents.findViewById(R.id.circle_banner);
|
||||||
|
|
||||||
TextView textTitle = (TextView) contents.findViewById(R.id.text_game_title);
|
TextView textTitle = (TextView) contents.findViewById(R.id.text_game_title);
|
||||||
TextView textDescription = (TextView) contents.findViewById(R.id.text_game_description);
|
TextView textDescription = (TextView) contents.findViewById(R.id.text_company);
|
||||||
|
|
||||||
TextView textCountry = (TextView) contents.findViewById(R.id.text_country);
|
TextView textCountry = (TextView) contents.findViewById(R.id.text_country);
|
||||||
TextView textDate = (TextView) contents.findViewById(R.id.text_date);
|
TextView textDate = (TextView) contents.findViewById(R.id.text_date);
|
||||||
|
|
||||||
ImageButton buttonLaunch = (ImageButton) contents.findViewById(R.id.button_launch);
|
ImageButton buttonLaunch = (ImageButton) contents.findViewById(R.id.button_launch);
|
||||||
|
|
||||||
|
int countryIndex = getArguments().getInt(ARGUMENT_GAME_COUNTRY);
|
||||||
|
String country = getResources().getStringArray(R.array.country_names)[countryIndex];
|
||||||
|
|
||||||
textTitle.setText(getArguments().getString(ARGUMENT_GAME_TITLE));
|
textTitle.setText(getArguments().getString(ARGUMENT_GAME_TITLE));
|
||||||
textDescription.setText(getArguments().getString(ARGUMENT_GAME_DESCRIPTION));
|
textDescription.setText(getArguments().getString(ARGUMENT_GAME_DESCRIPTION));
|
||||||
textCountry.setText(getArguments().getString(ARGUMENT_GAME_COUNTRY));
|
textCountry.setText(country);
|
||||||
textDate.setText(getArguments().getString(ARGUMENT_GAME_DATE));
|
textDate.setText(getArguments().getString(ARGUMENT_GAME_DATE));
|
||||||
buttonLaunch.setOnClickListener(new View.OnClickListener()
|
buttonLaunch.setOnClickListener(new View.OnClickListener()
|
||||||
{
|
{
|
||||||
@ -77,6 +79,8 @@ public class GameDetailsDialog extends DialogFragment
|
|||||||
Intent intent = new Intent(view.getContext(), EmulationActivity.class);
|
Intent intent = new Intent(view.getContext(), EmulationActivity.class);
|
||||||
|
|
||||||
intent.putExtra("SelectedGame", getArguments().getString(ARGUMENT_GAME_PATH));
|
intent.putExtra("SelectedGame", getArguments().getString(ARGUMENT_GAME_PATH));
|
||||||
|
intent.putExtra("SelectedTitle", getArguments().getString(ARGUMENT_GAME_TITLE));
|
||||||
|
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -0,0 +1,114 @@
|
|||||||
|
package org.dolphinemu.dolphinemu.fragments;
|
||||||
|
|
||||||
|
import android.app.Fragment;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import org.dolphinemu.dolphinemu.BuildConfig;
|
||||||
|
import org.dolphinemu.dolphinemu.NativeLibrary;
|
||||||
|
import org.dolphinemu.dolphinemu.R;
|
||||||
|
import org.dolphinemu.dolphinemu.emulation.overlay.InputOverlay;
|
||||||
|
|
||||||
|
|
||||||
|
public final class EmulationFragment extends Fragment
|
||||||
|
{
|
||||||
|
public static final String FRAGMENT_TAG = BuildConfig.APPLICATION_ID + ".emulation_fragment";
|
||||||
|
|
||||||
|
private static final String ARGUMENT_GAME_PATH = BuildConfig.APPLICATION_ID + ".game_path";
|
||||||
|
|
||||||
|
private SharedPreferences mPreferences;
|
||||||
|
|
||||||
|
private InputOverlay mInputOverlay;
|
||||||
|
|
||||||
|
public static EmulationFragment newInstance(String path)
|
||||||
|
{
|
||||||
|
EmulationFragment fragment = new EmulationFragment();
|
||||||
|
|
||||||
|
Bundle arguments = new Bundle();
|
||||||
|
arguments.putString(ARGUMENT_GAME_PATH, path);
|
||||||
|
fragment.setArguments(arguments);
|
||||||
|
|
||||||
|
return fragment;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize anything that doesn't depend on the layout / views in here.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState)
|
||||||
|
{
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
mPreferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the UI and start emulation in here.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
|
||||||
|
{
|
||||||
|
String path = getArguments().getString(ARGUMENT_GAME_PATH);
|
||||||
|
|
||||||
|
View contents = inflater.inflate(R.layout.fragment_emulation, container, false);
|
||||||
|
|
||||||
|
mInputOverlay = (InputOverlay) contents.findViewById(R.id.surface_input_overlay);
|
||||||
|
|
||||||
|
NativeLibrary.SetFilename(path);
|
||||||
|
|
||||||
|
|
||||||
|
// If the input overlay was previously disabled, then don't show it.
|
||||||
|
if (!mPreferences.getBoolean("showInputOverlay", true))
|
||||||
|
{
|
||||||
|
mInputOverlay.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return contents;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStart()
|
||||||
|
{
|
||||||
|
super.onStart();
|
||||||
|
NativeLibrary.UnPauseEmulation();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStop()
|
||||||
|
{
|
||||||
|
super.onStop();
|
||||||
|
NativeLibrary.PauseEmulation();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroyView()
|
||||||
|
{
|
||||||
|
super.onDestroyView();
|
||||||
|
NativeLibrary.StopEmulation();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void toggleInputOverlayVisibility()
|
||||||
|
{
|
||||||
|
SharedPreferences.Editor editor = mPreferences.edit();
|
||||||
|
|
||||||
|
// If the overlay is currently set to INVISIBLE
|
||||||
|
if (!mPreferences.getBoolean("showInputOverlay", false))
|
||||||
|
{
|
||||||
|
// Set it to VISIBLE
|
||||||
|
mInputOverlay.setVisibility(View.VISIBLE);
|
||||||
|
editor.putBoolean("showInputOverlay", true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Set it to INVISIBLE
|
||||||
|
mInputOverlay.setVisibility(View.GONE);
|
||||||
|
editor.putBoolean("showInputOverlay", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
editor.apply();
|
||||||
|
}
|
||||||
|
}
|
@ -13,7 +13,8 @@ public class FileListItem implements Comparable<FileListItem>
|
|||||||
public static final int TYPE_FOLDER = 0;
|
public static final int TYPE_FOLDER = 0;
|
||||||
public static final int TYPE_GC = 1;
|
public static final int TYPE_GC = 1;
|
||||||
public static final int TYPE_WII = 2;
|
public static final int TYPE_WII = 2;
|
||||||
public static final int TYPE_OTHER = 3;
|
public static final int TYPE_WII_WARE = 3;
|
||||||
|
public static final int TYPE_OTHER = 4;
|
||||||
|
|
||||||
private int mType;
|
private int mType;
|
||||||
private String mFilename;
|
private String mFilename;
|
||||||
@ -30,8 +31,6 @@ public class FileListItem implements Comparable<FileListItem>
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
String fileExtension = null;
|
|
||||||
|
|
||||||
int extensionStart = mPath.lastIndexOf('.');
|
int extensionStart = mPath.lastIndexOf('.');
|
||||||
if (extensionStart < 1)
|
if (extensionStart < 1)
|
||||||
{
|
{
|
||||||
@ -40,7 +39,7 @@ public class FileListItem implements Comparable<FileListItem>
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fileExtension = mPath.substring(extensionStart);
|
String fileExtension = mPath.substring(extensionStart);
|
||||||
|
|
||||||
// The extensions we care about.
|
// The extensions we care about.
|
||||||
Set<String> allowedExtensions = new HashSet<String>(Arrays.asList(".dff", ".dol", ".elf", ".gcm", ".gcz", ".iso", ".wad", ".wbfs"));
|
Set<String> allowedExtensions = new HashSet<String>(Arrays.asList(".dff", ".dol", ".elf", ".gcm", ".gcz", ".iso", ".wad", ".wbfs"));
|
||||||
@ -48,7 +47,8 @@ public class FileListItem implements Comparable<FileListItem>
|
|||||||
// Check that the file has an extension we care about before trying to read out of it.
|
// Check that the file has an extension we care about before trying to read out of it.
|
||||||
if (allowedExtensions.contains(fileExtension))
|
if (allowedExtensions.contains(fileExtension))
|
||||||
{
|
{
|
||||||
mType = NativeLibrary.IsWiiTitle(mPath) ? TYPE_WII : TYPE_GC;
|
// Add 1 because 0 = TYPE_FOLDER
|
||||||
|
mType = NativeLibrary.GetPlatform(mPath) + 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1,23 +1,154 @@
|
|||||||
package org.dolphinemu.dolphinemu.model;
|
package org.dolphinemu.dolphinemu.model;
|
||||||
|
|
||||||
public interface Game
|
import android.content.ContentValues;
|
||||||
|
import android.database.Cursor;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
public final class Game
|
||||||
{
|
{
|
||||||
public static final int PLATFORM_GC = 0;
|
public static final int PLATFORM_GC = 0;
|
||||||
public static final int PLATFORM_WII = 1;
|
public static final int PLATFORM_WII = 1;
|
||||||
|
public static final int PLATFORM_WII_WARE = 2;
|
||||||
|
|
||||||
public int getPlatform();
|
// Copied from IVolume::ECountry. Update these if that is ever modified.
|
||||||
|
public static final int COUNTRY_EUROPE = 0;
|
||||||
|
public static final int COUNTRY_JAPAN = 1;
|
||||||
|
public static final int COUNTRY_USA = 2;
|
||||||
|
public static final int COUNTRY_AUSTRALIA = 3;
|
||||||
|
public static final int COUNTRY_FRANCE = 4;
|
||||||
|
public static final int COUNTRY_GERMANY = 5;
|
||||||
|
public static final int COUNTRY_ITALY = 6;
|
||||||
|
public static final int COUNTRY_KOREA = 7;
|
||||||
|
public static final int COUNTRY_NETHERLANDS = 8;
|
||||||
|
public static final int COUNTRY_RUSSIA = 9;
|
||||||
|
public static final int COUNTRY_SPAIN = 10;
|
||||||
|
public static final int COUNTRY_TAIWAN = 11;
|
||||||
|
public static final int COUNTRY_WORLD = 12;
|
||||||
|
public static final int COUNTRY_UNKNOWN = 13;
|
||||||
|
|
||||||
public String getDate();
|
private static final String PATH_SCREENSHOT_FOLDER = "file:///sdcard/dolphin-emu/ScreenShots/";
|
||||||
|
|
||||||
public String getTitle();
|
private String mTitle;
|
||||||
|
private String mDescription;
|
||||||
|
private String mPath;
|
||||||
|
private String mGameId;
|
||||||
|
private String mScreenshotFolderPath;
|
||||||
|
private String mCompany;
|
||||||
|
|
||||||
public String getDescription();
|
private int mPlatform;
|
||||||
|
private int mCountry;
|
||||||
|
|
||||||
public String getCountry();
|
public Game(int platform, String title, String description, int country, String path, String gameId, String company)
|
||||||
|
{
|
||||||
|
mPlatform = platform;
|
||||||
|
mTitle = title;
|
||||||
|
mDescription = description;
|
||||||
|
mCountry = country;
|
||||||
|
mPath = path;
|
||||||
|
mGameId = gameId;
|
||||||
|
mCompany = company;
|
||||||
|
mScreenshotFolderPath = PATH_SCREENSHOT_FOLDER + getGameId() + "/";
|
||||||
|
}
|
||||||
|
|
||||||
public String getPath();
|
public int getPlatform()
|
||||||
|
{
|
||||||
|
return mPlatform;
|
||||||
|
}
|
||||||
|
|
||||||
public String getGameId();
|
public String getTitle()
|
||||||
|
{
|
||||||
|
return mTitle;
|
||||||
|
}
|
||||||
|
|
||||||
public String getScreenPath();
|
public String getDescription()
|
||||||
|
{
|
||||||
|
return mDescription;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCompany()
|
||||||
|
{
|
||||||
|
return mCompany;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCountry()
|
||||||
|
{
|
||||||
|
return mCountry;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPath()
|
||||||
|
{
|
||||||
|
return mPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGameId()
|
||||||
|
{
|
||||||
|
return mGameId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getScreenshotFolderPath()
|
||||||
|
{
|
||||||
|
return mScreenshotFolderPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getScreenPath()
|
||||||
|
{
|
||||||
|
// Count how many screenshots are available, so we can use the most recent one.
|
||||||
|
File screenshotFolder = new File(mScreenshotFolderPath.substring(mScreenshotFolderPath.indexOf('s') - 1));
|
||||||
|
int screenCount = 0;
|
||||||
|
|
||||||
|
if (screenshotFolder.isDirectory())
|
||||||
|
{
|
||||||
|
screenCount = screenshotFolder.list().length;
|
||||||
|
}
|
||||||
|
|
||||||
|
String screenPath = mScreenshotFolderPath
|
||||||
|
+ getGameId() + "-"
|
||||||
|
+ screenCount + ".png";
|
||||||
|
|
||||||
|
return screenPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ContentValues asContentValues(int platform, String title, String description, int country, String path, String gameId, String company)
|
||||||
|
{
|
||||||
|
ContentValues values = new ContentValues();
|
||||||
|
|
||||||
|
// TODO Come up with a way of finding the most recent screenshot that doesn't involve counting files
|
||||||
|
String screenshotFolderPath = PATH_SCREENSHOT_FOLDER + gameId + "/";
|
||||||
|
|
||||||
|
// Count how many screenshots are available, so we can use the most recent one.
|
||||||
|
File screenshotFolder = new File(screenshotFolderPath.substring(screenshotFolderPath.indexOf('s') - 1));
|
||||||
|
int screenCount = 0;
|
||||||
|
|
||||||
|
if (screenshotFolder.isDirectory())
|
||||||
|
{
|
||||||
|
screenCount = screenshotFolder.list().length;
|
||||||
|
}
|
||||||
|
|
||||||
|
String screenPath = screenshotFolderPath
|
||||||
|
+ gameId + "-"
|
||||||
|
+ screenCount + ".png";
|
||||||
|
|
||||||
|
values.put(GameDatabase.KEY_GAME_PLATFORM, platform);
|
||||||
|
values.put(GameDatabase.KEY_GAME_TITLE, title);
|
||||||
|
values.put(GameDatabase.KEY_GAME_DESCRIPTION, description);
|
||||||
|
values.put(GameDatabase.KEY_GAME_COUNTRY, company);
|
||||||
|
values.put(GameDatabase.KEY_GAME_PATH, path);
|
||||||
|
values.put(GameDatabase.KEY_GAME_ID, gameId);
|
||||||
|
values.put(GameDatabase.KEY_GAME_COMPANY, company);
|
||||||
|
values.put(GameDatabase.KEY_GAME_SCREENSHOT_PATH, screenPath);
|
||||||
|
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Game fromCursor(Cursor cursor)
|
||||||
|
{
|
||||||
|
return new Game(cursor.getInt(GameDatabase.GAME_COLUMN_PLATFORM),
|
||||||
|
cursor.getString(GameDatabase.GAME_COLUMN_TITLE),
|
||||||
|
cursor.getString(GameDatabase.GAME_COLUMN_DESCRIPTION),
|
||||||
|
cursor.getInt(GameDatabase.GAME_COLUMN_COUNTRY),
|
||||||
|
cursor.getString(GameDatabase.GAME_COLUMN_PATH),
|
||||||
|
cursor.getString(GameDatabase.GAME_COLUMN_GAME_ID),
|
||||||
|
cursor.getString(GameDatabase.GAME_COLUMN_COMPANY));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,190 @@
|
|||||||
|
package org.dolphinemu.dolphinemu.model;
|
||||||
|
|
||||||
|
import android.content.ContentValues;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
|
import android.database.sqlite.SQLiteOpenHelper;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import org.dolphinemu.dolphinemu.NativeLibrary;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A helper class that provides several utilities simplifying interaction with
|
||||||
|
* the SQLite database.
|
||||||
|
*/
|
||||||
|
public final class GameDatabase extends SQLiteOpenHelper
|
||||||
|
{
|
||||||
|
private static final int DB_VERSION = 1;
|
||||||
|
|
||||||
|
public static final int COLUMN_DB_ID = 0;
|
||||||
|
|
||||||
|
public static final int GAME_COLUMN_PATH = 1;
|
||||||
|
public static final int GAME_COLUMN_PLATFORM = 2;
|
||||||
|
public static final int GAME_COLUMN_TITLE = 3;
|
||||||
|
public static final int GAME_COLUMN_DESCRIPTION = 4;
|
||||||
|
public static final int GAME_COLUMN_COUNTRY = 5;
|
||||||
|
public static final int GAME_COLUMN_GAME_ID = 6;
|
||||||
|
public static final int GAME_COLUMN_COMPANY = 7;
|
||||||
|
public static final int GAME_COLUMN_SCREENSHOT_PATH = 8;
|
||||||
|
|
||||||
|
public static final int FOLDER_COLUMN_PATH = 1;
|
||||||
|
|
||||||
|
public static final String KEY_DB_ID = "_id";
|
||||||
|
|
||||||
|
public static final String KEY_GAME_PATH = "path";
|
||||||
|
public static final String KEY_GAME_PLATFORM = "platform";
|
||||||
|
public static final String KEY_GAME_TITLE = "title";
|
||||||
|
public static final String KEY_GAME_DESCRIPTION = "description";
|
||||||
|
public static final String KEY_GAME_COUNTRY = "country";
|
||||||
|
public static final String KEY_GAME_ID = "game_id";
|
||||||
|
public static final String KEY_GAME_COMPANY = "company";
|
||||||
|
public static final String KEY_GAME_SCREENSHOT_PATH = "screenshot_path";
|
||||||
|
|
||||||
|
public static final String KEY_FOLDER_PATH = "path";
|
||||||
|
|
||||||
|
public static final String TABLE_NAME_FOLDERS = "folders";
|
||||||
|
public static final String TABLE_NAME_GAMES = "games";
|
||||||
|
|
||||||
|
private static final String TYPE_PRIMARY = " INTEGER PRIMARY KEY";
|
||||||
|
private static final String TYPE_INTEGER = " INTEGER";
|
||||||
|
private static final String TYPE_STRING = " TEXT";
|
||||||
|
|
||||||
|
private static final String CONSTRAINT_UNIQUE = " UNIQUE";
|
||||||
|
|
||||||
|
private static final String SEPARATOR = ", ";
|
||||||
|
|
||||||
|
private static final String SQL_CREATE_GAMES = "CREATE TABLE " + TABLE_NAME_GAMES + "("
|
||||||
|
+ KEY_DB_ID + TYPE_PRIMARY + SEPARATOR
|
||||||
|
+ KEY_GAME_PATH + TYPE_STRING + SEPARATOR
|
||||||
|
+ KEY_GAME_PLATFORM + TYPE_STRING + SEPARATOR
|
||||||
|
+ KEY_GAME_TITLE + TYPE_STRING + SEPARATOR
|
||||||
|
+ KEY_GAME_DESCRIPTION + TYPE_STRING + SEPARATOR
|
||||||
|
+ KEY_GAME_COUNTRY + TYPE_INTEGER + SEPARATOR
|
||||||
|
+ KEY_GAME_ID + TYPE_STRING + SEPARATOR
|
||||||
|
+ KEY_GAME_COMPANY + TYPE_STRING + SEPARATOR
|
||||||
|
+ KEY_GAME_SCREENSHOT_PATH + TYPE_STRING + ")";
|
||||||
|
|
||||||
|
private static final String SQL_CREATE_FOLDERS = "CREATE TABLE " + TABLE_NAME_FOLDERS + "("
|
||||||
|
+ KEY_DB_ID + TYPE_PRIMARY + SEPARATOR
|
||||||
|
+ KEY_FOLDER_PATH + TYPE_STRING + CONSTRAINT_UNIQUE + ")";
|
||||||
|
|
||||||
|
private static final String SQL_DELETE_GAMES = "DROP TABLE IF EXISTS " + TABLE_NAME_GAMES;
|
||||||
|
|
||||||
|
public GameDatabase(Context context)
|
||||||
|
{
|
||||||
|
// Superclass constructor builds a database or uses an existing one.
|
||||||
|
super(context, "games.db", null, DB_VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(SQLiteDatabase database)
|
||||||
|
{
|
||||||
|
Log.d("DolphinEmu", "GameDatabase - Creating database...");
|
||||||
|
|
||||||
|
Log.v("DolphinEmu", "Executing SQL: " + SQL_CREATE_GAMES);
|
||||||
|
database.execSQL(SQL_CREATE_GAMES);
|
||||||
|
|
||||||
|
Log.v("DolphinEmu", "Executing SQL: " + SQL_CREATE_FOLDERS);
|
||||||
|
database.execSQL(SQL_CREATE_FOLDERS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUpgrade(SQLiteDatabase database, int oldVersion, int newVersion)
|
||||||
|
{
|
||||||
|
Log.i("DolphinEmu", "Upgrading database from schema version " + oldVersion + " to " + newVersion);
|
||||||
|
|
||||||
|
Log.v("DolphinEmu", "Executing SQL: " + SQL_DELETE_GAMES);
|
||||||
|
database.execSQL(SQL_DELETE_GAMES);
|
||||||
|
|
||||||
|
Log.v("DolphinEmu", "Executing SQL: " + SQL_CREATE_GAMES);
|
||||||
|
database.execSQL(SQL_CREATE_GAMES);
|
||||||
|
|
||||||
|
Log.v("DolphinEmu", "Re-scanning library with new schema.");
|
||||||
|
scanLibrary(database);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void scanLibrary(SQLiteDatabase database)
|
||||||
|
{
|
||||||
|
// TODO Before scanning known folders, go through the game table and remove any entries for which the file itself is missing.
|
||||||
|
|
||||||
|
// Get a cursor listing all the folders the user has added to the library.
|
||||||
|
Cursor cursor = database.query(TABLE_NAME_FOLDERS,
|
||||||
|
null, // Get all columns.
|
||||||
|
null, // Get all rows.
|
||||||
|
null,
|
||||||
|
null, // No grouping.
|
||||||
|
null,
|
||||||
|
null); // Order of folders is irrelevant.
|
||||||
|
|
||||||
|
Set<String> allowedExtensions = new HashSet<String>(Arrays.asList(".dff", ".dol", ".elf", ".gcm", ".gcz", ".iso", ".wad", ".wbfs"));
|
||||||
|
|
||||||
|
// Possibly overly defensive, but ensures that moveToNext() does not skip a row.
|
||||||
|
cursor.moveToPosition(-1);
|
||||||
|
|
||||||
|
// Iterate through all results of the DB query (i.e. all folders in the library.)
|
||||||
|
while (cursor.moveToNext())
|
||||||
|
{
|
||||||
|
|
||||||
|
String folderPath = cursor.getString(FOLDER_COLUMN_PATH);
|
||||||
|
File folder = new File(folderPath);
|
||||||
|
|
||||||
|
Log.i("DolphinEmu", "Reading files from library folder: " + folderPath);
|
||||||
|
|
||||||
|
// Iterate through every file in the folder.
|
||||||
|
File[] children = folder.listFiles();
|
||||||
|
for (File file : children)
|
||||||
|
{
|
||||||
|
if (!file.isHidden() && !file.isDirectory())
|
||||||
|
{
|
||||||
|
String filePath = file.getPath();
|
||||||
|
|
||||||
|
int extensionStart = filePath.lastIndexOf('.');
|
||||||
|
if (extensionStart > 0)
|
||||||
|
{
|
||||||
|
String fileExtension = filePath.substring(extensionStart);
|
||||||
|
|
||||||
|
// Check that the file has an extension we care about before trying to read out of it.
|
||||||
|
if (allowedExtensions.contains(fileExtension))
|
||||||
|
{
|
||||||
|
ContentValues game = Game.asContentValues(NativeLibrary.GetPlatform(filePath),
|
||||||
|
NativeLibrary.GetTitle(filePath),
|
||||||
|
NativeLibrary.GetDescription(filePath).replace("\n", " "),
|
||||||
|
NativeLibrary.GetCountry(filePath),
|
||||||
|
filePath,
|
||||||
|
NativeLibrary.GetGameId(filePath),
|
||||||
|
NativeLibrary.GetCompany(filePath));
|
||||||
|
|
||||||
|
// Try to update an existing game first.
|
||||||
|
int rowsMatched = database.update(TABLE_NAME_GAMES, // Which table to update.
|
||||||
|
game, // The values to fill the row with.
|
||||||
|
KEY_GAME_ID + " = ?", // The WHERE clause used to find the right row.
|
||||||
|
new String[]{game.getAsString(KEY_GAME_ID)}); // The ? in WHERE clause is replaced with this,
|
||||||
|
// which is provided as an array because there
|
||||||
|
// could potentially be more than one argument.
|
||||||
|
|
||||||
|
// If update fails, insert a new game instead.
|
||||||
|
if (rowsMatched == 0)
|
||||||
|
{
|
||||||
|
Log.v("DolphinEmu", "Adding game: " + game.getAsString(KEY_GAME_TITLE));
|
||||||
|
database.insert(TABLE_NAME_GAMES, null, game);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log.v("DolphinEmu", "Updated game: " + game.getAsString(KEY_GAME_TITLE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor.close();
|
||||||
|
database.close();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,138 @@
|
|||||||
|
package org.dolphinemu.dolphinemu.model;
|
||||||
|
|
||||||
|
import android.content.ContentProvider;
|
||||||
|
import android.content.ContentValues;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import org.dolphinemu.dolphinemu.BuildConfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides an interface allowing Activities to interact with the SQLite database.
|
||||||
|
* CRUD methods in this class can be called by Activities using getContentResolver().
|
||||||
|
*/
|
||||||
|
public final class GameProvider extends ContentProvider
|
||||||
|
{
|
||||||
|
public static final String AUTHORITY = "content://" + BuildConfig.APPLICATION_ID + ".provider";
|
||||||
|
public static final Uri URI_FOLDER = Uri.parse(AUTHORITY + "/" + GameDatabase.TABLE_NAME_FOLDERS + "/");
|
||||||
|
public static final Uri URI_GAME = Uri.parse(AUTHORITY + "/" + GameDatabase.TABLE_NAME_GAMES + "/");
|
||||||
|
|
||||||
|
public static final String MIME_TYPE_FOLDER = "vnd.android.cursor.item/vnd.dolphin.folder";
|
||||||
|
public static final String MIME_TYPE_GAME = "vnd.android.cursor.item/vnd.dolphin.game";
|
||||||
|
|
||||||
|
private GameDatabase mDbHelper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCreate()
|
||||||
|
{
|
||||||
|
Log.i("DolphinEmu", "Creating Content Provider...");
|
||||||
|
|
||||||
|
mDbHelper = new GameDatabase(getContext());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
|
||||||
|
{
|
||||||
|
Log.i("DolphinEmu", "Querying URI: " + uri);
|
||||||
|
|
||||||
|
SQLiteDatabase db = mDbHelper.getReadableDatabase();
|
||||||
|
|
||||||
|
String table = uri.getLastPathSegment();
|
||||||
|
|
||||||
|
if (table == null)
|
||||||
|
{
|
||||||
|
Log.e("DolphinEmu", "Badly formatted URI: " + uri);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Cursor cursor = db.query(table, projection, selection, selectionArgs, null, null, sortOrder);
|
||||||
|
cursor.setNotificationUri(getContext().getContentResolver(), uri);
|
||||||
|
|
||||||
|
return cursor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getType(Uri uri)
|
||||||
|
{
|
||||||
|
Log.v("DolphinEmu", "Getting MIME type for URI: " + uri);
|
||||||
|
String lastSegment = uri.getLastPathSegment();
|
||||||
|
|
||||||
|
if (lastSegment == null)
|
||||||
|
{
|
||||||
|
Log.e("DolphinEmu", "Badly formatted URI: " + uri);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastSegment.equals(GameDatabase.TABLE_NAME_FOLDERS))
|
||||||
|
{
|
||||||
|
return MIME_TYPE_FOLDER;
|
||||||
|
}
|
||||||
|
else if (lastSegment.equals(GameDatabase.TABLE_NAME_GAMES))
|
||||||
|
{
|
||||||
|
return MIME_TYPE_GAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.e("DolphinEmu", "Unknown MIME type for URI: " + uri);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Uri insert(Uri uri, ContentValues values)
|
||||||
|
{
|
||||||
|
Log.i("DolphinEmu", "Inserting row at URI: " + uri);
|
||||||
|
|
||||||
|
SQLiteDatabase database = mDbHelper.getWritableDatabase();
|
||||||
|
String table = uri.getLastPathSegment();
|
||||||
|
|
||||||
|
long id = -1;
|
||||||
|
|
||||||
|
if (table != null)
|
||||||
|
{
|
||||||
|
id = database.insertWithOnConflict(table, null, values, SQLiteDatabase.CONFLICT_IGNORE);
|
||||||
|
|
||||||
|
// If insertion was successful...
|
||||||
|
if (id > 0)
|
||||||
|
{
|
||||||
|
// If we just added a folder, add its contents to the game list.
|
||||||
|
if (table.equals(GameDatabase.TABLE_NAME_FOLDERS))
|
||||||
|
{
|
||||||
|
mDbHelper.scanLibrary(database);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Notify the UI that its contents should be refreshed.
|
||||||
|
getContext().getContentResolver().notifyChange(uri, null);
|
||||||
|
uri = Uri.withAppendedPath(uri, Long.toString(id));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log.e("DolphinEmu", "Row already exists: " + uri + " id: " + id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log.e("DolphinEmu", "Badly formatted URI: " + uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
database.close();
|
||||||
|
|
||||||
|
return uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int delete(Uri uri, String selection, String[] selectionArgs)
|
||||||
|
{
|
||||||
|
Log.e("DolphinEmu", "Delete operations unsupported. URI: " + uri);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)
|
||||||
|
{
|
||||||
|
Log.e("DolphinEmu", "Update operations unsupported. URI: " + uri);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
@ -1,96 +0,0 @@
|
|||||||
package org.dolphinemu.dolphinemu.model;
|
|
||||||
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
|
|
||||||
public final class GcGame implements Game
|
|
||||||
{
|
|
||||||
private String mTitle;
|
|
||||||
private String mDescription;
|
|
||||||
private String mCountry;
|
|
||||||
private String mPath;
|
|
||||||
private String mGameId;
|
|
||||||
|
|
||||||
private String mScreenshotFolderPath;
|
|
||||||
|
|
||||||
private String mDate;
|
|
||||||
private int mPlatform = PLATFORM_GC;
|
|
||||||
|
|
||||||
private static final String PATH_SCREENSHOT_FOLDER = "file:///sdcard/dolphin-emu/ScreenShots/";
|
|
||||||
|
|
||||||
public GcGame(String title, String description, String country, String path, String gameId, String date)
|
|
||||||
{
|
|
||||||
mTitle = title;
|
|
||||||
mDescription = description;
|
|
||||||
mCountry = country;
|
|
||||||
mPath = path;
|
|
||||||
mGameId = gameId;
|
|
||||||
mDate = date;
|
|
||||||
mScreenshotFolderPath = PATH_SCREENSHOT_FOLDER + getGameId() + "/";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getPlatform()
|
|
||||||
{
|
|
||||||
return mPlatform;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getTitle()
|
|
||||||
{
|
|
||||||
return mTitle;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getDescription()
|
|
||||||
{
|
|
||||||
return mDescription;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getDate()
|
|
||||||
{
|
|
||||||
return mDate;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getCountry()
|
|
||||||
{
|
|
||||||
return mCountry;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getPath()
|
|
||||||
{
|
|
||||||
return mPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getGameId()
|
|
||||||
{
|
|
||||||
return mGameId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getScreenshotFolderPath()
|
|
||||||
{
|
|
||||||
return mScreenshotFolderPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getScreenPath()
|
|
||||||
{
|
|
||||||
// Count how many screenshots are available, so we can use the most recent one.
|
|
||||||
File screenshotFolder = new File(mScreenshotFolderPath.substring(mScreenshotFolderPath.indexOf('s') - 1));
|
|
||||||
int screenCount = 0;
|
|
||||||
|
|
||||||
if (screenshotFolder.isDirectory())
|
|
||||||
{
|
|
||||||
screenCount = screenshotFolder.list().length;
|
|
||||||
}
|
|
||||||
|
|
||||||
String screenPath = mScreenshotFolderPath
|
|
||||||
+ getGameId() + "-"
|
|
||||||
+ screenCount + ".png";
|
|
||||||
|
|
||||||
return screenPath;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,53 +0,0 @@
|
|||||||
package org.dolphinemu.dolphinemu.model;
|
|
||||||
|
|
||||||
|
|
||||||
public final class WiiGame implements Game
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public int getPlatform()
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getDate()
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getTitle()
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getDescription()
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getCountry()
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getPath()
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getGameId()
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getScreenPath()
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
@ -7,7 +7,10 @@ import android.widget.TextView;
|
|||||||
|
|
||||||
import org.dolphinemu.dolphinemu.R;
|
import org.dolphinemu.dolphinemu.R;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple class that stores references to views so that the FileAdapter doesn't need to
|
||||||
|
* keep calling findViewById(), which is expensive.
|
||||||
|
*/
|
||||||
public class FileViewHolder extends RecyclerView.ViewHolder
|
public class FileViewHolder extends RecyclerView.ViewHolder
|
||||||
{
|
{
|
||||||
public View itemView;
|
public View itemView;
|
||||||
|
@ -1,29 +1,31 @@
|
|||||||
package org.dolphinemu.dolphinemu.viewholders;
|
package org.dolphinemu.dolphinemu.viewholders;
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.ImageButton;
|
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import org.dolphinemu.dolphinemu.R;
|
import org.dolphinemu.dolphinemu.R;
|
||||||
import org.dolphinemu.dolphinemu.dialogs.GameDetailsDialog;
|
|
||||||
import org.dolphinemu.dolphinemu.emulation.EmulationActivity;
|
|
||||||
import org.dolphinemu.dolphinemu.model.Game;
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple class that stores references to views so that the GameAdapter doesn't need to
|
||||||
|
* keep calling findViewById(), which is expensive.
|
||||||
|
*/
|
||||||
public class GameViewHolder extends RecyclerView.ViewHolder
|
public class GameViewHolder extends RecyclerView.ViewHolder
|
||||||
{
|
{
|
||||||
public ImageView imageScreenshot;
|
public ImageView imageScreenshot;
|
||||||
public TextView textGameTitle;
|
public TextView textGameTitle;
|
||||||
public TextView textDescription;
|
public TextView textCompany;
|
||||||
|
|
||||||
// Used to handle onClick(). Set this in onBindViewHolder().
|
public String gameId;
|
||||||
|
|
||||||
|
// TODO Not need any of this stuff. Currently only the properties dialog needs it.
|
||||||
public String path;
|
public String path;
|
||||||
|
public String title;
|
||||||
|
public String description;
|
||||||
|
public int country;
|
||||||
|
public String company;
|
||||||
public String screenshotPath;
|
public String screenshotPath;
|
||||||
public Game game;
|
|
||||||
|
|
||||||
public GameViewHolder(View itemView)
|
public GameViewHolder(View itemView)
|
||||||
{
|
{
|
||||||
@ -33,6 +35,6 @@ public class GameViewHolder extends RecyclerView.ViewHolder
|
|||||||
|
|
||||||
imageScreenshot = (ImageView) itemView.findViewById(R.id.image_game_screen);
|
imageScreenshot = (ImageView) itemView.findViewById(R.id.image_game_screen);
|
||||||
textGameTitle = (TextView) itemView.findViewById(R.id.text_game_title);
|
textGameTitle = (TextView) itemView.findViewById(R.id.text_game_title);
|
||||||
textDescription = (TextView) itemView.findViewById(R.id.text_game_description);
|
textCompany = (TextView) itemView.findViewById(R.id.text_company);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
BIN
Source/Android/app/src/main/res/drawable-hdpi/ic_company.png
Normal file
BIN
Source/Android/app/src/main/res/drawable-hdpi/ic_company.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 288 B |
BIN
Source/Android/app/src/main/res/drawable-mdpi/ic_company.png
Normal file
BIN
Source/Android/app/src/main/res/drawable-mdpi/ic_company.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 255 B |
BIN
Source/Android/app/src/main/res/drawable-xhdpi/ic_company.png
Normal file
BIN
Source/Android/app/src/main/res/drawable-xhdpi/ic_company.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 242 B |
BIN
Source/Android/app/src/main/res/drawable-xxhdpi/ic_company.png
Normal file
BIN
Source/Android/app/src/main/res/drawable-xxhdpi/ic_company.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 367 B |
BIN
Source/Android/app/src/main/res/drawable-xxxhdpi/ic_company.png
Normal file
BIN
Source/Android/app/src/main/res/drawable-xxxhdpi/ic_company.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 411 B |
@ -2,7 +2,7 @@
|
|||||||
android:color="?android:colorControlHighlight">
|
android:color="?android:colorControlHighlight">
|
||||||
<item>
|
<item>
|
||||||
<shape android:shape="oval">
|
<shape android:shape="oval">
|
||||||
<solid android:color="@color/dolphin_accent_wii"/>
|
<solid android:color="?android:colorAccent"/>
|
||||||
</shape>
|
</shape>
|
||||||
</item>
|
</item>
|
||||||
</ripple>
|
</ripple>
|
@ -1,8 +0,0 @@
|
|||||||
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:color="?android:colorControlHighlight">
|
|
||||||
<item>
|
|
||||||
<shape android:shape="oval">
|
|
||||||
<solid android:color="@color/dolphin_accent_gamecube"/>
|
|
||||||
</shape>
|
|
||||||
</item>
|
|
||||||
</ripple>
|
|
@ -0,0 +1,5 @@
|
|||||||
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:id="@+id/frame_content">
|
||||||
|
</FrameLayout>
|
@ -9,7 +9,7 @@
|
|||||||
android:id="@+id/toolbar_game_list"
|
android:id="@+id/toolbar_game_list"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="@color/dolphin_blue"
|
android:background="?android:colorPrimary"
|
||||||
android:minHeight="?android:attr/actionBarSize"
|
android:minHeight="?android:attr/actionBarSize"
|
||||||
android:theme="@android:style/ThemeOverlay.Material.Dark.ActionBar"
|
android:theme="@android:style/ThemeOverlay.Material.Dark.ActionBar"
|
||||||
android:elevation="6dp"/>
|
android:elevation="6dp"/>
|
||||||
@ -33,7 +33,7 @@
|
|||||||
android:layout_alignBottom="@+id/image_game_screen"
|
android:layout_alignBottom="@+id/image_game_screen"
|
||||||
android:layout_alignEnd="@+id/text_game_title"
|
android:layout_alignEnd="@+id/text_game_title"
|
||||||
android:layout_marginBottom="28dp"
|
android:layout_marginBottom="28dp"
|
||||||
android:background="@drawable/oval_ripple_gc"
|
android:background="@drawable/oval_ripple_accent"
|
||||||
android:src="@drawable/ic_add"
|
android:src="@drawable/ic_add"
|
||||||
android:stateListAnimator="@anim/button_elevation"
|
android:stateListAnimator="@anim/button_elevation"
|
||||||
android:elevation="4dp"
|
android:elevation="4dp"
|
||||||
|
@ -40,7 +40,7 @@
|
|||||||
tools:text="The Legend of Zelda: The Wind Waker"/>
|
tools:text="The Legend of Zelda: The Wind Waker"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/text_game_description"
|
android:id="@+id/text_company"
|
||||||
style="@android:style/TextAppearance.Material.Caption"
|
style="@android:style/TextAppearance.Material.Caption"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@ -51,7 +51,7 @@
|
|||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:lines="1"
|
android:lines="1"
|
||||||
android:maxLines="1"
|
android:maxLines="1"
|
||||||
tools:text="Zany rhythm action!"/>
|
tools:text="Nintendo"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
android:layout_marginLeft="16dp"
|
android:layout_marginLeft="16dp"
|
||||||
android:layout_marginTop="24dp"
|
android:layout_marginTop="24dp"
|
||||||
tools:src="@drawable/placeholder_banner"
|
tools:src="@drawable/placeholder_banner"
|
||||||
app:border_color="#ffcccccc"
|
app:border_color="?android:colorAccent"
|
||||||
app:border_width="2dp"
|
app:border_width="2dp"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@ -32,6 +32,7 @@
|
|||||||
android:layout_alignParentStart="true"
|
android:layout_alignParentStart="true"
|
||||||
android:layout_alignParentTop="true"
|
android:layout_alignParentTop="true"
|
||||||
android:transitionName="image_game_screen"
|
android:transitionName="image_game_screen"
|
||||||
|
tools:scaleType="centerCrop"
|
||||||
tools:src="@drawable/placeholder_screenshot"/>
|
tools:src="@drawable/placeholder_screenshot"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
@ -46,12 +47,10 @@
|
|||||||
android:layout_marginTop="24dp"
|
android:layout_marginTop="24dp"
|
||||||
android:layout_toEndOf="@+id/circle_banner"
|
android:layout_toEndOf="@+id/circle_banner"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:lines="1"
|
|
||||||
android:maxLines="1"
|
|
||||||
tools:text="Rhythm Heaven Fever"/>
|
tools:text="Rhythm Heaven Fever"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/text_game_description"
|
android:id="@+id/text_company"
|
||||||
style="@android:style/TextAppearance.Material.Caption"
|
style="@android:style/TextAppearance.Material.Caption"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@ -59,7 +58,6 @@
|
|||||||
android:layout_alignStart="@+id/text_game_title"
|
android:layout_alignStart="@+id/text_game_title"
|
||||||
android:layout_below="@+id/text_game_title"
|
android:layout_below="@+id/text_game_title"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="8dp"
|
||||||
android:text="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus sed odio vel quam auctor euismod. Pellentesque odio nibh, fermentum ut hendrerit id, ultrices et justo. "
|
|
||||||
tools:text="Zany rhythm action!"
|
tools:text="Zany rhythm action!"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@ -69,7 +67,7 @@
|
|||||||
android:layout_height="1dp"
|
android:layout_height="1dp"
|
||||||
android:layout_alignParentLeft="true"
|
android:layout_alignParentLeft="true"
|
||||||
android:layout_alignParentRight="true"
|
android:layout_alignParentRight="true"
|
||||||
android:layout_below="@+id/text_game_description"
|
android:layout_below="@+id/text_company"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="16dp"
|
||||||
|
|
||||||
android:background="#1F000000"/>
|
android:background="#1F000000"/>
|
||||||
@ -85,14 +83,14 @@
|
|||||||
android:src="@drawable/ic_country"/>
|
android:src="@drawable/ic_country"/>
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/icon_year"
|
android:id="@+id/icon_company"
|
||||||
android:layout_width="48dp"
|
android:layout_width="48dp"
|
||||||
android:layout_height="48dp"
|
android:layout_height="48dp"
|
||||||
android:layout_alignStart="@+id/icon_country"
|
android:layout_alignStart="@+id/icon_country"
|
||||||
android:layout_below="@+id/icon_country"
|
android:layout_below="@+id/icon_country"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="16dp"
|
||||||
android:padding="6dp"
|
android:padding="6dp"
|
||||||
android:src="@drawable/ic_date"
|
android:src="@drawable/ic_company"
|
||||||
android:layout_marginBottom="16dp"/>
|
android:layout_marginBottom="16dp"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
@ -100,22 +98,20 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignBottom="@+id/icon_country"
|
android:layout_alignBottom="@+id/icon_country"
|
||||||
android:layout_alignStart="@+id/text_game_description"
|
android:layout_alignStart="@+id/text_company"
|
||||||
android:layout_alignTop="@+id/icon_country"
|
android:layout_alignTop="@+id/icon_country"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:text="United States"
|
|
||||||
tools:text="United States"/>
|
tools:text="United States"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/text_date"
|
android:id="@+id/text_date"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignBottom="@+id/icon_year"
|
android:layout_alignBottom="@+id/icon_company"
|
||||||
android:layout_alignStart="@+id/text_country"
|
android:layout_alignStart="@+id/text_country"
|
||||||
android:layout_alignTop="@+id/icon_year"
|
android:layout_alignTop="@+id/icon_company"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:text="2010"
|
tools:text="Nintendo"/>
|
||||||
tools:text="2010"/>
|
|
||||||
|
|
||||||
<ImageButton
|
<ImageButton
|
||||||
android:id="@+id/button_launch"
|
android:id="@+id/button_launch"
|
||||||
@ -124,7 +120,7 @@
|
|||||||
android:layout_alignBottom="@+id/image_game_screen"
|
android:layout_alignBottom="@+id/image_game_screen"
|
||||||
android:layout_alignEnd="@+id/text_game_title"
|
android:layout_alignEnd="@+id/text_game_title"
|
||||||
android:layout_marginBottom="-28dp"
|
android:layout_marginBottom="-28dp"
|
||||||
android:background="@drawable/oval_ripple_wii"
|
android:background="@drawable/oval_ripple_accent"
|
||||||
android:src="@drawable/ic_play"
|
android:src="@drawable/ic_play"
|
||||||
android:stateListAnimator="@anim/button_elevation"
|
android:stateListAnimator="@anim/button_elevation"
|
||||||
android:elevation="4dp"/>
|
android:elevation="4dp"/>
|
||||||
|
@ -0,0 +1,22 @@
|
|||||||
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:context="org.dolphinemu.dolphinemu.fragments.EmulationFragment">
|
||||||
|
|
||||||
|
<!-- This is what everything is rendered to during emulation -->
|
||||||
|
<org.dolphinemu.dolphinemu.emulation.NativeGLSurfaceView
|
||||||
|
android:id="@+id/surface_emulation"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:focusable="false"
|
||||||
|
android:focusableInTouchMode="false"/>
|
||||||
|
|
||||||
|
<!-- This is the onscreen input overlay -->
|
||||||
|
<org.dolphinemu.dolphinemu.emulation.overlay.InputOverlay
|
||||||
|
android:id="@+id/surface_input_overlay"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:focusable="true"
|
||||||
|
android:focusableInTouchMode="true"/>
|
||||||
|
</FrameLayout>
|
77
Source/Android/app/src/main/res/menu/menu_emulation.xml
Normal file
77
Source/Android/app/src/main/res/menu/menu_emulation.xml
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
tools:context="org.dolphinemu.dolphinemu.activities.EmulationActivity">
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Enable/Disabe Input Overlay -->
|
||||||
|
<item
|
||||||
|
android:id="@+id/enableInputOverlay"
|
||||||
|
android:showAsAction="ifRoom"
|
||||||
|
android:title="@string/emulation_toggle_input"/>
|
||||||
|
|
||||||
|
<!-- Save State Slots -->
|
||||||
|
<item
|
||||||
|
android:id="@+id/takeScreenshot"
|
||||||
|
android:showAsAction="ifRoom"
|
||||||
|
android:title="@string/overlay_screenshot"/>
|
||||||
|
<item
|
||||||
|
android:id="@+id/saveStateRoot"
|
||||||
|
android:showAsAction="never"
|
||||||
|
android:title="@string/overlay_savestate">
|
||||||
|
<menu>
|
||||||
|
<item
|
||||||
|
android:id="@+id/saveSlot1"
|
||||||
|
android:title="@string/overlay_slot1"/>
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/saveSlot2"
|
||||||
|
android:title="@string/overlay_slot2"/>
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/saveSlot3"
|
||||||
|
android:title="@string/overlay_slot3"/>
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/saveSlot4"
|
||||||
|
android:title="@string/overlay_slot4"/>
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/saveSlot5"
|
||||||
|
android:title="@string/overlay_slot5"/>
|
||||||
|
</menu>
|
||||||
|
</item>
|
||||||
|
|
||||||
|
<!-- Load State Slots -->
|
||||||
|
<item
|
||||||
|
android:id="@+id/loadStateRoot"
|
||||||
|
android:showAsAction="never"
|
||||||
|
android:title="@string/overlay_loadstate">
|
||||||
|
<menu>
|
||||||
|
<item
|
||||||
|
android:id="@+id/loadSlot1"
|
||||||
|
android:title="@string/overlay_slot1"/>
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/loadSlot2"
|
||||||
|
android:title="@string/overlay_slot2"/>
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/loadSlot3"
|
||||||
|
android:title="@string/overlay_slot3"/>
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/loadSlot4"
|
||||||
|
android:title="@string/overlay_slot4"/>
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/loadSlot5"
|
||||||
|
android:title="@string/overlay_slot5"/>
|
||||||
|
</menu>
|
||||||
|
</item>
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/exitEmulation"
|
||||||
|
android:showAsAction="ifRoom"
|
||||||
|
android:title="@string/overlay_exit_emulation">
|
||||||
|
</item>
|
||||||
|
</menu>
|
@ -190,4 +190,20 @@
|
|||||||
<item>2</item>
|
<item>2</item>
|
||||||
<item>3</item>
|
<item>3</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="country_names">
|
||||||
|
<item>Europe</item>
|
||||||
|
<item>Japan</item>
|
||||||
|
<item>USA</item>
|
||||||
|
<item>Australia</item>
|
||||||
|
<item>France</item>
|
||||||
|
<item>Germany</item>
|
||||||
|
<item>Italy</item>
|
||||||
|
<item>Korea</item>
|
||||||
|
<item>Netherlands</item>
|
||||||
|
<item>Russia</item>
|
||||||
|
<item>Spain</item>
|
||||||
|
<item>Taiwan</item>
|
||||||
|
<item>Unknown</item>
|
||||||
|
</string-array>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -236,4 +236,7 @@
|
|||||||
<string name="preferences_cpu">CPU Settings</string>
|
<string name="preferences_cpu">CPU Settings</string>
|
||||||
<string name="preferences_input">Input Settings</string>
|
<string name="preferences_input">Input Settings</string>
|
||||||
<string name="preferences_video">Video Settings</string>
|
<string name="preferences_video">Video Settings</string>
|
||||||
|
<string name="emulation_title">Emulation Activity</string>
|
||||||
|
|
||||||
|
<string name="emulation_toggle_input">Toggle Input Overlay</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -22,23 +22,19 @@
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="DolphinGamecube" parent="DolphinBase">
|
<style name="DolphinGamecube" parent="DolphinBase">
|
||||||
<!-- theme UI controls like checkboxes and text fields -->
|
|
||||||
<item name="android:colorAccent">@color/dolphin_accent_gamecube</item>
|
<item name="android:colorAccent">@color/dolphin_accent_gamecube</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="DolphinWiiware" parent="DolphinBase">
|
<style name="DolphinWiiware" parent="DolphinBase">
|
||||||
<!-- theme UI controls like checkboxes and text fields -->
|
|
||||||
<item name="android:colorAccent">@color/dolphin_accent_wiiware</item>
|
<item name="android:colorAccent">@color/dolphin_accent_wiiware</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<!-- Inherit from the Base Dolphin Settings Theme-->
|
<!-- Inherit from the Base Dolphin Settings Theme-->
|
||||||
<style name="DolphinSettingsWii" parent="DolphinSettingsBase">
|
<style name="DolphinSettingsWii" parent="DolphinSettingsBase">
|
||||||
<!-- theme UI controls like checkboxes and text fields -->
|
|
||||||
<item name="android:colorAccent">@color/dolphin_accent_wii</item>
|
<item name="android:colorAccent">@color/dolphin_accent_wii</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="DolphinSettingsGamecube" parent="DolphinSettingsBase">
|
<style name="DolphinSettingsGamecube" parent="DolphinSettingsBase">
|
||||||
<!-- theme UI controls like checkboxes and text fields -->
|
|
||||||
<item name="android:colorAccent">@color/dolphin_accent_gamecube</item>
|
<item name="android:colorAccent">@color/dolphin_accent_gamecube</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
@ -46,4 +42,42 @@
|
|||||||
<!-- theme UI controls like checkboxes and text fields -->
|
<!-- theme UI controls like checkboxes and text fields -->
|
||||||
<item name="android:colorAccent">@color/dolphin_accent_wiiware</item>
|
<item name="android:colorAccent">@color/dolphin_accent_wiiware</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<!-- Themes for Dialogs -->
|
||||||
|
<style name="DolphinDialogBase" parent="android:Theme.Material.Light.Dialog">
|
||||||
|
<item name="android:colorPrimary">@color/dolphin_blue</item>
|
||||||
|
<item name="android:colorPrimaryDark">@color/dolphin_blue_dark</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<!-- Inherit from the Base Dolphin Dialog Theme-->
|
||||||
|
<style name="DolphinDialogWii" parent="DolphinDialogBase">
|
||||||
|
<item name="android:colorAccent">@color/dolphin_accent_wii</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="DolphinDialogGamecube" parent="DolphinDialogBase">
|
||||||
|
<item name="android:colorAccent">@color/dolphin_accent_gamecube</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="DolphinDialogWiiware" parent="DolphinDialogBase">
|
||||||
|
<item name="android:colorAccent">@color/dolphin_accent_wiiware</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="DolphinEmulationBase" parent="android:Theme.Material.Light.DarkActionBar">
|
||||||
|
<item name="android:colorPrimary">@color/dolphin_blue</item>
|
||||||
|
<item name="android:colorPrimaryDark">@color/dolphin_blue_dark</item>
|
||||||
|
<item name="android:windowTranslucentNavigation">true</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<!-- Inherit from the Base Dolphin Emulation Theme-->
|
||||||
|
<style name="DolphinEmulationWii" parent="DolphinEmulationBase">
|
||||||
|
<item name="android:colorAccent">@color/dolphin_accent_wii</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="DolphinEmulationGamecube" parent="DolphinEmulationBase">
|
||||||
|
<item name="android:colorAccent">@color/dolphin_accent_gamecube</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="DolphinEmulationWiiware" parent="DolphinEmulationBase">
|
||||||
|
<item name="android:colorAccent">@color/dolphin_accent_wiiware</item>
|
||||||
|
</style>
|
||||||
</resources>
|
</resources>
|
@ -21,7 +21,7 @@
|
|||||||
#include <android/log.h>
|
#include <android/log.h>
|
||||||
#include <android/native_window_jni.h>
|
#include <android/native_window_jni.h>
|
||||||
#include <EGL/egl.h>
|
#include <EGL/egl.h>
|
||||||
|
#include "../DiscIO/Volume.h"
|
||||||
#include "Android/ButtonManager.h"
|
#include "Android/ButtonManager.h"
|
||||||
#include "Common/CommonPaths.h"
|
#include "Common/CommonPaths.h"
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
@ -161,21 +161,52 @@ static bool LoadBanner(std::string filename, u32 *Banner)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool IsWiiTitle(std::string filename)
|
static int GetCountry(std::string filename)
|
||||||
{
|
{
|
||||||
std::unique_ptr<DiscIO::IVolume> pVolume(DiscIO::CreateVolumeFromFilename(filename));
|
std::unique_ptr<DiscIO::IVolume> pVolume(DiscIO::CreateVolumeFromFilename(filename));
|
||||||
|
|
||||||
if (pVolume != nullptr)
|
if (pVolume != nullptr)
|
||||||
{
|
{
|
||||||
bool is_wii_title = pVolume->IsWiiDisc() || pVolume->IsWadFile();
|
DiscIO::IVolume::ECountry country = pVolume->GetCountry();
|
||||||
|
|
||||||
__android_log_print(ANDROID_LOG_INFO, DOLPHIN_TAG, "Is %s a Wii Disc: %s", filename.c_str(), is_wii_title ? "Yes" : "No" );
|
__android_log_print(ANDROID_LOG_INFO, DOLPHIN_TAG, "Country Code: %i", country);
|
||||||
|
|
||||||
return is_wii_title;
|
return country;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Technically correct.
|
// Return UNKNOWN
|
||||||
return false;
|
return 13;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int GetPlatform(std::string filename)
|
||||||
|
{
|
||||||
|
std::unique_ptr<DiscIO::IVolume> pVolume(DiscIO::CreateVolumeFromFilename(filename));
|
||||||
|
|
||||||
|
if (pVolume != nullptr)
|
||||||
|
{
|
||||||
|
bool is_wii_disc = pVolume->IsWiiDisc();
|
||||||
|
bool is_wii_wad = pVolume->IsWadFile();
|
||||||
|
|
||||||
|
if (is_wii_disc)
|
||||||
|
{
|
||||||
|
__android_log_print(ANDROID_LOG_INFO, DOLPHIN_TAG, "Volume is a Wii disc.");
|
||||||
|
|
||||||
|
// See Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/Game.java
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (is_wii_wad)
|
||||||
|
{
|
||||||
|
__android_log_print(ANDROID_LOG_INFO, DOLPHIN_TAG, "Volume is a Wii WAD.");
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
__android_log_print(ANDROID_LOG_INFO, DOLPHIN_TAG, "Volume is a Gamecube disc.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string GetTitle(std::string filename)
|
static std::string GetTitle(std::string filename)
|
||||||
@ -274,15 +305,15 @@ static std::string GetGameId(std::string filename)
|
|||||||
return std::string ("");
|
return std::string ("");
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string GetApploaderDate(std::string filename)
|
static std::string GetCompany(std::string filename)
|
||||||
{
|
{
|
||||||
__android_log_print(ANDROID_LOG_WARN, DOLPHIN_TAG, "Getting Date for file: %s", filename.c_str());
|
__android_log_print(ANDROID_LOG_WARN, DOLPHIN_TAG, "Getting Company for file: %s", filename.c_str());
|
||||||
|
|
||||||
DiscIO::IVolume* pVolume = DiscIO::CreateVolumeFromFilename(filename);
|
DiscIO::IVolume* pVolume = DiscIO::CreateVolumeFromFilename(filename);
|
||||||
if (pVolume != nullptr)
|
if (pVolume != nullptr)
|
||||||
{
|
{
|
||||||
std::string date = pVolume->GetApploaderDate();
|
std::string date = pVolume->GetCompany();
|
||||||
__android_log_print(ANDROID_LOG_INFO, DOLPHIN_TAG, "Date: %s", date.c_str());
|
__android_log_print(ANDROID_LOG_INFO, DOLPHIN_TAG, "Company: %s", date.c_str());
|
||||||
|
|
||||||
return date;
|
return date;
|
||||||
}
|
}
|
||||||
@ -297,7 +328,8 @@ static u64 GetFileSize(std::string filename)
|
|||||||
if (pVolume != nullptr)
|
if (pVolume != nullptr)
|
||||||
{
|
{
|
||||||
u64 size = pVolume->GetSize();
|
u64 size = pVolume->GetSize();
|
||||||
__android_log_print(ANDROID_LOG_INFO, DOLPHIN_TAG, "Size: %lu", size);
|
// Causes a warning because size is u64, not 'long unsigned'
|
||||||
|
//__android_log_print(ANDROID_LOG_INFO, DOLPHIN_TAG, "Size: %lu", size);
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
@ -330,9 +362,10 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_onGamePadMov
|
|||||||
JNIEXPORT jintArray JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetBanner(JNIEnv *env, jobject obj, jstring jFile);JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetTitle(JNIEnv *env, jobject obj, jstring jFilename);
|
JNIEXPORT jintArray JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetBanner(JNIEnv *env, jobject obj, jstring jFile);JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetTitle(JNIEnv *env, jobject obj, jstring jFilename);
|
||||||
JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetDescription(JNIEnv *env, jobject obj, jstring jFilename);
|
JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetDescription(JNIEnv *env, jobject obj, jstring jFilename);
|
||||||
JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetGameId(JNIEnv *env, jobject obj, jstring jFilename);
|
JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetGameId(JNIEnv *env, jobject obj, jstring jFilename);
|
||||||
JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetDate(JNIEnv *env, jobject obj, jstring jFilename);
|
JNIEXPORT jint JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetCountry(JNIEnv *env, jobject obj, jstring jFilename);
|
||||||
|
JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetCompany(JNIEnv *env, jobject obj, jstring jFilename);
|
||||||
JNIEXPORT jlong JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetFilesize(JNIEnv *env, jobject obj, jstring jFilename);
|
JNIEXPORT jlong JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetFilesize(JNIEnv *env, jobject obj, jstring jFilename);
|
||||||
JNIEXPORT jboolean JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_IsWiiTitle(JNIEnv *env, jobject obj, jstring jFilename);
|
JNIEXPORT jint JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetPlatform(JNIEnv *env, jobject obj, jstring jFilename);
|
||||||
JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetVersionString(JNIEnv *env, jobject obj);
|
JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetVersionString(JNIEnv *env, jobject obj);
|
||||||
JNIEXPORT jboolean JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SupportsNEON(JNIEnv *env, jobject obj);
|
JNIEXPORT jboolean JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SupportsNEON(JNIEnv *env, jobject obj);
|
||||||
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SaveScreenShot(JNIEnv *env, jobject obj);
|
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SaveScreenShot(JNIEnv *env, jobject obj);
|
||||||
@ -404,11 +437,18 @@ JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetGameId
|
|||||||
return env->NewStringUTF(id.c_str());
|
return env->NewStringUTF(id.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetDate(JNIEnv *env, jobject obj, jstring jFilename)
|
JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetCompany(JNIEnv *env, jobject obj, jstring jFilename)
|
||||||
{
|
{
|
||||||
std::string filename = GetJString(env, jFilename);
|
std::string filename = GetJString(env, jFilename);
|
||||||
std::string date = GetApploaderDate(filename);
|
std::string company = GetCompany(filename);
|
||||||
return env->NewStringUTF(date.c_str());
|
return env->NewStringUTF(company.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jint JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetCountry(JNIEnv *env, jobject obj, jstring jFilename)
|
||||||
|
{
|
||||||
|
std::string filename = GetJString(env, jFilename);
|
||||||
|
int country = GetCountry(filename);
|
||||||
|
return country;
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT jlong JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetFilesize(JNIEnv *env, jobject obj, jstring jFilename)
|
JNIEXPORT jlong JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetFilesize(JNIEnv *env, jobject obj, jstring jFilename)
|
||||||
@ -418,11 +458,11 @@ JNIEXPORT jlong JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetFilesize
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT jboolean JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_IsWiiTitle(JNIEnv *env, jobject obj, jstring jFilename)
|
JNIEXPORT jint JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetPlatform(JNIEnv *env, jobject obj, jstring jFilename)
|
||||||
{
|
{
|
||||||
std::string filename = GetJString(env, jFilename);
|
std::string filename = GetJString(env, jFilename);
|
||||||
bool wiiDisc = IsWiiTitle(filename);
|
int platform = GetPlatform(filename);
|
||||||
return wiiDisc;
|
return platform;
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetVersionString(JNIEnv *env, jobject obj)
|
JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetVersionString(JNIEnv *env, jobject obj)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user