android: Convert NativeLibrary to Kotlin

This commit is contained in:
Charles Lombardo 2023-04-02 23:46:22 -04:00 committed by bunnei
parent a827486391
commit 4d9011a8f0
15 changed files with 523 additions and 766 deletions

View File

@ -1,698 +0,0 @@
/*
* Copyright 2013 Dolphin Emulator Project
* Licensed under GPLv2+
* Refer to the license.txt file included.
*/
package org.yuzu.yuzu_emu;
import android.app.Activity;
import android.app.Dialog;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.os.Bundle;
import android.text.Html;
import android.text.method.LinkMovementMethod;
import android.view.Surface;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.DialogFragment;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import org.yuzu.yuzu_emu.activities.EmulationActivity;
import org.yuzu.yuzu_emu.utils.DocumentsTree;
import org.yuzu.yuzu_emu.utils.EmulationMenuSettings;
import org.yuzu.yuzu_emu.utils.FileUtil;
import org.yuzu.yuzu_emu.utils.Log;
import java.lang.ref.WeakReference;
import java.util.Objects;
import static android.Manifest.permission.CAMERA;
import static android.Manifest.permission.RECORD_AUDIO;
/**
* Class which contains methods that interact
* with the native side of the Citra code.
*/
public final class NativeLibrary {
/**
* Default controller id for each device
*/
public static final int Player1Device = 0;
public static final int Player2Device = 1;
public static final int Player3Device = 2;
public static final int Player4Device = 3;
public static final int Player5Device = 4;
public static final int Player6Device = 5;
public static final int Player7Device = 6;
public static final int Player8Device = 7;
public static final int ConsoleDevice = 8;
public static WeakReference<EmulationActivity> sEmulationActivity = new WeakReference<>(null);
private static boolean alertResult = false;
private static String alertPromptResult = "";
private static int alertPromptButton = 0;
private static final Object alertPromptLock = new Object();
private static boolean alertPromptInProgress = false;
private static String alertPromptCaption = "";
private static int alertPromptButtonConfig = 0;
private static EditText alertPromptEditText = null;
static {
try {
System.loadLibrary("yuzu-android");
} catch (UnsatisfiedLinkError ex) {
Log.error("[NativeLibrary] " + ex.toString());
}
}
private NativeLibrary() {
// Disallows instantiation.
}
public static int openContentUri(String path, String openmode) {
if (DocumentsTree.isNativePath(path)) {
return YuzuApplication.documentsTree.openContentUri(path, openmode);
}
return FileUtil.openContentUri(YuzuApplication.getAppContext(), path, openmode);
}
public static long getSize(String path) {
if (DocumentsTree.isNativePath(path)) {
return YuzuApplication.documentsTree.getFileSize(path);
}
return FileUtil.getFileSize(YuzuApplication.getAppContext(), path);
}
/**
* Handles button press events for a gamepad.
*
* @param Device The input descriptor of the gamepad.
* @param Button Key code identifying which button was pressed.
* @param Action Mask identifying which action is happening (button pressed down, or button released).
* @return If we handled the button press.
*/
public static native boolean onGamePadButtonEvent(int Device, int Button, int Action);
/**
* Handles joystick movement events.
*
* @param Device The device ID of the gamepad.
* @param Axis The axis ID
* @param x_axis The value of the x-axis represented by the given ID.
* @param y_axis The value of the y-axis represented by the given ID.
*/
public static native boolean onGamePadJoystickEvent(int Device, int Axis, float x_axis, float y_axis);
/**
* Handles motion events.
*
* @param delta_timestamp The finger id corresponding to this event
* @param gyro_x,gyro_y,gyro_z The value of the accelerometer sensor.
* @param accel_x,accel_y,accel_z The value of the y-axis
*/
public static native boolean onGamePadMotionEvent(int Device, long delta_timestamp, float gyro_x, float gyro_y,
float gyro_z, float accel_x, float accel_y, float accel_z);
/**
* Signals and load a nfc tag
*
* @param data Byte array containing all the data from a nfc tag
*/
public static native boolean onReadNfcTag(byte[] data);
/**
* Removes current loaded nfc tag
*/
public static native boolean onRemoveNfcTag();
/**
* Handles touch press events.
*
* @param finger_id The finger id corresponding to this event
* @param x_axis The value of the x-axis.
* @param y_axis The value of the y-axis.
*/
public static native void onTouchPressed(int finger_id, float x_axis, float y_axis);
/**
* Handles touch movement.
*
* @param x_axis The value of the instantaneous x-axis.
* @param y_axis The value of the instantaneous y-axis.
*/
public static native void onTouchMoved(int finger_id, float x_axis, float y_axis);
/**
* Handles touch release events.
*
* @param finger_id The finger id corresponding to this event
*/
public static native void onTouchReleased(int finger_id);
public static native void ReloadSettings();
public static native String GetUserSetting(String gameID, String Section, String Key);
public static native void SetUserSetting(String gameID, String Section, String Key, String Value);
public static native void InitGameIni(String gameID);
/**
* Gets the embedded icon within the given ROM.
*
* @param filename the file path to the ROM.
* @return a byte array containing the JPEG data for the icon.
*/
public static native byte[] GetIcon(String filename);
/**
* Gets the embedded title of the given ISO/ROM.
*
* @param filename The file path to the ISO/ROM.
* @return the embedded title of the ISO/ROM.
*/
public static native String GetTitle(String filename);
public static native String GetDescription(String filename);
public static native String GetGameId(String filename);
public static native String GetRegions(String filename);
public static native String GetCompany(String filename);
public static native String GetGitRevision();
public static native void SetAppDirectory(String directory);
public static native void InitializeGpuDriver(String hookLibDir, String customDriverDir, String customDriverName, String fileRedirectDir);
public static native boolean ReloadKeys();
public static native void InitializeEmulation();
public static native int DefaultCPUCore();
/**
* Begins emulation.
*/
public static native void Run(String path);
/**
* Begins emulation from the specified savestate.
*/
public static native void Run(String path, String savestatePath, boolean deleteSavestate);
// Surface Handling
public static native void SurfaceChanged(Surface surf);
public static native void SurfaceDestroyed();
/**
* Unpauses emulation from a paused state.
*/
public static native void UnPauseEmulation();
/**
* Pauses emulation.
*/
public static native void PauseEmulation();
/**
* Stops emulation.
*/
public static native void StopEmulation();
/**
* Resets the in-memory ROM metadata cache.
*/
public static native void ResetRomMetadata();
/**
* Returns true if emulation is running (or is paused).
*/
public static native boolean IsRunning();
/**
* Returns the performance stats for the current game
**/
public static native double[] GetPerfStats();
/**
* Notifies the core emulation that the orientation has changed.
*/
public static native void NotifyOrientationChange(int layout_option, int rotation);
public enum CoreError {
ErrorSystemFiles,
ErrorSavestate,
ErrorUnknown,
}
private static boolean coreErrorAlertResult = false;
private static final Object coreErrorAlertLock = new Object();
public static class CoreErrorDialogFragment extends DialogFragment {
static CoreErrorDialogFragment newInstance(String title, String message) {
CoreErrorDialogFragment frag = new CoreErrorDialogFragment();
Bundle args = new Bundle();
args.putString("title", title);
args.putString("message", message);
frag.setArguments(args);
return frag;
}
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final Activity emulationActivity = Objects.requireNonNull(getActivity());
final String title = Objects.requireNonNull(Objects.requireNonNull(getArguments()).getString("title"));
final String message = Objects.requireNonNull(Objects.requireNonNull(getArguments()).getString("message"));
return new MaterialAlertDialogBuilder(emulationActivity)
.setTitle(title)
.setMessage(message)
.setPositiveButton(R.string.continue_button, (dialog, which) -> {
coreErrorAlertResult = true;
synchronized (coreErrorAlertLock) {
coreErrorAlertLock.notify();
}
})
.setNegativeButton(R.string.abort_button, (dialog, which) -> {
coreErrorAlertResult = false;
synchronized (coreErrorAlertLock) {
coreErrorAlertLock.notify();
}
}).setOnDismissListener(dialog -> {
coreErrorAlertResult = true;
synchronized (coreErrorAlertLock) {
coreErrorAlertLock.notify();
}
}).create();
}
}
private static void OnCoreErrorImpl(String title, String message) {
final EmulationActivity emulationActivity = sEmulationActivity.get();
if (emulationActivity == null) {
Log.error("[NativeLibrary] EmulationActivity not present");
return;
}
CoreErrorDialogFragment fragment = CoreErrorDialogFragment.newInstance(title, message);
fragment.show(emulationActivity.getSupportFragmentManager(), "coreError");
}
/**
* Handles a core error.
*
* @return true: continue; false: abort
*/
public static boolean OnCoreError(CoreError error, String details) {
final EmulationActivity emulationActivity = sEmulationActivity.get();
if (emulationActivity == null) {
Log.error("[NativeLibrary] EmulationActivity not present");
return false;
}
String title, message;
switch (error) {
case ErrorSystemFiles: {
title = emulationActivity.getString(R.string.system_archive_not_found);
message = emulationActivity.getString(R.string.system_archive_not_found_message, details.isEmpty() ? emulationActivity.getString(R.string.system_archive_general) : details);
break;
}
case ErrorSavestate: {
title = emulationActivity.getString(R.string.save_load_error);
message = details;
break;
}
case ErrorUnknown: {
title = emulationActivity.getString(R.string.fatal_error);
message = emulationActivity.getString(R.string.fatal_error_message);
break;
}
default: {
return true;
}
}
// Show the AlertDialog on the main thread.
emulationActivity.runOnUiThread(() -> OnCoreErrorImpl(title, message));
// Wait for the lock to notify that it is complete.
synchronized (coreErrorAlertLock) {
try {
coreErrorAlertLock.wait();
} catch (Exception ignored) {
}
}
return coreErrorAlertResult;
}
public static boolean isPortraitMode() {
return YuzuApplication.getAppContext().getResources().getConfiguration().orientation ==
Configuration.ORIENTATION_PORTRAIT;
}
public static int landscapeScreenLayout() {
return EmulationMenuSettings.getLandscapeScreenLayout();
}
public static boolean displayAlertMsg(final String caption, final String text,
final boolean yesNo) {
Log.error("[NativeLibrary] Alert: " + text);
final EmulationActivity emulationActivity = sEmulationActivity.get();
boolean result = false;
if (emulationActivity == null) {
Log.warning("[NativeLibrary] EmulationActivity is null, can't do panic alert.");
} else {
// Create object used for waiting.
final Object lock = new Object();
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(emulationActivity)
.setTitle(caption)
.setMessage(text);
// If not yes/no dialog just have one button that dismisses modal,
// otherwise have a yes and no button that sets alertResult accordingly.
if (!yesNo) {
builder
.setCancelable(false)
.setPositiveButton(android.R.string.ok, (dialog, whichButton) ->
{
dialog.dismiss();
synchronized (lock) {
lock.notify();
}
});
} else {
alertResult = false;
builder
.setPositiveButton(android.R.string.yes, (dialog, whichButton) ->
{
alertResult = true;
dialog.dismiss();
synchronized (lock) {
lock.notify();
}
})
.setNegativeButton(android.R.string.no, (dialog, whichButton) ->
{
alertResult = false;
dialog.dismiss();
synchronized (lock) {
lock.notify();
}
});
}
// Show the AlertDialog on the main thread.
emulationActivity.runOnUiThread(builder::show);
// Wait for the lock to notify that it is complete.
synchronized (lock) {
try {
lock.wait();
} catch (Exception e) {
}
}
if (yesNo)
result = alertResult;
}
return result;
}
public static void retryDisplayAlertPrompt() {
if (!alertPromptInProgress) {
return;
}
displayAlertPromptImpl(alertPromptCaption, alertPromptEditText.getText().toString(), alertPromptButtonConfig).show();
}
public static String displayAlertPrompt(String caption, String text, int buttonConfig) {
alertPromptCaption = caption;
alertPromptButtonConfig = buttonConfig;
alertPromptInProgress = true;
// Show the AlertDialog on the main thread
sEmulationActivity.get().runOnUiThread(() -> displayAlertPromptImpl(alertPromptCaption, text, alertPromptButtonConfig).show());
// Wait for the lock to notify that it is complete
synchronized (alertPromptLock) {
try {
alertPromptLock.wait();
} catch (Exception e) {
}
}
alertPromptInProgress = false;
return alertPromptResult;
}
public static MaterialAlertDialogBuilder displayAlertPromptImpl(String caption, String text, int buttonConfig) {
final EmulationActivity emulationActivity = sEmulationActivity.get();
alertPromptResult = "";
alertPromptButton = 0;
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params.leftMargin = params.rightMargin = YuzuApplication.getAppContext().getResources().getDimensionPixelSize(R.dimen.dialog_margin);
// Set up the input
alertPromptEditText = new EditText(YuzuApplication.getAppContext());
alertPromptEditText.setText(text);
alertPromptEditText.setSingleLine();
alertPromptEditText.setLayoutParams(params);
FrameLayout container = new FrameLayout(emulationActivity);
container.addView(alertPromptEditText);
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(emulationActivity)
.setTitle(caption)
.setView(container)
.setPositiveButton(android.R.string.ok, (dialogInterface, i) ->
{
alertPromptButton = buttonConfig;
alertPromptResult = alertPromptEditText.getText().toString();
synchronized (alertPromptLock) {
alertPromptLock.notifyAll();
}
})
.setOnDismissListener(dialogInterface ->
{
alertPromptResult = "";
synchronized (alertPromptLock) {
alertPromptLock.notifyAll();
}
});
if (buttonConfig > 0) {
builder.setNegativeButton(android.R.string.cancel, (dialogInterface, i) ->
{
alertPromptResult = "";
synchronized (alertPromptLock) {
alertPromptLock.notifyAll();
}
});
}
return builder;
}
public static int alertPromptButton() {
return alertPromptButton;
}
public static void exitEmulationActivity(int resultCode) {
final int Success = 0;
final int ErrorNotInitialized = 1;
final int ErrorGetLoader = 2;
final int ErrorSystemFiles = 3;
final int ErrorSharedFont = 4;
final int ErrorVideoCore = 5;
final int ErrorUnknown = 6;
final int ErrorLoader = 7;
int captionId;
int descriptionId;
switch (resultCode) {
case ErrorVideoCore:
captionId = R.string.loader_error_video_core;
descriptionId = R.string.loader_error_video_core_description;
break;
default:
captionId = R.string.loader_error_encrypted;
descriptionId = R.string.loader_error_encrypted_roms_description;
if (!ReloadKeys()) {
descriptionId = R.string.loader_error_encrypted_keys_description;
}
break;
}
final EmulationActivity emulationActivity = sEmulationActivity.get();
if (emulationActivity == null) {
Log.warning("[NativeLibrary] EmulationActivity is null, can't exit.");
return;
}
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(emulationActivity)
.setTitle(captionId)
.setMessage(Html.fromHtml(emulationActivity.getString(descriptionId), Html.FROM_HTML_MODE_LEGACY))
.setPositiveButton(android.R.string.ok, (dialog, whichButton) -> emulationActivity.finish())
.setOnDismissListener(dialogInterface -> emulationActivity.finish());
emulationActivity.runOnUiThread(() -> {
AlertDialog alert = builder.create();
alert.show();
((TextView) alert.findViewById(android.R.id.message)).setMovementMethod(LinkMovementMethod.getInstance());
});
}
public static void setEmulationActivity(EmulationActivity emulationActivity) {
Log.verbose("[NativeLibrary] Registering EmulationActivity.");
sEmulationActivity = new WeakReference<>(emulationActivity);
}
public static void clearEmulationActivity() {
Log.verbose("[NativeLibrary] Unregistering EmulationActivity.");
sEmulationActivity.clear();
}
private static final Object cameraPermissionLock = new Object();
private static boolean cameraPermissionGranted = false;
public static final int REQUEST_CODE_NATIVE_CAMERA = 800;
public static boolean RequestCameraPermission() {
final EmulationActivity emulationActivity = sEmulationActivity.get();
if (emulationActivity == null) {
Log.error("[NativeLibrary] EmulationActivity not present");
return false;
}
if (ContextCompat.checkSelfPermission(emulationActivity, CAMERA) == PackageManager.PERMISSION_GRANTED) {
// Permission already granted
return true;
}
emulationActivity.requestPermissions(new String[]{CAMERA}, REQUEST_CODE_NATIVE_CAMERA);
// Wait until result is returned
synchronized (cameraPermissionLock) {
try {
cameraPermissionLock.wait();
} catch (InterruptedException ignored) {
}
}
return cameraPermissionGranted;
}
public static void CameraPermissionResult(boolean granted) {
cameraPermissionGranted = granted;
synchronized (cameraPermissionLock) {
cameraPermissionLock.notify();
}
}
private static final Object micPermissionLock = new Object();
private static boolean micPermissionGranted = false;
public static final int REQUEST_CODE_NATIVE_MIC = 900;
public static boolean RequestMicPermission() {
final EmulationActivity emulationActivity = sEmulationActivity.get();
if (emulationActivity == null) {
Log.error("[NativeLibrary] EmulationActivity not present");
return false;
}
if (ContextCompat.checkSelfPermission(emulationActivity, RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED) {
// Permission already granted
return true;
}
emulationActivity.requestPermissions(new String[]{RECORD_AUDIO}, REQUEST_CODE_NATIVE_MIC);
// Wait until result is returned
synchronized (micPermissionLock) {
try {
micPermissionLock.wait();
} catch (InterruptedException ignored) {
}
}
return micPermissionGranted;
}
public static void MicPermissionResult(boolean granted) {
micPermissionGranted = granted;
synchronized (micPermissionLock) {
micPermissionLock.notify();
}
}
/**
* Logs the Citra version, Android version and, CPU.
*/
public static native void LogDeviceInfo();
/**
* Submits inline keyboard text. Called on input for buttons that result text.
* @param text Text to submit to the inline software keyboard implementation.
*/
public static native void SubmitInlineKeyboardText(String text);
/**
* Submits inline keyboard input. Used to indicate keys pressed that are not text.
* @param key_code Android Key Code associated with the keyboard input.
*/
public static native void SubmitInlineKeyboardInput(int key_code);
/**
* Button type for use in onTouchEvent
*/
public static final class ButtonType {
public static final int BUTTON_A = 0;
public static final int BUTTON_B = 1;
public static final int BUTTON_X = 2;
public static final int BUTTON_Y = 3;
public static final int STICK_L = 4;
public static final int STICK_R = 5;
public static final int TRIGGER_L = 6;
public static final int TRIGGER_R = 7;
public static final int TRIGGER_ZL = 8;
public static final int TRIGGER_ZR = 9;
public static final int BUTTON_PLUS = 10;
public static final int BUTTON_MINUS = 11;
public static final int DPAD_LEFT = 12;
public static final int DPAD_UP = 13;
public static final int DPAD_RIGHT = 14;
public static final int DPAD_DOWN = 15;
public static final int BUTTON_SL = 16;
public static final int BUTTON_SR = 17;
public static final int BUTTON_HOME = 18;
public static final int BUTTON_CAPTURE = 19;
}
/**
* Stick type for use in onTouchEvent
*/
public static final class StickType {
public static final int STICK_L = 0;
public static final int STICK_R = 1;
}
/**
* Button states
*/
public static final class ButtonState {
public static final int RELEASED = 0;
public static final int PRESSED = 1;
}
}

View File

@ -0,0 +1,463 @@
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
package org.yuzu.yuzu_emu
import android.app.Dialog
import android.content.DialogInterface
import android.os.Bundle
import android.text.Html
import android.text.method.LinkMovementMethod
import android.view.Surface
import android.view.View
import android.widget.TextView
import androidx.fragment.app.DialogFragment
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import org.yuzu.yuzu_emu.YuzuApplication.Companion.appContext
import org.yuzu.yuzu_emu.activities.EmulationActivity
import org.yuzu.yuzu_emu.utils.DocumentsTree.Companion.isNativePath
import org.yuzu.yuzu_emu.utils.FileUtil.getFileSize
import org.yuzu.yuzu_emu.utils.FileUtil.openContentUri
import org.yuzu.yuzu_emu.utils.Log.error
import org.yuzu.yuzu_emu.utils.Log.verbose
import org.yuzu.yuzu_emu.utils.Log.warning
import org.yuzu.yuzu_emu.utils.SerializableHelper.serializable
import java.lang.ref.WeakReference
/**
* Class which contains methods that interact
* with the native side of the Yuzu code.
*/
object NativeLibrary {
/**
* Default controller id for each device
*/
const val Player1Device = 0
const val Player2Device = 1
const val Player3Device = 2
const val Player4Device = 3
const val Player5Device = 4
const val Player6Device = 5
const val Player7Device = 6
const val Player8Device = 7
const val ConsoleDevice = 8
var sEmulationActivity = WeakReference<EmulationActivity?>(null)
init {
try {
System.loadLibrary("yuzu-android")
} catch (ex: UnsatisfiedLinkError) {
error("[NativeLibrary] $ex")
}
}
@JvmStatic
fun openContentUri(path: String?, openmode: String?): Int {
return if (isNativePath(path!!)) {
YuzuApplication.documentsTree!!.openContentUri(path, openmode)
} else openContentUri(appContext, path, openmode)
}
@JvmStatic
fun getSize(path: String?): Long {
return if (isNativePath(path!!)) {
YuzuApplication.documentsTree!!.getFileSize(path)
} else getFileSize(appContext, path)
}
/**
* Handles button press events for a gamepad.
*
* @param Device The input descriptor of the gamepad.
* @param Button Key code identifying which button was pressed.
* @param Action Mask identifying which action is happening (button pressed down, or button released).
* @return If we handled the button press.
*/
external fun onGamePadButtonEvent(Device: Int, Button: Int, Action: Int): Boolean
/**
* Handles joystick movement events.
*
* @param Device The device ID of the gamepad.
* @param Axis The axis ID
* @param x_axis The value of the x-axis represented by the given ID.
* @param y_axis The value of the y-axis represented by the given ID.
*/
external fun onGamePadJoystickEvent(
Device: Int,
Axis: Int,
x_axis: Float,
y_axis: Float
): Boolean
/**
* Handles motion events.
*
* @param delta_timestamp The finger id corresponding to this event
* @param gyro_x,gyro_y,gyro_z The value of the accelerometer sensor.
* @param accel_x,accel_y,accel_z The value of the y-axis
*/
external fun onGamePadMotionEvent(
Device: Int,
delta_timestamp: Long,
gyro_x: Float,
gyro_y: Float,
gyro_z: Float,
accel_x: Float,
accel_y: Float,
accel_z: Float
): Boolean
/**
* Signals and load a nfc tag
*
* @param data Byte array containing all the data from a nfc tag
*/
external fun onReadNfcTag(data: ByteArray?): Boolean
/**
* Removes current loaded nfc tag
*/
external fun onRemoveNfcTag(): Boolean
/**
* Handles touch press events.
*
* @param finger_id The finger id corresponding to this event
* @param x_axis The value of the x-axis.
* @param y_axis The value of the y-axis.
*/
external fun onTouchPressed(finger_id: Int, x_axis: Float, y_axis: Float)
/**
* Handles touch movement.
*
* @param x_axis The value of the instantaneous x-axis.
* @param y_axis The value of the instantaneous y-axis.
*/
external fun onTouchMoved(finger_id: Int, x_axis: Float, y_axis: Float)
/**
* Handles touch release events.
*
* @param finger_id The finger id corresponding to this event
*/
external fun onTouchReleased(finger_id: Int)
external fun reloadSettings()
external fun getUserSetting(gameID: String?, Section: String?, Key: String?): String?
external fun setUserSetting(gameID: String?, Section: String?, Key: String?, Value: String?)
external fun initGameIni(gameID: String?)
/**
* Gets the embedded icon within the given ROM.
*
* @param filename the file path to the ROM.
* @return a byte array containing the JPEG data for the icon.
*/
external fun getIcon(filename: String): ByteArray
/**
* Gets the embedded title of the given ISO/ROM.
*
* @param filename The file path to the ISO/ROM.
* @return the embedded title of the ISO/ROM.
*/
external fun getTitle(filename: String): String
external fun getDescription(filename: String): String
external fun getGameId(filename: String): String
external fun getRegions(filename: String): String
external fun getCompany(filename: String): String
external fun setAppDirectory(directory: String)
external fun initializeGpuDriver(
hookLibDir: String?,
customDriverDir: String?,
customDriverName: String?,
fileRedirectDir: String?
)
external fun reloadKeys(): Boolean
external fun initializeEmulation()
external fun defaultCPUCore(): Int
/**
* Begins emulation.
*/
external fun run(path: String?)
/**
* Begins emulation from the specified savestate.
*/
external fun run(path: String?, savestatePath: String?, deleteSavestate: Boolean)
// Surface Handling
external fun surfaceChanged(surf: Surface?)
external fun surfaceDestroyed()
external fun doFrame()
/**
* Unpauses emulation from a paused state.
*/
external fun unPauseEmulation()
/**
* Pauses emulation.
*/
external fun pauseEmulation()
/**
* Stops emulation.
*/
external fun stopEmulation()
/**
* Resets the in-memory ROM metadata cache.
*/
external fun resetRomMetadata()
/**
* Returns true if emulation is running (or is paused).
*/
external fun isRunning(): Boolean
/**
* Returns the performance stats for the current game
*/
external fun getPerfStats(): DoubleArray
/**
* Notifies the core emulation that the orientation has changed.
*/
external fun notifyOrientationChange(layout_option: Int, rotation: Int)
enum class CoreError {
ErrorSystemFiles,
ErrorSavestate,
ErrorUnknown
}
private var coreErrorAlertResult = false
private val coreErrorAlertLock = Object()
class CoreErrorDialogFragment : DialogFragment() {
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val title = requireArguments().serializable<String>("title")
val message = requireArguments().serializable<String>("message")
return MaterialAlertDialogBuilder(requireActivity())
.setTitle(title)
.setMessage(message)
.setPositiveButton(R.string.continue_button, null)
.setNegativeButton(R.string.abort_button) { _: DialogInterface?, _: Int ->
coreErrorAlertResult = false
synchronized(coreErrorAlertLock) { coreErrorAlertLock.notify() }
}
.create()
}
override fun onDismiss(dialog: DialogInterface) {
coreErrorAlertResult = true
synchronized(coreErrorAlertLock) { coreErrorAlertLock.notify() }
}
companion object {
fun newInstance(title: String?, message: String?): CoreErrorDialogFragment {
val frag = CoreErrorDialogFragment()
val args = Bundle()
args.putString("title", title)
args.putString("message", message)
frag.arguments = args
return frag
}
}
}
private fun onCoreErrorImpl(title: String, message: String) {
val emulationActivity = sEmulationActivity.get()
if (emulationActivity == null) {
error("[NativeLibrary] EmulationActivity not present")
return
}
val fragment = CoreErrorDialogFragment.newInstance(title, message)
fragment.show(emulationActivity.supportFragmentManager, "coreError")
}
/**
* Handles a core error.
*
* @return true: continue; false: abort
*/
fun onCoreError(error: CoreError?, details: String): Boolean {
val emulationActivity = sEmulationActivity.get()
if (emulationActivity == null) {
error("[NativeLibrary] EmulationActivity not present")
return false
}
val title: String
val message: String
when (error) {
CoreError.ErrorSystemFiles -> {
title = emulationActivity.getString(R.string.system_archive_not_found)
message = emulationActivity.getString(
R.string.system_archive_not_found_message,
details.ifEmpty { emulationActivity.getString(R.string.system_archive_general) }
)
}
CoreError.ErrorSavestate -> {
title = emulationActivity.getString(R.string.save_load_error)
message = details
}
CoreError.ErrorUnknown -> {
title = emulationActivity.getString(R.string.fatal_error)
message = emulationActivity.getString(R.string.fatal_error_message)
}
else -> {
return true
}
}
// Show the AlertDialog on the main thread.
emulationActivity.runOnUiThread(Runnable { onCoreErrorImpl(title, message) })
// Wait for the lock to notify that it is complete.
synchronized(coreErrorAlertLock) { coreErrorAlertLock.wait() }
return coreErrorAlertResult
}
@JvmStatic
fun exitEmulationActivity(resultCode: Int) {
val Success = 0
val ErrorNotInitialized = 1
val ErrorGetLoader = 2
val ErrorSystemFiles = 3
val ErrorSharedFont = 4
val ErrorVideoCore = 5
val ErrorUnknown = 6
val ErrorLoader = 7
val captionId: Int
var descriptionId: Int
when (resultCode) {
ErrorVideoCore -> {
captionId = R.string.loader_error_video_core
descriptionId = R.string.loader_error_video_core_description
}
else -> {
captionId = R.string.loader_error_encrypted
descriptionId = R.string.loader_error_encrypted_roms_description
if (!reloadKeys()) {
descriptionId = R.string.loader_error_encrypted_keys_description
}
}
}
val emulationActivity = sEmulationActivity.get()
if (emulationActivity == null) {
warning("[NativeLibrary] EmulationActivity is null, can't exit.")
return
}
val builder = MaterialAlertDialogBuilder(emulationActivity)
.setTitle(captionId)
.setMessage(
Html.fromHtml(
emulationActivity.getString(descriptionId),
Html.FROM_HTML_MODE_LEGACY
)
)
.setPositiveButton(android.R.string.ok) { _: DialogInterface?, _: Int -> emulationActivity.finish() }
.setOnDismissListener { emulationActivity.finish() }
emulationActivity.runOnUiThread {
val alert = builder.create()
alert.show()
(alert.findViewById<View>(android.R.id.message) as TextView).movementMethod =
LinkMovementMethod.getInstance()
}
}
fun setEmulationActivity(emulationActivity: EmulationActivity?) {
verbose("[NativeLibrary] Registering EmulationActivity.")
sEmulationActivity = WeakReference(emulationActivity)
}
fun clearEmulationActivity() {
verbose("[NativeLibrary] Unregistering EmulationActivity.")
sEmulationActivity.clear()
}
/**
* Logs the Yuzu version, Android version and, CPU.
*/
external fun logDeviceInfo()
/**
* Submits inline keyboard text. Called on input for buttons that result text.
* @param text Text to submit to the inline software keyboard implementation.
*/
external fun submitInlineKeyboardText(text: String?)
/**
* Submits inline keyboard input. Used to indicate keys pressed that are not text.
* @param key_code Android Key Code associated with the keyboard input.
*/
external fun submitInlineKeyboardInput(key_code: Int)
/**
* Button type for use in onTouchEvent
*/
object ButtonType {
const val BUTTON_A = 0
const val BUTTON_B = 1
const val BUTTON_X = 2
const val BUTTON_Y = 3
const val STICK_L = 4
const val STICK_R = 5
const val TRIGGER_L = 6
const val TRIGGER_R = 7
const val TRIGGER_ZL = 8
const val TRIGGER_ZR = 9
const val BUTTON_PLUS = 10
const val BUTTON_MINUS = 11
const val DPAD_LEFT = 12
const val DPAD_UP = 13
const val DPAD_RIGHT = 14
const val DPAD_DOWN = 15
const val BUTTON_SL = 16
const val BUTTON_SR = 17
const val BUTTON_HOME = 18
const val BUTTON_CAPTURE = 19
}
/**
* Stick type for use in onTouchEvent
*/
object StickType {
const val STICK_L = 0
const val STICK_R = 1
}
/**
* Button states
*/
object ButtonState {
const val RELEASED = 0
const val PRESSED = 1
}
}

View File

@ -40,7 +40,7 @@ class YuzuApplication : Application() {
documentsTree = DocumentsTree() documentsTree = DocumentsTree()
DirectoryInitialization.start(applicationContext) DirectoryInitialization.start(applicationContext)
GpuDriverHelper.initializeDriverParameters(applicationContext) GpuDriverHelper.initializeDriverParameters(applicationContext)
NativeLibrary.LogDeviceInfo() NativeLibrary.logDeviceInfo()
// TODO(bunnei): Disable notifications until we support app suspension. // TODO(bunnei): Disable notifications until we support app suspension.
//createNotificationChannel(); //createNotificationChannel();

View File

@ -100,10 +100,10 @@ open class EmulationActivity : AppCompatActivity() {
val textChar = event.unicodeChar val textChar = event.unicodeChar
if (textChar == 0) { if (textChar == 0) {
// No text, button input. // No text, button input.
NativeLibrary.SubmitInlineKeyboardInput(keyCode) NativeLibrary.submitInlineKeyboardInput(keyCode)
} else { } else {
// Text submitted. // Text submitted.
NativeLibrary.SubmitInlineKeyboardText(textChar.toChar().toString()) NativeLibrary.submitInlineKeyboardText(textChar.toChar().toString())
} }
} }
} }
@ -132,9 +132,6 @@ open class EmulationActivity : AppCompatActivity() {
private fun restoreState(savedInstanceState: Bundle) { private fun restoreState(savedInstanceState: Bundle) {
game = savedInstanceState.parcelable(EXTRA_SELECTED_GAME)!! game = savedInstanceState.parcelable(EXTRA_SELECTED_GAME)!!
// If an alert prompt was in progress when state was restored, retry displaying it
NativeLibrary.retryDisplayAlertPrompt()
} }
private fun enableFullscreenImmersive() { private fun enableFullscreenImmersive() {

View File

@ -93,7 +93,7 @@ class GameAdapter(private val activity: AppCompatActivity, var games: ArrayList<
} }
private fun decodeGameIcon(uri: String): Bitmap? { private fun decodeGameIcon(uri: String): Bitmap? {
val data = NativeLibrary.GetIcon(uri) val data = NativeLibrary.getIcon(uri)
return BitmapFactory.decodeByteArray( return BitmapFactory.decodeByteArray(
data, data,
0, 0,

View File

@ -48,7 +48,7 @@ object SoftwareKeyboard {
} }
// No longer visible, submit the result. // No longer visible, submit the result.
NativeLibrary.SubmitInlineKeyboardInput(KeyEvent.KEYCODE_ENTER) NativeLibrary.submitInlineKeyboardInput(KeyEvent.KEYCODE_ENTER)
} }
}, delayMs.toLong()) }, delayMs.toLong())
} }

View File

@ -85,7 +85,7 @@ class SettingsActivity : AppCompatActivity(), SettingsActivityView {
presenter.onStop(isFinishing) presenter.onStop(isFinishing)
// Update framebuffer layout when closing the settings // Update framebuffer layout when closing the settings
NativeLibrary.NotifyOrientationChange( NativeLibrary.notifyOrientationChange(
EmulationMenuSettings.landscapeScreenLayout, EmulationMenuSettings.landscapeScreenLayout,
windowManager.defaultDisplay.rotation windowManager.defaultDisplay.rotation
) )

View File

@ -63,7 +63,7 @@ class SettingsActivityPresenter(private val activityView: SettingsActivityView)
Log.debug("[SettingsActivity] Settings activity stopping. Saving settings to INI...") Log.debug("[SettingsActivity] Settings activity stopping. Saving settings to INI...")
settings.saveSettings(activityView) settings.saveSettings(activityView)
} }
NativeLibrary.ReloadSettings() NativeLibrary.reloadSettings()
} }
fun onSettingChanged() { fun onSettingChanged() {

View File

@ -155,7 +155,7 @@ object SettingsFile {
val sortedKeySet: Set<String> = TreeSet(settings.keys) val sortedKeySet: Set<String> = TreeSet(settings.keys)
for (settingKey in sortedKeySet) { for (settingKey in sortedKeySet) {
val setting = settings[settingKey] val setting = settings[settingKey]
NativeLibrary.SetUserSetting( NativeLibrary.setUserSetting(
gameId, mapSectionNameFromIni( gameId, mapSectionNameFromIni(
section.name section.name
), setting!!.key, setting.valueAsString ), setting!!.key, setting.valueAsString

View File

@ -182,7 +182,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
val FRAMETIME = 2 val FRAMETIME = 2
val SPEED = 3 val SPEED = 3
perfStatsUpdater = { perfStatsUpdater = {
val perfStats = NativeLibrary.GetPerfStats() val perfStats = NativeLibrary.getPerfStats()
if (perfStats[FPS] > 0 && _binding != null) { if (perfStats[FPS] > 0 && _binding != null) {
binding.showFpsText.text = String.format("FPS: %.1f", perfStats[FPS]) binding.showFpsText.text = String.format("FPS: %.1f", perfStats[FPS])
} }
@ -333,7 +333,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
if (state != State.STOPPED) { if (state != State.STOPPED) {
Log.debug("[EmulationFragment] Stopping emulation.") Log.debug("[EmulationFragment] Stopping emulation.")
state = State.STOPPED state = State.STOPPED
NativeLibrary.StopEmulation() NativeLibrary.stopEmulation()
} else { } else {
Log.warning("[EmulationFragment] Stop called while already stopped.") Log.warning("[EmulationFragment] Stop called while already stopped.")
} }
@ -347,8 +347,8 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
Log.debug("[EmulationFragment] Pausing emulation.") Log.debug("[EmulationFragment] Pausing emulation.")
// Release the surface before pausing, since emulation has to be running for that. // Release the surface before pausing, since emulation has to be running for that.
NativeLibrary.SurfaceDestroyed() NativeLibrary.surfaceDestroyed()
NativeLibrary.PauseEmulation() NativeLibrary.pauseEmulation()
} else { } else {
Log.warning("[EmulationFragment] Pause called while already paused.") Log.warning("[EmulationFragment] Pause called while already paused.")
} }
@ -357,7 +357,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
@Synchronized @Synchronized
fun run(isActivityRecreated: Boolean) { fun run(isActivityRecreated: Boolean) {
if (isActivityRecreated) { if (isActivityRecreated) {
if (NativeLibrary.IsRunning()) { if (NativeLibrary.isRunning()) {
state = State.PAUSED state = State.PAUSED
} }
} else { } else {
@ -390,7 +390,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
Log.debug("[EmulationFragment] Surface destroyed.") Log.debug("[EmulationFragment] Surface destroyed.")
when (state) { when (state) {
State.RUNNING -> { State.RUNNING -> {
NativeLibrary.SurfaceDestroyed() NativeLibrary.surfaceDestroyed()
state = State.PAUSED state = State.PAUSED
} }
State.PAUSED -> Log.warning("[EmulationFragment] Surface cleared while emulation paused.") State.PAUSED -> Log.warning("[EmulationFragment] Surface cleared while emulation paused.")
@ -403,17 +403,17 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
runWhenSurfaceIsValid = false runWhenSurfaceIsValid = false
when (state) { when (state) {
State.STOPPED -> { State.STOPPED -> {
NativeLibrary.SurfaceChanged(surface) NativeLibrary.surfaceChanged(surface)
val mEmulationThread = Thread({ val mEmulationThread = Thread({
Log.debug("[EmulationFragment] Starting emulation thread.") Log.debug("[EmulationFragment] Starting emulation thread.")
NativeLibrary.Run(mGamePath) NativeLibrary.run(mGamePath)
}, "NativeEmulation") }, "NativeEmulation")
mEmulationThread.start() mEmulationThread.start()
} }
State.PAUSED -> { State.PAUSED -> {
Log.debug("[EmulationFragment] Resuming emulation.") Log.debug("[EmulationFragment] Resuming emulation.")
NativeLibrary.SurfaceChanged(surface) NativeLibrary.surfaceChanged(surface)
NativeLibrary.UnPauseEmulation() NativeLibrary.unPauseEmulation()
} }
else -> Log.debug("[EmulationFragment] Bug, run called while already running.") else -> Log.debug("[EmulationFragment] Bug, run called while already running.")
} }

View File

@ -142,7 +142,7 @@ class MainActivity : AppCompatActivity(), MainView {
private fun refreshFragment() { private fun refreshFragment() {
if (platformGamesFragment != null) { if (platformGamesFragment != null) {
NativeLibrary.ResetRomMetadata() NativeLibrary.resetRomMetadata()
platformGamesFragment!!.refresh() platformGamesFragment!!.refresh()
} }
} }
@ -194,7 +194,7 @@ class MainActivity : AppCompatActivity(), MainView {
val dstPath = DirectoryInitialization.userDirectory + "/keys/" val dstPath = DirectoryInitialization.userDirectory + "/keys/"
if (FileUtil.copyUriToInternalStorage(this, result, dstPath, "prod.keys")) { if (FileUtil.copyUriToInternalStorage(this, result, dstPath, "prod.keys")) {
if (NativeLibrary.ReloadKeys()) { if (NativeLibrary.reloadKeys()) {
Toast.makeText( Toast.makeText(
this, this,
R.string.install_keys_success, R.string.install_keys_success,
@ -225,7 +225,7 @@ class MainActivity : AppCompatActivity(), MainView {
val dstPath = DirectoryInitialization.userDirectory + "/keys/" val dstPath = DirectoryInitialization.userDirectory + "/keys/"
if (FileUtil.copyUriToInternalStorage(this, result, dstPath, "key_retail.bin")) { if (FileUtil.copyUriToInternalStorage(this, result, dstPath, "key_retail.bin")) {
if (NativeLibrary.ReloadKeys()) { if (NativeLibrary.reloadKeys()) {
Toast.makeText( Toast.makeText(
this, this,
R.string.install_keys_success, R.string.install_keys_success,

View File

@ -16,7 +16,7 @@ object DirectoryInitialization {
fun start(context: Context) { fun start(context: Context) {
if (!areDirectoriesReady) { if (!areDirectoriesReady) {
initializeInternalStorage(context) initializeInternalStorage(context)
NativeLibrary.InitializeEmulation() NativeLibrary.initializeEmulation()
areDirectoriesReady = true areDirectoriesReady = true
} }
} }
@ -30,7 +30,7 @@ object DirectoryInitialization {
private fun initializeInternalStorage(context: Context) { private fun initializeInternalStorage(context: Context) {
try { try {
userPath = context.getExternalFilesDir(null)!!.canonicalPath userPath = context.getExternalFilesDir(null)!!.canonicalPath
NativeLibrary.SetAppDirectory(userPath) NativeLibrary.setAppDirectory(userPath!!)
} catch (e: IOException) { } catch (e: IOException) {
e.printStackTrace() e.printStackTrace()
} }

View File

@ -22,7 +22,7 @@ object GameHelper {
val gamesUri = Uri.parse(gamesDir) val gamesUri = Uri.parse(gamesDir)
// Ensure keys are loaded so that ROM metadata can be decrypted. // Ensure keys are loaded so that ROM metadata can be decrypted.
NativeLibrary.ReloadKeys() NativeLibrary.reloadKeys()
val children = FileUtil.listFiles(context, gamesUri) val children = FileUtil.listFiles(context, gamesUri)
for (file in children) { for (file in children) {
@ -44,13 +44,13 @@ object GameHelper {
} }
private fun getGame(filePath: String): Game { private fun getGame(filePath: String): Game {
var name = NativeLibrary.GetTitle(filePath) var name = NativeLibrary.getTitle(filePath)
// If the game's title field is empty, use the filename. // If the game's title field is empty, use the filename.
if (name.isEmpty()) { if (name.isEmpty()) {
name = filePath.substring(filePath.lastIndexOf("/") + 1) name = filePath.substring(filePath.lastIndexOf("/") + 1)
} }
var gameId = NativeLibrary.GetGameId(filePath) var gameId = NativeLibrary.getGameId(filePath)
// If the game's ID field is empty, use the filename without extension. // If the game's ID field is empty, use the filename without extension.
if (gameId.isEmpty()) { if (gameId.isEmpty()) {
@ -62,11 +62,11 @@ object GameHelper {
return Game( return Game(
name, name,
NativeLibrary.GetDescription(filePath).replace("\n", " "), NativeLibrary.getDescription(filePath).replace("\n", " "),
NativeLibrary.GetRegions(filePath), NativeLibrary.getRegions(filePath),
filePath, filePath,
gameId, gameId,
NativeLibrary.GetCompany(filePath) NativeLibrary.getCompany(filePath)
) )
} }
} }

View File

@ -67,7 +67,7 @@ object GpuDriverHelper {
hookLibPath = context.applicationInfo.nativeLibraryDir + "/" hookLibPath = context.applicationInfo.nativeLibraryDir + "/"
// Initialize GPU driver. // Initialize GPU driver.
NativeLibrary.InitializeGpuDriver( NativeLibrary.initializeGpuDriver(
hookLibPath, hookLibPath,
driverInstallationPath, driverInstallationPath,
customDriverLibraryName, customDriverLibraryName,

View File

@ -353,32 +353,32 @@ static Core::SystemResultStatus RunEmulation(const std::string& filepath) {
extern "C" { extern "C" {
void Java_org_yuzu_yuzu_1emu_NativeLibrary_SurfaceChanged(JNIEnv* env, void Java_org_yuzu_yuzu_1emu_NativeLibrary_surfaceChanged(JNIEnv* env,
[[maybe_unused]] jclass clazz, [[maybe_unused]] jclass clazz,
jobject surf) { jobject surf) {
EmulationSession::GetInstance().SetNativeWindow(ANativeWindow_fromSurface(env, surf)); EmulationSession::GetInstance().SetNativeWindow(ANativeWindow_fromSurface(env, surf));
EmulationSession::GetInstance().SurfaceChanged(); EmulationSession::GetInstance().SurfaceChanged();
} }
void Java_org_yuzu_yuzu_1emu_NativeLibrary_SurfaceDestroyed(JNIEnv* env, void Java_org_yuzu_yuzu_1emu_NativeLibrary_surfaceDestroyed(JNIEnv* env,
[[maybe_unused]] jclass clazz) { [[maybe_unused]] jclass clazz) {
ANativeWindow_release(EmulationSession::GetInstance().NativeWindow()); ANativeWindow_release(EmulationSession::GetInstance().NativeWindow());
EmulationSession::GetInstance().SetNativeWindow(nullptr); EmulationSession::GetInstance().SetNativeWindow(nullptr);
EmulationSession::GetInstance().SurfaceChanged(); EmulationSession::GetInstance().SurfaceChanged();
} }
void Java_org_yuzu_yuzu_1emu_NativeLibrary_NotifyOrientationChange(JNIEnv* env, void Java_org_yuzu_yuzu_1emu_NativeLibrary_notifyOrientationChange(JNIEnv* env,
[[maybe_unused]] jclass clazz, [[maybe_unused]] jclass clazz,
jint layout_option, jint layout_option,
jint rotation) {} jint rotation) {}
void Java_org_yuzu_yuzu_1emu_NativeLibrary_SetAppDirectory(JNIEnv* env, void Java_org_yuzu_yuzu_1emu_NativeLibrary_setAppDirectory(JNIEnv* env,
[[maybe_unused]] jclass clazz, [[maybe_unused]] jclass clazz,
jstring j_directory) { jstring j_directory) {
Common::FS::SetAppDirectory(GetJString(env, j_directory)); Common::FS::SetAppDirectory(GetJString(env, j_directory));
} }
void JNICALL Java_org_yuzu_yuzu_1emu_NativeLibrary_InitializeGpuDriver( void JNICALL Java_org_yuzu_yuzu_1emu_NativeLibrary_initializeGpuDriver(
JNIEnv* env, [[maybe_unused]] jclass clazz, jstring hook_lib_dir, jstring custom_driver_dir, JNIEnv* env, [[maybe_unused]] jclass clazz, jstring hook_lib_dir, jstring custom_driver_dir,
jstring custom_driver_name, jstring file_redirect_dir) { jstring custom_driver_name, jstring file_redirect_dir) {
EmulationSession::GetInstance().InitializeGpuDriver( EmulationSession::GetInstance().InitializeGpuDriver(
@ -386,33 +386,33 @@ void JNICALL Java_org_yuzu_yuzu_1emu_NativeLibrary_InitializeGpuDriver(
GetJString(env, custom_driver_name), GetJString(env, file_redirect_dir)); GetJString(env, custom_driver_name), GetJString(env, file_redirect_dir));
} }
jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_ReloadKeys(JNIEnv* env, jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_reloadKeys(JNIEnv* env,
[[maybe_unused]] jclass clazz) { [[maybe_unused]] jclass clazz) {
Core::Crypto::KeyManager::Instance().ReloadKeys(); Core::Crypto::KeyManager::Instance().ReloadKeys();
return static_cast<jboolean>(Core::Crypto::KeyManager::Instance().AreKeysLoaded()); return static_cast<jboolean>(Core::Crypto::KeyManager::Instance().AreKeysLoaded());
} }
void Java_org_yuzu_yuzu_1emu_NativeLibrary_UnPauseEmulation([[maybe_unused]] JNIEnv* env, void Java_org_yuzu_yuzu_1emu_NativeLibrary_unPauseEmulation([[maybe_unused]] JNIEnv* env,
[[maybe_unused]] jclass clazz) { [[maybe_unused]] jclass clazz) {
EmulationSession::GetInstance().UnPauseEmulation(); EmulationSession::GetInstance().UnPauseEmulation();
} }
void Java_org_yuzu_yuzu_1emu_NativeLibrary_PauseEmulation([[maybe_unused]] JNIEnv* env, void Java_org_yuzu_yuzu_1emu_NativeLibrary_pauseEmulation([[maybe_unused]] JNIEnv* env,
[[maybe_unused]] jclass clazz) { [[maybe_unused]] jclass clazz) {
EmulationSession::GetInstance().PauseEmulation(); EmulationSession::GetInstance().PauseEmulation();
} }
void Java_org_yuzu_yuzu_1emu_NativeLibrary_StopEmulation([[maybe_unused]] JNIEnv* env, void Java_org_yuzu_yuzu_1emu_NativeLibrary_stopEmulation([[maybe_unused]] JNIEnv* env,
[[maybe_unused]] jclass clazz) { [[maybe_unused]] jclass clazz) {
EmulationSession::GetInstance().HaltEmulation(); EmulationSession::GetInstance().HaltEmulation();
} }
void Java_org_yuzu_yuzu_1emu_NativeLibrary_ResetRomMetadata([[maybe_unused]] JNIEnv* env, void Java_org_yuzu_yuzu_1emu_NativeLibrary_resetRomMetadata([[maybe_unused]] JNIEnv* env,
[[maybe_unused]] jclass clazz) { [[maybe_unused]] jclass clazz) {
EmulationSession::GetInstance().ResetRomMetadata(); EmulationSession::GetInstance().ResetRomMetadata();
} }
jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_IsRunning([[maybe_unused]] JNIEnv* env, jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_isRunning([[maybe_unused]] JNIEnv* env,
[[maybe_unused]] jclass clazz) { [[maybe_unused]] jclass clazz) {
return static_cast<jboolean>(EmulationSession::GetInstance().IsRunning()); return static_cast<jboolean>(EmulationSession::GetInstance().IsRunning());
} }
@ -492,7 +492,7 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_onTouchReleased([[maybe_unused]] JNIE
} }
} }
jbyteArray Java_org_yuzu_yuzu_1emu_NativeLibrary_GetIcon([[maybe_unused]] JNIEnv* env, jbyteArray Java_org_yuzu_yuzu_1emu_NativeLibrary_getIcon([[maybe_unused]] JNIEnv* env,
[[maybe_unused]] jclass clazz, [[maybe_unused]] jclass clazz,
[[maybe_unused]] jstring j_filename) { [[maybe_unused]] jstring j_filename) {
auto icon_data = EmulationSession::GetInstance().GetRomIcon(GetJString(env, j_filename)); auto icon_data = EmulationSession::GetInstance().GetRomIcon(GetJString(env, j_filename));
@ -502,43 +502,38 @@ jbyteArray Java_org_yuzu_yuzu_1emu_NativeLibrary_GetIcon([[maybe_unused]] JNIEnv
return icon; return icon;
} }
jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_GetTitle([[maybe_unused]] JNIEnv* env, jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getTitle([[maybe_unused]] JNIEnv* env,
[[maybe_unused]] jclass clazz, [[maybe_unused]] jclass clazz,
[[maybe_unused]] jstring j_filename) { [[maybe_unused]] jstring j_filename) {
auto title = EmulationSession::GetInstance().GetRomTitle(GetJString(env, j_filename)); auto title = EmulationSession::GetInstance().GetRomTitle(GetJString(env, j_filename));
return env->NewStringUTF(title.c_str()); return env->NewStringUTF(title.c_str());
} }
jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_GetDescription([[maybe_unused]] JNIEnv* env, jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getDescription([[maybe_unused]] JNIEnv* env,
[[maybe_unused]] jclass clazz, [[maybe_unused]] jclass clazz,
jstring j_filename) { jstring j_filename) {
return j_filename; return j_filename;
} }
jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_GetGameId([[maybe_unused]] JNIEnv* env, jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getGameId([[maybe_unused]] JNIEnv* env,
[[maybe_unused]] jclass clazz, [[maybe_unused]] jclass clazz,
jstring j_filename) { jstring j_filename) {
return j_filename; return j_filename;
} }
jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_GetRegions([[maybe_unused]] JNIEnv* env, jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getRegions([[maybe_unused]] JNIEnv* env,
[[maybe_unused]] jclass clazz, [[maybe_unused]] jclass clazz,
[[maybe_unused]] jstring j_filename) { [[maybe_unused]] jstring j_filename) {
return env->NewStringUTF(""); return env->NewStringUTF("");
} }
jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_GetCompany([[maybe_unused]] JNIEnv* env, jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getCompany([[maybe_unused]] JNIEnv* env,
[[maybe_unused]] jclass clazz, [[maybe_unused]] jclass clazz,
[[maybe_unused]] jstring j_filename) { [[maybe_unused]] jstring j_filename) {
return env->NewStringUTF(""); return env->NewStringUTF("");
} }
jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_GetGitRevision([[maybe_unused]] JNIEnv* env, void Java_org_yuzu_yuzu_1emu_NativeLibrary_initializeEmulation
[[maybe_unused]] jclass clazz) {
return {};
}
void Java_org_yuzu_yuzu_1emu_NativeLibrary_InitializeEmulation
[[maybe_unused]] (JNIEnv* env, [[maybe_unused]] jclass clazz) { [[maybe_unused]] (JNIEnv* env, [[maybe_unused]] jclass clazz) {
// Create the default config.ini. // Create the default config.ini.
Config{}; Config{};
@ -546,21 +541,21 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_InitializeEmulation
EmulationSession::GetInstance().System().Initialize(); EmulationSession::GetInstance().System().Initialize();
} }
jint Java_org_yuzu_yuzu_1emu_NativeLibrary_DefaultCPUCore([[maybe_unused]] JNIEnv* env, jint Java_org_yuzu_yuzu_1emu_NativeLibrary_defaultCPUCore([[maybe_unused]] JNIEnv* env,
[[maybe_unused]] jclass clazz) { [[maybe_unused]] jclass clazz) {
return {}; return {};
} }
void Java_org_yuzu_yuzu_1emu_NativeLibrary_Run__Ljava_lang_String_2Ljava_lang_String_2Z( void Java_org_yuzu_yuzu_1emu_NativeLibrary_run__Ljava_lang_String_2Ljava_lang_String_2Z(
[[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, [[maybe_unused]] jstring j_file, [[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, [[maybe_unused]] jstring j_file,
[[maybe_unused]] jstring j_savestate, [[maybe_unused]] jboolean j_delete_savestate) {} [[maybe_unused]] jstring j_savestate, [[maybe_unused]] jboolean j_delete_savestate) {}
void Java_org_yuzu_yuzu_1emu_NativeLibrary_ReloadSettings([[maybe_unused]] JNIEnv* env, void Java_org_yuzu_yuzu_1emu_NativeLibrary_reloadSettings([[maybe_unused]] JNIEnv* env,
[[maybe_unused]] jclass clazz) { [[maybe_unused]] jclass clazz) {
Config{}; Config{};
} }
jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_GetUserSetting([[maybe_unused]] JNIEnv* env, jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getUserSetting([[maybe_unused]] JNIEnv* env,
[[maybe_unused]] jclass clazz, [[maybe_unused]] jclass clazz,
jstring j_game_id, jstring j_section, jstring j_game_id, jstring j_section,
jstring j_key) { jstring j_key) {
@ -575,7 +570,7 @@ jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_GetUserSetting([[maybe_unused]] JN
return env->NewStringUTF(""); return env->NewStringUTF("");
} }
void Java_org_yuzu_yuzu_1emu_NativeLibrary_SetUserSetting([[maybe_unused]] JNIEnv* env, void Java_org_yuzu_yuzu_1emu_NativeLibrary_setUserSetting([[maybe_unused]] JNIEnv* env,
[[maybe_unused]] jclass clazz, [[maybe_unused]] jclass clazz,
jstring j_game_id, jstring j_section, jstring j_game_id, jstring j_section,
jstring j_key, jstring j_value) { jstring j_key, jstring j_value) {
@ -590,7 +585,7 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_SetUserSetting([[maybe_unused]] JNIEn
env->ReleaseStringUTFChars(j_value, value.data()); env->ReleaseStringUTFChars(j_value, value.data());
} }
void Java_org_yuzu_yuzu_1emu_NativeLibrary_InitGameIni([[maybe_unused]] JNIEnv* env, void Java_org_yuzu_yuzu_1emu_NativeLibrary_initGameIni([[maybe_unused]] JNIEnv* env,
[[maybe_unused]] jclass clazz, [[maybe_unused]] jclass clazz,
jstring j_game_id) { jstring j_game_id) {
std::string_view game_id = env->GetStringUTFChars(j_game_id, 0); std::string_view game_id = env->GetStringUTFChars(j_game_id, 0);
@ -598,7 +593,7 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_InitGameIni([[maybe_unused]] JNIEnv*
env->ReleaseStringUTFChars(j_game_id, game_id.data()); env->ReleaseStringUTFChars(j_game_id, game_id.data());
} }
jdoubleArray Java_org_yuzu_yuzu_1emu_NativeLibrary_GetPerfStats([[maybe_unused]] JNIEnv* env, jdoubleArray Java_org_yuzu_yuzu_1emu_NativeLibrary_getPerfStats([[maybe_unused]] JNIEnv* env,
[[maybe_unused]] jclass clazz) { [[maybe_unused]] jclass clazz) {
jdoubleArray j_stats = env->NewDoubleArray(4); jdoubleArray j_stats = env->NewDoubleArray(4);
@ -615,10 +610,10 @@ jdoubleArray Java_org_yuzu_yuzu_1emu_NativeLibrary_GetPerfStats([[maybe_unused]]
return j_stats; return j_stats;
} }
void Java_org_yuzu_yuzu_1emu_utils_DirectoryInitialization_SetSysDirectory( void Java_org_yuzu_yuzu_1emu_utils_DirectoryInitialization_setSysDirectory(
[[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jstring j_path) {} [[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jstring j_path) {}
void Java_org_yuzu_yuzu_1emu_NativeLibrary_Run__Ljava_lang_String_2([[maybe_unused]] JNIEnv* env, void Java_org_yuzu_yuzu_1emu_NativeLibrary_run__Ljava_lang_String_2([[maybe_unused]] JNIEnv* env,
[[maybe_unused]] jclass clazz, [[maybe_unused]] jclass clazz,
jstring j_path) { jstring j_path) {
const std::string path = GetJString(env, j_path); const std::string path = GetJString(env, j_path);
@ -630,19 +625,19 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_Run__Ljava_lang_String_2([[maybe_unus
} }
} }
void Java_org_yuzu_yuzu_1emu_NativeLibrary_LogDeviceInfo([[maybe_unused]] JNIEnv* env, void Java_org_yuzu_yuzu_1emu_NativeLibrary_logDeviceInfo([[maybe_unused]] JNIEnv* env,
[[maybe_unused]] jclass clazz) { [[maybe_unused]] jclass clazz) {
LOG_INFO(Frontend, "yuzu Version: {}-{}", Common::g_scm_branch, Common::g_scm_desc); LOG_INFO(Frontend, "yuzu Version: {}-{}", Common::g_scm_branch, Common::g_scm_desc);
LOG_INFO(Frontend, "Host OS: Android API level {}", android_get_device_api_level()); LOG_INFO(Frontend, "Host OS: Android API level {}", android_get_device_api_level());
} }
void Java_org_yuzu_yuzu_1emu_NativeLibrary_SubmitInlineKeyboardText(JNIEnv* env, jclass clazz, void Java_org_yuzu_yuzu_1emu_NativeLibrary_submitInlineKeyboardText(JNIEnv* env, jclass clazz,
jstring j_text) { jstring j_text) {
const std::u16string input = Common::UTF8ToUTF16(GetJString(env, j_text)); const std::u16string input = Common::UTF8ToUTF16(GetJString(env, j_text));
EmulationSession::GetInstance().SoftwareKeyboard()->SubmitInlineKeyboardText(input); EmulationSession::GetInstance().SoftwareKeyboard()->SubmitInlineKeyboardText(input);
} }
void Java_org_yuzu_yuzu_1emu_NativeLibrary_SubmitInlineKeyboardInput(JNIEnv* env, jclass clazz, void Java_org_yuzu_yuzu_1emu_NativeLibrary_submitInlineKeyboardInput(JNIEnv* env, jclass clazz,
jint j_key_code) { jint j_key_code) {
EmulationSession::GetInstance().SoftwareKeyboard()->SubmitInlineKeyboardInput(j_key_code); EmulationSession::GetInstance().SoftwareKeyboard()->SubmitInlineKeyboardInput(j_key_code);
} }