mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-02-14 00:09:24 +01:00
Android: Implement basic read-only cheats list
This commit is contained in:
parent
ee3a5a4a81
commit
4d609c769f
@ -90,6 +90,7 @@ dependencies {
|
|||||||
implementation 'androidx.recyclerview:recyclerview:1.2.1'
|
implementation 'androidx.recyclerview:recyclerview:1.2.1'
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
|
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
|
||||||
implementation 'androidx.lifecycle:lifecycle-viewmodel:2.3.1'
|
implementation 'androidx.lifecycle:lifecycle-viewmodel:2.3.1'
|
||||||
|
implementation 'androidx.fragment:fragment:1.3.6'
|
||||||
implementation 'com.google.android.material:material:1.4.0'
|
implementation 'com.google.android.material:material:1.4.0'
|
||||||
|
|
||||||
// Android TV UI libraries.
|
// Android TV UI libraries.
|
||||||
|
@ -0,0 +1,27 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.features.cheats.model;
|
||||||
|
|
||||||
|
import androidx.annotation.Keep;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
public class ARCheat implements Cheat
|
||||||
|
{
|
||||||
|
@Keep
|
||||||
|
private final long mPointer;
|
||||||
|
|
||||||
|
@Keep
|
||||||
|
private ARCheat(long pointer)
|
||||||
|
{
|
||||||
|
mPointer = pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public native void finalize();
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public native String getName();
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public static native ARCheat[] loadCodes(String gameId, int revision);
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.features.cheats.model;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
public interface Cheat
|
||||||
|
{
|
||||||
|
@NonNull
|
||||||
|
String getName();
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.features.cheats.model;
|
||||||
|
|
||||||
|
import androidx.lifecycle.ViewModel;
|
||||||
|
|
||||||
|
public class CheatsViewModel extends ViewModel
|
||||||
|
{
|
||||||
|
private boolean mLoaded = false;
|
||||||
|
|
||||||
|
private PatchCheat[] mPatchCheats;
|
||||||
|
private ARCheat[] mARCheats;
|
||||||
|
private GeckoCheat[] mGeckoCheats;
|
||||||
|
|
||||||
|
public void load(String gameID, int revision)
|
||||||
|
{
|
||||||
|
if (mLoaded)
|
||||||
|
return;
|
||||||
|
|
||||||
|
mPatchCheats = PatchCheat.loadCodes(gameID, revision);
|
||||||
|
mARCheats = ARCheat.loadCodes(gameID, revision);
|
||||||
|
mGeckoCheats = GeckoCheat.loadCodes(gameID, revision);
|
||||||
|
|
||||||
|
mLoaded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Cheat[] getPatchCheats()
|
||||||
|
{
|
||||||
|
return mPatchCheats;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ARCheat[] getARCheats()
|
||||||
|
{
|
||||||
|
return mARCheats;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Cheat[] getGeckoCheats()
|
||||||
|
{
|
||||||
|
return mGeckoCheats;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.features.cheats.model;
|
||||||
|
|
||||||
|
import androidx.annotation.Keep;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
public class GeckoCheat implements Cheat
|
||||||
|
{
|
||||||
|
@Keep
|
||||||
|
private final long mPointer;
|
||||||
|
|
||||||
|
@Keep
|
||||||
|
private GeckoCheat(long pointer)
|
||||||
|
{
|
||||||
|
mPointer = pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public native void finalize();
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public native String getName();
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public static native GeckoCheat[] loadCodes(String gameId, int revision);
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.features.cheats.model;
|
||||||
|
|
||||||
|
import androidx.annotation.Keep;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
public class PatchCheat implements Cheat
|
||||||
|
{
|
||||||
|
@Keep
|
||||||
|
private final long mPointer;
|
||||||
|
|
||||||
|
@Keep
|
||||||
|
private PatchCheat(long pointer)
|
||||||
|
{
|
||||||
|
mPointer = pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public native void finalize();
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public native String getName();
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public static native PatchCheat[] loadCodes(String gameId, int revision);
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.features.cheats.ui;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import org.dolphinemu.dolphinemu.R;
|
||||||
|
import org.dolphinemu.dolphinemu.features.cheats.model.CheatsViewModel;
|
||||||
|
import org.dolphinemu.dolphinemu.ui.DividerItemDecoration;
|
||||||
|
|
||||||
|
public class CheatListFragment extends Fragment
|
||||||
|
{
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
|
||||||
|
@Nullable Bundle savedInstanceState)
|
||||||
|
{
|
||||||
|
return inflater.inflate(R.layout.fragment_cheat_list, container, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState)
|
||||||
|
{
|
||||||
|
RecyclerView recyclerView = view.findViewById(R.id.cheat_list);
|
||||||
|
|
||||||
|
CheatsActivity activity = (CheatsActivity) requireActivity();
|
||||||
|
CheatsViewModel viewModel = new ViewModelProvider(activity).get(CheatsViewModel.class);
|
||||||
|
|
||||||
|
recyclerView.setAdapter(new CheatsAdapter(viewModel));
|
||||||
|
recyclerView.setLayoutManager(new LinearLayoutManager(activity));
|
||||||
|
recyclerView.addItemDecoration(new DividerItemDecoration(activity, null));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.features.cheats.ui;
|
||||||
|
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView.ViewHolder;
|
||||||
|
|
||||||
|
import org.dolphinemu.dolphinemu.R;
|
||||||
|
import org.dolphinemu.dolphinemu.features.cheats.model.Cheat;
|
||||||
|
|
||||||
|
public class CheatViewHolder extends ViewHolder
|
||||||
|
{
|
||||||
|
private TextView mName;
|
||||||
|
|
||||||
|
public CheatViewHolder(@NonNull View itemView)
|
||||||
|
{
|
||||||
|
super(itemView);
|
||||||
|
|
||||||
|
mName = itemView.findViewById(R.id.text_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void bind(Cheat item)
|
||||||
|
{
|
||||||
|
mName.setText(item.getName());
|
||||||
|
}
|
||||||
|
}
|
@ -4,8 +4,14 @@ package org.dolphinemu.dolphinemu.features.cheats.ui;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
|
|
||||||
|
import org.dolphinemu.dolphinemu.R;
|
||||||
|
import org.dolphinemu.dolphinemu.features.cheats.model.CheatsViewModel;
|
||||||
|
import org.dolphinemu.dolphinemu.ui.main.MainPresenter;
|
||||||
|
|
||||||
public class CheatsActivity extends AppCompatActivity
|
public class CheatsActivity extends AppCompatActivity
|
||||||
{
|
{
|
||||||
@ -19,4 +25,23 @@ public class CheatsActivity extends AppCompatActivity
|
|||||||
intent.putExtra(ARG_REVISION, revision);
|
intent.putExtra(ARG_REVISION, revision);
|
||||||
context.startActivity(intent);
|
context.startActivity(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState)
|
||||||
|
{
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
MainPresenter.skipRescanningLibrary();
|
||||||
|
|
||||||
|
Intent intent = getIntent();
|
||||||
|
String gameId = intent.getStringExtra(ARG_GAME_ID);
|
||||||
|
int revision = intent.getIntExtra(ARG_REVISION, 0);
|
||||||
|
|
||||||
|
setTitle(getString(R.string.cheats_with_game_id, gameId));
|
||||||
|
|
||||||
|
CheatsViewModel viewModel = new ViewModelProvider(this).get(CheatsViewModel.class);
|
||||||
|
viewModel.load(gameId, revision);
|
||||||
|
|
||||||
|
setContentView(R.layout.activity_cheats);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,72 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.features.cheats.ui;
|
||||||
|
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import org.dolphinemu.dolphinemu.R;
|
||||||
|
import org.dolphinemu.dolphinemu.features.cheats.model.Cheat;
|
||||||
|
import org.dolphinemu.dolphinemu.features.cheats.model.CheatsViewModel;
|
||||||
|
|
||||||
|
public class CheatsAdapter extends RecyclerView.Adapter<CheatViewHolder>
|
||||||
|
{
|
||||||
|
private final CheatsViewModel mViewModel;
|
||||||
|
|
||||||
|
public CheatsAdapter(CheatsViewModel viewModel)
|
||||||
|
{
|
||||||
|
mViewModel = viewModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public CheatViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType)
|
||||||
|
{
|
||||||
|
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
|
||||||
|
View view = inflater.inflate(R.layout.list_item_cheat, parent, false);
|
||||||
|
return new CheatViewHolder(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(@NonNull CheatViewHolder holder, int position)
|
||||||
|
{
|
||||||
|
holder.bind(getItemAt(position));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount()
|
||||||
|
{
|
||||||
|
return mViewModel.getARCheats().length + mViewModel.getGeckoCheats().length +
|
||||||
|
mViewModel.getPatchCheats().length;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Cheat getItemAt(int position)
|
||||||
|
{
|
||||||
|
Cheat[] patchCheats = mViewModel.getPatchCheats();
|
||||||
|
if (position < patchCheats.length)
|
||||||
|
{
|
||||||
|
return patchCheats[position];
|
||||||
|
}
|
||||||
|
position -= patchCheats.length;
|
||||||
|
|
||||||
|
Cheat[] arCheats = mViewModel.getARCheats();
|
||||||
|
if (position < arCheats.length)
|
||||||
|
{
|
||||||
|
return arCheats[position];
|
||||||
|
}
|
||||||
|
position -= arCheats.length;
|
||||||
|
|
||||||
|
Cheat[] geckoCheats = mViewModel.getGeckoCheats();
|
||||||
|
if (position < geckoCheats.length)
|
||||||
|
{
|
||||||
|
return geckoCheats[position];
|
||||||
|
}
|
||||||
|
position -= geckoCheats.length;
|
||||||
|
|
||||||
|
throw new IndexOutOfBoundsException();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.fragment.app.FragmentContainerView
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:id="@+id/cheat_list"
|
||||||
|
android:name="org.dolphinemu.dolphinemu.features.cheats.ui.CheatListFragment" />
|
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:id="@+id/cheat_list" />
|
23
Source/Android/app/src/main/res/layout/list_item_cheat.xml
Normal file
23
Source/Android/app/src/main/res/layout/list_item_cheat.xml
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:focusable="true">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/text_name"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
style="@style/TextAppearance.AppCompat.Headline"
|
||||||
|
android:textSize="16sp"
|
||||||
|
tools:text="Hyrule Field Speed Hack"
|
||||||
|
android:layout_margin="@dimen/spacing_large"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -58,6 +58,18 @@ static jmethodID s_network_helper_get_network_gateway;
|
|||||||
static jclass s_boolean_supplier_class;
|
static jclass s_boolean_supplier_class;
|
||||||
static jmethodID s_boolean_supplier_get;
|
static jmethodID s_boolean_supplier_get;
|
||||||
|
|
||||||
|
static jclass s_ar_cheat_class;
|
||||||
|
static jfieldID s_ar_cheat_pointer;
|
||||||
|
static jmethodID s_ar_cheat_constructor;
|
||||||
|
|
||||||
|
static jclass s_gecko_cheat_class;
|
||||||
|
static jfieldID s_gecko_cheat_pointer;
|
||||||
|
static jmethodID s_gecko_cheat_constructor;
|
||||||
|
|
||||||
|
static jclass s_patch_cheat_class;
|
||||||
|
static jfieldID s_patch_cheat_pointer;
|
||||||
|
static jmethodID s_patch_cheat_constructor;
|
||||||
|
|
||||||
namespace IDCache
|
namespace IDCache
|
||||||
{
|
{
|
||||||
JNIEnv* GetEnvForThread()
|
JNIEnv* GetEnvForThread()
|
||||||
@ -268,6 +280,51 @@ jmethodID GetBooleanSupplierGet()
|
|||||||
return s_boolean_supplier_get;
|
return s_boolean_supplier_get;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jclass GetARCheatClass()
|
||||||
|
{
|
||||||
|
return s_ar_cheat_class;
|
||||||
|
}
|
||||||
|
|
||||||
|
jfieldID GetARCheatPointer()
|
||||||
|
{
|
||||||
|
return s_ar_cheat_pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
jmethodID GetARCheatConstructor()
|
||||||
|
{
|
||||||
|
return s_ar_cheat_constructor;
|
||||||
|
}
|
||||||
|
|
||||||
|
jclass GetGeckoCheatClass()
|
||||||
|
{
|
||||||
|
return s_gecko_cheat_class;
|
||||||
|
}
|
||||||
|
|
||||||
|
jfieldID GetGeckoCheatPointer()
|
||||||
|
{
|
||||||
|
return s_gecko_cheat_pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
jmethodID GetGeckoCheatConstructor()
|
||||||
|
{
|
||||||
|
return s_gecko_cheat_constructor;
|
||||||
|
}
|
||||||
|
|
||||||
|
jclass GetPatchCheatClass()
|
||||||
|
{
|
||||||
|
return s_patch_cheat_class;
|
||||||
|
}
|
||||||
|
|
||||||
|
jfieldID GetPatchCheatPointer()
|
||||||
|
{
|
||||||
|
return s_patch_cheat_pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
jmethodID GetPatchCheatConstructor()
|
||||||
|
{
|
||||||
|
return s_patch_cheat_constructor;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace IDCache
|
} // namespace IDCache
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -376,6 +433,27 @@ JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved)
|
|||||||
s_boolean_supplier_get = env->GetMethodID(s_boolean_supplier_class, "get", "()Z");
|
s_boolean_supplier_get = env->GetMethodID(s_boolean_supplier_class, "get", "()Z");
|
||||||
env->DeleteLocalRef(boolean_supplier_class);
|
env->DeleteLocalRef(boolean_supplier_class);
|
||||||
|
|
||||||
|
const jclass ar_cheat_class =
|
||||||
|
env->FindClass("org/dolphinemu/dolphinemu/features/cheats/model/ARCheat");
|
||||||
|
s_ar_cheat_class = reinterpret_cast<jclass>(env->NewGlobalRef(ar_cheat_class));
|
||||||
|
s_ar_cheat_pointer = env->GetFieldID(ar_cheat_class, "mPointer", "J");
|
||||||
|
s_ar_cheat_constructor = env->GetMethodID(ar_cheat_class, "<init>", "(J)V");
|
||||||
|
env->DeleteLocalRef(ar_cheat_class);
|
||||||
|
|
||||||
|
const jclass gecko_cheat_class =
|
||||||
|
env->FindClass("org/dolphinemu/dolphinemu/features/cheats/model/GeckoCheat");
|
||||||
|
s_gecko_cheat_class = reinterpret_cast<jclass>(env->NewGlobalRef(gecko_cheat_class));
|
||||||
|
s_gecko_cheat_pointer = env->GetFieldID(gecko_cheat_class, "mPointer", "J");
|
||||||
|
s_gecko_cheat_constructor = env->GetMethodID(gecko_cheat_class, "<init>", "(J)V");
|
||||||
|
env->DeleteLocalRef(gecko_cheat_class);
|
||||||
|
|
||||||
|
const jclass patch_cheat_class =
|
||||||
|
env->FindClass("org/dolphinemu/dolphinemu/features/cheats/model/PatchCheat");
|
||||||
|
s_patch_cheat_class = reinterpret_cast<jclass>(env->NewGlobalRef(patch_cheat_class));
|
||||||
|
s_patch_cheat_pointer = env->GetFieldID(patch_cheat_class, "mPointer", "J");
|
||||||
|
s_patch_cheat_constructor = env->GetMethodID(patch_cheat_class, "<init>", "(J)V");
|
||||||
|
env->DeleteLocalRef(patch_cheat_class);
|
||||||
|
|
||||||
return JNI_VERSION;
|
return JNI_VERSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -396,5 +474,8 @@ JNIEXPORT void JNI_OnUnload(JavaVM* vm, void* reserved)
|
|||||||
env->DeleteGlobalRef(s_content_handler_class);
|
env->DeleteGlobalRef(s_content_handler_class);
|
||||||
env->DeleteGlobalRef(s_network_helper_class);
|
env->DeleteGlobalRef(s_network_helper_class);
|
||||||
env->DeleteGlobalRef(s_boolean_supplier_class);
|
env->DeleteGlobalRef(s_boolean_supplier_class);
|
||||||
|
env->DeleteGlobalRef(s_ar_cheat_class);
|
||||||
|
env->DeleteGlobalRef(s_gecko_cheat_class);
|
||||||
|
env->DeleteGlobalRef(s_patch_cheat_class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,4 +57,16 @@ jmethodID GetNetworkHelperGetNetworkGateway();
|
|||||||
|
|
||||||
jmethodID GetBooleanSupplierGet();
|
jmethodID GetBooleanSupplierGet();
|
||||||
|
|
||||||
|
jclass GetARCheatClass();
|
||||||
|
jfieldID GetARCheatPointer();
|
||||||
|
jmethodID GetARCheatConstructor();
|
||||||
|
|
||||||
|
jclass GetGeckoCheatClass();
|
||||||
|
jfieldID GetGeckoCheatPointer();
|
||||||
|
jmethodID GetGeckoCheatConstructor();
|
||||||
|
|
||||||
|
jclass GetPatchCheatClass();
|
||||||
|
jfieldID GetPatchCheatPointer();
|
||||||
|
jmethodID GetPatchCheatConstructor();
|
||||||
|
|
||||||
} // namespace IDCache
|
} // namespace IDCache
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
add_library(main SHARED
|
add_library(main SHARED
|
||||||
|
Cheats/ARCheat.cpp
|
||||||
|
Cheats/GeckoCheat.cpp
|
||||||
|
Cheats/PatchCheat.cpp
|
||||||
Config/NativeConfig.cpp
|
Config/NativeConfig.cpp
|
||||||
Config/PostProcessing.cpp
|
Config/PostProcessing.cpp
|
||||||
GameList/GameFile.cpp
|
GameList/GameFile.cpp
|
||||||
|
67
Source/Android/jni/Cheats/ARCheat.cpp
Normal file
67
Source/Android/jni/Cheats/ARCheat.cpp
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
// Copyright 2021 Dolphin Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <jni.h>
|
||||||
|
|
||||||
|
#include "Common/FileUtil.h"
|
||||||
|
#include "Common/IniFile.h"
|
||||||
|
#include "Core/ActionReplay.h"
|
||||||
|
#include "Core/ConfigManager.h"
|
||||||
|
#include "jni/AndroidCommon/AndroidCommon.h"
|
||||||
|
#include "jni/AndroidCommon/IDCache.h"
|
||||||
|
|
||||||
|
static ActionReplay::ARCode* GetPointer(JNIEnv* env, jobject obj)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<ActionReplay::ARCode*>(
|
||||||
|
env->GetLongField(obj, IDCache::GetARCheatPointer()));
|
||||||
|
}
|
||||||
|
|
||||||
|
jobject ARCheatToJava(JNIEnv* env, const ActionReplay::ARCode& code)
|
||||||
|
{
|
||||||
|
return env->NewObject(IDCache::GetARCheatClass(), IDCache::GetARCheatConstructor(),
|
||||||
|
reinterpret_cast<jlong>(new ActionReplay::ARCode(code)));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL
|
||||||
|
Java_org_dolphinemu_dolphinemu_features_cheats_model_ARCheat_finalize(JNIEnv* env, jobject obj)
|
||||||
|
{
|
||||||
|
delete GetPointer(env, obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jstring JNICALL
|
||||||
|
Java_org_dolphinemu_dolphinemu_features_cheats_model_ARCheat_getName(JNIEnv* env, jobject obj)
|
||||||
|
{
|
||||||
|
return ToJString(env, GetPointer(env, obj)->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jobjectArray JNICALL
|
||||||
|
Java_org_dolphinemu_dolphinemu_features_cheats_model_ARCheat_loadCodes(JNIEnv* env, jclass,
|
||||||
|
jstring jGameID,
|
||||||
|
jint revision)
|
||||||
|
{
|
||||||
|
const std::string game_id = GetJString(env, jGameID);
|
||||||
|
IniFile game_ini_local;
|
||||||
|
|
||||||
|
// We don't use LoadLocalGameIni() here because user cheat codes that are installed via the UI
|
||||||
|
// will always be stored in GS/${GAMEID}.ini
|
||||||
|
game_ini_local.Load(File::GetUserPath(D_GAMESETTINGS_IDX) + game_id + ".ini");
|
||||||
|
const IniFile game_ini_default = SConfig::LoadDefaultGameIni(game_id, revision);
|
||||||
|
|
||||||
|
const std::vector<ActionReplay::ARCode> codes =
|
||||||
|
ActionReplay::LoadCodes(game_ini_default, game_ini_local);
|
||||||
|
|
||||||
|
const jobjectArray array =
|
||||||
|
env->NewObjectArray(static_cast<jsize>(codes.size()), IDCache::GetARCheatClass(), nullptr);
|
||||||
|
|
||||||
|
jsize i = 0;
|
||||||
|
for (const ActionReplay::ARCode& code : codes)
|
||||||
|
env->SetObjectArrayElement(array, i++, ARCheatToJava(env, code));
|
||||||
|
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
}
|
67
Source/Android/jni/Cheats/GeckoCheat.cpp
Normal file
67
Source/Android/jni/Cheats/GeckoCheat.cpp
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
// Copyright 2021 Dolphin Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <jni.h>
|
||||||
|
|
||||||
|
#include "Common/FileUtil.h"
|
||||||
|
#include "Common/IniFile.h"
|
||||||
|
#include "Core/ConfigManager.h"
|
||||||
|
#include "Core/GeckoCode.h"
|
||||||
|
#include "Core/GeckoCodeConfig.h"
|
||||||
|
#include "jni/AndroidCommon/AndroidCommon.h"
|
||||||
|
#include "jni/AndroidCommon/IDCache.h"
|
||||||
|
|
||||||
|
static Gecko::GeckoCode* GetPointer(JNIEnv* env, jobject obj)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<Gecko::GeckoCode*>(
|
||||||
|
env->GetLongField(obj, IDCache::GetGeckoCheatPointer()));
|
||||||
|
}
|
||||||
|
|
||||||
|
jobject GeckoCheatToJava(JNIEnv* env, const Gecko::GeckoCode& code)
|
||||||
|
{
|
||||||
|
return env->NewObject(IDCache::GetGeckoCheatClass(), IDCache::GetGeckoCheatConstructor(),
|
||||||
|
reinterpret_cast<jlong>(new Gecko::GeckoCode(code)));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL
|
||||||
|
Java_org_dolphinemu_dolphinemu_features_cheats_model_GeckoCheat_finalize(JNIEnv* env, jobject obj)
|
||||||
|
{
|
||||||
|
delete GetPointer(env, obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jstring JNICALL
|
||||||
|
Java_org_dolphinemu_dolphinemu_features_cheats_model_GeckoCheat_getName(JNIEnv* env, jobject obj)
|
||||||
|
{
|
||||||
|
return ToJString(env, GetPointer(env, obj)->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jobjectArray JNICALL
|
||||||
|
Java_org_dolphinemu_dolphinemu_features_cheats_model_GeckoCheat_loadCodes(JNIEnv* env, jclass,
|
||||||
|
jstring jGameID,
|
||||||
|
jint revision)
|
||||||
|
{
|
||||||
|
const std::string game_id = GetJString(env, jGameID);
|
||||||
|
IniFile game_ini_local;
|
||||||
|
|
||||||
|
// We don't use LoadLocalGameIni() here because user cheat codes that are installed via the UI
|
||||||
|
// will always be stored in GS/${GAMEID}.ini
|
||||||
|
game_ini_local.Load(File::GetUserPath(D_GAMESETTINGS_IDX) + game_id + ".ini");
|
||||||
|
const IniFile game_ini_default = SConfig::LoadDefaultGameIni(game_id, revision);
|
||||||
|
|
||||||
|
const std::vector<Gecko::GeckoCode> codes = Gecko::LoadCodes(game_ini_default, game_ini_local);
|
||||||
|
|
||||||
|
const jobjectArray array =
|
||||||
|
env->NewObjectArray(static_cast<jsize>(codes.size()), IDCache::GetGeckoCheatClass(), nullptr);
|
||||||
|
|
||||||
|
jsize i = 0;
|
||||||
|
for (const Gecko::GeckoCode& code : codes)
|
||||||
|
env->SetObjectArrayElement(array, i++, GeckoCheatToJava(env, code));
|
||||||
|
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
}
|
67
Source/Android/jni/Cheats/PatchCheat.cpp
Normal file
67
Source/Android/jni/Cheats/PatchCheat.cpp
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
// Copyright 2021 Dolphin Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <jni.h>
|
||||||
|
|
||||||
|
#include "Common/FileUtil.h"
|
||||||
|
#include "Common/IniFile.h"
|
||||||
|
#include "Core/ConfigManager.h"
|
||||||
|
#include "Core/PatchEngine.h"
|
||||||
|
#include "jni/AndroidCommon/AndroidCommon.h"
|
||||||
|
#include "jni/AndroidCommon/IDCache.h"
|
||||||
|
|
||||||
|
static PatchEngine::Patch* GetPointer(JNIEnv* env, jobject obj)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<PatchEngine::Patch*>(
|
||||||
|
env->GetLongField(obj, IDCache::GetPatchCheatPointer()));
|
||||||
|
}
|
||||||
|
|
||||||
|
jobject PatchCheatToJava(JNIEnv* env, const PatchEngine::Patch& patch)
|
||||||
|
{
|
||||||
|
return env->NewObject(IDCache::GetPatchCheatClass(), IDCache::GetPatchCheatConstructor(),
|
||||||
|
reinterpret_cast<jlong>(new PatchEngine::Patch(patch)));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL
|
||||||
|
Java_org_dolphinemu_dolphinemu_features_cheats_model_PatchCheat_finalize(JNIEnv* env, jobject obj)
|
||||||
|
{
|
||||||
|
delete GetPointer(env, obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jstring JNICALL
|
||||||
|
Java_org_dolphinemu_dolphinemu_features_cheats_model_PatchCheat_getName(JNIEnv* env, jobject obj)
|
||||||
|
{
|
||||||
|
return ToJString(env, GetPointer(env, obj)->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jobjectArray JNICALL
|
||||||
|
Java_org_dolphinemu_dolphinemu_features_cheats_model_PatchCheat_loadCodes(JNIEnv* env, jclass,
|
||||||
|
jstring jGameID,
|
||||||
|
jint revision)
|
||||||
|
{
|
||||||
|
const std::string game_id = GetJString(env, jGameID);
|
||||||
|
IniFile game_ini_local;
|
||||||
|
|
||||||
|
// We don't use LoadLocalGameIni() here because user cheat codes that are installed via the UI
|
||||||
|
// will always be stored in GS/${GAMEID}.ini
|
||||||
|
game_ini_local.Load(File::GetUserPath(D_GAMESETTINGS_IDX) + game_id + ".ini");
|
||||||
|
const IniFile game_ini_default = SConfig::LoadDefaultGameIni(game_id, revision);
|
||||||
|
|
||||||
|
std::vector<PatchEngine::Patch> patches;
|
||||||
|
PatchEngine::LoadPatchSection("OnFrame", &patches, game_ini_default, game_ini_local);
|
||||||
|
|
||||||
|
const jobjectArray array = env->NewObjectArray(static_cast<jsize>(patches.size()),
|
||||||
|
IDCache::GetPatchCheatClass(), nullptr);
|
||||||
|
|
||||||
|
jsize i = 0;
|
||||||
|
for (const PatchEngine::Patch& patch : patches)
|
||||||
|
env->SetObjectArrayElement(array, i++, PatchCheatToJava(env, patch));
|
||||||
|
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user