summaryrefslogtreecommitdiff
path: root/Source/Core/DolphinQt/Config/CheatCodeEditor.cpp
diff options
context:
space:
mode:
authorspycrab <spycrab@users.noreply.github.com>2018-07-07 00:40:15 +0200
committerspycrab <spycrab@users.noreply.github.com>2018-07-07 00:48:38 +0200
commit13ba24c5a6795532c8893eccf2a21ae95682e1b7 (patch)
tree747e394036c189c46add1b3e1451e50f48230e11 /Source/Core/DolphinQt/Config/CheatCodeEditor.cpp
parent059880bb1640d5a3b0e1fbbf66e1a356df4b9f41 (diff)
Move DolphinQt2 to DolphinQt
Diffstat (limited to 'Source/Core/DolphinQt/Config/CheatCodeEditor.cpp')
-rw-r--r--Source/Core/DolphinQt/Config/CheatCodeEditor.cpp305
1 files changed, 305 insertions, 0 deletions
diff --git a/Source/Core/DolphinQt/Config/CheatCodeEditor.cpp b/Source/Core/DolphinQt/Config/CheatCodeEditor.cpp
new file mode 100644
index 0000000000..a72e4781be
--- /dev/null
+++ b/Source/Core/DolphinQt/Config/CheatCodeEditor.cpp
@@ -0,0 +1,305 @@
+// Copyright 2018 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#include "DolphinQt/Config/CheatCodeEditor.h"
+
+#include <QDialogButtonBox>
+#include <QFontDatabase>
+#include <QGridLayout>
+#include <QLabel>
+#include <QLineEdit>
+#include <QMessageBox>
+#include <QStringList>
+#include <QTextEdit>
+
+#include "Core/ARDecrypt.h"
+#include "Core/ActionReplay.h"
+#include "Core/GeckoCodeConfig.h"
+
+CheatCodeEditor::CheatCodeEditor(QWidget* parent) : QDialog(parent)
+{
+ setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+ setWindowTitle(tr("Cheat Code Editor"));
+
+ CreateWidgets();
+ ConnectWidgets();
+}
+
+void CheatCodeEditor::SetARCode(ActionReplay::ARCode* code)
+{
+ m_name_edit->setText(QString::fromStdString(code->name));
+
+ QString s;
+
+ for (ActionReplay::AREntry& e : code->ops)
+ {
+ s += QStringLiteral("%1 %2\n")
+ .arg(e.cmd_addr, 8, 16, QLatin1Char('0'))
+ .arg(e.value, 8, 16, QLatin1Char('0'));
+ }
+
+ m_code_edit->setText(s);
+
+ m_creator_label->setHidden(true);
+ m_creator_edit->setHidden(true);
+ m_notes_label->setHidden(true);
+ m_notes_edit->setHidden(true);
+
+ m_ar_code = code;
+ m_gecko_code = nullptr;
+}
+
+void CheatCodeEditor::SetGeckoCode(Gecko::GeckoCode* code)
+{
+ m_name_edit->setText(QString::fromStdString(code->name));
+ m_creator_edit->setText(QString::fromStdString(code->creator));
+
+ QString code_string;
+
+ for (const auto& c : code->codes)
+ code_string += QStringLiteral("%1 %2\n")
+ .arg(c.address, 8, 16, QLatin1Char('0'))
+ .arg(c.data, 8, 16, QLatin1Char('0'));
+
+ m_code_edit->setText(code_string);
+
+ QString notes_string;
+ for (const auto& line : code->notes)
+ notes_string += QStringLiteral("%1\n").arg(QString::fromStdString(line));
+
+ 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);
+
+ m_gecko_code = code;
+ m_ar_code = nullptr;
+}
+
+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);
+
+ QFont monospace(QFontDatabase::systemFont(QFontDatabase::FixedFont).family());
+
+ m_code_edit->setFont(monospace);
+
+ m_code_edit->setAcceptRichText(false);
+ m_notes_edit->setAcceptRichText(false);
+
+ setLayout(grid_layout);
+}
+
+void CheatCodeEditor::ConnectWidgets()
+{
+ connect(m_button_box, &QDialogButtonBox::accepted, this, &CheatCodeEditor::accept);
+ connect(m_button_box, &QDialogButtonBox::rejected, this, &QDialog::reject);
+}
+
+bool CheatCodeEditor::AcceptAR()
+{
+ std::vector<ActionReplay::AREntry> entries;
+ std::vector<std::string> encrypted_lines;
+
+ QStringList lines = m_code_edit->toPlainText().split(QStringLiteral("\n"));
+
+ for (int i = 0; i < lines.size(); i++)
+ {
+ QString line = lines[i];
+
+ if (line.isEmpty())
+ continue;
+
+ QStringList values = line.split(QStringLiteral(" "));
+
+ bool good = true;
+
+ u32 addr = 0;
+ u32 value = 0;
+
+ if (values.size() == 2)
+ {
+ addr = values[0].toUInt(&good, 16);
+
+ if (good)
+ value = values[1].toUInt(&good, 16);
+
+ if (good)
+ entries.push_back(ActionReplay::AREntry(addr, value));
+ }
+ else
+ {
+ QStringList blocks = line.split(QStringLiteral("-"));
+
+ if (blocks.size() == 3 && blocks[0].size() == 4 && blocks[1].size() == 4 &&
+ blocks[2].size() == 5)
+ {
+ encrypted_lines.emplace_back(blocks[0].toStdString() + blocks[1].toStdString() +
+ blocks[2].toStdString());
+ }
+ else
+ {
+ good = false;
+ }
+ }
+
+ if (!good)
+ {
+ auto result = QMessageBox::warning(
+ this, tr("Parsing Error"),
+ tr("Unable to parse line %1 of the entered AR code as a valid "
+ "encrypted or decrypted code. Make sure you typed it correctly.\n\n"
+ "Would you like to ignore this line and continue parsing?")
+ .arg(i + 1),
+ QMessageBox::Ok | QMessageBox::Abort);
+
+ if (result == QMessageBox::Abort)
+ return false;
+ }
+ }
+
+ if (!encrypted_lines.empty())
+ {
+ if (!entries.empty())
+ {
+ auto result = QMessageBox::warning(
+ this, tr("Invalid Mixed Code"),
+ tr("This Action Replay code contains both encrypted and unencrypted lines; "
+ "you should check that you have entered it correctly.\n\n"
+ "Do you want to discard all unencrypted lines?"),
+ QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
+
+ // YES = Discard the unencrypted lines then decrypt the encrypted ones instead.
+ // NO = Discard the encrypted lines, keep the unencrypted ones
+ // CANCEL = Stop and let the user go back to editing
+ switch (result)
+ {
+ case QMessageBox::Yes:
+ entries.clear();
+ break;
+ case QMessageBox::No:
+ encrypted_lines.clear();
+ break;
+ case QMessageBox::Cancel:
+ return false;
+ default:
+ break;
+ }
+ }
+ ActionReplay::DecryptARCode(encrypted_lines, &entries);
+ }
+
+ if (entries.empty())
+ {
+ QMessageBox::critical(this, tr("Error"),
+ tr("The resulting decrypted AR code doesn't contain any lines."));
+ return false;
+ }
+
+ m_ar_code->name = m_name_edit->text().toStdString();
+ m_ar_code->ops = std::move(entries);
+ m_ar_code->user_defined = true;
+
+ return true;
+}
+
+bool CheatCodeEditor::AcceptGecko()
+{
+ std::vector<Gecko::GeckoCode::Code> entries;
+
+ QStringList lines = m_code_edit->toPlainText().split(QStringLiteral("\n"));
+
+ for (int i = 0; i < lines.size(); i++)
+ {
+ QString line = lines[i];
+
+ if (line.isEmpty())
+ continue;
+
+ QStringList values = line.split(QStringLiteral(" "));
+
+ bool good = values.size() == 2;
+
+ u32 addr = 0;
+ u32 value = 0;
+
+ if (good)
+ addr = values[0].toUInt(&good, 16);
+
+ if (good)
+ value = values[1].toUInt(&good, 16);
+
+ if (!good)
+ {
+ auto result =
+ QMessageBox::warning(this, tr("Parsing Error"),
+ tr("Unable to parse line %1 of the entered Gecko code as a valid "
+ "code. Make sure you typed it correctly.\n\n"
+ "Would you like to ignore this line and continue parsing?")
+ .arg(i + 1),
+ QMessageBox::Ok | QMessageBox::Abort);
+
+ if (result == QMessageBox::Abort)
+ return false;
+ }
+ else
+ {
+ Gecko::GeckoCode::Code c;
+ c.address = addr;
+ c.data = value;
+ c.original_line = line.toStdString();
+
+ entries.push_back(c);
+ }
+ }
+
+ if (entries.empty())
+ {
+ QMessageBox::critical(this, tr("Error"),
+ tr("The resulting decrypted AR code doesn't contain any lines."));
+ return false;
+ }
+
+ m_gecko_code->name = m_name_edit->text().toStdString();
+ m_gecko_code->creator = m_creator_edit->text().toStdString();
+ m_gecko_code->codes = std::move(entries);
+ m_gecko_code->user_defined = true;
+
+ std::vector<std::string> note_lines;
+ for (QString line : m_notes_edit->toPlainText().split(QStringLiteral("\n")))
+ note_lines.push_back(line.toStdString());
+
+ m_gecko_code->notes = std::move(note_lines);
+
+ return true;
+}
+
+void CheatCodeEditor::accept()
+{
+ bool success = m_gecko_code != nullptr ? AcceptGecko() : AcceptAR();
+
+ if (success)
+ QDialog::accept();
+}