diff options
Diffstat (limited to 'Source/Android/app/src/main/java')
5 files changed, 334 insertions, 1 deletions
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/riivolution/model/RiivolutionPatches.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/riivolution/model/RiivolutionPatches.java new file mode 100644 index 0000000000..6d2ff51b6b --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/riivolution/model/RiivolutionPatches.java @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +package org.dolphinemu.dolphinemu.features.riivolution.model; + +import androidx.annotation.Keep; + +public class RiivolutionPatches +{ + private String mGameId; + private int mRevision; + private int mDiscNumber; + + private boolean mUnsavedChanges = false; + + @Keep + private long mPointer; + + public RiivolutionPatches(String gameId, int revision, int discNumber) + { + mGameId = gameId; + mRevision = revision; + mDiscNumber = discNumber; + + mPointer = initialize(); + } + + @Override + public native void finalize(); + + private static native long initialize(); + + public native int getDiscCount(); + + public native String getDiscName(int discIndex); + + public native int getSectionCount(int discIndex); + + public native String getSectionName(int discIndex, int sectionIndex); + + public native int getOptionCount(int discIndex, int sectionIndex); + + public native String getOptionName(int discIndex, int sectionIndex, int optionIndex); + + public native int getChoiceCount(int discIndex, int sectionIndex, int optionIndex); + + public native String getChoiceName(int discIndex, int sectionIndex, int optionIndex, + int choiceIndex); + + /** + * @return 0 if no choice is selected, otherwise the index of the selected choice plus one. + */ + public native int getSelectedChoice(int discIndex, int sectionIndex, int optionIndex); + + /** + * @param choiceIndex 0 to select no choice, otherwise the choice index plus one. + */ + public void setSelectedChoice(int discIndex, int sectionIndex, int optionIndex, int choiceIndex) + { + mUnsavedChanges = true; + setSelectedChoiceImpl(discIndex, sectionIndex, optionIndex, choiceIndex); + } + + /** + * @param choiceIndex 0 to select no choice, otherwise the choice index plus one. + */ + private native void setSelectedChoiceImpl(int discIndex, int sectionIndex, int optionIndex, + int choiceIndex); + + public void loadConfig() + { + loadConfigImpl(mGameId, mRevision, mDiscNumber); + } + + private native void loadConfigImpl(String gameId, int revision, int discNumber); + + public void saveConfig() + { + if (mUnsavedChanges) + { + mUnsavedChanges = false; + saveConfigImpl(mGameId); + } + } + + private native void saveConfigImpl(String gameId); +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/riivolution/ui/RiivolutionAdapter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/riivolution/ui/RiivolutionAdapter.java new file mode 100644 index 0000000000..d1fe8ca5b3 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/riivolution/ui/RiivolutionAdapter.java @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +package org.dolphinemu.dolphinemu.features.riivolution.ui; + +import android.content.Context; +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.riivolution.model.RiivolutionPatches; + +import java.util.ArrayList; + +public class RiivolutionAdapter extends RecyclerView.Adapter<RiivolutionViewHolder> +{ + private final Context mContext; + private final RiivolutionPatches mPatches; + private final ArrayList<RiivolutionItem> mItems = new ArrayList<>(); + + public RiivolutionAdapter(Context context, RiivolutionPatches patches) + { + mContext = context; + mPatches = patches; + + int discCount = mPatches.getDiscCount(); + for (int i = 0; i < discCount; i++) + { + mItems.add(new RiivolutionItem(i)); + + int sectionCount = mPatches.getSectionCount(i); + for (int j = 0; j < sectionCount; j++) + { + mItems.add(new RiivolutionItem(i, j)); + + int optionCount = mPatches.getOptionCount(i, j); + for (int k = 0; k < optionCount; k++) + { + mItems.add(new RiivolutionItem(i, j, k)); + } + } + } + } + + @NonNull @Override + public RiivolutionViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) + { + LayoutInflater inflater = LayoutInflater.from(parent.getContext()); + + switch (viewType) + { + case RiivolutionViewHolder.TYPE_HEADER: + View headerView = inflater.inflate(R.layout.list_item_riivolution_header, parent, false); + return new RiivolutionViewHolder(headerView); + case RiivolutionViewHolder.TYPE_OPTION: + View optionView = inflater.inflate(R.layout.list_item_riivolution_option, parent, false); + return new RiivolutionViewHolder(optionView); + default: + throw new UnsupportedOperationException(); + } + } + + @Override + public void onBindViewHolder(@NonNull RiivolutionViewHolder holder, int position) + { + holder.bind(mContext, mPatches, mItems.get(position)); + } + + @Override + public int getItemCount() + { + return mItems.size(); + } + + @Override + public int getItemViewType(int position) + { + return mItems.get(position).mOptionIndex != -1 ? + RiivolutionViewHolder.TYPE_OPTION : RiivolutionViewHolder.TYPE_HEADER; + } +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/riivolution/ui/RiivolutionBootActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/riivolution/ui/RiivolutionBootActivity.java index 1b6e55df98..37921c4af8 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/riivolution/ui/RiivolutionBootActivity.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/riivolution/ui/RiivolutionBootActivity.java @@ -7,10 +7,15 @@ import android.content.Intent; import android.os.Bundle; import android.widget.Button; +import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; import org.dolphinemu.dolphinemu.R; import org.dolphinemu.dolphinemu.activities.EmulationActivity; +import org.dolphinemu.dolphinemu.features.riivolution.model.RiivolutionPatches; +import org.dolphinemu.dolphinemu.ui.DividerItemDecoration; public class RiivolutionBootActivity extends AppCompatActivity { @@ -19,6 +24,8 @@ public class RiivolutionBootActivity extends AppCompatActivity private static final String ARG_REVISION = "revision"; private static final String ARG_DISC_NUMBER = "disc_number"; + private RiivolutionPatches mPatches; + public static void launch(Context context, String gamePath, String gameId, int revision, int discNumber) { @@ -45,6 +52,38 @@ public class RiivolutionBootActivity extends AppCompatActivity int discNumber = intent.getIntExtra(ARG_DISC_NUMBER, -1); Button buttonStart = findViewById(R.id.button_start); - buttonStart.setOnClickListener((v) -> EmulationActivity.launch(this, path, true)); + buttonStart.setOnClickListener((v) -> + { + if (mPatches != null) + mPatches.saveConfig(); + + EmulationActivity.launch(this, path, true); + }); + + new Thread(() -> + { + RiivolutionPatches patches = new RiivolutionPatches(gameId, revision, discNumber); + patches.loadConfig(); + runOnUiThread(() -> populateList(patches)); + }).start(); + } + + @Override + protected void onStop() + { + super.onStop(); + + if (mPatches != null) + mPatches.saveConfig(); + } + + private void populateList(RiivolutionPatches patches) + { + mPatches = patches; + + RecyclerView recyclerView = findViewById(R.id.recycler_view); + + recyclerView.setAdapter(new RiivolutionAdapter(this, patches)); + recyclerView.setLayoutManager(new LinearLayoutManager(this)); } } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/riivolution/ui/RiivolutionItem.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/riivolution/ui/RiivolutionItem.java new file mode 100644 index 0000000000..8d2ef17e5b --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/riivolution/ui/RiivolutionItem.java @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +package org.dolphinemu.dolphinemu.features.riivolution.ui; + +public class RiivolutionItem +{ + public final int mDiscIndex; + public final int mSectionIndex; + public final int mOptionIndex; + + /** + * Constructor for a disc. + */ + public RiivolutionItem(int discIndex) + { + mDiscIndex = discIndex; + mSectionIndex = -1; + mOptionIndex = -1; + } + + /** + * Constructor for a section. + */ + public RiivolutionItem(int discIndex, int sectionIndex) + { + mDiscIndex = discIndex; + mSectionIndex = sectionIndex; + mOptionIndex = -1; + } + + /** + * Constructor for an option. + */ + public RiivolutionItem(int discIndex, int sectionIndex, int optionIndex) + { + mDiscIndex = discIndex; + mSectionIndex = sectionIndex; + mOptionIndex = optionIndex; + } +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/riivolution/ui/RiivolutionViewHolder.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/riivolution/ui/RiivolutionViewHolder.java new file mode 100644 index 0000000000..e51a575262 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/riivolution/ui/RiivolutionViewHolder.java @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +package org.dolphinemu.dolphinemu.features.riivolution.ui; + +import android.content.Context; +import android.view.View; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.Spinner; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.recyclerview.widget.RecyclerView; + +import org.dolphinemu.dolphinemu.R; +import org.dolphinemu.dolphinemu.features.riivolution.model.RiivolutionPatches; + +public class RiivolutionViewHolder extends RecyclerView.ViewHolder + implements AdapterView.OnItemSelectedListener +{ + public static final int TYPE_HEADER = 0; + public static final int TYPE_OPTION = 1; + + private final TextView mTextView; + private final Spinner mSpinner; + + private RiivolutionPatches mPatches; + private RiivolutionItem mItem; + + public RiivolutionViewHolder(@NonNull View itemView) + { + super(itemView); + + mTextView = itemView.findViewById(R.id.text_name); + mSpinner = itemView.findViewById(R.id.spinner_choice); + } + + public void bind(Context context, RiivolutionPatches patches, RiivolutionItem item) + { + String text; + if (item.mOptionIndex != -1) + text = patches.getOptionName(item.mDiscIndex, item.mSectionIndex, item.mOptionIndex); + else if (item.mSectionIndex != -1) + text = patches.getSectionName(item.mDiscIndex, item.mSectionIndex); + else + text = patches.getDiscName(item.mDiscIndex); + mTextView.setText(text); + + if (item.mOptionIndex != -1) + { + mPatches = patches; + mItem = item; + + ArrayAdapter<String> adapter = new ArrayAdapter<>(context, + R.layout.list_item_riivolution_header); + + int choiceCount = patches.getChoiceCount(mItem.mDiscIndex, mItem.mSectionIndex, + mItem.mOptionIndex); + adapter.add(context.getString(R.string.riivolution_disabled)); + for (int i = 0; i < choiceCount; i++) + { + adapter.add(patches.getChoiceName(mItem.mDiscIndex, mItem.mSectionIndex, mItem.mOptionIndex, + i)); + } + + mSpinner.setAdapter(adapter); + mSpinner.setSelection(patches.getSelectedChoice(mItem.mDiscIndex, mItem.mSectionIndex, + mItem.mOptionIndex)); + mSpinner.setOnItemSelectedListener(this); + } + } + + @Override + public void onItemSelected(AdapterView<?> parent, View view, int position, long id) + { + mPatches.setSelectedChoice(mItem.mDiscIndex, mItem.mSectionIndex, mItem.mOptionIndex, position); + } + + @Override + public void onNothingSelected(AdapterView<?> parent) + { + } +} |
