Infinity Base: Code tidyups and de-duplication
This commit is contained in:
parent
f632f94645
commit
529d0a1c63
File diff suppressed because it is too large
Load Diff
|
@ -7,6 +7,7 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
#include <span>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
|
@ -15,38 +16,23 @@
|
||||||
|
|
||||||
namespace IOS::HLE::USB
|
namespace IOS::HLE::USB
|
||||||
{
|
{
|
||||||
const u8 INFINITY_NUM_BLOCKS = 0x14;
|
constexpr u8 INFINITY_NUM_BLOCKS = 0x14;
|
||||||
const u8 INFINITY_BLOCK_SIZE = 0x10;
|
constexpr u8 INFINITY_BLOCK_SIZE = 0x10;
|
||||||
|
|
||||||
// Enum type, used when generating blank toys
|
|
||||||
enum class InfinityFigureType
|
|
||||||
{
|
|
||||||
Character = 1,
|
|
||||||
Playset = 2,
|
|
||||||
Ability_A = 3,
|
|
||||||
Ability_B = 4,
|
|
||||||
Item = 5
|
|
||||||
};
|
|
||||||
|
|
||||||
struct InfinityFigureInfo
|
|
||||||
{
|
|
||||||
InfinityFigureType type;
|
|
||||||
u16 figure_number;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct InfinityFigure final
|
struct InfinityFigure final
|
||||||
{
|
{
|
||||||
|
void Save();
|
||||||
|
|
||||||
File::IOFile inf_file;
|
File::IOFile inf_file;
|
||||||
std::array<u8, INFINITY_NUM_BLOCKS * INFINITY_BLOCK_SIZE> data{};
|
std::array<u8, INFINITY_NUM_BLOCKS * INFINITY_BLOCK_SIZE> data{};
|
||||||
bool present = false;
|
bool present = false;
|
||||||
u8 order_added = 255;
|
u8 order_added = 255;
|
||||||
void Save();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class InfinityUSB final : public Device
|
class InfinityUSB final : public Device
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
InfinityUSB(Kernel& ios, const std::string& device_name);
|
InfinityUSB(EmulationKernel& ios, const std::string& device_name);
|
||||||
~InfinityUSB() override;
|
~InfinityUSB() override;
|
||||||
DeviceDescriptor GetDeviceDescriptor() const override;
|
DeviceDescriptor GetDeviceDescriptor() const override;
|
||||||
std::vector<ConfigDescriptor> GetConfigurations() const override;
|
std::vector<ConfigDescriptor> GetConfigurations() const override;
|
||||||
|
@ -64,7 +50,10 @@ public:
|
||||||
int SubmitTransfer(std::unique_ptr<IsoMessage> message) override;
|
int SubmitTransfer(std::unique_ptr<IsoMessage> message) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Kernel& m_ios;
|
void ScheduleTransfer(std::unique_ptr<TransferCommand> command, const std::array<u8, 32>& data,
|
||||||
|
u64 expected_time_us);
|
||||||
|
|
||||||
|
EmulationKernel& m_ios;
|
||||||
u16 m_vid = 0;
|
u16 m_vid = 0;
|
||||||
u16 m_pid = 0;
|
u16 m_pid = 0;
|
||||||
u8 m_active_interface = 0;
|
u8 m_active_interface = 0;
|
||||||
|
@ -75,44 +64,45 @@ private:
|
||||||
std::vector<EndpointDescriptor> m_endpoint_descriptor;
|
std::vector<EndpointDescriptor> m_endpoint_descriptor;
|
||||||
std::queue<std::array<u8, 32>> m_queries;
|
std::queue<std::array<u8, 32>> m_queries;
|
||||||
std::queue<std::unique_ptr<IntrMessage>> m_response_list;
|
std::queue<std::unique_ptr<IntrMessage>> m_response_list;
|
||||||
void ScheduleTransfer(std::unique_ptr<TransferCommand> command, const std::array<u8, 32>& data,
|
|
||||||
s32 expected_count, u64 expected_time_us);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class InfinityBase final
|
class InfinityBase final
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
bool HasFigureBeenAddedRemoved() const;
|
bool HasFigureBeenAddedRemoved() const;
|
||||||
std::array<u8, 32> GetAddedRemovedResponse();
|
std::array<u8, 32> PopAddedRemovedResponse();
|
||||||
void GetBlankResponse(u8 sequence, u8* reply_buf);
|
void GetBlankResponse(u8 sequence, std::array<u8, 32>& reply_buf);
|
||||||
void GetPresentFigures(u8 sequence, u8* reply_buf);
|
void GetPresentFigures(u8 sequence, std::array<u8, 32>& reply_buf);
|
||||||
void GetFigureIdentifier(u8 fig_num, u8 sequence, u8* reply_buf);
|
void GetFigureIdentifier(u8 fig_num, u8 sequence, std::array<u8, 32>& reply_buf);
|
||||||
void QueryBlock(u8 fig_num, u8 block, u8* reply_buf, u8 sequence);
|
void QueryBlock(u8 fig_num, u8 block, std::array<u8, 32>& reply_buf, u8 sequence);
|
||||||
void WriteBlock(u8 fig_num, u8 block, const u8* to_write_buf, u8* reply_buf, u8 sequence);
|
void WriteBlock(u8 fig_num, u8 block, const u8* to_write_buf, std::array<u8, 32>& reply_buf,
|
||||||
|
u8 sequence);
|
||||||
|
void DescrambleAndSeed(u8* buf, u8 sequence, std::array<u8, 32>& reply_buf);
|
||||||
|
void GetNextAndScramble(u8 sequence, std::array<u8, 32>& reply_buf);
|
||||||
void RemoveFigure(u8 position);
|
void RemoveFigure(u8 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(u8* buf, File::IOFile in_file, u8 position);
|
std::string LoadFigure(const std::array<u8, INFINITY_NUM_BLOCKS * INFINITY_BLOCK_SIZE>& buf,
|
||||||
bool CreateFigure(const std::string& file_path, u16 character);
|
File::IOFile in_file, u8 position);
|
||||||
static const std::map<const char*, const InfinityFigureInfo>& GetFigureList();
|
bool CreateFigure(const std::string& file_path, u32 character);
|
||||||
std::string FindFigure(u16 character) const;
|
static std::span<const std::pair<const char*, const u32>> GetFigureList();
|
||||||
|
std::string FindFigure(u32 character) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::mutex m_infinity_mutex;
|
||||||
|
std::array<InfinityFigure, 7> m_figures;
|
||||||
|
|
||||||
|
private:
|
||||||
|
InfinityFigure& GetFigureByOrder(u8 order_added);
|
||||||
|
std::array<u8, 16> GenerateInfinityFigureKey(const std::vector<u8>& sha1_data);
|
||||||
|
std::array<u8, 16> GenerateBlankFigureData(u32 figure_num);
|
||||||
|
u8 DeriveFigurePosition(u8 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);
|
||||||
u32 Descramble(u64 num_to_descramble);
|
u32 Descramble(u64 num_to_descramble);
|
||||||
u8 GenerateChecksum(const u8* data, int num_of_bytes) const;
|
u8 GenerateChecksum(const std::array<u8, 32>& data, int num_of_bytes) const;
|
||||||
|
|
||||||
protected:
|
// These 4 variables are state variables used during the seeding and use of the random number
|
||||||
std::mutex m_infinity_mutex;
|
|
||||||
InfinityFigure m_player_one;
|
|
||||||
InfinityFigure m_player_two;
|
|
||||||
InfinityFigure m_player_one_ability_one;
|
|
||||||
InfinityFigure m_player_one_ability_two;
|
|
||||||
InfinityFigure m_player_two_ability_one;
|
|
||||||
InfinityFigure m_player_two_ability_two;
|
|
||||||
InfinityFigure m_hexagon;
|
|
||||||
|
|
||||||
private:
|
|
||||||
// These 4 variables are state variables used during the seeding of, and use of the random number
|
|
||||||
// generator.
|
// generator.
|
||||||
u32 m_random_a;
|
u32 m_random_a;
|
||||||
u32 m_random_b;
|
u32 m_random_b;
|
||||||
|
|
|
@ -139,7 +139,8 @@ bool USBHost::AddNewDevices(std::set<u64>& new_devices, DeviceChangeHooks& hooks
|
||||||
if (whitelist.count({descriptor.idVendor, descriptor.idProduct}) == 0)
|
if (whitelist.count({descriptor.idVendor, descriptor.idProduct}) == 0)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
auto usb_device = std::make_unique<USB::LibusbDevice>(GetEmulationKernel(), device, descriptor);
|
auto usb_device =
|
||||||
|
std::make_unique<USB::LibusbDevice>(GetEmulationKernel(), device, descriptor);
|
||||||
CheckAndAddDevice(std::move(usb_device), new_devices, hooks, always_add_hooks);
|
CheckAndAddDevice(std::move(usb_device), new_devices, hooks, always_add_hooks);
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
@ -186,7 +187,8 @@ void USBHost::AddEmulatedDevices(std::set<u64>& new_devices, DeviceChangeHooks&
|
||||||
{
|
{
|
||||||
if (Config::Get(Config::MAIN_EMULATE_SKYLANDER_PORTAL) && !NetPlay::IsNetPlayRunning())
|
if (Config::Get(Config::MAIN_EMULATE_SKYLANDER_PORTAL) && !NetPlay::IsNetPlayRunning())
|
||||||
{
|
{
|
||||||
auto skylanderportal = std::make_unique<USB::SkylanderUSB>(GetEmulationKernel(), "Skylander Portal");
|
auto skylanderportal =
|
||||||
|
std::make_unique<USB::SkylanderUSB>(GetEmulationKernel(), "Skylander Portal");
|
||||||
CheckAndAddDevice(std::move(skylanderportal), new_devices, hooks, always_add_hooks);
|
CheckAndAddDevice(std::move(skylanderportal), new_devices, hooks, always_add_hooks);
|
||||||
}
|
}
|
||||||
if (Config::Get(Config::MAIN_EMULATE_INFINITY_BASE) && !NetPlay::IsNetPlayRunning())
|
if (Config::Get(Config::MAIN_EMULATE_INFINITY_BASE) && !NetPlay::IsNetPlayRunning())
|
||||||
|
|
|
@ -31,7 +31,7 @@ static QString s_last_figure_path;
|
||||||
InfinityBaseWindow::InfinityBaseWindow(QWidget* parent) : QWidget(parent)
|
InfinityBaseWindow::InfinityBaseWindow(QWidget* parent) : QWidget(parent)
|
||||||
{
|
{
|
||||||
setWindowTitle(tr("Infinity Manager"));
|
setWindowTitle(tr("Infinity Manager"));
|
||||||
setObjectName(QString::fromStdString("infinity_manager"));
|
setObjectName(QStringLiteral("infinity_manager"));
|
||||||
setMinimumSize(QSize(700, 200));
|
setMinimumSize(QSize(700, 200));
|
||||||
|
|
||||||
CreateMainWindow();
|
CreateMainWindow();
|
||||||
|
@ -71,19 +71,19 @@ 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, QString(tr("Play Set/Power Disc")), 0x01);
|
AddFigureSlot(vbox_group, QString(tr("Play Set/Power Disc")), 0);
|
||||||
add_line(vbox_group);
|
add_line(vbox_group);
|
||||||
AddFigureSlot(vbox_group, QString(tr("Player One")), 0x02);
|
AddFigureSlot(vbox_group, QString(tr("Player One")), 1);
|
||||||
add_line(vbox_group);
|
add_line(vbox_group);
|
||||||
AddFigureSlot(vbox_group, QString(tr("Player One Ability One")), 0x04);
|
AddFigureSlot(vbox_group, QString(tr("Player One Ability One")), 3);
|
||||||
add_line(vbox_group);
|
add_line(vbox_group);
|
||||||
AddFigureSlot(vbox_group, QString(tr("Player One Ability Two")), 0x06);
|
AddFigureSlot(vbox_group, QString(tr("Player One Ability Two")), 5);
|
||||||
add_line(vbox_group);
|
add_line(vbox_group);
|
||||||
AddFigureSlot(vbox_group, QString(tr("Player Two")), 0x03);
|
AddFigureSlot(vbox_group, QString(tr("Player Two")), 2);
|
||||||
add_line(vbox_group);
|
add_line(vbox_group);
|
||||||
AddFigureSlot(vbox_group, QString(tr("Player Two Ability One")), 0x05);
|
AddFigureSlot(vbox_group, QString(tr("Player Two Ability One")), 4);
|
||||||
add_line(vbox_group);
|
add_line(vbox_group);
|
||||||
AddFigureSlot(vbox_group, QString(tr("Player Two Ability Two")), 0x07);
|
AddFigureSlot(vbox_group, QString(tr("Player Two Ability Two")), 6);
|
||||||
|
|
||||||
m_group_figures->setLayout(vbox_group);
|
m_group_figures->setLayout(vbox_group);
|
||||||
scroll_area->setWidget(m_group_figures);
|
scroll_area->setWidget(m_group_figures);
|
||||||
|
@ -102,16 +102,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 - 1] = new QLineEdit();
|
m_edit_figures[slot] = new QLineEdit();
|
||||||
m_edit_figures[slot - 1]->setEnabled(false);
|
m_edit_figures[slot]->setEnabled(false);
|
||||||
m_edit_figures[slot - 1]->setText(tr("None"));
|
m_edit_figures[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 - 1]);
|
hbox_infinity->addWidget(m_edit_figures[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);
|
||||||
|
@ -122,7 +122,7 @@ void InfinityBaseWindow::AddFigureSlot(QVBoxLayout* vbox_group, QString name, u8
|
||||||
void InfinityBaseWindow::ClearFigure(u8 slot)
|
void InfinityBaseWindow::ClearFigure(u8 slot)
|
||||||
{
|
{
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = Core::System::GetInstance();
|
||||||
m_edit_figures[slot - 1]->setText(tr("None"));
|
m_edit_figures[slot]->setText(tr("None"));
|
||||||
|
|
||||||
system.GetInfinityBase().RemoveFigure(slot);
|
system.GetInfinityBase().RemoveFigure(slot);
|
||||||
}
|
}
|
||||||
|
@ -139,7 +139,7 @@ void InfinityBaseWindow::LoadFigure(u8 slot)
|
||||||
|
|
||||||
s_last_figure_path = QFileInfo(file_path).absolutePath() + QLatin1Char('/');
|
s_last_figure_path = QFileInfo(file_path).absolutePath() + QLatin1Char('/');
|
||||||
|
|
||||||
m_edit_figures[slot - 1]->setText(QFileInfo(file_path).fileName());
|
m_edit_figures[slot]->setText(QFileInfo(file_path).fileName());
|
||||||
|
|
||||||
LoadFigurePath(slot, file_path);
|
LoadFigurePath(slot, file_path);
|
||||||
}
|
}
|
||||||
|
@ -177,8 +177,8 @@ 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 - 1]->setText(QString::fromStdString(
|
m_edit_figures[slot]->setText(QString::fromStdString(
|
||||||
system.GetInfinityBase().LoadFigure(file_data.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, u8 slot) : QDialog(parent)
|
||||||
|
@ -190,24 +190,22 @@ CreateFigureDialog::CreateFigureDialog(QWidget* parent, u8 slot) : QDialog(paren
|
||||||
|
|
||||||
auto* combo_figlist = new QComboBox();
|
auto* combo_figlist = new QComboBox();
|
||||||
QStringList filterlist;
|
QStringList filterlist;
|
||||||
u16 first_entry = 0;
|
u32 first_entry = 0;
|
||||||
for (const auto& entry : Core::System::GetInstance().GetInfinityBase().GetFigureList())
|
for (const auto& entry : Core::System::GetInstance().GetInfinityBase().GetFigureList())
|
||||||
{
|
{
|
||||||
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 == 0x01 && (figure.type == IOS::HLE::USB::InfinityFigureType::Playset ||
|
if ((slot == 0 &&
|
||||||
figure.type == IOS::HLE::USB::InfinityFigureType::Item)) ||
|
((figure > 0x1E8480 && figure < 0x2DC6BF) || (figure > 0x3D0900 && figure < 0x4C4B3F))) ||
|
||||||
((slot == 0x02 || slot == 0x03) &&
|
((slot == 1 || slot == 2) && figure < 0x1E847F) ||
|
||||||
figure.type == IOS::HLE::USB::InfinityFigureType::Character) ||
|
((slot == 3 || slot == 4 || slot == 5 || slot == 6) &&
|
||||||
((slot == 0x04 || slot == 0x05 || slot == 0x06 || slot == 0x07) &&
|
(figure > 0x2DC6C0 && figure < 0x3D08FF)))
|
||||||
(figure.type == IOS::HLE::USB::InfinityFigureType::Ability_A ||
|
|
||||||
figure.type == IOS::HLE::USB::InfinityFigureType::Ability_B)))
|
|
||||||
{
|
{
|
||||||
combo_figlist->addItem(QString::fromStdString(entry.first), QVariant(figure.figure_number));
|
combo_figlist->addItem(QString::fromStdString(entry.first), QVariant(figure));
|
||||||
filterlist << QString::fromStdString(entry.first);
|
filterlist << QString::fromStdString(entry.first);
|
||||||
if (first_entry == 0)
|
if (first_entry == 0)
|
||||||
{
|
{
|
||||||
first_entry = figure.figure_number;
|
first_entry = figure;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -253,7 +251,7 @@ CreateFigureDialog::CreateFigureDialog(QWidget* parent, u8 slot) : QDialog(paren
|
||||||
|
|
||||||
connect(buttons, &QDialogButtonBox::accepted, this, [=, this]() {
|
connect(buttons, &QDialogButtonBox::accepted, this, [=, this]() {
|
||||||
bool ok_char = false;
|
bool ok_char = false;
|
||||||
const u16 char_number = edit_num->text().toUShort(&ok_char);
|
const u32 char_number = edit_num->text().toULong(&ok_char);
|
||||||
if (!ok_char)
|
if (!ok_char)
|
||||||
{
|
{
|
||||||
QMessageBox::warning(this, tr("Error converting value"), tr("Character entered is invalid!"),
|
QMessageBox::warning(this, tr("Error converting value"), tr("Character entered is invalid!"),
|
||||||
|
@ -265,7 +263,7 @@ CreateFigureDialog::CreateFigureDialog(QWidget* parent, u8 slot) : QDialog(paren
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = Core::System::GetInstance();
|
||||||
const auto found_fig = system.GetInfinityBase().FindFigure(char_number);
|
const auto found_fig = system.GetInfinityBase().FindFigure(char_number);
|
||||||
if (found_fig != "")
|
if (!found_fig.empty())
|
||||||
{
|
{
|
||||||
predef_name += QString::fromStdString(std::string(found_fig) + ".bin");
|
predef_name += QString::fromStdString(std::string(found_fig) + ".bin");
|
||||||
}
|
}
|
||||||
|
@ -284,8 +282,10 @@ CreateFigureDialog::CreateFigureDialog(QWidget* parent, u8 slot) : QDialog(paren
|
||||||
|
|
||||||
if (!system.GetInfinityBase().CreateFigure(m_file_path.toStdString(), char_number))
|
if (!system.GetInfinityBase().CreateFigure(m_file_path.toStdString(), char_number))
|
||||||
{
|
{
|
||||||
QMessageBox::warning(this, tr("Failed to create Infinity file!"),
|
QMessageBox::warning(
|
||||||
tr("Failed to create Infinity file:\n%1").arg(m_file_path),
|
this, tr("Failed to create Infinity file"),
|
||||||
|
tr("Blank figure creation failed at:\n%1, try again with a different character")
|
||||||
|
.arg(m_file_path),
|
||||||
QMessageBox::Ok);
|
QMessageBox::Ok);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue