6 次代码提交 df08e5f0b8 ... eb8a933639

作者 SHA1 备注 提交日期
  wangyongj eb8a933639 add save state notify broadcast for main apk. 1 年之前
  wangyongj c31d41d121 Merge branch 'master' of ssh://xugame.server.local:/efiles/resp/game-console 1 年之前
  wangyongj 8438f9c1d9 remove png 1 年之前
  wangyongj 33eb145765 add 3588 system sign tool 1 年之前
  ZengGengSen 9f9c979533 feat(state): add save state callback 1 年之前
  wangyongj 540bbcfb42 feat: some activty 1 年之前

二进制
3288_android9_system.jks


二进制
3588_ma_system.jks


+ 7 - 5
app/build.gradle

@@ -14,11 +14,11 @@ android {
 
         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
 
-        externalNativeBuild {
-            cmake {
-                arguments '-DANDROID_STL=c++_shared'
-            }
-        }
+//        externalNativeBuild {
+//            cmake {
+//                arguments '-DANDROID_STL=c++_shared'
+//            }
+//        }
 
         ndk{
             abiFilters  "armeabi-v7a"
@@ -48,11 +48,13 @@ android {
             keyAlias 'system'
             keyPassword 'xugame888'
             storeFile file('../s905_system.jks')
+//            storeFile file('../3588_ma_system.jks')
 //            storeFile file('../android_4.4_haisi_zou_system.jks')//android4.4
 //            storeFile file('../q5_t509_system.jks')
 //            storeFile file('../q5_t509_system.jks')
 //            storeFile file('../3399_systemkey.jks')
 //            storeFile file('../android_10_system.jks')
+//            storeFile file('../3288_android9_system.jks')//android10.1
             storePassword 'xugame888'
         }
         release {

二进制
app/release/app-release.apk


+ 20 - 0
app/release/output-metadata.json

@@ -0,0 +1,20 @@
+{
+  "version": 3,
+  "artifactType": {
+    "type": "APK",
+    "kind": "Directory"
+  },
+  "applicationId": "com.xugame.gameconsole",
+  "variantName": "release",
+  "elements": [
+    {
+      "type": "SINGLE",
+      "filters": [],
+      "attributes": [],
+      "versionCode": 1,
+      "versionName": "1.0",
+      "outputFile": "app-release.apk"
+    }
+  ],
+  "elementType": "File"
+}

+ 9 - 7
app/src/main/AndroidManifest.xml

@@ -3,6 +3,7 @@
     xmlns:tools="http://schemas.android.com/tools"
     package="com.xugame.gameconsole"
     android:installLocation="internalOnly"
+    android:sharedUserId="android.uid.system"
     android:versionCode="1597175257"
     android:versionName="1.15.0">
 
@@ -37,7 +38,7 @@
     <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
 
     <!--    <uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission>-->
-
+    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
 
     <uses-permission android:name="android.permission.RECORD_AUDIO" />
 
@@ -62,15 +63,16 @@
 
             android:launchMode="singleTop">
             <intent-filter>
-<!--                <action android:name="android.intent.action.MAIN" />-->
-<!--                <category android:name="android.intent.category.LAUNCHER" />-->
-<!--                <data-->
-<!--                    android:host="com.xugame.gameconsole.TextCopyFileActivity"-->
-<!--                    android:scheme="com.xugame.gameconsole.TextCopyFileActivity"-->
-<!--                    tools:ignore="AppLinkUrlError" />-->
+                <!--                <action android:name="android.intent.action.MAIN" />-->
+                <!--                <category android:name="android.intent.category.LAUNCHER" />-->
+                <!--                <data-->
+                <!--                    android:host="com.xugame.gameconsole.TextCopyFileActivity"-->
+                <!--                    android:scheme="com.xugame.gameconsole.TextCopyFileActivity"-->
+                <!--                    tools:ignore="AppLinkUrlError" />-->
                 <category android:name="android.intent.category.LAUNCHER" />
 
                 <action android:name="android.intent.action.MAIN" />
+
                 <category android:name="android.intent.category.DEFAULT" />
                 <category android:name="android.intent.category.MONKEY" />
             </intent-filter>

+ 602 - 600
app/src/main/java/com/retroarch/browser/retroactivity/RetroActivityCommon.java

@@ -51,272 +51,265 @@ import java.util.Locale;
  * Class which provides common methods for RetroActivity related classes.
  */
 //public class RetroActivityCommon extends NativeActivity
-public abstract class RetroActivityCommon extends NativeActivity
-{
-  private static final String TAG = "RetroActivityCommonTAG";
-
-  static { System.loadLibrary("retroarch-activity"); }
-
-  public static int FRONTEND_POWERSTATE_NONE = 0;
-  public static int FRONTEND_POWERSTATE_NO_SOURCE = 1;
-  public static int FRONTEND_POWERSTATE_CHARGING = 2;
-  public static int FRONTEND_POWERSTATE_CHARGED = 3;
-  public static int FRONTEND_POWERSTATE_ON_POWER_SOURCE = 4;
-  public static int FRONTEND_ORIENTATION_0 = 0;
-  public static int FRONTEND_ORIENTATION_90 = 1;
-  public static int FRONTEND_ORIENTATION_180 = 2;
-  public static int FRONTEND_ORIENTATION_270 = 3;
-  public static int RETRO_RUMBLE_STRONG = 0;
-  public static int RETRO_RUMBLE_WEAK = 1;
-  public boolean sustainedPerformanceMode = true;
-  public int screenOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
-  protected EnvironmentCallback callback = null;
-
-  public abstract void showExitDialog();
-
-  public void environmentCallback(int cmd, Object data) {
-    if (callback == null) return;
-
-    if (cmd == EnvironmentCallbackCmd.SET_INPUT_DESCRIPTORS) {
-      callback.setInputDescriptors((InputDescriptorBean[]) data);
-    } else if (cmd == EnvironmentCallbackCmd.SET_SYSTEM_AV_INFO) {
-      callback.setSystemAVInfo((SystemAVInfo) data);
-    } else if (cmd == EnvironmentCallbackCmd.SET_GEOMETRY) {
-      callback.setGeometry((SystemAVInfo.GameGeometry) data);
-    }
-  }
-  public void contentLoaded() {
-    if (callback != null)
-      callback.contentLoaded();
-  }
-
-  @Override
-  protected void onCreate(Bundle savedInstanceState) {
-    cleanupSymlinks();
-    updateSymlinks();
-
-    PlayCoreManager.getInstance().onCreate(this);
-    super.onCreate(savedInstanceState);
+public abstract class RetroActivityCommon extends NativeActivity {
+    private static final String TAG = "RetroActivityCommonTAG";
+
+    static {
+        System.loadLibrary("retroarch-activity");
+    }
+
+    public static int FRONTEND_POWERSTATE_NONE = 0;
+    public static int FRONTEND_POWERSTATE_NO_SOURCE = 1;
+    public static int FRONTEND_POWERSTATE_CHARGING = 2;
+    public static int FRONTEND_POWERSTATE_CHARGED = 3;
+    public static int FRONTEND_POWERSTATE_ON_POWER_SOURCE = 4;
+    public static int FRONTEND_ORIENTATION_0 = 0;
+    public static int FRONTEND_ORIENTATION_90 = 1;
+    public static int FRONTEND_ORIENTATION_180 = 2;
+    public static int FRONTEND_ORIENTATION_270 = 3;
+    public static int RETRO_RUMBLE_STRONG = 0;
+    public static int RETRO_RUMBLE_WEAK = 1;
+    public boolean sustainedPerformanceMode = true;
+    public int screenOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+    protected EnvironmentCallback callback = null;
+
+    public abstract void showExitDialog();
+
+    public void environmentCallback(int cmd, Object data) {
+        if (callback == null) return;
+
+        if (cmd == EnvironmentCallbackCmd.SET_INPUT_DESCRIPTORS) {
+            callback.setInputDescriptors((InputDescriptorBean[]) data);
+        } else if (cmd == EnvironmentCallbackCmd.SET_SYSTEM_AV_INFO) {
+            callback.setSystemAVInfo((SystemAVInfo) data);
+        } else if (cmd == EnvironmentCallbackCmd.SET_GEOMETRY) {
+            callback.setGeometry((SystemAVInfo.GameGeometry) data);
+        }
+    }
+
+    public void contentLoaded() {
+        if (callback != null)
+            callback.contentLoaded();
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        cleanupSymlinks();
+        updateSymlinks();
+
+        PlayCoreManager.getInstance().onCreate(this);
+        super.onCreate(savedInstanceState);
 //    startCuntDown();
-  }
-
-  private native void registerBeans();
-  private native void unregisterBeans();
-
-  @Override
-  protected void onStart() {
-    super.onStart();
-
-    registerBeans();
-  }
-
-  @Override
-  protected void onStop() {
-    super.onStop();
-  }
-
-
-  private CountDownTimer mDownTimer;
-  private void startCuntDown(){
-    mDownTimer=new CountDownTimer(4000,1000) {
-      @Override
-      public void onTick(long millisUntilFinished) {
-DebugUtil.i(TAG,"onTick"+millisUntilFinished);
-      }
-
-      @Override
-      public void onFinish() {
-      finish();
-      }
-    };
-    mDownTimer.start();
-  }
-
-  @Override
-  protected void onDestroy() {
-    PlayCoreManager.getInstance().onDestroy();
-    unregisterBeans();
-    super.onDestroy();
-  }
-
-  public void doVibrate(int id, int effect, int strength, int oneShot)
-  {
-    Vibrator vibrator = null;
-    int repeat = 0;
-    long[] pattern = {0, 16};
-    int[] strengths = {0, strength};
-
-    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
-      if (id == -1)
-        vibrator = (Vibrator)getSystemService(Context.VIBRATOR_SERVICE);
-      else
-      {
-        InputDevice dev = InputDevice.getDevice(id);
-
-        if (dev != null)
-          vibrator = dev.getVibrator();
-      }
-    }
-
-    if (vibrator == null)
-      return;
-
-    if (strength == 0) {
-      vibrator.cancel();
-      return;
-    }
-
-    if (oneShot > 0)
-      repeat = -1;
-    else
-      pattern[1] = 1000;
-
-    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
-      if (id >= 0)
-        Log.i("RetroActivity", "Vibrate id " + id + ": strength " + strength);
-
-      vibrator.vibrate(VibrationEffect.createWaveform(pattern, strengths, repeat), new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_GAME).setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION).build());
-    }else{
-      vibrator.vibrate(pattern, repeat);
-    }
-  }
-
-  public void doHapticFeedback(int effect)
-  {
-    getWindow().getDecorView().performHapticFeedback(effect,
-        HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING | HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
-    Log.i("RetroActivity", "Haptic Feedback effect " + effect);
-  }
-
-  // Exiting cleanly from NDK seems to be nearly impossible.
-  // Have to use exit(0) to avoid weird things happening, even with runOnUiThread() approaches.
-  // Use a separate JNI function to explicitly trigger the readback.
-  public void onRetroArchExit()
-  {
-
-      DebugUtil.i(TAG,"onRetroArchExit");
-      finish();
-  }
-
-  public int getVolumeCount()
-  {
-    int ret = 0;
-
-    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
-      StorageManager storageManager = (StorageManager) getApplicationContext().getSystemService(Context.STORAGE_SERVICE);
-      List<StorageVolume> storageVolumeList = storageManager.getStorageVolumes();
-
-      for (int i = 0; i < storageVolumeList.size(); i++) {
-        ret++;
-      }
-      Log.i("RetroActivity", "volume count: " + ret);
-    }
-
-    return (int)ret;
-  }
-
-  public String getVolumePath(String input)
-  {
-    String ret = "";
-
-    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
-      int index = Integer.valueOf(input);
-      int j = 0;
-
-      StorageManager storageManager = (StorageManager) getApplicationContext().getSystemService(Context.STORAGE_SERVICE);
-      List<StorageVolume> storageVolumeList = storageManager.getStorageVolumes();
-
-      for (int i = 0; i < storageVolumeList.size(); i++) {
-        if (i == j) {
-          ret = String.valueOf(storageVolumeList.get(index).getDirectory());
+    }
+
+    private native void registerBeans();
+
+    private native void unregisterBeans();
+
+    @Override
+    protected void onStart() {
+        super.onStart();
+
+        registerBeans();
+    }
+
+    @Override
+    protected void onStop() {
+        super.onStop();
+    }
+
+
+    private CountDownTimer mDownTimer;
+
+    private void startCuntDown() {
+        mDownTimer = new CountDownTimer(4000, 1000) {
+            @Override
+            public void onTick(long millisUntilFinished) {
+                DebugUtil.i(TAG, "onTick" + millisUntilFinished);
+            }
+
+            @Override
+            public void onFinish() {
+                finish();
+            }
+        };
+        mDownTimer.start();
+    }
+
+    @Override
+    protected void onDestroy() {
+        PlayCoreManager.getInstance().onDestroy();
+        unregisterBeans();
+        super.onDestroy();
+    }
+
+    public void doVibrate(int id, int effect, int strength, int oneShot) {
+        Vibrator vibrator = null;
+        int repeat = 0;
+        long[] pattern = {0, 16};
+        int[] strengths = {0, strength};
+
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
+            if (id == -1)
+                vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
+            else {
+                InputDevice dev = InputDevice.getDevice(id);
+
+                if (dev != null)
+                    vibrator = dev.getVibrator();
+            }
         }
-      }
-      Log.i("RetroActivity", "volume path: " + ret);
-    }
-
-    return ret;
-  }
-// https://stackoverflow.com/questions/4553650/how-to-check-device-natural-default-orientation-on-android-i-e-get-landscape/4555528#4555528
-  public int getDeviceDefaultOrientation() {
-    WindowManager windowManager = (WindowManager)getSystemService(Context.WINDOW_SERVICE);
-    Configuration config = getResources().getConfiguration();
-    int rotation = windowManager.getDefaultDisplay().getRotation();
-
-    if (((rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) &&
-        config.orientation == Configuration.ORIENTATION_LANDSCAPE)
-        || ((rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270) &&
-        config.orientation == Configuration.ORIENTATION_PORTRAIT))
-    {
-      return Configuration.ORIENTATION_LANDSCAPE;
-    }else{
-      return Configuration.ORIENTATION_PORTRAIT;
-    }
-  }
-
-  public void setScreenOrientation(int orientation)
-  {
-    int naturalOrientation = getDeviceDefaultOrientation();
-    int newOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
-
-    // We assume no device has a natural orientation that is reversed
-    switch (naturalOrientation) {
-      case Configuration.ORIENTATION_PORTRAIT:
-      {
-        if (orientation == FRONTEND_ORIENTATION_0) {
-          newOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
-        }else if (orientation == FRONTEND_ORIENTATION_90) {
-          newOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
-        }else if (orientation == FRONTEND_ORIENTATION_180) {
-          newOrientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
-        }else if (orientation == FRONTEND_ORIENTATION_270) {
-          newOrientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
+
+        if (vibrator == null)
+            return;
+
+        if (strength == 0) {
+            vibrator.cancel();
+            return;
         }
-        break;
-      }
-      case Configuration.ORIENTATION_LANDSCAPE:
-      {
-        if (orientation == FRONTEND_ORIENTATION_0) {
-          newOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
-        }else if (orientation == FRONTEND_ORIENTATION_90) {
-          newOrientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
-        }else if (orientation == FRONTEND_ORIENTATION_180) {
-          newOrientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
-        }else if (orientation == FRONTEND_ORIENTATION_270) {
-          newOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
+
+        if (oneShot > 0)
+            repeat = -1;
+        else
+            pattern[1] = 1000;
+
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+            if (id >= 0)
+                Log.i("RetroActivity", "Vibrate id " + id + ": strength " + strength);
+
+            vibrator.vibrate(VibrationEffect.createWaveform(pattern, strengths, repeat), new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_GAME).setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION).build());
+        } else {
+            vibrator.vibrate(pattern, repeat);
         }
-        break;
-      }
     }
 
-    screenOrientation = newOrientation;
+    public void doHapticFeedback(int effect) {
+        getWindow().getDecorView().performHapticFeedback(effect,
+                HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING | HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
+        Log.i("RetroActivity", "Haptic Feedback effect " + effect);
+    }
 
-    Log.i("RetroActivity", "setting new orientation to " + screenOrientation);
+    // Exiting cleanly from NDK seems to be nearly impossible.
+    // Have to use exit(0) to avoid weird things happening, even with runOnUiThread() approaches.
+    // Use a separate JNI function to explicitly trigger the readback.
+    public void onRetroArchExit() {
 
-    runOnUiThread(new Runnable() {
-      @Override
-      public void run() {
-        setRequestedOrientation(screenOrientation);
-      }
-    });
-  }
+        DebugUtil.i(TAG, "onRetroArchExit");
+        finish();
+    }
 
-  public String getUserLanguageString()
-  {
-    String lang = Locale.getDefault().getLanguage();
-    String country = Locale.getDefault().getCountry();
+    public int getVolumeCount() {
+        int ret = 0;
 
-    if (lang.length() == 0)
-      return "en";
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+            StorageManager storageManager = (StorageManager) getApplicationContext().getSystemService(Context.STORAGE_SERVICE);
+            List<StorageVolume> storageVolumeList = storageManager.getStorageVolumes();
 
-    if (country.length() == 0)
-      return lang;
+            for (int i = 0; i < storageVolumeList.size(); i++) {
+                ret++;
+            }
+            Log.i("RetroActivity", "volume count: " + ret);
+        }
 
-    return lang + '_' + country;
-  }
+        return (int) ret;
+    }
+
+    public String getVolumePath(String input) {
+        String ret = "";
+
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+            int index = Integer.valueOf(input);
+            int j = 0;
+
+            StorageManager storageManager = (StorageManager) getApplicationContext().getSystemService(Context.STORAGE_SERVICE);
+            List<StorageVolume> storageVolumeList = storageManager.getStorageVolumes();
+
+            for (int i = 0; i < storageVolumeList.size(); i++) {
+                if (i == j) {
+                    ret = String.valueOf(storageVolumeList.get(index).getDirectory());
+                }
+            }
+            Log.i("RetroActivity", "volume path: " + ret);
+        }
+
+        return ret;
+    }
+
+    // https://stackoverflow.com/questions/4553650/how-to-check-device-natural-default-orientation-on-android-i-e-get-landscape/4555528#4555528
+    public int getDeviceDefaultOrientation() {
+        WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
+        Configuration config = getResources().getConfiguration();
+        int rotation = windowManager.getDefaultDisplay().getRotation();
+
+        if (((rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) &&
+                config.orientation == Configuration.ORIENTATION_LANDSCAPE)
+                || ((rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270) &&
+                config.orientation == Configuration.ORIENTATION_PORTRAIT)) {
+            return Configuration.ORIENTATION_LANDSCAPE;
+        } else {
+            return Configuration.ORIENTATION_PORTRAIT;
+        }
+    }
+
+    public void setScreenOrientation(int orientation) {
+        int naturalOrientation = getDeviceDefaultOrientation();
+        int newOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+
+        // We assume no device has a natural orientation that is reversed
+        switch (naturalOrientation) {
+            case Configuration.ORIENTATION_PORTRAIT: {
+                if (orientation == FRONTEND_ORIENTATION_0) {
+                    newOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
+                } else if (orientation == FRONTEND_ORIENTATION_90) {
+                    newOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
+                } else if (orientation == FRONTEND_ORIENTATION_180) {
+                    newOrientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
+                } else if (orientation == FRONTEND_ORIENTATION_270) {
+                    newOrientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
+                }
+                break;
+            }
+            case Configuration.ORIENTATION_LANDSCAPE: {
+                if (orientation == FRONTEND_ORIENTATION_0) {
+                    newOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
+                } else if (orientation == FRONTEND_ORIENTATION_90) {
+                    newOrientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
+                } else if (orientation == FRONTEND_ORIENTATION_180) {
+                    newOrientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
+                } else if (orientation == FRONTEND_ORIENTATION_270) {
+                    newOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
+                }
+                break;
+            }
+        }
+
+        screenOrientation = newOrientation;
+
+        Log.i("RetroActivity", "setting new orientation to " + screenOrientation);
+
+        runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                setRequestedOrientation(screenOrientation);
+            }
+        });
+    }
+
+    public String getUserLanguageString() {
+        String lang = Locale.getDefault().getLanguage();
+        String country = Locale.getDefault().getCountry();
+
+        if (lang.length() == 0)
+            return "en";
+
+        if (country.length() == 0)
+            return lang;
 
-  @TargetApi(24)
-  public void setSustainedPerformanceMode(boolean on)
-  {
+        return lang + '_' + country;
+    }
+
+    @TargetApi(24)
+    public void setSustainedPerformanceMode(boolean on) {
 //    sustainedPerformanceMode = on;
 //
 //    if (Build.VERSION.SDK_INT >= 24) {
@@ -341,363 +334,372 @@ DebugUtil.i(TAG,"onTick"+millisUntilFinished);
 //        }
 //      }
 //    }
-  }
+    }
+
+    @TargetApi(24)
+    public boolean isSustainedPerformanceModeSupported() {
+        boolean supported = false;
+
+        if (Build.VERSION.SDK_INT >= 24) {
+            PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
+
+            if (powerManager.isSustainedPerformanceModeSupported())
+                supported = true;
+        }
+
+        Log.i("RetroActivity", "isSustainedPerformanceModeSupported? " + supported);
+
+        return supported;
+    }
+
+    public int getBatteryLevel() {
+        IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
+        // This doesn't actually register anything (or need to) because we know this particular intent is sticky and we do not specify a BroadcastReceiver anyway
+        Intent batteryStatus = registerReceiver(null, ifilter);
+        int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
+        int scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, 100);
+
+        float percent = ((float) level / (float) scale) * 100.0f;
 
-  @TargetApi(24)
-  public boolean isSustainedPerformanceModeSupported()
-  {
-    boolean supported = false;
+        Log.i("RetroActivity", "battery: level = " + level + ", scale = " + scale + ", percent = " + percent);
 
-    if (Build.VERSION.SDK_INT >= 24)
-    {
-      PowerManager powerManager = (PowerManager)getSystemService(Context.POWER_SERVICE);
+        return (int) percent;
+    }
 
-      if (powerManager.isSustainedPerformanceModeSupported())
-        supported = true;
+    public int getPowerstate() {
+        IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
+        // This doesn't actually register anything (or need to) because we know this particular intent is sticky and we do not specify a BroadcastReceiver anyway
+        Intent batteryStatus = registerReceiver(null, ifilter);
+        int status = batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
+        boolean hasBattery = batteryStatus.getBooleanExtra(BatteryManager.EXTRA_PRESENT, false);
+        boolean isCharging = (status == BatteryManager.BATTERY_STATUS_CHARGING);
+        boolean isCharged = (status == BatteryManager.BATTERY_STATUS_FULL);
+        int powerstate = FRONTEND_POWERSTATE_NONE;
+
+        if (isCharged)
+            powerstate = FRONTEND_POWERSTATE_CHARGED;
+        else if (isCharging)
+            powerstate = FRONTEND_POWERSTATE_CHARGING;
+        else if (!hasBattery)
+            powerstate = FRONTEND_POWERSTATE_NO_SOURCE;
+        else
+            powerstate = FRONTEND_POWERSTATE_ON_POWER_SOURCE;
+
+        Log.i("RetroActivity", "power state = " + powerstate);
+
+        return powerstate;
     }
 
-    Log.i("RetroActivity", "isSustainedPerformanceModeSupported? " + supported);
+    public boolean isAndroidTV() {
+        Configuration config = getResources().getConfiguration();
+        UiModeManager uiModeManager = (UiModeManager) getSystemService(UI_MODE_SERVICE);
 
-    return supported;
-  }
+        if (uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION) {
+            Log.i("RetroActivity", "isAndroidTV == true");
+            return true;
+        } else {
+            Log.i("RetroActivity", "isAndroidTV == false");
+            return false;
+        }
+    }
+
+    //call by jni
+    public void openGameDialog() {
+        DebugUtil.i(TAG, "openGameDialog");
+        showExitDialog();
+    }
 
-  public int getBatteryLevel()
-  {
-    IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
-    // This doesn't actually register anything (or need to) because we know this particular intent is sticky and we do not specify a BroadcastReceiver anyway
-    Intent batteryStatus = registerReceiver(null, ifilter);
-    int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
-    int scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, 100);
-
-    float percent = ((float)level / (float)scale) * 100.0f;
+    @Override
+    public void onConfigurationChanged(Configuration newConfig) {
+        int oldOrientation = 0;
+        boolean hasOldOrientation = false;
 
-    Log.i("RetroActivity", "battery: level = " + level + ", scale = " + scale + ", percent = " + percent);
-
-    return (int)percent;
-  }
-
-  public int getPowerstate()
-  {
-    IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
-    // This doesn't actually register anything (or need to) because we know this particular intent is sticky and we do not specify a BroadcastReceiver anyway
-    Intent batteryStatus = registerReceiver(null, ifilter);
-    int status = batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
-    boolean hasBattery = batteryStatus.getBooleanExtra(BatteryManager.EXTRA_PRESENT, false);
-    boolean isCharging = (status == BatteryManager.BATTERY_STATUS_CHARGING);
-    boolean isCharged = (status == BatteryManager.BATTERY_STATUS_FULL);
-    int powerstate = FRONTEND_POWERSTATE_NONE;
-
-    if (isCharged)
-      powerstate = FRONTEND_POWERSTATE_CHARGED;
-    else if (isCharging)
-      powerstate = FRONTEND_POWERSTATE_CHARGING;
-    else if (!hasBattery)
-      powerstate = FRONTEND_POWERSTATE_NO_SOURCE;
-    else
-      powerstate = FRONTEND_POWERSTATE_ON_POWER_SOURCE;
-
-    Log.i("RetroActivity", "power state = " + powerstate);
-
-    return powerstate;
-  }
-
-  public boolean isAndroidTV()
-  {
-    Configuration config = getResources().getConfiguration();
-    UiModeManager uiModeManager = (UiModeManager)getSystemService(UI_MODE_SERVICE);
-
-    if (uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION)
-    {
-      Log.i("RetroActivity", "isAndroidTV == true");
-      return true;
-    }
-    else
-    {
-      Log.i("RetroActivity", "isAndroidTV == false");
-      return false;
-    }
-  }
-
-  //call by jni
-  public void openGameDialog() {
-    DebugUtil.i(TAG,"openGameDialog");
-    showExitDialog();
-  }
-
-  @Override
-  public void onConfigurationChanged(Configuration newConfig) {
-    int oldOrientation = 0;
-    boolean hasOldOrientation = false;
-
-    super.onConfigurationChanged(newConfig);
-
-    Log.i("RetroActivity", "onConfigurationChanged: orientation is now " + newConfig.orientation);
-
-    SharedPreferences prefs = UserPreferences.getPreferences(this);
-    SharedPreferences.Editor edit = prefs.edit();
-
-    hasOldOrientation = prefs.contains("ORIENTATION");
-
-    if (hasOldOrientation)
-      oldOrientation = prefs.getInt("ORIENTATION", 0);
-
-    edit.putInt("ORIENTATION", newConfig.orientation);
-    edit.apply();
-
-    Log.i("RetroActivity", "hasOldOrientation? " + hasOldOrientation + " newOrientation: " + newConfig.orientation + " oldOrientation: " + oldOrientation);
-  }
-
-  /**
-   * Checks if this version of RetroArch is a Play Store build.
-   *
-   * @return true if this is a Play Store build, false otherwise
-   */
-  public boolean isPlayStoreBuild() {
-    Log.i("RetroActivity", "isPlayStoreBuild: " + BuildConfig.PLAY_STORE_BUILD);
-
-    return BuildConfig.PLAY_STORE_BUILD;
-  }
-
-  /**
-   * Gets the list of available cores that can be downloaded as Dynamic Feature Modules.
-   *
-   * @return the list of available cores
-   */
-  public String[] getAvailableCores() {
-    int id = getResources().getIdentifier("module_names_" + Build.CPU_ABI.replace('-', '_'), "array", getPackageName());
-
-    String[] returnVal = getResources().getStringArray(id);
-    Log.i("RetroActivity", "getAvailableCores: " + Arrays.toString(returnVal));
-    return returnVal;
-  }
-
-  /**
-   * Gets the list of cores that are currently installed as Dynamic Feature Modules.
-   *
-   * @return the list of installed cores
-   */
-  public String[] getInstalledCores() {
-    String[] modules = PlayCoreManager.getInstance().getInstalledModules();
-    List<String> cores = new ArrayList<>();
-    List<String> availableCores = Arrays.asList(getAvailableCores());
-
-    SharedPreferences prefs = UserPreferences.getPreferences(this);
-
-    for(int i = 0; i < modules.length; i++) {
-      String coreName = unsanitizeCoreName(modules[i]);
-      if(!prefs.getBoolean("core_deleted_" + coreName, false)
-              && availableCores.contains(coreName)) {
-        cores.add(coreName);
-      }
-    }
-
-    String[] returnVal = cores.toArray(new String[0]);
-    Log.i("RetroActivity", "getInstalledCores: " + Arrays.toString(returnVal));
-    return returnVal;
-  }
-
-  /**
-   * Asks the system to download a core.
-   *
-   * @param coreName Name of the core to install
-   */
-  public void downloadCore(final String coreName) {
-    Log.i("RetroActivity", "downloadCore: " + coreName);
-
-    SharedPreferences prefs = UserPreferences.getPreferences(this);
-    prefs.edit().remove("core_deleted_" + coreName).apply();
-
-    PlayCoreManager.getInstance().downloadCore(coreName);
-  }
-
-  /**
-   * Asks the system to delete a core.
-   *
-   * Note that the actual module deletion will not happen immediately (the OS will delete
-   * it whenever it feels like it), but the symlink will still be immediately removed.
-   *
-   * @param coreName Name of the core to delete
-   */
-  public void deleteCore(String coreName) {
-    Log.i("RetroActivity", "deleteCore: " + coreName);
-
-    String newFilename = getCorePath() + coreName + "_libretro_android.so";
-    new File(newFilename).delete();
-
-    SharedPreferences prefs = UserPreferences.getPreferences(this);
-    prefs.edit().putBoolean("core_deleted_" + coreName, true).apply();
-
-    PlayCoreManager.getInstance().deleteCore(coreName);
-  }
-
-  /////////////// JNI methods ///////////////
-  /**
-   * 点击返回时,退出库
-   */
-  public native void exitLocalGame();
-
-  /**
-   * 保存状态
-   * @param stateIndex 状态索引
-   * @return 成功返回true,失败返回false
-   */
-  public native boolean saveState(int stateIndex);
-
-  /**
-   * 加载状态
-   * @param stateIndex 状态索引
-   * @return 成功返回true,失败返回false
-   */
-  public native boolean loadState(int stateIndex);
-
-  /**
-   * 设置分辨率
-   */
-  public native void setAspectRatio(int aspectRatioIndex);
-
-  /**
-   * 设置分辨率自定义时,的位置和大小
-   */
-  public native void setCustomX(int x);
-  public native void setCustomY(int y);
-  public native void setCustomWidth(int width);
-  public native void setCustomHeight(int height);
-  public native void setCustomViewPort(int x, int y, int width, int height);
-
-  /**
-   * 切换渲染路径
-   */
-  public native void switchFilter(String path);
-
-  /**
-   * 切换渲染路径
-   */
-  public native void setInputKeys(int port, int keyBindId, int key);
-
-  /**
-   * 保存配置
-   */
-  public native void saveOverrideConfig();
-
-  public native void gameDialogClosed();
-
-  public native void setJoystickBindNative(int port, int[] joyKeys, int[] joyAxiss);
-
-  /////////////// Private methods ///////////////
-  /**
-   * Sanitizes a core name so that it can be used when dealing with
-   * Dynamic Feature Modules. Needed because Gradle modules cannot use
-   * dashes, but we have at least one core name ("mesen-s") that uses them.
-   *
-   * @param coreName Name of the core to sanitize.
-   * @return The sanitized core name.
-   */
-  public String sanitizeCoreName(String coreName) {
-    return "core_" + coreName.replace('-', '_');
-  }
-
-  /**
-   * Unsanitizes a core name from its module name.
-   *
-   * @param coreName Name of the core to unsanitize.
-   * @return The unsanitized core name.
-   */
-  public String unsanitizeCoreName(String coreName) {
-    if(coreName.equals("core_mesen_s")) {
-      return "mesen-s";
-    }
-
-    return coreName.substring(5);
-  }
-
-  /**
-   * Gets the path to the RetroArch cores directory.
-   *
-   * @return The path to the RetroArch cores directory
-   */
-  private String getCorePath() {
-    String path = getApplicationInfo().dataDir + "/cores/";
-    new File(path).mkdirs();
-
-    return path;
-  }
-
-  /**
-   * Cleans up existing symlinks before new ones are created.
-   */
-  private void cleanupSymlinks() {
-    if(Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return;
-
-    File[] files = new File(getCorePath()).listFiles();
-    for(int i = 0; i < files.length; i++) {
-      try {
-        Os.readlink(files[i].getAbsolutePath());
-        files[i].delete();
-      } catch (Exception e) {
-        // File is not a symlink, so don't delete.
-      }
-    }
-  }
-
-  /**
-   * Triggers a symlink update in the known places that Dynamic Feature Modules
-   * are installed to.
-   */
-  public void updateSymlinks() {
-    if(!isPlayStoreBuild()) return;
-
-    traverseFilesystem(getFilesDir());
-    traverseFilesystem(new File(getApplicationInfo().nativeLibraryDir));
-  }
-
-  /**
-   * Traverse the filesystem, looking for native libraries.
-   * Symlinks any libraries it finds to the main RetroArch "cores" folder,
-   * updating any existing symlinks with the correct path to the native libraries.
-   *
-   * This is necessary because Dynamic Feature Modules are first downloaded
-   * and installed to a temporary location on disk, before being moved
-   * to a more permanent location by the system at a later point.
-   *
-   * This could probably be done in native code instead, if that's preferred.
-   *
-   * @param file The parent directory of the tree to traverse.
-   */
-  private void traverseFilesystem(File file) {
-    if(Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return;
-
-    File[] list = file.listFiles();
-    if(list == null) return;
-
-    List<String> availableCores = Arrays.asList(getAvailableCores());
-
-    // Check each file in a directory to see if it's a native library.
-    for(int i = 0; i < list.length; i++) {
-      File child = list[i];
-      String name = child.getName();
-
-      if(name.startsWith("lib") && name.endsWith(".so") && !name.contains("retroarch-activity")) {
-        // Found a native library!
-        String core = name.subSequence(3, name.length() - 3).toString();
-        String filename = child.getAbsolutePath();
+        super.onConfigurationChanged(newConfig);
+
+        Log.i("RetroActivity", "onConfigurationChanged: orientation is now " + newConfig.orientation);
 
         SharedPreferences prefs = UserPreferences.getPreferences(this);
-        if(!prefs.getBoolean("core_deleted_" + core, false)
-                && availableCores.contains(core)) {
-          // Generate the destination filename and delete any existing symlinks / cores
-          String newFilename = getCorePath() + core + "_libretro_android.so";
-          new File(newFilename).delete();
-
-          try {
-            Os.symlink(filename, newFilename);
-          } catch (Exception e) {
-            // Symlink failed to be created. Should never happen.
-          }
+        SharedPreferences.Editor edit = prefs.edit();
+
+        hasOldOrientation = prefs.contains("ORIENTATION");
+
+        if (hasOldOrientation)
+            oldOrientation = prefs.getInt("ORIENTATION", 0);
+
+        edit.putInt("ORIENTATION", newConfig.orientation);
+        edit.apply();
+
+        Log.i("RetroActivity", "hasOldOrientation? " + hasOldOrientation + " newOrientation: " + newConfig.orientation + " oldOrientation: " + oldOrientation);
+    }
+
+    /**
+     * Checks if this version of RetroArch is a Play Store build.
+     *
+     * @return true if this is a Play Store build, false otherwise
+     */
+    public boolean isPlayStoreBuild() {
+        Log.i("RetroActivity", "isPlayStoreBuild: " + BuildConfig.PLAY_STORE_BUILD);
+
+        return BuildConfig.PLAY_STORE_BUILD;
+    }
+
+    /**
+     * Gets the list of available cores that can be downloaded as Dynamic Feature Modules.
+     *
+     * @return the list of available cores
+     */
+    public String[] getAvailableCores() {
+        int id = getResources().getIdentifier("module_names_" + Build.CPU_ABI.replace('-', '_'), "array", getPackageName());
+
+        String[] returnVal = getResources().getStringArray(id);
+        Log.i("RetroActivity", "getAvailableCores: " + Arrays.toString(returnVal));
+        return returnVal;
+    }
+
+    /**
+     * Gets the list of cores that are currently installed as Dynamic Feature Modules.
+     *
+     * @return the list of installed cores
+     */
+    public String[] getInstalledCores() {
+        String[] modules = PlayCoreManager.getInstance().getInstalledModules();
+        List<String> cores = new ArrayList<>();
+        List<String> availableCores = Arrays.asList(getAvailableCores());
+
+        SharedPreferences prefs = UserPreferences.getPreferences(this);
+
+        for (int i = 0; i < modules.length; i++) {
+            String coreName = unsanitizeCoreName(modules[i]);
+            if (!prefs.getBoolean("core_deleted_" + coreName, false)
+                    && availableCores.contains(coreName)) {
+                cores.add(coreName);
+            }
+        }
+
+        String[] returnVal = cores.toArray(new String[0]);
+        Log.i("RetroActivity", "getInstalledCores: " + Arrays.toString(returnVal));
+        return returnVal;
+    }
+
+    /**
+     * Asks the system to download a core.
+     *
+     * @param coreName Name of the core to install
+     */
+    public void downloadCore(final String coreName) {
+        Log.i("RetroActivity", "downloadCore: " + coreName);
+
+        SharedPreferences prefs = UserPreferences.getPreferences(this);
+        prefs.edit().remove("core_deleted_" + coreName).apply();
+
+        PlayCoreManager.getInstance().downloadCore(coreName);
+    }
+
+    /**
+     * Asks the system to delete a core.
+     * <p>
+     * Note that the actual module deletion will not happen immediately (the OS will delete
+     * it whenever it feels like it), but the symlink will still be immediately removed.
+     *
+     * @param coreName Name of the core to delete
+     */
+    public void deleteCore(String coreName) {
+        Log.i("RetroActivity", "deleteCore: " + coreName);
+
+        String newFilename = getCorePath() + coreName + "_libretro_android.so";
+        new File(newFilename).delete();
+
+        SharedPreferences prefs = UserPreferences.getPreferences(this);
+        prefs.edit().putBoolean("core_deleted_" + coreName, true).apply();
+
+        PlayCoreManager.getInstance().deleteCore(coreName);
+    }
+
+    /////////////// JNI methods ///////////////
+
+    /**
+     * 点击返回时,退出库
+     */
+    public native void exitLocalGame();
+
+    /**
+     * 保存状态
+     *
+     * @param stateIndex 状态索引
+     * @return 成功返回true,失败返回false
+     */
+    public native boolean saveState(int stateIndex);
+
+    /**
+     * 保存状态
+     *
+     * @param error 是否出错了
+     */
+    public void saveStateCallback(int error) {
+        this.callback.saveStateCallback(error);
+    }
+
+    /**
+     * 加载状态
+     *
+     * @param stateIndex 状态索引
+     * @return 成功返回true,失败返回false
+     */
+    public native boolean loadState(int stateIndex);
+
+    /**
+     * 设置分辨率
+     */
+    public native void setAspectRatio(int aspectRatioIndex);
+
+    /**
+     * 设置分辨率自定义时,的位置和大小
+     */
+    public native void setCustomX(int x);
+
+    public native void setCustomY(int y);
+
+    public native void setCustomWidth(int width);
+
+    public native void setCustomHeight(int height);
+
+    public native void setCustomViewPort(int x, int y, int width, int height);
+
+    /**
+     * 切换渲染路径
+     */
+    public native void switchFilter(String path);
+
+    /**
+     * 切换渲染路径
+     */
+    public native void setInputKeys(int port, int keyBindId, int key);
+
+    /**
+     * 保存配置
+     */
+    public native void saveOverrideConfig();
+
+    public native void gameDialogClosed();
+
+    public native void setJoystickBindNative(int port, int[] joyKeys, int[] joyAxiss);
+
+    /////////////// Private methods ///////////////
+
+    /**
+     * Sanitizes a core name so that it can be used when dealing with
+     * Dynamic Feature Modules. Needed because Gradle modules cannot use
+     * dashes, but we have at least one core name ("mesen-s") that uses them.
+     *
+     * @param coreName Name of the core to sanitize.
+     * @return The sanitized core name.
+     */
+    public String sanitizeCoreName(String coreName) {
+        return "core_" + coreName.replace('-', '_');
+    }
+
+    /**
+     * Unsanitizes a core name from its module name.
+     *
+     * @param coreName Name of the core to unsanitize.
+     * @return The unsanitized core name.
+     */
+    public String unsanitizeCoreName(String coreName) {
+        if (coreName.equals("core_mesen_s")) {
+            return "mesen-s";
+        }
+
+        return coreName.substring(5);
+    }
+
+    /**
+     * Gets the path to the RetroArch cores directory.
+     *
+     * @return The path to the RetroArch cores directory
+     */
+    private String getCorePath() {
+        String path = getApplicationInfo().dataDir + "/cores/";
+        new File(path).mkdirs();
+
+        return path;
+    }
+
+    /**
+     * Cleans up existing symlinks before new ones are created.
+     */
+    private void cleanupSymlinks() {
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return;
+
+        File[] files = new File(getCorePath()).listFiles();
+        for (int i = 0; i < files.length; i++) {
+            try {
+                Os.readlink(files[i].getAbsolutePath());
+                files[i].delete();
+            } catch (Exception e) {
+                // File is not a symlink, so don't delete.
+            }
+        }
+    }
+
+    /**
+     * Triggers a symlink update in the known places that Dynamic Feature Modules
+     * are installed to.
+     */
+    public void updateSymlinks() {
+        if (!isPlayStoreBuild()) return;
+
+        traverseFilesystem(getFilesDir());
+        traverseFilesystem(new File(getApplicationInfo().nativeLibraryDir));
+    }
+
+    /**
+     * Traverse the filesystem, looking for native libraries.
+     * Symlinks any libraries it finds to the main RetroArch "cores" folder,
+     * updating any existing symlinks with the correct path to the native libraries.
+     * <p>
+     * This is necessary because Dynamic Feature Modules are first downloaded
+     * and installed to a temporary location on disk, before being moved
+     * to a more permanent location by the system at a later point.
+     * <p>
+     * This could probably be done in native code instead, if that's preferred.
+     *
+     * @param file The parent directory of the tree to traverse.
+     */
+    private void traverseFilesystem(File file) {
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return;
+
+        File[] list = file.listFiles();
+        if (list == null) return;
+
+        List<String> availableCores = Arrays.asList(getAvailableCores());
+
+        // Check each file in a directory to see if it's a native library.
+        for (int i = 0; i < list.length; i++) {
+            File child = list[i];
+            String name = child.getName();
+
+            if (name.startsWith("lib") && name.endsWith(".so") && !name.contains("retroarch-activity")) {
+                // Found a native library!
+                String core = name.subSequence(3, name.length() - 3).toString();
+                String filename = child.getAbsolutePath();
+
+                SharedPreferences prefs = UserPreferences.getPreferences(this);
+                if (!prefs.getBoolean("core_deleted_" + core, false)
+                        && availableCores.contains(core)) {
+                    // Generate the destination filename and delete any existing symlinks / cores
+                    String newFilename = getCorePath() + core + "_libretro_android.so";
+                    new File(newFilename).delete();
+
+                    try {
+                        Os.symlink(filename, newFilename);
+                    } catch (Exception e) {
+                        // Symlink failed to be created. Should never happen.
+                    }
+                }
+            } else if (file.isDirectory()) {
+                // Found another directory, so traverse it
+                traverseFilesystem(child);
+            }
         }
-      } else if(file.isDirectory()) {
-        // Found another directory, so traverse it
-        traverseFilesystem(child);
-      }
     }
-  }
 }

+ 2 - 0
app/src/main/java/com/xugame/BuildConfig.java

@@ -9,4 +9,6 @@ public class BuildConfig {
     public static final String VERSION_NAME = "1.15.0_GIT";
     // Field from product flavor: aarch64
     public static final boolean PLAY_STORE_BUILD = false;
+
+    public static int FIRST_DEVICE_ID=-1;
 }

+ 1 - 0
app/src/main/java/com/xugame/app/EnvironmentCallback.java

@@ -9,4 +9,5 @@ public interface EnvironmentCallback {
     void setGeometry(SystemAVInfo.GameGeometry geometry);
 
     void contentLoaded();
+    void saveStateCallback(int error);
 }

+ 29 - 5
app/src/main/java/com/xugame/app/JoypadManager.java

@@ -3,6 +3,7 @@ package com.xugame.app;
 import android.view.InputDevice;
 import android.view.MotionEvent;
 
+import com.xugame.BuildConfig;
 import com.xugame.gameconsole.util.DebugUtil;
 
 import java.util.ArrayList;
@@ -10,6 +11,7 @@ import java.util.HashSet;
 
 public class JoypadManager {
     protected static JoypadHandler mJoystickHandler = null;
+
     public static void initialize() {
         if (mJoystickHandler == null) {
             mJoystickHandler = new JoypadHandler_API();
@@ -34,9 +36,12 @@ public class JoypadManager {
         if ((device == null) || (deviceId < 0)) {
             return false;
         }
-        if(device.getName().equals("sunxi-gpadc"))
+        if (device.getName().equals("sunxi-gpadc"))
+            return true;
+        if (device.getName().equals("robot"))
             return true;
-        if(device.getName().equals("robot"))
+
+        if (device.getName().equals("P4"))
             return true;
 
         if (device.isVirtual()) {
@@ -58,11 +63,11 @@ public class JoypadManager {
         }
         */
         InputDevice.MotionRange range = device.getMotionRange(MotionEvent.AXIS_HAT_X);
-        if(range == null)
+        if (range == null)
             return false;
 
         range = device.getMotionRange(MotionEvent.AXIS_HAT_Y);
-        if(range == null)
+        if (range == null)
             return false;
 
         return ((sources & InputDevice.SOURCE_CLASS_JOYSTICK) != 0 ||
@@ -72,6 +77,7 @@ public class JoypadManager {
     }
 
     public static native void addJoystickNative(int deviceId, int deviceSource);
+
     public static native void removeJoystickNative(int deviceId);
 }
 
@@ -97,11 +103,29 @@ class JoypadHandler_API extends JoypadHandler {
     public void pollInputDevices() {
         int[] deviceIds = InputDevice.getDeviceIds();
 
+        //20231205--如果指定1p首先增加
+        if (BuildConfig.FIRST_DEVICE_ID >= 0) {
+            int tempID = BuildConfig.FIRST_DEVICE_ID;
+            for (int dID : deviceIds) {
+                if (mJoypadIds != null && !mJoypadIds.contains(dID)) {
+                    if (tempID == dID) {
+                        InputDevice joypadDevice = InputDevice.getDevice(dID);
+                        mJoypadIds.add(dID);
+                        JoypadManager.addJoystickNative(
+                                dID,
+                                joypadDevice.getSources()
+                        );
+                        break;
+                    }
+                }
+            }
+        }
+
         for (int deviceId : deviceIds) {
 //            DebugUtil.i("JOYPAD:",""+InputDevice.getDevice(deviceId).toString());
             if (!mJoypadIds.contains(deviceId)) {
                 if (JoypadManager.isDeviceJoystick(deviceId)) {
-//                    DebugUtil.i("JOYPAD has:",""+InputDevice.getDevice(deviceId).toString());
+                    DebugUtil.i("JOYPAD has:", "" + InputDevice.getDevice(deviceId).toString());
 
                     InputDevice joypadDevice = InputDevice.getDevice(deviceId);
                     mJoypadIds.add(deviceId);

+ 259 - 11
app/src/main/java/com/xugame/gameconsole/MainActivity.java

@@ -22,8 +22,12 @@ import android.widget.Button;
 import android.widget.EditText;
 import android.widget.Toast;
 
+import com.xugame.BuildConfig;
+import com.xugame.gameconsole.dialog.LoadingDialog;
 import com.xugame.gameconsole.emulator.RetroArchEmulatorActivity;
 import com.xugame.gameconsole.preferences.UserPreferences;
+import com.xugame.gameconsole.util.CheckFileCRC;
+import com.xugame.gameconsole.util.CheckFileCRCListener;
 import com.xugame.gameconsole.util.DebugUtil;
 import com.xugame.gameconsole.util.Util;
 
@@ -37,13 +41,18 @@ import java.lang.reflect.Field;
 import java.util.ArrayList;
 import java.util.List;
 
-public class MainActivity extends PreferenceActivity implements View.OnClickListener {
+public class MainActivity extends PreferenceActivity implements View.OnClickListener,
+        CheckFileCRCListener {
+    private static final String TAG = "MainActivityTAG";
     private EditText mETRom, mETLib, mETConfig;
     private Button mBtnLocalGame, mBtnNetP1, mBtnNetP2;
 
     final private int REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS = 124;
     public static String PACKAGE_NAME;
     boolean checkPermissions = false;
+    private LoadingDialog mLoadingDialog;
+    private CheckFileCRC mCheckFileCRC;
+    private int retryCOUNT = 0;
 
     public void showMessageOKCancel(String message, DialogInterface.OnClickListener onClickListener) {
         new AlertDialog.Builder(this).setMessage(message)
@@ -61,7 +70,6 @@ public class MainActivity extends PreferenceActivity implements View.OnClickList
                     return false;
             }
         }
-
         return true;
     }
 
@@ -191,6 +199,9 @@ public class MainActivity extends PreferenceActivity implements View.OnClickList
         corePath = getIntent().getStringExtra("corePath");
         coreName = getIntent().getStringExtra("coreName");
         screenMode = getIntent().getIntExtra("screenMode", 0);
+        BuildConfig.FIRST_DEVICE_ID = getIntent().getIntExtra("first_device_id", -1);
+        DebugUtil.i(TAG,"DEFAULT_DEVICE"+BuildConfig.FIRST_DEVICE_ID);
+        mLoadingDialog = new LoadingDialog(this);
         checkCores();
 //        checkRobot();
     }
@@ -222,20 +233,43 @@ public class MainActivity extends PreferenceActivity implements View.OnClickList
     }
 
     private void checkCores() {
+        if (mLoadingDialog != null)
+            mLoadingDialog.show();
         if (TextUtils.isEmpty(corePath)) {
             finish();
         }
         File file = new File(corePath);
         if (file.exists()) {
-            start();
+            DebugUtil.i(TAG, "core is exists,to check" + coreName);
+            if (coreName.equals("fbalpha2012_libretro_android.so")) {
+                //不校验
+                DebugUtil.i(TAG, "不校验" + coreName);
+                file.delete();
+                startCopy(coreName, corePath);
+            } else
+                toCheckCrc(file.getAbsolutePath());
+//            start();
         } else {
+            DebugUtil.i(TAG, "core not exists,to copy");
             startCopy(coreName, corePath);
         }
     }
 
+    private void toCheckCrc(String path) {
+        mCheckFileCRC = new CheckFileCRC(this, this);
+        mCheckFileCRC.check(path);
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        if (mLoadingDialog != null && mLoadingDialog.isShowing())
+            mLoadingDialog.dismiss();
+    }
 
     private void startCopy(final String fileName, final String toPath) {
         File file = new File(this.getFilesDir().getParent() + File.separator + "cores");
+        DebugUtil.i(TAG, "core path=" + file.getAbsolutePath());
         if (!file.exists())
             file.mkdirs();
         new AsyncTask<String, Integer, String>() {
@@ -247,7 +281,13 @@ public class MainActivity extends PreferenceActivity implements View.OnClickList
 
             @Override
             protected void onPostExecute(String s) {
-                start();
+//                start();
+                if (coreName.equals("fbalpha2012_libretro_android.so")) {
+                    //不校验
+                    start();
+                } else
+                    toCheckCrc(corePath);
+
                 super.onPostExecute(s);
             }
         }.execute("");
@@ -255,15 +295,21 @@ public class MainActivity extends PreferenceActivity implements View.OnClickList
 
 
     private boolean copyFile(String file_path, String fileName) {
-        File baseFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/arcade/cores/");
-        if (!baseFile.exists())//创建/arcade/cores文件夹
-            baseFile.mkdirs();
+//        File baseFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/arcade/cores/");
+//        if (!baseFile.exists())//创建/arcade/cores文件夹
+//            baseFile.mkdirs();
+//        File file;
+//        if (!TextUtils.isEmpty(baseUsbPath)) {
+//            file = new File(baseUsbPath + "/cores/" + fileName);
+//        } else
+//            file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/arcade/cores/" + fileName);
+//20231207修改cores默认路径为本机存储/cores
+
+
         File file;
-        if (!TextUtils.isEmpty(baseUsbPath)) {
-            file = new File(baseUsbPath + "/cores/" + fileName);
-        } else
-            file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/arcade/cores/" + fileName);
+            file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/cores/" + fileName);
 
+        DebugUtil.i(TAG, "从" + file.getAbsolutePath() + "复制");
         if (!file.exists())//检测cores文件夹下是否存在.so
             return false;
         DebugUtil.i("COPY:", file.getAbsolutePath());
@@ -286,6 +332,7 @@ public class MainActivity extends PreferenceActivity implements View.OnClickList
             return true;
 
         } catch (IOException e) {
+            DebugUtil.i(TAG, "IOException");
             e.printStackTrace();
         }
 
@@ -299,6 +346,8 @@ public class MainActivity extends PreferenceActivity implements View.OnClickList
         UserPreferences.updateConfigFile(this, baseUsbPath + File.separator + "/system");
 
         checkRuntimePermissions();
+        if (mLoadingDialog != null && mLoadingDialog.isShowing())
+            mLoadingDialog.dismiss();
     }
 
     private void findView() {
@@ -341,4 +390,203 @@ public class MainActivity extends PreferenceActivity implements View.OnClickList
         }
 
     }
+
+    @Override
+    public void onCheckCoresCRCDone(String crc, String defaultCRC) {
+        DebugUtil.i(TAG, "onCheckCoresCRCDone" + crc + "-" + defaultCRC);
+        if (crc.equals(defaultCRC)) {
+            start();
+        } else {
+            onCheckCoresCRCError(-3);
+        }
+    }
+
+    @Override
+    public void onCheckCoresCRCError(int error) {
+        DebugUtil.i(TAG, "onCheckCoresCRCError" + error);
+        if (retryCOUNT < 3) {
+            retryCOUNT++;
+            startCopy(coreName, corePath);
+        } else {
+            retryCOUNT = 0;
+            Toast.makeText(this, "cores is error", Toast.LENGTH_SHORT).show();
+            finish();
+        }
+    }
+
+//    2023-11-01 11:07:45.634 7083-7083/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: passPermissons
+//2023-11-01 11:07:45.636 7083-7083/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: aaaaaaaaaa
+//2023-11-01 11:07:45.719 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: 2048_libretro_android.so==1042003817
+//            2023-11-01 11:07:45.771 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: 3dengine_libretro_android.so==1535549497
+//            2023-11-01 11:07:45.796 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: 81_libretro_android.so==3797825066
+//            2023-11-01 11:07:45.808 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: a5200_libretro_android.so==3869894026
+//            2023-11-01 11:07:45.841 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: arduous_libretro_android.so==780006344
+//            2023-11-01 11:07:45.866 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: atari800_libretro_android.so==3982345270
+//            2023-11-01 11:07:45.877 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: bk_libretro_android.so==3404889964
+//            2023-11-01 11:07:45.931 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: bluemsx_libretro_android.so==2174918511
+//            2023-11-01 11:07:45.981 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: bsnes2014_accuracy_libretro_android.so==4004440739
+//            2023-11-01 11:07:46.026 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: bsnes2014_balanced_libretro_android.so==3040064712
+//            2023-11-01 11:07:46.069 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: bsnes2014_performance_libretro_android.so==3696944667
+//            2023-11-01 11:07:46.099 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: bsnes_cplusplus98_libretro_android.so==1869373139
+//            2023-11-01 11:07:46.151 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: bsnes_hd_beta_libretro_android.so==382458000
+//            2023-11-01 11:07:46.256 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: bsnes_libretro_android.so==3307173016
+//            2023-11-01 11:07:46.318 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: bsnes_mercury_accuracy_libretro_android.so==3911464644
+//            2023-11-01 11:07:46.367 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: bsnes_mercury_balanced_libretro_android.so==252543078
+//            2023-11-01 11:07:46.490 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: bsnes_mercury_performance_libretro_android.so==1625131764
+//            2023-11-01 11:07:46.528 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: cannonball_libretro_android.so==2880937827
+//            2023-11-01 11:07:46.594 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: cap32_libretro_android.so==2493288555
+//            2023-11-01 11:07:46.734 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: chailove_libretro_android.so==1375760160
+//            2023-11-01 11:07:46.776 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: craft_libretro_android.so==1081743909
+//            2023-11-01 11:07:46.799 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: crocods_libretro_android.so==1627025149
+//            2023-11-01 11:07:46.880 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: daphne_libretro_android.so==1749009889
+//            2023-11-01 11:07:46.956 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: desmume2015_libretro_android.so==3350467466
+//            2023-11-01 11:07:47.054 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: desmume_libretro_android.so==2142315990
+//            2023-11-01 11:07:47.089 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: dinothawr_libretro_android.so==205446461
+//            2023-11-01 11:07:47.119 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: dirksimple_libretro_android.so==1067967961
+//            2023-11-01 11:07:47.265 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: dosbox_core_libretro_android.so==1427022774
+//            2023-11-01 11:07:47.403 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: dosbox_pure_libretro_android.so==572308854
+//            2023-11-01 11:07:47.529 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: dosbox_svn_libretro_android.so==2385688716
+//            2023-11-01 11:07:48.026 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: easyrpg_libretro_android.so==2585895017
+//            2023-11-01 11:07:48.077 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: ecwolf_libretro_android.so==2475511887
+//            2023-11-01 11:07:48.228 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: ep128emu_core_libretro_android.so==1052432164
+//            2023-11-01 11:07:48.314 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: fbalpha2012_cps1_libretro_android.so==1386541134
+//            2023-11-01 11:07:48.394 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: fbalpha2012_cps2_libretro_android.so==3732721916
+//            2023-11-01 11:07:48.420 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: fbalpha2012_cps3_libretro_android.so==2416818326
+//            2023-11-01 11:07:48.996 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: fbalpha2012_libretro_android.so==147964066
+//            2023-11-01 11:07:49.059 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: fbalpha2012_neogeo_libretro_android.so==1517614885
+//            2023-11-01 11:07:50.397 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: fbalpha_libretro_android.so==1536260623
+//            2023-11-01 11:07:52.070 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: fbneo_libretro_android.so==1018321941
+//            2023-11-01 11:07:52.158 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: fceumm_libretro_android.so==1950764938
+//            2023-11-01 11:07:52.665 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: ffmpeg_libretro_android.so==587118488
+//            2023-11-01 11:07:53.821 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: flycast_libretro_android.so==880260156
+//            2023-11-01 11:07:53.831 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: fmsx_libretro_android.so==3889882656
+//            2023-11-01 11:07:53.837 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: freechaf_libretro_android.so==2075251627
+//            2023-11-01 11:07:53.844 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: freeintv_libretro_android.so==516128921
+//            2023-11-01 11:07:53.873 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: frodo_libretro_android.so==2469160198
+//            2023-11-01 11:07:53.933 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: fuse_libretro_android.so==3857999837
+//            2023-11-01 11:07:53.946 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: galaksija_libretro_android.so==999199391
+//            2023-11-01 11:07:54.031 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: gambatte_libretro_android.so==3111808968
+//            2023-11-01 11:07:54.057 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: gearboy_libretro_android.so==4188330667
+//            2023-11-01 11:07:54.087 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: gearcoleco_libretro_android.so==1921185480
+//            2023-11-01 11:07:54.114 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: gearsystem_libretro_android.so==3669451411
+//            2023-11-01 11:07:54.370 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: genesis_plus_gx_libretro_android.so==3411919808
+//            2023-11-01 11:07:54.625 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: genesis_plus_gx_wide_libretro_android.so==3033288201
+//            2023-11-01 11:07:54.642 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: gme_libretro_android.so==910154216
+//            2023-11-01 11:07:54.644 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: gong_libretro_android.so==510552488
+//            2023-11-01 11:07:54.682 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: gpsp_libretro_android.so==3115776383
+//            2023-11-01 11:07:54.705 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: gw_libretro_android.so==78719041
+//            2023-11-01 11:07:54.731 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: handy_libretro_android.so==1857042333
+//            2023-11-01 11:07:54.800 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: hatari_libretro_android.so==4002646417
+//            2023-11-01 11:07:54.804 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: jaxe_libretro_android.so==2538426728
+//            2023-11-01 11:07:54.809 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: jumpnbump_libretro_android.so==2835147507
+//            2023-11-01 11:07:54.816 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: lowresnx_libretro_android.so==2020869293
+//            2023-11-01 11:07:54.897 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: lutro_libretro_android.so==1367222163
+//            2023-11-01 11:07:55.241 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: mame2000_libretro_android.so==3850503187
+//            2023-11-01 11:07:56.154 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: mame2003_libretro_android.so==1483054888
+//            2023-11-01 11:07:56.239 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: mame2003_midway_libretro_android.so==2944755977
+//            2023-11-01 11:07:57.193 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: mame2003_plus_libretro_android.so==2050019383
+//            2023-11-01 11:07:58.691 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: mame2010_libretro_android.so==658690590
+//            2023-11-01 11:08:05.747 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: mamearcade_libretro_android.so==3141440399
+//            2023-11-01 11:08:05.772 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: mednafen_gba_libretro_android.so==3627362044
+//            2023-11-01 11:08:05.789 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: mednafen_lynx_libretro_android.so==3022889740
+//            2023-11-01 11:08:05.806 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: mednafen_ngp_libretro_android.so==997079995
+//            2023-11-01 11:08:05.899 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: mednafen_pce_fast_libretro_android.so==301716041
+//            2023-11-01 11:08:06.009 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: mednafen_pce_libretro_android.so==2459283410
+//            2023-11-01 11:08:06.065 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: mednafen_pcfx_libretro_android.so==920163216
+//            2023-11-01 11:08:06.342 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: mednafen_psx_hw_libretro_android.so==2978947402
+//            2023-11-01 11:08:06.532 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: mednafen_psx_libretro_android.so==1510037674
+//            2023-11-01 11:08:06.717 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: mednafen_saturn_libretro_android.so==356920118
+//            2023-11-01 11:08:06.773 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: mednafen_snes_libretro_android.so==1257017063
+//            2023-11-01 11:08:06.847 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: mednafen_supafaust_libretro_android.so==4081301686
+//            2023-11-01 11:08:06.925 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: mednafen_supergrafx_libretro_android.so==2594090264
+//            2023-11-01 11:08:06.965 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: mednafen_vb_libretro_android.so==3256836489
+//            2023-11-01 11:08:07.001 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: mednafen_wswan_libretro_android.so==3497937091
+//            2023-11-01 11:08:07.082 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: melonds_libretro_android.so==2918883364
+//            2023-11-01 11:08:07.145 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: mesen-s_libretro_android.so==1260744833
+//            2023-11-01 11:08:07.296 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: mesen_libretro_android.so==2700063797
+//            2023-11-01 11:08:07.318 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: meteor_libretro_android.so==3258943291
+//            2023-11-01 11:08:07.401 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: mgba_libretro_android.so==2923170793
+//            2023-11-01 11:08:07.425 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: minivmac_libretro_android.so==4156638768
+//            2023-11-01 11:08:07.463 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: mojozork_libretro_android.so==2562154472
+//            2023-11-01 11:08:07.848 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: mrboom_libretro_android.so==3736040718
+//            2023-11-01 11:08:08.130 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: mupen64plus_next_gles2_libretro_android.so==92497630
+//            2023-11-01 11:08:08.450 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: mupen64plus_next_gles3_libretro_android.so==914889182
+//            2023-11-01 11:08:08.473 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: mu_libretro_android.so==643777069
+//            2023-11-01 11:08:08.515 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: nekop2_libretro_android.so==145865232
+//            2023-11-01 11:08:08.601 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: neocd_libretro_android.so==2661926962
+//            2023-11-01 11:08:08.751 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: nestopia_libretro_android.so==2387233794
+//            2023-11-01 11:08:08.821 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: np2kai_libretro_android.so==2954182638
+//            2023-11-01 11:08:08.881 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: numero_libretro_android.so==1595551155
+//            2023-11-01 11:08:08.915 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: nxengine_libretro_android.so==3498192948
+//            2023-11-01 11:08:08.933 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: o2em_libretro_android.so==2159610848
+//            2023-11-01 11:08:08.968 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: oberon_libretro_android.so==2524142882
+//            2023-11-01 11:08:09.038 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: openlara_libretro_android.so==842639624
+//            2023-11-01 11:08:09.081 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: opera_libretro_android.so==3164829577
+//            2023-11-01 11:08:09.423 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: parallel_n64_libretro_android.so==3098451268
+//            2023-11-01 11:08:09.479 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: pcsx_rearmed_libretro_android.so==1576915211
+//            2023-11-01 11:08:09.545 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: picodrive_libretro_android.so==3845465822
+//            2023-11-01 11:08:11.023 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: play_libretro_android.so==1988422128
+//            2023-11-01 11:08:11.031 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: pocketcdg_libretro_android.so==1618466829
+//            2023-11-01 11:08:11.082 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: pokemini_libretro_android.so==1592896062
+//            2023-11-01 11:08:11.130 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: potator_libretro_android.so==3022486751
+//            2023-11-01 11:08:11.768 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: ppsspp_libretro_android.so==820240270
+//            2023-11-01 11:08:11.814 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: prboom_libretro_android.so==2332874982
+//            2023-11-01 11:08:11.824 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: prosystem_libretro_android.so==2684419963
+//            2023-11-01 11:08:12.267 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: puae2021_libretro_android.so==807296260
+//            2023-11-01 11:08:13.077 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: puae_libretro_android.so==2126600417
+//            2023-11-01 11:08:13.109 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: px68k_libretro_android.so==3887247101
+//            2023-11-01 11:08:13.164 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: quasi88_libretro_android.so==2354749396
+//            2023-11-01 11:08:13.202 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: quicknes_libretro_android.so==1635437732
+//            2023-11-01 11:08:13.242 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: race_libretro_android.so==1179511441
+//            2023-11-01 11:08:13.259 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: reminiscence_libretro_android.so==812522150
+//            2023-11-01 11:08:13.321 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: retro8_libretro_android.so==1733843823
+//            2023-11-01 11:08:13.336 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: sameboy_libretro_android.so==450186404
+//            2023-11-01 11:08:13.343 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: sameduck_libretro_android.so==3214298071
+//            2023-11-01 11:08:16.254 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: same_cdi_libretro_android.so==992935775
+//            2023-11-01 11:08:18.569 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: scummvm_libretro_android.so==4100300513
+//            2023-11-01 11:08:18.578 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: smsplus_libretro_android.so==1061157626
+//            2023-11-01 11:08:18.613 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: snes9x2002_libretro_android.so==1832895834
+//            2023-11-01 11:08:18.662 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: snes9x2005_libretro_android.so==265847001
+//            2023-11-01 11:08:18.713 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: snes9x2005_plus_libretro_android.so==406882931
+//            2023-11-01 11:08:18.807 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: snes9x2010_libretro_android.so==1912744787
+//            2023-11-01 11:08:18.874 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: snes9x_libretro_android.so==1396374684
+//            2023-11-01 11:08:18.879 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: squirreljme_libretro_android.so==1686990514
+//            2023-11-01 11:08:18.995 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: stella2014_libretro_android.so==2694497635
+//            2023-11-01 11:08:19.150 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: stella_libretro_android.so==2878062309
+//            2023-11-01 11:08:19.257 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: superbroswar_libretro_android.so==1177918814
+//            2023-11-01 11:08:19.441 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: swanstation_libretro_android.so==2189927838
+//            2023-11-01 11:08:19.471 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: test_libretro_android.so==4072819540
+//            2023-11-01 11:08:19.519 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: tgbdual_libretro_android.so==4118501607
+//            2023-11-01 11:08:19.652 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: theodore_libretro_android.so==1794530955
+//            2023-11-01 11:08:19.836 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: thepowdertoy_libretro_android.so==1431444086
+//            2023-11-01 11:08:19.941 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: tic80_libretro_android.so==3523696412
+//            2023-11-01 11:08:19.972 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: tyrquake_libretro_android.so==4011954349
+//            2023-11-01 11:08:19.984 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: uw8_libretro_android.so==707177494
+//            2023-11-01 11:08:19.995 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: uzem_libretro_android.so==4025363444
+//            2023-11-01 11:08:20.035 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: vaporspec_libretro_android.so==62375315
+//            2023-11-01 11:08:20.117 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: vbam_libretro_android.so==2529213728
+//            2023-11-01 11:08:20.144 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: vba_next_libretro_android.so==3272353476
+//            2023-11-01 11:08:20.152 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: vecx_libretro_android.so==3708413075
+//            2023-11-01 11:08:20.172 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: vemulator_libretro_android.so==1403685916
+//            2023-11-01 11:08:20.314 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: vice_x128_libretro_android.so==77282354
+//            2023-11-01 11:08:20.436 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: vice_x64sc_libretro_android.so==502339610
+//            2023-11-01 11:08:20.553 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: vice_x64_libretro_android.so==3744918022
+//            2023-11-01 11:08:20.653 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: vice_xcbm2_libretro_android.so==3472472312
+//            2023-11-01 11:08:20.771 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: vice_xcbm5x0_libretro_android.so==41796132
+//            2023-11-01 11:08:20.872 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: vice_xpet_libretro_android.so==3282819252
+//            2023-11-01 11:08:21.012 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: vice_xplus4_libretro_android.so==262861266
+//            2023-11-01 11:08:21.156 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: vice_xscpu64_libretro_android.so==3181671713
+//            2023-11-01 11:08:21.257 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: vice_xvic_libretro_android.so==2385615623
+//            2023-11-01 11:08:21.340 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: virtualjaguar_libretro_android.so==3681754840
+//            2023-11-01 11:08:21.370 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: virtualxt_libretro_android.so==1112863931
+//            2023-11-01 11:08:21.424 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: vitaquake2-rogue_libretro_android.so==3746780493
+//            2023-11-01 11:08:21.474 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: vitaquake2-xatrix_libretro_android.so==1734504512
+//            2023-11-01 11:08:21.526 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: vitaquake2-zaero_libretro_android.so==3920496352
+//            2023-11-01 11:08:21.574 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: vitaquake2_libretro_android.so==1500644696
+//            2023-11-01 11:08:21.583 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: wasm4_libretro_android.so==4263425003
+//            2023-11-01 11:08:21.647 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: x1_libretro_android.so==265044321
+//            2023-11-01 11:08:21.667 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: xrick_libretro_android.so==3169920846
+//            2023-11-01 11:08:21.737 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: yabasanshiro_libretro_android.so==1494296251
+//            2023-11-01 11:08:21.826 7083-7099/com.xugame.TestSomeThing1 I/TestCircleActivityTAG: yabause_libretro_android.so==1201015839
+
 }

+ 91 - 27
app/src/main/java/com/xugame/gameconsole/emulator/RetroArchEmulatorActivity.java

@@ -137,6 +137,16 @@ public class RetroArchEmulatorActivity extends RetroActivityCamera
             @Override
             public void contentLoaded() {
                 Log.i("EnvironmentCallback", "Content Loaded");
+//                testSetKey2();
+            }
+
+            @Override
+            public void saveStateCallback(int error) {
+                Log.i("EnvironmentCallback", "saveStateCallback: " + error);
+                Intent intent = new Intent();
+                intent.setAction(EmulatorMonitor.EMULATOR_SAVE_STATE_RESULT_ACTION);
+                intent.putExtra("save_state_flag", error == 0);
+                sendBroadcast(intent);
             }
         };
         mEmulatorMonitor = new EmulatorMonitor(this, this);
@@ -425,15 +435,16 @@ public class RetroArchEmulatorActivity extends RetroActivityCamera
 //        alertDialog.show();
     }
 
-    private int mScreen = 0;
-    private int mScanline = 0;
+    private int mScreen = -1;
+    private int mScanline = -1;
 
     @Override
     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        DebugUtil.i(TAG,"requestCode="+requestCode+"resultCode="+resultCode);
         if (requestCode == 200) {
             if (resultCode == 201) {//继续游戏
                 gameDialogClosed();
-//                testSetKey();
+//                testSetKey2();
                 if (data != null) {
                     //增加完美像素单独开关,避免混淆
                     boolean isPixelPerfect = data.getBooleanExtra("is_pixelperfect", false);
@@ -462,28 +473,31 @@ public class RetroArchEmulatorActivity extends RetroActivityCamera
                             }
                         }
 //                        }
-                        if (mScanline != scanLine) {
-                            if (scanLine >= 0 && scanLine < 4) {
-                                DebugUtil.i(TAG, "设置scanLine" + scanLine + ScreenType.values()[scanLine]);
-
-                                switch (ScreenType.values()[scanLine]) {
-                                    case NORMAL:
-                                        switchFilter(null);
-                                        break;
-                                    case SAI_2X:
-                                        switchFilter("/data/user/0/com.xugame.gameconsole/filters/video/Scale2x.filt");
-                                        break;
-                                    case SCANLINE:
-                                        switchFilter("/data/user/0/com.xugame.gameconsole/filters/video/Scanline2x.filt");
-                                        break;
-                                    case EPX:
-                                        switchFilter("/data/user/0/com.xugame.gameconsole/filters/video/EPX.filt");
-                                        break;
-                                }
+//                        if (mScanline != scanLine) {
+                        mScanline = scanLine;
+                        if (scanLine >= 0 && scanLine < 4) {
+                            DebugUtil.i(TAG, "设置scanLine" + scanLine + ScreenType.values()[scanLine]);
+
+                            switch (ScreenType.values()[scanLine]) {
+                                case NORMAL:
+                                    switchFilter(null);
+                                    break;
+                                case SAI_2X:
+                                    switchFilter("/data/user/0/com.xugame.gameconsole/filters/video/Scale2x.filt");
+                                    break;
+                                case SCANLINE:
+                                    switchFilter("/data/user/0/com.xugame.gameconsole/filters/video/Scanline2x.filt");
+                                    break;
+                                case EPX:
+                                    switchFilter("/data/user/0/com.xugame.gameconsole/filters/video/EPX.filt");
+                                    break;
                             }
                         }
+//                        }
                     } else {
                         int multiple = data.getIntExtra("multiple", -1);
+                        mScanline = -1;
+                        mScreen = -1;
                         DebugUtil.i(TAG, "multiple=" + multiple);
                         if (multiple >= 2 && multiple <= 5) {
                             resetScreenForPerfect(multiple);
@@ -540,6 +554,55 @@ public class RetroArchEmulatorActivity extends RetroActivityCamera
     }
 
 
+    private void testSetKey2() {
+        int tempKeys[] = new int[35];
+        int tempAxis[] = new int[35];
+        for (int i = 0; i < tempKeys.length; i++) {
+            tempKeys[i] = 0;
+
+            tempAxis[i] = 0;
+        }
+
+        int[] keys = {//纯按键
+                InputCode.JoypadBindKeySet.JOYPAD_BTN_A,//轻拳
+                InputCode.JoypadBindKeySet.JOYPAD_BTN_B,//重拳
+                108,
+                109,
+                InputCode.JoypadBindKeySet.JOYPAD_HAT_DOWN,
+                InputCode.JoypadBindKeySet.JOYPAD_HAT_UP,
+                InputCode.JoypadBindKeySet.JOYPAD_HAT_LEFT,
+                InputCode.JoypadBindKeySet.JOYPAD_HAT_RIGHT,
+                99,//轻脚
+                100,//重脚
+                98,
+                101,
+                103,
+                104,
+                105,
+                106
+        };
+        for (int i = 0; i < keys.length; i++) {
+            tempKeys[i] = keys[i];
+        }
+        int[] axiss = {//轴
+                -1,
+                -1,
+                -1,
+                -1,
+                InputCode.JoypadBindKeySet.JOYPAD_AXIS_Y_MINIS,
+                InputCode.JoypadBindKeySet.JOYPAD_AXIS_Y_PLUS,
+                InputCode.JoypadBindKeySet.JOYPAD_AXIS_X_MINIS,
+                InputCode.JoypadBindKeySet.JOYPAD_AXIS_X_PLUS,
+                InputCode.JoypadBindKeySet.JOYPAD_AXIS_Z_PLUS,
+                InputCode.JoypadBindKeySet.JOYPAD_AXIS_Z_MINIS,
+        };
+        for (int i = 0; i < axiss.length; i++) {
+            tempAxis[i] = axiss[i];
+        }
+        setJoystickBindNative(0, tempKeys, tempAxis);
+    }
+
+
     private void resetScreenForPerfect(int multiple) {
         if (system != null && system.systemAVInfo != null) {
             int w = system.systemAVInfo.getGeometry().getBaseWidth();
@@ -635,12 +698,13 @@ public class RetroArchEmulatorActivity extends RetroActivityCamera
     public void onMenuSaveState(int index) {
         DebugUtil.i(TAG, "saveState" + index);
         if (index >= 0 && index < 10) {
-            if (saveState(index)) {
-                Intent intent = new Intent();
-                intent.setAction(EmulatorMonitor.EMULATOR_SAVE_STATE_ACTION);
-                intent.putExtra("save_state_flag", true);
-                this.sendBroadcast(intent);
-            }
+            saveState(index);
+//            if (saveState(index)) {
+//                Intent intent = new Intent();
+//                intent.setAction(EmulatorMonitor.EMULATOR_SAVE_STATE_ACTION);
+//                intent.putExtra("save_state_flag", true);
+//                this.sendBroadcast(intent);
+//            }
         }
     }
 

+ 0 - 2
app/src/main/java/com/xugame/gameconsole/emulator/ScreenType.java

@@ -2,8 +2,6 @@ package com.xugame.gameconsole.emulator;
 
 public enum ScreenType {
     NORMAL,
-    NORMAL_2X,
-    NORMAL_4X,
     SAI_2X,
     SCANLINE,
     EPX,

+ 2 - 0
app/src/main/java/com/xugame/gameconsole/monitor/EmulatorMonitor.java

@@ -14,6 +14,8 @@ public class EmulatorMonitor {
     public static final String EMULATOR_SAVE_STATE_ACTION = "EMULATOR_SAVE_STATE_ACTION";
     public static final String EMULATOR_LOAD_STATE_ACTION = "EMULATOR_LOAD_STATE_ACTION";
 
+    public static final String EMULATOR_SAVE_STATE_RESULT_ACTION = "EMULATOR_SAVE_STATE_RESULT_ACTION";//用于存档结果回调
+
 
     private static final String SYSTEM_REASON = "reason";
     private static final String SYSTEM_HOME_KEY = "homekey";

+ 157 - 0
app/src/main/java/com/xugame/gameconsole/util/CheckFileCRC.java

@@ -0,0 +1,157 @@
+package com.xugame.gameconsole.util;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.text.TextUtils;
+
+import androidx.annotation.NonNull;
+
+import com.xugame.gameconsole.R;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.zip.CRC32;
+import java.util.zip.CheckedInputStream;
+
+public class CheckFileCRC implements Runnable {
+    private static final String TAG = "CheckFileCRCTAG";
+    private Thread mThread;
+    private Handler mHandler;
+    private CheckFileCRCListener mListener;
+    private String mPath;
+    private String mCoreName;
+    private Context mContext;
+
+    public CheckFileCRC(Context context, CheckFileCRCListener listener) {
+        this.mContext = context;
+        this.mListener = listener;
+    }
+
+    public void check(String path) {
+        DebugUtil.i(TAG,"check"+path);
+        if (TextUtils.isEmpty(path)) {
+            this.mListener.onCheckCoresCRCError(-1);
+            return;
+        }
+        mPath = path;
+        File file = new File(path);
+        if (!file.exists()) {
+            this.mListener.onCheckCoresCRCError(-2);
+            return;
+        }
+        mCoreName = file.getName();
+        this.init();
+
+        this.mThread = new Thread(this);
+        this.mThread.setPriority(Thread.MAX_PRIORITY);
+        this.mThread.start();
+    }
+
+    private void init() {
+        mHandler = new Handler(Looper.myLooper()) {
+            @Override
+            public void handleMessage(@NonNull Message msg) {
+                super.handleMessage(msg);
+                if(msg.what==0){
+                    Bundle bundle=msg.getData();
+                    if(bundle!=null){
+                        long filecrc=bundle.getLong("filecrc");
+                        String dfCrc=bundle.getString("default_crc");
+                        if(mListener!=null){
+                            mListener.onCheckCoresCRCDone(""+filecrc,dfCrc);
+                        }
+                    }
+                }
+            }
+        };
+    }
+
+    @Override
+    public void run() {
+        long filecrc = ChecksumCRC32(mPath);
+        String defaultCrc = returnDEF(mCoreName);
+        DebugUtil.i(TAG,"checkCrc="+filecrc+"defCrc="+defaultCrc);
+        if(mHandler!=null){
+            Message message=new Message();
+            message.what=0;
+            Bundle bundle=new Bundle();
+            bundle.putLong("filecrc",filecrc);
+            bundle.putString("default_crc",defaultCrc);
+            message.setData(bundle);
+            mHandler.sendMessage(message);
+        }
+    }
+
+
+    public long ChecksumCRC32(String path) {
+        long checksum = 0;
+
+        CheckedInputStream cis = null;
+        File file = new File(path);
+
+        try {
+            cis = new CheckedInputStream(new FileInputStream(file), new CRC32());
+            byte[] buf = new byte[1024];
+
+            while (cis.read(buf) >= 0) {
+                checksum = cis.getChecksum().getValue();
+            }
+        } catch (FileNotFoundException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        } catch (IOException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+
+        return checksum;
+    }
+
+    private String returnDEF(String name) {
+        if (name.equals("fbneo_libretro_android.so")) {
+            return mContext.getResources().getString(R.string.fbneo_libretro_android);
+        } else if (name.equals("fceumm_libretro_android.so")) {
+            return mContext.getResources().getString(R.string.fceumm_libretro_android);
+        } else if (name.equals("mame2010_libretro_android.so")) {
+            return mContext.getResources().getString(R.string.mame2010_libretro_android);
+        } else if (name.equals("snes9x2010_libretro_android.so")) {
+            return mContext.getResources().getString(R.string.snes9x2010_libretro_android);
+        } else if (name.equals("mgba_libretro_android.so")) {
+            return mContext.getResources().getString(R.string.mgba_libretro_android);
+        } else if (name.equals("tgbdual_libretro_android.so")) {
+            return mContext.getResources().getString(R.string.tgbdual_libretro_android);
+        } else if (name.equals("genesis_plus_gx_wide_libretro_android.so")) {
+            return mContext.getResources().getString(R.string.genesis_plus_gx_wide_libretro_android);
+        } else if (name.equals("mednafen_ngp_libretro_android.so")) {
+            return mContext.getResources().getString(R.string.mednafen_ngp_libretro_android);
+        } else if (name.equals("mednafen_pce_libretro_android.so")) {
+            return mContext.getResources().getString(R.string.mednafen_pce_libretro_android);
+        } else if (name.equals("pcsx_rearmed_libretro_android.so")) {
+            return mContext.getResources().getString(R.string.pcsx_rearmed_libretro_android);
+        } else if (name.equals("smsplus_libretro_android.so")) {
+            return mContext.getResources().getString(R.string.smsplus_libretro_android);
+        } else if (name.equals("mednafen_wswan_libretro_android.so")) {
+            return mContext.getResources().getString(R.string.mednafen_wswan_libretro_android);
+        } else if (name.equals("ppsspp_libretro_android.so")) {
+            return mContext.getResources().getString(R.string.ppsspp_libretro_android);
+        } else if (name.equals("mupen64plus_next_gles2_libretro_android.so")) {
+            return mContext.getResources().getString(R.string.mupen64plus_next_gles2_libretro_android);
+        } else if (name.equals("flycast_libretro_android.so")) {
+            return mContext.getResources().getString(R.string.flycast_libretro_android);
+        } else if (name.equals("stella_libretro_android.so")) {
+            return mContext.getResources().getString(R.string.stella_libretro_android);
+        } else if (name.equals("vice_x64_libretro_android.so")) {
+            return mContext.getResources().getString(R.string.vice_x64_libretro_android);
+        } else if (name.equals("picodrive_libretro_android.so")) {
+            return mContext.getResources().getString(R.string.picodrive_libretro_android);
+        }  else {
+            return "";
+        }
+    }
+
+}

+ 6 - 0
app/src/main/java/com/xugame/gameconsole/util/CheckFileCRCListener.java

@@ -0,0 +1,6 @@
+package com.xugame.gameconsole.util;
+
+public interface CheckFileCRCListener {
+    void  onCheckCoresCRCDone(String crc,String defaultCRC);
+    void  onCheckCoresCRCError(int error);
+}

+ 1 - 1
app/src/main/java/com/xugame/gameconsole/util/DebugUtil.java

@@ -4,7 +4,7 @@ import android.util.Log;
 
 
 public class DebugUtil {
-    static private boolean DEBUG = false;
+    static private boolean DEBUG = true;
 
     public static void d(String tag, String msg) {
         if (DEBUG)

+ 1 - 1
app/src/main/res/layout/dialog_loadging.xml

@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
-    android:background="#64000000"
+    android:background="@android:color/transparent"
     android:layout_height="match_parent">
 
     <com.xugame.gameconsole.dialog.loadingview.SpinKitView

+ 200 - 0
app/src/main/res/values/strings.xml

@@ -1,3 +1,203 @@
 <resources>
     <string name="app_name">Emulator</string>
+
+<!--FOR CRC-->
+<!--    //1018321941-->
+    <string name="fbneo_libretro_android">1018321941</string>
+    <!--    NES-->
+    <string name="fceumm_libretro_android">1950764938</string>
+    <!--    MAME-->
+    <string name="mame2010_libretro_android">658690590</string>
+    <!--    SFC-->
+    <string name="snes9x2010_libretro_android">1912744787</string>
+    <!--    GBA-->
+    <string name="mgba_libretro_android">2923170793</string>
+    <!--    GBC-->
+    <string name="tgbdual_libretro_android">4118501607</string>
+    <!--    MD-->
+    <string name="genesis_plus_gx_wide_libretro_android">3033288201</string>
+    <!--    NGPC-->
+    <string name="mednafen_ngp_libretro_android">997079995</string>
+    <!--    PCE-->
+    <string name="mednafen_pce_libretro_android">2459283410</string>
+    <!--    PS1-->
+    <string name="pcsx_rearmed_libretro_android">1576915211</string>
+    <!--    SMS-->
+    <string name="smsplus_libretro_android">1061157626</string>
+    <!--    WONDERSWAN-->
+    <string name="mednafen_wswan_libretro_android">3497937091</string>
+    <!--    PSP-->
+    <string name="ppsspp_libretro_android">820240270</string>
+    <!--    N64-->
+    <string name="mupen64plus_next_gles2_libretro_android">92497630</string>
+    <!--    DREAMCAST-->
+    <string name="flycast_libretro_android">880260156</string>
+    <!--    ATARI2600-->
+    <string name="stella_libretro_android">2878062309</string>
+    <!--    COMMODORE64-->
+    <string name="vice_x64_libretro_android">3744918022</string>
+
+
+
+    <string name="_2048_libretro_android">1042003817</string>
+    <string name="_3dengine_libretro_android">1535549497</string>
+    <string name="_81_libretro_android">3797825066</string>
+    <string name="a5200_libretro_android">3869894026</string>
+    <string name="arduous_libretro_android">780006344</string>
+    <string name="atari800_libretro_android">3982345270</string>
+    <string name="bk_libretro_android">3404889964</string>
+    <string name="bluemsx_libretro_android">2174918511</string>
+    <string name="bsnes2014_accuracy_libretro_android">4004440739</string>
+    <string name="bsnes2014_balanced_libretro_android">3040064712</string>
+    <string name="bsnes2014_performance_libretro_android">3696944667</string>
+    <string name="bsnes_cplusplus98_libretro_android">1869373139</string>
+    <string name="bsnes_hd_beta_libretro_android">382458000</string>
+    <string name="bsnes_libretro_android">3307173016</string>
+    <string name="bsnes_mercury_accuracy_libretro_android">3911464644</string>
+    <string name="bsnes_mercury_balanced_libretro_android">252543078</string>
+    <string name="bsnes_mercury_performance_libretro_android">1625131764</string>
+    <string name="cannonball_libretro_android">2880937827</string>
+    <string name="cap32_libretro_android">2493288555</string>
+    <string name="chailove_libretro_android">1375760160</string>
+
+    <string name="craft_libretro_android">1081743909</string>
+    <string name="crocods_libretro_android">1627025149</string>
+    <string name="daphne_libretro_android">1749009889</string>
+    <string name="desmume2015_libretro_android">3350467466</string>
+    <string name="desmume_libretro_android">2142315990</string>
+    <string name="dinothawr_libretro_android">205446461</string>
+    <string name="dirksimple_libretro_android">1067967961</string>
+    <string name="dosbox_core_libretro_android">1427022774</string>
+    <string name="dosbox_pure_libretro_android">572308854</string>
+    <string name="dosbox_svn_libretro_android">2385688716</string>
+    <string name="easyrpg_libretro_android">2585895017</string>
+    <string name="ecwolf_libretro_android">2475511887</string>
+    <string name="ep128emu_core_libretro_android">1052432164</string>
+    <string name="fbalpha2012_cps1_libretro_android">1386541134</string>
+    <string name="fbalpha2012_cps2_libretro_android">3732721916</string>
+    <string name="fbalpha2012_cps3_libretro_android">2416818326</string>
+    <string name="fbalpha2012_libretro_android">147964066</string>
+    <string name="fbalpha2012_neogeo_libretro_android">1517614885</string>
+    <string name="fbalpha_libretro_android">1536260623</string>
+
+    <string name="ffmpeg_libretro_android">587118488</string>
+    <string name="fmsx_libretro_android">3889882656</string>
+    <string name="freechaf_libretro_android">2075251627</string>
+    <string name="freeintv_libretro_android">516128921</string>
+    <string name="frodo_libretro_android">2469160198</string>
+    <string name="fuse_libretro_android">3857999837</string>
+    <string name="galaksija_libretro_android">999199391</string>
+    <string name="gambatte_libretro_android">3111808968</string>
+    <string name="gearboy_libretro_android">4188330667</string>
+    <string name="gearcoleco_libretro_android">1921185480</string>
+    <string name="gearsystem_libretro_android">3669451411</string>
+    <string name="genesis_plus_gx_libretro_android">3411919808</string>
+    <string name="gme_libretro_android">910154216</string>
+    <string name="gong_libretro_android">510552488</string>
+    <string name="gpsp_libretro_android">3115776383</string>
+    <string name="gw_libretro_android">78719041</string>
+    <string name="handy_libretro_android">1857042333</string>
+    <string name="hatari_libretro_android">4002646417</string>
+    <string name="jaxe_libretro_android">2538426728</string>
+
+
+    <string name="jumpnbump_libretro_android">2835147507</string>
+    <string name="lowresnx_libretro_android">2020869293</string>
+    <string name="lutro_libretro_android">1367222163</string>
+    <string name="mame2000_libretro_android">3850503187</string>
+    <string name="mame2003_libretro_android">1483054888</string>
+    <string name="mame2003_midway_libretro_android">2944755977</string>
+    <string name="mame2003_plus_libretro_android">2050019383</string>
+    <string name="mamearcade_libretro_android">3141440399</string>
+    <string name="mednafen_gba_libretro_android">3627362044</string>
+    <string name="mednafen_lynx_libretro_android">3022889740</string>
+    <string name="mednafen_pce_fast_libretro_android">301716041</string>
+    <string name="mednafen_pcfx_libretro_android">920163216</string>
+    <string name="mednafen_psx_hw_libretro_android">2978947402</string>
+    <string name="mednafen_psx_libretro_android">1510037674</string>
+    <string name="mednafen_saturn_libretro_android">356920118</string>
+    <string name="mednafen_snes_libretro_android">1257017063</string>
+    <string name="mednafen_supafaust_libretro_android">4081301686</string>
+    <string name="mednafen_supergrafx_libretro_android">2594090264</string>
+
+
+    <string name="mednafen_vb_libretro_android">3256836489</string>
+    <string name="melonds_libretro_android">2918883364</string>
+    <string name="mesen_s_libretro_android">1260744833</string>
+    <string name="mesen_libretro_android">2700063797</string>
+    <string name="meteor_libretro_android">3258943291</string>
+    <string name="minivmac_libretro_android">4156638768</string>
+    <string name="mojozork_libretro_android">2562154472</string>
+    <string name="mrboom_libretro_android">3736040718</string>
+    <string name="mupen64plus_next_gles3_libretro_android">914889182</string>
+    <string name="mu_libretro_android">643777069</string>
+    <string name="nekop2_libretro_android">145865232</string>
+    <string name="neocd_libretro_android">2661926962</string>
+    <string name="nestopia_libretro_android">2387233794</string>
+    <string name="np2kai_libretro_android">2954182638</string>
+    <string name="numero_libretro_android">1595551155</string>
+    <string name="nxengine_libretro_android">3498192948</string>
+    <string name="o2em_libretro_android">2159610848</string>
+    <string name="oberon_libretro_android">2524142882</string>
+
+
+    <string name="openlara_libretro_android">842639624</string>
+    <string name="opera_libretro_android">3164829577</string>
+    <string name="parallel_n64_libretro_android">3098451268</string>
+    <string name="picodrive_libretro_android">3845465822</string>
+    <string name="play_libretro_android">1988422128</string>
+    <string name="pocketcdg_libretro_android">1618466829</string>
+    <string name="pokemini_libretro_android">1592896062</string>
+    <string name="potator_libretro_android">3022486751</string>
+    <string name="prboom_libretro_android">2332874982</string>
+    <string name="prosystem_libretro_android">2684419963</string>
+    <string name="puae2021_libretro_android">807296260</string>
+    <string name="puae_libretro_android">2126600417</string>
+    <string name="px68k_libretro_android">3887247101</string>
+    <string name="quasi88_libretro_android">2354749396</string>
+    <string name="quicknes_libretro_android">1635437732</string>
+    <string name="race_libretro_android">1179511441</string>
+    <string name="reminiscence_libretro_android">812522150</string>
+    <string name="retro8_libretro_android">1733843823</string>
+    <string name="sameboy_libretro_android">450186404</string>
+
+
+    <string name="sameduck_libretro_android">3214298071</string>
+    <string name="same_cdi_libretro_android">992935775</string>
+    <string name="scummvm_libretro_android">4100300513</string>
+    <string name="snes9x2002_libretro_android">1832895834</string>
+    <string name="snes9x2005_libretro_android">265847001</string>
+    <string name="snes9x2005_plus_libretro_android">406882931</string>
+    <string name="snes9x_libretro_android">1396374684</string>
+    <string name="squirreljme_libretro_android">1686990514</string>
+    <string name="stella2014_libretro_android">2694497635</string>
+    <string name="superbroswar_libretro_android">1177918814</string>
+    <string name="swanstation_libretro_android">2189927838</string>
+    <string name="test_libretro_android">4072819540</string>
+    <string name="theodore_libretro_android">1794530955</string>
+    <string name="thepowdertoy_libretro_android">1431444086</string>
+    <string name="tic80_libretro_android">3523696412</string>
+    <string name="tyrquake_libretro_android">4011954349</string>
+    <string name="uw8_libretro_android">707177494</string>
+
+    <string name="uzem_libretro_android">4025363444</string>
+    <string name="vaporspec_libretro_android">62375315</string>
+    <string name="vbam_libretro_android">2529213728</string>
+    <string name="vba_next_libretro_android">3272353476</string>
+    <string name="vecx_libretro_android">3708413075</string>
+    <string name="vemulator_libretro_android">1403685916</string>
+    <string name="vice_x128_libretro_android">77282354</string>
+    <string name="vice_x64sc_libretro_android">502339610</string>
+    <string name="vice_xcbm2_libretro_android">3472472312</string>
+    <string name="vice_xcbm5x0_libretro_android">41796132</string>
+    <string name="vice_xpet_libretro_android">3282819252</string>
+    <string name="vice_xplus4_libretro_android">262861266</string>
+    <string name="vice_xscpu64_libretro_android">3181671713</string>
+    <string name="vice_xvic_libretro_android">2385615623</string>
+    <string name="virtualjaguar_libretro_android">3681754840</string>
+    <string name="virtualxt_libretro_android">1112863931</string>
+    <string name="vitaquake2_rogue_libretro_android">3746780493</string>
+    <string name="vitaquake2_xatrix_libretro_android">1734504512</string>
+    <string name="vitaquake2_zaero_libretro_android">3920496352</string>
+    <string name="vitaquake2_libretro_android">1500644696</string>
 </resources>

+ 1 - 1
app/src/main/res/values/themes.xml

@@ -8,7 +8,7 @@
         <!-- Secondary brand color. -->
         <item name="colorSecondary">@color/teal_200</item>
         <item name="colorSecondaryVariant">@color/teal_700</item>
-        <item name="android:windowBackground">@drawable/app_main_bg</item>
+        <item name="android:windowBackground">@color/black</item>
         <item name="colorOnSecondary">@color/black</item>
         <!-- Status bar color. -->
         <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>

二进制
rk_3288_system.jks