Merge pull request #1528 from reicast/fh/android-wipeout

Removing most of the java code and various bug fixes
This commit is contained in:
skmp 2019-03-29 14:43:10 +01:00 committed by GitHub
commit 95f4c8e9ac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
177 changed files with 420 additions and 9016 deletions

View File

@ -286,10 +286,6 @@
#define FEAT_HAS_SOFTREND BUILD_COMPILER == COMPILER_VC //GCC wants us to enable sse4 globaly to enable intrins
#endif
#define RAM_SIZE_MAX (32*1024*1024)
#define VRAM_SIZE_MAX (16*1024*1024)
#define ARAM_SIZE_MAX (8*1024*1024)
//Depricated build configs
#ifdef HOST_NO_REC
#error Dont use HOST_NO_REC
@ -298,3 +294,108 @@
#ifdef HOST_NO_AREC
#error Dont use HOST_NO_AREC
#endif
// TARGET PLATFORM
#define RAM_SIZE_MAX (32*1024*1024)
#define VRAM_SIZE_MAX (16*1024*1024)
#define ARAM_SIZE_MAX (8*1024*1024)
#if (DC_PLATFORM==DC_PLATFORM_DREAMCAST)
#define BUILD_DREAMCAST 1
//DC : 16 mb ram, 8 mb vram, 2 mb aram, 2 mb bios, 128k flash
#define RAM_SIZE (16*1024*1024)
#define VRAM_SIZE (8*1024*1024)
#define ARAM_SIZE (2*1024*1024)
#define BIOS_SIZE (2*1024*1024)
#define FLASH_SIZE (128*1024)
#define ROM_PREFIX "dc_"
#define ROM_NAMES
#define NVR_OPTIONAL 0
#elif (DC_PLATFORM==DC_PLATFORM_DEV_UNIT)
#define BUILD_DEV_UNIT 1
//Devkit : 32 mb ram, 8? mb vram, 2? mb aram, 2? mb bios, ? flash
#define RAM_SIZE (32*1024*1024)
#define VRAM_SIZE (8*1024*1024)
#define ARAM_SIZE (2*1024*1024)
#define BIOS_SIZE (2*1024*1024)
#define FLASH_SIZE (128*1024)
#define ROM_PREFIX "hkt_"
#define ROM_NAMES
#define NVR_OPTIONAL 0
#elif (DC_PLATFORM==DC_PLATFORM_NAOMI)
//Naomi : 32 mb ram, 16 mb vram, 8 mb aram, 2 mb bios, ? flash
#define RAM_SIZE (32*1024*1024)
#define VRAM_SIZE (16*1024*1024)
#define ARAM_SIZE (8*1024*1024)
#define BIOS_SIZE (2*1024*1024)
#define BBSRAM_SIZE (32*1024)
#define ROM_PREFIX "naomi_"
#define ROM_NAMES ";epr-21576d.bin"
#define NVR_OPTIONAL 1
#elif (DC_PLATFORM==DC_PLATFORM_NAOMI2)
//Naomi2 : 32 mb ram, 16 mb vram, 8 mb aram, 2 mb bios, ? flash
#define RAM_SIZE (32*1024*1024)
#define VRAM_SIZE (16*1024*1024)
#define ARAM_SIZE (8*1024*1024)
#define BIOS_SIZE (2*1024*1024)
#define BBSRAM_SIZE (32*1024)
#define ROM_PREFIX "n2_"
#define ROM_NAMES
#define NVR_OPTIONAL 1
#elif (DC_PLATFORM==DC_PLATFORM_ATOMISWAVE)
#define BUILD_ATOMISWAVE 1
//Atomiswave : 16 mb ram, 8 mb vram, 8 mb aram, 128kb bios on flash, 128kb battery-backed ram
#define RAM_SIZE (16*1024*1024)
#define VRAM_SIZE (8*1024*1024)
#define ARAM_SIZE (8*1024*1024)
#define BIOS_SIZE (128*1024)
#define BBSRAM_SIZE (128*1024)
#define ROM_PREFIX "aw_"
#define ROM_NAMES ";bios.ic23_l"
#define NVR_OPTIONAL 1
#else
#error invalid build config
#endif
#define RAM_MASK (RAM_SIZE-1)
#define VRAM_MASK (VRAM_SIZE-1)
#define ARAM_MASK (ARAM_SIZE-1)
#define BIOS_MASK (BIOS_SIZE-1)
#ifdef FLASH_SIZE
#define FLASH_MASK (FLASH_SIZE-1)
#endif
#ifdef BBSRAM_SIZE
#define BBSRAM_MASK (BBSRAM_SIZE-1)
#endif
#define GD_CLOCK 33868800 //GDROM XTAL -- 768fs
#define AICA_CORE_CLOCK (GD_CLOCK*4/3) //[45158400] GD->PLL 3:4 -> AICA CORE -- 1024fs
#define ADAC_CLOCK (AICA_CORE_CLOCK/2) //[11289600] 44100*256, AICA CORE -> PLL 4:1 -> ADAC -- 256fs
#define AICA_ARM_CLOCK (AICA_CORE_CLOCK/2) //[22579200] AICA CORE -> PLL 2:1 -> ARM
#define AICA_SDRAM_CLOCK (GD_CLOCK*2) //[67737600] GD-> PLL 2 -> SDRAM
#define SH4_MAIN_CLOCK (200*1000*1000) //[200000000] XTal(13.5) -> PLL (33.3) -> PLL 1:6 (200)
#define SH4_RAM_CLOCK (100*1000*1000) //[100000000] XTal(13.5) -> PLL (33.3) -> PLL 1:3 (100) , also suplied to HOLLY chip
#define G2_BUS_CLOCK (25*1000*1000) //[25000000] from Holly, from SH4_RAM_CLOCK w/ 2 2:1 plls

View File

@ -499,8 +499,13 @@ __asm__ (
".hidden arm_dispatch \n"
"arm_dispatch: \n\t"
"ldp w0, w1, [x28, #184] \n\t" // load Next PC, interrupt
"ubfx w2, w0, #2, #21 \n\t" // w2 = pc >> 2. Note: assuming address space <= 8 MB (23 bits)
#if ARAM_SIZE == 2*1024*1024
"ubfx w2, w0, #2, #19 \n\t" // w2 = pc >> 2. Note: assuming address space == 2 MB (21 bits)
#elif ARAM_SIZE == 8*1024*1024
"ubfx w2, w0, #2, #21 \n\t" // w2 = pc >> 2. Note: assuming address space == 8 MB (23 bits)
#else
#error Unsupported AICA RAM size
#endif
"cbnz w1, arm_dofiq \n\t" // if interrupt pending, handle it
"add x2, x26, x2, lsl #3 \n\t" // x2 = EntryPoints + pc << 1

View File

@ -256,6 +256,7 @@ void gd_set_state(gd_states state)
void gd_setdisc()
{
cdda.playing = false;
DiscType newd = (DiscType)libGDR_GetDiscType();
switch(newd)

View File

@ -3,10 +3,22 @@
#include <sstream>
#include <algorithm>
// On windows, transform / to \\
string normalize_path_separator(string path)
{
#if HOST_OS == OS_WINDOWS
std::replace(path.begin(), path.end(), '/', '\\');
#endif
return path;
}
// given file/name.ext or file\name.ext returns file/ or file\, depending on the platform
// given name.ext returns ./ or .\, depending on the platform
string OS_dirname(string file)
{
file = normalize_path_separator(file);
#if HOST_OS == OS_WINDOWS
const char sep = '\\';
#else
@ -25,19 +37,6 @@ string OS_dirname(string file)
return file.substr(0, last_slash + 1);
}
// On windows, transform / to \\
// On linux, transform \\ to /
string normalize_path_separator(string path)
{
#if HOST_OS == OS_WINDOWS
std::replace( path.begin(), path.end(), '/', '\\');
#else
std::replace( path.begin(), path.end(), '\\', '/');
#endif
return path;
}
#if 0 // TODO: Move this to some tests, make it platform agnostic
namespace {
struct OS_dirname_Test {

View File

@ -53,8 +53,8 @@ enum DreamcastKey
// System axes
EMU_AXIS_NONE = 0x00000,
EMU_AXIS_DPAD1_X = 0x00001,
EMU_AXIS_DPAD1_Y = 0x00002,
EMU_AXIS_DPAD2_X = 0x00003,
EMU_AXIS_DPAD2_Y = 0x00004,
EMU_AXIS_DPAD1_X = DC_DPAD_LEFT,
EMU_AXIS_DPAD1_Y = DC_DPAD_UP,
EMU_AXIS_DPAD2_X = DC_DPAD2_LEFT,
EMU_AXIS_DPAD2_Y = DC_DPAD2_RIGHT,
};

View File

@ -20,6 +20,7 @@
#include <limits.h>
#include "gamepad_device.h"
#include "rend/gui.h"
#include "oslib/oslib.h"
extern void dc_exit();
@ -32,7 +33,8 @@ std::mutex GamepadDevice::_gamepads_mutex;
bool GamepadDevice::gamepad_btn_input(u32 code, bool pressed)
{
if (_input_detected != NULL && _detecting_button && pressed)
if (_input_detected != NULL && _detecting_button
&& os_GetSeconds() >= _detection_start_time && pressed)
{
_input_detected(code);
_input_detected = NULL;
@ -84,7 +86,8 @@ bool GamepadDevice::gamepad_axis_input(u32 code, int value)
v = (get_axis_min_value(code) + get_axis_range(code) - value) * 255 / get_axis_range(code) - 128;
else
v = (value - get_axis_min_value(code)) * 255 / get_axis_range(code) - 128; //-128 ... + 127 range
if (_input_detected != NULL && !_detecting_button && (v >= 64 || v <= -64))
if (_input_detected != NULL && !_detecting_button
&& os_GetSeconds() >= _detection_start_time && (v >= 64 || v <= -64))
{
_input_detected(code);
_input_detected = NULL;
@ -235,3 +238,18 @@ void UpdateVibration(u32 port, float power, float inclination, u32 duration_ms)
gamepad->rumble(power, inclination, duration_ms);
}
}
void GamepadDevice::detect_btn_input(input_detected_cb button_pressed)
{
_input_detected = button_pressed;
_detecting_button = true;
_detection_start_time = os_GetSeconds() + 0.2;
}
void GamepadDevice::detect_axis_input(input_detected_cb axis_moved)
{
_input_detected = axis_moved;
_detecting_button = false;
_detection_start_time = os_GetSeconds() + 0.2;
}

View File

@ -35,16 +35,8 @@ public:
bool gamepad_axis_input(u32 code, int value);
virtual ~GamepadDevice() {}
void detect_btn_input(input_detected_cb button_pressed)
{
_input_detected = button_pressed;
_detecting_button = true;
}
void detect_axis_input(input_detected_cb axis_moved)
{
_input_detected = axis_moved;
_detecting_button = false;
}
void detect_btn_input(input_detected_cb button_pressed);
void detect_axis_input(input_detected_cb axis_moved);
void cancel_detect_input()
{
_input_detected = NULL;
@ -104,6 +96,7 @@ private:
std::string _api_name;
int _maple_port;
bool _detecting_button = false;
double _detection_start_time;
input_detected_cb _input_detected;
bool _remappable;
float _dead_zone = 0.1f;

View File

@ -58,6 +58,7 @@ bkpt #0
bkpt
#endif
ubfx r0,r3,#5,#19 @ get vram offset
@ should be only 18 bits for 8MB VRAM but it wraps around on dc
add r3,r1,#0x04000000 @ get vram ptr from r1, part 1
add r3,#512 @ get ram ptr from r1, part 2
add r3,r0,lsl #5 @ ram + offset
@ -180,6 +181,7 @@ CSYM(no_update): @ next_pc _MUST_ be on r4 *R4 NOT R0 anymore*
#if RAM_SIZE_MAX == 33554432
sub r2,r8,#0x4100000
ubfx r1,r4,#1,#24 @ 24+1 bits: 32 MB
@ RAM wraps around so if actual RAM size is 16MB, we won't overflow
#elif RAM_SIZE_MAX == 16777216
sub r2,r8,#0x2100000
ubfx r1,r4,#1,#23 @ 23+1 bits: 16 MB
@ -241,7 +243,13 @@ HIDDEN(arm_dispatch)
CSYM(arm_dispatch):
ldrd r0,r1,[r8,#184] @load: Next PC, interrupt
#if ARAM_SIZE == 2*1024*1024
ubfx r2,r0,#2,#19 @ assuming 2 MB address space max (21 bits)
#elif ARAM_SIZE == 8*1024*1024
ubfx r2,r0,#2,#21 @ assuming 8 MB address space max (23 bits)
#else
#error Unsupported AICA RAM size
#endif
cmp r1,#0
bne arm_dofiq

View File

@ -617,31 +617,25 @@ public:
break;
case shop_pref:
Mov(w0, regalloc.MapRegister(op.rs1));
if (op.flags != 0x1337)
{
Lsr(w1, regalloc.MapRegister(op.rs1), 26);
Cmp(w1, 0x38);
}
Label not_sqw;
B(&not_sqw, ne);
Mov(w0, regalloc.MapRegister(op.rs1));
if (CCN_MMUCR.AT)
{
Ldr(x9, reinterpret_cast<uintptr_t>(&do_sqw_mmu));
}
else
{
Sub(x9, x28, offsetof(Sh4RCB, cntx) - offsetof(Sh4RCB, do_sqw_nommu));
Ldr(x9, MemOperand(x9));
Sub(x1, x28, offsetof(Sh4RCB, cntx) - offsetof(Sh4RCB, sq_buffer));
}
if (op.flags == 0x1337)
if (CCN_MMUCR.AT)
{
Ldr(x9, reinterpret_cast<uintptr_t>(&do_sqw_mmu));
}
else
{
Sub(x9, x28, offsetof(Sh4RCB, cntx) - offsetof(Sh4RCB, do_sqw_nommu));
Ldr(x9, MemOperand(x9));
Sub(x1, x28, offsetof(Sh4RCB, cntx) - offsetof(Sh4RCB, sq_buffer));
}
Blr(x9);
else
{
Label no_branch;
B(&no_branch, ne);
Blr(x9);
Bind(&no_branch);
Bind(&not_sqw);
}
break;

View File

@ -1488,3 +1488,10 @@ int msgboxf(const wchar* text, unsigned int type, ...) {
return 1;
}
extern bool subfolders_read;
void gui_refresh_files()
{
game_list_done = false;
subfolders_read = false;
}

View File

@ -25,6 +25,7 @@ void gui_display_notification(const char *msg, int duration);
void gui_display_osd();
void gui_open_onboarding();
void gui_term();
void gui_refresh_files();
extern int screen_dpi;

View File

@ -33,7 +33,7 @@ extern int screen_width, screen_height;
static std::string select_current_directory;
static std::vector<std::string> select_subfolders;
static bool subfolders_read;
bool subfolders_read;
#ifdef _WIN32
static const std::string separators = "/\\";
static const std::string native_separator = "\\";

View File

@ -204,106 +204,6 @@ struct vram_block
void* userdata;
};
#if (DC_PLATFORM==DC_PLATFORM_DREAMCAST)
#define BUILD_DREAMCAST 1
//DC : 16 mb ram, 8 mb vram, 2 mb aram, 2 mb bios, 128k flash
#define RAM_SIZE (16*1024*1024)
#define VRAM_SIZE (8*1024*1024)
#define ARAM_SIZE (2*1024*1024)
#define BIOS_SIZE (2*1024*1024)
#define FLASH_SIZE (128*1024)
#define ROM_PREFIX "dc_"
#define ROM_NAMES
#define NVR_OPTIONAL 0
#elif (DC_PLATFORM==DC_PLATFORM_DEV_UNIT)
#define BUILD_DEV_UNIT 1
//Devkit : 32 mb ram, 8? mb vram, 2? mb aram, 2? mb bios, ? flash
#define RAM_SIZE (32*1024*1024)
#define VRAM_SIZE (8*1024*1024)
#define ARAM_SIZE (2*1024*1024)
#define BIOS_SIZE (2*1024*1024)
#define FLASH_SIZE (128*1024)
#define ROM_PREFIX "hkt_"
#define ROM_NAMES
#define NVR_OPTIONAL 0
#elif (DC_PLATFORM==DC_PLATFORM_NAOMI)
//Naomi : 32 mb ram, 16 mb vram, 8 mb aram, 2 mb bios, ? flash
#define RAM_SIZE (32*1024*1024)
#define VRAM_SIZE (16*1024*1024)
#define ARAM_SIZE (8*1024*1024)
#define BIOS_SIZE (2*1024*1024)
#define BBSRAM_SIZE (32*1024)
#define ROM_PREFIX "naomi_"
#define ROM_NAMES ";epr-21576d.bin"
#define NVR_OPTIONAL 1
#elif (DC_PLATFORM==DC_PLATFORM_NAOMI2)
//Naomi2 : 32 mb ram, 16 mb vram, 8 mb aram, 2 mb bios, ? flash
#define RAM_SIZE (32*1024*1024)
#define VRAM_SIZE (16*1024*1024)
#define ARAM_SIZE (8*1024*1024)
#define BIOS_SIZE (2*1024*1024)
#define BBSRAM_SIZE (32*1024)
#define ROM_PREFIX "n2_"
#define ROM_NAMES
#define NVR_OPTIONAL 1
#elif (DC_PLATFORM==DC_PLATFORM_ATOMISWAVE)
#define BUILD_ATOMISWAVE 1
//Atomiswave : 16 mb ram, 8 mb vram, 8 mb aram, 128kb bios on flash, 128kb battery-backed ram
#define RAM_SIZE (16*1024*1024)
#define VRAM_SIZE (8*1024*1024)
#define ARAM_SIZE (8*1024*1024)
#define BIOS_SIZE (128*1024)
#define BBSRAM_SIZE (128*1024)
#define ROM_PREFIX "aw_"
#define ROM_NAMES ";bios.ic23_l"
#define NVR_OPTIONAL 1
#else
#error invalid build config
#endif
#define RAM_MASK (RAM_SIZE-1)
#define VRAM_MASK (VRAM_SIZE-1)
#define ARAM_MASK (ARAM_SIZE-1)
#define BIOS_MASK (BIOS_SIZE-1)
#ifdef FLASH_SIZE
#define FLASH_MASK (FLASH_SIZE-1)
#endif
#ifdef BBSRAM_SIZE
#define BBSRAM_MASK (BBSRAM_SIZE-1)
#endif
#define GD_CLOCK 33868800 //GDROM XTAL -- 768fs
#define AICA_CORE_CLOCK (GD_CLOCK*4/3) //[45158400] GD->PLL 3:4 -> AICA CORE -- 1024fs
#define ADAC_CLOCK (AICA_CORE_CLOCK/2) //[11289600] 44100*256, AICA CORE -> PLL 4:1 -> ADAC -- 256fs
#define AICA_ARM_CLOCK (AICA_CORE_CLOCK/2) //[22579200] AICA CORE -> PLL 2:1 -> ARM
#define AICA_SDRAM_CLOCK (GD_CLOCK*2) //[67737600] GD-> PLL 2 -> SDRAM
#define SH4_MAIN_CLOCK (200*1000*1000) //[200000000] XTal(13.5) -> PLL (33.3) -> PLL 1:6 (200)
#define SH4_RAM_CLOCK (100*1000*1000) //[100000000] XTal(13.5) -> PLL (33.3) -> PLL 1:3 (100) , also suplied to HOLLY chip
#define G2_BUS_CLOCK (25*1000*1000) //[25000000] from Holly, from SH4_RAM_CLOCK w/ 2 2:1 plls
enum ndc_error_codes
{
rv_ok = 0, //no error

View File

@ -3,7 +3,7 @@
xmlns:tools="http://schemas.android.com/tools">
<application android:name="com.reicast.emulator.Emulator">
<activity
android:name="com.reicast.emulator.MainActivity">
android:name="com.reicast.emulator.NativeGLActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />

View File

@ -37,7 +37,7 @@
android:name="com.reicast.emulator.Emulator"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:roundIcon="@drawable/ic_launcher"
android:banner="@drawable/ic_banner"
android:logo="@drawable/ic_banner"
@ -45,12 +45,15 @@
android:isGame="true">
<meta-data android:name="android.max_aspect" android:value="2.1" />
<activity
android:name="com.reicast.emulator.MainActivity"
android:name="com.reicast.emulator.GL2JNIActivity"
android:configChanges="orientation|navigation|screenSize|screenLayout|uiMode|keyboard|keyboardHidden"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar">
android:screenOrientation="sensorLandscape">
</activity>
<activity
android:name="com.reicast.emulator.NativeGLActivity"
android:configChanges="orientation|navigation|screenSize|screenLayout|uiMode|keyboard|keyboardHidden"
android:screenOrientation="sensorLandscape">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
@ -58,29 +61,6 @@
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.reicast.emulator.GL2JNIActivity"
android:configChanges="orientation|navigation|screenSize|screenLayout|uiMode|keyboard|keyboardHidden"
android:screenOrientation="sensorLandscape"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
</activity>
<activity
android:name="com.reicast.emulator.NativeGLActivity"
android:configChanges="orientation|navigation|screenSize|screenLayout|uiMode|keyboard|keyboardHidden"
android:screenOrientation="sensorLandscape"
android:theme="@style/AppTheme.NoActionBar">
</activity>
<activity
android:name="com.dropbox.client2.android.AuthActivity"
android:configChanges="orientation|keyboard"
android:launchMode="singleTask">
<intent-filter>
<data android:scheme="db-lowa9ps6h5k7zbo" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.provider"

View File

@ -12,50 +12,16 @@ import android.preference.PreferenceManager;
import com.reicast.emulator.config.Config;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.nio.IntBuffer;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Vector;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import javax.microedition.khronos.opengles.GL10;
public class FileUtils {
public Collection<File> listFiles(File directory, FilenameFilter[] filter,
int recurse) {
Vector<File> files = new Vector<>();
File[] entries = directory.listFiles();
if (entries != null) {
for (File entry : entries) {
for (FilenameFilter filefilter : filter) {
if (filefilter.accept(directory, entry.getName())) {
files.add(entry);
}
}
if ((recurse <= -1) || (recurse > 0 && entry.isDirectory())) {
recurse--;
files.addAll(listFiles(entry, filter, recurse));
recurse++;
}
}
}
return files;
}
public static void saveScreenshot(final Context c, int w, int h, GL10 gl){
try {
SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(c);
@ -80,7 +46,7 @@ public class FileUtils {
}
//thank you stackoverflow
public static Bitmap savePixels(int x, int y, int w, int h, GL10 gl)
private static Bitmap savePixels(int x, int y, int w, int h, GL10 gl)
{
int b[]=new int[w*(y+h)];
int bt[]=new int[w*h];

View File

@ -2,9 +2,12 @@ package com.reicast.emulator;
import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
@ -12,16 +15,13 @@ import android.os.Handler;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar;
import android.support.v4.app.ActivityCompat;
import android.util.Log;
import android.view.Gravity;
import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.widget.TextView;
import com.reicast.emulator.config.Config;
import com.reicast.emulator.debug.GenerateLogs;
@ -35,18 +35,27 @@ import java.util.List;
import tv.ouya.console.api.OuyaController;
public class BaseGLActivity extends Activity implements ActivityCompat.OnRequestPermissionsResultCallback {
public abstract class BaseGLActivity extends Activity implements ActivityCompat.OnRequestPermissionsResultCallback {
private static final int STORAGE_PERM_REQUEST = 1001;
private static final int AUDIO_PERM_REQUEST = 1002;
protected View mView;
protected SharedPreferences prefs;
protected float[][] vjoy_d_cached; // Used for VJoy editing
private AudioBackend audioBackend;
private Handler handler = new Handler();
public static byte[] syms;
private boolean audioPermissionRequested;
private boolean audioPermissionRequested = false;
private boolean paused = true;
private boolean resumedCalled = false;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (!getFilesDir().exists()) {
getFilesDir().mkdir();
}
prefs = PreferenceManager.getDefaultSharedPreferences(this);
Emulator app = (Emulator)getApplicationContext();
@ -57,32 +66,124 @@ public class BaseGLActivity extends Activity implements ActivityCompat.OnRequest
String home_directory = prefs.getString(Config.pref_home, "");
String result = JNIdc.initEnvironment((Emulator)getApplicationContext(), home_directory);
if (result != null)
showToastMessage("Initialization failed: " + result, Snackbar.LENGTH_LONG);
if (result != null) {
AlertDialog.Builder dlgAlert = new AlertDialog.Builder(this);
dlgAlert.setMessage("Initialization failed. Please try again and/or reinstall.\n\n"
+ "Error: " + result);
dlgAlert.setTitle("Reicast Error");
dlgAlert.setPositiveButton("Exit",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,int id) {
BaseGLActivity.this.finish();
}
});
dlgAlert.setIcon(android.R.drawable.ic_dialog_alert);
dlgAlert.setCancelable(false);
dlgAlert.create().show();
return;
}
setStorageDirectories();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
ActivityCompat.requestPermissions(this,
new String[]{
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
},
STORAGE_PERM_REQUEST);
}
InputDeviceManager.getInstance().startListening(getApplicationContext());
register(this);
audioBackend = new AudioBackend();
// When viewing a resource, pass its URI to the native code for opening
Intent intent = getIntent();
if (intent.getAction() != null) {
if (intent.getAction().equals(Intent.ACTION_VIEW)) {
Uri gameUri = Uri.parse(intent.getData().toString());
// Flush the intent to prevent multiple calls
getIntent().setData(null);
setIntent(null);
if (gameUri != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
gameUri = Uri.parse(gameUri.toString().replace("content://"
+ gameUri.getAuthority() + "/external_files", "/storage"));
}
if (gameUri != null)
JNIdc.setGameUri(gameUri.toString());
}
}
}
private void setStorageDirectories()
{
String android_home_directory = Environment.getExternalStorageDirectory().getAbsolutePath();
List<String> pathList = new ArrayList<>();
pathList.add(android_home_directory);
pathList.addAll(FileBrowser.getExternalMounts());
Log.i("reicast", "External storage dirs: " + pathList);
JNIdc.setExternalStorageDirectories(pathList.toArray());
InputDeviceManager.getInstance().startListening(getApplicationContext());
register(this);
audioBackend = new AudioBackend();
}
@Override
protected void onDestroy() {
super.onDestroy();
paused = true;
InputDeviceManager.getInstance().stopListening();
register(null);
audioBackend.release();
if (audioBackend != null)
audioBackend.release();
Emulator.setCurrentActivity(null);
stopEmulator();
}
@Override
protected void onPause() {
super.onPause();
resumedCalled = false;
handleStateChange(true);
}
@Override
protected void onResume() {
super.onResume();
resumedCalled = true;
handleStateChange(false);
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus) {
handleStateChange(false);
} else {
handleStateChange(true);
}
}
protected abstract void doPause();
protected abstract void doResume();
protected abstract boolean isSurfaceReady();
public void handleStateChange(boolean paused)
{
if (paused == this.paused)
return;
if (!paused && (!resumedCalled || !isSurfaceReady()))
return;
this.paused = paused;
if (paused) {
doPause();
}
else {
doResume();
}
}
private boolean showMenu() {
JNIdc.guiOpenSettings();
return true;
@ -133,13 +234,7 @@ public class BaseGLActivity extends Activity implements ActivityCompat.OnRequest
return true;
}
else if (JNIdc.guiIsContentBrowser()) {
// Only if this is the main activity
//finish();
// so for now we hack it
Intent startMain = new Intent(Intent.ACTION_MAIN);
startMain.addCategory(Intent.CATEGORY_HOME);
startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(startMain);
finish();
return true;
}
}
@ -154,21 +249,6 @@ public class BaseGLActivity extends Activity implements ActivityCompat.OnRequest
return super.onKeyDown(keyCode, event);
}
private void showToastMessage(String message, int duration) {
View view = findViewById(android.R.id.content);
Snackbar snackbar = Snackbar.make(view, message, duration);
View snackbarLayout = snackbar.getView();
TextView textView = (TextView) snackbarLayout.findViewById(
android.support.design.R.id.snackbar_text);
textView.setGravity(Gravity.CENTER_VERTICAL);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1)
textView.setTextAlignment(View.TEXT_ALIGNMENT_GRAVITY);
textView.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_notification, 0, 0, 0);
textView.setCompoundDrawablePadding(getResources()
.getDimensionPixelOffset(R.dimen.snackbar_icon_padding));
snackbar.show();
}
protected void stopEmulator() {
JNIdc.stop();
}
@ -181,19 +261,18 @@ public class BaseGLActivity extends Activity implements ActivityCompat.OnRequest
handler.post(new Runnable() {
@Override
public void run() {
mView.setVisibility(View.INVISIBLE);
ActivityCompat.requestPermissions(BaseGLActivity.this,
new String[]{
Manifest.permission.RECORD_AUDIO
},
0);
AUDIO_PERM_REQUEST);
}
});
}
else
{
onRequestPermissionsResult(0, new String[] { Manifest.permission.RECORD_AUDIO },
onRequestPermissionsResult(AUDIO_PERM_REQUEST, new String[] { Manifest.permission.RECORD_AUDIO },
new int[] { PackageManager.PERMISSION_GRANTED });
}
}
@ -201,12 +280,19 @@ public class BaseGLActivity extends Activity implements ActivityCompat.OnRequest
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (permissions.length > 0 && Manifest.permission.RECORD_AUDIO .equals(permissions[0]) && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (requestCode == AUDIO_PERM_REQUEST && permissions.length > 0
&& Manifest.permission.RECORD_AUDIO .equals(permissions[0]) && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
SipEmulator sip = new SipEmulator();
sip.startRecording();
JNIdc.setupMic(sip);
}
mView.setVisibility(View.VISIBLE);
else if (requestCode == STORAGE_PERM_REQUEST) {
setStorageDirectories();
//setup mic
if (Emulator.micPluggedIn())
requestRecordAudioPermission();
}
}
// Called from native code
@ -214,7 +300,20 @@ public class BaseGLActivity extends Activity implements ActivityCompat.OnRequest
try {
new GenerateLogs(this).execute(getFilesDir().getAbsolutePath());
} catch (RuntimeException e) {
showToastMessage("An error occurred retrieving the log file: " + e.getMessage(), Snackbar.LENGTH_LONG);
AlertDialog.Builder dlgAlert = new AlertDialog.Builder(this);
dlgAlert.setMessage("An error occurred retrieving the log file:\n\n"
+ e.getMessage());
dlgAlert.setTitle("Reicast Error");
dlgAlert.setPositiveButton("Ok",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,int id) {
dialog.cancel();
}
});
dlgAlert.setIcon(android.R.drawable.ic_dialog_info);
dlgAlert.setCancelable(false);
dlgAlert.create().show();
}
}

View File

@ -1,6 +1,5 @@
package com.reicast.emulator;
import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.content.SharedPreferences;
@ -14,31 +13,23 @@ import com.reicast.emulator.emu.JNIdc;
public class Emulator extends Application {
private static Context context;
private static Activity currentActivity;
private static BaseGLActivity currentActivity;
// see MapleDeviceType in hw/maple/maple_devs.h
public static final int MDT_SegaController = 0;
public static final int MDT_SegaVMU = 1;
public static final int MDT_Microphone = 2;
public static final int MDT_PurupuruPack = 3;
public static final int MDT_Keyboard = 4;
public static final int MDT_Mouse = 5;
public static final int MDT_LightGun = 6;
public static final int MDT_NaomiJamma = 7;
public static final int MDT_None = 8;
public static final int MDT_Count = 9;
public static boolean nosound = false;
public static int vibrationDuration = 20;
public static int maple_devices[] = {
MDT_SegaController,
MDT_None,
MDT_None,
MDT_None,
MDT_None
};
public static int maple_expansion_devices[][] = {
{ MDT_SegaVMU, MDT_None },
{ MDT_None, MDT_None },
{ MDT_None, MDT_None },
{ MDT_None, MDT_None },
{ MDT_None, MDT_None },
@ -56,7 +47,7 @@ public class Emulator extends Application {
/**
* Fetch current configuration settings from the emulator and save them
*
* Called from JNI code
*/
public void SaveAndroidSettings(String homeDirectory)
{
@ -71,8 +62,8 @@ public class Emulator extends Application {
AudioBackend.getInstance().enableSound(!Emulator.nosound);
FileBrowser.installButtons(prefs);
if (micPluggedIn() && currentActivity instanceof NativeGLActivity) {
((NativeGLActivity)currentActivity).requestRecordAudioPermission();
if (micPluggedIn() && currentActivity instanceof BaseGLActivity) {
((BaseGLActivity)currentActivity).requestRecordAudioPermission();
}
}
@ -95,11 +86,11 @@ public class Emulator extends Application {
return Emulator.context;
}
public static Activity getCurrentActivity() {
public static BaseGLActivity getCurrentActivity() {
return Emulator.currentActivity;
}
public static void setCurrentActivity(Activity activity) {
public static void setCurrentActivity(BaseGLActivity activity) {
Emulator.currentActivity = activity;
}

View File

@ -1,35 +1,9 @@
package com.reicast.emulator;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Vibrator;
import android.preference.PreferenceManager;
import android.support.constraint.ConstraintLayout;
import android.support.design.widget.Snackbar;
import android.support.graphics.drawable.VectorDrawableCompat;
import android.support.v4.app.Fragment;
import android.support.v4.content.FileProvider;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TextView;
import com.android.util.FileUtils;
import com.reicast.emulator.config.Config;
import com.reicast.emulator.emu.JNIdc;
import org.apache.commons.lang3.StringUtils;
@ -37,56 +11,13 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
public class FileBrowser extends Fragment {
private Vibrator vib;
private boolean games;
private String searchQuery = null;
private OnItemSelectedListener mCallback;
private SharedPreferences mPrefs;
private File sdcard = Environment.getExternalStorageDirectory();
private String home_directory = sdcard.getAbsolutePath();
private String game_directory = sdcard.getAbsolutePath();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPrefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
home_directory = mPrefs.getString(Config.pref_home, home_directory);
game_directory = mPrefs.getString(Config.pref_games, game_directory);
Bundle b = getArguments();
if (b != null) {
if (games = b.getBoolean("games_entry", false)) {
if (b.getString("path_entry") != null) {
home_directory = b.getString("path_entry");
}
} else {
if (b.getString("path_entry") != null) {
game_directory = b.getString("path_entry");
}
}
if (b.getString("search_params") != null) {
searchQuery = b.getString("search_params");
}
}
}
public class FileBrowser {
android.support.v4.content.FileProvider provider; // To avoid ClassNotFoundException at runtime
public static HashSet<String> getExternalMounts() {
final HashSet<String> out = new HashSet<>();
@ -126,61 +57,6 @@ public class FileBrowser extends Fragment {
return out;
}
// Container Activity must implement this interface
public interface OnItemSelectedListener {
void onGameSelected(Uri uri);
void onFolderSelected(Uri uri);
}
@Override @SuppressWarnings("deprecation")
public void onAttach(Activity activity) {
super.onAttach(activity);
// This makes sure that the container activity has implemented
// the callback interface. If not, it throws an exception
try {
mCallback = (OnItemSelectedListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnItemSelectedListener");
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.browser_fragment, container, false);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
// setContentView(R.layout.activity_main);
vib = (Vibrator) getActivity().getSystemService(Context.VIBRATOR_SERVICE);
/*
* OnTouchListener viblist=new OnTouchListener() {
*
* public boolean onTouch(View v, MotionEvent event) { if
* (event.getActionMasked()==MotionEvent.ACTION_DOWN) vib.vibrate(50);
* return false; } };
*
* findViewById(R.id.config).setOnTouchListener(viblist);
* findViewById(R.id.about).setOnTouchListener(viblist);
*/
String temp = mPrefs.getString(Config.pref_home, null);
if (temp == null || !new File(temp).isDirectory()) {
showToastMessage(getActivity().getString(R.string.config_home), Snackbar.LENGTH_LONG);
}
installButtons(mPrefs);
if (!games) {
new LocateGames(this, R.array.flash).execute(home_directory);
} else {
new LocateGames(this, R.array.images).execute(game_directory);
}
}
public static void installButtons(SharedPreferences prefs) {
try {
File buttons = null;
@ -216,389 +92,4 @@ public class FileBrowser extends Fragment {
ioe.printStackTrace();
}
}
private static final class LocateGames extends AsyncTask<String, Integer, List<File>> {
private WeakReference<FileBrowser> browser;
private int array;
LocateGames(FileBrowser context, int arrayType) {
browser = new WeakReference<>(context);
this.array = arrayType;
}
@Override
protected List<File> doInBackground(String... paths) {
File storage = new File(paths[0]);
// array of valid image file extensions
String[] mediaTypes = browser.get().getActivity().getResources().getStringArray(array);
FilenameFilter[] filter = new FilenameFilter[mediaTypes.length];
int i = 0;
for (final String type : mediaTypes) {
filter[i] = new FilenameFilter() {
public boolean accept(File dir, String name) {
return !dir.getName().equals("obb") && !dir.getName().equals("cache")
&& !dir.getName().startsWith(".") && !name.startsWith(".")
&& (array != R.array.flash || name.startsWith("dc_"))
&& (browser.get().searchQuery == null
|| name.toLowerCase(Locale.getDefault()).contains(
browser.get().searchQuery.toLowerCase(Locale.getDefault())))
&& StringUtils.endsWithIgnoreCase(name, "." + type);
}
};
i++;
}
FileUtils fileUtils = new FileUtils();
int recurse = 2;
if (array == R.array.flash) {
recurse = 4;
}
Collection<File> files = fileUtils.listFiles(storage, filter, recurse);
return (List<File>) files;
}
@Override
protected void onPostExecute(List<File> items) {
LinearLayout list = (LinearLayout) browser.get().getActivity().findViewById(R.id.game_list);
if (list.getChildCount() > 0) {
list.removeAllViews();
}
String heading = browser.get().getActivity().getString(R.string.games_listing);
browser.get().createListHeader(heading, list, array == R.array.images);
if (items != null && !items.isEmpty()) {
for (int i = 0; i < items.size(); i++) {
browser.get().createListItem(list, items.get(i), i, array == R.array.images);
}
} else if (browser.get().searchQuery != null) {
final View childview = browser.get().getActivity().getLayoutInflater().inflate(
R.layout.browser_fragment_item, null, false);
((TextView) childview.findViewById(R.id.item_name)).setText(R.string.no_games);
((ImageView) childview.findViewById(R.id.item_icon))
.setImageResource(R.mipmap.disk_missing);
list.addView(childview);
} else {
browser.get().browseStorage(array == R.array.images);
}
list.invalidate();
}
}
private void browseStorage(boolean images) {
if (images) {
(new navigate(this)).executeOnExecutor(
AsyncTask.THREAD_POOL_EXECUTOR, new File(home_directory));
} else {
if (game_directory.equals(sdcard.getAbsolutePath())) {
HashSet<String> extStorage = FileBrowser.getExternalMounts();
if (extStorage != null && !extStorage.isEmpty()) {
for (String sd : extStorage) {
String sdCardPath = sd.replace("mnt/media_rw", "storage");
if (!sdCardPath.equals(sdcard.getAbsolutePath())) {
if (new File(sdCardPath).canRead()) {
(new navigate(this)).execute(new File(sdCardPath));
return;
}
}
}
}
}
(new navigate(this)).executeOnExecutor(
AsyncTask.THREAD_POOL_EXECUTOR, new File(game_directory));
}
}
private void createListHeader(String header_text, View view, boolean hasBios) {
if (hasBios && getResources().getString(R.string.flavor).equals("dreamcast")) {
final View childview = getActivity().getLayoutInflater().inflate(
R.layout.bios_list_item, null, false);
((TextView) childview.findViewById(R.id.item_name)).setText(R.string.boot_bios);
ImageView icon = (ImageView) childview.findViewById(R.id.item_icon);
icon.setImageResource(R.mipmap.disk_bios);
configureTheme(childview, true);
childview.setTag(null);
childview.findViewById(R.id.childview).setOnClickListener(
new OnClickListener() {
public void onClick(View view) {
vib.vibrate(50);
mCallback.onGameSelected(Uri.EMPTY);
vib.vibrate(250);
}
});
((ViewGroup) view).addView(childview);
}
if (searchQuery != null) {
final View childview = getActivity().getLayoutInflater().inflate(
R.layout.bios_list_item, null, false);
((TextView) childview.findViewById(R.id.item_name)).setText(R.string.clear_search);
ImageView icon = (ImageView) childview.findViewById(R.id.item_icon);
icon.setImageResource(R.mipmap.disk_unknown);
configureTheme(childview, true);
childview.setTag(null);
childview.findViewById(R.id.childview).setOnClickListener(
new OnClickListener() {
public void onClick(View view) {
searchQuery = null;
new LocateGames(FileBrowser.this,
R.array.images).execute(game_directory);
}
});
((ViewGroup) view).addView(childview);
}
final View headerView = getActivity().getLayoutInflater().inflate(
R.layout.browser_fragment_header, null, false);
((ImageView) headerView.findViewById(R.id.item_icon))
.setImageResource(R.drawable.open_folder);
((TextView) headerView.findViewById(R.id.item_name))
.setText(header_text);
((TextView) headerView.findViewById(R.id.item_name))
.setTypeface(Typeface.DEFAULT_BOLD);
((ViewGroup) view).addView(headerView);
}
private void createListItem(LinearLayout list, final File game, final int index, final boolean isGame) {
final View childview = getActivity().getLayoutInflater().inflate(
R.layout.browser_fragment_item, null, false);
XMLParser xmlParser = new XMLParser(game, index, mPrefs);
xmlParser.setViewParent(getActivity(), childview, mCallback);
childview.findViewById(R.id.childview).setOnClickListener(
new OnClickListener() {
public void onClick(View view) {
if (isGame) {
vib.vibrate(50);
Uri gameUri = Uri.EMPTY;
if (game != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
gameUri = FileProvider.getUriForFile(getActivity(),
"com.reicast.emulator.provider", game);
} else {
gameUri = Uri.fromFile(game);
}
}
mCallback.onGameSelected(gameUri);
vib.vibrate(250);
} else {
vib.vibrate(50);
home_directory = game.getAbsolutePath().substring(0,
game.getAbsolutePath().lastIndexOf(File.separator))
.replace("/data", "");
if (requireDataBIOS()) {
showToastMessage(getActivity().getString(R.string.config_data,
home_directory), Snackbar.LENGTH_LONG);
}
mPrefs.edit().putString(Config.pref_home, home_directory).apply();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
mCallback.onFolderSelected(FileProvider.getUriForFile(getActivity(),
"com.reicast.emulator.provider", new File(home_directory)));
} else {
mCallback.onFolderSelected(
Uri.fromFile(new File(home_directory)));
}
//JNIdc.config(home_directory);
}
}
});
configureTheme(childview, false);
list.addView(childview);
xmlParser.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, game.getName());
}
private static class navigate extends AsyncTask<File, Integer, List<File>> {
private WeakReference<FileBrowser> browser;
private String heading;
private File parent;
navigate(FileBrowser context) {
browser = new WeakReference<>(context);
}
private final class DirSort implements Comparator<File> {
@Override
public int compare(File filea, File fileb) {
return ((filea.isFile() ? "a" : "b") + filea.getName().toLowerCase(
Locale.getDefault()))
.compareTo((fileb.isFile() ? "a" : "b")
+ fileb.getName().toLowerCase(Locale.getDefault()));
}
}
@Override
protected void onPreExecute() {
LinearLayout listView = (LinearLayout)
browser.get().getActivity().findViewById(R.id.game_list);
if (listView.getChildCount() > 0)
listView.removeAllViews();
}
@Override
protected List<File> doInBackground(File... paths) {
heading = paths[0].getAbsolutePath();
ArrayList<File> list = new ArrayList<>();
File flist[] = paths[0].listFiles();
parent = paths[0].getParentFile();
list.add(null);
if (parent != null) {
list.add(parent);
}
if (flist != null) {
Arrays.sort(flist, new DirSort());
Collections.addAll(list, flist);
}
return list;
}
@Override
protected void onPostExecute(List<File> list) {
if (list != null && !list.isEmpty()) {
LinearLayout listView = (LinearLayout)
browser.get().getActivity().findViewById(R.id.game_list);
browser.get().createListHeader(heading, listView, false);
for (final File file : list) {
if (file != null && !file.isDirectory() && !file.getAbsolutePath().equals("/data"))
continue;
final View childview = browser.get().getActivity().getLayoutInflater().inflate(
R.layout.browser_fragment_item, null, false);
if (file == null) {
((TextView) childview.findViewById(R.id.item_name)).setText(R.string.folder_select);
} else if (file == parent)
((TextView) childview.findViewById(R.id.item_name)).setText("..");
else
((TextView) childview.findViewById(R.id.item_name)).setText(file.getName());
ImageView icon = (ImageView) childview.findViewById(R.id.item_icon);
icon.setImageResource(file == null
? R.drawable.ic_settings: file.isDirectory()
? R.drawable.ic_folder_black_24dp : R.drawable.disk_unknown);
browser.get().configureTheme(childview, true);
childview.setTag(file);
// vw.findViewById(R.id.childview).setBackgroundColor(0xFFFFFFFF);
childview.findViewById(R.id.childview).setOnClickListener(
new OnClickListener() {
public void onClick(View view) {
if (file != null && file.isDirectory()) {
(new navigate(browser.get())).executeOnExecutor(
AsyncTask.THREAD_POOL_EXECUTOR, file);
ScrollView sv = (ScrollView) browser.get().getActivity()
.findViewById(R.id.game_scroller);
sv.scrollTo(0, 0);
browser.get().vib.vibrate(50);
} else if (view.getTag() == null) {
browser.get().vib.vibrate(250);
if (browser.get().games) {
browser.get().game_directory = heading;
browser.get().mPrefs.edit().putString(
Config.pref_games, heading).apply();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
browser.get().mCallback.onFolderSelected(FileProvider
.getUriForFile(browser.get().getActivity(),
"com.reicast.emulator.provider",
new File(browser.get().game_directory)));
} else {
browser.get().mCallback.onFolderSelected(Uri.fromFile(
new File(browser.get().game_directory)));
}
} else {
browser.get().home_directory = heading
.replace("/data", "");
browser.get().mPrefs.edit().putString(
Config.pref_home, browser.get().home_directory).apply();
if (browser.get().requireDataBIOS()) {
browser.get().showToastMessage(browser.get().getActivity()
.getString(R.string.config_data, browser.get()
.home_directory), Snackbar.LENGTH_LONG);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
browser.get().mCallback.onFolderSelected(FileProvider
.getUriForFile(browser.get().getActivity(),
"com.reicast.emulator.provider",
new File(browser.get().home_directory)));
} else {
browser.get().mCallback.onFolderSelected(Uri.fromFile(
new File(browser.get().home_directory)));
}
//JNIdc.config(browser.get().home_directory);
}
}
}
});
listView.addView(childview);
}
listView.invalidate();
}
}
}
private boolean requireDataBIOS() {
File data_directory = new File(home_directory, "data");
if (data_directory.exists() && data_directory.isDirectory()) {
File bios = new File(home_directory, "data/dc_boot.bin");
File flash = new File(home_directory, "data/dc_flash.bin");
return !(bios.exists() && flash.exists());
} else {
if (data_directory.mkdirs()) {
File bios = new File(home_directory, "dc_boot.bin");
if (bios.renameTo(new File(home_directory, "data/dc_boot.bin"))) {
return !new File(home_directory, "dc_flash.bin").renameTo(
new File(home_directory, "data/dc_flash.bin"));
}
}
return true;
}
}
private void configureTheme(View childview, boolean useTint) {
}
private void showToastMessage(String message, int duration) {
ConstraintLayout layout = (ConstraintLayout) getActivity().findViewById(R.id.mainui_layout);
Snackbar snackbar = Snackbar.make(layout, message, duration);
View snackbarLayout = snackbar.getView();
TextView textView = (TextView) snackbarLayout.findViewById(
android.support.design.R.id.snackbar_text);
textView.setGravity(Gravity.CENTER_VERTICAL);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1)
textView.setTextAlignment(View.TEXT_ALIGNMENT_GRAVITY);
Drawable drawable;
if (android.os.Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
drawable = getResources().getDrawable(
R.drawable.ic_subdirectory_arrow_right, getActivity().getTheme());
} else {
drawable = VectorDrawableCompat.create(getResources(),
R.drawable.ic_subdirectory_arrow_right, getActivity().getTheme());
}
textView.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null);
textView.setCompoundDrawablePadding(getResources()
.getDimensionPixelOffset(R.dimen.snackbar_icon_padding));
snackbar.show();
}
}

View File

@ -2,16 +2,19 @@ package com.reicast.emulator;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.app.ActivityCompat;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.RelativeLayout;
import com.reicast.emulator.config.Config;
import com.reicast.emulator.emu.GL2JNIView;
import com.reicast.emulator.emu.JNIdc;
import com.reicast.emulator.periph.VJoy;
public class GL2JNIActivity extends BaseGLActivity implements ActivityCompat.OnRequestPermissionsResultCallback {
public class GL2JNIActivity extends BaseGLActivity {
private static ViewGroup mLayout; // used for text input
@Override
protected void onCreate(Bundle icicle) {
requestWindowFeature(Window.FEATURE_NO_TITLE);
@ -28,11 +31,10 @@ public class GL2JNIActivity extends BaseGLActivity implements ActivityCompat.OnR
// Create the actual GLES view
mView = new GL2JNIView(GL2JNIActivity.this, false,
prefs.getInt(Config.pref_renderdepth, 24), 8);
setContentView(mView);
mLayout = new RelativeLayout(this);
mLayout.addView(mView);
//setup mic
if (Emulator.micPluggedIn())
requestRecordAudioPermission();
setContentView(mLayout);
}
public void screenGrab() {
@ -40,23 +42,18 @@ public class GL2JNIActivity extends BaseGLActivity implements ActivityCompat.OnR
}
@Override
protected void onPause() {
super.onPause();
protected void doPause() {
((GL2JNIView)mView).onPause();
JNIdc.pause();
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mView != null) {
((GL2JNIView)mView).onDestroy();
}
protected boolean isSurfaceReady() {
return true; // FIXME
}
@Override
protected void onResume() {
super.onResume();
protected void doResume() {
((GL2JNIView)mView).onResume();
JNIdc.resume();
}

View File

@ -1,195 +0,0 @@
package com.reicast.emulator;
import android.Manifest;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.View.OnSystemUiVisibilityChangeListener;
import android.view.WindowManager;
import com.reicast.emulator.debug.GenerateLogs;
import com.reicast.emulator.emu.JNIdc;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private static final int PERMISSION_REQUEST = 1001;
private boolean hasAndroidMarket = false;
private boolean renderer_started = false;
private Uri gameUri;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
getWindow().getDecorView().setOnSystemUiVisibilityChangeListener (new OnSystemUiVisibilityChangeListener() {
public void onSystemUiVisibilityChange(int visibility) {
if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
getWindow().getDecorView().setSystemUiVisibility(
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_STICKY);
}
}
});
} else {
getWindow().setFlags (WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
String prior_error = prefs.getString("prior_error", null);
if (prior_error != null) {
displayLogOutput(prior_error);
prefs.edit().remove("prior_error").apply();
}
UncaughtExceptionHandler mUEHandler = new Thread.UncaughtExceptionHandler() {
public void uncaughtException(Thread t, Throwable error) {
if (error != null) {
StringBuilder output = new StringBuilder();
for (StackTraceElement trace : error.getStackTrace()) {
output.append(trace.toString());
output.append("\n");
}
prefs.edit().putString("prior_error", output.toString()).apply();
error.printStackTrace();
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(0);
}
}
};
Thread.setDefaultUncaughtExceptionHandler(mUEHandler);
Intent market = new Intent(Intent.ACTION_VIEW, Uri.parse("market://search?q=dummy"));
if (isCallable(market)) {
hasAndroidMarket = true;
}
if (!getFilesDir().exists()) {
getFilesDir().mkdir();
}
// When viewing a resource, pass its URI to the native code for opening
Intent intent = getIntent();
if (intent.getAction() != null) {
if (intent.getAction().equals(Intent.ACTION_VIEW)) {
gameUri = Uri.parse(intent.getData().toString());
// Flush the intent to prevent multiple calls
getIntent().setData(null);
setIntent(null);
}
}
if (prior_error == null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
},
PERMISSION_REQUEST);
} else
startNativeRenderer();
}
}
public void generateErrorLog() {
new GenerateLogs(MainActivity.this).execute(getFilesDir().getAbsolutePath());
}
/**
* Display a dialog to notify the user of prior crash
*
* @param error
* A generalized summary of the crash cause
*/
private void displayLogOutput(final String error) {
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setTitle(R.string.report_issue);
builder.setMessage(error);
builder.setPositiveButton(R.string.report,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
generateErrorLog();
startNativeRenderer();
}
});
builder.setNegativeButton(R.string.dismiss,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
startNativeRenderer();
}
});
builder.create();
builder.show();
}
private void startNativeRenderer() {
if (renderer_started)
return;
renderer_started = true;
if (gameUri != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
gameUri = Uri.parse(gameUri.toString().replace("content://"
+ gameUri.getAuthority() + "/external_files", "/storage"));
}
if (gameUri != null)
JNIdc.setGameUri(gameUri.toString());
Intent intent = new Intent("com.reicast.EMULATOR",
//gameUri, getApplicationContext(), GL2JNIActivity.class);
gameUri, getApplicationContext(), NativeGLActivity.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
startActivity(intent);
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
getWindow().getDecorView().setSystemUiVisibility(
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_STICKY);
}
}
private boolean isCallable(Intent intent) {
List<ResolveInfo> list = getPackageManager().queryIntentActivities(
intent, PackageManager.MATCH_DEFAULT_ONLY);
return list.size() > 0;
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (permissions.length > 0 && (Manifest.permission.READ_EXTERNAL_STORAGE.equals(permissions[0]) || Manifest.permission.WRITE_EXTERNAL_STORAGE.equals(permissions[0]))
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
startNativeRenderer();
}
}
}

View File

@ -2,7 +2,9 @@ package com.reicast.emulator;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.RelativeLayout;
import com.reicast.emulator.emu.JNIdc;
import com.reicast.emulator.emu.NativeGLView;
@ -10,6 +12,8 @@ import com.reicast.emulator.periph.VJoy;
public final class NativeGLActivity extends BaseGLActivity {
private static ViewGroup mLayout; // used for text input
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_NO_TITLE);
@ -17,28 +21,28 @@ public final class NativeGLActivity extends BaseGLActivity {
super.onCreate(savedInstanceState);
// Create the actual GL view
// mView = new NativeGLView(this);
// setContentView(mView);
setContentView(R.layout.nativegl_content);
mView = findViewById(R.id.glView);
mView = new NativeGLView(this);
mLayout = new RelativeLayout(this);
mLayout.addView(mView);
//setup mic
if (Emulator.micPluggedIn())
requestRecordAudioPermission();
setContentView(mLayout);
}
@Override
protected void onPause() {
super.onPause();
protected void doPause() {
((NativeGLView)mView).pause();
}
@Override
protected void onResume() {
super.onResume();
protected void doResume() {
((NativeGLView)mView).resume();
}
@Override
public boolean isSurfaceReady() {
return ((NativeGLView)mView).isSurfaceReady();
}
// Called from native code
private void VJoyStartEditing() {
vjoy_d_cached = VJoy.readCustomVjoyValues(getApplicationContext());

View File

@ -1,368 +0,0 @@
package com.reicast.emulator;
import android.app.AlertDialog;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.AsyncTask;
import android.os.Build;
import android.view.View;
import android.view.View.OnLongClickListener;
import android.widget.ImageView;
import android.widget.TextView;
import com.reicast.emulator.FileBrowser.OnItemSelectedListener;
import com.reicast.emulator.config.Config;
import org.apache.commons.io.FilenameUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.lang.ref.WeakReference;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.Locale;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
public class XMLParser extends AsyncTask<String, Integer, String> {
private SharedPreferences mPrefs;
private File game;
private int index;
private OnItemSelectedListener mCallback;
private String game_name;
private Drawable game_icon;
private String gameId;
private String game_details;
private WeakReference<Context> mContext;
private WeakReference<View> childview;
XMLParser(File game, int index, SharedPreferences mPrefs) {
this.mPrefs = mPrefs;
this.game = game;
this.index = index;
}
public void setViewParent(Context reference, View childview, OnItemSelectedListener mCallback) {
this.mContext = new WeakReference<>(reference);
this.childview = new WeakReference<>(childview);
this.mCallback = mCallback;
initializeDefaults();
}
private void setGameID(String id) {
this.gameId = id;
}
@Override
protected String doInBackground(String... params) {
String filename = game_name = params[0];
if (isNetworkAvailable() && mPrefs.getBoolean(Config.pref_gamedetails, false)) {
String xmlUrl;
if (gameId != null) {
xmlUrl = "http://legacy.thegamesdb.net/api/GetGame.php?platform=sega+dreamcast&id=" + gameId;
} else {
filename = filename.substring(0, filename.lastIndexOf("."));
try {
filename = URLEncoder.encode(filename, "UTF-8");
} catch (UnsupportedEncodingException e) {
filename = filename.replace(" ", "+");
}
xmlUrl = "http://legacy.thegamesdb.net/api/GetGamesList.php?platform=sega+dreamcast&name=" + filename;
}
try {
HttpURLConnection conn = (HttpURLConnection) new URL(xmlUrl).openConnection();
conn.setRequestMethod("POST");
conn.setDoInput(true);
InputStream in = conn.getInputStream();
BufferedReader streamReader = new BufferedReader(
new InputStreamReader(in, "UTF-8"));
StringBuilder responseStrBuilder = new StringBuilder();
String inputStr;
while ((inputStr = streamReader.readLine()) != null)
responseStrBuilder.append(inputStr);
in.close();
return responseStrBuilder.toString();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
@Override
protected void onPostExecute(String gameData) {
if (gameData != null) {
try {
Document doc = getDomElement(gameData);
if (doc.getElementsByTagName("Game") != null) {
Element root = (Element) doc.getElementsByTagName("Game").item(0);
if (gameId == null) {
XMLParser xmlParser = new XMLParser(game, index, mPrefs);
xmlParser.setViewParent(mContext.get(), childview.get(), mCallback);
xmlParser.setGameID(getValue(root, "id"));
xmlParser.execute(game_name);
} else if (root != null) {
String name = getValue(root, "GameTitle");
if (!name.equals(""))
game_name = name + " [" + FilenameUtils.getExtension(
game.getName()).toUpperCase(Locale.getDefault()) + "]";
game_details = getValue(root, "Overview");
getBoxart((Element) root.getElementsByTagName("Images").item(0));
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
if (childview.get() != null) {
((TextView) childview.get().findViewById(R.id.item_name)).setText(game_name);
if (mPrefs.getBoolean(Config.pref_gamedetails, false)) {
childview.get().findViewById(R.id.childview).setOnLongClickListener(
new OnLongClickListener() {
public boolean onLongClick(View view) {
new AlertDialog.Builder(mContext.get()).setCancelable(true).setIcon(game_icon)
.setTitle(mContext.get().getString(R.string.game_details, game_name))
.setMessage(game_details).create().show();
return true;
}
});
}
childview.get().setTag(game_name);
}
}
private void getBoxart(Element images) {
Element boxart = null;
if (images.getElementsByTagName("boxart").getLength() > 1) {
boxart = (Element) images.getElementsByTagName("boxart").item(1);
} else if (images.getElementsByTagName("boxart").getLength() == 1) {
boxart = (Element) images.getElementsByTagName("boxart").item(0);
}
if (boxart != null) {
decodeBitmapIcon icon = new decodeBitmapIcon(mContext.get());
icon.setListener(new decodeBitmapIcon.decodeBitmapIconListener() {
@Override
public void onDecodeBitmapIconFinished(Bitmap gameImage) {
if (childview.get() != null && gameImage != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
((ImageView) childview.get().findViewById(
R.id.item_icon)).setImageTintList(null);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
game_icon = new BitmapDrawable(
mContext.get().getResources(), gameImage);
} else {
//noinspection deprecation
game_icon = new BitmapDrawable(gameImage);
}
((ImageView) childview.get().findViewById(
R.id.item_icon)).setImageDrawable(game_icon);
}
}
});
icon.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,
"https://cdn.thegamesdb.net/images/thumb/"
+ getElementValue(boxart)
.replace("original/", ""));
}
}
private void initializeDefaults() {
game_details = mContext.get().getString(R.string.info_unavailable);
final String nameLower = game.getName().toLowerCase(Locale.getDefault());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
game_icon = mContext.get().getResources().getDrawable(
game.isDirectory() ? R.drawable.open_folder
: nameLower.endsWith(".gdi") ? R.mipmap.disk_gdi
: nameLower.endsWith(".chd") ? R.mipmap.disk_chd
: nameLower.endsWith(".cdi") ? R.mipmap.disk_cdi
: R.mipmap.disk_unknown);
} else {
game_icon = mContext.get().getResources().getDrawable(
game.isDirectory() ? R.drawable.open_folder
: nameLower.endsWith(".gdi") ? R.drawable.gdi
: nameLower.endsWith(".chd") ? R.drawable.chd
: nameLower.endsWith(".cdi") ? R.drawable.cdi
: R.drawable.disk_unknown);
}
ImageView icon = (ImageView) childview.get().findViewById(R.id.item_icon);
icon.setImageDrawable(game_icon);
}
private boolean isNetworkAvailable() {
ConnectivityManager connectivityManager = (ConnectivityManager) mContext.get()
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo mWifi = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
NetworkInfo mMobile = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
if (mMobile != null && mWifi != null) {
return mMobile.isAvailable() || mWifi.isAvailable();
} else {
return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}
}
private Document getDomElement(String xml) {
Document doc = null;
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
try {
DocumentBuilder db = dbf.newDocumentBuilder();
InputSource is = new InputSource();
is.setCharacterStream(new StringReader(xml));
doc = db.parse(is);
} catch (ParserConfigurationException e) {
return null;
} catch (SAXException e) {
return null;
} catch (IOException e) {
return null;
}
return doc;
}
private String getValue(Element item, String str) {
if (item != null) {
NodeList n = item.getElementsByTagName(str);
return this.getElementValue(n.item(0));
} else {
return "";
}
}
private String getElementValue(Node elem) {
Node child;
if (elem != null) {
if (elem.hasChildNodes()) {
for (child = elem.getFirstChild(); child != null; child = child
.getNextSibling()) {
if (child.getNodeType() == Node.TEXT_NODE) {
return child.getNodeValue();
}
}
}
}
return "";
}
private static class decodeBitmapIcon extends AsyncTask<String, Integer, Bitmap> {
private WeakReference<Context> mContext;
private decodeBitmapIconListener listener;
decodeBitmapIcon(Context reference) {
this.mContext = new WeakReference<>(reference);
}
@Override
protected Bitmap doInBackground(String... params) {
try {
String index = params[0].substring(params[0].lastIndexOf(
"/") + 1, params[0].lastIndexOf("."));
File file = new File(mContext.get().getExternalFilesDir(
null) + "/images", index + ".png");
if (file.exists()) {
return BitmapFactory.decodeFile(file.getAbsolutePath());
} else {
URL updateURL = new URL(params[0]);
URLConnection conn1 = updateURL.openConnection();
InputStream im = conn1.getInputStream();
BufferedInputStream bis = new BufferedInputStream(im, 512);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(bis, null, options);
int heightRatio = (int) Math.ceil(options.outHeight / (float) 72);
int widthRatio = (int) Math.ceil(options.outWidth / (float) 72);
if (heightRatio > 1 || widthRatio > 1) {
if (heightRatio > widthRatio) {
options.inSampleSize = heightRatio;
} else {
options.inSampleSize = widthRatio;
}
}
options.inJustDecodeBounds = false;
bis.close();
im.close();
conn1 = updateURL.openConnection();
im = conn1.getInputStream();
bis = new BufferedInputStream(im, 512);
Bitmap bitmap = BitmapFactory.decodeStream(bis, null, options);
bis.close();
im.close();
OutputStream fOut;
if (!file.getParentFile().exists()) {
file.getParentFile().mkdir();
}
try {
fOut = new FileOutputStream(file, false);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fOut);
fOut.flush();
fOut.close();
} catch (Exception ex) {
ex.printStackTrace();
}
return bitmap;
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Bitmap gameImage) {
super.onPostExecute(gameImage);
if (listener != null) {
listener.onDecodeBitmapIconFinished(gameImage);
}
}
void setListener(decodeBitmapIconListener listener) {
this.listener = listener;
}
public interface decodeBitmapIconListener {
void onDecodeBitmapIconFinished(Bitmap gameImage);
}
}
}

View File

@ -3,11 +3,8 @@ package com.reicast.emulator.config;
public class Config {
public static final String pref_home = "home_directory";
public static final String pref_games = "game_directory";
public static final String pref_theme = "button_theme";
public static final String pref_gamedetails = "game_details";
public static final String pref_rendertype = "render_type";
public static final String pref_renderdepth = "depth_render";

View File

@ -1,653 +0,0 @@
package com.reicast.emulator.config;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.app.Fragment;
import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.ImageView;
import android.widget.Spinner;
import android.widget.TextView;
import com.reicast.emulator.R;
import com.reicast.emulator.periph.Gamepad;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import tv.ouya.console.api.OuyaController;
public class InputModFragment extends Fragment {
private SharedPreferences mPrefs;
private CompoundButton switchModifiedLayoutEnabled;
private CompoundButton switchCompatibilityEnabled;
private Spinner right_stick_spinner;
private CompoundButton switchJoystickDpadEnabled;
private TextView a_button_text;
private TextView b_button_text;
private TextView x_button_text;
private TextView y_button_text;
private TextView l_button_text;
private TextView r_button_text;
private TextView dpad_up_text;
private TextView dpad_down_text;
private TextView dpad_left_text;
private TextView dpad_right_text;
private TextView start_button_text;
private TextView select_button_text;
private TextView joystick_x_text;
private TextView joystick_y_text;
private String player = "_A";
private int sS = 2;
private int playerNum = -1;
private mapKeyCode mKey;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.input_mod_fragment, container, false);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
mPrefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
final String[] controllers = getResources().getStringArray(R.array.controllers);
Bundle b = getArguments();
if (b != null) {
playerNum = b.getInt("portNumber", -1);
}
switchJoystickDpadEnabled = (CompoundButton) getView().findViewById(
R.id.switchJoystickDpadEnabled);
switchModifiedLayoutEnabled = (CompoundButton) getView().findViewById(
R.id.switchModifiedLayoutEnabled);
switchCompatibilityEnabled = (CompoundButton) getView().findViewById(
R.id.switchCompatibilityEnabled);
OnCheckedChangeListener joystick_mode = new OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
mPrefs.edit().putBoolean(Gamepad.pref_js_merged + player, isChecked).apply();
}
};
switchJoystickDpadEnabled.setOnCheckedChangeListener(joystick_mode);
String[] rstick = getResources().getStringArray(R.array.right_stick);
right_stick_spinner = (Spinner) getView().findViewById(R.id.rstick_spinner);
ArrayAdapter<String> rstickAdapter = new ArrayAdapter<>(
getActivity(), android.R.layout.simple_spinner_item, rstick);
rstickAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
right_stick_spinner.setAdapter(rstickAdapter);
right_stick_spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
mPrefs.edit().putInt(Gamepad.pref_js_rstick + player, pos).apply();
}
public void onNothingSelected(AdapterView<?> arg0) {
}
});
OnCheckedChangeListener modified_layout = new OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
mPrefs.edit().putBoolean(Gamepad.pref_js_modified + player, isChecked).apply();
}
};
switchModifiedLayoutEnabled.setOnCheckedChangeListener(modified_layout);
OnCheckedChangeListener compat_mode = new OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
mPrefs.edit().putBoolean(Gamepad.pref_js_compat + player, isChecked).apply();
if (isChecked) {
selectController();
}
}
};
switchCompatibilityEnabled.setOnCheckedChangeListener(compat_mode);
mKey = new mapKeyCode(getActivity());
ImageView a_button_icon = (ImageView) getView().findViewById(
R.id.a_button_icon);
a_button_icon.setImageDrawable(getButtonImage(448 / sS, 0));
a_button_text = (TextView) getView().findViewById(R.id.a_button_key);
Button a_button = (Button) getView().findViewById(R.id.a_button_edit);
a_button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
mKey.intiateSearch(Gamepad.pref_button_a, a_button_text);
}
});
Button a_remove = (Button) getView().findViewById(R.id.remove_a_button);
a_remove.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
remKeyCode(Gamepad.pref_button_a, a_button_text);
}
});
ImageView b_button_icon = (ImageView) getView().findViewById(
R.id.b_button_icon);
b_button_icon.setImageDrawable(getButtonImage(384 / sS, 0));
b_button_text = (TextView) getView().findViewById(R.id.b_button_key);
Button b_button = (Button) getView().findViewById(R.id.b_button_edit);
b_button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
mKey.intiateSearch(Gamepad.pref_button_b, b_button_text);
}
});
Button b_remove = (Button) getView().findViewById(R.id.remove_b_button);
b_remove.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
remKeyCode(Gamepad.pref_button_b, b_button_text);
}
});
ImageView x_button_icon = (ImageView) getView().findViewById(
R.id.x_button_icon);
x_button_icon.setImageDrawable(getButtonImage(256 / sS, 0));
x_button_text = (TextView) getView().findViewById(R.id.x_button_key);
Button x_button = (Button) getView().findViewById(R.id.x_button_edit);
x_button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
mKey.intiateSearch(Gamepad.pref_button_x, x_button_text);
}
});
Button x_remove = (Button) getView().findViewById(R.id.remove_x_button);
x_remove.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
remKeyCode(Gamepad.pref_button_x, x_button_text);
}
});
ImageView y_button_icon = (ImageView) getView().findViewById(
R.id.y_button_icon);
y_button_icon.setImageDrawable(getButtonImage(320 / sS, 0));
y_button_text = (TextView) getView().findViewById(R.id.y_button_key);
Button y_button = (Button) getView().findViewById(R.id.y_button_edit);
y_button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
mKey.intiateSearch(Gamepad.pref_button_y, y_button_text);
}
});
Button y_remove = (Button) getView().findViewById(R.id.remove_y_button);
y_remove.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
remKeyCode(Gamepad.pref_button_y, y_button_text);
}
});
ImageView l_button_icon = (ImageView) getView().findViewById(
R.id.l_button_icon);
l_button_icon.setImageDrawable(getButtonImage(78 / sS, 64 / sS));
l_button_text = (TextView) getView().findViewById(R.id.l_button_key);
Button l_button = (Button) getView().findViewById(R.id.l_button_edit);
l_button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
mKey.intiateSearch(Gamepad.pref_button_l, l_button_text);
}
});
Button l_remove = (Button) getView().findViewById(R.id.remove_l_button);
l_remove.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
remKeyCode(Gamepad.pref_button_l, l_button_text);
}
});
ImageView r_button_icon = (ImageView) getView().findViewById(
R.id.r_button_icon);
r_button_icon.setImageDrawable(getButtonImage(162 / sS, 64 / sS));
r_button_text = (TextView) getView().findViewById(R.id.r_button_key);
Button r_button = (Button) getView().findViewById(R.id.r_button_edit);
r_button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
mKey.intiateSearch(Gamepad.pref_button_r, r_button_text);
}
});
Button r_remove = (Button) getView().findViewById(R.id.remove_r_button);
r_remove.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
remKeyCode(Gamepad.pref_button_r, r_button_text);
}
});
dpad_up_text = (TextView) getView().findViewById(R.id.dpad_up_key);
Button dpad_up = (Button) getView().findViewById(R.id.dpad_up_edit);
dpad_up.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
mKey.intiateSearch(Gamepad.pref_dpad_up, dpad_up_text);
}
});
Button up_remove = (Button) getView().findViewById(R.id.remove_dpad_up);
up_remove.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
remKeyCode(Gamepad.pref_dpad_up, dpad_up_text);
}
});
dpad_down_text = (TextView) getView().findViewById(R.id.dpad_down_key);
Button dpad_down = (Button) getView().findViewById(R.id.dpad_down_edit);
dpad_down.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
mKey.intiateSearch(Gamepad.pref_dpad_down, dpad_down_text);
}
});
Button down_remove = (Button) getView().findViewById(
R.id.remove_dpad_down);
down_remove.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
remKeyCode(Gamepad.pref_dpad_down, dpad_down_text);
}
});
dpad_left_text = (TextView) getView().findViewById(R.id.dpad_left_key);
Button dpad_left = (Button) getView().findViewById(R.id.dpad_left_edit);
dpad_left.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
mKey.intiateSearch(Gamepad.pref_dpad_left, dpad_left_text);
}
});
Button left_remove = (Button) getView().findViewById(
R.id.remove_dpad_left);
left_remove.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
remKeyCode(Gamepad.pref_dpad_left, dpad_left_text);
}
});
dpad_right_text = (TextView) getView()
.findViewById(R.id.dpad_right_key);
Button dpad_right = (Button) getView().findViewById(
R.id.dpad_right_edit);
dpad_right.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
mKey.intiateSearch(Gamepad.pref_dpad_right, dpad_right_text);
}
});
Button right_remove = (Button) getView().findViewById(
R.id.remove_dpad_right);
right_remove.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
remKeyCode(Gamepad.pref_dpad_right, dpad_right_text);
}
});
joystick_x_text = (TextView) getView().findViewById(
R.id.joystick_x_axis);
Button joystick_x = (Button) getView().findViewById(
R.id.joystick_x_edit);
joystick_x.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
mKey.mapAxis(Gamepad.pref_axis_x, joystick_x_text);
}
});
Button joystick_x_remove = (Button) getView().findViewById(
R.id.remove_joystick_x);
joystick_x_remove.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
remKeyCode(Gamepad.pref_axis_x, joystick_x_text);
}
});
joystick_y_text = (TextView) getView().findViewById(
R.id.joystick_y_axis);
Button joystick_y = (Button) getView().findViewById(
R.id.joystick_y_edit);
joystick_y.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
mKey.mapAxis(Gamepad.pref_axis_y, joystick_y_text);
}
});
Button joystick_y_remove = (Button) getView().findViewById(
R.id.remove_joystick_y);
joystick_y_remove.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
remKeyCode(Gamepad.pref_axis_y, joystick_y_text);
}
});
ImageView start_button_icon = (ImageView) getView().findViewById(
R.id.start_button_icon);
start_button_icon.setImageDrawable(getButtonImage(0, 64 / sS));
start_button_text = (TextView) getView().findViewById(
R.id.start_button_key);
Button start_button = (Button) getView().findViewById(
R.id.start_button_edit);
start_button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
mKey.intiateSearch(Gamepad.pref_button_start, start_button_text);
}
});
Button start_remove = (Button) getView()
.findViewById(R.id.remove_start);
start_remove.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
remKeyCode(Gamepad.pref_button_start, start_button_text);
}
});
ImageView select_button_icon = (ImageView) getView().findViewById(
R.id.select_button_icon);
select_button_icon.setImageResource(R.drawable.ic_drawer);
select_button_text = (TextView) getView().findViewById(
R.id.select_button_key);
Button select_button = (Button) getView().findViewById(
R.id.select_button_edit);
select_button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
mKey.intiateSearch(Gamepad.pref_button_select,
select_button_text);
}
});
Button select_remove = (Button) getView().findViewById(
R.id.remove_select);
select_remove.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
remKeyCode(Gamepad.pref_button_select, select_button_text);
}
});
Spinner player_spnr = (Spinner) getView().findViewById(
R.id.player_spinner);
ArrayAdapter<String> playerAdapter = new ArrayAdapter<>(
getActivity(), android.R.layout.simple_spinner_item,
controllers);
playerAdapter
.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
player_spnr.setAdapter(playerAdapter);
if (playerNum != -1) {
player_spnr.setSelection(playerNum, true);
}
player_spnr.setOnItemSelectedListener(new OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view,
int pos, long id) {
String selection = parent.getItemAtPosition(pos).toString();
player = "_"
+ selection.substring(selection.lastIndexOf(" ") + 1,
selection.length());
playerNum = pos;
updateController(player);
}
public void onNothingSelected(AdapterView<?> arg0) {
}
});
updateController(player);
}
/**
* Retrieve an image to serve as a visual representation
*
* @param x
* The x start value of the image within the atlas
* @param y
* The y start value of the image within the atlas
*/
private Drawable getButtonImage(int x, int y) {
Bitmap image = null;
try {
File buttons = null;
InputStream bitmap;
String theme = mPrefs.getString(Config.pref_theme, null);
if (theme != null) {
buttons = new File(theme);
}
if (buttons != null && buttons.exists()) {
bitmap = new FileInputStream(buttons);
} else {
bitmap = getResources().getAssets().open("buttons.png");
}
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = sS;
image = BitmapFactory.decodeStream(bitmap, null, options);
bitmap.close();
Matrix matrix = new Matrix();
matrix.postScale(32, 32);
Bitmap resizedBitmap = Bitmap.createBitmap(image, x, y, 64 / sS,
64 / sS, matrix, true);
@SuppressWarnings("deprecation")
BitmapDrawable bmd = new BitmapDrawable(resizedBitmap);
image.recycle();
image = null;
return bmd;
} catch (IOException e1) {
e1.printStackTrace();
} catch (OutOfMemoryError E) {
if (sS == 2) {
if (image != null) {
image.recycle();
}
sS = 4;
return getButtonImage(x, y);
} else {
E.printStackTrace();
}
}
return getResources().getDrawable(R.drawable.input);
}
/**
* Prompt the user to specify the controller to modify
*
*/
private void selectController() {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(R.string.select_controller_title);
builder.setMessage(getString(R.string.select_controller_message, player.replace("_", "")));
builder.setNegativeButton(R.string.cancel,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
builder.setOnKeyListener(new Dialog.OnKeyListener() {
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
mPrefs.edit().putInt("controller" + player, event.getDeviceId()).apply();
dialog.dismiss();
return true;
}
});
builder.create();
builder.show();
}
private class mapKeyCode extends AlertDialog.Builder {
mapKeyCode(Context c) {
super(c);
}
/**
* Prompt the user for the button to be assigned
*
* @param button
* The name of the emulator button being defined
* @param output
* The output display for the assigned button value
*/
public void intiateSearch(final String button, final TextView output) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(R.string.map_keycode_title);
builder.setMessage(getString(R.string.map_keycode_message, button.replace("_", " ")));
builder.setNegativeButton(R.string.cancel,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
builder.setOnKeyListener(new Dialog.OnKeyListener() {
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
mapButton(keyCode, button);
dialog.dismiss();
return getKeyCode(button, output);
}
});
builder.create();
builder.show();
}
/**
* Assign the user button to the emulator button
*
* @param keyCode
* The keycode generated by the button being assigned
* @param button
* The label of the button being assigned
*/
private void mapButton(int keyCode, String button) {
if (Build.MODEL.startsWith("R800")) {
if (keyCode == KeyEvent.KEYCODE_MENU)
return;
} else {
if (keyCode == KeyEvent.KEYCODE_BACK)
return;
}
mPrefs.edit().putInt(button + player, keyCode).apply();
}
private void mapAxis(final String button, final TextView output) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(R.string.map_keycode_title);
builder.setMessage(getString(R.string.map_keycode_message, button.replace("_", " ")));
View view = getLayoutInflater().inflate(R.layout.joystick_dialog, null);
builder.setView(view);
builder.setCancelable(false);
builder.create();
final Dialog dialog = builder.show();
view.findViewById(R.id.joystick_cancel_btn).setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
dialog.dismiss();
}
});
view.requestFocusFromTouch();
view.setOnGenericMotionListener(new View.OnGenericMotionListener() {
@Override
public boolean onGenericMotion(View view, MotionEvent event) {
int axis = -1;
if ((event.getSource() & InputDevice.SOURCE_JOYSTICK) ==
InputDevice.SOURCE_JOYSTICK &&
event.getAction() == MotionEvent.ACTION_MOVE) {
if (event.getAxisValue(MotionEvent.AXIS_X) != 0) {
axis = MotionEvent.AXIS_X;
}
if (event.getAxisValue(MotionEvent.AXIS_Y) != 0) {
axis = MotionEvent.AXIS_Y;
}
if (event.getAxisValue(MotionEvent.AXIS_RX) != 0) {
axis = MotionEvent.AXIS_RX;
}
if (event.getAxisValue(MotionEvent.AXIS_RY) != 0) {
axis = MotionEvent.AXIS_RY;
}
if (event.getAxisValue(MotionEvent.AXIS_HAT_X) != 0) {
axis = MotionEvent.AXIS_HAT_X;
}
if (event.getAxisValue(MotionEvent.AXIS_HAT_Y) != 0) {
axis = MotionEvent.AXIS_HAT_Y;
}
if (new Gamepad().IsOuyaOrTV(getActivity(), true)) {
if (event.getAxisValue(OuyaController.AXIS_LS_X) != 0) {
axis = OuyaController.AXIS_LS_X;
}
if (event.getAxisValue(OuyaController.AXIS_LS_Y) != 0) {
axis = OuyaController.AXIS_LS_Y;
}
}
mPrefs.edit().putInt(button + player, axis).apply();
dialog.dismiss();
return getKeyCode(button, output);
}
return true;
}
});
}
}
private void updateController(String player) {
switchJoystickDpadEnabled.setChecked(mPrefs.getBoolean(
Gamepad.pref_js_merged + player, false));
right_stick_spinner.setSelection(mPrefs.getInt(Gamepad.pref_js_rstick + player, 0));
switchModifiedLayoutEnabled.setChecked(mPrefs.getBoolean(
Gamepad.pref_js_modified + player, false));
switchCompatibilityEnabled.setChecked(mPrefs.getBoolean(
Gamepad.pref_js_compat + player, false));
getKeyCode(Gamepad.pref_button_a, a_button_text);
getKeyCode(Gamepad.pref_button_b, b_button_text);
getKeyCode(Gamepad.pref_button_x, x_button_text);
getKeyCode(Gamepad.pref_button_y, y_button_text);
getKeyCode(Gamepad.pref_button_l, l_button_text);
getKeyCode(Gamepad.pref_button_r, r_button_text);
getKeyCode(Gamepad.pref_dpad_up, dpad_up_text);
getKeyCode(Gamepad.pref_dpad_down, dpad_down_text);
getKeyCode(Gamepad.pref_dpad_left, dpad_left_text);
getKeyCode(Gamepad.pref_dpad_right, dpad_right_text);
getKeyCode(Gamepad.pref_axis_x, joystick_x_text);
getKeyCode(Gamepad.pref_axis_y, joystick_y_text);
getKeyCode(Gamepad.pref_button_start, start_button_text);
getKeyCode(Gamepad.pref_button_select, select_button_text);
}
private boolean getKeyCode(final String button, final TextView output) {
int keyCode = mPrefs.getInt(button + player, -1);
if (keyCode != -1) {
String label = output.getText().toString();
if (label.contains(":")) {
label = label.substring(0, label.indexOf(":"));
}
label += ": " + keyCode;
output.setText(label);
return true;
} else {
String label = output.getText().toString();
if (label.contains(":")) {
label = label.substring(0, label.indexOf(":"));
}
output.setText(label);
return false;
}
}
private void remKeyCode(final String button, TextView output) {
mPrefs.edit().remove(button + player).apply();
getKeyCode(button, output);
}
}

View File

@ -1,488 +0,0 @@
package com.reicast.emulator.config;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.preference.PreferenceManager;
import android.support.constraint.ConstraintLayout;
import android.support.design.widget.Snackbar;
import android.support.graphics.drawable.VectorDrawableCompat;
import android.support.v4.app.Fragment;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
import com.android.util.FileUtils;
import com.reicast.emulator.Emulator;
import com.reicast.emulator.FileBrowser;
import com.reicast.emulator.R;
import com.reicast.emulator.emu.GL2JNIView;
import com.reicast.emulator.emu.JNIdc;
import org.apache.commons.lang3.StringUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.ref.WeakReference;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
public class OptionsFragment extends Fragment {
private Spinner mSpnrThemes;
private OnClickListener mCallback;
private SharedPreferences mPrefs;
private File sdcard = Environment.getExternalStorageDirectory();
private String home_directory = sdcard.getAbsolutePath();
private String game_directory = sdcard.getAbsolutePath();
private String[] codes;
// Container Activity must implement this interface
public interface OnClickListener {
void recreateActivity();
void onMainBrowseSelected(String path_entry, boolean games, String query);
void launchBIOSdetection();
void synchronousRenderingNotice();
}
@Override @SuppressWarnings("deprecation")
public void onAttach(Activity activity) {
super.onAttach(activity);
// This makes sure that the container activity has implemented
// the callback interface. If not, it throws an exception
try {
mCallback = (OnClickListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnClickListener");
}
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
// This makes sure that the container activity has implemented
// the callback interface. If not, it throws an exception
try {
mCallback = (OnClickListener) context;
} catch (ClassCastException e) {
throw new ClassCastException(context.getClass().toString()
+ " must implement OnClickListener");
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.configure_fragment, container, false);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
mPrefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
// FIXME Specialized handler for devices with an extSdCard mount for external
HashSet<String> extStorage = FileBrowser.getExternalMounts();
if (extStorage != null && !extStorage.isEmpty()) {
for (String sd : extStorage) {
String sdCardPath = sd.replace("mnt/media_rw", "storage");
if (!sdCardPath.equals(sdcard.getAbsolutePath())) {
game_directory = sdCardPath;
}
}
}
home_directory = mPrefs.getString(Config.pref_home, home_directory);
Emulator app = (Emulator) getActivity().getApplicationContext();
app.getConfigurationPrefs();
// Generate the menu options and fill in existing settings
Button mainBrowse = (Button) getView().findViewById(R.id.browse_main_path);
mSpnrThemes = (Spinner) getView().findViewById(R.id.pick_button_theme);
new LocateThemes(this).execute(home_directory + "/themes");
final EditText editBrowse = (EditText) getView().findViewById(R.id.main_path);
editBrowse.setText(home_directory);
mainBrowse.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
mPrefs.edit().remove(Config.pref_home).apply();
hideSoftKeyBoard();
mCallback.launchBIOSdetection();
}
});
editBrowse.setOnEditorActionListener(new EditText.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_DONE
|| (event != null && event.getKeyCode() == KeyEvent.KEYCODE_ENTER
&& event.getAction() == KeyEvent.ACTION_DOWN)) {
if (event == null || !event.isShiftPressed()) {
if (v.getText() != null) {
home_directory = v.getText().toString();
if (home_directory.endsWith("/data")) {
home_directory.replace("/data", "");
showToastMessage(getActivity().getString(R.string.data_folder),
Snackbar.LENGTH_SHORT);
}
mPrefs.edit().putString(Config.pref_home, home_directory).apply();
//JNIdc.config(home_directory);
new LocateThemes(OptionsFragment.this).execute(home_directory + "/themes");
}
hideSoftKeyBoard();
return true;
}
}
return false;
}
});
OnCheckedChangeListener details_options = new OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
mPrefs.edit().putBoolean(Config.pref_gamedetails, isChecked).apply();
if (!isChecked) {
File dir = new File(getActivity().getExternalFilesDir(null), "images");
File[] files = dir == null ? null : dir.listFiles();
if (files != null) {
for (File file : files) {
if (!file.isDirectory()) {
file.delete();
}
}
}
}
}
};
CompoundButton details_opt = (CompoundButton) getView().findViewById(R.id.details_option);
details_opt.setChecked(mPrefs.getBoolean(Config.pref_gamedetails, false));
details_opt.setOnCheckedChangeListener(details_options);
Button gameBrowse = (Button) getView().findViewById(R.id.browse_game_path);
final EditText editGames = (EditText) getView().findViewById(R.id.game_path);
game_directory = mPrefs.getString(Config.pref_games, game_directory);
editGames.setText(game_directory);
gameBrowse.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
mPrefs.edit().remove(Config.pref_games).apply();
if (editBrowse.getText() != null) {
game_directory = editGames.getText().toString();
}
hideSoftKeyBoard();
mCallback.onMainBrowseSelected(game_directory, true, null);
}
});
editGames.setOnEditorActionListener(new EditText.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_DONE
|| (event != null && event.getKeyCode() == KeyEvent.KEYCODE_ENTER
&& event.getAction() == KeyEvent.ACTION_DOWN)) {
if (event == null || !event.isShiftPressed()) {
if (v.getText() != null) {
game_directory = v.getText().toString();
mPrefs.edit().putString(Config.pref_games, game_directory).apply();
}
hideSoftKeyBoard();
return true;
}
}
return false;
}
});
CompoundButton force_software_opt = (CompoundButton) getView().findViewById(
R.id.software_option);
OnCheckedChangeListener force_software = new OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
mPrefs.edit().putInt(Config.pref_rendertype, isChecked ?
GL2JNIView.LAYER_TYPE_SOFTWARE : GL2JNIView.LAYER_TYPE_HARDWARE).apply();
}
};
int software = mPrefs.getInt(Config.pref_rendertype, GL2JNIView.LAYER_TYPE_HARDWARE);
force_software_opt.setChecked(software == GL2JNIView.LAYER_TYPE_SOFTWARE);
force_software_opt.setOnCheckedChangeListener(force_software);
String[] depths = getResources().getStringArray(R.array.depth);
Spinner depth_spnr = (Spinner) getView().findViewById(R.id.depth_spinner);
ArrayAdapter<String> depthAdapter = new ArrayAdapter<>(
getActivity(), R.layout.spinner_selected, depths);
depthAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
depth_spnr.setAdapter(depthAdapter);
setSpinner(R.array.depth, R.id.depth_spinner,
Config.pref_renderdepth, 24, true);
Button resetEmu = (Button) getView().findViewById(R.id.reset_emu_btn);
resetEmu.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
AlertDialog.Builder b = new AlertDialog.Builder(getActivity());
b.setIcon(android.R.drawable.ic_dialog_alert);
b.setTitle(getActivity().getString(R.string.reset_emu_title) + "?");
b.setMessage(getActivity().getString(R.string.reset_emu_details));
b.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
resetEmuSettings();
}
});
b.setNegativeButton(android.R.string.no, null);
b.show();
}
});
}
private void setSpinner(int array, int view, final String pref, int def, final boolean parse) {
String[] stringArray = getResources().getStringArray(array);
Spinner spinner = (Spinner) getView().findViewById(view);
ArrayAdapter<String> adapter = new ArrayAdapter<>(
getActivity(), R.layout.spinner_selected, stringArray);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
if (parse) {
String value = String.valueOf(mPrefs.getInt(pref, def));
spinner.setSelection(adapter.getPosition(value), true);
} else {
spinner.setSelection(mPrefs.getInt(pref, def), true);
}
spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
if (parse) {
int value = Integer.parseInt(parent.getItemAtPosition(pos).toString());
mPrefs.edit().putInt(pref, value).apply();
} else {
mPrefs.edit().putInt(pref, pos).apply();
}
}
public void onNothingSelected(AdapterView<?> arg0) {
}
});
}
private static class LocateThemes extends AsyncTask<String, Integer, List<File>> {
private WeakReference<OptionsFragment> options;
LocateThemes(OptionsFragment context) {
options = new WeakReference<>(context);
}
@Override
protected List<File> doInBackground(String... paths) {
File storage = new File(paths[0]);
String[] mediaTypes = options.get().getResources().getStringArray(R.array.themes_ext);
FilenameFilter[] filter = new FilenameFilter[mediaTypes.length];
int i = 0;
for (final String type : mediaTypes) {
filter[i] = new FilenameFilter() {
public boolean accept(File dir, String name) {
return !dir.getName().startsWith(".") && !name.startsWith(".")
&& StringUtils.endsWithIgnoreCase(name, "." + type);
}
};
i++;
}
FileUtils fileUtils = new FileUtils();
Collection<File> files = fileUtils.listFiles(storage, filter, 0);
return (List<File>) files;
}
@Override
protected void onPostExecute(List<File> items) {
if (items != null && !items.isEmpty()) {
String[] themes = new String[items.size() + 1];
for (int i = 0; i < items.size(); i ++) {
themes[i] = items.get(i).getName();
}
themes[items.size()] = "None";
ArrayAdapter<String> themeAdapter = new ArrayAdapter<>(
options.get().getActivity(), android.R.layout.simple_spinner_item, themes);
themeAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
options.get().mSpnrThemes.setAdapter(themeAdapter);
options.get().mSpnrThemes.setOnItemSelectedListener(new OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
String theme = String.valueOf(parentView.getItemAtPosition(position));
if (theme.equals("None")) {
options.get().mPrefs.edit().remove(Config.pref_theme).apply();
} else {
String theme_path = options.get().home_directory + "/themes/" + theme;
options.get().mPrefs.edit().putString(Config.pref_theme, theme_path).apply();
}
}
@Override
public void onNothingSelected(AdapterView<?> parentView) {
}
});
} else {
options.get().mSpnrThemes.setEnabled(false);
}
}
}
private void hideSoftKeyBoard() {
try {
InputMethodManager iMm = (InputMethodManager) getActivity()
.getSystemService(Context.INPUT_METHOD_SERVICE);
if (iMm != null && iMm.isAcceptingText()) {
iMm.hideSoftInputFromWindow(getActivity().getCurrentFocus().getWindowToken(), 0);
}
} catch (NullPointerException e) {
// Keyboard may still be visible
}
}
private void copy(File src, File dst) throws IOException {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
try (InputStream in = new FileInputStream(src)) {
try (OutputStream out = new FileOutputStream(dst)) {
// Transfer bytes from in to out
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
}
}
} else {
InputStream in = new FileInputStream(src);
OutputStream out = new FileOutputStream(dst);
try {
// Transfer bytes from in to out
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
} finally {
in.close();
out.close();
}
}
}
private void flashBios(String localized) {
File local = new File(home_directory, "data/dc_flash[" + localized
+ "].bin");
File flash = new File(home_directory, "data/dc_flash.bin");
if (local.exists()) {
if (flash.exists()) {
flash.delete();
}
try {
copy(local, flash);
} catch (IOException ex) {
ex.printStackTrace();
local.renameTo(flash);
}
}
}
private void resetEmuSettings() {
mPrefs.edit().remove(Config.pref_gamedetails).apply();
mPrefs.edit().remove(Config.pref_rendertype).apply();
mPrefs.edit().remove(Config.pref_renderdepth).apply();
mPrefs.edit().remove(Config.pref_theme).apply();
Emulator.nosound = false;
getActivity().finish();
}
private void showToastMessage(String message, int duration) {
ConstraintLayout layout = (ConstraintLayout) getActivity().findViewById(R.id.mainui_layout);
Snackbar snackbar = Snackbar.make(layout, message, duration);
View snackbarLayout = snackbar.getView();
TextView textView = (TextView) snackbarLayout.findViewById(
android.support.design.R.id.snackbar_text);
textView.setGravity(Gravity.CENTER_VERTICAL);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1)
textView.setTextAlignment(View.TEXT_ALIGNMENT_GRAVITY);
Drawable drawable;
if (android.os.Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
drawable = getResources().getDrawable(
R.drawable.ic_settings, getActivity().getTheme());
} else {
drawable = VectorDrawableCompat.create(getResources(),
R.drawable.ic_settings, getActivity().getTheme());
}
textView.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null);
textView.setCompoundDrawablePadding(getResources()
.getDimensionPixelOffset(R.dimen.snackbar_icon_padding));
snackbar.show();
}
private int getBroadcastValue(String broadcastName) {
if (broadcastName.equals("NTSC-J"))
return 0;
else if (broadcastName.equals("NTSC-U"))
return 4;
else if (broadcastName.equals("PAL-M"))
return 6;
else if (broadcastName.equals("PAL-N"))
return 7;
else if (broadcastName.equals("PAL-E"))
return 9;
else
return -1;
}
private String getBroadcastName(int broadcastValue) {
if (broadcastValue == 0)
return "NTSC-J";
else if (broadcastValue == 4)
return "NTSC-U";
else if (broadcastValue == 6)
return "PAL-M";
else if (broadcastValue == 7)
return "PAL-N";
else if (broadcastValue == 9)
return "PAL-E";
else
return null;
}
}

View File

@ -1,170 +0,0 @@
package com.reicast.emulator.debug;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.graphics.PorterDuff;
import android.os.Build;
import android.preference.PreferenceManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.webkit.CookieManager;
import android.webkit.CookieSyncManager;
import android.webkit.WebSettings;
import android.webkit.WebSettings.PluginState;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import com.nostra13.universalimageloader.core.assist.ImageScaleType;
import com.reicast.emulator.R;
import com.reicast.emulator.config.Config;
import java.util.ArrayList;
import java.util.HashMap;
public class GitAdapter extends BaseAdapter {
private ArrayList<HashMap<String, String>> data;
private LayoutInflater inflater;
private DisplayImageOptions options;
private SharedPreferences mPrefs;
public GitAdapter(Activity activity, ArrayList<HashMap<String, String>> d) {
this.data = d;
this.inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
ImageLoaderConfiguration configicon = new ImageLoaderConfiguration.Builder(
activity).memoryCacheExtraOptions(96, 96).build();
this.options = new DisplayImageOptions.Builder()
.showStubImage(R.drawable.ic_github)
.showImageForEmptyUri(R.drawable.ic_github)
.imageScaleType(ImageScaleType.EXACTLY_STRETCHED).build();
ImageLoader.getInstance().init(configicon);
mPrefs = PreferenceManager.getDefaultSharedPreferences(activity);
}
public int getCount() {
return this.data.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(final int position, View convertView, ViewGroup parent) {
View vi = convertView;
if (convertView == null)
vi = this.inflater.inflate(R.layout.change_item, null);
TextView dateText = (TextView) vi.findViewById(R.id.date);
TextView committerText = (TextView) vi.findViewById(R.id.committer);
TextView titleText = (TextView) vi.findViewById(R.id.title);
ImageView avatarIcon = (ImageView) vi.findViewById(R.id.avatar);
final HashMap<String, String> commit = this.data.get(position);
final String date = commit.get("Date");
final String committer = commit.get("Committer");
final String title = commit.get("Title");
final String message = commit.get("Message");
final String sha = commit.get("Sha");
final String url = commit.get("Url");
final String author = commit.get("Author");
final String avatar = commit.get("Avatar");
final String current = commit.get("Build");
RelativeLayout item = (RelativeLayout) vi.findViewById(R.id.change);
if (current != null && current.equals(sha.substring(0, 7))) {
item.getBackground().setColorFilter(0xFF00FF00,
PorterDuff.Mode.MULTIPLY);
} else {
item.getBackground().setColorFilter(null);
}
dateText.setText(date);
committerText.setText(committer);
titleText.setText(title);
ImageLoader.getInstance().displayImage(avatar, avatarIcon, this.options);
vi.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
System.gc();
String output = title + "\n\n" + message + "\n\n" + " - " + author;
displayCommit(sha, output, url, v.getContext());
}
});
// Handle clicking individual item from list
return vi;
}
private void displayCommit(final String sha, String message, String url,
Context context) {
final AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setCancelable(true);
builder.setTitle(sha.substring(0,7));
builder.setMessage(message);
LayoutInflater infalter = LayoutInflater.from(context);
final View popWebView = infalter.inflate(R.layout.webview, null);
WebView mWebView = (WebView) popWebView.findViewById(R.id.webframe);
mWebView = configureWebview(url, context, mWebView);
builder.setView(popWebView);
builder.setPositiveButton("Close",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
return;
}
});
builder.create().show();
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@SuppressLint("SetJavaScriptEnabled")
@SuppressWarnings("deprecation")
private WebView configureWebview(String url, Context context,
WebView mWebView) {
mWebView.getSettings().setSupportZoom(true);
mWebView.getSettings().setBuiltInZoomControls(true);
mWebView.getSettings().setDisplayZoomControls(false);
mWebView.setInitialScale(1);
mWebView.getSettings().setUseWideViewPort(true);
mWebView.getSettings().setLoadWithOverviewMode(true);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.getSettings().setPluginState(PluginState.ON);
mWebView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
mWebView.clearHistory();
mWebView.clearFormData();
mWebView.clearCache(true);
CookieSyncManager.createInstance(context);
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.removeAllCookie();
CookieSyncManager.getInstance().stopSync();
mWebView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
});
mWebView.loadUrl(url);
return mWebView;
}
}

View File

@ -2,35 +2,21 @@ package com.reicast.emulator.emu;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.graphics.PixelFormat;
import android.opengl.GLSurfaceView;
import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.os.Vibrator;
import android.preference.PreferenceManager;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.InputDevice;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.ScaleGestureDetector.SimpleOnScaleGestureListener;
import android.view.View;
import android.widget.Toast;
import com.android.util.FileUtils;
import com.reicast.emulator.Emulator;
import com.reicast.emulator.GL2JNIActivity;
import com.reicast.emulator.R;
import com.reicast.emulator.config.Config;
import com.reicast.emulator.periph.Gamepad;
import com.reicast.emulator.periph.InputDeviceManager;
import com.reicast.emulator.periph.VJoy;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
@ -189,12 +175,7 @@ public class GL2JNIView extends GLSurfaceView
public void onSurfaceChanged(GL10 gl,int width,int height)
{
gl.glViewport(0, 0, width, height);
// TODO Is this required? The renderer sets the viewport and scissor test correctly
// if (Emulator.widescreen) {
JNIdc.rendinitJava(width, height);
// } else {
// JNIdc.rendinitJava(height * (4 / 3), height);
// }
JNIdc.rendinitJava(width, height);
}
public void onSurfaceCreated(GL10 gl,EGLConfig config)
@ -203,16 +184,10 @@ public class GL2JNIView extends GLSurfaceView
}
}
public void onDestroy() {
/*
// Workaround for ANR when returning to menu
System.exit(0);
try {
ethd.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
*/
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
JNIdc.rendtermJava();
}
@TargetApi(19)

View File

@ -14,12 +14,14 @@ import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import com.reicast.emulator.Emulator;
import com.reicast.emulator.NativeGLActivity;
import com.reicast.emulator.config.Config;
public class NativeGLView extends SurfaceView implements SurfaceHolder.Callback {
private Handler handler = new Handler();
private boolean surfaceReady = false;
private boolean paused = false;
VirtualJoystickDelegate vjoyDelegate;
@ -36,6 +38,9 @@ public class NativeGLView extends SurfaceView implements SurfaceHolder.Callback
super(context, attrs);
getHolder().addCallback(this);
setKeepScreenOn(true);
setFocusable(true);
setFocusableInTouchMode(true);
requestFocus();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
setOnSystemUiVisibilityChangeListener (new OnSystemUiVisibilityChangeListener() {
@ -105,13 +110,21 @@ public class NativeGLView extends SurfaceView implements SurfaceHolder.Callback
@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int format, int w, int h) {
//Log.i("reicast", "NativeGLView.surfaceChanged: " + w + "x" + h);
surfaceReady = true;
JNIdc.rendinitNative(surfaceHolder.getSurface(), w, h);
Emulator.getCurrentActivity().handleStateChange(false);
}
@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
//Log.i("reicast", "NativeGLView.surfaceDestroyed");
surfaceReady = false;
JNIdc.rendinitNative(null, 0, 0);
Emulator.getCurrentActivity().handleStateChange(true);
}
public boolean isSurfaceReady() {
return surfaceReady;
}
public void pause() {
@ -124,6 +137,9 @@ public class NativeGLView extends SurfaceView implements SurfaceHolder.Callback
if (paused) {
//Log.i("reicast", "NativeGLView.resume");
paused = false;
setFocusable(true);
setFocusableInTouchMode(true);
requestFocus();
JNIdc.resume();
}
startRendering();

View File

@ -1,10 +0,0 @@
package com.reicast.emulator.emu;
import android.content.Context;
public class OnScreenMenu {
public static int getPixelsFromDp(float dps, Context context) {
return (int) (dps * context.getResources().getDisplayMetrics().density + 0.5f);
}
}

View File

@ -1,210 +0,0 @@
package com.reicast.emulator.periph;
import android.app.UiModeManager;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.util.SparseArray;
import android.util.SparseIntArray;
import android.view.KeyEvent;
import java.util.HashMap;
import tv.ouya.console.api.OuyaController;
import tv.ouya.console.api.OuyaFacade;
public class Gamepad {
public static final String pref_player1 = "device_descriptor_player_1";
public static final String pref_player2 = "device_descriptor_player_2";
public static final String pref_player3 = "device_descriptor_player_3";
public static final String pref_player4 = "device_descriptor_player_4";
private static final String pref_pad = "controller";
public static final String pref_mic = "mic_plugged_in";
public static final String p2_peripheral = "p2_peripheral";
public static final String p3_peripheral = "p3_peripheral";
public static final String p4_peripheral = "p4_peripheral";
public static final String pref_js_modified = "modified_key_layout";
public static final String pref_js_compat = "controller_compat";
public static final String pref_js_merged = "merged_joystick";
public static final String pref_js_rstick = "right_joystick";
public static final String pref_button_a = "a_button";
public static final String pref_button_b = "b_button";
public static final String pref_button_x = "x_button";
public static final String pref_button_y = "y_button";
public static final String pref_button_l = "l_button";
public static final String pref_button_r = "r_button";
public static final String pref_dpad_up = "dpad_up";
public static final String pref_dpad_down = "dpad_down";
public static final String pref_dpad_left = "dpad_left";
public static final String pref_dpad_right = "dpad_right";
public static final String pref_axis_x = "x_axis";
public static final String pref_axis_y = "y_axis";
public static final String pref_button_start = "start_button";
public static final String pref_button_select = "select_button";
public static final String controllers_sony = "Sony PLAYSTATION(R)3 Controller";
public static final String controllers_xbox = "Microsoft X-Box 360 pad";
public static final String controllers_shield = "NVIDIA Corporation NVIDIA Controller";
public static final String controllers_gamekey = "gamekeyboard";
public static final String controllers_moga = "Moga";
public String[] portId = { "_A", "_B", "_C", "_D" };
public boolean[] compat = { false, false, false, false };
public boolean[] custom = { false, false, false, false };
public boolean[] joystick = { false, false, false, false };
public int[] name = { -1, -1, -1, -1 };
public float[] globalLS_X = new float[4], globalLS_Y = new float[4],
previousLS_X = new float[4], previousLS_Y = new float[4];
public int map[][] = new int[4][];
public SparseArray<String> deviceId_deviceDescriptor = new SparseArray<>();
public HashMap<String, Integer> deviceDescriptor_PlayerNum = new HashMap<>();
public boolean isOuyaOrTV;
private static final int key_CONT_B = 0x0002;
private static final int key_CONT_A = 0x0004;
private static final int key_CONT_START = 0x0008;
private static final int key_CONT_DPAD_UP = 0x0010;
private static final int key_CONT_DPAD_DOWN = 0x0020;
private static final int key_CONT_DPAD_LEFT = 0x0040;
private static final int key_CONT_DPAD_RIGHT = 0x0080;
private static final int key_CONT_Y = 0x0200;
private static final int key_CONT_X = 0x0400;
public int[] getConsoleController() {
return new int[] {
OuyaController.BUTTON_O, key_CONT_A,
OuyaController.BUTTON_A, key_CONT_B,
OuyaController.BUTTON_U, key_CONT_X,
OuyaController.BUTTON_Y, key_CONT_Y,
OuyaController.BUTTON_DPAD_UP, key_CONT_DPAD_UP,
OuyaController.BUTTON_DPAD_DOWN, key_CONT_DPAD_DOWN,
OuyaController.BUTTON_DPAD_LEFT, key_CONT_DPAD_LEFT,
OuyaController.BUTTON_DPAD_RIGHT, key_CONT_DPAD_RIGHT,
getStartButtonCode(), key_CONT_START,
getSelectButtonCode(), getSelectButtonCode()
// Redundant, but verifies it is mapped properly
};
}
public int[] getOUYAController() {
return new int[] {
OuyaController.BUTTON_O, key_CONT_A,
OuyaController.BUTTON_A, key_CONT_B,
OuyaController.BUTTON_U, key_CONT_X,
OuyaController.BUTTON_Y, key_CONT_Y,
OuyaController.BUTTON_DPAD_UP, key_CONT_DPAD_UP,
OuyaController.BUTTON_DPAD_DOWN, key_CONT_DPAD_DOWN,
OuyaController.BUTTON_DPAD_LEFT, key_CONT_DPAD_LEFT,
OuyaController.BUTTON_DPAD_RIGHT, key_CONT_DPAD_RIGHT,
getStartButtonCode(), key_CONT_START,
OuyaController.BUTTON_R3, key_CONT_START
};
}
public int[] getMogaController() {
return new int[] {
KeyEvent.KEYCODE_BUTTON_A, key_CONT_A,
KeyEvent.KEYCODE_BUTTON_B, key_CONT_B,
KeyEvent.KEYCODE_BUTTON_X, key_CONT_X,
KeyEvent.KEYCODE_BUTTON_Y, key_CONT_Y,
KeyEvent.KEYCODE_DPAD_UP, key_CONT_DPAD_UP,
KeyEvent.KEYCODE_DPAD_DOWN, key_CONT_DPAD_DOWN,
KeyEvent.KEYCODE_DPAD_LEFT, key_CONT_DPAD_LEFT,
KeyEvent.KEYCODE_DPAD_RIGHT, key_CONT_DPAD_RIGHT,
getStartButtonCode(), key_CONT_START,
getSelectButtonCode(), getSelectButtonCode()
};
}
private int[] setModifiedKeys(String id, SharedPreferences mPrefs) {
return new int[] {
mPrefs.getInt(pref_button_a + id, OuyaController.BUTTON_O), key_CONT_A,
mPrefs.getInt(pref_button_b + id, OuyaController.BUTTON_A), key_CONT_B,
mPrefs.getInt(pref_button_x + id, OuyaController.BUTTON_U), key_CONT_X,
mPrefs.getInt(pref_button_y + id, OuyaController.BUTTON_Y), key_CONT_Y,
mPrefs.getInt(pref_dpad_up + id, OuyaController.BUTTON_DPAD_UP), key_CONT_DPAD_UP,
mPrefs.getInt(pref_dpad_down + id, OuyaController.BUTTON_DPAD_DOWN), key_CONT_DPAD_DOWN,
mPrefs.getInt(pref_dpad_left + id, OuyaController.BUTTON_DPAD_LEFT), key_CONT_DPAD_LEFT,
mPrefs.getInt(pref_dpad_right + id, OuyaController.BUTTON_DPAD_RIGHT), key_CONT_DPAD_RIGHT,
mPrefs.getInt(pref_button_start + id, getStartButtonCode()), key_CONT_START,
mPrefs.getInt(pref_button_select + id, getSelectButtonCode()), getSelectButtonCode()
};
}
public boolean IsOuyaOrTV(Context context, boolean ouya) {
if (ouya) {
return OuyaFacade.getInstance().isRunningOnOUYAHardware();
} else {
try {
UiModeManager uiModeManager = (UiModeManager)
context.getSystemService(Context.UI_MODE_SERVICE);
if (uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION) {
return true;
}
} catch (Exception e) {
// Not entirely important
}
PackageManager pMan = context.getPackageManager();
return pMan.hasSystemFeature(PackageManager.FEATURE_TELEVISION)
|| OuyaFacade.getInstance().isRunningOnOUYAHardware();
}
}
private int getStartButtonCode() {
return KeyEvent.KEYCODE_BUTTON_START;
}
public int getSelectButtonCode() {
return KeyEvent.KEYCODE_BUTTON_SELECT;
}
public void setCustomMapping(String id, int playerNum, SharedPreferences prefs) {
map[playerNum] = setModifiedKeys(id, prefs);
}
public void initJoyStickLayout(int playerNum) {
if (!joystick[playerNum]) {
globalLS_X[playerNum] = previousLS_X[playerNum] = 0.0f;
globalLS_Y[playerNum] = previousLS_Y[playerNum] = 0.0f;
}
}
public void fullCompatibilityMode(SharedPreferences prefs) {
for (int joy = 0; joy < 4; joy++) {
if (compat[joy]) {
String id = portId[joy];
joystick[joy] = prefs.getBoolean(Gamepad.pref_js_merged + id, false);
getCompatibilityMap(joy, portId[joy], prefs);
initJoyStickLayout(joy);
}
}
}
public void getCompatibilityMap(int playerNum, String id, SharedPreferences prefs) {
name[playerNum] = prefs.getInt(Gamepad.pref_pad + id, -1);
if (name[playerNum] != -1) {
map[playerNum] = setModifiedKeys(id, prefs);
}
}
}

View File

@ -34,8 +34,10 @@ public final class InputDeviceManager implements InputManager.InputDeviceListene
public void stopListening()
{
inputManager.unregisterInputDeviceListener(this);
inputManager = null;
if (inputManager != null) {
inputManager.unregisterInputDeviceListener(this);
inputManager = null;
}
joystickRemoved(VIRTUAL_GAMEPAD_ID);
}

View File

@ -1,51 +0,0 @@
package com.reicast.emulator.periph;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.Log;
import android.view.View;
import com.reicast.emulator.emu.OnScreenMenu;
public class VmuLcd extends View {
public final static int w = 48;
public final static int h = 32;
private int[] image = new int[w*h];
private Bitmap current = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
private float scale;
private Paint paint;
public VmuLcd(Context context) {
super(context);
paint = new Paint();
scale = (float)OnScreenMenu.getPixelsFromDp(60, getContext()) / w;
Log.d("VmuLcd", "scale: "+scale);
}
public void configureScale(int dp) {
scale = (float)OnScreenMenu.getPixelsFromDp(dp, getContext()) / w;
}
public void updateBytes(byte[] data){
for(int i=0; i<h; i++){
for(int j=0; j<w; j++){
image[i*w+j] = data[(h-i-1)*w+j]==0x00?Color.BLACK:Color.WHITE;
}
}
postInvalidate();
}
@Override
public void onDraw(Canvas c) {
current.setPixels(image, 0, w, 0, 0, w, h);
c.scale(scale, scale);
paint.setFilterBitmap(true);
c.drawBitmap(current, 0, 0, paint);
}
}

View File

@ -259,6 +259,7 @@ JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_setExternalStorageDir
env->DeleteLocalRef(dir);
}
setenv("REICAST_HOME", paths.c_str(), 1);
gui_refresh_files();
}
JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_bootdisk(JNIEnv *env,jobject obj, jstring disk) {

View File

@ -67,6 +67,23 @@ public:
}
};
class ShieldRemoteInputMapping : public InputMapping
{
public:
ShieldRemoteInputMapping()
{
name = "Default";
set_button(DC_BTN_A, 23);
set_button(DC_DPAD_UP, 19);
set_button(DC_DPAD_DOWN, 20);
set_button(DC_DPAD_LEFT, 21);
set_button(DC_DPAD_RIGHT, 22);
set_button(EMU_BTN_MENU, 4);
dirty = false;
}
};
class AndroidGamepadDevice : public GamepadDevice
{
public:
@ -89,7 +106,10 @@ public:
}
else if (!find_mapping())
{
input_mapper = new DefaultInputMapping();
if (_name == "SHIELD Remote")
input_mapper = new ShieldRemoteInputMapping();
else
input_mapper = new DefaultInputMapping();
save_mapping();
printf("using default mapping\n");
}

View File

@ -1,27 +1,6 @@
#include <EGL/egl.h>
#include <GLES2/gl2.h>
extern "C" {
#include "deps/libpng/png.h"
}
#include "types.h"
#include "deps/libzip/zip.h"
#define TEXTURE_LOAD_ERROR 0
//Taken from http://en.wikibooks.org/wiki/OpenGL_Programming/Intermediate/Textures
/** loadTexture
* loads a png file into an opengl texture object, using cstdio , libpng, and opengl.
*
* \param filename : the png file to be loaded
* \param width : width of png, to be updated as a side effect of this function
* \param height : height of png, to be updated as a side effect of this function
*
* \return GLuint : an opengl texture id. Will be 0 if there is a major error,
* should be validated by the client of this function.
*
*/
zip_file* file;
zip* APKArchive;
void setAPK (const char* apkPath) {
LOGI("Loading APK %s", apkPath);
@ -42,133 +21,3 @@ void setAPK (const char* apkPath) {
LOGI("File %i : %s\n", i, name);
}
}
void png_zip_read(png_structp png_ptr, png_bytep data, png_size_t length) {
zip_fread(file, data, length);
}
GLuint loadTextureFromPNG(const char* filename, int &width, int &height) {
file = zip_fopen(APKArchive, filename, 0);
if (!file) {
LOGE("Error opening %s from APK", filename);
return TEXTURE_LOAD_ERROR;
}
//header for testing if it is a png
png_byte header[8];
//read the header
zip_fread(file, header, 8);
//test if png
int is_png = !png_sig_cmp(header, 0, 8);
if (!is_png) {
zip_fclose(file);
LOGE("Not a png file : %s", filename);
return TEXTURE_LOAD_ERROR;
}
//create png struct
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr) {
zip_fclose(file);
LOGE("Unable to create png struct : %s", filename);
return (TEXTURE_LOAD_ERROR);
}
//create png info struct
png_infop info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr) {
png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL);
LOGE("Unable to create png info : %s", filename);
zip_fclose(file);
return (TEXTURE_LOAD_ERROR);
}
//create png info struct
png_infop end_info = png_create_info_struct(png_ptr);
if (!end_info) {
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
LOGE("Unable to create png end info : %s", filename);
zip_fclose(file);
return (TEXTURE_LOAD_ERROR);
}
//png error stuff, not sure libpng man suggests this.
if (setjmp(png_jmpbuf(png_ptr))) {
zip_fclose(file);
LOGE("Error during setjmp : %s", filename);
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
return (TEXTURE_LOAD_ERROR);
}
//init png reading
//png_init_io(png_ptr, fp);
png_set_read_fn(png_ptr, NULL, png_zip_read);
//let libpng know you already read the first 8 bytes
png_set_sig_bytes(png_ptr, 8);
// read all the info up to the image data
png_read_info(png_ptr, info_ptr);
//variables to pass to get info
int bit_depth, color_type;
png_uint_32 twidth, theight;
// get info about png
png_get_IHDR(png_ptr, info_ptr, &twidth, &theight, &bit_depth, &color_type, NULL, NULL, NULL);
//update width and height based on png info
width = twidth;
height = theight;
// Update the png info struct.
png_read_update_info(png_ptr, info_ptr);
// Row size in bytes.
int rowbytes = png_get_rowbytes(png_ptr, info_ptr);
// Allocate the image_data as a big block, to be given to opengl
png_byte *image_data = new png_byte[rowbytes * height];
if (!image_data) {
//clean up memory and close stuff
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
LOGE("Unable to allocate image_data while loading %s ", filename);
zip_fclose(file);
return TEXTURE_LOAD_ERROR;
}
//row_pointers is for pointing to image_data for reading the png with libpng
png_bytep *row_pointers = new png_bytep[height];
if (!row_pointers) {
//clean up memory and close stuff
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
delete[] image_data;
LOGE("Unable to allocate row_pointer while loading %s ", filename);
zip_fclose(file);
return TEXTURE_LOAD_ERROR;
}
// set the individual row_pointers to point at the correct offsets of image_data
for (int i = 0; i < height; ++i)
row_pointers[height - 1 - i] = image_data + i * rowbytes;
//read the png into image_data through row_pointers
png_read_image(png_ptr, row_pointers);
//Now generate the OpenGL texture object
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA,
GL_UNSIGNED_BYTE, (GLvoid*) image_data);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
//clean up memory and close stuff
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
delete[] image_data;
delete[] row_pointers;
zip_fclose(file);
return texture;
}

View File

@ -2,7 +2,5 @@
#define UTILS_H_
void setAPK (const char* apkPath);
//Filename will be looked up in the apk (should start with assets/ or res/
GLuint loadTextureFromPNG (const char* filename, int &width, int &height);
#endif /* UTILS_H_ */

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

View File

@ -1,14 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle" android:padding="10dp" >
<solid android:color="#D0000000"/>
</shape>
</item>
<item>
<bitmap
android:gravity="center"
android:src="@drawable/menutile"
android:tileMode="repeat" />
</item>
</layer-list>

View File

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@mipmap/texture_blue"
android:tileMode="repeat" />

View File

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@mipmap/texture_light"
android:tileMode="repeat" />

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Selector style for listrow -->
<item android:drawable="@android:color/transparent" android:state_pressed="false" android:state_selected="false" android:state_focused="false"/>
<item android:drawable="@drawable/gradient_bg_hover_blue" android:state_pressed="true"/>
<item android:drawable="@drawable/gradient_bg_hover_blue" android:state_focused="true"/>
<item android:drawable="@drawable/gradient_bg_hover_blue" android:state_pressed="false" android:state_selected="true"/>
</selector>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Selector style for listrow -->
<item android:drawable="@android:color/transparent" android:state_pressed="false" android:state_selected="false" android:state_focused="false"/>
<item android:drawable="@drawable/gradient_bg_hover_dark" android:state_pressed="true"/>
<item android:drawable="@drawable/gradient_bg_hover_dark" android:state_focused="true"/>
<item android:drawable="@drawable/gradient_bg_hover_dark" android:state_pressed="false" android:state_selected="true"/>
</selector>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Selector style for listrow -->
<item android:drawable="@android:color/transparent" android:state_pressed="false" android:state_selected="false" android:state_focused="false"/>
<item android:drawable="@drawable/gradient_bg_hover_dream" android:state_pressed="true"/>
<item android:drawable="@drawable/gradient_bg_hover_dream" android:state_focused="true"/>
<item android:drawable="@drawable/gradient_bg_hover_dream" android:state_pressed="false" android:state_selected="true"/>
</selector>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

View File

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<!-- Gradient Bg for listrow -->
<gradient
android:angle="270"
android:centerColor="#e7e7e8"
android:endColor="#cfcfcf"
android:startColor="#f1f1f2" />
</shape>

View File

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<!-- Gradient BgColor for listrow Selected -->
<gradient
android:angle="270"
android:centerColor="@color/colorBlueAccentDark"
android:endColor="@color/colorBlueAccent"
android:startColor="@color/colorBlueAccent" />
</shape>

View File

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<!-- Gradient BgColor for listrow Selected -->
<gradient
android:angle="270"
android:centerColor="@color/colorDarkAccentDark"
android:endColor="@color/colorDarkAccent"
android:startColor="@color/colorDarkAccent" />
</shape>

View File

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<!-- Gradient BgColor for listrow Selected -->
<gradient
android:angle="270"
android:centerColor="@color/colorDreamAccentLight"
android:endColor="@color/colorDreamAccent"
android:startColor="@color/colorDreamAccent" />
</shape>

View File

@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M19.35,10.04C18.67,6.59 15.64,4 12,4 9.11,4 6.6,5.64 5.35,8.04 2.34,8.36 0,10.91 0,14c0,3.31 2.69,6 6,6h13c2.76,0 5,-2.24 5,-5 0,-2.64 -2.05,-4.78 -4.65,-4.96zM19,18H6c-2.21,0 -4,-1.79 -4,-4s1.79,-4 4,-4h0.71C7.37,7.69 9.48,6 12,6c3.04,0 5.5,2.46 5.5,5.5v0.5H19c1.66,0 3,1.34 3,3s-1.34,3 -3,3z"/>
</vector>

View File

@ -1,4 +0,0 @@
<vector android:height="40dp" android:viewportHeight="24.0"
android:viewportWidth="24.0" android:width="40dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M10,4H4c-1.1,0 -1.99,0.9 -1.99,2L2,18c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2V8c0,-1.1 -0.9,-2 -2,-2h-8l-2,-2z"/>
</vector>

View File

@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M11,17h2v-6h-2v6zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM11,9h2L13,7h-2v2z"/>
</vector>

View File

@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M21,3.01H3c-1.1,0 -2,0.9 -2,2V9h2V4.99h18v14.03H3V15H1v4.01c0,1.1 0.9,1.98 2,1.98h18c1.1,0 2,-0.88 2,-1.98v-14c0,-1.11 -0.9,-2 -2,-2zM11,16l4,-4 -4,-4v3H1v2h10v3z"/>
</vector>

View File

@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M20,2L4,2c-1.1,0 -1.99,0.9 -1.99,2L2,22l4,-4h14c1.1,0 2,-0.9 2,-2L22,4c0,-1.1 -0.9,-2 -2,-2zM6,14v-2.47l6.88,-6.88c0.2,-0.2 0.51,-0.2 0.71,0l1.77,1.77c0.2,0.2 0.2,0.51 0,0.71L8.47,14L6,14zM18,14h-7.5l2,-2L18,12v2z"/>
</vector>

View File

@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M2.01,21L23,12 2.01,3 2,10l15,2 -15,2z"/>
</vector>

View File

@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M19.43,12.98c0.04,-0.32 0.07,-0.64 0.07,-0.98s-0.03,-0.66 -0.07,-0.98l2.11,-1.65c0.19,-0.15 0.24,-0.42 0.12,-0.64l-2,-3.46c-0.12,-0.22 -0.39,-0.3 -0.61,-0.22l-2.49,1c-0.52,-0.4 -1.08,-0.73 -1.69,-0.98l-0.38,-2.65C14.46,2.18 14.25,2 14,2h-4c-0.25,0 -0.46,0.18 -0.49,0.42l-0.38,2.65c-0.61,0.25 -1.17,0.59 -1.69,0.98l-2.49,-1c-0.23,-0.09 -0.49,0 -0.61,0.22l-2,3.46c-0.13,0.22 -0.07,0.49 0.12,0.64l2.11,1.65c-0.04,0.32 -0.07,0.65 -0.07,0.98s0.03,0.66 0.07,0.98l-2.11,1.65c-0.19,0.15 -0.24,0.42 -0.12,0.64l2,3.46c0.12,0.22 0.39,0.3 0.61,0.22l2.49,-1c0.52,0.4 1.08,0.73 1.69,0.98l0.38,2.65c0.03,0.24 0.24,0.42 0.49,0.42h4c0.25,0 0.46,-0.18 0.49,-0.42l0.38,-2.65c0.61,-0.25 1.17,-0.59 1.69,-0.98l2.49,1c0.23,0.09 0.49,0 0.61,-0.22l2,-3.46c0.12,-0.22 0.07,-0.49 -0.12,-0.64l-2.11,-1.65zM12,15.5c-1.93,0 -3.5,-1.57 -3.5,-3.5s1.57,-3.5 3.5,-3.5 3.5,1.57 3.5,3.5 -1.57,3.5 -3.5,3.5z"/>
</vector>

View File

@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M19,15l-6,6 -1.42,-1.42L15.17,16H4V4h2v10h9.17l-3.59,-3.58L13,9l6,6z"/>
</vector>

View File

@ -1,14 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<shape android:shape="rectangle" >
<stroke
android:width="1dp"
android:color="#dbdbdc" />
<solid android:color="#FFFFFF" />
</shape>
</item>
</layer-list>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<stroke android:width="1dp" android:color="#FFA0A0A0" />
<padding android:left="0dp" android:top="1dp" android:right="0dp"
android:bottom="1dp" />
</shape>

View File

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Selector style for listrow -->
<item android:drawable="@drawable/gradient_bg" android:state_pressed="false" android:state_selected="false"/>
<item android:drawable="@drawable/gradient_bg_hover_blue" android:state_pressed="true"/>
<item android:drawable="@drawable/gradient_bg_hover_blue" android:state_pressed="false" android:state_selected="true"/>
</selector>

View File

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Selector style for listrow -->
<item android:drawable="@drawable/gradient_bg" android:state_pressed="false" android:state_selected="false"/>
<item android:drawable="@drawable/gradient_bg_hover_dark" android:state_pressed="true"/>
<item android:drawable="@drawable/gradient_bg_hover_dark" android:state_pressed="false" android:state_selected="true"/>
</selector>

View File

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Selector style for listrow -->
<item android:drawable="@drawable/gradient_bg" android:state_pressed="false" android:state_selected="false"/>
<item android:drawable="@drawable/gradient_bg_hover_dream" android:state_pressed="true"/>
<item android:drawable="@drawable/gradient_bg_hover_dream" android:state_pressed="false" android:state_selected="true"/>
</selector>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.3 KiB

Some files were not shown because too many files have changed in this diff Show More