CheatSearchFactoryWidget.cpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. // Copyright 2021 Dolphin Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include "DolphinQt/CheatSearchFactoryWidget.h"
  4. #include <string>
  5. #include <vector>
  6. #include <QButtonGroup>
  7. #include <QCheckBox>
  8. #include <QComboBox>
  9. #include <QGroupBox>
  10. #include <QLabel>
  11. #include <QLineEdit>
  12. #include <QPushButton>
  13. #include <QRadioButton>
  14. #include <QVBoxLayout>
  15. #include "Common/StringUtil.h"
  16. #include "Core/CheatSearch.h"
  17. #include "Core/Core.h"
  18. #include "Core/HW/Memmap.h"
  19. #include "Core/PowerPC/MMU.h"
  20. #include "Core/System.h"
  21. #include "DolphinQt/QtUtils/ModalMessageBox.h"
  22. #include "DolphinQt/QtUtils/NonDefaultQPushButton.h"
  23. CheatSearchFactoryWidget::CheatSearchFactoryWidget()
  24. {
  25. CreateWidgets();
  26. ConnectWidgets();
  27. RefreshGui();
  28. }
  29. CheatSearchFactoryWidget::~CheatSearchFactoryWidget() = default;
  30. Q_DECLARE_METATYPE(Cheats::DataType);
  31. void CheatSearchFactoryWidget::CreateWidgets()
  32. {
  33. auto* const layout = new QVBoxLayout{this};
  34. auto* address_space_group = new QGroupBox(tr("Address Space"));
  35. auto* address_space_layout = new QVBoxLayout();
  36. address_space_group->setLayout(address_space_layout);
  37. m_standard_address_space = new QRadioButton(tr("Typical GameCube/Wii Address Space"));
  38. m_standard_address_space->setChecked(true);
  39. m_custom_address_space = new QRadioButton(tr("Custom Address Space"));
  40. QLabel* label_standard_address_space =
  41. new QLabel(tr("Sets up the search using standard MEM1 and (on Wii) MEM2 mappings in virtual "
  42. "address space. This will work for the vast majority of games."));
  43. label_standard_address_space->setWordWrap(true);
  44. auto* custom_address_space_layout = new QVBoxLayout();
  45. custom_address_space_layout->setContentsMargins(6, 6, 6, 6);
  46. auto* custom_address_space_button_group = new QButtonGroup(this);
  47. m_custom_virtual_address_space = new QRadioButton(tr("Use virtual addresses when possible"));
  48. m_custom_virtual_address_space->setChecked(true);
  49. m_custom_physical_address_space = new QRadioButton(tr("Use physical addresses"));
  50. m_custom_effective_address_space =
  51. new QRadioButton(tr("Use memory mapper configuration at time of scan"));
  52. custom_address_space_button_group->addButton(m_custom_virtual_address_space);
  53. custom_address_space_button_group->addButton(m_custom_physical_address_space);
  54. custom_address_space_button_group->addButton(m_custom_effective_address_space);
  55. custom_address_space_layout->addWidget(m_custom_virtual_address_space);
  56. custom_address_space_layout->addWidget(m_custom_physical_address_space);
  57. custom_address_space_layout->addWidget(m_custom_effective_address_space);
  58. QLabel* label_range_start = new QLabel(tr("Range Start: "));
  59. m_custom_address_start = new QLineEdit(QStringLiteral("0x80000000"));
  60. QLabel* label_range_end = new QLabel(tr("Range End: "));
  61. m_custom_address_end = new QLineEdit(QStringLiteral("0x81800000"));
  62. custom_address_space_layout->addWidget(label_range_start);
  63. custom_address_space_layout->addWidget(m_custom_address_start);
  64. custom_address_space_layout->addWidget(label_range_end);
  65. custom_address_space_layout->addWidget(m_custom_address_end);
  66. address_space_layout->addWidget(m_standard_address_space);
  67. address_space_layout->addWidget(label_standard_address_space);
  68. address_space_layout->addWidget(m_custom_address_space);
  69. address_space_layout->addLayout(custom_address_space_layout);
  70. layout->addWidget(address_space_group);
  71. auto* data_type_group = new QGroupBox(tr("Data Type"));
  72. auto* data_type_layout = new QVBoxLayout();
  73. data_type_group->setLayout(data_type_layout);
  74. m_data_type_dropdown = new QComboBox();
  75. m_data_type_dropdown->addItem(tr("8-bit Unsigned Integer"),
  76. QVariant::fromValue(Cheats::DataType::U8));
  77. m_data_type_dropdown->addItem(tr("16-bit Unsigned Integer"),
  78. QVariant::fromValue(Cheats::DataType::U16));
  79. m_data_type_dropdown->addItem(tr("32-bit Unsigned Integer"),
  80. QVariant::fromValue(Cheats::DataType::U32));
  81. m_data_type_dropdown->addItem(tr("64-bit Unsigned Integer"),
  82. QVariant::fromValue(Cheats::DataType::U64));
  83. m_data_type_dropdown->addItem(tr("8-bit Signed Integer"),
  84. QVariant::fromValue(Cheats::DataType::S8));
  85. m_data_type_dropdown->addItem(tr("16-bit Signed Integer"),
  86. QVariant::fromValue(Cheats::DataType::S16));
  87. m_data_type_dropdown->addItem(tr("32-bit Signed Integer"),
  88. QVariant::fromValue(Cheats::DataType::S32));
  89. m_data_type_dropdown->addItem(tr("64-bit Signed Integer"),
  90. QVariant::fromValue(Cheats::DataType::S64));
  91. m_data_type_dropdown->addItem(tr("32-bit Float"), QVariant::fromValue(Cheats::DataType::F32));
  92. m_data_type_dropdown->addItem(tr("64-bit Float"), QVariant::fromValue(Cheats::DataType::F64));
  93. m_data_type_dropdown->setCurrentIndex(6); // select 32bit signed int by default
  94. data_type_layout->addWidget(m_data_type_dropdown);
  95. m_data_type_aligned = new QCheckBox(tr("Aligned to data type length"));
  96. m_data_type_aligned->setChecked(true);
  97. data_type_layout->addWidget(m_data_type_aligned);
  98. layout->addWidget(data_type_group);
  99. m_new_search = new NonDefaultQPushButton(tr("New Search"));
  100. layout->addWidget(m_new_search);
  101. layout->addStretch();
  102. }
  103. void CheatSearchFactoryWidget::ConnectWidgets()
  104. {
  105. connect(m_new_search, &QPushButton::clicked, this, &CheatSearchFactoryWidget::OnNewSearchClicked);
  106. connect(m_standard_address_space, &QPushButton::toggled, this,
  107. &CheatSearchFactoryWidget::OnAddressSpaceRadioChanged);
  108. connect(m_custom_address_space, &QRadioButton::toggled, this,
  109. &CheatSearchFactoryWidget::OnAddressSpaceRadioChanged);
  110. }
  111. void CheatSearchFactoryWidget::RefreshGui()
  112. {
  113. bool enable_custom = m_custom_address_space->isChecked();
  114. m_custom_virtual_address_space->setEnabled(enable_custom);
  115. m_custom_physical_address_space->setEnabled(enable_custom);
  116. m_custom_effective_address_space->setEnabled(enable_custom);
  117. m_custom_address_start->setEnabled(enable_custom);
  118. m_custom_address_end->setEnabled(enable_custom);
  119. }
  120. void CheatSearchFactoryWidget::OnAddressSpaceRadioChanged()
  121. {
  122. RefreshGui();
  123. }
  124. void CheatSearchFactoryWidget::OnNewSearchClicked()
  125. {
  126. std::vector<Cheats::MemoryRange> memory_ranges;
  127. PowerPC::RequestedAddressSpace address_space;
  128. if (m_standard_address_space->isChecked())
  129. {
  130. auto& system = Core::System::GetInstance();
  131. if (!Core::IsRunning(system))
  132. {
  133. ModalMessageBox::warning(
  134. this, tr("No game running."),
  135. tr("Please start a game before starting a search with standard memory regions."));
  136. return;
  137. }
  138. auto& memory = system.GetMemory();
  139. memory_ranges.emplace_back(0x80000000, memory.GetRamSizeReal());
  140. if (system.IsWii())
  141. memory_ranges.emplace_back(0x90000000, memory.GetExRamSizeReal());
  142. address_space = PowerPC::RequestedAddressSpace::Virtual;
  143. }
  144. else
  145. {
  146. const std::string address_start_str = m_custom_address_start->text().toStdString();
  147. const std::string address_end_str = m_custom_address_end->text().toStdString();
  148. u64 address_start;
  149. u64 address_end;
  150. if (!TryParse(address_start_str, &address_start) || !TryParse(address_end_str, &address_end))
  151. return;
  152. if (address_end <= address_start || address_end > 0x1'0000'0000)
  153. return;
  154. memory_ranges.emplace_back(static_cast<u32>(address_start), address_end - address_start);
  155. if (m_custom_virtual_address_space->isChecked())
  156. address_space = PowerPC::RequestedAddressSpace::Virtual;
  157. else if (m_custom_physical_address_space->isChecked())
  158. address_space = PowerPC::RequestedAddressSpace::Physical;
  159. else
  160. address_space = PowerPC::RequestedAddressSpace::Effective;
  161. }
  162. bool aligned = m_data_type_aligned->isChecked();
  163. auto data_type = m_data_type_dropdown->currentData().value<Cheats::DataType>();
  164. auto session = Cheats::MakeSession(std::move(memory_ranges), address_space, aligned, data_type);
  165. if (session)
  166. emit NewSessionCreated(*session);
  167. }