IOS/USB: Use Enum for Infinity Base Positions

This commit is contained in:
Joshua de Reeper 2024-06-26 23:04:27 +01:00
parent 3dbaf38eae
commit cfcdaab514
5 changed files with 106 additions and 65 deletions

View File

@ -10,6 +10,8 @@
#include "Core/IOS/USB/Emulated/Infinity.h" #include "Core/IOS/USB/Emulated/Infinity.h"
#include "Core/System.h" #include "Core/System.h"
using FigureUIPosition = IOS::HLE::USB::FigureUIPosition;
extern "C" { extern "C" {
JNIEXPORT jobject JNICALL JNIEXPORT jobject JNICALL
@ -66,7 +68,7 @@ Java_org_dolphinemu_dolphinemu_features_infinitybase_InfinityConfig_removeFigure
jint position) jint position)
{ {
auto& system = Core::System::GetInstance(); auto& system = Core::System::GetInstance();
system.GetInfinityBase().RemoveFigure(position); system.GetInfinityBase().RemoveFigure(static_cast<FigureUIPosition>(position));
} }
JNIEXPORT jstring JNICALL JNIEXPORT jstring JNICALL
@ -87,9 +89,10 @@ Java_org_dolphinemu_dolphinemu_features_infinitybase_InfinityConfig_loadFigure(J
} }
auto& system = Core::System::GetInstance(); auto& system = Core::System::GetInstance();
system.GetInfinityBase().RemoveFigure(position); system.GetInfinityBase().RemoveFigure(static_cast<FigureUIPosition>(position));
return ToJString(env, return ToJString(env,
system.GetInfinityBase().LoadFigure(file_data, std::move(inf_file), position)); system.GetInfinityBase().LoadFigure(file_data, std::move(inf_file),
static_cast<FigureUIPosition>(position)));
} }
JNIEXPORT jstring JNICALL JNIEXPORT jstring JNICALL
@ -102,7 +105,7 @@ Java_org_dolphinemu_dolphinemu_features_infinitybase_InfinityConfig_createFigure
auto& system = Core::System::GetInstance(); auto& system = Core::System::GetInstance();
system.GetInfinityBase().CreateFigure(file_name, fig_num); system.GetInfinityBase().CreateFigure(file_name, fig_num);
system.GetInfinityBase().RemoveFigure(position); system.GetInfinityBase().RemoveFigure(static_cast<FigureUIPosition>(position));
File::IOFile inf_file(file_name, "r+b"); File::IOFile inf_file(file_name, "r+b");
if (!inf_file) if (!inf_file)
@ -116,6 +119,7 @@ Java_org_dolphinemu_dolphinemu_features_infinitybase_InfinityConfig_createFigure
} }
return ToJString(env, return ToJString(env,
system.GetInfinityBase().LoadFigure(file_data, std::move(inf_file), position)); system.GetInfinityBase().LoadFigure(file_data, std::move(inf_file),
static_cast<FigureUIPosition>(position)));
} }
} }

View File

@ -594,7 +594,7 @@ static u32 InfinityCRC32(const std::array<u8, 16>& buffer)
std::string std::string
InfinityBase::LoadFigure(const std::array<u8, INFINITY_NUM_BLOCKS * INFINITY_BLOCK_SIZE>& buf, InfinityBase::LoadFigure(const std::array<u8, INFINITY_NUM_BLOCKS * INFINITY_BLOCK_SIZE>& buf,
File::IOFile in_file, u8 position) File::IOFile in_file, FigureUIPosition position)
{ {
std::lock_guard lock(m_infinity_mutex); std::lock_guard lock(m_infinity_mutex);
u8 order_added; u8 order_added;
@ -615,7 +615,7 @@ InfinityBase::LoadFigure(const std::array<u8, INFINITY_NUM_BLOCKS * INFINITY_BLO
u32(infinity_decrypted_block[3]); u32(infinity_decrypted_block[3]);
DEBUG_LOG_FMT(IOS_USB, "Toy Number: {}", number); DEBUG_LOG_FMT(IOS_USB, "Toy Number: {}", number);
InfinityFigure& figure = m_figures[position]; InfinityFigure& figure = m_figures[static_cast<u8>(position)];
figure.inf_file = std::move(in_file); figure.inf_file = std::move(in_file);
memcpy(figure.data.data(), buf.data(), figure.data.size()); memcpy(figure.data.data(), buf.data(), figure.data.size());
@ -627,24 +627,25 @@ InfinityBase::LoadFigure(const std::array<u8, INFINITY_NUM_BLOCKS * INFINITY_BLO
} }
order_added = figure.order_added; order_added = figure.order_added;
position = DeriveFigurePosition(position); FigureBasePosition derived_position = DeriveFigurePosition(position);
if (position == 0) if (derived_position == FigureBasePosition::Unknown)
{ {
ERROR_LOG_FMT(IOS_USB, "Invalid Position for Infinity Figure"); ERROR_LOG_FMT(IOS_USB, "Invalid Position for Infinity Figure");
return "Unknown Figure"; return "Unknown Figure";
} }
std::array<u8, 32> figure_change_response = {0xab, 0x04, position, 0x09, order_added, 0x00}; std::array<u8, 32> figure_change_response = {0xab, 0x04, static_cast<u8>(derived_position),
0x09, order_added, 0x00};
figure_change_response[6] = GenerateChecksum(figure_change_response, 6); figure_change_response[6] = GenerateChecksum(figure_change_response, 6);
m_figure_added_removed_response.push(figure_change_response); m_figure_added_removed_response.push(figure_change_response);
return FindFigure(number); return FindFigure(number);
} }
void InfinityBase::RemoveFigure(u8 position) void InfinityBase::RemoveFigure(FigureUIPosition position)
{ {
std::lock_guard lock(m_infinity_mutex); std::lock_guard lock(m_infinity_mutex);
InfinityFigure& figure = m_figures[position]; InfinityFigure& figure = m_figures[static_cast<u8>(position)];
if (figure.inf_file.IsOpen()) if (figure.inf_file.IsOpen())
{ {
@ -654,8 +655,8 @@ void InfinityBase::RemoveFigure(u8 position)
if (figure.present) if (figure.present)
{ {
position = DeriveFigurePosition(position); FigureBasePosition derived_position = DeriveFigurePosition(position);
if (position == 0) if (derived_position == FigureBasePosition::Unknown)
{ {
ERROR_LOG_FMT(IOS_USB, "Invalid Position for Infinity Figure"); ERROR_LOG_FMT(IOS_USB, "Invalid Position for Infinity Figure");
return; return;
@ -663,8 +664,8 @@ void InfinityBase::RemoveFigure(u8 position)
figure.present = false; figure.present = false;
std::array<u8, 32> figure_change_response = {0xab, 0x04, position, 0x09, figure.order_added, std::array<u8, 32> figure_change_response = {
0x01}; 0xab, 0x04, static_cast<u8>(derived_position), 0x09, figure.order_added, 0x01};
figure_change_response[6] = GenerateChecksum(figure_change_response, 6); figure_change_response[6] = GenerateChecksum(figure_change_response, 6);
m_figure_added_removed_response.push(figure_change_response); m_figure_added_removed_response.push(figure_change_response);
} }
@ -751,7 +752,7 @@ std::string InfinityBase::FindFigure(u32 number) const
return "Unknown Figure"; return "Unknown Figure";
} }
u8 InfinityBase::DeriveFigurePosition(u8 position) FigureBasePosition InfinityBase::DeriveFigurePosition(FigureUIPosition position)
{ {
// In the added/removed response, position needs to be 1 for the hexagon, 2 for Player 1 and // In the added/removed response, position needs to be 1 for the hexagon, 2 for Player 1 and
// Player 1's abilities, and 3 for Player 2 and Player 2's abilities. In the UI, positions 0, 1 // Player 1's abilities, and 3 for Player 2 and Player 2's abilities. In the UI, positions 0, 1
@ -760,21 +761,26 @@ u8 InfinityBase::DeriveFigurePosition(u8 position)
switch (position) switch (position)
{ {
case 0: case FigureUIPosition::HexagonDiscOne:
case 1: case FigureUIPosition::HexagonDiscTwo:
case 2: case FigureUIPosition::HexagonDiscThree:
return 1; {
case 3: return FigureBasePosition::HexagonSlot;
case 4: }
case 5: case FigureUIPosition::PlayerOne:
return 2; case FigureUIPosition::P1AbilityOne:
case 6: case FigureUIPosition::P1AbilityTwo:
case 7: {
case 8: return FigureBasePosition::PlayerOneSlot;
return 3; }
case FigureUIPosition::PlayerTwo:
case FigureUIPosition::P2AbilityOne:
case FigureUIPosition::P2AbilityTwo:
{
return FigureBasePosition::PlayerTwoSlot;
}
default: default:
return 0; return FigureBasePosition::Unknown;
} }
} }

View File

@ -66,6 +66,27 @@ private:
std::queue<std::unique_ptr<IntrMessage>> m_response_list; std::queue<std::unique_ptr<IntrMessage>> m_response_list;
}; };
enum class FigureUIPosition : u8
{
HexagonDiscOne = 0,
HexagonDiscTwo = 1,
HexagonDiscThree = 2,
PlayerOne = 3,
P1AbilityOne = 4,
P1AbilityTwo = 5,
PlayerTwo = 6,
P2AbilityOne = 7,
P2AbilityTwo = 8
};
enum class FigureBasePosition : u8
{
Unknown = 0,
HexagonSlot = 1,
PlayerOneSlot = 2,
PlayerTwoSlot = 3
};
class InfinityBase final class InfinityBase final
{ {
public: public:
@ -79,10 +100,10 @@ public:
u8 sequence); u8 sequence);
void DescrambleAndSeed(u8* buf, u8 sequence, std::array<u8, 32>& reply_buf); void DescrambleAndSeed(u8* buf, u8 sequence, std::array<u8, 32>& reply_buf);
void GetNextAndScramble(u8 sequence, std::array<u8, 32>& reply_buf); void GetNextAndScramble(u8 sequence, std::array<u8, 32>& reply_buf);
void RemoveFigure(u8 position); void RemoveFigure(FigureUIPosition position);
// Returns Infinity Figure name based on data from in_file param // Returns Infinity Figure name based on data from in_file param
std::string LoadFigure(const std::array<u8, INFINITY_NUM_BLOCKS * INFINITY_BLOCK_SIZE>& buf, std::string LoadFigure(const std::array<u8, INFINITY_NUM_BLOCKS * INFINITY_BLOCK_SIZE>& buf,
File::IOFile in_file, u8 position); File::IOFile in_file, FigureUIPosition position);
bool CreateFigure(const std::string& file_path, u32 character); bool CreateFigure(const std::string& file_path, u32 character);
static std::span<const std::pair<const char*, const u32>> GetFigureList(); static std::span<const std::pair<const char*, const u32>> GetFigureList();
std::string FindFigure(u32 character) const; std::string FindFigure(u32 character) const;
@ -95,7 +116,7 @@ private:
InfinityFigure& GetFigureByOrder(u8 order_added); InfinityFigure& GetFigureByOrder(u8 order_added);
std::array<u8, 16> GenerateInfinityFigureKey(const std::vector<u8>& sha1_data); std::array<u8, 16> GenerateInfinityFigureKey(const std::vector<u8>& sha1_data);
std::array<u8, 16> GenerateBlankFigureData(u32 figure_num); std::array<u8, 16> GenerateBlankFigureData(u32 figure_num);
u8 DeriveFigurePosition(u8 position); FigureBasePosition DeriveFigurePosition(FigureUIPosition position);
void GenerateSeed(u32 seed); void GenerateSeed(u32 seed);
u32 GetNext(); u32 GetNext();
u64 Scramble(u32 num_to_scramble, u32 garbage); u64 Scramble(u32 num_to_scramble, u32 garbage);

View File

@ -33,6 +33,8 @@
// static variable to ensure we open at the most recent figure file location // static variable to ensure we open at the most recent figure file location
static QString s_last_figure_path; static QString s_last_figure_path;
using FigureUIPosition = IOS::HLE::USB::FigureUIPosition;
InfinityBaseWindow::InfinityBaseWindow(QWidget* parent) : QWidget(parent) InfinityBaseWindow::InfinityBaseWindow(QWidget* parent) : QWidget(parent)
{ {
// i18n: Window for managing Disney Infinity figures // i18n: Window for managing Disney Infinity figures
@ -77,23 +79,23 @@ void InfinityBaseWindow::CreateMainWindow()
auto* vbox_group = new QVBoxLayout(); auto* vbox_group = new QVBoxLayout();
auto* scroll_area = new QScrollArea(); auto* scroll_area = new QScrollArea();
AddFigureSlot(vbox_group, tr("Play Set/Power Disc"), 0); AddFigureSlot(vbox_group, tr("Play Set/Power Disc"), FigureUIPosition::HexagonDiscOne);
add_line(vbox_group); add_line(vbox_group);
AddFigureSlot(vbox_group, tr("Power Disc Two"), 1); AddFigureSlot(vbox_group, tr("Power Disc Two"), FigureUIPosition::HexagonDiscTwo);
add_line(vbox_group); add_line(vbox_group);
AddFigureSlot(vbox_group, tr("Power Disc Three"), 2); AddFigureSlot(vbox_group, tr("Power Disc Three"), FigureUIPosition::HexagonDiscThree);
add_line(vbox_group); add_line(vbox_group);
AddFigureSlot(vbox_group, tr("Player One"), 3); AddFigureSlot(vbox_group, tr("Player One"), FigureUIPosition::PlayerOne);
add_line(vbox_group); add_line(vbox_group);
AddFigureSlot(vbox_group, tr("Player One Ability One"), 4); AddFigureSlot(vbox_group, tr("Player One Ability One"), FigureUIPosition::P1AbilityOne);
add_line(vbox_group); add_line(vbox_group);
AddFigureSlot(vbox_group, tr("Player One Ability Two"), 5); AddFigureSlot(vbox_group, tr("Player One Ability Two"), FigureUIPosition::P1AbilityTwo);
add_line(vbox_group); add_line(vbox_group);
AddFigureSlot(vbox_group, tr("Player Two"), 6); AddFigureSlot(vbox_group, tr("Player Two"), FigureUIPosition::PlayerTwo);
add_line(vbox_group); add_line(vbox_group);
AddFigureSlot(vbox_group, tr("Player Two Ability One"), 7); AddFigureSlot(vbox_group, tr("Player Two Ability One"), FigureUIPosition::P2AbilityOne);
add_line(vbox_group); add_line(vbox_group);
AddFigureSlot(vbox_group, tr("Player Two Ability Two"), 8); AddFigureSlot(vbox_group, tr("Player Two Ability Two"), FigureUIPosition::P2AbilityTwo);
m_group_figures->setLayout(vbox_group); m_group_figures->setLayout(vbox_group);
scroll_area->setWidget(m_group_figures); scroll_area->setWidget(m_group_figures);
@ -103,7 +105,7 @@ void InfinityBaseWindow::CreateMainWindow()
setLayout(main_layout); setLayout(main_layout);
} }
void InfinityBaseWindow::AddFigureSlot(QVBoxLayout* vbox_group, QString name, u8 slot) void InfinityBaseWindow::AddFigureSlot(QVBoxLayout* vbox_group, QString name, FigureUIPosition slot)
{ {
auto* hbox_infinity = new QHBoxLayout(); auto* hbox_infinity = new QHBoxLayout();
@ -112,16 +114,16 @@ void InfinityBaseWindow::AddFigureSlot(QVBoxLayout* vbox_group, QString name, u8
auto* clear_btn = new QPushButton(tr("Clear")); auto* clear_btn = new QPushButton(tr("Clear"));
auto* create_btn = new QPushButton(tr("Create")); auto* create_btn = new QPushButton(tr("Create"));
auto* load_btn = new QPushButton(tr("Load")); auto* load_btn = new QPushButton(tr("Load"));
m_edit_figures[slot] = new QLineEdit(); m_edit_figures[static_cast<u8>(slot)] = new QLineEdit();
m_edit_figures[slot]->setEnabled(false); m_edit_figures[static_cast<u8>(slot)]->setEnabled(false);
m_edit_figures[slot]->setText(tr("None")); m_edit_figures[static_cast<u8>(slot)]->setText(tr("None"));
connect(clear_btn, &QAbstractButton::clicked, this, [this, slot] { ClearFigure(slot); }); connect(clear_btn, &QAbstractButton::clicked, this, [this, slot] { ClearFigure(slot); });
connect(create_btn, &QAbstractButton::clicked, this, [this, slot] { CreateFigure(slot); }); connect(create_btn, &QAbstractButton::clicked, this, [this, slot] { CreateFigure(slot); });
connect(load_btn, &QAbstractButton::clicked, this, [this, slot] { LoadFigure(slot); }); connect(load_btn, &QAbstractButton::clicked, this, [this, slot] { LoadFigure(slot); });
hbox_infinity->addWidget(label_skyname); hbox_infinity->addWidget(label_skyname);
hbox_infinity->addWidget(m_edit_figures[slot]); hbox_infinity->addWidget(m_edit_figures[static_cast<u8>(slot)]);
hbox_infinity->addWidget(clear_btn); hbox_infinity->addWidget(clear_btn);
hbox_infinity->addWidget(create_btn); hbox_infinity->addWidget(create_btn);
hbox_infinity->addWidget(load_btn); hbox_infinity->addWidget(load_btn);
@ -129,15 +131,15 @@ void InfinityBaseWindow::AddFigureSlot(QVBoxLayout* vbox_group, QString name, u8
vbox_group->addLayout(hbox_infinity); vbox_group->addLayout(hbox_infinity);
} }
void InfinityBaseWindow::ClearFigure(u8 slot) void InfinityBaseWindow::ClearFigure(FigureUIPosition slot)
{ {
auto& system = Core::System::GetInstance(); auto& system = Core::System::GetInstance();
m_edit_figures[slot]->setText(tr("None")); m_edit_figures[static_cast<u8>(slot)]->setText(tr("None"));
system.GetInfinityBase().RemoveFigure(slot); system.GetInfinityBase().RemoveFigure(slot);
} }
void InfinityBaseWindow::LoadFigure(u8 slot) void InfinityBaseWindow::LoadFigure(FigureUIPosition slot)
{ {
const QString file_path = const QString file_path =
DolphinFileDialog::getOpenFileName(this, tr("Select Figure File"), s_last_figure_path, DolphinFileDialog::getOpenFileName(this, tr("Select Figure File"), s_last_figure_path,
@ -152,7 +154,7 @@ void InfinityBaseWindow::LoadFigure(u8 slot)
LoadFigurePath(slot, file_path); LoadFigurePath(slot, file_path);
} }
void InfinityBaseWindow::CreateFigure(u8 slot) void InfinityBaseWindow::CreateFigure(FigureUIPosition slot)
{ {
CreateFigureDialog create_dlg(this, slot); CreateFigureDialog create_dlg(this, slot);
SetQWidgetWindowDecorations(&create_dlg); SetQWidgetWindowDecorations(&create_dlg);
@ -162,7 +164,7 @@ void InfinityBaseWindow::CreateFigure(u8 slot)
} }
} }
void InfinityBaseWindow::LoadFigurePath(u8 slot, const QString& path) void InfinityBaseWindow::LoadFigurePath(FigureUIPosition slot, const QString& path)
{ {
File::IOFile inf_file(path.toStdString(), "r+b"); File::IOFile inf_file(path.toStdString(), "r+b");
if (!inf_file) if (!inf_file)
@ -187,11 +189,11 @@ void InfinityBaseWindow::LoadFigurePath(u8 slot, const QString& path)
auto& system = Core::System::GetInstance(); auto& system = Core::System::GetInstance();
system.GetInfinityBase().RemoveFigure(slot); system.GetInfinityBase().RemoveFigure(slot);
m_edit_figures[slot]->setText(QString::fromStdString( m_edit_figures[static_cast<u8>(slot)]->setText(QString::fromStdString(
system.GetInfinityBase().LoadFigure(file_data, std::move(inf_file), slot))); system.GetInfinityBase().LoadFigure(file_data, std::move(inf_file), slot)));
} }
CreateFigureDialog::CreateFigureDialog(QWidget* parent, u8 slot) : QDialog(parent) CreateFigureDialog::CreateFigureDialog(QWidget* parent, FigureUIPosition slot) : QDialog(parent)
{ {
setWindowTitle(tr("Infinity Figure Creator")); setWindowTitle(tr("Infinity Figure Creator"));
setObjectName(QStringLiteral("infinity_creator")); setObjectName(QStringLiteral("infinity_creator"));
@ -205,11 +207,14 @@ CreateFigureDialog::CreateFigureDialog(QWidget* parent, u8 slot) : QDialog(paren
{ {
const auto figure = entry.second; const auto figure = entry.second;
// Only display entry if it is a piece appropriate for the slot // Only display entry if it is a piece appropriate for the slot
if ((slot == 0 && if ((slot == FigureUIPosition::HexagonDiscOne &&
((figure > 0x1E8480 && figure < 0x2DC6BF) || (figure > 0x3D0900 && figure < 0x4C4B3F))) || ((figure > 0x1E8480 && figure < 0x2DC6BF) || (figure > 0x3D0900 && figure < 0x4C4B3F))) ||
((slot == 1 || slot == 2) && (figure > 0x3D0900 && figure < 0x4C4B3F)) || ((slot == FigureUIPosition::HexagonDiscTwo || slot == FigureUIPosition::HexagonDiscThree) &&
((slot == 3 || slot == 6) && figure < 0x1E847F) || (figure > 0x3D0900 && figure < 0x4C4B3F)) ||
((slot == 4 || slot == 5 || slot == 7 || slot == 8) && ((slot == FigureUIPosition::PlayerOne || slot == FigureUIPosition::PlayerTwo) &&
figure < 0x1E847F) ||
((slot == FigureUIPosition::P1AbilityOne || slot == FigureUIPosition::P1AbilityTwo ||
slot == FigureUIPosition::P2AbilityOne || slot == FigureUIPosition::P2AbilityTwo) &&
(figure > 0x2DC6C0 && figure < 0x3D08FF))) (figure > 0x2DC6C0 && figure < 0x3D08FF)))
{ {
const auto figure_name = QString::fromStdString(entry.first); const auto figure_name = QString::fromStdString(entry.first);

View File

@ -20,6 +20,11 @@ namespace Core
enum class State; enum class State;
} }
namespace IOS::HLE::USB
{
enum class FigureUIPosition : u8;
}
class InfinityBaseWindow : public QWidget class InfinityBaseWindow : public QWidget
{ {
Q_OBJECT Q_OBJECT
@ -32,13 +37,13 @@ protected:
private: private:
void CreateMainWindow(); void CreateMainWindow();
void AddFigureSlot(QVBoxLayout* vbox_group, QString name, u8 slot); void AddFigureSlot(QVBoxLayout* vbox_group, QString name, IOS::HLE::USB::FigureUIPosition slot);
void OnEmulationStateChanged(Core::State state); void OnEmulationStateChanged(Core::State state);
void EmulateBase(bool emulate); void EmulateBase(bool emulate);
void ClearFigure(u8 slot); void ClearFigure(IOS::HLE::USB::FigureUIPosition slot);
void LoadFigure(u8 slot); void LoadFigure(IOS::HLE::USB::FigureUIPosition slot);
void CreateFigure(u8 slot); void CreateFigure(IOS::HLE::USB::FigureUIPosition slot);
void LoadFigurePath(u8 slot, const QString& path); void LoadFigurePath(IOS::HLE::USB::FigureUIPosition slot, const QString& path);
QCheckBox* m_checkbox; QCheckBox* m_checkbox;
QGroupBox* m_group_figures; QGroupBox* m_group_figures;
@ -49,7 +54,7 @@ class CreateFigureDialog : public QDialog
Q_OBJECT Q_OBJECT
public: public:
explicit CreateFigureDialog(QWidget* parent, u8 slot); explicit CreateFigureDialog(QWidget* parent, IOS::HLE::USB::FigureUIPosition slot);
QString GetFilePath() const; QString GetFilePath() const;
protected: protected: