mirror of
https://github.com/citra-emu/citra-canary.git
synced 2024-12-23 12:55:30 +00:00
android: Open cheats by long pressing game in game list (#6491)
This commit is contained in:
parent
ebac6b17b0
commit
2e47afd48e
|
@ -128,6 +128,8 @@ public final class NativeLibrary {
|
||||||
|
|
||||||
public static native void InitGameIni(String gameID);
|
public static native void InitGameIni(String gameID);
|
||||||
|
|
||||||
|
public static native long GetTitleId(String filename);
|
||||||
|
|
||||||
public static native String GetGitRevision();
|
public static native String GetGitRevision();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -186,6 +188,11 @@ public final class NativeLibrary {
|
||||||
*/
|
*/
|
||||||
public static native boolean IsRunning();
|
public static native boolean IsRunning();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the title ID of the currently running title, or 0 on failure.
|
||||||
|
*/
|
||||||
|
public static native long GetRunningTitleId();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the performance stats for the current game
|
* Returns the performance stats for the current game
|
||||||
**/
|
**/
|
||||||
|
|
|
@ -491,7 +491,7 @@ public final class EmulationActivity extends AppCompatActivity {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MENU_ACTION_OPEN_CHEATS:
|
case MENU_ACTION_OPEN_CHEATS:
|
||||||
CheatsActivity.launch(this);
|
CheatsActivity.launch(this, NativeLibrary.GetRunningTitleId());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MENU_ACTION_CLOSE_GAME:
|
case MENU_ACTION_CLOSE_GAME:
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package org.citra.citra_emu.adapters;
|
package org.citra.citra_emu.adapters;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.database.DataSetObserver;
|
import android.database.DataSetObserver;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
|
@ -14,10 +15,13 @@ import androidx.fragment.app.FragmentActivity;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
import com.google.android.material.color.MaterialColors;
|
import com.google.android.material.color.MaterialColors;
|
||||||
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||||
|
|
||||||
import org.citra.citra_emu.CitraApplication;
|
import org.citra.citra_emu.CitraApplication;
|
||||||
|
import org.citra.citra_emu.NativeLibrary;
|
||||||
import org.citra.citra_emu.R;
|
import org.citra.citra_emu.R;
|
||||||
import org.citra.citra_emu.activities.EmulationActivity;
|
import org.citra.citra_emu.activities.EmulationActivity;
|
||||||
|
import org.citra.citra_emu.features.cheats.ui.CheatsActivity;
|
||||||
import org.citra.citra_emu.model.GameDatabase;
|
import org.citra.citra_emu.model.GameDatabase;
|
||||||
import org.citra.citra_emu.utils.FileUtil;
|
import org.citra.citra_emu.utils.FileUtil;
|
||||||
import org.citra.citra_emu.utils.Log;
|
import org.citra.citra_emu.utils.Log;
|
||||||
|
@ -31,8 +35,7 @@ import java.util.stream.Stream;
|
||||||
* ContentProviders and Loaders, allows for efficient display of a limited view into a (possibly)
|
* ContentProviders and Loaders, allows for efficient display of a limited view into a (possibly)
|
||||||
* large dataset.
|
* large dataset.
|
||||||
*/
|
*/
|
||||||
public final class GameAdapter extends RecyclerView.Adapter<GameViewHolder> implements
|
public final class GameAdapter extends RecyclerView.Adapter<GameViewHolder> {
|
||||||
View.OnClickListener {
|
|
||||||
private Cursor mCursor;
|
private Cursor mCursor;
|
||||||
private GameDataSetObserver mObserver;
|
private GameDataSetObserver mObserver;
|
||||||
|
|
||||||
|
@ -61,7 +64,8 @@ public final class GameAdapter extends RecyclerView.Adapter<GameViewHolder> impl
|
||||||
View gameCard = LayoutInflater.from(parent.getContext())
|
View gameCard = LayoutInflater.from(parent.getContext())
|
||||||
.inflate(R.layout.card_game, parent, false);
|
.inflate(R.layout.card_game, parent, false);
|
||||||
|
|
||||||
gameCard.setOnClickListener(this);
|
gameCard.setOnClickListener(this::onClick);
|
||||||
|
gameCard.setOnLongClickListener(this::onLongClick);
|
||||||
|
|
||||||
// Use that view to create a ViewHolder.
|
// Use that view to create a ViewHolder.
|
||||||
return new GameViewHolder(gameCard);
|
return new GameViewHolder(gameCard);
|
||||||
|
@ -193,10 +197,9 @@ public final class GameAdapter extends RecyclerView.Adapter<GameViewHolder> impl
|
||||||
/**
|
/**
|
||||||
* Launches the game that was clicked on.
|
* Launches the game that was clicked on.
|
||||||
*
|
*
|
||||||
* @param view The card representing the game the user wants to play.
|
* @param view The view representing the game the user wants to play.
|
||||||
*/
|
*/
|
||||||
@Override
|
private void onClick(View view) {
|
||||||
public void onClick(View view) {
|
|
||||||
// Double-click prevention, using threshold of 1000 ms
|
// Double-click prevention, using threshold of 1000 ms
|
||||||
if (SystemClock.elapsedRealtime() - mLastClickTime < 1000) {
|
if (SystemClock.elapsedRealtime() - mLastClickTime < 1000) {
|
||||||
return;
|
return;
|
||||||
|
@ -208,6 +211,31 @@ public final class GameAdapter extends RecyclerView.Adapter<GameViewHolder> impl
|
||||||
EmulationActivity.launch((FragmentActivity) view.getContext(), holder.path, holder.title);
|
EmulationActivity.launch((FragmentActivity) view.getContext(), holder.path, holder.title);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens the cheats settings for the game that was clicked on.
|
||||||
|
*
|
||||||
|
* @param view The view representing the game the user wants to play.
|
||||||
|
*/
|
||||||
|
private boolean onLongClick(View view) {
|
||||||
|
Context context = view.getContext();
|
||||||
|
GameViewHolder holder = (GameViewHolder) view.getTag();
|
||||||
|
|
||||||
|
final long titleId = NativeLibrary.GetTitleId(holder.path);
|
||||||
|
|
||||||
|
if (titleId == 0) {
|
||||||
|
new MaterialAlertDialogBuilder(context)
|
||||||
|
.setIcon(R.mipmap.ic_launcher)
|
||||||
|
.setTitle(R.string.properties)
|
||||||
|
.setMessage(R.string.properties_not_loaded)
|
||||||
|
.setPositiveButton(android.R.string.ok, null)
|
||||||
|
.show();
|
||||||
|
} else {
|
||||||
|
CheatsActivity.launch(context, titleId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isValidGame(String path) {
|
private boolean isValidGame(String path) {
|
||||||
return Stream.of(
|
return Stream.of(
|
||||||
".rar", ".zip", ".7z", ".torrent", ".tar", ".gz").noneMatch(suffix -> path.toLowerCase().endsWith(suffix));
|
".rar", ".zip", ".7z", ".torrent", ".tar", ".gz").noneMatch(suffix -> path.toLowerCase().endsWith(suffix));
|
||||||
|
|
|
@ -1,13 +1,28 @@
|
||||||
package org.citra.citra_emu.features.cheats.model;
|
package org.citra.citra_emu.features.cheats.model;
|
||||||
|
|
||||||
|
import androidx.annotation.Keep;
|
||||||
|
|
||||||
public class CheatEngine {
|
public class CheatEngine {
|
||||||
public static native Cheat[] getCheats();
|
@Keep
|
||||||
|
private final long mPointer;
|
||||||
|
|
||||||
public static native void addCheat(Cheat cheat);
|
@Keep
|
||||||
|
public CheatEngine(long titleId) {
|
||||||
|
mPointer = initialize(titleId);
|
||||||
|
}
|
||||||
|
|
||||||
public static native void removeCheat(int index);
|
private static native long initialize(long titleId);
|
||||||
|
|
||||||
public static native void updateCheat(int index, Cheat newCheat);
|
@Override
|
||||||
|
protected native void finalize();
|
||||||
|
|
||||||
public static native void saveCheatFile();
|
public native Cheat[] getCheats();
|
||||||
|
|
||||||
|
public native void addCheat(Cheat cheat);
|
||||||
|
|
||||||
|
public native void removeCheat(int index);
|
||||||
|
|
||||||
|
public native void updateCheat(int index, Cheat newCheat);
|
||||||
|
|
||||||
|
public native void saveCheatFile();
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,11 +19,17 @@ public class CheatsViewModel extends ViewModel {
|
||||||
private final MutableLiveData<Integer> mCheatDeletedEvent = new MutableLiveData<>(null);
|
private final MutableLiveData<Integer> mCheatDeletedEvent = new MutableLiveData<>(null);
|
||||||
private final MutableLiveData<Boolean> mOpenDetailsViewEvent = new MutableLiveData<>(false);
|
private final MutableLiveData<Boolean> mOpenDetailsViewEvent = new MutableLiveData<>(false);
|
||||||
|
|
||||||
|
private CheatEngine mCheatEngine;
|
||||||
private Cheat[] mCheats;
|
private Cheat[] mCheats;
|
||||||
private boolean mCheatsNeedSaving = false;
|
private boolean mCheatsNeedSaving = false;
|
||||||
|
|
||||||
public void load() {
|
public void initialize(long titleId) {
|
||||||
mCheats = CheatEngine.getCheats();
|
mCheatEngine = new CheatEngine(titleId);
|
||||||
|
load();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void load() {
|
||||||
|
mCheats = mCheatEngine.getCheats();
|
||||||
|
|
||||||
for (int i = 0; i < mCheats.length; i++) {
|
for (int i = 0; i < mCheats.length; i++) {
|
||||||
int position = i;
|
int position = i;
|
||||||
|
@ -36,7 +42,7 @@ public class CheatsViewModel extends ViewModel {
|
||||||
|
|
||||||
public void saveIfNeeded() {
|
public void saveIfNeeded() {
|
||||||
if (mCheatsNeedSaving) {
|
if (mCheatsNeedSaving) {
|
||||||
CheatEngine.saveCheatFile();
|
mCheatEngine.saveCheatFile();
|
||||||
mCheatsNeedSaving = false;
|
mCheatsNeedSaving = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,7 +112,7 @@ public class CheatsViewModel extends ViewModel {
|
||||||
|
|
||||||
int position = mCheats.length;
|
int position = mCheats.length;
|
||||||
|
|
||||||
CheatEngine.addCheat(cheat);
|
mCheatEngine.addCheat(cheat);
|
||||||
|
|
||||||
mCheatsNeedSaving = true;
|
mCheatsNeedSaving = true;
|
||||||
load();
|
load();
|
||||||
|
@ -132,7 +138,7 @@ public class CheatsViewModel extends ViewModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateSelectedCheat(Cheat newCheat) {
|
public void updateSelectedCheat(Cheat newCheat) {
|
||||||
CheatEngine.updateCheat(mSelectedCheatPosition, newCheat);
|
mCheatEngine.updateCheat(mSelectedCheatPosition, newCheat);
|
||||||
|
|
||||||
mCheatsNeedSaving = true;
|
mCheatsNeedSaving = true;
|
||||||
load();
|
load();
|
||||||
|
@ -162,7 +168,7 @@ public class CheatsViewModel extends ViewModel {
|
||||||
|
|
||||||
setSelectedCheat(null, -1);
|
setSelectedCheat(null, -1);
|
||||||
|
|
||||||
CheatEngine.removeCheat(position);
|
mCheatEngine.removeCheat(position);
|
||||||
|
|
||||||
mCheatsNeedSaving = true;
|
mCheatsNeedSaving = true;
|
||||||
load();
|
load();
|
||||||
|
|
|
@ -32,6 +32,8 @@ import java.util.List;
|
||||||
|
|
||||||
public class CheatsActivity extends AppCompatActivity
|
public class CheatsActivity extends AppCompatActivity
|
||||||
implements SlidingPaneLayout.PanelSlideListener {
|
implements SlidingPaneLayout.PanelSlideListener {
|
||||||
|
private static String ARG_TITLE_ID = "title_id";
|
||||||
|
|
||||||
private CheatsViewModel mViewModel;
|
private CheatsViewModel mViewModel;
|
||||||
|
|
||||||
private SlidingPaneLayout mSlidingPaneLayout;
|
private SlidingPaneLayout mSlidingPaneLayout;
|
||||||
|
@ -41,8 +43,9 @@ public class CheatsActivity extends AppCompatActivity
|
||||||
private View mCheatListLastFocus;
|
private View mCheatListLastFocus;
|
||||||
private View mCheatDetailsLastFocus;
|
private View mCheatDetailsLastFocus;
|
||||||
|
|
||||||
public static void launch(Context context) {
|
public static void launch(Context context, long titleId) {
|
||||||
Intent intent = new Intent(context, CheatsActivity.class);
|
Intent intent = new Intent(context, CheatsActivity.class);
|
||||||
|
intent.putExtra(ARG_TITLE_ID, titleId);
|
||||||
context.startActivity(intent);
|
context.startActivity(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,8 +57,10 @@ public class CheatsActivity extends AppCompatActivity
|
||||||
|
|
||||||
WindowCompat.setDecorFitsSystemWindows(getWindow(), false);
|
WindowCompat.setDecorFitsSystemWindows(getWindow(), false);
|
||||||
|
|
||||||
|
long titleId = getIntent().getLongExtra(ARG_TITLE_ID, -1);
|
||||||
|
|
||||||
mViewModel = new ViewModelProvider(this).get(CheatsViewModel.class);
|
mViewModel = new ViewModelProvider(this).get(CheatsViewModel.class);
|
||||||
mViewModel.load();
|
mViewModel.initialize(titleId);
|
||||||
|
|
||||||
setContentView(R.layout.activity_cheats);
|
setContentView(R.layout.activity_cheats);
|
||||||
|
|
||||||
|
|
|
@ -15,9 +15,24 @@
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
|
static Cheats::CheatEngine* GetPointer(JNIEnv* env, jobject obj) {
|
||||||
|
return reinterpret_cast<Cheats::CheatEngine*>(
|
||||||
|
env->GetLongField(obj, IDCache::GetCheatEnginePointer()));
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jlong JNICALL Java_org_citra_citra_1emu_features_cheats_model_CheatEngine_initialize(
|
||||||
|
JNIEnv* env, jclass, jlong title_id) {
|
||||||
|
return reinterpret_cast<jlong>(new Cheats::CheatEngine(title_id, Core::System::GetInstance()));
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL
|
||||||
|
Java_org_citra_citra_1emu_features_cheats_model_CheatEngine_finalize(JNIEnv* env, jobject obj) {
|
||||||
|
delete GetPointer(env, obj);
|
||||||
|
}
|
||||||
|
|
||||||
JNIEXPORT jobjectArray JNICALL
|
JNIEXPORT jobjectArray JNICALL
|
||||||
Java_org_citra_citra_1emu_features_cheats_model_CheatEngine_getCheats(JNIEnv* env, jclass) {
|
Java_org_citra_citra_1emu_features_cheats_model_CheatEngine_getCheats(JNIEnv* env, jobject obj) {
|
||||||
auto cheats = Core::System::GetInstance().CheatEngine().GetCheats();
|
auto cheats = GetPointer(env, obj)->GetCheats();
|
||||||
|
|
||||||
const jobjectArray array =
|
const jobjectArray array =
|
||||||
env->NewObjectArray(static_cast<jsize>(cheats.size()), IDCache::GetCheatClass(), nullptr);
|
env->NewObjectArray(static_cast<jsize>(cheats.size()), IDCache::GetCheatClass(), nullptr);
|
||||||
|
@ -30,22 +45,22 @@ Java_org_citra_citra_1emu_features_cheats_model_CheatEngine_getCheats(JNIEnv* en
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_org_citra_citra_1emu_features_cheats_model_CheatEngine_addCheat(
|
JNIEXPORT void JNICALL Java_org_citra_citra_1emu_features_cheats_model_CheatEngine_addCheat(
|
||||||
JNIEnv* env, jclass, jobject j_cheat) {
|
JNIEnv* env, jobject obj, jobject j_cheat) {
|
||||||
Core::System::GetInstance().CheatEngine().AddCheat(*CheatFromJava(env, j_cheat));
|
GetPointer(env, obj)->AddCheat(*CheatFromJava(env, j_cheat));
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_org_citra_citra_1emu_features_cheats_model_CheatEngine_removeCheat(
|
JNIEXPORT void JNICALL Java_org_citra_citra_1emu_features_cheats_model_CheatEngine_removeCheat(
|
||||||
JNIEnv* env, jclass, jint index) {
|
JNIEnv* env, jobject obj, jint index) {
|
||||||
Core::System::GetInstance().CheatEngine().RemoveCheat(index);
|
GetPointer(env, obj)->RemoveCheat(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_org_citra_citra_1emu_features_cheats_model_CheatEngine_updateCheat(
|
JNIEXPORT void JNICALL Java_org_citra_citra_1emu_features_cheats_model_CheatEngine_updateCheat(
|
||||||
JNIEnv* env, jclass, jint index, jobject j_new_cheat) {
|
JNIEnv* env, jobject obj, jint index, jobject j_new_cheat) {
|
||||||
Core::System::GetInstance().CheatEngine().UpdateCheat(index, *CheatFromJava(env, j_new_cheat));
|
GetPointer(env, obj)->UpdateCheat(index, *CheatFromJava(env, j_new_cheat));
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL
|
JNIEXPORT void JNICALL Java_org_citra_citra_1emu_features_cheats_model_CheatEngine_saveCheatFile(
|
||||||
Java_org_citra_citra_1emu_features_cheats_model_CheatEngine_saveCheatFile(JNIEnv* env, jclass) {
|
JNIEnv* env, jobject obj) {
|
||||||
Core::System::GetInstance().CheatEngine().SaveCheatFile();
|
GetPointer(env, obj)->SaveCheatFile();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,8 @@ static jclass s_cheat_class;
|
||||||
static jfieldID s_cheat_pointer;
|
static jfieldID s_cheat_pointer;
|
||||||
static jmethodID s_cheat_constructor;
|
static jmethodID s_cheat_constructor;
|
||||||
|
|
||||||
|
static jfieldID s_cheat_engine_pointer;
|
||||||
|
|
||||||
static jfieldID s_game_info_pointer;
|
static jfieldID s_game_info_pointer;
|
||||||
|
|
||||||
static std::unordered_map<VideoCore::LoadCallbackStage, jobject> s_java_load_callback_stages;
|
static std::unordered_map<VideoCore::LoadCallbackStage, jobject> s_java_load_callback_stages;
|
||||||
|
@ -137,6 +139,10 @@ jmethodID GetCheatConstructor() {
|
||||||
return s_cheat_constructor;
|
return s_cheat_constructor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jfieldID GetCheatEnginePointer() {
|
||||||
|
return s_cheat_engine_pointer;
|
||||||
|
}
|
||||||
|
|
||||||
jfieldID GetGameInfoPointer() {
|
jfieldID GetGameInfoPointer() {
|
||||||
return s_game_info_pointer;
|
return s_game_info_pointer;
|
||||||
}
|
}
|
||||||
|
@ -211,6 +217,12 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) {
|
||||||
s_cheat_constructor = env->GetMethodID(cheat_class, "<init>", "(J)V");
|
s_cheat_constructor = env->GetMethodID(cheat_class, "<init>", "(J)V");
|
||||||
env->DeleteLocalRef(cheat_class);
|
env->DeleteLocalRef(cheat_class);
|
||||||
|
|
||||||
|
// Initialize CheatEngine
|
||||||
|
const jclass cheat_engine_class =
|
||||||
|
env->FindClass("org/citra/citra_emu/features/cheats/model/CheatEngine");
|
||||||
|
s_cheat_engine_pointer = env->GetFieldID(cheat_engine_class, "mPointer", "J");
|
||||||
|
env->DeleteLocalRef(cheat_engine_class);
|
||||||
|
|
||||||
// Initialize GameInfo
|
// Initialize GameInfo
|
||||||
const jclass game_info_class = env->FindClass("org/citra/citra_emu/model/GameInfo");
|
const jclass game_info_class = env->FindClass("org/citra/citra_emu/model/GameInfo");
|
||||||
s_game_info_pointer = env->GetFieldID(game_info_class, "mPointer", "J");
|
s_game_info_pointer = env->GetFieldID(game_info_class, "mPointer", "J");
|
||||||
|
|
|
@ -34,6 +34,8 @@ jclass GetCheatClass();
|
||||||
jfieldID GetCheatPointer();
|
jfieldID GetCheatPointer();
|
||||||
jmethodID GetCheatConstructor();
|
jmethodID GetCheatConstructor();
|
||||||
|
|
||||||
|
jfieldID GetCheatEnginePointer();
|
||||||
|
|
||||||
jfieldID GetGameInfoPointer();
|
jfieldID GetGameInfoPointer();
|
||||||
|
|
||||||
jobject GetJavaLoadCallbackStage(VideoCore::LoadCallbackStage stage);
|
jobject GetJavaLoadCallbackStage(VideoCore::LoadCallbackStage stage);
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "core/frontend/camera/factory.h"
|
#include "core/frontend/camera/factory.h"
|
||||||
#include "core/hle/service/am/am.h"
|
#include "core/hle/service/am/am.h"
|
||||||
#include "core/hle/service/nfc/nfc.h"
|
#include "core/hle/service/nfc/nfc.h"
|
||||||
|
#include "core/loader/loader.h"
|
||||||
#include "core/savestate.h"
|
#include "core/savestate.h"
|
||||||
#include "jni/android_common/android_common.h"
|
#include "jni/android_common/android_common.h"
|
||||||
#include "jni/applets/mii_selector.h"
|
#include "jni/applets/mii_selector.h"
|
||||||
|
@ -379,6 +380,13 @@ jboolean Java_org_citra_citra_1emu_NativeLibrary_IsRunning(JNIEnv* env,
|
||||||
return static_cast<jboolean>(!stop_run);
|
return static_cast<jboolean>(!stop_run);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jlong Java_org_citra_citra_1emu_NativeLibrary_GetRunningTitleId(JNIEnv* env,
|
||||||
|
[[maybe_unused]] jclass clazz) {
|
||||||
|
u64 title_id{};
|
||||||
|
Core::System::GetInstance().GetAppLoader().ReadProgramId(title_id);
|
||||||
|
return static_cast<jlong>(title_id);
|
||||||
|
}
|
||||||
|
|
||||||
jboolean Java_org_citra_citra_1emu_NativeLibrary_onGamePadEvent(JNIEnv* env,
|
jboolean Java_org_citra_citra_1emu_NativeLibrary_onGamePadEvent(JNIEnv* env,
|
||||||
[[maybe_unused]] jclass clazz,
|
[[maybe_unused]] jclass clazz,
|
||||||
jstring j_device, jint j_button,
|
jstring j_device, jint j_button,
|
||||||
|
@ -435,6 +443,18 @@ void Java_org_citra_citra_1emu_NativeLibrary_onTouchMoved(JNIEnv* env,
|
||||||
window->OnTouchMoved((int)x, (int)y);
|
window->OnTouchMoved((int)x, (int)y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jlong Java_org_citra_citra_1emu_NativeLibrary_GetTitleId(JNIEnv* env, [[maybe_unused]] jclass clazz,
|
||||||
|
jstring j_filename) {
|
||||||
|
std::string filepath = GetJString(env, j_filename);
|
||||||
|
const auto loader = Loader::GetLoader(filepath);
|
||||||
|
|
||||||
|
u64 title_id{};
|
||||||
|
if (loader) {
|
||||||
|
loader->ReadProgramId(title_id);
|
||||||
|
}
|
||||||
|
return static_cast<jlong>(title_id);
|
||||||
|
}
|
||||||
|
|
||||||
jstring Java_org_citra_citra_1emu_NativeLibrary_GetGitRevision(JNIEnv* env,
|
jstring Java_org_citra_citra_1emu_NativeLibrary_GetGitRevision(JNIEnv* env,
|
||||||
[[maybe_unused]] jclass clazz) {
|
[[maybe_unused]] jclass clazz) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
|
@ -146,6 +146,10 @@
|
||||||
<string name="select_game_folder">Select Game Folder</string>
|
<string name="select_game_folder">Select Game Folder</string>
|
||||||
<string name="install_cia_title">Install CIA</string>
|
<string name="install_cia_title">Install CIA</string>
|
||||||
|
|
||||||
|
<!-- Game Properties -->
|
||||||
|
<string name="properties">Properties</string>
|
||||||
|
<string name="properties_not_loaded">The game properties could not be loaded.</string>
|
||||||
|
|
||||||
<!-- Preferences Screen -->
|
<!-- Preferences Screen -->
|
||||||
<string name="preferences_settings">Settings</string>
|
<string name="preferences_settings">Settings</string>
|
||||||
<string name="preferences_premium">Premium</string>
|
<string name="preferences_premium">Premium</string>
|
||||||
|
|
Loading…
Reference in a new issue