summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar liamwhite2022-11-11 16:15:36 -0500
committerGravatar GitHub2022-11-11 16:15:36 -0500
commitc4bc7ce7e2ec1d0d9441abc1f973a59040df9cfe (patch)
tree0457c22e886ffe37b0bfecd98e6e12d2a30722f4
parentMerge pull request #9167 from vonchenplus/tess (diff)
parentyuzu/main: Change to 8_GiB instead of magic number (diff)
downloadyuzu-c4bc7ce7e2ec1d0d9441abc1f973a59040df9cfe.tar.gz
yuzu-c4bc7ce7e2ec1d0d9441abc1f973a59040df9cfe.tar.xz
yuzu-c4bc7ce7e2ec1d0d9441abc1f973a59040df9cfe.zip
Merge pull request #9133 from FearlessTobi/compat-improvements
yuzu/compatdb: Improve compatibility submission system
-rw-r--r--src/yuzu/compatdb.cpp161
-rw-r--r--src/yuzu/compatdb.h11
-rw-r--r--src/yuzu/compatdb.ui277
-rw-r--r--src/yuzu/game_list_p.h12
-rw-r--r--src/yuzu/main.cpp14
5 files changed, 404 insertions, 71 deletions
diff --git a/src/yuzu/compatdb.cpp b/src/yuzu/compatdb.cpp
index f46fff340..b03e71248 100644
--- a/src/yuzu/compatdb.cpp
+++ b/src/yuzu/compatdb.cpp
@@ -15,12 +15,22 @@ CompatDB::CompatDB(Core::TelemetrySession& telemetry_session_, QWidget* parent)
15 : QWizard(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint), 15 : QWizard(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint),
16 ui{std::make_unique<Ui::CompatDB>()}, telemetry_session{telemetry_session_} { 16 ui{std::make_unique<Ui::CompatDB>()}, telemetry_session{telemetry_session_} {
17 ui->setupUi(this); 17 ui->setupUi(this);
18 connect(ui->radioButton_Perfect, &QRadioButton::clicked, this, &CompatDB::EnableNext); 18
19 connect(ui->radioButton_Great, &QRadioButton::clicked, this, &CompatDB::EnableNext); 19 connect(ui->radioButton_GameBoot_Yes, &QRadioButton::clicked, this, &CompatDB::EnableNext);
20 connect(ui->radioButton_Okay, &QRadioButton::clicked, this, &CompatDB::EnableNext); 20 connect(ui->radioButton_GameBoot_No, &QRadioButton::clicked, this, &CompatDB::EnableNext);
21 connect(ui->radioButton_Bad, &QRadioButton::clicked, this, &CompatDB::EnableNext); 21 connect(ui->radioButton_Gameplay_Yes, &QRadioButton::clicked, this, &CompatDB::EnableNext);
22 connect(ui->radioButton_IntroMenu, &QRadioButton::clicked, this, &CompatDB::EnableNext); 22 connect(ui->radioButton_Gameplay_No, &QRadioButton::clicked, this, &CompatDB::EnableNext);
23 connect(ui->radioButton_WontBoot, &QRadioButton::clicked, this, &CompatDB::EnableNext); 23 connect(ui->radioButton_NoFreeze_Yes, &QRadioButton::clicked, this, &CompatDB::EnableNext);
24 connect(ui->radioButton_NoFreeze_No, &QRadioButton::clicked, this, &CompatDB::EnableNext);
25 connect(ui->radioButton_Complete_Yes, &QRadioButton::clicked, this, &CompatDB::EnableNext);
26 connect(ui->radioButton_Complete_No, &QRadioButton::clicked, this, &CompatDB::EnableNext);
27 connect(ui->radioButton_Graphical_Major, &QRadioButton::clicked, this, &CompatDB::EnableNext);
28 connect(ui->radioButton_Graphical_Minor, &QRadioButton::clicked, this, &CompatDB::EnableNext);
29 connect(ui->radioButton_Graphical_No, &QRadioButton::clicked, this, &CompatDB::EnableNext);
30 connect(ui->radioButton_Audio_Major, &QRadioButton::clicked, this, &CompatDB::EnableNext);
31 connect(ui->radioButton_Audio_Minor, &QRadioButton::clicked, this, &CompatDB::EnableNext);
32 connect(ui->radioButton_Audio_No, &QRadioButton::clicked, this, &CompatDB::EnableNext);
33
24 connect(button(NextButton), &QPushButton::clicked, this, &CompatDB::Submit); 34 connect(button(NextButton), &QPushButton::clicked, this, &CompatDB::Submit);
25 connect(&testcase_watcher, &QFutureWatcher<bool>::finished, this, 35 connect(&testcase_watcher, &QFutureWatcher<bool>::finished, this,
26 &CompatDB::OnTestcaseSubmitted); 36 &CompatDB::OnTestcaseSubmitted);
@@ -30,29 +40,82 @@ CompatDB::~CompatDB() = default;
30 40
31enum class CompatDBPage { 41enum class CompatDBPage {
32 Intro = 0, 42 Intro = 0,
33 Selection = 1, 43 GameBoot = 1,
34 Final = 2, 44 GamePlay = 2,
45 Freeze = 3,
46 Completion = 4,
47 Graphical = 5,
48 Audio = 6,
49 Final = 7,
35}; 50};
36 51
37void CompatDB::Submit() { 52void CompatDB::Submit() {
38 QButtonGroup* compatibility = new QButtonGroup(this); 53 QButtonGroup* compatibility_GameBoot = new QButtonGroup(this);
39 compatibility->addButton(ui->radioButton_Perfect, 0); 54 compatibility_GameBoot->addButton(ui->radioButton_GameBoot_Yes, 0);
40 compatibility->addButton(ui->radioButton_Great, 1); 55 compatibility_GameBoot->addButton(ui->radioButton_GameBoot_No, 1);
41 compatibility->addButton(ui->radioButton_Okay, 2); 56
42 compatibility->addButton(ui->radioButton_Bad, 3); 57 QButtonGroup* compatibility_Gameplay = new QButtonGroup(this);
43 compatibility->addButton(ui->radioButton_IntroMenu, 4); 58 compatibility_Gameplay->addButton(ui->radioButton_Gameplay_Yes, 0);
44 compatibility->addButton(ui->radioButton_WontBoot, 5); 59 compatibility_Gameplay->addButton(ui->radioButton_Gameplay_No, 1);
60
61 QButtonGroup* compatibility_NoFreeze = new QButtonGroup(this);
62 compatibility_NoFreeze->addButton(ui->radioButton_NoFreeze_Yes, 0);
63 compatibility_NoFreeze->addButton(ui->radioButton_NoFreeze_No, 1);
64
65 QButtonGroup* compatibility_Complete = new QButtonGroup(this);
66 compatibility_Complete->addButton(ui->radioButton_Complete_Yes, 0);
67 compatibility_Complete->addButton(ui->radioButton_Complete_No, 1);
68
69 QButtonGroup* compatibility_Graphical = new QButtonGroup(this);
70 compatibility_Graphical->addButton(ui->radioButton_Graphical_Major, 0);
71 compatibility_Graphical->addButton(ui->radioButton_Graphical_Minor, 1);
72 compatibility_Graphical->addButton(ui->radioButton_Graphical_No, 2);
73
74 QButtonGroup* compatibility_Audio = new QButtonGroup(this);
75 compatibility_Audio->addButton(ui->radioButton_Audio_Major, 0);
76 compatibility_Graphical->addButton(ui->radioButton_Audio_Minor, 1);
77 compatibility_Audio->addButton(ui->radioButton_Audio_No, 2);
78
79 const int compatiblity = static_cast<int>(CalculateCompatibility());
80
45 switch ((static_cast<CompatDBPage>(currentId()))) { 81 switch ((static_cast<CompatDBPage>(currentId()))) {
46 case CompatDBPage::Selection: 82 case CompatDBPage::Intro:
47 if (compatibility->checkedId() == -1) { 83 break;
84 case CompatDBPage::GameBoot:
85 if (compatibility_GameBoot->checkedId() == -1) {
86 button(NextButton)->setEnabled(false);
87 }
88 break;
89 case CompatDBPage::GamePlay:
90 if (compatibility_Gameplay->checkedId() == -1) {
91 button(NextButton)->setEnabled(false);
92 }
93 break;
94 case CompatDBPage::Freeze:
95 if (compatibility_NoFreeze->checkedId() == -1) {
96 button(NextButton)->setEnabled(false);
97 }
98 break;
99 case CompatDBPage::Completion:
100 if (compatibility_Complete->checkedId() == -1) {
101 button(NextButton)->setEnabled(false);
102 }
103 break;
104 case CompatDBPage::Graphical:
105 if (compatibility_Graphical->checkedId() == -1) {
106 button(NextButton)->setEnabled(false);
107 }
108 break;
109 case CompatDBPage::Audio:
110 if (compatibility_Audio->checkedId() == -1) {
48 button(NextButton)->setEnabled(false); 111 button(NextButton)->setEnabled(false);
49 } 112 }
50 break; 113 break;
51 case CompatDBPage::Final: 114 case CompatDBPage::Final:
52 back(); 115 back();
53 LOG_DEBUG(Frontend, "Compatibility Rating: {}", compatibility->checkedId()); 116 LOG_INFO(Frontend, "Compatibility Rating: {}", compatiblity);
54 telemetry_session.AddField(Common::Telemetry::FieldType::UserFeedback, "Compatibility", 117 telemetry_session.AddField(Common::Telemetry::FieldType::UserFeedback, "Compatibility",
55 compatibility->checkedId()); 118 compatiblity);
56 119
57 button(NextButton)->setEnabled(false); 120 button(NextButton)->setEnabled(false);
58 button(NextButton)->setText(tr("Submitting")); 121 button(NextButton)->setText(tr("Submitting"));
@@ -66,6 +129,66 @@ void CompatDB::Submit() {
66 } 129 }
67} 130}
68 131
132int CompatDB::nextId() const {
133 switch ((static_cast<CompatDBPage>(currentId()))) {
134 case CompatDBPage::Intro:
135 return static_cast<int>(CompatDBPage::GameBoot);
136 case CompatDBPage::GameBoot:
137 if (ui->radioButton_GameBoot_No->isChecked()) {
138 return static_cast<int>(CompatDBPage::Final);
139 }
140 return static_cast<int>(CompatDBPage::GamePlay);
141 case CompatDBPage::GamePlay:
142 if (ui->radioButton_Gameplay_No->isChecked()) {
143 return static_cast<int>(CompatDBPage::Final);
144 }
145 return static_cast<int>(CompatDBPage::Freeze);
146 case CompatDBPage::Freeze:
147 if (ui->radioButton_NoFreeze_No->isChecked()) {
148 return static_cast<int>(CompatDBPage::Final);
149 }
150 return static_cast<int>(CompatDBPage::Completion);
151 case CompatDBPage::Completion:
152 if (ui->radioButton_Complete_No->isChecked()) {
153 return static_cast<int>(CompatDBPage::Final);
154 }
155 return static_cast<int>(CompatDBPage::Graphical);
156 case CompatDBPage::Graphical:
157 return static_cast<int>(CompatDBPage::Audio);
158 case CompatDBPage::Audio:
159 return static_cast<int>(CompatDBPage::Final);
160 case CompatDBPage::Final:
161 return -1;
162 default:
163 LOG_ERROR(Frontend, "Unexpected page: {}", currentId());
164 return static_cast<int>(CompatDBPage::Intro);
165 }
166}
167
168CompatibilityStatus CompatDB::CalculateCompatibility() const {
169 if (ui->radioButton_GameBoot_No->isChecked()) {
170 return CompatibilityStatus::WontBoot;
171 }
172
173 if (ui->radioButton_Gameplay_No->isChecked()) {
174 return CompatibilityStatus::IntroMenu;
175 }
176
177 if (ui->radioButton_NoFreeze_No->isChecked() || ui->radioButton_Complete_No->isChecked()) {
178 return CompatibilityStatus::Ingame;
179 }
180
181 if (ui->radioButton_Graphical_Major->isChecked() || ui->radioButton_Audio_Major->isChecked()) {
182 return CompatibilityStatus::Ingame;
183 }
184
185 if (ui->radioButton_Graphical_Minor->isChecked() || ui->radioButton_Audio_Minor->isChecked()) {
186 return CompatibilityStatus::Playable;
187 }
188
189 return CompatibilityStatus::Perfect;
190}
191
69void CompatDB::OnTestcaseSubmitted() { 192void CompatDB::OnTestcaseSubmitted() {
70 if (!testcase_watcher.result()) { 193 if (!testcase_watcher.result()) {
71 QMessageBox::critical(this, tr("Communication error"), 194 QMessageBox::critical(this, tr("Communication error"),
diff --git a/src/yuzu/compatdb.h b/src/yuzu/compatdb.h
index 3252fc47a..37e11278b 100644
--- a/src/yuzu/compatdb.h
+++ b/src/yuzu/compatdb.h
@@ -12,12 +12,22 @@ namespace Ui {
12class CompatDB; 12class CompatDB;
13} 13}
14 14
15enum class CompatibilityStatus {
16 Perfect = 0,
17 Playable = 1,
18 // Unused: Okay = 2,
19 Ingame = 3,
20 IntroMenu = 4,
21 WontBoot = 5,
22};
23
15class CompatDB : public QWizard { 24class CompatDB : public QWizard {
16 Q_OBJECT 25 Q_OBJECT
17 26
18public: 27public:
19 explicit CompatDB(Core::TelemetrySession& telemetry_session_, QWidget* parent = nullptr); 28 explicit CompatDB(Core::TelemetrySession& telemetry_session_, QWidget* parent = nullptr);
20 ~CompatDB(); 29 ~CompatDB();
30 int nextId() const override;
21 31
22private: 32private:
23 QFutureWatcher<bool> testcase_watcher; 33 QFutureWatcher<bool> testcase_watcher;
@@ -25,6 +35,7 @@ private:
25 std::unique_ptr<Ui::CompatDB> ui; 35 std::unique_ptr<Ui::CompatDB> ui;
26 36
27 void Submit(); 37 void Submit();
38 CompatibilityStatus CalculateCompatibility() const;
28 void OnTestcaseSubmitted(); 39 void OnTestcaseSubmitted();
29 void EnableNext(); 40 void EnableNext();
30 41
diff --git a/src/yuzu/compatdb.ui b/src/yuzu/compatdb.ui
index 3ca55eda6..d11669df2 100644
--- a/src/yuzu/compatdb.ui
+++ b/src/yuzu/compatdb.ui
@@ -58,128 +58,311 @@
58 </item> 58 </item>
59 </layout> 59 </layout>
60 </widget> 60 </widget>
61 <widget class="QWizardPage" name="wizard_Report"> 61 <widget class="QWizardPage" name="wizard_GameBoot">
62 <property name="title"> 62 <property name="title">
63 <string>Report Game Compatibility</string> 63 <string>Report Game Compatibility</string>
64 </property> 64 </property>
65 <attribute name="pageId"> 65 <attribute name="pageId">
66 <string notr="true">1</string> 66 <string notr="true">1</string>
67 </attribute> 67 </attribute>
68 <layout class="QFormLayout" name="formLayout"> 68 <layout class="QFormLayout" name="formLayout1">
69 <item row="0" column="0" colspan="2">
70 <widget class="QLabel" name="lbl_Independent1">
71 <property name="font">
72 <font>
73 <pointsize>10</pointsize>
74 </font>
75 </property>
76 <property name="text">
77 <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Does the game boot?&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
78 </property>
79 <property name="wordWrap">
80 <bool>true</bool>
81 </property>
82 </widget>
83 </item>
84 <item row="1" column="0" colspan="2">
85 <spacer name="verticalSpacer1">
86 <property name="orientation">
87 <enum>Qt::Vertical</enum>
88 </property>
89 <property name="sizeHint" stdset="0">
90 <size>
91 <width>20</width>
92 <height>0</height>
93 </size>
94 </property>
95 </spacer>
96 </item>
69 <item row="2" column="0"> 97 <item row="2" column="0">
70 <widget class="QRadioButton" name="radioButton_Perfect"> 98 <widget class="QRadioButton" name="radioButton_GameBoot_Yes">
71 <property name="text"> 99 <property name="text">
72 <string>Perfect</string> 100 <string>Yes The game starts to output video or audio</string>
73 </property> 101 </property>
74 </widget> 102 </widget>
75 </item> 103 </item>
76 <item row="2" column="1"> 104 <item row="4" column="0">
77 <widget class="QLabel" name="lbl_Perfect"> 105 <widget class="QRadioButton" name="radioButton_GameBoot_No">
78 <property name="text"> 106 <property name="text">
79 <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Game functions flawlessly with no audio or graphical glitches.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> 107 <string>No The game doesn't get past the &quot;Launching...&quot; screen</string>
80 </property> 108 </property>
81 <property name="wordWrap"> 109 </widget>
82 <bool>true</bool> 110 </item>
111 </layout>
112 </widget>
113 <widget class="QWizardPage" name="wizard_GamePlay">
114 <property name="title">
115 <string>Report Game Compatibility</string>
116 </property>
117 <attribute name="pageId">
118 <string notr="true">2</string>
119 </attribute>
120 <layout class="QFormLayout" name="formLayout2">
121 <item row="2" column="0">
122 <widget class="QRadioButton" name="radioButton_Gameplay_Yes">
123 <property name="text">
124 <string>Yes The game gets past the intro/menu and into gameplay</string>
83 </property> 125 </property>
84 </widget> 126 </widget>
85 </item> 127 </item>
86 <item row="4" column="0"> 128 <item row="4" column="0">
87 <widget class="QRadioButton" name="radioButton_Great"> 129 <widget class="QRadioButton" name="radioButton_Gameplay_No">
88 <property name="text"> 130 <property name="text">
89 <string>Great</string> 131 <string>No The game crashes or freezes while loading or using the menu</string>
90 </property> 132 </property>
91 </widget> 133 </widget>
92 </item> 134 </item>
93 <item row="4" column="1"> 135 <item row="0" column="0" colspan="2">
94 <widget class="QLabel" name="lbl_Great"> 136 <widget class="QLabel" name="lbl_Independent2">
137 <property name="font">
138 <font>
139 <pointsize>10</pointsize>
140 </font>
141 </property>
95 <property name="text"> 142 <property name="text">
96 <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Game functions with minor graphical or audio glitches and is playable from start to finish. May require some workarounds.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> 143 <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Does the game reach gameplay?&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
97 </property> 144 </property>
98 <property name="wordWrap"> 145 <property name="wordWrap">
99 <bool>true</bool> 146 <bool>true</bool>
100 </property> 147 </property>
101 </widget> 148 </widget>
102 </item> 149 </item>
103 <item row="5" column="0"> 150 <item row="1" column="0" colspan="2">
104 <widget class="QRadioButton" name="radioButton_Okay"> 151 <spacer name="verticalSpacer2">
152 <property name="orientation">
153 <enum>Qt::Vertical</enum>
154 </property>
155 <property name="sizeHint" stdset="0">
156 <size>
157 <width>20</width>
158 <height>0</height>
159 </size>
160 </property>
161 </spacer>
162 </item>
163 </layout>
164 </widget>
165 <widget class="QWizardPage" name="wizard_NoFreeze">
166 <property name="title">
167 <string>Report Game Compatibility</string>
168 </property>
169 <attribute name="pageId">
170 <string notr="true">3</string>
171 </attribute>
172 <layout class="QFormLayout" name="formLayout3">
173 <item row="2" column="0">
174 <widget class="QRadioButton" name="radioButton_NoFreeze_Yes">
105 <property name="text"> 175 <property name="text">
106 <string>Okay</string> 176 <string>Yes The game works without crashes</string>
107 </property> 177 </property>
108 </widget> 178 </widget>
109 </item> 179 </item>
110 <item row="5" column="1"> 180 <item row="4" column="0">
111 <widget class="QLabel" name="lbl_Okay"> 181 <widget class="QRadioButton" name="radioButton_NoFreeze_No">
182 <property name="text">
183 <string>No The game crashes or freezes during gameplay</string>
184 </property>
185 </widget>
186 </item>
187 <item row="0" column="0" colspan="2">
188 <widget class="QLabel" name="lbl_Independent3">
189 <property name="font">
190 <font>
191 <pointsize>10</pointsize>
192 </font>
193 </property>
112 <property name="text"> 194 <property name="text">
113 <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Game functions with major graphical or audio glitches, but game is playable from start to finish with workarounds.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> 195 <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Does the game work without crashing, freezing or locking up during gameplay?&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
114 </property> 196 </property>
115 <property name="wordWrap"> 197 <property name="wordWrap">
116 <bool>true</bool> 198 <bool>true</bool>
117 </property> 199 </property>
118 </widget> 200 </widget>
119 </item> 201 </item>
120 <item row="6" column="0"> 202 <item row="1" column="0" colspan="2">
121 <widget class="QRadioButton" name="radioButton_Bad"> 203 <spacer name="verticalSpacer3">
204 <property name="orientation">
205 <enum>Qt::Vertical</enum>
206 </property>
207 <property name="sizeHint" stdset="0">
208 <size>
209 <width>20</width>
210 <height>0</height>
211 </size>
212 </property>
213 </spacer>
214 </item>
215 </layout>
216 </widget>
217 <widget class="QWizardPage" name="wizard_Complete">
218 <property name="title">
219 <string>Report Game Compatibility</string>
220 </property>
221 <attribute name="pageId">
222 <string notr="true">4</string>
223 </attribute>
224 <layout class="QFormLayout" name="formLayout4">
225 <item row="2" column="0">
226 <widget class="QRadioButton" name="radioButton_Complete_Yes">
122 <property name="text"> 227 <property name="text">
123 <string>Bad</string> 228 <string>Yes The game can be finished without any workarounds</string>
124 </property> 229 </property>
125 </widget> 230 </widget>
126 </item> 231 </item>
127 <item row="6" column="1"> 232 <item row="4" column="0">
128 <widget class="QLabel" name="lbl_Bad"> 233 <widget class="QRadioButton" name="radioButton_Complete_No">
234 <property name="text">
235 <string>No The game can't progress past a certain area</string>
236 </property>
237 </widget>
238 </item>
239 <item row="0" column="0" colspan="2">
240 <widget class="QLabel" name="lbl_Independent4">
241 <property name="font">
242 <font>
243 <pointsize>10</pointsize>
244 </font>
245 </property>
129 <property name="text"> 246 <property name="text">
130 <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Game functions, but with major graphical or audio glitches. Unable to progress in specific areas due to glitches even with workarounds.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> 247 <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Is the game completely playable from start to finish?&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
131 </property> 248 </property>
132 <property name="wordWrap"> 249 <property name="wordWrap">
133 <bool>true</bool> 250 <bool>true</bool>
134 </property> 251 </property>
135 </widget> 252 </widget>
136 </item> 253 </item>
137 <item row="7" column="0"> 254 <item row="1" column="0" colspan="2">
138 <widget class="QRadioButton" name="radioButton_IntroMenu"> 255 <spacer name="verticalSpacer4">
256 <property name="orientation">
257 <enum>Qt::Vertical</enum>
258 </property>
259 <property name="sizeHint" stdset="0">
260 <size>
261 <width>20</width>
262 <height>0</height>
263 </size>
264 </property>
265 </spacer>
266 </item>
267 </layout>
268 </widget>
269 <widget class="QWizardPage" name="wizard_Graphical">
270 <property name="title">
271 <string>Report Game Compatibility</string>
272 </property>
273 <attribute name="pageId">
274 <string notr="true">5</string>
275 </attribute>
276 <layout class="QFormLayout" name="formLayout5">
277 <item row="2" column="0">
278 <widget class="QRadioButton" name="radioButton_Graphical_Major">
279 <property name="text">
280 <string>Major The game has major graphical errors</string>
281 </property>
282 </widget>
283 </item>
284 <item row="4" column="0">
285 <widget class="QRadioButton" name="radioButton_Graphical_Minor">
139 <property name="text"> 286 <property name="text">
140 <string>Intro/Menu</string> 287 <string>Minor The game has minor graphical errors</string>
141 </property> 288 </property>
142 </widget> 289 </widget>
143 </item> 290 </item>
144 <item row="7" column="1"> 291 <item row="6" column="0">
145 <widget class="QLabel" name="lbl_IntroMenu"> 292 <widget class="QRadioButton" name="radioButton_Graphical_No">
293 <property name="text">
294 <string>None Everything is rendered as it looks on the Nintendo Switch</string>
295 </property>
296 </widget>
297 </item>
298 <item row="0" column="0" colspan="2">
299 <widget class="QLabel" name="lbl_Independent5">
300 <property name="font">
301 <font>
302 <pointsize>10</pointsize>
303 </font>
304 </property>
146 <property name="text"> 305 <property name="text">
147 <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Game is completely unplayable due to major graphical or audio glitches. Unable to progress past the Start Screen.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> 306 <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Does the game have any graphical glitches?&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
148 </property> 307 </property>
149 <property name="wordWrap"> 308 <property name="wordWrap">
150 <bool>true</bool> 309 <bool>true</bool>
151 </property> 310 </property>
152 </widget> 311 </widget>
153 </item> 312 </item>
154 <item row="8" column="0"> 313 <item row="1" column="0" colspan="2">
155 <widget class="QRadioButton" name="radioButton_WontBoot"> 314 <spacer name="verticalSpacer5">
156 <property name="text"> 315 <property name="orientation">
157 <string>Won't Boot</string> 316 <enum>Qt::Vertical</enum>
158 </property> 317 </property>
159 <property name="checkable"> 318 <property name="sizeHint" stdset="0">
160 <bool>true</bool> 319 <size>
320 <width>20</width>
321 <height>0</height>
322 </size>
161 </property> 323 </property>
162 <property name="checked"> 324 </spacer>
163 <bool>false</bool> 325 </item>
326 </layout>
327 </widget>
328 <widget class="QWizardPage" name="wizard_Audio">
329 <property name="title">
330 <string>Report Game Compatibility</string>
331 </property>
332 <attribute name="pageId">
333 <string notr="true">6</string>
334 </attribute>
335 <layout class="QFormLayout" name="formLayout6">
336 <item row="2" column="0">
337 <widget class="QRadioButton" name="radioButton_Audio_Major">
338 <property name="text">
339 <string>Major The game has major audio errors</string>
340 </property>
341 </widget>
342 </item>
343 <item row="4" column="0">
344 <widget class="QRadioButton" name="radioButton_Audio_Minor">
345 <property name="text">
346 <string>Minor The game has minor audio errors</string>
164 </property> 347 </property>
165 </widget> 348 </widget>
166 </item> 349 </item>
167 <item row="8" column="1"> 350 <item row="6" column="0">
168 <widget class="QLabel" name="lbl_WontBoot"> 351 <widget class="QRadioButton" name="radioButton_Audio_No">
169 <property name="text"> 352 <property name="text">
170 <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The game crashes when attempting to startup.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> 353 <string>None Audio is played perfectly</string>
171 </property> 354 </property>
172 </widget> 355 </widget>
173 </item> 356 </item>
174 <item row="0" column="0" colspan="2"> 357 <item row="0" column="0" colspan="2">
175 <widget class="QLabel" name="lbl_Independent"> 358 <widget class="QLabel" name="lbl_Independent6">
176 <property name="font"> 359 <property name="font">
177 <font> 360 <font>
178 <pointsize>10</pointsize> 361 <pointsize>10</pointsize>
179 </font> 362 </font>
180 </property> 363 </property>
181 <property name="text"> 364 <property name="text">
182 <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Independent of speed or performance, how well does this game play from start to finish on this version of yuzu?&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> 365 <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Does the game have any audio glitches / missing effects?&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
183 </property> 366 </property>
184 <property name="wordWrap"> 367 <property name="wordWrap">
185 <bool>true</bool> 368 <bool>true</bool>
@@ -187,7 +370,7 @@
187 </widget> 370 </widget>
188 </item> 371 </item>
189 <item row="1" column="0" colspan="2"> 372 <item row="1" column="0" colspan="2">
190 <spacer name="verticalSpacer"> 373 <spacer name="verticalSpacer6">
191 <property name="orientation"> 374 <property name="orientation">
192 <enum>Qt::Vertical</enum> 375 <enum>Qt::Vertical</enum>
193 </property> 376 </property>
@@ -206,7 +389,7 @@
206 <string>Thank you for your submission!</string> 389 <string>Thank you for your submission!</string>
207 </property> 390 </property>
208 <attribute name="pageId"> 391 <attribute name="pageId">
209 <string notr="true">2</string> 392 <string notr="true">7</string>
210 </attribute> 393 </attribute>
211 </widget> 394 </widget>
212 </widget> 395 </widget>
diff --git a/src/yuzu/game_list_p.h b/src/yuzu/game_list_p.h
index 6198d1e4e..1800f090f 100644
--- a/src/yuzu/game_list_p.h
+++ b/src/yuzu/game_list_p.h
@@ -145,12 +145,14 @@ public:
145 const char* tooltip; 145 const char* tooltip;
146 }; 146 };
147 // clang-format off 147 // clang-format off
148 const auto ingame_status =
149 CompatStatus{QStringLiteral("#f2d624"), QT_TR_NOOP("Ingame"), QT_TR_NOOP("Game starts, but crashes or major glitches prevent it from being completed.")};
148 static const std::map<QString, CompatStatus> status_data = { 150 static const std::map<QString, CompatStatus> status_data = {
149 {QStringLiteral("0"), {QStringLiteral("#5c93ed"), QT_TR_NOOP("Perfect"), QT_TR_NOOP("Game functions flawless with no audio or graphical glitches, all tested functionality works as intended without\nany workarounds needed.")}}, 151 {QStringLiteral("0"), {QStringLiteral("#5c93ed"), QT_TR_NOOP("Perfect"), QT_TR_NOOP("Game can be played without issues.")}},
150 {QStringLiteral("1"), {QStringLiteral("#47d35c"), QT_TR_NOOP("Great"), QT_TR_NOOP("Game functions with minor graphical or audio glitches and is playable from start to finish. May require some\nworkarounds.")}}, 152 {QStringLiteral("1"), {QStringLiteral("#47d35c"), QT_TR_NOOP("Playable"), QT_TR_NOOP("Game functions with minor graphical or audio glitches and is playable from start to finish.")}},
151 {QStringLiteral("2"), {QStringLiteral("#94b242"), QT_TR_NOOP("Okay"), QT_TR_NOOP("Game functions with major graphical or audio glitches, but game is playable from start to finish with\nworkarounds.")}}, 153 {QStringLiteral("2"), ingame_status},
152 {QStringLiteral("3"), {QStringLiteral("#f2d624"), QT_TR_NOOP("Bad"), QT_TR_NOOP("Game functions, but with major graphical or audio glitches. Unable to progress in specific areas due to glitches\neven with workarounds.")}}, 154 {QStringLiteral("3"), ingame_status}, // Fallback for the removed "Okay" category
153 {QStringLiteral("4"), {QStringLiteral("#FF0000"), QT_TR_NOOP("Intro/Menu"), QT_TR_NOOP("Game is completely unplayable due to major graphical or audio glitches. Unable to progress past the Start\nScreen.")}}, 155 {QStringLiteral("4"), {QStringLiteral("#FF0000"), QT_TR_NOOP("Intro/Menu"), QT_TR_NOOP("Game loads, but is unable to progress past the Start Screen.")}},
154 {QStringLiteral("5"), {QStringLiteral("#828282"), QT_TR_NOOP("Won't Boot"), QT_TR_NOOP("The game crashes when attempting to startup.")}}, 156 {QStringLiteral("5"), {QStringLiteral("#828282"), QT_TR_NOOP("Won't Boot"), QT_TR_NOOP("The game crashes when attempting to startup.")}},
155 {QStringLiteral("99"), {QStringLiteral("#000000"), QT_TR_NOOP("Not Tested"), QT_TR_NOOP("The game has not yet been tested.")}}, 157 {QStringLiteral("99"), {QStringLiteral("#000000"), QT_TR_NOOP("Not Tested"), QT_TR_NOOP("The game has not yet been tested.")}},
156 }; 158 };
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 01a002e4f..d95915016 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -2817,6 +2817,20 @@ void GMainWindow::ErrorDisplayDisplayError(QString error_code, QString error_tex
2817} 2817}
2818 2818
2819void GMainWindow::OnMenuReportCompatibility() { 2819void GMainWindow::OnMenuReportCompatibility() {
2820 const auto& caps = Common::GetCPUCaps();
2821 const bool has_fma = caps.fma || caps.fma4;
2822 const auto processor_count = std::thread::hardware_concurrency();
2823 const bool has_4threads = processor_count == 0 || processor_count >= 4;
2824 const bool has_8gb_ram = Common::GetMemInfo().TotalPhysicalMemory >= 8_GiB;
2825 const bool has_broken_vulkan = UISettings::values.has_broken_vulkan;
2826
2827 if (!has_fma || !has_4threads || !has_8gb_ram || has_broken_vulkan) {
2828 QMessageBox::critical(this, tr("Hardware requirements not met"),
2829 tr("Your system does not meet the recommended hardware requirements. "
2830 "Compatibility reporting has been disabled."));
2831 return;
2832 }
2833
2820 if (!Settings::values.yuzu_token.GetValue().empty() && 2834 if (!Settings::values.yuzu_token.GetValue().empty() &&
2821 !Settings::values.yuzu_username.GetValue().empty()) { 2835 !Settings::values.yuzu_username.GetValue().empty()) {
2822 CompatDB compatdb{system->TelemetrySession(), this}; 2836 CompatDB compatdb{system->TelemetrySession(), this};