diff options
| author | spycrab <spycrab@users.noreply.github.com> | 2018-07-07 00:40:15 +0200 |
|---|---|---|
| committer | spycrab <spycrab@users.noreply.github.com> | 2018-07-07 00:48:38 +0200 |
| commit | 13ba24c5a6795532c8893eccf2a21ae95682e1b7 (patch) | |
| tree | 747e394036c189c46add1b3e1451e50f48230e11 /Source/Core/DolphinQt/Config/CheatCodeEditor.cpp | |
| parent | 059880bb1640d5a3b0e1fbbf66e1a356df4b9f41 (diff) | |
Move DolphinQt2 to DolphinQt
Diffstat (limited to 'Source/Core/DolphinQt/Config/CheatCodeEditor.cpp')
| -rw-r--r-- | Source/Core/DolphinQt/Config/CheatCodeEditor.cpp | 305 |
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(); +} |
