summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.reuse/dep510
-rw-r--r--dist/qt_themes/colorful/icons/48x48/list-add.png (renamed from dist/qt_themes/colorful/icons/48x48/plus.png)bin496 -> 496 bytes
-rw-r--r--dist/qt_themes/colorful/style.qrc2
-rw-r--r--dist/qt_themes/colorful_dark/icons/16x16/refresh.pngbin362 -> 0 bytes
-rw-r--r--dist/qt_themes/colorful_dark/icons/index.theme2
-rw-r--r--dist/qt_themes/colorful_dark/style.qrc2
-rw-r--r--dist/qt_themes/colorful_midnight_blue/icons/16x16/refresh.pngbin362 -> 0 bytes
-rw-r--r--dist/qt_themes/colorful_midnight_blue/style.qrc2
-rw-r--r--dist/qt_themes/default/default.qrc2
-rw-r--r--dist/qt_themes/default/icons/16x16/refresh.pngbin349 -> 0 bytes
-rw-r--r--dist/qt_themes/default/icons/48x48/list-add.png (renamed from dist/qt_themes/default/icons/48x48/plus.png)bin316 -> 316 bytes
-rw-r--r--dist/qt_themes/default_dark/icons/index.theme8
-rw-r--r--dist/qt_themes/default_dark/style.qrc25
-rw-r--r--dist/qt_themes/default_dark/style.qss687
-rw-r--r--dist/qt_themes/qdarkstyle/icons/16x16/refresh.pngbin362 -> 0 bytes
-rw-r--r--dist/qt_themes/qdarkstyle/icons/48x48/list-add.png (renamed from dist/qt_themes/qdarkstyle/icons/48x48/plus.png)bin339 -> 339 bytes
-rw-r--r--dist/qt_themes/qdarkstyle/style.qrc2
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/icons/16x16/lock.pngbin304 -> 0 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/icons/16x16/refresh.pngbin362 -> 0 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/icons/16x16/view-refresh.pngbin362 -> 0 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/icons/256x256/plus_folder.pngbin3438 -> 0 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/icons/48x48/bad_folder.pngbin1098 -> 0 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/icons/48x48/chip.pngbin15120 -> 0 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/icons/48x48/folder.pngbin542 -> 0 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/icons/48x48/plus.pngbin339 -> 0 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/icons/48x48/sd_card.pngbin676 -> 0 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/icons/48x48/star.pngbin725 -> 0 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/style.qrc19
-rw-r--r--src/core/CMakeLists.txt3
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_32.cpp15
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_64.cpp3
-rw-r--r--src/core/hle/service/ldn/errors.h12
-rw-r--r--src/core/hle/service/ldn/ldn.cpp436
-rw-r--r--src/core/hle/service/ldn/ldn.h6
-rw-r--r--src/core/hle/service/ldn/ldn_results.h27
-rw-r--r--src/core/hle/service/ldn/ldn_types.h284
-rw-r--r--src/yuzu/aboutdialog.ui3
-rw-r--r--src/yuzu/game_list.cpp2
-rw-r--r--src/yuzu/game_list_p.h2
-rw-r--r--src/yuzu/main.cpp82
-rw-r--r--src/yuzu/main.h5
-rw-r--r--src/yuzu/multiplayer/direct_connect.ui2
42 files changed, 1542 insertions, 101 deletions
diff --git a/.reuse/dep5 b/.reuse/dep5
index d72233e8c..5f31a4f55 100644
--- a/.reuse/dep5
+++ b/.reuse/dep5
@@ -42,20 +42,18 @@ Files: dist/qt_themes/*/icons/16x16/connected.png
42 dist/qt_themes/*/icons/48x48/sd_card.png 42 dist/qt_themes/*/icons/48x48/sd_card.png
43 dist/qt_themes/*/icons/48x48/star.png 43 dist/qt_themes/*/icons/48x48/star.png
44 dist/qt_themes/*/icons/256x256/plus_folder.png 44 dist/qt_themes/*/icons/256x256/plus_folder.png
45 dist/qt_themes/colorful/icons/48x48/plus.png 45 dist/qt_themes/colorful/icons/48x48/list-add.png
46 dist/qt_themes/default/icons/16x16/checked.png 46 dist/qt_themes/default/icons/16x16/checked.png
47 dist/qt_themes/default/icons/16x16/failed.png 47 dist/qt_themes/default/icons/16x16/failed.png
48Copyright: https://icons8.com 48Copyright: https://icons8.com
49License: CC-BY-ND-3.0 49License: CC-BY-ND-3.0
50 50
51Files: dist/qt_themes/*/icons/16x16/refresh.png 51Files: dist/qt_themes/*/icons/16x16/view-refresh.png
52 dist/qt_themes/*/icons/16x16/view-refresh.png
53Copyright: Google, Inc. 52Copyright: Google, Inc.
54License: Apache-2.0 53License: Apache-2.0
55 54
56Files: dist/qt_themes/default/icons/48x48/plus.png 55Files: dist/qt_themes/default/icons/48x48/list-add.png
57 dist/qt_themes/qdarkstyle/icons/48x48/plus.png 56 dist/qt_themes/qdarkstyle/icons/48x48/list-add.png
58 dist/qt_themes/qdarkstyle_midnight_blue/icons/48x48/plus.png
59Copyright: BreadFish64 57Copyright: BreadFish64
60License: CC0-1.0 58License: CC0-1.0
61 59
diff --git a/dist/qt_themes/colorful/icons/48x48/plus.png b/dist/qt_themes/colorful/icons/48x48/list-add.png
index bc2c47c91..bc2c47c91 100644
--- a/dist/qt_themes/colorful/icons/48x48/plus.png
+++ b/dist/qt_themes/colorful/icons/48x48/list-add.png
Binary files differ
diff --git a/dist/qt_themes/colorful/style.qrc b/dist/qt_themes/colorful/style.qrc
index 4b3f28d89..507e0e58b 100644
--- a/dist/qt_themes/colorful/style.qrc
+++ b/dist/qt_themes/colorful/style.qrc
@@ -13,7 +13,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
13 <file alias="48x48/bad_folder.png">icons/48x48/bad_folder.png</file> 13 <file alias="48x48/bad_folder.png">icons/48x48/bad_folder.png</file>
14 <file alias="48x48/chip.png">icons/48x48/chip.png</file> 14 <file alias="48x48/chip.png">icons/48x48/chip.png</file>
15 <file alias="48x48/folder.png">icons/48x48/folder.png</file> 15 <file alias="48x48/folder.png">icons/48x48/folder.png</file>
16 <file alias="48x48/plus.png">icons/48x48/plus.png</file> 16 <file alias="48x48/list-add.png">icons/48x48/list-add.png</file>
17 <file alias="48x48/sd_card.png">icons/48x48/sd_card.png</file> 17 <file alias="48x48/sd_card.png">icons/48x48/sd_card.png</file>
18 <file alias="48x48/star.png">icons/48x48/star.png</file> 18 <file alias="48x48/star.png">icons/48x48/star.png</file>
19 <file alias="256x256/plus_folder.png">icons/256x256/plus_folder.png</file> 19 <file alias="256x256/plus_folder.png">icons/256x256/plus_folder.png</file>
diff --git a/dist/qt_themes/colorful_dark/icons/16x16/refresh.png b/dist/qt_themes/colorful_dark/icons/16x16/refresh.png
deleted file mode 100644
index d4afd76f9..000000000
--- a/dist/qt_themes/colorful_dark/icons/16x16/refresh.png
+++ /dev/null
Binary files differ
diff --git a/dist/qt_themes/colorful_dark/icons/index.theme b/dist/qt_themes/colorful_dark/icons/index.theme
index 19dc0369a..b37a06df7 100644
--- a/dist/qt_themes/colorful_dark/icons/index.theme
+++ b/dist/qt_themes/colorful_dark/icons/index.theme
@@ -3,6 +3,6 @@ Name=colorful_dark
3Comment=Colorful theme (Dark style) 3Comment=Colorful theme (Dark style)
4Inherits=colorful 4Inherits=colorful
5Directories=16x16 5Directories=16x16
6 6
7[16x16] 7[16x16]
8Size=16 8Size=16
diff --git a/dist/qt_themes/colorful_dark/style.qrc b/dist/qt_themes/colorful_dark/style.qrc
index 50e78c37b..9853fd438 100644
--- a/dist/qt_themes/colorful_dark/style.qrc
+++ b/dist/qt_themes/colorful_dark/style.qrc
@@ -15,7 +15,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
15 <file alias="48x48/chip.png">../colorful/icons/48x48/chip.png</file> 15 <file alias="48x48/chip.png">../colorful/icons/48x48/chip.png</file>
16 <file alias="48x48/folder.png">../colorful/icons/48x48/folder.png</file> 16 <file alias="48x48/folder.png">../colorful/icons/48x48/folder.png</file>
17 <file alias="48x48/no_avatar.png">../qdarkstyle/icons/48x48/no_avatar.png</file> 17 <file alias="48x48/no_avatar.png">../qdarkstyle/icons/48x48/no_avatar.png</file>
18 <file alias="48x48/plus.png">../colorful/icons/48x48/plus.png</file> 18 <file alias="48x48/list-add.png">../colorful/icons/48x48/list-add.png</file>
19 <file alias="48x48/sd_card.png">../colorful/icons/48x48/sd_card.png</file> 19 <file alias="48x48/sd_card.png">../colorful/icons/48x48/sd_card.png</file>
20 <file alias="256x256/plus_folder.png">../colorful/icons/256x256/plus_folder.png</file> 20 <file alias="256x256/plus_folder.png">../colorful/icons/256x256/plus_folder.png</file>
21 </qresource> 21 </qresource>
diff --git a/dist/qt_themes/colorful_midnight_blue/icons/16x16/refresh.png b/dist/qt_themes/colorful_midnight_blue/icons/16x16/refresh.png
deleted file mode 100644
index d4afd76f9..000000000
--- a/dist/qt_themes/colorful_midnight_blue/icons/16x16/refresh.png
+++ /dev/null
Binary files differ
diff --git a/dist/qt_themes/colorful_midnight_blue/style.qrc b/dist/qt_themes/colorful_midnight_blue/style.qrc
index ac8cb0d49..1081d281d 100644
--- a/dist/qt_themes/colorful_midnight_blue/style.qrc
+++ b/dist/qt_themes/colorful_midnight_blue/style.qrc
@@ -11,7 +11,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
11 <file alias="48x48/bad_folder.png">../colorful/icons/48x48/bad_folder.png</file> 11 <file alias="48x48/bad_folder.png">../colorful/icons/48x48/bad_folder.png</file>
12 <file alias="48x48/chip.png">../colorful/icons/48x48/chip.png</file> 12 <file alias="48x48/chip.png">../colorful/icons/48x48/chip.png</file>
13 <file alias="48x48/folder.png">../colorful/icons/48x48/folder.png</file> 13 <file alias="48x48/folder.png">../colorful/icons/48x48/folder.png</file>
14 <file alias="48x48/plus.png">../colorful/icons/48x48/plus.png</file> 14 <file alias="48x48/list-add.png">../colorful/icons/48x48/list-add.png</file>
15 <file alias="48x48/sd_card.png">../colorful/icons/48x48/sd_card.png</file> 15 <file alias="48x48/sd_card.png">../colorful/icons/48x48/sd_card.png</file>
16 <file alias="256x256/plus_folder.png">../colorful/icons/256x256/plus_folder.png</file> 16 <file alias="256x256/plus_folder.png">../colorful/icons/256x256/plus_folder.png</file>
17 </qresource> 17 </qresource>
diff --git a/dist/qt_themes/default/default.qrc b/dist/qt_themes/default/default.qrc
index ef080c221..a07f2a9c1 100644
--- a/dist/qt_themes/default/default.qrc
+++ b/dist/qt_themes/default/default.qrc
@@ -17,7 +17,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
17 <file alias="48x48/chip.png">icons/48x48/chip.png</file> 17 <file alias="48x48/chip.png">icons/48x48/chip.png</file>
18 <file alias="48x48/folder.png">icons/48x48/folder.png</file> 18 <file alias="48x48/folder.png">icons/48x48/folder.png</file>
19 <file alias="48x48/no_avatar.png">icons/48x48/no_avatar.png</file> 19 <file alias="48x48/no_avatar.png">icons/48x48/no_avatar.png</file>
20 <file alias="48x48/plus.png">icons/48x48/plus.png</file> 20 <file alias="48x48/list-add.png">icons/48x48/list-add.png</file>
21 <file alias="48x48/sd_card.png">icons/48x48/sd_card.png</file> 21 <file alias="48x48/sd_card.png">icons/48x48/sd_card.png</file>
22 <file alias="48x48/star.png">icons/48x48/star.png</file> 22 <file alias="48x48/star.png">icons/48x48/star.png</file>
23 <file alias="256x256/yuzu.png">icons/256x256/yuzu.png</file> 23 <file alias="256x256/yuzu.png">icons/256x256/yuzu.png</file>
diff --git a/dist/qt_themes/default/icons/16x16/refresh.png b/dist/qt_themes/default/icons/16x16/refresh.png
deleted file mode 100644
index 69f9474ac..000000000
--- a/dist/qt_themes/default/icons/16x16/refresh.png
+++ /dev/null
Binary files differ
diff --git a/dist/qt_themes/default/icons/48x48/plus.png b/dist/qt_themes/default/icons/48x48/list-add.png
index dbc74687b..dbc74687b 100644
--- a/dist/qt_themes/default/icons/48x48/plus.png
+++ b/dist/qt_themes/default/icons/48x48/list-add.png
Binary files differ
diff --git a/dist/qt_themes/default_dark/icons/index.theme b/dist/qt_themes/default_dark/icons/index.theme
new file mode 100644
index 000000000..60a072d1d
--- /dev/null
+++ b/dist/qt_themes/default_dark/icons/index.theme
@@ -0,0 +1,8 @@
1[Icon Theme]
2Name=default_dark
3Comment=Colorful theme (Dark style)
4Inherits=colorful
5Directories=16x16
6
7[16x16]
8Size=16
diff --git a/dist/qt_themes/default_dark/style.qrc b/dist/qt_themes/default_dark/style.qrc
new file mode 100644
index 000000000..7de4737c2
--- /dev/null
+++ b/dist/qt_themes/default_dark/style.qrc
@@ -0,0 +1,25 @@
1<!--
2SPDX-FileCopyrightText: 2022 yuzu Emulator Project
3SPDX-License-Identifier: GPL-2.0-or-later
4-->
5<RCC>
6 <qresource prefix="icons/default_dark">
7 <file alias="16x16/connected.png">../colorful/icons/16x16/connected.png</file>
8 <file alias="16x16/connected_notification.png">../colorful/icons/16x16/connected_notification.png</file>
9 <file alias="16x16/disconnected.png">../colorful/icons/16x16/disconnected.png</file>
10 <file alias="index.theme">icons/index.theme</file>
11 <file alias="16x16/lock.png">../colorful_dark/icons/16x16/lock.png</file>
12 <file alias="16x16/view-refresh.png">../colorful_dark/icons/16x16/view-refresh.png</file>
13 <file alias="48x48/bad_folder.png">../colorful/icons/48x48/bad_folder.png</file>
14 <file alias="48x48/chip.png">../colorful/icons/48x48/chip.png</file>
15 <file alias="48x48/folder.png">../colorful/icons/48x48/folder.png</file>
16 <file alias="48x48/no_avatar.png">../qdarkstyle/icons/48x48/no_avatar.png</file>
17 <file alias="48x48/list-add.png">../colorful/icons/48x48/list-add.png</file>
18 <file alias="48x48/sd_card.png">../colorful/icons/48x48/sd_card.png</file>
19 <file alias="256x256/plus_folder.png">../colorful/icons/256x256/plus_folder.png</file>
20 </qresource>
21
22 <qresource prefix="default_dark">
23 <file>style.qss</file>
24 </qresource>
25</RCC>
diff --git a/dist/qt_themes/default_dark/style.qss b/dist/qt_themes/default_dark/style.qss
new file mode 100644
index 000000000..ca6daa2d5
--- /dev/null
+++ b/dist/qt_themes/default_dark/style.qss
@@ -0,0 +1,687 @@
1/*
2* SPDX-FileCopyrightText: 2018 yuzu Emulator Project
3* SPDX-License-Identifier: GPL-2.0-or-later
4*/
5QAbstractSpinBox {
6 min-height: 19px;
7}
8
9QPushButton#TogglableStatusBarButton {
10 color: #959595;
11 border: 1px solid transparent;
12 background-color: transparent;
13 padding: 0px 3px 0px 3px;
14 text-align: center;
15}
16
17QPushButton#TogglableStatusBarButton:checked {
18 color: palette(text);
19}
20
21QPushButton#TogglableStatusBarButton:hover {
22 border: 1px solid #76797C;
23}
24
25QPushButton#RendererStatusBarButton {
26 color: #656565;
27 border: 1px solid transparent;
28 background-color: transparent;
29 padding: 0px 3px 0px 3px;
30 text-align: center;
31}
32
33QPushButton#RendererStatusBarButton:hover {
34 border: 1px solid #76797C;
35}
36
37QPushButton#RendererStatusBarButton:checked {
38 color: #e85c00;
39}
40
41QPushButton#RendererStatusBarButton:!checked {
42 color: #00ccdd;
43}
44
45QPushButton#GPUStatusBarButton {
46 color: #656565;
47 border: 1px solid transparent;
48 background-color: transparent;
49 padding: 0px 3px 0px 3px;
50 text-align: center;
51}
52
53QPushButton#GPUStatusBarButton:hover {
54 border: 1px solid #76797C;
55}
56
57QPushButton#GPUStatusBarButton:checked {
58 color: #ff8040;
59}
60
61QPushButton#GPUStatusBarButton:!checked {
62 color: #40dd40;
63}
64
65QPushButton#DockingStatusBarButton {
66 min-width: 0px;
67 color: palette(text);
68 border: 1px solid transparent;
69 background-color: transparent;
70 padding: 0px 3px 0px 3px;
71 text-align: center;
72}
73
74QPushButton#DockingStatusBarButton:hover {
75 border: 1px solid #76797C;
76}
77
78QPushButton#buttonRefreshDevices {
79 min-width: 21px;
80 min-height: 21px;
81 max-width: 21px;
82 max-height: 21px;
83}
84
85QWidget#bottomPerGameInput,
86QWidget#topControllerApplet,
87QWidget#bottomControllerApplet,
88QGroupBox#groupPlayer1Connected:checked,
89QGroupBox#groupPlayer2Connected:checked,
90QGroupBox#groupPlayer3Connected:checked,
91QGroupBox#groupPlayer4Connected:checked,
92QGroupBox#groupPlayer5Connected:checked,
93QGroupBox#groupPlayer6Connected:checked,
94QGroupBox#groupPlayer7Connected:checked,
95QGroupBox#groupPlayer8Connected:checked {
96 background-color: #f5f5f5;
97}
98
99QWidget#topControllerApplet {
100 border-bottom: 1px solid #828790
101}
102
103QWidget#bottomPerGameInput,
104QWidget#bottomControllerApplet {
105 border-top: 1px solid #828790
106}
107
108QWidget#topPerGameInput,
109QWidget#middleControllerApplet {
110 background-color: #fff;
111}
112
113QWidget#topPerGameInput QComboBox,
114QWidget#middleControllerApplet QComboBox {
115 width: 120px;
116}
117
118QWidget#connectedControllers {
119 background: transparent;
120}
121
122QWidget#playersSupported,
123QWidget#controllersSupported,
124QWidget#controllerSupported1,
125QWidget#controllerSupported2,
126QWidget#controllerSupported3,
127QWidget#controllerSupported4,
128QWidget#controllerSupported5,
129QWidget#controllerSupported6 {
130 border: none;
131 background: transparent;
132}
133
134QGroupBox#groupPlayer1Connected,
135QGroupBox#groupPlayer2Connected,
136QGroupBox#groupPlayer3Connected,
137QGroupBox#groupPlayer4Connected,
138QGroupBox#groupPlayer5Connected,
139QGroupBox#groupPlayer6Connected,
140QGroupBox#groupPlayer7Connected,
141QGroupBox#groupPlayer8Connected {
142 border: 1px solid #828790;
143 border-radius: 3px;
144 padding: 0px;
145 min-height: 98px;
146 max-height: 98px;
147}
148
149QGroupBox#groupPlayer1Connected:unchecked,
150QGroupBox#groupPlayer2Connected:unchecked,
151QGroupBox#groupPlayer3Connected:unchecked,
152QGroupBox#groupPlayer4Connected:unchecked,
153QGroupBox#groupPlayer5Connected:unchecked,
154QGroupBox#groupPlayer6Connected:unchecked,
155QGroupBox#groupPlayer7Connected:unchecked,
156QGroupBox#groupPlayer8Connected:unchecked {
157 border: 1px solid #d9d9d9;
158}
159
160QGroupBox#groupPlayer1Connected::title,
161QGroupBox#groupPlayer2Connected::title,
162QGroupBox#groupPlayer3Connected::title,
163QGroupBox#groupPlayer4Connected::title,
164QGroupBox#groupPlayer5Connected::title,
165QGroupBox#groupPlayer6Connected::title,
166QGroupBox#groupPlayer7Connected::title,
167QGroupBox#groupPlayer8Connected::title {
168 subcontrol-origin: margin;
169 subcontrol-position: top left;
170 padding-left: 0px;
171 padding-right: 0px;
172 padding-top: 1px;
173 margin-left: 0px;
174 margin-right: -4px;
175 margin-bottom: 4px;
176}
177
178QCheckBox#checkboxPlayer1Connected,
179QCheckBox#checkboxPlayer2Connected,
180QCheckBox#checkboxPlayer3Connected,
181QCheckBox#checkboxPlayer4Connected,
182QCheckBox#checkboxPlayer5Connected,
183QCheckBox#checkboxPlayer6Connected,
184QCheckBox#checkboxPlayer7Connected,
185QCheckBox#checkboxPlayer8Connected {
186 spacing: 0px;
187}
188
189QWidget#Player1LEDs QCheckBox,
190QWidget#Player2LEDs QCheckBox,
191QWidget#Player3LEDs QCheckBox,
192QWidget#Player4LEDs QCheckBox,
193QWidget#Player5LEDs QCheckBox,
194QWidget#Player6LEDs QCheckBox,
195QWidget#Player7LEDs QCheckBox,
196QWidget#Player8LEDs QCheckBox {
197 spacing: 0px;
198}
199
200QWidget#Player1LEDs QCheckBox::indicator,
201QWidget#Player2LEDs QCheckBox::indicator,
202QWidget#Player3LEDs QCheckBox::indicator,
203QWidget#Player4LEDs QCheckBox::indicator,
204QWidget#Player5LEDs QCheckBox::indicator,
205QWidget#Player6LEDs QCheckBox::indicator,
206QWidget#Player7LEDs QCheckBox::indicator,
207QWidget#Player8LEDs QCheckBox::indicator {
208 width: 6px;
209 height: 6px;
210 margin-left: 0px;
211}
212
213QWidget#bottomPerGameInput QCheckBox#checkboxPlayer1Connected::indicator,
214QWidget#bottomPerGameInput QCheckBox#checkboxPlayer2Connected::indicator,
215QWidget#bottomPerGameInput QCheckBox#checkboxPlayer3Connected::indicator,
216QWidget#bottomPerGameInput QCheckBox#checkboxPlayer4Connected::indicator,
217QWidget#bottomPerGameInput QCheckBox#checkboxPlayer5Connected::indicator,
218QWidget#bottomPerGameInput QCheckBox#checkboxPlayer6Connected::indicator,
219QWidget#bottomPerGameInput QCheckBox#checkboxPlayer7Connected::indicator,
220QWidget#bottomPerGameInput QCheckBox#checkboxPlayer8Connected::indicator {
221 width: 12px;
222 height: 12px;
223}
224
225QCheckBox#checkboxPlayer1Connected::indicator,
226QCheckBox#checkboxPlayer2Connected::indicator,
227QCheckBox#checkboxPlayer3Connected::indicator,
228QCheckBox#checkboxPlayer4Connected::indicator,
229QCheckBox#checkboxPlayer5Connected::indicator,
230QCheckBox#checkboxPlayer6Connected::indicator,
231QCheckBox#checkboxPlayer7Connected::indicator,
232QCheckBox#checkboxPlayer8Connected::indicator {
233 width: 14px;
234 height: 14px;
235}
236
237QGroupBox#groupPlayer1Connected::indicator,
238QGroupBox#groupPlayer2Connected::indicator,
239QGroupBox#groupPlayer3Connected::indicator,
240QGroupBox#groupPlayer4Connected::indicator,
241QGroupBox#groupPlayer5Connected::indicator,
242QGroupBox#groupPlayer6Connected::indicator,
243QGroupBox#groupPlayer7Connected::indicator,
244QGroupBox#groupPlayer8Connected::indicator {
245 width: 16px;
246 height: 16px;
247}
248
249QWidget#Player1LEDs QCheckBox::indicator:checked,
250QWidget#Player2LEDs QCheckBox::indicator:checked,
251QWidget#Player3LEDs QCheckBox::indicator:checked,
252QWidget#Player4LEDs QCheckBox::indicator:checked,
253QWidget#Player5LEDs QCheckBox::indicator:checked,
254QWidget#Player6LEDs QCheckBox::indicator:checked,
255QWidget#Player7LEDs QCheckBox::indicator:checked,
256QWidget#Player8LEDs QCheckBox::indicator:checked,
257QGroupBox#groupPlayer1Connected::indicator:checked,
258QGroupBox#groupPlayer2Connected::indicator:checked,
259QGroupBox#groupPlayer3Connected::indicator:checked,
260QGroupBox#groupPlayer4Connected::indicator:checked,
261QGroupBox#groupPlayer5Connected::indicator:checked,
262QGroupBox#groupPlayer6Connected::indicator:checked,
263QGroupBox#groupPlayer7Connected::indicator:checked,
264QGroupBox#groupPlayer8Connected::indicator:checked,
265QCheckBox#checkboxPlayer1Connected::indicator:checked,
266QCheckBox#checkboxPlayer2Connected::indicator:checked,
267QCheckBox#checkboxPlayer3Connected::indicator:checked,
268QCheckBox#checkboxPlayer4Connected::indicator:checked,
269QCheckBox#checkboxPlayer5Connected::indicator:checked,
270QCheckBox#checkboxPlayer6Connected::indicator:checked,
271QCheckBox#checkboxPlayer7Connected::indicator:checked,
272QCheckBox#checkboxPlayer8Connected::indicator:checked,
273QGroupBox#groupConnectedController::indicator:checked {
274 border-radius: 2px;
275 border: 1px solid #929192;
276 background: #39ff14;
277 image: none;
278}
279
280QWidget#Player1LEDs QCheckBox::indicator:unchecked,
281QWidget#Player2LEDs QCheckBox::indicator:unchecked,
282QWidget#Player3LEDs QCheckBox::indicator:unchecked,
283QWidget#Player4LEDs QCheckBox::indicator:unchecked,
284QWidget#Player5LEDs QCheckBox::indicator:unchecked,
285QWidget#Player6LEDs QCheckBox::indicator:unchecked,
286QWidget#Player7LEDs QCheckBox::indicator:unchecked,
287QWidget#Player8LEDs QCheckBox::indicator:unchecked,
288QGroupBox#groupPlayer1Connected::indicator:unchecked,
289QGroupBox#groupPlayer2Connected::indicator:unchecked,
290QGroupBox#groupPlayer3Connected::indicator:unchecked,
291QGroupBox#groupPlayer4Connected::indicator:unchecked,
292QGroupBox#groupPlayer5Connected::indicator:unchecked,
293QGroupBox#groupPlayer6Connected::indicator:unchecked,
294QGroupBox#groupPlayer7Connected::indicator:unchecked,
295QGroupBox#groupPlayer8Connected::indicator:unchecked,
296QCheckBox#checkboxPlayer1Connected::indicator:unchecked,
297QCheckBox#checkboxPlayer2Connected::indicator:unchecked,
298QCheckBox#checkboxPlayer3Connected::indicator:unchecked,
299QCheckBox#checkboxPlayer4Connected::indicator:unchecked,
300QCheckBox#checkboxPlayer5Connected::indicator:unchecked,
301QCheckBox#checkboxPlayer6Connected::indicator:unchecked,
302QCheckBox#checkboxPlayer7Connected::indicator:unchecked,
303QCheckBox#checkboxPlayer8Connected::indicator:unchecked,
304QGroupBox#groupConnectedController::indicator:unchecked {
305 border-radius: 2px;
306 border: 1px solid #929192;
307 background: transparent;
308 image: none;
309}
310
311QWidget#controllerPlayer1,
312QWidget#controllerPlayer2,
313QWidget#controllerPlayer3,
314QWidget#controllerPlayer4,
315QWidget#controllerPlayer5,
316QWidget#controllerPlayer6,
317QWidget#controllerPlayer7,
318QWidget#controllerPlayer8 {
319 background: transparent;
320}
321
322QDialog#QtSoftwareKeyboardDialog,
323QStackedWidget#topOSK {
324 background: rgba(51, 51, 51, .9);
325}
326
327
328QDialog#OverlayDialog,
329QStackedWidget#stackedDialog {
330 background: rgba(51, 51, 51, .7);
331}
332
333QWidget#boxOSK,
334QWidget#lineOSK,
335QWidget#richDialog,
336QWidget#lineDialog {
337 background: transparent;
338}
339
340QStackedWidget#bottomOSK,
341QWidget#contentDialog,
342QWidget#contentRichDialog {
343 background: rgba(240, 240, 240, 1);
344}
345
346QWidget#contentDialog,
347QWidget#contentRichDialog {
348 margin: 5px;
349 border-radius: 6px;
350}
351
352QWidget#buttonsDialog,
353QWidget#buttonsRichDialog {
354 margin: 5px;
355 border-top: 2px solid rgba(44, 44, 44, 1);
356}
357
358QWidget#legendOSKnum {
359 border-top: 1px solid rgba(44, 44, 44, 1);
360}
361
362QStackedWidget#stackedDialog QTextBrowser QScrollBar::vertical {
363 background: #cdcdcd;
364 width: 15px;
365 margin: 15px 3px 15px 3px;
366 border: 1px transparent;
367 border-radius: 4px;
368}
369
370QStackedWidget#stackedDialog QTextBrowser QScrollBar::horizoncal {
371 background: #cdcdcd;
372 height: 15px;
373 margin: 3px 15px 3px 15px;
374 border: 1px transparent;
375 border-radius: 4px;
376}
377
378QStackedWidget#stackedDialog QTextBrowser QScrollBar::handle {
379 background: #fff;
380 border-radius: 4px;
381 min-height: 5px;
382 min-width: 5px;
383}
384
385QStackedWidget#stackedDialog QTextBrowser QScrollBar::add-line,
386QStackedWidget#stackedDialog QTextBrowser QScrollBar::sub-line,
387QStackedWidget#stackedDialog QTextBrowser QScrollBar::add-page,
388QStackedWidget#stackedDialog QTextBrowser QScrollBar::sub-page {
389 background: none;
390}
391
392QWidget#inputOSK {
393 border-bottom: 3px solid rgba(255, 255, 255, .9);
394}
395
396QWidget#inputOSK QLineEdit {
397 background: transparent;
398 border: none;
399 color: #ccc;
400}
401
402QWidget#inputBoxOSK {
403 border: 2px solid rgba(255, 255, 255, .9);
404}
405
406QWidget#inputBoxOSK QTextEdit {
407 background: transparent;
408 border: none;
409 color: #ccc;
410}
411
412QWidget#richDialog QTextBrowser {
413 background: transparent;
414 border: none;
415 padding: 35px 65px;
416}
417
418
419QWidget#lineOSK QLabel#label_header {
420 color: #f0f0f0;
421}
422
423QWidget#lineOSK QLabel#label_sub,
424QWidget#lineOSK QLabel#label_characters,
425QWidget#boxOSK QLabel#label_characters_box {
426 color: #ccc;
427}
428
429QWidget#contentDialog QLabel#label_title,
430QWidget#contentRichDialog QLabel#label_title_rich {
431 color: #888;
432}
433
434QWidget#contentDialog QLabel#label_dialog {
435 padding: 20px 65px;
436}
437
438QWidget#contentDialog QLabel#label_title,
439QWidget#contentRichDialog QLabel#label_title_rich {
440 padding: 0px 65px;
441}
442
443QDialog#OverlayDialog QPushButton {
444 color: rgba(49, 79, 239, 1);
445 background: transparent;
446 border: none;
447 padding: 0px;
448 min-width: 0px;
449}
450
451QDialog#OverlayDialog QPushButton:focus,
452QDialog#OverlayDialog QPushButton:hover {
453 color: rgba(49, 79, 239, 1);
454 background: rgba(255, 255, 255, 1);
455 border: 5px solid rgba(148, 250, 202, 1);
456 border-radius: 6px;
457 outline: none;
458}
459
460QDialog#OverlayDialog QPushButton:pressed {
461 color: rgba(240, 240, 240, 1);
462 background: rgba(150, 150, 150, 1);
463 border: 5px solid rgba(148, 250, 202, 1);
464 border-radius: 6px;
465 outline: none;
466}
467
468QDialog#QtSoftwareKeyboardDialog QPushButton {
469 background: rgba(232, 232, 232, 1);
470 border: 2px solid rgba(240, 240, 240, 1);
471}
472
473QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift,
474QDialog#QtSoftwareKeyboardDialog QPushButton#button_return,
475QDialog#QtSoftwareKeyboardDialog QPushButton#button_space,
476QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift,
477QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift,
478QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift {
479 background: rgba(218, 218, 218, 1);
480 border: 2px solid rgba(240, 240, 240, 1);
481}
482
483QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace,
484QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift,
485QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num {
486 color: rgba(240, 240, 240, 1);
487 background: rgba(44, 44, 44, 1);
488 border: 2px solid rgba(240, 240, 240, 1);
489}
490
491QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok,
492QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift,
493QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num {
494 color: rgba(240, 240, 240, 1);
495 background: rgba(49, 79, 239, 1);
496 border: 2px solid rgba(240, 240, 240, 1);
497}
498
499QDialog#QtSoftwareKeyboardDialog QPushButton:focus,
500QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:focus,
501QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift:focus,
502QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:focus,
503QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:focus,
504QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:focus,
505QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:focus,
506QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift:focus,
507QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:focus,
508QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:focus,
509QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:focus,
510QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:focus,
511QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:focus,
512
513QDialog#QtSoftwareKeyboardDialog QPushButton:hover,
514QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:hover,
515QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift:hover,
516QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:hover,
517QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:hover,
518QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:hover,
519QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:hover,
520QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift:hover,
521QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:hover,
522QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:hover,
523QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:hover,
524QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:hover,
525QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:hover {
526 color: rgba(0, 0, 0, 1);
527 background: rgba(255, 255, 255, 1);
528 border: 5px solid rgba(148, 250, 202, 1);
529 border-radius: 6px;
530 outline: none;
531}
532
533QDialog#QtSoftwareKeyboardDialog QPushButton:pressed,
534QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:pressed,
535QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift:pressed,
536QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:pressed,
537QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:pressed,
538QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:pressed,
539QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:pressed,
540QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift:pressed,
541QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:pressed,
542QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:pressed,
543QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:pressed,
544QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:pressed,
545QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:pressed {
546 color: rgba(240, 240, 240, 1);
547 background: rgba(150, 150, 150, 1);
548 border: 5px solid rgba(148, 250, 202, 1);
549 border-radius: 6px;
550}
551
552QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace,
553QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift,
554QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num {
555 image: url(:/overlay/osk_button_B.png);
556 image-position: right;
557 qproperty-icon: url(:/overlay/osk_button_backspace.png);
558 qproperty-iconSize: 36px;
559}
560
561QDialog#QtSoftwareKeyboardDialog QPushButton#button_space,
562QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift {
563 image: url(:/overlay/osk_button_Y.png);
564 image-position: right;
565}
566
567QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok,
568QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift,
569QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num {
570 image: url(:/overlay/osk_button_plus.png);
571 image-position: right;
572}
573
574QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift {
575 image: url(:/overlay/osk_button_shift_lock_off.png);
576 image-position: left;
577 qproperty-icon: url(:/overlay/osk_button_shift.png);
578 qproperty-iconSize: 36px;
579}
580
581QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift {
582 image: url(:/overlay/osk_button_shift_lock_off.png);
583 image-position: left;
584 qproperty-icon: url(:/overlay/osk_button_shift_on.png);
585 qproperty-iconSize: 36px;
586}
587
588QDialog#QtSoftwareKeyboardDialog QPushButton#button_left_bracket,
589QDialog#QtSoftwareKeyboardDialog QPushButton#button_right_bracket,
590QDialog#QtSoftwareKeyboardDialog QPushButton#button_left_parenthesis,
591QDialog#QtSoftwareKeyboardDialog QPushButton#button_right_parenthesis {
592 padding-bottom: 7px;
593}
594
595QDialog#QtSoftwareKeyboardDialog QWidget#titleOSK QLabel {
596 background: transparent;
597 color: #ccc;
598}
599
600QDialog#QtSoftwareKeyboardDialog QWidget#button_L,
601QDialog#QtSoftwareKeyboardDialog QWidget#button_L_shift,
602QDialog#QtSoftwareKeyboardDialog QWidget#button_L_num {
603 image: url(:/overlay/button_L.png);
604}
605
606QDialog#QtSoftwareKeyboardDialog QWidget#arrow_left,
607QDialog#QtSoftwareKeyboardDialog QWidget#arrow_left_shift,
608QDialog#QtSoftwareKeyboardDialog QWidget#arrow_left_num {
609 image: url(:/overlay/arrow_left.png);
610}
611
612QDialog#QtSoftwareKeyboardDialog QWidget#button_R,
613QDialog#QtSoftwareKeyboardDialog QWidget#button_R_shift,
614QDialog#QtSoftwareKeyboardDialog QWidget#button_R_num {
615 image: url(:/overlay/button_R.png);
616}
617
618QDialog#QtSoftwareKeyboardDialog QWidget#arrow_right,
619QDialog#QtSoftwareKeyboardDialog QWidget#arrow_right_shift,
620QDialog#QtSoftwareKeyboardDialog QWidget#arrow_right_num {
621 image: url(:/overlay/arrow_right.png);
622}
623
624QDialog#QtSoftwareKeyboardDialog QWidget#button_press_stick,
625QDialog#QtSoftwareKeyboardDialog QWidget#button_press_stick_shift {
626 image: url(:/overlay/button_press_stick.png);
627}
628
629QDialog#QtSoftwareKeyboardDialog QWidget#button_X,
630QDialog#QtSoftwareKeyboardDialog QWidget#button_X_shift,
631QDialog#QtSoftwareKeyboardDialog QWidget#button_X_num {
632 image: url(:/overlay/button_X.png);
633}
634
635QDialog#QtSoftwareKeyboardDialog QWidget#button_A,
636QDialog#QtSoftwareKeyboardDialog QWidget#button_A_shift,
637QDialog#QtSoftwareKeyboardDialog QWidget#button_A_num {
638 image: url(:/overlay/button_A.png);
639}
640
641QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:disabled,
642QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:disabled,
643QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:disabled,
644QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:disabled,
645QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:disabled,
646QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:disabled,
647QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:disabled,
648QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:disabled,
649QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:disabled,
650QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:disabled {
651 color: rgba(164, 164, 164, 1);
652 background-color: rgba(218, 218, 218, 1);
653}
654
655QDialog#QtSoftwareKeyboardDialog QPushButton#button_at:disabled,
656QDialog#QtSoftwareKeyboardDialog QPushButton#button_slash:disabled,
657QDialog#QtSoftwareKeyboardDialog QPushButton#button_percent:disabled,
658QDialog#QtSoftwareKeyboardDialog QPushButton#button_1:disabled,
659QDialog#QtSoftwareKeyboardDialog QPushButton#button_2:disabled,
660QDialog#QtSoftwareKeyboardDialog QPushButton#button_3:disabled,
661QDialog#QtSoftwareKeyboardDialog QPushButton#button_4:disabled,
662QDialog#QtSoftwareKeyboardDialog QPushButton#button_5:disabled,
663QDialog#QtSoftwareKeyboardDialog QPushButton#button_6:disabled,
664QDialog#QtSoftwareKeyboardDialog QPushButton#button_7:disabled,
665QDialog#QtSoftwareKeyboardDialog QPushButton#button_8:disabled,
666QDialog#QtSoftwareKeyboardDialog QPushButton#button_9:disabled,
667QDialog#QtSoftwareKeyboardDialog QPushButton#button_0:disabled,
668QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:disabled {
669 color: rgba(164, 164, 164, 1);
670}
671
672QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:disabled,
673QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:disabled,
674QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:disabled {
675 image: url(:/overlay/osk_button_plus_disabled.png);
676}
677
678QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:disabled,
679QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:disabled,
680QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:disabled {
681 image: url(:/overlay/osk_button_B_disabled.png);
682}
683
684QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:disabled,
685QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:disabled {
686 image: url(:/overlay/osk_button_Y_disabled.png);
687}
diff --git a/dist/qt_themes/qdarkstyle/icons/16x16/refresh.png b/dist/qt_themes/qdarkstyle/icons/16x16/refresh.png
deleted file mode 100644
index d4afd76f9..000000000
--- a/dist/qt_themes/qdarkstyle/icons/16x16/refresh.png
+++ /dev/null
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle/icons/48x48/plus.png b/dist/qt_themes/qdarkstyle/icons/48x48/list-add.png
index 16cc8b4f4..16cc8b4f4 100644
--- a/dist/qt_themes/qdarkstyle/icons/48x48/plus.png
+++ b/dist/qt_themes/qdarkstyle/icons/48x48/list-add.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle/style.qrc b/dist/qt_themes/qdarkstyle/style.qrc
index f770e09fd..a89fb26c6 100644
--- a/dist/qt_themes/qdarkstyle/style.qrc
+++ b/dist/qt_themes/qdarkstyle/style.qrc
@@ -10,7 +10,7 @@
10 <file alias="48x48/chip.png">icons/48x48/chip.png</file> 10 <file alias="48x48/chip.png">icons/48x48/chip.png</file>
11 <file alias="48x48/folder.png">icons/48x48/folder.png</file> 11 <file alias="48x48/folder.png">icons/48x48/folder.png</file>
12 <file alias="48x48/no_avatar.png">icons/48x48/no_avatar.png</file> 12 <file alias="48x48/no_avatar.png">icons/48x48/no_avatar.png</file>
13 <file alias="48x48/plus.png">icons/48x48/plus.png</file> 13 <file alias="48x48/list-add.png">icons/48x48/list-add.png</file>
14 <file alias="48x48/sd_card.png">icons/48x48/sd_card.png</file> 14 <file alias="48x48/sd_card.png">icons/48x48/sd_card.png</file>
15 <file alias="48x48/star.png">icons/48x48/star.png</file> 15 <file alias="48x48/star.png">icons/48x48/star.png</file>
16 <file alias="256x256/plus_folder.png">icons/256x256/plus_folder.png</file> 16 <file alias="256x256/plus_folder.png">icons/256x256/plus_folder.png</file>
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/icons/16x16/lock.png b/dist/qt_themes/qdarkstyle_midnight_blue/icons/16x16/lock.png
deleted file mode 100644
index c750a39e8..000000000
--- a/dist/qt_themes/qdarkstyle_midnight_blue/icons/16x16/lock.png
+++ /dev/null
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/icons/16x16/refresh.png b/dist/qt_themes/qdarkstyle_midnight_blue/icons/16x16/refresh.png
deleted file mode 100644
index d4afd76f9..000000000
--- a/dist/qt_themes/qdarkstyle_midnight_blue/icons/16x16/refresh.png
+++ /dev/null
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/icons/16x16/view-refresh.png b/dist/qt_themes/qdarkstyle_midnight_blue/icons/16x16/view-refresh.png
deleted file mode 100644
index d4afd76f9..000000000
--- a/dist/qt_themes/qdarkstyle_midnight_blue/icons/16x16/view-refresh.png
+++ /dev/null
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/icons/256x256/plus_folder.png b/dist/qt_themes/qdarkstyle_midnight_blue/icons/256x256/plus_folder.png
deleted file mode 100644
index 303f9a321..000000000
--- a/dist/qt_themes/qdarkstyle_midnight_blue/icons/256x256/plus_folder.png
+++ /dev/null
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/icons/48x48/bad_folder.png b/dist/qt_themes/qdarkstyle_midnight_blue/icons/48x48/bad_folder.png
deleted file mode 100644
index 4a9709623..000000000
--- a/dist/qt_themes/qdarkstyle_midnight_blue/icons/48x48/bad_folder.png
+++ /dev/null
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/icons/48x48/chip.png b/dist/qt_themes/qdarkstyle_midnight_blue/icons/48x48/chip.png
deleted file mode 100644
index 973fabd05..000000000
--- a/dist/qt_themes/qdarkstyle_midnight_blue/icons/48x48/chip.png
+++ /dev/null
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/icons/48x48/folder.png b/dist/qt_themes/qdarkstyle_midnight_blue/icons/48x48/folder.png
deleted file mode 100644
index 0f1e987d6..000000000
--- a/dist/qt_themes/qdarkstyle_midnight_blue/icons/48x48/folder.png
+++ /dev/null
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/icons/48x48/plus.png b/dist/qt_themes/qdarkstyle_midnight_blue/icons/48x48/plus.png
deleted file mode 100644
index 16cc8b4f4..000000000
--- a/dist/qt_themes/qdarkstyle_midnight_blue/icons/48x48/plus.png
+++ /dev/null
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/icons/48x48/sd_card.png b/dist/qt_themes/qdarkstyle_midnight_blue/icons/48x48/sd_card.png
deleted file mode 100644
index 0291c6542..000000000
--- a/dist/qt_themes/qdarkstyle_midnight_blue/icons/48x48/sd_card.png
+++ /dev/null
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/icons/48x48/star.png b/dist/qt_themes/qdarkstyle_midnight_blue/icons/48x48/star.png
deleted file mode 100644
index 90d423a1d..000000000
--- a/dist/qt_themes/qdarkstyle_midnight_blue/icons/48x48/star.png
+++ /dev/null
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/style.qrc b/dist/qt_themes/qdarkstyle_midnight_blue/style.qrc
index 142dd3288..dc3d7fecb 100644
--- a/dist/qt_themes/qdarkstyle_midnight_blue/style.qrc
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/style.qrc
@@ -1,15 +1,16 @@
1<RCC> 1<RCC>
2 <qresource prefix="icons/qdarkstyle_midnight_blue"> 2 <qresource prefix="icons/qdarkstyle_midnight_blue">
3 <file alias="index.theme">icons/index.theme</file> 3 <file alias="index.theme">icons/index.theme</file>
4 <file alias="16x16/lock.png">icons/16x16/lock.png</file> 4 <file alias="16x16/lock.png">../qdarkstyle/icons/16x16/lock.png</file>
5 <file alias="16x16/view-refresh.png">icons/16x16/view-refresh.png</file> 5 <file alias="16x16/view-refresh.png">../qdarkstyle/icons/16x16/view-refresh.png</file>
6 <file alias="48x48/bad_folder.png">icons/48x48/bad_folder.png</file> 6 <file alias="48x48/bad_folder.png">../qdarkstyle/icons/48x48/bad_folder.png</file>
7 <file alias="48x48/chip.png">icons/48x48/chip.png</file> 7 <file alias="48x48/chip.png">../qdarkstyle/icons/48x48/chip.png</file>
8 <file alias="48x48/folder.png">icons/48x48/folder.png</file> 8 <file alias="48x48/folder.png">../qdarkstyle/icons/48x48/folder.png</file>
9 <file alias="48x48/plus.png">icons/48x48/plus.png</file> 9 <file alias="48x48/no_avatar.png">../qdarkstyle/icons/48x48/no_avatar.png</file>
10 <file alias="48x48/sd_card.png">icons/48x48/sd_card.png</file> 10 <file alias="48x48/list-add.png">../qdarkstyle/icons/48x48/list-add.png</file>
11 <file alias="48x48/star.png">icons/48x48/star.png</file> 11 <file alias="48x48/sd_card.png">../qdarkstyle/icons/48x48/sd_card.png</file>
12 <file alias="256x256/plus_folder.png">icons/256x256/plus_folder.png</file> 12 <file alias="48x48/star.png">../qdarkstyle/icons/48x48/star.png</file>
13 <file alias="256x256/plus_folder.png">../qdarkstyle/icons/256x256/plus_folder.png</file>
13 </qresource> 14 </qresource>
14 <qresource prefix="qss_icons"> 15 <qresource prefix="qss_icons">
15 <file>rc/arrow_down.png</file> 16 <file>rc/arrow_down.png</file>
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 052357be4..4e39649a8 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -502,9 +502,10 @@ add_library(core STATIC
502 hle/service/jit/jit.h 502 hle/service/jit/jit.h
503 hle/service/lbl/lbl.cpp 503 hle/service/lbl/lbl.cpp
504 hle/service/lbl/lbl.h 504 hle/service/lbl/lbl.h
505 hle/service/ldn/errors.h 505 hle/service/ldn/ldn_results.h
506 hle/service/ldn/ldn.cpp 506 hle/service/ldn/ldn.cpp
507 hle/service/ldn/ldn.h 507 hle/service/ldn/ldn.h
508 hle/service/ldn/ldn_types.h
508 hle/service/ldr/ldr.cpp 509 hle/service/ldr/ldr.cpp
509 hle/service/ldr/ldr.h 510 hle/service/ldr/ldr.h
510 hle/service/lm/lm.cpp 511 hle/service/lm/lm.cpp
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
index 1638bc41d..3b8b43994 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
@@ -195,14 +195,16 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable*
195 if (page_table) { 195 if (page_table) {
196 config.page_table = reinterpret_cast<std::array<std::uint8_t*, NUM_PAGE_TABLE_ENTRIES>*>( 196 config.page_table = reinterpret_cast<std::array<std::uint8_t*, NUM_PAGE_TABLE_ENTRIES>*>(
197 page_table->pointers.data()); 197 page_table->pointers.data());
198 config.absolute_offset_page_table = true;
199 config.page_table_pointer_mask_bits = Common::PageTable::ATTRIBUTE_BITS;
200 config.detect_misaligned_access_via_page_table = 16 | 32 | 64 | 128;
201 config.only_detect_misalignment_via_page_table_on_page_boundary = true;
202
198 config.fastmem_pointer = page_table->fastmem_arena; 203 config.fastmem_pointer = page_table->fastmem_arena;
204
205 config.fastmem_exclusive_access = config.fastmem_pointer != nullptr;
206 config.recompile_on_exclusive_fastmem_failure = true;
199 } 207 }
200 config.absolute_offset_page_table = true;
201 config.page_table_pointer_mask_bits = Common::PageTable::ATTRIBUTE_BITS;
202 config.detect_misaligned_access_via_page_table = 16 | 32 | 64 | 128;
203 config.only_detect_misalignment_via_page_table_on_page_boundary = true;
204 config.fastmem_exclusive_access = true;
205 config.recompile_on_exclusive_fastmem_failure = true;
206 208
207 // Multi-process state 209 // Multi-process state
208 config.processor_id = core_index; 210 config.processor_id = core_index;
@@ -254,6 +256,7 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable*
254 } 256 }
255 if (!Settings::values.cpuopt_fastmem) { 257 if (!Settings::values.cpuopt_fastmem) {
256 config.fastmem_pointer = nullptr; 258 config.fastmem_pointer = nullptr;
259 config.fastmem_exclusive_access = false;
257 } 260 }
258 if (!Settings::values.cpuopt_fastmem_exclusives) { 261 if (!Settings::values.cpuopt_fastmem_exclusives) {
259 config.fastmem_exclusive_access = false; 262 config.fastmem_exclusive_access = false;
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
index 921a5a734..1d46f6d40 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
@@ -250,7 +250,7 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable*
250 config.fastmem_address_space_bits = address_space_bits; 250 config.fastmem_address_space_bits = address_space_bits;
251 config.silently_mirror_fastmem = false; 251 config.silently_mirror_fastmem = false;
252 252
253 config.fastmem_exclusive_access = true; 253 config.fastmem_exclusive_access = config.fastmem_pointer != nullptr;
254 config.recompile_on_exclusive_fastmem_failure = true; 254 config.recompile_on_exclusive_fastmem_failure = true;
255 } 255 }
256 256
@@ -314,6 +314,7 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable*
314 } 314 }
315 if (!Settings::values.cpuopt_fastmem) { 315 if (!Settings::values.cpuopt_fastmem) {
316 config.fastmem_pointer = nullptr; 316 config.fastmem_pointer = nullptr;
317 config.fastmem_exclusive_access = false;
317 } 318 }
318 if (!Settings::values.cpuopt_fastmem_exclusives) { 319 if (!Settings::values.cpuopt_fastmem_exclusives) {
319 config.fastmem_exclusive_access = false; 320 config.fastmem_exclusive_access = false;
diff --git a/src/core/hle/service/ldn/errors.h b/src/core/hle/service/ldn/errors.h
deleted file mode 100644
index 972a74806..000000000
--- a/src/core/hle/service/ldn/errors.h
+++ /dev/null
@@ -1,12 +0,0 @@
1// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/result.h"
7
8namespace Service::LDN {
9
10constexpr Result ERROR_DISABLED{ErrorModule::LDN, 22};
11
12} // namespace Service::LDN
diff --git a/src/core/hle/service/ldn/ldn.cpp b/src/core/hle/service/ldn/ldn.cpp
index 125d4dc4c..c11daff54 100644
--- a/src/core/hle/service/ldn/ldn.cpp
+++ b/src/core/hle/service/ldn/ldn.cpp
@@ -3,11 +3,15 @@
3 3
4#include <memory> 4#include <memory>
5 5
6#include "core/hle/ipc_helpers.h" 6#include "core/core.h"
7#include "core/hle/result.h"
8#include "core/hle/service/ldn/errors.h"
9#include "core/hle/service/ldn/ldn.h" 7#include "core/hle/service/ldn/ldn.h"
10#include "core/hle/service/sm/sm.h" 8#include "core/hle/service/ldn/ldn_results.h"
9#include "core/hle/service/ldn/ldn_types.h"
10#include "core/internal_network/network.h"
11#include "core/internal_network/network_interface.h"
12
13// This is defined by synchapi.h and conflicts with ServiceContext::CreateEvent
14#undef CreateEvent
11 15
12namespace Service::LDN { 16namespace Service::LDN {
13 17
@@ -100,74 +104,418 @@ class IUserLocalCommunicationService final
100 : public ServiceFramework<IUserLocalCommunicationService> { 104 : public ServiceFramework<IUserLocalCommunicationService> {
101public: 105public:
102 explicit IUserLocalCommunicationService(Core::System& system_) 106 explicit IUserLocalCommunicationService(Core::System& system_)
103 : ServiceFramework{system_, "IUserLocalCommunicationService"} { 107 : ServiceFramework{system_, "IUserLocalCommunicationService", ServiceThreadType::CreateNew},
108 service_context{system, "IUserLocalCommunicationService"}, room_network{
109 system_.GetRoomNetwork()} {
104 // clang-format off 110 // clang-format off
105 static const FunctionInfo functions[] = { 111 static const FunctionInfo functions[] = {
106 {0, &IUserLocalCommunicationService::GetState, "GetState"}, 112 {0, &IUserLocalCommunicationService::GetState, "GetState"},
107 {1, nullptr, "GetNetworkInfo"}, 113 {1, &IUserLocalCommunicationService::GetNetworkInfo, "GetNetworkInfo"},
108 {2, nullptr, "GetIpv4Address"}, 114 {2, nullptr, "GetIpv4Address"},
109 {3, nullptr, "GetDisconnectReason"}, 115 {3, &IUserLocalCommunicationService::GetDisconnectReason, "GetDisconnectReason"},
110 {4, nullptr, "GetSecurityParameter"}, 116 {4, &IUserLocalCommunicationService::GetSecurityParameter, "GetSecurityParameter"},
111 {5, nullptr, "GetNetworkConfig"}, 117 {5, &IUserLocalCommunicationService::GetNetworkConfig, "GetNetworkConfig"},
112 {100, nullptr, "AttachStateChangeEvent"}, 118 {100, &IUserLocalCommunicationService::AttachStateChangeEvent, "AttachStateChangeEvent"},
113 {101, nullptr, "GetNetworkInfoLatestUpdate"}, 119 {101, &IUserLocalCommunicationService::GetNetworkInfoLatestUpdate, "GetNetworkInfoLatestUpdate"},
114 {102, nullptr, "Scan"}, 120 {102, &IUserLocalCommunicationService::Scan, "Scan"},
115 {103, nullptr, "ScanPrivate"}, 121 {103, &IUserLocalCommunicationService::ScanPrivate, "ScanPrivate"},
116 {104, nullptr, "SetWirelessControllerRestriction"}, 122 {104, nullptr, "SetWirelessControllerRestriction"},
117 {200, nullptr, "OpenAccessPoint"}, 123 {200, &IUserLocalCommunicationService::OpenAccessPoint, "OpenAccessPoint"},
118 {201, nullptr, "CloseAccessPoint"}, 124 {201, &IUserLocalCommunicationService::CloseAccessPoint, "CloseAccessPoint"},
119 {202, nullptr, "CreateNetwork"}, 125 {202, &IUserLocalCommunicationService::CreateNetwork, "CreateNetwork"},
120 {203, nullptr, "CreateNetworkPrivate"}, 126 {203, &IUserLocalCommunicationService::CreateNetworkPrivate, "CreateNetworkPrivate"},
121 {204, nullptr, "DestroyNetwork"}, 127 {204, &IUserLocalCommunicationService::DestroyNetwork, "DestroyNetwork"},
122 {205, nullptr, "Reject"}, 128 {205, nullptr, "Reject"},
123 {206, nullptr, "SetAdvertiseData"}, 129 {206, &IUserLocalCommunicationService::SetAdvertiseData, "SetAdvertiseData"},
124 {207, nullptr, "SetStationAcceptPolicy"}, 130 {207, &IUserLocalCommunicationService::SetStationAcceptPolicy, "SetStationAcceptPolicy"},
125 {208, nullptr, "AddAcceptFilterEntry"}, 131 {208, &IUserLocalCommunicationService::AddAcceptFilterEntry, "AddAcceptFilterEntry"},
126 {209, nullptr, "ClearAcceptFilter"}, 132 {209, nullptr, "ClearAcceptFilter"},
127 {300, nullptr, "OpenStation"}, 133 {300, &IUserLocalCommunicationService::OpenStation, "OpenStation"},
128 {301, nullptr, "CloseStation"}, 134 {301, &IUserLocalCommunicationService::CloseStation, "CloseStation"},
129 {302, nullptr, "Connect"}, 135 {302, &IUserLocalCommunicationService::Connect, "Connect"},
130 {303, nullptr, "ConnectPrivate"}, 136 {303, nullptr, "ConnectPrivate"},
131 {304, nullptr, "Disconnect"}, 137 {304, &IUserLocalCommunicationService::Disconnect, "Disconnect"},
132 {400, nullptr, "Initialize"}, 138 {400, &IUserLocalCommunicationService::Initialize, "Initialize"},
133 {401, nullptr, "Finalize"}, 139 {401, &IUserLocalCommunicationService::Finalize, "Finalize"},
134 {402, &IUserLocalCommunicationService::Initialize2, "Initialize2"}, // 7.0.0+ 140 {402, &IUserLocalCommunicationService::Initialize2, "Initialize2"},
135 }; 141 };
136 // clang-format on 142 // clang-format on
137 143
138 RegisterHandlers(functions); 144 RegisterHandlers(functions);
145
146 state_change_event =
147 service_context.CreateEvent("IUserLocalCommunicationService:StateChangeEvent");
148 }
149
150 ~IUserLocalCommunicationService() {
151 service_context.CloseEvent(state_change_event);
152 }
153
154 void OnEventFired() {
155 state_change_event->GetWritableEvent().Signal();
139 } 156 }
140 157
141 void GetState(Kernel::HLERequestContext& ctx) { 158 void GetState(Kernel::HLERequestContext& ctx) {
159 State state = State::Error;
160 LOG_WARNING(Service_LDN, "(STUBBED) called, state = {}", state);
161
162 IPC::ResponseBuilder rb{ctx, 3};
163 rb.Push(ResultSuccess);
164 rb.PushEnum(state);
165 }
166
167 void GetNetworkInfo(Kernel::HLERequestContext& ctx) {
168 const auto write_buffer_size = ctx.GetWriteBufferSize();
169
170 if (write_buffer_size != sizeof(NetworkInfo)) {
171 LOG_ERROR(Service_LDN, "Invalid buffer size {}", write_buffer_size);
172 IPC::ResponseBuilder rb{ctx, 2};
173 rb.Push(ResultBadInput);
174 return;
175 }
176
177 NetworkInfo network_info{};
178 const auto rc = ResultSuccess;
179 if (rc.IsError()) {
180 LOG_ERROR(Service_LDN, "NetworkInfo is not valid {}", rc.raw);
181 IPC::ResponseBuilder rb{ctx, 2};
182 rb.Push(rc);
183 return;
184 }
185
186 LOG_WARNING(Service_LDN, "(STUBBED) called, ssid='{}', nodes={}",
187 network_info.common.ssid.GetStringValue(), network_info.ldn.node_count);
188
189 ctx.WriteBuffer<NetworkInfo>(network_info);
190 IPC::ResponseBuilder rb{ctx, 2};
191 rb.Push(rc);
192 }
193
194 void GetDisconnectReason(Kernel::HLERequestContext& ctx) {
195 const auto disconnect_reason = DisconnectReason::None;
196
197 LOG_WARNING(Service_LDN, "(STUBBED) called, disconnect_reason={}", disconnect_reason);
198
199 IPC::ResponseBuilder rb{ctx, 3};
200 rb.Push(ResultSuccess);
201 rb.PushEnum(disconnect_reason);
202 }
203
204 void GetSecurityParameter(Kernel::HLERequestContext& ctx) {
205 SecurityParameter security_parameter{};
206 NetworkInfo info{};
207 const Result rc = ResultSuccess;
208
209 if (rc.IsError()) {
210 LOG_ERROR(Service_LDN, "NetworkInfo is not valid {}", rc.raw);
211 IPC::ResponseBuilder rb{ctx, 2};
212 rb.Push(rc);
213 return;
214 }
215
216 security_parameter.session_id = info.network_id.session_id;
217 std::memcpy(security_parameter.data.data(), info.ldn.security_parameter.data(),
218 sizeof(SecurityParameter::data));
219
142 LOG_WARNING(Service_LDN, "(STUBBED) called"); 220 LOG_WARNING(Service_LDN, "(STUBBED) called");
143 221
222 IPC::ResponseBuilder rb{ctx, 10};
223 rb.Push(rc);
224 rb.PushRaw<SecurityParameter>(security_parameter);
225 }
226
227 void GetNetworkConfig(Kernel::HLERequestContext& ctx) {
228 NetworkConfig config{};
229 NetworkInfo info{};
230 const Result rc = ResultSuccess;
231
232 if (rc.IsError()) {
233 LOG_ERROR(Service_LDN, "NetworkConfig is not valid {}", rc.raw);
234 IPC::ResponseBuilder rb{ctx, 2};
235 rb.Push(rc);
236 return;
237 }
238
239 config.intent_id = info.network_id.intent_id;
240 config.channel = info.common.channel;
241 config.node_count_max = info.ldn.node_count_max;
242 config.local_communication_version = info.ldn.nodes[0].local_communication_version;
243
244 LOG_WARNING(Service_LDN,
245 "(STUBBED) called, intent_id={}/{}, channel={}, node_count_max={}, "
246 "local_communication_version={}",
247 config.intent_id.local_communication_id, config.intent_id.scene_id,
248 config.channel, config.node_count_max, config.local_communication_version);
249
250 IPC::ResponseBuilder rb{ctx, 10};
251 rb.Push(rc);
252 rb.PushRaw<NetworkConfig>(config);
253 }
254
255 void AttachStateChangeEvent(Kernel::HLERequestContext& ctx) {
256 LOG_INFO(Service_LDN, "called");
257
258 IPC::ResponseBuilder rb{ctx, 2, 1};
259 rb.Push(ResultSuccess);
260 rb.PushCopyObjects(state_change_event->GetReadableEvent());
261 }
262
263 void GetNetworkInfoLatestUpdate(Kernel::HLERequestContext& ctx) {
264 const std::size_t network_buffer_size = ctx.GetWriteBufferSize(0);
265 const std::size_t node_buffer_count = ctx.GetWriteBufferSize(1) / sizeof(NodeLatestUpdate);
266
267 if (node_buffer_count == 0 || network_buffer_size != sizeof(NetworkInfo)) {
268 LOG_ERROR(Service_LDN, "Invalid buffer size {}, {}", network_buffer_size,
269 node_buffer_count);
270 IPC::ResponseBuilder rb{ctx, 2};
271 rb.Push(ResultBadInput);
272 return;
273 }
274
275 NetworkInfo info;
276 std::vector<NodeLatestUpdate> latest_update(node_buffer_count);
277
278 const auto rc = ResultSuccess;
279 if (rc.IsError()) {
280 LOG_ERROR(Service_LDN, "NetworkInfo is not valid {}", rc.raw);
281 IPC::ResponseBuilder rb{ctx, 2};
282 rb.Push(rc);
283 return;
284 }
285
286 LOG_WARNING(Service_LDN, "(STUBBED) called, ssid='{}', nodes={}",
287 info.common.ssid.GetStringValue(), info.ldn.node_count);
288
289 ctx.WriteBuffer(info, 0);
290 ctx.WriteBuffer(latest_update, 1);
291
292 IPC::ResponseBuilder rb{ctx, 2};
293 rb.Push(ResultSuccess);
294 }
295
296 void Scan(Kernel::HLERequestContext& ctx) {
297 ScanImpl(ctx);
298 }
299
300 void ScanPrivate(Kernel::HLERequestContext& ctx) {
301 ScanImpl(ctx, true);
302 }
303
304 void ScanImpl(Kernel::HLERequestContext& ctx, bool is_private = false) {
305 IPC::RequestParser rp{ctx};
306 const auto channel{rp.PopEnum<WifiChannel>()};
307 const auto scan_filter{rp.PopRaw<ScanFilter>()};
308
309 const std::size_t network_info_size = ctx.GetWriteBufferSize() / sizeof(NetworkInfo);
310
311 if (network_info_size == 0) {
312 LOG_ERROR(Service_LDN, "Invalid buffer size {}", network_info_size);
313 IPC::ResponseBuilder rb{ctx, 2};
314 rb.Push(ResultBadInput);
315 return;
316 }
317
318 u16 count = 0;
319 std::vector<NetworkInfo> network_infos(network_info_size);
320
321 LOG_WARNING(Service_LDN,
322 "(STUBBED) called, channel={}, filter_scan_flag={}, filter_network_type={}",
323 channel, scan_filter.flag, scan_filter.network_type);
324
325 ctx.WriteBuffer(network_infos);
326
144 IPC::ResponseBuilder rb{ctx, 3}; 327 IPC::ResponseBuilder rb{ctx, 3};
328 rb.Push(ResultSuccess);
329 rb.Push<u32>(count);
330 }
331
332 void OpenAccessPoint(Kernel::HLERequestContext& ctx) {
333 LOG_WARNING(Service_LDN, "(STUBBED) called");
334
335 IPC::ResponseBuilder rb{ctx, 2};
336 rb.Push(ResultSuccess);
337 }
338
339 void CloseAccessPoint(Kernel::HLERequestContext& ctx) {
340 LOG_WARNING(Service_LDN, "(STUBBED) called");
341
342 IPC::ResponseBuilder rb{ctx, 2};
343 rb.Push(ResultSuccess);
344 }
345
346 void CreateNetwork(Kernel::HLERequestContext& ctx) {
347 IPC::RequestParser rp{ctx};
348 struct Parameters {
349 SecurityConfig security_config;
350 UserConfig user_config;
351 INSERT_PADDING_WORDS_NOINIT(1);
352 NetworkConfig network_config;
353 };
354 static_assert(sizeof(Parameters) == 0x98, "Parameters has incorrect size.");
355
356 const auto parameters{rp.PopRaw<Parameters>()};
357
358 LOG_WARNING(Service_LDN,
359 "(STUBBED) called, passphrase_size={}, security_mode={}, "
360 "local_communication_version={}",
361 parameters.security_config.passphrase_size,
362 parameters.security_config.security_mode,
363 parameters.network_config.local_communication_version);
364
365 IPC::ResponseBuilder rb{ctx, 2};
366 rb.Push(ResultSuccess);
367 }
368
369 void CreateNetworkPrivate(Kernel::HLERequestContext& ctx) {
370 IPC::RequestParser rp{ctx};
371 struct Parameters {
372 SecurityConfig security_config;
373 SecurityParameter security_parameter;
374 UserConfig user_config;
375 NetworkConfig network_config;
376 };
377 static_assert(sizeof(Parameters) == 0xB8, "Parameters has incorrect size.");
378
379 const auto parameters{rp.PopRaw<Parameters>()};
380
381 LOG_WARNING(Service_LDN,
382 "(STUBBED) called, passphrase_size={}, security_mode={}, "
383 "local_communication_version={}",
384 parameters.security_config.passphrase_size,
385 parameters.security_config.security_mode,
386 parameters.network_config.local_communication_version);
387
388 IPC::ResponseBuilder rb{ctx, 2};
389 rb.Push(ResultSuccess);
390 }
391
392 void DestroyNetwork(Kernel::HLERequestContext& ctx) {
393 LOG_WARNING(Service_LDN, "(STUBBED) called");
394
395 IPC::ResponseBuilder rb{ctx, 2};
396 rb.Push(ResultSuccess);
397 }
398
399 void SetAdvertiseData(Kernel::HLERequestContext& ctx) {
400 std::vector<u8> read_buffer = ctx.ReadBuffer();
401
402 LOG_WARNING(Service_LDN, "(STUBBED) called, size {}", read_buffer.size());
403
404 IPC::ResponseBuilder rb{ctx, 2};
405 rb.Push(ResultSuccess);
406 }
407
408 void SetStationAcceptPolicy(Kernel::HLERequestContext& ctx) {
409 LOG_WARNING(Service_LDN, "(STUBBED) called");
410
411 IPC::ResponseBuilder rb{ctx, 2};
412 rb.Push(ResultSuccess);
413 }
145 414
146 // Indicate a network error, as we do not actually emulate LDN 415 void AddAcceptFilterEntry(Kernel::HLERequestContext& ctx) {
147 rb.Push(static_cast<u32>(State::Error)); 416 LOG_WARNING(Service_LDN, "(STUBBED) called");
148 417
418 IPC::ResponseBuilder rb{ctx, 2};
419 rb.Push(ResultSuccess);
420 }
421
422 void OpenStation(Kernel::HLERequestContext& ctx) {
423 LOG_WARNING(Service_LDN, "(STUBBED) called");
424
425 IPC::ResponseBuilder rb{ctx, 2};
426 rb.Push(ResultSuccess);
427 }
428
429 void CloseStation(Kernel::HLERequestContext& ctx) {
430 LOG_WARNING(Service_LDN, "(STUBBED) called");
431
432 IPC::ResponseBuilder rb{ctx, 2};
433 rb.Push(ResultSuccess);
434 }
435
436 void Connect(Kernel::HLERequestContext& ctx) {
437 IPC::RequestParser rp{ctx};
438 struct Parameters {
439 SecurityConfig security_config;
440 UserConfig user_config;
441 u32 local_communication_version;
442 u32 option;
443 };
444 static_assert(sizeof(Parameters) == 0x7C, "Parameters has incorrect size.");
445
446 const auto parameters{rp.PopRaw<Parameters>()};
447
448 LOG_WARNING(Service_LDN,
449 "(STUBBED) called, passphrase_size={}, security_mode={}, "
450 "local_communication_version={}",
451 parameters.security_config.passphrase_size,
452 parameters.security_config.security_mode,
453 parameters.local_communication_version);
454
455 const std::vector<u8> read_buffer = ctx.ReadBuffer();
456 NetworkInfo network_info{};
457
458 if (read_buffer.size() != sizeof(NetworkInfo)) {
459 LOG_ERROR(Frontend, "NetworkInfo doesn't match read_buffer size!");
460 IPC::ResponseBuilder rb{ctx, 2};
461 rb.Push(ResultBadInput);
462 return;
463 }
464
465 std::memcpy(&network_info, read_buffer.data(), read_buffer.size());
466
467 IPC::ResponseBuilder rb{ctx, 2};
468 rb.Push(ResultSuccess);
469 }
470
471 void Disconnect(Kernel::HLERequestContext& ctx) {
472 LOG_WARNING(Service_LDN, "(STUBBED) called");
473
474 IPC::ResponseBuilder rb{ctx, 2};
475 rb.Push(ResultSuccess);
476 }
477 void Initialize(Kernel::HLERequestContext& ctx) {
478 LOG_WARNING(Service_LDN, "(STUBBED) called");
479
480 const auto rc = InitializeImpl(ctx);
481
482 IPC::ResponseBuilder rb{ctx, 2};
483 rb.Push(rc);
484 }
485
486 void Finalize(Kernel::HLERequestContext& ctx) {
487 LOG_WARNING(Service_LDN, "(STUBBED) called");
488
489 is_initialized = false;
490
491 IPC::ResponseBuilder rb{ctx, 2};
149 rb.Push(ResultSuccess); 492 rb.Push(ResultSuccess);
150 } 493 }
151 494
152 void Initialize2(Kernel::HLERequestContext& ctx) { 495 void Initialize2(Kernel::HLERequestContext& ctx) {
153 LOG_DEBUG(Service_LDN, "called"); 496 LOG_WARNING(Service_LDN, "(STUBBED) called");
154 497
155 is_initialized = true; 498 const auto rc = InitializeImpl(ctx);
156 499
157 IPC::ResponseBuilder rb{ctx, 2}; 500 IPC::ResponseBuilder rb{ctx, 2};
158 rb.Push(ERROR_DISABLED); 501 rb.Push(rc);
502 }
503
504 Result InitializeImpl(Kernel::HLERequestContext& ctx) {
505 const auto network_interface = Network::GetSelectedNetworkInterface();
506 if (!network_interface) {
507 LOG_ERROR(Service_LDN, "No network interface is set");
508 return ResultAirplaneModeEnabled;
509 }
510
511 is_initialized = true;
512 // TODO (flTobi): Change this to ResultSuccess when LDN is fully implemented
513 return ResultAirplaneModeEnabled;
159 } 514 }
160 515
161private: 516 KernelHelpers::ServiceContext service_context;
162 enum class State { 517 Kernel::KEvent* state_change_event;
163 None, 518 Network::RoomNetwork& room_network;
164 Initialized,
165 AccessPointOpened,
166 AccessPointCreated,
167 StationOpened,
168 StationConnected,
169 Error,
170 };
171 519
172 bool is_initialized{}; 520 bool is_initialized{};
173}; 521};
@@ -273,7 +621,7 @@ public:
273 LOG_WARNING(Service_LDN, "(STUBBED) called"); 621 LOG_WARNING(Service_LDN, "(STUBBED) called");
274 622
275 IPC::ResponseBuilder rb{ctx, 2}; 623 IPC::ResponseBuilder rb{ctx, 2};
276 rb.Push(ERROR_DISABLED); 624 rb.Push(ResultDisabled);
277 } 625 }
278}; 626};
279 627
diff --git a/src/core/hle/service/ldn/ldn.h b/src/core/hle/service/ldn/ldn.h
index a0031ac71..6afe2ea6f 100644
--- a/src/core/hle/service/ldn/ldn.h
+++ b/src/core/hle/service/ldn/ldn.h
@@ -3,6 +3,12 @@
3 3
4#pragma once 4#pragma once
5 5
6#include "core/hle/ipc_helpers.h"
7#include "core/hle/kernel/k_event.h"
8#include "core/hle/result.h"
9#include "core/hle/service/kernel_helpers.h"
10#include "core/hle/service/sm/sm.h"
11
6namespace Core { 12namespace Core {
7class System; 13class System;
8} 14}
diff --git a/src/core/hle/service/ldn/ldn_results.h b/src/core/hle/service/ldn/ldn_results.h
new file mode 100644
index 000000000..f340bda42
--- /dev/null
+++ b/src/core/hle/service/ldn/ldn_results.h
@@ -0,0 +1,27 @@
1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#pragma once
5
6#include "core/hle/result.h"
7
8namespace Service::LDN {
9
10constexpr Result ResultAdvertiseDataTooLarge{ErrorModule::LDN, 10};
11constexpr Result ResultAuthenticationFailed{ErrorModule::LDN, 20};
12constexpr Result ResultDisabled{ErrorModule::LDN, 22};
13constexpr Result ResultAirplaneModeEnabled{ErrorModule::LDN, 23};
14constexpr Result ResultInvalidNodeCount{ErrorModule::LDN, 30};
15constexpr Result ResultConnectionFailed{ErrorModule::LDN, 31};
16constexpr Result ResultBadState{ErrorModule::LDN, 32};
17constexpr Result ResultNoIpAddress{ErrorModule::LDN, 33};
18constexpr Result ResultInvalidBufferCount{ErrorModule::LDN, 50};
19constexpr Result ResultAccessPointConnectionFailed{ErrorModule::LDN, 65};
20constexpr Result ResultAuthenticationTimeout{ErrorModule::LDN, 66};
21constexpr Result ResultMaximumNodeCount{ErrorModule::LDN, 67};
22constexpr Result ResultBadInput{ErrorModule::LDN, 96};
23constexpr Result ResultLocalCommunicationIdNotFound{ErrorModule::LDN, 97};
24constexpr Result ResultLocalCommunicationVersionTooLow{ErrorModule::LDN, 113};
25constexpr Result ResultLocalCommunicationVersionTooHigh{ErrorModule::LDN, 114};
26
27} // namespace Service::LDN
diff --git a/src/core/hle/service/ldn/ldn_types.h b/src/core/hle/service/ldn/ldn_types.h
new file mode 100644
index 000000000..0c07a7397
--- /dev/null
+++ b/src/core/hle/service/ldn/ldn_types.h
@@ -0,0 +1,284 @@
1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#pragma once
5
6#include <fmt/format.h>
7
8#include "common/common_funcs.h"
9#include "common/common_types.h"
10#include "network/network.h"
11
12namespace Service::LDN {
13
14constexpr size_t SsidLengthMax = 32;
15constexpr size_t AdvertiseDataSizeMax = 384;
16constexpr size_t UserNameBytesMax = 32;
17constexpr int NodeCountMax = 8;
18constexpr int StationCountMax = NodeCountMax - 1;
19constexpr size_t PassphraseLengthMax = 64;
20
21enum class SecurityMode : u16 {
22 All,
23 Retail,
24 Debug,
25};
26
27enum class NodeStateChange : u8 {
28 None,
29 Connect,
30 Disconnect,
31 DisconnectAndConnect,
32};
33
34enum class ScanFilterFlag : u32 {
35 None = 0,
36 LocalCommunicationId = 1 << 0,
37 SessionId = 1 << 1,
38 NetworkType = 1 << 2,
39 Ssid = 1 << 4,
40 SceneId = 1 << 5,
41 IntentId = LocalCommunicationId | SceneId,
42 NetworkId = IntentId | SessionId,
43};
44
45enum class NetworkType : u32 {
46 None,
47 General,
48 Ldn,
49 All,
50};
51
52enum class PackedNetworkType : u8 {
53 None,
54 General,
55 Ldn,
56 All,
57};
58
59enum class State : u32 {
60 None,
61 Initialized,
62 AccessPointOpened,
63 AccessPointCreated,
64 StationOpened,
65 StationConnected,
66 Error,
67};
68
69enum class DisconnectReason : s16 {
70 Unknown = -1,
71 None,
72 DisconnectedByUser,
73 DisconnectedBySystem,
74 DestroyedByUser,
75 DestroyedBySystem,
76 Rejected,
77 SignalLost,
78};
79
80enum class NetworkError {
81 Unknown = -1,
82 None = 0,
83 PortUnreachable,
84 TooManyPlayers,
85 VersionTooLow,
86 VersionTooHigh,
87 ConnectFailure,
88 ConnectNotFound,
89 ConnectTimeout,
90 ConnectRejected,
91 RejectFailed,
92};
93
94enum class AcceptPolicy : u8 {
95 AcceptAll,
96 RejectAll,
97 BlackList,
98 WhiteList,
99};
100
101enum class WifiChannel : s16 {
102 Default = 0,
103 wifi24_1 = 1,
104 wifi24_6 = 6,
105 wifi24_11 = 11,
106 wifi50_36 = 36,
107 wifi50_40 = 40,
108 wifi50_44 = 44,
109 wifi50_48 = 48,
110};
111
112enum class LinkLevel : s8 {
113 Bad,
114 Low,
115 Good,
116 Excelent,
117};
118
119struct NodeLatestUpdate {
120 NodeStateChange state_change;
121 INSERT_PADDING_BYTES(0x7); // Unknown
122};
123static_assert(sizeof(NodeLatestUpdate) == 0x8, "NodeLatestUpdate is an invalid size");
124
125struct SessionId {
126 u64 high;
127 u64 low;
128
129 bool operator==(const SessionId&) const = default;
130};
131static_assert(sizeof(SessionId) == 0x10, "SessionId is an invalid size");
132
133struct IntentId {
134 u64 local_communication_id;
135 INSERT_PADDING_BYTES(0x2); // Reserved
136 u16 scene_id;
137 INSERT_PADDING_BYTES(0x4); // Reserved
138};
139static_assert(sizeof(IntentId) == 0x10, "IntentId is an invalid size");
140
141struct NetworkId {
142 IntentId intent_id;
143 SessionId session_id;
144};
145static_assert(sizeof(NetworkId) == 0x20, "NetworkId is an invalid size");
146
147struct Ssid {
148 u8 length;
149 std::array<char, SsidLengthMax + 1> raw;
150
151 std::string GetStringValue() const {
152 return std::string(raw.data(), length);
153 }
154};
155static_assert(sizeof(Ssid) == 0x22, "Ssid is an invalid size");
156
157struct Ipv4Address {
158 union {
159 u32 raw{};
160 std::array<u8, 4> bytes;
161 };
162
163 std::string GetStringValue() const {
164 return fmt::format("{}.{}.{}.{}", bytes[3], bytes[2], bytes[1], bytes[0]);
165 }
166};
167static_assert(sizeof(Ipv4Address) == 0x4, "Ipv4Address is an invalid size");
168
169struct MacAddress {
170 std::array<u8, 6> raw{};
171
172 friend bool operator==(const MacAddress& lhs, const MacAddress& rhs) = default;
173};
174static_assert(sizeof(MacAddress) == 0x6, "MacAddress is an invalid size");
175
176struct ScanFilter {
177 NetworkId network_id;
178 NetworkType network_type;
179 MacAddress mac_address;
180 Ssid ssid;
181 INSERT_PADDING_BYTES(0x10);
182 ScanFilterFlag flag;
183};
184static_assert(sizeof(ScanFilter) == 0x60, "ScanFilter is an invalid size");
185
186struct CommonNetworkInfo {
187 MacAddress bssid;
188 Ssid ssid;
189 WifiChannel channel;
190 LinkLevel link_level;
191 PackedNetworkType network_type;
192 INSERT_PADDING_BYTES(0x4);
193};
194static_assert(sizeof(CommonNetworkInfo) == 0x30, "CommonNetworkInfo is an invalid size");
195
196struct NodeInfo {
197 Ipv4Address ipv4_address;
198 MacAddress mac_address;
199 s8 node_id;
200 u8 is_connected;
201 std::array<u8, UserNameBytesMax + 1> user_name;
202 INSERT_PADDING_BYTES(0x1); // Reserved
203 s16 local_communication_version;
204 INSERT_PADDING_BYTES(0x10); // Reserved
205};
206static_assert(sizeof(NodeInfo) == 0x40, "NodeInfo is an invalid size");
207
208struct LdnNetworkInfo {
209 std::array<u8, 0x10> security_parameter;
210 SecurityMode security_mode;
211 AcceptPolicy station_accept_policy;
212 u8 has_action_frame;
213 INSERT_PADDING_BYTES(0x2); // Padding
214 u8 node_count_max;
215 u8 node_count;
216 std::array<NodeInfo, NodeCountMax> nodes;
217 INSERT_PADDING_BYTES(0x2); // Reserved
218 u16 advertise_data_size;
219 std::array<u8, AdvertiseDataSizeMax> advertise_data;
220 INSERT_PADDING_BYTES(0x8C); // Reserved
221 u64 random_authentication_id;
222};
223static_assert(sizeof(LdnNetworkInfo) == 0x430, "LdnNetworkInfo is an invalid size");
224
225struct NetworkInfo {
226 NetworkId network_id;
227 CommonNetworkInfo common;
228 LdnNetworkInfo ldn;
229};
230static_assert(sizeof(NetworkInfo) == 0x480, "NetworkInfo is an invalid size");
231
232struct SecurityConfig {
233 SecurityMode security_mode;
234 u16 passphrase_size;
235 std::array<u8, PassphraseLengthMax> passphrase;
236};
237static_assert(sizeof(SecurityConfig) == 0x44, "SecurityConfig is an invalid size");
238
239struct UserConfig {
240 std::array<u8, UserNameBytesMax + 1> user_name;
241 INSERT_PADDING_BYTES(0xF); // Reserved
242};
243static_assert(sizeof(UserConfig) == 0x30, "UserConfig is an invalid size");
244
245#pragma pack(push, 4)
246struct ConnectRequest {
247 SecurityConfig security_config;
248 UserConfig user_config;
249 u32 local_communication_version;
250 u32 option_unknown;
251 NetworkInfo network_info;
252};
253static_assert(sizeof(ConnectRequest) == 0x4FC, "ConnectRequest is an invalid size");
254#pragma pack(pop)
255
256struct SecurityParameter {
257 std::array<u8, 0x10> data; // Data, used with the same key derivation as SecurityConfig
258 SessionId session_id;
259};
260static_assert(sizeof(SecurityParameter) == 0x20, "SecurityParameter is an invalid size");
261
262struct NetworkConfig {
263 IntentId intent_id;
264 WifiChannel channel;
265 u8 node_count_max;
266 INSERT_PADDING_BYTES(0x1); // Reserved
267 u16 local_communication_version;
268 INSERT_PADDING_BYTES(0xA); // Reserved
269};
270static_assert(sizeof(NetworkConfig) == 0x20, "NetworkConfig is an invalid size");
271
272struct AddressEntry {
273 Ipv4Address ipv4_address;
274 MacAddress mac_address;
275 INSERT_PADDING_BYTES(0x2); // Reserved
276};
277static_assert(sizeof(AddressEntry) == 0xC, "AddressEntry is an invalid size");
278
279struct AddressList {
280 std::array<AddressEntry, 0x8> addresses;
281};
282static_assert(sizeof(AddressList) == 0x60, "AddressList is an invalid size");
283
284} // namespace Service::LDN
diff --git a/src/yuzu/aboutdialog.ui b/src/yuzu/aboutdialog.ui
index c4ffb293e..aea82809d 100644
--- a/src/yuzu/aboutdialog.ui
+++ b/src/yuzu/aboutdialog.ui
@@ -7,7 +7,7 @@
7 <x>0</x> 7 <x>0</x>
8 <y>0</y> 8 <y>0</y>
9 <width>616</width> 9 <width>616</width>
10 <height>261</height> 10 <height>294</height>
11 </rect> 11 </rect>
12 </property> 12 </property>
13 <property name="windowTitle"> 13 <property name="windowTitle">
@@ -165,6 +165,7 @@ p, li { white-space: pre-wrap; }
165 </widget> 165 </widget>
166 <resources> 166 <resources>
167 <include location="../../dist/qt_themes_default/default/default.qrc"/> 167 <include location="../../dist/qt_themes_default/default/default.qrc"/>
168 <include location="../../dist/qt_themes/default/default.qrc"/>
168 </resources> 169 </resources>
169 <connections> 170 <connections>
170 <connection> 171 <connection>
diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp
index 041e6ac11..c4b1f65bd 100644
--- a/src/yuzu/game_list.cpp
+++ b/src/yuzu/game_list.cpp
@@ -286,7 +286,7 @@ void GameList::OnUpdateThemedIcons() {
286 } 286 }
287 case GameListItemType::AddDir: 287 case GameListItemType::AddDir:
288 child->setData( 288 child->setData(
289 QIcon::fromTheme(QStringLiteral("plus")) 289 QIcon::fromTheme(QStringLiteral("list-add"))
290 .pixmap(icon_size) 290 .pixmap(icon_size)
291 .scaled(icon_size, icon_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), 291 .scaled(icon_size, icon_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation),
292 Qt::DecorationRole); 292 Qt::DecorationRole);
diff --git a/src/yuzu/game_list_p.h b/src/yuzu/game_list_p.h
index e7667cf60..0e19be22d 100644
--- a/src/yuzu/game_list_p.h
+++ b/src/yuzu/game_list_p.h
@@ -294,7 +294,7 @@ public:
294 294
295 const int icon_size = UISettings::values.folder_icon_size.GetValue(); 295 const int icon_size = UISettings::values.folder_icon_size.GetValue();
296 296
297 setData(QIcon::fromTheme(QStringLiteral("plus")) 297 setData(QIcon::fromTheme(QStringLiteral("list-add"))
298 .pixmap(icon_size) 298 .pixmap(icon_size)
299 .scaled(icon_size, icon_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), 299 .scaled(icon_size, icon_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation),
300 Qt::DecorationRole); 300 Qt::DecorationRole);
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index f82bec3b7..44d7feddc 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -257,6 +257,18 @@ static QString PrettyProductName() {
257 return QSysInfo::prettyProductName(); 257 return QSysInfo::prettyProductName();
258} 258}
259 259
260bool GMainWindow::CheckDarkMode() {
261#ifdef __linux__
262 const QPalette test_palette(qApp->palette());
263 const QColor text_color = test_palette.color(QPalette::Active, QPalette::Text);
264 const QColor window_color = test_palette.color(QPalette::Active, QPalette::Window);
265 return (text_color.value() > window_color.value());
266#else
267 // TODO: Windows
268 return false;
269#endif // __linux__
270}
271
260GMainWindow::GMainWindow(bool has_broken_vulkan) 272GMainWindow::GMainWindow(bool has_broken_vulkan)
261 : ui{std::make_unique<Ui::MainWindow>()}, system{std::make_unique<Core::System>()}, 273 : ui{std::make_unique<Ui::MainWindow>()}, system{std::make_unique<Core::System>()},
262 input_subsystem{std::make_shared<InputCommon::InputSubsystem>()}, 274 input_subsystem{std::make_shared<InputCommon::InputSubsystem>()},
@@ -274,6 +286,13 @@ GMainWindow::GMainWindow(bool has_broken_vulkan)
274 ui->setupUi(this); 286 ui->setupUi(this);
275 statusBar()->hide(); 287 statusBar()->hide();
276 288
289 // Check dark mode before a theme is loaded
290 os_dark_mode = CheckDarkMode();
291 startup_icon_theme = QIcon::themeName();
292 // fallback can only be set once, colorful theme icons are okay on both light/dark
293 QIcon::setFallbackThemeName(QStringLiteral("colorful"));
294 QIcon::setFallbackSearchPaths(QStringList(QStringLiteral(":/icons")));
295
277 default_theme_paths = QIcon::themeSearchPaths(); 296 default_theme_paths = QIcon::themeSearchPaths();
278 UpdateUITheme(); 297 UpdateUITheme();
279 298
@@ -3935,8 +3954,21 @@ void GMainWindow::filterBarSetChecked(bool state) {
3935 emit(OnToggleFilterBar()); 3954 emit(OnToggleFilterBar());
3936} 3955}
3937 3956
3957static void AdjustLinkColor() {
3958 QPalette new_pal(qApp->palette());
3959 if (UISettings::IsDarkTheme()) {
3960 new_pal.setColor(QPalette::Link, QColor(0, 190, 255, 255));
3961 } else {
3962 new_pal.setColor(QPalette::Link, QColor(0, 140, 200, 255));
3963 }
3964 if (qApp->palette().color(QPalette::Link) != new_pal.color(QPalette::Link)) {
3965 qApp->setPalette(new_pal);
3966 }
3967}
3968
3938void GMainWindow::UpdateUITheme() { 3969void GMainWindow::UpdateUITheme() {
3939 const QString default_theme = QStringLiteral("default"); 3970 const QString default_theme =
3971 QString::fromUtf8(UISettings::themes[static_cast<size_t>(Config::default_theme)].second);
3940 QString current_theme = UISettings::values.theme; 3972 QString current_theme = UISettings::values.theme;
3941 QStringList theme_paths(default_theme_paths); 3973 QStringList theme_paths(default_theme_paths);
3942 3974
@@ -3944,6 +3976,23 @@ void GMainWindow::UpdateUITheme() {
3944 current_theme = default_theme; 3976 current_theme = default_theme;
3945 } 3977 }
3946 3978
3979#ifdef _WIN32
3980 QIcon::setThemeName(current_theme);
3981 AdjustLinkColor();
3982#else
3983 if (current_theme == QStringLiteral("default") || current_theme == QStringLiteral("colorful")) {
3984 QIcon::setThemeName(current_theme == QStringLiteral("colorful") ? current_theme
3985 : startup_icon_theme);
3986 QIcon::setThemeSearchPaths(theme_paths);
3987 if (CheckDarkMode()) {
3988 current_theme = QStringLiteral("default_dark");
3989 }
3990 } else {
3991 QIcon::setThemeName(current_theme);
3992 QIcon::setThemeSearchPaths(QStringList(QStringLiteral(":/icons")));
3993 AdjustLinkColor();
3994 }
3995#endif
3947 if (current_theme != default_theme) { 3996 if (current_theme != default_theme) {
3948 QString theme_uri{QStringLiteral(":%1/style.qss").arg(current_theme)}; 3997 QString theme_uri{QStringLiteral(":%1/style.qss").arg(current_theme)};
3949 QFile f(theme_uri); 3998 QFile f(theme_uri);
@@ -3966,17 +4015,6 @@ void GMainWindow::UpdateUITheme() {
3966 qApp->setStyleSheet({}); 4015 qApp->setStyleSheet({});
3967 setStyleSheet({}); 4016 setStyleSheet({});
3968 } 4017 }
3969
3970 QPalette new_pal(qApp->palette());
3971 if (UISettings::IsDarkTheme()) {
3972 new_pal.setColor(QPalette::Link, QColor(0, 190, 255, 255));
3973 } else {
3974 new_pal.setColor(QPalette::Link, QColor(0, 140, 200, 255));
3975 }
3976 qApp->setPalette(new_pal);
3977
3978 QIcon::setThemeName(current_theme);
3979 QIcon::setThemeSearchPaths(theme_paths);
3980} 4018}
3981 4019
3982void GMainWindow::LoadTranslation() { 4020void GMainWindow::LoadTranslation() {
@@ -4022,6 +4060,26 @@ void GMainWindow::SetDiscordEnabled([[maybe_unused]] bool state) {
4022 discord_rpc->Update(); 4060 discord_rpc->Update();
4023} 4061}
4024 4062
4063void GMainWindow::changeEvent(QEvent* event) {
4064#ifdef __linux__
4065 // PaletteChange event appears to only reach so far into the GUI, explicitly asking to
4066 // UpdateUITheme is a decent work around
4067 if (event->type() == QEvent::PaletteChange) {
4068 const QPalette test_palette(qApp->palette());
4069 const QString current_theme = UISettings::values.theme;
4070 // Keeping eye on QPalette::Window to avoid looping. QPalette::Text might be useful too
4071 static QColor last_window_color;
4072 const QColor window_color = test_palette.color(QPalette::Active, QPalette::Window);
4073 if (last_window_color != window_color && (current_theme == QStringLiteral("default") ||
4074 current_theme == QStringLiteral("colorful"))) {
4075 UpdateUITheme();
4076 }
4077 last_window_color = window_color;
4078 }
4079#endif // __linux__
4080 QWidget::changeEvent(event);
4081}
4082
4025#ifdef main 4083#ifdef main
4026#undef main 4084#undef main
4027#endif 4085#endif
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index e13b38b24..1ae2b93d9 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -251,6 +251,7 @@ private:
251 bool ConfirmForceLockedExit(); 251 bool ConfirmForceLockedExit();
252 void RequestGameExit(); 252 void RequestGameExit();
253 void RequestGameResume(); 253 void RequestGameResume();
254 void changeEvent(QEvent* event) override;
254 void closeEvent(QCloseEvent* event) override; 255 void closeEvent(QCloseEvent* event) override;
255 256
256#ifdef __linux__ 257#ifdef __linux__
@@ -347,6 +348,7 @@ private:
347 void OpenURL(const QUrl& url); 348 void OpenURL(const QUrl& url);
348 void LoadTranslation(); 349 void LoadTranslation();
349 void OpenPerGameConfiguration(u64 title_id, const std::string& file_name); 350 void OpenPerGameConfiguration(u64 title_id, const std::string& file_name);
351 bool CheckDarkMode();
350 352
351 QString GetTasStateDescription() const; 353 QString GetTasStateDescription() const;
352 354
@@ -392,6 +394,9 @@ private:
392 QTimer mouse_hide_timer; 394 QTimer mouse_hide_timer;
393 QTimer mouse_center_timer; 395 QTimer mouse_center_timer;
394 396
397 QString startup_icon_theme;
398 bool os_dark_mode = false;
399
395 // FS 400 // FS
396 std::shared_ptr<FileSys::VfsFilesystem> vfs; 401 std::shared_ptr<FileSys::VfsFilesystem> vfs;
397 std::unique_ptr<FileSys::ManualContentProvider> provider; 402 std::unique_ptr<FileSys::ManualContentProvider> provider;
diff --git a/src/yuzu/multiplayer/direct_connect.ui b/src/yuzu/multiplayer/direct_connect.ui
index 681b6bf69..57d6ec25a 100644
--- a/src/yuzu/multiplayer/direct_connect.ui
+++ b/src/yuzu/multiplayer/direct_connect.ui
@@ -83,7 +83,7 @@
83 <number>5</number> 83 <number>5</number>
84 </property> 84 </property>
85 <property name="placeholderText"> 85 <property name="placeholderText">
86 <string>24872</string> 86 <string notr="true" extracomment="placeholder string that tells user default port">24872</string>
87 </property> 87 </property>
88 </widget> 88 </widget>
89 </item> 89 </item>