diff options
304 files changed, 11782 insertions, 5588 deletions
diff --git a/.ci/scripts/format/script.sh b/.ci/scripts/format/script.sh index 5ab828d5e..969ab637c 100644 --- a/.ci/scripts/format/script.sh +++ b/.ci/scripts/format/script.sh | |||
| @@ -7,7 +7,7 @@ if grep -nrI '\s$' src *.yml *.txt *.md Doxyfile .gitignore .gitmodules .ci* dis | |||
| 7 | fi | 7 | fi |
| 8 | 8 | ||
| 9 | # Default clang-format points to default 3.5 version one | 9 | # Default clang-format points to default 3.5 version one |
| 10 | CLANG_FORMAT=clang-format-6.0 | 10 | CLANG_FORMAT=clang-format-10 |
| 11 | $CLANG_FORMAT --version | 11 | $CLANG_FORMAT --version |
| 12 | 12 | ||
| 13 | if [ "$TRAVIS_EVENT_TYPE" = "pull_request" ]; then | 13 | if [ "$TRAVIS_EVENT_TYPE" = "pull_request" ]; then |
diff --git a/.travis/clang-format/script.sh b/.travis/clang-format/script.sh index 3eff6322f..56a785fe0 100755 --- a/.travis/clang-format/script.sh +++ b/.travis/clang-format/script.sh | |||
| @@ -7,7 +7,7 @@ if grep -nrI '\s$' src *.yml *.txt *.md Doxyfile .gitignore .gitmodules .travis* | |||
| 7 | fi | 7 | fi |
| 8 | 8 | ||
| 9 | # Default clang-format points to default 3.5 version one | 9 | # Default clang-format points to default 3.5 version one |
| 10 | CLANG_FORMAT=clang-format-6.0 | 10 | CLANG_FORMAT=clang-format-10.0 |
| 11 | $CLANG_FORMAT --version | 11 | $CLANG_FORMAT --version |
| 12 | 12 | ||
| 13 | if [ "$TRAVIS_EVENT_TYPE" = "pull_request" ]; then | 13 | if [ "$TRAVIS_EVENT_TYPE" = "pull_request" ]; then |
diff --git a/CMakeLists.txt b/CMakeLists.txt index 3282ae9d4..2f3c59c5d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt | |||
| @@ -161,7 +161,7 @@ macro(yuzu_find_packages) | |||
| 161 | # Cmake Pkg Prefix Version Conan Pkg | 161 | # Cmake Pkg Prefix Version Conan Pkg |
| 162 | "Boost 1.73 boost/1.73.0" | 162 | "Boost 1.73 boost/1.73.0" |
| 163 | "Catch2 2.13 catch2/2.13.0" | 163 | "Catch2 2.13 catch2/2.13.0" |
| 164 | "fmt 7.0 fmt/7.0.1" | 164 | "fmt 7.0 fmt/7.0.3" |
| 165 | # can't use until https://github.com/bincrafters/community/issues/1173 | 165 | # can't use until https://github.com/bincrafters/community/issues/1173 |
| 166 | #"libzip 1.5 libzip/1.5.2@bincrafters/stable" | 166 | #"libzip 1.5 libzip/1.5.2@bincrafters/stable" |
| 167 | "lz4 1.8 lz4/1.9.2" | 167 | "lz4 1.8 lz4/1.9.2" |
| @@ -456,7 +456,7 @@ endif() | |||
| 456 | # against all the src files. This should be used before making a pull request. | 456 | # against all the src files. This should be used before making a pull request. |
| 457 | # ======================================================================= | 457 | # ======================================================================= |
| 458 | 458 | ||
| 459 | set(CLANG_FORMAT_POSTFIX "-6.0") | 459 | set(CLANG_FORMAT_POSTFIX "-10") |
| 460 | find_program(CLANG_FORMAT | 460 | find_program(CLANG_FORMAT |
| 461 | NAMES clang-format${CLANG_FORMAT_POSTFIX} | 461 | NAMES clang-format${CLANG_FORMAT_POSTFIX} |
| 462 | clang-format | 462 | clang-format |
diff --git a/dist/icons/controller/controller.qrc b/dist/icons/controller/controller.qrc new file mode 100644 index 000000000..f44725d8f --- /dev/null +++ b/dist/icons/controller/controller.qrc | |||
| @@ -0,0 +1,25 @@ | |||
| 1 | <RCC> | ||
| 2 | <qresource prefix="controller"> | ||
| 3 | <file alias="dual_joycon">dual_joycon.png</file> | ||
| 4 | <file alias="dual_joycon_dark">dual_joycon_dark.png</file> | ||
| 5 | <file alias="dual_joycon_midnight">dual_joycon_midnight.png</file> | ||
| 6 | <file alias="handheld">handheld.png</file> | ||
| 7 | <file alias="handheld_dark">handheld_dark.png</file> | ||
| 8 | <file alias="handheld_midnight">handheld_midnight.png</file> | ||
| 9 | <file alias="pro_controller">pro_controller.png</file> | ||
| 10 | <file alias="pro_controller_dark">pro_controller_dark.png</file> | ||
| 11 | <file alias="pro_controller_midnight">pro_controller_midnight.png</file> | ||
| 12 | <file alias="single_joycon_left">single_joycon_left.png</file> | ||
| 13 | <file alias="single_joycon_left_dark">single_joycon_left_dark.png</file> | ||
| 14 | <file alias="single_joycon_left_midnight">single_joycon_left_midnight.png</file> | ||
| 15 | <file alias="single_joycon_right">single_joycon_right.png</file> | ||
| 16 | <file alias="single_joycon_right_dark">single_joycon_right_dark.png</file> | ||
| 17 | <file alias="single_joycon_right_midnight">single_joycon_right_midnight.png</file> | ||
| 18 | <file alias="single_joycon_left_vertical">single_joycon_left_vertical.png</file> | ||
| 19 | <file alias="single_joycon_left_vertical_dark">single_joycon_left_vertical_dark.png</file> | ||
| 20 | <file alias="single_joycon_left_vertical_midnight">single_joycon_left_vertical_midnight.png</file> | ||
| 21 | <file alias="single_joycon_right_vertical">single_joycon_right_vertical.png</file> | ||
| 22 | <file alias="single_joycon_right_vertical_dark">single_joycon_right_vertical_dark.png</file> | ||
| 23 | <file alias="single_joycon_right_vertical_midnight">single_joycon_right_vertical_midnight.png</file> | ||
| 24 | </qresource> | ||
| 25 | </RCC> | ||
diff --git a/dist/icons/controller/dual_joycon.png b/dist/icons/controller/dual_joycon.png new file mode 100644 index 000000000..4230f5f7b --- /dev/null +++ b/dist/icons/controller/dual_joycon.png | |||
| Binary files differ | |||
diff --git a/dist/icons/controller/dual_joycon_dark.png b/dist/icons/controller/dual_joycon_dark.png new file mode 100644 index 000000000..4445db489 --- /dev/null +++ b/dist/icons/controller/dual_joycon_dark.png | |||
| Binary files differ | |||
diff --git a/dist/icons/controller/dual_joycon_midnight.png b/dist/icons/controller/dual_joycon_midnight.png new file mode 100644 index 000000000..aac8e5321 --- /dev/null +++ b/dist/icons/controller/dual_joycon_midnight.png | |||
| Binary files differ | |||
diff --git a/dist/icons/controller/handheld.png b/dist/icons/controller/handheld.png new file mode 100644 index 000000000..d009b4a47 --- /dev/null +++ b/dist/icons/controller/handheld.png | |||
| Binary files differ | |||
diff --git a/dist/icons/controller/handheld_dark.png b/dist/icons/controller/handheld_dark.png new file mode 100644 index 000000000..c80ca9259 --- /dev/null +++ b/dist/icons/controller/handheld_dark.png | |||
| Binary files differ | |||
diff --git a/dist/icons/controller/handheld_midnight.png b/dist/icons/controller/handheld_midnight.png new file mode 100644 index 000000000..19de4629b --- /dev/null +++ b/dist/icons/controller/handheld_midnight.png | |||
| Binary files differ | |||
diff --git a/dist/icons/controller/pro_controller.png b/dist/icons/controller/pro_controller.png new file mode 100644 index 000000000..07d65e94a --- /dev/null +++ b/dist/icons/controller/pro_controller.png | |||
| Binary files differ | |||
diff --git a/dist/icons/controller/pro_controller_dark.png b/dist/icons/controller/pro_controller_dark.png new file mode 100644 index 000000000..73efe18f4 --- /dev/null +++ b/dist/icons/controller/pro_controller_dark.png | |||
| Binary files differ | |||
diff --git a/dist/icons/controller/pro_controller_midnight.png b/dist/icons/controller/pro_controller_midnight.png new file mode 100644 index 000000000..8d7e63f0d --- /dev/null +++ b/dist/icons/controller/pro_controller_midnight.png | |||
| Binary files differ | |||
diff --git a/dist/icons/controller/single_joycon_left.png b/dist/icons/controller/single_joycon_left.png new file mode 100644 index 000000000..547153034 --- /dev/null +++ b/dist/icons/controller/single_joycon_left.png | |||
| Binary files differ | |||
diff --git a/dist/icons/controller/single_joycon_left_dark.png b/dist/icons/controller/single_joycon_left_dark.png new file mode 100644 index 000000000..b6ee073cb --- /dev/null +++ b/dist/icons/controller/single_joycon_left_dark.png | |||
| Binary files differ | |||
diff --git a/dist/icons/controller/single_joycon_left_midnight.png b/dist/icons/controller/single_joycon_left_midnight.png new file mode 100644 index 000000000..34a485c81 --- /dev/null +++ b/dist/icons/controller/single_joycon_left_midnight.png | |||
| Binary files differ | |||
diff --git a/dist/icons/controller/single_joycon_left_vertical.png b/dist/icons/controller/single_joycon_left_vertical.png new file mode 100644 index 000000000..1e6282ad8 --- /dev/null +++ b/dist/icons/controller/single_joycon_left_vertical.png | |||
| Binary files differ | |||
diff --git a/dist/icons/controller/single_joycon_left_vertical_dark.png b/dist/icons/controller/single_joycon_left_vertical_dark.png new file mode 100644 index 000000000..a615d995d --- /dev/null +++ b/dist/icons/controller/single_joycon_left_vertical_dark.png | |||
| Binary files differ | |||
diff --git a/dist/icons/controller/single_joycon_left_vertical_midnight.png b/dist/icons/controller/single_joycon_left_vertical_midnight.png new file mode 100644 index 000000000..4cc578216 --- /dev/null +++ b/dist/icons/controller/single_joycon_left_vertical_midnight.png | |||
| Binary files differ | |||
diff --git a/dist/icons/controller/single_joycon_right.png b/dist/icons/controller/single_joycon_right.png new file mode 100644 index 000000000..8d29173f6 --- /dev/null +++ b/dist/icons/controller/single_joycon_right.png | |||
| Binary files differ | |||
diff --git a/dist/icons/controller/single_joycon_right_dark.png b/dist/icons/controller/single_joycon_right_dark.png new file mode 100644 index 000000000..ead2c44e0 --- /dev/null +++ b/dist/icons/controller/single_joycon_right_dark.png | |||
| Binary files differ | |||
diff --git a/dist/icons/controller/single_joycon_right_midnight.png b/dist/icons/controller/single_joycon_right_midnight.png new file mode 100644 index 000000000..89afe022d --- /dev/null +++ b/dist/icons/controller/single_joycon_right_midnight.png | |||
| Binary files differ | |||
diff --git a/dist/icons/controller/single_joycon_right_vertical.png b/dist/icons/controller/single_joycon_right_vertical.png new file mode 100644 index 000000000..4d7d06547 --- /dev/null +++ b/dist/icons/controller/single_joycon_right_vertical.png | |||
| Binary files differ | |||
diff --git a/dist/icons/controller/single_joycon_right_vertical_dark.png b/dist/icons/controller/single_joycon_right_vertical_dark.png new file mode 100644 index 000000000..9a6eb3013 --- /dev/null +++ b/dist/icons/controller/single_joycon_right_vertical_dark.png | |||
| Binary files differ | |||
diff --git a/dist/icons/controller/single_joycon_right_vertical_midnight.png b/dist/icons/controller/single_joycon_right_vertical_midnight.png new file mode 100644 index 000000000..685249b68 --- /dev/null +++ b/dist/icons/controller/single_joycon_right_vertical_midnight.png | |||
| Binary files differ | |||
diff --git a/dist/license.md b/dist/license.md index f1ff35c95..e9bc87656 100644 --- a/dist/license.md +++ b/dist/license.md | |||
| @@ -5,6 +5,7 @@ Icon Name | License | Origin/Author | |||
| 5 | qt_themes/default/icons/16x16/checked.png | CC BY-ND 3.0 | https://icons8.com | 5 | qt_themes/default/icons/16x16/checked.png | CC BY-ND 3.0 | https://icons8.com |
| 6 | qt_themes/default/icons/16x16/failed.png | CC BY-ND 3.0 | https://icons8.com | 6 | qt_themes/default/icons/16x16/failed.png | CC BY-ND 3.0 | https://icons8.com |
| 7 | qt_themes/default/icons/16x16/lock.png | CC BY-ND 3.0 | https://icons8.com | 7 | qt_themes/default/icons/16x16/lock.png | CC BY-ND 3.0 | https://icons8.com |
| 8 | qt_themes/default/icons/16x16/view-refresh.png | Apache 2.0 | https://material.io | ||
| 8 | qt_themes/default/icons/256x256/plus_folder.png | CC BY-ND 3.0 | https://icons8.com | 9 | qt_themes/default/icons/256x256/plus_folder.png | CC BY-ND 3.0 | https://icons8.com |
| 9 | qt_themes/default/icons/48x48/bad_folder.png | CC BY-ND 3.0 | https://icons8.com | 10 | qt_themes/default/icons/48x48/bad_folder.png | CC BY-ND 3.0 | https://icons8.com |
| 10 | qt_themes/default/icons/48x48/chip.png | CC BY-ND 3.0 | https://icons8.com | 11 | qt_themes/default/icons/48x48/chip.png | CC BY-ND 3.0 | https://icons8.com |
| @@ -12,6 +13,7 @@ qt_themes/default/icons/48x48/folder.png | CC BY-ND 3.0 | https://icons8.com | |||
| 12 | qt_themes/default/icons/48x48/plus.png | CC0 1.0 | Designed by BreadFish64 from the Citra team | 13 | qt_themes/default/icons/48x48/plus.png | CC0 1.0 | Designed by BreadFish64 from the Citra team |
| 13 | qt_themes/default/icons/48x48/sd_card.png | CC BY-ND 3.0 | https://icons8.com | 14 | qt_themes/default/icons/48x48/sd_card.png | CC BY-ND 3.0 | https://icons8.com |
| 14 | qt_themes/qdarkstyle/icons/16x16/lock.png | CC BY-ND 3.0 | https://icons8.com | 15 | qt_themes/qdarkstyle/icons/16x16/lock.png | CC BY-ND 3.0 | https://icons8.com |
| 16 | qt_themes/qdarkstyle/icons/16x16/view-refresh.png | Apache 2.0 | https://material.io | ||
| 15 | qt_themes/qdarkstyle/icons/256x256/plus_folder.png | CC BY-ND 3.0 | https://icons8.com | 17 | qt_themes/qdarkstyle/icons/256x256/plus_folder.png | CC BY-ND 3.0 | https://icons8.com |
| 16 | qt_themes/qdarkstyle/icons/48x48/bad_folder.png | CC BY-ND 3.0 | https://icons8.com | 18 | qt_themes/qdarkstyle/icons/48x48/bad_folder.png | CC BY-ND 3.0 | https://icons8.com |
| 17 | qt_themes/qdarkstyle/icons/48x48/chip.png | CC BY-ND 3.0 | https://icons8.com | 19 | qt_themes/qdarkstyle/icons/48x48/chip.png | CC BY-ND 3.0 | https://icons8.com |
| @@ -19,6 +21,7 @@ qt_themes/qdarkstyle/icons/48x48/folder.png | CC BY-ND 3.0 | https://icons8.com | |||
| 19 | qt_themes/qdarkstyle/icons/48x48/plus.png | CC0 1.0 | Designed by BreadFish64 from the Citra team | 21 | qt_themes/qdarkstyle/icons/48x48/plus.png | CC0 1.0 | Designed by BreadFish64 from the Citra team |
| 20 | qt_themes/qdarkstyle/icons/48x48/sd_card.png | CC BY-ND 3.0 | https://icons8.com | 22 | qt_themes/qdarkstyle/icons/48x48/sd_card.png | CC BY-ND 3.0 | https://icons8.com |
| 21 | qt_themes/colorful/icons/16x16/lock.png | CC BY-ND 3.0 | https://icons8.com | 23 | qt_themes/colorful/icons/16x16/lock.png | CC BY-ND 3.0 | https://icons8.com |
| 24 | qt_themes/colorful/icons/16x16/view-refresh.png | Apache 2.0 | https://material.io | ||
| 22 | qt_themes/colorful/icons/256x256/plus_folder.png | CC BY-ND 3.0 | https://icons8.com | 25 | qt_themes/colorful/icons/256x256/plus_folder.png | CC BY-ND 3.0 | https://icons8.com |
| 23 | qt_themes/colorful/icons/48x48/bad_folder.png | CC BY-ND 3.0 | https://icons8.com | 26 | qt_themes/colorful/icons/48x48/bad_folder.png | CC BY-ND 3.0 | https://icons8.com |
| 24 | qt_themes/colorful/icons/48x48/chip.png | CC BY-ND 3.0 | https://icons8.com | 27 | qt_themes/colorful/icons/48x48/chip.png | CC BY-ND 3.0 | https://icons8.com |
diff --git a/dist/qt_themes/colorful_dark/icons/16x16/refresh.png b/dist/qt_themes/colorful_dark/icons/16x16/refresh.png new file mode 100644 index 000000000..d4afd76f9 --- /dev/null +++ b/dist/qt_themes/colorful_dark/icons/16x16/refresh.png | |||
| Binary files differ | |||
diff --git a/dist/qt_themes/colorful_dark/icons/16x16/view-refresh.png b/dist/qt_themes/colorful_dark/icons/16x16/view-refresh.png new file mode 100644 index 000000000..d4afd76f9 --- /dev/null +++ b/dist/qt_themes/colorful_dark/icons/16x16/view-refresh.png | |||
| Binary files differ | |||
diff --git a/dist/qt_themes/colorful_dark/style.qrc b/dist/qt_themes/colorful_dark/style.qrc index 27a6cc87d..0abcb4e83 100644 --- a/dist/qt_themes/colorful_dark/style.qrc +++ b/dist/qt_themes/colorful_dark/style.qrc | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | <qresource prefix="icons/colorful_dark"> | 2 | <qresource prefix="icons/colorful_dark"> |
| 3 | <file alias="index.theme">icons/index.theme</file> | 3 | <file alias="index.theme">icons/index.theme</file> |
| 4 | <file alias="16x16/lock.png">icons/16x16/lock.png</file> | 4 | <file alias="16x16/lock.png">icons/16x16/lock.png</file> |
| 5 | <file alias="16x16/view-refresh.png">icons/16x16/view-refresh.png</file> | ||
| 5 | <file alias="48x48/bad_folder.png">../colorful/icons/48x48/bad_folder.png</file> | 6 | <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/chip.png">../colorful/icons/48x48/chip.png</file> |
| 7 | <file alias="48x48/folder.png">../colorful/icons/48x48/folder.png</file> | 8 | <file alias="48x48/folder.png">../colorful/icons/48x48/folder.png</file> |
diff --git a/dist/qt_themes/colorful_midnight_blue/icons/16x16/refresh.png b/dist/qt_themes/colorful_midnight_blue/icons/16x16/refresh.png new file mode 100644 index 000000000..d4afd76f9 --- /dev/null +++ b/dist/qt_themes/colorful_midnight_blue/icons/16x16/refresh.png | |||
| Binary files differ | |||
diff --git a/dist/qt_themes/colorful_midnight_blue/icons/16x16/view-refresh.png b/dist/qt_themes/colorful_midnight_blue/icons/16x16/view-refresh.png new file mode 100644 index 000000000..d4afd76f9 --- /dev/null +++ b/dist/qt_themes/colorful_midnight_blue/icons/16x16/view-refresh.png | |||
| Binary files differ | |||
diff --git a/dist/qt_themes/colorful_midnight_blue/style.qrc b/dist/qt_themes/colorful_midnight_blue/style.qrc index fd33bc850..bf367099a 100644 --- a/dist/qt_themes/colorful_midnight_blue/style.qrc +++ b/dist/qt_themes/colorful_midnight_blue/style.qrc | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | <qresource prefix="icons/colorful_midnight_blue"> | 2 | <qresource prefix="icons/colorful_midnight_blue"> |
| 3 | <file alias="index.theme">icons/index.theme</file> | 3 | <file alias="index.theme">icons/index.theme</file> |
| 4 | <file alias="16x16/lock.png">icons/16x16/lock.png</file> | 4 | <file alias="16x16/lock.png">icons/16x16/lock.png</file> |
| 5 | <file alias="16x16/view-refresh.png">icons/16x16/view-refresh.png</file> | ||
| 5 | <file alias="48x48/bad_folder.png">../colorful/icons/48x48/bad_folder.png</file> | 6 | <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/chip.png">../colorful/icons/48x48/chip.png</file> |
| 7 | <file alias="48x48/folder.png">../colorful/icons/48x48/folder.png</file> | 8 | <file alias="48x48/folder.png">../colorful/icons/48x48/folder.png</file> |
diff --git a/dist/qt_themes/default/default.qrc b/dist/qt_themes/default/default.qrc index c51fdb26c..2182f33f3 100644 --- a/dist/qt_themes/default/default.qrc +++ b/dist/qt_themes/default/default.qrc | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | <file alias="16x16/checked.png">icons/16x16/checked.png</file> | 4 | <file alias="16x16/checked.png">icons/16x16/checked.png</file> |
| 5 | <file alias="16x16/failed.png">icons/16x16/failed.png</file> | 5 | <file alias="16x16/failed.png">icons/16x16/failed.png</file> |
| 6 | <file alias="16x16/lock.png">icons/16x16/lock.png</file> | 6 | <file alias="16x16/lock.png">icons/16x16/lock.png</file> |
| 7 | <file alias="16x16/view-refresh.png">icons/16x16/view-refresh.png</file> | ||
| 7 | <file alias="48x48/bad_folder.png">icons/48x48/bad_folder.png</file> | 8 | <file alias="48x48/bad_folder.png">icons/48x48/bad_folder.png</file> |
| 8 | <file alias="48x48/chip.png">icons/48x48/chip.png</file> | 9 | <file alias="48x48/chip.png">icons/48x48/chip.png</file> |
| 9 | <file alias="48x48/folder.png">icons/48x48/folder.png</file> | 10 | <file alias="48x48/folder.png">icons/48x48/folder.png</file> |
diff --git a/dist/qt_themes/default/icons/16x16/refresh.png b/dist/qt_themes/default/icons/16x16/refresh.png new file mode 100644 index 000000000..69f9474ac --- /dev/null +++ b/dist/qt_themes/default/icons/16x16/refresh.png | |||
| Binary files differ | |||
diff --git a/dist/qt_themes/default/icons/16x16/view-refresh.png b/dist/qt_themes/default/icons/16x16/view-refresh.png new file mode 100644 index 000000000..69f9474ac --- /dev/null +++ b/dist/qt_themes/default/icons/16x16/view-refresh.png | |||
| Binary files differ | |||
diff --git a/dist/qt_themes/default/style.qss b/dist/qt_themes/default/style.qss index 6b5953e38..5da56520b 100644 --- a/dist/qt_themes/default/style.qss +++ b/dist/qt_themes/default/style.qss | |||
| @@ -30,6 +30,66 @@ QPushButton#RendererStatusBarButton:checked { | |||
| 30 | color: #e85c00; | 30 | color: #e85c00; |
| 31 | } | 31 | } |
| 32 | 32 | ||
| 33 | QPushButton#RendererStatusBarButton:!checked{ | 33 | QPushButton#RendererStatusBarButton:!checked { |
| 34 | color: #0066ff; | 34 | color: #0066ff; |
| 35 | } | 35 | } |
| 36 | |||
| 37 | QPushButton#buttonRefreshDevices { | ||
| 38 | min-width: 20px; | ||
| 39 | min-height: 20px; | ||
| 40 | max-width: 20px; | ||
| 41 | max-height: 20px; | ||
| 42 | } | ||
| 43 | |||
| 44 | QCheckBox#checkboxPlayer1Connected, | ||
| 45 | QCheckBox#checkboxPlayer2Connected, | ||
| 46 | QCheckBox#checkboxPlayer3Connected, | ||
| 47 | QCheckBox#checkboxPlayer4Connected, | ||
| 48 | QCheckBox#checkboxPlayer5Connected, | ||
| 49 | QCheckBox#checkboxPlayer6Connected, | ||
| 50 | QCheckBox#checkboxPlayer7Connected, | ||
| 51 | QCheckBox#checkboxPlayer8Connected { | ||
| 52 | spacing: 0px; | ||
| 53 | } | ||
| 54 | |||
| 55 | QCheckBox#checkboxPlayer1Connected::indicator, | ||
| 56 | QCheckBox#checkboxPlayer2Connected::indicator, | ||
| 57 | QCheckBox#checkboxPlayer3Connected::indicator, | ||
| 58 | QCheckBox#checkboxPlayer4Connected::indicator, | ||
| 59 | QCheckBox#checkboxPlayer5Connected::indicator, | ||
| 60 | QCheckBox#checkboxPlayer6Connected::indicator, | ||
| 61 | QCheckBox#checkboxPlayer7Connected::indicator, | ||
| 62 | QCheckBox#checkboxPlayer8Connected::indicator { | ||
| 63 | width: 14px; | ||
| 64 | height: 14px; | ||
| 65 | } | ||
| 66 | |||
| 67 | QCheckBox#checkboxPlayer1Connected::indicator:checked, | ||
| 68 | QCheckBox#checkboxPlayer2Connected::indicator:checked, | ||
| 69 | QCheckBox#checkboxPlayer3Connected::indicator:checked, | ||
| 70 | QCheckBox#checkboxPlayer4Connected::indicator:checked, | ||
| 71 | QCheckBox#checkboxPlayer5Connected::indicator:checked, | ||
| 72 | QCheckBox#checkboxPlayer6Connected::indicator:checked, | ||
| 73 | QCheckBox#checkboxPlayer7Connected::indicator:checked, | ||
| 74 | QCheckBox#checkboxPlayer8Connected::indicator:checked, | ||
| 75 | QGroupBox#groupConnectedController::indicator:checked { | ||
| 76 | border-radius: 2px; | ||
| 77 | border: 1px solid black; | ||
| 78 | background: #39ff14; | ||
| 79 | image: none; | ||
| 80 | } | ||
| 81 | |||
| 82 | QCheckBox#checkboxPlayer1Connected::indicator:unchecked, | ||
| 83 | QCheckBox#checkboxPlayer2Connected::indicator:unchecked, | ||
| 84 | QCheckBox#checkboxPlayer3Connected::indicator:unchecked, | ||
| 85 | QCheckBox#checkboxPlayer4Connected::indicator:unchecked, | ||
| 86 | QCheckBox#checkboxPlayer5Connected::indicator:unchecked, | ||
| 87 | QCheckBox#checkboxPlayer6Connected::indicator:unchecked, | ||
| 88 | QCheckBox#checkboxPlayer7Connected::indicator:unchecked, | ||
| 89 | QCheckBox#checkboxPlayer8Connected::indicator:unchecked, | ||
| 90 | QGroupBox#groupConnectedController::indicator:unchecked { | ||
| 91 | border-radius: 2px; | ||
| 92 | border: 1px solid black; | ||
| 93 | background: transparent; | ||
| 94 | image: none; | ||
| 95 | } | ||
diff --git a/dist/qt_themes/qdarkstyle/icons/16x16/refresh.png b/dist/qt_themes/qdarkstyle/icons/16x16/refresh.png new file mode 100644 index 000000000..d4afd76f9 --- /dev/null +++ b/dist/qt_themes/qdarkstyle/icons/16x16/refresh.png | |||
| Binary files differ | |||
diff --git a/dist/qt_themes/qdarkstyle/icons/16x16/view-refresh.png b/dist/qt_themes/qdarkstyle/icons/16x16/view-refresh.png new file mode 100644 index 000000000..d4afd76f9 --- /dev/null +++ b/dist/qt_themes/qdarkstyle/icons/16x16/view-refresh.png | |||
| Binary files differ | |||
diff --git a/dist/qt_themes/qdarkstyle/style.qrc b/dist/qt_themes/qdarkstyle/style.qrc index c2c14c28a..ec07ba160 100644 --- a/dist/qt_themes/qdarkstyle/style.qrc +++ b/dist/qt_themes/qdarkstyle/style.qrc | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | <qresource prefix="icons/qdarkstyle"> | 2 | <qresource prefix="icons/qdarkstyle"> |
| 3 | <file alias="index.theme">icons/index.theme</file> | 3 | <file alias="index.theme">icons/index.theme</file> |
| 4 | <file alias="16x16/lock.png">icons/16x16/lock.png</file> | 4 | <file alias="16x16/lock.png">icons/16x16/lock.png</file> |
| 5 | <file alias="16x16/view-refresh.png">icons/16x16/view-refresh.png</file> | ||
| 5 | <file alias="48x48/bad_folder.png">icons/48x48/bad_folder.png</file> | 6 | <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/chip.png">icons/48x48/chip.png</file> |
| 7 | <file alias="48x48/folder.png">icons/48x48/folder.png</file> | 8 | <file alias="48x48/folder.png">icons/48x48/folder.png</file> |
diff --git a/dist/qt_themes/qdarkstyle/style.qss b/dist/qt_themes/qdarkstyle/style.qss index 2926a05fa..7755426f8 100644 --- a/dist/qt_themes/qdarkstyle/style.qss +++ b/dist/qt_themes/qdarkstyle/style.qss | |||
| @@ -40,8 +40,8 @@ QCheckBox:disabled { | |||
| 40 | 40 | ||
| 41 | QCheckBox::indicator, | 41 | QCheckBox::indicator, |
| 42 | QGroupBox::indicator { | 42 | QGroupBox::indicator { |
| 43 | width: 18px; | 43 | width: 16px; |
| 44 | height: 18px; | 44 | height: 16px; |
| 45 | } | 45 | } |
| 46 | 46 | ||
| 47 | QGroupBox::indicator { | 47 | QGroupBox::indicator { |
| @@ -1237,6 +1237,7 @@ QPlainTextEdit:disabled { | |||
| 1237 | background-color: #2b2e31; | 1237 | background-color: #2b2e31; |
| 1238 | } | 1238 | } |
| 1239 | 1239 | ||
| 1240 | |||
| 1240 | QPushButton#TogglableStatusBarButton { | 1241 | QPushButton#TogglableStatusBarButton { |
| 1241 | min-width: 0px; | 1242 | min-width: 0px; |
| 1242 | color: #656565; | 1243 | color: #656565; |
| @@ -1271,6 +1272,102 @@ QPushButton#RendererStatusBarButton:checked { | |||
| 1271 | color: #e85c00; | 1272 | color: #e85c00; |
| 1272 | } | 1273 | } |
| 1273 | 1274 | ||
| 1274 | QPushButton#RendererStatusBarButton:!checked{ | 1275 | QPushButton#RendererStatusBarButton:!checked { |
| 1275 | color: #00ccdd; | 1276 | color: #00ccdd; |
| 1277 | } | ||
| 1278 | |||
| 1279 | QPushButton#buttonRefreshDevices { | ||
| 1280 | min-width: 24px; | ||
| 1281 | min-height: 24px; | ||
| 1282 | max-width: 24px; | ||
| 1283 | max-height: 24px; | ||
| 1284 | padding: 0px 0px; | ||
| 1285 | } | ||
| 1286 | |||
| 1287 | QCheckBox#checkboxPlayer1Connected, | ||
| 1288 | QCheckBox#checkboxPlayer2Connected, | ||
| 1289 | QCheckBox#checkboxPlayer3Connected, | ||
| 1290 | QCheckBox#checkboxPlayer4Connected, | ||
| 1291 | QCheckBox#checkboxPlayer5Connected, | ||
| 1292 | QCheckBox#checkboxPlayer6Connected, | ||
| 1293 | QCheckBox#checkboxPlayer7Connected, | ||
| 1294 | QCheckBox#checkboxPlayer8Connected { | ||
| 1295 | spacing: 0px; | ||
| 1296 | } | ||
| 1297 | |||
| 1298 | QCheckBox#checkboxPlayer1Connected::indicator, | ||
| 1299 | QCheckBox#checkboxPlayer2Connected::indicator, | ||
| 1300 | QCheckBox#checkboxPlayer3Connected::indicator, | ||
| 1301 | QCheckBox#checkboxPlayer4Connected::indicator, | ||
| 1302 | QCheckBox#checkboxPlayer5Connected::indicator, | ||
| 1303 | QCheckBox#checkboxPlayer6Connected::indicator, | ||
| 1304 | QCheckBox#checkboxPlayer7Connected::indicator, | ||
| 1305 | QCheckBox#checkboxPlayer8Connected::indicator { | ||
| 1306 | width: 14px; | ||
| 1307 | height: 14px; | ||
| 1308 | } | ||
| 1309 | |||
| 1310 | QCheckBox#checkboxPlayer1Connected::indicator:checked, | ||
| 1311 | QCheckBox#checkboxPlayer2Connected::indicator:checked, | ||
| 1312 | QCheckBox#checkboxPlayer3Connected::indicator:checked, | ||
| 1313 | QCheckBox#checkboxPlayer4Connected::indicator:checked, | ||
| 1314 | QCheckBox#checkboxPlayer5Connected::indicator:checked, | ||
| 1315 | QCheckBox#checkboxPlayer6Connected::indicator:checked, | ||
| 1316 | QCheckBox#checkboxPlayer7Connected::indicator:checked, | ||
| 1317 | QCheckBox#checkboxPlayer8Connected::indicator:checked, | ||
| 1318 | QGroupBox#groupConnectedController::indicator:checked { | ||
| 1319 | border-radius: 2px; | ||
| 1320 | border: 1px solid #929192; | ||
| 1321 | background: #39ff14; | ||
| 1322 | image: none; | ||
| 1323 | } | ||
| 1324 | |||
| 1325 | QCheckBox#checkboxPlayer1Connected::indicator:unchecked, | ||
| 1326 | QCheckBox#checkboxPlayer2Connected::indicator:unchecked, | ||
| 1327 | QCheckBox#checkboxPlayer3Connected::indicator:unchecked, | ||
| 1328 | QCheckBox#checkboxPlayer4Connected::indicator:unchecked, | ||
| 1329 | QCheckBox#checkboxPlayer5Connected::indicator:unchecked, | ||
| 1330 | QCheckBox#checkboxPlayer6Connected::indicator:unchecked, | ||
| 1331 | QCheckBox#checkboxPlayer7Connected::indicator:unchecked, | ||
| 1332 | QCheckBox#checkboxPlayer8Connected::indicator:unchecked, | ||
| 1333 | QGroupBox#groupConnectedController::indicator:unchecked { | ||
| 1334 | border-radius: 2px; | ||
| 1335 | border: 1px solid #929192; | ||
| 1336 | background: transparent; | ||
| 1337 | image: none; | ||
| 1338 | } | ||
| 1339 | |||
| 1340 | QSpinBox#spinboxLStickRange, | ||
| 1341 | QSpinBox#spinboxRStickRange { | ||
| 1342 | padding: 4px 0px 5px 0px; | ||
| 1343 | min-width: 63px; | ||
| 1344 | } | ||
| 1345 | |||
| 1346 | QSpinBox#vibrationSpin { | ||
| 1347 | padding: 4px 0px 5px 0px; | ||
| 1348 | min-width: 63px; | ||
| 1349 | } | ||
| 1350 | |||
| 1351 | QSpinBox#spinboxLStickRange:up-button, | ||
| 1352 | QSpinBox#spinboxRStickRange:up-button, | ||
| 1353 | QSpinBox#vibrationSpin:up-button { | ||
| 1354 | left: -2px; | ||
| 1355 | } | ||
| 1356 | |||
| 1357 | QSpinBox#spinboxLStickRange:down-button, | ||
| 1358 | QSpinBox#spinboxRStickRange:down-button, | ||
| 1359 | QSpinBox#vibrationSpin:down-button { | ||
| 1360 | right: -1px; | ||
| 1361 | } | ||
| 1362 | |||
| 1363 | QGroupBox#motionGroup::indicator, | ||
| 1364 | QGroupBox#vibrationGroup::indicator { | ||
| 1365 | margin-left: 0px; | ||
| 1366 | } | ||
| 1367 | |||
| 1368 | QGroupBox#motionGroup::title, | ||
| 1369 | QGroupBox#vibrationGroup::title { | ||
| 1370 | spacing: 2px; | ||
| 1371 | padding-left: 1px; | ||
| 1372 | padding-right: 1px; | ||
| 1276 | } | 1373 | } |
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/icons/16x16/refresh.png b/dist/qt_themes/qdarkstyle_midnight_blue/icons/16x16/refresh.png new file mode 100644 index 000000000..d4afd76f9 --- /dev/null +++ b/dist/qt_themes/qdarkstyle_midnight_blue/icons/16x16/refresh.png | |||
| Binary files differ | |||
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/icons/16x16/view-refresh.png b/dist/qt_themes/qdarkstyle_midnight_blue/icons/16x16/view-refresh.png new file mode 100644 index 000000000..d4afd76f9 --- /dev/null +++ b/dist/qt_themes/qdarkstyle_midnight_blue/icons/16x16/view-refresh.png | |||
| Binary files differ | |||
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/style.qrc b/dist/qt_themes/qdarkstyle_midnight_blue/style.qrc index 1b7686f15..616aace73 100644 --- a/dist/qt_themes/qdarkstyle_midnight_blue/style.qrc +++ b/dist/qt_themes/qdarkstyle_midnight_blue/style.qrc | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | <qresource prefix="icons/qdarkstyle_midnight_blue"> | 2 | <qresource prefix="icons/qdarkstyle_midnight_blue"> |
| 3 | <file alias="index.theme">icons/index.theme</file> | 3 | <file alias="index.theme">icons/index.theme</file> |
| 4 | <file alias="16x16/lock.png">icons/16x16/lock.png</file> | 4 | <file alias="16x16/lock.png">icons/16x16/lock.png</file> |
| 5 | <file alias="16x16/view-refresh.png">icons/16x16/view-refresh.png</file> | ||
| 5 | <file alias="48x48/bad_folder.png">icons/48x48/bad_folder.png</file> | 6 | <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/chip.png">icons/48x48/chip.png</file> |
| 7 | <file alias="48x48/folder.png">icons/48x48/folder.png</file> | 8 | <file alias="48x48/folder.png">icons/48x48/folder.png</file> |
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/style.qss b/dist/qt_themes/qdarkstyle_midnight_blue/style.qss index 9c24b0d07..a714e1475 100644 --- a/dist/qt_themes/qdarkstyle_midnight_blue/style.qss +++ b/dist/qt_themes/qdarkstyle_midnight_blue/style.qss | |||
| @@ -138,8 +138,6 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qstatusbar | |||
| 138 | 138 | ||
| 139 | --------------------------------------------------------------------------- */ | 139 | --------------------------------------------------------------------------- */ |
| 140 | QStatusBar { | 140 | QStatusBar { |
| 141 | border: 1px solid #32414B; | ||
| 142 | /* Fixes Spyder #9120, #9121 */ | ||
| 143 | background: #32414B; | 141 | background: #32414B; |
| 144 | /* Fixes #205, white vertical borders separating items */ | 142 | /* Fixes #205, white vertical borders separating items */ |
| 145 | } | 143 | } |
| @@ -161,6 +159,7 @@ QStatusBar QToolTip { | |||
| 161 | QStatusBar QLabel { | 159 | QStatusBar QLabel { |
| 162 | /* Fixes Spyder #9120, #9121 */ | 160 | /* Fixes Spyder #9120, #9121 */ |
| 163 | background: transparent; | 161 | background: transparent; |
| 162 | padding: 0px; | ||
| 164 | } | 163 | } |
| 165 | 164 | ||
| 166 | /* QCheckBox -------------------------------------------------------------- | 165 | /* QCheckBox -------------------------------------------------------------- |
| @@ -236,21 +235,19 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qgroupbox | |||
| 236 | 235 | ||
| 237 | --------------------------------------------------------------------------- */ | 236 | --------------------------------------------------------------------------- */ |
| 238 | QGroupBox { | 237 | QGroupBox { |
| 239 | font-weight: bold; | 238 | font-weight: bold; |
| 240 | border: 1px solid #32414B; | 239 | border: 1px solid #32414B; |
| 241 | border-radius: 4px; | 240 | border-radius: 4px; |
| 242 | padding: 4px; | 241 | margin-top: 12px; |
| 243 | margin-top: 16px; | 242 | padding: 4px; |
| 244 | } | 243 | } |
| 245 | 244 | ||
| 246 | QGroupBox::title { | 245 | QGroupBox::title { |
| 247 | subcontrol-origin: margin; | 246 | subcontrol-origin: margin; |
| 248 | subcontrol-position: top left; | 247 | subcontrol-position: top left; |
| 249 | left: 3px; | 248 | padding-left: 3px; |
| 250 | padding-left: 3px; | 249 | padding-right: 5px; |
| 251 | padding-right: 5px; | 250 | padding-top: 4px; |
| 252 | padding-top: 8px; | ||
| 253 | padding-bottom: 16px; | ||
| 254 | } | 251 | } |
| 255 | 252 | ||
| 256 | QGroupBox::indicator { | 253 | QGroupBox::indicator { |
| @@ -367,28 +364,19 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qmenubar | |||
| 367 | --------------------------------------------------------------------------- */ | 364 | --------------------------------------------------------------------------- */ |
| 368 | QMenuBar { | 365 | QMenuBar { |
| 369 | background-color: #32414B; | 366 | background-color: #32414B; |
| 370 | padding: 2px; | ||
| 371 | border: 1px solid #19232D; | ||
| 372 | color: #F0F0F0; | 367 | color: #F0F0F0; |
| 373 | } | 368 | } |
| 374 | 369 | ||
| 375 | QMenuBar:focus { | ||
| 376 | border: 1px solid #148CD2; | ||
| 377 | } | ||
| 378 | |||
| 379 | QMenuBar::item { | 370 | QMenuBar::item { |
| 380 | background: transparent; | 371 | background: transparent; |
| 381 | padding: 4px; | ||
| 382 | } | 372 | } |
| 383 | 373 | ||
| 384 | QMenuBar::item:selected { | 374 | QMenuBar::item:selected { |
| 385 | padding: 4px; | ||
| 386 | background: transparent; | 375 | background: transparent; |
| 387 | border: 0px solid #32414B; | 376 | border: 0px solid #32414B; |
| 388 | } | 377 | } |
| 389 | 378 | ||
| 390 | QMenuBar::item:pressed { | 379 | QMenuBar::item:pressed { |
| 391 | padding: 4px; | ||
| 392 | border: 0px solid #32414B; | 380 | border: 0px solid #32414B; |
| 393 | background-color: #148CD2; | 381 | background-color: #148CD2; |
| 394 | color: #F0F0F0; | 382 | color: #F0F0F0; |
| @@ -396,6 +384,7 @@ QMenuBar::item:pressed { | |||
| 396 | padding-bottom: 0px; | 384 | padding-bottom: 0px; |
| 397 | } | 385 | } |
| 398 | 386 | ||
| 387 | |||
| 399 | /* QMenu ------------------------------------------------------------------ | 388 | /* QMenu ------------------------------------------------------------------ |
| 400 | 389 | ||
| 401 | https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qmenu | 390 | https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qmenu |
| @@ -482,7 +471,7 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qcombobox | |||
| 482 | 471 | ||
| 483 | --------------------------------------------------------------------------- */ | 472 | --------------------------------------------------------------------------- */ |
| 484 | QAbstractItemView { | 473 | QAbstractItemView { |
| 485 | alternate-background-color: #19232D; | 474 | alternate-background-color: #1f2933; |
| 486 | color: #F0F0F0; | 475 | color: #F0F0F0; |
| 487 | border: 1px solid #32414B; | 476 | border: 1px solid #32414B; |
| 488 | border-radius: 4px; | 477 | border-radius: 4px; |
| @@ -501,13 +490,13 @@ QAbstractScrollArea { | |||
| 501 | background-color: #19232D; | 490 | background-color: #19232D; |
| 502 | border: 1px solid #32414B; | 491 | border: 1px solid #32414B; |
| 503 | border-radius: 4px; | 492 | border-radius: 4px; |
| 504 | padding: 2px; | ||
| 505 | /* fix #159 */ | 493 | /* fix #159 */ |
| 506 | min-height: 1.25em; | 494 | min-height: 1.25em; |
| 507 | /* fix #159 */ | 495 | /* fix #159 */ |
| 508 | color: #F0F0F0; | 496 | color: #F0F0F0; |
| 509 | } | 497 | } |
| 510 | 498 | ||
| 499 | |||
| 511 | QAbstractScrollArea:disabled { | 500 | QAbstractScrollArea:disabled { |
| 512 | color: #787878; | 501 | color: #787878; |
| 513 | } | 502 | } |
| @@ -807,20 +796,22 @@ QAbstractSpinBox { | |||
| 807 | } | 796 | } |
| 808 | 797 | ||
| 809 | QAbstractSpinBox:up-button { | 798 | QAbstractSpinBox:up-button { |
| 810 | background-color: transparent #19232D; | 799 | background-color: #505F69; |
| 811 | subcontrol-origin: border; | 800 | subcontrol-origin: border; |
| 812 | subcontrol-position: top right; | 801 | subcontrol-position: top right; |
| 813 | border-left: 1px solid #32414B; | 802 | border-left: 1px solid #32414B; |
| 814 | border-bottom: 1px solid #32414B; | 803 | border-top: 1px solid #32414B; |
| 804 | border-right: 1px solid #32414B; | ||
| 805 | border-top-right-radius: 4px; | ||
| 815 | border-top-left-radius: 0; | 806 | border-top-left-radius: 0; |
| 816 | border-bottom-left-radius: 0; | 807 | border-bottom-left-radius: 0; |
| 817 | margin: 1px; | 808 | margin: 0px; |
| 818 | width: 12px; | 809 | width: 12px; |
| 819 | margin-bottom: -1px; | 810 | margin-bottom: 0px; |
| 820 | } | 811 | } |
| 821 | 812 | ||
| 822 | QAbstractSpinBox::up-arrow, QAbstractSpinBox::up-arrow:disabled, QAbstractSpinBox::up-arrow:off { | 813 | QAbstractSpinBox::up-arrow, QAbstractSpinBox::up-arrow:disabled, QAbstractSpinBox::up-arrow:off { |
| 823 | image: url(":/qss_icons/rc/arrow_up_disabled.png"); | 814 | image: url(":/qss_icons/rc/up_arrow.png"); |
| 824 | height: 8px; | 815 | height: 8px; |
| 825 | width: 8px; | 816 | width: 8px; |
| 826 | } | 817 | } |
| @@ -830,20 +821,23 @@ QAbstractSpinBox::up-arrow:hover { | |||
| 830 | } | 821 | } |
| 831 | 822 | ||
| 832 | QAbstractSpinBox:down-button { | 823 | QAbstractSpinBox:down-button { |
| 833 | background-color: transparent #19232D; | 824 | background-color: #505F69; |
| 834 | subcontrol-origin: border; | 825 | subcontrol-origin: border; |
| 835 | subcontrol-position: bottom right; | 826 | subcontrol-position: bottom right; |
| 836 | border-left: 1px solid #32414B; | 827 | border-left: 1px solid #32414B; |
| 828 | border-right: 1px solid #32414B; | ||
| 829 | border-bottom: 1px solid #32414B; | ||
| 837 | border-top: 1px solid #32414B; | 830 | border-top: 1px solid #32414B; |
| 838 | border-top-left-radius: 0; | 831 | border-top-left-radius: 0; |
| 839 | border-bottom-left-radius: 0; | 832 | border-bottom-left-radius: 0; |
| 840 | margin: 1px; | 833 | border-bottom-right-radius: 4px; |
| 834 | margin: 0px; | ||
| 841 | width: 12px; | 835 | width: 12px; |
| 842 | margin-top: -1px; | 836 | margin-top: 0px; |
| 843 | } | 837 | } |
| 844 | 838 | ||
| 845 | QAbstractSpinBox::down-arrow, QAbstractSpinBox::down-arrow:disabled, QAbstractSpinBox::down-arrow:off { | 839 | QAbstractSpinBox::down-arrow, QAbstractSpinBox::down-arrow:disabled, QAbstractSpinBox::down-arrow:off { |
| 846 | image: url(":/qss_icons/rc/arrow_down_disabled.png"); | 840 | image: url(":/qss_icons/rc/down_arrow.png"); |
| 847 | height: 8px; | 841 | height: 8px; |
| 848 | width: 8px; | 842 | width: 8px; |
| 849 | } | 843 | } |
| @@ -1199,6 +1193,7 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qcombobox | |||
| 1199 | 1193 | ||
| 1200 | --------------------------------------------------------------------------- */ | 1194 | --------------------------------------------------------------------------- */ |
| 1201 | QComboBox { | 1195 | QComboBox { |
| 1196 | background-color: #0f1922; | ||
| 1202 | border: 1px solid #32414B; | 1197 | border: 1px solid #32414B; |
| 1203 | border-radius: 4px; | 1198 | border-radius: 4px; |
| 1204 | selection-background-color: #1464A0; | 1199 | selection-background-color: #1464A0; |
| @@ -1216,7 +1211,7 @@ QComboBox { | |||
| 1216 | QComboBox QAbstractItemView { | 1211 | QComboBox QAbstractItemView { |
| 1217 | border: 1px solid #32414B; | 1212 | border: 1px solid #32414B; |
| 1218 | border-radius: 0; | 1213 | border-radius: 0; |
| 1219 | background-color: #19232D; | 1214 | background-color: #0f1922; |
| 1220 | selection-background-color: #1464A0; | 1215 | selection-background-color: #1464A0; |
| 1221 | } | 1216 | } |
| 1222 | 1217 | ||
| @@ -1285,7 +1280,12 @@ QComboBox::drop-down { | |||
| 1285 | } | 1280 | } |
| 1286 | 1281 | ||
| 1287 | QComboBox::down-arrow { | 1282 | QComboBox::down-arrow { |
| 1288 | image: url(":/qss_icons/rc/arrow_down_disabled.png"); | 1283 | image: url(":/qss_icons/rc/down_arrow.png"); |
| 1284 | background-color: #505F69; | ||
| 1285 | padding: 6px 2px; | ||
| 1286 | border: 1px solid #32414B; | ||
| 1287 | border-top-right-radius: 4px; | ||
| 1288 | border-bottom-right-radius: 4px; | ||
| 1289 | height: 8px; | 1289 | height: 8px; |
| 1290 | width: 8px; | 1290 | width: 8px; |
| 1291 | } | 1291 | } |
| @@ -1559,12 +1559,12 @@ QTabBar::tab:right:!selected { | |||
| 1559 | QTabBar::tab:top { | 1559 | QTabBar::tab:top { |
| 1560 | background-color: #32414B; | 1560 | background-color: #32414B; |
| 1561 | color: #F0F0F0; | 1561 | color: #F0F0F0; |
| 1562 | min-width: 36px; | ||
| 1562 | margin-left: 2px; | 1563 | margin-left: 2px; |
| 1563 | padding-left: 4px; | 1564 | padding-left: 8px; |
| 1564 | padding-right: 4px; | 1565 | padding-right: 8px; |
| 1565 | padding-top: 2px; | 1566 | padding-top: 2px; |
| 1566 | padding-bottom: 2px; | 1567 | padding-bottom: 2px; |
| 1567 | min-width: 5px; | ||
| 1568 | border-bottom: 3px solid #32414B; | 1568 | border-bottom: 3px solid #32414B; |
| 1569 | border-top-left-radius: 3px; | 1569 | border-top-left-radius: 3px; |
| 1570 | border-top-right-radius: 3px; | 1570 | border-top-right-radius: 3px; |
| @@ -1588,16 +1588,16 @@ QTabBar::tab:top:!selected:hover { | |||
| 1588 | 1588 | ||
| 1589 | QTabBar::tab:bottom { | 1589 | QTabBar::tab:bottom { |
| 1590 | color: #F0F0F0; | 1590 | color: #F0F0F0; |
| 1591 | min-width: 36px; | ||
| 1591 | border-top: 3px solid #32414B; | 1592 | border-top: 3px solid #32414B; |
| 1592 | background-color: #32414B; | 1593 | background-color: #32414B; |
| 1593 | margin-left: 2px; | 1594 | margin-left: 2px; |
| 1594 | padding-left: 4px; | 1595 | padding-left: 8px; |
| 1595 | padding-right: 4px; | 1596 | padding-right: 8px; |
| 1596 | padding-top: 2px; | 1597 | padding-top: 2px; |
| 1597 | padding-bottom: 2px; | 1598 | padding-bottom: 2px; |
| 1598 | border-bottom-left-radius: 3px; | 1599 | border-bottom-left-radius: 3px; |
| 1599 | border-bottom-right-radius: 3px; | 1600 | border-bottom-right-radius: 3px; |
| 1600 | min-width: 5px; | ||
| 1601 | } | 1601 | } |
| 1602 | 1602 | ||
| 1603 | QTabBar::tab:bottom:selected { | 1603 | QTabBar::tab:bottom:selected { |
| @@ -1752,21 +1752,6 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qlistview | |||
| 1752 | https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtableview | 1752 | https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtableview |
| 1753 | 1753 | ||
| 1754 | --------------------------------------------------------------------------- */ | 1754 | --------------------------------------------------------------------------- */ |
| 1755 | QTreeView:branch:selected, QTreeView:branch:hover { | ||
| 1756 | background: url(":/qss_icons/rc/transparent.png"); | ||
| 1757 | } | ||
| 1758 | |||
| 1759 | QTreeView:branch:has-siblings:!adjoins-item { | ||
| 1760 | border-image: url(":/qss_icons/rc/branch_line.png") 0; | ||
| 1761 | } | ||
| 1762 | |||
| 1763 | QTreeView:branch:has-siblings:adjoins-item { | ||
| 1764 | border-image: url(":/qss_icons/rc/branch_more.png") 0; | ||
| 1765 | } | ||
| 1766 | |||
| 1767 | QTreeView:branch:!has-children:!has-siblings:adjoins-item { | ||
| 1768 | border-image: url(":/qss_icons/rc/branch_end.png") 0; | ||
| 1769 | } | ||
| 1770 | 1755 | ||
| 1771 | QTreeView:branch:has-children:!has-siblings:closed, QTreeView:branch:closed:has-children:has-siblings { | 1756 | QTreeView:branch:has-children:!has-siblings:closed, QTreeView:branch:closed:has-children:has-siblings { |
| 1772 | border-image: none; | 1757 | border-image: none; |
| @@ -1900,21 +1885,21 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qheaderview | |||
| 1900 | 1885 | ||
| 1901 | --------------------------------------------------------------------------- */ | 1886 | --------------------------------------------------------------------------- */ |
| 1902 | QHeaderView { | 1887 | QHeaderView { |
| 1903 | background-color: #32414B; | 1888 | background-color: #19232D; |
| 1904 | border: 0px transparent #32414B; | 1889 | border: 0px transparent #19232D; |
| 1905 | padding: 0px; | 1890 | padding: 0px; |
| 1906 | margin: 0px; | 1891 | margin: 0px; |
| 1907 | border-radius: 0px; | 1892 | border-radius: 0px; |
| 1908 | } | 1893 | } |
| 1909 | 1894 | ||
| 1910 | QHeaderView:disabled { | 1895 | QHeaderView:disabled { |
| 1911 | background-color: #32414B; | 1896 | background-color: #19232D; |
| 1912 | border: 1px transparent #32414B; | 1897 | border: 1px transparent #19232D; |
| 1913 | padding: 2px; | 1898 | padding: 2px; |
| 1914 | } | 1899 | } |
| 1915 | 1900 | ||
| 1916 | QHeaderView::section { | 1901 | QHeaderView::section { |
| 1917 | background-color: #32414B; | 1902 | background-color: #19232D; |
| 1918 | color: #F0F0F0; | 1903 | color: #F0F0F0; |
| 1919 | padding: 2px; | 1904 | padding: 2px; |
| 1920 | border-radius: 0px; | 1905 | border-radius: 0px; |
| @@ -1934,11 +1919,11 @@ QHeaderView::section:checked:disabled { | |||
| 1934 | QHeaderView::section::horizontal { | 1919 | QHeaderView::section::horizontal { |
| 1935 | padding-left: 4px; | 1920 | padding-left: 4px; |
| 1936 | padding-right: 4px; | 1921 | padding-right: 4px; |
| 1937 | border-left: 1px solid #19232D; | 1922 | border-left: 1px solid #32414B; |
| 1938 | } | 1923 | } |
| 1939 | 1924 | ||
| 1940 | QHeaderView::section::horizontal::first, QHeaderView::section::horizontal::only-one { | 1925 | QHeaderView::section::horizontal::first, QHeaderView::section::horizontal::only-one { |
| 1941 | border-left: 1px solid #32414B; | 1926 | border-left: 1px solid #19232D; |
| 1942 | } | 1927 | } |
| 1943 | 1928 | ||
| 1944 | QHeaderView::section::horizontal:disabled { | 1929 | QHeaderView::section::horizontal:disabled { |
| @@ -1948,7 +1933,7 @@ QHeaderView::section::horizontal:disabled { | |||
| 1948 | QHeaderView::section::vertical { | 1933 | QHeaderView::section::vertical { |
| 1949 | padding-left: 4px; | 1934 | padding-left: 4px; |
| 1950 | padding-right: 4px; | 1935 | padding-right: 4px; |
| 1951 | border-top: 1px solid #19232D; | 1936 | border-top: 1px solid #32414B; |
| 1952 | } | 1937 | } |
| 1953 | 1938 | ||
| 1954 | QHeaderView::section::vertical::first, QHeaderView::section::vertical::only-one { | 1939 | QHeaderView::section::vertical::first, QHeaderView::section::vertical::only-one { |
| @@ -1962,7 +1947,7 @@ QHeaderView::section::vertical:disabled { | |||
| 1962 | QHeaderView::down-arrow { | 1947 | QHeaderView::down-arrow { |
| 1963 | /* Those settings (border/width/height/background-color) solve bug */ | 1948 | /* Those settings (border/width/height/background-color) solve bug */ |
| 1964 | /* transparent arrow background and size */ | 1949 | /* transparent arrow background and size */ |
| 1965 | background-color: #32414B; | 1950 | background-color: #19232D; |
| 1966 | border: none; | 1951 | border: none; |
| 1967 | height: 12px; | 1952 | height: 12px; |
| 1968 | width: 12px; | 1953 | width: 12px; |
| @@ -1972,7 +1957,7 @@ QHeaderView::down-arrow { | |||
| 1972 | } | 1957 | } |
| 1973 | 1958 | ||
| 1974 | QHeaderView::up-arrow { | 1959 | QHeaderView::up-arrow { |
| 1975 | background-color: #32414B; | 1960 | background-color: #19232D; |
| 1976 | border: none; | 1961 | border: none; |
| 1977 | height: 12px; | 1962 | height: 12px; |
| 1978 | width: 12px; | 1963 | width: 12px; |
| @@ -2172,3 +2157,132 @@ PlotWidget { | |||
| 2172 | /* Fix cut labels in plots #134 */ | 2157 | /* Fix cut labels in plots #134 */ |
| 2173 | padding: 0px; | 2158 | padding: 0px; |
| 2174 | } | 2159 | } |
| 2160 | |||
| 2161 | |||
| 2162 | QPushButton#TogglableStatusBarButton { | ||
| 2163 | min-width: 0px; | ||
| 2164 | color: #656565; | ||
| 2165 | border: 1px solid transparent; | ||
| 2166 | background-color: transparent; | ||
| 2167 | padding: 0px 3px 0px 3px; | ||
| 2168 | text-align: center; | ||
| 2169 | } | ||
| 2170 | |||
| 2171 | QPushButton#TogglableStatusBarButton:checked { | ||
| 2172 | color: #ffffff; | ||
| 2173 | } | ||
| 2174 | |||
| 2175 | QPushButton#TogglableStatusBarButton:hover { | ||
| 2176 | border: 1px solid #76797C; | ||
| 2177 | } | ||
| 2178 | |||
| 2179 | QPushButton#RendererStatusBarButton { | ||
| 2180 | min-width: 0px; | ||
| 2181 | color: #656565; | ||
| 2182 | border: 1px solid transparent; | ||
| 2183 | background-color: transparent; | ||
| 2184 | padding: 0px 3px 0px 3px; | ||
| 2185 | text-align: center; | ||
| 2186 | } | ||
| 2187 | |||
| 2188 | QPushButton#RendererStatusBarButton:hover { | ||
| 2189 | border: 1px solid #76797C; | ||
| 2190 | } | ||
| 2191 | |||
| 2192 | QPushButton#RendererStatusBarButton:checked { | ||
| 2193 | color: #e85c00; | ||
| 2194 | } | ||
| 2195 | |||
| 2196 | QPushButton#RendererStatusBarButton:!checked { | ||
| 2197 | color: #00ccdd; | ||
| 2198 | } | ||
| 2199 | |||
| 2200 | QPushButton#buttonRefreshDevices { | ||
| 2201 | min-width: 20px; | ||
| 2202 | min-height: 20px; | ||
| 2203 | max-width: 20px; | ||
| 2204 | max-height: 20px; | ||
| 2205 | padding: 0px 0px; | ||
| 2206 | } | ||
| 2207 | |||
| 2208 | |||
| 2209 | QCheckBox#checkboxPlayer1Connected, | ||
| 2210 | QCheckBox#checkboxPlayer2Connected, | ||
| 2211 | QCheckBox#checkboxPlayer3Connected, | ||
| 2212 | QCheckBox#checkboxPlayer4Connected, | ||
| 2213 | QCheckBox#checkboxPlayer5Connected, | ||
| 2214 | QCheckBox#checkboxPlayer6Connected, | ||
| 2215 | QCheckBox#checkboxPlayer7Connected, | ||
| 2216 | QCheckBox#checkboxPlayer8Connected { | ||
| 2217 | spacing: 0px; | ||
| 2218 | } | ||
| 2219 | |||
| 2220 | QCheckBox#checkboxPlayer1Connected::indicator, | ||
| 2221 | QCheckBox#checkboxPlayer2Connected::indicator, | ||
| 2222 | QCheckBox#checkboxPlayer3Connected::indicator, | ||
| 2223 | QCheckBox#checkboxPlayer4Connected::indicator, | ||
| 2224 | QCheckBox#checkboxPlayer5Connected::indicator, | ||
| 2225 | QCheckBox#checkboxPlayer6Connected::indicator, | ||
| 2226 | QCheckBox#checkboxPlayer7Connected::indicator, | ||
| 2227 | QCheckBox#checkboxPlayer8Connected::indicator { | ||
| 2228 | width: 14px; | ||
| 2229 | height: 14px; | ||
| 2230 | } | ||
| 2231 | |||
| 2232 | QCheckBox#checkboxPlayer1Connected::indicator:checked, | ||
| 2233 | QCheckBox#checkboxPlayer2Connected::indicator:checked, | ||
| 2234 | QCheckBox#checkboxPlayer3Connected::indicator:checked, | ||
| 2235 | QCheckBox#checkboxPlayer4Connected::indicator:checked, | ||
| 2236 | QCheckBox#checkboxPlayer5Connected::indicator:checked, | ||
| 2237 | QCheckBox#checkboxPlayer6Connected::indicator:checked, | ||
| 2238 | QCheckBox#checkboxPlayer7Connected::indicator:checked, | ||
| 2239 | QCheckBox#checkboxPlayer8Connected::indicator:checked, | ||
| 2240 | QGroupBox#groupConnectedController::indicator:checked { | ||
| 2241 | border-radius: 2px; | ||
| 2242 | border: 1px solid #929192; | ||
| 2243 | background: #39ff14; | ||
| 2244 | image: none; | ||
| 2245 | } | ||
| 2246 | |||
| 2247 | QCheckBox#checkboxPlayer1Connected::indicator:unchecked, | ||
| 2248 | QCheckBox#checkboxPlayer2Connected::indicator:unchecked, | ||
| 2249 | QCheckBox#checkboxPlayer3Connected::indicator:unchecked, | ||
| 2250 | QCheckBox#checkboxPlayer4Connected::indicator:unchecked, | ||
| 2251 | QCheckBox#checkboxPlayer5Connected::indicator:unchecked, | ||
| 2252 | QCheckBox#checkboxPlayer6Connected::indicator:unchecked, | ||
| 2253 | QCheckBox#checkboxPlayer7Connected::indicator:unchecked, | ||
| 2254 | QCheckBox#checkboxPlayer8Connected::indicator:unchecked, | ||
| 2255 | QGroupBox#groupConnectedController::indicator:unchecked { | ||
| 2256 | border-radius: 2px; | ||
| 2257 | border: 1px solid #929192; | ||
| 2258 | background: transparent; | ||
| 2259 | image: none; | ||
| 2260 | } | ||
| 2261 | |||
| 2262 | QSpinBox#spinboxLStickRange, | ||
| 2263 | QSpinBox#spinboxRStickRange { | ||
| 2264 | min-width: 38px; | ||
| 2265 | } | ||
| 2266 | |||
| 2267 | QGroupBox#motionGroup::indicator, | ||
| 2268 | QGroupBox#vibrationGroup::indicator { | ||
| 2269 | margin-left: 0px; | ||
| 2270 | } | ||
| 2271 | |||
| 2272 | QGroupBox#motionGroup::title, | ||
| 2273 | QGroupBox#vibrationGroup::title { | ||
| 2274 | spacing: 2px; | ||
| 2275 | padding-left: 1px; | ||
| 2276 | padding-right: 1px; | ||
| 2277 | } | ||
| 2278 | |||
| 2279 | QListWidget#selectorList { | ||
| 2280 | background-color: #0f1922; | ||
| 2281 | } | ||
| 2282 | |||
| 2283 | QSpinBox, | ||
| 2284 | QLineEdit, | ||
| 2285 | QTreeView#hotkey_list, | ||
| 2286 | QScrollArea#scrollArea QTreeView { | ||
| 2287 | background-color: #0f1922; | ||
| 2288 | } \ No newline at end of file | ||
diff --git a/externals/dynarmic b/externals/dynarmic | |||
| Subproject 82417da7803e2cf18efc28a1cd3f3d0a4b6045a | Subproject 0e1112b7df77ae55a62a51622940d5c8f9e8c84 | ||
diff --git a/externals/microprofile/microprofile.h b/externals/microprofile/microprofile.h index 0c0d0a4d3..6dae65a66 100644 --- a/externals/microprofile/microprofile.h +++ b/externals/microprofile/microprofile.h | |||
| @@ -152,9 +152,11 @@ typedef uint16_t MicroProfileGroupId; | |||
| 152 | 152 | ||
| 153 | #include <stdint.h> | 153 | #include <stdint.h> |
| 154 | #include <string.h> | 154 | #include <string.h> |
| 155 | #include <thread> | 155 | #include <algorithm> |
| 156 | #include <mutex> | 156 | #include <array> |
| 157 | #include <atomic> | 157 | #include <atomic> |
| 158 | #include <mutex> | ||
| 159 | #include <thread> | ||
| 158 | 160 | ||
| 159 | #ifndef MICROPROFILE_API | 161 | #ifndef MICROPROFILE_API |
| 160 | #define MICROPROFILE_API | 162 | #define MICROPROFILE_API |
| @@ -605,28 +607,45 @@ struct MicroProfileFrameState | |||
| 605 | 607 | ||
| 606 | struct MicroProfileThreadLog | 608 | struct MicroProfileThreadLog |
| 607 | { | 609 | { |
| 608 | MicroProfileLogEntry Log[MICROPROFILE_BUFFER_SIZE]; | 610 | std::array<MicroProfileLogEntry, MICROPROFILE_BUFFER_SIZE> Log{}; |
| 609 | 611 | ||
| 610 | std::atomic<uint32_t> nPut; | 612 | std::atomic<uint32_t> nPut{0}; |
| 611 | std::atomic<uint32_t> nGet; | 613 | std::atomic<uint32_t> nGet{0}; |
| 612 | uint32_t nActive; | 614 | uint32_t nActive = 0; |
| 613 | uint32_t nGpu; | 615 | uint32_t nGpu = 0; |
| 614 | ThreadIdType nThreadId; | 616 | ThreadIdType nThreadId{}; |
| 615 | 617 | ||
| 616 | uint32_t nStack[MICROPROFILE_STACK_MAX]; | 618 | std::array<uint32_t, MICROPROFILE_STACK_MAX> nStack{}; |
| 617 | int64_t nChildTickStack[MICROPROFILE_STACK_MAX]; | 619 | std::array<int64_t, MICROPROFILE_STACK_MAX> nChildTickStack{}; |
| 618 | uint32_t nStackPos; | 620 | uint32_t nStackPos = 0; |
| 619 | 621 | ||
| 620 | 622 | ||
| 621 | uint8_t nGroupStackPos[MICROPROFILE_MAX_GROUPS]; | 623 | std::array<uint8_t, MICROPROFILE_MAX_GROUPS> nGroupStackPos{}; |
| 622 | int64_t nGroupTicks[MICROPROFILE_MAX_GROUPS]; | 624 | std::array<int64_t, MICROPROFILE_MAX_GROUPS> nGroupTicks{}; |
| 623 | int64_t nAggregateGroupTicks[MICROPROFILE_MAX_GROUPS]; | 625 | std::array<int64_t, MICROPROFILE_MAX_GROUPS> nAggregateGroupTicks{}; |
| 624 | enum | 626 | enum |
| 625 | { | 627 | { |
| 626 | THREAD_MAX_LEN = 64, | 628 | THREAD_MAX_LEN = 64, |
| 627 | }; | 629 | }; |
| 628 | char ThreadName[64]; | 630 | char ThreadName[64]{}; |
| 629 | int nFreeListNext; | 631 | int nFreeListNext = 0; |
| 632 | |||
| 633 | void Reset() { | ||
| 634 | Log.fill({}); | ||
| 635 | nPut = 0; | ||
| 636 | nGet = 0; | ||
| 637 | nActive = 0; | ||
| 638 | nGpu = 0; | ||
| 639 | nThreadId = {}; | ||
| 640 | nStack.fill(0); | ||
| 641 | nChildTickStack.fill(0); | ||
| 642 | nStackPos = 0; | ||
| 643 | nGroupStackPos.fill(0); | ||
| 644 | nGroupTicks.fill(0); | ||
| 645 | nAggregateGroupTicks.fill(0); | ||
| 646 | std::fill(std::begin(ThreadName), std::end(ThreadName), '\0'); | ||
| 647 | nFreeListNext = 0; | ||
| 648 | } | ||
| 630 | }; | 649 | }; |
| 631 | 650 | ||
| 632 | #if MICROPROFILE_GPU_TIMERS_D3D11 | 651 | #if MICROPROFILE_GPU_TIMERS_D3D11 |
| @@ -1151,6 +1170,7 @@ MicroProfileThreadLog* MicroProfileCreateThreadLog(const char* pName) | |||
| 1151 | MP_ASSERT(pLog->nPut.load() == 0); | 1170 | MP_ASSERT(pLog->nPut.load() == 0); |
| 1152 | MP_ASSERT(pLog->nGet.load() == 0); | 1171 | MP_ASSERT(pLog->nGet.load() == 0); |
| 1153 | S.nFreeListHead = S.Pool[S.nFreeListHead]->nFreeListNext; | 1172 | S.nFreeListHead = S.Pool[S.nFreeListHead]->nFreeListNext; |
| 1173 | pLog->Reset(); | ||
| 1154 | } | 1174 | } |
| 1155 | else | 1175 | else |
| 1156 | { | 1176 | { |
| @@ -1158,7 +1178,6 @@ MicroProfileThreadLog* MicroProfileCreateThreadLog(const char* pName) | |||
| 1158 | S.nMemUsage += sizeof(MicroProfileThreadLog); | 1178 | S.nMemUsage += sizeof(MicroProfileThreadLog); |
| 1159 | S.Pool[S.nNumLogs++] = pLog; | 1179 | S.Pool[S.nNumLogs++] = pLog; |
| 1160 | } | 1180 | } |
| 1161 | memset(pLog, 0, sizeof(*pLog)); | ||
| 1162 | int len = (int)strlen(pName); | 1181 | int len = (int)strlen(pName); |
| 1163 | int maxlen = sizeof(pLog->ThreadName)-1; | 1182 | int maxlen = sizeof(pLog->ThreadName)-1; |
| 1164 | len = len < maxlen ? len : maxlen; | 1183 | len = len < maxlen ? len : maxlen; |
| @@ -1206,8 +1225,8 @@ void MicroProfileOnThreadExit() | |||
| 1206 | { | 1225 | { |
| 1207 | S.Frames[i].nLogStart[nLogIndex] = 0; | 1226 | S.Frames[i].nLogStart[nLogIndex] = 0; |
| 1208 | } | 1227 | } |
| 1209 | memset(pLog->nGroupStackPos, 0, sizeof(pLog->nGroupStackPos)); | 1228 | pLog->nGroupStackPos.fill(0); |
| 1210 | memset(pLog->nGroupTicks, 0, sizeof(pLog->nGroupTicks)); | 1229 | pLog->nGroupTicks.fill(0); |
| 1211 | } | 1230 | } |
| 1212 | } | 1231 | } |
| 1213 | 1232 | ||
diff --git a/externals/microprofile/microprofileui.h b/externals/microprofile/microprofileui.h index fe2410cf4..85fbf2cb9 100644 --- a/externals/microprofile/microprofileui.h +++ b/externals/microprofile/microprofileui.h | |||
| @@ -169,14 +169,13 @@ MICROPROFILEUI_API void MicroProfileCustomGroup(const char* pCustomName, uint32_ | |||
| 169 | MICROPROFILEUI_API void MicroProfileCustomGroupAddTimer(const char* pCustomName, const char* pGroup, const char* pTimer); | 169 | MICROPROFILEUI_API void MicroProfileCustomGroupAddTimer(const char* pCustomName, const char* pGroup, const char* pTimer); |
| 170 | 170 | ||
| 171 | #ifdef MICROPROFILEUI_IMPL | 171 | #ifdef MICROPROFILEUI_IMPL |
| 172 | #ifdef _WIN32 | 172 | #include <inttypes.h> |
| 173 | #define snprintf _snprintf | ||
| 174 | #endif | ||
| 175 | #include <stdio.h> | 173 | #include <stdio.h> |
| 176 | #include <stdlib.h> | 174 | #include <stdlib.h> |
| 177 | #include <stdarg.h> | 175 | #include <stdarg.h> |
| 178 | #include <math.h> | 176 | #include <math.h> |
| 179 | #include <algorithm> | 177 | #include <algorithm> |
| 178 | #include <array> | ||
| 180 | 179 | ||
| 181 | MICROPROFILE_DEFINE(g_MicroProfileDetailed, "MicroProfile", "Detailed View", 0x8888000); | 180 | MICROPROFILE_DEFINE(g_MicroProfileDetailed, "MicroProfile", "Detailed View", 0x8888000); |
| 182 | MICROPROFILE_DEFINE(g_MicroProfileDrawGraph, "MicroProfile", "Draw Graph", 0xff44ee00); | 181 | MICROPROFILE_DEFINE(g_MicroProfileDrawGraph, "MicroProfile", "Draw Graph", 0xff44ee00); |
| @@ -227,10 +226,10 @@ struct SOptionDesc | |||
| 227 | uint8_t nIndex; | 226 | uint8_t nIndex; |
| 228 | bool bSelected; | 227 | bool bSelected; |
| 229 | }; | 228 | }; |
| 230 | static uint32_t g_MicroProfileAggregatePresets[] = {0, 10, 20, 30, 60, 120}; | 229 | static const std::array<uint32_t, 6> g_MicroProfileAggregatePresets{0, 10, 20, 30, 60, 120}; |
| 231 | static float g_MicroProfileReferenceTimePresets[] = {5.f, 10.f, 15.f,20.f, 33.33f, 66.66f, 100.f, 250.f, 500.f, 1000.f}; | 230 | static const std::array<float, 10> g_MicroProfileReferenceTimePresets{5.f, 10.f, 15.f,20.f, 33.33f, 66.66f, 100.f, 250.f, 500.f, 1000.f}; |
| 232 | static uint32_t g_MicroProfileOpacityPresets[] = {0x40, 0x80, 0xc0, 0xff}; | 231 | static const std::array<uint32_t, 4> g_MicroProfileOpacityPresets{0x40, 0x80, 0xc0, 0xff}; |
| 233 | static const char* g_MicroProfilePresetNames[] = | 232 | static const std::array<const char*, 7> g_MicroProfilePresetNames |
| 234 | { | 233 | { |
| 235 | MICROPROFILE_DEFAULT_PRESET, | 234 | MICROPROFILE_DEFAULT_PRESET, |
| 236 | "Render", | 235 | "Render", |
| @@ -243,8 +242,8 @@ static const char* g_MicroProfilePresetNames[] = | |||
| 243 | 242 | ||
| 244 | enum | 243 | enum |
| 245 | { | 244 | { |
| 246 | MICROPROFILE_NUM_REFERENCE_PRESETS = sizeof(g_MicroProfileReferenceTimePresets)/sizeof(g_MicroProfileReferenceTimePresets[0]), | 245 | MICROPROFILE_NUM_REFERENCE_PRESETS = g_MicroProfileReferenceTimePresets.size(), |
| 247 | MICROPROFILE_NUM_OPACITY_PRESETS = sizeof(g_MicroProfileOpacityPresets)/sizeof(g_MicroProfileOpacityPresets[0]), | 246 | MICROPROFILE_NUM_OPACITY_PRESETS = g_MicroProfileOpacityPresets.size(), |
| 248 | #if MICROPROFILE_CONTEXT_SWITCH_TRACE | 247 | #if MICROPROFILE_CONTEXT_SWITCH_TRACE |
| 249 | MICROPROFILE_OPTION_SIZE = MICROPROFILE_NUM_REFERENCE_PRESETS + MICROPROFILE_NUM_OPACITY_PRESETS * 2 + 2 + 7, | 248 | MICROPROFILE_OPTION_SIZE = MICROPROFILE_NUM_REFERENCE_PRESETS + MICROPROFILE_NUM_OPACITY_PRESETS * 2 + 2 + 7, |
| 250 | #else | 249 | #else |
| @@ -326,9 +325,9 @@ struct MicroProfileUI | |||
| 326 | 325 | ||
| 327 | MicroProfileUI g_MicroProfileUI; | 326 | MicroProfileUI g_MicroProfileUI; |
| 328 | #define UI g_MicroProfileUI | 327 | #define UI g_MicroProfileUI |
| 329 | static uint32_t g_nMicroProfileBackColors[2] = { 0x474747, 0x313131 }; | 328 | static const std::array<uint32_t, 2> g_nMicroProfileBackColors{ 0x474747, 0x313131 }; |
| 330 | #define MICROPROFILE_NUM_CONTEXT_SWITCH_COLORS 16 | 329 | #define MICROPROFILE_NUM_CONTEXT_SWITCH_COLORS 16 |
| 331 | static uint32_t g_nMicroProfileContextSwitchThreadColors[MICROPROFILE_NUM_CONTEXT_SWITCH_COLORS] = //palette generated by http://tools.medialab.sciences-po.fr/iwanthue/index.php | 330 | static const std::array<uint32_t, MICROPROFILE_NUM_CONTEXT_SWITCH_COLORS> g_nMicroProfileContextSwitchThreadColors //palette generated by http://tools.medialab.sciences-po.fr/iwanthue/index.php |
| 332 | { | 331 | { |
| 333 | 0x63607B, | 332 | 0x63607B, |
| 334 | 0x755E2B, | 333 | 0x755E2B, |
| @@ -356,7 +355,7 @@ void MicroProfileInitUI() | |||
| 356 | { | 355 | { |
| 357 | bInitialized = true; | 356 | bInitialized = true; |
| 358 | memset(&g_MicroProfileUI, 0, sizeof(g_MicroProfileUI)); | 357 | memset(&g_MicroProfileUI, 0, sizeof(g_MicroProfileUI)); |
| 359 | UI.nActiveMenu = (uint32_t)-1; | 358 | UI.nActiveMenu = UINT32_MAX; |
| 360 | UI.fDetailedOffsetTarget = UI.fDetailedOffset = 0.f; | 359 | UI.fDetailedOffsetTarget = UI.fDetailedOffset = 0.f; |
| 361 | UI.fDetailedRangeTarget = UI.fDetailedRange = 50.f; | 360 | UI.fDetailedRangeTarget = UI.fDetailedRange = 50.f; |
| 362 | 361 | ||
| @@ -368,7 +367,7 @@ void MicroProfileInitUI() | |||
| 368 | UI.nWidth = 100; | 367 | UI.nWidth = 100; |
| 369 | UI.nHeight = 100; | 368 | UI.nHeight = 100; |
| 370 | 369 | ||
| 371 | UI.nCustomActive = (uint32_t)-1; | 370 | UI.nCustomActive = UINT32_MAX; |
| 372 | UI.nCustomTimerCount = 0; | 371 | UI.nCustomTimerCount = 0; |
| 373 | UI.nCustomCount = 0; | 372 | UI.nCustomCount = 0; |
| 374 | 373 | ||
| @@ -498,8 +497,8 @@ inline void MicroProfileDrawFloatWindow(uint32_t nX, uint32_t nY, const char** p | |||
| 498 | { | 497 | { |
| 499 | MicroProfileDrawBox(nX-MICROPROFILE_TEXT_WIDTH, nY, nX, nY + MICROPROFILE_TEXT_WIDTH, pColors[i]|0xff000000); | 498 | MicroProfileDrawBox(nX-MICROPROFILE_TEXT_WIDTH, nY, nX, nY + MICROPROFILE_TEXT_WIDTH, pColors[i]|0xff000000); |
| 500 | } | 499 | } |
| 501 | MicroProfileDrawText(nX + 1, nY + 1, (uint32_t)-1, ppStrings[i0], (uint32_t)strlen(ppStrings[i0])); | 500 | MicroProfileDrawText(nX + 1, nY + 1, UINT32_MAX, ppStrings[i0], (uint32_t)strlen(ppStrings[i0])); |
| 502 | MicroProfileDrawText(nX + nWidth - nStringLengths[i0+1] * (MICROPROFILE_TEXT_WIDTH+1), nY + 1, (uint32_t)-1, ppStrings[i0+1], (uint32_t)strlen(ppStrings[i0+1])); | 501 | MicroProfileDrawText(nX + nWidth - nStringLengths[i0+1] * (MICROPROFILE_TEXT_WIDTH+1), nY + 1, UINT32_MAX, ppStrings[i0+1], (uint32_t)strlen(ppStrings[i0+1])); |
| 503 | nY += (MICROPROFILE_TEXT_HEIGHT+1); | 502 | nY += (MICROPROFILE_TEXT_HEIGHT+1); |
| 504 | } | 503 | } |
| 505 | } | 504 | } |
| @@ -522,7 +521,7 @@ inline void MicroProfileDrawTextBox(uint32_t nX, uint32_t nY, const char** ppStr | |||
| 522 | MicroProfileDrawBox(nX, nY, nX + nWidth, nY + nHeight, 0xff000000); | 521 | MicroProfileDrawBox(nX, nY, nX + nWidth, nY + nHeight, 0xff000000); |
| 523 | for(uint32_t i = 0; i < nNumStrings; ++i) | 522 | for(uint32_t i = 0; i < nNumStrings; ++i) |
| 524 | { | 523 | { |
| 525 | MicroProfileDrawText(nX + 1, nY + 1, (uint32_t)-1, ppStrings[i], (uint32_t)strlen(ppStrings[i])); | 524 | MicroProfileDrawText(nX + 1, nY + 1, UINT32_MAX, ppStrings[i], (uint32_t)strlen(ppStrings[i])); |
| 526 | nY += (MICROPROFILE_TEXT_HEIGHT+1); | 525 | nY += (MICROPROFILE_TEXT_HEIGHT+1); |
| 527 | } | 526 | } |
| 528 | } | 527 | } |
| @@ -781,7 +780,7 @@ inline void MicroProfileDrawDetailedContextSwitchBars(uint32_t nY, uint32_t nThr | |||
| 781 | { | 780 | { |
| 782 | MicroProfile& S = *MicroProfileGet(); | 781 | MicroProfile& S = *MicroProfileGet(); |
| 783 | int64_t nTickIn = -1; | 782 | int64_t nTickIn = -1; |
| 784 | uint32_t nThreadBefore = -1; | 783 | uint32_t nThreadBefore = UINT32_MAX; |
| 785 | float fToMs = MicroProfileTickToMsMultiplier(MicroProfileTicksPerSecondCpu()); | 784 | float fToMs = MicroProfileTickToMsMultiplier(MicroProfileTicksPerSecondCpu()); |
| 786 | float fMsToScreen = UI.nWidth / UI.fDetailedRange; | 785 | float fMsToScreen = UI.nWidth / UI.fDetailedRange; |
| 787 | float fMouseX = (float)UI.nMouseX; | 786 | float fMouseX = (float)UI.nMouseX; |
| @@ -949,10 +948,10 @@ inline void MicroProfileDrawDetailedBars(uint32_t nWidth, uint32_t nHeight, int | |||
| 949 | 948 | ||
| 950 | uint32_t nContextSwitchHoverThreadAfter = S.nContextSwitchHoverThreadAfter; | 949 | uint32_t nContextSwitchHoverThreadAfter = S.nContextSwitchHoverThreadAfter; |
| 951 | uint32_t nContextSwitchHoverThreadBefore = S.nContextSwitchHoverThreadBefore; | 950 | uint32_t nContextSwitchHoverThreadBefore = S.nContextSwitchHoverThreadBefore; |
| 952 | S.nContextSwitchHoverThread = S.nContextSwitchHoverThreadAfter = S.nContextSwitchHoverThreadBefore = -1; | 951 | S.nContextSwitchHoverThread = S.nContextSwitchHoverThreadAfter = S.nContextSwitchHoverThreadBefore = UINT32_MAX; |
| 953 | 952 | ||
| 954 | uint32_t nContextSwitchStart = -1; | 953 | uint32_t nContextSwitchStart = UINT32_MAX; |
| 955 | uint32_t nContextSwitchEnd = -1; | 954 | uint32_t nContextSwitchEnd = UINT32_MAX; |
| 956 | S.nContextSwitchHoverCpuNext = 0xff; | 955 | S.nContextSwitchHoverCpuNext = 0xff; |
| 957 | S.nContextSwitchHoverTickIn = -1; | 956 | S.nContextSwitchHoverTickIn = -1; |
| 958 | S.nContextSwitchHoverTickOut = -1; | 957 | S.nContextSwitchHoverTickOut = -1; |
| @@ -1005,9 +1004,10 @@ inline void MicroProfileDrawDetailedBars(uint32_t nWidth, uint32_t nHeight, int | |||
| 1005 | }while(pFrameLogFirst != pFrameFirst); | 1004 | }while(pFrameLogFirst != pFrameFirst); |
| 1006 | 1005 | ||
| 1007 | 1006 | ||
| 1008 | if(nGet == (uint32_t)-1) | 1007 | if (nGet == UINT32_MAX) { |
| 1009 | continue; | 1008 | continue; |
| 1010 | MP_ASSERT(nGet != (uint32_t)-1); | 1009 | } |
| 1010 | MP_ASSERT(nGet != UINT32_MAX); | ||
| 1011 | 1011 | ||
| 1012 | nPut = pFrameLogLast->nLogStart[i]; | 1012 | nPut = pFrameLogLast->nLogStart[i]; |
| 1013 | 1013 | ||
| @@ -1023,9 +1023,9 @@ inline void MicroProfileDrawDetailedBars(uint32_t nWidth, uint32_t nHeight, int | |||
| 1023 | int64_t nBaseTicks = bGpu ? nBaseTicksGpu : nBaseTicksCpu; | 1023 | int64_t nBaseTicks = bGpu ? nBaseTicksGpu : nBaseTicksCpu; |
| 1024 | char ThreadName[MicroProfileThreadLog::THREAD_MAX_LEN + 16]; | 1024 | char ThreadName[MicroProfileThreadLog::THREAD_MAX_LEN + 16]; |
| 1025 | uint64_t nThreadId = pLog->nThreadId; | 1025 | uint64_t nThreadId = pLog->nThreadId; |
| 1026 | snprintf(ThreadName, sizeof(ThreadName)-1, "%04llx: %s", nThreadId, &pLog->ThreadName[0] ); | 1026 | snprintf(ThreadName, sizeof(ThreadName)-1, "%04" PRIx64 ": %s", nThreadId, &pLog->ThreadName[0] ); |
| 1027 | nY += 3; | 1027 | nY += 3; |
| 1028 | uint32_t nThreadColor = -1; | 1028 | uint32_t nThreadColor = UINT32_MAX; |
| 1029 | if(pLog->nThreadId == nContextSwitchHoverThreadAfter || pLog->nThreadId == nContextSwitchHoverThreadBefore) | 1029 | if(pLog->nThreadId == nContextSwitchHoverThreadAfter || pLog->nThreadId == nContextSwitchHoverThreadBefore) |
| 1030 | nThreadColor = UI.nHoverColorShared|0x906060; | 1030 | nThreadColor = UI.nHoverColorShared|0x906060; |
| 1031 | MicroProfileDrawText(0, nY, nThreadColor, &ThreadName[0], (uint32_t)strlen(&ThreadName[0])); | 1031 | MicroProfileDrawText(0, nY, nThreadColor, &ThreadName[0], (uint32_t)strlen(&ThreadName[0])); |
| @@ -1048,7 +1048,7 @@ inline void MicroProfileDrawDetailedBars(uint32_t nWidth, uint32_t nHeight, int | |||
| 1048 | uint32_t nEnd = nRange[j][1]; | 1048 | uint32_t nEnd = nRange[j][1]; |
| 1049 | for(uint32_t k = nStart; k < nEnd; ++k) | 1049 | for(uint32_t k = nStart; k < nEnd; ++k) |
| 1050 | { | 1050 | { |
| 1051 | MicroProfileLogEntry* pEntry = pLog->Log + k; | 1051 | MicroProfileLogEntry* pEntry = &pLog->Log[k]; |
| 1052 | int nType = MicroProfileLogType(*pEntry); | 1052 | int nType = MicroProfileLogType(*pEntry); |
| 1053 | if(MP_LOG_ENTER == nType) | 1053 | if(MP_LOG_ENTER == nType) |
| 1054 | { | 1054 | { |
| @@ -1066,7 +1066,7 @@ inline void MicroProfileDrawDetailedBars(uint32_t nWidth, uint32_t nHeight, int | |||
| 1066 | continue; | 1066 | continue; |
| 1067 | } | 1067 | } |
| 1068 | 1068 | ||
| 1069 | MicroProfileLogEntry* pEntryEnter = pLog->Log + nStack[nStackPos-1]; | 1069 | MicroProfileLogEntry* pEntryEnter = &pLog->Log[nStack[nStackPos-1]]; |
| 1070 | if(MicroProfileLogTimerIndex(*pEntryEnter) != MicroProfileLogTimerIndex(*pEntry)) | 1070 | if(MicroProfileLogTimerIndex(*pEntryEnter) != MicroProfileLogTimerIndex(*pEntry)) |
| 1071 | { | 1071 | { |
| 1072 | //uprintf("mismatch %llx %llx\n", pEntryEnter->nToken, pEntry->nToken); | 1072 | //uprintf("mismatch %llx %llx\n", pEntryEnter->nToken, pEntry->nToken); |
| @@ -1126,7 +1126,7 @@ inline void MicroProfileDrawDetailedBars(uint32_t nWidth, uint32_t nHeight, int | |||
| 1126 | uint32_t nIntegerWidth = (uint32_t)(fXEnd - fXStart); | 1126 | uint32_t nIntegerWidth = (uint32_t)(fXEnd - fXStart); |
| 1127 | if(nIntegerWidth) | 1127 | if(nIntegerWidth) |
| 1128 | { | 1128 | { |
| 1129 | if(bHover && UI.nActiveMenu == -1) | 1129 | if(bHover && UI.nActiveMenu == UINT32_MAX) |
| 1130 | { | 1130 | { |
| 1131 | nHoverToken = MicroProfileLogTimerIndex(*pEntry); | 1131 | nHoverToken = MicroProfileLogTimerIndex(*pEntry); |
| 1132 | #if MICROPROFILE_DEBUG | 1132 | #if MICROPROFILE_DEBUG |
| @@ -1146,7 +1146,7 @@ inline void MicroProfileDrawDetailedBars(uint32_t nWidth, uint32_t nHeight, int | |||
| 1146 | int nCharacters = (nTextWidth - 2*MICROPROFILE_TEXT_WIDTH) / MICROPROFILE_TEXT_WIDTH; | 1146 | int nCharacters = (nTextWidth - 2*MICROPROFILE_TEXT_WIDTH) / MICROPROFILE_TEXT_WIDTH; |
| 1147 | if(nCharacters>0) | 1147 | if(nCharacters>0) |
| 1148 | { | 1148 | { |
| 1149 | MicroProfileDrawText(fXStartText+1, fYStart+1, -1, S.TimerInfo[nTimerIndex].pName, MicroProfileMin<uint32_t>(S.TimerInfo[nTimerIndex].nNameLen, nCharacters)); | 1149 | MicroProfileDrawText(fXStartText + 1, fYStart + 1, UINT32_MAX, S.TimerInfo[nTimerIndex].pName, MicroProfileMin<uint32_t>(S.TimerInfo[nTimerIndex].nNameLen, nCharacters)); |
| 1150 | } | 1150 | } |
| 1151 | } | 1151 | } |
| 1152 | #endif | 1152 | #endif |
| @@ -1158,7 +1158,7 @@ inline void MicroProfileDrawDetailedBars(uint32_t nWidth, uint32_t nHeight, int | |||
| 1158 | int nLineX = (int)floor(fXAvg+0.5f); | 1158 | int nLineX = (int)floor(fXAvg+0.5f); |
| 1159 | if(nLineX != (int)nLinesDrawn[nStackPos]) | 1159 | if(nLineX != (int)nLinesDrawn[nStackPos]) |
| 1160 | { | 1160 | { |
| 1161 | if(bHover && UI.nActiveMenu == -1) | 1161 | if(bHover && UI.nActiveMenu == UINT32_MAX) |
| 1162 | { | 1162 | { |
| 1163 | nHoverToken = (uint32_t)MicroProfileLogTimerIndex(*pEntry); | 1163 | nHoverToken = (uint32_t)MicroProfileLogTimerIndex(*pEntry); |
| 1164 | nHoverTime = MicroProfileLogTickDifference(nTickStart, nTickEnd); | 1164 | nHoverTime = MicroProfileLogTickDifference(nTickStart, nTickEnd); |
| @@ -1235,9 +1235,9 @@ inline void MicroProfileDrawDetailedBars(uint32_t nWidth, uint32_t nHeight, int | |||
| 1235 | // nThreadId is 32-bit on Windows | 1235 | // nThreadId is 32-bit on Windows |
| 1236 | int nStrLen = snprintf(ThreadName, sizeof(ThreadName)-1, "%04x: %s%s", nThreadId, cLocal, i < nNumThreadsBase ? &S.Pool[i]->ThreadName[0] : MICROPROFILE_THREAD_NAME_FROM_ID(nThreadId) ); | 1236 | int nStrLen = snprintf(ThreadName, sizeof(ThreadName)-1, "%04x: %s%s", nThreadId, cLocal, i < nNumThreadsBase ? &S.Pool[i]->ThreadName[0] : MICROPROFILE_THREAD_NAME_FROM_ID(nThreadId) ); |
| 1237 | #else | 1237 | #else |
| 1238 | int nStrLen = snprintf(ThreadName, sizeof(ThreadName)-1, "%04llx: %s%s", nThreadId, cLocal, i < nNumThreadsBase ? &S.Pool[i]->ThreadName[0] : MICROPROFILE_THREAD_NAME_FROM_ID(nThreadId) ); | 1238 | int nStrLen = snprintf(ThreadName, sizeof(ThreadName)-1, "%04" PRIx64 ": %s%s", nThreadId, cLocal, i < nNumThreadsBase ? &S.Pool[i]->ThreadName[0] : MICROPROFILE_THREAD_NAME_FROM_ID(nThreadId) ); |
| 1239 | #endif | 1239 | #endif |
| 1240 | uint32_t nThreadColor = -1; | 1240 | uint32_t nThreadColor = UINT32_MAX; |
| 1241 | if(nThreadId == nContextSwitchHoverThreadAfter || nThreadId == nContextSwitchHoverThreadBefore) | 1241 | if(nThreadId == nContextSwitchHoverThreadAfter || nThreadId == nContextSwitchHoverThreadBefore) |
| 1242 | nThreadColor = UI.nHoverColorShared|0x906060; | 1242 | nThreadColor = UI.nHoverColorShared|0x906060; |
| 1243 | MicroProfileDrawDetailedContextSwitchBars(nY+2, nThreadId, nContextSwitchStart, nContextSwitchEnd, nBaseTicksCpu, nBaseY); | 1243 | MicroProfileDrawDetailedContextSwitchBars(nY+2, nThreadId, nContextSwitchStart, nContextSwitchEnd, nBaseTicksCpu, nBaseY); |
| @@ -1249,9 +1249,6 @@ inline void MicroProfileDrawDetailedBars(uint32_t nWidth, uint32_t nHeight, int | |||
| 1249 | 1249 | ||
| 1250 | S.nContextSwitchHoverCpu = S.nContextSwitchHoverCpuNext; | 1250 | S.nContextSwitchHoverCpu = S.nContextSwitchHoverCpuNext; |
| 1251 | 1251 | ||
| 1252 | |||
| 1253 | |||
| 1254 | |||
| 1255 | UI.pDisplayMouseOver = pMouseOverNext; | 1252 | UI.pDisplayMouseOver = pMouseOverNext; |
| 1256 | 1253 | ||
| 1257 | if(!S.nRunning) | 1254 | if(!S.nRunning) |
| @@ -1286,10 +1283,10 @@ inline void MicroProfileDrawDetailedBars(uint32_t nWidth, uint32_t nHeight, int | |||
| 1286 | float fStartTextWidth = (float)((1+MICROPROFILE_TEXT_WIDTH) * nLenStart); | 1283 | float fStartTextWidth = (float)((1+MICROPROFILE_TEXT_WIDTH) * nLenStart); |
| 1287 | float fStartTextX = fXStart - fStartTextWidth - 2; | 1284 | float fStartTextX = fXStart - fStartTextWidth - 2; |
| 1288 | MicroProfileDrawBox(fStartTextX, nBaseY, fStartTextX + fStartTextWidth + 2, MICROPROFILE_TEXT_HEIGHT + 2 + nBaseY, 0x33000000, MicroProfileBoxTypeFlat); | 1285 | MicroProfileDrawBox(fStartTextX, nBaseY, fStartTextX + fStartTextWidth + 2, MICROPROFILE_TEXT_HEIGHT + 2 + nBaseY, 0x33000000, MicroProfileBoxTypeFlat); |
| 1289 | MicroProfileDrawText(fStartTextX+1, nBaseY, (uint32_t)-1, sBuffer, nLenStart); | 1286 | MicroProfileDrawText(fStartTextX+1, nBaseY, UINT32_MAX, sBuffer, nLenStart); |
| 1290 | uint32_t nLenEnd = snprintf(sBuffer, sizeof(sBuffer)-1, "%.2fms", fMsEnd); | 1287 | uint32_t nLenEnd = snprintf(sBuffer, sizeof(sBuffer)-1, "%.2fms", fMsEnd); |
| 1291 | MicroProfileDrawBox(fXEnd+1, nBaseY, fXEnd+1+(1+MICROPROFILE_TEXT_WIDTH) * nLenEnd + 3, MICROPROFILE_TEXT_HEIGHT + 2 + nBaseY, 0x33000000, MicroProfileBoxTypeFlat); | 1288 | MicroProfileDrawBox(fXEnd+1, nBaseY, fXEnd+1+(1+MICROPROFILE_TEXT_WIDTH) * nLenEnd + 3, MICROPROFILE_TEXT_HEIGHT + 2 + nBaseY, 0x33000000, MicroProfileBoxTypeFlat); |
| 1292 | MicroProfileDrawText(fXEnd+2, nBaseY+1, (uint32_t)-1, sBuffer, nLenEnd); | 1289 | MicroProfileDrawText(fXEnd+2, nBaseY+1, UINT32_MAX, sBuffer, nLenEnd); |
| 1293 | 1290 | ||
| 1294 | if(UI.nMouseRight) | 1291 | if(UI.nMouseRight) |
| 1295 | { | 1292 | { |
| @@ -1316,10 +1313,10 @@ inline void MicroProfileDrawDetailedBars(uint32_t nWidth, uint32_t nHeight, int | |||
| 1316 | float fStartTextWidth = (float)((1+MICROPROFILE_TEXT_WIDTH) * nLenStart); | 1313 | float fStartTextWidth = (float)((1+MICROPROFILE_TEXT_WIDTH) * nLenStart); |
| 1317 | float fStartTextX = fXStart - fStartTextWidth - 2; | 1314 | float fStartTextX = fXStart - fStartTextWidth - 2; |
| 1318 | MicroProfileDrawBox(fStartTextX, nBaseY, fStartTextX + fStartTextWidth + 2, MICROPROFILE_TEXT_HEIGHT + 2 + nBaseY, 0x33000000, MicroProfileBoxTypeFlat); | 1315 | MicroProfileDrawBox(fStartTextX, nBaseY, fStartTextX + fStartTextWidth + 2, MICROPROFILE_TEXT_HEIGHT + 2 + nBaseY, 0x33000000, MicroProfileBoxTypeFlat); |
| 1319 | MicroProfileDrawText(fStartTextX+1, nBaseY, (uint32_t)-1, sBuffer, nLenStart); | 1316 | MicroProfileDrawText(fStartTextX+1, nBaseY, UINT32_MAX, sBuffer, nLenStart); |
| 1320 | uint32_t nLenEnd = snprintf(sBuffer, sizeof(sBuffer)-1, "%.2fms", fMsEnd); | 1317 | uint32_t nLenEnd = snprintf(sBuffer, sizeof(sBuffer)-1, "%.2fms", fMsEnd); |
| 1321 | MicroProfileDrawBox(fXEnd+1, nBaseY, fXEnd+1+(1+MICROPROFILE_TEXT_WIDTH) * nLenEnd + 3, MICROPROFILE_TEXT_HEIGHT + 2 + nBaseY, 0x33000000, MicroProfileBoxTypeFlat); | 1318 | MicroProfileDrawBox(fXEnd+1, nBaseY, fXEnd+1+(1+MICROPROFILE_TEXT_WIDTH) * nLenEnd + 3, MICROPROFILE_TEXT_HEIGHT + 2 + nBaseY, 0x33000000, MicroProfileBoxTypeFlat); |
| 1322 | MicroProfileDrawText(fXEnd+2, nBaseY+1, (uint32_t)-1, sBuffer, nLenEnd); | 1319 | MicroProfileDrawText(fXEnd+2, nBaseY+1, UINT32_MAX, sBuffer, nLenEnd); |
| 1323 | } | 1320 | } |
| 1324 | } | 1321 | } |
| 1325 | } | 1322 | } |
| @@ -1365,7 +1362,7 @@ inline void MicroProfileDrawDetailedFrameHistory(uint32_t nWidth, uint32_t nHeig | |||
| 1365 | fBaseX = fXStart; | 1362 | fBaseX = fXStart; |
| 1366 | uint32_t nColor = MICROPROFILE_FRAME_HISTORY_COLOR_CPU; | 1363 | uint32_t nColor = MICROPROFILE_FRAME_HISTORY_COLOR_CPU; |
| 1367 | if(nIndex == nSelectedFrame) | 1364 | if(nIndex == nSelectedFrame) |
| 1368 | nColor = (uint32_t)-1; | 1365 | nColor = UINT32_MAX; |
| 1369 | MicroProfileDrawBox(fXStart, nBaseY + fScale * nBarHeight, fXEnd, nBaseY+MICROPROFILE_FRAME_HISTORY_HEIGHT, nColor, MicroProfileBoxTypeBar); | 1366 | MicroProfileDrawBox(fXStart, nBaseY + fScale * nBarHeight, fXEnd, nBaseY+MICROPROFILE_FRAME_HISTORY_HEIGHT, nColor, MicroProfileBoxTypeBar); |
| 1370 | if(pNext->nFrameStartCpu > nCpuStart) | 1367 | if(pNext->nFrameStartCpu > nCpuStart) |
| 1371 | { | 1368 | { |
| @@ -1387,7 +1384,7 @@ inline void MicroProfileDrawDetailedView(uint32_t nWidth, uint32_t nHeight) | |||
| 1387 | uint32_t nBaseY = MICROPROFILE_TEXT_HEIGHT + 1; | 1384 | uint32_t nBaseY = MICROPROFILE_TEXT_HEIGHT + 1; |
| 1388 | 1385 | ||
| 1389 | int nSelectedFrame = -1; | 1386 | int nSelectedFrame = -1; |
| 1390 | if(UI.nMouseY > nBaseY && UI.nMouseY <= nBaseY + MICROPROFILE_FRAME_HISTORY_HEIGHT && UI.nActiveMenu == -1) | 1387 | if(UI.nMouseY > nBaseY && UI.nMouseY <= nBaseY + MICROPROFILE_FRAME_HISTORY_HEIGHT && UI.nActiveMenu == UINT32_MAX) |
| 1391 | { | 1388 | { |
| 1392 | 1389 | ||
| 1393 | nSelectedFrame = ((MICROPROFILE_NUM_FRAMES) * (UI.nWidth-UI.nMouseX) / UI.nWidth); | 1390 | nSelectedFrame = ((MICROPROFILE_NUM_FRAMES) * (UI.nWidth-UI.nMouseX) / UI.nWidth); |
| @@ -1425,7 +1422,7 @@ inline void MicroProfileDrawHeader(int32_t nX, uint32_t nWidth, const char* pNam | |||
| 1425 | if(pName) | 1422 | if(pName) |
| 1426 | { | 1423 | { |
| 1427 | MicroProfileDrawBox(nX-8, MICROPROFILE_TEXT_HEIGHT + 2, nX + nWidth+5, MICROPROFILE_TEXT_HEIGHT + 2 + (MICROPROFILE_TEXT_HEIGHT+1), 0xff000000|g_nMicroProfileBackColors[1]); | 1424 | MicroProfileDrawBox(nX-8, MICROPROFILE_TEXT_HEIGHT + 2, nX + nWidth+5, MICROPROFILE_TEXT_HEIGHT + 2 + (MICROPROFILE_TEXT_HEIGHT+1), 0xff000000|g_nMicroProfileBackColors[1]); |
| 1428 | MicroProfileDrawText(nX, MICROPROFILE_TEXT_HEIGHT + 2, (uint32_t)-1, pName, (uint32_t)strlen(pName)); | 1425 | MicroProfileDrawText(nX, MICROPROFILE_TEXT_HEIGHT + 2, UINT32_MAX, pName, (uint32_t)strlen(pName)); |
| 1429 | } | 1426 | } |
| 1430 | } | 1427 | } |
| 1431 | 1428 | ||
| @@ -1440,7 +1437,7 @@ inline void MicroProfileLoopActiveGroupsDraw(int32_t nX, int32_t nY, const char* | |||
| 1440 | uint32_t nCount = 0; | 1437 | uint32_t nCount = 0; |
| 1441 | for(uint32_t j = 0; j < MICROPROFILE_MAX_GROUPS; ++j) | 1438 | for(uint32_t j = 0; j < MICROPROFILE_MAX_GROUPS; ++j) |
| 1442 | { | 1439 | { |
| 1443 | uint64_t nMask = 1ll << j; | 1440 | uint64_t nMask = 1ULL << j; |
| 1444 | if(nMask & nGroup) | 1441 | if(nMask & nGroup) |
| 1445 | { | 1442 | { |
| 1446 | nY += MICROPROFILE_TEXT_HEIGHT + 1; | 1443 | nY += MICROPROFILE_TEXT_HEIGHT + 1; |
| @@ -1521,7 +1518,7 @@ inline void MicroProfileCalcTimers(float* pTimers, float* pAverage, float* pMax, | |||
| 1521 | } | 1518 | } |
| 1522 | } | 1519 | } |
| 1523 | } | 1520 | } |
| 1524 | nMask <<= 1ll; | 1521 | nMask <<= 1; |
| 1525 | } | 1522 | } |
| 1526 | } | 1523 | } |
| 1527 | 1524 | ||
| @@ -1543,7 +1540,7 @@ inline void MicroProfileDrawBarArrayCallback(uint32_t nTimer, uint32_t nIdx, uin | |||
| 1543 | snprintf(sBuffer, SBUF_MAX-1, "%5.2f", pTimers[nIdx]); | 1540 | snprintf(sBuffer, SBUF_MAX-1, "%5.2f", pTimers[nIdx]); |
| 1544 | if (!pTimers2) | 1541 | if (!pTimers2) |
| 1545 | MicroProfileDrawBox(nX + nTextWidth, nY, nX + nTextWidth + fWidth * pTimers[nIdx+1], nY + nHeight, UI.nOpacityForeground|S.TimerInfo[nTimer].nColor, MicroProfileBoxTypeBar); | 1542 | MicroProfileDrawBox(nX + nTextWidth, nY, nX + nTextWidth + fWidth * pTimers[nIdx+1], nY + nHeight, UI.nOpacityForeground|S.TimerInfo[nTimer].nColor, MicroProfileBoxTypeBar); |
| 1546 | MicroProfileDrawText(nX, nY, (uint32_t)-1, sBuffer, (uint32_t)strlen(sBuffer)); | 1543 | MicroProfileDrawText(nX, nY, UINT32_MAX, sBuffer, (uint32_t)strlen(sBuffer)); |
| 1547 | } | 1544 | } |
| 1548 | 1545 | ||
| 1549 | 1546 | ||
| @@ -1564,7 +1561,7 @@ inline void MicroProfileDrawBarCallCountCallback(uint32_t nTimer, uint32_t nIdx, | |||
| 1564 | MicroProfile& S = *MicroProfileGet(); | 1561 | MicroProfile& S = *MicroProfileGet(); |
| 1565 | char sBuffer[SBUF_MAX]; | 1562 | char sBuffer[SBUF_MAX]; |
| 1566 | int nLen = snprintf(sBuffer, SBUF_MAX-1, "%5d", S.Frame[nTimer].nCount);//fix | 1563 | int nLen = snprintf(sBuffer, SBUF_MAX-1, "%5d", S.Frame[nTimer].nCount);//fix |
| 1567 | MicroProfileDrawText(nX, nY, (uint32_t)-1, sBuffer, nLen); | 1564 | MicroProfileDrawText(nX, nY, UINT32_MAX, sBuffer, nLen); |
| 1568 | } | 1565 | } |
| 1569 | 1566 | ||
| 1570 | inline uint32_t MicroProfileDrawBarCallCount(int32_t nX, int32_t nY, const char* pName) | 1567 | inline uint32_t MicroProfileDrawBarCallCount(int32_t nX, int32_t nY, const char* pName) |
| @@ -1588,7 +1585,7 @@ inline void MicroProfileDrawBarMetaAverageCallback(uint32_t nTimer, uint32_t nId | |||
| 1588 | float fRcpFrames = pArgs->fRcpFrames; | 1585 | float fRcpFrames = pArgs->fRcpFrames; |
| 1589 | char sBuffer[SBUF_MAX]; | 1586 | char sBuffer[SBUF_MAX]; |
| 1590 | int nLen = snprintf(sBuffer, SBUF_MAX-1, "%5.2f", pCounters[nTimer] * fRcpFrames); | 1587 | int nLen = snprintf(sBuffer, SBUF_MAX-1, "%5.2f", pCounters[nTimer] * fRcpFrames); |
| 1591 | MicroProfileDrawText(nX - nLen * (MICROPROFILE_TEXT_WIDTH+1), nY, (uint32_t)-1, sBuffer, nLen); | 1588 | MicroProfileDrawText(nX - nLen * (MICROPROFILE_TEXT_WIDTH+1), nY, UINT32_MAX, sBuffer, nLen); |
| 1592 | } | 1589 | } |
| 1593 | 1590 | ||
| 1594 | inline uint32_t MicroProfileDrawBarMetaAverage(int32_t nX, int32_t nY, uint64_t* pCounters, const char* pName, uint32_t nTotalHeight) | 1591 | inline uint32_t MicroProfileDrawBarMetaAverage(int32_t nX, int32_t nY, uint64_t* pCounters, const char* pName, uint32_t nTotalHeight) |
| @@ -1609,8 +1606,8 @@ inline void MicroProfileDrawBarMetaCountCallback(uint32_t nTimer, uint32_t nIdx, | |||
| 1609 | { | 1606 | { |
| 1610 | uint64_t* pCounters = (uint64_t*)pExtra; | 1607 | uint64_t* pCounters = (uint64_t*)pExtra; |
| 1611 | char sBuffer[SBUF_MAX]; | 1608 | char sBuffer[SBUF_MAX]; |
| 1612 | int nLen = snprintf(sBuffer, SBUF_MAX-1, "%5llu", pCounters[nTimer]); | 1609 | int nLen = snprintf(sBuffer, SBUF_MAX-1, "%5" PRIu64, pCounters[nTimer]); |
| 1613 | MicroProfileDrawText(nX - nLen * (MICROPROFILE_TEXT_WIDTH+1), nY, (uint32_t)-1, sBuffer, nLen); | 1610 | MicroProfileDrawText(nX - nLen * (MICROPROFILE_TEXT_WIDTH+1), nY, UINT32_MAX, sBuffer, nLen); |
| 1614 | } | 1611 | } |
| 1615 | 1612 | ||
| 1616 | inline uint32_t MicroProfileDrawBarMetaCount(int32_t nX, int32_t nY, uint64_t* pCounters, const char* pName, uint32_t nTotalHeight) | 1613 | inline uint32_t MicroProfileDrawBarMetaCount(int32_t nX, int32_t nY, uint64_t* pCounters, const char* pName, uint32_t nTotalHeight) |
| @@ -1667,7 +1664,7 @@ bool MicroProfileDrawGraph(uint32_t nScreenWidth, uint32_t nScreenHeight) | |||
| 1667 | if(bMouseOver) | 1664 | if(bMouseOver) |
| 1668 | { | 1665 | { |
| 1669 | float fXAvg = fMouseXPrc * MICROPROFILE_GRAPH_WIDTH + nX; | 1666 | float fXAvg = fMouseXPrc * MICROPROFILE_GRAPH_WIDTH + nX; |
| 1670 | MicroProfileDrawLineVertical(fXAvg, nY, nY + MICROPROFILE_GRAPH_HEIGHT, (uint32_t)-1); | 1667 | MicroProfileDrawLineVertical(fXAvg, nY, nY + MICROPROFILE_GRAPH_HEIGHT, UINT32_MAX); |
| 1671 | } | 1668 | } |
| 1672 | 1669 | ||
| 1673 | 1670 | ||
| @@ -1706,7 +1703,7 @@ bool MicroProfileDrawGraph(uint32_t nScreenWidth, uint32_t nScreenHeight) | |||
| 1706 | 1703 | ||
| 1707 | char buf[32]; | 1704 | char buf[32]; |
| 1708 | int nLen = snprintf(buf, sizeof(buf)-1, "%5.2fms", S.fReferenceTime); | 1705 | int nLen = snprintf(buf, sizeof(buf)-1, "%5.2fms", S.fReferenceTime); |
| 1709 | MicroProfileDrawText(nX+1, fY1 - (2+MICROPROFILE_TEXT_HEIGHT), (uint32_t)-1, buf, nLen); | 1706 | MicroProfileDrawText(nX+1, fY1 - (2+MICROPROFILE_TEXT_HEIGHT), UINT32_MAX, buf, nLen); |
| 1710 | } | 1707 | } |
| 1711 | 1708 | ||
| 1712 | 1709 | ||
| @@ -1782,7 +1779,7 @@ void MicroProfileDumpTimers() | |||
| 1782 | 1779 | ||
| 1783 | for(uint32_t j = 0; j < MICROPROFILE_MAX_GROUPS; ++j) | 1780 | for(uint32_t j = 0; j < MICROPROFILE_MAX_GROUPS; ++j) |
| 1784 | { | 1781 | { |
| 1785 | uint64_t nMask = 1ll << j; | 1782 | uint64_t nMask = 1ULL << j; |
| 1786 | if(nMask & nActiveGroup) | 1783 | if(nMask & nActiveGroup) |
| 1787 | { | 1784 | { |
| 1788 | MICROPROFILE_PRINTF("%s\n", S.GroupInfo[j].pName); | 1785 | MICROPROFILE_PRINTF("%s\n", S.GroupInfo[j].pName); |
| @@ -1823,7 +1820,7 @@ inline void MicroProfileDrawBarView(uint32_t nScreenWidth, uint32_t nScreenHeigh | |||
| 1823 | uint32_t nNumGroups = 0; | 1820 | uint32_t nNumGroups = 0; |
| 1824 | for(uint32_t j = 0; j < MICROPROFILE_MAX_GROUPS; ++j) | 1821 | for(uint32_t j = 0; j < MICROPROFILE_MAX_GROUPS; ++j) |
| 1825 | { | 1822 | { |
| 1826 | if(nActiveGroup & (1ll << j)) | 1823 | if(nActiveGroup & (1ULL << j)) |
| 1827 | { | 1824 | { |
| 1828 | nNumTimers += S.GroupInfo[j].nNumTimers; | 1825 | nNumTimers += S.GroupInfo[j].nNumTimers; |
| 1829 | nNumGroups += 1; | 1826 | nNumGroups += 1; |
| @@ -1878,7 +1875,7 @@ inline void MicroProfileDrawBarView(uint32_t nScreenWidth, uint32_t nScreenHeigh | |||
| 1878 | for(uint32_t i = 0; i < nNumTimers+nNumGroups+1; ++i) | 1875 | for(uint32_t i = 0; i < nNumTimers+nNumGroups+1; ++i) |
| 1879 | { | 1876 | { |
| 1880 | uint32_t nY0 = nY + i * (nHeight + 1); | 1877 | uint32_t nY0 = nY + i * (nHeight + 1); |
| 1881 | bool bInside = (UI.nActiveMenu == -1) && ((UI.nMouseY >= nY0) && (UI.nMouseY < (nY0 + nHeight + 1))); | 1878 | bool bInside = (UI.nActiveMenu == UINT32_MAX) && ((UI.nMouseY >= nY0) && (UI.nMouseY < (nY0 + nHeight + 1))); |
| 1882 | MicroProfileDrawBox(nX, nY0, nWidth+nX, nY0 + (nHeight+1)+1, UI.nOpacityBackground | (g_nMicroProfileBackColors[nColorIndex++ & 1] + ((bInside) ? 0x002c2c2c : 0))); | 1879 | MicroProfileDrawBox(nX, nY0, nWidth+nX, nY0 + (nHeight+1)+1, UI.nOpacityBackground | (g_nMicroProfileBackColors[nColorIndex++ & 1] + ((bInside) ? 0x002c2c2c : 0))); |
| 1883 | } | 1880 | } |
| 1884 | nX += 10; | 1881 | nX += 10; |
| @@ -1927,22 +1924,22 @@ inline void MicroProfileDrawBarView(uint32_t nScreenWidth, uint32_t nScreenHeigh | |||
| 1927 | nY = nHeight + 3 - UI.nOffsetY; | 1924 | nY = nHeight + 3 - UI.nOffsetY; |
| 1928 | for(uint32_t i = 0; i < nNumTimers+nNumGroups+1; ++i) | 1925 | for(uint32_t i = 0; i < nNumTimers+nNumGroups+1; ++i) |
| 1929 | { | 1926 | { |
| 1930 | uint32_t nY0 = nY + i * (nHeight + 1); | 1927 | const uint32_t nY0 = nY + i * (nHeight + 1); |
| 1931 | bool bInside = (UI.nActiveMenu == -1) && ((UI.nMouseY >= nY0) && (UI.nMouseY < (nY0 + nHeight + 1))); | 1928 | const bool bInside = (UI.nActiveMenu == UINT32_MAX) && ((UI.nMouseY >= nY0) && (UI.nMouseY < (nY0 + nHeight + 1))); |
| 1932 | MicroProfileDrawBox(nX, nY0, nTimerWidth, nY0 + (nHeight+1)+1, 0xff0000000 | (g_nMicroProfileBackColors[nColorIndex++ & 1] + ((bInside) ? 0x002c2c2c : 0))); | 1929 | MicroProfileDrawBox(nX, nY0, nTimerWidth, nY0 + (nHeight+1)+1, 0xff0000000 | (g_nMicroProfileBackColors[nColorIndex++ & 1] + ((bInside) ? 0x002c2c2c : 0))); |
| 1933 | } | 1930 | } |
| 1934 | nX += MicroProfileDrawBarLegend(nX, nY, nTotalHeight, nTimerWidth-5) + 1; | 1931 | nX += MicroProfileDrawBarLegend(nX, nY, nTotalHeight, nTimerWidth-5) + 1; |
| 1935 | 1932 | ||
| 1936 | for(uint32_t j = 0; j < MICROPROFILE_MAX_GROUPS; ++j) | 1933 | for(uint32_t j = 0; j < MICROPROFILE_MAX_GROUPS; ++j) |
| 1937 | { | 1934 | { |
| 1938 | if(nActiveGroup & (1ll << j)) | 1935 | if(nActiveGroup & (1ULL << j)) |
| 1939 | { | 1936 | { |
| 1940 | MicroProfileDrawText(nX, nY + (1+nHeight) * nLegendOffset, (uint32_t)-1, S.GroupInfo[j].pName, S.GroupInfo[j].nNameLen); | 1937 | MicroProfileDrawText(nX, nY + (1+nHeight) * nLegendOffset, UINT32_MAX, S.GroupInfo[j].pName, S.GroupInfo[j].nNameLen); |
| 1941 | nLegendOffset += S.GroupInfo[j].nNumTimers+1; | 1938 | nLegendOffset += S.GroupInfo[j].nNumTimers+1; |
| 1942 | } | 1939 | } |
| 1943 | } | 1940 | } |
| 1944 | MicroProfileDrawHeader(nX, nTimerWidth-5, "Group"); | 1941 | MicroProfileDrawHeader(nX, nTimerWidth-5, "Group"); |
| 1945 | MicroProfileDrawTextRight(nTimerWidth-3, MICROPROFILE_TEXT_HEIGHT + 2, (uint32_t)-1, "Timer", 5); | 1942 | MicroProfileDrawTextRight(nTimerWidth-3, MICROPROFILE_TEXT_HEIGHT + 2, UINT32_MAX, "Timer", 5); |
| 1946 | MicroProfileDrawLineVertical(nTimerWidth, 0, nTotalHeight+nY, UI.nOpacityBackground|g_nMicroProfileBackColors[0]|g_nMicroProfileBackColors[1]); | 1943 | MicroProfileDrawLineVertical(nTimerWidth, 0, nTotalHeight+nY, UI.nOpacityBackground|g_nMicroProfileBackColors[0]|g_nMicroProfileBackColors[1]); |
| 1947 | MicroProfileDrawLineHorizontal(0, nWidth, 2*MICROPROFILE_TEXT_HEIGHT + 3, UI.nOpacityBackground|g_nMicroProfileBackColors[0]|g_nMicroProfileBackColors[1]); | 1944 | MicroProfileDrawLineHorizontal(0, nWidth, 2*MICROPROFILE_TEXT_HEIGHT + 3, UI.nOpacityBackground|g_nMicroProfileBackColors[0]|g_nMicroProfileBackColors[1]); |
| 1948 | } | 1945 | } |
| @@ -2003,7 +2000,7 @@ inline const char* MicroProfileUIMenuGroups(int nIndex, bool* bSelected) | |||
| 2003 | } | 2000 | } |
| 2004 | else | 2001 | else |
| 2005 | { | 2002 | { |
| 2006 | *bSelected = 0 != (S.nActiveGroupWanted & (1ll << Item.nIndex)); | 2003 | *bSelected = 0 != (S.nActiveGroupWanted & (1ULL << Item.nIndex)); |
| 2007 | snprintf(buffer, sizeof(buffer)-1, " %s", Item.pName); | 2004 | snprintf(buffer, sizeof(buffer)-1, " %s", Item.pName); |
| 2008 | } | 2005 | } |
| 2009 | return buffer; | 2006 | return buffer; |
| @@ -2015,16 +2012,18 @@ inline const char* MicroProfileUIMenuGroups(int nIndex, bool* bSelected) | |||
| 2015 | inline const char* MicroProfileUIMenuAggregate(int nIndex, bool* bSelected) | 2012 | inline const char* MicroProfileUIMenuAggregate(int nIndex, bool* bSelected) |
| 2016 | { | 2013 | { |
| 2017 | MicroProfile& S = *MicroProfileGet(); | 2014 | MicroProfile& S = *MicroProfileGet(); |
| 2018 | if(nIndex < sizeof(g_MicroProfileAggregatePresets)/sizeof(g_MicroProfileAggregatePresets[0])) | 2015 | if(static_cast<uint32_t>(nIndex) < g_MicroProfileAggregatePresets.size()) |
| 2019 | { | 2016 | { |
| 2020 | int val = g_MicroProfileAggregatePresets[nIndex]; | 2017 | uint32_t val = g_MicroProfileAggregatePresets[nIndex]; |
| 2021 | *bSelected = (int)S.nAggregateFlip == val; | 2018 | *bSelected = S.nAggregateFlip == val; |
| 2022 | if(0 == val) | 2019 | if (0 == val) |
| 2020 | { | ||
| 2023 | return "Infinite"; | 2021 | return "Infinite"; |
| 2022 | } | ||
| 2024 | else | 2023 | else |
| 2025 | { | 2024 | { |
| 2026 | static char buf[128]; | 2025 | static char buf[128]; |
| 2027 | snprintf(buf, sizeof(buf)-1, "%7d", val); | 2026 | snprintf(buf, sizeof(buf)-1, "%7u", val); |
| 2028 | return buf; | 2027 | return buf; |
| 2029 | } | 2028 | } |
| 2030 | } | 2029 | } |
| @@ -2098,11 +2097,13 @@ inline const char* MicroProfileUIMenuPreset(int nIndex, bool* bSelected) | |||
| 2098 | { | 2097 | { |
| 2099 | static char buf[128]; | 2098 | static char buf[128]; |
| 2100 | *bSelected = false; | 2099 | *bSelected = false; |
| 2101 | int nNumPresets = sizeof(g_MicroProfilePresetNames) / sizeof(g_MicroProfilePresetNames[0]); | 2100 | int nNumPresets = static_cast<int>(g_MicroProfilePresetNames.size()); |
| 2102 | int nIndexSave = nIndex - nNumPresets - 1; | 2101 | int nIndexSave = nIndex - nNumPresets - 1; |
| 2103 | if(nIndex == nNumPresets) | 2102 | if (nIndex == nNumPresets) |
| 2103 | { | ||
| 2104 | return "--"; | 2104 | return "--"; |
| 2105 | else if(nIndexSave >=0 && nIndexSave <nNumPresets) | 2105 | } |
| 2106 | else if(nIndexSave >=0 && nIndexSave < nNumPresets) | ||
| 2106 | { | 2107 | { |
| 2107 | snprintf(buf, sizeof(buf)-1, "Save '%s'", g_MicroProfilePresetNames[nIndexSave]); | 2108 | snprintf(buf, sizeof(buf)-1, "Save '%s'", g_MicroProfilePresetNames[nIndexSave]); |
| 2108 | return buf; | 2109 | return buf; |
| @@ -2120,13 +2121,13 @@ inline const char* MicroProfileUIMenuPreset(int nIndex, bool* bSelected) | |||
| 2120 | 2121 | ||
| 2121 | inline const char* MicroProfileUIMenuCustom(int nIndex, bool* bSelected) | 2122 | inline const char* MicroProfileUIMenuCustom(int nIndex, bool* bSelected) |
| 2122 | { | 2123 | { |
| 2123 | if((uint32_t)-1 == UI.nCustomActive) | 2124 | if(UINT32_MAX == UI.nCustomActive) |
| 2124 | { | 2125 | { |
| 2125 | *bSelected = nIndex == 0; | 2126 | *bSelected = nIndex == 0; |
| 2126 | } | 2127 | } |
| 2127 | else | 2128 | else |
| 2128 | { | 2129 | { |
| 2129 | *bSelected = nIndex-2 == UI.nCustomActive; | 2130 | *bSelected = nIndex-2 == static_cast<int>(UI.nCustomActive); |
| 2130 | } | 2131 | } |
| 2131 | switch(nIndex) | 2132 | switch(nIndex) |
| 2132 | { | 2133 | { |
| @@ -2202,7 +2203,7 @@ inline void MicroProfileUIClickGroups(int nIndex) | |||
| 2202 | else | 2203 | else |
| 2203 | { | 2204 | { |
| 2204 | MP_ASSERT(Item.nIndex < S.nGroupCount); | 2205 | MP_ASSERT(Item.nIndex < S.nGroupCount); |
| 2205 | S.nActiveGroupWanted ^= (1ll << Item.nIndex); | 2206 | S.nActiveGroupWanted ^= (1ULL << Item.nIndex); |
| 2206 | } | 2207 | } |
| 2207 | } | 2208 | } |
| 2208 | } | 2209 | } |
| @@ -2273,7 +2274,7 @@ inline void MicroProfileUIClickOptions(int nIndex) | |||
| 2273 | 2274 | ||
| 2274 | inline void MicroProfileUIClickPreset(int nIndex) | 2275 | inline void MicroProfileUIClickPreset(int nIndex) |
| 2275 | { | 2276 | { |
| 2276 | int nNumPresets = sizeof(g_MicroProfilePresetNames) / sizeof(g_MicroProfilePresetNames[0]); | 2277 | int nNumPresets = static_cast<int>(g_MicroProfilePresetNames.size()); |
| 2277 | int nIndexSave = nIndex - nNumPresets - 1; | 2278 | int nIndexSave = nIndex - nNumPresets - 1; |
| 2278 | if(nIndexSave >= 0 && nIndexSave < nNumPresets) | 2279 | if(nIndexSave >= 0 && nIndexSave < nNumPresets) |
| 2279 | { | 2280 | { |
| @@ -2310,7 +2311,7 @@ inline void MicroProfileDrawMenu(uint32_t nWidth, uint32_t nHeight) | |||
| 2310 | 2311 | ||
| 2311 | uint32_t nX = 0; | 2312 | uint32_t nX = 0; |
| 2312 | uint32_t nY = 0; | 2313 | uint32_t nY = 0; |
| 2313 | bool bMouseOver = UI.nMouseY < MICROPROFILE_TEXT_HEIGHT + 1; | 2314 | |
| 2314 | #define SBUF_SIZE 256 | 2315 | #define SBUF_SIZE 256 |
| 2315 | char buffer[256]; | 2316 | char buffer[256]; |
| 2316 | MicroProfileDrawBox(nX, nY, nX + nWidth, nY + (MICROPROFILE_TEXT_HEIGHT+1)+1, 0xff000000|g_nMicroProfileBackColors[1]); | 2317 | MicroProfileDrawBox(nX, nY, nX + nWidth, nY + (MICROPROFILE_TEXT_HEIGHT+1)+1, 0xff000000|g_nMicroProfileBackColors[1]); |
| @@ -2321,7 +2322,7 @@ inline void MicroProfileDrawMenu(uint32_t nWidth, uint32_t nHeight) | |||
| 2321 | uint32_t nNumMenuItems = 0; | 2322 | uint32_t nNumMenuItems = 0; |
| 2322 | 2323 | ||
| 2323 | int nLen = snprintf(buffer, 127, "MicroProfile"); | 2324 | int nLen = snprintf(buffer, 127, "MicroProfile"); |
| 2324 | MicroProfileDrawText(nX, nY, (uint32_t)-1, buffer, nLen); | 2325 | MicroProfileDrawText(nX, nY, UINT32_MAX, buffer, nLen); |
| 2325 | nX += (sizeof("MicroProfile")+2) * (MICROPROFILE_TEXT_WIDTH+1); | 2326 | nX += (sizeof("MicroProfile")+2) * (MICROPROFILE_TEXT_WIDTH+1); |
| 2326 | pMenuText[nNumMenuItems++] = "Mode"; | 2327 | pMenuText[nNumMenuItems++] = "Mode"; |
| 2327 | pMenuText[nNumMenuItems++] = "Groups"; | 2328 | pMenuText[nNumMenuItems++] = "Groups"; |
| @@ -2409,7 +2410,7 @@ inline void MicroProfileDrawMenu(uint32_t nWidth, uint32_t nHeight) | |||
| 2409 | }; | 2410 | }; |
| 2410 | 2411 | ||
| 2411 | 2412 | ||
| 2412 | uint32_t nSelectMenu = (uint32_t)-1; | 2413 | uint32_t nSelectMenu = UINT32_MAX; |
| 2413 | for(uint32_t i = 0; i < nNumMenuItems; ++i) | 2414 | for(uint32_t i = 0; i < nNumMenuItems; ++i) |
| 2414 | { | 2415 | { |
| 2415 | nMenuX[i] = nX; | 2416 | nMenuX[i] = nX; |
| @@ -2419,17 +2420,17 @@ inline void MicroProfileDrawMenu(uint32_t nWidth, uint32_t nHeight) | |||
| 2419 | { | 2420 | { |
| 2420 | MicroProfileDrawBox(nX-1, nY, nX + nLen * (MICROPROFILE_TEXT_WIDTH+1), nY +(MICROPROFILE_TEXT_HEIGHT+1)+1, 0xff888888); | 2421 | MicroProfileDrawBox(nX-1, nY, nX + nLen * (MICROPROFILE_TEXT_WIDTH+1), nY +(MICROPROFILE_TEXT_HEIGHT+1)+1, 0xff888888); |
| 2421 | nSelectMenu = i; | 2422 | nSelectMenu = i; |
| 2422 | if((UI.nMouseLeft || UI.nMouseRight) && i == (int)nPauseIndex) | 2423 | if((UI.nMouseLeft || UI.nMouseRight) && i == (uint32_t)nPauseIndex) |
| 2423 | { | 2424 | { |
| 2424 | S.nToggleRunning = 1; | 2425 | S.nToggleRunning = 1; |
| 2425 | } | 2426 | } |
| 2426 | } | 2427 | } |
| 2427 | MicroProfileDrawText(nX, nY, (uint32_t)-1, pMenuText[i], (uint32_t)strlen(pMenuText[i])); | 2428 | MicroProfileDrawText(nX, nY, UINT32_MAX, pMenuText[i], (uint32_t)strlen(pMenuText[i])); |
| 2428 | nX += (nLen+1) * (MICROPROFILE_TEXT_WIDTH+1); | 2429 | nX += (nLen+1) * (MICROPROFILE_TEXT_WIDTH+1); |
| 2429 | } | 2430 | } |
| 2430 | uint32_t nMenu = nSelectMenu != (uint32_t)-1 ? nSelectMenu : UI.nActiveMenu; | 2431 | uint32_t nMenu = nSelectMenu != UINT32_MAX ? nSelectMenu : UI.nActiveMenu; |
| 2431 | UI.nActiveMenu = nMenu; | 2432 | UI.nActiveMenu = nMenu; |
| 2432 | if((uint32_t)-1 != nMenu) | 2433 | if(UINT32_MAX != nMenu) |
| 2433 | { | 2434 | { |
| 2434 | nX = nMenuX[nMenu]; | 2435 | nX = nMenuX[nMenu]; |
| 2435 | nY += MICROPROFILE_TEXT_HEIGHT+1; | 2436 | nY += MICROPROFILE_TEXT_HEIGHT+1; |
| @@ -2450,9 +2451,9 @@ inline void MicroProfileDrawMenu(uint32_t nWidth, uint32_t nHeight) | |||
| 2450 | { | 2451 | { |
| 2451 | UI.nActiveMenu = nMenu; | 2452 | UI.nActiveMenu = nMenu; |
| 2452 | } | 2453 | } |
| 2453 | else if(nSelectMenu == (uint32_t)-1) | 2454 | else if(nSelectMenu == UINT32_MAX) |
| 2454 | { | 2455 | { |
| 2455 | UI.nActiveMenu = (uint32_t)-1; | 2456 | UI.nActiveMenu = UINT32_MAX; |
| 2456 | } | 2457 | } |
| 2457 | MicroProfileDrawBox(nX, nY, nX + nWidth, nY + nHeight, 0xff000000|g_nMicroProfileBackColors[1]); | 2458 | MicroProfileDrawBox(nX, nY, nX + nWidth, nY + nHeight, 0xff000000|g_nMicroProfileBackColors[1]); |
| 2458 | for(int i = 0; i < nNumLines; ++i) | 2459 | for(int i = 0; i < nNumLines; ++i) |
| @@ -2461,7 +2462,6 @@ inline void MicroProfileDrawMenu(uint32_t nWidth, uint32_t nHeight) | |||
| 2461 | const char* pString = CB(i, &bSelected); | 2462 | const char* pString = CB(i, &bSelected); |
| 2462 | if(UI.nMouseY >= nY && UI.nMouseY < nY + MICROPROFILE_TEXT_HEIGHT + 1) | 2463 | if(UI.nMouseY >= nY && UI.nMouseY < nY + MICROPROFILE_TEXT_HEIGHT + 1) |
| 2463 | { | 2464 | { |
| 2464 | bMouseOver = true; | ||
| 2465 | if(UI.nMouseLeft || UI.nMouseRight) | 2465 | if(UI.nMouseLeft || UI.nMouseRight) |
| 2466 | { | 2466 | { |
| 2467 | CBClick[nMenu](i); | 2467 | CBClick[nMenu](i); |
| @@ -2469,7 +2469,7 @@ inline void MicroProfileDrawMenu(uint32_t nWidth, uint32_t nHeight) | |||
| 2469 | MicroProfileDrawBox(nX, nY, nX + nWidth, nY + MICROPROFILE_TEXT_HEIGHT + 1, 0xff888888); | 2469 | MicroProfileDrawBox(nX, nY, nX + nWidth, nY + MICROPROFILE_TEXT_HEIGHT + 1, 0xff888888); |
| 2470 | } | 2470 | } |
| 2471 | int nLen = snprintf(buffer, SBUF_SIZE-1, "%c %s", bSelected ? '*' : ' ' ,pString); | 2471 | int nLen = snprintf(buffer, SBUF_SIZE-1, "%c %s", bSelected ? '*' : ' ' ,pString); |
| 2472 | MicroProfileDrawText(nX, nY, (uint32_t)-1, buffer, nLen); | 2472 | MicroProfileDrawText(nX, nY, UINT32_MAX, buffer, nLen); |
| 2473 | nY += MICROPROFILE_TEXT_HEIGHT+1; | 2473 | nY += MICROPROFILE_TEXT_HEIGHT+1; |
| 2474 | } | 2474 | } |
| 2475 | } | 2475 | } |
| @@ -2484,7 +2484,7 @@ inline void MicroProfileDrawMenu(uint32_t nWidth, uint32_t nHeight) | |||
| 2484 | float fMaxMs = fToMs * S.nFlipMaxDisplay; | 2484 | float fMaxMs = fToMs * S.nFlipMaxDisplay; |
| 2485 | int nLen = snprintf(FrameTimeMessage, sizeof(FrameTimeMessage)-1, "Time[%6.2f] Avg[%6.2f] Max[%6.2f]", fMs, fAverageMs, fMaxMs); | 2485 | int nLen = snprintf(FrameTimeMessage, sizeof(FrameTimeMessage)-1, "Time[%6.2f] Avg[%6.2f] Max[%6.2f]", fMs, fAverageMs, fMaxMs); |
| 2486 | pMenuText[nNumMenuItems++] = &FrameTimeMessage[0]; | 2486 | pMenuText[nNumMenuItems++] = &FrameTimeMessage[0]; |
| 2487 | MicroProfileDrawText(nWidth - nLen * (MICROPROFILE_TEXT_WIDTH+1), 0, -1, FrameTimeMessage, nLen); | 2487 | MicroProfileDrawText(nWidth - nLen * (MICROPROFILE_TEXT_WIDTH+1), 0, UINT32_MAX, FrameTimeMessage, nLen); |
| 2488 | } | 2488 | } |
| 2489 | } | 2489 | } |
| 2490 | 2490 | ||
| @@ -2538,7 +2538,7 @@ inline void MicroProfileMoveGraph() | |||
| 2538 | 2538 | ||
| 2539 | inline void MicroProfileDrawCustom(uint32_t nWidth, uint32_t nHeight) | 2539 | inline void MicroProfileDrawCustom(uint32_t nWidth, uint32_t nHeight) |
| 2540 | { | 2540 | { |
| 2541 | if((uint32_t)-1 != UI.nCustomActive) | 2541 | if(UINT32_MAX != UI.nCustomActive) |
| 2542 | { | 2542 | { |
| 2543 | MicroProfile& S = *MicroProfileGet(); | 2543 | MicroProfile& S = *MicroProfileGet(); |
| 2544 | MP_ASSERT(UI.nCustomActive < MICROPROFILE_CUSTOM_MAX); | 2544 | MP_ASSERT(UI.nCustomActive < MICROPROFILE_CUSTOM_MAX); |
| @@ -2571,8 +2571,8 @@ inline void MicroProfileDrawCustom(uint32_t nWidth, uint32_t nHeight) | |||
| 2571 | pColors[i] = S.TimerInfo[nTimerIndex].nColor; | 2571 | pColors[i] = S.TimerInfo[nTimerIndex].nColor; |
| 2572 | } | 2572 | } |
| 2573 | 2573 | ||
| 2574 | MicroProfileDrawText(MICROPROFILE_CUSTOM_PADDING + 3*MICROPROFILE_TEXT_WIDTH, nOffsetY, (uint32_t)-1, "Avg", sizeof("Avg")-1); | 2574 | MicroProfileDrawText(MICROPROFILE_CUSTOM_PADDING + 3*MICROPROFILE_TEXT_WIDTH, nOffsetY, UINT32_MAX, "Avg", sizeof("Avg")-1); |
| 2575 | MicroProfileDrawText(MICROPROFILE_CUSTOM_PADDING + 13*MICROPROFILE_TEXT_WIDTH, nOffsetY, (uint32_t)-1, "Max", sizeof("Max")-1); | 2575 | MicroProfileDrawText(MICROPROFILE_CUSTOM_PADDING + 13*MICROPROFILE_TEXT_WIDTH, nOffsetY, UINT32_MAX, "Max", sizeof("Max")-1); |
| 2576 | for(uint32_t i = 0; i < nCount; ++i) | 2576 | for(uint32_t i = 0; i < nCount; ++i) |
| 2577 | { | 2577 | { |
| 2578 | nOffsetY += (1+MICROPROFILE_TEXT_HEIGHT); | 2578 | nOffsetY += (1+MICROPROFILE_TEXT_HEIGHT); |
| @@ -2582,10 +2582,10 @@ inline void MicroProfileDrawCustom(uint32_t nWidth, uint32_t nHeight) | |||
| 2582 | int nSize; | 2582 | int nSize; |
| 2583 | uint32_t nOffsetX = MICROPROFILE_CUSTOM_PADDING; | 2583 | uint32_t nOffsetX = MICROPROFILE_CUSTOM_PADDING; |
| 2584 | nSize = snprintf(Buffer, sizeof(Buffer)-1, "%6.2f", pTimeAvg[i]); | 2584 | nSize = snprintf(Buffer, sizeof(Buffer)-1, "%6.2f", pTimeAvg[i]); |
| 2585 | MicroProfileDrawText(nOffsetX, nOffsetY, (uint32_t)-1, Buffer, nSize); | 2585 | MicroProfileDrawText(nOffsetX, nOffsetY, UINT32_MAX, Buffer, nSize); |
| 2586 | nOffsetX += (nSize+2) * (MICROPROFILE_TEXT_WIDTH+1); | 2586 | nOffsetX += (nSize+2) * (MICROPROFILE_TEXT_WIDTH+1); |
| 2587 | nSize = snprintf(Buffer, sizeof(Buffer)-1, "%6.2f", pTimeMax[i]); | 2587 | nSize = snprintf(Buffer, sizeof(Buffer)-1, "%6.2f", pTimeMax[i]); |
| 2588 | MicroProfileDrawText(nOffsetX, nOffsetY, (uint32_t)-1, Buffer, nSize); | 2588 | MicroProfileDrawText(nOffsetX, nOffsetY, UINT32_MAX, Buffer, nSize); |
| 2589 | nOffsetX += (nSize+2) * (MICROPROFILE_TEXT_WIDTH+1); | 2589 | nOffsetX += (nSize+2) * (MICROPROFILE_TEXT_WIDTH+1); |
| 2590 | nSize = snprintf(Buffer, sizeof(Buffer)-1, "%s:%s", S.GroupInfo[nGroupIndex].pName, pTimerInfo->pName); | 2590 | nSize = snprintf(Buffer, sizeof(Buffer)-1, "%s:%s", S.GroupInfo[nGroupIndex].pName, pTimerInfo->pName); |
| 2591 | MicroProfileDrawText(nOffsetX, nOffsetY, pTimerInfo->nColor, Buffer, nSize); | 2591 | MicroProfileDrawText(nOffsetX, nOffsetY, pTimerInfo->nColor, Buffer, nSize); |
| @@ -2599,9 +2599,9 @@ inline void MicroProfileDrawCustom(uint32_t nWidth, uint32_t nHeight) | |||
| 2599 | nOffsetY = nOffsetYBase; | 2599 | nOffsetY = nOffsetYBase; |
| 2600 | float* pMs = pCustom->nFlags & MICROPROFILE_CUSTOM_BAR_SOURCE_MAX ? pTimeMax : pTimeAvg; | 2600 | float* pMs = pCustom->nFlags & MICROPROFILE_CUSTOM_BAR_SOURCE_MAX ? pTimeMax : pTimeAvg; |
| 2601 | const char* pString = pCustom->nFlags & MICROPROFILE_CUSTOM_BAR_SOURCE_MAX ? "Max" : "Avg"; | 2601 | const char* pString = pCustom->nFlags & MICROPROFILE_CUSTOM_BAR_SOURCE_MAX ? "Max" : "Avg"; |
| 2602 | MicroProfileDrawText(nMaxOffsetX, nOffsetY, (uint32_t)-1, pString, static_cast<uint32_t>(strlen(pString))); | 2602 | MicroProfileDrawText(nMaxOffsetX, nOffsetY, UINT32_MAX, pString, static_cast<uint32_t>(strlen(pString))); |
| 2603 | int nSize = snprintf(Buffer, sizeof(Buffer)-1, "%6.2fms", fReference); | 2603 | int nSize = snprintf(Buffer, sizeof(Buffer)-1, "%6.2fms", fReference); |
| 2604 | MicroProfileDrawText(nReducedWidth - (1+nSize) * (MICROPROFILE_TEXT_WIDTH+1), nOffsetY, (uint32_t)-1, Buffer, nSize); | 2604 | MicroProfileDrawText(nReducedWidth - (1+nSize) * (MICROPROFILE_TEXT_WIDTH+1), nOffsetY, UINT32_MAX, Buffer, nSize); |
| 2605 | for(uint32_t i = 0; i < nCount; ++i) | 2605 | for(uint32_t i = 0; i < nCount; ++i) |
| 2606 | { | 2606 | { |
| 2607 | nOffsetY += (1+MICROPROFILE_TEXT_HEIGHT); | 2607 | nOffsetY += (1+MICROPROFILE_TEXT_HEIGHT); |
| @@ -2613,9 +2613,9 @@ inline void MicroProfileDrawCustom(uint32_t nWidth, uint32_t nHeight) | |||
| 2613 | { | 2613 | { |
| 2614 | nOffsetY += 2*(1+MICROPROFILE_TEXT_HEIGHT); | 2614 | nOffsetY += 2*(1+MICROPROFILE_TEXT_HEIGHT); |
| 2615 | const char* pString = pCustom->nFlags & MICROPROFILE_CUSTOM_STACK_SOURCE_MAX ? "Max" : "Avg"; | 2615 | const char* pString = pCustom->nFlags & MICROPROFILE_CUSTOM_STACK_SOURCE_MAX ? "Max" : "Avg"; |
| 2616 | MicroProfileDrawText(MICROPROFILE_CUSTOM_PADDING, nOffsetY, (uint32_t)-1, pString, static_cast<uint32_t>(strlen(pString))); | 2616 | MicroProfileDrawText(MICROPROFILE_CUSTOM_PADDING, nOffsetY, UINT32_MAX, pString, static_cast<uint32_t>(strlen(pString))); |
| 2617 | int nSize = snprintf(Buffer, sizeof(Buffer)-1, "%6.2fms", fReference); | 2617 | int nSize = snprintf(Buffer, sizeof(Buffer)-1, "%6.2fms", fReference); |
| 2618 | MicroProfileDrawText(nReducedWidth - (1+nSize) * (MICROPROFILE_TEXT_WIDTH+1), nOffsetY, (uint32_t)-1, Buffer, nSize); | 2618 | MicroProfileDrawText(nReducedWidth - (1+nSize) * (MICROPROFILE_TEXT_WIDTH+1), nOffsetY, UINT32_MAX, Buffer, nSize); |
| 2619 | nOffsetY += (1+MICROPROFILE_TEXT_HEIGHT); | 2619 | nOffsetY += (1+MICROPROFILE_TEXT_HEIGHT); |
| 2620 | float fPosX = MICROPROFILE_CUSTOM_PADDING; | 2620 | float fPosX = MICROPROFILE_CUSTOM_PADDING; |
| 2621 | float* pMs = pCustom->nFlags & MICROPROFILE_CUSTOM_STACK_SOURCE_MAX ? pTimeMax : pTimeAvg; | 2621 | float* pMs = pCustom->nFlags & MICROPROFILE_CUSTOM_STACK_SOURCE_MAX ? pTimeMax : pTimeAvg; |
| @@ -2668,7 +2668,7 @@ inline void MicroProfileDraw(uint32_t nWidth, uint32_t nHeight) | |||
| 2668 | UI.nHoverTime = 0; | 2668 | UI.nHoverTime = 0; |
| 2669 | UI.nHoverFrame = -1; | 2669 | UI.nHoverFrame = -1; |
| 2670 | if(S.nDisplay != MP_DRAW_DETAILED) | 2670 | if(S.nDisplay != MP_DRAW_DETAILED) |
| 2671 | S.nContextSwitchHoverThread = S.nContextSwitchHoverThreadAfter = S.nContextSwitchHoverThreadBefore = -1; | 2671 | S.nContextSwitchHoverThread = S.nContextSwitchHoverThreadAfter = S.nContextSwitchHoverThreadBefore = UINT32_MAX; |
| 2672 | MicroProfileMoveGraph(); | 2672 | MicroProfileMoveGraph(); |
| 2673 | 2673 | ||
| 2674 | 2674 | ||
| @@ -2798,13 +2798,13 @@ inline void MicroProfileDraw(uint32_t nWidth, uint32_t nHeight) | |||
| 2798 | 2798 | ||
| 2799 | 2799 | ||
| 2800 | 2800 | ||
| 2801 | if(UI.nActiveMenu == -1 && !bMouseOverGraph) | 2801 | if(UI.nActiveMenu == UINT32_MAX && !bMouseOverGraph) |
| 2802 | { | 2802 | { |
| 2803 | if(UI.nHoverToken != MICROPROFILE_INVALID_TOKEN) | 2803 | if(UI.nHoverToken != MICROPROFILE_INVALID_TOKEN) |
| 2804 | { | 2804 | { |
| 2805 | MicroProfileDrawFloatTooltip(UI.nMouseX, UI.nMouseY, UI.nHoverToken, UI.nHoverTime); | 2805 | MicroProfileDrawFloatTooltip(UI.nMouseX, UI.nMouseY, UI.nHoverToken, UI.nHoverTime); |
| 2806 | } | 2806 | } |
| 2807 | else if(S.nContextSwitchHoverThreadAfter != -1 && S.nContextSwitchHoverThreadBefore != -1) | 2807 | else if(S.nContextSwitchHoverThreadAfter != UINT32_MAX && S.nContextSwitchHoverThreadBefore != UINT32_MAX) |
| 2808 | { | 2808 | { |
| 2809 | float fToMs = MicroProfileTickToMsMultiplier(MicroProfileTicksPerSecondCpu()); | 2809 | float fToMs = MicroProfileTickToMsMultiplier(MicroProfileTicksPerSecondCpu()); |
| 2810 | MicroProfileStringArray ToolTip; | 2810 | MicroProfileStringArray ToolTip; |
| @@ -2820,7 +2820,7 @@ inline void MicroProfileDraw(uint32_t nWidth, uint32_t nHeight) | |||
| 2820 | MicroProfileStringArrayFormat(&ToolTip, "%6.2fms", fToMs * nDifference ); | 2820 | MicroProfileStringArrayFormat(&ToolTip, "%6.2fms", fToMs * nDifference ); |
| 2821 | MicroProfileStringArrayAddLiteral(&ToolTip, "CPU"); | 2821 | MicroProfileStringArrayAddLiteral(&ToolTip, "CPU"); |
| 2822 | MicroProfileStringArrayFormat(&ToolTip, "%d", S.nContextSwitchHoverCpu); | 2822 | MicroProfileStringArrayFormat(&ToolTip, "%d", S.nContextSwitchHoverCpu); |
| 2823 | MicroProfileDrawFloatWindow(UI.nMouseX, UI.nMouseY+20, &ToolTip.ppStrings[0], ToolTip.nNumStrings, -1); | 2823 | MicroProfileDrawFloatWindow(UI.nMouseX, UI.nMouseY+20, &ToolTip.ppStrings[0], ToolTip.nNumStrings, UINT32_MAX); |
| 2824 | 2824 | ||
| 2825 | 2825 | ||
| 2826 | } | 2826 | } |
| @@ -2858,7 +2858,7 @@ inline void MicroProfileDraw(uint32_t nWidth, uint32_t nHeight) | |||
| 2858 | } | 2858 | } |
| 2859 | } | 2859 | } |
| 2860 | #endif | 2860 | #endif |
| 2861 | MicroProfileDrawFloatWindow(UI.nMouseX, UI.nMouseY+20, &ToolTip.ppStrings[0], ToolTip.nNumStrings, -1); | 2861 | MicroProfileDrawFloatWindow(UI.nMouseX, UI.nMouseY+20, &ToolTip.ppStrings[0], ToolTip.nNumStrings, UINT32_MAX); |
| 2862 | } | 2862 | } |
| 2863 | if(UI.nMouseLeft) | 2863 | if(UI.nMouseLeft) |
| 2864 | { | 2864 | { |
| @@ -2883,7 +2883,7 @@ inline void MicroProfileDraw(uint32_t nWidth, uint32_t nHeight) | |||
| 2883 | #endif | 2883 | #endif |
| 2884 | m.unlock(); | 2884 | m.unlock(); |
| 2885 | } | 2885 | } |
| 2886 | else if(UI.nCustomActive != (uint32_t)-1) | 2886 | else if(UI.nCustomActive != UINT32_MAX) |
| 2887 | { | 2887 | { |
| 2888 | std::recursive_mutex& m = MicroProfileGetMutex(); | 2888 | std::recursive_mutex& m = MicroProfileGetMutex(); |
| 2889 | m.lock(); | 2889 | m.lock(); |
| @@ -3179,7 +3179,7 @@ void MicroProfileLoadPreset(const char* pSuffix) | |||
| 3179 | { | 3179 | { |
| 3180 | if(0 == MP_STRCASECMP(pGroupName, S.GroupInfo[j].pName)) | 3180 | if(0 == MP_STRCASECMP(pGroupName, S.GroupInfo[j].pName)) |
| 3181 | { | 3181 | { |
| 3182 | S.nActiveGroupWanted |= (1ll << j); | 3182 | S.nActiveGroupWanted |= (1ULL << j); |
| 3183 | } | 3183 | } |
| 3184 | } | 3184 | } |
| 3185 | } | 3185 | } |
| @@ -3212,7 +3212,7 @@ void MicroProfileLoadPreset(const char* pSuffix) | |||
| 3212 | uint64_t nGroupIndex = S.TimerInfo[j].nGroupIndex; | 3212 | uint64_t nGroupIndex = S.TimerInfo[j].nGroupIndex; |
| 3213 | if(0 == MP_STRCASECMP(pGraphName, S.TimerInfo[j].pName) && 0 == MP_STRCASECMP(pGraphGroupName, S.GroupInfo[nGroupIndex].pName)) | 3213 | if(0 == MP_STRCASECMP(pGraphName, S.TimerInfo[j].pName) && 0 == MP_STRCASECMP(pGraphGroupName, S.GroupInfo[nGroupIndex].pName)) |
| 3214 | { | 3214 | { |
| 3215 | MicroProfileToken nToken = MicroProfileMakeToken(1ll << nGroupIndex, (uint16_t)j); | 3215 | MicroProfileToken nToken = MicroProfileMakeToken(1ULL << nGroupIndex, (uint16_t)j); |
| 3216 | S.Graph[i].nToken = nToken; // note: group index is stored here but is checked without in MicroProfileToggleGraph()! | 3216 | S.Graph[i].nToken = nToken; // note: group index is stored here but is checked without in MicroProfileToggleGraph()! |
| 3217 | S.TimerInfo[j].bGraph = true; | 3217 | S.TimerInfo[j].bGraph = true; |
| 3218 | if(nToken != nPrevToken) | 3218 | if(nToken != nPrevToken) |
| @@ -3235,7 +3235,7 @@ inline uint32_t MicroProfileCustomGroupFind(const char* pCustomName) | |||
| 3235 | return i; | 3235 | return i; |
| 3236 | } | 3236 | } |
| 3237 | } | 3237 | } |
| 3238 | return (uint32_t)-1; | 3238 | return UINT32_MAX; |
| 3239 | } | 3239 | } |
| 3240 | 3240 | ||
| 3241 | inline uint32_t MicroProfileCustomGroup(const char* pCustomName) | 3241 | inline uint32_t MicroProfileCustomGroup(const char* pCustomName) |
| @@ -3251,7 +3251,7 @@ inline uint32_t MicroProfileCustomGroup(const char* pCustomName) | |||
| 3251 | uint32_t nIndex = UI.nCustomCount; | 3251 | uint32_t nIndex = UI.nCustomCount; |
| 3252 | UI.nCustomCount++; | 3252 | UI.nCustomCount++; |
| 3253 | memset(&UI.Custom[nIndex], 0, sizeof(UI.Custom[nIndex])); | 3253 | memset(&UI.Custom[nIndex], 0, sizeof(UI.Custom[nIndex])); |
| 3254 | uint32_t nLen = (uint32_t)strlen(pCustomName); | 3254 | size_t nLen = strlen(pCustomName); |
| 3255 | if(nLen > MICROPROFILE_NAME_MAX_LEN-1) | 3255 | if(nLen > MICROPROFILE_NAME_MAX_LEN-1) |
| 3256 | nLen = MICROPROFILE_NAME_MAX_LEN-1; | 3256 | nLen = MICROPROFILE_NAME_MAX_LEN-1; |
| 3257 | memcpy(&UI.Custom[nIndex].pName[0], pCustomName, nLen); | 3257 | memcpy(&UI.Custom[nIndex].pName[0], pCustomName, nLen); |
| @@ -3309,7 +3309,7 @@ inline void MicroProfileCustomGroupEnable(uint32_t nIndex) | |||
| 3309 | void MicroProfileCustomGroupToggle(const char* pCustomName) | 3309 | void MicroProfileCustomGroupToggle(const char* pCustomName) |
| 3310 | { | 3310 | { |
| 3311 | uint32_t nIndex = MicroProfileCustomGroupFind(pCustomName); | 3311 | uint32_t nIndex = MicroProfileCustomGroupFind(pCustomName); |
| 3312 | if(nIndex == (uint32_t)-1 || nIndex == UI.nCustomActive) | 3312 | if(nIndex == UINT32_MAX || nIndex == UI.nCustomActive) |
| 3313 | { | 3313 | { |
| 3314 | MicroProfileCustomGroupDisable(); | 3314 | MicroProfileCustomGroupDisable(); |
| 3315 | } | 3315 | } |
| @@ -3328,13 +3328,13 @@ void MicroProfileCustomGroupDisable() | |||
| 3328 | { | 3328 | { |
| 3329 | MicroProfile& S = *MicroProfileGet(); | 3329 | MicroProfile& S = *MicroProfileGet(); |
| 3330 | S.nForceGroupUI = 0; | 3330 | S.nForceGroupUI = 0; |
| 3331 | UI.nCustomActive = (uint32_t)-1; | 3331 | UI.nCustomActive = UINT32_MAX; |
| 3332 | } | 3332 | } |
| 3333 | 3333 | ||
| 3334 | void MicroProfileCustomGroupAddTimer(const char* pCustomName, const char* pGroup, const char* pTimer) | 3334 | void MicroProfileCustomGroupAddTimer(const char* pCustomName, const char* pGroup, const char* pTimer) |
| 3335 | { | 3335 | { |
| 3336 | uint32_t nIndex = MicroProfileCustomGroupFind(pCustomName); | 3336 | uint32_t nIndex = MicroProfileCustomGroupFind(pCustomName); |
| 3337 | if((uint32_t)-1 == nIndex) | 3337 | if(UINT32_MAX == nIndex) |
| 3338 | { | 3338 | { |
| 3339 | return; | 3339 | return; |
| 3340 | } | 3340 | } |
| @@ -3344,7 +3344,7 @@ void MicroProfileCustomGroupAddTimer(const char* pCustomName, const char* pGroup | |||
| 3344 | MP_ASSERT(nToken != MICROPROFILE_INVALID_TOKEN); //Timer must be registered first. | 3344 | MP_ASSERT(nToken != MICROPROFILE_INVALID_TOKEN); //Timer must be registered first. |
| 3345 | UI.Custom[nIndex].pTimers[nTimerIndex] = nToken; | 3345 | UI.Custom[nIndex].pTimers[nTimerIndex] = nToken; |
| 3346 | uint16_t nGroup = MicroProfileGetGroupIndex(nToken); | 3346 | uint16_t nGroup = MicroProfileGetGroupIndex(nToken); |
| 3347 | UI.Custom[nIndex].nGroupMask |= (1ll << nGroup); | 3347 | UI.Custom[nIndex].nGroupMask |= (1ULL << nGroup); |
| 3348 | UI.Custom[nIndex].nNumTimers++; | 3348 | UI.Custom[nIndex].nNumTimers++; |
| 3349 | } | 3349 | } |
| 3350 | 3350 | ||
diff --git a/externals/xbyak b/externals/xbyak | |||
| Subproject 82b70e665918efc2ee348091742fd0237b3b68c | Subproject 18c9caaa0a3ed5706c39f5aa86cce0db6e65b17 | ||
diff --git a/src/audio_core/cubeb_sink.cpp b/src/audio_core/cubeb_sink.cpp index 41bf5cd4d..c27df946c 100644 --- a/src/audio_core/cubeb_sink.cpp +++ b/src/audio_core/cubeb_sink.cpp | |||
| @@ -78,7 +78,7 @@ public: | |||
| 78 | const s16 surround_left{samples[i + 4]}; | 78 | const s16 surround_left{samples[i + 4]}; |
| 79 | const s16 surround_right{samples[i + 5]}; | 79 | const s16 surround_right{samples[i + 5]}; |
| 80 | // Not used in the ATSC reference implementation | 80 | // Not used in the ATSC reference implementation |
| 81 | [[maybe_unused]] const s16 low_frequency_effects { samples[i + 3] }; | 81 | [[maybe_unused]] const s16 low_frequency_effects{samples[i + 3]}; |
| 82 | 82 | ||
| 83 | constexpr s32 clev{707}; // center mixing level coefficient | 83 | constexpr s32 clev{707}; // center mixing level coefficient |
| 84 | constexpr s32 slev{707}; // surround mixing level coefficient | 84 | constexpr s32 slev{707}; // surround mixing level coefficient |
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 78c3bfb3b..5d54516eb 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt | |||
| @@ -172,7 +172,6 @@ add_library(common STATIC | |||
| 172 | virtual_buffer.h | 172 | virtual_buffer.h |
| 173 | wall_clock.cpp | 173 | wall_clock.cpp |
| 174 | wall_clock.h | 174 | wall_clock.h |
| 175 | web_result.h | ||
| 176 | zstd_compression.cpp | 175 | zstd_compression.cpp |
| 177 | zstd_compression.h | 176 | zstd_compression.h |
| 178 | ) | 177 | ) |
diff --git a/src/common/algorithm.h b/src/common/algorithm.h index e21b1373c..4804a3421 100644 --- a/src/common/algorithm.h +++ b/src/common/algorithm.h | |||
| @@ -15,7 +15,8 @@ | |||
| 15 | namespace Common { | 15 | namespace Common { |
| 16 | 16 | ||
| 17 | template <class ForwardIt, class T, class Compare = std::less<>> | 17 | template <class ForwardIt, class T, class Compare = std::less<>> |
| 18 | ForwardIt BinaryFind(ForwardIt first, ForwardIt last, const T& value, Compare comp = {}) { | 18 | [[nodiscard]] ForwardIt BinaryFind(ForwardIt first, ForwardIt last, const T& value, |
| 19 | Compare comp = {}) { | ||
| 19 | // Note: BOTH type T and the type after ForwardIt is dereferenced | 20 | // Note: BOTH type T and the type after ForwardIt is dereferenced |
| 20 | // must be implicitly convertible to BOTH Type1 and Type2, used in Compare. | 21 | // must be implicitly convertible to BOTH Type1 and Type2, used in Compare. |
| 21 | // This is stricter than lower_bound requirement (see above) | 22 | // This is stricter than lower_bound requirement (see above) |
diff --git a/src/common/alignment.h b/src/common/alignment.h index ef4d6f896..5040043de 100644 --- a/src/common/alignment.h +++ b/src/common/alignment.h | |||
| @@ -9,7 +9,7 @@ | |||
| 9 | namespace Common { | 9 | namespace Common { |
| 10 | 10 | ||
| 11 | template <typename T> | 11 | template <typename T> |
| 12 | constexpr T AlignUp(T value, std::size_t size) { | 12 | [[nodiscard]] constexpr T AlignUp(T value, std::size_t size) { |
| 13 | static_assert(std::is_unsigned_v<T>, "T must be an unsigned value."); | 13 | static_assert(std::is_unsigned_v<T>, "T must be an unsigned value."); |
| 14 | auto mod{static_cast<T>(value % size)}; | 14 | auto mod{static_cast<T>(value % size)}; |
| 15 | value -= mod; | 15 | value -= mod; |
| @@ -17,31 +17,31 @@ constexpr T AlignUp(T value, std::size_t size) { | |||
| 17 | } | 17 | } |
| 18 | 18 | ||
| 19 | template <typename T> | 19 | template <typename T> |
| 20 | constexpr T AlignDown(T value, std::size_t size) { | 20 | [[nodiscard]] constexpr T AlignDown(T value, std::size_t size) { |
| 21 | static_assert(std::is_unsigned_v<T>, "T must be an unsigned value."); | 21 | static_assert(std::is_unsigned_v<T>, "T must be an unsigned value."); |
| 22 | return static_cast<T>(value - value % size); | 22 | return static_cast<T>(value - value % size); |
| 23 | } | 23 | } |
| 24 | 24 | ||
| 25 | template <typename T> | 25 | template <typename T> |
| 26 | constexpr T AlignBits(T value, std::size_t align) { | 26 | [[nodiscard]] constexpr T AlignBits(T value, std::size_t align) { |
| 27 | static_assert(std::is_unsigned_v<T>, "T must be an unsigned value."); | 27 | static_assert(std::is_unsigned_v<T>, "T must be an unsigned value."); |
| 28 | return static_cast<T>((value + ((1ULL << align) - 1)) >> align << align); | 28 | return static_cast<T>((value + ((1ULL << align) - 1)) >> align << align); |
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | template <typename T> | 31 | template <typename T> |
| 32 | constexpr bool Is4KBAligned(T value) { | 32 | [[nodiscard]] constexpr bool Is4KBAligned(T value) { |
| 33 | static_assert(std::is_unsigned_v<T>, "T must be an unsigned value."); | 33 | static_assert(std::is_unsigned_v<T>, "T must be an unsigned value."); |
| 34 | return (value & 0xFFF) == 0; | 34 | return (value & 0xFFF) == 0; |
| 35 | } | 35 | } |
| 36 | 36 | ||
| 37 | template <typename T> | 37 | template <typename T> |
| 38 | constexpr bool IsWordAligned(T value) { | 38 | [[nodiscard]] constexpr bool IsWordAligned(T value) { |
| 39 | static_assert(std::is_unsigned_v<T>, "T must be an unsigned value."); | 39 | static_assert(std::is_unsigned_v<T>, "T must be an unsigned value."); |
| 40 | return (value & 0b11) == 0; | 40 | return (value & 0b11) == 0; |
| 41 | } | 41 | } |
| 42 | 42 | ||
| 43 | template <typename T> | 43 | template <typename T> |
| 44 | constexpr bool IsAligned(T value, std::size_t alignment) { | 44 | [[nodiscard]] constexpr bool IsAligned(T value, std::size_t alignment) { |
| 45 | using U = typename std::make_unsigned<T>::type; | 45 | using U = typename std::make_unsigned<T>::type; |
| 46 | const U mask = static_cast<U>(alignment - 1); | 46 | const U mask = static_cast<U>(alignment - 1); |
| 47 | return (value & mask) == 0; | 47 | return (value & mask) == 0; |
| @@ -64,7 +64,7 @@ public: | |||
| 64 | template <typename T2> | 64 | template <typename T2> |
| 65 | constexpr AlignmentAllocator(const AlignmentAllocator<T2, Align>&) noexcept {} | 65 | constexpr AlignmentAllocator(const AlignmentAllocator<T2, Align>&) noexcept {} |
| 66 | 66 | ||
| 67 | T* allocate(size_type n) { | 67 | [[nodiscard]] T* allocate(size_type n) { |
| 68 | return static_cast<T*>(::operator new (n * sizeof(T), std::align_val_t{Align})); | 68 | return static_cast<T*>(::operator new (n * sizeof(T), std::align_val_t{Align})); |
| 69 | } | 69 | } |
| 70 | 70 | ||
diff --git a/src/common/assert.h b/src/common/assert.h index 5b67c5c52..06d7b5612 100644 --- a/src/common/assert.h +++ b/src/common/assert.h | |||
| @@ -17,11 +17,12 @@ | |||
| 17 | // enough for our purposes. | 17 | // enough for our purposes. |
| 18 | template <typename Fn> | 18 | template <typename Fn> |
| 19 | #if defined(_MSC_VER) | 19 | #if defined(_MSC_VER) |
| 20 | __declspec(noinline, noreturn) | 20 | [[msvc::noinline, noreturn]] |
| 21 | #elif defined(__GNUC__) | 21 | #elif defined(__GNUC__) |
| 22 | __attribute__((noinline, noreturn, cold)) | 22 | [[gnu::cold, gnu::noinline, noreturn]] |
| 23 | #endif | 23 | #endif |
| 24 | static void assert_noinline_call(const Fn& fn) { | 24 | static void |
| 25 | assert_noinline_call(const Fn& fn) { | ||
| 25 | fn(); | 26 | fn(); |
| 26 | Crash(); | 27 | Crash(); |
| 27 | exit(1); // Keeps GCC's mouth shut about this actually returning | 28 | exit(1); // Keeps GCC's mouth shut about this actually returning |
diff --git a/src/common/atomic_ops.h b/src/common/atomic_ops.h index 8d6b73c00..b46888589 100644 --- a/src/common/atomic_ops.h +++ b/src/common/atomic_ops.h | |||
| @@ -8,10 +8,10 @@ | |||
| 8 | 8 | ||
| 9 | namespace Common { | 9 | namespace Common { |
| 10 | 10 | ||
| 11 | bool AtomicCompareAndSwap(volatile u8* pointer, u8 value, u8 expected); | 11 | [[nodiscard]] bool AtomicCompareAndSwap(volatile u8* pointer, u8 value, u8 expected); |
| 12 | bool AtomicCompareAndSwap(volatile u16* pointer, u16 value, u16 expected); | 12 | [[nodiscard]] bool AtomicCompareAndSwap(volatile u16* pointer, u16 value, u16 expected); |
| 13 | bool AtomicCompareAndSwap(volatile u32* pointer, u32 value, u32 expected); | 13 | [[nodiscard]] bool AtomicCompareAndSwap(volatile u32* pointer, u32 value, u32 expected); |
| 14 | bool AtomicCompareAndSwap(volatile u64* pointer, u64 value, u64 expected); | 14 | [[nodiscard]] bool AtomicCompareAndSwap(volatile u64* pointer, u64 value, u64 expected); |
| 15 | bool AtomicCompareAndSwap(volatile u64* pointer, u128 value, u128 expected); | 15 | [[nodiscard]] bool AtomicCompareAndSwap(volatile u64* pointer, u128 value, u128 expected); |
| 16 | 16 | ||
| 17 | } // namespace Common | 17 | } // namespace Common |
diff --git a/src/common/bit_field.h b/src/common/bit_field.h index 26ae6c7fc..0f0661172 100644 --- a/src/common/bit_field.h +++ b/src/common/bit_field.h | |||
| @@ -36,13 +36,6 @@ | |||
| 36 | #include "common/common_funcs.h" | 36 | #include "common/common_funcs.h" |
| 37 | #include "common/swap.h" | 37 | #include "common/swap.h" |
| 38 | 38 | ||
| 39 | // Inlining | ||
| 40 | #ifdef _WIN32 | ||
| 41 | #define FORCE_INLINE __forceinline | ||
| 42 | #else | ||
| 43 | #define FORCE_INLINE inline __attribute__((always_inline)) | ||
| 44 | #endif | ||
| 45 | |||
| 46 | /* | 39 | /* |
| 47 | * Abstract bitfield class | 40 | * Abstract bitfield class |
| 48 | * | 41 | * |
| @@ -142,8 +135,8 @@ public: | |||
| 142 | * containing several bitfields can be assembled by formatting each of their values and ORing | 135 | * containing several bitfields can be assembled by formatting each of their values and ORing |
| 143 | * the results together. | 136 | * the results together. |
| 144 | */ | 137 | */ |
| 145 | static constexpr FORCE_INLINE StorageType FormatValue(const T& value) { | 138 | [[nodiscard]] static constexpr StorageType FormatValue(const T& value) { |
| 146 | return ((StorageType)value << position) & mask; | 139 | return (static_cast<StorageType>(value) << position) & mask; |
| 147 | } | 140 | } |
| 148 | 141 | ||
| 149 | /** | 142 | /** |
| @@ -151,7 +144,7 @@ public: | |||
| 151 | * (such as Value() or operator T), but this can be used to extract a value from a bitfield | 144 | * (such as Value() or operator T), but this can be used to extract a value from a bitfield |
| 152 | * union in a constexpr context. | 145 | * union in a constexpr context. |
| 153 | */ | 146 | */ |
| 154 | static constexpr FORCE_INLINE T ExtractValue(const StorageType& storage) { | 147 | [[nodiscard]] static constexpr T ExtractValue(const StorageType& storage) { |
| 155 | if constexpr (std::numeric_limits<UnderlyingType>::is_signed) { | 148 | if constexpr (std::numeric_limits<UnderlyingType>::is_signed) { |
| 156 | std::size_t shift = 8 * sizeof(T) - bits; | 149 | std::size_t shift = 8 * sizeof(T) - bits; |
| 157 | return static_cast<T>(static_cast<UnderlyingType>(storage << (shift - position)) >> | 150 | return static_cast<T>(static_cast<UnderlyingType>(storage << (shift - position)) >> |
| @@ -175,7 +168,7 @@ public: | |||
| 175 | constexpr BitField(BitField&&) noexcept = default; | 168 | constexpr BitField(BitField&&) noexcept = default; |
| 176 | constexpr BitField& operator=(BitField&&) noexcept = default; | 169 | constexpr BitField& operator=(BitField&&) noexcept = default; |
| 177 | 170 | ||
| 178 | constexpr operator T() const { | 171 | [[nodiscard]] constexpr operator T() const { |
| 179 | return Value(); | 172 | return Value(); |
| 180 | } | 173 | } |
| 181 | 174 | ||
| @@ -183,11 +176,11 @@ public: | |||
| 183 | storage = static_cast<StorageType>((storage & ~mask) | FormatValue(value)); | 176 | storage = static_cast<StorageType>((storage & ~mask) | FormatValue(value)); |
| 184 | } | 177 | } |
| 185 | 178 | ||
| 186 | constexpr T Value() const { | 179 | [[nodiscard]] constexpr T Value() const { |
| 187 | return ExtractValue(storage); | 180 | return ExtractValue(storage); |
| 188 | } | 181 | } |
| 189 | 182 | ||
| 190 | constexpr explicit operator bool() const { | 183 | [[nodiscard]] constexpr explicit operator bool() const { |
| 191 | return Value() != 0; | 184 | return Value() != 0; |
| 192 | } | 185 | } |
| 193 | 186 | ||
diff --git a/src/common/bit_util.h b/src/common/bit_util.h index 6f7d5a947..29f59a9a3 100644 --- a/src/common/bit_util.h +++ b/src/common/bit_util.h | |||
| @@ -17,12 +17,12 @@ namespace Common { | |||
| 17 | 17 | ||
| 18 | /// Gets the size of a specified type T in bits. | 18 | /// Gets the size of a specified type T in bits. |
| 19 | template <typename T> | 19 | template <typename T> |
| 20 | constexpr std::size_t BitSize() { | 20 | [[nodiscard]] constexpr std::size_t BitSize() { |
| 21 | return sizeof(T) * CHAR_BIT; | 21 | return sizeof(T) * CHAR_BIT; |
| 22 | } | 22 | } |
| 23 | 23 | ||
| 24 | #ifdef _MSC_VER | 24 | #ifdef _MSC_VER |
| 25 | inline u32 CountLeadingZeroes32(u32 value) { | 25 | [[nodiscard]] inline u32 CountLeadingZeroes32(u32 value) { |
| 26 | unsigned long leading_zero = 0; | 26 | unsigned long leading_zero = 0; |
| 27 | 27 | ||
| 28 | if (_BitScanReverse(&leading_zero, value) != 0) { | 28 | if (_BitScanReverse(&leading_zero, value) != 0) { |
| @@ -32,7 +32,7 @@ inline u32 CountLeadingZeroes32(u32 value) { | |||
| 32 | return 32; | 32 | return 32; |
| 33 | } | 33 | } |
| 34 | 34 | ||
| 35 | inline u32 CountLeadingZeroes64(u64 value) { | 35 | [[nodiscard]] inline u32 CountLeadingZeroes64(u64 value) { |
| 36 | unsigned long leading_zero = 0; | 36 | unsigned long leading_zero = 0; |
| 37 | 37 | ||
| 38 | if (_BitScanReverse64(&leading_zero, value) != 0) { | 38 | if (_BitScanReverse64(&leading_zero, value) != 0) { |
| @@ -42,7 +42,7 @@ inline u32 CountLeadingZeroes64(u64 value) { | |||
| 42 | return 64; | 42 | return 64; |
| 43 | } | 43 | } |
| 44 | #else | 44 | #else |
| 45 | inline u32 CountLeadingZeroes32(u32 value) { | 45 | [[nodiscard]] inline u32 CountLeadingZeroes32(u32 value) { |
| 46 | if (value == 0) { | 46 | if (value == 0) { |
| 47 | return 32; | 47 | return 32; |
| 48 | } | 48 | } |
| @@ -50,7 +50,7 @@ inline u32 CountLeadingZeroes32(u32 value) { | |||
| 50 | return static_cast<u32>(__builtin_clz(value)); | 50 | return static_cast<u32>(__builtin_clz(value)); |
| 51 | } | 51 | } |
| 52 | 52 | ||
| 53 | inline u32 CountLeadingZeroes64(u64 value) { | 53 | [[nodiscard]] inline u32 CountLeadingZeroes64(u64 value) { |
| 54 | if (value == 0) { | 54 | if (value == 0) { |
| 55 | return 64; | 55 | return 64; |
| 56 | } | 56 | } |
| @@ -60,7 +60,7 @@ inline u32 CountLeadingZeroes64(u64 value) { | |||
| 60 | #endif | 60 | #endif |
| 61 | 61 | ||
| 62 | #ifdef _MSC_VER | 62 | #ifdef _MSC_VER |
| 63 | inline u32 CountTrailingZeroes32(u32 value) { | 63 | [[nodiscard]] inline u32 CountTrailingZeroes32(u32 value) { |
| 64 | unsigned long trailing_zero = 0; | 64 | unsigned long trailing_zero = 0; |
| 65 | 65 | ||
| 66 | if (_BitScanForward(&trailing_zero, value) != 0) { | 66 | if (_BitScanForward(&trailing_zero, value) != 0) { |
| @@ -70,7 +70,7 @@ inline u32 CountTrailingZeroes32(u32 value) { | |||
| 70 | return 32; | 70 | return 32; |
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | inline u32 CountTrailingZeroes64(u64 value) { | 73 | [[nodiscard]] inline u32 CountTrailingZeroes64(u64 value) { |
| 74 | unsigned long trailing_zero = 0; | 74 | unsigned long trailing_zero = 0; |
| 75 | 75 | ||
| 76 | if (_BitScanForward64(&trailing_zero, value) != 0) { | 76 | if (_BitScanForward64(&trailing_zero, value) != 0) { |
| @@ -80,7 +80,7 @@ inline u32 CountTrailingZeroes64(u64 value) { | |||
| 80 | return 64; | 80 | return 64; |
| 81 | } | 81 | } |
| 82 | #else | 82 | #else |
| 83 | inline u32 CountTrailingZeroes32(u32 value) { | 83 | [[nodiscard]] inline u32 CountTrailingZeroes32(u32 value) { |
| 84 | if (value == 0) { | 84 | if (value == 0) { |
| 85 | return 32; | 85 | return 32; |
| 86 | } | 86 | } |
| @@ -88,7 +88,7 @@ inline u32 CountTrailingZeroes32(u32 value) { | |||
| 88 | return static_cast<u32>(__builtin_ctz(value)); | 88 | return static_cast<u32>(__builtin_ctz(value)); |
| 89 | } | 89 | } |
| 90 | 90 | ||
| 91 | inline u32 CountTrailingZeroes64(u64 value) { | 91 | [[nodiscard]] inline u32 CountTrailingZeroes64(u64 value) { |
| 92 | if (value == 0) { | 92 | if (value == 0) { |
| 93 | return 64; | 93 | return 64; |
| 94 | } | 94 | } |
| @@ -99,13 +99,13 @@ inline u32 CountTrailingZeroes64(u64 value) { | |||
| 99 | 99 | ||
| 100 | #ifdef _MSC_VER | 100 | #ifdef _MSC_VER |
| 101 | 101 | ||
| 102 | inline u32 MostSignificantBit32(const u32 value) { | 102 | [[nodiscard]] inline u32 MostSignificantBit32(const u32 value) { |
| 103 | unsigned long result; | 103 | unsigned long result; |
| 104 | _BitScanReverse(&result, value); | 104 | _BitScanReverse(&result, value); |
| 105 | return static_cast<u32>(result); | 105 | return static_cast<u32>(result); |
| 106 | } | 106 | } |
| 107 | 107 | ||
| 108 | inline u32 MostSignificantBit64(const u64 value) { | 108 | [[nodiscard]] inline u32 MostSignificantBit64(const u64 value) { |
| 109 | unsigned long result; | 109 | unsigned long result; |
| 110 | _BitScanReverse64(&result, value); | 110 | _BitScanReverse64(&result, value); |
| 111 | return static_cast<u32>(result); | 111 | return static_cast<u32>(result); |
| @@ -113,30 +113,30 @@ inline u32 MostSignificantBit64(const u64 value) { | |||
| 113 | 113 | ||
| 114 | #else | 114 | #else |
| 115 | 115 | ||
| 116 | inline u32 MostSignificantBit32(const u32 value) { | 116 | [[nodiscard]] inline u32 MostSignificantBit32(const u32 value) { |
| 117 | return 31U - static_cast<u32>(__builtin_clz(value)); | 117 | return 31U - static_cast<u32>(__builtin_clz(value)); |
| 118 | } | 118 | } |
| 119 | 119 | ||
| 120 | inline u32 MostSignificantBit64(const u64 value) { | 120 | [[nodiscard]] inline u32 MostSignificantBit64(const u64 value) { |
| 121 | return 63U - static_cast<u32>(__builtin_clzll(value)); | 121 | return 63U - static_cast<u32>(__builtin_clzll(value)); |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | #endif | 124 | #endif |
| 125 | 125 | ||
| 126 | inline u32 Log2Floor32(const u32 value) { | 126 | [[nodiscard]] inline u32 Log2Floor32(const u32 value) { |
| 127 | return MostSignificantBit32(value); | 127 | return MostSignificantBit32(value); |
| 128 | } | 128 | } |
| 129 | 129 | ||
| 130 | inline u32 Log2Ceil32(const u32 value) { | 130 | [[nodiscard]] inline u32 Log2Ceil32(const u32 value) { |
| 131 | const u32 log2_f = Log2Floor32(value); | 131 | const u32 log2_f = Log2Floor32(value); |
| 132 | return log2_f + ((value ^ (1U << log2_f)) != 0U); | 132 | return log2_f + ((value ^ (1U << log2_f)) != 0U); |
| 133 | } | 133 | } |
| 134 | 134 | ||
| 135 | inline u32 Log2Floor64(const u64 value) { | 135 | [[nodiscard]] inline u32 Log2Floor64(const u64 value) { |
| 136 | return MostSignificantBit64(value); | 136 | return MostSignificantBit64(value); |
| 137 | } | 137 | } |
| 138 | 138 | ||
| 139 | inline u32 Log2Ceil64(const u64 value) { | 139 | [[nodiscard]] inline u32 Log2Ceil64(const u64 value) { |
| 140 | const u64 log2_f = static_cast<u64>(Log2Floor64(value)); | 140 | const u64 log2_f = static_cast<u64>(Log2Floor64(value)); |
| 141 | return static_cast<u32>(log2_f + ((value ^ (1ULL << log2_f)) != 0ULL)); | 141 | return static_cast<u32>(log2_f + ((value ^ (1ULL << log2_f)) != 0ULL)); |
| 142 | } | 142 | } |
diff --git a/src/common/cityhash.h b/src/common/cityhash.h index 4b94f8e18..a00804e01 100644 --- a/src/common/cityhash.h +++ b/src/common/cityhash.h | |||
| @@ -61,42 +61,43 @@ | |||
| 61 | 61 | ||
| 62 | #pragma once | 62 | #pragma once |
| 63 | 63 | ||
| 64 | #include <cstddef> | ||
| 65 | #include <cstdint> | ||
| 64 | #include <utility> | 66 | #include <utility> |
| 65 | #include <stdint.h> | ||
| 66 | #include <stdlib.h> // for std::size_t. | ||
| 67 | 67 | ||
| 68 | namespace Common { | 68 | namespace Common { |
| 69 | 69 | ||
| 70 | typedef std::pair<uint64_t, uint64_t> uint128; | 70 | using uint128 = std::pair<uint64_t, uint64_t>; |
| 71 | 71 | ||
| 72 | inline uint64_t Uint128Low64(const uint128& x) { | 72 | [[nodiscard]] inline uint64_t Uint128Low64(const uint128& x) { |
| 73 | return x.first; | 73 | return x.first; |
| 74 | } | 74 | } |
| 75 | inline uint64_t Uint128High64(const uint128& x) { | 75 | [[nodiscard]] inline uint64_t Uint128High64(const uint128& x) { |
| 76 | return x.second; | 76 | return x.second; |
| 77 | } | 77 | } |
| 78 | 78 | ||
| 79 | // Hash function for a byte array. | 79 | // Hash function for a byte array. |
| 80 | uint64_t CityHash64(const char* buf, std::size_t len); | 80 | [[nodiscard]] uint64_t CityHash64(const char* buf, std::size_t len); |
| 81 | 81 | ||
| 82 | // Hash function for a byte array. For convenience, a 64-bit seed is also | 82 | // Hash function for a byte array. For convenience, a 64-bit seed is also |
| 83 | // hashed into the result. | 83 | // hashed into the result. |
| 84 | uint64_t CityHash64WithSeed(const char* buf, std::size_t len, uint64_t seed); | 84 | [[nodiscard]] uint64_t CityHash64WithSeed(const char* buf, std::size_t len, uint64_t seed); |
| 85 | 85 | ||
| 86 | // Hash function for a byte array. For convenience, two seeds are also | 86 | // Hash function for a byte array. For convenience, two seeds are also |
| 87 | // hashed into the result. | 87 | // hashed into the result. |
| 88 | uint64_t CityHash64WithSeeds(const char* buf, std::size_t len, uint64_t seed0, uint64_t seed1); | 88 | [[nodiscard]] uint64_t CityHash64WithSeeds(const char* buf, std::size_t len, uint64_t seed0, |
| 89 | uint64_t seed1); | ||
| 89 | 90 | ||
| 90 | // Hash function for a byte array. | 91 | // Hash function for a byte array. |
| 91 | uint128 CityHash128(const char* s, std::size_t len); | 92 | [[nodiscard]] uint128 CityHash128(const char* s, std::size_t len); |
| 92 | 93 | ||
| 93 | // Hash function for a byte array. For convenience, a 128-bit seed is also | 94 | // Hash function for a byte array. For convenience, a 128-bit seed is also |
| 94 | // hashed into the result. | 95 | // hashed into the result. |
| 95 | uint128 CityHash128WithSeed(const char* s, std::size_t len, uint128 seed); | 96 | [[nodiscard]] uint128 CityHash128WithSeed(const char* s, std::size_t len, uint128 seed); |
| 96 | 97 | ||
| 97 | // Hash 128 input bits down to 64 bits of output. | 98 | // Hash 128 input bits down to 64 bits of output. |
| 98 | // This is intended to be a reasonably good hash function. | 99 | // This is intended to be a reasonably good hash function. |
| 99 | inline uint64_t Hash128to64(const uint128& x) { | 100 | [[nodiscard]] inline uint64_t Hash128to64(const uint128& x) { |
| 100 | // Murmur-inspired hashing. | 101 | // Murmur-inspired hashing. |
| 101 | const uint64_t kMul = 0x9ddfea08eb382d69ULL; | 102 | const uint64_t kMul = 0x9ddfea08eb382d69ULL; |
| 102 | uint64_t a = (Uint128Low64(x) ^ Uint128High64(x)) * kMul; | 103 | uint64_t a = (Uint128Low64(x) ^ Uint128High64(x)) * kMul; |
diff --git a/src/common/color.h b/src/common/color.h index 3a2222077..bbcac858e 100644 --- a/src/common/color.h +++ b/src/common/color.h | |||
| @@ -10,45 +10,45 @@ | |||
| 10 | #include "common/swap.h" | 10 | #include "common/swap.h" |
| 11 | #include "common/vector_math.h" | 11 | #include "common/vector_math.h" |
| 12 | 12 | ||
| 13 | namespace Color { | 13 | namespace Common::Color { |
| 14 | 14 | ||
| 15 | /// Convert a 1-bit color component to 8 bit | 15 | /// Convert a 1-bit color component to 8 bit |
| 16 | constexpr u8 Convert1To8(u8 value) { | 16 | [[nodiscard]] constexpr u8 Convert1To8(u8 value) { |
| 17 | return value * 255; | 17 | return value * 255; |
| 18 | } | 18 | } |
| 19 | 19 | ||
| 20 | /// Convert a 4-bit color component to 8 bit | 20 | /// Convert a 4-bit color component to 8 bit |
| 21 | constexpr u8 Convert4To8(u8 value) { | 21 | [[nodiscard]] constexpr u8 Convert4To8(u8 value) { |
| 22 | return (value << 4) | value; | 22 | return (value << 4) | value; |
| 23 | } | 23 | } |
| 24 | 24 | ||
| 25 | /// Convert a 5-bit color component to 8 bit | 25 | /// Convert a 5-bit color component to 8 bit |
| 26 | constexpr u8 Convert5To8(u8 value) { | 26 | [[nodiscard]] constexpr u8 Convert5To8(u8 value) { |
| 27 | return (value << 3) | (value >> 2); | 27 | return (value << 3) | (value >> 2); |
| 28 | } | 28 | } |
| 29 | 29 | ||
| 30 | /// Convert a 6-bit color component to 8 bit | 30 | /// Convert a 6-bit color component to 8 bit |
| 31 | constexpr u8 Convert6To8(u8 value) { | 31 | [[nodiscard]] constexpr u8 Convert6To8(u8 value) { |
| 32 | return (value << 2) | (value >> 4); | 32 | return (value << 2) | (value >> 4); |
| 33 | } | 33 | } |
| 34 | 34 | ||
| 35 | /// Convert a 8-bit color component to 1 bit | 35 | /// Convert a 8-bit color component to 1 bit |
| 36 | constexpr u8 Convert8To1(u8 value) { | 36 | [[nodiscard]] constexpr u8 Convert8To1(u8 value) { |
| 37 | return value >> 7; | 37 | return value >> 7; |
| 38 | } | 38 | } |
| 39 | 39 | ||
| 40 | /// Convert a 8-bit color component to 4 bit | 40 | /// Convert a 8-bit color component to 4 bit |
| 41 | constexpr u8 Convert8To4(u8 value) { | 41 | [[nodiscard]] constexpr u8 Convert8To4(u8 value) { |
| 42 | return value >> 4; | 42 | return value >> 4; |
| 43 | } | 43 | } |
| 44 | 44 | ||
| 45 | /// Convert a 8-bit color component to 5 bit | 45 | /// Convert a 8-bit color component to 5 bit |
| 46 | constexpr u8 Convert8To5(u8 value) { | 46 | [[nodiscard]] constexpr u8 Convert8To5(u8 value) { |
| 47 | return value >> 3; | 47 | return value >> 3; |
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | /// Convert a 8-bit color component to 6 bit | 50 | /// Convert a 8-bit color component to 6 bit |
| 51 | constexpr u8 Convert8To6(u8 value) { | 51 | [[nodiscard]] constexpr u8 Convert8To6(u8 value) { |
| 52 | return value >> 2; | 52 | return value >> 2; |
| 53 | } | 53 | } |
| 54 | 54 | ||
| @@ -57,7 +57,7 @@ constexpr u8 Convert8To6(u8 value) { | |||
| 57 | * @param bytes Pointer to encoded source color | 57 | * @param bytes Pointer to encoded source color |
| 58 | * @return Result color decoded as Common::Vec4<u8> | 58 | * @return Result color decoded as Common::Vec4<u8> |
| 59 | */ | 59 | */ |
| 60 | inline Common::Vec4<u8> DecodeRGBA8(const u8* bytes) { | 60 | [[nodiscard]] inline Common::Vec4<u8> DecodeRGBA8(const u8* bytes) { |
| 61 | return {bytes[3], bytes[2], bytes[1], bytes[0]}; | 61 | return {bytes[3], bytes[2], bytes[1], bytes[0]}; |
| 62 | } | 62 | } |
| 63 | 63 | ||
| @@ -66,7 +66,7 @@ inline Common::Vec4<u8> DecodeRGBA8(const u8* bytes) { | |||
| 66 | * @param bytes Pointer to encoded source color | 66 | * @param bytes Pointer to encoded source color |
| 67 | * @return Result color decoded as Common::Vec4<u8> | 67 | * @return Result color decoded as Common::Vec4<u8> |
| 68 | */ | 68 | */ |
| 69 | inline Common::Vec4<u8> DecodeRGB8(const u8* bytes) { | 69 | [[nodiscard]] inline Common::Vec4<u8> DecodeRGB8(const u8* bytes) { |
| 70 | return {bytes[2], bytes[1], bytes[0], 255}; | 70 | return {bytes[2], bytes[1], bytes[0], 255}; |
| 71 | } | 71 | } |
| 72 | 72 | ||
| @@ -75,7 +75,7 @@ inline Common::Vec4<u8> DecodeRGB8(const u8* bytes) { | |||
| 75 | * @param bytes Pointer to encoded source color | 75 | * @param bytes Pointer to encoded source color |
| 76 | * @return Result color decoded as Common::Vec4<u8> | 76 | * @return Result color decoded as Common::Vec4<u8> |
| 77 | */ | 77 | */ |
| 78 | inline Common::Vec4<u8> DecodeRG8(const u8* bytes) { | 78 | [[nodiscard]] inline Common::Vec4<u8> DecodeRG8(const u8* bytes) { |
| 79 | return {bytes[1], bytes[0], 0, 255}; | 79 | return {bytes[1], bytes[0], 0, 255}; |
| 80 | } | 80 | } |
| 81 | 81 | ||
| @@ -84,7 +84,7 @@ inline Common::Vec4<u8> DecodeRG8(const u8* bytes) { | |||
| 84 | * @param bytes Pointer to encoded source color | 84 | * @param bytes Pointer to encoded source color |
| 85 | * @return Result color decoded as Common::Vec4<u8> | 85 | * @return Result color decoded as Common::Vec4<u8> |
| 86 | */ | 86 | */ |
| 87 | inline Common::Vec4<u8> DecodeRGB565(const u8* bytes) { | 87 | [[nodiscard]] inline Common::Vec4<u8> DecodeRGB565(const u8* bytes) { |
| 88 | u16_le pixel; | 88 | u16_le pixel; |
| 89 | std::memcpy(&pixel, bytes, sizeof(pixel)); | 89 | std::memcpy(&pixel, bytes, sizeof(pixel)); |
| 90 | return {Convert5To8((pixel >> 11) & 0x1F), Convert6To8((pixel >> 5) & 0x3F), | 90 | return {Convert5To8((pixel >> 11) & 0x1F), Convert6To8((pixel >> 5) & 0x3F), |
| @@ -96,7 +96,7 @@ inline Common::Vec4<u8> DecodeRGB565(const u8* bytes) { | |||
| 96 | * @param bytes Pointer to encoded source color | 96 | * @param bytes Pointer to encoded source color |
| 97 | * @return Result color decoded as Common::Vec4<u8> | 97 | * @return Result color decoded as Common::Vec4<u8> |
| 98 | */ | 98 | */ |
| 99 | inline Common::Vec4<u8> DecodeRGB5A1(const u8* bytes) { | 99 | [[nodiscard]] inline Common::Vec4<u8> DecodeRGB5A1(const u8* bytes) { |
| 100 | u16_le pixel; | 100 | u16_le pixel; |
| 101 | std::memcpy(&pixel, bytes, sizeof(pixel)); | 101 | std::memcpy(&pixel, bytes, sizeof(pixel)); |
| 102 | return {Convert5To8((pixel >> 11) & 0x1F), Convert5To8((pixel >> 6) & 0x1F), | 102 | return {Convert5To8((pixel >> 11) & 0x1F), Convert5To8((pixel >> 6) & 0x1F), |
| @@ -108,7 +108,7 @@ inline Common::Vec4<u8> DecodeRGB5A1(const u8* bytes) { | |||
| 108 | * @param bytes Pointer to encoded source color | 108 | * @param bytes Pointer to encoded source color |
| 109 | * @return Result color decoded as Common::Vec4<u8> | 109 | * @return Result color decoded as Common::Vec4<u8> |
| 110 | */ | 110 | */ |
| 111 | inline Common::Vec4<u8> DecodeRGBA4(const u8* bytes) { | 111 | [[nodiscard]] inline Common::Vec4<u8> DecodeRGBA4(const u8* bytes) { |
| 112 | u16_le pixel; | 112 | u16_le pixel; |
| 113 | std::memcpy(&pixel, bytes, sizeof(pixel)); | 113 | std::memcpy(&pixel, bytes, sizeof(pixel)); |
| 114 | return {Convert4To8((pixel >> 12) & 0xF), Convert4To8((pixel >> 8) & 0xF), | 114 | return {Convert4To8((pixel >> 12) & 0xF), Convert4To8((pixel >> 8) & 0xF), |
| @@ -120,7 +120,7 @@ inline Common::Vec4<u8> DecodeRGBA4(const u8* bytes) { | |||
| 120 | * @param bytes Pointer to encoded source value | 120 | * @param bytes Pointer to encoded source value |
| 121 | * @return Depth value as an u32 | 121 | * @return Depth value as an u32 |
| 122 | */ | 122 | */ |
| 123 | inline u32 DecodeD16(const u8* bytes) { | 123 | [[nodiscard]] inline u32 DecodeD16(const u8* bytes) { |
| 124 | u16_le data; | 124 | u16_le data; |
| 125 | std::memcpy(&data, bytes, sizeof(data)); | 125 | std::memcpy(&data, bytes, sizeof(data)); |
| 126 | return data; | 126 | return data; |
| @@ -131,7 +131,7 @@ inline u32 DecodeD16(const u8* bytes) { | |||
| 131 | * @param bytes Pointer to encoded source value | 131 | * @param bytes Pointer to encoded source value |
| 132 | * @return Depth value as an u32 | 132 | * @return Depth value as an u32 |
| 133 | */ | 133 | */ |
| 134 | inline u32 DecodeD24(const u8* bytes) { | 134 | [[nodiscard]] inline u32 DecodeD24(const u8* bytes) { |
| 135 | return (bytes[2] << 16) | (bytes[1] << 8) | bytes[0]; | 135 | return (bytes[2] << 16) | (bytes[1] << 8) | bytes[0]; |
| 136 | } | 136 | } |
| 137 | 137 | ||
| @@ -140,7 +140,7 @@ inline u32 DecodeD24(const u8* bytes) { | |||
| 140 | * @param bytes Pointer to encoded source values | 140 | * @param bytes Pointer to encoded source values |
| 141 | * @return Resulting values stored as a Common::Vec2 | 141 | * @return Resulting values stored as a Common::Vec2 |
| 142 | */ | 142 | */ |
| 143 | inline Common::Vec2<u32> DecodeD24S8(const u8* bytes) { | 143 | [[nodiscard]] inline Common::Vec2<u32> DecodeD24S8(const u8* bytes) { |
| 144 | return {static_cast<u32>((bytes[2] << 16) | (bytes[1] << 8) | bytes[0]), bytes[3]}; | 144 | return {static_cast<u32>((bytes[2] << 16) | (bytes[1] << 8) | bytes[0]), bytes[3]}; |
| 145 | } | 145 | } |
| 146 | 146 | ||
| @@ -268,4 +268,4 @@ inline void EncodeX24S8(u8 stencil, u8* bytes) { | |||
| 268 | bytes[3] = stencil; | 268 | bytes[3] = stencil; |
| 269 | } | 269 | } |
| 270 | 270 | ||
| 271 | } // namespace Color | 271 | } // namespace Common::Color |
diff --git a/src/common/common_funcs.h b/src/common/common_funcs.h index 88cf5250a..98421bced 100644 --- a/src/common/common_funcs.h +++ b/src/common/common_funcs.h | |||
| @@ -53,14 +53,14 @@ __declspec(dllimport) void __stdcall DebugBreak(void); | |||
| 53 | // Call directly after the command or use the error num. | 53 | // Call directly after the command or use the error num. |
| 54 | // This function might change the error code. | 54 | // This function might change the error code. |
| 55 | // Defined in Misc.cpp. | 55 | // Defined in Misc.cpp. |
| 56 | std::string GetLastErrorMsg(); | 56 | [[nodiscard]] std::string GetLastErrorMsg(); |
| 57 | 57 | ||
| 58 | #define DECLARE_ENUM_FLAG_OPERATORS(type) \ | 58 | #define DECLARE_ENUM_FLAG_OPERATORS(type) \ |
| 59 | constexpr type operator|(type a, type b) noexcept { \ | 59 | [[nodiscard]] constexpr type operator|(type a, type b) noexcept { \ |
| 60 | using T = std::underlying_type_t<type>; \ | 60 | using T = std::underlying_type_t<type>; \ |
| 61 | return static_cast<type>(static_cast<T>(a) | static_cast<T>(b)); \ | 61 | return static_cast<type>(static_cast<T>(a) | static_cast<T>(b)); \ |
| 62 | } \ | 62 | } \ |
| 63 | constexpr type operator&(type a, type b) noexcept { \ | 63 | [[nodiscard]] constexpr type operator&(type a, type b) noexcept { \ |
| 64 | using T = std::underlying_type_t<type>; \ | 64 | using T = std::underlying_type_t<type>; \ |
| 65 | return static_cast<type>(static_cast<T>(a) & static_cast<T>(b)); \ | 65 | return static_cast<type>(static_cast<T>(a) & static_cast<T>(b)); \ |
| 66 | } \ | 66 | } \ |
| @@ -74,22 +74,22 @@ std::string GetLastErrorMsg(); | |||
| 74 | a = static_cast<type>(static_cast<T>(a) & static_cast<T>(b)); \ | 74 | a = static_cast<type>(static_cast<T>(a) & static_cast<T>(b)); \ |
| 75 | return a; \ | 75 | return a; \ |
| 76 | } \ | 76 | } \ |
| 77 | constexpr type operator~(type key) noexcept { \ | 77 | [[nodiscard]] constexpr type operator~(type key) noexcept { \ |
| 78 | using T = std::underlying_type_t<type>; \ | 78 | using T = std::underlying_type_t<type>; \ |
| 79 | return static_cast<type>(~static_cast<T>(key)); \ | 79 | return static_cast<type>(~static_cast<T>(key)); \ |
| 80 | } \ | 80 | } \ |
| 81 | constexpr bool True(type key) noexcept { \ | 81 | [[nodiscard]] constexpr bool True(type key) noexcept { \ |
| 82 | using T = std::underlying_type_t<type>; \ | 82 | using T = std::underlying_type_t<type>; \ |
| 83 | return static_cast<T>(key) != 0; \ | 83 | return static_cast<T>(key) != 0; \ |
| 84 | } \ | 84 | } \ |
| 85 | constexpr bool False(type key) noexcept { \ | 85 | [[nodiscard]] constexpr bool False(type key) noexcept { \ |
| 86 | using T = std::underlying_type_t<type>; \ | 86 | using T = std::underlying_type_t<type>; \ |
| 87 | return static_cast<T>(key) == 0; \ | 87 | return static_cast<T>(key) == 0; \ |
| 88 | } | 88 | } |
| 89 | 89 | ||
| 90 | namespace Common { | 90 | namespace Common { |
| 91 | 91 | ||
| 92 | constexpr u32 MakeMagic(char a, char b, char c, char d) { | 92 | [[nodiscard]] constexpr u32 MakeMagic(char a, char b, char c, char d) { |
| 93 | return u32(a) | u32(b) << 8 | u32(c) << 16 | u32(d) << 24; | 93 | return u32(a) | u32(b) << 8 | u32(c) << 16 | u32(d) << 24; |
| 94 | } | 94 | } |
| 95 | 95 | ||
diff --git a/src/common/concepts.h b/src/common/concepts.h index db5fb373d..5bef3ad67 100644 --- a/src/common/concepts.h +++ b/src/common/concepts.h | |||
| @@ -4,10 +4,10 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | namespace Common { | ||
| 8 | |||
| 9 | #include <type_traits> | 7 | #include <type_traits> |
| 10 | 8 | ||
| 9 | namespace Common { | ||
| 10 | |||
| 11 | // Check if type is like an STL container | 11 | // Check if type is like an STL container |
| 12 | template <typename T> | 12 | template <typename T> |
| 13 | concept IsSTLContainer = requires(T t) { | 13 | concept IsSTLContainer = requires(T t) { |
| @@ -23,10 +23,12 @@ concept IsSTLContainer = requires(T t) { | |||
| 23 | t.size(); | 23 | t.size(); |
| 24 | }; | 24 | }; |
| 25 | 25 | ||
| 26 | // Check if type T is derived from T2 | 26 | // TODO: Replace with std::derived_from when the <concepts> header |
| 27 | template <typename T, typename T2> | 27 | // is available on all supported platforms. |
| 28 | concept IsBaseOf = requires { | 28 | template <typename Derived, typename Base> |
| 29 | std::is_base_of_v<T, T2>; | 29 | concept DerivedFrom = requires { |
| 30 | std::is_base_of_v<Base, Derived>; | ||
| 31 | std::is_convertible_v<const volatile Derived*, const volatile Base*>; | ||
| 30 | }; | 32 | }; |
| 31 | 33 | ||
| 32 | } // namespace Common | 34 | } // namespace Common |
diff --git a/src/common/detached_tasks.cpp b/src/common/detached_tasks.cpp index f268d6021..f2b4939df 100644 --- a/src/common/detached_tasks.cpp +++ b/src/common/detached_tasks.cpp | |||
| @@ -34,8 +34,7 @@ void DetachedTasks::AddTask(std::function<void()> task) { | |||
| 34 | std::unique_lock lock{instance->mutex}; | 34 | std::unique_lock lock{instance->mutex}; |
| 35 | --instance->count; | 35 | --instance->count; |
| 36 | std::notify_all_at_thread_exit(instance->cv, std::move(lock)); | 36 | std::notify_all_at_thread_exit(instance->cv, std::move(lock)); |
| 37 | }) | 37 | }).detach(); |
| 38 | .detach(); | ||
| 39 | } | 38 | } |
| 40 | 39 | ||
| 41 | } // namespace Common | 40 | } // namespace Common |
diff --git a/src/common/dynamic_library.cpp b/src/common/dynamic_library.cpp index 7ab54e9e4..7f0a10521 100644 --- a/src/common/dynamic_library.cpp +++ b/src/common/dynamic_library.cpp | |||
| @@ -21,7 +21,7 @@ namespace Common { | |||
| 21 | DynamicLibrary::DynamicLibrary() = default; | 21 | DynamicLibrary::DynamicLibrary() = default; |
| 22 | 22 | ||
| 23 | DynamicLibrary::DynamicLibrary(const char* filename) { | 23 | DynamicLibrary::DynamicLibrary(const char* filename) { |
| 24 | Open(filename); | 24 | void(Open(filename)); |
| 25 | } | 25 | } |
| 26 | 26 | ||
| 27 | DynamicLibrary::DynamicLibrary(DynamicLibrary&& rhs) noexcept | 27 | DynamicLibrary::DynamicLibrary(DynamicLibrary&& rhs) noexcept |
diff --git a/src/common/dynamic_library.h b/src/common/dynamic_library.h index 2a06372fd..3512da940 100644 --- a/src/common/dynamic_library.h +++ b/src/common/dynamic_library.h | |||
| @@ -33,7 +33,7 @@ public: | |||
| 33 | ~DynamicLibrary(); | 33 | ~DynamicLibrary(); |
| 34 | 34 | ||
| 35 | /// Returns the specified library name with the platform-specific suffix added. | 35 | /// Returns the specified library name with the platform-specific suffix added. |
| 36 | static std::string GetUnprefixedFilename(const char* filename); | 36 | [[nodiscard]] static std::string GetUnprefixedFilename(const char* filename); |
| 37 | 37 | ||
| 38 | /// Returns the specified library name in platform-specific format. | 38 | /// Returns the specified library name in platform-specific format. |
| 39 | /// Major/minor versions will not be included if set to -1. | 39 | /// Major/minor versions will not be included if set to -1. |
| @@ -41,28 +41,29 @@ public: | |||
| 41 | /// Windows: LIBNAME-MAJOR-MINOR.dll | 41 | /// Windows: LIBNAME-MAJOR-MINOR.dll |
| 42 | /// Linux: libLIBNAME.so.MAJOR.MINOR | 42 | /// Linux: libLIBNAME.so.MAJOR.MINOR |
| 43 | /// Mac: libLIBNAME.MAJOR.MINOR.dylib | 43 | /// Mac: libLIBNAME.MAJOR.MINOR.dylib |
| 44 | static std::string GetVersionedFilename(const char* libname, int major = -1, int minor = -1); | 44 | [[nodiscard]] static std::string GetVersionedFilename(const char* libname, int major = -1, |
| 45 | int minor = -1); | ||
| 45 | 46 | ||
| 46 | /// Returns true if a module is loaded, otherwise false. | 47 | /// Returns true if a module is loaded, otherwise false. |
| 47 | bool IsOpen() const { | 48 | [[nodiscard]] bool IsOpen() const { |
| 48 | return handle != nullptr; | 49 | return handle != nullptr; |
| 49 | } | 50 | } |
| 50 | 51 | ||
| 51 | /// Loads (or replaces) the handle with the specified library file name. | 52 | /// Loads (or replaces) the handle with the specified library file name. |
| 52 | /// Returns true if the library was loaded and can be used. | 53 | /// Returns true if the library was loaded and can be used. |
| 53 | bool Open(const char* filename); | 54 | [[nodiscard]] bool Open(const char* filename); |
| 54 | 55 | ||
| 55 | /// Unloads the library, any function pointers from this library are no longer valid. | 56 | /// Unloads the library, any function pointers from this library are no longer valid. |
| 56 | void Close(); | 57 | void Close(); |
| 57 | 58 | ||
| 58 | /// Returns the address of the specified symbol (function or variable) as an untyped pointer. | 59 | /// Returns the address of the specified symbol (function or variable) as an untyped pointer. |
| 59 | /// If the specified symbol does not exist in this library, nullptr is returned. | 60 | /// If the specified symbol does not exist in this library, nullptr is returned. |
| 60 | void* GetSymbolAddress(const char* name) const; | 61 | [[nodiscard]] void* GetSymbolAddress(const char* name) const; |
| 61 | 62 | ||
| 62 | /// Obtains the address of the specified symbol, automatically casting to the correct type. | 63 | /// Obtains the address of the specified symbol, automatically casting to the correct type. |
| 63 | /// Returns true if the symbol was found and assigned, otherwise false. | 64 | /// Returns true if the symbol was found and assigned, otherwise false. |
| 64 | template <typename T> | 65 | template <typename T> |
| 65 | bool GetSymbol(const char* name, T* ptr) const { | 66 | [[nodiscard]] bool GetSymbol(const char* name, T* ptr) const { |
| 66 | *ptr = reinterpret_cast<T>(GetSymbolAddress(name)); | 67 | *ptr = reinterpret_cast<T>(GetSymbolAddress(name)); |
| 67 | return *ptr != nullptr; | 68 | return *ptr != nullptr; |
| 68 | } | 69 | } |
diff --git a/src/common/fiber.h b/src/common/fiber.h index dafc1100e..89dde5e36 100644 --- a/src/common/fiber.h +++ b/src/common/fiber.h | |||
| @@ -47,7 +47,7 @@ public: | |||
| 47 | /// Yields control from Fiber 'from' to Fiber 'to' | 47 | /// Yields control from Fiber 'from' to Fiber 'to' |
| 48 | /// Fiber 'from' must be the currently running fiber. | 48 | /// Fiber 'from' must be the currently running fiber. |
| 49 | static void YieldTo(std::shared_ptr<Fiber>& from, std::shared_ptr<Fiber>& to); | 49 | static void YieldTo(std::shared_ptr<Fiber>& from, std::shared_ptr<Fiber>& to); |
| 50 | static std::shared_ptr<Fiber> ThreadToFiber(); | 50 | [[nodiscard]] static std::shared_ptr<Fiber> ThreadToFiber(); |
| 51 | 51 | ||
| 52 | void SetRewindPoint(std::function<void(void*)>&& rewind_func, void* start_parameter); | 52 | void SetRewindPoint(std::function<void(void*)>&& rewind_func, void* start_parameter); |
| 53 | 53 | ||
diff --git a/src/common/file_util.cpp b/src/common/file_util.cpp index 4ede9f72c..16c3713e0 100644 --- a/src/common/file_util.cpp +++ b/src/common/file_util.cpp | |||
| @@ -74,7 +74,7 @@ | |||
| 74 | // This namespace has various generic functions related to files and paths. | 74 | // This namespace has various generic functions related to files and paths. |
| 75 | // The code still needs a ton of cleanup. | 75 | // The code still needs a ton of cleanup. |
| 76 | // REMEMBER: strdup considered harmful! | 76 | // REMEMBER: strdup considered harmful! |
| 77 | namespace FileUtil { | 77 | namespace Common::FS { |
| 78 | 78 | ||
| 79 | // Remove any ending forward slashes from directory paths | 79 | // Remove any ending forward slashes from directory paths |
| 80 | // Modifies argument. | 80 | // Modifies argument. |
| @@ -196,7 +196,7 @@ bool CreateFullPath(const std::string& fullPath) { | |||
| 196 | int panicCounter = 100; | 196 | int panicCounter = 100; |
| 197 | LOG_TRACE(Common_Filesystem, "path {}", fullPath); | 197 | LOG_TRACE(Common_Filesystem, "path {}", fullPath); |
| 198 | 198 | ||
| 199 | if (FileUtil::Exists(fullPath)) { | 199 | if (Exists(fullPath)) { |
| 200 | LOG_DEBUG(Common_Filesystem, "path exists {}", fullPath); | 200 | LOG_DEBUG(Common_Filesystem, "path exists {}", fullPath); |
| 201 | return true; | 201 | return true; |
| 202 | } | 202 | } |
| @@ -212,7 +212,7 @@ bool CreateFullPath(const std::string& fullPath) { | |||
| 212 | 212 | ||
| 213 | // Include the '/' so the first call is CreateDir("/") rather than CreateDir("") | 213 | // Include the '/' so the first call is CreateDir("/") rather than CreateDir("") |
| 214 | std::string const subPath(fullPath.substr(0, position + 1)); | 214 | std::string const subPath(fullPath.substr(0, position + 1)); |
| 215 | if (!FileUtil::IsDirectory(subPath) && !FileUtil::CreateDir(subPath)) { | 215 | if (!IsDirectory(subPath) && !CreateDir(subPath)) { |
| 216 | LOG_ERROR(Common, "CreateFullPath: directory creation failed"); | 216 | LOG_ERROR(Common, "CreateFullPath: directory creation failed"); |
| 217 | return false; | 217 | return false; |
| 218 | } | 218 | } |
| @@ -231,7 +231,7 @@ bool DeleteDir(const std::string& filename) { | |||
| 231 | LOG_TRACE(Common_Filesystem, "directory {}", filename); | 231 | LOG_TRACE(Common_Filesystem, "directory {}", filename); |
| 232 | 232 | ||
| 233 | // check if a directory | 233 | // check if a directory |
| 234 | if (!FileUtil::IsDirectory(filename)) { | 234 | if (!IsDirectory(filename)) { |
| 235 | LOG_ERROR(Common_Filesystem, "Not a directory {}", filename); | 235 | LOG_ERROR(Common_Filesystem, "Not a directory {}", filename); |
| 236 | return false; | 236 | return false; |
| 237 | } | 237 | } |
| @@ -371,7 +371,7 @@ u64 GetSize(FILE* f) { | |||
| 371 | bool CreateEmptyFile(const std::string& filename) { | 371 | bool CreateEmptyFile(const std::string& filename) { |
| 372 | LOG_TRACE(Common_Filesystem, "{}", filename); | 372 | LOG_TRACE(Common_Filesystem, "{}", filename); |
| 373 | 373 | ||
| 374 | if (!FileUtil::IOFile(filename, "wb").IsOpen()) { | 374 | if (!IOFile(filename, "wb").IsOpen()) { |
| 375 | LOG_ERROR(Common_Filesystem, "failed {}: {}", filename, GetLastErrorMsg()); | 375 | LOG_ERROR(Common_Filesystem, "failed {}: {}", filename, GetLastErrorMsg()); |
| 376 | return false; | 376 | return false; |
| 377 | } | 377 | } |
| @@ -488,29 +488,34 @@ bool DeleteDirRecursively(const std::string& directory, unsigned int recursion) | |||
| 488 | return false; | 488 | return false; |
| 489 | 489 | ||
| 490 | // Delete the outermost directory | 490 | // Delete the outermost directory |
| 491 | FileUtil::DeleteDir(directory); | 491 | DeleteDir(directory); |
| 492 | return true; | 492 | return true; |
| 493 | } | 493 | } |
| 494 | 494 | ||
| 495 | void CopyDir(const std::string& source_path, const std::string& dest_path) { | 495 | void CopyDir(const std::string& source_path, const std::string& dest_path) { |
| 496 | #ifndef _WIN32 | 496 | #ifndef _WIN32 |
| 497 | if (source_path == dest_path) | 497 | if (source_path == dest_path) { |
| 498 | return; | 498 | return; |
| 499 | if (!FileUtil::Exists(source_path)) | 499 | } |
| 500 | if (!Exists(source_path)) { | ||
| 500 | return; | 501 | return; |
| 501 | if (!FileUtil::Exists(dest_path)) | 502 | } |
| 502 | FileUtil::CreateFullPath(dest_path); | 503 | if (!Exists(dest_path)) { |
| 504 | CreateFullPath(dest_path); | ||
| 505 | } | ||
| 503 | 506 | ||
| 504 | DIR* dirp = opendir(source_path.c_str()); | 507 | DIR* dirp = opendir(source_path.c_str()); |
| 505 | if (!dirp) | 508 | if (!dirp) { |
| 506 | return; | 509 | return; |
| 510 | } | ||
| 507 | 511 | ||
| 508 | while (struct dirent* result = readdir(dirp)) { | 512 | while (struct dirent* result = readdir(dirp)) { |
| 509 | const std::string virtualName(result->d_name); | 513 | const std::string virtualName(result->d_name); |
| 510 | // check for "." and ".." | 514 | // check for "." and ".." |
| 511 | if (((virtualName[0] == '.') && (virtualName[1] == '\0')) || | 515 | if (((virtualName[0] == '.') && (virtualName[1] == '\0')) || |
| 512 | ((virtualName[0] == '.') && (virtualName[1] == '.') && (virtualName[2] == '\0'))) | 516 | ((virtualName[0] == '.') && (virtualName[1] == '.') && (virtualName[2] == '\0'))) { |
| 513 | continue; | 517 | continue; |
| 518 | } | ||
| 514 | 519 | ||
| 515 | std::string source, dest; | 520 | std::string source, dest; |
| 516 | source = source_path + virtualName; | 521 | source = source_path + virtualName; |
| @@ -518,11 +523,13 @@ void CopyDir(const std::string& source_path, const std::string& dest_path) { | |||
| 518 | if (IsDirectory(source)) { | 523 | if (IsDirectory(source)) { |
| 519 | source += '/'; | 524 | source += '/'; |
| 520 | dest += '/'; | 525 | dest += '/'; |
| 521 | if (!FileUtil::Exists(dest)) | 526 | if (!Exists(dest)) { |
| 522 | FileUtil::CreateFullPath(dest); | 527 | CreateFullPath(dest); |
| 528 | } | ||
| 523 | CopyDir(source, dest); | 529 | CopyDir(source, dest); |
| 524 | } else if (!FileUtil::Exists(dest)) | 530 | } else if (!Exists(dest)) { |
| 525 | FileUtil::Copy(source, dest); | 531 | Copy(source, dest); |
| 532 | } | ||
| 526 | } | 533 | } |
| 527 | closedir(dirp); | 534 | closedir(dirp); |
| 528 | #endif | 535 | #endif |
| @@ -538,7 +545,7 @@ std::optional<std::string> GetCurrentDir() { | |||
| 538 | if (!dir) { | 545 | if (!dir) { |
| 539 | #endif | 546 | #endif |
| 540 | LOG_ERROR(Common_Filesystem, "GetCurrentDirectory failed: {}", GetLastErrorMsg()); | 547 | LOG_ERROR(Common_Filesystem, "GetCurrentDirectory failed: {}", GetLastErrorMsg()); |
| 541 | return {}; | 548 | return std::nullopt; |
| 542 | } | 549 | } |
| 543 | #ifdef _WIN32 | 550 | #ifdef _WIN32 |
| 544 | std::string strDir = Common::UTF16ToUTF8(dir); | 551 | std::string strDir = Common::UTF16ToUTF8(dir); |
| @@ -546,7 +553,7 @@ std::optional<std::string> GetCurrentDir() { | |||
| 546 | std::string strDir = dir; | 553 | std::string strDir = dir; |
| 547 | #endif | 554 | #endif |
| 548 | free(dir); | 555 | free(dir); |
| 549 | return strDir; | 556 | return std::move(strDir); |
| 550 | } | 557 | } |
| 551 | 558 | ||
| 552 | bool SetCurrentDir(const std::string& directory) { | 559 | bool SetCurrentDir(const std::string& directory) { |
| @@ -668,7 +675,7 @@ const std::string& GetUserPath(UserPath path, const std::string& new_path) { | |||
| 668 | if (user_path.empty()) { | 675 | if (user_path.empty()) { |
| 669 | #ifdef _WIN32 | 676 | #ifdef _WIN32 |
| 670 | user_path = GetExeDirectory() + DIR_SEP USERDATA_DIR DIR_SEP; | 677 | user_path = GetExeDirectory() + DIR_SEP USERDATA_DIR DIR_SEP; |
| 671 | if (!FileUtil::IsDirectory(user_path)) { | 678 | if (!IsDirectory(user_path)) { |
| 672 | user_path = AppDataRoamingDirectory() + DIR_SEP EMU_DATA_DIR DIR_SEP; | 679 | user_path = AppDataRoamingDirectory() + DIR_SEP EMU_DATA_DIR DIR_SEP; |
| 673 | } else { | 680 | } else { |
| 674 | LOG_INFO(Common_Filesystem, "Using the local user directory"); | 681 | LOG_INFO(Common_Filesystem, "Using the local user directory"); |
| @@ -677,7 +684,7 @@ const std::string& GetUserPath(UserPath path, const std::string& new_path) { | |||
| 677 | paths.emplace(UserPath::ConfigDir, user_path + CONFIG_DIR DIR_SEP); | 684 | paths.emplace(UserPath::ConfigDir, user_path + CONFIG_DIR DIR_SEP); |
| 678 | paths.emplace(UserPath::CacheDir, user_path + CACHE_DIR DIR_SEP); | 685 | paths.emplace(UserPath::CacheDir, user_path + CACHE_DIR DIR_SEP); |
| 679 | #else | 686 | #else |
| 680 | if (FileUtil::Exists(ROOT_DIR DIR_SEP USERDATA_DIR)) { | 687 | if (Exists(ROOT_DIR DIR_SEP USERDATA_DIR)) { |
| 681 | user_path = ROOT_DIR DIR_SEP USERDATA_DIR DIR_SEP; | 688 | user_path = ROOT_DIR DIR_SEP USERDATA_DIR DIR_SEP; |
| 682 | paths.emplace(UserPath::ConfigDir, user_path + CONFIG_DIR DIR_SEP); | 689 | paths.emplace(UserPath::ConfigDir, user_path + CONFIG_DIR DIR_SEP); |
| 683 | paths.emplace(UserPath::CacheDir, user_path + CACHE_DIR DIR_SEP); | 690 | paths.emplace(UserPath::CacheDir, user_path + CACHE_DIR DIR_SEP); |
| @@ -704,7 +711,7 @@ const std::string& GetUserPath(UserPath path, const std::string& new_path) { | |||
| 704 | } | 711 | } |
| 705 | 712 | ||
| 706 | if (!new_path.empty()) { | 713 | if (!new_path.empty()) { |
| 707 | if (!FileUtil::IsDirectory(new_path)) { | 714 | if (!IsDirectory(new_path)) { |
| 708 | LOG_ERROR(Common_Filesystem, "Invalid path specified {}", new_path); | 715 | LOG_ERROR(Common_Filesystem, "Invalid path specified {}", new_path); |
| 709 | return paths[path]; | 716 | return paths[path]; |
| 710 | } else { | 717 | } else { |
| @@ -902,10 +909,10 @@ std::string SanitizePath(std::string_view path_, DirectorySeparator directory_se | |||
| 902 | return std::string(RemoveTrailingSlash(path)); | 909 | return std::string(RemoveTrailingSlash(path)); |
| 903 | } | 910 | } |
| 904 | 911 | ||
| 905 | IOFile::IOFile() {} | 912 | IOFile::IOFile() = default; |
| 906 | 913 | ||
| 907 | IOFile::IOFile(const std::string& filename, const char openmode[], int flags) { | 914 | IOFile::IOFile(const std::string& filename, const char openmode[], int flags) { |
| 908 | Open(filename, openmode, flags); | 915 | void(Open(filename, openmode, flags)); |
| 909 | } | 916 | } |
| 910 | 917 | ||
| 911 | IOFile::~IOFile() { | 918 | IOFile::~IOFile() { |
| @@ -946,17 +953,18 @@ bool IOFile::Open(const std::string& filename, const char openmode[], int flags) | |||
| 946 | } | 953 | } |
| 947 | 954 | ||
| 948 | bool IOFile::Close() { | 955 | bool IOFile::Close() { |
| 949 | if (!IsOpen() || 0 != std::fclose(m_file)) | 956 | if (!IsOpen() || 0 != std::fclose(m_file)) { |
| 950 | return false; | 957 | return false; |
| 958 | } | ||
| 951 | 959 | ||
| 952 | m_file = nullptr; | 960 | m_file = nullptr; |
| 953 | return true; | 961 | return true; |
| 954 | } | 962 | } |
| 955 | 963 | ||
| 956 | u64 IOFile::GetSize() const { | 964 | u64 IOFile::GetSize() const { |
| 957 | if (IsOpen()) | 965 | if (IsOpen()) { |
| 958 | return FileUtil::GetSize(m_file); | 966 | return FS::GetSize(m_file); |
| 959 | 967 | } | |
| 960 | return 0; | 968 | return 0; |
| 961 | } | 969 | } |
| 962 | 970 | ||
| @@ -965,9 +973,9 @@ bool IOFile::Seek(s64 off, int origin) const { | |||
| 965 | } | 973 | } |
| 966 | 974 | ||
| 967 | u64 IOFile::Tell() const { | 975 | u64 IOFile::Tell() const { |
| 968 | if (IsOpen()) | 976 | if (IsOpen()) { |
| 969 | return ftello(m_file); | 977 | return ftello(m_file); |
| 970 | 978 | } | |
| 971 | return std::numeric_limits<u64>::max(); | 979 | return std::numeric_limits<u64>::max(); |
| 972 | } | 980 | } |
| 973 | 981 | ||
| @@ -1016,4 +1024,4 @@ bool IOFile::Resize(u64 size) { | |||
| 1016 | ; | 1024 | ; |
| 1017 | } | 1025 | } |
| 1018 | 1026 | ||
| 1019 | } // namespace FileUtil | 1027 | } // namespace Common::FS |
diff --git a/src/common/file_util.h b/src/common/file_util.h index 187b93161..8b587320f 100644 --- a/src/common/file_util.h +++ b/src/common/file_util.h | |||
| @@ -19,7 +19,7 @@ | |||
| 19 | #include "common/string_util.h" | 19 | #include "common/string_util.h" |
| 20 | #endif | 20 | #endif |
| 21 | 21 | ||
| 22 | namespace FileUtil { | 22 | namespace Common::FS { |
| 23 | 23 | ||
| 24 | // User paths for GetUserPath | 24 | // User paths for GetUserPath |
| 25 | enum class UserPath { | 25 | enum class UserPath { |
| @@ -48,19 +48,19 @@ struct FSTEntry { | |||
| 48 | }; | 48 | }; |
| 49 | 49 | ||
| 50 | // Returns true if file filename exists | 50 | // Returns true if file filename exists |
| 51 | bool Exists(const std::string& filename); | 51 | [[nodiscard]] bool Exists(const std::string& filename); |
| 52 | 52 | ||
| 53 | // Returns true if filename is a directory | 53 | // Returns true if filename is a directory |
| 54 | bool IsDirectory(const std::string& filename); | 54 | [[nodiscard]] bool IsDirectory(const std::string& filename); |
| 55 | 55 | ||
| 56 | // Returns the size of filename (64bit) | 56 | // Returns the size of filename (64bit) |
| 57 | u64 GetSize(const std::string& filename); | 57 | [[nodiscard]] u64 GetSize(const std::string& filename); |
| 58 | 58 | ||
| 59 | // Overloaded GetSize, accepts file descriptor | 59 | // Overloaded GetSize, accepts file descriptor |
| 60 | u64 GetSize(const int fd); | 60 | [[nodiscard]] u64 GetSize(int fd); |
| 61 | 61 | ||
| 62 | // Overloaded GetSize, accepts FILE* | 62 | // Overloaded GetSize, accepts FILE* |
| 63 | u64 GetSize(FILE* f); | 63 | [[nodiscard]] u64 GetSize(FILE* f); |
| 64 | 64 | ||
| 65 | // Returns true if successful, or path already exists. | 65 | // Returns true if successful, or path already exists. |
| 66 | bool CreateDir(const std::string& filename); | 66 | bool CreateDir(const std::string& filename); |
| @@ -120,7 +120,7 @@ u64 ScanDirectoryTree(const std::string& directory, FSTEntry& parent_entry, | |||
| 120 | bool DeleteDirRecursively(const std::string& directory, unsigned int recursion = 256); | 120 | bool DeleteDirRecursively(const std::string& directory, unsigned int recursion = 256); |
| 121 | 121 | ||
| 122 | // Returns the current directory | 122 | // Returns the current directory |
| 123 | std::optional<std::string> GetCurrentDir(); | 123 | [[nodiscard]] std::optional<std::string> GetCurrentDir(); |
| 124 | 124 | ||
| 125 | // Create directory and copy contents (does not overwrite existing files) | 125 | // Create directory and copy contents (does not overwrite existing files) |
| 126 | void CopyDir(const std::string& source_path, const std::string& dest_path); | 126 | void CopyDir(const std::string& source_path, const std::string& dest_path); |
| @@ -132,20 +132,20 @@ bool SetCurrentDir(const std::string& directory); | |||
| 132 | // directory. To be used in "multi-user" mode (that is, installed). | 132 | // directory. To be used in "multi-user" mode (that is, installed). |
| 133 | const std::string& GetUserPath(UserPath path, const std::string& new_path = ""); | 133 | const std::string& GetUserPath(UserPath path, const std::string& new_path = ""); |
| 134 | 134 | ||
| 135 | std::string GetHactoolConfigurationPath(); | 135 | [[nodiscard]] std::string GetHactoolConfigurationPath(); |
| 136 | 136 | ||
| 137 | std::string GetNANDRegistrationDir(bool system = false); | 137 | [[nodiscard]] std::string GetNANDRegistrationDir(bool system = false); |
| 138 | 138 | ||
| 139 | // Returns the path to where the sys file are | 139 | // Returns the path to where the sys file are |
| 140 | std::string GetSysDirectory(); | 140 | [[nodiscard]] std::string GetSysDirectory(); |
| 141 | 141 | ||
| 142 | #ifdef __APPLE__ | 142 | #ifdef __APPLE__ |
| 143 | std::string GetBundleDirectory(); | 143 | [[nodiscard]] std::string GetBundleDirectory(); |
| 144 | #endif | 144 | #endif |
| 145 | 145 | ||
| 146 | #ifdef _WIN32 | 146 | #ifdef _WIN32 |
| 147 | const std::string& GetExeDirectory(); | 147 | [[nodiscard]] const std::string& GetExeDirectory(); |
| 148 | std::string AppDataRoamingDirectory(); | 148 | [[nodiscard]] std::string AppDataRoamingDirectory(); |
| 149 | #endif | 149 | #endif |
| 150 | 150 | ||
| 151 | std::size_t WriteStringToFile(bool text_file, const std::string& filename, std::string_view str); | 151 | std::size_t WriteStringToFile(bool text_file, const std::string& filename, std::string_view str); |
| @@ -164,38 +164,55 @@ void SplitFilename83(const std::string& filename, std::array<char, 9>& short_nam | |||
| 164 | 164 | ||
| 165 | // Splits the path on '/' or '\' and put the components into a vector | 165 | // Splits the path on '/' or '\' and put the components into a vector |
| 166 | // i.e. "C:\Users\Yuzu\Documents\save.bin" becomes {"C:", "Users", "Yuzu", "Documents", "save.bin" } | 166 | // i.e. "C:\Users\Yuzu\Documents\save.bin" becomes {"C:", "Users", "Yuzu", "Documents", "save.bin" } |
| 167 | std::vector<std::string> SplitPathComponents(std::string_view filename); | 167 | [[nodiscard]] std::vector<std::string> SplitPathComponents(std::string_view filename); |
| 168 | 168 | ||
| 169 | // Gets all of the text up to the last '/' or '\' in the path. | 169 | // Gets all of the text up to the last '/' or '\' in the path. |
| 170 | std::string_view GetParentPath(std::string_view path); | 170 | [[nodiscard]] std::string_view GetParentPath(std::string_view path); |
| 171 | 171 | ||
| 172 | // Gets all of the text after the first '/' or '\' in the path. | 172 | // Gets all of the text after the first '/' or '\' in the path. |
| 173 | std::string_view GetPathWithoutTop(std::string_view path); | 173 | [[nodiscard]] std::string_view GetPathWithoutTop(std::string_view path); |
| 174 | 174 | ||
| 175 | // Gets the filename of the path | 175 | // Gets the filename of the path |
| 176 | std::string_view GetFilename(std::string_view path); | 176 | [[nodiscard]] std::string_view GetFilename(std::string_view path); |
| 177 | 177 | ||
| 178 | // Gets the extension of the filename | 178 | // Gets the extension of the filename |
| 179 | std::string_view GetExtensionFromFilename(std::string_view name); | 179 | [[nodiscard]] std::string_view GetExtensionFromFilename(std::string_view name); |
| 180 | 180 | ||
| 181 | // Removes the final '/' or '\' if one exists | 181 | // Removes the final '/' or '\' if one exists |
| 182 | std::string_view RemoveTrailingSlash(std::string_view path); | 182 | [[nodiscard]] std::string_view RemoveTrailingSlash(std::string_view path); |
| 183 | 183 | ||
| 184 | // Creates a new vector containing indices [first, last) from the original. | 184 | // Creates a new vector containing indices [first, last) from the original. |
| 185 | template <typename T> | 185 | template <typename T> |
| 186 | std::vector<T> SliceVector(const std::vector<T>& vector, std::size_t first, std::size_t last) { | 186 | [[nodiscard]] std::vector<T> SliceVector(const std::vector<T>& vector, std::size_t first, |
| 187 | if (first >= last) | 187 | std::size_t last) { |
| 188 | if (first >= last) { | ||
| 188 | return {}; | 189 | return {}; |
| 190 | } | ||
| 189 | last = std::min<std::size_t>(last, vector.size()); | 191 | last = std::min<std::size_t>(last, vector.size()); |
| 190 | return std::vector<T>(vector.begin() + first, vector.begin() + first + last); | 192 | return std::vector<T>(vector.begin() + first, vector.begin() + first + last); |
| 191 | } | 193 | } |
| 192 | 194 | ||
| 193 | enum class DirectorySeparator { ForwardSlash, BackwardSlash, PlatformDefault }; | 195 | enum class DirectorySeparator { |
| 196 | ForwardSlash, | ||
| 197 | BackwardSlash, | ||
| 198 | PlatformDefault, | ||
| 199 | }; | ||
| 194 | 200 | ||
| 195 | // Removes trailing slash, makes all '\\' into '/', and removes duplicate '/'. Makes '/' into '\\' | 201 | // Removes trailing slash, makes all '\\' into '/', and removes duplicate '/'. Makes '/' into '\\' |
| 196 | // depending if directory_separator is BackwardSlash or PlatformDefault and running on windows | 202 | // depending if directory_separator is BackwardSlash or PlatformDefault and running on windows |
| 197 | std::string SanitizePath(std::string_view path, | 203 | [[nodiscard]] std::string SanitizePath( |
| 198 | DirectorySeparator directory_separator = DirectorySeparator::ForwardSlash); | 204 | std::string_view path, |
| 205 | DirectorySeparator directory_separator = DirectorySeparator::ForwardSlash); | ||
| 206 | |||
| 207 | // To deal with Windows being dumb at Unicode | ||
| 208 | template <typename T> | ||
| 209 | void OpenFStream(T& fstream, const std::string& filename, std::ios_base::openmode openmode) { | ||
| 210 | #ifdef _MSC_VER | ||
| 211 | fstream.open(Common::UTF8ToUTF16W(filename), openmode); | ||
| 212 | #else | ||
| 213 | fstream.open(filename, openmode); | ||
| 214 | #endif | ||
| 215 | } | ||
| 199 | 216 | ||
| 200 | // simple wrapper for cstdlib file functions to | 217 | // simple wrapper for cstdlib file functions to |
| 201 | // hopefully will make error checking easier | 218 | // hopefully will make error checking easier |
| @@ -215,7 +232,7 @@ public: | |||
| 215 | 232 | ||
| 216 | void Swap(IOFile& other) noexcept; | 233 | void Swap(IOFile& other) noexcept; |
| 217 | 234 | ||
| 218 | bool Open(const std::string& filename, const char openmode[], int flags = 0); | 235 | [[nodiscard]] bool Open(const std::string& filename, const char openmode[], int flags = 0); |
| 219 | bool Close(); | 236 | bool Close(); |
| 220 | 237 | ||
| 221 | template <typename T> | 238 | template <typename T> |
| @@ -256,13 +273,13 @@ public: | |||
| 256 | return WriteArray(str.data(), str.length()); | 273 | return WriteArray(str.data(), str.length()); |
| 257 | } | 274 | } |
| 258 | 275 | ||
| 259 | bool IsOpen() const { | 276 | [[nodiscard]] bool IsOpen() const { |
| 260 | return nullptr != m_file; | 277 | return nullptr != m_file; |
| 261 | } | 278 | } |
| 262 | 279 | ||
| 263 | bool Seek(s64 off, int origin) const; | 280 | bool Seek(s64 off, int origin) const; |
| 264 | u64 Tell() const; | 281 | [[nodiscard]] u64 Tell() const; |
| 265 | u64 GetSize() const; | 282 | [[nodiscard]] u64 GetSize() const; |
| 266 | bool Resize(u64 size); | 283 | bool Resize(u64 size); |
| 267 | bool Flush(); | 284 | bool Flush(); |
| 268 | 285 | ||
| @@ -278,14 +295,4 @@ private: | |||
| 278 | std::FILE* m_file = nullptr; | 295 | std::FILE* m_file = nullptr; |
| 279 | }; | 296 | }; |
| 280 | 297 | ||
| 281 | } // namespace FileUtil | 298 | } // namespace Common::FS |
| 282 | |||
| 283 | // To deal with Windows being dumb at unicode: | ||
| 284 | template <typename T> | ||
| 285 | void OpenFStream(T& fstream, const std::string& filename, std::ios_base::openmode openmode) { | ||
| 286 | #ifdef _MSC_VER | ||
| 287 | fstream.open(Common::UTF8ToUTF16W(filename), openmode); | ||
| 288 | #else | ||
| 289 | fstream.open(filename, openmode); | ||
| 290 | #endif | ||
| 291 | } | ||
diff --git a/src/common/hash.h b/src/common/hash.h index b2538f3ea..298930702 100644 --- a/src/common/hash.h +++ b/src/common/hash.h | |||
| @@ -5,36 +5,11 @@ | |||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <cstddef> | 7 | #include <cstddef> |
| 8 | #include <cstring> | ||
| 9 | #include <utility> | 8 | #include <utility> |
| 10 | #include <boost/functional/hash.hpp> | 9 | #include <boost/functional/hash.hpp> |
| 11 | #include "common/cityhash.h" | ||
| 12 | #include "common/common_types.h" | ||
| 13 | 10 | ||
| 14 | namespace Common { | 11 | namespace Common { |
| 15 | 12 | ||
| 16 | /** | ||
| 17 | * Computes a 64-bit hash over the specified block of data | ||
| 18 | * @param data Block of data to compute hash over | ||
| 19 | * @param len Length of data (in bytes) to compute hash over | ||
| 20 | * @returns 64-bit hash value that was computed over the data block | ||
| 21 | */ | ||
| 22 | static inline u64 ComputeHash64(const void* data, std::size_t len) { | ||
| 23 | return CityHash64(static_cast<const char*>(data), len); | ||
| 24 | } | ||
| 25 | |||
| 26 | /** | ||
| 27 | * Computes a 64-bit hash of a struct. In addition to being trivially copyable, it is also critical | ||
| 28 | * that either the struct includes no padding, or that any padding is initialized to a known value | ||
| 29 | * by memsetting the struct to 0 before filling it in. | ||
| 30 | */ | ||
| 31 | template <typename T> | ||
| 32 | static inline u64 ComputeStructHash64(const T& data) { | ||
| 33 | static_assert(std::is_trivially_copyable_v<T>, | ||
| 34 | "Type passed to ComputeStructHash64 must be trivially copyable"); | ||
| 35 | return ComputeHash64(&data, sizeof(data)); | ||
| 36 | } | ||
| 37 | |||
| 38 | struct PairHash { | 13 | struct PairHash { |
| 39 | template <class T1, class T2> | 14 | template <class T1, class T2> |
| 40 | std::size_t operator()(const std::pair<T1, T2>& pair) const noexcept { | 15 | std::size_t operator()(const std::pair<T1, T2>& pair) const noexcept { |
diff --git a/src/common/hex_util.cpp b/src/common/hex_util.cpp index c2f6cf0f6..74f52dd11 100644 --- a/src/common/hex_util.cpp +++ b/src/common/hex_util.cpp | |||
| @@ -3,21 +3,9 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "common/hex_util.h" | 5 | #include "common/hex_util.h" |
| 6 | #include "common/logging/log.h" | ||
| 7 | 6 | ||
| 8 | namespace Common { | 7 | namespace Common { |
| 9 | 8 | ||
| 10 | u8 ToHexNibble(char c1) { | ||
| 11 | if (c1 >= 65 && c1 <= 70) | ||
| 12 | return c1 - 55; | ||
| 13 | if (c1 >= 97 && c1 <= 102) | ||
| 14 | return c1 - 87; | ||
| 15 | if (c1 >= 48 && c1 <= 57) | ||
| 16 | return c1 - 48; | ||
| 17 | LOG_ERROR(Common, "Invalid hex digit: 0x{:02X}", c1); | ||
| 18 | return 0; | ||
| 19 | } | ||
| 20 | |||
| 21 | std::vector<u8> HexStringToVector(std::string_view str, bool little_endian) { | 9 | std::vector<u8> HexStringToVector(std::string_view str, bool little_endian) { |
| 22 | std::vector<u8> out(str.size() / 2); | 10 | std::vector<u8> out(str.size() / 2); |
| 23 | if (little_endian) { | 11 | if (little_endian) { |
| @@ -30,26 +18,4 @@ std::vector<u8> HexStringToVector(std::string_view str, bool little_endian) { | |||
| 30 | return out; | 18 | return out; |
| 31 | } | 19 | } |
| 32 | 20 | ||
| 33 | std::array<u8, 16> operator""_array16(const char* str, std::size_t len) { | ||
| 34 | if (len != 32) { | ||
| 35 | LOG_ERROR(Common, | ||
| 36 | "Attempting to parse string to array that is not of correct size (expected=32, " | ||
| 37 | "actual={}).", | ||
| 38 | len); | ||
| 39 | return {}; | ||
| 40 | } | ||
| 41 | return HexStringToArray<16>(str); | ||
| 42 | } | ||
| 43 | |||
| 44 | std::array<u8, 32> operator""_array32(const char* str, std::size_t len) { | ||
| 45 | if (len != 64) { | ||
| 46 | LOG_ERROR(Common, | ||
| 47 | "Attempting to parse string to array that is not of correct size (expected=64, " | ||
| 48 | "actual={}).", | ||
| 49 | len); | ||
| 50 | return {}; | ||
| 51 | } | ||
| 52 | return HexStringToArray<32>(str); | ||
| 53 | } | ||
| 54 | |||
| 55 | } // namespace Common | 21 | } // namespace Common |
diff --git a/src/common/hex_util.h b/src/common/hex_util.h index bb4736f96..120f1a5e6 100644 --- a/src/common/hex_util.h +++ b/src/common/hex_util.h | |||
| @@ -14,25 +14,37 @@ | |||
| 14 | 14 | ||
| 15 | namespace Common { | 15 | namespace Common { |
| 16 | 16 | ||
| 17 | u8 ToHexNibble(char c1); | 17 | [[nodiscard]] constexpr u8 ToHexNibble(char c) { |
| 18 | if (c >= 65 && c <= 70) { | ||
| 19 | return c - 55; | ||
| 20 | } | ||
| 21 | |||
| 22 | if (c >= 97 && c <= 102) { | ||
| 23 | return c - 87; | ||
| 24 | } | ||
| 25 | |||
| 26 | return c - 48; | ||
| 27 | } | ||
| 18 | 28 | ||
| 19 | std::vector<u8> HexStringToVector(std::string_view str, bool little_endian); | 29 | [[nodiscard]] std::vector<u8> HexStringToVector(std::string_view str, bool little_endian); |
| 20 | 30 | ||
| 21 | template <std::size_t Size, bool le = false> | 31 | template <std::size_t Size, bool le = false> |
| 22 | std::array<u8, Size> HexStringToArray(std::string_view str) { | 32 | [[nodiscard]] constexpr std::array<u8, Size> HexStringToArray(std::string_view str) { |
| 23 | std::array<u8, Size> out{}; | 33 | std::array<u8, Size> out{}; |
| 24 | if constexpr (le) { | 34 | if constexpr (le) { |
| 25 | for (std::size_t i = 2 * Size - 2; i <= 2 * Size; i -= 2) | 35 | for (std::size_t i = 2 * Size - 2; i <= 2 * Size; i -= 2) { |
| 26 | out[i / 2] = (ToHexNibble(str[i]) << 4) | ToHexNibble(str[i + 1]); | 36 | out[i / 2] = (ToHexNibble(str[i]) << 4) | ToHexNibble(str[i + 1]); |
| 37 | } | ||
| 27 | } else { | 38 | } else { |
| 28 | for (std::size_t i = 0; i < 2 * Size; i += 2) | 39 | for (std::size_t i = 0; i < 2 * Size; i += 2) { |
| 29 | out[i / 2] = (ToHexNibble(str[i]) << 4) | ToHexNibble(str[i + 1]); | 40 | out[i / 2] = (ToHexNibble(str[i]) << 4) | ToHexNibble(str[i + 1]); |
| 41 | } | ||
| 30 | } | 42 | } |
| 31 | return out; | 43 | return out; |
| 32 | } | 44 | } |
| 33 | 45 | ||
| 34 | template <typename ContiguousContainer> | 46 | template <typename ContiguousContainer> |
| 35 | std::string HexToString(const ContiguousContainer& data, bool upper = true) { | 47 | [[nodiscard]] std::string HexToString(const ContiguousContainer& data, bool upper = true) { |
| 36 | static_assert(std::is_same_v<typename ContiguousContainer::value_type, u8>, | 48 | static_assert(std::is_same_v<typename ContiguousContainer::value_type, u8>, |
| 37 | "Underlying type within the contiguous container must be u8."); | 49 | "Underlying type within the contiguous container must be u8."); |
| 38 | 50 | ||
| @@ -48,7 +60,12 @@ std::string HexToString(const ContiguousContainer& data, bool upper = true) { | |||
| 48 | return out; | 60 | return out; |
| 49 | } | 61 | } |
| 50 | 62 | ||
| 51 | std::array<u8, 0x10> operator"" _array16(const char* str, std::size_t len); | 63 | [[nodiscard]] constexpr std::array<u8, 16> AsArray(const char (&data)[17]) { |
| 52 | std::array<u8, 0x20> operator"" _array32(const char* str, std::size_t len); | 64 | return HexStringToArray<16>(data); |
| 65 | } | ||
| 66 | |||
| 67 | [[nodiscard]] constexpr std::array<u8, 32> AsArray(const char (&data)[65]) { | ||
| 68 | return HexStringToArray<32>(data); | ||
| 69 | } | ||
| 53 | 70 | ||
| 54 | } // namespace Common | 71 | } // namespace Common |
diff --git a/src/common/logging/backend.h b/src/common/logging/backend.h index e5d702568..da1c2f185 100644 --- a/src/common/logging/backend.h +++ b/src/common/logging/backend.h | |||
| @@ -94,7 +94,7 @@ public: | |||
| 94 | void Write(const Entry& entry) override; | 94 | void Write(const Entry& entry) override; |
| 95 | 95 | ||
| 96 | private: | 96 | private: |
| 97 | FileUtil::IOFile file; | 97 | Common::FS::IOFile file; |
| 98 | std::size_t bytes_written; | 98 | std::size_t bytes_written; |
| 99 | }; | 99 | }; |
| 100 | 100 | ||
diff --git a/src/common/lz4_compression.cpp b/src/common/lz4_compression.cpp index ade6759bb..25700015a 100644 --- a/src/common/lz4_compression.cpp +++ b/src/common/lz4_compression.cpp | |||
| @@ -14,19 +14,19 @@ std::vector<u8> CompressDataLZ4(const u8* source, std::size_t source_size) { | |||
| 14 | ASSERT_MSG(source_size <= LZ4_MAX_INPUT_SIZE, "Source size exceeds LZ4 maximum input size"); | 14 | ASSERT_MSG(source_size <= LZ4_MAX_INPUT_SIZE, "Source size exceeds LZ4 maximum input size"); |
| 15 | 15 | ||
| 16 | const auto source_size_int = static_cast<int>(source_size); | 16 | const auto source_size_int = static_cast<int>(source_size); |
| 17 | const int max_compressed_size = LZ4_compressBound(source_size_int); | 17 | const auto max_compressed_size = static_cast<std::size_t>(LZ4_compressBound(source_size_int)); |
| 18 | std::vector<u8> compressed(max_compressed_size); | 18 | std::vector<u8> compressed(max_compressed_size); |
| 19 | 19 | ||
| 20 | const int compressed_size = LZ4_compress_default(reinterpret_cast<const char*>(source), | 20 | const int compressed_size = LZ4_compress_default( |
| 21 | reinterpret_cast<char*>(compressed.data()), | 21 | reinterpret_cast<const char*>(source), reinterpret_cast<char*>(compressed.data()), |
| 22 | source_size_int, max_compressed_size); | 22 | source_size_int, static_cast<int>(max_compressed_size)); |
| 23 | 23 | ||
| 24 | if (compressed_size <= 0) { | 24 | if (compressed_size <= 0) { |
| 25 | // Compression failed | 25 | // Compression failed |
| 26 | return {}; | 26 | return {}; |
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | compressed.resize(compressed_size); | 29 | compressed.resize(static_cast<std::size_t>(compressed_size)); |
| 30 | 30 | ||
| 31 | return compressed; | 31 | return compressed; |
| 32 | } | 32 | } |
| @@ -38,19 +38,19 @@ std::vector<u8> CompressDataLZ4HC(const u8* source, std::size_t source_size, | |||
| 38 | compression_level = std::clamp(compression_level, LZ4HC_CLEVEL_MIN, LZ4HC_CLEVEL_MAX); | 38 | compression_level = std::clamp(compression_level, LZ4HC_CLEVEL_MIN, LZ4HC_CLEVEL_MAX); |
| 39 | 39 | ||
| 40 | const auto source_size_int = static_cast<int>(source_size); | 40 | const auto source_size_int = static_cast<int>(source_size); |
| 41 | const int max_compressed_size = LZ4_compressBound(source_size_int); | 41 | const auto max_compressed_size = static_cast<std::size_t>(LZ4_compressBound(source_size_int)); |
| 42 | std::vector<u8> compressed(max_compressed_size); | 42 | std::vector<u8> compressed(max_compressed_size); |
| 43 | 43 | ||
| 44 | const int compressed_size = LZ4_compress_HC( | 44 | const int compressed_size = LZ4_compress_HC( |
| 45 | reinterpret_cast<const char*>(source), reinterpret_cast<char*>(compressed.data()), | 45 | reinterpret_cast<const char*>(source), reinterpret_cast<char*>(compressed.data()), |
| 46 | source_size_int, max_compressed_size, compression_level); | 46 | source_size_int, static_cast<int>(max_compressed_size), compression_level); |
| 47 | 47 | ||
| 48 | if (compressed_size <= 0) { | 48 | if (compressed_size <= 0) { |
| 49 | // Compression failed | 49 | // Compression failed |
| 50 | return {}; | 50 | return {}; |
| 51 | } | 51 | } |
| 52 | 52 | ||
| 53 | compressed.resize(compressed_size); | 53 | compressed.resize(static_cast<std::size_t>(compressed_size)); |
| 54 | 54 | ||
| 55 | return compressed; | 55 | return compressed; |
| 56 | } | 56 | } |
diff --git a/src/common/lz4_compression.h b/src/common/lz4_compression.h index 4c16f6e03..87a4be1b0 100644 --- a/src/common/lz4_compression.h +++ b/src/common/lz4_compression.h | |||
| @@ -13,12 +13,12 @@ namespace Common::Compression { | |||
| 13 | /** | 13 | /** |
| 14 | * Compresses a source memory region with LZ4 and returns the compressed data in a vector. | 14 | * Compresses a source memory region with LZ4 and returns the compressed data in a vector. |
| 15 | * | 15 | * |
| 16 | * @param source the uncompressed source memory region. | 16 | * @param source The uncompressed source memory region. |
| 17 | * @param source_size the size in bytes of the uncompressed source memory region. | 17 | * @param source_size The size of the uncompressed source memory region. |
| 18 | * | 18 | * |
| 19 | * @return the compressed data. | 19 | * @return the compressed data. |
| 20 | */ | 20 | */ |
| 21 | std::vector<u8> CompressDataLZ4(const u8* source, std::size_t source_size); | 21 | [[nodiscard]] std::vector<u8> CompressDataLZ4(const u8* source, std::size_t source_size); |
| 22 | 22 | ||
| 23 | /** | 23 | /** |
| 24 | * Utilizes the LZ4 subalgorithm LZ4HC with the specified compression level. Higher compression | 24 | * Utilizes the LZ4 subalgorithm LZ4HC with the specified compression level. Higher compression |
| @@ -26,23 +26,24 @@ std::vector<u8> CompressDataLZ4(const u8* source, std::size_t source_size); | |||
| 26 | * compression level has almost no impact on decompression speed. Data compressed with LZ4HC can | 26 | * compression level has almost no impact on decompression speed. Data compressed with LZ4HC can |
| 27 | * also be decompressed with the default LZ4 decompression. | 27 | * also be decompressed with the default LZ4 decompression. |
| 28 | * | 28 | * |
| 29 | * @param source the uncompressed source memory region. | 29 | * @param source The uncompressed source memory region. |
| 30 | * @param source_size the size in bytes of the uncompressed source memory region. | 30 | * @param source_size The size of the uncompressed source memory region. |
| 31 | * @param compression_level the used compression level. Should be between 3 and 12. | 31 | * @param compression_level The used compression level. Should be between 3 and 12. |
| 32 | * | 32 | * |
| 33 | * @return the compressed data. | 33 | * @return the compressed data. |
| 34 | */ | 34 | */ |
| 35 | std::vector<u8> CompressDataLZ4HC(const u8* source, std::size_t source_size, s32 compression_level); | 35 | [[nodiscard]] std::vector<u8> CompressDataLZ4HC(const u8* source, std::size_t source_size, |
| 36 | s32 compression_level); | ||
| 36 | 37 | ||
| 37 | /** | 38 | /** |
| 38 | * Utilizes the LZ4 subalgorithm LZ4HC with the highest possible compression level. | 39 | * Utilizes the LZ4 subalgorithm LZ4HC with the highest possible compression level. |
| 39 | * | 40 | * |
| 40 | * @param source the uncompressed source memory region. | 41 | * @param source The uncompressed source memory region. |
| 41 | * @param source_size the size in bytes of the uncompressed source memory region. | 42 | * @param source_size The size of the uncompressed source memory region |
| 42 | * | 43 | * |
| 43 | * @return the compressed data. | 44 | * @return the compressed data. |
| 44 | */ | 45 | */ |
| 45 | std::vector<u8> CompressDataLZ4HCMax(const u8* source, std::size_t source_size); | 46 | [[nodiscard]] std::vector<u8> CompressDataLZ4HCMax(const u8* source, std::size_t source_size); |
| 46 | 47 | ||
| 47 | /** | 48 | /** |
| 48 | * Decompresses a source memory region with LZ4 and returns the uncompressed data in a vector. | 49 | * Decompresses a source memory region with LZ4 and returns the uncompressed data in a vector. |
| @@ -52,6 +53,7 @@ std::vector<u8> CompressDataLZ4HCMax(const u8* source, std::size_t source_size); | |||
| 52 | * | 53 | * |
| 53 | * @return the decompressed data. | 54 | * @return the decompressed data. |
| 54 | */ | 55 | */ |
| 55 | std::vector<u8> DecompressDataLZ4(const std::vector<u8>& compressed, std::size_t uncompressed_size); | 56 | [[nodiscard]] std::vector<u8> DecompressDataLZ4(const std::vector<u8>& compressed, |
| 57 | std::size_t uncompressed_size); | ||
| 56 | 58 | ||
| 57 | } // namespace Common::Compression \ No newline at end of file | 59 | } // namespace Common::Compression \ No newline at end of file |
diff --git a/src/common/math_util.h b/src/common/math_util.h index 83ef0201f..cc35c90ee 100644 --- a/src/common/math_util.h +++ b/src/common/math_util.h | |||
| @@ -23,7 +23,7 @@ struct Rectangle { | |||
| 23 | constexpr Rectangle(T left, T top, T right, T bottom) | 23 | constexpr Rectangle(T left, T top, T right, T bottom) |
| 24 | : left(left), top(top), right(right), bottom(bottom) {} | 24 | : left(left), top(top), right(right), bottom(bottom) {} |
| 25 | 25 | ||
| 26 | T GetWidth() const { | 26 | [[nodiscard]] T GetWidth() const { |
| 27 | if constexpr (std::is_floating_point_v<T>) { | 27 | if constexpr (std::is_floating_point_v<T>) { |
| 28 | return std::abs(right - left); | 28 | return std::abs(right - left); |
| 29 | } else { | 29 | } else { |
| @@ -31,7 +31,7 @@ struct Rectangle { | |||
| 31 | } | 31 | } |
| 32 | } | 32 | } |
| 33 | 33 | ||
| 34 | T GetHeight() const { | 34 | [[nodiscard]] T GetHeight() const { |
| 35 | if constexpr (std::is_floating_point_v<T>) { | 35 | if constexpr (std::is_floating_point_v<T>) { |
| 36 | return std::abs(bottom - top); | 36 | return std::abs(bottom - top); |
| 37 | } else { | 37 | } else { |
| @@ -39,21 +39,21 @@ struct Rectangle { | |||
| 39 | } | 39 | } |
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | Rectangle<T> TranslateX(const T x) const { | 42 | [[nodiscard]] Rectangle<T> TranslateX(const T x) const { |
| 43 | return Rectangle{left + x, top, right + x, bottom}; | 43 | return Rectangle{left + x, top, right + x, bottom}; |
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | Rectangle<T> TranslateY(const T y) const { | 46 | [[nodiscard]] Rectangle<T> TranslateY(const T y) const { |
| 47 | return Rectangle{left, top + y, right, bottom + y}; | 47 | return Rectangle{left, top + y, right, bottom + y}; |
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | Rectangle<T> Scale(const float s) const { | 50 | [[nodiscard]] Rectangle<T> Scale(const float s) const { |
| 51 | return Rectangle{left, top, static_cast<T>(left + GetWidth() * s), | 51 | return Rectangle{left, top, static_cast<T>(left + GetWidth() * s), |
| 52 | static_cast<T>(top + GetHeight() * s)}; | 52 | static_cast<T>(top + GetHeight() * s)}; |
| 53 | } | 53 | } |
| 54 | }; | 54 | }; |
| 55 | 55 | ||
| 56 | template <typename T> | 56 | template <typename T> |
| 57 | Rectangle(T, T, T, T)->Rectangle<T>; | 57 | Rectangle(T, T, T, T) -> Rectangle<T>; |
| 58 | 58 | ||
| 59 | } // namespace Common | 59 | } // namespace Common |
diff --git a/src/common/memory_detect.h b/src/common/memory_detect.h index a73c0f3f4..0f73751c8 100644 --- a/src/common/memory_detect.h +++ b/src/common/memory_detect.h | |||
| @@ -17,6 +17,6 @@ struct MemoryInfo { | |||
| 17 | * Gets the memory info of the host system | 17 | * Gets the memory info of the host system |
| 18 | * @return Reference to a MemoryInfo struct with the physical and swap memory sizes in bytes | 18 | * @return Reference to a MemoryInfo struct with the physical and swap memory sizes in bytes |
| 19 | */ | 19 | */ |
| 20 | const MemoryInfo& GetMemInfo(); | 20 | [[nodiscard]] const MemoryInfo& GetMemInfo(); |
| 21 | 21 | ||
| 22 | } // namespace Common \ No newline at end of file | 22 | } // namespace Common \ No newline at end of file |
diff --git a/src/common/multi_level_queue.h b/src/common/multi_level_queue.h index 50acfdbf2..4b305bf40 100644 --- a/src/common/multi_level_queue.h +++ b/src/common/multi_level_queue.h | |||
| @@ -223,15 +223,15 @@ public: | |||
| 223 | ListShiftForward(levels[priority], n); | 223 | ListShiftForward(levels[priority], n); |
| 224 | } | 224 | } |
| 225 | 225 | ||
| 226 | std::size_t depth() const { | 226 | [[nodiscard]] std::size_t depth() const { |
| 227 | return Depth; | 227 | return Depth; |
| 228 | } | 228 | } |
| 229 | 229 | ||
| 230 | std::size_t size(u32 priority) const { | 230 | [[nodiscard]] std::size_t size(u32 priority) const { |
| 231 | return levels[priority].size(); | 231 | return levels[priority].size(); |
| 232 | } | 232 | } |
| 233 | 233 | ||
| 234 | std::size_t size() const { | 234 | [[nodiscard]] std::size_t size() const { |
| 235 | u64 priorities = used_priorities; | 235 | u64 priorities = used_priorities; |
| 236 | std::size_t size = 0; | 236 | std::size_t size = 0; |
| 237 | while (priorities != 0) { | 237 | while (priorities != 0) { |
| @@ -242,64 +242,64 @@ public: | |||
| 242 | return size; | 242 | return size; |
| 243 | } | 243 | } |
| 244 | 244 | ||
| 245 | bool empty() const { | 245 | [[nodiscard]] bool empty() const { |
| 246 | return used_priorities == 0; | 246 | return used_priorities == 0; |
| 247 | } | 247 | } |
| 248 | 248 | ||
| 249 | bool empty(u32 priority) const { | 249 | [[nodiscard]] bool empty(u32 priority) const { |
| 250 | return (used_priorities & (1ULL << priority)) == 0; | 250 | return (used_priorities & (1ULL << priority)) == 0; |
| 251 | } | 251 | } |
| 252 | 252 | ||
| 253 | u32 highest_priority_set(u32 max_priority = 0) const { | 253 | [[nodiscard]] u32 highest_priority_set(u32 max_priority = 0) const { |
| 254 | const u64 priorities = | 254 | const u64 priorities = |
| 255 | max_priority == 0 ? used_priorities : (used_priorities & ~((1ULL << max_priority) - 1)); | 255 | max_priority == 0 ? used_priorities : (used_priorities & ~((1ULL << max_priority) - 1)); |
| 256 | return priorities == 0 ? Depth : static_cast<u32>(CountTrailingZeroes64(priorities)); | 256 | return priorities == 0 ? Depth : static_cast<u32>(CountTrailingZeroes64(priorities)); |
| 257 | } | 257 | } |
| 258 | 258 | ||
| 259 | u32 lowest_priority_set(u32 min_priority = Depth - 1) const { | 259 | [[nodiscard]] u32 lowest_priority_set(u32 min_priority = Depth - 1) const { |
| 260 | const u64 priorities = min_priority >= Depth - 1 | 260 | const u64 priorities = min_priority >= Depth - 1 |
| 261 | ? used_priorities | 261 | ? used_priorities |
| 262 | : (used_priorities & ((1ULL << (min_priority + 1)) - 1)); | 262 | : (used_priorities & ((1ULL << (min_priority + 1)) - 1)); |
| 263 | return priorities == 0 ? Depth : 63 - CountLeadingZeroes64(priorities); | 263 | return priorities == 0 ? Depth : 63 - CountLeadingZeroes64(priorities); |
| 264 | } | 264 | } |
| 265 | 265 | ||
| 266 | const_iterator cbegin(u32 max_prio = 0) const { | 266 | [[nodiscard]] const_iterator cbegin(u32 max_prio = 0) const { |
| 267 | const u32 priority = highest_priority_set(max_prio); | 267 | const u32 priority = highest_priority_set(max_prio); |
| 268 | return priority == Depth ? cend() | 268 | return priority == Depth ? cend() |
| 269 | : const_iterator{*this, levels[priority].cbegin(), priority}; | 269 | : const_iterator{*this, levels[priority].cbegin(), priority}; |
| 270 | } | 270 | } |
| 271 | const_iterator begin(u32 max_prio = 0) const { | 271 | [[nodiscard]] const_iterator begin(u32 max_prio = 0) const { |
| 272 | return cbegin(max_prio); | 272 | return cbegin(max_prio); |
| 273 | } | 273 | } |
| 274 | iterator begin(u32 max_prio = 0) { | 274 | [[nodiscard]] iterator begin(u32 max_prio = 0) { |
| 275 | const u32 priority = highest_priority_set(max_prio); | 275 | const u32 priority = highest_priority_set(max_prio); |
| 276 | return priority == Depth ? end() : iterator{*this, levels[priority].begin(), priority}; | 276 | return priority == Depth ? end() : iterator{*this, levels[priority].begin(), priority}; |
| 277 | } | 277 | } |
| 278 | 278 | ||
| 279 | const_iterator cend(u32 min_prio = Depth - 1) const { | 279 | [[nodiscard]] const_iterator cend(u32 min_prio = Depth - 1) const { |
| 280 | return min_prio == Depth - 1 ? const_iterator{*this, Depth} : cbegin(min_prio + 1); | 280 | return min_prio == Depth - 1 ? const_iterator{*this, Depth} : cbegin(min_prio + 1); |
| 281 | } | 281 | } |
| 282 | const_iterator end(u32 min_prio = Depth - 1) const { | 282 | [[nodiscard]] const_iterator end(u32 min_prio = Depth - 1) const { |
| 283 | return cend(min_prio); | 283 | return cend(min_prio); |
| 284 | } | 284 | } |
| 285 | iterator end(u32 min_prio = Depth - 1) { | 285 | [[nodiscard]] iterator end(u32 min_prio = Depth - 1) { |
| 286 | return min_prio == Depth - 1 ? iterator{*this, Depth} : begin(min_prio + 1); | 286 | return min_prio == Depth - 1 ? iterator{*this, Depth} : begin(min_prio + 1); |
| 287 | } | 287 | } |
| 288 | 288 | ||
| 289 | T& front(u32 max_priority = 0) { | 289 | [[nodiscard]] T& front(u32 max_priority = 0) { |
| 290 | const u32 priority = highest_priority_set(max_priority); | 290 | const u32 priority = highest_priority_set(max_priority); |
| 291 | return levels[priority == Depth ? 0 : priority].front(); | 291 | return levels[priority == Depth ? 0 : priority].front(); |
| 292 | } | 292 | } |
| 293 | const T& front(u32 max_priority = 0) const { | 293 | [[nodiscard]] const T& front(u32 max_priority = 0) const { |
| 294 | const u32 priority = highest_priority_set(max_priority); | 294 | const u32 priority = highest_priority_set(max_priority); |
| 295 | return levels[priority == Depth ? 0 : priority].front(); | 295 | return levels[priority == Depth ? 0 : priority].front(); |
| 296 | } | 296 | } |
| 297 | 297 | ||
| 298 | T back(u32 min_priority = Depth - 1) { | 298 | [[nodiscard]] T& back(u32 min_priority = Depth - 1) { |
| 299 | const u32 priority = lowest_priority_set(min_priority); // intended | 299 | const u32 priority = lowest_priority_set(min_priority); // intended |
| 300 | return levels[priority == Depth ? 63 : priority].back(); | 300 | return levels[priority == Depth ? 63 : priority].back(); |
| 301 | } | 301 | } |
| 302 | const T& back(u32 min_priority = Depth - 1) const { | 302 | [[nodiscard]] const T& back(u32 min_priority = Depth - 1) const { |
| 303 | const u32 priority = lowest_priority_set(min_priority); // intended | 303 | const u32 priority = lowest_priority_set(min_priority); // intended |
| 304 | return levels[priority == Depth ? 63 : priority].back(); | 304 | return levels[priority == Depth ? 63 : priority].back(); |
| 305 | } | 305 | } |
| @@ -329,7 +329,8 @@ private: | |||
| 329 | in_list.splice(position, out_list, element); | 329 | in_list.splice(position, out_list, element); |
| 330 | } | 330 | } |
| 331 | 331 | ||
| 332 | static const_list_iterator ListIterateTo(const std::list<T>& list, const T& element) { | 332 | [[nodiscard]] static const_list_iterator ListIterateTo(const std::list<T>& list, |
| 333 | const T& element) { | ||
| 333 | auto it = list.cbegin(); | 334 | auto it = list.cbegin(); |
| 334 | while (it != list.cend() && *it != element) { | 335 | while (it != list.cend() && *it != element) { |
| 335 | ++it; | 336 | ++it; |
diff --git a/src/common/page_table.h b/src/common/page_table.h index 1e8bd3187..cf5eed780 100644 --- a/src/common/page_table.h +++ b/src/common/page_table.h | |||
| @@ -36,11 +36,11 @@ struct SpecialRegion { | |||
| 36 | 36 | ||
| 37 | MemoryHookPointer handler; | 37 | MemoryHookPointer handler; |
| 38 | 38 | ||
| 39 | bool operator<(const SpecialRegion& other) const { | 39 | [[nodiscard]] bool operator<(const SpecialRegion& other) const { |
| 40 | return std::tie(type, handler) < std::tie(other.type, other.handler); | 40 | return std::tie(type, handler) < std::tie(other.type, other.handler); |
| 41 | } | 41 | } |
| 42 | 42 | ||
| 43 | bool operator==(const SpecialRegion& other) const { | 43 | [[nodiscard]] bool operator==(const SpecialRegion& other) const { |
| 44 | return std::tie(type, handler) == std::tie(other.type, other.handler); | 44 | return std::tie(type, handler) == std::tie(other.type, other.handler); |
| 45 | } | 45 | } |
| 46 | }; | 46 | }; |
diff --git a/src/common/param_package.h b/src/common/param_package.h index 6a0a9b656..c13e45479 100644 --- a/src/common/param_package.h +++ b/src/common/param_package.h | |||
| @@ -19,19 +19,19 @@ public: | |||
| 19 | explicit ParamPackage(const std::string& serialized); | 19 | explicit ParamPackage(const std::string& serialized); |
| 20 | ParamPackage(std::initializer_list<DataType::value_type> list); | 20 | ParamPackage(std::initializer_list<DataType::value_type> list); |
| 21 | ParamPackage(const ParamPackage& other) = default; | 21 | ParamPackage(const ParamPackage& other) = default; |
| 22 | ParamPackage(ParamPackage&& other) = default; | 22 | ParamPackage(ParamPackage&& other) noexcept = default; |
| 23 | 23 | ||
| 24 | ParamPackage& operator=(const ParamPackage& other) = default; | 24 | ParamPackage& operator=(const ParamPackage& other) = default; |
| 25 | ParamPackage& operator=(ParamPackage&& other) = default; | 25 | ParamPackage& operator=(ParamPackage&& other) = default; |
| 26 | 26 | ||
| 27 | std::string Serialize() const; | 27 | [[nodiscard]] std::string Serialize() const; |
| 28 | std::string Get(const std::string& key, const std::string& default_value) const; | 28 | [[nodiscard]] std::string Get(const std::string& key, const std::string& default_value) const; |
| 29 | int Get(const std::string& key, int default_value) const; | 29 | [[nodiscard]] int Get(const std::string& key, int default_value) const; |
| 30 | float Get(const std::string& key, float default_value) const; | 30 | [[nodiscard]] float Get(const std::string& key, float default_value) const; |
| 31 | void Set(const std::string& key, std::string value); | 31 | void Set(const std::string& key, std::string value); |
| 32 | void Set(const std::string& key, int value); | 32 | void Set(const std::string& key, int value); |
| 33 | void Set(const std::string& key, float value); | 33 | void Set(const std::string& key, float value); |
| 34 | bool Has(const std::string& key) const; | 34 | [[nodiscard]] bool Has(const std::string& key) const; |
| 35 | void Erase(const std::string& key); | 35 | void Erase(const std::string& key); |
| 36 | void Clear(); | 36 | void Clear(); |
| 37 | 37 | ||
diff --git a/src/common/quaternion.h b/src/common/quaternion.h index 370198ae0..da44f35cd 100644 --- a/src/common/quaternion.h +++ b/src/common/quaternion.h | |||
| @@ -14,35 +14,36 @@ public: | |||
| 14 | Vec3<T> xyz; | 14 | Vec3<T> xyz; |
| 15 | T w{}; | 15 | T w{}; |
| 16 | 16 | ||
| 17 | Quaternion<decltype(-T{})> Inverse() const { | 17 | [[nodiscard]] Quaternion<decltype(-T{})> Inverse() const { |
| 18 | return {-xyz, w}; | 18 | return {-xyz, w}; |
| 19 | } | 19 | } |
| 20 | 20 | ||
| 21 | Quaternion<decltype(T{} + T{})> operator+(const Quaternion& other) const { | 21 | [[nodiscard]] Quaternion<decltype(T{} + T{})> operator+(const Quaternion& other) const { |
| 22 | return {xyz + other.xyz, w + other.w}; | 22 | return {xyz + other.xyz, w + other.w}; |
| 23 | } | 23 | } |
| 24 | 24 | ||
| 25 | Quaternion<decltype(T{} - T{})> operator-(const Quaternion& other) const { | 25 | [[nodiscard]] Quaternion<decltype(T{} - T{})> operator-(const Quaternion& other) const { |
| 26 | return {xyz - other.xyz, w - other.w}; | 26 | return {xyz - other.xyz, w - other.w}; |
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | Quaternion<decltype(T{} * T{} - T{} * T{})> operator*(const Quaternion& other) const { | 29 | [[nodiscard]] Quaternion<decltype(T{} * T{} - T{} * T{})> operator*( |
| 30 | const Quaternion& other) const { | ||
| 30 | return {xyz * other.w + other.xyz * w + Cross(xyz, other.xyz), | 31 | return {xyz * other.w + other.xyz * w + Cross(xyz, other.xyz), |
| 31 | w * other.w - Dot(xyz, other.xyz)}; | 32 | w * other.w - Dot(xyz, other.xyz)}; |
| 32 | } | 33 | } |
| 33 | 34 | ||
| 34 | Quaternion<T> Normalized() const { | 35 | [[nodiscard]] Quaternion<T> Normalized() const { |
| 35 | T length = std::sqrt(xyz.Length2() + w * w); | 36 | T length = std::sqrt(xyz.Length2() + w * w); |
| 36 | return {xyz / length, w / length}; | 37 | return {xyz / length, w / length}; |
| 37 | } | 38 | } |
| 38 | }; | 39 | }; |
| 39 | 40 | ||
| 40 | template <typename T> | 41 | template <typename T> |
| 41 | auto QuaternionRotate(const Quaternion<T>& q, const Vec3<T>& v) { | 42 | [[nodiscard]] auto QuaternionRotate(const Quaternion<T>& q, const Vec3<T>& v) { |
| 42 | return v + 2 * Cross(q.xyz, Cross(q.xyz, v) + v * q.w); | 43 | return v + 2 * Cross(q.xyz, Cross(q.xyz, v) + v * q.w); |
| 43 | } | 44 | } |
| 44 | 45 | ||
| 45 | inline Quaternion<float> MakeQuaternion(const Vec3<float>& axis, float angle) { | 46 | [[nodiscard]] inline Quaternion<float> MakeQuaternion(const Vec3<float>& axis, float angle) { |
| 46 | return {axis * std::sin(angle / 2), std::cos(angle / 2)}; | 47 | return {axis * std::sin(angle / 2), std::cos(angle / 2)}; |
| 47 | } | 48 | } |
| 48 | 49 | ||
diff --git a/src/common/ring_buffer.h b/src/common/ring_buffer.h index abe3b4dc2..138fa0131 100644 --- a/src/common/ring_buffer.h +++ b/src/common/ring_buffer.h | |||
| @@ -91,12 +91,12 @@ public: | |||
| 91 | } | 91 | } |
| 92 | 92 | ||
| 93 | /// @returns Number of slots used | 93 | /// @returns Number of slots used |
| 94 | std::size_t Size() const { | 94 | [[nodiscard]] std::size_t Size() const { |
| 95 | return m_write_index.load() - m_read_index.load(); | 95 | return m_write_index.load() - m_read_index.load(); |
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | /// @returns Maximum size of ring buffer | 98 | /// @returns Maximum size of ring buffer |
| 99 | constexpr std::size_t Capacity() const { | 99 | [[nodiscard]] constexpr std::size_t Capacity() const { |
| 100 | return capacity; | 100 | return capacity; |
| 101 | } | 101 | } |
| 102 | 102 | ||
diff --git a/src/common/spin_lock.h b/src/common/spin_lock.h index 1df5528c4..4f946a258 100644 --- a/src/common/spin_lock.h +++ b/src/common/spin_lock.h | |||
| @@ -17,7 +17,7 @@ class SpinLock { | |||
| 17 | public: | 17 | public: |
| 18 | void lock(); | 18 | void lock(); |
| 19 | void unlock(); | 19 | void unlock(); |
| 20 | bool try_lock(); | 20 | [[nodiscard]] bool try_lock(); |
| 21 | 21 | ||
| 22 | private: | 22 | private: |
| 23 | std::atomic_flag lck = ATOMIC_FLAG_INIT; | 23 | std::atomic_flag lck = ATOMIC_FLAG_INIT; |
diff --git a/src/common/string_util.h b/src/common/string_util.h index 023dff5dc..a32c07c06 100644 --- a/src/common/string_util.h +++ b/src/common/string_util.h | |||
| @@ -12,19 +12,19 @@ | |||
| 12 | namespace Common { | 12 | namespace Common { |
| 13 | 13 | ||
| 14 | /// Make a string lowercase | 14 | /// Make a string lowercase |
| 15 | std::string ToLower(std::string str); | 15 | [[nodiscard]] std::string ToLower(std::string str); |
| 16 | 16 | ||
| 17 | /// Make a string uppercase | 17 | /// Make a string uppercase |
| 18 | std::string ToUpper(std::string str); | 18 | [[nodiscard]] std::string ToUpper(std::string str); |
| 19 | 19 | ||
| 20 | std::string StringFromBuffer(const std::vector<u8>& data); | 20 | [[nodiscard]] std::string StringFromBuffer(const std::vector<u8>& data); |
| 21 | 21 | ||
| 22 | std::string StripSpaces(const std::string& s); | 22 | [[nodiscard]] std::string StripSpaces(const std::string& s); |
| 23 | std::string StripQuotes(const std::string& s); | 23 | [[nodiscard]] std::string StripQuotes(const std::string& s); |
| 24 | 24 | ||
| 25 | std::string StringFromBool(bool value); | 25 | [[nodiscard]] std::string StringFromBool(bool value); |
| 26 | 26 | ||
| 27 | std::string TabsToSpaces(int tab_size, std::string in); | 27 | [[nodiscard]] std::string TabsToSpaces(int tab_size, std::string in); |
| 28 | 28 | ||
| 29 | void SplitString(const std::string& str, char delim, std::vector<std::string>& output); | 29 | void SplitString(const std::string& str, char delim, std::vector<std::string>& output); |
| 30 | 30 | ||
| @@ -34,14 +34,15 @@ bool SplitPath(const std::string& full_path, std::string* _pPath, std::string* _ | |||
| 34 | 34 | ||
| 35 | void BuildCompleteFilename(std::string& _CompleteFilename, const std::string& _Path, | 35 | void BuildCompleteFilename(std::string& _CompleteFilename, const std::string& _Path, |
| 36 | const std::string& _Filename); | 36 | const std::string& _Filename); |
| 37 | std::string ReplaceAll(std::string result, const std::string& src, const std::string& dest); | 37 | [[nodiscard]] std::string ReplaceAll(std::string result, const std::string& src, |
| 38 | const std::string& dest); | ||
| 38 | 39 | ||
| 39 | std::string UTF16ToUTF8(const std::u16string& input); | 40 | [[nodiscard]] std::string UTF16ToUTF8(const std::u16string& input); |
| 40 | std::u16string UTF8ToUTF16(const std::string& input); | 41 | [[nodiscard]] std::u16string UTF8ToUTF16(const std::string& input); |
| 41 | 42 | ||
| 42 | #ifdef _WIN32 | 43 | #ifdef _WIN32 |
| 43 | std::string UTF16ToUTF8(const std::wstring& input); | 44 | [[nodiscard]] std::string UTF16ToUTF8(const std::wstring& input); |
| 44 | std::wstring UTF8ToUTF16W(const std::string& str); | 45 | [[nodiscard]] std::wstring UTF8ToUTF16W(const std::string& str); |
| 45 | 46 | ||
| 46 | #endif | 47 | #endif |
| 47 | 48 | ||
| @@ -50,7 +51,7 @@ std::wstring UTF8ToUTF16W(const std::string& str); | |||
| 50 | * `other` for equality. | 51 | * `other` for equality. |
| 51 | */ | 52 | */ |
| 52 | template <typename InIt> | 53 | template <typename InIt> |
| 53 | bool ComparePartialString(InIt begin, InIt end, const char* other) { | 54 | [[nodiscard]] bool ComparePartialString(InIt begin, InIt end, const char* other) { |
| 54 | for (; begin != end && *other != '\0'; ++begin, ++other) { | 55 | for (; begin != end && *other != '\0'; ++begin, ++other) { |
| 55 | if (*begin != *other) { | 56 | if (*begin != *other) { |
| 56 | return false; | 57 | return false; |
| @@ -64,14 +65,15 @@ bool ComparePartialString(InIt begin, InIt end, const char* other) { | |||
| 64 | * Creates a std::string from a fixed-size NUL-terminated char buffer. If the buffer isn't | 65 | * Creates a std::string from a fixed-size NUL-terminated char buffer. If the buffer isn't |
| 65 | * NUL-terminated then the string ends at max_len characters. | 66 | * NUL-terminated then the string ends at max_len characters. |
| 66 | */ | 67 | */ |
| 67 | std::string StringFromFixedZeroTerminatedBuffer(const char* buffer, std::size_t max_len); | 68 | [[nodiscard]] std::string StringFromFixedZeroTerminatedBuffer(const char* buffer, |
| 69 | std::size_t max_len); | ||
| 68 | 70 | ||
| 69 | /** | 71 | /** |
| 70 | * Creates a UTF-16 std::u16string from a fixed-size NUL-terminated char buffer. If the buffer isn't | 72 | * Creates a UTF-16 std::u16string from a fixed-size NUL-terminated char buffer. If the buffer isn't |
| 71 | * null-terminated, then the string ends at the greatest multiple of two less then or equal to | 73 | * null-terminated, then the string ends at the greatest multiple of two less then or equal to |
| 72 | * max_len_bytes. | 74 | * max_len_bytes. |
| 73 | */ | 75 | */ |
| 74 | std::u16string UTF16StringFromFixedZeroTerminatedBuffer(std::u16string_view buffer, | 76 | [[nodiscard]] std::u16string UTF16StringFromFixedZeroTerminatedBuffer(std::u16string_view buffer, |
| 75 | std::size_t max_len); | 77 | std::size_t max_len); |
| 76 | 78 | ||
| 77 | } // namespace Common | 79 | } // namespace Common |
diff --git a/src/common/telemetry.cpp b/src/common/telemetry.cpp index 16d42facd..6241d08b3 100644 --- a/src/common/telemetry.cpp +++ b/src/common/telemetry.cpp | |||
| @@ -12,7 +12,7 @@ | |||
| 12 | #include "common/x64/cpu_detect.h" | 12 | #include "common/x64/cpu_detect.h" |
| 13 | #endif | 13 | #endif |
| 14 | 14 | ||
| 15 | namespace Telemetry { | 15 | namespace Common::Telemetry { |
| 16 | 16 | ||
| 17 | void FieldCollection::Accept(VisitorInterface& visitor) const { | 17 | void FieldCollection::Accept(VisitorInterface& visitor) const { |
| 18 | for (const auto& field : fields) { | 18 | for (const auto& field : fields) { |
| @@ -88,4 +88,4 @@ void AppendOSInfo(FieldCollection& fc) { | |||
| 88 | #endif | 88 | #endif |
| 89 | } | 89 | } |
| 90 | 90 | ||
| 91 | } // namespace Telemetry | 91 | } // namespace Common::Telemetry |
diff --git a/src/common/telemetry.h b/src/common/telemetry.h index 854a73fae..a50c5d1de 100644 --- a/src/common/telemetry.h +++ b/src/common/telemetry.h | |||
| @@ -10,7 +10,7 @@ | |||
| 10 | #include <string> | 10 | #include <string> |
| 11 | #include "common/common_types.h" | 11 | #include "common/common_types.h" |
| 12 | 12 | ||
| 13 | namespace Telemetry { | 13 | namespace Common::Telemetry { |
| 14 | 14 | ||
| 15 | /// Field type, used for grouping fields together in the final submitted telemetry log | 15 | /// Field type, used for grouping fields together in the final submitted telemetry log |
| 16 | enum class FieldType : u8 { | 16 | enum class FieldType : u8 { |
| @@ -63,30 +63,30 @@ public: | |||
| 63 | 63 | ||
| 64 | void Accept(VisitorInterface& visitor) const override; | 64 | void Accept(VisitorInterface& visitor) const override; |
| 65 | 65 | ||
| 66 | const std::string& GetName() const override { | 66 | [[nodiscard]] const std::string& GetName() const override { |
| 67 | return name; | 67 | return name; |
| 68 | } | 68 | } |
| 69 | 69 | ||
| 70 | /** | 70 | /** |
| 71 | * Returns the type of the field. | 71 | * Returns the type of the field. |
| 72 | */ | 72 | */ |
| 73 | FieldType GetType() const { | 73 | [[nodiscard]] FieldType GetType() const { |
| 74 | return type; | 74 | return type; |
| 75 | } | 75 | } |
| 76 | 76 | ||
| 77 | /** | 77 | /** |
| 78 | * Returns the value of the field. | 78 | * Returns the value of the field. |
| 79 | */ | 79 | */ |
| 80 | const T& GetValue() const { | 80 | [[nodiscard]] const T& GetValue() const { |
| 81 | return value; | 81 | return value; |
| 82 | } | 82 | } |
| 83 | 83 | ||
| 84 | bool operator==(const Field& other) const { | 84 | [[nodiscard]] bool operator==(const Field& other) const { |
| 85 | return (type == other.type) && (name == other.name) && (value == other.value); | 85 | return (type == other.type) && (name == other.name) && (value == other.value); |
| 86 | } | 86 | } |
| 87 | 87 | ||
| 88 | bool operator!=(const Field& other) const { | 88 | [[nodiscard]] bool operator!=(const Field& other) const { |
| 89 | return !(*this == other); | 89 | return !operator==(other); |
| 90 | } | 90 | } |
| 91 | 91 | ||
| 92 | private: | 92 | private: |
| @@ -196,4 +196,4 @@ void AppendCPUInfo(FieldCollection& fc); | |||
| 196 | /// such as platform name, etc. | 196 | /// such as platform name, etc. |
| 197 | void AppendOSInfo(FieldCollection& fc); | 197 | void AppendOSInfo(FieldCollection& fc); |
| 198 | 198 | ||
| 199 | } // namespace Telemetry | 199 | } // namespace Common::Telemetry |
diff --git a/src/common/thread_queue_list.h b/src/common/thread_queue_list.h index 791f99a8c..def9e5d8d 100644 --- a/src/common/thread_queue_list.h +++ b/src/common/thread_queue_list.h | |||
| @@ -18,14 +18,14 @@ struct ThreadQueueList { | |||
| 18 | using Priority = unsigned int; | 18 | using Priority = unsigned int; |
| 19 | 19 | ||
| 20 | // Number of priority levels. (Valid levels are [0..NUM_QUEUES).) | 20 | // Number of priority levels. (Valid levels are [0..NUM_QUEUES).) |
| 21 | static const Priority NUM_QUEUES = N; | 21 | static constexpr Priority NUM_QUEUES = N; |
| 22 | 22 | ||
| 23 | ThreadQueueList() { | 23 | ThreadQueueList() { |
| 24 | first = nullptr; | 24 | first = nullptr; |
| 25 | } | 25 | } |
| 26 | 26 | ||
| 27 | // Only for debugging, returns priority level. | 27 | // Only for debugging, returns priority level. |
| 28 | Priority contains(const T& uid) const { | 28 | [[nodiscard]] Priority contains(const T& uid) const { |
| 29 | for (Priority i = 0; i < NUM_QUEUES; ++i) { | 29 | for (Priority i = 0; i < NUM_QUEUES; ++i) { |
| 30 | const Queue& cur = queues[i]; | 30 | const Queue& cur = queues[i]; |
| 31 | if (std::find(cur.data.cbegin(), cur.data.cend(), uid) != cur.data.cend()) { | 31 | if (std::find(cur.data.cbegin(), cur.data.cend(), uid) != cur.data.cend()) { |
| @@ -36,7 +36,7 @@ struct ThreadQueueList { | |||
| 36 | return -1; | 36 | return -1; |
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | T get_first() const { | 39 | [[nodiscard]] T get_first() const { |
| 40 | const Queue* cur = first; | 40 | const Queue* cur = first; |
| 41 | while (cur != nullptr) { | 41 | while (cur != nullptr) { |
| 42 | if (!cur->data.empty()) { | 42 | if (!cur->data.empty()) { |
| @@ -49,7 +49,7 @@ struct ThreadQueueList { | |||
| 49 | } | 49 | } |
| 50 | 50 | ||
| 51 | template <typename UnaryPredicate> | 51 | template <typename UnaryPredicate> |
| 52 | T get_first_filter(UnaryPredicate filter) const { | 52 | [[nodiscard]] T get_first_filter(UnaryPredicate filter) const { |
| 53 | const Queue* cur = first; | 53 | const Queue* cur = first; |
| 54 | while (cur != nullptr) { | 54 | while (cur != nullptr) { |
| 55 | if (!cur->data.empty()) { | 55 | if (!cur->data.empty()) { |
| @@ -129,7 +129,7 @@ struct ThreadQueueList { | |||
| 129 | first = nullptr; | 129 | first = nullptr; |
| 130 | } | 130 | } |
| 131 | 131 | ||
| 132 | bool empty(Priority priority) const { | 132 | [[nodiscard]] bool empty(Priority priority) const { |
| 133 | const Queue* cur = &queues[priority]; | 133 | const Queue* cur = &queues[priority]; |
| 134 | return cur->data.empty(); | 134 | return cur->data.empty(); |
| 135 | } | 135 | } |
diff --git a/src/common/threadsafe_queue.h b/src/common/threadsafe_queue.h index 8268bbd5c..a4647314a 100644 --- a/src/common/threadsafe_queue.h +++ b/src/common/threadsafe_queue.h | |||
| @@ -25,15 +25,15 @@ public: | |||
| 25 | delete read_ptr; | 25 | delete read_ptr; |
| 26 | } | 26 | } |
| 27 | 27 | ||
| 28 | std::size_t Size() const { | 28 | [[nodiscard]] std::size_t Size() const { |
| 29 | return size.load(); | 29 | return size.load(); |
| 30 | } | 30 | } |
| 31 | 31 | ||
| 32 | bool Empty() const { | 32 | [[nodiscard]] bool Empty() const { |
| 33 | return Size() == 0; | 33 | return Size() == 0; |
| 34 | } | 34 | } |
| 35 | 35 | ||
| 36 | T& Front() const { | 36 | [[nodiscard]] T& Front() const { |
| 37 | return read_ptr->current; | 37 | return read_ptr->current; |
| 38 | } | 38 | } |
| 39 | 39 | ||
| @@ -130,15 +130,15 @@ private: | |||
| 130 | template <typename T> | 130 | template <typename T> |
| 131 | class MPSCQueue { | 131 | class MPSCQueue { |
| 132 | public: | 132 | public: |
| 133 | std::size_t Size() const { | 133 | [[nodiscard]] std::size_t Size() const { |
| 134 | return spsc_queue.Size(); | 134 | return spsc_queue.Size(); |
| 135 | } | 135 | } |
| 136 | 136 | ||
| 137 | bool Empty() const { | 137 | [[nodiscard]] bool Empty() const { |
| 138 | return spsc_queue.Empty(); | 138 | return spsc_queue.Empty(); |
| 139 | } | 139 | } |
| 140 | 140 | ||
| 141 | T& Front() const { | 141 | [[nodiscard]] T& Front() const { |
| 142 | return spsc_queue.Front(); | 142 | return spsc_queue.Front(); |
| 143 | } | 143 | } |
| 144 | 144 | ||
diff --git a/src/common/time_zone.h b/src/common/time_zone.h index 945daa09c..9f5939ca5 100644 --- a/src/common/time_zone.h +++ b/src/common/time_zone.h | |||
| @@ -10,9 +10,9 @@ | |||
| 10 | namespace Common::TimeZone { | 10 | namespace Common::TimeZone { |
| 11 | 11 | ||
| 12 | /// Gets the default timezone, i.e. "GMT" | 12 | /// Gets the default timezone, i.e. "GMT" |
| 13 | std::string GetDefaultTimeZone(); | 13 | [[nodiscard]] std::string GetDefaultTimeZone(); |
| 14 | 14 | ||
| 15 | /// Gets the offset of the current timezone (from the default), in seconds | 15 | /// Gets the offset of the current timezone (from the default), in seconds |
| 16 | std::chrono::seconds GetCurrentOffsetSeconds(); | 16 | [[nodiscard]] std::chrono::seconds GetCurrentOffsetSeconds(); |
| 17 | 17 | ||
| 18 | } // namespace Common::TimeZone | 18 | } // namespace Common::TimeZone |
diff --git a/src/common/timer.h b/src/common/timer.h index 27b521baa..8894a143d 100644 --- a/src/common/timer.h +++ b/src/common/timer.h | |||
| @@ -19,18 +19,18 @@ public: | |||
| 19 | 19 | ||
| 20 | // The time difference is always returned in milliseconds, regardless of alternative internal | 20 | // The time difference is always returned in milliseconds, regardless of alternative internal |
| 21 | // representation | 21 | // representation |
| 22 | std::chrono::milliseconds GetTimeDifference(); | 22 | [[nodiscard]] std::chrono::milliseconds GetTimeDifference(); |
| 23 | void AddTimeDifference(); | 23 | void AddTimeDifference(); |
| 24 | 24 | ||
| 25 | static std::chrono::seconds GetTimeSinceJan1970(); | 25 | [[nodiscard]] static std::chrono::seconds GetTimeSinceJan1970(); |
| 26 | static std::chrono::seconds GetLocalTimeSinceJan1970(); | 26 | [[nodiscard]] static std::chrono::seconds GetLocalTimeSinceJan1970(); |
| 27 | static double GetDoubleTime(); | 27 | [[nodiscard]] static double GetDoubleTime(); |
| 28 | 28 | ||
| 29 | static std::string GetTimeFormatted(); | 29 | [[nodiscard]] static std::string GetTimeFormatted(); |
| 30 | std::string GetTimeElapsedFormatted() const; | 30 | [[nodiscard]] std::string GetTimeElapsedFormatted() const; |
| 31 | std::chrono::milliseconds GetTimeElapsed(); | 31 | [[nodiscard]] std::chrono::milliseconds GetTimeElapsed(); |
| 32 | 32 | ||
| 33 | static std::chrono::milliseconds GetTimeMs(); | 33 | [[nodiscard]] static std::chrono::milliseconds GetTimeMs(); |
| 34 | 34 | ||
| 35 | private: | 35 | private: |
| 36 | std::chrono::milliseconds m_LastTime; | 36 | std::chrono::milliseconds m_LastTime; |
diff --git a/src/common/uint128.h b/src/common/uint128.h index 503cd2d0c..969259ab6 100644 --- a/src/common/uint128.h +++ b/src/common/uint128.h | |||
| @@ -10,13 +10,13 @@ | |||
| 10 | namespace Common { | 10 | namespace Common { |
| 11 | 11 | ||
| 12 | // This function multiplies 2 u64 values and divides it by a u64 value. | 12 | // This function multiplies 2 u64 values and divides it by a u64 value. |
| 13 | u64 MultiplyAndDivide64(u64 a, u64 b, u64 d); | 13 | [[nodiscard]] u64 MultiplyAndDivide64(u64 a, u64 b, u64 d); |
| 14 | 14 | ||
| 15 | // This function multiplies 2 u64 values and produces a u128 value; | 15 | // This function multiplies 2 u64 values and produces a u128 value; |
| 16 | u128 Multiply64Into128(u64 a, u64 b); | 16 | [[nodiscard]] u128 Multiply64Into128(u64 a, u64 b); |
| 17 | 17 | ||
| 18 | // This function divides a u128 by a u32 value and produces two u64 values: | 18 | // This function divides a u128 by a u32 value and produces two u64 values: |
| 19 | // the result of division and the remainder | 19 | // the result of division and the remainder |
| 20 | std::pair<u64, u64> Divide128On32(u128 dividend, u32 divisor); | 20 | [[nodiscard]] std::pair<u64, u64> Divide128On32(u128 dividend, u32 divisor); |
| 21 | 21 | ||
| 22 | } // namespace Common | 22 | } // namespace Common |
diff --git a/src/common/uuid.h b/src/common/uuid.h index 4d3af8cec..4ab9a25f0 100644 --- a/src/common/uuid.h +++ b/src/common/uuid.h | |||
| @@ -19,21 +19,21 @@ struct UUID { | |||
| 19 | constexpr explicit UUID(const u128& id) : uuid{id} {} | 19 | constexpr explicit UUID(const u128& id) : uuid{id} {} |
| 20 | constexpr explicit UUID(const u64 lo, const u64 hi) : uuid{{lo, hi}} {} | 20 | constexpr explicit UUID(const u64 lo, const u64 hi) : uuid{{lo, hi}} {} |
| 21 | 21 | ||
| 22 | constexpr explicit operator bool() const { | 22 | [[nodiscard]] constexpr explicit operator bool() const { |
| 23 | return uuid[0] != INVALID_UUID[0] && uuid[1] != INVALID_UUID[1]; | 23 | return uuid[0] != INVALID_UUID[0] && uuid[1] != INVALID_UUID[1]; |
| 24 | } | 24 | } |
| 25 | 25 | ||
| 26 | constexpr bool operator==(const UUID& rhs) const { | 26 | [[nodiscard]] constexpr bool operator==(const UUID& rhs) const { |
| 27 | // TODO(DarkLordZach): Replace with uuid == rhs.uuid with C++20 | 27 | // TODO(DarkLordZach): Replace with uuid == rhs.uuid with C++20 |
| 28 | return uuid[0] == rhs.uuid[0] && uuid[1] == rhs.uuid[1]; | 28 | return uuid[0] == rhs.uuid[0] && uuid[1] == rhs.uuid[1]; |
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | constexpr bool operator!=(const UUID& rhs) const { | 31 | [[nodiscard]] constexpr bool operator!=(const UUID& rhs) const { |
| 32 | return !operator==(rhs); | 32 | return !operator==(rhs); |
| 33 | } | 33 | } |
| 34 | 34 | ||
| 35 | // TODO(ogniK): Properly generate uuids based on RFC-4122 | 35 | // TODO(ogniK): Properly generate uuids based on RFC-4122 |
| 36 | static UUID Generate(); | 36 | [[nodiscard]] static UUID Generate(); |
| 37 | 37 | ||
| 38 | // Set the UUID to {0,0} to be considered an invalid user | 38 | // Set the UUID to {0,0} to be considered an invalid user |
| 39 | constexpr void Invalidate() { | 39 | constexpr void Invalidate() { |
| @@ -41,12 +41,12 @@ struct UUID { | |||
| 41 | } | 41 | } |
| 42 | 42 | ||
| 43 | // TODO(ogniK): Properly generate a Nintendo ID | 43 | // TODO(ogniK): Properly generate a Nintendo ID |
| 44 | constexpr u64 GetNintendoID() const { | 44 | [[nodiscard]] constexpr u64 GetNintendoID() const { |
| 45 | return uuid[0]; | 45 | return uuid[0]; |
| 46 | } | 46 | } |
| 47 | 47 | ||
| 48 | std::string Format() const; | 48 | [[nodiscard]] std::string Format() const; |
| 49 | std::string FormatSwitch() const; | 49 | [[nodiscard]] std::string FormatSwitch() const; |
| 50 | }; | 50 | }; |
| 51 | static_assert(sizeof(UUID) == 16, "UUID is an invalid size!"); | 51 | static_assert(sizeof(UUID) == 16, "UUID is an invalid size!"); |
| 52 | 52 | ||
diff --git a/src/common/vector_math.h b/src/common/vector_math.h index 429485329..2a0fcf541 100644 --- a/src/common/vector_math.h +++ b/src/common/vector_math.h | |||
| @@ -52,15 +52,15 @@ public: | |||
| 52 | constexpr Vec2(const T& x_, const T& y_) : x(x_), y(y_) {} | 52 | constexpr Vec2(const T& x_, const T& y_) : x(x_), y(y_) {} |
| 53 | 53 | ||
| 54 | template <typename T2> | 54 | template <typename T2> |
| 55 | constexpr Vec2<T2> Cast() const { | 55 | [[nodiscard]] constexpr Vec2<T2> Cast() const { |
| 56 | return Vec2<T2>(static_cast<T2>(x), static_cast<T2>(y)); | 56 | return Vec2<T2>(static_cast<T2>(x), static_cast<T2>(y)); |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | static constexpr Vec2 AssignToAll(const T& f) { | 59 | [[nodiscard]] static constexpr Vec2 AssignToAll(const T& f) { |
| 60 | return Vec2{f, f}; | 60 | return Vec2{f, f}; |
| 61 | } | 61 | } |
| 62 | 62 | ||
| 63 | constexpr Vec2<decltype(T{} + T{})> operator+(const Vec2& other) const { | 63 | [[nodiscard]] constexpr Vec2<decltype(T{} + T{})> operator+(const Vec2& other) const { |
| 64 | return {x + other.x, y + other.y}; | 64 | return {x + other.x, y + other.y}; |
| 65 | } | 65 | } |
| 66 | constexpr Vec2& operator+=(const Vec2& other) { | 66 | constexpr Vec2& operator+=(const Vec2& other) { |
| @@ -68,7 +68,7 @@ public: | |||
| 68 | y += other.y; | 68 | y += other.y; |
| 69 | return *this; | 69 | return *this; |
| 70 | } | 70 | } |
| 71 | constexpr Vec2<decltype(T{} - T{})> operator-(const Vec2& other) const { | 71 | [[nodiscard]] constexpr Vec2<decltype(T{} - T{})> operator-(const Vec2& other) const { |
| 72 | return {x - other.x, y - other.y}; | 72 | return {x - other.x, y - other.y}; |
| 73 | } | 73 | } |
| 74 | constexpr Vec2& operator-=(const Vec2& other) { | 74 | constexpr Vec2& operator-=(const Vec2& other) { |
| @@ -78,15 +78,15 @@ public: | |||
| 78 | } | 78 | } |
| 79 | 79 | ||
| 80 | template <typename U = T> | 80 | template <typename U = T> |
| 81 | constexpr Vec2<std::enable_if_t<std::is_signed_v<U>, U>> operator-() const { | 81 | [[nodiscard]] constexpr Vec2<std::enable_if_t<std::is_signed_v<U>, U>> operator-() const { |
| 82 | return {-x, -y}; | 82 | return {-x, -y}; |
| 83 | } | 83 | } |
| 84 | constexpr Vec2<decltype(T{} * T{})> operator*(const Vec2& other) const { | 84 | [[nodiscard]] constexpr Vec2<decltype(T{} * T{})> operator*(const Vec2& other) const { |
| 85 | return {x * other.x, y * other.y}; | 85 | return {x * other.x, y * other.y}; |
| 86 | } | 86 | } |
| 87 | 87 | ||
| 88 | template <typename V> | 88 | template <typename V> |
| 89 | constexpr Vec2<decltype(T{} * V{})> operator*(const V& f) const { | 89 | [[nodiscard]] constexpr Vec2<decltype(T{} * V{})> operator*(const V& f) const { |
| 90 | return {x * f, y * f}; | 90 | return {x * f, y * f}; |
| 91 | } | 91 | } |
| 92 | 92 | ||
| @@ -97,7 +97,7 @@ public: | |||
| 97 | } | 97 | } |
| 98 | 98 | ||
| 99 | template <typename V> | 99 | template <typename V> |
| 100 | constexpr Vec2<decltype(T{} / V{})> operator/(const V& f) const { | 100 | [[nodiscard]] constexpr Vec2<decltype(T{} / V{})> operator/(const V& f) const { |
| 101 | return {x / f, y / f}; | 101 | return {x / f, y / f}; |
| 102 | } | 102 | } |
| 103 | 103 | ||
| @@ -107,18 +107,18 @@ public: | |||
| 107 | return *this; | 107 | return *this; |
| 108 | } | 108 | } |
| 109 | 109 | ||
| 110 | constexpr T Length2() const { | 110 | [[nodiscard]] constexpr T Length2() const { |
| 111 | return x * x + y * y; | 111 | return x * x + y * y; |
| 112 | } | 112 | } |
| 113 | 113 | ||
| 114 | // Only implemented for T=float | 114 | // Only implemented for T=float |
| 115 | float Length() const; | 115 | [[nodiscard]] float Length() const; |
| 116 | float Normalize(); // returns the previous length, which is often useful | 116 | [[nodiscard]] float Normalize(); // returns the previous length, which is often useful |
| 117 | 117 | ||
| 118 | constexpr T& operator[](std::size_t i) { | 118 | [[nodiscard]] constexpr T& operator[](std::size_t i) { |
| 119 | return *((&x) + i); | 119 | return *((&x) + i); |
| 120 | } | 120 | } |
| 121 | constexpr const T& operator[](std::size_t i) const { | 121 | [[nodiscard]] constexpr const T& operator[](std::size_t i) const { |
| 122 | return *((&x) + i); | 122 | return *((&x) + i); |
| 123 | } | 123 | } |
| 124 | 124 | ||
| @@ -128,46 +128,46 @@ public: | |||
| 128 | } | 128 | } |
| 129 | 129 | ||
| 130 | // Common aliases: UV (texel coordinates), ST (texture coordinates) | 130 | // Common aliases: UV (texel coordinates), ST (texture coordinates) |
| 131 | constexpr T& u() { | 131 | [[nodiscard]] constexpr T& u() { |
| 132 | return x; | 132 | return x; |
| 133 | } | 133 | } |
| 134 | constexpr T& v() { | 134 | [[nodiscard]] constexpr T& v() { |
| 135 | return y; | 135 | return y; |
| 136 | } | 136 | } |
| 137 | constexpr T& s() { | 137 | [[nodiscard]] constexpr T& s() { |
| 138 | return x; | 138 | return x; |
| 139 | } | 139 | } |
| 140 | constexpr T& t() { | 140 | [[nodiscard]] constexpr T& t() { |
| 141 | return y; | 141 | return y; |
| 142 | } | 142 | } |
| 143 | 143 | ||
| 144 | constexpr const T& u() const { | 144 | [[nodiscard]] constexpr const T& u() const { |
| 145 | return x; | 145 | return x; |
| 146 | } | 146 | } |
| 147 | constexpr const T& v() const { | 147 | [[nodiscard]] constexpr const T& v() const { |
| 148 | return y; | 148 | return y; |
| 149 | } | 149 | } |
| 150 | constexpr const T& s() const { | 150 | [[nodiscard]] constexpr const T& s() const { |
| 151 | return x; | 151 | return x; |
| 152 | } | 152 | } |
| 153 | constexpr const T& t() const { | 153 | [[nodiscard]] constexpr const T& t() const { |
| 154 | return y; | 154 | return y; |
| 155 | } | 155 | } |
| 156 | 156 | ||
| 157 | // swizzlers - create a subvector of specific components | 157 | // swizzlers - create a subvector of specific components |
| 158 | constexpr Vec2 yx() const { | 158 | [[nodiscard]] constexpr Vec2 yx() const { |
| 159 | return Vec2(y, x); | 159 | return Vec2(y, x); |
| 160 | } | 160 | } |
| 161 | constexpr Vec2 vu() const { | 161 | [[nodiscard]] constexpr Vec2 vu() const { |
| 162 | return Vec2(y, x); | 162 | return Vec2(y, x); |
| 163 | } | 163 | } |
| 164 | constexpr Vec2 ts() const { | 164 | [[nodiscard]] constexpr Vec2 ts() const { |
| 165 | return Vec2(y, x); | 165 | return Vec2(y, x); |
| 166 | } | 166 | } |
| 167 | }; | 167 | }; |
| 168 | 168 | ||
| 169 | template <typename T, typename V> | 169 | template <typename T, typename V> |
| 170 | constexpr Vec2<T> operator*(const V& f, const Vec2<T>& vec) { | 170 | [[nodiscard]] constexpr Vec2<T> operator*(const V& f, const Vec2<T>& vec) { |
| 171 | return Vec2<T>(f * vec.x, f * vec.y); | 171 | return Vec2<T>(f * vec.x, f * vec.y); |
| 172 | } | 172 | } |
| 173 | 173 | ||
| @@ -196,15 +196,15 @@ public: | |||
| 196 | constexpr Vec3(const T& x_, const T& y_, const T& z_) : x(x_), y(y_), z(z_) {} | 196 | constexpr Vec3(const T& x_, const T& y_, const T& z_) : x(x_), y(y_), z(z_) {} |
| 197 | 197 | ||
| 198 | template <typename T2> | 198 | template <typename T2> |
| 199 | constexpr Vec3<T2> Cast() const { | 199 | [[nodiscard]] constexpr Vec3<T2> Cast() const { |
| 200 | return Vec3<T2>(static_cast<T2>(x), static_cast<T2>(y), static_cast<T2>(z)); | 200 | return Vec3<T2>(static_cast<T2>(x), static_cast<T2>(y), static_cast<T2>(z)); |
| 201 | } | 201 | } |
| 202 | 202 | ||
| 203 | static constexpr Vec3 AssignToAll(const T& f) { | 203 | [[nodiscard]] static constexpr Vec3 AssignToAll(const T& f) { |
| 204 | return Vec3(f, f, f); | 204 | return Vec3(f, f, f); |
| 205 | } | 205 | } |
| 206 | 206 | ||
| 207 | constexpr Vec3<decltype(T{} + T{})> operator+(const Vec3& other) const { | 207 | [[nodiscard]] constexpr Vec3<decltype(T{} + T{})> operator+(const Vec3& other) const { |
| 208 | return {x + other.x, y + other.y, z + other.z}; | 208 | return {x + other.x, y + other.y, z + other.z}; |
| 209 | } | 209 | } |
| 210 | 210 | ||
| @@ -215,7 +215,7 @@ public: | |||
| 215 | return *this; | 215 | return *this; |
| 216 | } | 216 | } |
| 217 | 217 | ||
| 218 | constexpr Vec3<decltype(T{} - T{})> operator-(const Vec3& other) const { | 218 | [[nodiscard]] constexpr Vec3<decltype(T{} - T{})> operator-(const Vec3& other) const { |
| 219 | return {x - other.x, y - other.y, z - other.z}; | 219 | return {x - other.x, y - other.y, z - other.z}; |
| 220 | } | 220 | } |
| 221 | 221 | ||
| @@ -227,16 +227,16 @@ public: | |||
| 227 | } | 227 | } |
| 228 | 228 | ||
| 229 | template <typename U = T> | 229 | template <typename U = T> |
| 230 | constexpr Vec3<std::enable_if_t<std::is_signed_v<U>, U>> operator-() const { | 230 | [[nodiscard]] constexpr Vec3<std::enable_if_t<std::is_signed_v<U>, U>> operator-() const { |
| 231 | return {-x, -y, -z}; | 231 | return {-x, -y, -z}; |
| 232 | } | 232 | } |
| 233 | 233 | ||
| 234 | constexpr Vec3<decltype(T{} * T{})> operator*(const Vec3& other) const { | 234 | [[nodiscard]] constexpr Vec3<decltype(T{} * T{})> operator*(const Vec3& other) const { |
| 235 | return {x * other.x, y * other.y, z * other.z}; | 235 | return {x * other.x, y * other.y, z * other.z}; |
| 236 | } | 236 | } |
| 237 | 237 | ||
| 238 | template <typename V> | 238 | template <typename V> |
| 239 | constexpr Vec3<decltype(T{} * V{})> operator*(const V& f) const { | 239 | [[nodiscard]] constexpr Vec3<decltype(T{} * V{})> operator*(const V& f) const { |
| 240 | return {x * f, y * f, z * f}; | 240 | return {x * f, y * f, z * f}; |
| 241 | } | 241 | } |
| 242 | 242 | ||
| @@ -246,7 +246,7 @@ public: | |||
| 246 | return *this; | 246 | return *this; |
| 247 | } | 247 | } |
| 248 | template <typename V> | 248 | template <typename V> |
| 249 | constexpr Vec3<decltype(T{} / V{})> operator/(const V& f) const { | 249 | [[nodiscard]] constexpr Vec3<decltype(T{} / V{})> operator/(const V& f) const { |
| 250 | return {x / f, y / f, z / f}; | 250 | return {x / f, y / f, z / f}; |
| 251 | } | 251 | } |
| 252 | 252 | ||
| @@ -256,20 +256,20 @@ public: | |||
| 256 | return *this; | 256 | return *this; |
| 257 | } | 257 | } |
| 258 | 258 | ||
| 259 | constexpr T Length2() const { | 259 | [[nodiscard]] constexpr T Length2() const { |
| 260 | return x * x + y * y + z * z; | 260 | return x * x + y * y + z * z; |
| 261 | } | 261 | } |
| 262 | 262 | ||
| 263 | // Only implemented for T=float | 263 | // Only implemented for T=float |
| 264 | float Length() const; | 264 | [[nodiscard]] float Length() const; |
| 265 | Vec3 Normalized() const; | 265 | [[nodiscard]] Vec3 Normalized() const; |
| 266 | float Normalize(); // returns the previous length, which is often useful | 266 | [[nodiscard]] float Normalize(); // returns the previous length, which is often useful |
| 267 | 267 | ||
| 268 | constexpr T& operator[](std::size_t i) { | 268 | [[nodiscard]] constexpr T& operator[](std::size_t i) { |
| 269 | return *((&x) + i); | 269 | return *((&x) + i); |
| 270 | } | 270 | } |
| 271 | 271 | ||
| 272 | constexpr const T& operator[](std::size_t i) const { | 272 | [[nodiscard]] constexpr const T& operator[](std::size_t i) const { |
| 273 | return *((&x) + i); | 273 | return *((&x) + i); |
| 274 | } | 274 | } |
| 275 | 275 | ||
| @@ -280,63 +280,63 @@ public: | |||
| 280 | } | 280 | } |
| 281 | 281 | ||
| 282 | // Common aliases: UVW (texel coordinates), RGB (colors), STQ (texture coordinates) | 282 | // Common aliases: UVW (texel coordinates), RGB (colors), STQ (texture coordinates) |
| 283 | constexpr T& u() { | 283 | [[nodiscard]] constexpr T& u() { |
| 284 | return x; | 284 | return x; |
| 285 | } | 285 | } |
| 286 | constexpr T& v() { | 286 | [[nodiscard]] constexpr T& v() { |
| 287 | return y; | 287 | return y; |
| 288 | } | 288 | } |
| 289 | constexpr T& w() { | 289 | [[nodiscard]] constexpr T& w() { |
| 290 | return z; | 290 | return z; |
| 291 | } | 291 | } |
| 292 | 292 | ||
| 293 | constexpr T& r() { | 293 | [[nodiscard]] constexpr T& r() { |
| 294 | return x; | 294 | return x; |
| 295 | } | 295 | } |
| 296 | constexpr T& g() { | 296 | [[nodiscard]] constexpr T& g() { |
| 297 | return y; | 297 | return y; |
| 298 | } | 298 | } |
| 299 | constexpr T& b() { | 299 | [[nodiscard]] constexpr T& b() { |
| 300 | return z; | 300 | return z; |
| 301 | } | 301 | } |
| 302 | 302 | ||
| 303 | constexpr T& s() { | 303 | [[nodiscard]] constexpr T& s() { |
| 304 | return x; | 304 | return x; |
| 305 | } | 305 | } |
| 306 | constexpr T& t() { | 306 | [[nodiscard]] constexpr T& t() { |
| 307 | return y; | 307 | return y; |
| 308 | } | 308 | } |
| 309 | constexpr T& q() { | 309 | [[nodiscard]] constexpr T& q() { |
| 310 | return z; | 310 | return z; |
| 311 | } | 311 | } |
| 312 | 312 | ||
| 313 | constexpr const T& u() const { | 313 | [[nodiscard]] constexpr const T& u() const { |
| 314 | return x; | 314 | return x; |
| 315 | } | 315 | } |
| 316 | constexpr const T& v() const { | 316 | [[nodiscard]] constexpr const T& v() const { |
| 317 | return y; | 317 | return y; |
| 318 | } | 318 | } |
| 319 | constexpr const T& w() const { | 319 | [[nodiscard]] constexpr const T& w() const { |
| 320 | return z; | 320 | return z; |
| 321 | } | 321 | } |
| 322 | 322 | ||
| 323 | constexpr const T& r() const { | 323 | [[nodiscard]] constexpr const T& r() const { |
| 324 | return x; | 324 | return x; |
| 325 | } | 325 | } |
| 326 | constexpr const T& g() const { | 326 | [[nodiscard]] constexpr const T& g() const { |
| 327 | return y; | 327 | return y; |
| 328 | } | 328 | } |
| 329 | constexpr const T& b() const { | 329 | [[nodiscard]] constexpr const T& b() const { |
| 330 | return z; | 330 | return z; |
| 331 | } | 331 | } |
| 332 | 332 | ||
| 333 | constexpr const T& s() const { | 333 | [[nodiscard]] constexpr const T& s() const { |
| 334 | return x; | 334 | return x; |
| 335 | } | 335 | } |
| 336 | constexpr const T& t() const { | 336 | [[nodiscard]] constexpr const T& t() const { |
| 337 | return y; | 337 | return y; |
| 338 | } | 338 | } |
| 339 | constexpr const T& q() const { | 339 | [[nodiscard]] constexpr const T& q() const { |
| 340 | return z; | 340 | return z; |
| 341 | } | 341 | } |
| 342 | 342 | ||
| @@ -345,7 +345,7 @@ public: | |||
| 345 | // _DEFINE_SWIZZLER2 defines a single such function, DEFINE_SWIZZLER2 defines all of them for all | 345 | // _DEFINE_SWIZZLER2 defines a single such function, DEFINE_SWIZZLER2 defines all of them for all |
| 346 | // component names (x<->r) and permutations (xy<->yx) | 346 | // component names (x<->r) and permutations (xy<->yx) |
| 347 | #define _DEFINE_SWIZZLER2(a, b, name) \ | 347 | #define _DEFINE_SWIZZLER2(a, b, name) \ |
| 348 | constexpr Vec2<T> name() const { \ | 348 | [[nodiscard]] constexpr Vec2<T> name() const { \ |
| 349 | return Vec2<T>(a, b); \ | 349 | return Vec2<T>(a, b); \ |
| 350 | } | 350 | } |
| 351 | #define DEFINE_SWIZZLER2(a, b, a2, b2, a3, b3, a4, b4) \ | 351 | #define DEFINE_SWIZZLER2(a, b, a2, b2, a3, b3, a4, b4) \ |
| @@ -366,7 +366,7 @@ public: | |||
| 366 | }; | 366 | }; |
| 367 | 367 | ||
| 368 | template <typename T, typename V> | 368 | template <typename T, typename V> |
| 369 | constexpr Vec3<T> operator*(const V& f, const Vec3<T>& vec) { | 369 | [[nodiscard]] constexpr Vec3<T> operator*(const V& f, const Vec3<T>& vec) { |
| 370 | return Vec3<T>(f * vec.x, f * vec.y, f * vec.z); | 370 | return Vec3<T>(f * vec.x, f * vec.y, f * vec.z); |
| 371 | } | 371 | } |
| 372 | 372 | ||
| @@ -402,16 +402,16 @@ public: | |||
| 402 | : x(x_), y(y_), z(z_), w(w_) {} | 402 | : x(x_), y(y_), z(z_), w(w_) {} |
| 403 | 403 | ||
| 404 | template <typename T2> | 404 | template <typename T2> |
| 405 | constexpr Vec4<T2> Cast() const { | 405 | [[nodiscard]] constexpr Vec4<T2> Cast() const { |
| 406 | return Vec4<T2>(static_cast<T2>(x), static_cast<T2>(y), static_cast<T2>(z), | 406 | return Vec4<T2>(static_cast<T2>(x), static_cast<T2>(y), static_cast<T2>(z), |
| 407 | static_cast<T2>(w)); | 407 | static_cast<T2>(w)); |
| 408 | } | 408 | } |
| 409 | 409 | ||
| 410 | static constexpr Vec4 AssignToAll(const T& f) { | 410 | [[nodiscard]] static constexpr Vec4 AssignToAll(const T& f) { |
| 411 | return Vec4(f, f, f, f); | 411 | return Vec4(f, f, f, f); |
| 412 | } | 412 | } |
| 413 | 413 | ||
| 414 | constexpr Vec4<decltype(T{} + T{})> operator+(const Vec4& other) const { | 414 | [[nodiscard]] constexpr Vec4<decltype(T{} + T{})> operator+(const Vec4& other) const { |
| 415 | return {x + other.x, y + other.y, z + other.z, w + other.w}; | 415 | return {x + other.x, y + other.y, z + other.z, w + other.w}; |
| 416 | } | 416 | } |
| 417 | 417 | ||
| @@ -423,7 +423,7 @@ public: | |||
| 423 | return *this; | 423 | return *this; |
| 424 | } | 424 | } |
| 425 | 425 | ||
| 426 | constexpr Vec4<decltype(T{} - T{})> operator-(const Vec4& other) const { | 426 | [[nodiscard]] constexpr Vec4<decltype(T{} - T{})> operator-(const Vec4& other) const { |
| 427 | return {x - other.x, y - other.y, z - other.z, w - other.w}; | 427 | return {x - other.x, y - other.y, z - other.z, w - other.w}; |
| 428 | } | 428 | } |
| 429 | 429 | ||
| @@ -436,16 +436,16 @@ public: | |||
| 436 | } | 436 | } |
| 437 | 437 | ||
| 438 | template <typename U = T> | 438 | template <typename U = T> |
| 439 | constexpr Vec4<std::enable_if_t<std::is_signed_v<U>, U>> operator-() const { | 439 | [[nodiscard]] constexpr Vec4<std::enable_if_t<std::is_signed_v<U>, U>> operator-() const { |
| 440 | return {-x, -y, -z, -w}; | 440 | return {-x, -y, -z, -w}; |
| 441 | } | 441 | } |
| 442 | 442 | ||
| 443 | constexpr Vec4<decltype(T{} * T{})> operator*(const Vec4& other) const { | 443 | [[nodiscard]] constexpr Vec4<decltype(T{} * T{})> operator*(const Vec4& other) const { |
| 444 | return {x * other.x, y * other.y, z * other.z, w * other.w}; | 444 | return {x * other.x, y * other.y, z * other.z, w * other.w}; |
| 445 | } | 445 | } |
| 446 | 446 | ||
| 447 | template <typename V> | 447 | template <typename V> |
| 448 | constexpr Vec4<decltype(T{} * V{})> operator*(const V& f) const { | 448 | [[nodiscard]] constexpr Vec4<decltype(T{} * V{})> operator*(const V& f) const { |
| 449 | return {x * f, y * f, z * f, w * f}; | 449 | return {x * f, y * f, z * f, w * f}; |
| 450 | } | 450 | } |
| 451 | 451 | ||
| @@ -456,7 +456,7 @@ public: | |||
| 456 | } | 456 | } |
| 457 | 457 | ||
| 458 | template <typename V> | 458 | template <typename V> |
| 459 | constexpr Vec4<decltype(T{} / V{})> operator/(const V& f) const { | 459 | [[nodiscard]] constexpr Vec4<decltype(T{} / V{})> operator/(const V& f) const { |
| 460 | return {x / f, y / f, z / f, w / f}; | 460 | return {x / f, y / f, z / f, w / f}; |
| 461 | } | 461 | } |
| 462 | 462 | ||
| @@ -466,15 +466,15 @@ public: | |||
| 466 | return *this; | 466 | return *this; |
| 467 | } | 467 | } |
| 468 | 468 | ||
| 469 | constexpr T Length2() const { | 469 | [[nodiscard]] constexpr T Length2() const { |
| 470 | return x * x + y * y + z * z + w * w; | 470 | return x * x + y * y + z * z + w * w; |
| 471 | } | 471 | } |
| 472 | 472 | ||
| 473 | constexpr T& operator[](std::size_t i) { | 473 | [[nodiscard]] constexpr T& operator[](std::size_t i) { |
| 474 | return *((&x) + i); | 474 | return *((&x) + i); |
| 475 | } | 475 | } |
| 476 | 476 | ||
| 477 | constexpr const T& operator[](std::size_t i) const { | 477 | [[nodiscard]] constexpr const T& operator[](std::size_t i) const { |
| 478 | return *((&x) + i); | 478 | return *((&x) + i); |
| 479 | } | 479 | } |
| 480 | 480 | ||
| @@ -486,29 +486,29 @@ public: | |||
| 486 | } | 486 | } |
| 487 | 487 | ||
| 488 | // Common alias: RGBA (colors) | 488 | // Common alias: RGBA (colors) |
| 489 | constexpr T& r() { | 489 | [[nodiscard]] constexpr T& r() { |
| 490 | return x; | 490 | return x; |
| 491 | } | 491 | } |
| 492 | constexpr T& g() { | 492 | [[nodiscard]] constexpr T& g() { |
| 493 | return y; | 493 | return y; |
| 494 | } | 494 | } |
| 495 | constexpr T& b() { | 495 | [[nodiscard]] constexpr T& b() { |
| 496 | return z; | 496 | return z; |
| 497 | } | 497 | } |
| 498 | constexpr T& a() { | 498 | [[nodiscard]] constexpr T& a() { |
| 499 | return w; | 499 | return w; |
| 500 | } | 500 | } |
| 501 | 501 | ||
| 502 | constexpr const T& r() const { | 502 | [[nodiscard]] constexpr const T& r() const { |
| 503 | return x; | 503 | return x; |
| 504 | } | 504 | } |
| 505 | constexpr const T& g() const { | 505 | [[nodiscard]] constexpr const T& g() const { |
| 506 | return y; | 506 | return y; |
| 507 | } | 507 | } |
| 508 | constexpr const T& b() const { | 508 | [[nodiscard]] constexpr const T& b() const { |
| 509 | return z; | 509 | return z; |
| 510 | } | 510 | } |
| 511 | constexpr const T& a() const { | 511 | [[nodiscard]] constexpr const T& a() const { |
| 512 | return w; | 512 | return w; |
| 513 | } | 513 | } |
| 514 | 514 | ||
| @@ -520,7 +520,7 @@ public: | |||
| 520 | // DEFINE_SWIZZLER2_COMP2 defines two component functions for all component names (x<->r) and | 520 | // DEFINE_SWIZZLER2_COMP2 defines two component functions for all component names (x<->r) and |
| 521 | // permutations (xy<->yx) | 521 | // permutations (xy<->yx) |
| 522 | #define _DEFINE_SWIZZLER2(a, b, name) \ | 522 | #define _DEFINE_SWIZZLER2(a, b, name) \ |
| 523 | constexpr Vec2<T> name() const { \ | 523 | [[nodiscard]] constexpr Vec2<T> name() const { \ |
| 524 | return Vec2<T>(a, b); \ | 524 | return Vec2<T>(a, b); \ |
| 525 | } | 525 | } |
| 526 | #define DEFINE_SWIZZLER2_COMP1(a, a2) \ | 526 | #define DEFINE_SWIZZLER2_COMP1(a, a2) \ |
| @@ -547,7 +547,7 @@ public: | |||
| 547 | #undef _DEFINE_SWIZZLER2 | 547 | #undef _DEFINE_SWIZZLER2 |
| 548 | 548 | ||
| 549 | #define _DEFINE_SWIZZLER3(a, b, c, name) \ | 549 | #define _DEFINE_SWIZZLER3(a, b, c, name) \ |
| 550 | constexpr Vec3<T> name() const { \ | 550 | [[nodiscard]] constexpr Vec3<T> name() const { \ |
| 551 | return Vec3<T>(a, b, c); \ | 551 | return Vec3<T>(a, b, c); \ |
| 552 | } | 552 | } |
| 553 | #define DEFINE_SWIZZLER3_COMP1(a, a2) \ | 553 | #define DEFINE_SWIZZLER3_COMP1(a, a2) \ |
| @@ -581,7 +581,7 @@ public: | |||
| 581 | }; | 581 | }; |
| 582 | 582 | ||
| 583 | template <typename T, typename V> | 583 | template <typename T, typename V> |
| 584 | constexpr Vec4<decltype(V{} * T{})> operator*(const V& f, const Vec4<T>& vec) { | 584 | [[nodiscard]] constexpr Vec4<decltype(V{} * T{})> operator*(const V& f, const Vec4<T>& vec) { |
| 585 | return {f * vec.x, f * vec.y, f * vec.z, f * vec.w}; | 585 | return {f * vec.x, f * vec.y, f * vec.z, f * vec.w}; |
| 586 | } | 586 | } |
| 587 | 587 | ||
| @@ -593,39 +593,41 @@ constexpr decltype(T{} * T{} + T{} * T{}) Dot(const Vec2<T>& a, const Vec2<T>& b | |||
| 593 | } | 593 | } |
| 594 | 594 | ||
| 595 | template <typename T> | 595 | template <typename T> |
| 596 | constexpr decltype(T{} * T{} + T{} * T{}) Dot(const Vec3<T>& a, const Vec3<T>& b) { | 596 | [[nodiscard]] constexpr decltype(T{} * T{} + T{} * T{}) Dot(const Vec3<T>& a, const Vec3<T>& b) { |
| 597 | return a.x * b.x + a.y * b.y + a.z * b.z; | 597 | return a.x * b.x + a.y * b.y + a.z * b.z; |
| 598 | } | 598 | } |
| 599 | 599 | ||
| 600 | template <typename T> | 600 | template <typename T> |
| 601 | constexpr decltype(T{} * T{} + T{} * T{}) Dot(const Vec4<T>& a, const Vec4<T>& b) { | 601 | [[nodiscard]] constexpr decltype(T{} * T{} + T{} * T{}) Dot(const Vec4<T>& a, const Vec4<T>& b) { |
| 602 | return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; | 602 | return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; |
| 603 | } | 603 | } |
| 604 | 604 | ||
| 605 | template <typename T> | 605 | template <typename T> |
| 606 | constexpr Vec3<decltype(T{} * T{} - T{} * T{})> Cross(const Vec3<T>& a, const Vec3<T>& b) { | 606 | [[nodiscard]] constexpr Vec3<decltype(T{} * T{} - T{} * T{})> Cross(const Vec3<T>& a, |
| 607 | const Vec3<T>& b) { | ||
| 607 | return {a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x}; | 608 | return {a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x}; |
| 608 | } | 609 | } |
| 609 | 610 | ||
| 610 | // linear interpolation via float: 0.0=begin, 1.0=end | 611 | // linear interpolation via float: 0.0=begin, 1.0=end |
| 611 | template <typename X> | 612 | template <typename X> |
| 612 | constexpr decltype(X{} * float{} + X{} * float{}) Lerp(const X& begin, const X& end, | 613 | [[nodiscard]] constexpr decltype(X{} * float{} + X{} * float{}) Lerp(const X& begin, const X& end, |
| 613 | const float t) { | 614 | const float t) { |
| 614 | return begin * (1.f - t) + end * t; | 615 | return begin * (1.f - t) + end * t; |
| 615 | } | 616 | } |
| 616 | 617 | ||
| 617 | // linear interpolation via int: 0=begin, base=end | 618 | // linear interpolation via int: 0=begin, base=end |
| 618 | template <typename X, int base> | 619 | template <typename X, int base> |
| 619 | constexpr decltype((X{} * int{} + X{} * int{}) / base) LerpInt(const X& begin, const X& end, | 620 | [[nodiscard]] constexpr decltype((X{} * int{} + X{} * int{}) / base) LerpInt(const X& begin, |
| 620 | const int t) { | 621 | const X& end, |
| 622 | const int t) { | ||
| 621 | return (begin * (base - t) + end * t) / base; | 623 | return (begin * (base - t) + end * t) / base; |
| 622 | } | 624 | } |
| 623 | 625 | ||
| 624 | // bilinear interpolation. s is for interpolating x00-x01 and x10-x11, and t is for the second | 626 | // bilinear interpolation. s is for interpolating x00-x01 and x10-x11, and t is for the second |
| 625 | // interpolation. | 627 | // interpolation. |
| 626 | template <typename X> | 628 | template <typename X> |
| 627 | constexpr auto BilinearInterp(const X& x00, const X& x01, const X& x10, const X& x11, const float s, | 629 | [[nodiscard]] constexpr auto BilinearInterp(const X& x00, const X& x01, const X& x10, const X& x11, |
| 628 | const float t) { | 630 | const float s, const float t) { |
| 629 | auto y0 = Lerp(x00, x01, s); | 631 | auto y0 = Lerp(x00, x01, s); |
| 630 | auto y1 = Lerp(x10, x11, s); | 632 | auto y1 = Lerp(x10, x11, s); |
| 631 | return Lerp(y0, y1, t); | 633 | return Lerp(y0, y1, t); |
| @@ -633,42 +635,42 @@ constexpr auto BilinearInterp(const X& x00, const X& x01, const X& x10, const X& | |||
| 633 | 635 | ||
| 634 | // Utility vector factories | 636 | // Utility vector factories |
| 635 | template <typename T> | 637 | template <typename T> |
| 636 | constexpr Vec2<T> MakeVec(const T& x, const T& y) { | 638 | [[nodiscard]] constexpr Vec2<T> MakeVec(const T& x, const T& y) { |
| 637 | return Vec2<T>{x, y}; | 639 | return Vec2<T>{x, y}; |
| 638 | } | 640 | } |
| 639 | 641 | ||
| 640 | template <typename T> | 642 | template <typename T> |
| 641 | constexpr Vec3<T> MakeVec(const T& x, const T& y, const T& z) { | 643 | [[nodiscard]] constexpr Vec3<T> MakeVec(const T& x, const T& y, const T& z) { |
| 642 | return Vec3<T>{x, y, z}; | 644 | return Vec3<T>{x, y, z}; |
| 643 | } | 645 | } |
| 644 | 646 | ||
| 645 | template <typename T> | 647 | template <typename T> |
| 646 | constexpr Vec4<T> MakeVec(const T& x, const T& y, const Vec2<T>& zw) { | 648 | [[nodiscard]] constexpr Vec4<T> MakeVec(const T& x, const T& y, const Vec2<T>& zw) { |
| 647 | return MakeVec(x, y, zw[0], zw[1]); | 649 | return MakeVec(x, y, zw[0], zw[1]); |
| 648 | } | 650 | } |
| 649 | 651 | ||
| 650 | template <typename T> | 652 | template <typename T> |
| 651 | constexpr Vec3<T> MakeVec(const Vec2<T>& xy, const T& z) { | 653 | [[nodiscard]] constexpr Vec3<T> MakeVec(const Vec2<T>& xy, const T& z) { |
| 652 | return MakeVec(xy[0], xy[1], z); | 654 | return MakeVec(xy[0], xy[1], z); |
| 653 | } | 655 | } |
| 654 | 656 | ||
| 655 | template <typename T> | 657 | template <typename T> |
| 656 | constexpr Vec3<T> MakeVec(const T& x, const Vec2<T>& yz) { | 658 | [[nodiscard]] constexpr Vec3<T> MakeVec(const T& x, const Vec2<T>& yz) { |
| 657 | return MakeVec(x, yz[0], yz[1]); | 659 | return MakeVec(x, yz[0], yz[1]); |
| 658 | } | 660 | } |
| 659 | 661 | ||
| 660 | template <typename T> | 662 | template <typename T> |
| 661 | constexpr Vec4<T> MakeVec(const T& x, const T& y, const T& z, const T& w) { | 663 | [[nodiscard]] constexpr Vec4<T> MakeVec(const T& x, const T& y, const T& z, const T& w) { |
| 662 | return Vec4<T>{x, y, z, w}; | 664 | return Vec4<T>{x, y, z, w}; |
| 663 | } | 665 | } |
| 664 | 666 | ||
| 665 | template <typename T> | 667 | template <typename T> |
| 666 | constexpr Vec4<T> MakeVec(const Vec2<T>& xy, const T& z, const T& w) { | 668 | [[nodiscard]] constexpr Vec4<T> MakeVec(const Vec2<T>& xy, const T& z, const T& w) { |
| 667 | return MakeVec(xy[0], xy[1], z, w); | 669 | return MakeVec(xy[0], xy[1], z, w); |
| 668 | } | 670 | } |
| 669 | 671 | ||
| 670 | template <typename T> | 672 | template <typename T> |
| 671 | constexpr Vec4<T> MakeVec(const T& x, const Vec2<T>& yz, const T& w) { | 673 | [[nodiscard]] constexpr Vec4<T> MakeVec(const T& x, const Vec2<T>& yz, const T& w) { |
| 672 | return MakeVec(x, yz[0], yz[1], w); | 674 | return MakeVec(x, yz[0], yz[1], w); |
| 673 | } | 675 | } |
| 674 | 676 | ||
| @@ -676,17 +678,17 @@ constexpr Vec4<T> MakeVec(const T& x, const Vec2<T>& yz, const T& w) { | |||
| 676 | // Even if someone wanted to use an odd object like Vec2<Vec2<T>>, the compiler would error | 678 | // Even if someone wanted to use an odd object like Vec2<Vec2<T>>, the compiler would error |
| 677 | // out soon enough due to misuse of the returned structure. | 679 | // out soon enough due to misuse of the returned structure. |
| 678 | template <typename T> | 680 | template <typename T> |
| 679 | constexpr Vec4<T> MakeVec(const Vec2<T>& xy, const Vec2<T>& zw) { | 681 | [[nodiscard]] constexpr Vec4<T> MakeVec(const Vec2<T>& xy, const Vec2<T>& zw) { |
| 680 | return MakeVec(xy[0], xy[1], zw[0], zw[1]); | 682 | return MakeVec(xy[0], xy[1], zw[0], zw[1]); |
| 681 | } | 683 | } |
| 682 | 684 | ||
| 683 | template <typename T> | 685 | template <typename T> |
| 684 | constexpr Vec4<T> MakeVec(const Vec3<T>& xyz, const T& w) { | 686 | [[nodiscard]] constexpr Vec4<T> MakeVec(const Vec3<T>& xyz, const T& w) { |
| 685 | return MakeVec(xyz[0], xyz[1], xyz[2], w); | 687 | return MakeVec(xyz[0], xyz[1], xyz[2], w); |
| 686 | } | 688 | } |
| 687 | 689 | ||
| 688 | template <typename T> | 690 | template <typename T> |
| 689 | constexpr Vec4<T> MakeVec(const T& x, const Vec3<T>& yzw) { | 691 | [[nodiscard]] constexpr Vec4<T> MakeVec(const T& x, const Vec3<T>& yzw) { |
| 690 | return MakeVec(x, yzw[0], yzw[1], yzw[2]); | 692 | return MakeVec(x, yzw[0], yzw[1], yzw[2]); |
| 691 | } | 693 | } |
| 692 | 694 | ||
diff --git a/src/common/virtual_buffer.cpp b/src/common/virtual_buffer.cpp index be5b67752..b009cb500 100644 --- a/src/common/virtual_buffer.cpp +++ b/src/common/virtual_buffer.cpp | |||
| @@ -5,16 +5,7 @@ | |||
| 5 | #ifdef _WIN32 | 5 | #ifdef _WIN32 |
| 6 | #include <windows.h> | 6 | #include <windows.h> |
| 7 | #else | 7 | #else |
| 8 | #include <stdio.h> | ||
| 9 | #include <sys/mman.h> | 8 | #include <sys/mman.h> |
| 10 | #include <sys/types.h> | ||
| 11 | #if defined __APPLE__ || defined __FreeBSD__ || defined __OpenBSD__ | ||
| 12 | #include <sys/sysctl.h> | ||
| 13 | #elif defined __HAIKU__ | ||
| 14 | #include <OS.h> | ||
| 15 | #else | ||
| 16 | #include <sys/sysinfo.h> | ||
| 17 | #endif | ||
| 18 | #endif | 9 | #endif |
| 19 | 10 | ||
| 20 | #include "common/assert.h" | 11 | #include "common/assert.h" |
diff --git a/src/common/virtual_buffer.h b/src/common/virtual_buffer.h index da064e59e..125cb42f0 100644 --- a/src/common/virtual_buffer.h +++ b/src/common/virtual_buffer.h | |||
| @@ -30,23 +30,23 @@ public: | |||
| 30 | base_ptr = reinterpret_cast<T*>(AllocateMemoryPages(alloc_size)); | 30 | base_ptr = reinterpret_cast<T*>(AllocateMemoryPages(alloc_size)); |
| 31 | } | 31 | } |
| 32 | 32 | ||
| 33 | constexpr const T& operator[](std::size_t index) const { | 33 | [[nodiscard]] constexpr const T& operator[](std::size_t index) const { |
| 34 | return base_ptr[index]; | 34 | return base_ptr[index]; |
| 35 | } | 35 | } |
| 36 | 36 | ||
| 37 | constexpr T& operator[](std::size_t index) { | 37 | [[nodiscard]] constexpr T& operator[](std::size_t index) { |
| 38 | return base_ptr[index]; | 38 | return base_ptr[index]; |
| 39 | } | 39 | } |
| 40 | 40 | ||
| 41 | constexpr T* data() { | 41 | [[nodiscard]] constexpr T* data() { |
| 42 | return base_ptr; | 42 | return base_ptr; |
| 43 | } | 43 | } |
| 44 | 44 | ||
| 45 | constexpr const T* data() const { | 45 | [[nodiscard]] constexpr const T* data() const { |
| 46 | return base_ptr; | 46 | return base_ptr; |
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | constexpr std::size_t size() const { | 49 | [[nodiscard]] constexpr std::size_t size() const { |
| 50 | return alloc_size / sizeof(T); | 50 | return alloc_size / sizeof(T); |
| 51 | } | 51 | } |
| 52 | 52 | ||
diff --git a/src/common/wall_clock.h b/src/common/wall_clock.h index 367d72134..5db30083d 100644 --- a/src/common/wall_clock.h +++ b/src/common/wall_clock.h | |||
| @@ -14,24 +14,24 @@ namespace Common { | |||
| 14 | class WallClock { | 14 | class WallClock { |
| 15 | public: | 15 | public: |
| 16 | /// Returns current wall time in nanoseconds | 16 | /// Returns current wall time in nanoseconds |
| 17 | virtual std::chrono::nanoseconds GetTimeNS() = 0; | 17 | [[nodiscard]] virtual std::chrono::nanoseconds GetTimeNS() = 0; |
| 18 | 18 | ||
| 19 | /// Returns current wall time in microseconds | 19 | /// Returns current wall time in microseconds |
| 20 | virtual std::chrono::microseconds GetTimeUS() = 0; | 20 | [[nodiscard]] virtual std::chrono::microseconds GetTimeUS() = 0; |
| 21 | 21 | ||
| 22 | /// Returns current wall time in milliseconds | 22 | /// Returns current wall time in milliseconds |
| 23 | virtual std::chrono::milliseconds GetTimeMS() = 0; | 23 | [[nodiscard]] virtual std::chrono::milliseconds GetTimeMS() = 0; |
| 24 | 24 | ||
| 25 | /// Returns current wall time in emulated clock cycles | 25 | /// Returns current wall time in emulated clock cycles |
| 26 | virtual u64 GetClockCycles() = 0; | 26 | [[nodiscard]] virtual u64 GetClockCycles() = 0; |
| 27 | 27 | ||
| 28 | /// Returns current wall time in emulated cpu cycles | 28 | /// Returns current wall time in emulated cpu cycles |
| 29 | virtual u64 GetCPUCycles() = 0; | 29 | [[nodiscard]] virtual u64 GetCPUCycles() = 0; |
| 30 | 30 | ||
| 31 | virtual void Pause(bool is_paused) = 0; | 31 | virtual void Pause(bool is_paused) = 0; |
| 32 | 32 | ||
| 33 | /// Tells if the wall clock, uses the host CPU's hardware clock | 33 | /// Tells if the wall clock, uses the host CPU's hardware clock |
| 34 | bool IsNative() const { | 34 | [[nodiscard]] bool IsNative() const { |
| 35 | return is_native; | 35 | return is_native; |
| 36 | } | 36 | } |
| 37 | 37 | ||
| @@ -47,7 +47,7 @@ private: | |||
| 47 | bool is_native; | 47 | bool is_native; |
| 48 | }; | 48 | }; |
| 49 | 49 | ||
| 50 | std::unique_ptr<WallClock> CreateBestMatchingClock(u32 emulated_cpu_frequency, | 50 | [[nodiscard]] std::unique_ptr<WallClock> CreateBestMatchingClock(u32 emulated_cpu_frequency, |
| 51 | u32 emulated_clock_frequency); | 51 | u32 emulated_clock_frequency); |
| 52 | 52 | ||
| 53 | } // namespace Common | 53 | } // namespace Common |
diff --git a/src/common/zstd_compression.cpp b/src/common/zstd_compression.cpp index 978526492..5f45459da 100644 --- a/src/common/zstd_compression.cpp +++ b/src/common/zstd_compression.cpp | |||
| @@ -5,7 +5,6 @@ | |||
| 5 | #include <algorithm> | 5 | #include <algorithm> |
| 6 | #include <zstd.h> | 6 | #include <zstd.h> |
| 7 | 7 | ||
| 8 | #include "common/assert.h" | ||
| 9 | #include "common/zstd_compression.h" | 8 | #include "common/zstd_compression.h" |
| 10 | 9 | ||
| 11 | namespace Common::Compression { | 10 | namespace Common::Compression { |
diff --git a/src/common/zstd_compression.h b/src/common/zstd_compression.h index e9de941c8..c26a30ab9 100644 --- a/src/common/zstd_compression.h +++ b/src/common/zstd_compression.h | |||
| @@ -13,24 +13,25 @@ namespace Common::Compression { | |||
| 13 | /** | 13 | /** |
| 14 | * Compresses a source memory region with Zstandard and returns the compressed data in a vector. | 14 | * Compresses a source memory region with Zstandard and returns the compressed data in a vector. |
| 15 | * | 15 | * |
| 16 | * @param source the uncompressed source memory region. | 16 | * @param source The uncompressed source memory region. |
| 17 | * @param source_size the size in bytes of the uncompressed source memory region. | 17 | * @param source_size The size of the uncompressed source memory region. |
| 18 | * @param compression_level the used compression level. Should be between 1 and 22. | 18 | * @param compression_level The used compression level. Should be between 1 and 22. |
| 19 | * | 19 | * |
| 20 | * @return the compressed data. | 20 | * @return the compressed data. |
| 21 | */ | 21 | */ |
| 22 | std::vector<u8> CompressDataZSTD(const u8* source, std::size_t source_size, s32 compression_level); | 22 | [[nodiscard]] std::vector<u8> CompressDataZSTD(const u8* source, std::size_t source_size, |
| 23 | s32 compression_level); | ||
| 23 | 24 | ||
| 24 | /** | 25 | /** |
| 25 | * Compresses a source memory region with Zstandard with the default compression level and returns | 26 | * Compresses a source memory region with Zstandard with the default compression level and returns |
| 26 | * the compressed data in a vector. | 27 | * the compressed data in a vector. |
| 27 | * | 28 | * |
| 28 | * @param source the uncompressed source memory region. | 29 | * @param source The uncompressed source memory region. |
| 29 | * @param source_size the size in bytes of the uncompressed source memory region. | 30 | * @param source_size The size of the uncompressed source memory region. |
| 30 | * | 31 | * |
| 31 | * @return the compressed data. | 32 | * @return the compressed data. |
| 32 | */ | 33 | */ |
| 33 | std::vector<u8> CompressDataZSTDDefault(const u8* source, std::size_t source_size); | 34 | [[nodiscard]] std::vector<u8> CompressDataZSTDDefault(const u8* source, std::size_t source_size); |
| 34 | 35 | ||
| 35 | /** | 36 | /** |
| 36 | * Decompresses a source memory region with Zstandard and returns the uncompressed data in a vector. | 37 | * Decompresses a source memory region with Zstandard and returns the uncompressed data in a vector. |
| @@ -39,6 +40,6 @@ std::vector<u8> CompressDataZSTDDefault(const u8* source, std::size_t source_siz | |||
| 39 | * | 40 | * |
| 40 | * @return the decompressed data. | 41 | * @return the decompressed data. |
| 41 | */ | 42 | */ |
| 42 | std::vector<u8> DecompressDataZSTD(const std::vector<u8>& compressed); | 43 | [[nodiscard]] std::vector<u8> DecompressDataZSTD(const std::vector<u8>& compressed); |
| 43 | 44 | ||
| 44 | } // namespace Common::Compression \ No newline at end of file | 45 | } // namespace Common::Compression \ No newline at end of file |
diff --git a/src/core/arm/cpu_interrupt_handler.cpp b/src/core/arm/cpu_interrupt_handler.cpp index df0350881..9c8898700 100644 --- a/src/core/arm/cpu_interrupt_handler.cpp +++ b/src/core/arm/cpu_interrupt_handler.cpp | |||
| @@ -7,9 +7,7 @@ | |||
| 7 | 7 | ||
| 8 | namespace Core { | 8 | namespace Core { |
| 9 | 9 | ||
| 10 | CPUInterruptHandler::CPUInterruptHandler() : is_interrupted{} { | 10 | CPUInterruptHandler::CPUInterruptHandler() : interrupt_event{std::make_unique<Common::Event>()} {} |
| 11 | interrupt_event = std::make_unique<Common::Event>(); | ||
| 12 | } | ||
| 13 | 11 | ||
| 14 | CPUInterruptHandler::~CPUInterruptHandler() = default; | 12 | CPUInterruptHandler::~CPUInterruptHandler() = default; |
| 15 | 13 | ||
| @@ -17,7 +15,7 @@ void CPUInterruptHandler::SetInterrupt(bool is_interrupted_) { | |||
| 17 | if (is_interrupted_) { | 15 | if (is_interrupted_) { |
| 18 | interrupt_event->Set(); | 16 | interrupt_event->Set(); |
| 19 | } | 17 | } |
| 20 | this->is_interrupted = is_interrupted_; | 18 | is_interrupted = is_interrupted_; |
| 21 | } | 19 | } |
| 22 | 20 | ||
| 23 | void CPUInterruptHandler::AwaitInterrupt() { | 21 | void CPUInterruptHandler::AwaitInterrupt() { |
diff --git a/src/core/arm/cpu_interrupt_handler.h b/src/core/arm/cpu_interrupt_handler.h index 3d062d326..71e582f79 100644 --- a/src/core/arm/cpu_interrupt_handler.h +++ b/src/core/arm/cpu_interrupt_handler.h | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <atomic> | ||
| 7 | #include <memory> | 8 | #include <memory> |
| 8 | 9 | ||
| 9 | namespace Common { | 10 | namespace Common { |
| @@ -32,8 +33,8 @@ public: | |||
| 32 | void AwaitInterrupt(); | 33 | void AwaitInterrupt(); |
| 33 | 34 | ||
| 34 | private: | 35 | private: |
| 35 | bool is_interrupted{}; | ||
| 36 | std::unique_ptr<Common::Event> interrupt_event; | 36 | std::unique_ptr<Common::Event> interrupt_event; |
| 37 | std::atomic_bool is_interrupted{false}; | ||
| 37 | }; | 38 | }; |
| 38 | 39 | ||
| 39 | } // namespace Core | 40 | } // namespace Core |
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp index 443ca72eb..b5f28a86e 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp | |||
| @@ -143,7 +143,7 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable& | |||
| 143 | config.wall_clock_cntpct = uses_wall_clock; | 143 | config.wall_clock_cntpct = uses_wall_clock; |
| 144 | 144 | ||
| 145 | // Safe optimizations | 145 | // Safe optimizations |
| 146 | if (Settings::values.cpu_accuracy != Settings::CPUAccuracy::Accurate) { | 146 | if (Settings::values.cpu_accuracy == Settings::CPUAccuracy::DebugMode) { |
| 147 | if (!Settings::values.cpuopt_page_tables) { | 147 | if (!Settings::values.cpuopt_page_tables) { |
| 148 | config.page_table = nullptr; | 148 | config.page_table = nullptr; |
| 149 | } | 149 | } |
| @@ -170,6 +170,17 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable& | |||
| 170 | } | 170 | } |
| 171 | } | 171 | } |
| 172 | 172 | ||
| 173 | // Unsafe optimizations | ||
| 174 | if (Settings::values.cpu_accuracy == Settings::CPUAccuracy::Unsafe) { | ||
| 175 | config.unsafe_optimizations = true; | ||
| 176 | if (Settings::values.cpuopt_unsafe_unfuse_fma) { | ||
| 177 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA; | ||
| 178 | } | ||
| 179 | if (Settings::values.cpuopt_unsafe_reduce_fp_error) { | ||
| 180 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_ReducedErrorFP; | ||
| 181 | } | ||
| 182 | } | ||
| 183 | |||
| 173 | return std::make_unique<Dynarmic::A32::Jit>(config); | 184 | return std::make_unique<Dynarmic::A32::Jit>(config); |
| 174 | } | 185 | } |
| 175 | 186 | ||
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index a63a04a25..ce9968724 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp | |||
| @@ -195,7 +195,7 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable& | |||
| 195 | config.wall_clock_cntpct = uses_wall_clock; | 195 | config.wall_clock_cntpct = uses_wall_clock; |
| 196 | 196 | ||
| 197 | // Safe optimizations | 197 | // Safe optimizations |
| 198 | if (Settings::values.cpu_accuracy != Settings::CPUAccuracy::Accurate) { | 198 | if (Settings::values.cpu_accuracy == Settings::CPUAccuracy::DebugMode) { |
| 199 | if (!Settings::values.cpuopt_page_tables) { | 199 | if (!Settings::values.cpuopt_page_tables) { |
| 200 | config.page_table = nullptr; | 200 | config.page_table = nullptr; |
| 201 | } | 201 | } |
| @@ -222,6 +222,17 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable& | |||
| 222 | } | 222 | } |
| 223 | } | 223 | } |
| 224 | 224 | ||
| 225 | // Unsafe optimizations | ||
| 226 | if (Settings::values.cpu_accuracy == Settings::CPUAccuracy::Unsafe) { | ||
| 227 | config.unsafe_optimizations = true; | ||
| 228 | if (Settings::values.cpuopt_unsafe_unfuse_fma) { | ||
| 229 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA; | ||
| 230 | } | ||
| 231 | if (Settings::values.cpuopt_unsafe_reduce_fp_error) { | ||
| 232 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_ReducedErrorFP; | ||
| 233 | } | ||
| 234 | } | ||
| 235 | |||
| 225 | return std::make_shared<Dynarmic::A64::Jit>(config); | 236 | return std::make_shared<Dynarmic::A64::Jit>(config); |
| 226 | } | 237 | } |
| 227 | 238 | ||
diff --git a/src/core/core.cpp b/src/core/core.cpp index 42277e2cd..c2c0eec0b 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp | |||
| @@ -113,7 +113,7 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs, | |||
| 113 | return FileSys::ConcatenatedVfsFile::MakeConcatenatedFile(concat, dir->GetName()); | 113 | return FileSys::ConcatenatedVfsFile::MakeConcatenatedFile(concat, dir->GetName()); |
| 114 | } | 114 | } |
| 115 | 115 | ||
| 116 | if (FileUtil::IsDirectory(path)) | 116 | if (Common::FS::IsDirectory(path)) |
| 117 | return vfs->OpenFile(path + "/" + "main", FileSys::Mode::Read); | 117 | return vfs->OpenFile(path + "/" + "main", FileSys::Mode::Read); |
| 118 | 118 | ||
| 119 | return vfs->OpenFile(path, FileSys::Mode::Read); | 119 | return vfs->OpenFile(path, FileSys::Mode::Read); |
| @@ -269,14 +269,14 @@ struct System::Impl { | |||
| 269 | // Log last frame performance stats if game was loded | 269 | // Log last frame performance stats if game was loded |
| 270 | if (perf_stats) { | 270 | if (perf_stats) { |
| 271 | const auto perf_results = GetAndResetPerfStats(); | 271 | const auto perf_results = GetAndResetPerfStats(); |
| 272 | telemetry_session->AddField(Telemetry::FieldType::Performance, | 272 | constexpr auto performance = Common::Telemetry::FieldType::Performance; |
| 273 | "Shutdown_EmulationSpeed", | 273 | |
| 274 | telemetry_session->AddField(performance, "Shutdown_EmulationSpeed", | ||
| 274 | perf_results.emulation_speed * 100.0); | 275 | perf_results.emulation_speed * 100.0); |
| 275 | telemetry_session->AddField(Telemetry::FieldType::Performance, "Shutdown_Framerate", | 276 | telemetry_session->AddField(performance, "Shutdown_Framerate", perf_results.game_fps); |
| 276 | perf_results.game_fps); | 277 | telemetry_session->AddField(performance, "Shutdown_Frametime", |
| 277 | telemetry_session->AddField(Telemetry::FieldType::Performance, "Shutdown_Frametime", | ||
| 278 | perf_results.frametime * 1000.0); | 278 | perf_results.frametime * 1000.0); |
| 279 | telemetry_session->AddField(Telemetry::FieldType::Performance, "Mean_Frametime_MS", | 279 | telemetry_session->AddField(performance, "Mean_Frametime_MS", |
| 280 | perf_stats->GetMeanFrametime()); | 280 | perf_stats->GetMeanFrametime()); |
| 281 | } | 281 | } |
| 282 | 282 | ||
diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp index 71af26ec5..e6c8461a5 100644 --- a/src/core/core_timing.cpp +++ b/src/core/core_timing.cpp | |||
| @@ -7,14 +7,14 @@ | |||
| 7 | #include <string> | 7 | #include <string> |
| 8 | #include <tuple> | 8 | #include <tuple> |
| 9 | 9 | ||
| 10 | #include "common/assert.h" | ||
| 11 | #include "common/microprofile.h" | 10 | #include "common/microprofile.h" |
| 12 | #include "core/core_timing.h" | 11 | #include "core/core_timing.h" |
| 13 | #include "core/core_timing_util.h" | 12 | #include "core/core_timing_util.h" |
| 13 | #include "core/hardware_properties.h" | ||
| 14 | 14 | ||
| 15 | namespace Core::Timing { | 15 | namespace Core::Timing { |
| 16 | 16 | ||
| 17 | constexpr u64 MAX_SLICE_LENGTH = 4000; | 17 | constexpr s64 MAX_SLICE_LENGTH = 4000; |
| 18 | 18 | ||
| 19 | std::shared_ptr<EventType> CreateEvent(std::string name, TimedCallback&& callback) { | 19 | std::shared_ptr<EventType> CreateEvent(std::string name, TimedCallback&& callback) { |
| 20 | return std::make_shared<EventType>(std::move(callback), std::move(name)); | 20 | return std::make_shared<EventType>(std::move(callback), std::move(name)); |
| @@ -37,10 +37,8 @@ struct CoreTiming::Event { | |||
| 37 | } | 37 | } |
| 38 | }; | 38 | }; |
| 39 | 39 | ||
| 40 | CoreTiming::CoreTiming() { | 40 | CoreTiming::CoreTiming() |
| 41 | clock = | 41 | : clock{Common::CreateBestMatchingClock(Hardware::BASE_CLOCK_RATE, Hardware::CNTFREQ)} {} |
| 42 | Common::CreateBestMatchingClock(Core::Hardware::BASE_CLOCK_RATE, Core::Hardware::CNTFREQ); | ||
| 43 | } | ||
| 44 | 42 | ||
| 45 | CoreTiming::~CoreTiming() = default; | 43 | CoreTiming::~CoreTiming() = default; |
| 46 | 44 | ||
| @@ -136,7 +134,7 @@ void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type, | |||
| 136 | 134 | ||
| 137 | void CoreTiming::AddTicks(u64 ticks) { | 135 | void CoreTiming::AddTicks(u64 ticks) { |
| 138 | this->ticks += ticks; | 136 | this->ticks += ticks; |
| 139 | downcount -= ticks; | 137 | downcount -= static_cast<s64>(ticks); |
| 140 | } | 138 | } |
| 141 | 139 | ||
| 142 | void CoreTiming::Idle() { | 140 | void CoreTiming::Idle() { |
diff --git a/src/core/core_timing_util.cpp b/src/core/core_timing_util.cpp index aefc63663..8ce8e602e 100644 --- a/src/core/core_timing_util.cpp +++ b/src/core/core_timing_util.cpp | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #include <limits> | 8 | #include <limits> |
| 9 | #include "common/logging/log.h" | 9 | #include "common/logging/log.h" |
| 10 | #include "common/uint128.h" | 10 | #include "common/uint128.h" |
| 11 | #include "core/hardware_properties.h" | ||
| 11 | 12 | ||
| 12 | namespace Core::Timing { | 13 | namespace Core::Timing { |
| 13 | 14 | ||
diff --git a/src/core/core_timing_util.h b/src/core/core_timing_util.h index 2ed979e14..e4a046bf9 100644 --- a/src/core/core_timing_util.h +++ b/src/core/core_timing_util.h | |||
| @@ -6,7 +6,6 @@ | |||
| 6 | 6 | ||
| 7 | #include <chrono> | 7 | #include <chrono> |
| 8 | #include "common/common_types.h" | 8 | #include "common/common_types.h" |
| 9 | #include "core/hardware_properties.h" | ||
| 10 | 9 | ||
| 11 | namespace Core::Timing { | 10 | namespace Core::Timing { |
| 12 | 11 | ||
diff --git a/src/core/cpu_manager.cpp b/src/core/cpu_manager.cpp index 03651e285..688b99eba 100644 --- a/src/core/cpu_manager.cpp +++ b/src/core/cpu_manager.cpp | |||
| @@ -41,9 +41,9 @@ void CpuManager::Shutdown() { | |||
| 41 | running_mode = false; | 41 | running_mode = false; |
| 42 | Pause(false); | 42 | Pause(false); |
| 43 | if (is_multicore) { | 43 | if (is_multicore) { |
| 44 | for (std::size_t core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) { | 44 | for (auto& data : core_data) { |
| 45 | core_data[core].host_thread->join(); | 45 | data.host_thread->join(); |
| 46 | core_data[core].host_thread.reset(); | 46 | data.host_thread.reset(); |
| 47 | } | 47 | } |
| 48 | } else { | 48 | } else { |
| 49 | core_data[0].host_thread->join(); | 49 | core_data[0].host_thread->join(); |
| @@ -166,25 +166,23 @@ void CpuManager::MultiCorePause(bool paused) { | |||
| 166 | bool all_not_barrier = false; | 166 | bool all_not_barrier = false; |
| 167 | while (!all_not_barrier) { | 167 | while (!all_not_barrier) { |
| 168 | all_not_barrier = true; | 168 | all_not_barrier = true; |
| 169 | for (std::size_t core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) { | 169 | for (const auto& data : core_data) { |
| 170 | all_not_barrier &= | 170 | all_not_barrier &= !data.is_running.load() && data.initialized.load(); |
| 171 | !core_data[core].is_running.load() && core_data[core].initialized.load(); | ||
| 172 | } | 171 | } |
| 173 | } | 172 | } |
| 174 | for (std::size_t core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) { | 173 | for (auto& data : core_data) { |
| 175 | core_data[core].enter_barrier->Set(); | 174 | data.enter_barrier->Set(); |
| 176 | } | 175 | } |
| 177 | if (paused_state.load()) { | 176 | if (paused_state.load()) { |
| 178 | bool all_barrier = false; | 177 | bool all_barrier = false; |
| 179 | while (!all_barrier) { | 178 | while (!all_barrier) { |
| 180 | all_barrier = true; | 179 | all_barrier = true; |
| 181 | for (std::size_t core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) { | 180 | for (const auto& data : core_data) { |
| 182 | all_barrier &= | 181 | all_barrier &= data.is_paused.load() && data.initialized.load(); |
| 183 | core_data[core].is_paused.load() && core_data[core].initialized.load(); | ||
| 184 | } | 182 | } |
| 185 | } | 183 | } |
| 186 | for (std::size_t core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) { | 184 | for (auto& data : core_data) { |
| 187 | core_data[core].exit_barrier->Set(); | 185 | data.exit_barrier->Set(); |
| 188 | } | 186 | } |
| 189 | } | 187 | } |
| 190 | } else { | 188 | } else { |
| @@ -192,9 +190,8 @@ void CpuManager::MultiCorePause(bool paused) { | |||
| 192 | bool all_barrier = false; | 190 | bool all_barrier = false; |
| 193 | while (!all_barrier) { | 191 | while (!all_barrier) { |
| 194 | all_barrier = true; | 192 | all_barrier = true; |
| 195 | for (std::size_t core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) { | 193 | for (const auto& data : core_data) { |
| 196 | all_barrier &= | 194 | all_barrier &= data.is_paused.load() && data.initialized.load(); |
| 197 | core_data[core].is_paused.load() && core_data[core].initialized.load(); | ||
| 198 | } | 195 | } |
| 199 | } | 196 | } |
| 200 | /// Don't release the barrier | 197 | /// Don't release the barrier |
diff --git a/src/core/crypto/aes_util.cpp b/src/core/crypto/aes_util.cpp index 330996b24..6a9734812 100644 --- a/src/core/crypto/aes_util.cpp +++ b/src/core/crypto/aes_util.cpp | |||
| @@ -116,7 +116,7 @@ void AESCipher<Key, KeySize>::XTSTranscode(const u8* src, std::size_t size, u8* | |||
| 116 | 116 | ||
| 117 | for (std::size_t i = 0; i < size; i += sector_size) { | 117 | for (std::size_t i = 0; i < size; i += sector_size) { |
| 118 | SetIV(CalculateNintendoTweak(sector_id++)); | 118 | SetIV(CalculateNintendoTweak(sector_id++)); |
| 119 | Transcode<u8, u8>(src + i, sector_size, dest + i, op); | 119 | Transcode(src + i, sector_size, dest + i, op); |
| 120 | } | 120 | } |
| 121 | } | 121 | } |
| 122 | 122 | ||
diff --git a/src/core/crypto/key_manager.cpp b/src/core/crypto/key_manager.cpp index f87fe0abc..dc591c730 100644 --- a/src/core/crypto/key_manager.cpp +++ b/src/core/crypto/key_manager.cpp | |||
| @@ -36,18 +36,86 @@ | |||
| 36 | #include "core/settings.h" | 36 | #include "core/settings.h" |
| 37 | 37 | ||
| 38 | namespace Core::Crypto { | 38 | namespace Core::Crypto { |
| 39 | namespace { | ||
| 39 | 40 | ||
| 40 | constexpr u64 CURRENT_CRYPTO_REVISION = 0x5; | 41 | constexpr u64 CURRENT_CRYPTO_REVISION = 0x5; |
| 41 | constexpr u64 FULL_TICKET_SIZE = 0x400; | 42 | constexpr u64 FULL_TICKET_SIZE = 0x400; |
| 42 | 43 | ||
| 43 | using namespace Common; | 44 | using Common::AsArray; |
| 44 | 45 | ||
| 45 | const std::array<SHA256Hash, 2> eticket_source_hashes{ | 46 | // clang-format off |
| 46 | "B71DB271DC338DF380AA2C4335EF8873B1AFD408E80B3582D8719FC81C5E511C"_array32, // eticket_rsa_kek_source | 47 | constexpr std::array eticket_source_hashes{ |
| 47 | "E8965A187D30E57869F562D04383C996DE487BBA5761363D2D4D32391866A85C"_array32, // eticket_rsa_kekek_source | 48 | AsArray("B71DB271DC338DF380AA2C4335EF8873B1AFD408E80B3582D8719FC81C5E511C"), // eticket_rsa_kek_source |
| 49 | AsArray("E8965A187D30E57869F562D04383C996DE487BBA5761363D2D4D32391866A85C"), // eticket_rsa_kekek_source | ||
| 48 | }; | 50 | }; |
| 51 | // clang-format on | ||
| 49 | 52 | ||
| 50 | const std::map<std::pair<S128KeyType, u64>, std::string> KEYS_VARIABLE_LENGTH{ | 53 | constexpr std::array<std::pair<std::string_view, KeyIndex<S128KeyType>>, 30> s128_file_id{{ |
| 54 | {"eticket_rsa_kek", {S128KeyType::ETicketRSAKek, 0, 0}}, | ||
| 55 | {"eticket_rsa_kek_source", | ||
| 56 | {S128KeyType::Source, static_cast<u64>(SourceKeyType::ETicketKek), 0}}, | ||
| 57 | {"eticket_rsa_kekek_source", | ||
| 58 | {S128KeyType::Source, static_cast<u64>(SourceKeyType::ETicketKekek), 0}}, | ||
| 59 | {"rsa_kek_mask_0", {S128KeyType::RSAKek, static_cast<u64>(RSAKekType::Mask0), 0}}, | ||
| 60 | {"rsa_kek_seed_3", {S128KeyType::RSAKek, static_cast<u64>(RSAKekType::Seed3), 0}}, | ||
| 61 | {"rsa_oaep_kek_generation_source", | ||
| 62 | {S128KeyType::Source, static_cast<u64>(SourceKeyType::RSAOaepKekGeneration), 0}}, | ||
| 63 | {"sd_card_kek_source", {S128KeyType::Source, static_cast<u64>(SourceKeyType::SDKek), 0}}, | ||
| 64 | {"aes_kek_generation_source", | ||
| 65 | {S128KeyType::Source, static_cast<u64>(SourceKeyType::AESKekGeneration), 0}}, | ||
| 66 | {"aes_key_generation_source", | ||
| 67 | {S128KeyType::Source, static_cast<u64>(SourceKeyType::AESKeyGeneration), 0}}, | ||
| 68 | {"package2_key_source", {S128KeyType::Source, static_cast<u64>(SourceKeyType::Package2), 0}}, | ||
| 69 | {"master_key_source", {S128KeyType::Source, static_cast<u64>(SourceKeyType::Master), 0}}, | ||
| 70 | {"header_kek_source", {S128KeyType::Source, static_cast<u64>(SourceKeyType::HeaderKek), 0}}, | ||
| 71 | {"key_area_key_application_source", | ||
| 72 | {S128KeyType::Source, static_cast<u64>(SourceKeyType::KeyAreaKey), | ||
| 73 | static_cast<u64>(KeyAreaKeyType::Application)}}, | ||
| 74 | {"key_area_key_ocean_source", | ||
| 75 | {S128KeyType::Source, static_cast<u64>(SourceKeyType::KeyAreaKey), | ||
| 76 | static_cast<u64>(KeyAreaKeyType::Ocean)}}, | ||
| 77 | {"key_area_key_system_source", | ||
| 78 | {S128KeyType::Source, static_cast<u64>(SourceKeyType::KeyAreaKey), | ||
| 79 | static_cast<u64>(KeyAreaKeyType::System)}}, | ||
| 80 | {"titlekek_source", {S128KeyType::Source, static_cast<u64>(SourceKeyType::Titlekek), 0}}, | ||
| 81 | {"keyblob_mac_key_source", | ||
| 82 | {S128KeyType::Source, static_cast<u64>(SourceKeyType::KeyblobMAC), 0}}, | ||
| 83 | {"tsec_key", {S128KeyType::TSEC, 0, 0}}, | ||
| 84 | {"secure_boot_key", {S128KeyType::SecureBoot, 0, 0}}, | ||
| 85 | {"sd_seed", {S128KeyType::SDSeed, 0, 0}}, | ||
| 86 | {"bis_key_0_crypt", {S128KeyType::BIS, 0, static_cast<u64>(BISKeyType::Crypto)}}, | ||
| 87 | {"bis_key_0_tweak", {S128KeyType::BIS, 0, static_cast<u64>(BISKeyType::Tweak)}}, | ||
| 88 | {"bis_key_1_crypt", {S128KeyType::BIS, 1, static_cast<u64>(BISKeyType::Crypto)}}, | ||
| 89 | {"bis_key_1_tweak", {S128KeyType::BIS, 1, static_cast<u64>(BISKeyType::Tweak)}}, | ||
| 90 | {"bis_key_2_crypt", {S128KeyType::BIS, 2, static_cast<u64>(BISKeyType::Crypto)}}, | ||
| 91 | {"bis_key_2_tweak", {S128KeyType::BIS, 2, static_cast<u64>(BISKeyType::Tweak)}}, | ||
| 92 | {"bis_key_3_crypt", {S128KeyType::BIS, 3, static_cast<u64>(BISKeyType::Crypto)}}, | ||
| 93 | {"bis_key_3_tweak", {S128KeyType::BIS, 3, static_cast<u64>(BISKeyType::Tweak)}}, | ||
| 94 | {"header_kek", {S128KeyType::HeaderKek, 0, 0}}, | ||
| 95 | {"sd_card_kek", {S128KeyType::SDKek, 0, 0}}, | ||
| 96 | }}; | ||
| 97 | |||
| 98 | auto Find128ByName(std::string_view name) { | ||
| 99 | return std::find_if(s128_file_id.begin(), s128_file_id.end(), | ||
| 100 | [&name](const auto& pair) { return pair.first == name; }); | ||
| 101 | } | ||
| 102 | |||
| 103 | constexpr std::array<std::pair<std::string_view, KeyIndex<S256KeyType>>, 6> s256_file_id{{ | ||
| 104 | {"header_key", {S256KeyType::Header, 0, 0}}, | ||
| 105 | {"sd_card_save_key_source", {S256KeyType::SDKeySource, static_cast<u64>(SDKeyType::Save), 0}}, | ||
| 106 | {"sd_card_nca_key_source", {S256KeyType::SDKeySource, static_cast<u64>(SDKeyType::NCA), 0}}, | ||
| 107 | {"header_key_source", {S256KeyType::HeaderSource, 0, 0}}, | ||
| 108 | {"sd_card_save_key", {S256KeyType::SDKey, static_cast<u64>(SDKeyType::Save), 0}}, | ||
| 109 | {"sd_card_nca_key", {S256KeyType::SDKey, static_cast<u64>(SDKeyType::NCA), 0}}, | ||
| 110 | }}; | ||
| 111 | |||
| 112 | auto Find256ByName(std::string_view name) { | ||
| 113 | return std::find_if(s256_file_id.begin(), s256_file_id.end(), | ||
| 114 | [&name](const auto& pair) { return pair.first == name; }); | ||
| 115 | } | ||
| 116 | |||
| 117 | using KeyArray = std::array<std::pair<std::pair<S128KeyType, u64>, std::string_view>, 7>; | ||
| 118 | constexpr KeyArray KEYS_VARIABLE_LENGTH{{ | ||
| 51 | {{S128KeyType::Master, 0}, "master_key_"}, | 119 | {{S128KeyType::Master, 0}, "master_key_"}, |
| 52 | {{S128KeyType::Package1, 0}, "package1_key_"}, | 120 | {{S128KeyType::Package1, 0}, "package1_key_"}, |
| 53 | {{S128KeyType::Package2, 0}, "package2_key_"}, | 121 | {{S128KeyType::Package2, 0}, "package2_key_"}, |
| @@ -55,14 +123,13 @@ const std::map<std::pair<S128KeyType, u64>, std::string> KEYS_VARIABLE_LENGTH{ | |||
| 55 | {{S128KeyType::Source, static_cast<u64>(SourceKeyType::Keyblob)}, "keyblob_key_source_"}, | 123 | {{S128KeyType::Source, static_cast<u64>(SourceKeyType::Keyblob)}, "keyblob_key_source_"}, |
| 56 | {{S128KeyType::Keyblob, 0}, "keyblob_key_"}, | 124 | {{S128KeyType::Keyblob, 0}, "keyblob_key_"}, |
| 57 | {{S128KeyType::KeyblobMAC, 0}, "keyblob_mac_key_"}, | 125 | {{S128KeyType::KeyblobMAC, 0}, "keyblob_mac_key_"}, |
| 58 | }; | 126 | }}; |
| 59 | 127 | ||
| 60 | namespace { | ||
| 61 | template <std::size_t Size> | 128 | template <std::size_t Size> |
| 62 | bool IsAllZeroArray(const std::array<u8, Size>& array) { | 129 | bool IsAllZeroArray(const std::array<u8, Size>& array) { |
| 63 | return std::all_of(array.begin(), array.end(), [](const auto& elem) { return elem == 0; }); | 130 | return std::all_of(array.begin(), array.end(), [](const auto& elem) { return elem == 0; }); |
| 64 | } | 131 | } |
| 65 | } // namespace | 132 | } // Anonymous namespace |
| 66 | 133 | ||
| 67 | u64 GetSignatureTypeDataSize(SignatureType type) { | 134 | u64 GetSignatureTypeDataSize(SignatureType type) { |
| 68 | switch (type) { | 135 | switch (type) { |
| @@ -94,13 +161,13 @@ u64 GetSignatureTypePaddingSize(SignatureType type) { | |||
| 94 | } | 161 | } |
| 95 | 162 | ||
| 96 | SignatureType Ticket::GetSignatureType() const { | 163 | SignatureType Ticket::GetSignatureType() const { |
| 97 | if (auto ticket = std::get_if<RSA4096Ticket>(&data)) { | 164 | if (const auto* ticket = std::get_if<RSA4096Ticket>(&data)) { |
| 98 | return ticket->sig_type; | 165 | return ticket->sig_type; |
| 99 | } | 166 | } |
| 100 | if (auto ticket = std::get_if<RSA2048Ticket>(&data)) { | 167 | if (const auto* ticket = std::get_if<RSA2048Ticket>(&data)) { |
| 101 | return ticket->sig_type; | 168 | return ticket->sig_type; |
| 102 | } | 169 | } |
| 103 | if (auto ticket = std::get_if<ECDSATicket>(&data)) { | 170 | if (const auto* ticket = std::get_if<ECDSATicket>(&data)) { |
| 104 | return ticket->sig_type; | 171 | return ticket->sig_type; |
| 105 | } | 172 | } |
| 106 | 173 | ||
| @@ -108,13 +175,13 @@ SignatureType Ticket::GetSignatureType() const { | |||
| 108 | } | 175 | } |
| 109 | 176 | ||
| 110 | TicketData& Ticket::GetData() { | 177 | TicketData& Ticket::GetData() { |
| 111 | if (auto ticket = std::get_if<RSA4096Ticket>(&data)) { | 178 | if (auto* ticket = std::get_if<RSA4096Ticket>(&data)) { |
| 112 | return ticket->data; | 179 | return ticket->data; |
| 113 | } | 180 | } |
| 114 | if (auto ticket = std::get_if<RSA2048Ticket>(&data)) { | 181 | if (auto* ticket = std::get_if<RSA2048Ticket>(&data)) { |
| 115 | return ticket->data; | 182 | return ticket->data; |
| 116 | } | 183 | } |
| 117 | if (auto ticket = std::get_if<ECDSATicket>(&data)) { | 184 | if (auto* ticket = std::get_if<ECDSATicket>(&data)) { |
| 118 | return ticket->data; | 185 | return ticket->data; |
| 119 | } | 186 | } |
| 120 | 187 | ||
| @@ -122,13 +189,13 @@ TicketData& Ticket::GetData() { | |||
| 122 | } | 189 | } |
| 123 | 190 | ||
| 124 | const TicketData& Ticket::GetData() const { | 191 | const TicketData& Ticket::GetData() const { |
| 125 | if (auto ticket = std::get_if<RSA4096Ticket>(&data)) { | 192 | if (const auto* ticket = std::get_if<RSA4096Ticket>(&data)) { |
| 126 | return ticket->data; | 193 | return ticket->data; |
| 127 | } | 194 | } |
| 128 | if (auto ticket = std::get_if<RSA2048Ticket>(&data)) { | 195 | if (const auto* ticket = std::get_if<RSA2048Ticket>(&data)) { |
| 129 | return ticket->data; | 196 | return ticket->data; |
| 130 | } | 197 | } |
| 131 | if (auto ticket = std::get_if<ECDSATicket>(&data)) { | 198 | if (const auto* ticket = std::get_if<ECDSATicket>(&data)) { |
| 132 | return ticket->data; | 199 | return ticket->data; |
| 133 | } | 200 | } |
| 134 | 201 | ||
| @@ -231,8 +298,9 @@ void KeyManager::DeriveGeneralPurposeKeys(std::size_t crypto_revision) { | |||
| 231 | } | 298 | } |
| 232 | 299 | ||
| 233 | RSAKeyPair<2048> KeyManager::GetETicketRSAKey() const { | 300 | RSAKeyPair<2048> KeyManager::GetETicketRSAKey() const { |
| 234 | if (IsAllZeroArray(eticket_extended_kek) || !HasKey(S128KeyType::ETicketRSAKek)) | 301 | if (IsAllZeroArray(eticket_extended_kek) || !HasKey(S128KeyType::ETicketRSAKek)) { |
| 235 | return {}; | 302 | return {}; |
| 303 | } | ||
| 236 | 304 | ||
| 237 | const auto eticket_final = GetKey(S128KeyType::ETicketRSAKek); | 305 | const auto eticket_final = GetKey(S128KeyType::ETicketRSAKek); |
| 238 | 306 | ||
| @@ -259,27 +327,30 @@ Key128 DeriveKeyblobMACKey(const Key128& keyblob_key, const Key128& mac_source) | |||
| 259 | } | 327 | } |
| 260 | 328 | ||
| 261 | std::optional<Key128> DeriveSDSeed() { | 329 | std::optional<Key128> DeriveSDSeed() { |
| 262 | const FileUtil::IOFile save_43(FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) + | 330 | const Common::FS::IOFile save_43(Common::FS::GetUserPath(Common::FS::UserPath::NANDDir) + |
| 263 | "/system/save/8000000000000043", | 331 | "/system/save/8000000000000043", |
| 264 | "rb+"); | 332 | "rb+"); |
| 265 | if (!save_43.IsOpen()) | 333 | if (!save_43.IsOpen()) { |
| 266 | return {}; | 334 | return std::nullopt; |
| 335 | } | ||
| 267 | 336 | ||
| 268 | const FileUtil::IOFile sd_private( | 337 | const Common::FS::IOFile sd_private(Common::FS::GetUserPath(Common::FS::UserPath::SDMCDir) + |
| 269 | FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir) + "/Nintendo/Contents/private", "rb+"); | 338 | "/Nintendo/Contents/private", |
| 270 | if (!sd_private.IsOpen()) | 339 | "rb+"); |
| 271 | return {}; | 340 | if (!sd_private.IsOpen()) { |
| 341 | return std::nullopt; | ||
| 342 | } | ||
| 272 | 343 | ||
| 273 | std::array<u8, 0x10> private_seed{}; | 344 | std::array<u8, 0x10> private_seed{}; |
| 274 | if (sd_private.ReadBytes(private_seed.data(), private_seed.size()) != private_seed.size()) { | 345 | if (sd_private.ReadBytes(private_seed.data(), private_seed.size()) != private_seed.size()) { |
| 275 | return {}; | 346 | return std::nullopt; |
| 276 | } | 347 | } |
| 277 | 348 | ||
| 278 | std::array<u8, 0x10> buffer{}; | 349 | std::array<u8, 0x10> buffer{}; |
| 279 | std::size_t offset = 0; | 350 | std::size_t offset = 0; |
| 280 | for (; offset + 0x10 < save_43.GetSize(); ++offset) { | 351 | for (; offset + 0x10 < save_43.GetSize(); ++offset) { |
| 281 | if (!save_43.Seek(offset, SEEK_SET)) { | 352 | if (!save_43.Seek(offset, SEEK_SET)) { |
| 282 | return {}; | 353 | return std::nullopt; |
| 283 | } | 354 | } |
| 284 | 355 | ||
| 285 | save_43.ReadBytes(buffer.data(), buffer.size()); | 356 | save_43.ReadBytes(buffer.data(), buffer.size()); |
| @@ -289,23 +360,26 @@ std::optional<Key128> DeriveSDSeed() { | |||
| 289 | } | 360 | } |
| 290 | 361 | ||
| 291 | if (!save_43.Seek(offset + 0x10, SEEK_SET)) { | 362 | if (!save_43.Seek(offset + 0x10, SEEK_SET)) { |
| 292 | return {}; | 363 | return std::nullopt; |
| 293 | } | 364 | } |
| 294 | 365 | ||
| 295 | Key128 seed{}; | 366 | Key128 seed{}; |
| 296 | if (save_43.ReadBytes(seed.data(), seed.size()) != seed.size()) { | 367 | if (save_43.ReadBytes(seed.data(), seed.size()) != seed.size()) { |
| 297 | return {}; | 368 | return std::nullopt; |
| 298 | } | 369 | } |
| 299 | return seed; | 370 | return seed; |
| 300 | } | 371 | } |
| 301 | 372 | ||
| 302 | Loader::ResultStatus DeriveSDKeys(std::array<Key256, 2>& sd_keys, KeyManager& keys) { | 373 | Loader::ResultStatus DeriveSDKeys(std::array<Key256, 2>& sd_keys, KeyManager& keys) { |
| 303 | if (!keys.HasKey(S128KeyType::Source, static_cast<u64>(SourceKeyType::SDKek))) | 374 | if (!keys.HasKey(S128KeyType::Source, static_cast<u64>(SourceKeyType::SDKek))) { |
| 304 | return Loader::ResultStatus::ErrorMissingSDKEKSource; | 375 | return Loader::ResultStatus::ErrorMissingSDKEKSource; |
| 305 | if (!keys.HasKey(S128KeyType::Source, static_cast<u64>(SourceKeyType::AESKekGeneration))) | 376 | } |
| 377 | if (!keys.HasKey(S128KeyType::Source, static_cast<u64>(SourceKeyType::AESKekGeneration))) { | ||
| 306 | return Loader::ResultStatus::ErrorMissingAESKEKGenerationSource; | 378 | return Loader::ResultStatus::ErrorMissingAESKEKGenerationSource; |
| 307 | if (!keys.HasKey(S128KeyType::Source, static_cast<u64>(SourceKeyType::AESKeyGeneration))) | 379 | } |
| 380 | if (!keys.HasKey(S128KeyType::Source, static_cast<u64>(SourceKeyType::AESKeyGeneration))) { | ||
| 308 | return Loader::ResultStatus::ErrorMissingAESKeyGenerationSource; | 381 | return Loader::ResultStatus::ErrorMissingAESKeyGenerationSource; |
| 382 | } | ||
| 309 | 383 | ||
| 310 | const auto sd_kek_source = | 384 | const auto sd_kek_source = |
| 311 | keys.GetKey(S128KeyType::Source, static_cast<u64>(SourceKeyType::SDKek)); | 385 | keys.GetKey(S128KeyType::Source, static_cast<u64>(SourceKeyType::SDKek)); |
| @@ -318,14 +392,17 @@ Loader::ResultStatus DeriveSDKeys(std::array<Key256, 2>& sd_keys, KeyManager& ke | |||
| 318 | GenerateKeyEncryptionKey(sd_kek_source, master_00, aes_kek_gen, aes_key_gen); | 392 | GenerateKeyEncryptionKey(sd_kek_source, master_00, aes_kek_gen, aes_key_gen); |
| 319 | keys.SetKey(S128KeyType::SDKek, sd_kek); | 393 | keys.SetKey(S128KeyType::SDKek, sd_kek); |
| 320 | 394 | ||
| 321 | if (!keys.HasKey(S128KeyType::SDSeed)) | 395 | if (!keys.HasKey(S128KeyType::SDSeed)) { |
| 322 | return Loader::ResultStatus::ErrorMissingSDSeed; | 396 | return Loader::ResultStatus::ErrorMissingSDSeed; |
| 397 | } | ||
| 323 | const auto sd_seed = keys.GetKey(S128KeyType::SDSeed); | 398 | const auto sd_seed = keys.GetKey(S128KeyType::SDSeed); |
| 324 | 399 | ||
| 325 | if (!keys.HasKey(S256KeyType::SDKeySource, static_cast<u64>(SDKeyType::Save))) | 400 | if (!keys.HasKey(S256KeyType::SDKeySource, static_cast<u64>(SDKeyType::Save))) { |
| 326 | return Loader::ResultStatus::ErrorMissingSDSaveKeySource; | 401 | return Loader::ResultStatus::ErrorMissingSDSaveKeySource; |
| 327 | if (!keys.HasKey(S256KeyType::SDKeySource, static_cast<u64>(SDKeyType::NCA))) | 402 | } |
| 403 | if (!keys.HasKey(S256KeyType::SDKeySource, static_cast<u64>(SDKeyType::NCA))) { | ||
| 328 | return Loader::ResultStatus::ErrorMissingSDNCAKeySource; | 404 | return Loader::ResultStatus::ErrorMissingSDNCAKeySource; |
| 405 | } | ||
| 329 | 406 | ||
| 330 | std::array<Key256, 2> sd_key_sources{ | 407 | std::array<Key256, 2> sd_key_sources{ |
| 331 | keys.GetKey(S256KeyType::SDKeySource, static_cast<u64>(SDKeyType::Save)), | 408 | keys.GetKey(S256KeyType::SDKeySource, static_cast<u64>(SDKeyType::Save)), |
| @@ -334,8 +411,9 @@ Loader::ResultStatus DeriveSDKeys(std::array<Key256, 2>& sd_keys, KeyManager& ke | |||
| 334 | 411 | ||
| 335 | // Combine sources and seed | 412 | // Combine sources and seed |
| 336 | for (auto& source : sd_key_sources) { | 413 | for (auto& source : sd_key_sources) { |
| 337 | for (std::size_t i = 0; i < source.size(); ++i) | 414 | for (std::size_t i = 0; i < source.size(); ++i) { |
| 338 | source[i] ^= sd_seed[i & 0xF]; | 415 | source[i] ^= sd_seed[i & 0xF]; |
| 416 | } | ||
| 339 | } | 417 | } |
| 340 | 418 | ||
| 341 | AESCipher<Key128> cipher(sd_kek, Mode::ECB); | 419 | AESCipher<Key128> cipher(sd_kek, Mode::ECB); |
| @@ -353,9 +431,10 @@ Loader::ResultStatus DeriveSDKeys(std::array<Key256, 2>& sd_keys, KeyManager& ke | |||
| 353 | return Loader::ResultStatus::Success; | 431 | return Loader::ResultStatus::Success; |
| 354 | } | 432 | } |
| 355 | 433 | ||
| 356 | std::vector<Ticket> GetTicketblob(const FileUtil::IOFile& ticket_save) { | 434 | std::vector<Ticket> GetTicketblob(const Common::FS::IOFile& ticket_save) { |
| 357 | if (!ticket_save.IsOpen()) | 435 | if (!ticket_save.IsOpen()) { |
| 358 | return {}; | 436 | return {}; |
| 437 | } | ||
| 359 | 438 | ||
| 360 | std::vector<u8> buffer(ticket_save.GetSize()); | 439 | std::vector<u8> buffer(ticket_save.GetSize()); |
| 361 | if (ticket_save.ReadBytes(buffer.data(), buffer.size()) != buffer.size()) { | 440 | if (ticket_save.ReadBytes(buffer.data(), buffer.size()) != buffer.size()) { |
| @@ -415,7 +494,7 @@ static std::optional<u64> FindTicketOffset(const std::array<u8, size>& data) { | |||
| 415 | offset = i + 1; | 494 | offset = i + 1; |
| 416 | break; | 495 | break; |
| 417 | } else if (data[i] != 0x0) { | 496 | } else if (data[i] != 0x0) { |
| 418 | return {}; | 497 | return std::nullopt; |
| 419 | } | 498 | } |
| 420 | } | 499 | } |
| 421 | 500 | ||
| @@ -425,16 +504,18 @@ static std::optional<u64> FindTicketOffset(const std::array<u8, size>& data) { | |||
| 425 | std::optional<std::pair<Key128, Key128>> ParseTicket(const Ticket& ticket, | 504 | std::optional<std::pair<Key128, Key128>> ParseTicket(const Ticket& ticket, |
| 426 | const RSAKeyPair<2048>& key) { | 505 | const RSAKeyPair<2048>& key) { |
| 427 | const auto issuer = ticket.GetData().issuer; | 506 | const auto issuer = ticket.GetData().issuer; |
| 428 | if (IsAllZeroArray(issuer)) | 507 | if (IsAllZeroArray(issuer)) { |
| 429 | return {}; | 508 | return std::nullopt; |
| 509 | } | ||
| 430 | if (issuer[0] != 'R' || issuer[1] != 'o' || issuer[2] != 'o' || issuer[3] != 't') { | 510 | if (issuer[0] != 'R' || issuer[1] != 'o' || issuer[2] != 'o' || issuer[3] != 't') { |
| 431 | LOG_INFO(Crypto, "Attempting to parse ticket with non-standard certificate authority."); | 511 | LOG_INFO(Crypto, "Attempting to parse ticket with non-standard certificate authority."); |
| 432 | } | 512 | } |
| 433 | 513 | ||
| 434 | Key128 rights_id = ticket.GetData().rights_id; | 514 | Key128 rights_id = ticket.GetData().rights_id; |
| 435 | 515 | ||
| 436 | if (rights_id == Key128{}) | 516 | if (rights_id == Key128{}) { |
| 437 | return {}; | 517 | return std::nullopt; |
| 518 | } | ||
| 438 | 519 | ||
| 439 | if (!std::any_of(ticket.GetData().title_key_common_pad.begin(), | 520 | if (!std::any_of(ticket.GetData().title_key_common_pad.begin(), |
| 440 | ticket.GetData().title_key_common_pad.end(), [](u8 b) { return b != 0; })) { | 521 | ticket.GetData().title_key_common_pad.end(), [](u8 b) { return b != 0; })) { |
| @@ -466,15 +547,17 @@ std::optional<std::pair<Key128, Key128>> ParseTicket(const Ticket& ticket, | |||
| 466 | std::array<u8, 0xDF> m_2; | 547 | std::array<u8, 0xDF> m_2; |
| 467 | std::memcpy(m_2.data(), rsa_step.data() + 0x21, m_2.size()); | 548 | std::memcpy(m_2.data(), rsa_step.data() + 0x21, m_2.size()); |
| 468 | 549 | ||
| 469 | if (m_0 != 0) | 550 | if (m_0 != 0) { |
| 470 | return {}; | 551 | return std::nullopt; |
| 552 | } | ||
| 471 | 553 | ||
| 472 | m_1 = m_1 ^ MGF1<0x20>(m_2); | 554 | m_1 = m_1 ^ MGF1<0x20>(m_2); |
| 473 | m_2 = m_2 ^ MGF1<0xDF>(m_1); | 555 | m_2 = m_2 ^ MGF1<0xDF>(m_1); |
| 474 | 556 | ||
| 475 | const auto offset = FindTicketOffset(m_2); | 557 | const auto offset = FindTicketOffset(m_2); |
| 476 | if (!offset) | 558 | if (!offset) { |
| 477 | return {}; | 559 | return std::nullopt; |
| 560 | } | ||
| 478 | ASSERT(*offset > 0); | 561 | ASSERT(*offset > 0); |
| 479 | 562 | ||
| 480 | Key128 key_temp{}; | 563 | Key128 key_temp{}; |
| @@ -485,8 +568,8 @@ std::optional<std::pair<Key128, Key128>> ParseTicket(const Ticket& ticket, | |||
| 485 | 568 | ||
| 486 | KeyManager::KeyManager() { | 569 | KeyManager::KeyManager() { |
| 487 | // Initialize keys | 570 | // Initialize keys |
| 488 | const std::string hactool_keys_dir = FileUtil::GetHactoolConfigurationPath(); | 571 | const std::string hactool_keys_dir = Common::FS::GetHactoolConfigurationPath(); |
| 489 | const std::string yuzu_keys_dir = FileUtil::GetUserPath(FileUtil::UserPath::KeysDir); | 572 | const std::string yuzu_keys_dir = Common::FS::GetUserPath(Common::FS::UserPath::KeysDir); |
| 490 | if (Settings::values.use_dev_keys) { | 573 | if (Settings::values.use_dev_keys) { |
| 491 | dev_mode = true; | 574 | dev_mode = true; |
| 492 | AttemptLoadKeyFile(yuzu_keys_dir, hactool_keys_dir, "dev.keys", false); | 575 | AttemptLoadKeyFile(yuzu_keys_dir, hactool_keys_dir, "dev.keys", false); |
| @@ -504,34 +587,39 @@ KeyManager::KeyManager() { | |||
| 504 | } | 587 | } |
| 505 | 588 | ||
| 506 | static bool ValidCryptoRevisionString(std::string_view base, size_t begin, size_t length) { | 589 | static bool ValidCryptoRevisionString(std::string_view base, size_t begin, size_t length) { |
| 507 | if (base.size() < begin + length) | 590 | if (base.size() < begin + length) { |
| 508 | return false; | 591 | return false; |
| 592 | } | ||
| 509 | return std::all_of(base.begin() + begin, base.begin() + begin + length, | 593 | return std::all_of(base.begin() + begin, base.begin() + begin + length, |
| 510 | [](u8 c) { return std::isxdigit(c); }); | 594 | [](u8 c) { return std::isxdigit(c); }); |
| 511 | } | 595 | } |
| 512 | 596 | ||
| 513 | void KeyManager::LoadFromFile(const std::string& filename, bool is_title_keys) { | 597 | void KeyManager::LoadFromFile(const std::string& filename, bool is_title_keys) { |
| 514 | std::ifstream file; | 598 | std::ifstream file; |
| 515 | OpenFStream(file, filename, std::ios_base::in); | 599 | Common::FS::OpenFStream(file, filename, std::ios_base::in); |
| 516 | if (!file.is_open()) | 600 | if (!file.is_open()) { |
| 517 | return; | 601 | return; |
| 602 | } | ||
| 518 | 603 | ||
| 519 | std::string line; | 604 | std::string line; |
| 520 | while (std::getline(file, line)) { | 605 | while (std::getline(file, line)) { |
| 521 | std::vector<std::string> out; | 606 | std::vector<std::string> out; |
| 522 | std::stringstream stream(line); | 607 | std::stringstream stream(line); |
| 523 | std::string item; | 608 | std::string item; |
| 524 | while (std::getline(stream, item, '=')) | 609 | while (std::getline(stream, item, '=')) { |
| 525 | out.push_back(std::move(item)); | 610 | out.push_back(std::move(item)); |
| 611 | } | ||
| 526 | 612 | ||
| 527 | if (out.size() != 2) | 613 | if (out.size() != 2) { |
| 528 | continue; | 614 | continue; |
| 615 | } | ||
| 529 | 616 | ||
| 530 | out[0].erase(std::remove(out[0].begin(), out[0].end(), ' '), out[0].end()); | 617 | out[0].erase(std::remove(out[0].begin(), out[0].end(), ' '), out[0].end()); |
| 531 | out[1].erase(std::remove(out[1].begin(), out[1].end(), ' '), out[1].end()); | 618 | out[1].erase(std::remove(out[1].begin(), out[1].end(), ' '), out[1].end()); |
| 532 | 619 | ||
| 533 | if (out[0].compare(0, 1, "#") == 0) | 620 | if (out[0].compare(0, 1, "#") == 0) { |
| 534 | continue; | 621 | continue; |
| 622 | } | ||
| 535 | 623 | ||
| 536 | if (is_title_keys) { | 624 | if (is_title_keys) { |
| 537 | auto rights_id_raw = Common::HexStringToArray<16>(out[0]); | 625 | auto rights_id_raw = Common::HexStringToArray<16>(out[0]); |
| @@ -541,24 +629,26 @@ void KeyManager::LoadFromFile(const std::string& filename, bool is_title_keys) { | |||
| 541 | s128_keys[{S128KeyType::Titlekey, rights_id[1], rights_id[0]}] = key; | 629 | s128_keys[{S128KeyType::Titlekey, rights_id[1], rights_id[0]}] = key; |
| 542 | } else { | 630 | } else { |
| 543 | out[0] = Common::ToLower(out[0]); | 631 | out[0] = Common::ToLower(out[0]); |
| 544 | if (s128_file_id.find(out[0]) != s128_file_id.end()) { | 632 | if (const auto iter128 = Find128ByName(out[0]); iter128 != s128_file_id.end()) { |
| 545 | const auto index = s128_file_id.at(out[0]); | 633 | const auto& index = iter128->second; |
| 546 | Key128 key = Common::HexStringToArray<16>(out[1]); | 634 | const Key128 key = Common::HexStringToArray<16>(out[1]); |
| 547 | s128_keys[{index.type, index.field1, index.field2}] = key; | 635 | s128_keys[{index.type, index.field1, index.field2}] = key; |
| 548 | } else if (s256_file_id.find(out[0]) != s256_file_id.end()) { | 636 | } else if (const auto iter256 = Find256ByName(out[0]); iter256 != s256_file_id.end()) { |
| 549 | const auto index = s256_file_id.at(out[0]); | 637 | const auto& index = iter256->second; |
| 550 | Key256 key = Common::HexStringToArray<32>(out[1]); | 638 | const Key256 key = Common::HexStringToArray<32>(out[1]); |
| 551 | s256_keys[{index.type, index.field1, index.field2}] = key; | 639 | s256_keys[{index.type, index.field1, index.field2}] = key; |
| 552 | } else if (out[0].compare(0, 8, "keyblob_") == 0 && | 640 | } else if (out[0].compare(0, 8, "keyblob_") == 0 && |
| 553 | out[0].compare(0, 9, "keyblob_k") != 0) { | 641 | out[0].compare(0, 9, "keyblob_k") != 0) { |
| 554 | if (!ValidCryptoRevisionString(out[0], 8, 2)) | 642 | if (!ValidCryptoRevisionString(out[0], 8, 2)) { |
| 555 | continue; | 643 | continue; |
| 644 | } | ||
| 556 | 645 | ||
| 557 | const auto index = std::stoul(out[0].substr(8, 2), nullptr, 16); | 646 | const auto index = std::stoul(out[0].substr(8, 2), nullptr, 16); |
| 558 | keyblobs[index] = Common::HexStringToArray<0x90>(out[1]); | 647 | keyblobs[index] = Common::HexStringToArray<0x90>(out[1]); |
| 559 | } else if (out[0].compare(0, 18, "encrypted_keyblob_") == 0) { | 648 | } else if (out[0].compare(0, 18, "encrypted_keyblob_") == 0) { |
| 560 | if (!ValidCryptoRevisionString(out[0], 18, 2)) | 649 | if (!ValidCryptoRevisionString(out[0], 18, 2)) { |
| 561 | continue; | 650 | continue; |
| 651 | } | ||
| 562 | 652 | ||
| 563 | const auto index = std::stoul(out[0].substr(18, 2), nullptr, 16); | 653 | const auto index = std::stoul(out[0].substr(18, 2), nullptr, 16); |
| 564 | encrypted_keyblobs[index] = Common::HexStringToArray<0xB0>(out[1]); | 654 | encrypted_keyblobs[index] = Common::HexStringToArray<0xB0>(out[1]); |
| @@ -566,8 +656,9 @@ void KeyManager::LoadFromFile(const std::string& filename, bool is_title_keys) { | |||
| 566 | eticket_extended_kek = Common::HexStringToArray<576>(out[1]); | 656 | eticket_extended_kek = Common::HexStringToArray<576>(out[1]); |
| 567 | } else { | 657 | } else { |
| 568 | for (const auto& kv : KEYS_VARIABLE_LENGTH) { | 658 | for (const auto& kv : KEYS_VARIABLE_LENGTH) { |
| 569 | if (!ValidCryptoRevisionString(out[0], kv.second.size(), 2)) | 659 | if (!ValidCryptoRevisionString(out[0], kv.second.size(), 2)) { |
| 570 | continue; | 660 | continue; |
| 661 | } | ||
| 571 | if (out[0].compare(0, kv.second.size(), kv.second) == 0) { | 662 | if (out[0].compare(0, kv.second.size(), kv.second) == 0) { |
| 572 | const auto index = | 663 | const auto index = |
| 573 | std::stoul(out[0].substr(kv.second.size(), 2), nullptr, 16); | 664 | std::stoul(out[0].substr(kv.second.size(), 2), nullptr, 16); |
| @@ -602,10 +693,11 @@ void KeyManager::LoadFromFile(const std::string& filename, bool is_title_keys) { | |||
| 602 | 693 | ||
| 603 | void KeyManager::AttemptLoadKeyFile(const std::string& dir1, const std::string& dir2, | 694 | void KeyManager::AttemptLoadKeyFile(const std::string& dir1, const std::string& dir2, |
| 604 | const std::string& filename, bool title) { | 695 | const std::string& filename, bool title) { |
| 605 | if (FileUtil::Exists(dir1 + DIR_SEP + filename)) | 696 | if (Common::FS::Exists(dir1 + DIR_SEP + filename)) { |
| 606 | LoadFromFile(dir1 + DIR_SEP + filename, title); | 697 | LoadFromFile(dir1 + DIR_SEP + filename, title); |
| 607 | else if (FileUtil::Exists(dir2 + DIR_SEP + filename)) | 698 | } else if (Common::FS::Exists(dir2 + DIR_SEP + filename)) { |
| 608 | LoadFromFile(dir2 + DIR_SEP + filename, title); | 699 | LoadFromFile(dir2 + DIR_SEP + filename, title); |
| 700 | } | ||
| 609 | } | 701 | } |
| 610 | 702 | ||
| 611 | bool KeyManager::BaseDeriveNecessary() const { | 703 | bool KeyManager::BaseDeriveNecessary() const { |
| @@ -613,8 +705,9 @@ bool KeyManager::BaseDeriveNecessary() const { | |||
| 613 | return !HasKey(key_type, index1, index2); | 705 | return !HasKey(key_type, index1, index2); |
| 614 | }; | 706 | }; |
| 615 | 707 | ||
| 616 | if (check_key_existence(S256KeyType::Header)) | 708 | if (check_key_existence(S256KeyType::Header)) { |
| 617 | return true; | 709 | return true; |
| 710 | } | ||
| 618 | 711 | ||
| 619 | for (size_t i = 0; i < CURRENT_CRYPTO_REVISION; ++i) { | 712 | for (size_t i = 0; i < CURRENT_CRYPTO_REVISION; ++i) { |
| 620 | if (check_key_existence(S128KeyType::Master, i) || | 713 | if (check_key_existence(S128KeyType::Master, i) || |
| @@ -639,14 +732,16 @@ bool KeyManager::HasKey(S256KeyType id, u64 field1, u64 field2) const { | |||
| 639 | } | 732 | } |
| 640 | 733 | ||
| 641 | Key128 KeyManager::GetKey(S128KeyType id, u64 field1, u64 field2) const { | 734 | Key128 KeyManager::GetKey(S128KeyType id, u64 field1, u64 field2) const { |
| 642 | if (!HasKey(id, field1, field2)) | 735 | if (!HasKey(id, field1, field2)) { |
| 643 | return {}; | 736 | return {}; |
| 737 | } | ||
| 644 | return s128_keys.at({id, field1, field2}); | 738 | return s128_keys.at({id, field1, field2}); |
| 645 | } | 739 | } |
| 646 | 740 | ||
| 647 | Key256 KeyManager::GetKey(S256KeyType id, u64 field1, u64 field2) const { | 741 | Key256 KeyManager::GetKey(S256KeyType id, u64 field1, u64 field2) const { |
| 648 | if (!HasKey(id, field1, field2)) | 742 | if (!HasKey(id, field1, field2)) { |
| 649 | return {}; | 743 | return {}; |
| 744 | } | ||
| 650 | return s256_keys.at({id, field1, field2}); | 745 | return s256_keys.at({id, field1, field2}); |
| 651 | } | 746 | } |
| 652 | 747 | ||
| @@ -668,7 +763,7 @@ Key256 KeyManager::GetBISKey(u8 partition_id) const { | |||
| 668 | template <size_t Size> | 763 | template <size_t Size> |
| 669 | void KeyManager::WriteKeyToFile(KeyCategory category, std::string_view keyname, | 764 | void KeyManager::WriteKeyToFile(KeyCategory category, std::string_view keyname, |
| 670 | const std::array<u8, Size>& key) { | 765 | const std::array<u8, Size>& key) { |
| 671 | const std::string yuzu_keys_dir = FileUtil::GetUserPath(FileUtil::UserPath::KeysDir); | 766 | const std::string yuzu_keys_dir = Common::FS::GetUserPath(Common::FS::UserPath::KeysDir); |
| 672 | std::string filename = "title.keys_autogenerated"; | 767 | std::string filename = "title.keys_autogenerated"; |
| 673 | if (category == KeyCategory::Standard) { | 768 | if (category == KeyCategory::Standard) { |
| 674 | filename = dev_mode ? "dev.keys_autogenerated" : "prod.keys_autogenerated"; | 769 | filename = dev_mode ? "dev.keys_autogenerated" : "prod.keys_autogenerated"; |
| @@ -677,9 +772,9 @@ void KeyManager::WriteKeyToFile(KeyCategory category, std::string_view keyname, | |||
| 677 | } | 772 | } |
| 678 | 773 | ||
| 679 | const auto path = yuzu_keys_dir + DIR_SEP + filename; | 774 | const auto path = yuzu_keys_dir + DIR_SEP + filename; |
| 680 | const auto add_info_text = !FileUtil::Exists(path); | 775 | const auto add_info_text = !Common::FS::Exists(path); |
| 681 | FileUtil::CreateFullPath(path); | 776 | Common::FS::CreateFullPath(path); |
| 682 | FileUtil::IOFile file{path, "a"}; | 777 | Common::FS::IOFile file{path, "a"}; |
| 683 | if (!file.IsOpen()) { | 778 | if (!file.IsOpen()) { |
| 684 | return; | 779 | return; |
| 685 | } | 780 | } |
| @@ -712,8 +807,7 @@ void KeyManager::SetKey(S128KeyType id, Key128 key, u64 field1, u64 field2) { | |||
| 712 | } | 807 | } |
| 713 | 808 | ||
| 714 | const auto iter2 = std::find_if( | 809 | const auto iter2 = std::find_if( |
| 715 | s128_file_id.begin(), s128_file_id.end(), | 810 | s128_file_id.begin(), s128_file_id.end(), [&id, &field1, &field2](const auto& elem) { |
| 716 | [&id, &field1, &field2](const std::pair<std::string, KeyIndex<S128KeyType>> elem) { | ||
| 717 | return std::tie(elem.second.type, elem.second.field1, elem.second.field2) == | 811 | return std::tie(elem.second.type, elem.second.field1, elem.second.field2) == |
| 718 | std::tie(id, field1, field2); | 812 | std::tie(id, field1, field2); |
| 719 | }); | 813 | }); |
| @@ -723,9 +817,11 @@ void KeyManager::SetKey(S128KeyType id, Key128 key, u64 field1, u64 field2) { | |||
| 723 | 817 | ||
| 724 | // Variable cases | 818 | // Variable cases |
| 725 | if (id == S128KeyType::KeyArea) { | 819 | if (id == S128KeyType::KeyArea) { |
| 726 | static constexpr std::array<const char*, 3> kak_names = {"key_area_key_application_{:02X}", | 820 | static constexpr std::array<const char*, 3> kak_names = { |
| 727 | "key_area_key_ocean_{:02X}", | 821 | "key_area_key_application_{:02X}", |
| 728 | "key_area_key_system_{:02X}"}; | 822 | "key_area_key_ocean_{:02X}", |
| 823 | "key_area_key_system_{:02X}", | ||
| 824 | }; | ||
| 729 | WriteKeyToFile(category, fmt::format(kak_names.at(field2), field1), key); | 825 | WriteKeyToFile(category, fmt::format(kak_names.at(field2), field1), key); |
| 730 | } else if (id == S128KeyType::Master) { | 826 | } else if (id == S128KeyType::Master) { |
| 731 | WriteKeyToFile(category, fmt::format("master_key_{:02X}", field1), key); | 827 | WriteKeyToFile(category, fmt::format("master_key_{:02X}", field1), key); |
| @@ -751,8 +847,7 @@ void KeyManager::SetKey(S256KeyType id, Key256 key, u64 field1, u64 field2) { | |||
| 751 | return; | 847 | return; |
| 752 | } | 848 | } |
| 753 | const auto iter = std::find_if( | 849 | const auto iter = std::find_if( |
| 754 | s256_file_id.begin(), s256_file_id.end(), | 850 | s256_file_id.begin(), s256_file_id.end(), [&id, &field1, &field2](const auto& elem) { |
| 755 | [&id, &field1, &field2](const std::pair<std::string, KeyIndex<S256KeyType>> elem) { | ||
| 756 | return std::tie(elem.second.type, elem.second.field1, elem.second.field2) == | 851 | return std::tie(elem.second.type, elem.second.field1, elem.second.field2) == |
| 757 | std::tie(id, field1, field2); | 852 | std::tie(id, field1, field2); |
| 758 | }); | 853 | }); |
| @@ -763,29 +858,31 @@ void KeyManager::SetKey(S256KeyType id, Key256 key, u64 field1, u64 field2) { | |||
| 763 | } | 858 | } |
| 764 | 859 | ||
| 765 | bool KeyManager::KeyFileExists(bool title) { | 860 | bool KeyManager::KeyFileExists(bool title) { |
| 766 | const std::string hactool_keys_dir = FileUtil::GetHactoolConfigurationPath(); | 861 | const std::string hactool_keys_dir = Common::FS::GetHactoolConfigurationPath(); |
| 767 | const std::string yuzu_keys_dir = FileUtil::GetUserPath(FileUtil::UserPath::KeysDir); | 862 | const std::string yuzu_keys_dir = Common::FS::GetUserPath(Common::FS::UserPath::KeysDir); |
| 768 | if (title) { | 863 | if (title) { |
| 769 | return FileUtil::Exists(hactool_keys_dir + DIR_SEP + "title.keys") || | 864 | return Common::FS::Exists(hactool_keys_dir + DIR_SEP + "title.keys") || |
| 770 | FileUtil::Exists(yuzu_keys_dir + DIR_SEP + "title.keys"); | 865 | Common::FS::Exists(yuzu_keys_dir + DIR_SEP + "title.keys"); |
| 771 | } | 866 | } |
| 772 | 867 | ||
| 773 | if (Settings::values.use_dev_keys) { | 868 | if (Settings::values.use_dev_keys) { |
| 774 | return FileUtil::Exists(hactool_keys_dir + DIR_SEP + "dev.keys") || | 869 | return Common::FS::Exists(hactool_keys_dir + DIR_SEP + "dev.keys") || |
| 775 | FileUtil::Exists(yuzu_keys_dir + DIR_SEP + "dev.keys"); | 870 | Common::FS::Exists(yuzu_keys_dir + DIR_SEP + "dev.keys"); |
| 776 | } | 871 | } |
| 777 | 872 | ||
| 778 | return FileUtil::Exists(hactool_keys_dir + DIR_SEP + "prod.keys") || | 873 | return Common::FS::Exists(hactool_keys_dir + DIR_SEP + "prod.keys") || |
| 779 | FileUtil::Exists(yuzu_keys_dir + DIR_SEP + "prod.keys"); | 874 | Common::FS::Exists(yuzu_keys_dir + DIR_SEP + "prod.keys"); |
| 780 | } | 875 | } |
| 781 | 876 | ||
| 782 | void KeyManager::DeriveSDSeedLazy() { | 877 | void KeyManager::DeriveSDSeedLazy() { |
| 783 | if (HasKey(S128KeyType::SDSeed)) | 878 | if (HasKey(S128KeyType::SDSeed)) { |
| 784 | return; | 879 | return; |
| 880 | } | ||
| 785 | 881 | ||
| 786 | const auto res = DeriveSDSeed(); | 882 | const auto res = DeriveSDSeed(); |
| 787 | if (res) | 883 | if (res) { |
| 788 | SetKey(S128KeyType::SDSeed, *res); | 884 | SetKey(S128KeyType::SDSeed, *res); |
| 885 | } | ||
| 789 | } | 886 | } |
| 790 | 887 | ||
| 791 | static Key128 CalculateCMAC(const u8* source, size_t size, const Key128& key) { | 888 | static Key128 CalculateCMAC(const u8* source, size_t size, const Key128& key) { |
| @@ -797,11 +894,13 @@ static Key128 CalculateCMAC(const u8* source, size_t size, const Key128& key) { | |||
| 797 | } | 894 | } |
| 798 | 895 | ||
| 799 | void KeyManager::DeriveBase() { | 896 | void KeyManager::DeriveBase() { |
| 800 | if (!BaseDeriveNecessary()) | 897 | if (!BaseDeriveNecessary()) { |
| 801 | return; | 898 | return; |
| 899 | } | ||
| 802 | 900 | ||
| 803 | if (!HasKey(S128KeyType::SecureBoot) || !HasKey(S128KeyType::TSEC)) | 901 | if (!HasKey(S128KeyType::SecureBoot) || !HasKey(S128KeyType::TSEC)) { |
| 804 | return; | 902 | return; |
| 903 | } | ||
| 805 | 904 | ||
| 806 | const auto has_bis = [this](u64 id) { | 905 | const auto has_bis = [this](u64 id) { |
| 807 | return HasKey(S128KeyType::BIS, id, static_cast<u64>(BISKeyType::Crypto)) && | 906 | return HasKey(S128KeyType::BIS, id, static_cast<u64>(BISKeyType::Crypto)) && |
| @@ -818,10 +917,11 @@ void KeyManager::DeriveBase() { | |||
| 818 | static_cast<u64>(BISKeyType::Tweak)); | 917 | static_cast<u64>(BISKeyType::Tweak)); |
| 819 | }; | 918 | }; |
| 820 | 919 | ||
| 821 | if (has_bis(2) && !has_bis(3)) | 920 | if (has_bis(2) && !has_bis(3)) { |
| 822 | copy_bis(2, 3); | 921 | copy_bis(2, 3); |
| 823 | else if (has_bis(3) && !has_bis(2)) | 922 | } else if (has_bis(3) && !has_bis(2)) { |
| 824 | copy_bis(3, 2); | 923 | copy_bis(3, 2); |
| 924 | } | ||
| 825 | 925 | ||
| 826 | std::bitset<32> revisions(0xFFFFFFFF); | 926 | std::bitset<32> revisions(0xFFFFFFFF); |
| 827 | for (size_t i = 0; i < revisions.size(); ++i) { | 927 | for (size_t i = 0; i < revisions.size(); ++i) { |
| @@ -831,15 +931,17 @@ void KeyManager::DeriveBase() { | |||
| 831 | } | 931 | } |
| 832 | } | 932 | } |
| 833 | 933 | ||
| 834 | if (!revisions.any()) | 934 | if (!revisions.any()) { |
| 835 | return; | 935 | return; |
| 936 | } | ||
| 836 | 937 | ||
| 837 | const auto sbk = GetKey(S128KeyType::SecureBoot); | 938 | const auto sbk = GetKey(S128KeyType::SecureBoot); |
| 838 | const auto tsec = GetKey(S128KeyType::TSEC); | 939 | const auto tsec = GetKey(S128KeyType::TSEC); |
| 839 | 940 | ||
| 840 | for (size_t i = 0; i < revisions.size(); ++i) { | 941 | for (size_t i = 0; i < revisions.size(); ++i) { |
| 841 | if (!revisions[i]) | 942 | if (!revisions[i]) { |
| 842 | continue; | 943 | continue; |
| 944 | } | ||
| 843 | 945 | ||
| 844 | // Derive keyblob key | 946 | // Derive keyblob key |
| 845 | const auto key = DeriveKeyblobKey( | 947 | const auto key = DeriveKeyblobKey( |
| @@ -848,16 +950,18 @@ void KeyManager::DeriveBase() { | |||
| 848 | SetKey(S128KeyType::Keyblob, key, i); | 950 | SetKey(S128KeyType::Keyblob, key, i); |
| 849 | 951 | ||
| 850 | // Derive keyblob MAC key | 952 | // Derive keyblob MAC key |
| 851 | if (!HasKey(S128KeyType::Source, static_cast<u64>(SourceKeyType::KeyblobMAC))) | 953 | if (!HasKey(S128KeyType::Source, static_cast<u64>(SourceKeyType::KeyblobMAC))) { |
| 852 | continue; | 954 | continue; |
| 955 | } | ||
| 853 | 956 | ||
| 854 | const auto mac_key = DeriveKeyblobMACKey( | 957 | const auto mac_key = DeriveKeyblobMACKey( |
| 855 | key, GetKey(S128KeyType::Source, static_cast<u64>(SourceKeyType::KeyblobMAC))); | 958 | key, GetKey(S128KeyType::Source, static_cast<u64>(SourceKeyType::KeyblobMAC))); |
| 856 | SetKey(S128KeyType::KeyblobMAC, mac_key, i); | 959 | SetKey(S128KeyType::KeyblobMAC, mac_key, i); |
| 857 | 960 | ||
| 858 | Key128 cmac = CalculateCMAC(encrypted_keyblobs[i].data() + 0x10, 0xA0, mac_key); | 961 | Key128 cmac = CalculateCMAC(encrypted_keyblobs[i].data() + 0x10, 0xA0, mac_key); |
| 859 | if (std::memcmp(cmac.data(), encrypted_keyblobs[i].data(), cmac.size()) != 0) | 962 | if (std::memcmp(cmac.data(), encrypted_keyblobs[i].data(), cmac.size()) != 0) { |
| 860 | continue; | 963 | continue; |
| 964 | } | ||
| 861 | 965 | ||
| 862 | // Decrypt keyblob | 966 | // Decrypt keyblob |
| 863 | if (keyblobs[i] == std::array<u8, 0x90>{}) { | 967 | if (keyblobs[i] == std::array<u8, 0x90>{}) { |
| @@ -881,16 +985,19 @@ void KeyManager::DeriveBase() { | |||
| 881 | 985 | ||
| 882 | revisions.set(); | 986 | revisions.set(); |
| 883 | for (size_t i = 0; i < revisions.size(); ++i) { | 987 | for (size_t i = 0; i < revisions.size(); ++i) { |
| 884 | if (!HasKey(S128KeyType::Master, i)) | 988 | if (!HasKey(S128KeyType::Master, i)) { |
| 885 | revisions.reset(i); | 989 | revisions.reset(i); |
| 990 | } | ||
| 886 | } | 991 | } |
| 887 | 992 | ||
| 888 | if (!revisions.any()) | 993 | if (!revisions.any()) { |
| 889 | return; | 994 | return; |
| 995 | } | ||
| 890 | 996 | ||
| 891 | for (size_t i = 0; i < revisions.size(); ++i) { | 997 | for (size_t i = 0; i < revisions.size(); ++i) { |
| 892 | if (!revisions[i]) | 998 | if (!revisions[i]) { |
| 893 | continue; | 999 | continue; |
| 1000 | } | ||
| 894 | 1001 | ||
| 895 | // Derive general purpose keys | 1002 | // Derive general purpose keys |
| 896 | DeriveGeneralPurposeKeys(i); | 1003 | DeriveGeneralPurposeKeys(i); |
| @@ -920,16 +1027,19 @@ void KeyManager::DeriveETicket(PartitionDataManager& data) { | |||
| 920 | const auto es = Core::System::GetInstance().GetContentProvider().GetEntry( | 1027 | const auto es = Core::System::GetInstance().GetContentProvider().GetEntry( |
| 921 | 0x0100000000000033, FileSys::ContentRecordType::Program); | 1028 | 0x0100000000000033, FileSys::ContentRecordType::Program); |
| 922 | 1029 | ||
| 923 | if (es == nullptr) | 1030 | if (es == nullptr) { |
| 924 | return; | 1031 | return; |
| 1032 | } | ||
| 925 | 1033 | ||
| 926 | const auto exefs = es->GetExeFS(); | 1034 | const auto exefs = es->GetExeFS(); |
| 927 | if (exefs == nullptr) | 1035 | if (exefs == nullptr) { |
| 928 | return; | 1036 | return; |
| 1037 | } | ||
| 929 | 1038 | ||
| 930 | const auto main = exefs->GetFile("main"); | 1039 | const auto main = exefs->GetFile("main"); |
| 931 | if (main == nullptr) | 1040 | if (main == nullptr) { |
| 932 | return; | 1041 | return; |
| 1042 | } | ||
| 933 | 1043 | ||
| 934 | const auto bytes = main->ReadAllBytes(); | 1044 | const auto bytes = main->ReadAllBytes(); |
| 935 | 1045 | ||
| @@ -939,16 +1049,19 @@ void KeyManager::DeriveETicket(PartitionDataManager& data) { | |||
| 939 | const auto seed3 = data.GetRSAKekSeed3(); | 1049 | const auto seed3 = data.GetRSAKekSeed3(); |
| 940 | const auto mask0 = data.GetRSAKekMask0(); | 1050 | const auto mask0 = data.GetRSAKekMask0(); |
| 941 | 1051 | ||
| 942 | if (eticket_kek != Key128{}) | 1052 | if (eticket_kek != Key128{}) { |
| 943 | SetKey(S128KeyType::Source, eticket_kek, static_cast<size_t>(SourceKeyType::ETicketKek)); | 1053 | SetKey(S128KeyType::Source, eticket_kek, static_cast<size_t>(SourceKeyType::ETicketKek)); |
| 1054 | } | ||
| 944 | if (eticket_kekek != Key128{}) { | 1055 | if (eticket_kekek != Key128{}) { |
| 945 | SetKey(S128KeyType::Source, eticket_kekek, | 1056 | SetKey(S128KeyType::Source, eticket_kekek, |
| 946 | static_cast<size_t>(SourceKeyType::ETicketKekek)); | 1057 | static_cast<size_t>(SourceKeyType::ETicketKekek)); |
| 947 | } | 1058 | } |
| 948 | if (seed3 != Key128{}) | 1059 | if (seed3 != Key128{}) { |
| 949 | SetKey(S128KeyType::RSAKek, seed3, static_cast<size_t>(RSAKekType::Seed3)); | 1060 | SetKey(S128KeyType::RSAKek, seed3, static_cast<size_t>(RSAKekType::Seed3)); |
| 950 | if (mask0 != Key128{}) | 1061 | } |
| 1062 | if (mask0 != Key128{}) { | ||
| 951 | SetKey(S128KeyType::RSAKek, mask0, static_cast<size_t>(RSAKekType::Mask0)); | 1063 | SetKey(S128KeyType::RSAKek, mask0, static_cast<size_t>(RSAKekType::Mask0)); |
| 1064 | } | ||
| 952 | if (eticket_kek == Key128{} || eticket_kekek == Key128{} || seed3 == Key128{} || | 1065 | if (eticket_kek == Key128{} || eticket_kekek == Key128{} || seed3 == Key128{} || |
| 953 | mask0 == Key128{}) { | 1066 | mask0 == Key128{}) { |
| 954 | return; | 1067 | return; |
| @@ -974,8 +1087,9 @@ void KeyManager::DeriveETicket(PartitionDataManager& data) { | |||
| 974 | AESCipher<Key128> es_kek(temp_kekek, Mode::ECB); | 1087 | AESCipher<Key128> es_kek(temp_kekek, Mode::ECB); |
| 975 | es_kek.Transcode(eticket_kek.data(), eticket_kek.size(), eticket_final.data(), Op::Decrypt); | 1088 | es_kek.Transcode(eticket_kek.data(), eticket_kek.size(), eticket_final.data(), Op::Decrypt); |
| 976 | 1089 | ||
| 977 | if (eticket_final == Key128{}) | 1090 | if (eticket_final == Key128{}) { |
| 978 | return; | 1091 | return; |
| 1092 | } | ||
| 979 | 1093 | ||
| 980 | SetKey(S128KeyType::ETicketRSAKek, eticket_final); | 1094 | SetKey(S128KeyType::ETicketRSAKek, eticket_final); |
| 981 | 1095 | ||
| @@ -990,18 +1104,20 @@ void KeyManager::DeriveETicket(PartitionDataManager& data) { | |||
| 990 | void KeyManager::PopulateTickets() { | 1104 | void KeyManager::PopulateTickets() { |
| 991 | const auto rsa_key = GetETicketRSAKey(); | 1105 | const auto rsa_key = GetETicketRSAKey(); |
| 992 | 1106 | ||
| 993 | if (rsa_key == RSAKeyPair<2048>{}) | 1107 | if (rsa_key == RSAKeyPair<2048>{}) { |
| 994 | return; | 1108 | return; |
| 1109 | } | ||
| 995 | 1110 | ||
| 996 | if (!common_tickets.empty() && !personal_tickets.empty()) | 1111 | if (!common_tickets.empty() && !personal_tickets.empty()) { |
| 997 | return; | 1112 | return; |
| 1113 | } | ||
| 998 | 1114 | ||
| 999 | const FileUtil::IOFile save1(FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) + | 1115 | const Common::FS::IOFile save1(Common::FS::GetUserPath(Common::FS::UserPath::NANDDir) + |
| 1000 | "/system/save/80000000000000e1", | 1116 | "/system/save/80000000000000e1", |
| 1001 | "rb+"); | 1117 | "rb+"); |
| 1002 | const FileUtil::IOFile save2(FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) + | 1118 | const Common::FS::IOFile save2(Common::FS::GetUserPath(Common::FS::UserPath::NANDDir) + |
| 1003 | "/system/save/80000000000000e2", | 1119 | "/system/save/80000000000000e2", |
| 1004 | "rb+"); | 1120 | "rb+"); |
| 1005 | 1121 | ||
| 1006 | const auto blob2 = GetTicketblob(save2); | 1122 | const auto blob2 = GetTicketblob(save2); |
| 1007 | auto res = GetTicketblob(save1); | 1123 | auto res = GetTicketblob(save1); |
| @@ -1011,8 +1127,10 @@ void KeyManager::PopulateTickets() { | |||
| 1011 | for (std::size_t i = 0; i < res.size(); ++i) { | 1127 | for (std::size_t i = 0; i < res.size(); ++i) { |
| 1012 | const auto common = i < idx; | 1128 | const auto common = i < idx; |
| 1013 | const auto pair = ParseTicket(res[i], rsa_key); | 1129 | const auto pair = ParseTicket(res[i], rsa_key); |
| 1014 | if (!pair) | 1130 | if (!pair) { |
| 1015 | continue; | 1131 | continue; |
| 1132 | } | ||
| 1133 | |||
| 1016 | const auto& [rid, key] = *pair; | 1134 | const auto& [rid, key] = *pair; |
| 1017 | u128 rights_id; | 1135 | u128 rights_id; |
| 1018 | std::memcpy(rights_id.data(), rid.data(), rid.size()); | 1136 | std::memcpy(rights_id.data(), rid.data(), rid.size()); |
| @@ -1041,27 +1159,33 @@ void KeyManager::SynthesizeTickets() { | |||
| 1041 | } | 1159 | } |
| 1042 | 1160 | ||
| 1043 | void KeyManager::SetKeyWrapped(S128KeyType id, Key128 key, u64 field1, u64 field2) { | 1161 | void KeyManager::SetKeyWrapped(S128KeyType id, Key128 key, u64 field1, u64 field2) { |
| 1044 | if (key == Key128{}) | 1162 | if (key == Key128{}) { |
| 1045 | return; | 1163 | return; |
| 1164 | } | ||
| 1046 | SetKey(id, key, field1, field2); | 1165 | SetKey(id, key, field1, field2); |
| 1047 | } | 1166 | } |
| 1048 | 1167 | ||
| 1049 | void KeyManager::SetKeyWrapped(S256KeyType id, Key256 key, u64 field1, u64 field2) { | 1168 | void KeyManager::SetKeyWrapped(S256KeyType id, Key256 key, u64 field1, u64 field2) { |
| 1050 | if (key == Key256{}) | 1169 | if (key == Key256{}) { |
| 1051 | return; | 1170 | return; |
| 1171 | } | ||
| 1172 | |||
| 1052 | SetKey(id, key, field1, field2); | 1173 | SetKey(id, key, field1, field2); |
| 1053 | } | 1174 | } |
| 1054 | 1175 | ||
| 1055 | void KeyManager::PopulateFromPartitionData(PartitionDataManager& data) { | 1176 | void KeyManager::PopulateFromPartitionData(PartitionDataManager& data) { |
| 1056 | if (!BaseDeriveNecessary()) | 1177 | if (!BaseDeriveNecessary()) { |
| 1057 | return; | 1178 | return; |
| 1179 | } | ||
| 1058 | 1180 | ||
| 1059 | if (!data.HasBoot0()) | 1181 | if (!data.HasBoot0()) { |
| 1060 | return; | 1182 | return; |
| 1183 | } | ||
| 1061 | 1184 | ||
| 1062 | for (size_t i = 0; i < encrypted_keyblobs.size(); ++i) { | 1185 | for (size_t i = 0; i < encrypted_keyblobs.size(); ++i) { |
| 1063 | if (encrypted_keyblobs[i] != std::array<u8, 0xB0>{}) | 1186 | if (encrypted_keyblobs[i] != std::array<u8, 0xB0>{}) { |
| 1064 | continue; | 1187 | continue; |
| 1188 | } | ||
| 1065 | encrypted_keyblobs[i] = data.GetEncryptedKeyblob(i); | 1189 | encrypted_keyblobs[i] = data.GetEncryptedKeyblob(i); |
| 1066 | WriteKeyToFile<0xB0>(KeyCategory::Console, fmt::format("encrypted_keyblob_{:02X}", i), | 1190 | WriteKeyToFile<0xB0>(KeyCategory::Console, fmt::format("encrypted_keyblob_{:02X}", i), |
| 1067 | encrypted_keyblobs[i]); | 1191 | encrypted_keyblobs[i]); |
| @@ -1083,8 +1207,9 @@ void KeyManager::PopulateFromPartitionData(PartitionDataManager& data) { | |||
| 1083 | static_cast<u64>(SourceKeyType::Keyblob), i); | 1207 | static_cast<u64>(SourceKeyType::Keyblob), i); |
| 1084 | } | 1208 | } |
| 1085 | 1209 | ||
| 1086 | if (data.HasFuses()) | 1210 | if (data.HasFuses()) { |
| 1087 | SetKeyWrapped(S128KeyType::SecureBoot, data.GetSecureBootKey()); | 1211 | SetKeyWrapped(S128KeyType::SecureBoot, data.GetSecureBootKey()); |
| 1212 | } | ||
| 1088 | 1213 | ||
| 1089 | DeriveBase(); | 1214 | DeriveBase(); |
| 1090 | 1215 | ||
| @@ -1098,8 +1223,9 @@ void KeyManager::PopulateFromPartitionData(PartitionDataManager& data) { | |||
| 1098 | 1223 | ||
| 1099 | const auto masters = data.GetTZMasterKeys(latest_master); | 1224 | const auto masters = data.GetTZMasterKeys(latest_master); |
| 1100 | for (size_t i = 0; i < masters.size(); ++i) { | 1225 | for (size_t i = 0; i < masters.size(); ++i) { |
| 1101 | if (masters[i] != Key128{} && !HasKey(S128KeyType::Master, i)) | 1226 | if (masters[i] != Key128{} && !HasKey(S128KeyType::Master, i)) { |
| 1102 | SetKey(S128KeyType::Master, masters[i], i); | 1227 | SetKey(S128KeyType::Master, masters[i], i); |
| 1228 | } | ||
| 1103 | } | 1229 | } |
| 1104 | 1230 | ||
| 1105 | DeriveBase(); | 1231 | DeriveBase(); |
| @@ -1109,8 +1235,9 @@ void KeyManager::PopulateFromPartitionData(PartitionDataManager& data) { | |||
| 1109 | 1235 | ||
| 1110 | std::array<Key128, 0x20> package2_keys{}; | 1236 | std::array<Key128, 0x20> package2_keys{}; |
| 1111 | for (size_t i = 0; i < package2_keys.size(); ++i) { | 1237 | for (size_t i = 0; i < package2_keys.size(); ++i) { |
| 1112 | if (HasKey(S128KeyType::Package2, i)) | 1238 | if (HasKey(S128KeyType::Package2, i)) { |
| 1113 | package2_keys[i] = GetKey(S128KeyType::Package2, i); | 1239 | package2_keys[i] = GetKey(S128KeyType::Package2, i); |
| 1240 | } | ||
| 1114 | } | 1241 | } |
| 1115 | data.DecryptPackage2(package2_keys, Package2Type::NormalMain); | 1242 | data.DecryptPackage2(package2_keys, Package2Type::NormalMain); |
| 1116 | 1243 | ||
| @@ -1148,12 +1275,15 @@ const std::map<u128, Ticket>& KeyManager::GetPersonalizedTickets() const { | |||
| 1148 | 1275 | ||
| 1149 | bool KeyManager::AddTicketCommon(Ticket raw) { | 1276 | bool KeyManager::AddTicketCommon(Ticket raw) { |
| 1150 | const auto rsa_key = GetETicketRSAKey(); | 1277 | const auto rsa_key = GetETicketRSAKey(); |
| 1151 | if (rsa_key == RSAKeyPair<2048>{}) | 1278 | if (rsa_key == RSAKeyPair<2048>{}) { |
| 1152 | return false; | 1279 | return false; |
| 1280 | } | ||
| 1153 | 1281 | ||
| 1154 | const auto pair = ParseTicket(raw, rsa_key); | 1282 | const auto pair = ParseTicket(raw, rsa_key); |
| 1155 | if (!pair) | 1283 | if (!pair) { |
| 1156 | return false; | 1284 | return false; |
| 1285 | } | ||
| 1286 | |||
| 1157 | const auto& [rid, key] = *pair; | 1287 | const auto& [rid, key] = *pair; |
| 1158 | u128 rights_id; | 1288 | u128 rights_id; |
| 1159 | std::memcpy(rights_id.data(), rid.data(), rid.size()); | 1289 | std::memcpy(rights_id.data(), rid.data(), rid.size()); |
| @@ -1164,12 +1294,15 @@ bool KeyManager::AddTicketCommon(Ticket raw) { | |||
| 1164 | 1294 | ||
| 1165 | bool KeyManager::AddTicketPersonalized(Ticket raw) { | 1295 | bool KeyManager::AddTicketPersonalized(Ticket raw) { |
| 1166 | const auto rsa_key = GetETicketRSAKey(); | 1296 | const auto rsa_key = GetETicketRSAKey(); |
| 1167 | if (rsa_key == RSAKeyPair<2048>{}) | 1297 | if (rsa_key == RSAKeyPair<2048>{}) { |
| 1168 | return false; | 1298 | return false; |
| 1299 | } | ||
| 1169 | 1300 | ||
| 1170 | const auto pair = ParseTicket(raw, rsa_key); | 1301 | const auto pair = ParseTicket(raw, rsa_key); |
| 1171 | if (!pair) | 1302 | if (!pair) { |
| 1172 | return false; | 1303 | return false; |
| 1304 | } | ||
| 1305 | |||
| 1173 | const auto& [rid, key] = *pair; | 1306 | const auto& [rid, key] = *pair; |
| 1174 | u128 rights_id; | 1307 | u128 rights_id; |
| 1175 | std::memcpy(rights_id.data(), rid.data(), rid.size()); | 1308 | std::memcpy(rights_id.data(), rid.data(), rid.size()); |
| @@ -1177,58 +1310,4 @@ bool KeyManager::AddTicketPersonalized(Ticket raw) { | |||
| 1177 | SetKey(S128KeyType::Titlekey, key, rights_id[1], rights_id[0]); | 1310 | SetKey(S128KeyType::Titlekey, key, rights_id[1], rights_id[0]); |
| 1178 | return true; | 1311 | return true; |
| 1179 | } | 1312 | } |
| 1180 | |||
| 1181 | const boost::container::flat_map<std::string, KeyIndex<S128KeyType>> KeyManager::s128_file_id = { | ||
| 1182 | {"eticket_rsa_kek", {S128KeyType::ETicketRSAKek, 0, 0}}, | ||
| 1183 | {"eticket_rsa_kek_source", | ||
| 1184 | {S128KeyType::Source, static_cast<u64>(SourceKeyType::ETicketKek), 0}}, | ||
| 1185 | {"eticket_rsa_kekek_source", | ||
| 1186 | {S128KeyType::Source, static_cast<u64>(SourceKeyType::ETicketKekek), 0}}, | ||
| 1187 | {"rsa_kek_mask_0", {S128KeyType::RSAKek, static_cast<u64>(RSAKekType::Mask0), 0}}, | ||
| 1188 | {"rsa_kek_seed_3", {S128KeyType::RSAKek, static_cast<u64>(RSAKekType::Seed3), 0}}, | ||
| 1189 | {"rsa_oaep_kek_generation_source", | ||
| 1190 | {S128KeyType::Source, static_cast<u64>(SourceKeyType::RSAOaepKekGeneration), 0}}, | ||
| 1191 | {"sd_card_kek_source", {S128KeyType::Source, static_cast<u64>(SourceKeyType::SDKek), 0}}, | ||
| 1192 | {"aes_kek_generation_source", | ||
| 1193 | {S128KeyType::Source, static_cast<u64>(SourceKeyType::AESKekGeneration), 0}}, | ||
| 1194 | {"aes_key_generation_source", | ||
| 1195 | {S128KeyType::Source, static_cast<u64>(SourceKeyType::AESKeyGeneration), 0}}, | ||
| 1196 | {"package2_key_source", {S128KeyType::Source, static_cast<u64>(SourceKeyType::Package2), 0}}, | ||
| 1197 | {"master_key_source", {S128KeyType::Source, static_cast<u64>(SourceKeyType::Master), 0}}, | ||
| 1198 | {"header_kek_source", {S128KeyType::Source, static_cast<u64>(SourceKeyType::HeaderKek), 0}}, | ||
| 1199 | {"key_area_key_application_source", | ||
| 1200 | {S128KeyType::Source, static_cast<u64>(SourceKeyType::KeyAreaKey), | ||
| 1201 | static_cast<u64>(KeyAreaKeyType::Application)}}, | ||
| 1202 | {"key_area_key_ocean_source", | ||
| 1203 | {S128KeyType::Source, static_cast<u64>(SourceKeyType::KeyAreaKey), | ||
| 1204 | static_cast<u64>(KeyAreaKeyType::Ocean)}}, | ||
| 1205 | {"key_area_key_system_source", | ||
| 1206 | {S128KeyType::Source, static_cast<u64>(SourceKeyType::KeyAreaKey), | ||
| 1207 | static_cast<u64>(KeyAreaKeyType::System)}}, | ||
| 1208 | {"titlekek_source", {S128KeyType::Source, static_cast<u64>(SourceKeyType::Titlekek), 0}}, | ||
| 1209 | {"keyblob_mac_key_source", | ||
| 1210 | {S128KeyType::Source, static_cast<u64>(SourceKeyType::KeyblobMAC), 0}}, | ||
| 1211 | {"tsec_key", {S128KeyType::TSEC, 0, 0}}, | ||
| 1212 | {"secure_boot_key", {S128KeyType::SecureBoot, 0, 0}}, | ||
| 1213 | {"sd_seed", {S128KeyType::SDSeed, 0, 0}}, | ||
| 1214 | {"bis_key_0_crypt", {S128KeyType::BIS, 0, static_cast<u64>(BISKeyType::Crypto)}}, | ||
| 1215 | {"bis_key_0_tweak", {S128KeyType::BIS, 0, static_cast<u64>(BISKeyType::Tweak)}}, | ||
| 1216 | {"bis_key_1_crypt", {S128KeyType::BIS, 1, static_cast<u64>(BISKeyType::Crypto)}}, | ||
| 1217 | {"bis_key_1_tweak", {S128KeyType::BIS, 1, static_cast<u64>(BISKeyType::Tweak)}}, | ||
| 1218 | {"bis_key_2_crypt", {S128KeyType::BIS, 2, static_cast<u64>(BISKeyType::Crypto)}}, | ||
| 1219 | {"bis_key_2_tweak", {S128KeyType::BIS, 2, static_cast<u64>(BISKeyType::Tweak)}}, | ||
| 1220 | {"bis_key_3_crypt", {S128KeyType::BIS, 3, static_cast<u64>(BISKeyType::Crypto)}}, | ||
| 1221 | {"bis_key_3_tweak", {S128KeyType::BIS, 3, static_cast<u64>(BISKeyType::Tweak)}}, | ||
| 1222 | {"header_kek", {S128KeyType::HeaderKek, 0, 0}}, | ||
| 1223 | {"sd_card_kek", {S128KeyType::SDKek, 0, 0}}, | ||
| 1224 | }; | ||
| 1225 | |||
| 1226 | const boost::container::flat_map<std::string, KeyIndex<S256KeyType>> KeyManager::s256_file_id = { | ||
| 1227 | {"header_key", {S256KeyType::Header, 0, 0}}, | ||
| 1228 | {"sd_card_save_key_source", {S256KeyType::SDKeySource, static_cast<u64>(SDKeyType::Save), 0}}, | ||
| 1229 | {"sd_card_nca_key_source", {S256KeyType::SDKeySource, static_cast<u64>(SDKeyType::NCA), 0}}, | ||
| 1230 | {"header_key_source", {S256KeyType::HeaderSource, 0, 0}}, | ||
| 1231 | {"sd_card_save_key", {S256KeyType::SDKey, static_cast<u64>(SDKeyType::Save), 0}}, | ||
| 1232 | {"sd_card_nca_key", {S256KeyType::SDKey, static_cast<u64>(SDKeyType::NCA), 0}}, | ||
| 1233 | }; | ||
| 1234 | } // namespace Core::Crypto | 1313 | } // namespace Core::Crypto |
diff --git a/src/core/crypto/key_manager.h b/src/core/crypto/key_manager.h index 9269a73f2..321b75323 100644 --- a/src/core/crypto/key_manager.h +++ b/src/core/crypto/key_manager.h | |||
| @@ -10,14 +10,13 @@ | |||
| 10 | #include <string> | 10 | #include <string> |
| 11 | 11 | ||
| 12 | #include <variant> | 12 | #include <variant> |
| 13 | #include <boost/container/flat_map.hpp> | ||
| 14 | #include <fmt/format.h> | 13 | #include <fmt/format.h> |
| 15 | #include "common/common_funcs.h" | 14 | #include "common/common_funcs.h" |
| 16 | #include "common/common_types.h" | 15 | #include "common/common_types.h" |
| 17 | #include "core/crypto/partition_data_manager.h" | 16 | #include "core/crypto/partition_data_manager.h" |
| 18 | #include "core/file_sys/vfs_types.h" | 17 | #include "core/file_sys/vfs_types.h" |
| 19 | 18 | ||
| 20 | namespace FileUtil { | 19 | namespace Common::FS { |
| 21 | class IOFile; | 20 | class IOFile; |
| 22 | } | 21 | } |
| 23 | 22 | ||
| @@ -293,9 +292,6 @@ private: | |||
| 293 | 292 | ||
| 294 | void SetKeyWrapped(S128KeyType id, Key128 key, u64 field1 = 0, u64 field2 = 0); | 293 | void SetKeyWrapped(S128KeyType id, Key128 key, u64 field1 = 0, u64 field2 = 0); |
| 295 | void SetKeyWrapped(S256KeyType id, Key256 key, u64 field1 = 0, u64 field2 = 0); | 294 | void SetKeyWrapped(S256KeyType id, Key256 key, u64 field1 = 0, u64 field2 = 0); |
| 296 | |||
| 297 | static const boost::container::flat_map<std::string, KeyIndex<S128KeyType>> s128_file_id; | ||
| 298 | static const boost::container::flat_map<std::string, KeyIndex<S256KeyType>> s256_file_id; | ||
| 299 | }; | 295 | }; |
| 300 | 296 | ||
| 301 | Key128 GenerateKeyEncryptionKey(Key128 source, Key128 master, Key128 kek_seed, Key128 key_seed); | 297 | Key128 GenerateKeyEncryptionKey(Key128 source, Key128 master, Key128 kek_seed, Key128 key_seed); |
| @@ -308,7 +304,7 @@ std::array<u8, 0x90> DecryptKeyblob(const std::array<u8, 0xB0>& encrypted_keyblo | |||
| 308 | std::optional<Key128> DeriveSDSeed(); | 304 | std::optional<Key128> DeriveSDSeed(); |
| 309 | Loader::ResultStatus DeriveSDKeys(std::array<Key256, 2>& sd_keys, KeyManager& keys); | 305 | Loader::ResultStatus DeriveSDKeys(std::array<Key256, 2>& sd_keys, KeyManager& keys); |
| 310 | 306 | ||
| 311 | std::vector<Ticket> GetTicketblob(const FileUtil::IOFile& ticket_save); | 307 | std::vector<Ticket> GetTicketblob(const Common::FS::IOFile& ticket_save); |
| 312 | 308 | ||
| 313 | // Returns a pair of {rights_id, titlekey}. Fails if the ticket has no certificate authority | 309 | // Returns a pair of {rights_id, titlekey}. Fails if the ticket has no certificate authority |
| 314 | // (offset 0x140-0x144 is zero) | 310 | // (offset 0x140-0x144 is zero) |
diff --git a/src/core/crypto/partition_data_manager.cpp b/src/core/crypto/partition_data_manager.cpp index b31a81560..46136d04a 100644 --- a/src/core/crypto/partition_data_manager.cpp +++ b/src/core/crypto/partition_data_manager.cpp | |||
| @@ -27,7 +27,7 @@ | |||
| 27 | #include "core/file_sys/vfs_offset.h" | 27 | #include "core/file_sys/vfs_offset.h" |
| 28 | #include "core/file_sys/vfs_vector.h" | 28 | #include "core/file_sys/vfs_vector.h" |
| 29 | 29 | ||
| 30 | using namespace Common; | 30 | using Common::AsArray; |
| 31 | 31 | ||
| 32 | namespace Core::Crypto { | 32 | namespace Core::Crypto { |
| 33 | 33 | ||
| @@ -47,105 +47,123 @@ struct Package2Header { | |||
| 47 | }; | 47 | }; |
| 48 | static_assert(sizeof(Package2Header) == 0x200, "Package2Header has incorrect size."); | 48 | static_assert(sizeof(Package2Header) == 0x200, "Package2Header has incorrect size."); |
| 49 | 49 | ||
| 50 | const std::array<SHA256Hash, 0x10> source_hashes{ | 50 | // clang-format off |
| 51 | "B24BD293259DBC7AC5D63F88E60C59792498E6FC5443402C7FFE87EE8B61A3F0"_array32, // keyblob_mac_key_source | 51 | constexpr std::array source_hashes{ |
| 52 | "7944862A3A5C31C6720595EFD302245ABD1B54CCDCF33000557681E65C5664A4"_array32, // master_key_source | 52 | AsArray("B24BD293259DBC7AC5D63F88E60C59792498E6FC5443402C7FFE87EE8B61A3F0"), // keyblob_mac_key_source |
| 53 | "21E2DF100FC9E094DB51B47B9B1D6E94ED379DB8B547955BEF8FE08D8DD35603"_array32, // package2_key_source | 53 | AsArray("7944862A3A5C31C6720595EFD302245ABD1B54CCDCF33000557681E65C5664A4"), // master_key_source |
| 54 | "FC02B9D37B42D7A1452E71444F1F700311D1132E301A83B16062E72A78175085"_array32, // aes_kek_generation_source | 54 | AsArray("21E2DF100FC9E094DB51B47B9B1D6E94ED379DB8B547955BEF8FE08D8DD35603"), // package2_key_source |
| 55 | "FBD10056999EDC7ACDB96098E47E2C3606230270D23281E671F0F389FC5BC585"_array32, // aes_key_generation_source | 55 | AsArray("FC02B9D37B42D7A1452E71444F1F700311D1132E301A83B16062E72A78175085"), // aes_kek_generation_source |
| 56 | "C48B619827986C7F4E3081D59DB2B460C84312650E9A8E6B458E53E8CBCA4E87"_array32, // titlekek_source | 56 | AsArray("FBD10056999EDC7ACDB96098E47E2C3606230270D23281E671F0F389FC5BC585"), // aes_key_generation_source |
| 57 | "04AD66143C726B2A139FB6B21128B46F56C553B2B3887110304298D8D0092D9E"_array32, // key_area_key_application_source | 57 | AsArray("C48B619827986C7F4E3081D59DB2B460C84312650E9A8E6B458E53E8CBCA4E87"), // titlekek_source |
| 58 | "FD434000C8FF2B26F8E9A9D2D2C12F6BE5773CBB9DC86300E1BD99F8EA33A417"_array32, // key_area_key_ocean_source | 58 | AsArray("04AD66143C726B2A139FB6B21128B46F56C553B2B3887110304298D8D0092D9E"), // key_area_key_application_source |
| 59 | "1F17B1FD51AD1C2379B58F152CA4912EC2106441E51722F38700D5937A1162F7"_array32, // key_area_key_system_source | 59 | AsArray("FD434000C8FF2B26F8E9A9D2D2C12F6BE5773CBB9DC86300E1BD99F8EA33A417"), // key_area_key_ocean_source |
| 60 | "6B2ED877C2C52334AC51E59ABFA7EC457F4A7D01E46291E9F2EAA45F011D24B7"_array32, // sd_card_kek_source | 60 | AsArray("1F17B1FD51AD1C2379B58F152CA4912EC2106441E51722F38700D5937A1162F7"), // key_area_key_system_source |
| 61 | "D482743563D3EA5DCDC3B74E97C9AC8A342164FA041A1DC80F17F6D31E4BC01C"_array32, // sd_card_save_key_source | 61 | AsArray("6B2ED877C2C52334AC51E59ABFA7EC457F4A7D01E46291E9F2EAA45F011D24B7"), // sd_card_kek_source |
| 62 | "2E751CECF7D93A2B957BD5FFCB082FD038CC2853219DD3092C6DAB9838F5A7CC"_array32, // sd_card_nca_key_source | 62 | AsArray("D482743563D3EA5DCDC3B74E97C9AC8A342164FA041A1DC80F17F6D31E4BC01C"), // sd_card_save_key_source |
| 63 | "1888CAED5551B3EDE01499E87CE0D86827F80820EFB275921055AA4E2ABDFFC2"_array32, // header_kek_source | 63 | AsArray("2E751CECF7D93A2B957BD5FFCB082FD038CC2853219DD3092C6DAB9838F5A7CC"), // sd_card_nca_key_source |
| 64 | "8F783E46852DF6BE0BA4E19273C4ADBAEE16380043E1B8C418C4089A8BD64AA6"_array32, // header_key_source | 64 | AsArray("1888CAED5551B3EDE01499E87CE0D86827F80820EFB275921055AA4E2ABDFFC2"), // header_kek_source |
| 65 | "D1757E52F1AE55FA882EC690BC6F954AC46A83DC22F277F8806BD55577C6EED7"_array32, // rsa_kek_seed3 | 65 | AsArray("8F783E46852DF6BE0BA4E19273C4ADBAEE16380043E1B8C418C4089A8BD64AA6"), // header_key_source |
| 66 | "FC02B9D37B42D7A1452E71444F1F700311D1132E301A83B16062E72A78175085"_array32, // rsa_kek_mask0 | 66 | AsArray("D1757E52F1AE55FA882EC690BC6F954AC46A83DC22F277F8806BD55577C6EED7"), // rsa_kek_seed3 |
| 67 | AsArray("FC02B9D37B42D7A1452E71444F1F700311D1132E301A83B16062E72A78175085"), // rsa_kek_mask0 | ||
| 67 | }; | 68 | }; |
| 68 | 69 | // clang-format on | |
| 69 | const std::array<SHA256Hash, 0x20> keyblob_source_hashes{ | 70 | |
| 70 | "8A06FE274AC491436791FDB388BCDD3AB9943BD4DEF8094418CDAC150FD73786"_array32, // keyblob_key_source_00 | 71 | // clang-format off |
| 71 | "2D5CAEB2521FEF70B47E17D6D0F11F8CE2C1E442A979AD8035832C4E9FBCCC4B"_array32, // keyblob_key_source_01 | 72 | constexpr std::array keyblob_source_hashes{ |
| 72 | "61C5005E713BAE780641683AF43E5F5C0E03671117F702F401282847D2FC6064"_array32, // keyblob_key_source_02 | 73 | AsArray("8A06FE274AC491436791FDB388BCDD3AB9943BD4DEF8094418CDAC150FD73786"), // keyblob_key_source_00 |
| 73 | "8E9795928E1C4428E1B78F0BE724D7294D6934689C11B190943923B9D5B85903"_array32, // keyblob_key_source_03 | 74 | AsArray("2D5CAEB2521FEF70B47E17D6D0F11F8CE2C1E442A979AD8035832C4E9FBCCC4B"), // keyblob_key_source_01 |
| 74 | "95FA33AF95AFF9D9B61D164655B32710ED8D615D46C7D6CC3CC70481B686B402"_array32, // keyblob_key_source_04 | 75 | AsArray("61C5005E713BAE780641683AF43E5F5C0E03671117F702F401282847D2FC6064"), // keyblob_key_source_02 |
| 75 | "3F5BE7B3C8B1ABD8C10B4B703D44766BA08730562C172A4FE0D6B866B3E2DB3E"_array32, // keyblob_key_source_05 | 76 | AsArray("8E9795928E1C4428E1B78F0BE724D7294D6934689C11B190943923B9D5B85903"), // keyblob_key_source_03 |
| 76 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_06 | 77 | AsArray("95FA33AF95AFF9D9B61D164655B32710ED8D615D46C7D6CC3CC70481B686B402"), // keyblob_key_source_04 |
| 77 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_07 | 78 | AsArray("3F5BE7B3C8B1ABD8C10B4B703D44766BA08730562C172A4FE0D6B866B3E2DB3E"), // keyblob_key_source_05 |
| 78 | 79 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // keyblob_key_source_06 | |
| 79 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_08 | 80 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // keyblob_key_source_07 |
| 80 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_09 | 81 | |
| 81 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_0A | 82 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // keyblob_key_source_08 |
| 82 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_0B | 83 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // keyblob_key_source_09 |
| 83 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_0C | 84 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // keyblob_key_source_0A |
| 84 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_0D | 85 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // keyblob_key_source_0B |
| 85 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_0E | 86 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // keyblob_key_source_0C |
| 86 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_0F | 87 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // keyblob_key_source_0D |
| 87 | 88 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // keyblob_key_source_0E | |
| 88 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_10 | 89 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // keyblob_key_source_0F |
| 89 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_11 | 90 | |
| 90 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_12 | 91 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // keyblob_key_source_10 |
| 91 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_13 | 92 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // keyblob_key_source_11 |
| 92 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_14 | 93 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // keyblob_key_source_12 |
| 93 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_15 | 94 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // keyblob_key_source_13 |
| 94 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_16 | 95 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // keyblob_key_source_14 |
| 95 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_17 | 96 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // keyblob_key_source_15 |
| 96 | 97 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // keyblob_key_source_16 | |
| 97 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_18 | 98 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // keyblob_key_source_17 |
| 98 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_19 | 99 | |
| 99 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_1A | 100 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // keyblob_key_source_18 |
| 100 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_1B | 101 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // keyblob_key_source_19 |
| 101 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_1C | 102 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // keyblob_key_source_1A |
| 102 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_1D | 103 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // keyblob_key_source_1B |
| 103 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_1E | 104 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // keyblob_key_source_1C |
| 104 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_1F | 105 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // keyblob_key_source_1D |
| 106 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // keyblob_key_source_1E | ||
| 107 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // keyblob_key_source_1F | ||
| 105 | }; | 108 | }; |
| 106 | 109 | // clang-format on | |
| 107 | const std::array<SHA256Hash, 0x20> master_key_hashes{ | 110 | |
| 108 | "0EE359BE3C864BB0782E1D70A718A0342C551EED28C369754F9C4F691BECF7CA"_array32, // master_key_00 | 111 | // clang-format off |
| 109 | "4FE707B7E4ABDAF727C894AAF13B1351BFE2AC90D875F73B2E20FA94B9CC661E"_array32, // master_key_01 | 112 | constexpr std::array master_key_hashes{ |
| 110 | "79277C0237A2252EC3DFAC1F7C359C2B3D121E9DB15BB9AB4C2B4408D2F3AE09"_array32, // master_key_02 | 113 | AsArray("0EE359BE3C864BB0782E1D70A718A0342C551EED28C369754F9C4F691BECF7CA"), // master_key_00 |
| 111 | "4F36C565D13325F65EE134073C6A578FFCB0008E02D69400836844EAB7432754"_array32, // master_key_03 | 114 | AsArray("4FE707B7E4ABDAF727C894AAF13B1351BFE2AC90D875F73B2E20FA94B9CC661E"), // master_key_01 |
| 112 | "75FF1D95D26113550EE6FCC20ACB58E97EDEB3A2FF52543ED5AEC63BDCC3DA50"_array32, // master_key_04 | 115 | AsArray("79277C0237A2252EC3DFAC1F7C359C2B3D121E9DB15BB9AB4C2B4408D2F3AE09"), // master_key_02 |
| 113 | "EBE2BCD6704673EC0F88A187BB2AD9F1CC82B718C389425941BDC194DC46B0DD"_array32, // master_key_05 | 116 | AsArray("4F36C565D13325F65EE134073C6A578FFCB0008E02D69400836844EAB7432754"), // master_key_03 |
| 114 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_06 | 117 | AsArray("75FF1D95D26113550EE6FCC20ACB58E97EDEB3A2FF52543ED5AEC63BDCC3DA50"), // master_key_04 |
| 115 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_07 | 118 | AsArray("EBE2BCD6704673EC0F88A187BB2AD9F1CC82B718C389425941BDC194DC46B0DD"), // master_key_05 |
| 116 | 119 | AsArray("9497E6779F5D840F2BBA1DE4E95BA1D6F21EFC94717D5AE5CA37D7EC5BD37A19"), // master_key_06 | |
| 117 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_08 | 120 | AsArray("4EC96B8CB01B8DCE382149443430B2B6EBCB2983348AFA04A25E53609DABEDF6"), // master_key_07 |
| 118 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_09 | 121 | |
| 119 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_0A | 122 | AsArray("2998E2E23609BC2675FF062A2D64AF5B1B78DFF463B24119D64A1B64F01B2D51"), // master_key_08 |
| 120 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_0B | 123 | AsArray("9D486A98067C44B37CF173D3BF577891EB6081FF6B4A166347D9DBBF7025076B"), // master_key_09 |
| 121 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_0C | 124 | AsArray("4EC5A237A75A083A9C5F6CF615601522A7F822D06BD4BA32612C9CEBBB29BD45"), // master_key_0A |
| 122 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_0D | 125 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // master_key_0B |
| 123 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_0E | 126 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // master_key_0C |
| 124 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_0F | 127 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // master_key_0D |
| 125 | 128 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // master_key_0E | |
| 126 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_10 | 129 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // master_key_0F |
| 127 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_11 | 130 | |
| 128 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_12 | 131 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // master_key_10 |
| 129 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_13 | 132 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // master_key_11 |
| 130 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_14 | 133 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // master_key_12 |
| 131 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_15 | 134 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // master_key_13 |
| 132 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_16 | 135 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // master_key_14 |
| 133 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_17 | 136 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // master_key_15 |
| 134 | 137 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // master_key_16 | |
| 135 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_18 | 138 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // master_key_17 |
| 136 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_19 | 139 | |
| 137 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_1A | 140 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // master_key_18 |
| 138 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_1B | 141 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // master_key_19 |
| 139 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_1C | 142 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // master_key_1A |
| 140 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_1D | 143 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // master_key_1B |
| 141 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_1E | 144 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // master_key_1C |
| 142 | "0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_1F | 145 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // master_key_1D |
| 146 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // master_key_1E | ||
| 147 | AsArray("0000000000000000000000000000000000000000000000000000000000000000"), // master_key_1F | ||
| 143 | }; | 148 | }; |
| 149 | // clang-format on | ||
| 150 | |||
| 151 | static constexpr u8 CalculateMaxKeyblobSourceHash() { | ||
| 152 | const auto is_zero = [](const auto& data) { | ||
| 153 | // TODO: Replace with std::all_of whenever mingw decides to update their | ||
| 154 | // libraries to include the constexpr variant of it. | ||
| 155 | for (const auto element : data) { | ||
| 156 | if (element != 0) { | ||
| 157 | return false; | ||
| 158 | } | ||
| 159 | } | ||
| 160 | return true; | ||
| 161 | }; | ||
| 144 | 162 | ||
| 145 | static u8 CalculateMaxKeyblobSourceHash() { | ||
| 146 | for (s8 i = 0x1F; i >= 0; --i) { | 163 | for (s8 i = 0x1F; i >= 0; --i) { |
| 147 | if (keyblob_source_hashes[i] != SHA256Hash{}) | 164 | if (!is_zero(keyblob_source_hashes[i])) { |
| 148 | return static_cast<u8>(i + 1); | 165 | return static_cast<u8>(i + 1); |
| 166 | } | ||
| 149 | } | 167 | } |
| 150 | 168 | ||
| 151 | return 0; | 169 | return 0; |
| @@ -349,8 +367,8 @@ static bool AttemptDecrypt(const std::array<u8, 16>& key, Package2Header& header | |||
| 349 | Package2Header temp = header; | 367 | Package2Header temp = header; |
| 350 | AESCipher<Key128> cipher(key, Mode::CTR); | 368 | AESCipher<Key128> cipher(key, Mode::CTR); |
| 351 | cipher.SetIV(header.header_ctr); | 369 | cipher.SetIV(header.header_ctr); |
| 352 | cipher.Transcode(&temp.header_ctr, sizeof(Package2Header) - 0x100, &temp.header_ctr, | 370 | cipher.Transcode(&temp.header_ctr, sizeof(Package2Header) - sizeof(Package2Header::signature), |
| 353 | Op::Decrypt); | 371 | &temp.header_ctr, Op::Decrypt); |
| 354 | if (temp.magic == Common::MakeMagic('P', 'K', '2', '1')) { | 372 | if (temp.magic == Common::MakeMagic('P', 'K', '2', '1')) { |
| 355 | header = temp; | 373 | header = temp; |
| 356 | return true; | 374 | return true; |
diff --git a/src/core/file_sys/bis_factory.cpp b/src/core/file_sys/bis_factory.cpp index 285277ef8..9ffda2e14 100644 --- a/src/core/file_sys/bis_factory.cpp +++ b/src/core/file_sys/bis_factory.cpp | |||
| @@ -86,7 +86,7 @@ VirtualFile BISFactory::OpenPartitionStorage(BisPartitionId id) const { | |||
| 86 | auto& keys = Core::Crypto::KeyManager::Instance(); | 86 | auto& keys = Core::Crypto::KeyManager::Instance(); |
| 87 | Core::Crypto::PartitionDataManager pdm{ | 87 | Core::Crypto::PartitionDataManager pdm{ |
| 88 | Core::System::GetInstance().GetFilesystem()->OpenDirectory( | 88 | Core::System::GetInstance().GetFilesystem()->OpenDirectory( |
| 89 | FileUtil::GetUserPath(FileUtil::UserPath::SysDataDir), Mode::Read)}; | 89 | Common::FS::GetUserPath(Common::FS::UserPath::SysDataDir), Mode::Read)}; |
| 90 | keys.PopulateFromPartitionData(pdm); | 90 | keys.PopulateFromPartitionData(pdm); |
| 91 | 91 | ||
| 92 | switch (id) { | 92 | switch (id) { |
diff --git a/src/core/file_sys/registered_cache.cpp b/src/core/file_sys/registered_cache.cpp index f831487dd..da01002d5 100644 --- a/src/core/file_sys/registered_cache.cpp +++ b/src/core/file_sys/registered_cache.cpp | |||
| @@ -257,8 +257,7 @@ std::vector<NcaID> PlaceholderCache::List() const { | |||
| 257 | for (const auto& sdir : dir->GetSubdirectories()) { | 257 | for (const auto& sdir : dir->GetSubdirectories()) { |
| 258 | for (const auto& file : sdir->GetFiles()) { | 258 | for (const auto& file : sdir->GetFiles()) { |
| 259 | const auto name = file->GetName(); | 259 | const auto name = file->GetName(); |
| 260 | if (name.length() == 36 && name[32] == '.' && name[33] == 'n' && name[34] == 'c' && | 260 | if (name.length() == 36 && name.ends_with(".nca")) { |
| 261 | name[35] == 'a') { | ||
| 262 | out.push_back(Common::HexStringToArray<0x10>(name.substr(0, 32))); | 261 | out.push_back(Common::HexStringToArray<0x10>(name.substr(0, 32))); |
| 263 | } | 262 | } |
| 264 | } | 263 | } |
| @@ -621,25 +620,25 @@ InstallResult RegisteredCache::InstallEntry(const NSP& nsp, bool overwrite_if_ex | |||
| 621 | 620 | ||
| 622 | InstallResult RegisteredCache::InstallEntry(const NCA& nca, TitleType type, | 621 | InstallResult RegisteredCache::InstallEntry(const NCA& nca, TitleType type, |
| 623 | bool overwrite_if_exists, const VfsCopyFunction& copy) { | 622 | bool overwrite_if_exists, const VfsCopyFunction& copy) { |
| 624 | CNMTHeader header{ | 623 | const CNMTHeader header{ |
| 625 | nca.GetTitleId(), // Title ID | 624 | .title_id = nca.GetTitleId(), |
| 626 | 0, // Ignore/Default title version | 625 | .title_version = 0, |
| 627 | type, // Type | 626 | .type = type, |
| 628 | {}, // Padding | 627 | .reserved = {}, |
| 629 | 0x10, // Default table offset | 628 | .table_offset = 0x10, |
| 630 | 1, // 1 Content Entry | 629 | .number_content_entries = 1, |
| 631 | 0, // No Meta Entries | 630 | .number_meta_entries = 0, |
| 632 | {}, // Padding | 631 | .attributes = 0, |
| 633 | {}, // Reserved 1 | 632 | .reserved2 = {}, |
| 634 | 0, // Is committed | 633 | .is_committed = 0, |
| 635 | 0, // Required download system version | 634 | .required_download_system_version = 0, |
| 636 | {}, // Reserved 2 | 635 | .reserved3 = {}, |
| 637 | }; | 636 | }; |
| 638 | OptionalHeader opt_header{0, 0}; | 637 | const OptionalHeader opt_header{0, 0}; |
| 639 | ContentRecord c_rec{{}, {}, {}, GetCRTypeFromNCAType(nca.GetType()), {}}; | 638 | ContentRecord c_rec{{}, {}, {}, GetCRTypeFromNCAType(nca.GetType()), {}}; |
| 640 | const auto& data = nca.GetBaseFile()->ReadBytes(0x100000); | 639 | const auto& data = nca.GetBaseFile()->ReadBytes(0x100000); |
| 641 | mbedtls_sha256_ret(data.data(), data.size(), c_rec.hash.data(), 0); | 640 | mbedtls_sha256_ret(data.data(), data.size(), c_rec.hash.data(), 0); |
| 642 | memcpy(&c_rec.nca_id, &c_rec.hash, 16); | 641 | std::memcpy(&c_rec.nca_id, &c_rec.hash, 16); |
| 643 | const CNMT new_cnmt(header, opt_header, {c_rec}, {}); | 642 | const CNMT new_cnmt(header, opt_header, {c_rec}, {}); |
| 644 | if (!RawInstallYuzuMeta(new_cnmt)) { | 643 | if (!RawInstallYuzuMeta(new_cnmt)) { |
| 645 | return InstallResult::ErrorMetaFailed; | 644 | return InstallResult::ErrorMetaFailed; |
| @@ -728,7 +727,7 @@ InstallResult RegisteredCache::RawInstallNCA(const NCA& nca, const VfsCopyFuncti | |||
| 728 | LOG_WARNING(Loader, "Overwriting existing NCA..."); | 727 | LOG_WARNING(Loader, "Overwriting existing NCA..."); |
| 729 | VirtualDir c_dir; | 728 | VirtualDir c_dir; |
| 730 | { c_dir = dir->GetFileRelative(path)->GetContainingDirectory(); } | 729 | { c_dir = dir->GetFileRelative(path)->GetContainingDirectory(); } |
| 731 | c_dir->DeleteFile(FileUtil::GetFilename(path)); | 730 | c_dir->DeleteFile(Common::FS::GetFilename(path)); |
| 732 | } | 731 | } |
| 733 | 732 | ||
| 734 | auto out = dir->CreateFileRelative(path); | 733 | auto out = dir->CreateFileRelative(path); |
diff --git a/src/core/file_sys/registered_cache.h b/src/core/file_sys/registered_cache.h index ec1d54f27..5b414b0f0 100644 --- a/src/core/file_sys/registered_cache.h +++ b/src/core/file_sys/registered_cache.h | |||
| @@ -133,9 +133,9 @@ public: | |||
| 133 | // Parsing function defines the conversion from raw file to NCA. If there are other steps | 133 | // Parsing function defines the conversion from raw file to NCA. If there are other steps |
| 134 | // besides creating the NCA from the file (e.g. NAX0 on SD Card), that should go in a custom | 134 | // besides creating the NCA from the file (e.g. NAX0 on SD Card), that should go in a custom |
| 135 | // parsing function. | 135 | // parsing function. |
| 136 | explicit RegisteredCache(VirtualDir dir, | 136 | explicit RegisteredCache( |
| 137 | ContentProviderParsingFunction parsing_function = | 137 | VirtualDir dir, ContentProviderParsingFunction parsing_function = |
| 138 | [](const VirtualFile& file, const NcaID& id) { return file; }); | 138 | [](const VirtualFile& file, const NcaID& id) { return file; }); |
| 139 | ~RegisteredCache() override; | 139 | ~RegisteredCache() override; |
| 140 | 140 | ||
| 141 | void Refresh() override; | 141 | void Refresh() override; |
diff --git a/src/core/file_sys/system_archive/mii_model.cpp b/src/core/file_sys/system_archive/mii_model.cpp index 61bb67945..d65c7d234 100644 --- a/src/core/file_sys/system_archive/mii_model.cpp +++ b/src/core/file_sys/system_archive/mii_model.cpp | |||
| @@ -27,18 +27,12 @@ VirtualDir MiiModel() { | |||
| 27 | auto out = std::make_shared<VectorVfsDirectory>(std::vector<VirtualFile>{}, | 27 | auto out = std::make_shared<VectorVfsDirectory>(std::vector<VirtualFile>{}, |
| 28 | std::vector<VirtualDir>{}, "data"); | 28 | std::vector<VirtualDir>{}, "data"); |
| 29 | 29 | ||
| 30 | out->AddFile(std::make_shared<ArrayVfsFile<MiiModelData::TEXTURE_LOW_LINEAR.size()>>( | 30 | out->AddFile(MakeArrayFile(MiiModelData::TEXTURE_LOW_LINEAR, "NXTextureLowLinear.dat")); |
| 31 | MiiModelData::TEXTURE_LOW_LINEAR, "NXTextureLowLinear.dat")); | 31 | out->AddFile(MakeArrayFile(MiiModelData::TEXTURE_LOW_SRGB, "NXTextureLowSRGB.dat")); |
| 32 | out->AddFile(std::make_shared<ArrayVfsFile<MiiModelData::TEXTURE_LOW_SRGB.size()>>( | 32 | out->AddFile(MakeArrayFile(MiiModelData::TEXTURE_MID_LINEAR, "NXTextureMidLinear.dat")); |
| 33 | MiiModelData::TEXTURE_LOW_SRGB, "NXTextureLowSRGB.dat")); | 33 | out->AddFile(MakeArrayFile(MiiModelData::TEXTURE_MID_SRGB, "NXTextureMidSRGB.dat")); |
| 34 | out->AddFile(std::make_shared<ArrayVfsFile<MiiModelData::TEXTURE_MID_LINEAR.size()>>( | 34 | out->AddFile(MakeArrayFile(MiiModelData::SHAPE_HIGH, "ShapeHigh.dat")); |
| 35 | MiiModelData::TEXTURE_MID_LINEAR, "NXTextureMidLinear.dat")); | 35 | out->AddFile(MakeArrayFile(MiiModelData::SHAPE_MID, "ShapeMid.dat")); |
| 36 | out->AddFile(std::make_shared<ArrayVfsFile<MiiModelData::TEXTURE_MID_SRGB.size()>>( | ||
| 37 | MiiModelData::TEXTURE_MID_SRGB, "NXTextureMidSRGB.dat")); | ||
| 38 | out->AddFile(std::make_shared<ArrayVfsFile<MiiModelData::SHAPE_HIGH.size()>>( | ||
| 39 | MiiModelData::SHAPE_HIGH, "ShapeHigh.dat")); | ||
| 40 | out->AddFile(std::make_shared<ArrayVfsFile<MiiModelData::SHAPE_MID.size()>>( | ||
| 41 | MiiModelData::SHAPE_MID, "ShapeMid.dat")); | ||
| 42 | 36 | ||
| 43 | return out; | 37 | return out; |
| 44 | } | 38 | } |
diff --git a/src/core/file_sys/system_archive/ng_word.cpp b/src/core/file_sys/system_archive/ng_word.cpp index f4443784d..100d3c5db 100644 --- a/src/core/file_sys/system_archive/ng_word.cpp +++ b/src/core/file_sys/system_archive/ng_word.cpp | |||
| @@ -24,19 +24,18 @@ constexpr std::array<u8, 30> WORD_TXT{ | |||
| 24 | } // namespace NgWord1Data | 24 | } // namespace NgWord1Data |
| 25 | 25 | ||
| 26 | VirtualDir NgWord1() { | 26 | VirtualDir NgWord1() { |
| 27 | std::vector<VirtualFile> files(NgWord1Data::NUMBER_WORD_TXT_FILES); | 27 | std::vector<VirtualFile> files; |
| 28 | files.reserve(NgWord1Data::NUMBER_WORD_TXT_FILES); | ||
| 28 | 29 | ||
| 29 | for (std::size_t i = 0; i < files.size(); ++i) { | 30 | for (std::size_t i = 0; i < files.size(); ++i) { |
| 30 | files[i] = std::make_shared<ArrayVfsFile<NgWord1Data::WORD_TXT.size()>>( | 31 | files.push_back(MakeArrayFile(NgWord1Data::WORD_TXT, fmt::format("{}.txt", i))); |
| 31 | NgWord1Data::WORD_TXT, fmt::format("{}.txt", i)); | ||
| 32 | } | 32 | } |
| 33 | 33 | ||
| 34 | files.push_back(std::make_shared<ArrayVfsFile<NgWord1Data::WORD_TXT.size()>>( | 34 | files.push_back(MakeArrayFile(NgWord1Data::WORD_TXT, "common.txt")); |
| 35 | NgWord1Data::WORD_TXT, "common.txt")); | 35 | files.push_back(MakeArrayFile(NgWord1Data::VERSION_DAT, "version.dat")); |
| 36 | files.push_back(std::make_shared<ArrayVfsFile<NgWord1Data::VERSION_DAT.size()>>( | ||
| 37 | NgWord1Data::VERSION_DAT, "version.dat")); | ||
| 38 | 36 | ||
| 39 | return std::make_shared<VectorVfsDirectory>(files, std::vector<VirtualDir>{}, "data"); | 37 | return std::make_shared<VectorVfsDirectory>(std::move(files), std::vector<VirtualDir>{}, |
| 38 | "data"); | ||
| 40 | } | 39 | } |
| 41 | 40 | ||
| 42 | namespace NgWord2Data { | 41 | namespace NgWord2Data { |
| @@ -55,27 +54,22 @@ constexpr std::array<u8, 0x2C> AC_NX_DATA{ | |||
| 55 | } // namespace NgWord2Data | 54 | } // namespace NgWord2Data |
| 56 | 55 | ||
| 57 | VirtualDir NgWord2() { | 56 | VirtualDir NgWord2() { |
| 58 | std::vector<VirtualFile> files(NgWord2Data::NUMBER_AC_NX_FILES * 3); | 57 | std::vector<VirtualFile> files; |
| 58 | files.reserve(NgWord2Data::NUMBER_AC_NX_FILES * 3); | ||
| 59 | 59 | ||
| 60 | for (std::size_t i = 0; i < NgWord2Data::NUMBER_AC_NX_FILES; ++i) { | 60 | for (std::size_t i = 0; i < NgWord2Data::NUMBER_AC_NX_FILES; ++i) { |
| 61 | files[3 * i] = std::make_shared<ArrayVfsFile<NgWord2Data::AC_NX_DATA.size()>>( | 61 | files.push_back(MakeArrayFile(NgWord2Data::AC_NX_DATA, fmt::format("ac_{}_b1_nx", i))); |
| 62 | NgWord2Data::AC_NX_DATA, fmt::format("ac_{}_b1_nx", i)); | 62 | files.push_back(MakeArrayFile(NgWord2Data::AC_NX_DATA, fmt::format("ac_{}_b2_nx", i))); |
| 63 | files[3 * i + 1] = std::make_shared<ArrayVfsFile<NgWord2Data::AC_NX_DATA.size()>>( | 63 | files.push_back(MakeArrayFile(NgWord2Data::AC_NX_DATA, fmt::format("ac_{}_not_b_nx", i))); |
| 64 | NgWord2Data::AC_NX_DATA, fmt::format("ac_{}_b2_nx", i)); | ||
| 65 | files[3 * i + 2] = std::make_shared<ArrayVfsFile<NgWord2Data::AC_NX_DATA.size()>>( | ||
| 66 | NgWord2Data::AC_NX_DATA, fmt::format("ac_{}_not_b_nx", i)); | ||
| 67 | } | 64 | } |
| 68 | 65 | ||
| 69 | files.push_back(std::make_shared<ArrayVfsFile<NgWord2Data::AC_NX_DATA.size()>>( | 66 | files.push_back(MakeArrayFile(NgWord2Data::AC_NX_DATA, "ac_common_b1_nx")); |
| 70 | NgWord2Data::AC_NX_DATA, "ac_common_b1_nx")); | 67 | files.push_back(MakeArrayFile(NgWord2Data::AC_NX_DATA, "ac_common_b2_nx")); |
| 71 | files.push_back(std::make_shared<ArrayVfsFile<NgWord2Data::AC_NX_DATA.size()>>( | 68 | files.push_back(MakeArrayFile(NgWord2Data::AC_NX_DATA, "ac_common_not_b_nx")); |
| 72 | NgWord2Data::AC_NX_DATA, "ac_common_b2_nx")); | 69 | files.push_back(MakeArrayFile(NgWord2Data::VERSION_DAT, "version.dat")); |
| 73 | files.push_back(std::make_shared<ArrayVfsFile<NgWord2Data::AC_NX_DATA.size()>>( | ||
| 74 | NgWord2Data::AC_NX_DATA, "ac_common_not_b_nx")); | ||
| 75 | files.push_back(std::make_shared<ArrayVfsFile<NgWord2Data::VERSION_DAT.size()>>( | ||
| 76 | NgWord2Data::VERSION_DAT, "version.dat")); | ||
| 77 | 70 | ||
| 78 | return std::make_shared<VectorVfsDirectory>(files, std::vector<VirtualDir>{}, "data"); | 71 | return std::make_shared<VectorVfsDirectory>(std::move(files), std::vector<VirtualDir>{}, |
| 72 | "data"); | ||
| 79 | } | 73 | } |
| 80 | 74 | ||
| 81 | } // namespace FileSys::SystemArchive | 75 | } // namespace FileSys::SystemArchive |
diff --git a/src/core/file_sys/system_archive/time_zone_binary.cpp b/src/core/file_sys/system_archive/time_zone_binary.cpp index d1de63f20..8fd005012 100644 --- a/src/core/file_sys/system_archive/time_zone_binary.cpp +++ b/src/core/file_sys/system_archive/time_zone_binary.cpp | |||
| @@ -654,12 +654,13 @@ static VirtualFile GenerateDefaultTimeZoneFile() { | |||
| 654 | } | 654 | } |
| 655 | 655 | ||
| 656 | VirtualDir TimeZoneBinary() { | 656 | VirtualDir TimeZoneBinary() { |
| 657 | const std::vector<VirtualDir> root_dirs{std::make_shared<VectorVfsDirectory>( | 657 | std::vector<VirtualDir> root_dirs{std::make_shared<VectorVfsDirectory>( |
| 658 | std::vector<VirtualFile>{GenerateDefaultTimeZoneFile()}, std::vector<VirtualDir>{}, | 658 | std::vector<VirtualFile>{GenerateDefaultTimeZoneFile()}, std::vector<VirtualDir>{}, |
| 659 | "zoneinfo")}; | 659 | "zoneinfo")}; |
| 660 | const std::vector<VirtualFile> root_files{ | 660 | std::vector<VirtualFile> root_files{MakeArrayFile(LOCATION_NAMES, "binaryList.txt")}; |
| 661 | std::make_shared<ArrayVfsFile<LOCATION_NAMES.size()>>(LOCATION_NAMES, "binaryList.txt")}; | 661 | |
| 662 | return std::make_shared<VectorVfsDirectory>(root_files, root_dirs, "data"); | 662 | return std::make_shared<VectorVfsDirectory>(std::move(root_files), std::move(root_dirs), |
| 663 | "data"); | ||
| 663 | } | 664 | } |
| 664 | 665 | ||
| 665 | } // namespace FileSys::SystemArchive | 666 | } // namespace FileSys::SystemArchive |
diff --git a/src/core/file_sys/vfs.cpp b/src/core/file_sys/vfs.cpp index e33327ef0..a4c3f67c4 100644 --- a/src/core/file_sys/vfs.cpp +++ b/src/core/file_sys/vfs.cpp | |||
| @@ -30,7 +30,7 @@ bool VfsFilesystem::IsWritable() const { | |||
| 30 | } | 30 | } |
| 31 | 31 | ||
| 32 | VfsEntryType VfsFilesystem::GetEntryType(std::string_view path_) const { | 32 | VfsEntryType VfsFilesystem::GetEntryType(std::string_view path_) const { |
| 33 | const auto path = FileUtil::SanitizePath(path_); | 33 | const auto path = Common::FS::SanitizePath(path_); |
| 34 | if (root->GetFileRelative(path) != nullptr) | 34 | if (root->GetFileRelative(path) != nullptr) |
| 35 | return VfsEntryType::File; | 35 | return VfsEntryType::File; |
| 36 | if (root->GetDirectoryRelative(path) != nullptr) | 36 | if (root->GetDirectoryRelative(path) != nullptr) |
| @@ -40,22 +40,22 @@ VfsEntryType VfsFilesystem::GetEntryType(std::string_view path_) const { | |||
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | VirtualFile VfsFilesystem::OpenFile(std::string_view path_, Mode perms) { | 42 | VirtualFile VfsFilesystem::OpenFile(std::string_view path_, Mode perms) { |
| 43 | const auto path = FileUtil::SanitizePath(path_); | 43 | const auto path = Common::FS::SanitizePath(path_); |
| 44 | return root->GetFileRelative(path); | 44 | return root->GetFileRelative(path); |
| 45 | } | 45 | } |
| 46 | 46 | ||
| 47 | VirtualFile VfsFilesystem::CreateFile(std::string_view path_, Mode perms) { | 47 | VirtualFile VfsFilesystem::CreateFile(std::string_view path_, Mode perms) { |
| 48 | const auto path = FileUtil::SanitizePath(path_); | 48 | const auto path = Common::FS::SanitizePath(path_); |
| 49 | return root->CreateFileRelative(path); | 49 | return root->CreateFileRelative(path); |
| 50 | } | 50 | } |
| 51 | 51 | ||
| 52 | VirtualFile VfsFilesystem::CopyFile(std::string_view old_path_, std::string_view new_path_) { | 52 | VirtualFile VfsFilesystem::CopyFile(std::string_view old_path_, std::string_view new_path_) { |
| 53 | const auto old_path = FileUtil::SanitizePath(old_path_); | 53 | const auto old_path = Common::FS::SanitizePath(old_path_); |
| 54 | const auto new_path = FileUtil::SanitizePath(new_path_); | 54 | const auto new_path = Common::FS::SanitizePath(new_path_); |
| 55 | 55 | ||
| 56 | // VfsDirectory impls are only required to implement copy across the current directory. | 56 | // VfsDirectory impls are only required to implement copy across the current directory. |
| 57 | if (FileUtil::GetParentPath(old_path) == FileUtil::GetParentPath(new_path)) { | 57 | if (Common::FS::GetParentPath(old_path) == Common::FS::GetParentPath(new_path)) { |
| 58 | if (!root->Copy(FileUtil::GetFilename(old_path), FileUtil::GetFilename(new_path))) | 58 | if (!root->Copy(Common::FS::GetFilename(old_path), Common::FS::GetFilename(new_path))) |
| 59 | return nullptr; | 59 | return nullptr; |
| 60 | return OpenFile(new_path, Mode::ReadWrite); | 60 | return OpenFile(new_path, Mode::ReadWrite); |
| 61 | } | 61 | } |
| @@ -76,8 +76,8 @@ VirtualFile VfsFilesystem::CopyFile(std::string_view old_path_, std::string_view | |||
| 76 | } | 76 | } |
| 77 | 77 | ||
| 78 | VirtualFile VfsFilesystem::MoveFile(std::string_view old_path, std::string_view new_path) { | 78 | VirtualFile VfsFilesystem::MoveFile(std::string_view old_path, std::string_view new_path) { |
| 79 | const auto sanitized_old_path = FileUtil::SanitizePath(old_path); | 79 | const auto sanitized_old_path = Common::FS::SanitizePath(old_path); |
| 80 | const auto sanitized_new_path = FileUtil::SanitizePath(new_path); | 80 | const auto sanitized_new_path = Common::FS::SanitizePath(new_path); |
| 81 | 81 | ||
| 82 | // Again, non-default impls are highly encouraged to provide a more optimized version of this. | 82 | // Again, non-default impls are highly encouraged to provide a more optimized version of this. |
| 83 | auto out = CopyFile(sanitized_old_path, sanitized_new_path); | 83 | auto out = CopyFile(sanitized_old_path, sanitized_new_path); |
| @@ -89,26 +89,26 @@ VirtualFile VfsFilesystem::MoveFile(std::string_view old_path, std::string_view | |||
| 89 | } | 89 | } |
| 90 | 90 | ||
| 91 | bool VfsFilesystem::DeleteFile(std::string_view path_) { | 91 | bool VfsFilesystem::DeleteFile(std::string_view path_) { |
| 92 | const auto path = FileUtil::SanitizePath(path_); | 92 | const auto path = Common::FS::SanitizePath(path_); |
| 93 | auto parent = OpenDirectory(FileUtil::GetParentPath(path), Mode::Write); | 93 | auto parent = OpenDirectory(Common::FS::GetParentPath(path), Mode::Write); |
| 94 | if (parent == nullptr) | 94 | if (parent == nullptr) |
| 95 | return false; | 95 | return false; |
| 96 | return parent->DeleteFile(FileUtil::GetFilename(path)); | 96 | return parent->DeleteFile(Common::FS::GetFilename(path)); |
| 97 | } | 97 | } |
| 98 | 98 | ||
| 99 | VirtualDir VfsFilesystem::OpenDirectory(std::string_view path_, Mode perms) { | 99 | VirtualDir VfsFilesystem::OpenDirectory(std::string_view path_, Mode perms) { |
| 100 | const auto path = FileUtil::SanitizePath(path_); | 100 | const auto path = Common::FS::SanitizePath(path_); |
| 101 | return root->GetDirectoryRelative(path); | 101 | return root->GetDirectoryRelative(path); |
| 102 | } | 102 | } |
| 103 | 103 | ||
| 104 | VirtualDir VfsFilesystem::CreateDirectory(std::string_view path_, Mode perms) { | 104 | VirtualDir VfsFilesystem::CreateDirectory(std::string_view path_, Mode perms) { |
| 105 | const auto path = FileUtil::SanitizePath(path_); | 105 | const auto path = Common::FS::SanitizePath(path_); |
| 106 | return root->CreateDirectoryRelative(path); | 106 | return root->CreateDirectoryRelative(path); |
| 107 | } | 107 | } |
| 108 | 108 | ||
| 109 | VirtualDir VfsFilesystem::CopyDirectory(std::string_view old_path_, std::string_view new_path_) { | 109 | VirtualDir VfsFilesystem::CopyDirectory(std::string_view old_path_, std::string_view new_path_) { |
| 110 | const auto old_path = FileUtil::SanitizePath(old_path_); | 110 | const auto old_path = Common::FS::SanitizePath(old_path_); |
| 111 | const auto new_path = FileUtil::SanitizePath(new_path_); | 111 | const auto new_path = Common::FS::SanitizePath(new_path_); |
| 112 | 112 | ||
| 113 | // Non-default impls are highly encouraged to provide a more optimized version of this. | 113 | // Non-default impls are highly encouraged to provide a more optimized version of this. |
| 114 | auto old_dir = OpenDirectory(old_path, Mode::Read); | 114 | auto old_dir = OpenDirectory(old_path, Mode::Read); |
| @@ -139,8 +139,8 @@ VirtualDir VfsFilesystem::CopyDirectory(std::string_view old_path_, std::string_ | |||
| 139 | } | 139 | } |
| 140 | 140 | ||
| 141 | VirtualDir VfsFilesystem::MoveDirectory(std::string_view old_path, std::string_view new_path) { | 141 | VirtualDir VfsFilesystem::MoveDirectory(std::string_view old_path, std::string_view new_path) { |
| 142 | const auto sanitized_old_path = FileUtil::SanitizePath(old_path); | 142 | const auto sanitized_old_path = Common::FS::SanitizePath(old_path); |
| 143 | const auto sanitized_new_path = FileUtil::SanitizePath(new_path); | 143 | const auto sanitized_new_path = Common::FS::SanitizePath(new_path); |
| 144 | 144 | ||
| 145 | // Non-default impls are highly encouraged to provide a more optimized version of this. | 145 | // Non-default impls are highly encouraged to provide a more optimized version of this. |
| 146 | auto out = CopyDirectory(sanitized_old_path, sanitized_new_path); | 146 | auto out = CopyDirectory(sanitized_old_path, sanitized_new_path); |
| @@ -152,17 +152,17 @@ VirtualDir VfsFilesystem::MoveDirectory(std::string_view old_path, std::string_v | |||
| 152 | } | 152 | } |
| 153 | 153 | ||
| 154 | bool VfsFilesystem::DeleteDirectory(std::string_view path_) { | 154 | bool VfsFilesystem::DeleteDirectory(std::string_view path_) { |
| 155 | const auto path = FileUtil::SanitizePath(path_); | 155 | const auto path = Common::FS::SanitizePath(path_); |
| 156 | auto parent = OpenDirectory(FileUtil::GetParentPath(path), Mode::Write); | 156 | auto parent = OpenDirectory(Common::FS::GetParentPath(path), Mode::Write); |
| 157 | if (parent == nullptr) | 157 | if (parent == nullptr) |
| 158 | return false; | 158 | return false; |
| 159 | return parent->DeleteSubdirectoryRecursive(FileUtil::GetFilename(path)); | 159 | return parent->DeleteSubdirectoryRecursive(Common::FS::GetFilename(path)); |
| 160 | } | 160 | } |
| 161 | 161 | ||
| 162 | VfsFile::~VfsFile() = default; | 162 | VfsFile::~VfsFile() = default; |
| 163 | 163 | ||
| 164 | std::string VfsFile::GetExtension() const { | 164 | std::string VfsFile::GetExtension() const { |
| 165 | return std::string(FileUtil::GetExtensionFromFilename(GetName())); | 165 | return std::string(Common::FS::GetExtensionFromFilename(GetName())); |
| 166 | } | 166 | } |
| 167 | 167 | ||
| 168 | VfsDirectory::~VfsDirectory() = default; | 168 | VfsDirectory::~VfsDirectory() = default; |
| @@ -203,7 +203,7 @@ std::string VfsFile::GetFullPath() const { | |||
| 203 | } | 203 | } |
| 204 | 204 | ||
| 205 | std::shared_ptr<VfsFile> VfsDirectory::GetFileRelative(std::string_view path) const { | 205 | std::shared_ptr<VfsFile> VfsDirectory::GetFileRelative(std::string_view path) const { |
| 206 | auto vec = FileUtil::SplitPathComponents(path); | 206 | auto vec = Common::FS::SplitPathComponents(path); |
| 207 | vec.erase(std::remove_if(vec.begin(), vec.end(), [](const auto& str) { return str.empty(); }), | 207 | vec.erase(std::remove_if(vec.begin(), vec.end(), [](const auto& str) { return str.empty(); }), |
| 208 | vec.end()); | 208 | vec.end()); |
| 209 | if (vec.empty()) { | 209 | if (vec.empty()) { |
| @@ -239,7 +239,7 @@ std::shared_ptr<VfsFile> VfsDirectory::GetFileAbsolute(std::string_view path) co | |||
| 239 | } | 239 | } |
| 240 | 240 | ||
| 241 | std::shared_ptr<VfsDirectory> VfsDirectory::GetDirectoryRelative(std::string_view path) const { | 241 | std::shared_ptr<VfsDirectory> VfsDirectory::GetDirectoryRelative(std::string_view path) const { |
| 242 | auto vec = FileUtil::SplitPathComponents(path); | 242 | auto vec = Common::FS::SplitPathComponents(path); |
| 243 | vec.erase(std::remove_if(vec.begin(), vec.end(), [](const auto& str) { return str.empty(); }), | 243 | vec.erase(std::remove_if(vec.begin(), vec.end(), [](const auto& str) { return str.empty(); }), |
| 244 | vec.end()); | 244 | vec.end()); |
| 245 | if (vec.empty()) { | 245 | if (vec.empty()) { |
| @@ -301,7 +301,7 @@ std::size_t VfsDirectory::GetSize() const { | |||
| 301 | } | 301 | } |
| 302 | 302 | ||
| 303 | std::shared_ptr<VfsFile> VfsDirectory::CreateFileRelative(std::string_view path) { | 303 | std::shared_ptr<VfsFile> VfsDirectory::CreateFileRelative(std::string_view path) { |
| 304 | auto vec = FileUtil::SplitPathComponents(path); | 304 | auto vec = Common::FS::SplitPathComponents(path); |
| 305 | vec.erase(std::remove_if(vec.begin(), vec.end(), [](const auto& str) { return str.empty(); }), | 305 | vec.erase(std::remove_if(vec.begin(), vec.end(), [](const auto& str) { return str.empty(); }), |
| 306 | vec.end()); | 306 | vec.end()); |
| 307 | if (vec.empty()) { | 307 | if (vec.empty()) { |
| @@ -320,7 +320,7 @@ std::shared_ptr<VfsFile> VfsDirectory::CreateFileRelative(std::string_view path) | |||
| 320 | } | 320 | } |
| 321 | } | 321 | } |
| 322 | 322 | ||
| 323 | return dir->CreateFileRelative(FileUtil::GetPathWithoutTop(path)); | 323 | return dir->CreateFileRelative(Common::FS::GetPathWithoutTop(path)); |
| 324 | } | 324 | } |
| 325 | 325 | ||
| 326 | std::shared_ptr<VfsFile> VfsDirectory::CreateFileAbsolute(std::string_view path) { | 326 | std::shared_ptr<VfsFile> VfsDirectory::CreateFileAbsolute(std::string_view path) { |
| @@ -332,7 +332,7 @@ std::shared_ptr<VfsFile> VfsDirectory::CreateFileAbsolute(std::string_view path) | |||
| 332 | } | 332 | } |
| 333 | 333 | ||
| 334 | std::shared_ptr<VfsDirectory> VfsDirectory::CreateDirectoryRelative(std::string_view path) { | 334 | std::shared_ptr<VfsDirectory> VfsDirectory::CreateDirectoryRelative(std::string_view path) { |
| 335 | auto vec = FileUtil::SplitPathComponents(path); | 335 | auto vec = Common::FS::SplitPathComponents(path); |
| 336 | vec.erase(std::remove_if(vec.begin(), vec.end(), [](const auto& str) { return str.empty(); }), | 336 | vec.erase(std::remove_if(vec.begin(), vec.end(), [](const auto& str) { return str.empty(); }), |
| 337 | vec.end()); | 337 | vec.end()); |
| 338 | if (vec.empty()) { | 338 | if (vec.empty()) { |
| @@ -351,7 +351,7 @@ std::shared_ptr<VfsDirectory> VfsDirectory::CreateDirectoryRelative(std::string_ | |||
| 351 | } | 351 | } |
| 352 | } | 352 | } |
| 353 | 353 | ||
| 354 | return dir->CreateDirectoryRelative(FileUtil::GetPathWithoutTop(path)); | 354 | return dir->CreateDirectoryRelative(Common::FS::GetPathWithoutTop(path)); |
| 355 | } | 355 | } |
| 356 | 356 | ||
| 357 | std::shared_ptr<VfsDirectory> VfsDirectory::CreateDirectoryAbsolute(std::string_view path) { | 357 | std::shared_ptr<VfsDirectory> VfsDirectory::CreateDirectoryAbsolute(std::string_view path) { |
diff --git a/src/core/file_sys/vfs_libzip.cpp b/src/core/file_sys/vfs_libzip.cpp index d69952940..429d7bc8b 100644 --- a/src/core/file_sys/vfs_libzip.cpp +++ b/src/core/file_sys/vfs_libzip.cpp | |||
| @@ -49,7 +49,7 @@ VirtualDir ExtractZIP(VirtualFile file) { | |||
| 49 | if (zip_fread(file2.get(), buf.data(), buf.size()) != s64(buf.size())) | 49 | if (zip_fread(file2.get(), buf.data(), buf.size()) != s64(buf.size())) |
| 50 | return nullptr; | 50 | return nullptr; |
| 51 | 51 | ||
| 52 | const auto parts = FileUtil::SplitPathComponents(stat.name); | 52 | const auto parts = Common::FS::SplitPathComponents(stat.name); |
| 53 | const auto new_file = std::make_shared<VectorVfsFile>(buf, parts.back()); | 53 | const auto new_file = std::make_shared<VectorVfsFile>(buf, parts.back()); |
| 54 | 54 | ||
| 55 | std::shared_ptr<VectorVfsDirectory> dtrv = out; | 55 | std::shared_ptr<VectorVfsDirectory> dtrv = out; |
diff --git a/src/core/file_sys/vfs_real.cpp b/src/core/file_sys/vfs_real.cpp index 0db0091f6..488687ba9 100644 --- a/src/core/file_sys/vfs_real.cpp +++ b/src/core/file_sys/vfs_real.cpp | |||
| @@ -14,6 +14,8 @@ | |||
| 14 | 14 | ||
| 15 | namespace FileSys { | 15 | namespace FileSys { |
| 16 | 16 | ||
| 17 | namespace FS = Common::FS; | ||
| 18 | |||
| 17 | static std::string ModeFlagsToString(Mode mode) { | 19 | static std::string ModeFlagsToString(Mode mode) { |
| 18 | std::string mode_str; | 20 | std::string mode_str; |
| 19 | 21 | ||
| @@ -57,79 +59,82 @@ bool RealVfsFilesystem::IsWritable() const { | |||
| 57 | } | 59 | } |
| 58 | 60 | ||
| 59 | VfsEntryType RealVfsFilesystem::GetEntryType(std::string_view path_) const { | 61 | VfsEntryType RealVfsFilesystem::GetEntryType(std::string_view path_) const { |
| 60 | const auto path = FileUtil::SanitizePath(path_, FileUtil::DirectorySeparator::PlatformDefault); | 62 | const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault); |
| 61 | if (!FileUtil::Exists(path)) | 63 | if (!FS::Exists(path)) { |
| 62 | return VfsEntryType::None; | 64 | return VfsEntryType::None; |
| 63 | if (FileUtil::IsDirectory(path)) | 65 | } |
| 66 | if (FS::IsDirectory(path)) { | ||
| 64 | return VfsEntryType::Directory; | 67 | return VfsEntryType::Directory; |
| 68 | } | ||
| 65 | 69 | ||
| 66 | return VfsEntryType::File; | 70 | return VfsEntryType::File; |
| 67 | } | 71 | } |
| 68 | 72 | ||
| 69 | VirtualFile RealVfsFilesystem::OpenFile(std::string_view path_, Mode perms) { | 73 | VirtualFile RealVfsFilesystem::OpenFile(std::string_view path_, Mode perms) { |
| 70 | const auto path = FileUtil::SanitizePath(path_, FileUtil::DirectorySeparator::PlatformDefault); | 74 | const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault); |
| 71 | if (cache.find(path) != cache.end()) { | 75 | |
| 72 | auto weak = cache[path]; | 76 | if (const auto weak_iter = cache.find(path); weak_iter != cache.cend()) { |
| 77 | const auto& weak = weak_iter->second; | ||
| 78 | |||
| 73 | if (!weak.expired()) { | 79 | if (!weak.expired()) { |
| 74 | return std::shared_ptr<RealVfsFile>(new RealVfsFile(*this, weak.lock(), path, perms)); | 80 | return std::shared_ptr<RealVfsFile>(new RealVfsFile(*this, weak.lock(), path, perms)); |
| 75 | } | 81 | } |
| 76 | } | 82 | } |
| 77 | 83 | ||
| 78 | if (!FileUtil::Exists(path) && True(perms & Mode::WriteAppend)) { | 84 | if (!FS::Exists(path) && True(perms & Mode::WriteAppend)) { |
| 79 | FileUtil::CreateEmptyFile(path); | 85 | FS::CreateEmptyFile(path); |
| 80 | } | 86 | } |
| 81 | 87 | ||
| 82 | auto backing = std::make_shared<FileUtil::IOFile>(path, ModeFlagsToString(perms).c_str()); | 88 | auto backing = std::make_shared<FS::IOFile>(path, ModeFlagsToString(perms).c_str()); |
| 83 | cache[path] = backing; | 89 | cache.insert_or_assign(path, backing); |
| 84 | 90 | ||
| 85 | // Cannot use make_shared as RealVfsFile constructor is private | 91 | // Cannot use make_shared as RealVfsFile constructor is private |
| 86 | return std::shared_ptr<RealVfsFile>(new RealVfsFile(*this, backing, path, perms)); | 92 | return std::shared_ptr<RealVfsFile>(new RealVfsFile(*this, backing, path, perms)); |
| 87 | } | 93 | } |
| 88 | 94 | ||
| 89 | VirtualFile RealVfsFilesystem::CreateFile(std::string_view path_, Mode perms) { | 95 | VirtualFile RealVfsFilesystem::CreateFile(std::string_view path_, Mode perms) { |
| 90 | const auto path = FileUtil::SanitizePath(path_, FileUtil::DirectorySeparator::PlatformDefault); | 96 | const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault); |
| 91 | const auto path_fwd = FileUtil::SanitizePath(path, FileUtil::DirectorySeparator::ForwardSlash); | 97 | const auto path_fwd = FS::SanitizePath(path, FS::DirectorySeparator::ForwardSlash); |
| 92 | if (!FileUtil::Exists(path)) { | 98 | if (!FS::Exists(path)) { |
| 93 | FileUtil::CreateFullPath(path_fwd); | 99 | FS::CreateFullPath(path_fwd); |
| 94 | if (!FileUtil::CreateEmptyFile(path)) | 100 | if (!FS::CreateEmptyFile(path)) { |
| 95 | return nullptr; | 101 | return nullptr; |
| 102 | } | ||
| 96 | } | 103 | } |
| 97 | return OpenFile(path, perms); | 104 | return OpenFile(path, perms); |
| 98 | } | 105 | } |
| 99 | 106 | ||
| 100 | VirtualFile RealVfsFilesystem::CopyFile(std::string_view old_path_, std::string_view new_path_) { | 107 | VirtualFile RealVfsFilesystem::CopyFile(std::string_view old_path_, std::string_view new_path_) { |
| 101 | const auto old_path = | 108 | const auto old_path = FS::SanitizePath(old_path_, FS::DirectorySeparator::PlatformDefault); |
| 102 | FileUtil::SanitizePath(old_path_, FileUtil::DirectorySeparator::PlatformDefault); | 109 | const auto new_path = FS::SanitizePath(new_path_, FS::DirectorySeparator::PlatformDefault); |
| 103 | const auto new_path = | ||
| 104 | FileUtil::SanitizePath(new_path_, FileUtil::DirectorySeparator::PlatformDefault); | ||
| 105 | 110 | ||
| 106 | if (!FileUtil::Exists(old_path) || FileUtil::Exists(new_path) || | 111 | if (!FS::Exists(old_path) || FS::Exists(new_path) || FS::IsDirectory(old_path) || |
| 107 | FileUtil::IsDirectory(old_path) || !FileUtil::Copy(old_path, new_path)) | 112 | !FS::Copy(old_path, new_path)) { |
| 108 | return nullptr; | 113 | return nullptr; |
| 114 | } | ||
| 109 | return OpenFile(new_path, Mode::ReadWrite); | 115 | return OpenFile(new_path, Mode::ReadWrite); |
| 110 | } | 116 | } |
| 111 | 117 | ||
| 112 | VirtualFile RealVfsFilesystem::MoveFile(std::string_view old_path_, std::string_view new_path_) { | 118 | VirtualFile RealVfsFilesystem::MoveFile(std::string_view old_path_, std::string_view new_path_) { |
| 113 | const auto old_path = | 119 | const auto old_path = FS::SanitizePath(old_path_, FS::DirectorySeparator::PlatformDefault); |
| 114 | FileUtil::SanitizePath(old_path_, FileUtil::DirectorySeparator::PlatformDefault); | 120 | const auto new_path = FS::SanitizePath(new_path_, FS::DirectorySeparator::PlatformDefault); |
| 115 | const auto new_path = | 121 | const auto cached_file_iter = cache.find(old_path); |
| 116 | FileUtil::SanitizePath(new_path_, FileUtil::DirectorySeparator::PlatformDefault); | ||
| 117 | 122 | ||
| 118 | if (cache.find(old_path) != cache.end()) { | 123 | if (cached_file_iter != cache.cend()) { |
| 119 | auto file = cache[old_path].lock(); | 124 | auto file = cached_file_iter->second.lock(); |
| 120 | 125 | ||
| 121 | if (!cache[old_path].expired()) { | 126 | if (!cached_file_iter->second.expired()) { |
| 122 | file->Close(); | 127 | file->Close(); |
| 123 | } | 128 | } |
| 124 | 129 | ||
| 125 | if (!FileUtil::Exists(old_path) || FileUtil::Exists(new_path) || | 130 | if (!FS::Exists(old_path) || FS::Exists(new_path) || FS::IsDirectory(old_path) || |
| 126 | FileUtil::IsDirectory(old_path) || !FileUtil::Rename(old_path, new_path)) { | 131 | !FS::Rename(old_path, new_path)) { |
| 127 | return nullptr; | 132 | return nullptr; |
| 128 | } | 133 | } |
| 129 | 134 | ||
| 130 | cache.erase(old_path); | 135 | cache.erase(old_path); |
| 131 | file->Open(new_path, "r+b"); | 136 | file->Open(new_path, "r+b"); |
| 132 | cache[new_path] = file; | 137 | cache.insert_or_assign(new_path, std::move(file)); |
| 133 | } else { | 138 | } else { |
| 134 | UNREACHABLE(); | 139 | UNREACHABLE(); |
| 135 | return nullptr; | 140 | return nullptr; |
| @@ -139,28 +144,33 @@ VirtualFile RealVfsFilesystem::MoveFile(std::string_view old_path_, std::string_ | |||
| 139 | } | 144 | } |
| 140 | 145 | ||
| 141 | bool RealVfsFilesystem::DeleteFile(std::string_view path_) { | 146 | bool RealVfsFilesystem::DeleteFile(std::string_view path_) { |
| 142 | const auto path = FileUtil::SanitizePath(path_, FileUtil::DirectorySeparator::PlatformDefault); | 147 | const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault); |
| 143 | if (cache.find(path) != cache.end()) { | 148 | const auto cached_iter = cache.find(path); |
| 144 | if (!cache[path].expired()) | 149 | |
| 145 | cache[path].lock()->Close(); | 150 | if (cached_iter != cache.cend()) { |
| 151 | if (!cached_iter->second.expired()) { | ||
| 152 | cached_iter->second.lock()->Close(); | ||
| 153 | } | ||
| 146 | cache.erase(path); | 154 | cache.erase(path); |
| 147 | } | 155 | } |
| 148 | return FileUtil::Delete(path); | 156 | |
| 157 | return FS::Delete(path); | ||
| 149 | } | 158 | } |
| 150 | 159 | ||
| 151 | VirtualDir RealVfsFilesystem::OpenDirectory(std::string_view path_, Mode perms) { | 160 | VirtualDir RealVfsFilesystem::OpenDirectory(std::string_view path_, Mode perms) { |
| 152 | const auto path = FileUtil::SanitizePath(path_, FileUtil::DirectorySeparator::PlatformDefault); | 161 | const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault); |
| 153 | // Cannot use make_shared as RealVfsDirectory constructor is private | 162 | // Cannot use make_shared as RealVfsDirectory constructor is private |
| 154 | return std::shared_ptr<RealVfsDirectory>(new RealVfsDirectory(*this, path, perms)); | 163 | return std::shared_ptr<RealVfsDirectory>(new RealVfsDirectory(*this, path, perms)); |
| 155 | } | 164 | } |
| 156 | 165 | ||
| 157 | VirtualDir RealVfsFilesystem::CreateDirectory(std::string_view path_, Mode perms) { | 166 | VirtualDir RealVfsFilesystem::CreateDirectory(std::string_view path_, Mode perms) { |
| 158 | const auto path = FileUtil::SanitizePath(path_, FileUtil::DirectorySeparator::PlatformDefault); | 167 | const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault); |
| 159 | const auto path_fwd = FileUtil::SanitizePath(path, FileUtil::DirectorySeparator::ForwardSlash); | 168 | const auto path_fwd = FS::SanitizePath(path, FS::DirectorySeparator::ForwardSlash); |
| 160 | if (!FileUtil::Exists(path)) { | 169 | if (!FS::Exists(path)) { |
| 161 | FileUtil::CreateFullPath(path_fwd); | 170 | FS::CreateFullPath(path_fwd); |
| 162 | if (!FileUtil::CreateDir(path)) | 171 | if (!FS::CreateDir(path)) { |
| 163 | return nullptr; | 172 | return nullptr; |
| 173 | } | ||
| 164 | } | 174 | } |
| 165 | // Cannot use make_shared as RealVfsDirectory constructor is private | 175 | // Cannot use make_shared as RealVfsDirectory constructor is private |
| 166 | return std::shared_ptr<RealVfsDirectory>(new RealVfsDirectory(*this, path, perms)); | 176 | return std::shared_ptr<RealVfsDirectory>(new RealVfsDirectory(*this, path, perms)); |
| @@ -168,67 +178,75 @@ VirtualDir RealVfsFilesystem::CreateDirectory(std::string_view path_, Mode perms | |||
| 168 | 178 | ||
| 169 | VirtualDir RealVfsFilesystem::CopyDirectory(std::string_view old_path_, | 179 | VirtualDir RealVfsFilesystem::CopyDirectory(std::string_view old_path_, |
| 170 | std::string_view new_path_) { | 180 | std::string_view new_path_) { |
| 171 | const auto old_path = | 181 | const auto old_path = FS::SanitizePath(old_path_, FS::DirectorySeparator::PlatformDefault); |
| 172 | FileUtil::SanitizePath(old_path_, FileUtil::DirectorySeparator::PlatformDefault); | 182 | const auto new_path = FS::SanitizePath(new_path_, FS::DirectorySeparator::PlatformDefault); |
| 173 | const auto new_path = | 183 | if (!FS::Exists(old_path) || FS::Exists(new_path) || !FS::IsDirectory(old_path)) { |
| 174 | FileUtil::SanitizePath(new_path_, FileUtil::DirectorySeparator::PlatformDefault); | ||
| 175 | if (!FileUtil::Exists(old_path) || FileUtil::Exists(new_path) || | ||
| 176 | !FileUtil::IsDirectory(old_path)) | ||
| 177 | return nullptr; | 184 | return nullptr; |
| 178 | FileUtil::CopyDir(old_path, new_path); | 185 | } |
| 186 | FS::CopyDir(old_path, new_path); | ||
| 179 | return OpenDirectory(new_path, Mode::ReadWrite); | 187 | return OpenDirectory(new_path, Mode::ReadWrite); |
| 180 | } | 188 | } |
| 181 | 189 | ||
| 182 | VirtualDir RealVfsFilesystem::MoveDirectory(std::string_view old_path_, | 190 | VirtualDir RealVfsFilesystem::MoveDirectory(std::string_view old_path_, |
| 183 | std::string_view new_path_) { | 191 | std::string_view new_path_) { |
| 184 | const auto old_path = | 192 | const auto old_path = FS::SanitizePath(old_path_, FS::DirectorySeparator::PlatformDefault); |
| 185 | FileUtil::SanitizePath(old_path_, FileUtil::DirectorySeparator::PlatformDefault); | 193 | const auto new_path = FS::SanitizePath(new_path_, FS::DirectorySeparator::PlatformDefault); |
| 186 | const auto new_path = | 194 | |
| 187 | FileUtil::SanitizePath(new_path_, FileUtil::DirectorySeparator::PlatformDefault); | 195 | if (!FS::Exists(old_path) || FS::Exists(new_path) || FS::IsDirectory(old_path) || |
| 188 | if (!FileUtil::Exists(old_path) || FileUtil::Exists(new_path) || | 196 | !FS::Rename(old_path, new_path)) { |
| 189 | FileUtil::IsDirectory(old_path) || !FileUtil::Rename(old_path, new_path)) | ||
| 190 | return nullptr; | 197 | return nullptr; |
| 198 | } | ||
| 191 | 199 | ||
| 192 | for (auto& kv : cache) { | 200 | for (auto& kv : cache) { |
| 193 | // Path in cache starts with old_path | 201 | // If the path in the cache doesn't start with old_path, then bail on this file. |
| 194 | if (kv.first.rfind(old_path, 0) == 0) { | 202 | if (kv.first.rfind(old_path, 0) != 0) { |
| 195 | const auto file_old_path = | 203 | continue; |
| 196 | FileUtil::SanitizePath(kv.first, FileUtil::DirectorySeparator::PlatformDefault); | 204 | } |
| 197 | const auto file_new_path = | 205 | |
| 198 | FileUtil::SanitizePath(new_path + DIR_SEP + kv.first.substr(old_path.size()), | 206 | const auto file_old_path = |
| 199 | FileUtil::DirectorySeparator::PlatformDefault); | 207 | FS::SanitizePath(kv.first, FS::DirectorySeparator::PlatformDefault); |
| 200 | auto cached = cache[file_old_path]; | 208 | auto file_new_path = FS::SanitizePath(new_path + DIR_SEP + kv.first.substr(old_path.size()), |
| 201 | if (!cached.expired()) { | 209 | FS::DirectorySeparator::PlatformDefault); |
| 202 | auto file = cached.lock(); | 210 | const auto& cached = cache[file_old_path]; |
| 203 | file->Open(file_new_path, "r+b"); | 211 | |
| 204 | cache.erase(file_old_path); | 212 | if (cached.expired()) { |
| 205 | cache[file_new_path] = file; | 213 | continue; |
| 206 | } | ||
| 207 | } | 214 | } |
| 215 | |||
| 216 | auto file = cached.lock(); | ||
| 217 | file->Open(file_new_path, "r+b"); | ||
| 218 | cache.erase(file_old_path); | ||
| 219 | cache.insert_or_assign(std::move(file_new_path), std::move(file)); | ||
| 208 | } | 220 | } |
| 209 | 221 | ||
| 210 | return OpenDirectory(new_path, Mode::ReadWrite); | 222 | return OpenDirectory(new_path, Mode::ReadWrite); |
| 211 | } | 223 | } |
| 212 | 224 | ||
| 213 | bool RealVfsFilesystem::DeleteDirectory(std::string_view path_) { | 225 | bool RealVfsFilesystem::DeleteDirectory(std::string_view path_) { |
| 214 | const auto path = FileUtil::SanitizePath(path_, FileUtil::DirectorySeparator::PlatformDefault); | 226 | const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault); |
| 227 | |||
| 215 | for (auto& kv : cache) { | 228 | for (auto& kv : cache) { |
| 216 | // Path in cache starts with old_path | 229 | // If the path in the cache doesn't start with path, then bail on this file. |
| 217 | if (kv.first.rfind(path, 0) == 0) { | 230 | if (kv.first.rfind(path, 0) != 0) { |
| 218 | if (!cache[kv.first].expired()) | 231 | continue; |
| 219 | cache[kv.first].lock()->Close(); | 232 | } |
| 220 | cache.erase(kv.first); | 233 | |
| 234 | const auto& entry = cache[kv.first]; | ||
| 235 | if (!entry.expired()) { | ||
| 236 | entry.lock()->Close(); | ||
| 221 | } | 237 | } |
| 238 | |||
| 239 | cache.erase(kv.first); | ||
| 222 | } | 240 | } |
| 223 | return FileUtil::DeleteDirRecursively(path); | 241 | |
| 242 | return FS::DeleteDirRecursively(path); | ||
| 224 | } | 243 | } |
| 225 | 244 | ||
| 226 | RealVfsFile::RealVfsFile(RealVfsFilesystem& base_, std::shared_ptr<FileUtil::IOFile> backing_, | 245 | RealVfsFile::RealVfsFile(RealVfsFilesystem& base_, std::shared_ptr<FS::IOFile> backing_, |
| 227 | const std::string& path_, Mode perms_) | 246 | const std::string& path_, Mode perms_) |
| 228 | : base(base_), backing(std::move(backing_)), path(path_), | 247 | : base(base_), backing(std::move(backing_)), path(path_), parent_path(FS::GetParentPath(path_)), |
| 229 | parent_path(FileUtil::GetParentPath(path_)), | 248 | path_components(FS::SplitPathComponents(path_)), |
| 230 | path_components(FileUtil::SplitPathComponents(path_)), | 249 | parent_components(FS::SliceVector(path_components, 0, path_components.size() - 1)), |
| 231 | parent_components(FileUtil::SliceVector(path_components, 0, path_components.size() - 1)), | ||
| 232 | perms(perms_) {} | 250 | perms(perms_) {} |
| 233 | 251 | ||
| 234 | RealVfsFile::~RealVfsFile() = default; | 252 | RealVfsFile::~RealVfsFile() = default; |
| @@ -258,14 +276,16 @@ bool RealVfsFile::IsReadable() const { | |||
| 258 | } | 276 | } |
| 259 | 277 | ||
| 260 | std::size_t RealVfsFile::Read(u8* data, std::size_t length, std::size_t offset) const { | 278 | std::size_t RealVfsFile::Read(u8* data, std::size_t length, std::size_t offset) const { |
| 261 | if (!backing->Seek(offset, SEEK_SET)) | 279 | if (!backing->Seek(static_cast<s64>(offset), SEEK_SET)) { |
| 262 | return 0; | 280 | return 0; |
| 281 | } | ||
| 263 | return backing->ReadBytes(data, length); | 282 | return backing->ReadBytes(data, length); |
| 264 | } | 283 | } |
| 265 | 284 | ||
| 266 | std::size_t RealVfsFile::Write(const u8* data, std::size_t length, std::size_t offset) { | 285 | std::size_t RealVfsFile::Write(const u8* data, std::size_t length, std::size_t offset) { |
| 267 | if (!backing->Seek(offset, SEEK_SET)) | 286 | if (!backing->Seek(static_cast<s64>(offset), SEEK_SET)) { |
| 268 | return 0; | 287 | return 0; |
| 288 | } | ||
| 269 | return backing->WriteBytes(data, length); | 289 | return backing->WriteBytes(data, length); |
| 270 | } | 290 | } |
| 271 | 291 | ||
| @@ -282,16 +302,18 @@ bool RealVfsFile::Close() { | |||
| 282 | 302 | ||
| 283 | template <> | 303 | template <> |
| 284 | std::vector<VirtualFile> RealVfsDirectory::IterateEntries<RealVfsFile, VfsFile>() const { | 304 | std::vector<VirtualFile> RealVfsDirectory::IterateEntries<RealVfsFile, VfsFile>() const { |
| 285 | if (perms == Mode::Append) | 305 | if (perms == Mode::Append) { |
| 286 | return {}; | 306 | return {}; |
| 307 | } | ||
| 287 | 308 | ||
| 288 | std::vector<VirtualFile> out; | 309 | std::vector<VirtualFile> out; |
| 289 | FileUtil::ForeachDirectoryEntry( | 310 | FS::ForeachDirectoryEntry( |
| 290 | nullptr, path, | 311 | nullptr, path, |
| 291 | [&out, this](u64* entries_out, const std::string& directory, const std::string& filename) { | 312 | [&out, this](u64* entries_out, const std::string& directory, const std::string& filename) { |
| 292 | const std::string full_path = directory + DIR_SEP + filename; | 313 | const std::string full_path = directory + DIR_SEP + filename; |
| 293 | if (!FileUtil::IsDirectory(full_path)) | 314 | if (!FS::IsDirectory(full_path)) { |
| 294 | out.emplace_back(base.OpenFile(full_path, perms)); | 315 | out.emplace_back(base.OpenFile(full_path, perms)); |
| 316 | } | ||
| 295 | return true; | 317 | return true; |
| 296 | }); | 318 | }); |
| 297 | 319 | ||
| @@ -300,16 +322,18 @@ std::vector<VirtualFile> RealVfsDirectory::IterateEntries<RealVfsFile, VfsFile>( | |||
| 300 | 322 | ||
| 301 | template <> | 323 | template <> |
| 302 | std::vector<VirtualDir> RealVfsDirectory::IterateEntries<RealVfsDirectory, VfsDirectory>() const { | 324 | std::vector<VirtualDir> RealVfsDirectory::IterateEntries<RealVfsDirectory, VfsDirectory>() const { |
| 303 | if (perms == Mode::Append) | 325 | if (perms == Mode::Append) { |
| 304 | return {}; | 326 | return {}; |
| 327 | } | ||
| 305 | 328 | ||
| 306 | std::vector<VirtualDir> out; | 329 | std::vector<VirtualDir> out; |
| 307 | FileUtil::ForeachDirectoryEntry( | 330 | FS::ForeachDirectoryEntry( |
| 308 | nullptr, path, | 331 | nullptr, path, |
| 309 | [&out, this](u64* entries_out, const std::string& directory, const std::string& filename) { | 332 | [&out, this](u64* entries_out, const std::string& directory, const std::string& filename) { |
| 310 | const std::string full_path = directory + DIR_SEP + filename; | 333 | const std::string full_path = directory + DIR_SEP + filename; |
| 311 | if (FileUtil::IsDirectory(full_path)) | 334 | if (FS::IsDirectory(full_path)) { |
| 312 | out.emplace_back(base.OpenDirectory(full_path, perms)); | 335 | out.emplace_back(base.OpenDirectory(full_path, perms)); |
| 336 | } | ||
| 313 | return true; | 337 | return true; |
| 314 | }); | 338 | }); |
| 315 | 339 | ||
| @@ -317,29 +341,30 @@ std::vector<VirtualDir> RealVfsDirectory::IterateEntries<RealVfsDirectory, VfsDi | |||
| 317 | } | 341 | } |
| 318 | 342 | ||
| 319 | RealVfsDirectory::RealVfsDirectory(RealVfsFilesystem& base_, const std::string& path_, Mode perms_) | 343 | RealVfsDirectory::RealVfsDirectory(RealVfsFilesystem& base_, const std::string& path_, Mode perms_) |
| 320 | : base(base_), path(FileUtil::RemoveTrailingSlash(path_)), | 344 | : base(base_), path(FS::RemoveTrailingSlash(path_)), parent_path(FS::GetParentPath(path)), |
| 321 | parent_path(FileUtil::GetParentPath(path)), | 345 | path_components(FS::SplitPathComponents(path)), |
| 322 | path_components(FileUtil::SplitPathComponents(path)), | 346 | parent_components(FS::SliceVector(path_components, 0, path_components.size() - 1)), |
| 323 | parent_components(FileUtil::SliceVector(path_components, 0, path_components.size() - 1)), | ||
| 324 | perms(perms_) { | 347 | perms(perms_) { |
| 325 | if (!FileUtil::Exists(path) && True(perms & Mode::WriteAppend)) { | 348 | if (!FS::Exists(path) && True(perms & Mode::WriteAppend)) { |
| 326 | FileUtil::CreateDir(path); | 349 | FS::CreateDir(path); |
| 327 | } | 350 | } |
| 328 | } | 351 | } |
| 329 | 352 | ||
| 330 | RealVfsDirectory::~RealVfsDirectory() = default; | 353 | RealVfsDirectory::~RealVfsDirectory() = default; |
| 331 | 354 | ||
| 332 | std::shared_ptr<VfsFile> RealVfsDirectory::GetFileRelative(std::string_view path) const { | 355 | std::shared_ptr<VfsFile> RealVfsDirectory::GetFileRelative(std::string_view path) const { |
| 333 | const auto full_path = FileUtil::SanitizePath(this->path + DIR_SEP + std::string(path)); | 356 | const auto full_path = FS::SanitizePath(this->path + DIR_SEP + std::string(path)); |
| 334 | if (!FileUtil::Exists(full_path) || FileUtil::IsDirectory(full_path)) | 357 | if (!FS::Exists(full_path) || FS::IsDirectory(full_path)) { |
| 335 | return nullptr; | 358 | return nullptr; |
| 359 | } | ||
| 336 | return base.OpenFile(full_path, perms); | 360 | return base.OpenFile(full_path, perms); |
| 337 | } | 361 | } |
| 338 | 362 | ||
| 339 | std::shared_ptr<VfsDirectory> RealVfsDirectory::GetDirectoryRelative(std::string_view path) const { | 363 | std::shared_ptr<VfsDirectory> RealVfsDirectory::GetDirectoryRelative(std::string_view path) const { |
| 340 | const auto full_path = FileUtil::SanitizePath(this->path + DIR_SEP + std::string(path)); | 364 | const auto full_path = FS::SanitizePath(this->path + DIR_SEP + std::string(path)); |
| 341 | if (!FileUtil::Exists(full_path) || !FileUtil::IsDirectory(full_path)) | 365 | if (!FS::Exists(full_path) || !FS::IsDirectory(full_path)) { |
| 342 | return nullptr; | 366 | return nullptr; |
| 367 | } | ||
| 343 | return base.OpenDirectory(full_path, perms); | 368 | return base.OpenDirectory(full_path, perms); |
| 344 | } | 369 | } |
| 345 | 370 | ||
| @@ -352,17 +377,17 @@ std::shared_ptr<VfsDirectory> RealVfsDirectory::GetSubdirectory(std::string_view | |||
| 352 | } | 377 | } |
| 353 | 378 | ||
| 354 | std::shared_ptr<VfsFile> RealVfsDirectory::CreateFileRelative(std::string_view path) { | 379 | std::shared_ptr<VfsFile> RealVfsDirectory::CreateFileRelative(std::string_view path) { |
| 355 | const auto full_path = FileUtil::SanitizePath(this->path + DIR_SEP + std::string(path)); | 380 | const auto full_path = FS::SanitizePath(this->path + DIR_SEP + std::string(path)); |
| 356 | return base.CreateFile(full_path, perms); | 381 | return base.CreateFile(full_path, perms); |
| 357 | } | 382 | } |
| 358 | 383 | ||
| 359 | std::shared_ptr<VfsDirectory> RealVfsDirectory::CreateDirectoryRelative(std::string_view path) { | 384 | std::shared_ptr<VfsDirectory> RealVfsDirectory::CreateDirectoryRelative(std::string_view path) { |
| 360 | const auto full_path = FileUtil::SanitizePath(this->path + DIR_SEP + std::string(path)); | 385 | const auto full_path = FS::SanitizePath(this->path + DIR_SEP + std::string(path)); |
| 361 | return base.CreateDirectory(full_path, perms); | 386 | return base.CreateDirectory(full_path, perms); |
| 362 | } | 387 | } |
| 363 | 388 | ||
| 364 | bool RealVfsDirectory::DeleteSubdirectoryRecursive(std::string_view name) { | 389 | bool RealVfsDirectory::DeleteSubdirectoryRecursive(std::string_view name) { |
| 365 | auto full_path = FileUtil::SanitizePath(this->path + DIR_SEP + std::string(name)); | 390 | const auto full_path = FS::SanitizePath(this->path + DIR_SEP + std::string(name)); |
| 366 | return base.DeleteDirectory(full_path); | 391 | return base.DeleteDirectory(full_path); |
| 367 | } | 392 | } |
| 368 | 393 | ||
| @@ -387,8 +412,9 @@ std::string RealVfsDirectory::GetName() const { | |||
| 387 | } | 412 | } |
| 388 | 413 | ||
| 389 | std::shared_ptr<VfsDirectory> RealVfsDirectory::GetParentDirectory() const { | 414 | std::shared_ptr<VfsDirectory> RealVfsDirectory::GetParentDirectory() const { |
| 390 | if (path_components.size() <= 1) | 415 | if (path_components.size() <= 1) { |
| 391 | return nullptr; | 416 | return nullptr; |
| 417 | } | ||
| 392 | 418 | ||
| 393 | return base.OpenDirectory(parent_path, perms); | 419 | return base.OpenDirectory(parent_path, perms); |
| 394 | } | 420 | } |
| @@ -425,16 +451,17 @@ std::string RealVfsDirectory::GetFullPath() const { | |||
| 425 | } | 451 | } |
| 426 | 452 | ||
| 427 | std::map<std::string, VfsEntryType, std::less<>> RealVfsDirectory::GetEntries() const { | 453 | std::map<std::string, VfsEntryType, std::less<>> RealVfsDirectory::GetEntries() const { |
| 428 | if (perms == Mode::Append) | 454 | if (perms == Mode::Append) { |
| 429 | return {}; | 455 | return {}; |
| 456 | } | ||
| 430 | 457 | ||
| 431 | std::map<std::string, VfsEntryType, std::less<>> out; | 458 | std::map<std::string, VfsEntryType, std::less<>> out; |
| 432 | FileUtil::ForeachDirectoryEntry( | 459 | FS::ForeachDirectoryEntry( |
| 433 | nullptr, path, | 460 | nullptr, path, |
| 434 | [&out](u64* entries_out, const std::string& directory, const std::string& filename) { | 461 | [&out](u64* entries_out, const std::string& directory, const std::string& filename) { |
| 435 | const std::string full_path = directory + DIR_SEP + filename; | 462 | const std::string full_path = directory + DIR_SEP + filename; |
| 436 | out.emplace(filename, FileUtil::IsDirectory(full_path) ? VfsEntryType::Directory | 463 | out.emplace(filename, |
| 437 | : VfsEntryType::File); | 464 | FS::IsDirectory(full_path) ? VfsEntryType::Directory : VfsEntryType::File); |
| 438 | return true; | 465 | return true; |
| 439 | }); | 466 | }); |
| 440 | 467 | ||
diff --git a/src/core/file_sys/vfs_real.h b/src/core/file_sys/vfs_real.h index a0a857a31..0b537b22c 100644 --- a/src/core/file_sys/vfs_real.h +++ b/src/core/file_sys/vfs_real.h | |||
| @@ -9,7 +9,7 @@ | |||
| 9 | #include "core/file_sys/mode.h" | 9 | #include "core/file_sys/mode.h" |
| 10 | #include "core/file_sys/vfs.h" | 10 | #include "core/file_sys/vfs.h" |
| 11 | 11 | ||
| 12 | namespace FileUtil { | 12 | namespace Common::FS { |
| 13 | class IOFile; | 13 | class IOFile; |
| 14 | } | 14 | } |
| 15 | 15 | ||
| @@ -36,7 +36,7 @@ public: | |||
| 36 | bool DeleteDirectory(std::string_view path) override; | 36 | bool DeleteDirectory(std::string_view path) override; |
| 37 | 37 | ||
| 38 | private: | 38 | private: |
| 39 | boost::container::flat_map<std::string, std::weak_ptr<FileUtil::IOFile>> cache; | 39 | boost::container::flat_map<std::string, std::weak_ptr<Common::FS::IOFile>> cache; |
| 40 | }; | 40 | }; |
| 41 | 41 | ||
| 42 | // An implmentation of VfsFile that represents a file on the user's computer. | 42 | // An implmentation of VfsFile that represents a file on the user's computer. |
| @@ -58,13 +58,13 @@ public: | |||
| 58 | bool Rename(std::string_view name) override; | 58 | bool Rename(std::string_view name) override; |
| 59 | 59 | ||
| 60 | private: | 60 | private: |
| 61 | RealVfsFile(RealVfsFilesystem& base, std::shared_ptr<FileUtil::IOFile> backing, | 61 | RealVfsFile(RealVfsFilesystem& base, std::shared_ptr<Common::FS::IOFile> backing, |
| 62 | const std::string& path, Mode perms = Mode::Read); | 62 | const std::string& path, Mode perms = Mode::Read); |
| 63 | 63 | ||
| 64 | bool Close(); | 64 | bool Close(); |
| 65 | 65 | ||
| 66 | RealVfsFilesystem& base; | 66 | RealVfsFilesystem& base; |
| 67 | std::shared_ptr<FileUtil::IOFile> backing; | 67 | std::shared_ptr<Common::FS::IOFile> backing; |
| 68 | std::string path; | 68 | std::string path; |
| 69 | std::string parent_path; | 69 | std::string parent_path; |
| 70 | std::vector<std::string> path_components; | 70 | std::vector<std::string> path_components; |
diff --git a/src/core/file_sys/vfs_vector.h b/src/core/file_sys/vfs_vector.h index ac36cb2ee..95d3da2f2 100644 --- a/src/core/file_sys/vfs_vector.h +++ b/src/core/file_sys/vfs_vector.h | |||
| @@ -4,7 +4,11 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <array> | ||
| 7 | #include <cstring> | 8 | #include <cstring> |
| 9 | #include <memory> | ||
| 10 | #include <string> | ||
| 11 | #include <vector> | ||
| 8 | #include "core/file_sys/vfs.h" | 12 | #include "core/file_sys/vfs.h" |
| 9 | 13 | ||
| 10 | namespace FileSys { | 14 | namespace FileSys { |
| @@ -13,7 +17,8 @@ namespace FileSys { | |||
| 13 | template <std::size_t size> | 17 | template <std::size_t size> |
| 14 | class ArrayVfsFile : public VfsFile { | 18 | class ArrayVfsFile : public VfsFile { |
| 15 | public: | 19 | public: |
| 16 | ArrayVfsFile(std::array<u8, size> data, std::string name = "", VirtualDir parent = nullptr) | 20 | explicit ArrayVfsFile(const std::array<u8, size>& data, std::string name = "", |
| 21 | VirtualDir parent = nullptr) | ||
| 17 | : data(data), name(std::move(name)), parent(std::move(parent)) {} | 22 | : data(data), name(std::move(name)), parent(std::move(parent)) {} |
| 18 | 23 | ||
| 19 | std::string GetName() const override { | 24 | std::string GetName() const override { |
| @@ -61,6 +66,12 @@ private: | |||
| 61 | VirtualDir parent; | 66 | VirtualDir parent; |
| 62 | }; | 67 | }; |
| 63 | 68 | ||
| 69 | template <std::size_t Size, typename... Args> | ||
| 70 | std::shared_ptr<ArrayVfsFile<Size>> MakeArrayFile(const std::array<u8, Size>& data, | ||
| 71 | Args&&... args) { | ||
| 72 | return std::make_shared<ArrayVfsFile<Size>>(data, std::forward<Args>(args)...); | ||
| 73 | } | ||
| 74 | |||
| 64 | // An implementation of VfsFile that is backed by a vector optionally supplied upon construction | 75 | // An implementation of VfsFile that is backed by a vector optionally supplied upon construction |
| 65 | class VectorVfsFile : public VfsFile { | 76 | class VectorVfsFile : public VfsFile { |
| 66 | public: | 77 | public: |
diff --git a/src/core/file_sys/xts_archive.cpp b/src/core/file_sys/xts_archive.cpp index 81413c684..ccf5966d0 100644 --- a/src/core/file_sys/xts_archive.cpp +++ b/src/core/file_sys/xts_archive.cpp | |||
| @@ -44,7 +44,7 @@ static bool CalculateHMAC256(Destination* out, const SourceKey* key, std::size_t | |||
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | NAX::NAX(VirtualFile file_) : header(std::make_unique<NAXHeader>()), file(std::move(file_)) { | 46 | NAX::NAX(VirtualFile file_) : header(std::make_unique<NAXHeader>()), file(std::move(file_)) { |
| 47 | std::string path = FileUtil::SanitizePath(file->GetFullPath()); | 47 | std::string path = Common::FS::SanitizePath(file->GetFullPath()); |
| 48 | static const std::regex nax_path_regex("/registered/(000000[0-9A-F]{2})/([0-9A-F]{32})\\.nca", | 48 | static const std::regex nax_path_regex("/registered/(000000[0-9A-F]{2})/([0-9A-F]{32})\\.nca", |
| 49 | std::regex_constants::ECMAScript | | 49 | std::regex_constants::ECMAScript | |
| 50 | std::regex_constants::icase); | 50 | std::regex_constants::icase); |
diff --git a/src/core/frontend/emu_window.h b/src/core/frontend/emu_window.h index 13aa14934..3e8780243 100644 --- a/src/core/frontend/emu_window.h +++ b/src/core/frontend/emu_window.h | |||
| @@ -39,7 +39,7 @@ public: | |||
| 39 | 39 | ||
| 40 | class Scoped { | 40 | class Scoped { |
| 41 | public: | 41 | public: |
| 42 | explicit Scoped(GraphicsContext& context_) : context(context_) { | 42 | [[nodiscard]] explicit Scoped(GraphicsContext& context_) : context(context_) { |
| 43 | context.MakeCurrent(); | 43 | context.MakeCurrent(); |
| 44 | } | 44 | } |
| 45 | ~Scoped() { | 45 | ~Scoped() { |
| @@ -52,7 +52,7 @@ public: | |||
| 52 | 52 | ||
| 53 | /// Calls MakeCurrent on the context and calls DoneCurrent when the scope for the returned value | 53 | /// Calls MakeCurrent on the context and calls DoneCurrent when the scope for the returned value |
| 54 | /// ends | 54 | /// ends |
| 55 | Scoped Acquire() { | 55 | [[nodiscard]] Scoped Acquire() { |
| 56 | return Scoped{*this}; | 56 | return Scoped{*this}; |
| 57 | } | 57 | } |
| 58 | }; | 58 | }; |
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp index df0debe1b..b882eaa0f 100644 --- a/src/core/hle/kernel/address_arbiter.cpp +++ b/src/core/hle/kernel/address_arbiter.cpp | |||
| @@ -81,7 +81,7 @@ ResultCode AddressArbiter::IncrementAndSignalToAddressIfEqual(VAddr address, s32 | |||
| 81 | do { | 81 | do { |
| 82 | current_value = monitor.ExclusiveRead32(current_core, address); | 82 | current_value = monitor.ExclusiveRead32(current_core, address); |
| 83 | 83 | ||
| 84 | if (current_value != value) { | 84 | if (current_value != static_cast<u32>(value)) { |
| 85 | return ERR_INVALID_STATE; | 85 | return ERR_INVALID_STATE; |
| 86 | } | 86 | } |
| 87 | current_value++; | 87 | current_value++; |
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp index 9277b5d08..81f85643b 100644 --- a/src/core/hle/kernel/hle_ipc.cpp +++ b/src/core/hle/kernel/hle_ipc.cpp | |||
| @@ -293,13 +293,15 @@ std::vector<u8> HLERequestContext::ReadBuffer(std::size_t buffer_index) const { | |||
| 293 | BufferDescriptorA()[buffer_index].Size()}; | 293 | BufferDescriptorA()[buffer_index].Size()}; |
| 294 | 294 | ||
| 295 | if (is_buffer_a) { | 295 | if (is_buffer_a) { |
| 296 | ASSERT_OR_EXECUTE_MSG(BufferDescriptorA().size() > buffer_index, { return buffer; }, | 296 | ASSERT_OR_EXECUTE_MSG( |
| 297 | "BufferDescriptorA invalid buffer_index {}", buffer_index); | 297 | BufferDescriptorA().size() > buffer_index, { return buffer; }, |
| 298 | "BufferDescriptorA invalid buffer_index {}", buffer_index); | ||
| 298 | buffer.resize(BufferDescriptorA()[buffer_index].Size()); | 299 | buffer.resize(BufferDescriptorA()[buffer_index].Size()); |
| 299 | memory.ReadBlock(BufferDescriptorA()[buffer_index].Address(), buffer.data(), buffer.size()); | 300 | memory.ReadBlock(BufferDescriptorA()[buffer_index].Address(), buffer.data(), buffer.size()); |
| 300 | } else { | 301 | } else { |
| 301 | ASSERT_OR_EXECUTE_MSG(BufferDescriptorX().size() > buffer_index, { return buffer; }, | 302 | ASSERT_OR_EXECUTE_MSG( |
| 302 | "BufferDescriptorX invalid buffer_index {}", buffer_index); | 303 | BufferDescriptorX().size() > buffer_index, { return buffer; }, |
| 304 | "BufferDescriptorX invalid buffer_index {}", buffer_index); | ||
| 303 | buffer.resize(BufferDescriptorX()[buffer_index].Size()); | 305 | buffer.resize(BufferDescriptorX()[buffer_index].Size()); |
| 304 | memory.ReadBlock(BufferDescriptorX()[buffer_index].Address(), buffer.data(), buffer.size()); | 306 | memory.ReadBlock(BufferDescriptorX()[buffer_index].Address(), buffer.data(), buffer.size()); |
| 305 | } | 307 | } |
| @@ -324,16 +326,16 @@ std::size_t HLERequestContext::WriteBuffer(const void* buffer, std::size_t size, | |||
| 324 | } | 326 | } |
| 325 | 327 | ||
| 326 | if (is_buffer_b) { | 328 | if (is_buffer_b) { |
| 327 | ASSERT_OR_EXECUTE_MSG(BufferDescriptorB().size() > buffer_index && | 329 | ASSERT_OR_EXECUTE_MSG( |
| 328 | BufferDescriptorB()[buffer_index].Size() >= size, | 330 | BufferDescriptorB().size() > buffer_index && |
| 329 | { return 0; }, "BufferDescriptorB is invalid, index={}, size={}", | 331 | BufferDescriptorB()[buffer_index].Size() >= size, |
| 330 | buffer_index, size); | 332 | { return 0; }, "BufferDescriptorB is invalid, index={}, size={}", buffer_index, size); |
| 331 | memory.WriteBlock(BufferDescriptorB()[buffer_index].Address(), buffer, size); | 333 | memory.WriteBlock(BufferDescriptorB()[buffer_index].Address(), buffer, size); |
| 332 | } else { | 334 | } else { |
| 333 | ASSERT_OR_EXECUTE_MSG(BufferDescriptorC().size() > buffer_index && | 335 | ASSERT_OR_EXECUTE_MSG( |
| 334 | BufferDescriptorC()[buffer_index].Size() >= size, | 336 | BufferDescriptorC().size() > buffer_index && |
| 335 | { return 0; }, "BufferDescriptorC is invalid, index={}, size={}", | 337 | BufferDescriptorC()[buffer_index].Size() >= size, |
| 336 | buffer_index, size); | 338 | { return 0; }, "BufferDescriptorC is invalid, index={}, size={}", buffer_index, size); |
| 337 | memory.WriteBlock(BufferDescriptorC()[buffer_index].Address(), buffer, size); | 339 | memory.WriteBlock(BufferDescriptorC()[buffer_index].Address(), buffer, size); |
| 338 | } | 340 | } |
| 339 | 341 | ||
| @@ -344,12 +346,14 @@ std::size_t HLERequestContext::GetReadBufferSize(std::size_t buffer_index) const | |||
| 344 | const bool is_buffer_a{BufferDescriptorA().size() > buffer_index && | 346 | const bool is_buffer_a{BufferDescriptorA().size() > buffer_index && |
| 345 | BufferDescriptorA()[buffer_index].Size()}; | 347 | BufferDescriptorA()[buffer_index].Size()}; |
| 346 | if (is_buffer_a) { | 348 | if (is_buffer_a) { |
| 347 | ASSERT_OR_EXECUTE_MSG(BufferDescriptorA().size() > buffer_index, { return 0; }, | 349 | ASSERT_OR_EXECUTE_MSG( |
| 348 | "BufferDescriptorA invalid buffer_index {}", buffer_index); | 350 | BufferDescriptorA().size() > buffer_index, { return 0; }, |
| 351 | "BufferDescriptorA invalid buffer_index {}", buffer_index); | ||
| 349 | return BufferDescriptorA()[buffer_index].Size(); | 352 | return BufferDescriptorA()[buffer_index].Size(); |
| 350 | } else { | 353 | } else { |
| 351 | ASSERT_OR_EXECUTE_MSG(BufferDescriptorX().size() > buffer_index, { return 0; }, | 354 | ASSERT_OR_EXECUTE_MSG( |
| 352 | "BufferDescriptorX invalid buffer_index {}", buffer_index); | 355 | BufferDescriptorX().size() > buffer_index, { return 0; }, |
| 356 | "BufferDescriptorX invalid buffer_index {}", buffer_index); | ||
| 353 | return BufferDescriptorX()[buffer_index].Size(); | 357 | return BufferDescriptorX()[buffer_index].Size(); |
| 354 | } | 358 | } |
| 355 | } | 359 | } |
| @@ -358,12 +362,14 @@ std::size_t HLERequestContext::GetWriteBufferSize(std::size_t buffer_index) cons | |||
| 358 | const bool is_buffer_b{BufferDescriptorB().size() > buffer_index && | 362 | const bool is_buffer_b{BufferDescriptorB().size() > buffer_index && |
| 359 | BufferDescriptorB()[buffer_index].Size()}; | 363 | BufferDescriptorB()[buffer_index].Size()}; |
| 360 | if (is_buffer_b) { | 364 | if (is_buffer_b) { |
| 361 | ASSERT_OR_EXECUTE_MSG(BufferDescriptorB().size() > buffer_index, { return 0; }, | 365 | ASSERT_OR_EXECUTE_MSG( |
| 362 | "BufferDescriptorB invalid buffer_index {}", buffer_index); | 366 | BufferDescriptorB().size() > buffer_index, { return 0; }, |
| 367 | "BufferDescriptorB invalid buffer_index {}", buffer_index); | ||
| 363 | return BufferDescriptorB()[buffer_index].Size(); | 368 | return BufferDescriptorB()[buffer_index].Size(); |
| 364 | } else { | 369 | } else { |
| 365 | ASSERT_OR_EXECUTE_MSG(BufferDescriptorC().size() > buffer_index, { return 0; }, | 370 | ASSERT_OR_EXECUTE_MSG( |
| 366 | "BufferDescriptorC invalid buffer_index {}", buffer_index); | 371 | BufferDescriptorC().size() > buffer_index, { return 0; }, |
| 372 | "BufferDescriptorC invalid buffer_index {}", buffer_index); | ||
| 367 | return BufferDescriptorC()[buffer_index].Size(); | 373 | return BufferDescriptorC()[buffer_index].Size(); |
| 368 | } | 374 | } |
| 369 | return 0; | 375 | return 0; |
diff --git a/src/core/hle/kernel/memory/page_table.cpp b/src/core/hle/kernel/memory/page_table.cpp index 5d6aac00f..a3fadb533 100644 --- a/src/core/hle/kernel/memory/page_table.cpp +++ b/src/core/hle/kernel/memory/page_table.cpp | |||
| @@ -604,7 +604,6 @@ ResultCode PageTable::MapPages(VAddr addr, const PageLinkedList& page_linked_lis | |||
| 604 | if (const auto result{ | 604 | if (const auto result{ |
| 605 | Operate(cur_addr, node.GetNumPages(), perm, OperationType::Map, node.GetAddress())}; | 605 | Operate(cur_addr, node.GetNumPages(), perm, OperationType::Map, node.GetAddress())}; |
| 606 | result.IsError()) { | 606 | result.IsError()) { |
| 607 | const MemoryInfo info{block_manager->FindBlock(cur_addr).GetMemoryInfo()}; | ||
| 608 | const std::size_t num_pages{(addr - cur_addr) / PageSize}; | 607 | const std::size_t num_pages{(addr - cur_addr) / PageSize}; |
| 609 | 608 | ||
| 610 | ASSERT( | 609 | ASSERT( |
| @@ -852,11 +851,12 @@ ResultCode PageTable::LockForDeviceAddressSpace(VAddr addr, std::size_t size) { | |||
| 852 | return result; | 851 | return result; |
| 853 | } | 852 | } |
| 854 | 853 | ||
| 855 | block_manager->UpdateLock(addr, size / PageSize, | 854 | block_manager->UpdateLock( |
| 856 | [](MemoryBlockManager::iterator block, MemoryPermission perm) { | 855 | addr, size / PageSize, |
| 857 | block->ShareToDevice(perm); | 856 | [](MemoryBlockManager::iterator block, MemoryPermission perm) { |
| 858 | }, | 857 | block->ShareToDevice(perm); |
| 859 | perm); | 858 | }, |
| 859 | perm); | ||
| 860 | 860 | ||
| 861 | return RESULT_SUCCESS; | 861 | return RESULT_SUCCESS; |
| 862 | } | 862 | } |
| @@ -874,11 +874,12 @@ ResultCode PageTable::UnlockForDeviceAddressSpace(VAddr addr, std::size_t size) | |||
| 874 | return result; | 874 | return result; |
| 875 | } | 875 | } |
| 876 | 876 | ||
| 877 | block_manager->UpdateLock(addr, size / PageSize, | 877 | block_manager->UpdateLock( |
| 878 | [](MemoryBlockManager::iterator block, MemoryPermission perm) { | 878 | addr, size / PageSize, |
| 879 | block->UnshareToDevice(perm); | 879 | [](MemoryBlockManager::iterator block, MemoryPermission perm) { |
| 880 | }, | 880 | block->UnshareToDevice(perm); |
| 881 | perm); | 881 | }, |
| 882 | perm); | ||
| 882 | 883 | ||
| 883 | return RESULT_SUCCESS; | 884 | return RESULT_SUCCESS; |
| 884 | } | 885 | } |
diff --git a/src/core/hle/kernel/memory/system_control.cpp b/src/core/hle/kernel/memory/system_control.cpp index 2f98e9c4c..11d204bc2 100644 --- a/src/core/hle/kernel/memory/system_control.cpp +++ b/src/core/hle/kernel/memory/system_control.cpp | |||
| @@ -7,22 +7,15 @@ | |||
| 7 | #include "core/hle/kernel/memory/system_control.h" | 7 | #include "core/hle/kernel/memory/system_control.h" |
| 8 | 8 | ||
| 9 | namespace Kernel::Memory::SystemControl { | 9 | namespace Kernel::Memory::SystemControl { |
| 10 | 10 | namespace { | |
| 11 | u64 GenerateRandomU64ForInit() { | ||
| 12 | static std::random_device device; | ||
| 13 | static std::mt19937 gen(device()); | ||
| 14 | static std::uniform_int_distribution<u64> distribution(1, std::numeric_limits<u64>::max()); | ||
| 15 | return distribution(gen); | ||
| 16 | } | ||
| 17 | |||
| 18 | template <typename F> | 11 | template <typename F> |
| 19 | u64 GenerateUniformRange(u64 min, u64 max, F f) { | 12 | u64 GenerateUniformRange(u64 min, u64 max, F f) { |
| 20 | /* Handle the case where the difference is too large to represent. */ | 13 | // Handle the case where the difference is too large to represent. |
| 21 | if (max == std::numeric_limits<u64>::max() && min == std::numeric_limits<u64>::min()) { | 14 | if (max == std::numeric_limits<u64>::max() && min == std::numeric_limits<u64>::min()) { |
| 22 | return f(); | 15 | return f(); |
| 23 | } | 16 | } |
| 24 | 17 | ||
| 25 | /* Iterate until we get a value in range. */ | 18 | // Iterate until we get a value in range. |
| 26 | const u64 range_size = ((max + 1) - min); | 19 | const u64 range_size = ((max + 1) - min); |
| 27 | const u64 effective_max = (std::numeric_limits<u64>::max() / range_size) * range_size; | 20 | const u64 effective_max = (std::numeric_limits<u64>::max() / range_size) * range_size; |
| 28 | while (true) { | 21 | while (true) { |
| @@ -32,6 +25,14 @@ u64 GenerateUniformRange(u64 min, u64 max, F f) { | |||
| 32 | } | 25 | } |
| 33 | } | 26 | } |
| 34 | 27 | ||
| 28 | u64 GenerateRandomU64ForInit() { | ||
| 29 | static std::random_device device; | ||
| 30 | static std::mt19937 gen(device()); | ||
| 31 | static std::uniform_int_distribution<u64> distribution(1, std::numeric_limits<u64>::max()); | ||
| 32 | return distribution(gen); | ||
| 33 | } | ||
| 34 | } // Anonymous namespace | ||
| 35 | |||
| 35 | u64 GenerateRandomRange(u64 min, u64 max) { | 36 | u64 GenerateRandomRange(u64 min, u64 max) { |
| 36 | return GenerateUniformRange(min, max, GenerateRandomU64ForInit); | 37 | return GenerateUniformRange(min, max, GenerateRandomU64ForInit); |
| 37 | } | 38 | } |
diff --git a/src/core/hle/kernel/memory/system_control.h b/src/core/hle/kernel/memory/system_control.h index 3fa93111d..19cab8cbc 100644 --- a/src/core/hle/kernel/memory/system_control.h +++ b/src/core/hle/kernel/memory/system_control.h | |||
| @@ -8,11 +8,6 @@ | |||
| 8 | 8 | ||
| 9 | namespace Kernel::Memory::SystemControl { | 9 | namespace Kernel::Memory::SystemControl { |
| 10 | 10 | ||
| 11 | u64 GenerateRandomU64ForInit(); | ||
| 12 | |||
| 13 | template <typename F> | ||
| 14 | u64 GenerateUniformRange(u64 min, u64 max, F f); | ||
| 15 | |||
| 16 | u64 GenerateRandomRange(u64 min, u64 max); | 11 | u64 GenerateRandomRange(u64 min, u64 max); |
| 17 | 12 | ||
| 18 | } // namespace Kernel::Memory::SystemControl | 13 | } // namespace Kernel::Memory::SystemControl |
diff --git a/src/core/hle/kernel/scheduler.cpp b/src/core/hle/kernel/scheduler.cpp index f93e5e4b0..a4b234424 100644 --- a/src/core/hle/kernel/scheduler.cpp +++ b/src/core/hle/kernel/scheduler.cpp | |||
| @@ -131,7 +131,8 @@ u32 GlobalScheduler::SelectThreads() { | |||
| 131 | u32 cores_needing_context_switch{}; | 131 | u32 cores_needing_context_switch{}; |
| 132 | for (u32 core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) { | 132 | for (u32 core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) { |
| 133 | Scheduler& sched = kernel.Scheduler(core); | 133 | Scheduler& sched = kernel.Scheduler(core); |
| 134 | ASSERT(top_threads[core] == nullptr || top_threads[core]->GetProcessorID() == core); | 134 | ASSERT(top_threads[core] == nullptr || |
| 135 | static_cast<u32>(top_threads[core]->GetProcessorID()) == core); | ||
| 135 | if (update_thread(top_threads[core], sched)) { | 136 | if (update_thread(top_threads[core], sched)) { |
| 136 | cores_needing_context_switch |= (1ul << core); | 137 | cores_needing_context_switch |= (1ul << core); |
| 137 | } | 138 | } |
| @@ -663,32 +664,26 @@ void Scheduler::Reload() { | |||
| 663 | } | 664 | } |
| 664 | 665 | ||
| 665 | void Scheduler::SwitchContextStep2() { | 666 | void Scheduler::SwitchContextStep2() { |
| 666 | Thread* previous_thread = current_thread_prev.get(); | ||
| 667 | Thread* new_thread = selected_thread.get(); | ||
| 668 | |||
| 669 | // Load context of new thread | 667 | // Load context of new thread |
| 670 | Process* const previous_process = | 668 | if (selected_thread) { |
| 671 | previous_thread != nullptr ? previous_thread->GetOwnerProcess() : nullptr; | 669 | ASSERT_MSG(selected_thread->GetSchedulingStatus() == ThreadSchedStatus::Runnable, |
| 672 | |||
| 673 | if (new_thread) { | ||
| 674 | ASSERT_MSG(new_thread->GetSchedulingStatus() == ThreadSchedStatus::Runnable, | ||
| 675 | "Thread must be runnable."); | 670 | "Thread must be runnable."); |
| 676 | 671 | ||
| 677 | // Cancel any outstanding wakeup events for this thread | 672 | // Cancel any outstanding wakeup events for this thread |
| 678 | new_thread->SetIsRunning(true); | 673 | selected_thread->SetIsRunning(true); |
| 679 | new_thread->last_running_ticks = system.CoreTiming().GetCPUTicks(); | 674 | selected_thread->last_running_ticks = system.CoreTiming().GetCPUTicks(); |
| 680 | new_thread->SetWasRunning(false); | 675 | selected_thread->SetWasRunning(false); |
| 681 | 676 | ||
| 682 | auto* const thread_owner_process = current_thread->GetOwnerProcess(); | 677 | auto* const thread_owner_process = current_thread->GetOwnerProcess(); |
| 683 | if (thread_owner_process != nullptr) { | 678 | if (thread_owner_process != nullptr) { |
| 684 | system.Kernel().MakeCurrentProcess(thread_owner_process); | 679 | system.Kernel().MakeCurrentProcess(thread_owner_process); |
| 685 | } | 680 | } |
| 686 | if (!new_thread->IsHLEThread()) { | 681 | if (!selected_thread->IsHLEThread()) { |
| 687 | Core::ARM_Interface& cpu_core = new_thread->ArmInterface(); | 682 | Core::ARM_Interface& cpu_core = selected_thread->ArmInterface(); |
| 688 | cpu_core.LoadContext(new_thread->GetContext32()); | 683 | cpu_core.LoadContext(selected_thread->GetContext32()); |
| 689 | cpu_core.LoadContext(new_thread->GetContext64()); | 684 | cpu_core.LoadContext(selected_thread->GetContext64()); |
| 690 | cpu_core.SetTlsAddress(new_thread->GetTLSAddress()); | 685 | cpu_core.SetTlsAddress(selected_thread->GetTLSAddress()); |
| 691 | cpu_core.SetTPIDR_EL0(new_thread->GetTPIDR_EL0()); | 686 | cpu_core.SetTPIDR_EL0(selected_thread->GetTPIDR_EL0()); |
| 692 | cpu_core.ChangeProcessorID(this->core_id); | 687 | cpu_core.ChangeProcessorID(this->core_id); |
| 693 | cpu_core.ClearExclusiveState(); | 688 | cpu_core.ClearExclusiveState(); |
| 694 | } | 689 | } |
diff --git a/src/core/hle/kernel/scheduler.h b/src/core/hle/kernel/scheduler.h index b3b4b5169..36e3c26fb 100644 --- a/src/core/hle/kernel/scheduler.h +++ b/src/core/hle/kernel/scheduler.h | |||
| @@ -289,7 +289,7 @@ private: | |||
| 289 | 289 | ||
| 290 | class SchedulerLock { | 290 | class SchedulerLock { |
| 291 | public: | 291 | public: |
| 292 | explicit SchedulerLock(KernelCore& kernel); | 292 | [[nodiscard]] explicit SchedulerLock(KernelCore& kernel); |
| 293 | ~SchedulerLock(); | 293 | ~SchedulerLock(); |
| 294 | 294 | ||
| 295 | protected: | 295 | protected: |
diff --git a/src/core/hle/result.h b/src/core/hle/result.h index 450f61fea..b6bdbd988 100644 --- a/src/core/hle/result.h +++ b/src/core/hle/result.h | |||
| @@ -342,8 +342,9 @@ ResultVal<std::remove_reference_t<Arg>> MakeResult(Arg&& arg) { | |||
| 342 | */ | 342 | */ |
| 343 | #define CASCADE_RESULT(target, source) \ | 343 | #define CASCADE_RESULT(target, source) \ |
| 344 | auto CONCAT2(check_result_L, __LINE__) = source; \ | 344 | auto CONCAT2(check_result_L, __LINE__) = source; \ |
| 345 | if (CONCAT2(check_result_L, __LINE__).Failed()) \ | 345 | if (CONCAT2(check_result_L, __LINE__).Failed()) { \ |
| 346 | return CONCAT2(check_result_L, __LINE__).Code(); \ | 346 | return CONCAT2(check_result_L, __LINE__).Code(); \ |
| 347 | } \ | ||
| 347 | target = std::move(*CONCAT2(check_result_L, __LINE__)) | 348 | target = std::move(*CONCAT2(check_result_L, __LINE__)) |
| 348 | 349 | ||
| 349 | /** | 350 | /** |
| @@ -351,6 +352,9 @@ ResultVal<std::remove_reference_t<Arg>> MakeResult(Arg&& arg) { | |||
| 351 | * non-success, or discarded otherwise. | 352 | * non-success, or discarded otherwise. |
| 352 | */ | 353 | */ |
| 353 | #define CASCADE_CODE(source) \ | 354 | #define CASCADE_CODE(source) \ |
| 354 | auto CONCAT2(check_result_L, __LINE__) = source; \ | 355 | do { \ |
| 355 | if (CONCAT2(check_result_L, __LINE__).IsError()) \ | 356 | auto CONCAT2(check_result_L, __LINE__) = source; \ |
| 356 | return CONCAT2(check_result_L, __LINE__); | 357 | if (CONCAT2(check_result_L, __LINE__).IsError()) { \ |
| 358 | return CONCAT2(check_result_L, __LINE__); \ | ||
| 359 | } \ | ||
| 360 | } while (false) | ||
diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp index 63e4aeca0..eb54cb123 100644 --- a/src/core/hle/service/acc/acc.cpp +++ b/src/core/hle/service/acc/acc.cpp | |||
| @@ -35,7 +35,7 @@ constexpr ResultCode ERR_INVALID_BUFFER_SIZE{ErrorModule::Account, 30}; | |||
| 35 | constexpr ResultCode ERR_FAILED_SAVE_DATA{ErrorModule::Account, 100}; | 35 | constexpr ResultCode ERR_FAILED_SAVE_DATA{ErrorModule::Account, 100}; |
| 36 | 36 | ||
| 37 | static std::string GetImagePath(Common::UUID uuid) { | 37 | static std::string GetImagePath(Common::UUID uuid) { |
| 38 | return FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) + | 38 | return Common::FS::GetUserPath(Common::FS::UserPath::NANDDir) + |
| 39 | "/system/save/8000000000000010/su/avators/" + uuid.FormatSwitch() + ".jpg"; | 39 | "/system/save/8000000000000010/su/avators/" + uuid.FormatSwitch() + ".jpg"; |
| 40 | } | 40 | } |
| 41 | 41 | ||
| @@ -318,7 +318,7 @@ protected: | |||
| 318 | IPC::ResponseBuilder rb{ctx, 3}; | 318 | IPC::ResponseBuilder rb{ctx, 3}; |
| 319 | rb.Push(RESULT_SUCCESS); | 319 | rb.Push(RESULT_SUCCESS); |
| 320 | 320 | ||
| 321 | const FileUtil::IOFile image(GetImagePath(user_id), "rb"); | 321 | const Common::FS::IOFile image(GetImagePath(user_id), "rb"); |
| 322 | if (!image.IsOpen()) { | 322 | if (!image.IsOpen()) { |
| 323 | LOG_WARNING(Service_ACC, | 323 | LOG_WARNING(Service_ACC, |
| 324 | "Failed to load user provided image! Falling back to built-in backup..."); | 324 | "Failed to load user provided image! Falling back to built-in backup..."); |
| @@ -340,7 +340,7 @@ protected: | |||
| 340 | IPC::ResponseBuilder rb{ctx, 3}; | 340 | IPC::ResponseBuilder rb{ctx, 3}; |
| 341 | rb.Push(RESULT_SUCCESS); | 341 | rb.Push(RESULT_SUCCESS); |
| 342 | 342 | ||
| 343 | const FileUtil::IOFile image(GetImagePath(user_id), "rb"); | 343 | const Common::FS::IOFile image(GetImagePath(user_id), "rb"); |
| 344 | 344 | ||
| 345 | if (!image.IsOpen()) { | 345 | if (!image.IsOpen()) { |
| 346 | LOG_WARNING(Service_ACC, | 346 | LOG_WARNING(Service_ACC, |
| @@ -405,7 +405,7 @@ protected: | |||
| 405 | ProfileData data; | 405 | ProfileData data; |
| 406 | std::memcpy(&data, user_data.data(), sizeof(ProfileData)); | 406 | std::memcpy(&data, user_data.data(), sizeof(ProfileData)); |
| 407 | 407 | ||
| 408 | FileUtil::IOFile image(GetImagePath(user_id), "wb"); | 408 | Common::FS::IOFile image(GetImagePath(user_id), "wb"); |
| 409 | 409 | ||
| 410 | if (!image.IsOpen() || !image.Resize(image_data.size()) || | 410 | if (!image.IsOpen() || !image.Resize(image_data.size()) || |
| 411 | image.WriteBytes(image_data.data(), image_data.size()) != image_data.size() || | 411 | image.WriteBytes(image_data.data(), image_data.size()) != image_data.size() || |
diff --git a/src/core/hle/service/acc/profile_manager.cpp b/src/core/hle/service/acc/profile_manager.cpp index a98d57b5c..9b829e957 100644 --- a/src/core/hle/service/acc/profile_manager.cpp +++ b/src/core/hle/service/acc/profile_manager.cpp | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | 13 | ||
| 14 | namespace Service::Account { | 14 | namespace Service::Account { |
| 15 | 15 | ||
| 16 | namespace FS = Common::FS; | ||
| 16 | using Common::UUID; | 17 | using Common::UUID; |
| 17 | 18 | ||
| 18 | struct UserRaw { | 19 | struct UserRaw { |
| @@ -318,9 +319,8 @@ bool ProfileManager::SetProfileBaseAndData(Common::UUID uuid, const ProfileBase& | |||
| 318 | } | 319 | } |
| 319 | 320 | ||
| 320 | void ProfileManager::ParseUserSaveFile() { | 321 | void ProfileManager::ParseUserSaveFile() { |
| 321 | FileUtil::IOFile save(FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) + | 322 | const FS::IOFile save( |
| 322 | ACC_SAVE_AVATORS_BASE_PATH + "profiles.dat", | 323 | FS::GetUserPath(FS::UserPath::NANDDir) + ACC_SAVE_AVATORS_BASE_PATH + "profiles.dat", "rb"); |
| 323 | "rb"); | ||
| 324 | 324 | ||
| 325 | if (!save.IsOpen()) { | 325 | if (!save.IsOpen()) { |
| 326 | LOG_WARNING(Service_ACC, "Failed to load profile data from save data... Generating new " | 326 | LOG_WARNING(Service_ACC, "Failed to load profile data from save data... Generating new " |
| @@ -366,22 +366,22 @@ void ProfileManager::WriteUserSaveFile() { | |||
| 366 | }; | 366 | }; |
| 367 | } | 367 | } |
| 368 | 368 | ||
| 369 | const auto raw_path = | 369 | const auto raw_path = FS::GetUserPath(FS::UserPath::NANDDir) + "/system/save/8000000000000010"; |
| 370 | FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) + "/system/save/8000000000000010"; | 370 | if (FS::Exists(raw_path) && !FS::IsDirectory(raw_path)) { |
| 371 | if (FileUtil::Exists(raw_path) && !FileUtil::IsDirectory(raw_path)) | 371 | FS::Delete(raw_path); |
| 372 | FileUtil::Delete(raw_path); | 372 | } |
| 373 | 373 | ||
| 374 | const auto path = FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) + | 374 | const auto path = |
| 375 | ACC_SAVE_AVATORS_BASE_PATH + "profiles.dat"; | 375 | FS::GetUserPath(FS::UserPath::NANDDir) + ACC_SAVE_AVATORS_BASE_PATH + "profiles.dat"; |
| 376 | 376 | ||
| 377 | if (!FileUtil::CreateFullPath(path)) { | 377 | if (!FS::CreateFullPath(path)) { |
| 378 | LOG_WARNING(Service_ACC, "Failed to create full path of profiles.dat. Create the directory " | 378 | LOG_WARNING(Service_ACC, "Failed to create full path of profiles.dat. Create the directory " |
| 379 | "nand/system/save/8000000000000010/su/avators to mitigate this " | 379 | "nand/system/save/8000000000000010/su/avators to mitigate this " |
| 380 | "issue."); | 380 | "issue."); |
| 381 | return; | 381 | return; |
| 382 | } | 382 | } |
| 383 | 383 | ||
| 384 | FileUtil::IOFile save(path, "wb"); | 384 | FS::IOFile save(path, "wb"); |
| 385 | 385 | ||
| 386 | if (!save.IsOpen()) { | 386 | if (!save.IsOpen()) { |
| 387 | LOG_WARNING(Service_ACC, "Failed to write save data to file... No changes to user data " | 387 | LOG_WARNING(Service_ACC, "Failed to write save data to file... No changes to user data " |
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 55a1edf1a..7d92b25a3 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp | |||
| @@ -378,7 +378,11 @@ void ISelfController::GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& | |||
| 378 | } | 378 | } |
| 379 | 379 | ||
| 380 | void ISelfController::SetScreenShotPermission(Kernel::HLERequestContext& ctx) { | 380 | void ISelfController::SetScreenShotPermission(Kernel::HLERequestContext& ctx) { |
| 381 | LOG_WARNING(Service_AM, "(STUBBED) called"); | 381 | IPC::RequestParser rp{ctx}; |
| 382 | const auto permission = rp.PopEnum<ScreenshotPermission>(); | ||
| 383 | LOG_DEBUG(Service_AM, "called, permission={}", permission); | ||
| 384 | |||
| 385 | screenshot_permission = permission; | ||
| 382 | 386 | ||
| 383 | IPC::ResponseBuilder rb{ctx, 2}; | 387 | IPC::ResponseBuilder rb{ctx, 2}; |
| 384 | rb.Push(RESULT_SUCCESS); | 388 | rb.Push(RESULT_SUCCESS); |
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h index 6cfb11b48..6e69796ec 100644 --- a/src/core/hle/service/am/am.h +++ b/src/core/hle/service/am/am.h | |||
| @@ -149,6 +149,12 @@ private: | |||
| 149 | void GetAccumulatedSuspendedTickValue(Kernel::HLERequestContext& ctx); | 149 | void GetAccumulatedSuspendedTickValue(Kernel::HLERequestContext& ctx); |
| 150 | void GetAccumulatedSuspendedTickChangedEvent(Kernel::HLERequestContext& ctx); | 150 | void GetAccumulatedSuspendedTickChangedEvent(Kernel::HLERequestContext& ctx); |
| 151 | 151 | ||
| 152 | enum class ScreenshotPermission : u32 { | ||
| 153 | Inherit = 0, | ||
| 154 | Enable = 1, | ||
| 155 | Disable = 2, | ||
| 156 | }; | ||
| 157 | |||
| 152 | Core::System& system; | 158 | Core::System& system; |
| 153 | std::shared_ptr<NVFlinger::NVFlinger> nvflinger; | 159 | std::shared_ptr<NVFlinger::NVFlinger> nvflinger; |
| 154 | Kernel::EventPair launchable_event; | 160 | Kernel::EventPair launchable_event; |
| @@ -157,6 +163,7 @@ private: | |||
| 157 | u32 idle_time_detection_extension = 0; | 163 | u32 idle_time_detection_extension = 0; |
| 158 | u64 num_fatal_sections_entered = 0; | 164 | u64 num_fatal_sections_entered = 0; |
| 159 | bool is_auto_sleep_disabled = false; | 165 | bool is_auto_sleep_disabled = false; |
| 166 | ScreenshotPermission screenshot_permission = ScreenshotPermission::Inherit; | ||
| 160 | }; | 167 | }; |
| 161 | 168 | ||
| 162 | class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> { | 169 | class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> { |
diff --git a/src/core/hle/service/am/applets/software_keyboard.cpp b/src/core/hle/service/am/applets/software_keyboard.cpp index 289da2619..bdeb0737a 100644 --- a/src/core/hle/service/am/applets/software_keyboard.cpp +++ b/src/core/hle/service/am/applets/software_keyboard.cpp | |||
| @@ -122,8 +122,7 @@ void SoftwareKeyboard::ExecuteInteractive() { | |||
| 122 | 122 | ||
| 123 | switch (request) { | 123 | switch (request) { |
| 124 | case Request::Calc: { | 124 | case Request::Calc: { |
| 125 | broker.PushNormalDataFromApplet( | 125 | broker.PushNormalDataFromApplet(std::make_shared<IStorage>(std::vector<u8>{1})); |
| 126 | std::make_shared<IStorage>(std::move(std::vector<u8>{1}))); | ||
| 127 | broker.SignalStateChanged(); | 126 | broker.SignalStateChanged(); |
| 128 | break; | 127 | break; |
| 129 | } | 128 | } |
diff --git a/src/core/hle/service/am/applets/web_browser.cpp b/src/core/hle/service/am/applets/web_browser.cpp index 9f30e167d..efe595c4f 100644 --- a/src/core/hle/service/am/applets/web_browser.cpp +++ b/src/core/hle/service/am/applets/web_browser.cpp | |||
| @@ -293,8 +293,8 @@ void WebBrowser::Finalize() { | |||
| 293 | broker.PushNormalDataFromApplet(std::make_shared<IStorage>(std::move(data))); | 293 | broker.PushNormalDataFromApplet(std::make_shared<IStorage>(std::move(data))); |
| 294 | broker.SignalStateChanged(); | 294 | broker.SignalStateChanged(); |
| 295 | 295 | ||
| 296 | if (!temporary_dir.empty() && FileUtil::IsDirectory(temporary_dir)) { | 296 | if (!temporary_dir.empty() && Common::FS::IsDirectory(temporary_dir)) { |
| 297 | FileUtil::DeleteDirRecursively(temporary_dir); | 297 | Common::FS::DeleteDirRecursively(temporary_dir); |
| 298 | } | 298 | } |
| 299 | } | 299 | } |
| 300 | 300 | ||
| @@ -452,10 +452,10 @@ void WebBrowser::InitializeOffline() { | |||
| 452 | }; | 452 | }; |
| 453 | 453 | ||
| 454 | temporary_dir = | 454 | temporary_dir = |
| 455 | FileUtil::SanitizePath(FileUtil::GetUserPath(FileUtil::UserPath::CacheDir) + "web_applet_" + | 455 | Common::FS::SanitizePath(Common::FS::GetUserPath(Common::FS::UserPath::CacheDir) + |
| 456 | WEB_SOURCE_NAMES[static_cast<u32>(source) - 1], | 456 | "web_applet_" + WEB_SOURCE_NAMES[static_cast<u32>(source) - 1], |
| 457 | FileUtil::DirectorySeparator::PlatformDefault); | 457 | Common::FS::DirectorySeparator::PlatformDefault); |
| 458 | FileUtil::DeleteDirRecursively(temporary_dir); | 458 | Common::FS::DeleteDirRecursively(temporary_dir); |
| 459 | 459 | ||
| 460 | u64 title_id = 0; // 0 corresponds to current process | 460 | u64 title_id = 0; // 0 corresponds to current process |
| 461 | ASSERT(args[WebArgTLVType::ApplicationID].size() >= 0x8); | 461 | ASSERT(args[WebArgTLVType::ApplicationID].size() >= 0x8); |
| @@ -492,8 +492,8 @@ void WebBrowser::InitializeOffline() { | |||
| 492 | } | 492 | } |
| 493 | 493 | ||
| 494 | filename = | 494 | filename = |
| 495 | FileUtil::SanitizePath(temporary_dir + path_additional_directory + DIR_SEP + filename, | 495 | Common::FS::SanitizePath(temporary_dir + path_additional_directory + DIR_SEP + filename, |
| 496 | FileUtil::DirectorySeparator::PlatformDefault); | 496 | Common::FS::DirectorySeparator::PlatformDefault); |
| 497 | } | 497 | } |
| 498 | 498 | ||
| 499 | void WebBrowser::ExecuteShop() { | 499 | void WebBrowser::ExecuteShop() { |
| @@ -551,7 +551,8 @@ void WebBrowser::ExecuteShop() { | |||
| 551 | } | 551 | } |
| 552 | 552 | ||
| 553 | void WebBrowser::ExecuteOffline() { | 553 | void WebBrowser::ExecuteOffline() { |
| 554 | frontend.OpenPageLocal(filename, [this] { UnpackRomFS(); }, [this] { Finalize(); }); | 554 | frontend.OpenPageLocal( |
| 555 | filename, [this] { UnpackRomFS(); }, [this] { Finalize(); }); | ||
| 555 | } | 556 | } |
| 556 | 557 | ||
| 557 | } // namespace Service::AM::Applets | 558 | } // namespace Service::AM::Applets |
diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp index dd80dd1dc..9b4910e53 100644 --- a/src/core/hle/service/audio/audout_u.cpp +++ b/src/core/hle/service/audio/audout_u.cpp | |||
| @@ -206,7 +206,7 @@ private: | |||
| 206 | AudioCore::StreamPtr stream; | 206 | AudioCore::StreamPtr stream; |
| 207 | std::string device_name; | 207 | std::string device_name; |
| 208 | 208 | ||
| 209 | [[maybe_unused]] AudoutParams audio_params {}; | 209 | [[maybe_unused]] AudoutParams audio_params{}; |
| 210 | 210 | ||
| 211 | /// This is the event handle used to check if the audio buffer was released | 211 | /// This is the event handle used to check if the audio buffer was released |
| 212 | Kernel::EventPair buffer_event; | 212 | Kernel::EventPair buffer_event; |
diff --git a/src/core/hle/service/bcat/backend/boxcat.cpp b/src/core/hle/service/bcat/backend/boxcat.cpp index d29e78d7e..ca021a99f 100644 --- a/src/core/hle/service/bcat/backend/boxcat.cpp +++ b/src/core/hle/service/bcat/backend/boxcat.cpp | |||
| @@ -89,12 +89,12 @@ constexpr u32 TIMEOUT_SECONDS = 30; | |||
| 89 | 89 | ||
| 90 | std::string GetBINFilePath(u64 title_id) { | 90 | std::string GetBINFilePath(u64 title_id) { |
| 91 | return fmt::format("{}bcat/{:016X}/launchparam.bin", | 91 | return fmt::format("{}bcat/{:016X}/launchparam.bin", |
| 92 | FileUtil::GetUserPath(FileUtil::UserPath::CacheDir), title_id); | 92 | Common::FS::GetUserPath(Common::FS::UserPath::CacheDir), title_id); |
| 93 | } | 93 | } |
| 94 | 94 | ||
| 95 | std::string GetZIPFilePath(u64 title_id) { | 95 | std::string GetZIPFilePath(u64 title_id) { |
| 96 | return fmt::format("{}bcat/{:016X}/data.zip", | 96 | return fmt::format("{}bcat/{:016X}/data.zip", |
| 97 | FileUtil::GetUserPath(FileUtil::UserPath::CacheDir), title_id); | 97 | Common::FS::GetUserPath(Common::FS::UserPath::CacheDir), title_id); |
| 98 | } | 98 | } |
| 99 | 99 | ||
| 100 | // If the error is something the user should know about (build ID mismatch, bad client version), | 100 | // If the error is something the user should know about (build ID mismatch, bad client version), |
| @@ -205,8 +205,8 @@ private: | |||
| 205 | {std::string("Game-Build-Id"), fmt::format("{:016X}", build_id)}, | 205 | {std::string("Game-Build-Id"), fmt::format("{:016X}", build_id)}, |
| 206 | }; | 206 | }; |
| 207 | 207 | ||
| 208 | if (FileUtil::Exists(path)) { | 208 | if (Common::FS::Exists(path)) { |
| 209 | FileUtil::IOFile file{path, "rb"}; | 209 | Common::FS::IOFile file{path, "rb"}; |
| 210 | if (file.IsOpen()) { | 210 | if (file.IsOpen()) { |
| 211 | std::vector<u8> bytes(file.GetSize()); | 211 | std::vector<u8> bytes(file.GetSize()); |
| 212 | file.ReadBytes(bytes.data(), bytes.size()); | 212 | file.ReadBytes(bytes.data(), bytes.size()); |
| @@ -236,8 +236,8 @@ private: | |||
| 236 | return DownloadResult::InvalidContentType; | 236 | return DownloadResult::InvalidContentType; |
| 237 | } | 237 | } |
| 238 | 238 | ||
| 239 | FileUtil::CreateFullPath(path); | 239 | Common::FS::CreateFullPath(path); |
| 240 | FileUtil::IOFile file{path, "wb"}; | 240 | Common::FS::IOFile file{path, "wb"}; |
| 241 | if (!file.IsOpen()) | 241 | if (!file.IsOpen()) |
| 242 | return DownloadResult::GeneralFSError; | 242 | return DownloadResult::GeneralFSError; |
| 243 | if (!file.Resize(response->body.size())) | 243 | if (!file.Resize(response->body.size())) |
| @@ -290,7 +290,7 @@ void SynchronizeInternal(AM::Applets::AppletManager& applet_manager, DirectoryGe | |||
| 290 | LOG_ERROR(Service_BCAT, "Boxcat synchronization failed with error '{}'!", res); | 290 | LOG_ERROR(Service_BCAT, "Boxcat synchronization failed with error '{}'!", res); |
| 291 | 291 | ||
| 292 | if (res == DownloadResult::NoMatchBuildId || res == DownloadResult::NoMatchTitleId) { | 292 | if (res == DownloadResult::NoMatchBuildId || res == DownloadResult::NoMatchTitleId) { |
| 293 | FileUtil::Delete(zip_path); | 293 | Common::FS::Delete(zip_path); |
| 294 | } | 294 | } |
| 295 | 295 | ||
| 296 | HandleDownloadDisplayResult(applet_manager, res); | 296 | HandleDownloadDisplayResult(applet_manager, res); |
| @@ -300,7 +300,7 @@ void SynchronizeInternal(AM::Applets::AppletManager& applet_manager, DirectoryGe | |||
| 300 | 300 | ||
| 301 | progress.StartProcessingDataList(); | 301 | progress.StartProcessingDataList(); |
| 302 | 302 | ||
| 303 | FileUtil::IOFile zip{zip_path, "rb"}; | 303 | Common::FS::IOFile zip{zip_path, "rb"}; |
| 304 | const auto size = zip.GetSize(); | 304 | const auto size = zip.GetSize(); |
| 305 | std::vector<u8> bytes(size); | 305 | std::vector<u8> bytes(size); |
| 306 | if (!zip.IsOpen() || size == 0 || zip.ReadBytes(bytes.data(), bytes.size()) != bytes.size()) { | 306 | if (!zip.IsOpen() || size == 0 || zip.ReadBytes(bytes.data(), bytes.size()) != bytes.size()) { |
| @@ -365,8 +365,7 @@ bool Boxcat::Synchronize(TitleIDVersion title, ProgressServiceBackend& progress) | |||
| 365 | 365 | ||
| 366 | std::thread([this, title, &progress] { | 366 | std::thread([this, title, &progress] { |
| 367 | SynchronizeInternal(applet_manager, dir_getter, title, progress); | 367 | SynchronizeInternal(applet_manager, dir_getter, title, progress); |
| 368 | }) | 368 | }).detach(); |
| 369 | .detach(); | ||
| 370 | 369 | ||
| 371 | return true; | 370 | return true; |
| 372 | } | 371 | } |
| @@ -377,8 +376,7 @@ bool Boxcat::SynchronizeDirectory(TitleIDVersion title, std::string name, | |||
| 377 | 376 | ||
| 378 | std::thread([this, title, name, &progress] { | 377 | std::thread([this, title, name, &progress] { |
| 379 | SynchronizeInternal(applet_manager, dir_getter, title, progress, name); | 378 | SynchronizeInternal(applet_manager, dir_getter, title, progress, name); |
| 380 | }) | 379 | }).detach(); |
| 381 | .detach(); | ||
| 382 | 380 | ||
| 383 | return true; | 381 | return true; |
| 384 | } | 382 | } |
| @@ -422,7 +420,7 @@ std::optional<std::vector<u8>> Boxcat::GetLaunchParameter(TitleIDVersion title) | |||
| 422 | LOG_ERROR(Service_BCAT, "Boxcat synchronization failed with error '{}'!", res); | 420 | LOG_ERROR(Service_BCAT, "Boxcat synchronization failed with error '{}'!", res); |
| 423 | 421 | ||
| 424 | if (res == DownloadResult::NoMatchBuildId || res == DownloadResult::NoMatchTitleId) { | 422 | if (res == DownloadResult::NoMatchBuildId || res == DownloadResult::NoMatchTitleId) { |
| 425 | FileUtil::Delete(path); | 423 | Common::FS::Delete(path); |
| 426 | } | 424 | } |
| 427 | 425 | ||
| 428 | HandleDownloadDisplayResult(applet_manager, res); | 426 | HandleDownloadDisplayResult(applet_manager, res); |
| @@ -430,7 +428,7 @@ std::optional<std::vector<u8>> Boxcat::GetLaunchParameter(TitleIDVersion title) | |||
| 430 | } | 428 | } |
| 431 | } | 429 | } |
| 432 | 430 | ||
| 433 | FileUtil::IOFile bin{path, "rb"}; | 431 | Common::FS::IOFile bin{path, "rb"}; |
| 434 | const auto size = bin.GetSize(); | 432 | const auto size = bin.GetSize(); |
| 435 | std::vector<u8> bytes(size); | 433 | std::vector<u8> bytes(size); |
| 436 | if (!bin.IsOpen() || size == 0 || bin.ReadBytes(bytes.data(), bytes.size()) != bytes.size()) { | 434 | if (!bin.IsOpen() || size == 0 || bin.ReadBytes(bytes.data(), bytes.size()) != bytes.size()) { |
diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp index 4490f8e4c..2cee1193c 100644 --- a/src/core/hle/service/filesystem/filesystem.cpp +++ b/src/core/hle/service/filesystem/filesystem.cpp | |||
| @@ -36,7 +36,7 @@ constexpr u64 SUFFICIENT_SAVE_DATA_SIZE = 0xF0000000; | |||
| 36 | 36 | ||
| 37 | static FileSys::VirtualDir GetDirectoryRelativeWrapped(FileSys::VirtualDir base, | 37 | static FileSys::VirtualDir GetDirectoryRelativeWrapped(FileSys::VirtualDir base, |
| 38 | std::string_view dir_name_) { | 38 | std::string_view dir_name_) { |
| 39 | std::string dir_name(FileUtil::SanitizePath(dir_name_)); | 39 | std::string dir_name(Common::FS::SanitizePath(dir_name_)); |
| 40 | if (dir_name.empty() || dir_name == "." || dir_name == "/" || dir_name == "\\") | 40 | if (dir_name.empty() || dir_name == "." || dir_name == "/" || dir_name == "\\") |
| 41 | return base; | 41 | return base; |
| 42 | 42 | ||
| @@ -53,13 +53,13 @@ std::string VfsDirectoryServiceWrapper::GetName() const { | |||
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | ResultCode VfsDirectoryServiceWrapper::CreateFile(const std::string& path_, u64 size) const { | 55 | ResultCode VfsDirectoryServiceWrapper::CreateFile(const std::string& path_, u64 size) const { |
| 56 | std::string path(FileUtil::SanitizePath(path_)); | 56 | std::string path(Common::FS::SanitizePath(path_)); |
| 57 | auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path)); | 57 | auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path)); |
| 58 | // dir can be nullptr if path contains subdirectories, create those prior to creating the file. | 58 | // dir can be nullptr if path contains subdirectories, create those prior to creating the file. |
| 59 | if (dir == nullptr) { | 59 | if (dir == nullptr) { |
| 60 | dir = backing->CreateSubdirectory(FileUtil::GetParentPath(path)); | 60 | dir = backing->CreateSubdirectory(Common::FS::GetParentPath(path)); |
| 61 | } | 61 | } |
| 62 | auto file = dir->CreateFile(FileUtil::GetFilename(path)); | 62 | auto file = dir->CreateFile(Common::FS::GetFilename(path)); |
| 63 | if (file == nullptr) { | 63 | if (file == nullptr) { |
| 64 | // TODO(DarkLordZach): Find a better error code for this | 64 | // TODO(DarkLordZach): Find a better error code for this |
| 65 | return RESULT_UNKNOWN; | 65 | return RESULT_UNKNOWN; |
| @@ -72,17 +72,17 @@ ResultCode VfsDirectoryServiceWrapper::CreateFile(const std::string& path_, u64 | |||
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | ResultCode VfsDirectoryServiceWrapper::DeleteFile(const std::string& path_) const { | 74 | ResultCode VfsDirectoryServiceWrapper::DeleteFile(const std::string& path_) const { |
| 75 | std::string path(FileUtil::SanitizePath(path_)); | 75 | std::string path(Common::FS::SanitizePath(path_)); |
| 76 | if (path.empty()) { | 76 | if (path.empty()) { |
| 77 | // TODO(DarkLordZach): Why do games call this and what should it do? Works as is but... | 77 | // TODO(DarkLordZach): Why do games call this and what should it do? Works as is but... |
| 78 | return RESULT_SUCCESS; | 78 | return RESULT_SUCCESS; |
| 79 | } | 79 | } |
| 80 | 80 | ||
| 81 | auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path)); | 81 | auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path)); |
| 82 | if (dir->GetFile(FileUtil::GetFilename(path)) == nullptr) { | 82 | if (dir->GetFile(Common::FS::GetFilename(path)) == nullptr) { |
| 83 | return FileSys::ERROR_PATH_NOT_FOUND; | 83 | return FileSys::ERROR_PATH_NOT_FOUND; |
| 84 | } | 84 | } |
| 85 | if (!dir->DeleteFile(FileUtil::GetFilename(path))) { | 85 | if (!dir->DeleteFile(Common::FS::GetFilename(path))) { |
| 86 | // TODO(DarkLordZach): Find a better error code for this | 86 | // TODO(DarkLordZach): Find a better error code for this |
| 87 | return RESULT_UNKNOWN; | 87 | return RESULT_UNKNOWN; |
| 88 | } | 88 | } |
| @@ -91,11 +91,11 @@ ResultCode VfsDirectoryServiceWrapper::DeleteFile(const std::string& path_) cons | |||
| 91 | } | 91 | } |
| 92 | 92 | ||
| 93 | ResultCode VfsDirectoryServiceWrapper::CreateDirectory(const std::string& path_) const { | 93 | ResultCode VfsDirectoryServiceWrapper::CreateDirectory(const std::string& path_) const { |
| 94 | std::string path(FileUtil::SanitizePath(path_)); | 94 | std::string path(Common::FS::SanitizePath(path_)); |
| 95 | auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path)); | 95 | auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path)); |
| 96 | if (dir == nullptr && FileUtil::GetFilename(FileUtil::GetParentPath(path)).empty()) | 96 | if (dir == nullptr && Common::FS::GetFilename(Common::FS::GetParentPath(path)).empty()) |
| 97 | dir = backing; | 97 | dir = backing; |
| 98 | auto new_dir = dir->CreateSubdirectory(FileUtil::GetFilename(path)); | 98 | auto new_dir = dir->CreateSubdirectory(Common::FS::GetFilename(path)); |
| 99 | if (new_dir == nullptr) { | 99 | if (new_dir == nullptr) { |
| 100 | // TODO(DarkLordZach): Find a better error code for this | 100 | // TODO(DarkLordZach): Find a better error code for this |
| 101 | return RESULT_UNKNOWN; | 101 | return RESULT_UNKNOWN; |
| @@ -104,9 +104,9 @@ ResultCode VfsDirectoryServiceWrapper::CreateDirectory(const std::string& path_) | |||
| 104 | } | 104 | } |
| 105 | 105 | ||
| 106 | ResultCode VfsDirectoryServiceWrapper::DeleteDirectory(const std::string& path_) const { | 106 | ResultCode VfsDirectoryServiceWrapper::DeleteDirectory(const std::string& path_) const { |
| 107 | std::string path(FileUtil::SanitizePath(path_)); | 107 | std::string path(Common::FS::SanitizePath(path_)); |
| 108 | auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path)); | 108 | auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path)); |
| 109 | if (!dir->DeleteSubdirectory(FileUtil::GetFilename(path))) { | 109 | if (!dir->DeleteSubdirectory(Common::FS::GetFilename(path))) { |
| 110 | // TODO(DarkLordZach): Find a better error code for this | 110 | // TODO(DarkLordZach): Find a better error code for this |
| 111 | return RESULT_UNKNOWN; | 111 | return RESULT_UNKNOWN; |
| 112 | } | 112 | } |
| @@ -114,9 +114,9 @@ ResultCode VfsDirectoryServiceWrapper::DeleteDirectory(const std::string& path_) | |||
| 114 | } | 114 | } |
| 115 | 115 | ||
| 116 | ResultCode VfsDirectoryServiceWrapper::DeleteDirectoryRecursively(const std::string& path_) const { | 116 | ResultCode VfsDirectoryServiceWrapper::DeleteDirectoryRecursively(const std::string& path_) const { |
| 117 | std::string path(FileUtil::SanitizePath(path_)); | 117 | std::string path(Common::FS::SanitizePath(path_)); |
| 118 | auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path)); | 118 | auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path)); |
| 119 | if (!dir->DeleteSubdirectoryRecursive(FileUtil::GetFilename(path))) { | 119 | if (!dir->DeleteSubdirectoryRecursive(Common::FS::GetFilename(path))) { |
| 120 | // TODO(DarkLordZach): Find a better error code for this | 120 | // TODO(DarkLordZach): Find a better error code for this |
| 121 | return RESULT_UNKNOWN; | 121 | return RESULT_UNKNOWN; |
| 122 | } | 122 | } |
| @@ -124,10 +124,10 @@ ResultCode VfsDirectoryServiceWrapper::DeleteDirectoryRecursively(const std::str | |||
| 124 | } | 124 | } |
| 125 | 125 | ||
| 126 | ResultCode VfsDirectoryServiceWrapper::CleanDirectoryRecursively(const std::string& path) const { | 126 | ResultCode VfsDirectoryServiceWrapper::CleanDirectoryRecursively(const std::string& path) const { |
| 127 | const std::string sanitized_path(FileUtil::SanitizePath(path)); | 127 | const std::string sanitized_path(Common::FS::SanitizePath(path)); |
| 128 | auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(sanitized_path)); | 128 | auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(sanitized_path)); |
| 129 | 129 | ||
| 130 | if (!dir->CleanSubdirectoryRecursive(FileUtil::GetFilename(sanitized_path))) { | 130 | if (!dir->CleanSubdirectoryRecursive(Common::FS::GetFilename(sanitized_path))) { |
| 131 | // TODO(DarkLordZach): Find a better error code for this | 131 | // TODO(DarkLordZach): Find a better error code for this |
| 132 | return RESULT_UNKNOWN; | 132 | return RESULT_UNKNOWN; |
| 133 | } | 133 | } |
| @@ -137,14 +137,14 @@ ResultCode VfsDirectoryServiceWrapper::CleanDirectoryRecursively(const std::stri | |||
| 137 | 137 | ||
| 138 | ResultCode VfsDirectoryServiceWrapper::RenameFile(const std::string& src_path_, | 138 | ResultCode VfsDirectoryServiceWrapper::RenameFile(const std::string& src_path_, |
| 139 | const std::string& dest_path_) const { | 139 | const std::string& dest_path_) const { |
| 140 | std::string src_path(FileUtil::SanitizePath(src_path_)); | 140 | std::string src_path(Common::FS::SanitizePath(src_path_)); |
| 141 | std::string dest_path(FileUtil::SanitizePath(dest_path_)); | 141 | std::string dest_path(Common::FS::SanitizePath(dest_path_)); |
| 142 | auto src = backing->GetFileRelative(src_path); | 142 | auto src = backing->GetFileRelative(src_path); |
| 143 | if (FileUtil::GetParentPath(src_path) == FileUtil::GetParentPath(dest_path)) { | 143 | if (Common::FS::GetParentPath(src_path) == Common::FS::GetParentPath(dest_path)) { |
| 144 | // Use more-optimized vfs implementation rename. | 144 | // Use more-optimized vfs implementation rename. |
| 145 | if (src == nullptr) | 145 | if (src == nullptr) |
| 146 | return FileSys::ERROR_PATH_NOT_FOUND; | 146 | return FileSys::ERROR_PATH_NOT_FOUND; |
| 147 | if (!src->Rename(FileUtil::GetFilename(dest_path))) { | 147 | if (!src->Rename(Common::FS::GetFilename(dest_path))) { |
| 148 | // TODO(DarkLordZach): Find a better error code for this | 148 | // TODO(DarkLordZach): Find a better error code for this |
| 149 | return RESULT_UNKNOWN; | 149 | return RESULT_UNKNOWN; |
| 150 | } | 150 | } |
| @@ -162,7 +162,7 @@ ResultCode VfsDirectoryServiceWrapper::RenameFile(const std::string& src_path_, | |||
| 162 | ASSERT_MSG(dest->WriteBytes(src->ReadAllBytes()) == src->GetSize(), | 162 | ASSERT_MSG(dest->WriteBytes(src->ReadAllBytes()) == src->GetSize(), |
| 163 | "Could not write all of the bytes but everything else has succeded."); | 163 | "Could not write all of the bytes but everything else has succeded."); |
| 164 | 164 | ||
| 165 | if (!src->GetContainingDirectory()->DeleteFile(FileUtil::GetFilename(src_path))) { | 165 | if (!src->GetContainingDirectory()->DeleteFile(Common::FS::GetFilename(src_path))) { |
| 166 | // TODO(DarkLordZach): Find a better error code for this | 166 | // TODO(DarkLordZach): Find a better error code for this |
| 167 | return RESULT_UNKNOWN; | 167 | return RESULT_UNKNOWN; |
| 168 | } | 168 | } |
| @@ -172,14 +172,14 @@ ResultCode VfsDirectoryServiceWrapper::RenameFile(const std::string& src_path_, | |||
| 172 | 172 | ||
| 173 | ResultCode VfsDirectoryServiceWrapper::RenameDirectory(const std::string& src_path_, | 173 | ResultCode VfsDirectoryServiceWrapper::RenameDirectory(const std::string& src_path_, |
| 174 | const std::string& dest_path_) const { | 174 | const std::string& dest_path_) const { |
| 175 | std::string src_path(FileUtil::SanitizePath(src_path_)); | 175 | std::string src_path(Common::FS::SanitizePath(src_path_)); |
| 176 | std::string dest_path(FileUtil::SanitizePath(dest_path_)); | 176 | std::string dest_path(Common::FS::SanitizePath(dest_path_)); |
| 177 | auto src = GetDirectoryRelativeWrapped(backing, src_path); | 177 | auto src = GetDirectoryRelativeWrapped(backing, src_path); |
| 178 | if (FileUtil::GetParentPath(src_path) == FileUtil::GetParentPath(dest_path)) { | 178 | if (Common::FS::GetParentPath(src_path) == Common::FS::GetParentPath(dest_path)) { |
| 179 | // Use more-optimized vfs implementation rename. | 179 | // Use more-optimized vfs implementation rename. |
| 180 | if (src == nullptr) | 180 | if (src == nullptr) |
| 181 | return FileSys::ERROR_PATH_NOT_FOUND; | 181 | return FileSys::ERROR_PATH_NOT_FOUND; |
| 182 | if (!src->Rename(FileUtil::GetFilename(dest_path))) { | 182 | if (!src->Rename(Common::FS::GetFilename(dest_path))) { |
| 183 | // TODO(DarkLordZach): Find a better error code for this | 183 | // TODO(DarkLordZach): Find a better error code for this |
| 184 | return RESULT_UNKNOWN; | 184 | return RESULT_UNKNOWN; |
| 185 | } | 185 | } |
| @@ -198,7 +198,7 @@ ResultCode VfsDirectoryServiceWrapper::RenameDirectory(const std::string& src_pa | |||
| 198 | 198 | ||
| 199 | ResultVal<FileSys::VirtualFile> VfsDirectoryServiceWrapper::OpenFile(const std::string& path_, | 199 | ResultVal<FileSys::VirtualFile> VfsDirectoryServiceWrapper::OpenFile(const std::string& path_, |
| 200 | FileSys::Mode mode) const { | 200 | FileSys::Mode mode) const { |
| 201 | const std::string path(FileUtil::SanitizePath(path_)); | 201 | const std::string path(Common::FS::SanitizePath(path_)); |
| 202 | std::string_view npath = path; | 202 | std::string_view npath = path; |
| 203 | while (!npath.empty() && (npath[0] == '/' || npath[0] == '\\')) { | 203 | while (!npath.empty() && (npath[0] == '/' || npath[0] == '\\')) { |
| 204 | npath.remove_prefix(1); | 204 | npath.remove_prefix(1); |
| @@ -218,7 +218,7 @@ ResultVal<FileSys::VirtualFile> VfsDirectoryServiceWrapper::OpenFile(const std:: | |||
| 218 | } | 218 | } |
| 219 | 219 | ||
| 220 | ResultVal<FileSys::VirtualDir> VfsDirectoryServiceWrapper::OpenDirectory(const std::string& path_) { | 220 | ResultVal<FileSys::VirtualDir> VfsDirectoryServiceWrapper::OpenDirectory(const std::string& path_) { |
| 221 | std::string path(FileUtil::SanitizePath(path_)); | 221 | std::string path(Common::FS::SanitizePath(path_)); |
| 222 | auto dir = GetDirectoryRelativeWrapped(backing, path); | 222 | auto dir = GetDirectoryRelativeWrapped(backing, path); |
| 223 | if (dir == nullptr) { | 223 | if (dir == nullptr) { |
| 224 | // TODO(DarkLordZach): Find a better error code for this | 224 | // TODO(DarkLordZach): Find a better error code for this |
| @@ -229,11 +229,11 @@ ResultVal<FileSys::VirtualDir> VfsDirectoryServiceWrapper::OpenDirectory(const s | |||
| 229 | 229 | ||
| 230 | ResultVal<FileSys::EntryType> VfsDirectoryServiceWrapper::GetEntryType( | 230 | ResultVal<FileSys::EntryType> VfsDirectoryServiceWrapper::GetEntryType( |
| 231 | const std::string& path_) const { | 231 | const std::string& path_) const { |
| 232 | std::string path(FileUtil::SanitizePath(path_)); | 232 | std::string path(Common::FS::SanitizePath(path_)); |
| 233 | auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path)); | 233 | auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path)); |
| 234 | if (dir == nullptr) | 234 | if (dir == nullptr) |
| 235 | return FileSys::ERROR_PATH_NOT_FOUND; | 235 | return FileSys::ERROR_PATH_NOT_FOUND; |
| 236 | auto filename = FileUtil::GetFilename(path); | 236 | auto filename = Common::FS::GetFilename(path); |
| 237 | // TODO(Subv): Some games use the '/' path, find out what this means. | 237 | // TODO(Subv): Some games use the '/' path, find out what this means. |
| 238 | if (filename.empty()) | 238 | if (filename.empty()) |
| 239 | return MakeResult(FileSys::EntryType::Directory); | 239 | return MakeResult(FileSys::EntryType::Directory); |
| @@ -695,13 +695,13 @@ void FileSystemController::CreateFactories(FileSys::VfsFilesystem& vfs, bool ove | |||
| 695 | sdmc_factory = nullptr; | 695 | sdmc_factory = nullptr; |
| 696 | } | 696 | } |
| 697 | 697 | ||
| 698 | auto nand_directory = vfs.OpenDirectory(FileUtil::GetUserPath(FileUtil::UserPath::NANDDir), | 698 | auto nand_directory = vfs.OpenDirectory(Common::FS::GetUserPath(Common::FS::UserPath::NANDDir), |
| 699 | FileSys::Mode::ReadWrite); | 699 | FileSys::Mode::ReadWrite); |
| 700 | auto sd_directory = vfs.OpenDirectory(FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir), | 700 | auto sd_directory = vfs.OpenDirectory(Common::FS::GetUserPath(Common::FS::UserPath::SDMCDir), |
| 701 | FileSys::Mode::ReadWrite); | 701 | FileSys::Mode::ReadWrite); |
| 702 | auto load_directory = vfs.OpenDirectory(FileUtil::GetUserPath(FileUtil::UserPath::LoadDir), | 702 | auto load_directory = vfs.OpenDirectory(Common::FS::GetUserPath(Common::FS::UserPath::LoadDir), |
| 703 | FileSys::Mode::ReadWrite); | 703 | FileSys::Mode::ReadWrite); |
| 704 | auto dump_directory = vfs.OpenDirectory(FileUtil::GetUserPath(FileUtil::UserPath::DumpDir), | 704 | auto dump_directory = vfs.OpenDirectory(Common::FS::GetUserPath(Common::FS::UserPath::DumpDir), |
| 705 | FileSys::Mode::ReadWrite); | 705 | FileSys::Mode::ReadWrite); |
| 706 | 706 | ||
| 707 | if (bis_factory == nullptr) { | 707 | if (bis_factory == nullptr) { |
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index ef67ad690..45fde8df2 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp | |||
| @@ -24,6 +24,7 @@ constexpr s32 HID_JOYSTICK_MAX = 0x7fff; | |||
| 24 | constexpr std::size_t NPAD_OFFSET = 0x9A00; | 24 | constexpr std::size_t NPAD_OFFSET = 0x9A00; |
| 25 | constexpr u32 BATTERY_FULL = 2; | 25 | constexpr u32 BATTERY_FULL = 2; |
| 26 | constexpr u32 MAX_NPAD_ID = 7; | 26 | constexpr u32 MAX_NPAD_ID = 7; |
| 27 | constexpr std::size_t HANDHELD_INDEX = 8; | ||
| 27 | constexpr std::array<u32, 10> npad_id_list{ | 28 | constexpr std::array<u32, 10> npad_id_list{ |
| 28 | 0, 1, 2, 3, 4, 5, 6, 7, NPAD_HANDHELD, NPAD_UNKNOWN, | 29 | 0, 1, 2, 3, 4, 5, 6, 7, NPAD_HANDHELD, NPAD_UNKNOWN, |
| 29 | }; | 30 | }; |
| @@ -33,19 +34,41 @@ enum class JoystickId : std::size_t { | |||
| 33 | Joystick_Right, | 34 | Joystick_Right, |
| 34 | }; | 35 | }; |
| 35 | 36 | ||
| 36 | static Controller_NPad::NPadControllerType MapSettingsTypeToNPad(Settings::ControllerType type) { | 37 | Controller_NPad::NPadControllerType Controller_NPad::MapSettingsTypeToNPad( |
| 38 | Settings::ControllerType type) { | ||
| 37 | switch (type) { | 39 | switch (type) { |
| 38 | case Settings::ControllerType::ProController: | 40 | case Settings::ControllerType::ProController: |
| 39 | return Controller_NPad::NPadControllerType::ProController; | 41 | return NPadControllerType::ProController; |
| 40 | case Settings::ControllerType::DualJoycon: | 42 | case Settings::ControllerType::DualJoyconDetached: |
| 41 | return Controller_NPad::NPadControllerType::JoyDual; | 43 | return NPadControllerType::JoyDual; |
| 42 | case Settings::ControllerType::LeftJoycon: | 44 | case Settings::ControllerType::LeftJoycon: |
| 43 | return Controller_NPad::NPadControllerType::JoyLeft; | 45 | return NPadControllerType::JoyLeft; |
| 44 | case Settings::ControllerType::RightJoycon: | 46 | case Settings::ControllerType::RightJoycon: |
| 45 | return Controller_NPad::NPadControllerType::JoyRight; | 47 | return NPadControllerType::JoyRight; |
| 48 | case Settings::ControllerType::Handheld: | ||
| 49 | return NPadControllerType::Handheld; | ||
| 46 | default: | 50 | default: |
| 47 | UNREACHABLE(); | 51 | UNREACHABLE(); |
| 48 | return Controller_NPad::NPadControllerType::JoyDual; | 52 | return NPadControllerType::ProController; |
| 53 | } | ||
| 54 | } | ||
| 55 | |||
| 56 | Settings::ControllerType Controller_NPad::MapNPadToSettingsType( | ||
| 57 | Controller_NPad::NPadControllerType type) { | ||
| 58 | switch (type) { | ||
| 59 | case NPadControllerType::ProController: | ||
| 60 | return Settings::ControllerType::ProController; | ||
| 61 | case NPadControllerType::JoyDual: | ||
| 62 | return Settings::ControllerType::DualJoyconDetached; | ||
| 63 | case NPadControllerType::JoyLeft: | ||
| 64 | return Settings::ControllerType::LeftJoycon; | ||
| 65 | case NPadControllerType::JoyRight: | ||
| 66 | return Settings::ControllerType::RightJoycon; | ||
| 67 | case NPadControllerType::Handheld: | ||
| 68 | return Settings::ControllerType::Handheld; | ||
| 69 | default: | ||
| 70 | UNREACHABLE(); | ||
| 71 | return Settings::ControllerType::ProController; | ||
| 49 | } | 72 | } |
| 50 | } | 73 | } |
| 51 | 74 | ||
| @@ -60,9 +83,9 @@ std::size_t Controller_NPad::NPadIdToIndex(u32 npad_id) { | |||
| 60 | case 6: | 83 | case 6: |
| 61 | case 7: | 84 | case 7: |
| 62 | return npad_id; | 85 | return npad_id; |
| 63 | case 8: | 86 | case HANDHELD_INDEX: |
| 64 | case NPAD_HANDHELD: | 87 | case NPAD_HANDHELD: |
| 65 | return 8; | 88 | return HANDHELD_INDEX; |
| 66 | case 9: | 89 | case 9: |
| 67 | case NPAD_UNKNOWN: | 90 | case NPAD_UNKNOWN: |
| 68 | return 9; | 91 | return 9; |
| @@ -83,38 +106,48 @@ u32 Controller_NPad::IndexToNPad(std::size_t index) { | |||
| 83 | case 6: | 106 | case 6: |
| 84 | case 7: | 107 | case 7: |
| 85 | return static_cast<u32>(index); | 108 | return static_cast<u32>(index); |
| 86 | case 8: | 109 | case HANDHELD_INDEX: |
| 87 | return NPAD_HANDHELD; | 110 | return NPAD_HANDHELD; |
| 88 | case 9: | 111 | case 9: |
| 89 | return NPAD_UNKNOWN; | 112 | return NPAD_UNKNOWN; |
| 90 | default: | 113 | default: |
| 91 | UNIMPLEMENTED_MSG("Unknown npad index {}", index); | 114 | UNIMPLEMENTED_MSG("Unknown npad index {}", index); |
| 92 | return 0; | 115 | return 0; |
| 93 | }; | 116 | } |
| 94 | } | 117 | } |
| 95 | 118 | ||
| 96 | Controller_NPad::Controller_NPad(Core::System& system) : ControllerBase(system), system(system) {} | 119 | Controller_NPad::Controller_NPad(Core::System& system) : ControllerBase(system), system(system) {} |
| 97 | Controller_NPad::~Controller_NPad() = default; | 120 | Controller_NPad::~Controller_NPad() = default; |
| 98 | 121 | ||
| 99 | void Controller_NPad::InitNewlyAddedControler(std::size_t controller_idx) { | 122 | void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { |
| 100 | const auto controller_type = connected_controllers[controller_idx].type; | 123 | const auto controller_type = connected_controllers[controller_idx].type; |
| 101 | auto& controller = shared_memory_entries[controller_idx]; | 124 | auto& controller = shared_memory_entries[controller_idx]; |
| 102 | if (controller_type == NPadControllerType::None) { | 125 | if (controller_type == NPadControllerType::None) { |
| 126 | styleset_changed_events[controller_idx].writable->Signal(); | ||
| 103 | return; | 127 | return; |
| 104 | } | 128 | } |
| 105 | controller.joy_styles.raw = 0; // Zero out | 129 | controller.joy_styles.raw = 0; // Zero out |
| 106 | controller.device_type.raw = 0; | 130 | controller.device_type.raw = 0; |
| 131 | controller.properties.raw = 0; | ||
| 107 | switch (controller_type) { | 132 | switch (controller_type) { |
| 108 | case NPadControllerType::None: | 133 | case NPadControllerType::None: |
| 109 | UNREACHABLE(); | 134 | UNREACHABLE(); |
| 110 | break; | 135 | break; |
| 136 | case NPadControllerType::ProController: | ||
| 137 | controller.joy_styles.pro_controller.Assign(1); | ||
| 138 | controller.device_type.pro_controller.Assign(1); | ||
| 139 | controller.properties.is_vertical.Assign(1); | ||
| 140 | controller.properties.use_plus.Assign(1); | ||
| 141 | controller.properties.use_minus.Assign(1); | ||
| 142 | controller.pad_assignment = NPadAssignments::Single; | ||
| 143 | break; | ||
| 111 | case NPadControllerType::Handheld: | 144 | case NPadControllerType::Handheld: |
| 112 | controller.joy_styles.handheld.Assign(1); | 145 | controller.joy_styles.handheld.Assign(1); |
| 113 | controller.device_type.handheld.Assign(1); | 146 | controller.device_type.handheld.Assign(1); |
| 114 | controller.pad_assignment = NPadAssignments::Dual; | ||
| 115 | controller.properties.is_vertical.Assign(1); | 147 | controller.properties.is_vertical.Assign(1); |
| 116 | controller.properties.use_plus.Assign(1); | 148 | controller.properties.use_plus.Assign(1); |
| 117 | controller.properties.use_minus.Assign(1); | 149 | controller.properties.use_minus.Assign(1); |
| 150 | controller.pad_assignment = NPadAssignments::Dual; | ||
| 118 | break; | 151 | break; |
| 119 | case NPadControllerType::JoyDual: | 152 | case NPadControllerType::JoyDual: |
| 120 | controller.joy_styles.joycon_dual.Assign(1); | 153 | controller.joy_styles.joycon_dual.Assign(1); |
| @@ -144,14 +177,6 @@ void Controller_NPad::InitNewlyAddedControler(std::size_t controller_idx) { | |||
| 144 | controller.device_type.pokeball.Assign(1); | 177 | controller.device_type.pokeball.Assign(1); |
| 145 | controller.pad_assignment = NPadAssignments::Single; | 178 | controller.pad_assignment = NPadAssignments::Single; |
| 146 | break; | 179 | break; |
| 147 | case NPadControllerType::ProController: | ||
| 148 | controller.joy_styles.pro_controller.Assign(1); | ||
| 149 | controller.device_type.pro_controller.Assign(1); | ||
| 150 | controller.properties.is_vertical.Assign(1); | ||
| 151 | controller.properties.use_plus.Assign(1); | ||
| 152 | controller.properties.use_minus.Assign(1); | ||
| 153 | controller.pad_assignment = NPadAssignments::Single; | ||
| 154 | break; | ||
| 155 | } | 180 | } |
| 156 | 181 | ||
| 157 | controller.single_color_error = ColorReadError::ReadOk; | 182 | controller.single_color_error = ColorReadError::ReadOk; |
| @@ -192,36 +217,25 @@ void Controller_NPad::OnInit() { | |||
| 192 | style.pokeball.Assign(1); | 217 | style.pokeball.Assign(1); |
| 193 | } | 218 | } |
| 194 | 219 | ||
| 195 | std::transform( | 220 | std::transform(Settings::values.players.begin(), Settings::values.players.end(), |
| 196 | Settings::values.players.begin(), Settings::values.players.end(), | 221 | connected_controllers.begin(), [](const Settings::PlayerInput& player) { |
| 197 | connected_controllers.begin(), [](const Settings::PlayerInput& player) { | 222 | return ControllerHolder{MapSettingsTypeToNPad(player.controller_type), |
| 198 | return ControllerHolder{MapSettingsTypeToNPad(player.type), player.connected}; | 223 | player.connected}; |
| 199 | }); | 224 | }); |
| 200 | |||
| 201 | std::stable_partition(connected_controllers.begin(), connected_controllers.begin() + 8, | ||
| 202 | [](const ControllerHolder& holder) { return holder.is_connected; }); | ||
| 203 | 225 | ||
| 204 | // Account for handheld | 226 | // Account for handheld |
| 205 | if (connected_controllers[8].is_connected) | 227 | if (connected_controllers[HANDHELD_INDEX].is_connected) { |
| 206 | connected_controllers[8].type = NPadControllerType::Handheld; | 228 | connected_controllers[HANDHELD_INDEX].type = NPadControllerType::Handheld; |
| 229 | } | ||
| 207 | 230 | ||
| 208 | supported_npad_id_types.resize(npad_id_list.size()); | 231 | supported_npad_id_types.resize(npad_id_list.size()); |
| 209 | std::memcpy(supported_npad_id_types.data(), npad_id_list.data(), | 232 | std::memcpy(supported_npad_id_types.data(), npad_id_list.data(), |
| 210 | npad_id_list.size() * sizeof(u32)); | 233 | npad_id_list.size() * sizeof(u32)); |
| 211 | 234 | ||
| 212 | // Add a default dual joycon controller if none are present. | ||
| 213 | if (std::none_of(connected_controllers.begin(), connected_controllers.end(), | ||
| 214 | [](const ControllerHolder& controller) { return controller.is_connected; })) { | ||
| 215 | supported_npad_id_types.resize(npad_id_list.size()); | ||
| 216 | std::memcpy(supported_npad_id_types.data(), npad_id_list.data(), | ||
| 217 | npad_id_list.size() * sizeof(u32)); | ||
| 218 | AddNewController(NPadControllerType::JoyDual); | ||
| 219 | } | ||
| 220 | |||
| 221 | for (std::size_t i = 0; i < connected_controllers.size(); ++i) { | 235 | for (std::size_t i = 0; i < connected_controllers.size(); ++i) { |
| 222 | const auto& controller = connected_controllers[i]; | 236 | const auto& controller = connected_controllers[i]; |
| 223 | if (controller.is_connected) { | 237 | if (controller.is_connected) { |
| 224 | AddNewControllerAt(controller.type, IndexToNPad(i)); | 238 | AddNewControllerAt(controller.type, i); |
| 225 | } | 239 | } |
| 226 | } | 240 | } |
| 227 | } | 241 | } |
| @@ -309,8 +323,9 @@ void Controller_NPad::RequestPadStateUpdate(u32 npad_id) { | |||
| 309 | 323 | ||
| 310 | void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, | 324 | void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, |
| 311 | std::size_t data_len) { | 325 | std::size_t data_len) { |
| 312 | if (!IsControllerActivated()) | 326 | if (!IsControllerActivated()) { |
| 313 | return; | 327 | return; |
| 328 | } | ||
| 314 | for (std::size_t i = 0; i < shared_memory_entries.size(); i++) { | 329 | for (std::size_t i = 0; i < shared_memory_entries.size(); i++) { |
| 315 | auto& npad = shared_memory_entries[i]; | 330 | auto& npad = shared_memory_entries[i]; |
| 316 | const std::array<NPadGeneric*, 7> controller_npads{&npad.main_controller_states, | 331 | const std::array<NPadGeneric*, 7> controller_npads{&npad.main_controller_states, |
| @@ -360,13 +375,25 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* | |||
| 360 | auto& libnx_entry = npad.libnx.npad[npad.libnx.common.last_entry_index]; | 375 | auto& libnx_entry = npad.libnx.npad[npad.libnx.common.last_entry_index]; |
| 361 | 376 | ||
| 362 | libnx_entry.connection_status.raw = 0; | 377 | libnx_entry.connection_status.raw = 0; |
| 378 | libnx_entry.connection_status.IsConnected.Assign(1); | ||
| 363 | 379 | ||
| 364 | switch (controller_type) { | 380 | switch (controller_type) { |
| 365 | case NPadControllerType::None: | 381 | case NPadControllerType::None: |
| 366 | UNREACHABLE(); | 382 | UNREACHABLE(); |
| 367 | break; | 383 | break; |
| 384 | case NPadControllerType::ProController: | ||
| 385 | main_controller.connection_status.raw = 0; | ||
| 386 | main_controller.connection_status.IsConnected.Assign(1); | ||
| 387 | main_controller.connection_status.IsWired.Assign(1); | ||
| 388 | main_controller.pad.pad_states.raw = pad_state.pad_states.raw; | ||
| 389 | main_controller.pad.l_stick = pad_state.l_stick; | ||
| 390 | main_controller.pad.r_stick = pad_state.r_stick; | ||
| 391 | |||
| 392 | libnx_entry.connection_status.IsWired.Assign(1); | ||
| 393 | break; | ||
| 368 | case NPadControllerType::Handheld: | 394 | case NPadControllerType::Handheld: |
| 369 | handheld_entry.connection_status.raw = 0; | 395 | handheld_entry.connection_status.raw = 0; |
| 396 | handheld_entry.connection_status.IsConnected.Assign(1); | ||
| 370 | handheld_entry.connection_status.IsWired.Assign(1); | 397 | handheld_entry.connection_status.IsWired.Assign(1); |
| 371 | handheld_entry.connection_status.IsLeftJoyConnected.Assign(1); | 398 | handheld_entry.connection_status.IsLeftJoyConnected.Assign(1); |
| 372 | handheld_entry.connection_status.IsRightJoyConnected.Assign(1); | 399 | handheld_entry.connection_status.IsRightJoyConnected.Assign(1); |
| @@ -375,57 +402,52 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* | |||
| 375 | handheld_entry.pad.pad_states.raw = pad_state.pad_states.raw; | 402 | handheld_entry.pad.pad_states.raw = pad_state.pad_states.raw; |
| 376 | handheld_entry.pad.l_stick = pad_state.l_stick; | 403 | handheld_entry.pad.l_stick = pad_state.l_stick; |
| 377 | handheld_entry.pad.r_stick = pad_state.r_stick; | 404 | handheld_entry.pad.r_stick = pad_state.r_stick; |
| 405 | |||
| 406 | libnx_entry.connection_status.IsWired.Assign(1); | ||
| 407 | libnx_entry.connection_status.IsLeftJoyConnected.Assign(1); | ||
| 408 | libnx_entry.connection_status.IsRightJoyConnected.Assign(1); | ||
| 409 | libnx_entry.connection_status.IsLeftJoyWired.Assign(1); | ||
| 410 | libnx_entry.connection_status.IsRightJoyWired.Assign(1); | ||
| 378 | break; | 411 | break; |
| 379 | case NPadControllerType::JoyDual: | 412 | case NPadControllerType::JoyDual: |
| 380 | dual_entry.connection_status.raw = 0; | 413 | dual_entry.connection_status.raw = 0; |
| 381 | 414 | dual_entry.connection_status.IsConnected.Assign(1); | |
| 382 | dual_entry.connection_status.IsLeftJoyConnected.Assign(1); | 415 | dual_entry.connection_status.IsLeftJoyConnected.Assign(1); |
| 383 | dual_entry.connection_status.IsRightJoyConnected.Assign(1); | 416 | dual_entry.connection_status.IsRightJoyConnected.Assign(1); |
| 384 | dual_entry.connection_status.IsConnected.Assign(1); | ||
| 385 | |||
| 386 | libnx_entry.connection_status.IsLeftJoyConnected.Assign(1); | ||
| 387 | libnx_entry.connection_status.IsRightJoyConnected.Assign(1); | ||
| 388 | libnx_entry.connection_status.IsConnected.Assign(1); | ||
| 389 | |||
| 390 | dual_entry.pad.pad_states.raw = pad_state.pad_states.raw; | 417 | dual_entry.pad.pad_states.raw = pad_state.pad_states.raw; |
| 391 | dual_entry.pad.l_stick = pad_state.l_stick; | 418 | dual_entry.pad.l_stick = pad_state.l_stick; |
| 392 | dual_entry.pad.r_stick = pad_state.r_stick; | 419 | dual_entry.pad.r_stick = pad_state.r_stick; |
| 420 | |||
| 421 | libnx_entry.connection_status.IsLeftJoyConnected.Assign(1); | ||
| 422 | libnx_entry.connection_status.IsRightJoyConnected.Assign(1); | ||
| 393 | break; | 423 | break; |
| 394 | case NPadControllerType::JoyLeft: | 424 | case NPadControllerType::JoyLeft: |
| 395 | left_entry.connection_status.raw = 0; | 425 | left_entry.connection_status.raw = 0; |
| 396 | |||
| 397 | left_entry.connection_status.IsConnected.Assign(1); | 426 | left_entry.connection_status.IsConnected.Assign(1); |
| 427 | left_entry.connection_status.IsLeftJoyConnected.Assign(1); | ||
| 398 | left_entry.pad.pad_states.raw = pad_state.pad_states.raw; | 428 | left_entry.pad.pad_states.raw = pad_state.pad_states.raw; |
| 399 | left_entry.pad.l_stick = pad_state.l_stick; | 429 | left_entry.pad.l_stick = pad_state.l_stick; |
| 400 | left_entry.pad.r_stick = pad_state.r_stick; | 430 | left_entry.pad.r_stick = pad_state.r_stick; |
| 431 | |||
| 432 | libnx_entry.connection_status.IsLeftJoyConnected.Assign(1); | ||
| 401 | break; | 433 | break; |
| 402 | case NPadControllerType::JoyRight: | 434 | case NPadControllerType::JoyRight: |
| 403 | right_entry.connection_status.raw = 0; | 435 | right_entry.connection_status.raw = 0; |
| 404 | |||
| 405 | right_entry.connection_status.IsConnected.Assign(1); | 436 | right_entry.connection_status.IsConnected.Assign(1); |
| 437 | right_entry.connection_status.IsRightJoyConnected.Assign(1); | ||
| 406 | right_entry.pad.pad_states.raw = pad_state.pad_states.raw; | 438 | right_entry.pad.pad_states.raw = pad_state.pad_states.raw; |
| 407 | right_entry.pad.l_stick = pad_state.l_stick; | 439 | right_entry.pad.l_stick = pad_state.l_stick; |
| 408 | right_entry.pad.r_stick = pad_state.r_stick; | 440 | right_entry.pad.r_stick = pad_state.r_stick; |
| 441 | |||
| 442 | libnx_entry.connection_status.IsRightJoyConnected.Assign(1); | ||
| 409 | break; | 443 | break; |
| 410 | case NPadControllerType::Pokeball: | 444 | case NPadControllerType::Pokeball: |
| 411 | pokeball_entry.connection_status.raw = 0; | 445 | pokeball_entry.connection_status.raw = 0; |
| 412 | |||
| 413 | pokeball_entry.connection_status.IsConnected.Assign(1); | 446 | pokeball_entry.connection_status.IsConnected.Assign(1); |
| 414 | pokeball_entry.connection_status.IsWired.Assign(1); | ||
| 415 | |||
| 416 | pokeball_entry.pad.pad_states.raw = pad_state.pad_states.raw; | 447 | pokeball_entry.pad.pad_states.raw = pad_state.pad_states.raw; |
| 417 | pokeball_entry.pad.l_stick = pad_state.l_stick; | 448 | pokeball_entry.pad.l_stick = pad_state.l_stick; |
| 418 | pokeball_entry.pad.r_stick = pad_state.r_stick; | 449 | pokeball_entry.pad.r_stick = pad_state.r_stick; |
| 419 | break; | 450 | break; |
| 420 | case NPadControllerType::ProController: | ||
| 421 | main_controller.connection_status.raw = 0; | ||
| 422 | |||
| 423 | main_controller.connection_status.IsConnected.Assign(1); | ||
| 424 | main_controller.connection_status.IsWired.Assign(1); | ||
| 425 | main_controller.pad.pad_states.raw = pad_state.pad_states.raw; | ||
| 426 | main_controller.pad.l_stick = pad_state.l_stick; | ||
| 427 | main_controller.pad.r_stick = pad_state.r_stick; | ||
| 428 | break; | ||
| 429 | } | 451 | } |
| 430 | 452 | ||
| 431 | // LibNX exclusively uses this section, so we always update it since LibNX doesn't activate | 453 | // LibNX exclusively uses this section, so we always update it since LibNX doesn't activate |
| @@ -453,26 +475,6 @@ void Controller_NPad::SetSupportedNPadIdTypes(u8* data, std::size_t length) { | |||
| 453 | supported_npad_id_types.clear(); | 475 | supported_npad_id_types.clear(); |
| 454 | supported_npad_id_types.resize(length / sizeof(u32)); | 476 | supported_npad_id_types.resize(length / sizeof(u32)); |
| 455 | std::memcpy(supported_npad_id_types.data(), data, length); | 477 | std::memcpy(supported_npad_id_types.data(), data, length); |
| 456 | for (std::size_t i = 0; i < connected_controllers.size(); i++) { | ||
| 457 | auto& controller = connected_controllers[i]; | ||
| 458 | if (!controller.is_connected) { | ||
| 459 | continue; | ||
| 460 | } | ||
| 461 | const auto requested_controller = | ||
| 462 | i <= MAX_NPAD_ID ? MapSettingsTypeToNPad(Settings::values.players[i].type) | ||
| 463 | : NPadControllerType::Handheld; | ||
| 464 | if (!IsControllerSupported(requested_controller)) { | ||
| 465 | const auto is_handheld = requested_controller == NPadControllerType::Handheld; | ||
| 466 | if (is_handheld) { | ||
| 467 | controller.type = NPadControllerType::None; | ||
| 468 | controller.is_connected = false; | ||
| 469 | AddNewController(requested_controller); | ||
| 470 | } else { | ||
| 471 | controller.type = requested_controller; | ||
| 472 | InitNewlyAddedControler(i); | ||
| 473 | } | ||
| 474 | } | ||
| 475 | } | ||
| 476 | } | 478 | } |
| 477 | 479 | ||
| 478 | void Controller_NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length) { | 480 | void Controller_NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length) { |
| @@ -504,7 +506,7 @@ void Controller_NPad::VibrateController(const std::vector<u32>& controller_ids, | |||
| 504 | const std::vector<Vibration>& vibrations) { | 506 | const std::vector<Vibration>& vibrations) { |
| 505 | LOG_DEBUG(Service_HID, "(STUBBED) called"); | 507 | LOG_DEBUG(Service_HID, "(STUBBED) called"); |
| 506 | 508 | ||
| 507 | if (!can_controllers_vibrate) { | 509 | if (!Settings::values.vibration_enabled || !can_controllers_vibrate) { |
| 508 | return; | 510 | return; |
| 509 | } | 511 | } |
| 510 | for (std::size_t i = 0; i < controller_ids.size(); i++) { | 512 | for (std::size_t i = 0; i < controller_ids.size(); i++) { |
| @@ -517,8 +519,6 @@ void Controller_NPad::VibrateController(const std::vector<u32>& controller_ids, | |||
| 517 | } | 519 | } |
| 518 | 520 | ||
| 519 | std::shared_ptr<Kernel::ReadableEvent> Controller_NPad::GetStyleSetChangedEvent(u32 npad_id) const { | 521 | std::shared_ptr<Kernel::ReadableEvent> Controller_NPad::GetStyleSetChangedEvent(u32 npad_id) const { |
| 520 | // TODO(ogniK): Figure out the best time to signal this event. This event seems that it should | ||
| 521 | // be signalled at least once, and signaled after a new controller is connected? | ||
| 522 | const auto& styleset_event = styleset_changed_events[NPadIdToIndex(npad_id)]; | 522 | const auto& styleset_event = styleset_changed_events[NPadIdToIndex(npad_id)]; |
| 523 | return styleset_event.readable; | 523 | return styleset_event.readable; |
| 524 | } | 524 | } |
| @@ -527,43 +527,43 @@ Controller_NPad::Vibration Controller_NPad::GetLastVibration() const { | |||
| 527 | return last_processed_vibration; | 527 | return last_processed_vibration; |
| 528 | } | 528 | } |
| 529 | 529 | ||
| 530 | void Controller_NPad::AddNewController(NPadControllerType controller) { | 530 | void Controller_NPad::AddNewControllerAt(NPadControllerType controller, std::size_t npad_index) { |
| 531 | controller = DecideBestController(controller); | 531 | UpdateControllerAt(controller, npad_index, true); |
| 532 | if (controller == NPadControllerType::Handheld) { | 532 | } |
| 533 | connected_controllers[8] = {controller, true}; | 533 | |
| 534 | InitNewlyAddedControler(8); | 534 | void Controller_NPad::UpdateControllerAt(NPadControllerType controller, std::size_t npad_index, |
| 535 | return; | 535 | bool connected) { |
| 536 | } | 536 | if (!connected) { |
| 537 | const auto pos = | 537 | DisconnectNPad(IndexToNPad(npad_index)); |
| 538 | std::find_if(connected_controllers.begin(), connected_controllers.end() - 2, | ||
| 539 | [](const ControllerHolder& holder) { return !holder.is_connected; }); | ||
| 540 | if (pos == connected_controllers.end() - 2) { | ||
| 541 | LOG_ERROR(Service_HID, "Cannot connect any more controllers!"); | ||
| 542 | return; | 538 | return; |
| 543 | } | 539 | } |
| 544 | const auto controller_id = std::distance(connected_controllers.begin(), pos); | ||
| 545 | connected_controllers[controller_id] = {controller, true}; | ||
| 546 | InitNewlyAddedControler(controller_id); | ||
| 547 | } | ||
| 548 | 540 | ||
| 549 | void Controller_NPad::AddNewControllerAt(NPadControllerType controller, u32 npad_id) { | ||
| 550 | controller = DecideBestController(controller); | ||
| 551 | if (controller == NPadControllerType::Handheld) { | 541 | if (controller == NPadControllerType::Handheld) { |
| 552 | connected_controllers[NPadIdToIndex(NPAD_HANDHELD)] = {controller, true}; | 542 | Settings::values.players[HANDHELD_INDEX].controller_type = |
| 553 | InitNewlyAddedControler(NPadIdToIndex(NPAD_HANDHELD)); | 543 | MapNPadToSettingsType(controller); |
| 544 | Settings::values.players[HANDHELD_INDEX].connected = true; | ||
| 545 | connected_controllers[HANDHELD_INDEX] = {controller, true}; | ||
| 546 | InitNewlyAddedController(HANDHELD_INDEX); | ||
| 554 | return; | 547 | return; |
| 555 | } | 548 | } |
| 556 | 549 | ||
| 557 | connected_controllers[NPadIdToIndex(npad_id)] = {controller, true}; | 550 | Settings::values.players[npad_index].controller_type = MapNPadToSettingsType(controller); |
| 558 | InitNewlyAddedControler(NPadIdToIndex(npad_id)); | 551 | Settings::values.players[npad_index].connected = true; |
| 559 | } | 552 | connected_controllers[npad_index] = {controller, true}; |
| 560 | 553 | InitNewlyAddedController(npad_index); | |
| 561 | void Controller_NPad::ConnectNPad(u32 npad_id) { | ||
| 562 | connected_controllers[NPadIdToIndex(npad_id)].is_connected = true; | ||
| 563 | } | 554 | } |
| 564 | 555 | ||
| 565 | void Controller_NPad::DisconnectNPad(u32 npad_id) { | 556 | void Controller_NPad::DisconnectNPad(u32 npad_id) { |
| 566 | connected_controllers[NPadIdToIndex(npad_id)].is_connected = false; | 557 | const auto npad_index = NPadIdToIndex(npad_id); |
| 558 | connected_controllers[npad_index].is_connected = false; | ||
| 559 | Settings::values.players[npad_index].connected = false; | ||
| 560 | |||
| 561 | auto& controller = shared_memory_entries[npad_index]; | ||
| 562 | controller.joy_styles.raw = 0; // Zero out | ||
| 563 | controller.device_type.raw = 0; | ||
| 564 | controller.properties.raw = 0; | ||
| 565 | |||
| 566 | styleset_changed_events[npad_index].writable->Signal(); | ||
| 567 | } | 567 | } |
| 568 | 568 | ||
| 569 | void Controller_NPad::SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode) { | 569 | void Controller_NPad::SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode) { |
| @@ -599,8 +599,8 @@ bool Controller_NPad::SwapNpadAssignment(u32 npad_id_1, u32 npad_id_2) { | |||
| 599 | 599 | ||
| 600 | std::swap(connected_controllers[npad_index_1].type, connected_controllers[npad_index_2].type); | 600 | std::swap(connected_controllers[npad_index_1].type, connected_controllers[npad_index_2].type); |
| 601 | 601 | ||
| 602 | InitNewlyAddedControler(npad_index_1); | 602 | AddNewControllerAt(connected_controllers[npad_index_1].type, npad_index_1); |
| 603 | InitNewlyAddedControler(npad_index_2); | 603 | AddNewControllerAt(connected_controllers[npad_index_2].type, npad_index_2); |
| 604 | 604 | ||
| 605 | return true; | 605 | return true; |
| 606 | } | 606 | } |
| @@ -614,11 +614,11 @@ Controller_NPad::LedPattern Controller_NPad::GetLedPattern(u32 npad_id) { | |||
| 614 | case 0: | 614 | case 0: |
| 615 | return LedPattern{1, 0, 0, 0}; | 615 | return LedPattern{1, 0, 0, 0}; |
| 616 | case 1: | 616 | case 1: |
| 617 | return LedPattern{0, 1, 0, 0}; | 617 | return LedPattern{1, 1, 0, 0}; |
| 618 | case 2: | 618 | case 2: |
| 619 | return LedPattern{0, 0, 1, 0}; | 619 | return LedPattern{1, 1, 1, 0}; |
| 620 | case 3: | 620 | case 3: |
| 621 | return LedPattern{0, 0, 0, 1}; | 621 | return LedPattern{1, 1, 1, 1}; |
| 622 | case 4: | 622 | case 4: |
| 623 | return LedPattern{1, 0, 0, 1}; | 623 | return LedPattern{1, 0, 0, 1}; |
| 624 | case 5: | 624 | case 5: |
| @@ -628,9 +628,8 @@ Controller_NPad::LedPattern Controller_NPad::GetLedPattern(u32 npad_id) { | |||
| 628 | case 7: | 628 | case 7: |
| 629 | return LedPattern{0, 1, 1, 0}; | 629 | return LedPattern{0, 1, 1, 0}; |
| 630 | default: | 630 | default: |
| 631 | UNIMPLEMENTED_MSG("Unhandled npad_id {}", npad_id); | ||
| 632 | return LedPattern{0, 0, 0, 0}; | 631 | return LedPattern{0, 0, 0, 0}; |
| 633 | }; | 632 | } |
| 634 | } | 633 | } |
| 635 | 634 | ||
| 636 | void Controller_NPad::SetVibrationEnabled(bool can_vibrate) { | 635 | void Controller_NPad::SetVibrationEnabled(bool can_vibrate) { |
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 5d4c58a43..75ce5b731 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h | |||
| @@ -118,10 +118,11 @@ public: | |||
| 118 | std::shared_ptr<Kernel::ReadableEvent> GetStyleSetChangedEvent(u32 npad_id) const; | 118 | std::shared_ptr<Kernel::ReadableEvent> GetStyleSetChangedEvent(u32 npad_id) const; |
| 119 | Vibration GetLastVibration() const; | 119 | Vibration GetLastVibration() const; |
| 120 | 120 | ||
| 121 | void AddNewController(NPadControllerType controller); | 121 | // Adds a new controller at an index. |
| 122 | void AddNewControllerAt(NPadControllerType controller, u32 npad_id); | 122 | void AddNewControllerAt(NPadControllerType controller, std::size_t npad_index); |
| 123 | // Adds a new controller at an index with connection status. | ||
| 124 | void UpdateControllerAt(NPadControllerType controller, std::size_t npad_index, bool connected); | ||
| 123 | 125 | ||
| 124 | void ConnectNPad(u32 npad_id); | ||
| 125 | void DisconnectNPad(u32 npad_id); | 126 | void DisconnectNPad(u32 npad_id); |
| 126 | void SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode); | 127 | void SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode); |
| 127 | GyroscopeZeroDriftMode GetGyroscopeZeroDriftMode() const; | 128 | GyroscopeZeroDriftMode GetGyroscopeZeroDriftMode() const; |
| @@ -141,6 +142,8 @@ public: | |||
| 141 | // Specifically for cheat engine and other features. | 142 | // Specifically for cheat engine and other features. |
| 142 | u32 GetAndResetPressState(); | 143 | u32 GetAndResetPressState(); |
| 143 | 144 | ||
| 145 | static Controller_NPad::NPadControllerType MapSettingsTypeToNPad(Settings::ControllerType type); | ||
| 146 | static Settings::ControllerType MapNPadToSettingsType(Controller_NPad::NPadControllerType type); | ||
| 144 | static std::size_t NPadIdToIndex(u32 npad_id); | 147 | static std::size_t NPadIdToIndex(u32 npad_id); |
| 145 | static u32 IndexToNPad(std::size_t index); | 148 | static u32 IndexToNPad(std::size_t index); |
| 146 | 149 | ||
| @@ -309,7 +312,7 @@ private: | |||
| 309 | bool is_connected; | 312 | bool is_connected; |
| 310 | }; | 313 | }; |
| 311 | 314 | ||
| 312 | void InitNewlyAddedControler(std::size_t controller_idx); | 315 | void InitNewlyAddedController(std::size_t controller_idx); |
| 313 | bool IsControllerSupported(NPadControllerType controller) const; | 316 | bool IsControllerSupported(NPadControllerType controller) const; |
| 314 | NPadControllerType DecideBestController(NPadControllerType priority) const; | 317 | NPadControllerType DecideBestController(NPadControllerType priority) const; |
| 315 | void RequestPadStateUpdate(u32 npad_id); | 318 | void RequestPadStateUpdate(u32 npad_id); |
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 1e95b7580..33416b5dd 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp | |||
| @@ -38,11 +38,9 @@ | |||
| 38 | namespace Service::HID { | 38 | 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 | // HID is polled every 15ms, this value was derived from |
| 42 | constexpr auto pad_update_ns = std::chrono::nanoseconds{1000000000 / 66}; | 42 | // https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering#joy-con-status-data-packet |
| 43 | [[maybe_unused]] constexpr auto accelerometer_update_ns = | 43 | constexpr auto pad_update_ns = std::chrono::nanoseconds{15 * 1000 * 1000}; // (15ms, 66.6Hz) |
| 44 | std::chrono::nanoseconds{1000000000 / 100}; | ||
| 45 | [[maybe_unused]] constexpr auto gyroscope_update_ticks = std::chrono::nanoseconds{1000000000 / 100}; | ||
| 46 | constexpr std::size_t SHARED_MEMORY_SIZE = 0x40000; | 44 | constexpr std::size_t SHARED_MEMORY_SIZE = 0x40000; |
| 47 | 45 | ||
| 48 | IAppletResource::IAppletResource(Core::System& system) | 46 | IAppletResource::IAppletResource(Core::System& system) |
| @@ -845,8 +843,7 @@ void Hid::CreateActiveVibrationDeviceList(Kernel::HLERequestContext& ctx) { | |||
| 845 | void Hid::PermitVibration(Kernel::HLERequestContext& ctx) { | 843 | void Hid::PermitVibration(Kernel::HLERequestContext& ctx) { |
| 846 | IPC::RequestParser rp{ctx}; | 844 | IPC::RequestParser rp{ctx}; |
| 847 | const auto can_vibrate{rp.Pop<bool>()}; | 845 | const auto can_vibrate{rp.Pop<bool>()}; |
| 848 | applet_resource->GetController<Controller_NPad>(HidController::NPad) | 846 | Settings::values.vibration_enabled = can_vibrate; |
| 849 | .SetVibrationEnabled(can_vibrate); | ||
| 850 | 847 | ||
| 851 | LOG_DEBUG(Service_HID, "called, can_vibrate={}", can_vibrate); | 848 | LOG_DEBUG(Service_HID, "called, can_vibrate={}", can_vibrate); |
| 852 | 849 | ||
| @@ -859,8 +856,7 @@ void Hid::IsVibrationPermitted(Kernel::HLERequestContext& ctx) { | |||
| 859 | 856 | ||
| 860 | IPC::ResponseBuilder rb{ctx, 3}; | 857 | IPC::ResponseBuilder rb{ctx, 3}; |
| 861 | rb.Push(RESULT_SUCCESS); | 858 | rb.Push(RESULT_SUCCESS); |
| 862 | rb.Push( | 859 | rb.Push(Settings::values.vibration_enabled); |
| 863 | applet_resource->GetController<Controller_NPad>(HidController::NPad).IsVibrationEnabled()); | ||
| 864 | } | 860 | } |
| 865 | 861 | ||
| 866 | void Hid::ActivateConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) { | 862 | void Hid::ActivateConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) { |
diff --git a/src/core/hle/service/nvdrv/devices/nvdevice.h b/src/core/hle/service/nvdrv/devices/nvdevice.h index 1b52511a5..0240d6643 100644 --- a/src/core/hle/service/nvdrv/devices/nvdevice.h +++ b/src/core/hle/service/nvdrv/devices/nvdevice.h | |||
| @@ -21,8 +21,9 @@ namespace Service::Nvidia::Devices { | |||
| 21 | /// implement the ioctl interface. | 21 | /// implement the ioctl interface. |
| 22 | class nvdevice { | 22 | class nvdevice { |
| 23 | public: | 23 | public: |
| 24 | explicit nvdevice(Core::System& system) : system{system} {}; | 24 | explicit nvdevice(Core::System& system) : system{system} {} |
| 25 | virtual ~nvdevice() = default; | 25 | virtual ~nvdevice() = default; |
| 26 | |||
| 26 | union Ioctl { | 27 | union Ioctl { |
| 27 | u32_le raw; | 28 | u32_le raw; |
| 28 | BitField<0, 8, u32> cmd; | 29 | BitField<0, 8, u32> cmd; |
diff --git a/src/core/hle/service/nvflinger/nvflinger.h b/src/core/hle/service/nvflinger/nvflinger.h index ff85cbba6..1ebe949c0 100644 --- a/src/core/hle/service/nvflinger/nvflinger.h +++ b/src/core/hle/service/nvflinger/nvflinger.h | |||
| @@ -86,11 +86,13 @@ public: | |||
| 86 | 86 | ||
| 87 | [[nodiscard]] s64 GetNextTicks() const; | 87 | [[nodiscard]] s64 GetNextTicks() const; |
| 88 | 88 | ||
| 89 | [[nodiscard]] std::unique_lock<std::mutex> Lock() const { return std::unique_lock{*guard}; } | 89 | [[nodiscard]] std::unique_lock<std::mutex> Lock() const { |
| 90 | return std::unique_lock{*guard}; | ||
| 91 | } | ||
| 90 | 92 | ||
| 91 | private : | 93 | private: |
| 92 | /// Finds the display identified by the specified ID. | 94 | /// Finds the display identified by the specified ID. |
| 93 | [[nodiscard]] VI::Display* FindDisplay(u64 display_id); | 95 | [[nodiscard]] VI::Display* FindDisplay(u64 display_id); |
| 94 | 96 | ||
| 95 | /// Finds the display identified by the specified ID. | 97 | /// Finds the display identified by the specified ID. |
| 96 | [[nodiscard]] const VI::Display* FindDisplay(u64 display_id) const; | 98 | [[nodiscard]] const VI::Display* FindDisplay(u64 display_id) const; |
diff --git a/src/core/hle/service/sm/sm.h b/src/core/hle/service/sm/sm.h index b526a94fe..aabf166b7 100644 --- a/src/core/hle/service/sm/sm.h +++ b/src/core/hle/service/sm/sm.h | |||
| @@ -57,7 +57,7 @@ public: | |||
| 57 | ResultVal<std::shared_ptr<Kernel::ClientPort>> GetServicePort(const std::string& name); | 57 | ResultVal<std::shared_ptr<Kernel::ClientPort>> GetServicePort(const std::string& name); |
| 58 | ResultVal<std::shared_ptr<Kernel::ClientSession>> ConnectToService(const std::string& name); | 58 | ResultVal<std::shared_ptr<Kernel::ClientSession>> ConnectToService(const std::string& name); |
| 59 | 59 | ||
| 60 | template <Common::IsBaseOf<Kernel::SessionRequestHandler> T> | 60 | template <Common::DerivedFrom<Kernel::SessionRequestHandler> T> |
| 61 | std::shared_ptr<T> GetService(const std::string& service_name) const { | 61 | std::shared_ptr<T> GetService(const std::string& service_name) const { |
| 62 | auto service = registered_services.find(service_name); | 62 | auto service = registered_services.find(service_name); |
| 63 | if (service == registered_services.end()) { | 63 | if (service == registered_services.end()) { |
diff --git a/src/core/hle/service/time/time_zone_content_manager.cpp b/src/core/hle/service/time/time_zone_content_manager.cpp index c070d6e97..320672add 100644 --- a/src/core/hle/service/time/time_zone_content_manager.cpp +++ b/src/core/hle/service/time/time_zone_content_manager.cpp | |||
| @@ -73,10 +73,8 @@ TimeZoneContentManager::TimeZoneContentManager(TimeManager& time_manager, Core:: | |||
| 73 | 73 | ||
| 74 | std::string location_name; | 74 | std::string location_name; |
| 75 | const auto timezone_setting = Settings::GetTimeZoneString(); | 75 | const auto timezone_setting = Settings::GetTimeZoneString(); |
| 76 | if (timezone_setting == "auto") { | 76 | if (timezone_setting == "auto" || timezone_setting == "default") { |
| 77 | location_name = Common::TimeZone::GetDefaultTimeZone(); | 77 | location_name = Common::TimeZone::GetDefaultTimeZone(); |
| 78 | } else if (timezone_setting == "default") { | ||
| 79 | location_name = location_name; | ||
| 80 | } else { | 78 | } else { |
| 81 | location_name = timezone_setting; | 79 | location_name = timezone_setting; |
| 82 | } | 80 | } |
diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp index b8f8f1448..9bc3a8840 100644 --- a/src/core/loader/loader.cpp +++ b/src/core/loader/loader.cpp | |||
| @@ -25,7 +25,7 @@ namespace Loader { | |||
| 25 | 25 | ||
| 26 | namespace { | 26 | namespace { |
| 27 | 27 | ||
| 28 | template <Common::IsBaseOf<AppLoader> T> | 28 | template <Common::DerivedFrom<AppLoader> T> |
| 29 | std::optional<FileType> IdentifyFileLoader(FileSys::VirtualFile file) { | 29 | std::optional<FileType> IdentifyFileLoader(FileSys::VirtualFile file) { |
| 30 | const auto file_type = T::IdentifyType(file); | 30 | const auto file_type = T::IdentifyType(file); |
| 31 | if (file_type != FileType::Error) { | 31 | if (file_type != FileType::Error) { |
| @@ -67,7 +67,7 @@ FileType GuessFromFilename(const std::string& name) { | |||
| 67 | return FileType::NCA; | 67 | return FileType::NCA; |
| 68 | 68 | ||
| 69 | const std::string extension = | 69 | const std::string extension = |
| 70 | Common::ToLower(std::string(FileUtil::GetExtensionFromFilename(name))); | 70 | Common::ToLower(std::string(Common::FS::GetExtensionFromFilename(name))); |
| 71 | 71 | ||
| 72 | if (extension == "elf") | 72 | if (extension == "elf") |
| 73 | return FileType::ELF; | 73 | return FileType::ELF; |
diff --git a/src/core/memory/cheat_engine.cpp b/src/core/memory/cheat_engine.cpp index eeebdf02e..e503118dd 100644 --- a/src/core/memory/cheat_engine.cpp +++ b/src/core/memory/cheat_engine.cpp | |||
| @@ -42,7 +42,7 @@ u64 StandardVmCallbacks::HidKeysDown() { | |||
| 42 | if (applet_resource == nullptr) { | 42 | if (applet_resource == nullptr) { |
| 43 | LOG_WARNING(CheatEngine, | 43 | LOG_WARNING(CheatEngine, |
| 44 | "Attempted to read input state, but applet resource is not initialized!"); | 44 | "Attempted to read input state, but applet resource is not initialized!"); |
| 45 | return false; | 45 | return 0; |
| 46 | } | 46 | } |
| 47 | 47 | ||
| 48 | const auto press_state = | 48 | const auto press_state = |
| @@ -199,17 +199,29 @@ void CheatEngine::Initialize() { | |||
| 199 | metadata.title_id = system.CurrentProcess()->GetTitleID(); | 199 | metadata.title_id = system.CurrentProcess()->GetTitleID(); |
| 200 | 200 | ||
| 201 | const auto& page_table = system.CurrentProcess()->PageTable(); | 201 | const auto& page_table = system.CurrentProcess()->PageTable(); |
| 202 | metadata.heap_extents = {page_table.GetHeapRegionStart(), page_table.GetHeapRegionSize()}; | 202 | metadata.heap_extents = { |
| 203 | metadata.address_space_extents = {page_table.GetAddressSpaceStart(), | 203 | .base = page_table.GetHeapRegionStart(), |
| 204 | page_table.GetAddressSpaceSize()}; | 204 | .size = page_table.GetHeapRegionSize(), |
| 205 | metadata.alias_extents = {page_table.GetAliasCodeRegionStart(), | 205 | }; |
| 206 | page_table.GetAliasCodeRegionSize()}; | 206 | |
| 207 | metadata.address_space_extents = { | ||
| 208 | .base = page_table.GetAddressSpaceStart(), | ||
| 209 | .size = page_table.GetAddressSpaceSize(), | ||
| 210 | }; | ||
| 211 | |||
| 212 | metadata.alias_extents = { | ||
| 213 | .base = page_table.GetAliasCodeRegionStart(), | ||
| 214 | .size = page_table.GetAliasCodeRegionSize(), | ||
| 215 | }; | ||
| 207 | 216 | ||
| 208 | is_pending_reload.exchange(true); | 217 | is_pending_reload.exchange(true); |
| 209 | } | 218 | } |
| 210 | 219 | ||
| 211 | void CheatEngine::SetMainMemoryParameters(VAddr main_region_begin, u64 main_region_size) { | 220 | void CheatEngine::SetMainMemoryParameters(VAddr main_region_begin, u64 main_region_size) { |
| 212 | metadata.main_nso_extents = {main_region_begin, main_region_size}; | 221 | metadata.main_nso_extents = { |
| 222 | .base = main_region_begin, | ||
| 223 | .size = main_region_size, | ||
| 224 | }; | ||
| 213 | } | 225 | } |
| 214 | 226 | ||
| 215 | void CheatEngine::Reload(std::vector<CheatEntry> cheats) { | 227 | void CheatEngine::Reload(std::vector<CheatEntry> cheats) { |
diff --git a/src/core/perf_stats.cpp b/src/core/perf_stats.cpp index b899ac884..b93396a80 100644 --- a/src/core/perf_stats.cpp +++ b/src/core/perf_stats.cpp | |||
| @@ -38,11 +38,11 @@ PerfStats::~PerfStats() { | |||
| 38 | std::ostringstream stream; | 38 | std::ostringstream stream; |
| 39 | std::copy(perf_history.begin() + IgnoreFrames, perf_history.begin() + current_index, | 39 | std::copy(perf_history.begin() + IgnoreFrames, perf_history.begin() + current_index, |
| 40 | std::ostream_iterator<double>(stream, "\n")); | 40 | std::ostream_iterator<double>(stream, "\n")); |
| 41 | const std::string& path = FileUtil::GetUserPath(FileUtil::UserPath::LogDir); | 41 | const std::string& path = Common::FS::GetUserPath(Common::FS::UserPath::LogDir); |
| 42 | // %F Date format expanded is "%Y-%m-%d" | 42 | // %F Date format expanded is "%Y-%m-%d" |
| 43 | const std::string filename = | 43 | const std::string filename = |
| 44 | fmt::format("{}/{:%F-%H-%M}_{:016X}.csv", path, *std::localtime(&t), title_id); | 44 | fmt::format("{}/{:%F-%H-%M}_{:016X}.csv", path, *std::localtime(&t), title_id); |
| 45 | FileUtil::IOFile file(filename, "w"); | 45 | Common::FS::IOFile file(filename, "w"); |
| 46 | file.WriteString(stream.str()); | 46 | file.WriteString(stream.str()); |
| 47 | } | 47 | } |
| 48 | 48 | ||
diff --git a/src/core/reporter.cpp b/src/core/reporter.cpp index 76cfa5a17..0becdf642 100644 --- a/src/core/reporter.cpp +++ b/src/core/reporter.cpp | |||
| @@ -28,8 +28,9 @@ | |||
| 28 | namespace { | 28 | namespace { |
| 29 | 29 | ||
| 30 | std::string GetPath(std::string_view type, u64 title_id, std::string_view timestamp) { | 30 | std::string GetPath(std::string_view type, u64 title_id, std::string_view timestamp) { |
| 31 | return fmt::format("{}{}/{:016X}_{}.json", FileUtil::GetUserPath(FileUtil::UserPath::LogDir), | 31 | return fmt::format("{}{}/{:016X}_{}.json", |
| 32 | type, title_id, timestamp); | 32 | Common::FS::GetUserPath(Common::FS::UserPath::LogDir), type, title_id, |
| 33 | timestamp); | ||
| 33 | } | 34 | } |
| 34 | 35 | ||
| 35 | std::string GetTimestamp() { | 36 | std::string GetTimestamp() { |
| @@ -40,13 +41,13 @@ std::string GetTimestamp() { | |||
| 40 | using namespace nlohmann; | 41 | using namespace nlohmann; |
| 41 | 42 | ||
| 42 | void SaveToFile(json json, const std::string& filename) { | 43 | void SaveToFile(json json, const std::string& filename) { |
| 43 | if (!FileUtil::CreateFullPath(filename)) { | 44 | if (!Common::FS::CreateFullPath(filename)) { |
| 44 | LOG_ERROR(Core, "Failed to create path for '{}' to save report!", filename); | 45 | LOG_ERROR(Core, "Failed to create path for '{}' to save report!", filename); |
| 45 | return; | 46 | return; |
| 46 | } | 47 | } |
| 47 | 48 | ||
| 48 | std::ofstream file( | 49 | std::ofstream file( |
| 49 | FileUtil::SanitizePath(filename, FileUtil::DirectorySeparator::PlatformDefault)); | 50 | Common::FS::SanitizePath(filename, Common::FS::DirectorySeparator::PlatformDefault)); |
| 50 | file << std::setw(4) << json << std::endl; | 51 | file << std::setw(4) << json << std::endl; |
| 51 | } | 52 | } |
| 52 | 53 | ||
diff --git a/src/core/settings.cpp b/src/core/settings.cpp index 416b2d866..28d3f9099 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp | |||
| @@ -13,56 +13,6 @@ | |||
| 13 | 13 | ||
| 14 | namespace Settings { | 14 | namespace Settings { |
| 15 | 15 | ||
| 16 | namespace NativeButton { | ||
| 17 | const std::array<const char*, NumButtons> mapping = {{ | ||
| 18 | "button_a", | ||
| 19 | "button_b", | ||
| 20 | "button_x", | ||
| 21 | "button_y", | ||
| 22 | "button_lstick", | ||
| 23 | "button_rstick", | ||
| 24 | "button_l", | ||
| 25 | "button_r", | ||
| 26 | "button_zl", | ||
| 27 | "button_zr", | ||
| 28 | "button_plus", | ||
| 29 | "button_minus", | ||
| 30 | "button_dleft", | ||
| 31 | "button_dup", | ||
| 32 | "button_dright", | ||
| 33 | "button_ddown", | ||
| 34 | "button_lstick_left", | ||
| 35 | "button_lstick_up", | ||
| 36 | "button_lstick_right", | ||
| 37 | "button_lstick_down", | ||
| 38 | "button_rstick_left", | ||
| 39 | "button_rstick_up", | ||
| 40 | "button_rstick_right", | ||
| 41 | "button_rstick_down", | ||
| 42 | "button_sl", | ||
| 43 | "button_sr", | ||
| 44 | "button_home", | ||
| 45 | "button_screenshot", | ||
| 46 | }}; | ||
| 47 | } | ||
| 48 | |||
| 49 | namespace NativeAnalog { | ||
| 50 | const std::array<const char*, NumAnalogs> mapping = {{ | ||
| 51 | "lstick", | ||
| 52 | "rstick", | ||
| 53 | }}; | ||
| 54 | } | ||
| 55 | |||
| 56 | namespace NativeMouseButton { | ||
| 57 | const std::array<const char*, NumMouseButtons> mapping = {{ | ||
| 58 | "left", | ||
| 59 | "right", | ||
| 60 | "middle", | ||
| 61 | "forward", | ||
| 62 | "back", | ||
| 63 | }}; | ||
| 64 | } | ||
| 65 | |||
| 66 | Values values = {}; | 16 | Values values = {}; |
| 67 | bool configuring_global = true; | 17 | bool configuring_global = true; |
| 68 | 18 | ||
| @@ -121,8 +71,8 @@ void LogSettings() { | |||
| 121 | log_setting("Audio_EnableAudioStretching", values.enable_audio_stretching.GetValue()); | 71 | log_setting("Audio_EnableAudioStretching", values.enable_audio_stretching.GetValue()); |
| 122 | log_setting("Audio_OutputDevice", values.audio_device_id); | 72 | log_setting("Audio_OutputDevice", values.audio_device_id); |
| 123 | log_setting("DataStorage_UseVirtualSd", values.use_virtual_sd); | 73 | log_setting("DataStorage_UseVirtualSd", values.use_virtual_sd); |
| 124 | log_setting("DataStorage_NandDir", FileUtil::GetUserPath(FileUtil::UserPath::NANDDir)); | 74 | log_setting("DataStorage_NandDir", Common::FS::GetUserPath(Common::FS::UserPath::NANDDir)); |
| 125 | log_setting("DataStorage_SdmcDir", FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir)); | 75 | log_setting("DataStorage_SdmcDir", Common::FS::GetUserPath(Common::FS::UserPath::SDMCDir)); |
| 126 | log_setting("Debugging_UseGdbstub", values.use_gdbstub); | 76 | log_setting("Debugging_UseGdbstub", values.use_gdbstub); |
| 127 | log_setting("Debugging_GdbstubPort", values.gdbstub_port); | 77 | log_setting("Debugging_GdbstubPort", values.gdbstub_port); |
| 128 | log_setting("Debugging_ProgramArgs", values.program_args); | 78 | log_setting("Debugging_ProgramArgs", values.program_args); |
diff --git a/src/core/settings.h b/src/core/settings.h index bb145f193..732c6a894 100644 --- a/src/core/settings.h +++ b/src/core/settings.h | |||
| @@ -12,340 +12,10 @@ | |||
| 12 | #include <string> | 12 | #include <string> |
| 13 | #include <vector> | 13 | #include <vector> |
| 14 | #include "common/common_types.h" | 14 | #include "common/common_types.h" |
| 15 | #include "input_common/settings.h" | ||
| 15 | 16 | ||
| 16 | namespace Settings { | 17 | namespace Settings { |
| 17 | 18 | ||
| 18 | namespace NativeButton { | ||
| 19 | enum Values { | ||
| 20 | A, | ||
| 21 | B, | ||
| 22 | X, | ||
| 23 | Y, | ||
| 24 | LStick, | ||
| 25 | RStick, | ||
| 26 | L, | ||
| 27 | R, | ||
| 28 | ZL, | ||
| 29 | ZR, | ||
| 30 | Plus, | ||
| 31 | Minus, | ||
| 32 | |||
| 33 | DLeft, | ||
| 34 | DUp, | ||
| 35 | DRight, | ||
| 36 | DDown, | ||
| 37 | |||
| 38 | LStick_Left, | ||
| 39 | LStick_Up, | ||
| 40 | LStick_Right, | ||
| 41 | LStick_Down, | ||
| 42 | |||
| 43 | RStick_Left, | ||
| 44 | RStick_Up, | ||
| 45 | RStick_Right, | ||
| 46 | RStick_Down, | ||
| 47 | |||
| 48 | SL, | ||
| 49 | SR, | ||
| 50 | |||
| 51 | Home, | ||
| 52 | Screenshot, | ||
| 53 | |||
| 54 | NumButtons, | ||
| 55 | }; | ||
| 56 | |||
| 57 | constexpr int BUTTON_HID_BEGIN = A; | ||
| 58 | constexpr int BUTTON_NS_BEGIN = Home; | ||
| 59 | |||
| 60 | constexpr int BUTTON_HID_END = BUTTON_NS_BEGIN; | ||
| 61 | constexpr int BUTTON_NS_END = NumButtons; | ||
| 62 | |||
| 63 | constexpr int NUM_BUTTONS_HID = BUTTON_HID_END - BUTTON_HID_BEGIN; | ||
| 64 | constexpr int NUM_BUTTONS_NS = BUTTON_NS_END - BUTTON_NS_BEGIN; | ||
| 65 | |||
| 66 | extern const std::array<const char*, NumButtons> mapping; | ||
| 67 | |||
| 68 | } // namespace NativeButton | ||
| 69 | |||
| 70 | namespace NativeAnalog { | ||
| 71 | enum Values { | ||
| 72 | LStick, | ||
| 73 | RStick, | ||
| 74 | |||
| 75 | NumAnalogs, | ||
| 76 | }; | ||
| 77 | |||
| 78 | constexpr int STICK_HID_BEGIN = LStick; | ||
| 79 | constexpr int STICK_HID_END = NumAnalogs; | ||
| 80 | constexpr int NUM_STICKS_HID = NumAnalogs; | ||
| 81 | |||
| 82 | extern const std::array<const char*, NumAnalogs> mapping; | ||
| 83 | } // namespace NativeAnalog | ||
| 84 | |||
| 85 | namespace NativeMouseButton { | ||
| 86 | enum Values { | ||
| 87 | Left, | ||
| 88 | Right, | ||
| 89 | Middle, | ||
| 90 | Forward, | ||
| 91 | Back, | ||
| 92 | |||
| 93 | NumMouseButtons, | ||
| 94 | }; | ||
| 95 | |||
| 96 | constexpr int MOUSE_HID_BEGIN = Left; | ||
| 97 | constexpr int MOUSE_HID_END = NumMouseButtons; | ||
| 98 | constexpr int NUM_MOUSE_HID = NumMouseButtons; | ||
| 99 | |||
| 100 | extern const std::array<const char*, NumMouseButtons> mapping; | ||
| 101 | } // namespace NativeMouseButton | ||
| 102 | |||
| 103 | namespace NativeKeyboard { | ||
| 104 | enum Keys { | ||
| 105 | None, | ||
| 106 | Error, | ||
| 107 | |||
| 108 | A = 4, | ||
| 109 | B, | ||
| 110 | C, | ||
| 111 | D, | ||
| 112 | E, | ||
| 113 | F, | ||
| 114 | G, | ||
| 115 | H, | ||
| 116 | I, | ||
| 117 | J, | ||
| 118 | K, | ||
| 119 | L, | ||
| 120 | M, | ||
| 121 | N, | ||
| 122 | O, | ||
| 123 | P, | ||
| 124 | Q, | ||
| 125 | R, | ||
| 126 | S, | ||
| 127 | T, | ||
| 128 | U, | ||
| 129 | V, | ||
| 130 | W, | ||
| 131 | X, | ||
| 132 | Y, | ||
| 133 | Z, | ||
| 134 | N1, | ||
| 135 | N2, | ||
| 136 | N3, | ||
| 137 | N4, | ||
| 138 | N5, | ||
| 139 | N6, | ||
| 140 | N7, | ||
| 141 | N8, | ||
| 142 | N9, | ||
| 143 | N0, | ||
| 144 | Enter, | ||
| 145 | Escape, | ||
| 146 | Backspace, | ||
| 147 | Tab, | ||
| 148 | Space, | ||
| 149 | Minus, | ||
| 150 | Equal, | ||
| 151 | LeftBrace, | ||
| 152 | RightBrace, | ||
| 153 | Backslash, | ||
| 154 | Tilde, | ||
| 155 | Semicolon, | ||
| 156 | Apostrophe, | ||
| 157 | Grave, | ||
| 158 | Comma, | ||
| 159 | Dot, | ||
| 160 | Slash, | ||
| 161 | CapsLockKey, | ||
| 162 | |||
| 163 | F1, | ||
| 164 | F2, | ||
| 165 | F3, | ||
| 166 | F4, | ||
| 167 | F5, | ||
| 168 | F6, | ||
| 169 | F7, | ||
| 170 | F8, | ||
| 171 | F9, | ||
| 172 | F10, | ||
| 173 | F11, | ||
| 174 | F12, | ||
| 175 | |||
| 176 | SystemRequest, | ||
| 177 | ScrollLockKey, | ||
| 178 | Pause, | ||
| 179 | Insert, | ||
| 180 | Home, | ||
| 181 | PageUp, | ||
| 182 | Delete, | ||
| 183 | End, | ||
| 184 | PageDown, | ||
| 185 | Right, | ||
| 186 | Left, | ||
| 187 | Down, | ||
| 188 | Up, | ||
| 189 | |||
| 190 | NumLockKey, | ||
| 191 | KPSlash, | ||
| 192 | KPAsterisk, | ||
| 193 | KPMinus, | ||
| 194 | KPPlus, | ||
| 195 | KPEnter, | ||
| 196 | KP1, | ||
| 197 | KP2, | ||
| 198 | KP3, | ||
| 199 | KP4, | ||
| 200 | KP5, | ||
| 201 | KP6, | ||
| 202 | KP7, | ||
| 203 | KP8, | ||
| 204 | KP9, | ||
| 205 | KP0, | ||
| 206 | KPDot, | ||
| 207 | |||
| 208 | Key102, | ||
| 209 | Compose, | ||
| 210 | Power, | ||
| 211 | KPEqual, | ||
| 212 | |||
| 213 | F13, | ||
| 214 | F14, | ||
| 215 | F15, | ||
| 216 | F16, | ||
| 217 | F17, | ||
| 218 | F18, | ||
| 219 | F19, | ||
| 220 | F20, | ||
| 221 | F21, | ||
| 222 | F22, | ||
| 223 | F23, | ||
| 224 | F24, | ||
| 225 | |||
| 226 | Open, | ||
| 227 | Help, | ||
| 228 | Properties, | ||
| 229 | Front, | ||
| 230 | Stop, | ||
| 231 | Repeat, | ||
| 232 | Undo, | ||
| 233 | Cut, | ||
| 234 | Copy, | ||
| 235 | Paste, | ||
| 236 | Find, | ||
| 237 | Mute, | ||
| 238 | VolumeUp, | ||
| 239 | VolumeDown, | ||
| 240 | CapsLockActive, | ||
| 241 | NumLockActive, | ||
| 242 | ScrollLockActive, | ||
| 243 | KPComma, | ||
| 244 | |||
| 245 | KPLeftParenthesis, | ||
| 246 | KPRightParenthesis, | ||
| 247 | |||
| 248 | LeftControlKey = 0xE0, | ||
| 249 | LeftShiftKey, | ||
| 250 | LeftAltKey, | ||
| 251 | LeftMetaKey, | ||
| 252 | RightControlKey, | ||
| 253 | RightShiftKey, | ||
| 254 | RightAltKey, | ||
| 255 | RightMetaKey, | ||
| 256 | |||
| 257 | MediaPlayPause, | ||
| 258 | MediaStopCD, | ||
| 259 | MediaPrevious, | ||
| 260 | MediaNext, | ||
| 261 | MediaEject, | ||
| 262 | MediaVolumeUp, | ||
| 263 | MediaVolumeDown, | ||
| 264 | MediaMute, | ||
| 265 | MediaWebsite, | ||
| 266 | MediaBack, | ||
| 267 | MediaForward, | ||
| 268 | MediaStop, | ||
| 269 | MediaFind, | ||
| 270 | MediaScrollUp, | ||
| 271 | MediaScrollDown, | ||
| 272 | MediaEdit, | ||
| 273 | MediaSleep, | ||
| 274 | MediaCoffee, | ||
| 275 | MediaRefresh, | ||
| 276 | MediaCalculator, | ||
| 277 | |||
| 278 | NumKeyboardKeys, | ||
| 279 | }; | ||
| 280 | |||
| 281 | static_assert(NumKeyboardKeys == 0xFC, "Incorrect number of keyboard keys."); | ||
| 282 | |||
| 283 | enum Modifiers { | ||
| 284 | LeftControl, | ||
| 285 | LeftShift, | ||
| 286 | LeftAlt, | ||
| 287 | LeftMeta, | ||
| 288 | RightControl, | ||
| 289 | RightShift, | ||
| 290 | RightAlt, | ||
| 291 | RightMeta, | ||
| 292 | CapsLock, | ||
| 293 | ScrollLock, | ||
| 294 | NumLock, | ||
| 295 | |||
| 296 | NumKeyboardMods, | ||
| 297 | }; | ||
| 298 | |||
| 299 | constexpr int KEYBOARD_KEYS_HID_BEGIN = None; | ||
| 300 | constexpr int KEYBOARD_KEYS_HID_END = NumKeyboardKeys; | ||
| 301 | constexpr int NUM_KEYBOARD_KEYS_HID = NumKeyboardKeys; | ||
| 302 | |||
| 303 | constexpr int KEYBOARD_MODS_HID_BEGIN = LeftControl; | ||
| 304 | constexpr int KEYBOARD_MODS_HID_END = NumKeyboardMods; | ||
| 305 | constexpr int NUM_KEYBOARD_MODS_HID = NumKeyboardMods; | ||
| 306 | |||
| 307 | } // namespace NativeKeyboard | ||
| 308 | |||
| 309 | using ButtonsRaw = std::array<std::string, NativeButton::NumButtons>; | ||
| 310 | using AnalogsRaw = std::array<std::string, NativeAnalog::NumAnalogs>; | ||
| 311 | using MouseButtonsRaw = std::array<std::string, NativeMouseButton::NumMouseButtons>; | ||
| 312 | using KeyboardKeysRaw = std::array<std::string, NativeKeyboard::NumKeyboardKeys>; | ||
| 313 | using KeyboardModsRaw = std::array<std::string, NativeKeyboard::NumKeyboardMods>; | ||
| 314 | |||
| 315 | constexpr u32 JOYCON_BODY_NEON_RED = 0xFF3C28; | ||
| 316 | constexpr u32 JOYCON_BUTTONS_NEON_RED = 0x1E0A0A; | ||
| 317 | constexpr u32 JOYCON_BODY_NEON_BLUE = 0x0AB9E6; | ||
| 318 | constexpr u32 JOYCON_BUTTONS_NEON_BLUE = 0x001E1E; | ||
| 319 | |||
| 320 | enum class ControllerType { | ||
| 321 | ProController, | ||
| 322 | DualJoycon, | ||
| 323 | RightJoycon, | ||
| 324 | LeftJoycon, | ||
| 325 | }; | ||
| 326 | |||
| 327 | struct PlayerInput { | ||
| 328 | bool connected; | ||
| 329 | ControllerType type; | ||
| 330 | ButtonsRaw buttons; | ||
| 331 | AnalogsRaw analogs; | ||
| 332 | |||
| 333 | u32 body_color_right; | ||
| 334 | u32 button_color_right; | ||
| 335 | u32 body_color_left; | ||
| 336 | u32 button_color_left; | ||
| 337 | }; | ||
| 338 | |||
| 339 | struct TouchscreenInput { | ||
| 340 | bool enabled; | ||
| 341 | std::string device; | ||
| 342 | |||
| 343 | u32 finger; | ||
| 344 | u32 diameter_x; | ||
| 345 | u32 diameter_y; | ||
| 346 | u32 rotation_angle; | ||
| 347 | }; | ||
| 348 | |||
| 349 | enum class RendererBackend { | 19 | enum class RendererBackend { |
| 350 | OpenGL = 0, | 20 | OpenGL = 0, |
| 351 | Vulkan = 1, | 21 | Vulkan = 1, |
| @@ -359,7 +29,8 @@ enum class GPUAccuracy : u32 { | |||
| 359 | 29 | ||
| 360 | enum class CPUAccuracy { | 30 | enum class CPUAccuracy { |
| 361 | Accurate = 0, | 31 | Accurate = 0, |
| 362 | DebugMode = 1, | 32 | Unsafe = 1, |
| 33 | DebugMode = 2, | ||
| 363 | }; | 34 | }; |
| 364 | 35 | ||
| 365 | extern bool configuring_global; | 36 | extern bool configuring_global; |
| @@ -419,6 +90,9 @@ struct Values { | |||
| 419 | bool cpuopt_misc_ir; | 90 | bool cpuopt_misc_ir; |
| 420 | bool cpuopt_reduce_misalign_checks; | 91 | bool cpuopt_reduce_misalign_checks; |
| 421 | 92 | ||
| 93 | bool cpuopt_unsafe_unfuse_fma; | ||
| 94 | bool cpuopt_unsafe_reduce_fp_error; | ||
| 95 | |||
| 422 | // Renderer | 96 | // Renderer |
| 423 | Setting<RendererBackend> renderer_backend; | 97 | Setting<RendererBackend> renderer_backend; |
| 424 | bool renderer_debug; | 98 | bool renderer_debug; |
| @@ -457,6 +131,8 @@ struct Values { | |||
| 457 | // Controls | 131 | // Controls |
| 458 | std::array<PlayerInput, 10> players; | 132 | std::array<PlayerInput, 10> players; |
| 459 | 133 | ||
| 134 | bool use_docked_mode; | ||
| 135 | |||
| 460 | bool mouse_enabled; | 136 | bool mouse_enabled; |
| 461 | std::string mouse_device; | 137 | std::string mouse_device; |
| 462 | MouseButtonsRaw mouse_buttons; | 138 | MouseButtonsRaw mouse_buttons; |
| @@ -470,14 +146,15 @@ struct Values { | |||
| 470 | AnalogsRaw debug_pad_analogs; | 146 | AnalogsRaw debug_pad_analogs; |
| 471 | 147 | ||
| 472 | std::string motion_device; | 148 | std::string motion_device; |
| 149 | |||
| 150 | bool vibration_enabled; | ||
| 151 | |||
| 473 | TouchscreenInput touchscreen; | 152 | TouchscreenInput touchscreen; |
| 474 | std::atomic_bool is_device_reload_pending{true}; | 153 | std::atomic_bool is_device_reload_pending{true}; |
| 475 | std::string udp_input_address; | 154 | std::string udp_input_address; |
| 476 | u16 udp_input_port; | 155 | u16 udp_input_port; |
| 477 | u8 udp_pad_index; | 156 | u8 udp_pad_index; |
| 478 | 157 | ||
| 479 | bool use_docked_mode; | ||
| 480 | |||
| 481 | // Data Storage | 158 | // Data Storage |
| 482 | bool use_virtual_sd; | 159 | bool use_virtual_sd; |
| 483 | bool gamecard_inserted; | 160 | bool gamecard_inserted; |
diff --git a/src/core/telemetry_session.cpp b/src/core/telemetry_session.cpp index 5a30c75da..da09c0dbc 100644 --- a/src/core/telemetry_session.cpp +++ b/src/core/telemetry_session.cpp | |||
| @@ -25,6 +25,8 @@ | |||
| 25 | 25 | ||
| 26 | namespace Core { | 26 | namespace Core { |
| 27 | 27 | ||
| 28 | namespace Telemetry = Common::Telemetry; | ||
| 29 | |||
| 28 | static u64 GenerateTelemetryId() { | 30 | static u64 GenerateTelemetryId() { |
| 29 | u64 telemetry_id{}; | 31 | u64 telemetry_id{}; |
| 30 | 32 | ||
| @@ -70,12 +72,12 @@ static const char* TranslateGPUAccuracyLevel(Settings::GPUAccuracy backend) { | |||
| 70 | 72 | ||
| 71 | u64 GetTelemetryId() { | 73 | u64 GetTelemetryId() { |
| 72 | u64 telemetry_id{}; | 74 | u64 telemetry_id{}; |
| 73 | const std::string filename{FileUtil::GetUserPath(FileUtil::UserPath::ConfigDir) + | 75 | const std::string filename{Common::FS::GetUserPath(Common::FS::UserPath::ConfigDir) + |
| 74 | "telemetry_id"}; | 76 | "telemetry_id"}; |
| 75 | 77 | ||
| 76 | bool generate_new_id = !FileUtil::Exists(filename); | 78 | bool generate_new_id = !Common::FS::Exists(filename); |
| 77 | if (!generate_new_id) { | 79 | if (!generate_new_id) { |
| 78 | FileUtil::IOFile file(filename, "rb"); | 80 | Common::FS::IOFile file(filename, "rb"); |
| 79 | if (!file.IsOpen()) { | 81 | if (!file.IsOpen()) { |
| 80 | LOG_ERROR(Core, "failed to open telemetry_id: {}", filename); | 82 | LOG_ERROR(Core, "failed to open telemetry_id: {}", filename); |
| 81 | return {}; | 83 | return {}; |
| @@ -88,7 +90,7 @@ u64 GetTelemetryId() { | |||
| 88 | } | 90 | } |
| 89 | 91 | ||
| 90 | if (generate_new_id) { | 92 | if (generate_new_id) { |
| 91 | FileUtil::IOFile file(filename, "wb"); | 93 | Common::FS::IOFile file(filename, "wb"); |
| 92 | if (!file.IsOpen()) { | 94 | if (!file.IsOpen()) { |
| 93 | LOG_ERROR(Core, "failed to open telemetry_id: {}", filename); | 95 | LOG_ERROR(Core, "failed to open telemetry_id: {}", filename); |
| 94 | return {}; | 96 | return {}; |
| @@ -102,10 +104,10 @@ u64 GetTelemetryId() { | |||
| 102 | 104 | ||
| 103 | u64 RegenerateTelemetryId() { | 105 | u64 RegenerateTelemetryId() { |
| 104 | const u64 new_telemetry_id{GenerateTelemetryId()}; | 106 | const u64 new_telemetry_id{GenerateTelemetryId()}; |
| 105 | const std::string filename{FileUtil::GetUserPath(FileUtil::UserPath::ConfigDir) + | 107 | const std::string filename{Common::FS::GetUserPath(Common::FS::UserPath::ConfigDir) + |
| 106 | "telemetry_id"}; | 108 | "telemetry_id"}; |
| 107 | 109 | ||
| 108 | FileUtil::IOFile file(filename, "wb"); | 110 | Common::FS::IOFile file(filename, "wb"); |
| 109 | if (!file.IsOpen()) { | 111 | if (!file.IsOpen()) { |
| 110 | LOG_ERROR(Core, "failed to open telemetry_id: {}", filename); | 112 | LOG_ERROR(Core, "failed to open telemetry_id: {}", filename); |
| 111 | return {}; | 113 | return {}; |
diff --git a/src/core/telemetry_session.h b/src/core/telemetry_session.h index 17ac22377..66789d4bd 100644 --- a/src/core/telemetry_session.h +++ b/src/core/telemetry_session.h | |||
| @@ -52,7 +52,7 @@ public: | |||
| 52 | * @param value Value for the field to add. | 52 | * @param value Value for the field to add. |
| 53 | */ | 53 | */ |
| 54 | template <typename T> | 54 | template <typename T> |
| 55 | void AddField(Telemetry::FieldType type, const char* name, T value) { | 55 | void AddField(Common::Telemetry::FieldType type, const char* name, T value) { |
| 56 | field_collection.AddField(type, name, std::move(value)); | 56 | field_collection.AddField(type, name, std::move(value)); |
| 57 | } | 57 | } |
| 58 | 58 | ||
| @@ -63,7 +63,8 @@ public: | |||
| 63 | bool SubmitTestcase(); | 63 | bool SubmitTestcase(); |
| 64 | 64 | ||
| 65 | private: | 65 | private: |
| 66 | Telemetry::FieldCollection field_collection; ///< Tracks all added fields for the session | 66 | /// Tracks all added fields for the session |
| 67 | Common::Telemetry::FieldCollection field_collection; | ||
| 67 | }; | 68 | }; |
| 68 | 69 | ||
| 69 | /** | 70 | /** |
diff --git a/src/core/tools/freezer.cpp b/src/core/tools/freezer.cpp index 2003e096f..5c674a099 100644 --- a/src/core/tools/freezer.cpp +++ b/src/core/tools/freezer.cpp | |||
| @@ -107,28 +107,21 @@ void Freezer::Unfreeze(VAddr address) { | |||
| 107 | 107 | ||
| 108 | LOG_DEBUG(Common_Memory, "Unfreezing memory for address={:016X}", address); | 108 | LOG_DEBUG(Common_Memory, "Unfreezing memory for address={:016X}", address); |
| 109 | 109 | ||
| 110 | entries.erase( | 110 | std::erase_if(entries, [address](const Entry& entry) { return entry.address == address; }); |
| 111 | std::remove_if(entries.begin(), entries.end(), | ||
| 112 | [&address](const Entry& entry) { return entry.address == address; }), | ||
| 113 | entries.end()); | ||
| 114 | } | 111 | } |
| 115 | 112 | ||
| 116 | bool Freezer::IsFrozen(VAddr address) const { | 113 | bool Freezer::IsFrozen(VAddr address) const { |
| 117 | std::lock_guard lock{entries_mutex}; | 114 | std::lock_guard lock{entries_mutex}; |
| 118 | 115 | ||
| 119 | return std::find_if(entries.begin(), entries.end(), [&address](const Entry& entry) { | 116 | return FindEntry(address) != entries.cend(); |
| 120 | return entry.address == address; | ||
| 121 | }) != entries.end(); | ||
| 122 | } | 117 | } |
| 123 | 118 | ||
| 124 | void Freezer::SetFrozenValue(VAddr address, u64 value) { | 119 | void Freezer::SetFrozenValue(VAddr address, u64 value) { |
| 125 | std::lock_guard lock{entries_mutex}; | 120 | std::lock_guard lock{entries_mutex}; |
| 126 | 121 | ||
| 127 | const auto iter = std::find_if(entries.begin(), entries.end(), [&address](const Entry& entry) { | 122 | const auto iter = FindEntry(address); |
| 128 | return entry.address == address; | ||
| 129 | }); | ||
| 130 | 123 | ||
| 131 | if (iter == entries.end()) { | 124 | if (iter == entries.cend()) { |
| 132 | LOG_ERROR(Common_Memory, | 125 | LOG_ERROR(Common_Memory, |
| 133 | "Tried to set freeze value for address={:016X} that is not frozen!", address); | 126 | "Tried to set freeze value for address={:016X} that is not frozen!", address); |
| 134 | return; | 127 | return; |
| @@ -143,11 +136,9 @@ void Freezer::SetFrozenValue(VAddr address, u64 value) { | |||
| 143 | std::optional<Freezer::Entry> Freezer::GetEntry(VAddr address) const { | 136 | std::optional<Freezer::Entry> Freezer::GetEntry(VAddr address) const { |
| 144 | std::lock_guard lock{entries_mutex}; | 137 | std::lock_guard lock{entries_mutex}; |
| 145 | 138 | ||
| 146 | const auto iter = std::find_if(entries.begin(), entries.end(), [&address](const Entry& entry) { | 139 | const auto iter = FindEntry(address); |
| 147 | return entry.address == address; | ||
| 148 | }); | ||
| 149 | 140 | ||
| 150 | if (iter == entries.end()) { | 141 | if (iter == entries.cend()) { |
| 151 | return std::nullopt; | 142 | return std::nullopt; |
| 152 | } | 143 | } |
| 153 | 144 | ||
| @@ -160,6 +151,16 @@ std::vector<Freezer::Entry> Freezer::GetEntries() const { | |||
| 160 | return entries; | 151 | return entries; |
| 161 | } | 152 | } |
| 162 | 153 | ||
| 154 | Freezer::Entries::iterator Freezer::FindEntry(VAddr address) { | ||
| 155 | return std::find_if(entries.begin(), entries.end(), | ||
| 156 | [address](const Entry& entry) { return entry.address == address; }); | ||
| 157 | } | ||
| 158 | |||
| 159 | Freezer::Entries::const_iterator Freezer::FindEntry(VAddr address) const { | ||
| 160 | return std::find_if(entries.begin(), entries.end(), | ||
| 161 | [address](const Entry& entry) { return entry.address == address; }); | ||
| 162 | } | ||
| 163 | |||
| 163 | void Freezer::FrameCallback(std::uintptr_t, std::chrono::nanoseconds ns_late) { | 164 | void Freezer::FrameCallback(std::uintptr_t, std::chrono::nanoseconds ns_late) { |
| 164 | if (!IsActive()) { | 165 | if (!IsActive()) { |
| 165 | LOG_DEBUG(Common_Memory, "Memory freezer has been deactivated, ending callback events."); | 166 | LOG_DEBUG(Common_Memory, "Memory freezer has been deactivated, ending callback events."); |
diff --git a/src/core/tools/freezer.h b/src/core/tools/freezer.h index 2b2326bc4..0fdb701a7 100644 --- a/src/core/tools/freezer.h +++ b/src/core/tools/freezer.h | |||
| @@ -73,13 +73,18 @@ public: | |||
| 73 | std::vector<Entry> GetEntries() const; | 73 | std::vector<Entry> GetEntries() const; |
| 74 | 74 | ||
| 75 | private: | 75 | private: |
| 76 | using Entries = std::vector<Entry>; | ||
| 77 | |||
| 78 | Entries::iterator FindEntry(VAddr address); | ||
| 79 | Entries::const_iterator FindEntry(VAddr address) const; | ||
| 80 | |||
| 76 | void FrameCallback(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); | 81 | void FrameCallback(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); |
| 77 | void FillEntryReads(); | 82 | void FillEntryReads(); |
| 78 | 83 | ||
| 79 | std::atomic_bool active{false}; | 84 | std::atomic_bool active{false}; |
| 80 | 85 | ||
| 81 | mutable std::mutex entries_mutex; | 86 | mutable std::mutex entries_mutex; |
| 82 | std::vector<Entry> entries; | 87 | Entries entries; |
| 83 | 88 | ||
| 84 | std::shared_ptr<Core::Timing::EventType> event; | 89 | std::shared_ptr<Core::Timing::EventType> event; |
| 85 | Core::Timing::CoreTiming& core_timing; | 90 | Core::Timing::CoreTiming& core_timing; |
diff --git a/src/input_common/CMakeLists.txt b/src/input_common/CMakeLists.txt index 317c25bad..56267c8a8 100644 --- a/src/input_common/CMakeLists.txt +++ b/src/input_common/CMakeLists.txt | |||
| @@ -7,6 +7,8 @@ add_library(input_common STATIC | |||
| 7 | main.h | 7 | main.h |
| 8 | motion_emu.cpp | 8 | motion_emu.cpp |
| 9 | motion_emu.h | 9 | motion_emu.h |
| 10 | settings.cpp | ||
| 11 | settings.h | ||
| 10 | gcadapter/gc_adapter.cpp | 12 | gcadapter/gc_adapter.cpp |
| 11 | gcadapter/gc_adapter.h | 13 | gcadapter/gc_adapter.h |
| 12 | gcadapter/gc_poller.cpp | 14 | gcadapter/gc_poller.cpp |
diff --git a/src/input_common/gcadapter/gc_poller.cpp b/src/input_common/gcadapter/gc_poller.cpp index f45983f3f..71cd85eeb 100644 --- a/src/input_common/gcadapter/gc_poller.cpp +++ b/src/input_common/gcadapter/gc_poller.cpp | |||
| @@ -148,19 +148,17 @@ void GCButtonFactory::EndConfiguration() { | |||
| 148 | 148 | ||
| 149 | class GCAnalog final : public Input::AnalogDevice { | 149 | class GCAnalog final : public Input::AnalogDevice { |
| 150 | public: | 150 | public: |
| 151 | GCAnalog(int port_, int axis_x_, int axis_y_, float deadzone_, GCAdapter::Adapter* adapter) | 151 | GCAnalog(int port_, int axis_x_, int axis_y_, float deadzone_, GCAdapter::Adapter* adapter, |
| 152 | float range_) | ||
| 152 | : 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), |
| 153 | origin_value_x(adapter->GetOriginValue(port_, axis_x_)), | 154 | origin_value_x(adapter->GetOriginValue(port_, axis_x_)), |
| 154 | origin_value_y(adapter->GetOriginValue(port_, axis_y_)) {} | 155 | origin_value_y(adapter->GetOriginValue(port_, axis_y_)), range(range_) {} |
| 155 | 156 | ||
| 156 | float GetAxis(int axis) const { | 157 | float GetAxis(int axis) const { |
| 157 | if (gcadapter->DeviceConnected(port)) { | 158 | if (gcadapter->DeviceConnected(port)) { |
| 158 | std::lock_guard lock{mutex}; | 159 | std::lock_guard lock{mutex}; |
| 159 | const auto origin_value = axis % 2 == 0 ? origin_value_x : origin_value_y; | 160 | const auto origin_value = axis % 2 == 0 ? origin_value_x : origin_value_y; |
| 160 | // division is not by a perfect 128 to account for some variance in center location | 161 | return (gcadapter->GetPadState()[port].axes.at(axis) - origin_value) / (100.0f * range); |
| 161 | // e.g. my device idled at 131 in X, 120 in Y, and full range of motion was in range | ||
| 162 | // [20-230] | ||
| 163 | return (gcadapter->GetPadState()[port].axes.at(axis) - origin_value) / 95.0f; | ||
| 164 | } | 162 | } |
| 165 | return 0.0f; | 163 | return 0.0f; |
| 166 | } | 164 | } |
| @@ -193,7 +191,7 @@ public: | |||
| 193 | 191 | ||
| 194 | bool GetAnalogDirectionStatus(Input::AnalogDirection direction) const override { | 192 | bool GetAnalogDirectionStatus(Input::AnalogDirection direction) const override { |
| 195 | const auto [x, y] = GetStatus(); | 193 | const auto [x, y] = GetStatus(); |
| 196 | const float directional_deadzone = 0.4f; | 194 | const float directional_deadzone = 0.5f; |
| 197 | switch (direction) { | 195 | switch (direction) { |
| 198 | case Input::AnalogDirection::RIGHT: | 196 | case Input::AnalogDirection::RIGHT: |
| 199 | return x > directional_deadzone; | 197 | return x > directional_deadzone; |
| @@ -215,6 +213,7 @@ private: | |||
| 215 | GCAdapter::Adapter* gcadapter; | 213 | GCAdapter::Adapter* gcadapter; |
| 216 | const float origin_value_x; | 214 | const float origin_value_x; |
| 217 | const float origin_value_y; | 215 | const float origin_value_y; |
| 216 | const float range; | ||
| 218 | mutable std::mutex mutex; | 217 | mutable std::mutex mutex; |
| 219 | }; | 218 | }; |
| 220 | 219 | ||
| @@ -233,9 +232,10 @@ std::unique_ptr<Input::AnalogDevice> GCAnalogFactory::Create(const Common::Param | |||
| 233 | const int port = params.Get("port", 0); | 232 | const int port = params.Get("port", 0); |
| 234 | const int axis_x = params.Get("axis_x", 0); | 233 | const int axis_x = params.Get("axis_x", 0); |
| 235 | const int axis_y = params.Get("axis_y", 1); | 234 | const int axis_y = params.Get("axis_y", 1); |
| 236 | const float deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, .99f); | 235 | const float deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, 1.0f); |
| 236 | const float range = std::clamp(params.Get("range", 1.0f), 0.50f, 1.50f); | ||
| 237 | 237 | ||
| 238 | return std::make_unique<GCAnalog>(port, axis_x, axis_y, deadzone, adapter.get()); | 238 | return std::make_unique<GCAnalog>(port, axis_x, axis_y, deadzone, adapter.get(), range); |
| 239 | } | 239 | } |
| 240 | 240 | ||
| 241 | void GCAnalogFactory::BeginConfiguration() { | 241 | void GCAnalogFactory::BeginConfiguration() { |
diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp index b9d5d0ec3..57e7a25fe 100644 --- a/src/input_common/main.cpp +++ b/src/input_common/main.cpp | |||
| @@ -18,67 +18,166 @@ | |||
| 18 | 18 | ||
| 19 | namespace InputCommon { | 19 | namespace InputCommon { |
| 20 | 20 | ||
| 21 | static std::shared_ptr<Keyboard> keyboard; | 21 | struct InputSubsystem::Impl { |
| 22 | static std::shared_ptr<MotionEmu> motion_emu; | 22 | void Initialize() { |
| 23 | auto gcadapter = std::make_shared<GCAdapter::Adapter>(); | ||
| 24 | gcbuttons = std::make_shared<GCButtonFactory>(gcadapter); | ||
| 25 | Input::RegisterFactory<Input::ButtonDevice>("gcpad", gcbuttons); | ||
| 26 | gcanalog = std::make_shared<GCAnalogFactory>(gcadapter); | ||
| 27 | Input::RegisterFactory<Input::AnalogDevice>("gcpad", gcanalog); | ||
| 28 | |||
| 29 | keyboard = std::make_shared<Keyboard>(); | ||
| 30 | Input::RegisterFactory<Input::ButtonDevice>("keyboard", keyboard); | ||
| 31 | Input::RegisterFactory<Input::AnalogDevice>("analog_from_button", | ||
| 32 | std::make_shared<AnalogFromButton>()); | ||
| 33 | motion_emu = std::make_shared<MotionEmu>(); | ||
| 34 | Input::RegisterFactory<Input::MotionDevice>("motion_emu", motion_emu); | ||
| 35 | |||
| 23 | #ifdef HAVE_SDL2 | 36 | #ifdef HAVE_SDL2 |
| 24 | static std::unique_ptr<SDL::State> sdl; | 37 | sdl = SDL::Init(); |
| 25 | #endif | 38 | #endif |
| 26 | static std::unique_ptr<CemuhookUDP::State> udp; | ||
| 27 | static std::shared_ptr<GCButtonFactory> gcbuttons; | ||
| 28 | static std::shared_ptr<GCAnalogFactory> gcanalog; | ||
| 29 | |||
| 30 | void Init() { | ||
| 31 | auto gcadapter = std::make_shared<GCAdapter::Adapter>(); | ||
| 32 | gcbuttons = std::make_shared<GCButtonFactory>(gcadapter); | ||
| 33 | Input::RegisterFactory<Input::ButtonDevice>("gcpad", gcbuttons); | ||
| 34 | gcanalog = std::make_shared<GCAnalogFactory>(gcadapter); | ||
| 35 | Input::RegisterFactory<Input::AnalogDevice>("gcpad", gcanalog); | ||
| 36 | |||
| 37 | keyboard = std::make_shared<Keyboard>(); | ||
| 38 | Input::RegisterFactory<Input::ButtonDevice>("keyboard", keyboard); | ||
| 39 | Input::RegisterFactory<Input::AnalogDevice>("analog_from_button", | ||
| 40 | std::make_shared<AnalogFromButton>()); | ||
| 41 | motion_emu = std::make_shared<MotionEmu>(); | ||
| 42 | Input::RegisterFactory<Input::MotionDevice>("motion_emu", motion_emu); | ||
| 43 | 39 | ||
| 40 | udp = CemuhookUDP::Init(); | ||
| 41 | } | ||
| 42 | |||
| 43 | void Shutdown() { | ||
| 44 | Input::UnregisterFactory<Input::ButtonDevice>("keyboard"); | ||
| 45 | keyboard.reset(); | ||
| 46 | Input::UnregisterFactory<Input::AnalogDevice>("analog_from_button"); | ||
| 47 | Input::UnregisterFactory<Input::MotionDevice>("motion_emu"); | ||
| 48 | motion_emu.reset(); | ||
| 44 | #ifdef HAVE_SDL2 | 49 | #ifdef HAVE_SDL2 |
| 45 | sdl = SDL::Init(); | 50 | sdl.reset(); |
| 46 | #endif | 51 | #endif |
| 52 | udp.reset(); | ||
| 53 | Input::UnregisterFactory<Input::ButtonDevice>("gcpad"); | ||
| 54 | Input::UnregisterFactory<Input::AnalogDevice>("gcpad"); | ||
| 55 | |||
| 56 | gcbuttons.reset(); | ||
| 57 | gcanalog.reset(); | ||
| 58 | } | ||
| 59 | |||
| 60 | [[nodiscard]] std::vector<Common::ParamPackage> GetInputDevices() const { | ||
| 61 | std::vector<Common::ParamPackage> devices = { | ||
| 62 | Common::ParamPackage{{"display", "Any"}, {"class", "any"}}, | ||
| 63 | Common::ParamPackage{{"display", "Keyboard/Mouse"}, {"class", "key"}}, | ||
| 64 | }; | ||
| 65 | #ifdef HAVE_SDL2 | ||
| 66 | auto sdl_devices = sdl->GetInputDevices(); | ||
| 67 | devices.insert(devices.end(), sdl_devices.begin(), sdl_devices.end()); | ||
| 68 | #endif | ||
| 69 | auto udp_devices = udp->GetInputDevices(); | ||
| 70 | devices.insert(devices.end(), udp_devices.begin(), udp_devices.end()); | ||
| 71 | return devices; | ||
| 72 | } | ||
| 73 | |||
| 74 | [[nodiscard]] AnalogMapping GetAnalogMappingForDevice( | ||
| 75 | const Common::ParamPackage& params) const { | ||
| 76 | if (!params.Has("class") || params.Get("class", "") == "any") { | ||
| 77 | return {}; | ||
| 78 | } | ||
| 79 | if (params.Get("class", "") == "key") { | ||
| 80 | // TODO consider returning the SDL key codes for the default keybindings | ||
| 81 | return {}; | ||
| 82 | } | ||
| 83 | #ifdef HAVE_SDL2 | ||
| 84 | if (params.Get("class", "") == "sdl") { | ||
| 85 | return sdl->GetAnalogMappingForDevice(params); | ||
| 86 | } | ||
| 87 | #endif | ||
| 88 | return {}; | ||
| 89 | } | ||
| 90 | |||
| 91 | [[nodiscard]] ButtonMapping GetButtonMappingForDevice( | ||
| 92 | const Common::ParamPackage& params) const { | ||
| 93 | if (!params.Has("class") || params.Get("class", "") == "any") { | ||
| 94 | return {}; | ||
| 95 | } | ||
| 96 | if (params.Get("class", "") == "key") { | ||
| 97 | // TODO consider returning the SDL key codes for the default keybindings | ||
| 98 | return {}; | ||
| 99 | } | ||
| 100 | #ifdef HAVE_SDL2 | ||
| 101 | if (params.Get("class", "") == "sdl") { | ||
| 102 | return sdl->GetButtonMappingForDevice(params); | ||
| 103 | } | ||
| 104 | #endif | ||
| 105 | return {}; | ||
| 106 | } | ||
| 47 | 107 | ||
| 48 | udp = CemuhookUDP::Init(); | 108 | std::shared_ptr<Keyboard> keyboard; |
| 49 | } | 109 | std::shared_ptr<MotionEmu> motion_emu; |
| 50 | |||
| 51 | void Shutdown() { | ||
| 52 | Input::UnregisterFactory<Input::ButtonDevice>("keyboard"); | ||
| 53 | keyboard.reset(); | ||
| 54 | Input::UnregisterFactory<Input::AnalogDevice>("analog_from_button"); | ||
| 55 | Input::UnregisterFactory<Input::MotionDevice>("motion_emu"); | ||
| 56 | motion_emu.reset(); | ||
| 57 | #ifdef HAVE_SDL2 | 110 | #ifdef HAVE_SDL2 |
| 58 | sdl.reset(); | 111 | std::unique_ptr<SDL::State> sdl; |
| 59 | #endif | 112 | #endif |
| 60 | udp.reset(); | 113 | std::unique_ptr<CemuhookUDP::State> udp; |
| 61 | Input::UnregisterFactory<Input::ButtonDevice>("gcpad"); | 114 | std::shared_ptr<GCButtonFactory> gcbuttons; |
| 62 | Input::UnregisterFactory<Input::AnalogDevice>("gcpad"); | 115 | std::shared_ptr<GCAnalogFactory> gcanalog; |
| 116 | }; | ||
| 117 | |||
| 118 | InputSubsystem::InputSubsystem() : impl{std::make_unique<Impl>()} {} | ||
| 119 | |||
| 120 | InputSubsystem::~InputSubsystem() = default; | ||
| 121 | |||
| 122 | void InputSubsystem::Initialize() { | ||
| 123 | impl->Initialize(); | ||
| 124 | } | ||
| 125 | |||
| 126 | void InputSubsystem::Shutdown() { | ||
| 127 | impl->Shutdown(); | ||
| 128 | } | ||
| 129 | |||
| 130 | Keyboard* InputSubsystem::GetKeyboard() { | ||
| 131 | return impl->keyboard.get(); | ||
| 132 | } | ||
| 133 | |||
| 134 | const Keyboard* InputSubsystem::GetKeyboard() const { | ||
| 135 | return impl->keyboard.get(); | ||
| 136 | } | ||
| 63 | 137 | ||
| 64 | gcbuttons.reset(); | 138 | MotionEmu* InputSubsystem::GetMotionEmu() { |
| 65 | gcanalog.reset(); | 139 | return impl->motion_emu.get(); |
| 66 | } | 140 | } |
| 67 | 141 | ||
| 68 | Keyboard* GetKeyboard() { | 142 | const MotionEmu* InputSubsystem::GetMotionEmu() const { |
| 69 | return keyboard.get(); | 143 | return impl->motion_emu.get(); |
| 70 | } | 144 | } |
| 71 | 145 | ||
| 72 | MotionEmu* GetMotionEmu() { | 146 | std::vector<Common::ParamPackage> InputSubsystem::GetInputDevices() const { |
| 73 | return motion_emu.get(); | 147 | return impl->GetInputDevices(); |
| 74 | } | 148 | } |
| 75 | 149 | ||
| 76 | GCButtonFactory* GetGCButtons() { | 150 | AnalogMapping InputSubsystem::GetAnalogMappingForDevice(const Common::ParamPackage& device) const { |
| 77 | return gcbuttons.get(); | 151 | return impl->GetAnalogMappingForDevice(device); |
| 78 | } | 152 | } |
| 79 | 153 | ||
| 80 | GCAnalogFactory* GetGCAnalogs() { | 154 | ButtonMapping InputSubsystem::GetButtonMappingForDevice(const Common::ParamPackage& device) const { |
| 81 | return gcanalog.get(); | 155 | return impl->GetButtonMappingForDevice(device); |
| 156 | } | ||
| 157 | |||
| 158 | GCAnalogFactory* InputSubsystem::GetGCAnalogs() { | ||
| 159 | return impl->gcanalog.get(); | ||
| 160 | } | ||
| 161 | |||
| 162 | const GCAnalogFactory* InputSubsystem::GetGCAnalogs() const { | ||
| 163 | return impl->gcanalog.get(); | ||
| 164 | } | ||
| 165 | |||
| 166 | GCButtonFactory* InputSubsystem::GetGCButtons() { | ||
| 167 | return impl->gcbuttons.get(); | ||
| 168 | } | ||
| 169 | |||
| 170 | const GCButtonFactory* InputSubsystem::GetGCButtons() const { | ||
| 171 | return impl->gcbuttons.get(); | ||
| 172 | } | ||
| 173 | |||
| 174 | std::vector<std::unique_ptr<Polling::DevicePoller>> InputSubsystem::GetPollers( | ||
| 175 | Polling::DeviceType type) const { | ||
| 176 | #ifdef HAVE_SDL2 | ||
| 177 | return impl->sdl->GetPollers(type); | ||
| 178 | #else | ||
| 179 | return {}; | ||
| 180 | #endif | ||
| 82 | } | 181 | } |
| 83 | 182 | ||
| 84 | std::string GenerateKeyboardParam(int key_code) { | 183 | std::string GenerateKeyboardParam(int key_code) { |
| @@ -102,18 +201,4 @@ std::string GenerateAnalogParamFromKeys(int key_up, int key_down, int key_left, | |||
| 102 | }; | 201 | }; |
| 103 | return circle_pad_param.Serialize(); | 202 | return circle_pad_param.Serialize(); |
| 104 | } | 203 | } |
| 105 | |||
| 106 | namespace Polling { | ||
| 107 | |||
| 108 | std::vector<std::unique_ptr<DevicePoller>> GetPollers(DeviceType type) { | ||
| 109 | std::vector<std::unique_ptr<DevicePoller>> pollers; | ||
| 110 | |||
| 111 | #ifdef HAVE_SDL2 | ||
| 112 | pollers = sdl->GetPollers(type); | ||
| 113 | #endif | ||
| 114 | |||
| 115 | return pollers; | ||
| 116 | } | ||
| 117 | |||
| 118 | } // namespace Polling | ||
| 119 | } // namespace InputCommon | 204 | } // namespace InputCommon |
diff --git a/src/input_common/main.h b/src/input_common/main.h index 0e32856f6..58e5dc250 100644 --- a/src/input_common/main.h +++ b/src/input_common/main.h | |||
| @@ -6,45 +6,25 @@ | |||
| 6 | 6 | ||
| 7 | #include <memory> | 7 | #include <memory> |
| 8 | #include <string> | 8 | #include <string> |
| 9 | #include <unordered_map> | ||
| 9 | #include <vector> | 10 | #include <vector> |
| 10 | #include "input_common/gcadapter/gc_poller.h" | ||
| 11 | 11 | ||
| 12 | namespace Common { | 12 | namespace Common { |
| 13 | class ParamPackage; | 13 | class ParamPackage; |
| 14 | } | 14 | } |
| 15 | 15 | ||
| 16 | namespace InputCommon { | 16 | namespace Settings::NativeAnalog { |
| 17 | 17 | enum Values : int; | |
| 18 | /// Initializes and registers all built-in input device factories. | 18 | } |
| 19 | void Init(); | ||
| 20 | |||
| 21 | /// Deregisters all built-in input device factories and shuts them down. | ||
| 22 | void Shutdown(); | ||
| 23 | |||
| 24 | class Keyboard; | ||
| 25 | |||
| 26 | /// Gets the keyboard button device factory. | ||
| 27 | Keyboard* GetKeyboard(); | ||
| 28 | |||
| 29 | class MotionEmu; | ||
| 30 | |||
| 31 | /// Gets the motion emulation factory. | ||
| 32 | MotionEmu* GetMotionEmu(); | ||
| 33 | |||
| 34 | GCButtonFactory* GetGCButtons(); | ||
| 35 | |||
| 36 | GCAnalogFactory* GetGCAnalogs(); | ||
| 37 | |||
| 38 | /// Generates a serialized param package for creating a keyboard button device | ||
| 39 | std::string GenerateKeyboardParam(int key_code); | ||
| 40 | 19 | ||
| 41 | /// Generates a serialized param package for creating an analog device taking input from keyboard | 20 | namespace Settings::NativeButton { |
| 42 | std::string GenerateAnalogParamFromKeys(int key_up, int key_down, int key_left, int key_right, | 21 | enum Values : int; |
| 43 | int key_modifier, float modifier_scale); | 22 | } |
| 44 | 23 | ||
| 24 | namespace InputCommon { | ||
| 45 | namespace Polling { | 25 | namespace Polling { |
| 46 | 26 | ||
| 47 | enum class DeviceType { Button, Analog }; | 27 | enum class DeviceType { Button, AnalogPreferred }; |
| 48 | 28 | ||
| 49 | /** | 29 | /** |
| 50 | * A class that can be used to get inputs from an input device like controllers without having to | 30 | * A class that can be used to get inputs from an input device like controllers without having to |
| @@ -54,7 +34,9 @@ class DevicePoller { | |||
| 54 | public: | 34 | public: |
| 55 | virtual ~DevicePoller() = default; | 35 | virtual ~DevicePoller() = default; |
| 56 | /// Setup and start polling for inputs, should be called before GetNextInput | 36 | /// Setup and start polling for inputs, should be called before GetNextInput |
| 57 | virtual void Start() = 0; | 37 | /// If a device_id is provided, events should be filtered to only include events from this |
| 38 | /// device id | ||
| 39 | virtual void Start(const std::string& device_id = "") = 0; | ||
| 58 | /// Stop polling | 40 | /// Stop polling |
| 59 | virtual void Stop() = 0; | 41 | virtual void Stop() = 0; |
| 60 | /** | 42 | /** |
| @@ -64,8 +46,89 @@ public: | |||
| 64 | */ | 46 | */ |
| 65 | virtual Common::ParamPackage GetNextInput() = 0; | 47 | virtual Common::ParamPackage GetNextInput() = 0; |
| 66 | }; | 48 | }; |
| 67 | |||
| 68 | // Get all DevicePoller from all backends for a specific device type | ||
| 69 | std::vector<std::unique_ptr<DevicePoller>> GetPollers(DeviceType type); | ||
| 70 | } // namespace Polling | 49 | } // namespace Polling |
| 50 | |||
| 51 | class GCAnalogFactory; | ||
| 52 | class GCButtonFactory; | ||
| 53 | class Keyboard; | ||
| 54 | class MotionEmu; | ||
| 55 | |||
| 56 | /** | ||
| 57 | * Given a ParamPackage for a Device returned from `GetInputDevices`, attempt to get the default | ||
| 58 | * mapping for the device. This is currently only implemented for the SDL backend devices. | ||
| 59 | */ | ||
| 60 | using AnalogMapping = std::unordered_map<Settings::NativeAnalog::Values, Common::ParamPackage>; | ||
| 61 | using ButtonMapping = std::unordered_map<Settings::NativeButton::Values, Common::ParamPackage>; | ||
| 62 | |||
| 63 | class InputSubsystem { | ||
| 64 | public: | ||
| 65 | explicit InputSubsystem(); | ||
| 66 | ~InputSubsystem(); | ||
| 67 | |||
| 68 | InputSubsystem(const InputSubsystem&) = delete; | ||
| 69 | InputSubsystem& operator=(const InputSubsystem&) = delete; | ||
| 70 | |||
| 71 | InputSubsystem(InputSubsystem&&) = delete; | ||
| 72 | InputSubsystem& operator=(InputSubsystem&&) = delete; | ||
| 73 | |||
| 74 | /// Initializes and registers all built-in input device factories. | ||
| 75 | void Initialize(); | ||
| 76 | |||
| 77 | /// Unregisters all built-in input device factories and shuts them down. | ||
| 78 | void Shutdown(); | ||
| 79 | |||
| 80 | /// Retrieves the underlying keyboard device. | ||
| 81 | [[nodiscard]] Keyboard* GetKeyboard(); | ||
| 82 | |||
| 83 | /// Retrieves the underlying keyboard device. | ||
| 84 | [[nodiscard]] const Keyboard* GetKeyboard() const; | ||
| 85 | |||
| 86 | /// Retrieves the underlying motion emulation factory. | ||
| 87 | [[nodiscard]] MotionEmu* GetMotionEmu(); | ||
| 88 | |||
| 89 | /// Retrieves the underlying motion emulation factory. | ||
| 90 | [[nodiscard]] const MotionEmu* GetMotionEmu() const; | ||
| 91 | |||
| 92 | /** | ||
| 93 | * Returns all available input devices that this Factory can create a new device with. | ||
| 94 | * Each returned ParamPackage should have a `display` field used for display, a class field for | ||
| 95 | * backends to determine if this backend is meant to service the request and any other | ||
| 96 | * information needed to identify this in the backend later. | ||
| 97 | */ | ||
| 98 | [[nodiscard]] std::vector<Common::ParamPackage> GetInputDevices() const; | ||
| 99 | |||
| 100 | /// Retrieves the analog mappings for the given device. | ||
| 101 | [[nodiscard]] AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage& device) const; | ||
| 102 | |||
| 103 | /// Retrieves the button mappings for the given device. | ||
| 104 | [[nodiscard]] ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage& device) const; | ||
| 105 | |||
| 106 | /// Retrieves the underlying GameCube analog handler. | ||
| 107 | [[nodiscard]] GCAnalogFactory* GetGCAnalogs(); | ||
| 108 | |||
| 109 | /// Retrieves the underlying GameCube analog handler. | ||
| 110 | [[nodiscard]] const GCAnalogFactory* GetGCAnalogs() const; | ||
| 111 | |||
| 112 | /// Retrieves the underlying GameCube button handler. | ||
| 113 | [[nodiscard]] GCButtonFactory* GetGCButtons(); | ||
| 114 | |||
| 115 | /// Retrieves the underlying GameCube button handler. | ||
| 116 | [[nodiscard]] const GCButtonFactory* GetGCButtons() const; | ||
| 117 | |||
| 118 | /// Get all DevicePoller from all backends for a specific device type | ||
| 119 | [[nodiscard]] std::vector<std::unique_ptr<Polling::DevicePoller>> GetPollers( | ||
| 120 | Polling::DeviceType type) const; | ||
| 121 | |||
| 122 | private: | ||
| 123 | struct Impl; | ||
| 124 | std::unique_ptr<Impl> impl; | ||
| 125 | }; | ||
| 126 | |||
| 127 | /// Generates a serialized param package for creating a keyboard button device | ||
| 128 | std::string GenerateKeyboardParam(int key_code); | ||
| 129 | |||
| 130 | /// Generates a serialized param package for creating an analog device taking input from keyboard | ||
| 131 | std::string GenerateAnalogParamFromKeys(int key_up, int key_down, int key_left, int key_right, | ||
| 132 | int key_modifier, float modifier_scale); | ||
| 133 | |||
| 71 | } // namespace InputCommon | 134 | } // namespace InputCommon |
diff --git a/src/input_common/sdl/sdl.h b/src/input_common/sdl/sdl.h index 5306daa70..f3554be9a 100644 --- a/src/input_common/sdl/sdl.h +++ b/src/input_common/sdl/sdl.h | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | #include <memory> | 7 | #include <memory> |
| 8 | #include <vector> | 8 | #include <vector> |
| 9 | #include "common/param_package.h" | ||
| 9 | #include "input_common/main.h" | 10 | #include "input_common/main.h" |
| 10 | 11 | ||
| 11 | namespace InputCommon::Polling { | 12 | namespace InputCommon::Polling { |
| @@ -22,14 +23,24 @@ public: | |||
| 22 | /// Unregisters SDL device factories and shut them down. | 23 | /// Unregisters SDL device factories and shut them down. |
| 23 | virtual ~State() = default; | 24 | virtual ~State() = default; |
| 24 | 25 | ||
| 25 | virtual Pollers GetPollers(Polling::DeviceType type) = 0; | 26 | virtual Pollers GetPollers(Polling::DeviceType type) { |
| 27 | return {}; | ||
| 28 | } | ||
| 29 | |||
| 30 | virtual std::vector<Common::ParamPackage> GetInputDevices() { | ||
| 31 | return {}; | ||
| 32 | } | ||
| 33 | |||
| 34 | virtual ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage&) { | ||
| 35 | return {}; | ||
| 36 | } | ||
| 37 | virtual AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage&) { | ||
| 38 | return {}; | ||
| 39 | } | ||
| 26 | }; | 40 | }; |
| 27 | 41 | ||
| 28 | class NullState : public State { | 42 | class NullState : public State { |
| 29 | public: | 43 | public: |
| 30 | Pollers GetPollers(Polling::DeviceType type) override { | ||
| 31 | return {}; | ||
| 32 | } | ||
| 33 | }; | 44 | }; |
| 34 | 45 | ||
| 35 | std::unique_ptr<State> Init(); | 46 | std::unique_ptr<State> Init(); |
diff --git a/src/input_common/sdl/sdl_impl.cpp b/src/input_common/sdl/sdl_impl.cpp index 675b477fa..a9e676f4b 100644 --- a/src/input_common/sdl/sdl_impl.cpp +++ b/src/input_common/sdl/sdl_impl.cpp | |||
| @@ -3,10 +3,13 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <algorithm> | 5 | #include <algorithm> |
| 6 | #include <array> | ||
| 6 | #include <atomic> | 7 | #include <atomic> |
| 7 | #include <cmath> | 8 | #include <cmath> |
| 8 | #include <functional> | 9 | #include <functional> |
| 9 | #include <mutex> | 10 | #include <mutex> |
| 11 | #include <optional> | ||
| 12 | #include <sstream> | ||
| 10 | #include <string> | 13 | #include <string> |
| 11 | #include <thread> | 14 | #include <thread> |
| 12 | #include <tuple> | 15 | #include <tuple> |
| @@ -15,15 +18,16 @@ | |||
| 15 | #include <vector> | 18 | #include <vector> |
| 16 | #include <SDL.h> | 19 | #include <SDL.h> |
| 17 | #include "common/logging/log.h" | 20 | #include "common/logging/log.h" |
| 18 | #include "common/math_util.h" | ||
| 19 | #include "common/param_package.h" | 21 | #include "common/param_package.h" |
| 20 | #include "common/threadsafe_queue.h" | 22 | #include "common/threadsafe_queue.h" |
| 21 | #include "core/frontend/input.h" | 23 | #include "core/frontend/input.h" |
| 22 | #include "input_common/sdl/sdl_impl.h" | 24 | #include "input_common/sdl/sdl_impl.h" |
| 25 | #include "input_common/settings.h" | ||
| 23 | 26 | ||
| 24 | namespace InputCommon::SDL { | 27 | namespace InputCommon::SDL { |
| 25 | 28 | ||
| 26 | static std::string GetGUID(SDL_Joystick* joystick) { | 29 | namespace { |
| 30 | std::string GetGUID(SDL_Joystick* joystick) { | ||
| 27 | const SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick); | 31 | const SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick); |
| 28 | char guid_str[33]; | 32 | char guid_str[33]; |
| 29 | SDL_JoystickGetGUIDString(guid, guid_str, sizeof(guid_str)); | 33 | SDL_JoystickGetGUIDString(guid, guid_str, sizeof(guid_str)); |
| @@ -31,7 +35,8 @@ static std::string GetGUID(SDL_Joystick* joystick) { | |||
| 31 | } | 35 | } |
| 32 | 36 | ||
| 33 | /// Creates a ParamPackage from an SDL_Event that can directly be used to create a ButtonDevice | 37 | /// Creates a ParamPackage from an SDL_Event that can directly be used to create a ButtonDevice |
| 34 | static Common::ParamPackage SDLEventToButtonParamPackage(SDLState& state, const SDL_Event& event); | 38 | Common::ParamPackage SDLEventToButtonParamPackage(SDLState& state, const SDL_Event& event); |
| 39 | } // Anonymous namespace | ||
| 35 | 40 | ||
| 36 | static int SDLEventWatcher(void* user_data, SDL_Event* event) { | 41 | static int SDLEventWatcher(void* user_data, SDL_Event* event) { |
| 37 | auto* const sdl_state = static_cast<SDLState*>(user_data); | 42 | auto* const sdl_state = static_cast<SDLState*>(user_data); |
| @@ -48,8 +53,10 @@ static int SDLEventWatcher(void* user_data, SDL_Event* event) { | |||
| 48 | 53 | ||
| 49 | class SDLJoystick { | 54 | class SDLJoystick { |
| 50 | public: | 55 | public: |
| 51 | SDLJoystick(std::string guid_, int port_, SDL_Joystick* joystick) | 56 | SDLJoystick(std::string guid_, int port_, SDL_Joystick* joystick, |
| 52 | : guid{std::move(guid_)}, port{port_}, sdl_joystick{joystick, &SDL_JoystickClose} {} | 57 | SDL_GameController* gamecontroller) |
| 58 | : guid{std::move(guid_)}, port{port_}, sdl_joystick{joystick, &SDL_JoystickClose}, | ||
| 59 | sdl_controller{gamecontroller, &SDL_GameControllerClose} {} | ||
| 53 | 60 | ||
| 54 | void SetButton(int button, bool value) { | 61 | void SetButton(int button, bool value) { |
| 55 | std::lock_guard lock{mutex}; | 62 | std::lock_guard lock{mutex}; |
| @@ -66,14 +73,14 @@ public: | |||
| 66 | state.axes.insert_or_assign(axis, value); | 73 | state.axes.insert_or_assign(axis, value); |
| 67 | } | 74 | } |
| 68 | 75 | ||
| 69 | float GetAxis(int axis) const { | 76 | float GetAxis(int axis, float range) const { |
| 70 | std::lock_guard lock{mutex}; | 77 | std::lock_guard lock{mutex}; |
| 71 | return state.axes.at(axis) / 32767.0f; | 78 | return state.axes.at(axis) / (32767.0f * range); |
| 72 | } | 79 | } |
| 73 | 80 | ||
| 74 | std::tuple<float, float> GetAnalog(int axis_x, int axis_y) const { | 81 | std::tuple<float, float> GetAnalog(int axis_x, int axis_y, float range) const { |
| 75 | float x = GetAxis(axis_x); | 82 | float x = GetAxis(axis_x, range); |
| 76 | float y = GetAxis(axis_y); | 83 | float y = GetAxis(axis_y, range); |
| 77 | y = -y; // 3DS uses an y-axis inverse from SDL | 84 | y = -y; // 3DS uses an y-axis inverse from SDL |
| 78 | 85 | ||
| 79 | // Make sure the coordinates are in the unit circle, | 86 | // Make sure the coordinates are in the unit circle, |
| @@ -115,10 +122,15 @@ public: | |||
| 115 | return sdl_joystick.get(); | 122 | return sdl_joystick.get(); |
| 116 | } | 123 | } |
| 117 | 124 | ||
| 118 | void SetSDLJoystick(SDL_Joystick* joystick) { | 125 | void SetSDLJoystick(SDL_Joystick* joystick, SDL_GameController* controller) { |
| 126 | sdl_controller.reset(controller); | ||
| 119 | sdl_joystick.reset(joystick); | 127 | sdl_joystick.reset(joystick); |
| 120 | } | 128 | } |
| 121 | 129 | ||
| 130 | SDL_GameController* GetSDLGameController() const { | ||
| 131 | return sdl_controller.get(); | ||
| 132 | } | ||
| 133 | |||
| 122 | private: | 134 | private: |
| 123 | struct State { | 135 | struct State { |
| 124 | std::unordered_map<int, bool> buttons; | 136 | std::unordered_map<int, bool> buttons; |
| @@ -128,6 +140,7 @@ private: | |||
| 128 | std::string guid; | 140 | std::string guid; |
| 129 | int port; | 141 | int port; |
| 130 | std::unique_ptr<SDL_Joystick, decltype(&SDL_JoystickClose)> sdl_joystick; | 142 | std::unique_ptr<SDL_Joystick, decltype(&SDL_JoystickClose)> sdl_joystick; |
| 143 | std::unique_ptr<SDL_GameController, decltype(&SDL_GameControllerClose)> sdl_controller; | ||
| 131 | mutable std::mutex mutex; | 144 | mutable std::mutex mutex; |
| 132 | }; | 145 | }; |
| 133 | 146 | ||
| @@ -136,18 +149,19 @@ std::shared_ptr<SDLJoystick> SDLState::GetSDLJoystickByGUID(const std::string& g | |||
| 136 | const auto it = joystick_map.find(guid); | 149 | const auto it = joystick_map.find(guid); |
| 137 | if (it != joystick_map.end()) { | 150 | if (it != joystick_map.end()) { |
| 138 | while (it->second.size() <= static_cast<std::size_t>(port)) { | 151 | while (it->second.size() <= static_cast<std::size_t>(port)) { |
| 139 | auto joystick = | 152 | auto joystick = std::make_shared<SDLJoystick>(guid, static_cast<int>(it->second.size()), |
| 140 | std::make_shared<SDLJoystick>(guid, static_cast<int>(it->second.size()), nullptr); | 153 | nullptr, nullptr); |
| 141 | it->second.emplace_back(std::move(joystick)); | 154 | it->second.emplace_back(std::move(joystick)); |
| 142 | } | 155 | } |
| 143 | return it->second[port]; | 156 | return it->second[port]; |
| 144 | } | 157 | } |
| 145 | auto joystick = std::make_shared<SDLJoystick>(guid, 0, nullptr); | 158 | auto joystick = std::make_shared<SDLJoystick>(guid, 0, nullptr, nullptr); |
| 146 | return joystick_map[guid].emplace_back(std::move(joystick)); | 159 | return joystick_map[guid].emplace_back(std::move(joystick)); |
| 147 | } | 160 | } |
| 148 | 161 | ||
| 149 | std::shared_ptr<SDLJoystick> SDLState::GetSDLJoystickBySDLID(SDL_JoystickID sdl_id) { | 162 | std::shared_ptr<SDLJoystick> SDLState::GetSDLJoystickBySDLID(SDL_JoystickID sdl_id) { |
| 150 | auto sdl_joystick = SDL_JoystickFromInstanceID(sdl_id); | 163 | auto sdl_joystick = SDL_JoystickFromInstanceID(sdl_id); |
| 164 | auto sdl_controller = SDL_GameControllerFromInstanceID(sdl_id); | ||
| 151 | const std::string guid = GetGUID(sdl_joystick); | 165 | const std::string guid = GetGUID(sdl_joystick); |
| 152 | 166 | ||
| 153 | std::lock_guard lock{joystick_map_mutex}; | 167 | std::lock_guard lock{joystick_map_mutex}; |
| @@ -171,23 +185,27 @@ std::shared_ptr<SDLJoystick> SDLState::GetSDLJoystickBySDLID(SDL_JoystickID sdl_ | |||
| 171 | }); | 185 | }); |
| 172 | if (nullptr_it != map_it->second.end()) { | 186 | if (nullptr_it != map_it->second.end()) { |
| 173 | // ... and map it | 187 | // ... and map it |
| 174 | (*nullptr_it)->SetSDLJoystick(sdl_joystick); | 188 | (*nullptr_it)->SetSDLJoystick(sdl_joystick, sdl_controller); |
| 175 | return *nullptr_it; | 189 | return *nullptr_it; |
| 176 | } | 190 | } |
| 177 | 191 | ||
| 178 | // There is no SDLJoystick without a mapped SDL_Joystick | 192 | // There is no SDLJoystick without a mapped SDL_Joystick |
| 179 | // Create a new SDLJoystick | 193 | // Create a new SDLJoystick |
| 180 | const int port = static_cast<int>(map_it->second.size()); | 194 | const int port = static_cast<int>(map_it->second.size()); |
| 181 | auto joystick = std::make_shared<SDLJoystick>(guid, port, sdl_joystick); | 195 | auto joystick = std::make_shared<SDLJoystick>(guid, port, sdl_joystick, sdl_controller); |
| 182 | return map_it->second.emplace_back(std::move(joystick)); | 196 | return map_it->second.emplace_back(std::move(joystick)); |
| 183 | } | 197 | } |
| 184 | 198 | ||
| 185 | auto joystick = std::make_shared<SDLJoystick>(guid, 0, sdl_joystick); | 199 | auto joystick = std::make_shared<SDLJoystick>(guid, 0, sdl_joystick, sdl_controller); |
| 186 | return joystick_map[guid].emplace_back(std::move(joystick)); | 200 | return joystick_map[guid].emplace_back(std::move(joystick)); |
| 187 | } | 201 | } |
| 188 | 202 | ||
| 189 | void SDLState::InitJoystick(int joystick_index) { | 203 | void SDLState::InitJoystick(int joystick_index) { |
| 190 | SDL_Joystick* sdl_joystick = SDL_JoystickOpen(joystick_index); | 204 | SDL_Joystick* sdl_joystick = SDL_JoystickOpen(joystick_index); |
| 205 | SDL_GameController* sdl_gamecontroller = nullptr; | ||
| 206 | if (SDL_IsGameController(joystick_index)) { | ||
| 207 | sdl_gamecontroller = SDL_GameControllerOpen(joystick_index); | ||
| 208 | } | ||
| 191 | if (!sdl_joystick) { | 209 | if (!sdl_joystick) { |
| 192 | LOG_ERROR(Input, "failed to open joystick {}", joystick_index); | 210 | LOG_ERROR(Input, "failed to open joystick {}", joystick_index); |
| 193 | return; | 211 | return; |
| @@ -196,7 +214,7 @@ void SDLState::InitJoystick(int joystick_index) { | |||
| 196 | 214 | ||
| 197 | std::lock_guard lock{joystick_map_mutex}; | 215 | std::lock_guard lock{joystick_map_mutex}; |
| 198 | if (joystick_map.find(guid) == joystick_map.end()) { | 216 | if (joystick_map.find(guid) == joystick_map.end()) { |
| 199 | auto joystick = std::make_shared<SDLJoystick>(guid, 0, sdl_joystick); | 217 | auto joystick = std::make_shared<SDLJoystick>(guid, 0, sdl_joystick, sdl_gamecontroller); |
| 200 | joystick_map[guid].emplace_back(std::move(joystick)); | 218 | joystick_map[guid].emplace_back(std::move(joystick)); |
| 201 | return; | 219 | return; |
| 202 | } | 220 | } |
| @@ -205,11 +223,11 @@ void SDLState::InitJoystick(int joystick_index) { | |||
| 205 | joystick_guid_list.begin(), joystick_guid_list.end(), | 223 | joystick_guid_list.begin(), joystick_guid_list.end(), |
| 206 | [](const std::shared_ptr<SDLJoystick>& joystick) { return !joystick->GetSDLJoystick(); }); | 224 | [](const std::shared_ptr<SDLJoystick>& joystick) { return !joystick->GetSDLJoystick(); }); |
| 207 | if (it != joystick_guid_list.end()) { | 225 | if (it != joystick_guid_list.end()) { |
| 208 | (*it)->SetSDLJoystick(sdl_joystick); | 226 | (*it)->SetSDLJoystick(sdl_joystick, sdl_gamecontroller); |
| 209 | return; | 227 | return; |
| 210 | } | 228 | } |
| 211 | const int port = static_cast<int>(joystick_guid_list.size()); | 229 | const int port = static_cast<int>(joystick_guid_list.size()); |
| 212 | auto joystick = std::make_shared<SDLJoystick>(guid, port, sdl_joystick); | 230 | auto joystick = std::make_shared<SDLJoystick>(guid, port, sdl_joystick, sdl_gamecontroller); |
| 213 | joystick_guid_list.emplace_back(std::move(joystick)); | 231 | joystick_guid_list.emplace_back(std::move(joystick)); |
| 214 | } | 232 | } |
| 215 | 233 | ||
| @@ -231,7 +249,7 @@ void SDLState::CloseJoystick(SDL_Joystick* sdl_joystick) { | |||
| 231 | 249 | ||
| 232 | // Destruct SDL_Joystick outside the lock guard because SDL can internally call the | 250 | // Destruct SDL_Joystick outside the lock guard because SDL can internally call the |
| 233 | // event callback which locks the mutex again. | 251 | // event callback which locks the mutex again. |
| 234 | joystick->SetSDLJoystick(nullptr); | 252 | joystick->SetSDLJoystick(nullptr, nullptr); |
| 235 | } | 253 | } |
| 236 | 254 | ||
| 237 | void SDLState::HandleGameControllerEvent(const SDL_Event& event) { | 255 | void SDLState::HandleGameControllerEvent(const SDL_Event& event) { |
| @@ -313,7 +331,7 @@ public: | |||
| 313 | trigger_if_greater(trigger_if_greater_) {} | 331 | trigger_if_greater(trigger_if_greater_) {} |
| 314 | 332 | ||
| 315 | bool GetStatus() const override { | 333 | bool GetStatus() const override { |
| 316 | const float axis_value = joystick->GetAxis(axis); | 334 | const float axis_value = joystick->GetAxis(axis, 1.0f); |
| 317 | if (trigger_if_greater) { | 335 | if (trigger_if_greater) { |
| 318 | return axis_value > threshold; | 336 | return axis_value > threshold; |
| 319 | } | 337 | } |
| @@ -329,22 +347,24 @@ private: | |||
| 329 | 347 | ||
| 330 | class SDLAnalog final : public Input::AnalogDevice { | 348 | class SDLAnalog final : public Input::AnalogDevice { |
| 331 | public: | 349 | public: |
| 332 | SDLAnalog(std::shared_ptr<SDLJoystick> joystick_, int axis_x_, int axis_y_, float deadzone_) | 350 | SDLAnalog(std::shared_ptr<SDLJoystick> joystick_, int axis_x_, int axis_y_, float deadzone_, |
| 333 | : joystick(std::move(joystick_)), axis_x(axis_x_), axis_y(axis_y_), deadzone(deadzone_) {} | 351 | float range_) |
| 352 | : joystick(std::move(joystick_)), axis_x(axis_x_), axis_y(axis_y_), deadzone(deadzone_), | ||
| 353 | range(range_) {} | ||
| 334 | 354 | ||
| 335 | std::tuple<float, float> GetStatus() const override { | 355 | std::tuple<float, float> GetStatus() const override { |
| 336 | const auto [x, y] = joystick->GetAnalog(axis_x, axis_y); | 356 | const auto [x, y] = joystick->GetAnalog(axis_x, axis_y, range); |
| 337 | const float r = std::sqrt((x * x) + (y * y)); | 357 | const float r = std::sqrt((x * x) + (y * y)); |
| 338 | if (r > deadzone) { | 358 | if (r > deadzone) { |
| 339 | return std::make_tuple(x / r * (r - deadzone) / (1 - deadzone), | 359 | return std::make_tuple(x / r * (r - deadzone) / (1 - deadzone), |
| 340 | y / r * (r - deadzone) / (1 - deadzone)); | 360 | y / r * (r - deadzone) / (1 - deadzone)); |
| 341 | } | 361 | } |
| 342 | return std::make_tuple<float, float>(0.0f, 0.0f); | 362 | return {}; |
| 343 | } | 363 | } |
| 344 | 364 | ||
| 345 | bool GetAnalogDirectionStatus(Input::AnalogDirection direction) const override { | 365 | bool GetAnalogDirectionStatus(Input::AnalogDirection direction) const override { |
| 346 | const auto [x, y] = GetStatus(); | 366 | const auto [x, y] = GetStatus(); |
| 347 | const float directional_deadzone = 0.4f; | 367 | const float directional_deadzone = 0.5f; |
| 348 | switch (direction) { | 368 | switch (direction) { |
| 349 | case Input::AnalogDirection::RIGHT: | 369 | case Input::AnalogDirection::RIGHT: |
| 350 | return x > directional_deadzone; | 370 | return x > directional_deadzone; |
| @@ -363,6 +383,7 @@ private: | |||
| 363 | const int axis_x; | 383 | const int axis_x; |
| 364 | const int axis_y; | 384 | const int axis_y; |
| 365 | const float deadzone; | 385 | const float deadzone; |
| 386 | const float range; | ||
| 366 | }; | 387 | }; |
| 367 | 388 | ||
| 368 | /// A button device factory that creates button devices from SDL joystick | 389 | /// A button device factory that creates button devices from SDL joystick |
| @@ -457,14 +478,14 @@ public: | |||
| 457 | const int port = params.Get("port", 0); | 478 | const int port = params.Get("port", 0); |
| 458 | const int axis_x = params.Get("axis_x", 0); | 479 | const int axis_x = params.Get("axis_x", 0); |
| 459 | const int axis_y = params.Get("axis_y", 1); | 480 | const int axis_y = params.Get("axis_y", 1); |
| 460 | const float deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, .99f); | 481 | const float deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, 1.0f); |
| 461 | 482 | const float range = std::clamp(params.Get("range", 1.0f), 0.50f, 1.50f); | |
| 462 | auto joystick = state.GetSDLJoystickByGUID(guid, port); | 483 | auto joystick = state.GetSDLJoystickByGUID(guid, port); |
| 463 | 484 | ||
| 464 | // This is necessary so accessing GetAxis with axis_x and axis_y won't crash | 485 | // This is necessary so accessing GetAxis with axis_x and axis_y won't crash |
| 465 | joystick->SetAxis(axis_x, 0); | 486 | joystick->SetAxis(axis_x, 0); |
| 466 | joystick->SetAxis(axis_y, 0); | 487 | joystick->SetAxis(axis_y, 0); |
| 467 | return std::make_unique<SDLAnalog>(joystick, axis_x, axis_y, deadzone); | 488 | return std::make_unique<SDLAnalog>(joystick, axis_x, axis_y, deadzone, range); |
| 468 | } | 489 | } |
| 469 | 490 | ||
| 470 | private: | 491 | private: |
| @@ -473,8 +494,10 @@ private: | |||
| 473 | 494 | ||
| 474 | SDLState::SDLState() { | 495 | SDLState::SDLState() { |
| 475 | using namespace Input; | 496 | using namespace Input; |
| 476 | RegisterFactory<ButtonDevice>("sdl", std::make_shared<SDLButtonFactory>(*this)); | 497 | analog_factory = std::make_shared<SDLAnalogFactory>(*this); |
| 477 | RegisterFactory<AnalogDevice>("sdl", std::make_shared<SDLAnalogFactory>(*this)); | 498 | button_factory = std::make_shared<SDLButtonFactory>(*this); |
| 499 | RegisterFactory<AnalogDevice>("sdl", analog_factory); | ||
| 500 | RegisterFactory<ButtonDevice>("sdl", button_factory); | ||
| 478 | 501 | ||
| 479 | // If the frontend is going to manage the event loop, then we dont start one here | 502 | // If the frontend is going to manage the event loop, then we dont start one here |
| 480 | start_thread = !SDL_WasInit(SDL_INIT_JOYSTICK); | 503 | start_thread = !SDL_WasInit(SDL_INIT_JOYSTICK); |
| @@ -482,6 +505,7 @@ SDLState::SDLState() { | |||
| 482 | LOG_CRITICAL(Input, "SDL_Init(SDL_INIT_JOYSTICK) failed with: {}", SDL_GetError()); | 505 | LOG_CRITICAL(Input, "SDL_Init(SDL_INIT_JOYSTICK) failed with: {}", SDL_GetError()); |
| 483 | return; | 506 | return; |
| 484 | } | 507 | } |
| 508 | has_gamecontroller = SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER); | ||
| 485 | if (SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1") == SDL_FALSE) { | 509 | if (SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1") == SDL_FALSE) { |
| 486 | LOG_ERROR(Input, "Failed to set hint for background events with: {}", SDL_GetError()); | 510 | LOG_ERROR(Input, "Failed to set hint for background events with: {}", SDL_GetError()); |
| 487 | } | 511 | } |
| @@ -494,7 +518,7 @@ SDLState::SDLState() { | |||
| 494 | using namespace std::chrono_literals; | 518 | using namespace std::chrono_literals; |
| 495 | while (initialized) { | 519 | while (initialized) { |
| 496 | SDL_PumpEvents(); | 520 | SDL_PumpEvents(); |
| 497 | std::this_thread::sleep_for(10ms); | 521 | std::this_thread::sleep_for(5ms); |
| 498 | } | 522 | } |
| 499 | }); | 523 | }); |
| 500 | } | 524 | } |
| @@ -520,65 +544,230 @@ SDLState::~SDLState() { | |||
| 520 | } | 544 | } |
| 521 | } | 545 | } |
| 522 | 546 | ||
| 523 | static Common::ParamPackage SDLEventToButtonParamPackage(SDLState& state, const SDL_Event& event) { | 547 | std::vector<Common::ParamPackage> SDLState::GetInputDevices() { |
| 548 | std::scoped_lock lock(joystick_map_mutex); | ||
| 549 | std::vector<Common::ParamPackage> devices; | ||
| 550 | for (const auto& [key, value] : joystick_map) { | ||
| 551 | for (const auto& joystick : value) { | ||
| 552 | auto joy = joystick->GetSDLJoystick(); | ||
| 553 | if (auto controller = joystick->GetSDLGameController()) { | ||
| 554 | std::string name = | ||
| 555 | fmt::format("{} {}", SDL_GameControllerName(controller), joystick->GetPort()); | ||
| 556 | devices.emplace_back(Common::ParamPackage{ | ||
| 557 | {"class", "sdl"}, | ||
| 558 | {"display", std::move(name)}, | ||
| 559 | {"guid", joystick->GetGUID()}, | ||
| 560 | {"port", std::to_string(joystick->GetPort())}, | ||
| 561 | }); | ||
| 562 | } else if (joy) { | ||
| 563 | std::string name = fmt::format("{} {}", SDL_JoystickName(joy), joystick->GetPort()); | ||
| 564 | devices.emplace_back(Common::ParamPackage{ | ||
| 565 | {"class", "sdl"}, | ||
| 566 | {"display", std::move(name)}, | ||
| 567 | {"guid", joystick->GetGUID()}, | ||
| 568 | {"port", std::to_string(joystick->GetPort())}, | ||
| 569 | }); | ||
| 570 | } | ||
| 571 | } | ||
| 572 | } | ||
| 573 | return devices; | ||
| 574 | } | ||
| 575 | |||
| 576 | namespace { | ||
| 577 | Common::ParamPackage BuildAnalogParamPackageForButton(int port, std::string guid, u8 axis, | ||
| 578 | float value = 0.1f) { | ||
| 579 | Common::ParamPackage params({{"engine", "sdl"}}); | ||
| 580 | params.Set("port", port); | ||
| 581 | params.Set("guid", std::move(guid)); | ||
| 582 | params.Set("axis", axis); | ||
| 583 | if (value > 0) { | ||
| 584 | params.Set("direction", "+"); | ||
| 585 | params.Set("threshold", "0.5"); | ||
| 586 | } else { | ||
| 587 | params.Set("direction", "-"); | ||
| 588 | params.Set("threshold", "-0.5"); | ||
| 589 | } | ||
| 590 | return params; | ||
| 591 | } | ||
| 592 | |||
| 593 | Common::ParamPackage BuildButtonParamPackageForButton(int port, std::string guid, u8 button) { | ||
| 524 | Common::ParamPackage params({{"engine", "sdl"}}); | 594 | Common::ParamPackage params({{"engine", "sdl"}}); |
| 595 | params.Set("port", port); | ||
| 596 | params.Set("guid", std::move(guid)); | ||
| 597 | params.Set("button", button); | ||
| 598 | return params; | ||
| 599 | } | ||
| 600 | |||
| 601 | Common::ParamPackage BuildHatParamPackageForButton(int port, std::string guid, u8 hat, u8 value) { | ||
| 602 | Common::ParamPackage params({{"engine", "sdl"}}); | ||
| 603 | |||
| 604 | params.Set("port", port); | ||
| 605 | params.Set("guid", std::move(guid)); | ||
| 606 | params.Set("hat", hat); | ||
| 607 | switch (value) { | ||
| 608 | case SDL_HAT_UP: | ||
| 609 | params.Set("direction", "up"); | ||
| 610 | break; | ||
| 611 | case SDL_HAT_DOWN: | ||
| 612 | params.Set("direction", "down"); | ||
| 613 | break; | ||
| 614 | case SDL_HAT_LEFT: | ||
| 615 | params.Set("direction", "left"); | ||
| 616 | break; | ||
| 617 | case SDL_HAT_RIGHT: | ||
| 618 | params.Set("direction", "right"); | ||
| 619 | break; | ||
| 620 | default: | ||
| 621 | return {}; | ||
| 622 | } | ||
| 623 | return params; | ||
| 624 | } | ||
| 525 | 625 | ||
| 626 | Common::ParamPackage SDLEventToButtonParamPackage(SDLState& state, const SDL_Event& event) { | ||
| 526 | switch (event.type) { | 627 | switch (event.type) { |
| 527 | case SDL_JOYAXISMOTION: { | 628 | case SDL_JOYAXISMOTION: { |
| 528 | const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which); | 629 | const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which); |
| 529 | params.Set("port", joystick->GetPort()); | 630 | return BuildAnalogParamPackageForButton(joystick->GetPort(), joystick->GetGUID(), |
| 530 | params.Set("guid", joystick->GetGUID()); | 631 | event.jaxis.axis, event.jaxis.value); |
| 531 | params.Set("axis", event.jaxis.axis); | ||
| 532 | if (event.jaxis.value > 0) { | ||
| 533 | params.Set("direction", "+"); | ||
| 534 | params.Set("threshold", "0.5"); | ||
| 535 | } else { | ||
| 536 | params.Set("direction", "-"); | ||
| 537 | params.Set("threshold", "-0.5"); | ||
| 538 | } | ||
| 539 | break; | ||
| 540 | } | 632 | } |
| 541 | case SDL_JOYBUTTONUP: { | 633 | case SDL_JOYBUTTONUP: { |
| 542 | const auto joystick = state.GetSDLJoystickBySDLID(event.jbutton.which); | 634 | const auto joystick = state.GetSDLJoystickBySDLID(event.jbutton.which); |
| 543 | params.Set("port", joystick->GetPort()); | 635 | return BuildButtonParamPackageForButton(joystick->GetPort(), joystick->GetGUID(), |
| 544 | params.Set("guid", joystick->GetGUID()); | 636 | event.jbutton.button); |
| 545 | params.Set("button", event.jbutton.button); | ||
| 546 | break; | ||
| 547 | } | 637 | } |
| 548 | case SDL_JOYHATMOTION: { | 638 | case SDL_JOYHATMOTION: { |
| 549 | const auto joystick = state.GetSDLJoystickBySDLID(event.jhat.which); | 639 | const auto joystick = state.GetSDLJoystickBySDLID(event.jhat.which); |
| 550 | params.Set("port", joystick->GetPort()); | 640 | return BuildHatParamPackageForButton(joystick->GetPort(), joystick->GetGUID(), |
| 551 | params.Set("guid", joystick->GetGUID()); | 641 | event.jhat.hat, event.jhat.value); |
| 552 | params.Set("hat", event.jhat.hat); | ||
| 553 | switch (event.jhat.value) { | ||
| 554 | case SDL_HAT_UP: | ||
| 555 | params.Set("direction", "up"); | ||
| 556 | break; | ||
| 557 | case SDL_HAT_DOWN: | ||
| 558 | params.Set("direction", "down"); | ||
| 559 | break; | ||
| 560 | case SDL_HAT_LEFT: | ||
| 561 | params.Set("direction", "left"); | ||
| 562 | break; | ||
| 563 | case SDL_HAT_RIGHT: | ||
| 564 | params.Set("direction", "right"); | ||
| 565 | break; | ||
| 566 | default: | ||
| 567 | return {}; | ||
| 568 | } | ||
| 569 | break; | ||
| 570 | } | 642 | } |
| 571 | } | 643 | } |
| 644 | return {}; | ||
| 645 | } | ||
| 646 | |||
| 647 | Common::ParamPackage BuildParamPackageForBinding(int port, const std::string& guid, | ||
| 648 | const SDL_GameControllerButtonBind& binding) { | ||
| 649 | switch (binding.bindType) { | ||
| 650 | case SDL_CONTROLLER_BINDTYPE_AXIS: | ||
| 651 | return BuildAnalogParamPackageForButton(port, guid, binding.value.axis); | ||
| 652 | case SDL_CONTROLLER_BINDTYPE_BUTTON: | ||
| 653 | return BuildButtonParamPackageForButton(port, guid, binding.value.button); | ||
| 654 | case SDL_CONTROLLER_BINDTYPE_HAT: | ||
| 655 | return BuildHatParamPackageForButton(port, guid, binding.value.hat.hat, | ||
| 656 | binding.value.hat.hat_mask); | ||
| 657 | } | ||
| 658 | return {}; | ||
| 659 | } | ||
| 660 | |||
| 661 | Common::ParamPackage BuildParamPackageForAnalog(int port, const std::string& guid, int axis_x, | ||
| 662 | int axis_y) { | ||
| 663 | Common::ParamPackage params; | ||
| 664 | params.Set("engine", "sdl"); | ||
| 665 | params.Set("port", port); | ||
| 666 | params.Set("guid", guid); | ||
| 667 | params.Set("axis_x", axis_x); | ||
| 668 | params.Set("axis_y", axis_y); | ||
| 572 | return params; | 669 | return params; |
| 573 | } | 670 | } |
| 671 | } // Anonymous namespace | ||
| 574 | 672 | ||
| 575 | namespace Polling { | 673 | ButtonMapping SDLState::GetButtonMappingForDevice(const Common::ParamPackage& params) { |
| 674 | if (!params.Has("guid") || !params.Has("port")) { | ||
| 675 | return {}; | ||
| 676 | } | ||
| 677 | const auto joystick = GetSDLJoystickByGUID(params.Get("guid", ""), params.Get("port", 0)); | ||
| 678 | auto* controller = joystick->GetSDLGameController(); | ||
| 679 | if (controller == nullptr) { | ||
| 680 | return {}; | ||
| 681 | } | ||
| 682 | |||
| 683 | // This list is missing ZL/ZR since those are not considered buttons in SDL GameController. | ||
| 684 | // We will add those afterwards | ||
| 685 | // This list also excludes Screenshot since theres not really a mapping for that | ||
| 686 | using ButtonBindings = | ||
| 687 | std::array<std::pair<Settings::NativeButton::Values, SDL_GameControllerButton>, 17>; | ||
| 688 | static constexpr ButtonBindings switch_to_sdl_button{{ | ||
| 689 | {Settings::NativeButton::A, SDL_CONTROLLER_BUTTON_B}, | ||
| 690 | {Settings::NativeButton::B, SDL_CONTROLLER_BUTTON_A}, | ||
| 691 | {Settings::NativeButton::X, SDL_CONTROLLER_BUTTON_Y}, | ||
| 692 | {Settings::NativeButton::Y, SDL_CONTROLLER_BUTTON_X}, | ||
| 693 | {Settings::NativeButton::LStick, SDL_CONTROLLER_BUTTON_LEFTSTICK}, | ||
| 694 | {Settings::NativeButton::RStick, SDL_CONTROLLER_BUTTON_RIGHTSTICK}, | ||
| 695 | {Settings::NativeButton::L, SDL_CONTROLLER_BUTTON_LEFTSHOULDER}, | ||
| 696 | {Settings::NativeButton::R, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER}, | ||
| 697 | {Settings::NativeButton::Plus, SDL_CONTROLLER_BUTTON_START}, | ||
| 698 | {Settings::NativeButton::Minus, SDL_CONTROLLER_BUTTON_BACK}, | ||
| 699 | {Settings::NativeButton::DLeft, SDL_CONTROLLER_BUTTON_DPAD_LEFT}, | ||
| 700 | {Settings::NativeButton::DUp, SDL_CONTROLLER_BUTTON_DPAD_UP}, | ||
| 701 | {Settings::NativeButton::DRight, SDL_CONTROLLER_BUTTON_DPAD_RIGHT}, | ||
| 702 | {Settings::NativeButton::DDown, SDL_CONTROLLER_BUTTON_DPAD_DOWN}, | ||
| 703 | {Settings::NativeButton::SL, SDL_CONTROLLER_BUTTON_LEFTSHOULDER}, | ||
| 704 | {Settings::NativeButton::SR, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER}, | ||
| 705 | {Settings::NativeButton::Home, SDL_CONTROLLER_BUTTON_GUIDE}, | ||
| 706 | }}; | ||
| 707 | |||
| 708 | // Add the missing bindings for ZL/ZR | ||
| 709 | using ZBindings = | ||
| 710 | std::array<std::pair<Settings::NativeButton::Values, SDL_GameControllerAxis>, 2>; | ||
| 711 | static constexpr ZBindings switch_to_sdl_axis{{ | ||
| 712 | {Settings::NativeButton::ZL, SDL_CONTROLLER_AXIS_TRIGGERLEFT}, | ||
| 713 | {Settings::NativeButton::ZR, SDL_CONTROLLER_AXIS_TRIGGERRIGHT}, | ||
| 714 | }}; | ||
| 715 | |||
| 716 | ButtonMapping mapping; | ||
| 717 | mapping.reserve(switch_to_sdl_button.size() + switch_to_sdl_axis.size()); | ||
| 718 | |||
| 719 | for (const auto& [switch_button, sdl_button] : switch_to_sdl_button) { | ||
| 720 | const auto& binding = SDL_GameControllerGetBindForButton(controller, sdl_button); | ||
| 721 | mapping.insert_or_assign( | ||
| 722 | switch_button, | ||
| 723 | BuildParamPackageForBinding(joystick->GetPort(), joystick->GetGUID(), binding)); | ||
| 724 | } | ||
| 725 | for (const auto& [switch_button, sdl_axis] : switch_to_sdl_axis) { | ||
| 726 | const auto& binding = SDL_GameControllerGetBindForAxis(controller, sdl_axis); | ||
| 727 | mapping.insert_or_assign( | ||
| 728 | switch_button, | ||
| 729 | BuildParamPackageForBinding(joystick->GetPort(), joystick->GetGUID(), binding)); | ||
| 730 | } | ||
| 731 | |||
| 732 | return mapping; | ||
| 733 | } | ||
| 576 | 734 | ||
| 735 | AnalogMapping SDLState::GetAnalogMappingForDevice(const Common::ParamPackage& params) { | ||
| 736 | if (!params.Has("guid") || !params.Has("port")) { | ||
| 737 | return {}; | ||
| 738 | } | ||
| 739 | const auto joystick = GetSDLJoystickByGUID(params.Get("guid", ""), params.Get("port", 0)); | ||
| 740 | auto* controller = joystick->GetSDLGameController(); | ||
| 741 | if (controller == nullptr) { | ||
| 742 | return {}; | ||
| 743 | } | ||
| 744 | |||
| 745 | AnalogMapping mapping = {}; | ||
| 746 | const auto& binding_left_x = | ||
| 747 | SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTX); | ||
| 748 | const auto& binding_left_y = | ||
| 749 | SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTY); | ||
| 750 | mapping.insert_or_assign(Settings::NativeAnalog::LStick, | ||
| 751 | BuildParamPackageForAnalog(joystick->GetPort(), joystick->GetGUID(), | ||
| 752 | binding_left_x.value.axis, | ||
| 753 | binding_left_y.value.axis)); | ||
| 754 | const auto& binding_right_x = | ||
| 755 | SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_RIGHTX); | ||
| 756 | const auto& binding_right_y = | ||
| 757 | SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_RIGHTY); | ||
| 758 | mapping.insert_or_assign(Settings::NativeAnalog::RStick, | ||
| 759 | BuildParamPackageForAnalog(joystick->GetPort(), joystick->GetGUID(), | ||
| 760 | binding_right_x.value.axis, | ||
| 761 | binding_right_y.value.axis)); | ||
| 762 | return mapping; | ||
| 763 | } | ||
| 764 | |||
| 765 | namespace Polling { | ||
| 577 | class SDLPoller : public InputCommon::Polling::DevicePoller { | 766 | class SDLPoller : public InputCommon::Polling::DevicePoller { |
| 578 | public: | 767 | public: |
| 579 | explicit SDLPoller(SDLState& state_) : state(state_) {} | 768 | explicit SDLPoller(SDLState& state_) : state(state_) {} |
| 580 | 769 | ||
| 581 | void Start() override { | 770 | void Start(const std::string& device_id) override { |
| 582 | state.event_queue.Clear(); | 771 | state.event_queue.Clear(); |
| 583 | state.polling = true; | 772 | state.polling = true; |
| 584 | } | 773 | } |
| @@ -598,71 +787,106 @@ public: | |||
| 598 | Common::ParamPackage GetNextInput() override { | 787 | Common::ParamPackage GetNextInput() override { |
| 599 | SDL_Event event; | 788 | SDL_Event event; |
| 600 | while (state.event_queue.Pop(event)) { | 789 | while (state.event_queue.Pop(event)) { |
| 601 | switch (event.type) { | 790 | const auto package = FromEvent(event); |
| 602 | case SDL_JOYAXISMOTION: | 791 | if (package) { |
| 603 | if (std::abs(event.jaxis.value / 32767.0) < 0.5) { | 792 | return *package; |
| 604 | break; | ||
| 605 | } | ||
| 606 | [[fallthrough]]; | ||
| 607 | case SDL_JOYBUTTONUP: | ||
| 608 | case SDL_JOYHATMOTION: | ||
| 609 | return SDLEventToButtonParamPackage(state, event); | ||
| 610 | } | 793 | } |
| 611 | } | 794 | } |
| 612 | return {}; | 795 | return {}; |
| 613 | } | 796 | } |
| 797 | [[nodiscard]] std::optional<Common::ParamPackage> FromEvent(const SDL_Event& event) const { | ||
| 798 | switch (event.type) { | ||
| 799 | case SDL_JOYAXISMOTION: | ||
| 800 | if (std::abs(event.jaxis.value / 32767.0) < 0.5) { | ||
| 801 | break; | ||
| 802 | } | ||
| 803 | [[fallthrough]]; | ||
| 804 | case SDL_JOYBUTTONUP: | ||
| 805 | case SDL_JOYHATMOTION: | ||
| 806 | return {SDLEventToButtonParamPackage(state, event)}; | ||
| 807 | } | ||
| 808 | return std::nullopt; | ||
| 809 | } | ||
| 614 | }; | 810 | }; |
| 615 | 811 | ||
| 616 | class SDLAnalogPoller final : public SDLPoller { | 812 | /** |
| 813 | * Attempts to match the press to a controller joy axis (left/right stick) and if a match | ||
| 814 | * isn't found, checks if the event matches anything from SDLButtonPoller and uses that | ||
| 815 | * instead | ||
| 816 | */ | ||
| 817 | class SDLAnalogPreferredPoller final : public SDLPoller { | ||
| 617 | public: | 818 | public: |
| 618 | explicit SDLAnalogPoller(SDLState& state_) : SDLPoller(state_) {} | 819 | explicit SDLAnalogPreferredPoller(SDLState& state_) |
| 619 | 820 | : SDLPoller(state_), button_poller(state_) {} | |
| 620 | void Start() override { | ||
| 621 | SDLPoller::Start(); | ||
| 622 | 821 | ||
| 822 | void Start(const std::string& device_id) override { | ||
| 823 | SDLPoller::Start(device_id); | ||
| 824 | // Load the game controller | ||
| 623 | // Reset stored axes | 825 | // Reset stored axes |
| 624 | analog_x_axis = -1; | 826 | analog_x_axis = -1; |
| 625 | analog_y_axis = -1; | 827 | analog_y_axis = -1; |
| 626 | analog_axes_joystick = -1; | ||
| 627 | } | 828 | } |
| 628 | 829 | ||
| 629 | Common::ParamPackage GetNextInput() override { | 830 | Common::ParamPackage GetNextInput() override { |
| 630 | SDL_Event event; | 831 | SDL_Event event; |
| 631 | while (state.event_queue.Pop(event)) { | 832 | while (state.event_queue.Pop(event)) { |
| 632 | if (event.type != SDL_JOYAXISMOTION || std::abs(event.jaxis.value / 32767.0) < 0.5) { | 833 | // Filter out axis events that are below a threshold |
| 834 | if (event.type == SDL_JOYAXISMOTION && std::abs(event.jaxis.value / 32767.0) < 0.5) { | ||
| 633 | continue; | 835 | continue; |
| 634 | } | 836 | } |
| 635 | // An analog device needs two axes, so we need to store the axis for later and wait for | 837 | // Simplify controller config by testing if game controller support is enabled. |
| 636 | // a second SDL event. The axes also must be from the same joystick. | 838 | if (event.type == SDL_JOYAXISMOTION) { |
| 637 | const int axis = event.jaxis.axis; | 839 | const auto axis = event.jaxis.axis; |
| 638 | if (analog_x_axis == -1) { | 840 | const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which); |
| 639 | analog_x_axis = axis; | 841 | const auto controller = joystick->GetSDLGameController(); |
| 640 | analog_axes_joystick = event.jaxis.which; | 842 | if (controller) { |
| 641 | } else if (analog_y_axis == -1 && analog_x_axis != axis && | 843 | const auto axis_left_x = |
| 642 | analog_axes_joystick == event.jaxis.which) { | 844 | SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTX) |
| 643 | analog_y_axis = axis; | 845 | .value.axis; |
| 846 | const auto axis_left_y = | ||
| 847 | SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTY) | ||
| 848 | .value.axis; | ||
| 849 | const auto axis_right_x = | ||
| 850 | SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_RIGHTX) | ||
| 851 | .value.axis; | ||
| 852 | const auto axis_right_y = | ||
| 853 | SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_RIGHTY) | ||
| 854 | .value.axis; | ||
| 855 | |||
| 856 | if (axis == axis_left_x || axis == axis_left_y) { | ||
| 857 | analog_x_axis = axis_left_x; | ||
| 858 | analog_y_axis = axis_left_y; | ||
| 859 | break; | ||
| 860 | } else if (axis == axis_right_x || axis == axis_right_y) { | ||
| 861 | analog_x_axis = axis_right_x; | ||
| 862 | analog_y_axis = axis_right_y; | ||
| 863 | break; | ||
| 864 | } | ||
| 865 | } | ||
| 866 | } | ||
| 867 | |||
| 868 | // If the press wasn't accepted as a joy axis, check for a button press | ||
| 869 | auto button_press = button_poller.FromEvent(event); | ||
| 870 | if (button_press) { | ||
| 871 | return *button_press; | ||
| 644 | } | 872 | } |
| 645 | } | 873 | } |
| 646 | Common::ParamPackage params; | 874 | |
| 647 | if (analog_x_axis != -1 && analog_y_axis != -1) { | 875 | if (analog_x_axis != -1 && analog_y_axis != -1) { |
| 648 | const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which); | 876 | const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which); |
| 649 | params.Set("engine", "sdl"); | 877 | auto params = BuildParamPackageForAnalog(joystick->GetPort(), joystick->GetGUID(), |
| 650 | params.Set("port", joystick->GetPort()); | 878 | analog_x_axis, analog_y_axis); |
| 651 | params.Set("guid", joystick->GetGUID()); | ||
| 652 | params.Set("axis_x", analog_x_axis); | ||
| 653 | params.Set("axis_y", analog_y_axis); | ||
| 654 | analog_x_axis = -1; | 879 | analog_x_axis = -1; |
| 655 | analog_y_axis = -1; | 880 | analog_y_axis = -1; |
| 656 | analog_axes_joystick = -1; | ||
| 657 | return params; | 881 | return params; |
| 658 | } | 882 | } |
| 659 | return params; | 883 | return {}; |
| 660 | } | 884 | } |
| 661 | 885 | ||
| 662 | private: | 886 | private: |
| 663 | int analog_x_axis = -1; | 887 | int analog_x_axis = -1; |
| 664 | int analog_y_axis = -1; | 888 | int analog_y_axis = -1; |
| 665 | SDL_JoystickID analog_axes_joystick = -1; | 889 | SDLButtonPoller button_poller; |
| 666 | }; | 890 | }; |
| 667 | } // namespace Polling | 891 | } // namespace Polling |
| 668 | 892 | ||
| @@ -670,8 +894,8 @@ SDLState::Pollers SDLState::GetPollers(InputCommon::Polling::DeviceType type) { | |||
| 670 | Pollers pollers; | 894 | Pollers pollers; |
| 671 | 895 | ||
| 672 | switch (type) { | 896 | switch (type) { |
| 673 | case InputCommon::Polling::DeviceType::Analog: | 897 | case InputCommon::Polling::DeviceType::AnalogPreferred: |
| 674 | pollers.emplace_back(std::make_unique<Polling::SDLAnalogPoller>(*this)); | 898 | pollers.emplace_back(std::make_unique<Polling::SDLAnalogPreferredPoller>(*this)); |
| 675 | break; | 899 | break; |
| 676 | case InputCommon::Polling::DeviceType::Button: | 900 | case InputCommon::Polling::DeviceType::Button: |
| 677 | pollers.emplace_back(std::make_unique<Polling::SDLButtonPoller>(*this)); | 901 | pollers.emplace_back(std::make_unique<Polling::SDLButtonPoller>(*this)); |
diff --git a/src/input_common/sdl/sdl_impl.h b/src/input_common/sdl/sdl_impl.h index 606a32c5b..bd19ba61d 100644 --- a/src/input_common/sdl/sdl_impl.h +++ b/src/input_common/sdl/sdl_impl.h | |||
| @@ -50,6 +50,11 @@ public: | |||
| 50 | std::atomic<bool> polling = false; | 50 | std::atomic<bool> polling = false; |
| 51 | Common::SPSCQueue<SDL_Event> event_queue; | 51 | Common::SPSCQueue<SDL_Event> event_queue; |
| 52 | 52 | ||
| 53 | std::vector<Common::ParamPackage> GetInputDevices() override; | ||
| 54 | |||
| 55 | ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage& params) override; | ||
| 56 | AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage& params) override; | ||
| 57 | |||
| 53 | private: | 58 | private: |
| 54 | void InitJoystick(int joystick_index); | 59 | void InitJoystick(int joystick_index); |
| 55 | void CloseJoystick(SDL_Joystick* sdl_joystick); | 60 | void CloseJoystick(SDL_Joystick* sdl_joystick); |
| @@ -57,6 +62,9 @@ private: | |||
| 57 | /// Needs to be called before SDL_QuitSubSystem. | 62 | /// Needs to be called before SDL_QuitSubSystem. |
| 58 | void CloseJoysticks(); | 63 | void CloseJoysticks(); |
| 59 | 64 | ||
| 65 | // Set to true if SDL supports game controller subsystem | ||
| 66 | bool has_gamecontroller = false; | ||
| 67 | |||
| 60 | /// Map of GUID of a list of corresponding virtual Joysticks | 68 | /// Map of GUID of a list of corresponding virtual Joysticks |
| 61 | std::unordered_map<std::string, std::vector<std::shared_ptr<SDLJoystick>>> joystick_map; | 69 | std::unordered_map<std::string, std::vector<std::shared_ptr<SDLJoystick>>> joystick_map; |
| 62 | std::mutex joystick_map_mutex; | 70 | std::mutex joystick_map_mutex; |
diff --git a/src/input_common/settings.cpp b/src/input_common/settings.cpp new file mode 100644 index 000000000..80c719cf4 --- /dev/null +++ b/src/input_common/settings.cpp | |||
| @@ -0,0 +1,33 @@ | |||
| 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 "input_common/settings.h" | ||
| 6 | |||
| 7 | namespace Settings { | ||
| 8 | namespace NativeButton { | ||
| 9 | const std::array<const char*, NumButtons> mapping = {{ | ||
| 10 | "button_a", "button_b", "button_x", "button_y", "button_lstick", | ||
| 11 | "button_rstick", "button_l", "button_r", "button_zl", "button_zr", | ||
| 12 | "button_plus", "button_minus", "button_dleft", "button_dup", "button_dright", | ||
| 13 | "button_ddown", "button_sl", "button_sr", "button_home", "button_screenshot", | ||
| 14 | }}; | ||
| 15 | } | ||
| 16 | |||
| 17 | namespace NativeAnalog { | ||
| 18 | const std::array<const char*, NumAnalogs> mapping = {{ | ||
| 19 | "lstick", | ||
| 20 | "rstick", | ||
| 21 | }}; | ||
| 22 | } | ||
| 23 | |||
| 24 | namespace NativeMouseButton { | ||
| 25 | const std::array<const char*, NumMouseButtons> mapping = {{ | ||
| 26 | "left", | ||
| 27 | "right", | ||
| 28 | "middle", | ||
| 29 | "forward", | ||
| 30 | "back", | ||
| 31 | }}; | ||
| 32 | } | ||
| 33 | } // namespace Settings | ||
diff --git a/src/input_common/settings.h b/src/input_common/settings.h new file mode 100644 index 000000000..2d258960b --- /dev/null +++ b/src/input_common/settings.h | |||
| @@ -0,0 +1,335 @@ | |||
| 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 | #include <string> | ||
| 9 | #include "common/common_types.h" | ||
| 10 | |||
| 11 | namespace Settings { | ||
| 12 | namespace NativeButton { | ||
| 13 | enum Values : int { | ||
| 14 | A, | ||
| 15 | B, | ||
| 16 | X, | ||
| 17 | Y, | ||
| 18 | LStick, | ||
| 19 | RStick, | ||
| 20 | L, | ||
| 21 | R, | ||
| 22 | ZL, | ||
| 23 | ZR, | ||
| 24 | Plus, | ||
| 25 | Minus, | ||
| 26 | |||
| 27 | DLeft, | ||
| 28 | DUp, | ||
| 29 | DRight, | ||
| 30 | DDown, | ||
| 31 | |||
| 32 | SL, | ||
| 33 | SR, | ||
| 34 | |||
| 35 | Home, | ||
| 36 | Screenshot, | ||
| 37 | |||
| 38 | NumButtons, | ||
| 39 | }; | ||
| 40 | |||
| 41 | constexpr int BUTTON_HID_BEGIN = A; | ||
| 42 | constexpr int BUTTON_NS_BEGIN = Home; | ||
| 43 | |||
| 44 | constexpr int BUTTON_HID_END = BUTTON_NS_BEGIN; | ||
| 45 | constexpr int BUTTON_NS_END = NumButtons; | ||
| 46 | |||
| 47 | constexpr int NUM_BUTTONS_HID = BUTTON_HID_END - BUTTON_HID_BEGIN; | ||
| 48 | constexpr int NUM_BUTTONS_NS = BUTTON_NS_END - BUTTON_NS_BEGIN; | ||
| 49 | |||
| 50 | extern const std::array<const char*, NumButtons> mapping; | ||
| 51 | |||
| 52 | } // namespace NativeButton | ||
| 53 | |||
| 54 | namespace NativeAnalog { | ||
| 55 | enum Values : int { | ||
| 56 | LStick, | ||
| 57 | RStick, | ||
| 58 | |||
| 59 | NumAnalogs, | ||
| 60 | }; | ||
| 61 | |||
| 62 | constexpr int STICK_HID_BEGIN = LStick; | ||
| 63 | constexpr int STICK_HID_END = NumAnalogs; | ||
| 64 | constexpr int NUM_STICKS_HID = NumAnalogs; | ||
| 65 | |||
| 66 | extern const std::array<const char*, NumAnalogs> mapping; | ||
| 67 | } // namespace NativeAnalog | ||
| 68 | |||
| 69 | namespace NativeMouseButton { | ||
| 70 | enum Values { | ||
| 71 | Left, | ||
| 72 | Right, | ||
| 73 | Middle, | ||
| 74 | Forward, | ||
| 75 | Back, | ||
| 76 | |||
| 77 | NumMouseButtons, | ||
| 78 | }; | ||
| 79 | |||
| 80 | constexpr int MOUSE_HID_BEGIN = Left; | ||
| 81 | constexpr int MOUSE_HID_END = NumMouseButtons; | ||
| 82 | constexpr int NUM_MOUSE_HID = NumMouseButtons; | ||
| 83 | |||
| 84 | extern const std::array<const char*, NumMouseButtons> mapping; | ||
| 85 | } // namespace NativeMouseButton | ||
| 86 | |||
| 87 | namespace NativeKeyboard { | ||
| 88 | enum Keys { | ||
| 89 | None, | ||
| 90 | Error, | ||
| 91 | |||
| 92 | A = 4, | ||
| 93 | B, | ||
| 94 | C, | ||
| 95 | D, | ||
| 96 | E, | ||
| 97 | F, | ||
| 98 | G, | ||
| 99 | H, | ||
| 100 | I, | ||
| 101 | J, | ||
| 102 | K, | ||
| 103 | L, | ||
| 104 | M, | ||
| 105 | N, | ||
| 106 | O, | ||
| 107 | P, | ||
| 108 | Q, | ||
| 109 | R, | ||
| 110 | S, | ||
| 111 | T, | ||
| 112 | U, | ||
| 113 | V, | ||
| 114 | W, | ||
| 115 | X, | ||
| 116 | Y, | ||
| 117 | Z, | ||
| 118 | N1, | ||
| 119 | N2, | ||
| 120 | N3, | ||
| 121 | N4, | ||
| 122 | N5, | ||
| 123 | N6, | ||
| 124 | N7, | ||
| 125 | N8, | ||
| 126 | N9, | ||
| 127 | N0, | ||
| 128 | Enter, | ||
| 129 | Escape, | ||
| 130 | Backspace, | ||
| 131 | Tab, | ||
| 132 | Space, | ||
| 133 | Minus, | ||
| 134 | Equal, | ||
| 135 | LeftBrace, | ||
| 136 | RightBrace, | ||
| 137 | Backslash, | ||
| 138 | Tilde, | ||
| 139 | Semicolon, | ||
| 140 | Apostrophe, | ||
| 141 | Grave, | ||
| 142 | Comma, | ||
| 143 | Dot, | ||
| 144 | Slash, | ||
| 145 | CapsLockKey, | ||
| 146 | |||
| 147 | F1, | ||
| 148 | F2, | ||
| 149 | F3, | ||
| 150 | F4, | ||
| 151 | F5, | ||
| 152 | F6, | ||
| 153 | F7, | ||
| 154 | F8, | ||
| 155 | F9, | ||
| 156 | F10, | ||
| 157 | F11, | ||
| 158 | F12, | ||
| 159 | |||
| 160 | SystemRequest, | ||
| 161 | ScrollLockKey, | ||
| 162 | Pause, | ||
| 163 | Insert, | ||
| 164 | Home, | ||
| 165 | PageUp, | ||
| 166 | Delete, | ||
| 167 | End, | ||
| 168 | PageDown, | ||
| 169 | Right, | ||
| 170 | Left, | ||
| 171 | Down, | ||
| 172 | Up, | ||
| 173 | |||
| 174 | NumLockKey, | ||
| 175 | KPSlash, | ||
| 176 | KPAsterisk, | ||
| 177 | KPMinus, | ||
| 178 | KPPlus, | ||
| 179 | KPEnter, | ||
| 180 | KP1, | ||
| 181 | KP2, | ||
| 182 | KP3, | ||
| 183 | KP4, | ||
| 184 | KP5, | ||
| 185 | KP6, | ||
| 186 | KP7, | ||
| 187 | KP8, | ||
| 188 | KP9, | ||
| 189 | KP0, | ||
| 190 | KPDot, | ||
| 191 | |||
| 192 | Key102, | ||
| 193 | Compose, | ||
| 194 | Power, | ||
| 195 | KPEqual, | ||
| 196 | |||
| 197 | F13, | ||
| 198 | F14, | ||
| 199 | F15, | ||
| 200 | F16, | ||
| 201 | F17, | ||
| 202 | F18, | ||
| 203 | F19, | ||
| 204 | F20, | ||
| 205 | F21, | ||
| 206 | F22, | ||
| 207 | F23, | ||
| 208 | F24, | ||
| 209 | |||
| 210 | Open, | ||
| 211 | Help, | ||
| 212 | Properties, | ||
| 213 | Front, | ||
| 214 | Stop, | ||
| 215 | Repeat, | ||
| 216 | Undo, | ||
| 217 | Cut, | ||
| 218 | Copy, | ||
| 219 | Paste, | ||
| 220 | Find, | ||
| 221 | Mute, | ||
| 222 | VolumeUp, | ||
| 223 | VolumeDown, | ||
| 224 | CapsLockActive, | ||
| 225 | NumLockActive, | ||
| 226 | ScrollLockActive, | ||
| 227 | KPComma, | ||
| 228 | |||
| 229 | KPLeftParenthesis, | ||
| 230 | KPRightParenthesis, | ||
| 231 | |||
| 232 | LeftControlKey = 0xE0, | ||
| 233 | LeftShiftKey, | ||
| 234 | LeftAltKey, | ||
| 235 | LeftMetaKey, | ||
| 236 | RightControlKey, | ||
| 237 | RightShiftKey, | ||
| 238 | RightAltKey, | ||
| 239 | RightMetaKey, | ||
| 240 | |||
| 241 | MediaPlayPause, | ||
| 242 | MediaStopCD, | ||
| 243 | MediaPrevious, | ||
| 244 | MediaNext, | ||
| 245 | MediaEject, | ||
| 246 | MediaVolumeUp, | ||
| 247 | MediaVolumeDown, | ||
| 248 | MediaMute, | ||
| 249 | MediaWebsite, | ||
| 250 | MediaBack, | ||
| 251 | MediaForward, | ||
| 252 | MediaStop, | ||
| 253 | MediaFind, | ||
| 254 | MediaScrollUp, | ||
| 255 | MediaScrollDown, | ||
| 256 | MediaEdit, | ||
| 257 | MediaSleep, | ||
| 258 | MediaCoffee, | ||
| 259 | MediaRefresh, | ||
| 260 | MediaCalculator, | ||
| 261 | |||
| 262 | NumKeyboardKeys, | ||
| 263 | }; | ||
| 264 | |||
| 265 | static_assert(NumKeyboardKeys == 0xFC, "Incorrect number of keyboard keys."); | ||
| 266 | |||
| 267 | enum Modifiers { | ||
| 268 | LeftControl, | ||
| 269 | LeftShift, | ||
| 270 | LeftAlt, | ||
| 271 | LeftMeta, | ||
| 272 | RightControl, | ||
| 273 | RightShift, | ||
| 274 | RightAlt, | ||
| 275 | RightMeta, | ||
| 276 | CapsLock, | ||
| 277 | ScrollLock, | ||
| 278 | NumLock, | ||
| 279 | |||
| 280 | NumKeyboardMods, | ||
| 281 | }; | ||
| 282 | |||
| 283 | constexpr int KEYBOARD_KEYS_HID_BEGIN = None; | ||
| 284 | constexpr int KEYBOARD_KEYS_HID_END = NumKeyboardKeys; | ||
| 285 | constexpr int NUM_KEYBOARD_KEYS_HID = NumKeyboardKeys; | ||
| 286 | |||
| 287 | constexpr int KEYBOARD_MODS_HID_BEGIN = LeftControl; | ||
| 288 | constexpr int KEYBOARD_MODS_HID_END = NumKeyboardMods; | ||
| 289 | constexpr int NUM_KEYBOARD_MODS_HID = NumKeyboardMods; | ||
| 290 | |||
| 291 | } // namespace NativeKeyboard | ||
| 292 | |||
| 293 | using ButtonsRaw = std::array<std::string, NativeButton::NumButtons>; | ||
| 294 | using AnalogsRaw = std::array<std::string, NativeAnalog::NumAnalogs>; | ||
| 295 | using MouseButtonsRaw = std::array<std::string, NativeMouseButton::NumMouseButtons>; | ||
| 296 | using KeyboardKeysRaw = std::array<std::string, NativeKeyboard::NumKeyboardKeys>; | ||
| 297 | using KeyboardModsRaw = std::array<std::string, NativeKeyboard::NumKeyboardMods>; | ||
| 298 | |||
| 299 | constexpr u32 JOYCON_BODY_NEON_RED = 0xFF3C28; | ||
| 300 | constexpr u32 JOYCON_BUTTONS_NEON_RED = 0x1E0A0A; | ||
| 301 | constexpr u32 JOYCON_BODY_NEON_BLUE = 0x0AB9E6; | ||
| 302 | constexpr u32 JOYCON_BUTTONS_NEON_BLUE = 0x001E1E; | ||
| 303 | |||
| 304 | enum class ControllerType { | ||
| 305 | ProController, | ||
| 306 | DualJoyconDetached, | ||
| 307 | LeftJoycon, | ||
| 308 | RightJoycon, | ||
| 309 | Handheld, | ||
| 310 | }; | ||
| 311 | |||
| 312 | struct PlayerInput { | ||
| 313 | bool connected; | ||
| 314 | ControllerType controller_type; | ||
| 315 | ButtonsRaw buttons; | ||
| 316 | AnalogsRaw analogs; | ||
| 317 | std::string lstick_mod; | ||
| 318 | std::string rstick_mod; | ||
| 319 | |||
| 320 | u32 body_color_left; | ||
| 321 | u32 body_color_right; | ||
| 322 | u32 button_color_left; | ||
| 323 | u32 button_color_right; | ||
| 324 | }; | ||
| 325 | |||
| 326 | struct TouchscreenInput { | ||
| 327 | bool enabled; | ||
| 328 | std::string device; | ||
| 329 | |||
| 330 | u32 finger; | ||
| 331 | u32 diameter_x; | ||
| 332 | u32 diameter_y; | ||
| 333 | u32 rotation_angle; | ||
| 334 | }; | ||
| 335 | } // namespace Settings | ||
diff --git a/src/input_common/udp/client.cpp b/src/input_common/udp/client.cpp index 6c95a8b42..3f4eaf448 100644 --- a/src/input_common/udp/client.cpp +++ b/src/input_common/udp/client.cpp | |||
| @@ -224,8 +224,7 @@ void TestCommunication(const std::string& host, u16 port, u8 pad_index, u32 clie | |||
| 224 | } else { | 224 | } else { |
| 225 | failure_callback(); | 225 | failure_callback(); |
| 226 | } | 226 | } |
| 227 | }) | 227 | }).detach(); |
| 228 | .detach(); | ||
| 229 | } | 228 | } |
| 230 | 229 | ||
| 231 | CalibrationConfigurationJob::CalibrationConfigurationJob( | 230 | CalibrationConfigurationJob::CalibrationConfigurationJob( |
| @@ -279,8 +278,7 @@ CalibrationConfigurationJob::CalibrationConfigurationJob( | |||
| 279 | complete_event.Wait(); | 278 | complete_event.Wait(); |
| 280 | socket.Stop(); | 279 | socket.Stop(); |
| 281 | worker_thread.join(); | 280 | worker_thread.join(); |
| 282 | }) | 281 | }).detach(); |
| 283 | .detach(); | ||
| 284 | } | 282 | } |
| 285 | 283 | ||
| 286 | CalibrationConfigurationJob::~CalibrationConfigurationJob() { | 284 | CalibrationConfigurationJob::~CalibrationConfigurationJob() { |
diff --git a/src/input_common/udp/udp.cpp b/src/input_common/udp/udp.cpp index 8c6ef1394..4b347e47e 100644 --- a/src/input_common/udp/udp.cpp +++ b/src/input_common/udp/udp.cpp | |||
| @@ -77,10 +77,11 @@ State::State() { | |||
| 77 | std::make_unique<Client>(status, Settings::values.udp_input_address, | 77 | std::make_unique<Client>(status, Settings::values.udp_input_address, |
| 78 | Settings::values.udp_input_port, Settings::values.udp_pad_index); | 78 | Settings::values.udp_input_port, Settings::values.udp_pad_index); |
| 79 | 79 | ||
| 80 | Input::RegisterFactory<Input::TouchDevice>("cemuhookudp", | 80 | motion_factory = std::make_shared<UDPMotionFactory>(status); |
| 81 | std::make_shared<UDPTouchFactory>(status)); | 81 | touch_factory = std::make_shared<UDPTouchFactory>(status); |
| 82 | Input::RegisterFactory<Input::MotionDevice>("cemuhookudp", | 82 | |
| 83 | std::make_shared<UDPMotionFactory>(status)); | 83 | Input::RegisterFactory<Input::MotionDevice>("cemuhookudp", motion_factory); |
| 84 | Input::RegisterFactory<Input::TouchDevice>("cemuhookudp", touch_factory); | ||
| 84 | } | 85 | } |
| 85 | 86 | ||
| 86 | State::~State() { | 87 | State::~State() { |
| @@ -88,6 +89,11 @@ State::~State() { | |||
| 88 | Input::UnregisterFactory<Input::MotionDevice>("cemuhookudp"); | 89 | Input::UnregisterFactory<Input::MotionDevice>("cemuhookudp"); |
| 89 | } | 90 | } |
| 90 | 91 | ||
| 92 | std::vector<Common::ParamPackage> State::GetInputDevices() const { | ||
| 93 | // TODO support binding udp devices | ||
| 94 | return {}; | ||
| 95 | } | ||
| 96 | |||
| 91 | void State::ReloadUDPClient() { | 97 | void State::ReloadUDPClient() { |
| 92 | client->ReloadSocket(Settings::values.udp_input_address, Settings::values.udp_input_port, | 98 | client->ReloadSocket(Settings::values.udp_input_address, Settings::values.udp_input_port, |
| 93 | Settings::values.udp_pad_index); | 99 | Settings::values.udp_pad_index); |
diff --git a/src/input_common/udp/udp.h b/src/input_common/udp/udp.h index 4f83f0441..672a5c812 100644 --- a/src/input_common/udp/udp.h +++ b/src/input_common/udp/udp.h | |||
| @@ -5,19 +5,26 @@ | |||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <memory> | 7 | #include <memory> |
| 8 | #include <vector> | ||
| 9 | #include "common/param_package.h" | ||
| 8 | 10 | ||
| 9 | namespace InputCommon::CemuhookUDP { | 11 | namespace InputCommon::CemuhookUDP { |
| 10 | 12 | ||
| 11 | class Client; | 13 | class Client; |
| 14 | class UDPMotionFactory; | ||
| 15 | class UDPTouchFactory; | ||
| 12 | 16 | ||
| 13 | class State { | 17 | class State { |
| 14 | public: | 18 | public: |
| 15 | State(); | 19 | State(); |
| 16 | ~State(); | 20 | ~State(); |
| 17 | void ReloadUDPClient(); | 21 | void ReloadUDPClient(); |
| 22 | std::vector<Common::ParamPackage> GetInputDevices() const; | ||
| 18 | 23 | ||
| 19 | private: | 24 | private: |
| 20 | std::unique_ptr<Client> client; | 25 | std::unique_ptr<Client> client; |
| 26 | std::shared_ptr<UDPMotionFactory> motion_factory; | ||
| 27 | std::shared_ptr<UDPTouchFactory> touch_factory; | ||
| 21 | }; | 28 | }; |
| 22 | 29 | ||
| 23 | std::unique_ptr<State> Init(); | 30 | std::unique_ptr<State> Init(); |
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 3cd896a0f..d85f1e9d1 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt | |||
| @@ -1,3 +1,5 @@ | |||
| 1 | add_subdirectory(host_shaders) | ||
| 2 | |||
| 1 | add_library(video_core STATIC | 3 | add_library(video_core STATIC |
| 2 | buffer_cache/buffer_block.h | 4 | buffer_cache/buffer_block.h |
| 3 | buffer_cache/buffer_cache.h | 5 | buffer_cache/buffer_cache.h |
| @@ -244,6 +246,9 @@ create_target_directory_groups(video_core) | |||
| 244 | target_link_libraries(video_core PUBLIC common core) | 246 | target_link_libraries(video_core PUBLIC common core) |
| 245 | target_link_libraries(video_core PRIVATE glad xbyak) | 247 | target_link_libraries(video_core PRIVATE glad xbyak) |
| 246 | 248 | ||
| 249 | add_dependencies(video_core host_shaders) | ||
| 250 | target_include_directories(video_core PRIVATE ${HOST_SHADERS_INCLUDE}) | ||
| 251 | |||
| 247 | if (ENABLE_VULKAN) | 252 | if (ENABLE_VULKAN) |
| 248 | target_include_directories(video_core PRIVATE sirit ../../externals/Vulkan-Headers/include) | 253 | target_include_directories(video_core PRIVATE sirit ../../externals/Vulkan-Headers/include) |
| 249 | target_compile_definitions(video_core PRIVATE HAS_VULKAN) | 254 | target_compile_definitions(video_core PRIVATE HAS_VULKAN) |
diff --git a/src/video_core/engines/fermi_2d.cpp b/src/video_core/engines/fermi_2d.cpp index ff10ff40d..6e50661a3 100644 --- a/src/video_core/engines/fermi_2d.cpp +++ b/src/video_core/engines/fermi_2d.cpp | |||
| @@ -10,7 +10,13 @@ | |||
| 10 | 10 | ||
| 11 | namespace Tegra::Engines { | 11 | namespace Tegra::Engines { |
| 12 | 12 | ||
| 13 | Fermi2D::Fermi2D(VideoCore::RasterizerInterface& rasterizer) : rasterizer{rasterizer} {} | 13 | Fermi2D::Fermi2D() = default; |
| 14 | |||
| 15 | Fermi2D::~Fermi2D() = default; | ||
| 16 | |||
| 17 | void Fermi2D::BindRasterizer(VideoCore::RasterizerInterface& rasterizer_) { | ||
| 18 | rasterizer = &rasterizer_; | ||
| 19 | } | ||
| 14 | 20 | ||
| 15 | void Fermi2D::CallMethod(u32 method, u32 method_argument, bool is_last_call) { | 21 | void Fermi2D::CallMethod(u32 method, u32 method_argument, bool is_last_call) { |
| 16 | ASSERT_MSG(method < Regs::NUM_REGS, | 22 | ASSERT_MSG(method < Regs::NUM_REGS, |
| @@ -87,7 +93,7 @@ void Fermi2D::HandleSurfaceCopy() { | |||
| 87 | copy_config.src_rect = src_rect; | 93 | copy_config.src_rect = src_rect; |
| 88 | copy_config.dst_rect = dst_rect; | 94 | copy_config.dst_rect = dst_rect; |
| 89 | 95 | ||
| 90 | if (!rasterizer.AccelerateSurfaceCopy(regs.src, regs.dst, copy_config)) { | 96 | if (!rasterizer->AccelerateSurfaceCopy(regs.src, regs.dst, copy_config)) { |
| 91 | UNIMPLEMENTED(); | 97 | UNIMPLEMENTED(); |
| 92 | } | 98 | } |
| 93 | } | 99 | } |
diff --git a/src/video_core/engines/fermi_2d.h b/src/video_core/engines/fermi_2d.h index 8f37d053f..213abfaae 100644 --- a/src/video_core/engines/fermi_2d.h +++ b/src/video_core/engines/fermi_2d.h | |||
| @@ -34,8 +34,11 @@ namespace Tegra::Engines { | |||
| 34 | 34 | ||
| 35 | class Fermi2D final : public EngineInterface { | 35 | class Fermi2D final : public EngineInterface { |
| 36 | public: | 36 | public: |
| 37 | explicit Fermi2D(VideoCore::RasterizerInterface& rasterizer); | 37 | explicit Fermi2D(); |
| 38 | ~Fermi2D() = default; | 38 | ~Fermi2D(); |
| 39 | |||
| 40 | /// Binds a rasterizer to this engine. | ||
| 41 | void BindRasterizer(VideoCore::RasterizerInterface& rasterizer); | ||
| 39 | 42 | ||
| 40 | /// Write the value to the register identified by method. | 43 | /// Write the value to the register identified by method. |
| 41 | void CallMethod(u32 method, u32 method_argument, bool is_last_call) override; | 44 | void CallMethod(u32 method, u32 method_argument, bool is_last_call) override; |
| @@ -149,7 +152,7 @@ public: | |||
| 149 | }; | 152 | }; |
| 150 | 153 | ||
| 151 | private: | 154 | private: |
| 152 | VideoCore::RasterizerInterface& rasterizer; | 155 | VideoCore::RasterizerInterface* rasterizer; |
| 153 | 156 | ||
| 154 | /// Performs the copy from the source surface to the destination surface as configured in the | 157 | /// Performs the copy from the source surface to the destination surface as configured in the |
| 155 | /// registers. | 158 | /// registers. |
diff --git a/src/video_core/engines/kepler_compute.cpp b/src/video_core/engines/kepler_compute.cpp index a82b06a38..898370739 100644 --- a/src/video_core/engines/kepler_compute.cpp +++ b/src/video_core/engines/kepler_compute.cpp | |||
| @@ -16,14 +16,15 @@ | |||
| 16 | 16 | ||
| 17 | namespace Tegra::Engines { | 17 | namespace Tegra::Engines { |
| 18 | 18 | ||
| 19 | KeplerCompute::KeplerCompute(Core::System& system, VideoCore::RasterizerInterface& rasterizer, | 19 | KeplerCompute::KeplerCompute(Core::System& system_, MemoryManager& memory_manager_) |
| 20 | MemoryManager& memory_manager) | 20 | : system{system_}, memory_manager{memory_manager_}, upload_state{memory_manager, regs.upload} {} |
| 21 | : system{system}, rasterizer{rasterizer}, memory_manager{memory_manager}, upload_state{ | ||
| 22 | memory_manager, | ||
| 23 | regs.upload} {} | ||
| 24 | 21 | ||
| 25 | KeplerCompute::~KeplerCompute() = default; | 22 | KeplerCompute::~KeplerCompute() = default; |
| 26 | 23 | ||
| 24 | void KeplerCompute::BindRasterizer(VideoCore::RasterizerInterface& rasterizer_) { | ||
| 25 | rasterizer = &rasterizer_; | ||
| 26 | } | ||
| 27 | |||
| 27 | void KeplerCompute::CallMethod(u32 method, u32 method_argument, bool is_last_call) { | 28 | void KeplerCompute::CallMethod(u32 method, u32 method_argument, bool is_last_call) { |
| 28 | ASSERT_MSG(method < Regs::NUM_REGS, | 29 | ASSERT_MSG(method < Regs::NUM_REGS, |
| 29 | "Invalid KeplerCompute register, increase the size of the Regs structure"); | 30 | "Invalid KeplerCompute register, increase the size of the Regs structure"); |
| @@ -104,11 +105,11 @@ SamplerDescriptor KeplerCompute::AccessSampler(u32 handle) const { | |||
| 104 | } | 105 | } |
| 105 | 106 | ||
| 106 | VideoCore::GuestDriverProfile& KeplerCompute::AccessGuestDriverProfile() { | 107 | VideoCore::GuestDriverProfile& KeplerCompute::AccessGuestDriverProfile() { |
| 107 | return rasterizer.AccessGuestDriverProfile(); | 108 | return rasterizer->AccessGuestDriverProfile(); |
| 108 | } | 109 | } |
| 109 | 110 | ||
| 110 | const VideoCore::GuestDriverProfile& KeplerCompute::AccessGuestDriverProfile() const { | 111 | const VideoCore::GuestDriverProfile& KeplerCompute::AccessGuestDriverProfile() const { |
| 111 | return rasterizer.AccessGuestDriverProfile(); | 112 | return rasterizer->AccessGuestDriverProfile(); |
| 112 | } | 113 | } |
| 113 | 114 | ||
| 114 | void KeplerCompute::ProcessLaunch() { | 115 | void KeplerCompute::ProcessLaunch() { |
| @@ -119,7 +120,7 @@ void KeplerCompute::ProcessLaunch() { | |||
| 119 | const GPUVAddr code_addr = regs.code_loc.Address() + launch_description.program_start; | 120 | const GPUVAddr code_addr = regs.code_loc.Address() + launch_description.program_start; |
| 120 | LOG_TRACE(HW_GPU, "Compute invocation launched at address 0x{:016x}", code_addr); | 121 | LOG_TRACE(HW_GPU, "Compute invocation launched at address 0x{:016x}", code_addr); |
| 121 | 122 | ||
| 122 | rasterizer.DispatchCompute(code_addr); | 123 | rasterizer->DispatchCompute(code_addr); |
| 123 | } | 124 | } |
| 124 | 125 | ||
| 125 | Texture::TICEntry KeplerCompute::GetTICEntry(u32 tic_index) const { | 126 | Texture::TICEntry KeplerCompute::GetTICEntry(u32 tic_index) const { |
diff --git a/src/video_core/engines/kepler_compute.h b/src/video_core/engines/kepler_compute.h index b7f668d88..7f2500aab 100644 --- a/src/video_core/engines/kepler_compute.h +++ b/src/video_core/engines/kepler_compute.h | |||
| @@ -42,10 +42,12 @@ namespace Tegra::Engines { | |||
| 42 | 42 | ||
| 43 | class KeplerCompute final : public ConstBufferEngineInterface, public EngineInterface { | 43 | class KeplerCompute final : public ConstBufferEngineInterface, public EngineInterface { |
| 44 | public: | 44 | public: |
| 45 | explicit KeplerCompute(Core::System& system, VideoCore::RasterizerInterface& rasterizer, | 45 | explicit KeplerCompute(Core::System& system, MemoryManager& memory_manager); |
| 46 | MemoryManager& memory_manager); | ||
| 47 | ~KeplerCompute(); | 46 | ~KeplerCompute(); |
| 48 | 47 | ||
| 48 | /// Binds a rasterizer to this engine. | ||
| 49 | void BindRasterizer(VideoCore::RasterizerInterface& rasterizer); | ||
| 50 | |||
| 49 | static constexpr std::size_t NumConstBuffers = 8; | 51 | static constexpr std::size_t NumConstBuffers = 8; |
| 50 | 52 | ||
| 51 | struct Regs { | 53 | struct Regs { |
| @@ -230,11 +232,6 @@ public: | |||
| 230 | const VideoCore::GuestDriverProfile& AccessGuestDriverProfile() const override; | 232 | const VideoCore::GuestDriverProfile& AccessGuestDriverProfile() const override; |
| 231 | 233 | ||
| 232 | private: | 234 | private: |
| 233 | Core::System& system; | ||
| 234 | VideoCore::RasterizerInterface& rasterizer; | ||
| 235 | MemoryManager& memory_manager; | ||
| 236 | Upload::State upload_state; | ||
| 237 | |||
| 238 | void ProcessLaunch(); | 235 | void ProcessLaunch(); |
| 239 | 236 | ||
| 240 | /// Retrieves information about a specific TIC entry from the TIC buffer. | 237 | /// Retrieves information about a specific TIC entry from the TIC buffer. |
| @@ -242,6 +239,11 @@ private: | |||
| 242 | 239 | ||
| 243 | /// Retrieves information about a specific TSC entry from the TSC buffer. | 240 | /// Retrieves information about a specific TSC entry from the TSC buffer. |
| 244 | Texture::TSCEntry GetTSCEntry(u32 tsc_index) const; | 241 | Texture::TSCEntry GetTSCEntry(u32 tsc_index) const; |
| 242 | |||
| 243 | Core::System& system; | ||
| 244 | MemoryManager& memory_manager; | ||
| 245 | VideoCore::RasterizerInterface* rasterizer = nullptr; | ||
| 246 | Upload::State upload_state; | ||
| 245 | }; | 247 | }; |
| 246 | 248 | ||
| 247 | #define ASSERT_REG_POSITION(field_name, position) \ | 249 | #define ASSERT_REG_POSITION(field_name, position) \ |
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index c01436295..33854445f 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp | |||
| @@ -22,14 +22,19 @@ using VideoCore::QueryType; | |||
| 22 | /// First register id that is actually a Macro call. | 22 | /// First register id that is actually a Macro call. |
| 23 | constexpr u32 MacroRegistersStart = 0xE00; | 23 | constexpr u32 MacroRegistersStart = 0xE00; |
| 24 | 24 | ||
| 25 | Maxwell3D::Maxwell3D(Core::System& system, VideoCore::RasterizerInterface& rasterizer, | 25 | Maxwell3D::Maxwell3D(Core::System& system_, MemoryManager& memory_manager_) |
| 26 | MemoryManager& memory_manager) | 26 | : system{system_}, memory_manager{memory_manager_}, macro_engine{GetMacroEngine(*this)}, |
| 27 | : system{system}, rasterizer{rasterizer}, memory_manager{memory_manager}, | 27 | upload_state{memory_manager, regs.upload} { |
| 28 | macro_engine{GetMacroEngine(*this)}, upload_state{memory_manager, regs.upload} { | ||
| 29 | dirty.flags.flip(); | 28 | dirty.flags.flip(); |
| 30 | InitializeRegisterDefaults(); | 29 | InitializeRegisterDefaults(); |
| 31 | } | 30 | } |
| 32 | 31 | ||
| 32 | Maxwell3D::~Maxwell3D() = default; | ||
| 33 | |||
| 34 | void Maxwell3D::BindRasterizer(VideoCore::RasterizerInterface& rasterizer_) { | ||
| 35 | rasterizer = &rasterizer_; | ||
| 36 | } | ||
| 37 | |||
| 33 | void Maxwell3D::InitializeRegisterDefaults() { | 38 | void Maxwell3D::InitializeRegisterDefaults() { |
| 34 | // Initializes registers to their default values - what games expect them to be at boot. This is | 39 | // Initializes registers to their default values - what games expect them to be at boot. This is |
| 35 | // for certain registers that may not be explicitly set by games. | 40 | // for certain registers that may not be explicitly set by games. |
| @@ -192,7 +197,7 @@ void Maxwell3D::CallMethod(u32 method, u32 method_argument, bool is_last_call) { | |||
| 192 | 197 | ||
| 193 | switch (method) { | 198 | switch (method) { |
| 194 | case MAXWELL3D_REG_INDEX(wait_for_idle): { | 199 | case MAXWELL3D_REG_INDEX(wait_for_idle): { |
| 195 | rasterizer.WaitForIdle(); | 200 | rasterizer->WaitForIdle(); |
| 196 | break; | 201 | break; |
| 197 | } | 202 | } |
| 198 | case MAXWELL3D_REG_INDEX(shadow_ram_control): { | 203 | case MAXWELL3D_REG_INDEX(shadow_ram_control): { |
| @@ -402,7 +407,7 @@ void Maxwell3D::FlushMMEInlineDraw() { | |||
| 402 | 407 | ||
| 403 | const bool is_indexed = mme_draw.current_mode == MMEDrawMode::Indexed; | 408 | const bool is_indexed = mme_draw.current_mode == MMEDrawMode::Indexed; |
| 404 | if (ShouldExecute()) { | 409 | if (ShouldExecute()) { |
| 405 | rasterizer.Draw(is_indexed, true); | 410 | rasterizer->Draw(is_indexed, true); |
| 406 | } | 411 | } |
| 407 | 412 | ||
| 408 | // TODO(bunnei): Below, we reset vertex count so that we can use these registers to determine if | 413 | // TODO(bunnei): Below, we reset vertex count so that we can use these registers to determine if |
| @@ -465,7 +470,7 @@ void Maxwell3D::ProcessQueryGet() { | |||
| 465 | switch (regs.query.query_get.operation) { | 470 | switch (regs.query.query_get.operation) { |
| 466 | case Regs::QueryOperation::Release: | 471 | case Regs::QueryOperation::Release: |
| 467 | if (regs.query.query_get.fence == 1) { | 472 | if (regs.query.query_get.fence == 1) { |
| 468 | rasterizer.SignalSemaphore(regs.query.QueryAddress(), regs.query.query_sequence); | 473 | rasterizer->SignalSemaphore(regs.query.QueryAddress(), regs.query.query_sequence); |
| 469 | } else { | 474 | } else { |
| 470 | StampQueryResult(regs.query.query_sequence, regs.query.query_get.short_query == 0); | 475 | StampQueryResult(regs.query.query_sequence, regs.query.query_get.short_query == 0); |
| 471 | } | 476 | } |
| @@ -533,7 +538,7 @@ void Maxwell3D::ProcessQueryCondition() { | |||
| 533 | void Maxwell3D::ProcessCounterReset() { | 538 | void Maxwell3D::ProcessCounterReset() { |
| 534 | switch (regs.counter_reset) { | 539 | switch (regs.counter_reset) { |
| 535 | case Regs::CounterReset::SampleCnt: | 540 | case Regs::CounterReset::SampleCnt: |
| 536 | rasterizer.ResetCounter(QueryType::SamplesPassed); | 541 | rasterizer->ResetCounter(QueryType::SamplesPassed); |
| 537 | break; | 542 | break; |
| 538 | default: | 543 | default: |
| 539 | LOG_DEBUG(Render_OpenGL, "Unimplemented counter reset={}", | 544 | LOG_DEBUG(Render_OpenGL, "Unimplemented counter reset={}", |
| @@ -547,7 +552,7 @@ void Maxwell3D::ProcessSyncPoint() { | |||
| 547 | const u32 increment = regs.sync_info.increment.Value(); | 552 | const u32 increment = regs.sync_info.increment.Value(); |
| 548 | [[maybe_unused]] const u32 cache_flush = regs.sync_info.unknown.Value(); | 553 | [[maybe_unused]] const u32 cache_flush = regs.sync_info.unknown.Value(); |
| 549 | if (increment) { | 554 | if (increment) { |
| 550 | rasterizer.SignalSyncPoint(sync_point); | 555 | rasterizer->SignalSyncPoint(sync_point); |
| 551 | } | 556 | } |
| 552 | } | 557 | } |
| 553 | 558 | ||
| @@ -570,7 +575,7 @@ void Maxwell3D::DrawArrays() { | |||
| 570 | 575 | ||
| 571 | const bool is_indexed{regs.index_array.count && !regs.vertex_buffer.count}; | 576 | const bool is_indexed{regs.index_array.count && !regs.vertex_buffer.count}; |
| 572 | if (ShouldExecute()) { | 577 | if (ShouldExecute()) { |
| 573 | rasterizer.Draw(is_indexed, false); | 578 | rasterizer->Draw(is_indexed, false); |
| 574 | } | 579 | } |
| 575 | 580 | ||
| 576 | // TODO(bunnei): Below, we reset vertex count so that we can use these registers to determine if | 581 | // TODO(bunnei): Below, we reset vertex count so that we can use these registers to determine if |
| @@ -590,8 +595,8 @@ std::optional<u64> Maxwell3D::GetQueryResult() { | |||
| 590 | return 0; | 595 | return 0; |
| 591 | case Regs::QuerySelect::SamplesPassed: | 596 | case Regs::QuerySelect::SamplesPassed: |
| 592 | // Deferred. | 597 | // Deferred. |
| 593 | rasterizer.Query(regs.query.QueryAddress(), VideoCore::QueryType::SamplesPassed, | 598 | rasterizer->Query(regs.query.QueryAddress(), VideoCore::QueryType::SamplesPassed, |
| 594 | system.GPU().GetTicks()); | 599 | system.GPU().GetTicks()); |
| 595 | return {}; | 600 | return {}; |
| 596 | default: | 601 | default: |
| 597 | LOG_DEBUG(HW_GPU, "Unimplemented query select type {}", | 602 | LOG_DEBUG(HW_GPU, "Unimplemented query select type {}", |
| @@ -718,7 +723,7 @@ void Maxwell3D::ProcessClearBuffers() { | |||
| 718 | regs.clear_buffers.R == regs.clear_buffers.B && | 723 | regs.clear_buffers.R == regs.clear_buffers.B && |
| 719 | regs.clear_buffers.R == regs.clear_buffers.A); | 724 | regs.clear_buffers.R == regs.clear_buffers.A); |
| 720 | 725 | ||
| 721 | rasterizer.Clear(); | 726 | rasterizer->Clear(); |
| 722 | } | 727 | } |
| 723 | 728 | ||
| 724 | u32 Maxwell3D::AccessConstBuffer32(ShaderType stage, u64 const_buffer, u64 offset) const { | 729 | u32 Maxwell3D::AccessConstBuffer32(ShaderType stage, u64 const_buffer, u64 offset) const { |
| @@ -752,11 +757,11 @@ SamplerDescriptor Maxwell3D::AccessSampler(u32 handle) const { | |||
| 752 | } | 757 | } |
| 753 | 758 | ||
| 754 | VideoCore::GuestDriverProfile& Maxwell3D::AccessGuestDriverProfile() { | 759 | VideoCore::GuestDriverProfile& Maxwell3D::AccessGuestDriverProfile() { |
| 755 | return rasterizer.AccessGuestDriverProfile(); | 760 | return rasterizer->AccessGuestDriverProfile(); |
| 756 | } | 761 | } |
| 757 | 762 | ||
| 758 | const VideoCore::GuestDriverProfile& Maxwell3D::AccessGuestDriverProfile() const { | 763 | const VideoCore::GuestDriverProfile& Maxwell3D::AccessGuestDriverProfile() const { |
| 759 | return rasterizer.AccessGuestDriverProfile(); | 764 | return rasterizer->AccessGuestDriverProfile(); |
| 760 | } | 765 | } |
| 761 | 766 | ||
| 762 | } // namespace Tegra::Engines | 767 | } // namespace Tegra::Engines |
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index ef1618990..bc289c55d 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h | |||
| @@ -51,9 +51,11 @@ namespace Tegra::Engines { | |||
| 51 | 51 | ||
| 52 | class Maxwell3D final : public ConstBufferEngineInterface, public EngineInterface { | 52 | class Maxwell3D final : public ConstBufferEngineInterface, public EngineInterface { |
| 53 | public: | 53 | public: |
| 54 | explicit Maxwell3D(Core::System& system, VideoCore::RasterizerInterface& rasterizer, | 54 | explicit Maxwell3D(Core::System& system, MemoryManager& memory_manager); |
| 55 | MemoryManager& memory_manager); | 55 | ~Maxwell3D(); |
| 56 | ~Maxwell3D() = default; | 56 | |
| 57 | /// Binds a rasterizer to this engine. | ||
| 58 | void BindRasterizer(VideoCore::RasterizerInterface& rasterizer); | ||
| 57 | 59 | ||
| 58 | /// Register structure of the Maxwell3D engine. | 60 | /// Register structure of the Maxwell3D engine. |
| 59 | /// TODO(Subv): This structure will need to be made bigger as more registers are discovered. | 61 | /// TODO(Subv): This structure will need to be made bigger as more registers are discovered. |
| @@ -647,7 +649,7 @@ public: | |||
| 647 | GetX() + GetWidth(), // right | 649 | GetX() + GetWidth(), // right |
| 648 | GetY() // bottom | 650 | GetY() // bottom |
| 649 | }; | 651 | }; |
| 650 | }; | 652 | } |
| 651 | 653 | ||
| 652 | f32 GetX() const { | 654 | f32 GetX() const { |
| 653 | return std::max(0.0f, translate_x - std::fabs(scale_x)); | 655 | return std::max(0.0f, translate_x - std::fabs(scale_x)); |
| @@ -1418,12 +1420,12 @@ public: | |||
| 1418 | return execute_on; | 1420 | return execute_on; |
| 1419 | } | 1421 | } |
| 1420 | 1422 | ||
| 1421 | VideoCore::RasterizerInterface& GetRasterizer() { | 1423 | VideoCore::RasterizerInterface& Rasterizer() { |
| 1422 | return rasterizer; | 1424 | return *rasterizer; |
| 1423 | } | 1425 | } |
| 1424 | 1426 | ||
| 1425 | const VideoCore::RasterizerInterface& GetRasterizer() const { | 1427 | const VideoCore::RasterizerInterface& Rasterizer() const { |
| 1426 | return rasterizer; | 1428 | return *rasterizer; |
| 1427 | } | 1429 | } |
| 1428 | 1430 | ||
| 1429 | /// Notify a memory write has happened. | 1431 | /// Notify a memory write has happened. |
| @@ -1460,11 +1462,10 @@ private: | |||
| 1460 | void InitializeRegisterDefaults(); | 1462 | void InitializeRegisterDefaults(); |
| 1461 | 1463 | ||
| 1462 | Core::System& system; | 1464 | Core::System& system; |
| 1463 | |||
| 1464 | VideoCore::RasterizerInterface& rasterizer; | ||
| 1465 | |||
| 1466 | MemoryManager& memory_manager; | 1465 | MemoryManager& memory_manager; |
| 1467 | 1466 | ||
| 1467 | VideoCore::RasterizerInterface* rasterizer = nullptr; | ||
| 1468 | |||
| 1468 | /// Start offsets of each macro in macro_memory | 1469 | /// Start offsets of each macro in macro_memory |
| 1469 | std::array<u32, 0x80> macro_positions = {}; | 1470 | std::array<u32, 0x80> macro_positions = {}; |
| 1470 | 1471 | ||
diff --git a/src/video_core/engines/maxwell_dma.cpp b/src/video_core/engines/maxwell_dma.cpp index a2d3d7823..e88290754 100644 --- a/src/video_core/engines/maxwell_dma.cpp +++ b/src/video_core/engines/maxwell_dma.cpp | |||
| @@ -94,7 +94,8 @@ void MaxwellDMA::CopyPitchToPitch() { | |||
| 94 | } | 94 | } |
| 95 | 95 | ||
| 96 | void MaxwellDMA::CopyBlockLinearToPitch() { | 96 | void MaxwellDMA::CopyBlockLinearToPitch() { |
| 97 | ASSERT(regs.src_params.block_size.depth == 0); | 97 | UNIMPLEMENTED_IF(regs.src_params.block_size.depth != 0); |
| 98 | UNIMPLEMENTED_IF(regs.src_params.layer != 0); | ||
| 98 | 99 | ||
| 99 | // Optimized path for micro copies. | 100 | // Optimized path for micro copies. |
| 100 | const size_t dst_size = static_cast<size_t>(regs.pitch_out) * regs.line_count; | 101 | const size_t dst_size = static_cast<size_t>(regs.pitch_out) * regs.line_count; |
| @@ -123,17 +124,12 @@ void MaxwellDMA::CopyBlockLinearToPitch() { | |||
| 123 | write_buffer.resize(dst_size); | 124 | write_buffer.resize(dst_size); |
| 124 | } | 125 | } |
| 125 | 126 | ||
| 126 | if (Settings::IsGPULevelExtreme()) { | 127 | memory_manager.ReadBlock(regs.offset_in, read_buffer.data(), src_size); |
| 127 | memory_manager.ReadBlock(regs.offset_in, read_buffer.data(), src_size); | 128 | memory_manager.ReadBlock(regs.offset_out, write_buffer.data(), dst_size); |
| 128 | memory_manager.ReadBlock(regs.offset_out, write_buffer.data(), dst_size); | ||
| 129 | } else { | ||
| 130 | memory_manager.ReadBlockUnsafe(regs.offset_in, read_buffer.data(), src_size); | ||
| 131 | memory_manager.ReadBlockUnsafe(regs.offset_out, write_buffer.data(), dst_size); | ||
| 132 | } | ||
| 133 | 129 | ||
| 134 | UnswizzleSubrect(regs.line_length_in, regs.line_count, regs.pitch_out, width, bytes_per_pixel, | 130 | UnswizzleSubrect(regs.line_length_in, regs.line_count, regs.pitch_out, width, bytes_per_pixel, |
| 135 | read_buffer.data() + src_layer_size * src_params.layer, write_buffer.data(), | 131 | block_height, src_params.origin.x, src_params.origin.y, write_buffer.data(), |
| 136 | block_height, src_params.origin.x, src_params.origin.y); | 132 | read_buffer.data()); |
| 137 | 133 | ||
| 138 | memory_manager.WriteBlock(regs.offset_out, write_buffer.data(), dst_size); | 134 | memory_manager.WriteBlock(regs.offset_out, write_buffer.data(), dst_size); |
| 139 | } | 135 | } |
| @@ -198,7 +194,6 @@ void MaxwellDMA::FastCopyBlockLinearToPitch() { | |||
| 198 | if (read_buffer.size() < src_size) { | 194 | if (read_buffer.size() < src_size) { |
| 199 | read_buffer.resize(src_size); | 195 | read_buffer.resize(src_size); |
| 200 | } | 196 | } |
| 201 | |||
| 202 | if (write_buffer.size() < dst_size) { | 197 | if (write_buffer.size() < dst_size) { |
| 203 | write_buffer.resize(dst_size); | 198 | write_buffer.resize(dst_size); |
| 204 | } | 199 | } |
| @@ -212,8 +207,8 @@ void MaxwellDMA::FastCopyBlockLinearToPitch() { | |||
| 212 | } | 207 | } |
| 213 | 208 | ||
| 214 | UnswizzleSubrect(regs.line_length_in, regs.line_count, regs.pitch_out, regs.src_params.width, | 209 | UnswizzleSubrect(regs.line_length_in, regs.line_count, regs.pitch_out, regs.src_params.width, |
| 215 | bytes_per_pixel, read_buffer.data(), write_buffer.data(), | 210 | bytes_per_pixel, regs.src_params.block_size.height, pos_x, pos_y, |
| 216 | regs.src_params.block_size.height, pos_x, pos_y); | 211 | write_buffer.data(), read_buffer.data()); |
| 217 | 212 | ||
| 218 | memory_manager.WriteBlock(regs.offset_out, write_buffer.data(), dst_size); | 213 | memory_manager.WriteBlock(regs.offset_out, write_buffer.data(), dst_size); |
| 219 | } | 214 | } |
diff --git a/src/video_core/fence_manager.h b/src/video_core/fence_manager.h index 8b2a6a42c..06cc12d5a 100644 --- a/src/video_core/fence_manager.h +++ b/src/video_core/fence_manager.h | |||
| @@ -5,15 +5,10 @@ | |||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <algorithm> | 7 | #include <algorithm> |
| 8 | #include <array> | ||
| 9 | #include <memory> | ||
| 10 | #include <queue> | 8 | #include <queue> |
| 11 | 9 | ||
| 12 | #include "common/assert.h" | ||
| 13 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 14 | #include "core/core.h" | 11 | #include "core/core.h" |
| 15 | #include "core/memory.h" | ||
| 16 | #include "core/settings.h" | ||
| 17 | #include "video_core/gpu.h" | 12 | #include "video_core/gpu.h" |
| 18 | #include "video_core/memory_manager.h" | 13 | #include "video_core/memory_manager.h" |
| 19 | #include "video_core/rasterizer_interface.h" | 14 | #include "video_core/rasterizer_interface.h" |
diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index 512578c8b..acb6e6d46 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp | |||
| @@ -27,21 +27,28 @@ namespace Tegra { | |||
| 27 | 27 | ||
| 28 | MICROPROFILE_DEFINE(GPU_wait, "GPU", "Wait for the GPU", MP_RGB(128, 128, 192)); | 28 | MICROPROFILE_DEFINE(GPU_wait, "GPU", "Wait for the GPU", MP_RGB(128, 128, 192)); |
| 29 | 29 | ||
| 30 | GPU::GPU(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer_, bool is_async) | 30 | GPU::GPU(Core::System& system_, bool is_async_) |
| 31 | : system{system}, renderer{std::move(renderer_)}, is_async{is_async} { | 31 | : system{system_}, dma_pusher{std::make_unique<Tegra::DmaPusher>(system, *this)}, |
| 32 | auto& rasterizer{renderer->Rasterizer()}; | 32 | memory_manager{std::make_unique<Tegra::MemoryManager>(system)}, |
| 33 | memory_manager = std::make_unique<Tegra::MemoryManager>(system, rasterizer); | 33 | maxwell_3d{std::make_unique<Engines::Maxwell3D>(system, *memory_manager)}, |
| 34 | dma_pusher = std::make_unique<Tegra::DmaPusher>(system, *this); | 34 | fermi_2d{std::make_unique<Engines::Fermi2D>()}, |
| 35 | maxwell_3d = std::make_unique<Engines::Maxwell3D>(system, rasterizer, *memory_manager); | 35 | kepler_compute{std::make_unique<Engines::KeplerCompute>(system, *memory_manager)}, |
| 36 | fermi_2d = std::make_unique<Engines::Fermi2D>(rasterizer); | 36 | maxwell_dma{std::make_unique<Engines::MaxwellDMA>(system, *memory_manager)}, |
| 37 | kepler_compute = std::make_unique<Engines::KeplerCompute>(system, rasterizer, *memory_manager); | 37 | kepler_memory{std::make_unique<Engines::KeplerMemory>(system, *memory_manager)}, |
| 38 | maxwell_dma = std::make_unique<Engines::MaxwellDMA>(system, *memory_manager); | 38 | shader_notify{std::make_unique<VideoCore::ShaderNotify>()}, is_async{is_async_} {} |
| 39 | kepler_memory = std::make_unique<Engines::KeplerMemory>(system, *memory_manager); | ||
| 40 | shader_notify = std::make_unique<VideoCore::ShaderNotify>(); | ||
| 41 | } | ||
| 42 | 39 | ||
| 43 | GPU::~GPU() = default; | 40 | GPU::~GPU() = default; |
| 44 | 41 | ||
| 42 | void GPU::BindRenderer(std::unique_ptr<VideoCore::RendererBase> renderer_) { | ||
| 43 | renderer = std::move(renderer_); | ||
| 44 | |||
| 45 | VideoCore::RasterizerInterface& rasterizer = renderer->Rasterizer(); | ||
| 46 | memory_manager->BindRasterizer(rasterizer); | ||
| 47 | maxwell_3d->BindRasterizer(rasterizer); | ||
| 48 | fermi_2d->BindRasterizer(rasterizer); | ||
| 49 | kepler_compute->BindRasterizer(rasterizer); | ||
| 50 | } | ||
| 51 | |||
| 45 | Engines::Maxwell3D& GPU::Maxwell3D() { | 52 | Engines::Maxwell3D& GPU::Maxwell3D() { |
| 46 | return *maxwell_3d; | 53 | return *maxwell_3d; |
| 47 | } | 54 | } |
diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h index ebfc7b0c7..c7d11deb2 100644 --- a/src/video_core/gpu.h +++ b/src/video_core/gpu.h | |||
| @@ -142,11 +142,6 @@ class MemoryManager; | |||
| 142 | 142 | ||
| 143 | class GPU { | 143 | class GPU { |
| 144 | public: | 144 | public: |
| 145 | explicit GPU(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer, | ||
| 146 | bool is_async); | ||
| 147 | |||
| 148 | virtual ~GPU(); | ||
| 149 | |||
| 150 | struct MethodCall { | 145 | struct MethodCall { |
| 151 | u32 method{}; | 146 | u32 method{}; |
| 152 | u32 argument{}; | 147 | u32 argument{}; |
| @@ -162,6 +157,12 @@ public: | |||
| 162 | method_count(method_count) {} | 157 | method_count(method_count) {} |
| 163 | }; | 158 | }; |
| 164 | 159 | ||
| 160 | explicit GPU(Core::System& system, bool is_async); | ||
| 161 | virtual ~GPU(); | ||
| 162 | |||
| 163 | /// Binds a renderer to the GPU. | ||
| 164 | void BindRenderer(std::unique_ptr<VideoCore::RendererBase> renderer); | ||
| 165 | |||
| 165 | /// Calls a GPU method. | 166 | /// Calls a GPU method. |
| 166 | void CallMethod(const MethodCall& method_call); | 167 | void CallMethod(const MethodCall& method_call); |
| 167 | 168 | ||
| @@ -345,8 +346,8 @@ private: | |||
| 345 | bool ExecuteMethodOnEngine(u32 method); | 346 | bool ExecuteMethodOnEngine(u32 method); |
| 346 | 347 | ||
| 347 | protected: | 348 | protected: |
| 348 | std::unique_ptr<Tegra::DmaPusher> dma_pusher; | ||
| 349 | Core::System& system; | 349 | Core::System& system; |
| 350 | std::unique_ptr<Tegra::DmaPusher> dma_pusher; | ||
| 350 | std::unique_ptr<VideoCore::RendererBase> renderer; | 351 | std::unique_ptr<VideoCore::RendererBase> renderer; |
| 351 | 352 | ||
| 352 | private: | 353 | private: |
diff --git a/src/video_core/gpu_asynch.cpp b/src/video_core/gpu_asynch.cpp index 7b855f63e..70a3d5738 100644 --- a/src/video_core/gpu_asynch.cpp +++ b/src/video_core/gpu_asynch.cpp | |||
| @@ -10,16 +10,14 @@ | |||
| 10 | 10 | ||
| 11 | namespace VideoCommon { | 11 | namespace VideoCommon { |
| 12 | 12 | ||
| 13 | GPUAsynch::GPUAsynch(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer_, | 13 | GPUAsynch::GPUAsynch(Core::System& system) : GPU{system, true}, gpu_thread{system} {} |
| 14 | std::unique_ptr<Core::Frontend::GraphicsContext>&& context) | ||
| 15 | : GPU(system, std::move(renderer_), true), gpu_thread{system}, | ||
| 16 | cpu_context(renderer->GetRenderWindow().CreateSharedContext()), | ||
| 17 | gpu_context(std::move(context)) {} | ||
| 18 | 14 | ||
| 19 | GPUAsynch::~GPUAsynch() = default; | 15 | GPUAsynch::~GPUAsynch() = default; |
| 20 | 16 | ||
| 21 | void GPUAsynch::Start() { | 17 | void GPUAsynch::Start() { |
| 22 | gpu_thread.StartThread(*renderer, *gpu_context, *dma_pusher); | 18 | gpu_thread.StartThread(*renderer, renderer->Context(), *dma_pusher); |
| 19 | cpu_context = renderer->GetRenderWindow().CreateSharedContext(); | ||
| 20 | cpu_context->MakeCurrent(); | ||
| 23 | } | 21 | } |
| 24 | 22 | ||
| 25 | void GPUAsynch::ObtainContext() { | 23 | void GPUAsynch::ObtainContext() { |
diff --git a/src/video_core/gpu_asynch.h b/src/video_core/gpu_asynch.h index 15e9f1d38..f89c855a5 100644 --- a/src/video_core/gpu_asynch.h +++ b/src/video_core/gpu_asynch.h | |||
| @@ -20,8 +20,7 @@ namespace VideoCommon { | |||
| 20 | /// Implementation of GPU interface that runs the GPU asynchronously | 20 | /// Implementation of GPU interface that runs the GPU asynchronously |
| 21 | class GPUAsynch final : public Tegra::GPU { | 21 | class GPUAsynch final : public Tegra::GPU { |
| 22 | public: | 22 | public: |
| 23 | explicit GPUAsynch(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer, | 23 | explicit GPUAsynch(Core::System& system); |
| 24 | std::unique_ptr<Core::Frontend::GraphicsContext>&& context); | ||
| 25 | ~GPUAsynch() override; | 24 | ~GPUAsynch() override; |
| 26 | 25 | ||
| 27 | void Start() override; | 26 | void Start() override; |
| @@ -42,7 +41,6 @@ protected: | |||
| 42 | private: | 41 | private: |
| 43 | GPUThread::ThreadManager gpu_thread; | 42 | GPUThread::ThreadManager gpu_thread; |
| 44 | std::unique_ptr<Core::Frontend::GraphicsContext> cpu_context; | 43 | std::unique_ptr<Core::Frontend::GraphicsContext> cpu_context; |
| 45 | std::unique_ptr<Core::Frontend::GraphicsContext> gpu_context; | ||
| 46 | }; | 44 | }; |
| 47 | 45 | ||
| 48 | } // namespace VideoCommon | 46 | } // namespace VideoCommon |
diff --git a/src/video_core/gpu_synch.cpp b/src/video_core/gpu_synch.cpp index aaeb9811d..1ca47ddef 100644 --- a/src/video_core/gpu_synch.cpp +++ b/src/video_core/gpu_synch.cpp | |||
| @@ -7,20 +7,18 @@ | |||
| 7 | 7 | ||
| 8 | namespace VideoCommon { | 8 | namespace VideoCommon { |
| 9 | 9 | ||
| 10 | GPUSynch::GPUSynch(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer, | 10 | GPUSynch::GPUSynch(Core::System& system) : GPU{system, false} {} |
| 11 | std::unique_ptr<Core::Frontend::GraphicsContext>&& context) | ||
| 12 | : GPU(system, std::move(renderer), false), context{std::move(context)} {} | ||
| 13 | 11 | ||
| 14 | GPUSynch::~GPUSynch() = default; | 12 | GPUSynch::~GPUSynch() = default; |
| 15 | 13 | ||
| 16 | void GPUSynch::Start() {} | 14 | void GPUSynch::Start() {} |
| 17 | 15 | ||
| 18 | void GPUSynch::ObtainContext() { | 16 | void GPUSynch::ObtainContext() { |
| 19 | context->MakeCurrent(); | 17 | renderer->Context().MakeCurrent(); |
| 20 | } | 18 | } |
| 21 | 19 | ||
| 22 | void GPUSynch::ReleaseContext() { | 20 | void GPUSynch::ReleaseContext() { |
| 23 | context->DoneCurrent(); | 21 | renderer->Context().DoneCurrent(); |
| 24 | } | 22 | } |
| 25 | 23 | ||
| 26 | void GPUSynch::PushGPUEntries(Tegra::CommandList&& entries) { | 24 | void GPUSynch::PushGPUEntries(Tegra::CommandList&& entries) { |
diff --git a/src/video_core/gpu_synch.h b/src/video_core/gpu_synch.h index 762c20aa5..297258cb1 100644 --- a/src/video_core/gpu_synch.h +++ b/src/video_core/gpu_synch.h | |||
| @@ -19,8 +19,7 @@ namespace VideoCommon { | |||
| 19 | /// Implementation of GPU interface that runs the GPU synchronously | 19 | /// Implementation of GPU interface that runs the GPU synchronously |
| 20 | class GPUSynch final : public Tegra::GPU { | 20 | class GPUSynch final : public Tegra::GPU { |
| 21 | public: | 21 | public: |
| 22 | explicit GPUSynch(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer, | 22 | explicit GPUSynch(Core::System& system); |
| 23 | std::unique_ptr<Core::Frontend::GraphicsContext>&& context); | ||
| 24 | ~GPUSynch() override; | 23 | ~GPUSynch() override; |
| 25 | 24 | ||
| 26 | void Start() override; | 25 | void Start() override; |
| @@ -36,9 +35,6 @@ public: | |||
| 36 | protected: | 35 | protected: |
| 37 | void TriggerCpuInterrupt([[maybe_unused]] u32 syncpoint_id, | 36 | void TriggerCpuInterrupt([[maybe_unused]] u32 syncpoint_id, |
| 38 | [[maybe_unused]] u32 value) const override {} | 37 | [[maybe_unused]] u32 value) const override {} |
| 39 | |||
| 40 | private: | ||
| 41 | std::unique_ptr<Core::Frontend::GraphicsContext> context; | ||
| 42 | }; | 38 | }; |
| 43 | 39 | ||
| 44 | } // namespace VideoCommon | 40 | } // namespace VideoCommon |
diff --git a/src/video_core/host_shaders/CMakeLists.txt b/src/video_core/host_shaders/CMakeLists.txt new file mode 100644 index 000000000..aa62363a7 --- /dev/null +++ b/src/video_core/host_shaders/CMakeLists.txt | |||
| @@ -0,0 +1,43 @@ | |||
| 1 | set(SHADER_FILES | ||
| 2 | opengl_present.frag | ||
| 3 | opengl_present.vert | ||
| 4 | ) | ||
| 5 | |||
| 6 | set(SHADER_INCLUDE ${CMAKE_CURRENT_BINARY_DIR}/include) | ||
| 7 | set(HOST_SHADERS_INCLUDE ${SHADER_INCLUDE} PARENT_SCOPE) | ||
| 8 | |||
| 9 | set(SHADER_DIR ${SHADER_INCLUDE}/video_core/host_shaders) | ||
| 10 | add_custom_command( | ||
| 11 | OUTPUT | ||
| 12 | ${SHADER_DIR} | ||
| 13 | COMMAND | ||
| 14 | ${CMAKE_COMMAND} -E make_directory ${SHADER_DIR} | ||
| 15 | ) | ||
| 16 | |||
| 17 | set(INPUT_FILE ${CMAKE_CURRENT_SOURCE_DIR}/source_shader.h.in) | ||
| 18 | set(HEADER_GENERATOR ${CMAKE_CURRENT_SOURCE_DIR}/StringShaderHeader.cmake) | ||
| 19 | |||
| 20 | foreach(FILENAME IN ITEMS ${SHADER_FILES}) | ||
| 21 | string(REPLACE "." "_" SHADER_NAME ${FILENAME}) | ||
| 22 | set(SOURCE_FILE ${CMAKE_CURRENT_SOURCE_DIR}/${FILENAME}) | ||
| 23 | set(HEADER_FILE ${SHADER_DIR}/${SHADER_NAME}.h) | ||
| 24 | add_custom_command( | ||
| 25 | OUTPUT | ||
| 26 | ${HEADER_FILE} | ||
| 27 | COMMAND | ||
| 28 | ${CMAKE_COMMAND} -P ${HEADER_GENERATOR} ${SOURCE_FILE} ${HEADER_FILE} ${INPUT_FILE} | ||
| 29 | MAIN_DEPENDENCY | ||
| 30 | ${SOURCE_FILE} | ||
| 31 | DEPENDS | ||
| 32 | ${HEADER_GENERATOR} | ||
| 33 | ${INPUT_FILE} | ||
| 34 | ) | ||
| 35 | set(SHADER_HEADERS ${SHADER_HEADERS} ${HEADER_FILE}) | ||
| 36 | endforeach() | ||
| 37 | |||
| 38 | add_custom_target(host_shaders | ||
| 39 | DEPENDS | ||
| 40 | ${SHADER_HEADERS} | ||
| 41 | SOURCES | ||
| 42 | ${SHADER_FILES} | ||
| 43 | ) | ||
diff --git a/src/video_core/host_shaders/StringShaderHeader.cmake b/src/video_core/host_shaders/StringShaderHeader.cmake new file mode 100644 index 000000000..368bce0ed --- /dev/null +++ b/src/video_core/host_shaders/StringShaderHeader.cmake | |||
| @@ -0,0 +1,11 @@ | |||
| 1 | set(SOURCE_FILE ${CMAKE_ARGV3}) | ||
| 2 | set(HEADER_FILE ${CMAKE_ARGV4}) | ||
| 3 | set(INPUT_FILE ${CMAKE_ARGV5}) | ||
| 4 | |||
| 5 | get_filename_component(CONTENTS_NAME ${SOURCE_FILE} NAME) | ||
| 6 | string(REPLACE "." "_" CONTENTS_NAME ${CONTENTS_NAME}) | ||
| 7 | string(TOUPPER ${CONTENTS_NAME} CONTENTS_NAME) | ||
| 8 | |||
| 9 | file(READ ${SOURCE_FILE} CONTENTS) | ||
| 10 | |||
| 11 | configure_file(${INPUT_FILE} ${HEADER_FILE} @ONLY) | ||
diff --git a/src/video_core/host_shaders/opengl_present.frag b/src/video_core/host_shaders/opengl_present.frag new file mode 100644 index 000000000..8a4cb024b --- /dev/null +++ b/src/video_core/host_shaders/opengl_present.frag | |||
| @@ -0,0 +1,10 @@ | |||
| 1 | #version 430 core | ||
| 2 | |||
| 3 | layout (location = 0) in vec2 frag_tex_coord; | ||
| 4 | layout (location = 0) out vec4 color; | ||
| 5 | |||
| 6 | layout (binding = 0) uniform sampler2D color_texture; | ||
| 7 | |||
| 8 | void main() { | ||
| 9 | color = vec4(texture(color_texture, frag_tex_coord).rgb, 1.0f); | ||
| 10 | } | ||
diff --git a/src/video_core/host_shaders/opengl_present.vert b/src/video_core/host_shaders/opengl_present.vert new file mode 100644 index 000000000..2235d31a4 --- /dev/null +++ b/src/video_core/host_shaders/opengl_present.vert | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | #version 430 core | ||
| 2 | |||
| 3 | out gl_PerVertex { | ||
| 4 | vec4 gl_Position; | ||
| 5 | }; | ||
| 6 | |||
| 7 | layout (location = 0) in vec2 vert_position; | ||
| 8 | layout (location = 1) in vec2 vert_tex_coord; | ||
| 9 | layout (location = 0) out vec2 frag_tex_coord; | ||
| 10 | |||
| 11 | // This is a truncated 3x3 matrix for 2D transformations: | ||
| 12 | // The upper-left 2x2 submatrix performs scaling/rotation/mirroring. | ||
| 13 | // The third column performs translation. | ||
| 14 | // The third row could be used for projection, which we don't need in 2D. It hence is assumed to | ||
| 15 | // implicitly be [0, 0, 1] | ||
| 16 | layout (location = 0) uniform mat3x2 modelview_matrix; | ||
| 17 | |||
| 18 | void main() { | ||
| 19 | // Multiply input position by the rotscale part of the matrix and then manually translate by | ||
| 20 | // the last column. This is equivalent to using a full 3x3 matrix and expanding the vector | ||
| 21 | // to `vec3(vert_position.xy, 1.0)` | ||
| 22 | gl_Position = vec4(mat2(modelview_matrix) * vert_position + modelview_matrix[2], 0.0, 1.0); | ||
| 23 | frag_tex_coord = vert_tex_coord; | ||
| 24 | } | ||
diff --git a/src/video_core/host_shaders/source_shader.h.in b/src/video_core/host_shaders/source_shader.h.in new file mode 100644 index 000000000..ccdb0d2a9 --- /dev/null +++ b/src/video_core/host_shaders/source_shader.h.in | |||
| @@ -0,0 +1,9 @@ | |||
| 1 | #pragma once | ||
| 2 | |||
| 3 | #include <string_view> | ||
| 4 | |||
| 5 | namespace HostShaders { | ||
| 6 | |||
| 7 | constexpr std::string_view @CONTENTS_NAME@ = R"(@CONTENTS@)"; | ||
| 8 | |||
| 9 | } // namespace HostShaders | ||
diff --git a/src/video_core/macro/macro_hle.cpp b/src/video_core/macro/macro_hle.cpp index 0c9ff59a4..df00b57df 100644 --- a/src/video_core/macro/macro_hle.cpp +++ b/src/video_core/macro/macro_hle.cpp | |||
| @@ -24,7 +24,7 @@ void HLE_771BB18C62444DA0(Engines::Maxwell3D& maxwell3d, const std::vector<u32>& | |||
| 24 | maxwell3d.regs.index_array.first = parameters[4]; | 24 | maxwell3d.regs.index_array.first = parameters[4]; |
| 25 | 25 | ||
| 26 | if (maxwell3d.ShouldExecute()) { | 26 | if (maxwell3d.ShouldExecute()) { |
| 27 | maxwell3d.GetRasterizer().Draw(true, true); | 27 | maxwell3d.Rasterizer().Draw(true, true); |
| 28 | } | 28 | } |
| 29 | maxwell3d.regs.index_array.count = 0; | 29 | maxwell3d.regs.index_array.count = 0; |
| 30 | maxwell3d.mme_draw.instance_count = 0; | 30 | maxwell3d.mme_draw.instance_count = 0; |
| @@ -42,7 +42,7 @@ void HLE_0D61FC9FAAC9FCAD(Engines::Maxwell3D& maxwell3d, const std::vector<u32>& | |||
| 42 | maxwell3d.mme_draw.instance_count = count; | 42 | maxwell3d.mme_draw.instance_count = count; |
| 43 | 43 | ||
| 44 | if (maxwell3d.ShouldExecute()) { | 44 | if (maxwell3d.ShouldExecute()) { |
| 45 | maxwell3d.GetRasterizer().Draw(false, true); | 45 | maxwell3d.Rasterizer().Draw(false, true); |
| 46 | } | 46 | } |
| 47 | maxwell3d.regs.vertex_buffer.count = 0; | 47 | maxwell3d.regs.vertex_buffer.count = 0; |
| 48 | maxwell3d.mme_draw.instance_count = 0; | 48 | maxwell3d.mme_draw.instance_count = 0; |
| @@ -65,7 +65,7 @@ void HLE_0217920100488FF7(Engines::Maxwell3D& maxwell3d, const std::vector<u32>& | |||
| 65 | maxwell3d.regs.draw.topology.Assign( | 65 | maxwell3d.regs.draw.topology.Assign( |
| 66 | static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[0])); | 66 | static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[0])); |
| 67 | if (maxwell3d.ShouldExecute()) { | 67 | if (maxwell3d.ShouldExecute()) { |
| 68 | maxwell3d.GetRasterizer().Draw(true, true); | 68 | maxwell3d.Rasterizer().Draw(true, true); |
| 69 | } | 69 | } |
| 70 | maxwell3d.regs.reg_array[0x446] = 0x0; // vertex id base? | 70 | maxwell3d.regs.reg_array[0x446] = 0x0; // vertex id base? |
| 71 | maxwell3d.regs.index_array.count = 0; | 71 | maxwell3d.regs.index_array.count = 0; |
diff --git a/src/video_core/macro/macro_interpreter.cpp b/src/video_core/macro/macro_interpreter.cpp index aa5256419..bd01fd1f2 100644 --- a/src/video_core/macro/macro_interpreter.cpp +++ b/src/video_core/macro/macro_interpreter.cpp | |||
| @@ -34,7 +34,6 @@ void MacroInterpreterImpl::Execute(const std::vector<u32>& parameters, u32 metho | |||
| 34 | this->parameters = std::make_unique<u32[]>(num_parameters); | 34 | this->parameters = std::make_unique<u32[]>(num_parameters); |
| 35 | } | 35 | } |
| 36 | std::memcpy(this->parameters.get(), parameters.data(), num_parameters * sizeof(u32)); | 36 | std::memcpy(this->parameters.get(), parameters.data(), num_parameters * sizeof(u32)); |
| 37 | this->num_parameters = num_parameters; | ||
| 38 | 37 | ||
| 39 | // Execute the code until we hit an exit condition. | 38 | // Execute the code until we hit an exit condition. |
| 40 | bool keep_executing = true; | 39 | bool keep_executing = true; |
diff --git a/src/video_core/memory_manager.cpp b/src/video_core/memory_manager.cpp index 844164645..16b2aaa27 100644 --- a/src/video_core/memory_manager.cpp +++ b/src/video_core/memory_manager.cpp | |||
| @@ -14,11 +14,15 @@ | |||
| 14 | 14 | ||
| 15 | namespace Tegra { | 15 | namespace Tegra { |
| 16 | 16 | ||
| 17 | MemoryManager::MemoryManager(Core::System& system, VideoCore::RasterizerInterface& rasterizer) | 17 | MemoryManager::MemoryManager(Core::System& system_) |
| 18 | : system{system}, rasterizer{rasterizer}, page_table(page_table_size) {} | 18 | : system{system_}, page_table(page_table_size) {} |
| 19 | 19 | ||
| 20 | MemoryManager::~MemoryManager() = default; | 20 | MemoryManager::~MemoryManager() = default; |
| 21 | 21 | ||
| 22 | void MemoryManager::BindRasterizer(VideoCore::RasterizerInterface& rasterizer_) { | ||
| 23 | rasterizer = &rasterizer_; | ||
| 24 | } | ||
| 25 | |||
| 22 | GPUVAddr MemoryManager::UpdateRange(GPUVAddr gpu_addr, PageEntry page_entry, std::size_t size) { | 26 | GPUVAddr MemoryManager::UpdateRange(GPUVAddr gpu_addr, PageEntry page_entry, std::size_t size) { |
| 23 | u64 remaining_size{size}; | 27 | u64 remaining_size{size}; |
| 24 | for (u64 offset{}; offset < size; offset += page_size) { | 28 | for (u64 offset{}; offset < size; offset += page_size) { |
| @@ -217,7 +221,7 @@ void MemoryManager::ReadBlock(GPUVAddr gpu_src_addr, void* dest_buffer, std::siz | |||
| 217 | 221 | ||
| 218 | // Flush must happen on the rasterizer interface, such that memory is always synchronous | 222 | // Flush must happen on the rasterizer interface, such that memory is always synchronous |
| 219 | // when it is read (even when in asynchronous GPU mode). Fixes Dead Cells title menu. | 223 | // when it is read (even when in asynchronous GPU mode). Fixes Dead Cells title menu. |
| 220 | rasterizer.FlushRegion(src_addr, copy_amount); | 224 | rasterizer->FlushRegion(src_addr, copy_amount); |
| 221 | system.Memory().ReadBlockUnsafe(src_addr, dest_buffer, copy_amount); | 225 | system.Memory().ReadBlockUnsafe(src_addr, dest_buffer, copy_amount); |
| 222 | } | 226 | } |
| 223 | 227 | ||
| @@ -266,7 +270,7 @@ void MemoryManager::WriteBlock(GPUVAddr gpu_dest_addr, const void* src_buffer, s | |||
| 266 | 270 | ||
| 267 | // Invalidate must happen on the rasterizer interface, such that memory is always | 271 | // Invalidate must happen on the rasterizer interface, such that memory is always |
| 268 | // synchronous when it is written (even when in asynchronous GPU mode). | 272 | // synchronous when it is written (even when in asynchronous GPU mode). |
| 269 | rasterizer.InvalidateRegion(dest_addr, copy_amount); | 273 | rasterizer->InvalidateRegion(dest_addr, copy_amount); |
| 270 | system.Memory().WriteBlockUnsafe(dest_addr, src_buffer, copy_amount); | 274 | system.Memory().WriteBlockUnsafe(dest_addr, src_buffer, copy_amount); |
| 271 | } | 275 | } |
| 272 | 276 | ||
| @@ -312,10 +316,10 @@ void MemoryManager::CopyBlockUnsafe(GPUVAddr gpu_dest_addr, GPUVAddr gpu_src_add | |||
| 312 | WriteBlockUnsafe(gpu_dest_addr, tmp_buffer.data(), size); | 316 | WriteBlockUnsafe(gpu_dest_addr, tmp_buffer.data(), size); |
| 313 | } | 317 | } |
| 314 | 318 | ||
| 315 | bool MemoryManager::IsGranularRange(GPUVAddr gpu_addr, std::size_t size) { | 319 | bool MemoryManager::IsGranularRange(GPUVAddr gpu_addr, std::size_t size) const { |
| 316 | const auto cpu_addr{GpuToCpuAddress(gpu_addr)}; | 320 | const auto cpu_addr{GpuToCpuAddress(gpu_addr)}; |
| 317 | if (!cpu_addr) { | 321 | if (!cpu_addr) { |
| 318 | return {}; | 322 | return false; |
| 319 | } | 323 | } |
| 320 | const std::size_t page{(*cpu_addr & Core::Memory::PAGE_MASK) + size}; | 324 | const std::size_t page{(*cpu_addr & Core::Memory::PAGE_MASK) + size}; |
| 321 | return page <= Core::Memory::PAGE_SIZE; | 325 | return page <= Core::Memory::PAGE_SIZE; |
diff --git a/src/video_core/memory_manager.h b/src/video_core/memory_manager.h index 681bd9588..53c8d122a 100644 --- a/src/video_core/memory_manager.h +++ b/src/video_core/memory_manager.h | |||
| @@ -31,19 +31,19 @@ public: | |||
| 31 | constexpr PageEntry(State state) : state{state} {} | 31 | constexpr PageEntry(State state) : state{state} {} |
| 32 | constexpr PageEntry(VAddr addr) : state{static_cast<State>(addr >> ShiftBits)} {} | 32 | constexpr PageEntry(VAddr addr) : state{static_cast<State>(addr >> ShiftBits)} {} |
| 33 | 33 | ||
| 34 | constexpr bool IsUnmapped() const { | 34 | [[nodiscard]] constexpr bool IsUnmapped() const { |
| 35 | return state == State::Unmapped; | 35 | return state == State::Unmapped; |
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | constexpr bool IsAllocated() const { | 38 | [[nodiscard]] constexpr bool IsAllocated() const { |
| 39 | return state == State::Allocated; | 39 | return state == State::Allocated; |
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | constexpr bool IsValid() const { | 42 | [[nodiscard]] constexpr bool IsValid() const { |
| 43 | return !IsUnmapped() && !IsAllocated(); | 43 | return !IsUnmapped() && !IsAllocated(); |
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | constexpr VAddr ToAddress() const { | 46 | [[nodiscard]] constexpr VAddr ToAddress() const { |
| 47 | if (!IsValid()) { | 47 | if (!IsValid()) { |
| 48 | return {}; | 48 | return {}; |
| 49 | } | 49 | } |
| @@ -51,7 +51,7 @@ public: | |||
| 51 | return static_cast<VAddr>(state) << ShiftBits; | 51 | return static_cast<VAddr>(state) << ShiftBits; |
| 52 | } | 52 | } |
| 53 | 53 | ||
| 54 | constexpr PageEntry operator+(u64 offset) { | 54 | [[nodiscard]] constexpr PageEntry operator+(u64 offset) const { |
| 55 | // If this is a reserved value, offsets do not apply | 55 | // If this is a reserved value, offsets do not apply |
| 56 | if (!IsValid()) { | 56 | if (!IsValid()) { |
| 57 | return *this; | 57 | return *this; |
| @@ -68,19 +68,22 @@ static_assert(sizeof(PageEntry) == 4, "PageEntry is too large"); | |||
| 68 | 68 | ||
| 69 | class MemoryManager final { | 69 | class MemoryManager final { |
| 70 | public: | 70 | public: |
| 71 | explicit MemoryManager(Core::System& system, VideoCore::RasterizerInterface& rasterizer); | 71 | explicit MemoryManager(Core::System& system); |
| 72 | ~MemoryManager(); | 72 | ~MemoryManager(); |
| 73 | 73 | ||
| 74 | std::optional<VAddr> GpuToCpuAddress(GPUVAddr addr) const; | 74 | /// Binds a renderer to the memory manager. |
| 75 | void BindRasterizer(VideoCore::RasterizerInterface& rasterizer); | ||
| 76 | |||
| 77 | [[nodiscard]] std::optional<VAddr> GpuToCpuAddress(GPUVAddr addr) const; | ||
| 75 | 78 | ||
| 76 | template <typename T> | 79 | template <typename T> |
| 77 | T Read(GPUVAddr addr) const; | 80 | [[nodiscard]] T Read(GPUVAddr addr) const; |
| 78 | 81 | ||
| 79 | template <typename T> | 82 | template <typename T> |
| 80 | void Write(GPUVAddr addr, T data); | 83 | void Write(GPUVAddr addr, T data); |
| 81 | 84 | ||
| 82 | u8* GetPointer(GPUVAddr addr); | 85 | [[nodiscard]] u8* GetPointer(GPUVAddr addr); |
| 83 | const u8* GetPointer(GPUVAddr addr) const; | 86 | [[nodiscard]] const u8* GetPointer(GPUVAddr addr) const; |
| 84 | 87 | ||
| 85 | /** | 88 | /** |
| 86 | * ReadBlock and WriteBlock are full read and write operations over virtual | 89 | * ReadBlock and WriteBlock are full read and write operations over virtual |
| @@ -109,24 +112,24 @@ public: | |||
| 109 | /** | 112 | /** |
| 110 | * IsGranularRange checks if a gpu region can be simply read with a pointer. | 113 | * IsGranularRange checks if a gpu region can be simply read with a pointer. |
| 111 | */ | 114 | */ |
| 112 | bool IsGranularRange(GPUVAddr gpu_addr, std::size_t size); | 115 | [[nodiscard]] bool IsGranularRange(GPUVAddr gpu_addr, std::size_t size) const; |
| 113 | 116 | ||
| 114 | GPUVAddr Map(VAddr cpu_addr, GPUVAddr gpu_addr, std::size_t size); | 117 | [[nodiscard]] GPUVAddr Map(VAddr cpu_addr, GPUVAddr gpu_addr, std::size_t size); |
| 115 | GPUVAddr MapAllocate(VAddr cpu_addr, std::size_t size, std::size_t align); | 118 | [[nodiscard]] GPUVAddr MapAllocate(VAddr cpu_addr, std::size_t size, std::size_t align); |
| 116 | std::optional<GPUVAddr> AllocateFixed(GPUVAddr gpu_addr, std::size_t size); | 119 | [[nodiscard]] std::optional<GPUVAddr> AllocateFixed(GPUVAddr gpu_addr, std::size_t size); |
| 117 | GPUVAddr Allocate(std::size_t size, std::size_t align); | 120 | [[nodiscard]] GPUVAddr Allocate(std::size_t size, std::size_t align); |
| 118 | void Unmap(GPUVAddr gpu_addr, std::size_t size); | 121 | void Unmap(GPUVAddr gpu_addr, std::size_t size); |
| 119 | 122 | ||
| 120 | private: | 123 | private: |
| 121 | PageEntry GetPageEntry(GPUVAddr gpu_addr) const; | 124 | [[nodiscard]] PageEntry GetPageEntry(GPUVAddr gpu_addr) const; |
| 122 | void SetPageEntry(GPUVAddr gpu_addr, PageEntry page_entry, std::size_t size = page_size); | 125 | void SetPageEntry(GPUVAddr gpu_addr, PageEntry page_entry, std::size_t size = page_size); |
| 123 | GPUVAddr UpdateRange(GPUVAddr gpu_addr, PageEntry page_entry, std::size_t size); | 126 | GPUVAddr UpdateRange(GPUVAddr gpu_addr, PageEntry page_entry, std::size_t size); |
| 124 | std::optional<GPUVAddr> FindFreeRange(std::size_t size, std::size_t align) const; | 127 | [[nodiscard]] std::optional<GPUVAddr> FindFreeRange(std::size_t size, std::size_t align) const; |
| 125 | 128 | ||
| 126 | void TryLockPage(PageEntry page_entry, std::size_t size); | 129 | void TryLockPage(PageEntry page_entry, std::size_t size); |
| 127 | void TryUnlockPage(PageEntry page_entry, std::size_t size); | 130 | void TryUnlockPage(PageEntry page_entry, std::size_t size); |
| 128 | 131 | ||
| 129 | static constexpr std::size_t PageEntryIndex(GPUVAddr gpu_addr) { | 132 | [[nodiscard]] static constexpr std::size_t PageEntryIndex(GPUVAddr gpu_addr) { |
| 130 | return (gpu_addr >> page_bits) & page_table_mask; | 133 | return (gpu_addr >> page_bits) & page_table_mask; |
| 131 | } | 134 | } |
| 132 | 135 | ||
| @@ -141,7 +144,7 @@ private: | |||
| 141 | 144 | ||
| 142 | Core::System& system; | 145 | Core::System& system; |
| 143 | 146 | ||
| 144 | VideoCore::RasterizerInterface& rasterizer; | 147 | VideoCore::RasterizerInterface* rasterizer = nullptr; |
| 145 | 148 | ||
| 146 | std::vector<PageEntry> page_table; | 149 | std::vector<PageEntry> page_table; |
| 147 | }; | 150 | }; |
diff --git a/src/video_core/renderer_base.cpp b/src/video_core/renderer_base.cpp index dfb06e87e..a93a1732c 100644 --- a/src/video_core/renderer_base.cpp +++ b/src/video_core/renderer_base.cpp | |||
| @@ -9,7 +9,9 @@ | |||
| 9 | 9 | ||
| 10 | namespace VideoCore { | 10 | namespace VideoCore { |
| 11 | 11 | ||
| 12 | RendererBase::RendererBase(Core::Frontend::EmuWindow& window) : render_window{window} { | 12 | RendererBase::RendererBase(Core::Frontend::EmuWindow& window_, |
| 13 | std::unique_ptr<Core::Frontend::GraphicsContext> context_) | ||
| 14 | : render_window{window_}, context{std::move(context_)} { | ||
| 13 | RefreshBaseSettings(); | 15 | RefreshBaseSettings(); |
| 14 | } | 16 | } |
| 15 | 17 | ||
diff --git a/src/video_core/renderer_base.h b/src/video_core/renderer_base.h index 1d85219b6..649074acd 100644 --- a/src/video_core/renderer_base.h +++ b/src/video_core/renderer_base.h | |||
| @@ -15,7 +15,8 @@ | |||
| 15 | 15 | ||
| 16 | namespace Core::Frontend { | 16 | namespace Core::Frontend { |
| 17 | class EmuWindow; | 17 | class EmuWindow; |
| 18 | } | 18 | class GraphicsContext; |
| 19 | } // namespace Core::Frontend | ||
| 19 | 20 | ||
| 20 | namespace VideoCore { | 21 | namespace VideoCore { |
| 21 | 22 | ||
| @@ -25,14 +26,15 @@ struct RendererSettings { | |||
| 25 | 26 | ||
| 26 | // Screenshot | 27 | // Screenshot |
| 27 | std::atomic<bool> screenshot_requested{false}; | 28 | std::atomic<bool> screenshot_requested{false}; |
| 28 | void* screenshot_bits; | 29 | void* screenshot_bits{}; |
| 29 | std::function<void()> screenshot_complete_callback; | 30 | std::function<void()> screenshot_complete_callback; |
| 30 | Layout::FramebufferLayout screenshot_framebuffer_layout; | 31 | Layout::FramebufferLayout screenshot_framebuffer_layout; |
| 31 | }; | 32 | }; |
| 32 | 33 | ||
| 33 | class RendererBase : NonCopyable { | 34 | class RendererBase : NonCopyable { |
| 34 | public: | 35 | public: |
| 35 | explicit RendererBase(Core::Frontend::EmuWindow& window); | 36 | explicit RendererBase(Core::Frontend::EmuWindow& window, |
| 37 | std::unique_ptr<Core::Frontend::GraphicsContext> context); | ||
| 36 | virtual ~RendererBase(); | 38 | virtual ~RendererBase(); |
| 37 | 39 | ||
| 38 | /// Initialize the renderer | 40 | /// Initialize the renderer |
| @@ -68,6 +70,14 @@ public: | |||
| 68 | return *rasterizer; | 70 | return *rasterizer; |
| 69 | } | 71 | } |
| 70 | 72 | ||
| 73 | Core::Frontend::GraphicsContext& Context() { | ||
| 74 | return *context; | ||
| 75 | } | ||
| 76 | |||
| 77 | const Core::Frontend::GraphicsContext& Context() const { | ||
| 78 | return *context; | ||
| 79 | } | ||
| 80 | |||
| 71 | Core::Frontend::EmuWindow& GetRenderWindow() { | 81 | Core::Frontend::EmuWindow& GetRenderWindow() { |
| 72 | return render_window; | 82 | return render_window; |
| 73 | } | 83 | } |
| @@ -94,6 +104,7 @@ public: | |||
| 94 | protected: | 104 | protected: |
| 95 | Core::Frontend::EmuWindow& render_window; ///< Reference to the render window handle. | 105 | Core::Frontend::EmuWindow& render_window; ///< Reference to the render window handle. |
| 96 | std::unique_ptr<RasterizerInterface> rasterizer; | 106 | std::unique_ptr<RasterizerInterface> rasterizer; |
| 107 | std::unique_ptr<Core::Frontend::GraphicsContext> context; | ||
| 97 | f32 m_current_fps = 0.0f; ///< Current framerate, should be set by the renderer | 108 | f32 m_current_fps = 0.0f; ///< Current framerate, should be set by the renderer |
| 98 | int m_current_frame = 0; ///< Current frame, should be set by the renderer | 109 | int m_current_frame = 0; ///< Current frame, should be set by the renderer |
| 99 | 110 | ||
diff --git a/src/video_core/renderer_opengl/gl_fence_manager.cpp b/src/video_core/renderer_opengl/gl_fence_manager.cpp index ec5421afa..3d2588dd2 100644 --- a/src/video_core/renderer_opengl/gl_fence_manager.cpp +++ b/src/video_core/renderer_opengl/gl_fence_manager.cpp | |||
| @@ -4,16 +4,17 @@ | |||
| 4 | 4 | ||
| 5 | #include "common/assert.h" | 5 | #include "common/assert.h" |
| 6 | 6 | ||
| 7 | #include <glad/glad.h> | ||
| 8 | |||
| 7 | #include "video_core/renderer_opengl/gl_buffer_cache.h" | 9 | #include "video_core/renderer_opengl/gl_buffer_cache.h" |
| 8 | #include "video_core/renderer_opengl/gl_fence_manager.h" | 10 | #include "video_core/renderer_opengl/gl_fence_manager.h" |
| 9 | 11 | ||
| 10 | namespace OpenGL { | 12 | namespace OpenGL { |
| 11 | 13 | ||
| 12 | GLInnerFence::GLInnerFence(u32 payload, bool is_stubbed) | 14 | GLInnerFence::GLInnerFence(u32 payload, bool is_stubbed) : FenceBase(payload, is_stubbed) {} |
| 13 | : VideoCommon::FenceBase(payload, is_stubbed), sync_object{} {} | ||
| 14 | 15 | ||
| 15 | GLInnerFence::GLInnerFence(GPUVAddr address, u32 payload, bool is_stubbed) | 16 | GLInnerFence::GLInnerFence(GPUVAddr address, u32 payload, bool is_stubbed) |
| 16 | : VideoCommon::FenceBase(address, payload, is_stubbed), sync_object{} {} | 17 | : FenceBase(address, payload, is_stubbed) {} |
| 17 | 18 | ||
| 18 | GLInnerFence::~GLInnerFence() = default; | 19 | GLInnerFence::~GLInnerFence() = default; |
| 19 | 20 | ||
diff --git a/src/video_core/renderer_opengl/gl_fence_manager.h b/src/video_core/renderer_opengl/gl_fence_manager.h index c917b3343..1686cf5c8 100644 --- a/src/video_core/renderer_opengl/gl_fence_manager.h +++ b/src/video_core/renderer_opengl/gl_fence_manager.h | |||
| @@ -5,7 +5,6 @@ | |||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <memory> | 7 | #include <memory> |
| 8 | #include <glad/glad.h> | ||
| 9 | 8 | ||
| 10 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 11 | #include "video_core/fence_manager.h" | 10 | #include "video_core/fence_manager.h" |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index cb284db77..4af5824cd 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -177,15 +177,7 @@ RasterizerOpenGL::RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWind | |||
| 177 | } | 177 | } |
| 178 | 178 | ||
| 179 | if (device.UseAsynchronousShaders()) { | 179 | if (device.UseAsynchronousShaders()) { |
| 180 | // Max worker threads we should allow | 180 | async_shaders.AllocateWorkers(); |
| 181 | constexpr u32 MAX_THREADS = 4; | ||
| 182 | // Deduce how many threads we can use | ||
| 183 | const u32 threads_used = std::thread::hardware_concurrency() / 4; | ||
| 184 | // Always allow at least 1 thread regardless of our settings | ||
| 185 | const auto max_worker_count = std::max(1U, threads_used); | ||
| 186 | // Don't use more than MAX_THREADS | ||
| 187 | const auto worker_count = std::min(max_worker_count, MAX_THREADS); | ||
| 188 | async_shaders.AllocateWorkers(worker_count); | ||
| 189 | } | 181 | } |
| 190 | } | 182 | } |
| 191 | 183 | ||
diff --git a/src/video_core/renderer_opengl/gl_resource_manager.cpp b/src/video_core/renderer_opengl/gl_resource_manager.cpp index a787e27d2..0ebcec427 100644 --- a/src/video_core/renderer_opengl/gl_resource_manager.cpp +++ b/src/video_core/renderer_opengl/gl_resource_manager.cpp | |||
| @@ -2,6 +2,7 @@ | |||
| 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> | ||
| 5 | #include <utility> | 6 | #include <utility> |
| 6 | #include <glad/glad.h> | 7 | #include <glad/glad.h> |
| 7 | #include "common/common_types.h" | 8 | #include "common/common_types.h" |
| @@ -82,11 +83,13 @@ void OGLSampler::Release() { | |||
| 82 | handle = 0; | 83 | handle = 0; |
| 83 | } | 84 | } |
| 84 | 85 | ||
| 85 | void OGLShader::Create(const char* source, GLenum type) { | 86 | void OGLShader::Create(std::string_view source, GLenum type) { |
| 86 | if (handle != 0) | 87 | if (handle != 0) { |
| 87 | return; | 88 | return; |
| 88 | if (source == nullptr) | 89 | } |
| 90 | if (source.empty()) { | ||
| 89 | return; | 91 | return; |
| 92 | } | ||
| 90 | 93 | ||
| 91 | MICROPROFILE_SCOPE(OpenGL_ResourceCreation); | 94 | MICROPROFILE_SCOPE(OpenGL_ResourceCreation); |
| 92 | handle = GLShader::LoadShader(source, type); | 95 | handle = GLShader::LoadShader(source, type); |
diff --git a/src/video_core/renderer_opengl/gl_resource_manager.h b/src/video_core/renderer_opengl/gl_resource_manager.h index b05cb641c..f48398669 100644 --- a/src/video_core/renderer_opengl/gl_resource_manager.h +++ b/src/video_core/renderer_opengl/gl_resource_manager.h | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <string_view> | ||
| 7 | #include <utility> | 8 | #include <utility> |
| 8 | #include <glad/glad.h> | 9 | #include <glad/glad.h> |
| 9 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| @@ -127,7 +128,7 @@ public: | |||
| 127 | return *this; | 128 | return *this; |
| 128 | } | 129 | } |
| 129 | 130 | ||
| 130 | void Create(const char* source, GLenum type); | 131 | void Create(std::string_view source, GLenum type); |
| 131 | 132 | ||
| 132 | void Release(); | 133 | void Release(); |
| 133 | 134 | ||
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index be71e1733..a07d56ef0 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include "video_core/memory_manager.h" | 22 | #include "video_core/memory_manager.h" |
| 23 | #include "video_core/renderer_opengl/gl_arb_decompiler.h" | 23 | #include "video_core/renderer_opengl/gl_arb_decompiler.h" |
| 24 | #include "video_core/renderer_opengl/gl_rasterizer.h" | 24 | #include "video_core/renderer_opengl/gl_rasterizer.h" |
| 25 | #include "video_core/renderer_opengl/gl_resource_manager.h" | ||
| 25 | #include "video_core/renderer_opengl/gl_shader_cache.h" | 26 | #include "video_core/renderer_opengl/gl_shader_cache.h" |
| 26 | #include "video_core/renderer_opengl/gl_shader_decompiler.h" | 27 | #include "video_core/renderer_opengl/gl_shader_decompiler.h" |
| 27 | #include "video_core/renderer_opengl/gl_shader_disk_cache.h" | 28 | #include "video_core/renderer_opengl/gl_shader_disk_cache.h" |
| @@ -403,7 +404,7 @@ void ShaderCacheOpenGL::LoadDiskCache(const std::atomic_bool& stop_loading, | |||
| 403 | } | 404 | } |
| 404 | }; | 405 | }; |
| 405 | 406 | ||
| 406 | const auto num_workers{static_cast<std::size_t>(std::thread::hardware_concurrency() + 1ULL)}; | 407 | const std::size_t num_workers{std::max(1U, std::thread::hardware_concurrency())}; |
| 407 | const std::size_t bucket_size{transferable->size() / num_workers}; | 408 | const std::size_t bucket_size{transferable->size() / num_workers}; |
| 408 | std::vector<std::unique_ptr<Core::Frontend::GraphicsContext>> contexts(num_workers); | 409 | std::vector<std::unique_ptr<Core::Frontend::GraphicsContext>> contexts(num_workers); |
| 409 | std::vector<std::thread> threads(num_workers); | 410 | std::vector<std::thread> threads(num_workers); |
diff --git a/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp b/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp index 2dcc2b0eb..40c0877c1 100644 --- a/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp | |||
| @@ -73,7 +73,7 @@ ShaderDiskCacheEntry::ShaderDiskCacheEntry() = default; | |||
| 73 | 73 | ||
| 74 | ShaderDiskCacheEntry::~ShaderDiskCacheEntry() = default; | 74 | ShaderDiskCacheEntry::~ShaderDiskCacheEntry() = default; |
| 75 | 75 | ||
| 76 | bool ShaderDiskCacheEntry::Load(FileUtil::IOFile& file) { | 76 | bool ShaderDiskCacheEntry::Load(Common::FS::IOFile& file) { |
| 77 | if (file.ReadBytes(&type, sizeof(u32)) != sizeof(u32)) { | 77 | if (file.ReadBytes(&type, sizeof(u32)) != sizeof(u32)) { |
| 78 | return false; | 78 | return false; |
| 79 | } | 79 | } |
| @@ -144,7 +144,7 @@ bool ShaderDiskCacheEntry::Load(FileUtil::IOFile& file) { | |||
| 144 | return true; | 144 | return true; |
| 145 | } | 145 | } |
| 146 | 146 | ||
| 147 | bool ShaderDiskCacheEntry::Save(FileUtil::IOFile& file) const { | 147 | bool ShaderDiskCacheEntry::Save(Common::FS::IOFile& file) const { |
| 148 | if (file.WriteObject(static_cast<u32>(type)) != 1 || | 148 | if (file.WriteObject(static_cast<u32>(type)) != 1 || |
| 149 | file.WriteObject(static_cast<u32>(code.size())) != 1 || | 149 | file.WriteObject(static_cast<u32>(code.size())) != 1 || |
| 150 | file.WriteObject(static_cast<u32>(code_b.size())) != 1) { | 150 | file.WriteObject(static_cast<u32>(code_b.size())) != 1) { |
| @@ -214,20 +214,20 @@ std::optional<std::vector<ShaderDiskCacheEntry>> ShaderDiskCacheOpenGL::LoadTran | |||
| 214 | // Skip games without title id | 214 | // Skip games without title id |
| 215 | const bool has_title_id = system.CurrentProcess()->GetTitleID() != 0; | 215 | const bool has_title_id = system.CurrentProcess()->GetTitleID() != 0; |
| 216 | if (!Settings::values.use_disk_shader_cache.GetValue() || !has_title_id) { | 216 | if (!Settings::values.use_disk_shader_cache.GetValue() || !has_title_id) { |
| 217 | return {}; | 217 | return std::nullopt; |
| 218 | } | 218 | } |
| 219 | 219 | ||
| 220 | FileUtil::IOFile file(GetTransferablePath(), "rb"); | 220 | Common::FS::IOFile file(GetTransferablePath(), "rb"); |
| 221 | if (!file.IsOpen()) { | 221 | if (!file.IsOpen()) { |
| 222 | LOG_INFO(Render_OpenGL, "No transferable shader cache found"); | 222 | LOG_INFO(Render_OpenGL, "No transferable shader cache found"); |
| 223 | is_usable = true; | 223 | is_usable = true; |
| 224 | return {}; | 224 | return std::nullopt; |
| 225 | } | 225 | } |
| 226 | 226 | ||
| 227 | u32 version{}; | 227 | u32 version{}; |
| 228 | if (file.ReadBytes(&version, sizeof(version)) != sizeof(version)) { | 228 | if (file.ReadBytes(&version, sizeof(version)) != sizeof(version)) { |
| 229 | LOG_ERROR(Render_OpenGL, "Failed to get transferable cache version, skipping it"); | 229 | LOG_ERROR(Render_OpenGL, "Failed to get transferable cache version, skipping it"); |
| 230 | return {}; | 230 | return std::nullopt; |
| 231 | } | 231 | } |
| 232 | 232 | ||
| 233 | if (version < NativeVersion) { | 233 | if (version < NativeVersion) { |
| @@ -235,12 +235,12 @@ std::optional<std::vector<ShaderDiskCacheEntry>> ShaderDiskCacheOpenGL::LoadTran | |||
| 235 | file.Close(); | 235 | file.Close(); |
| 236 | InvalidateTransferable(); | 236 | InvalidateTransferable(); |
| 237 | is_usable = true; | 237 | is_usable = true; |
| 238 | return {}; | 238 | return std::nullopt; |
| 239 | } | 239 | } |
| 240 | if (version > NativeVersion) { | 240 | if (version > NativeVersion) { |
| 241 | LOG_WARNING(Render_OpenGL, "Transferable shader cache was generated with a newer version " | 241 | LOG_WARNING(Render_OpenGL, "Transferable shader cache was generated with a newer version " |
| 242 | "of the emulator, skipping"); | 242 | "of the emulator, skipping"); |
| 243 | return {}; | 243 | return std::nullopt; |
| 244 | } | 244 | } |
| 245 | 245 | ||
| 246 | // Version is valid, load the shaders | 246 | // Version is valid, load the shaders |
| @@ -249,7 +249,7 @@ std::optional<std::vector<ShaderDiskCacheEntry>> ShaderDiskCacheOpenGL::LoadTran | |||
| 249 | ShaderDiskCacheEntry& entry = entries.emplace_back(); | 249 | ShaderDiskCacheEntry& entry = entries.emplace_back(); |
| 250 | if (!entry.Load(file)) { | 250 | if (!entry.Load(file)) { |
| 251 | LOG_ERROR(Render_OpenGL, "Failed to load transferable raw entry, skipping"); | 251 | LOG_ERROR(Render_OpenGL, "Failed to load transferable raw entry, skipping"); |
| 252 | return {}; | 252 | return std::nullopt; |
| 253 | } | 253 | } |
| 254 | } | 254 | } |
| 255 | 255 | ||
| @@ -262,7 +262,7 @@ std::vector<ShaderDiskCachePrecompiled> ShaderDiskCacheOpenGL::LoadPrecompiled() | |||
| 262 | return {}; | 262 | return {}; |
| 263 | } | 263 | } |
| 264 | 264 | ||
| 265 | FileUtil::IOFile file(GetPrecompiledPath(), "rb"); | 265 | Common::FS::IOFile file(GetPrecompiledPath(), "rb"); |
| 266 | if (!file.IsOpen()) { | 266 | if (!file.IsOpen()) { |
| 267 | LOG_INFO(Render_OpenGL, "No precompiled shader cache found"); | 267 | LOG_INFO(Render_OpenGL, "No precompiled shader cache found"); |
| 268 | return {}; | 268 | return {}; |
| @@ -279,7 +279,7 @@ std::vector<ShaderDiskCachePrecompiled> ShaderDiskCacheOpenGL::LoadPrecompiled() | |||
| 279 | } | 279 | } |
| 280 | 280 | ||
| 281 | std::optional<std::vector<ShaderDiskCachePrecompiled>> ShaderDiskCacheOpenGL::LoadPrecompiledFile( | 281 | std::optional<std::vector<ShaderDiskCachePrecompiled>> ShaderDiskCacheOpenGL::LoadPrecompiledFile( |
| 282 | FileUtil::IOFile& file) { | 282 | Common::FS::IOFile& file) { |
| 283 | // Read compressed file from disk and decompress to virtual precompiled cache file | 283 | // Read compressed file from disk and decompress to virtual precompiled cache file |
| 284 | std::vector<u8> compressed(file.GetSize()); | 284 | std::vector<u8> compressed(file.GetSize()); |
| 285 | file.ReadBytes(compressed.data(), compressed.size()); | 285 | file.ReadBytes(compressed.data(), compressed.size()); |
| @@ -290,12 +290,12 @@ std::optional<std::vector<ShaderDiskCachePrecompiled>> ShaderDiskCacheOpenGL::Lo | |||
| 290 | ShaderCacheVersionHash file_hash{}; | 290 | ShaderCacheVersionHash file_hash{}; |
| 291 | if (!LoadArrayFromPrecompiled(file_hash.data(), file_hash.size())) { | 291 | if (!LoadArrayFromPrecompiled(file_hash.data(), file_hash.size())) { |
| 292 | precompiled_cache_virtual_file_offset = 0; | 292 | precompiled_cache_virtual_file_offset = 0; |
| 293 | return {}; | 293 | return std::nullopt; |
| 294 | } | 294 | } |
| 295 | if (GetShaderCacheVersionHash() != file_hash) { | 295 | if (GetShaderCacheVersionHash() != file_hash) { |
| 296 | LOG_INFO(Render_OpenGL, "Precompiled cache is from another version of the emulator"); | 296 | LOG_INFO(Render_OpenGL, "Precompiled cache is from another version of the emulator"); |
| 297 | precompiled_cache_virtual_file_offset = 0; | 297 | precompiled_cache_virtual_file_offset = 0; |
| 298 | return {}; | 298 | return std::nullopt; |
| 299 | } | 299 | } |
| 300 | 300 | ||
| 301 | std::vector<ShaderDiskCachePrecompiled> entries; | 301 | std::vector<ShaderDiskCachePrecompiled> entries; |
| @@ -305,19 +305,20 @@ std::optional<std::vector<ShaderDiskCachePrecompiled>> ShaderDiskCacheOpenGL::Lo | |||
| 305 | if (!LoadObjectFromPrecompiled(entry.unique_identifier) || | 305 | if (!LoadObjectFromPrecompiled(entry.unique_identifier) || |
| 306 | !LoadObjectFromPrecompiled(entry.binary_format) || | 306 | !LoadObjectFromPrecompiled(entry.binary_format) || |
| 307 | !LoadObjectFromPrecompiled(binary_size)) { | 307 | !LoadObjectFromPrecompiled(binary_size)) { |
| 308 | return {}; | 308 | return std::nullopt; |
| 309 | } | 309 | } |
| 310 | 310 | ||
| 311 | entry.binary.resize(binary_size); | 311 | entry.binary.resize(binary_size); |
| 312 | if (!LoadArrayFromPrecompiled(entry.binary.data(), entry.binary.size())) { | 312 | if (!LoadArrayFromPrecompiled(entry.binary.data(), entry.binary.size())) { |
| 313 | return {}; | 313 | return std::nullopt; |
| 314 | } | 314 | } |
| 315 | } | 315 | } |
| 316 | return entries; | 316 | |
| 317 | return std::move(entries); | ||
| 317 | } | 318 | } |
| 318 | 319 | ||
| 319 | void ShaderDiskCacheOpenGL::InvalidateTransferable() { | 320 | void ShaderDiskCacheOpenGL::InvalidateTransferable() { |
| 320 | if (!FileUtil::Delete(GetTransferablePath())) { | 321 | if (!Common::FS::Delete(GetTransferablePath())) { |
| 321 | LOG_ERROR(Render_OpenGL, "Failed to invalidate transferable file={}", | 322 | LOG_ERROR(Render_OpenGL, "Failed to invalidate transferable file={}", |
| 322 | GetTransferablePath()); | 323 | GetTransferablePath()); |
| 323 | } | 324 | } |
| @@ -328,7 +329,7 @@ void ShaderDiskCacheOpenGL::InvalidatePrecompiled() { | |||
| 328 | // Clear virtaul precompiled cache file | 329 | // Clear virtaul precompiled cache file |
| 329 | precompiled_cache_virtual_file.Resize(0); | 330 | precompiled_cache_virtual_file.Resize(0); |
| 330 | 331 | ||
| 331 | if (!FileUtil::Delete(GetPrecompiledPath())) { | 332 | if (!Common::FS::Delete(GetPrecompiledPath())) { |
| 332 | LOG_ERROR(Render_OpenGL, "Failed to invalidate precompiled file={}", GetPrecompiledPath()); | 333 | LOG_ERROR(Render_OpenGL, "Failed to invalidate precompiled file={}", GetPrecompiledPath()); |
| 333 | } | 334 | } |
| 334 | } | 335 | } |
| @@ -344,7 +345,7 @@ void ShaderDiskCacheOpenGL::SaveEntry(const ShaderDiskCacheEntry& entry) { | |||
| 344 | return; | 345 | return; |
| 345 | } | 346 | } |
| 346 | 347 | ||
| 347 | FileUtil::IOFile file = AppendTransferableFile(); | 348 | Common::FS::IOFile file = AppendTransferableFile(); |
| 348 | if (!file.IsOpen()) { | 349 | if (!file.IsOpen()) { |
| 349 | return; | 350 | return; |
| 350 | } | 351 | } |
| @@ -386,15 +387,15 @@ void ShaderDiskCacheOpenGL::SavePrecompiled(u64 unique_identifier, GLuint progra | |||
| 386 | } | 387 | } |
| 387 | } | 388 | } |
| 388 | 389 | ||
| 389 | FileUtil::IOFile ShaderDiskCacheOpenGL::AppendTransferableFile() const { | 390 | Common::FS::IOFile ShaderDiskCacheOpenGL::AppendTransferableFile() const { |
| 390 | if (!EnsureDirectories()) { | 391 | if (!EnsureDirectories()) { |
| 391 | return {}; | 392 | return {}; |
| 392 | } | 393 | } |
| 393 | 394 | ||
| 394 | const auto transferable_path{GetTransferablePath()}; | 395 | const auto transferable_path{GetTransferablePath()}; |
| 395 | const bool existed = FileUtil::Exists(transferable_path); | 396 | const bool existed = Common::FS::Exists(transferable_path); |
| 396 | 397 | ||
| 397 | FileUtil::IOFile file(transferable_path, "ab"); | 398 | Common::FS::IOFile file(transferable_path, "ab"); |
| 398 | if (!file.IsOpen()) { | 399 | if (!file.IsOpen()) { |
| 399 | LOG_ERROR(Render_OpenGL, "Failed to open transferable cache in path={}", transferable_path); | 400 | LOG_ERROR(Render_OpenGL, "Failed to open transferable cache in path={}", transferable_path); |
| 400 | return {}; | 401 | return {}; |
| @@ -426,7 +427,7 @@ void ShaderDiskCacheOpenGL::SaveVirtualPrecompiledFile() { | |||
| 426 | Common::Compression::CompressDataZSTDDefault(uncompressed.data(), uncompressed.size()); | 427 | Common::Compression::CompressDataZSTDDefault(uncompressed.data(), uncompressed.size()); |
| 427 | 428 | ||
| 428 | const auto precompiled_path{GetPrecompiledPath()}; | 429 | const auto precompiled_path{GetPrecompiledPath()}; |
| 429 | FileUtil::IOFile file(precompiled_path, "wb"); | 430 | Common::FS::IOFile file(precompiled_path, "wb"); |
| 430 | 431 | ||
| 431 | if (!file.IsOpen()) { | 432 | if (!file.IsOpen()) { |
| 432 | LOG_ERROR(Render_OpenGL, "Failed to open precompiled cache in path={}", precompiled_path); | 433 | LOG_ERROR(Render_OpenGL, "Failed to open precompiled cache in path={}", precompiled_path); |
| @@ -440,24 +441,24 @@ void ShaderDiskCacheOpenGL::SaveVirtualPrecompiledFile() { | |||
| 440 | 441 | ||
| 441 | bool ShaderDiskCacheOpenGL::EnsureDirectories() const { | 442 | bool ShaderDiskCacheOpenGL::EnsureDirectories() const { |
| 442 | const auto CreateDir = [](const std::string& dir) { | 443 | const auto CreateDir = [](const std::string& dir) { |
| 443 | if (!FileUtil::CreateDir(dir)) { | 444 | if (!Common::FS::CreateDir(dir)) { |
| 444 | LOG_ERROR(Render_OpenGL, "Failed to create directory={}", dir); | 445 | LOG_ERROR(Render_OpenGL, "Failed to create directory={}", dir); |
| 445 | return false; | 446 | return false; |
| 446 | } | 447 | } |
| 447 | return true; | 448 | return true; |
| 448 | }; | 449 | }; |
| 449 | 450 | ||
| 450 | return CreateDir(FileUtil::GetUserPath(FileUtil::UserPath::ShaderDir)) && | 451 | return CreateDir(Common::FS::GetUserPath(Common::FS::UserPath::ShaderDir)) && |
| 451 | CreateDir(GetBaseDir()) && CreateDir(GetTransferableDir()) && | 452 | CreateDir(GetBaseDir()) && CreateDir(GetTransferableDir()) && |
| 452 | CreateDir(GetPrecompiledDir()); | 453 | CreateDir(GetPrecompiledDir()); |
| 453 | } | 454 | } |
| 454 | 455 | ||
| 455 | std::string ShaderDiskCacheOpenGL::GetTransferablePath() const { | 456 | std::string ShaderDiskCacheOpenGL::GetTransferablePath() const { |
| 456 | return FileUtil::SanitizePath(GetTransferableDir() + DIR_SEP_CHR + GetTitleID() + ".bin"); | 457 | return Common::FS::SanitizePath(GetTransferableDir() + DIR_SEP_CHR + GetTitleID() + ".bin"); |
| 457 | } | 458 | } |
| 458 | 459 | ||
| 459 | std::string ShaderDiskCacheOpenGL::GetPrecompiledPath() const { | 460 | std::string ShaderDiskCacheOpenGL::GetPrecompiledPath() const { |
| 460 | return FileUtil::SanitizePath(GetPrecompiledDir() + DIR_SEP_CHR + GetTitleID() + ".bin"); | 461 | return Common::FS::SanitizePath(GetPrecompiledDir() + DIR_SEP_CHR + GetTitleID() + ".bin"); |
| 461 | } | 462 | } |
| 462 | 463 | ||
| 463 | std::string ShaderDiskCacheOpenGL::GetTransferableDir() const { | 464 | std::string ShaderDiskCacheOpenGL::GetTransferableDir() const { |
| @@ -469,7 +470,7 @@ std::string ShaderDiskCacheOpenGL::GetPrecompiledDir() const { | |||
| 469 | } | 470 | } |
| 470 | 471 | ||
| 471 | std::string ShaderDiskCacheOpenGL::GetBaseDir() const { | 472 | std::string ShaderDiskCacheOpenGL::GetBaseDir() const { |
| 472 | return FileUtil::GetUserPath(FileUtil::UserPath::ShaderDir) + DIR_SEP "opengl"; | 473 | return Common::FS::GetUserPath(Common::FS::UserPath::ShaderDir) + DIR_SEP "opengl"; |
| 473 | } | 474 | } |
| 474 | 475 | ||
| 475 | std::string ShaderDiskCacheOpenGL::GetTitleID() const { | 476 | std::string ShaderDiskCacheOpenGL::GetTitleID() const { |
diff --git a/src/video_core/renderer_opengl/gl_shader_disk_cache.h b/src/video_core/renderer_opengl/gl_shader_disk_cache.h index a79cef0e9..db2bb73bc 100644 --- a/src/video_core/renderer_opengl/gl_shader_disk_cache.h +++ b/src/video_core/renderer_opengl/gl_shader_disk_cache.h | |||
| @@ -25,7 +25,7 @@ namespace Core { | |||
| 25 | class System; | 25 | class System; |
| 26 | } | 26 | } |
| 27 | 27 | ||
| 28 | namespace FileUtil { | 28 | namespace Common::FS { |
| 29 | class IOFile; | 29 | class IOFile; |
| 30 | } | 30 | } |
| 31 | 31 | ||
| @@ -38,9 +38,9 @@ struct ShaderDiskCacheEntry { | |||
| 38 | ShaderDiskCacheEntry(); | 38 | ShaderDiskCacheEntry(); |
| 39 | ~ShaderDiskCacheEntry(); | 39 | ~ShaderDiskCacheEntry(); |
| 40 | 40 | ||
| 41 | bool Load(FileUtil::IOFile& file); | 41 | bool Load(Common::FS::IOFile& file); |
| 42 | 42 | ||
| 43 | bool Save(FileUtil::IOFile& file) const; | 43 | bool Save(Common::FS::IOFile& file) const; |
| 44 | 44 | ||
| 45 | bool HasProgramA() const { | 45 | bool HasProgramA() const { |
| 46 | return !code.empty() && !code_b.empty(); | 46 | return !code.empty() && !code_b.empty(); |
| @@ -97,10 +97,10 @@ public: | |||
| 97 | private: | 97 | private: |
| 98 | /// Loads the transferable cache. Returns empty on failure. | 98 | /// Loads the transferable cache. Returns empty on failure. |
| 99 | std::optional<std::vector<ShaderDiskCachePrecompiled>> LoadPrecompiledFile( | 99 | std::optional<std::vector<ShaderDiskCachePrecompiled>> LoadPrecompiledFile( |
| 100 | FileUtil::IOFile& file); | 100 | Common::FS::IOFile& file); |
| 101 | 101 | ||
| 102 | /// Opens current game's transferable file and write it's header if it doesn't exist | 102 | /// Opens current game's transferable file and write it's header if it doesn't exist |
| 103 | FileUtil::IOFile AppendTransferableFile() const; | 103 | Common::FS::IOFile AppendTransferableFile() const; |
| 104 | 104 | ||
| 105 | /// Save precompiled header to precompiled_cache_in_memory | 105 | /// Save precompiled header to precompiled_cache_in_memory |
| 106 | void SavePrecompiledHeaderToVirtualPrecompiledCache(); | 106 | void SavePrecompiledHeaderToVirtualPrecompiledCache(); |
diff --git a/src/video_core/renderer_opengl/gl_shader_util.cpp b/src/video_core/renderer_opengl/gl_shader_util.cpp index 9e74eda0d..4bf0d6090 100644 --- a/src/video_core/renderer_opengl/gl_shader_util.cpp +++ b/src/video_core/renderer_opengl/gl_shader_util.cpp | |||
| @@ -2,6 +2,7 @@ | |||
| 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> | ||
| 5 | #include <vector> | 6 | #include <vector> |
| 6 | #include <glad/glad.h> | 7 | #include <glad/glad.h> |
| 7 | #include "common/assert.h" | 8 | #include "common/assert.h" |
| @@ -11,7 +12,8 @@ | |||
| 11 | namespace OpenGL::GLShader { | 12 | namespace OpenGL::GLShader { |
| 12 | 13 | ||
| 13 | namespace { | 14 | namespace { |
| 14 | const char* GetStageDebugName(GLenum type) { | 15 | |
| 16 | std::string_view StageDebugName(GLenum type) { | ||
| 15 | switch (type) { | 17 | switch (type) { |
| 16 | case GL_VERTEX_SHADER: | 18 | case GL_VERTEX_SHADER: |
| 17 | return "vertex"; | 19 | return "vertex"; |
| @@ -25,12 +27,17 @@ const char* GetStageDebugName(GLenum type) { | |||
| 25 | UNIMPLEMENTED(); | 27 | UNIMPLEMENTED(); |
| 26 | return "unknown"; | 28 | return "unknown"; |
| 27 | } | 29 | } |
| 30 | |||
| 28 | } // Anonymous namespace | 31 | } // Anonymous namespace |
| 29 | 32 | ||
| 30 | GLuint LoadShader(const char* source, GLenum type) { | 33 | GLuint LoadShader(std::string_view source, GLenum type) { |
| 31 | const char* debug_type = GetStageDebugName(type); | 34 | const std::string_view debug_type = StageDebugName(type); |
| 32 | const GLuint shader_id = glCreateShader(type); | 35 | const GLuint shader_id = glCreateShader(type); |
| 33 | glShaderSource(shader_id, 1, &source, nullptr); | 36 | |
| 37 | const GLchar* source_string = source.data(); | ||
| 38 | const GLint source_length = static_cast<GLint>(source.size()); | ||
| 39 | |||
| 40 | glShaderSource(shader_id, 1, &source_string, &source_length); | ||
| 34 | LOG_DEBUG(Render_OpenGL, "Compiling {} shader...", debug_type); | 41 | LOG_DEBUG(Render_OpenGL, "Compiling {} shader...", debug_type); |
| 35 | glCompileShader(shader_id); | 42 | glCompileShader(shader_id); |
| 36 | 43 | ||
diff --git a/src/video_core/renderer_opengl/gl_shader_util.h b/src/video_core/renderer_opengl/gl_shader_util.h index 03b7548c2..1b770532e 100644 --- a/src/video_core/renderer_opengl/gl_shader_util.h +++ b/src/video_core/renderer_opengl/gl_shader_util.h | |||
| @@ -38,7 +38,7 @@ void LogShaderSource(T... shaders) { | |||
| 38 | * @param source String of the GLSL shader program | 38 | * @param source String of the GLSL shader program |
| 39 | * @param type Type of the shader (GL_VERTEX_SHADER, GL_GEOMETRY_SHADER or GL_FRAGMENT_SHADER) | 39 | * @param type Type of the shader (GL_VERTEX_SHADER, GL_GEOMETRY_SHADER or GL_FRAGMENT_SHADER) |
| 40 | */ | 40 | */ |
| 41 | GLuint LoadShader(const char* source, GLenum type); | 41 | GLuint LoadShader(std::string_view source, GLenum type); |
| 42 | 42 | ||
| 43 | /** | 43 | /** |
| 44 | * Utility function to create and compile an OpenGL GLSL shader program (vertex + fragment shader) | 44 | * Utility function to create and compile an OpenGL GLSL shader program (vertex + fragment shader) |
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp index 0a7bc9e2b..f403f388a 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.cpp +++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp | |||
| @@ -403,7 +403,7 @@ void CachedSurface::DecorateSurfaceName() { | |||
| 403 | LabelGLObject(GL_TEXTURE, texture.handle, GetGpuAddr(), params.TargetName()); | 403 | LabelGLObject(GL_TEXTURE, texture.handle, GetGpuAddr(), params.TargetName()); |
| 404 | } | 404 | } |
| 405 | 405 | ||
| 406 | void CachedSurfaceView::DecorateViewName(GPUVAddr gpu_addr, std::string prefix) { | 406 | void CachedSurfaceView::DecorateViewName(GPUVAddr gpu_addr, const std::string& prefix) { |
| 407 | LabelGLObject(GL_TEXTURE, main_view.handle, gpu_addr, prefix); | 407 | LabelGLObject(GL_TEXTURE, main_view.handle, gpu_addr, prefix); |
| 408 | } | 408 | } |
| 409 | 409 | ||
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h index bfc4ddf5d..de8f18489 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.h +++ b/src/video_core/renderer_opengl/gl_texture_cache.h | |||
| @@ -90,7 +90,7 @@ public: | |||
| 90 | Tegra::Texture::SwizzleSource z_source, | 90 | Tegra::Texture::SwizzleSource z_source, |
| 91 | Tegra::Texture::SwizzleSource w_source); | 91 | Tegra::Texture::SwizzleSource w_source); |
| 92 | 92 | ||
| 93 | void DecorateViewName(GPUVAddr gpu_addr, std::string prefix); | 93 | void DecorateViewName(GPUVAddr gpu_addr, const std::string& prefix); |
| 94 | 94 | ||
| 95 | void MarkAsModified(u64 tick) { | 95 | void MarkAsModified(u64 tick) { |
| 96 | surface.MarkAsModified(true, tick); | 96 | surface.MarkAsModified(true, tick); |
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 52e9e8250..b759c2dba 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp | |||
| @@ -21,6 +21,8 @@ | |||
| 21 | #include "core/perf_stats.h" | 21 | #include "core/perf_stats.h" |
| 22 | #include "core/settings.h" | 22 | #include "core/settings.h" |
| 23 | #include "core/telemetry_session.h" | 23 | #include "core/telemetry_session.h" |
| 24 | #include "video_core/host_shaders/opengl_present_frag.h" | ||
| 25 | #include "video_core/host_shaders/opengl_present_vert.h" | ||
| 24 | #include "video_core/morton.h" | 26 | #include "video_core/morton.h" |
| 25 | #include "video_core/renderer_opengl/gl_rasterizer.h" | 27 | #include "video_core/renderer_opengl/gl_rasterizer.h" |
| 26 | #include "video_core/renderer_opengl/gl_shader_manager.h" | 28 | #include "video_core/renderer_opengl/gl_shader_manager.h" |
| @@ -44,46 +46,6 @@ struct Frame { | |||
| 44 | bool is_srgb{}; /// Framebuffer is sRGB or RGB | 46 | bool is_srgb{}; /// Framebuffer is sRGB or RGB |
| 45 | }; | 47 | }; |
| 46 | 48 | ||
| 47 | constexpr char VERTEX_SHADER[] = R"( | ||
| 48 | #version 430 core | ||
| 49 | |||
| 50 | out gl_PerVertex { | ||
| 51 | vec4 gl_Position; | ||
| 52 | }; | ||
| 53 | |||
| 54 | layout (location = 0) in vec2 vert_position; | ||
| 55 | layout (location = 1) in vec2 vert_tex_coord; | ||
| 56 | layout (location = 0) out vec2 frag_tex_coord; | ||
| 57 | |||
| 58 | // This is a truncated 3x3 matrix for 2D transformations: | ||
| 59 | // The upper-left 2x2 submatrix performs scaling/rotation/mirroring. | ||
| 60 | // The third column performs translation. | ||
| 61 | // The third row could be used for projection, which we don't need in 2D. It hence is assumed to | ||
| 62 | // implicitly be [0, 0, 1] | ||
| 63 | layout (location = 0) uniform mat3x2 modelview_matrix; | ||
| 64 | |||
| 65 | void main() { | ||
| 66 | // Multiply input position by the rotscale part of the matrix and then manually translate by | ||
| 67 | // the last column. This is equivalent to using a full 3x3 matrix and expanding the vector | ||
| 68 | // to `vec3(vert_position.xy, 1.0)` | ||
| 69 | gl_Position = vec4(mat2(modelview_matrix) * vert_position + modelview_matrix[2], 0.0, 1.0); | ||
| 70 | frag_tex_coord = vert_tex_coord; | ||
| 71 | } | ||
| 72 | )"; | ||
| 73 | |||
| 74 | constexpr char FRAGMENT_SHADER[] = R"( | ||
| 75 | #version 430 core | ||
| 76 | |||
| 77 | layout (location = 0) in vec2 frag_tex_coord; | ||
| 78 | layout (location = 0) out vec4 color; | ||
| 79 | |||
| 80 | layout (binding = 0) uniform sampler2D color_texture; | ||
| 81 | |||
| 82 | void main() { | ||
| 83 | color = vec4(texture(color_texture, frag_tex_coord).rgb, 1.0f); | ||
| 84 | } | ||
| 85 | )"; | ||
| 86 | |||
| 87 | constexpr GLint PositionLocation = 0; | 49 | constexpr GLint PositionLocation = 0; |
| 88 | constexpr GLint TexCoordLocation = 1; | 50 | constexpr GLint TexCoordLocation = 1; |
| 89 | constexpr GLint ModelViewMatrixLocation = 0; | 51 | constexpr GLint ModelViewMatrixLocation = 0; |
| @@ -313,10 +275,11 @@ public: | |||
| 313 | } | 275 | } |
| 314 | }; | 276 | }; |
| 315 | 277 | ||
| 316 | RendererOpenGL::RendererOpenGL(Core::Frontend::EmuWindow& emu_window, Core::System& system, | 278 | RendererOpenGL::RendererOpenGL(Core::System& system_, Core::Frontend::EmuWindow& emu_window_, |
| 317 | Core::Frontend::GraphicsContext& context) | 279 | Tegra::GPU& gpu_, |
| 318 | : RendererBase{emu_window}, emu_window{emu_window}, system{system}, context{context}, | 280 | std::unique_ptr<Core::Frontend::GraphicsContext> context_) |
| 319 | program_manager{device}, has_debug_tool{HasDebugTool()} {} | 281 | : RendererBase{emu_window_, std::move(context_)}, system{system_}, |
| 282 | emu_window{emu_window_}, gpu{gpu_}, program_manager{device}, has_debug_tool{HasDebugTool()} {} | ||
| 320 | 283 | ||
| 321 | RendererOpenGL::~RendererOpenGL() = default; | 284 | RendererOpenGL::~RendererOpenGL() = default; |
| 322 | 285 | ||
| @@ -384,7 +347,7 @@ void RendererOpenGL::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { | |||
| 384 | if (has_debug_tool) { | 347 | if (has_debug_tool) { |
| 385 | glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); | 348 | glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); |
| 386 | Present(0); | 349 | Present(0); |
| 387 | context.SwapBuffers(); | 350 | context->SwapBuffers(); |
| 388 | } | 351 | } |
| 389 | } | 352 | } |
| 390 | 353 | ||
| @@ -460,10 +423,10 @@ void RendererOpenGL::InitOpenGLObjects() { | |||
| 460 | 423 | ||
| 461 | // Create shader programs | 424 | // Create shader programs |
| 462 | OGLShader vertex_shader; | 425 | OGLShader vertex_shader; |
| 463 | vertex_shader.Create(VERTEX_SHADER, GL_VERTEX_SHADER); | 426 | vertex_shader.Create(HostShaders::OPENGL_PRESENT_VERT, GL_VERTEX_SHADER); |
| 464 | 427 | ||
| 465 | OGLShader fragment_shader; | 428 | OGLShader fragment_shader; |
| 466 | fragment_shader.Create(FRAGMENT_SHADER, GL_FRAGMENT_SHADER); | 429 | fragment_shader.Create(HostShaders::OPENGL_PRESENT_FRAG, GL_FRAGMENT_SHADER); |
| 467 | 430 | ||
| 468 | vertex_program.Create(true, false, vertex_shader.handle); | 431 | vertex_program.Create(true, false, vertex_shader.handle); |
| 469 | fragment_program.Create(true, false, fragment_shader.handle); | 432 | fragment_program.Create(true, false, fragment_shader.handle); |
| @@ -509,9 +472,10 @@ void RendererOpenGL::AddTelemetryFields() { | |||
| 509 | LOG_INFO(Render_OpenGL, "GL_RENDERER: {}", gpu_model); | 472 | LOG_INFO(Render_OpenGL, "GL_RENDERER: {}", gpu_model); |
| 510 | 473 | ||
| 511 | auto& telemetry_session = system.TelemetrySession(); | 474 | auto& telemetry_session = system.TelemetrySession(); |
| 512 | telemetry_session.AddField(Telemetry::FieldType::UserSystem, "GPU_Vendor", gpu_vendor); | 475 | constexpr auto user_system = Common::Telemetry::FieldType::UserSystem; |
| 513 | telemetry_session.AddField(Telemetry::FieldType::UserSystem, "GPU_Model", gpu_model); | 476 | telemetry_session.AddField(user_system, "GPU_Vendor", gpu_vendor); |
| 514 | telemetry_session.AddField(Telemetry::FieldType::UserSystem, "GPU_OpenGL_Version", gl_version); | 477 | telemetry_session.AddField(user_system, "GPU_Model", gpu_model); |
| 478 | telemetry_session.AddField(user_system, "GPU_OpenGL_Version", gl_version); | ||
| 515 | } | 479 | } |
| 516 | 480 | ||
| 517 | void RendererOpenGL::CreateRasterizer() { | 481 | void RendererOpenGL::CreateRasterizer() { |
diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h index 8b18d32e6..52ea76b7d 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.h +++ b/src/video_core/renderer_opengl/renderer_opengl.h | |||
| @@ -56,8 +56,9 @@ class FrameMailbox; | |||
| 56 | 56 | ||
| 57 | class RendererOpenGL final : public VideoCore::RendererBase { | 57 | class RendererOpenGL final : public VideoCore::RendererBase { |
| 58 | public: | 58 | public: |
| 59 | explicit RendererOpenGL(Core::Frontend::EmuWindow& emu_window, Core::System& system, | 59 | explicit RendererOpenGL(Core::System& system, Core::Frontend::EmuWindow& emu_window, |
| 60 | Core::Frontend::GraphicsContext& context); | 60 | Tegra::GPU& gpu, |
| 61 | std::unique_ptr<Core::Frontend::GraphicsContext> context); | ||
| 61 | ~RendererOpenGL() override; | 62 | ~RendererOpenGL() override; |
| 62 | 63 | ||
| 63 | bool Init() override; | 64 | bool Init() override; |
| @@ -93,9 +94,9 @@ private: | |||
| 93 | 94 | ||
| 94 | bool Present(int timeout_ms); | 95 | bool Present(int timeout_ms); |
| 95 | 96 | ||
| 96 | Core::Frontend::EmuWindow& emu_window; | ||
| 97 | Core::System& system; | 97 | Core::System& system; |
| 98 | Core::Frontend::GraphicsContext& context; | 98 | Core::Frontend::EmuWindow& emu_window; |
| 99 | Tegra::GPU& gpu; | ||
| 99 | const Device device; | 100 | const Device device; |
| 100 | 101 | ||
| 101 | StateTracker state_tracker{system}; | 102 | StateTracker state_tracker{system}; |
| @@ -120,7 +121,7 @@ private: | |||
| 120 | std::vector<u8> gl_framebuffer_data; | 121 | std::vector<u8> gl_framebuffer_data; |
| 121 | 122 | ||
| 122 | /// Used for transforming the framebuffer orientation | 123 | /// Used for transforming the framebuffer orientation |
| 123 | Tegra::FramebufferConfig::TransformFlags framebuffer_transform_flags; | 124 | Tegra::FramebufferConfig::TransformFlags framebuffer_transform_flags{}; |
| 124 | Common::Rectangle<int> framebuffer_crop_rect; | 125 | Common::Rectangle<int> framebuffer_crop_rect; |
| 125 | 126 | ||
| 126 | /// Frame presentation mailbox | 127 | /// Frame presentation mailbox |
diff --git a/src/video_core/renderer_vulkan/nsight_aftermath_tracker.cpp b/src/video_core/renderer_vulkan/nsight_aftermath_tracker.cpp index 435c8c1b8..5b01020ec 100644 --- a/src/video_core/renderer_vulkan/nsight_aftermath_tracker.cpp +++ b/src/video_core/renderer_vulkan/nsight_aftermath_tracker.cpp | |||
| @@ -65,10 +65,10 @@ bool NsightAftermathTracker::Initialize() { | |||
| 65 | return false; | 65 | return false; |
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | dump_dir = FileUtil::GetUserPath(FileUtil::UserPath::LogDir) + "gpucrash"; | 68 | dump_dir = Common::FS::GetUserPath(Common::FS::UserPath::LogDir) + "gpucrash"; |
| 69 | 69 | ||
| 70 | (void)FileUtil::DeleteDirRecursively(dump_dir); | 70 | (void)Common::FS::DeleteDirRecursively(dump_dir); |
| 71 | if (!FileUtil::CreateDir(dump_dir)) { | 71 | if (!Common::FS::CreateDir(dump_dir)) { |
| 72 | LOG_ERROR(Render_Vulkan, "Failed to create Nsight Aftermath dump directory"); | 72 | LOG_ERROR(Render_Vulkan, "Failed to create Nsight Aftermath dump directory"); |
| 73 | return false; | 73 | return false; |
| 74 | } | 74 | } |
| @@ -106,7 +106,7 @@ void NsightAftermathTracker::SaveShader(const std::vector<u32>& spirv) const { | |||
| 106 | return; | 106 | return; |
| 107 | } | 107 | } |
| 108 | 108 | ||
| 109 | FileUtil::IOFile file(fmt::format("{}/source_{:016x}.spv", dump_dir, hash.hash), "wb"); | 109 | Common::FS::IOFile file(fmt::format("{}/source_{:016x}.spv", dump_dir, hash.hash), "wb"); |
| 110 | if (!file.IsOpen()) { | 110 | if (!file.IsOpen()) { |
| 111 | LOG_ERROR(Render_Vulkan, "Failed to dump SPIR-V module with hash={:016x}", hash.hash); | 111 | LOG_ERROR(Render_Vulkan, "Failed to dump SPIR-V module with hash={:016x}", hash.hash); |
| 112 | return; | 112 | return; |
| @@ -156,12 +156,12 @@ void NsightAftermathTracker::OnGpuCrashDumpCallback(const void* gpu_crash_dump, | |||
| 156 | }(); | 156 | }(); |
| 157 | 157 | ||
| 158 | std::string_view dump_view(static_cast<const char*>(gpu_crash_dump), gpu_crash_dump_size); | 158 | std::string_view dump_view(static_cast<const char*>(gpu_crash_dump), gpu_crash_dump_size); |
| 159 | if (FileUtil::WriteStringToFile(false, base_name, dump_view) != gpu_crash_dump_size) { | 159 | if (Common::FS::WriteStringToFile(false, base_name, dump_view) != gpu_crash_dump_size) { |
| 160 | LOG_ERROR(Render_Vulkan, "Failed to write dump file"); | 160 | LOG_ERROR(Render_Vulkan, "Failed to write dump file"); |
| 161 | return; | 161 | return; |
| 162 | } | 162 | } |
| 163 | const std::string_view json_view(json.data(), json.size()); | 163 | const std::string_view json_view(json.data(), json.size()); |
| 164 | if (FileUtil::WriteStringToFile(true, base_name + ".json", json_view) != json.size()) { | 164 | if (Common::FS::WriteStringToFile(true, base_name + ".json", json_view) != json.size()) { |
| 165 | LOG_ERROR(Render_Vulkan, "Failed to write JSON"); | 165 | LOG_ERROR(Render_Vulkan, "Failed to write JSON"); |
| 166 | return; | 166 | return; |
| 167 | } | 167 | } |
| @@ -180,7 +180,7 @@ void NsightAftermathTracker::OnShaderDebugInfoCallback(const void* shader_debug_ | |||
| 180 | 180 | ||
| 181 | const std::string path = | 181 | const std::string path = |
| 182 | fmt::format("{}/shader_{:016x}{:016x}.nvdbg", dump_dir, identifier.id[0], identifier.id[1]); | 182 | fmt::format("{}/shader_{:016x}{:016x}.nvdbg", dump_dir, identifier.id[0], identifier.id[1]); |
| 183 | FileUtil::IOFile file(path, "wb"); | 183 | Common::FS::IOFile file(path, "wb"); |
| 184 | if (!file.IsOpen()) { | 184 | if (!file.IsOpen()) { |
| 185 | LOG_ERROR(Render_Vulkan, "Failed to create file {}", path); | 185 | LOG_ERROR(Render_Vulkan, "Failed to create file {}", path); |
| 186 | return; | 186 | return; |
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index 2258479f5..ae46e0444 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp | |||
| @@ -78,7 +78,7 @@ Common::DynamicLibrary OpenVulkanLibrary() { | |||
| 78 | if (!libvulkan_env || !library.Open(libvulkan_env)) { | 78 | if (!libvulkan_env || !library.Open(libvulkan_env)) { |
| 79 | // Use the libvulkan.dylib from the application bundle. | 79 | // Use the libvulkan.dylib from the application bundle. |
| 80 | const std::string filename = | 80 | const std::string filename = |
| 81 | FileUtil::GetBundleDirectory() + "/Contents/Frameworks/libvulkan.dylib"; | 81 | Common::FS::GetBundleDirectory() + "/Contents/Frameworks/libvulkan.dylib"; |
| 82 | library.Open(filename.c_str()); | 82 | library.Open(filename.c_str()); |
| 83 | } | 83 | } |
| 84 | #else | 84 | #else |
| @@ -237,8 +237,10 @@ std::string BuildCommaSeparatedExtensions(std::vector<std::string> available_ext | |||
| 237 | 237 | ||
| 238 | } // Anonymous namespace | 238 | } // Anonymous namespace |
| 239 | 239 | ||
| 240 | RendererVulkan::RendererVulkan(Core::Frontend::EmuWindow& window, Core::System& system) | 240 | RendererVulkan::RendererVulkan(Core::System& system_, Core::Frontend::EmuWindow& emu_window, |
| 241 | : RendererBase(window), system{system} {} | 241 | Tegra::GPU& gpu_, |
| 242 | std::unique_ptr<Core::Frontend::GraphicsContext> context) | ||
| 243 | : RendererBase{emu_window, std::move(context)}, system{system_}, gpu{gpu_} {} | ||
| 242 | 244 | ||
| 243 | RendererVulkan::~RendererVulkan() { | 245 | RendererVulkan::~RendererVulkan() { |
| 244 | ShutDown(); | 246 | ShutDown(); |
| @@ -439,7 +441,7 @@ void RendererVulkan::Report() const { | |||
| 439 | LOG_INFO(Render_Vulkan, "Vulkan: {}", api_version); | 441 | LOG_INFO(Render_Vulkan, "Vulkan: {}", api_version); |
| 440 | 442 | ||
| 441 | auto& telemetry_session = system.TelemetrySession(); | 443 | auto& telemetry_session = system.TelemetrySession(); |
| 442 | constexpr auto field = Telemetry::FieldType::UserSystem; | 444 | constexpr auto field = Common::Telemetry::FieldType::UserSystem; |
| 443 | telemetry_session.AddField(field, "GPU_Vendor", vendor_name); | 445 | telemetry_session.AddField(field, "GPU_Vendor", vendor_name); |
| 444 | telemetry_session.AddField(field, "GPU_Model", model_name); | 446 | telemetry_session.AddField(field, "GPU_Model", model_name); |
| 445 | telemetry_session.AddField(field, "GPU_Vulkan_Driver", driver_name); | 447 | telemetry_session.AddField(field, "GPU_Vulkan_Driver", driver_name); |
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.h b/src/video_core/renderer_vulkan/renderer_vulkan.h index 522b5bff8..13debbbc0 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.h +++ b/src/video_core/renderer_vulkan/renderer_vulkan.h | |||
| @@ -38,7 +38,9 @@ struct VKScreenInfo { | |||
| 38 | 38 | ||
| 39 | class RendererVulkan final : public VideoCore::RendererBase { | 39 | class RendererVulkan final : public VideoCore::RendererBase { |
| 40 | public: | 40 | public: |
| 41 | explicit RendererVulkan(Core::Frontend::EmuWindow& window, Core::System& system); | 41 | explicit RendererVulkan(Core::System& system, Core::Frontend::EmuWindow& emu_window, |
| 42 | Tegra::GPU& gpu, | ||
| 43 | std::unique_ptr<Core::Frontend::GraphicsContext> context); | ||
| 42 | ~RendererVulkan() override; | 44 | ~RendererVulkan() override; |
| 43 | 45 | ||
| 44 | bool Init() override; | 46 | bool Init() override; |
| @@ -58,6 +60,7 @@ private: | |||
| 58 | void Report() const; | 60 | void Report() const; |
| 59 | 61 | ||
| 60 | Core::System& system; | 62 | Core::System& system; |
| 63 | Tegra::GPU& gpu; | ||
| 61 | 64 | ||
| 62 | Common::DynamicLibrary library; | 65 | Common::DynamicLibrary library; |
| 63 | vk::InstanceDispatch dld; | 66 | vk::InstanceDispatch dld; |
diff --git a/src/video_core/renderer_vulkan/vk_device.cpp b/src/video_core/renderer_vulkan/vk_device.cpp index 0c03e4d83..4205bd573 100644 --- a/src/video_core/renderer_vulkan/vk_device.cpp +++ b/src/video_core/renderer_vulkan/vk_device.cpp | |||
| @@ -380,8 +380,18 @@ bool VKDevice::Create() { | |||
| 380 | 380 | ||
| 381 | CollectTelemetryParameters(); | 381 | CollectTelemetryParameters(); |
| 382 | 382 | ||
| 383 | if (ext_extended_dynamic_state && driver_id == VK_DRIVER_ID_AMD_PROPRIETARY_KHR) { | ||
| 384 | // AMD's proprietary driver supports VK_EXT_extended_dynamic_state but the <stride> field | ||
| 385 | // seems to be bugged. Blacklisting it for now. | ||
| 386 | LOG_WARNING(Render_Vulkan, | ||
| 387 | "Blacklisting AMD proprietary from VK_EXT_extended_dynamic_state"); | ||
| 388 | ext_extended_dynamic_state = false; | ||
| 389 | } | ||
| 390 | |||
| 383 | graphics_queue = logical.GetQueue(graphics_family); | 391 | graphics_queue = logical.GetQueue(graphics_family); |
| 384 | present_queue = logical.GetQueue(present_family); | 392 | present_queue = logical.GetQueue(present_family); |
| 393 | |||
| 394 | use_asynchronous_shaders = Settings::values.use_asynchronous_shaders.GetValue(); | ||
| 385 | return true; | 395 | return true; |
| 386 | } | 396 | } |
| 387 | 397 | ||
diff --git a/src/video_core/renderer_vulkan/vk_device.h b/src/video_core/renderer_vulkan/vk_device.h index 529744f2d..26a233db1 100644 --- a/src/video_core/renderer_vulkan/vk_device.h +++ b/src/video_core/renderer_vulkan/vk_device.h | |||
| @@ -202,6 +202,11 @@ public: | |||
| 202 | return reported_extensions; | 202 | return reported_extensions; |
| 203 | } | 203 | } |
| 204 | 204 | ||
| 205 | /// Returns true if the setting for async shader compilation is enabled. | ||
| 206 | bool UseAsynchronousShaders() const { | ||
| 207 | return use_asynchronous_shaders; | ||
| 208 | } | ||
| 209 | |||
| 205 | /// Checks if the physical device is suitable. | 210 | /// Checks if the physical device is suitable. |
| 206 | static bool IsSuitable(vk::PhysicalDevice physical, VkSurfaceKHR surface); | 211 | static bool IsSuitable(vk::PhysicalDevice physical, VkSurfaceKHR surface); |
| 207 | 212 | ||
| @@ -252,6 +257,9 @@ private: | |||
| 252 | bool ext_extended_dynamic_state{}; ///< Support for VK_EXT_extended_dynamic_state. | 257 | bool ext_extended_dynamic_state{}; ///< Support for VK_EXT_extended_dynamic_state. |
| 253 | bool nv_device_diagnostics_config{}; ///< Support for VK_NV_device_diagnostics_config. | 258 | bool nv_device_diagnostics_config{}; ///< Support for VK_NV_device_diagnostics_config. |
| 254 | 259 | ||
| 260 | // Asynchronous Graphics Pipeline setting | ||
| 261 | bool use_asynchronous_shaders{}; ///< Setting to use asynchronous shaders/graphics pipeline | ||
| 262 | |||
| 255 | // Telemetry parameters | 263 | // Telemetry parameters |
| 256 | std::string vendor_name; ///< Device's driver name. | 264 | std::string vendor_name; ///< Device's driver name. |
| 257 | std::vector<std::string> reported_extensions; ///< Reported Vulkan extensions. | 265 | std::vector<std::string> reported_extensions; ///< Reported Vulkan extensions. |
diff --git a/src/video_core/renderer_vulkan/vk_fence_manager.cpp b/src/video_core/renderer_vulkan/vk_fence_manager.cpp index a02be5487..d7f65d435 100644 --- a/src/video_core/renderer_vulkan/vk_fence_manager.cpp +++ b/src/video_core/renderer_vulkan/vk_fence_manager.cpp | |||
| @@ -29,7 +29,7 @@ void InnerFence::Queue() { | |||
| 29 | } | 29 | } |
| 30 | ASSERT(!event); | 30 | ASSERT(!event); |
| 31 | 31 | ||
| 32 | event = device.GetLogical().CreateEvent(); | 32 | event = device.GetLogical().CreateNewEvent(); |
| 33 | ticks = scheduler.Ticks(); | 33 | ticks = scheduler.Ticks(); |
| 34 | 34 | ||
| 35 | scheduler.RequestOutsideRenderPassOperationContext(); | 35 | scheduler.RequestOutsideRenderPassOperationContext(); |
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index aaf930b90..2e46c6278 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp | |||
| @@ -78,15 +78,14 @@ VKGraphicsPipeline::VKGraphicsPipeline(const VKDevice& device, VKScheduler& sche | |||
| 78 | const GraphicsPipelineCacheKey& key, | 78 | const GraphicsPipelineCacheKey& key, |
| 79 | vk::Span<VkDescriptorSetLayoutBinding> bindings, | 79 | vk::Span<VkDescriptorSetLayoutBinding> bindings, |
| 80 | const SPIRVProgram& program) | 80 | const SPIRVProgram& program) |
| 81 | : device{device}, scheduler{scheduler}, fixed_state{key.fixed_state}, hash{key.Hash()}, | 81 | : device{device}, scheduler{scheduler}, cache_key{key}, hash{cache_key.Hash()}, |
| 82 | descriptor_set_layout{CreateDescriptorSetLayout(bindings)}, | 82 | descriptor_set_layout{CreateDescriptorSetLayout(bindings)}, |
| 83 | descriptor_allocator{descriptor_pool, *descriptor_set_layout}, | 83 | descriptor_allocator{descriptor_pool, *descriptor_set_layout}, |
| 84 | update_descriptor_queue{update_descriptor_queue}, layout{CreatePipelineLayout()}, | 84 | update_descriptor_queue{update_descriptor_queue}, layout{CreatePipelineLayout()}, |
| 85 | descriptor_template{CreateDescriptorUpdateTemplate(program)}, modules{CreateShaderModules( | 85 | descriptor_template{CreateDescriptorUpdateTemplate(program)}, modules{CreateShaderModules( |
| 86 | program)}, | 86 | program)}, |
| 87 | renderpass{renderpass_cache.GetRenderPass(key.renderpass_params)}, pipeline{CreatePipeline( | 87 | renderpass{renderpass_cache.GetRenderPass(cache_key.renderpass_params)}, |
| 88 | key.renderpass_params, | 88 | pipeline{CreatePipeline(cache_key.renderpass_params, program)} {} |
| 89 | program)} {} | ||
| 90 | 89 | ||
| 91 | VKGraphicsPipeline::~VKGraphicsPipeline() = default; | 90 | VKGraphicsPipeline::~VKGraphicsPipeline() = default; |
| 92 | 91 | ||
| @@ -181,7 +180,7 @@ std::vector<vk::ShaderModule> VKGraphicsPipeline::CreateShaderModules( | |||
| 181 | 180 | ||
| 182 | vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpass_params, | 181 | vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpass_params, |
| 183 | const SPIRVProgram& program) const { | 182 | const SPIRVProgram& program) const { |
| 184 | const auto& state = fixed_state; | 183 | const auto& state = cache_key.fixed_state; |
| 185 | const auto& viewport_swizzles = state.viewport_swizzles; | 184 | const auto& viewport_swizzles = state.viewport_swizzles; |
| 186 | 185 | ||
| 187 | FixedPipelineState::DynamicState dynamic; | 186 | FixedPipelineState::DynamicState dynamic; |
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h index a1d699a6c..58aa35efd 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h | |||
| @@ -19,7 +19,27 @@ namespace Vulkan { | |||
| 19 | 19 | ||
| 20 | using Maxwell = Tegra::Engines::Maxwell3D::Regs; | 20 | using Maxwell = Tegra::Engines::Maxwell3D::Regs; |
| 21 | 21 | ||
| 22 | struct GraphicsPipelineCacheKey; | 22 | struct GraphicsPipelineCacheKey { |
| 23 | RenderPassParams renderpass_params; | ||
| 24 | u32 padding; | ||
| 25 | std::array<GPUVAddr, Maxwell::MaxShaderProgram> shaders; | ||
| 26 | FixedPipelineState fixed_state; | ||
| 27 | |||
| 28 | std::size_t Hash() const noexcept; | ||
| 29 | |||
| 30 | bool operator==(const GraphicsPipelineCacheKey& rhs) const noexcept; | ||
| 31 | |||
| 32 | bool operator!=(const GraphicsPipelineCacheKey& rhs) const noexcept { | ||
| 33 | return !operator==(rhs); | ||
| 34 | } | ||
| 35 | |||
| 36 | std::size_t Size() const noexcept { | ||
| 37 | return sizeof(renderpass_params) + sizeof(padding) + sizeof(shaders) + fixed_state.Size(); | ||
| 38 | } | ||
| 39 | }; | ||
| 40 | static_assert(std::has_unique_object_representations_v<GraphicsPipelineCacheKey>); | ||
| 41 | static_assert(std::is_trivially_copyable_v<GraphicsPipelineCacheKey>); | ||
| 42 | static_assert(std::is_trivially_constructible_v<GraphicsPipelineCacheKey>); | ||
| 23 | 43 | ||
| 24 | class VKDescriptorPool; | 44 | class VKDescriptorPool; |
| 25 | class VKDevice; | 45 | class VKDevice; |
| @@ -54,6 +74,10 @@ public: | |||
| 54 | return renderpass; | 74 | return renderpass; |
| 55 | } | 75 | } |
| 56 | 76 | ||
| 77 | GraphicsPipelineCacheKey GetCacheKey() const { | ||
| 78 | return cache_key; | ||
| 79 | } | ||
| 80 | |||
| 57 | private: | 81 | private: |
| 58 | vk::DescriptorSetLayout CreateDescriptorSetLayout( | 82 | vk::DescriptorSetLayout CreateDescriptorSetLayout( |
| 59 | vk::Span<VkDescriptorSetLayoutBinding> bindings) const; | 83 | vk::Span<VkDescriptorSetLayoutBinding> bindings) const; |
| @@ -70,7 +94,7 @@ private: | |||
| 70 | 94 | ||
| 71 | const VKDevice& device; | 95 | const VKDevice& device; |
| 72 | VKScheduler& scheduler; | 96 | VKScheduler& scheduler; |
| 73 | const FixedPipelineState fixed_state; | 97 | const GraphicsPipelineCacheKey cache_key; |
| 74 | const u64 hash; | 98 | const u64 hash; |
| 75 | 99 | ||
| 76 | vk::DescriptorSetLayout descriptor_set_layout; | 100 | vk::DescriptorSetLayout descriptor_set_layout; |
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 418c62bc4..cfdcdd6ab 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | |||
| @@ -28,6 +28,7 @@ | |||
| 28 | #include "video_core/shader/compiler_settings.h" | 28 | #include "video_core/shader/compiler_settings.h" |
| 29 | #include "video_core/shader/memory_util.h" | 29 | #include "video_core/shader/memory_util.h" |
| 30 | #include "video_core/shader_cache.h" | 30 | #include "video_core/shader_cache.h" |
| 31 | #include "video_core/shader_notify.h" | ||
| 31 | 32 | ||
| 32 | namespace Vulkan { | 33 | namespace Vulkan { |
| 33 | 34 | ||
| @@ -205,24 +206,43 @@ std::array<Shader*, Maxwell::MaxShaderProgram> VKPipelineCache::GetShaders() { | |||
| 205 | return last_shaders = shaders; | 206 | return last_shaders = shaders; |
| 206 | } | 207 | } |
| 207 | 208 | ||
| 208 | VKGraphicsPipeline& VKPipelineCache::GetGraphicsPipeline(const GraphicsPipelineCacheKey& key) { | 209 | VKGraphicsPipeline* VKPipelineCache::GetGraphicsPipeline( |
| 210 | const GraphicsPipelineCacheKey& key, VideoCommon::Shader::AsyncShaders& async_shaders) { | ||
| 209 | MICROPROFILE_SCOPE(Vulkan_PipelineCache); | 211 | MICROPROFILE_SCOPE(Vulkan_PipelineCache); |
| 210 | 212 | ||
| 211 | if (last_graphics_pipeline && last_graphics_key == key) { | 213 | if (last_graphics_pipeline && last_graphics_key == key) { |
| 212 | return *last_graphics_pipeline; | 214 | return last_graphics_pipeline; |
| 213 | } | 215 | } |
| 214 | last_graphics_key = key; | 216 | last_graphics_key = key; |
| 215 | 217 | ||
| 218 | if (device.UseAsynchronousShaders() && async_shaders.IsShaderAsync(system.GPU())) { | ||
| 219 | std::unique_lock lock{pipeline_cache}; | ||
| 220 | const auto [pair, is_cache_miss] = graphics_cache.try_emplace(key); | ||
| 221 | if (is_cache_miss) { | ||
| 222 | system.GPU().ShaderNotify().MarkSharderBuilding(); | ||
| 223 | LOG_INFO(Render_Vulkan, "Compile 0x{:016X}", key.Hash()); | ||
| 224 | const auto [program, bindings] = DecompileShaders(key.fixed_state); | ||
| 225 | async_shaders.QueueVulkanShader(this, device, scheduler, descriptor_pool, | ||
| 226 | update_descriptor_queue, renderpass_cache, bindings, | ||
| 227 | program, key); | ||
| 228 | } | ||
| 229 | last_graphics_pipeline = pair->second.get(); | ||
| 230 | return last_graphics_pipeline; | ||
| 231 | } | ||
| 232 | |||
| 216 | const auto [pair, is_cache_miss] = graphics_cache.try_emplace(key); | 233 | const auto [pair, is_cache_miss] = graphics_cache.try_emplace(key); |
| 217 | auto& entry = pair->second; | 234 | auto& entry = pair->second; |
| 218 | if (is_cache_miss) { | 235 | if (is_cache_miss) { |
| 236 | system.GPU().ShaderNotify().MarkSharderBuilding(); | ||
| 219 | LOG_INFO(Render_Vulkan, "Compile 0x{:016X}", key.Hash()); | 237 | LOG_INFO(Render_Vulkan, "Compile 0x{:016X}", key.Hash()); |
| 220 | const auto [program, bindings] = DecompileShaders(key); | 238 | const auto [program, bindings] = DecompileShaders(key.fixed_state); |
| 221 | entry = std::make_unique<VKGraphicsPipeline>(device, scheduler, descriptor_pool, | 239 | entry = std::make_unique<VKGraphicsPipeline>(device, scheduler, descriptor_pool, |
| 222 | update_descriptor_queue, renderpass_cache, key, | 240 | update_descriptor_queue, renderpass_cache, key, |
| 223 | bindings, program); | 241 | bindings, program); |
| 242 | system.GPU().ShaderNotify().MarkShaderComplete(); | ||
| 224 | } | 243 | } |
| 225 | return *(last_graphics_pipeline = entry.get()); | 244 | last_graphics_pipeline = entry.get(); |
| 245 | return last_graphics_pipeline; | ||
| 226 | } | 246 | } |
| 227 | 247 | ||
| 228 | VKComputePipeline& VKPipelineCache::GetComputePipeline(const ComputePipelineCacheKey& key) { | 248 | VKComputePipeline& VKPipelineCache::GetComputePipeline(const ComputePipelineCacheKey& key) { |
| @@ -277,6 +297,12 @@ VKComputePipeline& VKPipelineCache::GetComputePipeline(const ComputePipelineCach | |||
| 277 | return *entry; | 297 | return *entry; |
| 278 | } | 298 | } |
| 279 | 299 | ||
| 300 | void VKPipelineCache::EmplacePipeline(std::unique_ptr<VKGraphicsPipeline> pipeline) { | ||
| 301 | system.GPU().ShaderNotify().MarkShaderComplete(); | ||
| 302 | std::unique_lock lock{pipeline_cache}; | ||
| 303 | graphics_cache.at(pipeline->GetCacheKey()) = std::move(pipeline); | ||
| 304 | } | ||
| 305 | |||
| 280 | void VKPipelineCache::OnShaderRemoval(Shader* shader) { | 306 | void VKPipelineCache::OnShaderRemoval(Shader* shader) { |
| 281 | bool finished = false; | 307 | bool finished = false; |
| 282 | const auto Finish = [&] { | 308 | const auto Finish = [&] { |
| @@ -312,8 +338,7 @@ void VKPipelineCache::OnShaderRemoval(Shader* shader) { | |||
| 312 | } | 338 | } |
| 313 | 339 | ||
| 314 | std::pair<SPIRVProgram, std::vector<VkDescriptorSetLayoutBinding>> | 340 | std::pair<SPIRVProgram, std::vector<VkDescriptorSetLayoutBinding>> |
| 315 | VKPipelineCache::DecompileShaders(const GraphicsPipelineCacheKey& key) { | 341 | VKPipelineCache::DecompileShaders(const FixedPipelineState& fixed_state) { |
| 316 | const auto& fixed_state = key.fixed_state; | ||
| 317 | auto& memory_manager = system.GPU().MemoryManager(); | 342 | auto& memory_manager = system.GPU().MemoryManager(); |
| 318 | const auto& gpu = system.GPU().Maxwell3D(); | 343 | const auto& gpu = system.GPU().Maxwell3D(); |
| 319 | 344 | ||
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.h b/src/video_core/renderer_vulkan/vk_pipeline_cache.h index 0a3fe65fb..c04829e77 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.h +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.h | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include "video_core/renderer_vulkan/vk_renderpass_cache.h" | 22 | #include "video_core/renderer_vulkan/vk_renderpass_cache.h" |
| 23 | #include "video_core/renderer_vulkan/vk_shader_decompiler.h" | 23 | #include "video_core/renderer_vulkan/vk_shader_decompiler.h" |
| 24 | #include "video_core/renderer_vulkan/wrapper.h" | 24 | #include "video_core/renderer_vulkan/wrapper.h" |
| 25 | #include "video_core/shader/async_shaders.h" | ||
| 25 | #include "video_core/shader/memory_util.h" | 26 | #include "video_core/shader/memory_util.h" |
| 26 | #include "video_core/shader/registry.h" | 27 | #include "video_core/shader/registry.h" |
| 27 | #include "video_core/shader/shader_ir.h" | 28 | #include "video_core/shader/shader_ir.h" |
| @@ -43,28 +44,6 @@ class VKUpdateDescriptorQueue; | |||
| 43 | 44 | ||
| 44 | using Maxwell = Tegra::Engines::Maxwell3D::Regs; | 45 | using Maxwell = Tegra::Engines::Maxwell3D::Regs; |
| 45 | 46 | ||
| 46 | struct GraphicsPipelineCacheKey { | ||
| 47 | RenderPassParams renderpass_params; | ||
| 48 | u32 padding; | ||
| 49 | std::array<GPUVAddr, Maxwell::MaxShaderProgram> shaders; | ||
| 50 | FixedPipelineState fixed_state; | ||
| 51 | |||
| 52 | std::size_t Hash() const noexcept; | ||
| 53 | |||
| 54 | bool operator==(const GraphicsPipelineCacheKey& rhs) const noexcept; | ||
| 55 | |||
| 56 | bool operator!=(const GraphicsPipelineCacheKey& rhs) const noexcept { | ||
| 57 | return !operator==(rhs); | ||
| 58 | } | ||
| 59 | |||
| 60 | std::size_t Size() const noexcept { | ||
| 61 | return sizeof(renderpass_params) + sizeof(padding) + sizeof(shaders) + fixed_state.Size(); | ||
| 62 | } | ||
| 63 | }; | ||
| 64 | static_assert(std::has_unique_object_representations_v<GraphicsPipelineCacheKey>); | ||
| 65 | static_assert(std::is_trivially_copyable_v<GraphicsPipelineCacheKey>); | ||
| 66 | static_assert(std::is_trivially_constructible_v<GraphicsPipelineCacheKey>); | ||
| 67 | |||
| 68 | struct ComputePipelineCacheKey { | 47 | struct ComputePipelineCacheKey { |
| 69 | GPUVAddr shader; | 48 | GPUVAddr shader; |
| 70 | u32 shared_memory_size; | 49 | u32 shared_memory_size; |
| @@ -152,16 +131,19 @@ public: | |||
| 152 | 131 | ||
| 153 | std::array<Shader*, Maxwell::MaxShaderProgram> GetShaders(); | 132 | std::array<Shader*, Maxwell::MaxShaderProgram> GetShaders(); |
| 154 | 133 | ||
| 155 | VKGraphicsPipeline& GetGraphicsPipeline(const GraphicsPipelineCacheKey& key); | 134 | VKGraphicsPipeline* GetGraphicsPipeline(const GraphicsPipelineCacheKey& key, |
| 135 | VideoCommon::Shader::AsyncShaders& async_shaders); | ||
| 156 | 136 | ||
| 157 | VKComputePipeline& GetComputePipeline(const ComputePipelineCacheKey& key); | 137 | VKComputePipeline& GetComputePipeline(const ComputePipelineCacheKey& key); |
| 158 | 138 | ||
| 139 | void EmplacePipeline(std::unique_ptr<VKGraphicsPipeline> pipeline); | ||
| 140 | |||
| 159 | protected: | 141 | protected: |
| 160 | void OnShaderRemoval(Shader* shader) final; | 142 | void OnShaderRemoval(Shader* shader) final; |
| 161 | 143 | ||
| 162 | private: | 144 | private: |
| 163 | std::pair<SPIRVProgram, std::vector<VkDescriptorSetLayoutBinding>> DecompileShaders( | 145 | std::pair<SPIRVProgram, std::vector<VkDescriptorSetLayoutBinding>> DecompileShaders( |
| 164 | const GraphicsPipelineCacheKey& key); | 146 | const FixedPipelineState& fixed_state); |
| 165 | 147 | ||
| 166 | Core::System& system; | 148 | Core::System& system; |
| 167 | const VKDevice& device; | 149 | const VKDevice& device; |
| @@ -178,6 +160,7 @@ private: | |||
| 178 | GraphicsPipelineCacheKey last_graphics_key; | 160 | GraphicsPipelineCacheKey last_graphics_key; |
| 179 | VKGraphicsPipeline* last_graphics_pipeline = nullptr; | 161 | VKGraphicsPipeline* last_graphics_pipeline = nullptr; |
| 180 | 162 | ||
| 163 | std::mutex pipeline_cache; | ||
| 181 | std::unordered_map<GraphicsPipelineCacheKey, std::unique_ptr<VKGraphicsPipeline>> | 164 | std::unordered_map<GraphicsPipelineCacheKey, std::unique_ptr<VKGraphicsPipeline>> |
| 182 | graphics_cache; | 165 | graphics_cache; |
| 183 | std::unordered_map<ComputePipelineCacheKey, std::unique_ptr<VKComputePipeline>> compute_cache; | 166 | std::unordered_map<ComputePipelineCacheKey, std::unique_ptr<VKComputePipeline>> compute_cache; |
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 7500e8244..ff1b52eab 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include "common/assert.h" | 14 | #include "common/assert.h" |
| 15 | #include "common/logging/log.h" | 15 | #include "common/logging/log.h" |
| 16 | #include "common/microprofile.h" | 16 | #include "common/microprofile.h" |
| 17 | #include "common/scope_exit.h" | ||
| 17 | #include "core/core.h" | 18 | #include "core/core.h" |
| 18 | #include "core/settings.h" | 19 | #include "core/settings.h" |
| 19 | #include "video_core/engines/kepler_compute.h" | 20 | #include "video_core/engines/kepler_compute.h" |
| @@ -400,8 +401,12 @@ RasterizerVulkan::RasterizerVulkan(Core::System& system, Core::Frontend::EmuWind | |||
| 400 | buffer_cache(*this, system, device, memory_manager, scheduler, staging_pool), | 401 | buffer_cache(*this, system, device, memory_manager, scheduler, staging_pool), |
| 401 | sampler_cache(device), | 402 | sampler_cache(device), |
| 402 | fence_manager(system, *this, device, scheduler, texture_cache, buffer_cache, query_cache), | 403 | fence_manager(system, *this, device, scheduler, texture_cache, buffer_cache, query_cache), |
| 403 | query_cache(system, *this, device, scheduler), wfi_event{device.GetLogical().CreateEvent()} { | 404 | query_cache(system, *this, device, scheduler), |
| 405 | wfi_event{device.GetLogical().CreateNewEvent()}, async_shaders{renderer} { | ||
| 404 | scheduler.SetQueryCache(query_cache); | 406 | scheduler.SetQueryCache(query_cache); |
| 407 | if (device.UseAsynchronousShaders()) { | ||
| 408 | async_shaders.AllocateWorkers(); | ||
| 409 | } | ||
| 405 | } | 410 | } |
| 406 | 411 | ||
| 407 | RasterizerVulkan::~RasterizerVulkan() = default; | 412 | RasterizerVulkan::~RasterizerVulkan() = default; |
| @@ -413,6 +418,8 @@ void RasterizerVulkan::Draw(bool is_indexed, bool is_instanced) { | |||
| 413 | 418 | ||
| 414 | query_cache.UpdateCounters(); | 419 | query_cache.UpdateCounters(); |
| 415 | 420 | ||
| 421 | SCOPE_EXIT({ system.GPU().TickWork(); }); | ||
| 422 | |||
| 416 | const auto& gpu = system.GPU().Maxwell3D(); | 423 | const auto& gpu = system.GPU().Maxwell3D(); |
| 417 | GraphicsPipelineCacheKey key; | 424 | GraphicsPipelineCacheKey key; |
| 418 | key.fixed_state.Fill(gpu.regs, device.IsExtExtendedDynamicStateSupported()); | 425 | key.fixed_state.Fill(gpu.regs, device.IsExtExtendedDynamicStateSupported()); |
| @@ -439,10 +446,15 @@ void RasterizerVulkan::Draw(bool is_indexed, bool is_instanced) { | |||
| 439 | key.renderpass_params = GetRenderPassParams(texceptions); | 446 | key.renderpass_params = GetRenderPassParams(texceptions); |
| 440 | key.padding = 0; | 447 | key.padding = 0; |
| 441 | 448 | ||
| 442 | auto& pipeline = pipeline_cache.GetGraphicsPipeline(key); | 449 | auto* pipeline = pipeline_cache.GetGraphicsPipeline(key, async_shaders); |
| 443 | scheduler.BindGraphicsPipeline(pipeline.GetHandle()); | 450 | if (pipeline == nullptr || pipeline->GetHandle() == VK_NULL_HANDLE) { |
| 451 | // Async graphics pipeline was not ready. | ||
| 452 | return; | ||
| 453 | } | ||
| 454 | |||
| 455 | scheduler.BindGraphicsPipeline(pipeline->GetHandle()); | ||
| 444 | 456 | ||
| 445 | const auto renderpass = pipeline.GetRenderPass(); | 457 | const auto renderpass = pipeline->GetRenderPass(); |
| 446 | const auto [framebuffer, render_area] = ConfigureFramebuffers(renderpass); | 458 | const auto [framebuffer, render_area] = ConfigureFramebuffers(renderpass); |
| 447 | scheduler.RequestRenderpass(renderpass, framebuffer, render_area); | 459 | scheduler.RequestRenderpass(renderpass, framebuffer, render_area); |
| 448 | 460 | ||
| @@ -452,8 +464,8 @@ void RasterizerVulkan::Draw(bool is_indexed, bool is_instanced) { | |||
| 452 | 464 | ||
| 453 | BeginTransformFeedback(); | 465 | BeginTransformFeedback(); |
| 454 | 466 | ||
| 455 | const auto pipeline_layout = pipeline.GetLayout(); | 467 | const auto pipeline_layout = pipeline->GetLayout(); |
| 456 | const auto descriptor_set = pipeline.CommitDescriptorSet(); | 468 | const auto descriptor_set = pipeline->CommitDescriptorSet(); |
| 457 | scheduler.Record([pipeline_layout, descriptor_set, draw_params](vk::CommandBuffer cmdbuf) { | 469 | scheduler.Record([pipeline_layout, descriptor_set, draw_params](vk::CommandBuffer cmdbuf) { |
| 458 | if (descriptor_set) { | 470 | if (descriptor_set) { |
| 459 | cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, | 471 | cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, |
| @@ -463,8 +475,6 @@ void RasterizerVulkan::Draw(bool is_indexed, bool is_instanced) { | |||
| 463 | }); | 475 | }); |
| 464 | 476 | ||
| 465 | EndTransformFeedback(); | 477 | EndTransformFeedback(); |
| 466 | |||
| 467 | system.GPU().TickWork(); | ||
| 468 | } | 478 | } |
| 469 | 479 | ||
| 470 | void RasterizerVulkan::Clear() { | 480 | void RasterizerVulkan::Clear() { |
| @@ -1433,10 +1443,10 @@ void RasterizerVulkan::UpdateFrontFace(Tegra::Engines::Maxwell3D::Regs& regs) { | |||
| 1433 | } | 1443 | } |
| 1434 | 1444 | ||
| 1435 | void RasterizerVulkan::UpdatePrimitiveTopology(Tegra::Engines::Maxwell3D::Regs& regs) { | 1445 | void RasterizerVulkan::UpdatePrimitiveTopology(Tegra::Engines::Maxwell3D::Regs& regs) { |
| 1436 | if (!state_tracker.TouchPrimitiveTopology()) { | 1446 | const Maxwell::PrimitiveTopology primitive_topology = regs.draw.topology.Value(); |
| 1447 | if (!state_tracker.ChangePrimitiveTopology(primitive_topology)) { | ||
| 1437 | return; | 1448 | return; |
| 1438 | } | 1449 | } |
| 1439 | const Maxwell::PrimitiveTopology primitive_topology = regs.draw.topology.Value(); | ||
| 1440 | scheduler.Record([this, primitive_topology](vk::CommandBuffer cmdbuf) { | 1450 | scheduler.Record([this, primitive_topology](vk::CommandBuffer cmdbuf) { |
| 1441 | cmdbuf.SetPrimitiveTopologyEXT(MaxwellToVK::PrimitiveTopology(device, primitive_topology)); | 1451 | cmdbuf.SetPrimitiveTopologyEXT(MaxwellToVK::PrimitiveTopology(device, primitive_topology)); |
| 1442 | }); | 1452 | }); |
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h index 923178b0b..f640ba649 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.h +++ b/src/video_core/renderer_vulkan/vk_rasterizer.h | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #include "video_core/renderer_vulkan/vk_texture_cache.h" | 32 | #include "video_core/renderer_vulkan/vk_texture_cache.h" |
| 33 | #include "video_core/renderer_vulkan/vk_update_descriptor.h" | 33 | #include "video_core/renderer_vulkan/vk_update_descriptor.h" |
| 34 | #include "video_core/renderer_vulkan/wrapper.h" | 34 | #include "video_core/renderer_vulkan/wrapper.h" |
| 35 | #include "video_core/shader/async_shaders.h" | ||
| 35 | 36 | ||
| 36 | namespace Core { | 37 | namespace Core { |
| 37 | class System; | 38 | class System; |
| @@ -136,6 +137,14 @@ public: | |||
| 136 | u32 pixel_stride) override; | 137 | u32 pixel_stride) override; |
| 137 | void SetupDirtyFlags() override; | 138 | void SetupDirtyFlags() override; |
| 138 | 139 | ||
| 140 | VideoCommon::Shader::AsyncShaders& GetAsyncShaders() { | ||
| 141 | return async_shaders; | ||
| 142 | } | ||
| 143 | |||
| 144 | const VideoCommon::Shader::AsyncShaders& GetAsyncShaders() const { | ||
| 145 | return async_shaders; | ||
| 146 | } | ||
| 147 | |||
| 139 | /// Maximum supported size that a constbuffer can have in bytes. | 148 | /// Maximum supported size that a constbuffer can have in bytes. |
| 140 | static constexpr std::size_t MaxConstbufferSize = 0x10000; | 149 | static constexpr std::size_t MaxConstbufferSize = 0x10000; |
| 141 | static_assert(MaxConstbufferSize % (4 * sizeof(float)) == 0, | 150 | static_assert(MaxConstbufferSize % (4 * sizeof(float)) == 0, |
| @@ -297,6 +306,7 @@ private: | |||
| 297 | vk::Buffer default_buffer; | 306 | vk::Buffer default_buffer; |
| 298 | VKMemoryCommit default_buffer_commit; | 307 | VKMemoryCommit default_buffer_commit; |
| 299 | vk::Event wfi_event; | 308 | vk::Event wfi_event; |
| 309 | VideoCommon::Shader::AsyncShaders async_shaders; | ||
| 300 | 310 | ||
| 301 | std::array<View, Maxwell::NumRenderTargets> color_attachments; | 311 | std::array<View, Maxwell::NumRenderTargets> color_attachments; |
| 302 | View zeta_attachment; | 312 | View zeta_attachment; |
diff --git a/src/video_core/renderer_vulkan/vk_state_tracker.cpp b/src/video_core/renderer_vulkan/vk_state_tracker.cpp index 9151d9fb1..4bd1009f9 100644 --- a/src/video_core/renderer_vulkan/vk_state_tracker.cpp +++ b/src/video_core/renderer_vulkan/vk_state_tracker.cpp | |||
| @@ -42,7 +42,6 @@ Flags MakeInvalidationFlags() { | |||
| 42 | flags[DepthWriteEnable] = true; | 42 | flags[DepthWriteEnable] = true; |
| 43 | flags[DepthCompareOp] = true; | 43 | flags[DepthCompareOp] = true; |
| 44 | flags[FrontFace] = true; | 44 | flags[FrontFace] = true; |
| 45 | flags[PrimitiveTopology] = true; | ||
| 46 | flags[StencilOp] = true; | 45 | flags[StencilOp] = true; |
| 47 | flags[StencilTestEnable] = true; | 46 | flags[StencilTestEnable] = true; |
| 48 | return flags; | 47 | return flags; |
| @@ -112,10 +111,6 @@ void SetupDirtyFrontFace(Tables& tables) { | |||
| 112 | table[OFF(screen_y_control)] = FrontFace; | 111 | table[OFF(screen_y_control)] = FrontFace; |
| 113 | } | 112 | } |
| 114 | 113 | ||
| 115 | void SetupDirtyPrimitiveTopology(Tables& tables) { | ||
| 116 | tables[0][OFF(draw.topology)] = PrimitiveTopology; | ||
| 117 | } | ||
| 118 | |||
| 119 | void SetupDirtyStencilOp(Tables& tables) { | 114 | void SetupDirtyStencilOp(Tables& tables) { |
| 120 | auto& table = tables[0]; | 115 | auto& table = tables[0]; |
| 121 | table[OFF(stencil_front_op_fail)] = StencilOp; | 116 | table[OFF(stencil_front_op_fail)] = StencilOp; |
| @@ -156,13 +151,13 @@ void StateTracker::Initialize() { | |||
| 156 | SetupDirtyDepthWriteEnable(tables); | 151 | SetupDirtyDepthWriteEnable(tables); |
| 157 | SetupDirtyDepthCompareOp(tables); | 152 | SetupDirtyDepthCompareOp(tables); |
| 158 | SetupDirtyFrontFace(tables); | 153 | SetupDirtyFrontFace(tables); |
| 159 | SetupDirtyPrimitiveTopology(tables); | ||
| 160 | SetupDirtyStencilOp(tables); | 154 | SetupDirtyStencilOp(tables); |
| 161 | SetupDirtyStencilTestEnable(tables); | 155 | SetupDirtyStencilTestEnable(tables); |
| 162 | } | 156 | } |
| 163 | 157 | ||
| 164 | void StateTracker::InvalidateCommandBufferState() { | 158 | void StateTracker::InvalidateCommandBufferState() { |
| 165 | system.GPU().Maxwell3D().dirty.flags |= invalidation_flags; | 159 | system.GPU().Maxwell3D().dirty.flags |= invalidation_flags; |
| 160 | current_topology = INVALID_TOPOLOGY; | ||
| 166 | } | 161 | } |
| 167 | 162 | ||
| 168 | } // namespace Vulkan | 163 | } // namespace Vulkan |
diff --git a/src/video_core/renderer_vulkan/vk_state_tracker.h b/src/video_core/renderer_vulkan/vk_state_tracker.h index 54ca0d6c6..13a6ce786 100644 --- a/src/video_core/renderer_vulkan/vk_state_tracker.h +++ b/src/video_core/renderer_vulkan/vk_state_tracker.h | |||
| @@ -32,7 +32,6 @@ enum : u8 { | |||
| 32 | DepthWriteEnable, | 32 | DepthWriteEnable, |
| 33 | DepthCompareOp, | 33 | DepthCompareOp, |
| 34 | FrontFace, | 34 | FrontFace, |
| 35 | PrimitiveTopology, | ||
| 36 | StencilOp, | 35 | StencilOp, |
| 37 | StencilTestEnable, | 36 | StencilTestEnable, |
| 38 | 37 | ||
| @@ -43,6 +42,8 @@ static_assert(Last <= std::numeric_limits<u8>::max()); | |||
| 43 | } // namespace Dirty | 42 | } // namespace Dirty |
| 44 | 43 | ||
| 45 | class StateTracker { | 44 | class StateTracker { |
| 45 | using Maxwell = Tegra::Engines::Maxwell3D::Regs; | ||
| 46 | |||
| 46 | public: | 47 | public: |
| 47 | explicit StateTracker(Core::System& system); | 48 | explicit StateTracker(Core::System& system); |
| 48 | 49 | ||
| @@ -102,10 +103,6 @@ public: | |||
| 102 | return Exchange(Dirty::FrontFace, false); | 103 | return Exchange(Dirty::FrontFace, false); |
| 103 | } | 104 | } |
| 104 | 105 | ||
| 105 | bool TouchPrimitiveTopology() { | ||
| 106 | return Exchange(Dirty::PrimitiveTopology, false); | ||
| 107 | } | ||
| 108 | |||
| 109 | bool TouchStencilOp() { | 106 | bool TouchStencilOp() { |
| 110 | return Exchange(Dirty::StencilOp, false); | 107 | return Exchange(Dirty::StencilOp, false); |
| 111 | } | 108 | } |
| @@ -114,7 +111,15 @@ public: | |||
| 114 | return Exchange(Dirty::StencilTestEnable, false); | 111 | return Exchange(Dirty::StencilTestEnable, false); |
| 115 | } | 112 | } |
| 116 | 113 | ||
| 114 | bool ChangePrimitiveTopology(Maxwell::PrimitiveTopology new_topology) { | ||
| 115 | const bool has_changed = current_topology != new_topology; | ||
| 116 | current_topology = new_topology; | ||
| 117 | return has_changed; | ||
| 118 | } | ||
| 119 | |||
| 117 | private: | 120 | private: |
| 121 | static constexpr auto INVALID_TOPOLOGY = static_cast<Maxwell::PrimitiveTopology>(~0u); | ||
| 122 | |||
| 118 | bool Exchange(std::size_t id, bool new_value) const noexcept { | 123 | bool Exchange(std::size_t id, bool new_value) const noexcept { |
| 119 | auto& flags = system.GPU().Maxwell3D().dirty.flags; | 124 | auto& flags = system.GPU().Maxwell3D().dirty.flags; |
| 120 | const bool is_dirty = flags[id]; | 125 | const bool is_dirty = flags[id]; |
| @@ -124,6 +129,7 @@ private: | |||
| 124 | 129 | ||
| 125 | Core::System& system; | 130 | Core::System& system; |
| 126 | Tegra::Engines::Maxwell3D::DirtyState::Flags invalidation_flags; | 131 | Tegra::Engines::Maxwell3D::DirtyState::Flags invalidation_flags; |
| 132 | Maxwell::PrimitiveTopology current_topology = INVALID_TOPOLOGY; | ||
| 127 | }; | 133 | }; |
| 128 | 134 | ||
| 129 | } // namespace Vulkan | 135 | } // namespace Vulkan |
diff --git a/src/video_core/renderer_vulkan/wrapper.cpp b/src/video_core/renderer_vulkan/wrapper.cpp index 14cac38ea..013865aa4 100644 --- a/src/video_core/renderer_vulkan/wrapper.cpp +++ b/src/video_core/renderer_vulkan/wrapper.cpp | |||
| @@ -644,7 +644,7 @@ ShaderModule Device::CreateShaderModule(const VkShaderModuleCreateInfo& ci) cons | |||
| 644 | return ShaderModule(object, handle, *dld); | 644 | return ShaderModule(object, handle, *dld); |
| 645 | } | 645 | } |
| 646 | 646 | ||
| 647 | Event Device::CreateEvent() const { | 647 | Event Device::CreateNewEvent() const { |
| 648 | static constexpr VkEventCreateInfo ci{ | 648 | static constexpr VkEventCreateInfo ci{ |
| 649 | .sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO, | 649 | .sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO, |
| 650 | .pNext = nullptr, | 650 | .pNext = nullptr, |
| @@ -786,7 +786,7 @@ std::optional<std::vector<VkExtensionProperties>> EnumerateInstanceExtensionProp | |||
| 786 | VK_SUCCESS) { | 786 | VK_SUCCESS) { |
| 787 | return std::nullopt; | 787 | return std::nullopt; |
| 788 | } | 788 | } |
| 789 | return properties; | 789 | return std::move(properties); |
| 790 | } | 790 | } |
| 791 | 791 | ||
| 792 | std::optional<std::vector<VkLayerProperties>> EnumerateInstanceLayerProperties( | 792 | std::optional<std::vector<VkLayerProperties>> EnumerateInstanceLayerProperties( |
diff --git a/src/video_core/renderer_vulkan/wrapper.h b/src/video_core/renderer_vulkan/wrapper.h index 71daac9d7..b9d3fedc1 100644 --- a/src/video_core/renderer_vulkan/wrapper.h +++ b/src/video_core/renderer_vulkan/wrapper.h | |||
| @@ -721,7 +721,7 @@ public: | |||
| 721 | 721 | ||
| 722 | ShaderModule CreateShaderModule(const VkShaderModuleCreateInfo& ci) const; | 722 | ShaderModule CreateShaderModule(const VkShaderModuleCreateInfo& ci) const; |
| 723 | 723 | ||
| 724 | Event CreateEvent() const; | 724 | Event CreateNewEvent() const; |
| 725 | 725 | ||
| 726 | SwapchainKHR CreateSwapchainKHR(const VkSwapchainCreateInfoKHR& ci) const; | 726 | SwapchainKHR CreateSwapchainKHR(const VkSwapchainCreateInfoKHR& ci) const; |
| 727 | 727 | ||
| @@ -756,8 +756,8 @@ public: | |||
| 756 | } | 756 | } |
| 757 | 757 | ||
| 758 | VkResult GetQueryResults(VkQueryPool query_pool, u32 first, u32 count, std::size_t data_size, | 758 | VkResult GetQueryResults(VkQueryPool query_pool, u32 first, u32 count, std::size_t data_size, |
| 759 | void* data, VkDeviceSize stride, VkQueryResultFlags flags) const | 759 | void* data, VkDeviceSize stride, |
| 760 | noexcept { | 760 | VkQueryResultFlags flags) const noexcept { |
| 761 | return dld->vkGetQueryPoolResults(handle, query_pool, first, count, data_size, data, stride, | 761 | return dld->vkGetQueryPoolResults(handle, query_pool, first, count, data_size, data, stride, |
| 762 | flags); | 762 | flags); |
| 763 | } | 763 | } |
| @@ -849,8 +849,8 @@ public: | |||
| 849 | dld->vkCmdBindPipeline(handle, bind_point, pipeline); | 849 | dld->vkCmdBindPipeline(handle, bind_point, pipeline); |
| 850 | } | 850 | } |
| 851 | 851 | ||
| 852 | void BindIndexBuffer(VkBuffer buffer, VkDeviceSize offset, VkIndexType index_type) const | 852 | void BindIndexBuffer(VkBuffer buffer, VkDeviceSize offset, |
| 853 | noexcept { | 853 | VkIndexType index_type) const noexcept { |
| 854 | dld->vkCmdBindIndexBuffer(handle, buffer, offset, index_type); | 854 | dld->vkCmdBindIndexBuffer(handle, buffer, offset, index_type); |
| 855 | } | 855 | } |
| 856 | 856 | ||
| @@ -863,8 +863,8 @@ public: | |||
| 863 | BindVertexBuffers(binding, 1, &buffer, &offset); | 863 | BindVertexBuffers(binding, 1, &buffer, &offset); |
| 864 | } | 864 | } |
| 865 | 865 | ||
| 866 | void Draw(u32 vertex_count, u32 instance_count, u32 first_vertex, u32 first_instance) const | 866 | void Draw(u32 vertex_count, u32 instance_count, u32 first_vertex, |
| 867 | noexcept { | 867 | u32 first_instance) const noexcept { |
| 868 | dld->vkCmdDraw(handle, vertex_count, instance_count, first_vertex, first_instance); | 868 | dld->vkCmdDraw(handle, vertex_count, instance_count, first_vertex, first_instance); |
| 869 | } | 869 | } |
| 870 | 870 | ||
| @@ -874,15 +874,15 @@ public: | |||
| 874 | first_instance); | 874 | first_instance); |
| 875 | } | 875 | } |
| 876 | 876 | ||
| 877 | void ClearAttachments(Span<VkClearAttachment> attachments, Span<VkClearRect> rects) const | 877 | void ClearAttachments(Span<VkClearAttachment> attachments, |
| 878 | noexcept { | 878 | Span<VkClearRect> rects) const noexcept { |
| 879 | dld->vkCmdClearAttachments(handle, attachments.size(), attachments.data(), rects.size(), | 879 | dld->vkCmdClearAttachments(handle, attachments.size(), attachments.data(), rects.size(), |
| 880 | rects.data()); | 880 | rects.data()); |
| 881 | } | 881 | } |
| 882 | 882 | ||
| 883 | void BlitImage(VkImage src_image, VkImageLayout src_layout, VkImage dst_image, | 883 | void BlitImage(VkImage src_image, VkImageLayout src_layout, VkImage dst_image, |
| 884 | VkImageLayout dst_layout, Span<VkImageBlit> regions, VkFilter filter) const | 884 | VkImageLayout dst_layout, Span<VkImageBlit> regions, |
| 885 | noexcept { | 885 | VkFilter filter) const noexcept { |
| 886 | dld->vkCmdBlitImage(handle, src_image, src_layout, dst_image, dst_layout, regions.size(), | 886 | dld->vkCmdBlitImage(handle, src_image, src_layout, dst_image, dst_layout, regions.size(), |
| 887 | regions.data(), filter); | 887 | regions.data(), filter); |
| 888 | } | 888 | } |
| @@ -907,8 +907,8 @@ public: | |||
| 907 | regions.data()); | 907 | regions.data()); |
| 908 | } | 908 | } |
| 909 | 909 | ||
| 910 | void CopyBuffer(VkBuffer src_buffer, VkBuffer dst_buffer, Span<VkBufferCopy> regions) const | 910 | void CopyBuffer(VkBuffer src_buffer, VkBuffer dst_buffer, |
| 911 | noexcept { | 911 | Span<VkBufferCopy> regions) const noexcept { |
| 912 | dld->vkCmdCopyBuffer(handle, src_buffer, dst_buffer, regions.size(), regions.data()); | 912 | dld->vkCmdCopyBuffer(handle, src_buffer, dst_buffer, regions.size(), regions.data()); |
| 913 | } | 913 | } |
| 914 | 914 | ||
| @@ -924,8 +924,8 @@ public: | |||
| 924 | regions.data()); | 924 | regions.data()); |
| 925 | } | 925 | } |
| 926 | 926 | ||
| 927 | void FillBuffer(VkBuffer dst_buffer, VkDeviceSize dst_offset, VkDeviceSize size, u32 data) const | 927 | void FillBuffer(VkBuffer dst_buffer, VkDeviceSize dst_offset, VkDeviceSize size, |
| 928 | noexcept { | 928 | u32 data) const noexcept { |
| 929 | dld->vkCmdFillBuffer(handle, dst_buffer, dst_offset, size, data); | 929 | dld->vkCmdFillBuffer(handle, dst_buffer, dst_offset, size, data); |
| 930 | } | 930 | } |
| 931 | 931 | ||
diff --git a/src/video_core/shader/async_shaders.cpp b/src/video_core/shader/async_shaders.cpp index b7f66d7ee..f815584f7 100644 --- a/src/video_core/shader/async_shaders.cpp +++ b/src/video_core/shader/async_shaders.cpp | |||
| @@ -2,7 +2,6 @@ | |||
| 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 <chrono> | ||
| 6 | #include <condition_variable> | 5 | #include <condition_variable> |
| 7 | #include <mutex> | 6 | #include <mutex> |
| 8 | #include <thread> | 7 | #include <thread> |
| @@ -20,9 +19,18 @@ AsyncShaders::~AsyncShaders() { | |||
| 20 | KillWorkers(); | 19 | KillWorkers(); |
| 21 | } | 20 | } |
| 22 | 21 | ||
| 23 | void AsyncShaders::AllocateWorkers(std::size_t num_workers) { | 22 | void AsyncShaders::AllocateWorkers() { |
| 24 | // If we're already have workers queued or don't want to queue workers, ignore | 23 | // Max worker threads we should allow |
| 25 | if (num_workers == worker_threads.size() || num_workers == 0) { | 24 | constexpr u32 MAX_THREADS = 4; |
| 25 | // Deduce how many threads we can use | ||
| 26 | const u32 threads_used = std::thread::hardware_concurrency() / 4; | ||
| 27 | // Always allow at least 1 thread regardless of our settings | ||
| 28 | const auto max_worker_count = std::max(1U, threads_used); | ||
| 29 | // Don't use more than MAX_THREADS | ||
| 30 | const auto num_workers = std::min(max_worker_count, MAX_THREADS); | ||
| 31 | |||
| 32 | // If we already have workers queued, ignore | ||
| 33 | if (num_workers == worker_threads.size()) { | ||
| 26 | return; | 34 | return; |
| 27 | } | 35 | } |
| 28 | 36 | ||
| @@ -34,8 +42,8 @@ void AsyncShaders::AllocateWorkers(std::size_t num_workers) { | |||
| 34 | // Create workers | 42 | // Create workers |
| 35 | for (std::size_t i = 0; i < num_workers; i++) { | 43 | for (std::size_t i = 0; i < num_workers; i++) { |
| 36 | context_list.push_back(emu_window.CreateSharedContext()); | 44 | context_list.push_back(emu_window.CreateSharedContext()); |
| 37 | worker_threads.push_back(std::move( | 45 | worker_threads.push_back( |
| 38 | std::thread(&AsyncShaders::ShaderCompilerThread, this, context_list[i].get()))); | 46 | std::thread(&AsyncShaders::ShaderCompilerThread, this, context_list[i].get())); |
| 39 | } | 47 | } |
| 40 | } | 48 | } |
| 41 | 49 | ||
| @@ -111,24 +119,50 @@ void AsyncShaders::QueueOpenGLShader(const OpenGL::Device& device, | |||
| 111 | VideoCommon::Shader::CompilerSettings compiler_settings, | 119 | VideoCommon::Shader::CompilerSettings compiler_settings, |
| 112 | const VideoCommon::Shader::Registry& registry, | 120 | const VideoCommon::Shader::Registry& registry, |
| 113 | VAddr cpu_addr) { | 121 | VAddr cpu_addr) { |
| 114 | WorkerParams params{device.UseAssemblyShaders() ? AsyncShaders::Backend::GLASM | 122 | WorkerParams params{ |
| 115 | : AsyncShaders::Backend::OpenGL, | 123 | .backend = device.UseAssemblyShaders() ? Backend::GLASM : Backend::OpenGL, |
| 116 | device, | 124 | .device = &device, |
| 117 | shader_type, | 125 | .shader_type = shader_type, |
| 118 | uid, | 126 | .uid = uid, |
| 119 | std::move(code), | 127 | .code = std::move(code), |
| 120 | std::move(code_b), | 128 | .code_b = std::move(code_b), |
| 121 | main_offset, | 129 | .main_offset = main_offset, |
| 122 | compiler_settings, | 130 | .compiler_settings = compiler_settings, |
| 123 | registry, | 131 | .registry = registry, |
| 124 | cpu_addr}; | 132 | .cpu_address = cpu_addr, |
| 133 | }; | ||
| 125 | std::unique_lock lock(queue_mutex); | 134 | std::unique_lock lock(queue_mutex); |
| 126 | pending_queue.push_back(std::move(params)); | 135 | pending_queue.push(std::move(params)); |
| 136 | cv.notify_one(); | ||
| 137 | } | ||
| 138 | |||
| 139 | void AsyncShaders::QueueVulkanShader(Vulkan::VKPipelineCache* pp_cache, | ||
| 140 | const Vulkan::VKDevice& device, Vulkan::VKScheduler& scheduler, | ||
| 141 | Vulkan::VKDescriptorPool& descriptor_pool, | ||
| 142 | Vulkan::VKUpdateDescriptorQueue& update_descriptor_queue, | ||
| 143 | Vulkan::VKRenderPassCache& renderpass_cache, | ||
| 144 | std::vector<VkDescriptorSetLayoutBinding> bindings, | ||
| 145 | Vulkan::SPIRVProgram program, | ||
| 146 | Vulkan::GraphicsPipelineCacheKey key) { | ||
| 147 | WorkerParams params{ | ||
| 148 | .backend = Backend::Vulkan, | ||
| 149 | .pp_cache = pp_cache, | ||
| 150 | .vk_device = &device, | ||
| 151 | .scheduler = &scheduler, | ||
| 152 | .descriptor_pool = &descriptor_pool, | ||
| 153 | .update_descriptor_queue = &update_descriptor_queue, | ||
| 154 | .renderpass_cache = &renderpass_cache, | ||
| 155 | .bindings = bindings, | ||
| 156 | .program = program, | ||
| 157 | .key = key, | ||
| 158 | }; | ||
| 159 | |||
| 160 | std::unique_lock lock(queue_mutex); | ||
| 161 | pending_queue.push(std::move(params)); | ||
| 127 | cv.notify_one(); | 162 | cv.notify_one(); |
| 128 | } | 163 | } |
| 129 | 164 | ||
| 130 | void AsyncShaders::ShaderCompilerThread(Core::Frontend::GraphicsContext* context) { | 165 | void AsyncShaders::ShaderCompilerThread(Core::Frontend::GraphicsContext* context) { |
| 131 | using namespace std::chrono_literals; | ||
| 132 | while (!is_thread_exiting.load(std::memory_order_relaxed)) { | 166 | while (!is_thread_exiting.load(std::memory_order_relaxed)) { |
| 133 | std::unique_lock lock{queue_mutex}; | 167 | std::unique_lock lock{queue_mutex}; |
| 134 | cv.wait(lock, [this] { return HasWorkQueued() || is_thread_exiting; }); | 168 | cv.wait(lock, [this] { return HasWorkQueued() || is_thread_exiting; }); |
| @@ -144,18 +178,17 @@ void AsyncShaders::ShaderCompilerThread(Core::Frontend::GraphicsContext* context | |||
| 144 | if (pending_queue.empty()) { | 178 | if (pending_queue.empty()) { |
| 145 | continue; | 179 | continue; |
| 146 | } | 180 | } |
| 181 | |||
| 147 | // Pull work from queue | 182 | // Pull work from queue |
| 148 | WorkerParams work = std::move(pending_queue.front()); | 183 | WorkerParams work = std::move(pending_queue.front()); |
| 149 | pending_queue.pop_front(); | 184 | pending_queue.pop(); |
| 150 | |||
| 151 | lock.unlock(); | 185 | lock.unlock(); |
| 152 | 186 | ||
| 153 | if (work.backend == AsyncShaders::Backend::OpenGL || | 187 | if (work.backend == Backend::OpenGL || work.backend == Backend::GLASM) { |
| 154 | work.backend == AsyncShaders::Backend::GLASM) { | 188 | const ShaderIR ir(work.code, work.main_offset, work.compiler_settings, *work.registry); |
| 155 | const ShaderIR ir(work.code, work.main_offset, work.compiler_settings, work.registry); | ||
| 156 | const auto scope = context->Acquire(); | 189 | const auto scope = context->Acquire(); |
| 157 | auto program = | 190 | auto program = |
| 158 | OpenGL::BuildShader(work.device, work.shader_type, work.uid, ir, work.registry); | 191 | OpenGL::BuildShader(*work.device, work.shader_type, work.uid, ir, *work.registry); |
| 159 | Result result{}; | 192 | Result result{}; |
| 160 | result.backend = work.backend; | 193 | result.backend = work.backend; |
| 161 | result.cpu_address = work.cpu_address; | 194 | result.cpu_address = work.cpu_address; |
| @@ -164,9 +197,9 @@ void AsyncShaders::ShaderCompilerThread(Core::Frontend::GraphicsContext* context | |||
| 164 | result.code_b = std::move(work.code_b); | 197 | result.code_b = std::move(work.code_b); |
| 165 | result.shader_type = work.shader_type; | 198 | result.shader_type = work.shader_type; |
| 166 | 199 | ||
| 167 | if (work.backend == AsyncShaders::Backend::OpenGL) { | 200 | if (work.backend == Backend::OpenGL) { |
| 168 | result.program.opengl = std::move(program->source_program); | 201 | result.program.opengl = std::move(program->source_program); |
| 169 | } else if (work.backend == AsyncShaders::Backend::GLASM) { | 202 | } else if (work.backend == Backend::GLASM) { |
| 170 | result.program.glasm = std::move(program->assembly_program); | 203 | result.program.glasm = std::move(program->assembly_program); |
| 171 | } | 204 | } |
| 172 | 205 | ||
| @@ -174,6 +207,13 @@ void AsyncShaders::ShaderCompilerThread(Core::Frontend::GraphicsContext* context | |||
| 174 | std::unique_lock complete_lock(completed_mutex); | 207 | std::unique_lock complete_lock(completed_mutex); |
| 175 | finished_work.push_back(std::move(result)); | 208 | finished_work.push_back(std::move(result)); |
| 176 | } | 209 | } |
| 210 | } else if (work.backend == Backend::Vulkan) { | ||
| 211 | auto pipeline = std::make_unique<Vulkan::VKGraphicsPipeline>( | ||
| 212 | *work.vk_device, *work.scheduler, *work.descriptor_pool, | ||
| 213 | *work.update_descriptor_queue, *work.renderpass_cache, work.key, work.bindings, | ||
| 214 | work.program); | ||
| 215 | |||
| 216 | work.pp_cache->EmplacePipeline(std::move(pipeline)); | ||
| 177 | } | 217 | } |
| 178 | } | 218 | } |
| 179 | } | 219 | } |
diff --git a/src/video_core/shader/async_shaders.h b/src/video_core/shader/async_shaders.h index 2f5ee94ad..d5ae814d5 100644 --- a/src/video_core/shader/async_shaders.h +++ b/src/video_core/shader/async_shaders.h | |||
| @@ -14,6 +14,10 @@ | |||
| 14 | #include "video_core/renderer_opengl/gl_device.h" | 14 | #include "video_core/renderer_opengl/gl_device.h" |
| 15 | #include "video_core/renderer_opengl/gl_resource_manager.h" | 15 | #include "video_core/renderer_opengl/gl_resource_manager.h" |
| 16 | #include "video_core/renderer_opengl/gl_shader_decompiler.h" | 16 | #include "video_core/renderer_opengl/gl_shader_decompiler.h" |
| 17 | #include "video_core/renderer_vulkan/vk_device.h" | ||
| 18 | #include "video_core/renderer_vulkan/vk_pipeline_cache.h" | ||
| 19 | #include "video_core/renderer_vulkan/vk_scheduler.h" | ||
| 20 | #include "video_core/renderer_vulkan/vk_update_descriptor.h" | ||
| 17 | 21 | ||
| 18 | namespace Core::Frontend { | 22 | namespace Core::Frontend { |
| 19 | class EmuWindow; | 23 | class EmuWindow; |
| @@ -24,6 +28,10 @@ namespace Tegra { | |||
| 24 | class GPU; | 28 | class GPU; |
| 25 | } | 29 | } |
| 26 | 30 | ||
| 31 | namespace Vulkan { | ||
| 32 | class VKPipelineCache; | ||
| 33 | } | ||
| 34 | |||
| 27 | namespace VideoCommon::Shader { | 35 | namespace VideoCommon::Shader { |
| 28 | 36 | ||
| 29 | class AsyncShaders { | 37 | class AsyncShaders { |
| @@ -31,6 +39,7 @@ public: | |||
| 31 | enum class Backend { | 39 | enum class Backend { |
| 32 | OpenGL, | 40 | OpenGL, |
| 33 | GLASM, | 41 | GLASM, |
| 42 | Vulkan, | ||
| 34 | }; | 43 | }; |
| 35 | 44 | ||
| 36 | struct ResultPrograms { | 45 | struct ResultPrograms { |
| @@ -52,7 +61,7 @@ public: | |||
| 52 | ~AsyncShaders(); | 61 | ~AsyncShaders(); |
| 53 | 62 | ||
| 54 | /// Start up shader worker threads | 63 | /// Start up shader worker threads |
| 55 | void AllocateWorkers(std::size_t num_workers); | 64 | void AllocateWorkers(); |
| 56 | 65 | ||
| 57 | /// Clear the shader queue and kill all worker threads | 66 | /// Clear the shader queue and kill all worker threads |
| 58 | void FreeWorkers(); | 67 | void FreeWorkers(); |
| @@ -76,6 +85,14 @@ public: | |||
| 76 | VideoCommon::Shader::CompilerSettings compiler_settings, | 85 | VideoCommon::Shader::CompilerSettings compiler_settings, |
| 77 | const VideoCommon::Shader::Registry& registry, VAddr cpu_addr); | 86 | const VideoCommon::Shader::Registry& registry, VAddr cpu_addr); |
| 78 | 87 | ||
| 88 | void QueueVulkanShader(Vulkan::VKPipelineCache* pp_cache, const Vulkan::VKDevice& device, | ||
| 89 | Vulkan::VKScheduler& scheduler, | ||
| 90 | Vulkan::VKDescriptorPool& descriptor_pool, | ||
| 91 | Vulkan::VKUpdateDescriptorQueue& update_descriptor_queue, | ||
| 92 | Vulkan::VKRenderPassCache& renderpass_cache, | ||
| 93 | std::vector<VkDescriptorSetLayoutBinding> bindings, | ||
| 94 | Vulkan::SPIRVProgram program, Vulkan::GraphicsPipelineCacheKey key); | ||
| 95 | |||
| 79 | private: | 96 | private: |
| 80 | void ShaderCompilerThread(Core::Frontend::GraphicsContext* context); | 97 | void ShaderCompilerThread(Core::Frontend::GraphicsContext* context); |
| 81 | 98 | ||
| @@ -83,16 +100,28 @@ private: | |||
| 83 | bool HasWorkQueued(); | 100 | bool HasWorkQueued(); |
| 84 | 101 | ||
| 85 | struct WorkerParams { | 102 | struct WorkerParams { |
| 86 | AsyncShaders::Backend backend; | 103 | Backend backend; |
| 87 | OpenGL::Device device; | 104 | // For OGL |
| 105 | const OpenGL::Device* device; | ||
| 88 | Tegra::Engines::ShaderType shader_type; | 106 | Tegra::Engines::ShaderType shader_type; |
| 89 | u64 uid; | 107 | u64 uid; |
| 90 | std::vector<u64> code; | 108 | std::vector<u64> code; |
| 91 | std::vector<u64> code_b; | 109 | std::vector<u64> code_b; |
| 92 | u32 main_offset; | 110 | u32 main_offset; |
| 93 | VideoCommon::Shader::CompilerSettings compiler_settings; | 111 | VideoCommon::Shader::CompilerSettings compiler_settings; |
| 94 | VideoCommon::Shader::Registry registry; | 112 | std::optional<VideoCommon::Shader::Registry> registry; |
| 95 | VAddr cpu_address; | 113 | VAddr cpu_address; |
| 114 | |||
| 115 | // For Vulkan | ||
| 116 | Vulkan::VKPipelineCache* pp_cache; | ||
| 117 | const Vulkan::VKDevice* vk_device; | ||
| 118 | Vulkan::VKScheduler* scheduler; | ||
| 119 | Vulkan::VKDescriptorPool* descriptor_pool; | ||
| 120 | Vulkan::VKUpdateDescriptorQueue* update_descriptor_queue; | ||
| 121 | Vulkan::VKRenderPassCache* renderpass_cache; | ||
| 122 | std::vector<VkDescriptorSetLayoutBinding> bindings; | ||
| 123 | Vulkan::SPIRVProgram program; | ||
| 124 | Vulkan::GraphicsPipelineCacheKey key; | ||
| 96 | }; | 125 | }; |
| 97 | 126 | ||
| 98 | std::condition_variable cv; | 127 | std::condition_variable cv; |
| @@ -101,7 +130,7 @@ private: | |||
| 101 | std::atomic<bool> is_thread_exiting{}; | 130 | std::atomic<bool> is_thread_exiting{}; |
| 102 | std::vector<std::unique_ptr<Core::Frontend::GraphicsContext>> context_list; | 131 | std::vector<std::unique_ptr<Core::Frontend::GraphicsContext>> context_list; |
| 103 | std::vector<std::thread> worker_threads; | 132 | std::vector<std::thread> worker_threads; |
| 104 | std::deque<WorkerParams> pending_queue; | 133 | std::queue<WorkerParams> pending_queue; |
| 105 | std::vector<AsyncShaders::Result> finished_work; | 134 | std::vector<AsyncShaders::Result> finished_work; |
| 106 | Core::Frontend::EmuWindow& emu_window; | 135 | Core::Frontend::EmuWindow& emu_window; |
| 107 | }; | 136 | }; |
diff --git a/src/video_core/shader/control_flow.cpp b/src/video_core/shader/control_flow.cpp index 8d86020f6..336397cdb 100644 --- a/src/video_core/shader/control_flow.cpp +++ b/src/video_core/shader/control_flow.cpp | |||
| @@ -187,24 +187,26 @@ std::optional<std::pair<BufferInfo, u64>> TrackLDC(const CFGRebuildState& state, | |||
| 187 | 187 | ||
| 188 | std::optional<u64> TrackSHLRegister(const CFGRebuildState& state, u32& pos, | 188 | std::optional<u64> TrackSHLRegister(const CFGRebuildState& state, u32& pos, |
| 189 | u64 ldc_tracked_register) { | 189 | u64 ldc_tracked_register) { |
| 190 | return TrackInstruction<u64>(state, pos, | 190 | return TrackInstruction<u64>( |
| 191 | [ldc_tracked_register](auto instr, const auto& opcode) { | 191 | state, pos, |
| 192 | return opcode.GetId() == OpCode::Id::SHL_IMM && | 192 | [ldc_tracked_register](auto instr, const auto& opcode) { |
| 193 | instr.gpr0.Value() == ldc_tracked_register; | 193 | return opcode.GetId() == OpCode::Id::SHL_IMM && |
| 194 | }, | 194 | instr.gpr0.Value() == ldc_tracked_register; |
| 195 | [](auto instr, const auto&) { return instr.gpr8.Value(); }); | 195 | }, |
| 196 | [](auto instr, const auto&) { return instr.gpr8.Value(); }); | ||
| 196 | } | 197 | } |
| 197 | 198 | ||
| 198 | std::optional<u32> TrackIMNMXValue(const CFGRebuildState& state, u32& pos, | 199 | std::optional<u32> TrackIMNMXValue(const CFGRebuildState& state, u32& pos, |
| 199 | u64 shl_tracked_register) { | 200 | u64 shl_tracked_register) { |
| 200 | return TrackInstruction<u32>(state, pos, | 201 | return TrackInstruction<u32>( |
| 201 | [shl_tracked_register](auto instr, const auto& opcode) { | 202 | state, pos, |
| 202 | return opcode.GetId() == OpCode::Id::IMNMX_IMM && | 203 | [shl_tracked_register](auto instr, const auto& opcode) { |
| 203 | instr.gpr0.Value() == shl_tracked_register; | 204 | return opcode.GetId() == OpCode::Id::IMNMX_IMM && |
| 204 | }, | 205 | instr.gpr0.Value() == shl_tracked_register; |
| 205 | [](auto instr, const auto&) { | 206 | }, |
| 206 | return static_cast<u32>(instr.alu.GetSignedImm20_20() + 1); | 207 | [](auto instr, const auto&) { |
| 207 | }); | 208 | return static_cast<u32>(instr.alu.GetSignedImm20_20() + 1); |
| 209 | }); | ||
| 208 | } | 210 | } |
| 209 | 211 | ||
| 210 | std::optional<BranchIndirectInfo> TrackBranchIndirectInfo(const CFGRebuildState& state, u32 pos) { | 212 | std::optional<BranchIndirectInfo> TrackBranchIndirectInfo(const CFGRebuildState& state, u32 pos) { |
diff --git a/src/video_core/shader/decode/memory.cpp b/src/video_core/shader/decode/memory.cpp index 63adbc4a3..e2bba88dd 100644 --- a/src/video_core/shader/decode/memory.cpp +++ b/src/video_core/shader/decode/memory.cpp | |||
| @@ -386,7 +386,8 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) { | |||
| 386 | break; | 386 | break; |
| 387 | } | 387 | } |
| 388 | case OpCode::Id::RED: { | 388 | case OpCode::Id::RED: { |
| 389 | UNIMPLEMENTED_IF_MSG(instr.red.type != GlobalAtomicType::U32); | 389 | UNIMPLEMENTED_IF_MSG(instr.red.type != GlobalAtomicType::U32, "type={}", |
| 390 | static_cast<int>(instr.red.type.Value())); | ||
| 390 | const auto [real_address, base_address, descriptor] = | 391 | const auto [real_address, base_address, descriptor] = |
| 391 | TrackGlobalMemory(bb, instr, true, true); | 392 | TrackGlobalMemory(bb, instr, true, true); |
| 392 | if (!real_address || !base_address) { | 393 | if (!real_address || !base_address) { |
| @@ -471,9 +472,9 @@ std::tuple<Node, Node, GlobalMemoryBase> ShaderIR::TrackGlobalMemory(NodeBlock& | |||
| 471 | 472 | ||
| 472 | const auto [base_address, index, offset] = | 473 | const auto [base_address, index, offset] = |
| 473 | TrackCbuf(addr_register, global_code, static_cast<s64>(global_code.size())); | 474 | TrackCbuf(addr_register, global_code, static_cast<s64>(global_code.size())); |
| 474 | ASSERT_OR_EXECUTE_MSG(base_address != nullptr, | 475 | ASSERT_OR_EXECUTE_MSG( |
| 475 | { return std::make_tuple(nullptr, nullptr, GlobalMemoryBase{}); }, | 476 | base_address != nullptr, { return std::make_tuple(nullptr, nullptr, GlobalMemoryBase{}); }, |
| 476 | "Global memory tracking failed"); | 477 | "Global memory tracking failed"); |
| 477 | 478 | ||
| 478 | bb.push_back(Comment(fmt::format("Base address is c[0x{:x}][0x{:x}]", index, offset))); | 479 | bb.push_back(Comment(fmt::format("Base address is c[0x{:x}][0x{:x}]", index, offset))); |
| 479 | 480 | ||
diff --git a/src/video_core/texture_cache/surface_params.cpp b/src/video_core/texture_cache/surface_params.cpp index 9a98f0e98..e614a92df 100644 --- a/src/video_core/texture_cache/surface_params.cpp +++ b/src/video_core/texture_cache/surface_params.cpp | |||
| @@ -96,7 +96,6 @@ SurfaceParams SurfaceParams::CreateForTexture(const FormatLookupTable& lookup_ta | |||
| 96 | } | 96 | } |
| 97 | params.type = GetFormatType(params.pixel_format); | 97 | params.type = GetFormatType(params.pixel_format); |
| 98 | } | 98 | } |
| 99 | params.type = GetFormatType(params.pixel_format); | ||
| 100 | // TODO: on 1DBuffer we should use the tic info. | 99 | // TODO: on 1DBuffer we should use the tic info. |
| 101 | if (tic.IsBuffer()) { | 100 | if (tic.IsBuffer()) { |
| 102 | params.target = SurfaceTarget::TextureBuffer; | 101 | params.target = SurfaceTarget::TextureBuffer; |
diff --git a/src/video_core/textures/decoders.cpp b/src/video_core/textures/decoders.cpp index 474ae620a..16d46a018 100644 --- a/src/video_core/textures/decoders.cpp +++ b/src/video_core/textures/decoders.cpp | |||
| @@ -228,24 +228,30 @@ void SwizzleSubrect(u32 subrect_width, u32 subrect_height, u32 source_pitch, u32 | |||
| 228 | } | 228 | } |
| 229 | } | 229 | } |
| 230 | 230 | ||
| 231 | void UnswizzleSubrect(u32 subrect_width, u32 subrect_height, u32 dest_pitch, u32 swizzled_width, | 231 | void UnswizzleSubrect(u32 line_length_in, u32 line_count, u32 pitch, u32 width, u32 bytes_per_pixel, |
| 232 | u32 bytes_per_pixel, u8* swizzled_data, u8* unswizzled_data, | 232 | u32 block_height, u32 origin_x, u32 origin_y, u8* output, const u8* input) { |
| 233 | u32 block_height_bit, u32 offset_x, u32 offset_y) { | 233 | const u32 stride = width * bytes_per_pixel; |
| 234 | const u32 block_height = 1U << block_height_bit; | 234 | const u32 gobs_in_x = (stride + GOB_SIZE_X - 1) / GOB_SIZE_X; |
| 235 | for (u32 line = 0; line < subrect_height; ++line) { | 235 | const u32 block_size = gobs_in_x << (GOB_SIZE_SHIFT + block_height); |
| 236 | const u32 y2 = line + offset_y; | 236 | |
| 237 | const u32 gob_address_y = (y2 / (GOB_SIZE_Y * block_height)) * GOB_SIZE * block_height + | 237 | const u32 block_height_mask = (1U << block_height) - 1; |
| 238 | ((y2 % (GOB_SIZE_Y * block_height)) / GOB_SIZE_Y) * GOB_SIZE; | 238 | const u32 x_shift = static_cast<u32>(GOB_SIZE_SHIFT) + block_height; |
| 239 | const auto& table = LEGACY_SWIZZLE_TABLE[y2 % GOB_SIZE_Y]; | 239 | |
| 240 | for (u32 x = 0; x < subrect_width; ++x) { | 240 | for (u32 line = 0; line < line_count; ++line) { |
| 241 | const u32 x2 = (x + offset_x) * bytes_per_pixel; | 241 | const u32 src_y = line + origin_y; |
| 242 | const u32 gob_address = gob_address_y + (x2 / GOB_SIZE_X) * GOB_SIZE * block_height; | 242 | const auto& table = LEGACY_SWIZZLE_TABLE[src_y % GOB_SIZE_Y]; |
| 243 | const u32 swizzled_offset = gob_address + table[x2 % GOB_SIZE_X]; | 243 | |
| 244 | const u32 unswizzled_offset = line * dest_pitch + x * bytes_per_pixel; | 244 | const u32 block_y = src_y >> GOB_SIZE_Y_SHIFT; |
| 245 | u8* dest_line = unswizzled_data + unswizzled_offset; | 245 | const u32 src_offset_y = (block_y >> block_height) * block_size + |
| 246 | u8* source_addr = swizzled_data + swizzled_offset; | 246 | ((block_y & block_height_mask) << GOB_SIZE_SHIFT); |
| 247 | for (u32 column = 0; column < line_length_in; ++column) { | ||
| 248 | const u32 src_x = (column + origin_x) * bytes_per_pixel; | ||
| 249 | const u32 src_offset_x = (src_x >> GOB_SIZE_X_SHIFT) << x_shift; | ||
| 250 | |||
| 251 | const u32 swizzled_offset = src_offset_y + src_offset_x + table[src_x % GOB_SIZE_X]; | ||
| 252 | const u32 unswizzled_offset = line * pitch + column * bytes_per_pixel; | ||
| 247 | 253 | ||
| 248 | std::memcpy(dest_line, source_addr, bytes_per_pixel); | 254 | std::memcpy(output + unswizzled_offset, input + swizzled_offset, bytes_per_pixel); |
| 249 | } | 255 | } |
| 250 | } | 256 | } |
| 251 | } | 257 | } |
| @@ -261,7 +267,7 @@ void SwizzleSliceToVoxel(u32 line_length_in, u32 line_count, u32 pitch, u32 widt | |||
| 261 | const u32 block_size = gobs_in_x << (GOB_SIZE_SHIFT + block_height + block_depth); | 267 | const u32 block_size = gobs_in_x << (GOB_SIZE_SHIFT + block_height + block_depth); |
| 262 | 268 | ||
| 263 | const u32 block_height_mask = (1U << block_height) - 1; | 269 | const u32 block_height_mask = (1U << block_height) - 1; |
| 264 | const u32 x_shift = Common::CountTrailingZeroes32(GOB_SIZE << (block_height + block_depth)); | 270 | const u32 x_shift = static_cast<u32>(GOB_SIZE_SHIFT) + block_height + block_depth; |
| 265 | 271 | ||
| 266 | for (u32 line = 0; line < line_count; ++line) { | 272 | for (u32 line = 0; line < line_count; ++line) { |
| 267 | const auto& table = LEGACY_SWIZZLE_TABLE[line % GOB_SIZE_Y]; | 273 | const auto& table = LEGACY_SWIZZLE_TABLE[line % GOB_SIZE_Y]; |
diff --git a/src/video_core/textures/decoders.h b/src/video_core/textures/decoders.h index d6fe35d37..01e156bc8 100644 --- a/src/video_core/textures/decoders.h +++ b/src/video_core/textures/decoders.h | |||
| @@ -48,9 +48,8 @@ void SwizzleSubrect(u32 subrect_width, u32 subrect_height, u32 source_pitch, u32 | |||
| 48 | u32 block_height_bit, u32 offset_x, u32 offset_y); | 48 | u32 block_height_bit, u32 offset_x, u32 offset_y); |
| 49 | 49 | ||
| 50 | /// Copies a tiled subrectangle into a linear surface. | 50 | /// Copies a tiled subrectangle into a linear surface. |
| 51 | void UnswizzleSubrect(u32 subrect_width, u32 subrect_height, u32 dest_pitch, u32 swizzled_width, | 51 | void UnswizzleSubrect(u32 line_length_in, u32 line_count, u32 pitch, u32 width, u32 bytes_per_pixel, |
| 52 | u32 bytes_per_pixel, u8* swizzled_data, u8* unswizzled_data, u32 block_height, | 52 | u32 block_height, u32 origin_x, u32 origin_y, u8* output, const u8* input); |
| 53 | u32 offset_x, u32 offset_y); | ||
| 54 | 53 | ||
| 55 | /// @brief Swizzles a 2D array of pixels into a 3D texture | 54 | /// @brief Swizzles a 2D array of pixels into a 3D texture |
| 56 | /// @param line_length_in Number of pixels per line | 55 | /// @param line_length_in Number of pixels per line |
diff --git a/src/video_core/video_core.cpp b/src/video_core/video_core.cpp index 45f360bdd..4e3a092c7 100644 --- a/src/video_core/video_core.cpp +++ b/src/video_core/video_core.cpp | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <memory> | 5 | #include <memory> |
| 6 | |||
| 6 | #include "common/logging/log.h" | 7 | #include "common/logging/log.h" |
| 7 | #include "core/core.h" | 8 | #include "core/core.h" |
| 8 | #include "core/settings.h" | 9 | #include "core/settings.h" |
| @@ -16,37 +17,46 @@ | |||
| 16 | #include "video_core/video_core.h" | 17 | #include "video_core/video_core.h" |
| 17 | 18 | ||
| 18 | namespace { | 19 | namespace { |
| 19 | std::unique_ptr<VideoCore::RendererBase> CreateRenderer(Core::Frontend::EmuWindow& emu_window, | 20 | |
| 20 | Core::System& system, | 21 | std::unique_ptr<VideoCore::RendererBase> CreateRenderer( |
| 21 | Core::Frontend::GraphicsContext& context) { | 22 | Core::System& system, Core::Frontend::EmuWindow& emu_window, Tegra::GPU& gpu, |
| 23 | std::unique_ptr<Core::Frontend::GraphicsContext> context) { | ||
| 22 | switch (Settings::values.renderer_backend.GetValue()) { | 24 | switch (Settings::values.renderer_backend.GetValue()) { |
| 23 | case Settings::RendererBackend::OpenGL: | 25 | case Settings::RendererBackend::OpenGL: |
| 24 | return std::make_unique<OpenGL::RendererOpenGL>(emu_window, system, context); | 26 | return std::make_unique<OpenGL::RendererOpenGL>(system, emu_window, gpu, |
| 27 | std::move(context)); | ||
| 25 | #ifdef HAS_VULKAN | 28 | #ifdef HAS_VULKAN |
| 26 | case Settings::RendererBackend::Vulkan: | 29 | case Settings::RendererBackend::Vulkan: |
| 27 | return std::make_unique<Vulkan::RendererVulkan>(emu_window, system); | 30 | return std::make_unique<Vulkan::RendererVulkan>(system, emu_window, gpu, |
| 31 | std::move(context)); | ||
| 28 | #endif | 32 | #endif |
| 29 | default: | 33 | default: |
| 30 | return nullptr; | 34 | return nullptr; |
| 31 | } | 35 | } |
| 32 | } | 36 | } |
| 37 | |||
| 33 | } // Anonymous namespace | 38 | } // Anonymous namespace |
| 34 | 39 | ||
| 35 | namespace VideoCore { | 40 | namespace VideoCore { |
| 36 | 41 | ||
| 37 | std::unique_ptr<Tegra::GPU> CreateGPU(Core::Frontend::EmuWindow& emu_window, Core::System& system) { | 42 | std::unique_ptr<Tegra::GPU> CreateGPU(Core::Frontend::EmuWindow& emu_window, Core::System& system) { |
| 43 | std::unique_ptr<Tegra::GPU> gpu; | ||
| 44 | if (Settings::values.use_asynchronous_gpu_emulation.GetValue()) { | ||
| 45 | gpu = std::make_unique<VideoCommon::GPUAsynch>(system); | ||
| 46 | } else { | ||
| 47 | gpu = std::make_unique<VideoCommon::GPUSynch>(system); | ||
| 48 | } | ||
| 49 | |||
| 38 | auto context = emu_window.CreateSharedContext(); | 50 | auto context = emu_window.CreateSharedContext(); |
| 39 | const auto scope = context->Acquire(); | 51 | const auto scope = context->Acquire(); |
| 40 | auto renderer = CreateRenderer(emu_window, system, *context); | 52 | |
| 53 | auto renderer = CreateRenderer(system, emu_window, *gpu, std::move(context)); | ||
| 41 | if (!renderer->Init()) { | 54 | if (!renderer->Init()) { |
| 42 | return nullptr; | 55 | return nullptr; |
| 43 | } | 56 | } |
| 44 | 57 | ||
| 45 | if (Settings::values.use_asynchronous_gpu_emulation.GetValue()) { | 58 | gpu->BindRenderer(std::move(renderer)); |
| 46 | return std::make_unique<VideoCommon::GPUAsynch>(system, std::move(renderer), | 59 | return gpu; |
| 47 | std::move(context)); | ||
| 48 | } | ||
| 49 | return std::make_unique<VideoCommon::GPUSynch>(system, std::move(renderer), std::move(context)); | ||
| 50 | } | 60 | } |
| 51 | 61 | ||
| 52 | u16 GetResolutionScaleFactor(const RendererBase& renderer) { | 62 | u16 GetResolutionScaleFactor(const RendererBase& renderer) { |
diff --git a/src/web_service/CMakeLists.txt b/src/web_service/CMakeLists.txt index 06ab7c59d..7e484b906 100644 --- a/src/web_service/CMakeLists.txt +++ b/src/web_service/CMakeLists.txt | |||
| @@ -5,6 +5,7 @@ add_library(web_service STATIC | |||
| 5 | verify_login.h | 5 | verify_login.h |
| 6 | web_backend.cpp | 6 | web_backend.cpp |
| 7 | web_backend.h | 7 | web_backend.h |
| 8 | web_result.h | ||
| 8 | ) | 9 | ) |
| 9 | 10 | ||
| 10 | create_target_directory_groups(web_service) | 11 | create_target_directory_groups(web_service) |
diff --git a/src/web_service/telemetry_json.cpp b/src/web_service/telemetry_json.cpp index 7a480e33c..6215c914f 100644 --- a/src/web_service/telemetry_json.cpp +++ b/src/web_service/telemetry_json.cpp | |||
| @@ -4,12 +4,14 @@ | |||
| 4 | 4 | ||
| 5 | #include <nlohmann/json.hpp> | 5 | #include <nlohmann/json.hpp> |
| 6 | #include "common/detached_tasks.h" | 6 | #include "common/detached_tasks.h" |
| 7 | #include "common/web_result.h" | ||
| 8 | #include "web_service/telemetry_json.h" | 7 | #include "web_service/telemetry_json.h" |
| 9 | #include "web_service/web_backend.h" | 8 | #include "web_service/web_backend.h" |
| 9 | #include "web_service/web_result.h" | ||
| 10 | 10 | ||
| 11 | namespace WebService { | 11 | namespace WebService { |
| 12 | 12 | ||
| 13 | namespace Telemetry = Common::Telemetry; | ||
| 14 | |||
| 13 | struct TelemetryJson::Impl { | 15 | struct TelemetryJson::Impl { |
| 14 | Impl(std::string host, std::string username, std::string token) | 16 | Impl(std::string host, std::string username, std::string token) |
| 15 | : host{std::move(host)}, username{std::move(username)}, token{std::move(token)} {} | 17 | : host{std::move(host)}, username{std::move(username)}, token{std::move(token)} {} |
| @@ -123,7 +125,7 @@ bool TelemetryJson::SubmitTestcase() { | |||
| 123 | Client client(impl->host, impl->username, impl->token); | 125 | Client client(impl->host, impl->username, impl->token); |
| 124 | auto value = client.PostJson("/gamedb/testcase", content, false); | 126 | auto value = client.PostJson("/gamedb/testcase", content, false); |
| 125 | 127 | ||
| 126 | return value.result_code == Common::WebResult::Code::Success; | 128 | return value.result_code == WebResult::Code::Success; |
| 127 | } | 129 | } |
| 128 | 130 | ||
| 129 | } // namespace WebService | 131 | } // namespace WebService |
diff --git a/src/web_service/telemetry_json.h b/src/web_service/telemetry_json.h index dfd202829..df51e00f8 100644 --- a/src/web_service/telemetry_json.h +++ b/src/web_service/telemetry_json.h | |||
| @@ -14,25 +14,25 @@ namespace WebService { | |||
| 14 | * Implementation of VisitorInterface that serialized telemetry into JSON, and submits it to the | 14 | * Implementation of VisitorInterface that serialized telemetry into JSON, and submits it to the |
| 15 | * yuzu web service | 15 | * yuzu web service |
| 16 | */ | 16 | */ |
| 17 | class TelemetryJson : public Telemetry::VisitorInterface { | 17 | class TelemetryJson : public Common::Telemetry::VisitorInterface { |
| 18 | public: | 18 | public: |
| 19 | TelemetryJson(std::string host, std::string username, std::string token); | 19 | TelemetryJson(std::string host, std::string username, std::string token); |
| 20 | ~TelemetryJson() override; | 20 | ~TelemetryJson() override; |
| 21 | 21 | ||
| 22 | void Visit(const Telemetry::Field<bool>& field) override; | 22 | void Visit(const Common::Telemetry::Field<bool>& field) override; |
| 23 | void Visit(const Telemetry::Field<double>& field) override; | 23 | void Visit(const Common::Telemetry::Field<double>& field) override; |
| 24 | void Visit(const Telemetry::Field<float>& field) override; | 24 | void Visit(const Common::Telemetry::Field<float>& field) override; |
| 25 | void Visit(const Telemetry::Field<u8>& field) override; | 25 | void Visit(const Common::Telemetry::Field<u8>& field) override; |
| 26 | void Visit(const Telemetry::Field<u16>& field) override; | 26 | void Visit(const Common::Telemetry::Field<u16>& field) override; |
| 27 | void Visit(const Telemetry::Field<u32>& field) override; | 27 | void Visit(const Common::Telemetry::Field<u32>& field) override; |
| 28 | void Visit(const Telemetry::Field<u64>& field) override; | 28 | void Visit(const Common::Telemetry::Field<u64>& field) override; |
| 29 | void Visit(const Telemetry::Field<s8>& field) override; | 29 | void Visit(const Common::Telemetry::Field<s8>& field) override; |
| 30 | void Visit(const Telemetry::Field<s16>& field) override; | 30 | void Visit(const Common::Telemetry::Field<s16>& field) override; |
| 31 | void Visit(const Telemetry::Field<s32>& field) override; | 31 | void Visit(const Common::Telemetry::Field<s32>& field) override; |
| 32 | void Visit(const Telemetry::Field<s64>& field) override; | 32 | void Visit(const Common::Telemetry::Field<s64>& field) override; |
| 33 | void Visit(const Telemetry::Field<std::string>& field) override; | 33 | void Visit(const Common::Telemetry::Field<std::string>& field) override; |
| 34 | void Visit(const Telemetry::Field<const char*>& field) override; | 34 | void Visit(const Common::Telemetry::Field<const char*>& field) override; |
| 35 | void Visit(const Telemetry::Field<std::chrono::microseconds>& field) override; | 35 | void Visit(const Common::Telemetry::Field<std::chrono::microseconds>& field) override; |
| 36 | 36 | ||
| 37 | void Complete() override; | 37 | void Complete() override; |
| 38 | bool SubmitTestcase() override; | 38 | bool SubmitTestcase() override; |
diff --git a/src/web_service/verify_login.cpp b/src/web_service/verify_login.cpp index bfaa5b70a..ceb55ca6b 100644 --- a/src/web_service/verify_login.cpp +++ b/src/web_service/verify_login.cpp | |||
| @@ -3,9 +3,9 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <nlohmann/json.hpp> | 5 | #include <nlohmann/json.hpp> |
| 6 | #include "common/web_result.h" | ||
| 7 | #include "web_service/verify_login.h" | 6 | #include "web_service/verify_login.h" |
| 8 | #include "web_service/web_backend.h" | 7 | #include "web_service/web_backend.h" |
| 8 | #include "web_service/web_result.h" | ||
| 9 | 9 | ||
| 10 | namespace WebService { | 10 | namespace WebService { |
| 11 | 11 | ||
diff --git a/src/web_service/web_backend.cpp b/src/web_service/web_backend.cpp index 09d1651ac..74e287045 100644 --- a/src/web_service/web_backend.cpp +++ b/src/web_service/web_backend.cpp | |||
| @@ -6,13 +6,14 @@ | |||
| 6 | #include <cstdlib> | 6 | #include <cstdlib> |
| 7 | #include <mutex> | 7 | #include <mutex> |
| 8 | #include <string> | 8 | #include <string> |
| 9 | |||
| 9 | #include <LUrlParser.h> | 10 | #include <LUrlParser.h> |
| 10 | #include <fmt/format.h> | 11 | #include <fmt/format.h> |
| 11 | #include <httplib.h> | 12 | #include <httplib.h> |
| 12 | #include "common/common_types.h" | 13 | |
| 13 | #include "common/logging/log.h" | 14 | #include "common/logging/log.h" |
| 14 | #include "common/web_result.h" | ||
| 15 | #include "web_service/web_backend.h" | 15 | #include "web_service/web_backend.h" |
| 16 | #include "web_service/web_result.h" | ||
| 16 | 17 | ||
| 17 | namespace WebService { | 18 | namespace WebService { |
| 18 | 19 | ||
| @@ -33,17 +34,16 @@ struct Client::Impl { | |||
| 33 | } | 34 | } |
| 34 | 35 | ||
| 35 | /// A generic function handles POST, GET and DELETE request together | 36 | /// A generic function handles POST, GET and DELETE request together |
| 36 | Common::WebResult GenericRequest(const std::string& method, const std::string& path, | 37 | WebResult GenericRequest(const std::string& method, const std::string& path, |
| 37 | const std::string& data, bool allow_anonymous, | 38 | const std::string& data, bool allow_anonymous, |
| 38 | const std::string& accept) { | 39 | const std::string& accept) { |
| 39 | if (jwt.empty()) { | 40 | if (jwt.empty()) { |
| 40 | UpdateJWT(); | 41 | UpdateJWT(); |
| 41 | } | 42 | } |
| 42 | 43 | ||
| 43 | if (jwt.empty() && !allow_anonymous) { | 44 | if (jwt.empty() && !allow_anonymous) { |
| 44 | LOG_ERROR(WebService, "Credentials must be provided for authenticated requests"); | 45 | LOG_ERROR(WebService, "Credentials must be provided for authenticated requests"); |
| 45 | return Common::WebResult{Common::WebResult::Code::CredentialsMissing, | 46 | return WebResult{WebResult::Code::CredentialsMissing, "Credentials needed", ""}; |
| 46 | "Credentials needed", ""}; | ||
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | auto result = GenericRequest(method, path, data, accept, jwt); | 49 | auto result = GenericRequest(method, path, data, accept, jwt); |
| @@ -62,10 +62,10 @@ struct Client::Impl { | |||
| 62 | * username + token is used if jwt is empty but username and token are | 62 | * username + token is used if jwt is empty but username and token are |
| 63 | * not empty anonymous if all of jwt, username and token are empty | 63 | * not empty anonymous if all of jwt, username and token are empty |
| 64 | */ | 64 | */ |
| 65 | Common::WebResult GenericRequest(const std::string& method, const std::string& path, | 65 | WebResult GenericRequest(const std::string& method, const std::string& path, |
| 66 | const std::string& data, const std::string& accept, | 66 | const std::string& data, const std::string& accept, |
| 67 | const std::string& jwt = "", const std::string& username = "", | 67 | const std::string& jwt = "", const std::string& username = "", |
| 68 | const std::string& token = "") { | 68 | const std::string& token = "") { |
| 69 | if (cli == nullptr) { | 69 | if (cli == nullptr) { |
| 70 | auto parsedUrl = LUrlParser::clParseURL::ParseURL(host); | 70 | auto parsedUrl = LUrlParser::clParseURL::ParseURL(host); |
| 71 | int port; | 71 | int port; |
| @@ -81,12 +81,12 @@ struct Client::Impl { | |||
| 81 | cli = std::make_unique<httplib::SSLClient>(parsedUrl.m_Host.c_str(), port); | 81 | cli = std::make_unique<httplib::SSLClient>(parsedUrl.m_Host.c_str(), port); |
| 82 | } else { | 82 | } else { |
| 83 | LOG_ERROR(WebService, "Bad URL scheme {}", parsedUrl.m_Scheme); | 83 | LOG_ERROR(WebService, "Bad URL scheme {}", parsedUrl.m_Scheme); |
| 84 | return Common::WebResult{Common::WebResult::Code::InvalidURL, "Bad URL scheme", ""}; | 84 | return WebResult{WebResult::Code::InvalidURL, "Bad URL scheme", ""}; |
| 85 | } | 85 | } |
| 86 | } | 86 | } |
| 87 | if (cli == nullptr) { | 87 | if (cli == nullptr) { |
| 88 | LOG_ERROR(WebService, "Invalid URL {}", host + path); | 88 | LOG_ERROR(WebService, "Invalid URL {}", host + path); |
| 89 | return Common::WebResult{Common::WebResult::Code::InvalidURL, "Invalid URL", ""}; | 89 | return WebResult{WebResult::Code::InvalidURL, "Invalid URL", ""}; |
| 90 | } | 90 | } |
| 91 | cli->set_timeout_sec(TIMEOUT_SECONDS); | 91 | cli->set_timeout_sec(TIMEOUT_SECONDS); |
| 92 | 92 | ||
| @@ -106,7 +106,7 @@ struct Client::Impl { | |||
| 106 | std::string(API_VERSION.begin(), API_VERSION.end())); | 106 | std::string(API_VERSION.begin(), API_VERSION.end())); |
| 107 | if (method != "GET") { | 107 | if (method != "GET") { |
| 108 | params.emplace(std::string("Content-Type"), std::string("application/json")); | 108 | params.emplace(std::string("Content-Type"), std::string("application/json")); |
| 109 | }; | 109 | } |
| 110 | 110 | ||
| 111 | httplib::Request request; | 111 | httplib::Request request; |
| 112 | request.method = method; | 112 | request.method = method; |
| @@ -118,29 +118,28 @@ struct Client::Impl { | |||
| 118 | 118 | ||
| 119 | if (!cli->send(request, response)) { | 119 | if (!cli->send(request, response)) { |
| 120 | LOG_ERROR(WebService, "{} to {} returned null", method, host + path); | 120 | LOG_ERROR(WebService, "{} to {} returned null", method, host + path); |
| 121 | return Common::WebResult{Common::WebResult::Code::LibError, "Null response", ""}; | 121 | return WebResult{WebResult::Code::LibError, "Null response", ""}; |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | if (response.status >= 400) { | 124 | if (response.status >= 400) { |
| 125 | LOG_ERROR(WebService, "{} to {} returned error status code: {}", method, host + path, | 125 | LOG_ERROR(WebService, "{} to {} returned error status code: {}", method, host + path, |
| 126 | response.status); | 126 | response.status); |
| 127 | return Common::WebResult{Common::WebResult::Code::HttpError, | 127 | return WebResult{WebResult::Code::HttpError, std::to_string(response.status), ""}; |
| 128 | std::to_string(response.status), ""}; | ||
| 129 | } | 128 | } |
| 130 | 129 | ||
| 131 | auto content_type = response.headers.find("content-type"); | 130 | auto content_type = response.headers.find("content-type"); |
| 132 | 131 | ||
| 133 | if (content_type == response.headers.end()) { | 132 | if (content_type == response.headers.end()) { |
| 134 | LOG_ERROR(WebService, "{} to {} returned no content", method, host + path); | 133 | LOG_ERROR(WebService, "{} to {} returned no content", method, host + path); |
| 135 | return Common::WebResult{Common::WebResult::Code::WrongContent, "", ""}; | 134 | return WebResult{WebResult::Code::WrongContent, "", ""}; |
| 136 | } | 135 | } |
| 137 | 136 | ||
| 138 | if (content_type->second.find(accept) == std::string::npos) { | 137 | if (content_type->second.find(accept) == std::string::npos) { |
| 139 | LOG_ERROR(WebService, "{} to {} returned wrong content: {}", method, host + path, | 138 | LOG_ERROR(WebService, "{} to {} returned wrong content: {}", method, host + path, |
| 140 | content_type->second); | 139 | content_type->second); |
| 141 | return Common::WebResult{Common::WebResult::Code::WrongContent, "Wrong content", ""}; | 140 | return WebResult{WebResult::Code::WrongContent, "Wrong content", ""}; |
| 142 | } | 141 | } |
| 143 | return Common::WebResult{Common::WebResult::Code::Success, "", response.body}; | 142 | return WebResult{WebResult::Code::Success, "", response.body}; |
| 144 | } | 143 | } |
| 145 | 144 | ||
| 146 | // Retrieve a new JWT from given username and token | 145 | // Retrieve a new JWT from given username and token |
| @@ -150,7 +149,7 @@ struct Client::Impl { | |||
| 150 | } | 149 | } |
| 151 | 150 | ||
| 152 | auto result = GenericRequest("POST", "/jwt/internal", "", "text/html", "", username, token); | 151 | auto result = GenericRequest("POST", "/jwt/internal", "", "text/html", "", username, token); |
| 153 | if (result.result_code != Common::WebResult::Code::Success) { | 152 | if (result.result_code != WebResult::Code::Success) { |
| 154 | LOG_ERROR(WebService, "UpdateJWT failed"); | 153 | LOG_ERROR(WebService, "UpdateJWT failed"); |
| 155 | } else { | 154 | } else { |
| 156 | std::lock_guard lock{jwt_cache.mutex}; | 155 | std::lock_guard lock{jwt_cache.mutex}; |
| @@ -180,29 +179,28 @@ Client::Client(std::string host, std::string username, std::string token) | |||
| 180 | 179 | ||
| 181 | Client::~Client() = default; | 180 | Client::~Client() = default; |
| 182 | 181 | ||
| 183 | Common::WebResult Client::PostJson(const std::string& path, const std::string& data, | 182 | WebResult Client::PostJson(const std::string& path, const std::string& data, bool allow_anonymous) { |
| 184 | bool allow_anonymous) { | ||
| 185 | return impl->GenericRequest("POST", path, data, allow_anonymous, "application/json"); | 183 | return impl->GenericRequest("POST", path, data, allow_anonymous, "application/json"); |
| 186 | } | 184 | } |
| 187 | 185 | ||
| 188 | Common::WebResult Client::GetJson(const std::string& path, bool allow_anonymous) { | 186 | WebResult Client::GetJson(const std::string& path, bool allow_anonymous) { |
| 189 | return impl->GenericRequest("GET", path, "", allow_anonymous, "application/json"); | 187 | return impl->GenericRequest("GET", path, "", allow_anonymous, "application/json"); |
| 190 | } | 188 | } |
| 191 | 189 | ||
| 192 | Common::WebResult Client::DeleteJson(const std::string& path, const std::string& data, | 190 | WebResult Client::DeleteJson(const std::string& path, const std::string& data, |
| 193 | bool allow_anonymous) { | 191 | bool allow_anonymous) { |
| 194 | return impl->GenericRequest("DELETE", path, data, allow_anonymous, "application/json"); | 192 | return impl->GenericRequest("DELETE", path, data, allow_anonymous, "application/json"); |
| 195 | } | 193 | } |
| 196 | 194 | ||
| 197 | Common::WebResult Client::GetPlain(const std::string& path, bool allow_anonymous) { | 195 | WebResult Client::GetPlain(const std::string& path, bool allow_anonymous) { |
| 198 | return impl->GenericRequest("GET", path, "", allow_anonymous, "text/plain"); | 196 | return impl->GenericRequest("GET", path, "", allow_anonymous, "text/plain"); |
| 199 | } | 197 | } |
| 200 | 198 | ||
| 201 | Common::WebResult Client::GetImage(const std::string& path, bool allow_anonymous) { | 199 | WebResult Client::GetImage(const std::string& path, bool allow_anonymous) { |
| 202 | return impl->GenericRequest("GET", path, "", allow_anonymous, "image/png"); | 200 | return impl->GenericRequest("GET", path, "", allow_anonymous, "image/png"); |
| 203 | } | 201 | } |
| 204 | 202 | ||
| 205 | Common::WebResult Client::GetExternalJWT(const std::string& audience) { | 203 | WebResult Client::GetExternalJWT(const std::string& audience) { |
| 206 | return impl->GenericRequest("POST", fmt::format("/jwt/external/{}", audience), "", false, | 204 | return impl->GenericRequest("POST", fmt::format("/jwt/external/{}", audience), "", false, |
| 207 | "text/html"); | 205 | "text/html"); |
| 208 | } | 206 | } |
diff --git a/src/web_service/web_backend.h b/src/web_service/web_backend.h index 04121f17e..81f58583c 100644 --- a/src/web_service/web_backend.h +++ b/src/web_service/web_backend.h | |||
| @@ -7,12 +7,10 @@ | |||
| 7 | #include <memory> | 7 | #include <memory> |
| 8 | #include <string> | 8 | #include <string> |
| 9 | 9 | ||
| 10 | namespace Common { | ||
| 11 | struct WebResult; | ||
| 12 | } | ||
| 13 | |||
| 14 | namespace WebService { | 10 | namespace WebService { |
| 15 | 11 | ||
| 12 | struct WebResult; | ||
| 13 | |||
| 16 | class Client { | 14 | class Client { |
| 17 | public: | 15 | public: |
| 18 | Client(std::string host, std::string username, std::string token); | 16 | Client(std::string host, std::string username, std::string token); |
| @@ -25,8 +23,7 @@ public: | |||
| 25 | * @param allow_anonymous If true, allow anonymous unauthenticated requests. | 23 | * @param allow_anonymous If true, allow anonymous unauthenticated requests. |
| 26 | * @return the result of the request. | 24 | * @return the result of the request. |
| 27 | */ | 25 | */ |
| 28 | Common::WebResult PostJson(const std::string& path, const std::string& data, | 26 | WebResult PostJson(const std::string& path, const std::string& data, bool allow_anonymous); |
| 29 | bool allow_anonymous); | ||
| 30 | 27 | ||
| 31 | /** | 28 | /** |
| 32 | * Gets JSON from the specified path. | 29 | * Gets JSON from the specified path. |
| @@ -34,7 +31,7 @@ public: | |||
| 34 | * @param allow_anonymous If true, allow anonymous unauthenticated requests. | 31 | * @param allow_anonymous If true, allow anonymous unauthenticated requests. |
| 35 | * @return the result of the request. | 32 | * @return the result of the request. |
| 36 | */ | 33 | */ |
| 37 | Common::WebResult GetJson(const std::string& path, bool allow_anonymous); | 34 | WebResult GetJson(const std::string& path, bool allow_anonymous); |
| 38 | 35 | ||
| 39 | /** | 36 | /** |
| 40 | * Deletes JSON to the specified path. | 37 | * Deletes JSON to the specified path. |
| @@ -43,8 +40,7 @@ public: | |||
| 43 | * @param allow_anonymous If true, allow anonymous unauthenticated requests. | 40 | * @param allow_anonymous If true, allow anonymous unauthenticated requests. |
| 44 | * @return the result of the request. | 41 | * @return the result of the request. |
| 45 | */ | 42 | */ |
| 46 | Common::WebResult DeleteJson(const std::string& path, const std::string& data, | 43 | WebResult DeleteJson(const std::string& path, const std::string& data, bool allow_anonymous); |
| 47 | bool allow_anonymous); | ||
| 48 | 44 | ||
| 49 | /** | 45 | /** |
| 50 | * Gets a plain string from the specified path. | 46 | * Gets a plain string from the specified path. |
| @@ -52,7 +48,7 @@ public: | |||
| 52 | * @param allow_anonymous If true, allow anonymous unauthenticated requests. | 48 | * @param allow_anonymous If true, allow anonymous unauthenticated requests. |
| 53 | * @return the result of the request. | 49 | * @return the result of the request. |
| 54 | */ | 50 | */ |
| 55 | Common::WebResult GetPlain(const std::string& path, bool allow_anonymous); | 51 | WebResult GetPlain(const std::string& path, bool allow_anonymous); |
| 56 | 52 | ||
| 57 | /** | 53 | /** |
| 58 | * Gets an PNG image from the specified path. | 54 | * Gets an PNG image from the specified path. |
| @@ -60,14 +56,14 @@ public: | |||
| 60 | * @param allow_anonymous If true, allow anonymous unauthenticated requests. | 56 | * @param allow_anonymous If true, allow anonymous unauthenticated requests. |
| 61 | * @return the result of the request. | 57 | * @return the result of the request. |
| 62 | */ | 58 | */ |
| 63 | Common::WebResult GetImage(const std::string& path, bool allow_anonymous); | 59 | WebResult GetImage(const std::string& path, bool allow_anonymous); |
| 64 | 60 | ||
| 65 | /** | 61 | /** |
| 66 | * Requests an external JWT for the specific audience provided. | 62 | * Requests an external JWT for the specific audience provided. |
| 67 | * @param audience the audience of the JWT requested. | 63 | * @param audience the audience of the JWT requested. |
| 68 | * @return the result of the request. | 64 | * @return the result of the request. |
| 69 | */ | 65 | */ |
| 70 | Common::WebResult GetExternalJWT(const std::string& audience); | 66 | WebResult GetExternalJWT(const std::string& audience); |
| 71 | 67 | ||
| 72 | private: | 68 | private: |
| 73 | struct Impl; | 69 | struct Impl; |
diff --git a/src/common/web_result.h b/src/web_service/web_result.h index 8bfa2141d..3aeeb5288 100644 --- a/src/common/web_result.h +++ b/src/web_service/web_result.h | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | #include <string> | 7 | #include <string> |
| 8 | #include "common/common_types.h" | 8 | #include "common/common_types.h" |
| 9 | 9 | ||
| 10 | namespace Common { | 10 | namespace WebService { |
| 11 | struct WebResult { | 11 | struct WebResult { |
| 12 | enum class Code : u32 { | 12 | enum class Code : u32 { |
| 13 | Success, | 13 | Success, |
| @@ -22,4 +22,4 @@ struct WebResult { | |||
| 22 | std::string result_string; | 22 | std::string result_string; |
| 23 | std::string returned_data; | 23 | std::string returned_data; |
| 24 | }; | 24 | }; |
| 25 | } // namespace Common | 25 | } // namespace WebService |
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index 656096c9f..6987e85e1 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt | |||
| @@ -39,6 +39,9 @@ add_executable(yuzu | |||
| 39 | configuration/configure_debug.cpp | 39 | configuration/configure_debug.cpp |
| 40 | configuration/configure_debug.h | 40 | configuration/configure_debug.h |
| 41 | configuration/configure_debug.ui | 41 | configuration/configure_debug.ui |
| 42 | configuration/configure_debug_controller.cpp | ||
| 43 | configuration/configure_debug_controller.h | ||
| 44 | configuration/configure_debug_controller.ui | ||
| 42 | configuration/configure_dialog.cpp | 45 | configuration/configure_dialog.cpp |
| 43 | configuration/configure_dialog.h | 46 | configuration/configure_dialog.h |
| 44 | configuration/configure_filesystem.cpp | 47 | configuration/configure_filesystem.cpp |
| @@ -62,9 +65,9 @@ add_executable(yuzu | |||
| 62 | configuration/configure_input_player.cpp | 65 | configuration/configure_input_player.cpp |
| 63 | configuration/configure_input_player.h | 66 | configuration/configure_input_player.h |
| 64 | configuration/configure_input_player.ui | 67 | configuration/configure_input_player.ui |
| 65 | configuration/configure_input_simple.cpp | 68 | configuration/configure_input_advanced.cpp |
| 66 | configuration/configure_input_simple.h | 69 | configuration/configure_input_advanced.h |
| 67 | configuration/configure_input_simple.ui | 70 | configuration/configure_input_advanced.ui |
| 68 | configuration/configure_mouse_advanced.cpp | 71 | configuration/configure_mouse_advanced.cpp |
| 69 | configuration/configure_mouse_advanced.h | 72 | configuration/configure_mouse_advanced.h |
| 70 | configuration/configure_mouse_advanced.ui | 73 | configuration/configure_mouse_advanced.ui |
diff --git a/src/yuzu/applets/profile_select.cpp b/src/yuzu/applets/profile_select.cpp index 4bc8ee726..dca8835ed 100644 --- a/src/yuzu/applets/profile_select.cpp +++ b/src/yuzu/applets/profile_select.cpp | |||
| @@ -26,7 +26,7 @@ QString FormatUserEntryText(const QString& username, Common::UUID uuid) { | |||
| 26 | } | 26 | } |
| 27 | 27 | ||
| 28 | QString GetImagePath(Common::UUID uuid) { | 28 | QString GetImagePath(Common::UUID uuid) { |
| 29 | const auto path = FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) + | 29 | const auto path = Common::FS::GetUserPath(Common::FS::UserPath::NANDDir) + |
| 30 | "/system/save/8000000000000010/su/avators/" + uuid.FormatSwitch() + ".jpg"; | 30 | "/system/save/8000000000000010/su/avators/" + uuid.FormatSwitch() + ".jpg"; |
| 31 | return QString::fromStdString(path); | 31 | return QString::fromStdString(path); |
| 32 | } | 32 | } |
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index 8fc322b30..21707e451 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp | |||
| @@ -304,8 +304,9 @@ static Core::Frontend::EmuWindow::WindowSystemInfo GetWindowSystemInfo(QWindow* | |||
| 304 | return wsi; | 304 | return wsi; |
| 305 | } | 305 | } |
| 306 | 306 | ||
| 307 | GRenderWindow::GRenderWindow(GMainWindow* parent_, EmuThread* emu_thread_) | 307 | GRenderWindow::GRenderWindow(GMainWindow* parent, EmuThread* emu_thread_, |
| 308 | : QWidget(parent_), emu_thread(emu_thread_) { | 308 | std::shared_ptr<InputCommon::InputSubsystem> input_subsystem_) |
| 309 | : QWidget(parent), emu_thread(emu_thread_), input_subsystem{std::move(input_subsystem_)} { | ||
| 309 | setWindowTitle(QStringLiteral("yuzu %1 | %2-%3") | 310 | setWindowTitle(QStringLiteral("yuzu %1 | %2-%3") |
| 310 | .arg(QString::fromUtf8(Common::g_build_name), | 311 | .arg(QString::fromUtf8(Common::g_build_name), |
| 311 | QString::fromUtf8(Common::g_scm_branch), | 312 | QString::fromUtf8(Common::g_scm_branch), |
| @@ -314,15 +315,15 @@ GRenderWindow::GRenderWindow(GMainWindow* parent_, EmuThread* emu_thread_) | |||
| 314 | auto layout = new QHBoxLayout(this); | 315 | auto layout = new QHBoxLayout(this); |
| 315 | layout->setMargin(0); | 316 | layout->setMargin(0); |
| 316 | setLayout(layout); | 317 | setLayout(layout); |
| 317 | InputCommon::Init(); | 318 | input_subsystem->Initialize(); |
| 318 | 319 | ||
| 319 | this->setMouseTracking(true); | 320 | this->setMouseTracking(true); |
| 320 | 321 | ||
| 321 | connect(this, &GRenderWindow::FirstFrameDisplayed, parent_, &GMainWindow::OnLoadComplete); | 322 | connect(this, &GRenderWindow::FirstFrameDisplayed, parent, &GMainWindow::OnLoadComplete); |
| 322 | } | 323 | } |
| 323 | 324 | ||
| 324 | GRenderWindow::~GRenderWindow() { | 325 | GRenderWindow::~GRenderWindow() { |
| 325 | InputCommon::Shutdown(); | 326 | input_subsystem->Shutdown(); |
| 326 | } | 327 | } |
| 327 | 328 | ||
| 328 | void GRenderWindow::PollEvents() { | 329 | void GRenderWindow::PollEvents() { |
| @@ -391,11 +392,11 @@ void GRenderWindow::closeEvent(QCloseEvent* event) { | |||
| 391 | } | 392 | } |
| 392 | 393 | ||
| 393 | void GRenderWindow::keyPressEvent(QKeyEvent* event) { | 394 | void GRenderWindow::keyPressEvent(QKeyEvent* event) { |
| 394 | InputCommon::GetKeyboard()->PressKey(event->key()); | 395 | input_subsystem->GetKeyboard()->PressKey(event->key()); |
| 395 | } | 396 | } |
| 396 | 397 | ||
| 397 | void GRenderWindow::keyReleaseEvent(QKeyEvent* event) { | 398 | void GRenderWindow::keyReleaseEvent(QKeyEvent* event) { |
| 398 | InputCommon::GetKeyboard()->ReleaseKey(event->key()); | 399 | input_subsystem->GetKeyboard()->ReleaseKey(event->key()); |
| 399 | } | 400 | } |
| 400 | 401 | ||
| 401 | void GRenderWindow::mousePressEvent(QMouseEvent* event) { | 402 | void GRenderWindow::mousePressEvent(QMouseEvent* event) { |
| @@ -409,7 +410,7 @@ void GRenderWindow::mousePressEvent(QMouseEvent* event) { | |||
| 409 | const auto [x, y] = ScaleTouch(pos); | 410 | const auto [x, y] = ScaleTouch(pos); |
| 410 | this->TouchPressed(x, y); | 411 | this->TouchPressed(x, y); |
| 411 | } else if (event->button() == Qt::RightButton) { | 412 | } else if (event->button() == Qt::RightButton) { |
| 412 | InputCommon::GetMotionEmu()->BeginTilt(pos.x(), pos.y()); | 413 | input_subsystem->GetMotionEmu()->BeginTilt(pos.x(), pos.y()); |
| 413 | } | 414 | } |
| 414 | QWidget::mousePressEvent(event); | 415 | QWidget::mousePressEvent(event); |
| 415 | } | 416 | } |
| @@ -423,7 +424,7 @@ void GRenderWindow::mouseMoveEvent(QMouseEvent* event) { | |||
| 423 | auto pos = event->pos(); | 424 | auto pos = event->pos(); |
| 424 | const auto [x, y] = ScaleTouch(pos); | 425 | const auto [x, y] = ScaleTouch(pos); |
| 425 | this->TouchMoved(x, y); | 426 | this->TouchMoved(x, y); |
| 426 | InputCommon::GetMotionEmu()->Tilt(pos.x(), pos.y()); | 427 | input_subsystem->GetMotionEmu()->Tilt(pos.x(), pos.y()); |
| 427 | QWidget::mouseMoveEvent(event); | 428 | QWidget::mouseMoveEvent(event); |
| 428 | } | 429 | } |
| 429 | 430 | ||
| @@ -436,7 +437,7 @@ void GRenderWindow::mouseReleaseEvent(QMouseEvent* event) { | |||
| 436 | if (event->button() == Qt::LeftButton) { | 437 | if (event->button() == Qt::LeftButton) { |
| 437 | this->TouchReleased(); | 438 | this->TouchReleased(); |
| 438 | } else if (event->button() == Qt::RightButton) { | 439 | } else if (event->button() == Qt::RightButton) { |
| 439 | InputCommon::GetMotionEmu()->EndTilt(); | 440 | input_subsystem->GetMotionEmu()->EndTilt(); |
| 440 | } | 441 | } |
| 441 | } | 442 | } |
| 442 | 443 | ||
| @@ -451,7 +452,7 @@ void GRenderWindow::TouchUpdateEvent(const QTouchEvent* event) { | |||
| 451 | int active_points = 0; | 452 | int active_points = 0; |
| 452 | 453 | ||
| 453 | // average all active touch points | 454 | // average all active touch points |
| 454 | for (const auto tp : event->touchPoints()) { | 455 | for (const auto& tp : event->touchPoints()) { |
| 455 | if (tp.state() & (Qt::TouchPointPressed | Qt::TouchPointMoved | Qt::TouchPointStationary)) { | 456 | if (tp.state() & (Qt::TouchPointPressed | Qt::TouchPointMoved | Qt::TouchPointStationary)) { |
| 456 | active_points++; | 457 | active_points++; |
| 457 | pos += tp.pos(); | 458 | pos += tp.pos(); |
| @@ -485,7 +486,7 @@ bool GRenderWindow::event(QEvent* event) { | |||
| 485 | 486 | ||
| 486 | void GRenderWindow::focusOutEvent(QFocusEvent* event) { | 487 | void GRenderWindow::focusOutEvent(QFocusEvent* event) { |
| 487 | QWidget::focusOutEvent(event); | 488 | QWidget::focusOutEvent(event); |
| 488 | InputCommon::GetKeyboard()->ReleaseAllKeys(); | 489 | input_subsystem->GetKeyboard()->ReleaseAllKeys(); |
| 489 | } | 490 | } |
| 490 | 491 | ||
| 491 | void GRenderWindow::resizeEvent(QResizeEvent* event) { | 492 | void GRenderWindow::resizeEvent(QResizeEvent* event) { |
diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h index 6c59b4d5c..ca35cf831 100644 --- a/src/yuzu/bootmanager.h +++ b/src/yuzu/bootmanager.h | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | #include <atomic> | 7 | #include <atomic> |
| 8 | #include <condition_variable> | 8 | #include <condition_variable> |
| 9 | #include <memory> | ||
| 9 | #include <mutex> | 10 | #include <mutex> |
| 10 | 11 | ||
| 11 | #include <QImage> | 12 | #include <QImage> |
| @@ -23,6 +24,10 @@ class QKeyEvent; | |||
| 23 | class QTouchEvent; | 24 | class QTouchEvent; |
| 24 | class QStringList; | 25 | class QStringList; |
| 25 | 26 | ||
| 27 | namespace InputCommon { | ||
| 28 | class InputSubsystem; | ||
| 29 | } | ||
| 30 | |||
| 26 | namespace VideoCore { | 31 | namespace VideoCore { |
| 27 | enum class LoadCallbackStage; | 32 | enum class LoadCallbackStage; |
| 28 | } | 33 | } |
| @@ -121,7 +126,8 @@ class GRenderWindow : public QWidget, public Core::Frontend::EmuWindow { | |||
| 121 | Q_OBJECT | 126 | Q_OBJECT |
| 122 | 127 | ||
| 123 | public: | 128 | public: |
| 124 | GRenderWindow(GMainWindow* parent, EmuThread* emu_thread); | 129 | explicit GRenderWindow(GMainWindow* parent, EmuThread* emu_thread_, |
| 130 | std::shared_ptr<InputCommon::InputSubsystem> input_subsystem_); | ||
| 125 | ~GRenderWindow() override; | 131 | ~GRenderWindow() override; |
| 126 | 132 | ||
| 127 | // EmuWindow implementation. | 133 | // EmuWindow implementation. |
| @@ -183,6 +189,7 @@ private: | |||
| 183 | QStringList GetUnsupportedGLExtensions() const; | 189 | QStringList GetUnsupportedGLExtensions() const; |
| 184 | 190 | ||
| 185 | EmuThread* emu_thread; | 191 | EmuThread* emu_thread; |
| 192 | std::shared_ptr<InputCommon::InputSubsystem> input_subsystem; | ||
| 186 | 193 | ||
| 187 | // Main context that will be shared with all other contexts that are requested. | 194 | // Main context that will be shared with all other contexts that are requested. |
| 188 | // If this is used in a shared context setting, then this should not be used directly, but | 195 | // If this is used in a shared context setting, then this should not be used directly, but |
diff --git a/src/yuzu/compatdb.cpp b/src/yuzu/compatdb.cpp index 5477f050c..649912557 100644 --- a/src/yuzu/compatdb.cpp +++ b/src/yuzu/compatdb.cpp | |||
| @@ -54,7 +54,8 @@ void CompatDB::Submit() { | |||
| 54 | back(); | 54 | back(); |
| 55 | LOG_DEBUG(Frontend, "Compatibility Rating: {}", compatibility->checkedId()); | 55 | LOG_DEBUG(Frontend, "Compatibility Rating: {}", compatibility->checkedId()); |
| 56 | Core::System::GetInstance().TelemetrySession().AddField( | 56 | Core::System::GetInstance().TelemetrySession().AddField( |
| 57 | Telemetry::FieldType::UserFeedback, "Compatibility", compatibility->checkedId()); | 57 | Common::Telemetry::FieldType::UserFeedback, "Compatibility", |
| 58 | compatibility->checkedId()); | ||
| 58 | 59 | ||
| 59 | button(NextButton)->setEnabled(false); | 60 | button(NextButton)->setEnabled(false); |
| 60 | button(NextButton)->setText(tr("Submitting")); | 61 | button(NextButton)->setText(tr("Submitting")); |
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index cb71b8d11..588bbd677 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp | |||
| @@ -6,17 +6,18 @@ | |||
| 6 | #include <QKeySequence> | 6 | #include <QKeySequence> |
| 7 | #include <QSettings> | 7 | #include <QSettings> |
| 8 | #include "common/file_util.h" | 8 | #include "common/file_util.h" |
| 9 | #include "configure_input_simple.h" | ||
| 10 | #include "core/hle/service/acc/profile_manager.h" | 9 | #include "core/hle/service/acc/profile_manager.h" |
| 11 | #include "core/hle/service/hid/controllers/npad.h" | 10 | #include "core/hle/service/hid/controllers/npad.h" |
| 12 | #include "input_common/main.h" | 11 | #include "input_common/main.h" |
| 13 | #include "input_common/udp/client.h" | 12 | #include "input_common/udp/client.h" |
| 14 | #include "yuzu/configuration/config.h" | 13 | #include "yuzu/configuration/config.h" |
| 15 | 14 | ||
| 15 | namespace FS = Common::FS; | ||
| 16 | |||
| 16 | Config::Config(const std::string& config_file, bool is_global) { | 17 | Config::Config(const std::string& config_file, bool is_global) { |
| 17 | // TODO: Don't hardcode the path; let the frontend decide where to put the config files. | 18 | // TODO: Don't hardcode the path; let the frontend decide where to put the config files. |
| 18 | qt_config_loc = FileUtil::GetUserPath(FileUtil::UserPath::ConfigDir) + config_file; | 19 | qt_config_loc = FS::GetUserPath(FS::UserPath::ConfigDir) + config_file; |
| 19 | FileUtil::CreateFullPath(qt_config_loc); | 20 | FS::CreateFullPath(qt_config_loc); |
| 20 | qt_config = | 21 | qt_config = |
| 21 | std::make_unique<QSettings>(QString::fromStdString(qt_config_loc), QSettings::IniFormat); | 22 | std::make_unique<QSettings>(QString::fromStdString(qt_config_loc), QSettings::IniFormat); |
| 22 | global = is_global; | 23 | global = is_global; |
| @@ -30,29 +31,31 @@ Config::~Config() { | |||
| 30 | } | 31 | } |
| 31 | 32 | ||
| 32 | const std::array<int, Settings::NativeButton::NumButtons> Config::default_buttons = { | 33 | const std::array<int, Settings::NativeButton::NumButtons> Config::default_buttons = { |
| 33 | Qt::Key_A, Qt::Key_S, Qt::Key_Z, Qt::Key_X, Qt::Key_3, Qt::Key_4, Qt::Key_Q, | 34 | Qt::Key_A, Qt::Key_S, Qt::Key_Z, Qt::Key_X, Qt::Key_3, Qt::Key_4, Qt::Key_Q, |
| 34 | Qt::Key_W, Qt::Key_1, Qt::Key_2, Qt::Key_N, Qt::Key_M, Qt::Key_F, Qt::Key_T, | 35 | Qt::Key_W, Qt::Key_1, Qt::Key_2, Qt::Key_N, Qt::Key_M, Qt::Key_F, Qt::Key_T, |
| 35 | Qt::Key_H, Qt::Key_G, Qt::Key_Left, Qt::Key_Up, Qt::Key_Right, Qt::Key_Down, Qt::Key_J, | 36 | Qt::Key_H, Qt::Key_G, Qt::Key_D, Qt::Key_C, Qt::Key_B, Qt::Key_V, |
| 36 | Qt::Key_I, Qt::Key_L, Qt::Key_K, Qt::Key_D, Qt::Key_C, Qt::Key_B, Qt::Key_V, | ||
| 37 | }; | 37 | }; |
| 38 | 38 | ||
| 39 | const std::array<std::array<int, 5>, Settings::NativeAnalog::NumAnalogs> Config::default_analogs{{ | 39 | const std::array<std::array<int, 4>, Settings::NativeAnalog::NumAnalogs> Config::default_analogs{{ |
| 40 | { | 40 | { |
| 41 | Qt::Key_Up, | 41 | Qt::Key_Up, |
| 42 | Qt::Key_Down, | 42 | Qt::Key_Down, |
| 43 | Qt::Key_Left, | 43 | Qt::Key_Left, |
| 44 | Qt::Key_Right, | 44 | Qt::Key_Right, |
| 45 | Qt::Key_E, | ||
| 46 | }, | 45 | }, |
| 47 | { | 46 | { |
| 48 | Qt::Key_I, | 47 | Qt::Key_I, |
| 49 | Qt::Key_K, | 48 | Qt::Key_K, |
| 50 | Qt::Key_J, | 49 | Qt::Key_J, |
| 51 | Qt::Key_L, | 50 | Qt::Key_L, |
| 52 | Qt::Key_R, | ||
| 53 | }, | 51 | }, |
| 54 | }}; | 52 | }}; |
| 55 | 53 | ||
| 54 | const std::array<int, 2> Config::default_stick_mod = { | ||
| 55 | Qt::Key_E, | ||
| 56 | Qt::Key_R, | ||
| 57 | }; | ||
| 58 | |||
| 56 | const std::array<int, Settings::NativeMouseButton::NumMouseButtons> Config::default_mouse_buttons = | 59 | const std::array<int, Settings::NativeMouseButton::NumMouseButtons> Config::default_mouse_buttons = |
| 57 | { | 60 | { |
| 58 | Qt::Key_BracketLeft, Qt::Key_BracketRight, Qt::Key_Apostrophe, Qt::Key_Minus, Qt::Key_Equal, | 61 | Qt::Key_BracketLeft, Qt::Key_BracketRight, Qt::Key_Apostrophe, Qt::Key_Minus, Qt::Key_Equal, |
| @@ -241,10 +244,10 @@ void Config::ReadPlayerValues() { | |||
| 241 | player.connected = | 244 | player.connected = |
| 242 | ReadSetting(QStringLiteral("player_%1_connected").arg(p), false).toBool(); | 245 | ReadSetting(QStringLiteral("player_%1_connected").arg(p), false).toBool(); |
| 243 | 246 | ||
| 244 | player.type = static_cast<Settings::ControllerType>( | 247 | player.controller_type = static_cast<Settings::ControllerType>( |
| 245 | qt_config | 248 | qt_config |
| 246 | ->value(QStringLiteral("player_%1_type").arg(p), | 249 | ->value(QStringLiteral("player_%1_type").arg(p), |
| 247 | static_cast<u8>(Settings::ControllerType::DualJoycon)) | 250 | static_cast<u8>(Settings::ControllerType::ProController)) |
| 248 | .toUInt()); | 251 | .toUInt()); |
| 249 | 252 | ||
| 250 | player.body_color_left = qt_config | 253 | player.body_color_left = qt_config |
| @@ -284,7 +287,7 @@ void Config::ReadPlayerValues() { | |||
| 284 | for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { | 287 | for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { |
| 285 | const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( | 288 | const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( |
| 286 | default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], | 289 | default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], |
| 287 | default_analogs[i][3], default_analogs[i][4], 0.5f); | 290 | default_analogs[i][3], default_stick_mod[i], 0.5f); |
| 288 | auto& player_analogs = player.analogs[i]; | 291 | auto& player_analogs = player.analogs[i]; |
| 289 | 292 | ||
| 290 | player_analogs = qt_config | 293 | player_analogs = qt_config |
| @@ -298,12 +301,6 @@ void Config::ReadPlayerValues() { | |||
| 298 | } | 301 | } |
| 299 | } | 302 | } |
| 300 | } | 303 | } |
| 301 | |||
| 302 | std::stable_partition( | ||
| 303 | Settings::values.players.begin(), | ||
| 304 | Settings::values.players.begin() + | ||
| 305 | Service::HID::Controller_NPad::NPadIdToIndex(Service::HID::NPAD_HANDHELD), | ||
| 306 | [](const auto& player) { return player.connected; }); | ||
| 307 | } | 304 | } |
| 308 | 305 | ||
| 309 | void Config::ReadDebugValues() { | 306 | void Config::ReadDebugValues() { |
| @@ -328,7 +325,7 @@ void Config::ReadDebugValues() { | |||
| 328 | for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { | 325 | for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { |
| 329 | const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( | 326 | const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( |
| 330 | default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], | 327 | default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], |
| 331 | default_analogs[i][3], default_analogs[i][4], 0.5f); | 328 | default_analogs[i][3], default_stick_mod[i], 0.5f); |
| 332 | auto& debug_pad_analogs = Settings::values.debug_pad_analogs[i]; | 329 | auto& debug_pad_analogs = Settings::values.debug_pad_analogs[i]; |
| 333 | 330 | ||
| 334 | debug_pad_analogs = qt_config | 331 | debug_pad_analogs = qt_config |
| @@ -395,13 +392,6 @@ void Config::ReadTouchscreenValues() { | |||
| 395 | ReadSetting(QStringLiteral("touchscreen_diameter_y"), 15).toUInt(); | 392 | ReadSetting(QStringLiteral("touchscreen_diameter_y"), 15).toUInt(); |
| 396 | } | 393 | } |
| 397 | 394 | ||
| 398 | void Config::ApplyDefaultProfileIfInputInvalid() { | ||
| 399 | if (!std::any_of(Settings::values.players.begin(), Settings::values.players.end(), | ||
| 400 | [](const Settings::PlayerInput& in) { return in.connected; })) { | ||
| 401 | ApplyInputProfileConfiguration(UISettings::values.profile_index); | ||
| 402 | } | ||
| 403 | } | ||
| 404 | |||
| 405 | void Config::ReadAudioValues() { | 395 | void Config::ReadAudioValues() { |
| 406 | qt_config->beginGroup(QStringLiteral("Audio")); | 396 | qt_config->beginGroup(QStringLiteral("Audio")); |
| 407 | 397 | ||
| @@ -431,6 +421,8 @@ void Config::ReadControlValues() { | |||
| 431 | ReadMouseValues(); | 421 | ReadMouseValues(); |
| 432 | ReadTouchscreenValues(); | 422 | ReadTouchscreenValues(); |
| 433 | 423 | ||
| 424 | Settings::values.vibration_enabled = | ||
| 425 | ReadSetting(QStringLiteral("vibration_enabled"), true).toBool(); | ||
| 434 | Settings::values.motion_device = | 426 | Settings::values.motion_device = |
| 435 | ReadSetting(QStringLiteral("motion_device"), | 427 | ReadSetting(QStringLiteral("motion_device"), |
| 436 | QStringLiteral("engine:motion_emu,update_period:100,sensitivity:0.01")) | 428 | QStringLiteral("engine:motion_emu,update_period:100,sensitivity:0.01")) |
| @@ -464,47 +456,42 @@ void Config::ReadDataStorageValues() { | |||
| 464 | qt_config->beginGroup(QStringLiteral("Data Storage")); | 456 | qt_config->beginGroup(QStringLiteral("Data Storage")); |
| 465 | 457 | ||
| 466 | Settings::values.use_virtual_sd = ReadSetting(QStringLiteral("use_virtual_sd"), true).toBool(); | 458 | Settings::values.use_virtual_sd = ReadSetting(QStringLiteral("use_virtual_sd"), true).toBool(); |
| 467 | FileUtil::GetUserPath( | 459 | FS::GetUserPath(FS::UserPath::NANDDir, |
| 468 | FileUtil::UserPath::NANDDir, | 460 | qt_config |
| 469 | qt_config | 461 | ->value(QStringLiteral("nand_directory"), |
| 470 | ->value(QStringLiteral("nand_directory"), | 462 | QString::fromStdString(FS::GetUserPath(FS::UserPath::NANDDir))) |
| 471 | QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::NANDDir))) | 463 | .toString() |
| 472 | .toString() | 464 | .toStdString()); |
| 473 | .toStdString()); | 465 | FS::GetUserPath(FS::UserPath::SDMCDir, |
| 474 | FileUtil::GetUserPath( | 466 | qt_config |
| 475 | FileUtil::UserPath::SDMCDir, | 467 | ->value(QStringLiteral("sdmc_directory"), |
| 476 | qt_config | 468 | QString::fromStdString(FS::GetUserPath(FS::UserPath::SDMCDir))) |
| 477 | ->value(QStringLiteral("sdmc_directory"), | 469 | .toString() |
| 478 | QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir))) | 470 | .toStdString()); |
| 479 | .toString() | 471 | FS::GetUserPath(FS::UserPath::LoadDir, |
| 480 | .toStdString()); | 472 | qt_config |
| 481 | FileUtil::GetUserPath( | 473 | ->value(QStringLiteral("load_directory"), |
| 482 | FileUtil::UserPath::LoadDir, | 474 | QString::fromStdString(FS::GetUserPath(FS::UserPath::LoadDir))) |
| 483 | qt_config | 475 | .toString() |
| 484 | ->value(QStringLiteral("load_directory"), | 476 | .toStdString()); |
| 485 | QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::LoadDir))) | 477 | FS::GetUserPath(FS::UserPath::DumpDir, |
| 486 | .toString() | 478 | qt_config |
| 487 | .toStdString()); | 479 | ->value(QStringLiteral("dump_directory"), |
| 488 | FileUtil::GetUserPath( | 480 | QString::fromStdString(FS::GetUserPath(FS::UserPath::DumpDir))) |
| 489 | FileUtil::UserPath::DumpDir, | 481 | .toString() |
| 490 | qt_config | 482 | .toStdString()); |
| 491 | ->value(QStringLiteral("dump_directory"), | 483 | FS::GetUserPath(FS::UserPath::CacheDir, |
| 492 | QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::DumpDir))) | 484 | qt_config |
| 493 | .toString() | 485 | ->value(QStringLiteral("cache_directory"), |
| 494 | .toStdString()); | 486 | QString::fromStdString(FS::GetUserPath(FS::UserPath::CacheDir))) |
| 495 | FileUtil::GetUserPath( | 487 | .toString() |
| 496 | FileUtil::UserPath::CacheDir, | 488 | .toStdString()); |
| 497 | qt_config | ||
| 498 | ->value(QStringLiteral("cache_directory"), | ||
| 499 | QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::CacheDir))) | ||
| 500 | .toString() | ||
| 501 | .toStdString()); | ||
| 502 | Settings::values.gamecard_inserted = | 489 | Settings::values.gamecard_inserted = |
| 503 | ReadSetting(QStringLiteral("gamecard_inserted"), false).toBool(); | 490 | ReadSetting(QStringLiteral("gamecard_inserted"), false).toBool(); |
| 504 | Settings::values.gamecard_current_game = | 491 | Settings::values.gamecard_current_game = |
| 505 | ReadSetting(QStringLiteral("gamecard_current_game"), false).toBool(); | 492 | ReadSetting(QStringLiteral("gamecard_current_game"), false).toBool(); |
| 506 | Settings::values.gamecard_path = | 493 | Settings::values.gamecard_path = |
| 507 | ReadSetting(QStringLiteral("gamecard_path"), QStringLiteral("")).toString().toStdString(); | 494 | ReadSetting(QStringLiteral("gamecard_path"), QString{}).toString().toStdString(); |
| 508 | 495 | ||
| 509 | qt_config->endGroup(); | 496 | qt_config->endGroup(); |
| 510 | } | 497 | } |
| @@ -518,7 +505,7 @@ void Config::ReadDebuggingValues() { | |||
| 518 | Settings::values.use_gdbstub = ReadSetting(QStringLiteral("use_gdbstub"), false).toBool(); | 505 | Settings::values.use_gdbstub = ReadSetting(QStringLiteral("use_gdbstub"), false).toBool(); |
| 519 | Settings::values.gdbstub_port = ReadSetting(QStringLiteral("gdbstub_port"), 24689).toInt(); | 506 | Settings::values.gdbstub_port = ReadSetting(QStringLiteral("gdbstub_port"), 24689).toInt(); |
| 520 | Settings::values.program_args = | 507 | Settings::values.program_args = |
| 521 | ReadSetting(QStringLiteral("program_args"), QStringLiteral("")).toString().toStdString(); | 508 | ReadSetting(QStringLiteral("program_args"), QString{}).toString().toStdString(); |
| 522 | Settings::values.dump_exefs = ReadSetting(QStringLiteral("dump_exefs"), false).toBool(); | 509 | Settings::values.dump_exefs = ReadSetting(QStringLiteral("dump_exefs"), false).toBool(); |
| 523 | Settings::values.dump_nso = ReadSetting(QStringLiteral("dump_nso"), false).toBool(); | 510 | Settings::values.dump_nso = ReadSetting(QStringLiteral("dump_nso"), false).toBool(); |
| 524 | Settings::values.reporting_services = | 511 | Settings::values.reporting_services = |
| @@ -551,8 +538,7 @@ void Config::ReadDisabledAddOnValues() { | |||
| 551 | const auto d_size = qt_config->beginReadArray(QStringLiteral("disabled")); | 538 | const auto d_size = qt_config->beginReadArray(QStringLiteral("disabled")); |
| 552 | for (int j = 0; j < d_size; ++j) { | 539 | for (int j = 0; j < d_size; ++j) { |
| 553 | qt_config->setArrayIndex(j); | 540 | qt_config->setArrayIndex(j); |
| 554 | out.push_back( | 541 | out.push_back(ReadSetting(QStringLiteral("d"), QString{}).toString().toStdString()); |
| 555 | ReadSetting(QStringLiteral("d"), QStringLiteral("")).toString().toStdString()); | ||
| 556 | } | 542 | } |
| 557 | qt_config->endArray(); | 543 | qt_config->endArray(); |
| 558 | Settings::values.disabled_addons.insert_or_assign(title_id, out); | 544 | Settings::values.disabled_addons.insert_or_assign(title_id, out); |
| @@ -638,6 +624,11 @@ void Config::ReadCpuValues() { | |||
| 638 | ReadSetting(QStringLiteral("cpuopt_misc_ir"), true).toBool(); | 624 | ReadSetting(QStringLiteral("cpuopt_misc_ir"), true).toBool(); |
| 639 | Settings::values.cpuopt_reduce_misalign_checks = | 625 | Settings::values.cpuopt_reduce_misalign_checks = |
| 640 | ReadSetting(QStringLiteral("cpuopt_reduce_misalign_checks"), true).toBool(); | 626 | ReadSetting(QStringLiteral("cpuopt_reduce_misalign_checks"), true).toBool(); |
| 627 | |||
| 628 | Settings::values.cpuopt_unsafe_unfuse_fma = | ||
| 629 | ReadSetting(QStringLiteral("cpuopt_unsafe_unfuse_fma"), true).toBool(); | ||
| 630 | Settings::values.cpuopt_unsafe_reduce_fp_error = | ||
| 631 | ReadSetting(QStringLiteral("cpuopt_unsafe_reduce_fp_error"), true).toBool(); | ||
| 641 | } | 632 | } |
| 642 | 633 | ||
| 643 | qt_config->endGroup(); | 634 | qt_config->endGroup(); |
| @@ -677,11 +668,11 @@ void Config::ReadScreenshotValues() { | |||
| 677 | 668 | ||
| 678 | UISettings::values.enable_screenshot_save_as = | 669 | UISettings::values.enable_screenshot_save_as = |
| 679 | ReadSetting(QStringLiteral("enable_screenshot_save_as"), true).toBool(); | 670 | ReadSetting(QStringLiteral("enable_screenshot_save_as"), true).toBool(); |
| 680 | FileUtil::GetUserPath( | 671 | FS::GetUserPath( |
| 681 | FileUtil::UserPath::ScreenshotsDir, | 672 | FS::UserPath::ScreenshotsDir, |
| 682 | qt_config | 673 | qt_config |
| 683 | ->value(QStringLiteral("screenshot_path"), QString::fromStdString(FileUtil::GetUserPath( | 674 | ->value(QStringLiteral("screenshot_path"), |
| 684 | FileUtil::UserPath::ScreenshotsDir))) | 675 | QString::fromStdString(FS::GetUserPath(FS::UserPath::ScreenshotsDir))) |
| 685 | .toString() | 676 | .toString() |
| 686 | .toStdString()); | 677 | .toStdString()); |
| 687 | 678 | ||
| @@ -786,14 +777,11 @@ void Config::ReadUIValues() { | |||
| 786 | UISettings::values.first_start = ReadSetting(QStringLiteral("firstStart"), true).toBool(); | 777 | UISettings::values.first_start = ReadSetting(QStringLiteral("firstStart"), true).toBool(); |
| 787 | UISettings::values.callout_flags = ReadSetting(QStringLiteral("calloutFlags"), 0).toUInt(); | 778 | UISettings::values.callout_flags = ReadSetting(QStringLiteral("calloutFlags"), 0).toUInt(); |
| 788 | UISettings::values.show_console = ReadSetting(QStringLiteral("showConsole"), false).toBool(); | 779 | UISettings::values.show_console = ReadSetting(QStringLiteral("showConsole"), false).toBool(); |
| 789 | UISettings::values.profile_index = ReadSetting(QStringLiteral("profileIndex"), 0).toUInt(); | ||
| 790 | UISettings::values.pause_when_in_background = | 780 | UISettings::values.pause_when_in_background = |
| 791 | ReadSetting(QStringLiteral("pauseWhenInBackground"), false).toBool(); | 781 | ReadSetting(QStringLiteral("pauseWhenInBackground"), false).toBool(); |
| 792 | UISettings::values.hide_mouse = | 782 | UISettings::values.hide_mouse = |
| 793 | ReadSetting(QStringLiteral("hideInactiveMouse"), false).toBool(); | 783 | ReadSetting(QStringLiteral("hideInactiveMouse"), false).toBool(); |
| 794 | 784 | ||
| 795 | ApplyDefaultProfileIfInputInvalid(); | ||
| 796 | |||
| 797 | qt_config->endGroup(); | 785 | qt_config->endGroup(); |
| 798 | } | 786 | } |
| 799 | 787 | ||
| @@ -867,8 +855,9 @@ void Config::SavePlayerValues() { | |||
| 867 | const auto& player = Settings::values.players[p]; | 855 | const auto& player = Settings::values.players[p]; |
| 868 | 856 | ||
| 869 | WriteSetting(QStringLiteral("player_%1_connected").arg(p), player.connected, false); | 857 | WriteSetting(QStringLiteral("player_%1_connected").arg(p), player.connected, false); |
| 870 | WriteSetting(QStringLiteral("player_%1_type").arg(p), static_cast<u8>(player.type), | 858 | WriteSetting(QStringLiteral("player_%1_type").arg(p), |
| 871 | static_cast<u8>(Settings::ControllerType::DualJoycon)); | 859 | static_cast<u8>(player.controller_type), |
| 860 | static_cast<u8>(Settings::ControllerType::ProController)); | ||
| 872 | 861 | ||
| 873 | WriteSetting(QStringLiteral("player_%1_body_color_left").arg(p), player.body_color_left, | 862 | WriteSetting(QStringLiteral("player_%1_body_color_left").arg(p), player.body_color_left, |
| 874 | Settings::JOYCON_BODY_NEON_BLUE); | 863 | Settings::JOYCON_BODY_NEON_BLUE); |
| @@ -890,7 +879,7 @@ void Config::SavePlayerValues() { | |||
| 890 | for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { | 879 | for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { |
| 891 | const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( | 880 | const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( |
| 892 | default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], | 881 | default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], |
| 893 | default_analogs[i][3], default_analogs[i][4], 0.5f); | 882 | default_analogs[i][3], default_stick_mod[i], 0.5f); |
| 894 | WriteSetting(QStringLiteral("player_%1_").arg(p) + | 883 | WriteSetting(QStringLiteral("player_%1_").arg(p) + |
| 895 | QString::fromStdString(Settings::NativeAnalog::mapping[i]), | 884 | QString::fromStdString(Settings::NativeAnalog::mapping[i]), |
| 896 | QString::fromStdString(player.analogs[i]), | 885 | QString::fromStdString(player.analogs[i]), |
| @@ -911,7 +900,7 @@ void Config::SaveDebugValues() { | |||
| 911 | for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { | 900 | for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { |
| 912 | const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( | 901 | const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( |
| 913 | default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], | 902 | default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], |
| 914 | default_analogs[i][3], default_analogs[i][4], 0.5f); | 903 | default_analogs[i][3], default_stick_mod[i], 0.5f); |
| 915 | WriteSetting(QStringLiteral("debug_pad_") + | 904 | WriteSetting(QStringLiteral("debug_pad_") + |
| 916 | QString::fromStdString(Settings::NativeAnalog::mapping[i]), | 905 | QString::fromStdString(Settings::NativeAnalog::mapping[i]), |
| 917 | QString::fromStdString(Settings::values.debug_pad_analogs[i]), | 906 | QString::fromStdString(Settings::values.debug_pad_analogs[i]), |
| @@ -988,6 +977,7 @@ void Config::SaveControlValues() { | |||
| 988 | SaveMouseValues(); | 977 | SaveMouseValues(); |
| 989 | SaveTouchscreenValues(); | 978 | SaveTouchscreenValues(); |
| 990 | 979 | ||
| 980 | WriteSetting(QStringLiteral("vibration_enabled"), Settings::values.vibration_enabled, true); | ||
| 991 | WriteSetting(QStringLiteral("motion_device"), | 981 | WriteSetting(QStringLiteral("motion_device"), |
| 992 | QString::fromStdString(Settings::values.motion_device), | 982 | QString::fromStdString(Settings::values.motion_device), |
| 993 | QStringLiteral("engine:motion_emu,update_period:100,sensitivity:0.01")); | 983 | QStringLiteral("engine:motion_emu,update_period:100,sensitivity:0.01")); |
| @@ -1016,25 +1006,25 @@ void Config::SaveDataStorageValues() { | |||
| 1016 | 1006 | ||
| 1017 | WriteSetting(QStringLiteral("use_virtual_sd"), Settings::values.use_virtual_sd, true); | 1007 | WriteSetting(QStringLiteral("use_virtual_sd"), Settings::values.use_virtual_sd, true); |
| 1018 | WriteSetting(QStringLiteral("nand_directory"), | 1008 | WriteSetting(QStringLiteral("nand_directory"), |
| 1019 | QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::NANDDir)), | 1009 | QString::fromStdString(FS::GetUserPath(FS::UserPath::NANDDir)), |
| 1020 | QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::NANDDir))); | 1010 | QString::fromStdString(FS::GetUserPath(FS::UserPath::NANDDir))); |
| 1021 | WriteSetting(QStringLiteral("sdmc_directory"), | 1011 | WriteSetting(QStringLiteral("sdmc_directory"), |
| 1022 | QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir)), | 1012 | QString::fromStdString(FS::GetUserPath(FS::UserPath::SDMCDir)), |
| 1023 | QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir))); | 1013 | QString::fromStdString(FS::GetUserPath(FS::UserPath::SDMCDir))); |
| 1024 | WriteSetting(QStringLiteral("load_directory"), | 1014 | WriteSetting(QStringLiteral("load_directory"), |
| 1025 | QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::LoadDir)), | 1015 | QString::fromStdString(FS::GetUserPath(FS::UserPath::LoadDir)), |
| 1026 | QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::LoadDir))); | 1016 | QString::fromStdString(FS::GetUserPath(FS::UserPath::LoadDir))); |
| 1027 | WriteSetting(QStringLiteral("dump_directory"), | 1017 | WriteSetting(QStringLiteral("dump_directory"), |
| 1028 | QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::DumpDir)), | 1018 | QString::fromStdString(FS::GetUserPath(FS::UserPath::DumpDir)), |
| 1029 | QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::DumpDir))); | 1019 | QString::fromStdString(FS::GetUserPath(FS::UserPath::DumpDir))); |
| 1030 | WriteSetting(QStringLiteral("cache_directory"), | 1020 | WriteSetting(QStringLiteral("cache_directory"), |
| 1031 | QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::CacheDir)), | 1021 | QString::fromStdString(FS::GetUserPath(FS::UserPath::CacheDir)), |
| 1032 | QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::CacheDir))); | 1022 | QString::fromStdString(FS::GetUserPath(FS::UserPath::CacheDir))); |
| 1033 | WriteSetting(QStringLiteral("gamecard_inserted"), Settings::values.gamecard_inserted, false); | 1023 | WriteSetting(QStringLiteral("gamecard_inserted"), Settings::values.gamecard_inserted, false); |
| 1034 | WriteSetting(QStringLiteral("gamecard_current_game"), Settings::values.gamecard_current_game, | 1024 | WriteSetting(QStringLiteral("gamecard_current_game"), Settings::values.gamecard_current_game, |
| 1035 | false); | 1025 | false); |
| 1036 | WriteSetting(QStringLiteral("gamecard_path"), | 1026 | WriteSetting(QStringLiteral("gamecard_path"), |
| 1037 | QString::fromStdString(Settings::values.gamecard_path), QStringLiteral("")); | 1027 | QString::fromStdString(Settings::values.gamecard_path), QString{}); |
| 1038 | 1028 | ||
| 1039 | qt_config->endGroup(); | 1029 | qt_config->endGroup(); |
| 1040 | } | 1030 | } |
| @@ -1047,7 +1037,7 @@ void Config::SaveDebuggingValues() { | |||
| 1047 | WriteSetting(QStringLiteral("use_gdbstub"), Settings::values.use_gdbstub, false); | 1037 | WriteSetting(QStringLiteral("use_gdbstub"), Settings::values.use_gdbstub, false); |
| 1048 | WriteSetting(QStringLiteral("gdbstub_port"), Settings::values.gdbstub_port, 24689); | 1038 | WriteSetting(QStringLiteral("gdbstub_port"), Settings::values.gdbstub_port, 24689); |
| 1049 | WriteSetting(QStringLiteral("program_args"), | 1039 | WriteSetting(QStringLiteral("program_args"), |
| 1050 | QString::fromStdString(Settings::values.program_args), QStringLiteral("")); | 1040 | QString::fromStdString(Settings::values.program_args), QString{}); |
| 1051 | WriteSetting(QStringLiteral("dump_exefs"), Settings::values.dump_exefs, false); | 1041 | WriteSetting(QStringLiteral("dump_exefs"), Settings::values.dump_exefs, false); |
| 1052 | WriteSetting(QStringLiteral("dump_nso"), Settings::values.dump_nso, false); | 1042 | WriteSetting(QStringLiteral("dump_nso"), Settings::values.dump_nso, false); |
| 1053 | WriteSetting(QStringLiteral("quest_flag"), Settings::values.quest_flag, false); | 1043 | WriteSetting(QStringLiteral("quest_flag"), Settings::values.quest_flag, false); |
| @@ -1074,8 +1064,7 @@ void Config::SaveDisabledAddOnValues() { | |||
| 1074 | qt_config->beginWriteArray(QStringLiteral("disabled")); | 1064 | qt_config->beginWriteArray(QStringLiteral("disabled")); |
| 1075 | for (std::size_t j = 0; j < elem.second.size(); ++j) { | 1065 | for (std::size_t j = 0; j < elem.second.size(); ++j) { |
| 1076 | qt_config->setArrayIndex(static_cast<int>(j)); | 1066 | qt_config->setArrayIndex(static_cast<int>(j)); |
| 1077 | WriteSetting(QStringLiteral("d"), QString::fromStdString(elem.second[j]), | 1067 | WriteSetting(QStringLiteral("d"), QString::fromStdString(elem.second[j]), QString{}); |
| 1078 | QStringLiteral("")); | ||
| 1079 | } | 1068 | } |
| 1080 | qt_config->endArray(); | 1069 | qt_config->endArray(); |
| 1081 | ++i; | 1070 | ++i; |
| @@ -1135,6 +1124,11 @@ void Config::SaveCpuValues() { | |||
| 1135 | WriteSetting(QStringLiteral("cpuopt_misc_ir"), Settings::values.cpuopt_misc_ir, true); | 1124 | WriteSetting(QStringLiteral("cpuopt_misc_ir"), Settings::values.cpuopt_misc_ir, true); |
| 1136 | WriteSetting(QStringLiteral("cpuopt_reduce_misalign_checks"), | 1125 | WriteSetting(QStringLiteral("cpuopt_reduce_misalign_checks"), |
| 1137 | Settings::values.cpuopt_reduce_misalign_checks, true); | 1126 | Settings::values.cpuopt_reduce_misalign_checks, true); |
| 1127 | |||
| 1128 | WriteSetting(QStringLiteral("cpuopt_unsafe_unfuse_fma"), | ||
| 1129 | Settings::values.cpuopt_unsafe_unfuse_fma, true); | ||
| 1130 | WriteSetting(QStringLiteral("cpuopt_unsafe_reduce_fp_error"), | ||
| 1131 | Settings::values.cpuopt_unsafe_reduce_fp_error, true); | ||
| 1138 | } | 1132 | } |
| 1139 | 1133 | ||
| 1140 | qt_config->endGroup(); | 1134 | qt_config->endGroup(); |
| @@ -1180,7 +1174,7 @@ void Config::SaveScreenshotValues() { | |||
| 1180 | WriteSetting(QStringLiteral("enable_screenshot_save_as"), | 1174 | WriteSetting(QStringLiteral("enable_screenshot_save_as"), |
| 1181 | UISettings::values.enable_screenshot_save_as); | 1175 | UISettings::values.enable_screenshot_save_as); |
| 1182 | WriteSetting(QStringLiteral("screenshot_path"), | 1176 | WriteSetting(QStringLiteral("screenshot_path"), |
| 1183 | QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::ScreenshotsDir))); | 1177 | QString::fromStdString(FS::GetUserPath(FS::UserPath::ScreenshotsDir))); |
| 1184 | 1178 | ||
| 1185 | qt_config->endGroup(); | 1179 | qt_config->endGroup(); |
| 1186 | } | 1180 | } |
| @@ -1259,7 +1253,6 @@ void Config::SaveUIValues() { | |||
| 1259 | WriteSetting(QStringLiteral("firstStart"), UISettings::values.first_start, true); | 1253 | WriteSetting(QStringLiteral("firstStart"), UISettings::values.first_start, true); |
| 1260 | WriteSetting(QStringLiteral("calloutFlags"), UISettings::values.callout_flags, 0); | 1254 | WriteSetting(QStringLiteral("calloutFlags"), UISettings::values.callout_flags, 0); |
| 1261 | WriteSetting(QStringLiteral("showConsole"), UISettings::values.show_console, false); | 1255 | WriteSetting(QStringLiteral("showConsole"), UISettings::values.show_console, false); |
| 1262 | WriteSetting(QStringLiteral("profileIndex"), UISettings::values.profile_index, 0); | ||
| 1263 | WriteSetting(QStringLiteral("pauseWhenInBackground"), | 1256 | WriteSetting(QStringLiteral("pauseWhenInBackground"), |
| 1264 | UISettings::values.pause_when_in_background, false); | 1257 | UISettings::values.pause_when_in_background, false); |
| 1265 | WriteSetting(QStringLiteral("hideInactiveMouse"), UISettings::values.hide_mouse, false); | 1258 | WriteSetting(QStringLiteral("hideInactiveMouse"), UISettings::values.hide_mouse, false); |
diff --git a/src/yuzu/configuration/config.h b/src/yuzu/configuration/config.h index e5f39b040..aa929d134 100644 --- a/src/yuzu/configuration/config.h +++ b/src/yuzu/configuration/config.h | |||
| @@ -23,7 +23,8 @@ public: | |||
| 23 | void Save(); | 23 | void Save(); |
| 24 | 24 | ||
| 25 | static const std::array<int, Settings::NativeButton::NumButtons> default_buttons; | 25 | static const std::array<int, Settings::NativeButton::NumButtons> default_buttons; |
| 26 | static const std::array<std::array<int, 5>, Settings::NativeAnalog::NumAnalogs> default_analogs; | 26 | static const std::array<std::array<int, 4>, Settings::NativeAnalog::NumAnalogs> default_analogs; |
| 27 | static const std::array<int, 2> default_stick_mod; | ||
| 27 | static const std::array<int, Settings::NativeMouseButton::NumMouseButtons> | 28 | static const std::array<int, Settings::NativeMouseButton::NumMouseButtons> |
| 28 | default_mouse_buttons; | 29 | default_mouse_buttons; |
| 29 | static const std::array<int, Settings::NativeKeyboard::NumKeyboardKeys> default_keyboard_keys; | 30 | static const std::array<int, Settings::NativeKeyboard::NumKeyboardKeys> default_keyboard_keys; |
| @@ -37,7 +38,6 @@ private: | |||
| 37 | void ReadKeyboardValues(); | 38 | void ReadKeyboardValues(); |
| 38 | void ReadMouseValues(); | 39 | void ReadMouseValues(); |
| 39 | void ReadTouchscreenValues(); | 40 | void ReadTouchscreenValues(); |
| 40 | void ApplyDefaultProfileIfInputInvalid(); | ||
| 41 | 41 | ||
| 42 | // Read functions bases off the respective config section names. | 42 | // Read functions bases off the respective config section names. |
| 43 | void ReadAudioValues(); | 43 | void ReadAudioValues(); |
diff --git a/src/yuzu/configuration/configuration_shared.cpp b/src/yuzu/configuration/configuration_shared.cpp index f9becab6e..18482795c 100644 --- a/src/yuzu/configuration/configuration_shared.cpp +++ b/src/yuzu/configuration/configuration_shared.cpp | |||
| @@ -72,18 +72,18 @@ void ConfigurationShared::SetPerGameSetting( | |||
| 72 | ConfigurationShared::USE_GLOBAL_OFFSET); | 72 | ConfigurationShared::USE_GLOBAL_OFFSET); |
| 73 | } | 73 | } |
| 74 | 74 | ||
| 75 | void ConfigurationShared::SetHighlight(QWidget* widget, const std::string& name, bool highlighted) { | 75 | void ConfigurationShared::SetHighlight(QWidget* widget, bool highlighted) { |
| 76 | if (highlighted) { | 76 | if (highlighted) { |
| 77 | widget->setStyleSheet(QStringLiteral("QWidget#%1 { background-color:rgba(0,203,255,0.5) }") | 77 | widget->setStyleSheet(QStringLiteral("QWidget#%1 { background-color:rgba(0,203,255,0.5) }") |
| 78 | .arg(QString::fromStdString(name))); | 78 | .arg(widget->objectName())); |
| 79 | } else { | 79 | } else { |
| 80 | widget->setStyleSheet(QStringLiteral("QWidget#%1 { background-color:rgba(0,0,0,0) }") | 80 | widget->setStyleSheet(QStringLiteral("QWidget#%1 { background-color:rgba(0,0,0,0) }") |
| 81 | .arg(QString::fromStdString(name))); | 81 | .arg(widget->objectName())); |
| 82 | } | 82 | } |
| 83 | widget->show(); | 83 | widget->show(); |
| 84 | } | 84 | } |
| 85 | 85 | ||
| 86 | void ConfigurationShared::SetColoredTristate(QCheckBox* checkbox, const std::string& name, | 86 | void ConfigurationShared::SetColoredTristate(QCheckBox* checkbox, |
| 87 | const Settings::Setting<bool>& setting, | 87 | const Settings::Setting<bool>& setting, |
| 88 | CheckState& tracker) { | 88 | CheckState& tracker) { |
| 89 | if (setting.UsingGlobal()) { | 89 | if (setting.UsingGlobal()) { |
| @@ -91,45 +91,39 @@ void ConfigurationShared::SetColoredTristate(QCheckBox* checkbox, const std::str | |||
| 91 | } else { | 91 | } else { |
| 92 | tracker = (setting.GetValue() == setting.GetValue(true)) ? CheckState::On : CheckState::Off; | 92 | tracker = (setting.GetValue() == setting.GetValue(true)) ? CheckState::On : CheckState::Off; |
| 93 | } | 93 | } |
| 94 | SetHighlight(checkbox, name, tracker != CheckState::Global); | 94 | SetHighlight(checkbox, tracker != CheckState::Global); |
| 95 | QObject::connect(checkbox, &QCheckBox::clicked, checkbox, | 95 | QObject::connect(checkbox, &QCheckBox::clicked, checkbox, [checkbox, setting, &tracker] { |
| 96 | [checkbox, name, setting, &tracker]() { | 96 | tracker = static_cast<CheckState>((static_cast<int>(tracker) + 1) % |
| 97 | tracker = static_cast<CheckState>((static_cast<int>(tracker) + 1) % | 97 | static_cast<int>(CheckState::Count)); |
| 98 | static_cast<int>(CheckState::Count)); | 98 | if (tracker == CheckState::Global) { |
| 99 | if (tracker == CheckState::Global) { | 99 | checkbox->setChecked(setting.GetValue(true)); |
| 100 | checkbox->setChecked(setting.GetValue(true)); | 100 | } |
| 101 | } | 101 | SetHighlight(checkbox, tracker != CheckState::Global); |
| 102 | SetHighlight(checkbox, name, tracker != CheckState::Global); | 102 | }); |
| 103 | }); | ||
| 104 | } | 103 | } |
| 105 | 104 | ||
| 106 | void ConfigurationShared::SetColoredTristate(QCheckBox* checkbox, const std::string& name, | 105 | void ConfigurationShared::SetColoredTristate(QCheckBox* checkbox, bool global, bool state, |
| 107 | bool global, bool state, bool global_state, | 106 | bool global_state, CheckState& tracker) { |
| 108 | CheckState& tracker) { | ||
| 109 | if (global) { | 107 | if (global) { |
| 110 | tracker = CheckState::Global; | 108 | tracker = CheckState::Global; |
| 111 | } else { | 109 | } else { |
| 112 | tracker = (state == global_state) ? CheckState::On : CheckState::Off; | 110 | tracker = (state == global_state) ? CheckState::On : CheckState::Off; |
| 113 | } | 111 | } |
| 114 | SetHighlight(checkbox, name, tracker != CheckState::Global); | 112 | SetHighlight(checkbox, tracker != CheckState::Global); |
| 115 | QObject::connect(checkbox, &QCheckBox::clicked, checkbox, | 113 | QObject::connect(checkbox, &QCheckBox::clicked, checkbox, [checkbox, global_state, &tracker] { |
| 116 | [checkbox, name, global_state, &tracker]() { | 114 | tracker = static_cast<CheckState>((static_cast<int>(tracker) + 1) % |
| 117 | tracker = static_cast<CheckState>((static_cast<int>(tracker) + 1) % | 115 | static_cast<int>(CheckState::Count)); |
| 118 | static_cast<int>(CheckState::Count)); | 116 | if (tracker == CheckState::Global) { |
| 119 | if (tracker == CheckState::Global) { | 117 | checkbox->setChecked(global_state); |
| 120 | checkbox->setChecked(global_state); | 118 | } |
| 121 | } | 119 | SetHighlight(checkbox, tracker != CheckState::Global); |
| 122 | SetHighlight(checkbox, name, tracker != CheckState::Global); | 120 | }); |
| 123 | }); | ||
| 124 | } | 121 | } |
| 125 | 122 | ||
| 126 | void ConfigurationShared::SetColoredComboBox(QComboBox* combobox, QWidget* target, | 123 | void ConfigurationShared::SetColoredComboBox(QComboBox* combobox, QWidget* target, int global) { |
| 127 | const std::string& target_name, int global) { | ||
| 128 | InsertGlobalItem(combobox, global); | 124 | InsertGlobalItem(combobox, global); |
| 129 | QObject::connect(combobox, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), target, | 125 | QObject::connect(combobox, qOverload<int>(&QComboBox::activated), target, |
| 130 | [target, target_name](int index) { | 126 | [target](int index) { SetHighlight(target, index != 0); }); |
| 131 | ConfigurationShared::SetHighlight(target, target_name, index != 0); | ||
| 132 | }); | ||
| 133 | } | 127 | } |
| 134 | 128 | ||
| 135 | void ConfigurationShared::InsertGlobalItem(QComboBox* combobox, int global_index) { | 129 | void ConfigurationShared::InsertGlobalItem(QComboBox* combobox, int global_index) { |
diff --git a/src/yuzu/configuration/configuration_shared.h b/src/yuzu/configuration/configuration_shared.h index 003148c68..312b9e549 100644 --- a/src/yuzu/configuration/configuration_shared.h +++ b/src/yuzu/configuration/configuration_shared.h | |||
| @@ -39,13 +39,12 @@ void SetPerGameSetting(QComboBox* combobox, | |||
| 39 | void SetPerGameSetting(QComboBox* combobox, | 39 | void SetPerGameSetting(QComboBox* combobox, |
| 40 | const Settings::Setting<Settings::GPUAccuracy>* setting); | 40 | const Settings::Setting<Settings::GPUAccuracy>* setting); |
| 41 | 41 | ||
| 42 | void SetHighlight(QWidget* widget, const std::string& name, bool highlighted); | 42 | void SetHighlight(QWidget* widget, bool highlighted); |
| 43 | void SetColoredTristate(QCheckBox* checkbox, const std::string& name, | 43 | void SetColoredTristate(QCheckBox* checkbox, const Settings::Setting<bool>& setting, |
| 44 | const Settings::Setting<bool>& setting, CheckState& tracker); | 44 | CheckState& tracker); |
| 45 | void SetColoredTristate(QCheckBox* checkbox, const std::string& name, bool global, bool state, | 45 | void SetColoredTristate(QCheckBox* checkbox, bool global, bool state, bool global_state, |
| 46 | bool global_state, CheckState& tracker); | 46 | CheckState& tracker); |
| 47 | void SetColoredComboBox(QComboBox* combobox, QWidget* target, const std::string& target_name, | 47 | void SetColoredComboBox(QComboBox* combobox, QWidget* target, int global); |
| 48 | int global); | ||
| 49 | 48 | ||
| 50 | void InsertGlobalItem(QComboBox* combobox, int global_index); | 49 | void InsertGlobalItem(QComboBox* combobox, int global_index); |
| 51 | 50 | ||
diff --git a/src/yuzu/configuration/configure.ui b/src/yuzu/configuration/configure.ui index 5f5d8e571..fcf42cdcb 100644 --- a/src/yuzu/configuration/configure.ui +++ b/src/yuzu/configuration/configure.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>382</width> | 9 | <width>650</width> |
| 10 | <height>650</height> | 10 | <height>650</height> |
| 11 | </rect> | 11 | </rect> |
| 12 | </property> | 12 | </property> |
| @@ -26,13 +26,13 @@ | |||
| 26 | <widget class="QListWidget" name="selectorList"> | 26 | <widget class="QListWidget" name="selectorList"> |
| 27 | <property name="minimumSize"> | 27 | <property name="minimumSize"> |
| 28 | <size> | 28 | <size> |
| 29 | <width>150</width> | 29 | <width>120</width> |
| 30 | <height>0</height> | 30 | <height>0</height> |
| 31 | </size> | 31 | </size> |
| 32 | </property> | 32 | </property> |
| 33 | <property name="maximumSize"> | 33 | <property name="maximumSize"> |
| 34 | <size> | 34 | <size> |
| 35 | <width>150</width> | 35 | <width>120</width> |
| 36 | <height>16777215</height> | 36 | <height>16777215</height> |
| 37 | </size> | 37 | </size> |
| 38 | </property> | 38 | </property> |
| @@ -44,76 +44,121 @@ | |||
| 44 | <number>0</number> | 44 | <number>0</number> |
| 45 | </property> | 45 | </property> |
| 46 | <widget class="ConfigureGeneral" name="generalTab"> | 46 | <widget class="ConfigureGeneral" name="generalTab"> |
| 47 | <property name="accessibleName"> | ||
| 48 | <string>General</string> | ||
| 49 | </property> | ||
| 47 | <attribute name="title"> | 50 | <attribute name="title"> |
| 48 | <string>General</string> | 51 | <string>General</string> |
| 49 | </attribute> | 52 | </attribute> |
| 50 | </widget> | 53 | </widget> |
| 51 | <widget class="ConfigureUi" name="uiTab"> | 54 | <widget class="ConfigureUi" name="uiTab"> |
| 55 | <property name="accessibleName"> | ||
| 56 | <string>UI</string> | ||
| 57 | </property> | ||
| 52 | <attribute name="title"> | 58 | <attribute name="title"> |
| 53 | <string>Game List</string> | 59 | <string>Game List</string> |
| 54 | </attribute> | 60 | </attribute> |
| 55 | </widget> | 61 | </widget> |
| 56 | <widget class="ConfigureSystem" name="systemTab"> | 62 | <widget class="ConfigureSystem" name="systemTab"> |
| 63 | <property name="accessibleName"> | ||
| 64 | <string>System</string> | ||
| 65 | </property> | ||
| 57 | <attribute name="title"> | 66 | <attribute name="title"> |
| 58 | <string>System</string> | 67 | <string>System</string> |
| 59 | </attribute> | 68 | </attribute> |
| 60 | </widget> | 69 | </widget> |
| 61 | <widget class="ConfigureProfileManager" name="profileManagerTab"> | 70 | <widget class="ConfigureProfileManager" name="profileManagerTab"> |
| 71 | <property name="accessibleName"> | ||
| 72 | <string>Profiles</string> | ||
| 73 | </property> | ||
| 62 | <attribute name="title"> | 74 | <attribute name="title"> |
| 63 | <string>Profiles</string> | 75 | <string>Profiles</string> |
| 64 | </attribute> | 76 | </attribute> |
| 65 | </widget> | 77 | </widget> |
| 66 | <widget class="ConfigureFilesystem" name="filesystemTab"> | 78 | <widget class="ConfigureFilesystem" name="filesystemTab"> |
| 79 | <property name="accessibleName"> | ||
| 80 | <string>Filesystem</string> | ||
| 81 | </property> | ||
| 67 | <attribute name="title"> | 82 | <attribute name="title"> |
| 68 | <string>Filesystem</string> | 83 | <string>Filesystem</string> |
| 69 | </attribute> | 84 | </attribute> |
| 70 | </widget> | 85 | </widget> |
| 71 | <widget class="ConfigureInputSimple" name="inputTab"> | 86 | <widget class="ConfigureInput" name="inputTab"> |
| 87 | <property name="accessibleName"> | ||
| 88 | <string>Controls</string> | ||
| 89 | </property> | ||
| 72 | <attribute name="title"> | 90 | <attribute name="title"> |
| 73 | <string>Input</string> | 91 | <string>Controls</string> |
| 74 | </attribute> | 92 | </attribute> |
| 75 | </widget> | 93 | </widget> |
| 76 | <widget class="ConfigureHotkeys" name="hotkeysTab"> | 94 | <widget class="ConfigureHotkeys" name="hotkeysTab"> |
| 95 | <property name="accessibleName"> | ||
| 96 | <string>Hotkeys</string> | ||
| 97 | </property> | ||
| 77 | <attribute name="title"> | 98 | <attribute name="title"> |
| 78 | <string>Hotkeys</string> | 99 | <string>Hotkeys</string> |
| 79 | </attribute> | 100 | </attribute> |
| 80 | </widget> | 101 | </widget> |
| 81 | <widget class="ConfigureCpu" name="cpuTab"> | 102 | <widget class="ConfigureCpu" name="cpuTab"> |
| 103 | <property name="accessibleName"> | ||
| 104 | <string>CPU</string> | ||
| 105 | </property> | ||
| 82 | <attribute name="title"> | 106 | <attribute name="title"> |
| 83 | <string>CPU</string> | 107 | <string>CPU</string> |
| 84 | </attribute> | 108 | </attribute> |
| 85 | </widget> | 109 | </widget> |
| 86 | <widget class="ConfigureCpuDebug" name="cpuDebugTab"> | 110 | <widget class="ConfigureCpuDebug" name="cpuDebugTab"> |
| 111 | <property name="accessibleName"> | ||
| 112 | <string>Debug</string> | ||
| 113 | </property> | ||
| 87 | <attribute name="title"> | 114 | <attribute name="title"> |
| 88 | <string>Debug</string> | 115 | <string>Debug</string> |
| 89 | </attribute> | 116 | </attribute> |
| 90 | </widget> | 117 | </widget> |
| 91 | <widget class="ConfigureGraphics" name="graphicsTab"> | 118 | <widget class="ConfigureGraphics" name="graphicsTab"> |
| 119 | <property name="accessibleName"> | ||
| 120 | <string>Graphics</string> | ||
| 121 | </property> | ||
| 92 | <attribute name="title"> | 122 | <attribute name="title"> |
| 93 | <string>Graphics</string> | 123 | <string>Graphics</string> |
| 94 | </attribute> | 124 | </attribute> |
| 95 | </widget> | 125 | </widget> |
| 96 | <widget class="ConfigureGraphicsAdvanced" name="graphicsAdvancedTab"> | 126 | <widget class="ConfigureGraphicsAdvanced" name="graphicsAdvancedTab"> |
| 127 | <property name="accessibleName"> | ||
| 128 | <string>Advanced</string> | ||
| 129 | </property> | ||
| 97 | <attribute name="title"> | 130 | <attribute name="title"> |
| 98 | <string>GraphicsAdvanced</string> | 131 | <string>GraphicsAdvanced</string> |
| 99 | </attribute> | 132 | </attribute> |
| 100 | </widget> | 133 | </widget> |
| 101 | <widget class="ConfigureAudio" name="audioTab"> | 134 | <widget class="ConfigureAudio" name="audioTab"> |
| 135 | <property name="accessibleName"> | ||
| 136 | <string>Audio</string> | ||
| 137 | </property> | ||
| 102 | <attribute name="title"> | 138 | <attribute name="title"> |
| 103 | <string>Audio</string> | 139 | <string>Audio</string> |
| 104 | </attribute> | 140 | </attribute> |
| 105 | </widget> | 141 | </widget> |
| 106 | <widget class="ConfigureDebug" name="debugTab"> | 142 | <widget class="ConfigureDebug" name="debugTab"> |
| 143 | <property name="accessibleName"> | ||
| 144 | <string>Debug</string> | ||
| 145 | </property> | ||
| 107 | <attribute name="title"> | 146 | <attribute name="title"> |
| 108 | <string>Debug</string> | 147 | <string>Debug</string> |
| 109 | </attribute> | 148 | </attribute> |
| 110 | </widget> | 149 | </widget> |
| 111 | <widget class="ConfigureWeb" name="webTab"> | 150 | <widget class="ConfigureWeb" name="webTab"> |
| 151 | <property name="accessibleName"> | ||
| 152 | <string>Web</string> | ||
| 153 | </property> | ||
| 112 | <attribute name="title"> | 154 | <attribute name="title"> |
| 113 | <string>Web</string> | 155 | <string>Web</string> |
| 114 | </attribute> | 156 | </attribute> |
| 115 | </widget> | 157 | </widget> |
| 116 | <widget class="ConfigureService" name="serviceTab"> | 158 | <widget class="ConfigureService" name="serviceTab"> |
| 159 | <property name="accessibleName"> | ||
| 160 | <string>Services</string> | ||
| 161 | </property> | ||
| 117 | <attribute name="title"> | 162 | <attribute name="title"> |
| 118 | <string>Services</string> | 163 | <string>Services</string> |
| 119 | </attribute> | 164 | </attribute> |
| @@ -205,9 +250,9 @@ | |||
| 205 | <container>1</container> | 250 | <container>1</container> |
| 206 | </customwidget> | 251 | </customwidget> |
| 207 | <customwidget> | 252 | <customwidget> |
| 208 | <class>ConfigureInputSimple</class> | 253 | <class>ConfigureInput</class> |
| 209 | <extends>QWidget</extends> | 254 | <extends>QWidget</extends> |
| 210 | <header>configuration/configure_input_simple.h</header> | 255 | <header>configuration/configure_input.h</header> |
| 211 | <container>1</container> | 256 | <container>1</container> |
| 212 | </customwidget> | 257 | </customwidget> |
| 213 | <customwidget> | 258 | <customwidget> |
diff --git a/src/yuzu/configuration/configure_audio.cpp b/src/yuzu/configuration/configure_audio.cpp index fea632531..fa9124ecf 100644 --- a/src/yuzu/configuration/configure_audio.cpp +++ b/src/yuzu/configuration/configure_audio.cpp | |||
| @@ -59,7 +59,7 @@ void ConfigureAudio::SetConfiguration() { | |||
| 59 | ui->volume_combo_box->setCurrentIndex(1); | 59 | ui->volume_combo_box->setCurrentIndex(1); |
| 60 | ui->volume_slider->setEnabled(true); | 60 | ui->volume_slider->setEnabled(true); |
| 61 | } | 61 | } |
| 62 | ConfigurationShared::SetHighlight(ui->volume_layout, "volume_layout", | 62 | ConfigurationShared::SetHighlight(ui->volume_layout, |
| 63 | !Settings::values.volume.UsingGlobal()); | 63 | !Settings::values.volume.UsingGlobal()); |
| 64 | } | 64 | } |
| 65 | SetVolumeIndicatorText(ui->volume_slider->sliderPosition()); | 65 | SetVolumeIndicatorText(ui->volume_slider->sliderPosition()); |
| @@ -173,14 +173,13 @@ void ConfigureAudio::SetupPerGameUI() { | |||
| 173 | return; | 173 | return; |
| 174 | } | 174 | } |
| 175 | 175 | ||
| 176 | ConfigurationShared::SetColoredTristate(ui->toggle_audio_stretching, "toggle_audio_stretching", | 176 | ConfigurationShared::SetColoredTristate(ui->toggle_audio_stretching, |
| 177 | Settings::values.enable_audio_stretching, | 177 | Settings::values.enable_audio_stretching, |
| 178 | enable_audio_stretching); | 178 | enable_audio_stretching); |
| 179 | connect(ui->volume_combo_box, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), | 179 | connect(ui->volume_combo_box, qOverload<int>(&QComboBox::activated), this, [this](int index) { |
| 180 | this, [this](int index) { | 180 | ui->volume_slider->setEnabled(index == 1); |
| 181 | ui->volume_slider->setEnabled(index == 1); | 181 | ConfigurationShared::SetHighlight(ui->volume_layout, index == 1); |
| 182 | ConfigurationShared::SetHighlight(ui->volume_layout, "volume_layout", index == 1); | 182 | }); |
| 183 | }); | ||
| 184 | 183 | ||
| 185 | ui->output_sink_combo_box->setVisible(false); | 184 | ui->output_sink_combo_box->setVisible(false); |
| 186 | ui->output_sink_label->setVisible(false); | 185 | ui->output_sink_label->setVisible(false); |
diff --git a/src/yuzu/configuration/configure_cpu.cpp b/src/yuzu/configuration/configure_cpu.cpp index 7493e5ffb..37fcd6adc 100644 --- a/src/yuzu/configuration/configure_cpu.cpp +++ b/src/yuzu/configuration/configure_cpu.cpp | |||
| @@ -19,6 +19,8 @@ ConfigureCpu::ConfigureCpu(QWidget* parent) : QWidget(parent), ui(new Ui::Config | |||
| 19 | 19 | ||
| 20 | connect(ui->accuracy, qOverload<int>(&QComboBox::activated), this, | 20 | connect(ui->accuracy, qOverload<int>(&QComboBox::activated), this, |
| 21 | &ConfigureCpu::AccuracyUpdated); | 21 | &ConfigureCpu::AccuracyUpdated); |
| 22 | connect(ui->accuracy, qOverload<int>(&QComboBox::currentIndexChanged), this, | ||
| 23 | &ConfigureCpu::UpdateGroup); | ||
| 22 | } | 24 | } |
| 23 | 25 | ||
| 24 | ConfigureCpu::~ConfigureCpu() = default; | 26 | ConfigureCpu::~ConfigureCpu() = default; |
| @@ -28,6 +30,12 @@ void ConfigureCpu::SetConfiguration() { | |||
| 28 | 30 | ||
| 29 | ui->accuracy->setEnabled(runtime_lock); | 31 | ui->accuracy->setEnabled(runtime_lock); |
| 30 | ui->accuracy->setCurrentIndex(static_cast<int>(Settings::values.cpu_accuracy)); | 32 | ui->accuracy->setCurrentIndex(static_cast<int>(Settings::values.cpu_accuracy)); |
| 33 | UpdateGroup(static_cast<int>(Settings::values.cpu_accuracy)); | ||
| 34 | |||
| 35 | ui->cpuopt_unsafe_unfuse_fma->setEnabled(runtime_lock); | ||
| 36 | ui->cpuopt_unsafe_unfuse_fma->setChecked(Settings::values.cpuopt_unsafe_unfuse_fma); | ||
| 37 | ui->cpuopt_unsafe_reduce_fp_error->setEnabled(runtime_lock); | ||
| 38 | ui->cpuopt_unsafe_reduce_fp_error->setChecked(Settings::values.cpuopt_unsafe_reduce_fp_error); | ||
| 31 | } | 39 | } |
| 32 | 40 | ||
| 33 | void ConfigureCpu::AccuracyUpdated(int index) { | 41 | void ConfigureCpu::AccuracyUpdated(int index) { |
| @@ -38,14 +46,21 @@ void ConfigureCpu::AccuracyUpdated(int index) { | |||
| 38 | QMessageBox::Yes | QMessageBox::No); | 46 | QMessageBox::Yes | QMessageBox::No); |
| 39 | if (result == QMessageBox::No) { | 47 | if (result == QMessageBox::No) { |
| 40 | ui->accuracy->setCurrentIndex(static_cast<int>(Settings::CPUAccuracy::Accurate)); | 48 | ui->accuracy->setCurrentIndex(static_cast<int>(Settings::CPUAccuracy::Accurate)); |
| 41 | return; | 49 | UpdateGroup(static_cast<int>(Settings::CPUAccuracy::Accurate)); |
| 42 | } | 50 | } |
| 43 | } | 51 | } |
| 44 | } | 52 | } |
| 45 | 53 | ||
| 54 | void ConfigureCpu::UpdateGroup(int index) { | ||
| 55 | ui->unsafe_group->setVisible(static_cast<Settings::CPUAccuracy>(index) == | ||
| 56 | Settings::CPUAccuracy::Unsafe); | ||
| 57 | } | ||
| 58 | |||
| 46 | void ConfigureCpu::ApplyConfiguration() { | 59 | void ConfigureCpu::ApplyConfiguration() { |
| 47 | Settings::values.cpu_accuracy = | 60 | Settings::values.cpu_accuracy = |
| 48 | static_cast<Settings::CPUAccuracy>(ui->accuracy->currentIndex()); | 61 | static_cast<Settings::CPUAccuracy>(ui->accuracy->currentIndex()); |
| 62 | Settings::values.cpuopt_unsafe_unfuse_fma = ui->cpuopt_unsafe_unfuse_fma->isChecked(); | ||
| 63 | Settings::values.cpuopt_unsafe_reduce_fp_error = ui->cpuopt_unsafe_reduce_fp_error->isChecked(); | ||
| 49 | } | 64 | } |
| 50 | 65 | ||
| 51 | void ConfigureCpu::changeEvent(QEvent* event) { | 66 | void ConfigureCpu::changeEvent(QEvent* event) { |
diff --git a/src/yuzu/configuration/configure_cpu.h b/src/yuzu/configuration/configure_cpu.h index e4741d3a4..3c5683d81 100644 --- a/src/yuzu/configuration/configure_cpu.h +++ b/src/yuzu/configuration/configure_cpu.h | |||
| @@ -26,6 +26,7 @@ private: | |||
| 26 | void RetranslateUI(); | 26 | void RetranslateUI(); |
| 27 | 27 | ||
| 28 | void AccuracyUpdated(int index); | 28 | void AccuracyUpdated(int index); |
| 29 | void UpdateGroup(int index); | ||
| 29 | 30 | ||
| 30 | void SetConfiguration(); | 31 | void SetConfiguration(); |
| 31 | 32 | ||
diff --git a/src/yuzu/configuration/configure_cpu.ui b/src/yuzu/configuration/configure_cpu.ui index bf6ea79bb..ebdd2e6e9 100644 --- a/src/yuzu/configuration/configure_cpu.ui +++ b/src/yuzu/configuration/configure_cpu.ui | |||
| @@ -40,6 +40,11 @@ | |||
| 40 | </item> | 40 | </item> |
| 41 | <item> | 41 | <item> |
| 42 | <property name="text"> | 42 | <property name="text"> |
| 43 | <string>Unsafe</string> | ||
| 44 | </property> | ||
| 45 | </item> | ||
| 46 | <item> | ||
| 47 | <property name="text"> | ||
| 43 | <string>Enable Debug Mode</string> | 48 | <string>Enable Debug Mode</string> |
| 44 | </property> | 49 | </property> |
| 45 | </item> | 50 | </item> |
| @@ -63,6 +68,53 @@ | |||
| 63 | </layout> | 68 | </layout> |
| 64 | </item> | 69 | </item> |
| 65 | <item> | 70 | <item> |
| 71 | <layout class="QVBoxLayout"> | ||
| 72 | <item> | ||
| 73 | <widget class="QGroupBox" name="unsafe_group"> | ||
| 74 | <property name="title"> | ||
| 75 | <string>Unsafe CPU Optimization Settings</string> | ||
| 76 | </property> | ||
| 77 | <layout class="QVBoxLayout"> | ||
| 78 | <item> | ||
| 79 | <widget class="QLabel"> | ||
| 80 | <property name="wordWrap"> | ||
| 81 | <bool>1</bool> | ||
| 82 | </property> | ||
| 83 | <property name="text"> | ||
| 84 | <string>These settings reduce accuracy for speed.</string> | ||
| 85 | </property> | ||
| 86 | </widget> | ||
| 87 | </item> | ||
| 88 | <item> | ||
| 89 | <widget class="QCheckBox" name="cpuopt_unsafe_unfuse_fma"> | ||
| 90 | <property name="text"> | ||
| 91 | <string>Unfuse FMA (improve performance on CPUs without FMA)</string> | ||
| 92 | </property> | ||
| 93 | <property name="toolTip"> | ||
| 94 | <string> | ||
| 95 | <div>This option improves speed by reducing accuracy of fused-multiply-add instructions on CPUs without native FMA support.</div> | ||
| 96 | </string> | ||
| 97 | </property> | ||
| 98 | </widget> | ||
| 99 | </item> | ||
| 100 | <item> | ||
| 101 | <widget class="QCheckBox" name="cpuopt_unsafe_reduce_fp_error"> | ||
| 102 | <property name="text"> | ||
| 103 | <string>Faster FRSQRTE and FRECPE</string> | ||
| 104 | </property> | ||
| 105 | <property name="toolTip"> | ||
| 106 | <string> | ||
| 107 | <div>This option improves the speed of some approximate floating-point functions by using less accurate native approximations.</div> | ||
| 108 | </string> | ||
| 109 | </property> | ||
| 110 | </widget> | ||
| 111 | </item> | ||
| 112 | </layout> | ||
| 113 | </widget> | ||
| 114 | </item> | ||
| 115 | </layout> | ||
| 116 | </item> | ||
| 117 | <item> | ||
| 66 | <spacer name="verticalSpacer"> | 118 | <spacer name="verticalSpacer"> |
| 67 | <property name="orientation"> | 119 | <property name="orientation"> |
| 68 | <enum>Qt::Vertical</enum> | 120 | <enum>Qt::Vertical</enum> |
diff --git a/src/yuzu/configuration/configure_debug.cpp b/src/yuzu/configuration/configure_debug.cpp index d0e71dd60..2bfe2c306 100644 --- a/src/yuzu/configuration/configure_debug.cpp +++ b/src/yuzu/configuration/configure_debug.cpp | |||
| @@ -19,7 +19,8 @@ ConfigureDebug::ConfigureDebug(QWidget* parent) : QWidget(parent), ui(new Ui::Co | |||
| 19 | SetConfiguration(); | 19 | SetConfiguration(); |
| 20 | 20 | ||
| 21 | connect(ui->open_log_button, &QPushButton::clicked, []() { | 21 | connect(ui->open_log_button, &QPushButton::clicked, []() { |
| 22 | QString path = QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::LogDir)); | 22 | const auto path = |
| 23 | QString::fromStdString(Common::FS::GetUserPath(Common::FS::UserPath::LogDir)); | ||
| 23 | QDesktopServices::openUrl(QUrl::fromLocalFile(path)); | 24 | QDesktopServices::openUrl(QUrl::fromLocalFile(path)); |
| 24 | }); | 25 | }); |
| 25 | } | 26 | } |
diff --git a/src/yuzu/configuration/configure_debug_controller.cpp b/src/yuzu/configuration/configure_debug_controller.cpp new file mode 100644 index 000000000..0097c9a29 --- /dev/null +++ b/src/yuzu/configuration/configure_debug_controller.cpp | |||
| @@ -0,0 +1,40 @@ | |||
| 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 "ui_configure_debug_controller.h" | ||
| 6 | #include "yuzu/configuration/configure_debug_controller.h" | ||
| 7 | |||
| 8 | ConfigureDebugController::ConfigureDebugController(QWidget* parent, | ||
| 9 | InputCommon::InputSubsystem* input_subsystem) | ||
| 10 | : QDialog(parent), ui(std::make_unique<Ui::ConfigureDebugController>()), | ||
| 11 | debug_controller(new ConfigureInputPlayer(this, 9, nullptr, input_subsystem, true)) { | ||
| 12 | ui->setupUi(this); | ||
| 13 | |||
| 14 | ui->controllerLayout->addWidget(debug_controller); | ||
| 15 | |||
| 16 | connect(ui->clear_all_button, &QPushButton::clicked, this, | ||
| 17 | [this] { debug_controller->ClearAll(); }); | ||
| 18 | connect(ui->restore_defaults_button, &QPushButton::clicked, this, | ||
| 19 | [this] { debug_controller->RestoreDefaults(); }); | ||
| 20 | |||
| 21 | RetranslateUI(); | ||
| 22 | } | ||
| 23 | |||
| 24 | ConfigureDebugController::~ConfigureDebugController() = default; | ||
| 25 | |||
| 26 | void ConfigureDebugController::ApplyConfiguration() { | ||
| 27 | debug_controller->ApplyConfiguration(); | ||
| 28 | } | ||
| 29 | |||
| 30 | void ConfigureDebugController::changeEvent(QEvent* event) { | ||
| 31 | if (event->type() == QEvent::LanguageChange) { | ||
| 32 | RetranslateUI(); | ||
| 33 | } | ||
| 34 | |||
| 35 | QDialog::changeEvent(event); | ||
| 36 | } | ||
| 37 | |||
| 38 | void ConfigureDebugController::RetranslateUI() { | ||
| 39 | ui->retranslateUi(this); | ||
| 40 | } | ||
diff --git a/src/yuzu/configuration/configure_debug_controller.h b/src/yuzu/configuration/configure_debug_controller.h new file mode 100644 index 000000000..34dcf705f --- /dev/null +++ b/src/yuzu/configuration/configure_debug_controller.h | |||
| @@ -0,0 +1,38 @@ | |||
| 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 <memory> | ||
| 8 | #include <QDialog> | ||
| 9 | #include "yuzu/configuration/configure_input_player.h" | ||
| 10 | |||
| 11 | class QPushButton; | ||
| 12 | |||
| 13 | namespace InputCommon { | ||
| 14 | class InputSubsystem; | ||
| 15 | } | ||
| 16 | |||
| 17 | namespace Ui { | ||
| 18 | class ConfigureDebugController; | ||
| 19 | } | ||
| 20 | |||
| 21 | class ConfigureDebugController : public QDialog { | ||
| 22 | Q_OBJECT | ||
| 23 | |||
| 24 | public: | ||
| 25 | explicit ConfigureDebugController(QWidget* parent, | ||
| 26 | InputCommon::InputSubsystem* input_subsystem); | ||
| 27 | ~ConfigureDebugController() override; | ||
| 28 | |||
| 29 | void ApplyConfiguration(); | ||
| 30 | |||
| 31 | private: | ||
| 32 | void changeEvent(QEvent* event) override; | ||
| 33 | void RetranslateUI(); | ||
| 34 | |||
| 35 | std::unique_ptr<Ui::ConfigureDebugController> ui; | ||
| 36 | |||
| 37 | ConfigureInputPlayer* debug_controller; | ||
| 38 | }; | ||
diff --git a/src/yuzu/configuration/configure_debug_controller.ui b/src/yuzu/configuration/configure_debug_controller.ui new file mode 100644 index 000000000..a95ed50ff --- /dev/null +++ b/src/yuzu/configuration/configure_debug_controller.ui | |||
| @@ -0,0 +1,97 @@ | |||
| 1 | <?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | <ui version="4.0"> | ||
| 3 | <class>ConfigureDebugController</class> | ||
| 4 | <widget class="QDialog" name="ConfigureDebugController"> | ||
| 5 | <property name="geometry"> | ||
| 6 | <rect> | ||
| 7 | <x>0</x> | ||
| 8 | <y>0</y> | ||
| 9 | <width>780</width> | ||
| 10 | <height>500</height> | ||
| 11 | </rect> | ||
| 12 | </property> | ||
| 13 | <property name="windowTitle"> | ||
| 14 | <string>Configure Debug Controller</string> | ||
| 15 | </property> | ||
| 16 | <layout class="QVBoxLayout" name="verticalLayout"> | ||
| 17 | <property name="spacing"> | ||
| 18 | <number>2</number> | ||
| 19 | </property> | ||
| 20 | <property name="leftMargin"> | ||
| 21 | <number>9</number> | ||
| 22 | </property> | ||
| 23 | <property name="topMargin"> | ||
| 24 | <number>9</number> | ||
| 25 | </property> | ||
| 26 | <property name="rightMargin"> | ||
| 27 | <number>9</number> | ||
| 28 | </property> | ||
| 29 | <property name="bottomMargin"> | ||
| 30 | <number>9</number> | ||
| 31 | </property> | ||
| 32 | <item> | ||
| 33 | <layout class="QHBoxLayout" name="controllerLayout"/> | ||
| 34 | </item> | ||
| 35 | <item> | ||
| 36 | <layout class="QHBoxLayout" name="horizontalLayout"> | ||
| 37 | <item> | ||
| 38 | <widget class="QPushButton" name="clear_all_button"> | ||
| 39 | <property name="text"> | ||
| 40 | <string>Clear</string> | ||
| 41 | </property> | ||
| 42 | </widget> | ||
| 43 | </item> | ||
| 44 | <item> | ||
| 45 | <widget class="QPushButton" name="restore_defaults_button"> | ||
| 46 | <property name="text"> | ||
| 47 | <string>Defaults</string> | ||
| 48 | </property> | ||
| 49 | </widget> | ||
| 50 | </item> | ||
| 51 | <item> | ||
| 52 | <widget class="QDialogButtonBox" name="buttonBox"> | ||
| 53 | <property name="standardButtons"> | ||
| 54 | <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> | ||
| 55 | </property> | ||
| 56 | </widget> | ||
| 57 | </item> | ||
| 58 | </layout> | ||
| 59 | </item> | ||
| 60 | </layout> | ||
| 61 | </widget> | ||
| 62 | <resources/> | ||
| 63 | <connections> | ||
| 64 | <connection> | ||
| 65 | <sender>buttonBox</sender> | ||
| 66 | <signal>accepted()</signal> | ||
| 67 | <receiver>ConfigureDebugController</receiver> | ||
| 68 | <slot>accept()</slot> | ||
| 69 | <hints> | ||
| 70 | <hint type="sourcelabel"> | ||
| 71 | <x>140</x> | ||
| 72 | <y>318</y> | ||
| 73 | </hint> | ||
| 74 | <hint type="destinationlabel"> | ||
| 75 | <x>140</x> | ||
| 76 | <y>169</y> | ||
| 77 | </hint> | ||
| 78 | </hints> | ||
| 79 | </connection> | ||
| 80 | <connection> | ||
| 81 | <sender>buttonBox</sender> | ||
| 82 | <signal>rejected()</signal> | ||
| 83 | <receiver>ConfigureDebugController</receiver> | ||
| 84 | <slot>reject()</slot> | ||
| 85 | <hints> | ||
| 86 | <hint type="sourcelabel"> | ||
| 87 | <x>140</x> | ||
| 88 | <y>318</y> | ||
| 89 | </hint> | ||
| 90 | <hint type="destinationlabel"> | ||
| 91 | <x>140</x> | ||
| 92 | <y>169</y> | ||
| 93 | </hint> | ||
| 94 | </hints> | ||
| 95 | </connection> | ||
| 96 | </connections> | ||
| 97 | </ui> | ||
diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp index 4e30dc51e..8186929a6 100644 --- a/src/yuzu/configuration/configure_dialog.cpp +++ b/src/yuzu/configuration/configure_dialog.cpp | |||
| @@ -12,7 +12,8 @@ | |||
| 12 | #include "yuzu/configuration/configure_input_player.h" | 12 | #include "yuzu/configuration/configure_input_player.h" |
| 13 | #include "yuzu/hotkeys.h" | 13 | #include "yuzu/hotkeys.h" |
| 14 | 14 | ||
| 15 | ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry) | 15 | ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry, |
| 16 | InputCommon::InputSubsystem* input_subsystem) | ||
| 16 | : QDialog(parent), ui(new Ui::ConfigureDialog), registry(registry) { | 17 | : QDialog(parent), ui(new Ui::ConfigureDialog), registry(registry) { |
| 17 | Settings::configuring_global = true; | 18 | Settings::configuring_global = true; |
| 18 | 19 | ||
| @@ -20,6 +21,8 @@ ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry) | |||
| 20 | ui->hotkeysTab->Populate(registry); | 21 | ui->hotkeysTab->Populate(registry); |
| 21 | setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); | 22 | setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); |
| 22 | 23 | ||
| 24 | ui->inputTab->Initialize(input_subsystem); | ||
| 25 | |||
| 23 | SetConfiguration(); | 26 | SetConfiguration(); |
| 24 | PopulateSelectionList(); | 27 | PopulateSelectionList(); |
| 25 | 28 | ||
| @@ -80,12 +83,12 @@ Q_DECLARE_METATYPE(QList<QWidget*>); | |||
| 80 | 83 | ||
| 81 | void ConfigureDialog::PopulateSelectionList() { | 84 | void ConfigureDialog::PopulateSelectionList() { |
| 82 | const std::array<std::pair<QString, QList<QWidget*>>, 6> items{ | 85 | const std::array<std::pair<QString, QList<QWidget*>>, 6> items{ |
| 83 | {{tr("General"), {ui->generalTab, ui->webTab, ui->debugTab, ui->uiTab}}, | 86 | {{tr("General"), {ui->generalTab, ui->hotkeysTab, ui->uiTab, ui->webTab, ui->debugTab}}, |
| 84 | {tr("System"), {ui->systemTab, ui->profileManagerTab, ui->serviceTab, ui->filesystemTab}}, | 87 | {tr("System"), {ui->systemTab, ui->profileManagerTab, ui->serviceTab, ui->filesystemTab}}, |
| 85 | {tr("CPU"), {ui->cpuTab, ui->cpuDebugTab}}, | 88 | {tr("CPU"), {ui->cpuTab, ui->cpuDebugTab}}, |
| 86 | {tr("Graphics"), {ui->graphicsTab, ui->graphicsAdvancedTab}}, | 89 | {tr("Graphics"), {ui->graphicsTab, ui->graphicsAdvancedTab}}, |
| 87 | {tr("Audio"), {ui->audioTab}}, | 90 | {tr("Audio"), {ui->audioTab}}, |
| 88 | {tr("Controls"), {ui->inputTab, ui->hotkeysTab}}}, | 91 | {tr("Controls"), ui->inputTab->GetSubTabs()}}, |
| 89 | }; | 92 | }; |
| 90 | 93 | ||
| 91 | [[maybe_unused]] const QSignalBlocker blocker(ui->selectorList); | 94 | [[maybe_unused]] const QSignalBlocker blocker(ui->selectorList); |
| @@ -117,7 +120,7 @@ void ConfigureDialog::UpdateVisibleTabs() { | |||
| 117 | {ui->generalTab, tr("General")}, | 120 | {ui->generalTab, tr("General")}, |
| 118 | {ui->systemTab, tr("System")}, | 121 | {ui->systemTab, tr("System")}, |
| 119 | {ui->profileManagerTab, tr("Profiles")}, | 122 | {ui->profileManagerTab, tr("Profiles")}, |
| 120 | {ui->inputTab, tr("Input")}, | 123 | {ui->inputTab, tr("Controls")}, |
| 121 | {ui->hotkeysTab, tr("Hotkeys")}, | 124 | {ui->hotkeysTab, tr("Hotkeys")}, |
| 122 | {ui->cpuTab, tr("CPU")}, | 125 | {ui->cpuTab, tr("CPU")}, |
| 123 | {ui->cpuDebugTab, tr("Debug")}, | 126 | {ui->cpuDebugTab, tr("Debug")}, |
| @@ -138,6 +141,6 @@ void ConfigureDialog::UpdateVisibleTabs() { | |||
| 138 | const QList<QWidget*> tabs = qvariant_cast<QList<QWidget*>>(items[0]->data(Qt::UserRole)); | 141 | const QList<QWidget*> tabs = qvariant_cast<QList<QWidget*>>(items[0]->data(Qt::UserRole)); |
| 139 | 142 | ||
| 140 | for (const auto tab : tabs) { | 143 | for (const auto tab : tabs) { |
| 141 | ui->tabWidget->addTab(tab, widgets.at(tab)); | 144 | ui->tabWidget->addTab(tab, tab->accessibleName()); |
| 142 | } | 145 | } |
| 143 | } | 146 | } |
diff --git a/src/yuzu/configuration/configure_dialog.h b/src/yuzu/configuration/configure_dialog.h index 4289bc225..570c3b941 100644 --- a/src/yuzu/configuration/configure_dialog.h +++ b/src/yuzu/configuration/configure_dialog.h | |||
| @@ -9,6 +9,10 @@ | |||
| 9 | 9 | ||
| 10 | class HotkeyRegistry; | 10 | class HotkeyRegistry; |
| 11 | 11 | ||
| 12 | namespace InputCommon { | ||
| 13 | class InputSubsystem; | ||
| 14 | } | ||
| 15 | |||
| 12 | namespace Ui { | 16 | namespace Ui { |
| 13 | class ConfigureDialog; | 17 | class ConfigureDialog; |
| 14 | } | 18 | } |
| @@ -17,7 +21,8 @@ class ConfigureDialog : public QDialog { | |||
| 17 | Q_OBJECT | 21 | Q_OBJECT |
| 18 | 22 | ||
| 19 | public: | 23 | public: |
| 20 | explicit ConfigureDialog(QWidget* parent, HotkeyRegistry& registry); | 24 | explicit ConfigureDialog(QWidget* parent, HotkeyRegistry& registry, |
| 25 | InputCommon::InputSubsystem* input_subsystem); | ||
| 21 | ~ConfigureDialog() override; | 26 | ~ConfigureDialog() override; |
| 22 | 27 | ||
| 23 | void ApplyConfiguration(); | 28 | void ApplyConfiguration(); |
diff --git a/src/yuzu/configuration/configure_filesystem.cpp b/src/yuzu/configuration/configure_filesystem.cpp index a089f5733..7ab4a80f7 100644 --- a/src/yuzu/configuration/configure_filesystem.cpp +++ b/src/yuzu/configuration/configure_filesystem.cpp | |||
| @@ -42,16 +42,16 @@ ConfigureFilesystem::~ConfigureFilesystem() = default; | |||
| 42 | 42 | ||
| 43 | void ConfigureFilesystem::setConfiguration() { | 43 | void ConfigureFilesystem::setConfiguration() { |
| 44 | ui->nand_directory_edit->setText( | 44 | ui->nand_directory_edit->setText( |
| 45 | QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::NANDDir))); | 45 | QString::fromStdString(Common::FS::GetUserPath(Common::FS::UserPath::NANDDir))); |
| 46 | ui->sdmc_directory_edit->setText( | 46 | ui->sdmc_directory_edit->setText( |
| 47 | QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir))); | 47 | QString::fromStdString(Common::FS::GetUserPath(Common::FS::UserPath::SDMCDir))); |
| 48 | ui->gamecard_path_edit->setText(QString::fromStdString(Settings::values.gamecard_path)); | 48 | ui->gamecard_path_edit->setText(QString::fromStdString(Settings::values.gamecard_path)); |
| 49 | ui->dump_path_edit->setText( | 49 | ui->dump_path_edit->setText( |
| 50 | QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::DumpDir))); | 50 | QString::fromStdString(Common::FS::GetUserPath(Common::FS::UserPath::DumpDir))); |
| 51 | ui->load_path_edit->setText( | 51 | ui->load_path_edit->setText( |
| 52 | QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::LoadDir))); | 52 | QString::fromStdString(Common::FS::GetUserPath(Common::FS::UserPath::LoadDir))); |
| 53 | ui->cache_directory_edit->setText( | 53 | ui->cache_directory_edit->setText( |
| 54 | QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::CacheDir))); | 54 | QString::fromStdString(Common::FS::GetUserPath(Common::FS::UserPath::CacheDir))); |
| 55 | 55 | ||
| 56 | ui->gamecard_inserted->setChecked(Settings::values.gamecard_inserted); | 56 | ui->gamecard_inserted->setChecked(Settings::values.gamecard_inserted); |
| 57 | ui->gamecard_current_game->setChecked(Settings::values.gamecard_current_game); | 57 | ui->gamecard_current_game->setChecked(Settings::values.gamecard_current_game); |
| @@ -64,14 +64,16 @@ void ConfigureFilesystem::setConfiguration() { | |||
| 64 | } | 64 | } |
| 65 | 65 | ||
| 66 | void ConfigureFilesystem::applyConfiguration() { | 66 | void ConfigureFilesystem::applyConfiguration() { |
| 67 | FileUtil::GetUserPath(FileUtil::UserPath::NANDDir, | 67 | Common::FS::GetUserPath(Common::FS::UserPath::NANDDir, |
| 68 | ui->nand_directory_edit->text().toStdString()); | 68 | ui->nand_directory_edit->text().toStdString()); |
| 69 | FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir, | 69 | Common::FS::GetUserPath(Common::FS::UserPath::SDMCDir, |
| 70 | ui->sdmc_directory_edit->text().toStdString()); | 70 | ui->sdmc_directory_edit->text().toStdString()); |
| 71 | FileUtil::GetUserPath(FileUtil::UserPath::DumpDir, ui->dump_path_edit->text().toStdString()); | 71 | Common::FS::GetUserPath(Common::FS::UserPath::DumpDir, |
| 72 | FileUtil::GetUserPath(FileUtil::UserPath::LoadDir, ui->load_path_edit->text().toStdString()); | 72 | ui->dump_path_edit->text().toStdString()); |
| 73 | FileUtil::GetUserPath(FileUtil::UserPath::CacheDir, | 73 | Common::FS::GetUserPath(Common::FS::UserPath::LoadDir, |
| 74 | ui->cache_directory_edit->text().toStdString()); | 74 | ui->load_path_edit->text().toStdString()); |
| 75 | Common::FS::GetUserPath(Common::FS::UserPath::CacheDir, | ||
| 76 | ui->cache_directory_edit->text().toStdString()); | ||
| 75 | Settings::values.gamecard_path = ui->gamecard_path_edit->text().toStdString(); | 77 | Settings::values.gamecard_path = ui->gamecard_path_edit->text().toStdString(); |
| 76 | 78 | ||
| 77 | Settings::values.gamecard_inserted = ui->gamecard_inserted->isChecked(); | 79 | Settings::values.gamecard_inserted = ui->gamecard_inserted->isChecked(); |
| @@ -121,12 +123,13 @@ void ConfigureFilesystem::SetDirectory(DirectoryTarget target, QLineEdit* edit) | |||
| 121 | } | 123 | } |
| 122 | 124 | ||
| 123 | void ConfigureFilesystem::ResetMetadata() { | 125 | void ConfigureFilesystem::ResetMetadata() { |
| 124 | if (!FileUtil::Exists(FileUtil::GetUserPath(FileUtil::UserPath::CacheDir) + DIR_SEP + | 126 | if (!Common::FS::Exists(Common::FS::GetUserPath(Common::FS::UserPath::CacheDir) + DIR_SEP + |
| 125 | "game_list")) { | 127 | "game_list")) { |
| 126 | QMessageBox::information(this, tr("Reset Metadata Cache"), | 128 | QMessageBox::information(this, tr("Reset Metadata Cache"), |
| 127 | tr("The metadata cache is already empty.")); | 129 | tr("The metadata cache is already empty.")); |
| 128 | } else if (FileUtil::DeleteDirRecursively(FileUtil::GetUserPath(FileUtil::UserPath::CacheDir) + | 130 | } else if (Common::FS::DeleteDirRecursively( |
| 129 | DIR_SEP + "game_list")) { | 131 | Common::FS::GetUserPath(Common::FS::UserPath::CacheDir) + DIR_SEP + |
| 132 | "game_list")) { | ||
| 130 | QMessageBox::information(this, tr("Reset Metadata Cache"), | 133 | QMessageBox::information(this, tr("Reset Metadata Cache"), |
| 131 | tr("The operation completed successfully.")); | 134 | tr("The operation completed successfully.")); |
| 132 | UISettings::values.is_game_list_reload_pending.exchange(true); | 135 | UISettings::values.is_game_list_reload_pending.exchange(true); |
diff --git a/src/yuzu/configuration/configure_general.cpp b/src/yuzu/configuration/configure_general.cpp index c0dbd9855..830096ea0 100644 --- a/src/yuzu/configuration/configure_general.cpp +++ b/src/yuzu/configuration/configure_general.cpp | |||
| @@ -105,10 +105,10 @@ void ConfigureGeneral::SetupPerGameUI() { | |||
| 105 | ui->toggle_background_pause->setVisible(false); | 105 | ui->toggle_background_pause->setVisible(false); |
| 106 | ui->toggle_hide_mouse->setVisible(false); | 106 | ui->toggle_hide_mouse->setVisible(false); |
| 107 | 107 | ||
| 108 | ConfigurationShared::SetColoredTristate(ui->toggle_frame_limit, "toggle_frame_limit", | 108 | ConfigurationShared::SetColoredTristate(ui->toggle_frame_limit, |
| 109 | Settings::values.use_frame_limit, use_frame_limit); | 109 | Settings::values.use_frame_limit, use_frame_limit); |
| 110 | ConfigurationShared::SetColoredTristate(ui->use_multi_core, "use_multi_core", | 110 | ConfigurationShared::SetColoredTristate(ui->use_multi_core, Settings::values.use_multi_core, |
| 111 | Settings::values.use_multi_core, use_multi_core); | 111 | use_multi_core); |
| 112 | 112 | ||
| 113 | connect(ui->toggle_frame_limit, &QCheckBox::clicked, ui->frame_limit, [this]() { | 113 | connect(ui->toggle_frame_limit, &QCheckBox::clicked, ui->frame_limit, [this]() { |
| 114 | ui->frame_limit->setEnabled(ui->toggle_frame_limit->isChecked() && | 114 | ui->frame_limit->setEnabled(ui->toggle_frame_limit->isChecked() && |
diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp index 3e42531c3..07d818548 100644 --- a/src/yuzu/configuration/configure_graphics.cpp +++ b/src/yuzu/configuration/configure_graphics.cpp | |||
| @@ -34,9 +34,8 @@ ConfigureGraphics::ConfigureGraphics(QWidget* parent) | |||
| 34 | connect(ui->api, qOverload<int>(&QComboBox::currentIndexChanged), this, [this] { | 34 | connect(ui->api, qOverload<int>(&QComboBox::currentIndexChanged), this, [this] { |
| 35 | UpdateDeviceComboBox(); | 35 | UpdateDeviceComboBox(); |
| 36 | if (!Settings::configuring_global) { | 36 | if (!Settings::configuring_global) { |
| 37 | ConfigurationShared::SetHighlight(ui->api_layout, "api_layout", | 37 | ConfigurationShared::SetHighlight( |
| 38 | ui->api->currentIndex() != | 38 | ui->api_layout, ui->api->currentIndex() != ConfigurationShared::USE_GLOBAL_INDEX); |
| 39 | ConfigurationShared::USE_GLOBAL_INDEX); | ||
| 40 | } | 39 | } |
| 41 | }); | 40 | }); |
| 42 | connect(ui->device, qOverload<int>(&QComboBox::activated), this, | 41 | connect(ui->device, qOverload<int>(&QComboBox::activated), this, |
| @@ -80,17 +79,16 @@ void ConfigureGraphics::SetConfiguration() { | |||
| 80 | ui->aspect_ratio_combobox->setCurrentIndex(Settings::values.aspect_ratio.GetValue()); | 79 | ui->aspect_ratio_combobox->setCurrentIndex(Settings::values.aspect_ratio.GetValue()); |
| 81 | } else { | 80 | } else { |
| 82 | ConfigurationShared::SetPerGameSetting(ui->api, &Settings::values.renderer_backend); | 81 | ConfigurationShared::SetPerGameSetting(ui->api, &Settings::values.renderer_backend); |
| 83 | ConfigurationShared::SetHighlight(ui->api_layout, "api_layout", | 82 | ConfigurationShared::SetHighlight(ui->api_layout, |
| 84 | !Settings::values.renderer_backend.UsingGlobal()); | 83 | !Settings::values.renderer_backend.UsingGlobal()); |
| 85 | ConfigurationShared::SetPerGameSetting(ui->aspect_ratio_combobox, | 84 | ConfigurationShared::SetPerGameSetting(ui->aspect_ratio_combobox, |
| 86 | &Settings::values.aspect_ratio); | 85 | &Settings::values.aspect_ratio); |
| 87 | 86 | ||
| 88 | ui->bg_combobox->setCurrentIndex(Settings::values.bg_red.UsingGlobal() ? 0 : 1); | 87 | ui->bg_combobox->setCurrentIndex(Settings::values.bg_red.UsingGlobal() ? 0 : 1); |
| 89 | ui->bg_button->setEnabled(!Settings::values.bg_red.UsingGlobal()); | 88 | ui->bg_button->setEnabled(!Settings::values.bg_red.UsingGlobal()); |
| 90 | ConfigurationShared::SetHighlight(ui->ar_label, "ar_label", | 89 | ConfigurationShared::SetHighlight(ui->ar_label, |
| 91 | !Settings::values.aspect_ratio.UsingGlobal()); | 90 | !Settings::values.aspect_ratio.UsingGlobal()); |
| 92 | ConfigurationShared::SetHighlight(ui->bg_layout, "bg_layout", | 91 | ConfigurationShared::SetHighlight(ui->bg_layout, !Settings::values.bg_red.UsingGlobal()); |
| 93 | !Settings::values.bg_red.UsingGlobal()); | ||
| 94 | } | 92 | } |
| 95 | 93 | ||
| 96 | UpdateBackgroundColorButton(QColor::fromRgbF(Settings::values.bg_red.GetValue(), | 94 | UpdateBackgroundColorButton(QColor::fromRgbF(Settings::values.bg_red.GetValue(), |
| @@ -248,20 +246,18 @@ void ConfigureGraphics::SetupPerGameUI() { | |||
| 248 | return; | 246 | return; |
| 249 | } | 247 | } |
| 250 | 248 | ||
| 251 | connect(ui->bg_combobox, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), this, | 249 | connect(ui->bg_combobox, qOverload<int>(&QComboBox::activated), this, [this](int index) { |
| 252 | [this](int index) { | 250 | ui->bg_button->setEnabled(index == 1); |
| 253 | ui->bg_button->setEnabled(index == 1); | 251 | ConfigurationShared::SetHighlight(ui->bg_layout, index == 1); |
| 254 | ConfigurationShared::SetHighlight(ui->bg_layout, "bg_layout", index == 1); | 252 | }); |
| 255 | }); | ||
| 256 | 253 | ||
| 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( | 254 | ConfigurationShared::SetColoredTristate( |
| 261 | ui->use_asynchronous_gpu_emulation, "use_asynchronous_gpu_emulation", | 255 | ui->use_disk_shader_cache, Settings::values.use_disk_shader_cache, use_disk_shader_cache); |
| 262 | Settings::values.use_asynchronous_gpu_emulation, use_asynchronous_gpu_emulation); | 256 | ConfigurationShared::SetColoredTristate(ui->use_asynchronous_gpu_emulation, |
| 257 | Settings::values.use_asynchronous_gpu_emulation, | ||
| 258 | use_asynchronous_gpu_emulation); | ||
| 263 | 259 | ||
| 264 | ConfigurationShared::SetColoredComboBox(ui->aspect_ratio_combobox, ui->ar_label, "ar_label", | 260 | ConfigurationShared::SetColoredComboBox(ui->aspect_ratio_combobox, ui->ar_label, |
| 265 | Settings::values.aspect_ratio.GetValue(true)); | 261 | Settings::values.aspect_ratio.GetValue(true)); |
| 266 | ConfigurationShared::InsertGlobalItem( | 262 | ConfigurationShared::InsertGlobalItem( |
| 267 | ui->api, static_cast<int>(Settings::values.renderer_backend.GetValue(true))); | 263 | ui->api, static_cast<int>(Settings::values.renderer_backend.GetValue(true))); |
diff --git a/src/yuzu/configuration/configure_graphics_advanced.cpp b/src/yuzu/configuration/configure_graphics_advanced.cpp index c5d1a778c..73f276949 100644 --- a/src/yuzu/configuration/configure_graphics_advanced.cpp +++ b/src/yuzu/configuration/configure_graphics_advanced.cpp | |||
| @@ -41,9 +41,9 @@ void ConfigureGraphicsAdvanced::SetConfiguration() { | |||
| 41 | ConfigurationShared::SetPerGameSetting(ui->gpu_accuracy, &Settings::values.gpu_accuracy); | 41 | ConfigurationShared::SetPerGameSetting(ui->gpu_accuracy, &Settings::values.gpu_accuracy); |
| 42 | ConfigurationShared::SetPerGameSetting(ui->anisotropic_filtering_combobox, | 42 | ConfigurationShared::SetPerGameSetting(ui->anisotropic_filtering_combobox, |
| 43 | &Settings::values.max_anisotropy); | 43 | &Settings::values.max_anisotropy); |
| 44 | ConfigurationShared::SetHighlight(ui->label_gpu_accuracy, "label_gpu_accuracy", | 44 | ConfigurationShared::SetHighlight(ui->label_gpu_accuracy, |
| 45 | !Settings::values.gpu_accuracy.UsingGlobal()); | 45 | !Settings::values.gpu_accuracy.UsingGlobal()); |
| 46 | ConfigurationShared::SetHighlight(ui->af_label, "af_label", | 46 | ConfigurationShared::SetHighlight(ui->af_label, |
| 47 | !Settings::values.max_anisotropy.UsingGlobal()); | 47 | !Settings::values.max_anisotropy.UsingGlobal()); |
| 48 | } | 48 | } |
| 49 | } | 49 | } |
| @@ -131,20 +131,18 @@ void ConfigureGraphicsAdvanced::SetupPerGameUI() { | |||
| 131 | return; | 131 | return; |
| 132 | } | 132 | } |
| 133 | 133 | ||
| 134 | ConfigurationShared::SetColoredTristate(ui->use_vsync, "use_vsync", Settings::values.use_vsync, | 134 | ConfigurationShared::SetColoredTristate(ui->use_vsync, Settings::values.use_vsync, use_vsync); |
| 135 | use_vsync); | ||
| 136 | ConfigurationShared::SetColoredTristate(ui->use_assembly_shaders, "use_assembly_shaders", | ||
| 137 | Settings::values.use_assembly_shaders, | ||
| 138 | use_assembly_shaders); | ||
| 139 | ConfigurationShared::SetColoredTristate( | 135 | ConfigurationShared::SetColoredTristate( |
| 140 | ui->use_asynchronous_shaders, "use_asynchronous_shaders", | 136 | ui->use_assembly_shaders, Settings::values.use_assembly_shaders, use_assembly_shaders); |
| 141 | Settings::values.use_asynchronous_shaders, use_asynchronous_shaders); | 137 | ConfigurationShared::SetColoredTristate(ui->use_asynchronous_shaders, |
| 142 | ConfigurationShared::SetColoredTristate(ui->use_fast_gpu_time, "use_fast_gpu_time", | 138 | Settings::values.use_asynchronous_shaders, |
| 139 | use_asynchronous_shaders); | ||
| 140 | ConfigurationShared::SetColoredTristate(ui->use_fast_gpu_time, | ||
| 143 | Settings::values.use_fast_gpu_time, use_fast_gpu_time); | 141 | Settings::values.use_fast_gpu_time, use_fast_gpu_time); |
| 144 | ConfigurationShared::SetColoredComboBox( | 142 | ConfigurationShared::SetColoredComboBox( |
| 145 | ui->gpu_accuracy, ui->label_gpu_accuracy, "label_gpu_accuracy", | 143 | ui->gpu_accuracy, ui->label_gpu_accuracy, |
| 146 | static_cast<int>(Settings::values.gpu_accuracy.GetValue(true))); | 144 | static_cast<int>(Settings::values.gpu_accuracy.GetValue(true))); |
| 147 | ConfigurationShared::SetColoredComboBox( | 145 | ConfigurationShared::SetColoredComboBox( |
| 148 | ui->anisotropic_filtering_combobox, ui->af_label, "af_label", | 146 | ui->anisotropic_filtering_combobox, ui->af_label, |
| 149 | static_cast<int>(Settings::values.max_anisotropy.GetValue(true))); | 147 | static_cast<int>(Settings::values.max_anisotropy.GetValue(true))); |
| 150 | } | 148 | } |
diff --git a/src/yuzu/configuration/configure_graphics_advanced.ui b/src/yuzu/configuration/configure_graphics_advanced.ui index a793c803d..846a30586 100644 --- a/src/yuzu/configuration/configure_graphics_advanced.ui +++ b/src/yuzu/configuration/configure_graphics_advanced.ui | |||
| @@ -92,7 +92,7 @@ | |||
| 92 | <string>Enables asynchronous shader compilation, which may reduce shader stutter. This feature is experimental.</string> | 92 | <string>Enables asynchronous shader compilation, which may reduce shader stutter. This feature is experimental.</string> |
| 93 | </property> | 93 | </property> |
| 94 | <property name="text"> | 94 | <property name="text"> |
| 95 | <string>Use asynchronous shader building (experimental, OpenGL or Assembly shaders only)</string> | 95 | <string>Use asynchronous shader building (experimental)</string> |
| 96 | </property> | 96 | </property> |
| 97 | </widget> | 97 | </widget> |
| 98 | </item> | 98 | </item> |
diff --git a/src/yuzu/configuration/configure_hotkeys.cpp b/src/yuzu/configuration/configure_hotkeys.cpp index 6f7fd4414..cbee51a5e 100644 --- a/src/yuzu/configuration/configure_hotkeys.cpp +++ b/src/yuzu/configuration/configure_hotkeys.cpp | |||
| @@ -154,7 +154,7 @@ void ConfigureHotkeys::ClearAll() { | |||
| 154 | const QStandardItem* parent = model->item(r, 0); | 154 | const QStandardItem* parent = model->item(r, 0); |
| 155 | 155 | ||
| 156 | for (int r2 = 0; r2 < parent->rowCount(); ++r2) { | 156 | for (int r2 = 0; r2 < parent->rowCount(); ++r2) { |
| 157 | model->item(r, 0)->child(r2, 1)->setText(tr("")); | 157 | model->item(r, 0)->child(r2, 1)->setText(QString{}); |
| 158 | } | 158 | } |
| 159 | } | 159 | } |
| 160 | } | 160 | } |
| @@ -186,7 +186,7 @@ void ConfigureHotkeys::PopupContextMenu(const QPoint& menu_location) { | |||
| 186 | model->setData(selected, default_key_sequence.toString(QKeySequence::NativeText)); | 186 | model->setData(selected, default_key_sequence.toString(QKeySequence::NativeText)); |
| 187 | } | 187 | } |
| 188 | }); | 188 | }); |
| 189 | connect(clear, &QAction::triggered, [this, selected] { model->setData(selected, tr("")); }); | 189 | connect(clear, &QAction::triggered, [this, selected] { model->setData(selected, QString{}); }); |
| 190 | 190 | ||
| 191 | context_menu.exec(ui->hotkey_list->viewport()->mapToGlobal(menu_location)); | 191 | context_menu.exec(ui->hotkey_list->viewport()->mapToGlobal(menu_location)); |
| 192 | } | 192 | } |
diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp index f2977719c..5223eed1d 100644 --- a/src/yuzu/configuration/configure_input.cpp +++ b/src/yuzu/configuration/configure_input.cpp | |||
| @@ -8,18 +8,32 @@ | |||
| 8 | #include <QSignalBlocker> | 8 | #include <QSignalBlocker> |
| 9 | #include <QTimer> | 9 | #include <QTimer> |
| 10 | 10 | ||
| 11 | #include "configuration/configure_touchscreen_advanced.h" | ||
| 12 | #include "core/core.h" | 11 | #include "core/core.h" |
| 13 | #include "core/hle/service/am/am.h" | 12 | #include "core/hle/service/am/am.h" |
| 14 | #include "core/hle/service/am/applet_ae.h" | 13 | #include "core/hle/service/am/applet_ae.h" |
| 15 | #include "core/hle/service/am/applet_oe.h" | 14 | #include "core/hle/service/am/applet_oe.h" |
| 16 | #include "core/hle/service/hid/controllers/npad.h" | ||
| 17 | #include "core/hle/service/sm/sm.h" | 15 | #include "core/hle/service/sm/sm.h" |
| 18 | #include "ui_configure_input.h" | 16 | #include "ui_configure_input.h" |
| 17 | #include "ui_configure_input_advanced.h" | ||
| 19 | #include "ui_configure_input_player.h" | 18 | #include "ui_configure_input_player.h" |
| 19 | #include "yuzu/configuration/configure_debug_controller.h" | ||
| 20 | #include "yuzu/configuration/configure_input.h" | 20 | #include "yuzu/configuration/configure_input.h" |
| 21 | #include "yuzu/configuration/configure_input_advanced.h" | ||
| 21 | #include "yuzu/configuration/configure_input_player.h" | 22 | #include "yuzu/configuration/configure_input_player.h" |
| 22 | #include "yuzu/configuration/configure_mouse_advanced.h" | 23 | #include "yuzu/configuration/configure_mouse_advanced.h" |
| 24 | #include "yuzu/configuration/configure_touchscreen_advanced.h" | ||
| 25 | |||
| 26 | namespace { | ||
| 27 | template <typename Dialog, typename... Args> | ||
| 28 | void CallConfigureDialog(ConfigureInput& parent, Args&&... args) { | ||
| 29 | Dialog dialog(&parent, std::forward<Args>(args)...); | ||
| 30 | |||
| 31 | const auto res = dialog.exec(); | ||
| 32 | if (res == QDialog::Accepted) { | ||
| 33 | dialog.ApplyConfiguration(); | ||
| 34 | } | ||
| 35 | } | ||
| 36 | } // Anonymous namespace | ||
| 23 | 37 | ||
| 24 | void OnDockedModeChanged(bool last_state, bool new_state) { | 38 | void OnDockedModeChanged(bool last_state, bool new_state) { |
| 25 | if (last_state == new_state) { | 39 | if (last_state == new_state) { |
| @@ -48,97 +62,98 @@ void OnDockedModeChanged(bool last_state, bool new_state) { | |||
| 48 | } | 62 | } |
| 49 | } | 63 | } |
| 50 | 64 | ||
| 51 | namespace { | ||
| 52 | template <typename Dialog, typename... Args> | ||
| 53 | void CallConfigureDialog(ConfigureInput& parent, Args&&... args) { | ||
| 54 | parent.ApplyConfiguration(); | ||
| 55 | Dialog dialog(&parent, std::forward<Args>(args)...); | ||
| 56 | |||
| 57 | const auto res = dialog.exec(); | ||
| 58 | if (res == QDialog::Accepted) { | ||
| 59 | dialog.ApplyConfiguration(); | ||
| 60 | } | ||
| 61 | } | ||
| 62 | } // Anonymous namespace | ||
| 63 | |||
| 64 | ConfigureInput::ConfigureInput(QWidget* parent) | 65 | ConfigureInput::ConfigureInput(QWidget* parent) |
| 65 | : QDialog(parent), ui(std::make_unique<Ui::ConfigureInput>()) { | 66 | : QWidget(parent), ui(std::make_unique<Ui::ConfigureInput>()) { |
| 66 | ui->setupUi(this); | 67 | ui->setupUi(this); |
| 68 | } | ||
| 67 | 69 | ||
| 68 | players_controller = { | 70 | ConfigureInput::~ConfigureInput() = default; |
| 69 | ui->player1_combobox, ui->player2_combobox, ui->player3_combobox, ui->player4_combobox, | ||
| 70 | ui->player5_combobox, ui->player6_combobox, ui->player7_combobox, ui->player8_combobox, | ||
| 71 | }; | ||
| 72 | 71 | ||
| 73 | players_configure = { | 72 | void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem) { |
| 74 | ui->player1_configure, ui->player2_configure, ui->player3_configure, ui->player4_configure, | 73 | player_controllers = { |
| 75 | ui->player5_configure, ui->player6_configure, ui->player7_configure, ui->player8_configure, | 74 | new ConfigureInputPlayer(this, 0, ui->consoleInputSettings, input_subsystem), |
| 75 | new ConfigureInputPlayer(this, 1, ui->consoleInputSettings, input_subsystem), | ||
| 76 | new ConfigureInputPlayer(this, 2, ui->consoleInputSettings, input_subsystem), | ||
| 77 | new ConfigureInputPlayer(this, 3, ui->consoleInputSettings, input_subsystem), | ||
| 78 | new ConfigureInputPlayer(this, 4, ui->consoleInputSettings, input_subsystem), | ||
| 79 | new ConfigureInputPlayer(this, 5, ui->consoleInputSettings, input_subsystem), | ||
| 80 | new ConfigureInputPlayer(this, 6, ui->consoleInputSettings, input_subsystem), | ||
| 81 | new ConfigureInputPlayer(this, 7, ui->consoleInputSettings, input_subsystem), | ||
| 76 | }; | 82 | }; |
| 77 | 83 | ||
| 78 | RetranslateUI(); | 84 | player_tabs = { |
| 79 | LoadConfiguration(); | 85 | ui->tabPlayer1, ui->tabPlayer2, ui->tabPlayer3, ui->tabPlayer4, |
| 80 | UpdateUIEnabled(); | 86 | ui->tabPlayer5, ui->tabPlayer6, ui->tabPlayer7, ui->tabPlayer8, |
| 87 | }; | ||
| 81 | 88 | ||
| 82 | connect(ui->restore_defaults_button, &QPushButton::clicked, this, | 89 | player_connected = { |
| 83 | &ConfigureInput::RestoreDefaults); | 90 | ui->checkboxPlayer1Connected, ui->checkboxPlayer2Connected, ui->checkboxPlayer3Connected, |
| 91 | ui->checkboxPlayer4Connected, ui->checkboxPlayer5Connected, ui->checkboxPlayer6Connected, | ||
| 92 | ui->checkboxPlayer7Connected, ui->checkboxPlayer8Connected, | ||
| 93 | }; | ||
| 84 | 94 | ||
| 85 | for (auto* enabled : players_controller) { | 95 | for (std::size_t i = 0; i < player_tabs.size(); ++i) { |
| 86 | connect(enabled, QOverload<int>::of(&QComboBox::currentIndexChanged), this, | 96 | player_tabs[i]->setLayout(new QHBoxLayout(player_tabs[i])); |
| 87 | &ConfigureInput::UpdateUIEnabled); | 97 | player_tabs[i]->layout()->addWidget(player_controllers[i]); |
| 88 | } | 98 | connect(player_controllers[i], &ConfigureInputPlayer::Connected, [&, i](bool is_connected) { |
| 89 | connect(ui->use_docked_mode, &QCheckBox::stateChanged, this, &ConfigureInput::UpdateUIEnabled); | 99 | if (is_connected) { |
| 90 | connect(ui->handheld_connected, &QCheckBox::stateChanged, this, | 100 | for (std::size_t index = 0; index <= i; ++index) { |
| 91 | &ConfigureInput::UpdateUIEnabled); | 101 | player_connected[index]->setChecked(is_connected); |
| 92 | connect(ui->mouse_enabled, &QCheckBox::stateChanged, this, &ConfigureInput::UpdateUIEnabled); | 102 | } |
| 93 | connect(ui->keyboard_enabled, &QCheckBox::stateChanged, this, &ConfigureInput::UpdateUIEnabled); | 103 | } else { |
| 94 | connect(ui->debug_enabled, &QCheckBox::stateChanged, this, &ConfigureInput::UpdateUIEnabled); | 104 | for (std::size_t index = i; index < player_tabs.size(); ++index) { |
| 95 | connect(ui->touchscreen_enabled, &QCheckBox::stateChanged, this, | 105 | player_connected[index]->setChecked(is_connected); |
| 96 | &ConfigureInput::UpdateUIEnabled); | 106 | } |
| 97 | 107 | } | |
| 98 | for (std::size_t i = 0; i < players_configure.size(); ++i) { | 108 | }); |
| 99 | connect(players_configure[i], &QPushButton::clicked, this, | 109 | connect(player_controllers[i], &ConfigureInputPlayer::RefreshInputDevices, |
| 100 | [this, i] { CallConfigureDialog<ConfigureInputPlayer>(*this, i, false); }); | 110 | [this] { UpdateAllInputDevices(); }); |
| 111 | connect(player_connected[i], &QCheckBox::stateChanged, [this, i](int state) { | ||
| 112 | player_controllers[i]->ConnectPlayer(state == Qt::Checked); | ||
| 113 | }); | ||
| 101 | } | 114 | } |
| 115 | // Only the first player can choose handheld mode so connect the signal just to player 1 | ||
| 116 | connect(player_controllers[0], &ConfigureInputPlayer::HandheldStateChanged, | ||
| 117 | [this](bool is_handheld) { UpdateDockedState(is_handheld); }); | ||
| 118 | |||
| 119 | advanced = new ConfigureInputAdvanced(this); | ||
| 120 | ui->tabAdvanced->setLayout(new QHBoxLayout(ui->tabAdvanced)); | ||
| 121 | ui->tabAdvanced->layout()->addWidget(advanced); | ||
| 122 | connect(advanced, &ConfigureInputAdvanced::CallDebugControllerDialog, [this, input_subsystem] { | ||
| 123 | CallConfigureDialog<ConfigureDebugController>(*this, input_subsystem); | ||
| 124 | }); | ||
| 125 | connect(advanced, &ConfigureInputAdvanced::CallMouseConfigDialog, [this, input_subsystem] { | ||
| 126 | CallConfigureDialog<ConfigureMouseAdvanced>(*this, input_subsystem); | ||
| 127 | }); | ||
| 128 | connect(advanced, &ConfigureInputAdvanced::CallTouchscreenConfigDialog, | ||
| 129 | [this] { CallConfigureDialog<ConfigureTouchscreenAdvanced>(*this); }); | ||
| 102 | 130 | ||
| 103 | connect(ui->handheld_configure, &QPushButton::clicked, this, | 131 | connect(ui->buttonClearAll, &QPushButton::clicked, [this] { ClearAll(); }); |
| 104 | [this] { CallConfigureDialog<ConfigureInputPlayer>(*this, 8, false); }); | 132 | connect(ui->buttonRestoreDefaults, &QPushButton::clicked, [this] { RestoreDefaults(); }); |
| 105 | |||
| 106 | connect(ui->debug_configure, &QPushButton::clicked, this, | ||
| 107 | [this] { CallConfigureDialog<ConfigureInputPlayer>(*this, 9, true); }); | ||
| 108 | |||
| 109 | connect(ui->mouse_advanced, &QPushButton::clicked, this, | ||
| 110 | [this] { CallConfigureDialog<ConfigureMouseAdvanced>(*this); }); | ||
| 111 | 133 | ||
| 112 | connect(ui->touchscreen_advanced, &QPushButton::clicked, this, | 134 | RetranslateUI(); |
| 113 | [this] { CallConfigureDialog<ConfigureTouchscreenAdvanced>(*this); }); | 135 | LoadConfiguration(); |
| 114 | } | 136 | } |
| 115 | 137 | ||
| 116 | ConfigureInput::~ConfigureInput() = default; | 138 | QList<QWidget*> ConfigureInput::GetSubTabs() const { |
| 139 | return { | ||
| 140 | ui->tabPlayer1, ui->tabPlayer2, ui->tabPlayer3, ui->tabPlayer4, ui->tabPlayer5, | ||
| 141 | ui->tabPlayer6, ui->tabPlayer7, ui->tabPlayer8, ui->tabAdvanced, | ||
| 142 | }; | ||
| 143 | } | ||
| 117 | 144 | ||
| 118 | void ConfigureInput::ApplyConfiguration() { | 145 | void ConfigureInput::ApplyConfiguration() { |
| 119 | for (std::size_t i = 0; i < players_controller.size(); ++i) { | 146 | for (auto controller : player_controllers) { |
| 120 | const auto controller_type_index = players_controller[i]->currentIndex(); | 147 | controller->ApplyConfiguration(); |
| 121 | |||
| 122 | Settings::values.players[i].connected = controller_type_index != 0; | ||
| 123 | |||
| 124 | if (controller_type_index > 0) { | ||
| 125 | Settings::values.players[i].type = | ||
| 126 | static_cast<Settings::ControllerType>(controller_type_index - 1); | ||
| 127 | } else { | ||
| 128 | Settings::values.players[i].type = Settings::ControllerType::DualJoycon; | ||
| 129 | } | ||
| 130 | } | 148 | } |
| 131 | 149 | ||
| 150 | advanced->ApplyConfiguration(); | ||
| 151 | |||
| 132 | const bool pre_docked_mode = Settings::values.use_docked_mode; | 152 | const bool pre_docked_mode = Settings::values.use_docked_mode; |
| 133 | Settings::values.use_docked_mode = ui->use_docked_mode->isChecked(); | 153 | Settings::values.use_docked_mode = ui->radioDocked->isChecked(); |
| 134 | OnDockedModeChanged(pre_docked_mode, Settings::values.use_docked_mode); | 154 | OnDockedModeChanged(pre_docked_mode, Settings::values.use_docked_mode); |
| 135 | Settings::values | 155 | |
| 136 | .players[Service::HID::Controller_NPad::NPadIdToIndex(Service::HID::NPAD_HANDHELD)] | 156 | Settings::values.vibration_enabled = ui->vibrationGroup->isChecked(); |
| 137 | .connected = ui->handheld_connected->isChecked(); | ||
| 138 | Settings::values.debug_pad_enabled = ui->debug_enabled->isChecked(); | ||
| 139 | Settings::values.mouse_enabled = ui->mouse_enabled->isChecked(); | ||
| 140 | Settings::values.keyboard_enabled = ui->keyboard_enabled->isChecked(); | ||
| 141 | Settings::values.touchscreen.enabled = ui->touchscreen_enabled->isChecked(); | ||
| 142 | } | 157 | } |
| 143 | 158 | ||
| 144 | void ConfigureInput::changeEvent(QEvent* event) { | 159 | void ConfigureInput::changeEvent(QEvent* event) { |
| @@ -146,94 +161,63 @@ void ConfigureInput::changeEvent(QEvent* event) { | |||
| 146 | RetranslateUI(); | 161 | RetranslateUI(); |
| 147 | } | 162 | } |
| 148 | 163 | ||
| 149 | QDialog::changeEvent(event); | 164 | QWidget::changeEvent(event); |
| 150 | } | 165 | } |
| 151 | 166 | ||
| 152 | void ConfigureInput::RetranslateUI() { | 167 | void ConfigureInput::RetranslateUI() { |
| 153 | ui->retranslateUi(this); | 168 | ui->retranslateUi(this); |
| 154 | RetranslateControllerComboBoxes(); | ||
| 155 | } | 169 | } |
| 156 | 170 | ||
| 157 | void ConfigureInput::RetranslateControllerComboBoxes() { | 171 | void ConfigureInput::LoadConfiguration() { |
| 158 | for (auto* controller_box : players_controller) { | ||
| 159 | [[maybe_unused]] const QSignalBlocker blocker(controller_box); | ||
| 160 | |||
| 161 | controller_box->clear(); | ||
| 162 | controller_box->addItems({tr("None"), tr("Pro Controller"), tr("Dual Joycons"), | ||
| 163 | tr("Single Right Joycon"), tr("Single Left Joycon")}); | ||
| 164 | } | ||
| 165 | |||
| 166 | LoadPlayerControllerIndices(); | 172 | LoadPlayerControllerIndices(); |
| 167 | } | 173 | UpdateDockedState(Settings::values.players[0].controller_type == |
| 174 | Settings::ControllerType::Handheld); | ||
| 168 | 175 | ||
| 169 | void ConfigureInput::UpdateUIEnabled() { | 176 | ui->vibrationGroup->setChecked(Settings::values.vibration_enabled); |
| 170 | bool hit_disabled = false; | 177 | } |
| 171 | for (auto* player : players_controller) { | ||
| 172 | player->setDisabled(hit_disabled); | ||
| 173 | if (hit_disabled) { | ||
| 174 | player->setCurrentIndex(0); | ||
| 175 | } | ||
| 176 | if (!hit_disabled && player->currentIndex() == 0) { | ||
| 177 | hit_disabled = true; | ||
| 178 | } | ||
| 179 | } | ||
| 180 | 178 | ||
| 181 | for (std::size_t i = 0; i < players_controller.size(); ++i) { | 179 | void ConfigureInput::LoadPlayerControllerIndices() { |
| 182 | players_configure[i]->setEnabled(players_controller[i]->currentIndex() != 0); | 180 | for (std::size_t i = 0; i < player_connected.size(); ++i) { |
| 181 | const auto connected = Settings::values.players[i].connected || | ||
| 182 | (i == 0 && Settings::values.players[8].connected); | ||
| 183 | player_connected[i]->setChecked(connected); | ||
| 183 | } | 184 | } |
| 185 | } | ||
| 184 | 186 | ||
| 185 | ui->handheld_connected->setChecked(ui->handheld_connected->isChecked() && | 187 | void ConfigureInput::ClearAll() { |
| 186 | !ui->use_docked_mode->isChecked()); | 188 | // We don't have a good way to know what tab is active, but we can find out by getting the |
| 187 | ui->handheld_connected->setEnabled(!ui->use_docked_mode->isChecked()); | 189 | // parent of the consoleInputSettings |
| 188 | ui->handheld_configure->setEnabled(ui->handheld_connected->isChecked() && | 190 | auto* player_tab = static_cast<ConfigureInputPlayer*>(ui->consoleInputSettings->parent()); |
| 189 | !ui->use_docked_mode->isChecked()); | 191 | player_tab->ClearAll(); |
| 190 | ui->mouse_advanced->setEnabled(ui->mouse_enabled->isChecked()); | ||
| 191 | ui->debug_configure->setEnabled(ui->debug_enabled->isChecked()); | ||
| 192 | ui->touchscreen_advanced->setEnabled(ui->touchscreen_enabled->isChecked()); | ||
| 193 | } | 192 | } |
| 194 | 193 | ||
| 195 | void ConfigureInput::LoadConfiguration() { | 194 | void ConfigureInput::RestoreDefaults() { |
| 196 | std::stable_partition( | 195 | // We don't have a good way to know what tab is active, but we can find out by getting the |
| 197 | Settings::values.players.begin(), | 196 | // parent of the consoleInputSettings |
| 198 | Settings::values.players.begin() + | 197 | auto* player_tab = static_cast<ConfigureInputPlayer*>(ui->consoleInputSettings->parent()); |
| 199 | Service::HID::Controller_NPad::NPadIdToIndex(Service::HID::NPAD_HANDHELD), | 198 | player_tab->RestoreDefaults(); |
| 200 | [](const auto& player) { return player.connected; }); | 199 | |
| 200 | ui->radioDocked->setChecked(true); | ||
| 201 | ui->radioUndocked->setChecked(false); | ||
| 202 | ui->vibrationGroup->setChecked(true); | ||
| 203 | } | ||
| 201 | 204 | ||
| 202 | LoadPlayerControllerIndices(); | 205 | void ConfigureInput::UpdateDockedState(bool is_handheld) { |
| 206 | // If the controller type is handheld only, disallow changing docked mode | ||
| 207 | ui->radioDocked->setEnabled(!is_handheld); | ||
| 208 | ui->radioUndocked->setEnabled(!is_handheld); | ||
| 203 | 209 | ||
| 204 | ui->use_docked_mode->setChecked(Settings::values.use_docked_mode); | 210 | ui->radioDocked->setChecked(Settings::values.use_docked_mode); |
| 205 | ui->handheld_connected->setChecked( | 211 | ui->radioUndocked->setChecked(!Settings::values.use_docked_mode); |
| 206 | Settings::values | ||
| 207 | .players[Service::HID::Controller_NPad::NPadIdToIndex(Service::HID::NPAD_HANDHELD)] | ||
| 208 | .connected); | ||
| 209 | ui->debug_enabled->setChecked(Settings::values.debug_pad_enabled); | ||
| 210 | ui->mouse_enabled->setChecked(Settings::values.mouse_enabled); | ||
| 211 | ui->keyboard_enabled->setChecked(Settings::values.keyboard_enabled); | ||
| 212 | ui->touchscreen_enabled->setChecked(Settings::values.touchscreen.enabled); | ||
| 213 | |||
| 214 | UpdateUIEnabled(); | ||
| 215 | } | ||
| 216 | 212 | ||
| 217 | void ConfigureInput::LoadPlayerControllerIndices() { | 213 | // If its handheld only, force docked mode off (since you can't play handheld in a dock) |
| 218 | for (std::size_t i = 0; i < players_controller.size(); ++i) { | 214 | if (is_handheld) { |
| 219 | const auto connected = Settings::values.players[i].connected; | 215 | ui->radioUndocked->setChecked(true); |
| 220 | players_controller[i]->setCurrentIndex( | ||
| 221 | connected ? static_cast<u8>(Settings::values.players[i].type) + 1 : 0); | ||
| 222 | } | 216 | } |
| 223 | } | 217 | } |
| 224 | 218 | ||
| 225 | void ConfigureInput::RestoreDefaults() { | 219 | void ConfigureInput::UpdateAllInputDevices() { |
| 226 | players_controller[0]->setCurrentIndex(2); | 220 | for (const auto& player : player_controllers) { |
| 227 | 221 | player->UpdateInputDevices(); | |
| 228 | for (std::size_t i = 1; i < players_controller.size(); ++i) { | ||
| 229 | players_controller[i]->setCurrentIndex(0); | ||
| 230 | } | 222 | } |
| 231 | |||
| 232 | ui->use_docked_mode->setCheckState(Qt::Unchecked); | ||
| 233 | ui->handheld_connected->setCheckState(Qt::Unchecked); | ||
| 234 | ui->mouse_enabled->setCheckState(Qt::Unchecked); | ||
| 235 | ui->keyboard_enabled->setCheckState(Qt::Unchecked); | ||
| 236 | ui->debug_enabled->setCheckState(Qt::Unchecked); | ||
| 237 | ui->touchscreen_enabled->setCheckState(Qt::Checked); | ||
| 238 | UpdateUIEnabled(); | ||
| 239 | } | 223 | } |
diff --git a/src/yuzu/configuration/configure_input.h b/src/yuzu/configuration/configure_input.h index 2f70cb3ca..d08a24f96 100644 --- a/src/yuzu/configuration/configure_input.h +++ b/src/yuzu/configuration/configure_input.h | |||
| @@ -7,37 +7,50 @@ | |||
| 7 | #include <array> | 7 | #include <array> |
| 8 | #include <memory> | 8 | #include <memory> |
| 9 | 9 | ||
| 10 | #include <QDialog> | ||
| 11 | #include <QKeyEvent> | 10 | #include <QKeyEvent> |
| 11 | #include <QWidget> | ||
| 12 | |||
| 13 | #include "yuzu/configuration/configure_input_advanced.h" | ||
| 14 | #include "yuzu/configuration/configure_input_player.h" | ||
| 12 | 15 | ||
| 13 | #include "ui_configure_input.h" | 16 | #include "ui_configure_input.h" |
| 14 | 17 | ||
| 15 | class QPushButton; | 18 | class QCheckBox; |
| 16 | class QString; | 19 | class QString; |
| 17 | class QTimer; | 20 | class QTimer; |
| 18 | 21 | ||
| 22 | namespace InputCommon { | ||
| 23 | class InputSubsystem; | ||
| 24 | } | ||
| 25 | |||
| 19 | namespace Ui { | 26 | namespace Ui { |
| 20 | class ConfigureInput; | 27 | class ConfigureInput; |
| 21 | } | 28 | } |
| 22 | 29 | ||
| 23 | void OnDockedModeChanged(bool last_state, bool new_state); | 30 | void OnDockedModeChanged(bool last_state, bool new_state); |
| 24 | 31 | ||
| 25 | class ConfigureInput : public QDialog { | 32 | class ConfigureInput : public QWidget { |
| 26 | Q_OBJECT | 33 | Q_OBJECT |
| 27 | 34 | ||
| 28 | public: | 35 | public: |
| 29 | explicit ConfigureInput(QWidget* parent = nullptr); | 36 | explicit ConfigureInput(QWidget* parent = nullptr); |
| 30 | ~ConfigureInput() override; | 37 | ~ConfigureInput() override; |
| 31 | 38 | ||
| 32 | /// Save all button configurations to settings file | 39 | /// Initializes the input dialog with the given input subsystem. |
| 40 | void Initialize(InputCommon::InputSubsystem* input_subsystem_); | ||
| 41 | |||
| 42 | /// Save all button configurations to settings file. | ||
| 33 | void ApplyConfiguration(); | 43 | void ApplyConfiguration(); |
| 34 | 44 | ||
| 45 | QList<QWidget*> GetSubTabs() const; | ||
| 46 | |||
| 35 | private: | 47 | private: |
| 36 | void changeEvent(QEvent* event) override; | 48 | void changeEvent(QEvent* event) override; |
| 37 | void RetranslateUI(); | 49 | void RetranslateUI(); |
| 38 | void RetranslateControllerComboBoxes(); | 50 | void ClearAll(); |
| 39 | 51 | ||
| 40 | void UpdateUIEnabled(); | 52 | void UpdateDockedState(bool is_handheld); |
| 53 | void UpdateAllInputDevices(); | ||
| 41 | 54 | ||
| 42 | /// Load configuration settings. | 55 | /// Load configuration settings. |
| 43 | void LoadConfiguration(); | 56 | void LoadConfiguration(); |
| @@ -48,6 +61,8 @@ private: | |||
| 48 | 61 | ||
| 49 | std::unique_ptr<Ui::ConfigureInput> ui; | 62 | std::unique_ptr<Ui::ConfigureInput> ui; |
| 50 | 63 | ||
| 51 | std::array<QComboBox*, 8> players_controller; | 64 | std::array<ConfigureInputPlayer*, 8> player_controllers; |
| 52 | std::array<QPushButton*, 8> players_configure; | 65 | std::array<QWidget*, 8> player_tabs; |
| 66 | std::array<QCheckBox*, 8> player_connected; | ||
| 67 | ConfigureInputAdvanced* advanced; | ||
| 53 | }; | 68 | }; |
diff --git a/src/yuzu/configuration/configure_input.ui b/src/yuzu/configuration/configure_input.ui index efffd8487..136955224 100644 --- a/src/yuzu/configuration/configure_input.ui +++ b/src/yuzu/configuration/configure_input.ui | |||
| @@ -1,529 +1,554 @@ | |||
| 1 | <?xml version="1.0" encoding="UTF-8"?> | 1 | <?xml version="1.0" encoding="UTF-8"?> |
| 2 | <ui version="4.0"> | 2 | <ui version="4.0"> |
| 3 | <class>ConfigureInput</class> | 3 | <class>ConfigureInput</class> |
| 4 | <widget class="QDialog" name="ConfigureInput"> | 4 | <widget class="QWidget" name="ConfigureInput"> |
| 5 | <property name="geometry"> | 5 | <property name="geometry"> |
| 6 | <rect> | 6 | <rect> |
| 7 | <x>0</x> | 7 | <x>0</x> |
| 8 | <y>0</y> | 8 | <y>0</y> |
| 9 | <width>384</width> | 9 | <width>700</width> |
| 10 | <height>576</height> | 10 | <height>540</height> |
| 11 | </rect> | 11 | </rect> |
| 12 | </property> | 12 | </property> |
| 13 | <property name="windowTitle"> | 13 | <property name="windowTitle"> |
| 14 | <string>Custom Input Settings</string> | 14 | <string>ConfigureInput</string> |
| 15 | </property> | 15 | </property> |
| 16 | <layout class="QVBoxLayout" name="verticalLayout_5"> | 16 | <layout class="QVBoxLayout" name="verticalLayout_5"> |
| 17 | <property name="spacing"> | ||
| 18 | <number>2</number> | ||
| 19 | </property> | ||
| 20 | <property name="leftMargin"> | ||
| 21 | <number>3</number> | ||
| 22 | </property> | ||
| 23 | <property name="topMargin"> | ||
| 24 | <number>3</number> | ||
| 25 | </property> | ||
| 26 | <property name="rightMargin"> | ||
| 27 | <number>3</number> | ||
| 28 | </property> | ||
| 29 | <property name="bottomMargin"> | ||
| 30 | <number>3</number> | ||
| 31 | </property> | ||
| 17 | <item> | 32 | <item> |
| 18 | <layout class="QVBoxLayout" name="verticalLayout"> | 33 | <widget class="QTabWidget" name="tabWidget"> |
| 19 | <item> | 34 | <property name="currentIndex"> |
| 20 | <widget class="QGroupBox" name="gridGroupBox_1"> | 35 | <number>0</number> |
| 21 | <property name="title"> | 36 | </property> |
| 22 | <string>Players</string> | 37 | <widget class="QWidget" name="tabPlayer1"> |
| 23 | </property> | 38 | <property name="accessibleName"> |
| 24 | <layout class="QGridLayout" name="gridLayout"> | 39 | <string>Player 1</string> |
| 25 | <item row="1" column="2"> | 40 | </property> |
| 26 | <widget class="QComboBox" name="player1_combobox"> | 41 | <attribute name="title"> |
| 27 | <property name="minimumSize"> | 42 | <string>Player 1</string> |
| 28 | <size> | 43 | </attribute> |
| 29 | <width>110</width> | 44 | </widget> |
| 30 | <height>0</height> | 45 | <widget class="QWidget" name="tabPlayer2"> |
| 31 | </size> | 46 | <property name="accessibleName"> |
| 32 | </property> | 47 | <string>Player 2</string> |
| 33 | </widget> | 48 | </property> |
| 34 | </item> | 49 | <attribute name="title"> |
| 35 | <item row="1" column="3"> | 50 | <string>Player 2</string> |
| 36 | <widget class="QPushButton" name="player1_configure"> | 51 | </attribute> |
| 37 | <property name="text"> | 52 | </widget> |
| 38 | <string>Configure</string> | 53 | <widget class="QWidget" name="tabPlayer3"> |
| 39 | </property> | 54 | <property name="accessibleName"> |
| 40 | </widget> | 55 | <string>Player 3</string> |
| 41 | </item> | 56 | </property> |
| 42 | <item row="0" column="2"> | 57 | <attribute name="title"> |
| 43 | <widget class="QLabel" name="label"> | 58 | <string>Player 3</string> |
| 44 | <property name="text"> | 59 | </attribute> |
| 45 | <string>Controller Type</string> | 60 | </widget> |
| 46 | </property> | 61 | <widget class="QWidget" name="tabPlayer4"> |
| 47 | <property name="alignment"> | 62 | <property name="accessibleName"> |
| 48 | <set>Qt::AlignCenter</set> | 63 | <string>Player 4</string> |
| 49 | </property> | 64 | </property> |
| 50 | </widget> | 65 | <attribute name="title"> |
| 51 | </item> | 66 | <string>Player 4</string> |
| 52 | <item row="2" column="2"> | 67 | </attribute> |
| 53 | <widget class="QComboBox" name="player2_combobox"> | 68 | </widget> |
| 54 | <property name="minimumSize"> | 69 | <widget class="QWidget" name="tabPlayer5"> |
| 55 | <size> | 70 | <property name="accessibleName"> |
| 56 | <width>110</width> | 71 | <string>Player 5</string> |
| 57 | <height>0</height> | 72 | </property> |
| 58 | </size> | 73 | <attribute name="title"> |
| 59 | </property> | 74 | <string>Player 5</string> |
| 60 | </widget> | 75 | </attribute> |
| 61 | </item> | 76 | </widget> |
| 62 | <item row="3" column="2"> | 77 | <widget class="QWidget" name="tabPlayer6"> |
| 63 | <widget class="QComboBox" name="player3_combobox"> | 78 | <property name="accessibleName"> |
| 64 | <property name="minimumSize"> | 79 | <string>Player 6</string> |
| 65 | <size> | 80 | </property> |
| 66 | <width>110</width> | 81 | <attribute name="title"> |
| 67 | <height>0</height> | 82 | <string>Player 6</string> |
| 68 | </size> | 83 | </attribute> |
| 69 | </property> | 84 | </widget> |
| 70 | </widget> | 85 | <widget class="QWidget" name="tabPlayer7"> |
| 71 | </item> | 86 | <property name="accessibleName"> |
| 72 | <item row="4" column="2"> | 87 | <string>Player 7</string> |
| 73 | <widget class="QComboBox" name="player4_combobox"> | 88 | </property> |
| 74 | <property name="minimumSize"> | 89 | <attribute name="title"> |
| 75 | <size> | 90 | <string>Player 7</string> |
| 76 | <width>110</width> | 91 | </attribute> |
| 77 | <height>0</height> | 92 | </widget> |
| 78 | </size> | 93 | <widget class="QWidget" name="tabPlayer8"> |
| 79 | </property> | 94 | <property name="accessibleName"> |
| 80 | </widget> | 95 | <string>Player 8</string> |
| 81 | </item> | 96 | </property> |
| 82 | <item row="5" column="2"> | 97 | <attribute name="title"> |
| 83 | <widget class="QComboBox" name="player5_combobox"> | 98 | <string>Player 8</string> |
| 84 | <property name="minimumSize"> | 99 | </attribute> |
| 85 | <size> | 100 | </widget> |
| 86 | <width>110</width> | 101 | <widget class="QWidget" name="tabAdvanced"> |
| 87 | <height>0</height> | 102 | <property name="accessibleName"> |
| 88 | </size> | 103 | <string>Advanced</string> |
| 89 | </property> | 104 | </property> |
| 90 | </widget> | 105 | <attribute name="title"> |
| 91 | </item> | 106 | <string>Advanced</string> |
| 92 | <item row="6" column="2"> | 107 | </attribute> |
| 93 | <widget class="QComboBox" name="player6_combobox"> | 108 | </widget> |
| 94 | <property name="minimumSize"> | 109 | </widget> |
| 95 | <size> | 110 | </item> |
| 96 | <width>110</width> | 111 | <item alignment="Qt::AlignVCenter"> |
| 97 | <height>0</height> | 112 | <widget class="QWidget" name="consoleInputSettings" native="true"> |
| 98 | </size> | 113 | <layout class="QHBoxLayout" name="buttonsBottomRightHorizontalLayout"> |
| 99 | </property> | 114 | <property name="spacing"> |
| 100 | </widget> | 115 | <number>3</number> |
| 101 | </item> | 116 | </property> |
| 102 | <item row="7" column="2"> | 117 | <property name="leftMargin"> |
| 103 | <widget class="QComboBox" name="player7_combobox"> | 118 | <number>0</number> |
| 104 | <property name="minimumSize"> | 119 | </property> |
| 105 | <size> | 120 | <property name="topMargin"> |
| 106 | <width>110</width> | 121 | <number>3</number> |
| 107 | <height>0</height> | 122 | </property> |
| 108 | </size> | 123 | <property name="rightMargin"> |
| 109 | </property> | 124 | <number>0</number> |
| 110 | </widget> | 125 | </property> |
| 111 | </item> | 126 | <property name="bottomMargin"> |
| 112 | <item row="8" column="2"> | 127 | <number>0</number> |
| 113 | <widget class="QComboBox" name="player8_combobox"> | 128 | </property> |
| 114 | <property name="minimumSize"> | 129 | <item alignment="Qt::AlignVCenter"> |
| 115 | <size> | 130 | <widget class="QGroupBox" name="handheldGroup"> |
| 116 | <width>110</width> | 131 | <property name="maximumSize"> |
| 117 | <height>0</height> | 132 | <size> |
| 118 | </size> | 133 | <width>16777215</width> |
| 119 | </property> | 134 | <height>16777215</height> |
| 120 | </widget> | 135 | </size> |
| 121 | </item> | 136 | </property> |
| 122 | <item row="2" column="3"> | 137 | <property name="title"> |
| 123 | <widget class="QPushButton" name="player2_configure"> | 138 | <string>Console Mode</string> |
| 124 | <property name="text"> | 139 | </property> |
| 125 | <string>Configure</string> | 140 | <layout class="QHBoxLayout" name="horizontalLayout"> |
| 126 | </property> | 141 | <property name="spacing"> |
| 127 | </widget> | 142 | <number>6</number> |
| 128 | </item> | 143 | </property> |
| 129 | <item row="3" column="3"> | 144 | <property name="leftMargin"> |
| 130 | <widget class="QPushButton" name="player3_configure"> | 145 | <number>3</number> |
| 131 | <property name="text"> | 146 | </property> |
| 132 | <string>Configure</string> | 147 | <property name="topMargin"> |
| 133 | </property> | 148 | <number>6</number> |
| 134 | </widget> | 149 | </property> |
| 135 | </item> | 150 | <property name="rightMargin"> |
| 136 | <item row="4" column="3"> | 151 | <number>3</number> |
| 137 | <widget class="QPushButton" name="player4_configure"> | 152 | </property> |
| 138 | <property name="text"> | 153 | <property name="bottomMargin"> |
| 139 | <string>Configure</string> | 154 | <number>6</number> |
| 140 | </property> | 155 | </property> |
| 141 | </widget> | 156 | <item> |
| 142 | </item> | 157 | <widget class="QRadioButton" name="radioDocked"> |
| 143 | <item row="5" column="3"> | 158 | <property name="text"> |
| 144 | <widget class="QPushButton" name="player5_configure"> | 159 | <string>Docked</string> |
| 145 | <property name="text"> | 160 | </property> |
| 146 | <string>Configure</string> | 161 | <property name="checked"> |
| 147 | </property> | 162 | <bool>true</bool> |
| 148 | </widget> | 163 | </property> |
| 149 | </item> | 164 | </widget> |
| 150 | <item row="6" column="3"> | 165 | </item> |
| 151 | <widget class="QPushButton" name="player6_configure"> | 166 | <item> |
| 152 | <property name="text"> | 167 | <widget class="QRadioButton" name="radioUndocked"> |
| 153 | <string>Configure</string> | 168 | <property name="text"> |
| 154 | </property> | 169 | <string>Undocked</string> |
| 155 | </widget> | 170 | </property> |
| 156 | </item> | 171 | </widget> |
| 157 | <item row="7" column="3"> | 172 | </item> |
| 158 | <widget class="QPushButton" name="player7_configure"> | 173 | </layout> |
| 159 | <property name="text"> | 174 | </widget> |
| 160 | <string>Configure</string> | 175 | </item> |
| 161 | </property> | 176 | <item> |
| 162 | </widget> | 177 | <widget class="QGroupBox" name="vibrationGroup"> |
| 163 | </item> | 178 | <property name="title"> |
| 164 | <item row="8" column="3"> | 179 | <string>Vibration</string> |
| 165 | <widget class="QPushButton" name="player8_configure"> | 180 | </property> |
| 166 | <property name="text"> | 181 | <property name="checkable"> |
| 167 | <string>Configure</string> | 182 | <bool>true</bool> |
| 168 | </property> | 183 | </property> |
| 169 | </widget> | 184 | <layout class="QHBoxLayout" name="horizontalLayout_2"> |
| 170 | </item> | 185 | <property name="leftMargin"> |
| 171 | <item row="0" column="0"> | 186 | <number>3</number> |
| 172 | <spacer name="horizontalSpacer"> | 187 | </property> |
| 173 | <property name="orientation"> | 188 | <property name="topMargin"> |
| 174 | <enum>Qt::Horizontal</enum> | 189 | <number>3</number> |
| 175 | </property> | 190 | </property> |
| 176 | <property name="sizeHint" stdset="0"> | 191 | <property name="rightMargin"> |
| 177 | <size> | 192 | <number>3</number> |
| 178 | <width>40</width> | 193 | </property> |
| 179 | <height>20</height> | 194 | <property name="bottomMargin"> |
| 180 | </size> | 195 | <number>3</number> |
| 181 | </property> | 196 | </property> |
| 182 | </spacer> | 197 | <item> |
| 183 | </item> | 198 | <widget class="QSpinBox" name="vibrationSpin"> |
| 184 | <item row="0" column="4"> | 199 | <property name="minimumSize"> |
| 185 | <spacer name="horizontalSpacer_2"> | 200 | <size> |
| 186 | <property name="orientation"> | 201 | <width>65</width> |
| 187 | <enum>Qt::Horizontal</enum> | 202 | <height>21</height> |
| 188 | </property> | 203 | </size> |
| 189 | <property name="sizeHint" stdset="0"> | 204 | </property> |
| 190 | <size> | 205 | <property name="maximumSize"> |
| 191 | <width>40</width> | 206 | <size> |
| 192 | <height>20</height> | 207 | <width>65</width> |
| 193 | </size> | 208 | <height>16777215</height> |
| 194 | </property> | 209 | </size> |
| 195 | </spacer> | 210 | </property> |
| 196 | </item> | 211 | <property name="suffix"> |
| 197 | <item row="1" column="1"> | 212 | <string>%</string> |
| 198 | <widget class="QLabel" name="label_3"> | 213 | </property> |
| 199 | <property name="minimumSize"> | 214 | <property name="minimum"> |
| 200 | <size> | 215 | <number>1</number> |
| 201 | <width>55</width> | 216 | </property> |
| 202 | <height>0</height> | 217 | <property name="maximum"> |
| 203 | </size> | 218 | <number>200</number> |
| 204 | </property> | 219 | </property> |
| 205 | <property name="text"> | 220 | <property name="value"> |
| 206 | <string>Player 1</string> | 221 | <number>100</number> |
| 207 | </property> | 222 | </property> |
| 208 | </widget> | 223 | </widget> |
| 209 | </item> | 224 | </item> |
| 210 | <item row="2" column="1"> | 225 | </layout> |
| 211 | <widget class="QLabel" name="label_4"> | 226 | </widget> |
| 212 | <property name="text"> | 227 | </item> |
| 213 | <string>Player 2</string> | 228 | <item> |
| 214 | </property> | 229 | <widget class="QGroupBox" name="motionGroup"> |
| 215 | </widget> | 230 | <property name="title"> |
| 216 | </item> | 231 | <string>Motion</string> |
| 217 | <item row="3" column="1"> | 232 | </property> |
| 218 | <widget class="QLabel" name="label_5"> | 233 | <property name="checkable"> |
| 219 | <property name="text"> | 234 | <bool>true</bool> |
| 220 | <string>Player 3</string> | 235 | </property> |
| 221 | </property> | 236 | <layout class="QHBoxLayout" name="horizontalLayout_3"> |
| 222 | </widget> | 237 | <property name="leftMargin"> |
| 223 | </item> | 238 | <number>3</number> |
| 224 | <item row="4" column="1"> | 239 | </property> |
| 225 | <widget class="QLabel" name="label_6"> | 240 | <property name="topMargin"> |
| 226 | <property name="text"> | 241 | <number>3</number> |
| 227 | <string>Player 4</string> | 242 | </property> |
| 228 | </property> | 243 | <property name="rightMargin"> |
| 229 | </widget> | 244 | <number>3</number> |
| 230 | </item> | 245 | </property> |
| 231 | <item row="5" column="1"> | 246 | <property name="bottomMargin"> |
| 232 | <widget class="QLabel" name="label_7"> | 247 | <number>3</number> |
| 233 | <property name="text"> | 248 | </property> |
| 234 | <string>Player 5</string> | 249 | <item> |
| 235 | </property> | 250 | <widget class="QPushButton" name="motionButton"> |
| 236 | </widget> | 251 | <property name="minimumSize"> |
| 237 | </item> | 252 | <size> |
| 238 | <item row="6" column="1"> | 253 | <width>57</width> |
| 239 | <widget class="QLabel" name="label_8"> | 254 | <height>0</height> |
| 240 | <property name="text"> | 255 | </size> |
| 241 | <string>Player 6</string> | 256 | </property> |
| 242 | </property> | 257 | <property name="maximumSize"> |
| 243 | </widget> | 258 | <size> |
| 244 | </item> | 259 | <width>55</width> |
| 245 | <item row="7" column="1"> | 260 | <height>16777215</height> |
| 246 | <widget class="QLabel" name="label_9"> | 261 | </size> |
| 247 | <property name="text"> | 262 | </property> |
| 248 | <string>Player 7</string> | 263 | <property name="styleSheet"> |
| 249 | </property> | 264 | <string notr="true">min-width: 55px;</string> |
| 250 | </widget> | 265 | </property> |
| 251 | </item> | 266 | <property name="text"> |
| 252 | <item row="8" column="1"> | 267 | <string>Configure</string> |
| 253 | <widget class="QLabel" name="label_10"> | 268 | </property> |
| 254 | <property name="text"> | 269 | </widget> |
| 255 | <string>Player 8</string> | 270 | </item> |
| 256 | </property> | 271 | </layout> |
| 257 | </widget> | 272 | </widget> |
| 258 | </item> | 273 | </item> |
| 259 | </layout> | 274 | <item alignment="Qt::AlignVCenter"> |
| 260 | </widget> | 275 | <widget class="QWidget" name="widget" native="true"> |
| 261 | </item> | 276 | <layout class="QGridLayout" name="gridLayout_2"> |
| 262 | <item> | 277 | <property name="leftMargin"> |
| 263 | <widget class="QGroupBox" name="gridGroupBox_2"> | 278 | <number>5</number> |
| 264 | <property name="title"> | 279 | </property> |
| 265 | <string>Handheld</string> | 280 | <property name="topMargin"> |
| 266 | </property> | 281 | <number>0</number> |
| 267 | <layout class="QGridLayout" name="gridLayout_2"> | ||
| 268 | <item row="1" column="2"> | ||
| 269 | <spacer name="horizontalSpacer_5"> | ||
| 270 | <property name="orientation"> | ||
| 271 | <enum>Qt::Horizontal</enum> | ||
| 272 | </property> | ||
| 273 | <property name="sizeType"> | ||
| 274 | <enum>QSizePolicy::Fixed</enum> | ||
| 275 | </property> | ||
| 276 | <property name="sizeHint" stdset="0"> | ||
| 277 | <size> | ||
| 278 | <width>72</width> | ||
| 279 | <height>20</height> | ||
| 280 | </size> | ||
| 281 | </property> | ||
| 282 | </spacer> | ||
| 283 | </item> | ||
| 284 | <item row="1" column="4"> | ||
| 285 | <spacer name="horizontalSpacer_4"> | ||
| 286 | <property name="orientation"> | ||
| 287 | <enum>Qt::Horizontal</enum> | ||
| 288 | </property> | ||
| 289 | <property name="sizeHint" stdset="0"> | ||
| 290 | <size> | ||
| 291 | <width>40</width> | ||
| 292 | <height>20</height> | ||
| 293 | </size> | ||
| 294 | </property> | ||
| 295 | </spacer> | ||
| 296 | </item> | ||
| 297 | <item row="1" column="3"> | ||
| 298 | <widget class="QPushButton" name="handheld_configure"> | ||
| 299 | <property name="text"> | ||
| 300 | <string>Configure</string> | ||
| 301 | </property> | ||
| 302 | </widget> | ||
| 303 | </item> | ||
| 304 | <item row="1" column="0"> | ||
| 305 | <spacer name="horizontalSpacer_3"> | ||
| 306 | <property name="orientation"> | ||
| 307 | <enum>Qt::Horizontal</enum> | ||
| 308 | </property> | ||
| 309 | <property name="sizeHint" stdset="0"> | ||
| 310 | <size> | ||
| 311 | <width>40</width> | ||
| 312 | <height>20</height> | ||
| 313 | </size> | ||
| 314 | </property> | ||
| 315 | </spacer> | ||
| 316 | </item> | ||
| 317 | <item row="1" column="1"> | ||
| 318 | <widget class="QCheckBox" name="handheld_connected"> | ||
| 319 | <property name="text"> | ||
| 320 | <string>Joycons Docked</string> | ||
| 321 | </property> | ||
| 322 | </widget> | ||
| 323 | </item> | ||
| 324 | <item row="0" column="1"> | ||
| 325 | <widget class="QCheckBox" name="use_docked_mode"> | ||
| 326 | <property name="text"> | ||
| 327 | <string>Use Docked Mode</string> | ||
| 328 | </property> | ||
| 329 | </widget> | ||
| 330 | </item> | ||
| 331 | </layout> | ||
| 332 | </widget> | ||
| 333 | </item> | ||
| 334 | <item> | ||
| 335 | <widget class="QGroupBox" name="gridGroupBox_3"> | ||
| 336 | <property name="title"> | ||
| 337 | <string>Other</string> | ||
| 338 | </property> | ||
| 339 | <layout class="QGridLayout" name="gridLayout_3"> | ||
| 340 | <item row="1" column="1"> | ||
| 341 | <widget class="QCheckBox" name="keyboard_enabled"> | ||
| 342 | <property name="minimumSize"> | ||
| 343 | <size> | ||
| 344 | <width>0</width> | ||
| 345 | <height>23</height> | ||
| 346 | </size> | ||
| 347 | </property> | ||
| 348 | <property name="text"> | ||
| 349 | <string>Keyboard</string> | ||
| 350 | </property> | ||
| 351 | </widget> | ||
| 352 | </item> | ||
| 353 | <item row="2" column="1"> | ||
| 354 | <widget class="QCheckBox" name="debug_enabled"> | ||
| 355 | <property name="text"> | ||
| 356 | <string>Debug Controller</string> | ||
| 357 | </property> | ||
| 358 | </widget> | ||
| 359 | </item> | ||
| 360 | <item row="3" column="1"> | ||
| 361 | <widget class="QCheckBox" name="touchscreen_enabled"> | ||
| 362 | <property name="text"> | ||
| 363 | <string>Touchscreen</string> | ||
| 364 | </property> | ||
| 365 | </widget> | ||
| 366 | </item> | ||
| 367 | <item row="0" column="1"> | ||
| 368 | <widget class="QCheckBox" name="mouse_enabled"> | ||
| 369 | <property name="minimumSize"> | ||
| 370 | <size> | ||
| 371 | <width>0</width> | ||
| 372 | <height>23</height> | ||
| 373 | </size> | ||
| 374 | </property> | ||
| 375 | <property name="text"> | ||
| 376 | <string>Mouse</string> | ||
| 377 | </property> | ||
| 378 | </widget> | ||
| 379 | </item> | ||
| 380 | <item row="0" column="4"> | ||
| 381 | <spacer name="horizontalSpacer_7"> | ||
| 382 | <property name="orientation"> | ||
| 383 | <enum>Qt::Horizontal</enum> | ||
| 384 | </property> | ||
| 385 | <property name="sizeHint" stdset="0"> | ||
| 386 | <size> | ||
| 387 | <width>40</width> | ||
| 388 | <height>20</height> | ||
| 389 | </size> | ||
| 390 | </property> | ||
| 391 | </spacer> | ||
| 392 | </item> | ||
| 393 | <item row="0" column="2"> | ||
| 394 | <spacer name="horizontalSpacer_8"> | ||
| 395 | <property name="orientation"> | ||
| 396 | <enum>Qt::Horizontal</enum> | ||
| 397 | </property> | ||
| 398 | <property name="sizeType"> | ||
| 399 | <enum>QSizePolicy::Fixed</enum> | ||
| 400 | </property> | ||
| 401 | <property name="sizeHint" stdset="0"> | ||
| 402 | <size> | ||
| 403 | <width>76</width> | ||
| 404 | <height>20</height> | ||
| 405 | </size> | ||
| 406 | </property> | ||
| 407 | </spacer> | ||
| 408 | </item> | ||
| 409 | <item row="0" column="0"> | ||
| 410 | <spacer name="horizontalSpacer_6"> | ||
| 411 | <property name="orientation"> | ||
| 412 | <enum>Qt::Horizontal</enum> | ||
| 413 | </property> | ||
| 414 | <property name="sizeHint" stdset="0"> | ||
| 415 | <size> | ||
| 416 | <width>40</width> | ||
| 417 | <height>20</height> | ||
| 418 | </size> | ||
| 419 | </property> | ||
| 420 | </spacer> | ||
| 421 | </item> | ||
| 422 | <item row="3" column="3"> | ||
| 423 | <widget class="QPushButton" name="touchscreen_advanced"> | ||
| 424 | <property name="text"> | ||
| 425 | <string>Advanced</string> | ||
| 426 | </property> | ||
| 427 | </widget> | ||
| 428 | </item> | ||
| 429 | <item row="2" column="3"> | ||
| 430 | <widget class="QPushButton" name="debug_configure"> | ||
| 431 | <property name="text"> | ||
| 432 | <string>Configure</string> | ||
| 433 | </property> | ||
| 434 | </widget> | ||
| 435 | </item> | ||
| 436 | <item row="0" column="3"> | ||
| 437 | <widget class="QPushButton" name="mouse_advanced"> | ||
| 438 | <property name="text"> | ||
| 439 | <string>Advanced</string> | ||
| 440 | </property> | ||
| 441 | </widget> | ||
| 442 | </item> | ||
| 443 | </layout> | ||
| 444 | </widget> | ||
| 445 | </item> | ||
| 446 | <item> | ||
| 447 | <spacer name="verticalSpacer"> | ||
| 448 | <property name="orientation"> | ||
| 449 | <enum>Qt::Vertical</enum> | ||
| 450 | </property> | ||
| 451 | <property name="sizeHint" stdset="0"> | ||
| 452 | <size> | ||
| 453 | <width>20</width> | ||
| 454 | <height>40</height> | ||
| 455 | </size> | ||
| 456 | </property> | ||
| 457 | </spacer> | ||
| 458 | </item> | ||
| 459 | <item> | ||
| 460 | <layout class="QHBoxLayout" name="horizontalLayout"> | ||
| 461 | <item> | ||
| 462 | <widget class="QPushButton" name="restore_defaults_button"> | ||
| 463 | <property name="text"> | ||
| 464 | <string>Restore Defaults</string> | ||
| 465 | </property> | 282 | </property> |
| 466 | </widget> | 283 | <property name="rightMargin"> |
| 467 | </item> | 284 | <number>0</number> |
| 468 | <item> | ||
| 469 | <spacer name="horizontalSpacer_9"> | ||
| 470 | <property name="orientation"> | ||
| 471 | <enum>Qt::Horizontal</enum> | ||
| 472 | </property> | 285 | </property> |
| 473 | <property name="sizeHint" stdset="0"> | 286 | <property name="bottomMargin"> |
| 474 | <size> | 287 | <number>0</number> |
| 475 | <width>40</width> | ||
| 476 | <height>20</height> | ||
| 477 | </size> | ||
| 478 | </property> | 288 | </property> |
| 479 | </spacer> | 289 | <property name="spacing"> |
| 480 | </item> | 290 | <number>3</number> |
| 481 | <item> | ||
| 482 | <widget class="QDialogButtonBox" name="buttonBox"> | ||
| 483 | <property name="standardButtons"> | ||
| 484 | <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> | ||
| 485 | </property> | 291 | </property> |
| 486 | </widget> | 292 | <item row="1" column="2"> |
| 487 | </item> | 293 | <widget class="QCheckBox" name="checkboxPlayer2Connected"> |
| 488 | </layout> | 294 | <property name="text"> |
| 489 | </item> | 295 | <string/> |
| 490 | </layout> | 296 | </property> |
| 297 | </widget> | ||
| 298 | </item> | ||
| 299 | <item row="1" column="0"> | ||
| 300 | <widget class="QLabel" name="label_2"> | ||
| 301 | <property name="text"> | ||
| 302 | <string>Controllers</string> | ||
| 303 | </property> | ||
| 304 | </widget> | ||
| 305 | </item> | ||
| 306 | <item row="1" column="4"> | ||
| 307 | <widget class="QCheckBox" name="checkboxPlayer4Connected"> | ||
| 308 | <property name="text"> | ||
| 309 | <string/> | ||
| 310 | </property> | ||
| 311 | </widget> | ||
| 312 | </item> | ||
| 313 | <item row="1" column="3"> | ||
| 314 | <widget class="QCheckBox" name="checkboxPlayer3Connected"> | ||
| 315 | <property name="text"> | ||
| 316 | <string/> | ||
| 317 | </property> | ||
| 318 | </widget> | ||
| 319 | </item> | ||
| 320 | <item row="1" column="5"> | ||
| 321 | <widget class="QCheckBox" name="checkboxPlayer5Connected"> | ||
| 322 | <property name="text"> | ||
| 323 | <string/> | ||
| 324 | </property> | ||
| 325 | </widget> | ||
| 326 | </item> | ||
| 327 | <item row="0" column="1"> | ||
| 328 | <widget class="QLabel" name="label"> | ||
| 329 | <property name="text"> | ||
| 330 | <string>1</string> | ||
| 331 | </property> | ||
| 332 | <property name="alignment"> | ||
| 333 | <set>Qt::AlignCenter</set> | ||
| 334 | </property> | ||
| 335 | </widget> | ||
| 336 | </item> | ||
| 337 | <item row="1" column="7"> | ||
| 338 | <widget class="QCheckBox" name="checkboxPlayer7Connected"> | ||
| 339 | <property name="text"> | ||
| 340 | <string/> | ||
| 341 | </property> | ||
| 342 | </widget> | ||
| 343 | </item> | ||
| 344 | <item row="1" column="6"> | ||
| 345 | <widget class="QCheckBox" name="checkboxPlayer6Connected"> | ||
| 346 | <property name="text"> | ||
| 347 | <string/> | ||
| 348 | </property> | ||
| 349 | </widget> | ||
| 350 | </item> | ||
| 351 | <item row="1" column="1"> | ||
| 352 | <widget class="QCheckBox" name="checkboxPlayer1Connected"> | ||
| 353 | <property name="layoutDirection"> | ||
| 354 | <enum>Qt::LeftToRight</enum> | ||
| 355 | </property> | ||
| 356 | <property name="checked"> | ||
| 357 | <bool>true</bool> | ||
| 358 | </property> | ||
| 359 | </widget> | ||
| 360 | </item> | ||
| 361 | <item row="1" column="8"> | ||
| 362 | <widget class="QCheckBox" name="checkboxPlayer8Connected"> | ||
| 363 | <property name="text"> | ||
| 364 | <string/> | ||
| 365 | </property> | ||
| 366 | </widget> | ||
| 367 | </item> | ||
| 368 | <item row="0" column="2"> | ||
| 369 | <widget class="QLabel" name="label_3"> | ||
| 370 | <property name="text"> | ||
| 371 | <string>2</string> | ||
| 372 | </property> | ||
| 373 | <property name="alignment"> | ||
| 374 | <set>Qt::AlignCenter</set> | ||
| 375 | </property> | ||
| 376 | </widget> | ||
| 377 | </item> | ||
| 378 | <item row="0" column="3"> | ||
| 379 | <widget class="QLabel" name="label_4"> | ||
| 380 | <property name="text"> | ||
| 381 | <string>3</string> | ||
| 382 | </property> | ||
| 383 | <property name="alignment"> | ||
| 384 | <set>Qt::AlignCenter</set> | ||
| 385 | </property> | ||
| 386 | </widget> | ||
| 387 | </item> | ||
| 388 | <item row="0" column="4"> | ||
| 389 | <widget class="QLabel" name="label_5"> | ||
| 390 | <property name="text"> | ||
| 391 | <string>4</string> | ||
| 392 | </property> | ||
| 393 | <property name="alignment"> | ||
| 394 | <set>Qt::AlignCenter</set> | ||
| 395 | </property> | ||
| 396 | </widget> | ||
| 397 | </item> | ||
| 398 | <item row="0" column="5"> | ||
| 399 | <widget class="QLabel" name="label_6"> | ||
| 400 | <property name="text"> | ||
| 401 | <string>5</string> | ||
| 402 | </property> | ||
| 403 | <property name="alignment"> | ||
| 404 | <set>Qt::AlignCenter</set> | ||
| 405 | </property> | ||
| 406 | </widget> | ||
| 407 | </item> | ||
| 408 | <item row="0" column="6"> | ||
| 409 | <widget class="QLabel" name="label_7"> | ||
| 410 | <property name="text"> | ||
| 411 | <string>6</string> | ||
| 412 | </property> | ||
| 413 | <property name="alignment"> | ||
| 414 | <set>Qt::AlignCenter</set> | ||
| 415 | </property> | ||
| 416 | </widget> | ||
| 417 | </item> | ||
| 418 | <item row="0" column="7"> | ||
| 419 | <widget class="QLabel" name="label_8"> | ||
| 420 | <property name="text"> | ||
| 421 | <string>7</string> | ||
| 422 | </property> | ||
| 423 | <property name="alignment"> | ||
| 424 | <set>Qt::AlignCenter</set> | ||
| 425 | </property> | ||
| 426 | </widget> | ||
| 427 | </item> | ||
| 428 | <item row="0" column="8"> | ||
| 429 | <widget class="QLabel" name="label_9"> | ||
| 430 | <property name="text"> | ||
| 431 | <string>8</string> | ||
| 432 | </property> | ||
| 433 | <property name="alignment"> | ||
| 434 | <set>Qt::AlignCenter</set> | ||
| 435 | </property> | ||
| 436 | </widget> | ||
| 437 | </item> | ||
| 438 | <item row="0" column="0"> | ||
| 439 | <widget class="QLabel" name="label_10"> | ||
| 440 | <property name="text"> | ||
| 441 | <string>Connected</string> | ||
| 442 | </property> | ||
| 443 | </widget> | ||
| 444 | </item> | ||
| 445 | </layout> | ||
| 446 | </widget> | ||
| 447 | </item> | ||
| 448 | <item> | ||
| 449 | <spacer name="horizontalSpacer"> | ||
| 450 | <property name="orientation"> | ||
| 451 | <enum>Qt::Horizontal</enum> | ||
| 452 | </property> | ||
| 453 | <property name="sizeHint" stdset="0"> | ||
| 454 | <size> | ||
| 455 | <width>40</width> | ||
| 456 | <height>20</height> | ||
| 457 | </size> | ||
| 458 | </property> | ||
| 459 | </spacer> | ||
| 460 | </item> | ||
| 461 | <item alignment="Qt::AlignBottom"> | ||
| 462 | <widget class="QPushButton" name="buttonRestoreDefaults"> | ||
| 463 | <property name="sizePolicy"> | ||
| 464 | <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> | ||
| 465 | <horstretch>0</horstretch> | ||
| 466 | <verstretch>0</verstretch> | ||
| 467 | </sizepolicy> | ||
| 468 | </property> | ||
| 469 | <property name="minimumSize"> | ||
| 470 | <size> | ||
| 471 | <width>57</width> | ||
| 472 | <height>0</height> | ||
| 473 | </size> | ||
| 474 | </property> | ||
| 475 | <property name="maximumSize"> | ||
| 476 | <size> | ||
| 477 | <width>55</width> | ||
| 478 | <height>16777215</height> | ||
| 479 | </size> | ||
| 480 | </property> | ||
| 481 | <property name="sizeIncrement"> | ||
| 482 | <size> | ||
| 483 | <width>0</width> | ||
| 484 | <height>0</height> | ||
| 485 | </size> | ||
| 486 | </property> | ||
| 487 | <property name="baseSize"> | ||
| 488 | <size> | ||
| 489 | <width>0</width> | ||
| 490 | <height>0</height> | ||
| 491 | </size> | ||
| 492 | </property> | ||
| 493 | <property name="layoutDirection"> | ||
| 494 | <enum>Qt::LeftToRight</enum> | ||
| 495 | </property> | ||
| 496 | <property name="styleSheet"> | ||
| 497 | <string notr="true">min-width: 55px;</string> | ||
| 498 | </property> | ||
| 499 | <property name="text"> | ||
| 500 | <string>Defaults</string> | ||
| 501 | </property> | ||
| 502 | </widget> | ||
| 503 | </item> | ||
| 504 | <item alignment="Qt::AlignBottom"> | ||
| 505 | <widget class="QPushButton" name="buttonClearAll"> | ||
| 506 | <property name="sizePolicy"> | ||
| 507 | <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> | ||
| 508 | <horstretch>0</horstretch> | ||
| 509 | <verstretch>0</verstretch> | ||
| 510 | </sizepolicy> | ||
| 511 | </property> | ||
| 512 | <property name="minimumSize"> | ||
| 513 | <size> | ||
| 514 | <width>57</width> | ||
| 515 | <height>0</height> | ||
| 516 | </size> | ||
| 517 | </property> | ||
| 518 | <property name="maximumSize"> | ||
| 519 | <size> | ||
| 520 | <width>55</width> | ||
| 521 | <height>16777215</height> | ||
| 522 | </size> | ||
| 523 | </property> | ||
| 524 | <property name="sizeIncrement"> | ||
| 525 | <size> | ||
| 526 | <width>0</width> | ||
| 527 | <height>0</height> | ||
| 528 | </size> | ||
| 529 | </property> | ||
| 530 | <property name="baseSize"> | ||
| 531 | <size> | ||
| 532 | <width>0</width> | ||
| 533 | <height>0</height> | ||
| 534 | </size> | ||
| 535 | </property> | ||
| 536 | <property name="layoutDirection"> | ||
| 537 | <enum>Qt::LeftToRight</enum> | ||
| 538 | </property> | ||
| 539 | <property name="styleSheet"> | ||
| 540 | <string notr="true">min-width: 55px;</string> | ||
| 541 | </property> | ||
| 542 | <property name="text"> | ||
| 543 | <string>Clear</string> | ||
| 544 | </property> | ||
| 545 | </widget> | ||
| 546 | </item> | ||
| 547 | </layout> | ||
| 548 | </widget> | ||
| 491 | </item> | 549 | </item> |
| 492 | </layout> | 550 | </layout> |
| 493 | </widget> | 551 | </widget> |
| 494 | <resources/> | 552 | <resources/> |
| 495 | <connections> | 553 | <connections/> |
| 496 | <connection> | ||
| 497 | <sender>buttonBox</sender> | ||
| 498 | <signal>accepted()</signal> | ||
| 499 | <receiver>ConfigureInput</receiver> | ||
| 500 | <slot>accept()</slot> | ||
| 501 | <hints> | ||
| 502 | <hint type="sourcelabel"> | ||
| 503 | <x>294</x> | ||
| 504 | <y>553</y> | ||
| 505 | </hint> | ||
| 506 | <hint type="destinationlabel"> | ||
| 507 | <x>191</x> | ||
| 508 | <y>287</y> | ||
| 509 | </hint> | ||
| 510 | </hints> | ||
| 511 | </connection> | ||
| 512 | <connection> | ||
| 513 | <sender>buttonBox</sender> | ||
| 514 | <signal>rejected()</signal> | ||
| 515 | <receiver>ConfigureInput</receiver> | ||
| 516 | <slot>reject()</slot> | ||
| 517 | <hints> | ||
| 518 | <hint type="sourcelabel"> | ||
| 519 | <x>294</x> | ||
| 520 | <y>553</y> | ||
| 521 | </hint> | ||
| 522 | <hint type="destinationlabel"> | ||
| 523 | <x>191</x> | ||
| 524 | <y>287</y> | ||
| 525 | </hint> | ||
| 526 | </hints> | ||
| 527 | </connection> | ||
| 528 | </connections> | ||
| 529 | </ui> | 554 | </ui> |
diff --git a/src/yuzu/configuration/configure_input_advanced.cpp b/src/yuzu/configuration/configure_input_advanced.cpp new file mode 100644 index 000000000..db42b826b --- /dev/null +++ b/src/yuzu/configuration/configure_input_advanced.cpp | |||
| @@ -0,0 +1,169 @@ | |||
| 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 <QColorDialog> | ||
| 6 | #include "core/core.h" | ||
| 7 | #include "core/settings.h" | ||
| 8 | #include "ui_configure_input_advanced.h" | ||
| 9 | #include "yuzu/configuration/configure_input_advanced.h" | ||
| 10 | |||
| 11 | ConfigureInputAdvanced::ConfigureInputAdvanced(QWidget* parent) | ||
| 12 | : QWidget(parent), ui(std::make_unique<Ui::ConfigureInputAdvanced>()) { | ||
| 13 | ui->setupUi(this); | ||
| 14 | |||
| 15 | controllers_color_buttons = {{ | ||
| 16 | { | ||
| 17 | ui->player1_left_body_button, | ||
| 18 | ui->player1_left_buttons_button, | ||
| 19 | ui->player1_right_body_button, | ||
| 20 | ui->player1_right_buttons_button, | ||
| 21 | }, | ||
| 22 | { | ||
| 23 | ui->player2_left_body_button, | ||
| 24 | ui->player2_left_buttons_button, | ||
| 25 | ui->player2_right_body_button, | ||
| 26 | ui->player2_right_buttons_button, | ||
| 27 | }, | ||
| 28 | { | ||
| 29 | ui->player3_left_body_button, | ||
| 30 | ui->player3_left_buttons_button, | ||
| 31 | ui->player3_right_body_button, | ||
| 32 | ui->player3_right_buttons_button, | ||
| 33 | }, | ||
| 34 | { | ||
| 35 | ui->player4_left_body_button, | ||
| 36 | ui->player4_left_buttons_button, | ||
| 37 | ui->player4_right_body_button, | ||
| 38 | ui->player4_right_buttons_button, | ||
| 39 | }, | ||
| 40 | { | ||
| 41 | ui->player5_left_body_button, | ||
| 42 | ui->player5_left_buttons_button, | ||
| 43 | ui->player5_right_body_button, | ||
| 44 | ui->player5_right_buttons_button, | ||
| 45 | }, | ||
| 46 | { | ||
| 47 | ui->player6_left_body_button, | ||
| 48 | ui->player6_left_buttons_button, | ||
| 49 | ui->player6_right_body_button, | ||
| 50 | ui->player6_right_buttons_button, | ||
| 51 | }, | ||
| 52 | { | ||
| 53 | ui->player7_left_body_button, | ||
| 54 | ui->player7_left_buttons_button, | ||
| 55 | ui->player7_right_body_button, | ||
| 56 | ui->player7_right_buttons_button, | ||
| 57 | }, | ||
| 58 | { | ||
| 59 | ui->player8_left_body_button, | ||
| 60 | ui->player8_left_buttons_button, | ||
| 61 | ui->player8_right_body_button, | ||
| 62 | ui->player8_right_buttons_button, | ||
| 63 | }, | ||
| 64 | }}; | ||
| 65 | |||
| 66 | for (std::size_t player_idx = 0; player_idx < controllers_color_buttons.size(); ++player_idx) { | ||
| 67 | auto& color_buttons = controllers_color_buttons[player_idx]; | ||
| 68 | for (std::size_t button_idx = 0; button_idx < color_buttons.size(); ++button_idx) { | ||
| 69 | connect(color_buttons[button_idx], &QPushButton::clicked, this, | ||
| 70 | [this, player_idx, button_idx] { | ||
| 71 | OnControllerButtonClick(static_cast<int>(player_idx), | ||
| 72 | static_cast<int>(button_idx)); | ||
| 73 | }); | ||
| 74 | } | ||
| 75 | } | ||
| 76 | |||
| 77 | connect(ui->mouse_enabled, &QCheckBox::stateChanged, this, | ||
| 78 | &ConfigureInputAdvanced::UpdateUIEnabled); | ||
| 79 | connect(ui->debug_enabled, &QCheckBox::stateChanged, this, | ||
| 80 | &ConfigureInputAdvanced::UpdateUIEnabled); | ||
| 81 | connect(ui->touchscreen_enabled, &QCheckBox::stateChanged, this, | ||
| 82 | &ConfigureInputAdvanced::UpdateUIEnabled); | ||
| 83 | |||
| 84 | connect(ui->debug_configure, &QPushButton::clicked, this, | ||
| 85 | [this] { CallDebugControllerDialog(); }); | ||
| 86 | connect(ui->mouse_advanced, &QPushButton::clicked, this, [this] { CallMouseConfigDialog(); }); | ||
| 87 | connect(ui->touchscreen_advanced, &QPushButton::clicked, this, | ||
| 88 | [this] { CallTouchscreenConfigDialog(); }); | ||
| 89 | |||
| 90 | LoadConfiguration(); | ||
| 91 | } | ||
| 92 | |||
| 93 | ConfigureInputAdvanced::~ConfigureInputAdvanced() = default; | ||
| 94 | |||
| 95 | void ConfigureInputAdvanced::OnControllerButtonClick(int player_idx, int button_idx) { | ||
| 96 | const QColor new_bg_color = QColorDialog::getColor(controllers_colors[player_idx][button_idx]); | ||
| 97 | if (!new_bg_color.isValid()) { | ||
| 98 | return; | ||
| 99 | } | ||
| 100 | controllers_colors[player_idx][button_idx] = new_bg_color; | ||
| 101 | controllers_color_buttons[player_idx][button_idx]->setStyleSheet( | ||
| 102 | QStringLiteral("background-color: %1; min-width: 55px;") | ||
| 103 | .arg(controllers_colors[player_idx][button_idx].name())); | ||
| 104 | } | ||
| 105 | |||
| 106 | void ConfigureInputAdvanced::ApplyConfiguration() { | ||
| 107 | for (std::size_t player_idx = 0; player_idx < controllers_color_buttons.size(); ++player_idx) { | ||
| 108 | auto& player = Settings::values.players[player_idx]; | ||
| 109 | std::array<u32, 4> colors{}; | ||
| 110 | std::transform(controllers_colors[player_idx].begin(), controllers_colors[player_idx].end(), | ||
| 111 | colors.begin(), [](QColor color) { return color.rgb(); }); | ||
| 112 | |||
| 113 | player.body_color_left = colors[0]; | ||
| 114 | player.button_color_left = colors[1]; | ||
| 115 | player.body_color_right = colors[2]; | ||
| 116 | player.button_color_right = colors[3]; | ||
| 117 | } | ||
| 118 | |||
| 119 | Settings::values.debug_pad_enabled = ui->debug_enabled->isChecked(); | ||
| 120 | Settings::values.mouse_enabled = ui->mouse_enabled->isChecked(); | ||
| 121 | Settings::values.keyboard_enabled = ui->keyboard_enabled->isChecked(); | ||
| 122 | Settings::values.touchscreen.enabled = ui->touchscreen_enabled->isChecked(); | ||
| 123 | } | ||
| 124 | |||
| 125 | void ConfigureInputAdvanced::LoadConfiguration() { | ||
| 126 | for (std::size_t player_idx = 0; player_idx < controllers_color_buttons.size(); ++player_idx) { | ||
| 127 | auto& player = Settings::values.players[player_idx]; | ||
| 128 | std::array<u32, 4> colors = { | ||
| 129 | player.body_color_left, | ||
| 130 | player.button_color_left, | ||
| 131 | player.body_color_right, | ||
| 132 | player.button_color_right, | ||
| 133 | }; | ||
| 134 | |||
| 135 | std::transform(colors.begin(), colors.end(), controllers_colors[player_idx].begin(), | ||
| 136 | [](u32 rgb) { return QColor::fromRgb(rgb); }); | ||
| 137 | |||
| 138 | for (std::size_t button_idx = 0; button_idx < colors.size(); ++button_idx) { | ||
| 139 | controllers_color_buttons[player_idx][button_idx]->setStyleSheet( | ||
| 140 | QStringLiteral("background-color: %1; min-width: 55px;") | ||
| 141 | .arg(controllers_colors[player_idx][button_idx].name())); | ||
| 142 | } | ||
| 143 | } | ||
| 144 | |||
| 145 | ui->debug_enabled->setChecked(Settings::values.debug_pad_enabled); | ||
| 146 | ui->mouse_enabled->setChecked(Settings::values.mouse_enabled); | ||
| 147 | ui->keyboard_enabled->setChecked(Settings::values.keyboard_enabled); | ||
| 148 | ui->touchscreen_enabled->setChecked(Settings::values.touchscreen.enabled); | ||
| 149 | |||
| 150 | UpdateUIEnabled(); | ||
| 151 | } | ||
| 152 | |||
| 153 | void ConfigureInputAdvanced::changeEvent(QEvent* event) { | ||
| 154 | if (event->type() == QEvent::LanguageChange) { | ||
| 155 | RetranslateUI(); | ||
| 156 | } | ||
| 157 | |||
| 158 | QWidget::changeEvent(event); | ||
| 159 | } | ||
| 160 | |||
| 161 | void ConfigureInputAdvanced::RetranslateUI() { | ||
| 162 | ui->retranslateUi(this); | ||
| 163 | } | ||
| 164 | |||
| 165 | void ConfigureInputAdvanced::UpdateUIEnabled() { | ||
| 166 | ui->mouse_advanced->setEnabled(ui->mouse_enabled->isChecked()); | ||
| 167 | ui->debug_configure->setEnabled(ui->debug_enabled->isChecked()); | ||
| 168 | ui->touchscreen_advanced->setEnabled(ui->touchscreen_enabled->isChecked()); | ||
| 169 | } | ||
diff --git a/src/yuzu/configuration/configure_input_advanced.h b/src/yuzu/configuration/configure_input_advanced.h new file mode 100644 index 000000000..d8fcec52d --- /dev/null +++ b/src/yuzu/configuration/configure_input_advanced.h | |||
| @@ -0,0 +1,45 @@ | |||
| 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 | #include <memory> | ||
| 9 | #include <QWidget> | ||
| 10 | |||
| 11 | class QColor; | ||
| 12 | class QPushButton; | ||
| 13 | |||
| 14 | namespace Ui { | ||
| 15 | class ConfigureInputAdvanced; | ||
| 16 | } | ||
| 17 | |||
| 18 | class ConfigureInputAdvanced : public QWidget { | ||
| 19 | Q_OBJECT | ||
| 20 | |||
| 21 | public: | ||
| 22 | explicit ConfigureInputAdvanced(QWidget* parent = nullptr); | ||
| 23 | ~ConfigureInputAdvanced() override; | ||
| 24 | |||
| 25 | void ApplyConfiguration(); | ||
| 26 | |||
| 27 | signals: | ||
| 28 | void CallDebugControllerDialog(); | ||
| 29 | void CallMouseConfigDialog(); | ||
| 30 | void CallTouchscreenConfigDialog(); | ||
| 31 | |||
| 32 | private: | ||
| 33 | void changeEvent(QEvent* event) override; | ||
| 34 | void RetranslateUI(); | ||
| 35 | void UpdateUIEnabled(); | ||
| 36 | |||
| 37 | void OnControllerButtonClick(int player_idx, int button_idx); | ||
| 38 | |||
| 39 | void LoadConfiguration(); | ||
| 40 | |||
| 41 | std::unique_ptr<Ui::ConfigureInputAdvanced> ui; | ||
| 42 | |||
| 43 | std::array<std::array<QColor, 4>, 8> controllers_colors; | ||
| 44 | std::array<std::array<QPushButton*, 4>, 8> controllers_color_buttons; | ||
| 45 | }; | ||
diff --git a/src/yuzu/configuration/configure_input_advanced.ui b/src/yuzu/configuration/configure_input_advanced.ui new file mode 100644 index 000000000..5958435fc --- /dev/null +++ b/src/yuzu/configuration/configure_input_advanced.ui | |||
| @@ -0,0 +1,2688 @@ | |||
| 1 | <?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | <ui version="4.0"> | ||
| 3 | <class>ConfigureInputAdvanced</class> | ||
| 4 | <widget class="QWidget" name="ConfigureInputAdvanced"> | ||
| 5 | <property name="geometry"> | ||
| 6 | <rect> | ||
| 7 | <x>0</x> | ||
| 8 | <y>0</y> | ||
| 9 | <width>710</width> | ||
| 10 | <height>580</height> | ||
| 11 | </rect> | ||
| 12 | </property> | ||
| 13 | <property name="windowTitle"> | ||
| 14 | <string>Configure Input</string> | ||
| 15 | </property> | ||
| 16 | <property name="styleSheet"> | ||
| 17 | <string notr="true"/> | ||
| 18 | </property> | ||
| 19 | <layout class="QHBoxLayout" name="horizontalLayout"> | ||
| 20 | <property name="spacing"> | ||
| 21 | <number>0</number> | ||
| 22 | </property> | ||
| 23 | <property name="leftMargin"> | ||
| 24 | <number>0</number> | ||
| 25 | </property> | ||
| 26 | <property name="topMargin"> | ||
| 27 | <number>0</number> | ||
| 28 | </property> | ||
| 29 | <property name="rightMargin"> | ||
| 30 | <number>0</number> | ||
| 31 | </property> | ||
| 32 | <property name="bottomMargin"> | ||
| 33 | <number>0</number> | ||
| 34 | </property> | ||
| 35 | <item> | ||
| 36 | <widget class="QWidget" name="mainInputAdvanced" native="true"> | ||
| 37 | <layout class="QHBoxLayout" name="main" stretch="1,1"> | ||
| 38 | <property name="spacing"> | ||
| 39 | <number>9</number> | ||
| 40 | </property> | ||
| 41 | <property name="leftMargin"> | ||
| 42 | <number>0</number> | ||
| 43 | </property> | ||
| 44 | <property name="topMargin"> | ||
| 45 | <number>0</number> | ||
| 46 | </property> | ||
| 47 | <property name="rightMargin"> | ||
| 48 | <number>0</number> | ||
| 49 | </property> | ||
| 50 | <property name="bottomMargin"> | ||
| 51 | <number>0</number> | ||
| 52 | </property> | ||
| 53 | <item> | ||
| 54 | <widget class="QWidget" name="leftInputAdvanced" native="true"> | ||
| 55 | <layout class="QVBoxLayout" name="leftLayout" stretch="0"> | ||
| 56 | <property name="spacing"> | ||
| 57 | <number>3</number> | ||
| 58 | </property> | ||
| 59 | <property name="leftMargin"> | ||
| 60 | <number>0</number> | ||
| 61 | </property> | ||
| 62 | <property name="topMargin"> | ||
| 63 | <number>0</number> | ||
| 64 | </property> | ||
| 65 | <property name="rightMargin"> | ||
| 66 | <number>0</number> | ||
| 67 | </property> | ||
| 68 | <property name="bottomMargin"> | ||
| 69 | <number>0</number> | ||
| 70 | </property> | ||
| 71 | <item> | ||
| 72 | <widget class="QGroupBox" name="joyconColorsGroup"> | ||
| 73 | <property name="title"> | ||
| 74 | <string>Joycon Colors</string> | ||
| 75 | </property> | ||
| 76 | <layout class="QVBoxLayout" name="verticalLayout_3" stretch="1,1"> | ||
| 77 | <property name="leftMargin"> | ||
| 78 | <number>9</number> | ||
| 79 | </property> | ||
| 80 | <property name="topMargin"> | ||
| 81 | <number>9</number> | ||
| 82 | </property> | ||
| 83 | <property name="rightMargin"> | ||
| 84 | <number>9</number> | ||
| 85 | </property> | ||
| 86 | <property name="bottomMargin"> | ||
| 87 | <number>9</number> | ||
| 88 | </property> | ||
| 89 | <item> | ||
| 90 | <widget class="QWidget" name="topLeftInputAdvanced" native="true"> | ||
| 91 | <layout class="QVBoxLayout" name="verticalLayout_4"> | ||
| 92 | <property name="spacing"> | ||
| 93 | <number>6</number> | ||
| 94 | </property> | ||
| 95 | <property name="leftMargin"> | ||
| 96 | <number>0</number> | ||
| 97 | </property> | ||
| 98 | <property name="topMargin"> | ||
| 99 | <number>0</number> | ||
| 100 | </property> | ||
| 101 | <property name="rightMargin"> | ||
| 102 | <number>0</number> | ||
| 103 | </property> | ||
| 104 | <property name="bottomMargin"> | ||
| 105 | <number>0</number> | ||
| 106 | </property> | ||
| 107 | <item> | ||
| 108 | <widget class="QWidget" name="player12Widget" native="true"> | ||
| 109 | <layout class="QHBoxLayout" name="horizontalLayout_4"> | ||
| 110 | <property name="leftMargin"> | ||
| 111 | <number>0</number> | ||
| 112 | </property> | ||
| 113 | <property name="topMargin"> | ||
| 114 | <number>0</number> | ||
| 115 | </property> | ||
| 116 | <property name="rightMargin"> | ||
| 117 | <number>0</number> | ||
| 118 | </property> | ||
| 119 | <property name="bottomMargin"> | ||
| 120 | <number>0</number> | ||
| 121 | </property> | ||
| 122 | <item> | ||
| 123 | <widget class="QGroupBox" name="player1Group"> | ||
| 124 | <property name="title"> | ||
| 125 | <string>Player 1</string> | ||
| 126 | </property> | ||
| 127 | <layout class="QHBoxLayout" name="horizontalLayout_2"> | ||
| 128 | <property name="spacing"> | ||
| 129 | <number>6</number> | ||
| 130 | </property> | ||
| 131 | <property name="leftMargin"> | ||
| 132 | <number>6</number> | ||
| 133 | </property> | ||
| 134 | <property name="topMargin"> | ||
| 135 | <number>0</number> | ||
| 136 | </property> | ||
| 137 | <property name="rightMargin"> | ||
| 138 | <number>6</number> | ||
| 139 | </property> | ||
| 140 | <property name="bottomMargin"> | ||
| 141 | <number>6</number> | ||
| 142 | </property> | ||
| 143 | <item> | ||
| 144 | <widget class="QWidget" name="player1LeftJoycon" native="true"> | ||
| 145 | <layout class="QVBoxLayout" name="buttonMiscButtonsLeftJoyconVerticalLayout_14"> | ||
| 146 | <property name="spacing"> | ||
| 147 | <number>0</number> | ||
| 148 | </property> | ||
| 149 | <property name="leftMargin"> | ||
| 150 | <number>0</number> | ||
| 151 | </property> | ||
| 152 | <property name="topMargin"> | ||
| 153 | <number>0</number> | ||
| 154 | </property> | ||
| 155 | <property name="rightMargin"> | ||
| 156 | <number>0</number> | ||
| 157 | </property> | ||
| 158 | <property name="bottomMargin"> | ||
| 159 | <number>0</number> | ||
| 160 | </property> | ||
| 161 | <item alignment="Qt::AlignHCenter"> | ||
| 162 | <widget class="QGroupBox" name="player1LeftBodyGroup"> | ||
| 163 | <property name="title"> | ||
| 164 | <string>L Body</string> | ||
| 165 | </property> | ||
| 166 | <property name="alignment"> | ||
| 167 | <set>Qt::AlignCenter</set> | ||
| 168 | </property> | ||
| 169 | <layout class="QVBoxLayout" name="verticalLayout_66"> | ||
| 170 | <property name="spacing"> | ||
| 171 | <number>3</number> | ||
| 172 | </property> | ||
| 173 | <property name="leftMargin"> | ||
| 174 | <number>3</number> | ||
| 175 | </property> | ||
| 176 | <property name="topMargin"> | ||
| 177 | <number>3</number> | ||
| 178 | </property> | ||
| 179 | <property name="rightMargin"> | ||
| 180 | <number>3</number> | ||
| 181 | </property> | ||
| 182 | <property name="bottomMargin"> | ||
| 183 | <number>3</number> | ||
| 184 | </property> | ||
| 185 | <item> | ||
| 186 | <widget class="QPushButton" name="player1_left_body_button"> | ||
| 187 | <property name="sizePolicy"> | ||
| 188 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 189 | <horstretch>0</horstretch> | ||
| 190 | <verstretch>0</verstretch> | ||
| 191 | </sizepolicy> | ||
| 192 | </property> | ||
| 193 | <property name="minimumSize"> | ||
| 194 | <size> | ||
| 195 | <width>57</width> | ||
| 196 | <height>0</height> | ||
| 197 | </size> | ||
| 198 | </property> | ||
| 199 | <property name="maximumSize"> | ||
| 200 | <size> | ||
| 201 | <width>55</width> | ||
| 202 | <height>16777215</height> | ||
| 203 | </size> | ||
| 204 | </property> | ||
| 205 | <property name="styleSheet"> | ||
| 206 | <string notr="true">min-width: 55px;</string> | ||
| 207 | </property> | ||
| 208 | <property name="text"> | ||
| 209 | <string/> | ||
| 210 | </property> | ||
| 211 | </widget> | ||
| 212 | </item> | ||
| 213 | </layout> | ||
| 214 | </widget> | ||
| 215 | </item> | ||
| 216 | <item alignment="Qt::AlignHCenter"> | ||
| 217 | <widget class="QGroupBox" name="player1LeftButtonsGroup"> | ||
| 218 | <property name="title"> | ||
| 219 | <string>L Button</string> | ||
| 220 | </property> | ||
| 221 | <property name="alignment"> | ||
| 222 | <set>Qt::AlignCenter</set> | ||
| 223 | </property> | ||
| 224 | <layout class="QVBoxLayout" name="verticalLayout_67"> | ||
| 225 | <property name="spacing"> | ||
| 226 | <number>3</number> | ||
| 227 | </property> | ||
| 228 | <property name="leftMargin"> | ||
| 229 | <number>3</number> | ||
| 230 | </property> | ||
| 231 | <property name="topMargin"> | ||
| 232 | <number>3</number> | ||
| 233 | </property> | ||
| 234 | <property name="rightMargin"> | ||
| 235 | <number>3</number> | ||
| 236 | </property> | ||
| 237 | <property name="bottomMargin"> | ||
| 238 | <number>3</number> | ||
| 239 | </property> | ||
| 240 | <item> | ||
| 241 | <widget class="QPushButton" name="player1_left_buttons_button"> | ||
| 242 | <property name="sizePolicy"> | ||
| 243 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 244 | <horstretch>0</horstretch> | ||
| 245 | <verstretch>0</verstretch> | ||
| 246 | </sizepolicy> | ||
| 247 | </property> | ||
| 248 | <property name="minimumSize"> | ||
| 249 | <size> | ||
| 250 | <width>57</width> | ||
| 251 | <height>0</height> | ||
| 252 | </size> | ||
| 253 | </property> | ||
| 254 | <property name="maximumSize"> | ||
| 255 | <size> | ||
| 256 | <width>55</width> | ||
| 257 | <height>16777215</height> | ||
| 258 | </size> | ||
| 259 | </property> | ||
| 260 | <property name="styleSheet"> | ||
| 261 | <string notr="true">min-width: 55px;</string> | ||
| 262 | </property> | ||
| 263 | <property name="text"> | ||
| 264 | <string/> | ||
| 265 | </property> | ||
| 266 | </widget> | ||
| 267 | </item> | ||
| 268 | </layout> | ||
| 269 | </widget> | ||
| 270 | </item> | ||
| 271 | </layout> | ||
| 272 | </widget> | ||
| 273 | </item> | ||
| 274 | <item> | ||
| 275 | <widget class="QWidget" name="player1RightJoycon" native="true"> | ||
| 276 | <layout class="QVBoxLayout" name="buttonMiscButtonsRightJoyconVerticalLayout_14"> | ||
| 277 | <property name="spacing"> | ||
| 278 | <number>0</number> | ||
| 279 | </property> | ||
| 280 | <property name="leftMargin"> | ||
| 281 | <number>0</number> | ||
| 282 | </property> | ||
| 283 | <property name="topMargin"> | ||
| 284 | <number>0</number> | ||
| 285 | </property> | ||
| 286 | <property name="rightMargin"> | ||
| 287 | <number>0</number> | ||
| 288 | </property> | ||
| 289 | <property name="bottomMargin"> | ||
| 290 | <number>0</number> | ||
| 291 | </property> | ||
| 292 | <item alignment="Qt::AlignHCenter"> | ||
| 293 | <widget class="QGroupBox" name="player1RightBodyGroup"> | ||
| 294 | <property name="title"> | ||
| 295 | <string>R Body</string> | ||
| 296 | </property> | ||
| 297 | <property name="alignment"> | ||
| 298 | <set>Qt::AlignCenter</set> | ||
| 299 | </property> | ||
| 300 | <layout class="QVBoxLayout" name="verticalLayout_64"> | ||
| 301 | <property name="spacing"> | ||
| 302 | <number>3</number> | ||
| 303 | </property> | ||
| 304 | <property name="leftMargin"> | ||
| 305 | <number>3</number> | ||
| 306 | </property> | ||
| 307 | <property name="topMargin"> | ||
| 308 | <number>3</number> | ||
| 309 | </property> | ||
| 310 | <property name="rightMargin"> | ||
| 311 | <number>3</number> | ||
| 312 | </property> | ||
| 313 | <property name="bottomMargin"> | ||
| 314 | <number>3</number> | ||
| 315 | </property> | ||
| 316 | <item> | ||
| 317 | <widget class="QPushButton" name="player1_right_body_button"> | ||
| 318 | <property name="sizePolicy"> | ||
| 319 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 320 | <horstretch>0</horstretch> | ||
| 321 | <verstretch>0</verstretch> | ||
| 322 | </sizepolicy> | ||
| 323 | </property> | ||
| 324 | <property name="minimumSize"> | ||
| 325 | <size> | ||
| 326 | <width>57</width> | ||
| 327 | <height>0</height> | ||
| 328 | </size> | ||
| 329 | </property> | ||
| 330 | <property name="maximumSize"> | ||
| 331 | <size> | ||
| 332 | <width>55</width> | ||
| 333 | <height>16777215</height> | ||
| 334 | </size> | ||
| 335 | </property> | ||
| 336 | <property name="styleSheet"> | ||
| 337 | <string notr="true">min-width: 55px;</string> | ||
| 338 | </property> | ||
| 339 | <property name="text"> | ||
| 340 | <string/> | ||
| 341 | </property> | ||
| 342 | </widget> | ||
| 343 | </item> | ||
| 344 | </layout> | ||
| 345 | </widget> | ||
| 346 | </item> | ||
| 347 | <item alignment="Qt::AlignHCenter"> | ||
| 348 | <widget class="QGroupBox" name="player1RightButtonsGroup"> | ||
| 349 | <property name="title"> | ||
| 350 | <string>R Button</string> | ||
| 351 | </property> | ||
| 352 | <property name="alignment"> | ||
| 353 | <set>Qt::AlignCenter</set> | ||
| 354 | </property> | ||
| 355 | <layout class="QVBoxLayout" name="verticalLayout_65"> | ||
| 356 | <property name="spacing"> | ||
| 357 | <number>3</number> | ||
| 358 | </property> | ||
| 359 | <property name="leftMargin"> | ||
| 360 | <number>3</number> | ||
| 361 | </property> | ||
| 362 | <property name="topMargin"> | ||
| 363 | <number>3</number> | ||
| 364 | </property> | ||
| 365 | <property name="rightMargin"> | ||
| 366 | <number>3</number> | ||
| 367 | </property> | ||
| 368 | <property name="bottomMargin"> | ||
| 369 | <number>3</number> | ||
| 370 | </property> | ||
| 371 | <item> | ||
| 372 | <widget class="QPushButton" name="player1_right_buttons_button"> | ||
| 373 | <property name="sizePolicy"> | ||
| 374 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 375 | <horstretch>0</horstretch> | ||
| 376 | <verstretch>0</verstretch> | ||
| 377 | </sizepolicy> | ||
| 378 | </property> | ||
| 379 | <property name="minimumSize"> | ||
| 380 | <size> | ||
| 381 | <width>57</width> | ||
| 382 | <height>0</height> | ||
| 383 | </size> | ||
| 384 | </property> | ||
| 385 | <property name="maximumSize"> | ||
| 386 | <size> | ||
| 387 | <width>55</width> | ||
| 388 | <height>16777215</height> | ||
| 389 | </size> | ||
| 390 | </property> | ||
| 391 | <property name="styleSheet"> | ||
| 392 | <string notr="true">min-width: 55px;</string> | ||
| 393 | </property> | ||
| 394 | <property name="text"> | ||
| 395 | <string/> | ||
| 396 | </property> | ||
| 397 | </widget> | ||
| 398 | </item> | ||
| 399 | </layout> | ||
| 400 | </widget> | ||
| 401 | </item> | ||
| 402 | </layout> | ||
| 403 | </widget> | ||
| 404 | </item> | ||
| 405 | </layout> | ||
| 406 | </widget> | ||
| 407 | </item> | ||
| 408 | <item> | ||
| 409 | <widget class="QGroupBox" name="player2Group"> | ||
| 410 | <property name="title"> | ||
| 411 | <string>Player 2</string> | ||
| 412 | </property> | ||
| 413 | <layout class="QHBoxLayout" name="horizontalLayout_14"> | ||
| 414 | <property name="spacing"> | ||
| 415 | <number>6</number> | ||
| 416 | </property> | ||
| 417 | <property name="leftMargin"> | ||
| 418 | <number>6</number> | ||
| 419 | </property> | ||
| 420 | <property name="topMargin"> | ||
| 421 | <number>0</number> | ||
| 422 | </property> | ||
| 423 | <property name="rightMargin"> | ||
| 424 | <number>6</number> | ||
| 425 | </property> | ||
| 426 | <property name="bottomMargin"> | ||
| 427 | <number>6</number> | ||
| 428 | </property> | ||
| 429 | <item> | ||
| 430 | <widget class="QWidget" name="player2LeftJoycon" native="true"> | ||
| 431 | <layout class="QVBoxLayout" name="buttonMiscButtonsLeftJoyconVerticalLayout_15"> | ||
| 432 | <property name="spacing"> | ||
| 433 | <number>0</number> | ||
| 434 | </property> | ||
| 435 | <property name="leftMargin"> | ||
| 436 | <number>0</number> | ||
| 437 | </property> | ||
| 438 | <property name="topMargin"> | ||
| 439 | <number>0</number> | ||
| 440 | </property> | ||
| 441 | <property name="rightMargin"> | ||
| 442 | <number>0</number> | ||
| 443 | </property> | ||
| 444 | <property name="bottomMargin"> | ||
| 445 | <number>0</number> | ||
| 446 | </property> | ||
| 447 | <item alignment="Qt::AlignHCenter"> | ||
| 448 | <widget class="QGroupBox" name="player2LeftBodyGroup"> | ||
| 449 | <property name="title"> | ||
| 450 | <string>L Body</string> | ||
| 451 | </property> | ||
| 452 | <property name="alignment"> | ||
| 453 | <set>Qt::AlignCenter</set> | ||
| 454 | </property> | ||
| 455 | <layout class="QVBoxLayout" name="verticalLayout_70"> | ||
| 456 | <property name="spacing"> | ||
| 457 | <number>3</number> | ||
| 458 | </property> | ||
| 459 | <property name="leftMargin"> | ||
| 460 | <number>3</number> | ||
| 461 | </property> | ||
| 462 | <property name="topMargin"> | ||
| 463 | <number>3</number> | ||
| 464 | </property> | ||
| 465 | <property name="rightMargin"> | ||
| 466 | <number>3</number> | ||
| 467 | </property> | ||
| 468 | <property name="bottomMargin"> | ||
| 469 | <number>3</number> | ||
| 470 | </property> | ||
| 471 | <item> | ||
| 472 | <widget class="QPushButton" name="player2_left_body_button"> | ||
| 473 | <property name="sizePolicy"> | ||
| 474 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 475 | <horstretch>0</horstretch> | ||
| 476 | <verstretch>0</verstretch> | ||
| 477 | </sizepolicy> | ||
| 478 | </property> | ||
| 479 | <property name="minimumSize"> | ||
| 480 | <size> | ||
| 481 | <width>57</width> | ||
| 482 | <height>0</height> | ||
| 483 | </size> | ||
| 484 | </property> | ||
| 485 | <property name="maximumSize"> | ||
| 486 | <size> | ||
| 487 | <width>55</width> | ||
| 488 | <height>16777215</height> | ||
| 489 | </size> | ||
| 490 | </property> | ||
| 491 | <property name="styleSheet"> | ||
| 492 | <string notr="true">min-width: 55px;</string> | ||
| 493 | </property> | ||
| 494 | <property name="text"> | ||
| 495 | <string/> | ||
| 496 | </property> | ||
| 497 | </widget> | ||
| 498 | </item> | ||
| 499 | </layout> | ||
| 500 | </widget> | ||
| 501 | </item> | ||
| 502 | <item alignment="Qt::AlignHCenter"> | ||
| 503 | <widget class="QGroupBox" name="player2LeftButtonsGroup"> | ||
| 504 | <property name="title"> | ||
| 505 | <string>L Button</string> | ||
| 506 | </property> | ||
| 507 | <property name="alignment"> | ||
| 508 | <set>Qt::AlignCenter</set> | ||
| 509 | </property> | ||
| 510 | <layout class="QVBoxLayout" name="verticalLayout_71"> | ||
| 511 | <property name="spacing"> | ||
| 512 | <number>3</number> | ||
| 513 | </property> | ||
| 514 | <property name="leftMargin"> | ||
| 515 | <number>3</number> | ||
| 516 | </property> | ||
| 517 | <property name="topMargin"> | ||
| 518 | <number>3</number> | ||
| 519 | </property> | ||
| 520 | <property name="rightMargin"> | ||
| 521 | <number>3</number> | ||
| 522 | </property> | ||
| 523 | <property name="bottomMargin"> | ||
| 524 | <number>3</number> | ||
| 525 | </property> | ||
| 526 | <item> | ||
| 527 | <widget class="QPushButton" name="player2_left_buttons_button"> | ||
| 528 | <property name="sizePolicy"> | ||
| 529 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 530 | <horstretch>0</horstretch> | ||
| 531 | <verstretch>0</verstretch> | ||
| 532 | </sizepolicy> | ||
| 533 | </property> | ||
| 534 | <property name="minimumSize"> | ||
| 535 | <size> | ||
| 536 | <width>57</width> | ||
| 537 | <height>0</height> | ||
| 538 | </size> | ||
| 539 | </property> | ||
| 540 | <property name="maximumSize"> | ||
| 541 | <size> | ||
| 542 | <width>55</width> | ||
| 543 | <height>16777215</height> | ||
| 544 | </size> | ||
| 545 | </property> | ||
| 546 | <property name="styleSheet"> | ||
| 547 | <string notr="true">min-width: 55px;</string> | ||
| 548 | </property> | ||
| 549 | <property name="text"> | ||
| 550 | <string/> | ||
| 551 | </property> | ||
| 552 | </widget> | ||
| 553 | </item> | ||
| 554 | </layout> | ||
| 555 | </widget> | ||
| 556 | </item> | ||
| 557 | </layout> | ||
| 558 | </widget> | ||
| 559 | </item> | ||
| 560 | <item> | ||
| 561 | <widget class="QWidget" name="player2RightJoycon" native="true"> | ||
| 562 | <layout class="QVBoxLayout" name="buttonMiscButtonsRightJoyconVerticalLayout_15"> | ||
| 563 | <property name="spacing"> | ||
| 564 | <number>0</number> | ||
| 565 | </property> | ||
| 566 | <property name="leftMargin"> | ||
| 567 | <number>0</number> | ||
| 568 | </property> | ||
| 569 | <property name="topMargin"> | ||
| 570 | <number>0</number> | ||
| 571 | </property> | ||
| 572 | <property name="rightMargin"> | ||
| 573 | <number>0</number> | ||
| 574 | </property> | ||
| 575 | <property name="bottomMargin"> | ||
| 576 | <number>0</number> | ||
| 577 | </property> | ||
| 578 | <item alignment="Qt::AlignHCenter"> | ||
| 579 | <widget class="QGroupBox" name="player2RightBodyGroup"> | ||
| 580 | <property name="title"> | ||
| 581 | <string>R Body</string> | ||
| 582 | </property> | ||
| 583 | <property name="alignment"> | ||
| 584 | <set>Qt::AlignCenter</set> | ||
| 585 | </property> | ||
| 586 | <layout class="QVBoxLayout" name="verticalLayout_68"> | ||
| 587 | <property name="spacing"> | ||
| 588 | <number>3</number> | ||
| 589 | </property> | ||
| 590 | <property name="leftMargin"> | ||
| 591 | <number>3</number> | ||
| 592 | </property> | ||
| 593 | <property name="topMargin"> | ||
| 594 | <number>3</number> | ||
| 595 | </property> | ||
| 596 | <property name="rightMargin"> | ||
| 597 | <number>3</number> | ||
| 598 | </property> | ||
| 599 | <property name="bottomMargin"> | ||
| 600 | <number>3</number> | ||
| 601 | </property> | ||
| 602 | <item> | ||
| 603 | <widget class="QPushButton" name="player2_right_body_button"> | ||
| 604 | <property name="sizePolicy"> | ||
| 605 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 606 | <horstretch>0</horstretch> | ||
| 607 | <verstretch>0</verstretch> | ||
| 608 | </sizepolicy> | ||
| 609 | </property> | ||
| 610 | <property name="minimumSize"> | ||
| 611 | <size> | ||
| 612 | <width>57</width> | ||
| 613 | <height>0</height> | ||
| 614 | </size> | ||
| 615 | </property> | ||
| 616 | <property name="maximumSize"> | ||
| 617 | <size> | ||
| 618 | <width>55</width> | ||
| 619 | <height>16777215</height> | ||
| 620 | </size> | ||
| 621 | </property> | ||
| 622 | <property name="styleSheet"> | ||
| 623 | <string notr="true">min-width: 55px;</string> | ||
| 624 | </property> | ||
| 625 | <property name="text"> | ||
| 626 | <string/> | ||
| 627 | </property> | ||
| 628 | </widget> | ||
| 629 | </item> | ||
| 630 | </layout> | ||
| 631 | </widget> | ||
| 632 | </item> | ||
| 633 | <item alignment="Qt::AlignHCenter"> | ||
| 634 | <widget class="QGroupBox" name="player2RightButtonsGroup"> | ||
| 635 | <property name="title"> | ||
| 636 | <string>R Button</string> | ||
| 637 | </property> | ||
| 638 | <property name="alignment"> | ||
| 639 | <set>Qt::AlignCenter</set> | ||
| 640 | </property> | ||
| 641 | <layout class="QVBoxLayout" name="verticalLayout_69"> | ||
| 642 | <property name="spacing"> | ||
| 643 | <number>3</number> | ||
| 644 | </property> | ||
| 645 | <property name="leftMargin"> | ||
| 646 | <number>3</number> | ||
| 647 | </property> | ||
| 648 | <property name="topMargin"> | ||
| 649 | <number>3</number> | ||
| 650 | </property> | ||
| 651 | <property name="rightMargin"> | ||
| 652 | <number>3</number> | ||
| 653 | </property> | ||
| 654 | <property name="bottomMargin"> | ||
| 655 | <number>3</number> | ||
| 656 | </property> | ||
| 657 | <item> | ||
| 658 | <widget class="QPushButton" name="player2_right_buttons_button"> | ||
| 659 | <property name="sizePolicy"> | ||
| 660 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 661 | <horstretch>0</horstretch> | ||
| 662 | <verstretch>0</verstretch> | ||
| 663 | </sizepolicy> | ||
| 664 | </property> | ||
| 665 | <property name="minimumSize"> | ||
| 666 | <size> | ||
| 667 | <width>57</width> | ||
| 668 | <height>0</height> | ||
| 669 | </size> | ||
| 670 | </property> | ||
| 671 | <property name="maximumSize"> | ||
| 672 | <size> | ||
| 673 | <width>55</width> | ||
| 674 | <height>16777215</height> | ||
| 675 | </size> | ||
| 676 | </property> | ||
| 677 | <property name="styleSheet"> | ||
| 678 | <string notr="true">min-width: 55px;</string> | ||
| 679 | </property> | ||
| 680 | <property name="text"> | ||
| 681 | <string/> | ||
| 682 | </property> | ||
| 683 | </widget> | ||
| 684 | </item> | ||
| 685 | </layout> | ||
| 686 | </widget> | ||
| 687 | </item> | ||
| 688 | </layout> | ||
| 689 | </widget> | ||
| 690 | </item> | ||
| 691 | </layout> | ||
| 692 | </widget> | ||
| 693 | </item> | ||
| 694 | </layout> | ||
| 695 | </widget> | ||
| 696 | </item> | ||
| 697 | <item> | ||
| 698 | <widget class="QWidget" name="player34Widget" native="true"> | ||
| 699 | <layout class="QHBoxLayout" name="horizontalLayout_5"> | ||
| 700 | <property name="leftMargin"> | ||
| 701 | <number>0</number> | ||
| 702 | </property> | ||
| 703 | <property name="topMargin"> | ||
| 704 | <number>0</number> | ||
| 705 | </property> | ||
| 706 | <property name="rightMargin"> | ||
| 707 | <number>0</number> | ||
| 708 | </property> | ||
| 709 | <property name="bottomMargin"> | ||
| 710 | <number>0</number> | ||
| 711 | </property> | ||
| 712 | <item> | ||
| 713 | <widget class="QGroupBox" name="player3Group"> | ||
| 714 | <property name="title"> | ||
| 715 | <string>Player 3</string> | ||
| 716 | </property> | ||
| 717 | <layout class="QHBoxLayout" name="horizontalLayout_15"> | ||
| 718 | <property name="spacing"> | ||
| 719 | <number>6</number> | ||
| 720 | </property> | ||
| 721 | <property name="leftMargin"> | ||
| 722 | <number>6</number> | ||
| 723 | </property> | ||
| 724 | <property name="topMargin"> | ||
| 725 | <number>0</number> | ||
| 726 | </property> | ||
| 727 | <property name="rightMargin"> | ||
| 728 | <number>6</number> | ||
| 729 | </property> | ||
| 730 | <property name="bottomMargin"> | ||
| 731 | <number>6</number> | ||
| 732 | </property> | ||
| 733 | <item> | ||
| 734 | <widget class="QWidget" name="player3LeftJoycon" native="true"> | ||
| 735 | <layout class="QVBoxLayout" name="buttonMiscButtonsLeftJoyconVerticalLayout_16"> | ||
| 736 | <property name="spacing"> | ||
| 737 | <number>0</number> | ||
| 738 | </property> | ||
| 739 | <property name="leftMargin"> | ||
| 740 | <number>0</number> | ||
| 741 | </property> | ||
| 742 | <property name="topMargin"> | ||
| 743 | <number>0</number> | ||
| 744 | </property> | ||
| 745 | <property name="rightMargin"> | ||
| 746 | <number>0</number> | ||
| 747 | </property> | ||
| 748 | <property name="bottomMargin"> | ||
| 749 | <number>0</number> | ||
| 750 | </property> | ||
| 751 | <item alignment="Qt::AlignHCenter"> | ||
| 752 | <widget class="QGroupBox" name="player3LeftBodyGroup"> | ||
| 753 | <property name="title"> | ||
| 754 | <string>L Body</string> | ||
| 755 | </property> | ||
| 756 | <property name="alignment"> | ||
| 757 | <set>Qt::AlignCenter</set> | ||
| 758 | </property> | ||
| 759 | <layout class="QVBoxLayout" name="verticalLayout_74"> | ||
| 760 | <property name="spacing"> | ||
| 761 | <number>3</number> | ||
| 762 | </property> | ||
| 763 | <property name="leftMargin"> | ||
| 764 | <number>3</number> | ||
| 765 | </property> | ||
| 766 | <property name="topMargin"> | ||
| 767 | <number>3</number> | ||
| 768 | </property> | ||
| 769 | <property name="rightMargin"> | ||
| 770 | <number>3</number> | ||
| 771 | </property> | ||
| 772 | <property name="bottomMargin"> | ||
| 773 | <number>3</number> | ||
| 774 | </property> | ||
| 775 | <item> | ||
| 776 | <widget class="QPushButton" name="player3_left_body_button"> | ||
| 777 | <property name="sizePolicy"> | ||
| 778 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 779 | <horstretch>0</horstretch> | ||
| 780 | <verstretch>0</verstretch> | ||
| 781 | </sizepolicy> | ||
| 782 | </property> | ||
| 783 | <property name="minimumSize"> | ||
| 784 | <size> | ||
| 785 | <width>57</width> | ||
| 786 | <height>0</height> | ||
| 787 | </size> | ||
| 788 | </property> | ||
| 789 | <property name="maximumSize"> | ||
| 790 | <size> | ||
| 791 | <width>55</width> | ||
| 792 | <height>16777215</height> | ||
| 793 | </size> | ||
| 794 | </property> | ||
| 795 | <property name="styleSheet"> | ||
| 796 | <string notr="true">min-width: 55px;</string> | ||
| 797 | </property> | ||
| 798 | <property name="text"> | ||
| 799 | <string/> | ||
| 800 | </property> | ||
| 801 | </widget> | ||
| 802 | </item> | ||
| 803 | </layout> | ||
| 804 | </widget> | ||
| 805 | </item> | ||
| 806 | <item alignment="Qt::AlignHCenter"> | ||
| 807 | <widget class="QGroupBox" name="player3LeftButtonsGroup"> | ||
| 808 | <property name="title"> | ||
| 809 | <string>L Button</string> | ||
| 810 | </property> | ||
| 811 | <property name="alignment"> | ||
| 812 | <set>Qt::AlignCenter</set> | ||
| 813 | </property> | ||
| 814 | <layout class="QVBoxLayout" name="verticalLayout_75"> | ||
| 815 | <property name="spacing"> | ||
| 816 | <number>3</number> | ||
| 817 | </property> | ||
| 818 | <property name="leftMargin"> | ||
| 819 | <number>3</number> | ||
| 820 | </property> | ||
| 821 | <property name="topMargin"> | ||
| 822 | <number>3</number> | ||
| 823 | </property> | ||
| 824 | <property name="rightMargin"> | ||
| 825 | <number>3</number> | ||
| 826 | </property> | ||
| 827 | <property name="bottomMargin"> | ||
| 828 | <number>3</number> | ||
| 829 | </property> | ||
| 830 | <item> | ||
| 831 | <widget class="QPushButton" name="player3_left_buttons_button"> | ||
| 832 | <property name="sizePolicy"> | ||
| 833 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 834 | <horstretch>0</horstretch> | ||
| 835 | <verstretch>0</verstretch> | ||
| 836 | </sizepolicy> | ||
| 837 | </property> | ||
| 838 | <property name="minimumSize"> | ||
| 839 | <size> | ||
| 840 | <width>57</width> | ||
| 841 | <height>0</height> | ||
| 842 | </size> | ||
| 843 | </property> | ||
| 844 | <property name="maximumSize"> | ||
| 845 | <size> | ||
| 846 | <width>55</width> | ||
| 847 | <height>16777215</height> | ||
| 848 | </size> | ||
| 849 | </property> | ||
| 850 | <property name="styleSheet"> | ||
| 851 | <string notr="true">min-width: 55px;</string> | ||
| 852 | </property> | ||
| 853 | <property name="text"> | ||
| 854 | <string/> | ||
| 855 | </property> | ||
| 856 | </widget> | ||
| 857 | </item> | ||
| 858 | </layout> | ||
| 859 | </widget> | ||
| 860 | </item> | ||
| 861 | </layout> | ||
| 862 | </widget> | ||
| 863 | </item> | ||
| 864 | <item> | ||
| 865 | <widget class="QWidget" name="player3RightJoycon" native="true"> | ||
| 866 | <layout class="QVBoxLayout" name="buttonMiscButtonsRightJoyconVerticalLayout_16"> | ||
| 867 | <property name="spacing"> | ||
| 868 | <number>0</number> | ||
| 869 | </property> | ||
| 870 | <property name="leftMargin"> | ||
| 871 | <number>0</number> | ||
| 872 | </property> | ||
| 873 | <property name="topMargin"> | ||
| 874 | <number>0</number> | ||
| 875 | </property> | ||
| 876 | <property name="rightMargin"> | ||
| 877 | <number>0</number> | ||
| 878 | </property> | ||
| 879 | <property name="bottomMargin"> | ||
| 880 | <number>0</number> | ||
| 881 | </property> | ||
| 882 | <item alignment="Qt::AlignHCenter"> | ||
| 883 | <widget class="QGroupBox" name="player3RightBodyGroup"> | ||
| 884 | <property name="title"> | ||
| 885 | <string>R Body</string> | ||
| 886 | </property> | ||
| 887 | <property name="alignment"> | ||
| 888 | <set>Qt::AlignCenter</set> | ||
| 889 | </property> | ||
| 890 | <layout class="QVBoxLayout" name="verticalLayout_72"> | ||
| 891 | <property name="spacing"> | ||
| 892 | <number>3</number> | ||
| 893 | </property> | ||
| 894 | <property name="leftMargin"> | ||
| 895 | <number>3</number> | ||
| 896 | </property> | ||
| 897 | <property name="topMargin"> | ||
| 898 | <number>3</number> | ||
| 899 | </property> | ||
| 900 | <property name="rightMargin"> | ||
| 901 | <number>3</number> | ||
| 902 | </property> | ||
| 903 | <property name="bottomMargin"> | ||
| 904 | <number>3</number> | ||
| 905 | </property> | ||
| 906 | <item> | ||
| 907 | <widget class="QPushButton" name="player3_right_body_button"> | ||
| 908 | <property name="sizePolicy"> | ||
| 909 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 910 | <horstretch>0</horstretch> | ||
| 911 | <verstretch>0</verstretch> | ||
| 912 | </sizepolicy> | ||
| 913 | </property> | ||
| 914 | <property name="minimumSize"> | ||
| 915 | <size> | ||
| 916 | <width>57</width> | ||
| 917 | <height>0</height> | ||
| 918 | </size> | ||
| 919 | </property> | ||
| 920 | <property name="maximumSize"> | ||
| 921 | <size> | ||
| 922 | <width>55</width> | ||
| 923 | <height>16777215</height> | ||
| 924 | </size> | ||
| 925 | </property> | ||
| 926 | <property name="styleSheet"> | ||
| 927 | <string notr="true">min-width: 55px;</string> | ||
| 928 | </property> | ||
| 929 | <property name="text"> | ||
| 930 | <string/> | ||
| 931 | </property> | ||
| 932 | </widget> | ||
| 933 | </item> | ||
| 934 | </layout> | ||
| 935 | </widget> | ||
| 936 | </item> | ||
| 937 | <item alignment="Qt::AlignHCenter"> | ||
| 938 | <widget class="QGroupBox" name="player3RightButtonsGroup"> | ||
| 939 | <property name="title"> | ||
| 940 | <string>R Button</string> | ||
| 941 | </property> | ||
| 942 | <property name="alignment"> | ||
| 943 | <set>Qt::AlignCenter</set> | ||
| 944 | </property> | ||
| 945 | <layout class="QVBoxLayout" name="verticalLayout_73"> | ||
| 946 | <property name="spacing"> | ||
| 947 | <number>3</number> | ||
| 948 | </property> | ||
| 949 | <property name="leftMargin"> | ||
| 950 | <number>3</number> | ||
| 951 | </property> | ||
| 952 | <property name="topMargin"> | ||
| 953 | <number>3</number> | ||
| 954 | </property> | ||
| 955 | <property name="rightMargin"> | ||
| 956 | <number>3</number> | ||
| 957 | </property> | ||
| 958 | <property name="bottomMargin"> | ||
| 959 | <number>3</number> | ||
| 960 | </property> | ||
| 961 | <item> | ||
| 962 | <widget class="QPushButton" name="player3_right_buttons_button"> | ||
| 963 | <property name="sizePolicy"> | ||
| 964 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 965 | <horstretch>0</horstretch> | ||
| 966 | <verstretch>0</verstretch> | ||
| 967 | </sizepolicy> | ||
| 968 | </property> | ||
| 969 | <property name="minimumSize"> | ||
| 970 | <size> | ||
| 971 | <width>57</width> | ||
| 972 | <height>0</height> | ||
| 973 | </size> | ||
| 974 | </property> | ||
| 975 | <property name="maximumSize"> | ||
| 976 | <size> | ||
| 977 | <width>55</width> | ||
| 978 | <height>16777215</height> | ||
| 979 | </size> | ||
| 980 | </property> | ||
| 981 | <property name="styleSheet"> | ||
| 982 | <string notr="true">min-width: 55px;</string> | ||
| 983 | </property> | ||
| 984 | <property name="text"> | ||
| 985 | <string/> | ||
| 986 | </property> | ||
| 987 | </widget> | ||
| 988 | </item> | ||
| 989 | </layout> | ||
| 990 | </widget> | ||
| 991 | </item> | ||
| 992 | </layout> | ||
| 993 | </widget> | ||
| 994 | </item> | ||
| 995 | </layout> | ||
| 996 | </widget> | ||
| 997 | </item> | ||
| 998 | <item> | ||
| 999 | <widget class="QGroupBox" name="player4Group"> | ||
| 1000 | <property name="title"> | ||
| 1001 | <string>Player 4</string> | ||
| 1002 | </property> | ||
| 1003 | <layout class="QHBoxLayout" name="horizontalLayout_16"> | ||
| 1004 | <property name="spacing"> | ||
| 1005 | <number>6</number> | ||
| 1006 | </property> | ||
| 1007 | <property name="leftMargin"> | ||
| 1008 | <number>6</number> | ||
| 1009 | </property> | ||
| 1010 | <property name="topMargin"> | ||
| 1011 | <number>0</number> | ||
| 1012 | </property> | ||
| 1013 | <property name="rightMargin"> | ||
| 1014 | <number>6</number> | ||
| 1015 | </property> | ||
| 1016 | <property name="bottomMargin"> | ||
| 1017 | <number>6</number> | ||
| 1018 | </property> | ||
| 1019 | <item> | ||
| 1020 | <widget class="QWidget" name="player4LeftJoycon" native="true"> | ||
| 1021 | <layout class="QVBoxLayout" name="buttonMiscButtonsLeftJoyconVerticalLayout_17"> | ||
| 1022 | <property name="spacing"> | ||
| 1023 | <number>0</number> | ||
| 1024 | </property> | ||
| 1025 | <property name="leftMargin"> | ||
| 1026 | <number>0</number> | ||
| 1027 | </property> | ||
| 1028 | <property name="topMargin"> | ||
| 1029 | <number>0</number> | ||
| 1030 | </property> | ||
| 1031 | <property name="rightMargin"> | ||
| 1032 | <number>0</number> | ||
| 1033 | </property> | ||
| 1034 | <property name="bottomMargin"> | ||
| 1035 | <number>0</number> | ||
| 1036 | </property> | ||
| 1037 | <item alignment="Qt::AlignHCenter"> | ||
| 1038 | <widget class="QGroupBox" name="player4LeftBodyGroup"> | ||
| 1039 | <property name="title"> | ||
| 1040 | <string>L Body</string> | ||
| 1041 | </property> | ||
| 1042 | <property name="alignment"> | ||
| 1043 | <set>Qt::AlignCenter</set> | ||
| 1044 | </property> | ||
| 1045 | <layout class="QVBoxLayout" name="verticalLayout_78"> | ||
| 1046 | <property name="spacing"> | ||
| 1047 | <number>3</number> | ||
| 1048 | </property> | ||
| 1049 | <property name="leftMargin"> | ||
| 1050 | <number>3</number> | ||
| 1051 | </property> | ||
| 1052 | <property name="topMargin"> | ||
| 1053 | <number>3</number> | ||
| 1054 | </property> | ||
| 1055 | <property name="rightMargin"> | ||
| 1056 | <number>3</number> | ||
| 1057 | </property> | ||
| 1058 | <property name="bottomMargin"> | ||
| 1059 | <number>3</number> | ||
| 1060 | </property> | ||
| 1061 | <item> | ||
| 1062 | <widget class="QPushButton" name="player4_left_body_button"> | ||
| 1063 | <property name="sizePolicy"> | ||
| 1064 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 1065 | <horstretch>0</horstretch> | ||
| 1066 | <verstretch>0</verstretch> | ||
| 1067 | </sizepolicy> | ||
| 1068 | </property> | ||
| 1069 | <property name="minimumSize"> | ||
| 1070 | <size> | ||
| 1071 | <width>57</width> | ||
| 1072 | <height>0</height> | ||
| 1073 | </size> | ||
| 1074 | </property> | ||
| 1075 | <property name="maximumSize"> | ||
| 1076 | <size> | ||
| 1077 | <width>55</width> | ||
| 1078 | <height>16777215</height> | ||
| 1079 | </size> | ||
| 1080 | </property> | ||
| 1081 | <property name="styleSheet"> | ||
| 1082 | <string notr="true">min-width: 55px;</string> | ||
| 1083 | </property> | ||
| 1084 | <property name="text"> | ||
| 1085 | <string/> | ||
| 1086 | </property> | ||
| 1087 | </widget> | ||
| 1088 | </item> | ||
| 1089 | </layout> | ||
| 1090 | </widget> | ||
| 1091 | </item> | ||
| 1092 | <item alignment="Qt::AlignHCenter"> | ||
| 1093 | <widget class="QGroupBox" name="player4LeftButtonsGroup"> | ||
| 1094 | <property name="title"> | ||
| 1095 | <string>L Button</string> | ||
| 1096 | </property> | ||
| 1097 | <property name="alignment"> | ||
| 1098 | <set>Qt::AlignCenter</set> | ||
| 1099 | </property> | ||
| 1100 | <layout class="QVBoxLayout" name="verticalLayout_79"> | ||
| 1101 | <property name="spacing"> | ||
| 1102 | <number>3</number> | ||
| 1103 | </property> | ||
| 1104 | <property name="leftMargin"> | ||
| 1105 | <number>3</number> | ||
| 1106 | </property> | ||
| 1107 | <property name="topMargin"> | ||
| 1108 | <number>3</number> | ||
| 1109 | </property> | ||
| 1110 | <property name="rightMargin"> | ||
| 1111 | <number>3</number> | ||
| 1112 | </property> | ||
| 1113 | <property name="bottomMargin"> | ||
| 1114 | <number>3</number> | ||
| 1115 | </property> | ||
| 1116 | <item> | ||
| 1117 | <widget class="QPushButton" name="player4_left_buttons_button"> | ||
| 1118 | <property name="sizePolicy"> | ||
| 1119 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 1120 | <horstretch>0</horstretch> | ||
| 1121 | <verstretch>0</verstretch> | ||
| 1122 | </sizepolicy> | ||
| 1123 | </property> | ||
| 1124 | <property name="minimumSize"> | ||
| 1125 | <size> | ||
| 1126 | <width>57</width> | ||
| 1127 | <height>0</height> | ||
| 1128 | </size> | ||
| 1129 | </property> | ||
| 1130 | <property name="maximumSize"> | ||
| 1131 | <size> | ||
| 1132 | <width>55</width> | ||
| 1133 | <height>16777215</height> | ||
| 1134 | </size> | ||
| 1135 | </property> | ||
| 1136 | <property name="styleSheet"> | ||
| 1137 | <string notr="true">min-width: 55px;</string> | ||
| 1138 | </property> | ||
| 1139 | <property name="text"> | ||
| 1140 | <string/> | ||
| 1141 | </property> | ||
| 1142 | </widget> | ||
| 1143 | </item> | ||
| 1144 | </layout> | ||
| 1145 | </widget> | ||
| 1146 | </item> | ||
| 1147 | </layout> | ||
| 1148 | </widget> | ||
| 1149 | </item> | ||
| 1150 | <item> | ||
| 1151 | <widget class="QWidget" name="player4RightJoycon" native="true"> | ||
| 1152 | <layout class="QVBoxLayout" name="buttonMiscButtonsRightJoyconVerticalLayout_17"> | ||
| 1153 | <property name="spacing"> | ||
| 1154 | <number>0</number> | ||
| 1155 | </property> | ||
| 1156 | <property name="leftMargin"> | ||
| 1157 | <number>0</number> | ||
| 1158 | </property> | ||
| 1159 | <property name="topMargin"> | ||
| 1160 | <number>0</number> | ||
| 1161 | </property> | ||
| 1162 | <property name="rightMargin"> | ||
| 1163 | <number>0</number> | ||
| 1164 | </property> | ||
| 1165 | <property name="bottomMargin"> | ||
| 1166 | <number>0</number> | ||
| 1167 | </property> | ||
| 1168 | <item alignment="Qt::AlignHCenter"> | ||
| 1169 | <widget class="QGroupBox" name="player4RightBodyGroup"> | ||
| 1170 | <property name="title"> | ||
| 1171 | <string>R Body</string> | ||
| 1172 | </property> | ||
| 1173 | <property name="alignment"> | ||
| 1174 | <set>Qt::AlignCenter</set> | ||
| 1175 | </property> | ||
| 1176 | <layout class="QVBoxLayout" name="verticalLayout_76"> | ||
| 1177 | <property name="spacing"> | ||
| 1178 | <number>3</number> | ||
| 1179 | </property> | ||
| 1180 | <property name="leftMargin"> | ||
| 1181 | <number>3</number> | ||
| 1182 | </property> | ||
| 1183 | <property name="topMargin"> | ||
| 1184 | <number>3</number> | ||
| 1185 | </property> | ||
| 1186 | <property name="rightMargin"> | ||
| 1187 | <number>3</number> | ||
| 1188 | </property> | ||
| 1189 | <property name="bottomMargin"> | ||
| 1190 | <number>3</number> | ||
| 1191 | </property> | ||
| 1192 | <item> | ||
| 1193 | <widget class="QPushButton" name="player4_right_body_button"> | ||
| 1194 | <property name="sizePolicy"> | ||
| 1195 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 1196 | <horstretch>0</horstretch> | ||
| 1197 | <verstretch>0</verstretch> | ||
| 1198 | </sizepolicy> | ||
| 1199 | </property> | ||
| 1200 | <property name="minimumSize"> | ||
| 1201 | <size> | ||
| 1202 | <width>57</width> | ||
| 1203 | <height>0</height> | ||
| 1204 | </size> | ||
| 1205 | </property> | ||
| 1206 | <property name="maximumSize"> | ||
| 1207 | <size> | ||
| 1208 | <width>55</width> | ||
| 1209 | <height>16777215</height> | ||
| 1210 | </size> | ||
| 1211 | </property> | ||
| 1212 | <property name="styleSheet"> | ||
| 1213 | <string notr="true">min-width: 55px;</string> | ||
| 1214 | </property> | ||
| 1215 | <property name="text"> | ||
| 1216 | <string/> | ||
| 1217 | </property> | ||
| 1218 | </widget> | ||
| 1219 | </item> | ||
| 1220 | </layout> | ||
| 1221 | </widget> | ||
| 1222 | </item> | ||
| 1223 | <item alignment="Qt::AlignHCenter"> | ||
| 1224 | <widget class="QGroupBox" name="player4RightButtonsGroup"> | ||
| 1225 | <property name="title"> | ||
| 1226 | <string>R Button</string> | ||
| 1227 | </property> | ||
| 1228 | <property name="alignment"> | ||
| 1229 | <set>Qt::AlignCenter</set> | ||
| 1230 | </property> | ||
| 1231 | <layout class="QVBoxLayout" name="verticalLayout_77"> | ||
| 1232 | <property name="spacing"> | ||
| 1233 | <number>3</number> | ||
| 1234 | </property> | ||
| 1235 | <property name="leftMargin"> | ||
| 1236 | <number>3</number> | ||
| 1237 | </property> | ||
| 1238 | <property name="topMargin"> | ||
| 1239 | <number>3</number> | ||
| 1240 | </property> | ||
| 1241 | <property name="rightMargin"> | ||
| 1242 | <number>3</number> | ||
| 1243 | </property> | ||
| 1244 | <property name="bottomMargin"> | ||
| 1245 | <number>3</number> | ||
| 1246 | </property> | ||
| 1247 | <item> | ||
| 1248 | <widget class="QPushButton" name="player4_right_buttons_button"> | ||
| 1249 | <property name="sizePolicy"> | ||
| 1250 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 1251 | <horstretch>0</horstretch> | ||
| 1252 | <verstretch>0</verstretch> | ||
| 1253 | </sizepolicy> | ||
| 1254 | </property> | ||
| 1255 | <property name="minimumSize"> | ||
| 1256 | <size> | ||
| 1257 | <width>57</width> | ||
| 1258 | <height>0</height> | ||
| 1259 | </size> | ||
| 1260 | </property> | ||
| 1261 | <property name="maximumSize"> | ||
| 1262 | <size> | ||
| 1263 | <width>55</width> | ||
| 1264 | <height>16777215</height> | ||
| 1265 | </size> | ||
| 1266 | </property> | ||
| 1267 | <property name="styleSheet"> | ||
| 1268 | <string notr="true">min-width: 55px;</string> | ||
| 1269 | </property> | ||
| 1270 | <property name="text"> | ||
| 1271 | <string/> | ||
| 1272 | </property> | ||
| 1273 | </widget> | ||
| 1274 | </item> | ||
| 1275 | </layout> | ||
| 1276 | </widget> | ||
| 1277 | </item> | ||
| 1278 | </layout> | ||
| 1279 | </widget> | ||
| 1280 | </item> | ||
| 1281 | </layout> | ||
| 1282 | </widget> | ||
| 1283 | </item> | ||
| 1284 | </layout> | ||
| 1285 | </widget> | ||
| 1286 | </item> | ||
| 1287 | </layout> | ||
| 1288 | </widget> | ||
| 1289 | </item> | ||
| 1290 | <item> | ||
| 1291 | <widget class="QWidget" name="bottomLeftInputAdvanced" native="true"> | ||
| 1292 | <layout class="QVBoxLayout" name="verticalLayout_5"> | ||
| 1293 | <property name="spacing"> | ||
| 1294 | <number>6</number> | ||
| 1295 | </property> | ||
| 1296 | <property name="leftMargin"> | ||
| 1297 | <number>0</number> | ||
| 1298 | </property> | ||
| 1299 | <property name="topMargin"> | ||
| 1300 | <number>0</number> | ||
| 1301 | </property> | ||
| 1302 | <property name="rightMargin"> | ||
| 1303 | <number>0</number> | ||
| 1304 | </property> | ||
| 1305 | <property name="bottomMargin"> | ||
| 1306 | <number>0</number> | ||
| 1307 | </property> | ||
| 1308 | <item> | ||
| 1309 | <widget class="QWidget" name="player56Widget" native="true"> | ||
| 1310 | <layout class="QHBoxLayout" name="horizontalLayout_6"> | ||
| 1311 | <property name="leftMargin"> | ||
| 1312 | <number>0</number> | ||
| 1313 | </property> | ||
| 1314 | <property name="topMargin"> | ||
| 1315 | <number>0</number> | ||
| 1316 | </property> | ||
| 1317 | <property name="rightMargin"> | ||
| 1318 | <number>0</number> | ||
| 1319 | </property> | ||
| 1320 | <property name="bottomMargin"> | ||
| 1321 | <number>0</number> | ||
| 1322 | </property> | ||
| 1323 | <item> | ||
| 1324 | <widget class="QGroupBox" name="player5Group"> | ||
| 1325 | <property name="title"> | ||
| 1326 | <string>Player 5</string> | ||
| 1327 | </property> | ||
| 1328 | <layout class="QHBoxLayout" name="horizontalLayout_10"> | ||
| 1329 | <property name="spacing"> | ||
| 1330 | <number>6</number> | ||
| 1331 | </property> | ||
| 1332 | <property name="leftMargin"> | ||
| 1333 | <number>6</number> | ||
| 1334 | </property> | ||
| 1335 | <property name="topMargin"> | ||
| 1336 | <number>0</number> | ||
| 1337 | </property> | ||
| 1338 | <property name="rightMargin"> | ||
| 1339 | <number>6</number> | ||
| 1340 | </property> | ||
| 1341 | <property name="bottomMargin"> | ||
| 1342 | <number>6</number> | ||
| 1343 | </property> | ||
| 1344 | <item> | ||
| 1345 | <widget class="QWidget" name="player5LeftJoycon" native="true"> | ||
| 1346 | <layout class="QVBoxLayout" name="buttonMiscButtonsLeftJoyconVerticalLayout_10"> | ||
| 1347 | <property name="spacing"> | ||
| 1348 | <number>0</number> | ||
| 1349 | </property> | ||
| 1350 | <property name="leftMargin"> | ||
| 1351 | <number>0</number> | ||
| 1352 | </property> | ||
| 1353 | <property name="topMargin"> | ||
| 1354 | <number>0</number> | ||
| 1355 | </property> | ||
| 1356 | <property name="rightMargin"> | ||
| 1357 | <number>0</number> | ||
| 1358 | </property> | ||
| 1359 | <property name="bottomMargin"> | ||
| 1360 | <number>0</number> | ||
| 1361 | </property> | ||
| 1362 | <item alignment="Qt::AlignHCenter"> | ||
| 1363 | <widget class="QGroupBox" name="player5LeftBodyGroup"> | ||
| 1364 | <property name="title"> | ||
| 1365 | <string>L Body</string> | ||
| 1366 | </property> | ||
| 1367 | <property name="alignment"> | ||
| 1368 | <set>Qt::AlignCenter</set> | ||
| 1369 | </property> | ||
| 1370 | <layout class="QVBoxLayout" name="verticalLayout_50"> | ||
| 1371 | <property name="spacing"> | ||
| 1372 | <number>3</number> | ||
| 1373 | </property> | ||
| 1374 | <property name="leftMargin"> | ||
| 1375 | <number>3</number> | ||
| 1376 | </property> | ||
| 1377 | <property name="topMargin"> | ||
| 1378 | <number>3</number> | ||
| 1379 | </property> | ||
| 1380 | <property name="rightMargin"> | ||
| 1381 | <number>3</number> | ||
| 1382 | </property> | ||
| 1383 | <property name="bottomMargin"> | ||
| 1384 | <number>3</number> | ||
| 1385 | </property> | ||
| 1386 | <item> | ||
| 1387 | <widget class="QPushButton" name="player5_left_body_button"> | ||
| 1388 | <property name="sizePolicy"> | ||
| 1389 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 1390 | <horstretch>0</horstretch> | ||
| 1391 | <verstretch>0</verstretch> | ||
| 1392 | </sizepolicy> | ||
| 1393 | </property> | ||
| 1394 | <property name="minimumSize"> | ||
| 1395 | <size> | ||
| 1396 | <width>57</width> | ||
| 1397 | <height>0</height> | ||
| 1398 | </size> | ||
| 1399 | </property> | ||
| 1400 | <property name="maximumSize"> | ||
| 1401 | <size> | ||
| 1402 | <width>55</width> | ||
| 1403 | <height>16777215</height> | ||
| 1404 | </size> | ||
| 1405 | </property> | ||
| 1406 | <property name="styleSheet"> | ||
| 1407 | <string notr="true">min-width: 55px;</string> | ||
| 1408 | </property> | ||
| 1409 | <property name="text"> | ||
| 1410 | <string/> | ||
| 1411 | </property> | ||
| 1412 | </widget> | ||
| 1413 | </item> | ||
| 1414 | </layout> | ||
| 1415 | </widget> | ||
| 1416 | </item> | ||
| 1417 | <item alignment="Qt::AlignHCenter"> | ||
| 1418 | <widget class="QGroupBox" name="player5LeftButtonsGroup"> | ||
| 1419 | <property name="title"> | ||
| 1420 | <string>L Button</string> | ||
| 1421 | </property> | ||
| 1422 | <property name="alignment"> | ||
| 1423 | <set>Qt::AlignCenter</set> | ||
| 1424 | </property> | ||
| 1425 | <layout class="QVBoxLayout" name="verticalLayout_51"> | ||
| 1426 | <property name="spacing"> | ||
| 1427 | <number>3</number> | ||
| 1428 | </property> | ||
| 1429 | <property name="leftMargin"> | ||
| 1430 | <number>3</number> | ||
| 1431 | </property> | ||
| 1432 | <property name="topMargin"> | ||
| 1433 | <number>3</number> | ||
| 1434 | </property> | ||
| 1435 | <property name="rightMargin"> | ||
| 1436 | <number>3</number> | ||
| 1437 | </property> | ||
| 1438 | <property name="bottomMargin"> | ||
| 1439 | <number>3</number> | ||
| 1440 | </property> | ||
| 1441 | <item> | ||
| 1442 | <widget class="QPushButton" name="player5_left_buttons_button"> | ||
| 1443 | <property name="sizePolicy"> | ||
| 1444 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 1445 | <horstretch>0</horstretch> | ||
| 1446 | <verstretch>0</verstretch> | ||
| 1447 | </sizepolicy> | ||
| 1448 | </property> | ||
| 1449 | <property name="minimumSize"> | ||
| 1450 | <size> | ||
| 1451 | <width>57</width> | ||
| 1452 | <height>0</height> | ||
| 1453 | </size> | ||
| 1454 | </property> | ||
| 1455 | <property name="maximumSize"> | ||
| 1456 | <size> | ||
| 1457 | <width>55</width> | ||
| 1458 | <height>16777215</height> | ||
| 1459 | </size> | ||
| 1460 | </property> | ||
| 1461 | <property name="styleSheet"> | ||
| 1462 | <string notr="true">min-width: 55px;</string> | ||
| 1463 | </property> | ||
| 1464 | <property name="text"> | ||
| 1465 | <string/> | ||
| 1466 | </property> | ||
| 1467 | </widget> | ||
| 1468 | </item> | ||
| 1469 | </layout> | ||
| 1470 | </widget> | ||
| 1471 | </item> | ||
| 1472 | </layout> | ||
| 1473 | </widget> | ||
| 1474 | </item> | ||
| 1475 | <item> | ||
| 1476 | <widget class="QWidget" name="player5RightJoycon" native="true"> | ||
| 1477 | <layout class="QVBoxLayout" name="buttonMiscButtonsRightJoyconVerticalLayout_10"> | ||
| 1478 | <property name="spacing"> | ||
| 1479 | <number>0</number> | ||
| 1480 | </property> | ||
| 1481 | <property name="leftMargin"> | ||
| 1482 | <number>0</number> | ||
| 1483 | </property> | ||
| 1484 | <property name="topMargin"> | ||
| 1485 | <number>0</number> | ||
| 1486 | </property> | ||
| 1487 | <property name="rightMargin"> | ||
| 1488 | <number>0</number> | ||
| 1489 | </property> | ||
| 1490 | <property name="bottomMargin"> | ||
| 1491 | <number>0</number> | ||
| 1492 | </property> | ||
| 1493 | <item alignment="Qt::AlignHCenter"> | ||
| 1494 | <widget class="QGroupBox" name="player5RightBodyGroup"> | ||
| 1495 | <property name="title"> | ||
| 1496 | <string>R Body</string> | ||
| 1497 | </property> | ||
| 1498 | <property name="alignment"> | ||
| 1499 | <set>Qt::AlignCenter</set> | ||
| 1500 | </property> | ||
| 1501 | <layout class="QVBoxLayout" name="verticalLayout_48"> | ||
| 1502 | <property name="spacing"> | ||
| 1503 | <number>3</number> | ||
| 1504 | </property> | ||
| 1505 | <property name="leftMargin"> | ||
| 1506 | <number>3</number> | ||
| 1507 | </property> | ||
| 1508 | <property name="topMargin"> | ||
| 1509 | <number>3</number> | ||
| 1510 | </property> | ||
| 1511 | <property name="rightMargin"> | ||
| 1512 | <number>3</number> | ||
| 1513 | </property> | ||
| 1514 | <property name="bottomMargin"> | ||
| 1515 | <number>3</number> | ||
| 1516 | </property> | ||
| 1517 | <item> | ||
| 1518 | <widget class="QPushButton" name="player5_right_body_button"> | ||
| 1519 | <property name="sizePolicy"> | ||
| 1520 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 1521 | <horstretch>0</horstretch> | ||
| 1522 | <verstretch>0</verstretch> | ||
| 1523 | </sizepolicy> | ||
| 1524 | </property> | ||
| 1525 | <property name="minimumSize"> | ||
| 1526 | <size> | ||
| 1527 | <width>57</width> | ||
| 1528 | <height>0</height> | ||
| 1529 | </size> | ||
| 1530 | </property> | ||
| 1531 | <property name="maximumSize"> | ||
| 1532 | <size> | ||
| 1533 | <width>55</width> | ||
| 1534 | <height>16777215</height> | ||
| 1535 | </size> | ||
| 1536 | </property> | ||
| 1537 | <property name="styleSheet"> | ||
| 1538 | <string notr="true">min-width: 55px;</string> | ||
| 1539 | </property> | ||
| 1540 | <property name="text"> | ||
| 1541 | <string/> | ||
| 1542 | </property> | ||
| 1543 | </widget> | ||
| 1544 | </item> | ||
| 1545 | </layout> | ||
| 1546 | </widget> | ||
| 1547 | </item> | ||
| 1548 | <item alignment="Qt::AlignHCenter"> | ||
| 1549 | <widget class="QGroupBox" name="player5RightButtonsGroup"> | ||
| 1550 | <property name="title"> | ||
| 1551 | <string>R Button</string> | ||
| 1552 | </property> | ||
| 1553 | <property name="alignment"> | ||
| 1554 | <set>Qt::AlignCenter</set> | ||
| 1555 | </property> | ||
| 1556 | <layout class="QVBoxLayout" name="verticalLayout_49"> | ||
| 1557 | <property name="spacing"> | ||
| 1558 | <number>3</number> | ||
| 1559 | </property> | ||
| 1560 | <property name="leftMargin"> | ||
| 1561 | <number>3</number> | ||
| 1562 | </property> | ||
| 1563 | <property name="topMargin"> | ||
| 1564 | <number>3</number> | ||
| 1565 | </property> | ||
| 1566 | <property name="rightMargin"> | ||
| 1567 | <number>3</number> | ||
| 1568 | </property> | ||
| 1569 | <property name="bottomMargin"> | ||
| 1570 | <number>3</number> | ||
| 1571 | </property> | ||
| 1572 | <item> | ||
| 1573 | <widget class="QPushButton" name="player5_right_buttons_button"> | ||
| 1574 | <property name="sizePolicy"> | ||
| 1575 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 1576 | <horstretch>0</horstretch> | ||
| 1577 | <verstretch>0</verstretch> | ||
| 1578 | </sizepolicy> | ||
| 1579 | </property> | ||
| 1580 | <property name="minimumSize"> | ||
| 1581 | <size> | ||
| 1582 | <width>57</width> | ||
| 1583 | <height>0</height> | ||
| 1584 | </size> | ||
| 1585 | </property> | ||
| 1586 | <property name="maximumSize"> | ||
| 1587 | <size> | ||
| 1588 | <width>55</width> | ||
| 1589 | <height>16777215</height> | ||
| 1590 | </size> | ||
| 1591 | </property> | ||
| 1592 | <property name="styleSheet"> | ||
| 1593 | <string notr="true">min-width: 55px;</string> | ||
| 1594 | </property> | ||
| 1595 | <property name="text"> | ||
| 1596 | <string/> | ||
| 1597 | </property> | ||
| 1598 | </widget> | ||
| 1599 | </item> | ||
| 1600 | </layout> | ||
| 1601 | </widget> | ||
| 1602 | </item> | ||
| 1603 | </layout> | ||
| 1604 | </widget> | ||
| 1605 | </item> | ||
| 1606 | </layout> | ||
| 1607 | </widget> | ||
| 1608 | </item> | ||
| 1609 | <item> | ||
| 1610 | <widget class="QGroupBox" name="player6Group"> | ||
| 1611 | <property name="title"> | ||
| 1612 | <string>Player 6</string> | ||
| 1613 | </property> | ||
| 1614 | <layout class="QHBoxLayout" name="horizontalLayout_11"> | ||
| 1615 | <property name="spacing"> | ||
| 1616 | <number>6</number> | ||
| 1617 | </property> | ||
| 1618 | <property name="leftMargin"> | ||
| 1619 | <number>6</number> | ||
| 1620 | </property> | ||
| 1621 | <property name="topMargin"> | ||
| 1622 | <number>0</number> | ||
| 1623 | </property> | ||
| 1624 | <property name="rightMargin"> | ||
| 1625 | <number>6</number> | ||
| 1626 | </property> | ||
| 1627 | <property name="bottomMargin"> | ||
| 1628 | <number>6</number> | ||
| 1629 | </property> | ||
| 1630 | <item> | ||
| 1631 | <widget class="QWidget" name="player6LeftJoycon" native="true"> | ||
| 1632 | <layout class="QVBoxLayout" name="buttonMiscButtonsLeftJoyconVerticalLayout_11"> | ||
| 1633 | <property name="spacing"> | ||
| 1634 | <number>0</number> | ||
| 1635 | </property> | ||
| 1636 | <property name="leftMargin"> | ||
| 1637 | <number>0</number> | ||
| 1638 | </property> | ||
| 1639 | <property name="topMargin"> | ||
| 1640 | <number>0</number> | ||
| 1641 | </property> | ||
| 1642 | <property name="rightMargin"> | ||
| 1643 | <number>0</number> | ||
| 1644 | </property> | ||
| 1645 | <property name="bottomMargin"> | ||
| 1646 | <number>0</number> | ||
| 1647 | </property> | ||
| 1648 | <item alignment="Qt::AlignHCenter"> | ||
| 1649 | <widget class="QGroupBox" name="player6LeftBodyGroup"> | ||
| 1650 | <property name="title"> | ||
| 1651 | <string>L Body</string> | ||
| 1652 | </property> | ||
| 1653 | <property name="alignment"> | ||
| 1654 | <set>Qt::AlignCenter</set> | ||
| 1655 | </property> | ||
| 1656 | <layout class="QVBoxLayout" name="verticalLayout_54"> | ||
| 1657 | <property name="spacing"> | ||
| 1658 | <number>3</number> | ||
| 1659 | </property> | ||
| 1660 | <property name="leftMargin"> | ||
| 1661 | <number>3</number> | ||
| 1662 | </property> | ||
| 1663 | <property name="topMargin"> | ||
| 1664 | <number>3</number> | ||
| 1665 | </property> | ||
| 1666 | <property name="rightMargin"> | ||
| 1667 | <number>3</number> | ||
| 1668 | </property> | ||
| 1669 | <property name="bottomMargin"> | ||
| 1670 | <number>3</number> | ||
| 1671 | </property> | ||
| 1672 | <item> | ||
| 1673 | <widget class="QPushButton" name="player6_left_body_button"> | ||
| 1674 | <property name="sizePolicy"> | ||
| 1675 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 1676 | <horstretch>0</horstretch> | ||
| 1677 | <verstretch>0</verstretch> | ||
| 1678 | </sizepolicy> | ||
| 1679 | </property> | ||
| 1680 | <property name="minimumSize"> | ||
| 1681 | <size> | ||
| 1682 | <width>57</width> | ||
| 1683 | <height>0</height> | ||
| 1684 | </size> | ||
| 1685 | </property> | ||
| 1686 | <property name="maximumSize"> | ||
| 1687 | <size> | ||
| 1688 | <width>55</width> | ||
| 1689 | <height>16777215</height> | ||
| 1690 | </size> | ||
| 1691 | </property> | ||
| 1692 | <property name="styleSheet"> | ||
| 1693 | <string notr="true">min-width: 55px;</string> | ||
| 1694 | </property> | ||
| 1695 | <property name="text"> | ||
| 1696 | <string/> | ||
| 1697 | </property> | ||
| 1698 | </widget> | ||
| 1699 | </item> | ||
| 1700 | </layout> | ||
| 1701 | </widget> | ||
| 1702 | </item> | ||
| 1703 | <item alignment="Qt::AlignHCenter"> | ||
| 1704 | <widget class="QGroupBox" name="player6LeftButtonsGroup"> | ||
| 1705 | <property name="title"> | ||
| 1706 | <string>L Button</string> | ||
| 1707 | </property> | ||
| 1708 | <property name="alignment"> | ||
| 1709 | <set>Qt::AlignCenter</set> | ||
| 1710 | </property> | ||
| 1711 | <layout class="QVBoxLayout" name="verticalLayout_55"> | ||
| 1712 | <property name="spacing"> | ||
| 1713 | <number>3</number> | ||
| 1714 | </property> | ||
| 1715 | <property name="leftMargin"> | ||
| 1716 | <number>3</number> | ||
| 1717 | </property> | ||
| 1718 | <property name="topMargin"> | ||
| 1719 | <number>3</number> | ||
| 1720 | </property> | ||
| 1721 | <property name="rightMargin"> | ||
| 1722 | <number>3</number> | ||
| 1723 | </property> | ||
| 1724 | <property name="bottomMargin"> | ||
| 1725 | <number>3</number> | ||
| 1726 | </property> | ||
| 1727 | <item> | ||
| 1728 | <widget class="QPushButton" name="player6_left_buttons_button"> | ||
| 1729 | <property name="sizePolicy"> | ||
| 1730 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 1731 | <horstretch>0</horstretch> | ||
| 1732 | <verstretch>0</verstretch> | ||
| 1733 | </sizepolicy> | ||
| 1734 | </property> | ||
| 1735 | <property name="minimumSize"> | ||
| 1736 | <size> | ||
| 1737 | <width>57</width> | ||
| 1738 | <height>0</height> | ||
| 1739 | </size> | ||
| 1740 | </property> | ||
| 1741 | <property name="maximumSize"> | ||
| 1742 | <size> | ||
| 1743 | <width>55</width> | ||
| 1744 | <height>16777215</height> | ||
| 1745 | </size> | ||
| 1746 | </property> | ||
| 1747 | <property name="styleSheet"> | ||
| 1748 | <string notr="true">min-width: 55px;</string> | ||
| 1749 | </property> | ||
| 1750 | <property name="text"> | ||
| 1751 | <string/> | ||
| 1752 | </property> | ||
| 1753 | </widget> | ||
| 1754 | </item> | ||
| 1755 | </layout> | ||
| 1756 | </widget> | ||
| 1757 | </item> | ||
| 1758 | </layout> | ||
| 1759 | </widget> | ||
| 1760 | </item> | ||
| 1761 | <item> | ||
| 1762 | <widget class="QWidget" name="player6RightJoycon" native="true"> | ||
| 1763 | <layout class="QVBoxLayout" name="buttonMiscButtonsRightJoyconVerticalLayout_11"> | ||
| 1764 | <property name="spacing"> | ||
| 1765 | <number>0</number> | ||
| 1766 | </property> | ||
| 1767 | <property name="leftMargin"> | ||
| 1768 | <number>0</number> | ||
| 1769 | </property> | ||
| 1770 | <property name="topMargin"> | ||
| 1771 | <number>0</number> | ||
| 1772 | </property> | ||
| 1773 | <property name="rightMargin"> | ||
| 1774 | <number>0</number> | ||
| 1775 | </property> | ||
| 1776 | <property name="bottomMargin"> | ||
| 1777 | <number>0</number> | ||
| 1778 | </property> | ||
| 1779 | <item alignment="Qt::AlignHCenter"> | ||
| 1780 | <widget class="QGroupBox" name="player6RightBodyGroup"> | ||
| 1781 | <property name="title"> | ||
| 1782 | <string>R Body</string> | ||
| 1783 | </property> | ||
| 1784 | <property name="alignment"> | ||
| 1785 | <set>Qt::AlignCenter</set> | ||
| 1786 | </property> | ||
| 1787 | <layout class="QVBoxLayout" name="verticalLayout_52"> | ||
| 1788 | <property name="spacing"> | ||
| 1789 | <number>3</number> | ||
| 1790 | </property> | ||
| 1791 | <property name="leftMargin"> | ||
| 1792 | <number>3</number> | ||
| 1793 | </property> | ||
| 1794 | <property name="topMargin"> | ||
| 1795 | <number>3</number> | ||
| 1796 | </property> | ||
| 1797 | <property name="rightMargin"> | ||
| 1798 | <number>3</number> | ||
| 1799 | </property> | ||
| 1800 | <property name="bottomMargin"> | ||
| 1801 | <number>3</number> | ||
| 1802 | </property> | ||
| 1803 | <item> | ||
| 1804 | <widget class="QPushButton" name="player6_right_body_button"> | ||
| 1805 | <property name="sizePolicy"> | ||
| 1806 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 1807 | <horstretch>0</horstretch> | ||
| 1808 | <verstretch>0</verstretch> | ||
| 1809 | </sizepolicy> | ||
| 1810 | </property> | ||
| 1811 | <property name="minimumSize"> | ||
| 1812 | <size> | ||
| 1813 | <width>57</width> | ||
| 1814 | <height>0</height> | ||
| 1815 | </size> | ||
| 1816 | </property> | ||
| 1817 | <property name="maximumSize"> | ||
| 1818 | <size> | ||
| 1819 | <width>55</width> | ||
| 1820 | <height>16777215</height> | ||
| 1821 | </size> | ||
| 1822 | </property> | ||
| 1823 | <property name="styleSheet"> | ||
| 1824 | <string notr="true">min-width: 55px;</string> | ||
| 1825 | </property> | ||
| 1826 | <property name="text"> | ||
| 1827 | <string/> | ||
| 1828 | </property> | ||
| 1829 | </widget> | ||
| 1830 | </item> | ||
| 1831 | </layout> | ||
| 1832 | </widget> | ||
| 1833 | </item> | ||
| 1834 | <item alignment="Qt::AlignHCenter"> | ||
| 1835 | <widget class="QGroupBox" name="player6RightButtonsGroup"> | ||
| 1836 | <property name="title"> | ||
| 1837 | <string>R Button</string> | ||
| 1838 | </property> | ||
| 1839 | <property name="alignment"> | ||
| 1840 | <set>Qt::AlignCenter</set> | ||
| 1841 | </property> | ||
| 1842 | <layout class="QVBoxLayout" name="verticalLayout_53"> | ||
| 1843 | <property name="spacing"> | ||
| 1844 | <number>3</number> | ||
| 1845 | </property> | ||
| 1846 | <property name="leftMargin"> | ||
| 1847 | <number>3</number> | ||
| 1848 | </property> | ||
| 1849 | <property name="topMargin"> | ||
| 1850 | <number>3</number> | ||
| 1851 | </property> | ||
| 1852 | <property name="rightMargin"> | ||
| 1853 | <number>3</number> | ||
| 1854 | </property> | ||
| 1855 | <property name="bottomMargin"> | ||
| 1856 | <number>3</number> | ||
| 1857 | </property> | ||
| 1858 | <item> | ||
| 1859 | <widget class="QPushButton" name="player6_right_buttons_button"> | ||
| 1860 | <property name="sizePolicy"> | ||
| 1861 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 1862 | <horstretch>0</horstretch> | ||
| 1863 | <verstretch>0</verstretch> | ||
| 1864 | </sizepolicy> | ||
| 1865 | </property> | ||
| 1866 | <property name="minimumSize"> | ||
| 1867 | <size> | ||
| 1868 | <width>57</width> | ||
| 1869 | <height>0</height> | ||
| 1870 | </size> | ||
| 1871 | </property> | ||
| 1872 | <property name="maximumSize"> | ||
| 1873 | <size> | ||
| 1874 | <width>55</width> | ||
| 1875 | <height>16777215</height> | ||
| 1876 | </size> | ||
| 1877 | </property> | ||
| 1878 | <property name="styleSheet"> | ||
| 1879 | <string notr="true">min-width: 55px;</string> | ||
| 1880 | </property> | ||
| 1881 | <property name="text"> | ||
| 1882 | <string/> | ||
| 1883 | </property> | ||
| 1884 | </widget> | ||
| 1885 | </item> | ||
| 1886 | </layout> | ||
| 1887 | </widget> | ||
| 1888 | </item> | ||
| 1889 | </layout> | ||
| 1890 | </widget> | ||
| 1891 | </item> | ||
| 1892 | </layout> | ||
| 1893 | </widget> | ||
| 1894 | </item> | ||
| 1895 | </layout> | ||
| 1896 | </widget> | ||
| 1897 | </item> | ||
| 1898 | <item> | ||
| 1899 | <widget class="QWidget" name="player78Widget" native="true"> | ||
| 1900 | <layout class="QHBoxLayout" name="horizontalLayout_7"> | ||
| 1901 | <property name="leftMargin"> | ||
| 1902 | <number>0</number> | ||
| 1903 | </property> | ||
| 1904 | <property name="topMargin"> | ||
| 1905 | <number>0</number> | ||
| 1906 | </property> | ||
| 1907 | <property name="rightMargin"> | ||
| 1908 | <number>0</number> | ||
| 1909 | </property> | ||
| 1910 | <property name="bottomMargin"> | ||
| 1911 | <number>0</number> | ||
| 1912 | </property> | ||
| 1913 | <item> | ||
| 1914 | <widget class="QGroupBox" name="player7Group"> | ||
| 1915 | <property name="title"> | ||
| 1916 | <string>Player 7</string> | ||
| 1917 | </property> | ||
| 1918 | <layout class="QHBoxLayout" name="horizontalLayout_12"> | ||
| 1919 | <property name="spacing"> | ||
| 1920 | <number>6</number> | ||
| 1921 | </property> | ||
| 1922 | <property name="leftMargin"> | ||
| 1923 | <number>6</number> | ||
| 1924 | </property> | ||
| 1925 | <property name="topMargin"> | ||
| 1926 | <number>0</number> | ||
| 1927 | </property> | ||
| 1928 | <property name="rightMargin"> | ||
| 1929 | <number>6</number> | ||
| 1930 | </property> | ||
| 1931 | <property name="bottomMargin"> | ||
| 1932 | <number>6</number> | ||
| 1933 | </property> | ||
| 1934 | <item> | ||
| 1935 | <widget class="QWidget" name="player7LeftJoycon" native="true"> | ||
| 1936 | <layout class="QVBoxLayout" name="buttonMiscButtonsLeftJoyconVerticalLayout_12"> | ||
| 1937 | <property name="spacing"> | ||
| 1938 | <number>0</number> | ||
| 1939 | </property> | ||
| 1940 | <property name="leftMargin"> | ||
| 1941 | <number>0</number> | ||
| 1942 | </property> | ||
| 1943 | <property name="topMargin"> | ||
| 1944 | <number>0</number> | ||
| 1945 | </property> | ||
| 1946 | <property name="rightMargin"> | ||
| 1947 | <number>0</number> | ||
| 1948 | </property> | ||
| 1949 | <property name="bottomMargin"> | ||
| 1950 | <number>0</number> | ||
| 1951 | </property> | ||
| 1952 | <item alignment="Qt::AlignHCenter"> | ||
| 1953 | <widget class="QGroupBox" name="player7LeftBodyGroup"> | ||
| 1954 | <property name="title"> | ||
| 1955 | <string>L Body</string> | ||
| 1956 | </property> | ||
| 1957 | <property name="alignment"> | ||
| 1958 | <set>Qt::AlignCenter</set> | ||
| 1959 | </property> | ||
| 1960 | <layout class="QVBoxLayout" name="verticalLayout_58"> | ||
| 1961 | <property name="spacing"> | ||
| 1962 | <number>3</number> | ||
| 1963 | </property> | ||
| 1964 | <property name="leftMargin"> | ||
| 1965 | <number>3</number> | ||
| 1966 | </property> | ||
| 1967 | <property name="topMargin"> | ||
| 1968 | <number>3</number> | ||
| 1969 | </property> | ||
| 1970 | <property name="rightMargin"> | ||
| 1971 | <number>3</number> | ||
| 1972 | </property> | ||
| 1973 | <property name="bottomMargin"> | ||
| 1974 | <number>3</number> | ||
| 1975 | </property> | ||
| 1976 | <item> | ||
| 1977 | <widget class="QPushButton" name="player7_left_body_button"> | ||
| 1978 | <property name="sizePolicy"> | ||
| 1979 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 1980 | <horstretch>0</horstretch> | ||
| 1981 | <verstretch>0</verstretch> | ||
| 1982 | </sizepolicy> | ||
| 1983 | </property> | ||
| 1984 | <property name="minimumSize"> | ||
| 1985 | <size> | ||
| 1986 | <width>57</width> | ||
| 1987 | <height>0</height> | ||
| 1988 | </size> | ||
| 1989 | </property> | ||
| 1990 | <property name="maximumSize"> | ||
| 1991 | <size> | ||
| 1992 | <width>55</width> | ||
| 1993 | <height>16777215</height> | ||
| 1994 | </size> | ||
| 1995 | </property> | ||
| 1996 | <property name="styleSheet"> | ||
| 1997 | <string notr="true">min-width: 55px;</string> | ||
| 1998 | </property> | ||
| 1999 | <property name="text"> | ||
| 2000 | <string/> | ||
| 2001 | </property> | ||
| 2002 | </widget> | ||
| 2003 | </item> | ||
| 2004 | </layout> | ||
| 2005 | </widget> | ||
| 2006 | </item> | ||
| 2007 | <item alignment="Qt::AlignHCenter"> | ||
| 2008 | <widget class="QGroupBox" name="player7LeftButtonsGroup"> | ||
| 2009 | <property name="title"> | ||
| 2010 | <string>L Button</string> | ||
| 2011 | </property> | ||
| 2012 | <property name="alignment"> | ||
| 2013 | <set>Qt::AlignCenter</set> | ||
| 2014 | </property> | ||
| 2015 | <layout class="QVBoxLayout" name="verticalLayout_59"> | ||
| 2016 | <property name="spacing"> | ||
| 2017 | <number>3</number> | ||
| 2018 | </property> | ||
| 2019 | <property name="leftMargin"> | ||
| 2020 | <number>3</number> | ||
| 2021 | </property> | ||
| 2022 | <property name="topMargin"> | ||
| 2023 | <number>3</number> | ||
| 2024 | </property> | ||
| 2025 | <property name="rightMargin"> | ||
| 2026 | <number>3</number> | ||
| 2027 | </property> | ||
| 2028 | <property name="bottomMargin"> | ||
| 2029 | <number>3</number> | ||
| 2030 | </property> | ||
| 2031 | <item> | ||
| 2032 | <widget class="QPushButton" name="player7_left_buttons_button"> | ||
| 2033 | <property name="sizePolicy"> | ||
| 2034 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 2035 | <horstretch>0</horstretch> | ||
| 2036 | <verstretch>0</verstretch> | ||
| 2037 | </sizepolicy> | ||
| 2038 | </property> | ||
| 2039 | <property name="minimumSize"> | ||
| 2040 | <size> | ||
| 2041 | <width>57</width> | ||
| 2042 | <height>0</height> | ||
| 2043 | </size> | ||
| 2044 | </property> | ||
| 2045 | <property name="maximumSize"> | ||
| 2046 | <size> | ||
| 2047 | <width>55</width> | ||
| 2048 | <height>16777215</height> | ||
| 2049 | </size> | ||
| 2050 | </property> | ||
| 2051 | <property name="styleSheet"> | ||
| 2052 | <string notr="true">min-width: 55px;</string> | ||
| 2053 | </property> | ||
| 2054 | <property name="text"> | ||
| 2055 | <string/> | ||
| 2056 | </property> | ||
| 2057 | </widget> | ||
| 2058 | </item> | ||
| 2059 | </layout> | ||
| 2060 | </widget> | ||
| 2061 | </item> | ||
| 2062 | </layout> | ||
| 2063 | </widget> | ||
| 2064 | </item> | ||
| 2065 | <item> | ||
| 2066 | <widget class="QWidget" name="player7RightJoycon" native="true"> | ||
| 2067 | <layout class="QVBoxLayout" name="buttonMiscButtonsRightJoyconVerticalLayout_12"> | ||
| 2068 | <property name="spacing"> | ||
| 2069 | <number>0</number> | ||
| 2070 | </property> | ||
| 2071 | <property name="leftMargin"> | ||
| 2072 | <number>0</number> | ||
| 2073 | </property> | ||
| 2074 | <property name="topMargin"> | ||
| 2075 | <number>0</number> | ||
| 2076 | </property> | ||
| 2077 | <property name="rightMargin"> | ||
| 2078 | <number>0</number> | ||
| 2079 | </property> | ||
| 2080 | <property name="bottomMargin"> | ||
| 2081 | <number>0</number> | ||
| 2082 | </property> | ||
| 2083 | <item alignment="Qt::AlignHCenter"> | ||
| 2084 | <widget class="QGroupBox" name="player7RightBodyGroup"> | ||
| 2085 | <property name="title"> | ||
| 2086 | <string>R Body</string> | ||
| 2087 | </property> | ||
| 2088 | <property name="alignment"> | ||
| 2089 | <set>Qt::AlignCenter</set> | ||
| 2090 | </property> | ||
| 2091 | <layout class="QVBoxLayout" name="verticalLayout_56"> | ||
| 2092 | <property name="spacing"> | ||
| 2093 | <number>3</number> | ||
| 2094 | </property> | ||
| 2095 | <property name="leftMargin"> | ||
| 2096 | <number>3</number> | ||
| 2097 | </property> | ||
| 2098 | <property name="topMargin"> | ||
| 2099 | <number>3</number> | ||
| 2100 | </property> | ||
| 2101 | <property name="rightMargin"> | ||
| 2102 | <number>3</number> | ||
| 2103 | </property> | ||
| 2104 | <property name="bottomMargin"> | ||
| 2105 | <number>3</number> | ||
| 2106 | </property> | ||
| 2107 | <item> | ||
| 2108 | <widget class="QPushButton" name="player7_right_body_button"> | ||
| 2109 | <property name="sizePolicy"> | ||
| 2110 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 2111 | <horstretch>0</horstretch> | ||
| 2112 | <verstretch>0</verstretch> | ||
| 2113 | </sizepolicy> | ||
| 2114 | </property> | ||
| 2115 | <property name="minimumSize"> | ||
| 2116 | <size> | ||
| 2117 | <width>57</width> | ||
| 2118 | <height>0</height> | ||
| 2119 | </size> | ||
| 2120 | </property> | ||
| 2121 | <property name="maximumSize"> | ||
| 2122 | <size> | ||
| 2123 | <width>55</width> | ||
| 2124 | <height>16777215</height> | ||
| 2125 | </size> | ||
| 2126 | </property> | ||
| 2127 | <property name="styleSheet"> | ||
| 2128 | <string notr="true">min-width: 55px;</string> | ||
| 2129 | </property> | ||
| 2130 | <property name="text"> | ||
| 2131 | <string/> | ||
| 2132 | </property> | ||
| 2133 | </widget> | ||
| 2134 | </item> | ||
| 2135 | </layout> | ||
| 2136 | </widget> | ||
| 2137 | </item> | ||
| 2138 | <item alignment="Qt::AlignHCenter"> | ||
| 2139 | <widget class="QGroupBox" name="player7RightButtonsGroup"> | ||
| 2140 | <property name="title"> | ||
| 2141 | <string>R Button</string> | ||
| 2142 | </property> | ||
| 2143 | <property name="alignment"> | ||
| 2144 | <set>Qt::AlignCenter</set> | ||
| 2145 | </property> | ||
| 2146 | <layout class="QVBoxLayout" name="verticalLayout_57"> | ||
| 2147 | <property name="spacing"> | ||
| 2148 | <number>3</number> | ||
| 2149 | </property> | ||
| 2150 | <property name="leftMargin"> | ||
| 2151 | <number>3</number> | ||
| 2152 | </property> | ||
| 2153 | <property name="topMargin"> | ||
| 2154 | <number>3</number> | ||
| 2155 | </property> | ||
| 2156 | <property name="rightMargin"> | ||
| 2157 | <number>3</number> | ||
| 2158 | </property> | ||
| 2159 | <property name="bottomMargin"> | ||
| 2160 | <number>3</number> | ||
| 2161 | </property> | ||
| 2162 | <item> | ||
| 2163 | <widget class="QPushButton" name="player7_right_buttons_button"> | ||
| 2164 | <property name="sizePolicy"> | ||
| 2165 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 2166 | <horstretch>0</horstretch> | ||
| 2167 | <verstretch>0</verstretch> | ||
| 2168 | </sizepolicy> | ||
| 2169 | </property> | ||
| 2170 | <property name="minimumSize"> | ||
| 2171 | <size> | ||
| 2172 | <width>57</width> | ||
| 2173 | <height>0</height> | ||
| 2174 | </size> | ||
| 2175 | </property> | ||
| 2176 | <property name="maximumSize"> | ||
| 2177 | <size> | ||
| 2178 | <width>55</width> | ||
| 2179 | <height>16777215</height> | ||
| 2180 | </size> | ||
| 2181 | </property> | ||
| 2182 | <property name="styleSheet"> | ||
| 2183 | <string notr="true">min-width: 55px;</string> | ||
| 2184 | </property> | ||
| 2185 | <property name="text"> | ||
| 2186 | <string/> | ||
| 2187 | </property> | ||
| 2188 | </widget> | ||
| 2189 | </item> | ||
| 2190 | </layout> | ||
| 2191 | </widget> | ||
| 2192 | </item> | ||
| 2193 | </layout> | ||
| 2194 | </widget> | ||
| 2195 | </item> | ||
| 2196 | </layout> | ||
| 2197 | </widget> | ||
| 2198 | </item> | ||
| 2199 | <item> | ||
| 2200 | <widget class="QGroupBox" name="player8Group"> | ||
| 2201 | <property name="title"> | ||
| 2202 | <string>Player 8</string> | ||
| 2203 | </property> | ||
| 2204 | <layout class="QHBoxLayout" name="horizontalLayout_13"> | ||
| 2205 | <property name="spacing"> | ||
| 2206 | <number>6</number> | ||
| 2207 | </property> | ||
| 2208 | <property name="leftMargin"> | ||
| 2209 | <number>6</number> | ||
| 2210 | </property> | ||
| 2211 | <property name="topMargin"> | ||
| 2212 | <number>0</number> | ||
| 2213 | </property> | ||
| 2214 | <property name="rightMargin"> | ||
| 2215 | <number>6</number> | ||
| 2216 | </property> | ||
| 2217 | <property name="bottomMargin"> | ||
| 2218 | <number>6</number> | ||
| 2219 | </property> | ||
| 2220 | <item> | ||
| 2221 | <widget class="QWidget" name="player8LeftJoycon" native="true"> | ||
| 2222 | <layout class="QVBoxLayout" name="buttonMiscButtonsLeftJoyconVerticalLayout_13"> | ||
| 2223 | <property name="spacing"> | ||
| 2224 | <number>0</number> | ||
| 2225 | </property> | ||
| 2226 | <property name="leftMargin"> | ||
| 2227 | <number>0</number> | ||
| 2228 | </property> | ||
| 2229 | <property name="topMargin"> | ||
| 2230 | <number>0</number> | ||
| 2231 | </property> | ||
| 2232 | <property name="rightMargin"> | ||
| 2233 | <number>0</number> | ||
| 2234 | </property> | ||
| 2235 | <property name="bottomMargin"> | ||
| 2236 | <number>0</number> | ||
| 2237 | </property> | ||
| 2238 | <item alignment="Qt::AlignHCenter"> | ||
| 2239 | <widget class="QGroupBox" name="player8LeftBodyGroup"> | ||
| 2240 | <property name="title"> | ||
| 2241 | <string>L Body</string> | ||
| 2242 | </property> | ||
| 2243 | <property name="alignment"> | ||
| 2244 | <set>Qt::AlignCenter</set> | ||
| 2245 | </property> | ||
| 2246 | <layout class="QVBoxLayout" name="verticalLayout_62"> | ||
| 2247 | <property name="spacing"> | ||
| 2248 | <number>3</number> | ||
| 2249 | </property> | ||
| 2250 | <property name="leftMargin"> | ||
| 2251 | <number>3</number> | ||
| 2252 | </property> | ||
| 2253 | <property name="topMargin"> | ||
| 2254 | <number>3</number> | ||
| 2255 | </property> | ||
| 2256 | <property name="rightMargin"> | ||
| 2257 | <number>3</number> | ||
| 2258 | </property> | ||
| 2259 | <property name="bottomMargin"> | ||
| 2260 | <number>3</number> | ||
| 2261 | </property> | ||
| 2262 | <item> | ||
| 2263 | <widget class="QPushButton" name="player8_left_body_button"> | ||
| 2264 | <property name="sizePolicy"> | ||
| 2265 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 2266 | <horstretch>0</horstretch> | ||
| 2267 | <verstretch>0</verstretch> | ||
| 2268 | </sizepolicy> | ||
| 2269 | </property> | ||
| 2270 | <property name="minimumSize"> | ||
| 2271 | <size> | ||
| 2272 | <width>57</width> | ||
| 2273 | <height>0</height> | ||
| 2274 | </size> | ||
| 2275 | </property> | ||
| 2276 | <property name="maximumSize"> | ||
| 2277 | <size> | ||
| 2278 | <width>55</width> | ||
| 2279 | <height>16777215</height> | ||
| 2280 | </size> | ||
| 2281 | </property> | ||
| 2282 | <property name="styleSheet"> | ||
| 2283 | <string notr="true">min-width: 55px;</string> | ||
| 2284 | </property> | ||
| 2285 | <property name="text"> | ||
| 2286 | <string/> | ||
| 2287 | </property> | ||
| 2288 | </widget> | ||
| 2289 | </item> | ||
| 2290 | </layout> | ||
| 2291 | </widget> | ||
| 2292 | </item> | ||
| 2293 | <item alignment="Qt::AlignHCenter"> | ||
| 2294 | <widget class="QGroupBox" name="player8LeftButtonsGroup"> | ||
| 2295 | <property name="title"> | ||
| 2296 | <string>L Button</string> | ||
| 2297 | </property> | ||
| 2298 | <property name="alignment"> | ||
| 2299 | <set>Qt::AlignCenter</set> | ||
| 2300 | </property> | ||
| 2301 | <layout class="QVBoxLayout" name="verticalLayout_63"> | ||
| 2302 | <property name="spacing"> | ||
| 2303 | <number>3</number> | ||
| 2304 | </property> | ||
| 2305 | <property name="leftMargin"> | ||
| 2306 | <number>3</number> | ||
| 2307 | </property> | ||
| 2308 | <property name="topMargin"> | ||
| 2309 | <number>3</number> | ||
| 2310 | </property> | ||
| 2311 | <property name="rightMargin"> | ||
| 2312 | <number>3</number> | ||
| 2313 | </property> | ||
| 2314 | <property name="bottomMargin"> | ||
| 2315 | <number>3</number> | ||
| 2316 | </property> | ||
| 2317 | <item> | ||
| 2318 | <widget class="QPushButton" name="player8_left_buttons_button"> | ||
| 2319 | <property name="sizePolicy"> | ||
| 2320 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 2321 | <horstretch>0</horstretch> | ||
| 2322 | <verstretch>0</verstretch> | ||
| 2323 | </sizepolicy> | ||
| 2324 | </property> | ||
| 2325 | <property name="minimumSize"> | ||
| 2326 | <size> | ||
| 2327 | <width>57</width> | ||
| 2328 | <height>0</height> | ||
| 2329 | </size> | ||
| 2330 | </property> | ||
| 2331 | <property name="maximumSize"> | ||
| 2332 | <size> | ||
| 2333 | <width>55</width> | ||
| 2334 | <height>16777215</height> | ||
| 2335 | </size> | ||
| 2336 | </property> | ||
| 2337 | <property name="styleSheet"> | ||
| 2338 | <string notr="true">min-width: 55px;</string> | ||
| 2339 | </property> | ||
| 2340 | <property name="text"> | ||
| 2341 | <string/> | ||
| 2342 | </property> | ||
| 2343 | </widget> | ||
| 2344 | </item> | ||
| 2345 | </layout> | ||
| 2346 | </widget> | ||
| 2347 | </item> | ||
| 2348 | </layout> | ||
| 2349 | </widget> | ||
| 2350 | </item> | ||
| 2351 | <item> | ||
| 2352 | <widget class="QWidget" name="player8RightJoycon" native="true"> | ||
| 2353 | <layout class="QVBoxLayout" name="buttonMiscButtonsRightJoyconVerticalLayout_13"> | ||
| 2354 | <property name="spacing"> | ||
| 2355 | <number>0</number> | ||
| 2356 | </property> | ||
| 2357 | <property name="leftMargin"> | ||
| 2358 | <number>0</number> | ||
| 2359 | </property> | ||
| 2360 | <property name="topMargin"> | ||
| 2361 | <number>0</number> | ||
| 2362 | </property> | ||
| 2363 | <property name="rightMargin"> | ||
| 2364 | <number>0</number> | ||
| 2365 | </property> | ||
| 2366 | <property name="bottomMargin"> | ||
| 2367 | <number>0</number> | ||
| 2368 | </property> | ||
| 2369 | <item alignment="Qt::AlignHCenter"> | ||
| 2370 | <widget class="QGroupBox" name="player8RightBodyGroup"> | ||
| 2371 | <property name="title"> | ||
| 2372 | <string>R Body</string> | ||
| 2373 | </property> | ||
| 2374 | <property name="alignment"> | ||
| 2375 | <set>Qt::AlignCenter</set> | ||
| 2376 | </property> | ||
| 2377 | <layout class="QVBoxLayout" name="verticalLayout_60"> | ||
| 2378 | <property name="spacing"> | ||
| 2379 | <number>3</number> | ||
| 2380 | </property> | ||
| 2381 | <property name="leftMargin"> | ||
| 2382 | <number>3</number> | ||
| 2383 | </property> | ||
| 2384 | <property name="topMargin"> | ||
| 2385 | <number>3</number> | ||
| 2386 | </property> | ||
| 2387 | <property name="rightMargin"> | ||
| 2388 | <number>3</number> | ||
| 2389 | </property> | ||
| 2390 | <property name="bottomMargin"> | ||
| 2391 | <number>3</number> | ||
| 2392 | </property> | ||
| 2393 | <item> | ||
| 2394 | <widget class="QPushButton" name="player8_right_body_button"> | ||
| 2395 | <property name="sizePolicy"> | ||
| 2396 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 2397 | <horstretch>0</horstretch> | ||
| 2398 | <verstretch>0</verstretch> | ||
| 2399 | </sizepolicy> | ||
| 2400 | </property> | ||
| 2401 | <property name="minimumSize"> | ||
| 2402 | <size> | ||
| 2403 | <width>57</width> | ||
| 2404 | <height>0</height> | ||
| 2405 | </size> | ||
| 2406 | </property> | ||
| 2407 | <property name="maximumSize"> | ||
| 2408 | <size> | ||
| 2409 | <width>55</width> | ||
| 2410 | <height>16777215</height> | ||
| 2411 | </size> | ||
| 2412 | </property> | ||
| 2413 | <property name="styleSheet"> | ||
| 2414 | <string notr="true">min-width: 55px;</string> | ||
| 2415 | </property> | ||
| 2416 | <property name="text"> | ||
| 2417 | <string/> | ||
| 2418 | </property> | ||
| 2419 | </widget> | ||
| 2420 | </item> | ||
| 2421 | </layout> | ||
| 2422 | </widget> | ||
| 2423 | </item> | ||
| 2424 | <item alignment="Qt::AlignHCenter"> | ||
| 2425 | <widget class="QGroupBox" name="player8RightButtonsGroup"> | ||
| 2426 | <property name="title"> | ||
| 2427 | <string>R Button</string> | ||
| 2428 | </property> | ||
| 2429 | <property name="alignment"> | ||
| 2430 | <set>Qt::AlignCenter</set> | ||
| 2431 | </property> | ||
| 2432 | <layout class="QVBoxLayout" name="verticalLayout_61"> | ||
| 2433 | <property name="spacing"> | ||
| 2434 | <number>3</number> | ||
| 2435 | </property> | ||
| 2436 | <property name="leftMargin"> | ||
| 2437 | <number>3</number> | ||
| 2438 | </property> | ||
| 2439 | <property name="topMargin"> | ||
| 2440 | <number>3</number> | ||
| 2441 | </property> | ||
| 2442 | <property name="rightMargin"> | ||
| 2443 | <number>3</number> | ||
| 2444 | </property> | ||
| 2445 | <property name="bottomMargin"> | ||
| 2446 | <number>3</number> | ||
| 2447 | </property> | ||
| 2448 | <item> | ||
| 2449 | <widget class="QPushButton" name="player8_right_buttons_button"> | ||
| 2450 | <property name="sizePolicy"> | ||
| 2451 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 2452 | <horstretch>0</horstretch> | ||
| 2453 | <verstretch>0</verstretch> | ||
| 2454 | </sizepolicy> | ||
| 2455 | </property> | ||
| 2456 | <property name="minimumSize"> | ||
| 2457 | <size> | ||
| 2458 | <width>57</width> | ||
| 2459 | <height>0</height> | ||
| 2460 | </size> | ||
| 2461 | </property> | ||
| 2462 | <property name="maximumSize"> | ||
| 2463 | <size> | ||
| 2464 | <width>55</width> | ||
| 2465 | <height>16777215</height> | ||
| 2466 | </size> | ||
| 2467 | </property> | ||
| 2468 | <property name="styleSheet"> | ||
| 2469 | <string notr="true">min-width: 55px;</string> | ||
| 2470 | </property> | ||
| 2471 | <property name="text"> | ||
| 2472 | <string/> | ||
| 2473 | </property> | ||
| 2474 | </widget> | ||
| 2475 | </item> | ||
| 2476 | </layout> | ||
| 2477 | </widget> | ||
| 2478 | </item> | ||
| 2479 | </layout> | ||
| 2480 | </widget> | ||
| 2481 | </item> | ||
| 2482 | </layout> | ||
| 2483 | </widget> | ||
| 2484 | </item> | ||
| 2485 | </layout> | ||
| 2486 | </widget> | ||
| 2487 | </item> | ||
| 2488 | </layout> | ||
| 2489 | </widget> | ||
| 2490 | </item> | ||
| 2491 | </layout> | ||
| 2492 | </widget> | ||
| 2493 | </item> | ||
| 2494 | </layout> | ||
| 2495 | </widget> | ||
| 2496 | </item> | ||
| 2497 | <item> | ||
| 2498 | <widget class="QWidget" name="rightInputAdvanced" native="true"> | ||
| 2499 | <layout class="QVBoxLayout" name="rightLayout" stretch="1,1"> | ||
| 2500 | <property name="spacing"> | ||
| 2501 | <number>3</number> | ||
| 2502 | </property> | ||
| 2503 | <property name="leftMargin"> | ||
| 2504 | <number>0</number> | ||
| 2505 | </property> | ||
| 2506 | <property name="topMargin"> | ||
| 2507 | <number>0</number> | ||
| 2508 | </property> | ||
| 2509 | <property name="rightMargin"> | ||
| 2510 | <number>0</number> | ||
| 2511 | </property> | ||
| 2512 | <property name="bottomMargin"> | ||
| 2513 | <number>0</number> | ||
| 2514 | </property> | ||
| 2515 | <item> | ||
| 2516 | <widget class="QWidget" name="topRightInputAdvanced" native="true"> | ||
| 2517 | <layout class="QVBoxLayout" name="verticalLayout"> | ||
| 2518 | <property name="leftMargin"> | ||
| 2519 | <number>0</number> | ||
| 2520 | </property> | ||
| 2521 | <property name="topMargin"> | ||
| 2522 | <number>0</number> | ||
| 2523 | </property> | ||
| 2524 | <property name="rightMargin"> | ||
| 2525 | <number>0</number> | ||
| 2526 | </property> | ||
| 2527 | <property name="bottomMargin"> | ||
| 2528 | <number>0</number> | ||
| 2529 | </property> | ||
| 2530 | <item> | ||
| 2531 | <widget class="QGroupBox" name="gridGroupBox_3"> | ||
| 2532 | <property name="title"> | ||
| 2533 | <string>Other</string> | ||
| 2534 | </property> | ||
| 2535 | <layout class="QGridLayout" name="gridLayout_3"> | ||
| 2536 | <item row="0" column="0"> | ||
| 2537 | <widget class="QCheckBox" name="keyboard_enabled"> | ||
| 2538 | <property name="minimumSize"> | ||
| 2539 | <size> | ||
| 2540 | <width>0</width> | ||
| 2541 | <height>23</height> | ||
| 2542 | </size> | ||
| 2543 | </property> | ||
| 2544 | <property name="text"> | ||
| 2545 | <string>Keyboard</string> | ||
| 2546 | </property> | ||
| 2547 | </widget> | ||
| 2548 | </item> | ||
| 2549 | <item row="4" column="2"> | ||
| 2550 | <widget class="QPushButton" name="touchscreen_advanced"> | ||
| 2551 | <property name="text"> | ||
| 2552 | <string>Advanced</string> | ||
| 2553 | </property> | ||
| 2554 | </widget> | ||
| 2555 | </item> | ||
| 2556 | <item row="1" column="1"> | ||
| 2557 | <spacer name="horizontalSpacer_8"> | ||
| 2558 | <property name="orientation"> | ||
| 2559 | <enum>Qt::Horizontal</enum> | ||
| 2560 | </property> | ||
| 2561 | <property name="sizeType"> | ||
| 2562 | <enum>QSizePolicy::Fixed</enum> | ||
| 2563 | </property> | ||
| 2564 | <property name="sizeHint" stdset="0"> | ||
| 2565 | <size> | ||
| 2566 | <width>76</width> | ||
| 2567 | <height>20</height> | ||
| 2568 | </size> | ||
| 2569 | </property> | ||
| 2570 | </spacer> | ||
| 2571 | </item> | ||
| 2572 | <item row="1" column="2"> | ||
| 2573 | <widget class="QPushButton" name="mouse_advanced"> | ||
| 2574 | <property name="text"> | ||
| 2575 | <string>Advanced</string> | ||
| 2576 | </property> | ||
| 2577 | </widget> | ||
| 2578 | </item> | ||
| 2579 | <item row="4" column="0"> | ||
| 2580 | <widget class="QCheckBox" name="touchscreen_enabled"> | ||
| 2581 | <property name="text"> | ||
| 2582 | <string>Touchscreen</string> | ||
| 2583 | </property> | ||
| 2584 | </widget> | ||
| 2585 | </item> | ||
| 2586 | <item row="1" column="0"> | ||
| 2587 | <widget class="QCheckBox" name="mouse_enabled"> | ||
| 2588 | <property name="minimumSize"> | ||
| 2589 | <size> | ||
| 2590 | <width>0</width> | ||
| 2591 | <height>23</height> | ||
| 2592 | </size> | ||
| 2593 | </property> | ||
| 2594 | <property name="text"> | ||
| 2595 | <string>Mouse</string> | ||
| 2596 | </property> | ||
| 2597 | </widget> | ||
| 2598 | </item> | ||
| 2599 | <item row="6" column="0"> | ||
| 2600 | <widget class="QLabel" name="motion_touch"> | ||
| 2601 | <property name="text"> | ||
| 2602 | <string>Motion / Touch</string> | ||
| 2603 | </property> | ||
| 2604 | </widget> | ||
| 2605 | </item> | ||
| 2606 | <item row="6" column="2"> | ||
| 2607 | <widget class="QPushButton" name="buttonMotionTouch"> | ||
| 2608 | <property name="text"> | ||
| 2609 | <string>Configure</string> | ||
| 2610 | </property> | ||
| 2611 | </widget> | ||
| 2612 | </item> | ||
| 2613 | <item row="5" column="0"> | ||
| 2614 | <widget class="QCheckBox" name="debug_enabled"> | ||
| 2615 | <property name="text"> | ||
| 2616 | <string>Debug Controller</string> | ||
| 2617 | </property> | ||
| 2618 | </widget> | ||
| 2619 | </item> | ||
| 2620 | <item row="5" column="2"> | ||
| 2621 | <widget class="QPushButton" name="debug_configure"> | ||
| 2622 | <property name="text"> | ||
| 2623 | <string>Configure</string> | ||
| 2624 | </property> | ||
| 2625 | </widget> | ||
| 2626 | </item> | ||
| 2627 | </layout> | ||
| 2628 | </widget> | ||
| 2629 | </item> | ||
| 2630 | <item> | ||
| 2631 | <spacer name="verticalSpacer"> | ||
| 2632 | <property name="orientation"> | ||
| 2633 | <enum>Qt::Vertical</enum> | ||
| 2634 | </property> | ||
| 2635 | <property name="sizeHint" stdset="0"> | ||
| 2636 | <size> | ||
| 2637 | <width>20</width> | ||
| 2638 | <height>40</height> | ||
| 2639 | </size> | ||
| 2640 | </property> | ||
| 2641 | </spacer> | ||
| 2642 | </item> | ||
| 2643 | </layout> | ||
| 2644 | </widget> | ||
| 2645 | </item> | ||
| 2646 | <item> | ||
| 2647 | <widget class="QWidget" name="bottomRightInputAdvanced" native="true"> | ||
| 2648 | <layout class="QVBoxLayout" name="verticalLayout_2"> | ||
| 2649 | <property name="leftMargin"> | ||
| 2650 | <number>0</number> | ||
| 2651 | </property> | ||
| 2652 | <property name="topMargin"> | ||
| 2653 | <number>0</number> | ||
| 2654 | </property> | ||
| 2655 | <property name="rightMargin"> | ||
| 2656 | <number>0</number> | ||
| 2657 | </property> | ||
| 2658 | <property name="bottomMargin"> | ||
| 2659 | <number>0</number> | ||
| 2660 | </property> | ||
| 2661 | <item> | ||
| 2662 | <spacer name="mainVerticalSpacer"> | ||
| 2663 | <property name="orientation"> | ||
| 2664 | <enum>Qt::Vertical</enum> | ||
| 2665 | </property> | ||
| 2666 | <property name="sizeHint" stdset="0"> | ||
| 2667 | <size> | ||
| 2668 | <width>20</width> | ||
| 2669 | <height>40</height> | ||
| 2670 | </size> | ||
| 2671 | </property> | ||
| 2672 | </spacer> | ||
| 2673 | </item> | ||
| 2674 | </layout> | ||
| 2675 | </widget> | ||
| 2676 | </item> | ||
| 2677 | </layout> | ||
| 2678 | </widget> | ||
| 2679 | </item> | ||
| 2680 | </layout> | ||
| 2681 | </widget> | ||
| 2682 | </item> | ||
| 2683 | </layout> | ||
| 2684 | </widget> | ||
| 2685 | <resources> | ||
| 2686 | </resources> | ||
| 2687 | <connections/> | ||
| 2688 | </ui> | ||
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index b1850bc95..13ecb3dc5 100644 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp | |||
| @@ -5,39 +5,97 @@ | |||
| 5 | #include <algorithm> | 5 | #include <algorithm> |
| 6 | #include <memory> | 6 | #include <memory> |
| 7 | #include <utility> | 7 | #include <utility> |
| 8 | #include <QColorDialog> | ||
| 9 | #include <QGridLayout> | 8 | #include <QGridLayout> |
| 9 | #include <QInputDialog> | ||
| 10 | #include <QKeyEvent> | 10 | #include <QKeyEvent> |
| 11 | #include <QMenu> | 11 | #include <QMenu> |
| 12 | #include <QMessageBox> | 12 | #include <QMessageBox> |
| 13 | #include <QTimer> | 13 | #include <QTimer> |
| 14 | #include "common/assert.h" | ||
| 15 | #include "common/param_package.h" | 14 | #include "common/param_package.h" |
| 15 | #include "core/core.h" | ||
| 16 | #include "core/hle/service/hid/controllers/npad.h" | ||
| 17 | #include "core/hle/service/hid/hid.h" | ||
| 18 | #include "core/hle/service/sm/sm.h" | ||
| 19 | #include "input_common/gcadapter/gc_poller.h" | ||
| 16 | #include "input_common/main.h" | 20 | #include "input_common/main.h" |
| 17 | #include "ui_configure_input_player.h" | 21 | #include "ui_configure_input_player.h" |
| 18 | #include "yuzu/configuration/config.h" | 22 | #include "yuzu/configuration/config.h" |
| 19 | #include "yuzu/configuration/configure_input_player.h" | 23 | #include "yuzu/configuration/configure_input_player.h" |
| 20 | 24 | ||
| 25 | constexpr std::size_t HANDHELD_INDEX = 8; | ||
| 26 | |||
| 21 | const std::array<std::string, ConfigureInputPlayer::ANALOG_SUB_BUTTONS_NUM> | 27 | const std::array<std::string, ConfigureInputPlayer::ANALOG_SUB_BUTTONS_NUM> |
| 22 | ConfigureInputPlayer::analog_sub_buttons{{ | 28 | ConfigureInputPlayer::analog_sub_buttons{{ |
| 23 | "up", | 29 | "up", |
| 24 | "down", | 30 | "down", |
| 25 | "left", | 31 | "left", |
| 26 | "right", | 32 | "right", |
| 27 | "modifier", | ||
| 28 | }}; | 33 | }}; |
| 29 | 34 | ||
| 30 | static void LayerGridElements(QGridLayout* grid, QWidget* item, QWidget* onTopOf) { | 35 | namespace { |
| 31 | const int index1 = grid->indexOf(item); | 36 | |
| 32 | const int index2 = grid->indexOf(onTopOf); | 37 | void UpdateController(Settings::ControllerType controller_type, std::size_t npad_index, |
| 33 | int row, column, rowSpan, columnSpan; | 38 | bool connected) { |
| 34 | grid->getItemPosition(index2, &row, &column, &rowSpan, &columnSpan); | 39 | Core::System& system{Core::System::GetInstance()}; |
| 35 | grid->takeAt(index1); | 40 | if (!system.IsPoweredOn()) { |
| 36 | grid->addWidget(item, row, column, rowSpan, columnSpan); | 41 | return; |
| 42 | } | ||
| 43 | Service::SM::ServiceManager& sm = system.ServiceManager(); | ||
| 44 | |||
| 45 | auto& npad = | ||
| 46 | sm.GetService<Service::HID::Hid>("hid") | ||
| 47 | ->GetAppletResource() | ||
| 48 | ->GetController<Service::HID::Controller_NPad>(Service::HID::HidController::NPad); | ||
| 49 | |||
| 50 | npad.UpdateControllerAt(npad.MapSettingsTypeToNPad(controller_type), npad_index, connected); | ||
| 37 | } | 51 | } |
| 38 | 52 | ||
| 39 | static QString GetKeyName(int key_code) { | 53 | /// Maps the controller type combobox index to Controller Type enum |
| 54 | constexpr Settings::ControllerType GetControllerTypeFromIndex(int index) { | ||
| 55 | switch (index) { | ||
| 56 | case 0: | ||
| 57 | default: | ||
| 58 | return Settings::ControllerType::ProController; | ||
| 59 | case 1: | ||
| 60 | return Settings::ControllerType::DualJoyconDetached; | ||
| 61 | case 2: | ||
| 62 | return Settings::ControllerType::LeftJoycon; | ||
| 63 | case 3: | ||
| 64 | return Settings::ControllerType::RightJoycon; | ||
| 65 | case 4: | ||
| 66 | return Settings::ControllerType::Handheld; | ||
| 67 | } | ||
| 68 | } | ||
| 69 | |||
| 70 | /// Maps the Controller Type enum to controller type combobox index | ||
| 71 | constexpr int GetIndexFromControllerType(Settings::ControllerType type) { | ||
| 72 | switch (type) { | ||
| 73 | case Settings::ControllerType::ProController: | ||
| 74 | default: | ||
| 75 | return 0; | ||
| 76 | case Settings::ControllerType::DualJoyconDetached: | ||
| 77 | return 1; | ||
| 78 | case Settings::ControllerType::LeftJoycon: | ||
| 79 | return 2; | ||
| 80 | case Settings::ControllerType::RightJoycon: | ||
| 81 | return 3; | ||
| 82 | case Settings::ControllerType::Handheld: | ||
| 83 | return 4; | ||
| 84 | } | ||
| 85 | } | ||
| 86 | |||
| 87 | QString GetKeyName(int key_code) { | ||
| 40 | switch (key_code) { | 88 | switch (key_code) { |
| 89 | case Qt::LeftButton: | ||
| 90 | return QObject::tr("Click 0"); | ||
| 91 | case Qt::RightButton: | ||
| 92 | return QObject::tr("Click 1"); | ||
| 93 | case Qt::MiddleButton: | ||
| 94 | return QObject::tr("Click 2"); | ||
| 95 | case Qt::BackButton: | ||
| 96 | return QObject::tr("Click 3"); | ||
| 97 | case Qt::ForwardButton: | ||
| 98 | return QObject::tr("Click 4"); | ||
| 41 | case Qt::Key_Shift: | 99 | case Qt::Key_Shift: |
| 42 | return QObject::tr("Shift"); | 100 | return QObject::tr("Shift"); |
| 43 | case Qt::Key_Control: | 101 | case Qt::Key_Control: |
| @@ -51,9 +109,16 @@ static QString GetKeyName(int key_code) { | |||
| 51 | } | 109 | } |
| 52 | } | 110 | } |
| 53 | 111 | ||
| 54 | static void SetAnalogButton(const Common::ParamPackage& input_param, | 112 | void SetAnalogParam(const Common::ParamPackage& input_param, Common::ParamPackage& analog_param, |
| 55 | Common::ParamPackage& analog_param, const std::string& button_name) { | 113 | const std::string& button_name) { |
| 56 | if (analog_param.Get("engine", "") != "analog_from_button") { | 114 | // The poller returned a complete axis, so set all the buttons |
| 115 | if (input_param.Has("axis_x") && input_param.Has("axis_y")) { | ||
| 116 | analog_param = input_param; | ||
| 117 | return; | ||
| 118 | } | ||
| 119 | // Check if the current configuration has either no engine or an axis binding. | ||
| 120 | // Clears out the old binding and adds one with analog_from_button. | ||
| 121 | if (!analog_param.Has("engine") || analog_param.Has("axis_x") || analog_param.Has("axis_y")) { | ||
| 57 | analog_param = { | 122 | analog_param = { |
| 58 | {"engine", "analog_from_button"}, | 123 | {"engine", "analog_from_button"}, |
| 59 | }; | 124 | }; |
| @@ -61,7 +126,7 @@ static void SetAnalogButton(const Common::ParamPackage& input_param, | |||
| 61 | analog_param.Set(button_name, input_param.Serialize()); | 126 | analog_param.Set(button_name, input_param.Serialize()); |
| 62 | } | 127 | } |
| 63 | 128 | ||
| 64 | static QString ButtonToText(const Common::ParamPackage& param) { | 129 | QString ButtonToText(const Common::ParamPackage& param) { |
| 65 | if (!param.Has("engine")) { | 130 | if (!param.Has("engine")) { |
| 66 | return QObject::tr("[not set]"); | 131 | return QObject::tr("[not set]"); |
| 67 | } | 132 | } |
| @@ -111,7 +176,7 @@ static QString ButtonToText(const Common::ParamPackage& param) { | |||
| 111 | return QObject::tr("[unknown]"); | 176 | return QObject::tr("[unknown]"); |
| 112 | } | 177 | } |
| 113 | 178 | ||
| 114 | static QString AnalogToText(const Common::ParamPackage& param, const std::string& dir) { | 179 | QString AnalogToText(const Common::ParamPackage& param, const std::string& dir) { |
| 115 | if (!param.Has("engine")) { | 180 | if (!param.Has("engine")) { |
| 116 | return QObject::tr("[not set]"); | 181 | return QObject::tr("[not set]"); |
| 117 | } | 182 | } |
| @@ -161,22 +226,25 @@ static QString AnalogToText(const Common::ParamPackage& param, const std::string | |||
| 161 | } | 226 | } |
| 162 | return QObject::tr("[unknown]"); | 227 | return QObject::tr("[unknown]"); |
| 163 | } | 228 | } |
| 164 | 229 | } // namespace | |
| 165 | ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_index, bool debug) | 230 | |
| 166 | : QDialog(parent), ui(std::make_unique<Ui::ConfigureInputPlayer>()), player_index(player_index), | 231 | ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_index, |
| 167 | debug(debug), timeout_timer(std::make_unique<QTimer>()), | 232 | QWidget* bottom_row, |
| 168 | poll_timer(std::make_unique<QTimer>()) { | 233 | InputCommon::InputSubsystem* input_subsystem_, |
| 234 | bool debug) | ||
| 235 | : QWidget(parent), ui(std::make_unique<Ui::ConfigureInputPlayer>()), player_index(player_index), | ||
| 236 | debug(debug), input_subsystem{input_subsystem_}, timeout_timer(std::make_unique<QTimer>()), | ||
| 237 | poll_timer(std::make_unique<QTimer>()), bottom_row(bottom_row) { | ||
| 169 | ui->setupUi(this); | 238 | ui->setupUi(this); |
| 239 | |||
| 170 | setFocusPolicy(Qt::ClickFocus); | 240 | setFocusPolicy(Qt::ClickFocus); |
| 171 | 241 | ||
| 172 | button_map = { | 242 | button_map = { |
| 173 | ui->buttonA, ui->buttonB, ui->buttonX, ui->buttonY, | 243 | ui->buttonA, ui->buttonB, ui->buttonX, ui->buttonY, |
| 174 | ui->buttonLStick, ui->buttonRStick, ui->buttonL, ui->buttonR, | 244 | ui->buttonLStick, ui->buttonRStick, ui->buttonL, ui->buttonR, |
| 175 | ui->buttonZL, ui->buttonZR, ui->buttonPlus, ui->buttonMinus, | 245 | ui->buttonZL, ui->buttonZR, ui->buttonPlus, ui->buttonMinus, |
| 176 | ui->buttonDpadLeft, ui->buttonDpadUp, ui->buttonDpadRight, ui->buttonDpadDown, | 246 | ui->buttonDpadLeft, ui->buttonDpadUp, ui->buttonDpadRight, ui->buttonDpadDown, |
| 177 | ui->buttonLStickLeft, ui->buttonLStickUp, ui->buttonLStickRight, ui->buttonLStickDown, | 247 | ui->buttonSL, ui->buttonSR, ui->buttonHome, ui->buttonScreenshot, |
| 178 | ui->buttonRStickLeft, ui->buttonRStickUp, ui->buttonRStickRight, ui->buttonRStickDown, | ||
| 179 | ui->buttonSL, ui->buttonSR, ui->buttonHome, ui->buttonScreenshot, | ||
| 180 | }; | 248 | }; |
| 181 | 249 | ||
| 182 | analog_map_buttons = {{ | 250 | analog_map_buttons = {{ |
| @@ -185,220 +253,165 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i | |||
| 185 | ui->buttonLStickDown, | 253 | ui->buttonLStickDown, |
| 186 | ui->buttonLStickLeft, | 254 | ui->buttonLStickLeft, |
| 187 | ui->buttonLStickRight, | 255 | ui->buttonLStickRight, |
| 188 | ui->buttonLStickMod, | ||
| 189 | }, | 256 | }, |
| 190 | { | 257 | { |
| 191 | ui->buttonRStickUp, | 258 | ui->buttonRStickUp, |
| 192 | ui->buttonRStickDown, | 259 | ui->buttonRStickDown, |
| 193 | ui->buttonRStickLeft, | 260 | ui->buttonRStickLeft, |
| 194 | ui->buttonRStickRight, | 261 | ui->buttonRStickRight, |
| 195 | ui->buttonRStickMod, | ||
| 196 | }, | 262 | }, |
| 197 | }}; | 263 | }}; |
| 198 | 264 | ||
| 199 | debug_hidden = { | 265 | analog_map_deadzone_label = {ui->labelLStickDeadzone, ui->labelRStickDeadzone}; |
| 200 | ui->buttonSL, ui->labelSL, | 266 | analog_map_deadzone_slider = {ui->sliderLStickDeadzone, ui->sliderRStickDeadzone}; |
| 201 | ui->buttonSR, ui->labelSR, | 267 | analog_map_modifier_groupbox = {ui->buttonLStickModGroup, ui->buttonRStickModGroup}; |
| 202 | ui->buttonLStick, ui->labelLStickPressed, | 268 | analog_map_modifier_label = {ui->labelLStickModifierRange, ui->labelRStickModifierRange}; |
| 203 | ui->buttonRStick, ui->labelRStickPressed, | 269 | analog_map_modifier_slider = {ui->sliderLStickModifierRange, ui->sliderRStickModifierRange}; |
| 204 | ui->buttonHome, ui->labelHome, | 270 | analog_map_range_groupbox = {ui->buttonLStickRangeGroup, ui->buttonRStickRangeGroup}; |
| 205 | ui->buttonScreenshot, ui->labelScreenshot, | 271 | analog_map_range_spinbox = {ui->spinboxLStickRange, ui->spinboxRStickRange}; |
| 206 | }; | ||
| 207 | |||
| 208 | auto layout = Settings::values.players[player_index].type; | ||
| 209 | if (debug) | ||
| 210 | layout = Settings::ControllerType::DualJoycon; | ||
| 211 | |||
| 212 | switch (layout) { | ||
| 213 | case Settings::ControllerType::ProController: | ||
| 214 | case Settings::ControllerType::DualJoycon: | ||
| 215 | layout_hidden = { | ||
| 216 | ui->buttonSL, | ||
| 217 | ui->labelSL, | ||
| 218 | ui->buttonSR, | ||
| 219 | ui->labelSR, | ||
| 220 | }; | ||
| 221 | break; | ||
| 222 | case Settings::ControllerType::LeftJoycon: | ||
| 223 | layout_hidden = { | ||
| 224 | ui->right_body_button, | ||
| 225 | ui->right_buttons_button, | ||
| 226 | ui->right_body_label, | ||
| 227 | ui->right_buttons_label, | ||
| 228 | ui->buttonR, | ||
| 229 | ui->labelR, | ||
| 230 | ui->buttonZR, | ||
| 231 | ui->labelZR, | ||
| 232 | ui->labelHome, | ||
| 233 | ui->buttonHome, | ||
| 234 | ui->buttonPlus, | ||
| 235 | ui->labelPlus, | ||
| 236 | ui->RStick, | ||
| 237 | ui->faceButtons, | ||
| 238 | }; | ||
| 239 | break; | ||
| 240 | case Settings::ControllerType::RightJoycon: | ||
| 241 | layout_hidden = { | ||
| 242 | ui->left_body_button, ui->left_buttons_button, | ||
| 243 | ui->left_body_label, ui->left_buttons_label, | ||
| 244 | ui->buttonL, ui->labelL, | ||
| 245 | ui->buttonZL, ui->labelZL, | ||
| 246 | ui->labelScreenshot, ui->buttonScreenshot, | ||
| 247 | ui->buttonMinus, ui->labelMinus, | ||
| 248 | ui->LStick, ui->Dpad, | ||
| 249 | }; | ||
| 250 | break; | ||
| 251 | } | ||
| 252 | |||
| 253 | if (debug || layout == Settings::ControllerType::ProController) { | ||
| 254 | ui->controller_color->hide(); | ||
| 255 | } else { | ||
| 256 | if (layout == Settings::ControllerType::LeftJoycon || | ||
| 257 | layout == Settings::ControllerType::RightJoycon) { | ||
| 258 | ui->horizontalSpacer_4->setGeometry({0, 0, 0, 0}); | ||
| 259 | |||
| 260 | LayerGridElements(ui->buttons, ui->shoulderButtons, ui->Dpad); | ||
| 261 | LayerGridElements(ui->buttons, ui->misc, ui->RStick); | ||
| 262 | LayerGridElements(ui->buttons, ui->Dpad, ui->faceButtons); | ||
| 263 | LayerGridElements(ui->buttons, ui->RStick, ui->LStick); | ||
| 264 | } | ||
| 265 | } | ||
| 266 | 272 | ||
| 267 | for (auto* widget : layout_hidden) | 273 | const auto ConfigureButtonClick = [&](QPushButton* button, Common::ParamPackage* param, |
| 268 | widget->setVisible(false); | 274 | int default_val) { |
| 269 | 275 | connect(button, &QPushButton::clicked, [=, this] { | |
| 270 | analog_map_stick = {ui->buttonLStickAnalog, ui->buttonRStickAnalog}; | 276 | HandleClick( |
| 271 | analog_map_deadzone_and_modifier_slider = {ui->sliderLStickDeadzoneAndModifier, | 277 | button, |
| 272 | ui->sliderRStickDeadzoneAndModifier}; | 278 | [=, this](Common::ParamPackage params) { |
| 273 | analog_map_deadzone_and_modifier_slider_label = {ui->labelLStickDeadzoneAndModifier, | 279 | // Workaround for ZL & ZR for analog triggers like on XBOX |
| 274 | ui->labelRStickDeadzoneAndModifier}; | 280 | // controllers. Analog triggers (from controllers like the XBOX |
| 281 | // controller) would not work due to a different range of their | ||
| 282 | // signals (from 0 to 255 on analog triggers instead of -32768 to | ||
| 283 | // 32768 on analog joysticks). The SDL driver misinterprets analog | ||
| 284 | // triggers as analog joysticks. | ||
| 285 | // TODO: reinterpret the signal range for analog triggers to map the | ||
| 286 | // values correctly. This is required for the correct emulation of | ||
| 287 | // the analog triggers of the GameCube controller. | ||
| 288 | if (button == ui->buttonZL || button == ui->buttonZR) { | ||
| 289 | params.Set("direction", "+"); | ||
| 290 | params.Set("threshold", "0.5"); | ||
| 291 | } | ||
| 292 | *param = std::move(params); | ||
| 293 | }, | ||
| 294 | InputCommon::Polling::DeviceType::Button); | ||
| 295 | }); | ||
| 296 | }; | ||
| 275 | 297 | ||
| 276 | for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; button_id++) { | 298 | for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; ++button_id) { |
| 277 | auto* const button = button_map[button_id]; | 299 | auto* const button = button_map[button_id]; |
| 278 | if (button == nullptr) { | 300 | if (button == nullptr) { |
| 279 | continue; | 301 | continue; |
| 280 | } | 302 | } |
| 281 | 303 | ConfigureButtonClick(button_map[button_id], &buttons_param[button_id], | |
| 282 | button->setContextMenuPolicy(Qt::CustomContextMenu); | 304 | Config::default_buttons[button_id]); |
| 283 | connect(button, &QPushButton::clicked, [=, this] { | ||
| 284 | HandleClick(button_map[button_id], | ||
| 285 | [=, this](Common::ParamPackage params) { | ||
| 286 | // Workaround for ZL & ZR for analog triggers like on XBOX controllors. | ||
| 287 | // Analog triggers (from controllers like the XBOX controller) would not | ||
| 288 | // work due to a different range of their signals (from 0 to 255 on | ||
| 289 | // analog triggers instead of -32768 to 32768 on analog joysticks). The | ||
| 290 | // SDL driver misinterprets analog triggers as analog joysticks. | ||
| 291 | // TODO: reinterpret the signal range for analog triggers to map the | ||
| 292 | // values correctly. This is required for the correct emulation of the | ||
| 293 | // analog triggers of the GameCube controller. | ||
| 294 | if (button_id == Settings::NativeButton::ZL || | ||
| 295 | button_id == Settings::NativeButton::ZR) { | ||
| 296 | params.Set("direction", "+"); | ||
| 297 | params.Set("threshold", "0.5"); | ||
| 298 | } | ||
| 299 | buttons_param[button_id] = std::move(params); | ||
| 300 | }, | ||
| 301 | InputCommon::Polling::DeviceType::Button); | ||
| 302 | }); | ||
| 303 | connect(button, &QPushButton::customContextMenuRequested, | ||
| 304 | [=, this](const QPoint& menu_location) { | ||
| 305 | QMenu context_menu; | ||
| 306 | context_menu.addAction(tr("Clear"), [&] { | ||
| 307 | buttons_param[button_id].Clear(); | ||
| 308 | button_map[button_id]->setText(tr("[not set]")); | ||
| 309 | }); | ||
| 310 | context_menu.addAction(tr("Restore Default"), [&] { | ||
| 311 | buttons_param[button_id] = Common::ParamPackage{ | ||
| 312 | InputCommon::GenerateKeyboardParam(Config::default_buttons[button_id])}; | ||
| 313 | button_map[button_id]->setText(ButtonToText(buttons_param[button_id])); | ||
| 314 | }); | ||
| 315 | context_menu.exec(button_map[button_id]->mapToGlobal(menu_location)); | ||
| 316 | }); | ||
| 317 | } | 305 | } |
| 318 | 306 | ||
| 319 | for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; analog_id++) { | 307 | // Handle clicks for the modifier buttons as well. |
| 320 | for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; sub_button_id++) { | 308 | ConfigureButtonClick(ui->buttonLStickMod, &lstick_mod, Config::default_stick_mod[0]); |
| 309 | ConfigureButtonClick(ui->buttonRStickMod, &rstick_mod, Config::default_stick_mod[1]); | ||
| 310 | |||
| 311 | for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; ++analog_id) { | ||
| 312 | for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; ++sub_button_id) { | ||
| 321 | auto* const analog_button = analog_map_buttons[analog_id][sub_button_id]; | 313 | auto* const analog_button = analog_map_buttons[analog_id][sub_button_id]; |
| 314 | |||
| 322 | if (analog_button == nullptr) { | 315 | if (analog_button == nullptr) { |
| 323 | continue; | 316 | continue; |
| 324 | } | 317 | } |
| 325 | 318 | ||
| 326 | analog_button->setContextMenuPolicy(Qt::CustomContextMenu); | ||
| 327 | connect(analog_button, &QPushButton::clicked, [=, this] { | 319 | connect(analog_button, &QPushButton::clicked, [=, this] { |
| 328 | HandleClick(analog_map_buttons[analog_id][sub_button_id], | 320 | HandleClick( |
| 329 | [=, this](const Common::ParamPackage& params) { | 321 | analog_map_buttons[analog_id][sub_button_id], |
| 330 | SetAnalogButton(params, analogs_param[analog_id], | 322 | [=, this](const Common::ParamPackage& params) { |
| 331 | analog_sub_buttons[sub_button_id]); | 323 | SetAnalogParam(params, analogs_param[analog_id], |
| 332 | }, | 324 | analog_sub_buttons[sub_button_id]); |
| 333 | InputCommon::Polling::DeviceType::Button); | 325 | }, |
| 326 | InputCommon::Polling::DeviceType::AnalogPreferred); | ||
| 334 | }); | 327 | }); |
| 335 | connect(analog_button, &QPushButton::customContextMenuRequested, | ||
| 336 | [=, this](const QPoint& menu_location) { | ||
| 337 | QMenu context_menu; | ||
| 338 | context_menu.addAction(tr("Clear"), [&] { | ||
| 339 | analogs_param[analog_id].Erase(analog_sub_buttons[sub_button_id]); | ||
| 340 | analog_map_buttons[analog_id][sub_button_id]->setText(tr("[not set]")); | ||
| 341 | }); | ||
| 342 | context_menu.addAction(tr("Restore Default"), [&] { | ||
| 343 | Common::ParamPackage params{InputCommon::GenerateKeyboardParam( | ||
| 344 | Config::default_analogs[analog_id][sub_button_id])}; | ||
| 345 | SetAnalogButton(params, analogs_param[analog_id], | ||
| 346 | analog_sub_buttons[sub_button_id]); | ||
| 347 | analog_map_buttons[analog_id][sub_button_id]->setText(AnalogToText( | ||
| 348 | analogs_param[analog_id], analog_sub_buttons[sub_button_id])); | ||
| 349 | }); | ||
| 350 | context_menu.exec(analog_map_buttons[analog_id][sub_button_id]->mapToGlobal( | ||
| 351 | menu_location)); | ||
| 352 | }); | ||
| 353 | } | 328 | } |
| 354 | connect(analog_map_stick[analog_id], &QPushButton::clicked, [=, this] { | ||
| 355 | if (QMessageBox::information( | ||
| 356 | this, tr("Information"), | ||
| 357 | tr("After pressing OK, first move your joystick horizontally, " | ||
| 358 | "and then vertically."), | ||
| 359 | QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok) { | ||
| 360 | HandleClick(analog_map_stick[analog_id], | ||
| 361 | [=, this](const Common::ParamPackage& params) { | ||
| 362 | analogs_param[analog_id] = params; | ||
| 363 | }, | ||
| 364 | InputCommon::Polling::DeviceType::Analog); | ||
| 365 | } | ||
| 366 | }); | ||
| 367 | 329 | ||
| 368 | connect(analog_map_deadzone_and_modifier_slider[analog_id], &QSlider::valueChanged, | 330 | connect(analog_map_range_spinbox[analog_id], qOverload<int>(&QSpinBox::valueChanged), |
| 369 | [=, this] { | 331 | [=, this] { |
| 370 | const float slider_value = | 332 | const auto spinbox_value = analog_map_range_spinbox[analog_id]->value(); |
| 371 | analog_map_deadzone_and_modifier_slider[analog_id]->value(); | 333 | analogs_param[analog_id].Set("range", spinbox_value / 100.0f); |
| 372 | if (analogs_param[analog_id].Get("engine", "") == "sdl" || | ||
| 373 | analogs_param[analog_id].Get("engine", "") == "gcpad") { | ||
| 374 | analog_map_deadzone_and_modifier_slider_label[analog_id]->setText( | ||
| 375 | tr("Deadzone: %1%").arg(slider_value)); | ||
| 376 | analogs_param[analog_id].Set("deadzone", slider_value / 100.0f); | ||
| 377 | } else { | ||
| 378 | analog_map_deadzone_and_modifier_slider_label[analog_id]->setText( | ||
| 379 | tr("Modifier Scale: %1%").arg(slider_value)); | ||
| 380 | analogs_param[analog_id].Set("modifier_scale", slider_value / 100.0f); | ||
| 381 | } | ||
| 382 | }); | 334 | }); |
| 335 | |||
| 336 | connect(analog_map_deadzone_slider[analog_id], &QSlider::valueChanged, [=, this] { | ||
| 337 | const auto slider_value = analog_map_deadzone_slider[analog_id]->value(); | ||
| 338 | analog_map_deadzone_label[analog_id]->setText(tr("Deadzone: %1%").arg(slider_value)); | ||
| 339 | analogs_param[analog_id].Set("deadzone", slider_value / 100.0f); | ||
| 340 | }); | ||
| 341 | |||
| 342 | connect(analog_map_modifier_slider[analog_id], &QSlider::valueChanged, [=, this] { | ||
| 343 | const auto slider_value = analog_map_modifier_slider[analog_id]->value(); | ||
| 344 | analog_map_modifier_label[analog_id]->setText( | ||
| 345 | tr("Modifier Range: %1%").arg(slider_value)); | ||
| 346 | analogs_param[analog_id].Set("modifier_scale", slider_value / 100.0f); | ||
| 347 | }); | ||
| 383 | } | 348 | } |
| 384 | 349 | ||
| 385 | connect(ui->buttonClearAll, &QPushButton::clicked, [this] { ClearAll(); }); | 350 | // Player Connected checkbox |
| 386 | connect(ui->buttonRestoreDefaults, &QPushButton::clicked, [this] { RestoreDefaults(); }); | 351 | connect(ui->groupConnectedController, &QGroupBox::toggled, |
| 352 | [this](bool checked) { emit Connected(checked); }); | ||
| 353 | |||
| 354 | // Set up controller type. Only Player 1 can choose Handheld. | ||
| 355 | ui->comboControllerType->clear(); | ||
| 356 | |||
| 357 | QStringList controller_types = { | ||
| 358 | tr("Pro Controller"), | ||
| 359 | tr("Dual Joycons"), | ||
| 360 | tr("Left Joycon"), | ||
| 361 | tr("Right Joycon"), | ||
| 362 | }; | ||
| 363 | |||
| 364 | if (player_index == 0) { | ||
| 365 | controller_types.append(tr("Handheld")); | ||
| 366 | connect(ui->comboControllerType, qOverload<int>(&QComboBox::currentIndexChanged), | ||
| 367 | [this](int index) { | ||
| 368 | emit HandheldStateChanged(GetControllerTypeFromIndex(index) == | ||
| 369 | Settings::ControllerType::Handheld); | ||
| 370 | }); | ||
| 371 | } | ||
| 372 | |||
| 373 | // The Debug Controller can only choose the Pro Controller. | ||
| 374 | if (debug) { | ||
| 375 | ui->buttonScreenshot->setEnabled(false); | ||
| 376 | ui->buttonHome->setEnabled(false); | ||
| 377 | ui->groupConnectedController->setCheckable(false); | ||
| 378 | QStringList debug_controller_types = { | ||
| 379 | tr("Pro Controller"), | ||
| 380 | }; | ||
| 381 | ui->comboControllerType->addItems(debug_controller_types); | ||
| 382 | } else { | ||
| 383 | ui->comboControllerType->addItems(controller_types); | ||
| 384 | } | ||
| 385 | |||
| 386 | UpdateControllerIcon(); | ||
| 387 | UpdateControllerAvailableButtons(); | ||
| 388 | connect(ui->comboControllerType, qOverload<int>(&QComboBox::currentIndexChanged), [this](int) { | ||
| 389 | UpdateControllerIcon(); | ||
| 390 | UpdateControllerAvailableButtons(); | ||
| 391 | }); | ||
| 392 | |||
| 393 | connect(ui->comboDevices, qOverload<int>(&QComboBox::currentIndexChanged), this, | ||
| 394 | &ConfigureInputPlayer::UpdateMappingWithDefaults); | ||
| 395 | |||
| 396 | ui->buttonRefreshDevices->setIcon(QIcon::fromTheme(QStringLiteral("view-refresh"))); | ||
| 397 | UpdateInputDevices(); | ||
| 398 | connect(ui->buttonRefreshDevices, &QPushButton::clicked, | ||
| 399 | [this] { emit RefreshInputDevices(); }); | ||
| 387 | 400 | ||
| 388 | timeout_timer->setSingleShot(true); | 401 | timeout_timer->setSingleShot(true); |
| 389 | connect(timeout_timer.get(), &QTimer::timeout, [this] { SetPollingResult({}, true); }); | 402 | connect(timeout_timer.get(), &QTimer::timeout, [this] { SetPollingResult({}, true); }); |
| 390 | 403 | ||
| 391 | connect(poll_timer.get(), &QTimer::timeout, [this] { | 404 | connect(poll_timer.get(), &QTimer::timeout, [this] { |
| 392 | Common::ParamPackage params; | 405 | Common::ParamPackage params; |
| 393 | if (InputCommon::GetGCButtons()->IsPolling()) { | 406 | if (input_subsystem->GetGCButtons()->IsPolling()) { |
| 394 | params = InputCommon::GetGCButtons()->GetNextInput(); | 407 | params = input_subsystem->GetGCButtons()->GetNextInput(); |
| 395 | if (params.Has("engine")) { | 408 | if (params.Has("engine")) { |
| 396 | SetPollingResult(params, false); | 409 | SetPollingResult(params, false); |
| 397 | return; | 410 | return; |
| 398 | } | 411 | } |
| 399 | } | 412 | } |
| 400 | if (InputCommon::GetGCAnalogs()->IsPolling()) { | 413 | if (input_subsystem->GetGCAnalogs()->IsPolling()) { |
| 401 | params = InputCommon::GetGCAnalogs()->GetNextInput(); | 414 | params = input_subsystem->GetGCAnalogs()->GetNextInput(); |
| 402 | if (params.Has("engine")) { | 415 | if (params.Has("engine")) { |
| 403 | SetPollingResult(params, false); | 416 | SetPollingResult(params, false); |
| 404 | return; | 417 | return; |
| @@ -413,20 +426,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i | |||
| 413 | } | 426 | } |
| 414 | }); | 427 | }); |
| 415 | 428 | ||
| 416 | controller_color_buttons = { | ||
| 417 | ui->left_body_button, | ||
| 418 | ui->left_buttons_button, | ||
| 419 | ui->right_body_button, | ||
| 420 | ui->right_buttons_button, | ||
| 421 | }; | ||
| 422 | |||
| 423 | for (std::size_t i = 0; i < controller_color_buttons.size(); ++i) { | ||
| 424 | connect(controller_color_buttons[i], &QPushButton::clicked, this, | ||
| 425 | [this, i] { OnControllerButtonClick(static_cast<int>(i)); }); | ||
| 426 | } | ||
| 427 | |||
| 428 | LoadConfiguration(); | 429 | LoadConfiguration(); |
| 429 | resize(0, 0); | ||
| 430 | 430 | ||
| 431 | // TODO(wwylele): enable this when we actually emulate it | 431 | // TODO(wwylele): enable this when we actually emulate it |
| 432 | ui->buttonHome->setEnabled(false); | 432 | ui->buttonHome->setEnabled(false); |
| @@ -435,27 +435,43 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i | |||
| 435 | ConfigureInputPlayer::~ConfigureInputPlayer() = default; | 435 | ConfigureInputPlayer::~ConfigureInputPlayer() = default; |
| 436 | 436 | ||
| 437 | void ConfigureInputPlayer::ApplyConfiguration() { | 437 | void ConfigureInputPlayer::ApplyConfiguration() { |
| 438 | auto& buttons = | 438 | auto& player = Settings::values.players[player_index]; |
| 439 | debug ? Settings::values.debug_pad_buttons : Settings::values.players[player_index].buttons; | 439 | auto& buttons = debug ? Settings::values.debug_pad_buttons : player.buttons; |
| 440 | auto& analogs = | 440 | auto& analogs = debug ? Settings::values.debug_pad_analogs : player.analogs; |
| 441 | debug ? Settings::values.debug_pad_analogs : Settings::values.players[player_index].analogs; | ||
| 442 | 441 | ||
| 443 | std::transform(buttons_param.begin(), buttons_param.end(), buttons.begin(), | 442 | std::transform(buttons_param.begin(), buttons_param.end(), buttons.begin(), |
| 444 | [](const Common::ParamPackage& param) { return param.Serialize(); }); | 443 | [](const Common::ParamPackage& param) { return param.Serialize(); }); |
| 445 | std::transform(analogs_param.begin(), analogs_param.end(), analogs.begin(), | 444 | std::transform(analogs_param.begin(), analogs_param.end(), analogs.begin(), |
| 446 | [](const Common::ParamPackage& param) { return param.Serialize(); }); | 445 | [](const Common::ParamPackage& param) { return param.Serialize(); }); |
| 447 | 446 | ||
| 448 | if (debug) | 447 | if (debug) { |
| 448 | return; | ||
| 449 | } | ||
| 450 | |||
| 451 | player.controller_type = | ||
| 452 | static_cast<Settings::ControllerType>(ui->comboControllerType->currentIndex()); | ||
| 453 | player.connected = ui->groupConnectedController->isChecked(); | ||
| 454 | |||
| 455 | // Player 2-8 | ||
| 456 | if (player_index != 0) { | ||
| 457 | UpdateController(player.controller_type, player_index, player.connected); | ||
| 449 | return; | 458 | return; |
| 459 | } | ||
| 450 | 460 | ||
| 451 | std::array<u32, 4> colors{}; | 461 | // Player 1 and Handheld |
| 452 | std::transform(controller_colors.begin(), controller_colors.end(), colors.begin(), | 462 | auto& handheld = Settings::values.players[HANDHELD_INDEX]; |
| 453 | [](QColor color) { return color.rgb(); }); | 463 | // If Handheld is selected, copy all the settings from Player 1 to Handheld. |
| 464 | if (player.controller_type == Settings::ControllerType::Handheld) { | ||
| 465 | handheld = player; | ||
| 466 | handheld.connected = ui->groupConnectedController->isChecked(); | ||
| 467 | player.connected = false; // Disconnect Player 1 | ||
| 468 | } else { | ||
| 469 | player.connected = ui->groupConnectedController->isChecked(); | ||
| 470 | handheld.connected = false; // Disconnect Handheld | ||
| 471 | } | ||
| 454 | 472 | ||
| 455 | Settings::values.players[player_index].body_color_left = colors[0]; | 473 | UpdateController(player.controller_type, player_index, player.connected); |
| 456 | Settings::values.players[player_index].button_color_left = colors[1]; | 474 | UpdateController(Settings::ControllerType::Handheld, HANDHELD_INDEX, handheld.connected); |
| 457 | Settings::values.players[player_index].body_color_right = colors[2]; | ||
| 458 | Settings::values.players[player_index].button_color_right = colors[3]; | ||
| 459 | } | 475 | } |
| 460 | 476 | ||
| 461 | void ConfigureInputPlayer::changeEvent(QEvent* event) { | 477 | void ConfigureInputPlayer::changeEvent(QEvent* event) { |
| @@ -463,24 +479,16 @@ void ConfigureInputPlayer::changeEvent(QEvent* event) { | |||
| 463 | RetranslateUI(); | 479 | RetranslateUI(); |
| 464 | } | 480 | } |
| 465 | 481 | ||
| 466 | QDialog::changeEvent(event); | 482 | QWidget::changeEvent(event); |
| 467 | } | 483 | } |
| 468 | 484 | ||
| 469 | void ConfigureInputPlayer::RetranslateUI() { | 485 | void ConfigureInputPlayer::RetranslateUI() { |
| 470 | ui->retranslateUi(this); | 486 | ui->retranslateUi(this); |
| 471 | UpdateButtonLabels(); | 487 | UpdateUI(); |
| 472 | } | ||
| 473 | |||
| 474 | void ConfigureInputPlayer::OnControllerButtonClick(int i) { | ||
| 475 | const QColor new_bg_color = QColorDialog::getColor(controller_colors[i]); | ||
| 476 | if (!new_bg_color.isValid()) | ||
| 477 | return; | ||
| 478 | controller_colors[i] = new_bg_color; | ||
| 479 | controller_color_buttons[i]->setStyleSheet( | ||
| 480 | QStringLiteral("QPushButton { background-color: %1 }").arg(controller_colors[i].name())); | ||
| 481 | } | 488 | } |
| 482 | 489 | ||
| 483 | void ConfigureInputPlayer::LoadConfiguration() { | 490 | void ConfigureInputPlayer::LoadConfiguration() { |
| 491 | auto& player = Settings::values.players[player_index]; | ||
| 484 | if (debug) { | 492 | if (debug) { |
| 485 | std::transform(Settings::values.debug_pad_buttons.begin(), | 493 | std::transform(Settings::values.debug_pad_buttons.begin(), |
| 486 | Settings::values.debug_pad_buttons.end(), buttons_param.begin(), | 494 | Settings::values.debug_pad_buttons.end(), buttons_param.begin(), |
| @@ -489,56 +497,60 @@ void ConfigureInputPlayer::LoadConfiguration() { | |||
| 489 | Settings::values.debug_pad_analogs.end(), analogs_param.begin(), | 497 | Settings::values.debug_pad_analogs.end(), analogs_param.begin(), |
| 490 | [](const std::string& str) { return Common::ParamPackage(str); }); | 498 | [](const std::string& str) { return Common::ParamPackage(str); }); |
| 491 | } else { | 499 | } else { |
| 492 | std::transform(Settings::values.players[player_index].buttons.begin(), | 500 | std::transform(player.buttons.begin(), player.buttons.end(), buttons_param.begin(), |
| 493 | Settings::values.players[player_index].buttons.end(), buttons_param.begin(), | ||
| 494 | [](const std::string& str) { return Common::ParamPackage(str); }); | 501 | [](const std::string& str) { return Common::ParamPackage(str); }); |
| 495 | std::transform(Settings::values.players[player_index].analogs.begin(), | 502 | std::transform(player.analogs.begin(), player.analogs.end(), analogs_param.begin(), |
| 496 | Settings::values.players[player_index].analogs.end(), analogs_param.begin(), | ||
| 497 | [](const std::string& str) { return Common::ParamPackage(str); }); | 503 | [](const std::string& str) { return Common::ParamPackage(str); }); |
| 498 | } | 504 | } |
| 499 | 505 | ||
| 500 | UpdateButtonLabels(); | 506 | UpdateUI(); |
| 501 | 507 | ||
| 502 | if (debug) | 508 | if (debug) { |
| 503 | return; | 509 | return; |
| 510 | } | ||
| 504 | 511 | ||
| 505 | std::array<u32, 4> colors = { | 512 | ui->comboControllerType->setCurrentIndex(static_cast<int>(player.controller_type)); |
| 506 | Settings::values.players[player_index].body_color_left, | 513 | ui->groupConnectedController->setChecked( |
| 507 | Settings::values.players[player_index].button_color_left, | 514 | player.connected || |
| 508 | Settings::values.players[player_index].body_color_right, | 515 | (player_index == 0 && Settings::values.players[HANDHELD_INDEX].connected)); |
| 509 | Settings::values.players[player_index].button_color_right, | 516 | } |
| 510 | }; | ||
| 511 | |||
| 512 | std::transform(colors.begin(), colors.end(), controller_colors.begin(), | ||
| 513 | [](u32 rgb) { return QColor::fromRgb(rgb); }); | ||
| 514 | 517 | ||
| 515 | for (std::size_t i = 0; i < colors.size(); ++i) { | 518 | void ConfigureInputPlayer::UpdateInputDevices() { |
| 516 | controller_color_buttons[i]->setStyleSheet( | 519 | input_devices = input_subsystem->GetInputDevices(); |
| 517 | QStringLiteral("QPushButton { background-color: %1 }") | 520 | ui->comboDevices->clear(); |
| 518 | .arg(controller_colors[i].name())); | 521 | for (auto device : input_devices) { |
| 522 | ui->comboDevices->addItem(QString::fromStdString(device.Get("display", "Unknown")), {}); | ||
| 519 | } | 523 | } |
| 520 | } | 524 | } |
| 521 | 525 | ||
| 522 | void ConfigureInputPlayer::RestoreDefaults() { | 526 | void ConfigureInputPlayer::RestoreDefaults() { |
| 523 | for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; button_id++) { | 527 | // Reset Buttons |
| 528 | for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; ++button_id) { | ||
| 524 | buttons_param[button_id] = Common::ParamPackage{ | 529 | buttons_param[button_id] = Common::ParamPackage{ |
| 525 | InputCommon::GenerateKeyboardParam(Config::default_buttons[button_id])}; | 530 | InputCommon::GenerateKeyboardParam(Config::default_buttons[button_id])}; |
| 526 | } | 531 | } |
| 527 | 532 | ||
| 528 | for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; analog_id++) { | 533 | // Reset Modifier Buttons |
| 529 | for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; sub_button_id++) { | 534 | lstick_mod = |
| 535 | Common::ParamPackage(InputCommon::GenerateKeyboardParam(Config::default_stick_mod[0])); | ||
| 536 | rstick_mod = | ||
| 537 | Common::ParamPackage(InputCommon::GenerateKeyboardParam(Config::default_stick_mod[1])); | ||
| 538 | |||
| 539 | // Reset Analogs | ||
| 540 | for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; ++analog_id) { | ||
| 541 | for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; ++sub_button_id) { | ||
| 530 | Common::ParamPackage params{InputCommon::GenerateKeyboardParam( | 542 | Common::ParamPackage params{InputCommon::GenerateKeyboardParam( |
| 531 | Config::default_analogs[analog_id][sub_button_id])}; | 543 | Config::default_analogs[analog_id][sub_button_id])}; |
| 532 | SetAnalogButton(params, analogs_param[analog_id], analog_sub_buttons[sub_button_id]); | 544 | SetAnalogParam(params, analogs_param[analog_id], analog_sub_buttons[sub_button_id]); |
| 533 | } | 545 | } |
| 534 | } | 546 | } |
| 535 | 547 | UpdateUI(); | |
| 536 | UpdateButtonLabels(); | 548 | UpdateInputDevices(); |
| 537 | ApplyConfiguration(); | 549 | ui->comboControllerType->setCurrentIndex(0); |
| 538 | } | 550 | } |
| 539 | 551 | ||
| 540 | void ConfigureInputPlayer::ClearAll() { | 552 | void ConfigureInputPlayer::ClearAll() { |
| 541 | for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; button_id++) { | 553 | for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; ++button_id) { |
| 542 | const auto* const button = button_map[button_id]; | 554 | const auto* const button = button_map[button_id]; |
| 543 | if (button == nullptr || !button->isEnabled()) { | 555 | if (button == nullptr || !button->isEnabled()) { |
| 544 | continue; | 556 | continue; |
| @@ -547,8 +559,11 @@ void ConfigureInputPlayer::ClearAll() { | |||
| 547 | buttons_param[button_id].Clear(); | 559 | buttons_param[button_id].Clear(); |
| 548 | } | 560 | } |
| 549 | 561 | ||
| 550 | for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; analog_id++) { | 562 | lstick_mod.Clear(); |
| 551 | for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; sub_button_id++) { | 563 | rstick_mod.Clear(); |
| 564 | |||
| 565 | for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; ++analog_id) { | ||
| 566 | for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; ++sub_button_id) { | ||
| 552 | const auto* const analog_button = analog_map_buttons[analog_id][sub_button_id]; | 567 | const auto* const analog_button = analog_map_buttons[analog_id][sub_button_id]; |
| 553 | if (analog_button == nullptr || !analog_button->isEnabled()) { | 568 | if (analog_button == nullptr || !analog_button->isEnabled()) { |
| 554 | continue; | 569 | continue; |
| @@ -558,17 +573,20 @@ void ConfigureInputPlayer::ClearAll() { | |||
| 558 | } | 573 | } |
| 559 | } | 574 | } |
| 560 | 575 | ||
| 561 | UpdateButtonLabels(); | 576 | UpdateUI(); |
| 562 | ApplyConfiguration(); | 577 | UpdateInputDevices(); |
| 563 | } | 578 | } |
| 564 | 579 | ||
| 565 | void ConfigureInputPlayer::UpdateButtonLabels() { | 580 | void ConfigureInputPlayer::UpdateUI() { |
| 566 | for (int button = 0; button < Settings::NativeButton::NumButtons; button++) { | 581 | for (int button = 0; button < Settings::NativeButton::NumButtons; ++button) { |
| 567 | button_map[button]->setText(ButtonToText(buttons_param[button])); | 582 | button_map[button]->setText(ButtonToText(buttons_param[button])); |
| 568 | } | 583 | } |
| 569 | 584 | ||
| 570 | for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; analog_id++) { | 585 | ui->buttonLStickMod->setText(ButtonToText(lstick_mod)); |
| 571 | for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; sub_button_id++) { | 586 | ui->buttonRStickMod->setText(ButtonToText(rstick_mod)); |
| 587 | |||
| 588 | for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; ++analog_id) { | ||
| 589 | for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; ++sub_button_id) { | ||
| 572 | auto* const analog_button = analog_map_buttons[analog_id][sub_button_id]; | 590 | auto* const analog_button = analog_map_buttons[analog_id][sub_button_id]; |
| 573 | 591 | ||
| 574 | if (analog_button == nullptr) { | 592 | if (analog_button == nullptr) { |
| @@ -578,99 +596,141 @@ void ConfigureInputPlayer::UpdateButtonLabels() { | |||
| 578 | analog_button->setText( | 596 | analog_button->setText( |
| 579 | AnalogToText(analogs_param[analog_id], analog_sub_buttons[sub_button_id])); | 597 | AnalogToText(analogs_param[analog_id], analog_sub_buttons[sub_button_id])); |
| 580 | } | 598 | } |
| 581 | analog_map_stick[analog_id]->setText(tr("Set Analog Stick")); | ||
| 582 | 599 | ||
| 600 | const auto deadzone_label = analog_map_deadzone_label[analog_id]; | ||
| 601 | const auto deadzone_slider = analog_map_deadzone_slider[analog_id]; | ||
| 602 | const auto modifier_groupbox = analog_map_modifier_groupbox[analog_id]; | ||
| 603 | const auto modifier_label = analog_map_modifier_label[analog_id]; | ||
| 604 | const auto modifier_slider = analog_map_modifier_slider[analog_id]; | ||
| 605 | const auto range_groupbox = analog_map_range_groupbox[analog_id]; | ||
| 606 | const auto range_spinbox = analog_map_range_spinbox[analog_id]; | ||
| 607 | |||
| 608 | int slider_value; | ||
| 583 | auto& param = analogs_param[analog_id]; | 609 | auto& param = analogs_param[analog_id]; |
| 584 | auto* const analog_stick_slider = analog_map_deadzone_and_modifier_slider[analog_id]; | 610 | const bool is_controller = |
| 585 | auto* const analog_stick_slider_label = | 611 | param.Get("engine", "") == "sdl" || param.Get("engine", "") == "gcpad"; |
| 586 | analog_map_deadzone_and_modifier_slider_label[analog_id]; | 612 | |
| 587 | 613 | if (is_controller) { | |
| 588 | if (param.Has("engine")) { | 614 | if (!param.Has("deadzone")) { |
| 589 | if (param.Get("engine", "") == "sdl" || param.Get("engine", "") == "gcpad") { | 615 | param.Set("deadzone", 0.1f); |
| 590 | if (!param.Has("deadzone")) { | 616 | } |
| 591 | param.Set("deadzone", 0.1f); | 617 | slider_value = static_cast<int>(param.Get("deadzone", 0.1f) * 100); |
| 592 | } | 618 | deadzone_label->setText(tr("Deadzone: %1%").arg(slider_value)); |
| 593 | 619 | deadzone_slider->setValue(slider_value); | |
| 594 | analog_stick_slider->setValue(static_cast<int>(param.Get("deadzone", 0.1f) * 100)); | 620 | if (!param.Has("range")) { |
| 595 | if (analog_stick_slider->value() == 0) { | 621 | param.Set("range", 1.0f); |
| 596 | analog_stick_slider_label->setText(tr("Deadzone: 0%")); | 622 | } |
| 597 | } | 623 | range_spinbox->setValue(static_cast<int>(param.Get("range", 1.0f) * 100)); |
| 598 | } else { | 624 | } else { |
| 599 | if (!param.Has("modifier_scale")) { | 625 | if (!param.Has("modifier_scale")) { |
| 600 | param.Set("modifier_scale", 0.5f); | 626 | param.Set("modifier_scale", 0.5f); |
| 601 | } | ||
| 602 | |||
| 603 | analog_stick_slider->setValue( | ||
| 604 | static_cast<int>(param.Get("modifier_scale", 0.5f) * 100)); | ||
| 605 | if (analog_stick_slider->value() == 0) { | ||
| 606 | analog_stick_slider_label->setText(tr("Modifier Scale: 0%")); | ||
| 607 | } | ||
| 608 | } | 627 | } |
| 628 | slider_value = static_cast<int>(param.Get("modifier_scale", 0.5f) * 100); | ||
| 629 | modifier_label->setText(tr("Modifier Range: %1%").arg(slider_value)); | ||
| 630 | modifier_slider->setValue(slider_value); | ||
| 609 | } | 631 | } |
| 632 | |||
| 633 | deadzone_label->setVisible(is_controller); | ||
| 634 | deadzone_slider->setVisible(is_controller); | ||
| 635 | modifier_groupbox->setVisible(!is_controller); | ||
| 636 | modifier_label->setVisible(!is_controller); | ||
| 637 | modifier_slider->setVisible(!is_controller); | ||
| 638 | range_groupbox->setVisible(is_controller); | ||
| 610 | } | 639 | } |
| 611 | } | 640 | } |
| 612 | 641 | ||
| 642 | void ConfigureInputPlayer::UpdateMappingWithDefaults() { | ||
| 643 | if (ui->comboDevices->currentIndex() < 2) { | ||
| 644 | return; | ||
| 645 | } | ||
| 646 | const auto& device = input_devices[ui->comboDevices->currentIndex()]; | ||
| 647 | auto button_mapping = input_subsystem->GetButtonMappingForDevice(device); | ||
| 648 | auto analog_mapping = input_subsystem->GetAnalogMappingForDevice(device); | ||
| 649 | for (int i = 0; i < buttons_param.size(); ++i) { | ||
| 650 | buttons_param[i] = button_mapping[static_cast<Settings::NativeButton::Values>(i)]; | ||
| 651 | } | ||
| 652 | for (int i = 0; i < analogs_param.size(); ++i) { | ||
| 653 | analogs_param[i] = analog_mapping[static_cast<Settings::NativeAnalog::Values>(i)]; | ||
| 654 | } | ||
| 655 | |||
| 656 | UpdateUI(); | ||
| 657 | } | ||
| 658 | |||
| 613 | void ConfigureInputPlayer::HandleClick( | 659 | void ConfigureInputPlayer::HandleClick( |
| 614 | QPushButton* button, std::function<void(const Common::ParamPackage&)> new_input_setter, | 660 | QPushButton* button, std::function<void(const Common::ParamPackage&)> new_input_setter, |
| 615 | InputCommon::Polling::DeviceType type) { | 661 | InputCommon::Polling::DeviceType type) { |
| 616 | button->setText(tr("[press key]")); | 662 | button->setText(tr("[waiting]")); |
| 617 | button->setFocus(); | 663 | button->setFocus(); |
| 618 | 664 | ||
| 619 | // Keyboard keys can only be used as button devices | 665 | // The first two input devices are always Any and Keyboard/Mouse. If the user filtered to a |
| 620 | want_keyboard_keys = type == InputCommon::Polling::DeviceType::Button; | 666 | // controller, then they don't want keyboard/mouse input |
| 621 | if (want_keyboard_keys) { | 667 | want_keyboard_mouse = ui->comboDevices->currentIndex() < 2; |
| 622 | const auto iter = std::find(button_map.begin(), button_map.end(), button); | ||
| 623 | ASSERT(iter != button_map.end()); | ||
| 624 | const auto index = std::distance(button_map.begin(), iter); | ||
| 625 | ASSERT(index < Settings::NativeButton::NumButtons && index >= 0); | ||
| 626 | } | ||
| 627 | 668 | ||
| 628 | input_setter = new_input_setter; | 669 | input_setter = new_input_setter; |
| 629 | 670 | ||
| 630 | device_pollers = InputCommon::Polling::GetPollers(type); | 671 | device_pollers = input_subsystem->GetPollers(type); |
| 631 | 672 | ||
| 632 | for (auto& poller : device_pollers) { | 673 | for (auto& poller : device_pollers) { |
| 633 | poller->Start(); | 674 | poller->Start(); |
| 634 | } | 675 | } |
| 635 | 676 | ||
| 636 | grabKeyboard(); | 677 | QWidget::grabMouse(); |
| 637 | grabMouse(); | 678 | QWidget::grabKeyboard(); |
| 679 | |||
| 638 | if (type == InputCommon::Polling::DeviceType::Button) { | 680 | if (type == InputCommon::Polling::DeviceType::Button) { |
| 639 | InputCommon::GetGCButtons()->BeginConfiguration(); | 681 | input_subsystem->GetGCButtons()->BeginConfiguration(); |
| 640 | } else { | 682 | } else { |
| 641 | InputCommon::GetGCAnalogs()->BeginConfiguration(); | 683 | input_subsystem->GetGCAnalogs()->BeginConfiguration(); |
| 642 | } | 684 | } |
| 643 | timeout_timer->start(5000); // Cancel after 5 seconds | 685 | |
| 644 | poll_timer->start(200); // Check for new inputs every 200ms | 686 | timeout_timer->start(2500); // Cancel after 2.5 seconds |
| 687 | poll_timer->start(50); // Check for new inputs every 50ms | ||
| 645 | } | 688 | } |
| 646 | 689 | ||
| 647 | void ConfigureInputPlayer::SetPollingResult(const Common::ParamPackage& params, bool abort) { | 690 | void ConfigureInputPlayer::SetPollingResult(const Common::ParamPackage& params, bool abort) { |
| 648 | releaseKeyboard(); | ||
| 649 | releaseMouse(); | ||
| 650 | timeout_timer->stop(); | 691 | timeout_timer->stop(); |
| 651 | poll_timer->stop(); | 692 | poll_timer->stop(); |
| 652 | for (auto& poller : device_pollers) { | 693 | for (auto& poller : device_pollers) { |
| 653 | poller->Stop(); | 694 | poller->Stop(); |
| 654 | } | 695 | } |
| 655 | 696 | ||
| 656 | InputCommon::GetGCButtons()->EndConfiguration(); | 697 | QWidget::releaseMouse(); |
| 657 | InputCommon::GetGCAnalogs()->EndConfiguration(); | 698 | QWidget::releaseKeyboard(); |
| 699 | |||
| 700 | input_subsystem->GetGCButtons()->EndConfiguration(); | ||
| 701 | input_subsystem->GetGCAnalogs()->EndConfiguration(); | ||
| 658 | 702 | ||
| 659 | if (!abort) { | 703 | if (!abort) { |
| 660 | (*input_setter)(params); | 704 | (*input_setter)(params); |
| 661 | } | 705 | } |
| 662 | 706 | ||
| 663 | UpdateButtonLabels(); | 707 | UpdateUI(); |
| 664 | input_setter = std::nullopt; | 708 | input_setter = std::nullopt; |
| 665 | } | 709 | } |
| 666 | 710 | ||
| 711 | void ConfigureInputPlayer::mousePressEvent(QMouseEvent* event) { | ||
| 712 | if (!input_setter || !event) { | ||
| 713 | return; | ||
| 714 | } | ||
| 715 | |||
| 716 | if (want_keyboard_mouse) { | ||
| 717 | SetPollingResult(Common::ParamPackage{InputCommon::GenerateKeyboardParam(event->button())}, | ||
| 718 | false); | ||
| 719 | } else { | ||
| 720 | // We don't want any mouse buttons, so don't stop polling | ||
| 721 | return; | ||
| 722 | } | ||
| 723 | |||
| 724 | SetPollingResult({}, true); | ||
| 725 | } | ||
| 726 | |||
| 667 | void ConfigureInputPlayer::keyPressEvent(QKeyEvent* event) { | 727 | void ConfigureInputPlayer::keyPressEvent(QKeyEvent* event) { |
| 668 | if (!input_setter || !event) { | 728 | if (!input_setter || !event) { |
| 669 | return; | 729 | return; |
| 670 | } | 730 | } |
| 671 | 731 | ||
| 672 | if (event->key() != Qt::Key_Escape) { | 732 | if (event->key() != Qt::Key_Escape) { |
| 673 | if (want_keyboard_keys) { | 733 | if (want_keyboard_mouse) { |
| 674 | SetPollingResult(Common::ParamPackage{InputCommon::GenerateKeyboardParam(event->key())}, | 734 | SetPollingResult(Common::ParamPackage{InputCommon::GenerateKeyboardParam(event->key())}, |
| 675 | false); | 735 | false); |
| 676 | } else { | 736 | } else { |
| @@ -678,5 +738,108 @@ void ConfigureInputPlayer::keyPressEvent(QKeyEvent* event) { | |||
| 678 | return; | 738 | return; |
| 679 | } | 739 | } |
| 680 | } | 740 | } |
| 741 | |||
| 681 | SetPollingResult({}, true); | 742 | SetPollingResult({}, true); |
| 682 | } | 743 | } |
| 744 | |||
| 745 | void ConfigureInputPlayer::UpdateControllerIcon() { | ||
| 746 | // We aren't using Qt's built in theme support here since we aren't drawing an icon (and its | ||
| 747 | // "nonstandard" to use an image through the icon support) | ||
| 748 | const QString stylesheet = [this] { | ||
| 749 | switch (GetControllerTypeFromIndex(ui->comboControllerType->currentIndex())) { | ||
| 750 | case Settings::ControllerType::ProController: | ||
| 751 | return QStringLiteral("image: url(:/controller/pro_controller%0)"); | ||
| 752 | case Settings::ControllerType::DualJoyconDetached: | ||
| 753 | return QStringLiteral("image: url(:/controller/dual_joycon%0)"); | ||
| 754 | case Settings::ControllerType::LeftJoycon: | ||
| 755 | return QStringLiteral("image: url(:/controller/single_joycon_left_vertical%0)"); | ||
| 756 | case Settings::ControllerType::RightJoycon: | ||
| 757 | return QStringLiteral("image: url(:/controller/single_joycon_right_vertical%0)"); | ||
| 758 | case Settings::ControllerType::Handheld: | ||
| 759 | return QStringLiteral("image: url(:/controller/handheld%0)"); | ||
| 760 | default: | ||
| 761 | return QString{}; | ||
| 762 | } | ||
| 763 | }(); | ||
| 764 | |||
| 765 | const QString theme = [this] { | ||
| 766 | if (QIcon::themeName().contains(QStringLiteral("dark"))) { | ||
| 767 | return QStringLiteral("_dark"); | ||
| 768 | } else if (QIcon::themeName().contains(QStringLiteral("midnight"))) { | ||
| 769 | return QStringLiteral("_midnight"); | ||
| 770 | } else { | ||
| 771 | return QString{}; | ||
| 772 | } | ||
| 773 | }(); | ||
| 774 | |||
| 775 | ui->controllerFrame->setStyleSheet(stylesheet.arg(theme)); | ||
| 776 | } | ||
| 777 | |||
| 778 | void ConfigureInputPlayer::UpdateControllerAvailableButtons() { | ||
| 779 | auto layout = GetControllerTypeFromIndex(ui->comboControllerType->currentIndex()); | ||
| 780 | if (debug) { | ||
| 781 | layout = Settings::ControllerType::ProController; | ||
| 782 | } | ||
| 783 | |||
| 784 | // List of all the widgets that will be hidden by any of the following layouts that need | ||
| 785 | // "unhidden" after the controller type changes | ||
| 786 | const std::array<QWidget*, 9> layout_show = { | ||
| 787 | ui->buttonShoulderButtonsSLSR, | ||
| 788 | ui->horizontalSpacerShoulderButtonsWidget, | ||
| 789 | ui->horizontalSpacerShoulderButtonsWidget2, | ||
| 790 | ui->buttonShoulderButtonsLeft, | ||
| 791 | ui->buttonMiscButtonsMinusScreenshot, | ||
| 792 | ui->bottomLeft, | ||
| 793 | ui->buttonShoulderButtonsRight, | ||
| 794 | ui->buttonMiscButtonsPlusHome, | ||
| 795 | ui->bottomRight, | ||
| 796 | }; | ||
| 797 | |||
| 798 | for (auto* widget : layout_show) { | ||
| 799 | widget->show(); | ||
| 800 | } | ||
| 801 | |||
| 802 | std::vector<QWidget*> layout_hidden; | ||
| 803 | switch (layout) { | ||
| 804 | case Settings::ControllerType::ProController: | ||
| 805 | case Settings::ControllerType::DualJoyconDetached: | ||
| 806 | case Settings::ControllerType::Handheld: | ||
| 807 | layout_hidden = { | ||
| 808 | ui->buttonShoulderButtonsSLSR, | ||
| 809 | ui->horizontalSpacerShoulderButtonsWidget2, | ||
| 810 | }; | ||
| 811 | break; | ||
| 812 | case Settings::ControllerType::LeftJoycon: | ||
| 813 | layout_hidden = { | ||
| 814 | ui->horizontalSpacerShoulderButtonsWidget2, | ||
| 815 | ui->buttonShoulderButtonsRight, | ||
| 816 | ui->buttonMiscButtonsPlusHome, | ||
| 817 | ui->bottomRight, | ||
| 818 | }; | ||
| 819 | break; | ||
| 820 | case Settings::ControllerType::RightJoycon: | ||
| 821 | layout_hidden = { | ||
| 822 | ui->horizontalSpacerShoulderButtonsWidget, | ||
| 823 | ui->buttonShoulderButtonsLeft, | ||
| 824 | ui->buttonMiscButtonsMinusScreenshot, | ||
| 825 | ui->bottomLeft, | ||
| 826 | }; | ||
| 827 | break; | ||
| 828 | } | ||
| 829 | |||
| 830 | for (auto* widget : layout_hidden) { | ||
| 831 | widget->hide(); | ||
| 832 | } | ||
| 833 | } | ||
| 834 | |||
| 835 | void ConfigureInputPlayer::showEvent(QShowEvent* event) { | ||
| 836 | if (bottom_row == nullptr) { | ||
| 837 | return; | ||
| 838 | } | ||
| 839 | QWidget::showEvent(event); | ||
| 840 | ui->main->addWidget(bottom_row); | ||
| 841 | } | ||
| 842 | |||
| 843 | void ConfigureInputPlayer::ConnectPlayer(bool connected) { | ||
| 844 | ui->groupConnectedController->setChecked(connected); | ||
| 845 | } | ||
diff --git a/src/yuzu/configuration/configure_input_player.h b/src/yuzu/configuration/configure_input_player.h index 95afa5375..a25bc3bd9 100644 --- a/src/yuzu/configuration/configure_input_player.h +++ b/src/yuzu/configuration/configure_input_player.h | |||
| @@ -10,16 +10,25 @@ | |||
| 10 | #include <optional> | 10 | #include <optional> |
| 11 | #include <string> | 11 | #include <string> |
| 12 | 12 | ||
| 13 | #include <QDialog> | 13 | #include <QWidget> |
| 14 | 14 | ||
| 15 | #include "common/param_package.h" | 15 | #include "common/param_package.h" |
| 16 | #include "core/settings.h" | 16 | #include "core/settings.h" |
| 17 | #include "ui_configure_input.h" | 17 | #include "ui_configure_input.h" |
| 18 | 18 | ||
| 19 | class QCheckBox; | ||
| 19 | class QKeyEvent; | 20 | class QKeyEvent; |
| 21 | class QLabel; | ||
| 20 | class QPushButton; | 22 | class QPushButton; |
| 23 | class QSlider; | ||
| 24 | class QSpinBox; | ||
| 21 | class QString; | 25 | class QString; |
| 22 | class QTimer; | 26 | class QTimer; |
| 27 | class QWidget; | ||
| 28 | |||
| 29 | namespace InputCommon { | ||
| 30 | class InputSubsystem; | ||
| 31 | } | ||
| 23 | 32 | ||
| 24 | namespace InputCommon::Polling { | 33 | namespace InputCommon::Polling { |
| 25 | class DevicePoller; | 34 | class DevicePoller; |
| @@ -30,77 +39,116 @@ namespace Ui { | |||
| 30 | class ConfigureInputPlayer; | 39 | class ConfigureInputPlayer; |
| 31 | } | 40 | } |
| 32 | 41 | ||
| 33 | class ConfigureInputPlayer : public QDialog { | 42 | class ConfigureInputPlayer : public QWidget { |
| 34 | Q_OBJECT | 43 | Q_OBJECT |
| 35 | 44 | ||
| 36 | public: | 45 | public: |
| 37 | explicit ConfigureInputPlayer(QWidget* parent, std::size_t player_index, bool debug = false); | 46 | explicit ConfigureInputPlayer(QWidget* parent, std::size_t player_index, QWidget* bottom_row, |
| 47 | InputCommon::InputSubsystem* input_subsystem_, | ||
| 48 | bool debug = false); | ||
| 38 | ~ConfigureInputPlayer() override; | 49 | ~ConfigureInputPlayer() override; |
| 39 | 50 | ||
| 40 | /// Save all button configurations to settings file | 51 | /// Save all button configurations to settings file. |
| 41 | void ApplyConfiguration(); | 52 | void ApplyConfiguration(); |
| 42 | 53 | ||
| 54 | /// Update the input devices combobox. | ||
| 55 | void UpdateInputDevices(); | ||
| 56 | |||
| 57 | /// Restore all buttons to their default values. | ||
| 58 | void RestoreDefaults(); | ||
| 59 | |||
| 60 | /// Clear all input configuration. | ||
| 61 | void ClearAll(); | ||
| 62 | |||
| 63 | /// Set the connection state checkbox (used to sync state). | ||
| 64 | void ConnectPlayer(bool connected); | ||
| 65 | |||
| 66 | signals: | ||
| 67 | /// Emitted when this controller is connected by the user. | ||
| 68 | void Connected(bool connected); | ||
| 69 | /// Emitted when the Handheld mode is selected (undocked with dual joycons attached). | ||
| 70 | void HandheldStateChanged(bool is_handheld); | ||
| 71 | /// Emitted when the input devices combobox is being refreshed. | ||
| 72 | void RefreshInputDevices(); | ||
| 73 | |||
| 74 | protected: | ||
| 75 | void showEvent(QShowEvent* event) override; | ||
| 76 | |||
| 43 | private: | 77 | private: |
| 44 | void changeEvent(QEvent* event) override; | 78 | void changeEvent(QEvent* event) override; |
| 45 | void RetranslateUI(); | 79 | void RetranslateUI(); |
| 46 | 80 | ||
| 47 | void OnControllerButtonClick(int i); | ||
| 48 | |||
| 49 | /// Load configuration settings. | 81 | /// Load configuration settings. |
| 50 | void LoadConfiguration(); | 82 | void LoadConfiguration(); |
| 51 | /// Restore all buttons to their default values. | ||
| 52 | void RestoreDefaults(); | ||
| 53 | /// Clear all input configuration | ||
| 54 | void ClearAll(); | ||
| 55 | |||
| 56 | /// Update UI to reflect current configuration. | ||
| 57 | void UpdateButtonLabels(); | ||
| 58 | 83 | ||
| 59 | /// Called when the button was pressed. | 84 | /// Called when the button was pressed. |
| 60 | void HandleClick(QPushButton* button, | 85 | void HandleClick(QPushButton* button, |
| 61 | std::function<void(const Common::ParamPackage&)> new_input_setter, | 86 | std::function<void(const Common::ParamPackage&)> new_input_setter, |
| 62 | InputCommon::Polling::DeviceType type); | 87 | InputCommon::Polling::DeviceType type); |
| 63 | 88 | ||
| 64 | /// Finish polling and configure input using the input_setter | 89 | /// Finish polling and configure input using the input_setter. |
| 65 | void SetPollingResult(const Common::ParamPackage& params, bool abort); | 90 | void SetPollingResult(const Common::ParamPackage& params, bool abort); |
| 66 | 91 | ||
| 92 | /// Handle mouse button press events. | ||
| 93 | void mousePressEvent(QMouseEvent* event) override; | ||
| 94 | |||
| 67 | /// Handle key press events. | 95 | /// Handle key press events. |
| 68 | void keyPressEvent(QKeyEvent* event) override; | 96 | void keyPressEvent(QKeyEvent* event) override; |
| 69 | 97 | ||
| 98 | /// Update UI to reflect current configuration. | ||
| 99 | void UpdateUI(); | ||
| 100 | |||
| 101 | /// Update the controller selection combobox | ||
| 102 | void UpdateControllerCombobox(); | ||
| 103 | |||
| 104 | /// Update the current controller icon. | ||
| 105 | void UpdateControllerIcon(); | ||
| 106 | |||
| 107 | /// Hides and disables controller settings based on the current controller type. | ||
| 108 | void UpdateControllerAvailableButtons(); | ||
| 109 | |||
| 110 | /// Gets the default controller mapping for this device and auto configures the input to match. | ||
| 111 | void UpdateMappingWithDefaults(); | ||
| 112 | |||
| 70 | std::unique_ptr<Ui::ConfigureInputPlayer> ui; | 113 | std::unique_ptr<Ui::ConfigureInputPlayer> ui; |
| 71 | 114 | ||
| 72 | std::size_t player_index; | 115 | std::size_t player_index; |
| 73 | bool debug; | 116 | bool debug; |
| 74 | 117 | ||
| 118 | InputCommon::InputSubsystem* input_subsystem; | ||
| 119 | |||
| 75 | std::unique_ptr<QTimer> timeout_timer; | 120 | std::unique_ptr<QTimer> timeout_timer; |
| 76 | std::unique_ptr<QTimer> poll_timer; | 121 | std::unique_ptr<QTimer> poll_timer; |
| 77 | 122 | ||
| 123 | static constexpr int PLAYER_COUNT = 8; | ||
| 124 | std::array<QCheckBox*, PLAYER_COUNT> player_connected_checkbox; | ||
| 125 | |||
| 78 | /// This will be the the setting function when an input is awaiting configuration. | 126 | /// This will be the the setting function when an input is awaiting configuration. |
| 79 | std::optional<std::function<void(const Common::ParamPackage&)>> input_setter; | 127 | std::optional<std::function<void(const Common::ParamPackage&)>> input_setter; |
| 80 | 128 | ||
| 81 | std::array<Common::ParamPackage, Settings::NativeButton::NumButtons> buttons_param; | 129 | std::array<Common::ParamPackage, Settings::NativeButton::NumButtons> buttons_param; |
| 82 | std::array<Common::ParamPackage, Settings::NativeAnalog::NumAnalogs> analogs_param; | 130 | std::array<Common::ParamPackage, Settings::NativeAnalog::NumAnalogs> analogs_param; |
| 83 | 131 | ||
| 84 | static constexpr int ANALOG_SUB_BUTTONS_NUM = 5; | 132 | static constexpr int ANALOG_SUB_BUTTONS_NUM = 4; |
| 85 | 133 | ||
| 86 | /// Each button input is represented by a QPushButton. | 134 | /// Each button input is represented by a QPushButton. |
| 87 | std::array<QPushButton*, Settings::NativeButton::NumButtons> button_map; | 135 | std::array<QPushButton*, Settings::NativeButton::NumButtons> button_map; |
| 136 | /// Extra buttons for the modifiers. | ||
| 137 | Common::ParamPackage lstick_mod; | ||
| 138 | Common::ParamPackage rstick_mod; | ||
| 88 | 139 | ||
| 89 | std::vector<QWidget*> debug_hidden; | 140 | /// A group of four QPushButtons represent one analog input. The buttons each represent up, |
| 90 | std::vector<QWidget*> layout_hidden; | 141 | /// down, left, right, respectively. |
| 91 | |||
| 92 | /// A group of five QPushButtons represent one analog input. The buttons each represent up, | ||
| 93 | /// down, left, right, and modifier, respectively. | ||
| 94 | std::array<std::array<QPushButton*, ANALOG_SUB_BUTTONS_NUM>, Settings::NativeAnalog::NumAnalogs> | 142 | std::array<std::array<QPushButton*, ANALOG_SUB_BUTTONS_NUM>, Settings::NativeAnalog::NumAnalogs> |
| 95 | analog_map_buttons; | 143 | analog_map_buttons; |
| 96 | 144 | ||
| 97 | /// Analog inputs are also represented each with a single button, used to configure with an | 145 | std::array<QLabel*, Settings::NativeAnalog::NumAnalogs> analog_map_deadzone_label; |
| 98 | /// actual analog stick | 146 | std::array<QSlider*, Settings::NativeAnalog::NumAnalogs> analog_map_deadzone_slider; |
| 99 | std::array<QPushButton*, Settings::NativeAnalog::NumAnalogs> analog_map_stick; | 147 | std::array<QGroupBox*, Settings::NativeAnalog::NumAnalogs> analog_map_modifier_groupbox; |
| 100 | std::array<QSlider*, Settings::NativeAnalog::NumAnalogs> | 148 | std::array<QLabel*, Settings::NativeAnalog::NumAnalogs> analog_map_modifier_label; |
| 101 | analog_map_deadzone_and_modifier_slider; | 149 | std::array<QSlider*, Settings::NativeAnalog::NumAnalogs> analog_map_modifier_slider; |
| 102 | std::array<QLabel*, Settings::NativeAnalog::NumAnalogs> | 150 | std::array<QGroupBox*, Settings::NativeAnalog::NumAnalogs> analog_map_range_groupbox; |
| 103 | analog_map_deadzone_and_modifier_slider_label; | 151 | std::array<QSpinBox*, Settings::NativeAnalog::NumAnalogs> analog_map_range_spinbox; |
| 104 | 152 | ||
| 105 | static const std::array<std::string, ANALOG_SUB_BUTTONS_NUM> analog_sub_buttons; | 153 | static const std::array<std::string, ANALOG_SUB_BUTTONS_NUM> analog_sub_buttons; |
| 106 | 154 | ||
| @@ -108,8 +156,14 @@ private: | |||
| 108 | 156 | ||
| 109 | /// A flag to indicate if keyboard keys are okay when configuring an input. If this is false, | 157 | /// A flag to indicate if keyboard keys are okay when configuring an input. If this is false, |
| 110 | /// keyboard events are ignored. | 158 | /// keyboard events are ignored. |
| 111 | bool want_keyboard_keys = false; | 159 | bool want_keyboard_mouse = false; |
| 160 | |||
| 161 | /// List of physical devices users can map with. If a SDL backed device is selected, then you | ||
| 162 | /// can usue this device to get a default mapping. | ||
| 163 | std::vector<Common::ParamPackage> input_devices; | ||
| 112 | 164 | ||
| 113 | std::array<QPushButton*, 4> controller_color_buttons; | 165 | /// Bottom row is where console wide settings are held, and its "owned" by the parent |
| 114 | std::array<QColor, 4> controller_colors; | 166 | /// ConfigureInput widget. On show, add this widget to the main layout. This will change the |
| 167 | /// parent of the widget to this widget (but thats fine). | ||
| 168 | QWidget* bottom_row; | ||
| 115 | }; | 169 | }; |
diff --git a/src/yuzu/configuration/configure_input_player.ui b/src/yuzu/configuration/configure_input_player.ui index f27a77180..9bc681894 100644 --- a/src/yuzu/configuration/configure_input_player.ui +++ b/src/yuzu/configuration/configure_input_player.ui | |||
| @@ -1,1243 +1,2974 @@ | |||
| 1 | <?xml version="1.0" encoding="UTF-8"?> | 1 | <?xml version="1.0" encoding="UTF-8"?> |
| 2 | <ui version="4.0"> | 2 | <ui version="4.0"> |
| 3 | <class>ConfigureInputPlayer</class> | 3 | <class>ConfigureInputPlayer</class> |
| 4 | <widget class="QDialog" name="ConfigureInputPlayer"> | 4 | <widget class="QWidget" name="ConfigureInputPlayer"> |
| 5 | <property name="geometry"> | 5 | <property name="geometry"> |
| 6 | <rect> | 6 | <rect> |
| 7 | <x>0</x> | 7 | <x>0</x> |
| 8 | <y>0</y> | 8 | <y>0</y> |
| 9 | <width>408</width> | 9 | <width>780</width> |
| 10 | <height>731</height> | 10 | <height>487</height> |
| 11 | </rect> | 11 | </rect> |
| 12 | </property> | 12 | </property> |
| 13 | <property name="windowTitle"> | 13 | <property name="windowTitle"> |
| 14 | <string>Configure Input</string> | 14 | <string>Configure Input</string> |
| 15 | </property> | 15 | </property> |
| 16 | <layout class="QVBoxLayout" name="verticalLayout_5"> | 16 | <layout class="QHBoxLayout" name="horizontalLayout_2"> |
| 17 | <property name="spacing"> | ||
| 18 | <number>0</number> | ||
| 19 | </property> | ||
| 20 | <property name="leftMargin"> | ||
| 21 | <number>0</number> | ||
| 22 | </property> | ||
| 23 | <property name="topMargin"> | ||
| 24 | <number>0</number> | ||
| 25 | </property> | ||
| 26 | <property name="rightMargin"> | ||
| 27 | <number>0</number> | ||
| 28 | </property> | ||
| 29 | <property name="bottomMargin"> | ||
| 30 | <number>0</number> | ||
| 31 | </property> | ||
| 17 | <item> | 32 | <item> |
| 18 | <layout class="QGridLayout" name="buttons"> | 33 | <layout class="QVBoxLayout" name="main"> |
| 19 | <item row="1" column="1"> | 34 | <property name="spacing"> |
| 20 | <widget class="QGroupBox" name="RStick"> | 35 | <number>0</number> |
| 21 | <property name="title"> | 36 | </property> |
| 22 | <string>Right Stick</string> | 37 | <property name="leftMargin"> |
| 23 | </property> | 38 | <number>0</number> |
| 24 | <property name="alignment"> | 39 | </property> |
| 25 | <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> | 40 | <property name="topMargin"> |
| 26 | </property> | 41 | <number>0</number> |
| 27 | <property name="flat"> | 42 | </property> |
| 28 | <bool>false</bool> | 43 | <property name="rightMargin"> |
| 44 | <number>0</number> | ||
| 45 | </property> | ||
| 46 | <property name="bottomMargin"> | ||
| 47 | <number>0</number> | ||
| 48 | </property> | ||
| 49 | <item> | ||
| 50 | <layout class="QHBoxLayout" name="top" stretch="0,1,2"> | ||
| 51 | <property name="spacing"> | ||
| 52 | <number>3</number> | ||
| 29 | </property> | 53 | </property> |
| 30 | <property name="checkable"> | 54 | <property name="topMargin"> |
| 31 | <bool>false</bool> | 55 | <number>0</number> |
| 32 | </property> | 56 | </property> |
| 33 | <layout class="QGridLayout" name="gridLayout_5"> | 57 | <item> |
| 34 | <item row="1" column="1"> | 58 | <widget class="QGroupBox" name="groupConnectedController"> |
| 35 | <layout class="QVBoxLayout" name="buttonRStickDownVerticalLayout"> | 59 | <property name="layoutDirection"> |
| 60 | <enum>Qt::LeftToRight</enum> | ||
| 61 | </property> | ||
| 62 | <property name="title"> | ||
| 63 | <string>Connect Controller</string> | ||
| 64 | </property> | ||
| 65 | <property name="flat"> | ||
| 66 | <bool>false</bool> | ||
| 67 | </property> | ||
| 68 | <property name="checkable"> | ||
| 69 | <bool>true</bool> | ||
| 70 | </property> | ||
| 71 | <layout class="QHBoxLayout" name="horizontalLayout_3"> | ||
| 72 | <property name="leftMargin"> | ||
| 73 | <number>5</number> | ||
| 74 | </property> | ||
| 75 | <property name="topMargin"> | ||
| 76 | <number>5</number> | ||
| 77 | </property> | ||
| 78 | <property name="rightMargin"> | ||
| 79 | <number>5</number> | ||
| 80 | </property> | ||
| 81 | <property name="bottomMargin"> | ||
| 82 | <number>5</number> | ||
| 83 | </property> | ||
| 36 | <item> | 84 | <item> |
| 37 | <layout class="QHBoxLayout" name="buttonRStickDownHorizontalLayout"> | 85 | <widget class="QComboBox" name="comboControllerType"> |
| 38 | <item> | 86 | <item> |
| 39 | <widget class="QLabel" name="labelRStickDown"> | 87 | <property name="text"> |
| 40 | <property name="text"> | 88 | <string>Pro Controller</string> |
| 41 | <string>Down:</string> | 89 | </property> |
| 42 | </property> | ||
| 43 | </widget> | ||
| 44 | </item> | 90 | </item> |
| 45 | </layout> | ||
| 46 | </item> | ||
| 47 | <item> | ||
| 48 | <widget class="QPushButton" name="buttonRStickDown"> | ||
| 49 | <property name="text"> | ||
| 50 | <string/> | ||
| 51 | </property> | ||
| 52 | </widget> | ||
| 53 | </item> | ||
| 54 | </layout> | ||
| 55 | </item> | ||
| 56 | <item row="0" column="1"> | ||
| 57 | <layout class="QVBoxLayout" name="buttonRStickRightVerticalLayout"> | ||
| 58 | <item> | ||
| 59 | <layout class="QHBoxLayout" name="buttonRStickRightHorizontalLayout"> | ||
| 60 | <item> | 91 | <item> |
| 61 | <widget class="QLabel" name="labelRStickRight"> | 92 | <property name="text"> |
| 62 | <property name="text"> | 93 | <string>Dual Joycons</string> |
| 63 | <string>Right:</string> | 94 | </property> |
| 64 | </property> | ||
| 65 | </widget> | ||
| 66 | </item> | 95 | </item> |
| 67 | </layout> | ||
| 68 | </item> | ||
| 69 | <item> | ||
| 70 | <widget class="QPushButton" name="buttonRStickRight"> | ||
| 71 | <property name="text"> | ||
| 72 | <string/> | ||
| 73 | </property> | ||
| 74 | </widget> | ||
| 75 | </item> | ||
| 76 | </layout> | ||
| 77 | </item> | ||
| 78 | <item row="3" column="0" colspan="2"> | ||
| 79 | <widget class="QPushButton" name="buttonRStickAnalog"> | ||
| 80 | <property name="text"> | ||
| 81 | <string>Set Analog Stick</string> | ||
| 82 | </property> | ||
| 83 | </widget> | ||
| 84 | </item> | ||
| 85 | <item row="0" column="0"> | ||
| 86 | <layout class="QVBoxLayout" name="buttonRStickLeftVerticalLayout"> | ||
| 87 | <item> | ||
| 88 | <layout class="QHBoxLayout" name="buttonRStickLeftHorizontalLayout"> | ||
| 89 | <item> | 96 | <item> |
| 90 | <widget class="QLabel" name="labelRStickLeft"> | 97 | <property name="text"> |
| 91 | <property name="text"> | 98 | <string>Left Joycon</string> |
| 92 | <string>Left:</string> | 99 | </property> |
| 93 | </property> | ||
| 94 | </widget> | ||
| 95 | </item> | 100 | </item> |
| 96 | </layout> | ||
| 97 | </item> | ||
| 98 | <item> | ||
| 99 | <widget class="QPushButton" name="buttonRStickLeft"> | ||
| 100 | <property name="text"> | ||
| 101 | <string/> | ||
| 102 | </property> | ||
| 103 | </widget> | ||
| 104 | </item> | ||
| 105 | </layout> | ||
| 106 | </item> | ||
| 107 | <item row="1" column="0"> | ||
| 108 | <layout class="QVBoxLayout" name="buttonRStickUpVerticalLayout"> | ||
| 109 | <item> | ||
| 110 | <layout class="QHBoxLayout" name="buttonRStickUpHorizontalLayout"> | ||
| 111 | <item> | 101 | <item> |
| 112 | <widget class="QLabel" name="labelRStickUp"> | 102 | <property name="text"> |
| 113 | <property name="text"> | 103 | <string>Right Joycon</string> |
| 114 | <string>Up:</string> | 104 | </property> |
| 115 | </property> | ||
| 116 | </widget> | ||
| 117 | </item> | 105 | </item> |
| 118 | </layout> | ||
| 119 | </item> | ||
| 120 | <item> | ||
| 121 | <widget class="QPushButton" name="buttonRStickUp"> | ||
| 122 | <property name="text"> | ||
| 123 | <string/> | ||
| 124 | </property> | ||
| 125 | </widget> | ||
| 126 | </item> | ||
| 127 | </layout> | ||
| 128 | </item> | ||
| 129 | <item row="2" column="0"> | ||
| 130 | <layout class="QVBoxLayout" name="buttonRStickPressedVerticalLayout"> | ||
| 131 | <item> | ||
| 132 | <layout class="QHBoxLayout" name="buttonRStickPressedHorizontalLayout"> | ||
| 133 | <item> | 106 | <item> |
| 134 | <widget class="QLabel" name="labelRStickPressed"> | 107 | <property name="text"> |
| 135 | <property name="text"> | 108 | <string>Handheld</string> |
| 136 | <string>Pressed:</string> | 109 | </property> |
| 137 | </property> | ||
| 138 | </widget> | ||
| 139 | </item> | 110 | </item> |
| 140 | </layout> | ||
| 141 | </item> | ||
| 142 | <item> | ||
| 143 | <widget class="QPushButton" name="buttonRStick"> | ||
| 144 | <property name="text"> | ||
| 145 | <string/> | ||
| 146 | </property> | ||
| 147 | </widget> | 111 | </widget> |
| 148 | </item> | 112 | </item> |
| 149 | </layout> | 113 | </layout> |
| 150 | </item> | 114 | </widget> |
| 151 | <item row="2" column="1"> | 115 | </item> |
| 152 | <layout class="QVBoxLayout" name="buttonRStickModVerticalLayout"> | 116 | <item> |
| 117 | <widget class="QGroupBox" name="devicesGroup"> | ||
| 118 | <property name="title"> | ||
| 119 | <string>Input Device</string> | ||
| 120 | </property> | ||
| 121 | <layout class="QHBoxLayout" name="horizontalLayout_5"> | ||
| 122 | <property name="spacing"> | ||
| 123 | <number>3</number> | ||
| 124 | </property> | ||
| 125 | <property name="leftMargin"> | ||
| 126 | <number>5</number> | ||
| 127 | </property> | ||
| 128 | <property name="topMargin"> | ||
| 129 | <number>5</number> | ||
| 130 | </property> | ||
| 131 | <property name="rightMargin"> | ||
| 132 | <number>5</number> | ||
| 133 | </property> | ||
| 134 | <property name="bottomMargin"> | ||
| 135 | <number>5</number> | ||
| 136 | </property> | ||
| 153 | <item> | 137 | <item> |
| 154 | <layout class="QHBoxLayout" name="buttonRStickModHorizontalLayout"> | 138 | <widget class="QComboBox" name="comboDevices"> |
| 155 | <item> | 139 | <item> |
| 156 | <widget class="QLabel" name="labelRStickMod"> | 140 | <property name="text"> |
| 157 | <property name="text"> | 141 | <string>Any</string> |
| 158 | <string>Modifier:</string> | 142 | </property> |
| 159 | </property> | ||
| 160 | </widget> | ||
| 161 | </item> | 143 | </item> |
| 162 | </layout> | ||
| 163 | </item> | ||
| 164 | <item> | ||
| 165 | <widget class="QPushButton" name="buttonRStickMod"> | ||
| 166 | <property name="text"> | ||
| 167 | <string/> | ||
| 168 | </property> | ||
| 169 | </widget> | ||
| 170 | </item> | ||
| 171 | </layout> | ||
| 172 | </item> | ||
| 173 | <item row="4" column="0" colspan="2"> | ||
| 174 | <layout class="QVBoxLayout" name="sliderRStickDeadzoneAndModifierVerticalLayout"> | ||
| 175 | <item> | ||
| 176 | <layout class="QHBoxLayout" name="sliderRStickDeadzoneAndModifierHorizontalLayout"> | ||
| 177 | <item> | 144 | <item> |
| 178 | <widget class="QLabel" name="labelRStickDeadzoneAndModifier"> | 145 | <property name="text"> |
| 179 | <property name="text"> | 146 | <string>Keyboard/Mouse</string> |
| 180 | <string>Deadzone: 0</string> | 147 | </property> |
| 181 | </property> | ||
| 182 | <property name="alignment"> | ||
| 183 | <enum>Qt::AlignHCenter</enum> | ||
| 184 | </property> | ||
| 185 | </widget> | ||
| 186 | </item> | 148 | </item> |
| 187 | </layout> | 149 | </widget> |
| 188 | </item> | 150 | </item> |
| 189 | <item> | 151 | <item> |
| 190 | <widget class="QSlider" name="sliderRStickDeadzoneAndModifier"> | 152 | <widget class="QPushButton" name="buttonRefreshDevices"> |
| 191 | <property name="orientation"> | 153 | <property name="minimumSize"> |
| 192 | <enum>Qt::Horizontal</enum> | 154 | <size> |
| 155 | <width>24</width> | ||
| 156 | <height>22</height> | ||
| 157 | </size> | ||
| 158 | </property> | ||
| 159 | <property name="maximumSize"> | ||
| 160 | <size> | ||
| 161 | <width>24</width> | ||
| 162 | <height>22</height> | ||
| 163 | </size> | ||
| 164 | </property> | ||
| 165 | <property name="styleSheet"> | ||
| 166 | <string notr="true"/> | ||
| 193 | </property> | 167 | </property> |
| 194 | </widget> | 168 | </widget> |
| 195 | </item> | 169 | </item> |
| 196 | </layout> | 170 | </layout> |
| 197 | </item> | 171 | </widget> |
| 198 | <item row="5" column="0"> | 172 | </item> |
| 199 | <spacer name="RStick_verticalSpacer"> | 173 | <item> |
| 200 | <property name="orientation"> | 174 | <widget class="QGroupBox" name="profilesGroup"> |
| 201 | <enum>Qt::Vertical</enum> | 175 | <property name="minimumSize"> |
| 176 | <size> | ||
| 177 | <width>0</width> | ||
| 178 | <height>0</height> | ||
| 179 | </size> | ||
| 180 | </property> | ||
| 181 | <property name="title"> | ||
| 182 | <string>Profile</string> | ||
| 183 | </property> | ||
| 184 | <layout class="QHBoxLayout" name="horizontalLayout_4" stretch="2,0,0,0"> | ||
| 185 | <property name="spacing"> | ||
| 186 | <number>3</number> | ||
| 202 | </property> | 187 | </property> |
| 203 | <property name="sizeHint" stdset="0"> | 188 | <property name="leftMargin"> |
| 204 | <size> | 189 | <number>5</number> |
| 205 | <width>0</width> | 190 | </property> |
| 206 | <height>0</height> | 191 | <property name="topMargin"> |
| 207 | </size> | 192 | <number>5</number> |
| 193 | </property> | ||
| 194 | <property name="rightMargin"> | ||
| 195 | <number>5</number> | ||
| 196 | </property> | ||
| 197 | <property name="bottomMargin"> | ||
| 198 | <number>5</number> | ||
| 208 | </property> | 199 | </property> |
| 209 | </spacer> | ||
| 210 | </item> | ||
| 211 | </layout> | ||
| 212 | </widget> | ||
| 213 | </item> | ||
| 214 | <item row="0" column="1"> | ||
| 215 | <widget class="QGroupBox" name="Dpad"> | ||
| 216 | <property name="title"> | ||
| 217 | <string>Directional Pad</string> | ||
| 218 | </property> | ||
| 219 | <property name="flat"> | ||
| 220 | <bool>false</bool> | ||
| 221 | </property> | ||
| 222 | <property name="checkable"> | ||
| 223 | <bool>false</bool> | ||
| 224 | </property> | ||
| 225 | <layout class="QGridLayout" name="gridLayout_2"> | ||
| 226 | <item row="1" column="0"> | ||
| 227 | <layout class="QVBoxLayout" name="buttonDpadUpVerticalLayout"> | ||
| 228 | <item> | 200 | <item> |
| 229 | <layout class="QHBoxLayout" name="buttonDpadUpHorizontalLayout"> | 201 | <widget class="QComboBox" name="comboProfiles"/> |
| 230 | <item> | ||
| 231 | <widget class="QLabel" name="labelDpadUp"> | ||
| 232 | <property name="text"> | ||
| 233 | <string>Up:</string> | ||
| 234 | </property> | ||
| 235 | </widget> | ||
| 236 | </item> | ||
| 237 | </layout> | ||
| 238 | </item> | 202 | </item> |
| 239 | <item> | 203 | <item> |
| 240 | <widget class="QPushButton" name="buttonDpadUp"> | 204 | <widget class="QPushButton" name="buttonProfilesSave"> |
| 241 | <property name="text"> | 205 | <property name="maximumSize"> |
| 242 | <string/> | 206 | <size> |
| 207 | <width>55</width> | ||
| 208 | <height>16777215</height> | ||
| 209 | </size> | ||
| 210 | </property> | ||
| 211 | <property name="styleSheet"> | ||
| 212 | <string notr="true">min-width: 55px;</string> | ||
| 243 | </property> | 213 | </property> |
| 244 | </widget> | ||
| 245 | </item> | ||
| 246 | </layout> | ||
| 247 | </item> | ||
| 248 | <item row="1" column="1"> | ||
| 249 | <layout class="QVBoxLayout" name="buttonDpadDownVerticalLayout"> | ||
| 250 | <item> | ||
| 251 | <layout class="QHBoxLayout" name="buttonDpadDownHorizontalLayout"> | ||
| 252 | <item> | ||
| 253 | <widget class="QLabel" name="labelDpadDown"> | ||
| 254 | <property name="text"> | ||
| 255 | <string>Down:</string> | ||
| 256 | </property> | ||
| 257 | </widget> | ||
| 258 | </item> | ||
| 259 | </layout> | ||
| 260 | </item> | ||
| 261 | <item> | ||
| 262 | <widget class="QPushButton" name="buttonDpadDown"> | ||
| 263 | <property name="text"> | 214 | <property name="text"> |
| 264 | <string/> | 215 | <string>Save</string> |
| 265 | </property> | 216 | </property> |
| 266 | </widget> | 217 | </widget> |
| 267 | </item> | 218 | </item> |
| 268 | </layout> | ||
| 269 | </item> | ||
| 270 | <item row="0" column="0"> | ||
| 271 | <layout class="QVBoxLayout" name="buttonDpadLeftVerticalLayout"> | ||
| 272 | <item> | ||
| 273 | <layout class="QHBoxLayout" name="buttonDpadLeftHorizontalLayout"> | ||
| 274 | <item> | ||
| 275 | <widget class="QLabel" name="labelDpadLeft"> | ||
| 276 | <property name="minimumSize"> | ||
| 277 | <size> | ||
| 278 | <width>80</width> | ||
| 279 | <height>0</height> | ||
| 280 | </size> | ||
| 281 | </property> | ||
| 282 | <property name="text"> | ||
| 283 | <string>Left:</string> | ||
| 284 | </property> | ||
| 285 | </widget> | ||
| 286 | </item> | ||
| 287 | </layout> | ||
| 288 | </item> | ||
| 289 | <item> | 219 | <item> |
| 290 | <widget class="QPushButton" name="buttonDpadLeft"> | 220 | <widget class="QPushButton" name="buttonProfilesNew"> |
| 221 | <property name="maximumSize"> | ||
| 222 | <size> | ||
| 223 | <width>55</width> | ||
| 224 | <height>16777215</height> | ||
| 225 | </size> | ||
| 226 | </property> | ||
| 227 | <property name="styleSheet"> | ||
| 228 | <string notr="true">min-width: 55px;</string> | ||
| 229 | </property> | ||
| 291 | <property name="text"> | 230 | <property name="text"> |
| 292 | <string/> | 231 | <string>New</string> |
| 293 | </property> | 232 | </property> |
| 294 | </widget> | 233 | </widget> |
| 295 | </item> | 234 | </item> |
| 296 | </layout> | ||
| 297 | </item> | ||
| 298 | <item row="0" column="1"> | ||
| 299 | <layout class="QVBoxLayout" name="buttonDpadRightVerticalLayout"> | ||
| 300 | <item> | ||
| 301 | <layout class="QHBoxLayout" name="buttonDpadRightHorizontalLayout"> | ||
| 302 | <item> | ||
| 303 | <widget class="QLabel" name="labelDpadRight"> | ||
| 304 | <property name="minimumSize"> | ||
| 305 | <size> | ||
| 306 | <width>80</width> | ||
| 307 | <height>0</height> | ||
| 308 | </size> | ||
| 309 | </property> | ||
| 310 | <property name="text"> | ||
| 311 | <string>Right:</string> | ||
| 312 | </property> | ||
| 313 | </widget> | ||
| 314 | </item> | ||
| 315 | </layout> | ||
| 316 | </item> | ||
| 317 | <item> | 235 | <item> |
| 318 | <widget class="QPushButton" name="buttonDpadRight"> | 236 | <widget class="QPushButton" name="buttonProfilesDelete"> |
| 237 | <property name="maximumSize"> | ||
| 238 | <size> | ||
| 239 | <width>55</width> | ||
| 240 | <height>16777215</height> | ||
| 241 | </size> | ||
| 242 | </property> | ||
| 243 | <property name="styleSheet"> | ||
| 244 | <string notr="true">min-width: 55px;</string> | ||
| 245 | </property> | ||
| 319 | <property name="text"> | 246 | <property name="text"> |
| 320 | <string/> | 247 | <string>Delete</string> |
| 321 | </property> | 248 | </property> |
| 322 | </widget> | 249 | </widget> |
| 323 | </item> | 250 | </item> |
| 324 | </layout> | 251 | </layout> |
| 325 | </item> | 252 | </widget> |
| 326 | </layout> | 253 | </item> |
| 327 | </widget> | 254 | </layout> |
| 328 | </item> | 255 | </item> |
| 329 | <item row="0" column="0"> | 256 | <item> |
| 330 | <widget class="QGroupBox" name="faceButtons"> | 257 | <widget class="QFrame" name="bottom"> |
| 331 | <property name="title"> | 258 | <property name="sizePolicy"> |
| 332 | <string>Face Buttons</string> | 259 | <sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding"> |
| 333 | </property> | 260 | <horstretch>0</horstretch> |
| 334 | <property name="flat"> | 261 | <verstretch>0</verstretch> |
| 335 | <bool>false</bool> | 262 | </sizepolicy> |
| 336 | </property> | ||
| 337 | <property name="checkable"> | ||
| 338 | <bool>false</bool> | ||
| 339 | </property> | 263 | </property> |
| 340 | <layout class="QGridLayout" name="gridLayout"> | 264 | <layout class="QHBoxLayout" name="_2"> |
| 341 | <item row="0" column="0"> | 265 | <property name="sizeConstraint"> |
| 342 | <layout class="QVBoxLayout" name="buttonFaceButtonsAVerticalLayout"> | 266 | <enum>QLayout::SetMinimumSize</enum> |
| 343 | <item> | 267 | </property> |
| 344 | <layout class="QHBoxLayout" name="buttonFaceButtonsAHorizontalLayout"> | 268 | <property name="leftMargin"> |
| 345 | <item> | 269 | <number>0</number> |
| 346 | <widget class="QLabel" name="labelA"> | 270 | </property> |
| 347 | <property name="minimumSize"> | 271 | <property name="topMargin"> |
| 348 | <size> | 272 | <number>0</number> |
| 349 | <width>80</width> | 273 | </property> |
| 350 | <height>0</height> | 274 | <property name="rightMargin"> |
| 351 | </size> | 275 | <number>0</number> |
| 276 | </property> | ||
| 277 | <property name="bottomMargin"> | ||
| 278 | <number>0</number> | ||
| 279 | </property> | ||
| 280 | <item> | ||
| 281 | <widget class="QWidget" name="bottomLeft" native="true"> | ||
| 282 | <layout class="QVBoxLayout" name="bottomLeftLayout" stretch="0,0,0,0"> | ||
| 283 | <property name="spacing"> | ||
| 284 | <number>0</number> | ||
| 285 | </property> | ||
| 286 | <property name="sizeConstraint"> | ||
| 287 | <enum>QLayout::SetDefaultConstraint</enum> | ||
| 288 | </property> | ||
| 289 | <property name="leftMargin"> | ||
| 290 | <number>0</number> | ||
| 291 | </property> | ||
| 292 | <property name="topMargin"> | ||
| 293 | <number>0</number> | ||
| 294 | </property> | ||
| 295 | <property name="rightMargin"> | ||
| 296 | <number>0</number> | ||
| 297 | </property> | ||
| 298 | <property name="bottomMargin"> | ||
| 299 | <number>0</number> | ||
| 300 | </property> | ||
| 301 | <item> | ||
| 302 | <widget class="QGroupBox" name="LStick"> | ||
| 303 | <property name="sizePolicy"> | ||
| 304 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 305 | <horstretch>0</horstretch> | ||
| 306 | <verstretch>0</verstretch> | ||
| 307 | </sizepolicy> | ||
| 308 | </property> | ||
| 309 | <property name="title"> | ||
| 310 | <string>Left Stick</string> | ||
| 311 | </property> | ||
| 312 | <property name="alignment"> | ||
| 313 | <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> | ||
| 314 | </property> | ||
| 315 | <layout class="QVBoxLayout" name="verticalLayout_3"> | ||
| 316 | <property name="spacing"> | ||
| 317 | <number>0</number> | ||
| 352 | </property> | 318 | </property> |
| 353 | <property name="text"> | 319 | <property name="sizeConstraint"> |
| 354 | <string>A:</string> | 320 | <enum>QLayout::SetDefaultConstraint</enum> |
| 355 | </property> | 321 | </property> |
| 356 | </widget> | 322 | <property name="leftMargin"> |
| 357 | </item> | 323 | <number>3</number> |
| 358 | </layout> | ||
| 359 | </item> | ||
| 360 | <item> | ||
| 361 | <widget class="QPushButton" name="buttonA"> | ||
| 362 | <property name="text"> | ||
| 363 | <string/> | ||
| 364 | </property> | ||
| 365 | </widget> | ||
| 366 | </item> | ||
| 367 | </layout> | ||
| 368 | </item> | ||
| 369 | <item row="0" column="1"> | ||
| 370 | <layout class="QVBoxLayout" name="buttonFaceButtonsBVerticalLayout"> | ||
| 371 | <item> | ||
| 372 | <layout class="QHBoxLayout" name="buttonFaceButtonsBHorizontalLayout"> | ||
| 373 | <item> | ||
| 374 | <widget class="QLabel" name="labelB"> | ||
| 375 | <property name="minimumSize"> | ||
| 376 | <size> | ||
| 377 | <width>80</width> | ||
| 378 | <height>0</height> | ||
| 379 | </size> | ||
| 380 | </property> | 324 | </property> |
| 381 | <property name="text"> | 325 | <property name="topMargin"> |
| 382 | <string>B:</string> | 326 | <number>0</number> |
| 383 | </property> | 327 | </property> |
| 384 | </widget> | 328 | <property name="rightMargin"> |
| 385 | </item> | 329 | <number>3</number> |
| 386 | </layout> | ||
| 387 | </item> | ||
| 388 | <item> | ||
| 389 | <widget class="QPushButton" name="buttonB"> | ||
| 390 | <property name="text"> | ||
| 391 | <string/> | ||
| 392 | </property> | ||
| 393 | </widget> | ||
| 394 | </item> | ||
| 395 | </layout> | ||
| 396 | </item> | ||
| 397 | <item row="1" column="0"> | ||
| 398 | <layout class="QVBoxLayout" name="buttonFaceButtonsXVerticalLayout"> | ||
| 399 | <item> | ||
| 400 | <layout class="QHBoxLayout" name="buttonFaceButtonsXHorizontalLayout"> | ||
| 401 | <item> | ||
| 402 | <widget class="QLabel" name="labelX"> | ||
| 403 | <property name="text"> | ||
| 404 | <string>X:</string> | ||
| 405 | </property> | 330 | </property> |
| 406 | </widget> | 331 | <property name="bottomMargin"> |
| 407 | </item> | 332 | <number>0</number> |
| 408 | </layout> | ||
| 409 | </item> | ||
| 410 | <item> | ||
| 411 | <widget class="QPushButton" name="buttonX"> | ||
| 412 | <property name="text"> | ||
| 413 | <string/> | ||
| 414 | </property> | ||
| 415 | </widget> | ||
| 416 | </item> | ||
| 417 | </layout> | ||
| 418 | </item> | ||
| 419 | <item row="1" column="1"> | ||
| 420 | <layout class="QVBoxLayout" name="buttonFaceButtonsYVerticalLayout"> | ||
| 421 | <item> | ||
| 422 | <layout class="QHBoxLayout" name="buttonFaceButtonsYHorizontalLayout"> | ||
| 423 | <item> | ||
| 424 | <widget class="QLabel" name="labelY"> | ||
| 425 | <property name="text"> | ||
| 426 | <string>Y:</string> | ||
| 427 | </property> | 333 | </property> |
| 428 | </widget> | 334 | <item> |
| 429 | </item> | 335 | <widget class="QWidget" name="buttonLStickUpWidget" native="true"> |
| 430 | </layout> | 336 | <layout class="QHBoxLayout" name="horizontalLayout_20"> |
| 431 | </item> | 337 | <property name="spacing"> |
| 432 | <item> | 338 | <number>0</number> |
| 433 | <widget class="QPushButton" name="buttonY"> | 339 | </property> |
| 434 | <property name="text"> | 340 | <property name="leftMargin"> |
| 435 | <string/> | 341 | <number>0</number> |
| 436 | </property> | 342 | </property> |
| 437 | </widget> | 343 | <property name="topMargin"> |
| 438 | </item> | 344 | <number>0</number> |
| 439 | </layout> | 345 | </property> |
| 440 | </item> | 346 | <property name="rightMargin"> |
| 441 | </layout> | 347 | <number>0</number> |
| 442 | </widget> | 348 | </property> |
| 443 | </item> | 349 | <property name="bottomMargin"> |
| 444 | <item row="5" column="0" colspan="2"> | 350 | <number>0</number> |
| 445 | <widget class="QGroupBox" name="controller_color"> | 351 | </property> |
| 446 | <property name="title"> | 352 | <item> |
| 447 | <string>Controller Color</string> | 353 | <spacer name="horizontalSpacerLStickUpLeft"> |
| 448 | </property> | 354 | <property name="orientation"> |
| 449 | <layout class="QGridLayout" name="gridLayout_10" columnstretch="0,0,0,0,0,0,0"> | 355 | <enum>Qt::Horizontal</enum> |
| 450 | <item row="0" column="0"> | 356 | </property> |
| 451 | <spacer name="horizontalSpacer_2"> | 357 | <property name="sizeHint" stdset="0"> |
| 452 | <property name="orientation"> | 358 | <size> |
| 453 | <enum>Qt::Horizontal</enum> | 359 | <width>20</width> |
| 454 | </property> | 360 | <height>20</height> |
| 455 | <property name="sizeHint" stdset="0"> | 361 | </size> |
| 456 | <size> | 362 | </property> |
| 457 | <width>40</width> | 363 | </spacer> |
| 458 | <height>20</height> | 364 | </item> |
| 459 | </size> | 365 | <item alignment="Qt::AlignHCenter"> |
| 460 | </property> | 366 | <widget class="QGroupBox" name="buttonLStickUpGroup"> |
| 461 | </spacer> | 367 | <property name="title"> |
| 462 | </item> | 368 | <string>Up</string> |
| 463 | <item row="0" column="1"> | 369 | </property> |
| 464 | <widget class="QLabel" name="left_body_label"> | 370 | <property name="alignment"> |
| 465 | <property name="text"> | 371 | <set>Qt::AlignCenter</set> |
| 466 | <string>Left Body</string> | 372 | </property> |
| 467 | </property> | 373 | <property name="flat"> |
| 468 | </widget> | 374 | <bool>false</bool> |
| 469 | </item> | 375 | </property> |
| 470 | <item row="0" column="6"> | 376 | <layout class="QVBoxLayout" name="buttonLStickUpVerticalLayout"> |
| 471 | <spacer name="horizontalSpacer_3"> | 377 | <property name="spacing"> |
| 472 | <property name="orientation"> | 378 | <number>3</number> |
| 473 | <enum>Qt::Horizontal</enum> | 379 | </property> |
| 474 | </property> | 380 | <property name="leftMargin"> |
| 475 | <property name="sizeHint" stdset="0"> | 381 | <number>3</number> |
| 476 | <size> | 382 | </property> |
| 477 | <width>40</width> | 383 | <property name="topMargin"> |
| 478 | <height>20</height> | 384 | <number>3</number> |
| 479 | </size> | 385 | </property> |
| 480 | </property> | 386 | <property name="rightMargin"> |
| 481 | </spacer> | 387 | <number>3</number> |
| 482 | </item> | 388 | </property> |
| 483 | <item row="1" column="1"> | 389 | <property name="bottomMargin"> |
| 484 | <widget class="QLabel" name="left_buttons_label"> | 390 | <number>3</number> |
| 485 | <property name="minimumSize"> | 391 | </property> |
| 486 | <size> | 392 | <item> |
| 487 | <width>90</width> | 393 | <widget class="QPushButton" name="buttonLStickUp"> |
| 488 | <height>0</height> | 394 | <property name="minimumSize"> |
| 489 | </size> | 395 | <size> |
| 490 | </property> | 396 | <width>57</width> |
| 491 | <property name="text"> | 397 | <height>0</height> |
| 492 | <string>Left Buttons</string> | 398 | </size> |
| 493 | </property> | 399 | </property> |
| 494 | </widget> | 400 | <property name="maximumSize"> |
| 495 | </item> | 401 | <size> |
| 496 | <item row="1" column="5"> | 402 | <width>55</width> |
| 497 | <widget class="QPushButton" name="right_buttons_button"> | 403 | <height>16777215</height> |
| 498 | <property name="sizePolicy"> | 404 | </size> |
| 499 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | 405 | </property> |
| 500 | <horstretch>0</horstretch> | 406 | <property name="styleSheet"> |
| 501 | <verstretch>0</verstretch> | 407 | <string notr="true">min-width: 55px;</string> |
| 502 | </sizepolicy> | 408 | </property> |
| 503 | </property> | 409 | <property name="text"> |
| 504 | <property name="minimumSize"> | 410 | <string>Up</string> |
| 505 | <size> | 411 | </property> |
| 506 | <width>32</width> | 412 | </widget> |
| 507 | <height>0</height> | 413 | </item> |
| 508 | </size> | 414 | </layout> |
| 509 | </property> | 415 | </widget> |
| 510 | <property name="maximumSize"> | 416 | </item> |
| 511 | <size> | 417 | <item> |
| 512 | <width>40</width> | 418 | <spacer name="horizontalSpacerLStickUpRight"> |
| 513 | <height>16777215</height> | 419 | <property name="orientation"> |
| 514 | </size> | 420 | <enum>Qt::Horizontal</enum> |
| 515 | </property> | 421 | </property> |
| 516 | <property name="text"> | 422 | <property name="sizeHint" stdset="0"> |
| 517 | <string/> | 423 | <size> |
| 518 | </property> | 424 | <width>20</width> |
| 519 | </widget> | 425 | <height>20</height> |
| 520 | </item> | 426 | </size> |
| 521 | <item row="0" column="4"> | 427 | </property> |
| 522 | <widget class="QLabel" name="right_body_label"> | 428 | </spacer> |
| 523 | <property name="text"> | 429 | </item> |
| 524 | <string>Right Body</string> | 430 | </layout> |
| 525 | </property> | 431 | </widget> |
| 526 | </widget> | 432 | </item> |
| 527 | </item> | 433 | <item> |
| 528 | <item row="1" column="4"> | 434 | <layout class="QHBoxLayout" name="buttonLStickLeftRightHorizontaLayout"> |
| 529 | <widget class="QLabel" name="right_buttons_label"> | 435 | <property name="spacing"> |
| 530 | <property name="minimumSize"> | 436 | <number>3</number> |
| 531 | <size> | 437 | </property> |
| 532 | <width>90</width> | 438 | <item alignment="Qt::AlignHCenter"> |
| 533 | <height>0</height> | 439 | <widget class="QGroupBox" name="buttonLStickLeftGroup"> |
| 534 | </size> | 440 | <property name="title"> |
| 535 | </property> | 441 | <string>Left</string> |
| 536 | <property name="text"> | 442 | </property> |
| 537 | <string>Right Buttons</string> | 443 | <property name="alignment"> |
| 538 | </property> | 444 | <set>Qt::AlignCenter</set> |
| 539 | </widget> | 445 | </property> |
| 540 | </item> | 446 | <layout class="QVBoxLayout" name="buttonLStickLeftVerticalLayout"> |
| 541 | <item row="1" column="2"> | 447 | <property name="spacing"> |
| 542 | <widget class="QPushButton" name="left_buttons_button"> | 448 | <number>3</number> |
| 543 | <property name="sizePolicy"> | 449 | </property> |
| 544 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | 450 | <property name="leftMargin"> |
| 545 | <horstretch>0</horstretch> | 451 | <number>3</number> |
| 546 | <verstretch>0</verstretch> | 452 | </property> |
| 547 | </sizepolicy> | 453 | <property name="topMargin"> |
| 548 | </property> | 454 | <number>3</number> |
| 549 | <property name="minimumSize"> | 455 | </property> |
| 550 | <size> | 456 | <property name="rightMargin"> |
| 551 | <width>32</width> | 457 | <number>3</number> |
| 552 | <height>0</height> | 458 | </property> |
| 553 | </size> | 459 | <property name="bottomMargin"> |
| 554 | </property> | 460 | <number>3</number> |
| 555 | <property name="maximumSize"> | 461 | </property> |
| 556 | <size> | 462 | <item> |
| 557 | <width>40</width> | 463 | <widget class="QPushButton" name="buttonLStickLeft"> |
| 558 | <height>16777215</height> | 464 | <property name="minimumSize"> |
| 559 | </size> | 465 | <size> |
| 560 | </property> | 466 | <width>57</width> |
| 561 | <property name="text"> | 467 | <height>0</height> |
| 562 | <string/> | 468 | </size> |
| 563 | </property> | 469 | </property> |
| 564 | </widget> | 470 | <property name="maximumSize"> |
| 565 | </item> | 471 | <size> |
| 566 | <item row="0" column="2"> | 472 | <width>55</width> |
| 567 | <widget class="QPushButton" name="left_body_button"> | 473 | <height>16777215</height> |
| 568 | <property name="sizePolicy"> | 474 | </size> |
| 569 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | 475 | </property> |
| 570 | <horstretch>0</horstretch> | 476 | <property name="styleSheet"> |
| 571 | <verstretch>0</verstretch> | 477 | <string notr="true">min-width: 55px;</string> |
| 572 | </sizepolicy> | 478 | </property> |
| 573 | </property> | 479 | <property name="text"> |
| 574 | <property name="minimumSize"> | 480 | <string>Left</string> |
| 575 | <size> | 481 | </property> |
| 576 | <width>32</width> | 482 | </widget> |
| 577 | <height>0</height> | 483 | </item> |
| 578 | </size> | 484 | </layout> |
| 579 | </property> | 485 | </widget> |
| 580 | <property name="maximumSize"> | 486 | </item> |
| 581 | <size> | 487 | <item alignment="Qt::AlignHCenter"> |
| 582 | <width>40</width> | 488 | <widget class="QGroupBox" name="buttonLStickRightGroup"> |
| 583 | <height>16777215</height> | 489 | <property name="title"> |
| 584 | </size> | 490 | <string>Right</string> |
| 585 | </property> | 491 | </property> |
| 586 | <property name="text"> | 492 | <property name="alignment"> |
| 587 | <string/> | 493 | <set>Qt::AlignCenter</set> |
| 588 | </property> | 494 | </property> |
| 589 | </widget> | 495 | <layout class="QVBoxLayout" name="buttonLStickRightVerticalLayout"> |
| 590 | </item> | 496 | <property name="spacing"> |
| 591 | <item row="0" column="5"> | 497 | <number>3</number> |
| 592 | <widget class="QPushButton" name="right_body_button"> | 498 | </property> |
| 593 | <property name="sizePolicy"> | 499 | <property name="leftMargin"> |
| 594 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | 500 | <number>3</number> |
| 595 | <horstretch>0</horstretch> | 501 | </property> |
| 596 | <verstretch>0</verstretch> | 502 | <property name="topMargin"> |
| 597 | </sizepolicy> | 503 | <number>3</number> |
| 598 | </property> | 504 | </property> |
| 599 | <property name="minimumSize"> | 505 | <property name="rightMargin"> |
| 600 | <size> | 506 | <number>3</number> |
| 601 | <width>32</width> | 507 | </property> |
| 602 | <height>0</height> | 508 | <property name="bottomMargin"> |
| 603 | </size> | 509 | <number>3</number> |
| 604 | </property> | 510 | </property> |
| 605 | <property name="maximumSize"> | 511 | <item> |
| 606 | <size> | 512 | <widget class="QPushButton" name="buttonLStickRight"> |
| 607 | <width>40</width> | 513 | <property name="minimumSize"> |
| 608 | <height>16777215</height> | 514 | <size> |
| 609 | </size> | 515 | <width>57</width> |
| 610 | </property> | 516 | <height>0</height> |
| 611 | <property name="text"> | 517 | </size> |
| 612 | <string/> | 518 | </property> |
| 613 | </property> | 519 | <property name="maximumSize"> |
| 614 | </widget> | 520 | <size> |
| 615 | </item> | 521 | <width>55</width> |
| 616 | <item row="0" column="3"> | 522 | <height>16777215</height> |
| 617 | <spacer name="horizontalSpacer_4"> | 523 | </size> |
| 618 | <property name="orientation"> | 524 | </property> |
| 619 | <enum>Qt::Horizontal</enum> | 525 | <property name="styleSheet"> |
| 620 | </property> | 526 | <string notr="true">min-width: 55px;</string> |
| 621 | <property name="sizeType"> | 527 | </property> |
| 622 | <enum>QSizePolicy::Fixed</enum> | 528 | <property name="text"> |
| 623 | </property> | 529 | <string>Right</string> |
| 624 | <property name="sizeHint" stdset="0"> | 530 | </property> |
| 625 | <size> | 531 | </widget> |
| 626 | <width>20</width> | 532 | </item> |
| 627 | <height>20</height> | 533 | </layout> |
| 628 | </size> | 534 | </widget> |
| 629 | </property> | 535 | </item> |
| 630 | </spacer> | 536 | </layout> |
| 631 | </item> | 537 | </item> |
| 632 | </layout> | 538 | <item> |
| 633 | </widget> | 539 | <widget class="QWidget" name="buttonLStickDownWidget" native="true"> |
| 634 | </item> | 540 | <layout class="QHBoxLayout" name="horizontalLayout_22"> |
| 635 | <item row="1" column="0"> | 541 | <property name="spacing"> |
| 636 | <widget class="QGroupBox" name="LStick"> | 542 | <number>0</number> |
| 637 | <property name="title"> | 543 | </property> |
| 638 | <string>Left Stick</string> | 544 | <property name="leftMargin"> |
| 639 | </property> | 545 | <number>0</number> |
| 640 | <property name="flat"> | 546 | </property> |
| 641 | <bool>false</bool> | 547 | <property name="topMargin"> |
| 642 | </property> | 548 | <number>0</number> |
| 643 | <property name="checkable"> | 549 | </property> |
| 644 | <bool>false</bool> | 550 | <property name="rightMargin"> |
| 645 | </property> | 551 | <number>0</number> |
| 646 | <layout class="QGridLayout" name="gridLayout_4"> | 552 | </property> |
| 647 | <item row="1" column="1"> | 553 | <property name="bottomMargin"> |
| 648 | <layout class="QVBoxLayout" name="buttonLStickUpVerticalLayout"> | 554 | <number>0</number> |
| 649 | <item> | 555 | </property> |
| 650 | <layout class="QHBoxLayout" name="buttonLStickUpHorizontalLayout"> | 556 | <item> |
| 651 | <item> | 557 | <spacer name="horizontalSpacerLStickDownLeft"> |
| 652 | <widget class="QLabel" name="labelLStickUp"> | 558 | <property name="orientation"> |
| 653 | <property name="text"> | 559 | <enum>Qt::Horizontal</enum> |
| 654 | <string>Up:</string> | 560 | </property> |
| 561 | <property name="sizeHint" stdset="0"> | ||
| 562 | <size> | ||
| 563 | <width>20</width> | ||
| 564 | <height>20</height> | ||
| 565 | </size> | ||
| 566 | </property> | ||
| 567 | </spacer> | ||
| 568 | </item> | ||
| 569 | <item alignment="Qt::AlignHCenter"> | ||
| 570 | <widget class="QGroupBox" name="buttonLStickDownGroup"> | ||
| 571 | <property name="title"> | ||
| 572 | <string>Down</string> | ||
| 573 | </property> | ||
| 574 | <property name="alignment"> | ||
| 575 | <set>Qt::AlignCenter</set> | ||
| 576 | </property> | ||
| 577 | <layout class="QVBoxLayout" name="buttonLStickDownVerticalLayout"> | ||
| 578 | <property name="spacing"> | ||
| 579 | <number>3</number> | ||
| 580 | </property> | ||
| 581 | <property name="leftMargin"> | ||
| 582 | <number>3</number> | ||
| 583 | </property> | ||
| 584 | <property name="topMargin"> | ||
| 585 | <number>3</number> | ||
| 586 | </property> | ||
| 587 | <property name="rightMargin"> | ||
| 588 | <number>3</number> | ||
| 589 | </property> | ||
| 590 | <property name="bottomMargin"> | ||
| 591 | <number>3</number> | ||
| 592 | </property> | ||
| 593 | <item> | ||
| 594 | <widget class="QPushButton" name="buttonLStickDown"> | ||
| 595 | <property name="minimumSize"> | ||
| 596 | <size> | ||
| 597 | <width>57</width> | ||
| 598 | <height>0</height> | ||
| 599 | </size> | ||
| 600 | </property> | ||
| 601 | <property name="maximumSize"> | ||
| 602 | <size> | ||
| 603 | <width>55</width> | ||
| 604 | <height>16777215</height> | ||
| 605 | </size> | ||
| 606 | </property> | ||
| 607 | <property name="styleSheet"> | ||
| 608 | <string notr="true">min-width: 55px;</string> | ||
| 609 | </property> | ||
| 610 | <property name="text"> | ||
| 611 | <string>Down</string> | ||
| 612 | </property> | ||
| 613 | </widget> | ||
| 614 | </item> | ||
| 615 | </layout> | ||
| 616 | </widget> | ||
| 617 | </item> | ||
| 618 | <item> | ||
| 619 | <spacer name="horizontalSpacerLStickDownRight"> | ||
| 620 | <property name="orientation"> | ||
| 621 | <enum>Qt::Horizontal</enum> | ||
| 622 | </property> | ||
| 623 | <property name="sizeHint" stdset="0"> | ||
| 624 | <size> | ||
| 625 | <width>20</width> | ||
| 626 | <height>20</height> | ||
| 627 | </size> | ||
| 628 | </property> | ||
| 629 | </spacer> | ||
| 630 | </item> | ||
| 631 | </layout> | ||
| 632 | </widget> | ||
| 633 | </item> | ||
| 634 | <item> | ||
| 635 | <layout class="QHBoxLayout" name="buttonLStickPressedModifierHorizontalLayout"> | ||
| 636 | <property name="spacing"> | ||
| 637 | <number>3</number> | ||
| 638 | </property> | ||
| 639 | <item alignment="Qt::AlignHCenter"> | ||
| 640 | <widget class="QGroupBox" name="buttonLStickPressedGroup"> | ||
| 641 | <property name="title"> | ||
| 642 | <string>Pressed</string> | ||
| 643 | </property> | ||
| 644 | <property name="alignment"> | ||
| 645 | <set>Qt::AlignCenter</set> | ||
| 646 | </property> | ||
| 647 | <layout class="QVBoxLayout" name="buttonLStickPressedVerticalLayout" stretch="0"> | ||
| 648 | <property name="spacing"> | ||
| 649 | <number>3</number> | ||
| 650 | </property> | ||
| 651 | <property name="leftMargin"> | ||
| 652 | <number>3</number> | ||
| 653 | </property> | ||
| 654 | <property name="topMargin"> | ||
| 655 | <number>3</number> | ||
| 656 | </property> | ||
| 657 | <property name="rightMargin"> | ||
| 658 | <number>3</number> | ||
| 659 | </property> | ||
| 660 | <property name="bottomMargin"> | ||
| 661 | <number>3</number> | ||
| 662 | </property> | ||
| 663 | <item> | ||
| 664 | <widget class="QPushButton" name="buttonLStick"> | ||
| 665 | <property name="minimumSize"> | ||
| 666 | <size> | ||
| 667 | <width>57</width> | ||
| 668 | <height>0</height> | ||
| 669 | </size> | ||
| 670 | </property> | ||
| 671 | <property name="maximumSize"> | ||
| 672 | <size> | ||
| 673 | <width>55</width> | ||
| 674 | <height>16777215</height> | ||
| 675 | </size> | ||
| 676 | </property> | ||
| 677 | <property name="styleSheet"> | ||
| 678 | <string notr="true">min-width: 55px;</string> | ||
| 679 | </property> | ||
| 680 | <property name="text"> | ||
| 681 | <string>Pressed</string> | ||
| 682 | </property> | ||
| 683 | </widget> | ||
| 684 | </item> | ||
| 685 | </layout> | ||
| 686 | </widget> | ||
| 687 | </item> | ||
| 688 | <item alignment="Qt::AlignHCenter"> | ||
| 689 | <widget class="QGroupBox" name="buttonLStickModGroup"> | ||
| 690 | <property name="title"> | ||
| 691 | <string>Modifier</string> | ||
| 692 | </property> | ||
| 693 | <property name="alignment"> | ||
| 694 | <set>Qt::AlignCenter</set> | ||
| 695 | </property> | ||
| 696 | <layout class="QVBoxLayout" name="buttonLStickModVerticalLayout"> | ||
| 697 | <property name="spacing"> | ||
| 698 | <number>3</number> | ||
| 699 | </property> | ||
| 700 | <property name="leftMargin"> | ||
| 701 | <number>3</number> | ||
| 702 | </property> | ||
| 703 | <property name="topMargin"> | ||
| 704 | <number>3</number> | ||
| 705 | </property> | ||
| 706 | <property name="rightMargin"> | ||
| 707 | <number>3</number> | ||
| 708 | </property> | ||
| 709 | <property name="bottomMargin"> | ||
| 710 | <number>3</number> | ||
| 711 | </property> | ||
| 712 | <item> | ||
| 713 | <widget class="QPushButton" name="buttonLStickMod"> | ||
| 714 | <property name="minimumSize"> | ||
| 715 | <size> | ||
| 716 | <width>57</width> | ||
| 717 | <height>0</height> | ||
| 718 | </size> | ||
| 719 | </property> | ||
| 720 | <property name="maximumSize"> | ||
| 721 | <size> | ||
| 722 | <width>55</width> | ||
| 723 | <height>16777215</height> | ||
| 724 | </size> | ||
| 725 | </property> | ||
| 726 | <property name="styleSheet"> | ||
| 727 | <string notr="true">min-width: 55px;</string> | ||
| 728 | </property> | ||
| 729 | <property name="text"> | ||
| 730 | <string>Modifier</string> | ||
| 731 | </property> | ||
| 732 | </widget> | ||
| 733 | </item> | ||
| 734 | </layout> | ||
| 735 | </widget> | ||
| 736 | </item> | ||
| 737 | <item> | ||
| 738 | <widget class="QGroupBox" name="buttonLStickRangeGroup"> | ||
| 739 | <property name="title"> | ||
| 740 | <string>Range</string> | ||
| 741 | </property> | ||
| 742 | <layout class="QHBoxLayout" name="buttonLStickRangeGroupHorizontalLayout"> | ||
| 743 | <property name="spacing"> | ||
| 744 | <number>3</number> | ||
| 745 | </property> | ||
| 746 | <property name="leftMargin"> | ||
| 747 | <number>3</number> | ||
| 748 | </property> | ||
| 749 | <property name="topMargin"> | ||
| 750 | <number>3</number> | ||
| 751 | </property> | ||
| 752 | <property name="rightMargin"> | ||
| 753 | <number>3</number> | ||
| 754 | </property> | ||
| 755 | <property name="bottomMargin"> | ||
| 756 | <number>3</number> | ||
| 757 | </property> | ||
| 758 | <item> | ||
| 759 | <widget class="QSpinBox" name="spinboxLStickRange"> | ||
| 760 | <property name="minimumSize"> | ||
| 761 | <size> | ||
| 762 | <width>55</width> | ||
| 763 | <height>21</height> | ||
| 764 | </size> | ||
| 765 | </property> | ||
| 766 | <property name="maximumSize"> | ||
| 767 | <size> | ||
| 768 | <width>55</width> | ||
| 769 | <height>16777215</height> | ||
| 770 | </size> | ||
| 771 | </property> | ||
| 772 | <property name="suffix"> | ||
| 773 | <string>%</string> | ||
| 774 | </property> | ||
| 775 | <property name="minimum"> | ||
| 776 | <number>50</number> | ||
| 777 | </property> | ||
| 778 | <property name="maximum"> | ||
| 779 | <number>150</number> | ||
| 780 | </property> | ||
| 781 | <property name="value"> | ||
| 782 | <number>100</number> | ||
| 783 | </property> | ||
| 784 | </widget> | ||
| 785 | </item> | ||
| 786 | </layout> | ||
| 787 | </widget> | ||
| 788 | </item> | ||
| 789 | </layout> | ||
| 790 | </item> | ||
| 791 | <item> | ||
| 792 | <layout class="QVBoxLayout" name="sliderLStickDeadzoneModifierRangeVerticalLayout"> | ||
| 793 | <property name="spacing"> | ||
| 794 | <number>3</number> | ||
| 795 | </property> | ||
| 796 | <property name="sizeConstraint"> | ||
| 797 | <enum>QLayout::SetDefaultConstraint</enum> | ||
| 798 | </property> | ||
| 799 | <property name="leftMargin"> | ||
| 800 | <number>0</number> | ||
| 801 | </property> | ||
| 802 | <property name="topMargin"> | ||
| 803 | <number>2</number> | ||
| 804 | </property> | ||
| 805 | <property name="rightMargin"> | ||
| 806 | <number>0</number> | ||
| 807 | </property> | ||
| 808 | <property name="bottomMargin"> | ||
| 809 | <number>3</number> | ||
| 810 | </property> | ||
| 811 | <item> | ||
| 812 | <layout class="QHBoxLayout" name="sliderLStickDeadzoneHorizontalLayout"> | ||
| 813 | <item> | ||
| 814 | <widget class="QLabel" name="labelLStickDeadzone"> | ||
| 815 | <property name="text"> | ||
| 816 | <string>Deadzone: 0%</string> | ||
| 817 | </property> | ||
| 818 | <property name="alignment"> | ||
| 819 | <set>Qt::AlignHCenter</set> | ||
| 820 | </property> | ||
| 821 | </widget> | ||
| 822 | </item> | ||
| 823 | </layout> | ||
| 824 | </item> | ||
| 825 | <item> | ||
| 826 | <widget class="QSlider" name="sliderLStickDeadzone"> | ||
| 827 | <property name="maximum"> | ||
| 828 | <number>100</number> | ||
| 829 | </property> | ||
| 830 | <property name="orientation"> | ||
| 831 | <enum>Qt::Horizontal</enum> | ||
| 832 | </property> | ||
| 833 | </widget> | ||
| 834 | </item> | ||
| 835 | <item> | ||
| 836 | <layout class="QHBoxLayout" name="sliderLStickModifierRangeHorizontalLayout"> | ||
| 837 | <item> | ||
| 838 | <widget class="QLabel" name="labelLStickModifierRange"> | ||
| 839 | <property name="text"> | ||
| 840 | <string>Modifier Range: 0%</string> | ||
| 841 | </property> | ||
| 842 | <property name="alignment"> | ||
| 843 | <set>Qt::AlignHCenter</set> | ||
| 844 | </property> | ||
| 845 | </widget> | ||
| 846 | </item> | ||
| 847 | </layout> | ||
| 848 | </item> | ||
| 849 | <item> | ||
| 850 | <widget class="QSlider" name="sliderLStickModifierRange"> | ||
| 851 | <property name="maximum"> | ||
| 852 | <number>100</number> | ||
| 853 | </property> | ||
| 854 | <property name="orientation"> | ||
| 855 | <enum>Qt::Horizontal</enum> | ||
| 856 | </property> | ||
| 857 | </widget> | ||
| 858 | </item> | ||
| 859 | </layout> | ||
| 860 | </item> | ||
| 861 | </layout> | ||
| 862 | </widget> | ||
| 863 | </item> | ||
| 864 | <item> | ||
| 865 | <spacer name="verticalSpacerBottomLeft"> | ||
| 866 | <property name="orientation"> | ||
| 867 | <enum>Qt::Vertical</enum> | ||
| 868 | </property> | ||
| 869 | <property name="sizeHint" stdset="0"> | ||
| 870 | <size> | ||
| 871 | <width>20</width> | ||
| 872 | <height>0</height> | ||
| 873 | </size> | ||
| 874 | </property> | ||
| 875 | </spacer> | ||
| 876 | </item> | ||
| 877 | <item> | ||
| 878 | <widget class="QGroupBox" name="Dpad"> | ||
| 879 | <property name="sizePolicy"> | ||
| 880 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 881 | <horstretch>0</horstretch> | ||
| 882 | <verstretch>0</verstretch> | ||
| 883 | </sizepolicy> | ||
| 884 | </property> | ||
| 885 | <property name="title"> | ||
| 886 | <string>D-Pad</string> | ||
| 887 | </property> | ||
| 888 | <property name="flat"> | ||
| 889 | <bool>false</bool> | ||
| 890 | </property> | ||
| 891 | <property name="checkable"> | ||
| 892 | <bool>false</bool> | ||
| 893 | </property> | ||
| 894 | <layout class="QVBoxLayout" name="verticalLayout_5"> | ||
| 895 | <property name="spacing"> | ||
| 896 | <number>0</number> | ||
| 655 | </property> | 897 | </property> |
| 656 | </widget> | 898 | <property name="leftMargin"> |
| 657 | </item> | 899 | <number>3</number> |
| 658 | </layout> | ||
| 659 | </item> | ||
| 660 | <item> | ||
| 661 | <widget class="QPushButton" name="buttonLStickUp"> | ||
| 662 | <property name="text"> | ||
| 663 | <string/> | ||
| 664 | </property> | ||
| 665 | </widget> | ||
| 666 | </item> | ||
| 667 | </layout> | ||
| 668 | </item> | ||
| 669 | <item row="0" column="2"> | ||
| 670 | <layout class="QVBoxLayout" name="buttonLStickRightVerticalLayout"> | ||
| 671 | <item> | ||
| 672 | <layout class="QHBoxLayout" name="buttonLStickRightHorizontalLayout"> | ||
| 673 | <item> | ||
| 674 | <widget class="QLabel" name="labelLStickRight"> | ||
| 675 | <property name="text"> | ||
| 676 | <string>Right:</string> | ||
| 677 | </property> | 900 | </property> |
| 678 | </widget> | 901 | <property name="topMargin"> |
| 679 | </item> | 902 | <number>0</number> |
| 680 | </layout> | ||
| 681 | </item> | ||
| 682 | <item> | ||
| 683 | <widget class="QPushButton" name="buttonLStickRight"> | ||
| 684 | <property name="text"> | ||
| 685 | <string/> | ||
| 686 | </property> | ||
| 687 | </widget> | ||
| 688 | </item> | ||
| 689 | </layout> | ||
| 690 | </item> | ||
| 691 | <item row="4" column="1" colspan="2"> | ||
| 692 | <widget class="QPushButton" name="buttonLStickAnalog"> | ||
| 693 | <property name="text"> | ||
| 694 | <string>Set Analog Stick</string> | ||
| 695 | </property> | ||
| 696 | </widget> | ||
| 697 | </item> | ||
| 698 | <item row="0" column="1"> | ||
| 699 | <layout class="QVBoxLayout" name="buttonLStickLeftVerticalLayout"> | ||
| 700 | <item> | ||
| 701 | <layout class="QHBoxLayout" name="buttonLStickLeftHorizontalLayout_2"> | ||
| 702 | <item> | ||
| 703 | <widget class="QLabel" name="labelLStickLeft"> | ||
| 704 | <property name="text"> | ||
| 705 | <string>Left:</string> | ||
| 706 | </property> | 903 | </property> |
| 707 | </widget> | 904 | <property name="rightMargin"> |
| 708 | </item> | 905 | <number>3</number> |
| 709 | </layout> | ||
| 710 | </item> | ||
| 711 | <item> | ||
| 712 | <widget class="QPushButton" name="buttonLStickLeft"> | ||
| 713 | <property name="text"> | ||
| 714 | <string/> | ||
| 715 | </property> | ||
| 716 | </widget> | ||
| 717 | </item> | ||
| 718 | </layout> | ||
| 719 | </item> | ||
| 720 | <item row="1" column="2"> | ||
| 721 | <layout class="QVBoxLayout" name="buttonLStickDownVerticalLayout"> | ||
| 722 | <item> | ||
| 723 | <layout class="QHBoxLayout" name="buttonLStickDownHorizontalLayout"> | ||
| 724 | <item> | ||
| 725 | <widget class="QLabel" name="labelLStickDown"> | ||
| 726 | <property name="text"> | ||
| 727 | <string>Down:</string> | ||
| 728 | </property> | 906 | </property> |
| 729 | </widget> | 907 | <property name="bottomMargin"> |
| 730 | </item> | 908 | <number>3</number> |
| 731 | </layout> | ||
| 732 | </item> | ||
| 733 | <item> | ||
| 734 | <widget class="QPushButton" name="buttonLStickDown"> | ||
| 735 | <property name="text"> | ||
| 736 | <string/> | ||
| 737 | </property> | ||
| 738 | </widget> | ||
| 739 | </item> | ||
| 740 | </layout> | ||
| 741 | </item> | ||
| 742 | <item row="3" column="2"> | ||
| 743 | <layout class="QVBoxLayout" name="buttonLStickModVerticalLayout"> | ||
| 744 | <item> | ||
| 745 | <layout class="QHBoxLayout" name="buttonLStickModHorizontalLayout"> | ||
| 746 | <item> | ||
| 747 | <widget class="QLabel" name="labelLStickMod"> | ||
| 748 | <property name="text"> | ||
| 749 | <string>Modifier:</string> | ||
| 750 | </property> | 909 | </property> |
| 751 | </widget> | 910 | <item> |
| 752 | </item> | 911 | <widget class="QWidget" name="buttonDpadUpWidget" native="true"> |
| 753 | </layout> | 912 | <layout class="QHBoxLayout" name="horizontalLayout_23"> |
| 754 | </item> | 913 | <property name="spacing"> |
| 755 | <item> | 914 | <number>0</number> |
| 756 | <widget class="QPushButton" name="buttonLStickMod"> | 915 | </property> |
| 757 | <property name="text"> | 916 | <property name="leftMargin"> |
| 758 | <string/> | 917 | <number>0</number> |
| 759 | </property> | 918 | </property> |
| 760 | </widget> | 919 | <property name="topMargin"> |
| 761 | </item> | 920 | <number>0</number> |
| 762 | </layout> | 921 | </property> |
| 922 | <property name="rightMargin"> | ||
| 923 | <number>0</number> | ||
| 924 | </property> | ||
| 925 | <property name="bottomMargin"> | ||
| 926 | <number>0</number> | ||
| 927 | </property> | ||
| 928 | <item> | ||
| 929 | <spacer name="horizontalSpacerDpadUpLeft"> | ||
| 930 | <property name="orientation"> | ||
| 931 | <enum>Qt::Horizontal</enum> | ||
| 932 | </property> | ||
| 933 | <property name="sizeHint" stdset="0"> | ||
| 934 | <size> | ||
| 935 | <width>20</width> | ||
| 936 | <height>20</height> | ||
| 937 | </size> | ||
| 938 | </property> | ||
| 939 | </spacer> | ||
| 940 | </item> | ||
| 941 | <item alignment="Qt::AlignHCenter"> | ||
| 942 | <widget class="QGroupBox" name="buttonDpadUpGroup"> | ||
| 943 | <property name="title"> | ||
| 944 | <string>Up</string> | ||
| 945 | </property> | ||
| 946 | <property name="alignment"> | ||
| 947 | <set>Qt::AlignCenter</set> | ||
| 948 | </property> | ||
| 949 | <layout class="QVBoxLayout" name="buttonDpadUpVerticalLayout"> | ||
| 950 | <property name="spacing"> | ||
| 951 | <number>3</number> | ||
| 952 | </property> | ||
| 953 | <property name="leftMargin"> | ||
| 954 | <number>3</number> | ||
| 955 | </property> | ||
| 956 | <property name="topMargin"> | ||
| 957 | <number>3</number> | ||
| 958 | </property> | ||
| 959 | <property name="rightMargin"> | ||
| 960 | <number>3</number> | ||
| 961 | </property> | ||
| 962 | <property name="bottomMargin"> | ||
| 963 | <number>3</number> | ||
| 964 | </property> | ||
| 965 | <item> | ||
| 966 | <widget class="QPushButton" name="buttonDpadUp"> | ||
| 967 | <property name="minimumSize"> | ||
| 968 | <size> | ||
| 969 | <width>57</width> | ||
| 970 | <height>0</height> | ||
| 971 | </size> | ||
| 972 | </property> | ||
| 973 | <property name="maximumSize"> | ||
| 974 | <size> | ||
| 975 | <width>55</width> | ||
| 976 | <height>16777215</height> | ||
| 977 | </size> | ||
| 978 | </property> | ||
| 979 | <property name="styleSheet"> | ||
| 980 | <string notr="true">min-width: 55px;</string> | ||
| 981 | </property> | ||
| 982 | <property name="text"> | ||
| 983 | <string>Up</string> | ||
| 984 | </property> | ||
| 985 | </widget> | ||
| 986 | </item> | ||
| 987 | </layout> | ||
| 988 | </widget> | ||
| 989 | </item> | ||
| 990 | <item> | ||
| 991 | <spacer name="horizontalSpacerDpadUpRight"> | ||
| 992 | <property name="orientation"> | ||
| 993 | <enum>Qt::Horizontal</enum> | ||
| 994 | </property> | ||
| 995 | <property name="sizeHint" stdset="0"> | ||
| 996 | <size> | ||
| 997 | <width>20</width> | ||
| 998 | <height>20</height> | ||
| 999 | </size> | ||
| 1000 | </property> | ||
| 1001 | </spacer> | ||
| 1002 | </item> | ||
| 1003 | </layout> | ||
| 1004 | </widget> | ||
| 1005 | </item> | ||
| 1006 | <item> | ||
| 1007 | <layout class="QHBoxLayout" name="buttonDpadLeftRightHorizontalLayout"> | ||
| 1008 | <property name="spacing"> | ||
| 1009 | <number>3</number> | ||
| 1010 | </property> | ||
| 1011 | <item alignment="Qt::AlignHCenter"> | ||
| 1012 | <widget class="QGroupBox" name="buttonDpadLeftGroup"> | ||
| 1013 | <property name="title"> | ||
| 1014 | <string>Left</string> | ||
| 1015 | </property> | ||
| 1016 | <property name="alignment"> | ||
| 1017 | <set>Qt::AlignCenter</set> | ||
| 1018 | </property> | ||
| 1019 | <layout class="QVBoxLayout" name="buttonDpadLeftVerticalLayout"> | ||
| 1020 | <property name="spacing"> | ||
| 1021 | <number>3</number> | ||
| 1022 | </property> | ||
| 1023 | <property name="leftMargin"> | ||
| 1024 | <number>3</number> | ||
| 1025 | </property> | ||
| 1026 | <property name="topMargin"> | ||
| 1027 | <number>3</number> | ||
| 1028 | </property> | ||
| 1029 | <property name="rightMargin"> | ||
| 1030 | <number>3</number> | ||
| 1031 | </property> | ||
| 1032 | <property name="bottomMargin"> | ||
| 1033 | <number>3</number> | ||
| 1034 | </property> | ||
| 1035 | <item> | ||
| 1036 | <widget class="QPushButton" name="buttonDpadLeft"> | ||
| 1037 | <property name="minimumSize"> | ||
| 1038 | <size> | ||
| 1039 | <width>57</width> | ||
| 1040 | <height>0</height> | ||
| 1041 | </size> | ||
| 1042 | </property> | ||
| 1043 | <property name="maximumSize"> | ||
| 1044 | <size> | ||
| 1045 | <width>55</width> | ||
| 1046 | <height>16777215</height> | ||
| 1047 | </size> | ||
| 1048 | </property> | ||
| 1049 | <property name="styleSheet"> | ||
| 1050 | <string notr="true">min-width: 55px;</string> | ||
| 1051 | </property> | ||
| 1052 | <property name="text"> | ||
| 1053 | <string>Left</string> | ||
| 1054 | </property> | ||
| 1055 | </widget> | ||
| 1056 | </item> | ||
| 1057 | </layout> | ||
| 1058 | </widget> | ||
| 1059 | </item> | ||
| 1060 | <item alignment="Qt::AlignHCenter"> | ||
| 1061 | <widget class="QGroupBox" name="buttonDpadRightGroup"> | ||
| 1062 | <property name="title"> | ||
| 1063 | <string>Right</string> | ||
| 1064 | </property> | ||
| 1065 | <property name="alignment"> | ||
| 1066 | <set>Qt::AlignCenter</set> | ||
| 1067 | </property> | ||
| 1068 | <layout class="QVBoxLayout" name="buttonDpadRightVerticalLayout"> | ||
| 1069 | <property name="spacing"> | ||
| 1070 | <number>3</number> | ||
| 1071 | </property> | ||
| 1072 | <property name="leftMargin"> | ||
| 1073 | <number>3</number> | ||
| 1074 | </property> | ||
| 1075 | <property name="topMargin"> | ||
| 1076 | <number>3</number> | ||
| 1077 | </property> | ||
| 1078 | <property name="rightMargin"> | ||
| 1079 | <number>3</number> | ||
| 1080 | </property> | ||
| 1081 | <property name="bottomMargin"> | ||
| 1082 | <number>3</number> | ||
| 1083 | </property> | ||
| 1084 | <item> | ||
| 1085 | <widget class="QPushButton" name="buttonDpadRight"> | ||
| 1086 | <property name="minimumSize"> | ||
| 1087 | <size> | ||
| 1088 | <width>57</width> | ||
| 1089 | <height>0</height> | ||
| 1090 | </size> | ||
| 1091 | </property> | ||
| 1092 | <property name="maximumSize"> | ||
| 1093 | <size> | ||
| 1094 | <width>55</width> | ||
| 1095 | <height>16777215</height> | ||
| 1096 | </size> | ||
| 1097 | </property> | ||
| 1098 | <property name="styleSheet"> | ||
| 1099 | <string notr="true">min-width: 55px;</string> | ||
| 1100 | </property> | ||
| 1101 | <property name="text"> | ||
| 1102 | <string>Right</string> | ||
| 1103 | </property> | ||
| 1104 | </widget> | ||
| 1105 | </item> | ||
| 1106 | </layout> | ||
| 1107 | </widget> | ||
| 1108 | </item> | ||
| 1109 | </layout> | ||
| 1110 | </item> | ||
| 1111 | <item> | ||
| 1112 | <widget class="QWidget" name="buttonDpadDownWidget" native="true"> | ||
| 1113 | <layout class="QHBoxLayout" name="horizontalLayout_24"> | ||
| 1114 | <property name="spacing"> | ||
| 1115 | <number>0</number> | ||
| 1116 | </property> | ||
| 1117 | <property name="leftMargin"> | ||
| 1118 | <number>0</number> | ||
| 1119 | </property> | ||
| 1120 | <property name="topMargin"> | ||
| 1121 | <number>0</number> | ||
| 1122 | </property> | ||
| 1123 | <property name="rightMargin"> | ||
| 1124 | <number>0</number> | ||
| 1125 | </property> | ||
| 1126 | <property name="bottomMargin"> | ||
| 1127 | <number>0</number> | ||
| 1128 | </property> | ||
| 1129 | <item> | ||
| 1130 | <spacer name="horizontalSpacerDpadDownLeft"> | ||
| 1131 | <property name="orientation"> | ||
| 1132 | <enum>Qt::Horizontal</enum> | ||
| 1133 | </property> | ||
| 1134 | <property name="sizeHint" stdset="0"> | ||
| 1135 | <size> | ||
| 1136 | <width>20</width> | ||
| 1137 | <height>20</height> | ||
| 1138 | </size> | ||
| 1139 | </property> | ||
| 1140 | </spacer> | ||
| 1141 | </item> | ||
| 1142 | <item alignment="Qt::AlignHCenter"> | ||
| 1143 | <widget class="QGroupBox" name="buttonDpadDownGroup"> | ||
| 1144 | <property name="title"> | ||
| 1145 | <string>Down</string> | ||
| 1146 | </property> | ||
| 1147 | <property name="alignment"> | ||
| 1148 | <set>Qt::AlignCenter</set> | ||
| 1149 | </property> | ||
| 1150 | <layout class="QVBoxLayout" name="buttonDpadDownVerticalLayout"> | ||
| 1151 | <property name="spacing"> | ||
| 1152 | <number>3</number> | ||
| 1153 | </property> | ||
| 1154 | <property name="leftMargin"> | ||
| 1155 | <number>3</number> | ||
| 1156 | </property> | ||
| 1157 | <property name="topMargin"> | ||
| 1158 | <number>3</number> | ||
| 1159 | </property> | ||
| 1160 | <property name="rightMargin"> | ||
| 1161 | <number>3</number> | ||
| 1162 | </property> | ||
| 1163 | <property name="bottomMargin"> | ||
| 1164 | <number>3</number> | ||
| 1165 | </property> | ||
| 1166 | <item> | ||
| 1167 | <widget class="QPushButton" name="buttonDpadDown"> | ||
| 1168 | <property name="minimumSize"> | ||
| 1169 | <size> | ||
| 1170 | <width>57</width> | ||
| 1171 | <height>0</height> | ||
| 1172 | </size> | ||
| 1173 | </property> | ||
| 1174 | <property name="maximumSize"> | ||
| 1175 | <size> | ||
| 1176 | <width>55</width> | ||
| 1177 | <height>16777215</height> | ||
| 1178 | </size> | ||
| 1179 | </property> | ||
| 1180 | <property name="styleSheet"> | ||
| 1181 | <string notr="true">min-width: 55px;</string> | ||
| 1182 | </property> | ||
| 1183 | <property name="text"> | ||
| 1184 | <string>Down</string> | ||
| 1185 | </property> | ||
| 1186 | </widget> | ||
| 1187 | </item> | ||
| 1188 | </layout> | ||
| 1189 | </widget> | ||
| 1190 | </item> | ||
| 1191 | <item> | ||
| 1192 | <spacer name="horizontalSpacerDpadDownRight"> | ||
| 1193 | <property name="orientation"> | ||
| 1194 | <enum>Qt::Horizontal</enum> | ||
| 1195 | </property> | ||
| 1196 | <property name="sizeHint" stdset="0"> | ||
| 1197 | <size> | ||
| 1198 | <width>20</width> | ||
| 1199 | <height>20</height> | ||
| 1200 | </size> | ||
| 1201 | </property> | ||
| 1202 | </spacer> | ||
| 1203 | </item> | ||
| 1204 | </layout> | ||
| 1205 | </widget> | ||
| 1206 | </item> | ||
| 1207 | </layout> | ||
| 1208 | </widget> | ||
| 1209 | </item> | ||
| 1210 | <item> | ||
| 1211 | <spacer name="verticalSpacerBottomLeft_2"> | ||
| 1212 | <property name="orientation"> | ||
| 1213 | <enum>Qt::Vertical</enum> | ||
| 1214 | </property> | ||
| 1215 | <property name="sizeHint" stdset="0"> | ||
| 1216 | <size> | ||
| 1217 | <width>20</width> | ||
| 1218 | <height>0</height> | ||
| 1219 | </size> | ||
| 1220 | </property> | ||
| 1221 | </spacer> | ||
| 1222 | </item> | ||
| 1223 | </layout> | ||
| 1224 | </widget> | ||
| 763 | </item> | 1225 | </item> |
| 764 | <item row="3" column="1"> | 1226 | <item> |
| 765 | <layout class="QVBoxLayout" name="buttonLStickPressedVerticalLayout" stretch="0,0"> | 1227 | <widget class="QWidget" name="bottomMiddle" native="true"> |
| 766 | <item> | 1228 | <layout class="QVBoxLayout" stretch="0,0,0"> |
| 767 | <layout class="QHBoxLayout" name="buttonLStickPressedHorizontalLayout"> | 1229 | <property name="spacing"> |
| 768 | <item> | 1230 | <number>6</number> |
| 769 | <widget class="QLabel" name="labelLStickPressed"> | 1231 | </property> |
| 770 | <property name="text"> | 1232 | <property name="leftMargin"> |
| 771 | <string>Pressed:</string> | 1233 | <number>0</number> |
| 1234 | </property> | ||
| 1235 | <property name="topMargin"> | ||
| 1236 | <number>0</number> | ||
| 1237 | </property> | ||
| 1238 | <property name="rightMargin"> | ||
| 1239 | <number>0</number> | ||
| 1240 | </property> | ||
| 1241 | <property name="bottomMargin"> | ||
| 1242 | <number>0</number> | ||
| 1243 | </property> | ||
| 1244 | <item> | ||
| 1245 | <layout class="QHBoxLayout" name="shoulderButtons"> | ||
| 1246 | <property name="spacing"> | ||
| 1247 | <number>3</number> | ||
| 1248 | </property> | ||
| 1249 | <item> | ||
| 1250 | <widget class="QWidget" name="buttonShoulderButtonsLeft" native="true"> | ||
| 1251 | <layout class="QVBoxLayout" name="buttonShoulderButtonsLeftVerticalLayout"> | ||
| 1252 | <property name="spacing"> | ||
| 1253 | <number>0</number> | ||
| 1254 | </property> | ||
| 1255 | <property name="leftMargin"> | ||
| 1256 | <number>0</number> | ||
| 1257 | </property> | ||
| 1258 | <property name="topMargin"> | ||
| 1259 | <number>0</number> | ||
| 1260 | </property> | ||
| 1261 | <property name="rightMargin"> | ||
| 1262 | <number>0</number> | ||
| 1263 | </property> | ||
| 1264 | <property name="bottomMargin"> | ||
| 1265 | <number>0</number> | ||
| 1266 | </property> | ||
| 1267 | <item> | ||
| 1268 | <widget class="QGroupBox" name="buttonShoulderButtonsButtonLGroup"> | ||
| 1269 | <property name="title"> | ||
| 1270 | <string>L</string> | ||
| 1271 | </property> | ||
| 1272 | <property name="alignment"> | ||
| 1273 | <set>Qt::AlignCenter</set> | ||
| 1274 | </property> | ||
| 1275 | <layout class="QVBoxLayout" name="buttonShoulderButtonsLVerticalLayout"> | ||
| 1276 | <property name="spacing"> | ||
| 1277 | <number>3</number> | ||
| 1278 | </property> | ||
| 1279 | <property name="leftMargin"> | ||
| 1280 | <number>3</number> | ||
| 1281 | </property> | ||
| 1282 | <property name="topMargin"> | ||
| 1283 | <number>3</number> | ||
| 1284 | </property> | ||
| 1285 | <property name="rightMargin"> | ||
| 1286 | <number>3</number> | ||
| 1287 | </property> | ||
| 1288 | <property name="bottomMargin"> | ||
| 1289 | <number>3</number> | ||
| 1290 | </property> | ||
| 1291 | <item> | ||
| 1292 | <widget class="QPushButton" name="buttonL"> | ||
| 1293 | <property name="minimumSize"> | ||
| 1294 | <size> | ||
| 1295 | <width>57</width> | ||
| 1296 | <height>0</height> | ||
| 1297 | </size> | ||
| 1298 | </property> | ||
| 1299 | <property name="maximumSize"> | ||
| 1300 | <size> | ||
| 1301 | <width>55</width> | ||
| 1302 | <height>16777215</height> | ||
| 1303 | </size> | ||
| 1304 | </property> | ||
| 1305 | <property name="styleSheet"> | ||
| 1306 | <string notr="true">min-width: 55px;</string> | ||
| 1307 | </property> | ||
| 1308 | <property name="text"> | ||
| 1309 | <string>L</string> | ||
| 1310 | </property> | ||
| 1311 | </widget> | ||
| 1312 | </item> | ||
| 1313 | </layout> | ||
| 1314 | </widget> | ||
| 1315 | </item> | ||
| 1316 | <item> | ||
| 1317 | <widget class="QGroupBox" name="buttonShoulderButtonsButtonZLGroup"> | ||
| 1318 | <property name="title"> | ||
| 1319 | <string>ZL</string> | ||
| 1320 | </property> | ||
| 1321 | <property name="alignment"> | ||
| 1322 | <set>Qt::AlignCenter</set> | ||
| 1323 | </property> | ||
| 1324 | <layout class="QVBoxLayout" name="buttonShoulderButtonsZLVerticalLayout"> | ||
| 1325 | <property name="spacing"> | ||
| 1326 | <number>3</number> | ||
| 1327 | </property> | ||
| 1328 | <property name="leftMargin"> | ||
| 1329 | <number>3</number> | ||
| 1330 | </property> | ||
| 1331 | <property name="topMargin"> | ||
| 1332 | <number>3</number> | ||
| 1333 | </property> | ||
| 1334 | <property name="rightMargin"> | ||
| 1335 | <number>3</number> | ||
| 1336 | </property> | ||
| 1337 | <property name="bottomMargin"> | ||
| 1338 | <number>3</number> | ||
| 1339 | </property> | ||
| 1340 | <item> | ||
| 1341 | <widget class="QPushButton" name="buttonZL"> | ||
| 1342 | <property name="minimumSize"> | ||
| 1343 | <size> | ||
| 1344 | <width>57</width> | ||
| 1345 | <height>0</height> | ||
| 1346 | </size> | ||
| 1347 | </property> | ||
| 1348 | <property name="maximumSize"> | ||
| 1349 | <size> | ||
| 1350 | <width>55</width> | ||
| 1351 | <height>16777215</height> | ||
| 1352 | </size> | ||
| 1353 | </property> | ||
| 1354 | <property name="styleSheet"> | ||
| 1355 | <string notr="true">min-width: 55px;</string> | ||
| 1356 | </property> | ||
| 1357 | <property name="text"> | ||
| 1358 | <string>ZL</string> | ||
| 1359 | </property> | ||
| 1360 | </widget> | ||
| 1361 | </item> | ||
| 1362 | </layout> | ||
| 1363 | </widget> | ||
| 1364 | </item> | ||
| 1365 | </layout> | ||
| 1366 | </widget> | ||
| 1367 | </item> | ||
| 1368 | <item> | ||
| 1369 | <widget class="QWidget" name="horizontalSpacerShoulderButtonsWidget" native="true"> | ||
| 1370 | <layout class="QHBoxLayout" name="horizontalSpacerShoulderButtonsWidgetLayout"> | ||
| 1371 | <property name="spacing"> | ||
| 1372 | <number>0</number> | ||
| 1373 | </property> | ||
| 1374 | <property name="leftMargin"> | ||
| 1375 | <number>0</number> | ||
| 1376 | </property> | ||
| 1377 | <property name="topMargin"> | ||
| 1378 | <number>0</number> | ||
| 1379 | </property> | ||
| 1380 | <property name="rightMargin"> | ||
| 1381 | <number>0</number> | ||
| 1382 | </property> | ||
| 1383 | <property name="bottomMargin"> | ||
| 1384 | <number>0</number> | ||
| 1385 | </property> | ||
| 1386 | <item> | ||
| 1387 | <spacer name="horizontalSpacerShoulderButtons1"> | ||
| 1388 | <property name="orientation"> | ||
| 1389 | <enum>Qt::Horizontal</enum> | ||
| 1390 | </property> | ||
| 1391 | <property name="sizeHint" stdset="0"> | ||
| 1392 | <size> | ||
| 1393 | <width>0</width> | ||
| 1394 | <height>20</height> | ||
| 1395 | </size> | ||
| 1396 | </property> | ||
| 1397 | </spacer> | ||
| 1398 | </item> | ||
| 1399 | </layout> | ||
| 1400 | </widget> | ||
| 1401 | </item> | ||
| 1402 | <item> | ||
| 1403 | <widget class="QWidget" name="buttonMiscButtonsMinusScreenshot" native="true"> | ||
| 1404 | <layout class="QVBoxLayout" name="buttonMiscButtonsMinusScreenshotVerticalLayout"> | ||
| 1405 | <property name="spacing"> | ||
| 1406 | <number>0</number> | ||
| 1407 | </property> | ||
| 1408 | <property name="leftMargin"> | ||
| 1409 | <number>0</number> | ||
| 1410 | </property> | ||
| 1411 | <property name="topMargin"> | ||
| 1412 | <number>0</number> | ||
| 1413 | </property> | ||
| 1414 | <property name="rightMargin"> | ||
| 1415 | <number>0</number> | ||
| 1416 | </property> | ||
| 1417 | <property name="bottomMargin"> | ||
| 1418 | <number>0</number> | ||
| 1419 | </property> | ||
| 1420 | <item alignment="Qt::AlignHCenter"> | ||
| 1421 | <widget class="QGroupBox" name="buttonMiscButtonsMinusGroup"> | ||
| 1422 | <property name="title"> | ||
| 1423 | <string>Minus</string> | ||
| 1424 | </property> | ||
| 1425 | <property name="alignment"> | ||
| 1426 | <set>Qt::AlignCenter</set> | ||
| 1427 | </property> | ||
| 1428 | <layout class="QVBoxLayout" name="buttonMiscMinusVerticalLayout"> | ||
| 1429 | <property name="spacing"> | ||
| 1430 | <number>3</number> | ||
| 1431 | </property> | ||
| 1432 | <property name="leftMargin"> | ||
| 1433 | <number>3</number> | ||
| 1434 | </property> | ||
| 1435 | <property name="topMargin"> | ||
| 1436 | <number>3</number> | ||
| 1437 | </property> | ||
| 1438 | <property name="rightMargin"> | ||
| 1439 | <number>3</number> | ||
| 1440 | </property> | ||
| 1441 | <property name="bottomMargin"> | ||
| 1442 | <number>3</number> | ||
| 1443 | </property> | ||
| 1444 | <item> | ||
| 1445 | <widget class="QPushButton" name="buttonMinus"> | ||
| 1446 | <property name="minimumSize"> | ||
| 1447 | <size> | ||
| 1448 | <width>57</width> | ||
| 1449 | <height>0</height> | ||
| 1450 | </size> | ||
| 1451 | </property> | ||
| 1452 | <property name="maximumSize"> | ||
| 1453 | <size> | ||
| 1454 | <width>55</width> | ||
| 1455 | <height>16777215</height> | ||
| 1456 | </size> | ||
| 1457 | </property> | ||
| 1458 | <property name="styleSheet"> | ||
| 1459 | <string notr="true">min-width: 55px;</string> | ||
| 1460 | </property> | ||
| 1461 | <property name="text"> | ||
| 1462 | <string>Minus</string> | ||
| 1463 | </property> | ||
| 1464 | </widget> | ||
| 1465 | </item> | ||
| 1466 | </layout> | ||
| 1467 | </widget> | ||
| 1468 | </item> | ||
| 1469 | <item alignment="Qt::AlignHCenter"> | ||
| 1470 | <widget class="QGroupBox" name="buttonMiscButtonsScreenshotGroup"> | ||
| 1471 | <property name="title"> | ||
| 1472 | <string>Capture</string> | ||
| 1473 | </property> | ||
| 1474 | <property name="alignment"> | ||
| 1475 | <set>Qt::AlignCenter</set> | ||
| 1476 | </property> | ||
| 1477 | <layout class="QVBoxLayout" name="buttonMiscScrCapVerticalLayout"> | ||
| 1478 | <property name="spacing"> | ||
| 1479 | <number>3</number> | ||
| 1480 | </property> | ||
| 1481 | <property name="leftMargin"> | ||
| 1482 | <number>3</number> | ||
| 1483 | </property> | ||
| 1484 | <property name="topMargin"> | ||
| 1485 | <number>3</number> | ||
| 1486 | </property> | ||
| 1487 | <property name="rightMargin"> | ||
| 1488 | <number>3</number> | ||
| 1489 | </property> | ||
| 1490 | <property name="bottomMargin"> | ||
| 1491 | <number>3</number> | ||
| 1492 | </property> | ||
| 1493 | <item> | ||
| 1494 | <widget class="QPushButton" name="buttonScreenshot"> | ||
| 1495 | <property name="minimumSize"> | ||
| 1496 | <size> | ||
| 1497 | <width>57</width> | ||
| 1498 | <height>0</height> | ||
| 1499 | </size> | ||
| 1500 | </property> | ||
| 1501 | <property name="maximumSize"> | ||
| 1502 | <size> | ||
| 1503 | <width>55</width> | ||
| 1504 | <height>16777215</height> | ||
| 1505 | </size> | ||
| 1506 | </property> | ||
| 1507 | <property name="styleSheet"> | ||
| 1508 | <string notr="true">min-width: 55px;</string> | ||
| 1509 | </property> | ||
| 1510 | <property name="text"> | ||
| 1511 | <string>Capture</string> | ||
| 1512 | </property> | ||
| 1513 | </widget> | ||
| 1514 | </item> | ||
| 1515 | </layout> | ||
| 1516 | </widget> | ||
| 1517 | </item> | ||
| 1518 | </layout> | ||
| 1519 | </widget> | ||
| 1520 | </item> | ||
| 1521 | <item> | ||
| 1522 | <widget class="QWidget" name="buttonMiscButtonsPlusHome" native="true"> | ||
| 1523 | <layout class="QVBoxLayout" name="buttonMiscButtonsPlusHomeVerticalLayout"> | ||
| 1524 | <property name="spacing"> | ||
| 1525 | <number>0</number> | ||
| 1526 | </property> | ||
| 1527 | <property name="leftMargin"> | ||
| 1528 | <number>0</number> | ||
| 1529 | </property> | ||
| 1530 | <property name="topMargin"> | ||
| 1531 | <number>0</number> | ||
| 1532 | </property> | ||
| 1533 | <property name="rightMargin"> | ||
| 1534 | <number>0</number> | ||
| 1535 | </property> | ||
| 1536 | <property name="bottomMargin"> | ||
| 1537 | <number>0</number> | ||
| 1538 | </property> | ||
| 1539 | <item alignment="Qt::AlignHCenter"> | ||
| 1540 | <widget class="QGroupBox" name="buttonMiscButtonsPlusGroup"> | ||
| 1541 | <property name="title"> | ||
| 1542 | <string>Plus</string> | ||
| 1543 | </property> | ||
| 1544 | <property name="alignment"> | ||
| 1545 | <set>Qt::AlignCenter</set> | ||
| 1546 | </property> | ||
| 1547 | <layout class="QVBoxLayout" name="buttonMiscPlusVerticalLayout"> | ||
| 1548 | <property name="spacing"> | ||
| 1549 | <number>3</number> | ||
| 1550 | </property> | ||
| 1551 | <property name="leftMargin"> | ||
| 1552 | <number>3</number> | ||
| 1553 | </property> | ||
| 1554 | <property name="topMargin"> | ||
| 1555 | <number>3</number> | ||
| 1556 | </property> | ||
| 1557 | <property name="rightMargin"> | ||
| 1558 | <number>3</number> | ||
| 1559 | </property> | ||
| 1560 | <property name="bottomMargin"> | ||
| 1561 | <number>3</number> | ||
| 1562 | </property> | ||
| 1563 | <item> | ||
| 1564 | <widget class="QPushButton" name="buttonPlus"> | ||
| 1565 | <property name="minimumSize"> | ||
| 1566 | <size> | ||
| 1567 | <width>57</width> | ||
| 1568 | <height>0</height> | ||
| 1569 | </size> | ||
| 1570 | </property> | ||
| 1571 | <property name="maximumSize"> | ||
| 1572 | <size> | ||
| 1573 | <width>55</width> | ||
| 1574 | <height>16777215</height> | ||
| 1575 | </size> | ||
| 1576 | </property> | ||
| 1577 | <property name="styleSheet"> | ||
| 1578 | <string notr="true">min-width: 55px;</string> | ||
| 1579 | </property> | ||
| 1580 | <property name="text"> | ||
| 1581 | <string>Plus</string> | ||
| 1582 | </property> | ||
| 1583 | </widget> | ||
| 1584 | </item> | ||
| 1585 | </layout> | ||
| 1586 | </widget> | ||
| 1587 | </item> | ||
| 1588 | <item alignment="Qt::AlignHCenter"> | ||
| 1589 | <widget class="QGroupBox" name="buttonMiscButtonsHomeGroup"> | ||
| 1590 | <property name="title"> | ||
| 1591 | <string>Home</string> | ||
| 1592 | </property> | ||
| 1593 | <property name="alignment"> | ||
| 1594 | <set>Qt::AlignCenter</set> | ||
| 1595 | </property> | ||
| 1596 | <layout class="QVBoxLayout" name="buttonMiscHomeVerticalLayout"> | ||
| 1597 | <property name="spacing"> | ||
| 1598 | <number>3</number> | ||
| 1599 | </property> | ||
| 1600 | <property name="leftMargin"> | ||
| 1601 | <number>3</number> | ||
| 1602 | </property> | ||
| 1603 | <property name="topMargin"> | ||
| 1604 | <number>3</number> | ||
| 1605 | </property> | ||
| 1606 | <property name="rightMargin"> | ||
| 1607 | <number>3</number> | ||
| 1608 | </property> | ||
| 1609 | <property name="bottomMargin"> | ||
| 1610 | <number>3</number> | ||
| 1611 | </property> | ||
| 1612 | <item> | ||
| 1613 | <widget class="QPushButton" name="buttonHome"> | ||
| 1614 | <property name="minimumSize"> | ||
| 1615 | <size> | ||
| 1616 | <width>57</width> | ||
| 1617 | <height>0</height> | ||
| 1618 | </size> | ||
| 1619 | </property> | ||
| 1620 | <property name="maximumSize"> | ||
| 1621 | <size> | ||
| 1622 | <width>55</width> | ||
| 1623 | <height>16777215</height> | ||
| 1624 | </size> | ||
| 1625 | </property> | ||
| 1626 | <property name="styleSheet"> | ||
| 1627 | <string notr="true">min-width: 55px;</string> | ||
| 1628 | </property> | ||
| 1629 | <property name="text"> | ||
| 1630 | <string>Home</string> | ||
| 1631 | </property> | ||
| 1632 | </widget> | ||
| 1633 | </item> | ||
| 1634 | </layout> | ||
| 1635 | </widget> | ||
| 1636 | </item> | ||
| 1637 | </layout> | ||
| 1638 | </widget> | ||
| 1639 | </item> | ||
| 1640 | <item> | ||
| 1641 | <widget class="QWidget" name="horizontalSpacerShoulderButtonsWidget3" native="true"> | ||
| 1642 | <layout class="QHBoxLayout" name="horizontalSpacerShoulderButtonsWidget3Layout"> | ||
| 1643 | <property name="spacing"> | ||
| 1644 | <number>0</number> | ||
| 1645 | </property> | ||
| 1646 | <property name="leftMargin"> | ||
| 1647 | <number>0</number> | ||
| 1648 | </property> | ||
| 1649 | <property name="topMargin"> | ||
| 1650 | <number>0</number> | ||
| 1651 | </property> | ||
| 1652 | <property name="rightMargin"> | ||
| 1653 | <number>0</number> | ||
| 1654 | </property> | ||
| 1655 | <property name="bottomMargin"> | ||
| 1656 | <number>0</number> | ||
| 1657 | </property> | ||
| 1658 | <item> | ||
| 1659 | <spacer name="horizontalSpacerShoulderButtons2"> | ||
| 1660 | <property name="orientation"> | ||
| 1661 | <enum>Qt::Horizontal</enum> | ||
| 1662 | </property> | ||
| 1663 | <property name="sizeHint" stdset="0"> | ||
| 1664 | <size> | ||
| 1665 | <width>0</width> | ||
| 1666 | <height>20</height> | ||
| 1667 | </size> | ||
| 1668 | </property> | ||
| 1669 | </spacer> | ||
| 1670 | </item> | ||
| 1671 | </layout> | ||
| 1672 | </widget> | ||
| 1673 | </item> | ||
| 1674 | <item> | ||
| 1675 | <widget class="QWidget" name="buttonShoulderButtonsRight" native="true"> | ||
| 1676 | <layout class="QVBoxLayout" name="buttonShoulderButtonsRightVerticalLayout"> | ||
| 1677 | <property name="spacing"> | ||
| 1678 | <number>0</number> | ||
| 1679 | </property> | ||
| 1680 | <property name="leftMargin"> | ||
| 1681 | <number>0</number> | ||
| 1682 | </property> | ||
| 1683 | <property name="topMargin"> | ||
| 1684 | <number>0</number> | ||
| 1685 | </property> | ||
| 1686 | <property name="rightMargin"> | ||
| 1687 | <number>0</number> | ||
| 1688 | </property> | ||
| 1689 | <property name="bottomMargin"> | ||
| 1690 | <number>0</number> | ||
| 1691 | </property> | ||
| 1692 | <item> | ||
| 1693 | <widget class="QGroupBox" name="buttonShoulderButtonsRGroup"> | ||
| 1694 | <property name="title"> | ||
| 1695 | <string>R</string> | ||
| 1696 | </property> | ||
| 1697 | <property name="alignment"> | ||
| 1698 | <set>Qt::AlignCenter</set> | ||
| 1699 | </property> | ||
| 1700 | <layout class="QVBoxLayout" name="buttonShoulderButtonsRVerticalLayout"> | ||
| 1701 | <property name="spacing"> | ||
| 1702 | <number>3</number> | ||
| 1703 | </property> | ||
| 1704 | <property name="leftMargin"> | ||
| 1705 | <number>3</number> | ||
| 1706 | </property> | ||
| 1707 | <property name="topMargin"> | ||
| 1708 | <number>3</number> | ||
| 1709 | </property> | ||
| 1710 | <property name="rightMargin"> | ||
| 1711 | <number>3</number> | ||
| 1712 | </property> | ||
| 1713 | <property name="bottomMargin"> | ||
| 1714 | <number>3</number> | ||
| 1715 | </property> | ||
| 1716 | <item> | ||
| 1717 | <widget class="QPushButton" name="buttonR"> | ||
| 1718 | <property name="minimumSize"> | ||
| 1719 | <size> | ||
| 1720 | <width>57</width> | ||
| 1721 | <height>0</height> | ||
| 1722 | </size> | ||
| 1723 | </property> | ||
| 1724 | <property name="maximumSize"> | ||
| 1725 | <size> | ||
| 1726 | <width>55</width> | ||
| 1727 | <height>16777215</height> | ||
| 1728 | </size> | ||
| 1729 | </property> | ||
| 1730 | <property name="styleSheet"> | ||
| 1731 | <string notr="true">min-width: 55px;</string> | ||
| 1732 | </property> | ||
| 1733 | <property name="text"> | ||
| 1734 | <string>R</string> | ||
| 1735 | </property> | ||
| 1736 | </widget> | ||
| 1737 | </item> | ||
| 1738 | </layout> | ||
| 1739 | </widget> | ||
| 1740 | </item> | ||
| 1741 | <item> | ||
| 1742 | <widget class="QGroupBox" name="buttonShoulderButtonsZRGroup"> | ||
| 1743 | <property name="title"> | ||
| 1744 | <string>ZR</string> | ||
| 1745 | </property> | ||
| 1746 | <property name="alignment"> | ||
| 1747 | <set>Qt::AlignCenter</set> | ||
| 1748 | </property> | ||
| 1749 | <layout class="QVBoxLayout" name="buttonShoulderButtonsZRVerticalLayout"> | ||
| 1750 | <property name="spacing"> | ||
| 1751 | <number>3</number> | ||
| 1752 | </property> | ||
| 1753 | <property name="leftMargin"> | ||
| 1754 | <number>3</number> | ||
| 1755 | </property> | ||
| 1756 | <property name="topMargin"> | ||
| 1757 | <number>3</number> | ||
| 1758 | </property> | ||
| 1759 | <property name="rightMargin"> | ||
| 1760 | <number>3</number> | ||
| 1761 | </property> | ||
| 1762 | <property name="bottomMargin"> | ||
| 1763 | <number>3</number> | ||
| 1764 | </property> | ||
| 1765 | <item> | ||
| 1766 | <widget class="QPushButton" name="buttonZR"> | ||
| 1767 | <property name="minimumSize"> | ||
| 1768 | <size> | ||
| 1769 | <width>57</width> | ||
| 1770 | <height>0</height> | ||
| 1771 | </size> | ||
| 1772 | </property> | ||
| 1773 | <property name="maximumSize"> | ||
| 1774 | <size> | ||
| 1775 | <width>55</width> | ||
| 1776 | <height>16777215</height> | ||
| 1777 | </size> | ||
| 1778 | </property> | ||
| 1779 | <property name="styleSheet"> | ||
| 1780 | <string notr="true">min-width: 55px;</string> | ||
| 1781 | </property> | ||
| 1782 | <property name="text"> | ||
| 1783 | <string>ZR</string> | ||
| 1784 | </property> | ||
| 1785 | </widget> | ||
| 1786 | </item> | ||
| 1787 | </layout> | ||
| 1788 | </widget> | ||
| 1789 | </item> | ||
| 1790 | </layout> | ||
| 1791 | </widget> | ||
| 1792 | </item> | ||
| 1793 | <item> | ||
| 1794 | <widget class="QWidget" name="horizontalSpacerShoulderButtonsWidget2" native="true"> | ||
| 1795 | <layout class="QHBoxLayout" name="horizontalSpacerShoulderButtonsWidget2Layout"> | ||
| 1796 | <property name="spacing"> | ||
| 1797 | <number>0</number> | ||
| 1798 | </property> | ||
| 1799 | <property name="leftMargin"> | ||
| 1800 | <number>0</number> | ||
| 1801 | </property> | ||
| 1802 | <property name="topMargin"> | ||
| 1803 | <number>0</number> | ||
| 1804 | </property> | ||
| 1805 | <property name="rightMargin"> | ||
| 1806 | <number>0</number> | ||
| 1807 | </property> | ||
| 1808 | <property name="bottomMargin"> | ||
| 1809 | <number>0</number> | ||
| 1810 | </property> | ||
| 1811 | <item> | ||
| 1812 | <spacer name="horizontalSpacerShoulderButtons3"> | ||
| 1813 | <property name="orientation"> | ||
| 1814 | <enum>Qt::Horizontal</enum> | ||
| 1815 | </property> | ||
| 1816 | <property name="sizeHint" stdset="0"> | ||
| 1817 | <size> | ||
| 1818 | <width>0</width> | ||
| 1819 | <height>20</height> | ||
| 1820 | </size> | ||
| 1821 | </property> | ||
| 1822 | </spacer> | ||
| 1823 | </item> | ||
| 1824 | </layout> | ||
| 1825 | </widget> | ||
| 1826 | </item> | ||
| 1827 | <item> | ||
| 1828 | <widget class="QWidget" name="buttonShoulderButtonsSLSR" native="true"> | ||
| 1829 | <layout class="QVBoxLayout" name="buttonShoulderButtonsSLSRVerticalLayout"> | ||
| 1830 | <property name="spacing"> | ||
| 1831 | <number>0</number> | ||
| 1832 | </property> | ||
| 1833 | <property name="leftMargin"> | ||
| 1834 | <number>0</number> | ||
| 1835 | </property> | ||
| 1836 | <property name="topMargin"> | ||
| 1837 | <number>0</number> | ||
| 1838 | </property> | ||
| 1839 | <property name="rightMargin"> | ||
| 1840 | <number>0</number> | ||
| 1841 | </property> | ||
| 1842 | <property name="bottomMargin"> | ||
| 1843 | <number>0</number> | ||
| 1844 | </property> | ||
| 1845 | <item alignment="Qt::AlignHCenter"> | ||
| 1846 | <widget class="QGroupBox" name="buttonShoulderButtonsSLGroup"> | ||
| 1847 | <property name="title"> | ||
| 1848 | <string>SL</string> | ||
| 1849 | </property> | ||
| 1850 | <property name="alignment"> | ||
| 1851 | <set>Qt::AlignCenter</set> | ||
| 1852 | </property> | ||
| 1853 | <layout class="QVBoxLayout" name="buttonShoulderButtonsSLVerticalLayout"> | ||
| 1854 | <property name="spacing"> | ||
| 1855 | <number>3</number> | ||
| 1856 | </property> | ||
| 1857 | <property name="leftMargin"> | ||
| 1858 | <number>3</number> | ||
| 1859 | </property> | ||
| 1860 | <property name="topMargin"> | ||
| 1861 | <number>3</number> | ||
| 1862 | </property> | ||
| 1863 | <property name="rightMargin"> | ||
| 1864 | <number>3</number> | ||
| 1865 | </property> | ||
| 1866 | <property name="bottomMargin"> | ||
| 1867 | <number>3</number> | ||
| 1868 | </property> | ||
| 1869 | <item> | ||
| 1870 | <widget class="QPushButton" name="buttonSL"> | ||
| 1871 | <property name="minimumSize"> | ||
| 1872 | <size> | ||
| 1873 | <width>57</width> | ||
| 1874 | <height>0</height> | ||
| 1875 | </size> | ||
| 1876 | </property> | ||
| 1877 | <property name="maximumSize"> | ||
| 1878 | <size> | ||
| 1879 | <width>55</width> | ||
| 1880 | <height>16777215</height> | ||
| 1881 | </size> | ||
| 1882 | </property> | ||
| 1883 | <property name="styleSheet"> | ||
| 1884 | <string notr="true">min-width: 55px;</string> | ||
| 1885 | </property> | ||
| 1886 | <property name="text"> | ||
| 1887 | <string>SL</string> | ||
| 1888 | </property> | ||
| 1889 | </widget> | ||
| 1890 | </item> | ||
| 1891 | </layout> | ||
| 1892 | </widget> | ||
| 1893 | </item> | ||
| 1894 | <item alignment="Qt::AlignHCenter"> | ||
| 1895 | <widget class="QGroupBox" name="buttonShoulderButtonsSRGroup"> | ||
| 1896 | <property name="title"> | ||
| 1897 | <string>SR</string> | ||
| 1898 | </property> | ||
| 1899 | <property name="alignment"> | ||
| 1900 | <set>Qt::AlignCenter</set> | ||
| 1901 | </property> | ||
| 1902 | <layout class="QVBoxLayout" name="buttonShoulderButtonsSRVerticalLayout"> | ||
| 1903 | <property name="spacing"> | ||
| 1904 | <number>3</number> | ||
| 1905 | </property> | ||
| 1906 | <property name="leftMargin"> | ||
| 1907 | <number>3</number> | ||
| 1908 | </property> | ||
| 1909 | <property name="topMargin"> | ||
| 1910 | <number>3</number> | ||
| 1911 | </property> | ||
| 1912 | <property name="rightMargin"> | ||
| 1913 | <number>3</number> | ||
| 1914 | </property> | ||
| 1915 | <property name="bottomMargin"> | ||
| 1916 | <number>3</number> | ||
| 1917 | </property> | ||
| 1918 | <item> | ||
| 1919 | <widget class="QPushButton" name="buttonSR"> | ||
| 1920 | <property name="minimumSize"> | ||
| 1921 | <size> | ||
| 1922 | <width>57</width> | ||
| 1923 | <height>0</height> | ||
| 1924 | </size> | ||
| 1925 | </property> | ||
| 1926 | <property name="maximumSize"> | ||
| 1927 | <size> | ||
| 1928 | <width>55</width> | ||
| 1929 | <height>16777215</height> | ||
| 1930 | </size> | ||
| 1931 | </property> | ||
| 1932 | <property name="styleSheet"> | ||
| 1933 | <string notr="true">min-width: 55px;</string> | ||
| 1934 | </property> | ||
| 1935 | <property name="text"> | ||
| 1936 | <string>SR</string> | ||
| 1937 | </property> | ||
| 1938 | </widget> | ||
| 1939 | </item> | ||
| 1940 | </layout> | ||
| 1941 | </widget> | ||
| 1942 | </item> | ||
| 1943 | </layout> | ||
| 1944 | </widget> | ||
| 1945 | </item> | ||
| 1946 | </layout> | ||
| 1947 | </item> | ||
| 1948 | <item> | ||
| 1949 | <widget class="QFrame" name="controllerFrame"> | ||
| 1950 | <property name="sizePolicy"> | ||
| 1951 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 1952 | <horstretch>0</horstretch> | ||
| 1953 | <verstretch>0</verstretch> | ||
| 1954 | </sizepolicy> | ||
| 1955 | </property> | ||
| 1956 | <property name="font"> | ||
| 1957 | <font> | ||
| 1958 | <weight>75</weight> | ||
| 1959 | <bold>true</bold> | ||
| 1960 | </font> | ||
| 1961 | </property> | ||
| 1962 | <property name="styleSheet"> | ||
| 1963 | <string notr="true">image: url(:/controller/pro);</string> | ||
| 1964 | </property> | ||
| 1965 | <layout class="QVBoxLayout" name="verticalLayout_4"> | ||
| 1966 | <property name="leftMargin"> | ||
| 1967 | <number>0</number> | ||
| 772 | </property> | 1968 | </property> |
| 773 | </widget> | 1969 | <property name="topMargin"> |
| 774 | </item> | 1970 | <number>0</number> |
| 775 | </layout> | ||
| 776 | </item> | ||
| 777 | <item> | ||
| 778 | <widget class="QPushButton" name="buttonLStick"> | ||
| 779 | <property name="text"> | ||
| 780 | <string/> | ||
| 781 | </property> | ||
| 782 | </widget> | ||
| 783 | </item> | ||
| 784 | </layout> | ||
| 785 | </item> | ||
| 786 | <item row="5" column="1" colspan="2"> | ||
| 787 | <layout class="QVBoxLayout" name="sliderLStickDeadzoneAndModifierVerticalLayout"> | ||
| 788 | <property name="sizeConstraint"> | ||
| 789 | <enum>QLayout::SetDefaultConstraint</enum> | ||
| 790 | </property> | ||
| 791 | <item> | ||
| 792 | <layout class="QHBoxLayout" name="sliderLStickDeadzoneAndModifierHorizontalLayout"> | ||
| 793 | <item> | ||
| 794 | <widget class="QLabel" name="labelLStickDeadzoneAndModifier"> | ||
| 795 | <property name="text"> | ||
| 796 | <string>Deadzone: 0</string> | ||
| 797 | </property> | 1971 | </property> |
| 798 | <property name="alignment"> | 1972 | <property name="rightMargin"> |
| 799 | <enum>Qt::AlignHCenter</enum> | 1973 | <number>0</number> |
| 800 | </property> | 1974 | </property> |
| 801 | </widget> | 1975 | <property name="bottomMargin"> |
| 802 | </item> | 1976 | <number>0</number> |
| 803 | </layout> | ||
| 804 | </item> | ||
| 805 | <item> | ||
| 806 | <widget class="QSlider" name="sliderLStickDeadzoneAndModifier"> | ||
| 807 | <property name="orientation"> | ||
| 808 | <enum>Qt::Horizontal</enum> | ||
| 809 | </property> | ||
| 810 | </widget> | ||
| 811 | </item> | ||
| 812 | </layout> | ||
| 813 | </item> | ||
| 814 | <item row="6" column="1"> | ||
| 815 | <spacer name="LStick_verticalSpacer"> | ||
| 816 | <property name="orientation"> | ||
| 817 | <enum>Qt::Vertical</enum> | ||
| 818 | </property> | ||
| 819 | <property name="sizeHint" stdset="0"> | ||
| 820 | <size> | ||
| 821 | <width>0</width> | ||
| 822 | <height>0</height> | ||
| 823 | </size> | ||
| 824 | </property> | ||
| 825 | </spacer> | ||
| 826 | </item> | ||
| 827 | </layout> | ||
| 828 | </widget> | ||
| 829 | </item> | ||
| 830 | <item row="3" column="0"> | ||
| 831 | <widget class="QGroupBox" name="shoulderButtons"> | ||
| 832 | <property name="title"> | ||
| 833 | <string>Shoulder Buttons</string> | ||
| 834 | </property> | ||
| 835 | <property name="flat"> | ||
| 836 | <bool>false</bool> | ||
| 837 | </property> | ||
| 838 | <property name="checkable"> | ||
| 839 | <bool>false</bool> | ||
| 840 | </property> | ||
| 841 | <layout class="QGridLayout" name="gridLayout_3"> | ||
| 842 | <item row="0" column="0"> | ||
| 843 | <layout class="QVBoxLayout" name="buttonShoulderButtonsLVerticalLayout"> | ||
| 844 | <item> | ||
| 845 | <layout class="QHBoxLayout" name="buttonShoulderButtonsLHorizontalLayout"> | ||
| 846 | <item> | ||
| 847 | <widget class="QLabel" name="labelL"> | ||
| 848 | <property name="text"> | ||
| 849 | <string>L:</string> | ||
| 850 | </property> | 1977 | </property> |
| 851 | </widget> | 1978 | </layout> |
| 852 | </item> | 1979 | </widget> |
| 853 | </layout> | 1980 | </item> |
| 854 | </item> | 1981 | <item> |
| 855 | <item> | 1982 | <layout class="QHBoxLayout" name="miscButtons"> |
| 856 | <widget class="QPushButton" name="buttonL"> | 1983 | <property name="spacing"> |
| 857 | <property name="text"> | 1984 | <number>3</number> |
| 858 | <string/> | 1985 | </property> |
| 859 | </property> | 1986 | <item> |
| 860 | </widget> | 1987 | <spacer name="horizontalSpacerMiscButtons1"> |
| 861 | </item> | 1988 | <property name="orientation"> |
| 862 | </layout> | 1989 | <enum>Qt::Horizontal</enum> |
| 1990 | </property> | ||
| 1991 | <property name="sizeHint" stdset="0"> | ||
| 1992 | <size> | ||
| 1993 | <width>40</width> | ||
| 1994 | <height>0</height> | ||
| 1995 | </size> | ||
| 1996 | </property> | ||
| 1997 | </spacer> | ||
| 1998 | </item> | ||
| 1999 | <item> | ||
| 2000 | <spacer name="horizontalSpacerMiscButtons4"> | ||
| 2001 | <property name="orientation"> | ||
| 2002 | <enum>Qt::Horizontal</enum> | ||
| 2003 | </property> | ||
| 2004 | <property name="sizeHint" stdset="0"> | ||
| 2005 | <size> | ||
| 2006 | <width>40</width> | ||
| 2007 | <height>0</height> | ||
| 2008 | </size> | ||
| 2009 | </property> | ||
| 2010 | </spacer> | ||
| 2011 | </item> | ||
| 2012 | </layout> | ||
| 2013 | </item> | ||
| 2014 | </layout> | ||
| 2015 | </widget> | ||
| 863 | </item> | 2016 | </item> |
| 864 | <item row="0" column="1"> | 2017 | <item> |
| 865 | <layout class="QVBoxLayout" name="buttonShoulderButtonsRVerticalLayout"> | 2018 | <widget class="QWidget" name="bottomRight" native="true"> |
| 866 | <item> | 2019 | <layout class="QVBoxLayout" name="bottomRightLayout"> |
| 867 | <layout class="QHBoxLayout" name="buttonShoulderButtonsRHorizontalLayout"> | 2020 | <property name="spacing"> |
| 868 | <item> | 2021 | <number>0</number> |
| 869 | <widget class="QLabel" name="labelR"> | 2022 | </property> |
| 870 | <property name="text"> | 2023 | <property name="leftMargin"> |
| 871 | <string>R:</string> | 2024 | <number>0</number> |
| 2025 | </property> | ||
| 2026 | <property name="topMargin"> | ||
| 2027 | <number>0</number> | ||
| 2028 | </property> | ||
| 2029 | <property name="rightMargin"> | ||
| 2030 | <number>0</number> | ||
| 2031 | </property> | ||
| 2032 | <property name="bottomMargin"> | ||
| 2033 | <number>0</number> | ||
| 2034 | </property> | ||
| 2035 | <item> | ||
| 2036 | <widget class="QGroupBox" name="faceButtons"> | ||
| 2037 | <property name="sizePolicy"> | ||
| 2038 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 2039 | <horstretch>0</horstretch> | ||
| 2040 | <verstretch>0</verstretch> | ||
| 2041 | </sizepolicy> | ||
| 2042 | </property> | ||
| 2043 | <property name="title"> | ||
| 2044 | <string>Face Buttons</string> | ||
| 2045 | </property> | ||
| 2046 | <property name="flat"> | ||
| 2047 | <bool>false</bool> | ||
| 2048 | </property> | ||
| 2049 | <property name="checkable"> | ||
| 2050 | <bool>false</bool> | ||
| 2051 | </property> | ||
| 2052 | <layout class="QVBoxLayout" name="verticalLayout"> | ||
| 2053 | <property name="spacing"> | ||
| 2054 | <number>0</number> | ||
| 872 | </property> | 2055 | </property> |
| 873 | </widget> | 2056 | <property name="leftMargin"> |
| 874 | </item> | 2057 | <number>3</number> |
| 875 | </layout> | ||
| 876 | </item> | ||
| 877 | <item> | ||
| 878 | <widget class="QPushButton" name="buttonR"> | ||
| 879 | <property name="text"> | ||
| 880 | <string/> | ||
| 881 | </property> | ||
| 882 | </widget> | ||
| 883 | </item> | ||
| 884 | </layout> | ||
| 885 | </item> | ||
| 886 | <item row="1" column="0"> | ||
| 887 | <layout class="QVBoxLayout" name="buttonShoulderButtonsZLVerticalLayout"> | ||
| 888 | <item> | ||
| 889 | <layout class="QHBoxLayout" name="buttonShoulderButtonsZLHorizontalLayout"> | ||
| 890 | <item> | ||
| 891 | <widget class="QLabel" name="labelZL"> | ||
| 892 | <property name="text"> | ||
| 893 | <string>ZL:</string> | ||
| 894 | </property> | 2058 | </property> |
| 895 | </widget> | 2059 | <property name="topMargin"> |
| 896 | </item> | 2060 | <number>0</number> |
| 897 | </layout> | ||
| 898 | </item> | ||
| 899 | <item> | ||
| 900 | <widget class="QPushButton" name="buttonZL"> | ||
| 901 | <property name="text"> | ||
| 902 | <string/> | ||
| 903 | </property> | ||
| 904 | </widget> | ||
| 905 | </item> | ||
| 906 | </layout> | ||
| 907 | </item> | ||
| 908 | <item row="1" column="1"> | ||
| 909 | <layout class="QVBoxLayout" name="buttonShoulderButtonsZRVerticalLayout"> | ||
| 910 | <item> | ||
| 911 | <layout class="QHBoxLayout" name="buttonShoulderButtonsZRHorizontalLayout"> | ||
| 912 | <item> | ||
| 913 | <widget class="QLabel" name="labelZR"> | ||
| 914 | <property name="text"> | ||
| 915 | <string>ZR:</string> | ||
| 916 | </property> | 2061 | </property> |
| 917 | </widget> | 2062 | <property name="rightMargin"> |
| 918 | </item> | 2063 | <number>3</number> |
| 919 | </layout> | ||
| 920 | </item> | ||
| 921 | <item> | ||
| 922 | <widget class="QPushButton" name="buttonZR"> | ||
| 923 | <property name="text"> | ||
| 924 | <string/> | ||
| 925 | </property> | ||
| 926 | </widget> | ||
| 927 | </item> | ||
| 928 | </layout> | ||
| 929 | </item> | ||
| 930 | <item row="0" column="2"> | ||
| 931 | <layout class="QVBoxLayout" name="buttonShoulderButtonsSLVerticalLayout"> | ||
| 932 | <item> | ||
| 933 | <layout class="QHBoxLayout" name="buttonShoulderButtonsSLHorizontalLayout"> | ||
| 934 | <item> | ||
| 935 | <widget class="QLabel" name="labelSL"> | ||
| 936 | <property name="text"> | ||
| 937 | <string>SL:</string> | ||
| 938 | </property> | 2064 | </property> |
| 939 | </widget> | 2065 | <property name="bottomMargin"> |
| 940 | </item> | 2066 | <number>3</number> |
| 941 | </layout> | ||
| 942 | </item> | ||
| 943 | <item> | ||
| 944 | <widget class="QPushButton" name="buttonSL"> | ||
| 945 | <property name="text"> | ||
| 946 | <string/> | ||
| 947 | </property> | ||
| 948 | </widget> | ||
| 949 | </item> | ||
| 950 | </layout> | ||
| 951 | </item> | ||
| 952 | <item row="1" column="2"> | ||
| 953 | <layout class="QVBoxLayout" name="buttonShoulderButtonsSRVerticalLayout"> | ||
| 954 | <item> | ||
| 955 | <layout class="QHBoxLayout" name="buttonShoulderButtonsSRHorizontalLayout"> | ||
| 956 | <item> | ||
| 957 | <widget class="QLabel" name="labelSR"> | ||
| 958 | <property name="text"> | ||
| 959 | <string>SR:</string> | ||
| 960 | </property> | 2067 | </property> |
| 961 | </widget> | 2068 | <item> |
| 962 | </item> | 2069 | <widget class="QWidget" name="buttonFaceButtonsBWidget" native="true"> |
| 963 | </layout> | 2070 | <layout class="QHBoxLayout" name="horizontalLayout_6"> |
| 964 | </item> | 2071 | <property name="spacing"> |
| 965 | <item> | 2072 | <number>0</number> |
| 966 | <widget class="QPushButton" name="buttonSR"> | 2073 | </property> |
| 967 | <property name="text"> | 2074 | <property name="leftMargin"> |
| 968 | <string/> | 2075 | <number>0</number> |
| 969 | </property> | 2076 | </property> |
| 970 | </widget> | 2077 | <property name="topMargin"> |
| 971 | </item> | 2078 | <number>0</number> |
| 972 | </layout> | 2079 | </property> |
| 973 | </item> | 2080 | <property name="rightMargin"> |
| 974 | </layout> | 2081 | <number>0</number> |
| 975 | </widget> | 2082 | </property> |
| 976 | </item> | 2083 | <property name="bottomMargin"> |
| 977 | <item row="3" column="1"> | 2084 | <number>0</number> |
| 978 | <widget class="QGroupBox" name="misc"> | 2085 | </property> |
| 979 | <property name="title"> | 2086 | <item> |
| 980 | <string>Misc.</string> | 2087 | <spacer name="horizontalSpacerBLeft"> |
| 981 | </property> | 2088 | <property name="orientation"> |
| 982 | <property name="flat"> | 2089 | <enum>Qt::Horizontal</enum> |
| 983 | <bool>false</bool> | 2090 | </property> |
| 984 | </property> | 2091 | <property name="sizeHint" stdset="0"> |
| 985 | <property name="checkable"> | 2092 | <size> |
| 986 | <bool>false</bool> | 2093 | <width>20</width> |
| 987 | </property> | 2094 | <height>20</height> |
| 988 | <layout class="QGridLayout" name="gridLayout_6"> | 2095 | </size> |
| 989 | <item row="1" column="0"> | 2096 | </property> |
| 990 | <layout class="QVBoxLayout" name="buttonMiscMinusVerticalLayout"> | 2097 | </spacer> |
| 991 | <item> | 2098 | </item> |
| 992 | <layout class="QHBoxLayout" name="buttonMiscMinusHorizontalLayout"> | 2099 | <item alignment="Qt::AlignHCenter"> |
| 993 | <item> | 2100 | <widget class="QGroupBox" name="buttonFaceButtonsXGroup"> |
| 994 | <widget class="QLabel" name="labelMinus"> | 2101 | <property name="title"> |
| 995 | <property name="text"> | 2102 | <string>X</string> |
| 996 | <string>Minus:</string> | 2103 | </property> |
| 2104 | <property name="alignment"> | ||
| 2105 | <set>Qt::AlignCenter</set> | ||
| 2106 | </property> | ||
| 2107 | <layout class="QVBoxLayout" name="buttonFaceButtonsXVerticalLayout"> | ||
| 2108 | <property name="spacing"> | ||
| 2109 | <number>3</number> | ||
| 2110 | </property> | ||
| 2111 | <property name="leftMargin"> | ||
| 2112 | <number>3</number> | ||
| 2113 | </property> | ||
| 2114 | <property name="topMargin"> | ||
| 2115 | <number>3</number> | ||
| 2116 | </property> | ||
| 2117 | <property name="rightMargin"> | ||
| 2118 | <number>3</number> | ||
| 2119 | </property> | ||
| 2120 | <property name="bottomMargin"> | ||
| 2121 | <number>3</number> | ||
| 2122 | </property> | ||
| 2123 | <item> | ||
| 2124 | <widget class="QPushButton" name="buttonX"> | ||
| 2125 | <property name="minimumSize"> | ||
| 2126 | <size> | ||
| 2127 | <width>57</width> | ||
| 2128 | <height>0</height> | ||
| 2129 | </size> | ||
| 2130 | </property> | ||
| 2131 | <property name="maximumSize"> | ||
| 2132 | <size> | ||
| 2133 | <width>55</width> | ||
| 2134 | <height>16777215</height> | ||
| 2135 | </size> | ||
| 2136 | </property> | ||
| 2137 | <property name="styleSheet"> | ||
| 2138 | <string notr="true">min-width: 55px;</string> | ||
| 2139 | </property> | ||
| 2140 | <property name="text"> | ||
| 2141 | <string>X</string> | ||
| 2142 | </property> | ||
| 2143 | </widget> | ||
| 2144 | </item> | ||
| 2145 | </layout> | ||
| 2146 | </widget> | ||
| 2147 | </item> | ||
| 2148 | <item> | ||
| 2149 | <spacer name="horizontalSpacerBRight"> | ||
| 2150 | <property name="orientation"> | ||
| 2151 | <enum>Qt::Horizontal</enum> | ||
| 2152 | </property> | ||
| 2153 | <property name="sizeHint" stdset="0"> | ||
| 2154 | <size> | ||
| 2155 | <width>20</width> | ||
| 2156 | <height>20</height> | ||
| 2157 | </size> | ||
| 2158 | </property> | ||
| 2159 | </spacer> | ||
| 2160 | </item> | ||
| 2161 | </layout> | ||
| 2162 | </widget> | ||
| 2163 | </item> | ||
| 2164 | <item> | ||
| 2165 | <layout class="QHBoxLayout" name="buttonFaceButtonsYAHorizontalLayout"> | ||
| 2166 | <property name="spacing"> | ||
| 2167 | <number>3</number> | ||
| 2168 | </property> | ||
| 2169 | <item alignment="Qt::AlignHCenter"> | ||
| 2170 | <widget class="QGroupBox" name="buttonFaceButtonsYGroup"> | ||
| 2171 | <property name="title"> | ||
| 2172 | <string>Y</string> | ||
| 2173 | </property> | ||
| 2174 | <property name="alignment"> | ||
| 2175 | <set>Qt::AlignCenter</set> | ||
| 2176 | </property> | ||
| 2177 | <layout class="QVBoxLayout" name="buttonFaceButtonsYVerticalLayout"> | ||
| 2178 | <property name="spacing"> | ||
| 2179 | <number>3</number> | ||
| 2180 | </property> | ||
| 2181 | <property name="leftMargin"> | ||
| 2182 | <number>3</number> | ||
| 2183 | </property> | ||
| 2184 | <property name="topMargin"> | ||
| 2185 | <number>3</number> | ||
| 2186 | </property> | ||
| 2187 | <property name="rightMargin"> | ||
| 2188 | <number>3</number> | ||
| 2189 | </property> | ||
| 2190 | <property name="bottomMargin"> | ||
| 2191 | <number>3</number> | ||
| 2192 | </property> | ||
| 2193 | <item> | ||
| 2194 | <widget class="QPushButton" name="buttonY"> | ||
| 2195 | <property name="minimumSize"> | ||
| 2196 | <size> | ||
| 2197 | <width>57</width> | ||
| 2198 | <height>0</height> | ||
| 2199 | </size> | ||
| 2200 | </property> | ||
| 2201 | <property name="maximumSize"> | ||
| 2202 | <size> | ||
| 2203 | <width>55</width> | ||
| 2204 | <height>16777215</height> | ||
| 2205 | </size> | ||
| 2206 | </property> | ||
| 2207 | <property name="styleSheet"> | ||
| 2208 | <string notr="true">min-width: 55px;</string> | ||
| 2209 | </property> | ||
| 2210 | <property name="text"> | ||
| 2211 | <string>Y</string> | ||
| 2212 | </property> | ||
| 2213 | </widget> | ||
| 2214 | </item> | ||
| 2215 | </layout> | ||
| 2216 | </widget> | ||
| 2217 | </item> | ||
| 2218 | <item alignment="Qt::AlignHCenter"> | ||
| 2219 | <widget class="QGroupBox" name="buttonFaceButtonsAGroup"> | ||
| 2220 | <property name="title"> | ||
| 2221 | <string>A</string> | ||
| 2222 | </property> | ||
| 2223 | <property name="alignment"> | ||
| 2224 | <set>Qt::AlignCenter</set> | ||
| 2225 | </property> | ||
| 2226 | <layout class="QVBoxLayout" name="buttonFaceButtonsAVerticalLayout"> | ||
| 2227 | <property name="spacing"> | ||
| 2228 | <number>3</number> | ||
| 2229 | </property> | ||
| 2230 | <property name="leftMargin"> | ||
| 2231 | <number>3</number> | ||
| 2232 | </property> | ||
| 2233 | <property name="topMargin"> | ||
| 2234 | <number>3</number> | ||
| 2235 | </property> | ||
| 2236 | <property name="rightMargin"> | ||
| 2237 | <number>3</number> | ||
| 2238 | </property> | ||
| 2239 | <property name="bottomMargin"> | ||
| 2240 | <number>3</number> | ||
| 2241 | </property> | ||
| 2242 | <item> | ||
| 2243 | <widget class="QPushButton" name="buttonA"> | ||
| 2244 | <property name="minimumSize"> | ||
| 2245 | <size> | ||
| 2246 | <width>57</width> | ||
| 2247 | <height>0</height> | ||
| 2248 | </size> | ||
| 2249 | </property> | ||
| 2250 | <property name="maximumSize"> | ||
| 2251 | <size> | ||
| 2252 | <width>55</width> | ||
| 2253 | <height>16777215</height> | ||
| 2254 | </size> | ||
| 2255 | </property> | ||
| 2256 | <property name="styleSheet"> | ||
| 2257 | <string notr="true">min-width: 55px;</string> | ||
| 2258 | </property> | ||
| 2259 | <property name="text"> | ||
| 2260 | <string>A</string> | ||
| 2261 | </property> | ||
| 2262 | </widget> | ||
| 2263 | </item> | ||
| 2264 | </layout> | ||
| 2265 | </widget> | ||
| 2266 | </item> | ||
| 2267 | </layout> | ||
| 2268 | </item> | ||
| 2269 | <item> | ||
| 2270 | <widget class="QWidget" name="buttonFaceButtonsXWidget" native="true"> | ||
| 2271 | <layout class="QHBoxLayout" name="horizontalLayout_10"> | ||
| 2272 | <property name="spacing"> | ||
| 2273 | <number>0</number> | ||
| 2274 | </property> | ||
| 2275 | <property name="leftMargin"> | ||
| 2276 | <number>0</number> | ||
| 2277 | </property> | ||
| 2278 | <property name="topMargin"> | ||
| 2279 | <number>0</number> | ||
| 2280 | </property> | ||
| 2281 | <property name="rightMargin"> | ||
| 2282 | <number>0</number> | ||
| 2283 | </property> | ||
| 2284 | <property name="bottomMargin"> | ||
| 2285 | <number>0</number> | ||
| 2286 | </property> | ||
| 2287 | <item> | ||
| 2288 | <spacer name="horizontalSpacerXLeft"> | ||
| 2289 | <property name="orientation"> | ||
| 2290 | <enum>Qt::Horizontal</enum> | ||
| 2291 | </property> | ||
| 2292 | <property name="sizeHint" stdset="0"> | ||
| 2293 | <size> | ||
| 2294 | <width>20</width> | ||
| 2295 | <height>20</height> | ||
| 2296 | </size> | ||
| 2297 | </property> | ||
| 2298 | </spacer> | ||
| 2299 | </item> | ||
| 2300 | <item alignment="Qt::AlignHCenter"> | ||
| 2301 | <widget class="QGroupBox" name="buttonFaceButtonsBWidget_2"> | ||
| 2302 | <property name="title"> | ||
| 2303 | <string>B</string> | ||
| 2304 | </property> | ||
| 2305 | <property name="alignment"> | ||
| 2306 | <set>Qt::AlignCenter</set> | ||
| 2307 | </property> | ||
| 2308 | <layout class="QVBoxLayout" name="buttonFaceButtonsBVerticalLayout"> | ||
| 2309 | <property name="spacing"> | ||
| 2310 | <number>3</number> | ||
| 2311 | </property> | ||
| 2312 | <property name="leftMargin"> | ||
| 2313 | <number>3</number> | ||
| 2314 | </property> | ||
| 2315 | <property name="topMargin"> | ||
| 2316 | <number>3</number> | ||
| 2317 | </property> | ||
| 2318 | <property name="rightMargin"> | ||
| 2319 | <number>3</number> | ||
| 2320 | </property> | ||
| 2321 | <property name="bottomMargin"> | ||
| 2322 | <number>3</number> | ||
| 2323 | </property> | ||
| 2324 | <item> | ||
| 2325 | <widget class="QPushButton" name="buttonB"> | ||
| 2326 | <property name="minimumSize"> | ||
| 2327 | <size> | ||
| 2328 | <width>57</width> | ||
| 2329 | <height>0</height> | ||
| 2330 | </size> | ||
| 2331 | </property> | ||
| 2332 | <property name="maximumSize"> | ||
| 2333 | <size> | ||
| 2334 | <width>55</width> | ||
| 2335 | <height>16777215</height> | ||
| 2336 | </size> | ||
| 2337 | </property> | ||
| 2338 | <property name="styleSheet"> | ||
| 2339 | <string notr="true">min-width: 55px;</string> | ||
| 2340 | </property> | ||
| 2341 | <property name="text"> | ||
| 2342 | <string>B</string> | ||
| 2343 | </property> | ||
| 2344 | </widget> | ||
| 2345 | </item> | ||
| 2346 | </layout> | ||
| 2347 | </widget> | ||
| 2348 | </item> | ||
| 2349 | <item> | ||
| 2350 | <spacer name="horizontalSpacerXRight"> | ||
| 2351 | <property name="orientation"> | ||
| 2352 | <enum>Qt::Horizontal</enum> | ||
| 2353 | </property> | ||
| 2354 | <property name="sizeHint" stdset="0"> | ||
| 2355 | <size> | ||
| 2356 | <width>20</width> | ||
| 2357 | <height>20</height> | ||
| 2358 | </size> | ||
| 2359 | </property> | ||
| 2360 | </spacer> | ||
| 2361 | </item> | ||
| 2362 | </layout> | ||
| 2363 | </widget> | ||
| 2364 | </item> | ||
| 2365 | </layout> | ||
| 2366 | </widget> | ||
| 2367 | </item> | ||
| 2368 | <item> | ||
| 2369 | <spacer name="verticalSpacerBottomRight"> | ||
| 2370 | <property name="orientation"> | ||
| 2371 | <enum>Qt::Vertical</enum> | ||
| 2372 | </property> | ||
| 2373 | <property name="sizeHint" stdset="0"> | ||
| 2374 | <size> | ||
| 2375 | <width>20</width> | ||
| 2376 | <height>0</height> | ||
| 2377 | </size> | ||
| 2378 | </property> | ||
| 2379 | </spacer> | ||
| 2380 | </item> | ||
| 2381 | <item> | ||
| 2382 | <widget class="QGroupBox" name="RStick"> | ||
| 2383 | <property name="sizePolicy"> | ||
| 2384 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 2385 | <horstretch>0</horstretch> | ||
| 2386 | <verstretch>0</verstretch> | ||
| 2387 | </sizepolicy> | ||
| 2388 | </property> | ||
| 2389 | <property name="title"> | ||
| 2390 | <string>Right Stick</string> | ||
| 2391 | </property> | ||
| 2392 | <property name="alignment"> | ||
| 2393 | <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> | ||
| 2394 | </property> | ||
| 2395 | <property name="flat"> | ||
| 2396 | <bool>false</bool> | ||
| 2397 | </property> | ||
| 2398 | <property name="checkable"> | ||
| 2399 | <bool>false</bool> | ||
| 2400 | </property> | ||
| 2401 | <layout class="QVBoxLayout" name="verticalLayout_2"> | ||
| 2402 | <property name="spacing"> | ||
| 2403 | <number>0</number> | ||
| 997 | </property> | 2404 | </property> |
| 998 | </widget> | 2405 | <property name="leftMargin"> |
| 999 | </item> | 2406 | <number>3</number> |
| 1000 | </layout> | ||
| 1001 | </item> | ||
| 1002 | <item> | ||
| 1003 | <widget class="QPushButton" name="buttonMinus"> | ||
| 1004 | <property name="text"> | ||
| 1005 | <string/> | ||
| 1006 | </property> | ||
| 1007 | </widget> | ||
| 1008 | </item> | ||
| 1009 | </layout> | ||
| 1010 | </item> | ||
| 1011 | <item row="3" column="1"> | ||
| 1012 | <spacer name="verticalSpacer_2"> | ||
| 1013 | <property name="orientation"> | ||
| 1014 | <enum>Qt::Vertical</enum> | ||
| 1015 | </property> | ||
| 1016 | <property name="sizeHint" stdset="0"> | ||
| 1017 | <size> | ||
| 1018 | <width>20</width> | ||
| 1019 | <height>40</height> | ||
| 1020 | </size> | ||
| 1021 | </property> | ||
| 1022 | </spacer> | ||
| 1023 | </item> | ||
| 1024 | <item row="0" column="0"> | ||
| 1025 | <layout class="QVBoxLayout" name="buttonMiscPlusVerticalLayout"> | ||
| 1026 | <item> | ||
| 1027 | <layout class="QHBoxLayout" name="buttonMiscPlusHorizontalLayout"> | ||
| 1028 | <item> | ||
| 1029 | <widget class="QLabel" name="labelPlus"> | ||
| 1030 | <property name="text"> | ||
| 1031 | <string>Plus:</string> | ||
| 1032 | </property> | 2407 | </property> |
| 1033 | </widget> | 2408 | <property name="topMargin"> |
| 1034 | </item> | 2409 | <number>0</number> |
| 1035 | </layout> | ||
| 1036 | </item> | ||
| 1037 | <item> | ||
| 1038 | <widget class="QPushButton" name="buttonPlus"> | ||
| 1039 | <property name="text"> | ||
| 1040 | <string/> | ||
| 1041 | </property> | ||
| 1042 | </widget> | ||
| 1043 | </item> | ||
| 1044 | </layout> | ||
| 1045 | </item> | ||
| 1046 | <item row="0" column="1"> | ||
| 1047 | <layout class="QVBoxLayout" name="buttonMiscHomeVerticalLayout"> | ||
| 1048 | <item> | ||
| 1049 | <layout class="QHBoxLayout" name="buttonMiscHomeHorizontalLayout"> | ||
| 1050 | <item> | ||
| 1051 | <widget class="QLabel" name="labelHome"> | ||
| 1052 | <property name="text"> | ||
| 1053 | <string>Home:</string> | ||
| 1054 | </property> | 2410 | </property> |
| 1055 | </widget> | 2411 | <property name="rightMargin"> |
| 1056 | </item> | 2412 | <number>3</number> |
| 1057 | </layout> | ||
| 1058 | </item> | ||
| 1059 | <item> | ||
| 1060 | <widget class="QPushButton" name="buttonHome"> | ||
| 1061 | <property name="text"> | ||
| 1062 | <string/> | ||
| 1063 | </property> | ||
| 1064 | </widget> | ||
| 1065 | </item> | ||
| 1066 | </layout> | ||
| 1067 | </item> | ||
| 1068 | <item row="1" column="1"> | ||
| 1069 | <layout class="QVBoxLayout" name="buttonMiscScrCapVerticalLayout"> | ||
| 1070 | <item> | ||
| 1071 | <layout class="QHBoxLayout" name="buttonMiscScrCapHorizontalLayout"> | ||
| 1072 | <item> | ||
| 1073 | <widget class="QLabel" name="labelScreenshot"> | ||
| 1074 | <property name="text"> | ||
| 1075 | <string>Screen Capture:</string> | ||
| 1076 | </property> | 2413 | </property> |
| 1077 | <property name="wordWrap"> | 2414 | <property name="bottomMargin"> |
| 1078 | <bool>false</bool> | 2415 | <number>0</number> |
| 1079 | </property> | 2416 | </property> |
| 1080 | </widget> | 2417 | <item> |
| 1081 | </item> | 2418 | <widget class="QWidget" name="buttonRStickUpWidget" native="true"> |
| 1082 | </layout> | 2419 | <property name="minimumSize"> |
| 1083 | </item> | 2420 | <size> |
| 1084 | <item> | 2421 | <width>0</width> |
| 1085 | <widget class="QPushButton" name="buttonScreenshot"> | 2422 | <height>0</height> |
| 1086 | <property name="sizePolicy"> | 2423 | </size> |
| 1087 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | 2424 | </property> |
| 1088 | <horstretch>0</horstretch> | 2425 | <layout class="QHBoxLayout" name="horizontalLayout_9"> |
| 1089 | <verstretch>0</verstretch> | 2426 | <property name="spacing"> |
| 1090 | </sizepolicy> | 2427 | <number>0</number> |
| 1091 | </property> | 2428 | </property> |
| 1092 | <property name="maximumSize"> | 2429 | <property name="leftMargin"> |
| 1093 | <size> | 2430 | <number>0</number> |
| 1094 | <width>80</width> | 2431 | </property> |
| 1095 | <height>16777215</height> | 2432 | <property name="topMargin"> |
| 1096 | </size> | 2433 | <number>0</number> |
| 1097 | </property> | 2434 | </property> |
| 1098 | <property name="text"> | 2435 | <property name="rightMargin"> |
| 1099 | <string/> | 2436 | <number>0</number> |
| 1100 | </property> | 2437 | </property> |
| 1101 | </widget> | 2438 | <property name="bottomMargin"> |
| 1102 | </item> | 2439 | <number>0</number> |
| 1103 | </layout> | 2440 | </property> |
| 2441 | <item> | ||
| 2442 | <spacer name="horizontalSpacerRStickUpLeft"> | ||
| 2443 | <property name="orientation"> | ||
| 2444 | <enum>Qt::Horizontal</enum> | ||
| 2445 | </property> | ||
| 2446 | <property name="sizeHint" stdset="0"> | ||
| 2447 | <size> | ||
| 2448 | <width>20</width> | ||
| 2449 | <height>20</height> | ||
| 2450 | </size> | ||
| 2451 | </property> | ||
| 2452 | </spacer> | ||
| 2453 | </item> | ||
| 2454 | <item alignment="Qt::AlignHCenter"> | ||
| 2455 | <widget class="QGroupBox" name="buttonRStickUpGroup"> | ||
| 2456 | <property name="title"> | ||
| 2457 | <string>Up</string> | ||
| 2458 | </property> | ||
| 2459 | <property name="alignment"> | ||
| 2460 | <set>Qt::AlignCenter</set> | ||
| 2461 | </property> | ||
| 2462 | <layout class="QVBoxLayout" name="buttonRStickUpVerticalLayout"> | ||
| 2463 | <property name="spacing"> | ||
| 2464 | <number>3</number> | ||
| 2465 | </property> | ||
| 2466 | <property name="leftMargin"> | ||
| 2467 | <number>3</number> | ||
| 2468 | </property> | ||
| 2469 | <property name="topMargin"> | ||
| 2470 | <number>3</number> | ||
| 2471 | </property> | ||
| 2472 | <property name="rightMargin"> | ||
| 2473 | <number>3</number> | ||
| 2474 | </property> | ||
| 2475 | <property name="bottomMargin"> | ||
| 2476 | <number>3</number> | ||
| 2477 | </property> | ||
| 2478 | <item> | ||
| 2479 | <widget class="QPushButton" name="buttonRStickUp"> | ||
| 2480 | <property name="minimumSize"> | ||
| 2481 | <size> | ||
| 2482 | <width>57</width> | ||
| 2483 | <height>0</height> | ||
| 2484 | </size> | ||
| 2485 | </property> | ||
| 2486 | <property name="maximumSize"> | ||
| 2487 | <size> | ||
| 2488 | <width>55</width> | ||
| 2489 | <height>16777215</height> | ||
| 2490 | </size> | ||
| 2491 | </property> | ||
| 2492 | <property name="styleSheet"> | ||
| 2493 | <string notr="true">min-width: 55px;</string> | ||
| 2494 | </property> | ||
| 2495 | <property name="text"> | ||
| 2496 | <string>Up</string> | ||
| 2497 | </property> | ||
| 2498 | </widget> | ||
| 2499 | </item> | ||
| 2500 | </layout> | ||
| 2501 | </widget> | ||
| 2502 | </item> | ||
| 2503 | <item> | ||
| 2504 | <spacer name="horizontalSpacerRStickUpRight"> | ||
| 2505 | <property name="orientation"> | ||
| 2506 | <enum>Qt::Horizontal</enum> | ||
| 2507 | </property> | ||
| 2508 | <property name="sizeHint" stdset="0"> | ||
| 2509 | <size> | ||
| 2510 | <width>20</width> | ||
| 2511 | <height>20</height> | ||
| 2512 | </size> | ||
| 2513 | </property> | ||
| 2514 | </spacer> | ||
| 2515 | </item> | ||
| 2516 | </layout> | ||
| 2517 | </widget> | ||
| 2518 | </item> | ||
| 2519 | <item> | ||
| 2520 | <layout class="QHBoxLayout" name="buttonRStickLeftRightHorizontalLayout"> | ||
| 2521 | <property name="spacing"> | ||
| 2522 | <number>3</number> | ||
| 2523 | </property> | ||
| 2524 | <item alignment="Qt::AlignHCenter"> | ||
| 2525 | <widget class="QGroupBox" name="buttonRStickLeftGroup"> | ||
| 2526 | <property name="title"> | ||
| 2527 | <string>Left</string> | ||
| 2528 | </property> | ||
| 2529 | <property name="alignment"> | ||
| 2530 | <set>Qt::AlignCenter</set> | ||
| 2531 | </property> | ||
| 2532 | <layout class="QVBoxLayout" name="buttonRStickLeftVerticalLayout"> | ||
| 2533 | <property name="spacing"> | ||
| 2534 | <number>3</number> | ||
| 2535 | </property> | ||
| 2536 | <property name="leftMargin"> | ||
| 2537 | <number>3</number> | ||
| 2538 | </property> | ||
| 2539 | <property name="topMargin"> | ||
| 2540 | <number>3</number> | ||
| 2541 | </property> | ||
| 2542 | <property name="rightMargin"> | ||
| 2543 | <number>3</number> | ||
| 2544 | </property> | ||
| 2545 | <property name="bottomMargin"> | ||
| 2546 | <number>3</number> | ||
| 2547 | </property> | ||
| 2548 | <item> | ||
| 2549 | <widget class="QPushButton" name="buttonRStickLeft"> | ||
| 2550 | <property name="minimumSize"> | ||
| 2551 | <size> | ||
| 2552 | <width>57</width> | ||
| 2553 | <height>0</height> | ||
| 2554 | </size> | ||
| 2555 | </property> | ||
| 2556 | <property name="maximumSize"> | ||
| 2557 | <size> | ||
| 2558 | <width>55</width> | ||
| 2559 | <height>16777215</height> | ||
| 2560 | </size> | ||
| 2561 | </property> | ||
| 2562 | <property name="styleSheet"> | ||
| 2563 | <string notr="true">min-width: 55px;</string> | ||
| 2564 | </property> | ||
| 2565 | <property name="text"> | ||
| 2566 | <string>Left</string> | ||
| 2567 | </property> | ||
| 2568 | </widget> | ||
| 2569 | </item> | ||
| 2570 | </layout> | ||
| 2571 | </widget> | ||
| 2572 | </item> | ||
| 2573 | <item alignment="Qt::AlignHCenter"> | ||
| 2574 | <widget class="QGroupBox" name="buttonRStickRightGroup"> | ||
| 2575 | <property name="title"> | ||
| 2576 | <string>Right</string> | ||
| 2577 | </property> | ||
| 2578 | <property name="alignment"> | ||
| 2579 | <set>Qt::AlignCenter</set> | ||
| 2580 | </property> | ||
| 2581 | <layout class="QVBoxLayout" name="buttonRStickRightVerticalLayout"> | ||
| 2582 | <property name="spacing"> | ||
| 2583 | <number>3</number> | ||
| 2584 | </property> | ||
| 2585 | <property name="leftMargin"> | ||
| 2586 | <number>3</number> | ||
| 2587 | </property> | ||
| 2588 | <property name="topMargin"> | ||
| 2589 | <number>3</number> | ||
| 2590 | </property> | ||
| 2591 | <property name="rightMargin"> | ||
| 2592 | <number>3</number> | ||
| 2593 | </property> | ||
| 2594 | <property name="bottomMargin"> | ||
| 2595 | <number>3</number> | ||
| 2596 | </property> | ||
| 2597 | <item> | ||
| 2598 | <widget class="QPushButton" name="buttonRStickRight"> | ||
| 2599 | <property name="minimumSize"> | ||
| 2600 | <size> | ||
| 2601 | <width>57</width> | ||
| 2602 | <height>0</height> | ||
| 2603 | </size> | ||
| 2604 | </property> | ||
| 2605 | <property name="maximumSize"> | ||
| 2606 | <size> | ||
| 2607 | <width>55</width> | ||
| 2608 | <height>16777215</height> | ||
| 2609 | </size> | ||
| 2610 | </property> | ||
| 2611 | <property name="styleSheet"> | ||
| 2612 | <string notr="true">min-width: 55px;</string> | ||
| 2613 | </property> | ||
| 2614 | <property name="text"> | ||
| 2615 | <string>Right</string> | ||
| 2616 | </property> | ||
| 2617 | </widget> | ||
| 2618 | </item> | ||
| 2619 | </layout> | ||
| 2620 | </widget> | ||
| 2621 | </item> | ||
| 2622 | </layout> | ||
| 2623 | </item> | ||
| 2624 | <item> | ||
| 2625 | <widget class="QWidget" name="buttonRStickDownWidget" native="true"> | ||
| 2626 | <layout class="QHBoxLayout" name="horizontalLayout_11"> | ||
| 2627 | <property name="spacing"> | ||
| 2628 | <number>0</number> | ||
| 2629 | </property> | ||
| 2630 | <property name="leftMargin"> | ||
| 2631 | <number>0</number> | ||
| 2632 | </property> | ||
| 2633 | <property name="topMargin"> | ||
| 2634 | <number>0</number> | ||
| 2635 | </property> | ||
| 2636 | <property name="rightMargin"> | ||
| 2637 | <number>0</number> | ||
| 2638 | </property> | ||
| 2639 | <property name="bottomMargin"> | ||
| 2640 | <number>0</number> | ||
| 2641 | </property> | ||
| 2642 | <item> | ||
| 2643 | <spacer name="horizontalSpacerRStickDownLeft"> | ||
| 2644 | <property name="orientation"> | ||
| 2645 | <enum>Qt::Horizontal</enum> | ||
| 2646 | </property> | ||
| 2647 | <property name="sizeHint" stdset="0"> | ||
| 2648 | <size> | ||
| 2649 | <width>20</width> | ||
| 2650 | <height>20</height> | ||
| 2651 | </size> | ||
| 2652 | </property> | ||
| 2653 | </spacer> | ||
| 2654 | </item> | ||
| 2655 | <item> | ||
| 2656 | <widget class="QGroupBox" name="buttonRStickDownGroup"> | ||
| 2657 | <property name="title"> | ||
| 2658 | <string>Down</string> | ||
| 2659 | </property> | ||
| 2660 | <property name="alignment"> | ||
| 2661 | <set>Qt::AlignCenter</set> | ||
| 2662 | </property> | ||
| 2663 | <layout class="QVBoxLayout" name="buttonRStickDownVerticalLayout"> | ||
| 2664 | <property name="spacing"> | ||
| 2665 | <number>3</number> | ||
| 2666 | </property> | ||
| 2667 | <property name="leftMargin"> | ||
| 2668 | <number>3</number> | ||
| 2669 | </property> | ||
| 2670 | <property name="topMargin"> | ||
| 2671 | <number>3</number> | ||
| 2672 | </property> | ||
| 2673 | <property name="rightMargin"> | ||
| 2674 | <number>3</number> | ||
| 2675 | </property> | ||
| 2676 | <property name="bottomMargin"> | ||
| 2677 | <number>3</number> | ||
| 2678 | </property> | ||
| 2679 | <item> | ||
| 2680 | <widget class="QPushButton" name="buttonRStickDown"> | ||
| 2681 | <property name="minimumSize"> | ||
| 2682 | <size> | ||
| 2683 | <width>57</width> | ||
| 2684 | <height>0</height> | ||
| 2685 | </size> | ||
| 2686 | </property> | ||
| 2687 | <property name="maximumSize"> | ||
| 2688 | <size> | ||
| 2689 | <width>55</width> | ||
| 2690 | <height>16777215</height> | ||
| 2691 | </size> | ||
| 2692 | </property> | ||
| 2693 | <property name="styleSheet"> | ||
| 2694 | <string notr="true">min-width: 55px;</string> | ||
| 2695 | </property> | ||
| 2696 | <property name="text"> | ||
| 2697 | <string>Down</string> | ||
| 2698 | </property> | ||
| 2699 | </widget> | ||
| 2700 | </item> | ||
| 2701 | </layout> | ||
| 2702 | </widget> | ||
| 2703 | </item> | ||
| 2704 | <item> | ||
| 2705 | <spacer name="horizontalSpacerRStickDownRight"> | ||
| 2706 | <property name="orientation"> | ||
| 2707 | <enum>Qt::Horizontal</enum> | ||
| 2708 | </property> | ||
| 2709 | <property name="sizeHint" stdset="0"> | ||
| 2710 | <size> | ||
| 2711 | <width>20</width> | ||
| 2712 | <height>20</height> | ||
| 2713 | </size> | ||
| 2714 | </property> | ||
| 2715 | </spacer> | ||
| 2716 | </item> | ||
| 2717 | </layout> | ||
| 2718 | </widget> | ||
| 2719 | </item> | ||
| 2720 | <item> | ||
| 2721 | <layout class="QHBoxLayout" name="buttonRStickPressedModifierHorizontalLayout"> | ||
| 2722 | <property name="spacing"> | ||
| 2723 | <number>3</number> | ||
| 2724 | </property> | ||
| 2725 | <item alignment="Qt::AlignHCenter"> | ||
| 2726 | <widget class="QGroupBox" name="groupRStickPressed"> | ||
| 2727 | <property name="title"> | ||
| 2728 | <string>Pressed</string> | ||
| 2729 | </property> | ||
| 2730 | <property name="alignment"> | ||
| 2731 | <set>Qt::AlignCenter</set> | ||
| 2732 | </property> | ||
| 2733 | <layout class="QVBoxLayout" name="buttonRStickPressedVerticalLayout"> | ||
| 2734 | <property name="spacing"> | ||
| 2735 | <number>3</number> | ||
| 2736 | </property> | ||
| 2737 | <property name="leftMargin"> | ||
| 2738 | <number>3</number> | ||
| 2739 | </property> | ||
| 2740 | <property name="topMargin"> | ||
| 2741 | <number>3</number> | ||
| 2742 | </property> | ||
| 2743 | <property name="rightMargin"> | ||
| 2744 | <number>3</number> | ||
| 2745 | </property> | ||
| 2746 | <property name="bottomMargin"> | ||
| 2747 | <number>3</number> | ||
| 2748 | </property> | ||
| 2749 | <item> | ||
| 2750 | <widget class="QPushButton" name="buttonRStick"> | ||
| 2751 | <property name="minimumSize"> | ||
| 2752 | <size> | ||
| 2753 | <width>57</width> | ||
| 2754 | <height>0</height> | ||
| 2755 | </size> | ||
| 2756 | </property> | ||
| 2757 | <property name="maximumSize"> | ||
| 2758 | <size> | ||
| 2759 | <width>55</width> | ||
| 2760 | <height>16777215</height> | ||
| 2761 | </size> | ||
| 2762 | </property> | ||
| 2763 | <property name="styleSheet"> | ||
| 2764 | <string notr="true">min-width: 55px;</string> | ||
| 2765 | </property> | ||
| 2766 | <property name="text"> | ||
| 2767 | <string>Pressed</string> | ||
| 2768 | </property> | ||
| 2769 | </widget> | ||
| 2770 | </item> | ||
| 2771 | </layout> | ||
| 2772 | </widget> | ||
| 2773 | </item> | ||
| 2774 | <item alignment="Qt::AlignHCenter"> | ||
| 2775 | <widget class="QGroupBox" name="buttonRStickModGroup"> | ||
| 2776 | <property name="title"> | ||
| 2777 | <string>Modifier</string> | ||
| 2778 | </property> | ||
| 2779 | <property name="alignment"> | ||
| 2780 | <set>Qt::AlignCenter</set> | ||
| 2781 | </property> | ||
| 2782 | <layout class="QVBoxLayout" name="buttonRStickModVerticalLayout"> | ||
| 2783 | <property name="spacing"> | ||
| 2784 | <number>3</number> | ||
| 2785 | </property> | ||
| 2786 | <property name="leftMargin"> | ||
| 2787 | <number>3</number> | ||
| 2788 | </property> | ||
| 2789 | <property name="topMargin"> | ||
| 2790 | <number>3</number> | ||
| 2791 | </property> | ||
| 2792 | <property name="rightMargin"> | ||
| 2793 | <number>3</number> | ||
| 2794 | </property> | ||
| 2795 | <property name="bottomMargin"> | ||
| 2796 | <number>3</number> | ||
| 2797 | </property> | ||
| 2798 | <item> | ||
| 2799 | <widget class="QPushButton" name="buttonRStickMod"> | ||
| 2800 | <property name="minimumSize"> | ||
| 2801 | <size> | ||
| 2802 | <width>57</width> | ||
| 2803 | <height>0</height> | ||
| 2804 | </size> | ||
| 2805 | </property> | ||
| 2806 | <property name="maximumSize"> | ||
| 2807 | <size> | ||
| 2808 | <width>55</width> | ||
| 2809 | <height>16777215</height> | ||
| 2810 | </size> | ||
| 2811 | </property> | ||
| 2812 | <property name="styleSheet"> | ||
| 2813 | <string notr="true">min-width: 55px;</string> | ||
| 2814 | </property> | ||
| 2815 | <property name="text"> | ||
| 2816 | <string>Modifier</string> | ||
| 2817 | </property> | ||
| 2818 | </widget> | ||
| 2819 | </item> | ||
| 2820 | </layout> | ||
| 2821 | </widget> | ||
| 2822 | </item> | ||
| 2823 | <item> | ||
| 2824 | <widget class="QGroupBox" name="buttonRStickRangeGroup"> | ||
| 2825 | <property name="title"> | ||
| 2826 | <string>Range</string> | ||
| 2827 | </property> | ||
| 2828 | <layout class="QHBoxLayout" name="buttonRStickRangeGroupHorizontalLayout"> | ||
| 2829 | <property name="spacing"> | ||
| 2830 | <number>3</number> | ||
| 2831 | </property> | ||
| 2832 | <property name="leftMargin"> | ||
| 2833 | <number>3</number> | ||
| 2834 | </property> | ||
| 2835 | <property name="topMargin"> | ||
| 2836 | <number>3</number> | ||
| 2837 | </property> | ||
| 2838 | <property name="rightMargin"> | ||
| 2839 | <number>3</number> | ||
| 2840 | </property> | ||
| 2841 | <property name="bottomMargin"> | ||
| 2842 | <number>3</number> | ||
| 2843 | </property> | ||
| 2844 | <item> | ||
| 2845 | <widget class="QSpinBox" name="spinboxRStickRange"> | ||
| 2846 | <property name="minimumSize"> | ||
| 2847 | <size> | ||
| 2848 | <width>55</width> | ||
| 2849 | <height>21</height> | ||
| 2850 | </size> | ||
| 2851 | </property> | ||
| 2852 | <property name="maximumSize"> | ||
| 2853 | <size> | ||
| 2854 | <width>55</width> | ||
| 2855 | <height>16777215</height> | ||
| 2856 | </size> | ||
| 2857 | </property> | ||
| 2858 | <property name="suffix"> | ||
| 2859 | <string>%</string> | ||
| 2860 | </property> | ||
| 2861 | <property name="minimum"> | ||
| 2862 | <number>50</number> | ||
| 2863 | </property> | ||
| 2864 | <property name="maximum"> | ||
| 2865 | <number>150</number> | ||
| 2866 | </property> | ||
| 2867 | <property name="value"> | ||
| 2868 | <number>100</number> | ||
| 2869 | </property> | ||
| 2870 | </widget> | ||
| 2871 | </item> | ||
| 2872 | </layout> | ||
| 2873 | </widget> | ||
| 2874 | </item> | ||
| 2875 | </layout> | ||
| 2876 | </item> | ||
| 2877 | <item> | ||
| 2878 | <layout class="QVBoxLayout" name="sliderRStickDeadzoneModifierRangeVerticalLayout"> | ||
| 2879 | <property name="spacing"> | ||
| 2880 | <number>3</number> | ||
| 2881 | </property> | ||
| 2882 | <property name="leftMargin"> | ||
| 2883 | <number>0</number> | ||
| 2884 | </property> | ||
| 2885 | <property name="topMargin"> | ||
| 2886 | <number>2</number> | ||
| 2887 | </property> | ||
| 2888 | <property name="rightMargin"> | ||
| 2889 | <number>0</number> | ||
| 2890 | </property> | ||
| 2891 | <property name="bottomMargin"> | ||
| 2892 | <number>3</number> | ||
| 2893 | </property> | ||
| 2894 | <item> | ||
| 2895 | <layout class="QHBoxLayout" name="sliderRStickDeadzoneHorizontalLayout"> | ||
| 2896 | <item> | ||
| 2897 | <widget class="QLabel" name="labelRStickDeadzone"> | ||
| 2898 | <property name="text"> | ||
| 2899 | <string>Deadzone: 0%</string> | ||
| 2900 | </property> | ||
| 2901 | <property name="alignment"> | ||
| 2902 | <set>Qt::AlignHCenter</set> | ||
| 2903 | </property> | ||
| 2904 | </widget> | ||
| 2905 | </item> | ||
| 2906 | </layout> | ||
| 2907 | </item> | ||
| 2908 | <item> | ||
| 2909 | <widget class="QSlider" name="sliderRStickDeadzone"> | ||
| 2910 | <property name="maximum"> | ||
| 2911 | <number>100</number> | ||
| 2912 | </property> | ||
| 2913 | <property name="orientation"> | ||
| 2914 | <enum>Qt::Horizontal</enum> | ||
| 2915 | </property> | ||
| 2916 | </widget> | ||
| 2917 | </item> | ||
| 2918 | <item> | ||
| 2919 | <layout class="QHBoxLayout" name="sliderRStickModifierRangeHorizontalLayout"> | ||
| 2920 | <item> | ||
| 2921 | <widget class="QLabel" name="labelRStickModifierRange"> | ||
| 2922 | <property name="text"> | ||
| 2923 | <string>Modifier Range: 0%</string> | ||
| 2924 | </property> | ||
| 2925 | <property name="alignment"> | ||
| 2926 | <set>Qt::AlignHCenter</set> | ||
| 2927 | </property> | ||
| 2928 | </widget> | ||
| 2929 | </item> | ||
| 2930 | </layout> | ||
| 2931 | </item> | ||
| 2932 | <item> | ||
| 2933 | <widget class="QSlider" name="sliderRStickModifierRange"> | ||
| 2934 | <property name="maximum"> | ||
| 2935 | <number>100</number> | ||
| 2936 | </property> | ||
| 2937 | <property name="orientation"> | ||
| 2938 | <enum>Qt::Horizontal</enum> | ||
| 2939 | </property> | ||
| 2940 | </widget> | ||
| 2941 | </item> | ||
| 2942 | </layout> | ||
| 2943 | </item> | ||
| 2944 | </layout> | ||
| 2945 | </widget> | ||
| 2946 | </item> | ||
| 2947 | <item> | ||
| 2948 | <spacer name="verticalSpacerBottomRight_2"> | ||
| 2949 | <property name="orientation"> | ||
| 2950 | <enum>Qt::Vertical</enum> | ||
| 2951 | </property> | ||
| 2952 | <property name="sizeHint" stdset="0"> | ||
| 2953 | <size> | ||
| 2954 | <width>20</width> | ||
| 2955 | <height>0</height> | ||
| 2956 | </size> | ||
| 2957 | </property> | ||
| 2958 | </spacer> | ||
| 2959 | </item> | ||
| 2960 | </layout> | ||
| 2961 | </widget> | ||
| 1104 | </item> | 2962 | </item> |
| 1105 | </layout> | 2963 | </layout> |
| 1106 | </widget> | 2964 | </widget> |
| 1107 | </item> | 2965 | </item> |
| 1108 | </layout> | 2966 | </layout> |
| 1109 | </item> | 2967 | </item> |
| 1110 | <item> | ||
| 1111 | <spacer name="verticalSpacer"> | ||
| 1112 | <property name="orientation"> | ||
| 1113 | <enum>Qt::Vertical</enum> | ||
| 1114 | </property> | ||
| 1115 | <property name="sizeHint" stdset="0"> | ||
| 1116 | <size> | ||
| 1117 | <width>20</width> | ||
| 1118 | <height>40</height> | ||
| 1119 | </size> | ||
| 1120 | </property> | ||
| 1121 | </spacer> | ||
| 1122 | </item> | ||
| 1123 | <item> | ||
| 1124 | <layout class="QHBoxLayout" name="horizontalLayout"/> | ||
| 1125 | </item> | ||
| 1126 | <item> | ||
| 1127 | <layout class="QHBoxLayout" name="horizontalLayout_2"> | ||
| 1128 | <item> | ||
| 1129 | <widget class="QPushButton" name="buttonClearAll"> | ||
| 1130 | <property name="sizePolicy"> | ||
| 1131 | <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> | ||
| 1132 | <horstretch>0</horstretch> | ||
| 1133 | <verstretch>0</verstretch> | ||
| 1134 | </sizepolicy> | ||
| 1135 | </property> | ||
| 1136 | <property name="sizeIncrement"> | ||
| 1137 | <size> | ||
| 1138 | <width>0</width> | ||
| 1139 | <height>0</height> | ||
| 1140 | </size> | ||
| 1141 | </property> | ||
| 1142 | <property name="baseSize"> | ||
| 1143 | <size> | ||
| 1144 | <width>0</width> | ||
| 1145 | <height>0</height> | ||
| 1146 | </size> | ||
| 1147 | </property> | ||
| 1148 | <property name="layoutDirection"> | ||
| 1149 | <enum>Qt::LeftToRight</enum> | ||
| 1150 | </property> | ||
| 1151 | <property name="text"> | ||
| 1152 | <string>Clear All</string> | ||
| 1153 | </property> | ||
| 1154 | </widget> | ||
| 1155 | </item> | ||
| 1156 | <item> | ||
| 1157 | <widget class="QPushButton" name="buttonRestoreDefaults"> | ||
| 1158 | <property name="sizePolicy"> | ||
| 1159 | <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> | ||
| 1160 | <horstretch>0</horstretch> | ||
| 1161 | <verstretch>0</verstretch> | ||
| 1162 | </sizepolicy> | ||
| 1163 | </property> | ||
| 1164 | <property name="sizeIncrement"> | ||
| 1165 | <size> | ||
| 1166 | <width>0</width> | ||
| 1167 | <height>0</height> | ||
| 1168 | </size> | ||
| 1169 | </property> | ||
| 1170 | <property name="baseSize"> | ||
| 1171 | <size> | ||
| 1172 | <width>0</width> | ||
| 1173 | <height>0</height> | ||
| 1174 | </size> | ||
| 1175 | </property> | ||
| 1176 | <property name="layoutDirection"> | ||
| 1177 | <enum>Qt::LeftToRight</enum> | ||
| 1178 | </property> | ||
| 1179 | <property name="text"> | ||
| 1180 | <string>Restore Defaults</string> | ||
| 1181 | </property> | ||
| 1182 | </widget> | ||
| 1183 | </item> | ||
| 1184 | <item> | ||
| 1185 | <spacer name="horizontalSpacer"> | ||
| 1186 | <property name="orientation"> | ||
| 1187 | <enum>Qt::Horizontal</enum> | ||
| 1188 | </property> | ||
| 1189 | <property name="sizeHint" stdset="0"> | ||
| 1190 | <size> | ||
| 1191 | <width>40</width> | ||
| 1192 | <height>20</height> | ||
| 1193 | </size> | ||
| 1194 | </property> | ||
| 1195 | </spacer> | ||
| 1196 | </item> | ||
| 1197 | <item> | ||
| 1198 | <widget class="QDialogButtonBox" name="buttonBox"> | ||
| 1199 | <property name="standardButtons"> | ||
| 1200 | <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> | ||
| 1201 | </property> | ||
| 1202 | </widget> | ||
| 1203 | </item> | ||
| 1204 | </layout> | ||
| 1205 | </item> | ||
| 1206 | </layout> | 2968 | </layout> |
| 1207 | </widget> | 2969 | </widget> |
| 1208 | <resources/> | 2970 | <resources> |
| 1209 | <connections> | 2971 | <include location="../../../dist/icons/controller/controller.qrc"/> |
| 1210 | <connection> | 2972 | </resources> |
| 1211 | <sender>buttonBox</sender> | 2973 | <connections/> |
| 1212 | <signal>accepted()</signal> | ||
| 1213 | <receiver>ConfigureInputPlayer</receiver> | ||
| 1214 | <slot>accept()</slot> | ||
| 1215 | <hints> | ||
| 1216 | <hint type="sourcelabel"> | ||
| 1217 | <x>371</x> | ||
| 1218 | <y>730</y> | ||
| 1219 | </hint> | ||
| 1220 | <hint type="destinationlabel"> | ||
| 1221 | <x>229</x> | ||
| 1222 | <y>375</y> | ||
| 1223 | </hint> | ||
| 1224 | </hints> | ||
| 1225 | </connection> | ||
| 1226 | <connection> | ||
| 1227 | <sender>buttonBox</sender> | ||
| 1228 | <signal>rejected()</signal> | ||
| 1229 | <receiver>ConfigureInputPlayer</receiver> | ||
| 1230 | <slot>reject()</slot> | ||
| 1231 | <hints> | ||
| 1232 | <hint type="sourcelabel"> | ||
| 1233 | <x>371</x> | ||
| 1234 | <y>730</y> | ||
| 1235 | </hint> | ||
| 1236 | <hint type="destinationlabel"> | ||
| 1237 | <x>229</x> | ||
| 1238 | <y>375</y> | ||
| 1239 | </hint> | ||
| 1240 | </hints> | ||
| 1241 | </connection> | ||
| 1242 | </connections> | ||
| 1243 | </ui> | 2974 | </ui> |
diff --git a/src/yuzu/configuration/configure_input_simple.cpp b/src/yuzu/configuration/configure_input_simple.cpp deleted file mode 100644 index 0e0e8f113..000000000 --- a/src/yuzu/configuration/configure_input_simple.cpp +++ /dev/null | |||
| @@ -1,152 +0,0 @@ | |||
| 1 | // Copyright 2016 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <array> | ||
| 6 | #include <tuple> | ||
| 7 | |||
| 8 | #include "ui_configure_input_simple.h" | ||
| 9 | #include "yuzu/configuration/configure_input.h" | ||
| 10 | #include "yuzu/configuration/configure_input_player.h" | ||
| 11 | #include "yuzu/configuration/configure_input_simple.h" | ||
| 12 | #include "yuzu/uisettings.h" | ||
| 13 | |||
| 14 | namespace { | ||
| 15 | |||
| 16 | template <typename Dialog, typename... Args> | ||
| 17 | void CallConfigureDialog(ConfigureInputSimple* caller, Args&&... args) { | ||
| 18 | caller->ApplyConfiguration(); | ||
| 19 | Dialog dialog(caller, std::forward<Args>(args)...); | ||
| 20 | |||
| 21 | const auto res = dialog.exec(); | ||
| 22 | if (res == QDialog::Accepted) { | ||
| 23 | dialog.ApplyConfiguration(); | ||
| 24 | } | ||
| 25 | } | ||
| 26 | |||
| 27 | // OnProfileSelect functions should (when applicable): | ||
| 28 | // - Set controller types | ||
| 29 | // - Set controller enabled | ||
| 30 | // - Set docked mode | ||
| 31 | // - Set advanced controller config/enabled (i.e. debug, kbd, mouse, touch) | ||
| 32 | // | ||
| 33 | // OnProfileSelect function should NOT however: | ||
| 34 | // - Reset any button mappings | ||
| 35 | // - Open any dialogs | ||
| 36 | // - Block in any way | ||
| 37 | |||
| 38 | constexpr std::size_t PLAYER_0_INDEX = 0; | ||
| 39 | constexpr std::size_t HANDHELD_INDEX = 8; | ||
| 40 | |||
| 41 | void HandheldOnProfileSelect() { | ||
| 42 | Settings::values.players[HANDHELD_INDEX].connected = true; | ||
| 43 | Settings::values.players[HANDHELD_INDEX].type = Settings::ControllerType::DualJoycon; | ||
| 44 | |||
| 45 | for (std::size_t player = 0; player < HANDHELD_INDEX; ++player) { | ||
| 46 | Settings::values.players[player].connected = false; | ||
| 47 | } | ||
| 48 | |||
| 49 | Settings::values.use_docked_mode = false; | ||
| 50 | Settings::values.keyboard_enabled = false; | ||
| 51 | Settings::values.mouse_enabled = false; | ||
| 52 | Settings::values.debug_pad_enabled = false; | ||
| 53 | Settings::values.touchscreen.enabled = true; | ||
| 54 | } | ||
| 55 | |||
| 56 | void DualJoyconsDockedOnProfileSelect() { | ||
| 57 | Settings::values.players[PLAYER_0_INDEX].connected = true; | ||
| 58 | Settings::values.players[PLAYER_0_INDEX].type = Settings::ControllerType::DualJoycon; | ||
| 59 | |||
| 60 | for (std::size_t player = 1; player <= HANDHELD_INDEX; ++player) { | ||
| 61 | Settings::values.players[player].connected = false; | ||
| 62 | } | ||
| 63 | |||
| 64 | Settings::values.use_docked_mode = true; | ||
| 65 | Settings::values.keyboard_enabled = false; | ||
| 66 | Settings::values.mouse_enabled = false; | ||
| 67 | Settings::values.debug_pad_enabled = false; | ||
| 68 | Settings::values.touchscreen.enabled = true; | ||
| 69 | } | ||
| 70 | |||
| 71 | // Name, OnProfileSelect (called when selected in drop down), OnConfigure (called when configure | ||
| 72 | // is clicked) | ||
| 73 | using InputProfile = std::tuple<const char*, void (*)(), void (*)(ConfigureInputSimple*)>; | ||
| 74 | |||
| 75 | constexpr std::array<InputProfile, 3> INPUT_PROFILES{{ | ||
| 76 | {QT_TR_NOOP("Single Player - Handheld - Undocked"), HandheldOnProfileSelect, | ||
| 77 | [](ConfigureInputSimple* caller) { | ||
| 78 | CallConfigureDialog<ConfigureInputPlayer>(caller, HANDHELD_INDEX, false); | ||
| 79 | }}, | ||
| 80 | {QT_TR_NOOP("Single Player - Dual Joycons - Docked"), DualJoyconsDockedOnProfileSelect, | ||
| 81 | [](ConfigureInputSimple* caller) { | ||
| 82 | CallConfigureDialog<ConfigureInputPlayer>(caller, PLAYER_0_INDEX, false); | ||
| 83 | }}, | ||
| 84 | {QT_TR_NOOP("Custom"), [] {}, CallConfigureDialog<ConfigureInput>}, | ||
| 85 | }}; | ||
| 86 | |||
| 87 | } // namespace | ||
| 88 | |||
| 89 | void ApplyInputProfileConfiguration(int profile_index) { | ||
| 90 | std::get<1>( | ||
| 91 | INPUT_PROFILES.at(std::min(profile_index, static_cast<int>(INPUT_PROFILES.size() - 1))))(); | ||
| 92 | } | ||
| 93 | |||
| 94 | ConfigureInputSimple::ConfigureInputSimple(QWidget* parent) | ||
| 95 | : QWidget(parent), ui(std::make_unique<Ui::ConfigureInputSimple>()) { | ||
| 96 | ui->setupUi(this); | ||
| 97 | |||
| 98 | for (const auto& profile : INPUT_PROFILES) { | ||
| 99 | const QString label = tr(std::get<0>(profile)); | ||
| 100 | ui->profile_combobox->addItem(label, label); | ||
| 101 | } | ||
| 102 | |||
| 103 | connect(ui->profile_combobox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, | ||
| 104 | &ConfigureInputSimple::OnSelectProfile); | ||
| 105 | connect(ui->profile_configure, &QPushButton::clicked, this, &ConfigureInputSimple::OnConfigure); | ||
| 106 | |||
| 107 | LoadConfiguration(); | ||
| 108 | } | ||
| 109 | |||
| 110 | ConfigureInputSimple::~ConfigureInputSimple() = default; | ||
| 111 | |||
| 112 | void ConfigureInputSimple::ApplyConfiguration() { | ||
| 113 | auto index = ui->profile_combobox->currentIndex(); | ||
| 114 | // Make the stored index for "Custom" very large so that if new profiles are added it | ||
| 115 | // doesn't change. | ||
| 116 | if (index >= static_cast<int>(INPUT_PROFILES.size() - 1)) { | ||
| 117 | index = std::numeric_limits<int>::max(); | ||
| 118 | } | ||
| 119 | |||
| 120 | UISettings::values.profile_index = index; | ||
| 121 | } | ||
| 122 | |||
| 123 | void ConfigureInputSimple::changeEvent(QEvent* event) { | ||
| 124 | if (event->type() == QEvent::LanguageChange) { | ||
| 125 | RetranslateUI(); | ||
| 126 | } | ||
| 127 | |||
| 128 | QWidget::changeEvent(event); | ||
| 129 | } | ||
| 130 | |||
| 131 | void ConfigureInputSimple::RetranslateUI() { | ||
| 132 | ui->retranslateUi(this); | ||
| 133 | } | ||
| 134 | |||
| 135 | void ConfigureInputSimple::LoadConfiguration() { | ||
| 136 | const auto index = UISettings::values.profile_index; | ||
| 137 | if (index >= static_cast<int>(INPUT_PROFILES.size()) || index < 0) { | ||
| 138 | ui->profile_combobox->setCurrentIndex(static_cast<int>(INPUT_PROFILES.size() - 1)); | ||
| 139 | } else { | ||
| 140 | ui->profile_combobox->setCurrentIndex(index); | ||
| 141 | } | ||
| 142 | } | ||
| 143 | |||
| 144 | void ConfigureInputSimple::OnSelectProfile(int index) { | ||
| 145 | const auto old_docked = Settings::values.use_docked_mode; | ||
| 146 | ApplyInputProfileConfiguration(index); | ||
| 147 | OnDockedModeChanged(old_docked, Settings::values.use_docked_mode); | ||
| 148 | } | ||
| 149 | |||
| 150 | void ConfigureInputSimple::OnConfigure() { | ||
| 151 | std::get<2>(INPUT_PROFILES.at(ui->profile_combobox->currentIndex()))(this); | ||
| 152 | } | ||
diff --git a/src/yuzu/configuration/configure_input_simple.h b/src/yuzu/configuration/configure_input_simple.h deleted file mode 100644 index bb5050224..000000000 --- a/src/yuzu/configuration/configure_input_simple.h +++ /dev/null | |||
| @@ -1,43 +0,0 @@ | |||
| 1 | // Copyright 2016 Citra 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 <memory> | ||
| 8 | |||
| 9 | #include <QWidget> | ||
| 10 | |||
| 11 | class QPushButton; | ||
| 12 | class QString; | ||
| 13 | class QTimer; | ||
| 14 | |||
| 15 | namespace Ui { | ||
| 16 | class ConfigureInputSimple; | ||
| 17 | } | ||
| 18 | |||
| 19 | // Used by configuration loader to apply a profile if the input is invalid. | ||
| 20 | void ApplyInputProfileConfiguration(int profile_index); | ||
| 21 | |||
| 22 | class ConfigureInputSimple : public QWidget { | ||
| 23 | Q_OBJECT | ||
| 24 | |||
| 25 | public: | ||
| 26 | explicit ConfigureInputSimple(QWidget* parent = nullptr); | ||
| 27 | ~ConfigureInputSimple() override; | ||
| 28 | |||
| 29 | /// Save all button configurations to settings file | ||
| 30 | void ApplyConfiguration(); | ||
| 31 | |||
| 32 | private: | ||
| 33 | void changeEvent(QEvent* event) override; | ||
| 34 | void RetranslateUI(); | ||
| 35 | |||
| 36 | /// Load configuration settings. | ||
| 37 | void LoadConfiguration(); | ||
| 38 | |||
| 39 | void OnSelectProfile(int index); | ||
| 40 | void OnConfigure(); | ||
| 41 | |||
| 42 | std::unique_ptr<Ui::ConfigureInputSimple> ui; | ||
| 43 | }; | ||
diff --git a/src/yuzu/configuration/configure_input_simple.ui b/src/yuzu/configuration/configure_input_simple.ui deleted file mode 100644 index c4889caa9..000000000 --- a/src/yuzu/configuration/configure_input_simple.ui +++ /dev/null | |||
| @@ -1,97 +0,0 @@ | |||
| 1 | <?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | <ui version="4.0"> | ||
| 3 | <class>ConfigureInputSimple</class> | ||
| 4 | <widget class="QWidget" name="ConfigureInputSimple"> | ||
| 5 | <property name="geometry"> | ||
| 6 | <rect> | ||
| 7 | <x>0</x> | ||
| 8 | <y>0</y> | ||
| 9 | <width>473</width> | ||
| 10 | <height>685</height> | ||
| 11 | </rect> | ||
| 12 | </property> | ||
| 13 | <property name="windowTitle"> | ||
| 14 | <string>ConfigureInputSimple</string> | ||
| 15 | </property> | ||
| 16 | <layout class="QVBoxLayout" name="verticalLayout_5"> | ||
| 17 | <item> | ||
| 18 | <layout class="QVBoxLayout" name="verticalLayout"> | ||
| 19 | <item> | ||
| 20 | <widget class="QGroupBox" name="gridGroupBox"> | ||
| 21 | <property name="title"> | ||
| 22 | <string>Profile</string> | ||
| 23 | </property> | ||
| 24 | <layout class="QGridLayout" name="gridLayout"> | ||
| 25 | <item row="1" column="2"> | ||
| 26 | <widget class="QPushButton" name="profile_configure"> | ||
| 27 | <property name="text"> | ||
| 28 | <string>Configure</string> | ||
| 29 | </property> | ||
| 30 | </widget> | ||
| 31 | </item> | ||
| 32 | <item row="1" column="0"> | ||
| 33 | <spacer name="horizontalSpacer"> | ||
| 34 | <property name="orientation"> | ||
| 35 | <enum>Qt::Horizontal</enum> | ||
| 36 | </property> | ||
| 37 | <property name="sizeHint" stdset="0"> | ||
| 38 | <size> | ||
| 39 | <width>40</width> | ||
| 40 | <height>20</height> | ||
| 41 | </size> | ||
| 42 | </property> | ||
| 43 | </spacer> | ||
| 44 | </item> | ||
| 45 | <item row="1" column="3"> | ||
| 46 | <spacer name="horizontalSpacer_2"> | ||
| 47 | <property name="orientation"> | ||
| 48 | <enum>Qt::Horizontal</enum> | ||
| 49 | </property> | ||
| 50 | <property name="sizeHint" stdset="0"> | ||
| 51 | <size> | ||
| 52 | <width>40</width> | ||
| 53 | <height>20</height> | ||
| 54 | </size> | ||
| 55 | </property> | ||
| 56 | </spacer> | ||
| 57 | </item> | ||
| 58 | <item row="1" column="1"> | ||
| 59 | <widget class="QComboBox" name="profile_combobox"> | ||
| 60 | <property name="minimumSize"> | ||
| 61 | <size> | ||
| 62 | <width>250</width> | ||
| 63 | <height>0</height> | ||
| 64 | </size> | ||
| 65 | </property> | ||
| 66 | </widget> | ||
| 67 | </item> | ||
| 68 | <item row="0" column="1" colspan="2"> | ||
| 69 | <widget class="QLabel" name="label"> | ||
| 70 | <property name="text"> | ||
| 71 | <string>Choose a controller configuration:</string> | ||
| 72 | </property> | ||
| 73 | </widget> | ||
| 74 | </item> | ||
| 75 | </layout> | ||
| 76 | </widget> | ||
| 77 | </item> | ||
| 78 | </layout> | ||
| 79 | </item> | ||
| 80 | <item> | ||
| 81 | <spacer name="verticalSpacer"> | ||
| 82 | <property name="orientation"> | ||
| 83 | <enum>Qt::Vertical</enum> | ||
| 84 | </property> | ||
| 85 | <property name="sizeHint" stdset="0"> | ||
| 86 | <size> | ||
| 87 | <width>20</width> | ||
| 88 | <height>40</height> | ||
| 89 | </size> | ||
| 90 | </property> | ||
| 91 | </spacer> | ||
| 92 | </item> | ||
| 93 | </layout> | ||
| 94 | </widget> | ||
| 95 | <resources/> | ||
| 96 | <connections/> | ||
| 97 | </ui> | ||
diff --git a/src/yuzu/configuration/configure_mouse_advanced.cpp b/src/yuzu/configuration/configure_mouse_advanced.cpp index ea2549363..2af3afda8 100644 --- a/src/yuzu/configuration/configure_mouse_advanced.cpp +++ b/src/yuzu/configuration/configure_mouse_advanced.cpp | |||
| @@ -18,6 +18,16 @@ | |||
| 18 | 18 | ||
| 19 | static QString GetKeyName(int key_code) { | 19 | static QString GetKeyName(int key_code) { |
| 20 | switch (key_code) { | 20 | switch (key_code) { |
| 21 | case Qt::LeftButton: | ||
| 22 | return QObject::tr("Click 0"); | ||
| 23 | case Qt::RightButton: | ||
| 24 | return QObject::tr("Click 1"); | ||
| 25 | case Qt::MiddleButton: | ||
| 26 | return QObject::tr("Click 2"); | ||
| 27 | case Qt::BackButton: | ||
| 28 | return QObject::tr("Click 3"); | ||
| 29 | case Qt::ForwardButton: | ||
| 30 | return QObject::tr("Click 4"); | ||
| 21 | case Qt::Key_Shift: | 31 | case Qt::Key_Shift: |
| 22 | return QObject::tr("Shift"); | 32 | return QObject::tr("Shift"); |
| 23 | case Qt::Key_Control: | 33 | case Qt::Key_Control: |
| @@ -66,8 +76,10 @@ static QString ButtonToText(const Common::ParamPackage& param) { | |||
| 66 | return QObject::tr("[unknown]"); | 76 | return QObject::tr("[unknown]"); |
| 67 | } | 77 | } |
| 68 | 78 | ||
| 69 | ConfigureMouseAdvanced::ConfigureMouseAdvanced(QWidget* parent) | 79 | ConfigureMouseAdvanced::ConfigureMouseAdvanced(QWidget* parent, |
| 70 | : QDialog(parent), ui(std::make_unique<Ui::ConfigureMouseAdvanced>()), | 80 | InputCommon::InputSubsystem* input_subsystem_) |
| 81 | : QDialog(parent), | ||
| 82 | ui(std::make_unique<Ui::ConfigureMouseAdvanced>()), input_subsystem{input_subsystem_}, | ||
| 71 | timeout_timer(std::make_unique<QTimer>()), poll_timer(std::make_unique<QTimer>()) { | 83 | timeout_timer(std::make_unique<QTimer>()), poll_timer(std::make_unique<QTimer>()) { |
| 72 | ui->setupUi(this); | 84 | ui->setupUi(this); |
| 73 | setFocusPolicy(Qt::ClickFocus); | 85 | setFocusPolicy(Qt::ClickFocus); |
| @@ -84,11 +96,12 @@ ConfigureMouseAdvanced::ConfigureMouseAdvanced(QWidget* parent) | |||
| 84 | 96 | ||
| 85 | button->setContextMenuPolicy(Qt::CustomContextMenu); | 97 | button->setContextMenuPolicy(Qt::CustomContextMenu); |
| 86 | connect(button, &QPushButton::clicked, [=, this] { | 98 | connect(button, &QPushButton::clicked, [=, this] { |
| 87 | HandleClick(button_map[button_id], | 99 | HandleClick( |
| 88 | [=, this](const Common::ParamPackage& params) { | 100 | button_map[button_id], |
| 89 | buttons_param[button_id] = params; | 101 | [=, this](const Common::ParamPackage& params) { |
| 90 | }, | 102 | buttons_param[button_id] = params; |
| 91 | InputCommon::Polling::DeviceType::Button); | 103 | }, |
| 104 | InputCommon::Polling::DeviceType::Button); | ||
| 92 | }); | 105 | }); |
| 93 | connect(button, &QPushButton::customContextMenuRequested, | 106 | connect(button, &QPushButton::customContextMenuRequested, |
| 94 | [=, this](const QPoint& menu_location) { | 107 | [=, this](const QPoint& menu_location) { |
| @@ -187,9 +200,9 @@ void ConfigureMouseAdvanced::HandleClick( | |||
| 187 | button->setText(tr("[press key]")); | 200 | button->setText(tr("[press key]")); |
| 188 | button->setFocus(); | 201 | button->setFocus(); |
| 189 | 202 | ||
| 190 | // Keyboard keys can only be used as button devices | 203 | // Keyboard keys or mouse buttons can only be used as button devices |
| 191 | want_keyboard_keys = type == InputCommon::Polling::DeviceType::Button; | 204 | want_keyboard_mouse = type == InputCommon::Polling::DeviceType::Button; |
| 192 | if (want_keyboard_keys) { | 205 | if (want_keyboard_mouse) { |
| 193 | const auto iter = std::find(button_map.begin(), button_map.end(), button); | 206 | const auto iter = std::find(button_map.begin(), button_map.end(), button); |
| 194 | ASSERT(iter != button_map.end()); | 207 | ASSERT(iter != button_map.end()); |
| 195 | const auto index = std::distance(button_map.begin(), iter); | 208 | const auto index = std::distance(button_map.begin(), iter); |
| @@ -198,27 +211,29 @@ void ConfigureMouseAdvanced::HandleClick( | |||
| 198 | 211 | ||
| 199 | input_setter = new_input_setter; | 212 | input_setter = new_input_setter; |
| 200 | 213 | ||
| 201 | device_pollers = InputCommon::Polling::GetPollers(type); | 214 | device_pollers = input_subsystem->GetPollers(type); |
| 202 | 215 | ||
| 203 | for (auto& poller : device_pollers) { | 216 | for (auto& poller : device_pollers) { |
| 204 | poller->Start(); | 217 | poller->Start(); |
| 205 | } | 218 | } |
| 206 | 219 | ||
| 207 | grabKeyboard(); | 220 | QWidget::grabMouse(); |
| 208 | grabMouse(); | 221 | QWidget::grabKeyboard(); |
| 209 | timeout_timer->start(5000); // Cancel after 5 seconds | 222 | |
| 210 | poll_timer->start(200); // Check for new inputs every 200ms | 223 | timeout_timer->start(2500); // Cancel after 2.5 seconds |
| 224 | poll_timer->start(50); // Check for new inputs every 50ms | ||
| 211 | } | 225 | } |
| 212 | 226 | ||
| 213 | void ConfigureMouseAdvanced::SetPollingResult(const Common::ParamPackage& params, bool abort) { | 227 | void ConfigureMouseAdvanced::SetPollingResult(const Common::ParamPackage& params, bool abort) { |
| 214 | releaseKeyboard(); | ||
| 215 | releaseMouse(); | ||
| 216 | timeout_timer->stop(); | 228 | timeout_timer->stop(); |
| 217 | poll_timer->stop(); | 229 | poll_timer->stop(); |
| 218 | for (auto& poller : device_pollers) { | 230 | for (auto& poller : device_pollers) { |
| 219 | poller->Stop(); | 231 | poller->Stop(); |
| 220 | } | 232 | } |
| 221 | 233 | ||
| 234 | QWidget::releaseMouse(); | ||
| 235 | QWidget::releaseKeyboard(); | ||
| 236 | |||
| 222 | if (!abort) { | 237 | if (!abort) { |
| 223 | (*input_setter)(params); | 238 | (*input_setter)(params); |
| 224 | } | 239 | } |
| @@ -227,13 +242,29 @@ void ConfigureMouseAdvanced::SetPollingResult(const Common::ParamPackage& params | |||
| 227 | input_setter = std::nullopt; | 242 | input_setter = std::nullopt; |
| 228 | } | 243 | } |
| 229 | 244 | ||
| 245 | void ConfigureMouseAdvanced::mousePressEvent(QMouseEvent* event) { | ||
| 246 | if (!input_setter || !event) { | ||
| 247 | return; | ||
| 248 | } | ||
| 249 | |||
| 250 | if (want_keyboard_mouse) { | ||
| 251 | SetPollingResult(Common::ParamPackage{InputCommon::GenerateKeyboardParam(event->button())}, | ||
| 252 | false); | ||
| 253 | } else { | ||
| 254 | // We don't want any mouse buttons, so don't stop polling | ||
| 255 | return; | ||
| 256 | } | ||
| 257 | |||
| 258 | SetPollingResult({}, true); | ||
| 259 | } | ||
| 260 | |||
| 230 | void ConfigureMouseAdvanced::keyPressEvent(QKeyEvent* event) { | 261 | void ConfigureMouseAdvanced::keyPressEvent(QKeyEvent* event) { |
| 231 | if (!input_setter || !event) { | 262 | if (!input_setter || !event) { |
| 232 | return; | 263 | return; |
| 233 | } | 264 | } |
| 234 | 265 | ||
| 235 | if (event->key() != Qt::Key_Escape) { | 266 | if (event->key() != Qt::Key_Escape) { |
| 236 | if (want_keyboard_keys) { | 267 | if (want_keyboard_mouse) { |
| 237 | SetPollingResult(Common::ParamPackage{InputCommon::GenerateKeyboardParam(event->key())}, | 268 | SetPollingResult(Common::ParamPackage{InputCommon::GenerateKeyboardParam(event->key())}, |
| 238 | false); | 269 | false); |
| 239 | } else { | 270 | } else { |
diff --git a/src/yuzu/configuration/configure_mouse_advanced.h b/src/yuzu/configuration/configure_mouse_advanced.h index 342b82412..65b6fca9a 100644 --- a/src/yuzu/configuration/configure_mouse_advanced.h +++ b/src/yuzu/configuration/configure_mouse_advanced.h | |||
| @@ -8,12 +8,14 @@ | |||
| 8 | #include <optional> | 8 | #include <optional> |
| 9 | #include <QDialog> | 9 | #include <QDialog> |
| 10 | 10 | ||
| 11 | #include "core/settings.h" | ||
| 12 | |||
| 13 | class QCheckBox; | 11 | class QCheckBox; |
| 14 | class QPushButton; | 12 | class QPushButton; |
| 15 | class QTimer; | 13 | class QTimer; |
| 16 | 14 | ||
| 15 | namespace InputCommon { | ||
| 16 | class InputSubsystem; | ||
| 17 | } | ||
| 18 | |||
| 17 | namespace Ui { | 19 | namespace Ui { |
| 18 | class ConfigureMouseAdvanced; | 20 | class ConfigureMouseAdvanced; |
| 19 | } | 21 | } |
| @@ -22,7 +24,7 @@ class ConfigureMouseAdvanced : public QDialog { | |||
| 22 | Q_OBJECT | 24 | Q_OBJECT |
| 23 | 25 | ||
| 24 | public: | 26 | public: |
| 25 | explicit ConfigureMouseAdvanced(QWidget* parent); | 27 | explicit ConfigureMouseAdvanced(QWidget* parent, InputCommon::InputSubsystem* input_subsystem_); |
| 26 | ~ConfigureMouseAdvanced() override; | 28 | ~ConfigureMouseAdvanced() override; |
| 27 | 29 | ||
| 28 | void ApplyConfiguration(); | 30 | void ApplyConfiguration(); |
| @@ -49,11 +51,16 @@ private: | |||
| 49 | /// Finish polling and configure input using the input_setter | 51 | /// Finish polling and configure input using the input_setter |
| 50 | void SetPollingResult(const Common::ParamPackage& params, bool abort); | 52 | void SetPollingResult(const Common::ParamPackage& params, bool abort); |
| 51 | 53 | ||
| 54 | /// Handle mouse button press events. | ||
| 55 | void mousePressEvent(QMouseEvent* event) override; | ||
| 56 | |||
| 52 | /// Handle key press events. | 57 | /// Handle key press events. |
| 53 | void keyPressEvent(QKeyEvent* event) override; | 58 | void keyPressEvent(QKeyEvent* event) override; |
| 54 | 59 | ||
| 55 | std::unique_ptr<Ui::ConfigureMouseAdvanced> ui; | 60 | std::unique_ptr<Ui::ConfigureMouseAdvanced> ui; |
| 56 | 61 | ||
| 62 | InputCommon::InputSubsystem* input_subsystem; | ||
| 63 | |||
| 57 | /// This will be the the setting function when an input is awaiting configuration. | 64 | /// This will be the the setting function when an input is awaiting configuration. |
| 58 | std::optional<std::function<void(const Common::ParamPackage&)>> input_setter; | 65 | std::optional<std::function<void(const Common::ParamPackage&)>> input_setter; |
| 59 | 66 | ||
| @@ -67,5 +74,5 @@ private: | |||
| 67 | 74 | ||
| 68 | /// A flag to indicate if keyboard keys are okay when configuring an input. If this is false, | 75 | /// A flag to indicate if keyboard keys are okay when configuring an input. If this is false, |
| 69 | /// keyboard events are ignored. | 76 | /// keyboard events are ignored. |
| 70 | bool want_keyboard_keys = false; | 77 | bool want_keyboard_mouse = false; |
| 71 | }; | 78 | }; |
diff --git a/src/yuzu/configuration/configure_mouse_advanced.ui b/src/yuzu/configuration/configure_mouse_advanced.ui index 08245ecf0..74552fdbd 100644 --- a/src/yuzu/configuration/configure_mouse_advanced.ui +++ b/src/yuzu/configuration/configure_mouse_advanced.ui | |||
| @@ -6,13 +6,18 @@ | |||
| 6 | <rect> | 6 | <rect> |
| 7 | <x>0</x> | 7 | <x>0</x> |
| 8 | <y>0</y> | 8 | <y>0</y> |
| 9 | <width>250</width> | 9 | <width>310</width> |
| 10 | <height>261</height> | 10 | <height>193</height> |
| 11 | </rect> | 11 | </rect> |
| 12 | </property> | 12 | </property> |
| 13 | <property name="windowTitle"> | 13 | <property name="windowTitle"> |
| 14 | <string>Configure Mouse</string> | 14 | <string>Configure Mouse</string> |
| 15 | </property> | 15 | </property> |
| 16 | <property name="styleSheet"> | ||
| 17 | <string notr="true">QPushButton { | ||
| 18 | min-width: 55px; | ||
| 19 | }</string> | ||
| 20 | </property> | ||
| 16 | <layout class="QVBoxLayout" name="verticalLayout"> | 21 | <layout class="QVBoxLayout" name="verticalLayout"> |
| 17 | <item> | 22 | <item> |
| 18 | <widget class="QGroupBox" name="gridGroupBox"> | 23 | <widget class="QGroupBox" name="gridGroupBox"> |
| @@ -20,81 +25,33 @@ | |||
| 20 | <string>Mouse Buttons</string> | 25 | <string>Mouse Buttons</string> |
| 21 | </property> | 26 | </property> |
| 22 | <layout class="QGridLayout" name="gridLayout"> | 27 | <layout class="QGridLayout" name="gridLayout"> |
| 23 | <item row="0" column="4"> | 28 | <item row="3" column="5"> |
| 24 | <spacer name="horizontalSpacer_2"> | 29 | <layout class="QVBoxLayout" name="verticalLayout_6"> |
| 25 | <property name="orientation"> | ||
| 26 | <enum>Qt::Horizontal</enum> | ||
| 27 | </property> | ||
| 28 | <property name="sizeType"> | ||
| 29 | <enum>QSizePolicy::Fixed</enum> | ||
| 30 | </property> | ||
| 31 | <property name="sizeHint" stdset="0"> | ||
| 32 | <size> | ||
| 33 | <width>20</width> | ||
| 34 | <height>20</height> | ||
| 35 | </size> | ||
| 36 | </property> | ||
| 37 | </spacer> | ||
| 38 | </item> | ||
| 39 | <item row="0" column="3"> | ||
| 40 | <layout class="QVBoxLayout" name="verticalLayout_4"> | ||
| 41 | <item> | 30 | <item> |
| 42 | <layout class="QHBoxLayout" name="horizontalLayout_3"> | 31 | <layout class="QHBoxLayout" name="horizontalLayout_5"> |
| 43 | <item> | 32 | <item> |
| 44 | <widget class="QLabel" name="label_3"> | 33 | <widget class="QLabel" name="label_5"> |
| 45 | <property name="text"> | 34 | <property name="text"> |
| 46 | <string>Right:</string> | 35 | <string>Forward:</string> |
| 47 | </property> | 36 | </property> |
| 48 | </widget> | 37 | </widget> |
| 49 | </item> | 38 | </item> |
| 50 | </layout> | 39 | </layout> |
| 51 | </item> | 40 | </item> |
| 52 | <item> | 41 | <item> |
| 53 | <widget class="QPushButton" name="right_button"> | 42 | <widget class="QPushButton" name="forward_button"> |
| 54 | <property name="minimumSize"> | 43 | <property name="minimumSize"> |
| 55 | <size> | 44 | <size> |
| 56 | <width>75</width> | 45 | <width>57</width> |
| 57 | <height>0</height> | 46 | <height>0</height> |
| 58 | </size> | 47 | </size> |
| 59 | </property> | 48 | </property> |
| 60 | <property name="text"> | 49 | <property name="maximumSize"> |
| 61 | <string/> | 50 | <size> |
| 51 | <width>16777215</width> | ||
| 52 | <height>16777215</height> | ||
| 53 | </size> | ||
| 62 | </property> | 54 | </property> |
| 63 | </widget> | ||
| 64 | </item> | ||
| 65 | </layout> | ||
| 66 | </item> | ||
| 67 | <item row="0" column="0"> | ||
| 68 | <spacer name="horizontalSpacer"> | ||
| 69 | <property name="orientation"> | ||
| 70 | <enum>Qt::Horizontal</enum> | ||
| 71 | </property> | ||
| 72 | <property name="sizeType"> | ||
| 73 | <enum>QSizePolicy::Fixed</enum> | ||
| 74 | </property> | ||
| 75 | <property name="sizeHint" stdset="0"> | ||
| 76 | <size> | ||
| 77 | <width>20</width> | ||
| 78 | <height>20</height> | ||
| 79 | </size> | ||
| 80 | </property> | ||
| 81 | </spacer> | ||
| 82 | </item> | ||
| 83 | <item row="2" column="1"> | ||
| 84 | <layout class="QVBoxLayout" name="verticalLayout_3"> | ||
| 85 | <item> | ||
| 86 | <layout class="QHBoxLayout" name="horizontalLayout_2"> | ||
| 87 | <item> | ||
| 88 | <widget class="QLabel" name="label_2"> | ||
| 89 | <property name="text"> | ||
| 90 | <string>Middle:</string> | ||
| 91 | </property> | ||
| 92 | </widget> | ||
| 93 | </item> | ||
| 94 | </layout> | ||
| 95 | </item> | ||
| 96 | <item> | ||
| 97 | <widget class="QPushButton" name="middle_button"> | ||
| 98 | <property name="text"> | 55 | <property name="text"> |
| 99 | <string/> | 56 | <string/> |
| 100 | </property> | 57 | </property> |
| @@ -123,6 +80,12 @@ | |||
| 123 | </item> | 80 | </item> |
| 124 | <item> | 81 | <item> |
| 125 | <widget class="QPushButton" name="back_button"> | 82 | <widget class="QPushButton" name="back_button"> |
| 83 | <property name="minimumSize"> | ||
| 84 | <size> | ||
| 85 | <width>57</width> | ||
| 86 | <height>0</height> | ||
| 87 | </size> | ||
| 88 | </property> | ||
| 126 | <property name="text"> | 89 | <property name="text"> |
| 127 | <string/> | 90 | <string/> |
| 128 | </property> | 91 | </property> |
| @@ -147,7 +110,7 @@ | |||
| 147 | <widget class="QPushButton" name="left_button"> | 110 | <widget class="QPushButton" name="left_button"> |
| 148 | <property name="minimumSize"> | 111 | <property name="minimumSize"> |
| 149 | <size> | 112 | <size> |
| 150 | <width>75</width> | 113 | <width>57</width> |
| 151 | <height>0</height> | 114 | <height>0</height> |
| 152 | </size> | 115 | </size> |
| 153 | </property> | 116 | </property> |
| @@ -158,21 +121,99 @@ | |||
| 158 | </item> | 121 | </item> |
| 159 | </layout> | 122 | </layout> |
| 160 | </item> | 123 | </item> |
| 161 | <item row="3" column="3"> | 124 | <item row="0" column="3"> |
| 162 | <layout class="QVBoxLayout" name="verticalLayout_6"> | 125 | <layout class="QVBoxLayout" name="verticalLayout_3"> |
| 163 | <item> | 126 | <item> |
| 164 | <layout class="QHBoxLayout" name="horizontalLayout_5"> | 127 | <layout class="QHBoxLayout" name="horizontalLayout_2"> |
| 165 | <item> | 128 | <item> |
| 166 | <widget class="QLabel" name="label_5"> | 129 | <widget class="QLabel" name="label_2"> |
| 167 | <property name="text"> | 130 | <property name="text"> |
| 168 | <string>Forward:</string> | 131 | <string>Middle:</string> |
| 169 | </property> | 132 | </property> |
| 170 | </widget> | 133 | </widget> |
| 171 | </item> | 134 | </item> |
| 172 | </layout> | 135 | </layout> |
| 173 | </item> | 136 | </item> |
| 174 | <item> | 137 | <item> |
| 175 | <widget class="QPushButton" name="forward_button"> | 138 | <widget class="QPushButton" name="middle_button"> |
| 139 | <property name="minimumSize"> | ||
| 140 | <size> | ||
| 141 | <width>57</width> | ||
| 142 | <height>0</height> | ||
| 143 | </size> | ||
| 144 | </property> | ||
| 145 | <property name="maximumSize"> | ||
| 146 | <size> | ||
| 147 | <width>16777215</width> | ||
| 148 | <height>16777215</height> | ||
| 149 | </size> | ||
| 150 | </property> | ||
| 151 | <property name="text"> | ||
| 152 | <string/> | ||
| 153 | </property> | ||
| 154 | </widget> | ||
| 155 | </item> | ||
| 156 | </layout> | ||
| 157 | </item> | ||
| 158 | <item row="0" column="6"> | ||
| 159 | <spacer name="horizontalSpacer_2"> | ||
| 160 | <property name="orientation"> | ||
| 161 | <enum>Qt::Horizontal</enum> | ||
| 162 | </property> | ||
| 163 | <property name="sizeType"> | ||
| 164 | <enum>QSizePolicy::Fixed</enum> | ||
| 165 | </property> | ||
| 166 | <property name="sizeHint" stdset="0"> | ||
| 167 | <size> | ||
| 168 | <width>0</width> | ||
| 169 | <height>20</height> | ||
| 170 | </size> | ||
| 171 | </property> | ||
| 172 | </spacer> | ||
| 173 | </item> | ||
| 174 | <item row="0" column="0"> | ||
| 175 | <spacer name="horizontalSpacer"> | ||
| 176 | <property name="orientation"> | ||
| 177 | <enum>Qt::Horizontal</enum> | ||
| 178 | </property> | ||
| 179 | <property name="sizeType"> | ||
| 180 | <enum>QSizePolicy::Fixed</enum> | ||
| 181 | </property> | ||
| 182 | <property name="sizeHint" stdset="0"> | ||
| 183 | <size> | ||
| 184 | <width>0</width> | ||
| 185 | <height>20</height> | ||
| 186 | </size> | ||
| 187 | </property> | ||
| 188 | </spacer> | ||
| 189 | </item> | ||
| 190 | <item row="0" column="5"> | ||
| 191 | <layout class="QVBoxLayout" name="verticalLayout_4"> | ||
| 192 | <item> | ||
| 193 | <layout class="QHBoxLayout" name="horizontalLayout_3"> | ||
| 194 | <item> | ||
| 195 | <widget class="QLabel" name="label_3"> | ||
| 196 | <property name="text"> | ||
| 197 | <string>Right:</string> | ||
| 198 | </property> | ||
| 199 | </widget> | ||
| 200 | </item> | ||
| 201 | </layout> | ||
| 202 | </item> | ||
| 203 | <item> | ||
| 204 | <widget class="QPushButton" name="right_button"> | ||
| 205 | <property name="minimumSize"> | ||
| 206 | <size> | ||
| 207 | <width>57</width> | ||
| 208 | <height>0</height> | ||
| 209 | </size> | ||
| 210 | </property> | ||
| 211 | <property name="maximumSize"> | ||
| 212 | <size> | ||
| 213 | <width>16777215</width> | ||
| 214 | <height>16777215</height> | ||
| 215 | </size> | ||
| 216 | </property> | ||
| 176 | <property name="text"> | 217 | <property name="text"> |
| 177 | <string/> | 218 | <string/> |
| 178 | </property> | 219 | </property> |
| @@ -180,6 +221,32 @@ | |||
| 180 | </item> | 221 | </item> |
| 181 | </layout> | 222 | </layout> |
| 182 | </item> | 223 | </item> |
| 224 | <item row="0" column="2"> | ||
| 225 | <spacer name="horizontalSpacer_4"> | ||
| 226 | <property name="orientation"> | ||
| 227 | <enum>Qt::Horizontal</enum> | ||
| 228 | </property> | ||
| 229 | <property name="sizeHint" stdset="0"> | ||
| 230 | <size> | ||
| 231 | <width>0</width> | ||
| 232 | <height>20</height> | ||
| 233 | </size> | ||
| 234 | </property> | ||
| 235 | </spacer> | ||
| 236 | </item> | ||
| 237 | <item row="0" column="4"> | ||
| 238 | <spacer name="horizontalSpacer_5"> | ||
| 239 | <property name="orientation"> | ||
| 240 | <enum>Qt::Horizontal</enum> | ||
| 241 | </property> | ||
| 242 | <property name="sizeHint" stdset="0"> | ||
| 243 | <size> | ||
| 244 | <width>0</width> | ||
| 245 | <height>20</height> | ||
| 246 | </size> | ||
| 247 | </property> | ||
| 248 | </spacer> | ||
| 249 | </item> | ||
| 183 | </layout> | 250 | </layout> |
| 184 | </widget> | 251 | </widget> |
| 185 | </item> | 252 | </item> |
| @@ -187,15 +254,39 @@ | |||
| 187 | <layout class="QHBoxLayout" name="horizontalLayout_6"> | 254 | <layout class="QHBoxLayout" name="horizontalLayout_6"> |
| 188 | <item> | 255 | <item> |
| 189 | <widget class="QPushButton" name="buttonClearAll"> | 256 | <widget class="QPushButton" name="buttonClearAll"> |
| 257 | <property name="minimumSize"> | ||
| 258 | <size> | ||
| 259 | <width>57</width> | ||
| 260 | <height>0</height> | ||
| 261 | </size> | ||
| 262 | </property> | ||
| 263 | <property name="maximumSize"> | ||
| 264 | <size> | ||
| 265 | <width>16777215</width> | ||
| 266 | <height>16777215</height> | ||
| 267 | </size> | ||
| 268 | </property> | ||
| 190 | <property name="text"> | 269 | <property name="text"> |
| 191 | <string>Clear All</string> | 270 | <string>Clear</string> |
| 192 | </property> | 271 | </property> |
| 193 | </widget> | 272 | </widget> |
| 194 | </item> | 273 | </item> |
| 195 | <item> | 274 | <item> |
| 196 | <widget class="QPushButton" name="buttonRestoreDefaults"> | 275 | <widget class="QPushButton" name="buttonRestoreDefaults"> |
| 276 | <property name="minimumSize"> | ||
| 277 | <size> | ||
| 278 | <width>57</width> | ||
| 279 | <height>0</height> | ||
| 280 | </size> | ||
| 281 | </property> | ||
| 282 | <property name="maximumSize"> | ||
| 283 | <size> | ||
| 284 | <width>16777215</width> | ||
| 285 | <height>16777215</height> | ||
| 286 | </size> | ||
| 287 | </property> | ||
| 197 | <property name="text"> | 288 | <property name="text"> |
| 198 | <string>Restore Defaults</string> | 289 | <string>Defaults</string> |
| 199 | </property> | 290 | </property> |
| 200 | </widget> | 291 | </widget> |
| 201 | </item> | 292 | </item> |
| @@ -206,21 +297,24 @@ | |||
| 206 | </property> | 297 | </property> |
| 207 | <property name="sizeHint" stdset="0"> | 298 | <property name="sizeHint" stdset="0"> |
| 208 | <size> | 299 | <size> |
| 209 | <width>40</width> | 300 | <width>0</width> |
| 210 | <height>20</height> | 301 | <height>20</height> |
| 211 | </size> | 302 | </size> |
| 212 | </property> | 303 | </property> |
| 213 | </spacer> | 304 | </spacer> |
| 214 | </item> | 305 | </item> |
| 306 | <item> | ||
| 307 | <widget class="QDialogButtonBox" name="buttonBox"> | ||
| 308 | <property name="styleSheet"> | ||
| 309 | <string notr="true"/> | ||
| 310 | </property> | ||
| 311 | <property name="standardButtons"> | ||
| 312 | <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> | ||
| 313 | </property> | ||
| 314 | </widget> | ||
| 315 | </item> | ||
| 215 | </layout> | 316 | </layout> |
| 216 | </item> | 317 | </item> |
| 217 | <item> | ||
| 218 | <widget class="QDialogButtonBox" name="buttonBox"> | ||
| 219 | <property name="standardButtons"> | ||
| 220 | <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> | ||
| 221 | </property> | ||
| 222 | </widget> | ||
| 223 | </item> | ||
| 224 | </layout> | 318 | </layout> |
| 225 | </widget> | 319 | </widget> |
| 226 | <resources/> | 320 | <resources/> |
diff --git a/src/yuzu/configuration/configure_per_game_addons.cpp b/src/yuzu/configuration/configure_per_game_addons.cpp index 478d5d3a1..793fd8975 100644 --- a/src/yuzu/configuration/configure_per_game_addons.cpp +++ b/src/yuzu/configuration/configure_per_game_addons.cpp | |||
| @@ -79,8 +79,8 @@ void ConfigurePerGameAddons::ApplyConfiguration() { | |||
| 79 | std::sort(disabled_addons.begin(), disabled_addons.end()); | 79 | std::sort(disabled_addons.begin(), disabled_addons.end()); |
| 80 | std::sort(current.begin(), current.end()); | 80 | std::sort(current.begin(), current.end()); |
| 81 | if (disabled_addons != current) { | 81 | if (disabled_addons != current) { |
| 82 | FileUtil::Delete(FileUtil::GetUserPath(FileUtil::UserPath::CacheDir) + DIR_SEP + | 82 | Common::FS::Delete(Common::FS::GetUserPath(Common::FS::UserPath::CacheDir) + DIR_SEP + |
| 83 | "game_list" + DIR_SEP + fmt::format("{:016X}.pv.txt", title_id)); | 83 | "game_list" + DIR_SEP + fmt::format("{:016X}.pv.txt", title_id)); |
| 84 | } | 84 | } |
| 85 | 85 | ||
| 86 | Settings::values.disabled_addons[title_id] = disabled_addons; | 86 | Settings::values.disabled_addons[title_id] = disabled_addons; |
diff --git a/src/yuzu/configuration/configure_profile_manager.cpp b/src/yuzu/configuration/configure_profile_manager.cpp index f53423440..6334c4c50 100644 --- a/src/yuzu/configuration/configure_profile_manager.cpp +++ b/src/yuzu/configuration/configure_profile_manager.cpp | |||
| @@ -34,7 +34,7 @@ constexpr std::array<u8, 107> backup_jpeg{ | |||
| 34 | }; | 34 | }; |
| 35 | 35 | ||
| 36 | QString GetImagePath(Common::UUID uuid) { | 36 | QString GetImagePath(Common::UUID uuid) { |
| 37 | const auto path = FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) + | 37 | const auto path = Common::FS::GetUserPath(Common::FS::UserPath::NANDDir) + |
| 38 | "/system/save/8000000000000010/su/avators/" + uuid.FormatSwitch() + ".jpg"; | 38 | "/system/save/8000000000000010/su/avators/" + uuid.FormatSwitch() + ".jpg"; |
| 39 | return QString::fromStdString(path); | 39 | return QString::fromStdString(path); |
| 40 | } | 40 | } |
| @@ -282,7 +282,7 @@ void ConfigureProfileManager::SetUserImage() { | |||
| 282 | } | 282 | } |
| 283 | 283 | ||
| 284 | const auto raw_path = QString::fromStdString( | 284 | const auto raw_path = QString::fromStdString( |
| 285 | FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) + "/system/save/8000000000000010"); | 285 | Common::FS::GetUserPath(Common::FS::UserPath::NANDDir) + "/system/save/8000000000000010"); |
| 286 | const QFileInfo raw_info{raw_path}; | 286 | const QFileInfo raw_info{raw_path}; |
| 287 | if (raw_info.exists() && !raw_info.isDir() && !QFile::remove(raw_path)) { | 287 | if (raw_info.exists() && !raw_info.isDir() && !QFile::remove(raw_path)) { |
| 288 | QMessageBox::warning(this, tr("Error deleting file"), | 288 | QMessageBox::warning(this, tr("Error deleting file"), |
diff --git a/src/yuzu/configuration/configure_system.cpp b/src/yuzu/configuration/configure_system.cpp index 0c4daf147..9ad43ed8f 100644 --- a/src/yuzu/configuration/configure_system.cpp +++ b/src/yuzu/configuration/configure_system.cpp | |||
| @@ -90,13 +90,13 @@ 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 | ConfigurationShared::SetHighlight(ui->label_language, "label_language", | 93 | ConfigurationShared::SetHighlight(ui->label_language, |
| 94 | !Settings::values.language_index.UsingGlobal()); | 94 | !Settings::values.language_index.UsingGlobal()); |
| 95 | ConfigurationShared::SetHighlight(ui->label_region, "label_region", | 95 | ConfigurationShared::SetHighlight(ui->label_region, |
| 96 | !Settings::values.region_index.UsingGlobal()); | 96 | !Settings::values.region_index.UsingGlobal()); |
| 97 | ConfigurationShared::SetHighlight(ui->label_timezone, "label_timezone", | 97 | ConfigurationShared::SetHighlight(ui->label_timezone, |
| 98 | !Settings::values.time_zone_index.UsingGlobal()); | 98 | !Settings::values.time_zone_index.UsingGlobal()); |
| 99 | ConfigurationShared::SetHighlight(ui->label_sound, "label_sound", | 99 | ConfigurationShared::SetHighlight(ui->label_sound, |
| 100 | !Settings::values.sound_index.UsingGlobal()); | 100 | !Settings::values.sound_index.UsingGlobal()); |
| 101 | } | 101 | } |
| 102 | } | 102 | } |
| @@ -224,22 +224,20 @@ void ConfigureSystem::SetupPerGameUI() { | |||
| 224 | } | 224 | } |
| 225 | 225 | ||
| 226 | ConfigurationShared::SetColoredComboBox(ui->combo_language, ui->label_language, | 226 | ConfigurationShared::SetColoredComboBox(ui->combo_language, ui->label_language, |
| 227 | "label_language", | ||
| 228 | Settings::values.language_index.GetValue(true)); | 227 | Settings::values.language_index.GetValue(true)); |
| 229 | ConfigurationShared::SetColoredComboBox(ui->combo_region, ui->label_region, "label_region", | 228 | ConfigurationShared::SetColoredComboBox(ui->combo_region, ui->label_region, |
| 230 | Settings::values.region_index.GetValue(true)); | 229 | Settings::values.region_index.GetValue(true)); |
| 231 | ConfigurationShared::SetColoredComboBox(ui->combo_time_zone, ui->label_timezone, | 230 | ConfigurationShared::SetColoredComboBox(ui->combo_time_zone, ui->label_timezone, |
| 232 | "label_timezone", | ||
| 233 | Settings::values.time_zone_index.GetValue(true)); | 231 | Settings::values.time_zone_index.GetValue(true)); |
| 234 | ConfigurationShared::SetColoredComboBox(ui->combo_sound, ui->label_sound, "label_sound", | 232 | ConfigurationShared::SetColoredComboBox(ui->combo_sound, ui->label_sound, |
| 235 | Settings::values.sound_index.GetValue(true)); | 233 | Settings::values.sound_index.GetValue(true)); |
| 236 | 234 | ||
| 237 | ConfigurationShared::SetColoredTristate( | 235 | ConfigurationShared::SetColoredTristate( |
| 238 | ui->rng_seed_checkbox, "rng_seed_checkbox", Settings::values.rng_seed.UsingGlobal(), | 236 | ui->rng_seed_checkbox, Settings::values.rng_seed.UsingGlobal(), |
| 239 | Settings::values.rng_seed.GetValue().has_value(), | 237 | Settings::values.rng_seed.GetValue().has_value(), |
| 240 | Settings::values.rng_seed.GetValue(true).has_value(), use_rng_seed); | 238 | Settings::values.rng_seed.GetValue(true).has_value(), use_rng_seed); |
| 241 | ConfigurationShared::SetColoredTristate( | 239 | ConfigurationShared::SetColoredTristate( |
| 242 | ui->custom_rtc_checkbox, "custom_rtc_checkbox", Settings::values.custom_rtc.UsingGlobal(), | 240 | ui->custom_rtc_checkbox, Settings::values.custom_rtc.UsingGlobal(), |
| 243 | Settings::values.custom_rtc.GetValue().has_value(), | 241 | Settings::values.custom_rtc.GetValue().has_value(), |
| 244 | Settings::values.custom_rtc.GetValue(true).has_value(), use_custom_rtc); | 242 | Settings::values.custom_rtc.GetValue(true).has_value(), use_custom_rtc); |
| 245 | } | 243 | } |
diff --git a/src/yuzu/configuration/configure_ui.cpp b/src/yuzu/configuration/configure_ui.cpp index 2c20b68d0..dbe3f78c8 100644 --- a/src/yuzu/configuration/configure_ui.cpp +++ b/src/yuzu/configuration/configure_ui.cpp | |||
| @@ -61,9 +61,9 @@ ConfigureUi::ConfigureUi(QWidget* parent) : QWidget(parent), ui(new Ui::Configur | |||
| 61 | // Set screenshot path to user specification. | 61 | // Set screenshot path to user specification. |
| 62 | connect(ui->screenshot_path_button, &QToolButton::pressed, this, [this] { | 62 | connect(ui->screenshot_path_button, &QToolButton::pressed, this, [this] { |
| 63 | const QString& filename = | 63 | const QString& filename = |
| 64 | QFileDialog::getExistingDirectory( | 64 | QFileDialog::getExistingDirectory(this, tr("Select Screenshots Path..."), |
| 65 | this, tr("Select Screenshots Path..."), | 65 | QString::fromStdString(Common::FS::GetUserPath( |
| 66 | QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::ScreenshotsDir))) + | 66 | Common::FS::UserPath::ScreenshotsDir))) + |
| 67 | QDir::separator(); | 67 | QDir::separator(); |
| 68 | if (!filename.isEmpty()) { | 68 | if (!filename.isEmpty()) { |
| 69 | ui->screenshot_path_edit->setText(filename); | 69 | ui->screenshot_path_edit->setText(filename); |
| @@ -82,8 +82,8 @@ void ConfigureUi::ApplyConfiguration() { | |||
| 82 | UISettings::values.row_2_text_id = ui->row_2_text_combobox->currentData().toUInt(); | 82 | UISettings::values.row_2_text_id = ui->row_2_text_combobox->currentData().toUInt(); |
| 83 | 83 | ||
| 84 | UISettings::values.enable_screenshot_save_as = ui->enable_screenshot_save_as->isChecked(); | 84 | UISettings::values.enable_screenshot_save_as = ui->enable_screenshot_save_as->isChecked(); |
| 85 | FileUtil::GetUserPath(FileUtil::UserPath::ScreenshotsDir, | 85 | Common::FS::GetUserPath(Common::FS::UserPath::ScreenshotsDir, |
| 86 | ui->screenshot_path_edit->text().toStdString()); | 86 | ui->screenshot_path_edit->text().toStdString()); |
| 87 | Settings::Apply(); | 87 | Settings::Apply(); |
| 88 | } | 88 | } |
| 89 | 89 | ||
| @@ -101,7 +101,7 @@ void ConfigureUi::SetConfiguration() { | |||
| 101 | 101 | ||
| 102 | ui->enable_screenshot_save_as->setChecked(UISettings::values.enable_screenshot_save_as); | 102 | ui->enable_screenshot_save_as->setChecked(UISettings::values.enable_screenshot_save_as); |
| 103 | ui->screenshot_path_edit->setText( | 103 | ui->screenshot_path_edit->setText( |
| 104 | QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::ScreenshotsDir))); | 104 | QString::fromStdString(Common::FS::GetUserPath(Common::FS::UserPath::ScreenshotsDir))); |
| 105 | } | 105 | } |
| 106 | 106 | ||
| 107 | void ConfigureUi::changeEvent(QEvent* event) { | 107 | void ConfigureUi::changeEvent(QEvent* event) { |
diff --git a/src/yuzu/debugger/profiler.cpp b/src/yuzu/debugger/profiler.cpp index 53049ffd6..0e26f765b 100644 --- a/src/yuzu/debugger/profiler.cpp +++ b/src/yuzu/debugger/profiler.cpp | |||
| @@ -109,8 +109,7 @@ MicroProfileWidget::MicroProfileWidget(QWidget* parent) : QWidget(parent) { | |||
| 109 | MicroProfileSetDisplayMode(1); // Timers screen | 109 | MicroProfileSetDisplayMode(1); // Timers screen |
| 110 | MicroProfileInitUI(); | 110 | MicroProfileInitUI(); |
| 111 | 111 | ||
| 112 | connect(&update_timer, &QTimer::timeout, this, | 112 | connect(&update_timer, &QTimer::timeout, this, qOverload<>(&MicroProfileWidget::update)); |
| 113 | static_cast<void (MicroProfileWidget::*)()>(&MicroProfileWidget::update)); | ||
| 114 | } | 113 | } |
| 115 | 114 | ||
| 116 | void MicroProfileWidget::paintEvent(QPaintEvent* ev) { | 115 | void MicroProfileWidget::paintEvent(QPaintEvent* ev) { |
diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp index 62acc3720..6a71d9644 100644 --- a/src/yuzu/game_list.cpp +++ b/src/yuzu/game_list.cpp | |||
| @@ -406,7 +406,7 @@ bool GameList::isEmpty() const { | |||
| 406 | type == GameListItemType::SysNandDir)) { | 406 | type == GameListItemType::SysNandDir)) { |
| 407 | item_model->invisibleRootItem()->removeRow(child->row()); | 407 | item_model->invisibleRootItem()->removeRow(child->row()); |
| 408 | i--; | 408 | i--; |
| 409 | }; | 409 | } |
| 410 | } | 410 | } |
| 411 | return !item_model->invisibleRootItem()->hasChildren(); | 411 | return !item_model->invisibleRootItem()->hasChildren(); |
| 412 | } | 412 | } |
| @@ -502,10 +502,10 @@ void GameList::AddGamePopup(QMenu& context_menu, u64 program_id, std::string pat | |||
| 502 | navigate_to_gamedb_entry->setVisible(it != compatibility_list.end() && program_id != 0); | 502 | navigate_to_gamedb_entry->setVisible(it != compatibility_list.end() && program_id != 0); |
| 503 | 503 | ||
| 504 | connect(open_save_location, &QAction::triggered, [this, program_id, path]() { | 504 | connect(open_save_location, &QAction::triggered, [this, program_id, path]() { |
| 505 | emit OpenFolderRequested(GameListOpenTarget::SaveData, path); | 505 | emit OpenFolderRequested(program_id, GameListOpenTarget::SaveData, path); |
| 506 | }); | 506 | }); |
| 507 | connect(open_mod_location, &QAction::triggered, [this, program_id, path]() { | 507 | connect(open_mod_location, &QAction::triggered, [this, program_id, path]() { |
| 508 | emit OpenFolderRequested(GameListOpenTarget::ModData, path); | 508 | emit OpenFolderRequested(program_id, GameListOpenTarget::ModData, path); |
| 509 | }); | 509 | }); |
| 510 | connect(open_transferable_shader_cache, &QAction::triggered, | 510 | connect(open_transferable_shader_cache, &QAction::triggered, |
| 511 | [this, program_id]() { emit OpenTransferableShaderCacheRequested(program_id); }); | 511 | [this, program_id]() { emit OpenTransferableShaderCacheRequested(program_id); }); |
diff --git a/src/yuzu/game_list.h b/src/yuzu/game_list.h index 483835cce..78e2ba169 100644 --- a/src/yuzu/game_list.h +++ b/src/yuzu/game_list.h | |||
| @@ -84,7 +84,8 @@ public: | |||
| 84 | signals: | 84 | signals: |
| 85 | void GameChosen(QString game_path); | 85 | void GameChosen(QString game_path); |
| 86 | void ShouldCancelWorker(); | 86 | void ShouldCancelWorker(); |
| 87 | void OpenFolderRequested(GameListOpenTarget target, const std::string& game_path); | 87 | void OpenFolderRequested(u64 program_id, GameListOpenTarget target, |
| 88 | const std::string& game_path); | ||
| 88 | void OpenTransferableShaderCacheRequested(u64 program_id); | 89 | void OpenTransferableShaderCacheRequested(u64 program_id); |
| 89 | void RemoveInstalledEntryRequested(u64 program_id, InstalledEntryType type); | 90 | void RemoveInstalledEntryRequested(u64 program_id, InstalledEntryType type); |
| 90 | void RemoveFileRequested(u64 program_id, GameListRemoveTarget target); | 91 | void RemoveFileRequested(u64 program_id, GameListRemoveTarget target); |
diff --git a/src/yuzu/game_list_worker.cpp b/src/yuzu/game_list_worker.cpp index 239016b94..e0ce45fd9 100644 --- a/src/yuzu/game_list_worker.cpp +++ b/src/yuzu/game_list_worker.cpp | |||
| @@ -39,12 +39,12 @@ QString GetGameListCachedObject(const std::string& filename, const std::string& | |||
| 39 | return generator(); | 39 | return generator(); |
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | const auto path = FileUtil::GetUserPath(FileUtil::UserPath::CacheDir) + DIR_SEP + "game_list" + | 42 | const auto path = Common::FS::GetUserPath(Common::FS::UserPath::CacheDir) + DIR_SEP + |
| 43 | DIR_SEP + filename + '.' + ext; | 43 | "game_list" + DIR_SEP + filename + '.' + ext; |
| 44 | 44 | ||
| 45 | FileUtil::CreateFullPath(path); | 45 | Common::FS::CreateFullPath(path); |
| 46 | 46 | ||
| 47 | if (!FileUtil::Exists(path)) { | 47 | if (!Common::FS::Exists(path)) { |
| 48 | const auto str = generator(); | 48 | const auto str = generator(); |
| 49 | 49 | ||
| 50 | QFile file{QString::fromStdString(path)}; | 50 | QFile file{QString::fromStdString(path)}; |
| @@ -70,14 +70,14 @@ std::pair<std::vector<u8>, std::string> GetGameListCachedObject( | |||
| 70 | return generator(); | 70 | return generator(); |
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | const auto path1 = FileUtil::GetUserPath(FileUtil::UserPath::CacheDir) + DIR_SEP + "game_list" + | 73 | const auto path1 = Common::FS::GetUserPath(Common::FS::UserPath::CacheDir) + DIR_SEP + |
| 74 | DIR_SEP + filename + ".jpeg"; | 74 | "game_list" + DIR_SEP + filename + ".jpeg"; |
| 75 | const auto path2 = FileUtil::GetUserPath(FileUtil::UserPath::CacheDir) + DIR_SEP + "game_list" + | 75 | const auto path2 = Common::FS::GetUserPath(Common::FS::UserPath::CacheDir) + DIR_SEP + |
| 76 | DIR_SEP + filename + ".appname.txt"; | 76 | "game_list" + DIR_SEP + filename + ".appname.txt"; |
| 77 | 77 | ||
| 78 | FileUtil::CreateFullPath(path1); | 78 | Common::FS::CreateFullPath(path1); |
| 79 | 79 | ||
| 80 | if (!FileUtil::Exists(path1) || !FileUtil::Exists(path2)) { | 80 | if (!Common::FS::Exists(path1) || !Common::FS::Exists(path2)) { |
| 81 | const auto [icon, nacp] = generator(); | 81 | const auto [icon, nacp] = generator(); |
| 82 | 82 | ||
| 83 | QFile file1{QString::fromStdString(path1)}; | 83 | QFile file1{QString::fromStdString(path1)}; |
| @@ -208,7 +208,7 @@ QList<QStandardItem*> MakeGameListEntry(const std::string& path, const std::stri | |||
| 208 | file_type_string, program_id), | 208 | file_type_string, program_id), |
| 209 | new GameListItemCompat(compatibility), | 209 | new GameListItemCompat(compatibility), |
| 210 | new GameListItem(file_type_string), | 210 | new GameListItem(file_type_string), |
| 211 | new GameListItemSize(FileUtil::GetSize(path)), | 211 | new GameListItemSize(Common::FS::GetSize(path)), |
| 212 | }; | 212 | }; |
| 213 | 213 | ||
| 214 | if (UISettings::values.show_add_ons) { | 214 | if (UISettings::values.show_add_ons) { |
| @@ -289,7 +289,7 @@ void GameListWorker::ScanFileSystem(ScanTarget target, const std::string& dir_pa | |||
| 289 | } | 289 | } |
| 290 | 290 | ||
| 291 | const std::string physical_name = directory + DIR_SEP + virtual_name; | 291 | const std::string physical_name = directory + DIR_SEP + virtual_name; |
| 292 | const bool is_dir = FileUtil::IsDirectory(physical_name); | 292 | const bool is_dir = Common::FS::IsDirectory(physical_name); |
| 293 | if (!is_dir && | 293 | if (!is_dir && |
| 294 | (HasSupportedFileExtension(physical_name) || IsExtractedNCAMain(physical_name))) { | 294 | (HasSupportedFileExtension(physical_name) || IsExtractedNCAMain(physical_name))) { |
| 295 | const auto file = vfs->OpenFile(physical_name, FileSys::Mode::Read); | 295 | const auto file = vfs->OpenFile(physical_name, FileSys::Mode::Read); |
| @@ -345,11 +345,12 @@ void GameListWorker::ScanFileSystem(ScanTarget target, const std::string& dir_pa | |||
| 345 | return true; | 345 | return true; |
| 346 | }; | 346 | }; |
| 347 | 347 | ||
| 348 | FileUtil::ForeachDirectoryEntry(nullptr, dir_path, callback); | 348 | Common::FS::ForeachDirectoryEntry(nullptr, dir_path, callback); |
| 349 | } | 349 | } |
| 350 | 350 | ||
| 351 | void GameListWorker::run() { | 351 | void GameListWorker::run() { |
| 352 | stop_processing = false; | 352 | stop_processing = false; |
| 353 | provider->ClearAllEntries(); | ||
| 353 | 354 | ||
| 354 | for (UISettings::GameDir& game_dir : game_dirs) { | 355 | for (UISettings::GameDir& game_dir : game_dirs) { |
| 355 | if (game_dir.path == QStringLiteral("SDMC")) { | 356 | if (game_dir.path == QStringLiteral("SDMC")) { |
| @@ -368,13 +369,12 @@ void GameListWorker::run() { | |||
| 368 | watch_list.append(game_dir.path); | 369 | watch_list.append(game_dir.path); |
| 369 | auto* const game_list_dir = new GameListDir(game_dir); | 370 | auto* const game_list_dir = new GameListDir(game_dir); |
| 370 | emit DirEntryReady(game_list_dir); | 371 | emit DirEntryReady(game_list_dir); |
| 371 | provider->ClearAllEntries(); | ||
| 372 | ScanFileSystem(ScanTarget::FillManualContentProvider, game_dir.path.toStdString(), | 372 | ScanFileSystem(ScanTarget::FillManualContentProvider, game_dir.path.toStdString(), |
| 373 | game_dir.deep_scan ? 256 : 0, game_list_dir); | 373 | game_dir.deep_scan ? 256 : 0, game_list_dir); |
| 374 | ScanFileSystem(ScanTarget::PopulateGameList, game_dir.path.toStdString(), | 374 | ScanFileSystem(ScanTarget::PopulateGameList, game_dir.path.toStdString(), |
| 375 | game_dir.deep_scan ? 256 : 0, game_list_dir); | 375 | game_dir.deep_scan ? 256 : 0, game_list_dir); |
| 376 | } | 376 | } |
| 377 | }; | 377 | } |
| 378 | 378 | ||
| 379 | emit Finished(watch_list); | 379 | emit Finished(watch_list); |
| 380 | } | 380 | } |
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 592993c36..a1b61d119 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp | |||
| @@ -94,6 +94,7 @@ 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 "input_common/main.h" | ||
| 97 | #include "video_core/gpu.h" | 98 | #include "video_core/gpu.h" |
| 98 | #include "video_core/shader_notify.h" | 99 | #include "video_core/shader_notify.h" |
| 99 | #include "yuzu/about_dialog.h" | 100 | #include "yuzu/about_dialog.h" |
| @@ -177,8 +178,8 @@ static void InitializeLogging() { | |||
| 177 | log_filter.ParseFilterString(Settings::values.log_filter); | 178 | log_filter.ParseFilterString(Settings::values.log_filter); |
| 178 | Log::SetGlobalFilter(log_filter); | 179 | Log::SetGlobalFilter(log_filter); |
| 179 | 180 | ||
| 180 | const std::string& log_dir = FileUtil::GetUserPath(FileUtil::UserPath::LogDir); | 181 | const std::string& log_dir = Common::FS::GetUserPath(Common::FS::UserPath::LogDir); |
| 181 | FileUtil::CreateFullPath(log_dir); | 182 | Common::FS::CreateFullPath(log_dir); |
| 182 | Log::AddBackend(std::make_unique<Log::FileBackend>(log_dir + LOG_FILE)); | 183 | Log::AddBackend(std::make_unique<Log::FileBackend>(log_dir + LOG_FILE)); |
| 183 | #ifdef _WIN32 | 184 | #ifdef _WIN32 |
| 184 | Log::AddBackend(std::make_unique<Log::DebuggerBackend>()); | 185 | Log::AddBackend(std::make_unique<Log::DebuggerBackend>()); |
| @@ -186,9 +187,9 @@ static void InitializeLogging() { | |||
| 186 | } | 187 | } |
| 187 | 188 | ||
| 188 | GMainWindow::GMainWindow() | 189 | GMainWindow::GMainWindow() |
| 189 | : config(new Config()), emu_thread(nullptr), | 190 | : input_subsystem{std::make_shared<InputCommon::InputSubsystem>()}, |
| 190 | vfs(std::make_shared<FileSys::RealVfsFilesystem>()), | 191 | config{std::make_unique<Config>()}, vfs{std::make_shared<FileSys::RealVfsFilesystem>()}, |
| 191 | provider(std::make_unique<FileSys::ManualContentProvider>()) { | 192 | provider{std::make_unique<FileSys::ManualContentProvider>()} { |
| 192 | InitializeLogging(); | 193 | InitializeLogging(); |
| 193 | 194 | ||
| 194 | LoadTranslation(); | 195 | LoadTranslation(); |
| @@ -473,7 +474,7 @@ void GMainWindow::InitializeWidgets() { | |||
| 473 | #ifdef YUZU_ENABLE_COMPATIBILITY_REPORTING | 474 | #ifdef YUZU_ENABLE_COMPATIBILITY_REPORTING |
| 474 | ui.action_Report_Compatibility->setVisible(true); | 475 | ui.action_Report_Compatibility->setVisible(true); |
| 475 | #endif | 476 | #endif |
| 476 | render_window = new GRenderWindow(this, emu_thread.get()); | 477 | render_window = new GRenderWindow(this, emu_thread.get(), input_subsystem); |
| 477 | render_window->hide(); | 478 | render_window->hide(); |
| 478 | 479 | ||
| 479 | game_list = new GameList(vfs, provider.get(), this); | 480 | game_list = new GameList(vfs, provider.get(), this); |
| @@ -894,6 +895,8 @@ void GMainWindow::ConnectMenuEvents() { | |||
| 894 | connect(ui.action_Open_FAQ, &QAction::triggered, this, &GMainWindow::OnOpenFAQ); | 895 | connect(ui.action_Open_FAQ, &QAction::triggered, this, &GMainWindow::OnOpenFAQ); |
| 895 | connect(ui.action_Restart, &QAction::triggered, this, [this] { BootGame(QString(game_path)); }); | 896 | connect(ui.action_Restart, &QAction::triggered, this, [this] { BootGame(QString(game_path)); }); |
| 896 | connect(ui.action_Configure, &QAction::triggered, this, &GMainWindow::OnConfigure); | 897 | connect(ui.action_Configure, &QAction::triggered, this, &GMainWindow::OnConfigure); |
| 898 | connect(ui.action_Configure_Current_Game, &QAction::triggered, this, | ||
| 899 | &GMainWindow::OnConfigurePerGame); | ||
| 897 | 900 | ||
| 898 | // View | 901 | // View |
| 899 | connect(ui.action_Single_Window_Mode, &QAction::triggered, this, | 902 | connect(ui.action_Single_Window_Mode, &QAction::triggered, this, |
| @@ -1039,7 +1042,7 @@ bool GMainWindow::LoadROM(const QString& filename) { | |||
| 1039 | } | 1042 | } |
| 1040 | game_path = filename; | 1043 | game_path = filename; |
| 1041 | 1044 | ||
| 1042 | system.TelemetrySession().AddField(Telemetry::FieldType::App, "Frontend", "Qt"); | 1045 | system.TelemetrySession().AddField(Common::Telemetry::FieldType::App, "Frontend", "Qt"); |
| 1043 | return true; | 1046 | return true; |
| 1044 | } | 1047 | } |
| 1045 | 1048 | ||
| @@ -1121,7 +1124,7 @@ void GMainWindow::BootGame(const QString& filename) { | |||
| 1121 | title_name = metadata.first->GetApplicationName(); | 1124 | title_name = metadata.first->GetApplicationName(); |
| 1122 | } | 1125 | } |
| 1123 | if (res != Loader::ResultStatus::Success || title_name.empty()) { | 1126 | if (res != Loader::ResultStatus::Success || title_name.empty()) { |
| 1124 | title_name = FileUtil::GetFilename(filename.toStdString()); | 1127 | title_name = Common::FS::GetFilename(filename.toStdString()); |
| 1125 | } | 1128 | } |
| 1126 | LOG_INFO(Frontend, "Booting game: {:016X} | {} | {}", title_id, title_name, title_version); | 1129 | LOG_INFO(Frontend, "Booting game: {:016X} | {} | {}", title_id, title_name, title_version); |
| 1127 | UpdateWindowTitle(title_name, title_version); | 1130 | UpdateWindowTitle(title_name, title_version); |
| @@ -1167,6 +1170,7 @@ void GMainWindow::ShutdownGame() { | |||
| 1167 | ui.action_Pause->setEnabled(false); | 1170 | ui.action_Pause->setEnabled(false); |
| 1168 | ui.action_Stop->setEnabled(false); | 1171 | ui.action_Stop->setEnabled(false); |
| 1169 | ui.action_Restart->setEnabled(false); | 1172 | ui.action_Restart->setEnabled(false); |
| 1173 | ui.action_Configure_Current_Game->setEnabled(false); | ||
| 1170 | ui.action_Report_Compatibility->setEnabled(false); | 1174 | ui.action_Report_Compatibility->setEnabled(false); |
| 1171 | ui.action_Load_Amiibo->setEnabled(false); | 1175 | ui.action_Load_Amiibo->setEnabled(false); |
| 1172 | ui.action_Capture_Screenshot->setEnabled(false); | 1176 | ui.action_Capture_Screenshot->setEnabled(false); |
| @@ -1239,27 +1243,36 @@ void GMainWindow::OnGameListLoadFile(QString game_path) { | |||
| 1239 | BootGame(game_path); | 1243 | BootGame(game_path); |
| 1240 | } | 1244 | } |
| 1241 | 1245 | ||
| 1242 | void GMainWindow::OnGameListOpenFolder(GameListOpenTarget target, const std::string& game_path) { | 1246 | void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target, |
| 1247 | const std::string& game_path) { | ||
| 1243 | std::string path; | 1248 | std::string path; |
| 1244 | QString open_target; | 1249 | QString open_target; |
| 1245 | 1250 | ||
| 1246 | const auto v_file = Core::GetGameFileFromPath(vfs, game_path); | 1251 | const auto [user_save_size, device_save_size] = [this, &program_id, &game_path] { |
| 1247 | const auto loader = Loader::GetLoader(v_file); | 1252 | FileSys::PatchManager pm{program_id}; |
| 1248 | FileSys::NACP control{}; | 1253 | const auto control = pm.GetControlMetadata().first; |
| 1249 | u64 program_id{}; | 1254 | if (control != nullptr) { |
| 1255 | return std::make_pair(control->GetDefaultNormalSaveSize(), | ||
| 1256 | control->GetDeviceSaveDataSize()); | ||
| 1257 | } else { | ||
| 1258 | const auto file = Core::GetGameFileFromPath(vfs, game_path); | ||
| 1259 | const auto loader = Loader::GetLoader(file); | ||
| 1250 | 1260 | ||
| 1251 | loader->ReadControlData(control); | 1261 | FileSys::NACP nacp{}; |
| 1252 | loader->ReadProgramId(program_id); | 1262 | loader->ReadControlData(nacp); |
| 1263 | return std::make_pair(nacp.GetDefaultNormalSaveSize(), nacp.GetDeviceSaveDataSize()); | ||
| 1264 | } | ||
| 1265 | }(); | ||
| 1253 | 1266 | ||
| 1254 | const bool has_user_save{control.GetDefaultNormalSaveSize() > 0}; | 1267 | const bool has_user_save{user_save_size > 0}; |
| 1255 | const bool has_device_save{control.GetDeviceSaveDataSize() > 0}; | 1268 | const bool has_device_save{device_save_size > 0}; |
| 1256 | 1269 | ||
| 1257 | ASSERT_MSG(has_user_save != has_device_save, "Game uses both user and device savedata?"); | 1270 | ASSERT_MSG(has_user_save != has_device_save, "Game uses both user and device savedata?"); |
| 1258 | 1271 | ||
| 1259 | switch (target) { | 1272 | switch (target) { |
| 1260 | case GameListOpenTarget::SaveData: { | 1273 | case GameListOpenTarget::SaveData: { |
| 1261 | open_target = tr("Save Data"); | 1274 | open_target = tr("Save Data"); |
| 1262 | const std::string nand_dir = FileUtil::GetUserPath(FileUtil::UserPath::NANDDir); | 1275 | const std::string nand_dir = Common::FS::GetUserPath(Common::FS::UserPath::NANDDir); |
| 1263 | 1276 | ||
| 1264 | if (has_user_save) { | 1277 | if (has_user_save) { |
| 1265 | // User save data | 1278 | // User save data |
| @@ -1294,16 +1307,16 @@ void GMainWindow::OnGameListOpenFolder(GameListOpenTarget target, const std::str | |||
| 1294 | FileSys::SaveDataType::SaveData, program_id, {}, 0); | 1307 | FileSys::SaveDataType::SaveData, program_id, {}, 0); |
| 1295 | } | 1308 | } |
| 1296 | 1309 | ||
| 1297 | if (!FileUtil::Exists(path)) { | 1310 | if (!Common::FS::Exists(path)) { |
| 1298 | FileUtil::CreateFullPath(path); | 1311 | Common::FS::CreateFullPath(path); |
| 1299 | FileUtil::CreateDir(path); | 1312 | Common::FS::CreateDir(path); |
| 1300 | } | 1313 | } |
| 1301 | 1314 | ||
| 1302 | break; | 1315 | break; |
| 1303 | } | 1316 | } |
| 1304 | case GameListOpenTarget::ModData: { | 1317 | case GameListOpenTarget::ModData: { |
| 1305 | open_target = tr("Mod Data"); | 1318 | open_target = tr("Mod Data"); |
| 1306 | const auto load_dir = FileUtil::GetUserPath(FileUtil::UserPath::LoadDir); | 1319 | const auto load_dir = Common::FS::GetUserPath(Common::FS::UserPath::LoadDir); |
| 1307 | path = fmt::format("{}{:016X}", load_dir, program_id); | 1320 | path = fmt::format("{}{:016X}", load_dir, program_id); |
| 1308 | break; | 1321 | break; |
| 1309 | } | 1322 | } |
| @@ -1325,7 +1338,7 @@ void GMainWindow::OnGameListOpenFolder(GameListOpenTarget target, const std::str | |||
| 1325 | 1338 | ||
| 1326 | void GMainWindow::OnTransferableShaderCacheOpenFile(u64 program_id) { | 1339 | void GMainWindow::OnTransferableShaderCacheOpenFile(u64 program_id) { |
| 1327 | const QString shader_dir = | 1340 | const QString shader_dir = |
| 1328 | QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::ShaderDir)); | 1341 | QString::fromStdString(Common::FS::GetUserPath(Common::FS::UserPath::ShaderDir)); |
| 1329 | const QString transferable_shader_cache_folder_path = | 1342 | const QString transferable_shader_cache_folder_path = |
| 1330 | shader_dir + QStringLiteral("opengl") + QDir::separator() + QStringLiteral("transferable"); | 1343 | shader_dir + QStringLiteral("opengl") + QDir::separator() + QStringLiteral("transferable"); |
| 1331 | const QString transferable_shader_cache_file_path = | 1344 | const QString transferable_shader_cache_file_path = |
| @@ -1428,8 +1441,8 @@ void GMainWindow::OnGameListRemoveInstalledEntry(u64 program_id, InstalledEntryT | |||
| 1428 | RemoveAddOnContent(program_id, entry_type); | 1441 | RemoveAddOnContent(program_id, entry_type); |
| 1429 | break; | 1442 | break; |
| 1430 | } | 1443 | } |
| 1431 | FileUtil::DeleteDirRecursively(FileUtil::GetUserPath(FileUtil::UserPath::CacheDir) + DIR_SEP + | 1444 | Common::FS::DeleteDirRecursively(Common::FS::GetUserPath(Common::FS::UserPath::CacheDir) + |
| 1432 | "game_list"); | 1445 | DIR_SEP + "game_list"); |
| 1433 | game_list->PopulateAsync(UISettings::values.game_dirs); | 1446 | game_list->PopulateAsync(UISettings::values.game_dirs); |
| 1434 | } | 1447 | } |
| 1435 | 1448 | ||
| @@ -1519,7 +1532,7 @@ void GMainWindow::OnGameListRemoveFile(u64 program_id, GameListRemoveTarget targ | |||
| 1519 | 1532 | ||
| 1520 | void GMainWindow::RemoveTransferableShaderCache(u64 program_id) { | 1533 | void GMainWindow::RemoveTransferableShaderCache(u64 program_id) { |
| 1521 | const QString shader_dir = | 1534 | const QString shader_dir = |
| 1522 | QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::ShaderDir)); | 1535 | QString::fromStdString(Common::FS::GetUserPath(Common::FS::UserPath::ShaderDir)); |
| 1523 | const QString transferable_shader_cache_folder_path = | 1536 | const QString transferable_shader_cache_folder_path = |
| 1524 | shader_dir + QStringLiteral("opengl") + QDir::separator() + QStringLiteral("transferable"); | 1537 | shader_dir + QStringLiteral("opengl") + QDir::separator() + QStringLiteral("transferable"); |
| 1525 | const QString transferable_shader_cache_file_path = | 1538 | const QString transferable_shader_cache_file_path = |
| @@ -1543,7 +1556,7 @@ void GMainWindow::RemoveTransferableShaderCache(u64 program_id) { | |||
| 1543 | 1556 | ||
| 1544 | void GMainWindow::RemoveCustomConfiguration(u64 program_id) { | 1557 | void GMainWindow::RemoveCustomConfiguration(u64 program_id) { |
| 1545 | const QString config_dir = | 1558 | const QString config_dir = |
| 1546 | QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::ConfigDir)); | 1559 | QString::fromStdString(Common::FS::GetUserPath(Common::FS::UserPath::ConfigDir)); |
| 1547 | const QString custom_config_file_path = | 1560 | const QString custom_config_file_path = |
| 1548 | config_dir + QString::fromStdString(fmt::format("{:016X}.ini", program_id)); | 1561 | config_dir + QString::fromStdString(fmt::format("{:016X}.ini", program_id)); |
| 1549 | 1562 | ||
| @@ -1590,7 +1603,7 @@ void GMainWindow::OnGameListDumpRomFS(u64 program_id, const std::string& game_pa | |||
| 1590 | } | 1603 | } |
| 1591 | 1604 | ||
| 1592 | const auto path = fmt::format( | 1605 | const auto path = fmt::format( |
| 1593 | "{}{:016X}/romfs", FileUtil::GetUserPath(FileUtil::UserPath::DumpDir), *romfs_title_id); | 1606 | "{}{:016X}/romfs", Common::FS::GetUserPath(Common::FS::UserPath::DumpDir), *romfs_title_id); |
| 1594 | 1607 | ||
| 1595 | FileSys::VirtualFile romfs; | 1608 | FileSys::VirtualFile romfs; |
| 1596 | 1609 | ||
| @@ -1670,13 +1683,13 @@ void GMainWindow::OnGameListNavigateToGamedbEntry(u64 program_id, | |||
| 1670 | void GMainWindow::OnGameListOpenDirectory(const QString& directory) { | 1683 | void GMainWindow::OnGameListOpenDirectory(const QString& directory) { |
| 1671 | QString path; | 1684 | QString path; |
| 1672 | if (directory == QStringLiteral("SDMC")) { | 1685 | if (directory == QStringLiteral("SDMC")) { |
| 1673 | path = QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir) + | 1686 | path = QString::fromStdString(Common::FS::GetUserPath(Common::FS::UserPath::SDMCDir) + |
| 1674 | "Nintendo/Contents/registered"); | 1687 | "Nintendo/Contents/registered"); |
| 1675 | } else if (directory == QStringLiteral("UserNAND")) { | 1688 | } else if (directory == QStringLiteral("UserNAND")) { |
| 1676 | path = QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) + | 1689 | path = QString::fromStdString(Common::FS::GetUserPath(Common::FS::UserPath::NANDDir) + |
| 1677 | "user/Contents/registered"); | 1690 | "user/Contents/registered"); |
| 1678 | } else if (directory == QStringLiteral("SysNAND")) { | 1691 | } else if (directory == QStringLiteral("SysNAND")) { |
| 1679 | path = QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) + | 1692 | path = QString::fromStdString(Common::FS::GetUserPath(Common::FS::UserPath::NANDDir) + |
| 1680 | "system/Contents/registered"); | 1693 | "system/Contents/registered"); |
| 1681 | } else { | 1694 | } else { |
| 1682 | path = directory; | 1695 | path = directory; |
| @@ -1690,8 +1703,10 @@ void GMainWindow::OnGameListOpenDirectory(const QString& directory) { | |||
| 1690 | 1703 | ||
| 1691 | void GMainWindow::OnGameListAddDirectory() { | 1704 | void GMainWindow::OnGameListAddDirectory() { |
| 1692 | const QString dir_path = QFileDialog::getExistingDirectory(this, tr("Select Directory")); | 1705 | const QString dir_path = QFileDialog::getExistingDirectory(this, tr("Select Directory")); |
| 1693 | if (dir_path.isEmpty()) | 1706 | if (dir_path.isEmpty()) { |
| 1694 | return; | 1707 | return; |
| 1708 | } | ||
| 1709 | |||
| 1695 | UISettings::GameDir game_dir{dir_path, false, true}; | 1710 | UISettings::GameDir game_dir{dir_path, false, true}; |
| 1696 | if (!UISettings::values.game_dirs.contains(game_dir)) { | 1711 | if (!UISettings::values.game_dirs.contains(game_dir)) { |
| 1697 | UISettings::values.game_dirs.append(game_dir); | 1712 | UISettings::values.game_dirs.append(game_dir); |
| @@ -1718,26 +1733,7 @@ void GMainWindow::OnGameListOpenPerGameProperties(const std::string& file) { | |||
| 1718 | return; | 1733 | return; |
| 1719 | } | 1734 | } |
| 1720 | 1735 | ||
| 1721 | ConfigurePerGame dialog(this, title_id); | 1736 | OpenPerGameConfiguration(title_id, file); |
| 1722 | dialog.LoadFromFile(v_file); | ||
| 1723 | auto result = dialog.exec(); | ||
| 1724 | if (result == QDialog::Accepted) { | ||
| 1725 | dialog.ApplyConfiguration(); | ||
| 1726 | |||
| 1727 | const auto reload = UISettings::values.is_game_list_reload_pending.exchange(false); | ||
| 1728 | if (reload) { | ||
| 1729 | game_list->PopulateAsync(UISettings::values.game_dirs); | ||
| 1730 | } | ||
| 1731 | |||
| 1732 | // Do not cause the global config to write local settings into the config file | ||
| 1733 | Settings::RestoreGlobalState(); | ||
| 1734 | |||
| 1735 | if (!Core::System::GetInstance().IsPoweredOn()) { | ||
| 1736 | config->Save(); | ||
| 1737 | } | ||
| 1738 | } else { | ||
| 1739 | Settings::RestoreGlobalState(); | ||
| 1740 | } | ||
| 1741 | } | 1737 | } |
| 1742 | 1738 | ||
| 1743 | void GMainWindow::OnMenuLoadFile() { | 1739 | void GMainWindow::OnMenuLoadFile() { |
| @@ -1882,8 +1878,8 @@ void GMainWindow::OnMenuInstallToNAND() { | |||
| 1882 | : tr("%n file(s) failed to install\n", "", failed_files.size())); | 1878 | : tr("%n file(s) failed to install\n", "", failed_files.size())); |
| 1883 | 1879 | ||
| 1884 | QMessageBox::information(this, tr("Install Results"), install_results); | 1880 | QMessageBox::information(this, tr("Install Results"), install_results); |
| 1885 | FileUtil::DeleteDirRecursively(FileUtil::GetUserPath(FileUtil::UserPath::CacheDir) + DIR_SEP + | 1881 | Common::FS::DeleteDirRecursively(Common::FS::GetUserPath(Common::FS::UserPath::CacheDir) + |
| 1886 | "game_list"); | 1882 | DIR_SEP + "game_list"); |
| 1887 | game_list->PopulateAsync(UISettings::values.game_dirs); | 1883 | game_list->PopulateAsync(UISettings::values.game_dirs); |
| 1888 | ui.action_Install_File_NAND->setEnabled(true); | 1884 | ui.action_Install_File_NAND->setEnabled(true); |
| 1889 | } | 1885 | } |
| @@ -2066,6 +2062,7 @@ void GMainWindow::OnStartGame() { | |||
| 2066 | ui.action_Pause->setEnabled(true); | 2062 | ui.action_Pause->setEnabled(true); |
| 2067 | ui.action_Stop->setEnabled(true); | 2063 | ui.action_Stop->setEnabled(true); |
| 2068 | ui.action_Restart->setEnabled(true); | 2064 | ui.action_Restart->setEnabled(true); |
| 2065 | ui.action_Configure_Current_Game->setEnabled(true); | ||
| 2069 | ui.action_Report_Compatibility->setEnabled(true); | 2066 | ui.action_Report_Compatibility->setEnabled(true); |
| 2070 | 2067 | ||
| 2071 | discord_rpc->Update(); | 2068 | discord_rpc->Update(); |
| @@ -2217,7 +2214,7 @@ void GMainWindow::OnConfigure() { | |||
| 2217 | const auto old_theme = UISettings::values.theme; | 2214 | const auto old_theme = UISettings::values.theme; |
| 2218 | const bool old_discord_presence = UISettings::values.enable_discord_presence; | 2215 | const bool old_discord_presence = UISettings::values.enable_discord_presence; |
| 2219 | 2216 | ||
| 2220 | ConfigureDialog configure_dialog(this, hotkey_registry); | 2217 | ConfigureDialog configure_dialog(this, hotkey_registry, input_subsystem.get()); |
| 2221 | connect(&configure_dialog, &ConfigureDialog::LanguageChanged, this, | 2218 | connect(&configure_dialog, &ConfigureDialog::LanguageChanged, this, |
| 2222 | &GMainWindow::OnLanguageChanged); | 2219 | &GMainWindow::OnLanguageChanged); |
| 2223 | 2220 | ||
| @@ -2255,6 +2252,36 @@ void GMainWindow::OnConfigure() { | |||
| 2255 | UpdateStatusButtons(); | 2252 | UpdateStatusButtons(); |
| 2256 | } | 2253 | } |
| 2257 | 2254 | ||
| 2255 | void GMainWindow::OnConfigurePerGame() { | ||
| 2256 | const u64 title_id = Core::System::GetInstance().CurrentProcess()->GetTitleID(); | ||
| 2257 | OpenPerGameConfiguration(title_id, game_path.toStdString()); | ||
| 2258 | } | ||
| 2259 | |||
| 2260 | void GMainWindow::OpenPerGameConfiguration(u64 title_id, const std::string& file_name) { | ||
| 2261 | const auto v_file = Core::GetGameFileFromPath(vfs, file_name); | ||
| 2262 | |||
| 2263 | ConfigurePerGame dialog(this, title_id); | ||
| 2264 | dialog.LoadFromFile(v_file); | ||
| 2265 | auto result = dialog.exec(); | ||
| 2266 | if (result == QDialog::Accepted) { | ||
| 2267 | dialog.ApplyConfiguration(); | ||
| 2268 | |||
| 2269 | const auto reload = UISettings::values.is_game_list_reload_pending.exchange(false); | ||
| 2270 | if (reload) { | ||
| 2271 | game_list->PopulateAsync(UISettings::values.game_dirs); | ||
| 2272 | } | ||
| 2273 | |||
| 2274 | // Do not cause the global config to write local settings into the config file | ||
| 2275 | Settings::RestoreGlobalState(); | ||
| 2276 | |||
| 2277 | if (!Core::System::GetInstance().IsPoweredOn()) { | ||
| 2278 | config->Save(); | ||
| 2279 | } | ||
| 2280 | } else { | ||
| 2281 | Settings::RestoreGlobalState(); | ||
| 2282 | } | ||
| 2283 | } | ||
| 2284 | |||
| 2258 | void GMainWindow::OnLoadAmiibo() { | 2285 | void GMainWindow::OnLoadAmiibo() { |
| 2259 | const QString extensions{QStringLiteral("*.bin")}; | 2286 | const QString extensions{QStringLiteral("*.bin")}; |
| 2260 | const QString file_filter = tr("Amiibo File (%1);; All Files (*.*)").arg(extensions); | 2287 | const QString file_filter = tr("Amiibo File (%1);; All Files (*.*)").arg(extensions); |
| @@ -2302,7 +2329,7 @@ void GMainWindow::LoadAmiibo(const QString& filename) { | |||
| 2302 | 2329 | ||
| 2303 | void GMainWindow::OnOpenYuzuFolder() { | 2330 | void GMainWindow::OnOpenYuzuFolder() { |
| 2304 | QDesktopServices::openUrl(QUrl::fromLocalFile( | 2331 | QDesktopServices::openUrl(QUrl::fromLocalFile( |
| 2305 | QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::UserDir)))); | 2332 | QString::fromStdString(Common::FS::GetUserPath(Common::FS::UserPath::UserDir)))); |
| 2306 | } | 2333 | } |
| 2307 | 2334 | ||
| 2308 | void GMainWindow::OnAbout() { | 2335 | void GMainWindow::OnAbout() { |
| @@ -2324,7 +2351,7 @@ void GMainWindow::OnCaptureScreenshot() { | |||
| 2324 | 2351 | ||
| 2325 | const u64 title_id = Core::System::GetInstance().CurrentProcess()->GetTitleID(); | 2352 | const u64 title_id = Core::System::GetInstance().CurrentProcess()->GetTitleID(); |
| 2326 | const auto screenshot_path = | 2353 | const auto screenshot_path = |
| 2327 | QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::ScreenshotsDir)); | 2354 | QString::fromStdString(Common::FS::GetUserPath(Common::FS::UserPath::ScreenshotsDir)); |
| 2328 | const auto date = | 2355 | const auto date = |
| 2329 | QDateTime::currentDateTime().toString(QStringLiteral("yyyy-MM-dd_hh-mm-ss-zzz")); | 2356 | QDateTime::currentDateTime().toString(QStringLiteral("yyyy-MM-dd_hh-mm-ss-zzz")); |
| 2330 | QString filename = QStringLiteral("%1%2_%3.png") | 2357 | QString filename = QStringLiteral("%1%2_%3.png") |
| @@ -2527,18 +2554,18 @@ void GMainWindow::OnReinitializeKeys(ReinitializeKeyBehavior behavior) { | |||
| 2527 | if (res == QMessageBox::Cancel) | 2554 | if (res == QMessageBox::Cancel) |
| 2528 | return; | 2555 | return; |
| 2529 | 2556 | ||
| 2530 | FileUtil::Delete(FileUtil::GetUserPath(FileUtil::UserPath::KeysDir) + | 2557 | Common::FS::Delete(Common::FS::GetUserPath(Common::FS::UserPath::KeysDir) + |
| 2531 | "prod.keys_autogenerated"); | 2558 | "prod.keys_autogenerated"); |
| 2532 | FileUtil::Delete(FileUtil::GetUserPath(FileUtil::UserPath::KeysDir) + | 2559 | Common::FS::Delete(Common::FS::GetUserPath(Common::FS::UserPath::KeysDir) + |
| 2533 | "console.keys_autogenerated"); | 2560 | "console.keys_autogenerated"); |
| 2534 | FileUtil::Delete(FileUtil::GetUserPath(FileUtil::UserPath::KeysDir) + | 2561 | Common::FS::Delete(Common::FS::GetUserPath(Common::FS::UserPath::KeysDir) + |
| 2535 | "title.keys_autogenerated"); | 2562 | "title.keys_autogenerated"); |
| 2536 | } | 2563 | } |
| 2537 | 2564 | ||
| 2538 | Core::Crypto::KeyManager& keys = Core::Crypto::KeyManager::Instance(); | 2565 | Core::Crypto::KeyManager& keys = Core::Crypto::KeyManager::Instance(); |
| 2539 | if (keys.BaseDeriveNecessary()) { | 2566 | if (keys.BaseDeriveNecessary()) { |
| 2540 | Core::Crypto::PartitionDataManager pdm{vfs->OpenDirectory( | 2567 | Core::Crypto::PartitionDataManager pdm{vfs->OpenDirectory( |
| 2541 | FileUtil::GetUserPath(FileUtil::UserPath::SysDataDir), FileSys::Mode::Read)}; | 2568 | Common::FS::GetUserPath(Common::FS::UserPath::SysDataDir), FileSys::Mode::Read)}; |
| 2542 | 2569 | ||
| 2543 | const auto function = [this, &keys, &pdm] { | 2570 | const auto function = [this, &keys, &pdm] { |
| 2544 | keys.PopulateFromPartitionData(pdm); | 2571 | keys.PopulateFromPartitionData(pdm); |
| @@ -2870,7 +2897,7 @@ int main(int argc, char* argv[]) { | |||
| 2870 | // If you start a bundle (binary) on OSX without the Terminal, the working directory is "/". | 2897 | // If you start a bundle (binary) on OSX without the Terminal, the working directory is "/". |
| 2871 | // But since we require the working directory to be the executable path for the location of | 2898 | // But since we require the working directory to be the executable path for the location of |
| 2872 | // the user folder in the Qt Frontend, we need to cd into that working directory | 2899 | // the user folder in the Qt Frontend, we need to cd into that working directory |
| 2873 | const std::string bin_path = FileUtil::GetBundleDirectory() + DIR_SEP + ".."; | 2900 | const std::string bin_path = Common::FS::GetBundleDirectory() + DIR_SEP + ".."; |
| 2874 | chdir(bin_path.c_str()); | 2901 | chdir(bin_path.c_str()); |
| 2875 | #endif | 2902 | #endif |
| 2876 | 2903 | ||
diff --git a/src/yuzu/main.h b/src/yuzu/main.h index 73a44a3bf..0ce66a1ca 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h | |||
| @@ -40,12 +40,20 @@ namespace Core::Frontend { | |||
| 40 | struct SoftwareKeyboardParameters; | 40 | struct SoftwareKeyboardParameters; |
| 41 | } // namespace Core::Frontend | 41 | } // namespace Core::Frontend |
| 42 | 42 | ||
| 43 | namespace DiscordRPC { | ||
| 44 | class DiscordInterface; | ||
| 45 | } | ||
| 46 | |||
| 43 | namespace FileSys { | 47 | namespace FileSys { |
| 44 | class ContentProvider; | 48 | class ContentProvider; |
| 45 | class ManualContentProvider; | 49 | class ManualContentProvider; |
| 46 | class VfsFilesystem; | 50 | class VfsFilesystem; |
| 47 | } // namespace FileSys | 51 | } // namespace FileSys |
| 48 | 52 | ||
| 53 | namespace InputCommon { | ||
| 54 | class InputSubsystem; | ||
| 55 | } | ||
| 56 | |||
| 49 | enum class EmulatedDirectoryTarget { | 57 | enum class EmulatedDirectoryTarget { |
| 50 | NAND, | 58 | NAND, |
| 51 | SDMC, | 59 | SDMC, |
| @@ -62,10 +70,6 @@ enum class ReinitializeKeyBehavior { | |||
| 62 | Warning, | 70 | Warning, |
| 63 | }; | 71 | }; |
| 64 | 72 | ||
| 65 | namespace DiscordRPC { | ||
| 66 | class DiscordInterface; | ||
| 67 | } | ||
| 68 | |||
| 69 | class GMainWindow : public QMainWindow { | 73 | class GMainWindow : public QMainWindow { |
| 70 | Q_OBJECT | 74 | Q_OBJECT |
| 71 | 75 | ||
| @@ -86,8 +90,6 @@ public: | |||
| 86 | GMainWindow(); | 90 | GMainWindow(); |
| 87 | ~GMainWindow() override; | 91 | ~GMainWindow() override; |
| 88 | 92 | ||
| 89 | std::unique_ptr<DiscordRPC::DiscordInterface> discord_rpc; | ||
| 90 | |||
| 91 | bool DropAction(QDropEvent* event); | 93 | bool DropAction(QDropEvent* event); |
| 92 | void AcceptDropEvent(QDropEvent* event); | 94 | void AcceptDropEvent(QDropEvent* event); |
| 93 | 95 | ||
| @@ -198,7 +200,8 @@ private slots: | |||
| 198 | void OnOpenFAQ(); | 200 | void OnOpenFAQ(); |
| 199 | /// Called whenever a user selects a game in the game list widget. | 201 | /// Called whenever a user selects a game in the game list widget. |
| 200 | void OnGameListLoadFile(QString game_path); | 202 | void OnGameListLoadFile(QString game_path); |
| 201 | void OnGameListOpenFolder(GameListOpenTarget target, const std::string& game_path); | 203 | void OnGameListOpenFolder(u64 program_id, GameListOpenTarget target, |
| 204 | const std::string& game_path); | ||
| 202 | void OnTransferableShaderCacheOpenFile(u64 program_id); | 205 | void OnTransferableShaderCacheOpenFile(u64 program_id); |
| 203 | void OnGameListRemoveInstalledEntry(u64 program_id, InstalledEntryType type); | 206 | void OnGameListRemoveInstalledEntry(u64 program_id, InstalledEntryType type); |
| 204 | void OnGameListRemoveFile(u64 program_id, GameListRemoveTarget target); | 207 | void OnGameListRemoveFile(u64 program_id, GameListRemoveTarget target); |
| @@ -216,6 +219,7 @@ private slots: | |||
| 216 | void OnMenuInstallToNAND(); | 219 | void OnMenuInstallToNAND(); |
| 217 | void OnMenuRecentFile(); | 220 | void OnMenuRecentFile(); |
| 218 | void OnConfigure(); | 221 | void OnConfigure(); |
| 222 | void OnConfigurePerGame(); | ||
| 219 | void OnLoadAmiibo(); | 223 | void OnLoadAmiibo(); |
| 220 | void OnOpenYuzuFolder(); | 224 | void OnOpenYuzuFolder(); |
| 221 | void OnAbout(); | 225 | void OnAbout(); |
| @@ -249,9 +253,13 @@ private: | |||
| 249 | void ShowMouseCursor(); | 253 | void ShowMouseCursor(); |
| 250 | void OpenURL(const QUrl& url); | 254 | void OpenURL(const QUrl& url); |
| 251 | void LoadTranslation(); | 255 | void LoadTranslation(); |
| 256 | void OpenPerGameConfiguration(u64 title_id, const std::string& file_name); | ||
| 252 | 257 | ||
| 253 | Ui::MainWindow ui; | 258 | Ui::MainWindow ui; |
| 254 | 259 | ||
| 260 | std::unique_ptr<DiscordRPC::DiscordInterface> discord_rpc; | ||
| 261 | std::shared_ptr<InputCommon::InputSubsystem> input_subsystem; | ||
| 262 | |||
| 255 | GRenderWindow* render_window; | 263 | GRenderWindow* render_window; |
| 256 | GameList* game_list; | 264 | GameList* game_list; |
| 257 | LoadingScreen* loading_screen; | 265 | LoadingScreen* loading_screen; |
diff --git a/src/yuzu/main.ui b/src/yuzu/main.ui index c3a1d715e..87ea985d8 100644 --- a/src/yuzu/main.ui +++ b/src/yuzu/main.ui | |||
| @@ -81,6 +81,7 @@ | |||
| 81 | <addaction name="action_Restart"/> | 81 | <addaction name="action_Restart"/> |
| 82 | <addaction name="separator"/> | 82 | <addaction name="separator"/> |
| 83 | <addaction name="action_Configure"/> | 83 | <addaction name="action_Configure"/> |
| 84 | <addaction name="action_Configure_Current_Game"/> | ||
| 84 | </widget> | 85 | </widget> |
| 85 | <widget class="QMenu" name="menu_View"> | 86 | <widget class="QMenu" name="menu_View"> |
| 86 | <property name="title"> | 87 | <property name="title"> |
| @@ -287,6 +288,14 @@ | |||
| 287 | <string>Capture Screenshot</string> | 288 | <string>Capture Screenshot</string> |
| 288 | </property> | 289 | </property> |
| 289 | </action> | 290 | </action> |
| 291 | <action name="action_Configure_Current_Game"> | ||
| 292 | <property name="enabled"> | ||
| 293 | <bool>false</bool> | ||
| 294 | </property> | ||
| 295 | <property name="text"> | ||
| 296 | <string>Configure Current Game..</string> | ||
| 297 | </property> | ||
| 298 | </action> | ||
| 290 | </widget> | 299 | </widget> |
| 291 | <resources/> | 300 | <resources/> |
| 292 | <connections/> | 301 | <connections/> |
diff --git a/src/yuzu/uisettings.cpp b/src/yuzu/uisettings.cpp index a51175f36..37499fc85 100644 --- a/src/yuzu/uisettings.cpp +++ b/src/yuzu/uisettings.cpp | |||
| @@ -16,4 +16,5 @@ const Themes themes{{ | |||
| 16 | }}; | 16 | }}; |
| 17 | 17 | ||
| 18 | Values values = {}; | 18 | Values values = {}; |
| 19 | |||
| 19 | } // namespace UISettings | 20 | } // namespace UISettings |
diff --git a/src/yuzu/uisettings.h b/src/yuzu/uisettings.h index bbfeafc55..ce3945485 100644 --- a/src/yuzu/uisettings.h +++ b/src/yuzu/uisettings.h | |||
| @@ -29,14 +29,14 @@ extern const Themes themes; | |||
| 29 | 29 | ||
| 30 | struct GameDir { | 30 | struct GameDir { |
| 31 | QString path; | 31 | QString path; |
| 32 | bool deep_scan; | 32 | bool deep_scan = false; |
| 33 | bool expanded; | 33 | bool expanded = false; |
| 34 | bool operator==(const GameDir& rhs) const { | 34 | bool operator==(const GameDir& rhs) const { |
| 35 | return path == rhs.path; | 35 | return path == rhs.path; |
| 36 | }; | 36 | } |
| 37 | bool operator!=(const GameDir& rhs) const { | 37 | bool operator!=(const GameDir& rhs) const { |
| 38 | return !operator==(rhs); | 38 | return !operator==(rhs); |
| 39 | }; | 39 | } |
| 40 | }; | 40 | }; |
| 41 | 41 | ||
| 42 | struct Values { | 42 | struct Values { |
| @@ -87,9 +87,6 @@ struct Values { | |||
| 87 | // logging | 87 | // logging |
| 88 | bool show_console; | 88 | bool show_console; |
| 89 | 89 | ||
| 90 | // Controllers | ||
| 91 | int profile_index; | ||
| 92 | |||
| 93 | // Game List | 90 | // Game List |
| 94 | bool show_add_ons; | 91 | bool show_add_ons; |
| 95 | uint32_t icon_size; | 92 | uint32_t icon_size; |
| @@ -100,6 +97,7 @@ struct Values { | |||
| 100 | }; | 97 | }; |
| 101 | 98 | ||
| 102 | extern Values values; | 99 | extern Values values; |
| 100 | |||
| 103 | } // namespace UISettings | 101 | } // namespace UISettings |
| 104 | 102 | ||
| 105 | Q_DECLARE_METATYPE(UISettings::GameDir*); | 103 | Q_DECLARE_METATYPE(UISettings::GameDir*); |
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp index c2a2982fb..e9f1c6500 100644 --- a/src/yuzu_cmd/config.cpp +++ b/src/yuzu_cmd/config.cpp | |||
| @@ -16,9 +16,11 @@ | |||
| 16 | #include "yuzu_cmd/config.h" | 16 | #include "yuzu_cmd/config.h" |
| 17 | #include "yuzu_cmd/default_ini.h" | 17 | #include "yuzu_cmd/default_ini.h" |
| 18 | 18 | ||
| 19 | namespace FS = Common::FS; | ||
| 20 | |||
| 19 | Config::Config() { | 21 | Config::Config() { |
| 20 | // TODO: Don't hardcode the path; let the frontend decide where to put the config files. | 22 | // TODO: Don't hardcode the path; let the frontend decide where to put the config files. |
| 21 | sdl2_config_loc = FileUtil::GetUserPath(FileUtil::UserPath::ConfigDir) + "sdl2-config.ini"; | 23 | sdl2_config_loc = FS::GetUserPath(FS::UserPath::ConfigDir) + "sdl2-config.ini"; |
| 22 | sdl2_config = std::make_unique<INIReader>(sdl2_config_loc); | 24 | sdl2_config = std::make_unique<INIReader>(sdl2_config_loc); |
| 23 | 25 | ||
| 24 | Reload(); | 26 | Reload(); |
| @@ -31,8 +33,8 @@ bool Config::LoadINI(const std::string& default_contents, bool retry) { | |||
| 31 | if (sdl2_config->ParseError() < 0) { | 33 | if (sdl2_config->ParseError() < 0) { |
| 32 | if (retry) { | 34 | if (retry) { |
| 33 | LOG_WARNING(Config, "Failed to load {}. Creating file from defaults...", location); | 35 | LOG_WARNING(Config, "Failed to load {}. Creating file from defaults...", location); |
| 34 | FileUtil::CreateFullPath(location); | 36 | FS::CreateFullPath(location); |
| 35 | FileUtil::WriteStringToFile(true, location, default_contents); | 37 | FS::WriteStringToFile(true, location, default_contents); |
| 36 | sdl2_config = std::make_unique<INIReader>(location); // Reopen file | 38 | sdl2_config = std::make_unique<INIReader>(location); // Reopen file |
| 37 | 39 | ||
| 38 | return LoadINI(default_contents, false); | 40 | return LoadINI(default_contents, false); |
| @@ -286,6 +288,8 @@ void Config::ReadValues() { | |||
| 286 | Settings::values.debug_pad_analogs[i] = default_param; | 288 | Settings::values.debug_pad_analogs[i] = default_param; |
| 287 | } | 289 | } |
| 288 | 290 | ||
| 291 | Settings::values.vibration_enabled = | ||
| 292 | sdl2_config->GetBoolean("ControlsGeneral", "vibration_enabled", true); | ||
| 289 | Settings::values.touchscreen.enabled = | 293 | Settings::values.touchscreen.enabled = |
| 290 | sdl2_config->GetBoolean("ControlsGeneral", "touch_enabled", true); | 294 | sdl2_config->GetBoolean("ControlsGeneral", "touch_enabled", true); |
| 291 | Settings::values.touchscreen.device = | 295 | Settings::values.touchscreen.device = |
| @@ -315,21 +319,21 @@ void Config::ReadValues() { | |||
| 315 | // Data Storage | 319 | // Data Storage |
| 316 | Settings::values.use_virtual_sd = | 320 | Settings::values.use_virtual_sd = |
| 317 | sdl2_config->GetBoolean("Data Storage", "use_virtual_sd", true); | 321 | sdl2_config->GetBoolean("Data Storage", "use_virtual_sd", true); |
| 318 | FileUtil::GetUserPath(FileUtil::UserPath::NANDDir, | 322 | FS::GetUserPath( |
| 319 | sdl2_config->Get("Data Storage", "nand_directory", | 323 | FS::UserPath::NANDDir, |
| 320 | FileUtil::GetUserPath(FileUtil::UserPath::NANDDir))); | 324 | sdl2_config->Get("Data Storage", "nand_directory", FS::GetUserPath(FS::UserPath::NANDDir))); |
| 321 | FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir, | 325 | FS::GetUserPath( |
| 322 | sdl2_config->Get("Data Storage", "sdmc_directory", | 326 | FS::UserPath::SDMCDir, |
| 323 | FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir))); | 327 | sdl2_config->Get("Data Storage", "sdmc_directory", FS::GetUserPath(FS::UserPath::SDMCDir))); |
| 324 | FileUtil::GetUserPath(FileUtil::UserPath::LoadDir, | 328 | FS::GetUserPath( |
| 325 | sdl2_config->Get("Data Storage", "load_directory", | 329 | FS::UserPath::LoadDir, |
| 326 | FileUtil::GetUserPath(FileUtil::UserPath::LoadDir))); | 330 | sdl2_config->Get("Data Storage", "load_directory", FS::GetUserPath(FS::UserPath::LoadDir))); |
| 327 | FileUtil::GetUserPath(FileUtil::UserPath::DumpDir, | 331 | FS::GetUserPath( |
| 328 | sdl2_config->Get("Data Storage", "dump_directory", | 332 | FS::UserPath::DumpDir, |
| 329 | FileUtil::GetUserPath(FileUtil::UserPath::DumpDir))); | 333 | sdl2_config->Get("Data Storage", "dump_directory", FS::GetUserPath(FS::UserPath::DumpDir))); |
| 330 | FileUtil::GetUserPath(FileUtil::UserPath::CacheDir, | 334 | FS::GetUserPath(FS::UserPath::CacheDir, |
| 331 | sdl2_config->Get("Data Storage", "cache_directory", | 335 | sdl2_config->Get("Data Storage", "cache_directory", |
| 332 | FileUtil::GetUserPath(FileUtil::UserPath::CacheDir))); | 336 | FS::GetUserPath(FS::UserPath::CacheDir))); |
| 333 | Settings::values.gamecard_inserted = | 337 | Settings::values.gamecard_inserted = |
| 334 | sdl2_config->GetBoolean("Data Storage", "gamecard_inserted", false); | 338 | sdl2_config->GetBoolean("Data Storage", "gamecard_inserted", false); |
| 335 | Settings::values.gamecard_current_game = | 339 | Settings::values.gamecard_current_game = |
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp index e5e684206..a804d5185 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp | |||
| @@ -13,23 +13,25 @@ | |||
| 13 | #include "input_common/sdl/sdl.h" | 13 | #include "input_common/sdl/sdl.h" |
| 14 | #include "yuzu_cmd/emu_window/emu_window_sdl2.h" | 14 | #include "yuzu_cmd/emu_window/emu_window_sdl2.h" |
| 15 | 15 | ||
| 16 | EmuWindow_SDL2::EmuWindow_SDL2(Core::System& system, bool fullscreen) : system{system} { | 16 | EmuWindow_SDL2::EmuWindow_SDL2(Core::System& system, bool fullscreen, |
| 17 | InputCommon::InputSubsystem* input_subsystem_) | ||
| 18 | : system{system}, input_subsystem{input_subsystem_} { | ||
| 17 | if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) { | 19 | if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) { |
| 18 | LOG_CRITICAL(Frontend, "Failed to initialize SDL2! Exiting..."); | 20 | LOG_CRITICAL(Frontend, "Failed to initialize SDL2! Exiting..."); |
| 19 | exit(1); | 21 | exit(1); |
| 20 | } | 22 | } |
| 21 | InputCommon::Init(); | 23 | input_subsystem->Initialize(); |
| 22 | SDL_SetMainReady(); | 24 | SDL_SetMainReady(); |
| 23 | } | 25 | } |
| 24 | 26 | ||
| 25 | EmuWindow_SDL2::~EmuWindow_SDL2() { | 27 | EmuWindow_SDL2::~EmuWindow_SDL2() { |
| 26 | InputCommon::Shutdown(); | 28 | input_subsystem->Shutdown(); |
| 27 | SDL_Quit(); | 29 | SDL_Quit(); |
| 28 | } | 30 | } |
| 29 | 31 | ||
| 30 | void EmuWindow_SDL2::OnMouseMotion(s32 x, s32 y) { | 32 | void EmuWindow_SDL2::OnMouseMotion(s32 x, s32 y) { |
| 31 | TouchMoved((unsigned)std::max(x, 0), (unsigned)std::max(y, 0)); | 33 | TouchMoved((unsigned)std::max(x, 0), (unsigned)std::max(y, 0)); |
| 32 | InputCommon::GetMotionEmu()->Tilt(x, y); | 34 | input_subsystem->GetMotionEmu()->Tilt(x, y); |
| 33 | } | 35 | } |
| 34 | 36 | ||
| 35 | void EmuWindow_SDL2::OnMouseButton(u32 button, u8 state, s32 x, s32 y) { | 37 | void EmuWindow_SDL2::OnMouseButton(u32 button, u8 state, s32 x, s32 y) { |
| @@ -41,9 +43,9 @@ void EmuWindow_SDL2::OnMouseButton(u32 button, u8 state, s32 x, s32 y) { | |||
| 41 | } | 43 | } |
| 42 | } else if (button == SDL_BUTTON_RIGHT) { | 44 | } else if (button == SDL_BUTTON_RIGHT) { |
| 43 | if (state == SDL_PRESSED) { | 45 | if (state == SDL_PRESSED) { |
| 44 | InputCommon::GetMotionEmu()->BeginTilt(x, y); | 46 | input_subsystem->GetMotionEmu()->BeginTilt(x, y); |
| 45 | } else { | 47 | } else { |
| 46 | InputCommon::GetMotionEmu()->EndTilt(); | 48 | input_subsystem->GetMotionEmu()->EndTilt(); |
| 47 | } | 49 | } |
| 48 | } | 50 | } |
| 49 | } | 51 | } |
| @@ -79,9 +81,9 @@ void EmuWindow_SDL2::OnFingerUp() { | |||
| 79 | 81 | ||
| 80 | void EmuWindow_SDL2::OnKeyEvent(int key, u8 state) { | 82 | void EmuWindow_SDL2::OnKeyEvent(int key, u8 state) { |
| 81 | if (state == SDL_PRESSED) { | 83 | if (state == SDL_PRESSED) { |
| 82 | InputCommon::GetKeyboard()->PressKey(key); | 84 | input_subsystem->GetKeyboard()->PressKey(key); |
| 83 | } else if (state == SDL_RELEASED) { | 85 | } else if (state == SDL_RELEASED) { |
| 84 | InputCommon::GetKeyboard()->ReleaseKey(key); | 86 | input_subsystem->GetKeyboard()->ReleaseKey(key); |
| 85 | } | 87 | } |
| 86 | } | 88 | } |
| 87 | 89 | ||
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.h b/src/yuzu_cmd/emu_window/emu_window_sdl2.h index fffac4252..82750ffec 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2.h +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.h | |||
| @@ -14,9 +14,14 @@ namespace Core { | |||
| 14 | class System; | 14 | class System; |
| 15 | } | 15 | } |
| 16 | 16 | ||
| 17 | namespace InputCommon { | ||
| 18 | class InputSubsystem; | ||
| 19 | } | ||
| 20 | |||
| 17 | class EmuWindow_SDL2 : public Core::Frontend::EmuWindow { | 21 | class EmuWindow_SDL2 : public Core::Frontend::EmuWindow { |
| 18 | public: | 22 | public: |
| 19 | explicit EmuWindow_SDL2(Core::System& system, bool fullscreen); | 23 | explicit EmuWindow_SDL2(Core::System& system, bool fullscreen, |
| 24 | InputCommon::InputSubsystem* input_subsystem); | ||
| 20 | ~EmuWindow_SDL2(); | 25 | ~EmuWindow_SDL2(); |
| 21 | 26 | ||
| 22 | /// Polls window events | 27 | /// Polls window events |
| @@ -76,4 +81,7 @@ protected: | |||
| 76 | 81 | ||
| 77 | /// Keeps track of how often to update the title bar during gameplay | 82 | /// Keeps track of how often to update the title bar during gameplay |
| 78 | u32 last_time = 0; | 83 | u32 last_time = 0; |
| 84 | |||
| 85 | /// Input subsystem to use with this window. | ||
| 86 | InputCommon::InputSubsystem* input_subsystem; | ||
| 79 | }; | 87 | }; |
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp index e78025737..881b67a76 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp | |||
| @@ -87,8 +87,9 @@ bool EmuWindow_SDL2_GL::SupportsRequiredGLExtensions() { | |||
| 87 | return unsupported_ext.empty(); | 87 | return unsupported_ext.empty(); |
| 88 | } | 88 | } |
| 89 | 89 | ||
| 90 | EmuWindow_SDL2_GL::EmuWindow_SDL2_GL(Core::System& system, bool fullscreen) | 90 | EmuWindow_SDL2_GL::EmuWindow_SDL2_GL(Core::System& system, bool fullscreen, |
| 91 | : EmuWindow_SDL2{system, fullscreen} { | 91 | InputCommon::InputSubsystem* input_subsystem) |
| 92 | : EmuWindow_SDL2{system, fullscreen, input_subsystem} { | ||
| 92 | SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4); | 93 | SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4); |
| 93 | SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); | 94 | SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); |
| 94 | SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY); | 95 | SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY); |
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.h b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.h index 48bb41683..732a64edd 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.h +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.h | |||
| @@ -8,9 +8,14 @@ | |||
| 8 | #include "core/frontend/emu_window.h" | 8 | #include "core/frontend/emu_window.h" |
| 9 | #include "yuzu_cmd/emu_window/emu_window_sdl2.h" | 9 | #include "yuzu_cmd/emu_window/emu_window_sdl2.h" |
| 10 | 10 | ||
| 11 | namespace InputCommon { | ||
| 12 | class InputSubsystem; | ||
| 13 | } | ||
| 14 | |||
| 11 | class EmuWindow_SDL2_GL final : public EmuWindow_SDL2 { | 15 | class EmuWindow_SDL2_GL final : public EmuWindow_SDL2 { |
| 12 | public: | 16 | public: |
| 13 | explicit EmuWindow_SDL2_GL(Core::System& system, bool fullscreen); | 17 | explicit EmuWindow_SDL2_GL(Core::System& system, bool fullscreen, |
| 18 | InputCommon::InputSubsystem* input_subsystem); | ||
| 14 | ~EmuWindow_SDL2_GL(); | 19 | ~EmuWindow_SDL2_GL(); |
| 15 | 20 | ||
| 16 | void Present() override; | 21 | void Present() override; |
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp index cb8e68a39..53491f86e 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp | |||
| @@ -19,8 +19,9 @@ | |||
| 19 | #include <SDL.h> | 19 | #include <SDL.h> |
| 20 | #include <SDL_syswm.h> | 20 | #include <SDL_syswm.h> |
| 21 | 21 | ||
| 22 | EmuWindow_SDL2_VK::EmuWindow_SDL2_VK(Core::System& system, bool fullscreen) | 22 | EmuWindow_SDL2_VK::EmuWindow_SDL2_VK(Core::System& system, bool fullscreen, |
| 23 | : EmuWindow_SDL2{system, fullscreen} { | 23 | InputCommon::InputSubsystem* input_subsystem) |
| 24 | : EmuWindow_SDL2{system, fullscreen, input_subsystem} { | ||
| 24 | const std::string window_title = fmt::format("yuzu {} | {}-{} (Vulkan)", Common::g_build_name, | 25 | const std::string window_title = fmt::format("yuzu {} | {}-{} (Vulkan)", Common::g_build_name, |
| 25 | Common::g_scm_branch, Common::g_scm_desc); | 26 | Common::g_scm_branch, Common::g_scm_desc); |
| 26 | render_window = | 27 | render_window = |
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.h b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.h index 77a6ca72b..f99704d4c 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.h +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.h | |||
| @@ -13,9 +13,14 @@ namespace Core { | |||
| 13 | class System; | 13 | class System; |
| 14 | } | 14 | } |
| 15 | 15 | ||
| 16 | namespace InputCommon { | ||
| 17 | class InputSubsystem; | ||
| 18 | } | ||
| 19 | |||
| 16 | class EmuWindow_SDL2_VK final : public EmuWindow_SDL2 { | 20 | class EmuWindow_SDL2_VK final : public EmuWindow_SDL2 { |
| 17 | public: | 21 | public: |
| 18 | explicit EmuWindow_SDL2_VK(Core::System& system, bool fullscreen); | 22 | explicit EmuWindow_SDL2_VK(Core::System& system, bool fullscreen, |
| 23 | InputCommon::InputSubsystem* input_subsystem); | ||
| 19 | ~EmuWindow_SDL2_VK(); | 24 | ~EmuWindow_SDL2_VK(); |
| 20 | 25 | ||
| 21 | void Present() override; | 26 | void Present() override; |
diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp index 512b060a7..4f00c804d 100644 --- a/src/yuzu_cmd/yuzu.cpp +++ b/src/yuzu_cmd/yuzu.cpp | |||
| @@ -23,12 +23,14 @@ | |||
| 23 | #include "common/telemetry.h" | 23 | #include "common/telemetry.h" |
| 24 | #include "core/core.h" | 24 | #include "core/core.h" |
| 25 | #include "core/crypto/key_manager.h" | 25 | #include "core/crypto/key_manager.h" |
| 26 | #include "core/file_sys/registered_cache.h" | ||
| 26 | #include "core/file_sys/vfs_real.h" | 27 | #include "core/file_sys/vfs_real.h" |
| 27 | #include "core/gdbstub/gdbstub.h" | 28 | #include "core/gdbstub/gdbstub.h" |
| 28 | #include "core/hle/service/filesystem/filesystem.h" | 29 | #include "core/hle/service/filesystem/filesystem.h" |
| 29 | #include "core/loader/loader.h" | 30 | #include "core/loader/loader.h" |
| 30 | #include "core/settings.h" | 31 | #include "core/settings.h" |
| 31 | #include "core/telemetry_session.h" | 32 | #include "core/telemetry_session.h" |
| 33 | #include "input_common/main.h" | ||
| 32 | #include "video_core/renderer_base.h" | 34 | #include "video_core/renderer_base.h" |
| 33 | #include "yuzu_cmd/config.h" | 35 | #include "yuzu_cmd/config.h" |
| 34 | #include "yuzu_cmd/emu_window/emu_window_sdl2.h" | 36 | #include "yuzu_cmd/emu_window/emu_window_sdl2.h" |
| @@ -37,8 +39,6 @@ | |||
| 37 | #include "yuzu_cmd/emu_window/emu_window_sdl2_vk.h" | 39 | #include "yuzu_cmd/emu_window/emu_window_sdl2_vk.h" |
| 38 | #endif | 40 | #endif |
| 39 | 41 | ||
| 40 | #include "core/file_sys/registered_cache.h" | ||
| 41 | |||
| 42 | #ifdef _WIN32 | 42 | #ifdef _WIN32 |
| 43 | // windows.h needs to be included before shellapi.h | 43 | // windows.h needs to be included before shellapi.h |
| 44 | #include <windows.h> | 44 | #include <windows.h> |
| @@ -82,8 +82,8 @@ static void InitializeLogging() { | |||
| 82 | 82 | ||
| 83 | Log::AddBackend(std::make_unique<Log::ColorConsoleBackend>()); | 83 | Log::AddBackend(std::make_unique<Log::ColorConsoleBackend>()); |
| 84 | 84 | ||
| 85 | const std::string& log_dir = FileUtil::GetUserPath(FileUtil::UserPath::LogDir); | 85 | const std::string& log_dir = Common::FS::GetUserPath(Common::FS::UserPath::LogDir); |
| 86 | FileUtil::CreateFullPath(log_dir); | 86 | Common::FS::CreateFullPath(log_dir); |
| 87 | Log::AddBackend(std::make_unique<Log::FileBackend>(log_dir + LOG_FILE)); | 87 | Log::AddBackend(std::make_unique<Log::FileBackend>(log_dir + LOG_FILE)); |
| 88 | #ifdef _WIN32 | 88 | #ifdef _WIN32 |
| 89 | Log::AddBackend(std::make_unique<Log::DebuggerBackend>()); | 89 | Log::AddBackend(std::make_unique<Log::DebuggerBackend>()); |
| @@ -179,15 +179,16 @@ int main(int argc, char** argv) { | |||
| 179 | Settings::Apply(); | 179 | Settings::Apply(); |
| 180 | 180 | ||
| 181 | Core::System& system{Core::System::GetInstance()}; | 181 | Core::System& system{Core::System::GetInstance()}; |
| 182 | InputCommon::InputSubsystem input_subsystem; | ||
| 182 | 183 | ||
| 183 | std::unique_ptr<EmuWindow_SDL2> emu_window; | 184 | std::unique_ptr<EmuWindow_SDL2> emu_window; |
| 184 | switch (Settings::values.renderer_backend.GetValue()) { | 185 | switch (Settings::values.renderer_backend.GetValue()) { |
| 185 | case Settings::RendererBackend::OpenGL: | 186 | case Settings::RendererBackend::OpenGL: |
| 186 | emu_window = std::make_unique<EmuWindow_SDL2_GL>(system, fullscreen); | 187 | emu_window = std::make_unique<EmuWindow_SDL2_GL>(system, fullscreen, &input_subsystem); |
| 187 | break; | 188 | break; |
| 188 | case Settings::RendererBackend::Vulkan: | 189 | case Settings::RendererBackend::Vulkan: |
| 189 | #ifdef HAS_VULKAN | 190 | #ifdef HAS_VULKAN |
| 190 | emu_window = std::make_unique<EmuWindow_SDL2_VK>(system, fullscreen); | 191 | emu_window = std::make_unique<EmuWindow_SDL2_VK>(system, fullscreen, &input_subsystem); |
| 191 | break; | 192 | break; |
| 192 | #else | 193 | #else |
| 193 | LOG_CRITICAL(Frontend, "Vulkan backend has not been compiled!"); | 194 | LOG_CRITICAL(Frontend, "Vulkan backend has not been compiled!"); |
| @@ -229,7 +230,7 @@ int main(int argc, char** argv) { | |||
| 229 | } | 230 | } |
| 230 | } | 231 | } |
| 231 | 232 | ||
| 232 | system.TelemetrySession().AddField(Telemetry::FieldType::App, "Frontend", "SDL"); | 233 | system.TelemetrySession().AddField(Common::Telemetry::FieldType::App, "Frontend", "SDL"); |
| 233 | 234 | ||
| 234 | // Core is loaded, start the GPU (makes the GPU contexts current to this thread) | 235 | // Core is loaded, start the GPU (makes the GPU contexts current to this thread) |
| 235 | system.GPU().Start(); | 236 | system.GPU().Start(); |
diff --git a/src/yuzu_tester/config.cpp b/src/yuzu_tester/config.cpp index acb22885e..aaf59129a 100644 --- a/src/yuzu_tester/config.cpp +++ b/src/yuzu_tester/config.cpp | |||
| @@ -15,10 +15,11 @@ | |||
| 15 | #include "yuzu_tester/config.h" | 15 | #include "yuzu_tester/config.h" |
| 16 | #include "yuzu_tester/default_ini.h" | 16 | #include "yuzu_tester/default_ini.h" |
| 17 | 17 | ||
| 18 | namespace FS = Common::FS; | ||
| 19 | |||
| 18 | Config::Config() { | 20 | Config::Config() { |
| 19 | // TODO: Don't hardcode the path; let the frontend decide where to put the config files. | 21 | // TODO: Don't hardcode the path; let the frontend decide where to put the config files. |
| 20 | sdl2_config_loc = | 22 | sdl2_config_loc = FS::GetUserPath(FS::UserPath::ConfigDir) + "sdl2-tester-config.ini"; |
| 21 | FileUtil::GetUserPath(FileUtil::UserPath::ConfigDir) + "sdl2-tester-config.ini"; | ||
| 22 | sdl2_config = std::make_unique<INIReader>(sdl2_config_loc); | 23 | sdl2_config = std::make_unique<INIReader>(sdl2_config_loc); |
| 23 | 24 | ||
| 24 | Reload(); | 25 | Reload(); |
| @@ -31,8 +32,8 @@ bool Config::LoadINI(const std::string& default_contents, bool retry) { | |||
| 31 | if (sdl2_config->ParseError() < 0) { | 32 | if (sdl2_config->ParseError() < 0) { |
| 32 | if (retry) { | 33 | if (retry) { |
| 33 | LOG_WARNING(Config, "Failed to load {}. Creating file from defaults...", location); | 34 | LOG_WARNING(Config, "Failed to load {}. Creating file from defaults...", location); |
| 34 | FileUtil::CreateFullPath(location); | 35 | FS::CreateFullPath(location); |
| 35 | FileUtil::WriteStringToFile(true, default_contents, location); | 36 | FS::WriteStringToFile(true, default_contents, location); |
| 36 | sdl2_config = std::make_unique<INIReader>(location); // Reopen file | 37 | sdl2_config = std::make_unique<INIReader>(location); // Reopen file |
| 37 | 38 | ||
| 38 | return LoadINI(default_contents, false); | 39 | return LoadINI(default_contents, false); |
| @@ -74,6 +75,7 @@ void Config::ReadValues() { | |||
| 74 | Settings::values.debug_pad_analogs[i] = ""; | 75 | Settings::values.debug_pad_analogs[i] = ""; |
| 75 | } | 76 | } |
| 76 | 77 | ||
| 78 | Settings::values.vibration_enabled = true; | ||
| 77 | Settings::values.touchscreen.enabled = ""; | 79 | Settings::values.touchscreen.enabled = ""; |
| 78 | Settings::values.touchscreen.device = ""; | 80 | Settings::values.touchscreen.device = ""; |
| 79 | Settings::values.touchscreen.finger = 0; | 81 | Settings::values.touchscreen.finger = 0; |
| @@ -87,12 +89,12 @@ void Config::ReadValues() { | |||
| 87 | // Data Storage | 89 | // Data Storage |
| 88 | Settings::values.use_virtual_sd = | 90 | Settings::values.use_virtual_sd = |
| 89 | sdl2_config->GetBoolean("Data Storage", "use_virtual_sd", true); | 91 | sdl2_config->GetBoolean("Data Storage", "use_virtual_sd", true); |
| 90 | FileUtil::GetUserPath(FileUtil::UserPath::NANDDir, | 92 | FS::GetUserPath(Common::FS::UserPath::NANDDir, |
| 91 | sdl2_config->Get("Data Storage", "nand_directory", | 93 | sdl2_config->Get("Data Storage", "nand_directory", |
| 92 | FileUtil::GetUserPath(FileUtil::UserPath::NANDDir))); | 94 | Common::FS::GetUserPath(Common::FS::UserPath::NANDDir))); |
| 93 | FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir, | 95 | FS::GetUserPath(Common::FS::UserPath::SDMCDir, |
| 94 | sdl2_config->Get("Data Storage", "sdmc_directory", | 96 | sdl2_config->Get("Data Storage", "sdmc_directory", |
| 95 | FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir))); | 97 | Common::FS::GetUserPath(Common::FS::UserPath::SDMCDir))); |
| 96 | 98 | ||
| 97 | // System | 99 | // System |
| 98 | Settings::values.current_user = std::clamp<int>( | 100 | Settings::values.current_user = std::clamp<int>( |
diff --git a/src/yuzu_tester/emu_window/emu_window_sdl2_hide.cpp b/src/yuzu_tester/emu_window/emu_window_sdl2_hide.cpp index 8584f6671..78f75fb38 100644 --- a/src/yuzu_tester/emu_window/emu_window_sdl2_hide.cpp +++ b/src/yuzu_tester/emu_window/emu_window_sdl2_hide.cpp | |||
| @@ -13,7 +13,6 @@ | |||
| 13 | 13 | ||
| 14 | #include <glad/glad.h> | 14 | #include <glad/glad.h> |
| 15 | 15 | ||
| 16 | #include "common/assert.h" | ||
| 17 | #include "common/logging/log.h" | 16 | #include "common/logging/log.h" |
| 18 | #include "common/scm_rev.h" | 17 | #include "common/scm_rev.h" |
| 19 | #include "core/settings.h" | 18 | #include "core/settings.h" |
| @@ -53,7 +52,7 @@ EmuWindow_SDL2_Hide::EmuWindow_SDL2_Hide() { | |||
| 53 | exit(1); | 52 | exit(1); |
| 54 | } | 53 | } |
| 55 | 54 | ||
| 56 | InputCommon::Init(); | 55 | input_subsystem->Initialize(); |
| 57 | 56 | ||
| 58 | SDL_SetMainReady(); | 57 | SDL_SetMainReady(); |
| 59 | 58 | ||
| @@ -105,7 +104,7 @@ EmuWindow_SDL2_Hide::EmuWindow_SDL2_Hide() { | |||
| 105 | } | 104 | } |
| 106 | 105 | ||
| 107 | EmuWindow_SDL2_Hide::~EmuWindow_SDL2_Hide() { | 106 | EmuWindow_SDL2_Hide::~EmuWindow_SDL2_Hide() { |
| 108 | InputCommon::Shutdown(); | 107 | input_subsystem->Shutdown(); |
| 109 | SDL_GL_DeleteContext(gl_context); | 108 | SDL_GL_DeleteContext(gl_context); |
| 110 | SDL_Quit(); | 109 | SDL_Quit(); |
| 111 | } | 110 | } |
diff --git a/src/yuzu_tester/emu_window/emu_window_sdl2_hide.h b/src/yuzu_tester/emu_window/emu_window_sdl2_hide.h index c13a82df2..a553b4b95 100644 --- a/src/yuzu_tester/emu_window/emu_window_sdl2_hide.h +++ b/src/yuzu_tester/emu_window/emu_window_sdl2_hide.h | |||
| @@ -8,6 +8,10 @@ | |||
| 8 | 8 | ||
| 9 | struct SDL_Window; | 9 | struct SDL_Window; |
| 10 | 10 | ||
| 11 | namespace InputCommon { | ||
| 12 | class InputSubsystem; | ||
| 13 | } | ||
| 14 | |||
| 11 | class EmuWindow_SDL2_Hide : public Core::Frontend::EmuWindow { | 15 | class EmuWindow_SDL2_Hide : public Core::Frontend::EmuWindow { |
| 12 | public: | 16 | public: |
| 13 | explicit EmuWindow_SDL2_Hide(); | 17 | explicit EmuWindow_SDL2_Hide(); |
| @@ -25,6 +29,8 @@ private: | |||
| 25 | /// Whether the GPU and driver supports the OpenGL extension required | 29 | /// Whether the GPU and driver supports the OpenGL extension required |
| 26 | bool SupportsRequiredGLExtensions(); | 30 | bool SupportsRequiredGLExtensions(); |
| 27 | 31 | ||
| 32 | std::unique_ptr<InputCommon::InputSubsystem> input_subsystem; | ||
| 33 | |||
| 28 | /// Internal SDL2 render window | 34 | /// Internal SDL2 render window |
| 29 | SDL_Window* render_window; | 35 | SDL_Window* render_window; |
| 30 | 36 | ||
diff --git a/src/yuzu_tester/yuzu.cpp b/src/yuzu_tester/yuzu.cpp index 083667baf..7acf0caad 100644 --- a/src/yuzu_tester/yuzu.cpp +++ b/src/yuzu_tester/yuzu.cpp | |||
| @@ -79,8 +79,8 @@ static void InitializeLogging(bool console) { | |||
| 79 | if (console) | 79 | if (console) |
| 80 | Log::AddBackend(std::make_unique<Log::ColorConsoleBackend>()); | 80 | Log::AddBackend(std::make_unique<Log::ColorConsoleBackend>()); |
| 81 | 81 | ||
| 82 | const std::string& log_dir = FileUtil::GetUserPath(FileUtil::UserPath::LogDir); | 82 | const std::string& log_dir = Common::FS::GetUserPath(Common::FS::UserPath::LogDir); |
| 83 | FileUtil::CreateFullPath(log_dir); | 83 | Common::FS::CreateFullPath(log_dir); |
| 84 | Log::AddBackend(std::make_unique<Log::FileBackend>(log_dir + LOG_FILE)); | 84 | Log::AddBackend(std::make_unique<Log::FileBackend>(log_dir + LOG_FILE)); |
| 85 | #ifdef _WIN32 | 85 | #ifdef _WIN32 |
| 86 | Log::AddBackend(std::make_unique<Log::DebuggerBackend>()); | 86 | Log::AddBackend(std::make_unique<Log::DebuggerBackend>()); |
| @@ -251,7 +251,8 @@ int main(int argc, char** argv) { | |||
| 251 | 251 | ||
| 252 | Service::Yuzu::InstallInterfaces(system.ServiceManager(), datastring, callback); | 252 | Service::Yuzu::InstallInterfaces(system.ServiceManager(), datastring, callback); |
| 253 | 253 | ||
| 254 | system.TelemetrySession().AddField(Telemetry::FieldType::App, "Frontend", "SDLHideTester"); | 254 | system.TelemetrySession().AddField(Common::Telemetry::FieldType::App, "Frontend", |
| 255 | "SDLHideTester"); | ||
| 255 | 256 | ||
| 256 | system.GPU().Start(); | 257 | system.GPU().Start(); |
| 257 | system.Renderer().Rasterizer().LoadDiskResources(); | 258 | system.Renderer().Rasterizer().LoadDiskResources(); |