Core: Combine Gecko cheat code name and creator name into a single field.

This aligns Gecko codes with Action Replay codes, where the distinction
between code name and creator name has never existed.

The main objective of the change is to address potential inconsistencies
where two Gecko codes of the same name but of different creator can
coexist in the `INI` file but cannot be individually enabled in Dolphin.

This was a valid scenario prior to these changes:

```ini
[Gecko]
$Infinite Power [Alice]
<code line 1>
<code line 2>
<code line 3>
<...>
$Infinite Power [Bob]
<code line 1>
<code line 2>
<code line 3>
<...>
[Gecko_Enabled]
$Infinite Power
```

Notice that, previously, enabled cheat codes in the `[Gecko_Enabled]`
section would only include the cheat code name excluding the creator
name (which was technically a different field in Dolphin's data
structures).

Now, the equivalent INI document lists the cheat code full name
(including the creator name), allowing both codes to be enabled
separately:

```ini
[Gecko]
$Infinite Power [Alice]
<code line 1>
<code line 2>
<code line 3>
<...>
$Infinite Power [Bob]
<code line 1>
<code line 2>
<code line 3>
<...>
[Gecko_Enabled]
$Infinite Power [Alice]
```

This also fixes https://bugs.dolphin-emu.org/issues/13695.
This commit is contained in:
cristian64 2024-12-10 15:29:11 +00:00
parent 394db8b798
commit 6bdda09b71
7 changed files with 11 additions and 49 deletions

View File

@ -29,7 +29,7 @@ class GeckoCheat : AbstractCheat {
} }
override fun supportsCreator(): Boolean { override fun supportsCreator(): Boolean {
return true return false
} }
override fun supportsNotes(): Boolean { override fun supportsNotes(): Boolean {
@ -38,8 +38,6 @@ class GeckoCheat : AbstractCheat {
external override fun getName(): String external override fun getName(): String
external override fun getCreator(): String
external override fun getNotes(): String external override fun getNotes(): String
external override fun getCode(): String external override fun getCode(): String

View File

@ -52,12 +52,6 @@ Java_org_dolphinemu_dolphinemu_features_cheats_model_GeckoCheat_getName(JNIEnv*
return ToJString(env, GetPointer(env, obj)->name); return ToJString(env, GetPointer(env, obj)->name);
} }
JNIEXPORT jstring JNICALL
Java_org_dolphinemu_dolphinemu_features_cheats_model_GeckoCheat_getCreator(JNIEnv* env, jobject obj)
{
return ToJString(env, GetPointer(env, obj)->creator);
}
JNIEXPORT jstring JNICALL JNIEXPORT jstring JNICALL
Java_org_dolphinemu_dolphinemu_features_cheats_model_GeckoCheat_getNotes(JNIEnv* env, jobject obj) Java_org_dolphinemu_dolphinemu_features_cheats_model_GeckoCheat_getNotes(JNIEnv* env, jobject obj)
{ {
@ -128,7 +122,6 @@ JNIEXPORT jint JNICALL Java_org_dolphinemu_dolphinemu_features_cheats_model_Geck
return Cheats::TRY_SET_FAIL_NO_CODE_LINES; return Cheats::TRY_SET_FAIL_NO_CODE_LINES;
code->name = GetJString(env, name); code->name = GetJString(env, name);
code->creator = GetJString(env, creator);
code->notes = SplitString(GetJString(env, notes), '\n'); code->notes = SplitString(GetJString(env, notes), '\n');
code->codes = std::move(entries); code->codes = std::move(entries);

View File

@ -30,7 +30,7 @@ public:
}; };
std::vector<Code> codes; std::vector<Code> codes;
std::string name, creator; std::string name;
std::vector<std::string> notes; std::vector<std::string> notes;
bool enabled = false; bool enabled = false;

View File

@ -72,12 +72,9 @@ std::vector<GeckoCode> DownloadCodes(std::string gametdb_id, bool* succeeded, bo
case 0: case 0:
{ {
std::istringstream ssline(line); std::istringstream ssline(line);
// stop at [ character (beginning of contributor name) std::getline(ssline, gcode.name);
std::getline(ssline, gcode.name, '[');
gcode.name = StripWhitespace(gcode.name); gcode.name = StripWhitespace(gcode.name);
gcode.user_defined = true; gcode.user_defined = true;
// read the code creator name
std::getline(ssline, gcode.creator, ']');
read_state = 1; read_state = 1;
} }
break; break;
@ -162,10 +159,8 @@ std::vector<GeckoCode> LoadCodes(const Common::IniFile& globalIni, const Common:
gcode.user_defined = (ini == &localIni); gcode.user_defined = (ini == &localIni);
ss.seekg(1, std::ios_base::cur); ss.seekg(1, std::ios_base::cur);
// read the code name // read the code name
std::getline(ss, gcode.name, '['); // stop at [ character (beginning of contributor name) std::getline(ss, gcode.name);
gcode.name = StripWhitespace(gcode.name); gcode.name = StripWhitespace(gcode.name);
// read the code creator name
std::getline(ss, gcode.creator, ']');
break; break;
// notes // notes
@ -208,14 +203,7 @@ std::vector<GeckoCode> LoadCodes(const Common::IniFile& globalIni, const Common:
static std::string MakeGeckoCodeTitle(const GeckoCode& code) static std::string MakeGeckoCodeTitle(const GeckoCode& code)
{ {
std::string title = '$' + code.name; return '$' + code.name;
if (!code.creator.empty())
{
title += " [" + code.creator + ']';
}
return title;
} }
// used by the SaveGeckoCodes function // used by the SaveGeckoCodes function

View File

@ -37,8 +37,6 @@ void CheatCodeEditor::SetARCode(ActionReplay::ARCode* code)
for (ActionReplay::AREntry& e : code->ops) for (ActionReplay::AREntry& e : code->ops)
m_code_edit->append(QString::fromStdString(ActionReplay::SerializeLine(e))); m_code_edit->append(QString::fromStdString(ActionReplay::SerializeLine(e)));
m_creator_label->setHidden(true);
m_creator_edit->setHidden(true);
m_notes_label->setHidden(true); m_notes_label->setHidden(true);
m_notes_edit->setHidden(true); m_notes_edit->setHidden(true);
@ -49,7 +47,6 @@ void CheatCodeEditor::SetARCode(ActionReplay::ARCode* code)
void CheatCodeEditor::SetGeckoCode(Gecko::GeckoCode* code) void CheatCodeEditor::SetGeckoCode(Gecko::GeckoCode* code)
{ {
m_name_edit->setText(QString::fromStdString(code->name)); m_name_edit->setText(QString::fromStdString(code->name));
m_creator_edit->setText(QString::fromStdString(code->creator));
m_code_edit->clear(); m_code_edit->clear();
@ -62,8 +59,6 @@ void CheatCodeEditor::SetGeckoCode(Gecko::GeckoCode* code)
m_notes_edit->setText(notes_string); m_notes_edit->setText(notes_string);
m_creator_label->setHidden(false);
m_creator_edit->setHidden(false);
m_notes_label->setHidden(false); m_notes_label->setHidden(false);
m_notes_edit->setHidden(false); m_notes_edit->setHidden(false);
@ -74,25 +69,21 @@ void CheatCodeEditor::SetGeckoCode(Gecko::GeckoCode* code)
void CheatCodeEditor::CreateWidgets() void CheatCodeEditor::CreateWidgets()
{ {
m_name_edit = new QLineEdit; m_name_edit = new QLineEdit;
m_creator_edit = new QLineEdit;
m_notes_edit = new QTextEdit; m_notes_edit = new QTextEdit;
m_code_edit = new QTextEdit; m_code_edit = new QTextEdit;
m_button_box = new QDialogButtonBox(QDialogButtonBox::Cancel | QDialogButtonBox::Save); m_button_box = new QDialogButtonBox(QDialogButtonBox::Cancel | QDialogButtonBox::Save);
m_creator_label = new QLabel(tr("Creator:"));
m_notes_label = new QLabel(tr("Notes:")); m_notes_label = new QLabel(tr("Notes:"));
QGridLayout* grid_layout = new QGridLayout; QGridLayout* grid_layout = new QGridLayout;
grid_layout->addWidget(new QLabel(tr("Name:")), 0, 0); grid_layout->addWidget(new QLabel(tr("Name:")), 0, 0);
grid_layout->addWidget(m_name_edit, 0, 1); grid_layout->addWidget(m_name_edit, 0, 1);
grid_layout->addWidget(m_creator_label, 1, 0); grid_layout->addWidget(m_notes_label, 1, 0);
grid_layout->addWidget(m_creator_edit, 1, 1); grid_layout->addWidget(m_notes_edit, 1, 1);
grid_layout->addWidget(m_notes_label, 2, 0); grid_layout->addWidget(new QLabel(tr("Code:")), 2, 0);
grid_layout->addWidget(m_notes_edit, 2, 1); grid_layout->addWidget(m_code_edit, 2, 1);
grid_layout->addWidget(new QLabel(tr("Code:")), 3, 0); grid_layout->addWidget(m_button_box, 3, 1);
grid_layout->addWidget(m_code_edit, 3, 1);
grid_layout->addWidget(m_button_box, 4, 1);
QFont monospace(QFontDatabase::systemFont(QFontDatabase::FixedFont).family()); QFont monospace(QFontDatabase::systemFont(QFontDatabase::FixedFont).family());
@ -252,7 +243,6 @@ bool CheatCodeEditor::AcceptGecko()
} }
m_gecko_code->name = name.toStdString(); m_gecko_code->name = name.toStdString();
m_gecko_code->creator = m_creator_edit->text().toStdString();
m_gecko_code->codes = std::move(entries); m_gecko_code->codes = std::move(entries);
m_gecko_code->notes = SplitString(m_notes_edit->toPlainText().toStdString(), '\n'); m_gecko_code->notes = SplitString(m_notes_edit->toPlainText().toStdString(), '\n');
m_gecko_code->user_defined = true; m_gecko_code->user_defined = true;

View File

@ -37,11 +37,9 @@ private:
void accept() override; void accept() override;
QLabel* m_creator_label;
QLabel* m_notes_label; QLabel* m_notes_label;
QLineEdit* m_name_edit; QLineEdit* m_name_edit;
QLineEdit* m_creator_edit;
QTextEdit* m_notes_edit; QTextEdit* m_notes_edit;
QTextEdit* m_code_edit; QTextEdit* m_code_edit;
QDialogButtonBox* m_button_box; QDialogButtonBox* m_button_box;

View File

@ -56,7 +56,6 @@ void GeckoCodeWidget::ChangeGame(std::string game_id, std::string gametdb_id,
m_gecko_codes.clear(); m_gecko_codes.clear();
m_code_list->clear(); m_code_list->clear();
m_name_label->clear(); m_name_label->clear();
m_creator_label->clear();
m_code_description->clear(); m_code_description->clear();
m_code_view->clear(); m_code_view->clear();
@ -78,7 +77,6 @@ void GeckoCodeWidget::CreateWidgets()
#endif // USE_RETRO_ACHIEVEMENTS #endif // USE_RETRO_ACHIEVEMENTS
m_code_list = new QListWidget; m_code_list = new QListWidget;
m_name_label = new QLabel; m_name_label = new QLabel;
m_creator_label = new QLabel;
m_code_list->setContextMenuPolicy(Qt::CustomContextMenu); m_code_list->setContextMenuPolicy(Qt::CustomContextMenu);
@ -116,12 +114,11 @@ void GeckoCodeWidget::CreateWidgets()
auto* info_layout = new QFormLayout; auto* info_layout = new QFormLayout;
info_layout->addRow(tr("Name:"), m_name_label); info_layout->addRow(tr("Name:"), m_name_label);
info_layout->addRow(tr("Creator:"), m_creator_label);
info_layout->addRow(tr("Description:"), static_cast<QWidget*>(nullptr)); info_layout->addRow(tr("Description:"), static_cast<QWidget*>(nullptr));
info_layout->setFormAlignment(Qt::AlignLeft | Qt::AlignTop); info_layout->setFormAlignment(Qt::AlignLeft | Qt::AlignTop);
for (QLabel* label : {m_name_label, m_creator_label}) for (QLabel* const label : {m_name_label})
{ {
label->setTextInteractionFlags(Qt::TextSelectableByMouse); label->setTextInteractionFlags(Qt::TextSelectableByMouse);
label->setCursor(Qt::IBeamCursor); label->setCursor(Qt::IBeamCursor);
@ -183,7 +180,6 @@ void GeckoCodeWidget::OnSelectionChanged()
const auto& code = m_gecko_codes[index]; const auto& code = m_gecko_codes[index];
m_name_label->setText(QString::fromStdString(code.name)); m_name_label->setText(QString::fromStdString(code.name));
m_creator_label->setText(QString::fromStdString(code.creator));
m_code_description->clear(); m_code_description->clear();
@ -269,7 +265,6 @@ void GeckoCodeWidget::LoadCodes()
m_code_list->setEnabled(!m_game_id.empty()); m_code_list->setEnabled(!m_game_id.empty());
m_name_label->setEnabled(!m_game_id.empty()); m_name_label->setEnabled(!m_game_id.empty());
m_creator_label->setEnabled(!m_game_id.empty());
m_code_description->setEnabled(!m_game_id.empty()); m_code_description->setEnabled(!m_game_id.empty());
m_code_view->setEnabled(!m_game_id.empty()); m_code_view->setEnabled(!m_game_id.empty());