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 {
return true
return false
}
override fun supportsNotes(): Boolean {
@ -38,8 +38,6 @@ class GeckoCheat : AbstractCheat {
external override fun getName(): String
external override fun getCreator(): String
external override fun getNotes(): 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);
}
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
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;
code->name = GetJString(env, name);
code->creator = GetJString(env, creator);
code->notes = SplitString(GetJString(env, notes), '\n');
code->codes = std::move(entries);

View File

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

View File

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

View File

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

View File

@ -37,11 +37,9 @@ private:
void accept() override;
QLabel* m_creator_label;
QLabel* m_notes_label;
QLineEdit* m_name_edit;
QLineEdit* m_creator_edit;
QTextEdit* m_notes_edit;
QTextEdit* m_code_edit;
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_code_list->clear();
m_name_label->clear();
m_creator_label->clear();
m_code_description->clear();
m_code_view->clear();
@ -78,7 +77,6 @@ void GeckoCodeWidget::CreateWidgets()
#endif // USE_RETRO_ACHIEVEMENTS
m_code_list = new QListWidget;
m_name_label = new QLabel;
m_creator_label = new QLabel;
m_code_list->setContextMenuPolicy(Qt::CustomContextMenu);
@ -116,12 +114,11 @@ void GeckoCodeWidget::CreateWidgets()
auto* info_layout = new QFormLayout;
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->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->setCursor(Qt::IBeamCursor);
@ -183,7 +180,6 @@ void GeckoCodeWidget::OnSelectionChanged()
const auto& code = m_gecko_codes[index];
m_name_label->setText(QString::fromStdString(code.name));
m_creator_label->setText(QString::fromStdString(code.creator));
m_code_description->clear();
@ -269,7 +265,6 @@ void GeckoCodeWidget::LoadCodes()
m_code_list->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_view->setEnabled(!m_game_id.empty());