summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-x.ci/scripts/linux/docker.sh2
-rwxr-xr-x.ci/scripts/windows/docker.sh2
-rw-r--r--CMakeLists.txt5
-rw-r--r--README.md2
-rw-r--r--dist/languages/.gitignore2
-rw-r--r--dist/languages/.tx/config8
-rw-r--r--dist/languages/README.md1
-rw-r--r--dist/qt_themes/colorful_midnight_blue/icons/16x16/lock.pngbin0 -> 401 bytes
-rw-r--r--dist/qt_themes/colorful_midnight_blue/icons/index.theme8
-rw-r--r--dist/qt_themes/colorful_midnight_blue/style.qrc57
-rw-r--r--dist/qt_themes/qdarkstyle/rc/checkbox_checked.pngbin492 -> 1935 bytes
-rw-r--r--dist/qt_themes/qdarkstyle/rc/checkbox_checked_disabled.pngbin491 -> 1960 bytes
-rw-r--r--dist/qt_themes/qdarkstyle/rc/checkbox_checked_focus.pngbin252 -> 1813 bytes
-rw-r--r--dist/qt_themes/qdarkstyle/rc/checkbox_indeterminate.pngbin493 -> 492 bytes
-rw-r--r--dist/qt_themes/qdarkstyle/rc/checkbox_indeterminate_disabled.pngbin492 -> 491 bytes
-rw-r--r--dist/qt_themes/qdarkstyle/rc/checkbox_indeterminate_focus.pngbin249 -> 252 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/LICENSE.rst405
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/icons/16x16/lock.pngbin0 -> 304 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/icons/256x256/plus_folder.pngbin0 -> 3438 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/icons/48x48/bad_folder.pngbin0 -> 1098 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/icons/48x48/chip.pngbin0 -> 15120 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/icons/48x48/folder.pngbin0 -> 542 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/icons/48x48/plus.pngbin0 -> 339 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/icons/48x48/sd_card.pngbin0 -> 676 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/icons/index.theme14
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/Hmovetoolbar.pngbin0 -> 220 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/Hsepartoolbar.pngbin0 -> 172 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/Vmovetoolbar.pngbin0 -> 228 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/Vsepartoolbar.pngbin0 -> 187 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_down.pngbin0 -> 525 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_down@2x.pngbin0 -> 977 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_down_disabled.pngbin0 -> 547 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_down_disabled@2x.pngbin0 -> 1040 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_down_focus.pngbin0 -> 530 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_down_focus@2x.pngbin0 -> 1025 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_down_pressed.pngbin0 -> 518 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_down_pressed@2x.pngbin0 -> 1007 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_left.pngbin0 -> 546 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_left@2x.pngbin0 -> 1072 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_left_disabled.pngbin0 -> 569 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_left_disabled@2x.pngbin0 -> 1126 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_left_focus.pngbin0 -> 565 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_left_focus@2x.pngbin0 -> 1143 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_left_pressed.pngbin0 -> 541 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_left_pressed@2x.pngbin0 -> 1120 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_right.pngbin0 -> 518 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_right@2x.pngbin0 -> 1062 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_right_disabled.pngbin0 -> 553 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_right_disabled@2x.pngbin0 -> 1143 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_right_focus.pngbin0 -> 543 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_right_focus@2x.pngbin0 -> 1139 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_right_pressed.pngbin0 -> 544 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_right_pressed@2x.pngbin0 -> 1121 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_up.pngbin0 -> 512 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_up@2x.pngbin0 -> 969 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_up_disabled.pngbin0 -> 538 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_up_disabled@2x.pngbin0 -> 1046 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_up_focus.pngbin0 -> 530 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_up_focus@2x.pngbin0 -> 1017 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_up_pressed.pngbin0 -> 518 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_up_pressed@2x.pngbin0 -> 998 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/base_icon.pngbin0 -> 1256 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/base_icon@2x.pngbin0 -> 3286 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/base_icon_disabled.pngbin0 -> 1256 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/base_icon_disabled@2x.pngbin0 -> 3286 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/base_icon_focus.pngbin0 -> 1256 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/base_icon_focus@2x.pngbin0 -> 3286 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/base_icon_pressed.pngbin0 -> 1256 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/base_icon_pressed@2x.pngbin0 -> 3286 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_closed-on.pngbin0 -> 147 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_closed.pngbin0 -> 350 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_closed@2x.pngbin0 -> 704 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_closed_disabled.pngbin0 -> 373 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_closed_disabled@2x.pngbin0 -> 729 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_closed_focus.pngbin0 -> 380 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_closed_focus@2x.pngbin0 -> 717 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_closed_pressed.pngbin0 -> 372 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_closed_pressed@2x.pngbin0 -> 725 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_end.pngbin0 -> 142 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_end@2x.pngbin0 -> 220 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_end_disabled.pngbin0 -> 146 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_end_disabled@2x.pngbin0 -> 225 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_end_focus.pngbin0 -> 146 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_end_focus@2x.pngbin0 -> 226 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_end_pressed.pngbin0 -> 146 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_end_pressed@2x.pngbin0 -> 225 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_line.pngbin0 -> 130 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_line@2x.pngbin0 -> 242 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_line_disabled.pngbin0 -> 134 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_line_disabled@2x.pngbin0 -> 248 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_line_focus.pngbin0 -> 134 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_line_focus@2x.pngbin0 -> 249 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_line_pressed.pngbin0 -> 134 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_line_pressed@2x.pngbin0 -> 248 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_more.pngbin0 -> 155 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_more@2x.pngbin0 -> 257 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_more_disabled.pngbin0 -> 162 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_more_disabled@2x.pngbin0 -> 265 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_more_focus.pngbin0 -> 162 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_more_focus@2x.pngbin0 -> 266 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_more_pressed.pngbin0 -> 162 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_more_pressed@2x.pngbin0 -> 265 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_open-on.pngbin0 -> 150 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_open.pngbin0 -> 354 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_open@2x.pngbin0 -> 657 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_open_disabled.pngbin0 -> 375 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_open_disabled@2x.pngbin0 -> 682 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_open_focus.pngbin0 -> 367 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_open_focus@2x.pngbin0 -> 665 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_open_pressed.pngbin0 -> 369 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_open_pressed@2x.pngbin0 -> 661 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_checked.pngbin0 -> 452 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_checked@2x.pngbin0 -> 825 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_checked_disabled.pngbin0 -> 467 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_checked_disabled@2x.pngbin0 -> 845 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_checked_focus.pngbin0 -> 441 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_checked_focus@2x.pngbin0 -> 823 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_checked_pressed.pngbin0 -> 418 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_checked_pressed@2x.pngbin0 -> 829 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_indeterminate.pngbin0 -> 581 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_indeterminate@2x.pngbin0 -> 1081 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_indeterminate_disabled.pngbin0 -> 614 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_indeterminate_disabled@2x.pngbin0 -> 1105 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_indeterminate_focus.pngbin0 -> 576 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_indeterminate_focus@2x.pngbin0 -> 1066 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_indeterminate_pressed.pngbin0 -> 563 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_indeterminate_pressed@2x.pngbin0 -> 1087 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_unchecked.pngbin0 -> 397 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_unchecked@2x.pngbin0 -> 828 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_unchecked_disabled.pngbin0 -> 386 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_unchecked_disabled@2x.pngbin0 -> 875 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_unchecked_focus.pngbin0 -> 394 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_unchecked_focus@2x.pngbin0 -> 866 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_unchecked_pressed.pngbin0 -> 403 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_unchecked_pressed@2x.pngbin0 -> 861 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/close-hover.pngbin0 -> 598 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/close-pressed.pngbin0 -> 598 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/close.pngbin0 -> 586 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/down_arrow.pngbin0 -> 165 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/down_arrow_disabled.pngbin0 -> 166 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/left_arrow.pngbin0 -> 166 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/left_arrow_disabled.pngbin0 -> 166 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/line_horizontal.pngbin0 -> 117 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/line_horizontal@2x.pngbin0 -> 135 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/line_horizontal_disabled.pngbin0 -> 121 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/line_horizontal_disabled@2x.pngbin0 -> 139 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/line_horizontal_focus.pngbin0 -> 120 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/line_horizontal_focus@2x.pngbin0 -> 138 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/line_horizontal_pressed.pngbin0 -> 120 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/line_horizontal_pressed@2x.pngbin0 -> 138 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/line_vertical.pngbin0 -> 130 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/line_vertical@2x.pngbin0 -> 242 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/line_vertical_disabled.pngbin0 -> 134 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/line_vertical_disabled@2x.pngbin0 -> 248 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/line_vertical_focus.pngbin0 -> 134 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/line_vertical_focus@2x.pngbin0 -> 249 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/line_vertical_pressed.pngbin0 -> 134 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/line_vertical_pressed@2x.pngbin0 -> 248 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_checked.pngbin0 -> 1224 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_checked@2x.pngbin0 -> 2714 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_checked_disabled.pngbin0 -> 1325 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_checked_disabled@2x.pngbin0 -> 2893 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_checked_focus.pngbin0 -> 1293 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_checked_focus@2x.pngbin0 -> 2736 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_checked_pressed.pngbin0 -> 1276 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_checked_pressed@2x.pngbin0 -> 2765 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_unchecked.pngbin0 -> 963 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_unchecked@2x.pngbin0 -> 2195 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_unchecked_disabled.pngbin0 -> 1040 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_unchecked_disabled@2x.pngbin0 -> 2294 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_unchecked_focus.pngbin0 -> 1032 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_unchecked_focus@2x.pngbin0 -> 2186 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_unchecked_pressed.pngbin0 -> 1022 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_unchecked_pressed@2x.pngbin0 -> 2197 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/right_arrow.pngbin0 -> 160 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/right_arrow_disabled.pngbin0 -> 160 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/sizegrip.pngbin0 -> 129 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/stylesheet-branch-end.pngbin0 -> 224 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/stylesheet-branch-more.pngbin0 -> 182 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/stylesheet-vline.pngbin0 -> 239 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_horizontal.pngbin0 -> 150 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_horizontal@2x.pngbin0 -> 304 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_horizontal_disabled.pngbin0 -> 155 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_horizontal_disabled@2x.pngbin0 -> 308 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_horizontal_focus.pngbin0 -> 154 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_horizontal_focus@2x.pngbin0 -> 311 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_horizontal_pressed.pngbin0 -> 154 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_horizontal_pressed@2x.pngbin0 -> 307 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_vertical.pngbin0 -> 137 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_vertical@2x.pngbin0 -> 201 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_vertical_disabled.pngbin0 -> 140 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_vertical_disabled@2x.pngbin0 -> 212 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_vertical_focus.pngbin0 -> 144 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_vertical_focus@2x.pngbin0 -> 211 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_vertical_pressed.pngbin0 -> 143 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_vertical_pressed@2x.pngbin0 -> 204 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_horizontal.pngbin0 -> 145 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_horizontal@2x.pngbin0 -> 286 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_horizontal_disabled.pngbin0 -> 151 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_horizontal_disabled@2x.pngbin0 -> 292 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_horizontal_focus.pngbin0 -> 149 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_horizontal_focus@2x.pngbin0 -> 294 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_horizontal_pressed.pngbin0 -> 149 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_horizontal_pressed@2x.pngbin0 -> 289 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_vertical.pngbin0 -> 133 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_vertical@2x.pngbin0 -> 191 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_vertical_disabled.pngbin0 -> 135 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_vertical_disabled@2x.pngbin0 -> 199 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_vertical_focus.pngbin0 -> 139 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_vertical_focus@2x.pngbin0 -> 196 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_vertical_pressed.pngbin0 -> 138 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_vertical_pressed@2x.pngbin0 -> 193 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/transparent.pngbin0 -> 104 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/transparent@2x.pngbin0 -> 117 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/transparent_disabled.pngbin0 -> 104 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/transparent_disabled@2x.pngbin0 -> 117 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/transparent_focus.pngbin0 -> 104 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/transparent_focus@2x.pngbin0 -> 117 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/transparent_pressed.pngbin0 -> 104 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/transparent_pressed@2x.pngbin0 -> 117 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/undock.pngbin0 -> 578 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/up_arrow.pngbin0 -> 158 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/up_arrow_disabled.pngbin0 -> 159 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/window_close.pngbin0 -> 766 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/window_close@2x.pngbin0 -> 1690 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/window_close_disabled.pngbin0 -> 838 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/window_close_disabled@2x.pngbin0 -> 1724 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/window_close_focus.pngbin0 -> 756 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/window_close_focus@2x.pngbin0 -> 1704 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/window_close_pressed.pngbin0 -> 745 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/window_close_pressed@2x.pngbin0 -> 1679 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/window_grip.pngbin0 -> 426 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/window_grip@2x.pngbin0 -> 735 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/window_grip_disabled.pngbin0 -> 447 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/window_grip_disabled@2x.pngbin0 -> 768 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/window_grip_focus.pngbin0 -> 435 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/window_grip_focus@2x.pngbin0 -> 738 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/window_grip_pressed.pngbin0 -> 444 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/window_grip_pressed@2x.pngbin0 -> 729 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/window_minimize.pngbin0 -> 193 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/window_minimize@2x.pngbin0 -> 316 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/window_minimize_disabled.pngbin0 -> 206 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/window_minimize_disabled@2x.pngbin0 -> 332 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/window_minimize_focus.pngbin0 -> 208 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/window_minimize_focus@2x.pngbin0 -> 339 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/window_minimize_pressed.pngbin0 -> 202 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/window_minimize_pressed@2x.pngbin0 -> 336 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/window_undock.pngbin0 -> 510 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/window_undock@2x.pngbin0 -> 875 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/window_undock_disabled.pngbin0 -> 541 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/window_undock_disabled@2x.pngbin0 -> 910 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/window_undock_focus.pngbin0 -> 519 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/window_undock_focus@2x.pngbin0 -> 877 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/window_undock_pressed.pngbin0 -> 523 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/rc/window_undock_pressed@2x.pngbin0 -> 880 bytes
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/style.qrc225
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/style.qss2175
-rw-r--r--src/audio_core/stream.cpp23
-rw-r--r--src/audio_core/stream.h10
-rw-r--r--src/common/alignment.h48
-rw-r--r--src/common/string_util.h12
-rw-r--r--src/core/CMakeLists.txt11
-rw-r--r--src/core/constants.h1
-rw-r--r--src/core/core.cpp4
-rw-r--r--src/core/core_timing.cpp15
-rw-r--r--src/core/core_timing.h20
-rw-r--r--src/core/cpu_manager.h10
-rw-r--r--src/core/file_sys/fsmitm_romfsbuild.cpp4
-rw-r--r--src/core/file_sys/fsmitm_romfsbuild.h2
-rw-r--r--src/core/file_sys/vfs_concat.cpp8
-rw-r--r--src/core/file_sys/vfs_concat.h6
-rw-r--r--src/core/hardware_interrupt_manager.cpp15
-rw-r--r--src/core/hle/kernel/address_arbiter.cpp1
-rw-r--r--src/core/hle/kernel/handle_table.cpp8
-rw-r--r--src/core/hle/kernel/handle_table.h7
-rw-r--r--src/core/hle/kernel/kernel.cpp24
-rw-r--r--src/core/hle/kernel/kernel.h1
-rw-r--r--src/core/hle/kernel/memory/address_space_info.cpp67
-rw-r--r--src/core/hle/kernel/memory/address_space_info.h29
-rw-r--r--src/core/hle/kernel/process.cpp2
-rw-r--r--src/core/hle/kernel/process.h12
-rw-r--r--src/core/hle/kernel/scheduler.cpp2
-rw-r--r--src/core/hle/kernel/server_session.cpp6
-rw-r--r--src/core/hle/kernel/svc.cpp7
-rw-r--r--src/core/hle/kernel/synchronization.cpp1
-rw-r--r--src/core/hle/kernel/thread.cpp24
-rw-r--r--src/core/hle/kernel/thread.h7
-rw-r--r--src/core/hle/kernel/time_manager.cpp5
-rw-r--r--src/core/hle/service/am/applets/software_keyboard.cpp61
-rw-r--r--src/core/hle/service/am/applets/software_keyboard.h1
-rw-r--r--src/core/hle/service/filesystem/filesystem.cpp4
-rw-r--r--src/core/hle/service/hid/hid.cpp17
-rw-r--r--src/core/hle/service/hid/hid.h7
-rw-r--r--src/core/hle/service/mii/manager.cpp484
-rw-r--r--src/core/hle/service/mii/manager.h331
-rw-r--r--src/core/hle/service/mii/mii.cpp315
-rw-r--r--src/core/hle/service/mii/mii_manager.cpp420
-rw-r--r--src/core/hle/service/mii/mii_manager.h273
-rw-r--r--src/core/hle/service/mii/raw_data.cpp2261
-rw-r--r--src/core/hle/service/mii/raw_data.h27
-rw-r--r--src/core/hle/service/mii/types.h67
-rw-r--r--src/core/hle/service/nvflinger/nvflinger.cpp19
-rw-r--r--src/core/memory/cheat_engine.cpp16
-rw-r--r--src/core/memory/cheat_engine.h3
-rw-r--r--src/core/memory/dmnt_cheat_vm.cpp29
-rw-r--r--src/core/memory/dmnt_cheat_vm.h14
-rw-r--r--src/core/network/network.cpp654
-rw-r--r--src/core/network/network.h87
-rw-r--r--src/core/network/sockets.h94
-rw-r--r--src/core/settings.cpp84
-rw-r--r--src/core/settings.h4
-rw-r--r--src/core/telemetry_session.cpp2
-rw-r--r--src/core/tools/freezer.cpp17
-rw-r--r--src/core/tools/freezer.h3
-rw-r--r--src/input_common/gcadapter/gc_adapter.cpp178
-rw-r--r--src/input_common/gcadapter/gc_adapter.h54
-rw-r--r--src/input_common/gcadapter/gc_poller.cpp24
-rw-r--r--src/tests/core/core_timing.cpp27
-rw-r--r--src/video_core/CMakeLists.txt4
-rw-r--r--src/video_core/buffer_cache/buffer_cache.h9
-rw-r--r--src/video_core/compatible_formats.cpp87
-rw-r--r--src/video_core/gpu.cpp2
-rw-r--r--src/video_core/gpu.h93
-rw-r--r--src/video_core/gpu_thread.cpp4
-rw-r--r--src/video_core/macro/macro.h3
-rw-r--r--src/video_core/macro/macro_hle.cpp20
-rw-r--r--src/video_core/macro/macro_jit_x64.cpp1
-rw-r--r--src/video_core/morton.cpp276
-rw-r--r--src/video_core/renderer_opengl/gl_arb_decompiler.cpp117
-rw-r--r--src/video_core/renderer_opengl/gl_buffer_cache.cpp2
-rw-r--r--src/video_core/renderer_opengl/gl_device.cpp4
-rw-r--r--src/video_core/renderer_opengl/gl_device.h10
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp125
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h14
-rw-r--r--src/video_core/renderer_opengl/gl_resource_manager.h6
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.cpp184
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.h36
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp26
-rw-r--r--src/video_core/renderer_opengl/gl_shader_manager.cpp71
-rw-r--r--src/video_core/renderer_opengl/gl_shader_manager.h17
-rw-r--r--src/video_core/renderer_opengl/gl_stream_buffer.cpp2
-rw-r--r--src/video_core/renderer_opengl/gl_texture_cache.cpp162
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp4
-rw-r--r--src/video_core/renderer_vulkan/fixed_pipeline_state.cpp1
-rw-r--r--src/video_core/renderer_vulkan/maxwell_to_vk.cpp173
-rw-r--r--src/video_core/renderer_vulkan/vk_blit_screen.cpp722
-rw-r--r--src/video_core/renderer_vulkan/vk_buffer_cache.cpp63
-rw-r--r--src/video_core/renderer_vulkan/vk_compute_pass.cpp194
-rw-r--r--src/video_core/renderer_vulkan/vk_compute_pipeline.cpp131
-rw-r--r--src/video_core/renderer_vulkan/vk_descriptor_pool.cpp33
-rw-r--r--src/video_core/renderer_vulkan/vk_device.cpp281
-rw-r--r--src/video_core/renderer_vulkan/vk_device.h5
-rw-r--r--src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp423
-rw-r--r--src/video_core/renderer_vulkan/vk_image.cpp38
-rw-r--r--src/video_core/renderer_vulkan/vk_memory_manager.cpp13
-rw-r--r--src/video_core/renderer_vulkan/vk_pipeline_cache.cpp66
-rw-r--r--src/video_core/renderer_vulkan/vk_query_cache.cpp16
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.cpp92
-rw-r--r--src/video_core/renderer_vulkan/vk_renderpass_cache.cpp129
-rw-r--r--src/video_core/renderer_vulkan/vk_resource_manager.cpp29
-rw-r--r--src/video_core/renderer_vulkan/vk_sampler_cache.cpp51
-rw-r--r--src/video_core/renderer_vulkan/vk_scheduler.cpp57
-rw-r--r--src/video_core/renderer_vulkan/vk_shader_decompiler.cpp17
-rw-r--r--src/video_core/renderer_vulkan/vk_shader_util.cpp14
-rw-r--r--src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp25
-rw-r--r--src/video_core/renderer_vulkan/vk_state_tracker.cpp1
-rw-r--r--src/video_core/renderer_vulkan/vk_stream_buffer.cpp35
-rw-r--r--src/video_core/renderer_vulkan/vk_swapchain.cpp94
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.cpp251
-rw-r--r--src/video_core/renderer_vulkan/wrapper.cpp120
-rw-r--r--src/video_core/shader/async_shaders.cpp181
-rw-r--r--src/video_core/shader/async_shaders.h109
-rw-r--r--src/video_core/shader/decode/arithmetic_integer.cpp6
-rw-r--r--src/video_core/shader/decode/image.cpp54
-rw-r--r--src/video_core/shader/decode/other.cpp3
-rw-r--r--src/video_core/shader/decode/video.cpp19
-rw-r--r--src/video_core/shader/decode/xmad.cpp15
-rw-r--r--src/video_core/shader/shader_ir.cpp4
-rw-r--r--src/video_core/shader_cache.h4
-rw-r--r--src/video_core/shader_notify.cpp42
-rw-r--r--src/video_core/shader_notify.h29
-rw-r--r--src/video_core/surface.cpp257
-rw-r--r--src/video_core/surface.h770
-rw-r--r--src/video_core/texture_cache/format_lookup_table.cpp149
-rw-r--r--src/video_core/texture_cache/surface_base.cpp2
-rw-r--r--src/video_core/texture_cache/surface_params.cpp18
-rw-r--r--src/video_core/texture_cache/texture_cache.h8
-rw-r--r--src/video_core/textures/convert.cpp6
-rw-r--r--src/video_core/textures/decoders.cpp89
-rw-r--r--src/video_core/textures/decoders.h4
-rw-r--r--src/video_core/textures/texture.h49
-rw-r--r--src/yuzu/CMakeLists.txt33
-rw-r--r--src/yuzu/configuration/config.cpp8
-rw-r--r--src/yuzu/configuration/configuration_shared.cpp74
-rw-r--r--src/yuzu/configuration/configuration_shared.h20
-rw-r--r--src/yuzu/configuration/configure_audio.cpp23
-rw-r--r--src/yuzu/configuration/configure_audio.h6
-rw-r--r--src/yuzu/configuration/configure_audio.ui151
-rw-r--r--src/yuzu/configuration/configure_dialog.cpp9
-rw-r--r--src/yuzu/configuration/configure_dialog.h6
-rw-r--r--src/yuzu/configuration/configure_general.cpp37
-rw-r--r--src/yuzu/configuration/configure_general.h7
-rw-r--r--src/yuzu/configuration/configure_graphics.cpp54
-rw-r--r--src/yuzu/configuration/configure_graphics.h7
-rw-r--r--src/yuzu/configuration/configure_graphics.ui282
-rw-r--r--src/yuzu/configuration/configure_graphics_advanced.cpp68
-rw-r--r--src/yuzu/configuration/configure_graphics_advanced.h10
-rw-r--r--src/yuzu/configuration/configure_graphics_advanced.ui164
-rw-r--r--src/yuzu/configuration/configure_system.cpp115
-rw-r--r--src/yuzu/configuration/configure_system.h7
-rw-r--r--src/yuzu/configuration/configure_system.ui972
-rw-r--r--src/yuzu/configuration/configure_ui.cpp31
-rw-r--r--src/yuzu/configuration/configure_ui.h7
-rw-r--r--src/yuzu/configuration/configure_ui.ui188
-rw-r--r--src/yuzu/debugger/wait_tree.cpp55
-rw-r--r--src/yuzu/main.cpp96
-rw-r--r--src/yuzu/main.h6
-rw-r--r--src/yuzu/uisettings.cpp2
-rw-r--r--src/yuzu/uisettings.h3
-rw-r--r--src/yuzu_cmd/config.cpp4
-rw-r--r--src/yuzu_cmd/default_ini.h4
421 files changed, 12409 insertions, 5086 deletions
diff --git a/.ci/scripts/linux/docker.sh b/.ci/scripts/linux/docker.sh
index 5559a527c..277775ef6 100755
--- a/.ci/scripts/linux/docker.sh
+++ b/.ci/scripts/linux/docker.sh
@@ -5,7 +5,7 @@ cd /yuzu
5ccache -s 5ccache -s
6 6
7mkdir build || true && cd build 7mkdir build || true && cd build
8cmake .. -G Ninja -DDISPLAY_VERSION=$1 -DYUZU_USE_BUNDLED_UNICORN=ON -DYUZU_USE_QT_WEB_ENGINE=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=/usr/lib/ccache/gcc -DCMAKE_CXX_COMPILER=/usr/lib/ccache/g++ -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DUSE_DISCORD_PRESENCE=ON 8cmake .. -G Ninja -DDISPLAY_VERSION=$1 -DYUZU_USE_BUNDLED_UNICORN=ON -DYUZU_USE_QT_WEB_ENGINE=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=/usr/lib/ccache/gcc -DCMAKE_CXX_COMPILER=/usr/lib/ccache/g++ -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DUSE_DISCORD_PRESENCE=ON -DENABLE_QT_TRANSLATION=ON
9 9
10ninja 10ninja
11 11
diff --git a/.ci/scripts/windows/docker.sh b/.ci/scripts/windows/docker.sh
index d53281741..adfd636fa 100755
--- a/.ci/scripts/windows/docker.sh
+++ b/.ci/scripts/windows/docker.sh
@@ -5,7 +5,7 @@ cd /yuzu
5ccache -s 5ccache -s
6 6
7mkdir build || true && cd build 7mkdir build || true && cd build
8cmake .. -G Ninja -DDISPLAY_VERSION=$1 -DCMAKE_TOOLCHAIN_FILE="$(pwd)/../CMakeModules/MinGWCross.cmake" -DUSE_CCACHE=ON -DYUZU_USE_BUNDLED_UNICORN=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DCMAKE_BUILD_TYPE=Release 8cmake .. -G Ninja -DDISPLAY_VERSION=$1 -DCMAKE_TOOLCHAIN_FILE="$(pwd)/../CMakeModules/MinGWCross.cmake" -DUSE_CCACHE=ON -DYUZU_USE_BUNDLED_UNICORN=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DCMAKE_BUILD_TYPE=Release -DENABLE_QT_TRANSLATION=ON
9ninja 9ninja
10 10
11ccache -s 11ccache -s
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ce46a2c2b..7a49318aa 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -13,6 +13,7 @@ project(yuzu)
13option(ENABLE_SDL2 "Enable the SDL2 frontend" ON) 13option(ENABLE_SDL2 "Enable the SDL2 frontend" ON)
14 14
15option(ENABLE_QT "Enable the Qt frontend" ON) 15option(ENABLE_QT "Enable the Qt frontend" ON)
16option(ENABLE_QT_TRANSLATION "Enable translations for the Qt frontend" OFF)
16CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_QT "Download bundled Qt binaries" ON "ENABLE_QT;MSVC" OFF) 17CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_QT "Download bundled Qt binaries" ON "ENABLE_QT;MSVC" OFF)
17 18
18option(ENABLE_WEB_SERVICE "Enable web services (telemetry, etc.)" ON) 19option(ENABLE_WEB_SERVICE "Enable web services (telemetry, etc.)" ON)
@@ -224,6 +225,10 @@ if(ENABLE_QT)
224 if (YUZU_USE_QT_WEB_ENGINE) 225 if (YUZU_USE_QT_WEB_ENGINE)
225 find_package(Qt5 COMPONENTS WebEngineCore WebEngineWidgets) 226 find_package(Qt5 COMPONENTS WebEngineCore WebEngineWidgets)
226 endif() 227 endif()
228
229 if (ENABLE_QT_TRANSLATION)
230 find_package(Qt5 REQUIRED COMPONENTS LinguistTools ${QT_PREFIX_HINT})
231 endif()
227 if (NOT Qt5_FOUND) 232 if (NOT Qt5_FOUND)
228 list(APPEND CONAN_REQUIRED_LIBS "qt/5.14.1@bincrafters/stable") 233 list(APPEND CONAN_REQUIRED_LIBS "qt/5.14.1@bincrafters/stable")
229 endif() 234 endif()
diff --git a/README.md b/README.md
index e4ecb531d..981c8ef24 100644
--- a/README.md
+++ b/README.md
@@ -24,6 +24,8 @@ Most of the development happens on GitHub. It's also where [our central reposito
24 24
25If you want to contribute please take a look at the [Contributor's Guide](https://github.com/yuzu-emu/yuzu/wiki/Contributing) and [Developer Information](https://github.com/yuzu-emu/yuzu/wiki/Developer-Information). You should also contact any of the developers on Discord in order to know about the current state of the emulator. 25If you want to contribute please take a look at the [Contributor's Guide](https://github.com/yuzu-emu/yuzu/wiki/Contributing) and [Developer Information](https://github.com/yuzu-emu/yuzu/wiki/Developer-Information). You should also contact any of the developers on Discord in order to know about the current state of the emulator.
26 26
27If you want to contribute to the user interface translation, please check out the [yuzu project on transifex](https://www.transifex.com/yuzu-emulator/yuzu). We centralize translation work there, and periodically upstream translations.
28
27### Building 29### Building
28 30
29* __Windows__: [Windows Build](https://github.com/yuzu-emu/yuzu/wiki/Building-For-Windows) 31* __Windows__: [Windows Build](https://github.com/yuzu-emu/yuzu/wiki/Building-For-Windows)
diff --git a/dist/languages/.gitignore b/dist/languages/.gitignore
new file mode 100644
index 000000000..27e5a0158
--- /dev/null
+++ b/dist/languages/.gitignore
@@ -0,0 +1,2 @@
1# Ignore the source language file
2en.ts
diff --git a/dist/languages/.tx/config b/dist/languages/.tx/config
new file mode 100644
index 000000000..0d9b512ea
--- /dev/null
+++ b/dist/languages/.tx/config
@@ -0,0 +1,8 @@
1[main]
2host = https://www.transifex.com
3
4[yuzu.emulator]
5file_filter = <lang>.ts
6source_file = en.ts
7source_lang = en
8type = QT
diff --git a/dist/languages/README.md b/dist/languages/README.md
new file mode 100644
index 000000000..61981ab1d
--- /dev/null
+++ b/dist/languages/README.md
@@ -0,0 +1 @@
This directory stores translation patches (TS files) for yuzu Qt frontend. This directory is linked with [yuzu project on transifex](https://www.transifex.com/yuzu-emulator/yuzu), so you can update the translation by executing `tx pull -a`. If you want to contribute to the translation, please go the transifex link and submit your translation there. This directory on the main repo will be synchronized with transifex periodically. Do not directly open PRs on github to modify the translation.
diff --git a/dist/qt_themes/colorful_midnight_blue/icons/16x16/lock.png b/dist/qt_themes/colorful_midnight_blue/icons/16x16/lock.png
new file mode 100644
index 000000000..32c505848
--- /dev/null
+++ b/dist/qt_themes/colorful_midnight_blue/icons/16x16/lock.png
Binary files differ
diff --git a/dist/qt_themes/colorful_midnight_blue/icons/index.theme b/dist/qt_themes/colorful_midnight_blue/icons/index.theme
new file mode 100644
index 000000000..e23bfe6f9
--- /dev/null
+++ b/dist/qt_themes/colorful_midnight_blue/icons/index.theme
@@ -0,0 +1,8 @@
1[Icon Theme]
2Name=colorful_midnight_blue
3Comment=Colorful theme (Midnight Blue style)
4Inherits=default
5Directories=16x16
6
7[16x16]
8Size=16
diff --git a/dist/qt_themes/colorful_midnight_blue/style.qrc b/dist/qt_themes/colorful_midnight_blue/style.qrc
new file mode 100644
index 000000000..fd33bc850
--- /dev/null
+++ b/dist/qt_themes/colorful_midnight_blue/style.qrc
@@ -0,0 +1,57 @@
1<RCC>
2 <qresource prefix="icons/colorful_midnight_blue">
3 <file alias="index.theme">icons/index.theme</file>
4 <file alias="16x16/lock.png">icons/16x16/lock.png</file>
5 <file alias="48x48/bad_folder.png">../colorful/icons/48x48/bad_folder.png</file>
6 <file alias="48x48/chip.png">../colorful/icons/48x48/chip.png</file>
7 <file alias="48x48/folder.png">../colorful/icons/48x48/folder.png</file>
8 <file alias="48x48/plus.png">../colorful/icons/48x48/plus.png</file>
9 <file alias="48x48/sd_card.png">../colorful/icons/48x48/sd_card.png</file>
10 <file alias="256x256/plus_folder.png">../colorful/icons/256x256/plus_folder.png</file>
11 </qresource>
12
13 <qresource prefix="qss_icons">
14 <file alias="rc/up_arrow_disabled.png">../qdarkstyle_midnight_blue/rc/up_arrow_disabled.png</file>
15 <file alias="rc/Hmovetoolbar.png">../qdarkstyle_midnight_blue/rc/Hmovetoolbar.png</file>
16 <file alias="rc/stylesheet-branch-end.png">../qdarkstyle_midnight_blue/rc/stylesheet-branch-end.png</file>
17 <file alias="rc/branch_closed-on.png">../qdarkstyle_midnight_blue/rc/branch_closed-on.png</file>
18 <file alias="rc/stylesheet-vline.png">../qdarkstyle_midnight_blue/rc/stylesheet-vline.png</file>
19 <file alias="rc/branch_closed.png">../qdarkstyle_midnight_blue/rc/branch_closed.png</file>
20 <file alias="rc/branch_open-on.png">../qdarkstyle_midnight_blue/rc/branch_open-on.png</file>
21 <file alias="rc/transparent.png">../qdarkstyle_midnight_blue/rc/transparent.png</file>
22 <file alias="rc/right_arrow_disabled.png">../qdarkstyle_midnight_blue/rc/right_arrow_disabled.png</file>
23 <file alias="rc/sizegrip.png">../qdarkstyle_midnight_blue/rc/sizegrip.png</file>
24 <file alias="rc/close.png">../qdarkstyle_midnight_blue/rc/close.png</file>
25 <file alias="rc/close-hover.png">../qdarkstyle_midnight_blue/rc/close-hover.png</file>
26 <file alias="rc/close-pressed.png">../qdarkstyle_midnight_blue/rc/close-pressed.png</file>
27 <file alias="rc/down_arrow.png">../qdarkstyle_midnight_blue/rc/down_arrow.png</file>
28 <file alias="rc/Vmovetoolbar.png">../qdarkstyle_midnight_blue/rc/Vmovetoolbar.png</file>
29 <file alias="rc/left_arrow.png">../qdarkstyle_midnight_blue/rc/left_arrow.png</file>
30 <file alias="rc/stylesheet-branch-more.png">../qdarkstyle_midnight_blue/rc/stylesheet-branch-more.png</file>
31 <file alias="rc/up_arrow.png">../qdarkstyle_midnight_blue/rc/up_arrow.png</file>
32 <file alias="rc/right_arrow.png">../qdarkstyle_midnight_blue/rc/right_arrow.png</file>
33 <file alias="rc/left_arrow_disabled.png">../qdarkstyle_midnight_blue/rc/left_arrow_disabled.png</file>
34 <file alias="rc/Hsepartoolbar.png">../qdarkstyle_midnight_blue/rc/Hsepartoolbar.png</file>
35 <file alias="rc/branch_open.png">../qdarkstyle_midnight_blue/rc/branch_open.png</file>
36 <file alias="rc/Vsepartoolbar.png">../qdarkstyle_midnight_blue/rc/Vsepartoolbar.png</file>
37 <file alias="rc/down_arrow_disabled.png">../qdarkstyle_midnight_blue/rc/down_arrow_disabled.png</file>
38 <file alias="rc/undock.png">../qdarkstyle_midnight_blue/rc/undock.png</file>
39 <file alias="rc/checkbox_checked_disabled.png">../qdarkstyle_midnight_blue/rc/checkbox_checked_disabled.png</file>
40 <file alias="rc/checkbox_checked_focus.png">../qdarkstyle_midnight_blue/rc/checkbox_checked_focus.png</file>
41 <file alias="rc/checkbox_checked.png">../qdarkstyle_midnight_blue/rc/checkbox_checked.png</file>
42 <file alias="rc/checkbox_indeterminate.png">../qdarkstyle_midnight_blue/rc/checkbox_indeterminate.png</file>
43 <file alias="rc/checkbox_indeterminate_focus.png">../qdarkstyle_midnight_blue/rc/checkbox_indeterminate_focus.png</file>
44 <file alias="rc/checkbox_unchecked_disabled.png">../qdarkstyle_midnight_blue/rc/checkbox_unchecked_disabled.png</file>
45 <file alias="rc/checkbox_unchecked_focus.png">../qdarkstyle_midnight_blue/rc/checkbox_unchecked_focus.png</file>
46 <file alias="rc/checkbox_unchecked.png">../qdarkstyle_midnight_blue/rc/checkbox_unchecked.png</file>
47 <file alias="rc/radio_checked_disabled.png">../qdarkstyle_midnight_blue/rc/radio_checked_disabled.png</file>
48 <file alias="rc/radio_checked_focus.png">../qdarkstyle_midnight_blue/rc/radio_checked_focus.png</file>
49 <file alias="rc/radio_checked.png">../qdarkstyle_midnight_blue/rc/radio_checked.png</file>
50 <file alias="rc/radio_unchecked_disabled.png">../qdarkstyle_midnight_blue/rc/radio_unchecked_disabled.png</file>
51 <file alias="rc/radio_unchecked_focus.png">../qdarkstyle_midnight_blue/rc/radio_unchecked_focus.png</file>
52 <file alias="rc/radio_unchecked.png">../qdarkstyle_midnight_blue/rc/radio_unchecked.png</file>
53 </qresource>
54 <qresource prefix="colorful_midnight_blue">
55 <file alias="style.qss">../qdarkstyle_midnight_blue/style.qss</file>
56 </qresource>
57</RCC>
diff --git a/dist/qt_themes/qdarkstyle/rc/checkbox_checked.png b/dist/qt_themes/qdarkstyle/rc/checkbox_checked.png
index 830cfee65..dd891298f 100644
--- a/dist/qt_themes/qdarkstyle/rc/checkbox_checked.png
+++ b/dist/qt_themes/qdarkstyle/rc/checkbox_checked.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle/rc/checkbox_checked_disabled.png b/dist/qt_themes/qdarkstyle/rc/checkbox_checked_disabled.png
index cb63cc2fa..44bf145f8 100644
--- a/dist/qt_themes/qdarkstyle/rc/checkbox_checked_disabled.png
+++ b/dist/qt_themes/qdarkstyle/rc/checkbox_checked_disabled.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle/rc/checkbox_checked_focus.png b/dist/qt_themes/qdarkstyle/rc/checkbox_checked_focus.png
index 671be273b..60238b21d 100644
--- a/dist/qt_themes/qdarkstyle/rc/checkbox_checked_focus.png
+++ b/dist/qt_themes/qdarkstyle/rc/checkbox_checked_focus.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle/rc/checkbox_indeterminate.png b/dist/qt_themes/qdarkstyle/rc/checkbox_indeterminate.png
index 41024f768..830cfee65 100644
--- a/dist/qt_themes/qdarkstyle/rc/checkbox_indeterminate.png
+++ b/dist/qt_themes/qdarkstyle/rc/checkbox_indeterminate.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle/rc/checkbox_indeterminate_disabled.png b/dist/qt_themes/qdarkstyle/rc/checkbox_indeterminate_disabled.png
index abdc01d90..cb63cc2fa 100644
--- a/dist/qt_themes/qdarkstyle/rc/checkbox_indeterminate_disabled.png
+++ b/dist/qt_themes/qdarkstyle/rc/checkbox_indeterminate_disabled.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle/rc/checkbox_indeterminate_focus.png b/dist/qt_themes/qdarkstyle/rc/checkbox_indeterminate_focus.png
index 415f9b6e1..671be273b 100644
--- a/dist/qt_themes/qdarkstyle/rc/checkbox_indeterminate_focus.png
+++ b/dist/qt_themes/qdarkstyle/rc/checkbox_indeterminate_focus.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/LICENSE.rst b/dist/qt_themes/qdarkstyle_midnight_blue/LICENSE.rst
new file mode 100644
index 000000000..e22b68735
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/LICENSE.rst
@@ -0,0 +1,405 @@
1License
2=======
3
4The MIT License (MIT) - Code
5----------------------------
6
7Copyright (c) 2013-2019 Colin Duquesnoy
8
9Permission is hereby granted, free of charge, to any person obtaining a
10copy of this software and associated documentation files (the
11"Software"), to deal in the Software without restriction, including
12without limitation the rights to use, copy, modify, merge, publish,
13distribute, sublicense, and/or sell copies of the Software, and to
14permit persons to whom the Software is furnished to do so, subject to
15the following conditions:
16
17The above copyright notice and this permission notice shall be included
18in all copies or substantial portions of the Software.
19
20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
24CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
28
29Creative Commons Attribution International 4.0 - Images
30-------------------------------------------------------
31
32QDarkStyle (c) 2013-2019 Colin Duquesnoy
33QDarkStyle (c) 2019-2019 Daniel Cosmo Pizetta
34
35Creative Commons Corporation (“Creative Commons”) is not a law firm and
36does not provide legal services or legal advice. Distribution of
37Creative Commons public licenses does not create a lawyer-client or
38other relationship. Creative Commons makes its licenses and related
39information available on an “as-is” basis. Creative Commons gives no
40warranties regarding its licenses, any material licensed under their
41terms and conditions, or any related information. Creative Commons
42disclaims all liability for damages resulting from their use to the
43fullest extent possible.
44
45Using Creative Commons Public Licenses
46~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
47
48Creative Commons public licenses provide a standard set of terms and
49conditions that creators and other rights holders may use to share
50original works of authorship and other material subject to copyright and
51certain other rights specified in the public license below. The
52following considerations are for informational purposes only, are not
53exhaustive, and do not form part of our licenses.
54
55- **Considerations for licensors:** Our public licenses are intended
56 for use by those authorized to give the public permission to use
57 material in ways otherwise restricted by copyright and certain other
58 rights. Our licenses are irrevocable. Licensors should read and
59 understand the terms and conditions of the license they choose before
60 applying it. Licensors should also secure all rights necessary before
61 applying our licenses so that the public can reuse the material as
62 expected. Licensors should clearly mark any material not subject to
63 the license. This includes other CC-licensed material, or material
64 used under an exception or limitation to copyright. `More
65 considerations for
66 licensors <http://wiki.creativecommons.org/Considerations_for_licensors_and_licensees#Considerations_for_licensors>`__.
67
68- **Considerations for the public:** By using one of our public
69 licenses, a licensor grants the public permission to use the licensed
70 material under specified terms and conditions. If the licensor’s
71 permission is not necessary for any reason–for example, because of
72 any applicable exception or limitation to copyright–then that use is
73 not regulated by the license. Our licenses grant only permissions
74 under copyright and certain other rights that a licensor has
75 authority to grant. Use of the licensed material may still be
76 restricted for other reasons, including because others have copyright
77 or other rights in the material. A licensor may make special
78 requests, such as asking that all changes be marked or described.
79 Although not required by our licenses, you are encouraged to respect
80 those requests where reasonable. `More considerations for the
81 public <http://wiki.creativecommons.org/Considerations_for_licensors_and_licensees#Considerations_for_licensees>`__.
82
83
84Creative Commons Attribution 4.0 International Public License
85-------------------------------------------------------------
86
87By exercising the Licensed Rights (defined below), You accept and agree
88to be bound by the terms and conditions of this Creative Commons
89Attribution 4.0 International Public License ("Public License"). To the
90extent this Public License may be interpreted as a contract, You are
91granted the Licensed Rights in consideration of Your acceptance of these
92terms and conditions, and the Licensor grants You such rights in
93consideration of benefits the Licensor receives from making the Licensed
94Material available under these terms and conditions.
95
96Section 1 – Definitions
97~~~~~~~~~~~~~~~~~~~~~~~
98
99a. **Adapted Material** means material subject to Copyright and Similar
100 Rights that is derived from or based upon the Licensed Material and
101 in which the Licensed Material is translated, altered, arranged,
102 transformed, or otherwise modified in a manner requiring permission
103 under the Copyright and Similar Rights held by the Licensor. For
104 purposes of this Public License, where the Licensed Material is a
105 musical work, performance, or sound recording, Adapted Material is
106 always produced where the Licensed Material is synched in timed
107 relation with a moving image.
108
109b. **Adapter's License** means the license You apply to Your Copyright
110 and Similar Rights in Your contributions to Adapted Material in
111 accordance with the terms and conditions of this Public License.
112
113c. **Copyright and Similar Rights** means copyright and/or similar
114 rights closely related to copyright including, without limitation,
115 performance, broadcast, sound recording, and Sui Generis Database
116 Rights, without regard to how the rights are labeled or categorized.
117 For purposes of this Public License, the rights specified in Section
118 2(b)(1)-(2) are not Copyright and Similar Rights.
119
120d. **Effective Technological Measures** means those measures that, in
121 the absence of proper authority, may not be circumvented under laws
122 fulfilling obligations under Article 11 of the WIPO Copyright Treaty
123 adopted on December 20, 1996, and/or similar international
124 agreements.
125
126e. **Exceptions and Limitations** means fair use, fair dealing, and/or
127 any other exception or limitation to Copyright and Similar Rights
128 that applies to Your use of the Licensed Material.
129
130f. **Licensed Material** means the artistic or literary work, database,
131 or other material to which the Licensor applied this Public License.
132
133g. **Licensed Rights** means the rights granted to You subject to the
134 terms and conditions of this Public License, which are limited to all
135 Copyright and Similar Rights that apply to Your use of the Licensed
136 Material and that the Licensor has authority to license.
137
138h. **Licensor** means the individual(s) or entity(ies) granting rights
139 under this Public License.
140
141i. **Share** means to provide material to the public by any means or
142 process that requires permission under the Licensed Rights, such as
143 reproduction, public display, public performance, distribution,
144 dissemination, communication, or importation, and to make material
145 available to the public including in ways that members of the public
146 may access the material from a place and at a time individually
147 chosen by them.
148
149j. **Sui Generis Database Rights** means rights other than copyright
150 resulting from Directive 96/9/EC of the European Parliament and of
151 the Council of 11 March 1996 on the legal protection of databases, as
152 amended and/or succeeded, as well as other essentially equivalent
153 rights anywhere in the world.
154
155k. **You** means the individual or entity exercising the Licensed Rights
156 under this Public License. Your has a corresponding meaning.
157
158Section 2 – Scope
159~~~~~~~~~~~~~~~~~
160
161a. **License grant.**
162
1631. Subject to the terms and conditions of this Public License, the
164 Licensor hereby grants You a worldwide, royalty-free,
165 non-sublicensable, non-exclusive, irrevocable license to exercise the
166 Licensed Rights in the Licensed Material to:
167
168 A. reproduce and Share the Licensed Material, in whole or in part;
169 and
170
171 B. produce, reproduce, and Share Adapted Material.
172
1732. **Exceptions and Limitations.** For the avoidance of doubt, where
174 Exceptions and Limitations apply to Your use, this Public License
175 does not apply, and You do not need to comply with its terms and
176 conditions.
177
1783. **Term.** The term of this Public License is specified in Section
179 6(a).
180
1814. **Media and formats; technical modifications allowed.** The Licensor
182 authorizes You to exercise the Licensed Rights in all media and
183 formats whether now known or hereafter created, and to make technical
184 modifications necessary to do so. The Licensor waives and/or agrees
185 not to assert any right or authority to forbid You from making
186 technical modifications necessary to exercise the Licensed Rights,
187 including technical modifications necessary to circumvent Effective
188 Technological Measures. For purposes of this Public License, simply
189 making modifications authorized by this Section 2(a)(4) never
190 produces Adapted Material.
191
1925. **Downstream recipients.**
193
194 A. **Offer from the Licensor – Licensed Material.** Every recipient
195 of the Licensed Material automatically receives an offer from the
196 Licensor to exercise the Licensed Rights under the terms and
197 conditions of this Public License.
198
199 B. **No downstream restrictions.** You may not offer or impose any
200 additional or different terms or conditions on, or apply any
201 Effective Technological Measures to, the Licensed Material if doing
202 so restricts exercise of the Licensed Rights by any recipient of the
203 Licensed Material.
204
2056. **No endorsement.** Nothing in this Public License constitutes or may
206 be construed as permission to assert or imply that You are, or that
207 Your use of the Licensed Material is, connected with, or sponsored,
208 endorsed, or granted official status by, the Licensor or others
209 designated to receive attribution as provided in Section
210 3(a)(1)(A)(i).
211
212b. **Other rights.**
213
2141. Moral rights, such as the right of integrity, are not licensed under
215 this Public License, nor are publicity, privacy, and/or other similar
216 personality rights; however, to the extent possible, the Licensor
217 waives and/or agrees not to assert any such rights held by the
218 Licensor to the limited extent necessary to allow You to exercise the
219 Licensed Rights, but not otherwise.
220
2212. Patent and trademark rights are not licensed under this Public
222 License.
223
2243. To the extent possible, the Licensor waives any right to collect
225 royalties from You for the exercise of the Licensed Rights, whether
226 directly or through a collecting society under any voluntary or
227 waivable statutory or compulsory licensing scheme. In all other cases
228 the Licensor expressly reserves any right to collect such royalties.
229
230Section 3 – License Conditions
231~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
232
233Your exercise of the Licensed Rights is expressly made subject to the
234following conditions.
235
236a. **Attribution.**
237
2381. If You Share the Licensed Material (including in modified form), You
239 must:
240
241 A. retain the following if it is supplied by the Licensor with the
242 Licensed Material:
243
244 i. identification of the creator(s) of the Licensed Material and any
245 others designated to receive attribution, in any reasonable manner
246 requested by the Licensor (including by pseudonym if designated);
247
248 ii. a copyright notice;
249
250 iii. a notice that refers to this Public License;
251
252 iv. a notice that refers to the disclaimer of warranties;
253
254 v. a URI or hyperlink to the Licensed Material to the extent reasonably practicable;
255
256 B. indicate if You modified the Licensed Material and retain an
257 indication of any previous modifications; and
258
259 C. indicate the Licensed Material is licensed under this Public
260 License, and include the text of, or the URI or hyperlink to, this
261 Public License.
262
2632. You may satisfy the conditions in Section 3(a)(1) in any reasonable
264 manner based on the medium, means, and context in which You Share the
265 Licensed Material. For example, it may be reasonable to satisfy the
266 conditions by providing a URI or hyperlink to a resource that
267 includes the required information.
268
2693. If requested by the Licensor, You must remove any of the information
270 required by Section 3(a)(1)(A) to the extent reasonably practicable.
271
2724. If You Share Adapted Material You produce, the Adapter's License You
273 apply must not prevent recipients of the Adapted Material from
274 complying with this Public License.
275
276Section 4 – Sui Generis Database Rights
277~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
278
279Where the Licensed Rights include Sui Generis Database Rights that apply
280to Your use of the Licensed Material:
281
282a. for the avoidance of doubt, Section 2(a)(1) grants You the right to
283 extract, reuse, reproduce, and Share all or a substantial portion of
284 the contents of the database;
285
286b. if You include all or a substantial portion of the database contents
287 in a database in which You have Sui Generis Database Rights, then the
288 database in which You have Sui Generis Database Rights (but not its
289 individual contents) is Adapted Material; and
290
291c. You must comply with the conditions in Section 3(a) if You Share all
292 or a substantial portion of the contents of the database.
293
294For the avoidance of doubt, this Section 4 supplements and does not
295replace Your obligations under this Public License where the Licensed
296Rights include other Copyright and Similar Rights.
297
298Section 5 – Disclaimer of Warranties and Limitation of Liability
299~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
300
301a. Unless otherwise separately undertaken by the Licensor, to the
302 extent possible, the Licensor offers the Licensed Material as-is and
303 as-available, and makes no representations or warranties of any kind
304 concerning the Licensed Material, whether express, implied,
305 statutory, or other. This includes, without limitation, warranties of
306 title, merchantability, fitness for a particular purpose,
307 non-infringement, absence of latent or other defects, accuracy, or
308 the presence or absence of errors, whether or not known or
309 discoverable. Where disclaimers of warranties are not allowed in full
310 or in part, this disclaimer may not apply to You.
311
312b. To the extent possible, in no event will the Licensor be liable to
313 You on any legal theory (including, without limitation, negligence)
314 or otherwise for any direct, special, indirect, incidental,
315 consequential, punitive, exemplary, or other losses, costs, expenses,
316 or damages arising out of this Public License or use of the Licensed
317 Material, even if the Licensor has been advised of the possibility of
318 such losses, costs, expenses, or damages. Where a limitation of
319 liability is not allowed in full or in part, this limitation may not
320 apply to You.
321
322c. The disclaimer of warranties and limitation of liability provided
323 above shall be interpreted in a manner that, to the extent possible,
324 most closely approximates an absolute disclaimer and waiver of all
325 liability.
326
327Section 6 – Term and Termination
328~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
329
330a. This Public License applies for the term of the Copyright and Similar
331 Rights licensed here. However, if You fail to comply with this Public
332 License, then Your rights under this Public License terminate
333 automatically.
334
335b. Where Your right to use the Licensed Material has terminated under
336 Section 6(a), it reinstates:
337
3381. automatically as of the date the violation is cured, provided it is
339 cured within 30 days of Your discovery of the violation; or
340
3412. upon express reinstatement by the Licensor.
342
343For the avoidance of doubt, this Section 6(b) does not affect any right
344the Licensor may have to seek remedies for Your violations of this
345Public License.
346
347c. For the avoidance of doubt, the Licensor may also offer the Licensed
348 Material under separate terms or conditions or stop distributing the
349 Licensed Material at any time; however, doing so will not terminate
350 this Public License.
351
352d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
353 License.
354
355Section 7 – Other Terms and Conditions
356~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
357
358a. The Licensor shall not be bound by any additional or different terms
359 or conditions communicated by You unless expressly agreed.
360
361b. Any arrangements, understandings, or agreements regarding the
362 Licensed Material not stated herein are separate from and independent
363 of the terms and conditions of this Public License.
364
365Section 8 – Interpretation
366~~~~~~~~~~~~~~~~~~~~~~~~~~
367
368a. For the avoidance of doubt, this Public License does not, and shall
369 not be interpreted to, reduce, limit, restrict, or impose conditions
370 on any use of the Licensed Material that could lawfully be made
371 without permission under this Public License.
372
373b. To the extent possible, if any provision of this Public License is
374 deemed unenforceable, it shall be automatically reformed to the
375 minimum extent necessary to make it enforceable. If the provision
376 cannot be reformed, it shall be severed from this Public License
377 without affecting the enforceability of the remaining terms and
378 conditions.
379
380c. No term or condition of this Public License will be waived and no
381 failure to comply consented to unless expressly agreed to by the
382 Licensor.
383
384d. Nothing in this Public License constitutes or may be interpreted as a
385 limitation upon, or waiver of, any privileges and immunities that
386 apply to the Licensor or You, including from the legal processes of
387 any jurisdiction or authority.
388
389 Creative Commons is not a party to its public licenses.
390 Notwithstanding, Creative Commons may elect to apply one of its
391 public licenses to material it publishes and in those instances will
392 be considered the “Licensor.” Except for the limited purpose of
393 indicating that material is shared under a Creative Commons public
394 license or as otherwise permitted by the Creative Commons policies
395 published at
396 `creativecommons.org/policies <http://creativecommons.org/policies>`__,
397 Creative Commons does not authorize the use of the trademark
398 “Creative Commons” or any other trademark or logo of Creative
399 Commons without its prior written consent including, without
400 limitation, in connection with any unauthorized modifications to any
401 of its public licenses or any other arrangements, understandings, or
402 agreements concerning use of licensed material. For the avoidance of
403 doubt, this paragraph does not form part of the public licenses.
404
405 Creative Commons may be contacted at creativecommons.org
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/icons/16x16/lock.png b/dist/qt_themes/qdarkstyle_midnight_blue/icons/16x16/lock.png
new file mode 100644
index 000000000..c750a39e8
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/icons/16x16/lock.png
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
new file mode 100644
index 000000000..303f9a321
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/icons/256x256/plus_folder.png
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
new file mode 100644
index 000000000..4a9709623
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/icons/48x48/bad_folder.png
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
new file mode 100644
index 000000000..973fabd05
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/icons/48x48/chip.png
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
new file mode 100644
index 000000000..0f1e987d6
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/icons/48x48/folder.png
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
new file mode 100644
index 000000000..16cc8b4f4
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/icons/48x48/plus.png
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
new file mode 100644
index 000000000..0291c6542
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/icons/48x48/sd_card.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/icons/index.theme b/dist/qt_themes/qdarkstyle_midnight_blue/icons/index.theme
new file mode 100644
index 000000000..447a6c8be
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/icons/index.theme
@@ -0,0 +1,14 @@
1[Icon Theme]
2Name=qdarkstyle_midnight_blue
3Comment=dark theme
4Inherits=default
5Directories=16x16,48x48,256x256
6
7[16x16]
8Size=16
9
10[48x48]
11Size=48
12
13[256x256]
14Size=256
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/Hmovetoolbar.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/Hmovetoolbar.png
new file mode 100644
index 000000000..cead99ed1
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/Hmovetoolbar.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/Hsepartoolbar.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/Hsepartoolbar.png
new file mode 100644
index 000000000..7f183c8b3
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/Hsepartoolbar.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/Vmovetoolbar.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/Vmovetoolbar.png
new file mode 100644
index 000000000..512edcecd
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/Vmovetoolbar.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/Vsepartoolbar.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/Vsepartoolbar.png
new file mode 100644
index 000000000..d9dc1561b
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/Vsepartoolbar.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_down.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_down.png
new file mode 100644
index 000000000..c4e6894ba
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_down.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_down@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_down@2x.png
new file mode 100644
index 000000000..bb8cbed0d
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_down@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_down_disabled.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_down_disabled.png
new file mode 100644
index 000000000..aa1d06c08
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_down_disabled.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_down_disabled@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_down_disabled@2x.png
new file mode 100644
index 000000000..86bf434b8
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_down_disabled@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_down_focus.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_down_focus.png
new file mode 100644
index 000000000..1c42ee8f6
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_down_focus.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_down_focus@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_down_focus@2x.png
new file mode 100644
index 000000000..7374637c5
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_down_focus@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_down_pressed.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_down_pressed.png
new file mode 100644
index 000000000..8139ee3e8
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_down_pressed.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_down_pressed@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_down_pressed@2x.png
new file mode 100644
index 000000000..5e9d225ff
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_down_pressed@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_left.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_left.png
new file mode 100644
index 000000000..ef929fdf0
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_left.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_left@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_left@2x.png
new file mode 100644
index 000000000..c8923d6f4
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_left@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_left_disabled.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_left_disabled.png
new file mode 100644
index 000000000..9c69561a7
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_left_disabled.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_left_disabled@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_left_disabled@2x.png
new file mode 100644
index 000000000..e52114312
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_left_disabled@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_left_focus.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_left_focus.png
new file mode 100644
index 000000000..a1f070455
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_left_focus.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_left_focus@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_left_focus@2x.png
new file mode 100644
index 000000000..c4267e856
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_left_focus@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_left_pressed.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_left_pressed.png
new file mode 100644
index 000000000..bd706cbdd
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_left_pressed.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_left_pressed@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_left_pressed@2x.png
new file mode 100644
index 000000000..341b2e541
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_left_pressed@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_right.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_right.png
new file mode 100644
index 000000000..4f3388505
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_right.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_right@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_right@2x.png
new file mode 100644
index 000000000..94b260965
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_right@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_right_disabled.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_right_disabled.png
new file mode 100644
index 000000000..0fbc6b04c
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_right_disabled.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_right_disabled@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_right_disabled@2x.png
new file mode 100644
index 000000000..8e9272a5b
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_right_disabled@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_right_focus.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_right_focus.png
new file mode 100644
index 000000000..764940945
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_right_focus.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_right_focus@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_right_focus@2x.png
new file mode 100644
index 000000000..6d52b5fa3
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_right_focus@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_right_pressed.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_right_pressed.png
new file mode 100644
index 000000000..a5f04522a
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_right_pressed.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_right_pressed@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_right_pressed@2x.png
new file mode 100644
index 000000000..6f6a8130c
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_right_pressed@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_up.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_up.png
new file mode 100644
index 000000000..61d7574a4
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_up.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_up@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_up@2x.png
new file mode 100644
index 000000000..d711fae16
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_up@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_up_disabled.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_up_disabled.png
new file mode 100644
index 000000000..18e8ecd8d
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_up_disabled.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_up_disabled@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_up_disabled@2x.png
new file mode 100644
index 000000000..fb4defb52
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_up_disabled@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_up_focus.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_up_focus.png
new file mode 100644
index 000000000..a7acd9b66
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_up_focus.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_up_focus@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_up_focus@2x.png
new file mode 100644
index 000000000..9cd982a1d
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_up_focus@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_up_pressed.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_up_pressed.png
new file mode 100644
index 000000000..390a80e21
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_up_pressed.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_up_pressed@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_up_pressed@2x.png
new file mode 100644
index 000000000..dd352cff3
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/arrow_up_pressed@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/base_icon.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/base_icon.png
new file mode 100644
index 000000000..37a6158cc
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/base_icon.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/base_icon@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/base_icon@2x.png
new file mode 100644
index 000000000..e6e5cb916
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/base_icon@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/base_icon_disabled.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/base_icon_disabled.png
new file mode 100644
index 000000000..37a6158cc
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/base_icon_disabled.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/base_icon_disabled@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/base_icon_disabled@2x.png
new file mode 100644
index 000000000..e6e5cb916
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/base_icon_disabled@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/base_icon_focus.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/base_icon_focus.png
new file mode 100644
index 000000000..37a6158cc
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/base_icon_focus.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/base_icon_focus@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/base_icon_focus@2x.png
new file mode 100644
index 000000000..e6e5cb916
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/base_icon_focus@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/base_icon_pressed.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/base_icon_pressed.png
new file mode 100644
index 000000000..37a6158cc
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/base_icon_pressed.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/base_icon_pressed@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/base_icon_pressed@2x.png
new file mode 100644
index 000000000..e6e5cb916
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/base_icon_pressed@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_closed-on.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_closed-on.png
new file mode 100644
index 000000000..d081e9b3b
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_closed-on.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_closed.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_closed.png
new file mode 100644
index 000000000..53e2c51f5
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_closed.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_closed@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_closed@2x.png
new file mode 100644
index 000000000..06cdefa5f
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_closed@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_closed_disabled.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_closed_disabled.png
new file mode 100644
index 000000000..5106a1438
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_closed_disabled.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_closed_disabled@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_closed_disabled@2x.png
new file mode 100644
index 000000000..180bae9e6
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_closed_disabled@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_closed_focus.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_closed_focus.png
new file mode 100644
index 000000000..c227f9f71
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_closed_focus.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_closed_focus@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_closed_focus@2x.png
new file mode 100644
index 000000000..ad23d0d33
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_closed_focus@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_closed_pressed.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_closed_pressed.png
new file mode 100644
index 000000000..90845a81f
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_closed_pressed.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_closed_pressed@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_closed_pressed@2x.png
new file mode 100644
index 000000000..60aaeb7fb
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_closed_pressed@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_end.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_end.png
new file mode 100644
index 000000000..08b5559b2
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_end.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_end@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_end@2x.png
new file mode 100644
index 000000000..ae6dbe991
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_end@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_end_disabled.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_end_disabled.png
new file mode 100644
index 000000000..027a8894a
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_end_disabled.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_end_disabled@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_end_disabled@2x.png
new file mode 100644
index 000000000..43c1b0c76
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_end_disabled@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_end_focus.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_end_focus.png
new file mode 100644
index 000000000..fdb3160bb
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_end_focus.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_end_focus@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_end_focus@2x.png
new file mode 100644
index 000000000..3ca890449
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_end_focus@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_end_pressed.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_end_pressed.png
new file mode 100644
index 000000000..1c2432dd4
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_end_pressed.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_end_pressed@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_end_pressed@2x.png
new file mode 100644
index 000000000..af0f8fa5a
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_end_pressed@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_line.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_line.png
new file mode 100644
index 000000000..a3a564e44
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_line.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_line@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_line@2x.png
new file mode 100644
index 000000000..1dbf71fc7
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_line@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_line_disabled.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_line_disabled.png
new file mode 100644
index 000000000..ecc7e6d93
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_line_disabled.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_line_disabled@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_line_disabled@2x.png
new file mode 100644
index 000000000..adc6446c9
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_line_disabled@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_line_focus.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_line_focus.png
new file mode 100644
index 000000000..0037f175a
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_line_focus.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_line_focus@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_line_focus@2x.png
new file mode 100644
index 000000000..cb257a914
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_line_focus@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_line_pressed.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_line_pressed.png
new file mode 100644
index 000000000..2d0856527
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_line_pressed.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_line_pressed@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_line_pressed@2x.png
new file mode 100644
index 000000000..803708fb4
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_line_pressed@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_more.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_more.png
new file mode 100644
index 000000000..31b6cee87
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_more.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_more@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_more@2x.png
new file mode 100644
index 000000000..f1f7a67f1
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_more@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_more_disabled.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_more_disabled.png
new file mode 100644
index 000000000..d4b604905
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_more_disabled.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_more_disabled@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_more_disabled@2x.png
new file mode 100644
index 000000000..3ef752108
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_more_disabled@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_more_focus.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_more_focus.png
new file mode 100644
index 000000000..943c13d0b
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_more_focus.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_more_focus@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_more_focus@2x.png
new file mode 100644
index 000000000..9f53ef1fa
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_more_focus@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_more_pressed.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_more_pressed.png
new file mode 100644
index 000000000..9037ed3b3
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_more_pressed.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_more_pressed@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_more_pressed@2x.png
new file mode 100644
index 000000000..675d52c76
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_more_pressed@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_open-on.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_open-on.png
new file mode 100644
index 000000000..ec372b27d
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_open-on.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_open.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_open.png
new file mode 100644
index 000000000..0861d0bc7
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_open.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_open@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_open@2x.png
new file mode 100644
index 000000000..8850f7367
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_open@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_open_disabled.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_open_disabled.png
new file mode 100644
index 000000000..b6c80243b
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_open_disabled.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_open_disabled@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_open_disabled@2x.png
new file mode 100644
index 000000000..15ce9f265
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_open_disabled@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_open_focus.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_open_focus.png
new file mode 100644
index 000000000..eadb0962a
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_open_focus.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_open_focus@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_open_focus@2x.png
new file mode 100644
index 000000000..7dfcbbe8a
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_open_focus@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_open_pressed.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_open_pressed.png
new file mode 100644
index 000000000..2b22e8d08
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_open_pressed.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_open_pressed@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_open_pressed@2x.png
new file mode 100644
index 000000000..269a0cbee
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/branch_open_pressed@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_checked.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_checked.png
new file mode 100644
index 000000000..e7ed08081
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_checked.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_checked@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_checked@2x.png
new file mode 100644
index 000000000..35f2ade58
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_checked@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_checked_disabled.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_checked_disabled.png
new file mode 100644
index 000000000..512b0a3e4
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_checked_disabled.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_checked_disabled@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_checked_disabled@2x.png
new file mode 100644
index 000000000..557383ec8
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_checked_disabled@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_checked_focus.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_checked_focus.png
new file mode 100644
index 000000000..0b90412f2
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_checked_focus.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_checked_focus@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_checked_focus@2x.png
new file mode 100644
index 000000000..7aee03cbb
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_checked_focus@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_checked_pressed.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_checked_pressed.png
new file mode 100644
index 000000000..3d4c869b7
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_checked_pressed.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_checked_pressed@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_checked_pressed@2x.png
new file mode 100644
index 000000000..bfbc14b94
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_checked_pressed@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_indeterminate.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_indeterminate.png
new file mode 100644
index 000000000..c21ab99bf
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_indeterminate.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_indeterminate@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_indeterminate@2x.png
new file mode 100644
index 000000000..2fc29cee6
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_indeterminate@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_indeterminate_disabled.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_indeterminate_disabled.png
new file mode 100644
index 000000000..1d3c21492
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_indeterminate_disabled.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_indeterminate_disabled@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_indeterminate_disabled@2x.png
new file mode 100644
index 000000000..bb8e7a747
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_indeterminate_disabled@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_indeterminate_focus.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_indeterminate_focus.png
new file mode 100644
index 000000000..13ca4a7a4
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_indeterminate_focus.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_indeterminate_focus@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_indeterminate_focus@2x.png
new file mode 100644
index 000000000..3907eb8d4
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_indeterminate_focus@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_indeterminate_pressed.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_indeterminate_pressed.png
new file mode 100644
index 000000000..12f83ceba
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_indeterminate_pressed.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_indeterminate_pressed@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_indeterminate_pressed@2x.png
new file mode 100644
index 000000000..5ff4f6629
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_indeterminate_pressed@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_unchecked.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_unchecked.png
new file mode 100644
index 000000000..e2da452fa
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_unchecked.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_unchecked@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_unchecked@2x.png
new file mode 100644
index 000000000..3732d5406
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_unchecked@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_unchecked_disabled.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_unchecked_disabled.png
new file mode 100644
index 000000000..c2e30c690
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_unchecked_disabled.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_unchecked_disabled@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_unchecked_disabled@2x.png
new file mode 100644
index 000000000..c4bddb6eb
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_unchecked_disabled@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_unchecked_focus.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_unchecked_focus.png
new file mode 100644
index 000000000..c57f04d9f
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_unchecked_focus.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_unchecked_focus@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_unchecked_focus@2x.png
new file mode 100644
index 000000000..1776ad048
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_unchecked_focus@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_unchecked_pressed.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_unchecked_pressed.png
new file mode 100644
index 000000000..be41236e1
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_unchecked_pressed.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_unchecked_pressed@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_unchecked_pressed@2x.png
new file mode 100644
index 000000000..b1ad7c72f
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/checkbox_unchecked_pressed@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/close-hover.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/close-hover.png
new file mode 100644
index 000000000..657943a66
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/close-hover.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/close-pressed.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/close-pressed.png
new file mode 100644
index 000000000..937d00598
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/close-pressed.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/close.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/close.png
new file mode 100644
index 000000000..bc0f57610
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/close.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/down_arrow.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/down_arrow.png
new file mode 100644
index 000000000..e271f7f90
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/down_arrow.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/down_arrow_disabled.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/down_arrow_disabled.png
new file mode 100644
index 000000000..5805d9842
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/down_arrow_disabled.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/left_arrow.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/left_arrow.png
new file mode 100644
index 000000000..f808d2d72
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/left_arrow.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/left_arrow_disabled.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/left_arrow_disabled.png
new file mode 100644
index 000000000..f5b9af8a3
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/left_arrow_disabled.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/line_horizontal.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/line_horizontal.png
new file mode 100644
index 000000000..11bc5c003
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/line_horizontal.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/line_horizontal@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/line_horizontal@2x.png
new file mode 100644
index 000000000..c229ac963
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/line_horizontal@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/line_horizontal_disabled.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/line_horizontal_disabled.png
new file mode 100644
index 000000000..204df8058
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/line_horizontal_disabled.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/line_horizontal_disabled@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/line_horizontal_disabled@2x.png
new file mode 100644
index 000000000..a4713c565
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/line_horizontal_disabled@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/line_horizontal_focus.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/line_horizontal_focus.png
new file mode 100644
index 000000000..ecda0c10b
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/line_horizontal_focus.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/line_horizontal_focus@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/line_horizontal_focus@2x.png
new file mode 100644
index 000000000..84397efdb
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/line_horizontal_focus@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/line_horizontal_pressed.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/line_horizontal_pressed.png
new file mode 100644
index 000000000..fd5d864ca
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/line_horizontal_pressed.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/line_horizontal_pressed@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/line_horizontal_pressed@2x.png
new file mode 100644
index 000000000..140552e4f
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/line_horizontal_pressed@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/line_vertical.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/line_vertical.png
new file mode 100644
index 000000000..a3a564e44
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/line_vertical.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/line_vertical@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/line_vertical@2x.png
new file mode 100644
index 000000000..1dbf71fc7
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/line_vertical@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/line_vertical_disabled.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/line_vertical_disabled.png
new file mode 100644
index 000000000..ecc7e6d93
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/line_vertical_disabled.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/line_vertical_disabled@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/line_vertical_disabled@2x.png
new file mode 100644
index 000000000..adc6446c9
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/line_vertical_disabled@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/line_vertical_focus.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/line_vertical_focus.png
new file mode 100644
index 000000000..0037f175a
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/line_vertical_focus.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/line_vertical_focus@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/line_vertical_focus@2x.png
new file mode 100644
index 000000000..cb257a914
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/line_vertical_focus@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/line_vertical_pressed.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/line_vertical_pressed.png
new file mode 100644
index 000000000..2d0856527
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/line_vertical_pressed.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/line_vertical_pressed@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/line_vertical_pressed@2x.png
new file mode 100644
index 000000000..803708fb4
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/line_vertical_pressed@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_checked.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_checked.png
new file mode 100644
index 000000000..6f1fd6ca6
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_checked.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_checked@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_checked@2x.png
new file mode 100644
index 000000000..228ffdbf2
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_checked@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_checked_disabled.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_checked_disabled.png
new file mode 100644
index 000000000..27788530d
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_checked_disabled.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_checked_disabled@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_checked_disabled@2x.png
new file mode 100644
index 000000000..930bfaf70
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_checked_disabled@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_checked_focus.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_checked_focus.png
new file mode 100644
index 000000000..ca8e8bc9a
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_checked_focus.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_checked_focus@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_checked_focus@2x.png
new file mode 100644
index 000000000..aa0f1152b
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_checked_focus@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_checked_pressed.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_checked_pressed.png
new file mode 100644
index 000000000..6e391a0ff
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_checked_pressed.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_checked_pressed@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_checked_pressed@2x.png
new file mode 100644
index 000000000..0512731ae
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_checked_pressed@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_unchecked.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_unchecked.png
new file mode 100644
index 000000000..763306bdc
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_unchecked.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_unchecked@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_unchecked@2x.png
new file mode 100644
index 000000000..28b6a0784
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_unchecked@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_unchecked_disabled.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_unchecked_disabled.png
new file mode 100644
index 000000000..fc0b12f78
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_unchecked_disabled.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_unchecked_disabled@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_unchecked_disabled@2x.png
new file mode 100644
index 000000000..d31f2b4b9
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_unchecked_disabled@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_unchecked_focus.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_unchecked_focus.png
new file mode 100644
index 000000000..9c87b01e4
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_unchecked_focus.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_unchecked_focus@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_unchecked_focus@2x.png
new file mode 100644
index 000000000..4b4c7321d
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_unchecked_focus@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_unchecked_pressed.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_unchecked_pressed.png
new file mode 100644
index 000000000..709e31633
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_unchecked_pressed.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_unchecked_pressed@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_unchecked_pressed@2x.png
new file mode 100644
index 000000000..b014de5f0
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/radio_unchecked_pressed@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/right_arrow.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/right_arrow.png
new file mode 100644
index 000000000..9b0a4e6a7
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/right_arrow.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/right_arrow_disabled.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/right_arrow_disabled.png
new file mode 100644
index 000000000..5c0bee402
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/right_arrow_disabled.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/sizegrip.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/sizegrip.png
new file mode 100644
index 000000000..350583aaa
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/sizegrip.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/stylesheet-branch-end.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/stylesheet-branch-end.png
new file mode 100644
index 000000000..cb5d3b51f
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/stylesheet-branch-end.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/stylesheet-branch-more.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/stylesheet-branch-more.png
new file mode 100644
index 000000000..62711409d
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/stylesheet-branch-more.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/stylesheet-vline.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/stylesheet-vline.png
new file mode 100644
index 000000000..87536cce1
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/stylesheet-vline.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_horizontal.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_horizontal.png
new file mode 100644
index 000000000..012ea2dfb
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_horizontal.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_horizontal@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_horizontal@2x.png
new file mode 100644
index 000000000..520c34f98
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_horizontal@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_horizontal_disabled.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_horizontal_disabled.png
new file mode 100644
index 000000000..1f91df98f
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_horizontal_disabled.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_horizontal_disabled@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_horizontal_disabled@2x.png
new file mode 100644
index 000000000..738008f92
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_horizontal_disabled@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_horizontal_focus.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_horizontal_focus.png
new file mode 100644
index 000000000..999b3c7d8
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_horizontal_focus.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_horizontal_focus@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_horizontal_focus@2x.png
new file mode 100644
index 000000000..f8e40b7d1
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_horizontal_focus@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_horizontal_pressed.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_horizontal_pressed.png
new file mode 100644
index 000000000..c31b69deb
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_horizontal_pressed.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_horizontal_pressed@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_horizontal_pressed@2x.png
new file mode 100644
index 000000000..2f4cb41c7
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_horizontal_pressed@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_vertical.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_vertical.png
new file mode 100644
index 000000000..16473bfd8
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_vertical.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_vertical@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_vertical@2x.png
new file mode 100644
index 000000000..90a5caee3
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_vertical@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_vertical_disabled.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_vertical_disabled.png
new file mode 100644
index 000000000..2d240edb5
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_vertical_disabled.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_vertical_disabled@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_vertical_disabled@2x.png
new file mode 100644
index 000000000..fd1df30f1
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_vertical_disabled@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_vertical_focus.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_vertical_focus.png
new file mode 100644
index 000000000..58cda1f80
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_vertical_focus.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_vertical_focus@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_vertical_focus@2x.png
new file mode 100644
index 000000000..9222b4fd8
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_vertical_focus@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_vertical_pressed.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_vertical_pressed.png
new file mode 100644
index 000000000..e7d641926
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_vertical_pressed.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_vertical_pressed@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_vertical_pressed@2x.png
new file mode 100644
index 000000000..9c438faf4
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_move_vertical_pressed@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_horizontal.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_horizontal.png
new file mode 100644
index 000000000..3c0acbdcc
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_horizontal.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_horizontal@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_horizontal@2x.png
new file mode 100644
index 000000000..fb4e24c88
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_horizontal@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_horizontal_disabled.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_horizontal_disabled.png
new file mode 100644
index 000000000..32f7e8ca6
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_horizontal_disabled.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_horizontal_disabled@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_horizontal_disabled@2x.png
new file mode 100644
index 000000000..f7bec188b
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_horizontal_disabled@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_horizontal_focus.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_horizontal_focus.png
new file mode 100644
index 000000000..91c19d65c
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_horizontal_focus.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_horizontal_focus@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_horizontal_focus@2x.png
new file mode 100644
index 000000000..c4829918d
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_horizontal_focus@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_horizontal_pressed.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_horizontal_pressed.png
new file mode 100644
index 000000000..7a7f91737
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_horizontal_pressed.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_horizontal_pressed@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_horizontal_pressed@2x.png
new file mode 100644
index 000000000..d65773b48
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_horizontal_pressed@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_vertical.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_vertical.png
new file mode 100644
index 000000000..4dde3f37f
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_vertical.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_vertical@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_vertical@2x.png
new file mode 100644
index 000000000..fe97c0de3
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_vertical@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_vertical_disabled.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_vertical_disabled.png
new file mode 100644
index 000000000..7426ae2de
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_vertical_disabled.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_vertical_disabled@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_vertical_disabled@2x.png
new file mode 100644
index 000000000..7acc6d33e
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_vertical_disabled@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_vertical_focus.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_vertical_focus.png
new file mode 100644
index 000000000..6e3c12143
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_vertical_focus.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_vertical_focus@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_vertical_focus@2x.png
new file mode 100644
index 000000000..cac3a56c2
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_vertical_focus@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_vertical_pressed.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_vertical_pressed.png
new file mode 100644
index 000000000..b777784b8
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_vertical_pressed.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_vertical_pressed@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_vertical_pressed@2x.png
new file mode 100644
index 000000000..7ed878fd3
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/toolbar_separator_vertical_pressed@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/transparent.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/transparent.png
new file mode 100644
index 000000000..8b241c4a4
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/transparent.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/transparent@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/transparent@2x.png
new file mode 100644
index 000000000..2c3df7a5e
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/transparent@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/transparent_disabled.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/transparent_disabled.png
new file mode 100644
index 000000000..8b241c4a4
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/transparent_disabled.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/transparent_disabled@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/transparent_disabled@2x.png
new file mode 100644
index 000000000..2c3df7a5e
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/transparent_disabled@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/transparent_focus.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/transparent_focus.png
new file mode 100644
index 000000000..8b241c4a4
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/transparent_focus.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/transparent_focus@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/transparent_focus@2x.png
new file mode 100644
index 000000000..2c3df7a5e
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/transparent_focus@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/transparent_pressed.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/transparent_pressed.png
new file mode 100644
index 000000000..8b241c4a4
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/transparent_pressed.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/transparent_pressed@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/transparent_pressed@2x.png
new file mode 100644
index 000000000..2c3df7a5e
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/transparent_pressed@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/undock.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/undock.png
new file mode 100644
index 000000000..88691d779
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/undock.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/up_arrow.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/up_arrow.png
new file mode 100644
index 000000000..abcc72452
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/up_arrow.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/up_arrow_disabled.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/up_arrow_disabled.png
new file mode 100644
index 000000000..b9c8e3b53
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/up_arrow_disabled.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_close.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_close.png
new file mode 100644
index 000000000..6f55c3ae7
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_close.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_close@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_close@2x.png
new file mode 100644
index 000000000..ff644f2e8
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_close@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_close_disabled.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_close_disabled.png
new file mode 100644
index 000000000..22694e31d
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_close_disabled.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_close_disabled@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_close_disabled@2x.png
new file mode 100644
index 000000000..ebc97db70
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_close_disabled@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_close_focus.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_close_focus.png
new file mode 100644
index 000000000..f017eda31
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_close_focus.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_close_focus@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_close_focus@2x.png
new file mode 100644
index 000000000..5a354d796
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_close_focus@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_close_pressed.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_close_pressed.png
new file mode 100644
index 000000000..04b922dd0
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_close_pressed.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_close_pressed@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_close_pressed@2x.png
new file mode 100644
index 000000000..58c0bf592
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_close_pressed@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_grip.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_grip.png
new file mode 100644
index 000000000..0528049bb
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_grip.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_grip@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_grip@2x.png
new file mode 100644
index 000000000..1ca1b073c
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_grip@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_grip_disabled.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_grip_disabled.png
new file mode 100644
index 000000000..15f55c056
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_grip_disabled.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_grip_disabled@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_grip_disabled@2x.png
new file mode 100644
index 000000000..33a4588e8
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_grip_disabled@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_grip_focus.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_grip_focus.png
new file mode 100644
index 000000000..06e76c31f
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_grip_focus.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_grip_focus@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_grip_focus@2x.png
new file mode 100644
index 000000000..58c2d06e4
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_grip_focus@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_grip_pressed.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_grip_pressed.png
new file mode 100644
index 000000000..b3a566cdb
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_grip_pressed.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_grip_pressed@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_grip_pressed@2x.png
new file mode 100644
index 000000000..e9da94049
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_grip_pressed@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_minimize.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_minimize.png
new file mode 100644
index 000000000..f60981615
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_minimize.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_minimize@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_minimize@2x.png
new file mode 100644
index 000000000..30f728f02
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_minimize@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_minimize_disabled.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_minimize_disabled.png
new file mode 100644
index 000000000..29db1c9b1
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_minimize_disabled.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_minimize_disabled@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_minimize_disabled@2x.png
new file mode 100644
index 000000000..1572ca2fe
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_minimize_disabled@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_minimize_focus.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_minimize_focus.png
new file mode 100644
index 000000000..cb592f598
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_minimize_focus.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_minimize_focus@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_minimize_focus@2x.png
new file mode 100644
index 000000000..6f6465169
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_minimize_focus@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_minimize_pressed.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_minimize_pressed.png
new file mode 100644
index 000000000..6962440ac
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_minimize_pressed.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_minimize_pressed@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_minimize_pressed@2x.png
new file mode 100644
index 000000000..cb028272b
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_minimize_pressed@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_undock.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_undock.png
new file mode 100644
index 000000000..616da991a
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_undock.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_undock@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_undock@2x.png
new file mode 100644
index 000000000..511036bf2
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_undock@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_undock_disabled.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_undock_disabled.png
new file mode 100644
index 000000000..a2b3d25b2
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_undock_disabled.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_undock_disabled@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_undock_disabled@2x.png
new file mode 100644
index 000000000..638ec8104
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_undock_disabled@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_undock_focus.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_undock_focus.png
new file mode 100644
index 000000000..ae6dc4a60
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_undock_focus.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_undock_focus@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_undock_focus@2x.png
new file mode 100644
index 000000000..d06dd1eac
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_undock_focus@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_undock_pressed.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_undock_pressed.png
new file mode 100644
index 000000000..e9142ded2
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_undock_pressed.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_undock_pressed@2x.png b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_undock_pressed@2x.png
new file mode 100644
index 000000000..a597420f3
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/rc/window_undock_pressed@2x.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/style.qrc b/dist/qt_themes/qdarkstyle_midnight_blue/style.qrc
new file mode 100644
index 000000000..1b7686f15
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/style.qrc
@@ -0,0 +1,225 @@
1<RCC>
2 <qresource prefix="icons/qdarkstyle_midnight_blue">
3 <file alias="index.theme">icons/index.theme</file>
4 <file alias="16x16/lock.png">icons/16x16/lock.png</file>
5 <file alias="48x48/bad_folder.png">icons/48x48/bad_folder.png</file>
6 <file alias="48x48/chip.png">icons/48x48/chip.png</file>
7 <file alias="48x48/folder.png">icons/48x48/folder.png</file>
8 <file alias="48x48/plus.png">icons/48x48/plus.png</file>
9 <file alias="48x48/sd_card.png">icons/48x48/sd_card.png</file>
10 <file alias="256x256/plus_folder.png">icons/256x256/plus_folder.png</file>
11 </qresource>
12 <qresource prefix="qss_icons">
13 <file>rc/arrow_down.png</file>
14 <file>rc/arrow_down@2x.png</file>
15 <file>rc/arrow_down_disabled.png</file>
16 <file>rc/arrow_down_disabled@2x.png</file>
17 <file>rc/arrow_down_focus.png</file>
18 <file>rc/arrow_down_focus@2x.png</file>
19 <file>rc/arrow_down_pressed.png</file>
20 <file>rc/arrow_down_pressed@2x.png</file>
21 <file>rc/arrow_left.png</file>
22 <file>rc/arrow_left@2x.png</file>
23 <file>rc/arrow_left_disabled.png</file>
24 <file>rc/arrow_left_disabled@2x.png</file>
25 <file>rc/arrow_left_focus.png</file>
26 <file>rc/arrow_left_focus@2x.png</file>
27 <file>rc/arrow_left_pressed.png</file>
28 <file>rc/arrow_left_pressed@2x.png</file>
29 <file>rc/arrow_right.png</file>
30 <file>rc/arrow_right@2x.png</file>
31 <file>rc/arrow_right_disabled.png</file>
32 <file>rc/arrow_right_disabled@2x.png</file>
33 <file>rc/arrow_right_focus.png</file>
34 <file>rc/arrow_right_focus@2x.png</file>
35 <file>rc/arrow_right_pressed.png</file>
36 <file>rc/arrow_right_pressed@2x.png</file>
37 <file>rc/arrow_up.png</file>
38 <file>rc/arrow_up@2x.png</file>
39 <file>rc/arrow_up_disabled.png</file>
40 <file>rc/arrow_up_disabled@2x.png</file>
41 <file>rc/arrow_up_focus.png</file>
42 <file>rc/arrow_up_focus@2x.png</file>
43 <file>rc/arrow_up_pressed.png</file>
44 <file>rc/arrow_up_pressed@2x.png</file>
45 <file>rc/base_icon.png</file>
46 <file>rc/base_icon@2x.png</file>
47 <file>rc/base_icon_disabled.png</file>
48 <file>rc/base_icon_disabled@2x.png</file>
49 <file>rc/base_icon_focus.png</file>
50 <file>rc/base_icon_focus@2x.png</file>
51 <file>rc/base_icon_pressed.png</file>
52 <file>rc/base_icon_pressed@2x.png</file>
53 <file>rc/branch_closed.png</file>
54 <file>rc/branch_closed@2x.png</file>
55 <file>rc/branch_closed_disabled.png</file>
56 <file>rc/branch_closed_disabled@2x.png</file>
57 <file>rc/branch_closed_focus.png</file>
58 <file>rc/branch_closed_focus@2x.png</file>
59 <file>rc/branch_closed_pressed.png</file>
60 <file>rc/branch_closed_pressed@2x.png</file>
61 <file>rc/branch_end.png</file>
62 <file>rc/branch_end@2x.png</file>
63 <file>rc/branch_end_disabled.png</file>
64 <file>rc/branch_end_disabled@2x.png</file>
65 <file>rc/branch_end_focus.png</file>
66 <file>rc/branch_end_focus@2x.png</file>
67 <file>rc/branch_end_pressed.png</file>
68 <file>rc/branch_end_pressed@2x.png</file>
69 <file>rc/branch_line.png</file>
70 <file>rc/branch_line@2x.png</file>
71 <file>rc/branch_line_disabled.png</file>
72 <file>rc/branch_line_disabled@2x.png</file>
73 <file>rc/branch_line_focus.png</file>
74 <file>rc/branch_line_focus@2x.png</file>
75 <file>rc/branch_line_pressed.png</file>
76 <file>rc/branch_line_pressed@2x.png</file>
77 <file>rc/branch_more.png</file>
78 <file>rc/branch_more@2x.png</file>
79 <file>rc/branch_more_disabled.png</file>
80 <file>rc/branch_more_disabled@2x.png</file>
81 <file>rc/branch_more_focus.png</file>
82 <file>rc/branch_more_focus@2x.png</file>
83 <file>rc/branch_more_pressed.png</file>
84 <file>rc/branch_more_pressed@2x.png</file>
85 <file>rc/branch_open.png</file>
86 <file>rc/branch_open@2x.png</file>
87 <file>rc/branch_open_disabled.png</file>
88 <file>rc/branch_open_disabled@2x.png</file>
89 <file>rc/branch_open_focus.png</file>
90 <file>rc/branch_open_focus@2x.png</file>
91 <file>rc/branch_open_pressed.png</file>
92 <file>rc/branch_open_pressed@2x.png</file>
93 <file>rc/checkbox_checked.png</file>
94 <file>rc/checkbox_checked@2x.png</file>
95 <file>rc/checkbox_checked_disabled.png</file>
96 <file>rc/checkbox_checked_disabled@2x.png</file>
97 <file>rc/checkbox_checked_focus.png</file>
98 <file>rc/checkbox_checked_focus@2x.png</file>
99 <file>rc/checkbox_checked_pressed.png</file>
100 <file>rc/checkbox_checked_pressed@2x.png</file>
101 <file>rc/checkbox_indeterminate.png</file>
102 <file>rc/checkbox_indeterminate@2x.png</file>
103 <file>rc/checkbox_indeterminate_disabled.png</file>
104 <file>rc/checkbox_indeterminate_disabled@2x.png</file>
105 <file>rc/checkbox_indeterminate_focus.png</file>
106 <file>rc/checkbox_indeterminate_focus@2x.png</file>
107 <file>rc/checkbox_indeterminate_pressed.png</file>
108 <file>rc/checkbox_indeterminate_pressed@2x.png</file>
109 <file>rc/checkbox_unchecked.png</file>
110 <file>rc/checkbox_unchecked@2x.png</file>
111 <file>rc/checkbox_unchecked_disabled.png</file>
112 <file>rc/checkbox_unchecked_disabled@2x.png</file>
113 <file>rc/checkbox_unchecked_focus.png</file>
114 <file>rc/checkbox_unchecked_focus@2x.png</file>
115 <file>rc/checkbox_unchecked_pressed.png</file>
116 <file>rc/checkbox_unchecked_pressed@2x.png</file>
117 <file>rc/line_horizontal.png</file>
118 <file>rc/line_horizontal@2x.png</file>
119 <file>rc/line_horizontal_disabled.png</file>
120 <file>rc/line_horizontal_disabled@2x.png</file>
121 <file>rc/line_horizontal_focus.png</file>
122 <file>rc/line_horizontal_focus@2x.png</file>
123 <file>rc/line_horizontal_pressed.png</file>
124 <file>rc/line_horizontal_pressed@2x.png</file>
125 <file>rc/line_vertical.png</file>
126 <file>rc/line_vertical@2x.png</file>
127 <file>rc/line_vertical_disabled.png</file>
128 <file>rc/line_vertical_disabled@2x.png</file>
129 <file>rc/line_vertical_focus.png</file>
130 <file>rc/line_vertical_focus@2x.png</file>
131 <file>rc/line_vertical_pressed.png</file>
132 <file>rc/line_vertical_pressed@2x.png</file>
133 <file>rc/radio_checked.png</file>
134 <file>rc/radio_checked@2x.png</file>
135 <file>rc/radio_checked_disabled.png</file>
136 <file>rc/radio_checked_disabled@2x.png</file>
137 <file>rc/radio_checked_focus.png</file>
138 <file>rc/radio_checked_focus@2x.png</file>
139 <file>rc/radio_checked_pressed.png</file>
140 <file>rc/radio_checked_pressed@2x.png</file>
141 <file>rc/radio_unchecked.png</file>
142 <file>rc/radio_unchecked@2x.png</file>
143 <file>rc/radio_unchecked_disabled.png</file>
144 <file>rc/radio_unchecked_disabled@2x.png</file>
145 <file>rc/radio_unchecked_focus.png</file>
146 <file>rc/radio_unchecked_focus@2x.png</file>
147 <file>rc/radio_unchecked_pressed.png</file>
148 <file>rc/radio_unchecked_pressed@2x.png</file>
149 <file>rc/toolbar_move_horizontal.png</file>
150 <file>rc/toolbar_move_horizontal@2x.png</file>
151 <file>rc/toolbar_move_horizontal_disabled.png</file>
152 <file>rc/toolbar_move_horizontal_disabled@2x.png</file>
153 <file>rc/toolbar_move_horizontal_focus.png</file>
154 <file>rc/toolbar_move_horizontal_focus@2x.png</file>
155 <file>rc/toolbar_move_horizontal_pressed.png</file>
156 <file>rc/toolbar_move_horizontal_pressed@2x.png</file>
157 <file>rc/toolbar_move_vertical.png</file>
158 <file>rc/toolbar_move_vertical@2x.png</file>
159 <file>rc/toolbar_move_vertical_disabled.png</file>
160 <file>rc/toolbar_move_vertical_disabled@2x.png</file>
161 <file>rc/toolbar_move_vertical_focus.png</file>
162 <file>rc/toolbar_move_vertical_focus@2x.png</file>
163 <file>rc/toolbar_move_vertical_pressed.png</file>
164 <file>rc/toolbar_move_vertical_pressed@2x.png</file>
165 <file>rc/toolbar_separator_horizontal.png</file>
166 <file>rc/toolbar_separator_horizontal@2x.png</file>
167 <file>rc/toolbar_separator_horizontal_disabled.png</file>
168 <file>rc/toolbar_separator_horizontal_disabled@2x.png</file>
169 <file>rc/toolbar_separator_horizontal_focus.png</file>
170 <file>rc/toolbar_separator_horizontal_focus@2x.png</file>
171 <file>rc/toolbar_separator_horizontal_pressed.png</file>
172 <file>rc/toolbar_separator_horizontal_pressed@2x.png</file>
173 <file>rc/toolbar_separator_vertical.png</file>
174 <file>rc/toolbar_separator_vertical@2x.png</file>
175 <file>rc/toolbar_separator_vertical_disabled.png</file>
176 <file>rc/toolbar_separator_vertical_disabled@2x.png</file>
177 <file>rc/toolbar_separator_vertical_focus.png</file>
178 <file>rc/toolbar_separator_vertical_focus@2x.png</file>
179 <file>rc/toolbar_separator_vertical_pressed.png</file>
180 <file>rc/toolbar_separator_vertical_pressed@2x.png</file>
181 <file>rc/transparent.png</file>
182 <file>rc/transparent@2x.png</file>
183 <file>rc/transparent_disabled.png</file>
184 <file>rc/transparent_disabled@2x.png</file>
185 <file>rc/transparent_focus.png</file>
186 <file>rc/transparent_focus@2x.png</file>
187 <file>rc/transparent_pressed.png</file>
188 <file>rc/transparent_pressed@2x.png</file>
189 <file>rc/window_close.png</file>
190 <file>rc/window_close@2x.png</file>
191 <file>rc/window_close_disabled.png</file>
192 <file>rc/window_close_disabled@2x.png</file>
193 <file>rc/window_close_focus.png</file>
194 <file>rc/window_close_focus@2x.png</file>
195 <file>rc/window_close_pressed.png</file>
196 <file>rc/window_close_pressed@2x.png</file>
197 <file>rc/window_grip.png</file>
198 <file>rc/window_grip@2x.png</file>
199 <file>rc/window_grip_disabled.png</file>
200 <file>rc/window_grip_disabled@2x.png</file>
201 <file>rc/window_grip_focus.png</file>
202 <file>rc/window_grip_focus@2x.png</file>
203 <file>rc/window_grip_pressed.png</file>
204 <file>rc/window_grip_pressed@2x.png</file>
205 <file>rc/window_minimize.png</file>
206 <file>rc/window_minimize@2x.png</file>
207 <file>rc/window_minimize_disabled.png</file>
208 <file>rc/window_minimize_disabled@2x.png</file>
209 <file>rc/window_minimize_focus.png</file>
210 <file>rc/window_minimize_focus@2x.png</file>
211 <file>rc/window_minimize_pressed.png</file>
212 <file>rc/window_minimize_pressed@2x.png</file>
213 <file>rc/window_undock.png</file>
214 <file>rc/window_undock@2x.png</file>
215 <file>rc/window_undock_disabled.png</file>
216 <file>rc/window_undock_disabled@2x.png</file>
217 <file>rc/window_undock_focus.png</file>
218 <file>rc/window_undock_focus@2x.png</file>
219 <file>rc/window_undock_pressed.png</file>
220 <file>rc/window_undock_pressed@2x.png</file>
221 </qresource>
222 <qresource prefix="qdarkstyle_midnight_blue">
223 <file>style.qss</file>
224 </qresource>
225</RCC>
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/style.qss b/dist/qt_themes/qdarkstyle_midnight_blue/style.qss
new file mode 100644
index 000000000..be645c907
--- /dev/null
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/style.qss
@@ -0,0 +1,2175 @@
1/* ---------------------------------------------------------------------------
2
3 Created by the qtsass compiler v0.1.1
4
5 The definitions are in the "qdarkstyle.qss._styles.scss" module
6
7 WARNING! All changes made in this file will be lost!
8
9--------------------------------------------------------------------------- */
10/* QDarkStyleSheet -----------------------------------------------------------
11
12This is the main style sheet, the palette has nine colors.
13
14It is based on three selecting colors, three greyish (background) colors
15plus three whitish (foreground) colors. Each set of widgets of the same
16type have a header like this:
17
18 ------------------
19 GroupName --------
20 ------------------
21
22And each widget is separated with a header like this:
23
24 QWidgetName ------
25
26This makes more easy to find and change some css field. The basic
27configuration is described bellow.
28
29 BACKGROUND -----------
30
31 Light (unpressed)
32 Normal (border, disabled, pressed, checked, toolbars, menus)
33 Dark (background)
34
35 FOREGROUND -----------
36
37 Light (texts/labels)
38 Normal (not used yet)
39 Dark (disabled texts)
40
41 SELECTION ------------
42
43 Light (selection/hover/active)
44 Normal (selected)
45 Dark (selected disabled)
46
47If a stranger configuration is required because of a bugfix or anything
48else, keep the comment on the line above so nobody changes it, including the
49issue number.
50
51*/
52/*
53
54See Qt documentation:
55
56 - https://doc.qt.io/qt-5/stylesheet.html
57 - https://doc.qt.io/qt-5/stylesheet-reference.html
58 - https://doc.qt.io/qt-5/stylesheet-examples.html
59
60--------------------------------------------------------------------------- */
61/* QWidget ----------------------------------------------------------------
62
63--------------------------------------------------------------------------- */
64QWidget {
65 background-color: #19232D;
66 border: 0px solid #32414B;
67 padding: 0px;
68 color: #F0F0F0;
69 selection-background-color: #1464A0;
70 selection-color: #F0F0F0;
71}
72
73QWidget:disabled {
74 background-color: #19232D;
75 color: #787878;
76 selection-background-color: #14506E;
77 selection-color: #787878;
78}
79
80QWidget::item:selected {
81 background-color: #1464A0;
82}
83
84QWidget::item:hover {
85 background-color: #148CD2;
86 color: #32414B;
87}
88
89/* QMainWindow ------------------------------------------------------------
90
91This adjusts the splitter in the dock widget, not qsplitter
92https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qmainwindow
93
94--------------------------------------------------------------------------- */
95QMainWindow::separator {
96 background-color: #32414B;
97 border: 0px solid #19232D;
98 spacing: 0px;
99 padding: 2px;
100}
101
102QMainWindow::separator:hover {
103 background-color: #505F69;
104 border: 0px solid #148CD2;
105}
106
107QMainWindow::separator:horizontal {
108 width: 5px;
109 margin-top: 2px;
110 margin-bottom: 2px;
111 image: url(":/qss_icons/rc/toolbar_separator_vertical.png");
112}
113
114QMainWindow::separator:vertical {
115 height: 5px;
116 margin-left: 2px;
117 margin-right: 2px;
118 image: url(":/qss_icons/rc/toolbar_separator_horizontal.png");
119}
120
121/* QToolTip ---------------------------------------------------------------
122
123https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtooltip
124
125--------------------------------------------------------------------------- */
126QToolTip {
127 background-color: #148CD2;
128 border: 1px solid #19232D;
129 color: #19232D;
130 /* Remove padding, for fix combo box tooltip */
131 padding: 0px;
132 /* Remove opacity, fix #174 - may need to use RGBA */
133}
134
135/* QStatusBar -------------------------------------------------------------
136
137https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qstatusbar
138
139--------------------------------------------------------------------------- */
140QStatusBar {
141 border: 1px solid #32414B;
142 /* Fixes Spyder #9120, #9121 */
143 background: #32414B;
144 /* Fixes #205, white vertical borders separating items */
145}
146
147QStatusBar::item {
148 border: none;
149}
150
151QStatusBar QToolTip {
152 background-color: #148CD2;
153 border: 1px solid #19232D;
154 color: #19232D;
155 /* Remove padding, for fix combo box tooltip */
156 padding: 0px;
157 /* Reducing transparency to read better */
158 opacity: 230;
159}
160
161QStatusBar QLabel {
162 /* Fixes Spyder #9120, #9121 */
163 background: transparent;
164}
165
166/* QCheckBox --------------------------------------------------------------
167
168https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qcheckbox
169
170--------------------------------------------------------------------------- */
171QCheckBox {
172 background-color: #19232D;
173 color: #F0F0F0;
174 spacing: 4px;
175 outline: none;
176 padding-top: 4px;
177 padding-bottom: 4px;
178}
179
180QCheckBox:focus {
181 border: none;
182}
183
184QCheckBox QWidget:disabled {
185 background-color: #19232D;
186 color: #787878;
187}
188
189QCheckBox::indicator {
190 margin-left: 4px;
191 height: 16px;
192 width: 16px;
193}
194
195QCheckBox::indicator:unchecked {
196 image: url(":/qss_icons/rc/checkbox_unchecked.png");
197}
198
199QCheckBox::indicator:unchecked:hover, QCheckBox::indicator:unchecked:focus, QCheckBox::indicator:unchecked:pressed {
200 border: none;
201 image: url(":/qss_icons/rc/checkbox_unchecked_focus.png");
202}
203
204QCheckBox::indicator:unchecked:disabled {
205 image: url(":/qss_icons/rc/checkbox_unchecked_disabled.png");
206}
207
208QCheckBox::indicator:checked {
209 image: url(":/qss_icons/rc/checkbox_checked.png");
210}
211
212QCheckBox::indicator:checked:hover, QCheckBox::indicator:checked:focus, QCheckBox::indicator:checked:pressed {
213 border: none;
214 image: url(":/qss_icons/rc/checkbox_checked_focus.png");
215}
216
217QCheckBox::indicator:checked:disabled {
218 image: url(":/qss_icons/rc/checkbox_checked_disabled.png");
219}
220
221QCheckBox::indicator:indeterminate {
222 image: url(":/qss_icons/rc/checkbox_indeterminate.png");
223}
224
225QCheckBox::indicator:indeterminate:disabled {
226 image: url(":/qss_icons/rc/checkbox_indeterminate_disabled.png");
227}
228
229QCheckBox::indicator:indeterminate:focus, QCheckBox::indicator:indeterminate:hover, QCheckBox::indicator:indeterminate:pressed {
230 image: url(":/qss_icons/rc/checkbox_indeterminate_focus.png");
231}
232
233/* QGroupBox --------------------------------------------------------------
234
235https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qgroupbox
236
237--------------------------------------------------------------------------- */
238QGroupBox {
239 font-weight: bold;
240 border: 1px solid #32414B;
241 border-radius: 4px;
242 padding: 4px;
243 margin-top: 16px;
244}
245
246QGroupBox::title {
247 subcontrol-origin: margin;
248 subcontrol-position: top left;
249 left: 3px;
250 padding-left: 3px;
251 padding-right: 5px;
252 padding-top: 8px;
253 padding-bottom: 16px;
254}
255
256QGroupBox::indicator {
257 margin-left: 2px;
258 height: 16px;
259 width: 16px;
260}
261
262QGroupBox::indicator:unchecked {
263 border: none;
264 image: url(":/qss_icons/rc/checkbox_unchecked.png");
265}
266
267QGroupBox::indicator:unchecked:hover, QGroupBox::indicator:unchecked:focus, QGroupBox::indicator:unchecked:pressed {
268 border: none;
269 image: url(":/qss_icons/rc/checkbox_unchecked_focus.png");
270}
271
272QGroupBox::indicator:unchecked:disabled {
273 image: url(":/qss_icons/rc/checkbox_unchecked_disabled.png");
274}
275
276QGroupBox::indicator:checked {
277 border: none;
278 image: url(":/qss_icons/rc/checkbox_checked.png");
279}
280
281QGroupBox::indicator:checked:hover, QGroupBox::indicator:checked:focus, QGroupBox::indicator:checked:pressed {
282 border: none;
283 image: url(":/qss_icons/rc/checkbox_checked_focus.png");
284}
285
286QGroupBox::indicator:checked:disabled {
287 image: url(":/qss_icons/rc/checkbox_checked_disabled.png");
288}
289
290/* QRadioButton -----------------------------------------------------------
291
292https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qradiobutton
293
294--------------------------------------------------------------------------- */
295QRadioButton {
296 background-color: #19232D;
297 color: #F0F0F0;
298 spacing: 4px;
299 padding: 0px;
300 border: none;
301 outline: none;
302}
303
304QRadioButton:focus {
305 border: none;
306}
307
308QRadioButton:disabled {
309 background-color: #19232D;
310 color: #787878;
311 border: none;
312 outline: none;
313}
314
315QRadioButton QWidget {
316 background-color: #19232D;
317 color: #F0F0F0;
318 spacing: 0px;
319 padding: 0px;
320 outline: none;
321 border: none;
322}
323
324QRadioButton::indicator {
325 border: none;
326 outline: none;
327 margin-left: 4px;
328 height: 16px;
329 width: 16px;
330}
331
332QRadioButton::indicator:unchecked {
333 image: url(":/qss_icons/rc/radio_unchecked.png");
334}
335
336QRadioButton::indicator:unchecked:hover, QRadioButton::indicator:unchecked:focus, QRadioButton::indicator:unchecked:pressed {
337 border: none;
338 outline: none;
339 image: url(":/qss_icons/rc/radio_unchecked_focus.png");
340}
341
342QRadioButton::indicator:unchecked:disabled {
343 image: url(":/qss_icons/rc/radio_unchecked_disabled.png");
344}
345
346QRadioButton::indicator:checked {
347 border: none;
348 outline: none;
349 image: url(":/qss_icons/rc/radio_checked.png");
350}
351
352QRadioButton::indicator:checked:hover, QRadioButton::indicator:checked:focus, QRadioButton::indicator:checked:pressed {
353 border: none;
354 outline: none;
355 image: url(":/qss_icons/rc/radio_checked_focus.png");
356}
357
358QRadioButton::indicator:checked:disabled {
359 outline: none;
360 image: url(":/qss_icons/rc/radio_checked_disabled.png");
361}
362
363/* QMenuBar ---------------------------------------------------------------
364
365https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qmenubar
366
367--------------------------------------------------------------------------- */
368QMenuBar {
369 background-color: #32414B;
370 padding: 2px;
371 border: 1px solid #19232D;
372 color: #F0F0F0;
373}
374
375QMenuBar:focus {
376 border: 1px solid #148CD2;
377}
378
379QMenuBar::item {
380 background: transparent;
381 padding: 4px;
382}
383
384QMenuBar::item:selected {
385 padding: 4px;
386 background: transparent;
387 border: 0px solid #32414B;
388}
389
390QMenuBar::item:pressed {
391 padding: 4px;
392 border: 0px solid #32414B;
393 background-color: #148CD2;
394 color: #F0F0F0;
395 margin-bottom: 0px;
396 padding-bottom: 0px;
397}
398
399/* QMenu ------------------------------------------------------------------
400
401https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qmenu
402
403--------------------------------------------------------------------------- */
404QMenu {
405 border: 0px solid #32414B;
406 color: #F0F0F0;
407 margin: 0px;
408}
409
410QMenu::separator {
411 height: 1px;
412 background-color: #505F69;
413 color: #F0F0F0;
414}
415
416QMenu::icon {
417 margin: 0px;
418 padding-left: 8px;
419}
420
421QMenu::item {
422 background-color: #32414B;
423 padding: 4px 24px 4px 24px;
424 /* Reserve space for selection border */
425 border: 1px transparent #32414B;
426}
427
428QMenu::item:selected {
429 color: #F0F0F0;
430}
431
432QMenu::indicator {
433 width: 12px;
434 height: 12px;
435 padding-left: 6px;
436 /* non-exclusive indicator = check box style indicator (see QActionGroup::setExclusive) */
437 /* exclusive indicator = radio button style indicator (see QActionGroup::setExclusive) */
438}
439
440QMenu::indicator:non-exclusive:unchecked {
441 image: url(":/qss_icons/rc/checkbox_unchecked.png");
442}
443
444QMenu::indicator:non-exclusive:unchecked:selected {
445 image: url(":/qss_icons/rc/checkbox_unchecked_disabled.png");
446}
447
448QMenu::indicator:non-exclusive:checked {
449 image: url(":/qss_icons/rc/checkbox_checked.png");
450}
451
452QMenu::indicator:non-exclusive:checked:selected {
453 image: url(":/qss_icons/rc/checkbox_checked_disabled.png");
454}
455
456QMenu::indicator:exclusive:unchecked {
457 image: url(":/qss_icons/rc/radio_unchecked.png");
458}
459
460QMenu::indicator:exclusive:unchecked:selected {
461 image: url(":/qss_icons/rc/radio_unchecked_disabled.png");
462}
463
464QMenu::indicator:exclusive:checked {
465 image: url(":/qss_icons/rc/radio_checked.png");
466}
467
468QMenu::indicator:exclusive:checked:selected {
469 image: url(":/qss_icons/rc/radio_checked_disabled.png");
470}
471
472QMenu::right-arrow {
473 margin: 5px;
474 image: url(":/qss_icons/rc/arrow_right.png");
475 height: 12px;
476 width: 12px;
477}
478
479/* QAbstractItemView ------------------------------------------------------
480
481https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qcombobox
482
483--------------------------------------------------------------------------- */
484QAbstractItemView {
485 alternate-background-color: #19232D;
486 color: #F0F0F0;
487 border: 1px solid #32414B;
488 border-radius: 4px;
489}
490
491QAbstractItemView QLineEdit {
492 padding: 2px;
493}
494
495/* QAbstractScrollArea ----------------------------------------------------
496
497https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qabstractscrollarea
498
499--------------------------------------------------------------------------- */
500QAbstractScrollArea {
501 background-color: #19232D;
502 border: 1px solid #32414B;
503 border-radius: 4px;
504 padding: 2px;
505 /* fix #159 */
506 min-height: 1.25em;
507 /* fix #159 */
508 color: #F0F0F0;
509}
510
511QAbstractScrollArea:disabled {
512 color: #787878;
513}
514
515/* QScrollArea ------------------------------------------------------------
516
517--------------------------------------------------------------------------- */
518QScrollArea QWidget QWidget:disabled {
519 background-color: #19232D;
520}
521
522/* QScrollBar -------------------------------------------------------------
523
524https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qscrollbar
525
526--------------------------------------------------------------------------- */
527QScrollBar:horizontal {
528 height: 16px;
529 margin: 2px 16px 2px 16px;
530 border: 1px solid #32414B;
531 border-radius: 4px;
532 background-color: #19232D;
533}
534
535QScrollBar:vertical {
536 background-color: #19232D;
537 width: 16px;
538 margin: 16px 2px 16px 2px;
539 border: 1px solid #32414B;
540 border-radius: 4px;
541}
542
543QScrollBar::handle:horizontal {
544 background-color: #787878;
545 border: 1px solid #32414B;
546 border-radius: 4px;
547 min-width: 8px;
548}
549
550QScrollBar::handle:horizontal:hover {
551 background-color: #148CD2;
552 border: 1px solid #148CD2;
553 border-radius: 4px;
554 min-width: 8px;
555}
556
557QScrollBar::handle:horizontal:focus {
558 border: 1px solid #1464A0;
559}
560
561QScrollBar::handle:vertical {
562 background-color: #787878;
563 border: 1px solid #32414B;
564 min-height: 8px;
565 border-radius: 4px;
566}
567
568QScrollBar::handle:vertical:hover {
569 background-color: #148CD2;
570 border: 1px solid #148CD2;
571 border-radius: 4px;
572 min-height: 8px;
573}
574
575QScrollBar::handle:vertical:focus {
576 border: 1px solid #1464A0;
577}
578
579QScrollBar::add-line:horizontal {
580 margin: 0px 0px 0px 0px;
581 border-image: url(":/qss_icons/rc/arrow_right_disabled.png");
582 height: 12px;
583 width: 12px;
584 subcontrol-position: right;
585 subcontrol-origin: margin;
586}
587
588QScrollBar::add-line:horizontal:hover, QScrollBar::add-line:horizontal:on {
589 border-image: url(":/qss_icons/rc/arrow_right.png");
590 height: 12px;
591 width: 12px;
592 subcontrol-position: right;
593 subcontrol-origin: margin;
594}
595
596QScrollBar::add-line:vertical {
597 margin: 3px 0px 3px 0px;
598 border-image: url(":/qss_icons/rc/arrow_down_disabled.png");
599 height: 12px;
600 width: 12px;
601 subcontrol-position: bottom;
602 subcontrol-origin: margin;
603}
604
605QScrollBar::add-line:vertical:hover, QScrollBar::add-line:vertical:on {
606 border-image: url(":/qss_icons/rc/arrow_down.png");
607 height: 12px;
608 width: 12px;
609 subcontrol-position: bottom;
610 subcontrol-origin: margin;
611}
612
613QScrollBar::sub-line:horizontal {
614 margin: 0px 3px 0px 3px;
615 border-image: url(":/qss_icons/rc/arrow_left_disabled.png");
616 height: 12px;
617 width: 12px;
618 subcontrol-position: left;
619 subcontrol-origin: margin;
620}
621
622QScrollBar::sub-line:horizontal:hover, QScrollBar::sub-line:horizontal:on {
623 border-image: url(":/qss_icons/rc/arrow_left.png");
624 height: 12px;
625 width: 12px;
626 subcontrol-position: left;
627 subcontrol-origin: margin;
628}
629
630QScrollBar::sub-line:vertical {
631 margin: 3px 0px 3px 0px;
632 border-image: url(":/qss_icons/rc/arrow_up_disabled.png");
633 height: 12px;
634 width: 12px;
635 subcontrol-position: top;
636 subcontrol-origin: margin;
637}
638
639QScrollBar::sub-line:vertical:hover, QScrollBar::sub-line:vertical:on {
640 border-image: url(":/qss_icons/rc/arrow_up.png");
641 height: 12px;
642 width: 12px;
643 subcontrol-position: top;
644 subcontrol-origin: margin;
645}
646
647QScrollBar::up-arrow:horizontal, QScrollBar::down-arrow:horizontal {
648 background: none;
649}
650
651QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical {
652 background: none;
653}
654
655QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal {
656 background: none;
657}
658
659QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical {
660 background: none;
661}
662
663/* QTextEdit --------------------------------------------------------------
664
665https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-specific-widgets
666
667--------------------------------------------------------------------------- */
668QTextEdit {
669 background-color: #19232D;
670 color: #F0F0F0;
671 border-radius: 4px;
672 border: 1px solid #32414B;
673}
674
675QTextEdit:hover {
676 border: 1px solid #148CD2;
677 color: #F0F0F0;
678}
679
680QTextEdit:focus {
681 border: 1px solid #1464A0;
682}
683
684QTextEdit:selected {
685 background: #1464A0;
686 color: #32414B;
687}
688
689/* QPlainTextEdit ---------------------------------------------------------
690
691--------------------------------------------------------------------------- */
692QPlainTextEdit {
693 background-color: #19232D;
694 color: #F0F0F0;
695 border-radius: 4px;
696 border: 1px solid #32414B;
697}
698
699QPlainTextEdit:hover {
700 border: 1px solid #148CD2;
701 color: #F0F0F0;
702}
703
704QPlainTextEdit:focus {
705 border: 1px solid #1464A0;
706}
707
708QPlainTextEdit:selected {
709 background: #1464A0;
710 color: #32414B;
711}
712
713/* QSizeGrip --------------------------------------------------------------
714
715https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qsizegrip
716
717--------------------------------------------------------------------------- */
718QSizeGrip {
719 background: transparent;
720 width: 12px;
721 height: 12px;
722 image: url(":/qss_icons/rc/window_grip.png");
723}
724
725/* QStackedWidget ---------------------------------------------------------
726
727--------------------------------------------------------------------------- */
728QStackedWidget {
729 padding: 2px;
730 border: 1px solid #32414B;
731 border: 1px solid #19232D;
732}
733
734/* QToolBar ---------------------------------------------------------------
735
736https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtoolbar
737
738--------------------------------------------------------------------------- */
739QToolBar {
740 background-color: #32414B;
741 border-bottom: 1px solid #19232D;
742 padding: 2px;
743 font-weight: bold;
744 spacing: 2px;
745}
746
747QToolBar QToolButton {
748 background-color: #32414B;
749 border: 1px solid #32414B;
750}
751
752QToolBar QToolButton:hover {
753 border: 1px solid #148CD2;
754}
755
756QToolBar QToolButton:checked {
757 border: 1px solid #19232D;
758 background-color: #19232D;
759}
760
761QToolBar QToolButton:checked:hover {
762 border: 1px solid #148CD2;
763}
764
765QToolBar::handle:horizontal {
766 width: 16px;
767 image: url(":/qss_icons/rc/toolbar_move_horizontal.png");
768}
769
770QToolBar::handle:vertical {
771 height: 16px;
772 image: url(":/qss_icons/rc/toolbar_move_vertical.png");
773}
774
775QToolBar::separator:horizontal {
776 width: 16px;
777 image: url(":/qss_icons/rc/toolbar_separator_horizontal.png");
778}
779
780QToolBar::separator:vertical {
781 height: 16px;
782 image: url(":/qss_icons/rc/toolbar_separator_vertical.png");
783}
784
785QToolButton#qt_toolbar_ext_button {
786 background: #32414B;
787 border: 0px;
788 color: #F0F0F0;
789 image: url(":/qss_icons/rc/arrow_right.png");
790}
791
792/* QAbstractSpinBox -------------------------------------------------------
793
794--------------------------------------------------------------------------- */
795QAbstractSpinBox {
796 background-color: #19232D;
797 border: 1px solid #32414B;
798 color: #F0F0F0;
799 /* This fixes 103, 111 */
800 padding-top: 2px;
801 /* This fixes 103, 111 */
802 padding-bottom: 2px;
803 padding-left: 4px;
804 padding-right: 4px;
805 border-radius: 4px;
806 /* min-width: 5px; removed to fix 109 */
807}
808
809QAbstractSpinBox:up-button {
810 background-color: transparent #19232D;
811 subcontrol-origin: border;
812 subcontrol-position: top right;
813 border-left: 1px solid #32414B;
814 border-bottom: 1px solid #32414B;
815 border-top-left-radius: 0;
816 border-bottom-left-radius: 0;
817 margin: 1px;
818 width: 12px;
819 margin-bottom: -1px;
820}
821
822QAbstractSpinBox::up-arrow, QAbstractSpinBox::up-arrow:disabled, QAbstractSpinBox::up-arrow:off {
823 image: url(":/qss_icons/rc/arrow_up_disabled.png");
824 height: 8px;
825 width: 8px;
826}
827
828QAbstractSpinBox::up-arrow:hover {
829 image: url(":/qss_icons/rc/arrow_up.png");
830}
831
832QAbstractSpinBox:down-button {
833 background-color: transparent #19232D;
834 subcontrol-origin: border;
835 subcontrol-position: bottom right;
836 border-left: 1px solid #32414B;
837 border-top: 1px solid #32414B;
838 border-top-left-radius: 0;
839 border-bottom-left-radius: 0;
840 margin: 1px;
841 width: 12px;
842 margin-top: -1px;
843}
844
845QAbstractSpinBox::down-arrow, QAbstractSpinBox::down-arrow:disabled, QAbstractSpinBox::down-arrow:off {
846 image: url(":/qss_icons/rc/arrow_down_disabled.png");
847 height: 8px;
848 width: 8px;
849}
850
851QAbstractSpinBox::down-arrow:hover {
852 image: url(":/qss_icons/rc/arrow_down.png");
853}
854
855QAbstractSpinBox:hover {
856 border: 1px solid #148CD2;
857 color: #F0F0F0;
858}
859
860QAbstractSpinBox:focus {
861 border: 1px solid #1464A0;
862}
863
864QAbstractSpinBox:selected {
865 background: #1464A0;
866 color: #32414B;
867}
868
869/* ------------------------------------------------------------------------ */
870/* DISPLAYS --------------------------------------------------------------- */
871/* ------------------------------------------------------------------------ */
872/* QLabel -----------------------------------------------------------------
873
874https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qframe
875
876--------------------------------------------------------------------------- */
877QLabel {
878 background-color: #19232D;
879 border: 0px solid #32414B;
880 padding: 2px;
881 margin: 0px;
882 color: #F0F0F0;
883}
884
885QLabel:disabled {
886 background-color: #19232D;
887 border: 0px solid #32414B;
888 color: #787878;
889}
890
891/* QTextBrowser -----------------------------------------------------------
892
893https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qabstractscrollarea
894
895--------------------------------------------------------------------------- */
896QTextBrowser {
897 background-color: #19232D;
898 border: 1px solid #32414B;
899 color: #F0F0F0;
900 border-radius: 4px;
901}
902
903QTextBrowser:disabled {
904 background-color: #19232D;
905 border: 1px solid #32414B;
906 color: #787878;
907 border-radius: 4px;
908}
909
910QTextBrowser:hover, QTextBrowser:!hover, QTextBrowser:selected, QTextBrowser:pressed {
911 border: 1px solid #32414B;
912}
913
914/* QGraphicsView ----------------------------------------------------------
915
916--------------------------------------------------------------------------- */
917QGraphicsView {
918 background-color: #19232D;
919 border: 1px solid #32414B;
920 color: #F0F0F0;
921 border-radius: 4px;
922}
923
924QGraphicsView:disabled {
925 background-color: #19232D;
926 border: 1px solid #32414B;
927 color: #787878;
928 border-radius: 4px;
929}
930
931QGraphicsView:hover, QGraphicsView:!hover, QGraphicsView:selected, QGraphicsView:pressed {
932 border: 1px solid #32414B;
933}
934
935/* QCalendarWidget --------------------------------------------------------
936
937--------------------------------------------------------------------------- */
938QCalendarWidget {
939 border: 1px solid #32414B;
940 border-radius: 4px;
941}
942
943QCalendarWidget:disabled {
944 background-color: #19232D;
945 color: #787878;
946}
947
948/* QLCDNumber -------------------------------------------------------------
949
950--------------------------------------------------------------------------- */
951QLCDNumber {
952 background-color: #19232D;
953 color: #F0F0F0;
954}
955
956QLCDNumber:disabled {
957 background-color: #19232D;
958 color: #787878;
959}
960
961/* QProgressBar -----------------------------------------------------------
962
963https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qprogressbar
964
965--------------------------------------------------------------------------- */
966QProgressBar {
967 background-color: #19232D;
968 border: 1px solid #32414B;
969 color: #F0F0F0;
970 border-radius: 4px;
971 text-align: center;
972}
973
974QProgressBar:disabled {
975 background-color: #19232D;
976 border: 1px solid #32414B;
977 color: #787878;
978 border-radius: 4px;
979 text-align: center;
980}
981
982QProgressBar::chunk {
983 background-color: #1464A0;
984 color: #19232D;
985 border-radius: 4px;
986}
987
988QProgressBar::chunk:disabled {
989 background-color: #14506E;
990 color: #787878;
991 border-radius: 4px;
992}
993
994/* ------------------------------------------------------------------------ */
995/* BUTTONS ---------------------------------------------------------------- */
996/* ------------------------------------------------------------------------ */
997/* QPushButton ------------------------------------------------------------
998
999https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qpushbutton
1000
1001--------------------------------------------------------------------------- */
1002QPushButton {
1003 background-color: #505F69;
1004 border: 1px solid #32414B;
1005 color: #F0F0F0;
1006 border-radius: 4px;
1007 padding: 3px;
1008 outline: none;
1009 /* Issue #194 - Special case of QPushButton inside dialogs, for better UI */
1010 min-width: 80px;
1011}
1012
1013QPushButton:disabled {
1014 background-color: #32414B;
1015 border: 1px solid #32414B;
1016 color: #787878;
1017 border-radius: 4px;
1018 padding: 3px;
1019}
1020
1021QPushButton:checked {
1022 background-color: #32414B;
1023 border: 1px solid #32414B;
1024 border-radius: 4px;
1025 padding: 3px;
1026 outline: none;
1027}
1028
1029QPushButton:checked:disabled {
1030 background-color: #19232D;
1031 border: 1px solid #32414B;
1032 color: #787878;
1033 border-radius: 4px;
1034 padding: 3px;
1035 outline: none;
1036}
1037
1038QPushButton:checked:selected {
1039 background: #1464A0;
1040 color: #32414B;
1041}
1042
1043QPushButton::menu-indicator {
1044 subcontrol-origin: padding;
1045 subcontrol-position: bottom right;
1046 bottom: 4px;
1047}
1048
1049QPushButton:pressed {
1050 background-color: #19232D;
1051 border: 1px solid #19232D;
1052}
1053
1054QPushButton:pressed:hover {
1055 border: 1px solid #148CD2;
1056}
1057
1058QPushButton:hover {
1059 border: 1px solid #148CD2;
1060 color: #F0F0F0;
1061}
1062
1063QPushButton:selected {
1064 background: #1464A0;
1065 color: #32414B;
1066}
1067
1068QPushButton:hover {
1069 border: 1px solid #148CD2;
1070 color: #F0F0F0;
1071}
1072
1073QPushButton:focus {
1074 border: 1px solid #1464A0;
1075}
1076
1077/* QToolButton ------------------------------------------------------------
1078
1079https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtoolbutton
1080
1081--------------------------------------------------------------------------- */
1082QToolButton {
1083 background-color: transparent;
1084 border: 1px solid transparent;
1085 border-radius: 4px;
1086 margin: 0px;
1087 padding: 2px;
1088 /* The subcontrols below are used only in the DelayedPopup mode */
1089 /* The subcontrols below are used only in the MenuButtonPopup mode */
1090 /* The subcontrol below is used only in the InstantPopup or DelayedPopup mode */
1091}
1092
1093QToolButton:checked {
1094 background-color: transparent;
1095 border: 1px solid #1464A0;
1096}
1097
1098QToolButton:checked:disabled {
1099 border: 1px solid #14506E;
1100}
1101
1102QToolButton:pressed {
1103 margin: 1px;
1104 background-color: transparent;
1105 border: 1px solid #1464A0;
1106}
1107
1108QToolButton:disabled {
1109 border: none;
1110}
1111
1112QToolButton:hover {
1113 border: 1px solid #148CD2;
1114}
1115
1116QToolButton[popupMode="0"] {
1117 /* Only for DelayedPopup */
1118 padding-right: 2px;
1119}
1120
1121QToolButton[popupMode="1"] {
1122 /* Only for MenuButtonPopup */
1123 padding-right: 20px;
1124}
1125
1126QToolButton[popupMode="1"]::menu-button {
1127 border: none;
1128}
1129
1130QToolButton[popupMode="1"]::menu-button:hover {
1131 border: none;
1132 border-left: 1px solid #148CD2;
1133 border-radius: 0;
1134}
1135
1136QToolButton[popupMode="2"] {
1137 /* Only for InstantPopup */
1138 padding-right: 2px;
1139}
1140
1141QToolButton::menu-button {
1142 padding: 2px;
1143 border-radius: 4px;
1144 border: 1px solid #32414B;
1145 width: 12px;
1146 outline: none;
1147}
1148
1149QToolButton::menu-button:hover {
1150 border: 1px solid #148CD2;
1151}
1152
1153QToolButton::menu-button:checked:hover {
1154 border: 1px solid #148CD2;
1155}
1156
1157QToolButton::menu-indicator {
1158 image: url(":/qss_icons/rc/arrow_down.png");
1159 height: 8px;
1160 width: 8px;
1161 top: 0;
1162 /* Exclude a shift for better image */
1163 left: -2px;
1164 /* Shift it a bit */
1165}
1166
1167QToolButton::menu-arrow {
1168 image: url(":/qss_icons/rc/arrow_down.png");
1169 height: 8px;
1170 width: 8px;
1171}
1172
1173QToolButton::menu-arrow:hover {
1174 image: url(":/qss_icons/rc/arrow_down_focus.png");
1175}
1176
1177/* QCommandLinkButton -----------------------------------------------------
1178
1179--------------------------------------------------------------------------- */
1180QCommandLinkButton {
1181 background-color: transparent;
1182 border: 1px solid #32414B;
1183 color: #F0F0F0;
1184 border-radius: 4px;
1185 padding: 0px;
1186 margin: 0px;
1187}
1188
1189QCommandLinkButton:disabled {
1190 background-color: transparent;
1191 color: #787878;
1192}
1193
1194/* ------------------------------------------------------------------------ */
1195/* INPUTS - NO FIELDS ----------------------------------------------------- */
1196/* ------------------------------------------------------------------------ */
1197/* QComboBox --------------------------------------------------------------
1198
1199https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qcombobox
1200
1201--------------------------------------------------------------------------- */
1202QComboBox {
1203 border: 1px solid #32414B;
1204 border-radius: 4px;
1205 selection-background-color: #1464A0;
1206 padding-left: 4px;
1207 padding-right: 36px;
1208 /* 4 + 16*2 See scrollbar size */
1209 /* Fixes #103, #111 */
1210 min-height: 1.5em;
1211 /* padding-top: 2px; removed to fix #132 */
1212 /* padding-bottom: 2px; removed to fix #132 */
1213 /* min-width: 75px; removed to fix #109 */
1214 /* Needed to remove indicator - fix #132 */
1215}
1216
1217QComboBox QAbstractItemView {
1218 border: 1px solid #32414B;
1219 border-radius: 0;
1220 background-color: #19232D;
1221 selection-background-color: #1464A0;
1222}
1223
1224QComboBox QAbstractItemView:hover {
1225 background-color: #19232D;
1226 color: #F0F0F0;
1227}
1228
1229QComboBox QAbstractItemView:selected {
1230 background: #1464A0;
1231 color: #32414B;
1232}
1233
1234QComboBox QAbstractItemView:alternate {
1235 background: #19232D;
1236}
1237
1238QComboBox:disabled {
1239 background-color: #19232D;
1240 color: #787878;
1241}
1242
1243QComboBox:hover {
1244 border: 1px solid #148CD2;
1245}
1246
1247QComboBox:focus {
1248 border: 1px solid #1464A0;
1249}
1250
1251QComboBox:on {
1252 selection-background-color: #1464A0;
1253}
1254
1255QComboBox::indicator {
1256 border: none;
1257 border-radius: 0;
1258 background-color: transparent;
1259 selection-background-color: transparent;
1260 color: transparent;
1261 selection-color: transparent;
1262 /* Needed to remove indicator - fix #132 */
1263}
1264
1265QComboBox::indicator:alternate {
1266 background: #19232D;
1267}
1268
1269QComboBox::item:alternate {
1270 background: #19232D;
1271}
1272
1273QComboBox::item:checked {
1274 font-weight: bold;
1275}
1276
1277QComboBox::item:selected {
1278 border: 0px solid transparent;
1279}
1280
1281QComboBox::drop-down {
1282 subcontrol-origin: padding;
1283 subcontrol-position: top right;
1284 width: 12px;
1285 border-left: 1px solid #32414B;
1286}
1287
1288QComboBox::down-arrow {
1289 image: url(":/qss_icons/rc/arrow_down_disabled.png");
1290 height: 8px;
1291 width: 8px;
1292}
1293
1294QComboBox::down-arrow:on, QComboBox::down-arrow:hover, QComboBox::down-arrow:focus {
1295 image: url(":/qss_icons/rc/arrow_down.png");
1296}
1297
1298/* QSlider ----------------------------------------------------------------
1299
1300https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qslider
1301
1302--------------------------------------------------------------------------- */
1303QSlider:disabled {
1304 background: #19232D;
1305}
1306
1307QSlider:focus {
1308 border: none;
1309}
1310
1311QSlider::groove:horizontal {
1312 background: #32414B;
1313 border: 1px solid #32414B;
1314 height: 4px;
1315 margin: 0px;
1316 border-radius: 4px;
1317}
1318
1319QSlider::groove:vertical {
1320 background: #32414B;
1321 border: 1px solid #32414B;
1322 width: 4px;
1323 margin: 0px;
1324 border-radius: 4px;
1325}
1326
1327QSlider::add-page:vertical {
1328 background: #1464A0;
1329 border: 1px solid #32414B;
1330 width: 4px;
1331 margin: 0px;
1332 border-radius: 4px;
1333}
1334
1335QSlider::add-page:vertical :disabled {
1336 background: #14506E;
1337}
1338
1339QSlider::sub-page:horizontal {
1340 background: #1464A0;
1341 border: 1px solid #32414B;
1342 height: 4px;
1343 margin: 0px;
1344 border-radius: 4px;
1345}
1346
1347QSlider::sub-page:horizontal:disabled {
1348 background: #14506E;
1349}
1350
1351QSlider::handle:horizontal {
1352 background: #787878;
1353 border: 1px solid #32414B;
1354 width: 8px;
1355 height: 8px;
1356 margin: -8px 0px;
1357 border-radius: 4px;
1358}
1359
1360QSlider::handle:horizontal:hover {
1361 background: #148CD2;
1362 border: 1px solid #148CD2;
1363}
1364
1365QSlider::handle:horizontal:focus {
1366 border: 1px solid #1464A0;
1367}
1368
1369QSlider::handle:vertical {
1370 background: #787878;
1371 border: 1px solid #32414B;
1372 width: 8px;
1373 height: 8px;
1374 margin: 0 -8px;
1375 border-radius: 4px;
1376}
1377
1378QSlider::handle:vertical:hover {
1379 background: #148CD2;
1380 border: 1px solid #148CD2;
1381}
1382
1383QSlider::handle:vertical:focus {
1384 border: 1px solid #1464A0;
1385}
1386
1387/* QLineEdit --------------------------------------------------------------
1388
1389https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qlineedit
1390
1391--------------------------------------------------------------------------- */
1392QLineEdit {
1393 background-color: #19232D;
1394 padding-top: 2px;
1395 /* This QLineEdit fix 103, 111 */
1396 padding-bottom: 2px;
1397 /* This QLineEdit fix 103, 111 */
1398 padding-left: 4px;
1399 padding-right: 4px;
1400 border-style: solid;
1401 border: 1px solid #32414B;
1402 border-radius: 4px;
1403 color: #F0F0F0;
1404}
1405
1406QLineEdit:disabled {
1407 background-color: #19232D;
1408 color: #787878;
1409}
1410
1411QLineEdit:hover {
1412 border: 1px solid #148CD2;
1413 color: #F0F0F0;
1414}
1415
1416QLineEdit:focus {
1417 border: 1px solid #1464A0;
1418}
1419
1420QLineEdit:selected {
1421 background-color: #1464A0;
1422 color: #32414B;
1423}
1424
1425/* QTabWiget --------------------------------------------------------------
1426
1427https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtabwidget-and-qtabbar
1428
1429--------------------------------------------------------------------------- */
1430QTabWidget {
1431 padding: 2px;
1432 selection-background-color: #32414B;
1433}
1434
1435QTabWidget QWidget {
1436 /* Fixes #189 */
1437 border-radius: 4px;
1438}
1439
1440QTabWidget::pane {
1441 border: 1px solid #32414B;
1442 border-radius: 4px;
1443 margin: 0px;
1444 /* Fixes double border inside pane with pyqt5 */
1445 padding: 0px;
1446}
1447
1448QTabWidget::pane:selected {
1449 background-color: #32414B;
1450 border: 1px solid #1464A0;
1451}
1452
1453/* QTabBar ----------------------------------------------------------------
1454
1455https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtabwidget-and-qtabbar
1456
1457--------------------------------------------------------------------------- */
1458QTabBar {
1459 qproperty-drawBase: 0;
1460 border-radius: 4px;
1461 margin: 0px;
1462 padding: 2px;
1463 border: 0;
1464 /* left: 5px; move to the right by 5px - removed for fix */
1465}
1466
1467QTabBar::close-button {
1468 border: 0;
1469 margin: 2px;
1470 padding: 2px;
1471 image: url(":/qss_icons/rc/window_close.png");
1472}
1473
1474QTabBar::close-button:hover {
1475 image: url(":/qss_icons/rc/window_close_focus.png");
1476}
1477
1478QTabBar::close-button:pressed {
1479 image: url(":/qss_icons/rc/window_close_pressed.png");
1480}
1481
1482/* QTabBar::tab - selected ------------------------------------------------
1483
1484https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtabwidget-and-qtabbar
1485
1486--------------------------------------------------------------------------- */
1487QTabBar::tab {
1488 /* !selected and disabled ----------------------------------------- */
1489 /* selected ------------------------------------------------------- */
1490}
1491
1492QTabBar::tab:top:selected:disabled {
1493 border-bottom: 3px solid #14506E;
1494 color: #787878;
1495 background-color: #32414B;
1496}
1497
1498QTabBar::tab:bottom:selected:disabled {
1499 border-top: 3px solid #14506E;
1500 color: #787878;
1501 background-color: #32414B;
1502}
1503
1504QTabBar::tab:left:selected:disabled {
1505 border-right: 3px solid #14506E;
1506 color: #787878;
1507 background-color: #32414B;
1508}
1509
1510QTabBar::tab:right:selected:disabled {
1511 border-left: 3px solid #14506E;
1512 color: #787878;
1513 background-color: #32414B;
1514}
1515
1516QTabBar::tab:top:!selected:disabled {
1517 border-bottom: 3px solid #19232D;
1518 color: #787878;
1519 background-color: #19232D;
1520}
1521
1522QTabBar::tab:bottom:!selected:disabled {
1523 border-top: 3px solid #19232D;
1524 color: #787878;
1525 background-color: #19232D;
1526}
1527
1528QTabBar::tab:left:!selected:disabled {
1529 border-right: 3px solid #19232D;
1530 color: #787878;
1531 background-color: #19232D;
1532}
1533
1534QTabBar::tab:right:!selected:disabled {
1535 border-left: 3px solid #19232D;
1536 color: #787878;
1537 background-color: #19232D;
1538}
1539
1540QTabBar::tab:top:!selected {
1541 border-bottom: 2px solid #19232D;
1542 margin-top: 2px;
1543}
1544
1545QTabBar::tab:bottom:!selected {
1546 border-top: 2px solid #19232D;
1547 margin-bottom: 3px;
1548}
1549
1550QTabBar::tab:left:!selected {
1551 border-left: 2px solid #19232D;
1552 margin-right: 2px;
1553}
1554
1555QTabBar::tab:right:!selected {
1556 border-right: 2px solid #19232D;
1557 margin-left: 2px;
1558}
1559
1560QTabBar::tab:top {
1561 background-color: #32414B;
1562 color: #F0F0F0;
1563 margin-left: 2px;
1564 padding-left: 4px;
1565 padding-right: 4px;
1566 padding-top: 2px;
1567 padding-bottom: 2px;
1568 min-width: 5px;
1569 border-bottom: 3px solid #32414B;
1570 border-top-left-radius: 3px;
1571 border-top-right-radius: 3px;
1572}
1573
1574QTabBar::tab:top:selected {
1575 background-color: #505F69;
1576 color: #F0F0F0;
1577 border-bottom: 3px solid #1464A0;
1578 border-top-left-radius: 3px;
1579 border-top-right-radius: 3px;
1580}
1581
1582QTabBar::tab:top:!selected:hover {
1583 border: 1px solid #148CD2;
1584 border-bottom: 3px solid #148CD2;
1585 /* Fixes spyder-ide/spyder#9766 */
1586 padding-left: 4px;
1587 padding-right: 4px;
1588}
1589
1590QTabBar::tab:bottom {
1591 color: #F0F0F0;
1592 border-top: 3px solid #32414B;
1593 background-color: #32414B;
1594 margin-left: 2px;
1595 padding-left: 4px;
1596 padding-right: 4px;
1597 padding-top: 2px;
1598 padding-bottom: 2px;
1599 border-bottom-left-radius: 3px;
1600 border-bottom-right-radius: 3px;
1601 min-width: 5px;
1602}
1603
1604QTabBar::tab:bottom:selected {
1605 color: #F0F0F0;
1606 background-color: #505F69;
1607 border-top: 3px solid #1464A0;
1608 border-bottom-left-radius: 3px;
1609 border-bottom-right-radius: 3px;
1610}
1611
1612QTabBar::tab:bottom:!selected:hover {
1613 border: 1px solid #148CD2;
1614 border-top: 3px solid #148CD2;
1615 /* Fixes spyder-ide/spyder#9766 */
1616 padding-left: 4px;
1617 padding-right: 4px;
1618}
1619
1620QTabBar::tab:left {
1621 color: #F0F0F0;
1622 background-color: #32414B;
1623 margin-top: 2px;
1624 padding-left: 2px;
1625 padding-right: 2px;
1626 padding-top: 4px;
1627 padding-bottom: 4px;
1628 border-top-left-radius: 3px;
1629 border-bottom-left-radius: 3px;
1630 min-height: 5px;
1631}
1632
1633QTabBar::tab:left:selected {
1634 color: #F0F0F0;
1635 background-color: #505F69;
1636 border-right: 3px solid #1464A0;
1637}
1638
1639QTabBar::tab:left:!selected:hover {
1640 border: 1px solid #148CD2;
1641 border-right: 3px solid #148CD2;
1642 padding: 0px;
1643}
1644
1645QTabBar::tab:right {
1646 color: #F0F0F0;
1647 background-color: #32414B;
1648 margin-top: 2px;
1649 padding-left: 2px;
1650 padding-right: 2px;
1651 padding-top: 4px;
1652 padding-bottom: 4px;
1653 border-top-right-radius: 3px;
1654 border-bottom-right-radius: 3px;
1655 min-height: 5px;
1656}
1657
1658QTabBar::tab:right:selected {
1659 color: #F0F0F0;
1660 background-color: #505F69;
1661 border-left: 3px solid #1464A0;
1662}
1663
1664QTabBar::tab:right:!selected:hover {
1665 border: 1px solid #148CD2;
1666 border-left: 3px solid #148CD2;
1667 padding: 0px;
1668}
1669
1670QTabBar QToolButton {
1671 /* Fixes #136 */
1672 background-color: #32414B;
1673 height: 12px;
1674 width: 12px;
1675}
1676
1677QTabBar QToolButton:pressed {
1678 background-color: #32414B;
1679}
1680
1681QTabBar QToolButton:pressed:hover {
1682 border: 1px solid #148CD2;
1683}
1684
1685QTabBar QToolButton::left-arrow:enabled {
1686 image: url(":/qss_icons/rc/arrow_left.png");
1687}
1688
1689QTabBar QToolButton::left-arrow:disabled {
1690 image: url(":/qss_icons/rc/arrow_left_disabled.png");
1691}
1692
1693QTabBar QToolButton::right-arrow:enabled {
1694 image: url(":/qss_icons/rc/arrow_right.png");
1695}
1696
1697QTabBar QToolButton::right-arrow:disabled {
1698 image: url(":/qss_icons/rc/arrow_right_disabled.png");
1699}
1700
1701/* QDockWiget -------------------------------------------------------------
1702
1703--------------------------------------------------------------------------- */
1704QDockWidget {
1705 outline: 1px solid #32414B;
1706 background-color: #19232D;
1707 border: 1px solid #32414B;
1708 border-radius: 4px;
1709 titlebar-close-icon: url(":/qss_icons/rc/window_close.png");
1710 titlebar-normal-icon: url(":/qss_icons/rc/window_undock.png");
1711}
1712
1713QDockWidget::title {
1714 /* Better size for title bar */
1715 padding: 6px;
1716 spacing: 4px;
1717 border: none;
1718 background-color: #32414B;
1719}
1720
1721QDockWidget::close-button {
1722 background-color: #32414B;
1723 border-radius: 4px;
1724 border: none;
1725}
1726
1727QDockWidget::close-button:hover {
1728 image: url(":/qss_icons/rc/window_close_focus.png");
1729}
1730
1731QDockWidget::close-button:pressed {
1732 image: url(":/qss_icons/rc/window_close_pressed.png");
1733}
1734
1735QDockWidget::float-button {
1736 background-color: #32414B;
1737 border-radius: 4px;
1738 border: none;
1739}
1740
1741QDockWidget::float-button:hover {
1742 image: url(":/qss_icons/rc/window_undock_focus.png");
1743}
1744
1745QDockWidget::float-button:pressed {
1746 image: url(":/qss_icons/rc/window_undock_pressed.png");
1747}
1748
1749/* QTreeView QListView QTableView -----------------------------------------
1750
1751https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtreeview
1752https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qlistview
1753https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtableview
1754
1755--------------------------------------------------------------------------- */
1756QTreeView:branch:selected, QTreeView:branch:hover {
1757 background: url(":/qss_icons/rc/transparent.png");
1758}
1759
1760QTreeView:branch:has-siblings:!adjoins-item {
1761 border-image: url(":/qss_icons/rc/branch_line.png") 0;
1762}
1763
1764QTreeView:branch:has-siblings:adjoins-item {
1765 border-image: url(":/qss_icons/rc/branch_more.png") 0;
1766}
1767
1768QTreeView:branch:!has-children:!has-siblings:adjoins-item {
1769 border-image: url(":/qss_icons/rc/branch_end.png") 0;
1770}
1771
1772QTreeView:branch:has-children:!has-siblings:closed, QTreeView:branch:closed:has-children:has-siblings {
1773 border-image: none;
1774 image: url(":/qss_icons/rc/branch_closed.png");
1775}
1776
1777QTreeView:branch:open:has-children:!has-siblings, QTreeView:branch:open:has-children:has-siblings {
1778 border-image: none;
1779 image: url(":/qss_icons/rc/branch_open.png");
1780}
1781
1782QTreeView:branch:has-children:!has-siblings:closed:hover, QTreeView:branch:closed:has-children:has-siblings:hover {
1783 image: url(":/qss_icons/rc/branch_closed_focus.png");
1784}
1785
1786QTreeView:branch:open:has-children:!has-siblings:hover, QTreeView:branch:open:has-children:has-siblings:hover {
1787 image: url(":/qss_icons/rc/branch_open_focus.png");
1788}
1789
1790QTreeView::indicator:checked,
1791QListView::indicator:checked {
1792 image: url(":/qss_icons/rc/checkbox_checked.png");
1793}
1794
1795QTreeView::indicator:checked:hover, QTreeView::indicator:checked:focus, QTreeView::indicator:checked:pressed,
1796QListView::indicator:checked:hover,
1797QListView::indicator:checked:focus,
1798QListView::indicator:checked:pressed {
1799 image: url(":/qss_icons/rc/checkbox_checked_focus.png");
1800}
1801
1802QTreeView::indicator:unchecked,
1803QListView::indicator:unchecked {
1804 image: url(":/qss_icons/rc/checkbox_unchecked.png");
1805}
1806
1807QTreeView::indicator:unchecked:hover, QTreeView::indicator:unchecked:focus, QTreeView::indicator:unchecked:pressed,
1808QListView::indicator:unchecked:hover,
1809QListView::indicator:unchecked:focus,
1810QListView::indicator:unchecked:pressed {
1811 image: url(":/qss_icons/rc/checkbox_unchecked_focus.png");
1812}
1813
1814QTreeView::indicator:indeterminate,
1815QListView::indicator:indeterminate {
1816 image: url(":/qss_icons/rc/checkbox_indeterminate.png");
1817}
1818
1819QTreeView::indicator:indeterminate:hover, QTreeView::indicator:indeterminate:focus, QTreeView::indicator:indeterminate:pressed,
1820QListView::indicator:indeterminate:hover,
1821QListView::indicator:indeterminate:focus,
1822QListView::indicator:indeterminate:pressed {
1823 image: url(":/qss_icons/rc/checkbox_indeterminate_focus.png");
1824}
1825
1826QTreeView,
1827QListView,
1828QTableView,
1829QColumnView {
1830 background-color: #19232D;
1831 border: 1px solid #32414B;
1832 color: #F0F0F0;
1833 gridline-color: #32414B;
1834 border-radius: 4px;
1835}
1836
1837QTreeView:disabled,
1838QListView:disabled,
1839QTableView:disabled,
1840QColumnView:disabled {
1841 background-color: #19232D;
1842 color: #787878;
1843}
1844
1845QTreeView:selected,
1846QListView:selected,
1847QTableView:selected,
1848QColumnView:selected {
1849 background-color: #1464A0;
1850 color: #32414B;
1851}
1852
1853QTreeView:hover,
1854QListView:hover,
1855QTableView:hover,
1856QColumnView:hover {
1857 background-color: #19232D;
1858 border: 1px solid #148CD2;
1859}
1860
1861QTreeView::item:pressed,
1862QListView::item:pressed,
1863QTableView::item:pressed,
1864QColumnView::item:pressed {
1865 background-color: #1464A0;
1866}
1867
1868QTreeView::item:selected:hover,
1869QListView::item:selected:hover,
1870QTableView::item:selected:hover,
1871QColumnView::item:selected:hover {
1872 background: #1464A0;
1873 color: #19232D;
1874}
1875
1876QTreeView::item:selected:active,
1877QListView::item:selected:active,
1878QTableView::item:selected:active,
1879QColumnView::item:selected:active {
1880 background-color: #1464A0;
1881}
1882
1883QTreeView::item:!selected:hover,
1884QListView::item:!selected:hover,
1885QTableView::item:!selected:hover,
1886QColumnView::item:!selected:hover {
1887 outline: 0;
1888 color: #148CD2;
1889 background-color: #32414B;
1890}
1891
1892QTableCornerButton::section {
1893 background-color: #19232D;
1894 border: 1px transparent #32414B;
1895 border-radius: 0px;
1896}
1897
1898/* QHeaderView ------------------------------------------------------------
1899
1900https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qheaderview
1901
1902--------------------------------------------------------------------------- */
1903QHeaderView {
1904 background-color: #32414B;
1905 border: 0px transparent #32414B;
1906 padding: 0px;
1907 margin: 0px;
1908 border-radius: 0px;
1909}
1910
1911QHeaderView:disabled {
1912 background-color: #32414B;
1913 border: 1px transparent #32414B;
1914 padding: 2px;
1915}
1916
1917QHeaderView::section {
1918 background-color: #32414B;
1919 color: #F0F0F0;
1920 padding: 2px;
1921 border-radius: 0px;
1922 text-align: left;
1923}
1924
1925QHeaderView::section:checked {
1926 color: #F0F0F0;
1927 background-color: #1464A0;
1928}
1929
1930QHeaderView::section:checked:disabled {
1931 color: #787878;
1932 background-color: #14506E;
1933}
1934
1935QHeaderView::section::horizontal {
1936 padding-left: 4px;
1937 padding-right: 4px;
1938 border-left: 1px solid #19232D;
1939}
1940
1941QHeaderView::section::horizontal::first, QHeaderView::section::horizontal::only-one {
1942 border-left: 1px solid #32414B;
1943}
1944
1945QHeaderView::section::horizontal:disabled {
1946 color: #787878;
1947}
1948
1949QHeaderView::section::vertical {
1950 padding-left: 4px;
1951 padding-right: 4px;
1952 border-top: 1px solid #19232D;
1953}
1954
1955QHeaderView::section::vertical::first, QHeaderView::section::vertical::only-one {
1956 border-top: 1px solid #32414B;
1957}
1958
1959QHeaderView::section::vertical:disabled {
1960 color: #787878;
1961}
1962
1963QHeaderView::down-arrow {
1964 /* Those settings (border/width/height/background-color) solve bug */
1965 /* transparent arrow background and size */
1966 background-color: #32414B;
1967 border: none;
1968 height: 12px;
1969 width: 12px;
1970 padding-left: 2px;
1971 padding-right: 2px;
1972 image: url(":/qss_icons/rc/arrow_down.png");
1973}
1974
1975QHeaderView::up-arrow {
1976 background-color: #32414B;
1977 border: none;
1978 height: 12px;
1979 width: 12px;
1980 padding-left: 2px;
1981 padding-right: 2px;
1982 image: url(":/qss_icons/rc/arrow_up.png");
1983}
1984
1985/* QToolBox --------------------------------------------------------------
1986
1987https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtoolbox
1988
1989--------------------------------------------------------------------------- */
1990QToolBox {
1991 padding: 0px;
1992 border: 0px;
1993 border: 1px solid #32414B;
1994}
1995
1996QToolBox:selected {
1997 padding: 0px;
1998 border: 2px solid #1464A0;
1999}
2000
2001QToolBox::tab {
2002 background-color: #19232D;
2003 border: 1px solid #32414B;
2004 color: #F0F0F0;
2005 border-top-left-radius: 4px;
2006 border-top-right-radius: 4px;
2007}
2008
2009QToolBox::tab:disabled {
2010 color: #787878;
2011}
2012
2013QToolBox::tab:selected {
2014 background-color: #505F69;
2015 border-bottom: 2px solid #1464A0;
2016}
2017
2018QToolBox::tab:selected:disabled {
2019 background-color: #32414B;
2020 border-bottom: 2px solid #14506E;
2021}
2022
2023QToolBox::tab:!selected {
2024 background-color: #32414B;
2025 border-bottom: 2px solid #32414B;
2026}
2027
2028QToolBox::tab:!selected:disabled {
2029 background-color: #19232D;
2030}
2031
2032QToolBox::tab:hover {
2033 border-color: #148CD2;
2034 border-bottom: 2px solid #148CD2;
2035}
2036
2037QToolBox QScrollArea QWidget QWidget {
2038 padding: 0px;
2039 border: 0px;
2040 background-color: #19232D;
2041}
2042
2043/* QFrame -----------------------------------------------------------------
2044
2045https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qframe
2046https://doc.qt.io/qt-5/qframe.html#-prop
2047https://doc.qt.io/qt-5/qframe.html#details
2048https://stackoverflow.com/questions/14581498/qt-stylesheet-for-hline-vline-color
2049
2050--------------------------------------------------------------------------- */
2051/* (dot) .QFrame fix #141, #126, #123 */
2052.QFrame {
2053 border-radius: 4px;
2054 border: 1px solid #32414B;
2055 /* No frame */
2056 /* HLine */
2057 /* HLine */
2058}
2059
2060.QFrame[frameShape="0"] {
2061 border-radius: 4px;
2062 border: 1px transparent #32414B;
2063}
2064
2065.QFrame[frameShape="4"] {
2066 max-height: 2px;
2067 border: none;
2068 background-color: #32414B;
2069}
2070
2071.QFrame[frameShape="5"] {
2072 max-width: 2px;
2073 border: none;
2074 background-color: #32414B;
2075}
2076
2077/* QSplitter --------------------------------------------------------------
2078
2079https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qsplitter
2080
2081--------------------------------------------------------------------------- */
2082QSplitter {
2083 background-color: #32414B;
2084 spacing: 0px;
2085 padding: 0px;
2086 margin: 0px;
2087}
2088
2089QSplitter::handle {
2090 background-color: #32414B;
2091 border: 0px solid #19232D;
2092 spacing: 0px;
2093 padding: 1px;
2094 margin: 0px;
2095}
2096
2097QSplitter::handle:hover {
2098 background-color: #787878;
2099}
2100
2101QSplitter::handle:horizontal {
2102 width: 5px;
2103 image: url(":/qss_icons/rc/line_vertical.png");
2104}
2105
2106QSplitter::handle:vertical {
2107 height: 5px;
2108 image: url(":/qss_icons/rc/line_horizontal.png");
2109}
2110
2111/* QDateEdit, QDateTimeEdit -----------------------------------------------
2112
2113--------------------------------------------------------------------------- */
2114QDateEdit, QDateTimeEdit {
2115 selection-background-color: #1464A0;
2116 border-style: solid;
2117 border: 1px solid #32414B;
2118 border-radius: 4px;
2119 /* This fixes 103, 111 */
2120 padding-top: 2px;
2121 /* This fixes 103, 111 */
2122 padding-bottom: 2px;
2123 padding-left: 4px;
2124 padding-right: 4px;
2125 min-width: 10px;
2126}
2127
2128QDateEdit:on, QDateTimeEdit:on {
2129 selection-background-color: #1464A0;
2130}
2131
2132QDateEdit::drop-down, QDateTimeEdit::drop-down {
2133 subcontrol-origin: padding;
2134 subcontrol-position: top right;
2135 width: 12px;
2136 border-left: 1px solid #32414B;
2137}
2138
2139QDateEdit::down-arrow, QDateTimeEdit::down-arrow {
2140 image: url(":/qss_icons/rc/arrow_down_disabled.png");
2141 height: 8px;
2142 width: 8px;
2143}
2144
2145QDateEdit::down-arrow:on, QDateEdit::down-arrow:hover, QDateEdit::down-arrow:focus, QDateTimeEdit::down-arrow:on, QDateTimeEdit::down-arrow:hover, QDateTimeEdit::down-arrow:focus {
2146 image: url(":/qss_icons/rc/arrow_down.png");
2147}
2148
2149QDateEdit QAbstractItemView, QDateTimeEdit QAbstractItemView {
2150 background-color: #19232D;
2151 border-radius: 4px;
2152 border: 1px solid #32414B;
2153 selection-background-color: #1464A0;
2154}
2155
2156/* QAbstractView ----------------------------------------------------------
2157
2158--------------------------------------------------------------------------- */
2159QAbstractView:hover {
2160 border: 1px solid #148CD2;
2161 color: #F0F0F0;
2162}
2163
2164QAbstractView:selected {
2165 background: #1464A0;
2166 color: #32414B;
2167}
2168
2169/* PlotWidget -------------------------------------------------------------
2170
2171--------------------------------------------------------------------------- */
2172PlotWidget {
2173 /* Fix cut labels in plots #134 */
2174 padding: 0px;
2175}
diff --git a/src/audio_core/stream.cpp b/src/audio_core/stream.cpp
index aab3e979a..f80ab92e4 100644
--- a/src/audio_core/stream.cpp
+++ b/src/audio_core/stream.cpp
@@ -38,7 +38,7 @@ Stream::Stream(Core::Timing::CoreTiming& core_timing, u32 sample_rate, Format fo
38 sink_stream{sink_stream}, core_timing{core_timing}, name{std::move(name_)} { 38 sink_stream{sink_stream}, core_timing{core_timing}, name{std::move(name_)} {
39 39
40 release_event = Core::Timing::CreateEvent( 40 release_event = Core::Timing::CreateEvent(
41 name, [this](u64 userdata, s64 cycles_late) { ReleaseActiveBuffer(cycles_late); }); 41 name, [this](u64, std::chrono::nanoseconds ns_late) { ReleaseActiveBuffer(ns_late); });
42} 42}
43 43
44void Stream::Play() { 44void Stream::Play() {
@@ -59,11 +59,9 @@ Stream::State Stream::GetState() const {
59 return state; 59 return state;
60} 60}
61 61
62s64 Stream::GetBufferReleaseNS(const Buffer& buffer) const { 62std::chrono::nanoseconds Stream::GetBufferReleaseNS(const Buffer& buffer) const {
63 const std::size_t num_samples{buffer.GetSamples().size() / GetNumChannels()}; 63 const std::size_t num_samples{buffer.GetSamples().size() / GetNumChannels()};
64 const auto ns = 64 return std::chrono::nanoseconds((static_cast<u64>(num_samples) * 1000000000ULL) / sample_rate);
65 std::chrono::nanoseconds((static_cast<u64>(num_samples) * 1000000000ULL) / sample_rate);
66 return ns.count();
67} 65}
68 66
69static void VolumeAdjustSamples(std::vector<s16>& samples, float game_volume) { 67static void VolumeAdjustSamples(std::vector<s16>& samples, float game_volume) {
@@ -80,7 +78,7 @@ static void VolumeAdjustSamples(std::vector<s16>& samples, float game_volume) {
80 } 78 }
81} 79}
82 80
83void Stream::PlayNextBuffer(s64 cycles_late) { 81void Stream::PlayNextBuffer(std::chrono::nanoseconds ns_late) {
84 if (!IsPlaying()) { 82 if (!IsPlaying()) {
85 // Ensure we are in playing state before playing the next buffer 83 // Ensure we are in playing state before playing the next buffer
86 sink_stream.Flush(); 84 sink_stream.Flush();
@@ -105,17 +103,18 @@ void Stream::PlayNextBuffer(s64 cycles_late) {
105 103
106 sink_stream.EnqueueSamples(GetNumChannels(), active_buffer->GetSamples()); 104 sink_stream.EnqueueSamples(GetNumChannels(), active_buffer->GetSamples());
107 105
108 core_timing.ScheduleEvent( 106 const auto time_stretch_delta = Settings::values.enable_audio_stretching.GetValue()
109 GetBufferReleaseNS(*active_buffer) - 107 ? std::chrono::nanoseconds::zero()
110 (Settings::values.enable_audio_stretching.GetValue() ? 0 : cycles_late), 108 : ns_late;
111 release_event, {}); 109 const auto future_time = GetBufferReleaseNS(*active_buffer) - time_stretch_delta;
110 core_timing.ScheduleEvent(future_time, release_event, {});
112} 111}
113 112
114void Stream::ReleaseActiveBuffer(s64 cycles_late) { 113void Stream::ReleaseActiveBuffer(std::chrono::nanoseconds ns_late) {
115 ASSERT(active_buffer); 114 ASSERT(active_buffer);
116 released_buffers.push(std::move(active_buffer)); 115 released_buffers.push(std::move(active_buffer));
117 release_callback(); 116 release_callback();
118 PlayNextBuffer(cycles_late); 117 PlayNextBuffer(ns_late);
119} 118}
120 119
121bool Stream::QueueBuffer(BufferPtr&& buffer) { 120bool Stream::QueueBuffer(BufferPtr&& buffer) {
diff --git a/src/audio_core/stream.h b/src/audio_core/stream.h
index 524376257..6437b8591 100644
--- a/src/audio_core/stream.h
+++ b/src/audio_core/stream.h
@@ -4,6 +4,7 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <chrono>
7#include <functional> 8#include <functional>
8#include <memory> 9#include <memory>
9#include <string> 10#include <string>
@@ -90,16 +91,13 @@ public:
90 91
91private: 92private:
92 /// Plays the next queued buffer in the audio stream, starting playback if necessary 93 /// Plays the next queued buffer in the audio stream, starting playback if necessary
93 void PlayNextBuffer(s64 cycles_late = 0); 94 void PlayNextBuffer(std::chrono::nanoseconds ns_late = {});
94 95
95 /// Releases the actively playing buffer, signalling that it has been completed 96 /// Releases the actively playing buffer, signalling that it has been completed
96 void ReleaseActiveBuffer(s64 cycles_late = 0); 97 void ReleaseActiveBuffer(std::chrono::nanoseconds ns_late = {});
97 98
98 /// Gets the number of core cycles when the specified buffer will be released 99 /// Gets the number of core cycles when the specified buffer will be released
99 s64 GetBufferReleaseNS(const Buffer& buffer) const; 100 std::chrono::nanoseconds GetBufferReleaseNS(const Buffer& buffer) const;
100
101 /// Gets the number of core cycles when the specified buffer will be released
102 s64 GetBufferReleaseNSHostTiming(const Buffer& buffer) const;
103 101
104 u32 sample_rate; ///< Sample rate of the stream 102 u32 sample_rate; ///< Sample rate of the stream
105 Format format; ///< Format of the stream 103 Format format; ///< Format of the stream
diff --git a/src/common/alignment.h b/src/common/alignment.h
index b37044bb6..ef4d6f896 100644
--- a/src/common/alignment.h
+++ b/src/common/alignment.h
@@ -3,7 +3,7 @@
3#pragma once 3#pragma once
4 4
5#include <cstddef> 5#include <cstddef>
6#include <memory> 6#include <new>
7#include <type_traits> 7#include <type_traits>
8 8
9namespace Common { 9namespace Common {
@@ -54,66 +54,28 @@ public:
54 using size_type = std::size_t; 54 using size_type = std::size_t;
55 using difference_type = std::ptrdiff_t; 55 using difference_type = std::ptrdiff_t;
56 56
57 using pointer = T*;
58 using const_pointer = const T*;
59
60 using reference = T&;
61 using const_reference = const T&;
62
63 using propagate_on_container_copy_assignment = std::true_type; 57 using propagate_on_container_copy_assignment = std::true_type;
64 using propagate_on_container_move_assignment = std::true_type; 58 using propagate_on_container_move_assignment = std::true_type;
65 using propagate_on_container_swap = std::true_type; 59 using propagate_on_container_swap = std::true_type;
66 using is_always_equal = std::true_type; 60 using is_always_equal = std::true_type;
67 61
68public:
69 constexpr AlignmentAllocator() noexcept = default; 62 constexpr AlignmentAllocator() noexcept = default;
70 63
71 template <typename T2> 64 template <typename T2>
72 constexpr AlignmentAllocator(const AlignmentAllocator<T2, Align>&) noexcept {} 65 constexpr AlignmentAllocator(const AlignmentAllocator<T2, Align>&) noexcept {}
73 66
74 pointer address(reference r) noexcept { 67 T* allocate(size_type n) {
75 return std::addressof(r); 68 return static_cast<T*>(::operator new (n * sizeof(T), std::align_val_t{Align}));
76 }
77
78 const_pointer address(const_reference r) const noexcept {
79 return std::addressof(r);
80 }
81
82 pointer allocate(size_type n) {
83 return static_cast<pointer>(::operator new (n, std::align_val_t{Align}));
84 }
85
86 void deallocate(pointer p, size_type) {
87 ::operator delete (p, std::align_val_t{Align});
88 } 69 }
89 70
90 void construct(pointer p, const value_type& wert) { 71 void deallocate(T* p, size_type n) {
91 new (p) value_type(wert); 72 ::operator delete (p, n * sizeof(T), std::align_val_t{Align});
92 }
93
94 void destroy(pointer p) {
95 p->~value_type();
96 }
97
98 size_type max_size() const noexcept {
99 return size_type(-1) / sizeof(value_type);
100 } 73 }
101 74
102 template <typename T2> 75 template <typename T2>
103 struct rebind { 76 struct rebind {
104 using other = AlignmentAllocator<T2, Align>; 77 using other = AlignmentAllocator<T2, Align>;
105 }; 78 };
106
107 bool operator!=(const AlignmentAllocator<T, Align>& other) const noexcept {
108 return !(*this == other);
109 }
110
111 // Returns true if and only if storage allocated from *this
112 // can be deallocated from other, and vice versa.
113 // Always returns true for stateless allocators.
114 bool operator==(const AlignmentAllocator<T, Align>& other) const noexcept {
115 return true;
116 }
117}; 79};
118 80
119} // namespace Common 81} // namespace Common
diff --git a/src/common/string_util.h b/src/common/string_util.h
index 583fd05e6..023dff5dc 100644
--- a/src/common/string_util.h
+++ b/src/common/string_util.h
@@ -74,16 +74,4 @@ std::string StringFromFixedZeroTerminatedBuffer(const char* buffer, std::size_t
74std::u16string UTF16StringFromFixedZeroTerminatedBuffer(std::u16string_view buffer, 74std::u16string UTF16StringFromFixedZeroTerminatedBuffer(std::u16string_view buffer,
75 std::size_t max_len); 75 std::size_t max_len);
76 76
77/**
78 * Attempts to trim an arbitrary prefix from `path`, leaving only the part starting at `root`. It's
79 * intended to be used to strip a system-specific build directory from the `__FILE__` macro,
80 * leaving only the path relative to the sources root.
81 *
82 * @param path The input file path as a null-terminated string
83 * @param root The name of the root source directory as a null-terminated string. Path up to and
84 * including the last occurrence of this name will be stripped
85 * @return A pointer to the same string passed as `path`, but starting at the trimmed portion
86 */
87const char* TrimSourcePath(const char* path, const char* root = "src");
88
89} // namespace Common 77} // namespace Common
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index d1f173f42..c85c9485f 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -185,6 +185,7 @@ add_library(core STATIC
185 hle/kernel/object.h 185 hle/kernel/object.h
186 hle/kernel/physical_core.cpp 186 hle/kernel/physical_core.cpp
187 hle/kernel/physical_core.h 187 hle/kernel/physical_core.h
188 hle/kernel/physical_memory.h
188 hle/kernel/process.cpp 189 hle/kernel/process.cpp
189 hle/kernel/process.h 190 hle/kernel/process.h
190 hle/kernel/process_capability.cpp 191 hle/kernel/process_capability.cpp
@@ -398,10 +399,13 @@ add_library(core STATIC
398 hle/service/lm/manager.h 399 hle/service/lm/manager.h
399 hle/service/mig/mig.cpp 400 hle/service/mig/mig.cpp
400 hle/service/mig/mig.h 401 hle/service/mig/mig.h
402 hle/service/mii/manager.cpp
403 hle/service/mii/manager.h
401 hle/service/mii/mii.cpp 404 hle/service/mii/mii.cpp
402 hle/service/mii/mii.h 405 hle/service/mii/mii.h
403 hle/service/mii/mii_manager.cpp 406 hle/service/mii/raw_data.cpp
404 hle/service/mii/mii_manager.h 407 hle/service/mii/raw_data.h
408 hle/service/mii/types.h
405 hle/service/mm/mm_u.cpp 409 hle/service/mm/mm_u.cpp
406 hle/service/mm/mm_u.h 410 hle/service/mm/mm_u.h
407 hle/service/ncm/ncm.cpp 411 hle/service/ncm/ncm.cpp
@@ -582,6 +586,9 @@ add_library(core STATIC
582 memory/dmnt_cheat_vm.h 586 memory/dmnt_cheat_vm.h
583 memory.cpp 587 memory.cpp
584 memory.h 588 memory.h
589 network/network.cpp
590 network/network.h
591 network/sockets.h
585 perf_stats.cpp 592 perf_stats.cpp
586 perf_stats.h 593 perf_stats.h
587 reporter.cpp 594 reporter.cpp
diff --git a/src/core/constants.h b/src/core/constants.h
index 6d0ec022a..81c5cb279 100644
--- a/src/core/constants.h
+++ b/src/core/constants.h
@@ -4,6 +4,7 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <array>
7#include "common/common_types.h" 8#include "common/common_types.h"
8 9
9// This is to consolidate system-wide constants that are used by multiple components of yuzu. 10// This is to consolidate system-wide constants that are used by multiple components of yuzu.
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 69a1aa0a5..e598c0e2b 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -43,6 +43,7 @@
43#include "core/loader/loader.h" 43#include "core/loader/loader.h"
44#include "core/memory.h" 44#include "core/memory.h"
45#include "core/memory/cheat_engine.h" 45#include "core/memory/cheat_engine.h"
46#include "core/network/network.h"
46#include "core/perf_stats.h" 47#include "core/perf_stats.h"
47#include "core/reporter.h" 48#include "core/reporter.h"
48#include "core/settings.h" 49#include "core/settings.h"
@@ -394,6 +395,9 @@ struct System::Impl {
394 /// Telemetry session for this emulation session 395 /// Telemetry session for this emulation session
395 std::unique_ptr<Core::TelemetrySession> telemetry_session; 396 std::unique_ptr<Core::TelemetrySession> telemetry_session;
396 397
398 /// Network instance
399 Network::NetworkInstance network_instance;
400
397 ResultStatus status = ResultStatus::Success; 401 ResultStatus status = ResultStatus::Success;
398 std::string status_details = ""; 402 std::string status_details = "";
399 403
diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp
index a63e60461..b5feb3f24 100644
--- a/src/core/core_timing.cpp
+++ b/src/core/core_timing.cpp
@@ -53,12 +53,12 @@ void CoreTiming::ThreadEntry(CoreTiming& instance) {
53 instance.ThreadLoop(); 53 instance.ThreadLoop();
54} 54}
55 55
56void CoreTiming::Initialize(std::function<void(void)>&& on_thread_init_) { 56void CoreTiming::Initialize(std::function<void()>&& on_thread_init_) {
57 on_thread_init = std::move(on_thread_init_); 57 on_thread_init = std::move(on_thread_init_);
58 event_fifo_id = 0; 58 event_fifo_id = 0;
59 shutting_down = false; 59 shutting_down = false;
60 ticks = 0; 60 ticks = 0;
61 const auto empty_timed_callback = [](u64, s64) {}; 61 const auto empty_timed_callback = [](u64, std::chrono::nanoseconds) {};
62 ev_lost = CreateEvent("_lost_event", empty_timed_callback); 62 ev_lost = CreateEvent("_lost_event", empty_timed_callback);
63 if (is_multicore) { 63 if (is_multicore) {
64 timer_thread = std::make_unique<std::thread>(ThreadEntry, std::ref(*this)); 64 timer_thread = std::make_unique<std::thread>(ThreadEntry, std::ref(*this));
@@ -106,11 +106,11 @@ bool CoreTiming::HasPendingEvents() const {
106 return !(wait_set && event_queue.empty()); 106 return !(wait_set && event_queue.empty());
107} 107}
108 108
109void CoreTiming::ScheduleEvent(s64 ns_into_future, const std::shared_ptr<EventType>& event_type, 109void CoreTiming::ScheduleEvent(std::chrono::nanoseconds ns_into_future,
110 u64 userdata) { 110 const std::shared_ptr<EventType>& event_type, u64 userdata) {
111 { 111 {
112 std::scoped_lock scope{basic_lock}; 112 std::scoped_lock scope{basic_lock};
113 const u64 timeout = static_cast<u64>(GetGlobalTimeNs().count() + ns_into_future); 113 const u64 timeout = static_cast<u64>((GetGlobalTimeNs() + ns_into_future).count());
114 114
115 event_queue.emplace_back(Event{timeout, event_fifo_id++, userdata, event_type}); 115 event_queue.emplace_back(Event{timeout, event_fifo_id++, userdata, event_type});
116 116
@@ -195,8 +195,9 @@ std::optional<s64> CoreTiming::Advance() {
195 event_queue.pop_back(); 195 event_queue.pop_back();
196 basic_lock.unlock(); 196 basic_lock.unlock();
197 197
198 if (auto event_type{evt.type.lock()}) { 198 if (const auto event_type{evt.type.lock()}) {
199 event_type->callback(evt.userdata, global_timer - evt.time); 199 event_type->callback(
200 evt.userdata, std::chrono::nanoseconds{static_cast<s64>(global_timer - evt.time)});
200 } 201 }
201 202
202 basic_lock.lock(); 203 basic_lock.lock();
diff --git a/src/core/core_timing.h b/src/core/core_timing.h
index 72faaab64..120c74e46 100644
--- a/src/core/core_timing.h
+++ b/src/core/core_timing.h
@@ -17,14 +17,12 @@
17#include "common/common_types.h" 17#include "common/common_types.h"
18#include "common/spin_lock.h" 18#include "common/spin_lock.h"
19#include "common/thread.h" 19#include "common/thread.h"
20#include "common/threadsafe_queue.h"
21#include "common/wall_clock.h" 20#include "common/wall_clock.h"
22#include "core/hardware_properties.h"
23 21
24namespace Core::Timing { 22namespace Core::Timing {
25 23
26/// A callback that may be scheduled for a particular core timing event. 24/// A callback that may be scheduled for a particular core timing event.
27using TimedCallback = std::function<void(u64 userdata, s64 cycles_late)>; 25using TimedCallback = std::function<void(u64 userdata, std::chrono::nanoseconds ns_late)>;
28 26
29/// Contains the characteristics of a particular event. 27/// Contains the characteristics of a particular event.
30struct EventType { 28struct EventType {
@@ -42,12 +40,12 @@ struct EventType {
42 * in main CPU clock cycles. 40 * in main CPU clock cycles.
43 * 41 *
44 * To schedule an event, you first have to register its type. This is where you pass in the 42 * To schedule an event, you first have to register its type. This is where you pass in the
45 * callback. You then schedule events using the type id you get back. 43 * callback. You then schedule events using the type ID you get back.
46 * 44 *
47 * The int cyclesLate that the callbacks get is how many cycles late it was. 45 * The s64 ns_late that the callbacks get is how many ns late it was.
48 * So to schedule a new event on a regular basis: 46 * So to schedule a new event on a regular basis:
49 * inside callback: 47 * inside callback:
50 * ScheduleEvent(periodInCycles - cyclesLate, callback, "whatever") 48 * ScheduleEvent(period_in_ns - ns_late, callback, "whatever")
51 */ 49 */
52class CoreTiming { 50class CoreTiming {
53public: 51public:
@@ -62,7 +60,7 @@ public:
62 60
63 /// CoreTiming begins at the boundary of timing slice -1. An initial call to Advance() is 61 /// CoreTiming begins at the boundary of timing slice -1. An initial call to Advance() is
64 /// required to end slice - 1 and start slice 0 before the first cycle of code is executed. 62 /// required to end slice - 1 and start slice 0 before the first cycle of code is executed.
65 void Initialize(std::function<void(void)>&& on_thread_init_); 63 void Initialize(std::function<void()>&& on_thread_init_);
66 64
67 /// Tears down all timing related functionality. 65 /// Tears down all timing related functionality.
68 void Shutdown(); 66 void Shutdown();
@@ -95,8 +93,8 @@ public:
95 bool HasPendingEvents() const; 93 bool HasPendingEvents() const;
96 94
97 /// Schedules an event in core timing 95 /// Schedules an event in core timing
98 void ScheduleEvent(s64 ns_into_future, const std::shared_ptr<EventType>& event_type, 96 void ScheduleEvent(std::chrono::nanoseconds ns_into_future,
99 u64 userdata = 0); 97 const std::shared_ptr<EventType>& event_type, u64 userdata = 0);
100 98
101 void UnscheduleEvent(const std::shared_ptr<EventType>& event_type, u64 userdata); 99 void UnscheduleEvent(const std::shared_ptr<EventType>& event_type, u64 userdata);
102 100
@@ -141,8 +139,6 @@ private:
141 139
142 u64 global_timer = 0; 140 u64 global_timer = 0;
143 141
144 std::chrono::nanoseconds start_point;
145
146 // The queue is a min-heap using std::make_heap/push_heap/pop_heap. 142 // The queue is a min-heap using std::make_heap/push_heap/pop_heap.
147 // We don't use std::priority_queue because we need to be able to serialize, unserialize and 143 // We don't use std::priority_queue because we need to be able to serialize, unserialize and
148 // erase arbitrary events (RemoveEvent()) regardless of the queue order. These aren't 144 // erase arbitrary events (RemoveEvent()) regardless of the queue order. These aren't
@@ -161,7 +157,7 @@ private:
161 std::atomic<bool> wait_set{}; 157 std::atomic<bool> wait_set{};
162 std::atomic<bool> shutting_down{}; 158 std::atomic<bool> shutting_down{};
163 std::atomic<bool> has_started{}; 159 std::atomic<bool> has_started{};
164 std::function<void(void)> on_thread_init{}; 160 std::function<void()> on_thread_init{};
165 161
166 bool is_multicore{}; 162 bool is_multicore{};
167 163
diff --git a/src/core/cpu_manager.h b/src/core/cpu_manager.h
index 35929ed94..17420c941 100644
--- a/src/core/cpu_manager.h
+++ b/src/core/cpu_manager.h
@@ -9,6 +9,9 @@
9#include <functional> 9#include <functional>
10#include <memory> 10#include <memory>
11#include <thread> 11#include <thread>
12
13#include "common/fiber.h"
14#include "common/thread.h"
12#include "core/hardware_properties.h" 15#include "core/hardware_properties.h"
13 16
14namespace Common { 17namespace Common {
@@ -46,9 +49,9 @@ public:
46 49
47 void Pause(bool paused); 50 void Pause(bool paused);
48 51
49 std::function<void(void*)> GetGuestThreadStartFunc(); 52 static std::function<void(void*)> GetGuestThreadStartFunc();
50 std::function<void(void*)> GetIdleThreadStartFunc(); 53 static std::function<void(void*)> GetIdleThreadStartFunc();
51 std::function<void(void*)> GetSuspendThreadStartFunc(); 54 static std::function<void(void*)> GetSuspendThreadStartFunc();
52 void* GetStartFuncParamater(); 55 void* GetStartFuncParamater();
53 56
54 void PreemptSingleCore(bool from_running_enviroment = true); 57 void PreemptSingleCore(bool from_running_enviroment = true);
@@ -97,7 +100,6 @@ private:
97 bool is_async_gpu{}; 100 bool is_async_gpu{};
98 bool is_multicore{}; 101 bool is_multicore{};
99 std::atomic<std::size_t> current_core{}; 102 std::atomic<std::size_t> current_core{};
100 std::size_t preemption_count{};
101 std::size_t idle_count{}; 103 std::size_t idle_count{};
102 static constexpr std::size_t max_cycle_runs = 5; 104 static constexpr std::size_t max_cycle_runs = 5;
103 105
diff --git a/src/core/file_sys/fsmitm_romfsbuild.cpp b/src/core/file_sys/fsmitm_romfsbuild.cpp
index d126ae8dd..2aff2708a 100644
--- a/src/core/file_sys/fsmitm_romfsbuild.cpp
+++ b/src/core/file_sys/fsmitm_romfsbuild.cpp
@@ -240,7 +240,7 @@ RomFSBuildContext::RomFSBuildContext(VirtualDir base_, VirtualDir ext_)
240 240
241RomFSBuildContext::~RomFSBuildContext() = default; 241RomFSBuildContext::~RomFSBuildContext() = default;
242 242
243std::map<u64, VirtualFile> RomFSBuildContext::Build() { 243std::multimap<u64, VirtualFile> RomFSBuildContext::Build() {
244 const u64 dir_hash_table_entry_count = romfs_get_hash_table_count(num_dirs); 244 const u64 dir_hash_table_entry_count = romfs_get_hash_table_count(num_dirs);
245 const u64 file_hash_table_entry_count = romfs_get_hash_table_count(num_files); 245 const u64 file_hash_table_entry_count = romfs_get_hash_table_count(num_files);
246 dir_hash_table_size = 4 * dir_hash_table_entry_count; 246 dir_hash_table_size = 4 * dir_hash_table_entry_count;
@@ -294,7 +294,7 @@ std::map<u64, VirtualFile> RomFSBuildContext::Build() {
294 cur_dir->parent->child = cur_dir; 294 cur_dir->parent->child = cur_dir;
295 } 295 }
296 296
297 std::map<u64, VirtualFile> out; 297 std::multimap<u64, VirtualFile> out;
298 298
299 // Populate file tables. 299 // Populate file tables.
300 for (const auto& it : files) { 300 for (const auto& it : files) {
diff --git a/src/core/file_sys/fsmitm_romfsbuild.h b/src/core/file_sys/fsmitm_romfsbuild.h
index a62502193..049de180b 100644
--- a/src/core/file_sys/fsmitm_romfsbuild.h
+++ b/src/core/file_sys/fsmitm_romfsbuild.h
@@ -43,7 +43,7 @@ public:
43 ~RomFSBuildContext(); 43 ~RomFSBuildContext();
44 44
45 // This finalizes the context. 45 // This finalizes the context.
46 std::map<u64, VirtualFile> Build(); 46 std::multimap<u64, VirtualFile> Build();
47 47
48private: 48private:
49 VirtualDir base; 49 VirtualDir base;
diff --git a/src/core/file_sys/vfs_concat.cpp b/src/core/file_sys/vfs_concat.cpp
index 16d801c0c..e0ff70174 100644
--- a/src/core/file_sys/vfs_concat.cpp
+++ b/src/core/file_sys/vfs_concat.cpp
@@ -11,7 +11,7 @@
11 11
12namespace FileSys { 12namespace FileSys {
13 13
14static bool VerifyConcatenationMapContinuity(const std::map<u64, VirtualFile>& map) { 14static bool VerifyConcatenationMapContinuity(const std::multimap<u64, VirtualFile>& map) {
15 const auto last_valid = --map.end(); 15 const auto last_valid = --map.end();
16 for (auto iter = map.begin(); iter != last_valid;) { 16 for (auto iter = map.begin(); iter != last_valid;) {
17 const auto old = iter++; 17 const auto old = iter++;
@@ -27,12 +27,12 @@ ConcatenatedVfsFile::ConcatenatedVfsFile(std::vector<VirtualFile> files_, std::s
27 : name(std::move(name)) { 27 : name(std::move(name)) {
28 std::size_t next_offset = 0; 28 std::size_t next_offset = 0;
29 for (const auto& file : files_) { 29 for (const auto& file : files_) {
30 files[next_offset] = file; 30 files.emplace(next_offset, file);
31 next_offset += file->GetSize(); 31 next_offset += file->GetSize();
32 } 32 }
33} 33}
34 34
35ConcatenatedVfsFile::ConcatenatedVfsFile(std::map<u64, VirtualFile> files_, std::string name) 35ConcatenatedVfsFile::ConcatenatedVfsFile(std::multimap<u64, VirtualFile> files_, std::string name)
36 : files(std::move(files_)), name(std::move(name)) { 36 : files(std::move(files_)), name(std::move(name)) {
37 ASSERT(VerifyConcatenationMapContinuity(files)); 37 ASSERT(VerifyConcatenationMapContinuity(files));
38} 38}
@@ -50,7 +50,7 @@ VirtualFile ConcatenatedVfsFile::MakeConcatenatedFile(std::vector<VirtualFile> f
50} 50}
51 51
52VirtualFile ConcatenatedVfsFile::MakeConcatenatedFile(u8 filler_byte, 52VirtualFile ConcatenatedVfsFile::MakeConcatenatedFile(u8 filler_byte,
53 std::map<u64, VirtualFile> files, 53 std::multimap<u64, VirtualFile> files,
54 std::string name) { 54 std::string name) {
55 if (files.empty()) 55 if (files.empty())
56 return nullptr; 56 return nullptr;
diff --git a/src/core/file_sys/vfs_concat.h b/src/core/file_sys/vfs_concat.h
index c90f9d5d1..7a26343c0 100644
--- a/src/core/file_sys/vfs_concat.h
+++ b/src/core/file_sys/vfs_concat.h
@@ -15,7 +15,7 @@ namespace FileSys {
15// read-only. 15// read-only.
16class ConcatenatedVfsFile : public VfsFile { 16class ConcatenatedVfsFile : public VfsFile {
17 ConcatenatedVfsFile(std::vector<VirtualFile> files, std::string name); 17 ConcatenatedVfsFile(std::vector<VirtualFile> files, std::string name);
18 ConcatenatedVfsFile(std::map<u64, VirtualFile> files, std::string name); 18 ConcatenatedVfsFile(std::multimap<u64, VirtualFile> files, std::string name);
19 19
20public: 20public:
21 ~ConcatenatedVfsFile() override; 21 ~ConcatenatedVfsFile() override;
@@ -25,7 +25,7 @@ public:
25 25
26 /// Convenience function that turns a map of offsets to files into a concatenated file, filling 26 /// Convenience function that turns a map of offsets to files into a concatenated file, filling
27 /// gaps with a given filler byte. 27 /// gaps with a given filler byte.
28 static VirtualFile MakeConcatenatedFile(u8 filler_byte, std::map<u64, VirtualFile> files, 28 static VirtualFile MakeConcatenatedFile(u8 filler_byte, std::multimap<u64, VirtualFile> files,
29 std::string name); 29 std::string name);
30 30
31 std::string GetName() const override; 31 std::string GetName() const override;
@@ -40,7 +40,7 @@ public:
40 40
41private: 41private:
42 // Maps starting offset to file -- more efficient. 42 // Maps starting offset to file -- more efficient.
43 std::map<u64, VirtualFile> files; 43 std::multimap<u64, VirtualFile> files;
44 std::string name; 44 std::string name;
45}; 45};
46 46
diff --git a/src/core/hardware_interrupt_manager.cpp b/src/core/hardware_interrupt_manager.cpp
index c629d9fa1..efc1030c1 100644
--- a/src/core/hardware_interrupt_manager.cpp
+++ b/src/core/hardware_interrupt_manager.cpp
@@ -11,19 +11,20 @@
11namespace Core::Hardware { 11namespace Core::Hardware {
12 12
13InterruptManager::InterruptManager(Core::System& system_in) : system(system_in) { 13InterruptManager::InterruptManager(Core::System& system_in) : system(system_in) {
14 gpu_interrupt_event = Core::Timing::CreateEvent("GPUInterrupt", [this](u64 message, s64) { 14 gpu_interrupt_event =
15 auto nvdrv = system.ServiceManager().GetService<Service::Nvidia::NVDRV>("nvdrv"); 15 Core::Timing::CreateEvent("GPUInterrupt", [this](u64 message, std::chrono::nanoseconds) {
16 const u32 syncpt = static_cast<u32>(message >> 32); 16 auto nvdrv = system.ServiceManager().GetService<Service::Nvidia::NVDRV>("nvdrv");
17 const u32 value = static_cast<u32>(message); 17 const u32 syncpt = static_cast<u32>(message >> 32);
18 nvdrv->SignalGPUInterruptSyncpt(syncpt, value); 18 const u32 value = static_cast<u32>(message);
19 }); 19 nvdrv->SignalGPUInterruptSyncpt(syncpt, value);
20 });
20} 21}
21 22
22InterruptManager::~InterruptManager() = default; 23InterruptManager::~InterruptManager() = default;
23 24
24void InterruptManager::GPUInterruptSyncpt(const u32 syncpoint_id, const u32 value) { 25void InterruptManager::GPUInterruptSyncpt(const u32 syncpoint_id, const u32 value) {
25 const u64 msg = (static_cast<u64>(syncpoint_id) << 32ULL) | value; 26 const u64 msg = (static_cast<u64>(syncpoint_id) << 32ULL) | value;
26 system.CoreTiming().ScheduleEvent(10, gpu_interrupt_event, msg); 27 system.CoreTiming().ScheduleEvent(std::chrono::nanoseconds{10}, gpu_interrupt_event, msg);
27} 28}
28 29
29} // namespace Core::Hardware 30} // namespace Core::Hardware
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp
index 4d2a9b35d..df0debe1b 100644
--- a/src/core/hle/kernel/address_arbiter.cpp
+++ b/src/core/hle/kernel/address_arbiter.cpp
@@ -24,7 +24,6 @@ namespace Kernel {
24// Wake up num_to_wake (or all) threads in a vector. 24// Wake up num_to_wake (or all) threads in a vector.
25void AddressArbiter::WakeThreads(const std::vector<std::shared_ptr<Thread>>& waiting_threads, 25void AddressArbiter::WakeThreads(const std::vector<std::shared_ptr<Thread>>& waiting_threads,
26 s32 num_to_wake) { 26 s32 num_to_wake) {
27 auto& time_manager = system.Kernel().TimeManager();
28 // Only process up to 'target' threads, unless 'target' is <= 0, in which case process 27 // Only process up to 'target' threads, unless 'target' is <= 0, in which case process
29 // them all. 28 // them all.
30 std::size_t last = waiting_threads.size(); 29 std::size_t last = waiting_threads.size();
diff --git a/src/core/hle/kernel/handle_table.cpp b/src/core/hle/kernel/handle_table.cpp
index 35448b576..fb30b6f8b 100644
--- a/src/core/hle/kernel/handle_table.cpp
+++ b/src/core/hle/kernel/handle_table.cpp
@@ -8,7 +8,9 @@
8#include "core/core.h" 8#include "core/core.h"
9#include "core/hle/kernel/errors.h" 9#include "core/hle/kernel/errors.h"
10#include "core/hle/kernel/handle_table.h" 10#include "core/hle/kernel/handle_table.h"
11#include "core/hle/kernel/kernel.h"
11#include "core/hle/kernel/process.h" 12#include "core/hle/kernel/process.h"
13#include "core/hle/kernel/scheduler.h"
12#include "core/hle/kernel/thread.h" 14#include "core/hle/kernel/thread.h"
13 15
14namespace Kernel { 16namespace Kernel {
@@ -22,7 +24,7 @@ constexpr u16 GetGeneration(Handle handle) {
22} 24}
23} // Anonymous namespace 25} // Anonymous namespace
24 26
25HandleTable::HandleTable() { 27HandleTable::HandleTable(KernelCore& kernel) : kernel{kernel} {
26 Clear(); 28 Clear();
27} 29}
28 30
@@ -103,9 +105,9 @@ bool HandleTable::IsValid(Handle handle) const {
103 105
104std::shared_ptr<Object> HandleTable::GetGeneric(Handle handle) const { 106std::shared_ptr<Object> HandleTable::GetGeneric(Handle handle) const {
105 if (handle == CurrentThread) { 107 if (handle == CurrentThread) {
106 return SharedFrom(GetCurrentThread()); 108 return SharedFrom(kernel.CurrentScheduler().GetCurrentThread());
107 } else if (handle == CurrentProcess) { 109 } else if (handle == CurrentProcess) {
108 return SharedFrom(Core::System::GetInstance().CurrentProcess()); 110 return SharedFrom(kernel.CurrentProcess());
109 } 111 }
110 112
111 if (!IsValid(handle)) { 113 if (!IsValid(handle)) {
diff --git a/src/core/hle/kernel/handle_table.h b/src/core/hle/kernel/handle_table.h
index 8029660ed..c9dab8cdd 100644
--- a/src/core/hle/kernel/handle_table.h
+++ b/src/core/hle/kernel/handle_table.h
@@ -14,6 +14,8 @@
14 14
15namespace Kernel { 15namespace Kernel {
16 16
17class KernelCore;
18
17enum KernelHandle : Handle { 19enum KernelHandle : Handle {
18 InvalidHandle = 0, 20 InvalidHandle = 0,
19 CurrentThread = 0xFFFF8000, 21 CurrentThread = 0xFFFF8000,
@@ -48,7 +50,7 @@ public:
48 /// This is the maximum limit of handles allowed per process in Horizon 50 /// This is the maximum limit of handles allowed per process in Horizon
49 static constexpr std::size_t MAX_COUNT = 1024; 51 static constexpr std::size_t MAX_COUNT = 1024;
50 52
51 HandleTable(); 53 explicit HandleTable(KernelCore& kernel);
52 ~HandleTable(); 54 ~HandleTable();
53 55
54 /** 56 /**
@@ -134,6 +136,9 @@ private:
134 136
135 /// Head of the free slots linked list. 137 /// Head of the free slots linked list.
136 u16 next_free_slot = 0; 138 u16 next_free_slot = 0;
139
140 /// Underlying kernel instance that this handle table operates under.
141 KernelCore& kernel;
137}; 142};
138 143
139} // namespace Kernel 144} // namespace Kernel
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 1f2af7a1b..8dd4a2637 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -50,7 +50,8 @@ namespace Kernel {
50 50
51struct KernelCore::Impl { 51struct KernelCore::Impl {
52 explicit Impl(Core::System& system, KernelCore& kernel) 52 explicit Impl(Core::System& system, KernelCore& kernel)
53 : global_scheduler{kernel}, synchronization{system}, time_manager{system}, system{system} {} 53 : global_scheduler{kernel}, synchronization{system}, time_manager{system},
54 global_handle_table{kernel}, system{system} {}
54 55
55 void SetMulticore(bool is_multicore) { 56 void SetMulticore(bool is_multicore) {
56 this->is_multicore = is_multicore; 57 this->is_multicore = is_multicore;
@@ -144,29 +145,32 @@ struct KernelCore::Impl {
144 145
145 void InitializePreemption(KernelCore& kernel) { 146 void InitializePreemption(KernelCore& kernel) {
146 preemption_event = Core::Timing::CreateEvent( 147 preemption_event = Core::Timing::CreateEvent(
147 "PreemptionCallback", [this, &kernel](u64 userdata, s64 cycles_late) { 148 "PreemptionCallback", [this, &kernel](u64, std::chrono::nanoseconds) {
148 { 149 {
149 SchedulerLock lock(kernel); 150 SchedulerLock lock(kernel);
150 global_scheduler.PreemptThreads(); 151 global_scheduler.PreemptThreads();
151 } 152 }
152 s64 time_interval = Core::Timing::msToCycles(std::chrono::milliseconds(10)); 153 const auto time_interval = std::chrono::nanoseconds{
154 Core::Timing::msToCycles(std::chrono::milliseconds(10))};
153 system.CoreTiming().ScheduleEvent(time_interval, preemption_event); 155 system.CoreTiming().ScheduleEvent(time_interval, preemption_event);
154 }); 156 });
155 157
156 s64 time_interval = Core::Timing::msToCycles(std::chrono::milliseconds(10)); 158 const auto time_interval =
159 std::chrono::nanoseconds{Core::Timing::msToCycles(std::chrono::milliseconds(10))};
157 system.CoreTiming().ScheduleEvent(time_interval, preemption_event); 160 system.CoreTiming().ScheduleEvent(time_interval, preemption_event);
158 } 161 }
159 162
160 void InitializeSuspendThreads() { 163 void InitializeSuspendThreads() {
161 for (std::size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) { 164 for (std::size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
162 std::string name = "Suspend Thread Id:" + std::to_string(i); 165 std::string name = "Suspend Thread Id:" + std::to_string(i);
163 std::function<void(void*)> init_func = 166 std::function<void(void*)> init_func = Core::CpuManager::GetSuspendThreadStartFunc();
164 system.GetCpuManager().GetSuspendThreadStartFunc();
165 void* init_func_parameter = system.GetCpuManager().GetStartFuncParamater(); 167 void* init_func_parameter = system.GetCpuManager().GetStartFuncParamater();
166 ThreadType type = 168 const auto type =
167 static_cast<ThreadType>(THREADTYPE_KERNEL | THREADTYPE_HLE | THREADTYPE_SUSPEND); 169 static_cast<ThreadType>(THREADTYPE_KERNEL | THREADTYPE_HLE | THREADTYPE_SUSPEND);
168 auto thread_res = Thread::Create(system, type, name, 0, 0, 0, static_cast<u32>(i), 0, 170 auto thread_res =
169 nullptr, std::move(init_func), init_func_parameter); 171 Thread::Create(system, type, std::move(name), 0, 0, 0, static_cast<u32>(i), 0,
172 nullptr, std::move(init_func), init_func_parameter);
173
170 suspend_threads[i] = std::move(thread_res).Unwrap(); 174 suspend_threads[i] = std::move(thread_res).Unwrap();
171 } 175 }
172 } 176 }
@@ -307,7 +311,7 @@ struct KernelCore::Impl {
307 311
308 // This is the kernel's handle table or supervisor handle table which 312 // This is the kernel's handle table or supervisor handle table which
309 // stores all the objects in place. 313 // stores all the objects in place.
310 Kernel::HandleTable global_handle_table; 314 HandleTable global_handle_table;
311 315
312 /// Map of named ports managed by the kernel, which can be retrieved using 316 /// Map of named ports managed by the kernel, which can be retrieved using
313 /// the ConnectToPort SVC. 317 /// the ConnectToPort SVC.
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 49bd47e89..16285c3f0 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -9,6 +9,7 @@
9#include <string> 9#include <string>
10#include <unordered_map> 10#include <unordered_map>
11#include <vector> 11#include <vector>
12#include "core/arm/cpu_interrupt_handler.h"
12#include "core/hardware_properties.h" 13#include "core/hardware_properties.h"
13#include "core/hle/kernel/memory/memory_types.h" 14#include "core/hle/kernel/memory/memory_types.h"
14#include "core/hle/kernel/object.h" 15#include "core/hle/kernel/object.h"
diff --git a/src/core/hle/kernel/memory/address_space_info.cpp b/src/core/hle/kernel/memory/address_space_info.cpp
index a523a2502..e4288cab4 100644
--- a/src/core/hle/kernel/memory/address_space_info.cpp
+++ b/src/core/hle/kernel/memory/address_space_info.cpp
@@ -29,40 +29,39 @@ enum : u64 {
29 29
30// clang-format off 30// clang-format off
31constexpr std::array<AddressSpaceInfo, 13> AddressSpaceInfos{{ 31constexpr std::array<AddressSpaceInfo, 13> AddressSpaceInfos{{
32 { 32 /*bit_width*/, Size_2_MB /*addr*/, Size_1_GB - Size_2_MB /*size*/, AddressSpaceInfo::Type::Is32Bit, }, 32 { .bit_width = 32, .address = Size_2_MB , .size = Size_1_GB - Size_2_MB , .type = AddressSpaceInfo::Type::Is32Bit, },
33 { 32 /*bit_width*/, Size_1_GB /*addr*/, Size_4_GB - Size_1_GB /*size*/, AddressSpaceInfo::Type::Small64Bit, }, 33 { .bit_width = 32, .address = Size_1_GB , .size = Size_4_GB - Size_1_GB , .type = AddressSpaceInfo::Type::Small64Bit, },
34 { 32 /*bit_width*/, Invalid /*addr*/, Size_1_GB /*size*/, AddressSpaceInfo::Type::Heap, }, 34 { .bit_width = 32, .address = Invalid , .size = Size_1_GB , .type = AddressSpaceInfo::Type::Heap, },
35 { 32 /*bit_width*/, Invalid /*addr*/, Size_1_GB /*size*/, AddressSpaceInfo::Type::Alias, }, 35 { .bit_width = 32, .address = Invalid , .size = Size_1_GB , .type = AddressSpaceInfo::Type::Alias, },
36 { 36 /*bit_width*/, Size_128_MB /*addr*/, Size_2_GB - Size_128_MB /*size*/, AddressSpaceInfo::Type::Is32Bit, }, 36 { .bit_width = 36, .address = Size_128_MB, .size = Size_2_GB - Size_128_MB, .type = AddressSpaceInfo::Type::Is32Bit, },
37 { 36 /*bit_width*/, Size_2_GB /*addr*/, Size_64_GB - Size_2_GB /*size*/, AddressSpaceInfo::Type::Small64Bit, }, 37 { .bit_width = 36, .address = Size_2_GB , .size = Size_64_GB - Size_2_GB , .type = AddressSpaceInfo::Type::Small64Bit, },
38 { 36 /*bit_width*/, Invalid /*addr*/, Size_6_GB /*size*/, AddressSpaceInfo::Type::Heap, }, 38 { .bit_width = 36, .address = Invalid , .size = Size_6_GB , .type = AddressSpaceInfo::Type::Heap, },
39 { 36 /*bit_width*/, Invalid /*addr*/, Size_6_GB /*size*/, AddressSpaceInfo::Type::Alias, }, 39 { .bit_width = 36, .address = Invalid , .size = Size_6_GB , .type = AddressSpaceInfo::Type::Alias, },
40 { 39 /*bit_width*/, Size_128_MB /*addr*/, Size_512_GB - Size_128_MB /*size*/, AddressSpaceInfo::Type::Large64Bit, }, 40 { .bit_width = 39, .address = Size_128_MB, .size = Size_512_GB - Size_128_MB, .type = AddressSpaceInfo::Type::Large64Bit, },
41 { 39 /*bit_width*/, Invalid /*addr*/, Size_64_GB /*size*/, AddressSpaceInfo::Type::Is32Bit }, 41 { .bit_width = 39, .address = Invalid , .size = Size_64_GB , .type = AddressSpaceInfo::Type::Is32Bit },
42 { 39 /*bit_width*/, Invalid /*addr*/, Size_6_GB /*size*/, AddressSpaceInfo::Type::Heap, }, 42 { .bit_width = 39, .address = Invalid , .size = Size_6_GB , .type = AddressSpaceInfo::Type::Heap, },
43 { 39 /*bit_width*/, Invalid /*addr*/, Size_64_GB /*size*/, AddressSpaceInfo::Type::Alias, }, 43 { .bit_width = 39, .address = Invalid , .size = Size_64_GB , .type = AddressSpaceInfo::Type::Alias, },
44 { 39 /*bit_width*/, Invalid /*addr*/, Size_2_GB /*size*/, AddressSpaceInfo::Type::Stack, }, 44 { .bit_width = 39, .address = Invalid , .size = Size_2_GB , .type = AddressSpaceInfo::Type::Stack, },
45}}; 45}};
46// clang-format on 46// clang-format on
47 47
48constexpr bool IsAllowedIndexForAddress(std::size_t index) { 48constexpr bool IsAllowedIndexForAddress(std::size_t index) {
49 return index < std::size(AddressSpaceInfos) && AddressSpaceInfos[index].GetAddress() != Invalid; 49 return index < AddressSpaceInfos.size() && AddressSpaceInfos[index].address != Invalid;
50} 50}
51 51
52constexpr std::array<std::size_t, static_cast<std::size_t>(AddressSpaceInfo::Type::Count)> 52using IndexArray = std::array<std::size_t, static_cast<std::size_t>(AddressSpaceInfo::Type::Count)>;
53 AddressSpaceIndices32Bit{
54 0, 1, 0, 2, 0, 3,
55 };
56 53
57constexpr std::array<std::size_t, static_cast<std::size_t>(AddressSpaceInfo::Type::Count)> 54constexpr IndexArray AddressSpaceIndices32Bit{
58 AddressSpaceIndices36Bit{ 55 0, 1, 0, 2, 0, 3,
59 4, 5, 4, 6, 4, 7, 56};
60 }; 57
58constexpr IndexArray AddressSpaceIndices36Bit{
59 4, 5, 4, 6, 4, 7,
60};
61 61
62constexpr std::array<std::size_t, static_cast<std::size_t>(AddressSpaceInfo::Type::Count)> 62constexpr IndexArray AddressSpaceIndices39Bit{
63 AddressSpaceIndices39Bit{ 63 9, 8, 8, 10, 12, 11,
64 9, 8, 8, 10, 12, 11, 64};
65 };
66 65
67constexpr bool IsAllowed32BitType(AddressSpaceInfo::Type type) { 66constexpr bool IsAllowed32BitType(AddressSpaceInfo::Type type) {
68 return type < AddressSpaceInfo::Type::Count && type != AddressSpaceInfo::Type::Large64Bit && 67 return type < AddressSpaceInfo::Type::Count && type != AddressSpaceInfo::Type::Large64Bit &&
@@ -80,37 +79,37 @@ constexpr bool IsAllowed39BitType(AddressSpaceInfo::Type type) {
80 79
81} // namespace 80} // namespace
82 81
83u64 AddressSpaceInfo::GetAddressSpaceStart(std::size_t width, AddressSpaceInfo::Type type) { 82u64 AddressSpaceInfo::GetAddressSpaceStart(std::size_t width, Type type) {
84 const std::size_t index{static_cast<std::size_t>(type)}; 83 const std::size_t index{static_cast<std::size_t>(type)};
85 switch (width) { 84 switch (width) {
86 case 32: 85 case 32:
87 ASSERT(IsAllowed32BitType(type)); 86 ASSERT(IsAllowed32BitType(type));
88 ASSERT(IsAllowedIndexForAddress(AddressSpaceIndices32Bit[index])); 87 ASSERT(IsAllowedIndexForAddress(AddressSpaceIndices32Bit[index]));
89 return AddressSpaceInfos[AddressSpaceIndices32Bit[index]].GetAddress(); 88 return AddressSpaceInfos[AddressSpaceIndices32Bit[index]].address;
90 case 36: 89 case 36:
91 ASSERT(IsAllowed36BitType(type)); 90 ASSERT(IsAllowed36BitType(type));
92 ASSERT(IsAllowedIndexForAddress(AddressSpaceIndices36Bit[index])); 91 ASSERT(IsAllowedIndexForAddress(AddressSpaceIndices36Bit[index]));
93 return AddressSpaceInfos[AddressSpaceIndices36Bit[index]].GetAddress(); 92 return AddressSpaceInfos[AddressSpaceIndices36Bit[index]].address;
94 case 39: 93 case 39:
95 ASSERT(IsAllowed39BitType(type)); 94 ASSERT(IsAllowed39BitType(type));
96 ASSERT(IsAllowedIndexForAddress(AddressSpaceIndices39Bit[index])); 95 ASSERT(IsAllowedIndexForAddress(AddressSpaceIndices39Bit[index]));
97 return AddressSpaceInfos[AddressSpaceIndices39Bit[index]].GetAddress(); 96 return AddressSpaceInfos[AddressSpaceIndices39Bit[index]].address;
98 } 97 }
99 UNREACHABLE(); 98 UNREACHABLE();
100} 99}
101 100
102std::size_t AddressSpaceInfo::GetAddressSpaceSize(std::size_t width, AddressSpaceInfo::Type type) { 101std::size_t AddressSpaceInfo::GetAddressSpaceSize(std::size_t width, Type type) {
103 const std::size_t index{static_cast<std::size_t>(type)}; 102 const std::size_t index{static_cast<std::size_t>(type)};
104 switch (width) { 103 switch (width) {
105 case 32: 104 case 32:
106 ASSERT(IsAllowed32BitType(type)); 105 ASSERT(IsAllowed32BitType(type));
107 return AddressSpaceInfos[AddressSpaceIndices32Bit[index]].GetSize(); 106 return AddressSpaceInfos[AddressSpaceIndices32Bit[index]].size;
108 case 36: 107 case 36:
109 ASSERT(IsAllowed36BitType(type)); 108 ASSERT(IsAllowed36BitType(type));
110 return AddressSpaceInfos[AddressSpaceIndices36Bit[index]].GetSize(); 109 return AddressSpaceInfos[AddressSpaceIndices36Bit[index]].size;
111 case 39: 110 case 39:
112 ASSERT(IsAllowed39BitType(type)); 111 ASSERT(IsAllowed39BitType(type));
113 return AddressSpaceInfos[AddressSpaceIndices39Bit[index]].GetSize(); 112 return AddressSpaceInfos[AddressSpaceIndices39Bit[index]].size;
114 } 113 }
115 UNREACHABLE(); 114 UNREACHABLE();
116} 115}
diff --git a/src/core/hle/kernel/memory/address_space_info.h b/src/core/hle/kernel/memory/address_space_info.h
index c479890be..a4e6e91e5 100644
--- a/src/core/hle/kernel/memory/address_space_info.h
+++ b/src/core/hle/kernel/memory/address_space_info.h
@@ -11,8 +11,7 @@
11 11
12namespace Kernel::Memory { 12namespace Kernel::Memory {
13 13
14class AddressSpaceInfo final : NonCopyable { 14struct AddressSpaceInfo final {
15public:
16 enum class Type : u32 { 15 enum class Type : u32 {
17 Is32Bit = 0, 16 Is32Bit = 0,
18 Small64Bit = 1, 17 Small64Bit = 1,
@@ -23,31 +22,13 @@ public:
23 Count, 22 Count,
24 }; 23 };
25 24
26private:
27 std::size_t bit_width{};
28 std::size_t addr{};
29 std::size_t size{};
30 Type type{};
31
32public:
33 static u64 GetAddressSpaceStart(std::size_t width, Type type); 25 static u64 GetAddressSpaceStart(std::size_t width, Type type);
34 static std::size_t GetAddressSpaceSize(std::size_t width, Type type); 26 static std::size_t GetAddressSpaceSize(std::size_t width, Type type);
35 27
36 constexpr AddressSpaceInfo(std::size_t bit_width, std::size_t addr, std::size_t size, Type type) 28 const std::size_t bit_width{};
37 : bit_width{bit_width}, addr{addr}, size{size}, type{type} {} 29 const std::size_t address{};
38 30 const std::size_t size{};
39 constexpr std::size_t GetWidth() const { 31 const Type type{};
40 return bit_width;
41 }
42 constexpr std::size_t GetAddress() const {
43 return addr;
44 }
45 constexpr std::size_t GetSize() const {
46 return size;
47 }
48 constexpr Type GetType() const {
49 return type;
50 }
51}; 32};
52 33
53} // namespace Kernel::Memory 34} // namespace Kernel::Memory
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index c6fcb56ad..ff9d9248b 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -408,7 +408,7 @@ void Process::LoadModule(CodeSet code_set, VAddr base_addr) {
408Process::Process(Core::System& system) 408Process::Process(Core::System& system)
409 : SynchronizationObject{system.Kernel()}, page_table{std::make_unique<Memory::PageTable>( 409 : SynchronizationObject{system.Kernel()}, page_table{std::make_unique<Memory::PageTable>(
410 system)}, 410 system)},
411 address_arbiter{system}, mutex{system}, system{system} {} 411 handle_table{system.Kernel()}, address_arbiter{system}, mutex{system}, system{system} {}
412 412
413Process::~Process() = default; 413Process::~Process() = default;
414 414
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h
index 9dabe3568..f45cb5674 100644
--- a/src/core/hle/kernel/process.h
+++ b/src/core/hle/kernel/process.h
@@ -382,12 +382,6 @@ private:
382 /// List of threads waiting for a condition variable 382 /// List of threads waiting for a condition variable
383 std::unordered_map<VAddr, std::list<std::shared_ptr<Thread>>> cond_var_threads; 383 std::unordered_map<VAddr, std::list<std::shared_ptr<Thread>>> cond_var_threads;
384 384
385 /// System context
386 Core::System& system;
387
388 /// Name of this process
389 std::string name;
390
391 /// Address of the top of the main thread's stack 385 /// Address of the top of the main thread's stack
392 VAddr main_thread_stack_top{}; 386 VAddr main_thread_stack_top{};
393 387
@@ -399,6 +393,12 @@ private:
399 393
400 /// Process total image size 394 /// Process total image size
401 std::size_t image_size{}; 395 std::size_t image_size{};
396
397 /// Name of this process
398 std::string name;
399
400 /// System context
401 Core::System& system;
402}; 402};
403 403
404} // namespace Kernel 404} // namespace Kernel
diff --git a/src/core/hle/kernel/scheduler.cpp b/src/core/hle/kernel/scheduler.cpp
index 7b929781c..f93e5e4b0 100644
--- a/src/core/hle/kernel/scheduler.cpp
+++ b/src/core/hle/kernel/scheduler.cpp
@@ -802,7 +802,7 @@ void Scheduler::UpdateLastContextSwitchTime(Thread* thread, Process* process) {
802 802
803void Scheduler::Initialize() { 803void Scheduler::Initialize() {
804 std::string name = "Idle Thread Id:" + std::to_string(core_id); 804 std::string name = "Idle Thread Id:" + std::to_string(core_id);
805 std::function<void(void*)> init_func = system.GetCpuManager().GetIdleThreadStartFunc(); 805 std::function<void(void*)> init_func = Core::CpuManager::GetIdleThreadStartFunc();
806 void* init_func_parameter = system.GetCpuManager().GetStartFuncParamater(); 806 void* init_func_parameter = system.GetCpuManager().GetStartFuncParamater();
807 ThreadType type = static_cast<ThreadType>(THREADTYPE_KERNEL | THREADTYPE_HLE | THREADTYPE_IDLE); 807 ThreadType type = static_cast<ThreadType>(THREADTYPE_KERNEL | THREADTYPE_HLE | THREADTYPE_IDLE);
808 auto thread_res = Thread::Create(system, type, name, 0, 64, 0, static_cast<u32>(core_id), 0, 808 auto thread_res = Thread::Create(system, type, name, 0, 64, 0, static_cast<u32>(core_id), 0,
diff --git a/src/core/hle/kernel/server_session.cpp b/src/core/hle/kernel/server_session.cpp
index 7b23a6889..af22f4c33 100644
--- a/src/core/hle/kernel/server_session.cpp
+++ b/src/core/hle/kernel/server_session.cpp
@@ -34,7 +34,7 @@ ResultVal<std::shared_ptr<ServerSession>> ServerSession::Create(KernelCore& kern
34 std::shared_ptr<ServerSession> session{std::make_shared<ServerSession>(kernel)}; 34 std::shared_ptr<ServerSession> session{std::make_shared<ServerSession>(kernel)};
35 35
36 session->request_event = Core::Timing::CreateEvent( 36 session->request_event = Core::Timing::CreateEvent(
37 name, [session](u64 userdata, s64 cycles_late) { session->CompleteSyncRequest(); }); 37 name, [session](u64, std::chrono::nanoseconds) { session->CompleteSyncRequest(); });
38 session->name = std::move(name); 38 session->name = std::move(name);
39 session->parent = std::move(parent); 39 session->parent = std::move(parent);
40 40
@@ -184,8 +184,8 @@ ResultCode ServerSession::CompleteSyncRequest() {
184 184
185ResultCode ServerSession::HandleSyncRequest(std::shared_ptr<Thread> thread, 185ResultCode ServerSession::HandleSyncRequest(std::shared_ptr<Thread> thread,
186 Core::Memory::Memory& memory) { 186 Core::Memory::Memory& memory) {
187 ResultCode result = QueueSyncRequest(std::move(thread), memory); 187 const ResultCode result = QueueSyncRequest(std::move(thread), memory);
188 const u64 delay = kernel.IsMulticore() ? 0U : 20000U; 188 const auto delay = std::chrono::nanoseconds{kernel.IsMulticore() ? 0 : 20000};
189 Core::System::GetInstance().CoreTiming().ScheduleEvent(delay, request_event, {}); 189 Core::System::GetInstance().CoreTiming().ScheduleEvent(delay, request_event, {});
190 return result; 190 return result;
191} 191}
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 5db19dcf3..01ae57053 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -458,9 +458,7 @@ static ResultCode WaitSynchronization(Core::System& system, Handle* index, VAddr
458 return ERR_OUT_OF_RANGE; 458 return ERR_OUT_OF_RANGE;
459 } 459 }
460 460
461 auto* const thread = system.CurrentScheduler().GetCurrentThread();
462 auto& kernel = system.Kernel(); 461 auto& kernel = system.Kernel();
463 using ObjectPtr = Thread::ThreadSynchronizationObjects::value_type;
464 Thread::ThreadSynchronizationObjects objects(handle_count); 462 Thread::ThreadSynchronizationObjects objects(handle_count);
465 const auto& handle_table = kernel.CurrentProcess()->GetHandleTable(); 463 const auto& handle_table = kernel.CurrentProcess()->GetHandleTable();
466 464
@@ -1750,9 +1748,9 @@ static void SignalProcessWideKey(Core::System& system, VAddr condition_variable_
1750 // Only process up to 'target' threads, unless 'target' is less equal 0, in which case process 1748 // Only process up to 'target' threads, unless 'target' is less equal 0, in which case process
1751 // them all. 1749 // them all.
1752 std::size_t last = waiting_threads.size(); 1750 std::size_t last = waiting_threads.size();
1753 if (target > 0) 1751 if (target > 0) {
1754 last = std::min(waiting_threads.size(), static_cast<std::size_t>(target)); 1752 last = std::min(waiting_threads.size(), static_cast<std::size_t>(target));
1755 auto& time_manager = kernel.TimeManager(); 1753 }
1756 for (std::size_t index = 0; index < last; ++index) { 1754 for (std::size_t index = 0; index < last; ++index) {
1757 auto& thread = waiting_threads[index]; 1755 auto& thread = waiting_threads[index];
1758 1756
@@ -1763,7 +1761,6 @@ static void SignalProcessWideKey(Core::System& system, VAddr condition_variable_
1763 1761
1764 const std::size_t current_core = system.CurrentCoreIndex(); 1762 const std::size_t current_core = system.CurrentCoreIndex();
1765 auto& monitor = system.Monitor(); 1763 auto& monitor = system.Monitor();
1766 auto& memory = system.Memory();
1767 1764
1768 // Atomically read the value of the mutex. 1765 // Atomically read the value of the mutex.
1769 u32 mutex_val = 0; 1766 u32 mutex_val = 0;
diff --git a/src/core/hle/kernel/synchronization.cpp b/src/core/hle/kernel/synchronization.cpp
index 851b702a5..8b875d853 100644
--- a/src/core/hle/kernel/synchronization.cpp
+++ b/src/core/hle/kernel/synchronization.cpp
@@ -19,7 +19,6 @@ Synchronization::Synchronization(Core::System& system) : system{system} {}
19void Synchronization::SignalObject(SynchronizationObject& obj) const { 19void Synchronization::SignalObject(SynchronizationObject& obj) const {
20 auto& kernel = system.Kernel(); 20 auto& kernel = system.Kernel();
21 SchedulerLock lock(kernel); 21 SchedulerLock lock(kernel);
22 auto& time_manager = kernel.TimeManager();
23 if (obj.IsSignaled()) { 22 if (obj.IsSignaled()) {
24 for (auto thread : obj.GetWaitingThreads()) { 23 for (auto thread : obj.GetWaitingThreads()) {
25 if (thread->GetSchedulingStatus() == ThreadSchedStatus::Paused) { 24 if (thread->GetSchedulingStatus() == ThreadSchedStatus::Paused) {
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 2b1092697..d132aba34 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -13,16 +13,8 @@
13#include "common/logging/log.h" 13#include "common/logging/log.h"
14#include "common/thread_queue_list.h" 14#include "common/thread_queue_list.h"
15#include "core/arm/arm_interface.h" 15#include "core/arm/arm_interface.h"
16#ifdef ARCHITECTURE_x86_64
17#include "core/arm/dynarmic/arm_dynarmic_32.h"
18#include "core/arm/dynarmic/arm_dynarmic_64.h"
19#endif
20#include "core/arm/cpu_interrupt_handler.h"
21#include "core/arm/exclusive_monitor.h"
22#include "core/arm/unicorn/arm_unicorn.h" 16#include "core/arm/unicorn/arm_unicorn.h"
23#include "core/core.h" 17#include "core/core.h"
24#include "core/core_timing.h"
25#include "core/core_timing_util.h"
26#include "core/cpu_manager.h" 18#include "core/cpu_manager.h"
27#include "core/hardware_properties.h" 19#include "core/hardware_properties.h"
28#include "core/hle/kernel/errors.h" 20#include "core/hle/kernel/errors.h"
@@ -36,6 +28,11 @@
36#include "core/hle/result.h" 28#include "core/hle/result.h"
37#include "core/memory.h" 29#include "core/memory.h"
38 30
31#ifdef ARCHITECTURE_x86_64
32#include "core/arm/dynarmic/arm_dynarmic_32.h"
33#include "core/arm/dynarmic/arm_dynarmic_64.h"
34#endif
35
39namespace Kernel { 36namespace Kernel {
40 37
41bool Thread::ShouldWait(const Thread* thread) const { 38bool Thread::ShouldWait(const Thread* thread) const {
@@ -158,7 +155,7 @@ ResultVal<std::shared_ptr<Thread>> Thread::Create(Core::System& system, ThreadTy
158 std::string name, VAddr entry_point, u32 priority, 155 std::string name, VAddr entry_point, u32 priority,
159 u64 arg, s32 processor_id, VAddr stack_top, 156 u64 arg, s32 processor_id, VAddr stack_top,
160 Process* owner_process) { 157 Process* owner_process) {
161 std::function<void(void*)> init_func = system.GetCpuManager().GetGuestThreadStartFunc(); 158 std::function<void(void*)> init_func = Core::CpuManager::GetGuestThreadStartFunc();
162 void* init_func_parameter = system.GetCpuManager().GetStartFuncParamater(); 159 void* init_func_parameter = system.GetCpuManager().GetStartFuncParamater();
163 return Create(system, type_flags, name, entry_point, priority, arg, processor_id, stack_top, 160 return Create(system, type_flags, name, entry_point, priority, arg, processor_id, stack_top,
164 owner_process, std::move(init_func), init_func_parameter); 161 owner_process, std::move(init_func), init_func_parameter);
@@ -540,13 +537,4 @@ ResultCode Thread::SetCoreAndAffinityMask(s32 new_core, u64 new_affinity_mask) {
540 return RESULT_SUCCESS; 537 return RESULT_SUCCESS;
541} 538}
542 539
543////////////////////////////////////////////////////////////////////////////////////////////////////
544
545/**
546 * Gets the current thread
547 */
548Thread* GetCurrentThread() {
549 return Core::System::GetInstance().CurrentScheduler().GetCurrentThread();
550}
551
552} // namespace Kernel 540} // namespace Kernel
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index c0342c462..8daf79fac 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -583,8 +583,6 @@ private:
583 583
584 void SetCurrentPriority(u32 new_priority); 584 void SetCurrentPriority(u32 new_priority);
585 585
586 void AdjustSchedulingOnAffinity(u64 old_affinity_mask, s32 old_core);
587
588 Common::SpinLock context_guard{}; 586 Common::SpinLock context_guard{};
589 ThreadContext32 context_32{}; 587 ThreadContext32 context_32{};
590 ThreadContext64 context_64{}; 588 ThreadContext64 context_64{};
@@ -680,9 +678,4 @@ private:
680 std::string name; 678 std::string name;
681}; 679};
682 680
683/**
684 * Gets the current thread
685 */
686Thread* GetCurrentThread();
687
688} // namespace Kernel 681} // namespace Kernel
diff --git a/src/core/hle/kernel/time_manager.cpp b/src/core/hle/kernel/time_manager.cpp
index 941305e8e..88b01b751 100644
--- a/src/core/hle/kernel/time_manager.cpp
+++ b/src/core/hle/kernel/time_manager.cpp
@@ -16,7 +16,7 @@ namespace Kernel {
16 16
17TimeManager::TimeManager(Core::System& system_) : system{system_} { 17TimeManager::TimeManager(Core::System& system_) : system{system_} {
18 time_manager_event_type = Core::Timing::CreateEvent( 18 time_manager_event_type = Core::Timing::CreateEvent(
19 "Kernel::TimeManagerCallback", [this](u64 thread_handle, [[maybe_unused]] s64 cycles_late) { 19 "Kernel::TimeManagerCallback", [this](u64 thread_handle, std::chrono::nanoseconds) {
20 SchedulerLock lock(system.Kernel()); 20 SchedulerLock lock(system.Kernel());
21 Handle proper_handle = static_cast<Handle>(thread_handle); 21 Handle proper_handle = static_cast<Handle>(thread_handle);
22 if (cancelled_events[proper_handle]) { 22 if (cancelled_events[proper_handle]) {
@@ -34,7 +34,8 @@ void TimeManager::ScheduleTimeEvent(Handle& event_handle, Thread* timetask, s64
34 ASSERT(timetask); 34 ASSERT(timetask);
35 ASSERT(timetask->GetStatus() != ThreadStatus::Ready); 35 ASSERT(timetask->GetStatus() != ThreadStatus::Ready);
36 ASSERT(timetask->GetStatus() != ThreadStatus::WaitMutex); 36 ASSERT(timetask->GetStatus() != ThreadStatus::WaitMutex);
37 system.CoreTiming().ScheduleEvent(nanoseconds, time_manager_event_type, event_handle); 37 system.CoreTiming().ScheduleEvent(std::chrono::nanoseconds{nanoseconds},
38 time_manager_event_type, event_handle);
38 } else { 39 } else {
39 event_handle = InvalidHandle; 40 event_handle = InvalidHandle;
40 } 41 }
diff --git a/src/core/hle/service/am/applets/software_keyboard.cpp b/src/core/hle/service/am/applets/software_keyboard.cpp
index fbe3686ae..289da2619 100644
--- a/src/core/hle/service/am/applets/software_keyboard.cpp
+++ b/src/core/hle/service/am/applets/software_keyboard.cpp
@@ -13,11 +13,23 @@
13 13
14namespace Service::AM::Applets { 14namespace Service::AM::Applets {
15 15
16namespace {
17enum class Request : u32 {
18 Finalize = 0x4,
19 SetUserWordInfo = 0x6,
20 SetCustomizeDic = 0x7,
21 Calc = 0xa,
22 SetCustomizedDictionaries = 0xb,
23 UnsetCustomizedDictionaries = 0xc,
24 UnknownD = 0xd,
25 UnknownE = 0xe,
26};
27constexpr std::size_t SWKBD_INLINE_INIT_SIZE = 0x8;
16constexpr std::size_t SWKBD_OUTPUT_BUFFER_SIZE = 0x7D8; 28constexpr std::size_t SWKBD_OUTPUT_BUFFER_SIZE = 0x7D8;
17constexpr std::size_t SWKBD_OUTPUT_INTERACTIVE_BUFFER_SIZE = 0x7D4; 29constexpr std::size_t SWKBD_OUTPUT_INTERACTIVE_BUFFER_SIZE = 0x7D4;
18constexpr std::size_t DEFAULT_MAX_LENGTH = 500; 30constexpr std::size_t DEFAULT_MAX_LENGTH = 500;
19constexpr bool INTERACTIVE_STATUS_OK = false; 31constexpr bool INTERACTIVE_STATUS_OK = false;
20 32} // Anonymous namespace
21static Core::Frontend::SoftwareKeyboardParameters ConvertToFrontendParameters( 33static Core::Frontend::SoftwareKeyboardParameters ConvertToFrontendParameters(
22 KeyboardConfig config, std::u16string initial_text) { 34 KeyboardConfig config, std::u16string initial_text) {
23 Core::Frontend::SoftwareKeyboardParameters params{}; 35 Core::Frontend::SoftwareKeyboardParameters params{};
@@ -47,6 +59,7 @@ SoftwareKeyboard::~SoftwareKeyboard() = default;
47 59
48void SoftwareKeyboard::Initialize() { 60void SoftwareKeyboard::Initialize() {
49 complete = false; 61 complete = false;
62 is_inline = false;
50 initial_text.clear(); 63 initial_text.clear();
51 final_data.clear(); 64 final_data.clear();
52 65
@@ -56,6 +69,11 @@ void SoftwareKeyboard::Initialize() {
56 ASSERT(keyboard_config_storage != nullptr); 69 ASSERT(keyboard_config_storage != nullptr);
57 const auto& keyboard_config = keyboard_config_storage->GetData(); 70 const auto& keyboard_config = keyboard_config_storage->GetData();
58 71
72 if (keyboard_config.size() == SWKBD_INLINE_INIT_SIZE) {
73 is_inline = true;
74 return;
75 }
76
59 ASSERT(keyboard_config.size() >= sizeof(KeyboardConfig)); 77 ASSERT(keyboard_config.size() >= sizeof(KeyboardConfig));
60 std::memcpy(&config, keyboard_config.data(), sizeof(KeyboardConfig)); 78 std::memcpy(&config, keyboard_config.data(), sizeof(KeyboardConfig));
61 79
@@ -87,16 +105,32 @@ void SoftwareKeyboard::ExecuteInteractive() {
87 const auto storage = broker.PopInteractiveDataToApplet(); 105 const auto storage = broker.PopInteractiveDataToApplet();
88 ASSERT(storage != nullptr); 106 ASSERT(storage != nullptr);
89 const auto data = storage->GetData(); 107 const auto data = storage->GetData();
90 const auto status = static_cast<bool>(data[0]); 108 if (!is_inline) {
91 109 const auto status = static_cast<bool>(data[0]);
92 if (status == INTERACTIVE_STATUS_OK) { 110 if (status == INTERACTIVE_STATUS_OK) {
93 complete = true; 111 complete = true;
112 } else {
113 std::array<char16_t, SWKBD_OUTPUT_INTERACTIVE_BUFFER_SIZE / 2 - 2> string;
114 std::memcpy(string.data(), data.data() + 4, string.size() * 2);
115 frontend.SendTextCheckDialog(
116 Common::UTF16StringFromFixedZeroTerminatedBuffer(string.data(), string.size()),
117 [this] { broker.SignalStateChanged(); });
118 }
94 } else { 119 } else {
95 std::array<char16_t, SWKBD_OUTPUT_INTERACTIVE_BUFFER_SIZE / 2 - 2> string; 120 Request request{};
96 std::memcpy(string.data(), data.data() + 4, string.size() * 2); 121 std::memcpy(&request, data.data(), sizeof(Request));
97 frontend.SendTextCheckDialog( 122
98 Common::UTF16StringFromFixedZeroTerminatedBuffer(string.data(), string.size()), 123 switch (request) {
99 [this] { broker.SignalStateChanged(); }); 124 case Request::Calc: {
125 broker.PushNormalDataFromApplet(
126 std::make_shared<IStorage>(std::move(std::vector<u8>{1})));
127 broker.SignalStateChanged();
128 break;
129 }
130 default:
131 UNIMPLEMENTED_MSG("Request {:X} is not implemented", request);
132 break;
133 }
100 } 134 }
101} 135}
102 136
@@ -108,9 +142,10 @@ void SoftwareKeyboard::Execute() {
108 } 142 }
109 143
110 const auto parameters = ConvertToFrontendParameters(config, initial_text); 144 const auto parameters = ConvertToFrontendParameters(config, initial_text);
111 145 if (!is_inline) {
112 frontend.RequestText([this](std::optional<std::u16string> text) { WriteText(std::move(text)); }, 146 frontend.RequestText(
113 parameters); 147 [this](std::optional<std::u16string> text) { WriteText(std::move(text)); }, parameters);
148 }
114} 149}
115 150
116void SoftwareKeyboard::WriteText(std::optional<std::u16string> text) { 151void SoftwareKeyboard::WriteText(std::optional<std::u16string> text) {
diff --git a/src/core/hle/service/am/applets/software_keyboard.h b/src/core/hle/service/am/applets/software_keyboard.h
index ef4801fc6..5a3824b5a 100644
--- a/src/core/hle/service/am/applets/software_keyboard.h
+++ b/src/core/hle/service/am/applets/software_keyboard.h
@@ -78,6 +78,7 @@ private:
78 KeyboardConfig config; 78 KeyboardConfig config;
79 std::u16string initial_text; 79 std::u16string initial_text;
80 bool complete = false; 80 bool complete = false;
81 bool is_inline = false;
81 std::vector<u8> final_data; 82 std::vector<u8> final_data;
82}; 83};
83 84
diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp
index cadc03805..c66124998 100644
--- a/src/core/hle/service/filesystem/filesystem.cpp
+++ b/src/core/hle/service/filesystem/filesystem.cpp
@@ -55,6 +55,10 @@ std::string VfsDirectoryServiceWrapper::GetName() const {
55ResultCode VfsDirectoryServiceWrapper::CreateFile(const std::string& path_, u64 size) const { 55ResultCode VfsDirectoryServiceWrapper::CreateFile(const std::string& path_, u64 size) const {
56 std::string path(FileUtil::SanitizePath(path_)); 56 std::string path(FileUtil::SanitizePath(path_));
57 auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path)); 57 auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path));
58 // dir can be nullptr if path contains subdirectories, create those prior to creating the file.
59 if (dir == nullptr) {
60 dir = backing->CreateSubdirectory(FileUtil::GetParentPath(path));
61 }
58 auto file = dir->CreateFile(FileUtil::GetFilename(path)); 62 auto file = dir->CreateFile(FileUtil::GetFilename(path));
59 if (file == nullptr) { 63 if (file == nullptr) {
60 // TODO(DarkLordZach): Find a better error code for this 64 // TODO(DarkLordZach): Find a better error code for this
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index e9020e0dc..680290cbd 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -39,9 +39,10 @@ namespace Service::HID {
39 39
40// Updating period for each HID device. 40// Updating period for each HID device.
41// TODO(ogniK): Find actual polling rate of hid 41// TODO(ogniK): Find actual polling rate of hid
42constexpr s64 pad_update_ticks = static_cast<s64>(1000000000 / 66); 42constexpr auto pad_update_ns = std::chrono::nanoseconds{1000000000 / 66};
43[[maybe_unused]] constexpr s64 accelerometer_update_ticks = static_cast<s64>(1000000000 / 100); 43[[maybe_unused]] constexpr auto accelerometer_update_ns =
44[[maybe_unused]] constexpr s64 gyroscope_update_ticks = static_cast<s64>(1000000000 / 100); 44 std::chrono::nanoseconds{1000000000 / 100};
45[[maybe_unused]] constexpr auto gyroscope_update_ticks = std::chrono::nanoseconds{1000000000 / 100};
45constexpr std::size_t SHARED_MEMORY_SIZE = 0x40000; 46constexpr std::size_t SHARED_MEMORY_SIZE = 0x40000;
46 47
47IAppletResource::IAppletResource(Core::System& system) 48IAppletResource::IAppletResource(Core::System& system)
@@ -75,14 +76,14 @@ IAppletResource::IAppletResource(Core::System& system)
75 GetController<Controller_Stubbed>(HidController::Unknown3).SetCommonHeaderOffset(0x5000); 76 GetController<Controller_Stubbed>(HidController::Unknown3).SetCommonHeaderOffset(0x5000);
76 77
77 // Register update callbacks 78 // Register update callbacks
78 pad_update_event = 79 pad_update_event = Core::Timing::CreateEvent(
79 Core::Timing::CreateEvent("HID::UpdatePadCallback", [this](u64 userdata, s64 ns_late) { 80 "HID::UpdatePadCallback", [this](u64 userdata, std::chrono::nanoseconds ns_late) {
80 UpdateControllers(userdata, ns_late); 81 UpdateControllers(userdata, ns_late);
81 }); 82 });
82 83
83 // TODO(shinyquagsire23): Other update callbacks? (accel, gyro?) 84 // TODO(shinyquagsire23): Other update callbacks? (accel, gyro?)
84 85
85 system.CoreTiming().ScheduleEvent(pad_update_ticks, pad_update_event); 86 system.CoreTiming().ScheduleEvent(pad_update_ns, pad_update_event);
86 87
87 ReloadInputDevices(); 88 ReloadInputDevices();
88} 89}
@@ -107,7 +108,7 @@ void IAppletResource::GetSharedMemoryHandle(Kernel::HLERequestContext& ctx) {
107 rb.PushCopyObjects(shared_mem); 108 rb.PushCopyObjects(shared_mem);
108} 109}
109 110
110void IAppletResource::UpdateControllers(u64 userdata, s64 ns_late) { 111void IAppletResource::UpdateControllers(u64 userdata, std::chrono::nanoseconds ns_late) {
111 auto& core_timing = system.CoreTiming(); 112 auto& core_timing = system.CoreTiming();
112 113
113 const bool should_reload = Settings::values.is_device_reload_pending.exchange(false); 114 const bool should_reload = Settings::values.is_device_reload_pending.exchange(false);
@@ -118,7 +119,7 @@ void IAppletResource::UpdateControllers(u64 userdata, s64 ns_late) {
118 controller->OnUpdate(core_timing, shared_mem->GetPointer(), SHARED_MEMORY_SIZE); 119 controller->OnUpdate(core_timing, shared_mem->GetPointer(), SHARED_MEMORY_SIZE);
119 } 120 }
120 121
121 core_timing.ScheduleEvent(pad_update_ticks - ns_late, pad_update_event); 122 core_timing.ScheduleEvent(pad_update_ns - ns_late, pad_update_event);
122} 123}
123 124
124class IActiveVibrationDeviceList final : public ServiceFramework<IActiveVibrationDeviceList> { 125class IActiveVibrationDeviceList final : public ServiceFramework<IActiveVibrationDeviceList> {
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h
index 6fb048360..c6f0a2584 100644
--- a/src/core/hle/service/hid/hid.h
+++ b/src/core/hle/service/hid/hid.h
@@ -4,10 +4,9 @@
4 4
5#pragma once 5#pragma once
6 6
7#include "core/hle/service/hid/controllers/controller_base.h" 7#include <chrono>
8#include "core/hle/service/service.h"
9 8
10#include "controllers/controller_base.h" 9#include "core/hle/service/hid/controllers/controller_base.h"
11#include "core/hle/service/service.h" 10#include "core/hle/service/service.h"
12 11
13namespace Core::Timing { 12namespace Core::Timing {
@@ -65,7 +64,7 @@ private:
65 } 64 }
66 65
67 void GetSharedMemoryHandle(Kernel::HLERequestContext& ctx); 66 void GetSharedMemoryHandle(Kernel::HLERequestContext& ctx);
68 void UpdateControllers(u64 userdata, s64 cycles_late); 67 void UpdateControllers(u64 userdata, std::chrono::nanoseconds ns_late);
69 68
70 std::shared_ptr<Kernel::SharedMemory> shared_mem; 69 std::shared_ptr<Kernel::SharedMemory> shared_mem;
71 70
diff --git a/src/core/hle/service/mii/manager.cpp b/src/core/hle/service/mii/manager.cpp
new file mode 100644
index 000000000..4730070cb
--- /dev/null
+++ b/src/core/hle/service/mii/manager.cpp
@@ -0,0 +1,484 @@
1// Copyright 2020 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <cstring>
6#include <random>
7
8#include "common/assert.h"
9#include "common/file_util.h"
10#include "common/logging/log.h"
11#include "common/string_util.h"
12
13#include "core/hle/service/acc/profile_manager.h"
14#include "core/hle/service/mii/manager.h"
15#include "core/hle/service/mii/raw_data.h"
16#include "core/hle/service/mii/types.h"
17
18namespace Service::Mii {
19
20namespace {
21
22constexpr ResultCode ERROR_CANNOT_FIND_ENTRY{ErrorModule::Mii, 4};
23
24constexpr std::size_t DefaultMiiCount{sizeof(RawData::DefaultMii) / sizeof(DefaultMii)};
25
26constexpr MiiStoreData::Name DefaultMiiName{u'y', u'u', u'z', u'u'};
27constexpr std::array<u8, 8> HairColorLookup{8, 1, 2, 3, 4, 5, 6, 7};
28constexpr std::array<u8, 6> EyeColorLookup{8, 9, 10, 11, 12, 13};
29constexpr std::array<u8, 5> MouthColorLookup{19, 20, 21, 22, 23};
30constexpr std::array<u8, 7> GlassesColorLookup{8, 14, 15, 16, 17, 18, 0};
31constexpr std::array<u8, 62> EyeRotateLookup{
32 {0x03, 0x04, 0x04, 0x04, 0x03, 0x04, 0x04, 0x04, 0x03, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x04,
33 0x04, 0x04, 0x03, 0x03, 0x04, 0x03, 0x04, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x03, 0x04, 0x04,
34 0x04, 0x03, 0x03, 0x03, 0x04, 0x04, 0x03, 0x03, 0x03, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03,
35 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x03, 0x04, 0x04, 0x03, 0x04, 0x04}};
36constexpr std::array<u8, 24> EyebrowRotateLookup{{0x06, 0x06, 0x05, 0x07, 0x06, 0x07, 0x06, 0x07,
37 0x04, 0x07, 0x06, 0x08, 0x05, 0x05, 0x06, 0x06,
38 0x07, 0x07, 0x06, 0x06, 0x05, 0x06, 0x07, 0x05}};
39
40template <typename T, std::size_t SourceArraySize, std::size_t DestArraySize>
41std::array<T, DestArraySize> ResizeArray(const std::array<T, SourceArraySize>& in) {
42 std::array<T, DestArraySize> out{};
43 std::memcpy(out.data(), in.data(), sizeof(T) * std::min(SourceArraySize, DestArraySize));
44 return out;
45}
46
47MiiInfo ConvertStoreDataToInfo(const MiiStoreData& data) {
48 MiiStoreBitFields bf;
49 std::memcpy(&bf, data.data.data.data(), sizeof(MiiStoreBitFields));
50
51 return {
52 .uuid = data.data.uuid,
53 .name = ResizeArray<char16_t, 10, 11>(data.data.name),
54 .font_region = static_cast<u8>(bf.font_region.Value()),
55 .favorite_color = static_cast<u8>(bf.favorite_color.Value()),
56 .gender = static_cast<u8>(bf.gender.Value()),
57 .height = static_cast<u8>(bf.height.Value()),
58 .build = static_cast<u8>(bf.build.Value()),
59 .type = static_cast<u8>(bf.type.Value()),
60 .region_move = static_cast<u8>(bf.region_move.Value()),
61 .faceline_type = static_cast<u8>(bf.faceline_type.Value()),
62 .faceline_color = static_cast<u8>(bf.faceline_color.Value()),
63 .faceline_wrinkle = static_cast<u8>(bf.faceline_wrinkle.Value()),
64 .faceline_make = static_cast<u8>(bf.faceline_makeup.Value()),
65 .hair_type = static_cast<u8>(bf.hair_type.Value()),
66 .hair_color = static_cast<u8>(bf.hair_color.Value()),
67 .hair_flip = static_cast<u8>(bf.hair_flip.Value()),
68 .eye_type = static_cast<u8>(bf.eye_type.Value()),
69 .eye_color = static_cast<u8>(bf.eye_color.Value()),
70 .eye_scale = static_cast<u8>(bf.eye_scale.Value()),
71 .eye_aspect = static_cast<u8>(bf.eye_aspect.Value()),
72 .eye_rotate = static_cast<u8>(bf.eye_rotate.Value()),
73 .eye_x = static_cast<u8>(bf.eye_x.Value()),
74 .eye_y = static_cast<u8>(bf.eye_y.Value()),
75 .eyebrow_type = static_cast<u8>(bf.eyebrow_type.Value()),
76 .eyebrow_color = static_cast<u8>(bf.eyebrow_color.Value()),
77 .eyebrow_scale = static_cast<u8>(bf.eyebrow_scale.Value()),
78 .eyebrow_aspect = static_cast<u8>(bf.eyebrow_aspect.Value()),
79 .eyebrow_rotate = static_cast<u8>(bf.eyebrow_rotate.Value()),
80 .eyebrow_x = static_cast<u8>(bf.eyebrow_x.Value()),
81 .eyebrow_y = static_cast<u8>(bf.eyebrow_y.Value() + 3),
82 .nose_type = static_cast<u8>(bf.nose_type.Value()),
83 .nose_scale = static_cast<u8>(bf.nose_scale.Value()),
84 .nose_y = static_cast<u8>(bf.nose_y.Value()),
85 .mouth_type = static_cast<u8>(bf.mouth_type.Value()),
86 .mouth_color = static_cast<u8>(bf.mouth_color.Value()),
87 .mouth_scale = static_cast<u8>(bf.mouth_scale.Value()),
88 .mouth_aspect = static_cast<u8>(bf.mouth_aspect.Value()),
89 .mouth_y = static_cast<u8>(bf.mouth_y.Value()),
90 .beard_color = static_cast<u8>(bf.beard_color.Value()),
91 .beard_type = static_cast<u8>(bf.beard_type.Value()),
92 .mustache_type = static_cast<u8>(bf.mustache_type.Value()),
93 .mustache_scale = static_cast<u8>(bf.mustache_scale.Value()),
94 .mustache_y = static_cast<u8>(bf.mustache_y.Value()),
95 .glasses_type = static_cast<u8>(bf.glasses_type.Value()),
96 .glasses_color = static_cast<u8>(bf.glasses_color.Value()),
97 .glasses_scale = static_cast<u8>(bf.glasses_scale.Value()),
98 .glasses_y = static_cast<u8>(bf.glasses_y.Value()),
99 .mole_type = static_cast<u8>(bf.mole_type.Value()),
100 .mole_scale = static_cast<u8>(bf.mole_scale.Value()),
101 .mole_x = static_cast<u8>(bf.mole_x.Value()),
102 .mole_y = static_cast<u8>(bf.mole_y.Value()),
103 };
104}
105
106u16 GenerateCrc16(const void* data, std::size_t size) {
107 s32 crc{};
108 for (std::size_t i = 0; i < size; i++) {
109 crc ^= static_cast<const u8*>(data)[i] << 8;
110 for (std::size_t j = 0; j < 8; j++) {
111 crc <<= 1;
112 if ((crc & 0x10000) != 0) {
113 crc = (crc ^ 0x1021) & 0xFFFF;
114 }
115 }
116 }
117 return Common::swap16(static_cast<u16>(crc));
118}
119
120Common::UUID GenerateValidUUID() {
121 auto uuid{Common::UUID::Generate()};
122
123 // Bit 7 must be set, and bit 6 unset for the UUID to be valid
124 uuid.uuid[1] &= 0xFFFFFFFFFFFFFF3FULL;
125 uuid.uuid[1] |= 0x0000000000000080ULL;
126
127 return uuid;
128}
129
130template <typename T>
131T GetRandomValue(T min, T max) {
132 std::random_device device;
133 std::mt19937 gen(device());
134 std::uniform_int_distribution<u64> distribution(0, static_cast<u64>(max));
135 return static_cast<T>(distribution(gen));
136}
137
138template <typename T>
139T GetRandomValue(T max) {
140 return GetRandomValue<T>({}, max);
141}
142
143template <typename T>
144T GetArrayValue(const u8* data, std::size_t index) {
145 T result{};
146 std::memcpy(&result, &data[index * sizeof(T)], sizeof(T));
147 return result;
148}
149
150MiiStoreData BuildRandomStoreData(Age age, Gender gender, Race race, const Common::UUID& user_id) {
151 MiiStoreBitFields bf{};
152
153 if (gender == Gender::All) {
154 gender = GetRandomValue<Gender>(Gender::Maximum);
155 }
156
157 bf.gender.Assign(gender);
158 bf.favorite_color.Assign(GetRandomValue<u8>(11));
159 bf.region_move.Assign(0);
160 bf.font_region.Assign(FontRegion::Standard);
161 bf.type.Assign(0);
162 bf.height.Assign(64);
163 bf.build.Assign(64);
164
165 if (age == Age::All) {
166 const auto temp{GetRandomValue<int>(10)};
167 if (temp >= 8) {
168 age = Age::Old;
169 } else if (temp >= 4) {
170 age = Age::Normal;
171 } else {
172 age = Age::Young;
173 }
174 }
175
176 if (race == Race::All) {
177 const auto temp{GetRandomValue<int>(10)};
178 if (temp >= 8) {
179 race = Race::Black;
180 } else if (temp >= 4) {
181 race = Race::White;
182 } else {
183 race = Race::Asian;
184 }
185 }
186
187 u32 axis_y{};
188 if (gender == Gender::Female && age == Age::Young) {
189 axis_y = GetRandomValue<u32>(3);
190 }
191
192 const std::size_t index{3 * static_cast<std::size_t>(age) +
193 9 * static_cast<std::size_t>(gender) + static_cast<std::size_t>(race)};
194
195 const auto faceline_type_info{
196 GetArrayValue<RandomMiiData4>(&RawData::RandomMiiFaceline[0], index)};
197 const auto faceline_color_info{GetArrayValue<RandomMiiData3>(
198 RawData::RandomMiiFacelineColor.data(),
199 3 * static_cast<std::size_t>(gender) + static_cast<std::size_t>(race))};
200 const auto faceline_wrinkle_info{
201 GetArrayValue<RandomMiiData4>(RawData::RandomMiiFacelineWrinkle.data(), index)};
202 const auto faceline_makeup_info{
203 GetArrayValue<RandomMiiData4>(RawData::RandomMiiFacelineMakeup.data(), index)};
204 const auto hair_type_info{
205 GetArrayValue<RandomMiiData4>(RawData::RandomMiiHairType.data(), index)};
206 const auto hair_color_info{GetArrayValue<RandomMiiData3>(RawData::RandomMiiHairColor.data(),
207 3 * static_cast<std::size_t>(race) +
208 static_cast<std::size_t>(age))};
209 const auto eye_type_info{
210 GetArrayValue<RandomMiiData4>(RawData::RandomMiiEyeType.data(), index)};
211 const auto eye_color_info{GetArrayValue<RandomMiiData2>(RawData::RandomMiiEyeColor.data(),
212 static_cast<std::size_t>(race))};
213 const auto eyebrow_type_info{
214 GetArrayValue<RandomMiiData4>(RawData::RandomMiiEyebrowType.data(), index)};
215 const auto nose_type_info{
216 GetArrayValue<RandomMiiData4>(RawData::RandomMiiNoseType.data(), index)};
217 const auto mouth_type_info{
218 GetArrayValue<RandomMiiData4>(RawData::RandomMiiMouthType.data(), index)};
219 const auto glasses_type_info{GetArrayValue<RandomMiiData2>(RawData::RandomMiiGlassType.data(),
220 static_cast<std::size_t>(age))};
221
222 bf.faceline_type.Assign(
223 faceline_type_info.values[GetRandomValue<std::size_t>(faceline_type_info.values_count)]);
224 bf.faceline_color.Assign(
225 faceline_color_info.values[GetRandomValue<std::size_t>(faceline_color_info.values_count)]);
226 bf.faceline_wrinkle.Assign(
227 faceline_wrinkle_info
228 .values[GetRandomValue<std::size_t>(faceline_wrinkle_info.values_count)]);
229 bf.faceline_makeup.Assign(
230 faceline_makeup_info
231 .values[GetRandomValue<std::size_t>(faceline_makeup_info.values_count)]);
232
233 bf.hair_type.Assign(
234 hair_type_info.values[GetRandomValue<std::size_t>(hair_type_info.values_count)]);
235 bf.hair_color.Assign(
236 HairColorLookup[hair_color_info
237 .values[GetRandomValue<std::size_t>(hair_color_info.values_count)]]);
238 bf.hair_flip.Assign(GetRandomValue<HairFlip>(HairFlip::Maximum));
239
240 bf.eye_type.Assign(
241 eye_type_info.values[GetRandomValue<std::size_t>(eye_type_info.values_count)]);
242
243 const auto eye_rotate_1{gender != Gender::Male ? 4 : 2};
244 const auto eye_rotate_2{gender != Gender::Male ? 3 : 4};
245 const auto eye_rotate_offset{32 - EyeRotateLookup[eye_rotate_1] + eye_rotate_2};
246 const auto eye_rotate{32 - EyeRotateLookup[bf.eye_type]};
247
248 bf.eye_color.Assign(
249 EyeColorLookup[eye_color_info
250 .values[GetRandomValue<std::size_t>(eye_color_info.values_count)]]);
251 bf.eye_scale.Assign(4);
252 bf.eye_aspect.Assign(3);
253 bf.eye_rotate.Assign(eye_rotate_offset - eye_rotate);
254 bf.eye_x.Assign(2);
255 bf.eye_y.Assign(axis_y + 12);
256
257 bf.eyebrow_type.Assign(
258 eyebrow_type_info.values[GetRandomValue<std::size_t>(eyebrow_type_info.values_count)]);
259
260 const auto eyebrow_rotate_1{race == Race::Asian ? 6 : 0};
261 const auto eyebrow_y{race == Race::Asian ? 9 : 10};
262 const auto eyebrow_rotate_offset{32 - EyebrowRotateLookup[eyebrow_rotate_1] + 6};
263 const auto eyebrow_rotate{
264 32 - EyebrowRotateLookup[static_cast<std::size_t>(bf.eyebrow_type.Value())]};
265
266 bf.eyebrow_color.Assign(bf.hair_color);
267 bf.eyebrow_scale.Assign(4);
268 bf.eyebrow_aspect.Assign(3);
269 bf.eyebrow_rotate.Assign(eyebrow_rotate_offset - eyebrow_rotate);
270 bf.eyebrow_x.Assign(2);
271 bf.eyebrow_y.Assign(axis_y + eyebrow_y);
272
273 const auto nose_scale{gender == Gender::Female ? 3 : 4};
274
275 bf.nose_type.Assign(
276 nose_type_info.values[GetRandomValue<std::size_t>(nose_type_info.values_count)]);
277 bf.nose_scale.Assign(nose_scale);
278 bf.nose_y.Assign(axis_y + 9);
279
280 const auto mouth_color{gender == Gender::Female ? GetRandomValue<int>(4) : 0};
281
282 bf.mouth_type.Assign(
283 mouth_type_info.values[GetRandomValue<std::size_t>(mouth_type_info.values_count)]);
284 bf.mouth_color.Assign(MouthColorLookup[mouth_color]);
285 bf.mouth_scale.Assign(4);
286 bf.mouth_aspect.Assign(3);
287 bf.mouth_y.Assign(axis_y + 13);
288
289 bf.beard_color.Assign(bf.hair_color);
290 bf.mustache_scale.Assign(4);
291
292 if (gender == Gender::Male && age != Age::Young && GetRandomValue<int>(10) < 2) {
293 const auto mustache_and_beard_flag{
294 GetRandomValue<BeardAndMustacheFlag>(BeardAndMustacheFlag::All)};
295
296 auto beard_type{BeardType::None};
297 auto mustache_type{MustacheType::None};
298
299 if ((mustache_and_beard_flag & BeardAndMustacheFlag::Beard) ==
300 BeardAndMustacheFlag::Beard) {
301 beard_type = GetRandomValue<BeardType>(BeardType::Beard1, BeardType::Beard5);
302 }
303
304 if ((mustache_and_beard_flag & BeardAndMustacheFlag::Mustache) ==
305 BeardAndMustacheFlag::Mustache) {
306 mustache_type =
307 GetRandomValue<MustacheType>(MustacheType::Mustache1, MustacheType::Mustache5);
308 }
309
310 bf.mustache_type.Assign(mustache_type);
311 bf.beard_type.Assign(beard_type);
312 bf.mustache_y.Assign(10);
313 } else {
314 bf.mustache_type.Assign(MustacheType::None);
315 bf.beard_type.Assign(BeardType::None);
316 bf.mustache_y.Assign(axis_y + 10);
317 }
318
319 const auto glasses_type_start{GetRandomValue<std::size_t>(100)};
320 u8 glasses_type{};
321 while (glasses_type_start < glasses_type_info.values[glasses_type]) {
322 if (++glasses_type >= glasses_type_info.values_count) {
323 UNREACHABLE();
324 break;
325 }
326 }
327
328 bf.glasses_type.Assign(glasses_type);
329 bf.glasses_color.Assign(GlassesColorLookup[0]);
330 bf.glasses_scale.Assign(4);
331 bf.glasses_y.Assign(axis_y + 10);
332
333 bf.mole_type.Assign(0);
334 bf.mole_scale.Assign(4);
335 bf.mole_x.Assign(2);
336 bf.mole_y.Assign(20);
337
338 return {DefaultMiiName, bf, user_id};
339}
340
341MiiStoreData BuildDefaultStoreData(const DefaultMii& info, const Common::UUID& user_id) {
342 MiiStoreBitFields bf{};
343
344 bf.font_region.Assign(info.font_region);
345 bf.favorite_color.Assign(info.favorite_color);
346 bf.gender.Assign(info.gender);
347 bf.height.Assign(info.height);
348 bf.build.Assign(info.weight);
349 bf.type.Assign(info.type);
350 bf.region_move.Assign(info.region);
351 bf.faceline_type.Assign(info.face_type);
352 bf.faceline_color.Assign(info.face_color);
353 bf.faceline_wrinkle.Assign(info.face_wrinkle);
354 bf.faceline_makeup.Assign(info.face_makeup);
355 bf.hair_type.Assign(info.hair_type);
356 bf.hair_color.Assign(HairColorLookup[info.hair_color]);
357 bf.hair_flip.Assign(static_cast<HairFlip>(info.hair_flip));
358 bf.eye_type.Assign(info.eye_type);
359 bf.eye_color.Assign(EyeColorLookup[info.eye_color]);
360 bf.eye_scale.Assign(info.eye_scale);
361 bf.eye_aspect.Assign(info.eye_aspect);
362 bf.eye_rotate.Assign(info.eye_rotate);
363 bf.eye_x.Assign(info.eye_x);
364 bf.eye_y.Assign(info.eye_y);
365 bf.eyebrow_type.Assign(info.eyebrow_type);
366 bf.eyebrow_color.Assign(HairColorLookup[info.eyebrow_color]);
367 bf.eyebrow_scale.Assign(info.eyebrow_scale);
368 bf.eyebrow_aspect.Assign(info.eyebrow_aspect);
369 bf.eyebrow_rotate.Assign(info.eyebrow_rotate);
370 bf.eyebrow_x.Assign(info.eyebrow_x);
371 bf.eyebrow_y.Assign(info.eyebrow_y - 3);
372 bf.nose_type.Assign(info.nose_type);
373 bf.nose_scale.Assign(info.nose_scale);
374 bf.nose_y.Assign(info.nose_y);
375 bf.mouth_type.Assign(info.mouth_type);
376 bf.mouth_color.Assign(MouthColorLookup[info.mouth_color]);
377 bf.mouth_scale.Assign(info.mouth_scale);
378 bf.mouth_aspect.Assign(info.mouth_aspect);
379 bf.mouth_y.Assign(info.mouth_y);
380 bf.beard_color.Assign(HairColorLookup[info.beard_color]);
381 bf.beard_type.Assign(static_cast<BeardType>(info.beard_type));
382 bf.mustache_type.Assign(static_cast<MustacheType>(info.mustache_type));
383 bf.mustache_scale.Assign(info.mustache_scale);
384 bf.mustache_y.Assign(info.mustache_y);
385 bf.glasses_type.Assign(info.glasses_type);
386 bf.glasses_color.Assign(GlassesColorLookup[info.glasses_color]);
387 bf.glasses_scale.Assign(info.glasses_scale);
388 bf.glasses_y.Assign(info.glasses_y);
389 bf.mole_type.Assign(info.mole_type);
390 bf.mole_scale.Assign(info.mole_scale);
391 bf.mole_x.Assign(info.mole_x);
392 bf.mole_y.Assign(info.mole_y);
393
394 return {DefaultMiiName, bf, user_id};
395}
396
397} // namespace
398
399MiiStoreData::MiiStoreData() = default;
400
401MiiStoreData::MiiStoreData(const MiiStoreData::Name& name, const MiiStoreBitFields& bit_fields,
402 const Common::UUID& user_id) {
403 data.name = name;
404 data.uuid = GenerateValidUUID();
405
406 std::memcpy(data.data.data(), &bit_fields, sizeof(MiiStoreBitFields));
407 data_crc = GenerateCrc16(data.data.data(), sizeof(data));
408 device_crc = GenerateCrc16(&user_id, sizeof(Common::UUID));
409}
410
411MiiManager::MiiManager() : user_id{Service::Account::ProfileManager().GetLastOpenedUser()} {}
412
413bool MiiManager::CheckAndResetUpdateCounter(SourceFlag source_flag, u64& current_update_counter) {
414 if ((source_flag & SourceFlag::Database) == SourceFlag::None) {
415 return false;
416 }
417
418 const bool result{current_update_counter != update_counter};
419
420 current_update_counter = update_counter;
421
422 return result;
423}
424
425bool MiiManager::IsFullDatabase() const {
426 // TODO(bunnei): We don't implement the Mii database, so it cannot be full
427 return false;
428}
429
430u32 MiiManager::GetCount(SourceFlag source_flag) const {
431 u32 count{};
432 if ((source_flag & SourceFlag::Database) != SourceFlag::None) {
433 // TODO(bunnei): We don't implement the Mii database, but when we do, update this
434 count += 0;
435 }
436 if ((source_flag & SourceFlag::Default) != SourceFlag::None) {
437 count += DefaultMiiCount;
438 }
439 return count;
440}
441
442ResultVal<MiiInfo> MiiManager::UpdateLatest([[maybe_unused]] const MiiInfo& info,
443 SourceFlag source_flag) {
444 if ((source_flag & SourceFlag::Database) == SourceFlag::None) {
445 return ERROR_CANNOT_FIND_ENTRY;
446 }
447
448 // TODO(bunnei): We don't implement the Mii database, so we can't have an entry
449 return ERROR_CANNOT_FIND_ENTRY;
450}
451
452MiiInfo MiiManager::BuildRandom(Age age, Gender gender, Race race) {
453 return ConvertStoreDataToInfo(BuildRandomStoreData(age, gender, race, user_id));
454}
455
456MiiInfo MiiManager::BuildDefault(std::size_t index) {
457 return ConvertStoreDataToInfo(BuildDefaultStoreData(
458 GetArrayValue<DefaultMii>(RawData::DefaultMii.data(), index), user_id));
459}
460
461ResultVal<std::vector<MiiInfoElement>> MiiManager::GetDefault(SourceFlag source_flag) {
462 std::vector<MiiInfoElement> result;
463
464 if ((source_flag & SourceFlag::Default) == SourceFlag::None) {
465 return MakeResult(std::move(result));
466 }
467
468 for (std::size_t index = 0; index < DefaultMiiCount; index++) {
469 result.emplace_back(BuildDefault(index), Source::Default);
470 }
471
472 return MakeResult(std::move(result));
473}
474
475ResultCode MiiManager::GetIndex([[maybe_unused]] const MiiInfo& info, u32& index) {
476 constexpr u32 INVALID_INDEX{0xFFFFFFFF};
477
478 index = INVALID_INDEX;
479
480 // TODO(bunnei): We don't implement the Mii database, so we can't have an index
481 return ERROR_CANNOT_FIND_ENTRY;
482}
483
484} // namespace Service::Mii
diff --git a/src/core/hle/service/mii/manager.h b/src/core/hle/service/mii/manager.h
new file mode 100644
index 000000000..927451dea
--- /dev/null
+++ b/src/core/hle/service/mii/manager.h
@@ -0,0 +1,331 @@
1// Copyright 2020 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "common/bit_field.h"
8#include "common/common_funcs.h"
9#include "common/uuid.h"
10#include "core/hle/result.h"
11#include "core/hle/service/mii/types.h"
12
13namespace Service::Mii {
14
15enum class Source : u32 {
16 Database = 0,
17 Default = 1,
18 Account = 2,
19 Friend = 3,
20};
21
22enum class SourceFlag : u32 {
23 None = 0,
24 Database = 1 << 0,
25 Default = 1 << 1,
26};
27DECLARE_ENUM_FLAG_OPERATORS(SourceFlag);
28
29struct MiiInfo {
30 Common::UUID uuid{Common::INVALID_UUID};
31 std::array<char16_t, 11> name{};
32 u8 font_region{};
33 u8 favorite_color{};
34 u8 gender{};
35 u8 height{};
36 u8 build{};
37 u8 type{};
38 u8 region_move{};
39 u8 faceline_type{};
40 u8 faceline_color{};
41 u8 faceline_wrinkle{};
42 u8 faceline_make{};
43 u8 hair_type{};
44 u8 hair_color{};
45 u8 hair_flip{};
46 u8 eye_type{};
47 u8 eye_color{};
48 u8 eye_scale{};
49 u8 eye_aspect{};
50 u8 eye_rotate{};
51 u8 eye_x{};
52 u8 eye_y{};
53 u8 eyebrow_type{};
54 u8 eyebrow_color{};
55 u8 eyebrow_scale{};
56 u8 eyebrow_aspect{};
57 u8 eyebrow_rotate{};
58 u8 eyebrow_x{};
59 u8 eyebrow_y{};
60 u8 nose_type{};
61 u8 nose_scale{};
62 u8 nose_y{};
63 u8 mouth_type{};
64 u8 mouth_color{};
65 u8 mouth_scale{};
66 u8 mouth_aspect{};
67 u8 mouth_y{};
68 u8 beard_color{};
69 u8 beard_type{};
70 u8 mustache_type{};
71 u8 mustache_scale{};
72 u8 mustache_y{};
73 u8 glasses_type{};
74 u8 glasses_color{};
75 u8 glasses_scale{};
76 u8 glasses_y{};
77 u8 mole_type{};
78 u8 mole_scale{};
79 u8 mole_x{};
80 u8 mole_y{};
81 INSERT_PADDING_BYTES(1);
82
83 std::u16string Name() const;
84};
85static_assert(sizeof(MiiInfo) == 0x58, "MiiInfo has incorrect size.");
86static_assert(std::has_unique_object_representations_v<MiiInfo>,
87 "All bits of MiiInfo must contribute to its value.");
88
89#pragma pack(push, 4)
90
91struct MiiInfoElement {
92 MiiInfoElement(const MiiInfo& info, Source source) : info{info}, source{source} {}
93
94 MiiInfo info{};
95 Source source{};
96};
97static_assert(sizeof(MiiInfoElement) == 0x5c, "MiiInfoElement has incorrect size.");
98
99struct MiiStoreBitFields {
100 union {
101 u32 word_0{};
102
103 BitField<0, 8, u32> hair_type;
104 BitField<8, 7, u32> height;
105 BitField<15, 1, u32> mole_type;
106 BitField<16, 7, u32> build;
107 BitField<23, 1, HairFlip> hair_flip;
108 BitField<24, 7, u32> hair_color;
109 BitField<31, 1, u32> type;
110 };
111
112 union {
113 u32 word_1{};
114
115 BitField<0, 7, u32> eye_color;
116 BitField<7, 1, Gender> gender;
117 BitField<8, 7, u32> eyebrow_color;
118 BitField<16, 7, u32> mouth_color;
119 BitField<24, 7, u32> beard_color;
120 };
121
122 union {
123 u32 word_2{};
124
125 BitField<0, 7, u32> glasses_color;
126 BitField<8, 6, u32> eye_type;
127 BitField<14, 2, u32> region_move;
128 BitField<16, 6, u32> mouth_type;
129 BitField<22, 2, FontRegion> font_region;
130 BitField<24, 5, u32> eye_y;
131 BitField<29, 3, u32> glasses_scale;
132 };
133
134 union {
135 u32 word_3{};
136
137 BitField<0, 5, u32> eyebrow_type;
138 BitField<5, 3, MustacheType> mustache_type;
139 BitField<8, 5, u32> nose_type;
140 BitField<13, 3, BeardType> beard_type;
141 BitField<16, 5, u32> nose_y;
142 BitField<21, 3, u32> mouth_aspect;
143 BitField<24, 5, u32> mouth_y;
144 BitField<29, 3, u32> eyebrow_aspect;
145 };
146
147 union {
148 u32 word_4{};
149
150 BitField<0, 5, u32> mustache_y;
151 BitField<5, 3, u32> eye_rotate;
152 BitField<8, 5, u32> glasses_y;
153 BitField<13, 3, u32> eye_aspect;
154 BitField<16, 5, u32> mole_x;
155 BitField<21, 3, u32> eye_scale;
156 BitField<24, 5, u32> mole_y;
157 };
158
159 union {
160 u32 word_5{};
161
162 BitField<0, 5, u32> glasses_type;
163 BitField<8, 4, u32> favorite_color;
164 BitField<12, 4, u32> faceline_type;
165 BitField<16, 4, u32> faceline_color;
166 BitField<20, 4, u32> faceline_wrinkle;
167 BitField<24, 4, u32> faceline_makeup;
168 BitField<28, 4, u32> eye_x;
169 };
170
171 union {
172 u32 word_6{};
173
174 BitField<0, 4, u32> eyebrow_scale;
175 BitField<4, 4, u32> eyebrow_rotate;
176 BitField<8, 4, u32> eyebrow_x;
177 BitField<12, 4, u32> eyebrow_y;
178 BitField<16, 4, u32> nose_scale;
179 BitField<20, 4, u32> mouth_scale;
180 BitField<24, 4, u32> mustache_scale;
181 BitField<28, 4, u32> mole_scale;
182 };
183};
184static_assert(sizeof(MiiStoreBitFields) == 0x1c, "MiiStoreBitFields has incorrect size.");
185static_assert(std::is_trivially_copyable_v<MiiStoreBitFields>,
186 "MiiStoreBitFields is not trivially copyable.");
187
188struct MiiStoreData {
189 using Name = std::array<char16_t, 10>;
190
191 MiiStoreData();
192 MiiStoreData(const Name& name, const MiiStoreBitFields& bit_fields,
193 const Common::UUID& user_id);
194
195 // This corresponds to the above structure MiiStoreBitFields. I did it like this because the
196 // BitField<> type makes this (and any thing that contains it) not trivially copyable, which is
197 // not suitable for our uses.
198 struct {
199 std::array<u8, 0x1C> data{};
200 static_assert(sizeof(MiiStoreBitFields) == sizeof(data), "data field has incorrect size.");
201
202 Name name{};
203 Common::UUID uuid{Common::INVALID_UUID};
204 } data;
205
206 u16 data_crc{};
207 u16 device_crc{};
208};
209static_assert(sizeof(MiiStoreData) == 0x44, "MiiStoreData has incorrect size.");
210
211struct MiiStoreDataElement {
212 MiiStoreData data{};
213 Source source{};
214};
215static_assert(sizeof(MiiStoreDataElement) == 0x48, "MiiStoreDataElement has incorrect size.");
216
217struct MiiDatabase {
218 u32 magic{}; // 'NFDB'
219 std::array<MiiStoreData, 0x64> miis{};
220 INSERT_PADDING_BYTES(1);
221 u8 count{};
222 u16 crc{};
223};
224static_assert(sizeof(MiiDatabase) == 0x1A98, "MiiDatabase has incorrect size.");
225
226struct RandomMiiValues {
227 std::array<u8, 0xbc> values{};
228};
229static_assert(sizeof(RandomMiiValues) == 0xbc, "RandomMiiValues has incorrect size.");
230
231struct RandomMiiData4 {
232 Gender gender{};
233 Age age{};
234 Race race{};
235 u32 values_count{};
236 std::array<u8, 0xbc> values{};
237};
238static_assert(sizeof(RandomMiiData4) == 0xcc, "RandomMiiData4 has incorrect size.");
239
240struct RandomMiiData3 {
241 u32 arg_1;
242 u32 arg_2;
243 u32 values_count;
244 std::array<u8, 0xbc> values{};
245};
246static_assert(sizeof(RandomMiiData3) == 0xc8, "RandomMiiData3 has incorrect size.");
247
248struct RandomMiiData2 {
249 u32 arg_1;
250 u32 values_count;
251 std::array<u8, 0xbc> values{};
252};
253static_assert(sizeof(RandomMiiData2) == 0xc4, "RandomMiiData2 has incorrect size.");
254
255struct DefaultMii {
256 u32 face_type{};
257 u32 face_color{};
258 u32 face_wrinkle{};
259 u32 face_makeup{};
260 u32 hair_type{};
261 u32 hair_color{};
262 u32 hair_flip{};
263 u32 eye_type{};
264 u32 eye_color{};
265 u32 eye_scale{};
266 u32 eye_aspect{};
267 u32 eye_rotate{};
268 u32 eye_x{};
269 u32 eye_y{};
270 u32 eyebrow_type{};
271 u32 eyebrow_color{};
272 u32 eyebrow_scale{};
273 u32 eyebrow_aspect{};
274 u32 eyebrow_rotate{};
275 u32 eyebrow_x{};
276 u32 eyebrow_y{};
277 u32 nose_type{};
278 u32 nose_scale{};
279 u32 nose_y{};
280 u32 mouth_type{};
281 u32 mouth_color{};
282 u32 mouth_scale{};
283 u32 mouth_aspect{};
284 u32 mouth_y{};
285 u32 mustache_type{};
286 u32 beard_type{};
287 u32 beard_color{};
288 u32 mustache_scale{};
289 u32 mustache_y{};
290 u32 glasses_type{};
291 u32 glasses_color{};
292 u32 glasses_scale{};
293 u32 glasses_y{};
294 u32 mole_type{};
295 u32 mole_scale{};
296 u32 mole_x{};
297 u32 mole_y{};
298 u32 height{};
299 u32 weight{};
300 Gender gender{};
301 u32 favorite_color{};
302 u32 region{};
303 FontRegion font_region{};
304 u32 type{};
305 INSERT_PADDING_WORDS(5);
306};
307static_assert(sizeof(DefaultMii) == 0xd8, "MiiStoreData has incorrect size.");
308
309#pragma pack(pop)
310
311// The Mii manager is responsible for loading and storing the Miis to the database in NAND along
312// with providing an easy interface for HLE emulation of the mii service.
313class MiiManager {
314public:
315 MiiManager();
316
317 bool CheckAndResetUpdateCounter(SourceFlag source_flag, u64& current_update_counter);
318 bool IsFullDatabase() const;
319 u32 GetCount(SourceFlag source_flag) const;
320 ResultVal<MiiInfo> UpdateLatest(const MiiInfo& info, SourceFlag source_flag);
321 MiiInfo BuildRandom(Age age, Gender gender, Race race);
322 MiiInfo BuildDefault(std::size_t index);
323 ResultVal<std::vector<MiiInfoElement>> GetDefault(SourceFlag source_flag);
324 ResultCode GetIndex(const MiiInfo& info, u32& index);
325
326private:
327 const Common::UUID user_id;
328 u64 update_counter{};
329};
330
331}; // namespace Service::Mii
diff --git a/src/core/hle/service/mii/mii.cpp b/src/core/hle/service/mii/mii.cpp
index a128edb43..b81bf6277 100644
--- a/src/core/hle/service/mii/mii.cpp
+++ b/src/core/hle/service/mii/mii.cpp
@@ -4,22 +4,17 @@
4 4
5#include <memory> 5#include <memory>
6 6
7#include <fmt/ostream.h>
8
9#include "common/logging/log.h" 7#include "common/logging/log.h"
10#include "common/string_util.h"
11#include "core/hle/ipc_helpers.h" 8#include "core/hle/ipc_helpers.h"
12#include "core/hle/kernel/hle_ipc.h" 9#include "core/hle/kernel/hle_ipc.h"
10#include "core/hle/service/mii/manager.h"
13#include "core/hle/service/mii/mii.h" 11#include "core/hle/service/mii/mii.h"
14#include "core/hle/service/mii/mii_manager.h"
15#include "core/hle/service/service.h" 12#include "core/hle/service/service.h"
16#include "core/hle/service/sm/sm.h" 13#include "core/hle/service/sm/sm.h"
17 14
18namespace Service::Mii { 15namespace Service::Mii {
19 16
20constexpr ResultCode ERROR_INVALID_ARGUMENT{ErrorModule::Mii, 1}; 17constexpr ResultCode ERROR_INVALID_ARGUMENT{ErrorModule::Mii, 1};
21constexpr ResultCode ERROR_CANNOT_FIND_ENTRY{ErrorModule::Mii, 4};
22constexpr ResultCode ERROR_NOT_IN_TEST_MODE{ErrorModule::Mii, 99};
23 18
24class IDatabaseService final : public ServiceFramework<IDatabaseService> { 19class IDatabaseService final : public ServiceFramework<IDatabaseService> {
25public: 20public:
@@ -31,19 +26,19 @@ public:
31 {2, &IDatabaseService::GetCount, "GetCount"}, 26 {2, &IDatabaseService::GetCount, "GetCount"},
32 {3, &IDatabaseService::Get, "Get"}, 27 {3, &IDatabaseService::Get, "Get"},
33 {4, &IDatabaseService::Get1, "Get1"}, 28 {4, &IDatabaseService::Get1, "Get1"},
34 {5, nullptr, "UpdateLatest"}, 29 {5, &IDatabaseService::UpdateLatest, "UpdateLatest"},
35 {6, &IDatabaseService::BuildRandom, "BuildRandom"}, 30 {6, &IDatabaseService::BuildRandom, "BuildRandom"},
36 {7, &IDatabaseService::BuildDefault, "BuildDefault"}, 31 {7, &IDatabaseService::BuildDefault, "BuildDefault"},
37 {8, &IDatabaseService::Get2, "Get2"}, 32 {8, nullptr, "Get2"},
38 {9, &IDatabaseService::Get3, "Get3"}, 33 {9, nullptr, "Get3"},
39 {10, nullptr, "UpdateLatest1"}, 34 {10, nullptr, "UpdateLatest1"},
40 {11, &IDatabaseService::FindIndex, "FindIndex"}, 35 {11, nullptr, "FindIndex"},
41 {12, &IDatabaseService::Move, "Move"}, 36 {12, nullptr, "Move"},
42 {13, &IDatabaseService::AddOrReplace, "AddOrReplace"}, 37 {13, nullptr, "AddOrReplace"},
43 {14, &IDatabaseService::Delete, "Delete"}, 38 {14, nullptr, "Delete"},
44 {15, &IDatabaseService::DestroyFile, "DestroyFile"}, 39 {15, nullptr, "DestroyFile"},
45 {16, &IDatabaseService::DeleteFile, "DeleteFile"}, 40 {16, nullptr, "DeleteFile"},
46 {17, &IDatabaseService::Format, "Format"}, 41 {17, nullptr, "Format"},
47 {18, nullptr, "Import"}, 42 {18, nullptr, "Import"},
48 {19, nullptr, "Export"}, 43 {19, nullptr, "Export"},
49 {20, nullptr, "IsBrokenDatabaseWithClearFlag"}, 44 {20, nullptr, "IsBrokenDatabaseWithClearFlag"},
@@ -59,31 +54,26 @@ public:
59 } 54 }
60 55
61private: 56private:
62 template <typename OutType> 57 template <typename T>
63 std::vector<u8> SerializeArray(OutType (MiiManager::*getter)(u32) const, u32 offset, 58 std::vector<u8> SerializeArray(const std::vector<T>& values) {
64 u32 requested_size, u32& read_size) { 59 std::vector<u8> out(values.size() * sizeof(T));
65 read_size = std::min(requested_size, db.Size() - offset); 60 std::size_t offset{};
66 61 for (const auto& value : values) {
67 std::vector<u8> out(read_size * sizeof(OutType)); 62 std::memcpy(out.data() + offset, &value, sizeof(T));
68 63 offset += sizeof(T);
69 for (u32 i = 0; i < read_size; ++i) {
70 const auto obj = (db.*getter)(offset + i);
71 std::memcpy(out.data() + i * sizeof(OutType), &obj, sizeof(OutType));
72 } 64 }
73
74 return out; 65 return out;
75 } 66 }
76 67
77 void IsUpdated(Kernel::HLERequestContext& ctx) { 68 void IsUpdated(Kernel::HLERequestContext& ctx) {
78 IPC::RequestParser rp{ctx}; 69 IPC::RequestParser rp{ctx};
79 const auto source{rp.PopRaw<Source>()}; 70 const auto source_flag{rp.PopRaw<SourceFlag>()};
80 71
81 LOG_DEBUG(Service_Mii, "called with source={}", source); 72 LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag);
82 73
83 IPC::ResponseBuilder rb{ctx, 3}; 74 IPC::ResponseBuilder rb{ctx, 3};
84 rb.Push(RESULT_SUCCESS); 75 rb.Push(RESULT_SUCCESS);
85 rb.Push(db.CheckUpdatedFlag()); 76 rb.Push(manager.CheckAndResetUpdateCounter(source_flag, current_update_counter));
86 db.ResetUpdatedFlag();
87 } 77 }
88 78
89 void IsFullDatabase(Kernel::HLERequestContext& ctx) { 79 void IsFullDatabase(Kernel::HLERequestContext& ctx) {
@@ -91,264 +81,149 @@ private:
91 81
92 IPC::ResponseBuilder rb{ctx, 3}; 82 IPC::ResponseBuilder rb{ctx, 3};
93 rb.Push(RESULT_SUCCESS); 83 rb.Push(RESULT_SUCCESS);
94 rb.Push(db.Full()); 84 rb.Push(manager.IsFullDatabase());
95 } 85 }
96 86
97 void GetCount(Kernel::HLERequestContext& ctx) { 87 void GetCount(Kernel::HLERequestContext& ctx) {
98 IPC::RequestParser rp{ctx}; 88 IPC::RequestParser rp{ctx};
99 const auto source{rp.PopRaw<Source>()}; 89 const auto source_flag{rp.PopRaw<SourceFlag>()};
100 90
101 LOG_DEBUG(Service_Mii, "called with source={}", source); 91 LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag);
102 92
103 IPC::ResponseBuilder rb{ctx, 3}; 93 IPC::ResponseBuilder rb{ctx, 3};
104 rb.Push(RESULT_SUCCESS); 94 rb.Push(RESULT_SUCCESS);
105 rb.Push<u32>(db.Size()); 95 rb.Push<u32>(manager.GetCount(source_flag));
106 } 96 }
107 97
108 // Gets Miis from database at offset and index in format MiiInfoElement
109 void Get(Kernel::HLERequestContext& ctx) { 98 void Get(Kernel::HLERequestContext& ctx) {
110 IPC::RequestParser rp{ctx}; 99 IPC::RequestParser rp{ctx};
111 const auto size{rp.PopRaw<u32>()}; 100 const auto source_flag{rp.PopRaw<SourceFlag>()};
112 const auto source{rp.PopRaw<Source>()};
113
114 LOG_DEBUG(Service_Mii, "called with size={:08X}, offset={:08X}, source={}", size,
115 offsets[0], source);
116
117 u32 read_size{};
118 ctx.WriteBuffer(SerializeArray(&MiiManager::GetInfoElement, offsets[0], size, read_size));
119 offsets[0] += read_size;
120
121 IPC::ResponseBuilder rb{ctx, 3};
122 rb.Push(RESULT_SUCCESS);
123 rb.Push<u32>(read_size);
124 }
125 101
126 // Gets Miis from database at offset and index in format MiiInfo 102 LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag);
127 void Get1(Kernel::HLERequestContext& ctx) {
128 IPC::RequestParser rp{ctx};
129 const auto size{rp.PopRaw<u32>()};
130 const auto source{rp.PopRaw<Source>()};
131 103
132 LOG_DEBUG(Service_Mii, "called with size={:08X}, offset={:08X}, source={}", size, 104 const auto result{manager.GetDefault(source_flag)};
133 offsets[1], source); 105 if (result.Failed()) {
106 IPC::ResponseBuilder rb{ctx, 2};
107 rb.Push(result.Code());
108 return;
109 }
134 110
135 u32 read_size{}; 111 if (result->size() > 0) {
136 ctx.WriteBuffer(SerializeArray(&MiiManager::GetInfo, offsets[1], size, read_size)); 112 ctx.WriteBuffer(SerializeArray(*result));
137 offsets[1] += read_size; 113 }
138 114
139 IPC::ResponseBuilder rb{ctx, 3}; 115 IPC::ResponseBuilder rb{ctx, 3};
140 rb.Push(RESULT_SUCCESS); 116 rb.Push(RESULT_SUCCESS);
141 rb.Push<u32>(read_size); 117 rb.Push<u32>(static_cast<u32>(result->size()));
142 } 118 }
143 119
144 void BuildRandom(Kernel::HLERequestContext& ctx) { 120 void Get1(Kernel::HLERequestContext& ctx) {
145 IPC::RequestParser rp{ctx}; 121 IPC::RequestParser rp{ctx};
146 const auto [unknown1, unknown2, unknown3] = rp.PopRaw<RandomParameters>(); 122 const auto source_flag{rp.PopRaw<SourceFlag>()};
147 123
148 if (unknown1 > 3) { 124 LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag);
149 IPC::ResponseBuilder rb{ctx, 2};
150 rb.Push(ERROR_INVALID_ARGUMENT);
151 LOG_ERROR(Service_Mii, "Invalid unknown1 value: {}", unknown1);
152 return;
153 }
154 125
155 if (unknown2 > 2) { 126 const auto result{manager.GetDefault(source_flag)};
127 if (result.Failed()) {
156 IPC::ResponseBuilder rb{ctx, 2}; 128 IPC::ResponseBuilder rb{ctx, 2};
157 rb.Push(ERROR_INVALID_ARGUMENT); 129 rb.Push(result.Code());
158 LOG_ERROR(Service_Mii, "Invalid unknown2 value: {}", unknown2);
159 return; 130 return;
160 } 131 }
161 132
162 if (unknown3 > 3) { 133 std::vector<MiiInfo> values;
163 IPC::ResponseBuilder rb{ctx, 2}; 134 for (const auto& element : *result) {
164 rb.Push(ERROR_INVALID_ARGUMENT); 135 values.emplace_back(element.info);
165 LOG_ERROR(Service_Mii, "Invalid unknown3 value: {}", unknown3);
166 return;
167 } 136 }
168 137
169 LOG_DEBUG(Service_Mii, "called with param_1={:08X}, param_2={:08X}, param_3={:08X}", 138 ctx.WriteBuffer(SerializeArray(values));
170 unknown1, unknown2, unknown3);
171 139
172 const auto info = db.CreateRandom({unknown1, unknown2, unknown3}); 140 IPC::ResponseBuilder rb{ctx, 3};
173 IPC::ResponseBuilder rb{ctx, 2 + sizeof(MiiInfo) / sizeof(u32)};
174 rb.Push(RESULT_SUCCESS); 141 rb.Push(RESULT_SUCCESS);
175 rb.PushRaw<MiiInfo>(info); 142 rb.Push<u32>(static_cast<u32>(result->size()));
176 } 143 }
177 144
178 void BuildDefault(Kernel::HLERequestContext& ctx) { 145 void UpdateLatest(Kernel::HLERequestContext& ctx) {
179 IPC::RequestParser rp{ctx}; 146 IPC::RequestParser rp{ctx};
180 const auto index{rp.PopRaw<u32>()}; 147 const auto info{rp.PopRaw<MiiInfo>()};
148 const auto source_flag{rp.PopRaw<SourceFlag>()};
181 149
182 if (index > 5) { 150 LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag);
183 LOG_ERROR(Service_Mii, "invalid argument, index cannot be greater than 5 but is {:08X}", 151
184 index); 152 const auto result{manager.UpdateLatest(info, source_flag)};
153 if (result.Failed()) {
185 IPC::ResponseBuilder rb{ctx, 2}; 154 IPC::ResponseBuilder rb{ctx, 2};
186 rb.Push(ERROR_INVALID_ARGUMENT); 155 rb.Push(result.Code());
187 return; 156 return;
188 } 157 }
189 158
190 LOG_DEBUG(Service_Mii, "called with index={:08X}", index);
191
192 const auto info = db.CreateDefault(index);
193 IPC::ResponseBuilder rb{ctx, 2 + sizeof(MiiInfo) / sizeof(u32)}; 159 IPC::ResponseBuilder rb{ctx, 2 + sizeof(MiiInfo) / sizeof(u32)};
194 rb.Push(RESULT_SUCCESS); 160 rb.Push(RESULT_SUCCESS);
195 rb.PushRaw<MiiInfo>(info); 161 rb.PushRaw<MiiInfo>(*result);
196 } 162 }
197 163
198 // Gets Miis from database at offset and index in format MiiStoreDataElement 164 void BuildRandom(Kernel::HLERequestContext& ctx) {
199 void Get2(Kernel::HLERequestContext& ctx) {
200 IPC::RequestParser rp{ctx};
201 const auto size{rp.PopRaw<u32>()};
202 const auto source{rp.PopRaw<Source>()};
203
204 LOG_DEBUG(Service_Mii, "called with size={:08X}, offset={:08X}, source={}", size,
205 offsets[2], source);
206
207 u32 read_size{};
208 ctx.WriteBuffer(
209 SerializeArray(&MiiManager::GetStoreDataElement, offsets[2], size, read_size));
210 offsets[2] += read_size;
211
212 IPC::ResponseBuilder rb{ctx, 3};
213 rb.Push(RESULT_SUCCESS);
214 rb.Push<u32>(read_size);
215 }
216
217 // Gets Miis from database at offset and index in format MiiStoreData
218 void Get3(Kernel::HLERequestContext& ctx) {
219 IPC::RequestParser rp{ctx};
220 const auto size{rp.PopRaw<u32>()};
221 const auto source{rp.PopRaw<Source>()};
222
223 LOG_DEBUG(Service_Mii, "called with size={:08X}, offset={:08X}, source={}", size,
224 offsets[3], source);
225
226 u32 read_size{};
227 ctx.WriteBuffer(SerializeArray(&MiiManager::GetStoreData, offsets[3], size, read_size));
228 offsets[3] += read_size;
229
230 IPC::ResponseBuilder rb{ctx, 3};
231 rb.Push(RESULT_SUCCESS);
232 rb.Push<u32>(read_size);
233 }
234
235 void FindIndex(Kernel::HLERequestContext& ctx) {
236 IPC::RequestParser rp{ctx}; 165 IPC::RequestParser rp{ctx};
237 const auto uuid{rp.PopRaw<Common::UUID>()};
238 const auto unknown{rp.PopRaw<bool>()};
239 166
240 LOG_DEBUG(Service_Mii, "called with uuid={}, unknown={}", uuid.FormatSwitch(), unknown); 167 const auto age{rp.PopRaw<Age>()};
168 const auto gender{rp.PopRaw<Gender>()};
169 const auto race{rp.PopRaw<Race>()};
241 170
242 IPC::ResponseBuilder rb{ctx, 3}; 171 LOG_DEBUG(Service_Mii, "called with age={}, gender={}, race={}", age, gender, race);
243 172
244 const auto index = db.IndexOf(uuid); 173 if (age > Age::All) {
245 if (index > MAX_MIIS) { 174 IPC::ResponseBuilder rb{ctx, 2};
246 // TODO(DarkLordZach): Find a better error code 175 rb.Push(ERROR_INVALID_ARGUMENT);
247 rb.Push(RESULT_UNKNOWN); 176 LOG_ERROR(Service_Mii, "invalid age={}", age);
248 rb.Push(index); 177 return;
249 } else {
250 rb.Push(RESULT_SUCCESS);
251 rb.Push(index);
252 } 178 }
253 }
254 179
255 void Move(Kernel::HLERequestContext& ctx) { 180 if (gender > Gender::All) {
256 IPC::RequestParser rp{ctx};
257 const auto uuid{rp.PopRaw<Common::UUID>()};
258 const auto index{rp.PopRaw<s32>()};
259
260 if (index < 0) {
261 LOG_ERROR(Service_Mii, "Index cannot be negative but is {:08X}!", index);
262 IPC::ResponseBuilder rb{ctx, 2}; 181 IPC::ResponseBuilder rb{ctx, 2};
263 rb.Push(ERROR_INVALID_ARGUMENT); 182 rb.Push(ERROR_INVALID_ARGUMENT);
183 LOG_ERROR(Service_Mii, "invalid gender={}", gender);
264 return; 184 return;
265 } 185 }
266 186
267 LOG_DEBUG(Service_Mii, "called with uuid={}, index={:08X}", uuid.FormatSwitch(), index); 187 if (race > Race::All) {
268
269 const auto success = db.Move(uuid, index);
270
271 IPC::ResponseBuilder rb{ctx, 2};
272 // TODO(DarkLordZach): Find a better error code
273 rb.Push(success ? RESULT_SUCCESS : RESULT_UNKNOWN);
274 }
275
276 void AddOrReplace(Kernel::HLERequestContext& ctx) {
277 IPC::RequestParser rp{ctx};
278 const auto data{rp.PopRaw<MiiStoreData>()};
279
280 LOG_DEBUG(Service_Mii, "called with Mii data uuid={}, name={}", data.uuid.FormatSwitch(),
281 Common::UTF16ToUTF8(data.Name()));
282
283 const auto success = db.AddOrReplace(data);
284
285 IPC::ResponseBuilder rb{ctx, 2};
286 // TODO(DarkLordZach): Find a better error code
287 rb.Push(success ? RESULT_SUCCESS : RESULT_UNKNOWN);
288 }
289
290 void Delete(Kernel::HLERequestContext& ctx) {
291 IPC::RequestParser rp{ctx};
292 const auto uuid{rp.PopRaw<Common::UUID>()};
293
294 LOG_DEBUG(Service_Mii, "called with uuid={}", uuid.FormatSwitch());
295
296 const auto success = db.Remove(uuid);
297
298 IPC::ResponseBuilder rb{ctx, 2};
299 rb.Push(success ? RESULT_SUCCESS : ERROR_CANNOT_FIND_ENTRY);
300 }
301
302 void DestroyFile(Kernel::HLERequestContext& ctx) {
303 LOG_DEBUG(Service_Mii, "called");
304
305 if (!db.IsTestModeEnabled()) {
306 LOG_ERROR(Service_Mii, "Database is not in test mode -- cannot destory database file.");
307 IPC::ResponseBuilder rb{ctx, 2}; 188 IPC::ResponseBuilder rb{ctx, 2};
308 rb.Push(ERROR_NOT_IN_TEST_MODE); 189 rb.Push(ERROR_INVALID_ARGUMENT);
190 LOG_ERROR(Service_Mii, "invalid race={}", race);
309 return; 191 return;
310 } 192 }
311 193
312 IPC::ResponseBuilder rb{ctx, 3}; 194 IPC::ResponseBuilder rb{ctx, 2 + sizeof(MiiInfo) / sizeof(u32)};
313 rb.Push(RESULT_SUCCESS); 195 rb.Push(RESULT_SUCCESS);
314 rb.Push(db.DestroyFile()); 196 rb.PushRaw<MiiInfo>(manager.BuildRandom(age, gender, race));
315 } 197 }
316 198
317 void DeleteFile(Kernel::HLERequestContext& ctx) { 199 void BuildDefault(Kernel::HLERequestContext& ctx) {
318 LOG_DEBUG(Service_Mii, "called"); 200 IPC::RequestParser rp{ctx};
201 const auto index{rp.Pop<u32>()};
202
203 LOG_DEBUG(Service_Mii, "called with index={}", index);
319 204
320 if (!db.IsTestModeEnabled()) { 205 if (index > 5) {
321 LOG_ERROR(Service_Mii, "Database is not in test mode -- cannot delete database file."); 206 LOG_ERROR(Service_Mii, "invalid argument, index cannot be greater than 5 but is {:08X}",
207 index);
322 IPC::ResponseBuilder rb{ctx, 2}; 208 IPC::ResponseBuilder rb{ctx, 2};
323 rb.Push(ERROR_NOT_IN_TEST_MODE); 209 rb.Push(ERROR_INVALID_ARGUMENT);
324 return; 210 return;
325 } 211 }
326 212
327 IPC::ResponseBuilder rb{ctx, 3}; 213 IPC::ResponseBuilder rb{ctx, 2 + sizeof(MiiInfo) / sizeof(u32)};
328 rb.Push(RESULT_SUCCESS);
329 rb.Push(db.DeleteFile());
330 }
331
332 void Format(Kernel::HLERequestContext& ctx) {
333 LOG_DEBUG(Service_Mii, "called");
334
335 db.Clear();
336
337 IPC::ResponseBuilder rb{ctx, 2};
338 rb.Push(RESULT_SUCCESS); 214 rb.Push(RESULT_SUCCESS);
215 rb.PushRaw<MiiInfo>(manager.BuildDefault(index));
339 } 216 }
340 217
341 void GetIndex(Kernel::HLERequestContext& ctx) { 218 void GetIndex(Kernel::HLERequestContext& ctx) {
342 IPC::RequestParser rp{ctx}; 219 IPC::RequestParser rp{ctx};
343 const auto info{rp.PopRaw<MiiInfo>()}; 220 const auto info{rp.PopRaw<MiiInfo>()};
344 221
345 LOG_DEBUG(Service_Mii, "called with Mii info uuid={}, name={}", info.uuid.FormatSwitch(), 222 LOG_DEBUG(Service_Mii, "called");
346 Common::UTF16ToUTF8(info.Name()));
347
348 const auto index = db.IndexOf(info);
349 223
350 IPC::ResponseBuilder rb{ctx, 2}; 224 u32 index{};
351 rb.Push(RESULT_SUCCESS); 225 IPC::ResponseBuilder rb{ctx, 3};
226 rb.Push(manager.GetIndex(info, index));
352 rb.Push(index); 227 rb.Push(index);
353 } 228 }
354 229
@@ -364,12 +239,14 @@ private:
364 rb.Push(RESULT_SUCCESS); 239 rb.Push(RESULT_SUCCESS);
365 } 240 }
366 241
367 MiiManager db; 242 constexpr bool IsInterfaceVersionSupported(u32 interface_version) const {
243 return current_interface_version >= interface_version;
244 }
368 245
369 u32 current_interface_version = 0; 246 MiiManager manager;
370 247
371 // Last read offsets of Get functions 248 u32 current_interface_version{};
372 std::array<u32, 4> offsets{}; 249 u64 current_update_counter{};
373}; 250};
374 251
375class MiiDBModule final : public ServiceFramework<MiiDBModule> { 252class MiiDBModule final : public ServiceFramework<MiiDBModule> {
diff --git a/src/core/hle/service/mii/mii_manager.cpp b/src/core/hle/service/mii/mii_manager.cpp
deleted file mode 100644
index 8d0353075..000000000
--- a/src/core/hle/service/mii/mii_manager.cpp
+++ /dev/null
@@ -1,420 +0,0 @@
1// Copyright 2018 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <algorithm>
6#include <cstring>
7#include "common/assert.h"
8#include "common/file_util.h"
9#include "common/logging/log.h"
10#include "common/string_util.h"
11#include "core/hle/service/mii/mii_manager.h"
12
13namespace Service::Mii {
14
15namespace {
16
17constexpr char MII_SAVE_DATABASE_PATH[] = "/system/save/8000000000000030/MiiDatabase.dat";
18constexpr std::array<char16_t, 11> DEFAULT_MII_NAME = {u'y', u'u', u'z', u'u', u'\0'};
19
20// This value was retrieved from HW test
21constexpr MiiStoreData DEFAULT_MII = {
22 {
23 0x21, 0x40, 0x40, 0x01, 0x08, 0x01, 0x13, 0x08, 0x08, 0x02, 0x17, 0x8C, 0x06, 0x01,
24 0x69, 0x6D, 0x8A, 0x6A, 0x82, 0x14, 0x00, 0x00, 0x00, 0x20, 0x64, 0x72, 0x44, 0x44,
25 },
26 {'y', 'u', 'z', 'u', '\0'},
27 Common::UUID{1, 0},
28 0,
29 0,
30};
31
32// Default values taken from multiple real databases
33const MiiDatabase DEFAULT_MII_DATABASE{Common::MakeMagic('N', 'F', 'D', 'B'), {}, {1}, 0, 0};
34
35constexpr std::array<const char*, 4> SOURCE_NAMES{
36 "Database",
37 "Default",
38 "Account",
39 "Friend",
40};
41
42template <typename T, std::size_t SourceArraySize, std::size_t DestArraySize>
43std::array<T, DestArraySize> ResizeArray(const std::array<T, SourceArraySize>& in) {
44 std::array<T, DestArraySize> out{};
45 std::memcpy(out.data(), in.data(), sizeof(T) * std::min(SourceArraySize, DestArraySize));
46 return out;
47}
48
49MiiInfo ConvertStoreDataToInfo(const MiiStoreData& data) {
50 MiiStoreBitFields bf{};
51 std::memcpy(&bf, data.data.data(), sizeof(MiiStoreBitFields));
52 return {
53 data.uuid,
54 ResizeArray<char16_t, 10, 11>(data.name),
55 static_cast<u8>(bf.font_region.Value()),
56 static_cast<u8>(bf.favorite_color.Value()),
57 static_cast<u8>(bf.gender.Value()),
58 static_cast<u8>(bf.height.Value()),
59 static_cast<u8>(bf.weight.Value()),
60 static_cast<u8>(bf.mii_type.Value()),
61 static_cast<u8>(bf.mii_region.Value()),
62 static_cast<u8>(bf.face_type.Value()),
63 static_cast<u8>(bf.face_color.Value()),
64 static_cast<u8>(bf.face_wrinkle.Value()),
65 static_cast<u8>(bf.face_makeup.Value()),
66 static_cast<u8>(bf.hair_type.Value()),
67 static_cast<u8>(bf.hair_color.Value()),
68 static_cast<bool>(bf.hair_flip.Value()),
69 static_cast<u8>(bf.eye_type.Value()),
70 static_cast<u8>(bf.eye_color.Value()),
71 static_cast<u8>(bf.eye_scale.Value()),
72 static_cast<u8>(bf.eye_aspect.Value()),
73 static_cast<u8>(bf.eye_rotate.Value()),
74 static_cast<u8>(bf.eye_x.Value()),
75 static_cast<u8>(bf.eye_y.Value()),
76 static_cast<u8>(bf.eyebrow_type.Value()),
77 static_cast<u8>(bf.eyebrow_color.Value()),
78 static_cast<u8>(bf.eyebrow_scale.Value()),
79 static_cast<u8>(bf.eyebrow_aspect.Value()),
80 static_cast<u8>(bf.eyebrow_rotate.Value()),
81 static_cast<u8>(bf.eyebrow_x.Value()),
82 static_cast<u8>(bf.eyebrow_y.Value()),
83 static_cast<u8>(bf.nose_type.Value()),
84 static_cast<u8>(bf.nose_scale.Value()),
85 static_cast<u8>(bf.nose_y.Value()),
86 static_cast<u8>(bf.mouth_type.Value()),
87 static_cast<u8>(bf.mouth_color.Value()),
88 static_cast<u8>(bf.mouth_scale.Value()),
89 static_cast<u8>(bf.mouth_aspect.Value()),
90 static_cast<u8>(bf.mouth_y.Value()),
91 static_cast<u8>(bf.facial_hair_color.Value()),
92 static_cast<u8>(bf.beard_type.Value()),
93 static_cast<u8>(bf.mustache_type.Value()),
94 static_cast<u8>(bf.mustache_scale.Value()),
95 static_cast<u8>(bf.mustache_y.Value()),
96 static_cast<u8>(bf.glasses_type.Value()),
97 static_cast<u8>(bf.glasses_color.Value()),
98 static_cast<u8>(bf.glasses_scale.Value()),
99 static_cast<u8>(bf.glasses_y.Value()),
100 static_cast<u8>(bf.mole_type.Value()),
101 static_cast<u8>(bf.mole_scale.Value()),
102 static_cast<u8>(bf.mole_x.Value()),
103 static_cast<u8>(bf.mole_y.Value()),
104 0x00,
105 };
106}
107MiiStoreData ConvertInfoToStoreData(const MiiInfo& info) {
108 MiiStoreData out{};
109 out.name = ResizeArray<char16_t, 11, 10>(info.name);
110 out.uuid = info.uuid;
111
112 MiiStoreBitFields bf{};
113
114 bf.hair_type.Assign(info.hair_type);
115 bf.mole_type.Assign(info.mole_type);
116 bf.height.Assign(info.height);
117 bf.hair_flip.Assign(info.hair_flip);
118 bf.weight.Assign(info.weight);
119 bf.hair_color.Assign(info.hair_color);
120
121 bf.gender.Assign(info.gender);
122 bf.eye_color.Assign(info.eye_color);
123 bf.eyebrow_color.Assign(info.eyebrow_color);
124 bf.mouth_color.Assign(info.mouth_color);
125 bf.facial_hair_color.Assign(info.facial_hair_color);
126
127 bf.mii_type.Assign(info.mii_type);
128 bf.glasses_color.Assign(info.glasses_color);
129 bf.font_region.Assign(info.font_region);
130 bf.eye_type.Assign(info.eye_type);
131 bf.mii_region.Assign(info.mii_region);
132 bf.mouth_type.Assign(info.mouth_type);
133 bf.glasses_scale.Assign(info.glasses_scale);
134 bf.eye_y.Assign(info.eye_y);
135
136 bf.mustache_type.Assign(info.mustache_type);
137 bf.eyebrow_type.Assign(info.eyebrow_type);
138 bf.beard_type.Assign(info.beard_type);
139 bf.nose_type.Assign(info.nose_type);
140 bf.mouth_aspect.Assign(info.mouth_aspect_ratio);
141 bf.nose_y.Assign(info.nose_y);
142 bf.eyebrow_aspect.Assign(info.eyebrow_aspect_ratio);
143 bf.mouth_y.Assign(info.mouth_y);
144
145 bf.eye_rotate.Assign(info.eye_rotate);
146 bf.mustache_y.Assign(info.mustache_y);
147 bf.eye_aspect.Assign(info.eye_aspect_ratio);
148 bf.glasses_y.Assign(info.glasses_y);
149 bf.eye_scale.Assign(info.eye_scale);
150 bf.mole_x.Assign(info.mole_x);
151 bf.mole_y.Assign(info.mole_y);
152
153 bf.glasses_type.Assign(info.glasses_type);
154 bf.face_type.Assign(info.face_type);
155 bf.favorite_color.Assign(info.favorite_color);
156 bf.face_wrinkle.Assign(info.face_wrinkle);
157 bf.face_color.Assign(info.face_color);
158 bf.eye_x.Assign(info.eye_x);
159 bf.face_makeup.Assign(info.face_makeup);
160
161 bf.eyebrow_rotate.Assign(info.eyebrow_rotate);
162 bf.eyebrow_scale.Assign(info.eyebrow_scale);
163 bf.eyebrow_y.Assign(info.eyebrow_y);
164 bf.eyebrow_x.Assign(info.eyebrow_x);
165 bf.mouth_scale.Assign(info.mouth_scale);
166 bf.nose_scale.Assign(info.nose_scale);
167 bf.mole_scale.Assign(info.mole_scale);
168 bf.mustache_scale.Assign(info.mustache_scale);
169
170 std::memcpy(out.data.data(), &bf, sizeof(MiiStoreBitFields));
171
172 return out;
173}
174
175} // namespace
176
177std::ostream& operator<<(std::ostream& os, Source source) {
178 if (static_cast<std::size_t>(source) >= SOURCE_NAMES.size()) {
179 return os << "[UNKNOWN SOURCE]";
180 }
181
182 os << SOURCE_NAMES.at(static_cast<std::size_t>(source));
183 return os;
184}
185
186std::u16string MiiInfo::Name() const {
187 return Common::UTF16StringFromFixedZeroTerminatedBuffer(name.data(), name.size());
188}
189
190bool operator==(const MiiInfo& lhs, const MiiInfo& rhs) {
191 return std::memcmp(&lhs, &rhs, sizeof(MiiInfo)) == 0;
192}
193
194bool operator!=(const MiiInfo& lhs, const MiiInfo& rhs) {
195 return !operator==(lhs, rhs);
196}
197
198std::u16string MiiStoreData::Name() const {
199 return Common::UTF16StringFromFixedZeroTerminatedBuffer(name.data(), name.size());
200}
201
202MiiManager::MiiManager() = default;
203
204MiiManager::~MiiManager() = default;
205
206MiiInfo MiiManager::CreateRandom(RandomParameters params) {
207 LOG_WARNING(Service_Mii,
208 "(STUBBED) called with params={:08X}{:08X}{:08X}, returning default Mii",
209 params.unknown_1, params.unknown_2, params.unknown_3);
210
211 return ConvertStoreDataToInfo(CreateMiiWithUniqueUUID());
212}
213
214MiiInfo MiiManager::CreateDefault(u32 index) {
215 const auto new_mii = CreateMiiWithUniqueUUID();
216
217 database.miis.at(index) = new_mii;
218
219 EnsureDatabasePartition();
220 return ConvertStoreDataToInfo(new_mii);
221}
222
223bool MiiManager::CheckUpdatedFlag() const {
224 return updated_flag;
225}
226
227void MiiManager::ResetUpdatedFlag() {
228 updated_flag = false;
229}
230
231bool MiiManager::IsTestModeEnabled() const {
232 return is_test_mode_enabled;
233}
234
235bool MiiManager::Empty() const {
236 return Size() == 0;
237}
238
239bool MiiManager::Full() const {
240 return Size() == MAX_MIIS;
241}
242
243void MiiManager::Clear() {
244 updated_flag = true;
245 std::fill(database.miis.begin(), database.miis.end(), MiiStoreData{});
246}
247
248u32 MiiManager::Size() const {
249 return static_cast<u32>(std::count_if(database.miis.begin(), database.miis.end(),
250 [](const MiiStoreData& elem) { return elem.uuid; }));
251}
252
253MiiInfo MiiManager::GetInfo(u32 index) const {
254 return ConvertStoreDataToInfo(GetStoreData(index));
255}
256
257MiiInfoElement MiiManager::GetInfoElement(u32 index) const {
258 return {GetInfo(index), Source::Database};
259}
260
261MiiStoreData MiiManager::GetStoreData(u32 index) const {
262 return database.miis.at(index);
263}
264
265MiiStoreDataElement MiiManager::GetStoreDataElement(u32 index) const {
266 return {GetStoreData(index), Source::Database};
267}
268
269bool MiiManager::Remove(Common::UUID uuid) {
270 const auto iter = std::find_if(database.miis.begin(), database.miis.end(),
271 [uuid](const MiiStoreData& elem) { return elem.uuid == uuid; });
272
273 if (iter == database.miis.end())
274 return false;
275
276 updated_flag = true;
277 *iter = MiiStoreData{};
278 EnsureDatabasePartition();
279 return true;
280}
281
282u32 MiiManager::IndexOf(Common::UUID uuid) const {
283 const auto iter = std::find_if(database.miis.begin(), database.miis.end(),
284 [uuid](const MiiStoreData& elem) { return elem.uuid == uuid; });
285
286 if (iter == database.miis.end())
287 return INVALID_INDEX;
288
289 return static_cast<u32>(std::distance(database.miis.begin(), iter));
290}
291
292u32 MiiManager::IndexOf(const MiiInfo& info) const {
293 const auto iter =
294 std::find_if(database.miis.begin(), database.miis.end(), [&info](const MiiStoreData& elem) {
295 return ConvertStoreDataToInfo(elem) == info;
296 });
297
298 if (iter == database.miis.end())
299 return INVALID_INDEX;
300
301 return static_cast<u32>(std::distance(database.miis.begin(), iter));
302}
303
304bool MiiManager::Move(Common::UUID uuid, u32 new_index) {
305 const auto index = IndexOf(uuid);
306
307 if (index == INVALID_INDEX || new_index >= MAX_MIIS)
308 return false;
309
310 updated_flag = true;
311 const auto moving = database.miis[index];
312 const auto replacing = database.miis[new_index];
313 if (replacing.uuid) {
314 database.miis[index] = replacing;
315 database.miis[new_index] = moving;
316 } else {
317 database.miis[index] = MiiStoreData{};
318 database.miis[new_index] = moving;
319 }
320
321 EnsureDatabasePartition();
322 return true;
323}
324
325bool MiiManager::AddOrReplace(const MiiStoreData& data) {
326 const auto index = IndexOf(data.uuid);
327
328 updated_flag = true;
329 if (index == INVALID_INDEX) {
330 const auto size = Size();
331 if (size == MAX_MIIS)
332 return false;
333 database.miis[size] = data;
334 } else {
335 database.miis[index] = data;
336 }
337
338 return true;
339}
340
341bool MiiManager::DestroyFile() {
342 database = DEFAULT_MII_DATABASE;
343 updated_flag = false;
344 return DeleteFile();
345}
346
347bool MiiManager::DeleteFile() {
348 const auto path = FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) + MII_SAVE_DATABASE_PATH;
349 return FileUtil::Exists(path) && FileUtil::Delete(path);
350}
351
352void MiiManager::WriteToFile() {
353 const auto raw_path =
354 FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) + "/system/save/8000000000000030";
355 if (FileUtil::Exists(raw_path) && !FileUtil::IsDirectory(raw_path))
356 FileUtil::Delete(raw_path);
357
358 const auto path = FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) + MII_SAVE_DATABASE_PATH;
359
360 if (!FileUtil::CreateFullPath(path)) {
361 LOG_WARNING(Service_Mii,
362 "Failed to create full path of MiiDatabase.dat. Create the directory "
363 "nand/system/save/8000000000000030 to mitigate this "
364 "issue.");
365 return;
366 }
367
368 FileUtil::IOFile save(path, "wb");
369
370 if (!save.IsOpen()) {
371 LOG_WARNING(Service_Mii, "Failed to write save data to file... No changes to user data "
372 "made in current session will be saved.");
373 return;
374 }
375
376 save.Resize(sizeof(MiiDatabase));
377 if (save.WriteBytes(&database, sizeof(MiiDatabase)) != sizeof(MiiDatabase)) {
378 LOG_WARNING(Service_Mii, "Failed to write all data to save file... Data may be malformed "
379 "and/or regenerated on next run.");
380 save.Resize(0);
381 }
382}
383
384void MiiManager::ReadFromFile() {
385 FileUtil::IOFile save(
386 FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) + MII_SAVE_DATABASE_PATH, "rb");
387
388 if (!save.IsOpen()) {
389 LOG_WARNING(Service_ACC, "Failed to load profile data from save data... Generating new "
390 "blank Mii database with no Miis.");
391 std::memcpy(&database, &DEFAULT_MII_DATABASE, sizeof(MiiDatabase));
392 return;
393 }
394
395 if (save.ReadBytes(&database, sizeof(MiiDatabase)) != sizeof(MiiDatabase)) {
396 LOG_WARNING(Service_ACC, "MiiDatabase.dat is smaller than expected... Generating new blank "
397 "Mii database with no Miis.");
398 std::memcpy(&database, &DEFAULT_MII_DATABASE, sizeof(MiiDatabase));
399 return;
400 }
401
402 EnsureDatabasePartition();
403}
404
405MiiStoreData MiiManager::CreateMiiWithUniqueUUID() const {
406 auto new_mii = DEFAULT_MII;
407
408 do {
409 new_mii.uuid = Common::UUID::Generate();
410 } while (IndexOf(new_mii.uuid) != INVALID_INDEX);
411
412 return new_mii;
413}
414
415void MiiManager::EnsureDatabasePartition() {
416 std::stable_partition(database.miis.begin(), database.miis.end(),
417 [](const MiiStoreData& elem) { return elem.uuid; });
418}
419
420} // namespace Service::Mii
diff --git a/src/core/hle/service/mii/mii_manager.h b/src/core/hle/service/mii/mii_manager.h
deleted file mode 100644
index fc742816a..000000000
--- a/src/core/hle/service/mii/mii_manager.h
+++ /dev/null
@@ -1,273 +0,0 @@
1// Copyright 2018 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "common/bit_field.h"
8#include "common/common_funcs.h"
9#include "common/uuid.h"
10
11namespace Service::Mii {
12
13constexpr std::size_t MAX_MIIS{100};
14constexpr u32 INVALID_INDEX{0xFFFFFFFF};
15
16struct RandomParameters {
17 u32 unknown_1{};
18 u32 unknown_2{};
19 u32 unknown_3{};
20};
21static_assert(sizeof(RandomParameters) == 0xC, "RandomParameters has incorrect size.");
22
23enum class Source : u32 {
24 Database = 0,
25 Default = 1,
26 Account = 2,
27 Friend = 3,
28};
29
30std::ostream& operator<<(std::ostream& os, Source source);
31
32struct MiiInfo {
33 Common::UUID uuid{Common::INVALID_UUID};
34 std::array<char16_t, 11> name{};
35 u8 font_region{};
36 u8 favorite_color{};
37 u8 gender{};
38 u8 height{};
39 u8 weight{};
40 u8 mii_type{};
41 u8 mii_region{};
42 u8 face_type{};
43 u8 face_color{};
44 u8 face_wrinkle{};
45 u8 face_makeup{};
46 u8 hair_type{};
47 u8 hair_color{};
48 bool hair_flip{};
49 u8 eye_type{};
50 u8 eye_color{};
51 u8 eye_scale{};
52 u8 eye_aspect_ratio{};
53 u8 eye_rotate{};
54 u8 eye_x{};
55 u8 eye_y{};
56 u8 eyebrow_type{};
57 u8 eyebrow_color{};
58 u8 eyebrow_scale{};
59 u8 eyebrow_aspect_ratio{};
60 u8 eyebrow_rotate{};
61 u8 eyebrow_x{};
62 u8 eyebrow_y{};
63 u8 nose_type{};
64 u8 nose_scale{};
65 u8 nose_y{};
66 u8 mouth_type{};
67 u8 mouth_color{};
68 u8 mouth_scale{};
69 u8 mouth_aspect_ratio{};
70 u8 mouth_y{};
71 u8 facial_hair_color{};
72 u8 beard_type{};
73 u8 mustache_type{};
74 u8 mustache_scale{};
75 u8 mustache_y{};
76 u8 glasses_type{};
77 u8 glasses_color{};
78 u8 glasses_scale{};
79 u8 glasses_y{};
80 u8 mole_type{};
81 u8 mole_scale{};
82 u8 mole_x{};
83 u8 mole_y{};
84 INSERT_PADDING_BYTES(1);
85
86 std::u16string Name() const;
87};
88static_assert(sizeof(MiiInfo) == 0x58, "MiiInfo has incorrect size.");
89static_assert(std::has_unique_object_representations_v<MiiInfo>,
90 "All bits of MiiInfo must contribute to its value.");
91
92bool operator==(const MiiInfo& lhs, const MiiInfo& rhs);
93bool operator!=(const MiiInfo& lhs, const MiiInfo& rhs);
94
95#pragma pack(push, 4)
96struct MiiInfoElement {
97 MiiInfo info{};
98 Source source{};
99};
100static_assert(sizeof(MiiInfoElement) == 0x5C, "MiiInfoElement has incorrect size.");
101
102struct MiiStoreBitFields {
103 union {
104 u32 word_0{};
105
106 BitField<24, 8, u32> hair_type;
107 BitField<23, 1, u32> mole_type;
108 BitField<16, 7, u32> height;
109 BitField<15, 1, u32> hair_flip;
110 BitField<8, 7, u32> weight;
111 BitField<0, 7, u32> hair_color;
112 };
113
114 union {
115 u32 word_1{};
116
117 BitField<31, 1, u32> gender;
118 BitField<24, 7, u32> eye_color;
119 BitField<16, 7, u32> eyebrow_color;
120 BitField<8, 7, u32> mouth_color;
121 BitField<0, 7, u32> facial_hair_color;
122 };
123
124 union {
125 u32 word_2{};
126
127 BitField<31, 1, u32> mii_type;
128 BitField<24, 7, u32> glasses_color;
129 BitField<22, 2, u32> font_region;
130 BitField<16, 6, u32> eye_type;
131 BitField<14, 2, u32> mii_region;
132 BitField<8, 6, u32> mouth_type;
133 BitField<5, 3, u32> glasses_scale;
134 BitField<0, 5, u32> eye_y;
135 };
136
137 union {
138 u32 word_3{};
139
140 BitField<29, 3, u32> mustache_type;
141 BitField<24, 5, u32> eyebrow_type;
142 BitField<21, 3, u32> beard_type;
143 BitField<16, 5, u32> nose_type;
144 BitField<13, 3, u32> mouth_aspect;
145 BitField<8, 5, u32> nose_y;
146 BitField<5, 3, u32> eyebrow_aspect;
147 BitField<0, 5, u32> mouth_y;
148 };
149
150 union {
151 u32 word_4{};
152
153 BitField<29, 3, u32> eye_rotate;
154 BitField<24, 5, u32> mustache_y;
155 BitField<21, 3, u32> eye_aspect;
156 BitField<16, 5, u32> glasses_y;
157 BitField<13, 3, u32> eye_scale;
158 BitField<8, 5, u32> mole_x;
159 BitField<0, 5, u32> mole_y;
160 };
161
162 union {
163 u32 word_5{};
164
165 BitField<24, 5, u32> glasses_type;
166 BitField<20, 4, u32> face_type;
167 BitField<16, 4, u32> favorite_color;
168 BitField<12, 4, u32> face_wrinkle;
169 BitField<8, 4, u32> face_color;
170 BitField<4, 4, u32> eye_x;
171 BitField<0, 4, u32> face_makeup;
172 };
173
174 union {
175 u32 word_6{};
176
177 BitField<28, 4, u32> eyebrow_rotate;
178 BitField<24, 4, u32> eyebrow_scale;
179 BitField<20, 4, u32> eyebrow_y;
180 BitField<16, 4, u32> eyebrow_x;
181 BitField<12, 4, u32> mouth_scale;
182 BitField<8, 4, u32> nose_scale;
183 BitField<4, 4, u32> mole_scale;
184 BitField<0, 4, u32> mustache_scale;
185 };
186};
187static_assert(sizeof(MiiStoreBitFields) == 0x1C, "MiiStoreBitFields has incorrect size.");
188static_assert(std::is_trivially_copyable_v<MiiStoreBitFields>,
189 "MiiStoreBitFields is not trivially copyable.");
190
191struct MiiStoreData {
192 // This corresponds to the above structure MiiStoreBitFields. I did it like this because the
193 // BitField<> type makes this (and any thing that contains it) not trivially copyable, which is
194 // not suitable for our uses.
195 std::array<u8, 0x1C> data{};
196 static_assert(sizeof(MiiStoreBitFields) == sizeof(data), "data field has incorrect size.");
197
198 std::array<char16_t, 10> name{};
199 Common::UUID uuid{Common::INVALID_UUID};
200 u16 crc_1{};
201 u16 crc_2{};
202
203 std::u16string Name() const;
204};
205static_assert(sizeof(MiiStoreData) == 0x44, "MiiStoreData has incorrect size.");
206
207struct MiiStoreDataElement {
208 MiiStoreData data{};
209 Source source{};
210};
211static_assert(sizeof(MiiStoreDataElement) == 0x48, "MiiStoreDataElement has incorrect size.");
212
213struct MiiDatabase {
214 u32 magic{}; // 'NFDB'
215 std::array<MiiStoreData, MAX_MIIS> miis{};
216 INSERT_PADDING_BYTES(1);
217 u8 count{};
218 u16 crc{};
219};
220static_assert(sizeof(MiiDatabase) == 0x1A98, "MiiDatabase has incorrect size.");
221#pragma pack(pop)
222
223// The Mii manager is responsible for loading and storing the Miis to the database in NAND along
224// with providing an easy interface for HLE emulation of the mii service.
225class MiiManager {
226public:
227 MiiManager();
228 ~MiiManager();
229
230 MiiInfo CreateRandom(RandomParameters params);
231 MiiInfo CreateDefault(u32 index);
232
233 bool CheckUpdatedFlag() const;
234 void ResetUpdatedFlag();
235
236 bool IsTestModeEnabled() const;
237
238 bool Empty() const;
239 bool Full() const;
240
241 void Clear();
242
243 u32 Size() const;
244
245 MiiInfo GetInfo(u32 index) const;
246 MiiInfoElement GetInfoElement(u32 index) const;
247 MiiStoreData GetStoreData(u32 index) const;
248 MiiStoreDataElement GetStoreDataElement(u32 index) const;
249
250 bool Remove(Common::UUID uuid);
251 u32 IndexOf(Common::UUID uuid) const;
252 u32 IndexOf(const MiiInfo& info) const;
253
254 bool Move(Common::UUID uuid, u32 new_index);
255 bool AddOrReplace(const MiiStoreData& data);
256
257 bool DestroyFile();
258 bool DeleteFile();
259
260private:
261 void WriteToFile();
262 void ReadFromFile();
263
264 MiiStoreData CreateMiiWithUniqueUUID() const;
265
266 void EnsureDatabasePartition();
267
268 MiiDatabase database;
269 bool updated_flag{};
270 bool is_test_mode_enabled{};
271};
272
273}; // namespace Service::Mii
diff --git a/src/core/hle/service/mii/raw_data.cpp b/src/core/hle/service/mii/raw_data.cpp
new file mode 100644
index 000000000..25d7bae0c
--- /dev/null
+++ b/src/core/hle/service/mii/raw_data.cpp
@@ -0,0 +1,2261 @@
1// MIT License
2//
3// Copyright (c) Ryujinx Team and Contributors
4//
5// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
6// associated documentation files (the "Software"), to deal in the Software without restriction,
7// including without limitation the rights to use, copy, modify, merge, publish, distribute,
8// sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
9// furnished to do so, subject to the following conditions:
10//
11// The above copyright notice and this permission notice shall be included in all copies or
12// substantial portions of the Software.
13//
14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
15// NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
16// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
17// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19//
20
21#include "core/hle/service/mii/raw_data.h"
22
23namespace Service::Mii::RawData {
24
25const std::array<u8, 1728> DefaultMii{
26 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
27 0x21, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
28 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
29 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
30 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
31 0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
32 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
33 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34 0x04, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
35 0x04, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
36 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
37 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
38 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
39 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
40 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
41 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
42 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
43 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
44 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
45 0x04, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
46 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
47 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
48 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
49 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
50 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
51 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
52 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
53 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
54 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
55 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
56 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
57 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
58 0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
59 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
60 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
61 0x04, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
62 0x04, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
63 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
64 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
65 0x00, 0x00, 0x00, 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6d, 0x00,
66 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
67 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
68 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
69 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
70 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
71 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
72 0x04, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
73 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
74 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
75 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
76 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
77 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
78 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x00, 0x6f, 0x00,
79 0x20, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
80 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
81 0x21, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
82 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
83 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
84 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
85 0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
86 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
87 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
88 0x04, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
89 0x04, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
90 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
91 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
92 0x00, 0x00, 0x00, 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6d, 0x00,
93 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
94 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
95 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
96 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
97 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
98 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
99 0x04, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
100 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
101 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
102 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
103 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
104 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
105 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x00, 0x6f, 0x00,
106 0x20, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
107 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
108 0x0e, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
109 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
110 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
111 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
112 0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
113 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
114 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
115 0x04, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
116 0x04, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
117 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
118 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
119 0x00, 0x00, 0x00, 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6d, 0x00,
120 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
121 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
122 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
123 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
124 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
125 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
126 0x04, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
127 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
128 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
129 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
130 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
131 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
132 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x00, 0x6f, 0x00,
133 0x20, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
134
135const std::array<u8, 3672> RandomMiiFaceline{
136 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
137 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
138 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
139 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
140 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
141 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
142 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
143 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
144 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
145 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
146 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
147 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
148 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
149 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
150 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
151 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
152 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
153 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
154 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
155 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
156 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
157 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
158 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
159 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
160 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
161 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
162 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
163 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
164 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
165 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
166 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
167 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
168 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
169 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
170 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
171 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
172 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
173 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
174 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
175 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
176 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
177 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
178 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
179 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
180 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
181 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
182 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
183 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
184 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
185 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
186 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
187 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
188 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
189 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
190 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
191 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
192 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
193 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
194 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
195 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
196 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
197 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
198 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
199 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
200 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
201 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
202 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
203 0x07, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
204 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
205 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
206 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
207 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
208 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
209 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
210 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
211 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
212 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
213 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
214 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
215 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
216 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
217 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
218 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
219 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
220 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
221 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
222 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
223 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
224 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
225 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
226 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
227 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
228 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
229 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
230 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
231 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
232 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
233 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
234 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
235 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
236 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
237 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
238 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
239 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
240 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
241 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
242 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
243 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
244 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
245 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
246 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
247 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
248 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
249 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
250 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
251 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
252 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
253 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
254 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
255 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
256 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
257 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
258 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
259 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
260 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
261 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
262 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
263 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
264 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
265 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
266 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
267 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
268 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
269 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
270 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
271 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
272 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
273 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
274 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
275 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
276 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
277 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
278 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
279 0x05, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
280 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
281 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
282 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
283 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
284 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
285 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
286 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
287 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
288 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
289 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
290 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
291 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
292 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
293 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
294 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
295 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
296 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
297 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
298 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
299 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
300 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
301 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
302 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
303 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
304 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
305 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
306 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
307 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
308 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
309 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
310 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
311 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
312 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
313 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
314 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
315 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
316 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
317 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
318 0x08, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
319 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
320 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
321 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
322 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
323 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
324 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
325 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
326 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
327 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
328 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
329 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
330 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
331 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
332 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
333 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
334 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
335 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
336 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
337 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
338 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
339 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
340 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
341 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
342 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
343 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
344 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
345 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
346 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
347 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
348 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
349 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
350 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
351 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
352 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
353 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
354 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
355 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
356 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
357 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
358 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
359 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
360 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
361 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
362 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
363 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
364 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
365 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
366
367const std::array<u8, 1200> RandomMiiFacelineColor{
368 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
369 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
370 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
371 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
372 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
373 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
374 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
375 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
376 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
377 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
378 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
379 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
380 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
381 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
382 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
383 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
384 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
385 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
386 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
387 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
388 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
389 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
390 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
391 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
392 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
393 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
394 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
395 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
396 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
397 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
398 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
399 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
400 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
401 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
402 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
403 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
404 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
405 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
406 0x0a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
407 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
408 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
409 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
410 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
411 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
412 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
413 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
414 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
415 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
416 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
417 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
418 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
419 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
420 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
421 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
422 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
423 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
424 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
425 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
426 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
427 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
428 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
429 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
430 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
431 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
432 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
433 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
434 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
435 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
436 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
437 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
438 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
439 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
440 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
441 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
442 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
443
444const std::array<u8, 3672> RandomMiiFacelineWrinkle{
445 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
446 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
447 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
448 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
449 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
450 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
451 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
452 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
453 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
454 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
455 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
456 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
457 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
458 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
459 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
460 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
461 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
462 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
463 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
464 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
465 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
466 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
467 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
468 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
469 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
470 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
471 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
472 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
473 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
474 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
475 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
476 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
477 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
478 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
479 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
480 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
481 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
482 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
483 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
484 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
485 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
486 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
487 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
488 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
489 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
490 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
491 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
492 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
493 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
494 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
495 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
496 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
497 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
498 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
499 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
500 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
501 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
502 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
503 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
504 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
505 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
506 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
507 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
508 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
509 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
510 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
511 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
512 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
513 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
514 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
515 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
516 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
517 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
518 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
519 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
520 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
521 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
522 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
523 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
524 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
525 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
526 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
527 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
528 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
529 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
530 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
531 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
532 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
533 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
534 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
535 0x14, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
536 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
537 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
538 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
539 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
540 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
541 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
542 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
543 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
544 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
545 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
546 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
547 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
548 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
549 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
550 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
551 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
552 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
553 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
554 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
555 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
556 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
557 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
558 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
559 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
560 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
561 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
562 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
563 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
564 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
565 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
566 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
567 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
568 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
569 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
570 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
571 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
572 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
573 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
574 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
575 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
576 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
577 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
578 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
579 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
580 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
581 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
582 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
583 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
584 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
585 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
586 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
587 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
588 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
589 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
590 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
591 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
592 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
593 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
594 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
595 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
596 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
597 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
598 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
599 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
600 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
601 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
602 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
603 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
604 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
605 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
606 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
607 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
608 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
609 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
610 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
611 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
612 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
613 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
614 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
615 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
616 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
617 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
618 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
619 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
620 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
621 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
622 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
623 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
624 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
625 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
626 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
627 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
628 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
629 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
630 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
631 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
632 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
633 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
634 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
635 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
636 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
637 0x14, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
638 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
639 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
640 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
641 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
642 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
643 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
644 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
645 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
646 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
647 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
648 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
649 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
650 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
651 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
652 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
653 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
654 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
655 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
656 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
657 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
658 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
659 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
660 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
661 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
662 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
663 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
664 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
665 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
666 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
667 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
668 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
669 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
670 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
671 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
672 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
673 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
674 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
675
676const std::array<u8, 3672> RandomMiiFacelineMakeup{
677 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
678 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
679 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
680 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
681 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
682 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
683 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
684 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
685 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
686 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
687 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
688 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
689 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
690 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
691 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
692 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
693 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
694 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
695 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
696 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
697 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
698 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
699 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
700 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
701 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
702 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
703 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
704 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
705 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
706 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
707 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
708 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
709 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
710 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
711 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
712 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
713 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
714 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
715 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
716 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
717 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
718 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
719 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
720 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
721 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
722 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
723 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
724 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
725 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
726 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
727 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
728 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
729 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
730 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
731 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
732 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
733 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
734 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
735 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
736 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
737 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
738 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
739 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
740 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
741 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
742 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
743 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
744 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
745 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
746 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
747 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
748 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
749 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
750 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
751 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
752 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
753 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
754 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
755 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
756 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
757 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
758 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
759 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
760 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
761 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
762 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
763 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
764 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
765 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
766 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
767 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
768 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
769 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
770 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
771 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
772 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
773 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
774 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
775 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
776 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
777 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
778 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
779 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
780 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
781 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
782 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
783 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
784 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
785 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
786 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
787 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
788 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
789 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
790 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
791 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
792 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
793 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
794 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
795 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
796 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
797 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
798 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
799 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
800 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
801 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
802 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
803 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
804 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
805 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
806 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
807 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
808 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
809 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
810 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
811 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
812 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
813 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
814 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
815 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
816 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
817 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
818 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
819 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
820 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
821 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
822 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
823 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
824 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
825 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
826 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
827 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
828 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
829 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
830 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
831 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
832 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
833 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
834 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
835 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
836 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
837 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
838 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
839 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
840 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
841 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
842 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
843 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
844 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
845 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
846 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
847 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
848 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
849 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
850 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
851 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
852 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
853 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
854 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
855 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
856 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
857 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
858 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
859 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
860 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
861 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
862 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
863 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
864 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
865 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
866 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
867 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
868 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
869 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
870 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
871 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
872 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
873 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
874 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
875 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
876 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
877 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
878 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
879 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
880 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
881 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
882 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
883 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
884 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
885 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
886 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
887 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
888 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
889 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
890 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
891 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
892 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
893 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
894 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
895 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
896 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
897 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
898 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
899 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
900 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
901 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
902 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
903 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
904 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
905 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
906 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
907
908const std::array<u8, 3672> RandomMiiHairType{
909 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
910 0x0d, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00,
911 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
912 0x24, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
913 0x2b, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00,
914 0x30, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00,
915 0x34, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00,
916 0x40, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
917 0x56, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
918 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
919 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
920 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
921 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
922 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
923 0x17, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
924 0x21, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
925 0x25, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00,
926 0x2c, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
927 0x31, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
928 0x36, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
929 0x42, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00,
930 0x56, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
931 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
932 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
933 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
934 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
935 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
936 0x1e, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
937 0x22, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
938 0x26, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
939 0x2d, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00,
940 0x32, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
941 0x38, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00,
942 0x49, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00,
943 0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
944 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
945 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
946 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
947 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
948 0x26, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
949 0x1f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
950 0x24, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
951 0x2a, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00,
952 0x2f, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00,
953 0x33, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
954 0x37, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00,
955 0x3c, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00,
956 0x43, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00,
957 0x4c, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
958 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
959 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
960 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
961 0x0d, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00,
962 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
963 0x25, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
964 0x2b, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00,
965 0x30, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00,
966 0x34, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
967 0x38, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
968 0x40, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00,
969 0x44, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00,
970 0x51, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
971 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
972 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
973 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
974 0x17, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
975 0x21, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
976 0x26, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00,
977 0x2c, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
978 0x31, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
979 0x35, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
980 0x3a, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
981 0x41, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00,
982 0x46, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00,
983 0x56, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
984 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
985 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
986 0x02, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
987 0x1e, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00,
988 0x2d, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00,
989 0x36, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00,
990 0x41, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00,
991 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
992 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
993 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
994 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
995 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
996 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
997 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
998 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
999 0x13, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
1000 0x24, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00,
1001 0x2d, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00,
1002 0x36, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00,
1003 0x41, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00,
1004 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1005 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1006 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1007 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1008 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1009 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1010 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1011 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
1012 0x0d, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
1013 0x25, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00,
1014 0x2f, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
1015 0x37, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00,
1016 0x43, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1017 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1018 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1019 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1020 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1021 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1022 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1023 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1024 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1025 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1026 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1027 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
1028 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
1029 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
1030 0x16, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00,
1031 0x1c, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00,
1032 0x3e, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00,
1033 0x4c, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00,
1034 0x53, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1035 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1036 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1037 0x00, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1038 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1039 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1040 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1041 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
1042 0x13, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
1043 0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
1044 0x2e, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00,
1045 0x3f, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
1046 0x4a, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00,
1047 0x53, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00,
1048 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1049 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1050 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1051 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1052 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1053 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1054 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
1055 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
1056 0x19, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00,
1057 0x32, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00,
1058 0x40, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00,
1059 0x4d, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00,
1060 0x54, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1061 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1062 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
1063 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1064 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1065 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1066 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1067 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
1068 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
1069 0x19, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
1070 0x2a, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
1071 0x3e, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00,
1072 0x47, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00,
1073 0x51, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00,
1074 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1075 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1076 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1077 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1078 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1079 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1080 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1081 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
1082 0x1a, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00,
1083 0x3a, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00,
1084 0x40, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
1085 0x4a, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00,
1086 0x53, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1087 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1088 0x01, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1089 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1090 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1091 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
1092 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
1093 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
1094 0x16, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00,
1095 0x1b, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
1096 0x3c, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
1097 0x45, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00,
1098 0x4f, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00,
1099 0x54, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1100 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1101 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1102 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1103 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
1104 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
1105 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
1106 0x3a, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
1107 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1108 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1109 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1110 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1111 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1112 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1113 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00,
1114 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1115 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1116 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1117 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1118 0x15, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
1119 0x3e, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
1120 0x51, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1121 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1122 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1123 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1124 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1125 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1126 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1127 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1128 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1129 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1130 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
1131 0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00,
1132 0x45, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00,
1133 0x53, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1134 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1135 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1136 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1137 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1138 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
1139
1140const std::array<u8, 1800> RandomMiiHairColor{
1141 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1142 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1143 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1144 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1145 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1146 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1147 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1148 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1149 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1150 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1151 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1152 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1153 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1154 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1155 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1156 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1157 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1158 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1159 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1160 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1161 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1162 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1163 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1164 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1165 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1166 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1167 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1168 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1169 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1170 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1171 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1172 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1173 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1174 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1175 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1176 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1177 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1178 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1179 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1180 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1181 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1182 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1183 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1184 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1185 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1186 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1187 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1188 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1189 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1190 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1191 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1192 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1193 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1194 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1195 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1196 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1197 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1198 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1199 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1200 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1201 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1202 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1203 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1204 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1205 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1206 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1207 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1208 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1209 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1210 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1211 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1212 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1213 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1214 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1215 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1216 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1217 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1218 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1219 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1220 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1221 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1222 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1223 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1224 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1225 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1226 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1227 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1228 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1229 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1230 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1231 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1232 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1233 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1234 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1235 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1236 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1237 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1238 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1239 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1240 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1241 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1242 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1243 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1244 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1245 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1246 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1247 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1248 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1249 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1250 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1251 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1252 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1253 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
1254
1255const std::array<u8, 3672> RandomMiiEyeType{
1256 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00,
1257 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1258 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1259 0x0d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
1260 0x1b, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
1261 0x24, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00,
1262 0x2b, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00,
1263 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1264 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1265 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1266 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1267 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1268 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1269 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1270 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1271 0x09, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
1272 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00,
1273 0x1d, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
1274 0x26, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00,
1275 0x2f, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00,
1276 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1277 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1278 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1279 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1280 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1281 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1282 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1283 0x05, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1284 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1285 0x10, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00,
1286 0x1d, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
1287 0x26, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00,
1288 0x2f, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00,
1289 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1290 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1291 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1292 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1293 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1294 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1295 0x23, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1296 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1297 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1298 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
1299 0x16, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00,
1300 0x20, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1301 0x26, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00,
1302 0x2c, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00,
1303 0x35, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00,
1304 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1305 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1306 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1307 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
1308 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1309 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1310 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1311 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
1312 0x1b, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
1313 0x22, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00,
1314 0x27, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
1315 0x2f, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00,
1316 0x37, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1317 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1318 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1319 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1320 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1321 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1322 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1323 0x0d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
1324 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00,
1325 0x1d, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
1326 0x24, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
1327 0x29, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00,
1328 0x30, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00,
1329 0x38, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1330 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1331 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1332 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1333 0x02, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1334 0x05, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1335 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1336 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
1337 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
1338 0x22, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
1339 0x29, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00,
1340 0x35, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00,
1341 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1342 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1343 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1344 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1345 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1346 0x1e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1347 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1348 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1349 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
1350 0x16, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
1351 0x24, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00,
1352 0x2c, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00,
1353 0x37, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1354 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1355 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1356 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1357 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1358 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
1359 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1360 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1361 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1362 0x12, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00,
1363 0x1f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
1364 0x25, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
1365 0x30, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00,
1366 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1367 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1368 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1369 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1370 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1371 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1372 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1373 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1374 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1375 0x10, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
1376 0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
1377 0x1d, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
1378 0x23, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1379 0x29, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00,
1380 0x2f, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
1381 0x39, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1382 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1383 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1384 0x00, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1385 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1386 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1387 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1388 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
1389 0x19, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
1390 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
1391 0x26, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00,
1392 0x2a, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00,
1393 0x30, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00,
1394 0x3b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1395 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1396 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1397 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1398 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1399 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1400 0x0d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
1401 0x13, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
1402 0x1a, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
1403 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
1404 0x26, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00,
1405 0x2a, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00,
1406 0x30, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00,
1407 0x3b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1408 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1409 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00,
1410 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1411 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1412 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1413 0x0d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
1414 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
1415 0x17, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00,
1416 0x1c, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
1417 0x21, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1418 0x26, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00,
1419 0x2a, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00,
1420 0x30, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00,
1421 0x3a, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1422 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1423 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1424 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1425 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
1426 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
1427 0x13, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
1428 0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
1429 0x1d, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
1430 0x22, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00,
1431 0x27, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00,
1432 0x2d, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1433 0x35, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
1434 0x3b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1435 0x01, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1436 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1437 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1438 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1439 0x10, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1440 0x15, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
1441 0x1a, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
1442 0x1e, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
1443 0x23, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
1444 0x28, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00,
1445 0x2e, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00,
1446 0x36, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00,
1447 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1448 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1449 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1450 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1451 0x0d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
1452 0x13, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
1453 0x1b, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
1454 0x21, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00,
1455 0x27, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00,
1456 0x2d, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1457 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1458 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1459 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1460 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
1461 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1462 0x05, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1463 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
1464 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
1465 0x17, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00,
1466 0x1c, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
1467 0x22, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
1468 0x28, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00,
1469 0x2e, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1470 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1471 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1472 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1473 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1474 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1475 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1476 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1477 0x10, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
1478 0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00,
1479 0x1c, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
1480 0x22, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
1481 0x28, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00,
1482 0x2e, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1483 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1484 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1485 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
1486
1487const std::array<u8, 588> RandomMiiEyeColor{
1488 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1489 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1490 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1491 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1492 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1493 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1494 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1495 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1496 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1497 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1498 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1499 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1500 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1501 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1502 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1503 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1504 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1505 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1506 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1507 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1508 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1509 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1510 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1511 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1512 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1513 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1514 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1515 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1516 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1517 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1518 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1519 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1520 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1521 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1522 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1523 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1524 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
1525
1526const std::array<u8, 3672> RandomMiiEyebrowType{
1527 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
1528 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1529 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1530 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1531 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
1532 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1533 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1534 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1535 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1536 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1537 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1538 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1539 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1540 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1541 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1542 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1543 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1544 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
1545 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1546 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1547 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1548 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1549 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1550 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1551 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1552 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1553 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1554 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1555 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1556 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
1557 0x0e, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1558 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1559 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1560 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1561 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1562 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1563 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1564 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1565 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1566 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1567 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1568 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1569 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1570 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
1571 0x13, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
1572 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1573 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1574 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1575 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1576 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1577 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1578 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
1579 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1580 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1581 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1582 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1583 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
1584 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1585 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1586 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1587 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1588 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1589 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1590 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1591 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1592 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1593 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1594 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1595 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1596 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1597 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1598 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1599 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1600 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1601 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1602 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1603 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1604 0x02, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1605 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1606 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1607 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1608 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
1609 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1610 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1611 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1612 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1613 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1614 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1615 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1616 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1617 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1618 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1619 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1620 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1621 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1622 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1623 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1624 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1625 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1626 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1627 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1628 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1629 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
1630 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1631 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1632 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1633 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1634 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
1635 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1636 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1637 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1638 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1639 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1640 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1641 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1642 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1643 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1644 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
1645 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1646 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1647 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1648 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1649 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1650 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1651 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1652 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1653 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1654 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1655 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1656 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1657 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1658 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1659 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1660 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1661 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1662 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1663 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1664 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1665 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1666 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1667 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1668 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1669 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1670 0x0b, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1671 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1672 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1673 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1674 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1675 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1676 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1677 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1678 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1679 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1680 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1681 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1682 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1683 0x0d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1684 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1685 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1686 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1687 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1688 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1689 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1690 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1691 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1692 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1693 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1694 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1695 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
1696 0x0f, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1697 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1698 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1699 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1700 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1701 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1702 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1703 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1704 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1705 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1706 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1707 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1708 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1709 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1710 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1711 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1712 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1713 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1714 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1715 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1716 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1717 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1718 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1719 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1720 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1721 0x0d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1722 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1723 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1724 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1725 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1726 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1727 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1728 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1729 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1730 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1731 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1732 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1733 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
1734 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1735 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1736 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1737 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1738 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1739 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1740 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1741 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1742 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1743 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1744 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1745 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1746 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1747 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1748 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1749 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1750 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1751 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1752 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1753 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1754 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1755 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1756 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
1757
1758const std::array<u8, 3672> RandomMiiNoseType{
1759 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1760 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1761 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1762 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1763 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1764 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1765 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1766 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1767 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1768 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1769 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1770 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1771 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1772 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1773 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1774 0x05, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1775 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1776 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1777 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1778 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1779 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1780 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1781 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1782 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1783 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1784 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1785 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1786 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1787 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
1788 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1789 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1790 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1791 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1792 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1793 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1794 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1795 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1796 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1797 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1798 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1799 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1800 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1801 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1802 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1803 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1804 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1805 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1806 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1807 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1808 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1809 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1810 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
1811 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1812 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1813 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1814 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1815 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1816 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1817 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1818 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1819 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1820 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1821 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1822 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1823 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1824 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1825 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1826 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
1827 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1828 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1829 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1830 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1831 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1832 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1833 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1834 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1835 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1836 0x02, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1837 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1838 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1839 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
1840 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
1841 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1842 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1843 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1844 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1845 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1846 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1847 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1848 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1849 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1850 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1851 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1852 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1853 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1854 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1855 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1856 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1857 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1858 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1859 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1860 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1861 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1862 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1863 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1864 0x08, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1865 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1866 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1867 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1868 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1869 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1870 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1871 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1872 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1873 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1874 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1875 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1876 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1877 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1878 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1879 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1880 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1881 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1882 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1883 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1884 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1885 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1886 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1887 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1888 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1889 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1890 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1891 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1892 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1893 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1894 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1895 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1896 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1897 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1898 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1899 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1900 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1901 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
1902 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1903 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1904 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1905 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1906 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1907 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1908 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1909 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1910 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1911 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1912 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1913 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1914 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1915 0x0b, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1916 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1917 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1918 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1919 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1920 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1921 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1922 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1923 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1924 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1925 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1926 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1927 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1928 0x0d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1929 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1930 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1931 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1932 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1933 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1934 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1935 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1936 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1937 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1938 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1939 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1940 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1941 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1942 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1943 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1944 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1945 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1946 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1947 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1948 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1949 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1950 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1951 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1952 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1953 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1954 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1955 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1956 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1957 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1958 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1959 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1960 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1961 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1962 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1963 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1964 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1965 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1966 0x0b, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1967 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1968 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1969 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1970 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1971 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1972 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1973 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1974 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1975 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1976 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1977 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1978 0x08, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
1979 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1980 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1981 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1982 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1983 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1984 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1985 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1986 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1987 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1988 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
1989
1990const std::array<u8, 3672> RandomMiiMouthType{
1991 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
1992 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1993 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1994 0x0c, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
1995 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
1996 0x17, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
1997 0x1e, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
1998 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1999 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2000 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2001 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2002 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2003 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2004 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2005 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
2006 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
2007 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
2008 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
2009 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00,
2010 0x1c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
2011 0x22, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2012 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2013 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2014 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2015 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2016 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
2017 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
2018 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
2019 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
2020 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
2021 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
2022 0x17, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
2023 0x1e, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
2024 0x22, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2025 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2026 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2027 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2028 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2029 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2030 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
2031 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
2032 0x0a, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
2033 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
2034 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
2035 0x1e, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
2036 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2037 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2038 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2039 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2040 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2041 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2042 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00,
2043 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
2044 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
2045 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
2046 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
2047 0x13, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
2048 0x17, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
2049 0x22, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2050 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2051 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2052 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2053 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2054 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2055 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2056 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
2057 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
2058 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
2059 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
2060 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
2061 0x1e, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
2062 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2063 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2064 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2065 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2066 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2067 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2068 0x02, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
2069 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
2070 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
2071 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
2072 0x13, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
2073 0x17, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
2074 0x22, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2075 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2076 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2077 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2078 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2079 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2080 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
2081 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
2082 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
2083 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
2084 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
2085 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
2086 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00,
2087 0x21, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2088 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2089 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2090 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2091 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2092 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2093 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00,
2094 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
2095 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
2096 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
2097 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
2098 0x13, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
2099 0x17, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
2100 0x22, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2101 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2102 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2103 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2104 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2105 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2106 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2107 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
2108 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
2109 0x09, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
2110 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
2111 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00,
2112 0x1e, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
2113 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2114 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2115 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2116 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2117 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2118 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2119 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2120 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
2121 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
2122 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
2123 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
2124 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00,
2125 0x1e, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
2126 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2127 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2128 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2129 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2130 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2131 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2132 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
2133 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
2134 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
2135 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
2136 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
2137 0x17, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
2138 0x21, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2139 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2140 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2141 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2142 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2143 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2144 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
2145 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
2146 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
2147 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
2148 0x0f, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
2149 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
2150 0x1a, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
2151 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2152 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2153 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2154 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2155 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2156 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2157 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2158 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
2159 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
2160 0x09, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
2161 0x0f, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
2162 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
2163 0x1a, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
2164 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2165 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2166 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2167 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2168 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2169 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
2170 0x01, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2171 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
2172 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
2173 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
2174 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
2175 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
2176 0x1d, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2177 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2178 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2179 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2180 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2181 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2182 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
2183 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
2184 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
2185 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
2186 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
2187 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
2188 0x17, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
2189 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2190 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2191 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2192 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2193 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2194 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2195 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
2196 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
2197 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
2198 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
2199 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
2200 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
2201 0x17, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
2202 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2203 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2204 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2205 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2206 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2207 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2208 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2209 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
2210 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
2211 0x09, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
2212 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
2213 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
2214 0x19, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
2215 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2216 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2217 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2218 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2219 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2220 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
2221
2222const std::array<u8, 588> RandomMiiGlassType{
2223 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00,
2224 0x60, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2225 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2226 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2227 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2228 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2229 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2230 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2231 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2232 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2233 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2234 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2235 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00,
2236 0x56, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00,
2237 0x60, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2238 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2239 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2240 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2241 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2242 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2243 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2244 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2245 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2246 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2247 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
2248 0x4e, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00,
2249 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
2250 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2251 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2252 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2253 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2254 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2255 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2256 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2257 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2258 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2259 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
2260
2261} // namespace Service::Mii::RawData
diff --git a/src/core/hle/service/mii/raw_data.h b/src/core/hle/service/mii/raw_data.h
new file mode 100644
index 000000000..a02a5c0fd
--- /dev/null
+++ b/src/core/hle/service/mii/raw_data.h
@@ -0,0 +1,27 @@
1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <array>
8
9#include "common/common_types.h"
10
11namespace Service::Mii::RawData {
12
13extern const std::array<u8, 1728> DefaultMii;
14extern const std::array<u8, 3672> RandomMiiFaceline;
15extern const std::array<u8, 1200> RandomMiiFacelineColor;
16extern const std::array<u8, 3672> RandomMiiFacelineWrinkle;
17extern const std::array<u8, 3672> RandomMiiFacelineMakeup;
18extern const std::array<u8, 3672> RandomMiiHairType;
19extern const std::array<u8, 1800> RandomMiiHairColor;
20extern const std::array<u8, 3672> RandomMiiEyeType;
21extern const std::array<u8, 588> RandomMiiEyeColor;
22extern const std::array<u8, 3672> RandomMiiEyebrowType;
23extern const std::array<u8, 3672> RandomMiiNoseType;
24extern const std::array<u8, 3672> RandomMiiMouthType;
25extern const std::array<u8, 588> RandomMiiGlassType;
26
27} // namespace Service::Mii::RawData
diff --git a/src/core/hle/service/mii/types.h b/src/core/hle/service/mii/types.h
new file mode 100644
index 000000000..d65a1055e
--- /dev/null
+++ b/src/core/hle/service/mii/types.h
@@ -0,0 +1,67 @@
1// Copyright 2020 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "common/common_funcs.h"
8#include "common/common_types.h"
9
10namespace Service::Mii {
11
12enum class Age : u32 {
13 Young,
14 Normal,
15 Old,
16 All,
17};
18
19enum class BeardType : u32 {
20 None,
21 Beard1,
22 Beard2,
23 Beard3,
24 Beard4,
25 Beard5,
26};
27
28enum class BeardAndMustacheFlag : u32 { Beard = 1, Mustache, All = Beard | Mustache };
29DECLARE_ENUM_FLAG_OPERATORS(BeardAndMustacheFlag);
30
31enum class FontRegion : u32 {
32 Standard,
33 China,
34 Korea,
35 Taiwan,
36};
37
38enum class Gender : u32 {
39 Male,
40 Female,
41 All,
42 Maximum = Female,
43};
44
45enum class HairFlip : u32 {
46 Left,
47 Right,
48 Maximum = Right,
49};
50
51enum class MustacheType : u32 {
52 None,
53 Mustache1,
54 Mustache2,
55 Mustache3,
56 Mustache4,
57 Mustache5,
58};
59
60enum class Race : u32 {
61 Black,
62 White,
63 Asian,
64 All,
65};
66
67} // namespace Service::Mii
diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp
index 2f44d3779..789856118 100644
--- a/src/core/hle/service/nvflinger/nvflinger.cpp
+++ b/src/core/hle/service/nvflinger/nvflinger.cpp
@@ -28,8 +28,7 @@
28 28
29namespace Service::NVFlinger { 29namespace Service::NVFlinger {
30 30
31constexpr s64 frame_ticks = static_cast<s64>(1000000000 / 60); 31constexpr auto frame_ns = std::chrono::nanoseconds{1000000000 / 60};
32constexpr s64 frame_ticks_30fps = static_cast<s64>(1000000000 / 30);
33 32
34void NVFlinger::VSyncThread(NVFlinger& nv_flinger) { 33void NVFlinger::VSyncThread(NVFlinger& nv_flinger) {
35 nv_flinger.SplitVSync(); 34 nv_flinger.SplitVSync();
@@ -67,20 +66,24 @@ NVFlinger::NVFlinger(Core::System& system) : system(system) {
67 guard = std::make_shared<std::mutex>(); 66 guard = std::make_shared<std::mutex>();
68 67
69 // Schedule the screen composition events 68 // Schedule the screen composition events
70 composition_event = 69 composition_event = Core::Timing::CreateEvent(
71 Core::Timing::CreateEvent("ScreenComposition", [this](u64 userdata, s64 ns_late) { 70 "ScreenComposition", [this](u64, std::chrono::nanoseconds ns_late) {
72 Lock(); 71 Lock();
73 Compose(); 72 Compose();
74 const auto ticks = GetNextTicks(); 73
75 this->system.CoreTiming().ScheduleEvent(std::max<s64>(0LL, ticks - ns_late), 74 const auto ticks = std::chrono::nanoseconds{GetNextTicks()};
76 composition_event); 75 const auto ticks_delta = ticks - ns_late;
76 const auto future_ns = std::max(std::chrono::nanoseconds::zero(), ticks_delta);
77
78 this->system.CoreTiming().ScheduleEvent(future_ns, composition_event);
77 }); 79 });
80
78 if (system.IsMulticore()) { 81 if (system.IsMulticore()) {
79 is_running = true; 82 is_running = true;
80 wait_event = std::make_unique<Common::Event>(); 83 wait_event = std::make_unique<Common::Event>();
81 vsync_thread = std::make_unique<std::thread>(VSyncThread, std::ref(*this)); 84 vsync_thread = std::make_unique<std::thread>(VSyncThread, std::ref(*this));
82 } else { 85 } else {
83 system.CoreTiming().ScheduleEvent(frame_ticks, composition_event); 86 system.CoreTiming().ScheduleEvent(frame_ns, composition_event);
84 } 87 }
85} 88}
86 89
diff --git a/src/core/memory/cheat_engine.cpp b/src/core/memory/cheat_engine.cpp
index 53d27859b..ced41b1fe 100644
--- a/src/core/memory/cheat_engine.cpp
+++ b/src/core/memory/cheat_engine.cpp
@@ -20,7 +20,7 @@
20 20
21namespace Core::Memory { 21namespace Core::Memory {
22 22
23constexpr s64 CHEAT_ENGINE_TICKS = static_cast<s64>(1000000000 / 12); 23constexpr auto CHEAT_ENGINE_NS = std::chrono::nanoseconds{1000000000 / 12};
24constexpr u32 KEYPAD_BITMASK = 0x3FFFFFF; 24constexpr u32 KEYPAD_BITMASK = 0x3FFFFFF;
25 25
26StandardVmCallbacks::StandardVmCallbacks(Core::System& system, const CheatProcessMetadata& metadata) 26StandardVmCallbacks::StandardVmCallbacks(Core::System& system, const CheatProcessMetadata& metadata)
@@ -188,10 +188,12 @@ CheatEngine::~CheatEngine() {
188} 188}
189 189
190void CheatEngine::Initialize() { 190void CheatEngine::Initialize() {
191 event = Core::Timing::CreateEvent( 191 event = Core::Timing::CreateEvent("CheatEngine::FrameCallback::" +
192 "CheatEngine::FrameCallback::" + Common::HexToString(metadata.main_nso_build_id), 192 Common::HexToString(metadata.main_nso_build_id),
193 [this](u64 userdata, s64 ns_late) { FrameCallback(userdata, ns_late); }); 193 [this](u64 userdata, std::chrono::nanoseconds ns_late) {
194 core_timing.ScheduleEvent(CHEAT_ENGINE_TICKS, event); 194 FrameCallback(userdata, ns_late);
195 });
196 core_timing.ScheduleEvent(CHEAT_ENGINE_NS, event);
195 197
196 metadata.process_id = system.CurrentProcess()->GetProcessID(); 198 metadata.process_id = system.CurrentProcess()->GetProcessID();
197 metadata.title_id = system.CurrentProcess()->GetTitleID(); 199 metadata.title_id = system.CurrentProcess()->GetTitleID();
@@ -217,7 +219,7 @@ void CheatEngine::Reload(std::vector<CheatEntry> cheats) {
217 219
218MICROPROFILE_DEFINE(Cheat_Engine, "Add-Ons", "Cheat Engine", MP_RGB(70, 200, 70)); 220MICROPROFILE_DEFINE(Cheat_Engine, "Add-Ons", "Cheat Engine", MP_RGB(70, 200, 70));
219 221
220void CheatEngine::FrameCallback(u64 userdata, s64 ns_late) { 222void CheatEngine::FrameCallback(u64, std::chrono::nanoseconds ns_late) {
221 if (is_pending_reload.exchange(false)) { 223 if (is_pending_reload.exchange(false)) {
222 vm.LoadProgram(cheats); 224 vm.LoadProgram(cheats);
223 } 225 }
@@ -230,7 +232,7 @@ void CheatEngine::FrameCallback(u64 userdata, s64 ns_late) {
230 232
231 vm.Execute(metadata); 233 vm.Execute(metadata);
232 234
233 core_timing.ScheduleEvent(CHEAT_ENGINE_TICKS - ns_late, event); 235 core_timing.ScheduleEvent(CHEAT_ENGINE_NS - ns_late, event);
234} 236}
235 237
236} // namespace Core::Memory 238} // namespace Core::Memory
diff --git a/src/core/memory/cheat_engine.h b/src/core/memory/cheat_engine.h
index 2649423f8..d4068cf84 100644
--- a/src/core/memory/cheat_engine.h
+++ b/src/core/memory/cheat_engine.h
@@ -5,6 +5,7 @@
5#pragma once 5#pragma once
6 6
7#include <atomic> 7#include <atomic>
8#include <chrono>
8#include <memory> 9#include <memory>
9#include <vector> 10#include <vector>
10#include "common/common_types.h" 11#include "common/common_types.h"
@@ -71,7 +72,7 @@ public:
71 void Reload(std::vector<CheatEntry> cheats); 72 void Reload(std::vector<CheatEntry> cheats);
72 73
73private: 74private:
74 void FrameCallback(u64 userdata, s64 cycles_late); 75 void FrameCallback(u64 userdata, std::chrono::nanoseconds ns_late);
75 76
76 DmntCheatVm vm; 77 DmntCheatVm vm;
77 CheatProcessMetadata metadata; 78 CheatProcessMetadata metadata;
diff --git a/src/core/memory/dmnt_cheat_vm.cpp b/src/core/memory/dmnt_cheat_vm.cpp
index fb9f36bfd..2e7da23fe 100644
--- a/src/core/memory/dmnt_cheat_vm.cpp
+++ b/src/core/memory/dmnt_cheat_vm.cpp
@@ -190,6 +190,15 @@ void DmntCheatVm::LogOpcode(const CheatVmOpcode& opcode) {
190 callbacks->CommandLog( 190 callbacks->CommandLog(
191 fmt::format("Act[{:02X}]: {:d}", i, save_restore_regmask->should_operate[i])); 191 fmt::format("Act[{:02X}]: {:d}", i, save_restore_regmask->should_operate[i]));
192 } 192 }
193 } else if (auto rw_static_reg = std::get_if<ReadWriteStaticRegisterOpcode>(&opcode.opcode)) {
194 callbacks->CommandLog("Opcode: Read/Write Static Register");
195 if (rw_static_reg->static_idx < NumReadableStaticRegisters) {
196 callbacks->CommandLog("Op Type: ReadStaticRegister");
197 } else {
198 callbacks->CommandLog("Op Type: WriteStaticRegister");
199 }
200 callbacks->CommandLog(fmt::format("Reg Idx {:X}", rw_static_reg->idx));
201 callbacks->CommandLog(fmt::format("Stc Idx {:X}", rw_static_reg->static_idx));
193 } else if (auto debug_log = std::get_if<DebugLogOpcode>(&opcode.opcode)) { 202 } else if (auto debug_log = std::get_if<DebugLogOpcode>(&opcode.opcode)) {
194 callbacks->CommandLog("Opcode: Debug Log"); 203 callbacks->CommandLog("Opcode: Debug Log");
195 callbacks->CommandLog(fmt::format("Bit Width: {:X}", debug_log->bit_width)); 204 callbacks->CommandLog(fmt::format("Bit Width: {:X}", debug_log->bit_width));
@@ -544,6 +553,16 @@ bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode& out) {
544 } 553 }
545 opcode.opcode = save_restore_regmask; 554 opcode.opcode = save_restore_regmask;
546 } break; 555 } break;
556 case CheatVmOpcodeType::ReadWriteStaticRegister: {
557 ReadWriteStaticRegisterOpcode rw_static_reg{};
558 // C3000XXx
559 // C3 = opcode 0xC3.
560 // XX = static register index.
561 // x = register index.
562 rw_static_reg.static_idx = ((first_dword >> 4) & 0xFF);
563 rw_static_reg.idx = (first_dword & 0xF);
564 opcode.opcode = rw_static_reg;
565 } break;
547 case CheatVmOpcodeType::DebugLog: { 566 case CheatVmOpcodeType::DebugLog: {
548 DebugLogOpcode debug_log{}; 567 DebugLogOpcode debug_log{};
549 // FFFTIX## 568 // FFFTIX##
@@ -667,6 +686,7 @@ void DmntCheatVm::ResetState() {
667 registers.fill(0); 686 registers.fill(0);
668 saved_values.fill(0); 687 saved_values.fill(0);
669 loop_tops.fill(0); 688 loop_tops.fill(0);
689 static_registers.fill(0);
670 instruction_ptr = 0; 690 instruction_ptr = 0;
671 condition_depth = 0; 691 condition_depth = 0;
672 decode_success = true; 692 decode_success = true;
@@ -1153,6 +1173,15 @@ void DmntCheatVm::Execute(const CheatProcessMetadata& metadata) {
1153 } 1173 }
1154 } 1174 }
1155 } 1175 }
1176 } else if (auto rw_static_reg =
1177 std::get_if<ReadWriteStaticRegisterOpcode>(&cur_opcode.opcode)) {
1178 if (rw_static_reg->static_idx < NumReadableStaticRegisters) {
1179 // Load a register with a static register.
1180 registers[rw_static_reg->idx] = static_registers[rw_static_reg->static_idx];
1181 } else {
1182 // Store a register to a static register.
1183 static_registers[rw_static_reg->static_idx] = registers[rw_static_reg->idx];
1184 }
1156 } else if (auto debug_log = std::get_if<DebugLogOpcode>(&cur_opcode.opcode)) { 1185 } else if (auto debug_log = std::get_if<DebugLogOpcode>(&cur_opcode.opcode)) {
1157 // Read value from memory. 1186 // Read value from memory.
1158 u64 log_value = 0; 1187 u64 log_value = 0;
diff --git a/src/core/memory/dmnt_cheat_vm.h b/src/core/memory/dmnt_cheat_vm.h
index 8351fd798..21b86b72c 100644
--- a/src/core/memory/dmnt_cheat_vm.h
+++ b/src/core/memory/dmnt_cheat_vm.h
@@ -56,6 +56,7 @@ enum class CheatVmOpcodeType : u32 {
56 BeginRegisterConditionalBlock = 0xC0, 56 BeginRegisterConditionalBlock = 0xC0,
57 SaveRestoreRegister = 0xC1, 57 SaveRestoreRegister = 0xC1,
58 SaveRestoreRegisterMask = 0xC2, 58 SaveRestoreRegisterMask = 0xC2,
59 ReadWriteStaticRegister = 0xC3,
59 60
60 // This is a meta entry, and not a real opcode. 61 // This is a meta entry, and not a real opcode.
61 // This is to facilitate multi-nybble instruction decoding. 62 // This is to facilitate multi-nybble instruction decoding.
@@ -237,6 +238,11 @@ struct SaveRestoreRegisterMaskOpcode {
237 std::array<bool, 0x10> should_operate{}; 238 std::array<bool, 0x10> should_operate{};
238}; 239};
239 240
241struct ReadWriteStaticRegisterOpcode {
242 u32 static_idx{};
243 u32 idx{};
244};
245
240struct DebugLogOpcode { 246struct DebugLogOpcode {
241 u32 bit_width{}; 247 u32 bit_width{};
242 u32 log_id{}; 248 u32 log_id{};
@@ -259,7 +265,8 @@ struct CheatVmOpcode {
259 PerformArithmeticStaticOpcode, BeginKeypressConditionalOpcode, 265 PerformArithmeticStaticOpcode, BeginKeypressConditionalOpcode,
260 PerformArithmeticRegisterOpcode, StoreRegisterToAddressOpcode, 266 PerformArithmeticRegisterOpcode, StoreRegisterToAddressOpcode,
261 BeginRegisterConditionalOpcode, SaveRestoreRegisterOpcode, 267 BeginRegisterConditionalOpcode, SaveRestoreRegisterOpcode,
262 SaveRestoreRegisterMaskOpcode, DebugLogOpcode, UnrecognizedInstruction> 268 SaveRestoreRegisterMaskOpcode, ReadWriteStaticRegisterOpcode, DebugLogOpcode,
269 UnrecognizedInstruction>
263 opcode{}; 270 opcode{};
264}; 271};
265 272
@@ -281,6 +288,10 @@ public:
281 288
282 static constexpr std::size_t MaximumProgramOpcodeCount = 0x400; 289 static constexpr std::size_t MaximumProgramOpcodeCount = 0x400;
283 static constexpr std::size_t NumRegisters = 0x10; 290 static constexpr std::size_t NumRegisters = 0x10;
291 static constexpr std::size_t NumReadableStaticRegisters = 0x80;
292 static constexpr std::size_t NumWritableStaticRegisters = 0x80;
293 static constexpr std::size_t NumStaticRegisters =
294 NumReadableStaticRegisters + NumWritableStaticRegisters;
284 295
285 explicit DmntCheatVm(std::unique_ptr<Callbacks> callbacks); 296 explicit DmntCheatVm(std::unique_ptr<Callbacks> callbacks);
286 ~DmntCheatVm(); 297 ~DmntCheatVm();
@@ -302,6 +313,7 @@ private:
302 std::array<u32, MaximumProgramOpcodeCount> program{}; 313 std::array<u32, MaximumProgramOpcodeCount> program{};
303 std::array<u64, NumRegisters> registers{}; 314 std::array<u64, NumRegisters> registers{};
304 std::array<u64, NumRegisters> saved_values{}; 315 std::array<u64, NumRegisters> saved_values{};
316 std::array<u64, NumStaticRegisters> static_registers{};
305 std::array<std::size_t, NumRegisters> loop_tops{}; 317 std::array<std::size_t, NumRegisters> loop_tops{};
306 318
307 bool DecodeNextOpcode(CheatVmOpcode& out); 319 bool DecodeNextOpcode(CheatVmOpcode& out);
diff --git a/src/core/network/network.cpp b/src/core/network/network.cpp
new file mode 100644
index 000000000..56d173b5e
--- /dev/null
+++ b/src/core/network/network.cpp
@@ -0,0 +1,654 @@
1// Copyright 2020 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <algorithm>
6#include <cstring>
7#include <limits>
8#include <utility>
9#include <vector>
10
11#ifdef _WIN32
12#define _WINSOCK_DEPRECATED_NO_WARNINGS // gethostname
13#include <winsock2.h>
14#elif __unix__
15#include <errno.h>
16#include <fcntl.h>
17#include <netdb.h>
18#include <netinet/in.h>
19#include <poll.h>
20#include <sys/socket.h>
21#include <unistd.h>
22#else
23#error "Unimplemented platform"
24#endif
25
26#include "common/assert.h"
27#include "common/common_types.h"
28#include "common/logging/log.h"
29#include "core/network/network.h"
30#include "core/network/sockets.h"
31
32namespace Network {
33
34namespace {
35
36#ifdef _WIN32
37
38using socklen_t = int;
39
40void Initialize() {
41 WSADATA wsa_data;
42 (void)WSAStartup(MAKEWORD(2, 2), &wsa_data);
43}
44
45void Finalize() {
46 WSACleanup();
47}
48
49constexpr IPv4Address TranslateIPv4(in_addr addr) {
50 auto& bytes = addr.S_un.S_un_b;
51 return IPv4Address{bytes.s_b1, bytes.s_b2, bytes.s_b3, bytes.s_b4};
52}
53
54sockaddr TranslateFromSockAddrIn(SockAddrIn input) {
55 sockaddr_in result;
56
57#ifdef __unix__
58 result.sin_len = sizeof(result);
59#endif
60
61 switch (static_cast<Domain>(input.family)) {
62 case Domain::INET:
63 result.sin_family = AF_INET;
64 break;
65 default:
66 UNIMPLEMENTED_MSG("Unhandled sockaddr family={}", static_cast<int>(input.family));
67 result.sin_family = AF_INET;
68 break;
69 }
70
71 result.sin_port = htons(input.portno);
72
73 auto& ip = result.sin_addr.S_un.S_un_b;
74 ip.s_b1 = input.ip[0];
75 ip.s_b2 = input.ip[1];
76 ip.s_b3 = input.ip[2];
77 ip.s_b4 = input.ip[3];
78
79 sockaddr addr;
80 std::memcpy(&addr, &result, sizeof(addr));
81 return addr;
82}
83
84LINGER MakeLinger(bool enable, u32 linger_value) {
85 ASSERT(linger_value <= std::numeric_limits<u_short>::max());
86
87 LINGER value;
88 value.l_onoff = enable ? 1 : 0;
89 value.l_linger = static_cast<u_short>(linger_value);
90 return value;
91}
92
93int LastError() {
94 return WSAGetLastError();
95}
96
97bool EnableNonBlock(SOCKET fd, bool enable) {
98 u_long value = enable ? 1 : 0;
99 return ioctlsocket(fd, FIONBIO, &value) != SOCKET_ERROR;
100}
101
102#elif __unix__ // ^ _WIN32 v __unix__
103
104using SOCKET = int;
105using WSAPOLLFD = pollfd;
106using ULONG = u64;
107
108constexpr SOCKET INVALID_SOCKET = -1;
109constexpr SOCKET SOCKET_ERROR = -1;
110
111constexpr int WSAEWOULDBLOCK = EAGAIN;
112constexpr int WSAENOTCONN = ENOTCONN;
113
114constexpr int SD_RECEIVE = SHUT_RD;
115constexpr int SD_SEND = SHUT_WR;
116constexpr int SD_BOTH = SHUT_RDWR;
117
118void Initialize() {}
119
120void Finalize() {}
121
122constexpr IPv4Address TranslateIPv4(in_addr addr) {
123 const u32 bytes = addr.s_addr;
124 return IPv4Address{static_cast<u8>(bytes), static_cast<u8>(bytes >> 8),
125 static_cast<u8>(bytes >> 16), static_cast<u8>(bytes >> 24)};
126}
127
128sockaddr TranslateFromSockAddrIn(SockAddrIn input) {
129 sockaddr_in result;
130
131 switch (static_cast<Domain>(input.family)) {
132 case Domain::INET:
133 result.sin_family = AF_INET;
134 break;
135 default:
136 UNIMPLEMENTED_MSG("Unhandled sockaddr family={}", static_cast<int>(input.family));
137 result.sin_family = AF_INET;
138 break;
139 }
140
141 result.sin_port = htons(input.portno);
142
143 result.sin_addr.s_addr = input.ip[0] | input.ip[1] << 8 | input.ip[2] << 16 | input.ip[3] << 24;
144
145 sockaddr addr;
146 std::memcpy(&addr, &result, sizeof(addr));
147 return addr;
148}
149
150int WSAPoll(WSAPOLLFD* fds, ULONG nfds, int timeout) {
151 return poll(fds, nfds, timeout);
152}
153
154int closesocket(SOCKET fd) {
155 return close(fd);
156}
157
158linger MakeLinger(bool enable, u32 linger_value) {
159 linger value;
160 value.l_onoff = enable ? 1 : 0;
161 value.l_linger = linger_value;
162 return value;
163}
164
165int LastError() {
166 return errno;
167}
168
169bool EnableNonBlock(int fd, bool enable) {
170 int flags = fcntl(fd, F_GETFD);
171 if (flags == -1) {
172 return false;
173 }
174 if (enable) {
175 flags |= O_NONBLOCK;
176 } else {
177 flags &= ~O_NONBLOCK;
178 }
179 return fcntl(fd, F_SETFD, flags) == 0;
180}
181
182#endif
183
184int TranslateDomain(Domain domain) {
185 switch (domain) {
186 case Domain::INET:
187 return AF_INET;
188 default:
189 UNIMPLEMENTED_MSG("Unimplemented domain={}", static_cast<int>(domain));
190 return 0;
191 }
192}
193
194int TranslateType(Type type) {
195 switch (type) {
196 case Type::STREAM:
197 return SOCK_STREAM;
198 case Type::DGRAM:
199 return SOCK_DGRAM;
200 default:
201 UNIMPLEMENTED_MSG("Unimplemented type={}", static_cast<int>(type));
202 return 0;
203 }
204}
205
206int TranslateProtocol(Protocol protocol) {
207 switch (protocol) {
208 case Protocol::TCP:
209 return IPPROTO_TCP;
210 case Protocol::UDP:
211 return IPPROTO_UDP;
212 default:
213 UNIMPLEMENTED_MSG("Unimplemented protocol={}", static_cast<int>(protocol));
214 return 0;
215 }
216}
217
218SockAddrIn TranslateToSockAddrIn(sockaddr input_) {
219 sockaddr_in input;
220 std::memcpy(&input, &input_, sizeof(input));
221
222 SockAddrIn result;
223
224 switch (input.sin_family) {
225 case AF_INET:
226 result.family = Domain::INET;
227 break;
228 default:
229 UNIMPLEMENTED_MSG("Unhandled sockaddr family={}", input.sin_family);
230 result.family = Domain::INET;
231 break;
232 }
233
234 result.portno = ntohs(input.sin_port);
235
236 result.ip = TranslateIPv4(input.sin_addr);
237
238 return result;
239}
240
241u16 TranslatePollEvents(u16 events) {
242 u16 result = 0;
243
244 if (events & POLL_IN) {
245 events &= ~POLL_IN;
246 result |= POLLIN;
247 }
248 if (events & POLL_PRI) {
249 events &= ~POLL_PRI;
250#ifdef _WIN32
251 LOG_WARNING(Service, "Winsock doesn't support POLLPRI");
252#else
253 result |= POLL_PRI;
254#endif
255 }
256 if (events & POLL_OUT) {
257 events &= ~POLL_OUT;
258 result |= POLLOUT;
259 }
260
261 UNIMPLEMENTED_IF_MSG(events != 0, "Unhandled guest events=0x{:x}", events);
262
263 return result;
264}
265
266u16 TranslatePollRevents(u16 revents) {
267 u16 result = 0;
268 const auto translate = [&result, &revents](int host, unsigned guest) {
269 if (revents & host) {
270 revents &= ~host;
271 result |= guest;
272 }
273 };
274
275 translate(POLLIN, POLL_IN);
276 translate(POLLPRI, POLL_PRI);
277 translate(POLLOUT, POLL_OUT);
278 translate(POLLERR, POLL_ERR);
279 translate(POLLHUP, POLL_HUP);
280
281 UNIMPLEMENTED_IF_MSG(revents != 0, "Unhandled host revents=0x{:x}", revents);
282
283 return result;
284}
285
286template <typename T>
287Errno SetSockOpt(SOCKET fd, int option, T value) {
288 const int result =
289 setsockopt(fd, SOL_SOCKET, option, reinterpret_cast<const char*>(&value), sizeof(value));
290 if (result != SOCKET_ERROR) {
291 return Errno::SUCCESS;
292 }
293 const int ec = LastError();
294 UNREACHABLE_MSG("Unhandled host socket error={}", ec);
295 return Errno::SUCCESS;
296}
297
298} // Anonymous namespace
299
300NetworkInstance::NetworkInstance() {
301 Initialize();
302}
303
304NetworkInstance::~NetworkInstance() {
305 Finalize();
306}
307
308std::pair<IPv4Address, Errno> GetHostIPv4Address() {
309 std::array<char, 256> name{};
310 if (gethostname(name.data(), static_cast<int>(name.size()) - 1) == SOCKET_ERROR) {
311 UNIMPLEMENTED_MSG("Unhandled gethostname error");
312 return {IPv4Address{}, Errno::SUCCESS};
313 }
314
315 hostent* const ent = gethostbyname(name.data());
316 if (!ent) {
317 UNIMPLEMENTED_MSG("Unhandled gethostbyname error");
318 return {IPv4Address{}, Errno::SUCCESS};
319 }
320 if (ent->h_addr_list == nullptr) {
321 UNIMPLEMENTED_MSG("No addr provided in hostent->h_addr_list");
322 return {IPv4Address{}, Errno::SUCCESS};
323 }
324 if (ent->h_length != sizeof(in_addr)) {
325 UNIMPLEMENTED_MSG("Unexpected size={} in hostent->h_length", ent->h_length);
326 }
327
328 in_addr addr;
329 std::memcpy(&addr, ent->h_addr_list[0], sizeof(addr));
330 return {TranslateIPv4(addr), Errno::SUCCESS};
331}
332
333std::pair<s32, Errno> Poll(std::vector<PollFD>& pollfds, s32 timeout) {
334 const size_t num = pollfds.size();
335
336 std::vector<WSAPOLLFD> host_pollfds(pollfds.size());
337 std::transform(pollfds.begin(), pollfds.end(), host_pollfds.begin(), [](PollFD fd) {
338 WSAPOLLFD result;
339 result.fd = fd.socket->fd;
340 result.events = TranslatePollEvents(fd.events);
341 result.revents = 0;
342 return result;
343 });
344
345 const int result = WSAPoll(host_pollfds.data(), static_cast<ULONG>(num), timeout);
346 if (result == 0) {
347 ASSERT(std::all_of(host_pollfds.begin(), host_pollfds.end(),
348 [](WSAPOLLFD fd) { return fd.revents == 0; }));
349 return {0, Errno::SUCCESS};
350 }
351
352 for (size_t i = 0; i < num; ++i) {
353 pollfds[i].revents = TranslatePollRevents(host_pollfds[i].revents);
354 }
355
356 if (result > 0) {
357 return {result, Errno::SUCCESS};
358 }
359
360 ASSERT(result == SOCKET_ERROR);
361
362 const int ec = LastError();
363 UNREACHABLE_MSG("Unhandled host socket error={}", ec);
364 return {-1, Errno::SUCCESS};
365}
366
367Socket::~Socket() {
368 if (fd == INVALID_SOCKET) {
369 return;
370 }
371 (void)closesocket(fd);
372 fd = INVALID_SOCKET;
373}
374
375Socket::Socket(Socket&& rhs) noexcept : fd{std::exchange(rhs.fd, INVALID_SOCKET)} {}
376
377Errno Socket::Initialize(Domain domain, Type type, Protocol protocol) {
378 fd = socket(TranslateDomain(domain), TranslateType(type), TranslateProtocol(protocol));
379 if (fd != INVALID_SOCKET) {
380 return Errno::SUCCESS;
381 }
382
383 const int ec = LastError();
384 UNREACHABLE_MSG("Unhandled host socket error={}", ec);
385 return Errno::SUCCESS;
386}
387
388std::pair<Socket::AcceptResult, Errno> Socket::Accept() {
389 sockaddr addr;
390 socklen_t addrlen = sizeof(addr);
391 const SOCKET new_socket = accept(fd, &addr, &addrlen);
392
393 if (new_socket == INVALID_SOCKET) {
394 const int ec = LastError();
395 UNREACHABLE_MSG("Unhandled host socket error={}", ec);
396 return {AcceptResult{}, Errno::SUCCESS};
397 }
398
399 AcceptResult result;
400 result.socket = std::make_unique<Socket>();
401 result.socket->fd = new_socket;
402
403 ASSERT(addrlen == sizeof(sockaddr_in));
404 result.sockaddr_in = TranslateToSockAddrIn(addr);
405
406 return {std::move(result), Errno::SUCCESS};
407}
408
409Errno Socket::Connect(SockAddrIn addr_in) {
410 const sockaddr host_addr_in = TranslateFromSockAddrIn(addr_in);
411 if (connect(fd, &host_addr_in, sizeof(host_addr_in)) != INVALID_SOCKET) {
412 return Errno::SUCCESS;
413 }
414
415 switch (const int ec = LastError()) {
416 case WSAEWOULDBLOCK:
417 LOG_DEBUG(Service, "EAGAIN generated");
418 return Errno::AGAIN;
419 default:
420 UNREACHABLE_MSG("Unhandled host socket error={}", ec);
421 return Errno::SUCCESS;
422 }
423}
424
425std::pair<SockAddrIn, Errno> Socket::GetPeerName() {
426 sockaddr addr;
427 socklen_t addrlen = sizeof(addr);
428 if (getpeername(fd, &addr, &addrlen) == SOCKET_ERROR) {
429 const int ec = LastError();
430 UNREACHABLE_MSG("Unhandled host socket error={}", ec);
431 return {SockAddrIn{}, Errno::SUCCESS};
432 }
433
434 ASSERT(addrlen == sizeof(sockaddr_in));
435 return {TranslateToSockAddrIn(addr), Errno::SUCCESS};
436}
437
438std::pair<SockAddrIn, Errno> Socket::GetSockName() {
439 sockaddr addr;
440 socklen_t addrlen = sizeof(addr);
441 if (getsockname(fd, &addr, &addrlen) == SOCKET_ERROR) {
442 const int ec = LastError();
443 UNREACHABLE_MSG("Unhandled host socket error={}", ec);
444 return {SockAddrIn{}, Errno::SUCCESS};
445 }
446
447 ASSERT(addrlen == sizeof(sockaddr_in));
448 return {TranslateToSockAddrIn(addr), Errno::SUCCESS};
449}
450
451Errno Socket::Bind(SockAddrIn addr) {
452 const sockaddr addr_in = TranslateFromSockAddrIn(addr);
453 if (bind(fd, &addr_in, sizeof(addr_in)) != SOCKET_ERROR) {
454 return Errno::SUCCESS;
455 }
456
457 const int ec = LastError();
458 UNREACHABLE_MSG("Unhandled host socket error={}", ec);
459 return Errno::SUCCESS;
460}
461
462Errno Socket::Listen(s32 backlog) {
463 if (listen(fd, backlog) != SOCKET_ERROR) {
464 return Errno::SUCCESS;
465 }
466
467 const int ec = LastError();
468 UNREACHABLE_MSG("Unhandled host socket error={}", ec);
469 return Errno::SUCCESS;
470}
471
472Errno Socket::Shutdown(ShutdownHow how) {
473 int host_how = 0;
474 switch (how) {
475 case ShutdownHow::RD:
476 host_how = SD_RECEIVE;
477 break;
478 case ShutdownHow::WR:
479 host_how = SD_SEND;
480 break;
481 case ShutdownHow::RDWR:
482 host_how = SD_BOTH;
483 break;
484 default:
485 UNIMPLEMENTED_MSG("Unimplemented flag how={}", static_cast<int>(how));
486 return Errno::SUCCESS;
487 }
488 if (shutdown(fd, host_how) != SOCKET_ERROR) {
489 return Errno::SUCCESS;
490 }
491
492 switch (const int ec = LastError()) {
493 case WSAENOTCONN:
494 LOG_ERROR(Service, "ENOTCONN generated");
495 return Errno::NOTCONN;
496 default:
497 UNREACHABLE_MSG("Unhandled host socket error={}", ec);
498 return Errno::SUCCESS;
499 }
500}
501
502std::pair<s32, Errno> Socket::Recv(int flags, std::vector<u8>& message) {
503 ASSERT(flags == 0);
504 ASSERT(message.size() < static_cast<size_t>(std::numeric_limits<int>::max()));
505
506 const int result =
507 recv(fd, reinterpret_cast<char*>(message.data()), static_cast<int>(message.size()), 0);
508 if (result != SOCKET_ERROR) {
509 return {result, Errno::SUCCESS};
510 }
511
512 switch (const int ec = LastError()) {
513 case WSAEWOULDBLOCK:
514 LOG_DEBUG(Service, "EAGAIN generated");
515 return {-1, Errno::AGAIN};
516 case WSAENOTCONN:
517 LOG_ERROR(Service, "ENOTCONN generated");
518 return {-1, Errno::NOTCONN};
519 default:
520 UNREACHABLE_MSG("Unhandled host socket error={}", ec);
521 return {0, Errno::SUCCESS};
522 }
523}
524
525std::pair<s32, Errno> Socket::RecvFrom(int flags, std::vector<u8>& message, SockAddrIn* addr) {
526 ASSERT(flags == 0);
527 ASSERT(message.size() < static_cast<size_t>(std::numeric_limits<int>::max()));
528
529 sockaddr addr_in{};
530 socklen_t addrlen = sizeof(addr_in);
531 socklen_t* const p_addrlen = addr ? &addrlen : nullptr;
532 sockaddr* const p_addr_in = addr ? &addr_in : nullptr;
533
534 const int result = recvfrom(fd, reinterpret_cast<char*>(message.data()),
535 static_cast<int>(message.size()), 0, p_addr_in, p_addrlen);
536 if (result != SOCKET_ERROR) {
537 if (addr) {
538 ASSERT(addrlen == sizeof(addr_in));
539 *addr = TranslateToSockAddrIn(addr_in);
540 }
541 return {result, Errno::SUCCESS};
542 }
543
544 switch (const int ec = LastError()) {
545 case WSAEWOULDBLOCK:
546 LOG_DEBUG(Service, "EAGAIN generated");
547 return {-1, Errno::AGAIN};
548 case WSAENOTCONN:
549 LOG_ERROR(Service, "ENOTCONN generated");
550 return {-1, Errno::NOTCONN};
551 default:
552 UNREACHABLE_MSG("Unhandled host socket error={}", ec);
553 return {-1, Errno::SUCCESS};
554 }
555}
556
557std::pair<s32, Errno> Socket::Send(const std::vector<u8>& message, int flags) {
558 ASSERT(message.size() < static_cast<size_t>(std::numeric_limits<int>::max()));
559 ASSERT(flags == 0);
560
561 const int result = send(fd, reinterpret_cast<const char*>(message.data()),
562 static_cast<int>(message.size()), 0);
563 if (result != SOCKET_ERROR) {
564 return {result, Errno::SUCCESS};
565 }
566
567 const int ec = LastError();
568 switch (ec) {
569 case WSAEWOULDBLOCK:
570 LOG_DEBUG(Service, "EAGAIN generated");
571 return {-1, Errno::AGAIN};
572 case WSAENOTCONN:
573 LOG_ERROR(Service, "ENOTCONN generated");
574 return {-1, Errno::NOTCONN};
575 default:
576 UNREACHABLE_MSG("Unhandled host socket error={}", ec);
577 return {-1, Errno::SUCCESS};
578 }
579}
580
581std::pair<s32, Errno> Socket::SendTo(u32 flags, const std::vector<u8>& message,
582 const SockAddrIn* addr) {
583 ASSERT(flags == 0);
584
585 const sockaddr* to = nullptr;
586 const int tolen = addr ? 0 : sizeof(sockaddr);
587 sockaddr host_addr_in;
588
589 if (addr) {
590 host_addr_in = TranslateFromSockAddrIn(*addr);
591 to = &host_addr_in;
592 }
593
594 const int result = sendto(fd, reinterpret_cast<const char*>(message.data()),
595 static_cast<int>(message.size()), 0, to, tolen);
596 if (result != SOCKET_ERROR) {
597 return {result, Errno::SUCCESS};
598 }
599
600 const int ec = LastError();
601 UNREACHABLE_MSG("Unhandled host socket error={}", ec);
602 return {-1, Errno::SUCCESS};
603}
604
605Errno Socket::Close() {
606 [[maybe_unused]] const int result = closesocket(fd);
607 ASSERT(result == 0);
608 fd = INVALID_SOCKET;
609
610 return Errno::SUCCESS;
611}
612
613Errno Socket::SetLinger(bool enable, u32 linger) {
614 return SetSockOpt(fd, SO_LINGER, MakeLinger(enable, linger));
615}
616
617Errno Socket::SetReuseAddr(bool enable) {
618 return SetSockOpt<u32>(fd, SO_REUSEADDR, enable ? 1 : 0);
619}
620
621Errno Socket::SetBroadcast(bool enable) {
622 return SetSockOpt<u32>(fd, SO_BROADCAST, enable ? 1 : 0);
623}
624
625Errno Socket::SetSndBuf(u32 value) {
626 return SetSockOpt(fd, SO_SNDBUF, value);
627}
628
629Errno Socket::SetRcvBuf(u32 value) {
630 return SetSockOpt(fd, SO_RCVBUF, value);
631}
632
633Errno Socket::SetSndTimeo(u32 value) {
634 return SetSockOpt(fd, SO_SNDTIMEO, value);
635}
636
637Errno Socket::SetRcvTimeo(u32 value) {
638 return SetSockOpt(fd, SO_RCVTIMEO, value);
639}
640
641Errno Socket::SetNonBlock(bool enable) {
642 if (EnableNonBlock(fd, enable)) {
643 return Errno::SUCCESS;
644 }
645 const int ec = LastError();
646 UNREACHABLE_MSG("Unhandled host socket error={}", ec);
647 return Errno::SUCCESS;
648}
649
650bool Socket::IsOpened() const {
651 return fd != INVALID_SOCKET;
652}
653
654} // namespace Network
diff --git a/src/core/network/network.h b/src/core/network/network.h
new file mode 100644
index 000000000..0622e4593
--- /dev/null
+++ b/src/core/network/network.h
@@ -0,0 +1,87 @@
1// Copyright 2020 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <array>
8#include <utility>
9
10#include "common/common_types.h"
11
12namespace Network {
13
14class Socket;
15
16/// Error code for network functions
17enum class Errno {
18 SUCCESS,
19 BADF,
20 INVAL,
21 MFILE,
22 NOTCONN,
23 AGAIN,
24};
25
26/// Address families
27enum class Domain {
28 INET, ///< Address family for IPv4
29};
30
31/// Socket types
32enum class Type {
33 STREAM,
34 DGRAM,
35 RAW,
36 SEQPACKET,
37};
38
39/// Protocol values for sockets
40enum class Protocol {
41 ICMP,
42 TCP,
43 UDP,
44};
45
46/// Shutdown mode
47enum class ShutdownHow {
48 RD,
49 WR,
50 RDWR,
51};
52
53/// Array of IPv4 address
54using IPv4Address = std::array<u8, 4>;
55
56/// Cross-platform sockaddr structure
57struct SockAddrIn {
58 Domain family;
59 IPv4Address ip;
60 u16 portno;
61};
62
63/// Cross-platform poll fd structure
64struct PollFD {
65 Socket* socket;
66 u16 events;
67 u16 revents;
68};
69
70constexpr u16 POLL_IN = 1 << 0;
71constexpr u16 POLL_PRI = 1 << 1;
72constexpr u16 POLL_OUT = 1 << 2;
73constexpr u16 POLL_ERR = 1 << 3;
74constexpr u16 POLL_HUP = 1 << 4;
75constexpr u16 POLL_NVAL = 1 << 5;
76
77class NetworkInstance {
78public:
79 explicit NetworkInstance();
80 ~NetworkInstance();
81};
82
83/// @brief Returns host's IPv4 address
84/// @return Pair of an array of human ordered IPv4 address (e.g. 192.168.0.1) and an error code
85std::pair<IPv4Address, Errno> GetHostIPv4Address();
86
87} // namespace Network
diff --git a/src/core/network/sockets.h b/src/core/network/sockets.h
new file mode 100644
index 000000000..7bdff0fe4
--- /dev/null
+++ b/src/core/network/sockets.h
@@ -0,0 +1,94 @@
1// Copyright 2020 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <memory>
8#include <utility>
9
10#if defined(_WIN32)
11#include <winsock.h>
12#elif !defined(__unix__)
13#error "Platform not implemented"
14#endif
15
16#include "common/common_types.h"
17#include "core/network/network.h"
18
19// TODO: C++20 Replace std::vector usages with std::span
20
21namespace Network {
22
23class Socket {
24public:
25 struct AcceptResult {
26 std::unique_ptr<Socket> socket;
27 SockAddrIn sockaddr_in;
28 };
29
30 explicit Socket() = default;
31 ~Socket();
32
33 Socket(const Socket&) = delete;
34 Socket& operator=(const Socket&) = delete;
35
36 Socket(Socket&& rhs) noexcept;
37
38 // Avoid closing sockets implicitly
39 Socket& operator=(Socket&&) noexcept = delete;
40
41 Errno Initialize(Domain domain, Type type, Protocol protocol);
42
43 Errno Close();
44
45 std::pair<AcceptResult, Errno> Accept();
46
47 Errno Connect(SockAddrIn addr_in);
48
49 std::pair<SockAddrIn, Errno> GetPeerName();
50
51 std::pair<SockAddrIn, Errno> GetSockName();
52
53 Errno Bind(SockAddrIn addr);
54
55 Errno Listen(s32 backlog);
56
57 Errno Shutdown(ShutdownHow how);
58
59 std::pair<s32, Errno> Recv(int flags, std::vector<u8>& message);
60
61 std::pair<s32, Errno> RecvFrom(int flags, std::vector<u8>& message, SockAddrIn* addr);
62
63 std::pair<s32, Errno> Send(const std::vector<u8>& message, int flags);
64
65 std::pair<s32, Errno> SendTo(u32 flags, const std::vector<u8>& message, const SockAddrIn* addr);
66
67 Errno SetLinger(bool enable, u32 linger);
68
69 Errno SetReuseAddr(bool enable);
70
71 Errno SetBroadcast(bool enable);
72
73 Errno SetSndBuf(u32 value);
74
75 Errno SetRcvBuf(u32 value);
76
77 Errno SetSndTimeo(u32 value);
78
79 Errno SetRcvTimeo(u32 value);
80
81 Errno SetNonBlock(bool enable);
82
83 bool IsOpened() const;
84
85#if defined(_WIN32)
86 SOCKET fd = INVALID_SOCKET;
87#elif defined(__unix__)
88 int fd = -1;
89#endif
90};
91
92std::pair<s32, Errno> Poll(std::vector<PollFD>& poll_fds, s32 timeout);
93
94} // namespace Network
diff --git a/src/core/settings.cpp b/src/core/settings.cpp
index d3886c4ec..44252dd81 100644
--- a/src/core/settings.cpp
+++ b/src/core/settings.cpp
@@ -2,6 +2,8 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <string_view>
6
5#include "common/file_util.h" 7#include "common/file_util.h"
6#include "core/core.h" 8#include "core/core.h"
7#include "core/gdbstub/gdbstub.h" 9#include "core/gdbstub/gdbstub.h"
@@ -65,18 +67,18 @@ Values values = {};
65bool configuring_global = true; 67bool configuring_global = true;
66 68
67std::string GetTimeZoneString() { 69std::string GetTimeZoneString() {
68 static constexpr std::array<const char*, 46> timezones{{ 70 static constexpr std::array timezones{
69 "auto", "default", "CET", "CST6CDT", "Cuba", "EET", "Egypt", "Eire", 71 "auto", "default", "CET", "CST6CDT", "Cuba", "EET", "Egypt", "Eire",
70 "EST", "EST5EDT", "GB", "GB-Eire", "GMT", "GMT+0", "GMT-0", "GMT0", 72 "EST", "EST5EDT", "GB", "GB-Eire", "GMT", "GMT+0", "GMT-0", "GMT0",
71 "Greenwich", "Hongkong", "HST", "Iceland", "Iran", "Israel", "Jamaica", "Japan", 73 "Greenwich", "Hongkong", "HST", "Iceland", "Iran", "Israel", "Jamaica", "Japan",
72 "Kwajalein", "Libya", "MET", "MST", "MST7MDT", "Navajo", "NZ", "NZ-CHAT", 74 "Kwajalein", "Libya", "MET", "MST", "MST7MDT", "Navajo", "NZ", "NZ-CHAT",
73 "Poland", "Portugal", "PRC", "PST8PDT", "ROC", "ROK", "Singapore", "Turkey", 75 "Poland", "Portugal", "PRC", "PST8PDT", "ROC", "ROK", "Singapore", "Turkey",
74 "UCT", "Universal", "UTC", "W-SU", "WET", "Zulu", 76 "UCT", "Universal", "UTC", "W-SU", "WET", "Zulu",
75 }}; 77 };
76
77 ASSERT(Settings::values.time_zone_index.GetValue() < timezones.size());
78 78
79 return timezones[Settings::values.time_zone_index.GetValue()]; 79 const auto time_zone_index = static_cast<std::size_t>(values.time_zone_index.GetValue());
80 ASSERT(time_zone_index < timezones.size());
81 return timezones[time_zone_index];
80} 82}
81 83
82void Apply() { 84void Apply() {
@@ -91,41 +93,41 @@ void Apply() {
91 Service::HID::ReloadInputDevices(); 93 Service::HID::ReloadInputDevices();
92} 94}
93 95
94template <typename T>
95void LogSetting(const std::string& name, const T& value) {
96 LOG_INFO(Config, "{}: {}", name, value);
97}
98
99void LogSettings() { 96void LogSettings() {
97 const auto log_setting = [](std::string_view name, const auto& value) {
98 LOG_INFO(Config, "{}: {}", name, value);
99 };
100
100 LOG_INFO(Config, "yuzu Configuration:"); 101 LOG_INFO(Config, "yuzu Configuration:");
101 LogSetting("Controls_UseDockedMode", Settings::values.use_docked_mode); 102 log_setting("Controls_UseDockedMode", values.use_docked_mode);
102 LogSetting("System_RngSeed", Settings::values.rng_seed.GetValue().value_or(0)); 103 log_setting("System_RngSeed", values.rng_seed.GetValue().value_or(0));
103 LogSetting("System_CurrentUser", Settings::values.current_user); 104 log_setting("System_CurrentUser", values.current_user);
104 LogSetting("System_LanguageIndex", Settings::values.language_index.GetValue()); 105 log_setting("System_LanguageIndex", values.language_index.GetValue());
105 LogSetting("System_RegionIndex", Settings::values.region_index.GetValue()); 106 log_setting("System_RegionIndex", values.region_index.GetValue());
106 LogSetting("System_TimeZoneIndex", Settings::values.time_zone_index.GetValue()); 107 log_setting("System_TimeZoneIndex", values.time_zone_index.GetValue());
107 LogSetting("Core_UseMultiCore", Settings::values.use_multi_core.GetValue()); 108 log_setting("Core_UseMultiCore", values.use_multi_core.GetValue());
108 LogSetting("Renderer_UseResolutionFactor", Settings::values.resolution_factor.GetValue()); 109 log_setting("Renderer_UseResolutionFactor", values.resolution_factor.GetValue());
109 LogSetting("Renderer_UseFrameLimit", Settings::values.use_frame_limit.GetValue()); 110 log_setting("Renderer_UseFrameLimit", values.use_frame_limit.GetValue());
110 LogSetting("Renderer_FrameLimit", Settings::values.frame_limit.GetValue()); 111 log_setting("Renderer_FrameLimit", values.frame_limit.GetValue());
111 LogSetting("Renderer_UseDiskShaderCache", Settings::values.use_disk_shader_cache.GetValue()); 112 log_setting("Renderer_UseDiskShaderCache", values.use_disk_shader_cache.GetValue());
112 LogSetting("Renderer_GPUAccuracyLevel", Settings::values.gpu_accuracy.GetValue()); 113 log_setting("Renderer_GPUAccuracyLevel", values.gpu_accuracy.GetValue());
113 LogSetting("Renderer_UseAsynchronousGpuEmulation", 114 log_setting("Renderer_UseAsynchronousGpuEmulation",
114 Settings::values.use_asynchronous_gpu_emulation.GetValue()); 115 values.use_asynchronous_gpu_emulation.GetValue());
115 LogSetting("Renderer_UseVsync", Settings::values.use_vsync.GetValue()); 116 log_setting("Renderer_UseVsync", values.use_vsync.GetValue());
116 LogSetting("Renderer_UseAssemblyShaders", Settings::values.use_assembly_shaders.GetValue()); 117 log_setting("Renderer_UseAssemblyShaders", values.use_assembly_shaders.GetValue());
117 LogSetting("Renderer_AnisotropicFilteringLevel", Settings::values.max_anisotropy.GetValue()); 118 log_setting("Renderer_UseAsynchronousShaders", values.use_asynchronous_shaders.GetValue());
118 LogSetting("Audio_OutputEngine", Settings::values.sink_id); 119 log_setting("Renderer_AnisotropicFilteringLevel", values.max_anisotropy.GetValue());
119 LogSetting("Audio_EnableAudioStretching", Settings::values.enable_audio_stretching.GetValue()); 120 log_setting("Audio_OutputEngine", values.sink_id);
120 LogSetting("Audio_OutputDevice", Settings::values.audio_device_id); 121 log_setting("Audio_EnableAudioStretching", values.enable_audio_stretching.GetValue());
121 LogSetting("DataStorage_UseVirtualSd", Settings::values.use_virtual_sd); 122 log_setting("Audio_OutputDevice", values.audio_device_id);
122 LogSetting("DataStorage_NandDir", FileUtil::GetUserPath(FileUtil::UserPath::NANDDir)); 123 log_setting("DataStorage_UseVirtualSd", values.use_virtual_sd);
123 LogSetting("DataStorage_SdmcDir", FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir)); 124 log_setting("DataStorage_NandDir", FileUtil::GetUserPath(FileUtil::UserPath::NANDDir));
124 LogSetting("Debugging_UseGdbstub", Settings::values.use_gdbstub); 125 log_setting("DataStorage_SdmcDir", FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir));
125 LogSetting("Debugging_GdbstubPort", Settings::values.gdbstub_port); 126 log_setting("Debugging_UseGdbstub", values.use_gdbstub);
126 LogSetting("Debugging_ProgramArgs", Settings::values.program_args); 127 log_setting("Debugging_GdbstubPort", values.gdbstub_port);
127 LogSetting("Services_BCATBackend", Settings::values.bcat_backend); 128 log_setting("Debugging_ProgramArgs", values.program_args);
128 LogSetting("Services_BCATBoxcatLocal", Settings::values.bcat_boxcat_local); 129 log_setting("Services_BCATBackend", values.bcat_backend);
130 log_setting("Services_BCATBoxcatLocal", values.bcat_boxcat_local);
129} 131}
130 132
131float Volume() { 133float Volume() {
@@ -169,6 +171,7 @@ void RestoreGlobalState() {
169 values.use_asynchronous_gpu_emulation.SetGlobal(true); 171 values.use_asynchronous_gpu_emulation.SetGlobal(true);
170 values.use_vsync.SetGlobal(true); 172 values.use_vsync.SetGlobal(true);
171 values.use_assembly_shaders.SetGlobal(true); 173 values.use_assembly_shaders.SetGlobal(true);
174 values.use_asynchronous_shaders.SetGlobal(true);
172 values.use_fast_gpu_time.SetGlobal(true); 175 values.use_fast_gpu_time.SetGlobal(true);
173 values.force_30fps_mode.SetGlobal(true); 176 values.force_30fps_mode.SetGlobal(true);
174 values.bg_red.SetGlobal(true); 177 values.bg_red.SetGlobal(true);
@@ -184,4 +187,9 @@ void RestoreGlobalState() {
184 values.sound_index.SetGlobal(true); 187 values.sound_index.SetGlobal(true);
185} 188}
186 189
190void Sanitize() {
191 values.use_asynchronous_gpu_emulation.SetValue(
192 values.use_asynchronous_gpu_emulation.GetValue() || values.use_multi_core.GetValue());
193}
194
187} // namespace Settings 195} // namespace Settings
diff --git a/src/core/settings.h b/src/core/settings.h
index 3eb336f75..386233fdf 100644
--- a/src/core/settings.h
+++ b/src/core/settings.h
@@ -434,6 +434,7 @@ struct Values {
434 Setting<bool> use_asynchronous_gpu_emulation; 434 Setting<bool> use_asynchronous_gpu_emulation;
435 Setting<bool> use_vsync; 435 Setting<bool> use_vsync;
436 Setting<bool> use_assembly_shaders; 436 Setting<bool> use_assembly_shaders;
437 Setting<bool> use_asynchronous_shaders;
437 Setting<bool> force_30fps_mode; 438 Setting<bool> force_30fps_mode;
438 Setting<bool> use_fast_gpu_time; 439 Setting<bool> use_fast_gpu_time;
439 440
@@ -526,4 +527,7 @@ void LogSettings();
526// Restore the global state of all applicable settings in the Values struct 527// Restore the global state of all applicable settings in the Values struct
527void RestoreGlobalState(); 528void RestoreGlobalState();
528 529
530// Fixes settings that are known to cause issues with the emulator
531void Sanitize();
532
529} // namespace Settings 533} // namespace Settings
diff --git a/src/core/telemetry_session.cpp b/src/core/telemetry_session.cpp
index 78915e6db..5a30c75da 100644
--- a/src/core/telemetry_session.cpp
+++ b/src/core/telemetry_session.cpp
@@ -207,6 +207,8 @@ void TelemetrySession::AddInitialInfo(Loader::AppLoader& app_loader) {
207 AddField(field_type, "Renderer_UseVsync", Settings::values.use_vsync.GetValue()); 207 AddField(field_type, "Renderer_UseVsync", Settings::values.use_vsync.GetValue());
208 AddField(field_type, "Renderer_UseAssemblyShaders", 208 AddField(field_type, "Renderer_UseAssemblyShaders",
209 Settings::values.use_assembly_shaders.GetValue()); 209 Settings::values.use_assembly_shaders.GetValue());
210 AddField(field_type, "Renderer_UseAsynchronousShaders",
211 Settings::values.use_asynchronous_shaders.GetValue());
210 AddField(field_type, "System_UseDockedMode", Settings::values.use_docked_mode); 212 AddField(field_type, "System_UseDockedMode", Settings::values.use_docked_mode);
211} 213}
212 214
diff --git a/src/core/tools/freezer.cpp b/src/core/tools/freezer.cpp
index 8b0c50d11..27b894b51 100644
--- a/src/core/tools/freezer.cpp
+++ b/src/core/tools/freezer.cpp
@@ -14,7 +14,7 @@
14namespace Tools { 14namespace Tools {
15namespace { 15namespace {
16 16
17constexpr s64 MEMORY_FREEZER_TICKS = static_cast<s64>(1000000000 / 60); 17constexpr auto memory_freezer_ns = std::chrono::nanoseconds{1000000000 / 60};
18 18
19u64 MemoryReadWidth(Core::Memory::Memory& memory, u32 width, VAddr addr) { 19u64 MemoryReadWidth(Core::Memory::Memory& memory, u32 width, VAddr addr) {
20 switch (width) { 20 switch (width) {
@@ -55,10 +55,11 @@ void MemoryWriteWidth(Core::Memory::Memory& memory, u32 width, VAddr addr, u64 v
55 55
56Freezer::Freezer(Core::Timing::CoreTiming& core_timing_, Core::Memory::Memory& memory_) 56Freezer::Freezer(Core::Timing::CoreTiming& core_timing_, Core::Memory::Memory& memory_)
57 : core_timing{core_timing_}, memory{memory_} { 57 : core_timing{core_timing_}, memory{memory_} {
58 event = Core::Timing::CreateEvent( 58 event = Core::Timing::CreateEvent("MemoryFreezer::FrameCallback",
59 "MemoryFreezer::FrameCallback", 59 [this](u64 userdata, std::chrono::nanoseconds ns_late) {
60 [this](u64 userdata, s64 ns_late) { FrameCallback(userdata, ns_late); }); 60 FrameCallback(userdata, ns_late);
61 core_timing.ScheduleEvent(MEMORY_FREEZER_TICKS, event); 61 });
62 core_timing.ScheduleEvent(memory_freezer_ns, event);
62} 63}
63 64
64Freezer::~Freezer() { 65Freezer::~Freezer() {
@@ -68,7 +69,7 @@ Freezer::~Freezer() {
68void Freezer::SetActive(bool active) { 69void Freezer::SetActive(bool active) {
69 if (!this->active.exchange(active)) { 70 if (!this->active.exchange(active)) {
70 FillEntryReads(); 71 FillEntryReads();
71 core_timing.ScheduleEvent(MEMORY_FREEZER_TICKS, event); 72 core_timing.ScheduleEvent(memory_freezer_ns, event);
72 LOG_DEBUG(Common_Memory, "Memory freezer activated!"); 73 LOG_DEBUG(Common_Memory, "Memory freezer activated!");
73 } else { 74 } else {
74 LOG_DEBUG(Common_Memory, "Memory freezer deactivated!"); 75 LOG_DEBUG(Common_Memory, "Memory freezer deactivated!");
@@ -158,7 +159,7 @@ std::vector<Freezer::Entry> Freezer::GetEntries() const {
158 return entries; 159 return entries;
159} 160}
160 161
161void Freezer::FrameCallback(u64 userdata, s64 ns_late) { 162void Freezer::FrameCallback(u64, std::chrono::nanoseconds ns_late) {
162 if (!IsActive()) { 163 if (!IsActive()) {
163 LOG_DEBUG(Common_Memory, "Memory freezer has been deactivated, ending callback events."); 164 LOG_DEBUG(Common_Memory, "Memory freezer has been deactivated, ending callback events.");
164 return; 165 return;
@@ -173,7 +174,7 @@ void Freezer::FrameCallback(u64 userdata, s64 ns_late) {
173 MemoryWriteWidth(memory, entry.width, entry.address, entry.value); 174 MemoryWriteWidth(memory, entry.width, entry.address, entry.value);
174 } 175 }
175 176
176 core_timing.ScheduleEvent(MEMORY_FREEZER_TICKS - ns_late, event); 177 core_timing.ScheduleEvent(memory_freezer_ns - ns_late, event);
177} 178}
178 179
179void Freezer::FillEntryReads() { 180void Freezer::FillEntryReads() {
diff --git a/src/core/tools/freezer.h b/src/core/tools/freezer.h
index 62fc6aa6c..8438783d5 100644
--- a/src/core/tools/freezer.h
+++ b/src/core/tools/freezer.h
@@ -5,6 +5,7 @@
5#pragma once 5#pragma once
6 6
7#include <atomic> 7#include <atomic>
8#include <chrono>
8#include <memory> 9#include <memory>
9#include <mutex> 10#include <mutex>
10#include <optional> 11#include <optional>
@@ -72,7 +73,7 @@ public:
72 std::vector<Entry> GetEntries() const; 73 std::vector<Entry> GetEntries() const;
73 74
74private: 75private:
75 void FrameCallback(u64 userdata, s64 cycles_late); 76 void FrameCallback(u64 userdata, std::chrono::nanoseconds ns_late);
76 void FillEntryReads(); 77 void FillEntryReads();
77 78
78 std::atomic_bool active{false}; 79 std::atomic_bool active{false};
diff --git a/src/input_common/gcadapter/gc_adapter.cpp b/src/input_common/gcadapter/gc_adapter.cpp
index 38210ffcb..02d06876f 100644
--- a/src/input_common/gcadapter/gc_adapter.cpp
+++ b/src/input_common/gcadapter/gc_adapter.cpp
@@ -24,11 +24,9 @@ Adapter::Adapter() {
24 } 24 }
25 LOG_INFO(Input, "GC Adapter Initialization started"); 25 LOG_INFO(Input, "GC Adapter Initialization started");
26 26
27 current_status = NO_ADAPTER_DETECTED;
28
29 const int init_res = libusb_init(&libusb_ctx); 27 const int init_res = libusb_init(&libusb_ctx);
30 if (init_res == LIBUSB_SUCCESS) { 28 if (init_res == LIBUSB_SUCCESS) {
31 StartScanThread(); 29 Setup();
32 } else { 30 } else {
33 LOG_ERROR(Input, "libusb could not be initialized. failed with error = {}", init_res); 31 LOG_ERROR(Input, "libusb could not be initialized. failed with error = {}", init_res);
34 } 32 }
@@ -36,14 +34,9 @@ Adapter::Adapter() {
36 34
37GCPadStatus Adapter::GetPadStatus(std::size_t port, const std::array<u8, 37>& adapter_payload) { 35GCPadStatus Adapter::GetPadStatus(std::size_t port, const std::array<u8, 37>& adapter_payload) {
38 GCPadStatus pad = {}; 36 GCPadStatus pad = {};
39 bool get_origin = false; 37 const std::size_t offset = 1 + (9 * port);
40
41 ControllerTypes type = ControllerTypes(adapter_payload[1 + (9 * port)] >> 4);
42 if (type != ControllerTypes::None) {
43 get_origin = true;
44 }
45 38
46 adapter_controllers_status[port] = type; 39 adapter_controllers_status[port] = static_cast<ControllerTypes>(adapter_payload[offset] >> 4);
47 40
48 static constexpr std::array<PadButton, 8> b1_buttons{ 41 static constexpr std::array<PadButton, 8> b1_buttons{
49 PadButton::PAD_BUTTON_A, PadButton::PAD_BUTTON_B, PadButton::PAD_BUTTON_X, 42 PadButton::PAD_BUTTON_A, PadButton::PAD_BUTTON_B, PadButton::PAD_BUTTON_X,
@@ -58,9 +51,19 @@ GCPadStatus Adapter::GetPadStatus(std::size_t port, const std::array<u8, 37>& ad
58 PadButton::PAD_TRIGGER_L, 51 PadButton::PAD_TRIGGER_L,
59 }; 52 };
60 53
54 static constexpr std::array<PadAxes, 6> axes{
55 PadAxes::StickX, PadAxes::StickY, PadAxes::SubstickX,
56 PadAxes::SubstickY, PadAxes::TriggerLeft, PadAxes::TriggerRight,
57 };
58
59 if (adapter_controllers_status[port] == ControllerTypes::None && !get_origin[port]) {
60 // Controller may have been disconnected, recalibrate if reconnected.
61 get_origin[port] = true;
62 }
63
61 if (adapter_controllers_status[port] != ControllerTypes::None) { 64 if (adapter_controllers_status[port] != ControllerTypes::None) {
62 const u8 b1 = adapter_payload[1 + (9 * port) + 1]; 65 const u8 b1 = adapter_payload[offset + 1];
63 const u8 b2 = adapter_payload[1 + (9 * port) + 2]; 66 const u8 b2 = adapter_payload[offset + 2];
64 67
65 for (std::size_t i = 0; i < b1_buttons.size(); ++i) { 68 for (std::size_t i = 0; i < b1_buttons.size(); ++i) {
66 if ((b1 & (1U << i)) != 0) { 69 if ((b1 & (1U << i)) != 0) {
@@ -73,17 +76,15 @@ GCPadStatus Adapter::GetPadStatus(std::size_t port, const std::array<u8, 37>& ad
73 pad.button |= static_cast<u16>(b2_buttons[j]); 76 pad.button |= static_cast<u16>(b2_buttons[j]);
74 } 77 }
75 } 78 }
76 79 for (PadAxes axis : axes) {
77 if (get_origin) { 80 const std::size_t index = static_cast<std::size_t>(axis);
78 pad.button |= PAD_GET_ORIGIN; 81 pad.axis_values[index] = adapter_payload[offset + 3 + index];
79 } 82 }
80 83
81 pad.stick_x = adapter_payload[1 + (9 * port) + 3]; 84 if (get_origin[port]) {
82 pad.stick_y = adapter_payload[1 + (9 * port) + 4]; 85 origin_status[port].axis_values = pad.axis_values;
83 pad.substick_x = adapter_payload[1 + (9 * port) + 5]; 86 get_origin[port] = false;
84 pad.substick_y = adapter_payload[1 + (9 * port) + 6]; 87 }
85 pad.trigger_left = adapter_payload[1 + (9 * port) + 7];
86 pad.trigger_right = adapter_payload[1 + (9 * port) + 8];
87 } 88 }
88 return pad; 89 return pad;
89} 90}
@@ -94,82 +95,47 @@ void Adapter::PadToState(const GCPadStatus& pad, GCState& state) {
94 state.buttons.insert_or_assign(button_value, pad.button & button_value); 95 state.buttons.insert_or_assign(button_value, pad.button & button_value);
95 } 96 }
96 97
97 state.axes.insert_or_assign(static_cast<u8>(PadAxes::StickX), pad.stick_x); 98 for (size_t i = 0; i < pad.axis_values.size(); ++i) {
98 state.axes.insert_or_assign(static_cast<u8>(PadAxes::StickY), pad.stick_y); 99 state.axes.insert_or_assign(static_cast<u8>(i), pad.axis_values[i]);
99 state.axes.insert_or_assign(static_cast<u8>(PadAxes::SubstickX), pad.substick_x); 100 }
100 state.axes.insert_or_assign(static_cast<u8>(PadAxes::SubstickY), pad.substick_y);
101 state.axes.insert_or_assign(static_cast<u8>(PadAxes::TriggerLeft), pad.trigger_left);
102 state.axes.insert_or_assign(static_cast<u8>(PadAxes::TriggerRight), pad.trigger_right);
103} 101}
104 102
105void Adapter::Read() { 103void Adapter::Read() {
106 LOG_DEBUG(Input, "GC Adapter Read() thread started"); 104 LOG_DEBUG(Input, "GC Adapter Read() thread started");
107 105
108 int payload_size_in, payload_size_copy; 106 int payload_size;
109 std::array<u8, 37> adapter_payload; 107 std::array<u8, 37> adapter_payload;
110 std::array<u8, 37> adapter_payload_copy;
111 std::array<GCPadStatus, 4> pads; 108 std::array<GCPadStatus, 4> pads;
112 109
113 while (adapter_thread_running) { 110 while (adapter_thread_running) {
114 libusb_interrupt_transfer(usb_adapter_handle, input_endpoint, adapter_payload.data(), 111 libusb_interrupt_transfer(usb_adapter_handle, input_endpoint, adapter_payload.data(),
115 sizeof(adapter_payload), &payload_size_in, 16); 112 sizeof(adapter_payload), &payload_size, 16);
116 payload_size_copy = 0;
117 // this mutex might be redundant?
118 {
119 std::lock_guard<std::mutex> lk(s_mutex);
120 std::copy(std::begin(adapter_payload), std::end(adapter_payload),
121 std::begin(adapter_payload_copy));
122 payload_size_copy = payload_size_in;
123 }
124 113
125 if (payload_size_copy != sizeof(adapter_payload_copy) || 114 if (payload_size != sizeof(adapter_payload) || adapter_payload[0] != LIBUSB_DT_HID) {
126 adapter_payload_copy[0] != LIBUSB_DT_HID) { 115 LOG_ERROR(Input,
127 LOG_ERROR(Input, "error reading payload (size: {}, type: {:02x})", payload_size_copy, 116 "Error reading payload (size: {}, type: {:02x}) Is the adapter connected?",
128 adapter_payload_copy[0]); 117 payload_size, adapter_payload[0]);
129 adapter_thread_running = false; // error reading from adapter, stop reading. 118 adapter_thread_running = false; // error reading from adapter, stop reading.
130 break; 119 break;
131 } 120 }
132 for (std::size_t port = 0; port < pads.size(); ++port) { 121 for (std::size_t port = 0; port < pads.size(); ++port) {
133 pads[port] = GetPadStatus(port, adapter_payload_copy); 122 pads[port] = GetPadStatus(port, adapter_payload);
134 if (DeviceConnected(port) && configuring) { 123 if (DeviceConnected(port) && configuring) {
135 if (pads[port].button != PAD_GET_ORIGIN) { 124 if (pads[port].button != 0) {
136 pad_queue[port].Push(pads[port]); 125 pad_queue[port].Push(pads[port]);
137 } 126 }
138 127
139 // Accounting for a threshold here because of some controller variance 128 // Accounting for a threshold here to ensure an intentional press
140 if (pads[port].stick_x > pads[port].MAIN_STICK_CENTER_X + pads[port].THRESHOLD || 129 for (size_t i = 0; i < pads[port].axis_values.size(); ++i) {
141 pads[port].stick_x < pads[port].MAIN_STICK_CENTER_X - pads[port].THRESHOLD) { 130 const u8 value = pads[port].axis_values[i];
142 pads[port].axis = GCAdapter::PadAxes::StickX; 131 const u8 origin = origin_status[port].axis_values[i];
143 pads[port].axis_value = pads[port].stick_x; 132
144 pad_queue[port].Push(pads[port]); 133 if (value > origin + pads[port].THRESHOLD ||
145 } 134 value < origin - pads[port].THRESHOLD) {
146 if (pads[port].stick_y > pads[port].MAIN_STICK_CENTER_Y + pads[port].THRESHOLD || 135 pads[port].axis = static_cast<PadAxes>(i);
147 pads[port].stick_y < pads[port].MAIN_STICK_CENTER_Y - pads[port].THRESHOLD) { 136 pads[port].axis_value = pads[port].axis_values[i];
148 pads[port].axis = GCAdapter::PadAxes::StickY; 137 pad_queue[port].Push(pads[port]);
149 pads[port].axis_value = pads[port].stick_y; 138 }
150 pad_queue[port].Push(pads[port]);
151 }
152 if (pads[port].substick_x > pads[port].C_STICK_CENTER_X + pads[port].THRESHOLD ||
153 pads[port].substick_x < pads[port].C_STICK_CENTER_X - pads[port].THRESHOLD) {
154 pads[port].axis = GCAdapter::PadAxes::SubstickX;
155 pads[port].axis_value = pads[port].substick_x;
156 pad_queue[port].Push(pads[port]);
157 }
158 if (pads[port].substick_y > pads[port].C_STICK_CENTER_Y + pads[port].THRESHOLD ||
159 pads[port].substick_y < pads[port].C_STICK_CENTER_Y - pads[port].THRESHOLD) {
160 pads[port].axis = GCAdapter::PadAxes::SubstickY;
161 pads[port].axis_value = pads[port].substick_y;
162 pad_queue[port].Push(pads[port]);
163 }
164 if (pads[port].trigger_left > pads[port].TRIGGER_THRESHOLD) {
165 pads[port].axis = GCAdapter::PadAxes::TriggerLeft;
166 pads[port].axis_value = pads[port].trigger_left;
167 pad_queue[port].Push(pads[port]);
168 }
169 if (pads[port].trigger_right > pads[port].TRIGGER_THRESHOLD) {
170 pads[port].axis = GCAdapter::PadAxes::TriggerRight;
171 pads[port].axis_value = pads[port].trigger_right;
172 pad_queue[port].Push(pads[port]);
173 } 139 }
174 } 140 }
175 PadToState(pads[port], state[port]); 141 PadToState(pads[port], state[port]);
@@ -178,42 +144,11 @@ void Adapter::Read() {
178 } 144 }
179} 145}
180 146
181void Adapter::ScanThreadFunc() {
182 LOG_INFO(Input, "GC Adapter scanning thread started");
183
184 while (detect_thread_running) {
185 if (usb_adapter_handle == nullptr) {
186 std::lock_guard<std::mutex> lk(initialization_mutex);
187 Setup();
188 }
189 std::this_thread::sleep_for(std::chrono::milliseconds(500));
190 }
191}
192
193void Adapter::StartScanThread() {
194 if (detect_thread_running) {
195 return;
196 }
197 if (!libusb_ctx) {
198 return;
199 }
200
201 detect_thread_running = true;
202 detect_thread = std::thread(&Adapter::ScanThreadFunc, this);
203}
204
205void Adapter::StopScanThread() {
206 detect_thread_running = false;
207 detect_thread.join();
208}
209
210void Adapter::Setup() { 147void Adapter::Setup() {
211 // Reset the error status in case the adapter gets unplugged 148 // Initialize all controllers as unplugged
212 if (current_status < 0) {
213 current_status = NO_ADAPTER_DETECTED;
214 }
215
216 adapter_controllers_status.fill(ControllerTypes::None); 149 adapter_controllers_status.fill(ControllerTypes::None);
150 // Initialize all ports to store axis origin values
151 get_origin.fill(true);
217 152
218 // pointer to list of connected usb devices 153 // pointer to list of connected usb devices
219 libusb_device** devices{}; 154 libusb_device** devices{};
@@ -222,8 +157,6 @@ void Adapter::Setup() {
222 const ssize_t device_count = libusb_get_device_list(libusb_ctx, &devices); 157 const ssize_t device_count = libusb_get_device_list(libusb_ctx, &devices);
223 if (device_count < 0) { 158 if (device_count < 0) {
224 LOG_ERROR(Input, "libusb_get_device_list failed with error: {}", device_count); 159 LOG_ERROR(Input, "libusb_get_device_list failed with error: {}", device_count);
225 detect_thread_running = false; // Stop the loop constantly checking for gc adapter
226 // TODO: For hotplug+gc adapter checkbox implementation, revert this.
227 return; 160 return;
228 } 161 }
229 162
@@ -321,31 +254,21 @@ void Adapter::GetGCEndpoint(libusb_device* device) {
321 sizeof(clear_payload), nullptr, 16); 254 sizeof(clear_payload), nullptr, 16);
322 255
323 adapter_thread_running = true; 256 adapter_thread_running = true;
324 current_status = ADAPTER_DETECTED;
325 adapter_input_thread = std::thread([=] { Read(); }); // Read input 257 adapter_input_thread = std::thread([=] { Read(); }); // Read input
326} 258}
327 259
328Adapter::~Adapter() { 260Adapter::~Adapter() {
329 StopScanThread();
330 Reset(); 261 Reset();
331} 262}
332 263
333void Adapter::Reset() { 264void Adapter::Reset() {
334 std::unique_lock<std::mutex> lock(initialization_mutex, std::defer_lock);
335 if (!lock.try_lock()) {
336 return;
337 }
338 if (current_status != ADAPTER_DETECTED) {
339 return;
340 }
341
342 if (adapter_thread_running) { 265 if (adapter_thread_running) {
343 adapter_thread_running = false; 266 adapter_thread_running = false;
344 } 267 }
345 adapter_input_thread.join(); 268 adapter_input_thread.join();
346 269
347 adapter_controllers_status.fill(ControllerTypes::None); 270 adapter_controllers_status.fill(ControllerTypes::None);
348 current_status = NO_ADAPTER_DETECTED; 271 get_origin.fill(true);
349 272
350 if (usb_adapter_handle) { 273 if (usb_adapter_handle) {
351 libusb_release_interface(usb_adapter_handle, 1); 274 libusb_release_interface(usb_adapter_handle, 1);
@@ -367,6 +290,7 @@ void Adapter::ResetDeviceType(std::size_t port) {
367} 290}
368 291
369void Adapter::BeginConfiguration() { 292void Adapter::BeginConfiguration() {
293 get_origin.fill(true);
370 for (auto& pq : pad_queue) { 294 for (auto& pq : pad_queue) {
371 pq.Clear(); 295 pq.Clear();
372 } 296 }
@@ -396,4 +320,8 @@ const std::array<GCState, 4>& Adapter::GetPadState() const {
396 return state; 320 return state;
397} 321}
398 322
323int Adapter::GetOriginValue(int port, int axis) const {
324 return origin_status[port].axis_values[axis];
325}
326
399} // namespace GCAdapter 327} // namespace GCAdapter
diff --git a/src/input_common/gcadapter/gc_adapter.h b/src/input_common/gcadapter/gc_adapter.h
index e2cdd6255..bed81915c 100644
--- a/src/input_common/gcadapter/gc_adapter.h
+++ b/src/input_common/gcadapter/gc_adapter.h
@@ -17,12 +17,6 @@ struct libusb_device_handle;
17 17
18namespace GCAdapter { 18namespace GCAdapter {
19 19
20enum {
21 PAD_USE_ORIGIN = 0x0080,
22 PAD_GET_ORIGIN = 0x2000,
23 PAD_ERR_STATUS = 0x8000,
24};
25
26enum class PadButton { 20enum class PadButton {
27 PAD_BUTTON_LEFT = 0x0001, 21 PAD_BUTTON_LEFT = 0x0001,
28 PAD_BUTTON_RIGHT = 0x0002, 22 PAD_BUTTON_RIGHT = 0x0002,
@@ -53,24 +47,10 @@ enum class PadAxes : u8 {
53}; 47};
54 48
55struct GCPadStatus { 49struct GCPadStatus {
56 u16 button{}; // Or-ed PAD_BUTTON_* and PAD_TRIGGER_* bits 50 u16 button{}; // Or-ed PAD_BUTTON_* and PAD_TRIGGER_* bits
57 u8 stick_x{}; // 0 <= stick_x <= 255 51
58 u8 stick_y{}; // 0 <= stick_y <= 255 52 std::array<u8, 6> axis_values{}; // Triggers and sticks, following indices defined in PadAxes
59 u8 substick_x{}; // 0 <= substick_x <= 255 53 static constexpr u8 THRESHOLD = 50; // Threshold for axis press for polling
60 u8 substick_y{}; // 0 <= substick_y <= 255
61 u8 trigger_left{}; // 0 <= trigger_left <= 255
62 u8 trigger_right{}; // 0 <= trigger_right <= 255
63
64 static constexpr u8 MAIN_STICK_CENTER_X = 0x80;
65 static constexpr u8 MAIN_STICK_CENTER_Y = 0x80;
66 static constexpr u8 MAIN_STICK_RADIUS = 0x7f;
67 static constexpr u8 C_STICK_CENTER_X = 0x80;
68 static constexpr u8 C_STICK_CENTER_Y = 0x80;
69 static constexpr u8 C_STICK_RADIUS = 0x7f;
70 static constexpr u8 THRESHOLD = 10;
71
72 // 256/4, at least a quarter press to count as a press. For polling mostly
73 static constexpr u8 TRIGGER_THRESHOLD = 64;
74 54
75 u8 port{}; 55 u8 port{};
76 PadAxes axis{PadAxes::Undefined}; 56 PadAxes axis{PadAxes::Undefined};
@@ -84,11 +64,6 @@ struct GCState {
84 64
85enum class ControllerTypes { None, Wired, Wireless }; 65enum class ControllerTypes { None, Wired, Wireless };
86 66
87enum {
88 NO_ADAPTER_DETECTED = 0,
89 ADAPTER_DETECTED = 1,
90};
91
92class Adapter { 67class Adapter {
93public: 68public:
94 /// Initialize the GC Adapter capture and read sequence 69 /// Initialize the GC Adapter capture and read sequence
@@ -109,18 +84,14 @@ public:
109 std::array<GCState, 4>& GetPadState(); 84 std::array<GCState, 4>& GetPadState();
110 const std::array<GCState, 4>& GetPadState() const; 85 const std::array<GCState, 4>& GetPadState() const;
111 86
87 int GetOriginValue(int port, int axis) const;
88
112private: 89private:
113 GCPadStatus GetPadStatus(std::size_t port, const std::array<u8, 37>& adapter_payload); 90 GCPadStatus GetPadStatus(std::size_t port, const std::array<u8, 37>& adapter_payload);
114 91
115 void PadToState(const GCPadStatus& pad, GCState& state); 92 void PadToState(const GCPadStatus& pad, GCState& state);
116 93
117 void Read(); 94 void Read();
118 void ScanThreadFunc();
119 /// Begin scanning for the GC Adapter.
120 void StartScanThread();
121
122 /// Stop scanning for the adapter
123 void StopScanThread();
124 95
125 /// Resets status of device connected to port 96 /// Resets status of device connected to port
126 void ResetDeviceType(std::size_t port); 97 void ResetDeviceType(std::size_t port);
@@ -137,19 +108,11 @@ private:
137 /// For use in initialization, querying devices to find the adapter 108 /// For use in initialization, querying devices to find the adapter
138 void Setup(); 109 void Setup();
139 110
140 int current_status = NO_ADAPTER_DETECTED;
141 libusb_device_handle* usb_adapter_handle = nullptr; 111 libusb_device_handle* usb_adapter_handle = nullptr;
142 std::array<ControllerTypes, 4> adapter_controllers_status{};
143
144 std::mutex s_mutex;
145 112
146 std::thread adapter_input_thread; 113 std::thread adapter_input_thread;
147 bool adapter_thread_running; 114 bool adapter_thread_running;
148 115
149 std::mutex initialization_mutex;
150 std::thread detect_thread;
151 bool detect_thread_running = false;
152
153 libusb_context* libusb_ctx; 116 libusb_context* libusb_ctx;
154 117
155 u8 input_endpoint = 0; 118 u8 input_endpoint = 0;
@@ -157,8 +120,11 @@ private:
157 120
158 bool configuring = false; 121 bool configuring = false;
159 122
160 std::array<Common::SPSCQueue<GCPadStatus>, 4> pad_queue;
161 std::array<GCState, 4> state; 123 std::array<GCState, 4> state;
124 std::array<bool, 4> get_origin;
125 std::array<GCPadStatus, 4> origin_status;
126 std::array<Common::SPSCQueue<GCPadStatus>, 4> pad_queue;
127 std::array<ControllerTypes, 4> adapter_controllers_status{};
162}; 128};
163 129
164} // namespace GCAdapter 130} // namespace GCAdapter
diff --git a/src/input_common/gcadapter/gc_poller.cpp b/src/input_common/gcadapter/gc_poller.cpp
index b20419ec3..96e22d3ad 100644
--- a/src/input_common/gcadapter/gc_poller.cpp
+++ b/src/input_common/gcadapter/gc_poller.cpp
@@ -38,18 +38,12 @@ public:
38 explicit GCAxisButton(int port_, int axis_, float threshold_, bool trigger_if_greater_, 38 explicit GCAxisButton(int port_, int axis_, float threshold_, bool trigger_if_greater_,
39 GCAdapter::Adapter* adapter) 39 GCAdapter::Adapter* adapter)
40 : port(port_), axis(axis_), threshold(threshold_), trigger_if_greater(trigger_if_greater_), 40 : port(port_), axis(axis_), threshold(threshold_), trigger_if_greater(trigger_if_greater_),
41 gcadapter(adapter) { 41 gcadapter(adapter), origin_value(adapter->GetOriginValue(port_, axis_)) {}
42 // L/R triggers range is only in positive direction beginning near 0
43 // 0.0 threshold equates to near half trigger press, but threshold accounts for variability.
44 if (axis > 3) {
45 threshold *= -0.5;
46 }
47 }
48 42
49 bool GetStatus() const override { 43 bool GetStatus() const override {
50 if (gcadapter->DeviceConnected(port)) { 44 if (gcadapter->DeviceConnected(port)) {
51 const float axis_value = 45 const float current_axis_value = gcadapter->GetPadState()[port].axes.at(axis);
52 (gcadapter->GetPadState()[port].axes.at(axis) - 128.0f) / 128.0f; 46 const float axis_value = (current_axis_value - origin_value) / 128.0f;
53 if (trigger_if_greater) { 47 if (trigger_if_greater) {
54 // TODO: Might be worthwile to set a slider for the trigger threshold. It is 48 // TODO: Might be worthwile to set a slider for the trigger threshold. It is
55 // currently always set to 0.5 in configure_input_player.cpp ZL/ZR HandleClick 49 // currently always set to 0.5 in configure_input_player.cpp ZL/ZR HandleClick
@@ -66,6 +60,7 @@ private:
66 float threshold; 60 float threshold;
67 bool trigger_if_greater; 61 bool trigger_if_greater;
68 GCAdapter::Adapter* gcadapter; 62 GCAdapter::Adapter* gcadapter;
63 const float origin_value;
69}; 64};
70 65
71GCButtonFactory::GCButtonFactory(std::shared_ptr<GCAdapter::Adapter> adapter_) 66GCButtonFactory::GCButtonFactory(std::shared_ptr<GCAdapter::Adapter> adapter_)
@@ -155,15 +150,18 @@ void GCButtonFactory::EndConfiguration() {
155class GCAnalog final : public Input::AnalogDevice { 150class GCAnalog final : public Input::AnalogDevice {
156public: 151public:
157 GCAnalog(int port_, int axis_x_, int axis_y_, float deadzone_, GCAdapter::Adapter* adapter) 152 GCAnalog(int port_, int axis_x_, int axis_y_, float deadzone_, GCAdapter::Adapter* adapter)
158 : port(port_), axis_x(axis_x_), axis_y(axis_y_), deadzone(deadzone_), gcadapter(adapter) {} 153 : port(port_), axis_x(axis_x_), axis_y(axis_y_), deadzone(deadzone_), gcadapter(adapter),
154 origin_value_x(adapter->GetOriginValue(port_, axis_x_)),
155 origin_value_y(adapter->GetOriginValue(port_, axis_y_)) {}
159 156
160 float GetAxis(int axis) const { 157 float GetAxis(int axis) const {
161 if (gcadapter->DeviceConnected(port)) { 158 if (gcadapter->DeviceConnected(port)) {
162 std::lock_guard lock{mutex}; 159 std::lock_guard lock{mutex};
160 const auto origin_value = axis % 2 == 0 ? origin_value_x : origin_value_y;
163 // division is not by a perfect 128 to account for some variance in center location 161 // division is not by a perfect 128 to account for some variance in center location
164 // e.g. my device idled at 131 in X, 120 in Y, and full range of motion was in range 162 // e.g. my device idled at 131 in X, 120 in Y, and full range of motion was in range
165 // [20-230] 163 // [20-230]
166 return (gcadapter->GetPadState()[port].axes.at(axis) - 128.0f) / 95.0f; 164 return (gcadapter->GetPadState()[port].axes.at(axis) - origin_value) / 95.0f;
167 } 165 }
168 return 0.0f; 166 return 0.0f;
169 } 167 }
@@ -215,8 +213,10 @@ private:
215 const int axis_x; 213 const int axis_x;
216 const int axis_y; 214 const int axis_y;
217 const float deadzone; 215 const float deadzone;
218 mutable std::mutex mutex;
219 GCAdapter::Adapter* gcadapter; 216 GCAdapter::Adapter* gcadapter;
217 const float origin_value_x;
218 const float origin_value_y;
219 mutable std::mutex mutex;
220}; 220};
221 221
222/// An analog device factory that creates analog devices from GC Adapter 222/// An analog device factory that creates analog devices from GC Adapter
diff --git a/src/tests/core/core_timing.cpp b/src/tests/core/core_timing.cpp
index e66db1940..244463a47 100644
--- a/src/tests/core/core_timing.cpp
+++ b/src/tests/core/core_timing.cpp
@@ -6,6 +6,7 @@
6 6
7#include <array> 7#include <array>
8#include <bitset> 8#include <bitset>
9#include <chrono>
9#include <cstdlib> 10#include <cstdlib>
10#include <memory> 11#include <memory>
11#include <string> 12#include <string>
@@ -17,7 +18,6 @@
17namespace { 18namespace {
18// Numbers are chosen randomly to make sure the correct one is given. 19// Numbers are chosen randomly to make sure the correct one is given.
19constexpr std::array<u64, 5> CB_IDS{{42, 144, 93, 1026, UINT64_C(0xFFFF7FFFF7FFFF)}}; 20constexpr std::array<u64, 5> CB_IDS{{42, 144, 93, 1026, UINT64_C(0xFFFF7FFFF7FFFF)}};
20constexpr int MAX_SLICE_LENGTH = 10000; // Copied from CoreTiming internals
21constexpr std::array<u64, 5> calls_order{{2, 0, 1, 4, 3}}; 21constexpr std::array<u64, 5> calls_order{{2, 0, 1, 4, 3}};
22std::array<s64, 5> delays{}; 22std::array<s64, 5> delays{};
23 23
@@ -25,12 +25,12 @@ std::bitset<CB_IDS.size()> callbacks_ran_flags;
25u64 expected_callback = 0; 25u64 expected_callback = 0;
26 26
27template <unsigned int IDX> 27template <unsigned int IDX>
28void HostCallbackTemplate(u64 userdata, s64 nanoseconds_late) { 28void HostCallbackTemplate(u64 userdata, std::chrono::nanoseconds ns_late) {
29 static_assert(IDX < CB_IDS.size(), "IDX out of range"); 29 static_assert(IDX < CB_IDS.size(), "IDX out of range");
30 callbacks_ran_flags.set(IDX); 30 callbacks_ran_flags.set(IDX);
31 REQUIRE(CB_IDS[IDX] == userdata); 31 REQUIRE(CB_IDS[IDX] == userdata);
32 REQUIRE(CB_IDS[IDX] == CB_IDS[calls_order[expected_callback]]); 32 REQUIRE(CB_IDS[IDX] == CB_IDS[calls_order[expected_callback]]);
33 delays[IDX] = nanoseconds_late; 33 delays[IDX] = ns_late.count();
34 ++expected_callback; 34 ++expected_callback;
35} 35}
36 36
@@ -77,10 +77,12 @@ TEST_CASE("CoreTiming[BasicOrder]", "[core]") {
77 77
78 core_timing.SyncPause(true); 78 core_timing.SyncPause(true);
79 79
80 u64 one_micro = 1000U; 80 const u64 one_micro = 1000U;
81 for (std::size_t i = 0; i < events.size(); i++) { 81 for (std::size_t i = 0; i < events.size(); i++) {
82 u64 order = calls_order[i]; 82 const u64 order = calls_order[i];
83 core_timing.ScheduleEvent(i * one_micro + 100U, events[order], CB_IDS[order]); 83 const auto future_ns = std::chrono::nanoseconds{static_cast<s64>(i * one_micro + 100)};
84
85 core_timing.ScheduleEvent(future_ns, events[order], CB_IDS[order]);
84 } 86 }
85 /// test pause 87 /// test pause
86 REQUIRE(callbacks_ran_flags.none()); 88 REQUIRE(callbacks_ran_flags.none());
@@ -116,13 +118,16 @@ TEST_CASE("CoreTiming[BasicOrderNoPausing]", "[core]") {
116 118
117 expected_callback = 0; 119 expected_callback = 0;
118 120
119 u64 start = core_timing.GetGlobalTimeNs().count(); 121 const u64 start = core_timing.GetGlobalTimeNs().count();
120 u64 one_micro = 1000U; 122 const u64 one_micro = 1000U;
123
121 for (std::size_t i = 0; i < events.size(); i++) { 124 for (std::size_t i = 0; i < events.size(); i++) {
122 u64 order = calls_order[i]; 125 const u64 order = calls_order[i];
123 core_timing.ScheduleEvent(i * one_micro + 100U, events[order], CB_IDS[order]); 126 const auto future_ns = std::chrono::nanoseconds{static_cast<s64>(i * one_micro + 100)};
127 core_timing.ScheduleEvent(future_ns, events[order], CB_IDS[order]);
124 } 128 }
125 u64 end = core_timing.GetGlobalTimeNs().count(); 129
130 const u64 end = core_timing.GetGlobalTimeNs().count();
126 const double scheduling_time = static_cast<double>(end - start); 131 const double scheduling_time = static_cast<double>(end - start);
127 const double timer_time = static_cast<double>(TestTimerSpeed(core_timing)); 132 const double timer_time = static_cast<double>(TestTimerSpeed(core_timing));
128 133
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt
index 21c46a567..3cd896a0f 100644
--- a/src/video_core/CMakeLists.txt
+++ b/src/video_core/CMakeLists.txt
@@ -98,6 +98,8 @@ add_library(video_core STATIC
98 sampler_cache.cpp 98 sampler_cache.cpp
99 sampler_cache.h 99 sampler_cache.h
100 shader_cache.h 100 shader_cache.h
101 shader_notify.cpp
102 shader_notify.h
101 shader/decode/arithmetic.cpp 103 shader/decode/arithmetic.cpp
102 shader/decode/arithmetic_immediate.cpp 104 shader/decode/arithmetic_immediate.cpp
103 shader/decode/bfe.cpp 105 shader/decode/bfe.cpp
@@ -128,6 +130,8 @@ add_library(video_core STATIC
128 shader/decode/other.cpp 130 shader/decode/other.cpp
129 shader/ast.cpp 131 shader/ast.cpp
130 shader/ast.h 132 shader/ast.h
133 shader/async_shaders.cpp
134 shader/async_shaders.h
131 shader/compiler_settings.cpp 135 shader/compiler_settings.cpp
132 shader/compiler_settings.h 136 shader/compiler_settings.h
133 shader/control_flow.cpp 137 shader/control_flow.cpp
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h
index dd7ce8c99..b5dc68902 100644
--- a/src/video_core/buffer_cache/buffer_cache.h
+++ b/src/video_core/buffer_cache/buffer_cache.h
@@ -524,11 +524,8 @@ private:
524 void MarkRegionAsWritten(VAddr start, VAddr end) { 524 void MarkRegionAsWritten(VAddr start, VAddr end) {
525 const u64 page_end = end >> WRITE_PAGE_BIT; 525 const u64 page_end = end >> WRITE_PAGE_BIT;
526 for (u64 page_start = start >> WRITE_PAGE_BIT; page_start <= page_end; ++page_start) { 526 for (u64 page_start = start >> WRITE_PAGE_BIT; page_start <= page_end; ++page_start) {
527 auto it = written_pages.find(page_start); 527 if (const auto [it, inserted] = written_pages.emplace(page_start, 1); !inserted) {
528 if (it != written_pages.end()) { 528 ++it->second;
529 it->second = it->second + 1;
530 } else {
531 written_pages.insert_or_assign(page_start, 1);
532 } 529 }
533 } 530 }
534 } 531 }
@@ -539,7 +536,7 @@ private:
539 auto it = written_pages.find(page_start); 536 auto it = written_pages.find(page_start);
540 if (it != written_pages.end()) { 537 if (it != written_pages.end()) {
541 if (it->second > 1) { 538 if (it->second > 1) {
542 it->second = it->second - 1; 539 --it->second;
543 } else { 540 } else {
544 written_pages.erase(it); 541 written_pages.erase(it);
545 } 542 }
diff --git a/src/video_core/compatible_formats.cpp b/src/video_core/compatible_formats.cpp
index 6c426b035..b06c32c84 100644
--- a/src/video_core/compatible_formats.cpp
+++ b/src/video_core/compatible_formats.cpp
@@ -17,101 +17,94 @@ namespace {
17// https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_texture_view.txt 17// https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_texture_view.txt
18 18
19constexpr std::array VIEW_CLASS_128_BITS = { 19constexpr std::array VIEW_CLASS_128_BITS = {
20 PixelFormat::RGBA32F, 20 PixelFormat::R32G32B32A32_FLOAT,
21 PixelFormat::RGBA32UI, 21 PixelFormat::R32G32B32A32_UINT,
22 PixelFormat::R32G32B32A32_SINT,
22}; 23};
23// Missing formats:
24// PixelFormat::RGBA32I
25 24
26constexpr std::array VIEW_CLASS_96_BITS = { 25constexpr std::array VIEW_CLASS_96_BITS = {
27 PixelFormat::RGB32F, 26 PixelFormat::R32G32B32_FLOAT,
28}; 27};
29// Missing formats: 28// Missing formats:
30// PixelFormat::RGB32UI, 29// PixelFormat::RGB32UI,
31// PixelFormat::RGB32I, 30// PixelFormat::RGB32I,
32 31
33constexpr std::array VIEW_CLASS_64_BITS = { 32constexpr std::array VIEW_CLASS_64_BITS = {
34 PixelFormat::RGBA16F, PixelFormat::RG32F, PixelFormat::RGBA16UI, PixelFormat::RG32UI, 33 PixelFormat::R32G32_FLOAT, PixelFormat::R32G32_UINT,
35 PixelFormat::RGBA16U, PixelFormat::RGBA16F, PixelFormat::RGBA16S, 34 PixelFormat::R32G32_SINT, PixelFormat::R16G16B16A16_FLOAT,
35 PixelFormat::R16G16B16A16_UNORM, PixelFormat::R16G16B16A16_SNORM,
36 PixelFormat::R16G16B16A16_UINT, PixelFormat::R16G16B16A16_SINT,
36}; 37};
37// Missing formats:
38// PixelFormat::RGBA16I
39// PixelFormat::RG32I
40 38
41// TODO: How should we handle 48 bits? 39// TODO: How should we handle 48 bits?
42 40
43constexpr std::array VIEW_CLASS_32_BITS = { 41constexpr std::array VIEW_CLASS_32_BITS = {
44 PixelFormat::RG16F, PixelFormat::R11FG11FB10F, PixelFormat::R32F, 42 PixelFormat::R16G16_FLOAT, PixelFormat::B10G11R11_FLOAT, PixelFormat::R32_FLOAT,
45 PixelFormat::A2B10G10R10U, PixelFormat::RG16UI, PixelFormat::R32UI, 43 PixelFormat::A2B10G10R10_UNORM, PixelFormat::R16G16_UINT, PixelFormat::R32_UINT,
46 PixelFormat::RG16I, PixelFormat::R32I, PixelFormat::ABGR8U, 44 PixelFormat::R16G16_SINT, PixelFormat::R32_SINT, PixelFormat::A8B8G8R8_UNORM,
47 PixelFormat::RG16, PixelFormat::ABGR8S, PixelFormat::RG16S, 45 PixelFormat::R16G16_UNORM, PixelFormat::A8B8G8R8_SNORM, PixelFormat::R16G16_SNORM,
48 PixelFormat::RGBA8_SRGB, PixelFormat::E5B9G9R9F, PixelFormat::BGRA8, 46 PixelFormat::A8B8G8R8_SRGB, PixelFormat::E5B9G9R9_FLOAT, PixelFormat::B8G8R8A8_UNORM,
49 PixelFormat::BGRA8_SRGB, 47 PixelFormat::B8G8R8A8_SRGB, PixelFormat::A8B8G8R8_UINT, PixelFormat::A8B8G8R8_SINT,
48 PixelFormat::A2B10G10R10_UINT,
50}; 49};
51// Missing formats:
52// PixelFormat::RGBA8UI
53// PixelFormat::RGBA8I
54// PixelFormat::RGB10_A2_UI
55 50
56// TODO: How should we handle 24 bits? 51// TODO: How should we handle 24 bits?
57 52
58constexpr std::array VIEW_CLASS_16_BITS = { 53constexpr std::array VIEW_CLASS_16_BITS = {
59 PixelFormat::R16F, PixelFormat::RG8UI, PixelFormat::R16UI, PixelFormat::R16I, 54 PixelFormat::R16_FLOAT, PixelFormat::R8G8_UINT, PixelFormat::R16_UINT,
60 PixelFormat::RG8U, PixelFormat::R16U, PixelFormat::RG8S, PixelFormat::R16S, 55 PixelFormat::R16_SINT, PixelFormat::R8G8_UNORM, PixelFormat::R16_UNORM,
56 PixelFormat::R8G8_SNORM, PixelFormat::R16_SNORM, PixelFormat::R8G8_SINT,
61}; 57};
62// Missing formats:
63// PixelFormat::RG8I
64 58
65constexpr std::array VIEW_CLASS_8_BITS = { 59constexpr std::array VIEW_CLASS_8_BITS = {
66 PixelFormat::R8UI, 60 PixelFormat::R8_UINT,
67 PixelFormat::R8U, 61 PixelFormat::R8_UNORM,
62 PixelFormat::R8_SINT,
63 PixelFormat::R8_SNORM,
68}; 64};
69// Missing formats:
70// PixelFormat::R8I
71// PixelFormat::R8S
72 65
73constexpr std::array VIEW_CLASS_RGTC1_RED = { 66constexpr std::array VIEW_CLASS_RGTC1_RED = {
74 PixelFormat::DXN1, 67 PixelFormat::BC4_UNORM,
68 PixelFormat::BC4_SNORM,
75}; 69};
76// Missing formats:
77// COMPRESSED_SIGNED_RED_RGTC1
78 70
79constexpr std::array VIEW_CLASS_RGTC2_RG = { 71constexpr std::array VIEW_CLASS_RGTC2_RG = {
80 PixelFormat::DXN2UNORM, 72 PixelFormat::BC5_UNORM,
81 PixelFormat::DXN2SNORM, 73 PixelFormat::BC5_SNORM,
82}; 74};
83 75
84constexpr std::array VIEW_CLASS_BPTC_UNORM = { 76constexpr std::array VIEW_CLASS_BPTC_UNORM = {
85 PixelFormat::BC7U, 77 PixelFormat::BC7_UNORM,
86 PixelFormat::BC7U_SRGB, 78 PixelFormat::BC7_SRGB,
87}; 79};
88 80
89constexpr std::array VIEW_CLASS_BPTC_FLOAT = { 81constexpr std::array VIEW_CLASS_BPTC_FLOAT = {
90 PixelFormat::BC6H_SF16, 82 PixelFormat::BC6H_SFLOAT,
91 PixelFormat::BC6H_UF16, 83 PixelFormat::BC6H_UFLOAT,
92}; 84};
93 85
94// Compatibility table taken from Table 4.X.1 in: 86// Compatibility table taken from Table 4.X.1 in:
95// https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_copy_image.txt 87// https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_copy_image.txt
96 88
97constexpr std::array COPY_CLASS_128_BITS = { 89constexpr std::array COPY_CLASS_128_BITS = {
98 PixelFormat::RGBA32UI, PixelFormat::RGBA32F, PixelFormat::DXT23, 90 PixelFormat::R32G32B32A32_UINT, PixelFormat::R32G32B32A32_FLOAT, PixelFormat::R32G32B32A32_SINT,
99 PixelFormat::DXT23_SRGB, PixelFormat::DXT45, PixelFormat::DXT45_SRGB, 91 PixelFormat::BC2_UNORM, PixelFormat::BC2_SRGB, PixelFormat::BC3_UNORM,
100 PixelFormat::DXN2SNORM, PixelFormat::BC7U, PixelFormat::BC7U_SRGB, 92 PixelFormat::BC3_SRGB, PixelFormat::BC5_UNORM, PixelFormat::BC5_SNORM,
101 PixelFormat::BC6H_SF16, PixelFormat::BC6H_UF16, 93 PixelFormat::BC7_UNORM, PixelFormat::BC7_SRGB, PixelFormat::BC6H_SFLOAT,
94 PixelFormat::BC6H_UFLOAT,
102}; 95};
103// Missing formats: 96// Missing formats:
104// PixelFormat::RGBA32I 97// PixelFormat::RGBA32I
105// COMPRESSED_RG_RGTC2 98// COMPRESSED_RG_RGTC2
106 99
107constexpr std::array COPY_CLASS_64_BITS = { 100constexpr std::array COPY_CLASS_64_BITS = {
108 PixelFormat::RGBA16F, PixelFormat::RG32F, PixelFormat::RGBA16UI, PixelFormat::RG32UI, 101 PixelFormat::R16G16B16A16_FLOAT, PixelFormat::R16G16B16A16_UINT,
109 PixelFormat::RGBA16U, PixelFormat::RGBA16S, PixelFormat::DXT1_SRGB, PixelFormat::DXT1, 102 PixelFormat::R16G16B16A16_UNORM, PixelFormat::R16G16B16A16_SNORM,
110 103 PixelFormat::R16G16B16A16_SINT, PixelFormat::R32G32_UINT,
104 PixelFormat::R32G32_FLOAT, PixelFormat::R32G32_SINT,
105 PixelFormat::BC1_RGBA_UNORM, PixelFormat::BC1_RGBA_SRGB,
111}; 106};
112// Missing formats: 107// Missing formats:
113// PixelFormat::RGBA16I
114// PixelFormat::RG32I,
115// COMPRESSED_RGB_S3TC_DXT1_EXT 108// COMPRESSED_RGB_S3TC_DXT1_EXT
116// COMPRESSED_SRGB_S3TC_DXT1_EXT 109// COMPRESSED_SRGB_S3TC_DXT1_EXT
117// COMPRESSED_RGBA_S3TC_DXT1_EXT 110// COMPRESSED_RGBA_S3TC_DXT1_EXT
diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp
index 758bfe148..8e19c3373 100644
--- a/src/video_core/gpu.cpp
+++ b/src/video_core/gpu.cpp
@@ -20,6 +20,7 @@
20#include "video_core/gpu.h" 20#include "video_core/gpu.h"
21#include "video_core/memory_manager.h" 21#include "video_core/memory_manager.h"
22#include "video_core/renderer_base.h" 22#include "video_core/renderer_base.h"
23#include "video_core/shader_notify.h"
23#include "video_core/video_core.h" 24#include "video_core/video_core.h"
24 25
25namespace Tegra { 26namespace Tegra {
@@ -36,6 +37,7 @@ GPU::GPU(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& render
36 kepler_compute = std::make_unique<Engines::KeplerCompute>(system, rasterizer, *memory_manager); 37 kepler_compute = std::make_unique<Engines::KeplerCompute>(system, rasterizer, *memory_manager);
37 maxwell_dma = std::make_unique<Engines::MaxwellDMA>(system, *memory_manager); 38 maxwell_dma = std::make_unique<Engines::MaxwellDMA>(system, *memory_manager);
38 kepler_memory = std::make_unique<Engines::KeplerMemory>(system, *memory_manager); 39 kepler_memory = std::make_unique<Engines::KeplerMemory>(system, *memory_manager);
40 shader_notify = std::make_unique<VideoCore::ShaderNotify>();
39} 41}
40 42
41GPU::~GPU() = default; 43GPU::~GPU() = default;
diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h
index 2c42483bd..19a34c402 100644
--- a/src/video_core/gpu.h
+++ b/src/video_core/gpu.h
@@ -33,59 +33,68 @@ class System;
33 33
34namespace VideoCore { 34namespace VideoCore {
35class RendererBase; 35class RendererBase;
36class ShaderNotify;
36} // namespace VideoCore 37} // namespace VideoCore
37 38
38namespace Tegra { 39namespace Tegra {
39 40
40enum class RenderTargetFormat : u32 { 41enum class RenderTargetFormat : u32 {
41 NONE = 0x0, 42 NONE = 0x0,
42 RGBA32_FLOAT = 0xC0, 43 R32B32G32A32_FLOAT = 0xC0,
43 RGBA32_UINT = 0xC2, 44 R32G32B32A32_SINT = 0xC1,
44 RGBA16_UNORM = 0xC6, 45 R32G32B32A32_UINT = 0xC2,
45 RGBA16_SNORM = 0xC7, 46 R16G16B16A16_UNORM = 0xC6,
46 RGBA16_UINT = 0xC9, 47 R16G16B16A16_SNORM = 0xC7,
47 RGBA16_FLOAT = 0xCA, 48 R16G16B16A16_SINT = 0xC8,
48 RG32_FLOAT = 0xCB, 49 R16G16B16A16_UINT = 0xC9,
49 RG32_UINT = 0xCD, 50 R16G16B16A16_FLOAT = 0xCA,
50 RGBX16_FLOAT = 0xCE, 51 R32G32_FLOAT = 0xCB,
51 BGRA8_UNORM = 0xCF, 52 R32G32_SINT = 0xCC,
52 BGRA8_SRGB = 0xD0, 53 R32G32_UINT = 0xCD,
53 RGB10_A2_UNORM = 0xD1, 54 R16G16B16X16_FLOAT = 0xCE,
54 RGBA8_UNORM = 0xD5, 55 B8G8R8A8_UNORM = 0xCF,
55 RGBA8_SRGB = 0xD6, 56 B8G8R8A8_SRGB = 0xD0,
56 RGBA8_SNORM = 0xD7, 57 A2B10G10R10_UNORM = 0xD1,
57 RGBA8_UINT = 0xD9, 58 A2B10G10R10_UINT = 0xD2,
58 RG16_UNORM = 0xDA, 59 A8B8G8R8_UNORM = 0xD5,
59 RG16_SNORM = 0xDB, 60 A8B8G8R8_SRGB = 0xD6,
60 RG16_SINT = 0xDC, 61 A8B8G8R8_SNORM = 0xD7,
61 RG16_UINT = 0xDD, 62 A8B8G8R8_SINT = 0xD8,
62 RG16_FLOAT = 0xDE, 63 A8B8G8R8_UINT = 0xD9,
63 R11G11B10_FLOAT = 0xE0, 64 R16G16_UNORM = 0xDA,
65 R16G16_SNORM = 0xDB,
66 R16G16_SINT = 0xDC,
67 R16G16_UINT = 0xDD,
68 R16G16_FLOAT = 0xDE,
69 B10G11R11_FLOAT = 0xE0,
64 R32_SINT = 0xE3, 70 R32_SINT = 0xE3,
65 R32_UINT = 0xE4, 71 R32_UINT = 0xE4,
66 R32_FLOAT = 0xE5, 72 R32_FLOAT = 0xE5,
67 B5G6R5_UNORM = 0xE8, 73 R5G6B5_UNORM = 0xE8,
68 BGR5A1_UNORM = 0xE9, 74 A1R5G5B5_UNORM = 0xE9,
69 RG8_UNORM = 0xEA, 75 R8G8_UNORM = 0xEA,
70 RG8_SNORM = 0xEB, 76 R8G8_SNORM = 0xEB,
71 RG8_UINT = 0xED, 77 R8G8_SINT = 0xEC,
78 R8G8_UINT = 0xED,
72 R16_UNORM = 0xEE, 79 R16_UNORM = 0xEE,
73 R16_SNORM = 0xEF, 80 R16_SNORM = 0xEF,
74 R16_SINT = 0xF0, 81 R16_SINT = 0xF0,
75 R16_UINT = 0xF1, 82 R16_UINT = 0xF1,
76 R16_FLOAT = 0xF2, 83 R16_FLOAT = 0xF2,
77 R8_UNORM = 0xF3, 84 R8_UNORM = 0xF3,
85 R8_SNORM = 0xF4,
86 R8_SINT = 0xF5,
78 R8_UINT = 0xF6, 87 R8_UINT = 0xF6,
79}; 88};
80 89
81enum class DepthFormat : u32 { 90enum class DepthFormat : u32 {
82 Z32_FLOAT = 0xA, 91 D32_FLOAT = 0xA,
83 Z16_UNORM = 0x13, 92 D16_UNORM = 0x13,
84 S8_Z24_UNORM = 0x14, 93 S8_UINT_Z24_UNORM = 0x14,
85 Z24_X8_UNORM = 0x15, 94 D24X8_UNORM = 0x15,
86 Z24_S8_UNORM = 0x16, 95 D24S8_UNORM = 0x16,
87 Z24_C8_UNORM = 0x18, 96 D24C8_UNORM = 0x18,
88 Z32_S8_X24_FLOAT = 0x19, 97 D32_FLOAT_S8X24_UINT = 0x19,
89}; 98};
90 99
91struct CommandListHeader; 100struct CommandListHeader;
@@ -96,9 +105,9 @@ class DebugContext;
96 */ 105 */
97struct FramebufferConfig { 106struct FramebufferConfig {
98 enum class PixelFormat : u32 { 107 enum class PixelFormat : u32 {
99 ABGR8 = 1, 108 A8B8G8R8_UNORM = 1,
100 RGB565 = 4, 109 RGB565_UNORM = 4,
101 BGRA8 = 5, 110 B8G8R8A8_UNORM = 5,
102 }; 111 };
103 112
104 VAddr address; 113 VAddr address;
@@ -207,6 +216,14 @@ public:
207 return *renderer; 216 return *renderer;
208 } 217 }
209 218
219 VideoCore::ShaderNotify& ShaderNotify() {
220 return *shader_notify;
221 }
222
223 const VideoCore::ShaderNotify& ShaderNotify() const {
224 return *shader_notify;
225 }
226
210 // Waits for the GPU to finish working 227 // Waits for the GPU to finish working
211 virtual void WaitIdle() const = 0; 228 virtual void WaitIdle() const = 0;
212 229
@@ -347,6 +364,8 @@ private:
347 std::unique_ptr<Engines::MaxwellDMA> maxwell_dma; 364 std::unique_ptr<Engines::MaxwellDMA> maxwell_dma;
348 /// Inline memory engine 365 /// Inline memory engine
349 std::unique_ptr<Engines::KeplerMemory> kepler_memory; 366 std::unique_ptr<Engines::KeplerMemory> kepler_memory;
367 /// Shader build notifier
368 std::unique_ptr<VideoCore::ShaderNotify> shader_notify;
350 369
351 std::array<std::atomic<u32>, Service::Nvidia::MaxSyncPoints> syncpoints{}; 370 std::array<std::atomic<u32>, Service::Nvidia::MaxSyncPoints> syncpoints{};
352 371
diff --git a/src/video_core/gpu_thread.cpp b/src/video_core/gpu_thread.cpp
index 738c6f0c1..bf761abf2 100644
--- a/src/video_core/gpu_thread.cpp
+++ b/src/video_core/gpu_thread.cpp
@@ -44,9 +44,9 @@ static void RunThread(Core::System& system, VideoCore::RendererBase& renderer,
44 dma_pusher.DispatchCalls(); 44 dma_pusher.DispatchCalls();
45 } else if (const auto data = std::get_if<SwapBuffersCommand>(&next.data)) { 45 } else if (const auto data = std::get_if<SwapBuffersCommand>(&next.data)) {
46 renderer.SwapBuffers(data->framebuffer ? &*data->framebuffer : nullptr); 46 renderer.SwapBuffers(data->framebuffer ? &*data->framebuffer : nullptr);
47 } else if (const auto data = std::get_if<OnCommandListEndCommand>(&next.data)) { 47 } else if (std::holds_alternative<OnCommandListEndCommand>(next.data)) {
48 renderer.Rasterizer().ReleaseFences(); 48 renderer.Rasterizer().ReleaseFences();
49 } else if (const auto data = std::get_if<GPUTickCommand>(&next.data)) { 49 } else if (std::holds_alternative<GPUTickCommand>(next.data)) {
50 system.GPU().TickWork(); 50 system.GPU().TickWork();
51 } else if (const auto data = std::get_if<FlushRegionCommand>(&next.data)) { 51 } else if (const auto data = std::get_if<FlushRegionCommand>(&next.data)) {
52 renderer.Rasterizer().FlushRegion(data->addr, data->size); 52 renderer.Rasterizer().FlushRegion(data->addr, data->size);
diff --git a/src/video_core/macro/macro.h b/src/video_core/macro/macro.h
index 4d00b84b0..31ee3440a 100644
--- a/src/video_core/macro/macro.h
+++ b/src/video_core/macro/macro.h
@@ -103,8 +103,9 @@ public:
103 virtual ~CachedMacro() = default; 103 virtual ~CachedMacro() = default;
104 /** 104 /**
105 * Executes the macro code with the specified input parameters. 105 * Executes the macro code with the specified input parameters.
106 * @param code The macro byte code to execute 106 *
107 * @param parameters The parameters of the macro 107 * @param parameters The parameters of the macro
108 * @param method The method to execute
108 */ 109 */
109 virtual void Execute(const std::vector<u32>& parameters, u32 method) = 0; 110 virtual void Execute(const std::vector<u32>& parameters, u32 method) = 0;
110}; 111};
diff --git a/src/video_core/macro/macro_hle.cpp b/src/video_core/macro/macro_hle.cpp
index 410f99018..0c9ff59a4 100644
--- a/src/video_core/macro/macro_hle.cpp
+++ b/src/video_core/macro/macro_hle.cpp
@@ -12,13 +12,11 @@ namespace Tegra {
12 12
13namespace { 13namespace {
14// HLE'd functions 14// HLE'd functions
15static void HLE_771BB18C62444DA0(Engines::Maxwell3D& maxwell3d, 15void HLE_771BB18C62444DA0(Engines::Maxwell3D& maxwell3d, const std::vector<u32>& parameters) {
16 const std::vector<u32>& parameters) {
17 const u32 instance_count = parameters[2] & maxwell3d.GetRegisterValue(0xD1B); 16 const u32 instance_count = parameters[2] & maxwell3d.GetRegisterValue(0xD1B);
18 17
19 maxwell3d.regs.draw.topology.Assign( 18 maxwell3d.regs.draw.topology.Assign(
20 static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[0] & 19 static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[0] & 0x3ffffff));
21 ~(0x3ffffff << 26)));
22 maxwell3d.regs.vb_base_instance = parameters[5]; 20 maxwell3d.regs.vb_base_instance = parameters[5];
23 maxwell3d.mme_draw.instance_count = instance_count; 21 maxwell3d.mme_draw.instance_count = instance_count;
24 maxwell3d.regs.vb_element_base = parameters[3]; 22 maxwell3d.regs.vb_element_base = parameters[3];
@@ -33,8 +31,7 @@ static void HLE_771BB18C62444DA0(Engines::Maxwell3D& maxwell3d,
33 maxwell3d.mme_draw.current_mode = Engines::Maxwell3D::MMEDrawMode::Undefined; 31 maxwell3d.mme_draw.current_mode = Engines::Maxwell3D::MMEDrawMode::Undefined;
34} 32}
35 33
36static void HLE_0D61FC9FAAC9FCAD(Engines::Maxwell3D& maxwell3d, 34void HLE_0D61FC9FAAC9FCAD(Engines::Maxwell3D& maxwell3d, const std::vector<u32>& parameters) {
37 const std::vector<u32>& parameters) {
38 const u32 count = (maxwell3d.GetRegisterValue(0xD1B) & parameters[2]); 35 const u32 count = (maxwell3d.GetRegisterValue(0xD1B) & parameters[2]);
39 36
40 maxwell3d.regs.vertex_buffer.first = parameters[3]; 37 maxwell3d.regs.vertex_buffer.first = parameters[3];
@@ -52,8 +49,7 @@ static void HLE_0D61FC9FAAC9FCAD(Engines::Maxwell3D& maxwell3d,
52 maxwell3d.mme_draw.current_mode = Engines::Maxwell3D::MMEDrawMode::Undefined; 49 maxwell3d.mme_draw.current_mode = Engines::Maxwell3D::MMEDrawMode::Undefined;
53} 50}
54 51
55static void HLE_0217920100488FF7(Engines::Maxwell3D& maxwell3d, 52void HLE_0217920100488FF7(Engines::Maxwell3D& maxwell3d, const std::vector<u32>& parameters) {
56 const std::vector<u32>& parameters) {
57 const u32 instance_count = (maxwell3d.GetRegisterValue(0xD1B) & parameters[2]); 53 const u32 instance_count = (maxwell3d.GetRegisterValue(0xD1B) & parameters[2]);
58 const u32 element_base = parameters[4]; 54 const u32 element_base = parameters[4];
59 const u32 base_instance = parameters[5]; 55 const u32 base_instance = parameters[5];
@@ -81,12 +77,12 @@ static void HLE_0217920100488FF7(Engines::Maxwell3D& maxwell3d,
81 maxwell3d.CallMethodFromMME(0x8e5, 0x0); 77 maxwell3d.CallMethodFromMME(0x8e5, 0x0);
82 maxwell3d.mme_draw.current_mode = Engines::Maxwell3D::MMEDrawMode::Undefined; 78 maxwell3d.mme_draw.current_mode = Engines::Maxwell3D::MMEDrawMode::Undefined;
83} 79}
84} // namespace 80} // Anonymous namespace
85 81
86constexpr std::array<std::pair<u64, HLEFunction>, 3> hle_funcs{{ 82constexpr std::array<std::pair<u64, HLEFunction>, 3> hle_funcs{{
87 std::make_pair<u64, HLEFunction>(0x771BB18C62444DA0, &HLE_771BB18C62444DA0), 83 {0x771BB18C62444DA0, &HLE_771BB18C62444DA0},
88 std::make_pair<u64, HLEFunction>(0x0D61FC9FAAC9FCAD, &HLE_0D61FC9FAAC9FCAD), 84 {0x0D61FC9FAAC9FCAD, &HLE_0D61FC9FAAC9FCAD},
89 std::make_pair<u64, HLEFunction>(0x0217920100488FF7, &HLE_0217920100488FF7), 85 {0x0217920100488FF7, &HLE_0217920100488FF7},
90}}; 86}};
91 87
92HLEMacro::HLEMacro(Engines::Maxwell3D& maxwell3d) : maxwell3d(maxwell3d) {} 88HLEMacro::HLEMacro(Engines::Maxwell3D& maxwell3d) : maxwell3d(maxwell3d) {}
diff --git a/src/video_core/macro/macro_jit_x64.cpp b/src/video_core/macro/macro_jit_x64.cpp
index 07292702f..c1b9e4ad9 100644
--- a/src/video_core/macro/macro_jit_x64.cpp
+++ b/src/video_core/macro/macro_jit_x64.cpp
@@ -419,7 +419,6 @@ void Tegra::MacroJITx64Impl::Optimizer_ScanFlags() {
419 419
420void MacroJITx64Impl::Compile() { 420void MacroJITx64Impl::Compile() {
421 MICROPROFILE_SCOPE(MacroJitCompile); 421 MICROPROFILE_SCOPE(MacroJitCompile);
422 bool keep_executing = true;
423 labels.fill(Xbyak::Label()); 422 labels.fill(Xbyak::Label());
424 423
425 Common::X64::ABI_PushRegistersAndAdjustStack(*this, Common::X64::ABI_ALL_CALLEE_SAVED, 8); 424 Common::X64::ABI_PushRegistersAndAdjustStack(*this, Common::X64::ABI_ALL_CALLEE_SAVED, 8);
diff --git a/src/video_core/morton.cpp b/src/video_core/morton.cpp
index 836b25c1d..9da9fb4ff 100644
--- a/src/video_core/morton.cpp
+++ b/src/video_core/morton.cpp
@@ -41,146 +41,168 @@ static void MortonCopy(u32 stride, u32 block_height, u32 height, u32 block_depth
41} 41}
42 42
43static constexpr ConversionArray morton_to_linear_fns = { 43static constexpr ConversionArray morton_to_linear_fns = {
44 MortonCopy<true, PixelFormat::ABGR8U>, 44 MortonCopy<true, PixelFormat::A8B8G8R8_UNORM>,
45 MortonCopy<true, PixelFormat::ABGR8S>, 45 MortonCopy<true, PixelFormat::A8B8G8R8_SNORM>,
46 MortonCopy<true, PixelFormat::ABGR8UI>, 46 MortonCopy<true, PixelFormat::A8B8G8R8_SINT>,
47 MortonCopy<true, PixelFormat::B5G6R5U>, 47 MortonCopy<true, PixelFormat::A8B8G8R8_UINT>,
48 MortonCopy<true, PixelFormat::A2B10G10R10U>, 48 MortonCopy<true, PixelFormat::R5G6B5_UNORM>,
49 MortonCopy<true, PixelFormat::A1B5G5R5U>, 49 MortonCopy<true, PixelFormat::B5G6R5_UNORM>,
50 MortonCopy<true, PixelFormat::R8U>, 50 MortonCopy<true, PixelFormat::A1R5G5B5_UNORM>,
51 MortonCopy<true, PixelFormat::R8UI>, 51 MortonCopy<true, PixelFormat::A2B10G10R10_UNORM>,
52 MortonCopy<true, PixelFormat::RGBA16F>, 52 MortonCopy<true, PixelFormat::A2B10G10R10_UINT>,
53 MortonCopy<true, PixelFormat::RGBA16U>, 53 MortonCopy<true, PixelFormat::A1B5G5R5_UNORM>,
54 MortonCopy<true, PixelFormat::RGBA16S>, 54 MortonCopy<true, PixelFormat::R8_UNORM>,
55 MortonCopy<true, PixelFormat::RGBA16UI>, 55 MortonCopy<true, PixelFormat::R8_SNORM>,
56 MortonCopy<true, PixelFormat::R11FG11FB10F>, 56 MortonCopy<true, PixelFormat::R8_SINT>,
57 MortonCopy<true, PixelFormat::RGBA32UI>, 57 MortonCopy<true, PixelFormat::R8_UINT>,
58 MortonCopy<true, PixelFormat::DXT1>, 58 MortonCopy<true, PixelFormat::R16G16B16A16_FLOAT>,
59 MortonCopy<true, PixelFormat::DXT23>, 59 MortonCopy<true, PixelFormat::R16G16B16A16_UNORM>,
60 MortonCopy<true, PixelFormat::DXT45>, 60 MortonCopy<true, PixelFormat::R16G16B16A16_SNORM>,
61 MortonCopy<true, PixelFormat::DXN1>, 61 MortonCopy<true, PixelFormat::R16G16B16A16_SINT>,
62 MortonCopy<true, PixelFormat::DXN2UNORM>, 62 MortonCopy<true, PixelFormat::R16G16B16A16_UINT>,
63 MortonCopy<true, PixelFormat::DXN2SNORM>, 63 MortonCopy<true, PixelFormat::B10G11R11_FLOAT>,
64 MortonCopy<true, PixelFormat::BC7U>, 64 MortonCopy<true, PixelFormat::R32G32B32A32_UINT>,
65 MortonCopy<true, PixelFormat::BC6H_UF16>, 65 MortonCopy<true, PixelFormat::BC1_RGBA_UNORM>,
66 MortonCopy<true, PixelFormat::BC6H_SF16>, 66 MortonCopy<true, PixelFormat::BC2_UNORM>,
67 MortonCopy<true, PixelFormat::ASTC_2D_4X4>, 67 MortonCopy<true, PixelFormat::BC3_UNORM>,
68 MortonCopy<true, PixelFormat::BGRA8>, 68 MortonCopy<true, PixelFormat::BC4_UNORM>,
69 MortonCopy<true, PixelFormat::RGBA32F>, 69 MortonCopy<true, PixelFormat::BC4_SNORM>,
70 MortonCopy<true, PixelFormat::RG32F>, 70 MortonCopy<true, PixelFormat::BC5_UNORM>,
71 MortonCopy<true, PixelFormat::R32F>, 71 MortonCopy<true, PixelFormat::BC5_SNORM>,
72 MortonCopy<true, PixelFormat::R16F>, 72 MortonCopy<true, PixelFormat::BC7_UNORM>,
73 MortonCopy<true, PixelFormat::R16U>, 73 MortonCopy<true, PixelFormat::BC6H_UFLOAT>,
74 MortonCopy<true, PixelFormat::R16S>, 74 MortonCopy<true, PixelFormat::BC6H_SFLOAT>,
75 MortonCopy<true, PixelFormat::R16UI>, 75 MortonCopy<true, PixelFormat::ASTC_2D_4X4_UNORM>,
76 MortonCopy<true, PixelFormat::R16I>, 76 MortonCopy<true, PixelFormat::B8G8R8A8_UNORM>,
77 MortonCopy<true, PixelFormat::RG16>, 77 MortonCopy<true, PixelFormat::R32G32B32A32_FLOAT>,
78 MortonCopy<true, PixelFormat::RG16F>, 78 MortonCopy<true, PixelFormat::R32G32B32A32_SINT>,
79 MortonCopy<true, PixelFormat::RG16UI>, 79 MortonCopy<true, PixelFormat::R32G32_FLOAT>,
80 MortonCopy<true, PixelFormat::RG16I>, 80 MortonCopy<true, PixelFormat::R32G32_SINT>,
81 MortonCopy<true, PixelFormat::RG16S>, 81 MortonCopy<true, PixelFormat::R32_FLOAT>,
82 MortonCopy<true, PixelFormat::RGB32F>, 82 MortonCopy<true, PixelFormat::R16_FLOAT>,
83 MortonCopy<true, PixelFormat::RGBA8_SRGB>, 83 MortonCopy<true, PixelFormat::R16_UNORM>,
84 MortonCopy<true, PixelFormat::RG8U>, 84 MortonCopy<true, PixelFormat::R16_SNORM>,
85 MortonCopy<true, PixelFormat::RG8S>, 85 MortonCopy<true, PixelFormat::R16_UINT>,
86 MortonCopy<true, PixelFormat::RG8UI>, 86 MortonCopy<true, PixelFormat::R16_SINT>,
87 MortonCopy<true, PixelFormat::RG32UI>, 87 MortonCopy<true, PixelFormat::R16G16_UNORM>,
88 MortonCopy<true, PixelFormat::RGBX16F>, 88 MortonCopy<true, PixelFormat::R16G16_FLOAT>,
89 MortonCopy<true, PixelFormat::R32UI>, 89 MortonCopy<true, PixelFormat::R16G16_UINT>,
90 MortonCopy<true, PixelFormat::R32I>, 90 MortonCopy<true, PixelFormat::R16G16_SINT>,
91 MortonCopy<true, PixelFormat::ASTC_2D_8X8>, 91 MortonCopy<true, PixelFormat::R16G16_SNORM>,
92 MortonCopy<true, PixelFormat::ASTC_2D_8X5>, 92 MortonCopy<true, PixelFormat::R32G32B32_FLOAT>,
93 MortonCopy<true, PixelFormat::ASTC_2D_5X4>, 93 MortonCopy<true, PixelFormat::A8B8G8R8_SRGB>,
94 MortonCopy<true, PixelFormat::BGRA8_SRGB>, 94 MortonCopy<true, PixelFormat::R8G8_UNORM>,
95 MortonCopy<true, PixelFormat::DXT1_SRGB>, 95 MortonCopy<true, PixelFormat::R8G8_SNORM>,
96 MortonCopy<true, PixelFormat::DXT23_SRGB>, 96 MortonCopy<true, PixelFormat::R8G8_SINT>,
97 MortonCopy<true, PixelFormat::DXT45_SRGB>, 97 MortonCopy<true, PixelFormat::R8G8_UINT>,
98 MortonCopy<true, PixelFormat::BC7U_SRGB>, 98 MortonCopy<true, PixelFormat::R32G32_UINT>,
99 MortonCopy<true, PixelFormat::R4G4B4A4U>, 99 MortonCopy<true, PixelFormat::R16G16B16X16_FLOAT>,
100 MortonCopy<true, PixelFormat::R32_UINT>,
101 MortonCopy<true, PixelFormat::R32_SINT>,
102 MortonCopy<true, PixelFormat::ASTC_2D_8X8_UNORM>,
103 MortonCopy<true, PixelFormat::ASTC_2D_8X5_UNORM>,
104 MortonCopy<true, PixelFormat::ASTC_2D_5X4_UNORM>,
105 MortonCopy<true, PixelFormat::B8G8R8A8_SRGB>,
106 MortonCopy<true, PixelFormat::BC1_RGBA_SRGB>,
107 MortonCopy<true, PixelFormat::BC2_SRGB>,
108 MortonCopy<true, PixelFormat::BC3_SRGB>,
109 MortonCopy<true, PixelFormat::BC7_SRGB>,
110 MortonCopy<true, PixelFormat::A4B4G4R4_UNORM>,
100 MortonCopy<true, PixelFormat::ASTC_2D_4X4_SRGB>, 111 MortonCopy<true, PixelFormat::ASTC_2D_4X4_SRGB>,
101 MortonCopy<true, PixelFormat::ASTC_2D_8X8_SRGB>, 112 MortonCopy<true, PixelFormat::ASTC_2D_8X8_SRGB>,
102 MortonCopy<true, PixelFormat::ASTC_2D_8X5_SRGB>, 113 MortonCopy<true, PixelFormat::ASTC_2D_8X5_SRGB>,
103 MortonCopy<true, PixelFormat::ASTC_2D_5X4_SRGB>, 114 MortonCopy<true, PixelFormat::ASTC_2D_5X4_SRGB>,
104 MortonCopy<true, PixelFormat::ASTC_2D_5X5>, 115 MortonCopy<true, PixelFormat::ASTC_2D_5X5_UNORM>,
105 MortonCopy<true, PixelFormat::ASTC_2D_5X5_SRGB>, 116 MortonCopy<true, PixelFormat::ASTC_2D_5X5_SRGB>,
106 MortonCopy<true, PixelFormat::ASTC_2D_10X8>, 117 MortonCopy<true, PixelFormat::ASTC_2D_10X8_UNORM>,
107 MortonCopy<true, PixelFormat::ASTC_2D_10X8_SRGB>, 118 MortonCopy<true, PixelFormat::ASTC_2D_10X8_SRGB>,
108 MortonCopy<true, PixelFormat::ASTC_2D_6X6>, 119 MortonCopy<true, PixelFormat::ASTC_2D_6X6_UNORM>,
109 MortonCopy<true, PixelFormat::ASTC_2D_6X6_SRGB>, 120 MortonCopy<true, PixelFormat::ASTC_2D_6X6_SRGB>,
110 MortonCopy<true, PixelFormat::ASTC_2D_10X10>, 121 MortonCopy<true, PixelFormat::ASTC_2D_10X10_UNORM>,
111 MortonCopy<true, PixelFormat::ASTC_2D_10X10_SRGB>, 122 MortonCopy<true, PixelFormat::ASTC_2D_10X10_SRGB>,
112 MortonCopy<true, PixelFormat::ASTC_2D_12X12>, 123 MortonCopy<true, PixelFormat::ASTC_2D_12X12_UNORM>,
113 MortonCopy<true, PixelFormat::ASTC_2D_12X12_SRGB>, 124 MortonCopy<true, PixelFormat::ASTC_2D_12X12_SRGB>,
114 MortonCopy<true, PixelFormat::ASTC_2D_8X6>, 125 MortonCopy<true, PixelFormat::ASTC_2D_8X6_UNORM>,
115 MortonCopy<true, PixelFormat::ASTC_2D_8X6_SRGB>, 126 MortonCopy<true, PixelFormat::ASTC_2D_8X6_SRGB>,
116 MortonCopy<true, PixelFormat::ASTC_2D_6X5>, 127 MortonCopy<true, PixelFormat::ASTC_2D_6X5_UNORM>,
117 MortonCopy<true, PixelFormat::ASTC_2D_6X5_SRGB>, 128 MortonCopy<true, PixelFormat::ASTC_2D_6X5_SRGB>,
118 MortonCopy<true, PixelFormat::E5B9G9R9F>, 129 MortonCopy<true, PixelFormat::E5B9G9R9_FLOAT>,
119 MortonCopy<true, PixelFormat::Z32F>, 130 MortonCopy<true, PixelFormat::D32_FLOAT>,
120 MortonCopy<true, PixelFormat::Z16>, 131 MortonCopy<true, PixelFormat::D16_UNORM>,
121 MortonCopy<true, PixelFormat::Z24S8>, 132 MortonCopy<true, PixelFormat::D24_UNORM_S8_UINT>,
122 MortonCopy<true, PixelFormat::S8Z24>, 133 MortonCopy<true, PixelFormat::S8_UINT_D24_UNORM>,
123 MortonCopy<true, PixelFormat::Z32FS8>, 134 MortonCopy<true, PixelFormat::D32_FLOAT_S8_UINT>,
124}; 135};
125 136
126static constexpr ConversionArray linear_to_morton_fns = { 137static constexpr ConversionArray linear_to_morton_fns = {
127 MortonCopy<false, PixelFormat::ABGR8U>, 138 MortonCopy<false, PixelFormat::A8B8G8R8_UNORM>,
128 MortonCopy<false, PixelFormat::ABGR8S>, 139 MortonCopy<false, PixelFormat::A8B8G8R8_SNORM>,
129 MortonCopy<false, PixelFormat::ABGR8UI>, 140 MortonCopy<false, PixelFormat::A8B8G8R8_SINT>,
130 MortonCopy<false, PixelFormat::B5G6R5U>, 141 MortonCopy<false, PixelFormat::A8B8G8R8_UINT>,
131 MortonCopy<false, PixelFormat::A2B10G10R10U>, 142 MortonCopy<false, PixelFormat::R5G6B5_UNORM>,
132 MortonCopy<false, PixelFormat::A1B5G5R5U>, 143 MortonCopy<false, PixelFormat::B5G6R5_UNORM>,
133 MortonCopy<false, PixelFormat::R8U>, 144 MortonCopy<false, PixelFormat::A1R5G5B5_UNORM>,
134 MortonCopy<false, PixelFormat::R8UI>, 145 MortonCopy<false, PixelFormat::A2B10G10R10_UNORM>,
135 MortonCopy<false, PixelFormat::RGBA16F>, 146 MortonCopy<false, PixelFormat::A2B10G10R10_UINT>,
136 MortonCopy<false, PixelFormat::RGBA16S>, 147 MortonCopy<false, PixelFormat::A1B5G5R5_UNORM>,
137 MortonCopy<false, PixelFormat::RGBA16U>, 148 MortonCopy<false, PixelFormat::R8_UNORM>,
138 MortonCopy<false, PixelFormat::RGBA16UI>, 149 MortonCopy<false, PixelFormat::R8_SNORM>,
139 MortonCopy<false, PixelFormat::R11FG11FB10F>, 150 MortonCopy<false, PixelFormat::R8_SINT>,
140 MortonCopy<false, PixelFormat::RGBA32UI>, 151 MortonCopy<false, PixelFormat::R8_UINT>,
141 MortonCopy<false, PixelFormat::DXT1>, 152 MortonCopy<false, PixelFormat::R16G16B16A16_FLOAT>,
142 MortonCopy<false, PixelFormat::DXT23>, 153 MortonCopy<false, PixelFormat::R16G16B16A16_SNORM>,
143 MortonCopy<false, PixelFormat::DXT45>, 154 MortonCopy<false, PixelFormat::R16G16B16A16_SINT>,
144 MortonCopy<false, PixelFormat::DXN1>, 155 MortonCopy<false, PixelFormat::R16G16B16A16_UNORM>,
145 MortonCopy<false, PixelFormat::DXN2UNORM>, 156 MortonCopy<false, PixelFormat::R16G16B16A16_UINT>,
146 MortonCopy<false, PixelFormat::DXN2SNORM>, 157 MortonCopy<false, PixelFormat::B10G11R11_FLOAT>,
147 MortonCopy<false, PixelFormat::BC7U>, 158 MortonCopy<false, PixelFormat::R32G32B32A32_UINT>,
148 MortonCopy<false, PixelFormat::BC6H_UF16>, 159 MortonCopy<false, PixelFormat::BC1_RGBA_UNORM>,
149 MortonCopy<false, PixelFormat::BC6H_SF16>, 160 MortonCopy<false, PixelFormat::BC2_UNORM>,
161 MortonCopy<false, PixelFormat::BC3_UNORM>,
162 MortonCopy<false, PixelFormat::BC4_UNORM>,
163 MortonCopy<false, PixelFormat::BC4_SNORM>,
164 MortonCopy<false, PixelFormat::BC5_UNORM>,
165 MortonCopy<false, PixelFormat::BC5_SNORM>,
166 MortonCopy<false, PixelFormat::BC7_UNORM>,
167 MortonCopy<false, PixelFormat::BC6H_UFLOAT>,
168 MortonCopy<false, PixelFormat::BC6H_SFLOAT>,
150 // TODO(Subv): Swizzling ASTC formats are not supported 169 // TODO(Subv): Swizzling ASTC formats are not supported
151 nullptr, 170 nullptr,
152 MortonCopy<false, PixelFormat::BGRA8>, 171 MortonCopy<false, PixelFormat::B8G8R8A8_UNORM>,
153 MortonCopy<false, PixelFormat::RGBA32F>, 172 MortonCopy<false, PixelFormat::R32G32B32A32_FLOAT>,
154 MortonCopy<false, PixelFormat::RG32F>, 173 MortonCopy<false, PixelFormat::R32G32B32A32_SINT>,
155 MortonCopy<false, PixelFormat::R32F>, 174 MortonCopy<false, PixelFormat::R32G32_FLOAT>,
156 MortonCopy<false, PixelFormat::R16F>, 175 MortonCopy<false, PixelFormat::R32G32_SINT>,
157 MortonCopy<false, PixelFormat::R16U>, 176 MortonCopy<false, PixelFormat::R32_FLOAT>,
158 MortonCopy<false, PixelFormat::R16S>, 177 MortonCopy<false, PixelFormat::R16_FLOAT>,
159 MortonCopy<false, PixelFormat::R16UI>, 178 MortonCopy<false, PixelFormat::R16_UNORM>,
160 MortonCopy<false, PixelFormat::R16I>, 179 MortonCopy<false, PixelFormat::R16_SNORM>,
161 MortonCopy<false, PixelFormat::RG16>, 180 MortonCopy<false, PixelFormat::R16_UINT>,
162 MortonCopy<false, PixelFormat::RG16F>, 181 MortonCopy<false, PixelFormat::R16_SINT>,
163 MortonCopy<false, PixelFormat::RG16UI>, 182 MortonCopy<false, PixelFormat::R16G16_UNORM>,
164 MortonCopy<false, PixelFormat::RG16I>, 183 MortonCopy<false, PixelFormat::R16G16_FLOAT>,
165 MortonCopy<false, PixelFormat::RG16S>, 184 MortonCopy<false, PixelFormat::R16G16_UINT>,
166 MortonCopy<false, PixelFormat::RGB32F>, 185 MortonCopy<false, PixelFormat::R16G16_SINT>,
167 MortonCopy<false, PixelFormat::RGBA8_SRGB>, 186 MortonCopy<false, PixelFormat::R16G16_SNORM>,
168 MortonCopy<false, PixelFormat::RG8U>, 187 MortonCopy<false, PixelFormat::R32G32B32_FLOAT>,
169 MortonCopy<false, PixelFormat::RG8S>, 188 MortonCopy<false, PixelFormat::A8B8G8R8_SRGB>,
170 MortonCopy<false, PixelFormat::RG8UI>, 189 MortonCopy<false, PixelFormat::R8G8_UNORM>,
171 MortonCopy<false, PixelFormat::RG32UI>, 190 MortonCopy<false, PixelFormat::R8G8_SNORM>,
172 MortonCopy<false, PixelFormat::RGBX16F>, 191 MortonCopy<false, PixelFormat::R8G8_SINT>,
173 MortonCopy<false, PixelFormat::R32UI>, 192 MortonCopy<false, PixelFormat::R8G8_UINT>,
174 MortonCopy<false, PixelFormat::R32I>, 193 MortonCopy<false, PixelFormat::R32G32_UINT>,
194 MortonCopy<false, PixelFormat::R16G16B16X16_FLOAT>,
195 MortonCopy<false, PixelFormat::R32_UINT>,
196 MortonCopy<false, PixelFormat::R32_SINT>,
175 nullptr, 197 nullptr,
176 nullptr, 198 nullptr,
177 nullptr, 199 nullptr,
178 MortonCopy<false, PixelFormat::BGRA8_SRGB>, 200 MortonCopy<false, PixelFormat::B8G8R8A8_SRGB>,
179 MortonCopy<false, PixelFormat::DXT1_SRGB>, 201 MortonCopy<false, PixelFormat::BC1_RGBA_SRGB>,
180 MortonCopy<false, PixelFormat::DXT23_SRGB>, 202 MortonCopy<false, PixelFormat::BC2_SRGB>,
181 MortonCopy<false, PixelFormat::DXT45_SRGB>, 203 MortonCopy<false, PixelFormat::BC3_SRGB>,
182 MortonCopy<false, PixelFormat::BC7U_SRGB>, 204 MortonCopy<false, PixelFormat::BC7_SRGB>,
183 MortonCopy<false, PixelFormat::R4G4B4A4U>, 205 MortonCopy<false, PixelFormat::A4B4G4R4_UNORM>,
184 nullptr, 206 nullptr,
185 nullptr, 207 nullptr,
186 nullptr, 208 nullptr,
@@ -199,12 +221,12 @@ static constexpr ConversionArray linear_to_morton_fns = {
199 nullptr, 221 nullptr,
200 nullptr, 222 nullptr,
201 nullptr, 223 nullptr,
202 MortonCopy<false, PixelFormat::E5B9G9R9F>, 224 MortonCopy<false, PixelFormat::E5B9G9R9_FLOAT>,
203 MortonCopy<false, PixelFormat::Z32F>, 225 MortonCopy<false, PixelFormat::D32_FLOAT>,
204 MortonCopy<false, PixelFormat::Z16>, 226 MortonCopy<false, PixelFormat::D16_UNORM>,
205 MortonCopy<false, PixelFormat::Z24S8>, 227 MortonCopy<false, PixelFormat::D24_UNORM_S8_UINT>,
206 MortonCopy<false, PixelFormat::S8Z24>, 228 MortonCopy<false, PixelFormat::S8_UINT_D24_UNORM>,
207 MortonCopy<false, PixelFormat::Z32FS8>, 229 MortonCopy<false, PixelFormat::D32_FLOAT_S8_UINT>,
208}; 230};
209 231
210static MortonCopyFn GetSwizzleFunction(MortonSwizzleMode mode, Surface::PixelFormat format) { 232static MortonCopyFn GetSwizzleFunction(MortonSwizzleMode mode, Surface::PixelFormat format) {
diff --git a/src/video_core/renderer_opengl/gl_arb_decompiler.cpp b/src/video_core/renderer_opengl/gl_arb_decompiler.cpp
index eb5158407..b7e9ed2e9 100644
--- a/src/video_core/renderer_opengl/gl_arb_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_arb_decompiler.cpp
@@ -185,10 +185,6 @@ std::string TextureType(const MetaTexture& meta) {
185 return type; 185 return type;
186} 186}
187 187
188std::string GlobalMemoryName(const GlobalMemoryBase& base) {
189 return fmt::format("gmem{}_{}", base.cbuf_index, base.cbuf_offset);
190}
191
192class ARBDecompiler final { 188class ARBDecompiler final {
193public: 189public:
194 explicit ARBDecompiler(const Device& device, const ShaderIR& ir, const Registry& registry, 190 explicit ARBDecompiler(const Device& device, const ShaderIR& ir, const Registry& registry,
@@ -199,6 +195,8 @@ public:
199 } 195 }
200 196
201private: 197private:
198 void DefineGlobalMemory();
199
202 void DeclareHeader(); 200 void DeclareHeader();
203 void DeclareVertex(); 201 void DeclareVertex();
204 void DeclareGeometry(); 202 void DeclareGeometry();
@@ -228,6 +226,7 @@ private:
228 226
229 std::pair<std::string, std::size_t> BuildCoords(Operation); 227 std::pair<std::string, std::size_t> BuildCoords(Operation);
230 std::string BuildAoffi(Operation); 228 std::string BuildAoffi(Operation);
229 std::string GlobalMemoryPointer(const GmemNode& gmem);
231 void Exit(); 230 void Exit();
232 231
233 std::string Assign(Operation); 232 std::string Assign(Operation);
@@ -378,10 +377,8 @@ private:
378 std::string address; 377 std::string address;
379 std::string_view opname; 378 std::string_view opname;
380 if (const auto gmem = std::get_if<GmemNode>(&*operation[0])) { 379 if (const auto gmem = std::get_if<GmemNode>(&*operation[0])) {
381 AddLine("SUB.U {}, {}, {};", temporary, Visit(gmem->GetRealAddress()), 380 address = GlobalMemoryPointer(*gmem);
382 Visit(gmem->GetBaseAddress())); 381 opname = "ATOM";
383 address = fmt::format("{}[{}]", GlobalMemoryName(gmem->GetDescriptor()), temporary);
384 opname = "ATOMB";
385 } else if (const auto smem = std::get_if<SmemNode>(&*operation[0])) { 382 } else if (const auto smem = std::get_if<SmemNode>(&*operation[0])) {
386 address = fmt::format("shared_mem[{}]", Visit(smem->GetAddress())); 383 address = fmt::format("shared_mem[{}]", Visit(smem->GetAddress()));
387 opname = "ATOMS"; 384 opname = "ATOMS";
@@ -456,9 +453,13 @@ private:
456 shader_source += '\n'; 453 shader_source += '\n';
457 } 454 }
458 455
459 std::string AllocTemporary() { 456 std::string AllocLongVectorTemporary() {
460 max_temporaries = std::max(max_temporaries, num_temporaries + 1); 457 max_long_temporaries = std::max(max_long_temporaries, num_long_temporaries + 1);
461 return fmt::format("T{}.x", num_temporaries++); 458 return fmt::format("L{}", num_long_temporaries++);
459 }
460
461 std::string AllocLongTemporary() {
462 return fmt::format("{}.x", AllocLongVectorTemporary());
462 } 463 }
463 464
464 std::string AllocVectorTemporary() { 465 std::string AllocVectorTemporary() {
@@ -466,8 +467,13 @@ private:
466 return fmt::format("T{}", num_temporaries++); 467 return fmt::format("T{}", num_temporaries++);
467 } 468 }
468 469
470 std::string AllocTemporary() {
471 return fmt::format("{}.x", AllocVectorTemporary());
472 }
473
469 void ResetTemporaries() noexcept { 474 void ResetTemporaries() noexcept {
470 num_temporaries = 0; 475 num_temporaries = 0;
476 num_long_temporaries = 0;
471 } 477 }
472 478
473 const Device& device; 479 const Device& device;
@@ -478,6 +484,11 @@ private:
478 std::size_t num_temporaries = 0; 484 std::size_t num_temporaries = 0;
479 std::size_t max_temporaries = 0; 485 std::size_t max_temporaries = 0;
480 486
487 std::size_t num_long_temporaries = 0;
488 std::size_t max_long_temporaries = 0;
489
490 std::map<GlobalMemoryBase, u32> global_memory_names;
491
481 std::string shader_source; 492 std::string shader_source;
482 493
483 static constexpr std::string_view ADD_F32 = "ADD.F32"; 494 static constexpr std::string_view ADD_F32 = "ADD.F32";
@@ -784,6 +795,8 @@ private:
784ARBDecompiler::ARBDecompiler(const Device& device, const ShaderIR& ir, const Registry& registry, 795ARBDecompiler::ARBDecompiler(const Device& device, const ShaderIR& ir, const Registry& registry,
785 ShaderType stage, std::string_view identifier) 796 ShaderType stage, std::string_view identifier)
786 : device{device}, ir{ir}, registry{registry}, stage{stage} { 797 : device{device}, ir{ir}, registry{registry}, stage{stage} {
798 DefineGlobalMemory();
799
787 AddLine("TEMP RC;"); 800 AddLine("TEMP RC;");
788 AddLine("TEMP FSWZA[4];"); 801 AddLine("TEMP FSWZA[4];");
789 AddLine("TEMP FSWZB[4];"); 802 AddLine("TEMP FSWZB[4];");
@@ -829,12 +842,20 @@ std::string_view HeaderStageName(ShaderType stage) {
829 } 842 }
830} 843}
831 844
845void ARBDecompiler::DefineGlobalMemory() {
846 u32 binding = 0;
847 for (const auto& pair : ir.GetGlobalMemory()) {
848 const GlobalMemoryBase base = pair.first;
849 global_memory_names.emplace(base, binding);
850 ++binding;
851 }
852}
853
832void ARBDecompiler::DeclareHeader() { 854void ARBDecompiler::DeclareHeader() {
833 AddLine("!!NV{}5.0", HeaderStageName(stage)); 855 AddLine("!!NV{}5.0", HeaderStageName(stage));
834 // Enabling this allows us to cheat on some instructions like TXL with SHADOWARRAY2D 856 // Enabling this allows us to cheat on some instructions like TXL with SHADOWARRAY2D
835 AddLine("OPTION NV_internal;"); 857 AddLine("OPTION NV_internal;");
836 AddLine("OPTION NV_gpu_program_fp64;"); 858 AddLine("OPTION NV_gpu_program_fp64;");
837 AddLine("OPTION NV_shader_storage_buffer;");
838 AddLine("OPTION NV_shader_thread_group;"); 859 AddLine("OPTION NV_shader_thread_group;");
839 if (ir.UsesWarps() && device.HasWarpIntrinsics()) { 860 if (ir.UsesWarps() && device.HasWarpIntrinsics()) {
840 AddLine("OPTION NV_shader_thread_shuffle;"); 861 AddLine("OPTION NV_shader_thread_shuffle;");
@@ -892,11 +913,19 @@ void ARBDecompiler::DeclareCompute() {
892 const ComputeInfo& info = registry.GetComputeInfo(); 913 const ComputeInfo& info = registry.GetComputeInfo();
893 AddLine("GROUP_SIZE {} {} {};", info.workgroup_size[0], info.workgroup_size[1], 914 AddLine("GROUP_SIZE {} {} {};", info.workgroup_size[0], info.workgroup_size[1],
894 info.workgroup_size[2]); 915 info.workgroup_size[2]);
895 if (info.shared_memory_size_in_words > 0) { 916 if (info.shared_memory_size_in_words == 0) {
896 const u32 size_in_bytes = info.shared_memory_size_in_words * 4; 917 return;
897 AddLine("SHARED_MEMORY {};", size_in_bytes); 918 }
898 AddLine("SHARED shared_mem[] = {{program.sharedmem}};"); 919 const u32 limit = device.GetMaxComputeSharedMemorySize();
920 u32 size_in_bytes = info.shared_memory_size_in_words * 4;
921 if (size_in_bytes > limit) {
922 LOG_ERROR(Render_OpenGL, "Shared memory size {} is clamped to host's limit {}",
923 size_in_bytes, limit);
924 size_in_bytes = limit;
899 } 925 }
926
927 AddLine("SHARED_MEMORY {};", size_in_bytes);
928 AddLine("SHARED shared_mem[] = {{program.sharedmem}};");
900} 929}
901 930
902void ARBDecompiler::DeclareInputAttributes() { 931void ARBDecompiler::DeclareInputAttributes() {
@@ -951,11 +980,10 @@ void ARBDecompiler::DeclareLocalMemory() {
951} 980}
952 981
953void ARBDecompiler::DeclareGlobalMemory() { 982void ARBDecompiler::DeclareGlobalMemory() {
954 u32 binding = 0; // device.GetBaseBindings(stage).shader_storage_buffer; 983 const std::size_t num_entries = ir.GetGlobalMemory().size();
955 for (const auto& pair : ir.GetGlobalMemory()) { 984 if (num_entries > 0) {
956 const auto& base = pair.first; 985 const std::size_t num_vectors = Common::AlignUp(num_entries, 2) / 2;
957 AddLine("STORAGE {}[] = {{ program.storage[{}] }};", GlobalMemoryName(base), binding); 986 AddLine("PARAM c[{}] = {{ program.local[0..{}] }};", num_vectors, num_vectors - 1);
958 ++binding;
959 } 987 }
960} 988}
961 989
@@ -977,6 +1005,9 @@ void ARBDecompiler::DeclareTemporaries() {
977 for (std::size_t i = 0; i < max_temporaries; ++i) { 1005 for (std::size_t i = 0; i < max_temporaries; ++i) {
978 AddLine("TEMP T{};", i); 1006 AddLine("TEMP T{};", i);
979 } 1007 }
1008 for (std::size_t i = 0; i < max_long_temporaries; ++i) {
1009 AddLine("LONG TEMP L{};", i);
1010 }
980} 1011}
981 1012
982void ARBDecompiler::DeclarePredicates() { 1013void ARBDecompiler::DeclarePredicates() {
@@ -1260,13 +1291,6 @@ std::string ARBDecompiler::Visit(const Node& node) {
1260 return "{0, 0, 0, 0}.x"; 1291 return "{0, 0, 0, 0}.x";
1261 } 1292 }
1262 1293
1263 const auto buffer_index = [this, &abuf]() -> std::string {
1264 if (stage != ShaderType::Geometry) {
1265 return "";
1266 }
1267 return fmt::format("[{}]", Visit(abuf->GetBuffer()));
1268 };
1269
1270 const Attribute::Index index = abuf->GetIndex(); 1294 const Attribute::Index index = abuf->GetIndex();
1271 const u32 element = abuf->GetElement(); 1295 const u32 element = abuf->GetElement();
1272 const char swizzle = Swizzle(element); 1296 const char swizzle = Swizzle(element);
@@ -1339,10 +1363,7 @@ std::string ARBDecompiler::Visit(const Node& node) {
1339 1363
1340 if (const auto gmem = std::get_if<GmemNode>(&*node)) { 1364 if (const auto gmem = std::get_if<GmemNode>(&*node)) {
1341 std::string temporary = AllocTemporary(); 1365 std::string temporary = AllocTemporary();
1342 AddLine("SUB.U {}, {}, {};", temporary, Visit(gmem->GetRealAddress()), 1366 AddLine("LOAD.U32 {}, {};", temporary, GlobalMemoryPointer(*gmem));
1343 Visit(gmem->GetBaseAddress()));
1344 AddLine("LDB.U32 {}, {}[{}];", temporary, GlobalMemoryName(gmem->GetDescriptor()),
1345 temporary);
1346 return temporary; 1367 return temporary;
1347 } 1368 }
1348 1369
@@ -1375,7 +1396,7 @@ std::string ARBDecompiler::Visit(const Node& node) {
1375 return {}; 1396 return {};
1376 } 1397 }
1377 1398
1378 if (const auto cmt = std::get_if<CommentNode>(&*node)) { 1399 if ([[maybe_unused]] const auto cmt = std::get_if<CommentNode>(&*node)) {
1379 // Uncommenting this will generate invalid code. GLASM lacks comments. 1400 // Uncommenting this will generate invalid code. GLASM lacks comments.
1380 // AddLine("// {}", cmt->GetText()); 1401 // AddLine("// {}", cmt->GetText());
1381 return {}; 1402 return {};
@@ -1419,6 +1440,22 @@ std::string ARBDecompiler::BuildAoffi(Operation operation) {
1419 return fmt::format(", offset({})", temporary); 1440 return fmt::format(", offset({})", temporary);
1420} 1441}
1421 1442
1443std::string ARBDecompiler::GlobalMemoryPointer(const GmemNode& gmem) {
1444 const u32 binding = global_memory_names.at(gmem.GetDescriptor());
1445 const char result_swizzle = binding % 2 == 0 ? 'x' : 'y';
1446
1447 const std::string pointer = AllocLongVectorTemporary();
1448 std::string temporary = AllocTemporary();
1449
1450 const u32 local_index = binding / 2;
1451 AddLine("PK64.U {}, c[{}];", pointer, local_index);
1452 AddLine("SUB.U {}, {}, {};", temporary, Visit(gmem.GetRealAddress()),
1453 Visit(gmem.GetBaseAddress()));
1454 AddLine("CVT.U64.U32 {}.z, {};", pointer, temporary);
1455 AddLine("ADD.U64 {}.x, {}.{}, {}.z;", pointer, pointer, result_swizzle, pointer);
1456 return fmt::format("{}.x", pointer);
1457}
1458
1422void ARBDecompiler::Exit() { 1459void ARBDecompiler::Exit() {
1423 if (stage != ShaderType::Fragment) { 1460 if (stage != ShaderType::Fragment) {
1424 AddLine("RET;"); 1461 AddLine("RET;");
@@ -1515,11 +1552,7 @@ std::string ARBDecompiler::Assign(Operation operation) {
1515 ResetTemporaries(); 1552 ResetTemporaries();
1516 return {}; 1553 return {};
1517 } else if (const auto gmem = std::get_if<GmemNode>(&*dest)) { 1554 } else if (const auto gmem = std::get_if<GmemNode>(&*dest)) {
1518 const std::string temporary = AllocTemporary(); 1555 AddLine("STORE.U32 {}, {};", Visit(src), GlobalMemoryPointer(*gmem));
1519 AddLine("SUB.U {}, {}, {};", temporary, Visit(gmem->GetRealAddress()),
1520 Visit(gmem->GetBaseAddress()));
1521 AddLine("STB.U32 {}, {}[{}];", Visit(src), GlobalMemoryName(gmem->GetDescriptor()),
1522 temporary);
1523 ResetTemporaries(); 1556 ResetTemporaries();
1524 return {}; 1557 return {};
1525 } else { 1558 } else {
@@ -1671,7 +1704,7 @@ std::string ARBDecompiler::HCastFloat(Operation operation) {
1671} 1704}
1672 1705
1673std::string ARBDecompiler::HUnpack(Operation operation) { 1706std::string ARBDecompiler::HUnpack(Operation operation) {
1674 const std::string operand = Visit(operation[0]); 1707 std::string operand = Visit(operation[0]);
1675 switch (std::get<Tegra::Shader::HalfType>(operation.GetMeta())) { 1708 switch (std::get<Tegra::Shader::HalfType>(operation.GetMeta())) {
1676 case Tegra::Shader::HalfType::H0_H1: 1709 case Tegra::Shader::HalfType::H0_H1:
1677 return operand; 1710 return operand;
@@ -2021,7 +2054,7 @@ std::string ARBDecompiler::InvocationId(Operation) {
2021 2054
2022std::string ARBDecompiler::YNegate(Operation) { 2055std::string ARBDecompiler::YNegate(Operation) {
2023 LOG_WARNING(Render_OpenGL, "(STUBBED)"); 2056 LOG_WARNING(Render_OpenGL, "(STUBBED)");
2024 const std::string temporary = AllocTemporary(); 2057 std::string temporary = AllocTemporary();
2025 AddLine("MOV.F {}, 1;", temporary); 2058 AddLine("MOV.F {}, 1;", temporary);
2026 return temporary; 2059 return temporary;
2027} 2060}
@@ -2044,10 +2077,6 @@ std::string ARBDecompiler::ShuffleIndexed(Operation operation) {
2044} 2077}
2045 2078
2046std::string ARBDecompiler::Barrier(Operation) { 2079std::string ARBDecompiler::Barrier(Operation) {
2047 if (!ir.IsDecompiled()) {
2048 LOG_ERROR(Render_OpenGL, "BAR used but shader is not decompiled");
2049 return {};
2050 }
2051 AddLine("BAR;"); 2080 AddLine("BAR;");
2052 return {}; 2081 return {};
2053} 2082}
diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.cpp b/src/video_core/renderer_opengl/gl_buffer_cache.cpp
index e461e4c70..e866d8f2f 100644
--- a/src/video_core/renderer_opengl/gl_buffer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_buffer_cache.cpp
@@ -26,7 +26,7 @@ Buffer::Buffer(const Device& device, VAddr cpu_addr, std::size_t size)
26 : VideoCommon::BufferBlock{cpu_addr, size} { 26 : VideoCommon::BufferBlock{cpu_addr, size} {
27 gl_buffer.Create(); 27 gl_buffer.Create();
28 glNamedBufferData(gl_buffer.handle, static_cast<GLsizeiptr>(size), nullptr, GL_DYNAMIC_DRAW); 28 glNamedBufferData(gl_buffer.handle, static_cast<GLsizeiptr>(size), nullptr, GL_DYNAMIC_DRAW);
29 if (device.HasVertexBufferUnifiedMemory()) { 29 if (device.UseAssemblyShaders() || device.HasVertexBufferUnifiedMemory()) {
30 glMakeNamedBufferResidentNV(gl_buffer.handle, GL_READ_WRITE); 30 glMakeNamedBufferResidentNV(gl_buffer.handle, GL_READ_WRITE);
31 glGetNamedBufferParameterui64vNV(gl_buffer.handle, GL_BUFFER_GPU_ADDRESS_NV, &gpu_address); 31 glGetNamedBufferParameterui64vNV(gl_buffer.handle, GL_BUFFER_GPU_ADDRESS_NV, &gpu_address);
32 } 32 }
diff --git a/src/video_core/renderer_opengl/gl_device.cpp b/src/video_core/renderer_opengl/gl_device.cpp
index c1f20f0ab..e7d95149f 100644
--- a/src/video_core/renderer_opengl/gl_device.cpp
+++ b/src/video_core/renderer_opengl/gl_device.cpp
@@ -212,6 +212,7 @@ Device::Device()
212 shader_storage_alignment = GetInteger<std::size_t>(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT); 212 shader_storage_alignment = GetInteger<std::size_t>(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT);
213 max_vertex_attributes = GetInteger<u32>(GL_MAX_VERTEX_ATTRIBS); 213 max_vertex_attributes = GetInteger<u32>(GL_MAX_VERTEX_ATTRIBS);
214 max_varyings = GetInteger<u32>(GL_MAX_VARYING_VECTORS); 214 max_varyings = GetInteger<u32>(GL_MAX_VARYING_VECTORS);
215 max_compute_shared_memory_size = GetInteger<u32>(GL_MAX_COMPUTE_SHARED_MEMORY_SIZE);
215 has_warp_intrinsics = GLAD_GL_NV_gpu_shader5 && GLAD_GL_NV_shader_thread_group && 216 has_warp_intrinsics = GLAD_GL_NV_gpu_shader5 && GLAD_GL_NV_shader_thread_group &&
216 GLAD_GL_NV_shader_thread_shuffle; 217 GLAD_GL_NV_shader_thread_shuffle;
217 has_shader_ballot = GLAD_GL_ARB_shader_ballot; 218 has_shader_ballot = GLAD_GL_ARB_shader_ballot;
@@ -233,6 +234,8 @@ Device::Device()
233 GLAD_GL_NV_gpu_program5 && GLAD_GL_NV_compute_program5 && 234 GLAD_GL_NV_gpu_program5 && GLAD_GL_NV_compute_program5 &&
234 GLAD_GL_NV_transform_feedback && GLAD_GL_NV_transform_feedback2; 235 GLAD_GL_NV_transform_feedback && GLAD_GL_NV_transform_feedback2;
235 236
237 use_asynchronous_shaders = Settings::values.use_asynchronous_shaders.GetValue();
238
236 LOG_INFO(Render_OpenGL, "Renderer_VariableAOFFI: {}", has_variable_aoffi); 239 LOG_INFO(Render_OpenGL, "Renderer_VariableAOFFI: {}", has_variable_aoffi);
237 LOG_INFO(Render_OpenGL, "Renderer_ComponentIndexingBug: {}", has_component_indexing_bug); 240 LOG_INFO(Render_OpenGL, "Renderer_ComponentIndexingBug: {}", has_component_indexing_bug);
238 LOG_INFO(Render_OpenGL, "Renderer_PreciseBug: {}", has_precise_bug); 241 LOG_INFO(Render_OpenGL, "Renderer_PreciseBug: {}", has_precise_bug);
@@ -248,6 +251,7 @@ Device::Device(std::nullptr_t) {
248 shader_storage_alignment = 4; 251 shader_storage_alignment = 4;
249 max_vertex_attributes = 16; 252 max_vertex_attributes = 16;
250 max_varyings = 15; 253 max_varyings = 15;
254 max_compute_shared_memory_size = 0x10000;
251 has_warp_intrinsics = true; 255 has_warp_intrinsics = true;
252 has_shader_ballot = true; 256 has_shader_ballot = true;
253 has_vertex_viewport_layer = true; 257 has_vertex_viewport_layer = true;
diff --git a/src/video_core/renderer_opengl/gl_device.h b/src/video_core/renderer_opengl/gl_device.h
index e1d811966..8a4b6b9fc 100644
--- a/src/video_core/renderer_opengl/gl_device.h
+++ b/src/video_core/renderer_opengl/gl_device.h
@@ -52,6 +52,10 @@ public:
52 return max_varyings; 52 return max_varyings;
53 } 53 }
54 54
55 u32 GetMaxComputeSharedMemorySize() const {
56 return max_compute_shared_memory_size;
57 }
58
55 bool HasWarpIntrinsics() const { 59 bool HasWarpIntrinsics() const {
56 return has_warp_intrinsics; 60 return has_warp_intrinsics;
57 } 61 }
@@ -104,6 +108,10 @@ public:
104 return use_assembly_shaders; 108 return use_assembly_shaders;
105 } 109 }
106 110
111 bool UseAsynchronousShaders() const {
112 return use_asynchronous_shaders;
113 }
114
107private: 115private:
108 static bool TestVariableAoffi(); 116 static bool TestVariableAoffi();
109 static bool TestPreciseBug(); 117 static bool TestPreciseBug();
@@ -114,6 +122,7 @@ private:
114 std::size_t shader_storage_alignment{}; 122 std::size_t shader_storage_alignment{};
115 u32 max_vertex_attributes{}; 123 u32 max_vertex_attributes{};
116 u32 max_varyings{}; 124 u32 max_varyings{};
125 u32 max_compute_shared_memory_size{};
117 bool has_warp_intrinsics{}; 126 bool has_warp_intrinsics{};
118 bool has_shader_ballot{}; 127 bool has_shader_ballot{};
119 bool has_vertex_viewport_layer{}; 128 bool has_vertex_viewport_layer{};
@@ -127,6 +136,7 @@ private:
127 bool has_fast_buffer_sub_data{}; 136 bool has_fast_buffer_sub_data{};
128 bool has_nv_viewport_array2{}; 137 bool has_nv_viewport_array2{};
129 bool use_assembly_shaders{}; 138 bool use_assembly_shaders{};
139 bool use_asynchronous_shaders{};
130}; 140};
131 141
132} // namespace OpenGL 142} // namespace OpenGL
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index e960a0ef1..03e82c599 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -139,6 +139,18 @@ void oglEnable(GLenum cap, bool state) {
139 (state ? glEnable : glDisable)(cap); 139 (state ? glEnable : glDisable)(cap);
140} 140}
141 141
142void UpdateBindlessPointers(GLenum target, GLuint64EXT* pointers, std::size_t num_entries) {
143 if (num_entries == 0) {
144 return;
145 }
146 if (num_entries % 2 == 1) {
147 pointers[num_entries] = 0;
148 }
149 const GLsizei num_vectors = static_cast<GLsizei>((num_entries + 1) / 2);
150 glProgramLocalParametersI4uivNV(target, 0, num_vectors,
151 reinterpret_cast<const GLuint*>(pointers));
152}
153
142} // Anonymous namespace 154} // Anonymous namespace
143 155
144RasterizerOpenGL::RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWindow& emu_window, 156RasterizerOpenGL::RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWindow& emu_window,
@@ -149,7 +161,8 @@ RasterizerOpenGL::RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWind
149 shader_cache{*this, system, emu_window, device}, query_cache{system, *this}, 161 shader_cache{*this, system, emu_window, device}, query_cache{system, *this},
150 buffer_cache{*this, system, device, STREAM_BUFFER_SIZE}, 162 buffer_cache{*this, system, device, STREAM_BUFFER_SIZE},
151 fence_manager{system, *this, texture_cache, buffer_cache, query_cache}, system{system}, 163 fence_manager{system, *this, texture_cache, buffer_cache, query_cache}, system{system},
152 screen_info{info}, program_manager{program_manager}, state_tracker{state_tracker} { 164 screen_info{info}, program_manager{program_manager}, state_tracker{state_tracker},
165 async_shaders{emu_window} {
153 CheckExtensions(); 166 CheckExtensions();
154 167
155 unified_uniform_buffer.Create(); 168 unified_uniform_buffer.Create();
@@ -162,6 +175,23 @@ RasterizerOpenGL::RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWind
162 nullptr, 0); 175 nullptr, 0);
163 } 176 }
164 } 177 }
178
179 if (device.UseAsynchronousShaders()) {
180 // Max worker threads we should allow
181 constexpr auto MAX_THREADS = 2u;
182 // Amount of threads we should reserve for other parts of yuzu
183 constexpr auto RESERVED_THREADS = 6u;
184 // Get the amount of threads we can use(this can return zero)
185 const auto cpu_thread_count =
186 std::max(RESERVED_THREADS, std::thread::hardware_concurrency());
187 // Deduce how many "extra" threads we have to use.
188 const auto max_threads_unused = cpu_thread_count - RESERVED_THREADS;
189 // Always allow at least 1 thread regardless of our settings
190 const auto max_worker_count = std::max(1u, max_threads_unused);
191 // Don't use more than MAX_THREADS
192 const auto worker_count = std::min(max_worker_count, MAX_THREADS);
193 async_shaders.AllocateWorkers(worker_count);
194 }
165} 195}
166 196
167RasterizerOpenGL::~RasterizerOpenGL() { 197RasterizerOpenGL::~RasterizerOpenGL() {
@@ -306,7 +336,6 @@ GLintptr RasterizerOpenGL::SetupIndexBuffer() {
306void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) { 336void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) {
307 MICROPROFILE_SCOPE(OpenGL_Shader); 337 MICROPROFILE_SCOPE(OpenGL_Shader);
308 auto& gpu = system.GPU().Maxwell3D(); 338 auto& gpu = system.GPU().Maxwell3D();
309 std::size_t num_ssbos = 0;
310 u32 clip_distances = 0; 339 u32 clip_distances = 0;
311 340
312 for (std::size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) { 341 for (std::size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) {
@@ -329,31 +358,15 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) {
329 } 358 }
330 359
331 // Currently this stages are not supported in the OpenGL backend. 360 // Currently this stages are not supported in the OpenGL backend.
332 // Todo(Blinkhawk): Port tesselation shaders from Vulkan to OpenGL 361 // TODO(Blinkhawk): Port tesselation shaders from Vulkan to OpenGL
333 if (program == Maxwell::ShaderProgram::TesselationControl) { 362 if (program == Maxwell::ShaderProgram::TesselationControl ||
334 continue; 363 program == Maxwell::ShaderProgram::TesselationEval) {
335 } else if (program == Maxwell::ShaderProgram::TesselationEval) {
336 continue; 364 continue;
337 } 365 }
338 366
339 Shader* const shader = shader_cache.GetStageProgram(program); 367 Shader* const shader = shader_cache.GetStageProgram(program, async_shaders);
340
341 if (device.UseAssemblyShaders()) {
342 // Check for ARB limitation. We only have 16 SSBOs per context state. To workaround this
343 // all stages share the same bindings.
344 const std::size_t num_stage_ssbos = shader->GetEntries().global_memory_entries.size();
345 ASSERT_MSG(num_stage_ssbos == 0 || num_ssbos == 0, "SSBOs on more than one stage");
346 num_ssbos += num_stage_ssbos;
347 }
348 368
349 // Stage indices are 0 - 5 369 const GLuint program_handle = shader->IsBuilt() ? shader->GetHandle() : 0;
350 const std::size_t stage = index == 0 ? 0 : index - 1;
351 SetupDrawConstBuffers(stage, shader);
352 SetupDrawGlobalMemory(stage, shader);
353 SetupDrawTextures(stage, shader);
354 SetupDrawImages(stage, shader);
355
356 const GLuint program_handle = shader->GetHandle();
357 switch (program) { 370 switch (program) {
358 case Maxwell::ShaderProgram::VertexA: 371 case Maxwell::ShaderProgram::VertexA:
359 case Maxwell::ShaderProgram::VertexB: 372 case Maxwell::ShaderProgram::VertexB:
@@ -370,6 +383,13 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) {
370 shader_config.enable.Value(), shader_config.offset); 383 shader_config.enable.Value(), shader_config.offset);
371 } 384 }
372 385
386 // Stage indices are 0 - 5
387 const std::size_t stage = index == 0 ? 0 : index - 1;
388 SetupDrawConstBuffers(stage, shader);
389 SetupDrawGlobalMemory(stage, shader);
390 SetupDrawTextures(stage, shader);
391 SetupDrawImages(stage, shader);
392
373 // Workaround for Intel drivers. 393 // Workaround for Intel drivers.
374 // When a clip distance is enabled but not set in the shader it crops parts of the screen 394 // When a clip distance is enabled but not set in the shader it crops parts of the screen
375 // (sometimes it's half the screen, sometimes three quarters). To avoid this, enable the 395 // (sometimes it's half the screen, sometimes three quarters). To avoid this, enable the
@@ -731,6 +751,8 @@ void RasterizerOpenGL::DispatchCompute(GPUVAddr code_addr) {
731 current_cbuf = 0; 751 current_cbuf = 0;
732 752
733 auto kernel = shader_cache.GetComputeKernel(code_addr); 753 auto kernel = shader_cache.GetComputeKernel(code_addr);
754 program_manager.BindCompute(kernel->GetHandle());
755
734 SetupComputeTextures(kernel); 756 SetupComputeTextures(kernel);
735 SetupComputeImages(kernel); 757 SetupComputeImages(kernel);
736 758
@@ -745,7 +767,6 @@ void RasterizerOpenGL::DispatchCompute(GPUVAddr code_addr) {
745 buffer_cache.Unmap(); 767 buffer_cache.Unmap();
746 768
747 const auto& launch_desc = system.GPU().KeplerCompute().launch_description; 769 const auto& launch_desc = system.GPU().KeplerCompute().launch_description;
748 program_manager.BindCompute(kernel->GetHandle());
749 glDispatchCompute(launch_desc.grid_dim_x, launch_desc.grid_dim_y, launch_desc.grid_dim_z); 770 glDispatchCompute(launch_desc.grid_dim_x, launch_desc.grid_dim_y, launch_desc.grid_dim_z);
750 ++num_queued_commands; 771 ++num_queued_commands;
751} 772}
@@ -1005,40 +1026,66 @@ void RasterizerOpenGL::SetupConstBuffer(GLenum stage, u32 binding,
1005} 1026}
1006 1027
1007void RasterizerOpenGL::SetupDrawGlobalMemory(std::size_t stage_index, Shader* shader) { 1028void RasterizerOpenGL::SetupDrawGlobalMemory(std::size_t stage_index, Shader* shader) {
1029 static constexpr std::array TARGET_LUT = {
1030 GL_VERTEX_PROGRAM_NV, GL_TESS_CONTROL_PROGRAM_NV, GL_TESS_EVALUATION_PROGRAM_NV,
1031 GL_GEOMETRY_PROGRAM_NV, GL_FRAGMENT_PROGRAM_NV,
1032 };
1033
1008 auto& gpu{system.GPU()}; 1034 auto& gpu{system.GPU()};
1009 auto& memory_manager{gpu.MemoryManager()}; 1035 auto& memory_manager{gpu.MemoryManager()};
1010 const auto cbufs{gpu.Maxwell3D().state.shader_stages[stage_index]}; 1036 const auto& cbufs{gpu.Maxwell3D().state.shader_stages[stage_index]};
1037 const auto& entries{shader->GetEntries().global_memory_entries};
1038
1039 std::array<GLuint64EXT, 32> pointers;
1040 ASSERT(entries.size() < pointers.size());
1011 1041
1012 u32 binding = 1042 const bool assembly_shaders = device.UseAssemblyShaders();
1013 device.UseAssemblyShaders() ? 0 : device.GetBaseBindings(stage_index).shader_storage_buffer; 1043 u32 binding = assembly_shaders ? 0 : device.GetBaseBindings(stage_index).shader_storage_buffer;
1014 for (const auto& entry : shader->GetEntries().global_memory_entries) { 1044 for (const auto& entry : entries) {
1015 const GPUVAddr addr{cbufs.const_buffers[entry.cbuf_index].address + entry.cbuf_offset}; 1045 const GPUVAddr addr{cbufs.const_buffers[entry.cbuf_index].address + entry.cbuf_offset};
1016 const GPUVAddr gpu_addr{memory_manager.Read<u64>(addr)}; 1046 const GPUVAddr gpu_addr{memory_manager.Read<u64>(addr)};
1017 const u32 size{memory_manager.Read<u32>(addr + 8)}; 1047 const u32 size{memory_manager.Read<u32>(addr + 8)};
1018 SetupGlobalMemory(binding++, entry, gpu_addr, size); 1048 SetupGlobalMemory(binding, entry, gpu_addr, size, &pointers[binding]);
1049 ++binding;
1050 }
1051 if (assembly_shaders) {
1052 UpdateBindlessPointers(TARGET_LUT[stage_index], pointers.data(), entries.size());
1019 } 1053 }
1020} 1054}
1021 1055
1022void RasterizerOpenGL::SetupComputeGlobalMemory(Shader* kernel) { 1056void RasterizerOpenGL::SetupComputeGlobalMemory(Shader* kernel) {
1023 auto& gpu{system.GPU()}; 1057 auto& gpu{system.GPU()};
1024 auto& memory_manager{gpu.MemoryManager()}; 1058 auto& memory_manager{gpu.MemoryManager()};
1025 const auto cbufs{gpu.KeplerCompute().launch_description.const_buffer_config}; 1059 const auto& cbufs{gpu.KeplerCompute().launch_description.const_buffer_config};
1060 const auto& entries{kernel->GetEntries().global_memory_entries};
1061
1062 std::array<GLuint64EXT, 32> pointers;
1063 ASSERT(entries.size() < pointers.size());
1026 1064
1027 u32 binding = 0; 1065 u32 binding = 0;
1028 for (const auto& entry : kernel->GetEntries().global_memory_entries) { 1066 for (const auto& entry : entries) {
1029 const auto addr{cbufs[entry.cbuf_index].Address() + entry.cbuf_offset}; 1067 const GPUVAddr addr{cbufs[entry.cbuf_index].Address() + entry.cbuf_offset};
1030 const auto gpu_addr{memory_manager.Read<u64>(addr)}; 1068 const GPUVAddr gpu_addr{memory_manager.Read<u64>(addr)};
1031 const auto size{memory_manager.Read<u32>(addr + 8)}; 1069 const u32 size{memory_manager.Read<u32>(addr + 8)};
1032 SetupGlobalMemory(binding++, entry, gpu_addr, size); 1070 SetupGlobalMemory(binding, entry, gpu_addr, size, &pointers[binding]);
1071 ++binding;
1072 }
1073 if (device.UseAssemblyShaders()) {
1074 UpdateBindlessPointers(GL_COMPUTE_PROGRAM_NV, pointers.data(), entries.size());
1033 } 1075 }
1034} 1076}
1035 1077
1036void RasterizerOpenGL::SetupGlobalMemory(u32 binding, const GlobalMemoryEntry& entry, 1078void RasterizerOpenGL::SetupGlobalMemory(u32 binding, const GlobalMemoryEntry& entry,
1037 GPUVAddr gpu_addr, std::size_t size) { 1079 GPUVAddr gpu_addr, std::size_t size,
1038 const auto alignment{device.GetShaderStorageBufferAlignment()}; 1080 GLuint64EXT* pointer) {
1081 const std::size_t alignment{device.GetShaderStorageBufferAlignment()};
1039 const auto info = buffer_cache.UploadMemory(gpu_addr, size, alignment, entry.is_written); 1082 const auto info = buffer_cache.UploadMemory(gpu_addr, size, alignment, entry.is_written);
1040 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, binding, info.handle, info.offset, 1083 if (device.UseAssemblyShaders()) {
1041 static_cast<GLsizeiptr>(size)); 1084 *pointer = info.address + info.offset;
1085 } else {
1086 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, binding, info.handle, info.offset,
1087 static_cast<GLsizeiptr>(size));
1088 }
1042} 1089}
1043 1090
1044void RasterizerOpenGL::SetupDrawTextures(std::size_t stage_index, Shader* shader) { 1091void RasterizerOpenGL::SetupDrawTextures(std::size_t stage_index, Shader* shader) {
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index 4f082592f..ccc6f50f6 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -33,6 +33,7 @@
33#include "video_core/renderer_opengl/gl_state_tracker.h" 33#include "video_core/renderer_opengl/gl_state_tracker.h"
34#include "video_core/renderer_opengl/gl_texture_cache.h" 34#include "video_core/renderer_opengl/gl_texture_cache.h"
35#include "video_core/renderer_opengl/utils.h" 35#include "video_core/renderer_opengl/utils.h"
36#include "video_core/shader/async_shaders.h"
36#include "video_core/textures/texture.h" 37#include "video_core/textures/texture.h"
37 38
38namespace Core { 39namespace Core {
@@ -91,6 +92,14 @@ public:
91 return num_queued_commands > 0; 92 return num_queued_commands > 0;
92 } 93 }
93 94
95 VideoCommon::Shader::AsyncShaders& GetAsyncShaders() {
96 return async_shaders;
97 }
98
99 const VideoCommon::Shader::AsyncShaders& GetAsyncShaders() const {
100 return async_shaders;
101 }
102
94private: 103private:
95 /// Configures the color and depth framebuffer states. 104 /// Configures the color and depth framebuffer states.
96 void ConfigureFramebuffers(); 105 void ConfigureFramebuffers();
@@ -115,9 +124,9 @@ private:
115 /// Configures the current global memory entries to use for the kernel invocation. 124 /// Configures the current global memory entries to use for the kernel invocation.
116 void SetupComputeGlobalMemory(Shader* kernel); 125 void SetupComputeGlobalMemory(Shader* kernel);
117 126
118 /// Configures a constant buffer. 127 /// Configures a global memory buffer.
119 void SetupGlobalMemory(u32 binding, const GlobalMemoryEntry& entry, GPUVAddr gpu_addr, 128 void SetupGlobalMemory(u32 binding, const GlobalMemoryEntry& entry, GPUVAddr gpu_addr,
120 std::size_t size); 129 std::size_t size, GLuint64EXT* pointer);
121 130
122 /// Configures the current textures to use for the draw command. 131 /// Configures the current textures to use for the draw command.
123 void SetupDrawTextures(std::size_t stage_index, Shader* shader); 132 void SetupDrawTextures(std::size_t stage_index, Shader* shader);
@@ -242,6 +251,7 @@ private:
242 ScreenInfo& screen_info; 251 ScreenInfo& screen_info;
243 ProgramManager& program_manager; 252 ProgramManager& program_manager;
244 StateTracker& state_tracker; 253 StateTracker& state_tracker;
254 VideoCommon::Shader::AsyncShaders async_shaders;
245 255
246 static constexpr std::size_t STREAM_BUFFER_SIZE = 128 * 1024 * 1024; 256 static constexpr std::size_t STREAM_BUFFER_SIZE = 128 * 1024 * 1024;
247 257
diff --git a/src/video_core/renderer_opengl/gl_resource_manager.h b/src/video_core/renderer_opengl/gl_resource_manager.h
index f8b322227..b05cb641c 100644
--- a/src/video_core/renderer_opengl/gl_resource_manager.h
+++ b/src/video_core/renderer_opengl/gl_resource_manager.h
@@ -177,6 +177,12 @@ public:
177 Release(); 177 Release();
178 } 178 }
179 179
180 OGLAssemblyProgram& operator=(OGLAssemblyProgram&& o) noexcept {
181 Release();
182 handle = std::exchange(o.handle, 0);
183 return *this;
184 }
185
180 /// Deletes the internal OpenGL resource 186 /// Deletes the internal OpenGL resource
181 void Release(); 187 void Release();
182 188
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp
index c6a3bf3a1..be71e1733 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp
@@ -31,6 +31,7 @@
31#include "video_core/shader/registry.h" 31#include "video_core/shader/registry.h"
32#include "video_core/shader/shader_ir.h" 32#include "video_core/shader/shader_ir.h"
33#include "video_core/shader_cache.h" 33#include "video_core/shader_cache.h"
34#include "video_core/shader_notify.h"
34 35
35namespace OpenGL { 36namespace OpenGL {
36 37
@@ -125,7 +126,7 @@ std::shared_ptr<Registry> MakeRegistry(const ShaderDiskCacheEntry& entry) {
125 const VideoCore::GuestDriverProfile guest_profile{entry.texture_handler_size}; 126 const VideoCore::GuestDriverProfile guest_profile{entry.texture_handler_size};
126 const VideoCommon::Shader::SerializedRegistryInfo info{guest_profile, entry.bound_buffer, 127 const VideoCommon::Shader::SerializedRegistryInfo info{guest_profile, entry.bound_buffer,
127 entry.graphics_info, entry.compute_info}; 128 entry.graphics_info, entry.compute_info};
128 const auto registry = std::make_shared<Registry>(entry.type, info); 129 auto registry = std::make_shared<Registry>(entry.type, info);
129 for (const auto& [address, value] : entry.keys) { 130 for (const auto& [address, value] : entry.keys) {
130 const auto [buffer, offset] = address; 131 const auto [buffer, offset] = address;
131 registry->InsertKey(buffer, offset, value); 132 registry->InsertKey(buffer, offset, value);
@@ -140,9 +141,24 @@ std::shared_ptr<Registry> MakeRegistry(const ShaderDiskCacheEntry& entry) {
140 return registry; 141 return registry;
141} 142}
142 143
144std::unordered_set<GLenum> GetSupportedFormats() {
145 GLint num_formats;
146 glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &num_formats);
147
148 std::vector<GLint> formats(num_formats);
149 glGetIntegerv(GL_PROGRAM_BINARY_FORMATS, formats.data());
150
151 std::unordered_set<GLenum> supported_formats;
152 for (const GLint format : formats) {
153 supported_formats.insert(static_cast<GLenum>(format));
154 }
155 return supported_formats;
156}
157
158} // Anonymous namespace
159
143ProgramSharedPtr BuildShader(const Device& device, ShaderType shader_type, u64 unique_identifier, 160ProgramSharedPtr BuildShader(const Device& device, ShaderType shader_type, u64 unique_identifier,
144 const ShaderIR& ir, const Registry& registry, 161 const ShaderIR& ir, const Registry& registry, bool hint_retrievable) {
145 bool hint_retrievable = false) {
146 const std::string shader_id = MakeShaderID(unique_identifier, shader_type); 162 const std::string shader_id = MakeShaderID(unique_identifier, shader_type);
147 LOG_INFO(Render_OpenGL, "{}", shader_id); 163 LOG_INFO(Render_OpenGL, "{}", shader_id);
148 164
@@ -181,30 +197,17 @@ ProgramSharedPtr BuildShader(const Device& device, ShaderType shader_type, u64 u
181 return program; 197 return program;
182} 198}
183 199
184std::unordered_set<GLenum> GetSupportedFormats() {
185 GLint num_formats;
186 glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &num_formats);
187
188 std::vector<GLint> formats(num_formats);
189 glGetIntegerv(GL_PROGRAM_BINARY_FORMATS, formats.data());
190
191 std::unordered_set<GLenum> supported_formats;
192 for (const GLint format : formats) {
193 supported_formats.insert(static_cast<GLenum>(format));
194 }
195 return supported_formats;
196}
197
198} // Anonymous namespace
199
200Shader::Shader(std::shared_ptr<VideoCommon::Shader::Registry> registry_, ShaderEntries entries_, 200Shader::Shader(std::shared_ptr<VideoCommon::Shader::Registry> registry_, ShaderEntries entries_,
201 ProgramSharedPtr program_) 201 ProgramSharedPtr program_, bool is_built)
202 : registry{std::move(registry_)}, entries{std::move(entries_)}, program{std::move(program_)} { 202 : registry{std::move(registry_)}, entries{std::move(entries_)}, program{std::move(program_)},
203 is_built(is_built) {
203 handle = program->assembly_program.handle; 204 handle = program->assembly_program.handle;
204 if (handle == 0) { 205 if (handle == 0) {
205 handle = program->source_program.handle; 206 handle = program->source_program.handle;
206 } 207 }
207 ASSERT(handle != 0); 208 if (is_built) {
209 ASSERT(handle != 0);
210 }
208} 211}
209 212
210Shader::~Shader() = default; 213Shader::~Shader() = default;
@@ -214,42 +217,79 @@ GLuint Shader::GetHandle() const {
214 return handle; 217 return handle;
215} 218}
216 219
217std::unique_ptr<Shader> Shader::CreateStageFromMemory(const ShaderParameters& params, 220bool Shader::IsBuilt() const {
218 Maxwell::ShaderProgram program_type, 221 return is_built;
219 ProgramCode code, ProgramCode code_b) { 222}
223
224void Shader::AsyncOpenGLBuilt(OGLProgram new_program) {
225 program->source_program = std::move(new_program);
226 handle = program->source_program.handle;
227 is_built = true;
228}
229
230void Shader::AsyncGLASMBuilt(OGLAssemblyProgram new_program) {
231 program->assembly_program = std::move(new_program);
232 handle = program->assembly_program.handle;
233 is_built = true;
234}
235
236std::unique_ptr<Shader> Shader::CreateStageFromMemory(
237 const ShaderParameters& params, Maxwell::ShaderProgram program_type, ProgramCode code,
238 ProgramCode code_b, VideoCommon::Shader::AsyncShaders& async_shaders, VAddr cpu_addr) {
220 const auto shader_type = GetShaderType(program_type); 239 const auto shader_type = GetShaderType(program_type);
221 const std::size_t size_in_bytes = code.size() * sizeof(u64);
222 240
223 auto registry = std::make_shared<Registry>(shader_type, params.system.GPU().Maxwell3D()); 241 auto& gpu = params.system.GPU();
224 const ShaderIR ir(code, STAGE_MAIN_OFFSET, COMPILER_SETTINGS, *registry); 242 gpu.ShaderNotify().MarkSharderBuilding();
225 // TODO(Rodrigo): Handle VertexA shaders 243
226 // std::optional<ShaderIR> ir_b; 244 auto registry = std::make_shared<Registry>(shader_type, gpu.Maxwell3D());
227 // if (!code_b.empty()) { 245 if (!async_shaders.IsShaderAsync(params.system.GPU()) ||
228 // ir_b.emplace(code_b, STAGE_MAIN_OFFSET); 246 !params.device.UseAsynchronousShaders()) {
229 // } 247 const ShaderIR ir(code, STAGE_MAIN_OFFSET, COMPILER_SETTINGS, *registry);
230 auto program = BuildShader(params.device, shader_type, params.unique_identifier, ir, *registry); 248 // TODO(Rodrigo): Handle VertexA shaders
249 // std::optional<ShaderIR> ir_b;
250 // if (!code_b.empty()) {
251 // ir_b.emplace(code_b, STAGE_MAIN_OFFSET);
252 // }
253 auto program =
254 BuildShader(params.device, shader_type, params.unique_identifier, ir, *registry);
255 ShaderDiskCacheEntry entry;
256 entry.type = shader_type;
257 entry.code = std::move(code);
258 entry.code_b = std::move(code_b);
259 entry.unique_identifier = params.unique_identifier;
260 entry.bound_buffer = registry->GetBoundBuffer();
261 entry.graphics_info = registry->GetGraphicsInfo();
262 entry.keys = registry->GetKeys();
263 entry.bound_samplers = registry->GetBoundSamplers();
264 entry.bindless_samplers = registry->GetBindlessSamplers();
265 params.disk_cache.SaveEntry(std::move(entry));
266
267 gpu.ShaderNotify().MarkShaderComplete();
268
269 return std::unique_ptr<Shader>(new Shader(std::move(registry),
270 MakeEntries(params.device, ir, shader_type),
271 std::move(program), true));
272 } else {
273 // Required for entries
274 const ShaderIR ir(code, STAGE_MAIN_OFFSET, COMPILER_SETTINGS, *registry);
275 auto entries = MakeEntries(params.device, ir, shader_type);
231 276
232 ShaderDiskCacheEntry entry; 277 async_shaders.QueueOpenGLShader(params.device, shader_type, params.unique_identifier,
233 entry.type = shader_type; 278 std::move(code), std::move(code_b), STAGE_MAIN_OFFSET,
234 entry.code = std::move(code); 279 COMPILER_SETTINGS, *registry, cpu_addr);
235 entry.code_b = std::move(code_b);
236 entry.unique_identifier = params.unique_identifier;
237 entry.bound_buffer = registry->GetBoundBuffer();
238 entry.graphics_info = registry->GetGraphicsInfo();
239 entry.keys = registry->GetKeys();
240 entry.bound_samplers = registry->GetBoundSamplers();
241 entry.bindless_samplers = registry->GetBindlessSamplers();
242 params.disk_cache.SaveEntry(std::move(entry));
243 280
244 return std::unique_ptr<Shader>(new Shader( 281 auto program = std::make_shared<ProgramHandle>();
245 std::move(registry), MakeEntries(params.device, ir, shader_type), std::move(program))); 282 return std::unique_ptr<Shader>(
283 new Shader(std::move(registry), std::move(entries), std::move(program), false));
284 }
246} 285}
247 286
248std::unique_ptr<Shader> Shader::CreateKernelFromMemory(const ShaderParameters& params, 287std::unique_ptr<Shader> Shader::CreateKernelFromMemory(const ShaderParameters& params,
249 ProgramCode code) { 288 ProgramCode code) {
250 const std::size_t size_in_bytes = code.size() * sizeof(u64); 289 auto& gpu = params.system.GPU();
290 gpu.ShaderNotify().MarkSharderBuilding();
251 291
252 auto& engine = params.system.GPU().KeplerCompute(); 292 auto& engine = gpu.KeplerCompute();
253 auto registry = std::make_shared<Registry>(ShaderType::Compute, engine); 293 auto registry = std::make_shared<Registry>(ShaderType::Compute, engine);
254 const ShaderIR ir(code, KERNEL_MAIN_OFFSET, COMPILER_SETTINGS, *registry); 294 const ShaderIR ir(code, KERNEL_MAIN_OFFSET, COMPILER_SETTINGS, *registry);
255 const u64 uid = params.unique_identifier; 295 const u64 uid = params.unique_identifier;
@@ -266,6 +306,8 @@ std::unique_ptr<Shader> Shader::CreateKernelFromMemory(const ShaderParameters& p
266 entry.bindless_samplers = registry->GetBindlessSamplers(); 306 entry.bindless_samplers = registry->GetBindlessSamplers();
267 params.disk_cache.SaveEntry(std::move(entry)); 307 params.disk_cache.SaveEntry(std::move(entry));
268 308
309 gpu.ShaderNotify().MarkShaderComplete();
310
269 return std::unique_ptr<Shader>(new Shader(std::move(registry), 311 return std::unique_ptr<Shader>(new Shader(std::move(registry),
270 MakeEntries(params.device, ir, ShaderType::Compute), 312 MakeEntries(params.device, ir, ShaderType::Compute),
271 std::move(program))); 313 std::move(program)));
@@ -436,14 +478,51 @@ ProgramSharedPtr ShaderCacheOpenGL::GeneratePrecompiledProgram(
436 return program; 478 return program;
437} 479}
438 480
439Shader* ShaderCacheOpenGL::GetStageProgram(Maxwell::ShaderProgram program) { 481Shader* ShaderCacheOpenGL::GetStageProgram(Maxwell::ShaderProgram program,
482 VideoCommon::Shader::AsyncShaders& async_shaders) {
440 if (!system.GPU().Maxwell3D().dirty.flags[Dirty::Shaders]) { 483 if (!system.GPU().Maxwell3D().dirty.flags[Dirty::Shaders]) {
441 return last_shaders[static_cast<std::size_t>(program)]; 484 auto* last_shader = last_shaders[static_cast<std::size_t>(program)];
485 if (last_shader->IsBuilt()) {
486 return last_shader;
487 }
442 } 488 }
443 489
444 auto& memory_manager{system.GPU().MemoryManager()}; 490 auto& memory_manager{system.GPU().MemoryManager()};
445 const GPUVAddr address{GetShaderAddress(system, program)}; 491 const GPUVAddr address{GetShaderAddress(system, program)};
446 492
493 if (device.UseAsynchronousShaders() && async_shaders.HasCompletedWork()) {
494 auto completed_work = async_shaders.GetCompletedWork();
495 for (auto& work : completed_work) {
496 Shader* shader = TryGet(work.cpu_address);
497 auto& gpu = system.GPU();
498 gpu.ShaderNotify().MarkShaderComplete();
499 if (shader == nullptr) {
500 continue;
501 }
502 using namespace VideoCommon::Shader;
503 if (work.backend == AsyncShaders::Backend::OpenGL) {
504 shader->AsyncOpenGLBuilt(std::move(work.program.opengl));
505 } else if (work.backend == AsyncShaders::Backend::GLASM) {
506 shader->AsyncGLASMBuilt(std::move(work.program.glasm));
507 }
508
509 ShaderDiskCacheEntry entry;
510 entry.type = work.shader_type;
511 entry.code = std::move(work.code);
512 entry.code_b = std::move(work.code_b);
513 entry.unique_identifier = work.uid;
514
515 auto& registry = shader->GetRegistry();
516
517 entry.bound_buffer = registry.GetBoundBuffer();
518 entry.graphics_info = registry.GetGraphicsInfo();
519 entry.keys = registry.GetKeys();
520 entry.bound_samplers = registry.GetBoundSamplers();
521 entry.bindless_samplers = registry.GetBindlessSamplers();
522 disk_cache.SaveEntry(std::move(entry));
523 }
524 }
525
447 // Look up shader in the cache based on address 526 // Look up shader in the cache based on address
448 const auto cpu_addr{memory_manager.GpuToCpuAddress(address)}; 527 const auto cpu_addr{memory_manager.GpuToCpuAddress(address)};
449 if (Shader* const shader{cpu_addr ? TryGet(*cpu_addr) : null_shader.get()}) { 528 if (Shader* const shader{cpu_addr ? TryGet(*cpu_addr) : null_shader.get()}) {
@@ -471,7 +550,8 @@ Shader* ShaderCacheOpenGL::GetStageProgram(Maxwell::ShaderProgram program) {
471 std::unique_ptr<Shader> shader; 550 std::unique_ptr<Shader> shader;
472 const auto found = runtime_cache.find(unique_identifier); 551 const auto found = runtime_cache.find(unique_identifier);
473 if (found == runtime_cache.end()) { 552 if (found == runtime_cache.end()) {
474 shader = Shader::CreateStageFromMemory(params, program, std::move(code), std::move(code_b)); 553 shader = Shader::CreateStageFromMemory(params, program, std::move(code), std::move(code_b),
554 async_shaders, cpu_addr.value_or(0));
475 } else { 555 } else {
476 shader = Shader::CreateFromCache(params, found->second); 556 shader = Shader::CreateFromCache(params, found->second);
477 } 557 }
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.h b/src/video_core/renderer_opengl/gl_shader_cache.h
index 994aaeaf2..7528ac686 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.h
+++ b/src/video_core/renderer_opengl/gl_shader_cache.h
@@ -33,6 +33,10 @@ namespace Core::Frontend {
33class EmuWindow; 33class EmuWindow;
34} 34}
35 35
36namespace VideoCommon::Shader {
37class AsyncShaders;
38}
39
36namespace OpenGL { 40namespace OpenGL {
37 41
38class Device; 42class Device;
@@ -61,6 +65,11 @@ struct ShaderParameters {
61 u64 unique_identifier; 65 u64 unique_identifier;
62}; 66};
63 67
68ProgramSharedPtr BuildShader(const Device& device, Tegra::Engines::ShaderType shader_type,
69 u64 unique_identifier, const VideoCommon::Shader::ShaderIR& ir,
70 const VideoCommon::Shader::Registry& registry,
71 bool hint_retrievable = false);
72
64class Shader final { 73class Shader final {
65public: 74public:
66 ~Shader(); 75 ~Shader();
@@ -68,15 +77,28 @@ public:
68 /// Gets the GL program handle for the shader 77 /// Gets the GL program handle for the shader
69 GLuint GetHandle() const; 78 GLuint GetHandle() const;
70 79
80 bool IsBuilt() const;
81
71 /// Gets the shader entries for the shader 82 /// Gets the shader entries for the shader
72 const ShaderEntries& GetEntries() const { 83 const ShaderEntries& GetEntries() const {
73 return entries; 84 return entries;
74 } 85 }
75 86
76 static std::unique_ptr<Shader> CreateStageFromMemory(const ShaderParameters& params, 87 const VideoCommon::Shader::Registry& GetRegistry() const {
77 Maxwell::ShaderProgram program_type, 88 return *registry;
78 ProgramCode program_code, 89 }
79 ProgramCode program_code_b); 90
91 /// Mark a OpenGL shader as built
92 void AsyncOpenGLBuilt(OGLProgram new_program);
93
94 /// Mark a GLASM shader as built
95 void AsyncGLASMBuilt(OGLAssemblyProgram new_program);
96
97 static std::unique_ptr<Shader> CreateStageFromMemory(
98 const ShaderParameters& params, Maxwell::ShaderProgram program_type,
99 ProgramCode program_code, ProgramCode program_code_b,
100 VideoCommon::Shader::AsyncShaders& async_shaders, VAddr cpu_addr);
101
80 static std::unique_ptr<Shader> CreateKernelFromMemory(const ShaderParameters& params, 102 static std::unique_ptr<Shader> CreateKernelFromMemory(const ShaderParameters& params,
81 ProgramCode code); 103 ProgramCode code);
82 104
@@ -85,12 +107,13 @@ public:
85 107
86private: 108private:
87 explicit Shader(std::shared_ptr<VideoCommon::Shader::Registry> registry, ShaderEntries entries, 109 explicit Shader(std::shared_ptr<VideoCommon::Shader::Registry> registry, ShaderEntries entries,
88 ProgramSharedPtr program); 110 ProgramSharedPtr program, bool is_built = true);
89 111
90 std::shared_ptr<VideoCommon::Shader::Registry> registry; 112 std::shared_ptr<VideoCommon::Shader::Registry> registry;
91 ShaderEntries entries; 113 ShaderEntries entries;
92 ProgramSharedPtr program; 114 ProgramSharedPtr program;
93 GLuint handle = 0; 115 GLuint handle = 0;
116 bool is_built{};
94}; 117};
95 118
96class ShaderCacheOpenGL final : public VideoCommon::ShaderCache<Shader> { 119class ShaderCacheOpenGL final : public VideoCommon::ShaderCache<Shader> {
@@ -104,7 +127,8 @@ public:
104 const VideoCore::DiskResourceLoadCallback& callback); 127 const VideoCore::DiskResourceLoadCallback& callback);
105 128
106 /// Gets the current specified shader stage program 129 /// Gets the current specified shader stage program
107 Shader* GetStageProgram(Maxwell::ShaderProgram program); 130 Shader* GetStageProgram(Maxwell::ShaderProgram program,
131 VideoCommon::Shader::AsyncShaders& async_shaders);
108 132
109 /// Gets a compute kernel in the passed address 133 /// Gets a compute kernel in the passed address
110 Shader* GetComputeKernel(GPUVAddr code_addr); 134 Shader* GetComputeKernel(GPUVAddr code_addr);
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 2c49aeaac..3f75fcd2b 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -602,8 +602,15 @@ private:
602 return; 602 return;
603 } 603 }
604 const auto& info = registry.GetComputeInfo(); 604 const auto& info = registry.GetComputeInfo();
605 if (const u32 size = info.shared_memory_size_in_words; size > 0) { 605 if (u32 size = info.shared_memory_size_in_words * 4; size > 0) {
606 code.AddLine("shared uint smem[{}];", size); 606 const u32 limit = device.GetMaxComputeSharedMemorySize();
607 if (size > limit) {
608 LOG_ERROR(Render_OpenGL, "Shared memory size {} is clamped to host's limit {}",
609 size, limit);
610 size = limit;
611 }
612
613 code.AddLine("shared uint smem[{}];", size / 4);
607 code.AddNewLine(); 614 code.AddNewLine();
608 } 615 }
609 code.AddLine("layout (local_size_x = {}, local_size_y = {}, local_size_z = {}) in;", 616 code.AddLine("layout (local_size_x = {}, local_size_y = {}, local_size_z = {}) in;",
@@ -1912,7 +1919,7 @@ private:
1912 Expression Comparison(Operation operation) { 1919 Expression Comparison(Operation operation) {
1913 static_assert(!unordered || type == Type::Float); 1920 static_assert(!unordered || type == Type::Float);
1914 1921
1915 const Expression expr = GenerateBinaryInfix(operation, op, Type::Bool, type, type); 1922 Expression expr = GenerateBinaryInfix(operation, op, Type::Bool, type, type);
1916 1923
1917 if constexpr (op.compare("!=") == 0 && type == Type::Float && !unordered) { 1924 if constexpr (op.compare("!=") == 0 && type == Type::Float && !unordered) {
1918 // GLSL's operator!=(float, float) doesn't seem be ordered. This happens on both AMD's 1925 // GLSL's operator!=(float, float) doesn't seem be ordered. This happens on both AMD's
@@ -1952,10 +1959,6 @@ private:
1952 return {fmt::format("({} != 0)", carry), Type::Bool}; 1959 return {fmt::format("({} != 0)", carry), Type::Bool};
1953 } 1960 }
1954 1961
1955 Expression LogicalFIsNan(Operation operation) {
1956 return GenerateUnary(operation, "isnan", Type::Bool, Type::Float);
1957 }
1958
1959 Expression LogicalAssign(Operation operation) { 1962 Expression LogicalAssign(Operation operation) {
1960 const Node& dest = operation[0]; 1963 const Node& dest = operation[0];
1961 const Node& src = operation[1]; 1964 const Node& src = operation[1];
@@ -2771,15 +2774,6 @@ private:
2771 return std::min<u32>(device.GetMaxVaryings(), Maxwell::NumVaryings); 2774 return std::min<u32>(device.GetMaxVaryings(), Maxwell::NumVaryings);
2772 } 2775 }
2773 2776
2774 bool IsRenderTargetEnabled(u32 render_target) const {
2775 for (u32 component = 0; component < 4; ++component) {
2776 if (header.ps.IsColorComponentOutputEnabled(render_target, component)) {
2777 return true;
2778 }
2779 }
2780 return false;
2781 }
2782
2783 const Device& device; 2777 const Device& device;
2784 const ShaderIR& ir; 2778 const ShaderIR& ir;
2785 const Registry& registry; 2779 const Registry& registry;
diff --git a/src/video_core/renderer_opengl/gl_shader_manager.cpp b/src/video_core/renderer_opengl/gl_shader_manager.cpp
index 8e754fa90..691c6c79b 100644
--- a/src/video_core/renderer_opengl/gl_shader_manager.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_manager.cpp
@@ -11,8 +11,30 @@
11 11
12namespace OpenGL { 12namespace OpenGL {
13 13
14ProgramManager::ProgramManager(const Device& device) { 14namespace {
15 use_assembly_programs = device.UseAssemblyShaders(); 15
16void BindProgram(GLenum stage, GLuint current, GLuint old, bool& enabled) {
17 if (current == old) {
18 return;
19 }
20 if (current == 0) {
21 if (enabled) {
22 enabled = false;
23 glDisable(stage);
24 }
25 return;
26 }
27 if (!enabled) {
28 enabled = true;
29 glEnable(stage);
30 }
31 glBindProgramARB(stage, current);
32}
33
34} // Anonymous namespace
35
36ProgramManager::ProgramManager(const Device& device)
37 : use_assembly_programs{device.UseAssemblyShaders()} {
16 if (use_assembly_programs) { 38 if (use_assembly_programs) {
17 glEnable(GL_COMPUTE_PROGRAM_NV); 39 glEnable(GL_COMPUTE_PROGRAM_NV);
18 } else { 40 } else {
@@ -33,9 +55,7 @@ void ProgramManager::BindCompute(GLuint program) {
33} 55}
34 56
35void ProgramManager::BindGraphicsPipeline() { 57void ProgramManager::BindGraphicsPipeline() {
36 if (use_assembly_programs) { 58 if (!use_assembly_programs) {
37 UpdateAssemblyPrograms();
38 } else {
39 UpdateSourcePrograms(); 59 UpdateSourcePrograms();
40 } 60 }
41} 61}
@@ -63,32 +83,25 @@ void ProgramManager::RestoreGuestPipeline() {
63 } 83 }
64} 84}
65 85
66void ProgramManager::UpdateAssemblyPrograms() { 86void ProgramManager::UseVertexShader(GLuint program) {
67 const auto update_state = [](GLenum stage, bool& enabled, GLuint current, GLuint old) { 87 if (use_assembly_programs) {
68 if (current == old) { 88 BindProgram(GL_VERTEX_PROGRAM_NV, program, current_state.vertex, vertex_enabled);
69 return; 89 }
70 } 90 current_state.vertex = program;
71 if (current == 0) { 91}
72 if (enabled) {
73 enabled = false;
74 glDisable(stage);
75 }
76 return;
77 }
78 if (!enabled) {
79 enabled = true;
80 glEnable(stage);
81 }
82 glBindProgramARB(stage, current);
83 };
84 92
85 update_state(GL_VERTEX_PROGRAM_NV, vertex_enabled, current_state.vertex, old_state.vertex); 93void ProgramManager::UseGeometryShader(GLuint program) {
86 update_state(GL_GEOMETRY_PROGRAM_NV, geometry_enabled, current_state.geometry, 94 if (use_assembly_programs) {
87 old_state.geometry); 95 BindProgram(GL_GEOMETRY_PROGRAM_NV, program, current_state.vertex, geometry_enabled);
88 update_state(GL_FRAGMENT_PROGRAM_NV, fragment_enabled, current_state.fragment, 96 }
89 old_state.fragment); 97 current_state.geometry = program;
98}
90 99
91 old_state = current_state; 100void ProgramManager::UseFragmentShader(GLuint program) {
101 if (use_assembly_programs) {
102 BindProgram(GL_FRAGMENT_PROGRAM_NV, program, current_state.vertex, fragment_enabled);
103 }
104 current_state.fragment = program;
92} 105}
93 106
94void ProgramManager::UpdateSourcePrograms() { 107void ProgramManager::UpdateSourcePrograms() {
diff --git a/src/video_core/renderer_opengl/gl_shader_manager.h b/src/video_core/renderer_opengl/gl_shader_manager.h
index 0f03b4f12..950e0dfcb 100644
--- a/src/video_core/renderer_opengl/gl_shader_manager.h
+++ b/src/video_core/renderer_opengl/gl_shader_manager.h
@@ -45,17 +45,9 @@ public:
45 /// Rewinds BindHostPipeline state changes. 45 /// Rewinds BindHostPipeline state changes.
46 void RestoreGuestPipeline(); 46 void RestoreGuestPipeline();
47 47
48 void UseVertexShader(GLuint program) { 48 void UseVertexShader(GLuint program);
49 current_state.vertex = program; 49 void UseGeometryShader(GLuint program);
50 } 50 void UseFragmentShader(GLuint program);
51
52 void UseGeometryShader(GLuint program) {
53 current_state.geometry = program;
54 }
55
56 void UseFragmentShader(GLuint program) {
57 current_state.fragment = program;
58 }
59 51
60private: 52private:
61 struct PipelineState { 53 struct PipelineState {
@@ -64,9 +56,6 @@ private:
64 GLuint fragment = 0; 56 GLuint fragment = 0;
65 }; 57 };
66 58
67 /// Update NV_gpu_program5 programs.
68 void UpdateAssemblyPrograms();
69
70 /// Update GLSL programs. 59 /// Update GLSL programs.
71 void UpdateSourcePrograms(); 60 void UpdateSourcePrograms();
72 61
diff --git a/src/video_core/renderer_opengl/gl_stream_buffer.cpp b/src/video_core/renderer_opengl/gl_stream_buffer.cpp
index 3655ff629..887995cf4 100644
--- a/src/video_core/renderer_opengl/gl_stream_buffer.cpp
+++ b/src/video_core/renderer_opengl/gl_stream_buffer.cpp
@@ -35,7 +35,7 @@ OGLStreamBuffer::OGLStreamBuffer(const Device& device, GLsizeiptr size, bool ver
35 mapped_ptr = static_cast<u8*>( 35 mapped_ptr = static_cast<u8*>(
36 glMapNamedBufferRange(gl_buffer.handle, 0, buffer_size, flags | GL_MAP_FLUSH_EXPLICIT_BIT)); 36 glMapNamedBufferRange(gl_buffer.handle, 0, buffer_size, flags | GL_MAP_FLUSH_EXPLICIT_BIT));
37 37
38 if (device.HasVertexBufferUnifiedMemory()) { 38 if (device.UseAssemblyShaders() || device.HasVertexBufferUnifiedMemory()) {
39 glMakeNamedBufferResidentNV(gl_buffer.handle, GL_READ_ONLY); 39 glMakeNamedBufferResidentNV(gl_buffer.handle, GL_READ_ONLY);
40 glGetNamedBufferParameterui64vNV(gl_buffer.handle, GL_BUFFER_GPU_ADDRESS_NV, &gpu_address); 40 glGetNamedBufferParameterui64vNV(gl_buffer.handle, GL_BUFFER_GPU_ADDRESS_NV, &gpu_address);
41 } 41 }
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp
index 61505879b..0a7bc9e2b 100644
--- a/src/video_core/renderer_opengl/gl_texture_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp
@@ -41,91 +41,103 @@ struct FormatTuple {
41}; 41};
42 42
43constexpr std::array<FormatTuple, VideoCore::Surface::MaxPixelFormat> tex_format_tuples = {{ 43constexpr std::array<FormatTuple, VideoCore::Surface::MaxPixelFormat> tex_format_tuples = {{
44 {GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV}, // ABGR8U 44 {GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV}, // A8B8G8R8_UNORM
45 {GL_RGBA8_SNORM, GL_RGBA, GL_BYTE}, // ABGR8S 45 {GL_RGBA8_SNORM, GL_RGBA, GL_BYTE}, // A8B8G8R8_SNORM
46 {GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE}, // ABGR8UI 46 {GL_RGBA8I, GL_RGBA_INTEGER, GL_BYTE}, // A8B8G8R8_SINT
47 {GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV}, // B5G6R5U 47 {GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE}, // A8B8G8R8_UINT
48 {GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV}, // A2B10G10R10U 48 {GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5}, // R5G6B5_UNORM
49 {GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV}, // A1B5G5R5U 49 {GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV}, // B5G6R5_UNORM
50 {GL_R8, GL_RED, GL_UNSIGNED_BYTE}, // R8U 50 {GL_RGB5_A1, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV}, // A1R5G5B5_UNORM
51 {GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE}, // R8UI 51 {GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV}, // A2B10G10R10_UNORM
52 {GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT}, // RGBA16F 52 {GL_RGB10_A2UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV}, // A2B10G10R10_UINT
53 {GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT}, // RGBA16U 53 {GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV}, // A1B5G5R5_UNORM
54 {GL_RGBA16_SNORM, GL_RGBA, GL_SHORT}, // RGBA16S 54 {GL_R8, GL_RED, GL_UNSIGNED_BYTE}, // R8_UNORM
55 {GL_RGBA16UI, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT}, // RGBA16UI 55 {GL_R8_SNORM, GL_RED, GL_BYTE}, // R8_SNORM
56 {GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV}, // R11FG11FB10F 56 {GL_R8I, GL_RED_INTEGER, GL_BYTE}, // R8_SINT
57 {GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT}, // RGBA32UI 57 {GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE}, // R8_UINT
58 {GL_COMPRESSED_RGBA_S3TC_DXT1_EXT}, // DXT1 58 {GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT}, // R16G16B16A16_FLOAT
59 {GL_COMPRESSED_RGBA_S3TC_DXT3_EXT}, // DXT23 59 {GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT}, // R16G16B16A16_UNORM
60 {GL_COMPRESSED_RGBA_S3TC_DXT5_EXT}, // DXT45 60 {GL_RGBA16_SNORM, GL_RGBA, GL_SHORT}, // R16G16B16A16_SNORM
61 {GL_COMPRESSED_RED_RGTC1}, // DXN1 61 {GL_RGBA16I, GL_RGBA_INTEGER, GL_SHORT}, // R16G16B16A16_SINT
62 {GL_COMPRESSED_RG_RGTC2}, // DXN2UNORM 62 {GL_RGBA16UI, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT}, // R16G16B16A16_UINT
63 {GL_COMPRESSED_SIGNED_RG_RGTC2}, // DXN2SNORM 63 {GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV}, // B10G11R11_FLOAT
64 {GL_COMPRESSED_RGBA_BPTC_UNORM}, // BC7U 64 {GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT}, // R32G32B32A32_UINT
65 {GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT}, // BC6H_UF16 65 {GL_COMPRESSED_RGBA_S3TC_DXT1_EXT}, // BC1_RGBA_UNORM
66 {GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT}, // BC6H_SF16 66 {GL_COMPRESSED_RGBA_S3TC_DXT3_EXT}, // BC2_UNORM
67 {GL_COMPRESSED_RGBA_ASTC_4x4_KHR}, // ASTC_2D_4X4 67 {GL_COMPRESSED_RGBA_S3TC_DXT5_EXT}, // BC3_UNORM
68 {GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE}, // BGRA8 68 {GL_COMPRESSED_RED_RGTC1}, // BC4_UNORM
69 {GL_RGBA32F, GL_RGBA, GL_FLOAT}, // RGBA32F 69 {GL_COMPRESSED_SIGNED_RED_RGTC1}, // BC4_SNORM
70 {GL_RG32F, GL_RG, GL_FLOAT}, // RG32F 70 {GL_COMPRESSED_RG_RGTC2}, // BC5_UNORM
71 {GL_R32F, GL_RED, GL_FLOAT}, // R32F 71 {GL_COMPRESSED_SIGNED_RG_RGTC2}, // BC5_SNORM
72 {GL_R16F, GL_RED, GL_HALF_FLOAT}, // R16F 72 {GL_COMPRESSED_RGBA_BPTC_UNORM}, // BC7_UNORM
73 {GL_R16, GL_RED, GL_UNSIGNED_SHORT}, // R16U 73 {GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT}, // BC6H_UFLOAT
74 {GL_R16_SNORM, GL_RED, GL_SHORT}, // R16S 74 {GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT}, // BC6H_SFLOAT
75 {GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT}, // R16UI 75 {GL_COMPRESSED_RGBA_ASTC_4x4_KHR}, // ASTC_2D_4X4_UNORM
76 {GL_R16I, GL_RED_INTEGER, GL_SHORT}, // R16I 76 {GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE}, // B8G8R8A8_UNORM
77 {GL_RG16, GL_RG, GL_UNSIGNED_SHORT}, // RG16 77 {GL_RGBA32F, GL_RGBA, GL_FLOAT}, // R32G32B32A32_FLOAT
78 {GL_RG16F, GL_RG, GL_HALF_FLOAT}, // RG16F 78 {GL_RGBA32I, GL_RGBA_INTEGER, GL_INT}, // R32G32B32A32_SINT
79 {GL_RG16UI, GL_RG_INTEGER, GL_UNSIGNED_SHORT}, // RG16UI 79 {GL_RG32F, GL_RG, GL_FLOAT}, // R32G32_FLOAT
80 {GL_RG16I, GL_RG_INTEGER, GL_SHORT}, // RG16I 80 {GL_RG32I, GL_RG_INTEGER, GL_INT}, // R32G32_SINT
81 {GL_RG16_SNORM, GL_RG, GL_SHORT}, // RG16S 81 {GL_R32F, GL_RED, GL_FLOAT}, // R32_FLOAT
82 {GL_RGB32F, GL_RGB, GL_FLOAT}, // RGB32F 82 {GL_R16F, GL_RED, GL_HALF_FLOAT}, // R16_FLOAT
83 {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV}, // RGBA8_SRGB 83 {GL_R16, GL_RED, GL_UNSIGNED_SHORT}, // R16_UNORM
84 {GL_RG8, GL_RG, GL_UNSIGNED_BYTE}, // RG8U 84 {GL_R16_SNORM, GL_RED, GL_SHORT}, // R16_SNORM
85 {GL_RG8_SNORM, GL_RG, GL_BYTE}, // RG8S 85 {GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT}, // R16_UINT
86 {GL_RG8UI, GL_RG_INTEGER, GL_UNSIGNED_INT}, // RG8UI 86 {GL_R16I, GL_RED_INTEGER, GL_SHORT}, // R16_SINT
87 {GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT}, // RG32UI 87 {GL_RG16, GL_RG, GL_UNSIGNED_SHORT}, // R16G16_UNORM
88 {GL_RGB16F, GL_RGBA, GL_HALF_FLOAT}, // RGBX16F 88 {GL_RG16F, GL_RG, GL_HALF_FLOAT}, // R16G16_FLOAT
89 {GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT}, // R32UI 89 {GL_RG16UI, GL_RG_INTEGER, GL_UNSIGNED_SHORT}, // R16G16_UINT
90 {GL_R32I, GL_RED_INTEGER, GL_INT}, // R32I 90 {GL_RG16I, GL_RG_INTEGER, GL_SHORT}, // R16G16_SINT
91 {GL_COMPRESSED_RGBA_ASTC_8x8_KHR}, // ASTC_2D_8X8 91 {GL_RG16_SNORM, GL_RG, GL_SHORT}, // R16G16_SNORM
92 {GL_COMPRESSED_RGBA_ASTC_8x5_KHR}, // ASTC_2D_8X5 92 {GL_RGB32F, GL_RGB, GL_FLOAT}, // R32G32B32_FLOAT
93 {GL_COMPRESSED_RGBA_ASTC_5x4_KHR}, // ASTC_2D_5X4 93 {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV}, // A8B8G8R8_SRGB
94 {GL_SRGB8_ALPHA8, GL_BGRA, GL_UNSIGNED_BYTE}, // BGRA8 94 {GL_RG8, GL_RG, GL_UNSIGNED_BYTE}, // R8G8_UNORM
95 {GL_RG8_SNORM, GL_RG, GL_BYTE}, // R8G8_SNORM
96 {GL_RG8I, GL_RG_INTEGER, GL_BYTE}, // R8G8_SINT
97 {GL_RG8UI, GL_RG_INTEGER, GL_UNSIGNED_BYTE}, // R8G8_UINT
98 {GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT}, // R32G32_UINT
99 {GL_RGB16F, GL_RGBA, GL_HALF_FLOAT}, // R16G16B16X16_FLOAT
100 {GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT}, // R32_UINT
101 {GL_R32I, GL_RED_INTEGER, GL_INT}, // R32_SINT
102 {GL_COMPRESSED_RGBA_ASTC_8x8_KHR}, // ASTC_2D_8X8_UNORM
103 {GL_COMPRESSED_RGBA_ASTC_8x5_KHR}, // ASTC_2D_8X5_UNORM
104 {GL_COMPRESSED_RGBA_ASTC_5x4_KHR}, // ASTC_2D_5X4_UNORM
105 {GL_SRGB8_ALPHA8, GL_BGRA, GL_UNSIGNED_BYTE}, // B8G8R8A8_UNORM
95 // Compressed sRGB formats 106 // Compressed sRGB formats
96 {GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT}, // DXT1_SRGB 107 {GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT}, // BC1_RGBA_SRGB
97 {GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT}, // DXT23_SRGB 108 {GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT}, // BC2_SRGB
98 {GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT}, // DXT45_SRGB 109 {GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT}, // BC3_SRGB
99 {GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM}, // BC7U_SRGB 110 {GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM}, // BC7_SRGB
100 {GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4_REV}, // R4G4B4A4U 111 {GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4_REV}, // A4B4G4R4_UNORM
101 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR}, // ASTC_2D_4X4_SRGB 112 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR}, // ASTC_2D_4X4_SRGB
102 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR}, // ASTC_2D_8X8_SRGB 113 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR}, // ASTC_2D_8X8_SRGB
103 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR}, // ASTC_2D_8X5_SRGB 114 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR}, // ASTC_2D_8X5_SRGB
104 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR}, // ASTC_2D_5X4_SRGB 115 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR}, // ASTC_2D_5X4_SRGB
105 {GL_COMPRESSED_RGBA_ASTC_5x5_KHR}, // ASTC_2D_5X5 116 {GL_COMPRESSED_RGBA_ASTC_5x5_KHR}, // ASTC_2D_5X5_UNORM
106 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR}, // ASTC_2D_5X5_SRGB 117 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR}, // ASTC_2D_5X5_SRGB
107 {GL_COMPRESSED_RGBA_ASTC_10x8_KHR}, // ASTC_2D_10X8 118 {GL_COMPRESSED_RGBA_ASTC_10x8_KHR}, // ASTC_2D_10X8_UNORM
108 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR}, // ASTC_2D_10X8_SRGB 119 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR}, // ASTC_2D_10X8_SRGB
109 {GL_COMPRESSED_RGBA_ASTC_6x6_KHR}, // ASTC_2D_6X6 120 {GL_COMPRESSED_RGBA_ASTC_6x6_KHR}, // ASTC_2D_6X6_UNORM
110 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR}, // ASTC_2D_6X6_SRGB 121 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR}, // ASTC_2D_6X6_SRGB
111 {GL_COMPRESSED_RGBA_ASTC_10x10_KHR}, // ASTC_2D_10X10 122 {GL_COMPRESSED_RGBA_ASTC_10x10_KHR}, // ASTC_2D_10X10_UNORM
112 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR}, // ASTC_2D_10X10_SRGB 123 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR}, // ASTC_2D_10X10_SRGB
113 {GL_COMPRESSED_RGBA_ASTC_12x12_KHR}, // ASTC_2D_12X12 124 {GL_COMPRESSED_RGBA_ASTC_12x12_KHR}, // ASTC_2D_12X12_UNORM
114 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR}, // ASTC_2D_12X12_SRGB 125 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR}, // ASTC_2D_12X12_SRGB
115 {GL_COMPRESSED_RGBA_ASTC_8x6_KHR}, // ASTC_2D_8X6 126 {GL_COMPRESSED_RGBA_ASTC_8x6_KHR}, // ASTC_2D_8X6_UNORM
116 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR}, // ASTC_2D_8X6_SRGB 127 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR}, // ASTC_2D_8X6_SRGB
117 {GL_COMPRESSED_RGBA_ASTC_6x5_KHR}, // ASTC_2D_6X5 128 {GL_COMPRESSED_RGBA_ASTC_6x5_KHR}, // ASTC_2D_6X5_UNORM
118 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR}, // ASTC_2D_6X5_SRGB 129 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR}, // ASTC_2D_6X5_SRGB
119 {GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV}, // E5B9G9R9F 130 {GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV}, // E5B9G9R9_FLOAT
120 131
121 // Depth formats 132 // Depth formats
122 {GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT}, // Z32F 133 {GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT}, // D32_FLOAT
123 {GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT}, // Z16 134 {GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT}, // D16_UNORM
124 135
125 // DepthStencil formats 136 // DepthStencil formats
126 {GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8}, // Z24S8 137 {GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8}, // D24_UNORM_S8_UINT
127 {GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8}, // S8Z24 138 {GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8}, // S8_UINT_D24_UNORM
128 {GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV}, // Z32FS8 139 {GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL,
140 GL_FLOAT_32_UNSIGNED_INT_24_8_REV}, // D32_FLOAT_S8_UINT
129}}; 141}};
130 142
131const FormatTuple& GetFormatTuple(PixelFormat pixel_format) { 143const FormatTuple& GetFormatTuple(PixelFormat pixel_format) {
@@ -178,10 +190,10 @@ GLint GetSwizzleSource(SwizzleSource source) {
178 190
179GLenum GetComponent(PixelFormat format, bool is_first) { 191GLenum GetComponent(PixelFormat format, bool is_first) {
180 switch (format) { 192 switch (format) {
181 case PixelFormat::Z24S8: 193 case PixelFormat::D24_UNORM_S8_UINT:
182 case PixelFormat::Z32FS8: 194 case PixelFormat::D32_FLOAT_S8_UINT:
183 return is_first ? GL_DEPTH_COMPONENT : GL_STENCIL_INDEX; 195 return is_first ? GL_DEPTH_COMPONENT : GL_STENCIL_INDEX;
184 case PixelFormat::S8Z24: 196 case PixelFormat::S8_UINT_D24_UNORM:
185 return is_first ? GL_STENCIL_INDEX : GL_DEPTH_COMPONENT; 197 return is_first ? GL_STENCIL_INDEX : GL_DEPTH_COMPONENT;
186 default: 198 default:
187 UNREACHABLE(); 199 UNREACHABLE();
@@ -482,9 +494,9 @@ GLuint CachedSurfaceView::GetTexture(SwizzleSource x_source, SwizzleSource y_sou
482 std::array swizzle{x_source, y_source, z_source, w_source}; 494 std::array swizzle{x_source, y_source, z_source, w_source};
483 495
484 switch (const PixelFormat format = GetSurfaceParams().pixel_format) { 496 switch (const PixelFormat format = GetSurfaceParams().pixel_format) {
485 case PixelFormat::Z24S8: 497 case PixelFormat::D24_UNORM_S8_UINT:
486 case PixelFormat::Z32FS8: 498 case PixelFormat::D32_FLOAT_S8_UINT:
487 case PixelFormat::S8Z24: 499 case PixelFormat::S8_UINT_D24_UNORM:
488 UNIMPLEMENTED_IF(x_source != SwizzleSource::R && x_source != SwizzleSource::G); 500 UNIMPLEMENTED_IF(x_source != SwizzleSource::R && x_source != SwizzleSource::G);
489 glTextureParameteri(view.handle, GL_DEPTH_STENCIL_TEXTURE_MODE, 501 glTextureParameteri(view.handle, GL_DEPTH_STENCIL_TEXTURE_MODE,
490 GetComponent(format, x_source == SwizzleSource::R)); 502 GetComponent(format, x_source == SwizzleSource::R));
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index e66cdc083..52e9e8250 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -535,12 +535,12 @@ void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture,
535 535
536 GLint internal_format; 536 GLint internal_format;
537 switch (framebuffer.pixel_format) { 537 switch (framebuffer.pixel_format) {
538 case Tegra::FramebufferConfig::PixelFormat::ABGR8: 538 case Tegra::FramebufferConfig::PixelFormat::A8B8G8R8_UNORM:
539 internal_format = GL_RGBA8; 539 internal_format = GL_RGBA8;
540 texture.gl_format = GL_RGBA; 540 texture.gl_format = GL_RGBA;
541 texture.gl_type = GL_UNSIGNED_INT_8_8_8_8_REV; 541 texture.gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
542 break; 542 break;
543 case Tegra::FramebufferConfig::PixelFormat::RGB565: 543 case Tegra::FramebufferConfig::PixelFormat::RGB565_UNORM:
544 internal_format = GL_RGB565; 544 internal_format = GL_RGB565;
545 texture.gl_format = GL_RGB; 545 texture.gl_format = GL_RGB;
546 texture.gl_type = GL_UNSIGNED_SHORT_5_6_5; 546 texture.gl_type = GL_UNSIGNED_SHORT_5_6_5;
diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp
index d1f0ea932..81a39a3b8 100644
--- a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp
+++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp
@@ -40,7 +40,6 @@ constexpr std::array POLYGON_OFFSET_ENABLE_LUT = {
40} // Anonymous namespace 40} // Anonymous namespace
41 41
42void FixedPipelineState::Fill(const Maxwell& regs, bool has_extended_dynamic_state) { 42void FixedPipelineState::Fill(const Maxwell& regs, bool has_extended_dynamic_state) {
43 const auto& clip = regs.view_volume_clip_control;
44 const std::array enabled_lut = {regs.polygon_offset_point_enable, 43 const std::array enabled_lut = {regs.polygon_offset_point_enable,
45 regs.polygon_offset_line_enable, 44 regs.polygon_offset_line_enable,
46 regs.polygon_offset_fill_enable}; 45 regs.polygon_offset_fill_enable};
diff --git a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp
index d7f1ae89f..f8c77f4fa 100644
--- a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp
+++ b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp
@@ -117,90 +117,101 @@ struct FormatTuple {
117 VkFormat format; ///< Vulkan format 117 VkFormat format; ///< Vulkan format
118 int usage = 0; ///< Describes image format usage 118 int usage = 0; ///< Describes image format usage
119} constexpr tex_format_tuples[] = { 119} constexpr tex_format_tuples[] = {
120 {VK_FORMAT_A8B8G8R8_UNORM_PACK32, Attachable | Storage}, // ABGR8U 120 {VK_FORMAT_A8B8G8R8_UNORM_PACK32, Attachable | Storage}, // A8B8G8R8_UNORM
121 {VK_FORMAT_A8B8G8R8_SNORM_PACK32, Attachable | Storage}, // ABGR8S 121 {VK_FORMAT_A8B8G8R8_SNORM_PACK32, Attachable | Storage}, // A8B8G8R8_SNORM
122 {VK_FORMAT_A8B8G8R8_UINT_PACK32, Attachable | Storage}, // ABGR8UI 122 {VK_FORMAT_A8B8G8R8_SINT_PACK32, Attachable | Storage}, // A8B8G8R8_SINT
123 {VK_FORMAT_B5G6R5_UNORM_PACK16}, // B5G6R5U 123 {VK_FORMAT_A8B8G8R8_UINT_PACK32, Attachable | Storage}, // A8B8G8R8_UINT
124 {VK_FORMAT_A2B10G10R10_UNORM_PACK32, Attachable | Storage}, // A2B10G10R10U 124 {VK_FORMAT_R5G6B5_UNORM_PACK16, Attachable}, // R5G6B5_UNORM
125 {VK_FORMAT_A1R5G5B5_UNORM_PACK16, Attachable}, // A1B5G5R5U (flipped with swizzle) 125 {VK_FORMAT_B5G6R5_UNORM_PACK16, Attachable}, // B5G6R5_UNORM
126 {VK_FORMAT_R8_UNORM, Attachable | Storage}, // R8U 126 {VK_FORMAT_A1R5G5B5_UNORM_PACK16, Attachable}, // A1R5G5B5_UNORM
127 {VK_FORMAT_R8_UINT, Attachable | Storage}, // R8UI 127 {VK_FORMAT_A2B10G10R10_UNORM_PACK32, Attachable | Storage}, // A2B10G10R10_UNORM
128 {VK_FORMAT_R16G16B16A16_SFLOAT, Attachable | Storage}, // RGBA16F 128 {VK_FORMAT_A2B10G10R10_UINT_PACK32, Attachable | Storage}, // A2B10G10R10_UINT
129 {VK_FORMAT_R16G16B16A16_UNORM, Attachable | Storage}, // RGBA16U 129 {VK_FORMAT_A1R5G5B5_UNORM_PACK16, Attachable}, // A1B5G5R5_UNORM (flipped with swizzle)
130 {VK_FORMAT_R16G16B16A16_SNORM, Attachable | Storage}, // RGBA16S 130 {VK_FORMAT_R8_UNORM, Attachable | Storage}, // R8_UNORM
131 {VK_FORMAT_R16G16B16A16_UINT, Attachable | Storage}, // RGBA16UI 131 {VK_FORMAT_R8_SNORM, Attachable | Storage}, // R8_SNORM
132 {VK_FORMAT_B10G11R11_UFLOAT_PACK32, Attachable | Storage}, // R11FG11FB10F 132 {VK_FORMAT_R8_SINT, Attachable | Storage}, // R8_SINT
133 {VK_FORMAT_R32G32B32A32_UINT, Attachable | Storage}, // RGBA32UI 133 {VK_FORMAT_R8_UINT, Attachable | Storage}, // R8_UINT
134 {VK_FORMAT_BC1_RGBA_UNORM_BLOCK}, // DXT1 134 {VK_FORMAT_R16G16B16A16_SFLOAT, Attachable | Storage}, // R16G16B16A16_FLOAT
135 {VK_FORMAT_BC2_UNORM_BLOCK}, // DXT23 135 {VK_FORMAT_R16G16B16A16_UNORM, Attachable | Storage}, // R16G16B16A16_UNORM
136 {VK_FORMAT_BC3_UNORM_BLOCK}, // DXT45 136 {VK_FORMAT_R16G16B16A16_SNORM, Attachable | Storage}, // R16G16B16A16_SNORM
137 {VK_FORMAT_BC4_UNORM_BLOCK}, // DXN1 137 {VK_FORMAT_R16G16B16A16_SINT, Attachable | Storage}, // R16G16B16A16_SINT
138 {VK_FORMAT_BC5_UNORM_BLOCK}, // DXN2UNORM 138 {VK_FORMAT_R16G16B16A16_UINT, Attachable | Storage}, // R16G16B16A16_UINT
139 {VK_FORMAT_BC5_SNORM_BLOCK}, // DXN2SNORM 139 {VK_FORMAT_B10G11R11_UFLOAT_PACK32, Attachable | Storage}, // B10G11R11_FLOAT
140 {VK_FORMAT_BC7_UNORM_BLOCK}, // BC7U 140 {VK_FORMAT_R32G32B32A32_UINT, Attachable | Storage}, // R32G32B32A32_UINT
141 {VK_FORMAT_BC6H_UFLOAT_BLOCK}, // BC6H_UF16 141 {VK_FORMAT_BC1_RGBA_UNORM_BLOCK}, // BC1_RGBA_UNORM
142 {VK_FORMAT_BC6H_SFLOAT_BLOCK}, // BC6H_SF16 142 {VK_FORMAT_BC2_UNORM_BLOCK}, // BC2_UNORM
143 {VK_FORMAT_ASTC_4x4_UNORM_BLOCK}, // ASTC_2D_4X4 143 {VK_FORMAT_BC3_UNORM_BLOCK}, // BC3_UNORM
144 {VK_FORMAT_B8G8R8A8_UNORM, Attachable}, // BGRA8 144 {VK_FORMAT_BC4_UNORM_BLOCK}, // BC4_UNORM
145 {VK_FORMAT_R32G32B32A32_SFLOAT, Attachable | Storage}, // RGBA32F 145 {VK_FORMAT_BC4_SNORM_BLOCK}, // BC4_SNORM
146 {VK_FORMAT_R32G32_SFLOAT, Attachable | Storage}, // RG32F 146 {VK_FORMAT_BC5_UNORM_BLOCK}, // BC5_UNORM
147 {VK_FORMAT_R32_SFLOAT, Attachable | Storage}, // R32F 147 {VK_FORMAT_BC5_SNORM_BLOCK}, // BC5_SNORM
148 {VK_FORMAT_R16_SFLOAT, Attachable | Storage}, // R16F 148 {VK_FORMAT_BC7_UNORM_BLOCK}, // BC7_UNORM
149 {VK_FORMAT_R16_UNORM, Attachable | Storage}, // R16U 149 {VK_FORMAT_BC6H_UFLOAT_BLOCK}, // BC6H_UFLOAT
150 {VK_FORMAT_UNDEFINED}, // R16S 150 {VK_FORMAT_BC6H_SFLOAT_BLOCK}, // BC6H_SFLOAT
151 {VK_FORMAT_R16_UINT, Attachable | Storage}, // R16UI 151 {VK_FORMAT_ASTC_4x4_UNORM_BLOCK}, // ASTC_2D_4X4_UNORM
152 {VK_FORMAT_UNDEFINED}, // R16I 152 {VK_FORMAT_B8G8R8A8_UNORM, Attachable}, // B8G8R8A8_UNORM
153 {VK_FORMAT_R16G16_UNORM, Attachable | Storage}, // RG16 153 {VK_FORMAT_R32G32B32A32_SFLOAT, Attachable | Storage}, // R32G32B32A32_FLOAT
154 {VK_FORMAT_R16G16_SFLOAT, Attachable | Storage}, // RG16F 154 {VK_FORMAT_R32G32B32A32_SINT, Attachable | Storage}, // R32G32B32A32_SINT
155 {VK_FORMAT_UNDEFINED}, // RG16UI 155 {VK_FORMAT_R32G32_SFLOAT, Attachable | Storage}, // R32G32_FLOAT
156 {VK_FORMAT_UNDEFINED}, // RG16I 156 {VK_FORMAT_R32G32_SINT, Attachable | Storage}, // R32G32_SINT
157 {VK_FORMAT_R16G16_SNORM, Attachable | Storage}, // RG16S 157 {VK_FORMAT_R32_SFLOAT, Attachable | Storage}, // R32_FLOAT
158 {VK_FORMAT_UNDEFINED}, // RGB32F 158 {VK_FORMAT_R16_SFLOAT, Attachable | Storage}, // R16_FLOAT
159 {VK_FORMAT_R8G8B8A8_SRGB, Attachable}, // RGBA8_SRGB 159 {VK_FORMAT_R16_UNORM, Attachable | Storage}, // R16_UNORM
160 {VK_FORMAT_R8G8_UNORM, Attachable | Storage}, // RG8U 160 {VK_FORMAT_UNDEFINED}, // R16_SNORM
161 {VK_FORMAT_R8G8_SNORM, Attachable | Storage}, // RG8S 161 {VK_FORMAT_R16_UINT, Attachable | Storage}, // R16_UINT
162 {VK_FORMAT_R8G8_UINT, Attachable | Storage}, // RG8UI 162 {VK_FORMAT_UNDEFINED}, // R16_SINT
163 {VK_FORMAT_R32G32_UINT, Attachable | Storage}, // RG32UI 163 {VK_FORMAT_R16G16_UNORM, Attachable | Storage}, // R16G16_UNORM
164 {VK_FORMAT_UNDEFINED}, // RGBX16F 164 {VK_FORMAT_R16G16_SFLOAT, Attachable | Storage}, // R16G16_FLOAT
165 {VK_FORMAT_R32_UINT, Attachable | Storage}, // R32UI 165 {VK_FORMAT_UNDEFINED}, // R16G16_UINT
166 {VK_FORMAT_R32_SINT, Attachable | Storage}, // R32I 166 {VK_FORMAT_UNDEFINED}, // R16G16_SINT
167 {VK_FORMAT_ASTC_8x8_UNORM_BLOCK}, // ASTC_2D_8X8 167 {VK_FORMAT_R16G16_SNORM, Attachable | Storage}, // R16G16_SNORM
168 {VK_FORMAT_UNDEFINED}, // ASTC_2D_8X5 168 {VK_FORMAT_UNDEFINED}, // R32G32B32_FLOAT
169 {VK_FORMAT_UNDEFINED}, // ASTC_2D_5X4 169 {VK_FORMAT_R8G8B8A8_SRGB, Attachable}, // A8B8G8R8_SRGB
170 {VK_FORMAT_B8G8R8A8_SRGB, Attachable}, // BGRA8_SRGB 170 {VK_FORMAT_R8G8_UNORM, Attachable | Storage}, // R8G8_UNORM
171 {VK_FORMAT_BC1_RGBA_SRGB_BLOCK}, // DXT1_SRGB 171 {VK_FORMAT_R8G8_SNORM, Attachable | Storage}, // R8G8_SNORM
172 {VK_FORMAT_BC2_SRGB_BLOCK}, // DXT23_SRGB 172 {VK_FORMAT_R8G8_SINT, Attachable | Storage}, // R8G8_SINT
173 {VK_FORMAT_BC3_SRGB_BLOCK}, // DXT45_SRGB 173 {VK_FORMAT_R8G8_UINT, Attachable | Storage}, // R8G8_UINT
174 {VK_FORMAT_BC7_SRGB_BLOCK}, // BC7U_SRGB 174 {VK_FORMAT_R32G32_UINT, Attachable | Storage}, // R32G32_UINT
175 {VK_FORMAT_R4G4B4A4_UNORM_PACK16, Attachable}, // R4G4B4A4U 175 {VK_FORMAT_UNDEFINED}, // R16G16B16X16_FLOAT
176 {VK_FORMAT_ASTC_4x4_SRGB_BLOCK}, // ASTC_2D_4X4_SRGB 176 {VK_FORMAT_R32_UINT, Attachable | Storage}, // R32_UINT
177 {VK_FORMAT_ASTC_8x8_SRGB_BLOCK}, // ASTC_2D_8X8_SRGB 177 {VK_FORMAT_R32_SINT, Attachable | Storage}, // R32_SINT
178 {VK_FORMAT_ASTC_8x5_SRGB_BLOCK}, // ASTC_2D_8X5_SRGB 178 {VK_FORMAT_ASTC_8x8_UNORM_BLOCK}, // ASTC_2D_8X8_UNORM
179 {VK_FORMAT_ASTC_5x4_SRGB_BLOCK}, // ASTC_2D_5X4_SRGB 179 {VK_FORMAT_UNDEFINED}, // ASTC_2D_8X5_UNORM
180 {VK_FORMAT_ASTC_5x5_UNORM_BLOCK}, // ASTC_2D_5X5 180 {VK_FORMAT_UNDEFINED}, // ASTC_2D_5X4_UNORM
181 {VK_FORMAT_ASTC_5x5_SRGB_BLOCK}, // ASTC_2D_5X5_SRGB 181 {VK_FORMAT_B8G8R8A8_SRGB, Attachable}, // B8G8R8A8_SRGB
182 {VK_FORMAT_ASTC_10x8_UNORM_BLOCK}, // ASTC_2D_10X8 182 {VK_FORMAT_BC1_RGBA_SRGB_BLOCK}, // BC1_RGBA_SRGB
183 {VK_FORMAT_ASTC_10x8_SRGB_BLOCK}, // ASTC_2D_10X8_SRGB 183 {VK_FORMAT_BC2_SRGB_BLOCK}, // BC2_SRGB
184 {VK_FORMAT_ASTC_6x6_UNORM_BLOCK}, // ASTC_2D_6X6 184 {VK_FORMAT_BC3_SRGB_BLOCK}, // BC3_SRGB
185 {VK_FORMAT_ASTC_6x6_SRGB_BLOCK}, // ASTC_2D_6X6_SRGB 185 {VK_FORMAT_BC7_SRGB_BLOCK}, // BC7_SRGB
186 {VK_FORMAT_ASTC_10x10_UNORM_BLOCK}, // ASTC_2D_10X10 186 {VK_FORMAT_R4G4B4A4_UNORM_PACK16, Attachable}, // A4B4G4R4_UNORM
187 {VK_FORMAT_ASTC_10x10_SRGB_BLOCK}, // ASTC_2D_10X10_SRGB 187 {VK_FORMAT_ASTC_4x4_SRGB_BLOCK}, // ASTC_2D_4X4_SRGB
188 {VK_FORMAT_ASTC_12x12_UNORM_BLOCK}, // ASTC_2D_12X12 188 {VK_FORMAT_ASTC_8x8_SRGB_BLOCK}, // ASTC_2D_8X8_SRGB
189 {VK_FORMAT_ASTC_12x12_SRGB_BLOCK}, // ASTC_2D_12X12_SRGB 189 {VK_FORMAT_ASTC_8x5_SRGB_BLOCK}, // ASTC_2D_8X5_SRGB
190 {VK_FORMAT_ASTC_8x6_UNORM_BLOCK}, // ASTC_2D_8X6 190 {VK_FORMAT_ASTC_5x4_SRGB_BLOCK}, // ASTC_2D_5X4_SRGB
191 {VK_FORMAT_ASTC_8x6_SRGB_BLOCK}, // ASTC_2D_8X6_SRGB 191 {VK_FORMAT_ASTC_5x5_UNORM_BLOCK}, // ASTC_2D_5X5_UNORM
192 {VK_FORMAT_ASTC_6x5_UNORM_BLOCK}, // ASTC_2D_6X5 192 {VK_FORMAT_ASTC_5x5_SRGB_BLOCK}, // ASTC_2D_5X5_SRGB
193 {VK_FORMAT_ASTC_6x5_SRGB_BLOCK}, // ASTC_2D_6X5_SRGB 193 {VK_FORMAT_ASTC_10x8_UNORM_BLOCK}, // ASTC_2D_10X8_UNORM
194 {VK_FORMAT_E5B9G9R9_UFLOAT_PACK32}, // E5B9G9R9F 194 {VK_FORMAT_ASTC_10x8_SRGB_BLOCK}, // ASTC_2D_10X8_SRGB
195 {VK_FORMAT_ASTC_6x6_UNORM_BLOCK}, // ASTC_2D_6X6_UNORM
196 {VK_FORMAT_ASTC_6x6_SRGB_BLOCK}, // ASTC_2D_6X6_SRGB
197 {VK_FORMAT_ASTC_10x10_UNORM_BLOCK}, // ASTC_2D_10X10_UNORM
198 {VK_FORMAT_ASTC_10x10_SRGB_BLOCK}, // ASTC_2D_10X10_SRGB
199 {VK_FORMAT_ASTC_12x12_UNORM_BLOCK}, // ASTC_2D_12X12_UNORM
200 {VK_FORMAT_ASTC_12x12_SRGB_BLOCK}, // ASTC_2D_12X12_SRGB
201 {VK_FORMAT_ASTC_8x6_UNORM_BLOCK}, // ASTC_2D_8X6_UNORM
202 {VK_FORMAT_ASTC_8x6_SRGB_BLOCK}, // ASTC_2D_8X6_SRGB
203 {VK_FORMAT_ASTC_6x5_UNORM_BLOCK}, // ASTC_2D_6X5_UNORM
204 {VK_FORMAT_ASTC_6x5_SRGB_BLOCK}, // ASTC_2D_6X5_SRGB
205 {VK_FORMAT_E5B9G9R9_UFLOAT_PACK32}, // E5B9G9R9_FLOAT
195 206
196 // Depth formats 207 // Depth formats
197 {VK_FORMAT_D32_SFLOAT, Attachable}, // Z32F 208 {VK_FORMAT_D32_SFLOAT, Attachable}, // D32_FLOAT
198 {VK_FORMAT_D16_UNORM, Attachable}, // Z16 209 {VK_FORMAT_D16_UNORM, Attachable}, // D16_UNORM
199 210
200 // DepthStencil formats 211 // DepthStencil formats
201 {VK_FORMAT_D24_UNORM_S8_UINT, Attachable}, // Z24S8 212 {VK_FORMAT_D24_UNORM_S8_UINT, Attachable}, // D24_UNORM_S8_UINT
202 {VK_FORMAT_D24_UNORM_S8_UINT, Attachable}, // S8Z24 (emulated) 213 {VK_FORMAT_D24_UNORM_S8_UINT, Attachable}, // S8_UINT_D24_UNORM (emulated)
203 {VK_FORMAT_D32_SFLOAT_S8_UINT, Attachable}, // Z32FS8 214 {VK_FORMAT_D32_SFLOAT_S8_UINT, Attachable}, // D32_FLOAT_S8_UINT
204}; 215};
205static_assert(std::size(tex_format_tuples) == VideoCore::Surface::MaxPixelFormat); 216static_assert(std::size(tex_format_tuples) == VideoCore::Surface::MaxPixelFormat);
206 217
@@ -221,7 +232,7 @@ FormatInfo SurfaceFormat(const VKDevice& device, FormatType format_type, PixelFo
221 return {VK_FORMAT_A8B8G8R8_UNORM_PACK32, true, true}; 232 return {VK_FORMAT_A8B8G8R8_UNORM_PACK32, true, true};
222 } 233 }
223 234
224 // Use ABGR8 on hardware that doesn't support ASTC natively 235 // Use A8B8G8R8_UNORM on hardware that doesn't support ASTC natively
225 if (!device.IsOptimalAstcSupported() && VideoCore::Surface::IsPixelFormatASTC(pixel_format)) { 236 if (!device.IsOptimalAstcSupported() && VideoCore::Surface::IsPixelFormatASTC(pixel_format)) {
226 tuple.format = VideoCore::Surface::IsPixelFormatSRGB(pixel_format) 237 tuple.format = VideoCore::Surface::IsPixelFormatSRGB(pixel_format)
227 ? VK_FORMAT_A8B8G8R8_SRGB_PACK32 238 ? VK_FORMAT_A8B8G8R8_SRGB_PACK32
diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.cpp b/src/video_core/renderer_vulkan/vk_blit_screen.cpp
index fbd406f2b..ce53e5a6b 100644
--- a/src/video_core/renderer_vulkan/vk_blit_screen.cpp
+++ b/src/video_core/renderer_vulkan/vk_blit_screen.cpp
@@ -141,24 +141,28 @@ struct ScreenRectVertex {
141 std::array<f32, 2> tex_coord; 141 std::array<f32, 2> tex_coord;
142 142
143 static VkVertexInputBindingDescription GetDescription() { 143 static VkVertexInputBindingDescription GetDescription() {
144 VkVertexInputBindingDescription description; 144 return {
145 description.binding = 0; 145 .binding = 0,
146 description.stride = sizeof(ScreenRectVertex); 146 .stride = sizeof(ScreenRectVertex),
147 description.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; 147 .inputRate = VK_VERTEX_INPUT_RATE_VERTEX,
148 return description; 148 };
149 } 149 }
150 150
151 static std::array<VkVertexInputAttributeDescription, 2> GetAttributes() { 151 static std::array<VkVertexInputAttributeDescription, 2> GetAttributes() {
152 std::array<VkVertexInputAttributeDescription, 2> attributes; 152 return {{
153 attributes[0].location = 0; 153 {
154 attributes[0].binding = 0; 154 .location = 0,
155 attributes[0].format = VK_FORMAT_R32G32_SFLOAT; 155 .binding = 0,
156 attributes[0].offset = offsetof(ScreenRectVertex, position); 156 .format = VK_FORMAT_R32G32_SFLOAT,
157 attributes[1].location = 1; 157 .offset = offsetof(ScreenRectVertex, position),
158 attributes[1].binding = 0; 158 },
159 attributes[1].format = VK_FORMAT_R32G32_SFLOAT; 159 {
160 attributes[1].offset = offsetof(ScreenRectVertex, tex_coord); 160 .location = 1,
161 return attributes; 161 .binding = 0,
162 .format = VK_FORMAT_R32G32_SFLOAT,
163 .offset = offsetof(ScreenRectVertex, tex_coord),
164 },
165 }};
162 } 166 }
163}; 167};
164 168
@@ -183,9 +187,9 @@ std::size_t GetSizeInBytes(const Tegra::FramebufferConfig& framebuffer) {
183 187
184VkFormat GetFormat(const Tegra::FramebufferConfig& framebuffer) { 188VkFormat GetFormat(const Tegra::FramebufferConfig& framebuffer) {
185 switch (framebuffer.pixel_format) { 189 switch (framebuffer.pixel_format) {
186 case Tegra::FramebufferConfig::PixelFormat::ABGR8: 190 case Tegra::FramebufferConfig::PixelFormat::A8B8G8R8_UNORM:
187 return VK_FORMAT_A8B8G8R8_UNORM_PACK32; 191 return VK_FORMAT_A8B8G8R8_UNORM_PACK32;
188 case Tegra::FramebufferConfig::PixelFormat::RGB565: 192 case Tegra::FramebufferConfig::PixelFormat::RGB565_UNORM:
189 return VK_FORMAT_R5G6B5_UNORM_PACK16; 193 return VK_FORMAT_R5G6B5_UNORM_PACK16;
190 default: 194 default:
191 UNIMPLEMENTED_MSG("Unknown framebuffer pixel format: {}", 195 UNIMPLEMENTED_MSG("Unknown framebuffer pixel format: {}",
@@ -267,20 +271,25 @@ std::tuple<VKFence&, VkSemaphore> VKBlitScreen::Draw(const Tegra::FramebufferCon
267 blit_image->Transition(0, 1, 0, 1, VK_PIPELINE_STAGE_TRANSFER_BIT, 271 blit_image->Transition(0, 1, 0, 1, VK_PIPELINE_STAGE_TRANSFER_BIT,
268 VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); 272 VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
269 273
270 VkBufferImageCopy copy; 274 const VkBufferImageCopy copy{
271 copy.bufferOffset = image_offset; 275 .bufferOffset = image_offset,
272 copy.bufferRowLength = 0; 276 .bufferRowLength = 0,
273 copy.bufferImageHeight = 0; 277 .bufferImageHeight = 0,
274 copy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 278 .imageSubresource =
275 copy.imageSubresource.mipLevel = 0; 279 {
276 copy.imageSubresource.baseArrayLayer = 0; 280 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
277 copy.imageSubresource.layerCount = 1; 281 .mipLevel = 0,
278 copy.imageOffset.x = 0; 282 .baseArrayLayer = 0,
279 copy.imageOffset.y = 0; 283 .layerCount = 1,
280 copy.imageOffset.z = 0; 284 },
281 copy.imageExtent.width = framebuffer.width; 285 .imageOffset = {.x = 0, .y = 0, .z = 0},
282 copy.imageExtent.height = framebuffer.height; 286 .imageExtent =
283 copy.imageExtent.depth = 1; 287 {
288 .width = framebuffer.width,
289 .height = framebuffer.height,
290 .depth = 1,
291 },
292 };
284 scheduler.Record( 293 scheduler.Record(
285 [buffer = *buffer, image = *blit_image->GetHandle(), copy](vk::CommandBuffer cmdbuf) { 294 [buffer = *buffer, image = *blit_image->GetHandle(), copy](vk::CommandBuffer cmdbuf) {
286 cmdbuf.CopyBufferToImage(buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, copy); 295 cmdbuf.CopyBufferToImage(buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, copy);
@@ -295,11 +304,9 @@ std::tuple<VKFence&, VkSemaphore> VKBlitScreen::Draw(const Tegra::FramebufferCon
295 descriptor_set = descriptor_sets[image_index], buffer = *buffer, 304 descriptor_set = descriptor_sets[image_index], buffer = *buffer,
296 size = swapchain.GetSize(), pipeline = *pipeline, 305 size = swapchain.GetSize(), pipeline = *pipeline,
297 layout = *pipeline_layout](vk::CommandBuffer cmdbuf) { 306 layout = *pipeline_layout](vk::CommandBuffer cmdbuf) {
298 VkClearValue clear_color; 307 const VkClearValue clear_color{
299 clear_color.color.float32[0] = 0.0f; 308 .color = {.float32 = {0.0f, 0.0f, 0.0f, 0.0f}},
300 clear_color.color.float32[1] = 0.0f; 309 };
301 clear_color.color.float32[2] = 0.0f;
302 clear_color.color.float32[3] = 0.0f;
303 310
304 VkRenderPassBeginInfo renderpass_bi; 311 VkRenderPassBeginInfo renderpass_bi;
305 renderpass_bi.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; 312 renderpass_bi.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
@@ -379,93 +386,109 @@ void VKBlitScreen::CreateSemaphores() {
379} 386}
380 387
381void VKBlitScreen::CreateDescriptorPool() { 388void VKBlitScreen::CreateDescriptorPool() {
382 std::array<VkDescriptorPoolSize, 2> pool_sizes; 389 const std::array<VkDescriptorPoolSize, 2> pool_sizes{{
383 pool_sizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; 390 {
384 pool_sizes[0].descriptorCount = static_cast<u32>(image_count); 391 .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
385 pool_sizes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; 392 .descriptorCount = static_cast<u32>(image_count),
386 pool_sizes[1].descriptorCount = static_cast<u32>(image_count); 393 },
387 394 {
388 VkDescriptorPoolCreateInfo ci; 395 .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
389 ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; 396 .descriptorCount = static_cast<u32>(image_count),
390 ci.pNext = nullptr; 397 },
391 ci.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; 398 }};
392 ci.maxSets = static_cast<u32>(image_count); 399
393 ci.poolSizeCount = static_cast<u32>(pool_sizes.size()); 400 const VkDescriptorPoolCreateInfo ci{
394 ci.pPoolSizes = pool_sizes.data(); 401 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
402 .pNext = nullptr,
403 .flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
404 .maxSets = static_cast<u32>(image_count),
405 .poolSizeCount = static_cast<u32>(pool_sizes.size()),
406 .pPoolSizes = pool_sizes.data(),
407 };
395 descriptor_pool = device.GetLogical().CreateDescriptorPool(ci); 408 descriptor_pool = device.GetLogical().CreateDescriptorPool(ci);
396} 409}
397 410
398void VKBlitScreen::CreateRenderPass() { 411void VKBlitScreen::CreateRenderPass() {
399 VkAttachmentDescription color_attachment; 412 const VkAttachmentDescription color_attachment{
400 color_attachment.flags = 0; 413 .flags = 0,
401 color_attachment.format = swapchain.GetImageFormat(); 414 .format = swapchain.GetImageFormat(),
402 color_attachment.samples = VK_SAMPLE_COUNT_1_BIT; 415 .samples = VK_SAMPLE_COUNT_1_BIT,
403 color_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; 416 .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
404 color_attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; 417 .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
405 color_attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; 418 .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
406 color_attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; 419 .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
407 color_attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; 420 .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
408 color_attachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; 421 .finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
409 422 };
410 VkAttachmentReference color_attachment_ref; 423
411 color_attachment_ref.attachment = 0; 424 const VkAttachmentReference color_attachment_ref{
412 color_attachment_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 425 .attachment = 0,
413 426 .layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
414 VkSubpassDescription subpass_description; 427 };
415 subpass_description.flags = 0; 428
416 subpass_description.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; 429 const VkSubpassDescription subpass_description{
417 subpass_description.inputAttachmentCount = 0; 430 .flags = 0,
418 subpass_description.pInputAttachments = nullptr; 431 .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
419 subpass_description.colorAttachmentCount = 1; 432 .inputAttachmentCount = 0,
420 subpass_description.pColorAttachments = &color_attachment_ref; 433 .pInputAttachments = nullptr,
421 subpass_description.pResolveAttachments = nullptr; 434 .colorAttachmentCount = 1,
422 subpass_description.pDepthStencilAttachment = nullptr; 435 .pColorAttachments = &color_attachment_ref,
423 subpass_description.preserveAttachmentCount = 0; 436 .pResolveAttachments = nullptr,
424 subpass_description.pPreserveAttachments = nullptr; 437 .pDepthStencilAttachment = nullptr,
425 438 .preserveAttachmentCount = 0,
426 VkSubpassDependency dependency; 439 .pPreserveAttachments = nullptr,
427 dependency.srcSubpass = VK_SUBPASS_EXTERNAL; 440 };
428 dependency.dstSubpass = 0; 441
429 dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; 442 const VkSubpassDependency dependency{
430 dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; 443 .srcSubpass = VK_SUBPASS_EXTERNAL,
431 dependency.srcAccessMask = 0; 444 .dstSubpass = 0,
432 dependency.dstAccessMask = 445 .srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
433 VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; 446 .dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
434 dependency.dependencyFlags = 0; 447 .srcAccessMask = 0,
435 448 .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
436 VkRenderPassCreateInfo renderpass_ci; 449 .dependencyFlags = 0,
437 renderpass_ci.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; 450 };
438 renderpass_ci.pNext = nullptr; 451
439 renderpass_ci.flags = 0; 452 const VkRenderPassCreateInfo renderpass_ci{
440 renderpass_ci.attachmentCount = 1; 453 .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
441 renderpass_ci.pAttachments = &color_attachment; 454 .pNext = nullptr,
442 renderpass_ci.subpassCount = 1; 455 .flags = 0,
443 renderpass_ci.pSubpasses = &subpass_description; 456 .attachmentCount = 1,
444 renderpass_ci.dependencyCount = 1; 457 .pAttachments = &color_attachment,
445 renderpass_ci.pDependencies = &dependency; 458 .subpassCount = 1,
459 .pSubpasses = &subpass_description,
460 .dependencyCount = 1,
461 .pDependencies = &dependency,
462 };
446 463
447 renderpass = device.GetLogical().CreateRenderPass(renderpass_ci); 464 renderpass = device.GetLogical().CreateRenderPass(renderpass_ci);
448} 465}
449 466
450void VKBlitScreen::CreateDescriptorSetLayout() { 467void VKBlitScreen::CreateDescriptorSetLayout() {
451 std::array<VkDescriptorSetLayoutBinding, 2> layout_bindings; 468 const std::array<VkDescriptorSetLayoutBinding, 2> layout_bindings{{
452 layout_bindings[0].binding = 0; 469 {
453 layout_bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; 470 .binding = 0,
454 layout_bindings[0].descriptorCount = 1; 471 .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
455 layout_bindings[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; 472 .descriptorCount = 1,
456 layout_bindings[0].pImmutableSamplers = nullptr; 473 .stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
457 layout_bindings[1].binding = 1; 474 .pImmutableSamplers = nullptr,
458 layout_bindings[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; 475 },
459 layout_bindings[1].descriptorCount = 1; 476 {
460 layout_bindings[1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; 477 .binding = 1,
461 layout_bindings[1].pImmutableSamplers = nullptr; 478 .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
462 479 .descriptorCount = 1,
463 VkDescriptorSetLayoutCreateInfo ci; 480 .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
464 ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; 481 .pImmutableSamplers = nullptr,
465 ci.pNext = nullptr; 482 },
466 ci.flags = 0; 483 }};
467 ci.bindingCount = static_cast<u32>(layout_bindings.size()); 484
468 ci.pBindings = layout_bindings.data(); 485 const VkDescriptorSetLayoutCreateInfo ci{
486 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
487 .pNext = nullptr,
488 .flags = 0,
489 .bindingCount = static_cast<u32>(layout_bindings.size()),
490 .pBindings = layout_bindings.data(),
491 };
469 492
470 descriptor_set_layout = device.GetLogical().CreateDescriptorSetLayout(ci); 493 descriptor_set_layout = device.GetLogical().CreateDescriptorSetLayout(ci);
471} 494}
@@ -473,175 +496,192 @@ void VKBlitScreen::CreateDescriptorSetLayout() {
473void VKBlitScreen::CreateDescriptorSets() { 496void VKBlitScreen::CreateDescriptorSets() {
474 const std::vector layouts(image_count, *descriptor_set_layout); 497 const std::vector layouts(image_count, *descriptor_set_layout);
475 498
476 VkDescriptorSetAllocateInfo ai; 499 const VkDescriptorSetAllocateInfo ai{
477 ai.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; 500 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
478 ai.pNext = nullptr; 501 .pNext = nullptr,
479 ai.descriptorPool = *descriptor_pool; 502 .descriptorPool = *descriptor_pool,
480 ai.descriptorSetCount = static_cast<u32>(image_count); 503 .descriptorSetCount = static_cast<u32>(image_count),
481 ai.pSetLayouts = layouts.data(); 504 .pSetLayouts = layouts.data(),
505 };
506
482 descriptor_sets = descriptor_pool.Allocate(ai); 507 descriptor_sets = descriptor_pool.Allocate(ai);
483} 508}
484 509
485void VKBlitScreen::CreatePipelineLayout() { 510void VKBlitScreen::CreatePipelineLayout() {
486 VkPipelineLayoutCreateInfo ci; 511 const VkPipelineLayoutCreateInfo ci{
487 ci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; 512 .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
488 ci.pNext = nullptr; 513 .pNext = nullptr,
489 ci.flags = 0; 514 .flags = 0,
490 ci.setLayoutCount = 1; 515 .setLayoutCount = 1,
491 ci.pSetLayouts = descriptor_set_layout.address(); 516 .pSetLayouts = descriptor_set_layout.address(),
492 ci.pushConstantRangeCount = 0; 517 .pushConstantRangeCount = 0,
493 ci.pPushConstantRanges = nullptr; 518 .pPushConstantRanges = nullptr,
519 };
494 pipeline_layout = device.GetLogical().CreatePipelineLayout(ci); 520 pipeline_layout = device.GetLogical().CreatePipelineLayout(ci);
495} 521}
496 522
497void VKBlitScreen::CreateGraphicsPipeline() { 523void VKBlitScreen::CreateGraphicsPipeline() {
498 std::array<VkPipelineShaderStageCreateInfo, 2> shader_stages; 524 const std::array<VkPipelineShaderStageCreateInfo, 2> shader_stages{{
499 shader_stages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; 525 {
500 shader_stages[0].pNext = nullptr; 526 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
501 shader_stages[0].flags = 0; 527 .pNext = nullptr,
502 shader_stages[0].stage = VK_SHADER_STAGE_VERTEX_BIT; 528 .flags = 0,
503 shader_stages[0].module = *vertex_shader; 529 .stage = VK_SHADER_STAGE_VERTEX_BIT,
504 shader_stages[0].pName = "main"; 530 .module = *vertex_shader,
505 shader_stages[0].pSpecializationInfo = nullptr; 531 .pName = "main",
506 shader_stages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; 532 .pSpecializationInfo = nullptr,
507 shader_stages[1].pNext = nullptr; 533 },
508 shader_stages[1].flags = 0; 534 {
509 shader_stages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; 535 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
510 shader_stages[1].module = *fragment_shader; 536 .pNext = nullptr,
511 shader_stages[1].pName = "main"; 537 .flags = 0,
512 shader_stages[1].pSpecializationInfo = nullptr; 538 .stage = VK_SHADER_STAGE_FRAGMENT_BIT,
539 .module = *fragment_shader,
540 .pName = "main",
541 .pSpecializationInfo = nullptr,
542 },
543 }};
513 544
514 const auto vertex_binding_description = ScreenRectVertex::GetDescription(); 545 const auto vertex_binding_description = ScreenRectVertex::GetDescription();
515 const auto vertex_attrs_description = ScreenRectVertex::GetAttributes(); 546 const auto vertex_attrs_description = ScreenRectVertex::GetAttributes();
516 547
517 VkPipelineVertexInputStateCreateInfo vertex_input_ci; 548 const VkPipelineVertexInputStateCreateInfo vertex_input_ci{
518 vertex_input_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; 549 .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
519 vertex_input_ci.pNext = nullptr; 550 .pNext = nullptr,
520 vertex_input_ci.flags = 0; 551 .flags = 0,
521 vertex_input_ci.vertexBindingDescriptionCount = 1; 552 .vertexBindingDescriptionCount = 1,
522 vertex_input_ci.pVertexBindingDescriptions = &vertex_binding_description; 553 .pVertexBindingDescriptions = &vertex_binding_description,
523 vertex_input_ci.vertexAttributeDescriptionCount = u32{vertex_attrs_description.size()}; 554 .vertexAttributeDescriptionCount = u32{vertex_attrs_description.size()},
524 vertex_input_ci.pVertexAttributeDescriptions = vertex_attrs_description.data(); 555 .pVertexAttributeDescriptions = vertex_attrs_description.data(),
525 556 };
526 VkPipelineInputAssemblyStateCreateInfo input_assembly_ci; 557
527 input_assembly_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; 558 const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci{
528 input_assembly_ci.pNext = nullptr; 559 .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
529 input_assembly_ci.flags = 0; 560 .pNext = nullptr,
530 input_assembly_ci.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; 561 .flags = 0,
531 input_assembly_ci.primitiveRestartEnable = VK_FALSE; 562 .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
532 563 .primitiveRestartEnable = VK_FALSE,
533 VkPipelineViewportStateCreateInfo viewport_state_ci; 564 };
534 viewport_state_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; 565
535 viewport_state_ci.pNext = nullptr; 566 const VkPipelineViewportStateCreateInfo viewport_state_ci{
536 viewport_state_ci.flags = 0; 567 .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
537 viewport_state_ci.viewportCount = 1; 568 .pNext = nullptr,
538 viewport_state_ci.pViewports = nullptr; 569 .flags = 0,
539 viewport_state_ci.scissorCount = 1; 570 .viewportCount = 1,
540 viewport_state_ci.pScissors = nullptr; 571 .pViewports = nullptr,
541 572 .scissorCount = 1,
542 VkPipelineRasterizationStateCreateInfo rasterization_ci; 573 .pScissors = nullptr,
543 rasterization_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; 574 };
544 rasterization_ci.pNext = nullptr; 575
545 rasterization_ci.flags = 0; 576 const VkPipelineRasterizationStateCreateInfo rasterization_ci{
546 rasterization_ci.depthClampEnable = VK_FALSE; 577 .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
547 rasterization_ci.rasterizerDiscardEnable = VK_FALSE; 578 .pNext = nullptr,
548 rasterization_ci.polygonMode = VK_POLYGON_MODE_FILL; 579 .flags = 0,
549 rasterization_ci.cullMode = VK_CULL_MODE_NONE; 580 .depthClampEnable = VK_FALSE,
550 rasterization_ci.frontFace = VK_FRONT_FACE_CLOCKWISE; 581 .rasterizerDiscardEnable = VK_FALSE,
551 rasterization_ci.depthBiasEnable = VK_FALSE; 582 .polygonMode = VK_POLYGON_MODE_FILL,
552 rasterization_ci.depthBiasConstantFactor = 0.0f; 583 .cullMode = VK_CULL_MODE_NONE,
553 rasterization_ci.depthBiasClamp = 0.0f; 584 .frontFace = VK_FRONT_FACE_CLOCKWISE,
554 rasterization_ci.depthBiasSlopeFactor = 0.0f; 585 .depthBiasEnable = VK_FALSE,
555 rasterization_ci.lineWidth = 1.0f; 586 .depthBiasConstantFactor = 0.0f,
556 587 .depthBiasClamp = 0.0f,
557 VkPipelineMultisampleStateCreateInfo multisampling_ci; 588 .depthBiasSlopeFactor = 0.0f,
558 multisampling_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; 589 .lineWidth = 1.0f,
559 multisampling_ci.pNext = nullptr; 590 };
560 multisampling_ci.flags = 0; 591
561 multisampling_ci.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; 592 const VkPipelineMultisampleStateCreateInfo multisampling_ci{
562 multisampling_ci.sampleShadingEnable = VK_FALSE; 593 .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
563 multisampling_ci.minSampleShading = 0.0f; 594 .pNext = nullptr,
564 multisampling_ci.pSampleMask = nullptr; 595 .flags = 0,
565 multisampling_ci.alphaToCoverageEnable = VK_FALSE; 596 .rasterizationSamples = VK_SAMPLE_COUNT_1_BIT,
566 multisampling_ci.alphaToOneEnable = VK_FALSE; 597 .sampleShadingEnable = VK_FALSE,
567 598 .minSampleShading = 0.0f,
568 VkPipelineColorBlendAttachmentState color_blend_attachment; 599 .pSampleMask = nullptr,
569 color_blend_attachment.blendEnable = VK_FALSE; 600 .alphaToCoverageEnable = VK_FALSE,
570 color_blend_attachment.srcColorBlendFactor = VK_BLEND_FACTOR_ZERO; 601 .alphaToOneEnable = VK_FALSE,
571 color_blend_attachment.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO; 602 };
572 color_blend_attachment.colorBlendOp = VK_BLEND_OP_ADD; 603
573 color_blend_attachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; 604 const VkPipelineColorBlendAttachmentState color_blend_attachment{
574 color_blend_attachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; 605 .blendEnable = VK_FALSE,
575 color_blend_attachment.alphaBlendOp = VK_BLEND_OP_ADD; 606 .srcColorBlendFactor = VK_BLEND_FACTOR_ZERO,
576 color_blend_attachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | 607 .dstColorBlendFactor = VK_BLEND_FACTOR_ZERO,
577 VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; 608 .colorBlendOp = VK_BLEND_OP_ADD,
578 609 .srcAlphaBlendFactor = VK_BLEND_FACTOR_ZERO,
579 VkPipelineColorBlendStateCreateInfo color_blend_ci; 610 .dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO,
580 color_blend_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; 611 .alphaBlendOp = VK_BLEND_OP_ADD,
581 color_blend_ci.flags = 0; 612 .colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
582 color_blend_ci.pNext = nullptr; 613 VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT,
583 color_blend_ci.logicOpEnable = VK_FALSE; 614 };
584 color_blend_ci.logicOp = VK_LOGIC_OP_COPY; 615
585 color_blend_ci.attachmentCount = 1; 616 const VkPipelineColorBlendStateCreateInfo color_blend_ci{
586 color_blend_ci.pAttachments = &color_blend_attachment; 617 .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
587 color_blend_ci.blendConstants[0] = 0.0f; 618 .pNext = nullptr,
588 color_blend_ci.blendConstants[1] = 0.0f; 619 .flags = 0,
589 color_blend_ci.blendConstants[2] = 0.0f; 620 .logicOpEnable = VK_FALSE,
590 color_blend_ci.blendConstants[3] = 0.0f; 621 .logicOp = VK_LOGIC_OP_COPY,
591 622 .attachmentCount = 1,
592 static constexpr std::array dynamic_states = {VK_DYNAMIC_STATE_VIEWPORT, 623 .pAttachments = &color_blend_attachment,
593 VK_DYNAMIC_STATE_SCISSOR}; 624 .blendConstants = {0.0f, 0.0f, 0.0f, 0.0f},
594 VkPipelineDynamicStateCreateInfo dynamic_state_ci; 625 };
595 dynamic_state_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; 626
596 dynamic_state_ci.pNext = nullptr; 627 static constexpr std::array dynamic_states{
597 dynamic_state_ci.flags = 0; 628 VK_DYNAMIC_STATE_VIEWPORT,
598 dynamic_state_ci.dynamicStateCount = static_cast<u32>(dynamic_states.size()); 629 VK_DYNAMIC_STATE_SCISSOR,
599 dynamic_state_ci.pDynamicStates = dynamic_states.data(); 630 };
600 631 const VkPipelineDynamicStateCreateInfo dynamic_state_ci{
601 VkGraphicsPipelineCreateInfo pipeline_ci; 632 .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
602 pipeline_ci.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; 633 .pNext = nullptr,
603 pipeline_ci.pNext = nullptr; 634 .flags = 0,
604 pipeline_ci.flags = 0; 635 .dynamicStateCount = static_cast<u32>(dynamic_states.size()),
605 pipeline_ci.stageCount = static_cast<u32>(shader_stages.size()); 636 .pDynamicStates = dynamic_states.data(),
606 pipeline_ci.pStages = shader_stages.data(); 637 };
607 pipeline_ci.pVertexInputState = &vertex_input_ci; 638
608 pipeline_ci.pInputAssemblyState = &input_assembly_ci; 639 const VkGraphicsPipelineCreateInfo pipeline_ci{
609 pipeline_ci.pTessellationState = nullptr; 640 .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
610 pipeline_ci.pViewportState = &viewport_state_ci; 641 .pNext = nullptr,
611 pipeline_ci.pRasterizationState = &rasterization_ci; 642 .flags = 0,
612 pipeline_ci.pMultisampleState = &multisampling_ci; 643 .stageCount = static_cast<u32>(shader_stages.size()),
613 pipeline_ci.pDepthStencilState = nullptr; 644 .pStages = shader_stages.data(),
614 pipeline_ci.pColorBlendState = &color_blend_ci; 645 .pVertexInputState = &vertex_input_ci,
615 pipeline_ci.pDynamicState = &dynamic_state_ci; 646 .pInputAssemblyState = &input_assembly_ci,
616 pipeline_ci.layout = *pipeline_layout; 647 .pTessellationState = nullptr,
617 pipeline_ci.renderPass = *renderpass; 648 .pViewportState = &viewport_state_ci,
618 pipeline_ci.subpass = 0; 649 .pRasterizationState = &rasterization_ci,
619 pipeline_ci.basePipelineHandle = 0; 650 .pMultisampleState = &multisampling_ci,
620 pipeline_ci.basePipelineIndex = 0; 651 .pDepthStencilState = nullptr,
652 .pColorBlendState = &color_blend_ci,
653 .pDynamicState = &dynamic_state_ci,
654 .layout = *pipeline_layout,
655 .renderPass = *renderpass,
656 .subpass = 0,
657 .basePipelineHandle = 0,
658 .basePipelineIndex = 0,
659 };
621 660
622 pipeline = device.GetLogical().CreateGraphicsPipeline(pipeline_ci); 661 pipeline = device.GetLogical().CreateGraphicsPipeline(pipeline_ci);
623} 662}
624 663
625void VKBlitScreen::CreateSampler() { 664void VKBlitScreen::CreateSampler() {
626 VkSamplerCreateInfo ci; 665 const VkSamplerCreateInfo ci{
627 ci.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; 666 .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
628 ci.pNext = nullptr; 667 .pNext = nullptr,
629 ci.flags = 0; 668 .flags = 0,
630 ci.magFilter = VK_FILTER_LINEAR; 669 .magFilter = VK_FILTER_LINEAR,
631 ci.minFilter = VK_FILTER_NEAREST; 670 .minFilter = VK_FILTER_NEAREST,
632 ci.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; 671 .mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR,
633 ci.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; 672 .addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,
634 ci.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; 673 .addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,
635 ci.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; 674 .addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,
636 ci.mipLodBias = 0.0f; 675 .mipLodBias = 0.0f,
637 ci.anisotropyEnable = VK_FALSE; 676 .anisotropyEnable = VK_FALSE,
638 ci.maxAnisotropy = 0.0f; 677 .maxAnisotropy = 0.0f,
639 ci.compareEnable = VK_FALSE; 678 .compareEnable = VK_FALSE,
640 ci.compareOp = VK_COMPARE_OP_NEVER; 679 .compareOp = VK_COMPARE_OP_NEVER,
641 ci.minLod = 0.0f; 680 .minLod = 0.0f,
642 ci.maxLod = 0.0f; 681 .maxLod = 0.0f,
643 ci.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK; 682 .borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK,
644 ci.unnormalizedCoordinates = VK_FALSE; 683 .unnormalizedCoordinates = VK_FALSE,
684 };
645 685
646 sampler = device.GetLogical().CreateSampler(ci); 686 sampler = device.GetLogical().CreateSampler(ci);
647} 687}
@@ -650,15 +690,16 @@ void VKBlitScreen::CreateFramebuffers() {
650 const VkExtent2D size{swapchain.GetSize()}; 690 const VkExtent2D size{swapchain.GetSize()};
651 framebuffers.resize(image_count); 691 framebuffers.resize(image_count);
652 692
653 VkFramebufferCreateInfo ci; 693 VkFramebufferCreateInfo ci{
654 ci.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; 694 .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
655 ci.pNext = nullptr; 695 .pNext = nullptr,
656 ci.flags = 0; 696 .flags = 0,
657 ci.renderPass = *renderpass; 697 .renderPass = *renderpass,
658 ci.attachmentCount = 1; 698 .attachmentCount = 1,
659 ci.width = size.width; 699 .width = size.width,
660 ci.height = size.height; 700 .height = size.height,
661 ci.layers = 1; 701 .layers = 1,
702 };
662 703
663 for (std::size_t i = 0; i < image_count; ++i) { 704 for (std::size_t i = 0; i < image_count; ++i) {
664 const VkImageView image_view{swapchain.GetImageViewIndex(i)}; 705 const VkImageView image_view{swapchain.GetImageViewIndex(i)};
@@ -678,16 +719,17 @@ void VKBlitScreen::ReleaseRawImages() {
678} 719}
679 720
680void VKBlitScreen::CreateStagingBuffer(const Tegra::FramebufferConfig& framebuffer) { 721void VKBlitScreen::CreateStagingBuffer(const Tegra::FramebufferConfig& framebuffer) {
681 VkBufferCreateInfo ci; 722 const VkBufferCreateInfo ci{
682 ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; 723 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
683 ci.pNext = nullptr; 724 .pNext = nullptr,
684 ci.flags = 0; 725 .flags = 0,
685 ci.size = CalculateBufferSize(framebuffer); 726 .size = CalculateBufferSize(framebuffer),
686 ci.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | 727 .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT |
687 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; 728 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
688 ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; 729 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
689 ci.queueFamilyIndexCount = 0; 730 .queueFamilyIndexCount = 0,
690 ci.pQueueFamilyIndices = nullptr; 731 .pQueueFamilyIndices = nullptr,
732 };
691 733
692 buffer = device.GetLogical().CreateBuffer(ci); 734 buffer = device.GetLogical().CreateBuffer(ci);
693 buffer_commit = memory_manager.Commit(buffer, true); 735 buffer_commit = memory_manager.Commit(buffer, true);
@@ -697,24 +739,28 @@ void VKBlitScreen::CreateRawImages(const Tegra::FramebufferConfig& framebuffer)
697 raw_images.resize(image_count); 739 raw_images.resize(image_count);
698 raw_buffer_commits.resize(image_count); 740 raw_buffer_commits.resize(image_count);
699 741
700 VkImageCreateInfo ci; 742 const VkImageCreateInfo ci{
701 ci.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; 743 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
702 ci.pNext = nullptr; 744 .pNext = nullptr,
703 ci.flags = 0; 745 .flags = 0,
704 ci.imageType = VK_IMAGE_TYPE_2D; 746 .imageType = VK_IMAGE_TYPE_2D,
705 ci.format = GetFormat(framebuffer); 747 .format = GetFormat(framebuffer),
706 ci.extent.width = framebuffer.width; 748 .extent =
707 ci.extent.height = framebuffer.height; 749 {
708 ci.extent.depth = 1; 750 .width = framebuffer.width,
709 ci.mipLevels = 1; 751 .height = framebuffer.height,
710 ci.arrayLayers = 1; 752 .depth = 1,
711 ci.samples = VK_SAMPLE_COUNT_1_BIT; 753 },
712 ci.tiling = VK_IMAGE_TILING_LINEAR; 754 .mipLevels = 1,
713 ci.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; 755 .arrayLayers = 1,
714 ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; 756 .samples = VK_SAMPLE_COUNT_1_BIT,
715 ci.queueFamilyIndexCount = 0; 757 .tiling = VK_IMAGE_TILING_LINEAR,
716 ci.pQueueFamilyIndices = nullptr; 758 .usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
717 ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; 759 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
760 .queueFamilyIndexCount = 0,
761 .pQueueFamilyIndices = nullptr,
762 .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
763 };
718 764
719 for (std::size_t i = 0; i < image_count; ++i) { 765 for (std::size_t i = 0; i < image_count; ++i) {
720 raw_images[i] = std::make_unique<VKImage>(device, scheduler, ci, VK_IMAGE_ASPECT_COLOR_BIT); 766 raw_images[i] = std::make_unique<VKImage>(device, scheduler, ci, VK_IMAGE_ASPECT_COLOR_BIT);
@@ -723,39 +769,43 @@ void VKBlitScreen::CreateRawImages(const Tegra::FramebufferConfig& framebuffer)
723} 769}
724 770
725void VKBlitScreen::UpdateDescriptorSet(std::size_t image_index, VkImageView image_view) const { 771void VKBlitScreen::UpdateDescriptorSet(std::size_t image_index, VkImageView image_view) const {
726 VkDescriptorBufferInfo buffer_info; 772 const VkDescriptorBufferInfo buffer_info{
727 buffer_info.buffer = *buffer; 773 .buffer = *buffer,
728 buffer_info.offset = offsetof(BufferData, uniform); 774 .offset = offsetof(BufferData, uniform),
729 buffer_info.range = sizeof(BufferData::uniform); 775 .range = sizeof(BufferData::uniform),
730 776 };
731 VkWriteDescriptorSet ubo_write; 777
732 ubo_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; 778 const VkWriteDescriptorSet ubo_write{
733 ubo_write.pNext = nullptr; 779 .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
734 ubo_write.dstSet = descriptor_sets[image_index]; 780 .pNext = nullptr,
735 ubo_write.dstBinding = 0; 781 .dstSet = descriptor_sets[image_index],
736 ubo_write.dstArrayElement = 0; 782 .dstBinding = 0,
737 ubo_write.descriptorCount = 1; 783 .dstArrayElement = 0,
738 ubo_write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; 784 .descriptorCount = 1,
739 ubo_write.pImageInfo = nullptr; 785 .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
740 ubo_write.pBufferInfo = &buffer_info; 786 .pImageInfo = nullptr,
741 ubo_write.pTexelBufferView = nullptr; 787 .pBufferInfo = &buffer_info,
742 788 .pTexelBufferView = nullptr,
743 VkDescriptorImageInfo image_info; 789 };
744 image_info.sampler = *sampler; 790
745 image_info.imageView = image_view; 791 const VkDescriptorImageInfo image_info{
746 image_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; 792 .sampler = *sampler,
747 793 .imageView = image_view,
748 VkWriteDescriptorSet sampler_write; 794 .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
749 sampler_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; 795 };
750 sampler_write.pNext = nullptr; 796
751 sampler_write.dstSet = descriptor_sets[image_index]; 797 const VkWriteDescriptorSet sampler_write{
752 sampler_write.dstBinding = 1; 798 .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
753 sampler_write.dstArrayElement = 0; 799 .pNext = nullptr,
754 sampler_write.descriptorCount = 1; 800 .dstSet = descriptor_sets[image_index],
755 sampler_write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; 801 .dstBinding = 1,
756 sampler_write.pImageInfo = &image_info; 802 .dstArrayElement = 0,
757 sampler_write.pBufferInfo = nullptr; 803 .descriptorCount = 1,
758 sampler_write.pTexelBufferView = nullptr; 804 .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
805 .pImageInfo = &image_info,
806 .pBufferInfo = nullptr,
807 .pTexelBufferView = nullptr,
808 };
759 809
760 device.GetLogical().UpdateDescriptorSets(std::array{ubo_write, sampler_write}, {}); 810 device.GetLogical().UpdateDescriptorSets(std::array{ubo_write, sampler_write}, {});
761} 811}
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
index 2be38d419..1d2f8b557 100644
--- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
@@ -39,16 +39,17 @@ std::unique_ptr<VKStreamBuffer> CreateStreamBuffer(const VKDevice& device, VKSch
39 39
40Buffer::Buffer(const VKDevice& device, VKMemoryManager& memory_manager, VKScheduler& scheduler_, 40Buffer::Buffer(const VKDevice& device, VKMemoryManager& memory_manager, VKScheduler& scheduler_,
41 VKStagingBufferPool& staging_pool_, VAddr cpu_addr, std::size_t size) 41 VKStagingBufferPool& staging_pool_, VAddr cpu_addr, std::size_t size)
42 : VideoCommon::BufferBlock{cpu_addr, size}, scheduler{scheduler_}, staging_pool{staging_pool_} { 42 : BufferBlock{cpu_addr, size}, scheduler{scheduler_}, staging_pool{staging_pool_} {
43 VkBufferCreateInfo ci; 43 const VkBufferCreateInfo ci{
44 ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; 44 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
45 ci.pNext = nullptr; 45 .pNext = nullptr,
46 ci.flags = 0; 46 .flags = 0,
47 ci.size = static_cast<VkDeviceSize>(size); 47 .size = static_cast<VkDeviceSize>(size),
48 ci.usage = BUFFER_USAGE | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; 48 .usage = BUFFER_USAGE | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
49 ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; 49 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
50 ci.queueFamilyIndexCount = 0; 50 .queueFamilyIndexCount = 0,
51 ci.pQueueFamilyIndices = nullptr; 51 .pQueueFamilyIndices = nullptr,
52 };
52 53
53 buffer.handle = device.GetLogical().CreateBuffer(ci); 54 buffer.handle = device.GetLogical().CreateBuffer(ci);
54 buffer.commit = memory_manager.Commit(buffer.handle, false); 55 buffer.commit = memory_manager.Commit(buffer.handle, false);
@@ -66,16 +67,17 @@ void Buffer::Upload(std::size_t offset, std::size_t size, const u8* data) {
66 scheduler.Record([staging = *staging.handle, handle, offset, size](vk::CommandBuffer cmdbuf) { 67 scheduler.Record([staging = *staging.handle, handle, offset, size](vk::CommandBuffer cmdbuf) {
67 cmdbuf.CopyBuffer(staging, handle, VkBufferCopy{0, offset, size}); 68 cmdbuf.CopyBuffer(staging, handle, VkBufferCopy{0, offset, size});
68 69
69 VkBufferMemoryBarrier barrier; 70 const VkBufferMemoryBarrier barrier{
70 barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; 71 .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
71 barrier.pNext = nullptr; 72 .pNext = nullptr,
72 barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; 73 .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
73 barrier.dstAccessMask = UPLOAD_ACCESS_BARRIERS; 74 .dstAccessMask = UPLOAD_ACCESS_BARRIERS,
74 barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 75 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
75 barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 76 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
76 barrier.buffer = handle; 77 .buffer = handle,
77 barrier.offset = offset; 78 .offset = offset,
78 barrier.size = size; 79 .size = size,
80 };
79 cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, UPLOAD_PIPELINE_STAGE, 0, {}, 81 cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, UPLOAD_PIPELINE_STAGE, 0, {},
80 barrier, {}); 82 barrier, {});
81 }); 83 });
@@ -87,16 +89,17 @@ void Buffer::Download(std::size_t offset, std::size_t size, u8* data) {
87 89
88 const VkBuffer handle = Handle(); 90 const VkBuffer handle = Handle();
89 scheduler.Record([staging = *staging.handle, handle, offset, size](vk::CommandBuffer cmdbuf) { 91 scheduler.Record([staging = *staging.handle, handle, offset, size](vk::CommandBuffer cmdbuf) {
90 VkBufferMemoryBarrier barrier; 92 const VkBufferMemoryBarrier barrier{
91 barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; 93 .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
92 barrier.pNext = nullptr; 94 .pNext = nullptr,
93 barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; 95 .srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT,
94 barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; 96 .dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT,
95 barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 97 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
96 barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 98 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
97 barrier.buffer = handle; 99 .buffer = handle,
98 barrier.offset = offset; 100 .offset = offset,
99 barrier.size = size; 101 .size = size,
102 };
100 103
101 cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | 104 cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
102 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | 105 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
diff --git a/src/video_core/renderer_vulkan/vk_compute_pass.cpp b/src/video_core/renderer_vulkan/vk_compute_pass.cpp
index da71e710c..182461ed9 100644
--- a/src/video_core/renderer_vulkan/vk_compute_pass.cpp
+++ b/src/video_core/renderer_vulkan/vk_compute_pass.cpp
@@ -115,32 +115,32 @@ constexpr u8 quad_array[] = {
115 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00}; 115 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00};
116 116
117VkDescriptorSetLayoutBinding BuildQuadArrayPassDescriptorSetLayoutBinding() { 117VkDescriptorSetLayoutBinding BuildQuadArrayPassDescriptorSetLayoutBinding() {
118 VkDescriptorSetLayoutBinding binding; 118 return {
119 binding.binding = 0; 119 .binding = 0,
120 binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; 120 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
121 binding.descriptorCount = 1; 121 .descriptorCount = 1,
122 binding.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; 122 .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
123 binding.pImmutableSamplers = nullptr; 123 .pImmutableSamplers = nullptr,
124 return binding; 124 };
125} 125}
126 126
127VkDescriptorUpdateTemplateEntryKHR BuildQuadArrayPassDescriptorUpdateTemplateEntry() { 127VkDescriptorUpdateTemplateEntryKHR BuildQuadArrayPassDescriptorUpdateTemplateEntry() {
128 VkDescriptorUpdateTemplateEntryKHR entry; 128 return {
129 entry.dstBinding = 0; 129 .dstBinding = 0,
130 entry.dstArrayElement = 0; 130 .dstArrayElement = 0,
131 entry.descriptorCount = 1; 131 .descriptorCount = 1,
132 entry.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; 132 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
133 entry.offset = 0; 133 .offset = 0,
134 entry.stride = sizeof(DescriptorUpdateEntry); 134 .stride = sizeof(DescriptorUpdateEntry),
135 return entry; 135 };
136} 136}
137 137
138VkPushConstantRange BuildComputePushConstantRange(std::size_t size) { 138VkPushConstantRange BuildComputePushConstantRange(std::size_t size) {
139 VkPushConstantRange range; 139 return {
140 range.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; 140 .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
141 range.offset = 0; 141 .offset = 0,
142 range.size = static_cast<u32>(size); 142 .size = static_cast<u32>(size),
143 return range; 143 };
144} 144}
145 145
146// Uint8 SPIR-V module. Generated from the "shaders/" directory. 146// Uint8 SPIR-V module. Generated from the "shaders/" directory.
@@ -344,29 +344,33 @@ constexpr u8 QUAD_INDEXED_SPV[] = {
344 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00}; 344 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00};
345 345
346std::array<VkDescriptorSetLayoutBinding, 2> BuildInputOutputDescriptorSetBindings() { 346std::array<VkDescriptorSetLayoutBinding, 2> BuildInputOutputDescriptorSetBindings() {
347 std::array<VkDescriptorSetLayoutBinding, 2> bindings; 347 return {{
348 bindings[0].binding = 0; 348 {
349 bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; 349 .binding = 0,
350 bindings[0].descriptorCount = 1; 350 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
351 bindings[0].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; 351 .descriptorCount = 1,
352 bindings[0].pImmutableSamplers = nullptr; 352 .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
353 bindings[1].binding = 1; 353 .pImmutableSamplers = nullptr,
354 bindings[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; 354 },
355 bindings[1].descriptorCount = 1; 355 {
356 bindings[1].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; 356 .binding = 1,
357 bindings[1].pImmutableSamplers = nullptr; 357 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
358 return bindings; 358 .descriptorCount = 1,
359 .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
360 .pImmutableSamplers = nullptr,
361 },
362 }};
359} 363}
360 364
361VkDescriptorUpdateTemplateEntryKHR BuildInputOutputDescriptorUpdateTemplate() { 365VkDescriptorUpdateTemplateEntryKHR BuildInputOutputDescriptorUpdateTemplate() {
362 VkDescriptorUpdateTemplateEntryKHR entry; 366 return {
363 entry.dstBinding = 0; 367 .dstBinding = 0,
364 entry.dstArrayElement = 0; 368 .dstArrayElement = 0,
365 entry.descriptorCount = 2; 369 .descriptorCount = 2,
366 entry.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; 370 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
367 entry.offset = 0; 371 .offset = 0,
368 entry.stride = sizeof(DescriptorUpdateEntry); 372 .stride = sizeof(DescriptorUpdateEntry),
369 return entry; 373 };
370} 374}
371 375
372} // Anonymous namespace 376} // Anonymous namespace
@@ -376,37 +380,37 @@ VKComputePass::VKComputePass(const VKDevice& device, VKDescriptorPool& descripto
376 vk::Span<VkDescriptorUpdateTemplateEntryKHR> templates, 380 vk::Span<VkDescriptorUpdateTemplateEntryKHR> templates,
377 vk::Span<VkPushConstantRange> push_constants, std::size_t code_size, 381 vk::Span<VkPushConstantRange> push_constants, std::size_t code_size,
378 const u8* code) { 382 const u8* code) {
379 VkDescriptorSetLayoutCreateInfo descriptor_layout_ci; 383 descriptor_set_layout = device.GetLogical().CreateDescriptorSetLayout({
380 descriptor_layout_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; 384 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
381 descriptor_layout_ci.pNext = nullptr; 385 .pNext = nullptr,
382 descriptor_layout_ci.flags = 0; 386 .flags = 0,
383 descriptor_layout_ci.bindingCount = bindings.size(); 387 .bindingCount = bindings.size(),
384 descriptor_layout_ci.pBindings = bindings.data(); 388 .pBindings = bindings.data(),
385 descriptor_set_layout = device.GetLogical().CreateDescriptorSetLayout(descriptor_layout_ci); 389 });
386 390
387 VkPipelineLayoutCreateInfo pipeline_layout_ci; 391 layout = device.GetLogical().CreatePipelineLayout({
388 pipeline_layout_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; 392 .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
389 pipeline_layout_ci.pNext = nullptr; 393 .pNext = nullptr,
390 pipeline_layout_ci.flags = 0; 394 .flags = 0,
391 pipeline_layout_ci.setLayoutCount = 1; 395 .setLayoutCount = 1,
392 pipeline_layout_ci.pSetLayouts = descriptor_set_layout.address(); 396 .pSetLayouts = descriptor_set_layout.address(),
393 pipeline_layout_ci.pushConstantRangeCount = push_constants.size(); 397 .pushConstantRangeCount = push_constants.size(),
394 pipeline_layout_ci.pPushConstantRanges = push_constants.data(); 398 .pPushConstantRanges = push_constants.data(),
395 layout = device.GetLogical().CreatePipelineLayout(pipeline_layout_ci); 399 });
396 400
397 if (!templates.empty()) { 401 if (!templates.empty()) {
398 VkDescriptorUpdateTemplateCreateInfoKHR template_ci; 402 descriptor_template = device.GetLogical().CreateDescriptorUpdateTemplateKHR({
399 template_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR; 403 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR,
400 template_ci.pNext = nullptr; 404 .pNext = nullptr,
401 template_ci.flags = 0; 405 .flags = 0,
402 template_ci.descriptorUpdateEntryCount = templates.size(); 406 .descriptorUpdateEntryCount = templates.size(),
403 template_ci.pDescriptorUpdateEntries = templates.data(); 407 .pDescriptorUpdateEntries = templates.data(),
404 template_ci.templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR; 408 .templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR,
405 template_ci.descriptorSetLayout = *descriptor_set_layout; 409 .descriptorSetLayout = *descriptor_set_layout,
406 template_ci.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; 410 .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
407 template_ci.pipelineLayout = *layout; 411 .pipelineLayout = *layout,
408 template_ci.set = 0; 412 .set = 0,
409 descriptor_template = device.GetLogical().CreateDescriptorUpdateTemplateKHR(template_ci); 413 });
410 414
411 descriptor_allocator.emplace(descriptor_pool, *descriptor_set_layout); 415 descriptor_allocator.emplace(descriptor_pool, *descriptor_set_layout);
412 } 416 }
@@ -414,32 +418,32 @@ VKComputePass::VKComputePass(const VKDevice& device, VKDescriptorPool& descripto
414 auto code_copy = std::make_unique<u32[]>(code_size / sizeof(u32) + 1); 418 auto code_copy = std::make_unique<u32[]>(code_size / sizeof(u32) + 1);
415 std::memcpy(code_copy.get(), code, code_size); 419 std::memcpy(code_copy.get(), code, code_size);
416 420
417 VkShaderModuleCreateInfo module_ci; 421 module = device.GetLogical().CreateShaderModule({
418 module_ci.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; 422 .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
419 module_ci.pNext = nullptr; 423 .pNext = nullptr,
420 module_ci.flags = 0; 424 .flags = 0,
421 module_ci.codeSize = code_size; 425 .codeSize = code_size,
422 module_ci.pCode = code_copy.get(); 426 .pCode = code_copy.get(),
423 module = device.GetLogical().CreateShaderModule(module_ci); 427 });
424 428
425 VkComputePipelineCreateInfo pipeline_ci; 429 pipeline = device.GetLogical().CreateComputePipeline({
426 pipeline_ci.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; 430 .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
427 pipeline_ci.pNext = nullptr; 431 .pNext = nullptr,
428 pipeline_ci.flags = 0; 432 .flags = 0,
429 pipeline_ci.layout = *layout; 433 .stage =
430 pipeline_ci.basePipelineHandle = nullptr; 434 {
431 pipeline_ci.basePipelineIndex = 0; 435 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
432 436 .pNext = nullptr,
433 VkPipelineShaderStageCreateInfo& stage_ci = pipeline_ci.stage; 437 .flags = 0,
434 stage_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; 438 .stage = VK_SHADER_STAGE_COMPUTE_BIT,
435 stage_ci.pNext = nullptr; 439 .module = *module,
436 stage_ci.flags = 0; 440 .pName = "main",
437 stage_ci.stage = VK_SHADER_STAGE_COMPUTE_BIT; 441 .pSpecializationInfo = nullptr,
438 stage_ci.module = *module; 442 },
439 stage_ci.pName = "main"; 443 .layout = *layout,
440 stage_ci.pSpecializationInfo = nullptr; 444 .basePipelineHandle = nullptr,
441 445 .basePipelineIndex = 0,
442 pipeline = device.GetLogical().CreateComputePipeline(pipeline_ci); 446 });
443} 447}
444 448
445VKComputePass::~VKComputePass() = default; 449VKComputePass::~VKComputePass() = default;
diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
index 281bf9ac3..ed9d2991c 100644
--- a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
+++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
@@ -43,12 +43,13 @@ vk::DescriptorSetLayout VKComputePipeline::CreateDescriptorSetLayout() const {
43 const auto add_bindings = [&](VkDescriptorType descriptor_type, std::size_t num_entries) { 43 const auto add_bindings = [&](VkDescriptorType descriptor_type, std::size_t num_entries) {
44 // TODO(Rodrigo): Maybe make individual bindings here? 44 // TODO(Rodrigo): Maybe make individual bindings here?
45 for (u32 bindpoint = 0; bindpoint < static_cast<u32>(num_entries); ++bindpoint) { 45 for (u32 bindpoint = 0; bindpoint < static_cast<u32>(num_entries); ++bindpoint) {
46 VkDescriptorSetLayoutBinding& entry = bindings.emplace_back(); 46 bindings.push_back({
47 entry.binding = binding++; 47 .binding = binding++,
48 entry.descriptorType = descriptor_type; 48 .descriptorType = descriptor_type,
49 entry.descriptorCount = 1; 49 .descriptorCount = 1,
50 entry.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; 50 .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
51 entry.pImmutableSamplers = nullptr; 51 .pImmutableSamplers = nullptr,
52 });
52 } 53 }
53 }; 54 };
54 add_bindings(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, entries.const_buffers.size()); 55 add_bindings(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, entries.const_buffers.size());
@@ -58,25 +59,25 @@ vk::DescriptorSetLayout VKComputePipeline::CreateDescriptorSetLayout() const {
58 add_bindings(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, entries.storage_texels.size()); 59 add_bindings(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, entries.storage_texels.size());
59 add_bindings(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, entries.images.size()); 60 add_bindings(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, entries.images.size());
60 61
61 VkDescriptorSetLayoutCreateInfo ci; 62 return device.GetLogical().CreateDescriptorSetLayout({
62 ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; 63 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
63 ci.pNext = nullptr; 64 .pNext = nullptr,
64 ci.flags = 0; 65 .flags = 0,
65 ci.bindingCount = static_cast<u32>(bindings.size()); 66 .bindingCount = static_cast<u32>(bindings.size()),
66 ci.pBindings = bindings.data(); 67 .pBindings = bindings.data(),
67 return device.GetLogical().CreateDescriptorSetLayout(ci); 68 });
68} 69}
69 70
70vk::PipelineLayout VKComputePipeline::CreatePipelineLayout() const { 71vk::PipelineLayout VKComputePipeline::CreatePipelineLayout() const {
71 VkPipelineLayoutCreateInfo ci; 72 return device.GetLogical().CreatePipelineLayout({
72 ci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; 73 .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
73 ci.pNext = nullptr; 74 .pNext = nullptr,
74 ci.flags = 0; 75 .flags = 0,
75 ci.setLayoutCount = 1; 76 .setLayoutCount = 1,
76 ci.pSetLayouts = descriptor_set_layout.address(); 77 .pSetLayouts = descriptor_set_layout.address(),
77 ci.pushConstantRangeCount = 0; 78 .pushConstantRangeCount = 0,
78 ci.pPushConstantRanges = nullptr; 79 .pPushConstantRanges = nullptr,
79 return device.GetLogical().CreatePipelineLayout(ci); 80 });
80} 81}
81 82
82vk::DescriptorUpdateTemplateKHR VKComputePipeline::CreateDescriptorUpdateTemplate() const { 83vk::DescriptorUpdateTemplateKHR VKComputePipeline::CreateDescriptorUpdateTemplate() const {
@@ -89,59 +90,63 @@ vk::DescriptorUpdateTemplateKHR VKComputePipeline::CreateDescriptorUpdateTemplat
89 return {}; 90 return {};
90 } 91 }
91 92
92 VkDescriptorUpdateTemplateCreateInfoKHR ci; 93 return device.GetLogical().CreateDescriptorUpdateTemplateKHR({
93 ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR; 94 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR,
94 ci.pNext = nullptr; 95 .pNext = nullptr,
95 ci.flags = 0; 96 .flags = 0,
96 ci.descriptorUpdateEntryCount = static_cast<u32>(template_entries.size()); 97 .descriptorUpdateEntryCount = static_cast<u32>(template_entries.size()),
97 ci.pDescriptorUpdateEntries = template_entries.data(); 98 .pDescriptorUpdateEntries = template_entries.data(),
98 ci.templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR; 99 .templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR,
99 ci.descriptorSetLayout = *descriptor_set_layout; 100 .descriptorSetLayout = *descriptor_set_layout,
100 ci.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; 101 .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
101 ci.pipelineLayout = *layout; 102 .pipelineLayout = *layout,
102 ci.set = DESCRIPTOR_SET; 103 .set = DESCRIPTOR_SET,
103 return device.GetLogical().CreateDescriptorUpdateTemplateKHR(ci); 104 });
104} 105}
105 106
106vk::ShaderModule VKComputePipeline::CreateShaderModule(const std::vector<u32>& code) const { 107vk::ShaderModule VKComputePipeline::CreateShaderModule(const std::vector<u32>& code) const {
107 device.SaveShader(code); 108 device.SaveShader(code);
108 109
109 VkShaderModuleCreateInfo ci; 110 return device.GetLogical().CreateShaderModule({
110 ci.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; 111 .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
111 ci.pNext = nullptr; 112 .pNext = nullptr,
112 ci.flags = 0; 113 .flags = 0,
113 ci.codeSize = code.size() * sizeof(u32); 114 .codeSize = code.size() * sizeof(u32),
114 ci.pCode = code.data(); 115 .pCode = code.data(),
115 return device.GetLogical().CreateShaderModule(ci); 116 });
116} 117}
117 118
118vk::Pipeline VKComputePipeline::CreatePipeline() const { 119vk::Pipeline VKComputePipeline::CreatePipeline() const {
119 VkComputePipelineCreateInfo ci; 120
120 VkPipelineShaderStageCreateInfo& stage_ci = ci.stage; 121 VkComputePipelineCreateInfo ci{
121 stage_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; 122 .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
122 stage_ci.pNext = nullptr; 123 .pNext = nullptr,
123 stage_ci.flags = 0; 124 .flags = 0,
124 stage_ci.stage = VK_SHADER_STAGE_COMPUTE_BIT; 125 .stage =
125 stage_ci.module = *shader_module; 126 {
126 stage_ci.pName = "main"; 127 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
127 stage_ci.pSpecializationInfo = nullptr; 128 .pNext = nullptr,
128 129 .flags = 0,
129 VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT subgroup_size_ci; 130 .stage = VK_SHADER_STAGE_COMPUTE_BIT,
130 subgroup_size_ci.sType = 131 .module = *shader_module,
131 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT; 132 .pName = "main",
132 subgroup_size_ci.pNext = nullptr; 133 .pSpecializationInfo = nullptr,
133 subgroup_size_ci.requiredSubgroupSize = GuestWarpSize; 134 },
135 .layout = *layout,
136 .basePipelineHandle = nullptr,
137 .basePipelineIndex = 0,
138 };
139
140 const VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT subgroup_size_ci{
141 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT,
142 .pNext = nullptr,
143 .requiredSubgroupSize = GuestWarpSize,
144 };
134 145
135 if (entries.uses_warps && device.IsGuestWarpSizeSupported(VK_SHADER_STAGE_COMPUTE_BIT)) { 146 if (entries.uses_warps && device.IsGuestWarpSizeSupported(VK_SHADER_STAGE_COMPUTE_BIT)) {
136 stage_ci.pNext = &subgroup_size_ci; 147 ci.stage.pNext = &subgroup_size_ci;
137 } 148 }
138 149
139 ci.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
140 ci.pNext = nullptr;
141 ci.flags = 0;
142 ci.layout = *layout;
143 ci.basePipelineHandle = nullptr;
144 ci.basePipelineIndex = 0;
145 return device.GetLogical().CreateComputePipeline(ci); 150 return device.GetLogical().CreateComputePipeline(ci);
146} 151}
147 152
diff --git a/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp b/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp
index 9259b618d..ac4a0884e 100644
--- a/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp
+++ b/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp
@@ -43,27 +43,30 @@ vk::DescriptorPool* VKDescriptorPool::AllocateNewPool() {
43 {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, num_sets * 64}, 43 {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, num_sets * 64},
44 {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, num_sets * 64}, 44 {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, num_sets * 64},
45 {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, num_sets * 64}, 45 {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, num_sets * 64},
46 {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, num_sets * 40}}; 46 {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, num_sets * 40},
47 47 };
48 VkDescriptorPoolCreateInfo ci; 48
49 ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; 49 const VkDescriptorPoolCreateInfo ci{
50 ci.pNext = nullptr; 50 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
51 ci.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; 51 .pNext = nullptr,
52 ci.maxSets = num_sets; 52 .flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
53 ci.poolSizeCount = static_cast<u32>(std::size(pool_sizes)); 53 .maxSets = num_sets,
54 ci.pPoolSizes = std::data(pool_sizes); 54 .poolSizeCount = static_cast<u32>(std::size(pool_sizes)),
55 .pPoolSizes = std::data(pool_sizes),
56 };
55 return &pools.emplace_back(device.GetLogical().CreateDescriptorPool(ci)); 57 return &pools.emplace_back(device.GetLogical().CreateDescriptorPool(ci));
56} 58}
57 59
58vk::DescriptorSets VKDescriptorPool::AllocateDescriptors(VkDescriptorSetLayout layout, 60vk::DescriptorSets VKDescriptorPool::AllocateDescriptors(VkDescriptorSetLayout layout,
59 std::size_t count) { 61 std::size_t count) {
60 const std::vector layout_copies(count, layout); 62 const std::vector layout_copies(count, layout);
61 VkDescriptorSetAllocateInfo ai; 63 VkDescriptorSetAllocateInfo ai{
62 ai.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; 64 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
63 ai.pNext = nullptr; 65 .pNext = nullptr,
64 ai.descriptorPool = **active_pool; 66 .descriptorPool = **active_pool,
65 ai.descriptorSetCount = static_cast<u32>(count); 67 .descriptorSetCount = static_cast<u32>(count),
66 ai.pSetLayouts = layout_copies.data(); 68 .pSetLayouts = layout_copies.data(),
69 };
67 70
68 vk::DescriptorSets sets = active_pool->Allocate(ai); 71 vk::DescriptorSets sets = active_pool->Allocate(ai);
69 if (!sets.IsOutOfPoolMemory()) { 72 if (!sets.IsOutOfPoolMemory()) {
diff --git a/src/video_core/renderer_vulkan/vk_device.cpp b/src/video_core/renderer_vulkan/vk_device.cpp
index fdaea4210..6245e0d78 100644
--- a/src/video_core/renderer_vulkan/vk_device.cpp
+++ b/src/video_core/renderer_vulkan/vk_device.cpp
@@ -22,14 +22,21 @@ namespace {
22 22
23namespace Alternatives { 23namespace Alternatives {
24 24
25constexpr std::array Depth24UnormS8_UINT = {VK_FORMAT_D32_SFLOAT_S8_UINT, 25constexpr std::array Depth24UnormS8_UINT{
26 VK_FORMAT_D16_UNORM_S8_UINT, VkFormat{}}; 26 VK_FORMAT_D32_SFLOAT_S8_UINT,
27constexpr std::array Depth16UnormS8_UINT = {VK_FORMAT_D24_UNORM_S8_UINT, 27 VK_FORMAT_D16_UNORM_S8_UINT,
28 VK_FORMAT_D32_SFLOAT_S8_UINT, VkFormat{}}; 28 VkFormat{},
29};
30
31constexpr std::array Depth16UnormS8_UINT{
32 VK_FORMAT_D24_UNORM_S8_UINT,
33 VK_FORMAT_D32_SFLOAT_S8_UINT,
34 VkFormat{},
35};
29 36
30} // namespace Alternatives 37} // namespace Alternatives
31 38
32constexpr std::array REQUIRED_EXTENSIONS = { 39constexpr std::array REQUIRED_EXTENSIONS{
33 VK_KHR_SWAPCHAIN_EXTENSION_NAME, 40 VK_KHR_SWAPCHAIN_EXTENSION_NAME,
34 VK_KHR_16BIT_STORAGE_EXTENSION_NAME, 41 VK_KHR_16BIT_STORAGE_EXTENSION_NAME,
35 VK_KHR_8BIT_STORAGE_EXTENSION_NAME, 42 VK_KHR_8BIT_STORAGE_EXTENSION_NAME,
@@ -77,14 +84,19 @@ std::unordered_map<VkFormat, VkFormatProperties> GetFormatProperties(
77 VK_FORMAT_A8B8G8R8_UNORM_PACK32, 84 VK_FORMAT_A8B8G8R8_UNORM_PACK32,
78 VK_FORMAT_A8B8G8R8_UINT_PACK32, 85 VK_FORMAT_A8B8G8R8_UINT_PACK32,
79 VK_FORMAT_A8B8G8R8_SNORM_PACK32, 86 VK_FORMAT_A8B8G8R8_SNORM_PACK32,
87 VK_FORMAT_A8B8G8R8_SINT_PACK32,
80 VK_FORMAT_A8B8G8R8_SRGB_PACK32, 88 VK_FORMAT_A8B8G8R8_SRGB_PACK32,
81 VK_FORMAT_B5G6R5_UNORM_PACK16, 89 VK_FORMAT_B5G6R5_UNORM_PACK16,
82 VK_FORMAT_A2B10G10R10_UNORM_PACK32, 90 VK_FORMAT_A2B10G10R10_UNORM_PACK32,
91 VK_FORMAT_A2B10G10R10_UINT_PACK32,
83 VK_FORMAT_A1R5G5B5_UNORM_PACK16, 92 VK_FORMAT_A1R5G5B5_UNORM_PACK16,
84 VK_FORMAT_R32G32B32A32_SFLOAT, 93 VK_FORMAT_R32G32B32A32_SFLOAT,
94 VK_FORMAT_R32G32B32A32_SINT,
85 VK_FORMAT_R32G32B32A32_UINT, 95 VK_FORMAT_R32G32B32A32_UINT,
86 VK_FORMAT_R32G32_SFLOAT, 96 VK_FORMAT_R32G32_SFLOAT,
97 VK_FORMAT_R32G32_SINT,
87 VK_FORMAT_R32G32_UINT, 98 VK_FORMAT_R32G32_UINT,
99 VK_FORMAT_R16G16B16A16_SINT,
88 VK_FORMAT_R16G16B16A16_UINT, 100 VK_FORMAT_R16G16B16A16_UINT,
89 VK_FORMAT_R16G16B16A16_SNORM, 101 VK_FORMAT_R16G16B16A16_SNORM,
90 VK_FORMAT_R16G16B16A16_UNORM, 102 VK_FORMAT_R16G16B16A16_UNORM,
@@ -96,8 +108,11 @@ std::unordered_map<VkFormat, VkFormatProperties> GetFormatProperties(
96 VK_FORMAT_R8G8B8A8_SRGB, 108 VK_FORMAT_R8G8B8A8_SRGB,
97 VK_FORMAT_R8G8_UNORM, 109 VK_FORMAT_R8G8_UNORM,
98 VK_FORMAT_R8G8_SNORM, 110 VK_FORMAT_R8G8_SNORM,
111 VK_FORMAT_R8G8_SINT,
99 VK_FORMAT_R8G8_UINT, 112 VK_FORMAT_R8G8_UINT,
100 VK_FORMAT_R8_UNORM, 113 VK_FORMAT_R8_UNORM,
114 VK_FORMAT_R8_SNORM,
115 VK_FORMAT_R8_SINT,
101 VK_FORMAT_R8_UINT, 116 VK_FORMAT_R8_UINT,
102 VK_FORMAT_B10G11R11_UFLOAT_PACK32, 117 VK_FORMAT_B10G11R11_UFLOAT_PACK32,
103 VK_FORMAT_R32_SFLOAT, 118 VK_FORMAT_R32_SFLOAT,
@@ -117,6 +132,7 @@ std::unordered_map<VkFormat, VkFormatProperties> GetFormatProperties(
117 VK_FORMAT_BC2_UNORM_BLOCK, 132 VK_FORMAT_BC2_UNORM_BLOCK,
118 VK_FORMAT_BC3_UNORM_BLOCK, 133 VK_FORMAT_BC3_UNORM_BLOCK,
119 VK_FORMAT_BC4_UNORM_BLOCK, 134 VK_FORMAT_BC4_UNORM_BLOCK,
135 VK_FORMAT_BC4_SNORM_BLOCK,
120 VK_FORMAT_BC5_UNORM_BLOCK, 136 VK_FORMAT_BC5_UNORM_BLOCK,
121 VK_FORMAT_BC5_SNORM_BLOCK, 137 VK_FORMAT_BC5_SNORM_BLOCK,
122 VK_FORMAT_BC7_UNORM_BLOCK, 138 VK_FORMAT_BC7_UNORM_BLOCK,
@@ -169,97 +185,104 @@ bool VKDevice::Create() {
169 const auto queue_cis = GetDeviceQueueCreateInfos(); 185 const auto queue_cis = GetDeviceQueueCreateInfos();
170 const std::vector extensions = LoadExtensions(); 186 const std::vector extensions = LoadExtensions();
171 187
172 VkPhysicalDeviceFeatures2 features2; 188 VkPhysicalDeviceFeatures2 features2{
173 features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; 189 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
174 features2.pNext = nullptr; 190 .pNext = nullptr,
191 };
175 const void* first_next = &features2; 192 const void* first_next = &features2;
176 void** next = &features2.pNext; 193 void** next = &features2.pNext;
177 194
178 auto& features = features2.features; 195 features2.features = {
179 features.robustBufferAccess = false; 196 .robustBufferAccess = false,
180 features.fullDrawIndexUint32 = false; 197 .fullDrawIndexUint32 = false,
181 features.imageCubeArray = false; 198 .imageCubeArray = false,
182 features.independentBlend = true; 199 .independentBlend = true,
183 features.geometryShader = true; 200 .geometryShader = true,
184 features.tessellationShader = true; 201 .tessellationShader = true,
185 features.sampleRateShading = false; 202 .sampleRateShading = false,
186 features.dualSrcBlend = false; 203 .dualSrcBlend = false,
187 features.logicOp = false; 204 .logicOp = false,
188 features.multiDrawIndirect = false; 205 .multiDrawIndirect = false,
189 features.drawIndirectFirstInstance = false; 206 .drawIndirectFirstInstance = false,
190 features.depthClamp = true; 207 .depthClamp = true,
191 features.depthBiasClamp = true; 208 .depthBiasClamp = true,
192 features.fillModeNonSolid = false; 209 .fillModeNonSolid = false,
193 features.depthBounds = false; 210 .depthBounds = false,
194 features.wideLines = false; 211 .wideLines = false,
195 features.largePoints = true; 212 .largePoints = true,
196 features.alphaToOne = false; 213 .alphaToOne = false,
197 features.multiViewport = true; 214 .multiViewport = true,
198 features.samplerAnisotropy = true; 215 .samplerAnisotropy = true,
199 features.textureCompressionETC2 = false; 216 .textureCompressionETC2 = false,
200 features.textureCompressionASTC_LDR = is_optimal_astc_supported; 217 .textureCompressionASTC_LDR = is_optimal_astc_supported,
201 features.textureCompressionBC = false; 218 .textureCompressionBC = false,
202 features.occlusionQueryPrecise = true; 219 .occlusionQueryPrecise = true,
203 features.pipelineStatisticsQuery = false; 220 .pipelineStatisticsQuery = false,
204 features.vertexPipelineStoresAndAtomics = true; 221 .vertexPipelineStoresAndAtomics = true,
205 features.fragmentStoresAndAtomics = true; 222 .fragmentStoresAndAtomics = true,
206 features.shaderTessellationAndGeometryPointSize = false; 223 .shaderTessellationAndGeometryPointSize = false,
207 features.shaderImageGatherExtended = true; 224 .shaderImageGatherExtended = true,
208 features.shaderStorageImageExtendedFormats = false; 225 .shaderStorageImageExtendedFormats = false,
209 features.shaderStorageImageMultisample = false; 226 .shaderStorageImageMultisample = false,
210 features.shaderStorageImageReadWithoutFormat = is_formatless_image_load_supported; 227 .shaderStorageImageReadWithoutFormat = is_formatless_image_load_supported,
211 features.shaderStorageImageWriteWithoutFormat = true; 228 .shaderStorageImageWriteWithoutFormat = true,
212 features.shaderUniformBufferArrayDynamicIndexing = false; 229 .shaderUniformBufferArrayDynamicIndexing = false,
213 features.shaderSampledImageArrayDynamicIndexing = false; 230 .shaderSampledImageArrayDynamicIndexing = false,
214 features.shaderStorageBufferArrayDynamicIndexing = false; 231 .shaderStorageBufferArrayDynamicIndexing = false,
215 features.shaderStorageImageArrayDynamicIndexing = false; 232 .shaderStorageImageArrayDynamicIndexing = false,
216 features.shaderClipDistance = false; 233 .shaderClipDistance = false,
217 features.shaderCullDistance = false; 234 .shaderCullDistance = false,
218 features.shaderFloat64 = false; 235 .shaderFloat64 = false,
219 features.shaderInt64 = false; 236 .shaderInt64 = false,
220 features.shaderInt16 = false; 237 .shaderInt16 = false,
221 features.shaderResourceResidency = false; 238 .shaderResourceResidency = false,
222 features.shaderResourceMinLod = false; 239 .shaderResourceMinLod = false,
223 features.sparseBinding = false; 240 .sparseBinding = false,
224 features.sparseResidencyBuffer = false; 241 .sparseResidencyBuffer = false,
225 features.sparseResidencyImage2D = false; 242 .sparseResidencyImage2D = false,
226 features.sparseResidencyImage3D = false; 243 .sparseResidencyImage3D = false,
227 features.sparseResidency2Samples = false; 244 .sparseResidency2Samples = false,
228 features.sparseResidency4Samples = false; 245 .sparseResidency4Samples = false,
229 features.sparseResidency8Samples = false; 246 .sparseResidency8Samples = false,
230 features.sparseResidency16Samples = false; 247 .sparseResidency16Samples = false,
231 features.sparseResidencyAliased = false; 248 .sparseResidencyAliased = false,
232 features.variableMultisampleRate = false; 249 .variableMultisampleRate = false,
233 features.inheritedQueries = false; 250 .inheritedQueries = false,
234 251 };
235 VkPhysicalDevice16BitStorageFeaturesKHR bit16_storage; 252
236 bit16_storage.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR; 253 VkPhysicalDevice16BitStorageFeaturesKHR bit16_storage{
237 bit16_storage.pNext = nullptr; 254 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR,
238 bit16_storage.storageBuffer16BitAccess = false; 255 .pNext = nullptr,
239 bit16_storage.uniformAndStorageBuffer16BitAccess = true; 256 .storageBuffer16BitAccess = false,
240 bit16_storage.storagePushConstant16 = false; 257 .uniformAndStorageBuffer16BitAccess = true,
241 bit16_storage.storageInputOutput16 = false; 258 .storagePushConstant16 = false,
259 .storageInputOutput16 = false,
260 };
242 SetNext(next, bit16_storage); 261 SetNext(next, bit16_storage);
243 262
244 VkPhysicalDevice8BitStorageFeaturesKHR bit8_storage; 263 VkPhysicalDevice8BitStorageFeaturesKHR bit8_storage{
245 bit8_storage.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES_KHR; 264 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES_KHR,
246 bit8_storage.pNext = nullptr; 265 .pNext = nullptr,
247 bit8_storage.storageBuffer8BitAccess = false; 266 .storageBuffer8BitAccess = false,
248 bit8_storage.uniformAndStorageBuffer8BitAccess = true; 267 .uniformAndStorageBuffer8BitAccess = true,
249 bit8_storage.storagePushConstant8 = false; 268 .storagePushConstant8 = false,
269 };
250 SetNext(next, bit8_storage); 270 SetNext(next, bit8_storage);
251 271
252 VkPhysicalDeviceHostQueryResetFeaturesEXT host_query_reset; 272 VkPhysicalDeviceHostQueryResetFeaturesEXT host_query_reset{
253 host_query_reset.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES_EXT; 273 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES_EXT,
254 host_query_reset.hostQueryReset = true; 274 .hostQueryReset = true,
275 };
255 SetNext(next, host_query_reset); 276 SetNext(next, host_query_reset);
256 277
257 VkPhysicalDeviceFloat16Int8FeaturesKHR float16_int8; 278 VkPhysicalDeviceFloat16Int8FeaturesKHR float16_int8;
258 if (is_float16_supported) { 279 if (is_float16_supported) {
259 float16_int8.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR; 280 float16_int8 = {
260 float16_int8.pNext = nullptr; 281 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR,
261 float16_int8.shaderFloat16 = true; 282 .pNext = nullptr,
262 float16_int8.shaderInt8 = false; 283 .shaderFloat16 = true,
284 .shaderInt8 = false,
285 };
263 SetNext(next, float16_int8); 286 SetNext(next, float16_int8);
264 } else { 287 } else {
265 LOG_INFO(Render_Vulkan, "Device doesn't support float16 natively"); 288 LOG_INFO(Render_Vulkan, "Device doesn't support float16 natively");
@@ -271,10 +294,11 @@ bool VKDevice::Create() {
271 294
272 VkPhysicalDeviceUniformBufferStandardLayoutFeaturesKHR std430_layout; 295 VkPhysicalDeviceUniformBufferStandardLayoutFeaturesKHR std430_layout;
273 if (khr_uniform_buffer_standard_layout) { 296 if (khr_uniform_buffer_standard_layout) {
274 std430_layout.sType = 297 std430_layout = {
275 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES_KHR; 298 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES_KHR,
276 std430_layout.pNext = nullptr; 299 .pNext = nullptr,
277 std430_layout.uniformBufferStandardLayout = true; 300 .uniformBufferStandardLayout = true,
301 };
278 SetNext(next, std430_layout); 302 SetNext(next, std430_layout);
279 } else { 303 } else {
280 LOG_INFO(Render_Vulkan, "Device doesn't support packed UBOs"); 304 LOG_INFO(Render_Vulkan, "Device doesn't support packed UBOs");
@@ -282,9 +306,11 @@ bool VKDevice::Create() {
282 306
283 VkPhysicalDeviceIndexTypeUint8FeaturesEXT index_type_uint8; 307 VkPhysicalDeviceIndexTypeUint8FeaturesEXT index_type_uint8;
284 if (ext_index_type_uint8) { 308 if (ext_index_type_uint8) {
285 index_type_uint8.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES_EXT; 309 index_type_uint8 = {
286 index_type_uint8.pNext = nullptr; 310 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES_EXT,
287 index_type_uint8.indexTypeUint8 = true; 311 .pNext = nullptr,
312 .indexTypeUint8 = true,
313 };
288 SetNext(next, index_type_uint8); 314 SetNext(next, index_type_uint8);
289 } else { 315 } else {
290 LOG_INFO(Render_Vulkan, "Device doesn't support uint8 indexes"); 316 LOG_INFO(Render_Vulkan, "Device doesn't support uint8 indexes");
@@ -292,11 +318,12 @@ bool VKDevice::Create() {
292 318
293 VkPhysicalDeviceTransformFeedbackFeaturesEXT transform_feedback; 319 VkPhysicalDeviceTransformFeedbackFeaturesEXT transform_feedback;
294 if (ext_transform_feedback) { 320 if (ext_transform_feedback) {
295 transform_feedback.sType = 321 transform_feedback = {
296 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT; 322 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT,
297 transform_feedback.pNext = nullptr; 323 .pNext = nullptr,
298 transform_feedback.transformFeedback = true; 324 .transformFeedback = true,
299 transform_feedback.geometryStreams = true; 325 .geometryStreams = true,
326 };
300 SetNext(next, transform_feedback); 327 SetNext(next, transform_feedback);
301 } else { 328 } else {
302 LOG_INFO(Render_Vulkan, "Device doesn't support transform feedbacks"); 329 LOG_INFO(Render_Vulkan, "Device doesn't support transform feedbacks");
@@ -304,10 +331,12 @@ bool VKDevice::Create() {
304 331
305 VkPhysicalDeviceCustomBorderColorFeaturesEXT custom_border; 332 VkPhysicalDeviceCustomBorderColorFeaturesEXT custom_border;
306 if (ext_custom_border_color) { 333 if (ext_custom_border_color) {
307 custom_border.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT; 334 custom_border = {
308 custom_border.pNext = nullptr; 335 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT,
309 custom_border.customBorderColors = VK_TRUE; 336 .pNext = nullptr,
310 custom_border.customBorderColorWithoutFormat = VK_TRUE; 337 .customBorderColors = VK_TRUE,
338 .customBorderColorWithoutFormat = VK_TRUE,
339 };
311 SetNext(next, custom_border); 340 SetNext(next, custom_border);
312 } else { 341 } else {
313 LOG_INFO(Render_Vulkan, "Device doesn't support custom border colors"); 342 LOG_INFO(Render_Vulkan, "Device doesn't support custom border colors");
@@ -315,9 +344,11 @@ bool VKDevice::Create() {
315 344
316 VkPhysicalDeviceExtendedDynamicStateFeaturesEXT dynamic_state; 345 VkPhysicalDeviceExtendedDynamicStateFeaturesEXT dynamic_state;
317 if (ext_extended_dynamic_state) { 346 if (ext_extended_dynamic_state) {
318 dynamic_state.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT; 347 dynamic_state = {
319 dynamic_state.pNext = nullptr; 348 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT,
320 dynamic_state.extendedDynamicState = VK_TRUE; 349 .pNext = nullptr,
350 .extendedDynamicState = VK_TRUE,
351 };
321 SetNext(next, dynamic_state); 352 SetNext(next, dynamic_state);
322 } else { 353 } else {
323 LOG_INFO(Render_Vulkan, "Device doesn't support extended dynamic state"); 354 LOG_INFO(Render_Vulkan, "Device doesn't support extended dynamic state");
@@ -331,11 +362,13 @@ bool VKDevice::Create() {
331 if (nv_device_diagnostics_config) { 362 if (nv_device_diagnostics_config) {
332 nsight_aftermath_tracker.Initialize(); 363 nsight_aftermath_tracker.Initialize();
333 364
334 diagnostics_nv.sType = VK_STRUCTURE_TYPE_DEVICE_DIAGNOSTICS_CONFIG_CREATE_INFO_NV; 365 diagnostics_nv = {
335 diagnostics_nv.pNext = &features2; 366 .sType = VK_STRUCTURE_TYPE_DEVICE_DIAGNOSTICS_CONFIG_CREATE_INFO_NV,
336 diagnostics_nv.flags = VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_SHADER_DEBUG_INFO_BIT_NV | 367 .pNext = &features2,
337 VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_RESOURCE_TRACKING_BIT_NV | 368 .flags = VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_SHADER_DEBUG_INFO_BIT_NV |
338 VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_AUTOMATIC_CHECKPOINTS_BIT_NV; 369 VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_RESOURCE_TRACKING_BIT_NV |
370 VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_AUTOMATIC_CHECKPOINTS_BIT_NV,
371 };
339 first_next = &diagnostics_nv; 372 first_next = &diagnostics_nv;
340 } 373 }
341 374
@@ -704,13 +737,15 @@ void VKDevice::SetupFeatures() {
704} 737}
705 738
706void VKDevice::CollectTelemetryParameters() { 739void VKDevice::CollectTelemetryParameters() {
707 VkPhysicalDeviceDriverPropertiesKHR driver; 740 VkPhysicalDeviceDriverPropertiesKHR driver{
708 driver.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR; 741 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR,
709 driver.pNext = nullptr; 742 .pNext = nullptr,
743 };
710 744
711 VkPhysicalDeviceProperties2KHR properties; 745 VkPhysicalDeviceProperties2KHR properties{
712 properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR; 746 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR,
713 properties.pNext = &driver; 747 .pNext = &driver,
748 };
714 physical.GetProperties2KHR(properties); 749 physical.GetProperties2KHR(properties);
715 750
716 driver_id = driver.driverID; 751 driver_id = driver.driverID;
@@ -719,22 +754,24 @@ void VKDevice::CollectTelemetryParameters() {
719 const std::vector extensions = physical.EnumerateDeviceExtensionProperties(); 754 const std::vector extensions = physical.EnumerateDeviceExtensionProperties();
720 reported_extensions.reserve(std::size(extensions)); 755 reported_extensions.reserve(std::size(extensions));
721 for (const auto& extension : extensions) { 756 for (const auto& extension : extensions) {
722 reported_extensions.push_back(extension.extensionName); 757 reported_extensions.emplace_back(extension.extensionName);
723 } 758 }
724} 759}
725 760
726std::vector<VkDeviceQueueCreateInfo> VKDevice::GetDeviceQueueCreateInfos() const { 761std::vector<VkDeviceQueueCreateInfo> VKDevice::GetDeviceQueueCreateInfos() const {
727 static constexpr float QUEUE_PRIORITY = 1.0f; 762 static constexpr float QUEUE_PRIORITY = 1.0f;
728 763
729 std::unordered_set<u32> unique_queue_families = {graphics_family, present_family}; 764 std::unordered_set<u32> unique_queue_families{graphics_family, present_family};
730 std::vector<VkDeviceQueueCreateInfo> queue_cis; 765 std::vector<VkDeviceQueueCreateInfo> queue_cis;
766 queue_cis.reserve(unique_queue_families.size());
731 767
732 for (const u32 queue_family : unique_queue_families) { 768 for (const u32 queue_family : unique_queue_families) {
733 VkDeviceQueueCreateInfo& ci = queue_cis.emplace_back(); 769 auto& ci = queue_cis.emplace_back(VkDeviceQueueCreateInfo{
734 ci.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; 770 .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
735 ci.pNext = nullptr; 771 .pNext = nullptr,
736 ci.flags = 0; 772 .flags = 0,
737 ci.queueFamilyIndex = queue_family; 773 .queueFamilyIndex = queue_family,
774 });
738 ci.queueCount = 1; 775 ci.queueCount = 1;
739 ci.pQueuePriorities = &QUEUE_PRIORITY; 776 ci.pQueuePriorities = &QUEUE_PRIORITY;
740 } 777 }
diff --git a/src/video_core/renderer_vulkan/vk_device.h b/src/video_core/renderer_vulkan/vk_device.h
index ae5c21baa..529744f2d 100644
--- a/src/video_core/renderer_vulkan/vk_device.h
+++ b/src/video_core/renderer_vulkan/vk_device.h
@@ -122,6 +122,11 @@ public:
122 return properties.limits.maxPushConstantsSize; 122 return properties.limits.maxPushConstantsSize;
123 } 123 }
124 124
125 /// Returns the maximum size for shared memory.
126 u32 GetMaxComputeSharedMemorySize() const {
127 return properties.limits.maxComputeSharedMemorySize;
128 }
129
125 /// Returns true if ASTC is natively supported. 130 /// Returns true if ASTC is natively supported.
126 bool IsOptimalAstcSupported() const { 131 bool IsOptimalAstcSupported() const {
127 return is_optimal_astc_supported; 132 return is_optimal_astc_supported;
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
index 844445105..aaf930b90 100644
--- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
+++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
@@ -28,15 +28,15 @@ namespace {
28 28
29template <class StencilFace> 29template <class StencilFace>
30VkStencilOpState GetStencilFaceState(const StencilFace& face) { 30VkStencilOpState GetStencilFaceState(const StencilFace& face) {
31 VkStencilOpState state; 31 return {
32 state.failOp = MaxwellToVK::StencilOp(face.ActionStencilFail()); 32 .failOp = MaxwellToVK::StencilOp(face.ActionStencilFail()),
33 state.passOp = MaxwellToVK::StencilOp(face.ActionDepthPass()); 33 .passOp = MaxwellToVK::StencilOp(face.ActionDepthPass()),
34 state.depthFailOp = MaxwellToVK::StencilOp(face.ActionDepthFail()); 34 .depthFailOp = MaxwellToVK::StencilOp(face.ActionDepthFail()),
35 state.compareOp = MaxwellToVK::ComparisonOp(face.TestFunc()); 35 .compareOp = MaxwellToVK::ComparisonOp(face.TestFunc()),
36 state.compareMask = 0; 36 .compareMask = 0,
37 state.writeMask = 0; 37 .writeMask = 0,
38 state.reference = 0; 38 .reference = 0,
39 return state; 39 };
40} 40}
41 41
42bool SupportsPrimitiveRestart(VkPrimitiveTopology topology) { 42bool SupportsPrimitiveRestart(VkPrimitiveTopology topology) {
@@ -52,20 +52,21 @@ bool SupportsPrimitiveRestart(VkPrimitiveTopology topology) {
52} 52}
53 53
54VkViewportSwizzleNV UnpackViewportSwizzle(u16 swizzle) { 54VkViewportSwizzleNV UnpackViewportSwizzle(u16 swizzle) {
55 union { 55 union Swizzle {
56 u32 raw; 56 u32 raw;
57 BitField<0, 3, Maxwell::ViewportSwizzle> x; 57 BitField<0, 3, Maxwell::ViewportSwizzle> x;
58 BitField<4, 3, Maxwell::ViewportSwizzle> y; 58 BitField<4, 3, Maxwell::ViewportSwizzle> y;
59 BitField<8, 3, Maxwell::ViewportSwizzle> z; 59 BitField<8, 3, Maxwell::ViewportSwizzle> z;
60 BitField<12, 3, Maxwell::ViewportSwizzle> w; 60 BitField<12, 3, Maxwell::ViewportSwizzle> w;
61 } const unpacked{swizzle}; 61 };
62 62 const Swizzle unpacked{swizzle};
63 VkViewportSwizzleNV result; 63
64 result.x = MaxwellToVK::ViewportSwizzle(unpacked.x); 64 return {
65 result.y = MaxwellToVK::ViewportSwizzle(unpacked.y); 65 .x = MaxwellToVK::ViewportSwizzle(unpacked.x),
66 result.z = MaxwellToVK::ViewportSwizzle(unpacked.z); 66 .y = MaxwellToVK::ViewportSwizzle(unpacked.y),
67 result.w = MaxwellToVK::ViewportSwizzle(unpacked.w); 67 .z = MaxwellToVK::ViewportSwizzle(unpacked.z),
68 return result; 68 .w = MaxwellToVK::ViewportSwizzle(unpacked.w),
69 };
69} 70}
70 71
71} // Anonymous namespace 72} // Anonymous namespace
@@ -100,24 +101,26 @@ VkDescriptorSet VKGraphicsPipeline::CommitDescriptorSet() {
100 101
101vk::DescriptorSetLayout VKGraphicsPipeline::CreateDescriptorSetLayout( 102vk::DescriptorSetLayout VKGraphicsPipeline::CreateDescriptorSetLayout(
102 vk::Span<VkDescriptorSetLayoutBinding> bindings) const { 103 vk::Span<VkDescriptorSetLayoutBinding> bindings) const {
103 VkDescriptorSetLayoutCreateInfo ci; 104 const VkDescriptorSetLayoutCreateInfo ci{
104 ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; 105 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
105 ci.pNext = nullptr; 106 .pNext = nullptr,
106 ci.flags = 0; 107 .flags = 0,
107 ci.bindingCount = bindings.size(); 108 .bindingCount = bindings.size(),
108 ci.pBindings = bindings.data(); 109 .pBindings = bindings.data(),
110 };
109 return device.GetLogical().CreateDescriptorSetLayout(ci); 111 return device.GetLogical().CreateDescriptorSetLayout(ci);
110} 112}
111 113
112vk::PipelineLayout VKGraphicsPipeline::CreatePipelineLayout() const { 114vk::PipelineLayout VKGraphicsPipeline::CreatePipelineLayout() const {
113 VkPipelineLayoutCreateInfo ci; 115 const VkPipelineLayoutCreateInfo ci{
114 ci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; 116 .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
115 ci.pNext = nullptr; 117 .pNext = nullptr,
116 ci.flags = 0; 118 .flags = 0,
117 ci.setLayoutCount = 1; 119 .setLayoutCount = 1,
118 ci.pSetLayouts = descriptor_set_layout.address(); 120 .pSetLayouts = descriptor_set_layout.address(),
119 ci.pushConstantRangeCount = 0; 121 .pushConstantRangeCount = 0,
120 ci.pPushConstantRanges = nullptr; 122 .pPushConstantRanges = nullptr,
123 };
121 return device.GetLogical().CreatePipelineLayout(ci); 124 return device.GetLogical().CreatePipelineLayout(ci);
122} 125}
123 126
@@ -136,26 +139,28 @@ vk::DescriptorUpdateTemplateKHR VKGraphicsPipeline::CreateDescriptorUpdateTempla
136 return {}; 139 return {};
137 } 140 }
138 141
139 VkDescriptorUpdateTemplateCreateInfoKHR ci; 142 const VkDescriptorUpdateTemplateCreateInfoKHR ci{
140 ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR; 143 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR,
141 ci.pNext = nullptr; 144 .pNext = nullptr,
142 ci.flags = 0; 145 .flags = 0,
143 ci.descriptorUpdateEntryCount = static_cast<u32>(template_entries.size()); 146 .descriptorUpdateEntryCount = static_cast<u32>(template_entries.size()),
144 ci.pDescriptorUpdateEntries = template_entries.data(); 147 .pDescriptorUpdateEntries = template_entries.data(),
145 ci.templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR; 148 .templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR,
146 ci.descriptorSetLayout = *descriptor_set_layout; 149 .descriptorSetLayout = *descriptor_set_layout,
147 ci.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; 150 .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
148 ci.pipelineLayout = *layout; 151 .pipelineLayout = *layout,
149 ci.set = DESCRIPTOR_SET; 152 .set = DESCRIPTOR_SET,
153 };
150 return device.GetLogical().CreateDescriptorUpdateTemplateKHR(ci); 154 return device.GetLogical().CreateDescriptorUpdateTemplateKHR(ci);
151} 155}
152 156
153std::vector<vk::ShaderModule> VKGraphicsPipeline::CreateShaderModules( 157std::vector<vk::ShaderModule> VKGraphicsPipeline::CreateShaderModules(
154 const SPIRVProgram& program) const { 158 const SPIRVProgram& program) const {
155 VkShaderModuleCreateInfo ci; 159 VkShaderModuleCreateInfo ci{
156 ci.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; 160 .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
157 ci.pNext = nullptr; 161 .pNext = nullptr,
158 ci.flags = 0; 162 .flags = 0,
163 };
159 164
160 std::vector<vk::ShaderModule> modules; 165 std::vector<vk::ShaderModule> modules;
161 modules.reserve(Maxwell::MaxShaderStage); 166 modules.reserve(Maxwell::MaxShaderStage);
@@ -204,15 +209,17 @@ vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpa
204 const bool instanced = state.binding_divisors[index] != 0; 209 const bool instanced = state.binding_divisors[index] != 0;
205 const auto rate = instanced ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX; 210 const auto rate = instanced ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX;
206 211
207 auto& vertex_binding = vertex_bindings.emplace_back(); 212 vertex_bindings.push_back({
208 vertex_binding.binding = static_cast<u32>(index); 213 .binding = static_cast<u32>(index),
209 vertex_binding.stride = binding.stride; 214 .stride = binding.stride,
210 vertex_binding.inputRate = rate; 215 .inputRate = rate,
216 });
211 217
212 if (instanced) { 218 if (instanced) {
213 auto& binding_divisor = vertex_binding_divisors.emplace_back(); 219 vertex_binding_divisors.push_back({
214 binding_divisor.binding = static_cast<u32>(index); 220 .binding = static_cast<u32>(index),
215 binding_divisor.divisor = state.binding_divisors[index]; 221 .divisor = state.binding_divisors[index],
222 });
216 } 223 }
217 } 224 }
218 225
@@ -227,116 +234,132 @@ vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpa
227 // Skip attributes not used by the vertex shaders. 234 // Skip attributes not used by the vertex shaders.
228 continue; 235 continue;
229 } 236 }
230 auto& vertex_attribute = vertex_attributes.emplace_back(); 237 vertex_attributes.push_back({
231 vertex_attribute.location = static_cast<u32>(index); 238 .location = static_cast<u32>(index),
232 vertex_attribute.binding = attribute.buffer; 239 .binding = attribute.buffer,
233 vertex_attribute.format = MaxwellToVK::VertexFormat(attribute.Type(), attribute.Size()); 240 .format = MaxwellToVK::VertexFormat(attribute.Type(), attribute.Size()),
234 vertex_attribute.offset = attribute.offset; 241 .offset = attribute.offset,
242 });
235 } 243 }
236 244
237 VkPipelineVertexInputStateCreateInfo vertex_input_ci; 245 VkPipelineVertexInputStateCreateInfo vertex_input_ci{
238 vertex_input_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; 246 .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
239 vertex_input_ci.pNext = nullptr; 247 .pNext = nullptr,
240 vertex_input_ci.flags = 0; 248 .flags = 0,
241 vertex_input_ci.vertexBindingDescriptionCount = static_cast<u32>(vertex_bindings.size()); 249 .vertexBindingDescriptionCount = static_cast<u32>(vertex_bindings.size()),
242 vertex_input_ci.pVertexBindingDescriptions = vertex_bindings.data(); 250 .pVertexBindingDescriptions = vertex_bindings.data(),
243 vertex_input_ci.vertexAttributeDescriptionCount = static_cast<u32>(vertex_attributes.size()); 251 .vertexAttributeDescriptionCount = static_cast<u32>(vertex_attributes.size()),
244 vertex_input_ci.pVertexAttributeDescriptions = vertex_attributes.data(); 252 .pVertexAttributeDescriptions = vertex_attributes.data(),
245 253 };
246 VkPipelineVertexInputDivisorStateCreateInfoEXT input_divisor_ci; 254
247 input_divisor_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT; 255 const VkPipelineVertexInputDivisorStateCreateInfoEXT input_divisor_ci{
248 input_divisor_ci.pNext = nullptr; 256 .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT,
249 input_divisor_ci.vertexBindingDivisorCount = static_cast<u32>(vertex_binding_divisors.size()); 257 .pNext = nullptr,
250 input_divisor_ci.pVertexBindingDivisors = vertex_binding_divisors.data(); 258 .vertexBindingDivisorCount = static_cast<u32>(vertex_binding_divisors.size()),
259 .pVertexBindingDivisors = vertex_binding_divisors.data(),
260 };
251 if (!vertex_binding_divisors.empty()) { 261 if (!vertex_binding_divisors.empty()) {
252 vertex_input_ci.pNext = &input_divisor_ci; 262 vertex_input_ci.pNext = &input_divisor_ci;
253 } 263 }
254 264
255 VkPipelineInputAssemblyStateCreateInfo input_assembly_ci; 265 const auto input_assembly_topology = MaxwellToVK::PrimitiveTopology(device, dynamic.Topology());
256 input_assembly_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; 266 const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci{
257 input_assembly_ci.pNext = nullptr; 267 .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
258 input_assembly_ci.flags = 0; 268 .pNext = nullptr,
259 input_assembly_ci.topology = MaxwellToVK::PrimitiveTopology(device, dynamic.Topology()); 269 .flags = 0,
260 input_assembly_ci.primitiveRestartEnable = 270 .topology = MaxwellToVK::PrimitiveTopology(device, dynamic.Topology()),
261 state.primitive_restart_enable != 0 && SupportsPrimitiveRestart(input_assembly_ci.topology); 271 .primitiveRestartEnable = state.primitive_restart_enable != 0 &&
262 272 SupportsPrimitiveRestart(input_assembly_topology),
263 VkPipelineTessellationStateCreateInfo tessellation_ci; 273 };
264 tessellation_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO; 274
265 tessellation_ci.pNext = nullptr; 275 const VkPipelineTessellationStateCreateInfo tessellation_ci{
266 tessellation_ci.flags = 0; 276 .sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,
267 tessellation_ci.patchControlPoints = state.patch_control_points_minus_one.Value() + 1; 277 .pNext = nullptr,
268 278 .flags = 0,
269 VkPipelineViewportStateCreateInfo viewport_ci; 279 .patchControlPoints = state.patch_control_points_minus_one.Value() + 1,
270 viewport_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; 280 };
271 viewport_ci.pNext = nullptr; 281
272 viewport_ci.flags = 0; 282 VkPipelineViewportStateCreateInfo viewport_ci{
273 viewport_ci.viewportCount = Maxwell::NumViewports; 283 .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
274 viewport_ci.pViewports = nullptr; 284 .pNext = nullptr,
275 viewport_ci.scissorCount = Maxwell::NumViewports; 285 .flags = 0,
276 viewport_ci.pScissors = nullptr; 286 .viewportCount = Maxwell::NumViewports,
287 .pViewports = nullptr,
288 .scissorCount = Maxwell::NumViewports,
289 .pScissors = nullptr,
290 };
277 291
278 std::array<VkViewportSwizzleNV, Maxwell::NumViewports> swizzles; 292 std::array<VkViewportSwizzleNV, Maxwell::NumViewports> swizzles;
279 std::transform(viewport_swizzles.begin(), viewport_swizzles.end(), swizzles.begin(), 293 std::transform(viewport_swizzles.begin(), viewport_swizzles.end(), swizzles.begin(),
280 UnpackViewportSwizzle); 294 UnpackViewportSwizzle);
281 VkPipelineViewportSwizzleStateCreateInfoNV swizzle_ci; 295 VkPipelineViewportSwizzleStateCreateInfoNV swizzle_ci{
282 swizzle_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SWIZZLE_STATE_CREATE_INFO_NV; 296 .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SWIZZLE_STATE_CREATE_INFO_NV,
283 swizzle_ci.pNext = nullptr; 297 .pNext = nullptr,
284 swizzle_ci.flags = 0; 298 .flags = 0,
285 swizzle_ci.viewportCount = Maxwell::NumViewports; 299 .viewportCount = Maxwell::NumViewports,
286 swizzle_ci.pViewportSwizzles = swizzles.data(); 300 .pViewportSwizzles = swizzles.data(),
301 };
287 if (device.IsNvViewportSwizzleSupported()) { 302 if (device.IsNvViewportSwizzleSupported()) {
288 viewport_ci.pNext = &swizzle_ci; 303 viewport_ci.pNext = &swizzle_ci;
289 } 304 }
290 305
291 VkPipelineRasterizationStateCreateInfo rasterization_ci; 306 const VkPipelineRasterizationStateCreateInfo rasterization_ci{
292 rasterization_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; 307 .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
293 rasterization_ci.pNext = nullptr; 308 .pNext = nullptr,
294 rasterization_ci.flags = 0; 309 .flags = 0,
295 rasterization_ci.depthClampEnable = state.depth_clamp_disabled == 0 ? VK_TRUE : VK_FALSE; 310 .depthClampEnable =
296 rasterization_ci.rasterizerDiscardEnable = state.rasterize_enable == 0 ? VK_TRUE : VK_FALSE; 311 static_cast<VkBool32>(state.depth_clamp_disabled == 0 ? VK_TRUE : VK_FALSE),
297 rasterization_ci.polygonMode = VK_POLYGON_MODE_FILL; 312 .rasterizerDiscardEnable =
298 rasterization_ci.cullMode = 313 static_cast<VkBool32>(state.rasterize_enable == 0 ? VK_TRUE : VK_FALSE),
299 dynamic.cull_enable ? MaxwellToVK::CullFace(dynamic.CullFace()) : VK_CULL_MODE_NONE; 314 .polygonMode = VK_POLYGON_MODE_FILL,
300 rasterization_ci.frontFace = MaxwellToVK::FrontFace(dynamic.FrontFace()); 315 .cullMode =
301 rasterization_ci.depthBiasEnable = state.depth_bias_enable; 316 dynamic.cull_enable ? MaxwellToVK::CullFace(dynamic.CullFace()) : VK_CULL_MODE_NONE,
302 rasterization_ci.depthBiasConstantFactor = 0.0f; 317 .frontFace = MaxwellToVK::FrontFace(dynamic.FrontFace()),
303 rasterization_ci.depthBiasClamp = 0.0f; 318 .depthBiasEnable = state.depth_bias_enable,
304 rasterization_ci.depthBiasSlopeFactor = 0.0f; 319 .depthBiasConstantFactor = 0.0f,
305 rasterization_ci.lineWidth = 1.0f; 320 .depthBiasClamp = 0.0f,
306 321 .depthBiasSlopeFactor = 0.0f,
307 VkPipelineMultisampleStateCreateInfo multisample_ci; 322 .lineWidth = 1.0f,
308 multisample_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; 323 };
309 multisample_ci.pNext = nullptr; 324
310 multisample_ci.flags = 0; 325 const VkPipelineMultisampleStateCreateInfo multisample_ci{
311 multisample_ci.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; 326 .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
312 multisample_ci.sampleShadingEnable = VK_FALSE; 327 .pNext = nullptr,
313 multisample_ci.minSampleShading = 0.0f; 328 .flags = 0,
314 multisample_ci.pSampleMask = nullptr; 329 .rasterizationSamples = VK_SAMPLE_COUNT_1_BIT,
315 multisample_ci.alphaToCoverageEnable = VK_FALSE; 330 .sampleShadingEnable = VK_FALSE,
316 multisample_ci.alphaToOneEnable = VK_FALSE; 331 .minSampleShading = 0.0f,
317 332 .pSampleMask = nullptr,
318 VkPipelineDepthStencilStateCreateInfo depth_stencil_ci; 333 .alphaToCoverageEnable = VK_FALSE,
319 depth_stencil_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; 334 .alphaToOneEnable = VK_FALSE,
320 depth_stencil_ci.pNext = nullptr; 335 };
321 depth_stencil_ci.flags = 0; 336
322 depth_stencil_ci.depthTestEnable = dynamic.depth_test_enable; 337 const VkPipelineDepthStencilStateCreateInfo depth_stencil_ci{
323 depth_stencil_ci.depthWriteEnable = dynamic.depth_write_enable; 338 .sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
324 depth_stencil_ci.depthCompareOp = dynamic.depth_test_enable 339 .pNext = nullptr,
325 ? MaxwellToVK::ComparisonOp(dynamic.DepthTestFunc()) 340 .flags = 0,
326 : VK_COMPARE_OP_ALWAYS; 341 .depthTestEnable = dynamic.depth_test_enable,
327 depth_stencil_ci.depthBoundsTestEnable = dynamic.depth_bounds_enable; 342 .depthWriteEnable = dynamic.depth_write_enable,
328 depth_stencil_ci.stencilTestEnable = dynamic.stencil_enable; 343 .depthCompareOp = dynamic.depth_test_enable
329 depth_stencil_ci.front = GetStencilFaceState(dynamic.front); 344 ? MaxwellToVK::ComparisonOp(dynamic.DepthTestFunc())
330 depth_stencil_ci.back = GetStencilFaceState(dynamic.back); 345 : VK_COMPARE_OP_ALWAYS,
331 depth_stencil_ci.minDepthBounds = 0.0f; 346 .depthBoundsTestEnable = dynamic.depth_bounds_enable,
332 depth_stencil_ci.maxDepthBounds = 0.0f; 347 .stencilTestEnable = dynamic.stencil_enable,
348 .front = GetStencilFaceState(dynamic.front),
349 .back = GetStencilFaceState(dynamic.back),
350 .minDepthBounds = 0.0f,
351 .maxDepthBounds = 0.0f,
352 };
333 353
334 std::array<VkPipelineColorBlendAttachmentState, Maxwell::NumRenderTargets> cb_attachments; 354 std::array<VkPipelineColorBlendAttachmentState, Maxwell::NumRenderTargets> cb_attachments;
335 const auto num_attachments = static_cast<std::size_t>(renderpass_params.num_color_attachments); 355 const auto num_attachments = static_cast<std::size_t>(renderpass_params.num_color_attachments);
336 for (std::size_t index = 0; index < num_attachments; ++index) { 356 for (std::size_t index = 0; index < num_attachments; ++index) {
337 static constexpr std::array COMPONENT_TABLE = { 357 static constexpr std::array COMPONENT_TABLE{
338 VK_COLOR_COMPONENT_R_BIT, VK_COLOR_COMPONENT_G_BIT, VK_COLOR_COMPONENT_B_BIT, 358 VK_COLOR_COMPONENT_R_BIT,
339 VK_COLOR_COMPONENT_A_BIT}; 359 VK_COLOR_COMPONENT_G_BIT,
360 VK_COLOR_COMPONENT_B_BIT,
361 VK_COLOR_COMPONENT_A_BIT,
362 };
340 const auto& blend = state.attachments[index]; 363 const auto& blend = state.attachments[index];
341 364
342 VkColorComponentFlags color_components = 0; 365 VkColorComponentFlags color_components = 0;
@@ -346,35 +369,36 @@ vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpa
346 } 369 }
347 } 370 }
348 371
349 VkPipelineColorBlendAttachmentState& attachment = cb_attachments[index]; 372 cb_attachments[index] = {
350 attachment.blendEnable = blend.enable != 0; 373 .blendEnable = blend.enable != 0,
351 attachment.srcColorBlendFactor = MaxwellToVK::BlendFactor(blend.SourceRGBFactor()); 374 .srcColorBlendFactor = MaxwellToVK::BlendFactor(blend.SourceRGBFactor()),
352 attachment.dstColorBlendFactor = MaxwellToVK::BlendFactor(blend.DestRGBFactor()); 375 .dstColorBlendFactor = MaxwellToVK::BlendFactor(blend.DestRGBFactor()),
353 attachment.colorBlendOp = MaxwellToVK::BlendEquation(blend.EquationRGB()); 376 .colorBlendOp = MaxwellToVK::BlendEquation(blend.EquationRGB()),
354 attachment.srcAlphaBlendFactor = MaxwellToVK::BlendFactor(blend.SourceAlphaFactor()); 377 .srcAlphaBlendFactor = MaxwellToVK::BlendFactor(blend.SourceAlphaFactor()),
355 attachment.dstAlphaBlendFactor = MaxwellToVK::BlendFactor(blend.DestAlphaFactor()); 378 .dstAlphaBlendFactor = MaxwellToVK::BlendFactor(blend.DestAlphaFactor()),
356 attachment.alphaBlendOp = MaxwellToVK::BlendEquation(blend.EquationAlpha()); 379 .alphaBlendOp = MaxwellToVK::BlendEquation(blend.EquationAlpha()),
357 attachment.colorWriteMask = color_components; 380 .colorWriteMask = color_components,
381 };
358 } 382 }
359 383
360 VkPipelineColorBlendStateCreateInfo color_blend_ci; 384 const VkPipelineColorBlendStateCreateInfo color_blend_ci{
361 color_blend_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; 385 .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
362 color_blend_ci.pNext = nullptr; 386 .pNext = nullptr,
363 color_blend_ci.flags = 0; 387 .flags = 0,
364 color_blend_ci.logicOpEnable = VK_FALSE; 388 .logicOpEnable = VK_FALSE,
365 color_blend_ci.logicOp = VK_LOGIC_OP_COPY; 389 .logicOp = VK_LOGIC_OP_COPY,
366 color_blend_ci.attachmentCount = static_cast<u32>(num_attachments); 390 .attachmentCount = static_cast<u32>(num_attachments),
367 color_blend_ci.pAttachments = cb_attachments.data(); 391 .pAttachments = cb_attachments.data(),
368 std::memset(color_blend_ci.blendConstants, 0, sizeof(color_blend_ci.blendConstants)); 392 };
369 393
370 std::vector dynamic_states = { 394 std::vector dynamic_states{
371 VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR, 395 VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR,
372 VK_DYNAMIC_STATE_DEPTH_BIAS, VK_DYNAMIC_STATE_BLEND_CONSTANTS, 396 VK_DYNAMIC_STATE_DEPTH_BIAS, VK_DYNAMIC_STATE_BLEND_CONSTANTS,
373 VK_DYNAMIC_STATE_DEPTH_BOUNDS, VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK, 397 VK_DYNAMIC_STATE_DEPTH_BOUNDS, VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK,
374 VK_DYNAMIC_STATE_STENCIL_WRITE_MASK, VK_DYNAMIC_STATE_STENCIL_REFERENCE, 398 VK_DYNAMIC_STATE_STENCIL_WRITE_MASK, VK_DYNAMIC_STATE_STENCIL_REFERENCE,
375 }; 399 };
376 if (device.IsExtExtendedDynamicStateSupported()) { 400 if (device.IsExtExtendedDynamicStateSupported()) {
377 static constexpr std::array extended = { 401 static constexpr std::array extended{
378 VK_DYNAMIC_STATE_CULL_MODE_EXT, 402 VK_DYNAMIC_STATE_CULL_MODE_EXT,
379 VK_DYNAMIC_STATE_FRONT_FACE_EXT, 403 VK_DYNAMIC_STATE_FRONT_FACE_EXT,
380 VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT, 404 VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT,
@@ -389,18 +413,19 @@ vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpa
389 dynamic_states.insert(dynamic_states.end(), extended.begin(), extended.end()); 413 dynamic_states.insert(dynamic_states.end(), extended.begin(), extended.end());
390 } 414 }
391 415
392 VkPipelineDynamicStateCreateInfo dynamic_state_ci; 416 const VkPipelineDynamicStateCreateInfo dynamic_state_ci{
393 dynamic_state_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; 417 .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
394 dynamic_state_ci.pNext = nullptr; 418 .pNext = nullptr,
395 dynamic_state_ci.flags = 0; 419 .flags = 0,
396 dynamic_state_ci.dynamicStateCount = static_cast<u32>(dynamic_states.size()); 420 .dynamicStateCount = static_cast<u32>(dynamic_states.size()),
397 dynamic_state_ci.pDynamicStates = dynamic_states.data(); 421 .pDynamicStates = dynamic_states.data(),
422 };
398 423
399 VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT subgroup_size_ci; 424 const VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT subgroup_size_ci{
400 subgroup_size_ci.sType = 425 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT,
401 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT; 426 .pNext = nullptr,
402 subgroup_size_ci.pNext = nullptr; 427 .requiredSubgroupSize = GuestWarpSize,
403 subgroup_size_ci.requiredSubgroupSize = GuestWarpSize; 428 };
404 429
405 std::vector<VkPipelineShaderStageCreateInfo> shader_stages; 430 std::vector<VkPipelineShaderStageCreateInfo> shader_stages;
406 std::size_t module_index = 0; 431 std::size_t module_index = 0;
@@ -408,6 +433,7 @@ vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpa
408 if (!program[stage]) { 433 if (!program[stage]) {
409 continue; 434 continue;
410 } 435 }
436
411 VkPipelineShaderStageCreateInfo& stage_ci = shader_stages.emplace_back(); 437 VkPipelineShaderStageCreateInfo& stage_ci = shader_stages.emplace_back();
412 stage_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; 438 stage_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
413 stage_ci.pNext = nullptr; 439 stage_ci.pNext = nullptr;
@@ -422,26 +448,27 @@ vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpa
422 } 448 }
423 } 449 }
424 450
425 VkGraphicsPipelineCreateInfo ci; 451 const VkGraphicsPipelineCreateInfo ci{
426 ci.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; 452 .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
427 ci.pNext = nullptr; 453 .pNext = nullptr,
428 ci.flags = 0; 454 .flags = 0,
429 ci.stageCount = static_cast<u32>(shader_stages.size()); 455 .stageCount = static_cast<u32>(shader_stages.size()),
430 ci.pStages = shader_stages.data(); 456 .pStages = shader_stages.data(),
431 ci.pVertexInputState = &vertex_input_ci; 457 .pVertexInputState = &vertex_input_ci,
432 ci.pInputAssemblyState = &input_assembly_ci; 458 .pInputAssemblyState = &input_assembly_ci,
433 ci.pTessellationState = &tessellation_ci; 459 .pTessellationState = &tessellation_ci,
434 ci.pViewportState = &viewport_ci; 460 .pViewportState = &viewport_ci,
435 ci.pRasterizationState = &rasterization_ci; 461 .pRasterizationState = &rasterization_ci,
436 ci.pMultisampleState = &multisample_ci; 462 .pMultisampleState = &multisample_ci,
437 ci.pDepthStencilState = &depth_stencil_ci; 463 .pDepthStencilState = &depth_stencil_ci,
438 ci.pColorBlendState = &color_blend_ci; 464 .pColorBlendState = &color_blend_ci,
439 ci.pDynamicState = &dynamic_state_ci; 465 .pDynamicState = &dynamic_state_ci,
440 ci.layout = *layout; 466 .layout = *layout,
441 ci.renderPass = renderpass; 467 .renderPass = renderpass,
442 ci.subpass = 0; 468 .subpass = 0,
443 ci.basePipelineHandle = nullptr; 469 .basePipelineHandle = nullptr,
444 ci.basePipelineIndex = 0; 470 .basePipelineIndex = 0,
471 };
445 return device.GetLogical().CreateGraphicsPipeline(ci); 472 return device.GetLogical().CreateGraphicsPipeline(ci);
446} 473}
447 474
diff --git a/src/video_core/renderer_vulkan/vk_image.cpp b/src/video_core/renderer_vulkan/vk_image.cpp
index 9bceb3861..1c418ea17 100644
--- a/src/video_core/renderer_vulkan/vk_image.cpp
+++ b/src/video_core/renderer_vulkan/vk_image.cpp
@@ -102,21 +102,29 @@ bool VKImage::HasChanged(u32 base_layer, u32 num_layers, u32 base_level, u32 num
102 102
103void VKImage::CreatePresentView() { 103void VKImage::CreatePresentView() {
104 // Image type has to be 2D to be presented. 104 // Image type has to be 2D to be presented.
105 VkImageViewCreateInfo image_view_ci; 105 present_view = device.GetLogical().CreateImageView({
106 image_view_ci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; 106 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
107 image_view_ci.pNext = nullptr; 107 .pNext = nullptr,
108 image_view_ci.flags = 0; 108 .flags = 0,
109 image_view_ci.image = *image; 109 .image = *image,
110 image_view_ci.viewType = VK_IMAGE_VIEW_TYPE_2D; 110 .viewType = VK_IMAGE_VIEW_TYPE_2D,
111 image_view_ci.format = format; 111 .format = format,
112 image_view_ci.components = {VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, 112 .components =
113 VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY}; 113 {
114 image_view_ci.subresourceRange.aspectMask = aspect_mask; 114 .r = VK_COMPONENT_SWIZZLE_IDENTITY,
115 image_view_ci.subresourceRange.baseMipLevel = 0; 115 .g = VK_COMPONENT_SWIZZLE_IDENTITY,
116 image_view_ci.subresourceRange.levelCount = 1; 116 .b = VK_COMPONENT_SWIZZLE_IDENTITY,
117 image_view_ci.subresourceRange.baseArrayLayer = 0; 117 .a = VK_COMPONENT_SWIZZLE_IDENTITY,
118 image_view_ci.subresourceRange.layerCount = 1; 118 },
119 present_view = device.GetLogical().CreateImageView(image_view_ci); 119 .subresourceRange =
120 {
121 .aspectMask = aspect_mask,
122 .baseMipLevel = 0,
123 .levelCount = 1,
124 .baseArrayLayer = 0,
125 .layerCount = 1,
126 },
127 });
120} 128}
121 129
122VKImage::SubrangeState& VKImage::GetSubrangeState(u32 layer, u32 level) noexcept { 130VKImage::SubrangeState& VKImage::GetSubrangeState(u32 layer, u32 level) noexcept {
diff --git a/src/video_core/renderer_vulkan/vk_memory_manager.cpp b/src/video_core/renderer_vulkan/vk_memory_manager.cpp
index b4c650a63..24c8960ac 100644
--- a/src/video_core/renderer_vulkan/vk_memory_manager.cpp
+++ b/src/video_core/renderer_vulkan/vk_memory_manager.cpp
@@ -178,13 +178,12 @@ bool VKMemoryManager::AllocMemory(VkMemoryPropertyFlags wanted_properties, u32 t
178 }(); 178 }();
179 179
180 // Try to allocate found type. 180 // Try to allocate found type.
181 VkMemoryAllocateInfo memory_ai; 181 vk::DeviceMemory memory = device.GetLogical().TryAllocateMemory({
182 memory_ai.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; 182 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
183 memory_ai.pNext = nullptr; 183 .pNext = nullptr,
184 memory_ai.allocationSize = size; 184 .allocationSize = size,
185 memory_ai.memoryTypeIndex = type; 185 .memoryTypeIndex = type,
186 186 });
187 vk::DeviceMemory memory = device.GetLogical().TryAllocateMemory(memory_ai);
188 if (!memory) { 187 if (!memory) {
189 LOG_CRITICAL(Render_Vulkan, "Device allocation failed!"); 188 LOG_CRITICAL(Render_Vulkan, "Device allocation failed!");
190 return false; 189 return false;
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
index 3da835324..42b3a744c 100644
--- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
@@ -88,12 +88,13 @@ void AddBindings(std::vector<VkDescriptorSetLayoutBinding>& bindings, u32& bindi
88 // Combined image samplers can be arrayed. 88 // Combined image samplers can be arrayed.
89 count = container[i].size; 89 count = container[i].size;
90 } 90 }
91 VkDescriptorSetLayoutBinding& entry = bindings.emplace_back(); 91 bindings.push_back({
92 entry.binding = binding++; 92 .binding = binding++,
93 entry.descriptorType = descriptor_type; 93 .descriptorType = descriptor_type,
94 entry.descriptorCount = count; 94 .descriptorCount = count,
95 entry.stageFlags = stage_flags; 95 .stageFlags = stage_flags,
96 entry.pImmutableSamplers = nullptr; 96 .pImmutableSamplers = nullptr,
97 });
97 } 98 }
98} 99}
99 100
@@ -259,10 +260,10 @@ VKComputePipeline& VKPipelineCache::GetComputePipeline(const ComputePipelineCach
259 } 260 }
260 } 261 }
261 262
262 Specialization specialization; 263 const Specialization specialization{
263 specialization.workgroup_size = key.workgroup_size; 264 .workgroup_size = key.workgroup_size,
264 specialization.shared_memory_size = key.shared_memory_size; 265 .shared_memory_size = key.shared_memory_size,
265 266 };
266 const SPIRVShader spirv_shader{Decompile(device, shader->GetIR(), ShaderType::Compute, 267 const SPIRVShader spirv_shader{Decompile(device, shader->GetIR(), ShaderType::Compute,
267 shader->GetRegistry(), specialization), 268 shader->GetRegistry(), specialization),
268 shader->GetEntries()}; 269 shader->GetEntries()};
@@ -370,13 +371,14 @@ void AddEntry(std::vector<VkDescriptorUpdateTemplateEntry>& template_entries, u3
370 if constexpr (descriptor_type == COMBINED_IMAGE_SAMPLER) { 371 if constexpr (descriptor_type == COMBINED_IMAGE_SAMPLER) {
371 for (u32 i = 0; i < count; ++i) { 372 for (u32 i = 0; i < count; ++i) {
372 const u32 num_samplers = container[i].size; 373 const u32 num_samplers = container[i].size;
373 VkDescriptorUpdateTemplateEntry& entry = template_entries.emplace_back(); 374 template_entries.push_back({
374 entry.dstBinding = binding; 375 .dstBinding = binding,
375 entry.dstArrayElement = 0; 376 .dstArrayElement = 0,
376 entry.descriptorCount = num_samplers; 377 .descriptorCount = num_samplers,
377 entry.descriptorType = descriptor_type; 378 .descriptorType = descriptor_type,
378 entry.offset = offset; 379 .offset = offset,
379 entry.stride = entry_size; 380 .stride = entry_size,
381 });
380 382
381 ++binding; 383 ++binding;
382 offset += num_samplers * entry_size; 384 offset += num_samplers * entry_size;
@@ -389,22 +391,24 @@ void AddEntry(std::vector<VkDescriptorUpdateTemplateEntry>& template_entries, u3
389 // Nvidia has a bug where updating multiple texels at once causes the driver to crash. 391 // Nvidia has a bug where updating multiple texels at once causes the driver to crash.
390 // Note: Fixed in driver Windows 443.24, Linux 440.66.15 392 // Note: Fixed in driver Windows 443.24, Linux 440.66.15
391 for (u32 i = 0; i < count; ++i) { 393 for (u32 i = 0; i < count; ++i) {
392 VkDescriptorUpdateTemplateEntry& entry = template_entries.emplace_back(); 394 template_entries.push_back({
393 entry.dstBinding = binding + i; 395 .dstBinding = binding + i,
394 entry.dstArrayElement = 0; 396 .dstArrayElement = 0,
395 entry.descriptorCount = 1; 397 .descriptorCount = 1,
396 entry.descriptorType = descriptor_type; 398 .descriptorType = descriptor_type,
397 entry.offset = static_cast<std::size_t>(offset + i * entry_size); 399 .offset = static_cast<std::size_t>(offset + i * entry_size),
398 entry.stride = entry_size; 400 .stride = entry_size,
401 });
399 } 402 }
400 } else if (count > 0) { 403 } else if (count > 0) {
401 VkDescriptorUpdateTemplateEntry& entry = template_entries.emplace_back(); 404 template_entries.push_back({
402 entry.dstBinding = binding; 405 .dstBinding = binding,
403 entry.dstArrayElement = 0; 406 .dstArrayElement = 0,
404 entry.descriptorCount = count; 407 .descriptorCount = count,
405 entry.descriptorType = descriptor_type; 408 .descriptorType = descriptor_type,
406 entry.offset = offset; 409 .offset = offset,
407 entry.stride = entry_size; 410 .stride = entry_size,
411 });
408 } 412 }
409 offset += count * entry_size; 413 offset += count * entry_size;
410 binding += count; 414 binding += count;
diff --git a/src/video_core/renderer_vulkan/vk_query_cache.cpp b/src/video_core/renderer_vulkan/vk_query_cache.cpp
index bc91c48cc..6cd63d090 100644
--- a/src/video_core/renderer_vulkan/vk_query_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_query_cache.cpp
@@ -47,14 +47,14 @@ std::pair<VkQueryPool, u32> QueryPool::Commit(VKFence& fence) {
47void QueryPool::Allocate(std::size_t begin, std::size_t end) { 47void QueryPool::Allocate(std::size_t begin, std::size_t end) {
48 usage.resize(end); 48 usage.resize(end);
49 49
50 VkQueryPoolCreateInfo query_pool_ci; 50 pools.push_back(device->GetLogical().CreateQueryPool({
51 query_pool_ci.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO; 51 .sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,
52 query_pool_ci.pNext = nullptr; 52 .pNext = nullptr,
53 query_pool_ci.flags = 0; 53 .flags = 0,
54 query_pool_ci.queryType = GetTarget(type); 54 .queryType = GetTarget(type),
55 query_pool_ci.queryCount = static_cast<u32>(end - begin); 55 .queryCount = static_cast<u32>(end - begin),
56 query_pool_ci.pipelineStatistics = 0; 56 .pipelineStatistics = 0,
57 pools.push_back(device->GetLogical().CreateQueryPool(query_pool_ci)); 57 }));
58} 58}
59 59
60void QueryPool::Reserve(std::pair<VkQueryPool, u32> query) { 60void QueryPool::Reserve(std::pair<VkQueryPool, u32> query) {
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index 7625871c2..2ed2004f0 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -64,20 +64,22 @@ VkViewport GetViewportState(const VKDevice& device, const Maxwell& regs, std::si
64 const auto& src = regs.viewport_transform[index]; 64 const auto& src = regs.viewport_transform[index];
65 const float width = src.scale_x * 2.0f; 65 const float width = src.scale_x * 2.0f;
66 const float height = src.scale_y * 2.0f; 66 const float height = src.scale_y * 2.0f;
67 const float reduce_z = regs.depth_mode == Maxwell::DepthMode::MinusOneToOne ? 1.0f : 0.0f;
67 68
68 VkViewport viewport; 69 VkViewport viewport{
69 viewport.x = src.translate_x - src.scale_x; 70 .x = src.translate_x - src.scale_x,
70 viewport.y = src.translate_y - src.scale_y; 71 .y = src.translate_y - src.scale_y,
71 viewport.width = width != 0.0f ? width : 1.0f; 72 .width = width != 0.0f ? width : 1.0f,
72 viewport.height = height != 0.0f ? height : 1.0f; 73 .height = height != 0.0f ? height : 1.0f,
74 .minDepth = src.translate_z - src.scale_z * reduce_z,
75 .maxDepth = src.translate_z + src.scale_z,
76 };
73 77
74 const float reduce_z = regs.depth_mode == Maxwell::DepthMode::MinusOneToOne ? 1.0f : 0.0f;
75 viewport.minDepth = src.translate_z - src.scale_z * reduce_z;
76 viewport.maxDepth = src.translate_z + src.scale_z;
77 if (!device.IsExtDepthRangeUnrestrictedSupported()) { 78 if (!device.IsExtDepthRangeUnrestrictedSupported()) {
78 viewport.minDepth = std::clamp(viewport.minDepth, 0.0f, 1.0f); 79 viewport.minDepth = std::clamp(viewport.minDepth, 0.0f, 1.0f);
79 viewport.maxDepth = std::clamp(viewport.maxDepth, 0.0f, 1.0f); 80 viewport.maxDepth = std::clamp(viewport.maxDepth, 0.0f, 1.0f);
80 } 81 }
82
81 return viewport; 83 return viewport;
82} 84}
83 85
@@ -508,10 +510,11 @@ void RasterizerVulkan::Clear() {
508 510
509 const u32 color_attachment = regs.clear_buffers.RT; 511 const u32 color_attachment = regs.clear_buffers.RT;
510 scheduler.Record([color_attachment, clear_value, clear_rect](vk::CommandBuffer cmdbuf) { 512 scheduler.Record([color_attachment, clear_value, clear_rect](vk::CommandBuffer cmdbuf) {
511 VkClearAttachment attachment; 513 const VkClearAttachment attachment{
512 attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 514 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
513 attachment.colorAttachment = color_attachment; 515 .colorAttachment = color_attachment,
514 attachment.clearValue = clear_value; 516 .clearValue = clear_value,
517 };
515 cmdbuf.ClearAttachments(attachment, clear_rect); 518 cmdbuf.ClearAttachments(attachment, clear_rect);
516 }); 519 });
517 } 520 }
@@ -529,10 +532,6 @@ void RasterizerVulkan::Clear() {
529 532
530 scheduler.Record([clear_depth = regs.clear_depth, clear_stencil = regs.clear_stencil, 533 scheduler.Record([clear_depth = regs.clear_depth, clear_stencil = regs.clear_stencil,
531 clear_rect, aspect_flags](vk::CommandBuffer cmdbuf) { 534 clear_rect, aspect_flags](vk::CommandBuffer cmdbuf) {
532 VkClearValue clear_value;
533 clear_value.depthStencil.depth = clear_depth;
534 clear_value.depthStencil.stencil = clear_stencil;
535
536 VkClearAttachment attachment; 535 VkClearAttachment attachment;
537 attachment.aspectMask = aspect_flags; 536 attachment.aspectMask = aspect_flags;
538 attachment.colorAttachment = 0; 537 attachment.colorAttachment = 0;
@@ -551,13 +550,16 @@ void RasterizerVulkan::DispatchCompute(GPUVAddr code_addr) {
551 query_cache.UpdateCounters(); 550 query_cache.UpdateCounters();
552 551
553 const auto& launch_desc = system.GPU().KeplerCompute().launch_description; 552 const auto& launch_desc = system.GPU().KeplerCompute().launch_description;
554 ComputePipelineCacheKey key; 553 auto& pipeline = pipeline_cache.GetComputePipeline({
555 key.shader = code_addr; 554 .shader = code_addr,
556 key.shared_memory_size = launch_desc.shared_alloc; 555 .shared_memory_size = launch_desc.shared_alloc,
557 key.workgroup_size = {launch_desc.block_dim_x, launch_desc.block_dim_y, 556 .workgroup_size =
558 launch_desc.block_dim_z}; 557 {
559 558 launch_desc.block_dim_x,
560 auto& pipeline = pipeline_cache.GetComputePipeline(key); 559 launch_desc.block_dim_y,
560 launch_desc.block_dim_z,
561 },
562 });
561 563
562 // Compute dispatches can't be executed inside a renderpass 564 // Compute dispatches can't be executed inside a renderpass
563 scheduler.RequestOutsideRenderPassOperationContext(); 565 scheduler.RequestOutsideRenderPassOperationContext();
@@ -841,17 +843,17 @@ std::tuple<VkFramebuffer, VkExtent2D> RasterizerVulkan::ConfigureFramebuffers(
841 const auto [fbentry, is_cache_miss] = framebuffer_cache.try_emplace(key); 843 const auto [fbentry, is_cache_miss] = framebuffer_cache.try_emplace(key);
842 auto& framebuffer = fbentry->second; 844 auto& framebuffer = fbentry->second;
843 if (is_cache_miss) { 845 if (is_cache_miss) {
844 VkFramebufferCreateInfo framebuffer_ci; 846 framebuffer = device.GetLogical().CreateFramebuffer({
845 framebuffer_ci.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; 847 .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
846 framebuffer_ci.pNext = nullptr; 848 .pNext = nullptr,
847 framebuffer_ci.flags = 0; 849 .flags = 0,
848 framebuffer_ci.renderPass = key.renderpass; 850 .renderPass = key.renderpass,
849 framebuffer_ci.attachmentCount = static_cast<u32>(key.views.size()); 851 .attachmentCount = static_cast<u32>(key.views.size()),
850 framebuffer_ci.pAttachments = key.views.data(); 852 .pAttachments = key.views.data(),
851 framebuffer_ci.width = key.width; 853 .width = key.width,
852 framebuffer_ci.height = key.height; 854 .height = key.height,
853 framebuffer_ci.layers = key.layers; 855 .layers = key.layers,
854 framebuffer = device.GetLogical().CreateFramebuffer(framebuffer_ci); 856 });
855 } 857 }
856 858
857 return {*framebuffer, VkExtent2D{key.width, key.height}}; 859 return {*framebuffer, VkExtent2D{key.width, key.height}};
@@ -1553,17 +1555,17 @@ VkBuffer RasterizerVulkan::DefaultBuffer() {
1553 return *default_buffer; 1555 return *default_buffer;
1554 } 1556 }
1555 1557
1556 VkBufferCreateInfo ci; 1558 default_buffer = device.GetLogical().CreateBuffer({
1557 ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; 1559 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
1558 ci.pNext = nullptr; 1560 .pNext = nullptr,
1559 ci.flags = 0; 1561 .flags = 0,
1560 ci.size = DEFAULT_BUFFER_SIZE; 1562 .size = DEFAULT_BUFFER_SIZE,
1561 ci.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | 1563 .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT |
1562 VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; 1564 VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
1563 ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; 1565 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
1564 ci.queueFamilyIndexCount = 0; 1566 .queueFamilyIndexCount = 0,
1565 ci.pQueueFamilyIndices = nullptr; 1567 .pQueueFamilyIndices = nullptr,
1566 default_buffer = device.GetLogical().CreateBuffer(ci); 1568 });
1567 default_buffer_commit = memory_manager.Commit(default_buffer, false); 1569 default_buffer_commit = memory_manager.Commit(default_buffer, false);
1568 1570
1569 scheduler.RequestOutsideRenderPassOperationContext(); 1571 scheduler.RequestOutsideRenderPassOperationContext();
diff --git a/src/video_core/renderer_vulkan/vk_renderpass_cache.cpp b/src/video_core/renderer_vulkan/vk_renderpass_cache.cpp
index 3f71d005e..80284cf92 100644
--- a/src/video_core/renderer_vulkan/vk_renderpass_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_renderpass_cache.cpp
@@ -39,10 +39,14 @@ VkRenderPass VKRenderPassCache::GetRenderPass(const RenderPassParams& params) {
39 39
40vk::RenderPass VKRenderPassCache::CreateRenderPass(const RenderPassParams& params) const { 40vk::RenderPass VKRenderPassCache::CreateRenderPass(const RenderPassParams& params) const {
41 using namespace VideoCore::Surface; 41 using namespace VideoCore::Surface;
42 const std::size_t num_attachments = static_cast<std::size_t>(params.num_color_attachments);
43
42 std::vector<VkAttachmentDescription> descriptors; 44 std::vector<VkAttachmentDescription> descriptors;
45 descriptors.reserve(num_attachments);
46
43 std::vector<VkAttachmentReference> color_references; 47 std::vector<VkAttachmentReference> color_references;
48 color_references.reserve(num_attachments);
44 49
45 const std::size_t num_attachments = static_cast<std::size_t>(params.num_color_attachments);
46 for (std::size_t rt = 0; rt < num_attachments; ++rt) { 50 for (std::size_t rt = 0; rt < num_attachments; ++rt) {
47 const auto guest_format = static_cast<Tegra::RenderTargetFormat>(params.color_formats[rt]); 51 const auto guest_format = static_cast<Tegra::RenderTargetFormat>(params.color_formats[rt]);
48 const PixelFormat pixel_format = PixelFormatFromRenderTargetFormat(guest_format); 52 const PixelFormat pixel_format = PixelFormatFromRenderTargetFormat(guest_format);
@@ -54,20 +58,22 @@ vk::RenderPass VKRenderPassCache::CreateRenderPass(const RenderPassParams& param
54 const VkImageLayout color_layout = ((params.texceptions >> rt) & 1) != 0 58 const VkImageLayout color_layout = ((params.texceptions >> rt) & 1) != 0
55 ? VK_IMAGE_LAYOUT_GENERAL 59 ? VK_IMAGE_LAYOUT_GENERAL
56 : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 60 : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
57 VkAttachmentDescription& descriptor = descriptors.emplace_back(); 61 descriptors.push_back({
58 descriptor.flags = VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT; 62 .flags = VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT,
59 descriptor.format = format.format; 63 .format = format.format,
60 descriptor.samples = VK_SAMPLE_COUNT_1_BIT; 64 .samples = VK_SAMPLE_COUNT_1_BIT,
61 descriptor.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; 65 .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
62 descriptor.storeOp = VK_ATTACHMENT_STORE_OP_STORE; 66 .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
63 descriptor.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; 67 .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
64 descriptor.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; 68 .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
65 descriptor.initialLayout = color_layout; 69 .initialLayout = color_layout,
66 descriptor.finalLayout = color_layout; 70 .finalLayout = color_layout,
67 71 });
68 VkAttachmentReference& reference = color_references.emplace_back(); 72
69 reference.attachment = static_cast<u32>(rt); 73 color_references.push_back({
70 reference.layout = color_layout; 74 .attachment = static_cast<u32>(rt),
75 .layout = color_layout,
76 });
71 } 77 }
72 78
73 VkAttachmentReference zeta_attachment_ref; 79 VkAttachmentReference zeta_attachment_ref;
@@ -82,32 +88,36 @@ vk::RenderPass VKRenderPassCache::CreateRenderPass(const RenderPassParams& param
82 const VkImageLayout zeta_layout = params.zeta_texception != 0 88 const VkImageLayout zeta_layout = params.zeta_texception != 0
83 ? VK_IMAGE_LAYOUT_GENERAL 89 ? VK_IMAGE_LAYOUT_GENERAL
84 : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; 90 : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
85 VkAttachmentDescription& descriptor = descriptors.emplace_back(); 91 descriptors.push_back({
86 descriptor.flags = 0; 92 .flags = 0,
87 descriptor.format = format.format; 93 .format = format.format,
88 descriptor.samples = VK_SAMPLE_COUNT_1_BIT; 94 .samples = VK_SAMPLE_COUNT_1_BIT,
89 descriptor.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; 95 .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
90 descriptor.storeOp = VK_ATTACHMENT_STORE_OP_STORE; 96 .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
91 descriptor.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD; 97 .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
92 descriptor.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; 98 .stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE,
93 descriptor.initialLayout = zeta_layout; 99 .initialLayout = zeta_layout,
94 descriptor.finalLayout = zeta_layout; 100 .finalLayout = zeta_layout,
95 101 });
96 zeta_attachment_ref.attachment = static_cast<u32>(num_attachments); 102
97 zeta_attachment_ref.layout = zeta_layout; 103 zeta_attachment_ref = {
104 .attachment = static_cast<u32>(num_attachments),
105 .layout = zeta_layout,
106 };
98 } 107 }
99 108
100 VkSubpassDescription subpass_description; 109 const VkSubpassDescription subpass_description{
101 subpass_description.flags = 0; 110 .flags = 0,
102 subpass_description.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; 111 .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
103 subpass_description.inputAttachmentCount = 0; 112 .inputAttachmentCount = 0,
104 subpass_description.pInputAttachments = nullptr; 113 .pInputAttachments = nullptr,
105 subpass_description.colorAttachmentCount = static_cast<u32>(color_references.size()); 114 .colorAttachmentCount = static_cast<u32>(color_references.size()),
106 subpass_description.pColorAttachments = color_references.data(); 115 .pColorAttachments = color_references.data(),
107 subpass_description.pResolveAttachments = nullptr; 116 .pResolveAttachments = nullptr,
108 subpass_description.pDepthStencilAttachment = has_zeta ? &zeta_attachment_ref : nullptr; 117 .pDepthStencilAttachment = has_zeta ? &zeta_attachment_ref : nullptr,
109 subpass_description.preserveAttachmentCount = 0; 118 .preserveAttachmentCount = 0,
110 subpass_description.pPreserveAttachments = nullptr; 119 .pPreserveAttachments = nullptr,
120 };
111 121
112 VkAccessFlags access = 0; 122 VkAccessFlags access = 0;
113 VkPipelineStageFlags stage = 0; 123 VkPipelineStageFlags stage = 0;
@@ -122,26 +132,27 @@ vk::RenderPass VKRenderPassCache::CreateRenderPass(const RenderPassParams& param
122 stage |= VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; 132 stage |= VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
123 } 133 }
124 134
125 VkSubpassDependency subpass_dependency; 135 const VkSubpassDependency subpass_dependency{
126 subpass_dependency.srcSubpass = VK_SUBPASS_EXTERNAL; 136 .srcSubpass = VK_SUBPASS_EXTERNAL,
127 subpass_dependency.dstSubpass = 0; 137 .dstSubpass = 0,
128 subpass_dependency.srcStageMask = stage; 138 .srcStageMask = stage,
129 subpass_dependency.dstStageMask = stage; 139 .dstStageMask = stage,
130 subpass_dependency.srcAccessMask = 0; 140 .srcAccessMask = 0,
131 subpass_dependency.dstAccessMask = access; 141 .dstAccessMask = access,
132 subpass_dependency.dependencyFlags = 0; 142 .dependencyFlags = 0,
133 143 };
134 VkRenderPassCreateInfo ci; 144
135 ci.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; 145 return device.GetLogical().CreateRenderPass({
136 ci.pNext = nullptr; 146 .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
137 ci.flags = 0; 147 .pNext = nullptr,
138 ci.attachmentCount = static_cast<u32>(descriptors.size()); 148 .flags = 0,
139 ci.pAttachments = descriptors.data(); 149 .attachmentCount = static_cast<u32>(descriptors.size()),
140 ci.subpassCount = 1; 150 .pAttachments = descriptors.data(),
141 ci.pSubpasses = &subpass_description; 151 .subpassCount = 1,
142 ci.dependencyCount = 1; 152 .pSubpasses = &subpass_description,
143 ci.pDependencies = &subpass_dependency; 153 .dependencyCount = 1,
144 return device.GetLogical().CreateRenderPass(ci); 154 .pDependencies = &subpass_dependency,
155 });
145} 156}
146 157
147} // namespace Vulkan 158} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_resource_manager.cpp b/src/video_core/renderer_vulkan/vk_resource_manager.cpp
index dc06f545a..f19330a36 100644
--- a/src/video_core/renderer_vulkan/vk_resource_manager.cpp
+++ b/src/video_core/renderer_vulkan/vk_resource_manager.cpp
@@ -18,33 +18,32 @@ namespace {
18constexpr std::size_t COMMAND_BUFFER_POOL_SIZE = 0x1000; 18constexpr std::size_t COMMAND_BUFFER_POOL_SIZE = 0x1000;
19constexpr std::size_t FENCES_GROW_STEP = 0x40; 19constexpr std::size_t FENCES_GROW_STEP = 0x40;
20 20
21VkFenceCreateInfo BuildFenceCreateInfo() { 21constexpr VkFenceCreateInfo BuildFenceCreateInfo() {
22 VkFenceCreateInfo fence_ci; 22 return {
23 fence_ci.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; 23 .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
24 fence_ci.pNext = nullptr; 24 .pNext = nullptr,
25 fence_ci.flags = 0; 25 .flags = 0,
26 return fence_ci; 26 };
27} 27}
28 28
29} // Anonymous namespace 29} // Anonymous namespace
30 30
31class CommandBufferPool final : public VKFencedPool { 31class CommandBufferPool final : public VKFencedPool {
32public: 32public:
33 CommandBufferPool(const VKDevice& device) 33 explicit CommandBufferPool(const VKDevice& device)
34 : VKFencedPool(COMMAND_BUFFER_POOL_SIZE), device{device} {} 34 : VKFencedPool(COMMAND_BUFFER_POOL_SIZE), device{device} {}
35 35
36 void Allocate(std::size_t begin, std::size_t end) override { 36 void Allocate(std::size_t begin, std::size_t end) override {
37 // Command buffers are going to be commited, recorded, executed every single usage cycle. 37 // Command buffers are going to be commited, recorded, executed every single usage cycle.
38 // They are also going to be reseted when commited. 38 // They are also going to be reseted when commited.
39 VkCommandPoolCreateInfo command_pool_ci;
40 command_pool_ci.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
41 command_pool_ci.pNext = nullptr;
42 command_pool_ci.flags =
43 VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
44 command_pool_ci.queueFamilyIndex = device.GetGraphicsFamily();
45
46 Pool& pool = pools.emplace_back(); 39 Pool& pool = pools.emplace_back();
47 pool.handle = device.GetLogical().CreateCommandPool(command_pool_ci); 40 pool.handle = device.GetLogical().CreateCommandPool({
41 .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
42 .pNext = nullptr,
43 .flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT |
44 VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
45 .queueFamilyIndex = device.GetGraphicsFamily(),
46 });
48 pool.cmdbufs = pool.handle.Allocate(COMMAND_BUFFER_POOL_SIZE); 47 pool.cmdbufs = pool.handle.Allocate(COMMAND_BUFFER_POOL_SIZE);
49 } 48 }
50 49
diff --git a/src/video_core/renderer_vulkan/vk_sampler_cache.cpp b/src/video_core/renderer_vulkan/vk_sampler_cache.cpp
index 616eacc36..2d5460776 100644
--- a/src/video_core/renderer_vulkan/vk_sampler_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_sampler_cache.cpp
@@ -44,32 +44,35 @@ vk::Sampler VKSamplerCache::CreateSampler(const Tegra::Texture::TSCEntry& tsc) c
44 const bool arbitrary_borders = device.IsExtCustomBorderColorSupported(); 44 const bool arbitrary_borders = device.IsExtCustomBorderColorSupported();
45 const std::array color = tsc.GetBorderColor(); 45 const std::array color = tsc.GetBorderColor();
46 46
47 VkSamplerCustomBorderColorCreateInfoEXT border; 47 VkSamplerCustomBorderColorCreateInfoEXT border{
48 border.sType = VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT; 48 .sType = VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT,
49 border.pNext = nullptr; 49 .pNext = nullptr,
50 border.format = VK_FORMAT_UNDEFINED; 50 .format = VK_FORMAT_UNDEFINED,
51 };
51 std::memcpy(&border.customBorderColor, color.data(), sizeof(color)); 52 std::memcpy(&border.customBorderColor, color.data(), sizeof(color));
52 53
53 VkSamplerCreateInfo ci; 54 return device.GetLogical().CreateSampler({
54 ci.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; 55 .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
55 ci.pNext = arbitrary_borders ? &border : nullptr; 56 .pNext = arbitrary_borders ? &border : nullptr,
56 ci.flags = 0; 57 .flags = 0,
57 ci.magFilter = MaxwellToVK::Sampler::Filter(tsc.mag_filter); 58 .magFilter = MaxwellToVK::Sampler::Filter(tsc.mag_filter),
58 ci.minFilter = MaxwellToVK::Sampler::Filter(tsc.min_filter); 59 .minFilter = MaxwellToVK::Sampler::Filter(tsc.min_filter),
59 ci.mipmapMode = MaxwellToVK::Sampler::MipmapMode(tsc.mipmap_filter); 60 .mipmapMode = MaxwellToVK::Sampler::MipmapMode(tsc.mipmap_filter),
60 ci.addressModeU = MaxwellToVK::Sampler::WrapMode(device, tsc.wrap_u, tsc.mag_filter); 61 .addressModeU = MaxwellToVK::Sampler::WrapMode(device, tsc.wrap_u, tsc.mag_filter),
61 ci.addressModeV = MaxwellToVK::Sampler::WrapMode(device, tsc.wrap_v, tsc.mag_filter); 62 .addressModeV = MaxwellToVK::Sampler::WrapMode(device, tsc.wrap_v, tsc.mag_filter),
62 ci.addressModeW = MaxwellToVK::Sampler::WrapMode(device, tsc.wrap_p, tsc.mag_filter); 63 .addressModeW = MaxwellToVK::Sampler::WrapMode(device, tsc.wrap_p, tsc.mag_filter),
63 ci.mipLodBias = tsc.GetLodBias(); 64 .mipLodBias = tsc.GetLodBias(),
64 ci.anisotropyEnable = tsc.GetMaxAnisotropy() > 1.0f ? VK_TRUE : VK_FALSE; 65 .anisotropyEnable =
65 ci.maxAnisotropy = tsc.GetMaxAnisotropy(); 66 static_cast<VkBool32>(tsc.GetMaxAnisotropy() > 1.0f ? VK_TRUE : VK_FALSE),
66 ci.compareEnable = tsc.depth_compare_enabled; 67 .maxAnisotropy = tsc.GetMaxAnisotropy(),
67 ci.compareOp = MaxwellToVK::Sampler::DepthCompareFunction(tsc.depth_compare_func); 68 .compareEnable = tsc.depth_compare_enabled,
68 ci.minLod = tsc.mipmap_filter == TextureMipmapFilter::None ? 0.0f : tsc.GetMinLod(); 69 .compareOp = MaxwellToVK::Sampler::DepthCompareFunction(tsc.depth_compare_func),
69 ci.maxLod = tsc.mipmap_filter == TextureMipmapFilter::None ? 0.25f : tsc.GetMaxLod(); 70 .minLod = tsc.mipmap_filter == TextureMipmapFilter::None ? 0.0f : tsc.GetMinLod(),
70 ci.borderColor = arbitrary_borders ? VK_BORDER_COLOR_INT_CUSTOM_EXT : ConvertBorderColor(color); 71 .maxLod = tsc.mipmap_filter == TextureMipmapFilter::None ? 0.25f : tsc.GetMaxLod(),
71 ci.unnormalizedCoordinates = VK_FALSE; 72 .borderColor =
72 return device.GetLogical().CreateSampler(ci); 73 arbitrary_borders ? VK_BORDER_COLOR_INT_CUSTOM_EXT : ConvertBorderColor(color),
74 .unnormalizedCoordinates = VK_FALSE,
75 });
73} 76}
74 77
75VkSampler VKSamplerCache::ToSamplerType(const vk::Sampler& sampler) const { 78VkSampler VKSamplerCache::ToSamplerType(const vk::Sampler& sampler) const {
diff --git a/src/video_core/renderer_vulkan/vk_scheduler.cpp b/src/video_core/renderer_vulkan/vk_scheduler.cpp
index 56524e6f3..dbbd0961a 100644
--- a/src/video_core/renderer_vulkan/vk_scheduler.cpp
+++ b/src/video_core/renderer_vulkan/vk_scheduler.cpp
@@ -100,16 +100,19 @@ void VKScheduler::RequestRenderpass(VkRenderPass renderpass, VkFramebuffer frame
100 state.framebuffer = framebuffer; 100 state.framebuffer = framebuffer;
101 state.render_area = render_area; 101 state.render_area = render_area;
102 102
103 VkRenderPassBeginInfo renderpass_bi; 103 const VkRenderPassBeginInfo renderpass_bi{
104 renderpass_bi.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; 104 .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
105 renderpass_bi.pNext = nullptr; 105 .pNext = nullptr,
106 renderpass_bi.renderPass = renderpass; 106 .renderPass = renderpass,
107 renderpass_bi.framebuffer = framebuffer; 107 .framebuffer = framebuffer,
108 renderpass_bi.renderArea.offset.x = 0; 108 .renderArea =
109 renderpass_bi.renderArea.offset.y = 0; 109 {
110 renderpass_bi.renderArea.extent = render_area; 110 .offset = {.x = 0, .y = 0},
111 renderpass_bi.clearValueCount = 0; 111 .extent = render_area,
112 renderpass_bi.pClearValues = nullptr; 112 },
113 .clearValueCount = 0,
114 .pClearValues = nullptr,
115 };
113 116
114 Record([renderpass_bi, end_renderpass](vk::CommandBuffer cmdbuf) { 117 Record([renderpass_bi, end_renderpass](vk::CommandBuffer cmdbuf) {
115 if (end_renderpass) { 118 if (end_renderpass) {
@@ -157,16 +160,17 @@ void VKScheduler::SubmitExecution(VkSemaphore semaphore) {
157 160
158 current_cmdbuf.End(); 161 current_cmdbuf.End();
159 162
160 VkSubmitInfo submit_info; 163 const VkSubmitInfo submit_info{
161 submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; 164 .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
162 submit_info.pNext = nullptr; 165 .pNext = nullptr,
163 submit_info.waitSemaphoreCount = 0; 166 .waitSemaphoreCount = 0,
164 submit_info.pWaitSemaphores = nullptr; 167 .pWaitSemaphores = nullptr,
165 submit_info.pWaitDstStageMask = nullptr; 168 .pWaitDstStageMask = nullptr,
166 submit_info.commandBufferCount = 1; 169 .commandBufferCount = 1,
167 submit_info.pCommandBuffers = current_cmdbuf.address(); 170 .pCommandBuffers = current_cmdbuf.address(),
168 submit_info.signalSemaphoreCount = semaphore ? 1 : 0; 171 .signalSemaphoreCount = semaphore ? 1U : 0U,
169 submit_info.pSignalSemaphores = &semaphore; 172 .pSignalSemaphores = &semaphore,
173 };
170 switch (const VkResult result = device.GetGraphicsQueue().Submit(submit_info, *current_fence)) { 174 switch (const VkResult result = device.GetGraphicsQueue().Submit(submit_info, *current_fence)) {
171 case VK_SUCCESS: 175 case VK_SUCCESS:
172 break; 176 break;
@@ -181,19 +185,18 @@ void VKScheduler::SubmitExecution(VkSemaphore semaphore) {
181void VKScheduler::AllocateNewContext() { 185void VKScheduler::AllocateNewContext() {
182 ++ticks; 186 ++ticks;
183 187
184 VkCommandBufferBeginInfo cmdbuf_bi;
185 cmdbuf_bi.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
186 cmdbuf_bi.pNext = nullptr;
187 cmdbuf_bi.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
188 cmdbuf_bi.pInheritanceInfo = nullptr;
189
190 std::unique_lock lock{mutex}; 188 std::unique_lock lock{mutex};
191 current_fence = next_fence; 189 current_fence = next_fence;
192 next_fence = &resource_manager.CommitFence(); 190 next_fence = &resource_manager.CommitFence();
193 191
194 current_cmdbuf = vk::CommandBuffer(resource_manager.CommitCommandBuffer(*current_fence), 192 current_cmdbuf = vk::CommandBuffer(resource_manager.CommitCommandBuffer(*current_fence),
195 device.GetDispatchLoader()); 193 device.GetDispatchLoader());
196 current_cmdbuf.Begin(cmdbuf_bi); 194 current_cmdbuf.Begin({
195 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
196 .pNext = nullptr,
197 .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
198 .pInheritanceInfo = nullptr,
199 });
197 200
198 // Enable counters once again. These are disabled when a command buffer is finished. 201 // Enable counters once again. These are disabled when a command buffer is finished.
199 if (query_cache) { 202 if (query_cache) {
diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
index 97429cc59..cd7d7a4e4 100644
--- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
+++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
@@ -685,13 +685,19 @@ private:
685 } 685 }
686 t_smem_uint = TypePointer(spv::StorageClass::Workgroup, t_uint); 686 t_smem_uint = TypePointer(spv::StorageClass::Workgroup, t_uint);
687 687
688 const u32 smem_size = specialization.shared_memory_size; 688 u32 smem_size = specialization.shared_memory_size * 4;
689 if (smem_size == 0) { 689 if (smem_size == 0) {
690 // Avoid declaring an empty array. 690 // Avoid declaring an empty array.
691 return; 691 return;
692 } 692 }
693 const auto element_count = static_cast<u32>(Common::AlignUp(smem_size, 4) / 4); 693 const u32 limit = device.GetMaxComputeSharedMemorySize();
694 const Id type_array = TypeArray(t_uint, Constant(t_uint, element_count)); 694 if (smem_size > limit) {
695 LOG_ERROR(Render_Vulkan, "Shared memory size {} is clamped to host's limit {}",
696 smem_size, limit);
697 smem_size = limit;
698 }
699
700 const Id type_array = TypeArray(t_uint, Constant(t_uint, smem_size / 4));
695 const Id type_pointer = TypePointer(spv::StorageClass::Workgroup, type_array); 701 const Id type_pointer = TypePointer(spv::StorageClass::Workgroup, type_array);
696 Name(type_pointer, "SharedMemory"); 702 Name(type_pointer, "SharedMemory");
697 703
@@ -700,9 +706,9 @@ private:
700 } 706 }
701 707
702 void DeclareInternalFlags() { 708 void DeclareInternalFlags() {
703 constexpr std::array names = {"zero", "sign", "carry", "overflow"}; 709 static constexpr std::array names{"zero", "sign", "carry", "overflow"};
710
704 for (std::size_t flag = 0; flag < INTERNAL_FLAGS_COUNT; ++flag) { 711 for (std::size_t flag = 0; flag < INTERNAL_FLAGS_COUNT; ++flag) {
705 const auto flag_code = static_cast<InternalFlag>(flag);
706 const Id id = OpVariable(t_prv_bool, spv::StorageClass::Private, v_false); 712 const Id id = OpVariable(t_prv_bool, spv::StorageClass::Private, v_false);
707 internal_flags[flag] = AddGlobalVariable(Name(id, names[flag])); 713 internal_flags[flag] = AddGlobalVariable(Name(id, names[flag]));
708 } 714 }
@@ -2798,7 +2804,6 @@ private:
2798 std::map<GlobalMemoryBase, Id> global_buffers; 2804 std::map<GlobalMemoryBase, Id> global_buffers;
2799 std::map<u32, TexelBuffer> uniform_texels; 2805 std::map<u32, TexelBuffer> uniform_texels;
2800 std::map<u32, SampledImage> sampled_images; 2806 std::map<u32, SampledImage> sampled_images;
2801 std::map<u32, TexelBuffer> storage_texels;
2802 std::map<u32, StorageImage> images; 2807 std::map<u32, StorageImage> images;
2803 2808
2804 std::array<Id, Maxwell::NumRenderTargets> frag_colors{}; 2809 std::array<Id, Maxwell::NumRenderTargets> frag_colors{};
diff --git a/src/video_core/renderer_vulkan/vk_shader_util.cpp b/src/video_core/renderer_vulkan/vk_shader_util.cpp
index 112df9c71..c1a218d76 100644
--- a/src/video_core/renderer_vulkan/vk_shader_util.cpp
+++ b/src/video_core/renderer_vulkan/vk_shader_util.cpp
@@ -19,13 +19,13 @@ vk::ShaderModule BuildShader(const VKDevice& device, std::size_t code_size, cons
19 const auto data = std::make_unique<u32[]>(code_size / sizeof(u32)); 19 const auto data = std::make_unique<u32[]>(code_size / sizeof(u32));
20 std::memcpy(data.get(), code_data, code_size); 20 std::memcpy(data.get(), code_data, code_size);
21 21
22 VkShaderModuleCreateInfo ci; 22 return device.GetLogical().CreateShaderModule({
23 ci.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; 23 .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
24 ci.pNext = nullptr; 24 .pNext = nullptr,
25 ci.flags = 0; 25 .flags = 0,
26 ci.codeSize = code_size; 26 .codeSize = code_size,
27 ci.pCode = data.get(); 27 .pCode = data.get(),
28 return device.GetLogical().CreateShaderModule(ci); 28 });
29} 29}
30 30
31} // namespace Vulkan 31} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp
index 45c180221..5eca0ab91 100644
--- a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp
+++ b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp
@@ -71,20 +71,19 @@ VKBuffer* VKStagingBufferPool::TryGetReservedBuffer(std::size_t size, bool host_
71VKBuffer& VKStagingBufferPool::CreateStagingBuffer(std::size_t size, bool host_visible) { 71VKBuffer& VKStagingBufferPool::CreateStagingBuffer(std::size_t size, bool host_visible) {
72 const u32 log2 = Common::Log2Ceil64(size); 72 const u32 log2 = Common::Log2Ceil64(size);
73 73
74 VkBufferCreateInfo ci;
75 ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
76 ci.pNext = nullptr;
77 ci.flags = 0;
78 ci.size = 1ULL << log2;
79 ci.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT |
80 VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
81 VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
82 ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
83 ci.queueFamilyIndexCount = 0;
84 ci.pQueueFamilyIndices = nullptr;
85
86 auto buffer = std::make_unique<VKBuffer>(); 74 auto buffer = std::make_unique<VKBuffer>();
87 buffer->handle = device.GetLogical().CreateBuffer(ci); 75 buffer->handle = device.GetLogical().CreateBuffer({
76 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
77 .pNext = nullptr,
78 .flags = 0,
79 .size = 1ULL << log2,
80 .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT |
81 VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
82 VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
83 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
84 .queueFamilyIndexCount = 0,
85 .pQueueFamilyIndices = nullptr,
86 });
88 buffer->commit = memory_manager.Commit(buffer->handle, host_visible); 87 buffer->commit = memory_manager.Commit(buffer->handle, host_visible);
89 88
90 auto& entries = GetCache(host_visible)[log2].entries; 89 auto& entries = GetCache(host_visible)[log2].entries;
diff --git a/src/video_core/renderer_vulkan/vk_state_tracker.cpp b/src/video_core/renderer_vulkan/vk_state_tracker.cpp
index e5a583dd5..9151d9fb1 100644
--- a/src/video_core/renderer_vulkan/vk_state_tracker.cpp
+++ b/src/video_core/renderer_vulkan/vk_state_tracker.cpp
@@ -158,6 +158,7 @@ void StateTracker::Initialize() {
158 SetupDirtyFrontFace(tables); 158 SetupDirtyFrontFace(tables);
159 SetupDirtyPrimitiveTopology(tables); 159 SetupDirtyPrimitiveTopology(tables);
160 SetupDirtyStencilOp(tables); 160 SetupDirtyStencilOp(tables);
161 SetupDirtyStencilTestEnable(tables);
161} 162}
162 163
163void StateTracker::InvalidateCommandBufferState() { 164void StateTracker::InvalidateCommandBufferState() {
diff --git a/src/video_core/renderer_vulkan/vk_stream_buffer.cpp b/src/video_core/renderer_vulkan/vk_stream_buffer.cpp
index 2d28a6c47..a5526a3f5 100644
--- a/src/video_core/renderer_vulkan/vk_stream_buffer.cpp
+++ b/src/video_core/renderer_vulkan/vk_stream_buffer.cpp
@@ -122,30 +122,27 @@ void VKStreamBuffer::CreateBuffers(VkBufferUsageFlags usage) {
122 // Substract from the preferred heap size some bytes to avoid getting out of memory. 122 // Substract from the preferred heap size some bytes to avoid getting out of memory.
123 const VkDeviceSize heap_size = memory_properties.memoryHeaps[preferred_heap].size; 123 const VkDeviceSize heap_size = memory_properties.memoryHeaps[preferred_heap].size;
124 const VkDeviceSize allocable_size = heap_size - 9 * 1024 * 1024; 124 const VkDeviceSize allocable_size = heap_size - 9 * 1024 * 1024;
125 125 buffer = device.GetLogical().CreateBuffer({
126 VkBufferCreateInfo buffer_ci; 126 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
127 buffer_ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; 127 .pNext = nullptr,
128 buffer_ci.pNext = nullptr; 128 .flags = 0,
129 buffer_ci.flags = 0; 129 .size = std::min(PREFERRED_STREAM_BUFFER_SIZE, allocable_size),
130 buffer_ci.size = std::min(PREFERRED_STREAM_BUFFER_SIZE, allocable_size); 130 .usage = usage,
131 buffer_ci.usage = usage; 131 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
132 buffer_ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; 132 .queueFamilyIndexCount = 0,
133 buffer_ci.queueFamilyIndexCount = 0; 133 .pQueueFamilyIndices = nullptr,
134 buffer_ci.pQueueFamilyIndices = nullptr; 134 });
135
136 buffer = device.GetLogical().CreateBuffer(buffer_ci);
137 135
138 const auto requirements = device.GetLogical().GetBufferMemoryRequirements(*buffer); 136 const auto requirements = device.GetLogical().GetBufferMemoryRequirements(*buffer);
139 const u32 required_flags = requirements.memoryTypeBits; 137 const u32 required_flags = requirements.memoryTypeBits;
140 stream_buffer_size = static_cast<u64>(requirements.size); 138 stream_buffer_size = static_cast<u64>(requirements.size);
141 139
142 VkMemoryAllocateInfo memory_ai; 140 memory = device.GetLogical().AllocateMemory({
143 memory_ai.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; 141 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
144 memory_ai.pNext = nullptr; 142 .pNext = nullptr,
145 memory_ai.allocationSize = requirements.size; 143 .allocationSize = requirements.size,
146 memory_ai.memoryTypeIndex = GetMemoryType(memory_properties, required_flags); 144 .memoryTypeIndex = GetMemoryType(memory_properties, required_flags),
147 145 });
148 memory = device.GetLogical().AllocateMemory(memory_ai);
149 buffer.BindMemory(*memory, 0); 146 buffer.BindMemory(*memory, 0);
150} 147}
151 148
diff --git a/src/video_core/renderer_vulkan/vk_swapchain.cpp b/src/video_core/renderer_vulkan/vk_swapchain.cpp
index bffd8f32a..c25e312b6 100644
--- a/src/video_core/renderer_vulkan/vk_swapchain.cpp
+++ b/src/video_core/renderer_vulkan/vk_swapchain.cpp
@@ -95,15 +95,16 @@ bool VKSwapchain::Present(VkSemaphore render_semaphore, VKFence& fence) {
95 const auto present_queue{device.GetPresentQueue()}; 95 const auto present_queue{device.GetPresentQueue()};
96 bool recreated = false; 96 bool recreated = false;
97 97
98 VkPresentInfoKHR present_info; 98 const VkPresentInfoKHR present_info{
99 present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; 99 .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
100 present_info.pNext = nullptr; 100 .pNext = nullptr,
101 present_info.waitSemaphoreCount = render_semaphore ? 2U : 1U; 101 .waitSemaphoreCount = render_semaphore ? 2U : 1U,
102 present_info.pWaitSemaphores = semaphores.data(); 102 .pWaitSemaphores = semaphores.data(),
103 present_info.swapchainCount = 1; 103 .swapchainCount = 1,
104 present_info.pSwapchains = swapchain.address(); 104 .pSwapchains = swapchain.address(),
105 present_info.pImageIndices = &image_index; 105 .pImageIndices = &image_index,
106 present_info.pResults = nullptr; 106 .pResults = nullptr,
107 };
107 108
108 switch (const VkResult result = present_queue.Present(present_info)) { 109 switch (const VkResult result = present_queue.Present(present_info)) {
109 case VK_SUCCESS: 110 case VK_SUCCESS:
@@ -147,24 +148,25 @@ void VKSwapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities,
147 requested_image_count = capabilities.maxImageCount; 148 requested_image_count = capabilities.maxImageCount;
148 } 149 }
149 150
150 VkSwapchainCreateInfoKHR swapchain_ci; 151 VkSwapchainCreateInfoKHR swapchain_ci{
151 swapchain_ci.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; 152 .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
152 swapchain_ci.pNext = nullptr; 153 .pNext = nullptr,
153 swapchain_ci.flags = 0; 154 .flags = 0,
154 swapchain_ci.surface = surface; 155 .surface = surface,
155 swapchain_ci.minImageCount = requested_image_count; 156 .minImageCount = requested_image_count,
156 swapchain_ci.imageFormat = surface_format.format; 157 .imageFormat = surface_format.format,
157 swapchain_ci.imageColorSpace = surface_format.colorSpace; 158 .imageColorSpace = surface_format.colorSpace,
158 swapchain_ci.imageArrayLayers = 1; 159 .imageArrayLayers = 1,
159 swapchain_ci.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; 160 .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
160 swapchain_ci.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; 161 .imageSharingMode = VK_SHARING_MODE_EXCLUSIVE,
161 swapchain_ci.queueFamilyIndexCount = 0; 162 .queueFamilyIndexCount = 0,
162 swapchain_ci.pQueueFamilyIndices = nullptr; 163 .pQueueFamilyIndices = nullptr,
163 swapchain_ci.preTransform = capabilities.currentTransform; 164 .preTransform = capabilities.currentTransform,
164 swapchain_ci.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; 165 .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
165 swapchain_ci.presentMode = present_mode; 166 .presentMode = present_mode,
166 swapchain_ci.clipped = VK_FALSE; 167 .clipped = VK_FALSE,
167 swapchain_ci.oldSwapchain = nullptr; 168 .oldSwapchain = nullptr,
169 };
168 170
169 const u32 graphics_family{device.GetGraphicsFamily()}; 171 const u32 graphics_family{device.GetGraphicsFamily()};
170 const u32 present_family{device.GetPresentFamily()}; 172 const u32 present_family{device.GetPresentFamily()};
@@ -173,8 +175,6 @@ void VKSwapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities,
173 swapchain_ci.imageSharingMode = VK_SHARING_MODE_CONCURRENT; 175 swapchain_ci.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
174 swapchain_ci.queueFamilyIndexCount = static_cast<u32>(queue_indices.size()); 176 swapchain_ci.queueFamilyIndexCount = static_cast<u32>(queue_indices.size());
175 swapchain_ci.pQueueFamilyIndices = queue_indices.data(); 177 swapchain_ci.pQueueFamilyIndices = queue_indices.data();
176 } else {
177 swapchain_ci.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
178 } 178 }
179 179
180 // Request the size again to reduce the possibility of a TOCTOU race condition. 180 // Request the size again to reduce the possibility of a TOCTOU race condition.
@@ -200,20 +200,28 @@ void VKSwapchain::CreateSemaphores() {
200} 200}
201 201
202void VKSwapchain::CreateImageViews() { 202void VKSwapchain::CreateImageViews() {
203 VkImageViewCreateInfo ci; 203 VkImageViewCreateInfo ci{
204 ci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; 204 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
205 ci.pNext = nullptr; 205 .pNext = nullptr,
206 ci.flags = 0; 206 .flags = 0,
207 // ci.image 207 .viewType = VK_IMAGE_VIEW_TYPE_2D,
208 ci.viewType = VK_IMAGE_VIEW_TYPE_2D; 208 .format = image_format,
209 ci.format = image_format; 209 .components =
210 ci.components = {VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, 210 {
211 VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY}; 211 .r = VK_COMPONENT_SWIZZLE_IDENTITY,
212 ci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 212 .g = VK_COMPONENT_SWIZZLE_IDENTITY,
213 ci.subresourceRange.baseMipLevel = 0; 213 .b = VK_COMPONENT_SWIZZLE_IDENTITY,
214 ci.subresourceRange.levelCount = 1; 214 .a = VK_COMPONENT_SWIZZLE_IDENTITY,
215 ci.subresourceRange.baseArrayLayer = 0; 215 },
216 ci.subresourceRange.layerCount = 1; 216 .subresourceRange =
217 {
218 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
219 .baseMipLevel = 0,
220 .levelCount = 1,
221 .baseArrayLayer = 0,
222 .layerCount = 1,
223 },
224 };
217 225
218 image_views.resize(image_count); 226 image_views.resize(image_count);
219 for (std::size_t i = 0; i < image_count; i++) { 227 for (std::size_t i = 0; i < image_count; i++) {
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
index 430031665..d102e6d27 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
@@ -95,17 +95,18 @@ VkImageViewType GetImageViewType(SurfaceTarget target) {
95vk::Buffer CreateBuffer(const VKDevice& device, const SurfaceParams& params, 95vk::Buffer CreateBuffer(const VKDevice& device, const SurfaceParams& params,
96 std::size_t host_memory_size) { 96 std::size_t host_memory_size) {
97 // TODO(Rodrigo): Move texture buffer creation to the buffer cache 97 // TODO(Rodrigo): Move texture buffer creation to the buffer cache
98 VkBufferCreateInfo ci; 98 return device.GetLogical().CreateBuffer({
99 ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; 99 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
100 ci.pNext = nullptr; 100 .pNext = nullptr,
101 ci.flags = 0; 101 .flags = 0,
102 ci.size = static_cast<VkDeviceSize>(host_memory_size); 102 .size = static_cast<VkDeviceSize>(host_memory_size),
103 ci.usage = VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | 103 .usage = VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT |
104 VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; 104 VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT |
105 ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; 105 VK_BUFFER_USAGE_TRANSFER_DST_BIT,
106 ci.queueFamilyIndexCount = 0; 106 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
107 ci.pQueueFamilyIndices = nullptr; 107 .queueFamilyIndexCount = 0,
108 return device.GetLogical().CreateBuffer(ci); 108 .pQueueFamilyIndices = nullptr,
109 });
109} 110}
110 111
111VkBufferViewCreateInfo GenerateBufferViewCreateInfo(const VKDevice& device, 112VkBufferViewCreateInfo GenerateBufferViewCreateInfo(const VKDevice& device,
@@ -113,15 +114,16 @@ VkBufferViewCreateInfo GenerateBufferViewCreateInfo(const VKDevice& device,
113 std::size_t host_memory_size) { 114 std::size_t host_memory_size) {
114 ASSERT(params.IsBuffer()); 115 ASSERT(params.IsBuffer());
115 116
116 VkBufferViewCreateInfo ci; 117 return {
117 ci.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO; 118 .sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,
118 ci.pNext = nullptr; 119 .pNext = nullptr,
119 ci.flags = 0; 120 .flags = 0,
120 ci.buffer = buffer; 121 .buffer = buffer,
121 ci.format = MaxwellToVK::SurfaceFormat(device, FormatType::Buffer, params.pixel_format).format; 122 .format =
122 ci.offset = 0; 123 MaxwellToVK::SurfaceFormat(device, FormatType::Buffer, params.pixel_format).format,
123 ci.range = static_cast<VkDeviceSize>(host_memory_size); 124 .offset = 0,
124 return ci; 125 .range = static_cast<VkDeviceSize>(host_memory_size),
126 };
125} 127}
126 128
127VkImageCreateInfo GenerateImageCreateInfo(const VKDevice& device, const SurfaceParams& params) { 129VkImageCreateInfo GenerateImageCreateInfo(const VKDevice& device, const SurfaceParams& params) {
@@ -130,23 +132,23 @@ VkImageCreateInfo GenerateImageCreateInfo(const VKDevice& device, const SurfaceP
130 const auto [format, attachable, storage] = 132 const auto [format, attachable, storage] =
131 MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, params.pixel_format); 133 MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, params.pixel_format);
132 134
133 VkImageCreateInfo ci; 135 VkImageCreateInfo ci{
134 ci.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; 136 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
135 ci.pNext = nullptr; 137 .pNext = nullptr,
136 ci.flags = 0; 138 .flags = 0,
137 ci.imageType = SurfaceTargetToImage(params.target); 139 .imageType = SurfaceTargetToImage(params.target),
138 ci.format = format; 140 .format = format,
139 ci.mipLevels = params.num_levels; 141 .mipLevels = params.num_levels,
140 ci.arrayLayers = static_cast<u32>(params.GetNumLayers()); 142 .arrayLayers = static_cast<u32>(params.GetNumLayers()),
141 ci.samples = VK_SAMPLE_COUNT_1_BIT; 143 .samples = VK_SAMPLE_COUNT_1_BIT,
142 ci.tiling = VK_IMAGE_TILING_OPTIMAL; 144 .tiling = VK_IMAGE_TILING_OPTIMAL,
143 ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; 145 .usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
144 ci.queueFamilyIndexCount = 0; 146 VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
145 ci.pQueueFamilyIndices = nullptr; 147 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
146 ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; 148 .queueFamilyIndexCount = 0,
147 149 .pQueueFamilyIndices = nullptr,
148 ci.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | 150 .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
149 VK_IMAGE_USAGE_TRANSFER_SRC_BIT; 151 };
150 if (attachable) { 152 if (attachable) {
151 ci.usage |= params.IsPixelFormatZeta() ? VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT 153 ci.usage |= params.IsPixelFormatZeta() ? VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
152 : VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; 154 : VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
@@ -233,7 +235,7 @@ void CachedSurface::UploadTexture(const std::vector<u8>& staging_buffer) {
233void CachedSurface::DownloadTexture(std::vector<u8>& staging_buffer) { 235void CachedSurface::DownloadTexture(std::vector<u8>& staging_buffer) {
234 UNIMPLEMENTED_IF(params.IsBuffer()); 236 UNIMPLEMENTED_IF(params.IsBuffer());
235 237
236 if (params.pixel_format == VideoCore::Surface::PixelFormat::A1B5G5R5U) { 238 if (params.pixel_format == VideoCore::Surface::PixelFormat::A1B5G5R5_UNORM) {
237 LOG_WARNING(Render_Vulkan, "A1B5G5R5 flushing is stubbed"); 239 LOG_WARNING(Render_Vulkan, "A1B5G5R5 flushing is stubbed");
238 } 240 }
239 241
@@ -281,12 +283,10 @@ void CachedSurface::UploadBuffer(const std::vector<u8>& staging_buffer) {
281 VkBufferMemoryBarrier barrier; 283 VkBufferMemoryBarrier barrier;
282 barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; 284 barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
283 barrier.pNext = nullptr; 285 barrier.pNext = nullptr;
284 barrier.srcAccessMask = VK_PIPELINE_STAGE_TRANSFER_BIT; 286 barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
285 barrier.dstAccessMask = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT; 287 barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
286 barrier.srcQueueFamilyIndex = VK_ACCESS_TRANSFER_WRITE_BIT; 288 barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; // They'll be ignored anyway
287 barrier.dstQueueFamilyIndex = VK_ACCESS_SHADER_READ_BIT; 289 barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
288 barrier.srcQueueFamilyIndex = 0;
289 barrier.dstQueueFamilyIndex = 0;
290 barrier.buffer = dst_buffer; 290 barrier.buffer = dst_buffer;
291 barrier.offset = 0; 291 barrier.offset = 0;
292 barrier.size = size; 292 barrier.size = size;
@@ -323,22 +323,25 @@ void CachedSurface::UploadImage(const std::vector<u8>& staging_buffer) {
323} 323}
324 324
325VkBufferImageCopy CachedSurface::GetBufferImageCopy(u32 level) const { 325VkBufferImageCopy CachedSurface::GetBufferImageCopy(u32 level) const {
326 VkBufferImageCopy copy; 326 return {
327 copy.bufferOffset = params.GetHostMipmapLevelOffset(level, is_converted); 327 .bufferOffset = params.GetHostMipmapLevelOffset(level, is_converted),
328 copy.bufferRowLength = 0; 328 .bufferRowLength = 0,
329 copy.bufferImageHeight = 0; 329 .bufferImageHeight = 0,
330 copy.imageSubresource.aspectMask = image->GetAspectMask(); 330 .imageSubresource =
331 copy.imageSubresource.mipLevel = level; 331 {
332 copy.imageSubresource.baseArrayLayer = 0; 332 .aspectMask = image->GetAspectMask(),
333 copy.imageSubresource.layerCount = static_cast<u32>(params.GetNumLayers()); 333 .mipLevel = level,
334 copy.imageOffset.x = 0; 334 .baseArrayLayer = 0,
335 copy.imageOffset.y = 0; 335 .layerCount = static_cast<u32>(params.GetNumLayers()),
336 copy.imageOffset.z = 0; 336 },
337 copy.imageExtent.width = params.GetMipWidth(level); 337 .imageOffset = {.x = 0, .y = 0, .z = 0},
338 copy.imageExtent.height = params.GetMipHeight(level); 338 .imageExtent =
339 copy.imageExtent.depth = 339 {
340 params.target == SurfaceTarget::Texture3D ? params.GetMipDepth(level) : 1; 340 .width = params.GetMipWidth(level),
341 return copy; 341 .height = params.GetMipHeight(level),
342 .depth = params.target == SurfaceTarget::Texture3D ? params.GetMipDepth(level) : 1U,
343 },
344 };
342} 345}
343 346
344VkImageSubresourceRange CachedSurface::GetImageSubresourceRange() const { 347VkImageSubresourceRange CachedSurface::GetImageSubresourceRange() const {
@@ -382,7 +385,7 @@ VkImageView CachedSurfaceView::GetImageView(SwizzleSource x_source, SwizzleSourc
382 385
383 std::array swizzle{MaxwellToVK::SwizzleSource(x_source), MaxwellToVK::SwizzleSource(y_source), 386 std::array swizzle{MaxwellToVK::SwizzleSource(x_source), MaxwellToVK::SwizzleSource(y_source),
384 MaxwellToVK::SwizzleSource(z_source), MaxwellToVK::SwizzleSource(w_source)}; 387 MaxwellToVK::SwizzleSource(z_source), MaxwellToVK::SwizzleSource(w_source)};
385 if (params.pixel_format == VideoCore::Surface::PixelFormat::A1B5G5R5U) { 388 if (params.pixel_format == VideoCore::Surface::PixelFormat::A1B5G5R5_UNORM) {
386 // A1B5G5R5 is implemented as A1R5G5B5, we have to change the swizzle here. 389 // A1B5G5R5 is implemented as A1R5G5B5, we have to change the swizzle here.
387 std::swap(swizzle[0], swizzle[2]); 390 std::swap(swizzle[0], swizzle[2]);
388 } 391 }
@@ -394,11 +397,11 @@ VkImageView CachedSurfaceView::GetImageView(SwizzleSource x_source, SwizzleSourc
394 UNIMPLEMENTED_IF(x_source != SwizzleSource::R && x_source != SwizzleSource::G); 397 UNIMPLEMENTED_IF(x_source != SwizzleSource::R && x_source != SwizzleSource::G);
395 const bool is_first = x_source == SwizzleSource::R; 398 const bool is_first = x_source == SwizzleSource::R;
396 switch (params.pixel_format) { 399 switch (params.pixel_format) {
397 case VideoCore::Surface::PixelFormat::Z24S8: 400 case VideoCore::Surface::PixelFormat::D24_UNORM_S8_UINT:
398 case VideoCore::Surface::PixelFormat::Z32FS8: 401 case VideoCore::Surface::PixelFormat::D32_FLOAT_S8_UINT:
399 aspect = is_first ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_STENCIL_BIT; 402 aspect = is_first ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_STENCIL_BIT;
400 break; 403 break;
401 case VideoCore::Surface::PixelFormat::S8Z24: 404 case VideoCore::Surface::PixelFormat::S8_UINT_D24_UNORM:
402 aspect = is_first ? VK_IMAGE_ASPECT_STENCIL_BIT : VK_IMAGE_ASPECT_DEPTH_BIT; 405 aspect = is_first ? VK_IMAGE_ASPECT_STENCIL_BIT : VK_IMAGE_ASPECT_DEPTH_BIT;
403 break; 406 break;
404 default: 407 default:
@@ -418,20 +421,29 @@ VkImageView CachedSurfaceView::GetImageView(SwizzleSource x_source, SwizzleSourc
418 ASSERT(num_slices == params.depth); 421 ASSERT(num_slices == params.depth);
419 } 422 }
420 423
421 VkImageViewCreateInfo ci; 424 image_view = device.GetLogical().CreateImageView({
422 ci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; 425 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
423 ci.pNext = nullptr; 426 .pNext = nullptr,
424 ci.flags = 0; 427 .flags = 0,
425 ci.image = surface.GetImageHandle(); 428 .image = surface.GetImageHandle(),
426 ci.viewType = image_view_type; 429 .viewType = image_view_type,
427 ci.format = surface.GetImage().GetFormat(); 430 .format = surface.GetImage().GetFormat(),
428 ci.components = {swizzle[0], swizzle[1], swizzle[2], swizzle[3]}; 431 .components =
429 ci.subresourceRange.aspectMask = aspect; 432 {
430 ci.subresourceRange.baseMipLevel = base_level; 433 .r = swizzle[0],
431 ci.subresourceRange.levelCount = num_levels; 434 .g = swizzle[1],
432 ci.subresourceRange.baseArrayLayer = base_layer; 435 .b = swizzle[2],
433 ci.subresourceRange.layerCount = num_layers; 436 .a = swizzle[3],
434 image_view = device.GetLogical().CreateImageView(ci); 437 },
438 .subresourceRange =
439 {
440 .aspectMask = aspect,
441 .baseMipLevel = base_level,
442 .levelCount = num_levels,
443 .baseArrayLayer = base_layer,
444 .layerCount = num_layers,
445 },
446 });
435 447
436 return last_image_view = *image_view; 448 return last_image_view = *image_view;
437} 449}
@@ -441,17 +453,26 @@ VkImageView CachedSurfaceView::GetAttachment() {
441 return *render_target; 453 return *render_target;
442 } 454 }
443 455
444 VkImageViewCreateInfo ci; 456 VkImageViewCreateInfo ci{
445 ci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; 457 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
446 ci.pNext = nullptr; 458 .pNext = nullptr,
447 ci.flags = 0; 459 .flags = 0,
448 ci.image = surface.GetImageHandle(); 460 .image = surface.GetImageHandle(),
449 ci.format = surface.GetImage().GetFormat(); 461 .format = surface.GetImage().GetFormat(),
450 ci.components = {VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, 462 .components =
451 VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY}; 463 {
452 ci.subresourceRange.aspectMask = aspect_mask; 464 .r = VK_COMPONENT_SWIZZLE_IDENTITY,
453 ci.subresourceRange.baseMipLevel = base_level; 465 .g = VK_COMPONENT_SWIZZLE_IDENTITY,
454 ci.subresourceRange.levelCount = num_levels; 466 .b = VK_COMPONENT_SWIZZLE_IDENTITY,
467 .a = VK_COMPONENT_SWIZZLE_IDENTITY,
468 },
469 .subresourceRange =
470 {
471 .aspectMask = aspect_mask,
472 .baseMipLevel = base_level,
473 .levelCount = num_levels,
474 },
475 };
455 if (image_view_type == VK_IMAGE_VIEW_TYPE_3D) { 476 if (image_view_type == VK_IMAGE_VIEW_TYPE_3D) {
456 ci.viewType = num_slices > 1 ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D; 477 ci.viewType = num_slices > 1 ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D;
457 ci.subresourceRange.baseArrayLayer = base_slice; 478 ci.subresourceRange.baseArrayLayer = base_slice;
@@ -504,24 +525,40 @@ void VKTextureCache::ImageCopy(Surface& src_surface, Surface& dst_surface,
504 VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, 525 VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT,
505 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); 526 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
506 527
507 VkImageCopy copy; 528 const VkImageCopy copy{
508 copy.srcSubresource.aspectMask = src_surface->GetAspectMask(); 529 .srcSubresource =
509 copy.srcSubresource.mipLevel = copy_params.source_level; 530 {
510 copy.srcSubresource.baseArrayLayer = copy_params.source_z; 531 .aspectMask = src_surface->GetAspectMask(),
511 copy.srcSubresource.layerCount = num_layers; 532 .mipLevel = copy_params.source_level,
512 copy.srcOffset.x = copy_params.source_x; 533 .baseArrayLayer = copy_params.source_z,
513 copy.srcOffset.y = copy_params.source_y; 534 .layerCount = num_layers,
514 copy.srcOffset.z = 0; 535 },
515 copy.dstSubresource.aspectMask = dst_surface->GetAspectMask(); 536 .srcOffset =
516 copy.dstSubresource.mipLevel = copy_params.dest_level; 537 {
517 copy.dstSubresource.baseArrayLayer = dst_base_layer; 538 .x = static_cast<s32>(copy_params.source_x),
518 copy.dstSubresource.layerCount = num_layers; 539 .y = static_cast<s32>(copy_params.source_y),
519 copy.dstOffset.x = copy_params.dest_x; 540 .z = 0,
520 copy.dstOffset.y = copy_params.dest_y; 541 },
521 copy.dstOffset.z = dst_offset_z; 542 .dstSubresource =
522 copy.extent.width = copy_params.width; 543 {
523 copy.extent.height = copy_params.height; 544 .aspectMask = dst_surface->GetAspectMask(),
524 copy.extent.depth = extent_z; 545 .mipLevel = copy_params.dest_level,
546 .baseArrayLayer = dst_base_layer,
547 .layerCount = num_layers,
548 },
549 .dstOffset =
550 {
551 .x = static_cast<s32>(copy_params.dest_x),
552 .y = static_cast<s32>(copy_params.dest_y),
553 .z = static_cast<s32>(dst_offset_z),
554 },
555 .extent =
556 {
557 .width = copy_params.width,
558 .height = copy_params.height,
559 .depth = extent_z,
560 },
561 };
525 562
526 const VkImage src_image = src_surface->GetImageHandle(); 563 const VkImage src_image = src_surface->GetImageHandle();
527 const VkImage dst_image = dst_surface->GetImageHandle(); 564 const VkImage dst_image = dst_surface->GetImageHandle();
diff --git a/src/video_core/renderer_vulkan/wrapper.cpp b/src/video_core/renderer_vulkan/wrapper.cpp
index 051298cc8..14cac38ea 100644
--- a/src/video_core/renderer_vulkan/wrapper.cpp
+++ b/src/video_core/renderer_vulkan/wrapper.cpp
@@ -377,24 +377,26 @@ VkResult Free(VkDevice device, VkCommandPool handle, Span<VkCommandBuffer> buffe
377 377
378Instance Instance::Create(Span<const char*> layers, Span<const char*> extensions, 378Instance Instance::Create(Span<const char*> layers, Span<const char*> extensions,
379 InstanceDispatch& dld) noexcept { 379 InstanceDispatch& dld) noexcept {
380 VkApplicationInfo application_info; 380 static constexpr VkApplicationInfo application_info{
381 application_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; 381 .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
382 application_info.pNext = nullptr; 382 .pNext = nullptr,
383 application_info.pApplicationName = "yuzu Emulator"; 383 .pApplicationName = "yuzu Emulator",
384 application_info.applicationVersion = VK_MAKE_VERSION(0, 1, 0); 384 .applicationVersion = VK_MAKE_VERSION(0, 1, 0),
385 application_info.pEngineName = "yuzu Emulator"; 385 .pEngineName = "yuzu Emulator",
386 application_info.engineVersion = VK_MAKE_VERSION(0, 1, 0); 386 .engineVersion = VK_MAKE_VERSION(0, 1, 0),
387 application_info.apiVersion = VK_API_VERSION_1_1; 387 .apiVersion = VK_API_VERSION_1_1,
388 388 };
389 VkInstanceCreateInfo ci; 389
390 ci.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; 390 const VkInstanceCreateInfo ci{
391 ci.pNext = nullptr; 391 .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
392 ci.flags = 0; 392 .pNext = nullptr,
393 ci.pApplicationInfo = &application_info; 393 .flags = 0,
394 ci.enabledLayerCount = layers.size(); 394 .pApplicationInfo = &application_info,
395 ci.ppEnabledLayerNames = layers.data(); 395 .enabledLayerCount = layers.size(),
396 ci.enabledExtensionCount = extensions.size(); 396 .ppEnabledLayerNames = layers.data(),
397 ci.ppEnabledExtensionNames = extensions.data(); 397 .enabledExtensionCount = extensions.size(),
398 .ppEnabledExtensionNames = extensions.data(),
399 };
398 400
399 VkInstance instance; 401 VkInstance instance;
400 if (dld.vkCreateInstance(&ci, nullptr, &instance) != VK_SUCCESS) { 402 if (dld.vkCreateInstance(&ci, nullptr, &instance) != VK_SUCCESS) {
@@ -425,19 +427,20 @@ std::optional<std::vector<VkPhysicalDevice>> Instance::EnumeratePhysicalDevices(
425 427
426DebugCallback Instance::TryCreateDebugCallback( 428DebugCallback Instance::TryCreateDebugCallback(
427 PFN_vkDebugUtilsMessengerCallbackEXT callback) noexcept { 429 PFN_vkDebugUtilsMessengerCallbackEXT callback) noexcept {
428 VkDebugUtilsMessengerCreateInfoEXT ci; 430 const VkDebugUtilsMessengerCreateInfoEXT ci{
429 ci.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; 431 .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
430 ci.pNext = nullptr; 432 .pNext = nullptr,
431 ci.flags = 0; 433 .flags = 0,
432 ci.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | 434 .messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT |
433 VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | 435 VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
434 VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT | 436 VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT |
435 VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT; 437 VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT,
436 ci.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | 438 .messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
437 VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | 439 VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
438 VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT; 440 VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT,
439 ci.pfnUserCallback = callback; 441 .pfnUserCallback = callback,
440 ci.pUserData = nullptr; 442 .pUserData = nullptr,
443 };
441 444
442 VkDebugUtilsMessengerEXT messenger; 445 VkDebugUtilsMessengerEXT messenger;
443 if (dld->vkCreateDebugUtilsMessengerEXT(handle, &ci, nullptr, &messenger) != VK_SUCCESS) { 446 if (dld->vkCreateDebugUtilsMessengerEXT(handle, &ci, nullptr, &messenger) != VK_SUCCESS) {
@@ -468,12 +471,13 @@ DescriptorSets DescriptorPool::Allocate(const VkDescriptorSetAllocateInfo& ai) c
468} 471}
469 472
470CommandBuffers CommandPool::Allocate(std::size_t num_buffers, VkCommandBufferLevel level) const { 473CommandBuffers CommandPool::Allocate(std::size_t num_buffers, VkCommandBufferLevel level) const {
471 VkCommandBufferAllocateInfo ai; 474 const VkCommandBufferAllocateInfo ai{
472 ai.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; 475 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
473 ai.pNext = nullptr; 476 .pNext = nullptr,
474 ai.commandPool = handle; 477 .commandPool = handle,
475 ai.level = level; 478 .level = level,
476 ai.commandBufferCount = static_cast<u32>(num_buffers); 479 .commandBufferCount = static_cast<u32>(num_buffers),
480 };
477 481
478 std::unique_ptr buffers = std::make_unique<VkCommandBuffer[]>(num_buffers); 482 std::unique_ptr buffers = std::make_unique<VkCommandBuffer[]>(num_buffers);
479 switch (const VkResult result = dld->vkAllocateCommandBuffers(owner, &ai, buffers.get())) { 483 switch (const VkResult result = dld->vkAllocateCommandBuffers(owner, &ai, buffers.get())) {
@@ -497,17 +501,18 @@ std::vector<VkImage> SwapchainKHR::GetImages() const {
497Device Device::Create(VkPhysicalDevice physical_device, Span<VkDeviceQueueCreateInfo> queues_ci, 501Device Device::Create(VkPhysicalDevice physical_device, Span<VkDeviceQueueCreateInfo> queues_ci,
498 Span<const char*> enabled_extensions, const void* next, 502 Span<const char*> enabled_extensions, const void* next,
499 DeviceDispatch& dld) noexcept { 503 DeviceDispatch& dld) noexcept {
500 VkDeviceCreateInfo ci; 504 const VkDeviceCreateInfo ci{
501 ci.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; 505 .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
502 ci.pNext = next; 506 .pNext = next,
503 ci.flags = 0; 507 .flags = 0,
504 ci.queueCreateInfoCount = queues_ci.size(); 508 .queueCreateInfoCount = queues_ci.size(),
505 ci.pQueueCreateInfos = queues_ci.data(); 509 .pQueueCreateInfos = queues_ci.data(),
506 ci.enabledLayerCount = 0; 510 .enabledLayerCount = 0,
507 ci.ppEnabledLayerNames = nullptr; 511 .ppEnabledLayerNames = nullptr,
508 ci.enabledExtensionCount = enabled_extensions.size(); 512 .enabledExtensionCount = enabled_extensions.size(),
509 ci.ppEnabledExtensionNames = enabled_extensions.data(); 513 .ppEnabledExtensionNames = enabled_extensions.data(),
510 ci.pEnabledFeatures = nullptr; 514 .pEnabledFeatures = nullptr,
515 };
511 516
512 VkDevice device; 517 VkDevice device;
513 if (dld.vkCreateDevice(physical_device, &ci, nullptr, &device) != VK_SUCCESS) { 518 if (dld.vkCreateDevice(physical_device, &ci, nullptr, &device) != VK_SUCCESS) {
@@ -548,10 +553,11 @@ ImageView Device::CreateImageView(const VkImageViewCreateInfo& ci) const {
548} 553}
549 554
550Semaphore Device::CreateSemaphore() const { 555Semaphore Device::CreateSemaphore() const {
551 VkSemaphoreCreateInfo ci; 556 static constexpr VkSemaphoreCreateInfo ci{
552 ci.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; 557 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
553 ci.pNext = nullptr; 558 .pNext = nullptr,
554 ci.flags = 0; 559 .flags = 0,
560 };
555 561
556 VkSemaphore object; 562 VkSemaphore object;
557 Check(dld->vkCreateSemaphore(handle, &ci, nullptr, &object)); 563 Check(dld->vkCreateSemaphore(handle, &ci, nullptr, &object));
@@ -639,10 +645,12 @@ ShaderModule Device::CreateShaderModule(const VkShaderModuleCreateInfo& ci) cons
639} 645}
640 646
641Event Device::CreateEvent() const { 647Event Device::CreateEvent() const {
642 VkEventCreateInfo ci; 648 static constexpr VkEventCreateInfo ci{
643 ci.sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO; 649 .sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO,
644 ci.pNext = nullptr; 650 .pNext = nullptr,
645 ci.flags = 0; 651 .flags = 0,
652 };
653
646 VkEvent object; 654 VkEvent object;
647 Check(dld->vkCreateEvent(handle, &ci, nullptr, &object)); 655 Check(dld->vkCreateEvent(handle, &ci, nullptr, &object));
648 return Event(object, handle, *dld); 656 return Event(object, handle, *dld);
diff --git a/src/video_core/shader/async_shaders.cpp b/src/video_core/shader/async_shaders.cpp
new file mode 100644
index 000000000..b7f66d7ee
--- /dev/null
+++ b/src/video_core/shader/async_shaders.cpp
@@ -0,0 +1,181 @@
1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <chrono>
6#include <condition_variable>
7#include <mutex>
8#include <thread>
9#include <vector>
10#include "video_core/engines/maxwell_3d.h"
11#include "video_core/renderer_base.h"
12#include "video_core/renderer_opengl/gl_shader_cache.h"
13#include "video_core/shader/async_shaders.h"
14
15namespace VideoCommon::Shader {
16
17AsyncShaders::AsyncShaders(Core::Frontend::EmuWindow& emu_window) : emu_window(emu_window) {}
18
19AsyncShaders::~AsyncShaders() {
20 KillWorkers();
21}
22
23void AsyncShaders::AllocateWorkers(std::size_t num_workers) {
24 // If we're already have workers queued or don't want to queue workers, ignore
25 if (num_workers == worker_threads.size() || num_workers == 0) {
26 return;
27 }
28
29 // If workers already exist, clear them
30 if (!worker_threads.empty()) {
31 FreeWorkers();
32 }
33
34 // Create workers
35 for (std::size_t i = 0; i < num_workers; i++) {
36 context_list.push_back(emu_window.CreateSharedContext());
37 worker_threads.push_back(std::move(
38 std::thread(&AsyncShaders::ShaderCompilerThread, this, context_list[i].get())));
39 }
40}
41
42void AsyncShaders::FreeWorkers() {
43 // Mark all threads to quit
44 is_thread_exiting.store(true);
45 cv.notify_all();
46 for (auto& thread : worker_threads) {
47 thread.join();
48 }
49 // Clear our shared contexts
50 context_list.clear();
51
52 // Clear our worker threads
53 worker_threads.clear();
54}
55
56void AsyncShaders::KillWorkers() {
57 is_thread_exiting.store(true);
58 for (auto& thread : worker_threads) {
59 thread.detach();
60 }
61 // Clear our shared contexts
62 context_list.clear();
63
64 // Clear our worker threads
65 worker_threads.clear();
66}
67
68bool AsyncShaders::HasWorkQueued() {
69 return !pending_queue.empty();
70}
71
72bool AsyncShaders::HasCompletedWork() {
73 std::shared_lock lock{completed_mutex};
74 return !finished_work.empty();
75}
76
77bool AsyncShaders::IsShaderAsync(const Tegra::GPU& gpu) const {
78 const auto& regs = gpu.Maxwell3D().regs;
79
80 // If something is using depth, we can assume that games are not rendering anything which will
81 // be used one time.
82 if (regs.zeta_enable) {
83 return true;
84 }
85
86 // If games are using a small index count, we can assume these are full screen quads. Usually
87 // these shaders are only used once for building textures so we can assume they can't be built
88 // async
89 if (regs.index_array.count <= 6 || regs.vertex_buffer.count <= 6) {
90 return false;
91 }
92
93 return true;
94}
95
96std::vector<AsyncShaders::Result> AsyncShaders::GetCompletedWork() {
97 std::vector<AsyncShaders::Result> results;
98 {
99 std::unique_lock lock{completed_mutex};
100 results.assign(std::make_move_iterator(finished_work.begin()),
101 std::make_move_iterator(finished_work.end()));
102 finished_work.clear();
103 }
104 return results;
105}
106
107void AsyncShaders::QueueOpenGLShader(const OpenGL::Device& device,
108 Tegra::Engines::ShaderType shader_type, u64 uid,
109 std::vector<u64> code, std::vector<u64> code_b,
110 u32 main_offset,
111 VideoCommon::Shader::CompilerSettings compiler_settings,
112 const VideoCommon::Shader::Registry& registry,
113 VAddr cpu_addr) {
114 WorkerParams params{device.UseAssemblyShaders() ? AsyncShaders::Backend::GLASM
115 : AsyncShaders::Backend::OpenGL,
116 device,
117 shader_type,
118 uid,
119 std::move(code),
120 std::move(code_b),
121 main_offset,
122 compiler_settings,
123 registry,
124 cpu_addr};
125 std::unique_lock lock(queue_mutex);
126 pending_queue.push_back(std::move(params));
127 cv.notify_one();
128}
129
130void AsyncShaders::ShaderCompilerThread(Core::Frontend::GraphicsContext* context) {
131 using namespace std::chrono_literals;
132 while (!is_thread_exiting.load(std::memory_order_relaxed)) {
133 std::unique_lock lock{queue_mutex};
134 cv.wait(lock, [this] { return HasWorkQueued() || is_thread_exiting; });
135 if (is_thread_exiting) {
136 return;
137 }
138
139 // Partial lock to allow all threads to read at the same time
140 if (!HasWorkQueued()) {
141 continue;
142 }
143 // Another thread beat us, just unlock and wait for the next load
144 if (pending_queue.empty()) {
145 continue;
146 }
147 // Pull work from queue
148 WorkerParams work = std::move(pending_queue.front());
149 pending_queue.pop_front();
150
151 lock.unlock();
152
153 if (work.backend == AsyncShaders::Backend::OpenGL ||
154 work.backend == AsyncShaders::Backend::GLASM) {
155 const ShaderIR ir(work.code, work.main_offset, work.compiler_settings, work.registry);
156 const auto scope = context->Acquire();
157 auto program =
158 OpenGL::BuildShader(work.device, work.shader_type, work.uid, ir, work.registry);
159 Result result{};
160 result.backend = work.backend;
161 result.cpu_address = work.cpu_address;
162 result.uid = work.uid;
163 result.code = std::move(work.code);
164 result.code_b = std::move(work.code_b);
165 result.shader_type = work.shader_type;
166
167 if (work.backend == AsyncShaders::Backend::OpenGL) {
168 result.program.opengl = std::move(program->source_program);
169 } else if (work.backend == AsyncShaders::Backend::GLASM) {
170 result.program.glasm = std::move(program->assembly_program);
171 }
172
173 {
174 std::unique_lock complete_lock(completed_mutex);
175 finished_work.push_back(std::move(result));
176 }
177 }
178 }
179}
180
181} // namespace VideoCommon::Shader
diff --git a/src/video_core/shader/async_shaders.h b/src/video_core/shader/async_shaders.h
new file mode 100644
index 000000000..2f5ee94ad
--- /dev/null
+++ b/src/video_core/shader/async_shaders.h
@@ -0,0 +1,109 @@
1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <condition_variable>
8#include <deque>
9#include <memory>
10#include <shared_mutex>
11#include <thread>
12#include "common/bit_field.h"
13#include "common/common_types.h"
14#include "video_core/renderer_opengl/gl_device.h"
15#include "video_core/renderer_opengl/gl_resource_manager.h"
16#include "video_core/renderer_opengl/gl_shader_decompiler.h"
17
18namespace Core::Frontend {
19class EmuWindow;
20class GraphicsContext;
21} // namespace Core::Frontend
22
23namespace Tegra {
24class GPU;
25}
26
27namespace VideoCommon::Shader {
28
29class AsyncShaders {
30public:
31 enum class Backend {
32 OpenGL,
33 GLASM,
34 };
35
36 struct ResultPrograms {
37 OpenGL::OGLProgram opengl;
38 OpenGL::OGLAssemblyProgram glasm;
39 };
40
41 struct Result {
42 u64 uid;
43 VAddr cpu_address;
44 Backend backend;
45 ResultPrograms program;
46 std::vector<u64> code;
47 std::vector<u64> code_b;
48 Tegra::Engines::ShaderType shader_type;
49 };
50
51 explicit AsyncShaders(Core::Frontend::EmuWindow& emu_window);
52 ~AsyncShaders();
53
54 /// Start up shader worker threads
55 void AllocateWorkers(std::size_t num_workers);
56
57 /// Clear the shader queue and kill all worker threads
58 void FreeWorkers();
59
60 // Force end all threads
61 void KillWorkers();
62
63 /// Check to see if any shaders have actually been compiled
64 bool HasCompletedWork();
65
66 /// Deduce if a shader can be build on another thread of MUST be built in sync. We cannot build
67 /// every shader async as some shaders are only built and executed once. We try to "guess" which
68 /// shader would be used only once
69 bool IsShaderAsync(const Tegra::GPU& gpu) const;
70
71 /// Pulls completed compiled shaders
72 std::vector<Result> GetCompletedWork();
73
74 void QueueOpenGLShader(const OpenGL::Device& device, Tegra::Engines::ShaderType shader_type,
75 u64 uid, std::vector<u64> code, std::vector<u64> code_b, u32 main_offset,
76 VideoCommon::Shader::CompilerSettings compiler_settings,
77 const VideoCommon::Shader::Registry& registry, VAddr cpu_addr);
78
79private:
80 void ShaderCompilerThread(Core::Frontend::GraphicsContext* context);
81
82 /// Check our worker queue to see if we have any work queued already
83 bool HasWorkQueued();
84
85 struct WorkerParams {
86 AsyncShaders::Backend backend;
87 OpenGL::Device device;
88 Tegra::Engines::ShaderType shader_type;
89 u64 uid;
90 std::vector<u64> code;
91 std::vector<u64> code_b;
92 u32 main_offset;
93 VideoCommon::Shader::CompilerSettings compiler_settings;
94 VideoCommon::Shader::Registry registry;
95 VAddr cpu_address;
96 };
97
98 std::condition_variable cv;
99 std::mutex queue_mutex;
100 std::shared_mutex completed_mutex;
101 std::atomic<bool> is_thread_exiting{};
102 std::vector<std::unique_ptr<Core::Frontend::GraphicsContext>> context_list;
103 std::vector<std::thread> worker_threads;
104 std::deque<WorkerParams> pending_queue;
105 std::vector<AsyncShaders::Result> finished_work;
106 Core::Frontend::EmuWindow& emu_window;
107};
108
109} // namespace VideoCommon::Shader
diff --git a/src/video_core/shader/decode/arithmetic_integer.cpp b/src/video_core/shader/decode/arithmetic_integer.cpp
index a041519b7..73155966f 100644
--- a/src/video_core/shader/decode/arithmetic_integer.cpp
+++ b/src/video_core/shader/decode/arithmetic_integer.cpp
@@ -98,12 +98,12 @@ u32 ShaderIR::DecodeArithmeticInteger(NodeBlock& bb, u32 pc) {
98 op_b = GetOperandAbsNegInteger(op_b, false, instr.iadd3.neg_b, true); 98 op_b = GetOperandAbsNegInteger(op_b, false, instr.iadd3.neg_b, true);
99 op_c = GetOperandAbsNegInteger(op_c, false, instr.iadd3.neg_c, true); 99 op_c = GetOperandAbsNegInteger(op_c, false, instr.iadd3.neg_c, true);
100 100
101 const Node value = [&]() { 101 const Node value = [&] {
102 const Node add_ab = Operation(OperationCode::IAdd, NO_PRECISE, op_a, op_b); 102 Node add_ab = Operation(OperationCode::IAdd, NO_PRECISE, op_a, op_b);
103 if (opcode->get().GetId() != OpCode::Id::IADD3_R) { 103 if (opcode->get().GetId() != OpCode::Id::IADD3_R) {
104 return Operation(OperationCode::IAdd, NO_PRECISE, add_ab, op_c); 104 return Operation(OperationCode::IAdd, NO_PRECISE, add_ab, op_c);
105 } 105 }
106 const Node shifted = [&]() { 106 const Node shifted = [&] {
107 switch (instr.iadd3.mode) { 107 switch (instr.iadd3.mode) {
108 case Tegra::Shader::IAdd3Mode::RightShift: 108 case Tegra::Shader::IAdd3Mode::RightShift:
109 // TODO(tech4me): According to 109 // TODO(tech4me): According to
diff --git a/src/video_core/shader/decode/image.cpp b/src/video_core/shader/decode/image.cpp
index 07778dc3e..e75ca4fdb 100644
--- a/src/video_core/shader/decode/image.cpp
+++ b/src/video_core/shader/decode/image.cpp
@@ -31,11 +31,11 @@ ComponentType GetComponentType(Tegra::Engines::SamplerDescriptor descriptor,
31 std::size_t component) { 31 std::size_t component) {
32 const TextureFormat format{descriptor.format}; 32 const TextureFormat format{descriptor.format};
33 switch (format) { 33 switch (format) {
34 case TextureFormat::R16_G16_B16_A16: 34 case TextureFormat::R16G16B16A16:
35 case TextureFormat::R32_G32_B32_A32: 35 case TextureFormat::R32G32B32A32:
36 case TextureFormat::R32_G32_B32: 36 case TextureFormat::R32G32B32:
37 case TextureFormat::R32_G32: 37 case TextureFormat::R32G32:
38 case TextureFormat::R16_G16: 38 case TextureFormat::R16G16:
39 case TextureFormat::R32: 39 case TextureFormat::R32:
40 case TextureFormat::R16: 40 case TextureFormat::R16:
41 case TextureFormat::R8: 41 case TextureFormat::R8:
@@ -97,7 +97,7 @@ ComponentType GetComponentType(Tegra::Engines::SamplerDescriptor descriptor,
97 break; 97 break;
98 case TextureFormat::B5G6R5: 98 case TextureFormat::B5G6R5:
99 case TextureFormat::B6G5R5: 99 case TextureFormat::B6G5R5:
100 case TextureFormat::BF10GF11RF11: 100 case TextureFormat::B10G11R11:
101 if (component == 0) { 101 if (component == 0) {
102 return descriptor.b_type; 102 return descriptor.b_type;
103 } 103 }
@@ -108,9 +108,9 @@ ComponentType GetComponentType(Tegra::Engines::SamplerDescriptor descriptor,
108 return descriptor.r_type; 108 return descriptor.r_type;
109 } 109 }
110 break; 110 break;
111 case TextureFormat::G8R24: 111 case TextureFormat::R24G8:
112 case TextureFormat::G24R8: 112 case TextureFormat::R8G24:
113 case TextureFormat::G8R8: 113 case TextureFormat::R8G8:
114 case TextureFormat::G4R4: 114 case TextureFormat::G4R4:
115 if (component == 0) { 115 if (component == 0) {
116 return descriptor.g_type; 116 return descriptor.g_type;
@@ -137,15 +137,15 @@ bool IsComponentEnabled(std::size_t component_mask, std::size_t component) {
137 137
138u32 GetComponentSize(TextureFormat format, std::size_t component) { 138u32 GetComponentSize(TextureFormat format, std::size_t component) {
139 switch (format) { 139 switch (format) {
140 case TextureFormat::R32_G32_B32_A32: 140 case TextureFormat::R32G32B32A32:
141 return 32; 141 return 32;
142 case TextureFormat::R16_G16_B16_A16: 142 case TextureFormat::R16G16B16A16:
143 return 16; 143 return 16;
144 case TextureFormat::R32_G32_B32: 144 case TextureFormat::R32G32B32:
145 return component <= 2 ? 32 : 0; 145 return component <= 2 ? 32 : 0;
146 case TextureFormat::R32_G32: 146 case TextureFormat::R32G32:
147 return component <= 1 ? 32 : 0; 147 return component <= 1 ? 32 : 0;
148 case TextureFormat::R16_G16: 148 case TextureFormat::R16G16:
149 return component <= 1 ? 16 : 0; 149 return component <= 1 ? 16 : 0;
150 case TextureFormat::R32: 150 case TextureFormat::R32:
151 return component == 0 ? 32 : 0; 151 return component == 0 ? 32 : 0;
@@ -192,7 +192,7 @@ u32 GetComponentSize(TextureFormat format, std::size_t component) {
192 return 6; 192 return 6;
193 } 193 }
194 return 0; 194 return 0;
195 case TextureFormat::BF10GF11RF11: 195 case TextureFormat::B10G11R11:
196 if (component == 1 || component == 2) { 196 if (component == 1 || component == 2) {
197 return 11; 197 return 11;
198 } 198 }
@@ -200,7 +200,7 @@ u32 GetComponentSize(TextureFormat format, std::size_t component) {
200 return 10; 200 return 10;
201 } 201 }
202 return 0; 202 return 0;
203 case TextureFormat::G8R24: 203 case TextureFormat::R24G8:
204 if (component == 0) { 204 if (component == 0) {
205 return 8; 205 return 8;
206 } 206 }
@@ -208,7 +208,7 @@ u32 GetComponentSize(TextureFormat format, std::size_t component) {
208 return 24; 208 return 24;
209 } 209 }
210 return 0; 210 return 0;
211 case TextureFormat::G24R8: 211 case TextureFormat::R8G24:
212 if (component == 0) { 212 if (component == 0) {
213 return 8; 213 return 8;
214 } 214 }
@@ -216,7 +216,7 @@ u32 GetComponentSize(TextureFormat format, std::size_t component) {
216 return 24; 216 return 24;
217 } 217 }
218 return 0; 218 return 0;
219 case TextureFormat::G8R8: 219 case TextureFormat::R8G8:
220 return (component == 0 || component == 1) ? 8 : 0; 220 return (component == 0 || component == 1) ? 8 : 0;
221 case TextureFormat::G4R4: 221 case TextureFormat::G4R4:
222 return (component == 0 || component == 1) ? 4 : 0; 222 return (component == 0 || component == 1) ? 4 : 0;
@@ -231,25 +231,25 @@ std::size_t GetImageComponentMask(TextureFormat format) {
231 constexpr u8 B = 0b0100; 231 constexpr u8 B = 0b0100;
232 constexpr u8 A = 0b1000; 232 constexpr u8 A = 0b1000;
233 switch (format) { 233 switch (format) {
234 case TextureFormat::R32_G32_B32_A32: 234 case TextureFormat::R32G32B32A32:
235 case TextureFormat::R16_G16_B16_A16: 235 case TextureFormat::R16G16B16A16:
236 case TextureFormat::A8R8G8B8: 236 case TextureFormat::A8R8G8B8:
237 case TextureFormat::A2B10G10R10: 237 case TextureFormat::A2B10G10R10:
238 case TextureFormat::A4B4G4R4: 238 case TextureFormat::A4B4G4R4:
239 case TextureFormat::A5B5G5R1: 239 case TextureFormat::A5B5G5R1:
240 case TextureFormat::A1B5G5R5: 240 case TextureFormat::A1B5G5R5:
241 return std::size_t{R | G | B | A}; 241 return std::size_t{R | G | B | A};
242 case TextureFormat::R32_G32_B32: 242 case TextureFormat::R32G32B32:
243 case TextureFormat::R32_B24G8: 243 case TextureFormat::R32_B24G8:
244 case TextureFormat::B5G6R5: 244 case TextureFormat::B5G6R5:
245 case TextureFormat::B6G5R5: 245 case TextureFormat::B6G5R5:
246 case TextureFormat::BF10GF11RF11: 246 case TextureFormat::B10G11R11:
247 return std::size_t{R | G | B}; 247 return std::size_t{R | G | B};
248 case TextureFormat::R32_G32: 248 case TextureFormat::R32G32:
249 case TextureFormat::R16_G16: 249 case TextureFormat::R16G16:
250 case TextureFormat::G8R24: 250 case TextureFormat::R24G8:
251 case TextureFormat::G24R8: 251 case TextureFormat::R8G24:
252 case TextureFormat::G8R8: 252 case TextureFormat::R8G8:
253 case TextureFormat::G4R4: 253 case TextureFormat::G4R4:
254 return std::size_t{R | G}; 254 return std::size_t{R | G};
255 case TextureFormat::R32: 255 case TextureFormat::R32:
diff --git a/src/video_core/shader/decode/other.cpp b/src/video_core/shader/decode/other.cpp
index c0a8f233f..29a7cfbfe 100644
--- a/src/video_core/shader/decode/other.cpp
+++ b/src/video_core/shader/decode/other.cpp
@@ -75,8 +75,7 @@ u32 ShaderIR::DecodeOther(NodeBlock& bb, u32 pc) {
75 const Node value = [this, instr] { 75 const Node value = [this, instr] {
76 switch (instr.sys20) { 76 switch (instr.sys20) {
77 case SystemVariable::LaneId: 77 case SystemVariable::LaneId:
78 LOG_WARNING(HW_GPU, "S2R instruction with LaneId is incomplete"); 78 return Operation(OperationCode::ThreadId);
79 return Immediate(0U);
80 case SystemVariable::InvocationId: 79 case SystemVariable::InvocationId:
81 return Operation(OperationCode::InvocationId); 80 return Operation(OperationCode::InvocationId);
82 case SystemVariable::Ydirection: 81 case SystemVariable::Ydirection:
diff --git a/src/video_core/shader/decode/video.cpp b/src/video_core/shader/decode/video.cpp
index 64ba60ea2..1c0957277 100644
--- a/src/video_core/shader/decode/video.cpp
+++ b/src/video_core/shader/decode/video.cpp
@@ -91,29 +91,28 @@ u32 ShaderIR::DecodeVideo(NodeBlock& bb, u32 pc) {
91 return pc; 91 return pc;
92} 92}
93 93
94Node ShaderIR::GetVideoOperand(Node op, bool is_chunk, bool is_signed, 94Node ShaderIR::GetVideoOperand(Node op, bool is_chunk, bool is_signed, VideoType type,
95 Tegra::Shader::VideoType type, u64 byte_height) { 95 u64 byte_height) {
96 if (!is_chunk) { 96 if (!is_chunk) {
97 return BitfieldExtract(op, static_cast<u32>(byte_height * 8), 8); 97 return BitfieldExtract(op, static_cast<u32>(byte_height * 8), 8);
98 } 98 }
99 const Node zero = Immediate(0);
100 99
101 switch (type) { 100 switch (type) {
102 case Tegra::Shader::VideoType::Size16_Low: 101 case VideoType::Size16_Low:
103 return BitfieldExtract(op, 0, 16); 102 return BitfieldExtract(op, 0, 16);
104 case Tegra::Shader::VideoType::Size16_High: 103 case VideoType::Size16_High:
105 return BitfieldExtract(op, 16, 16); 104 return BitfieldExtract(op, 16, 16);
106 case Tegra::Shader::VideoType::Size32: 105 case VideoType::Size32:
107 // TODO(Rodrigo): From my hardware tests it becomes a bit "mad" when this type is used 106 // TODO(Rodrigo): From my hardware tests it becomes a bit "mad" when this type is used
108 // (1 * 1 + 0 == 0x5b800000). Until a better explanation is found: abort. 107 // (1 * 1 + 0 == 0x5b800000). Until a better explanation is found: abort.
109 UNIMPLEMENTED(); 108 UNIMPLEMENTED();
110 return zero; 109 return Immediate(0);
111 case Tegra::Shader::VideoType::Invalid: 110 case VideoType::Invalid:
112 UNREACHABLE_MSG("Invalid instruction encoding"); 111 UNREACHABLE_MSG("Invalid instruction encoding");
113 return zero; 112 return Immediate(0);
114 default: 113 default:
115 UNREACHABLE(); 114 UNREACHABLE();
116 return zero; 115 return Immediate(0);
117 } 116 }
118} 117}
119 118
diff --git a/src/video_core/shader/decode/xmad.cpp b/src/video_core/shader/decode/xmad.cpp
index c83dc6615..233b8fa42 100644
--- a/src/video_core/shader/decode/xmad.cpp
+++ b/src/video_core/shader/decode/xmad.cpp
@@ -81,20 +81,21 @@ u32 ShaderIR::DecodeXmad(NodeBlock& bb, u32 pc) {
81 SetTemporary(bb, 0, product); 81 SetTemporary(bb, 0, product);
82 product = GetTemporary(0); 82 product = GetTemporary(0);
83 83
84 const Node original_c = op_c; 84 Node original_c = op_c;
85 const Tegra::Shader::XmadMode set_mode = mode; // Workaround to clang compile error 85 const Tegra::Shader::XmadMode set_mode = mode; // Workaround to clang compile error
86 op_c = [&]() { 86 op_c = [&] {
87 switch (set_mode) { 87 switch (set_mode) {
88 case Tegra::Shader::XmadMode::None: 88 case Tegra::Shader::XmadMode::None:
89 return original_c; 89 return original_c;
90 case Tegra::Shader::XmadMode::CLo: 90 case Tegra::Shader::XmadMode::CLo:
91 return BitfieldExtract(original_c, 0, 16); 91 return BitfieldExtract(std::move(original_c), 0, 16);
92 case Tegra::Shader::XmadMode::CHi: 92 case Tegra::Shader::XmadMode::CHi:
93 return BitfieldExtract(original_c, 16, 16); 93 return BitfieldExtract(std::move(original_c), 16, 16);
94 case Tegra::Shader::XmadMode::CBcc: { 94 case Tegra::Shader::XmadMode::CBcc: {
95 const Node shifted_b = SignedOperation(OperationCode::ILogicalShiftLeft, is_signed_b, 95 Node shifted_b = SignedOperation(OperationCode::ILogicalShiftLeft, is_signed_b,
96 original_b, Immediate(16)); 96 original_b, Immediate(16));
97 return SignedOperation(OperationCode::IAdd, is_signed_c, original_c, shifted_b); 97 return SignedOperation(OperationCode::IAdd, is_signed_c, std::move(original_c),
98 std::move(shifted_b));
98 } 99 }
99 case Tegra::Shader::XmadMode::CSfu: { 100 case Tegra::Shader::XmadMode::CSfu: {
100 const Node comp_a = 101 const Node comp_a =
diff --git a/src/video_core/shader/shader_ir.cpp b/src/video_core/shader/shader_ir.cpp
index e322c3402..29d794b34 100644
--- a/src/video_core/shader/shader_ir.cpp
+++ b/src/video_core/shader/shader_ir.cpp
@@ -112,9 +112,9 @@ Node ShaderIR::GetOutputAttribute(Attribute::Index index, u64 element, Node buff
112} 112}
113 113
114Node ShaderIR::GetInternalFlag(InternalFlag flag, bool negated) const { 114Node ShaderIR::GetInternalFlag(InternalFlag flag, bool negated) const {
115 const Node node = MakeNode<InternalFlagNode>(flag); 115 Node node = MakeNode<InternalFlagNode>(flag);
116 if (negated) { 116 if (negated) {
117 return Operation(OperationCode::LogicalNegate, node); 117 return Operation(OperationCode::LogicalNegate, std::move(node));
118 } 118 }
119 return node; 119 return node;
120} 120}
diff --git a/src/video_core/shader_cache.h b/src/video_core/shader_cache.h
index b7608fc7b..015a789d6 100644
--- a/src/video_core/shader_cache.h
+++ b/src/video_core/shader_cache.h
@@ -209,11 +209,11 @@ private:
209 } 209 }
210 210
211 // Remove them from the cache 211 // Remove them from the cache
212 const auto is_removed = [&removed_shaders](std::unique_ptr<T>& shader) { 212 const auto is_removed = [&removed_shaders](const std::unique_ptr<T>& shader) {
213 return std::find(removed_shaders.begin(), removed_shaders.end(), shader.get()) != 213 return std::find(removed_shaders.begin(), removed_shaders.end(), shader.get()) !=
214 removed_shaders.end(); 214 removed_shaders.end();
215 }; 215 };
216 storage.erase(std::remove_if(storage.begin(), storage.end(), is_removed), storage.end()); 216 std::erase_if(storage, is_removed);
217 } 217 }
218 218
219 /// @brief Creates a new entry in the lookup cache and returns its pointer 219 /// @brief Creates a new entry in the lookup cache and returns its pointer
diff --git a/src/video_core/shader_notify.cpp b/src/video_core/shader_notify.cpp
new file mode 100644
index 000000000..c3c71657d
--- /dev/null
+++ b/src/video_core/shader_notify.cpp
@@ -0,0 +1,42 @@
1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "video_core/shader_notify.h"
6
7using namespace std::chrono_literals;
8
9namespace VideoCore {
10namespace {
11constexpr auto UPDATE_TICK = 32ms;
12}
13
14ShaderNotify::ShaderNotify() = default;
15ShaderNotify::~ShaderNotify() = default;
16
17std::size_t ShaderNotify::GetShadersBuilding() {
18 const auto now = std::chrono::high_resolution_clock::now();
19 const auto diff = now - last_update;
20 if (diff > UPDATE_TICK) {
21 std::shared_lock lock(mutex);
22 last_updated_count = accurate_count;
23 }
24 return last_updated_count;
25}
26
27std::size_t ShaderNotify::GetShadersBuildingAccurate() {
28 std::shared_lock lock{mutex};
29 return accurate_count;
30}
31
32void ShaderNotify::MarkShaderComplete() {
33 std::unique_lock lock{mutex};
34 accurate_count--;
35}
36
37void ShaderNotify::MarkSharderBuilding() {
38 std::unique_lock lock{mutex};
39 accurate_count++;
40}
41
42} // namespace VideoCore
diff --git a/src/video_core/shader_notify.h b/src/video_core/shader_notify.h
new file mode 100644
index 000000000..a9c92d179
--- /dev/null
+++ b/src/video_core/shader_notify.h
@@ -0,0 +1,29 @@
1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <chrono>
8#include <shared_mutex>
9#include "common/common_types.h"
10
11namespace VideoCore {
12class ShaderNotify {
13public:
14 ShaderNotify();
15 ~ShaderNotify();
16
17 std::size_t GetShadersBuilding();
18 std::size_t GetShadersBuildingAccurate();
19
20 void MarkShaderComplete();
21 void MarkSharderBuilding();
22
23private:
24 std::size_t last_updated_count{};
25 std::size_t accurate_count{};
26 std::shared_mutex mutex;
27 std::chrono::high_resolution_clock::time_point last_update{};
28};
29} // namespace VideoCore
diff --git a/src/video_core/surface.cpp b/src/video_core/surface.cpp
index bbe93903c..1688267bb 100644
--- a/src/video_core/surface.cpp
+++ b/src/video_core/surface.cpp
@@ -74,117 +74,131 @@ bool SurfaceTargetIsArray(SurfaceTarget target) {
74 74
75PixelFormat PixelFormatFromDepthFormat(Tegra::DepthFormat format) { 75PixelFormat PixelFormatFromDepthFormat(Tegra::DepthFormat format) {
76 switch (format) { 76 switch (format) {
77 case Tegra::DepthFormat::S8_Z24_UNORM: 77 case Tegra::DepthFormat::S8_UINT_Z24_UNORM:
78 return PixelFormat::S8Z24; 78 return PixelFormat::S8_UINT_D24_UNORM;
79 case Tegra::DepthFormat::Z24_S8_UNORM: 79 case Tegra::DepthFormat::D24S8_UNORM:
80 return PixelFormat::Z24S8; 80 return PixelFormat::D24_UNORM_S8_UINT;
81 case Tegra::DepthFormat::Z32_FLOAT: 81 case Tegra::DepthFormat::D32_FLOAT:
82 return PixelFormat::Z32F; 82 return PixelFormat::D32_FLOAT;
83 case Tegra::DepthFormat::Z16_UNORM: 83 case Tegra::DepthFormat::D16_UNORM:
84 return PixelFormat::Z16; 84 return PixelFormat::D16_UNORM;
85 case Tegra::DepthFormat::Z32_S8_X24_FLOAT: 85 case Tegra::DepthFormat::D32_FLOAT_S8X24_UINT:
86 return PixelFormat::Z32FS8; 86 return PixelFormat::D32_FLOAT_S8_UINT;
87 default: 87 default:
88 LOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format)); 88 UNIMPLEMENTED_MSG("Unimplemented format={}", static_cast<u32>(format));
89 UNREACHABLE(); 89 return PixelFormat::S8_UINT_D24_UNORM;
90 return PixelFormat::S8Z24;
91 } 90 }
92} 91}
93 92
94PixelFormat PixelFormatFromRenderTargetFormat(Tegra::RenderTargetFormat format) { 93PixelFormat PixelFormatFromRenderTargetFormat(Tegra::RenderTargetFormat format) {
95 switch (format) { 94 switch (format) {
96 case Tegra::RenderTargetFormat::RGBA8_SRGB: 95 case Tegra::RenderTargetFormat::R32B32G32A32_FLOAT:
97 return PixelFormat::RGBA8_SRGB; 96 return PixelFormat::R32G32B32A32_FLOAT;
98 case Tegra::RenderTargetFormat::RGBA8_UNORM: 97 case Tegra::RenderTargetFormat::R32G32B32A32_SINT:
99 return PixelFormat::ABGR8U; 98 return PixelFormat::R32G32B32A32_SINT;
100 case Tegra::RenderTargetFormat::RGBA8_SNORM: 99 case Tegra::RenderTargetFormat::R32G32B32A32_UINT:
101 return PixelFormat::ABGR8S; 100 return PixelFormat::R32G32B32A32_UINT;
102 case Tegra::RenderTargetFormat::RGBA8_UINT: 101 case Tegra::RenderTargetFormat::R16G16B16A16_UNORM:
103 return PixelFormat::ABGR8UI; 102 return PixelFormat::R16G16B16A16_UNORM;
104 case Tegra::RenderTargetFormat::BGRA8_SRGB: 103 case Tegra::RenderTargetFormat::R16G16B16A16_SNORM:
105 return PixelFormat::BGRA8_SRGB; 104 return PixelFormat::R16G16B16A16_SNORM;
106 case Tegra::RenderTargetFormat::BGRA8_UNORM: 105 case Tegra::RenderTargetFormat::R16G16B16A16_SINT:
107 return PixelFormat::BGRA8; 106 return PixelFormat::R16G16B16A16_SINT;
108 case Tegra::RenderTargetFormat::RGB10_A2_UNORM: 107 case Tegra::RenderTargetFormat::R16G16B16A16_UINT:
109 return PixelFormat::A2B10G10R10U; 108 return PixelFormat::R16G16B16A16_UINT;
110 case Tegra::RenderTargetFormat::RGBA16_FLOAT: 109 case Tegra::RenderTargetFormat::R16G16B16A16_FLOAT:
111 return PixelFormat::RGBA16F; 110 return PixelFormat::R16G16B16A16_FLOAT;
112 case Tegra::RenderTargetFormat::RGBA16_UNORM: 111 case Tegra::RenderTargetFormat::R32G32_FLOAT:
113 return PixelFormat::RGBA16U; 112 return PixelFormat::R32G32_FLOAT;
114 case Tegra::RenderTargetFormat::RGBA16_SNORM: 113 case Tegra::RenderTargetFormat::R32G32_SINT:
115 return PixelFormat::RGBA16S; 114 return PixelFormat::R32G32_SINT;
116 case Tegra::RenderTargetFormat::RGBA16_UINT: 115 case Tegra::RenderTargetFormat::R32G32_UINT:
117 return PixelFormat::RGBA16UI; 116 return PixelFormat::R32G32_UINT;
118 case Tegra::RenderTargetFormat::RGBA32_FLOAT: 117 case Tegra::RenderTargetFormat::R16G16B16X16_FLOAT:
119 return PixelFormat::RGBA32F; 118 return PixelFormat::R16G16B16X16_FLOAT;
120 case Tegra::RenderTargetFormat::RG32_FLOAT: 119 case Tegra::RenderTargetFormat::B8G8R8A8_UNORM:
121 return PixelFormat::RG32F; 120 return PixelFormat::B8G8R8A8_UNORM;
122 case Tegra::RenderTargetFormat::R11G11B10_FLOAT: 121 case Tegra::RenderTargetFormat::B8G8R8A8_SRGB:
123 return PixelFormat::R11FG11FB10F; 122 return PixelFormat::B8G8R8A8_SRGB;
124 case Tegra::RenderTargetFormat::B5G6R5_UNORM: 123 case Tegra::RenderTargetFormat::A2B10G10R10_UNORM:
125 return PixelFormat::B5G6R5U; 124 return PixelFormat::A2B10G10R10_UNORM;
126 case Tegra::RenderTargetFormat::BGR5A1_UNORM: 125 case Tegra::RenderTargetFormat::A2B10G10R10_UINT:
127 return PixelFormat::A1B5G5R5U; 126 return PixelFormat::A2B10G10R10_UINT;
128 case Tegra::RenderTargetFormat::RGBA32_UINT: 127 case Tegra::RenderTargetFormat::A8B8G8R8_UNORM:
129 return PixelFormat::RGBA32UI; 128 return PixelFormat::A8B8G8R8_UNORM;
130 case Tegra::RenderTargetFormat::R8_UNORM: 129 case Tegra::RenderTargetFormat::A8B8G8R8_SRGB:
131 return PixelFormat::R8U; 130 return PixelFormat::A8B8G8R8_SRGB;
132 case Tegra::RenderTargetFormat::R8_UINT: 131 case Tegra::RenderTargetFormat::A8B8G8R8_SNORM:
133 return PixelFormat::R8UI; 132 return PixelFormat::A8B8G8R8_SNORM;
134 case Tegra::RenderTargetFormat::RG16_FLOAT: 133 case Tegra::RenderTargetFormat::A8B8G8R8_SINT:
135 return PixelFormat::RG16F; 134 return PixelFormat::A8B8G8R8_SINT;
136 case Tegra::RenderTargetFormat::RG16_UINT: 135 case Tegra::RenderTargetFormat::A8B8G8R8_UINT:
137 return PixelFormat::RG16UI; 136 return PixelFormat::A8B8G8R8_UINT;
138 case Tegra::RenderTargetFormat::RG16_SINT: 137 case Tegra::RenderTargetFormat::R16G16_UNORM:
139 return PixelFormat::RG16I; 138 return PixelFormat::R16G16_UNORM;
140 case Tegra::RenderTargetFormat::RG16_UNORM: 139 case Tegra::RenderTargetFormat::R16G16_SNORM:
141 return PixelFormat::RG16; 140 return PixelFormat::R16G16_SNORM;
142 case Tegra::RenderTargetFormat::RG16_SNORM: 141 case Tegra::RenderTargetFormat::R16G16_SINT:
143 return PixelFormat::RG16S; 142 return PixelFormat::R16G16_SINT;
144 case Tegra::RenderTargetFormat::RG8_UNORM: 143 case Tegra::RenderTargetFormat::R16G16_UINT:
145 return PixelFormat::RG8U; 144 return PixelFormat::R16G16_UINT;
146 case Tegra::RenderTargetFormat::RG8_SNORM: 145 case Tegra::RenderTargetFormat::R16G16_FLOAT:
147 return PixelFormat::RG8S; 146 return PixelFormat::R16G16_FLOAT;
148 case Tegra::RenderTargetFormat::RG8_UINT: 147 case Tegra::RenderTargetFormat::B10G11R11_FLOAT:
149 return PixelFormat::RG8UI; 148 return PixelFormat::B10G11R11_FLOAT;
150 case Tegra::RenderTargetFormat::R16_FLOAT: 149 case Tegra::RenderTargetFormat::R32_SINT:
151 return PixelFormat::R16F; 150 return PixelFormat::R32_SINT;
151 case Tegra::RenderTargetFormat::R32_UINT:
152 return PixelFormat::R32_UINT;
153 case Tegra::RenderTargetFormat::R32_FLOAT:
154 return PixelFormat::R32_FLOAT;
155 case Tegra::RenderTargetFormat::R5G6B5_UNORM:
156 return PixelFormat::R5G6B5_UNORM;
157 case Tegra::RenderTargetFormat::A1R5G5B5_UNORM:
158 return PixelFormat::A1R5G5B5_UNORM;
159 case Tegra::RenderTargetFormat::R8G8_UNORM:
160 return PixelFormat::R8G8_UNORM;
161 case Tegra::RenderTargetFormat::R8G8_SNORM:
162 return PixelFormat::R8G8_SNORM;
163 case Tegra::RenderTargetFormat::R8G8_SINT:
164 return PixelFormat::R8G8_SINT;
165 case Tegra::RenderTargetFormat::R8G8_UINT:
166 return PixelFormat::R8G8_UINT;
152 case Tegra::RenderTargetFormat::R16_UNORM: 167 case Tegra::RenderTargetFormat::R16_UNORM:
153 return PixelFormat::R16U; 168 return PixelFormat::R16_UNORM;
154 case Tegra::RenderTargetFormat::R16_SNORM: 169 case Tegra::RenderTargetFormat::R16_SNORM:
155 return PixelFormat::R16S; 170 return PixelFormat::R16_SNORM;
156 case Tegra::RenderTargetFormat::R16_UINT:
157 return PixelFormat::R16UI;
158 case Tegra::RenderTargetFormat::R16_SINT: 171 case Tegra::RenderTargetFormat::R16_SINT:
159 return PixelFormat::R16I; 172 return PixelFormat::R16_SINT;
160 case Tegra::RenderTargetFormat::R32_FLOAT: 173 case Tegra::RenderTargetFormat::R16_UINT:
161 return PixelFormat::R32F; 174 return PixelFormat::R16_UINT;
162 case Tegra::RenderTargetFormat::R32_SINT: 175 case Tegra::RenderTargetFormat::R16_FLOAT:
163 return PixelFormat::R32I; 176 return PixelFormat::R16_FLOAT;
164 case Tegra::RenderTargetFormat::R32_UINT: 177 case Tegra::RenderTargetFormat::R8_UNORM:
165 return PixelFormat::R32UI; 178 return PixelFormat::R8_UNORM;
166 case Tegra::RenderTargetFormat::RG32_UINT: 179 case Tegra::RenderTargetFormat::R8_SNORM:
167 return PixelFormat::RG32UI; 180 return PixelFormat::R8_SNORM;
168 case Tegra::RenderTargetFormat::RGBX16_FLOAT: 181 case Tegra::RenderTargetFormat::R8_SINT:
169 return PixelFormat::RGBX16F; 182 return PixelFormat::R8_SINT;
183 case Tegra::RenderTargetFormat::R8_UINT:
184 return PixelFormat::R8_UINT;
170 default: 185 default:
171 LOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format)); 186 UNIMPLEMENTED_MSG("Unimplemented format={}", static_cast<int>(format));
172 UNREACHABLE(); 187 return PixelFormat::A8B8G8R8_UNORM;
173 return PixelFormat::RGBA8_SRGB;
174 } 188 }
175} 189}
176 190
177PixelFormat PixelFormatFromGPUPixelFormat(Tegra::FramebufferConfig::PixelFormat format) { 191PixelFormat PixelFormatFromGPUPixelFormat(Tegra::FramebufferConfig::PixelFormat format) {
178 switch (format) { 192 switch (format) {
179 case Tegra::FramebufferConfig::PixelFormat::ABGR8: 193 case Tegra::FramebufferConfig::PixelFormat::A8B8G8R8_UNORM:
180 return PixelFormat::ABGR8U; 194 return PixelFormat::A8B8G8R8_UNORM;
181 case Tegra::FramebufferConfig::PixelFormat::RGB565: 195 case Tegra::FramebufferConfig::PixelFormat::RGB565_UNORM:
182 return PixelFormat::B5G6R5U; 196 return PixelFormat::R5G6B5_UNORM;
183 case Tegra::FramebufferConfig::PixelFormat::BGRA8: 197 case Tegra::FramebufferConfig::PixelFormat::B8G8R8A8_UNORM:
184 return PixelFormat::BGRA8; 198 return PixelFormat::B8G8R8A8_UNORM;
185 default: 199 default:
186 UNIMPLEMENTED_MSG("Unimplemented format={}", static_cast<u32>(format)); 200 UNIMPLEMENTED_MSG("Unimplemented format={}", static_cast<u32>(format));
187 return PixelFormat::ABGR8U; 201 return PixelFormat::A8B8G8R8_UNORM;
188 } 202 }
189} 203}
190 204
@@ -212,27 +226,27 @@ SurfaceType GetFormatType(PixelFormat pixel_format) {
212 226
213bool IsPixelFormatASTC(PixelFormat format) { 227bool IsPixelFormatASTC(PixelFormat format) {
214 switch (format) { 228 switch (format) {
215 case PixelFormat::ASTC_2D_4X4: 229 case PixelFormat::ASTC_2D_4X4_UNORM:
216 case PixelFormat::ASTC_2D_5X4: 230 case PixelFormat::ASTC_2D_5X4_UNORM:
217 case PixelFormat::ASTC_2D_5X5: 231 case PixelFormat::ASTC_2D_5X5_UNORM:
218 case PixelFormat::ASTC_2D_8X8: 232 case PixelFormat::ASTC_2D_8X8_UNORM:
219 case PixelFormat::ASTC_2D_8X5: 233 case PixelFormat::ASTC_2D_8X5_UNORM:
220 case PixelFormat::ASTC_2D_4X4_SRGB: 234 case PixelFormat::ASTC_2D_4X4_SRGB:
221 case PixelFormat::ASTC_2D_5X4_SRGB: 235 case PixelFormat::ASTC_2D_5X4_SRGB:
222 case PixelFormat::ASTC_2D_5X5_SRGB: 236 case PixelFormat::ASTC_2D_5X5_SRGB:
223 case PixelFormat::ASTC_2D_8X8_SRGB: 237 case PixelFormat::ASTC_2D_8X8_SRGB:
224 case PixelFormat::ASTC_2D_8X5_SRGB: 238 case PixelFormat::ASTC_2D_8X5_SRGB:
225 case PixelFormat::ASTC_2D_10X8: 239 case PixelFormat::ASTC_2D_10X8_UNORM:
226 case PixelFormat::ASTC_2D_10X8_SRGB: 240 case PixelFormat::ASTC_2D_10X8_SRGB:
227 case PixelFormat::ASTC_2D_6X6: 241 case PixelFormat::ASTC_2D_6X6_UNORM:
228 case PixelFormat::ASTC_2D_6X6_SRGB: 242 case PixelFormat::ASTC_2D_6X6_SRGB:
229 case PixelFormat::ASTC_2D_10X10: 243 case PixelFormat::ASTC_2D_10X10_UNORM:
230 case PixelFormat::ASTC_2D_10X10_SRGB: 244 case PixelFormat::ASTC_2D_10X10_SRGB:
231 case PixelFormat::ASTC_2D_12X12: 245 case PixelFormat::ASTC_2D_12X12_UNORM:
232 case PixelFormat::ASTC_2D_12X12_SRGB: 246 case PixelFormat::ASTC_2D_12X12_SRGB:
233 case PixelFormat::ASTC_2D_8X6: 247 case PixelFormat::ASTC_2D_8X6_UNORM:
234 case PixelFormat::ASTC_2D_8X6_SRGB: 248 case PixelFormat::ASTC_2D_8X6_SRGB:
235 case PixelFormat::ASTC_2D_6X5: 249 case PixelFormat::ASTC_2D_6X5_UNORM:
236 case PixelFormat::ASTC_2D_6X5_SRGB: 250 case PixelFormat::ASTC_2D_6X5_SRGB:
237 return true; 251 return true;
238 default: 252 default:
@@ -242,12 +256,12 @@ bool IsPixelFormatASTC(PixelFormat format) {
242 256
243bool IsPixelFormatSRGB(PixelFormat format) { 257bool IsPixelFormatSRGB(PixelFormat format) {
244 switch (format) { 258 switch (format) {
245 case PixelFormat::RGBA8_SRGB: 259 case PixelFormat::A8B8G8R8_SRGB:
246 case PixelFormat::BGRA8_SRGB: 260 case PixelFormat::B8G8R8A8_SRGB:
247 case PixelFormat::DXT1_SRGB: 261 case PixelFormat::BC1_RGBA_SRGB:
248 case PixelFormat::DXT23_SRGB: 262 case PixelFormat::BC2_SRGB:
249 case PixelFormat::DXT45_SRGB: 263 case PixelFormat::BC3_SRGB:
250 case PixelFormat::BC7U_SRGB: 264 case PixelFormat::BC7_SRGB:
251 case PixelFormat::ASTC_2D_4X4_SRGB: 265 case PixelFormat::ASTC_2D_4X4_SRGB:
252 case PixelFormat::ASTC_2D_8X8_SRGB: 266 case PixelFormat::ASTC_2D_8X8_SRGB:
253 case PixelFormat::ASTC_2D_8X5_SRGB: 267 case PixelFormat::ASTC_2D_8X5_SRGB:
@@ -269,25 +283,4 @@ std::pair<u32, u32> GetASTCBlockSize(PixelFormat format) {
269 return {GetDefaultBlockWidth(format), GetDefaultBlockHeight(format)}; 283 return {GetDefaultBlockWidth(format), GetDefaultBlockHeight(format)};
270} 284}
271 285
272bool IsFormatBCn(PixelFormat format) {
273 switch (format) {
274 case PixelFormat::DXT1:
275 case PixelFormat::DXT23:
276 case PixelFormat::DXT45:
277 case PixelFormat::DXN1:
278 case PixelFormat::DXN2SNORM:
279 case PixelFormat::DXN2UNORM:
280 case PixelFormat::BC7U:
281 case PixelFormat::BC6H_UF16:
282 case PixelFormat::BC6H_SF16:
283 case PixelFormat::DXT1_SRGB:
284 case PixelFormat::DXT23_SRGB:
285 case PixelFormat::DXT45_SRGB:
286 case PixelFormat::BC7U_SRGB:
287 return true;
288 default:
289 return false;
290 }
291}
292
293} // namespace VideoCore::Surface 286} // namespace VideoCore::Surface
diff --git a/src/video_core/surface.h b/src/video_core/surface.h
index 6da6a1b97..cfd12fa61 100644
--- a/src/video_core/surface.h
+++ b/src/video_core/surface.h
@@ -15,94 +15,105 @@
15namespace VideoCore::Surface { 15namespace VideoCore::Surface {
16 16
17enum class PixelFormat { 17enum class PixelFormat {
18 ABGR8U = 0, 18 A8B8G8R8_UNORM,
19 ABGR8S = 1, 19 A8B8G8R8_SNORM,
20 ABGR8UI = 2, 20 A8B8G8R8_SINT,
21 B5G6R5U = 3, 21 A8B8G8R8_UINT,
22 A2B10G10R10U = 4, 22 R5G6B5_UNORM,
23 A1B5G5R5U = 5, 23 B5G6R5_UNORM,
24 R8U = 6, 24 A1R5G5B5_UNORM,
25 R8UI = 7, 25 A2B10G10R10_UNORM,
26 RGBA16F = 8, 26 A2B10G10R10_UINT,
27 RGBA16U = 9, 27 A1B5G5R5_UNORM,
28 RGBA16S = 10, 28 R8_UNORM,
29 RGBA16UI = 11, 29 R8_SNORM,
30 R11FG11FB10F = 12, 30 R8_SINT,
31 RGBA32UI = 13, 31 R8_UINT,
32 DXT1 = 14, 32 R16G16B16A16_FLOAT,
33 DXT23 = 15, 33 R16G16B16A16_UNORM,
34 DXT45 = 16, 34 R16G16B16A16_SNORM,
35 DXN1 = 17, // This is also known as BC4 35 R16G16B16A16_SINT,
36 DXN2UNORM = 18, 36 R16G16B16A16_UINT,
37 DXN2SNORM = 19, 37 B10G11R11_FLOAT,
38 BC7U = 20, 38 R32G32B32A32_UINT,
39 BC6H_UF16 = 21, 39 BC1_RGBA_UNORM,
40 BC6H_SF16 = 22, 40 BC2_UNORM,
41 ASTC_2D_4X4 = 23, 41 BC3_UNORM,
42 BGRA8 = 24, 42 BC4_UNORM,
43 RGBA32F = 25, 43 BC4_SNORM,
44 RG32F = 26, 44 BC5_UNORM,
45 R32F = 27, 45 BC5_SNORM,
46 R16F = 28, 46 BC7_UNORM,
47 R16U = 29, 47 BC6H_UFLOAT,
48 R16S = 30, 48 BC6H_SFLOAT,
49 R16UI = 31, 49 ASTC_2D_4X4_UNORM,
50 R16I = 32, 50 B8G8R8A8_UNORM,
51 RG16 = 33, 51 R32G32B32A32_FLOAT,
52 RG16F = 34, 52 R32G32B32A32_SINT,
53 RG16UI = 35, 53 R32G32_FLOAT,
54 RG16I = 36, 54 R32G32_SINT,
55 RG16S = 37, 55 R32_FLOAT,
56 RGB32F = 38, 56 R16_FLOAT,
57 RGBA8_SRGB = 39, 57 R16_UNORM,
58 RG8U = 40, 58 R16_SNORM,
59 RG8S = 41, 59 R16_UINT,
60 RG8UI = 42, 60 R16_SINT,
61 RG32UI = 43, 61 R16G16_UNORM,
62 RGBX16F = 44, 62 R16G16_FLOAT,
63 R32UI = 45, 63 R16G16_UINT,
64 R32I = 46, 64 R16G16_SINT,
65 ASTC_2D_8X8 = 47, 65 R16G16_SNORM,
66 ASTC_2D_8X5 = 48, 66 R32G32B32_FLOAT,
67 ASTC_2D_5X4 = 49, 67 A8B8G8R8_SRGB,
68 BGRA8_SRGB = 50, 68 R8G8_UNORM,
69 DXT1_SRGB = 51, 69 R8G8_SNORM,
70 DXT23_SRGB = 52, 70 R8G8_SINT,
71 DXT45_SRGB = 53, 71 R8G8_UINT,
72 BC7U_SRGB = 54, 72 R32G32_UINT,
73 R4G4B4A4U = 55, 73 R16G16B16X16_FLOAT,
74 ASTC_2D_4X4_SRGB = 56, 74 R32_UINT,
75 ASTC_2D_8X8_SRGB = 57, 75 R32_SINT,
76 ASTC_2D_8X5_SRGB = 58, 76 ASTC_2D_8X8_UNORM,
77 ASTC_2D_5X4_SRGB = 59, 77 ASTC_2D_8X5_UNORM,
78 ASTC_2D_5X5 = 60, 78 ASTC_2D_5X4_UNORM,
79 ASTC_2D_5X5_SRGB = 61, 79 B8G8R8A8_SRGB,
80 ASTC_2D_10X8 = 62, 80 BC1_RGBA_SRGB,
81 ASTC_2D_10X8_SRGB = 63, 81 BC2_SRGB,
82 ASTC_2D_6X6 = 64, 82 BC3_SRGB,
83 ASTC_2D_6X6_SRGB = 65, 83 BC7_SRGB,
84 ASTC_2D_10X10 = 66, 84 A4B4G4R4_UNORM,
85 ASTC_2D_10X10_SRGB = 67, 85 ASTC_2D_4X4_SRGB,
86 ASTC_2D_12X12 = 68, 86 ASTC_2D_8X8_SRGB,
87 ASTC_2D_12X12_SRGB = 69, 87 ASTC_2D_8X5_SRGB,
88 ASTC_2D_8X6 = 70, 88 ASTC_2D_5X4_SRGB,
89 ASTC_2D_8X6_SRGB = 71, 89 ASTC_2D_5X5_UNORM,
90 ASTC_2D_6X5 = 72, 90 ASTC_2D_5X5_SRGB,
91 ASTC_2D_6X5_SRGB = 73, 91 ASTC_2D_10X8_UNORM,
92 E5B9G9R9F = 74, 92 ASTC_2D_10X8_SRGB,
93 ASTC_2D_6X6_UNORM,
94 ASTC_2D_6X6_SRGB,
95 ASTC_2D_10X10_UNORM,
96 ASTC_2D_10X10_SRGB,
97 ASTC_2D_12X12_UNORM,
98 ASTC_2D_12X12_SRGB,
99 ASTC_2D_8X6_UNORM,
100 ASTC_2D_8X6_SRGB,
101 ASTC_2D_6X5_UNORM,
102 ASTC_2D_6X5_SRGB,
103 E5B9G9R9_FLOAT,
93 104
94 MaxColorFormat, 105 MaxColorFormat,
95 106
96 // Depth formats 107 // Depth formats
97 Z32F = 75, 108 D32_FLOAT = MaxColorFormat,
98 Z16 = 76, 109 D16_UNORM,
99 110
100 MaxDepthFormat, 111 MaxDepthFormat,
101 112
102 // DepthStencil formats 113 // DepthStencil formats
103 Z24S8 = 77, 114 D24_UNORM_S8_UINT = MaxDepthFormat,
104 S8Z24 = 78, 115 S8_UINT_D24_UNORM,
105 Z32FS8 = 79, 116 D32_FLOAT_S8_UINT,
106 117
107 MaxDepthStencilFormat, 118 MaxDepthStencilFormat,
108 119
@@ -130,86 +141,97 @@ enum class SurfaceTarget {
130}; 141};
131 142
132constexpr std::array<u32, MaxPixelFormat> compression_factor_shift_table = {{ 143constexpr std::array<u32, MaxPixelFormat> compression_factor_shift_table = {{
133 0, // ABGR8U 144 0, // A8B8G8R8_UNORM
134 0, // ABGR8S 145 0, // A8B8G8R8_SNORM
135 0, // ABGR8UI 146 0, // A8B8G8R8_SINT
136 0, // B5G6R5U 147 0, // A8B8G8R8_UINT
137 0, // A2B10G10R10U 148 0, // R5G6B5_UNORM
138 0, // A1B5G5R5U 149 0, // B5G6R5_UNORM
139 0, // R8U 150 0, // A1R5G5B5_UNORM
140 0, // R8UI 151 0, // A2B10G10R10_UNORM
141 0, // RGBA16F 152 0, // A2B10G10R10_UINT
142 0, // RGBA16U 153 0, // A1B5G5R5_UNORM
143 0, // RGBA16S 154 0, // R8_UNORM
144 0, // RGBA16UI 155 0, // R8_SNORM
145 0, // R11FG11FB10F 156 0, // R8_SINT
146 0, // RGBA32UI 157 0, // R8_UINT
147 2, // DXT1 158 0, // R16G16B16A16_FLOAT
148 2, // DXT23 159 0, // R16G16B16A16_UNORM
149 2, // DXT45 160 0, // R16G16B16A16_SNORM
150 2, // DXN1 161 0, // R16G16B16A16_SINT
151 2, // DXN2UNORM 162 0, // R16G16B16A16_UINT
152 2, // DXN2SNORM 163 0, // B10G11R11_FLOAT
153 2, // BC7U 164 0, // R32G32B32A32_UINT
154 2, // BC6H_UF16 165 2, // BC1_RGBA_UNORM
155 2, // BC6H_SF16 166 2, // BC2_UNORM
156 2, // ASTC_2D_4X4 167 2, // BC3_UNORM
157 0, // BGRA8 168 2, // BC4_UNORM
158 0, // RGBA32F 169 2, // BC4_SNORM
159 0, // RG32F 170 2, // BC5_UNORM
160 0, // R32F 171 2, // BC5_SNORM
161 0, // R16F 172 2, // BC7_UNORM
162 0, // R16U 173 2, // BC6H_UFLOAT
163 0, // R16S 174 2, // BC6H_SFLOAT
164 0, // R16UI 175 2, // ASTC_2D_4X4_UNORM
165 0, // R16I 176 0, // B8G8R8A8_UNORM
166 0, // RG16 177 0, // R32G32B32A32_FLOAT
167 0, // RG16F 178 0, // R32G32B32A32_SINT
168 0, // RG16UI 179 0, // R32G32_FLOAT
169 0, // RG16I 180 0, // R32G32_SINT
170 0, // RG16S 181 0, // R32_FLOAT
171 0, // RGB32F 182 0, // R16_FLOAT
172 0, // RGBA8_SRGB 183 0, // R16_UNORM
173 0, // RG8U 184 0, // R16_SNORM
174 0, // RG8S 185 0, // R16_UINT
175 0, // RG8UI 186 0, // R16_SINT
176 0, // RG32UI 187 0, // R16G16_UNORM
177 0, // RGBX16F 188 0, // R16G16_FLOAT
178 0, // R32UI 189 0, // R16G16_UINT
179 0, // R32I 190 0, // R16G16_SINT
180 2, // ASTC_2D_8X8 191 0, // R16G16_SNORM
181 2, // ASTC_2D_8X5 192 0, // R32G32B32_FLOAT
182 2, // ASTC_2D_5X4 193 0, // A8B8G8R8_SRGB
183 0, // BGRA8_SRGB 194 0, // R8G8_UNORM
184 2, // DXT1_SRGB 195 0, // R8G8_SNORM
185 2, // DXT23_SRGB 196 0, // R8G8_SINT
186 2, // DXT45_SRGB 197 0, // R8G8_UINT
187 2, // BC7U_SRGB 198 0, // R32G32_UINT
188 0, // R4G4B4A4U 199 0, // R16G16B16X16_FLOAT
200 0, // R32_UINT
201 0, // R32_SINT
202 2, // ASTC_2D_8X8_UNORM
203 2, // ASTC_2D_8X5_UNORM
204 2, // ASTC_2D_5X4_UNORM
205 0, // B8G8R8A8_SRGB
206 2, // BC1_RGBA_SRGB
207 2, // BC2_SRGB
208 2, // BC3_SRGB
209 2, // BC7_SRGB
210 0, // A4B4G4R4_UNORM
189 2, // ASTC_2D_4X4_SRGB 211 2, // ASTC_2D_4X4_SRGB
190 2, // ASTC_2D_8X8_SRGB 212 2, // ASTC_2D_8X8_SRGB
191 2, // ASTC_2D_8X5_SRGB 213 2, // ASTC_2D_8X5_SRGB
192 2, // ASTC_2D_5X4_SRGB 214 2, // ASTC_2D_5X4_SRGB
193 2, // ASTC_2D_5X5 215 2, // ASTC_2D_5X5_UNORM
194 2, // ASTC_2D_5X5_SRGB 216 2, // ASTC_2D_5X5_SRGB
195 2, // ASTC_2D_10X8 217 2, // ASTC_2D_10X8_UNORM
196 2, // ASTC_2D_10X8_SRGB 218 2, // ASTC_2D_10X8_SRGB
197 2, // ASTC_2D_6X6 219 2, // ASTC_2D_6X6_UNORM
198 2, // ASTC_2D_6X6_SRGB 220 2, // ASTC_2D_6X6_SRGB
199 2, // ASTC_2D_10X10 221 2, // ASTC_2D_10X10_UNORM
200 2, // ASTC_2D_10X10_SRGB 222 2, // ASTC_2D_10X10_SRGB
201 2, // ASTC_2D_12X12 223 2, // ASTC_2D_12X12_UNORM
202 2, // ASTC_2D_12X12_SRGB 224 2, // ASTC_2D_12X12_SRGB
203 2, // ASTC_2D_8X6 225 2, // ASTC_2D_8X6_UNORM
204 2, // ASTC_2D_8X6_SRGB 226 2, // ASTC_2D_8X6_SRGB
205 2, // ASTC_2D_6X5 227 2, // ASTC_2D_6X5_UNORM
206 2, // ASTC_2D_6X5_SRGB 228 2, // ASTC_2D_6X5_SRGB
207 0, // E5B9G9R9F 229 0, // E5B9G9R9_FLOAT
208 0, // Z32F 230 0, // D32_FLOAT
209 0, // Z16 231 0, // D16_UNORM
210 0, // Z24S8 232 0, // D24_UNORM_S8_UINT
211 0, // S8Z24 233 0, // S8_UINT_D24_UNORM
212 0, // Z32FS8 234 0, // D32_FLOAT_S8_UINT
213}}; 235}};
214 236
215/** 237/**
@@ -229,86 +251,97 @@ inline constexpr u32 GetCompressionFactor(PixelFormat format) {
229} 251}
230 252
231constexpr std::array<u32, MaxPixelFormat> block_width_table = {{ 253constexpr std::array<u32, MaxPixelFormat> block_width_table = {{
232 1, // ABGR8U 254 1, // A8B8G8R8_UNORM
233 1, // ABGR8S 255 1, // A8B8G8R8_SNORM
234 1, // ABGR8UI 256 1, // A8B8G8R8_SINT
235 1, // B5G6R5U 257 1, // A8B8G8R8_UINT
236 1, // A2B10G10R10U 258 1, // R5G6B5_UNORM
237 1, // A1B5G5R5U 259 1, // B5G6R5_UNORM
238 1, // R8U 260 1, // A1R5G5B5_UNORM
239 1, // R8UI 261 1, // A2B10G10R10_UNORM
240 1, // RGBA16F 262 1, // A2B10G10R10_UINT
241 1, // RGBA16U 263 1, // A1B5G5R5_UNORM
242 1, // RGBA16S 264 1, // R8_UNORM
243 1, // RGBA16UI 265 1, // R8_SNORM
244 1, // R11FG11FB10F 266 1, // R8_SINT
245 1, // RGBA32UI 267 1, // R8_UINT
246 4, // DXT1 268 1, // R16G16B16A16_FLOAT
247 4, // DXT23 269 1, // R16G16B16A16_UNORM
248 4, // DXT45 270 1, // R16G16B16A16_SNORM
249 4, // DXN1 271 1, // R16G16B16A16_SINT
250 4, // DXN2UNORM 272 1, // R16G16B16A16_UINT
251 4, // DXN2SNORM 273 1, // B10G11R11_FLOAT
252 4, // BC7U 274 1, // R32G32B32A32_UINT
253 4, // BC6H_UF16 275 4, // BC1_RGBA_UNORM
254 4, // BC6H_SF16 276 4, // BC2_UNORM
255 4, // ASTC_2D_4X4 277 4, // BC3_UNORM
256 1, // BGRA8 278 4, // BC4_UNORM
257 1, // RGBA32F 279 4, // BC4_SNORM
258 1, // RG32F 280 4, // BC5_UNORM
259 1, // R32F 281 4, // BC5_SNORM
260 1, // R16F 282 4, // BC7_UNORM
261 1, // R16U 283 4, // BC6H_UFLOAT
262 1, // R16S 284 4, // BC6H_SFLOAT
263 1, // R16UI 285 4, // ASTC_2D_4X4_UNORM
264 1, // R16I 286 1, // B8G8R8A8_UNORM
265 1, // RG16 287 1, // R32G32B32A32_FLOAT
266 1, // RG16F 288 1, // R32G32B32A32_SINT
267 1, // RG16UI 289 1, // R32G32_FLOAT
268 1, // RG16I 290 1, // R32G32_SINT
269 1, // RG16S 291 1, // R32_FLOAT
270 1, // RGB32F 292 1, // R16_FLOAT
271 1, // RGBA8_SRGB 293 1, // R16_UNORM
272 1, // RG8U 294 1, // R16_SNORM
273 1, // RG8S 295 1, // R16_UINT
274 1, // RG8UI 296 1, // R16_SINT
275 1, // RG32UI 297 1, // R16G16_UNORM
276 1, // RGBX16F 298 1, // R16G16_FLOAT
277 1, // R32UI 299 1, // R16G16_UINT
278 1, // R32I 300 1, // R16G16_SINT
279 8, // ASTC_2D_8X8 301 1, // R16G16_SNORM
280 8, // ASTC_2D_8X5 302 1, // R32G32B32_FLOAT
281 5, // ASTC_2D_5X4 303 1, // A8B8G8R8_SRGB
282 1, // BGRA8_SRGB 304 1, // R8G8_UNORM
283 4, // DXT1_SRGB 305 1, // R8G8_SNORM
284 4, // DXT23_SRGB 306 1, // R8G8_SINT
285 4, // DXT45_SRGB 307 1, // R8G8_UINT
286 4, // BC7U_SRGB 308 1, // R32G32_UINT
287 1, // R4G4B4A4U 309 1, // R16G16B16X16_FLOAT
310 1, // R32_UINT
311 1, // R32_SINT
312 8, // ASTC_2D_8X8_UNORM
313 8, // ASTC_2D_8X5_UNORM
314 5, // ASTC_2D_5X4_UNORM
315 1, // B8G8R8A8_SRGB
316 4, // BC1_RGBA_SRGB
317 4, // BC2_SRGB
318 4, // BC3_SRGB
319 4, // BC7_SRGB
320 1, // A4B4G4R4_UNORM
288 4, // ASTC_2D_4X4_SRGB 321 4, // ASTC_2D_4X4_SRGB
289 8, // ASTC_2D_8X8_SRGB 322 8, // ASTC_2D_8X8_SRGB
290 8, // ASTC_2D_8X5_SRGB 323 8, // ASTC_2D_8X5_SRGB
291 5, // ASTC_2D_5X4_SRGB 324 5, // ASTC_2D_5X4_SRGB
292 5, // ASTC_2D_5X5 325 5, // ASTC_2D_5X5_UNORM
293 5, // ASTC_2D_5X5_SRGB 326 5, // ASTC_2D_5X5_SRGB
294 10, // ASTC_2D_10X8 327 10, // ASTC_2D_10X8_UNORM
295 10, // ASTC_2D_10X8_SRGB 328 10, // ASTC_2D_10X8_SRGB
296 6, // ASTC_2D_6X6 329 6, // ASTC_2D_6X6_UNORM
297 6, // ASTC_2D_6X6_SRGB 330 6, // ASTC_2D_6X6_SRGB
298 10, // ASTC_2D_10X10 331 10, // ASTC_2D_10X10_UNORM
299 10, // ASTC_2D_10X10_SRGB 332 10, // ASTC_2D_10X10_SRGB
300 12, // ASTC_2D_12X12 333 12, // ASTC_2D_12X12_UNORM
301 12, // ASTC_2D_12X12_SRGB 334 12, // ASTC_2D_12X12_SRGB
302 8, // ASTC_2D_8X6 335 8, // ASTC_2D_8X6_UNORM
303 8, // ASTC_2D_8X6_SRGB 336 8, // ASTC_2D_8X6_SRGB
304 6, // ASTC_2D_6X5 337 6, // ASTC_2D_6X5_UNORM
305 6, // ASTC_2D_6X5_SRGB 338 6, // ASTC_2D_6X5_SRGB
306 1, // E5B9G9R9F 339 1, // E5B9G9R9_FLOAT
307 1, // Z32F 340 1, // D32_FLOAT
308 1, // Z16 341 1, // D16_UNORM
309 1, // Z24S8 342 1, // D24_UNORM_S8_UINT
310 1, // S8Z24 343 1, // S8_UINT_D24_UNORM
311 1, // Z32FS8 344 1, // D32_FLOAT_S8_UINT
312}}; 345}};
313 346
314static constexpr u32 GetDefaultBlockWidth(PixelFormat format) { 347static constexpr u32 GetDefaultBlockWidth(PixelFormat format) {
@@ -320,86 +353,97 @@ static constexpr u32 GetDefaultBlockWidth(PixelFormat format) {
320} 353}
321 354
322constexpr std::array<u32, MaxPixelFormat> block_height_table = {{ 355constexpr std::array<u32, MaxPixelFormat> block_height_table = {{
323 1, // ABGR8U 356 1, // A8B8G8R8_UNORM
324 1, // ABGR8S 357 1, // A8B8G8R8_SNORM
325 1, // ABGR8UI 358 1, // A8B8G8R8_SINT
326 1, // B5G6R5U 359 1, // A8B8G8R8_UINT
327 1, // A2B10G10R10U 360 1, // R5G6B5_UNORM
328 1, // A1B5G5R5U 361 1, // B5G6R5_UNORM
329 1, // R8U 362 1, // A1R5G5B5_UNORM
330 1, // R8UI 363 1, // A2B10G10R10_UNORM
331 1, // RGBA16F 364 1, // A2B10G10R10_UINT
332 1, // RGBA16U 365 1, // A1B5G5R5_UNORM
333 1, // RGBA16S 366 1, // R8_UNORM
334 1, // RGBA16UI 367 1, // R8_SNORM
335 1, // R11FG11FB10F 368 1, // R8_SINT
336 1, // RGBA32UI 369 1, // R8_UINT
337 4, // DXT1 370 1, // R16G16B16A16_FLOAT
338 4, // DXT23 371 1, // R16G16B16A16_UNORM
339 4, // DXT45 372 1, // R16G16B16A16_SNORM
340 4, // DXN1 373 1, // R16G16B16A16_SINT
341 4, // DXN2UNORM 374 1, // R16G16B16A16_UINT
342 4, // DXN2SNORM 375 1, // B10G11R11_FLOAT
343 4, // BC7U 376 1, // R32G32B32A32_UINT
344 4, // BC6H_UF16 377 4, // BC1_RGBA_UNORM
345 4, // BC6H_SF16 378 4, // BC2_UNORM
346 4, // ASTC_2D_4X4 379 4, // BC3_UNORM
347 1, // BGRA8 380 4, // BC4_UNORM
348 1, // RGBA32F 381 4, // BC4_SNORM
349 1, // RG32F 382 4, // BC5_UNORM
350 1, // R32F 383 4, // BC5_SNORM
351 1, // R16F 384 4, // BC7_UNORM
352 1, // R16U 385 4, // BC6H_UFLOAT
353 1, // R16S 386 4, // BC6H_SFLOAT
354 1, // R16UI 387 4, // ASTC_2D_4X4_UNORM
355 1, // R16I 388 1, // B8G8R8A8_UNORM
356 1, // RG16 389 1, // R32G32B32A32_FLOAT
357 1, // RG16F 390 1, // R32G32B32A32_SINT
358 1, // RG16UI 391 1, // R32G32_FLOAT
359 1, // RG16I 392 1, // R32G32_SINT
360 1, // RG16S 393 1, // R32_FLOAT
361 1, // RGB32F 394 1, // R16_FLOAT
362 1, // RGBA8_SRGB 395 1, // R16_UNORM
363 1, // RG8U 396 1, // R16_SNORM
364 1, // RG8S 397 1, // R16_UINT
365 1, // RG8UI 398 1, // R16_SINT
366 1, // RG32UI 399 1, // R16G16_UNORM
367 1, // RGBX16F 400 1, // R16G16_FLOAT
368 1, // R32UI 401 1, // R16G16_UINT
369 1, // R32I 402 1, // R16G16_SINT
370 8, // ASTC_2D_8X8 403 1, // R16G16_SNORM
371 5, // ASTC_2D_8X5 404 1, // R32G32B32_FLOAT
372 4, // ASTC_2D_5X4 405 1, // A8B8G8R8_SRGB
373 1, // BGRA8_SRGB 406 1, // R8G8_UNORM
374 4, // DXT1_SRGB 407 1, // R8G8_SNORM
375 4, // DXT23_SRGB 408 1, // R8G8_SINT
376 4, // DXT45_SRGB 409 1, // R8G8_UINT
377 4, // BC7U_SRGB 410 1, // R32G32_UINT
378 1, // R4G4B4A4U 411 1, // R16G16B16X16_FLOAT
412 1, // R32_UINT
413 1, // R32_SINT
414 8, // ASTC_2D_8X8_UNORM
415 5, // ASTC_2D_8X5_UNORM
416 4, // ASTC_2D_5X4_UNORM
417 1, // B8G8R8A8_SRGB
418 4, // BC1_RGBA_SRGB
419 4, // BC2_SRGB
420 4, // BC3_SRGB
421 4, // BC7_SRGB
422 1, // A4B4G4R4_UNORM
379 4, // ASTC_2D_4X4_SRGB 423 4, // ASTC_2D_4X4_SRGB
380 8, // ASTC_2D_8X8_SRGB 424 8, // ASTC_2D_8X8_SRGB
381 5, // ASTC_2D_8X5_SRGB 425 5, // ASTC_2D_8X5_SRGB
382 4, // ASTC_2D_5X4_SRGB 426 4, // ASTC_2D_5X4_SRGB
383 5, // ASTC_2D_5X5 427 5, // ASTC_2D_5X5_UNORM
384 5, // ASTC_2D_5X5_SRGB 428 5, // ASTC_2D_5X5_SRGB
385 8, // ASTC_2D_10X8 429 8, // ASTC_2D_10X8_UNORM
386 8, // ASTC_2D_10X8_SRGB 430 8, // ASTC_2D_10X8_SRGB
387 6, // ASTC_2D_6X6 431 6, // ASTC_2D_6X6_UNORM
388 6, // ASTC_2D_6X6_SRGB 432 6, // ASTC_2D_6X6_SRGB
389 10, // ASTC_2D_10X10 433 10, // ASTC_2D_10X10_UNORM
390 10, // ASTC_2D_10X10_SRGB 434 10, // ASTC_2D_10X10_SRGB
391 12, // ASTC_2D_12X12 435 12, // ASTC_2D_12X12_UNORM
392 12, // ASTC_2D_12X12_SRGB 436 12, // ASTC_2D_12X12_SRGB
393 6, // ASTC_2D_8X6 437 6, // ASTC_2D_8X6_UNORM
394 6, // ASTC_2D_8X6_SRGB 438 6, // ASTC_2D_8X6_SRGB
395 5, // ASTC_2D_6X5 439 5, // ASTC_2D_6X5_UNORM
396 5, // ASTC_2D_6X5_SRGB 440 5, // ASTC_2D_6X5_SRGB
397 1, // E5B9G9R9F 441 1, // E5B9G9R9_FLOAT
398 1, // Z32F 442 1, // D32_FLOAT
399 1, // Z16 443 1, // D16_UNORM
400 1, // Z24S8 444 1, // D24_UNORM_S8_UINT
401 1, // S8Z24 445 1, // S8_UINT_D24_UNORM
402 1, // Z32FS8 446 1, // D32_FLOAT_S8_UINT
403}}; 447}};
404 448
405static constexpr u32 GetDefaultBlockHeight(PixelFormat format) { 449static constexpr u32 GetDefaultBlockHeight(PixelFormat format) {
@@ -411,86 +455,97 @@ static constexpr u32 GetDefaultBlockHeight(PixelFormat format) {
411} 455}
412 456
413constexpr std::array<u32, MaxPixelFormat> bpp_table = {{ 457constexpr std::array<u32, MaxPixelFormat> bpp_table = {{
414 32, // ABGR8U 458 32, // A8B8G8R8_UNORM
415 32, // ABGR8S 459 32, // A8B8G8R8_SNORM
416 32, // ABGR8UI 460 32, // A8B8G8R8_SINT
417 16, // B5G6R5U 461 32, // A8B8G8R8_UINT
418 32, // A2B10G10R10U 462 16, // R5G6B5_UNORM
419 16, // A1B5G5R5U 463 16, // B5G6R5_UNORM
420 8, // R8U 464 16, // A1R5G5B5_UNORM
421 8, // R8UI 465 32, // A2B10G10R10_UNORM
422 64, // RGBA16F 466 32, // A2B10G10R10_UINT
423 64, // RGBA16U 467 16, // A1B5G5R5_UNORM
424 64, // RGBA16S 468 8, // R8_UNORM
425 64, // RGBA16UI 469 8, // R8_SNORM
426 32, // R11FG11FB10F 470 8, // R8_SINT
427 128, // RGBA32UI 471 8, // R8_UINT
428 64, // DXT1 472 64, // R16G16B16A16_FLOAT
429 128, // DXT23 473 64, // R16G16B16A16_UNORM
430 128, // DXT45 474 64, // R16G16B16A16_SNORM
431 64, // DXN1 475 64, // R16G16B16A16_SINT
432 128, // DXN2UNORM 476 64, // R16G16B16A16_UINT
433 128, // DXN2SNORM 477 32, // B10G11R11_FLOAT
434 128, // BC7U 478 128, // R32G32B32A32_UINT
435 128, // BC6H_UF16 479 64, // BC1_RGBA_UNORM
436 128, // BC6H_SF16 480 128, // BC2_UNORM
437 128, // ASTC_2D_4X4 481 128, // BC3_UNORM
438 32, // BGRA8 482 64, // BC4_UNORM
439 128, // RGBA32F 483 64, // BC4_SNORM
440 64, // RG32F 484 128, // BC5_UNORM
441 32, // R32F 485 128, // BC5_SNORM
442 16, // R16F 486 128, // BC7_UNORM
443 16, // R16U 487 128, // BC6H_UFLOAT
444 16, // R16S 488 128, // BC6H_SFLOAT
445 16, // R16UI 489 128, // ASTC_2D_4X4_UNORM
446 16, // R16I 490 32, // B8G8R8A8_UNORM
447 32, // RG16 491 128, // R32G32B32A32_FLOAT
448 32, // RG16F 492 128, // R32G32B32A32_SINT
449 32, // RG16UI 493 64, // R32G32_FLOAT
450 32, // RG16I 494 64, // R32G32_SINT
451 32, // RG16S 495 32, // R32_FLOAT
452 96, // RGB32F 496 16, // R16_FLOAT
453 32, // RGBA8_SRGB 497 16, // R16_UNORM
454 16, // RG8U 498 16, // R16_SNORM
455 16, // RG8S 499 16, // R16_UINT
456 16, // RG8UI 500 16, // R16_SINT
457 64, // RG32UI 501 32, // R16G16_UNORM
458 64, // RGBX16F 502 32, // R16G16_FLOAT
459 32, // R32UI 503 32, // R16G16_UINT
460 32, // R32I 504 32, // R16G16_SINT
461 128, // ASTC_2D_8X8 505 32, // R16G16_SNORM
462 128, // ASTC_2D_8X5 506 96, // R32G32B32_FLOAT
463 128, // ASTC_2D_5X4 507 32, // A8B8G8R8_SRGB
464 32, // BGRA8_SRGB 508 16, // R8G8_UNORM
465 64, // DXT1_SRGB 509 16, // R8G8_SNORM
466 128, // DXT23_SRGB 510 16, // R8G8_SINT
467 128, // DXT45_SRGB 511 16, // R8G8_UINT
468 128, // BC7U 512 64, // R32G32_UINT
469 16, // R4G4B4A4U 513 64, // R16G16B16X16_FLOAT
514 32, // R32_UINT
515 32, // R32_SINT
516 128, // ASTC_2D_8X8_UNORM
517 128, // ASTC_2D_8X5_UNORM
518 128, // ASTC_2D_5X4_UNORM
519 32, // B8G8R8A8_SRGB
520 64, // BC1_RGBA_SRGB
521 128, // BC2_SRGB
522 128, // BC3_SRGB
523 128, // BC7_UNORM
524 16, // A4B4G4R4_UNORM
470 128, // ASTC_2D_4X4_SRGB 525 128, // ASTC_2D_4X4_SRGB
471 128, // ASTC_2D_8X8_SRGB 526 128, // ASTC_2D_8X8_SRGB
472 128, // ASTC_2D_8X5_SRGB 527 128, // ASTC_2D_8X5_SRGB
473 128, // ASTC_2D_5X4_SRGB 528 128, // ASTC_2D_5X4_SRGB
474 128, // ASTC_2D_5X5 529 128, // ASTC_2D_5X5_UNORM
475 128, // ASTC_2D_5X5_SRGB 530 128, // ASTC_2D_5X5_SRGB
476 128, // ASTC_2D_10X8 531 128, // ASTC_2D_10X8_UNORM
477 128, // ASTC_2D_10X8_SRGB 532 128, // ASTC_2D_10X8_SRGB
478 128, // ASTC_2D_6X6 533 128, // ASTC_2D_6X6_UNORM
479 128, // ASTC_2D_6X6_SRGB 534 128, // ASTC_2D_6X6_SRGB
480 128, // ASTC_2D_10X10 535 128, // ASTC_2D_10X10_UNORM
481 128, // ASTC_2D_10X10_SRGB 536 128, // ASTC_2D_10X10_SRGB
482 128, // ASTC_2D_12X12 537 128, // ASTC_2D_12X12_UNORM
483 128, // ASTC_2D_12X12_SRGB 538 128, // ASTC_2D_12X12_SRGB
484 128, // ASTC_2D_8X6 539 128, // ASTC_2D_8X6_UNORM
485 128, // ASTC_2D_8X6_SRGB 540 128, // ASTC_2D_8X6_SRGB
486 128, // ASTC_2D_6X5 541 128, // ASTC_2D_6X5_UNORM
487 128, // ASTC_2D_6X5_SRGB 542 128, // ASTC_2D_6X5_SRGB
488 32, // E5B9G9R9F 543 32, // E5B9G9R9_FLOAT
489 32, // Z32F 544 32, // D32_FLOAT
490 16, // Z16 545 16, // D16_UNORM
491 32, // Z24S8 546 32, // D24_UNORM_S8_UINT
492 32, // S8Z24 547 32, // S8_UINT_D24_UNORM
493 64, // Z32FS8 548 64, // D32_FLOAT_S8_UINT
494}}; 549}};
495 550
496static constexpr u32 GetFormatBpp(PixelFormat format) { 551static constexpr u32 GetFormatBpp(PixelFormat format) {
@@ -529,7 +584,4 @@ bool IsPixelFormatSRGB(PixelFormat format);
529 584
530std::pair<u32, u32> GetASTCBlockSize(PixelFormat format); 585std::pair<u32, u32> GetASTCBlockSize(PixelFormat format);
531 586
532/// Returns true if the specified PixelFormat is a BCn format, e.g. DXT or DXN
533bool IsFormatBCn(PixelFormat format);
534
535} // namespace VideoCore::Surface 587} // namespace VideoCore::Surface
diff --git a/src/video_core/texture_cache/format_lookup_table.cpp b/src/video_core/texture_cache/format_lookup_table.cpp
index f476f03b0..7d5a75648 100644
--- a/src/video_core/texture_cache/format_lookup_table.cpp
+++ b/src/video_core/texture_cache/format_lookup_table.cpp
@@ -19,8 +19,6 @@ constexpr auto SNORM = ComponentType::SNORM;
19constexpr auto UNORM = ComponentType::UNORM; 19constexpr auto UNORM = ComponentType::UNORM;
20constexpr auto SINT = ComponentType::SINT; 20constexpr auto SINT = ComponentType::SINT;
21constexpr auto UINT = ComponentType::UINT; 21constexpr auto UINT = ComponentType::UINT;
22constexpr auto SNORM_FORCE_FP16 = ComponentType::SNORM_FORCE_FP16;
23constexpr auto UNORM_FORCE_FP16 = ComponentType::UNORM_FORCE_FP16;
24constexpr auto FLOAT = ComponentType::FLOAT; 22constexpr auto FLOAT = ComponentType::FLOAT;
25constexpr bool C = false; // Normal color 23constexpr bool C = false; // Normal color
26constexpr bool S = true; // Srgb 24constexpr bool S = true; // Srgb
@@ -41,119 +39,126 @@ struct Table {
41 ComponentType alpha_component; 39 ComponentType alpha_component;
42 bool is_srgb; 40 bool is_srgb;
43}; 41};
44constexpr std::array<Table, 78> DefinitionTable = {{ 42constexpr std::array<Table, 86> DefinitionTable = {{
45 {TextureFormat::A8R8G8B8, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ABGR8U}, 43 {TextureFormat::A8R8G8B8, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::A8B8G8R8_UNORM},
46 {TextureFormat::A8R8G8B8, C, SNORM, SNORM, SNORM, SNORM, PixelFormat::ABGR8S}, 44 {TextureFormat::A8R8G8B8, C, SNORM, SNORM, SNORM, SNORM, PixelFormat::A8B8G8R8_SNORM},
47 {TextureFormat::A8R8G8B8, C, UINT, UINT, UINT, UINT, PixelFormat::ABGR8UI}, 45 {TextureFormat::A8R8G8B8, C, UINT, UINT, UINT, UINT, PixelFormat::A8B8G8R8_UINT},
48 {TextureFormat::A8R8G8B8, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::RGBA8_SRGB}, 46 {TextureFormat::A8R8G8B8, C, SINT, SINT, SINT, SINT, PixelFormat::A8B8G8R8_SINT},
47 {TextureFormat::A8R8G8B8, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::A8B8G8R8_SRGB},
49 48
50 {TextureFormat::B5G6R5, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::B5G6R5U}, 49 {TextureFormat::B5G6R5, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::B5G6R5_UNORM},
51 50
52 {TextureFormat::A2B10G10R10, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::A2B10G10R10U}, 51 {TextureFormat::A2B10G10R10, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::A2B10G10R10_UNORM},
52 {TextureFormat::A2B10G10R10, C, UINT, UINT, UINT, UINT, PixelFormat::A2B10G10R10_UINT},
53 53
54 {TextureFormat::A1B5G5R5, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::A1B5G5R5U}, 54 {TextureFormat::A1B5G5R5, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::A1B5G5R5_UNORM},
55 55
56 {TextureFormat::A4B4G4R4, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::R4G4B4A4U}, 56 {TextureFormat::A4B4G4R4, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::A4B4G4R4_UNORM},
57 57
58 {TextureFormat::R8, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::R8U}, 58 {TextureFormat::R8, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::R8_UNORM},
59 {TextureFormat::R8, C, UINT, UINT, UINT, UINT, PixelFormat::R8UI}, 59 {TextureFormat::R8, C, SNORM, SNORM, SNORM, SNORM, PixelFormat::R8_SNORM},
60 {TextureFormat::R8, C, UINT, UINT, UINT, UINT, PixelFormat::R8_UINT},
61 {TextureFormat::R8, C, SINT, SINT, SINT, SINT, PixelFormat::R8_SINT},
60 62
61 {TextureFormat::G8R8, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::RG8U}, 63 {TextureFormat::R8G8, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::R8G8_UNORM},
62 {TextureFormat::G8R8, C, SNORM, SNORM, SNORM, SNORM, PixelFormat::RG8S}, 64 {TextureFormat::R8G8, C, SNORM, SNORM, SNORM, SNORM, PixelFormat::R8G8_SNORM},
63 {TextureFormat::G8R8, C, UINT, UINT, UINT, UINT, PixelFormat::RG8UI}, 65 {TextureFormat::R8G8, C, UINT, UINT, UINT, UINT, PixelFormat::R8G8_UINT},
66 {TextureFormat::R8G8, C, SINT, SINT, SINT, SINT, PixelFormat::R8G8_SINT},
64 67
65 {TextureFormat::R16_G16_B16_A16, C, SNORM, SNORM, SNORM, SNORM, PixelFormat::RGBA16S}, 68 {TextureFormat::R16G16B16A16, C, SNORM, SNORM, SNORM, SNORM, PixelFormat::R16G16B16A16_SNORM},
66 {TextureFormat::R16_G16_B16_A16, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::RGBA16U}, 69 {TextureFormat::R16G16B16A16, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::R16G16B16A16_UNORM},
67 {TextureFormat::R16_G16_B16_A16, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::RGBA16F}, 70 {TextureFormat::R16G16B16A16, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::R16G16B16A16_FLOAT},
68 {TextureFormat::R16_G16_B16_A16, C, UINT, UINT, UINT, UINT, PixelFormat::RGBA16UI}, 71 {TextureFormat::R16G16B16A16, C, UINT, UINT, UINT, UINT, PixelFormat::R16G16B16A16_UINT},
72 {TextureFormat::R16G16B16A16, C, SINT, SINT, SINT, SINT, PixelFormat::R16G16B16A16_SINT},
69 73
70 {TextureFormat::R16_G16, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::RG16F}, 74 {TextureFormat::R16G16, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::R16G16_FLOAT},
71 {TextureFormat::R16_G16, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::RG16}, 75 {TextureFormat::R16G16, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::R16G16_UNORM},
72 {TextureFormat::R16_G16, C, SNORM, SNORM, SNORM, SNORM, PixelFormat::RG16S}, 76 {TextureFormat::R16G16, C, SNORM, SNORM, SNORM, SNORM, PixelFormat::R16G16_SNORM},
73 {TextureFormat::R16_G16, C, UINT, UINT, UINT, UINT, PixelFormat::RG16UI}, 77 {TextureFormat::R16G16, C, UINT, UINT, UINT, UINT, PixelFormat::R16G16_UINT},
74 {TextureFormat::R16_G16, C, SINT, SINT, SINT, SINT, PixelFormat::RG16I}, 78 {TextureFormat::R16G16, C, SINT, SINT, SINT, SINT, PixelFormat::R16G16_SINT},
75 79
76 {TextureFormat::R16, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::R16F}, 80 {TextureFormat::R16, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::R16_FLOAT},
77 {TextureFormat::R16, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::R16U}, 81 {TextureFormat::R16, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::R16_UNORM},
78 {TextureFormat::R16, C, SNORM, SNORM, SNORM, SNORM, PixelFormat::R16S}, 82 {TextureFormat::R16, C, SNORM, SNORM, SNORM, SNORM, PixelFormat::R16_SNORM},
79 {TextureFormat::R16, C, UINT, UINT, UINT, UINT, PixelFormat::R16UI}, 83 {TextureFormat::R16, C, UINT, UINT, UINT, UINT, PixelFormat::R16_UINT},
80 {TextureFormat::R16, C, SINT, SINT, SINT, SINT, PixelFormat::R16I}, 84 {TextureFormat::R16, C, SINT, SINT, SINT, SINT, PixelFormat::R16_SINT},
81 85
82 {TextureFormat::BF10GF11RF11, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::R11FG11FB10F}, 86 {TextureFormat::B10G11R11, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::B10G11R11_FLOAT},
83 87
84 {TextureFormat::R32_G32_B32_A32, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::RGBA32F}, 88 {TextureFormat::R32G32B32A32, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::R32G32B32A32_FLOAT},
85 {TextureFormat::R32_G32_B32_A32, C, UINT, UINT, UINT, UINT, PixelFormat::RGBA32UI}, 89 {TextureFormat::R32G32B32A32, C, UINT, UINT, UINT, UINT, PixelFormat::R32G32B32A32_UINT},
90 {TextureFormat::R32G32B32A32, C, SINT, SINT, SINT, SINT, PixelFormat::R32G32B32A32_SINT},
86 91
87 {TextureFormat::R32_G32_B32, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::RGB32F}, 92 {TextureFormat::R32G32B32, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::R32G32B32_FLOAT},
88 93
89 {TextureFormat::R32_G32, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::RG32F}, 94 {TextureFormat::R32G32, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::R32G32_FLOAT},
90 {TextureFormat::R32_G32, C, UINT, UINT, UINT, UINT, PixelFormat::RG32UI}, 95 {TextureFormat::R32G32, C, UINT, UINT, UINT, UINT, PixelFormat::R32G32_UINT},
96 {TextureFormat::R32G32, C, SINT, SINT, SINT, SINT, PixelFormat::R32G32_SINT},
91 97
92 {TextureFormat::R32, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::R32F}, 98 {TextureFormat::R32, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::R32_FLOAT},
93 {TextureFormat::R32, C, UINT, UINT, UINT, UINT, PixelFormat::R32UI}, 99 {TextureFormat::R32, C, UINT, UINT, UINT, UINT, PixelFormat::R32_UINT},
94 {TextureFormat::R32, C, SINT, SINT, SINT, SINT, PixelFormat::R32I}, 100 {TextureFormat::R32, C, SINT, SINT, SINT, SINT, PixelFormat::R32_SINT},
95 101
96 {TextureFormat::E5B9G9R9_SHAREDEXP, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::E5B9G9R9F}, 102 {TextureFormat::E5B9G9R9, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::E5B9G9R9_FLOAT},
97 103
98 {TextureFormat::ZF32, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::Z32F}, 104 {TextureFormat::D32, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::D32_FLOAT},
99 {TextureFormat::Z16, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::Z16}, 105 {TextureFormat::D16, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::D16_UNORM},
100 {TextureFormat::S8Z24, C, UINT, UNORM, UNORM, UNORM, PixelFormat::S8Z24}, 106 {TextureFormat::S8D24, C, UINT, UNORM, UNORM, UNORM, PixelFormat::S8_UINT_D24_UNORM},
101 {TextureFormat::G24R8, C, UINT, UNORM, UNORM, UNORM, PixelFormat::S8Z24}, 107 {TextureFormat::R8G24, C, UINT, UNORM, UNORM, UNORM, PixelFormat::S8_UINT_D24_UNORM},
102 {TextureFormat::ZF32_X24S8, C, FLOAT, UINT, UNORM, UNORM, PixelFormat::Z32FS8}, 108 {TextureFormat::D32S8, C, FLOAT, UINT, UNORM, UNORM, PixelFormat::D32_FLOAT_S8_UINT},
103 109
104 {TextureFormat::DXT1, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::DXT1}, 110 {TextureFormat::BC1_RGBA, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::BC1_RGBA_UNORM},
105 {TextureFormat::DXT1, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::DXT1_SRGB}, 111 {TextureFormat::BC1_RGBA, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::BC1_RGBA_SRGB},
106 112
107 {TextureFormat::DXT23, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::DXT23}, 113 {TextureFormat::BC2, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::BC2_UNORM},
108 {TextureFormat::DXT23, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::DXT23_SRGB}, 114 {TextureFormat::BC2, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::BC2_SRGB},
109 115
110 {TextureFormat::DXT45, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::DXT45}, 116 {TextureFormat::BC3, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::BC3_UNORM},
111 {TextureFormat::DXT45, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::DXT45_SRGB}, 117 {TextureFormat::BC3, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::BC3_SRGB},
112 118
113 // TODO: Use a different pixel format for SNORM 119 {TextureFormat::BC4, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::BC4_UNORM},
114 {TextureFormat::DXN1, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::DXN1}, 120 {TextureFormat::BC4, C, SNORM, SNORM, SNORM, SNORM, PixelFormat::BC4_SNORM},
115 {TextureFormat::DXN1, C, SNORM, SNORM, SNORM, SNORM, PixelFormat::DXN1},
116 121
117 {TextureFormat::DXN2, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::DXN2UNORM}, 122 {TextureFormat::BC5, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::BC5_UNORM},
118 {TextureFormat::DXN2, C, SNORM, SNORM, SNORM, SNORM, PixelFormat::DXN2SNORM}, 123 {TextureFormat::BC5, C, SNORM, SNORM, SNORM, SNORM, PixelFormat::BC5_SNORM},
119 124
120 {TextureFormat::BC7U, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::BC7U}, 125 {TextureFormat::BC7, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::BC7_UNORM},
121 {TextureFormat::BC7U, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::BC7U_SRGB}, 126 {TextureFormat::BC7, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::BC7_SRGB},
122 127
123 {TextureFormat::BC6H_SF16, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::BC6H_SF16}, 128 {TextureFormat::BC6H_SFLOAT, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::BC6H_SFLOAT},
124 {TextureFormat::BC6H_UF16, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::BC6H_UF16}, 129 {TextureFormat::BC6H_UFLOAT, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::BC6H_UFLOAT},
125 130
126 {TextureFormat::ASTC_2D_4X4, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_4X4}, 131 {TextureFormat::ASTC_2D_4X4, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_4X4_UNORM},
127 {TextureFormat::ASTC_2D_4X4, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_4X4_SRGB}, 132 {TextureFormat::ASTC_2D_4X4, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_4X4_SRGB},
128 133
129 {TextureFormat::ASTC_2D_5X4, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_5X4}, 134 {TextureFormat::ASTC_2D_5X4, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_5X4_UNORM},
130 {TextureFormat::ASTC_2D_5X4, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_5X4_SRGB}, 135 {TextureFormat::ASTC_2D_5X4, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_5X4_SRGB},
131 136
132 {TextureFormat::ASTC_2D_5X5, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_5X5}, 137 {TextureFormat::ASTC_2D_5X5, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_5X5_UNORM},
133 {TextureFormat::ASTC_2D_5X5, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_5X5_SRGB}, 138 {TextureFormat::ASTC_2D_5X5, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_5X5_SRGB},
134 139
135 {TextureFormat::ASTC_2D_8X8, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_8X8}, 140 {TextureFormat::ASTC_2D_8X8, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_8X8_UNORM},
136 {TextureFormat::ASTC_2D_8X8, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_8X8_SRGB}, 141 {TextureFormat::ASTC_2D_8X8, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_8X8_SRGB},
137 142
138 {TextureFormat::ASTC_2D_8X5, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_8X5}, 143 {TextureFormat::ASTC_2D_8X5, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_8X5_UNORM},
139 {TextureFormat::ASTC_2D_8X5, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_8X5_SRGB}, 144 {TextureFormat::ASTC_2D_8X5, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_8X5_SRGB},
140 145
141 {TextureFormat::ASTC_2D_10X8, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_10X8}, 146 {TextureFormat::ASTC_2D_10X8, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_10X8_UNORM},
142 {TextureFormat::ASTC_2D_10X8, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_10X8_SRGB}, 147 {TextureFormat::ASTC_2D_10X8, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_10X8_SRGB},
143 148
144 {TextureFormat::ASTC_2D_6X6, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_6X6}, 149 {TextureFormat::ASTC_2D_6X6, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_6X6_UNORM},
145 {TextureFormat::ASTC_2D_6X6, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_6X6_SRGB}, 150 {TextureFormat::ASTC_2D_6X6, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_6X6_SRGB},
146 151
147 {TextureFormat::ASTC_2D_10X10, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_10X10}, 152 {TextureFormat::ASTC_2D_10X10, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_10X10_UNORM},
148 {TextureFormat::ASTC_2D_10X10, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_10X10_SRGB}, 153 {TextureFormat::ASTC_2D_10X10, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_10X10_SRGB},
149 154
150 {TextureFormat::ASTC_2D_12X12, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_12X12}, 155 {TextureFormat::ASTC_2D_12X12, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_12X12_UNORM},
151 {TextureFormat::ASTC_2D_12X12, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_12X12_SRGB}, 156 {TextureFormat::ASTC_2D_12X12, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_12X12_SRGB},
152 157
153 {TextureFormat::ASTC_2D_8X6, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_8X6}, 158 {TextureFormat::ASTC_2D_8X6, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_8X6_UNORM},
154 {TextureFormat::ASTC_2D_8X6, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_8X6_SRGB}, 159 {TextureFormat::ASTC_2D_8X6, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_8X6_SRGB},
155 160
156 {TextureFormat::ASTC_2D_6X5, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_6X5}, 161 {TextureFormat::ASTC_2D_6X5, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_6X5_UNORM},
157 {TextureFormat::ASTC_2D_6X5, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_6X5_SRGB}, 162 {TextureFormat::ASTC_2D_6X5, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_6X5_SRGB},
158}}; 163}};
159 164
@@ -184,7 +189,7 @@ PixelFormat FormatLookupTable::GetPixelFormat(TextureFormat format, bool is_srgb
184 static_cast<int>(format), is_srgb, static_cast<int>(red_component), 189 static_cast<int>(format), is_srgb, static_cast<int>(red_component),
185 static_cast<int>(green_component), static_cast<int>(blue_component), 190 static_cast<int>(green_component), static_cast<int>(blue_component),
186 static_cast<int>(alpha_component)); 191 static_cast<int>(alpha_component));
187 return PixelFormat::ABGR8U; 192 return PixelFormat::A8B8G8R8_UNORM;
188} 193}
189 194
190void FormatLookupTable::Set(TextureFormat format, bool is_srgb, ComponentType red_component, 195void FormatLookupTable::Set(TextureFormat format, bool is_srgb, ComponentType red_component,
diff --git a/src/video_core/texture_cache/surface_base.cpp b/src/video_core/texture_cache/surface_base.cpp
index 0caf3b4f0..dfcf36e0b 100644
--- a/src/video_core/texture_cache/surface_base.cpp
+++ b/src/video_core/texture_cache/surface_base.cpp
@@ -228,7 +228,7 @@ void SurfaceBaseImpl::LoadBuffer(Tegra::MemoryManager& memory_manager,
228 } 228 }
229 } 229 }
230 230
231 if (!is_converted && params.pixel_format != PixelFormat::S8Z24) { 231 if (!is_converted && params.pixel_format != PixelFormat::S8_UINT_D24_UNORM) {
232 return; 232 return;
233 } 233 }
234 234
diff --git a/src/video_core/texture_cache/surface_params.cpp b/src/video_core/texture_cache/surface_params.cpp
index 921562c1f..9e5fe2374 100644
--- a/src/video_core/texture_cache/surface_params.cpp
+++ b/src/video_core/texture_cache/surface_params.cpp
@@ -83,12 +83,12 @@ SurfaceParams SurfaceParams::CreateForTexture(const FormatLookupTable& lookup_ta
83 params.type = GetFormatType(params.pixel_format); 83 params.type = GetFormatType(params.pixel_format);
84 if (entry.is_shadow && params.type == SurfaceType::ColorTexture) { 84 if (entry.is_shadow && params.type == SurfaceType::ColorTexture) {
85 switch (params.pixel_format) { 85 switch (params.pixel_format) {
86 case PixelFormat::R16U: 86 case PixelFormat::R16_UNORM:
87 case PixelFormat::R16F: 87 case PixelFormat::R16_FLOAT:
88 params.pixel_format = PixelFormat::Z16; 88 params.pixel_format = PixelFormat::D16_UNORM;
89 break; 89 break;
90 case PixelFormat::R32F: 90 case PixelFormat::R32_FLOAT:
91 params.pixel_format = PixelFormat::Z32F; 91 params.pixel_format = PixelFormat::D32_FLOAT;
92 break; 92 break;
93 default: 93 default:
94 UNIMPLEMENTED_MSG("Unimplemented shadow convert format: {}", 94 UNIMPLEMENTED_MSG("Unimplemented shadow convert format: {}",
@@ -195,8 +195,8 @@ SurfaceParams SurfaceParams::CreateForFramebuffer(Core::System& system, std::siz
195 SurfaceParams params; 195 SurfaceParams params;
196 params.is_tiled = 196 params.is_tiled =
197 config.memory_layout.type == Tegra::Engines::Maxwell3D::Regs::InvMemoryLayout::BlockLinear; 197 config.memory_layout.type == Tegra::Engines::Maxwell3D::Regs::InvMemoryLayout::BlockLinear;
198 params.srgb_conversion = config.format == Tegra::RenderTargetFormat::BGRA8_SRGB || 198 params.srgb_conversion = config.format == Tegra::RenderTargetFormat::B8G8R8A8_SRGB ||
199 config.format == Tegra::RenderTargetFormat::RGBA8_SRGB; 199 config.format == Tegra::RenderTargetFormat::A8B8G8R8_SRGB;
200 params.block_width = config.memory_layout.block_width; 200 params.block_width = config.memory_layout.block_width;
201 params.block_height = config.memory_layout.block_height; 201 params.block_height = config.memory_layout.block_height;
202 params.block_depth = config.memory_layout.block_depth; 202 params.block_depth = config.memory_layout.block_depth;
@@ -235,8 +235,8 @@ SurfaceParams SurfaceParams::CreateForFermiCopySurface(
235 const Tegra::Engines::Fermi2D::Regs::Surface& config) { 235 const Tegra::Engines::Fermi2D::Regs::Surface& config) {
236 SurfaceParams params{}; 236 SurfaceParams params{};
237 params.is_tiled = !config.linear; 237 params.is_tiled = !config.linear;
238 params.srgb_conversion = config.format == Tegra::RenderTargetFormat::BGRA8_SRGB || 238 params.srgb_conversion = config.format == Tegra::RenderTargetFormat::B8G8R8A8_SRGB ||
239 config.format == Tegra::RenderTargetFormat::RGBA8_SRGB; 239 config.format == Tegra::RenderTargetFormat::A8B8G8R8_SRGB;
240 params.block_width = params.is_tiled ? std::min(config.BlockWidth(), 5U) : 0, 240 params.block_width = params.is_tiled ? std::min(config.BlockWidth(), 5U) : 0,
241 params.block_height = params.is_tiled ? std::min(config.BlockHeight(), 5U) : 0, 241 params.block_height = params.is_tiled ? std::min(config.BlockHeight(), 5U) : 0,
242 params.block_depth = params.is_tiled ? std::min(config.BlockDepth(), 5U) : 0, 242 params.block_depth = params.is_tiled ? std::min(config.BlockDepth(), 5U) : 0,
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h
index cdcddb225..96c4e4cc2 100644
--- a/src/video_core/texture_cache/texture_cache.h
+++ b/src/video_core/texture_cache/texture_cache.h
@@ -373,9 +373,9 @@ protected:
373 siblings_table[static_cast<std::size_t>(b)] = a; 373 siblings_table[static_cast<std::size_t>(b)] = a;
374 }; 374 };
375 std::fill(siblings_table.begin(), siblings_table.end(), PixelFormat::Invalid); 375 std::fill(siblings_table.begin(), siblings_table.end(), PixelFormat::Invalid);
376 make_siblings(PixelFormat::Z16, PixelFormat::R16U); 376 make_siblings(PixelFormat::D16_UNORM, PixelFormat::R16_UNORM);
377 make_siblings(PixelFormat::Z32F, PixelFormat::R32F); 377 make_siblings(PixelFormat::D32_FLOAT, PixelFormat::R32_FLOAT);
378 make_siblings(PixelFormat::Z32FS8, PixelFormat::RG32F); 378 make_siblings(PixelFormat::D32_FLOAT_S8_UINT, PixelFormat::R32G32_FLOAT);
379 379
380 sampled_textures.reserve(64); 380 sampled_textures.reserve(64);
381 } 381 }
@@ -1031,7 +1031,7 @@ private:
1031 params.pitch = 4; 1031 params.pitch = 4;
1032 params.num_levels = 1; 1032 params.num_levels = 1;
1033 params.emulated_levels = 1; 1033 params.emulated_levels = 1;
1034 params.pixel_format = VideoCore::Surface::PixelFormat::R8U; 1034 params.pixel_format = VideoCore::Surface::PixelFormat::R8_UNORM;
1035 params.type = VideoCore::Surface::SurfaceType::ColorTexture; 1035 params.type = VideoCore::Surface::SurfaceType::ColorTexture;
1036 auto surface = CreateSurface(0ULL, params); 1036 auto surface = CreateSurface(0ULL, params);
1037 invalid_memory.resize(surface->GetHostSizeInBytes(), 0U); 1037 invalid_memory.resize(surface->GetHostSizeInBytes(), 0U);
diff --git a/src/video_core/textures/convert.cpp b/src/video_core/textures/convert.cpp
index f3efa7eb0..962921483 100644
--- a/src/video_core/textures/convert.cpp
+++ b/src/video_core/textures/convert.cpp
@@ -35,7 +35,7 @@ void SwapS8Z24ToZ24S8(u8* data, u32 width, u32 height) {
35 S8Z24 s8z24_pixel{}; 35 S8Z24 s8z24_pixel{};
36 Z24S8 z24s8_pixel{}; 36 Z24S8 z24s8_pixel{};
37 constexpr auto bpp{ 37 constexpr auto bpp{
38 VideoCore::Surface::GetBytesPerPixel(VideoCore::Surface::PixelFormat::S8Z24)}; 38 VideoCore::Surface::GetBytesPerPixel(VideoCore::Surface::PixelFormat::S8_UINT_D24_UNORM)};
39 for (std::size_t y = 0; y < height; ++y) { 39 for (std::size_t y = 0; y < height; ++y) {
40 for (std::size_t x = 0; x < width; ++x) { 40 for (std::size_t x = 0; x < width; ++x) {
41 const std::size_t offset{bpp * (y * width + x)}; 41 const std::size_t offset{bpp * (y * width + x)};
@@ -73,7 +73,7 @@ void ConvertFromGuestToHost(u8* in_data, u8* out_data, PixelFormat pixel_format,
73 in_data, width, height, depth, block_width, block_height); 73 in_data, width, height, depth, block_width, block_height);
74 std::copy(rgba8_data.begin(), rgba8_data.end(), out_data); 74 std::copy(rgba8_data.begin(), rgba8_data.end(), out_data);
75 75
76 } else if (convert_s8z24 && pixel_format == PixelFormat::S8Z24) { 76 } else if (convert_s8z24 && pixel_format == PixelFormat::S8_UINT_D24_UNORM) {
77 Tegra::Texture::ConvertS8Z24ToZ24S8(in_data, width, height); 77 Tegra::Texture::ConvertS8Z24ToZ24S8(in_data, width, height);
78 } 78 }
79} 79}
@@ -85,7 +85,7 @@ void ConvertFromHostToGuest(u8* data, PixelFormat pixel_format, u32 width, u32 h
85 static_cast<u32>(pixel_format)); 85 static_cast<u32>(pixel_format));
86 UNREACHABLE(); 86 UNREACHABLE();
87 87
88 } else if (convert_s8z24 && pixel_format == PixelFormat::S8Z24) { 88 } else if (convert_s8z24 && pixel_format == PixelFormat::S8_UINT_D24_UNORM) {
89 Tegra::Texture::ConvertZ24S8ToS8Z24(data, width, height); 89 Tegra::Texture::ConvertZ24S8ToS8Z24(data, width, height);
90 } 90 }
91} 91}
diff --git a/src/video_core/textures/decoders.cpp b/src/video_core/textures/decoders.cpp
index 98beabef1..474ae620a 100644
--- a/src/video_core/textures/decoders.cpp
+++ b/src/video_core/textures/decoders.cpp
@@ -184,53 +184,6 @@ void CopySwizzledData(u32 width, u32 height, u32 depth, u32 bytes_per_pixel,
184 } 184 }
185} 185}
186 186
187u32 BytesPerPixel(TextureFormat format) {
188 switch (format) {
189 case TextureFormat::DXT1:
190 case TextureFormat::DXN1:
191 // In this case a 'pixel' actually refers to a 4x4 tile.
192 return 8;
193 case TextureFormat::DXT23:
194 case TextureFormat::DXT45:
195 case TextureFormat::DXN2:
196 case TextureFormat::BC7U:
197 case TextureFormat::BC6H_UF16:
198 case TextureFormat::BC6H_SF16:
199 // In this case a 'pixel' actually refers to a 4x4 tile.
200 return 16;
201 case TextureFormat::R32_G32_B32:
202 return 12;
203 case TextureFormat::ASTC_2D_4X4:
204 case TextureFormat::ASTC_2D_5X4:
205 case TextureFormat::ASTC_2D_8X8:
206 case TextureFormat::ASTC_2D_8X5:
207 case TextureFormat::ASTC_2D_10X8:
208 case TextureFormat::ASTC_2D_5X5:
209 case TextureFormat::A8R8G8B8:
210 case TextureFormat::A2B10G10R10:
211 case TextureFormat::BF10GF11RF11:
212 case TextureFormat::R32:
213 case TextureFormat::R16_G16:
214 return 4;
215 case TextureFormat::A1B5G5R5:
216 case TextureFormat::B5G6R5:
217 case TextureFormat::G8R8:
218 case TextureFormat::R16:
219 return 2;
220 case TextureFormat::R8:
221 return 1;
222 case TextureFormat::R16_G16_B16_A16:
223 return 8;
224 case TextureFormat::R32_G32_B32_A32:
225 return 16;
226 case TextureFormat::R32_G32:
227 return 8;
228 default:
229 UNIMPLEMENTED_MSG("Format not implemented");
230 return 1;
231 }
232}
233
234void UnswizzleTexture(u8* const unswizzled_data, u8* address, u32 tile_size_x, u32 tile_size_y, 187void UnswizzleTexture(u8* const unswizzled_data, u8* address, u32 tile_size_x, u32 tile_size_y,
235 u32 bytes_per_pixel, u32 width, u32 height, u32 depth, u32 block_height, 188 u32 bytes_per_pixel, u32 width, u32 height, u32 depth, u32 block_height,
236 u32 block_depth, u32 width_spacing) { 189 u32 block_depth, u32 width_spacing) {
@@ -348,48 +301,6 @@ void SwizzleKepler(const u32 width, const u32 height, const u32 dst_x, const u32
348 } 301 }
349} 302}
350 303
351std::vector<u8> DecodeTexture(const std::vector<u8>& texture_data, TextureFormat format, u32 width,
352 u32 height) {
353 std::vector<u8> rgba_data;
354
355 // TODO(Subv): Implement.
356 switch (format) {
357 case TextureFormat::DXT1:
358 case TextureFormat::DXT23:
359 case TextureFormat::DXT45:
360 case TextureFormat::DXN1:
361 case TextureFormat::DXN2:
362 case TextureFormat::BC7U:
363 case TextureFormat::BC6H_UF16:
364 case TextureFormat::BC6H_SF16:
365 case TextureFormat::ASTC_2D_4X4:
366 case TextureFormat::ASTC_2D_8X8:
367 case TextureFormat::ASTC_2D_5X5:
368 case TextureFormat::ASTC_2D_10X8:
369 case TextureFormat::A8R8G8B8:
370 case TextureFormat::A2B10G10R10:
371 case TextureFormat::A1B5G5R5:
372 case TextureFormat::B5G6R5:
373 case TextureFormat::R8:
374 case TextureFormat::G8R8:
375 case TextureFormat::BF10GF11RF11:
376 case TextureFormat::R32_G32_B32_A32:
377 case TextureFormat::R32_G32:
378 case TextureFormat::R32:
379 case TextureFormat::R16:
380 case TextureFormat::R16_G16:
381 case TextureFormat::R32_G32_B32:
382 // TODO(Subv): For the time being just forward the same data without any decoding.
383 rgba_data = texture_data;
384 break;
385 default:
386 UNIMPLEMENTED_MSG("Format not implemented");
387 break;
388 }
389
390 return rgba_data;
391}
392
393std::size_t CalculateSize(bool tiled, u32 bytes_per_pixel, u32 width, u32 height, u32 depth, 304std::size_t CalculateSize(bool tiled, u32 bytes_per_pixel, u32 width, u32 height, u32 depth,
394 u32 block_height, u32 block_depth) { 305 u32 block_height, u32 block_depth) {
395 if (tiled) { 306 if (tiled) {
diff --git a/src/video_core/textures/decoders.h b/src/video_core/textures/decoders.h
index 232b696b3..d6fe35d37 100644
--- a/src/video_core/textures/decoders.h
+++ b/src/video_core/textures/decoders.h
@@ -38,10 +38,6 @@ void CopySwizzledData(u32 width, u32 height, u32 depth, u32 bytes_per_pixel,
38 u32 out_bytes_per_pixel, u8* swizzled_data, u8* unswizzled_data, 38 u32 out_bytes_per_pixel, u8* swizzled_data, u8* unswizzled_data,
39 bool unswizzle, u32 block_height, u32 block_depth, u32 width_spacing); 39 bool unswizzle, u32 block_height, u32 block_depth, u32 width_spacing);
40 40
41/// Decodes an unswizzled texture into a A8R8G8B8 texture.
42std::vector<u8> DecodeTexture(const std::vector<u8>& texture_data, TextureFormat format, u32 width,
43 u32 height);
44
45/// This function calculates the correct size of a texture depending if it's tiled or not. 41/// This function calculates the correct size of a texture depending if it's tiled or not.
46std::size_t CalculateSize(bool tiled, u32 bytes_per_pixel, u32 width, u32 height, u32 depth, 42std::size_t CalculateSize(bool tiled, u32 bytes_per_pixel, u32 width, u32 height, u32 depth,
47 u32 block_height, u32 block_depth); 43 u32 block_height, u32 block_depth);
diff --git a/src/video_core/textures/texture.h b/src/video_core/textures/texture.h
index eba05aced..0574fef12 100644
--- a/src/video_core/textures/texture.h
+++ b/src/video_core/textures/texture.h
@@ -12,10 +12,10 @@
12namespace Tegra::Texture { 12namespace Tegra::Texture {
13 13
14enum class TextureFormat : u32 { 14enum class TextureFormat : u32 {
15 R32_G32_B32_A32 = 0x01, 15 R32G32B32A32 = 0x01,
16 R32_G32_B32 = 0x02, 16 R32G32B32 = 0x02,
17 R16_G16_B16_A16 = 0x03, 17 R16G16B16A16 = 0x03,
18 R32_G32 = 0x04, 18 R32G32 = 0x04,
19 R32_B24G8 = 0x05, 19 R32_B24G8 = 0x05,
20 ETC2_RGB = 0x06, 20 ETC2_RGB = 0x06,
21 X8B8G8R8 = 0x07, 21 X8B8G8R8 = 0x07,
@@ -23,19 +23,19 @@ enum class TextureFormat : u32 {
23 A2B10G10R10 = 0x09, 23 A2B10G10R10 = 0x09,
24 ETC2_RGB_PTA = 0x0a, 24 ETC2_RGB_PTA = 0x0a,
25 ETC2_RGBA = 0x0b, 25 ETC2_RGBA = 0x0b,
26 R16_G16 = 0x0c, 26 R16G16 = 0x0c,
27 G8R24 = 0x0d, 27 R24G8 = 0x0d,
28 G24R8 = 0x0e, 28 R8G24 = 0x0e,
29 R32 = 0x0f, 29 R32 = 0x0f,
30 BC6H_SF16 = 0x10, 30 BC6H_SFLOAT = 0x10,
31 BC6H_UF16 = 0x11, 31 BC6H_UFLOAT = 0x11,
32 A4B4G4R4 = 0x12, 32 A4B4G4R4 = 0x12,
33 A5B5G5R1 = 0x13, 33 A5B5G5R1 = 0x13,
34 A1B5G5R5 = 0x14, 34 A1B5G5R5 = 0x14,
35 B5G6R5 = 0x15, 35 B5G6R5 = 0x15,
36 B6G5R5 = 0x16, 36 B6G5R5 = 0x16,
37 BC7U = 0x17, 37 BC7 = 0x17,
38 G8R8 = 0x18, 38 R8G8 = 0x18,
39 EAC = 0x19, 39 EAC = 0x19,
40 EACX2 = 0x1a, 40 EACX2 = 0x1a,
41 R16 = 0x1b, 41 R16 = 0x1b,
@@ -43,23 +43,23 @@ enum class TextureFormat : u32 {
43 R8 = 0x1d, 43 R8 = 0x1d,
44 G4R4 = 0x1e, 44 G4R4 = 0x1e,
45 R1 = 0x1f, 45 R1 = 0x1f,
46 E5B9G9R9_SHAREDEXP = 0x20, 46 E5B9G9R9 = 0x20,
47 BF10GF11RF11 = 0x21, 47 B10G11R11 = 0x21,
48 G8B8G8R8 = 0x22, 48 G8B8G8R8 = 0x22,
49 B8G8R8G8 = 0x23, 49 B8G8R8G8 = 0x23,
50 DXT1 = 0x24, 50 BC1_RGBA = 0x24,
51 DXT23 = 0x25, 51 BC2 = 0x25,
52 DXT45 = 0x26, 52 BC3 = 0x26,
53 DXN1 = 0x27, 53 BC4 = 0x27,
54 DXN2 = 0x28, 54 BC5 = 0x28,
55 S8Z24 = 0x29, 55 S8D24 = 0x29,
56 X8Z24 = 0x2a, 56 X8Z24 = 0x2a,
57 Z24S8 = 0x2b, 57 D24S8 = 0x2b,
58 X4V4Z24__COV4R4V = 0x2c, 58 X4V4Z24__COV4R4V = 0x2c,
59 X4V4Z24__COV8R8V = 0x2d, 59 X4V4Z24__COV8R8V = 0x2d,
60 V8Z24__COV4R12V = 0x2e, 60 V8Z24__COV4R12V = 0x2e,
61 ZF32 = 0x2f, 61 D32 = 0x2f,
62 ZF32_X24S8 = 0x30, 62 D32S8 = 0x30,
63 X8Z24_X20V4S8__COV4R4V = 0x31, 63 X8Z24_X20V4S8__COV4R4V = 0x31,
64 X8Z24_X20V4S8__COV8R8V = 0x32, 64 X8Z24_X20V4S8__COV8R8V = 0x32,
65 ZF32_X20V4X8__COV4R4V = 0x33, 65 ZF32_X20V4X8__COV4R4V = 0x33,
@@ -69,7 +69,7 @@ enum class TextureFormat : u32 {
69 X8Z24_X16V8S8__COV4R12V = 0x37, 69 X8Z24_X16V8S8__COV4R12V = 0x37,
70 ZF32_X16V8X8__COV4R12V = 0x38, 70 ZF32_X16V8X8__COV4R12V = 0x38,
71 ZF32_X16V8S8__COV4R12V = 0x39, 71 ZF32_X16V8S8__COV4R12V = 0x39,
72 Z16 = 0x3a, 72 D16 = 0x3a,
73 V8Z24__COV8R24V = 0x3b, 73 V8Z24__COV8R24V = 0x3b,
74 X8Z24_X16V8S8__COV8R24V = 0x3c, 74 X8Z24_X16V8S8__COV8R24V = 0x3c,
75 ZF32_X16V8X8__COV8R24V = 0x3d, 75 ZF32_X16V8X8__COV8R24V = 0x3d,
@@ -375,7 +375,4 @@ struct FullTextureInfo {
375 TSCEntry tsc; 375 TSCEntry tsc;
376}; 376};
377 377
378/// Returns the number of bytes per pixel of the input texture format.
379u32 BytesPerPixel(TextureFormat format);
380
381} // namespace Tegra::Texture 378} // namespace Tegra::Texture
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt
index a862b2610..656096c9f 100644
--- a/src/yuzu/CMakeLists.txt
+++ b/src/yuzu/CMakeLists.txt
@@ -133,11 +133,44 @@ file(GLOB COMPAT_LIST
133file(GLOB_RECURSE ICONS ${PROJECT_SOURCE_DIR}/dist/icons/*) 133file(GLOB_RECURSE ICONS ${PROJECT_SOURCE_DIR}/dist/icons/*)
134file(GLOB_RECURSE THEMES ${PROJECT_SOURCE_DIR}/dist/qt_themes/*) 134file(GLOB_RECURSE THEMES ${PROJECT_SOURCE_DIR}/dist/qt_themes/*)
135 135
136if (ENABLE_QT_TRANSLATION)
137 set(YUZU_QT_LANGUAGES "${PROJECT_SOURCE_DIR}/dist/languages" CACHE PATH "Path to the translation bundle for the Qt frontend")
138 option(GENERATE_QT_TRANSLATION "Generate en.ts as the translation source file" OFF)
139
140 # Update source TS file if enabled
141 if (GENERATE_QT_TRANSLATION)
142 get_target_property(SRCS yuzu SOURCES)
143 qt5_create_translation(QM_FILES ${SRCS} ${UIS} ${YUZU_QT_LANGUAGES}/en.ts)
144 add_custom_target(translation ALL DEPENDS ${YUZU_QT_LANGUAGES}/en.ts)
145 endif()
146
147 # Find all TS files except en.ts
148 file(GLOB_RECURSE LANGUAGES_TS ${YUZU_QT_LANGUAGES}/*.ts)
149 list(REMOVE_ITEM LANGUAGES_TS ${YUZU_QT_LANGUAGES}/en.ts)
150
151 # Compile TS files to QM files
152 qt5_add_translation(LANGUAGES_QM ${LANGUAGES_TS})
153
154 # Build a QRC file from the QM file list
155 set(LANGUAGES_QRC ${CMAKE_CURRENT_BINARY_DIR}/languages.qrc)
156 file(WRITE ${LANGUAGES_QRC} "<RCC><qresource prefix=\"languages\">\n")
157 foreach (QM ${LANGUAGES_QM})
158 get_filename_component(QM_FILE ${QM} NAME)
159 file(APPEND ${LANGUAGES_QRC} "<file>${QM_FILE}</file>\n")
160 endforeach (QM)
161 file(APPEND ${LANGUAGES_QRC} "</qresource></RCC>")
162
163 # Add the QRC file to package in all QM files
164 qt5_add_resources(LANGUAGES ${LANGUAGES_QRC})
165else()
166 set(LANGUAGES)
167endif()
136 168
137target_sources(yuzu 169target_sources(yuzu
138 PRIVATE 170 PRIVATE
139 ${COMPAT_LIST} 171 ${COMPAT_LIST}
140 ${ICONS} 172 ${ICONS}
173 ${LANGUAGES}
141 ${THEMES} 174 ${THEMES}
142) 175)
143 176
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index 9e9b38214..59a193edd 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -611,6 +611,7 @@ void Config::ReadPathValues() {
611 } 611 }
612 } 612 }
613 UISettings::values.recent_files = ReadSetting(QStringLiteral("recentFiles")).toStringList(); 613 UISettings::values.recent_files = ReadSetting(QStringLiteral("recentFiles")).toStringList();
614 UISettings::values.language = ReadSetting(QStringLiteral("language"), QString{}).toString();
614 615
615 qt_config->endGroup(); 616 qt_config->endGroup();
616} 617}
@@ -661,6 +662,8 @@ void Config::ReadRendererValues() {
661 ReadSettingGlobal(Settings::values.use_vsync, QStringLiteral("use_vsync"), true); 662 ReadSettingGlobal(Settings::values.use_vsync, QStringLiteral("use_vsync"), true);
662 ReadSettingGlobal(Settings::values.use_assembly_shaders, QStringLiteral("use_assembly_shaders"), 663 ReadSettingGlobal(Settings::values.use_assembly_shaders, QStringLiteral("use_assembly_shaders"),
663 false); 664 false);
665 ReadSettingGlobal(Settings::values.use_asynchronous_shaders,
666 QStringLiteral("use_asynchronous_shaders"), false);
664 ReadSettingGlobal(Settings::values.use_fast_gpu_time, QStringLiteral("use_fast_gpu_time"), 667 ReadSettingGlobal(Settings::values.use_fast_gpu_time, QStringLiteral("use_fast_gpu_time"),
665 true); 668 true);
666 ReadSettingGlobal(Settings::values.force_30fps_mode, QStringLiteral("force_30fps_mode"), false); 669 ReadSettingGlobal(Settings::values.force_30fps_mode, QStringLiteral("force_30fps_mode"), false);
@@ -1093,6 +1096,7 @@ void Config::SavePathValues() {
1093 } 1096 }
1094 qt_config->endArray(); 1097 qt_config->endArray();
1095 WriteSetting(QStringLiteral("recentFiles"), UISettings::values.recent_files); 1098 WriteSetting(QStringLiteral("recentFiles"), UISettings::values.recent_files);
1099 WriteSetting(QStringLiteral("language"), UISettings::values.language, QString{});
1096 1100
1097 qt_config->endGroup(); 1101 qt_config->endGroup();
1098} 1102}
@@ -1145,6 +1149,8 @@ void Config::SaveRendererValues() {
1145 WriteSettingGlobal(QStringLiteral("use_vsync"), Settings::values.use_vsync, true); 1149 WriteSettingGlobal(QStringLiteral("use_vsync"), Settings::values.use_vsync, true);
1146 WriteSettingGlobal(QStringLiteral("use_assembly_shaders"), 1150 WriteSettingGlobal(QStringLiteral("use_assembly_shaders"),
1147 Settings::values.use_assembly_shaders, false); 1151 Settings::values.use_assembly_shaders, false);
1152 WriteSettingGlobal(QStringLiteral("use_asynchronous_shaders"),
1153 Settings::values.use_asynchronous_shaders, false);
1148 WriteSettingGlobal(QStringLiteral("use_fast_gpu_time"), Settings::values.use_fast_gpu_time, 1154 WriteSettingGlobal(QStringLiteral("use_fast_gpu_time"), Settings::values.use_fast_gpu_time,
1149 true); 1155 true);
1150 WriteSettingGlobal(QStringLiteral("force_30fps_mode"), Settings::values.force_30fps_mode, 1156 WriteSettingGlobal(QStringLiteral("force_30fps_mode"), Settings::values.force_30fps_mode,
@@ -1368,11 +1374,13 @@ void Config::WriteSettingGlobal(const QString& name, const QVariant& value, bool
1368 1374
1369void Config::Reload() { 1375void Config::Reload() {
1370 ReadValues(); 1376 ReadValues();
1377 Settings::Sanitize();
1371 // To apply default value changes 1378 // To apply default value changes
1372 SaveValues(); 1379 SaveValues();
1373 Settings::Apply(); 1380 Settings::Apply();
1374} 1381}
1375 1382
1376void Config::Save() { 1383void Config::Save() {
1384 Settings::Sanitize();
1377 SaveValues(); 1385 SaveValues();
1378} 1386}
diff --git a/src/yuzu/configuration/configuration_shared.cpp b/src/yuzu/configuration/configuration_shared.cpp
index bb47c3933..f9becab6e 100644
--- a/src/yuzu/configuration/configuration_shared.cpp
+++ b/src/yuzu/configuration/configuration_shared.cpp
@@ -4,17 +4,20 @@
4 4
5#include <QCheckBox> 5#include <QCheckBox>
6#include <QComboBox> 6#include <QComboBox>
7#include <QObject>
8#include <QString>
7#include "core/settings.h" 9#include "core/settings.h"
8#include "yuzu/configuration/configuration_shared.h" 10#include "yuzu/configuration/configuration_shared.h"
9#include "yuzu/configuration/configure_per_game.h" 11#include "yuzu/configuration/configure_per_game.h"
10 12
11void ConfigurationShared::ApplyPerGameSetting(Settings::Setting<bool>* setting, 13void ConfigurationShared::ApplyPerGameSetting(Settings::Setting<bool>* setting,
12 const QCheckBox* checkbox) { 14 const QCheckBox* checkbox,
13 if (checkbox->checkState() == Qt::PartiallyChecked) { 15 const CheckState& tracker) {
16 if (tracker == CheckState::Global) {
14 setting->SetGlobal(true); 17 setting->SetGlobal(true);
15 } else { 18 } else {
16 setting->SetGlobal(false); 19 setting->SetGlobal(false);
17 setting->SetValue(checkbox->checkState() == Qt::Checked); 20 setting->SetValue(checkbox->checkState());
18 } 21 }
19} 22}
20 23
@@ -69,8 +72,69 @@ void ConfigurationShared::SetPerGameSetting(
69 ConfigurationShared::USE_GLOBAL_OFFSET); 72 ConfigurationShared::USE_GLOBAL_OFFSET);
70} 73}
71 74
72void ConfigurationShared::InsertGlobalItem(QComboBox* combobox) { 75void ConfigurationShared::SetHighlight(QWidget* widget, const std::string& name, bool highlighted) {
73 const QString use_global_text = ConfigurePerGame::tr("Use global configuration"); 76 if (highlighted) {
77 widget->setStyleSheet(QStringLiteral("QWidget#%1 { background-color:rgba(0,203,255,0.5) }")
78 .arg(QString::fromStdString(name)));
79 } else {
80 widget->setStyleSheet(QStringLiteral("QWidget#%1 { background-color:rgba(0,0,0,0) }")
81 .arg(QString::fromStdString(name)));
82 }
83 widget->show();
84}
85
86void ConfigurationShared::SetColoredTristate(QCheckBox* checkbox, const std::string& name,
87 const Settings::Setting<bool>& setting,
88 CheckState& tracker) {
89 if (setting.UsingGlobal()) {
90 tracker = CheckState::Global;
91 } else {
92 tracker = (setting.GetValue() == setting.GetValue(true)) ? CheckState::On : CheckState::Off;
93 }
94 SetHighlight(checkbox, name, tracker != CheckState::Global);
95 QObject::connect(checkbox, &QCheckBox::clicked, checkbox,
96 [checkbox, name, setting, &tracker]() {
97 tracker = static_cast<CheckState>((static_cast<int>(tracker) + 1) %
98 static_cast<int>(CheckState::Count));
99 if (tracker == CheckState::Global) {
100 checkbox->setChecked(setting.GetValue(true));
101 }
102 SetHighlight(checkbox, name, tracker != CheckState::Global);
103 });
104}
105
106void ConfigurationShared::SetColoredTristate(QCheckBox* checkbox, const std::string& name,
107 bool global, bool state, bool global_state,
108 CheckState& tracker) {
109 if (global) {
110 tracker = CheckState::Global;
111 } else {
112 tracker = (state == global_state) ? CheckState::On : CheckState::Off;
113 }
114 SetHighlight(checkbox, name, tracker != CheckState::Global);
115 QObject::connect(checkbox, &QCheckBox::clicked, checkbox,
116 [checkbox, name, global_state, &tracker]() {
117 tracker = static_cast<CheckState>((static_cast<int>(tracker) + 1) %
118 static_cast<int>(CheckState::Count));
119 if (tracker == CheckState::Global) {
120 checkbox->setChecked(global_state);
121 }
122 SetHighlight(checkbox, name, tracker != CheckState::Global);
123 });
124}
125
126void ConfigurationShared::SetColoredComboBox(QComboBox* combobox, QWidget* target,
127 const std::string& target_name, int global) {
128 InsertGlobalItem(combobox, global);
129 QObject::connect(combobox, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), target,
130 [target, target_name](int index) {
131 ConfigurationShared::SetHighlight(target, target_name, index != 0);
132 });
133}
134
135void ConfigurationShared::InsertGlobalItem(QComboBox* combobox, int global_index) {
136 const QString use_global_text =
137 ConfigurePerGame::tr("Use global configuration (%1)").arg(combobox->itemText(global_index));
74 combobox->insertItem(ConfigurationShared::USE_GLOBAL_INDEX, use_global_text); 138 combobox->insertItem(ConfigurationShared::USE_GLOBAL_INDEX, use_global_text);
75 combobox->insertSeparator(ConfigurationShared::USE_GLOBAL_SEPARATOR_INDEX); 139 combobox->insertSeparator(ConfigurationShared::USE_GLOBAL_SEPARATOR_INDEX);
76} 140}
diff --git a/src/yuzu/configuration/configuration_shared.h b/src/yuzu/configuration/configuration_shared.h
index b11b1b950..003148c68 100644
--- a/src/yuzu/configuration/configuration_shared.h
+++ b/src/yuzu/configuration/configuration_shared.h
@@ -15,9 +15,17 @@ constexpr int USE_GLOBAL_INDEX = 0;
15constexpr int USE_GLOBAL_SEPARATOR_INDEX = 1; 15constexpr int USE_GLOBAL_SEPARATOR_INDEX = 1;
16constexpr int USE_GLOBAL_OFFSET = 2; 16constexpr int USE_GLOBAL_OFFSET = 2;
17 17
18enum class CheckState {
19 Off,
20 On,
21 Global,
22 Count,
23};
24
18// Global-aware apply and set functions 25// Global-aware apply and set functions
19 26
20void ApplyPerGameSetting(Settings::Setting<bool>* setting, const QCheckBox* checkbox); 27void ApplyPerGameSetting(Settings::Setting<bool>* setting, const QCheckBox* checkbox,
28 const CheckState& tracker);
21void ApplyPerGameSetting(Settings::Setting<int>* setting, const QComboBox* combobox); 29void ApplyPerGameSetting(Settings::Setting<int>* setting, const QComboBox* combobox);
22void ApplyPerGameSetting(Settings::Setting<Settings::RendererBackend>* setting, 30void ApplyPerGameSetting(Settings::Setting<Settings::RendererBackend>* setting,
23 const QComboBox* combobox); 31 const QComboBox* combobox);
@@ -31,6 +39,14 @@ void SetPerGameSetting(QComboBox* combobox,
31void SetPerGameSetting(QComboBox* combobox, 39void SetPerGameSetting(QComboBox* combobox,
32 const Settings::Setting<Settings::GPUAccuracy>* setting); 40 const Settings::Setting<Settings::GPUAccuracy>* setting);
33 41
34void InsertGlobalItem(QComboBox* combobox); 42void SetHighlight(QWidget* widget, const std::string& name, bool highlighted);
43void SetColoredTristate(QCheckBox* checkbox, const std::string& name,
44 const Settings::Setting<bool>& setting, CheckState& tracker);
45void SetColoredTristate(QCheckBox* checkbox, const std::string& name, bool global, bool state,
46 bool global_state, CheckState& tracker);
47void SetColoredComboBox(QComboBox* combobox, QWidget* target, const std::string& target_name,
48 int global);
49
50void InsertGlobalItem(QComboBox* combobox, int global_index);
35 51
36} // namespace ConfigurationShared 52} // namespace ConfigurationShared
diff --git a/src/yuzu/configuration/configure_audio.cpp b/src/yuzu/configuration/configure_audio.cpp
index cc021beec..fea632531 100644
--- a/src/yuzu/configuration/configure_audio.cpp
+++ b/src/yuzu/configuration/configure_audio.cpp
@@ -49,12 +49,9 @@ void ConfigureAudio::SetConfiguration() {
49 49
50 ui->volume_slider->setValue(Settings::values.volume.GetValue() * ui->volume_slider->maximum()); 50 ui->volume_slider->setValue(Settings::values.volume.GetValue() * ui->volume_slider->maximum());
51 51
52 if (Settings::configuring_global) { 52 ui->toggle_audio_stretching->setChecked(Settings::values.enable_audio_stretching.GetValue());
53 ui->toggle_audio_stretching->setChecked( 53
54 Settings::values.enable_audio_stretching.GetValue()); 54 if (!Settings::configuring_global) {
55 } else {
56 ConfigurationShared::SetPerGameSetting(ui->toggle_audio_stretching,
57 &Settings::values.enable_audio_stretching);
58 if (Settings::values.volume.UsingGlobal()) { 55 if (Settings::values.volume.UsingGlobal()) {
59 ui->volume_combo_box->setCurrentIndex(0); 56 ui->volume_combo_box->setCurrentIndex(0);
60 ui->volume_slider->setEnabled(false); 57 ui->volume_slider->setEnabled(false);
@@ -62,6 +59,8 @@ void ConfigureAudio::SetConfiguration() {
62 ui->volume_combo_box->setCurrentIndex(1); 59 ui->volume_combo_box->setCurrentIndex(1);
63 ui->volume_slider->setEnabled(true); 60 ui->volume_slider->setEnabled(true);
64 } 61 }
62 ConfigurationShared::SetHighlight(ui->volume_layout, "volume_layout",
63 !Settings::values.volume.UsingGlobal());
65 } 64 }
66 SetVolumeIndicatorText(ui->volume_slider->sliderPosition()); 65 SetVolumeIndicatorText(ui->volume_slider->sliderPosition());
67} 66}
@@ -120,7 +119,8 @@ void ConfigureAudio::ApplyConfiguration() {
120 } 119 }
121 } else { 120 } else {
122 ConfigurationShared::ApplyPerGameSetting(&Settings::values.enable_audio_stretching, 121 ConfigurationShared::ApplyPerGameSetting(&Settings::values.enable_audio_stretching,
123 ui->toggle_audio_stretching); 122 ui->toggle_audio_stretching,
123 enable_audio_stretching);
124 if (ui->volume_combo_box->currentIndex() == 0) { 124 if (ui->volume_combo_box->currentIndex() == 0) {
125 Settings::values.volume.SetGlobal(true); 125 Settings::values.volume.SetGlobal(true);
126 } else { 126 } else {
@@ -173,9 +173,14 @@ void ConfigureAudio::SetupPerGameUI() {
173 return; 173 return;
174 } 174 }
175 175
176 ui->toggle_audio_stretching->setTristate(true); 176 ConfigurationShared::SetColoredTristate(ui->toggle_audio_stretching, "toggle_audio_stretching",
177 Settings::values.enable_audio_stretching,
178 enable_audio_stretching);
177 connect(ui->volume_combo_box, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), 179 connect(ui->volume_combo_box, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated),
178 this, [this](int index) { ui->volume_slider->setEnabled(index == 1); }); 180 this, [this](int index) {
181 ui->volume_slider->setEnabled(index == 1);
182 ConfigurationShared::SetHighlight(ui->volume_layout, "volume_layout", index == 1);
183 });
179 184
180 ui->output_sink_combo_box->setVisible(false); 185 ui->output_sink_combo_box->setVisible(false);
181 ui->output_sink_label->setVisible(false); 186 ui->output_sink_label->setVisible(false);
diff --git a/src/yuzu/configuration/configure_audio.h b/src/yuzu/configuration/configure_audio.h
index d84f4a682..9dbd3d93e 100644
--- a/src/yuzu/configuration/configure_audio.h
+++ b/src/yuzu/configuration/configure_audio.h
@@ -7,6 +7,10 @@
7#include <memory> 7#include <memory>
8#include <QWidget> 8#include <QWidget>
9 9
10namespace ConfigurationShared {
11enum class CheckState;
12}
13
10namespace Ui { 14namespace Ui {
11class ConfigureAudio; 15class ConfigureAudio;
12} 16}
@@ -37,4 +41,6 @@ private:
37 void SetupPerGameUI(); 41 void SetupPerGameUI();
38 42
39 std::unique_ptr<Ui::ConfigureAudio> ui; 43 std::unique_ptr<Ui::ConfigureAudio> ui;
44
45 ConfigurationShared::CheckState enable_audio_stretching;
40}; 46};
diff --git a/src/yuzu/configuration/configure_audio.ui b/src/yuzu/configuration/configure_audio.ui
index 862ccb988..9bd0cca96 100644
--- a/src/yuzu/configuration/configure_audio.ui
+++ b/src/yuzu/configuration/configure_audio.ui
@@ -56,80 +56,91 @@
56 </layout> 56 </layout>
57 </item> 57 </item>
58 <item> 58 <item>
59 <layout class="QHBoxLayout" name="horizontalLayout_2"> 59 <widget class="QWidget" name="volume_layout" native="true">
60 <property name="topMargin"> 60 <layout class="QHBoxLayout" name="horizontalLayout_2">
61 <number>0</number> 61 <property name="leftMargin">
62 </property> 62 <number>0</number>
63 <item> 63 </property>
64 <widget class="QComboBox" name="volume_combo_box"> 64 <property name="topMargin">
65 <item> 65 <number>0</number>
66 </property>
67 <property name="rightMargin">
68 <number>0</number>
69 </property>
70 <property name="bottomMargin">
71 <number>0</number>
72 </property>
73 <item>
74 <widget class="QComboBox" name="volume_combo_box">
75 <item>
76 <property name="text">
77 <string>Use global volume</string>
78 </property>
79 </item>
80 <item>
81 <property name="text">
82 <string>Set volume:</string>
83 </property>
84 </item>
85 </widget>
86 </item>
87 <item>
88 <widget class="QLabel" name="volume_label">
66 <property name="text"> 89 <property name="text">
67 <string>Use global volume</string> 90 <string>Volume:</string>
91 </property>
92 </widget>
93 </item>
94 <item>
95 <spacer name="horizontalSpacer">
96 <property name="orientation">
97 <enum>Qt::Horizontal</enum>
98 </property>
99 <property name="sizeHint" stdset="0">
100 <size>
101 <width>30</width>
102 <height>20</height>
103 </size>
104 </property>
105 </spacer>
106 </item>
107 <item>
108 <widget class="QSlider" name="volume_slider">
109 <property name="sizePolicy">
110 <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
111 <horstretch>0</horstretch>
112 <verstretch>0</verstretch>
113 </sizepolicy>
114 </property>
115 <property name="maximum">
116 <number>100</number>
117 </property>
118 <property name="pageStep">
119 <number>10</number>
120 </property>
121 <property name="orientation">
122 <enum>Qt::Horizontal</enum>
123 </property>
124 </widget>
125 </item>
126 <item>
127 <widget class="QLabel" name="volume_indicator">
128 <property name="minimumSize">
129 <size>
130 <width>32</width>
131 <height>0</height>
132 </size>
68 </property> 133 </property>
69 </item>
70 <item>
71 <property name="text"> 134 <property name="text">
72 <string>Set volume:</string> 135 <string>0 %</string>
73 </property> 136 </property>
74 </item> 137 <property name="alignment">
75 </widget> 138 <set>Qt::AlignCenter</set>
76 </item> 139 </property>
77 <item> 140 </widget>
78 <widget class="QLabel" name="volume_label"> 141 </item>
79 <property name="text"> 142 </layout>
80 <string>Volume:</string> 143 </widget>
81 </property>
82 </widget>
83 </item>
84 <item>
85 <spacer name="horizontalSpacer">
86 <property name="orientation">
87 <enum>Qt::Horizontal</enum>
88 </property>
89 <property name="sizeHint" stdset="0">
90 <size>
91 <width>30</width>
92 <height>20</height>
93 </size>
94 </property>
95 </spacer>
96 </item>
97 <item>
98 <widget class="QSlider" name="volume_slider">
99 <property name="sizePolicy">
100 <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
101 <horstretch>0</horstretch>
102 <verstretch>0</verstretch>
103 </sizepolicy>
104 </property>
105 <property name="maximum">
106 <number>100</number>
107 </property>
108 <property name="pageStep">
109 <number>10</number>
110 </property>
111 <property name="orientation">
112 <enum>Qt::Horizontal</enum>
113 </property>
114 </widget>
115 </item>
116 <item>
117 <widget class="QLabel" name="volume_indicator">
118 <property name="minimumSize">
119 <size>
120 <width>32</width>
121 <height>0</height>
122 </size>
123 </property>
124 <property name="text">
125 <string>0 %</string>
126 </property>
127 <property name="alignment">
128 <set>Qt::AlignCenter</set>
129 </property>
130 </widget>
131 </item>
132 </layout>
133 </item> 144 </item>
134 </layout> 145 </layout>
135 </widget> 146 </widget>
diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp
index a5afb354f..4e30dc51e 100644
--- a/src/yuzu/configuration/configure_dialog.cpp
+++ b/src/yuzu/configuration/configure_dialog.cpp
@@ -23,6 +23,7 @@ ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry)
23 SetConfiguration(); 23 SetConfiguration();
24 PopulateSelectionList(); 24 PopulateSelectionList();
25 25
26 connect(ui->uiTab, &ConfigureUi::LanguageChanged, this, &ConfigureDialog::OnLanguageChanged);
26 connect(ui->selectorList, &QListWidget::itemSelectionChanged, this, 27 connect(ui->selectorList, &QListWidget::itemSelectionChanged, this,
27 &ConfigureDialog::UpdateVisibleTabs); 28 &ConfigureDialog::UpdateVisibleTabs);
28 29
@@ -98,6 +99,14 @@ void ConfigureDialog::PopulateSelectionList() {
98 } 99 }
99} 100}
100 101
102void ConfigureDialog::OnLanguageChanged(const QString& locale) {
103 emit LanguageChanged(locale);
104 // first apply the configuration, and then restore the display
105 ApplyConfiguration();
106 RetranslateUI();
107 SetConfiguration();
108}
109
101void ConfigureDialog::UpdateVisibleTabs() { 110void ConfigureDialog::UpdateVisibleTabs() {
102 const auto items = ui->selectorList->selectedItems(); 111 const auto items = ui->selectorList->selectedItems();
103 if (items.isEmpty()) { 112 if (items.isEmpty()) {
diff --git a/src/yuzu/configuration/configure_dialog.h b/src/yuzu/configuration/configure_dialog.h
index 2d3bfc2da..4289bc225 100644
--- a/src/yuzu/configuration/configure_dialog.h
+++ b/src/yuzu/configuration/configure_dialog.h
@@ -22,6 +22,12 @@ public:
22 22
23 void ApplyConfiguration(); 23 void ApplyConfiguration();
24 24
25private slots:
26 void OnLanguageChanged(const QString& locale);
27
28signals:
29 void LanguageChanged(const QString& locale);
30
25private: 31private:
26 void changeEvent(QEvent* event) override; 32 void changeEvent(QEvent* event) override;
27 33
diff --git a/src/yuzu/configuration/configure_general.cpp b/src/yuzu/configuration/configure_general.cpp
index 20316c9cc..c0dbd9855 100644
--- a/src/yuzu/configuration/configure_general.cpp
+++ b/src/yuzu/configuration/configure_general.cpp
@@ -19,9 +19,10 @@ ConfigureGeneral::ConfigureGeneral(QWidget* parent)
19 19
20 SetConfiguration(); 20 SetConfiguration();
21 21
22 connect(ui->toggle_frame_limit, &QCheckBox::stateChanged, ui->frame_limit, [this]() { 22 if (Settings::configuring_global) {
23 ui->frame_limit->setEnabled(ui->toggle_frame_limit->checkState() == Qt::Checked); 23 connect(ui->toggle_frame_limit, &QCheckBox::clicked, ui->frame_limit,
24 }); 24 [this]() { ui->frame_limit->setEnabled(ui->toggle_frame_limit->isChecked()); });
25 }
25} 26}
26 27
27ConfigureGeneral::~ConfigureGeneral() = default; 28ConfigureGeneral::~ConfigureGeneral() = default;
@@ -40,17 +41,12 @@ void ConfigureGeneral::SetConfiguration() {
40 ui->toggle_frame_limit->setChecked(Settings::values.use_frame_limit.GetValue()); 41 ui->toggle_frame_limit->setChecked(Settings::values.use_frame_limit.GetValue());
41 ui->frame_limit->setValue(Settings::values.frame_limit.GetValue()); 42 ui->frame_limit->setValue(Settings::values.frame_limit.GetValue());
42 43
43 if (!Settings::configuring_global) { 44 if (Settings::configuring_global) {
44 if (Settings::values.use_multi_core.UsingGlobal()) { 45 ui->frame_limit->setEnabled(Settings::values.use_frame_limit.GetValue());
45 ui->use_multi_core->setCheckState(Qt::PartiallyChecked); 46 } else {
46 } 47 ui->frame_limit->setEnabled(Settings::values.use_frame_limit.GetValue() &&
47 if (Settings::values.use_frame_limit.UsingGlobal()) { 48 use_frame_limit != ConfigurationShared::CheckState::Global);
48 ui->toggle_frame_limit->setCheckState(Qt::PartiallyChecked);
49 }
50 } 49 }
51
52 ui->frame_limit->setEnabled(ui->toggle_frame_limit->checkState() == Qt::Checked &&
53 ui->toggle_frame_limit->isEnabled());
54} 50}
55 51
56void ConfigureGeneral::ApplyConfiguration() { 52void ConfigureGeneral::ApplyConfiguration() {
@@ -71,9 +67,9 @@ void ConfigureGeneral::ApplyConfiguration() {
71 } 67 }
72 } else { 68 } else {
73 ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_multi_core, 69 ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_multi_core,
74 ui->use_multi_core); 70 ui->use_multi_core, use_multi_core);
75 71
76 bool global_frame_limit = ui->toggle_frame_limit->checkState() == Qt::PartiallyChecked; 72 bool global_frame_limit = use_frame_limit == ConfigurationShared::CheckState::Global;
77 Settings::values.use_frame_limit.SetGlobal(global_frame_limit); 73 Settings::values.use_frame_limit.SetGlobal(global_frame_limit);
78 Settings::values.frame_limit.SetGlobal(global_frame_limit); 74 Settings::values.frame_limit.SetGlobal(global_frame_limit);
79 if (!global_frame_limit) { 75 if (!global_frame_limit) {
@@ -109,6 +105,13 @@ void ConfigureGeneral::SetupPerGameUI() {
109 ui->toggle_background_pause->setVisible(false); 105 ui->toggle_background_pause->setVisible(false);
110 ui->toggle_hide_mouse->setVisible(false); 106 ui->toggle_hide_mouse->setVisible(false);
111 107
112 ui->toggle_frame_limit->setTristate(true); 108 ConfigurationShared::SetColoredTristate(ui->toggle_frame_limit, "toggle_frame_limit",
113 ui->use_multi_core->setTristate(true); 109 Settings::values.use_frame_limit, use_frame_limit);
110 ConfigurationShared::SetColoredTristate(ui->use_multi_core, "use_multi_core",
111 Settings::values.use_multi_core, use_multi_core);
112
113 connect(ui->toggle_frame_limit, &QCheckBox::clicked, ui->frame_limit, [this]() {
114 ui->frame_limit->setEnabled(ui->toggle_frame_limit->isChecked() &&
115 (use_frame_limit != ConfigurationShared::CheckState::Global));
116 });
114} 117}
diff --git a/src/yuzu/configuration/configure_general.h b/src/yuzu/configuration/configure_general.h
index 9c785c22e..323ffbd8f 100644
--- a/src/yuzu/configuration/configure_general.h
+++ b/src/yuzu/configuration/configure_general.h
@@ -7,6 +7,10 @@
7#include <memory> 7#include <memory>
8#include <QWidget> 8#include <QWidget>
9 9
10namespace ConfigurationShared {
11enum class CheckState;
12}
13
10class HotkeyRegistry; 14class HotkeyRegistry;
11 15
12namespace Ui { 16namespace Ui {
@@ -31,4 +35,7 @@ private:
31 void SetupPerGameUI(); 35 void SetupPerGameUI();
32 36
33 std::unique_ptr<Ui::ConfigureGeneral> ui; 37 std::unique_ptr<Ui::ConfigureGeneral> ui;
38
39 ConfigurationShared::CheckState use_frame_limit;
40 ConfigurationShared::CheckState use_multi_core;
34}; 41};
diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp
index cb4706bd6..3e42531c3 100644
--- a/src/yuzu/configuration/configure_graphics.cpp
+++ b/src/yuzu/configuration/configure_graphics.cpp
@@ -31,8 +31,14 @@ ConfigureGraphics::ConfigureGraphics(QWidget* parent)
31 31
32 SetConfiguration(); 32 SetConfiguration();
33 33
34 connect(ui->api, qOverload<int>(&QComboBox::currentIndexChanged), this, 34 connect(ui->api, qOverload<int>(&QComboBox::currentIndexChanged), this, [this] {
35 [this] { UpdateDeviceComboBox(); }); 35 UpdateDeviceComboBox();
36 if (!Settings::configuring_global) {
37 ConfigurationShared::SetHighlight(ui->api_layout, "api_layout",
38 ui->api->currentIndex() !=
39 ConfigurationShared::USE_GLOBAL_INDEX);
40 }
41 });
36 connect(ui->device, qOverload<int>(&QComboBox::activated), this, 42 connect(ui->device, qOverload<int>(&QComboBox::activated), this,
37 [this](int device) { UpdateDeviceSelection(device); }); 43 [this](int device) { UpdateDeviceSelection(device); });
38 44
@@ -65,25 +71,26 @@ void ConfigureGraphics::SetConfiguration() {
65 ui->api->setEnabled(runtime_lock); 71 ui->api->setEnabled(runtime_lock);
66 ui->use_asynchronous_gpu_emulation->setEnabled(runtime_lock); 72 ui->use_asynchronous_gpu_emulation->setEnabled(runtime_lock);
67 ui->use_disk_shader_cache->setEnabled(runtime_lock); 73 ui->use_disk_shader_cache->setEnabled(runtime_lock);
74 ui->use_disk_shader_cache->setChecked(Settings::values.use_disk_shader_cache.GetValue());
75 ui->use_asynchronous_gpu_emulation->setChecked(
76 Settings::values.use_asynchronous_gpu_emulation.GetValue());
68 77
69 if (Settings::configuring_global) { 78 if (Settings::configuring_global) {
70 ui->api->setCurrentIndex(static_cast<int>(Settings::values.renderer_backend.GetValue())); 79 ui->api->setCurrentIndex(static_cast<int>(Settings::values.renderer_backend.GetValue()));
71 ui->aspect_ratio_combobox->setCurrentIndex(Settings::values.aspect_ratio.GetValue()); 80 ui->aspect_ratio_combobox->setCurrentIndex(Settings::values.aspect_ratio.GetValue());
72 ui->use_disk_shader_cache->setChecked(Settings::values.use_disk_shader_cache.GetValue());
73 ui->use_asynchronous_gpu_emulation->setChecked(
74 Settings::values.use_asynchronous_gpu_emulation.GetValue());
75 } else { 81 } else {
76 ConfigurationShared::SetPerGameSetting(ui->use_disk_shader_cache,
77 &Settings::values.use_disk_shader_cache);
78 ConfigurationShared::SetPerGameSetting(ui->use_asynchronous_gpu_emulation,
79 &Settings::values.use_asynchronous_gpu_emulation);
80
81 ConfigurationShared::SetPerGameSetting(ui->api, &Settings::values.renderer_backend); 82 ConfigurationShared::SetPerGameSetting(ui->api, &Settings::values.renderer_backend);
83 ConfigurationShared::SetHighlight(ui->api_layout, "api_layout",
84 !Settings::values.renderer_backend.UsingGlobal());
82 ConfigurationShared::SetPerGameSetting(ui->aspect_ratio_combobox, 85 ConfigurationShared::SetPerGameSetting(ui->aspect_ratio_combobox,
83 &Settings::values.aspect_ratio); 86 &Settings::values.aspect_ratio);
84 87
85 ui->bg_combobox->setCurrentIndex(Settings::values.bg_red.UsingGlobal() ? 0 : 1); 88 ui->bg_combobox->setCurrentIndex(Settings::values.bg_red.UsingGlobal() ? 0 : 1);
86 ui->bg_button->setEnabled(!Settings::values.bg_red.UsingGlobal()); 89 ui->bg_button->setEnabled(!Settings::values.bg_red.UsingGlobal());
90 ConfigurationShared::SetHighlight(ui->ar_label, "ar_label",
91 !Settings::values.aspect_ratio.UsingGlobal());
92 ConfigurationShared::SetHighlight(ui->bg_layout, "bg_layout",
93 !Settings::values.bg_red.UsingGlobal());
87 } 94 }
88 95
89 UpdateBackgroundColorButton(QColor::fromRgbF(Settings::values.bg_red.GetValue(), 96 UpdateBackgroundColorButton(QColor::fromRgbF(Settings::values.bg_red.GetValue(),
@@ -135,9 +142,10 @@ void ConfigureGraphics::ApplyConfiguration() {
135 ui->aspect_ratio_combobox); 142 ui->aspect_ratio_combobox);
136 143
137 ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_disk_shader_cache, 144 ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_disk_shader_cache,
138 ui->use_disk_shader_cache); 145 ui->use_disk_shader_cache, use_disk_shader_cache);
139 ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_asynchronous_gpu_emulation, 146 ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_asynchronous_gpu_emulation,
140 ui->use_asynchronous_gpu_emulation); 147 ui->use_asynchronous_gpu_emulation,
148 use_asynchronous_gpu_emulation);
141 149
142 if (ui->bg_combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { 150 if (ui->bg_combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) {
143 Settings::values.bg_red.SetGlobal(true); 151 Settings::values.bg_red.SetGlobal(true);
@@ -241,10 +249,20 @@ void ConfigureGraphics::SetupPerGameUI() {
241 } 249 }
242 250
243 connect(ui->bg_combobox, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), this, 251 connect(ui->bg_combobox, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), this,
244 [this](int index) { ui->bg_button->setEnabled(index == 1); }); 252 [this](int index) {
245 253 ui->bg_button->setEnabled(index == 1);
246 ui->use_disk_shader_cache->setTristate(true); 254 ConfigurationShared::SetHighlight(ui->bg_layout, "bg_layout", index == 1);
247 ui->use_asynchronous_gpu_emulation->setTristate(true); 255 });
248 ConfigurationShared::InsertGlobalItem(ui->aspect_ratio_combobox); 256
249 ConfigurationShared::InsertGlobalItem(ui->api); 257 ConfigurationShared::SetColoredTristate(ui->use_disk_shader_cache, "use_disk_shader_cache",
258 Settings::values.use_disk_shader_cache,
259 use_disk_shader_cache);
260 ConfigurationShared::SetColoredTristate(
261 ui->use_asynchronous_gpu_emulation, "use_asynchronous_gpu_emulation",
262 Settings::values.use_asynchronous_gpu_emulation, use_asynchronous_gpu_emulation);
263
264 ConfigurationShared::SetColoredComboBox(ui->aspect_ratio_combobox, ui->ar_label, "ar_label",
265 Settings::values.aspect_ratio.GetValue(true));
266 ConfigurationShared::InsertGlobalItem(
267 ui->api, static_cast<int>(Settings::values.renderer_backend.GetValue(true)));
250} 268}
diff --git a/src/yuzu/configuration/configure_graphics.h b/src/yuzu/configuration/configure_graphics.h
index 24f01c739..b4961f719 100644
--- a/src/yuzu/configuration/configure_graphics.h
+++ b/src/yuzu/configuration/configure_graphics.h
@@ -10,6 +10,10 @@
10#include <QWidget> 10#include <QWidget>
11#include "core/settings.h" 11#include "core/settings.h"
12 12
13namespace ConfigurationShared {
14enum class CheckState;
15}
16
13namespace Ui { 17namespace Ui {
14class ConfigureGraphics; 18class ConfigureGraphics;
15} 19}
@@ -42,6 +46,9 @@ private:
42 std::unique_ptr<Ui::ConfigureGraphics> ui; 46 std::unique_ptr<Ui::ConfigureGraphics> ui;
43 QColor bg_color; 47 QColor bg_color;
44 48
49 ConfigurationShared::CheckState use_disk_shader_cache;
50 ConfigurationShared::CheckState use_asynchronous_gpu_emulation;
51
45 std::vector<QString> vulkan_devices; 52 std::vector<QString> vulkan_devices;
46 u32 vulkan_device{}; 53 u32 vulkan_device{};
47}; 54};
diff --git a/src/yuzu/configuration/configure_graphics.ui b/src/yuzu/configuration/configure_graphics.ui
index 62418fc14..62aa337e7 100644
--- a/src/yuzu/configuration/configure_graphics.ui
+++ b/src/yuzu/configuration/configure_graphics.ui
@@ -6,7 +6,7 @@
6 <rect> 6 <rect>
7 <x>0</x> 7 <x>0</x>
8 <y>0</y> 8 <y>0</y>
9 <width>400</width> 9 <width>437</width>
10 <height>321</height> 10 <height>321</height>
11 </rect> 11 </rect>
12 </property> 12 </property>
@@ -23,43 +23,56 @@
23 </property> 23 </property>
24 <layout class="QVBoxLayout" name="verticalLayout_3"> 24 <layout class="QVBoxLayout" name="verticalLayout_3">
25 <item> 25 <item>
26 <layout class="QHBoxLayout" name="horizontalLayout_4"> 26 <widget class="QWidget" name="api_layout" native="true">
27 <item> 27 <layout class="QGridLayout" name="gridLayout">
28 <widget class="QLabel" name="label_2"> 28 <property name="leftMargin">
29 <property name="text"> 29 <number>0</number>
30 <string>API:</string> 30 </property>
31 </property> 31 <property name="topMargin">
32 </widget> 32 <number>0</number>
33 </item> 33 </property>
34 <item> 34 <property name="rightMargin">
35 <widget class="QComboBox" name="api"> 35 <number>0</number>
36 <item> 36 </property>
37 <property name="bottomMargin">
38 <number>0</number>
39 </property>
40 <property name="horizontalSpacing">
41 <number>6</number>
42 </property>
43 <item row="0" column="0">
44 <widget class="QLabel" name="api_label">
37 <property name="text"> 45 <property name="text">
38 <string notr="true">OpenGL</string> 46 <string>API:</string>
39 </property> 47 </property>
40 </item> 48 </widget>
41 <item> 49 </item>
50 <item row="0" column="1">
51 <widget class="QComboBox" name="api">
52 <item>
53 <property name="text">
54 <string notr="true">OpenGL</string>
55 </property>
56 </item>
57 <item>
58 <property name="text">
59 <string notr="true">Vulkan</string>
60 </property>
61 </item>
62 </widget>
63 </item>
64 <item row="1" column="0">
65 <widget class="QLabel" name="device_label">
42 <property name="text"> 66 <property name="text">
43 <string notr="true">Vulkan</string> 67 <string>Device:</string>
44 </property> 68 </property>
45 </item> 69 </widget>
46 </widget> 70 </item>
47 </item> 71 <item row="1" column="1">
48 </layout> 72 <widget class="QComboBox" name="device"/>
49 </item> 73 </item>
50 <item> 74 </layout>
51 <layout class="QHBoxLayout" name="horizontalLayout_5"> 75 </widget>
52 <item>
53 <widget class="QLabel" name="label_3">
54 <property name="text">
55 <string>Device:</string>
56 </property>
57 </widget>
58 </item>
59 <item>
60 <widget class="QComboBox" name="device"/>
61 </item>
62 </layout>
63 </item> 76 </item>
64 </layout> 77 </layout>
65 </widget> 78 </widget>
@@ -85,96 +98,133 @@
85 </widget> 98 </widget>
86 </item> 99 </item>
87 <item> 100 <item>
88 <layout class="QHBoxLayout" name="horizontalLayout_6"> 101 <widget class="QWidget" name="aspect_ratio_layout" native="true">
89 <item> 102 <layout class="QHBoxLayout" name="horizontalLayout_6">
90 <widget class="QLabel" name="ar_label"> 103 <property name="leftMargin">
91 <property name="text"> 104 <number>0</number>
92 <string>Aspect Ratio:</string> 105 </property>
93 </property> 106 <property name="topMargin">
94 </widget> 107 <number>0</number>
95 </item> 108 </property>
96 <item> 109 <property name="rightMargin">
97 <widget class="QComboBox" name="aspect_ratio_combobox"> 110 <number>0</number>
98 <item> 111 </property>
99 <property name="text"> 112 <property name="bottomMargin">
100 <string>Default (16:9)</string> 113 <number>0</number>
101 </property> 114 </property>
102 </item> 115 <item>
103 <item> 116 <widget class="QLabel" name="ar_label">
104 <property name="text">
105 <string>Force 4:3</string>
106 </property>
107 </item>
108 <item>
109 <property name="text">
110 <string>Force 21:9</string>
111 </property>
112 </item>
113 <item>
114 <property name="text"> 117 <property name="text">
115 <string>Stretch to Window</string> 118 <string>Aspect Ratio:</string>
116 </property> 119 </property>
117 </item> 120 </widget>
118 </widget> 121 </item>
119 </item> 122 <item>
120 </layout> 123 <widget class="QComboBox" name="aspect_ratio_combobox">
124 <item>
125 <property name="text">
126 <string>Default (16:9)</string>
127 </property>
128 </item>
129 <item>
130 <property name="text">
131 <string>Force 4:3</string>
132 </property>
133 </item>
134 <item>
135 <property name="text">
136 <string>Force 21:9</string>
137 </property>
138 </item>
139 <item>
140 <property name="text">
141 <string>Stretch to Window</string>
142 </property>
143 </item>
144 </widget>
145 </item>
146 </layout>
147 </widget>
121 </item> 148 </item>
122 <item> 149 <item>
123 <layout class="QHBoxLayout" name="horizontalLayout_3"> 150 <widget class="QWidget" name="bg_layout" native="true">
124 <item> 151 <property name="sizePolicy">
125 <widget class="QComboBox" name="bg_combobox"> 152 <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
126 <property name="currentText"> 153 <horstretch>0</horstretch>
127 <string>Use global background color</string> 154 <verstretch>0</verstretch>
128 </property> 155 </sizepolicy>
129 <property name="currentIndex"> 156 </property>
130 <number>0</number> 157 <layout class="QHBoxLayout" name="horizontalLayout_3">
131 </property> 158 <property name="spacing">
132 <property name="maxVisibleItems"> 159 <number>6</number>
133 <number>10</number> 160 </property>
134 </property> 161 <property name="leftMargin">
135 <item> 162 <number>0</number>
136 <property name="text"> 163 </property>
164 <property name="topMargin">
165 <number>0</number>
166 </property>
167 <property name="rightMargin">
168 <number>0</number>
169 </property>
170 <property name="bottomMargin">
171 <number>0</number>
172 </property>
173 <item>
174 <widget class="QComboBox" name="bg_combobox">
175 <property name="currentText">
137 <string>Use global background color</string> 176 <string>Use global background color</string>
138 </property> 177 </property>
139 </item> 178 <property name="currentIndex">
140 <item> 179 <number>0</number>
180 </property>
181 <property name="maxVisibleItems">
182 <number>10</number>
183 </property>
184 <item>
185 <property name="text">
186 <string>Use global background color</string>
187 </property>
188 </item>
189 <item>
190 <property name="text">
191 <string>Set background color:</string>
192 </property>
193 </item>
194 </widget>
195 </item>
196 <item>
197 <widget class="QLabel" name="bg_label">
141 <property name="text"> 198 <property name="text">
142 <string>Set background color:</string> 199 <string>Background Color:</string>
143 </property> 200 </property>
144 </item> 201 </widget>
145 </widget> 202 </item>
146 </item> 203 <item>
147 <item> 204 <spacer name="horizontalSpacer">
148 <widget class="QLabel" name="bg_label"> 205 <property name="orientation">
149 <property name="text"> 206 <enum>Qt::Horizontal</enum>
150 <string>Background Color:</string> 207 </property>
151 </property> 208 <property name="sizeHint" stdset="0">
152 </widget> 209 <size>
153 </item> 210 <width>40</width>
154 <item> 211 <height>20</height>
155 <spacer name="horizontalSpacer"> 212 </size>
156 <property name="orientation"> 213 </property>
157 <enum>Qt::Horizontal</enum> 214 </spacer>
158 </property> 215 </item>
159 <property name="sizeHint" stdset="0"> 216 <item>
160 <size> 217 <widget class="QPushButton" name="bg_button">
161 <width>40</width> 218 <property name="maximumSize">
162 <height>20</height> 219 <size>
163 </size> 220 <width>40</width>
164 </property> 221 <height>16777215</height>
165 </spacer> 222 </size>
166 </item> 223 </property>
167 <item> 224 </widget>
168 <widget class="QPushButton" name="bg_button"> 225 </item>
169 <property name="maximumSize"> 226 </layout>
170 <size> 227 </widget>
171 <width>40</width>
172 <height>16777215</height>
173 </size>
174 </property>
175 </widget>
176 </item>
177 </layout>
178 </item> 228 </item>
179 </layout> 229 </layout>
180 </widget> 230 </widget>
diff --git a/src/yuzu/configuration/configure_graphics_advanced.cpp b/src/yuzu/configuration/configure_graphics_advanced.cpp
index 7c0fa7ec5..8b9180811 100644
--- a/src/yuzu/configuration/configure_graphics_advanced.cpp
+++ b/src/yuzu/configuration/configure_graphics_advanced.cpp
@@ -24,29 +24,29 @@ void ConfigureGraphicsAdvanced::SetConfiguration() {
24 const bool runtime_lock = !Core::System::GetInstance().IsPoweredOn(); 24 const bool runtime_lock = !Core::System::GetInstance().IsPoweredOn();
25 ui->use_vsync->setEnabled(runtime_lock); 25 ui->use_vsync->setEnabled(runtime_lock);
26 ui->use_assembly_shaders->setEnabled(runtime_lock); 26 ui->use_assembly_shaders->setEnabled(runtime_lock);
27 ui->use_asynchronous_shaders->setEnabled(runtime_lock);
27 ui->force_30fps_mode->setEnabled(runtime_lock); 28 ui->force_30fps_mode->setEnabled(runtime_lock);
28 ui->anisotropic_filtering_combobox->setEnabled(runtime_lock); 29 ui->anisotropic_filtering_combobox->setEnabled(runtime_lock);
29 30
31 ui->use_vsync->setChecked(Settings::values.use_vsync.GetValue());
32 ui->use_assembly_shaders->setChecked(Settings::values.use_assembly_shaders.GetValue());
33 ui->use_asynchronous_shaders->setChecked(Settings::values.use_asynchronous_shaders.GetValue());
34 ui->use_fast_gpu_time->setChecked(Settings::values.use_fast_gpu_time.GetValue());
35 ui->force_30fps_mode->setChecked(Settings::values.force_30fps_mode.GetValue());
36
30 if (Settings::configuring_global) { 37 if (Settings::configuring_global) {
31 ui->gpu_accuracy->setCurrentIndex( 38 ui->gpu_accuracy->setCurrentIndex(
32 static_cast<int>(Settings::values.gpu_accuracy.GetValue())); 39 static_cast<int>(Settings::values.gpu_accuracy.GetValue()));
33 ui->use_vsync->setChecked(Settings::values.use_vsync.GetValue());
34 ui->use_assembly_shaders->setChecked(Settings::values.use_assembly_shaders.GetValue());
35 ui->use_fast_gpu_time->setChecked(Settings::values.use_fast_gpu_time.GetValue());
36 ui->force_30fps_mode->setChecked(Settings::values.force_30fps_mode.GetValue());
37 ui->anisotropic_filtering_combobox->setCurrentIndex( 40 ui->anisotropic_filtering_combobox->setCurrentIndex(
38 Settings::values.max_anisotropy.GetValue()); 41 Settings::values.max_anisotropy.GetValue());
39 } else { 42 } else {
40 ConfigurationShared::SetPerGameSetting(ui->gpu_accuracy, &Settings::values.gpu_accuracy); 43 ConfigurationShared::SetPerGameSetting(ui->gpu_accuracy, &Settings::values.gpu_accuracy);
41 ConfigurationShared::SetPerGameSetting(ui->use_vsync, &Settings::values.use_vsync);
42 ConfigurationShared::SetPerGameSetting(ui->use_assembly_shaders,
43 &Settings::values.use_assembly_shaders);
44 ConfigurationShared::SetPerGameSetting(ui->use_fast_gpu_time,
45 &Settings::values.use_fast_gpu_time);
46 ConfigurationShared::SetPerGameSetting(ui->force_30fps_mode,
47 &Settings::values.force_30fps_mode);
48 ConfigurationShared::SetPerGameSetting(ui->anisotropic_filtering_combobox, 44 ConfigurationShared::SetPerGameSetting(ui->anisotropic_filtering_combobox,
49 &Settings::values.max_anisotropy); 45 &Settings::values.max_anisotropy);
46 ConfigurationShared::SetHighlight(ui->label_gpu_accuracy, "label_gpu_accuracy",
47 !Settings::values.gpu_accuracy.UsingGlobal());
48 ConfigurationShared::SetHighlight(ui->af_label, "af_label",
49 !Settings::values.max_anisotropy.UsingGlobal());
50 } 50 }
51} 51}
52 52
@@ -67,6 +67,14 @@ void ConfigureGraphicsAdvanced::ApplyConfiguration() {
67 if (Settings::values.use_assembly_shaders.UsingGlobal()) { 67 if (Settings::values.use_assembly_shaders.UsingGlobal()) {
68 Settings::values.use_assembly_shaders.SetValue(ui->use_assembly_shaders->isChecked()); 68 Settings::values.use_assembly_shaders.SetValue(ui->use_assembly_shaders->isChecked());
69 } 69 }
70 if (Settings::values.use_asynchronous_shaders.UsingGlobal()) {
71 Settings::values.use_asynchronous_shaders.SetValue(
72 ui->use_asynchronous_shaders->isChecked());
73 }
74 if (Settings::values.use_asynchronous_shaders.UsingGlobal()) {
75 Settings::values.use_asynchronous_shaders.SetValue(
76 ui->use_asynchronous_shaders->isChecked());
77 }
70 if (Settings::values.use_fast_gpu_time.UsingGlobal()) { 78 if (Settings::values.use_fast_gpu_time.UsingGlobal()) {
71 Settings::values.use_fast_gpu_time.SetValue(ui->use_fast_gpu_time->isChecked()); 79 Settings::values.use_fast_gpu_time.SetValue(ui->use_fast_gpu_time->isChecked());
72 } 80 }
@@ -80,13 +88,17 @@ void ConfigureGraphicsAdvanced::ApplyConfiguration() {
80 } else { 88 } else {
81 ConfigurationShared::ApplyPerGameSetting(&Settings::values.max_anisotropy, 89 ConfigurationShared::ApplyPerGameSetting(&Settings::values.max_anisotropy,
82 ui->anisotropic_filtering_combobox); 90 ui->anisotropic_filtering_combobox);
83 ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_vsync, ui->use_vsync); 91 ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_vsync, ui->use_vsync,
92 use_vsync);
84 ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_assembly_shaders, 93 ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_assembly_shaders,
85 ui->use_assembly_shaders); 94 ui->use_assembly_shaders, use_assembly_shaders);
95 ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_asynchronous_shaders,
96 ui->use_asynchronous_shaders,
97 use_asynchronous_shaders);
86 ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_fast_gpu_time, 98 ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_fast_gpu_time,
87 ui->use_fast_gpu_time); 99 ui->use_fast_gpu_time, use_fast_gpu_time);
88 ConfigurationShared::ApplyPerGameSetting(&Settings::values.force_30fps_mode, 100 ConfigurationShared::ApplyPerGameSetting(&Settings::values.force_30fps_mode,
89 ui->force_30fps_mode); 101 ui->force_30fps_mode, force_30fps_mode);
90 ConfigurationShared::ApplyPerGameSetting(&Settings::values.max_anisotropy, 102 ConfigurationShared::ApplyPerGameSetting(&Settings::values.max_anisotropy,
91 ui->anisotropic_filtering_combobox); 103 ui->anisotropic_filtering_combobox);
92 104
@@ -117,6 +129,8 @@ void ConfigureGraphicsAdvanced::SetupPerGameUI() {
117 ui->gpu_accuracy->setEnabled(Settings::values.gpu_accuracy.UsingGlobal()); 129 ui->gpu_accuracy->setEnabled(Settings::values.gpu_accuracy.UsingGlobal());
118 ui->use_vsync->setEnabled(Settings::values.use_vsync.UsingGlobal()); 130 ui->use_vsync->setEnabled(Settings::values.use_vsync.UsingGlobal());
119 ui->use_assembly_shaders->setEnabled(Settings::values.use_assembly_shaders.UsingGlobal()); 131 ui->use_assembly_shaders->setEnabled(Settings::values.use_assembly_shaders.UsingGlobal());
132 ui->use_asynchronous_shaders->setEnabled(
133 Settings::values.use_asynchronous_shaders.UsingGlobal());
120 ui->use_fast_gpu_time->setEnabled(Settings::values.use_fast_gpu_time.UsingGlobal()); 134 ui->use_fast_gpu_time->setEnabled(Settings::values.use_fast_gpu_time.UsingGlobal());
121 ui->force_30fps_mode->setEnabled(Settings::values.force_30fps_mode.UsingGlobal()); 135 ui->force_30fps_mode->setEnabled(Settings::values.force_30fps_mode.UsingGlobal());
122 ui->anisotropic_filtering_combobox->setEnabled( 136 ui->anisotropic_filtering_combobox->setEnabled(
@@ -125,10 +139,22 @@ void ConfigureGraphicsAdvanced::SetupPerGameUI() {
125 return; 139 return;
126 } 140 }
127 141
128 ConfigurationShared::InsertGlobalItem(ui->gpu_accuracy); 142 ConfigurationShared::SetColoredTristate(ui->use_vsync, "use_vsync", Settings::values.use_vsync,
129 ui->use_vsync->setTristate(true); 143 use_vsync);
130 ui->use_assembly_shaders->setTristate(true); 144 ConfigurationShared::SetColoredTristate(ui->use_assembly_shaders, "use_assembly_shaders",
131 ui->use_fast_gpu_time->setTristate(true); 145 Settings::values.use_assembly_shaders,
132 ui->force_30fps_mode->setTristate(true); 146 use_assembly_shaders);
133 ConfigurationShared::InsertGlobalItem(ui->anisotropic_filtering_combobox); 147 ConfigurationShared::SetColoredTristate(
148 ui->use_asynchronous_shaders, "use_asynchronous_shaders",
149 Settings::values.use_asynchronous_shaders, use_asynchronous_shaders);
150 ConfigurationShared::SetColoredTristate(ui->use_fast_gpu_time, "use_fast_gpu_time",
151 Settings::values.use_fast_gpu_time, use_fast_gpu_time);
152 ConfigurationShared::SetColoredTristate(ui->force_30fps_mode, "force_30fps_mode",
153 Settings::values.force_30fps_mode, force_30fps_mode);
154 ConfigurationShared::SetColoredComboBox(
155 ui->gpu_accuracy, ui->label_gpu_accuracy, "label_gpu_accuracy",
156 static_cast<int>(Settings::values.gpu_accuracy.GetValue(true)));
157 ConfigurationShared::SetColoredComboBox(
158 ui->anisotropic_filtering_combobox, ui->af_label, "af_label",
159 static_cast<int>(Settings::values.max_anisotropy.GetValue(true)));
134} 160}
diff --git a/src/yuzu/configuration/configure_graphics_advanced.h b/src/yuzu/configuration/configure_graphics_advanced.h
index c043588ff..3c4f6f7bb 100644
--- a/src/yuzu/configuration/configure_graphics_advanced.h
+++ b/src/yuzu/configuration/configure_graphics_advanced.h
@@ -7,6 +7,10 @@
7#include <memory> 7#include <memory>
8#include <QWidget> 8#include <QWidget>
9 9
10namespace ConfigurationShared {
11enum class CheckState;
12}
13
10namespace Ui { 14namespace Ui {
11class ConfigureGraphicsAdvanced; 15class ConfigureGraphicsAdvanced;
12} 16}
@@ -29,4 +33,10 @@ private:
29 void SetupPerGameUI(); 33 void SetupPerGameUI();
30 34
31 std::unique_ptr<Ui::ConfigureGraphicsAdvanced> ui; 35 std::unique_ptr<Ui::ConfigureGraphicsAdvanced> ui;
36
37 ConfigurationShared::CheckState use_vsync;
38 ConfigurationShared::CheckState use_assembly_shaders;
39 ConfigurationShared::CheckState use_asynchronous_shaders;
40 ConfigurationShared::CheckState use_fast_gpu_time;
41 ConfigurationShared::CheckState force_30fps_mode;
32}; 42};
diff --git a/src/yuzu/configuration/configure_graphics_advanced.ui b/src/yuzu/configuration/configure_graphics_advanced.ui
index 0021607ac..6a0d29c27 100644
--- a/src/yuzu/configuration/configure_graphics_advanced.ui
+++ b/src/yuzu/configuration/configure_graphics_advanced.ui
@@ -6,7 +6,7 @@
6 <rect> 6 <rect>
7 <x>0</x> 7 <x>0</x>
8 <y>0</y> 8 <y>0</y>
9 <width>400</width> 9 <width>404</width>
10 <height>321</height> 10 <height>321</height>
11 </rect> 11 </rect>
12 </property> 12 </property>
@@ -23,34 +23,48 @@
23 </property> 23 </property>
24 <layout class="QVBoxLayout" name="verticalLayout_3"> 24 <layout class="QVBoxLayout" name="verticalLayout_3">
25 <item> 25 <item>
26 <layout class="QHBoxLayout" name="horizontalLayout_2"> 26 <widget class="QWidget" name="gpu_accuracy_layout" native="true">
27 <item> 27 <layout class="QHBoxLayout" name="horizontalLayout_2">
28 <widget class="QLabel" name="label_gpu_accuracy"> 28 <property name="leftMargin">
29 <property name="text"> 29 <number>0</number>
30 <string>Accuracy Level:</string> 30 </property>
31 </property> 31 <property name="topMargin">
32 </widget> 32 <number>0</number>
33 </item> 33 </property>
34 <item> 34 <property name="rightMargin">
35 <widget class="QComboBox" name="gpu_accuracy"> 35 <number>0</number>
36 <item> 36 </property>
37 <property name="bottomMargin">
38 <number>0</number>
39 </property>
40 <item>
41 <widget class="QLabel" name="label_gpu_accuracy">
37 <property name="text"> 42 <property name="text">
38 <string notr="true">Normal</string> 43 <string>Accuracy Level:</string>
39 </property> 44 </property>
40 </item> 45 </widget>
41 <item> 46 </item>
42 <property name="text"> 47 <item>
43 <string notr="true">High</string> 48 <widget class="QComboBox" name="gpu_accuracy">
44 </property> 49 <item>
45 </item> 50 <property name="text">
46 <item> 51 <string notr="true">Normal</string>
47 <property name="text"> 52 </property>
48 <string notr="true">Extreme(very slow)</string> 53 </item>
49 </property> 54 <item>
50 </item> 55 <property name="text">
51 </widget> 56 <string notr="true">High</string>
52 </item> 57 </property>
53 </layout> 58 </item>
59 <item>
60 <property name="text">
61 <string notr="true">Extreme(very slow)</string>
62 </property>
63 </item>
64 </widget>
65 </item>
66 </layout>
67 </widget>
54 </item> 68 </item>
55 <item> 69 <item>
56 <widget class="QCheckBox" name="use_vsync"> 70 <widget class="QCheckBox" name="use_vsync">
@@ -73,6 +87,16 @@
73 </widget> 87 </widget>
74 </item> 88 </item>
75 <item> 89 <item>
90 <widget class="QCheckBox" name="use_asynchronous_shaders">
91 <property name="toolTip">
92 <string>Enables asynchronous shader compilation, which may reduce shader stutter. This feature is experimental.</string>
93 </property>
94 <property name="text">
95 <string>Use asynchronous shader building (experimental, OpenGL or Assembly shaders only)</string>
96 </property>
97 </widget>
98 </item>
99 <item>
76 <widget class="QCheckBox" name="force_30fps_mode"> 100 <widget class="QCheckBox" name="force_30fps_mode">
77 <property name="text"> 101 <property name="text">
78 <string>Force 30 FPS mode</string> 102 <string>Force 30 FPS mode</string>
@@ -87,44 +111,58 @@
87 </widget> 111 </widget>
88 </item> 112 </item>
89 <item> 113 <item>
90 <layout class="QHBoxLayout" name="horizontalLayout_1"> 114 <widget class="QWidget" name="af_layout" native="true">
91 <item> 115 <layout class="QHBoxLayout" name="horizontalLayout_1">
92 <widget class="QLabel" name="af_label"> 116 <property name="leftMargin">
93 <property name="text"> 117 <number>0</number>
94 <string>Anisotropic Filtering:</string> 118 </property>
95 </property> 119 <property name="topMargin">
96 </widget> 120 <number>0</number>
97 </item> 121 </property>
98 <item> 122 <property name="rightMargin">
99 <widget class="QComboBox" name="anisotropic_filtering_combobox"> 123 <number>0</number>
100 <item> 124 </property>
101 <property name="text"> 125 <property name="bottomMargin">
102 <string>Default</string> 126 <number>0</number>
103 </property> 127 </property>
104 </item> 128 <item>
105 <item> 129 <widget class="QLabel" name="af_label">
106 <property name="text">
107 <string>2x</string>
108 </property>
109 </item>
110 <item>
111 <property name="text"> 130 <property name="text">
112 <string>4x</string> 131 <string>Anisotropic Filtering:</string>
113 </property> 132 </property>
114 </item> 133 </widget>
115 <item> 134 </item>
116 <property name="text"> 135 <item>
117 <string>8x</string> 136 <widget class="QComboBox" name="anisotropic_filtering_combobox">
118 </property> 137 <item>
119 </item> 138 <property name="text">
120 <item> 139 <string>Default</string>
121 <property name="text"> 140 </property>
122 <string>16x</string> 141 </item>
123 </property> 142 <item>
124 </item> 143 <property name="text">
125 </widget> 144 <string>2x</string>
126 </item> 145 </property>
127 </layout> 146 </item>
147 <item>
148 <property name="text">
149 <string>4x</string>
150 </property>
151 </item>
152 <item>
153 <property name="text">
154 <string>8x</string>
155 </property>
156 </item>
157 <item>
158 <property name="text">
159 <string>16x</string>
160 </property>
161 </item>
162 </widget>
163 </item>
164 </layout>
165 </widget>
128 </item> 166 </item>
129 </layout> 167 </layout>
130 </widget> 168 </widget>
diff --git a/src/yuzu/configuration/configure_system.cpp b/src/yuzu/configuration/configure_system.cpp
index 68e02738b..0c4daf147 100644
--- a/src/yuzu/configuration/configure_system.cpp
+++ b/src/yuzu/configuration/configure_system.cpp
@@ -67,21 +67,21 @@ void ConfigureSystem::SetConfiguration() {
67 const auto rtc_time = Settings::values.custom_rtc.GetValue().value_or( 67 const auto rtc_time = Settings::values.custom_rtc.GetValue().value_or(
68 std::chrono::seconds(QDateTime::currentSecsSinceEpoch())); 68 std::chrono::seconds(QDateTime::currentSecsSinceEpoch()));
69 69
70 ui->rng_seed_checkbox->setChecked(Settings::values.rng_seed.GetValue().has_value());
71 ui->rng_seed_edit->setEnabled(Settings::values.rng_seed.GetValue().has_value() &&
72 Settings::values.rng_seed.UsingGlobal());
73 ui->rng_seed_edit->setText(rng_seed);
74
75 ui->custom_rtc_checkbox->setChecked(Settings::values.custom_rtc.GetValue().has_value());
76 ui->custom_rtc_edit->setEnabled(Settings::values.custom_rtc.GetValue().has_value() &&
77 Settings::values.rng_seed.UsingGlobal());
78 ui->custom_rtc_edit->setDateTime(QDateTime::fromSecsSinceEpoch(rtc_time.count()));
79
70 if (Settings::configuring_global) { 80 if (Settings::configuring_global) {
71 ui->combo_language->setCurrentIndex(Settings::values.language_index.GetValue()); 81 ui->combo_language->setCurrentIndex(Settings::values.language_index.GetValue());
72 ui->combo_region->setCurrentIndex(Settings::values.region_index.GetValue()); 82 ui->combo_region->setCurrentIndex(Settings::values.region_index.GetValue());
73 ui->combo_time_zone->setCurrentIndex(Settings::values.time_zone_index.GetValue()); 83 ui->combo_time_zone->setCurrentIndex(Settings::values.time_zone_index.GetValue());
74 ui->combo_sound->setCurrentIndex(Settings::values.sound_index.GetValue()); 84 ui->combo_sound->setCurrentIndex(Settings::values.sound_index.GetValue());
75
76 ui->rng_seed_checkbox->setChecked(Settings::values.rng_seed.GetValue().has_value());
77 ui->rng_seed_edit->setEnabled(Settings::values.rng_seed.GetValue().has_value() &&
78 Settings::values.rng_seed.UsingGlobal());
79 ui->rng_seed_edit->setText(rng_seed);
80
81 ui->custom_rtc_checkbox->setChecked(Settings::values.custom_rtc.GetValue().has_value());
82 ui->custom_rtc_edit->setEnabled(Settings::values.custom_rtc.GetValue().has_value() &&
83 Settings::values.rng_seed.UsingGlobal());
84 ui->custom_rtc_edit->setDateTime(QDateTime::fromSecsSinceEpoch(rtc_time.count()));
85 } else { 85 } else {
86 ConfigurationShared::SetPerGameSetting(ui->combo_language, 86 ConfigurationShared::SetPerGameSetting(ui->combo_language,
87 &Settings::values.language_index); 87 &Settings::values.language_index);
@@ -90,27 +90,14 @@ void ConfigureSystem::SetConfiguration() {
90 &Settings::values.time_zone_index); 90 &Settings::values.time_zone_index);
91 ConfigurationShared::SetPerGameSetting(ui->combo_sound, &Settings::values.sound_index); 91 ConfigurationShared::SetPerGameSetting(ui->combo_sound, &Settings::values.sound_index);
92 92
93 if (Settings::values.rng_seed.UsingGlobal()) { 93 ConfigurationShared::SetHighlight(ui->label_language, "label_language",
94 ui->rng_seed_checkbox->setCheckState(Qt::PartiallyChecked); 94 !Settings::values.language_index.UsingGlobal());
95 } else { 95 ConfigurationShared::SetHighlight(ui->label_region, "label_region",
96 ui->rng_seed_checkbox->setCheckState( 96 !Settings::values.region_index.UsingGlobal());
97 Settings::values.rng_seed.GetValue().has_value() ? Qt::Checked : Qt::Unchecked); 97 ConfigurationShared::SetHighlight(ui->label_timezone, "label_timezone",
98 ui->rng_seed_edit->setEnabled(Settings::values.rng_seed.GetValue().has_value()); 98 !Settings::values.time_zone_index.UsingGlobal());
99 if (Settings::values.rng_seed.GetValue().has_value()) { 99 ConfigurationShared::SetHighlight(ui->label_sound, "label_sound",
100 ui->rng_seed_edit->setText(rng_seed); 100 !Settings::values.sound_index.UsingGlobal());
101 }
102 }
103
104 if (Settings::values.custom_rtc.UsingGlobal()) {
105 ui->custom_rtc_checkbox->setCheckState(Qt::PartiallyChecked);
106 } else {
107 ui->custom_rtc_checkbox->setCheckState(
108 Settings::values.custom_rtc.GetValue().has_value() ? Qt::Checked : Qt::Unchecked);
109 ui->custom_rtc_edit->setEnabled(Settings::values.custom_rtc.GetValue().has_value());
110 if (Settings::values.custom_rtc.GetValue().has_value()) {
111 ui->custom_rtc_edit->setDateTime(QDateTime::fromSecsSinceEpoch(rtc_time.count()));
112 }
113 }
114 } 101 }
115} 102}
116 103
@@ -161,37 +148,44 @@ void ConfigureSystem::ApplyConfiguration() {
161 ui->combo_time_zone); 148 ui->combo_time_zone);
162 ConfigurationShared::ApplyPerGameSetting(&Settings::values.sound_index, ui->combo_sound); 149 ConfigurationShared::ApplyPerGameSetting(&Settings::values.sound_index, ui->combo_sound);
163 150
164 switch (ui->rng_seed_checkbox->checkState()) { 151 switch (use_rng_seed) {
165 case Qt::Checked: 152 case ConfigurationShared::CheckState::On:
166 Settings::values.rng_seed.SetGlobal(false); 153 case ConfigurationShared::CheckState::Off:
167 Settings::values.rng_seed.SetValue(ui->rng_seed_edit->text().toULongLong(nullptr, 16));
168 break;
169 case Qt::Unchecked:
170 Settings::values.rng_seed.SetGlobal(false); 154 Settings::values.rng_seed.SetGlobal(false);
171 Settings::values.rng_seed.SetValue(std::nullopt); 155 if (ui->rng_seed_checkbox->isChecked()) {
156 Settings::values.rng_seed.SetValue(
157 ui->rng_seed_edit->text().toULongLong(nullptr, 16));
158 } else {
159 Settings::values.rng_seed.SetValue(std::nullopt);
160 }
172 break; 161 break;
173 case Qt::PartiallyChecked: 162 case ConfigurationShared::CheckState::Global:
174 Settings::values.rng_seed.SetGlobal(false); 163 Settings::values.rng_seed.SetGlobal(false);
175 Settings::values.rng_seed.SetValue(std::nullopt); 164 Settings::values.rng_seed.SetValue(std::nullopt);
176 Settings::values.rng_seed.SetGlobal(true); 165 Settings::values.rng_seed.SetGlobal(true);
177 break; 166 break;
167 case ConfigurationShared::CheckState::Count:
168 break;
178 } 169 }
179 170
180 switch (ui->custom_rtc_checkbox->checkState()) { 171 switch (use_custom_rtc) {
181 case Qt::Checked: 172 case ConfigurationShared::CheckState::On:
182 Settings::values.custom_rtc.SetGlobal(false); 173 case ConfigurationShared::CheckState::Off:
183 Settings::values.custom_rtc.SetValue(
184 std::chrono::seconds(ui->custom_rtc_edit->dateTime().toSecsSinceEpoch()));
185 break;
186 case Qt::Unchecked:
187 Settings::values.custom_rtc.SetGlobal(false); 174 Settings::values.custom_rtc.SetGlobal(false);
188 Settings::values.custom_rtc.SetValue(std::nullopt); 175 if (ui->custom_rtc_checkbox->isChecked()) {
176 Settings::values.custom_rtc.SetValue(
177 std::chrono::seconds(ui->custom_rtc_edit->dateTime().toSecsSinceEpoch()));
178 } else {
179 Settings::values.custom_rtc.SetValue(std::nullopt);
180 }
189 break; 181 break;
190 case Qt::PartiallyChecked: 182 case ConfigurationShared::CheckState::Global:
191 Settings::values.custom_rtc.SetGlobal(false); 183 Settings::values.custom_rtc.SetGlobal(false);
192 Settings::values.custom_rtc.SetValue(std::nullopt); 184 Settings::values.custom_rtc.SetValue(std::nullopt);
193 Settings::values.custom_rtc.SetGlobal(true); 185 Settings::values.custom_rtc.SetGlobal(true);
194 break; 186 break;
187 case ConfigurationShared::CheckState::Count:
188 break;
195 } 189 }
196 } 190 }
197 191
@@ -229,10 +223,23 @@ void ConfigureSystem::SetupPerGameUI() {
229 return; 223 return;
230 } 224 }
231 225
232 ConfigurationShared::InsertGlobalItem(ui->combo_language); 226 ConfigurationShared::SetColoredComboBox(ui->combo_language, ui->label_language,
233 ConfigurationShared::InsertGlobalItem(ui->combo_region); 227 "label_language",
234 ConfigurationShared::InsertGlobalItem(ui->combo_time_zone); 228 Settings::values.language_index.GetValue(true));
235 ConfigurationShared::InsertGlobalItem(ui->combo_sound); 229 ConfigurationShared::SetColoredComboBox(ui->combo_region, ui->label_region, "label_region",
236 ui->rng_seed_checkbox->setTristate(true); 230 Settings::values.region_index.GetValue(true));
237 ui->custom_rtc_checkbox->setTristate(true); 231 ConfigurationShared::SetColoredComboBox(ui->combo_time_zone, ui->label_timezone,
232 "label_timezone",
233 Settings::values.time_zone_index.GetValue(true));
234 ConfigurationShared::SetColoredComboBox(ui->combo_sound, ui->label_sound, "label_sound",
235 Settings::values.sound_index.GetValue(true));
236
237 ConfigurationShared::SetColoredTristate(
238 ui->rng_seed_checkbox, "rng_seed_checkbox", Settings::values.rng_seed.UsingGlobal(),
239 Settings::values.rng_seed.GetValue().has_value(),
240 Settings::values.rng_seed.GetValue(true).has_value(), use_rng_seed);
241 ConfigurationShared::SetColoredTristate(
242 ui->custom_rtc_checkbox, "custom_rtc_checkbox", Settings::values.custom_rtc.UsingGlobal(),
243 Settings::values.custom_rtc.GetValue().has_value(),
244 Settings::values.custom_rtc.GetValue(true).has_value(), use_custom_rtc);
238} 245}
diff --git a/src/yuzu/configuration/configure_system.h b/src/yuzu/configuration/configure_system.h
index f317ef8b5..fc5cd2945 100644
--- a/src/yuzu/configuration/configure_system.h
+++ b/src/yuzu/configuration/configure_system.h
@@ -9,6 +9,10 @@
9#include <QList> 9#include <QList>
10#include <QWidget> 10#include <QWidget>
11 11
12namespace ConfigurationShared {
13enum class CheckState;
14}
15
12namespace Ui { 16namespace Ui {
13class ConfigureSystem; 17class ConfigureSystem;
14} 18}
@@ -41,4 +45,7 @@ private:
41 int region_index = 0; 45 int region_index = 0;
42 int time_zone_index = 0; 46 int time_zone_index = 0;
43 int sound_index = 0; 47 int sound_index = 0;
48
49 ConfigurationShared::CheckState use_rng_seed;
50 ConfigurationShared::CheckState use_custom_rtc;
44}; 51};
diff --git a/src/yuzu/configuration/configure_system.ui b/src/yuzu/configuration/configure_system.ui
index 9c8cca6dc..53b95658b 100644
--- a/src/yuzu/configuration/configure_system.ui
+++ b/src/yuzu/configuration/configure_system.ui
@@ -21,490 +21,494 @@
21 <property name="title"> 21 <property name="title">
22 <string>System Settings</string> 22 <string>System Settings</string>
23 </property> 23 </property>
24 <layout class="QGridLayout" name="gridLayout"> 24 <layout class="QVBoxLayout" name="verticalLayout_2">
25 <item row="3" column="0"> 25 <item>
26 <widget class="QLabel" name="label_sound"> 26 <layout class="QGridLayout" name="gridLayout_2">
27 <property name="text"> 27 <item row="1" column="0">
28 <string>Sound output mode</string> 28 <widget class="QLabel" name="label_region">
29 </property> 29 <property name="text">
30 </widget> 30 <string>Region:</string>
31 </item> 31 </property>
32 <item row="4" column="0"> 32 </widget>
33 <widget class="QLabel" name="label_console_id"> 33 </item>
34 <property name="text"> 34 <item row="2" column="1">
35 <string>Console ID:</string> 35 <widget class="QComboBox" name="combo_time_zone">
36 </property> 36 <item>
37 </widget> 37 <property name="text">
38 </item> 38 <string>Auto</string>
39 <item row="0" column="1"> 39 </property>
40 <widget class="QComboBox" name="combo_language"> 40 </item>
41 <property name="toolTip"> 41 <item>
42 <string>Note: this can be overridden when region setting is auto-select</string> 42 <property name="text">
43 </property> 43 <string>Default</string>
44 <item> 44 </property>
45 <property name="text"> 45 </item>
46 <string>Japanese (日本語)</string> 46 <item>
47 </property> 47 <property name="text">
48 </item> 48 <string>CET</string>
49 <item> 49 </property>
50 <property name="text"> 50 </item>
51 <string>English</string> 51 <item>
52 </property> 52 <property name="text">
53 </item> 53 <string>CST6CDT</string>
54 <item> 54 </property>
55 <property name="text"> 55 </item>
56 <string>French (français)</string> 56 <item>
57 </property> 57 <property name="text">
58 </item> 58 <string>Cuba</string>
59 <item> 59 </property>
60 <property name="text"> 60 </item>
61 <string>German (Deutsch)</string> 61 <item>
62 </property> 62 <property name="text">
63 </item> 63 <string>EET</string>
64 <item> 64 </property>
65 <property name="text"> 65 </item>
66 <string>Italian (italiano)</string> 66 <item>
67 </property> 67 <property name="text">
68 </item> 68 <string>Egypt</string>
69 <item> 69 </property>
70 <property name="text"> 70 </item>
71 <string>Spanish (español)</string> 71 <item>
72 </property> 72 <property name="text">
73 </item> 73 <string>Eire</string>
74 <item> 74 </property>
75 <property name="text"> 75 </item>
76 <string>Chinese</string> 76 <item>
77 </property> 77 <property name="text">
78 </item> 78 <string>EST</string>
79 <item> 79 </property>
80 <property name="text"> 80 </item>
81 <string>Korean (한국어)</string> 81 <item>
82 </property> 82 <property name="text">
83 </item> 83 <string>EST5EDT</string>
84 <item> 84 </property>
85 <property name="text"> 85 </item>
86 <string>Dutch (Nederlands)</string> 86 <item>
87 </property> 87 <property name="text">
88 </item> 88 <string>GB</string>
89 <item> 89 </property>
90 <property name="text"> 90 </item>
91 <string>Portuguese (português)</string> 91 <item>
92 </property> 92 <property name="text">
93 </item> 93 <string>GB-Eire</string>
94 <item> 94 </property>
95 <property name="text"> 95 </item>
96 <string>Russian (Русский)</string> 96 <item>
97 </property> 97 <property name="text">
98 </item> 98 <string>GMT</string>
99 <item> 99 </property>
100 <property name="text"> 100 </item>
101 <string>Taiwanese</string> 101 <item>
102 </property> 102 <property name="text">
103 </item> 103 <string>GMT+0</string>
104 <item> 104 </property>
105 <property name="text"> 105 </item>
106 <string>British English</string> 106 <item>
107 </property> 107 <property name="text">
108 </item> 108 <string>GMT-0</string>
109 <item> 109 </property>
110 <property name="text"> 110 </item>
111 <string>Canadian French</string> 111 <item>
112 </property> 112 <property name="text">
113 </item> 113 <string>GMT0</string>
114 <item> 114 </property>
115 <property name="text"> 115 </item>
116 <string>Latin American Spanish</string> 116 <item>
117 </property> 117 <property name="text">
118 </item> 118 <string>Greenwich</string>
119 <item> 119 </property>
120 <property name="text"> 120 </item>
121 <string>Simplified Chinese</string> 121 <item>
122 </property> 122 <property name="text">
123 </item> 123 <string>Hongkong</string>
124 <item> 124 </property>
125 <property name="text"> 125 </item>
126 <string>Traditional Chinese (正體中文)</string> 126 <item>
127 </property> 127 <property name="text">
128 </item> 128 <string>HST</string>
129 </widget> 129 </property>
130 </item> 130 </item>
131 <item row="1" column="0"> 131 <item>
132 <widget class="QLabel" name="label_region"> 132 <property name="text">
133 <property name="text"> 133 <string>Iceland</string>
134 <string>Region:</string> 134 </property>
135 </property> 135 </item>
136 </widget> 136 <item>
137 </item> 137 <property name="text">
138 <item row="1" column="1"> 138 <string>Iran</string>
139 <widget class="QComboBox" name="combo_region"> 139 </property>
140 <item> 140 </item>
141 <property name="text"> 141 <item>
142 <string>Japan</string> 142 <property name="text">
143 </property> 143 <string>Israel</string>
144 </item> 144 </property>
145 <item> 145 </item>
146 <property name="text"> 146 <item>
147 <string>USA</string> 147 <property name="text">
148 </property> 148 <string>Jamaica</string>
149 </item> 149 </property>
150 <item> 150 </item>
151 <property name="text"> 151 <item>
152 <string>Europe</string> 152 <property name="text">
153 </property> 153 <string>Japan</string>
154 </item> 154 </property>
155 <item> 155 </item>
156 <property name="text"> 156 <item>
157 <string>Australia</string> 157 <property name="text">
158 </property> 158 <string>Kwajalein</string>
159 </item> 159 </property>
160 <item> 160 </item>
161 <property name="text"> 161 <item>
162 <string>China</string> 162 <property name="text">
163 </property> 163 <string>Libya</string>
164 </item> 164 </property>
165 <item> 165 </item>
166 <property name="text"> 166 <item>
167 <string>Korea</string> 167 <property name="text">
168 </property> 168 <string>MET</string>
169 </item> 169 </property>
170 <item> 170 </item>
171 <property name="text"> 171 <item>
172 <string>Taiwan</string> 172 <property name="text">
173 </property> 173 <string>MST</string>
174 </item> 174 </property>
175 </widget> 175 </item>
176 </item> 176 <item>
177 <item row="2" column="0"> 177 <property name="text">
178 <widget class="QLabel" name="label_timezone"> 178 <string>MST7MDT</string>
179 <property name="text"> 179 </property>
180 <string>Time Zone:</string> 180 </item>
181 </property> 181 <item>
182 </widget> 182 <property name="text">
183 </item> 183 <string>Navajo</string>
184 <item row="2" column="1"> 184 </property>
185 <widget class="QComboBox" name="combo_time_zone"> 185 </item>
186 <item> 186 <item>
187 <property name="text"> 187 <property name="text">
188 <string>Auto</string> 188 <string>NZ</string>
189 </property> 189 </property>
190 </item> 190 </item>
191 <item> 191 <item>
192 <property name="text"> 192 <property name="text">
193 <string>Default</string> 193 <string>NZ-CHAT</string>
194 </property> 194 </property>
195 </item> 195 </item>
196 <item> 196 <item>
197 <property name="text"> 197 <property name="text">
198 <string>CET</string> 198 <string>Poland</string>
199 </property> 199 </property>
200 </item> 200 </item>
201 <item> 201 <item>
202 <property name="text"> 202 <property name="text">
203 <string>CST6CDT</string> 203 <string>Portugal</string>
204 </property> 204 </property>
205 </item> 205 </item>
206 <item> 206 <item>
207 <property name="text"> 207 <property name="text">
208 <string>Cuba</string> 208 <string>PRC</string>
209 </property> 209 </property>
210 </item> 210 </item>
211 <item> 211 <item>
212 <property name="text"> 212 <property name="text">
213 <string>EET</string> 213 <string>PST8PDT</string>
214 </property> 214 </property>
215 </item> 215 </item>
216 <item> 216 <item>
217 <property name="text"> 217 <property name="text">
218 <string>Egypt</string> 218 <string>ROC</string>
219 </property> 219 </property>
220 </item> 220 </item>
221 <item> 221 <item>
222 <property name="text"> 222 <property name="text">
223 <string>Eire</string> 223 <string>ROK</string>
224 </property> 224 </property>
225 </item> 225 </item>
226 <item> 226 <item>
227 <property name="text"> 227 <property name="text">
228 <string>EST</string> 228 <string>Singapore</string>
229 </property> 229 </property>
230 </item> 230 </item>
231 <item> 231 <item>
232 <property name="text"> 232 <property name="text">
233 <string>EST5EDT</string> 233 <string>Turkey</string>
234 </property> 234 </property>
235 </item> 235 </item>
236 <item> 236 <item>
237 <property name="text"> 237 <property name="text">
238 <string>GB</string> 238 <string>UCT</string>
239 </property> 239 </property>
240 </item> 240 </item>
241 <item> 241 <item>
242 <property name="text"> 242 <property name="text">
243 <string>GB-Eire</string> 243 <string>Universal</string>
244 </property> 244 </property>
245 </item> 245 </item>
246 <item> 246 <item>
247 <property name="text"> 247 <property name="text">
248 <string>GMT</string> 248 <string>UTC</string>
249 </property> 249 </property>
250 </item> 250 </item>
251 <item> 251 <item>
252 <property name="text"> 252 <property name="text">
253 <string>GMT+0</string> 253 <string>W-SU</string>
254 </property> 254 </property>
255 </item> 255 </item>
256 <item> 256 <item>
257 <property name="text"> 257 <property name="text">
258 <string>GMT-0</string> 258 <string>WET</string>
259 </property> 259 </property>
260 </item> 260 </item>
261 <item> 261 <item>
262 <property name="text"> 262 <property name="text">
263 <string>GMT0</string> 263 <string>Zulu</string>
264 </property> 264 </property>
265 </item> 265 </item>
266 <item> 266 </widget>
267 <property name="text"> 267 </item>
268 <string>Greenwich</string> 268 <item row="1" column="1">
269 </property> 269 <widget class="QComboBox" name="combo_region">
270 </item> 270 <item>
271 <item> 271 <property name="text">
272 <property name="text"> 272 <string>Japan</string>
273 <string>Hongkong</string> 273 </property>
274 </property> 274 </item>
275 </item> 275 <item>
276 <item> 276 <property name="text">
277 <property name="text"> 277 <string>USA</string>
278 <string>HST</string> 278 </property>
279 </property> 279 </item>
280 </item> 280 <item>
281 <item> 281 <property name="text">
282 <property name="text"> 282 <string>Europe</string>
283 <string>Iceland</string> 283 </property>
284 </property> 284 </item>
285 </item> 285 <item>
286 <item> 286 <property name="text">
287 <property name="text"> 287 <string>Australia</string>
288 <string>Iran</string> 288 </property>
289 </property> 289 </item>
290 </item> 290 <item>
291 <item> 291 <property name="text">
292 <property name="text"> 292 <string>China</string>
293 <string>Israel</string> 293 </property>
294 </property> 294 </item>
295 </item> 295 <item>
296 <item> 296 <property name="text">
297 <property name="text"> 297 <string>Korea</string>
298 <string>Jamaica</string> 298 </property>
299 </property> 299 </item>
300 </item> 300 <item>
301 <item> 301 <property name="text">
302 <property name="text"> 302 <string>Taiwan</string>
303 <string>Japan</string> 303 </property>
304 </property> 304 </item>
305 </item> 305 </widget>
306 <item> 306 </item>
307 <property name="text"> 307 <item row="2" column="0">
308 <string>Kwajalein</string> 308 <widget class="QLabel" name="label_timezone">
309 </property> 309 <property name="text">
310 </item> 310 <string>Time Zone:</string>
311 <item> 311 </property>
312 <property name="text"> 312 </widget>
313 <string>Libya</string> 313 </item>
314 </property> 314 <item row="0" column="1">
315 </item> 315 <widget class="QComboBox" name="combo_language">
316 <item> 316 <property name="toolTip">
317 <property name="text"> 317 <string>Note: this can be overridden when region setting is auto-select</string>
318 <string>MET</string> 318 </property>
319 </property> 319 <item>
320 </item> 320 <property name="text">
321 <item> 321 <string>Japanese (日本語)</string>
322 <property name="text"> 322 </property>
323 <string>MST</string> 323 </item>
324 </property> 324 <item>
325 </item> 325 <property name="text">
326 <item> 326 <string>English</string>
327 <property name="text"> 327 </property>
328 <string>MST7MDT</string> 328 </item>
329 </property> 329 <item>
330 </item> 330 <property name="text">
331 <item> 331 <string>French (français)</string>
332 <property name="text"> 332 </property>
333 <string>Navajo</string> 333 </item>
334 </property> 334 <item>
335 </item> 335 <property name="text">
336 <item> 336 <string>German (Deutsch)</string>
337 <property name="text"> 337 </property>
338 <string>NZ</string> 338 </item>
339 </property> 339 <item>
340 </item> 340 <property name="text">
341 <item> 341 <string>Italian (italiano)</string>
342 <property name="text"> 342 </property>
343 <string>NZ-CHAT</string> 343 </item>
344 </property> 344 <item>
345 </item> 345 <property name="text">
346 <item> 346 <string>Spanish (español)</string>
347 <property name="text"> 347 </property>
348 <string>Poland</string> 348 </item>
349 </property> 349 <item>
350 </item> 350 <property name="text">
351 <item> 351 <string>Chinese</string>
352 <property name="text"> 352 </property>
353 <string>Portugal</string> 353 </item>
354 </property> 354 <item>
355 </item> 355 <property name="text">
356 <item> 356 <string>Korean (한국어)</string>
357 <property name="text"> 357 </property>
358 <string>PRC</string> 358 </item>
359 </property> 359 <item>
360 </item> 360 <property name="text">
361 <item> 361 <string>Dutch (Nederlands)</string>
362 <property name="text"> 362 </property>
363 <string>PST8PDT</string> 363 </item>
364 </property> 364 <item>
365 </item> 365 <property name="text">
366 <item> 366 <string>Portuguese (português)</string>
367 <property name="text"> 367 </property>
368 <string>ROC</string> 368 </item>
369 </property> 369 <item>
370 </item> 370 <property name="text">
371 <item> 371 <string>Russian (Русский)</string>
372 <property name="text"> 372 </property>
373 <string>ROK</string> 373 </item>
374 </property> 374 <item>
375 </item> 375 <property name="text">
376 <item> 376 <string>Taiwanese</string>
377 <property name="text"> 377 </property>
378 <string>Singapore</string> 378 </item>
379 </property> 379 <item>
380 </item> 380 <property name="text">
381 <item> 381 <string>British English</string>
382 <property name="text"> 382 </property>
383 <string>Turkey</string> 383 </item>
384 </property> 384 <item>
385 </item> 385 <property name="text">
386 <item> 386 <string>Canadian French</string>
387 <property name="text"> 387 </property>
388 <string>UCT</string> 388 </item>
389 </property> 389 <item>
390 </item> 390 <property name="text">
391 <item> 391 <string>Latin American Spanish</string>
392 <property name="text"> 392 </property>
393 <string>Universal</string> 393 </item>
394 </property> 394 <item>
395 </item> 395 <property name="text">
396 <item> 396 <string>Simplified Chinese</string>
397 <property name="text"> 397 </property>
398 <string>UTC</string> 398 </item>
399 </property> 399 <item>
400 </item> 400 <property name="text">
401 <item> 401 <string>Traditional Chinese (正體中文)</string>
402 <property name="text"> 402 </property>
403 <string>W-SU</string> 403 </item>
404 </property> 404 </widget>
405 </item> 405 </item>
406 <item> 406 <item row="5" column="0">
407 <property name="text"> 407 <widget class="QCheckBox" name="custom_rtc_checkbox">
408 <string>WET</string> 408 <property name="text">
409 </property> 409 <string>Custom RTC</string>
410 </item> 410 </property>
411 <item> 411 </widget>
412 <property name="text"> 412 </item>
413 <string>Zulu</string> 413 <item row="0" column="0">
414 </property> 414 <widget class="QLabel" name="label_language">
415 </item> 415 <property name="text">
416 </widget> 416 <string>Language</string>
417 </item> 417 </property>
418 <item row="6" column="0"> 418 </widget>
419 <widget class="QCheckBox" name="rng_seed_checkbox"> 419 </item>
420 <property name="text"> 420 <item row="6" column="0">
421 <string>RNG Seed</string> 421 <widget class="QCheckBox" name="rng_seed_checkbox">
422 </property> 422 <property name="text">
423 </widget> 423 <string>RNG Seed</string>
424 </item> 424 </property>
425 <item row="3" column="1"> 425 </widget>
426 <widget class="QComboBox" name="combo_sound"> 426 </item>
427 <item> 427 <item row="3" column="1">
428 <property name="text"> 428 <widget class="QComboBox" name="combo_sound">
429 <string>Mono</string> 429 <item>
430 </property> 430 <property name="text">
431 </item> 431 <string>Mono</string>
432 <item> 432 </property>
433 <property name="text"> 433 </item>
434 <string>Stereo</string> 434 <item>
435 </property> 435 <property name="text">
436 </item> 436 <string>Stereo</string>
437 <item> 437 </property>
438 <property name="text"> 438 </item>
439 <string>Surround</string> 439 <item>
440 </property> 440 <property name="text">
441 </item> 441 <string>Surround</string>
442 </widget> 442 </property>
443 </item> 443 </item>
444 <item row="0" column="0"> 444 </widget>
445 <widget class="QLabel" name="label_language"> 445 </item>
446 <property name="text"> 446 <item row="4" column="0">
447 <string>Language</string> 447 <widget class="QLabel" name="label_console_id">
448 </property> 448 <property name="text">
449 </widget> 449 <string>Console ID:</string>
450 </item> 450 </property>
451 <item row="4" column="1"> 451 </widget>
452 <widget class="QPushButton" name="button_regenerate_console_id"> 452 </item>
453 <property name="sizePolicy"> 453 <item row="3" column="0">
454 <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> 454 <widget class="QLabel" name="label_sound">
455 <horstretch>0</horstretch> 455 <property name="text">
456 <verstretch>0</verstretch> 456 <string>Sound output mode</string>
457 </sizepolicy> 457 </property>
458 </property> 458 </widget>
459 <property name="layoutDirection"> 459 </item>
460 <enum>Qt::RightToLeft</enum> 460 <item row="5" column="1">
461 </property> 461 <widget class="QDateTimeEdit" name="custom_rtc_edit">
462 <property name="text"> 462 <property name="minimumDate">
463 <string>Regenerate</string> 463 <date>
464 </property> 464 <year>1970</year>
465 </widget> 465 <month>1</month>
466 </item> 466 <day>1</day>
467 <item row="5" column="0"> 467 </date>
468 <widget class="QCheckBox" name="custom_rtc_checkbox"> 468 </property>
469 <property name="text"> 469 <property name="displayFormat">
470 <string>Custom RTC</string> 470 <string>d MMM yyyy h:mm:ss AP</string>
471 </property> 471 </property>
472 </widget> 472 </widget>
473 </item> 473 </item>
474 <item row="5" column="1"> 474 <item row="6" column="1">
475 <widget class="QDateTimeEdit" name="custom_rtc_edit"> 475 <widget class="QLineEdit" name="rng_seed_edit">
476 <property name="minimumDate"> 476 <property name="sizePolicy">
477 <date> 477 <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
478 <year>1970</year> 478 <horstretch>0</horstretch>
479 <month>1</month> 479 <verstretch>0</verstretch>
480 <day>1</day> 480 </sizepolicy>
481 </date> 481 </property>
482 </property> 482 <property name="font">
483 <property name="displayFormat"> 483 <font>
484 <string>d MMM yyyy h:mm:ss AP</string> 484 <family>Lucida Console</family>
485 </property> 485 </font>
486 </widget> 486 </property>
487 </item> 487 <property name="inputMask">
488 <item row="6" column="1"> 488 <string notr="true">HHHHHHHH</string>
489 <widget class="QLineEdit" name="rng_seed_edit"> 489 </property>
490 <property name="sizePolicy"> 490 <property name="maxLength">
491 <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> 491 <number>8</number>
492 <horstretch>0</horstretch> 492 </property>
493 <verstretch>0</verstretch> 493 </widget>
494 </sizepolicy> 494 </item>
495 </property> 495 <item row="4" column="1">
496 <property name="font"> 496 <widget class="QPushButton" name="button_regenerate_console_id">
497 <font> 497 <property name="sizePolicy">
498 <family>Lucida Console</family> 498 <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
499 </font> 499 <horstretch>0</horstretch>
500 </property> 500 <verstretch>0</verstretch>
501 <property name="inputMask"> 501 </sizepolicy>
502 <string notr="true">HHHHHHHH</string> 502 </property>
503 </property> 503 <property name="layoutDirection">
504 <property name="maxLength"> 504 <enum>Qt::RightToLeft</enum>
505 <number>8</number> 505 </property>
506 </property> 506 <property name="text">
507 </widget> 507 <string>Regenerate</string>
508 </property>
509 </widget>
510 </item>
511 </layout>
508 </item> 512 </item>
509 </layout> 513 </layout>
510 </widget> 514 </widget>
diff --git a/src/yuzu/configuration/configure_ui.cpp b/src/yuzu/configuration/configure_ui.cpp
index 94424ee44..24b6c5b72 100644
--- a/src/yuzu/configuration/configure_ui.cpp
+++ b/src/yuzu/configuration/configure_ui.cpp
@@ -5,6 +5,7 @@
5#include <array> 5#include <array>
6#include <utility> 6#include <utility>
7 7
8#include <QDirIterator>
8#include "common/common_types.h" 9#include "common/common_types.h"
9#include "core/settings.h" 10#include "core/settings.h"
10#include "ui_configure_ui.h" 11#include "ui_configure_ui.h"
@@ -29,6 +30,8 @@ constexpr std::array row_text_names{
29ConfigureUi::ConfigureUi(QWidget* parent) : QWidget(parent), ui(new Ui::ConfigureUi) { 30ConfigureUi::ConfigureUi(QWidget* parent) : QWidget(parent), ui(new Ui::ConfigureUi) {
30 ui->setupUi(this); 31 ui->setupUi(this);
31 32
33 InitializeLanguageComboBox();
34
32 for (const auto& theme : UISettings::themes) { 35 for (const auto& theme : UISettings::themes) {
33 ui->theme_combobox->addItem(QString::fromUtf8(theme.first), 36 ui->theme_combobox->addItem(QString::fromUtf8(theme.first),
34 QString::fromUtf8(theme.second)); 37 QString::fromUtf8(theme.second));
@@ -72,6 +75,8 @@ void ConfigureUi::RequestGameListUpdate() {
72 75
73void ConfigureUi::SetConfiguration() { 76void ConfigureUi::SetConfiguration() {
74 ui->theme_combobox->setCurrentIndex(ui->theme_combobox->findData(UISettings::values.theme)); 77 ui->theme_combobox->setCurrentIndex(ui->theme_combobox->findData(UISettings::values.theme));
78 ui->language_combobox->setCurrentIndex(
79 ui->language_combobox->findData(UISettings::values.language));
75 ui->show_add_ons->setChecked(UISettings::values.show_add_ons); 80 ui->show_add_ons->setChecked(UISettings::values.show_add_ons);
76 ui->icon_size_combobox->setCurrentIndex( 81 ui->icon_size_combobox->setCurrentIndex(
77 ui->icon_size_combobox->findData(UISettings::values.icon_size)); 82 ui->icon_size_combobox->findData(UISettings::values.icon_size));
@@ -100,6 +105,25 @@ void ConfigureUi::RetranslateUI() {
100 } 105 }
101} 106}
102 107
108void ConfigureUi::InitializeLanguageComboBox() {
109 ui->language_combobox->addItem(tr("<System>"), QString{});
110 ui->language_combobox->addItem(tr("English"), QStringLiteral("en"));
111 QDirIterator it(QStringLiteral(":/languages"), QDirIterator::NoIteratorFlags);
112 while (it.hasNext()) {
113 QString locale = it.next();
114 locale.truncate(locale.lastIndexOf(QLatin1Char{'.'}));
115 locale.remove(0, locale.lastIndexOf(QLatin1Char{'/'}) + 1);
116 const QString lang = QLocale::languageToString(QLocale(locale).language());
117 ui->language_combobox->addItem(lang, locale);
118 }
119
120 // Unlike other configuration changes, interface language changes need to be reflected on the
121 // interface immediately. This is done by passing a signal to the main window, and then
122 // retranslating when passing back.
123 connect(ui->language_combobox, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
124 &ConfigureUi::OnLanguageChanged);
125}
126
103void ConfigureUi::InitializeIconSizeComboBox() { 127void ConfigureUi::InitializeIconSizeComboBox() {
104 for (const auto& size : default_icon_sizes) { 128 for (const auto& size : default_icon_sizes) {
105 ui->icon_size_combobox->addItem(QString::fromUtf8(size.second), size.first); 129 ui->icon_size_combobox->addItem(QString::fromUtf8(size.second), size.first);
@@ -147,3 +171,10 @@ void ConfigureUi::UpdateSecondRowComboBox(bool init) {
147 ui->row_2_text_combobox->removeItem( 171 ui->row_2_text_combobox->removeItem(
148 ui->row_2_text_combobox->findData(ui->row_1_text_combobox->currentData())); 172 ui->row_2_text_combobox->findData(ui->row_1_text_combobox->currentData()));
149} 173}
174
175void ConfigureUi::OnLanguageChanged(int index) {
176 if (index == -1)
177 return;
178
179 emit LanguageChanged(ui->language_combobox->itemData(index).toString());
180}
diff --git a/src/yuzu/configuration/configure_ui.h b/src/yuzu/configuration/configure_ui.h
index d471afe99..c30bcf6ff 100644
--- a/src/yuzu/configuration/configure_ui.h
+++ b/src/yuzu/configuration/configure_ui.h
@@ -20,6 +20,12 @@ public:
20 20
21 void ApplyConfiguration(); 21 void ApplyConfiguration();
22 22
23private slots:
24 void OnLanguageChanged(int index);
25
26signals:
27 void LanguageChanged(const QString& locale);
28
23private: 29private:
24 void RequestGameListUpdate(); 30 void RequestGameListUpdate();
25 31
@@ -28,6 +34,7 @@ private:
28 void changeEvent(QEvent*) override; 34 void changeEvent(QEvent*) override;
29 void RetranslateUI(); 35 void RetranslateUI();
30 36
37 void InitializeLanguageComboBox();
31 void InitializeIconSizeComboBox(); 38 void InitializeIconSizeComboBox();
32 void InitializeRowComboBoxes(); 39 void InitializeRowComboBoxes();
33 40
diff --git a/src/yuzu/configuration/configure_ui.ui b/src/yuzu/configuration/configure_ui.ui
index bd5c5d3c2..0b81747d7 100644
--- a/src/yuzu/configuration/configure_ui.ui
+++ b/src/yuzu/configuration/configure_ui.ui
@@ -13,112 +13,132 @@
13 <property name="windowTitle"> 13 <property name="windowTitle">
14 <string>Form</string> 14 <string>Form</string>
15 </property> 15 </property>
16 <layout class="QHBoxLayout" name="HorizontalLayout"> 16 <layout class="QVBoxLayout" name="verticalLayout">
17 <item> 17 <item>
18 <layout class="QVBoxLayout" name="VerticalLayout"> 18 <widget class="QGroupBox" name="general_groupBox">
19 <item> 19 <property name="title">
20 <widget class="QGroupBox" name="GeneralGroupBox"> 20 <string>General</string>
21 <property name="title"> 21 </property>
22 <string>General</string> 22 <layout class="QHBoxLayout" name="horizontalLayout">
23 </property> 23 <item>
24 <layout class="QHBoxLayout" name="horizontalLayout"> 24 <layout class="QVBoxLayout" name="verticalLayout_2">
25 <item> 25 <item>
26 <layout class="QVBoxLayout" name="verticalLayout"> 26 <widget class="QLabel" name="label_change_language_info">
27 <property name="text">
28 <string>Note: Changing language will apply your configuration.</string>
29 </property>
30 <property name="wordWrap">
31 <bool>true</bool>
32 </property>
33 </widget>
34 </item>
35 <item>
36 <layout class="QHBoxLayout" name="horizontalLayout_2">
37 <item>
38 <widget class="QLabel" name="language_label">
39 <property name="text">
40 <string>Interface language:</string>
41 </property>
42 </widget>
43 </item>
44 <item>
45 <widget class="QComboBox" name="language_combobox"/>
46 </item>
47 </layout>
48 </item>
49 <item>
50 <layout class="QHBoxLayout" name="horizontalLayout_3">
51 <item>
52 <widget class="QLabel" name="theme_label">
53 <property name="text">
54 <string>Theme:</string>
55 </property>
56 </widget>
57 </item>
27 <item> 58 <item>
28 <layout class="QHBoxLayout" name="horizontalLayout_3"> 59 <widget class="QComboBox" name="theme_combobox"/>
29 <item>
30 <widget class="QLabel" name="theme_label">
31 <property name="text">
32 <string>Theme:</string>
33 </property>
34 </widget>
35 </item>
36 <item>
37 <widget class="QComboBox" name="theme_combobox"/>
38 </item>
39 </layout>
40 </item> 60 </item>
41 </layout> 61 </layout>
42 </item> 62 </item>
43 </layout> 63 </layout>
44 </widget> 64 </item>
45 </item> 65 </layout>
46 <item> 66 </widget>
47 <widget class="QGroupBox" name="GameListGroupBox"> 67 </item>
48 <property name="title"> 68 <item>
49 <string>Game List</string> 69 <widget class="QGroupBox" name="GameListGroupBox">
50 </property> 70 <property name="title">
51 <layout class="QHBoxLayout" name="GameListHorizontalLayout"> 71 <string>Game List</string>
72 </property>
73 <layout class="QHBoxLayout" name="GameListHorizontalLayout">
74 <item>
75 <layout class="QVBoxLayout" name="GeneralVerticalLayout">
52 <item> 76 <item>
53 <layout class="QVBoxLayout" name="GeneralVerticalLayout"> 77 <widget class="QCheckBox" name="show_add_ons">
78 <property name="text">
79 <string>Show Add-Ons Column</string>
80 </property>
81 </widget>
82 </item>
83 <item>
84 <layout class="QHBoxLayout" name="icon_size_qhbox_layout_2">
54 <item> 85 <item>
55 <widget class="QCheckBox" name="show_add_ons"> 86 <widget class="QLabel" name="icon_size_label">
56 <property name="text"> 87 <property name="text">
57 <string>Show Add-Ons Column</string> 88 <string>Icon Size:</string>
58 </property> 89 </property>
59 </widget> 90 </widget>
60 </item> 91 </item>
61 <item> 92 <item>
62 <layout class="QHBoxLayout" name="icon_size_qhbox_layout_2"> 93 <widget class="QComboBox" name="icon_size_combobox"/>
63 <item>
64 <widget class="QLabel" name="icon_size_label">
65 <property name="text">
66 <string>Icon Size:</string>
67 </property>
68 </widget>
69 </item>
70 <item>
71 <widget class="QComboBox" name="icon_size_combobox"/>
72 </item>
73 </layout>
74 </item> 94 </item>
95 </layout>
96 </item>
97 <item>
98 <layout class="QHBoxLayout" name="row_1_qhbox_layout">
75 <item> 99 <item>
76 <layout class="QHBoxLayout" name="row_1_qhbox_layout"> 100 <widget class="QLabel" name="row_1_label">
77 <item> 101 <property name="text">
78 <widget class="QLabel" name="row_1_label"> 102 <string>Row 1 Text:</string>
79 <property name="text"> 103 </property>
80 <string>Row 1 Text:</string> 104 </widget>
81 </property>
82 </widget>
83 </item>
84 <item>
85 <widget class="QComboBox" name="row_1_text_combobox"/>
86 </item>
87 </layout>
88 </item> 105 </item>
89 <item> 106 <item>
90 <layout class="QHBoxLayout" name="row_2_qhbox_layout"> 107 <widget class="QComboBox" name="row_1_text_combobox"/>
91 <item> 108 </item>
92 <widget class="QLabel" name="row_2_label"> 109 </layout>
93 <property name="text"> 110 </item>
94 <string>Row 2 Text:</string> 111 <item>
95 </property> 112 <layout class="QHBoxLayout" name="row_2_qhbox_layout">
96 </widget> 113 <item>
97 </item> 114 <widget class="QLabel" name="row_2_label">
98 <item> 115 <property name="text">
99 <widget class="QComboBox" name="row_2_text_combobox"/> 116 <string>Row 2 Text:</string>
100 </item> 117 </property>
101 </layout> 118 </widget>
119 </item>
120 <item>
121 <widget class="QComboBox" name="row_2_text_combobox"/>
102 </item> 122 </item>
103 </layout> 123 </layout>
104 </item> 124 </item>
105 </layout> 125 </layout>
106 </widget> 126 </item>
107 </item> 127 </layout>
108 <item> 128 </widget>
109 <spacer name="verticalSpacer"> 129 </item>
110 <property name="orientation"> 130 <item>
111 <enum>Qt::Vertical</enum> 131 <spacer name="verticalSpacer">
112 </property> 132 <property name="orientation">
113 <property name="sizeHint" stdset="0"> 133 <enum>Qt::Vertical</enum>
114 <size> 134 </property>
115 <width>20</width> 135 <property name="sizeHint" stdset="0">
116 <height>40</height> 136 <size>
117 </size> 137 <width>20</width>
118 </property> 138 <height>40</height>
119 </spacer> 139 </size>
120 </item> 140 </property>
121 </layout> 141 </spacer>
122 </item> 142 </item>
123 </layout> 143 </layout>
124 </widget> 144 </widget>
diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp
index 9bb0a0109..3439cb333 100644
--- a/src/yuzu/debugger/wait_tree.cpp
+++ b/src/yuzu/debugger/wait_tree.cpp
@@ -2,9 +2,11 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <array>
5#include <fmt/format.h> 6#include <fmt/format.h>
6 7
7#include "yuzu/debugger/wait_tree.h" 8#include "yuzu/debugger/wait_tree.h"
9#include "yuzu/uisettings.h"
8#include "yuzu/util/util.h" 10#include "yuzu/util/util.h"
9 11
10#include "common/assert.h" 12#include "common/assert.h"
@@ -19,11 +21,40 @@
19#include "core/hle/kernel/thread.h" 21#include "core/hle/kernel/thread.h"
20#include "core/memory.h" 22#include "core/memory.h"
21 23
24namespace {
25
26constexpr std::array<std::array<Qt::GlobalColor, 2>, 10> WaitTreeColors{{
27 {Qt::GlobalColor::darkGreen, Qt::GlobalColor::green},
28 {Qt::GlobalColor::darkGreen, Qt::GlobalColor::green},
29 {Qt::GlobalColor::darkBlue, Qt::GlobalColor::cyan},
30 {Qt::GlobalColor::lightGray, Qt::GlobalColor::lightGray},
31 {Qt::GlobalColor::lightGray, Qt::GlobalColor::lightGray},
32 {Qt::GlobalColor::darkRed, Qt::GlobalColor::red},
33 {Qt::GlobalColor::darkYellow, Qt::GlobalColor::yellow},
34 {Qt::GlobalColor::red, Qt::GlobalColor::red},
35 {Qt::GlobalColor::darkCyan, Qt::GlobalColor::cyan},
36 {Qt::GlobalColor::gray, Qt::GlobalColor::gray},
37}};
38
39bool IsDarkTheme() {
40 const auto& theme = UISettings::values.theme;
41 return theme == QStringLiteral("qdarkstyle") ||
42 theme == QStringLiteral("qdarkstyle_midnight_blue") ||
43 theme == QStringLiteral("colorful_dark") ||
44 theme == QStringLiteral("colorful_midnight_blue");
45}
46
47} // namespace
48
22WaitTreeItem::WaitTreeItem() = default; 49WaitTreeItem::WaitTreeItem() = default;
23WaitTreeItem::~WaitTreeItem() = default; 50WaitTreeItem::~WaitTreeItem() = default;
24 51
25QColor WaitTreeItem::GetColor() const { 52QColor WaitTreeItem::GetColor() const {
26 return QColor(Qt::GlobalColor::black); 53 if (IsDarkTheme()) {
54 return QColor(Qt::GlobalColor::white);
55 } else {
56 return QColor(Qt::GlobalColor::black);
57 }
27} 58}
28 59
29std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeItem::GetChildren() const { 60std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeItem::GetChildren() const {
@@ -263,36 +294,38 @@ QString WaitTreeThread::GetText() const {
263} 294}
264 295
265QColor WaitTreeThread::GetColor() const { 296QColor WaitTreeThread::GetColor() const {
297 const std::size_t color_index = IsDarkTheme() ? 1 : 0;
298
266 const auto& thread = static_cast<const Kernel::Thread&>(object); 299 const auto& thread = static_cast<const Kernel::Thread&>(object);
267 switch (thread.GetStatus()) { 300 switch (thread.GetStatus()) {
268 case Kernel::ThreadStatus::Running: 301 case Kernel::ThreadStatus::Running:
269 return QColor(Qt::GlobalColor::darkGreen); 302 return QColor(WaitTreeColors[0][color_index]);
270 case Kernel::ThreadStatus::Ready: 303 case Kernel::ThreadStatus::Ready:
271 if (!thread.IsPaused()) { 304 if (!thread.IsPaused()) {
272 if (thread.WasRunning()) { 305 if (thread.WasRunning()) {
273 return QColor(Qt::GlobalColor::darkGreen); 306 return QColor(WaitTreeColors[1][color_index]);
274 } else { 307 } else {
275 return QColor(Qt::GlobalColor::darkBlue); 308 return QColor(WaitTreeColors[2][color_index]);
276 } 309 }
277 } else { 310 } else {
278 return QColor(Qt::GlobalColor::lightGray); 311 return QColor(WaitTreeColors[3][color_index]);
279 } 312 }
280 case Kernel::ThreadStatus::Paused: 313 case Kernel::ThreadStatus::Paused:
281 return QColor(Qt::GlobalColor::lightGray); 314 return QColor(WaitTreeColors[4][color_index]);
282 case Kernel::ThreadStatus::WaitHLEEvent: 315 case Kernel::ThreadStatus::WaitHLEEvent:
283 case Kernel::ThreadStatus::WaitIPC: 316 case Kernel::ThreadStatus::WaitIPC:
284 return QColor(Qt::GlobalColor::darkRed); 317 return QColor(WaitTreeColors[5][color_index]);
285 case Kernel::ThreadStatus::WaitSleep: 318 case Kernel::ThreadStatus::WaitSleep:
286 return QColor(Qt::GlobalColor::darkYellow); 319 return QColor(WaitTreeColors[6][color_index]);
287 case Kernel::ThreadStatus::WaitSynch: 320 case Kernel::ThreadStatus::WaitSynch:
288 case Kernel::ThreadStatus::WaitMutex: 321 case Kernel::ThreadStatus::WaitMutex:
289 case Kernel::ThreadStatus::WaitCondVar: 322 case Kernel::ThreadStatus::WaitCondVar:
290 case Kernel::ThreadStatus::WaitArb: 323 case Kernel::ThreadStatus::WaitArb:
291 return QColor(Qt::GlobalColor::red); 324 return QColor(WaitTreeColors[7][color_index]);
292 case Kernel::ThreadStatus::Dormant: 325 case Kernel::ThreadStatus::Dormant:
293 return QColor(Qt::GlobalColor::darkCyan); 326 return QColor(WaitTreeColors[8][color_index]);
294 case Kernel::ThreadStatus::Dead: 327 case Kernel::ThreadStatus::Dead:
295 return QColor(Qt::GlobalColor::gray); 328 return QColor(WaitTreeColors[9][color_index]);
296 default: 329 default:
297 return WaitTreeItem::GetColor(); 330 return WaitTreeItem::GetColor();
298 } 331 }
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index d51cb2bcb..31a635176 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -94,6 +94,8 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual
94#include "core/perf_stats.h" 94#include "core/perf_stats.h"
95#include "core/settings.h" 95#include "core/settings.h"
96#include "core/telemetry_session.h" 96#include "core/telemetry_session.h"
97#include "video_core/gpu.h"
98#include "video_core/shader_notify.h"
97#include "yuzu/about_dialog.h" 99#include "yuzu/about_dialog.h"
98#include "yuzu/bootmanager.h" 100#include "yuzu/bootmanager.h"
99#include "yuzu/compatdb.h" 101#include "yuzu/compatdb.h"
@@ -189,6 +191,8 @@ GMainWindow::GMainWindow()
189 provider(std::make_unique<FileSys::ManualContentProvider>()) { 191 provider(std::make_unique<FileSys::ManualContentProvider>()) {
190 InitializeLogging(); 192 InitializeLogging();
191 193
194 LoadTranslation();
195
192 setAcceptDrops(true); 196 setAcceptDrops(true);
193 ui.setupUi(this); 197 ui.setupUi(this);
194 statusBar()->hide(); 198 statusBar()->hide();
@@ -279,17 +283,21 @@ GMainWindow::~GMainWindow() {
279} 283}
280 284
281void GMainWindow::ProfileSelectorSelectProfile() { 285void GMainWindow::ProfileSelectorSelectProfile() {
282 QtProfileSelectionDialog dialog(this); 286 const Service::Account::ProfileManager manager;
283 dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | 287 int index = 0;
284 Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint); 288 if (manager.GetUserCount() != 1) {
285 dialog.setWindowModality(Qt::WindowModal); 289 QtProfileSelectionDialog dialog(this);
286 if (dialog.exec() == QDialog::Rejected) { 290 dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint |
287 emit ProfileSelectorFinishedSelection(std::nullopt); 291 Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint);
288 return; 292 dialog.setWindowModality(Qt::WindowModal);
293 if (dialog.exec() == QDialog::Rejected) {
294 emit ProfileSelectorFinishedSelection(std::nullopt);
295 return;
296 }
297 index = dialog.GetIndex();
289 } 298 }
290 299
291 Service::Account::ProfileManager manager; 300 const auto uuid = manager.GetUser(static_cast<std::size_t>(index));
292 const auto uuid = manager.GetUser(static_cast<std::size_t>(dialog.GetIndex()));
293 if (!uuid.has_value()) { 301 if (!uuid.has_value()) {
294 emit ProfileSelectorFinishedSelection(std::nullopt); 302 emit ProfileSelectorFinishedSelection(std::nullopt);
295 return; 303 return;
@@ -494,6 +502,8 @@ void GMainWindow::InitializeWidgets() {
494 message_label->setAlignment(Qt::AlignLeft); 502 message_label->setAlignment(Qt::AlignLeft);
495 statusBar()->addPermanentWidget(message_label, 1); 503 statusBar()->addPermanentWidget(message_label, 1);
496 504
505 shader_building_label = new QLabel();
506 shader_building_label->setToolTip(tr("The amount of shaders currently being built"));
497 emu_speed_label = new QLabel(); 507 emu_speed_label = new QLabel();
498 emu_speed_label->setToolTip( 508 emu_speed_label->setToolTip(
499 tr("Current emulation speed. Values higher or lower than 100% " 509 tr("Current emulation speed. Values higher or lower than 100% "
@@ -506,7 +516,8 @@ void GMainWindow::InitializeWidgets() {
506 tr("Time taken to emulate a Switch frame, not counting framelimiting or v-sync. For " 516 tr("Time taken to emulate a Switch frame, not counting framelimiting or v-sync. For "
507 "full-speed emulation this should be at most 16.67 ms.")); 517 "full-speed emulation this should be at most 16.67 ms."));
508 518
509 for (auto& label : {emu_speed_label, game_fps_label, emu_frametime_label}) { 519 for (auto& label :
520 {shader_building_label, emu_speed_label, game_fps_label, emu_frametime_label}) {
510 label->setVisible(false); 521 label->setVisible(false);
511 label->setFrameStyle(QFrame::NoFrame); 522 label->setFrameStyle(QFrame::NoFrame);
512 label->setContentsMargins(4, 0, 4, 0); 523 label->setContentsMargins(4, 0, 4, 0);
@@ -1172,6 +1183,7 @@ void GMainWindow::ShutdownGame() {
1172 1183
1173 // Disable status bar updates 1184 // Disable status bar updates
1174 status_bar_update_timer.stop(); 1185 status_bar_update_timer.stop();
1186 shader_building_label->setVisible(false);
1175 emu_speed_label->setVisible(false); 1187 emu_speed_label->setVisible(false);
1176 game_fps_label->setVisible(false); 1188 game_fps_label->setVisible(false);
1177 emu_frametime_label->setVisible(false); 1189 emu_frametime_label->setVisible(false);
@@ -2038,6 +2050,9 @@ void GMainWindow::OnConfigure() {
2038 const bool old_discord_presence = UISettings::values.enable_discord_presence; 2050 const bool old_discord_presence = UISettings::values.enable_discord_presence;
2039 2051
2040 ConfigureDialog configure_dialog(this, hotkey_registry); 2052 ConfigureDialog configure_dialog(this, hotkey_registry);
2053 connect(&configure_dialog, &ConfigureDialog::LanguageChanged, this,
2054 &GMainWindow::OnLanguageChanged);
2055
2041 const auto result = configure_dialog.exec(); 2056 const auto result = configure_dialog.exec();
2042 if (result != QDialog::Accepted) { 2057 if (result != QDialog::Accepted) {
2043 return; 2058 return;
@@ -2182,6 +2197,17 @@ void GMainWindow::UpdateStatusBar() {
2182 } 2197 }
2183 2198
2184 auto results = Core::System::GetInstance().GetAndResetPerfStats(); 2199 auto results = Core::System::GetInstance().GetAndResetPerfStats();
2200 auto& shader_notify = Core::System::GetInstance().GPU().ShaderNotify();
2201 const auto shaders_building = shader_notify.GetShadersBuilding();
2202
2203 if (shaders_building != 0) {
2204 shader_building_label->setText(
2205 tr("Building: %1 shader").arg(shaders_building) +
2206 (shaders_building != 1 ? QString::fromStdString("s") : QString::fromStdString("")));
2207 shader_building_label->setVisible(true);
2208 } else {
2209 shader_building_label->setVisible(false);
2210 }
2185 2211
2186 if (Settings::values.use_frame_limit.GetValue()) { 2212 if (Settings::values.use_frame_limit.GetValue()) {
2187 emu_speed_label->setText(tr("Speed: %1% / %2%") 2213 emu_speed_label->setText(tr("Speed: %1% / %2%")
@@ -2311,9 +2337,12 @@ void GMainWindow::OnReinitializeKeys(ReinitializeKeyBehavior behavior) {
2311 if (behavior == ReinitializeKeyBehavior::Warning) { 2337 if (behavior == ReinitializeKeyBehavior::Warning) {
2312 const auto res = QMessageBox::information( 2338 const auto res = QMessageBox::information(
2313 this, tr("Confirm Key Rederivation"), 2339 this, tr("Confirm Key Rederivation"),
2314 tr("You are about to force rederive all of your keys. \nIf you do not know what this " 2340 tr("You are about to force rederive all of your keys. \nIf you do not know what "
2315 "means or what you are doing, \nthis is a potentially destructive action. \nPlease " 2341 "this "
2316 "make sure this is what you want \nand optionally make backups.\n\nThis will delete " 2342 "means or what you are doing, \nthis is a potentially destructive action. "
2343 "\nPlease "
2344 "make sure this is what you want \nand optionally make backups.\n\nThis will "
2345 "delete "
2317 "your autogenerated key files and re-run the key derivation module."), 2346 "your autogenerated key files and re-run the key derivation module."),
2318 QMessageBox::StandardButtons{QMessageBox::Ok, QMessageBox::Cancel}); 2347 QMessageBox::StandardButtons{QMessageBox::Ok, QMessageBox::Cancel});
2319 2348
@@ -2596,6 +2625,43 @@ void GMainWindow::UpdateUITheme() {
2596 QIcon::setThemeSearchPaths(theme_paths); 2625 QIcon::setThemeSearchPaths(theme_paths);
2597} 2626}
2598 2627
2628void GMainWindow::LoadTranslation() {
2629 // If the selected language is English, no need to install any translation
2630 if (UISettings::values.language == QStringLiteral("en")) {
2631 return;
2632 }
2633
2634 bool loaded;
2635
2636 if (UISettings::values.language.isEmpty()) {
2637 // If the selected language is empty, use system locale
2638 loaded = translator.load(QLocale(), {}, {}, QStringLiteral(":/languages/"));
2639 } else {
2640 // Otherwise load from the specified file
2641 loaded = translator.load(UISettings::values.language, QStringLiteral(":/languages/"));
2642 }
2643
2644 if (loaded) {
2645 qApp->installTranslator(&translator);
2646 } else {
2647 UISettings::values.language = QStringLiteral("en");
2648 }
2649}
2650
2651void GMainWindow::OnLanguageChanged(const QString& locale) {
2652 if (UISettings::values.language != QStringLiteral("en")) {
2653 qApp->removeTranslator(&translator);
2654 }
2655
2656 UISettings::values.language = locale;
2657 LoadTranslation();
2658 ui.retranslateUi(this);
2659 UpdateWindowTitle();
2660
2661 if (emulation_running)
2662 ui.action_Start->setText(tr("Continue"));
2663}
2664
2599void GMainWindow::SetDiscordEnabled([[maybe_unused]] bool state) { 2665void GMainWindow::SetDiscordEnabled([[maybe_unused]] bool state) {
2600#ifdef USE_DISCORD_PRESENCE 2666#ifdef USE_DISCORD_PRESENCE
2601 if (state) { 2667 if (state) {
@@ -2624,8 +2690,8 @@ int main(int argc, char* argv[]) {
2624 2690
2625#ifdef __APPLE__ 2691#ifdef __APPLE__
2626 // If you start a bundle (binary) on OSX without the Terminal, the working directory is "/". 2692 // If you start a bundle (binary) on OSX without the Terminal, the working directory is "/".
2627 // But since we require the working directory to be the executable path for the location of the 2693 // But since we require the working directory to be the executable path for the location of
2628 // user folder in the Qt Frontend, we need to cd into that working directory 2694 // the user folder in the Qt Frontend, we need to cd into that working directory
2629 const std::string bin_path = FileUtil::GetBundleDirectory() + DIR_SEP + ".."; 2695 const std::string bin_path = FileUtil::GetBundleDirectory() + DIR_SEP + "..";
2630 chdir(bin_path.c_str()); 2696 chdir(bin_path.c_str());
2631#endif 2697#endif
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index adff65fb5..db573d606 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -10,6 +10,7 @@
10 10
11#include <QMainWindow> 11#include <QMainWindow>
12#include <QTimer> 12#include <QTimer>
13#include <QTranslator>
13 14
14#include "common/common_types.h" 15#include "common/common_types.h"
15#include "core/core.h" 16#include "core/core.h"
@@ -225,6 +226,7 @@ private slots:
225 void OnCaptureScreenshot(); 226 void OnCaptureScreenshot();
226 void OnCoreError(Core::System::ResultStatus, std::string); 227 void OnCoreError(Core::System::ResultStatus, std::string);
227 void OnReinitializeKeys(ReinitializeKeyBehavior behavior); 228 void OnReinitializeKeys(ReinitializeKeyBehavior behavior);
229 void OnLanguageChanged(const QString& locale);
228 230
229private: 231private:
230 std::optional<u64> SelectRomFSDumpTarget(const FileSys::ContentProvider&, u64 program_id); 232 std::optional<u64> SelectRomFSDumpTarget(const FileSys::ContentProvider&, u64 program_id);
@@ -237,6 +239,7 @@ private:
237 void HideMouseCursor(); 239 void HideMouseCursor();
238 void ShowMouseCursor(); 240 void ShowMouseCursor();
239 void OpenURL(const QUrl& url); 241 void OpenURL(const QUrl& url);
242 void LoadTranslation();
240 243
241 Ui::MainWindow ui; 244 Ui::MainWindow ui;
242 245
@@ -248,6 +251,7 @@ private:
248 251
249 // Status bar elements 252 // Status bar elements
250 QLabel* message_label = nullptr; 253 QLabel* message_label = nullptr;
254 QLabel* shader_building_label = nullptr;
251 QLabel* emu_speed_label = nullptr; 255 QLabel* emu_speed_label = nullptr;
252 QLabel* game_fps_label = nullptr; 256 QLabel* game_fps_label = nullptr;
253 QLabel* emu_frametime_label = nullptr; 257 QLabel* emu_frametime_label = nullptr;
@@ -284,6 +288,8 @@ private:
284 288
285 HotkeyRegistry hotkey_registry; 289 HotkeyRegistry hotkey_registry;
286 290
291 QTranslator translator;
292
287 // Install progress dialog 293 // Install progress dialog
288 QProgressDialog* install_progress; 294 QProgressDialog* install_progress;
289 295
diff --git a/src/yuzu/uisettings.cpp b/src/yuzu/uisettings.cpp
index 738c4b2fc..a51175f36 100644
--- a/src/yuzu/uisettings.cpp
+++ b/src/yuzu/uisettings.cpp
@@ -11,6 +11,8 @@ const Themes themes{{
11 {"Light Colorful", "colorful"}, 11 {"Light Colorful", "colorful"},
12 {"Dark", "qdarkstyle"}, 12 {"Dark", "qdarkstyle"},
13 {"Dark Colorful", "colorful_dark"}, 13 {"Dark Colorful", "colorful_dark"},
14 {"Midnight Blue", "qdarkstyle_midnight_blue"},
15 {"Midnight Blue Colorful", "colorful_midnight_blue"},
14}}; 16}};
15 17
16Values values = {}; 18Values values = {};
diff --git a/src/yuzu/uisettings.h b/src/yuzu/uisettings.h
index 830932d45..ac7b9aef6 100644
--- a/src/yuzu/uisettings.h
+++ b/src/yuzu/uisettings.h
@@ -24,7 +24,7 @@ struct Shortcut {
24 ContextualShortcut shortcut; 24 ContextualShortcut shortcut;
25}; 25};
26 26
27using Themes = std::array<std::pair<const char*, const char*>, 4>; 27using Themes = std::array<std::pair<const char*, const char*>, 6>;
28extern const Themes themes; 28extern const Themes themes;
29 29
30struct GameDir { 30struct GameDir {
@@ -75,6 +75,7 @@ struct Values {
75 bool game_dir_deprecated_deepscan; 75 bool game_dir_deprecated_deepscan;
76 QVector<UISettings::GameDir> game_dirs; 76 QVector<UISettings::GameDir> game_dirs;
77 QStringList recent_files; 77 QStringList recent_files;
78 QString language;
78 79
79 QString theme; 80 QString theme;
80 81
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp
index 7773228c8..c2a2982fb 100644
--- a/src/yuzu_cmd/config.cpp
+++ b/src/yuzu_cmd/config.cpp
@@ -394,6 +394,10 @@ void Config::ReadValues() {
394 static_cast<u16>(sdl2_config->GetInteger("Renderer", "use_vsync", 1))); 394 static_cast<u16>(sdl2_config->GetInteger("Renderer", "use_vsync", 1)));
395 Settings::values.use_assembly_shaders.SetValue( 395 Settings::values.use_assembly_shaders.SetValue(
396 sdl2_config->GetBoolean("Renderer", "use_assembly_shaders", false)); 396 sdl2_config->GetBoolean("Renderer", "use_assembly_shaders", false));
397 Settings::values.use_asynchronous_shaders.SetValue(
398 sdl2_config->GetBoolean("Renderer", "use_asynchronous_shaders", false));
399 Settings::values.use_asynchronous_shaders.SetValue(
400 sdl2_config->GetBoolean("Renderer", "use_asynchronous_shaders", false));
397 Settings::values.use_fast_gpu_time.SetValue( 401 Settings::values.use_fast_gpu_time.SetValue(
398 sdl2_config->GetBoolean("Renderer", "use_fast_gpu_time", true)); 402 sdl2_config->GetBoolean("Renderer", "use_fast_gpu_time", true));
399 403
diff --git a/src/yuzu_cmd/default_ini.h b/src/yuzu_cmd/default_ini.h
index 5bed47fd7..aa9e40380 100644
--- a/src/yuzu_cmd/default_ini.h
+++ b/src/yuzu_cmd/default_ini.h
@@ -166,6 +166,10 @@ use_vsync =
166# 0 (default): Off, 1: On 166# 0 (default): Off, 1: On
167use_assembly_shaders = 167use_assembly_shaders =
168 168
169# Whether to allow asynchronous shader building.
170# 0 (default): Off, 1: On
171use_asynchronous_shaders =
172
169# Turns on the frame limiter, which will limit frames output to the target game speed 173# Turns on the frame limiter, which will limit frames output to the target game speed
170# 0: Off, 1: On (default) 174# 0: Off, 1: On (default)
171use_frame_limit = 175use_frame_limit =