Android: Infinity Base UI

Add a UI option for the Infinity Base within the Android Emulation Activity
This commit is contained in:
Joshua de Reeper 2023-05-01 22:30:31 +12:00
parent 6d9529a68d
commit f8abc2c0e6
16 changed files with 586 additions and 37 deletions

View File

@ -38,7 +38,11 @@ import org.dolphinemu.dolphinemu.NativeLibrary;
import org.dolphinemu.dolphinemu.R; import org.dolphinemu.dolphinemu.R;
import org.dolphinemu.dolphinemu.databinding.ActivityEmulationBinding; import org.dolphinemu.dolphinemu.databinding.ActivityEmulationBinding;
import org.dolphinemu.dolphinemu.databinding.DialogInputAdjustBinding; import org.dolphinemu.dolphinemu.databinding.DialogInputAdjustBinding;
import org.dolphinemu.dolphinemu.databinding.DialogSkylandersManagerBinding; import org.dolphinemu.dolphinemu.databinding.DialogNfcFiguresManagerBinding;
import org.dolphinemu.dolphinemu.features.infinitybase.InfinityConfig;
import org.dolphinemu.dolphinemu.features.infinitybase.model.Figure;
import org.dolphinemu.dolphinemu.features.infinitybase.ui.FigureSlot;
import org.dolphinemu.dolphinemu.features.infinitybase.ui.FigureSlotAdapter;
import org.dolphinemu.dolphinemu.features.input.model.ControllerInterface; import org.dolphinemu.dolphinemu.features.input.model.ControllerInterface;
import org.dolphinemu.dolphinemu.features.input.model.DolphinSensorEventListener; import org.dolphinemu.dolphinemu.features.input.model.DolphinSensorEventListener;
import org.dolphinemu.dolphinemu.features.settings.model.BooleanSetting; import org.dolphinemu.dolphinemu.features.settings.model.BooleanSetting;
@ -78,6 +82,8 @@ public final class EmulationActivity extends AppCompatActivity implements ThemeP
public static final int REQUEST_CHANGE_DISC = 1; public static final int REQUEST_CHANGE_DISC = 1;
public static final int REQUEST_SKYLANDER_FILE = 2; public static final int REQUEST_SKYLANDER_FILE = 2;
public static final int REQUEST_CREATE_SKYLANDER = 3; public static final int REQUEST_CREATE_SKYLANDER = 3;
public static final int REQUEST_INFINITY_FIGURE_FILE = 4;
public static final int REQUEST_CREATE_INFINITY_FIGURE = 5;
private EmulationFragment mEmulationFragment; private EmulationFragment mEmulationFragment;
@ -107,6 +113,10 @@ public final class EmulationActivity extends AppCompatActivity implements ThemeP
public static final String EXTRA_SKYLANDER_ID = "SkylanderId"; public static final String EXTRA_SKYLANDER_ID = "SkylanderId";
public static final String EXTRA_SKYLANDER_VAR = "SkylanderVar"; public static final String EXTRA_SKYLANDER_VAR = "SkylanderVar";
public static final String EXTRA_SKYLANDER_NAME = "SkylanderName"; public static final String EXTRA_SKYLANDER_NAME = "SkylanderName";
public static final String EXTRA_INFINITY_POSITION = "FigurePosition";
public static final String EXTRA_INFINITY_LIST_POSITION = "FigureListPosition";
public static final String EXTRA_INFINITY_NUM = "FigureNum";
public static final String EXTRA_INFINITY_NAME = "FigureName";
@Retention(SOURCE) @Retention(SOURCE)
@IntDef( @IntDef(
@ -121,7 +131,7 @@ public final class EmulationActivity extends AppCompatActivity implements ThemeP
MENU_ACTION_RESET_OVERLAY, MENU_SET_IR_RECENTER, MENU_SET_IR_MODE, MENU_ACTION_RESET_OVERLAY, MENU_SET_IR_RECENTER, MENU_SET_IR_MODE,
MENU_ACTION_CHOOSE_DOUBLETAP, MENU_ACTION_PAUSE_EMULATION, MENU_ACTION_CHOOSE_DOUBLETAP, MENU_ACTION_PAUSE_EMULATION,
MENU_ACTION_UNPAUSE_EMULATION, MENU_ACTION_OVERLAY_CONTROLS, MENU_ACTION_SETTINGS, MENU_ACTION_UNPAUSE_EMULATION, MENU_ACTION_OVERLAY_CONTROLS, MENU_ACTION_SETTINGS,
MENU_ACTION_SKYLANDERS}) MENU_ACTION_SKYLANDERS, MENU_ACTION_INFINITY_BASE})
public @interface MenuAction public @interface MenuAction
{ {
} }
@ -160,14 +170,20 @@ public final class EmulationActivity extends AppCompatActivity implements ThemeP
public static final int MENU_ACTION_OVERLAY_CONTROLS = 34; public static final int MENU_ACTION_OVERLAY_CONTROLS = 34;
public static final int MENU_ACTION_SETTINGS = 35; public static final int MENU_ACTION_SETTINGS = 35;
public static final int MENU_ACTION_SKYLANDERS = 36; public static final int MENU_ACTION_SKYLANDERS = 36;
public static final int MENU_ACTION_INFINITY_BASE = 37;
private Skylander mSkylanderData = new Skylander(-1, -1, "Slot"); private Skylander mSkylanderData = new Skylander(-1, -1, "Slot");
private Figure mInfinityFigureData = new Figure(-1, "Position");
private int mSkylanderSlot = -1; private int mSkylanderSlot = -1;
private int mInfinityPosition = -1;
private int mInfinityListPosition = -1;
private DialogSkylandersManagerBinding mSkylandersBinding; private DialogNfcFiguresManagerBinding mSkylandersBinding;
private DialogNfcFiguresManagerBinding mInfinityBinding;
private static List<SkylanderSlot> sSkylanderSlots = new ArrayList<>(); private static List<SkylanderSlot> sSkylanderSlots = new ArrayList<>();
private static List<FigureSlot> sInfinityFigures = new ArrayList<>();
private static final SparseIntArray buttonsActionsMap = new SparseIntArray(); private static final SparseIntArray buttonsActionsMap = new SparseIntArray();
@ -348,6 +364,17 @@ public final class EmulationActivity extends AppCompatActivity implements ThemeP
sSkylanderSlots.add(new SkylanderSlot(getString(R.string.skylander_slot, i + 1), i)); sSkylanderSlots.add(new SkylanderSlot(getString(R.string.skylander_slot, i + 1), i));
} }
} }
if (sInfinityFigures.isEmpty())
{
sInfinityFigures.add(new FigureSlot(getString(R.string.infinity_hexagon_label), 0));
sInfinityFigures.add(new FigureSlot(getString(R.string.infinity_p1_label), 1));
sInfinityFigures.add(new FigureSlot(getString(R.string.infinity_p1a1_label), 3));
sInfinityFigures.add(new FigureSlot(getString(R.string.infinity_p1a2_label), 5));
sInfinityFigures.add(new FigureSlot(getString(R.string.infinity_p2_label), 2));
sInfinityFigures.add(new FigureSlot(getString(R.string.infinity_p2a1_label), 4));
sInfinityFigures.add(new FigureSlot(getString(R.string.infinity_p2a2_label), 6));
}
} }
@Override @Override
@ -364,6 +391,10 @@ public final class EmulationActivity extends AppCompatActivity implements ThemeP
outState.putInt(EXTRA_SKYLANDER_ID, mSkylanderData.getId()); outState.putInt(EXTRA_SKYLANDER_ID, mSkylanderData.getId());
outState.putInt(EXTRA_SKYLANDER_VAR, mSkylanderData.getVariant()); outState.putInt(EXTRA_SKYLANDER_VAR, mSkylanderData.getVariant());
outState.putString(EXTRA_SKYLANDER_NAME, mSkylanderData.getName()); outState.putString(EXTRA_SKYLANDER_NAME, mSkylanderData.getName());
outState.putInt(EXTRA_INFINITY_POSITION, mInfinityPosition);
outState.putInt(EXTRA_INFINITY_LIST_POSITION, mInfinityListPosition);
outState.putLong(EXTRA_INFINITY_NUM, mInfinityFigureData.getNumber());
outState.putString(EXTRA_INFINITY_NAME, mInfinityFigureData.getName());
super.onSaveInstanceState(outState); super.onSaveInstanceState(outState);
} }
@ -376,6 +407,10 @@ public final class EmulationActivity extends AppCompatActivity implements ThemeP
mSkylanderData = new Skylander(savedInstanceState.getInt(EXTRA_SKYLANDER_ID), mSkylanderData = new Skylander(savedInstanceState.getInt(EXTRA_SKYLANDER_ID),
savedInstanceState.getInt(EXTRA_SKYLANDER_VAR), savedInstanceState.getInt(EXTRA_SKYLANDER_VAR),
savedInstanceState.getString(EXTRA_SKYLANDER_NAME)); savedInstanceState.getString(EXTRA_SKYLANDER_NAME));
mInfinityPosition = savedInstanceState.getInt(EXTRA_INFINITY_POSITION);
mInfinityListPosition = savedInstanceState.getInt(EXTRA_INFINITY_LIST_POSITION);
mInfinityFigureData = new Figure(savedInstanceState.getLong(EXTRA_INFINITY_NUM),
savedInstanceState.getString(EXTRA_INFINITY_NAME));
} }
@Override @Override
@ -486,7 +521,7 @@ public final class EmulationActivity extends AppCompatActivity implements ThemeP
clearSkylander(mSkylanderSlot); clearSkylander(mSkylanderSlot);
sSkylanderSlots.get(mSkylanderSlot).setPortalSlot(slot.first); sSkylanderSlots.get(mSkylanderSlot).setPortalSlot(slot.first);
sSkylanderSlots.get(mSkylanderSlot).setLabel(slot.second); sSkylanderSlots.get(mSkylanderSlot).setLabel(slot.second);
mSkylandersBinding.skylandersManager.getAdapter().notifyItemChanged(mSkylanderSlot); mSkylandersBinding.figureManager.getAdapter().notifyItemChanged(mSkylanderSlot);
mSkylanderSlot = -1; mSkylanderSlot = -1;
mSkylanderData = Skylander.BLANK_SKYLANDER; mSkylanderData = Skylander.BLANK_SKYLANDER;
} }
@ -500,11 +535,48 @@ public final class EmulationActivity extends AppCompatActivity implements ThemeP
clearSkylander(mSkylanderSlot); clearSkylander(mSkylanderSlot);
sSkylanderSlots.get(mSkylanderSlot).setPortalSlot(slot.first); sSkylanderSlots.get(mSkylanderSlot).setPortalSlot(slot.first);
sSkylanderSlots.get(mSkylanderSlot).setLabel(slot.second); sSkylanderSlots.get(mSkylanderSlot).setLabel(slot.second);
mSkylandersBinding.skylandersManager.getAdapter().notifyItemChanged(mSkylanderSlot); mSkylandersBinding.figureManager.getAdapter().notifyItemChanged(mSkylanderSlot);
mSkylanderSlot = -1; mSkylanderSlot = -1;
mSkylanderData = Skylander.BLANK_SKYLANDER; mSkylanderData = Skylander.BLANK_SKYLANDER;
} }
} }
else if (requestCode == REQUEST_INFINITY_FIGURE_FILE)
{
String label = InfinityConfig.loadFigure(mInfinityPosition, result.getData().toString());
if (label != null && !label.equals("Unknown Figure"))
{
clearInfinityFigure(mInfinityListPosition);
sInfinityFigures.get(mInfinityListPosition).setLabel(label);
mInfinityBinding.figureManager.getAdapter().notifyItemChanged(mInfinityListPosition);
mInfinityPosition = -1;
mInfinityListPosition = -1;
mInfinityFigureData = Figure.BLANK_FIGURE;
}
else
{
new MaterialAlertDialogBuilder(this)
.setTitle(R.string.incompatible_figure_selected)
.setMessage(R.string.select_compatible_figure)
.setPositiveButton(R.string.ok, null)
.show();
}
}
else if (requestCode == REQUEST_CREATE_INFINITY_FIGURE)
{
if (!(mInfinityFigureData.getNumber() == -1))
{
String label =
InfinityConfig.createFigure(mInfinityFigureData.getNumber(),
result.getData().toString(),
mInfinityPosition);
clearInfinityFigure(mInfinityListPosition);
sInfinityFigures.get(mInfinityListPosition).setLabel(label);
mInfinityBinding.figureManager.getAdapter().notifyItemChanged(mInfinityListPosition);
mInfinityPosition = -1;
mInfinityListPosition = -1;
mInfinityFigureData = Figure.BLANK_FIGURE;
}
}
} }
} }
@ -775,6 +847,10 @@ public final class EmulationActivity extends AppCompatActivity implements ThemeP
showSkylanderPortalSettings(); showSkylanderPortalSettings();
break; break;
case MENU_ACTION_INFINITY_BASE:
showInfinityBaseSettings();
break;
case MENU_ACTION_EXIT: case MENU_ACTION_EXIT:
mEmulationFragment.stopEmulation(); mEmulationFragment.stopEmulation();
break; break;
@ -1036,10 +1112,10 @@ public final class EmulationActivity extends AppCompatActivity implements ThemeP
private void showSkylanderPortalSettings() private void showSkylanderPortalSettings()
{ {
mSkylandersBinding = mSkylandersBinding =
DialogSkylandersManagerBinding.inflate(getLayoutInflater()); DialogNfcFiguresManagerBinding.inflate(getLayoutInflater());
mSkylandersBinding.skylandersManager.setLayoutManager(new LinearLayoutManager(this)); mSkylandersBinding.figureManager.setLayoutManager(new LinearLayoutManager(this));
mSkylandersBinding.skylandersManager.setAdapter( mSkylandersBinding.figureManager.setAdapter(
new SkylanderSlotAdapter(sSkylanderSlots, this)); new SkylanderSlotAdapter(sSkylanderSlots, this));
new MaterialAlertDialogBuilder(this) new MaterialAlertDialogBuilder(this)
@ -1048,6 +1124,21 @@ public final class EmulationActivity extends AppCompatActivity implements ThemeP
.show(); .show();
} }
private void showInfinityBaseSettings()
{
mInfinityBinding =
DialogNfcFiguresManagerBinding.inflate(getLayoutInflater());
mInfinityBinding.figureManager.setLayoutManager(new LinearLayoutManager(this));
mInfinityBinding.figureManager.setAdapter(
new FigureSlotAdapter(sInfinityFigures, this));
new MaterialAlertDialogBuilder(this)
.setTitle(R.string.infinity_manager)
.setView(mInfinityBinding.getRoot())
.show();
}
public void setSkylanderData(int id, int var, String name, int slot) public void setSkylanderData(int id, int var, String name, int slot)
{ {
mSkylanderData = new Skylander(id, var, name); mSkylanderData = new Skylander(id, var, name);
@ -1057,7 +1148,43 @@ public final class EmulationActivity extends AppCompatActivity implements ThemeP
public void clearSkylander(int slot) public void clearSkylander(int slot)
{ {
sSkylanderSlots.get(slot).setLabel(getString(R.string.skylander_slot, slot + 1)); sSkylanderSlots.get(slot).setLabel(getString(R.string.skylander_slot, slot + 1));
mSkylandersBinding.skylandersManager.getAdapter().notifyItemChanged(slot); mSkylandersBinding.figureManager.getAdapter().notifyItemChanged(slot);
}
public void setInfinityFigureData(Long num, String name, int position, int listPosition)
{
mInfinityFigureData = new Figure(num, name);
mInfinityPosition = position;
mInfinityListPosition = listPosition;
}
public void clearInfinityFigure(int position)
{
switch (position)
{
case 0:
sInfinityFigures.get(position).setLabel(getString(R.string.infinity_hexagon_label));
break;
case 1:
sInfinityFigures.get(position).setLabel(getString(R.string.infinity_p1_label));
break;
case 2:
sInfinityFigures.get(position).setLabel(getString(R.string.infinity_p1a1_label));
break;
case 3:
sInfinityFigures.get(position).setLabel(getString(R.string.infinity_p1a2_label));
break;
case 4:
sInfinityFigures.get(position).setLabel(getString(R.string.infinity_p2_label));
break;
case 5:
sInfinityFigures.get(position).setLabel(getString(R.string.infinity_p2a1_label));
break;
case 6:
sInfinityFigures.get(position).setLabel(getString(R.string.infinity_p2a2_label));
break;
}
mInfinityBinding.figureManager.getAdapter().notifyItemChanged(position);
} }
private void resetOverlay() private void resetOverlay()

View File

@ -0,0 +1,24 @@
// SPDX-License-Identifier: GPL-2.0-or-later
package org.dolphinemu.dolphinemu.features.infinitybase
object InfinityConfig {
var LIST_FIGURES: Map<Long, String> = getFigureMap()
var REVERSE_LIST_FIGURES: Map<String, Long> = getInverseFigureMap()
private external fun getFigureMap(): Map<Long, String>
private external fun getInverseFigureMap(): Map<String, Long>
@JvmStatic
external fun removeFigure(position: Int)
@JvmStatic
external fun loadFigure(position: Int, fileName: String): String?
@JvmStatic
external fun createFigure(
figureNumber: Long,
fileName: String,
position: Int
): String?
}

View File

@ -0,0 +1,11 @@
// SPDX-License-Identifier: GPL-2.0-or-later
package org.dolphinemu.dolphinemu.features.infinitybase.model
data class Figure(var number: Long, var name: String) {
companion object {
@JvmField
val BLANK_FIGURE = Figure(-1, "Blank")
}
}

View File

@ -0,0 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-or-later
package org.dolphinemu.dolphinemu.features.infinitybase.ui
data class FigureSlot(var label: String, val position: Int)

View File

@ -0,0 +1,149 @@
// SPDX-License-Identifier: GPL-2.0-or-later
package org.dolphinemu.dolphinemu.features.infinitybase.ui
import android.app.AlertDialog
import android.content.Intent
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.AdapterView
import android.widget.AdapterView.OnItemClickListener
import android.widget.ArrayAdapter
import android.widget.Toast
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import org.dolphinemu.dolphinemu.R
import org.dolphinemu.dolphinemu.activities.EmulationActivity
import org.dolphinemu.dolphinemu.databinding.DialogCreateInfinityFigureBinding
import org.dolphinemu.dolphinemu.databinding.ListItemNfcFigureSlotBinding
import org.dolphinemu.dolphinemu.features.infinitybase.InfinityConfig
import org.dolphinemu.dolphinemu.features.infinitybase.InfinityConfig.removeFigure
class FigureSlotAdapter(
private val figures: List<FigureSlot>,
private val activity: EmulationActivity
) : RecyclerView.Adapter<FigureSlotAdapter.ViewHolder>(),
OnItemClickListener {
class ViewHolder(var binding: ListItemNfcFigureSlotBinding) :
RecyclerView.ViewHolder(binding.getRoot())
private lateinit var binding: DialogCreateInfinityFigureBinding
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): ViewHolder {
val inflater = LayoutInflater.from(parent.context)
val binding = ListItemNfcFigureSlotBinding.inflate(inflater, parent, false)
return ViewHolder(binding)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val figure = figures[position]
holder.binding.textFigureName.text = figure.label
holder.binding.buttonClearFigure.setOnClickListener {
removeFigure(figure.position)
activity.clearInfinityFigure(position)
}
holder.binding.buttonLoadFigure.setOnClickListener {
val loadFigure = Intent(Intent.ACTION_OPEN_DOCUMENT)
loadFigure.addCategory(Intent.CATEGORY_OPENABLE)
loadFigure.type = "*/*"
activity.setInfinityFigureData(0, "", figure.position, position)
activity.startActivityForResult(
loadFigure,
EmulationActivity.REQUEST_INFINITY_FIGURE_FILE
)
}
val inflater = LayoutInflater.from(activity)
binding = DialogCreateInfinityFigureBinding.inflate(inflater)
binding.infinityDropdown.onItemClickListener = this
holder.binding.buttonCreateFigure.setOnClickListener {
var validFigures = InfinityConfig.REVERSE_LIST_FIGURES
// Filter adapter list by position, either Hexagon Pieces, Characters or Abilities
validFigures = when (figure.position) {
0 -> {
// Hexagon Pieces
validFigures.filter { (_, value) -> value in 2000000..2999999 || value in 4000000..4999999 }
}
1, 2 -> {
// Characters
validFigures.filter { (_, value) -> value in 1000000..1999999 }
}
else -> {
// Abilities
validFigures.filter { (_, value) -> value in 3000000..3999999 }
}
}
val figureListKeys = validFigures.keys.toMutableList()
figureListKeys.sort()
val figureNames: ArrayList<String> = ArrayList(figureListKeys)
binding.infinityDropdown.setAdapter(
ArrayAdapter(
activity, R.layout.support_simple_spinner_dropdown_item,
figureNames
)
)
if (binding.getRoot().parent != null) {
(binding.getRoot().parent as ViewGroup).removeAllViews()
}
val createDialog = MaterialAlertDialogBuilder(activity)
.setTitle(R.string.create_figure_title)
.setView(binding.getRoot())
.setPositiveButton(R.string.create_figure, null)
.setNegativeButton(R.string.cancel, null)
.show()
createDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {
if (binding.infinityNum.text.toString().isNotBlank()) {
val createFigure = Intent(Intent.ACTION_CREATE_DOCUMENT)
createFigure.addCategory(Intent.CATEGORY_OPENABLE)
createFigure.type = "*/*"
val num = binding.infinityNum.text.toString().toLong()
val name = InfinityConfig.LIST_FIGURES[num]
if (name != null) {
createFigure.putExtra(
Intent.EXTRA_TITLE,
"$name.bin"
)
activity.setInfinityFigureData(num, name, figure.position, position)
} else {
createFigure.putExtra(
Intent.EXTRA_TITLE,
"Unknown(Number: $num).bin"
)
activity.setInfinityFigureData(num, "Unknown", figure.position, position)
}
activity.startActivityForResult(
createFigure,
EmulationActivity.REQUEST_CREATE_INFINITY_FIGURE
)
createDialog.dismiss()
} else {
Toast.makeText(
activity, R.string.invalid_infinity_figure,
Toast.LENGTH_SHORT
).show()
}
}
}
}
override fun getItemCount(): Int {
return figures.size
}
override fun onItemClick(parent: AdapterView<*>, view: View, position: Int, id: Long) {
val figureNumber = InfinityConfig.REVERSE_LIST_FIGURES[parent.getItemAtPosition(position)]
binding.infinityNum.setText(figureNumber.toString())
}
}

View File

@ -217,6 +217,12 @@ enum class BooleanSetting(
"EmulateSkylanderPortal", "EmulateSkylanderPortal",
false false
), ),
MAIN_EMULATE_INFINITY_BASE(
Settings.FILE_DOLPHIN,
Settings.SECTION_EMULATED_USB_DEVICES,
"EmulateInfinityBase",
false
),
MAIN_SHOW_GAME_TITLES( MAIN_SHOW_GAME_TITLES(
Settings.FILE_DOLPHIN, Settings.FILE_DOLPHIN,
Settings.SECTION_INI_ANDROID, Settings.SECTION_INI_ANDROID,
@ -719,7 +725,8 @@ enum class BooleanSetting(
MAIN_RAM_OVERRIDE_ENABLE, MAIN_RAM_OVERRIDE_ENABLE,
MAIN_CUSTOM_RTC_ENABLE, MAIN_CUSTOM_RTC_ENABLE,
MAIN_DSP_JIT, MAIN_DSP_JIT,
MAIN_EMULATE_SKYLANDER_PORTAL MAIN_EMULATE_SKYLANDER_PORTAL,
MAIN_EMULATE_INFINITY_BASE
) )
private val NOT_RUNTIME_EDITABLE: Set<BooleanSetting> = private val NOT_RUNTIME_EDITABLE: Set<BooleanSetting> =
HashSet(listOf(*NOT_RUNTIME_EDITABLE_ARRAY)) HashSet(listOf(*NOT_RUNTIME_EDITABLE_ARRAY))

View File

@ -115,6 +115,7 @@ class SettingsFragmentPresenter(
controllerNumber, controllerNumber,
controllerType controllerType
) )
MenuTag.WIIMOTE_1, MenuTag.WIIMOTE_1,
MenuTag.WIIMOTE_2, MenuTag.WIIMOTE_2,
MenuTag.WIIMOTE_3, MenuTag.WIIMOTE_3,
@ -122,6 +123,7 @@ class SettingsFragmentPresenter(
sl, sl,
controllerNumber controllerNumber
) )
MenuTag.WIIMOTE_EXTENSION_1, MenuTag.WIIMOTE_EXTENSION_1,
MenuTag.WIIMOTE_EXTENSION_2, MenuTag.WIIMOTE_EXTENSION_2,
MenuTag.WIIMOTE_EXTENSION_3, MenuTag.WIIMOTE_EXTENSION_3,
@ -130,6 +132,7 @@ class SettingsFragmentPresenter(
controllerNumber, controllerNumber,
controllerType controllerType
) )
MenuTag.WIIMOTE_GENERAL_1, MenuTag.WIIMOTE_GENERAL_1,
MenuTag.WIIMOTE_GENERAL_2, MenuTag.WIIMOTE_GENERAL_2,
MenuTag.WIIMOTE_GENERAL_3, MenuTag.WIIMOTE_GENERAL_3,
@ -137,6 +140,7 @@ class SettingsFragmentPresenter(
sl, sl,
controllerNumber controllerNumber
) )
MenuTag.WIIMOTE_MOTION_SIMULATION_1, MenuTag.WIIMOTE_MOTION_SIMULATION_1,
MenuTag.WIIMOTE_MOTION_SIMULATION_2, MenuTag.WIIMOTE_MOTION_SIMULATION_2,
MenuTag.WIIMOTE_MOTION_SIMULATION_3, MenuTag.WIIMOTE_MOTION_SIMULATION_3,
@ -144,6 +148,7 @@ class SettingsFragmentPresenter(
sl, sl,
controllerNumber controllerNumber
) )
MenuTag.WIIMOTE_MOTION_INPUT_1, MenuTag.WIIMOTE_MOTION_INPUT_1,
MenuTag.WIIMOTE_MOTION_INPUT_2, MenuTag.WIIMOTE_MOTION_INPUT_2,
MenuTag.WIIMOTE_MOTION_INPUT_3, MenuTag.WIIMOTE_MOTION_INPUT_3,
@ -151,6 +156,7 @@ class SettingsFragmentPresenter(
sl, sl,
controllerNumber controllerNumber
) )
else -> throw UnsupportedOperationException("Unimplemented menu") else -> throw UnsupportedOperationException("Unimplemented menu")
} }
@ -454,10 +460,12 @@ class SettingsFragmentPresenter(
BooleanSetting.MAIN_DSP_HLE.setBoolean(settings, true) BooleanSetting.MAIN_DSP_HLE.setBoolean(settings, true)
BooleanSetting.MAIN_DSP_JIT.setBoolean(settings, true) BooleanSetting.MAIN_DSP_JIT.setBoolean(settings, true)
} }
DSP_LLE_RECOMPILER -> { DSP_LLE_RECOMPILER -> {
BooleanSetting.MAIN_DSP_HLE.setBoolean(settings, false) BooleanSetting.MAIN_DSP_HLE.setBoolean(settings, false)
BooleanSetting.MAIN_DSP_JIT.setBoolean(settings, true) BooleanSetting.MAIN_DSP_JIT.setBoolean(settings, true)
} }
DSP_LLE_INTERPRETER -> { DSP_LLE_INTERPRETER -> {
BooleanSetting.MAIN_DSP_HLE.setBoolean(settings, false) BooleanSetting.MAIN_DSP_HLE.setBoolean(settings, false)
BooleanSetting.MAIN_DSP_JIT.setBoolean(settings, false) BooleanSetting.MAIN_DSP_JIT.setBoolean(settings, false)
@ -834,6 +842,14 @@ class SettingsFragmentPresenter(
0 0
) )
) )
sl.add(
SwitchSetting(
context,
BooleanSetting.MAIN_EMULATE_INFINITY_BASE,
R.string.emulate_infinity_base,
0
)
)
} }
private fun addAdvancedSettings(sl: ArrayList<SettingsItem>) { private fun addAdvancedSettings(sl: ArrayList<SettingsItem>) {
@ -856,10 +872,12 @@ class SettingsFragmentPresenter(
BooleanSetting.MAIN_SYNC_ON_SKIP_IDLE.setBoolean(settings, false) BooleanSetting.MAIN_SYNC_ON_SKIP_IDLE.setBoolean(settings, false)
BooleanSetting.MAIN_SYNC_GPU.setBoolean(settings, false) BooleanSetting.MAIN_SYNC_GPU.setBoolean(settings, false)
} }
SYNC_GPU_ON_IDLE_SKIP -> { SYNC_GPU_ON_IDLE_SKIP -> {
BooleanSetting.MAIN_SYNC_ON_SKIP_IDLE.setBoolean(settings, true) BooleanSetting.MAIN_SYNC_ON_SKIP_IDLE.setBoolean(settings, true)
BooleanSetting.MAIN_SYNC_GPU.setBoolean(settings, false) BooleanSetting.MAIN_SYNC_GPU.setBoolean(settings, false)
} }
SYNC_GPU_ALWAYS -> { SYNC_GPU_ALWAYS -> {
BooleanSetting.MAIN_SYNC_ON_SKIP_IDLE.setBoolean(settings, true) BooleanSetting.MAIN_SYNC_ON_SKIP_IDLE.setBoolean(settings, true)
BooleanSetting.MAIN_SYNC_GPU.setBoolean(settings, true) BooleanSetting.MAIN_SYNC_GPU.setBoolean(settings, true)
@ -893,10 +911,12 @@ class SettingsFragmentPresenter(
emuCoresEntries = R.array.emuCoresEntriesX86_64 emuCoresEntries = R.array.emuCoresEntriesX86_64
emuCoresValues = R.array.emuCoresValuesX86_64 emuCoresValues = R.array.emuCoresValuesX86_64
} }
4 -> { 4 -> {
emuCoresEntries = R.array.emuCoresEntriesARM64 emuCoresEntries = R.array.emuCoresEntriesARM64
emuCoresValues = R.array.emuCoresValuesARM64 emuCoresValues = R.array.emuCoresValuesARM64
} }
else -> { else -> {
emuCoresEntries = R.array.emuCoresEntriesGeneric emuCoresEntries = R.array.emuCoresEntriesGeneric
emuCoresValues = R.array.emuCoresValuesGeneric emuCoresValues = R.array.emuCoresValuesGeneric
@ -2246,6 +2266,7 @@ class SettingsFragmentPresenter(
setting.uiSuffix setting.uiSuffix
) )
) )
NumericSetting.TYPE_BOOLEAN -> sl.add( NumericSetting.TYPE_BOOLEAN -> sl.add(
SwitchSetting( SwitchSetting(
InputMappingBooleanSetting(setting), InputMappingBooleanSetting(setting),

View File

@ -16,7 +16,7 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
import org.dolphinemu.dolphinemu.R import org.dolphinemu.dolphinemu.R
import org.dolphinemu.dolphinemu.activities.EmulationActivity import org.dolphinemu.dolphinemu.activities.EmulationActivity
import org.dolphinemu.dolphinemu.databinding.DialogCreateSkylanderBinding import org.dolphinemu.dolphinemu.databinding.DialogCreateSkylanderBinding
import org.dolphinemu.dolphinemu.databinding.ListItemSkylanderSlotBinding import org.dolphinemu.dolphinemu.databinding.ListItemNfcFigureSlotBinding
import org.dolphinemu.dolphinemu.features.skylanders.SkylanderConfig import org.dolphinemu.dolphinemu.features.skylanders.SkylanderConfig
import org.dolphinemu.dolphinemu.features.skylanders.SkylanderConfig.removeSkylander import org.dolphinemu.dolphinemu.features.skylanders.SkylanderConfig.removeSkylander
import org.dolphinemu.dolphinemu.features.skylanders.model.SkylanderPair import org.dolphinemu.dolphinemu.features.skylanders.model.SkylanderPair
@ -25,27 +25,27 @@ class SkylanderSlotAdapter(
private val slots: List<SkylanderSlot>, private val slots: List<SkylanderSlot>,
private val activity: EmulationActivity private val activity: EmulationActivity
) : RecyclerView.Adapter<SkylanderSlotAdapter.ViewHolder>(), OnItemClickListener { ) : RecyclerView.Adapter<SkylanderSlotAdapter.ViewHolder>(), OnItemClickListener {
class ViewHolder(var binding: ListItemSkylanderSlotBinding) : class ViewHolder(var binding: ListItemNfcFigureSlotBinding) :
RecyclerView.ViewHolder(binding.getRoot()) RecyclerView.ViewHolder(binding.getRoot())
private lateinit var binding: DialogCreateSkylanderBinding private lateinit var binding: DialogCreateSkylanderBinding
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val inflater = LayoutInflater.from(parent.context) val inflater = LayoutInflater.from(parent.context)
val binding = ListItemSkylanderSlotBinding.inflate(inflater, parent, false) val binding = ListItemNfcFigureSlotBinding.inflate(inflater, parent, false)
return ViewHolder(binding) return ViewHolder(binding)
} }
override fun onBindViewHolder(holder: ViewHolder, position: Int) { override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val slot = slots[position] val slot = slots[position]
holder.binding.textSkylanderName.text = slot.label holder.binding.textFigureName.text = slot.label
holder.binding.buttonClearSkylander.setOnClickListener { holder.binding.buttonClearFigure.setOnClickListener {
removeSkylander(slot.portalSlot) removeSkylander(slot.portalSlot)
activity.clearSkylander(slot.slotNum) activity.clearSkylander(slot.slotNum)
} }
holder.binding.buttonLoadSkylander.setOnClickListener { holder.binding.buttonLoadFigure.setOnClickListener {
val loadSkylander = Intent(Intent.ACTION_OPEN_DOCUMENT) val loadSkylander = Intent(Intent.ACTION_OPEN_DOCUMENT)
loadSkylander.addCategory(Intent.CATEGORY_OPENABLE) loadSkylander.addCategory(Intent.CATEGORY_OPENABLE)
loadSkylander.type = "*/*" loadSkylander.type = "*/*"
@ -71,14 +71,14 @@ class SkylanderSlotAdapter(
) )
binding.skylanderDropdown.onItemClickListener = this binding.skylanderDropdown.onItemClickListener = this
holder.binding.buttonCreateSkylander.setOnClickListener { holder.binding.buttonCreateFigure.setOnClickListener {
if (binding.getRoot().parent != null) { if (binding.getRoot().parent != null) {
(binding.getRoot().parent as ViewGroup).removeAllViews() (binding.getRoot().parent as ViewGroup).removeAllViews()
} }
val createDialog = MaterialAlertDialogBuilder(activity) val createDialog = MaterialAlertDialogBuilder(activity)
.setTitle(R.string.create_skylander_title) .setTitle(R.string.create_skylander_title)
.setView(binding.getRoot()) .setView(binding.getRoot())
.setPositiveButton(R.string.create_skylander, null) .setPositiveButton(R.string.create_figure, null)
.setNegativeButton(R.string.cancel, null) .setNegativeButton(R.string.cancel, null)
.show() .show()
createDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener { createDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {

View File

@ -61,6 +61,7 @@ public final class MenuFragment extends Fragment implements View.OnClickListener
buttonsActionsMap.append(R.id.menu_exit, EmulationActivity.MENU_ACTION_EXIT); buttonsActionsMap.append(R.id.menu_exit, EmulationActivity.MENU_ACTION_EXIT);
buttonsActionsMap.append(R.id.menu_settings, EmulationActivity.MENU_ACTION_SETTINGS); buttonsActionsMap.append(R.id.menu_settings, EmulationActivity.MENU_ACTION_SETTINGS);
buttonsActionsMap.append(R.id.menu_skylanders, EmulationActivity.MENU_ACTION_SKYLANDERS); buttonsActionsMap.append(R.id.menu_skylanders, EmulationActivity.MENU_ACTION_SKYLANDERS);
buttonsActionsMap.append(R.id.menu_infinitybase, EmulationActivity.MENU_ACTION_INFINITY_BASE);
} }
private FragmentIngameMenuBinding mBinding; private FragmentIngameMenuBinding mBinding;

View File

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout android:id="@+id/root"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="@dimen/spacing_medlarge">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/layout_infinity_dropdown"
style="@style/Widget.Material3.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="@dimen/spacing_medlarge"
android:paddingHorizontal="@dimen/spacing_medlarge"
android:hint="@string/infinity_label"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.textfield.MaterialAutoCompleteTextView
android:id="@+id/infinity_dropdown"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:spinnerMode="dialog"
android:imeOptions="actionDone" />
</com.google.android.material.textfield.TextInputLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintTop_toBottomOf="@+id/layout_infinity_dropdown"
android:gravity="center_vertical"
android:baselineAligned="false">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/layout_infinity_num"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="@string/infinity_number"
android:paddingHorizontal="@dimen/spacing_medlarge">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/infinity_num"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="number" />
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -4,10 +4,10 @@
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/skylanders_manager" android:id="@+id/figure_manager"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="20dp" android:layout_marginTop="20dp"
android:scrollbars="vertical" android:fadeScrollbars="false"
android:fadeScrollbars="false"/> android:scrollbars="vertical" />
</androidx.appcompat.widget.LinearLayoutCompat> </androidx.appcompat.widget.LinearLayoutCompat>

View File

@ -106,6 +106,11 @@
android:text="@string/emulate_skylander_portal" android:text="@string/emulate_skylander_portal"
style="@style/InGameMenuOption" /> style="@style/InGameMenuOption" />
<Button
android:id="@+id/menu_infinitybase"
android:text="@string/emulate_infinity_base"
style="@style/InGameMenuOption" />
</LinearLayout> </LinearLayout>
</ScrollView> </ScrollView>

View File

@ -8,43 +8,43 @@
android:padding="@dimen/spacing_medlarge"> android:padding="@dimen/spacing_medlarge">
<Button <Button
android:id="@+id/button_create_skylander" android:id="@+id/button_create_figure"
style="?attr/materialIconButtonFilledTonalStyle" style="?attr/materialIconButtonFilledTonalStyle"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_centerVertical="true" android:layout_centerVertical="true"
android:layout_marginEnd="@dimen/spacing_small" android:layout_marginEnd="@dimen/spacing_small"
android:layout_toStartOf="@id/button_load_skylander" android:layout_toStartOf="@id/button_load_figure"
android:contentDescription="@string/create_skylander" android:contentDescription="@string/create_figure"
android:tooltipText="@string/create_skylander" android:tooltipText="@string/create_figure"
app:icon="@drawable/ic_add" /> app:icon="@drawable/ic_add" />
<Button <Button
android:id="@+id/button_load_skylander" android:id="@+id/button_load_figure"
style="?attr/materialIconButtonFilledTonalStyle" style="?attr/materialIconButtonFilledTonalStyle"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_centerVertical="true" android:layout_centerVertical="true"
android:layout_marginEnd="@dimen/spacing_small" android:layout_marginEnd="@dimen/spacing_small"
android:layout_toStartOf="@+id/button_clear_skylander" android:layout_toStartOf="@+id/button_clear_figure"
android:contentDescription="@string/load_skylander" android:contentDescription="@string/load_figure"
android:tooltipText="@string/load_skylander" android:tooltipText="@string/load_figure"
app:icon="@drawable/ic_load" /> app:icon="@drawable/ic_load" />
<Button <Button
android:id="@+id/button_clear_skylander" android:id="@+id/button_clear_figure"
style="?attr/materialIconButtonFilledTonalStyle" style="?attr/materialIconButtonFilledTonalStyle"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentEnd="true" android:layout_alignParentEnd="true"
android:layout_centerVertical="true" android:layout_centerVertical="true"
android:layout_marginEnd="@dimen/spacing_large" android:layout_marginEnd="@dimen/spacing_large"
android:contentDescription="@string/remove_skylander" android:contentDescription="@string/remove_figure"
android:tooltipText="@string/remove_skylander" android:tooltipText="@string/remove_figure"
app:icon="@drawable/ic_clear" /> app:icon="@drawable/ic_clear" />
<com.google.android.material.textview.MaterialTextView <com.google.android.material.textview.MaterialTextView
android:id="@+id/text_skylander_name" android:id="@+id/text_figure_name"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentStart="true" android:layout_alignParentStart="true"
@ -52,7 +52,7 @@
android:layout_marginBottom="@dimen/spacing_medlarge" android:layout_marginBottom="@dimen/spacing_medlarge"
android:layout_marginEnd="@dimen/spacing_large" android:layout_marginEnd="@dimen/spacing_large"
android:layout_marginStart="@dimen/spacing_large" android:layout_marginStart="@dimen/spacing_large"
android:layout_toStartOf="@+id/button_create_skylander" android:layout_toStartOf="@+id/button_create_figure"
android:textAlignment="viewStart" android:textAlignment="viewStart"
android:textColor="?attr/colorOnSurface" android:textColor="?attr/colorOnSurface"
android:textSize="16sp" android:textSize="16sp"

View File

@ -846,9 +846,6 @@ It can efficiently compress both junk data and encrypted Wii data.
<string name="emulated_usb_devices">Emulated USB Devices</string> <string name="emulated_usb_devices">Emulated USB Devices</string>
<string name="emulate_skylander_portal">Skylanders Portal</string> <string name="emulate_skylander_portal">Skylanders Portal</string>
<string name="skylanders_manager">Skylanders Manager</string> <string name="skylanders_manager">Skylanders Manager</string>
<string name="load_skylander">Load</string>
<string name="remove_skylander">Remove</string>
<string name="create_skylander">Create</string>
<string name="create_skylander_title">Create Skylander</string> <string name="create_skylander_title">Create Skylander</string>
<string name="skylander_label">Skylander</string> <string name="skylander_label">Skylander</string>
<string name="skylander_slot">Slot %1$d</string> <string name="skylander_slot">Slot %1$d</string>
@ -856,4 +853,23 @@ It can efficiently compress both junk data and encrypted Wii data.
<string name="skylander_variant">Variant</string> <string name="skylander_variant">Variant</string>
<string name="invalid_skylander">Invalid Skylander Selection</string> <string name="invalid_skylander">Invalid Skylander Selection</string>
<string name="emulate_infinity_base">Infinity Base</string>
<string name="infinity_manager">Infinity Manager</string>
<string name="load_figure">Load</string>
<string name="remove_figure">Remove</string>
<string name="create_figure">Create</string>
<string name="create_figure_title">Create Figure</string>
<string name="infinity_label">Infinity Figure</string>
<string name="infinity_number">Figure Number</string>
<string name="invalid_infinity_figure">Invalid Figure Selection</string>
<string name="infinity_hexagon_label">Power Disc/Play Set</string>
<string name="infinity_p1_label">Player One</string>
<string name="infinity_p2_label">Player Two</string>
<string name="infinity_p1a1_label">P1 Ability One</string>
<string name="infinity_p2a1_label">P2 Ability One</string>
<string name="infinity_p1a2_label">P1 Ability Two</string>
<string name="infinity_p2a2_label">P2 Ability Two</string>
<string name="incompatible_figure_selected">Incompatible Figure Selected</string>
<string name="select_compatible_figure">Please select a compatible figure file</string>
</resources> </resources>

View File

@ -10,6 +10,7 @@ add_library(main SHARED
GameList/GameFile.cpp GameList/GameFile.cpp
GameList/GameFile.h GameList/GameFile.h
GameList/GameFileCache.cpp GameList/GameFileCache.cpp
InfinityConfig.cpp
Input/Control.cpp Input/Control.cpp
Input/Control.h Input/Control.h
Input/ControlGroup.cpp Input/ControlGroup.cpp

View File

@ -0,0 +1,126 @@
// Copyright 2023 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <jni.h>
#include <array>
#include "AndroidCommon/AndroidCommon.h"
#include "Core/IOS/USB/Emulated/Infinity.h"
#include "Core/System.h"
extern "C" {
JNIEXPORT jobject JNICALL
Java_org_dolphinemu_dolphinemu_features_infinitybase_InfinityConfig_getFigureMap(JNIEnv* env,
jobject obj)
{
auto& system = Core::System::GetInstance();
jobject hash_map_obj = env->NewObject(IDCache::GetHashMapClass(), IDCache::GetHashMapInit(),
system.GetInfinityBase().GetFigureList().size());
jmethodID hash_map_put = env->GetMethodID(
hash_map_class, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
jclass long_class = env->FindClass("java/lang/Long");
jmethodID long_init = env->GetMethodID(long_class, "<init>", "(J)V");
for (const auto& it : system.GetInfinityBase().GetFigureList())
{
const std::string& name = it.first;
jobject figure_number = env->NewObject(long_class, long_init, (jlong)it.second);
env->CallObjectMethod(hash_map_obj, IDCache::GetHashMapPut(), figure_number,
ToJString(env, name));
env->DeleteLocalRef(figure_number);
}
return hash_map_obj;
}
JNIEXPORT jobject JNICALL
Java_org_dolphinemu_dolphinemu_features_infinitybase_InfinityConfig_getInverseFigureMap(JNIEnv* env,
jobject obj)
{
auto& system = Core::System::GetInstance();
jobject hash_map_obj = env->NewObject(IDCache::GetHashMapClass(), IDCache::GetHashMapInit(),
system.GetInfinityBase().GetFigureList().size());
jmethodID hash_map_put = env->GetMethodID(
hash_map_class, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
jclass long_class = env->FindClass("java/lang/Long");
jmethodID long_init = env->GetMethodID(long_class, "<init>", "(J)V");
for (const auto& it : system.GetInfinityBase().GetFigureList())
{
const std::string& name = it.first;
jobject figure_number = env->NewObject(long_class, long_init, (jlong)it.second);
env->CallObjectMethod(hash_map_obj, IDCache::GetHashMapPut(), ToJString(env, name),
figure_number);
env->DeleteLocalRef(figure_number);
}
return hash_map_obj;
}
JNIEXPORT void JNICALL
Java_org_dolphinemu_dolphinemu_features_infinitybase_InfinityConfig_removeFigure(JNIEnv* env,
jclass clazz,
jint position)
{
auto& system = Core::System::GetInstance();
system.GetInfinityBase().RemoveFigure(position);
}
JNIEXPORT jstring JNICALL
Java_org_dolphinemu_dolphinemu_features_infinitybase_InfinityConfig_loadFigure(JNIEnv* env,
jclass clazz,
jint position,
jstring file_name)
{
File::IOFile inf_file(GetJString(env, file_name), "r+b");
if (!inf_file)
{
return nullptr;
}
std::array<u8, 0x14 * 0x10> file_data{};
if (!inf_file.ReadBytes(file_data.data(), file_data.size()))
{
return nullptr;
}
auto& system = Core::System::GetInstance();
system.GetInfinityBase().RemoveFigure(position);
return ToJString(env,
system.GetInfinityBase().LoadFigure(file_data, std::move(inf_file), position));
}
JNIEXPORT jstring JNICALL
Java_org_dolphinemu_dolphinemu_features_infinitybase_InfinityConfig_createFigure(
JNIEnv* env, jclass clazz, jlong figure_number, jstring fileName, jint position)
{
u32 fig_num = static_cast<u32>(figure_number);
std::string file_name = GetJString(env, fileName);
auto& system = Core::System::GetInstance();
system.GetInfinityBase().CreateFigure(file_name, fig_num);
system.GetInfinityBase().RemoveFigure(position);
File::IOFile inf_file(file_name, "r+b");
if (!inf_file)
{
return nullptr;
}
std::array<u8, 0x14 * 0x10> file_data{};
if (!inf_file.ReadBytes(file_data.data(), file_data.size()))
{
return nullptr;
}
return ToJString(env,
system.GetInfinityBase().LoadFigure(file_data, std::move(inf_file), position));
}
}