Compare commits

...

47 Commits

Author SHA1 Message Date
Morph
8ffc491546 input_common/main: Add "/Mouse" to the display name 2020-08-26 22:41:51 -04:00
Morph
f5f30781ae configure_input_player: Fix modifier scale button mapping 2020-08-26 02:32:32 -04:00
Morph
1bd70d73c0 configuration/input: Add support for mouse button clicks
Supports the Left, Right, Middle, Backward and Forward mouse buttons.
2020-08-26 02:32:32 -04:00
Morph
eb149ec696 controllers/npad: Fix inconsistencies with controller connection statuses 2020-08-26 02:32:32 -04:00
Morph
334ef2efdd controllers/npad: Fix LibNX controller connection statuses
This allows homebrew applications to be able to properly detect connected controllers.
2020-08-26 02:32:32 -04:00
Morph
e7c174b426 controllers/npad: Fix LedPattern for P1-4 2020-08-26 02:32:32 -04:00
Morph
de79897f04 input_common: Fix directional deadzone values
The hardware tested value is 0.5 which translates to SHRT_MAX / 2
2020-08-26 02:32:32 -04:00
Morph
efa0b7a056 Address feedback 2020-08-26 02:32:32 -04:00
Morph
fc505110f1 qt_themes: Fix Midnight Blue theme
Co-authored-by: Its-Rei <kupfel@gmail.com>
2020-08-26 02:32:32 -04:00
Morph
f0fac0c7fb Project Mjölnir: Part 1
Co-authored-by: James Rowe <jroweboy@gmail.com>
Co-authored-by: Its-Rei <kupfel@gmail.com>
2020-08-26 02:32:32 -04:00
bunnei
b8885aa03b Merge pull request #4582 from lioncash/xbyak
externals: Update Xbyak to 5.95
2020-08-25 22:02:20 -04:00
Lioncash
c024e5c69a externals: Update Xbyak to 5.95
5.95 contains a potentially backward-compatibility breaking change, so
we should be updating to this to ensure that our code remains
forward-compatible.
2020-08-25 18:16:52 -04:00
bunnei
4efaecf125 Merge pull request #4572 from lioncash/xbyak
externals: Update xbyak to v5.941
2020-08-25 11:24:32 -04:00
bunnei
902bf6d37d Merge pull request #4574 from lioncash/const-fn
memory_manager: Mark IsGranularRange() as a const member function
2020-08-25 11:24:13 -04:00
bunnei
2cd788b6ad Merge pull request #4565 from lioncash/memset
microprofile: Don't memset through std::atomic types
2020-08-25 11:23:16 -04:00
bunnei
dd828607e0 Merge pull request #4563 from lioncash/rcache
registered_cache: Make use of designated initializers
2020-08-25 10:07:33 -04:00
bunnei
b798813eee Merge pull request #4548 from lioncash/color
common/color: Migrate code over to the Common namespace
2020-08-25 10:07:13 -04:00
bunnei
bb752df736 Merge pull request #4542 from ReinUsesLisp/gpu-init-base
video_core: Initialize renderer with a GPU
2020-08-24 22:56:11 -04:00
bunnei
6fd3a1bf85 Merge pull request #4562 from lioncash/loop
cpu_manager: Make use of ranged for where applicable
2020-08-24 17:58:41 -04:00
Rodrigo Locatti
b72d2069ba Merge pull request #4573 from lioncash/label
gl_texture_cache: Take std::string by reference in DecorateViewName()
2020-08-24 01:40:22 -03:00
Lioncash
5bce81c3d6 memory_manager: Mark IsGranularRange() as a const member function
This doesn't modify internal member state, so it can be marked as const.
2020-08-24 00:37:57 -04:00
Lioncash
bae4e6c2f5 gl_texture_cache: Take std::string by reference in DecorateViewName()
LabelGLObject takes a string_view, so we don't need to make copies of
the std::string.
2020-08-23 23:36:33 -04:00
Rodrigo Locatti
fff2de8224 Merge pull request #4571 from lioncash/fence
video_core/fence_manager: Remove unnecessary includes
2020-08-24 00:32:29 -03:00
Lioncash
3121acdf4e externals: Update xbyak to v5.941
Keeps the tracked submodule up to date with the latest release.
2020-08-23 22:47:41 -04:00
Lioncash
f3bb52c0a9 video_core/fence_manager: Remove unnecessary includes
Avoids pulling in unnecessary things that can cause rebuilds when they
aren't required.
2020-08-23 21:44:50 -04:00
Lioncash
ec8d72a567 microprofile: Don't memset through std::atomic types
Two of the members of the MicroProfileThreadLog contains two std::atomic
instances. Given these aren't trivially-copyable types, we shouldn't be
memsetting the structure, given implementation details can contain other
members within it.

To avoid potential undefined behavior on platforms, we can use aggregate
initialization to zero out the members while still having well-defined
behavior.

While we're at it we can also silence some sign conversion warnings.
2020-08-23 21:19:01 -04:00
bunnei
ab350b8975 Merge pull request #4561 from lioncash/key-constexpr
key_manager: Make data arrays constexpr
2020-08-23 20:41:05 -04:00
bunnei
42a00877a2 Merge pull request #4549 from lioncash/files
vfs_real: Avoid redundant map lookups
2020-08-23 19:08:36 -04:00
bunnei
9619964e8c Merge pull request #4559 from lioncash/webresult
web_service: Move web_result.h into web_service
2020-08-23 17:54:43 -04:00
Lioncash
67a8e73101 registered_cache: Make use of ends_with for string suffix checking
Simplifies code.
2020-08-23 11:25:45 -04:00
Lioncash
f83c6e1e0c registered_cache: Make use of designated initializers
Removes the need for comments to indicate the fields being assigned.
2020-08-23 10:26:20 -04:00
bunnei
cfb7fd395c Merge pull request #4560 from lioncash/convert
core_timing: Resolve sign conversion warning
2020-08-23 02:11:14 -04:00
Lioncash
b62a8ca43e key_manager: Make data arrays constexpr
We can convert these maps into constexpr arrays to eliminate some
runtime static constructors.
2020-08-22 22:47:24 -04:00
Lioncash
79504f1a39 core_timing: Remove unused header 2020-08-22 22:12:37 -04:00
Lioncash
25cd5d9dda core_timing: Move clock initializer into constructor initializer list
Same behavior, minus unnecessary zeroing out of the pointer.
2020-08-22 20:26:48 -04:00
Lioncash
2624b1eae6 core_timing: Resolve sign conversion warning
This constant is only ever assigned to downcount, which is a s64, not a
u64.
2020-08-22 20:26:45 -04:00
Lioncash
ca5ed50655 web_service: Move web_result.h into web_service
This is the only place it's actively used. It's also more appropriate
for web-related structures to be within the web service target.
Especially given this one doesn't rely on anything in the common
library.
2020-08-22 19:29:54 -04:00
ReinUsesLisp
da53bcee60 video_core: Initialize renderer with a GPU
Add an extra step in GPU initialization to be able to initialize render
backends with a valid GPU instance.
2020-08-22 01:51:45 -03:00
bunnei
baff9ffcac Merge pull request #4521 from lioncash/optionalcache
gl_shader_disk_cache: Make use of std::nullopt where applicable
2020-08-21 23:56:55 -04:00
bunnei
66ac7cf730 Merge pull request #4541 from MerryMage/yolo
dynarmic: Add unsafe optimizations
2020-08-21 23:06:21 -04:00
bunnei
53fbf8e206 Merge pull request #4523 from lioncash/self-assign
macro-interpreter: Resolve -Wself-assign-field warning
2020-08-21 18:25:53 -04:00
Lioncash
551882e512 vfs_real: Resolve sign conversion warnings 2020-08-18 14:58:33 -04:00
Lioncash
ed9ae5a977 vfs_real: Avoid redundant map lookups
Avoids some trivially avoidable map lookups by keeping the result of
find operations around and querying them.
2020-08-18 14:58:29 -04:00
Lioncash
e864aa25d5 common/color: Migrate code over to the Common namespace
No external code makes use of this header, so we can freely change the
namespace.
2020-08-18 14:27:41 -04:00
MerryMage
836ec9176a dynarmic: Add unsafe optimizations 2020-08-16 14:15:39 +01:00
Lioncash
34ec64233a macro-interpreter: Resolve -Wself-assign-field warning
This was assigning the field to itself, which is a no-op. The size
doesn't change between its initial assignment and this one, so this is a
safe change to make.
2020-08-14 08:26:50 -04:00
Lioncash
c8135b3c18 gl_shader_disk_cache: Make use of std::nullopt where applicable
Allows the compiler to avoid unnecessarily zeroing out the internal
buffer of std::optional on some implementations.
2020-08-14 08:20:44 -04:00
138 changed files with 9481 additions and 3798 deletions

25
dist/icons/controller/controller.qrc vendored Normal file
View File

@@ -0,0 +1,25 @@
<RCC>
<qresource prefix="controller">
<file alias="dual_joycon">dual_joycon.png</file>
<file alias="dual_joycon_dark">dual_joycon_dark.png</file>
<file alias="dual_joycon_midnight">dual_joycon_midnight.png</file>
<file alias="handheld">handheld.png</file>
<file alias="handheld_dark">handheld_dark.png</file>
<file alias="handheld_midnight">handheld_midnight.png</file>
<file alias="pro_controller">pro_controller.png</file>
<file alias="pro_controller_dark">pro_controller_dark.png</file>
<file alias="pro_controller_midnight">pro_controller_midnight.png</file>
<file alias="single_joycon_left">single_joycon_left.png</file>
<file alias="single_joycon_left_dark">single_joycon_left_dark.png</file>
<file alias="single_joycon_left_midnight">single_joycon_left_midnight.png</file>
<file alias="single_joycon_right">single_joycon_right.png</file>
<file alias="single_joycon_right_dark">single_joycon_right_dark.png</file>
<file alias="single_joycon_right_midnight">single_joycon_right_midnight.png</file>
<file alias="single_joycon_left_vertical">single_joycon_left_vertical.png</file>
<file alias="single_joycon_left_vertical_dark">single_joycon_left_vertical_dark.png</file>
<file alias="single_joycon_left_vertical_midnight">single_joycon_left_vertical_midnight.png</file>
<file alias="single_joycon_right_vertical">single_joycon_right_vertical.png</file>
<file alias="single_joycon_right_vertical_dark">single_joycon_right_vertical_dark.png</file>
<file alias="single_joycon_right_vertical_midnight">single_joycon_right_vertical_midnight.png</file>
</qresource>
</RCC>

BIN
dist/icons/controller/dual_joycon.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

BIN
dist/icons/controller/handheld.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
dist/icons/controller/handheld_dark.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
dist/icons/controller/pro_controller.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

3
dist/license.md vendored
View File

@@ -5,6 +5,7 @@ Icon Name | License | Origin/Author
qt_themes/default/icons/16x16/checked.png | CC BY-ND 3.0 | https://icons8.com
qt_themes/default/icons/16x16/failed.png | CC BY-ND 3.0 | https://icons8.com
qt_themes/default/icons/16x16/lock.png | CC BY-ND 3.0 | https://icons8.com
qt_themes/default/icons/16x16/view-refresh.png | Apache 2.0 | https://material.io
qt_themes/default/icons/256x256/plus_folder.png | CC BY-ND 3.0 | https://icons8.com
qt_themes/default/icons/48x48/bad_folder.png | CC BY-ND 3.0 | https://icons8.com
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
qt_themes/default/icons/48x48/plus.png | CC0 1.0 | Designed by BreadFish64 from the Citra team
qt_themes/default/icons/48x48/sd_card.png | CC BY-ND 3.0 | https://icons8.com
qt_themes/qdarkstyle/icons/16x16/lock.png | CC BY-ND 3.0 | https://icons8.com
qt_themes/qdarkstyle/icons/16x16/view-refresh.png | Apache 2.0 | https://material.io
qt_themes/qdarkstyle/icons/256x256/plus_folder.png | CC BY-ND 3.0 | https://icons8.com
qt_themes/qdarkstyle/icons/48x48/bad_folder.png | CC BY-ND 3.0 | https://icons8.com
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
qt_themes/qdarkstyle/icons/48x48/plus.png | CC0 1.0 | Designed by BreadFish64 from the Citra team
qt_themes/qdarkstyle/icons/48x48/sd_card.png | CC BY-ND 3.0 | https://icons8.com
qt_themes/colorful/icons/16x16/lock.png | CC BY-ND 3.0 | https://icons8.com
qt_themes/colorful/icons/16x16/view-refresh.png | Apache 2.0 | https://material.io
qt_themes/colorful/icons/256x256/plus_folder.png | CC BY-ND 3.0 | https://icons8.com
qt_themes/colorful/icons/48x48/bad_folder.png | CC BY-ND 3.0 | https://icons8.com
qt_themes/colorful/icons/48x48/chip.png | CC BY-ND 3.0 | https://icons8.com

Binary file not shown.

After

Width:  |  Height:  |  Size: 362 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 362 B

View File

@@ -2,6 +2,7 @@
<qresource prefix="icons/colorful_dark">
<file alias="index.theme">icons/index.theme</file>
<file alias="16x16/lock.png">icons/16x16/lock.png</file>
<file alias="16x16/view-refresh.png">icons/16x16/view-refresh.png</file>
<file alias="48x48/bad_folder.png">../colorful/icons/48x48/bad_folder.png</file>
<file alias="48x48/chip.png">../colorful/icons/48x48/chip.png</file>
<file alias="48x48/folder.png">../colorful/icons/48x48/folder.png</file>

Binary file not shown.

After

Width:  |  Height:  |  Size: 362 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 362 B

View File

@@ -2,6 +2,7 @@
<qresource prefix="icons/colorful_midnight_blue">
<file alias="index.theme">icons/index.theme</file>
<file alias="16x16/lock.png">icons/16x16/lock.png</file>
<file alias="16x16/view-refresh.png">icons/16x16/view-refresh.png</file>
<file alias="48x48/bad_folder.png">../colorful/icons/48x48/bad_folder.png</file>
<file alias="48x48/chip.png">../colorful/icons/48x48/chip.png</file>
<file alias="48x48/folder.png">../colorful/icons/48x48/folder.png</file>

View File

@@ -4,6 +4,7 @@
<file alias="16x16/checked.png">icons/16x16/checked.png</file>
<file alias="16x16/failed.png">icons/16x16/failed.png</file>
<file alias="16x16/lock.png">icons/16x16/lock.png</file>
<file alias="16x16/view-refresh.png">icons/16x16/view-refresh.png</file>
<file alias="48x48/bad_folder.png">icons/48x48/bad_folder.png</file>
<file alias="48x48/chip.png">icons/48x48/chip.png</file>
<file alias="48x48/folder.png">icons/48x48/folder.png</file>

Binary file not shown.

After

Width:  |  Height:  |  Size: 349 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 349 B

View File

@@ -30,6 +30,66 @@ QPushButton#RendererStatusBarButton:checked {
color: #e85c00;
}
QPushButton#RendererStatusBarButton:!checked{
QPushButton#RendererStatusBarButton:!checked {
color: #0066ff;
}
QPushButton#buttonRefreshDevices {
min-width: 20px;
min-height: 20px;
max-width: 20px;
max-height: 20px;
}
QCheckBox#checkboxPlayer1Connected,
QCheckBox#checkboxPlayer2Connected,
QCheckBox#checkboxPlayer3Connected,
QCheckBox#checkboxPlayer4Connected,
QCheckBox#checkboxPlayer5Connected,
QCheckBox#checkboxPlayer6Connected,
QCheckBox#checkboxPlayer7Connected,
QCheckBox#checkboxPlayer8Connected {
spacing: 0px;
}
QCheckBox#checkboxPlayer1Connected::indicator,
QCheckBox#checkboxPlayer2Connected::indicator,
QCheckBox#checkboxPlayer3Connected::indicator,
QCheckBox#checkboxPlayer4Connected::indicator,
QCheckBox#checkboxPlayer5Connected::indicator,
QCheckBox#checkboxPlayer6Connected::indicator,
QCheckBox#checkboxPlayer7Connected::indicator,
QCheckBox#checkboxPlayer8Connected::indicator {
width: 14px;
height: 14px;
}
QCheckBox#checkboxPlayer1Connected::indicator:checked,
QCheckBox#checkboxPlayer2Connected::indicator:checked,
QCheckBox#checkboxPlayer3Connected::indicator:checked,
QCheckBox#checkboxPlayer4Connected::indicator:checked,
QCheckBox#checkboxPlayer5Connected::indicator:checked,
QCheckBox#checkboxPlayer6Connected::indicator:checked,
QCheckBox#checkboxPlayer7Connected::indicator:checked,
QCheckBox#checkboxPlayer8Connected::indicator:checked,
QGroupBox#groupConnectedController::indicator:checked {
border-radius: 2px;
border: 1px solid black;
background: #39ff14;
image: none;
}
QCheckBox#checkboxPlayer1Connected::indicator:unchecked,
QCheckBox#checkboxPlayer2Connected::indicator:unchecked,
QCheckBox#checkboxPlayer3Connected::indicator:unchecked,
QCheckBox#checkboxPlayer4Connected::indicator:unchecked,
QCheckBox#checkboxPlayer5Connected::indicator:unchecked,
QCheckBox#checkboxPlayer6Connected::indicator:unchecked,
QCheckBox#checkboxPlayer7Connected::indicator:unchecked,
QCheckBox#checkboxPlayer8Connected::indicator:unchecked,
QGroupBox#groupConnectedController::indicator:unchecked {
border-radius: 2px;
border: 1px solid black;
background: transparent;
image: none;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 362 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 362 B

View File

@@ -2,6 +2,7 @@
<qresource prefix="icons/qdarkstyle">
<file alias="index.theme">icons/index.theme</file>
<file alias="16x16/lock.png">icons/16x16/lock.png</file>
<file alias="16x16/view-refresh.png">icons/16x16/view-refresh.png</file>
<file alias="48x48/bad_folder.png">icons/48x48/bad_folder.png</file>
<file alias="48x48/chip.png">icons/48x48/chip.png</file>
<file alias="48x48/folder.png">icons/48x48/folder.png</file>

View File

@@ -40,8 +40,8 @@ QCheckBox:disabled {
QCheckBox::indicator,
QGroupBox::indicator {
width: 18px;
height: 18px;
width: 16px;
height: 16px;
}
QGroupBox::indicator {
@@ -1237,6 +1237,7 @@ QPlainTextEdit:disabled {
background-color: #2b2e31;
}
QPushButton#TogglableStatusBarButton {
min-width: 0px;
color: #656565;
@@ -1271,6 +1272,102 @@ QPushButton#RendererStatusBarButton:checked {
color: #e85c00;
}
QPushButton#RendererStatusBarButton:!checked{
color: #00ccdd;
QPushButton#RendererStatusBarButton:!checked {
color: #00ccdd;
}
QPushButton#buttonRefreshDevices {
min-width: 24px;
min-height: 24px;
max-width: 24px;
max-height: 24px;
padding: 0px 0px;
}
QCheckBox#checkboxPlayer1Connected,
QCheckBox#checkboxPlayer2Connected,
QCheckBox#checkboxPlayer3Connected,
QCheckBox#checkboxPlayer4Connected,
QCheckBox#checkboxPlayer5Connected,
QCheckBox#checkboxPlayer6Connected,
QCheckBox#checkboxPlayer7Connected,
QCheckBox#checkboxPlayer8Connected {
spacing: 0px;
}
QCheckBox#checkboxPlayer1Connected::indicator,
QCheckBox#checkboxPlayer2Connected::indicator,
QCheckBox#checkboxPlayer3Connected::indicator,
QCheckBox#checkboxPlayer4Connected::indicator,
QCheckBox#checkboxPlayer5Connected::indicator,
QCheckBox#checkboxPlayer6Connected::indicator,
QCheckBox#checkboxPlayer7Connected::indicator,
QCheckBox#checkboxPlayer8Connected::indicator {
width: 14px;
height: 14px;
}
QCheckBox#checkboxPlayer1Connected::indicator:checked,
QCheckBox#checkboxPlayer2Connected::indicator:checked,
QCheckBox#checkboxPlayer3Connected::indicator:checked,
QCheckBox#checkboxPlayer4Connected::indicator:checked,
QCheckBox#checkboxPlayer5Connected::indicator:checked,
QCheckBox#checkboxPlayer6Connected::indicator:checked,
QCheckBox#checkboxPlayer7Connected::indicator:checked,
QCheckBox#checkboxPlayer8Connected::indicator:checked,
QGroupBox#groupConnectedController::indicator:checked {
border-radius: 2px;
border: 1px solid #929192;
background: #39ff14;
image: none;
}
QCheckBox#checkboxPlayer1Connected::indicator:unchecked,
QCheckBox#checkboxPlayer2Connected::indicator:unchecked,
QCheckBox#checkboxPlayer3Connected::indicator:unchecked,
QCheckBox#checkboxPlayer4Connected::indicator:unchecked,
QCheckBox#checkboxPlayer5Connected::indicator:unchecked,
QCheckBox#checkboxPlayer6Connected::indicator:unchecked,
QCheckBox#checkboxPlayer7Connected::indicator:unchecked,
QCheckBox#checkboxPlayer8Connected::indicator:unchecked,
QGroupBox#groupConnectedController::indicator:unchecked {
border-radius: 2px;
border: 1px solid #929192;
background: transparent;
image: none;
}
QSpinBox#spinboxLStickRange,
QSpinBox#spinboxRStickRange {
padding: 4px 0px 5px 0px;
min-width: 63px;
}
QSpinBox#vibrationSpin {
padding: 4px 0px 5px 0px;
min-width: 63px;
}
QSpinBox#spinboxLStickRange:up-button,
QSpinBox#spinboxRStickRange:up-button,
QSpinBox#vibrationSpin:up-button {
left: -2px;
}
QSpinBox#spinboxLStickRange:down-button,
QSpinBox#spinboxRStickRange:down-button,
QSpinBox#vibrationSpin:down-button {
right: -1px;
}
QGroupBox#motionGroup::indicator,
QGroupBox#vibrationGroup::indicator {
margin-left: 0px;
}
QGroupBox#motionGroup::title,
QGroupBox#vibrationGroup::title {
spacing: 2px;
padding-left: 1px;
padding-right: 1px;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 362 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 362 B

View File

@@ -2,6 +2,7 @@
<qresource prefix="icons/qdarkstyle_midnight_blue">
<file alias="index.theme">icons/index.theme</file>
<file alias="16x16/lock.png">icons/16x16/lock.png</file>
<file alias="16x16/view-refresh.png">icons/16x16/view-refresh.png</file>
<file alias="48x48/bad_folder.png">icons/48x48/bad_folder.png</file>
<file alias="48x48/chip.png">icons/48x48/chip.png</file>
<file alias="48x48/folder.png">icons/48x48/folder.png</file>

View File

@@ -138,8 +138,6 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qstatusbar
--------------------------------------------------------------------------- */
QStatusBar {
border: 1px solid #32414B;
/* Fixes Spyder #9120, #9121 */
background: #32414B;
/* Fixes #205, white vertical borders separating items */
}
@@ -161,6 +159,7 @@ QStatusBar QToolTip {
QStatusBar QLabel {
/* Fixes Spyder #9120, #9121 */
background: transparent;
padding: 0px;
}
/* QCheckBox --------------------------------------------------------------
@@ -236,21 +235,19 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qgroupbox
--------------------------------------------------------------------------- */
QGroupBox {
font-weight: bold;
border: 1px solid #32414B;
border-radius: 4px;
padding: 4px;
margin-top: 16px;
font-weight: bold;
border: 1px solid #32414B;
border-radius: 4px;
margin-top: 12px;
padding: 4px;
}
QGroupBox::title {
subcontrol-origin: margin;
subcontrol-position: top left;
left: 3px;
padding-left: 3px;
padding-right: 5px;
padding-top: 8px;
padding-bottom: 16px;
subcontrol-origin: margin;
subcontrol-position: top left;
padding-left: 3px;
padding-right: 5px;
padding-top: 4px;
}
QGroupBox::indicator {
@@ -367,28 +364,19 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qmenubar
--------------------------------------------------------------------------- */
QMenuBar {
background-color: #32414B;
padding: 2px;
border: 1px solid #19232D;
color: #F0F0F0;
}
QMenuBar:focus {
border: 1px solid #148CD2;
}
QMenuBar::item {
background: transparent;
padding: 4px;
}
QMenuBar::item:selected {
padding: 4px;
background: transparent;
border: 0px solid #32414B;
}
QMenuBar::item:pressed {
padding: 4px;
border: 0px solid #32414B;
background-color: #148CD2;
color: #F0F0F0;
@@ -396,6 +384,7 @@ QMenuBar::item:pressed {
padding-bottom: 0px;
}
/* QMenu ------------------------------------------------------------------
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
--------------------------------------------------------------------------- */
QAbstractItemView {
alternate-background-color: #19232D;
alternate-background-color: #1f2933;
color: #F0F0F0;
border: 1px solid #32414B;
border-radius: 4px;
@@ -501,13 +490,13 @@ QAbstractScrollArea {
background-color: #19232D;
border: 1px solid #32414B;
border-radius: 4px;
padding: 2px;
/* fix #159 */
min-height: 1.25em;
/* fix #159 */
color: #F0F0F0;
}
QAbstractScrollArea:disabled {
color: #787878;
}
@@ -807,20 +796,22 @@ QAbstractSpinBox {
}
QAbstractSpinBox:up-button {
background-color: transparent #19232D;
background-color: #505F69;
subcontrol-origin: border;
subcontrol-position: top right;
border-left: 1px solid #32414B;
border-bottom: 1px solid #32414B;
border-top: 1px solid #32414B;
border-right: 1px solid #32414B;
border-top-right-radius: 4px;
border-top-left-radius: 0;
border-bottom-left-radius: 0;
margin: 1px;
margin: 0px;
width: 12px;
margin-bottom: -1px;
margin-bottom: 0px;
}
QAbstractSpinBox::up-arrow, QAbstractSpinBox::up-arrow:disabled, QAbstractSpinBox::up-arrow:off {
image: url(":/qss_icons/rc/arrow_up_disabled.png");
image: url(":/qss_icons/rc/up_arrow.png");
height: 8px;
width: 8px;
}
@@ -830,20 +821,23 @@ QAbstractSpinBox::up-arrow:hover {
}
QAbstractSpinBox:down-button {
background-color: transparent #19232D;
background-color: #505F69;
subcontrol-origin: border;
subcontrol-position: bottom right;
border-left: 1px solid #32414B;
border-right: 1px solid #32414B;
border-bottom: 1px solid #32414B;
border-top: 1px solid #32414B;
border-top-left-radius: 0;
border-bottom-left-radius: 0;
margin: 1px;
border-bottom-right-radius: 4px;
margin: 0px;
width: 12px;
margin-top: -1px;
margin-top: 0px;
}
QAbstractSpinBox::down-arrow, QAbstractSpinBox::down-arrow:disabled, QAbstractSpinBox::down-arrow:off {
image: url(":/qss_icons/rc/arrow_down_disabled.png");
image: url(":/qss_icons/rc/down_arrow.png");
height: 8px;
width: 8px;
}
@@ -1199,6 +1193,7 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qcombobox
--------------------------------------------------------------------------- */
QComboBox {
background-color: #0f1922;
border: 1px solid #32414B;
border-radius: 4px;
selection-background-color: #1464A0;
@@ -1216,7 +1211,7 @@ QComboBox {
QComboBox QAbstractItemView {
border: 1px solid #32414B;
border-radius: 0;
background-color: #19232D;
background-color: #0f1922;
selection-background-color: #1464A0;
}
@@ -1285,7 +1280,12 @@ QComboBox::drop-down {
}
QComboBox::down-arrow {
image: url(":/qss_icons/rc/arrow_down_disabled.png");
image: url(":/qss_icons/rc/down_arrow.png");
background-color: #505F69;
padding: 6px 2px;
border: 1px solid #32414B;
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
height: 8px;
width: 8px;
}
@@ -1559,12 +1559,12 @@ QTabBar::tab:right:!selected {
QTabBar::tab:top {
background-color: #32414B;
color: #F0F0F0;
min-width: 36px;
margin-left: 2px;
padding-left: 4px;
padding-right: 4px;
padding-left: 8px;
padding-right: 8px;
padding-top: 2px;
padding-bottom: 2px;
min-width: 5px;
border-bottom: 3px solid #32414B;
border-top-left-radius: 3px;
border-top-right-radius: 3px;
@@ -1588,16 +1588,16 @@ QTabBar::tab:top:!selected:hover {
QTabBar::tab:bottom {
color: #F0F0F0;
min-width: 36px;
border-top: 3px solid #32414B;
background-color: #32414B;
margin-left: 2px;
padding-left: 4px;
padding-right: 4px;
padding-left: 8px;
padding-right: 8px;
padding-top: 2px;
padding-bottom: 2px;
border-bottom-left-radius: 3px;
border-bottom-right-radius: 3px;
min-width: 5px;
}
QTabBar::tab:bottom:selected {
@@ -1752,21 +1752,6 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qlistview
https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtableview
--------------------------------------------------------------------------- */
QTreeView:branch:selected, QTreeView:branch:hover {
background: url(":/qss_icons/rc/transparent.png");
}
QTreeView:branch:has-siblings:!adjoins-item {
border-image: url(":/qss_icons/rc/branch_line.png") 0;
}
QTreeView:branch:has-siblings:adjoins-item {
border-image: url(":/qss_icons/rc/branch_more.png") 0;
}
QTreeView:branch:!has-children:!has-siblings:adjoins-item {
border-image: url(":/qss_icons/rc/branch_end.png") 0;
}
QTreeView:branch:has-children:!has-siblings:closed, QTreeView:branch:closed:has-children:has-siblings {
border-image: none;
@@ -1900,21 +1885,21 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qheaderview
--------------------------------------------------------------------------- */
QHeaderView {
background-color: #32414B;
border: 0px transparent #32414B;
background-color: #19232D;
border: 0px transparent #19232D;
padding: 0px;
margin: 0px;
border-radius: 0px;
}
QHeaderView:disabled {
background-color: #32414B;
border: 1px transparent #32414B;
background-color: #19232D;
border: 1px transparent #19232D;
padding: 2px;
}
QHeaderView::section {
background-color: #32414B;
background-color: #19232D;
color: #F0F0F0;
padding: 2px;
border-radius: 0px;
@@ -1934,11 +1919,11 @@ QHeaderView::section:checked:disabled {
QHeaderView::section::horizontal {
padding-left: 4px;
padding-right: 4px;
border-left: 1px solid #19232D;
border-left: 1px solid #32414B;
}
QHeaderView::section::horizontal::first, QHeaderView::section::horizontal::only-one {
border-left: 1px solid #32414B;
border-left: 1px solid #19232D;
}
QHeaderView::section::horizontal:disabled {
@@ -1948,7 +1933,7 @@ QHeaderView::section::horizontal:disabled {
QHeaderView::section::vertical {
padding-left: 4px;
padding-right: 4px;
border-top: 1px solid #19232D;
border-top: 1px solid #32414B;
}
QHeaderView::section::vertical::first, QHeaderView::section::vertical::only-one {
@@ -1962,7 +1947,7 @@ QHeaderView::section::vertical:disabled {
QHeaderView::down-arrow {
/* Those settings (border/width/height/background-color) solve bug */
/* transparent arrow background and size */
background-color: #32414B;
background-color: #19232D;
border: none;
height: 12px;
width: 12px;
@@ -1972,7 +1957,7 @@ QHeaderView::down-arrow {
}
QHeaderView::up-arrow {
background-color: #32414B;
background-color: #19232D;
border: none;
height: 12px;
width: 12px;
@@ -2172,3 +2157,132 @@ PlotWidget {
/* Fix cut labels in plots #134 */
padding: 0px;
}
QPushButton#TogglableStatusBarButton {
min-width: 0px;
color: #656565;
border: 1px solid transparent;
background-color: transparent;
padding: 0px 3px 0px 3px;
text-align: center;
}
QPushButton#TogglableStatusBarButton:checked {
color: #ffffff;
}
QPushButton#TogglableStatusBarButton:hover {
border: 1px solid #76797C;
}
QPushButton#RendererStatusBarButton {
min-width: 0px;
color: #656565;
border: 1px solid transparent;
background-color: transparent;
padding: 0px 3px 0px 3px;
text-align: center;
}
QPushButton#RendererStatusBarButton:hover {
border: 1px solid #76797C;
}
QPushButton#RendererStatusBarButton:checked {
color: #e85c00;
}
QPushButton#RendererStatusBarButton:!checked {
color: #00ccdd;
}
QPushButton#buttonRefreshDevices {
min-width: 20px;
min-height: 20px;
max-width: 20px;
max-height: 20px;
padding: 0px 0px;
}
QCheckBox#checkboxPlayer1Connected,
QCheckBox#checkboxPlayer2Connected,
QCheckBox#checkboxPlayer3Connected,
QCheckBox#checkboxPlayer4Connected,
QCheckBox#checkboxPlayer5Connected,
QCheckBox#checkboxPlayer6Connected,
QCheckBox#checkboxPlayer7Connected,
QCheckBox#checkboxPlayer8Connected {
spacing: 0px;
}
QCheckBox#checkboxPlayer1Connected::indicator,
QCheckBox#checkboxPlayer2Connected::indicator,
QCheckBox#checkboxPlayer3Connected::indicator,
QCheckBox#checkboxPlayer4Connected::indicator,
QCheckBox#checkboxPlayer5Connected::indicator,
QCheckBox#checkboxPlayer6Connected::indicator,
QCheckBox#checkboxPlayer7Connected::indicator,
QCheckBox#checkboxPlayer8Connected::indicator {
width: 14px;
height: 14px;
}
QCheckBox#checkboxPlayer1Connected::indicator:checked,
QCheckBox#checkboxPlayer2Connected::indicator:checked,
QCheckBox#checkboxPlayer3Connected::indicator:checked,
QCheckBox#checkboxPlayer4Connected::indicator:checked,
QCheckBox#checkboxPlayer5Connected::indicator:checked,
QCheckBox#checkboxPlayer6Connected::indicator:checked,
QCheckBox#checkboxPlayer7Connected::indicator:checked,
QCheckBox#checkboxPlayer8Connected::indicator:checked,
QGroupBox#groupConnectedController::indicator:checked {
border-radius: 2px;
border: 1px solid #929192;
background: #39ff14;
image: none;
}
QCheckBox#checkboxPlayer1Connected::indicator:unchecked,
QCheckBox#checkboxPlayer2Connected::indicator:unchecked,
QCheckBox#checkboxPlayer3Connected::indicator:unchecked,
QCheckBox#checkboxPlayer4Connected::indicator:unchecked,
QCheckBox#checkboxPlayer5Connected::indicator:unchecked,
QCheckBox#checkboxPlayer6Connected::indicator:unchecked,
QCheckBox#checkboxPlayer7Connected::indicator:unchecked,
QCheckBox#checkboxPlayer8Connected::indicator:unchecked,
QGroupBox#groupConnectedController::indicator:unchecked {
border-radius: 2px;
border: 1px solid #929192;
background: transparent;
image: none;
}
QSpinBox#spinboxLStickRange,
QSpinBox#spinboxRStickRange {
min-width: 38px;
}
QGroupBox#motionGroup::indicator,
QGroupBox#vibrationGroup::indicator {
margin-left: 0px;
}
QGroupBox#motionGroup::title,
QGroupBox#vibrationGroup::title {
spacing: 2px;
padding-left: 1px;
padding-right: 1px;
}
QListWidget#selectorList {
background-color: #0f1922;
}
QSpinBox,
QLineEdit,
QTreeView#hotkey_list,
QScrollArea#scrollArea QTreeView {
background-color: #0f1922;
}

View File

@@ -152,9 +152,11 @@ typedef uint16_t MicroProfileGroupId;
#include <stdint.h>
#include <string.h>
#include <thread>
#include <mutex>
#include <algorithm>
#include <array>
#include <atomic>
#include <mutex>
#include <thread>
#ifndef MICROPROFILE_API
#define MICROPROFILE_API
@@ -605,28 +607,45 @@ struct MicroProfileFrameState
struct MicroProfileThreadLog
{
MicroProfileLogEntry Log[MICROPROFILE_BUFFER_SIZE];
std::array<MicroProfileLogEntry, MICROPROFILE_BUFFER_SIZE> Log{};
std::atomic<uint32_t> nPut;
std::atomic<uint32_t> nGet;
uint32_t nActive;
uint32_t nGpu;
ThreadIdType nThreadId;
std::atomic<uint32_t> nPut{0};
std::atomic<uint32_t> nGet{0};
uint32_t nActive = 0;
uint32_t nGpu = 0;
ThreadIdType nThreadId{};
uint32_t nStack[MICROPROFILE_STACK_MAX];
int64_t nChildTickStack[MICROPROFILE_STACK_MAX];
uint32_t nStackPos;
std::array<uint32_t, MICROPROFILE_STACK_MAX> nStack{};
std::array<int64_t, MICROPROFILE_STACK_MAX> nChildTickStack{};
uint32_t nStackPos = 0;
uint8_t nGroupStackPos[MICROPROFILE_MAX_GROUPS];
int64_t nGroupTicks[MICROPROFILE_MAX_GROUPS];
int64_t nAggregateGroupTicks[MICROPROFILE_MAX_GROUPS];
std::array<uint8_t, MICROPROFILE_MAX_GROUPS> nGroupStackPos{};
std::array<int64_t, MICROPROFILE_MAX_GROUPS> nGroupTicks{};
std::array<int64_t, MICROPROFILE_MAX_GROUPS> nAggregateGroupTicks{};
enum
{
THREAD_MAX_LEN = 64,
};
char ThreadName[64];
int nFreeListNext;
char ThreadName[64]{};
int nFreeListNext = 0;
void Reset() {
Log.fill({});
nPut = 0;
nGet = 0;
nActive = 0;
nGpu = 0;
nThreadId = {};
nStack.fill(0);
nChildTickStack.fill(0);
nStackPos = 0;
nGroupStackPos.fill(0);
nGroupTicks.fill(0);
nAggregateGroupTicks.fill(0);
std::fill(std::begin(ThreadName), std::end(ThreadName), '\0');
nFreeListNext = 0;
}
};
#if MICROPROFILE_GPU_TIMERS_D3D11
@@ -1151,6 +1170,7 @@ MicroProfileThreadLog* MicroProfileCreateThreadLog(const char* pName)
MP_ASSERT(pLog->nPut.load() == 0);
MP_ASSERT(pLog->nGet.load() == 0);
S.nFreeListHead = S.Pool[S.nFreeListHead]->nFreeListNext;
pLog->Reset();
}
else
{
@@ -1158,7 +1178,6 @@ MicroProfileThreadLog* MicroProfileCreateThreadLog(const char* pName)
S.nMemUsage += sizeof(MicroProfileThreadLog);
S.Pool[S.nNumLogs++] = pLog;
}
memset(pLog, 0, sizeof(*pLog));
int len = (int)strlen(pName);
int maxlen = sizeof(pLog->ThreadName)-1;
len = len < maxlen ? len : maxlen;
@@ -1206,8 +1225,8 @@ void MicroProfileOnThreadExit()
{
S.Frames[i].nLogStart[nLogIndex] = 0;
}
memset(pLog->nGroupStackPos, 0, sizeof(pLog->nGroupStackPos));
memset(pLog->nGroupTicks, 0, sizeof(pLog->nGroupTicks));
pLog->nGroupStackPos.fill(0);
pLog->nGroupTicks.fill(0);
}
}

View File

@@ -169,14 +169,13 @@ MICROPROFILEUI_API void MicroProfileCustomGroup(const char* pCustomName, uint32_
MICROPROFILEUI_API void MicroProfileCustomGroupAddTimer(const char* pCustomName, const char* pGroup, const char* pTimer);
#ifdef MICROPROFILEUI_IMPL
#ifdef _WIN32
#define snprintf _snprintf
#endif
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <math.h>
#include <algorithm>
#include <array>
MICROPROFILE_DEFINE(g_MicroProfileDetailed, "MicroProfile", "Detailed View", 0x8888000);
MICROPROFILE_DEFINE(g_MicroProfileDrawGraph, "MicroProfile", "Draw Graph", 0xff44ee00);
@@ -227,10 +226,10 @@ struct SOptionDesc
uint8_t nIndex;
bool bSelected;
};
static uint32_t g_MicroProfileAggregatePresets[] = {0, 10, 20, 30, 60, 120};
static float g_MicroProfileReferenceTimePresets[] = {5.f, 10.f, 15.f,20.f, 33.33f, 66.66f, 100.f, 250.f, 500.f, 1000.f};
static uint32_t g_MicroProfileOpacityPresets[] = {0x40, 0x80, 0xc0, 0xff};
static const char* g_MicroProfilePresetNames[] =
static const std::array<uint32_t, 6> g_MicroProfileAggregatePresets{0, 10, 20, 30, 60, 120};
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};
static const std::array<uint32_t, 4> g_MicroProfileOpacityPresets{0x40, 0x80, 0xc0, 0xff};
static const std::array<const char*, 7> g_MicroProfilePresetNames
{
MICROPROFILE_DEFAULT_PRESET,
"Render",
@@ -243,8 +242,8 @@ static const char* g_MicroProfilePresetNames[] =
enum
{
MICROPROFILE_NUM_REFERENCE_PRESETS = sizeof(g_MicroProfileReferenceTimePresets)/sizeof(g_MicroProfileReferenceTimePresets[0]),
MICROPROFILE_NUM_OPACITY_PRESETS = sizeof(g_MicroProfileOpacityPresets)/sizeof(g_MicroProfileOpacityPresets[0]),
MICROPROFILE_NUM_REFERENCE_PRESETS = g_MicroProfileReferenceTimePresets.size(),
MICROPROFILE_NUM_OPACITY_PRESETS = g_MicroProfileOpacityPresets.size(),
#if MICROPROFILE_CONTEXT_SWITCH_TRACE
MICROPROFILE_OPTION_SIZE = MICROPROFILE_NUM_REFERENCE_PRESETS + MICROPROFILE_NUM_OPACITY_PRESETS * 2 + 2 + 7,
#else
@@ -326,9 +325,9 @@ struct MicroProfileUI
MicroProfileUI g_MicroProfileUI;
#define UI g_MicroProfileUI
static uint32_t g_nMicroProfileBackColors[2] = { 0x474747, 0x313131 };
static const std::array<uint32_t, 2> g_nMicroProfileBackColors{ 0x474747, 0x313131 };
#define MICROPROFILE_NUM_CONTEXT_SWITCH_COLORS 16
static uint32_t g_nMicroProfileContextSwitchThreadColors[MICROPROFILE_NUM_CONTEXT_SWITCH_COLORS] = //palette generated by http://tools.medialab.sciences-po.fr/iwanthue/index.php
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
{
0x63607B,
0x755E2B,
@@ -356,7 +355,7 @@ void MicroProfileInitUI()
{
bInitialized = true;
memset(&g_MicroProfileUI, 0, sizeof(g_MicroProfileUI));
UI.nActiveMenu = (uint32_t)-1;
UI.nActiveMenu = UINT32_MAX;
UI.fDetailedOffsetTarget = UI.fDetailedOffset = 0.f;
UI.fDetailedRangeTarget = UI.fDetailedRange = 50.f;
@@ -368,7 +367,7 @@ void MicroProfileInitUI()
UI.nWidth = 100;
UI.nHeight = 100;
UI.nCustomActive = (uint32_t)-1;
UI.nCustomActive = UINT32_MAX;
UI.nCustomTimerCount = 0;
UI.nCustomCount = 0;
@@ -498,8 +497,8 @@ inline void MicroProfileDrawFloatWindow(uint32_t nX, uint32_t nY, const char** p
{
MicroProfileDrawBox(nX-MICROPROFILE_TEXT_WIDTH, nY, nX, nY + MICROPROFILE_TEXT_WIDTH, pColors[i]|0xff000000);
}
MicroProfileDrawText(nX + 1, nY + 1, (uint32_t)-1, ppStrings[i0], (uint32_t)strlen(ppStrings[i0]));
MicroProfileDrawText(nX + nWidth - nStringLengths[i0+1] * (MICROPROFILE_TEXT_WIDTH+1), nY + 1, (uint32_t)-1, ppStrings[i0+1], (uint32_t)strlen(ppStrings[i0+1]));
MicroProfileDrawText(nX + 1, nY + 1, UINT32_MAX, ppStrings[i0], (uint32_t)strlen(ppStrings[i0]));
MicroProfileDrawText(nX + nWidth - nStringLengths[i0+1] * (MICROPROFILE_TEXT_WIDTH+1), nY + 1, UINT32_MAX, ppStrings[i0+1], (uint32_t)strlen(ppStrings[i0+1]));
nY += (MICROPROFILE_TEXT_HEIGHT+1);
}
}
@@ -522,7 +521,7 @@ inline void MicroProfileDrawTextBox(uint32_t nX, uint32_t nY, const char** ppStr
MicroProfileDrawBox(nX, nY, nX + nWidth, nY + nHeight, 0xff000000);
for(uint32_t i = 0; i < nNumStrings; ++i)
{
MicroProfileDrawText(nX + 1, nY + 1, (uint32_t)-1, ppStrings[i], (uint32_t)strlen(ppStrings[i]));
MicroProfileDrawText(nX + 1, nY + 1, UINT32_MAX, ppStrings[i], (uint32_t)strlen(ppStrings[i]));
nY += (MICROPROFILE_TEXT_HEIGHT+1);
}
}
@@ -781,7 +780,7 @@ inline void MicroProfileDrawDetailedContextSwitchBars(uint32_t nY, uint32_t nThr
{
MicroProfile& S = *MicroProfileGet();
int64_t nTickIn = -1;
uint32_t nThreadBefore = -1;
uint32_t nThreadBefore = UINT32_MAX;
float fToMs = MicroProfileTickToMsMultiplier(MicroProfileTicksPerSecondCpu());
float fMsToScreen = UI.nWidth / UI.fDetailedRange;
float fMouseX = (float)UI.nMouseX;
@@ -949,10 +948,10 @@ inline void MicroProfileDrawDetailedBars(uint32_t nWidth, uint32_t nHeight, int
uint32_t nContextSwitchHoverThreadAfter = S.nContextSwitchHoverThreadAfter;
uint32_t nContextSwitchHoverThreadBefore = S.nContextSwitchHoverThreadBefore;
S.nContextSwitchHoverThread = S.nContextSwitchHoverThreadAfter = S.nContextSwitchHoverThreadBefore = -1;
S.nContextSwitchHoverThread = S.nContextSwitchHoverThreadAfter = S.nContextSwitchHoverThreadBefore = UINT32_MAX;
uint32_t nContextSwitchStart = -1;
uint32_t nContextSwitchEnd = -1;
uint32_t nContextSwitchStart = UINT32_MAX;
uint32_t nContextSwitchEnd = UINT32_MAX;
S.nContextSwitchHoverCpuNext = 0xff;
S.nContextSwitchHoverTickIn = -1;
S.nContextSwitchHoverTickOut = -1;
@@ -1005,9 +1004,10 @@ inline void MicroProfileDrawDetailedBars(uint32_t nWidth, uint32_t nHeight, int
}while(pFrameLogFirst != pFrameFirst);
if(nGet == (uint32_t)-1)
if (nGet == UINT32_MAX) {
continue;
MP_ASSERT(nGet != (uint32_t)-1);
}
MP_ASSERT(nGet != UINT32_MAX);
nPut = pFrameLogLast->nLogStart[i];
@@ -1023,9 +1023,9 @@ inline void MicroProfileDrawDetailedBars(uint32_t nWidth, uint32_t nHeight, int
int64_t nBaseTicks = bGpu ? nBaseTicksGpu : nBaseTicksCpu;
char ThreadName[MicroProfileThreadLog::THREAD_MAX_LEN + 16];
uint64_t nThreadId = pLog->nThreadId;
snprintf(ThreadName, sizeof(ThreadName)-1, "%04llx: %s", nThreadId, &pLog->ThreadName[0] );
snprintf(ThreadName, sizeof(ThreadName)-1, "%04" PRIx64 ": %s", nThreadId, &pLog->ThreadName[0] );
nY += 3;
uint32_t nThreadColor = -1;
uint32_t nThreadColor = UINT32_MAX;
if(pLog->nThreadId == nContextSwitchHoverThreadAfter || pLog->nThreadId == nContextSwitchHoverThreadBefore)
nThreadColor = UI.nHoverColorShared|0x906060;
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
uint32_t nEnd = nRange[j][1];
for(uint32_t k = nStart; k < nEnd; ++k)
{
MicroProfileLogEntry* pEntry = pLog->Log + k;
MicroProfileLogEntry* pEntry = &pLog->Log[k];
int nType = MicroProfileLogType(*pEntry);
if(MP_LOG_ENTER == nType)
{
@@ -1066,7 +1066,7 @@ inline void MicroProfileDrawDetailedBars(uint32_t nWidth, uint32_t nHeight, int
continue;
}
MicroProfileLogEntry* pEntryEnter = pLog->Log + nStack[nStackPos-1];
MicroProfileLogEntry* pEntryEnter = &pLog->Log[nStack[nStackPos-1]];
if(MicroProfileLogTimerIndex(*pEntryEnter) != MicroProfileLogTimerIndex(*pEntry))
{
//uprintf("mismatch %llx %llx\n", pEntryEnter->nToken, pEntry->nToken);
@@ -1126,7 +1126,7 @@ inline void MicroProfileDrawDetailedBars(uint32_t nWidth, uint32_t nHeight, int
uint32_t nIntegerWidth = (uint32_t)(fXEnd - fXStart);
if(nIntegerWidth)
{
if(bHover && UI.nActiveMenu == -1)
if(bHover && UI.nActiveMenu == UINT32_MAX)
{
nHoverToken = MicroProfileLogTimerIndex(*pEntry);
#if MICROPROFILE_DEBUG
@@ -1146,7 +1146,7 @@ inline void MicroProfileDrawDetailedBars(uint32_t nWidth, uint32_t nHeight, int
int nCharacters = (nTextWidth - 2*MICROPROFILE_TEXT_WIDTH) / MICROPROFILE_TEXT_WIDTH;
if(nCharacters>0)
{
MicroProfileDrawText(fXStartText+1, fYStart+1, -1, S.TimerInfo[nTimerIndex].pName, MicroProfileMin<uint32_t>(S.TimerInfo[nTimerIndex].nNameLen, nCharacters));
MicroProfileDrawText(fXStartText + 1, fYStart + 1, UINT32_MAX, S.TimerInfo[nTimerIndex].pName, MicroProfileMin<uint32_t>(S.TimerInfo[nTimerIndex].nNameLen, nCharacters));
}
}
#endif
@@ -1158,7 +1158,7 @@ inline void MicroProfileDrawDetailedBars(uint32_t nWidth, uint32_t nHeight, int
int nLineX = (int)floor(fXAvg+0.5f);
if(nLineX != (int)nLinesDrawn[nStackPos])
{
if(bHover && UI.nActiveMenu == -1)
if(bHover && UI.nActiveMenu == UINT32_MAX)
{
nHoverToken = (uint32_t)MicroProfileLogTimerIndex(*pEntry);
nHoverTime = MicroProfileLogTickDifference(nTickStart, nTickEnd);
@@ -1235,9 +1235,9 @@ inline void MicroProfileDrawDetailedBars(uint32_t nWidth, uint32_t nHeight, int
// nThreadId is 32-bit on Windows
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) );
#else
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) );
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) );
#endif
uint32_t nThreadColor = -1;
uint32_t nThreadColor = UINT32_MAX;
if(nThreadId == nContextSwitchHoverThreadAfter || nThreadId == nContextSwitchHoverThreadBefore)
nThreadColor = UI.nHoverColorShared|0x906060;
MicroProfileDrawDetailedContextSwitchBars(nY+2, nThreadId, nContextSwitchStart, nContextSwitchEnd, nBaseTicksCpu, nBaseY);
@@ -1249,9 +1249,6 @@ inline void MicroProfileDrawDetailedBars(uint32_t nWidth, uint32_t nHeight, int
S.nContextSwitchHoverCpu = S.nContextSwitchHoverCpuNext;
UI.pDisplayMouseOver = pMouseOverNext;
if(!S.nRunning)
@@ -1286,10 +1283,10 @@ inline void MicroProfileDrawDetailedBars(uint32_t nWidth, uint32_t nHeight, int
float fStartTextWidth = (float)((1+MICROPROFILE_TEXT_WIDTH) * nLenStart);
float fStartTextX = fXStart - fStartTextWidth - 2;
MicroProfileDrawBox(fStartTextX, nBaseY, fStartTextX + fStartTextWidth + 2, MICROPROFILE_TEXT_HEIGHT + 2 + nBaseY, 0x33000000, MicroProfileBoxTypeFlat);
MicroProfileDrawText(fStartTextX+1, nBaseY, (uint32_t)-1, sBuffer, nLenStart);
MicroProfileDrawText(fStartTextX+1, nBaseY, UINT32_MAX, sBuffer, nLenStart);
uint32_t nLenEnd = snprintf(sBuffer, sizeof(sBuffer)-1, "%.2fms", fMsEnd);
MicroProfileDrawBox(fXEnd+1, nBaseY, fXEnd+1+(1+MICROPROFILE_TEXT_WIDTH) * nLenEnd + 3, MICROPROFILE_TEXT_HEIGHT + 2 + nBaseY, 0x33000000, MicroProfileBoxTypeFlat);
MicroProfileDrawText(fXEnd+2, nBaseY+1, (uint32_t)-1, sBuffer, nLenEnd);
MicroProfileDrawText(fXEnd+2, nBaseY+1, UINT32_MAX, sBuffer, nLenEnd);
if(UI.nMouseRight)
{
@@ -1316,10 +1313,10 @@ inline void MicroProfileDrawDetailedBars(uint32_t nWidth, uint32_t nHeight, int
float fStartTextWidth = (float)((1+MICROPROFILE_TEXT_WIDTH) * nLenStart);
float fStartTextX = fXStart - fStartTextWidth - 2;
MicroProfileDrawBox(fStartTextX, nBaseY, fStartTextX + fStartTextWidth + 2, MICROPROFILE_TEXT_HEIGHT + 2 + nBaseY, 0x33000000, MicroProfileBoxTypeFlat);
MicroProfileDrawText(fStartTextX+1, nBaseY, (uint32_t)-1, sBuffer, nLenStart);
MicroProfileDrawText(fStartTextX+1, nBaseY, UINT32_MAX, sBuffer, nLenStart);
uint32_t nLenEnd = snprintf(sBuffer, sizeof(sBuffer)-1, "%.2fms", fMsEnd);
MicroProfileDrawBox(fXEnd+1, nBaseY, fXEnd+1+(1+MICROPROFILE_TEXT_WIDTH) * nLenEnd + 3, MICROPROFILE_TEXT_HEIGHT + 2 + nBaseY, 0x33000000, MicroProfileBoxTypeFlat);
MicroProfileDrawText(fXEnd+2, nBaseY+1, (uint32_t)-1, sBuffer, nLenEnd);
MicroProfileDrawText(fXEnd+2, nBaseY+1, UINT32_MAX, sBuffer, nLenEnd);
}
}
}
@@ -1365,7 +1362,7 @@ inline void MicroProfileDrawDetailedFrameHistory(uint32_t nWidth, uint32_t nHeig
fBaseX = fXStart;
uint32_t nColor = MICROPROFILE_FRAME_HISTORY_COLOR_CPU;
if(nIndex == nSelectedFrame)
nColor = (uint32_t)-1;
nColor = UINT32_MAX;
MicroProfileDrawBox(fXStart, nBaseY + fScale * nBarHeight, fXEnd, nBaseY+MICROPROFILE_FRAME_HISTORY_HEIGHT, nColor, MicroProfileBoxTypeBar);
if(pNext->nFrameStartCpu > nCpuStart)
{
@@ -1387,7 +1384,7 @@ inline void MicroProfileDrawDetailedView(uint32_t nWidth, uint32_t nHeight)
uint32_t nBaseY = MICROPROFILE_TEXT_HEIGHT + 1;
int nSelectedFrame = -1;
if(UI.nMouseY > nBaseY && UI.nMouseY <= nBaseY + MICROPROFILE_FRAME_HISTORY_HEIGHT && UI.nActiveMenu == -1)
if(UI.nMouseY > nBaseY && UI.nMouseY <= nBaseY + MICROPROFILE_FRAME_HISTORY_HEIGHT && UI.nActiveMenu == UINT32_MAX)
{
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
if(pName)
{
MicroProfileDrawBox(nX-8, MICROPROFILE_TEXT_HEIGHT + 2, nX + nWidth+5, MICROPROFILE_TEXT_HEIGHT + 2 + (MICROPROFILE_TEXT_HEIGHT+1), 0xff000000|g_nMicroProfileBackColors[1]);
MicroProfileDrawText(nX, MICROPROFILE_TEXT_HEIGHT + 2, (uint32_t)-1, pName, (uint32_t)strlen(pName));
MicroProfileDrawText(nX, MICROPROFILE_TEXT_HEIGHT + 2, UINT32_MAX, pName, (uint32_t)strlen(pName));
}
}
@@ -1440,7 +1437,7 @@ inline void MicroProfileLoopActiveGroupsDraw(int32_t nX, int32_t nY, const char*
uint32_t nCount = 0;
for(uint32_t j = 0; j < MICROPROFILE_MAX_GROUPS; ++j)
{
uint64_t nMask = 1ll << j;
uint64_t nMask = 1ULL << j;
if(nMask & nGroup)
{
nY += MICROPROFILE_TEXT_HEIGHT + 1;
@@ -1521,7 +1518,7 @@ inline void MicroProfileCalcTimers(float* pTimers, float* pAverage, float* pMax,
}
}
}
nMask <<= 1ll;
nMask <<= 1;
}
}
@@ -1543,7 +1540,7 @@ inline void MicroProfileDrawBarArrayCallback(uint32_t nTimer, uint32_t nIdx, uin
snprintf(sBuffer, SBUF_MAX-1, "%5.2f", pTimers[nIdx]);
if (!pTimers2)
MicroProfileDrawBox(nX + nTextWidth, nY, nX + nTextWidth + fWidth * pTimers[nIdx+1], nY + nHeight, UI.nOpacityForeground|S.TimerInfo[nTimer].nColor, MicroProfileBoxTypeBar);
MicroProfileDrawText(nX, nY, (uint32_t)-1, sBuffer, (uint32_t)strlen(sBuffer));
MicroProfileDrawText(nX, nY, UINT32_MAX, sBuffer, (uint32_t)strlen(sBuffer));
}
@@ -1564,7 +1561,7 @@ inline void MicroProfileDrawBarCallCountCallback(uint32_t nTimer, uint32_t nIdx,
MicroProfile& S = *MicroProfileGet();
char sBuffer[SBUF_MAX];
int nLen = snprintf(sBuffer, SBUF_MAX-1, "%5d", S.Frame[nTimer].nCount);//fix
MicroProfileDrawText(nX, nY, (uint32_t)-1, sBuffer, nLen);
MicroProfileDrawText(nX, nY, UINT32_MAX, sBuffer, nLen);
}
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
float fRcpFrames = pArgs->fRcpFrames;
char sBuffer[SBUF_MAX];
int nLen = snprintf(sBuffer, SBUF_MAX-1, "%5.2f", pCounters[nTimer] * fRcpFrames);
MicroProfileDrawText(nX - nLen * (MICROPROFILE_TEXT_WIDTH+1), nY, (uint32_t)-1, sBuffer, nLen);
MicroProfileDrawText(nX - nLen * (MICROPROFILE_TEXT_WIDTH+1), nY, UINT32_MAX, sBuffer, nLen);
}
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,
{
uint64_t* pCounters = (uint64_t*)pExtra;
char sBuffer[SBUF_MAX];
int nLen = snprintf(sBuffer, SBUF_MAX-1, "%5llu", pCounters[nTimer]);
MicroProfileDrawText(nX - nLen * (MICROPROFILE_TEXT_WIDTH+1), nY, (uint32_t)-1, sBuffer, nLen);
int nLen = snprintf(sBuffer, SBUF_MAX-1, "%5" PRIu64, pCounters[nTimer]);
MicroProfileDrawText(nX - nLen * (MICROPROFILE_TEXT_WIDTH+1), nY, UINT32_MAX, sBuffer, nLen);
}
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)
if(bMouseOver)
{
float fXAvg = fMouseXPrc * MICROPROFILE_GRAPH_WIDTH + nX;
MicroProfileDrawLineVertical(fXAvg, nY, nY + MICROPROFILE_GRAPH_HEIGHT, (uint32_t)-1);
MicroProfileDrawLineVertical(fXAvg, nY, nY + MICROPROFILE_GRAPH_HEIGHT, UINT32_MAX);
}
@@ -1706,7 +1703,7 @@ bool MicroProfileDrawGraph(uint32_t nScreenWidth, uint32_t nScreenHeight)
char buf[32];
int nLen = snprintf(buf, sizeof(buf)-1, "%5.2fms", S.fReferenceTime);
MicroProfileDrawText(nX+1, fY1 - (2+MICROPROFILE_TEXT_HEIGHT), (uint32_t)-1, buf, nLen);
MicroProfileDrawText(nX+1, fY1 - (2+MICROPROFILE_TEXT_HEIGHT), UINT32_MAX, buf, nLen);
}
@@ -1782,7 +1779,7 @@ void MicroProfileDumpTimers()
for(uint32_t j = 0; j < MICROPROFILE_MAX_GROUPS; ++j)
{
uint64_t nMask = 1ll << j;
uint64_t nMask = 1ULL << j;
if(nMask & nActiveGroup)
{
MICROPROFILE_PRINTF("%s\n", S.GroupInfo[j].pName);
@@ -1823,7 +1820,7 @@ inline void MicroProfileDrawBarView(uint32_t nScreenWidth, uint32_t nScreenHeigh
uint32_t nNumGroups = 0;
for(uint32_t j = 0; j < MICROPROFILE_MAX_GROUPS; ++j)
{
if(nActiveGroup & (1ll << j))
if(nActiveGroup & (1ULL << j))
{
nNumTimers += S.GroupInfo[j].nNumTimers;
nNumGroups += 1;
@@ -1878,7 +1875,7 @@ inline void MicroProfileDrawBarView(uint32_t nScreenWidth, uint32_t nScreenHeigh
for(uint32_t i = 0; i < nNumTimers+nNumGroups+1; ++i)
{
uint32_t nY0 = nY + i * (nHeight + 1);
bool bInside = (UI.nActiveMenu == -1) && ((UI.nMouseY >= nY0) && (UI.nMouseY < (nY0 + nHeight + 1)));
bool bInside = (UI.nActiveMenu == UINT32_MAX) && ((UI.nMouseY >= nY0) && (UI.nMouseY < (nY0 + nHeight + 1)));
MicroProfileDrawBox(nX, nY0, nWidth+nX, nY0 + (nHeight+1)+1, UI.nOpacityBackground | (g_nMicroProfileBackColors[nColorIndex++ & 1] + ((bInside) ? 0x002c2c2c : 0)));
}
nX += 10;
@@ -1927,22 +1924,22 @@ inline void MicroProfileDrawBarView(uint32_t nScreenWidth, uint32_t nScreenHeigh
nY = nHeight + 3 - UI.nOffsetY;
for(uint32_t i = 0; i < nNumTimers+nNumGroups+1; ++i)
{
uint32_t nY0 = nY + i * (nHeight + 1);
bool bInside = (UI.nActiveMenu == -1) && ((UI.nMouseY >= nY0) && (UI.nMouseY < (nY0 + nHeight + 1)));
const uint32_t nY0 = nY + i * (nHeight + 1);
const bool bInside = (UI.nActiveMenu == UINT32_MAX) && ((UI.nMouseY >= nY0) && (UI.nMouseY < (nY0 + nHeight + 1)));
MicroProfileDrawBox(nX, nY0, nTimerWidth, nY0 + (nHeight+1)+1, 0xff0000000 | (g_nMicroProfileBackColors[nColorIndex++ & 1] + ((bInside) ? 0x002c2c2c : 0)));
}
nX += MicroProfileDrawBarLegend(nX, nY, nTotalHeight, nTimerWidth-5) + 1;
for(uint32_t j = 0; j < MICROPROFILE_MAX_GROUPS; ++j)
{
if(nActiveGroup & (1ll << j))
if(nActiveGroup & (1ULL << j))
{
MicroProfileDrawText(nX, nY + (1+nHeight) * nLegendOffset, (uint32_t)-1, S.GroupInfo[j].pName, S.GroupInfo[j].nNameLen);
MicroProfileDrawText(nX, nY + (1+nHeight) * nLegendOffset, UINT32_MAX, S.GroupInfo[j].pName, S.GroupInfo[j].nNameLen);
nLegendOffset += S.GroupInfo[j].nNumTimers+1;
}
}
MicroProfileDrawHeader(nX, nTimerWidth-5, "Group");
MicroProfileDrawTextRight(nTimerWidth-3, MICROPROFILE_TEXT_HEIGHT + 2, (uint32_t)-1, "Timer", 5);
MicroProfileDrawTextRight(nTimerWidth-3, MICROPROFILE_TEXT_HEIGHT + 2, UINT32_MAX, "Timer", 5);
MicroProfileDrawLineVertical(nTimerWidth, 0, nTotalHeight+nY, UI.nOpacityBackground|g_nMicroProfileBackColors[0]|g_nMicroProfileBackColors[1]);
MicroProfileDrawLineHorizontal(0, nWidth, 2*MICROPROFILE_TEXT_HEIGHT + 3, UI.nOpacityBackground|g_nMicroProfileBackColors[0]|g_nMicroProfileBackColors[1]);
}
@@ -2003,7 +2000,7 @@ inline const char* MicroProfileUIMenuGroups(int nIndex, bool* bSelected)
}
else
{
*bSelected = 0 != (S.nActiveGroupWanted & (1ll << Item.nIndex));
*bSelected = 0 != (S.nActiveGroupWanted & (1ULL << Item.nIndex));
snprintf(buffer, sizeof(buffer)-1, " %s", Item.pName);
}
return buffer;
@@ -2015,16 +2012,18 @@ inline const char* MicroProfileUIMenuGroups(int nIndex, bool* bSelected)
inline const char* MicroProfileUIMenuAggregate(int nIndex, bool* bSelected)
{
MicroProfile& S = *MicroProfileGet();
if(nIndex < sizeof(g_MicroProfileAggregatePresets)/sizeof(g_MicroProfileAggregatePresets[0]))
if(static_cast<uint32_t>(nIndex) < g_MicroProfileAggregatePresets.size())
{
int val = g_MicroProfileAggregatePresets[nIndex];
*bSelected = (int)S.nAggregateFlip == val;
if(0 == val)
uint32_t val = g_MicroProfileAggregatePresets[nIndex];
*bSelected = S.nAggregateFlip == val;
if (0 == val)
{
return "Infinite";
}
else
{
static char buf[128];
snprintf(buf, sizeof(buf)-1, "%7d", val);
snprintf(buf, sizeof(buf)-1, "%7u", val);
return buf;
}
}
@@ -2098,11 +2097,13 @@ inline const char* MicroProfileUIMenuPreset(int nIndex, bool* bSelected)
{
static char buf[128];
*bSelected = false;
int nNumPresets = sizeof(g_MicroProfilePresetNames) / sizeof(g_MicroProfilePresetNames[0]);
int nNumPresets = static_cast<int>(g_MicroProfilePresetNames.size());
int nIndexSave = nIndex - nNumPresets - 1;
if(nIndex == nNumPresets)
if (nIndex == nNumPresets)
{
return "--";
else if(nIndexSave >=0 && nIndexSave <nNumPresets)
}
else if(nIndexSave >=0 && nIndexSave < nNumPresets)
{
snprintf(buf, sizeof(buf)-1, "Save '%s'", g_MicroProfilePresetNames[nIndexSave]);
return buf;
@@ -2120,13 +2121,13 @@ inline const char* MicroProfileUIMenuPreset(int nIndex, bool* bSelected)
inline const char* MicroProfileUIMenuCustom(int nIndex, bool* bSelected)
{
if((uint32_t)-1 == UI.nCustomActive)
if(UINT32_MAX == UI.nCustomActive)
{
*bSelected = nIndex == 0;
}
else
{
*bSelected = nIndex-2 == UI.nCustomActive;
*bSelected = nIndex-2 == static_cast<int>(UI.nCustomActive);
}
switch(nIndex)
{
@@ -2202,7 +2203,7 @@ inline void MicroProfileUIClickGroups(int nIndex)
else
{
MP_ASSERT(Item.nIndex < S.nGroupCount);
S.nActiveGroupWanted ^= (1ll << Item.nIndex);
S.nActiveGroupWanted ^= (1ULL << Item.nIndex);
}
}
}
@@ -2273,7 +2274,7 @@ inline void MicroProfileUIClickOptions(int nIndex)
inline void MicroProfileUIClickPreset(int nIndex)
{
int nNumPresets = sizeof(g_MicroProfilePresetNames) / sizeof(g_MicroProfilePresetNames[0]);
int nNumPresets = static_cast<int>(g_MicroProfilePresetNames.size());
int nIndexSave = nIndex - nNumPresets - 1;
if(nIndexSave >= 0 && nIndexSave < nNumPresets)
{
@@ -2310,7 +2311,7 @@ inline void MicroProfileDrawMenu(uint32_t nWidth, uint32_t nHeight)
uint32_t nX = 0;
uint32_t nY = 0;
bool bMouseOver = UI.nMouseY < MICROPROFILE_TEXT_HEIGHT + 1;
#define SBUF_SIZE 256
char buffer[256];
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)
uint32_t nNumMenuItems = 0;
int nLen = snprintf(buffer, 127, "MicroProfile");
MicroProfileDrawText(nX, nY, (uint32_t)-1, buffer, nLen);
MicroProfileDrawText(nX, nY, UINT32_MAX, buffer, nLen);
nX += (sizeof("MicroProfile")+2) * (MICROPROFILE_TEXT_WIDTH+1);
pMenuText[nNumMenuItems++] = "Mode";
pMenuText[nNumMenuItems++] = "Groups";
@@ -2409,7 +2410,7 @@ inline void MicroProfileDrawMenu(uint32_t nWidth, uint32_t nHeight)
};
uint32_t nSelectMenu = (uint32_t)-1;
uint32_t nSelectMenu = UINT32_MAX;
for(uint32_t i = 0; i < nNumMenuItems; ++i)
{
nMenuX[i] = nX;
@@ -2419,17 +2420,17 @@ inline void MicroProfileDrawMenu(uint32_t nWidth, uint32_t nHeight)
{
MicroProfileDrawBox(nX-1, nY, nX + nLen * (MICROPROFILE_TEXT_WIDTH+1), nY +(MICROPROFILE_TEXT_HEIGHT+1)+1, 0xff888888);
nSelectMenu = i;
if((UI.nMouseLeft || UI.nMouseRight) && i == (int)nPauseIndex)
if((UI.nMouseLeft || UI.nMouseRight) && i == (uint32_t)nPauseIndex)
{
S.nToggleRunning = 1;
}
}
MicroProfileDrawText(nX, nY, (uint32_t)-1, pMenuText[i], (uint32_t)strlen(pMenuText[i]));
MicroProfileDrawText(nX, nY, UINT32_MAX, pMenuText[i], (uint32_t)strlen(pMenuText[i]));
nX += (nLen+1) * (MICROPROFILE_TEXT_WIDTH+1);
}
uint32_t nMenu = nSelectMenu != (uint32_t)-1 ? nSelectMenu : UI.nActiveMenu;
uint32_t nMenu = nSelectMenu != UINT32_MAX ? nSelectMenu : UI.nActiveMenu;
UI.nActiveMenu = nMenu;
if((uint32_t)-1 != nMenu)
if(UINT32_MAX != nMenu)
{
nX = nMenuX[nMenu];
nY += MICROPROFILE_TEXT_HEIGHT+1;
@@ -2450,9 +2451,9 @@ inline void MicroProfileDrawMenu(uint32_t nWidth, uint32_t nHeight)
{
UI.nActiveMenu = nMenu;
}
else if(nSelectMenu == (uint32_t)-1)
else if(nSelectMenu == UINT32_MAX)
{
UI.nActiveMenu = (uint32_t)-1;
UI.nActiveMenu = UINT32_MAX;
}
MicroProfileDrawBox(nX, nY, nX + nWidth, nY + nHeight, 0xff000000|g_nMicroProfileBackColors[1]);
for(int i = 0; i < nNumLines; ++i)
@@ -2461,7 +2462,6 @@ inline void MicroProfileDrawMenu(uint32_t nWidth, uint32_t nHeight)
const char* pString = CB(i, &bSelected);
if(UI.nMouseY >= nY && UI.nMouseY < nY + MICROPROFILE_TEXT_HEIGHT + 1)
{
bMouseOver = true;
if(UI.nMouseLeft || UI.nMouseRight)
{
CBClick[nMenu](i);
@@ -2469,7 +2469,7 @@ inline void MicroProfileDrawMenu(uint32_t nWidth, uint32_t nHeight)
MicroProfileDrawBox(nX, nY, nX + nWidth, nY + MICROPROFILE_TEXT_HEIGHT + 1, 0xff888888);
}
int nLen = snprintf(buffer, SBUF_SIZE-1, "%c %s", bSelected ? '*' : ' ' ,pString);
MicroProfileDrawText(nX, nY, (uint32_t)-1, buffer, nLen);
MicroProfileDrawText(nX, nY, UINT32_MAX, buffer, nLen);
nY += MICROPROFILE_TEXT_HEIGHT+1;
}
}
@@ -2484,7 +2484,7 @@ inline void MicroProfileDrawMenu(uint32_t nWidth, uint32_t nHeight)
float fMaxMs = fToMs * S.nFlipMaxDisplay;
int nLen = snprintf(FrameTimeMessage, sizeof(FrameTimeMessage)-1, "Time[%6.2f] Avg[%6.2f] Max[%6.2f]", fMs, fAverageMs, fMaxMs);
pMenuText[nNumMenuItems++] = &FrameTimeMessage[0];
MicroProfileDrawText(nWidth - nLen * (MICROPROFILE_TEXT_WIDTH+1), 0, -1, FrameTimeMessage, nLen);
MicroProfileDrawText(nWidth - nLen * (MICROPROFILE_TEXT_WIDTH+1), 0, UINT32_MAX, FrameTimeMessage, nLen);
}
}
@@ -2538,7 +2538,7 @@ inline void MicroProfileMoveGraph()
inline void MicroProfileDrawCustom(uint32_t nWidth, uint32_t nHeight)
{
if((uint32_t)-1 != UI.nCustomActive)
if(UINT32_MAX != UI.nCustomActive)
{
MicroProfile& S = *MicroProfileGet();
MP_ASSERT(UI.nCustomActive < MICROPROFILE_CUSTOM_MAX);
@@ -2571,8 +2571,8 @@ inline void MicroProfileDrawCustom(uint32_t nWidth, uint32_t nHeight)
pColors[i] = S.TimerInfo[nTimerIndex].nColor;
}
MicroProfileDrawText(MICROPROFILE_CUSTOM_PADDING + 3*MICROPROFILE_TEXT_WIDTH, nOffsetY, (uint32_t)-1, "Avg", sizeof("Avg")-1);
MicroProfileDrawText(MICROPROFILE_CUSTOM_PADDING + 13*MICROPROFILE_TEXT_WIDTH, nOffsetY, (uint32_t)-1, "Max", sizeof("Max")-1);
MicroProfileDrawText(MICROPROFILE_CUSTOM_PADDING + 3*MICROPROFILE_TEXT_WIDTH, nOffsetY, UINT32_MAX, "Avg", sizeof("Avg")-1);
MicroProfileDrawText(MICROPROFILE_CUSTOM_PADDING + 13*MICROPROFILE_TEXT_WIDTH, nOffsetY, UINT32_MAX, "Max", sizeof("Max")-1);
for(uint32_t i = 0; i < nCount; ++i)
{
nOffsetY += (1+MICROPROFILE_TEXT_HEIGHT);
@@ -2582,10 +2582,10 @@ inline void MicroProfileDrawCustom(uint32_t nWidth, uint32_t nHeight)
int nSize;
uint32_t nOffsetX = MICROPROFILE_CUSTOM_PADDING;
nSize = snprintf(Buffer, sizeof(Buffer)-1, "%6.2f", pTimeAvg[i]);
MicroProfileDrawText(nOffsetX, nOffsetY, (uint32_t)-1, Buffer, nSize);
MicroProfileDrawText(nOffsetX, nOffsetY, UINT32_MAX, Buffer, nSize);
nOffsetX += (nSize+2) * (MICROPROFILE_TEXT_WIDTH+1);
nSize = snprintf(Buffer, sizeof(Buffer)-1, "%6.2f", pTimeMax[i]);
MicroProfileDrawText(nOffsetX, nOffsetY, (uint32_t)-1, Buffer, nSize);
MicroProfileDrawText(nOffsetX, nOffsetY, UINT32_MAX, Buffer, nSize);
nOffsetX += (nSize+2) * (MICROPROFILE_TEXT_WIDTH+1);
nSize = snprintf(Buffer, sizeof(Buffer)-1, "%s:%s", S.GroupInfo[nGroupIndex].pName, pTimerInfo->pName);
MicroProfileDrawText(nOffsetX, nOffsetY, pTimerInfo->nColor, Buffer, nSize);
@@ -2599,9 +2599,9 @@ inline void MicroProfileDrawCustom(uint32_t nWidth, uint32_t nHeight)
nOffsetY = nOffsetYBase;
float* pMs = pCustom->nFlags & MICROPROFILE_CUSTOM_BAR_SOURCE_MAX ? pTimeMax : pTimeAvg;
const char* pString = pCustom->nFlags & MICROPROFILE_CUSTOM_BAR_SOURCE_MAX ? "Max" : "Avg";
MicroProfileDrawText(nMaxOffsetX, nOffsetY, (uint32_t)-1, pString, static_cast<uint32_t>(strlen(pString)));
MicroProfileDrawText(nMaxOffsetX, nOffsetY, UINT32_MAX, pString, static_cast<uint32_t>(strlen(pString)));
int nSize = snprintf(Buffer, sizeof(Buffer)-1, "%6.2fms", fReference);
MicroProfileDrawText(nReducedWidth - (1+nSize) * (MICROPROFILE_TEXT_WIDTH+1), nOffsetY, (uint32_t)-1, Buffer, nSize);
MicroProfileDrawText(nReducedWidth - (1+nSize) * (MICROPROFILE_TEXT_WIDTH+1), nOffsetY, UINT32_MAX, Buffer, nSize);
for(uint32_t i = 0; i < nCount; ++i)
{
nOffsetY += (1+MICROPROFILE_TEXT_HEIGHT);
@@ -2613,9 +2613,9 @@ inline void MicroProfileDrawCustom(uint32_t nWidth, uint32_t nHeight)
{
nOffsetY += 2*(1+MICROPROFILE_TEXT_HEIGHT);
const char* pString = pCustom->nFlags & MICROPROFILE_CUSTOM_STACK_SOURCE_MAX ? "Max" : "Avg";
MicroProfileDrawText(MICROPROFILE_CUSTOM_PADDING, nOffsetY, (uint32_t)-1, pString, static_cast<uint32_t>(strlen(pString)));
MicroProfileDrawText(MICROPROFILE_CUSTOM_PADDING, nOffsetY, UINT32_MAX, pString, static_cast<uint32_t>(strlen(pString)));
int nSize = snprintf(Buffer, sizeof(Buffer)-1, "%6.2fms", fReference);
MicroProfileDrawText(nReducedWidth - (1+nSize) * (MICROPROFILE_TEXT_WIDTH+1), nOffsetY, (uint32_t)-1, Buffer, nSize);
MicroProfileDrawText(nReducedWidth - (1+nSize) * (MICROPROFILE_TEXT_WIDTH+1), nOffsetY, UINT32_MAX, Buffer, nSize);
nOffsetY += (1+MICROPROFILE_TEXT_HEIGHT);
float fPosX = MICROPROFILE_CUSTOM_PADDING;
float* pMs = pCustom->nFlags & MICROPROFILE_CUSTOM_STACK_SOURCE_MAX ? pTimeMax : pTimeAvg;
@@ -2668,7 +2668,7 @@ inline void MicroProfileDraw(uint32_t nWidth, uint32_t nHeight)
UI.nHoverTime = 0;
UI.nHoverFrame = -1;
if(S.nDisplay != MP_DRAW_DETAILED)
S.nContextSwitchHoverThread = S.nContextSwitchHoverThreadAfter = S.nContextSwitchHoverThreadBefore = -1;
S.nContextSwitchHoverThread = S.nContextSwitchHoverThreadAfter = S.nContextSwitchHoverThreadBefore = UINT32_MAX;
MicroProfileMoveGraph();
@@ -2798,13 +2798,13 @@ inline void MicroProfileDraw(uint32_t nWidth, uint32_t nHeight)
if(UI.nActiveMenu == -1 && !bMouseOverGraph)
if(UI.nActiveMenu == UINT32_MAX && !bMouseOverGraph)
{
if(UI.nHoverToken != MICROPROFILE_INVALID_TOKEN)
{
MicroProfileDrawFloatTooltip(UI.nMouseX, UI.nMouseY, UI.nHoverToken, UI.nHoverTime);
}
else if(S.nContextSwitchHoverThreadAfter != -1 && S.nContextSwitchHoverThreadBefore != -1)
else if(S.nContextSwitchHoverThreadAfter != UINT32_MAX && S.nContextSwitchHoverThreadBefore != UINT32_MAX)
{
float fToMs = MicroProfileTickToMsMultiplier(MicroProfileTicksPerSecondCpu());
MicroProfileStringArray ToolTip;
@@ -2820,7 +2820,7 @@ inline void MicroProfileDraw(uint32_t nWidth, uint32_t nHeight)
MicroProfileStringArrayFormat(&ToolTip, "%6.2fms", fToMs * nDifference );
MicroProfileStringArrayAddLiteral(&ToolTip, "CPU");
MicroProfileStringArrayFormat(&ToolTip, "%d", S.nContextSwitchHoverCpu);
MicroProfileDrawFloatWindow(UI.nMouseX, UI.nMouseY+20, &ToolTip.ppStrings[0], ToolTip.nNumStrings, -1);
MicroProfileDrawFloatWindow(UI.nMouseX, UI.nMouseY+20, &ToolTip.ppStrings[0], ToolTip.nNumStrings, UINT32_MAX);
}
@@ -2858,7 +2858,7 @@ inline void MicroProfileDraw(uint32_t nWidth, uint32_t nHeight)
}
}
#endif
MicroProfileDrawFloatWindow(UI.nMouseX, UI.nMouseY+20, &ToolTip.ppStrings[0], ToolTip.nNumStrings, -1);
MicroProfileDrawFloatWindow(UI.nMouseX, UI.nMouseY+20, &ToolTip.ppStrings[0], ToolTip.nNumStrings, UINT32_MAX);
}
if(UI.nMouseLeft)
{
@@ -2883,7 +2883,7 @@ inline void MicroProfileDraw(uint32_t nWidth, uint32_t nHeight)
#endif
m.unlock();
}
else if(UI.nCustomActive != (uint32_t)-1)
else if(UI.nCustomActive != UINT32_MAX)
{
std::recursive_mutex& m = MicroProfileGetMutex();
m.lock();
@@ -3179,7 +3179,7 @@ void MicroProfileLoadPreset(const char* pSuffix)
{
if(0 == MP_STRCASECMP(pGroupName, S.GroupInfo[j].pName))
{
S.nActiveGroupWanted |= (1ll << j);
S.nActiveGroupWanted |= (1ULL << j);
}
}
}
@@ -3212,7 +3212,7 @@ void MicroProfileLoadPreset(const char* pSuffix)
uint64_t nGroupIndex = S.TimerInfo[j].nGroupIndex;
if(0 == MP_STRCASECMP(pGraphName, S.TimerInfo[j].pName) && 0 == MP_STRCASECMP(pGraphGroupName, S.GroupInfo[nGroupIndex].pName))
{
MicroProfileToken nToken = MicroProfileMakeToken(1ll << nGroupIndex, (uint16_t)j);
MicroProfileToken nToken = MicroProfileMakeToken(1ULL << nGroupIndex, (uint16_t)j);
S.Graph[i].nToken = nToken; // note: group index is stored here but is checked without in MicroProfileToggleGraph()!
S.TimerInfo[j].bGraph = true;
if(nToken != nPrevToken)
@@ -3235,7 +3235,7 @@ inline uint32_t MicroProfileCustomGroupFind(const char* pCustomName)
return i;
}
}
return (uint32_t)-1;
return UINT32_MAX;
}
inline uint32_t MicroProfileCustomGroup(const char* pCustomName)
@@ -3251,7 +3251,7 @@ inline uint32_t MicroProfileCustomGroup(const char* pCustomName)
uint32_t nIndex = UI.nCustomCount;
UI.nCustomCount++;
memset(&UI.Custom[nIndex], 0, sizeof(UI.Custom[nIndex]));
uint32_t nLen = (uint32_t)strlen(pCustomName);
size_t nLen = strlen(pCustomName);
if(nLen > MICROPROFILE_NAME_MAX_LEN-1)
nLen = MICROPROFILE_NAME_MAX_LEN-1;
memcpy(&UI.Custom[nIndex].pName[0], pCustomName, nLen);
@@ -3309,7 +3309,7 @@ inline void MicroProfileCustomGroupEnable(uint32_t nIndex)
void MicroProfileCustomGroupToggle(const char* pCustomName)
{
uint32_t nIndex = MicroProfileCustomGroupFind(pCustomName);
if(nIndex == (uint32_t)-1 || nIndex == UI.nCustomActive)
if(nIndex == UINT32_MAX || nIndex == UI.nCustomActive)
{
MicroProfileCustomGroupDisable();
}
@@ -3328,13 +3328,13 @@ void MicroProfileCustomGroupDisable()
{
MicroProfile& S = *MicroProfileGet();
S.nForceGroupUI = 0;
UI.nCustomActive = (uint32_t)-1;
UI.nCustomActive = UINT32_MAX;
}
void MicroProfileCustomGroupAddTimer(const char* pCustomName, const char* pGroup, const char* pTimer)
{
uint32_t nIndex = MicroProfileCustomGroupFind(pCustomName);
if((uint32_t)-1 == nIndex)
if(UINT32_MAX == nIndex)
{
return;
}
@@ -3344,7 +3344,7 @@ void MicroProfileCustomGroupAddTimer(const char* pCustomName, const char* pGroup
MP_ASSERT(nToken != MICROPROFILE_INVALID_TOKEN); //Timer must be registered first.
UI.Custom[nIndex].pTimers[nTimerIndex] = nToken;
uint16_t nGroup = MicroProfileGetGroupIndex(nToken);
UI.Custom[nIndex].nGroupMask |= (1ll << nGroup);
UI.Custom[nIndex].nGroupMask |= (1ULL << nGroup);
UI.Custom[nIndex].nNumTimers++;
}

View File

@@ -172,7 +172,6 @@ add_library(common STATIC
virtual_buffer.h
wall_clock.cpp
wall_clock.h
web_result.h
zstd_compression.cpp
zstd_compression.h
)

View File

@@ -10,7 +10,7 @@
#include "common/swap.h"
#include "common/vector_math.h"
namespace Color {
namespace Common::Color {
/// Convert a 1-bit color component to 8 bit
[[nodiscard]] constexpr u8 Convert1To8(u8 value) {
@@ -268,4 +268,4 @@ inline void EncodeX24S8(u8 stencil, u8* bytes) {
bytes[3] = stencil;
}
} // namespace Color
} // namespace Common::Color

View File

@@ -19,7 +19,7 @@ public:
explicit ParamPackage(const std::string& serialized);
ParamPackage(std::initializer_list<DataType::value_type> list);
ParamPackage(const ParamPackage& other) = default;
ParamPackage(ParamPackage&& other) = default;
ParamPackage(ParamPackage&& other) noexcept = default;
ParamPackage& operator=(const ParamPackage& other) = default;
ParamPackage& operator=(ParamPackage&& other) = default;

View File

@@ -143,7 +143,7 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable&
config.wall_clock_cntpct = uses_wall_clock;
// Safe optimizations
if (Settings::values.cpu_accuracy != Settings::CPUAccuracy::Accurate) {
if (Settings::values.cpu_accuracy == Settings::CPUAccuracy::DebugMode) {
if (!Settings::values.cpuopt_page_tables) {
config.page_table = nullptr;
}
@@ -170,6 +170,17 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable&
}
}
// Unsafe optimizations
if (Settings::values.cpu_accuracy == Settings::CPUAccuracy::Unsafe) {
config.unsafe_optimizations = true;
if (Settings::values.cpuopt_unsafe_unfuse_fma) {
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA;
}
if (Settings::values.cpuopt_unsafe_reduce_fp_error) {
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_ReducedErrorFP;
}
}
return std::make_unique<Dynarmic::A32::Jit>(config);
}

View File

@@ -195,7 +195,7 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable&
config.wall_clock_cntpct = uses_wall_clock;
// Safe optimizations
if (Settings::values.cpu_accuracy != Settings::CPUAccuracy::Accurate) {
if (Settings::values.cpu_accuracy == Settings::CPUAccuracy::DebugMode) {
if (!Settings::values.cpuopt_page_tables) {
config.page_table = nullptr;
}
@@ -222,6 +222,17 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable&
}
}
// Unsafe optimizations
if (Settings::values.cpu_accuracy == Settings::CPUAccuracy::Unsafe) {
config.unsafe_optimizations = true;
if (Settings::values.cpuopt_unsafe_unfuse_fma) {
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA;
}
if (Settings::values.cpuopt_unsafe_reduce_fp_error) {
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_ReducedErrorFP;
}
}
return std::make_shared<Dynarmic::A64::Jit>(config);
}

View File

@@ -7,14 +7,14 @@
#include <string>
#include <tuple>
#include "common/assert.h"
#include "common/microprofile.h"
#include "core/core_timing.h"
#include "core/core_timing_util.h"
#include "core/hardware_properties.h"
namespace Core::Timing {
constexpr u64 MAX_SLICE_LENGTH = 4000;
constexpr s64 MAX_SLICE_LENGTH = 4000;
std::shared_ptr<EventType> CreateEvent(std::string name, TimedCallback&& callback) {
return std::make_shared<EventType>(std::move(callback), std::move(name));
@@ -37,10 +37,8 @@ struct CoreTiming::Event {
}
};
CoreTiming::CoreTiming() {
clock =
Common::CreateBestMatchingClock(Core::Hardware::BASE_CLOCK_RATE, Core::Hardware::CNTFREQ);
}
CoreTiming::CoreTiming()
: clock{Common::CreateBestMatchingClock(Hardware::BASE_CLOCK_RATE, Hardware::CNTFREQ)} {}
CoreTiming::~CoreTiming() = default;
@@ -136,7 +134,7 @@ void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type,
void CoreTiming::AddTicks(u64 ticks) {
this->ticks += ticks;
downcount -= ticks;
downcount -= static_cast<s64>(ticks);
}
void CoreTiming::Idle() {

View File

@@ -8,6 +8,7 @@
#include <limits>
#include "common/logging/log.h"
#include "common/uint128.h"
#include "core/hardware_properties.h"
namespace Core::Timing {

View File

@@ -6,7 +6,6 @@
#include <chrono>
#include "common/common_types.h"
#include "core/hardware_properties.h"
namespace Core::Timing {

View File

@@ -36,6 +36,7 @@
#include "core/settings.h"
namespace Core::Crypto {
namespace {
constexpr u64 CURRENT_CRYPTO_REVISION = 0x5;
constexpr u64 FULL_TICKET_SIZE = 0x400;
@@ -49,7 +50,72 @@ constexpr std::array eticket_source_hashes{
};
// clang-format on
const std::map<std::pair<S128KeyType, u64>, std::string> KEYS_VARIABLE_LENGTH{
constexpr std::array<std::pair<std::string_view, KeyIndex<S128KeyType>>, 30> s128_file_id{{
{"eticket_rsa_kek", {S128KeyType::ETicketRSAKek, 0, 0}},
{"eticket_rsa_kek_source",
{S128KeyType::Source, static_cast<u64>(SourceKeyType::ETicketKek), 0}},
{"eticket_rsa_kekek_source",
{S128KeyType::Source, static_cast<u64>(SourceKeyType::ETicketKekek), 0}},
{"rsa_kek_mask_0", {S128KeyType::RSAKek, static_cast<u64>(RSAKekType::Mask0), 0}},
{"rsa_kek_seed_3", {S128KeyType::RSAKek, static_cast<u64>(RSAKekType::Seed3), 0}},
{"rsa_oaep_kek_generation_source",
{S128KeyType::Source, static_cast<u64>(SourceKeyType::RSAOaepKekGeneration), 0}},
{"sd_card_kek_source", {S128KeyType::Source, static_cast<u64>(SourceKeyType::SDKek), 0}},
{"aes_kek_generation_source",
{S128KeyType::Source, static_cast<u64>(SourceKeyType::AESKekGeneration), 0}},
{"aes_key_generation_source",
{S128KeyType::Source, static_cast<u64>(SourceKeyType::AESKeyGeneration), 0}},
{"package2_key_source", {S128KeyType::Source, static_cast<u64>(SourceKeyType::Package2), 0}},
{"master_key_source", {S128KeyType::Source, static_cast<u64>(SourceKeyType::Master), 0}},
{"header_kek_source", {S128KeyType::Source, static_cast<u64>(SourceKeyType::HeaderKek), 0}},
{"key_area_key_application_source",
{S128KeyType::Source, static_cast<u64>(SourceKeyType::KeyAreaKey),
static_cast<u64>(KeyAreaKeyType::Application)}},
{"key_area_key_ocean_source",
{S128KeyType::Source, static_cast<u64>(SourceKeyType::KeyAreaKey),
static_cast<u64>(KeyAreaKeyType::Ocean)}},
{"key_area_key_system_source",
{S128KeyType::Source, static_cast<u64>(SourceKeyType::KeyAreaKey),
static_cast<u64>(KeyAreaKeyType::System)}},
{"titlekek_source", {S128KeyType::Source, static_cast<u64>(SourceKeyType::Titlekek), 0}},
{"keyblob_mac_key_source",
{S128KeyType::Source, static_cast<u64>(SourceKeyType::KeyblobMAC), 0}},
{"tsec_key", {S128KeyType::TSEC, 0, 0}},
{"secure_boot_key", {S128KeyType::SecureBoot, 0, 0}},
{"sd_seed", {S128KeyType::SDSeed, 0, 0}},
{"bis_key_0_crypt", {S128KeyType::BIS, 0, static_cast<u64>(BISKeyType::Crypto)}},
{"bis_key_0_tweak", {S128KeyType::BIS, 0, static_cast<u64>(BISKeyType::Tweak)}},
{"bis_key_1_crypt", {S128KeyType::BIS, 1, static_cast<u64>(BISKeyType::Crypto)}},
{"bis_key_1_tweak", {S128KeyType::BIS, 1, static_cast<u64>(BISKeyType::Tweak)}},
{"bis_key_2_crypt", {S128KeyType::BIS, 2, static_cast<u64>(BISKeyType::Crypto)}},
{"bis_key_2_tweak", {S128KeyType::BIS, 2, static_cast<u64>(BISKeyType::Tweak)}},
{"bis_key_3_crypt", {S128KeyType::BIS, 3, static_cast<u64>(BISKeyType::Crypto)}},
{"bis_key_3_tweak", {S128KeyType::BIS, 3, static_cast<u64>(BISKeyType::Tweak)}},
{"header_kek", {S128KeyType::HeaderKek, 0, 0}},
{"sd_card_kek", {S128KeyType::SDKek, 0, 0}},
}};
auto Find128ByName(std::string_view name) {
return std::find_if(s128_file_id.begin(), s128_file_id.end(),
[&name](const auto& pair) { return pair.first == name; });
}
constexpr std::array<std::pair<std::string_view, KeyIndex<S256KeyType>>, 6> s256_file_id{{
{"header_key", {S256KeyType::Header, 0, 0}},
{"sd_card_save_key_source", {S256KeyType::SDKeySource, static_cast<u64>(SDKeyType::Save), 0}},
{"sd_card_nca_key_source", {S256KeyType::SDKeySource, static_cast<u64>(SDKeyType::NCA), 0}},
{"header_key_source", {S256KeyType::HeaderSource, 0, 0}},
{"sd_card_save_key", {S256KeyType::SDKey, static_cast<u64>(SDKeyType::Save), 0}},
{"sd_card_nca_key", {S256KeyType::SDKey, static_cast<u64>(SDKeyType::NCA), 0}},
}};
auto Find256ByName(std::string_view name) {
return std::find_if(s256_file_id.begin(), s256_file_id.end(),
[&name](const auto& pair) { return pair.first == name; });
}
using KeyArray = std::array<std::pair<std::pair<S128KeyType, u64>, std::string_view>, 7>;
constexpr KeyArray KEYS_VARIABLE_LENGTH{{
{{S128KeyType::Master, 0}, "master_key_"},
{{S128KeyType::Package1, 0}, "package1_key_"},
{{S128KeyType::Package2, 0}, "package2_key_"},
@@ -57,14 +123,13 @@ const std::map<std::pair<S128KeyType, u64>, std::string> KEYS_VARIABLE_LENGTH{
{{S128KeyType::Source, static_cast<u64>(SourceKeyType::Keyblob)}, "keyblob_key_source_"},
{{S128KeyType::Keyblob, 0}, "keyblob_key_"},
{{S128KeyType::KeyblobMAC, 0}, "keyblob_mac_key_"},
};
}};
namespace {
template <std::size_t Size>
bool IsAllZeroArray(const std::array<u8, Size>& array) {
return std::all_of(array.begin(), array.end(), [](const auto& elem) { return elem == 0; });
}
} // namespace
} // Anonymous namespace
u64 GetSignatureTypeDataSize(SignatureType type) {
switch (type) {
@@ -564,13 +629,13 @@ void KeyManager::LoadFromFile(const std::string& filename, bool is_title_keys) {
s128_keys[{S128KeyType::Titlekey, rights_id[1], rights_id[0]}] = key;
} else {
out[0] = Common::ToLower(out[0]);
if (s128_file_id.find(out[0]) != s128_file_id.end()) {
const auto index = s128_file_id.at(out[0]);
Key128 key = Common::HexStringToArray<16>(out[1]);
if (const auto iter128 = Find128ByName(out[0]); iter128 != s128_file_id.end()) {
const auto& index = iter128->second;
const Key128 key = Common::HexStringToArray<16>(out[1]);
s128_keys[{index.type, index.field1, index.field2}] = key;
} else if (s256_file_id.find(out[0]) != s256_file_id.end()) {
const auto index = s256_file_id.at(out[0]);
Key256 key = Common::HexStringToArray<32>(out[1]);
} else if (const auto iter256 = Find256ByName(out[0]); iter256 != s256_file_id.end()) {
const auto& index = iter256->second;
const Key256 key = Common::HexStringToArray<32>(out[1]);
s256_keys[{index.type, index.field1, index.field2}] = key;
} else if (out[0].compare(0, 8, "keyblob_") == 0 &&
out[0].compare(0, 9, "keyblob_k") != 0) {
@@ -742,8 +807,7 @@ void KeyManager::SetKey(S128KeyType id, Key128 key, u64 field1, u64 field2) {
}
const auto iter2 = std::find_if(
s128_file_id.begin(), s128_file_id.end(),
[&id, &field1, &field2](const std::pair<std::string, KeyIndex<S128KeyType>> elem) {
s128_file_id.begin(), s128_file_id.end(), [&id, &field1, &field2](const auto& elem) {
return std::tie(elem.second.type, elem.second.field1, elem.second.field2) ==
std::tie(id, field1, field2);
});
@@ -753,9 +817,11 @@ void KeyManager::SetKey(S128KeyType id, Key128 key, u64 field1, u64 field2) {
// Variable cases
if (id == S128KeyType::KeyArea) {
static constexpr std::array<const char*, 3> kak_names = {"key_area_key_application_{:02X}",
"key_area_key_ocean_{:02X}",
"key_area_key_system_{:02X}"};
static constexpr std::array<const char*, 3> kak_names = {
"key_area_key_application_{:02X}",
"key_area_key_ocean_{:02X}",
"key_area_key_system_{:02X}",
};
WriteKeyToFile(category, fmt::format(kak_names.at(field2), field1), key);
} else if (id == S128KeyType::Master) {
WriteKeyToFile(category, fmt::format("master_key_{:02X}", field1), key);
@@ -781,8 +847,7 @@ void KeyManager::SetKey(S256KeyType id, Key256 key, u64 field1, u64 field2) {
return;
}
const auto iter = std::find_if(
s256_file_id.begin(), s256_file_id.end(),
[&id, &field1, &field2](const std::pair<std::string, KeyIndex<S256KeyType>> elem) {
s256_file_id.begin(), s256_file_id.end(), [&id, &field1, &field2](const auto& elem) {
return std::tie(elem.second.type, elem.second.field1, elem.second.field2) ==
std::tie(id, field1, field2);
});
@@ -1245,58 +1310,4 @@ bool KeyManager::AddTicketPersonalized(Ticket raw) {
SetKey(S128KeyType::Titlekey, key, rights_id[1], rights_id[0]);
return true;
}
const boost::container::flat_map<std::string, KeyIndex<S128KeyType>> KeyManager::s128_file_id = {
{"eticket_rsa_kek", {S128KeyType::ETicketRSAKek, 0, 0}},
{"eticket_rsa_kek_source",
{S128KeyType::Source, static_cast<u64>(SourceKeyType::ETicketKek), 0}},
{"eticket_rsa_kekek_source",
{S128KeyType::Source, static_cast<u64>(SourceKeyType::ETicketKekek), 0}},
{"rsa_kek_mask_0", {S128KeyType::RSAKek, static_cast<u64>(RSAKekType::Mask0), 0}},
{"rsa_kek_seed_3", {S128KeyType::RSAKek, static_cast<u64>(RSAKekType::Seed3), 0}},
{"rsa_oaep_kek_generation_source",
{S128KeyType::Source, static_cast<u64>(SourceKeyType::RSAOaepKekGeneration), 0}},
{"sd_card_kek_source", {S128KeyType::Source, static_cast<u64>(SourceKeyType::SDKek), 0}},
{"aes_kek_generation_source",
{S128KeyType::Source, static_cast<u64>(SourceKeyType::AESKekGeneration), 0}},
{"aes_key_generation_source",
{S128KeyType::Source, static_cast<u64>(SourceKeyType::AESKeyGeneration), 0}},
{"package2_key_source", {S128KeyType::Source, static_cast<u64>(SourceKeyType::Package2), 0}},
{"master_key_source", {S128KeyType::Source, static_cast<u64>(SourceKeyType::Master), 0}},
{"header_kek_source", {S128KeyType::Source, static_cast<u64>(SourceKeyType::HeaderKek), 0}},
{"key_area_key_application_source",
{S128KeyType::Source, static_cast<u64>(SourceKeyType::KeyAreaKey),
static_cast<u64>(KeyAreaKeyType::Application)}},
{"key_area_key_ocean_source",
{S128KeyType::Source, static_cast<u64>(SourceKeyType::KeyAreaKey),
static_cast<u64>(KeyAreaKeyType::Ocean)}},
{"key_area_key_system_source",
{S128KeyType::Source, static_cast<u64>(SourceKeyType::KeyAreaKey),
static_cast<u64>(KeyAreaKeyType::System)}},
{"titlekek_source", {S128KeyType::Source, static_cast<u64>(SourceKeyType::Titlekek), 0}},
{"keyblob_mac_key_source",
{S128KeyType::Source, static_cast<u64>(SourceKeyType::KeyblobMAC), 0}},
{"tsec_key", {S128KeyType::TSEC, 0, 0}},
{"secure_boot_key", {S128KeyType::SecureBoot, 0, 0}},
{"sd_seed", {S128KeyType::SDSeed, 0, 0}},
{"bis_key_0_crypt", {S128KeyType::BIS, 0, static_cast<u64>(BISKeyType::Crypto)}},
{"bis_key_0_tweak", {S128KeyType::BIS, 0, static_cast<u64>(BISKeyType::Tweak)}},
{"bis_key_1_crypt", {S128KeyType::BIS, 1, static_cast<u64>(BISKeyType::Crypto)}},
{"bis_key_1_tweak", {S128KeyType::BIS, 1, static_cast<u64>(BISKeyType::Tweak)}},
{"bis_key_2_crypt", {S128KeyType::BIS, 2, static_cast<u64>(BISKeyType::Crypto)}},
{"bis_key_2_tweak", {S128KeyType::BIS, 2, static_cast<u64>(BISKeyType::Tweak)}},
{"bis_key_3_crypt", {S128KeyType::BIS, 3, static_cast<u64>(BISKeyType::Crypto)}},
{"bis_key_3_tweak", {S128KeyType::BIS, 3, static_cast<u64>(BISKeyType::Tweak)}},
{"header_kek", {S128KeyType::HeaderKek, 0, 0}},
{"sd_card_kek", {S128KeyType::SDKek, 0, 0}},
};
const boost::container::flat_map<std::string, KeyIndex<S256KeyType>> KeyManager::s256_file_id = {
{"header_key", {S256KeyType::Header, 0, 0}},
{"sd_card_save_key_source", {S256KeyType::SDKeySource, static_cast<u64>(SDKeyType::Save), 0}},
{"sd_card_nca_key_source", {S256KeyType::SDKeySource, static_cast<u64>(SDKeyType::NCA), 0}},
{"header_key_source", {S256KeyType::HeaderSource, 0, 0}},
{"sd_card_save_key", {S256KeyType::SDKey, static_cast<u64>(SDKeyType::Save), 0}},
{"sd_card_nca_key", {S256KeyType::SDKey, static_cast<u64>(SDKeyType::NCA), 0}},
};
} // namespace Core::Crypto

View File

@@ -10,7 +10,6 @@
#include <string>
#include <variant>
#include <boost/container/flat_map.hpp>
#include <fmt/format.h>
#include "common/common_funcs.h"
#include "common/common_types.h"
@@ -293,9 +292,6 @@ private:
void SetKeyWrapped(S128KeyType id, Key128 key, u64 field1 = 0, u64 field2 = 0);
void SetKeyWrapped(S256KeyType id, Key256 key, u64 field1 = 0, u64 field2 = 0);
static const boost::container::flat_map<std::string, KeyIndex<S128KeyType>> s128_file_id;
static const boost::container::flat_map<std::string, KeyIndex<S256KeyType>> s256_file_id;
};
Key128 GenerateKeyEncryptionKey(Key128 source, Key128 master, Key128 kek_seed, Key128 key_seed);

View File

@@ -257,8 +257,7 @@ std::vector<NcaID> PlaceholderCache::List() const {
for (const auto& sdir : dir->GetSubdirectories()) {
for (const auto& file : sdir->GetFiles()) {
const auto name = file->GetName();
if (name.length() == 36 && name[32] == '.' && name[33] == 'n' && name[34] == 'c' &&
name[35] == 'a') {
if (name.length() == 36 && name.ends_with(".nca")) {
out.push_back(Common::HexStringToArray<0x10>(name.substr(0, 32)));
}
}
@@ -621,25 +620,25 @@ InstallResult RegisteredCache::InstallEntry(const NSP& nsp, bool overwrite_if_ex
InstallResult RegisteredCache::InstallEntry(const NCA& nca, TitleType type,
bool overwrite_if_exists, const VfsCopyFunction& copy) {
CNMTHeader header{
nca.GetTitleId(), // Title ID
0, // Ignore/Default title version
type, // Type
{}, // Padding
0x10, // Default table offset
1, // 1 Content Entry
0, // No Meta Entries
{}, // Padding
{}, // Reserved 1
0, // Is committed
0, // Required download system version
{}, // Reserved 2
const CNMTHeader header{
.title_id = nca.GetTitleId(),
.title_version = 0,
.type = type,
.reserved = {},
.table_offset = 0x10,
.number_content_entries = 1,
.number_meta_entries = 0,
.attributes = 0,
.reserved2 = {},
.is_committed = 0,
.required_download_system_version = 0,
.reserved3 = {},
};
OptionalHeader opt_header{0, 0};
const OptionalHeader opt_header{0, 0};
ContentRecord c_rec{{}, {}, {}, GetCRTypeFromNCAType(nca.GetType()), {}};
const auto& data = nca.GetBaseFile()->ReadBytes(0x100000);
mbedtls_sha256_ret(data.data(), data.size(), c_rec.hash.data(), 0);
memcpy(&c_rec.nca_id, &c_rec.hash, 16);
std::memcpy(&c_rec.nca_id, &c_rec.hash, 16);
const CNMT new_cnmt(header, opt_header, {c_rec}, {});
if (!RawInstallYuzuMeta(new_cnmt)) {
return InstallResult::ErrorMetaFailed;

View File

@@ -72,8 +72,10 @@ VfsEntryType RealVfsFilesystem::GetEntryType(std::string_view path_) const {
VirtualFile RealVfsFilesystem::OpenFile(std::string_view path_, Mode perms) {
const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault);
if (cache.find(path) != cache.end()) {
auto weak = cache[path];
if (const auto weak_iter = cache.find(path); weak_iter != cache.cend()) {
const auto& weak = weak_iter->second;
if (!weak.expired()) {
return std::shared_ptr<RealVfsFile>(new RealVfsFile(*this, weak.lock(), path, perms));
}
@@ -84,7 +86,7 @@ VirtualFile RealVfsFilesystem::OpenFile(std::string_view path_, Mode perms) {
}
auto backing = std::make_shared<FS::IOFile>(path, ModeFlagsToString(perms).c_str());
cache[path] = backing;
cache.insert_or_assign(path, backing);
// Cannot use make_shared as RealVfsFile constructor is private
return std::shared_ptr<RealVfsFile>(new RealVfsFile(*this, backing, path, perms));
@@ -116,11 +118,12 @@ VirtualFile RealVfsFilesystem::CopyFile(std::string_view old_path_, std::string_
VirtualFile RealVfsFilesystem::MoveFile(std::string_view old_path_, std::string_view new_path_) {
const auto old_path = FS::SanitizePath(old_path_, FS::DirectorySeparator::PlatformDefault);
const auto new_path = FS::SanitizePath(new_path_, FS::DirectorySeparator::PlatformDefault);
const auto cached_file_iter = cache.find(old_path);
if (cache.find(old_path) != cache.end()) {
auto file = cache[old_path].lock();
if (cached_file_iter != cache.cend()) {
auto file = cached_file_iter->second.lock();
if (!cache[old_path].expired()) {
if (!cached_file_iter->second.expired()) {
file->Close();
}
@@ -131,7 +134,7 @@ VirtualFile RealVfsFilesystem::MoveFile(std::string_view old_path_, std::string_
cache.erase(old_path);
file->Open(new_path, "r+b");
cache[new_path] = file;
cache.insert_or_assign(new_path, std::move(file));
} else {
UNREACHABLE();
return nullptr;
@@ -142,12 +145,15 @@ VirtualFile RealVfsFilesystem::MoveFile(std::string_view old_path_, std::string_
bool RealVfsFilesystem::DeleteFile(std::string_view path_) {
const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault);
if (cache.find(path) != cache.end()) {
if (!cache[path].expired()) {
cache[path].lock()->Close();
const auto cached_iter = cache.find(path);
if (cached_iter != cache.cend()) {
if (!cached_iter->second.expired()) {
cached_iter->second.lock()->Close();
}
cache.erase(path);
}
return FS::Delete(path);
}
@@ -192,21 +198,25 @@ VirtualDir RealVfsFilesystem::MoveDirectory(std::string_view old_path_,
}
for (auto& kv : cache) {
// Path in cache starts with old_path
if (kv.first.rfind(old_path, 0) == 0) {
const auto file_old_path =
FS::SanitizePath(kv.first, FS::DirectorySeparator::PlatformDefault);
const auto file_new_path =
FS::SanitizePath(new_path + DIR_SEP + kv.first.substr(old_path.size()),
FS::DirectorySeparator::PlatformDefault);
auto cached = cache[file_old_path];
if (!cached.expired()) {
auto file = cached.lock();
file->Open(file_new_path, "r+b");
cache.erase(file_old_path);
cache[file_new_path] = file;
}
// If the path in the cache doesn't start with old_path, then bail on this file.
if (kv.first.rfind(old_path, 0) != 0) {
continue;
}
const auto file_old_path =
FS::SanitizePath(kv.first, FS::DirectorySeparator::PlatformDefault);
auto file_new_path = FS::SanitizePath(new_path + DIR_SEP + kv.first.substr(old_path.size()),
FS::DirectorySeparator::PlatformDefault);
const auto& cached = cache[file_old_path];
if (cached.expired()) {
continue;
}
auto file = cached.lock();
file->Open(file_new_path, "r+b");
cache.erase(file_old_path);
cache.insert_or_assign(std::move(file_new_path), std::move(file));
}
return OpenDirectory(new_path, Mode::ReadWrite);
@@ -214,15 +224,21 @@ VirtualDir RealVfsFilesystem::MoveDirectory(std::string_view old_path_,
bool RealVfsFilesystem::DeleteDirectory(std::string_view path_) {
const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault);
for (auto& kv : cache) {
// Path in cache starts with old_path
if (kv.first.rfind(path, 0) == 0) {
if (!cache[kv.first].expired()) {
cache[kv.first].lock()->Close();
}
cache.erase(kv.first);
// If the path in the cache doesn't start with path, then bail on this file.
if (kv.first.rfind(path, 0) != 0) {
continue;
}
const auto& entry = cache[kv.first];
if (!entry.expired()) {
entry.lock()->Close();
}
cache.erase(kv.first);
}
return FS::DeleteDirRecursively(path);
}
@@ -260,14 +276,14 @@ bool RealVfsFile::IsReadable() const {
}
std::size_t RealVfsFile::Read(u8* data, std::size_t length, std::size_t offset) const {
if (!backing->Seek(offset, SEEK_SET)) {
if (!backing->Seek(static_cast<s64>(offset), SEEK_SET)) {
return 0;
}
return backing->ReadBytes(data, length);
}
std::size_t RealVfsFile::Write(const u8* data, std::size_t length, std::size_t offset) {
if (!backing->Seek(offset, SEEK_SET)) {
if (!backing->Seek(static_cast<s64>(offset), SEEK_SET)) {
return 0;
}
return backing->WriteBytes(data, length);

View File

@@ -24,6 +24,7 @@ constexpr s32 HID_JOYSTICK_MAX = 0x7fff;
constexpr std::size_t NPAD_OFFSET = 0x9A00;
constexpr u32 BATTERY_FULL = 2;
constexpr u32 MAX_NPAD_ID = 7;
constexpr std::size_t HANDHELD_INDEX = 8;
constexpr std::array<u32, 10> npad_id_list{
0, 1, 2, 3, 4, 5, 6, 7, NPAD_HANDHELD, NPAD_UNKNOWN,
};
@@ -33,19 +34,41 @@ enum class JoystickId : std::size_t {
Joystick_Right,
};
static Controller_NPad::NPadControllerType MapSettingsTypeToNPad(Settings::ControllerType type) {
Controller_NPad::NPadControllerType Controller_NPad::MapSettingsTypeToNPad(
Settings::ControllerType type) {
switch (type) {
case Settings::ControllerType::ProController:
return Controller_NPad::NPadControllerType::ProController;
case Settings::ControllerType::DualJoycon:
return Controller_NPad::NPadControllerType::JoyDual;
return NPadControllerType::ProController;
case Settings::ControllerType::DualJoyconDetached:
return NPadControllerType::JoyDual;
case Settings::ControllerType::LeftJoycon:
return Controller_NPad::NPadControllerType::JoyLeft;
return NPadControllerType::JoyLeft;
case Settings::ControllerType::RightJoycon:
return Controller_NPad::NPadControllerType::JoyRight;
return NPadControllerType::JoyRight;
case Settings::ControllerType::Handheld:
return NPadControllerType::Handheld;
default:
UNREACHABLE();
return Controller_NPad::NPadControllerType::JoyDual;
return NPadControllerType::ProController;
}
}
Settings::ControllerType Controller_NPad::MapNPadToSettingsType(
Controller_NPad::NPadControllerType type) {
switch (type) {
case NPadControllerType::ProController:
return Settings::ControllerType::ProController;
case NPadControllerType::JoyDual:
return Settings::ControllerType::DualJoyconDetached;
case NPadControllerType::JoyLeft:
return Settings::ControllerType::LeftJoycon;
case NPadControllerType::JoyRight:
return Settings::ControllerType::RightJoycon;
case NPadControllerType::Handheld:
return Settings::ControllerType::Handheld;
default:
UNREACHABLE();
return Settings::ControllerType::ProController;
}
}
@@ -60,9 +83,9 @@ std::size_t Controller_NPad::NPadIdToIndex(u32 npad_id) {
case 6:
case 7:
return npad_id;
case 8:
case HANDHELD_INDEX:
case NPAD_HANDHELD:
return 8;
return HANDHELD_INDEX;
case 9:
case NPAD_UNKNOWN:
return 9;
@@ -83,7 +106,7 @@ u32 Controller_NPad::IndexToNPad(std::size_t index) {
case 6:
case 7:
return static_cast<u32>(index);
case 8:
case HANDHELD_INDEX:
return NPAD_HANDHELD;
case 9:
return NPAD_UNKNOWN;
@@ -96,25 +119,35 @@ u32 Controller_NPad::IndexToNPad(std::size_t index) {
Controller_NPad::Controller_NPad(Core::System& system) : ControllerBase(system), system(system) {}
Controller_NPad::~Controller_NPad() = default;
void Controller_NPad::InitNewlyAddedControler(std::size_t controller_idx) {
void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
const auto controller_type = connected_controllers[controller_idx].type;
auto& controller = shared_memory_entries[controller_idx];
if (controller_type == NPadControllerType::None) {
styleset_changed_events[controller_idx].writable->Signal();
return;
}
controller.joy_styles.raw = 0; // Zero out
controller.device_type.raw = 0;
controller.properties.raw = 0;
switch (controller_type) {
case NPadControllerType::None:
UNREACHABLE();
break;
case NPadControllerType::Handheld:
controller.joy_styles.handheld.Assign(1);
controller.device_type.handheld.Assign(1);
controller.pad_assignment = NPadAssignments::Dual;
case NPadControllerType::ProController:
controller.joy_styles.pro_controller.Assign(1);
controller.device_type.pro_controller.Assign(1);
controller.properties.is_vertical.Assign(1);
controller.properties.use_plus.Assign(1);
controller.properties.use_minus.Assign(1);
controller.pad_assignment = NPadAssignments::Single;
break;
case NPadControllerType::Handheld:
controller.joy_styles.handheld.Assign(1);
controller.device_type.handheld.Assign(1);
controller.properties.is_vertical.Assign(1);
controller.properties.use_plus.Assign(1);
controller.properties.use_minus.Assign(1);
controller.pad_assignment = NPadAssignments::Dual;
break;
case NPadControllerType::JoyDual:
controller.joy_styles.joycon_dual.Assign(1);
@@ -144,14 +177,6 @@ void Controller_NPad::InitNewlyAddedControler(std::size_t controller_idx) {
controller.device_type.pokeball.Assign(1);
controller.pad_assignment = NPadAssignments::Single;
break;
case NPadControllerType::ProController:
controller.joy_styles.pro_controller.Assign(1);
controller.device_type.pro_controller.Assign(1);
controller.properties.is_vertical.Assign(1);
controller.properties.use_plus.Assign(1);
controller.properties.use_minus.Assign(1);
controller.pad_assignment = NPadAssignments::Single;
break;
}
controller.single_color_error = ColorReadError::ReadOk;
@@ -192,36 +217,25 @@ void Controller_NPad::OnInit() {
style.pokeball.Assign(1);
}
std::transform(
Settings::values.players.begin(), Settings::values.players.end(),
connected_controllers.begin(), [](const Settings::PlayerInput& player) {
return ControllerHolder{MapSettingsTypeToNPad(player.type), player.connected};
});
std::stable_partition(connected_controllers.begin(), connected_controllers.begin() + 8,
[](const ControllerHolder& holder) { return holder.is_connected; });
std::transform(Settings::values.players.begin(), Settings::values.players.end(),
connected_controllers.begin(), [](const Settings::PlayerInput& player) {
return ControllerHolder{MapSettingsTypeToNPad(player.controller_type),
player.connected};
});
// Account for handheld
if (connected_controllers[8].is_connected)
connected_controllers[8].type = NPadControllerType::Handheld;
if (connected_controllers[HANDHELD_INDEX].is_connected) {
connected_controllers[HANDHELD_INDEX].type = NPadControllerType::Handheld;
}
supported_npad_id_types.resize(npad_id_list.size());
std::memcpy(supported_npad_id_types.data(), npad_id_list.data(),
npad_id_list.size() * sizeof(u32));
// Add a default dual joycon controller if none are present.
if (std::none_of(connected_controllers.begin(), connected_controllers.end(),
[](const ControllerHolder& controller) { return controller.is_connected; })) {
supported_npad_id_types.resize(npad_id_list.size());
std::memcpy(supported_npad_id_types.data(), npad_id_list.data(),
npad_id_list.size() * sizeof(u32));
AddNewController(NPadControllerType::JoyDual);
}
for (std::size_t i = 0; i < connected_controllers.size(); ++i) {
const auto& controller = connected_controllers[i];
if (controller.is_connected) {
AddNewControllerAt(controller.type, IndexToNPad(i));
AddNewControllerAt(controller.type, i);
}
}
}
@@ -309,8 +323,9 @@ void Controller_NPad::RequestPadStateUpdate(u32 npad_id) {
void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
std::size_t data_len) {
if (!IsControllerActivated())
if (!IsControllerActivated()) {
return;
}
for (std::size_t i = 0; i < shared_memory_entries.size(); i++) {
auto& npad = shared_memory_entries[i];
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*
auto& libnx_entry = npad.libnx.npad[npad.libnx.common.last_entry_index];
libnx_entry.connection_status.raw = 0;
libnx_entry.connection_status.IsConnected.Assign(1);
switch (controller_type) {
case NPadControllerType::None:
UNREACHABLE();
break;
case NPadControllerType::ProController:
main_controller.connection_status.raw = 0;
main_controller.connection_status.IsConnected.Assign(1);
main_controller.connection_status.IsWired.Assign(1);
main_controller.pad.pad_states.raw = pad_state.pad_states.raw;
main_controller.pad.l_stick = pad_state.l_stick;
main_controller.pad.r_stick = pad_state.r_stick;
libnx_entry.connection_status.IsWired.Assign(1);
break;
case NPadControllerType::Handheld:
handheld_entry.connection_status.raw = 0;
handheld_entry.connection_status.IsConnected.Assign(1);
handheld_entry.connection_status.IsWired.Assign(1);
handheld_entry.connection_status.IsLeftJoyConnected.Assign(1);
handheld_entry.connection_status.IsRightJoyConnected.Assign(1);
@@ -375,57 +402,52 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
handheld_entry.pad.pad_states.raw = pad_state.pad_states.raw;
handheld_entry.pad.l_stick = pad_state.l_stick;
handheld_entry.pad.r_stick = pad_state.r_stick;
libnx_entry.connection_status.IsWired.Assign(1);
libnx_entry.connection_status.IsLeftJoyConnected.Assign(1);
libnx_entry.connection_status.IsRightJoyConnected.Assign(1);
libnx_entry.connection_status.IsLeftJoyWired.Assign(1);
libnx_entry.connection_status.IsRightJoyWired.Assign(1);
break;
case NPadControllerType::JoyDual:
dual_entry.connection_status.raw = 0;
dual_entry.connection_status.IsConnected.Assign(1);
dual_entry.connection_status.IsLeftJoyConnected.Assign(1);
dual_entry.connection_status.IsRightJoyConnected.Assign(1);
dual_entry.connection_status.IsConnected.Assign(1);
libnx_entry.connection_status.IsLeftJoyConnected.Assign(1);
libnx_entry.connection_status.IsRightJoyConnected.Assign(1);
libnx_entry.connection_status.IsConnected.Assign(1);
dual_entry.pad.pad_states.raw = pad_state.pad_states.raw;
dual_entry.pad.l_stick = pad_state.l_stick;
dual_entry.pad.r_stick = pad_state.r_stick;
libnx_entry.connection_status.IsLeftJoyConnected.Assign(1);
libnx_entry.connection_status.IsRightJoyConnected.Assign(1);
break;
case NPadControllerType::JoyLeft:
left_entry.connection_status.raw = 0;
left_entry.connection_status.IsConnected.Assign(1);
left_entry.connection_status.IsLeftJoyConnected.Assign(1);
left_entry.pad.pad_states.raw = pad_state.pad_states.raw;
left_entry.pad.l_stick = pad_state.l_stick;
left_entry.pad.r_stick = pad_state.r_stick;
libnx_entry.connection_status.IsLeftJoyConnected.Assign(1);
break;
case NPadControllerType::JoyRight:
right_entry.connection_status.raw = 0;
right_entry.connection_status.IsConnected.Assign(1);
right_entry.connection_status.IsRightJoyConnected.Assign(1);
right_entry.pad.pad_states.raw = pad_state.pad_states.raw;
right_entry.pad.l_stick = pad_state.l_stick;
right_entry.pad.r_stick = pad_state.r_stick;
libnx_entry.connection_status.IsRightJoyConnected.Assign(1);
break;
case NPadControllerType::Pokeball:
pokeball_entry.connection_status.raw = 0;
pokeball_entry.connection_status.IsConnected.Assign(1);
pokeball_entry.connection_status.IsWired.Assign(1);
pokeball_entry.pad.pad_states.raw = pad_state.pad_states.raw;
pokeball_entry.pad.l_stick = pad_state.l_stick;
pokeball_entry.pad.r_stick = pad_state.r_stick;
break;
case NPadControllerType::ProController:
main_controller.connection_status.raw = 0;
main_controller.connection_status.IsConnected.Assign(1);
main_controller.connection_status.IsWired.Assign(1);
main_controller.pad.pad_states.raw = pad_state.pad_states.raw;
main_controller.pad.l_stick = pad_state.l_stick;
main_controller.pad.r_stick = pad_state.r_stick;
break;
}
// 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) {
supported_npad_id_types.clear();
supported_npad_id_types.resize(length / sizeof(u32));
std::memcpy(supported_npad_id_types.data(), data, length);
for (std::size_t i = 0; i < connected_controllers.size(); i++) {
auto& controller = connected_controllers[i];
if (!controller.is_connected) {
continue;
}
const auto requested_controller =
i <= MAX_NPAD_ID ? MapSettingsTypeToNPad(Settings::values.players[i].type)
: NPadControllerType::Handheld;
if (!IsControllerSupported(requested_controller)) {
const auto is_handheld = requested_controller == NPadControllerType::Handheld;
if (is_handheld) {
controller.type = NPadControllerType::None;
controller.is_connected = false;
AddNewController(requested_controller);
} else {
controller.type = requested_controller;
InitNewlyAddedControler(i);
}
}
}
}
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,
const std::vector<Vibration>& vibrations) {
LOG_DEBUG(Service_HID, "(STUBBED) called");
if (!can_controllers_vibrate) {
if (!Settings::values.vibration_enabled || !can_controllers_vibrate) {
return;
}
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,
}
std::shared_ptr<Kernel::ReadableEvent> Controller_NPad::GetStyleSetChangedEvent(u32 npad_id) const {
// TODO(ogniK): Figure out the best time to signal this event. This event seems that it should
// be signalled at least once, and signaled after a new controller is connected?
const auto& styleset_event = styleset_changed_events[NPadIdToIndex(npad_id)];
return styleset_event.readable;
}
@@ -527,43 +527,43 @@ Controller_NPad::Vibration Controller_NPad::GetLastVibration() const {
return last_processed_vibration;
}
void Controller_NPad::AddNewController(NPadControllerType controller) {
controller = DecideBestController(controller);
if (controller == NPadControllerType::Handheld) {
connected_controllers[8] = {controller, true};
InitNewlyAddedControler(8);
return;
}
const auto pos =
std::find_if(connected_controllers.begin(), connected_controllers.end() - 2,
[](const ControllerHolder& holder) { return !holder.is_connected; });
if (pos == connected_controllers.end() - 2) {
LOG_ERROR(Service_HID, "Cannot connect any more controllers!");
return;
}
const auto controller_id = std::distance(connected_controllers.begin(), pos);
connected_controllers[controller_id] = {controller, true};
InitNewlyAddedControler(controller_id);
void Controller_NPad::AddNewControllerAt(NPadControllerType controller, std::size_t npad_index) {
UpdateControllerAt(controller, npad_index, true);
}
void Controller_NPad::AddNewControllerAt(NPadControllerType controller, u32 npad_id) {
controller = DecideBestController(controller);
if (controller == NPadControllerType::Handheld) {
connected_controllers[NPadIdToIndex(NPAD_HANDHELD)] = {controller, true};
InitNewlyAddedControler(NPadIdToIndex(NPAD_HANDHELD));
void Controller_NPad::UpdateControllerAt(NPadControllerType controller, std::size_t npad_index,
bool connected) {
if (!connected) {
DisconnectNPad(IndexToNPad(npad_index));
return;
}
connected_controllers[NPadIdToIndex(npad_id)] = {controller, true};
InitNewlyAddedControler(NPadIdToIndex(npad_id));
}
if (controller == NPadControllerType::Handheld) {
Settings::values.players[HANDHELD_INDEX].controller_type =
MapNPadToSettingsType(controller);
Settings::values.players[HANDHELD_INDEX].connected = true;
connected_controllers[HANDHELD_INDEX] = {controller, true};
InitNewlyAddedController(HANDHELD_INDEX);
return;
}
void Controller_NPad::ConnectNPad(u32 npad_id) {
connected_controllers[NPadIdToIndex(npad_id)].is_connected = true;
Settings::values.players[npad_index].controller_type = MapNPadToSettingsType(controller);
Settings::values.players[npad_index].connected = true;
connected_controllers[npad_index] = {controller, true};
InitNewlyAddedController(npad_index);
}
void Controller_NPad::DisconnectNPad(u32 npad_id) {
connected_controllers[NPadIdToIndex(npad_id)].is_connected = false;
const auto npad_index = NPadIdToIndex(npad_id);
connected_controllers[npad_index].is_connected = false;
Settings::values.players[npad_index].connected = false;
auto& controller = shared_memory_entries[npad_index];
controller.joy_styles.raw = 0; // Zero out
controller.device_type.raw = 0;
controller.properties.raw = 0;
styleset_changed_events[npad_index].writable->Signal();
}
void Controller_NPad::SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode) {
@@ -599,8 +599,8 @@ bool Controller_NPad::SwapNpadAssignment(u32 npad_id_1, u32 npad_id_2) {
std::swap(connected_controllers[npad_index_1].type, connected_controllers[npad_index_2].type);
InitNewlyAddedControler(npad_index_1);
InitNewlyAddedControler(npad_index_2);
AddNewControllerAt(connected_controllers[npad_index_1].type, npad_index_1);
AddNewControllerAt(connected_controllers[npad_index_2].type, npad_index_2);
return true;
}
@@ -614,11 +614,11 @@ Controller_NPad::LedPattern Controller_NPad::GetLedPattern(u32 npad_id) {
case 0:
return LedPattern{1, 0, 0, 0};
case 1:
return LedPattern{0, 1, 0, 0};
return LedPattern{1, 1, 0, 0};
case 2:
return LedPattern{0, 0, 1, 0};
return LedPattern{1, 1, 1, 0};
case 3:
return LedPattern{0, 0, 0, 1};
return LedPattern{1, 1, 1, 1};
case 4:
return LedPattern{1, 0, 0, 1};
case 5:
@@ -628,7 +628,6 @@ Controller_NPad::LedPattern Controller_NPad::GetLedPattern(u32 npad_id) {
case 7:
return LedPattern{0, 1, 1, 0};
default:
UNIMPLEMENTED_MSG("Unhandled npad_id {}", npad_id);
return LedPattern{0, 0, 0, 0};
}
}

View File

@@ -118,10 +118,11 @@ public:
std::shared_ptr<Kernel::ReadableEvent> GetStyleSetChangedEvent(u32 npad_id) const;
Vibration GetLastVibration() const;
void AddNewController(NPadControllerType controller);
void AddNewControllerAt(NPadControllerType controller, u32 npad_id);
// Adds a new controller at an index.
void AddNewControllerAt(NPadControllerType controller, std::size_t npad_index);
// Adds a new controller at an index with connection status.
void UpdateControllerAt(NPadControllerType controller, std::size_t npad_index, bool connected);
void ConnectNPad(u32 npad_id);
void DisconnectNPad(u32 npad_id);
void SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode);
GyroscopeZeroDriftMode GetGyroscopeZeroDriftMode() const;
@@ -141,6 +142,8 @@ public:
// Specifically for cheat engine and other features.
u32 GetAndResetPressState();
static Controller_NPad::NPadControllerType MapSettingsTypeToNPad(Settings::ControllerType type);
static Settings::ControllerType MapNPadToSettingsType(Controller_NPad::NPadControllerType type);
static std::size_t NPadIdToIndex(u32 npad_id);
static u32 IndexToNPad(std::size_t index);
@@ -309,7 +312,7 @@ private:
bool is_connected;
};
void InitNewlyAddedControler(std::size_t controller_idx);
void InitNewlyAddedController(std::size_t controller_idx);
bool IsControllerSupported(NPadControllerType controller) const;
NPadControllerType DecideBestController(NPadControllerType priority) const;
void RequestPadStateUpdate(u32 npad_id);

View File

@@ -38,11 +38,9 @@
namespace Service::HID {
// Updating period for each HID device.
// TODO(ogniK): Find actual polling rate of hid
constexpr auto pad_update_ns = std::chrono::nanoseconds{1000000000 / 66};
[[maybe_unused]] constexpr auto accelerometer_update_ns =
std::chrono::nanoseconds{1000000000 / 100};
[[maybe_unused]] constexpr auto gyroscope_update_ticks = std::chrono::nanoseconds{1000000000 / 100};
// HID is polled every 15ms, this value was derived from
// https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering#joy-con-status-data-packet
constexpr auto pad_update_ns = std::chrono::nanoseconds{15 * 1000 * 1000}; // (15ms, 66.6Hz)
constexpr std::size_t SHARED_MEMORY_SIZE = 0x40000;
IAppletResource::IAppletResource(Core::System& system)
@@ -845,8 +843,7 @@ void Hid::CreateActiveVibrationDeviceList(Kernel::HLERequestContext& ctx) {
void Hid::PermitVibration(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto can_vibrate{rp.Pop<bool>()};
applet_resource->GetController<Controller_NPad>(HidController::NPad)
.SetVibrationEnabled(can_vibrate);
Settings::values.vibration_enabled = can_vibrate;
LOG_DEBUG(Service_HID, "called, can_vibrate={}", can_vibrate);
@@ -859,8 +856,7 @@ void Hid::IsVibrationPermitted(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push(
applet_resource->GetController<Controller_NPad>(HidController::NPad).IsVibrationEnabled());
rb.Push(Settings::values.vibration_enabled);
}
void Hid::ActivateConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) {

View File

@@ -13,56 +13,6 @@
namespace Settings {
namespace NativeButton {
const std::array<const char*, NumButtons> mapping = {{
"button_a",
"button_b",
"button_x",
"button_y",
"button_lstick",
"button_rstick",
"button_l",
"button_r",
"button_zl",
"button_zr",
"button_plus",
"button_minus",
"button_dleft",
"button_dup",
"button_dright",
"button_ddown",
"button_lstick_left",
"button_lstick_up",
"button_lstick_right",
"button_lstick_down",
"button_rstick_left",
"button_rstick_up",
"button_rstick_right",
"button_rstick_down",
"button_sl",
"button_sr",
"button_home",
"button_screenshot",
}};
}
namespace NativeAnalog {
const std::array<const char*, NumAnalogs> mapping = {{
"lstick",
"rstick",
}};
}
namespace NativeMouseButton {
const std::array<const char*, NumMouseButtons> mapping = {{
"left",
"right",
"middle",
"forward",
"back",
}};
}
Values values = {};
bool configuring_global = true;

View File

@@ -12,340 +12,10 @@
#include <string>
#include <vector>
#include "common/common_types.h"
#include "input_common/settings.h"
namespace Settings {
namespace NativeButton {
enum Values {
A,
B,
X,
Y,
LStick,
RStick,
L,
R,
ZL,
ZR,
Plus,
Minus,
DLeft,
DUp,
DRight,
DDown,
LStick_Left,
LStick_Up,
LStick_Right,
LStick_Down,
RStick_Left,
RStick_Up,
RStick_Right,
RStick_Down,
SL,
SR,
Home,
Screenshot,
NumButtons,
};
constexpr int BUTTON_HID_BEGIN = A;
constexpr int BUTTON_NS_BEGIN = Home;
constexpr int BUTTON_HID_END = BUTTON_NS_BEGIN;
constexpr int BUTTON_NS_END = NumButtons;
constexpr int NUM_BUTTONS_HID = BUTTON_HID_END - BUTTON_HID_BEGIN;
constexpr int NUM_BUTTONS_NS = BUTTON_NS_END - BUTTON_NS_BEGIN;
extern const std::array<const char*, NumButtons> mapping;
} // namespace NativeButton
namespace NativeAnalog {
enum Values {
LStick,
RStick,
NumAnalogs,
};
constexpr int STICK_HID_BEGIN = LStick;
constexpr int STICK_HID_END = NumAnalogs;
constexpr int NUM_STICKS_HID = NumAnalogs;
extern const std::array<const char*, NumAnalogs> mapping;
} // namespace NativeAnalog
namespace NativeMouseButton {
enum Values {
Left,
Right,
Middle,
Forward,
Back,
NumMouseButtons,
};
constexpr int MOUSE_HID_BEGIN = Left;
constexpr int MOUSE_HID_END = NumMouseButtons;
constexpr int NUM_MOUSE_HID = NumMouseButtons;
extern const std::array<const char*, NumMouseButtons> mapping;
} // namespace NativeMouseButton
namespace NativeKeyboard {
enum Keys {
None,
Error,
A = 4,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z,
N1,
N2,
N3,
N4,
N5,
N6,
N7,
N8,
N9,
N0,
Enter,
Escape,
Backspace,
Tab,
Space,
Minus,
Equal,
LeftBrace,
RightBrace,
Backslash,
Tilde,
Semicolon,
Apostrophe,
Grave,
Comma,
Dot,
Slash,
CapsLockKey,
F1,
F2,
F3,
F4,
F5,
F6,
F7,
F8,
F9,
F10,
F11,
F12,
SystemRequest,
ScrollLockKey,
Pause,
Insert,
Home,
PageUp,
Delete,
End,
PageDown,
Right,
Left,
Down,
Up,
NumLockKey,
KPSlash,
KPAsterisk,
KPMinus,
KPPlus,
KPEnter,
KP1,
KP2,
KP3,
KP4,
KP5,
KP6,
KP7,
KP8,
KP9,
KP0,
KPDot,
Key102,
Compose,
Power,
KPEqual,
F13,
F14,
F15,
F16,
F17,
F18,
F19,
F20,
F21,
F22,
F23,
F24,
Open,
Help,
Properties,
Front,
Stop,
Repeat,
Undo,
Cut,
Copy,
Paste,
Find,
Mute,
VolumeUp,
VolumeDown,
CapsLockActive,
NumLockActive,
ScrollLockActive,
KPComma,
KPLeftParenthesis,
KPRightParenthesis,
LeftControlKey = 0xE0,
LeftShiftKey,
LeftAltKey,
LeftMetaKey,
RightControlKey,
RightShiftKey,
RightAltKey,
RightMetaKey,
MediaPlayPause,
MediaStopCD,
MediaPrevious,
MediaNext,
MediaEject,
MediaVolumeUp,
MediaVolumeDown,
MediaMute,
MediaWebsite,
MediaBack,
MediaForward,
MediaStop,
MediaFind,
MediaScrollUp,
MediaScrollDown,
MediaEdit,
MediaSleep,
MediaCoffee,
MediaRefresh,
MediaCalculator,
NumKeyboardKeys,
};
static_assert(NumKeyboardKeys == 0xFC, "Incorrect number of keyboard keys.");
enum Modifiers {
LeftControl,
LeftShift,
LeftAlt,
LeftMeta,
RightControl,
RightShift,
RightAlt,
RightMeta,
CapsLock,
ScrollLock,
NumLock,
NumKeyboardMods,
};
constexpr int KEYBOARD_KEYS_HID_BEGIN = None;
constexpr int KEYBOARD_KEYS_HID_END = NumKeyboardKeys;
constexpr int NUM_KEYBOARD_KEYS_HID = NumKeyboardKeys;
constexpr int KEYBOARD_MODS_HID_BEGIN = LeftControl;
constexpr int KEYBOARD_MODS_HID_END = NumKeyboardMods;
constexpr int NUM_KEYBOARD_MODS_HID = NumKeyboardMods;
} // namespace NativeKeyboard
using ButtonsRaw = std::array<std::string, NativeButton::NumButtons>;
using AnalogsRaw = std::array<std::string, NativeAnalog::NumAnalogs>;
using MouseButtonsRaw = std::array<std::string, NativeMouseButton::NumMouseButtons>;
using KeyboardKeysRaw = std::array<std::string, NativeKeyboard::NumKeyboardKeys>;
using KeyboardModsRaw = std::array<std::string, NativeKeyboard::NumKeyboardMods>;
constexpr u32 JOYCON_BODY_NEON_RED = 0xFF3C28;
constexpr u32 JOYCON_BUTTONS_NEON_RED = 0x1E0A0A;
constexpr u32 JOYCON_BODY_NEON_BLUE = 0x0AB9E6;
constexpr u32 JOYCON_BUTTONS_NEON_BLUE = 0x001E1E;
enum class ControllerType {
ProController,
DualJoycon,
RightJoycon,
LeftJoycon,
};
struct PlayerInput {
bool connected;
ControllerType type;
ButtonsRaw buttons;
AnalogsRaw analogs;
u32 body_color_right;
u32 button_color_right;
u32 body_color_left;
u32 button_color_left;
};
struct TouchscreenInput {
bool enabled;
std::string device;
u32 finger;
u32 diameter_x;
u32 diameter_y;
u32 rotation_angle;
};
enum class RendererBackend {
OpenGL = 0,
Vulkan = 1,
@@ -359,7 +29,8 @@ enum class GPUAccuracy : u32 {
enum class CPUAccuracy {
Accurate = 0,
DebugMode = 1,
Unsafe = 1,
DebugMode = 2,
};
extern bool configuring_global;
@@ -419,6 +90,9 @@ struct Values {
bool cpuopt_misc_ir;
bool cpuopt_reduce_misalign_checks;
bool cpuopt_unsafe_unfuse_fma;
bool cpuopt_unsafe_reduce_fp_error;
// Renderer
Setting<RendererBackend> renderer_backend;
bool renderer_debug;
@@ -457,6 +131,8 @@ struct Values {
// Controls
std::array<PlayerInput, 10> players;
bool use_docked_mode;
bool mouse_enabled;
std::string mouse_device;
MouseButtonsRaw mouse_buttons;
@@ -470,14 +146,15 @@ struct Values {
AnalogsRaw debug_pad_analogs;
std::string motion_device;
bool vibration_enabled;
TouchscreenInput touchscreen;
std::atomic_bool is_device_reload_pending{true};
std::string udp_input_address;
u16 udp_input_port;
u8 udp_pad_index;
bool use_docked_mode;
// Data Storage
bool use_virtual_sd;
bool gamecard_inserted;

View File

@@ -7,6 +7,8 @@ add_library(input_common STATIC
main.h
motion_emu.cpp
motion_emu.h
settings.cpp
settings.h
gcadapter/gc_adapter.cpp
gcadapter/gc_adapter.h
gcadapter/gc_poller.cpp

View File

@@ -191,7 +191,7 @@ public:
bool GetAnalogDirectionStatus(Input::AnalogDirection direction) const override {
const auto [x, y] = GetStatus();
const float directional_deadzone = 0.4f;
const float directional_deadzone = 0.5f;
switch (direction) {
case Input::AnalogDirection::RIGHT:
return x > directional_deadzone;
@@ -232,7 +232,7 @@ std::unique_ptr<Input::AnalogDevice> GCAnalogFactory::Create(const Common::Param
const int port = params.Get("port", 0);
const int axis_x = params.Get("axis_x", 0);
const int axis_y = params.Get("axis_y", 1);
const float deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, .99f);
const float deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, 1.0f);
const float range = std::clamp(params.Get("range", 1.0f), 0.50f, 1.50f);
return std::make_unique<GCAnalog>(port, axis_x, axis_y, deadzone, adapter.get(), range);

View File

@@ -44,7 +44,6 @@ void Init() {
#ifdef HAVE_SDL2
sdl = SDL::Init();
#endif
udp = CemuhookUDP::Init();
}
@@ -103,6 +102,56 @@ std::string GenerateAnalogParamFromKeys(int key_up, int key_down, int key_left,
return circle_pad_param.Serialize();
}
std::vector<Common::ParamPackage> GetInputDevices() {
std::vector<Common::ParamPackage> devices = {
Common::ParamPackage{{"display", "Any"}, {"class", "any"}},
Common::ParamPackage{{"display", "Keyboard/Mouse"}, {"class", "key"}},
};
#ifdef HAVE_SDL2
auto sdl_devices = sdl->GetInputDevices();
devices.insert(devices.end(), sdl_devices.begin(), sdl_devices.end());
#endif
auto udp_devices = udp->GetInputDevices();
devices.insert(devices.end(), udp_devices.begin(), udp_devices.end());
return devices;
}
std::unordered_map<Settings::NativeButton::Values, Common::ParamPackage> GetButtonMappingForDevice(
const Common::ParamPackage& params) {
std::unordered_map<Settings::NativeButton::Values, Common::ParamPackage> mappings;
if (!params.Has("class") || params.Get("class", "") == "any") {
return {};
}
if (params.Get("class", "") == "key") {
// TODO consider returning the SDL key codes for the default keybindings
return {};
}
#ifdef HAVE_SDL2
if (params.Get("class", "") == "sdl") {
return sdl->GetButtonMappingForDevice(params);
}
#endif
return {};
}
std::unordered_map<Settings::NativeAnalog::Values, Common::ParamPackage> GetAnalogMappingForDevice(
const Common::ParamPackage& params) {
std::unordered_map<Settings::NativeAnalog::Values, Common::ParamPackage> mappings;
if (!params.Has("class") || params.Get("class", "") == "any") {
return {};
}
if (params.Get("class", "") == "key") {
// TODO consider returning the SDL key codes for the default keybindings
return {};
}
#ifdef HAVE_SDL2
if (params.Get("class", "") == "sdl") {
return sdl->GetAnalogMappingForDevice(params);
}
#endif
return {};
}
namespace Polling {
std::vector<std::unique_ptr<DevicePoller>> GetPollers(DeviceType type) {

View File

@@ -6,8 +6,10 @@
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>
#include "input_common/gcadapter/gc_poller.h"
#include "input_common/settings.h"
namespace Common {
class ParamPackage;
@@ -42,9 +44,27 @@ std::string GenerateKeyboardParam(int key_code);
std::string GenerateAnalogParamFromKeys(int key_up, int key_down, int key_left, int key_right,
int key_modifier, float modifier_scale);
/**
* Return a list of available input devices that this Factory can create a new device with.
* Each returned Parampackage should have a `display` field used for display, a class field for
* backends to determine if this backend is meant to service the request and any other information
* needed to identify this in the backend later.
*/
std::vector<Common::ParamPackage> GetInputDevices();
/**
* Given a ParamPackage for a Device returned from `GetInputDevices`, attempt to get the default
* mapping for the device. This is currently only implemented for the sdl backend devices.
*/
using ButtonMapping = std::unordered_map<Settings::NativeButton::Values, Common::ParamPackage>;
using AnalogMapping = std::unordered_map<Settings::NativeAnalog::Values, Common::ParamPackage>;
ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage&);
AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage&);
namespace Polling {
enum class DeviceType { Button, Analog };
enum class DeviceType { Button, AnalogPreferred };
/**
* A class that can be used to get inputs from an input device like controllers without having to
@@ -54,7 +74,9 @@ class DevicePoller {
public:
virtual ~DevicePoller() = default;
/// Setup and start polling for inputs, should be called before GetNextInput
virtual void Start() = 0;
/// If a device_id is provided, events should be filtered to only include events from this
/// device id
virtual void Start(const std::string& device_id = "") = 0;
/// Stop polling
virtual void Stop() = 0;
/**

View File

@@ -6,6 +6,7 @@
#include <memory>
#include <vector>
#include "common/param_package.h"
#include "input_common/main.h"
namespace InputCommon::Polling {
@@ -22,14 +23,24 @@ public:
/// Unregisters SDL device factories and shut them down.
virtual ~State() = default;
virtual Pollers GetPollers(Polling::DeviceType type) = 0;
virtual Pollers GetPollers(Polling::DeviceType type) {
return {};
}
virtual std::vector<Common::ParamPackage> GetInputDevices() {
return {};
}
virtual ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage&) {
return {};
}
virtual AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage&) {
return {};
}
};
class NullState : public State {
public:
Pollers GetPollers(Polling::DeviceType type) override {
return {};
}
};
std::unique_ptr<State> Init();

View File

@@ -7,6 +7,8 @@
#include <cmath>
#include <functional>
#include <mutex>
#include <optional>
#include <sstream>
#include <string>
#include <thread>
#include <tuple>
@@ -23,7 +25,8 @@
namespace InputCommon::SDL {
static std::string GetGUID(SDL_Joystick* joystick) {
namespace {
std::string GetGUID(SDL_Joystick* joystick) {
const SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick);
char guid_str[33];
SDL_JoystickGetGUIDString(guid, guid_str, sizeof(guid_str));
@@ -31,7 +34,8 @@ static std::string GetGUID(SDL_Joystick* joystick) {
}
/// Creates a ParamPackage from an SDL_Event that can directly be used to create a ButtonDevice
static Common::ParamPackage SDLEventToButtonParamPackage(SDLState& state, const SDL_Event& event);
Common::ParamPackage SDLEventToButtonParamPackage(SDLState& state, const SDL_Event& event);
} // Anonymous namespace
static int SDLEventWatcher(void* user_data, SDL_Event* event) {
auto* const sdl_state = static_cast<SDLState*>(user_data);
@@ -48,8 +52,10 @@ static int SDLEventWatcher(void* user_data, SDL_Event* event) {
class SDLJoystick {
public:
SDLJoystick(std::string guid_, int port_, SDL_Joystick* joystick)
: guid{std::move(guid_)}, port{port_}, sdl_joystick{joystick, &SDL_JoystickClose} {}
SDLJoystick(std::string guid_, int port_, SDL_Joystick* joystick,
SDL_GameController* gamecontroller)
: guid{std::move(guid_)}, port{port_}, sdl_joystick{joystick, &SDL_JoystickClose},
sdl_controller{gamecontroller, &SDL_GameControllerClose} {}
void SetButton(int button, bool value) {
std::lock_guard lock{mutex};
@@ -115,10 +121,15 @@ public:
return sdl_joystick.get();
}
void SetSDLJoystick(SDL_Joystick* joystick) {
void SetSDLJoystick(SDL_Joystick* joystick, SDL_GameController* controller) {
sdl_controller.reset(controller);
sdl_joystick.reset(joystick);
}
SDL_GameController* GetSDLGameController() const {
return sdl_controller.get();
}
private:
struct State {
std::unordered_map<int, bool> buttons;
@@ -128,6 +139,7 @@ private:
std::string guid;
int port;
std::unique_ptr<SDL_Joystick, decltype(&SDL_JoystickClose)> sdl_joystick;
std::unique_ptr<SDL_GameController, decltype(&SDL_GameControllerClose)> sdl_controller;
mutable std::mutex mutex;
};
@@ -136,18 +148,19 @@ std::shared_ptr<SDLJoystick> SDLState::GetSDLJoystickByGUID(const std::string& g
const auto it = joystick_map.find(guid);
if (it != joystick_map.end()) {
while (it->second.size() <= static_cast<std::size_t>(port)) {
auto joystick =
std::make_shared<SDLJoystick>(guid, static_cast<int>(it->second.size()), nullptr);
auto joystick = std::make_shared<SDLJoystick>(guid, static_cast<int>(it->second.size()),
nullptr, nullptr);
it->second.emplace_back(std::move(joystick));
}
return it->second[port];
}
auto joystick = std::make_shared<SDLJoystick>(guid, 0, nullptr);
auto joystick = std::make_shared<SDLJoystick>(guid, 0, nullptr, nullptr);
return joystick_map[guid].emplace_back(std::move(joystick));
}
std::shared_ptr<SDLJoystick> SDLState::GetSDLJoystickBySDLID(SDL_JoystickID sdl_id) {
auto sdl_joystick = SDL_JoystickFromInstanceID(sdl_id);
auto sdl_controller = SDL_GameControllerFromInstanceID(sdl_id);
const std::string guid = GetGUID(sdl_joystick);
std::lock_guard lock{joystick_map_mutex};
@@ -171,23 +184,27 @@ std::shared_ptr<SDLJoystick> SDLState::GetSDLJoystickBySDLID(SDL_JoystickID sdl_
});
if (nullptr_it != map_it->second.end()) {
// ... and map it
(*nullptr_it)->SetSDLJoystick(sdl_joystick);
(*nullptr_it)->SetSDLJoystick(sdl_joystick, sdl_controller);
return *nullptr_it;
}
// There is no SDLJoystick without a mapped SDL_Joystick
// Create a new SDLJoystick
const int port = static_cast<int>(map_it->second.size());
auto joystick = std::make_shared<SDLJoystick>(guid, port, sdl_joystick);
auto joystick = std::make_shared<SDLJoystick>(guid, port, sdl_joystick, sdl_controller);
return map_it->second.emplace_back(std::move(joystick));
}
auto joystick = std::make_shared<SDLJoystick>(guid, 0, sdl_joystick);
auto joystick = std::make_shared<SDLJoystick>(guid, 0, sdl_joystick, sdl_controller);
return joystick_map[guid].emplace_back(std::move(joystick));
}
void SDLState::InitJoystick(int joystick_index) {
SDL_Joystick* sdl_joystick = SDL_JoystickOpen(joystick_index);
SDL_GameController* sdl_gamecontroller = nullptr;
if (SDL_IsGameController(joystick_index)) {
sdl_gamecontroller = SDL_GameControllerOpen(joystick_index);
}
if (!sdl_joystick) {
LOG_ERROR(Input, "failed to open joystick {}", joystick_index);
return;
@@ -196,7 +213,7 @@ void SDLState::InitJoystick(int joystick_index) {
std::lock_guard lock{joystick_map_mutex};
if (joystick_map.find(guid) == joystick_map.end()) {
auto joystick = std::make_shared<SDLJoystick>(guid, 0, sdl_joystick);
auto joystick = std::make_shared<SDLJoystick>(guid, 0, sdl_joystick, sdl_gamecontroller);
joystick_map[guid].emplace_back(std::move(joystick));
return;
}
@@ -205,11 +222,11 @@ void SDLState::InitJoystick(int joystick_index) {
joystick_guid_list.begin(), joystick_guid_list.end(),
[](const std::shared_ptr<SDLJoystick>& joystick) { return !joystick->GetSDLJoystick(); });
if (it != joystick_guid_list.end()) {
(*it)->SetSDLJoystick(sdl_joystick);
(*it)->SetSDLJoystick(sdl_joystick, sdl_gamecontroller);
return;
}
const int port = static_cast<int>(joystick_guid_list.size());
auto joystick = std::make_shared<SDLJoystick>(guid, port, sdl_joystick);
auto joystick = std::make_shared<SDLJoystick>(guid, port, sdl_joystick, sdl_gamecontroller);
joystick_guid_list.emplace_back(std::move(joystick));
}
@@ -231,7 +248,7 @@ void SDLState::CloseJoystick(SDL_Joystick* sdl_joystick) {
// Destruct SDL_Joystick outside the lock guard because SDL can internally call the
// event callback which locks the mutex again.
joystick->SetSDLJoystick(nullptr);
joystick->SetSDLJoystick(nullptr, nullptr);
}
void SDLState::HandleGameControllerEvent(const SDL_Event& event) {
@@ -346,7 +363,7 @@ public:
bool GetAnalogDirectionStatus(Input::AnalogDirection direction) const override {
const auto [x, y] = GetStatus();
const float directional_deadzone = 0.4f;
const float directional_deadzone = 0.5f;
switch (direction) {
case Input::AnalogDirection::RIGHT:
return x > directional_deadzone;
@@ -460,7 +477,7 @@ public:
const int port = params.Get("port", 0);
const int axis_x = params.Get("axis_x", 0);
const int axis_y = params.Get("axis_y", 1);
const float deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, .99f);
const float deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, 1.0f);
const float range = std::clamp(params.Get("range", 1.0f), 0.50f, 1.50f);
auto joystick = state.GetSDLJoystickByGUID(guid, port);
@@ -476,8 +493,10 @@ private:
SDLState::SDLState() {
using namespace Input;
RegisterFactory<ButtonDevice>("sdl", std::make_shared<SDLButtonFactory>(*this));
RegisterFactory<AnalogDevice>("sdl", std::make_shared<SDLAnalogFactory>(*this));
analog_factory = std::make_shared<SDLAnalogFactory>(*this);
button_factory = std::make_shared<SDLButtonFactory>(*this);
RegisterFactory<AnalogDevice>("sdl", analog_factory);
RegisterFactory<ButtonDevice>("sdl", button_factory);
// If the frontend is going to manage the event loop, then we dont start one here
start_thread = !SDL_WasInit(SDL_INIT_JOYSTICK);
@@ -485,6 +504,7 @@ SDLState::SDLState() {
LOG_CRITICAL(Input, "SDL_Init(SDL_INIT_JOYSTICK) failed with: {}", SDL_GetError());
return;
}
has_gamecontroller = SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER);
if (SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1") == SDL_FALSE) {
LOG_ERROR(Input, "Failed to set hint for background events with: {}", SDL_GetError());
}
@@ -497,7 +517,7 @@ SDLState::SDLState() {
using namespace std::chrono_literals;
while (initialized) {
SDL_PumpEvents();
std::this_thread::sleep_for(10ms);
std::this_thread::sleep_for(5ms);
}
});
}
@@ -523,65 +543,221 @@ SDLState::~SDLState() {
}
}
static Common::ParamPackage SDLEventToButtonParamPackage(SDLState& state, const SDL_Event& event) {
Common::ParamPackage params({{"engine", "sdl"}});
std::vector<Common::ParamPackage> SDLState::GetInputDevices() {
std::scoped_lock lock(joystick_map_mutex);
std::vector<Common::ParamPackage> devices;
for (const auto& [key, value] : joystick_map) {
for (const auto& joystick : value) {
auto joy = joystick->GetSDLJoystick();
if (auto controller = joystick->GetSDLGameController()) {
std::string name =
fmt::format("{} {}", SDL_GameControllerName(controller), joystick->GetPort());
devices.emplace_back(Common::ParamPackage{
{"class", "sdl"},
{"display", std::move(name)},
{"guid", joystick->GetGUID()},
{"port", std::to_string(joystick->GetPort())},
});
} else if (joy) {
std::string name = fmt::format("{} {}", SDL_JoystickName(joy), joystick->GetPort());
devices.emplace_back(Common::ParamPackage{
{"class", "sdl"},
{"display", std::move(name)},
{"guid", joystick->GetGUID()},
{"port", std::to_string(joystick->GetPort())},
});
}
}
}
return devices;
}
switch (event.type) {
case SDL_JOYAXISMOTION: {
const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which);
params.Set("port", joystick->GetPort());
params.Set("guid", joystick->GetGUID());
params.Set("axis", event.jaxis.axis);
if (event.jaxis.value > 0) {
params.Set("direction", "+");
params.Set("threshold", "0.5");
} else {
params.Set("direction", "-");
params.Set("threshold", "-0.5");
}
break;
}
case SDL_JOYBUTTONUP: {
const auto joystick = state.GetSDLJoystickBySDLID(event.jbutton.which);
params.Set("port", joystick->GetPort());
params.Set("guid", joystick->GetGUID());
params.Set("button", event.jbutton.button);
break;
}
case SDL_JOYHATMOTION: {
const auto joystick = state.GetSDLJoystickBySDLID(event.jhat.which);
params.Set("port", joystick->GetPort());
params.Set("guid", joystick->GetGUID());
params.Set("hat", event.jhat.hat);
switch (event.jhat.value) {
case SDL_HAT_UP:
params.Set("direction", "up");
break;
case SDL_HAT_DOWN:
params.Set("direction", "down");
break;
case SDL_HAT_LEFT:
params.Set("direction", "left");
break;
case SDL_HAT_RIGHT:
params.Set("direction", "right");
break;
default:
return {};
}
break;
}
namespace {
Common::ParamPackage BuildAnalogParamPackageForButton(int port, std::string guid, u8 axis,
float value = 0.1) {
Common::ParamPackage params({{"engine", "sdl"}});
params.Set("port", port);
params.Set("guid", guid);
params.Set("axis", axis);
if (value > 0) {
params.Set("direction", "+");
params.Set("threshold", "0.5");
} else {
params.Set("direction", "-");
params.Set("threshold", "-0.5");
}
return params;
}
namespace Polling {
Common::ParamPackage BuildButtonParamPackageForButton(int port, std::string guid, u8 button) {
Common::ParamPackage params({{"engine", "sdl"}});
params.Set("port", port);
params.Set("guid", guid);
params.Set("button", button);
return params;
}
Common::ParamPackage BuildHatParamPackageForButton(int port, std::string guid, u8 hat, u8 value) {
Common::ParamPackage params({{"engine", "sdl"}});
params.Set("port", port);
params.Set("guid", guid);
params.Set("hat", hat);
switch (value) {
case SDL_HAT_UP:
params.Set("direction", "up");
break;
case SDL_HAT_DOWN:
params.Set("direction", "down");
break;
case SDL_HAT_LEFT:
params.Set("direction", "left");
break;
case SDL_HAT_RIGHT:
params.Set("direction", "right");
break;
default:
return {};
}
return params;
}
Common::ParamPackage SDLEventToButtonParamPackage(SDLState& state, const SDL_Event& event) {
switch (event.type) {
case SDL_JOYAXISMOTION: {
const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which);
return BuildAnalogParamPackageForButton(joystick->GetPort(), joystick->GetGUID(),
event.jaxis.axis, event.jaxis.value);
}
case SDL_JOYBUTTONUP: {
const auto joystick = state.GetSDLJoystickBySDLID(event.jbutton.which);
return BuildButtonParamPackageForButton(joystick->GetPort(), joystick->GetGUID(),
event.jbutton.button);
}
case SDL_JOYHATMOTION: {
const auto joystick = state.GetSDLJoystickBySDLID(event.jhat.which);
return BuildHatParamPackageForButton(joystick->GetPort(), joystick->GetGUID(),
event.jhat.hat, event.jhat.value);
}
}
return {};
}
Common::ParamPackage BuildParamPackageForBinding(int port, const std::string& guid,
const SDL_GameControllerButtonBind& binding) {
switch (binding.bindType) {
case SDL_CONTROLLER_BINDTYPE_AXIS:
return BuildAnalogParamPackageForButton(port, guid, binding.value.axis);
case SDL_CONTROLLER_BINDTYPE_BUTTON:
return BuildButtonParamPackageForButton(port, guid, binding.value.button);
case SDL_CONTROLLER_BINDTYPE_HAT:
return BuildHatParamPackageForButton(port, guid, binding.value.hat.hat,
binding.value.hat.hat_mask);
}
return {};
}
Common::ParamPackage BuildParamPackageForAnalog(int port, const std::string& guid, int axis_x,
int axis_y) {
Common::ParamPackage params;
params.Set("engine", "sdl");
params.Set("port", port);
params.Set("guid", guid);
params.Set("axis_x", axis_x);
params.Set("axis_y", axis_y);
return params;
}
} // Anonymous namespace
ButtonMapping SDLState::GetButtonMappingForDevice(const Common::ParamPackage& params) {
// This list is missing ZL/ZR since those are not considered buttons in SDL GameController.
// We will add those afterwards
// This list also excludes Screenshot since theres not really a mapping for that
std::unordered_map<Settings::NativeButton::Values, SDL_GameControllerButton>
switch_to_sdl_button = {
{Settings::NativeButton::A, SDL_CONTROLLER_BUTTON_B},
{Settings::NativeButton::B, SDL_CONTROLLER_BUTTON_A},
{Settings::NativeButton::X, SDL_CONTROLLER_BUTTON_Y},
{Settings::NativeButton::Y, SDL_CONTROLLER_BUTTON_X},
{Settings::NativeButton::LStick, SDL_CONTROLLER_BUTTON_LEFTSTICK},
{Settings::NativeButton::RStick, SDL_CONTROLLER_BUTTON_RIGHTSTICK},
{Settings::NativeButton::L, SDL_CONTROLLER_BUTTON_LEFTSHOULDER},
{Settings::NativeButton::R, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER},
{Settings::NativeButton::Plus, SDL_CONTROLLER_BUTTON_START},
{Settings::NativeButton::Minus, SDL_CONTROLLER_BUTTON_BACK},
{Settings::NativeButton::DLeft, SDL_CONTROLLER_BUTTON_DPAD_LEFT},
{Settings::NativeButton::DUp, SDL_CONTROLLER_BUTTON_DPAD_UP},
{Settings::NativeButton::DRight, SDL_CONTROLLER_BUTTON_DPAD_RIGHT},
{Settings::NativeButton::DDown, SDL_CONTROLLER_BUTTON_DPAD_DOWN},
{Settings::NativeButton::SL, SDL_CONTROLLER_BUTTON_LEFTSHOULDER},
{Settings::NativeButton::SR, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER},
{Settings::NativeButton::Home, SDL_CONTROLLER_BUTTON_GUIDE},
};
if (!params.Has("guid") || !params.Has("port")) {
return {};
}
const auto joystick = GetSDLJoystickByGUID(params.Get("guid", ""), params.Get("port", 0));
auto controller = joystick->GetSDLGameController();
if (!controller) {
return {};
}
ButtonMapping mapping{};
for (const auto& [switch_button, sdl_button] : switch_to_sdl_button) {
const auto& binding = SDL_GameControllerGetBindForButton(controller, sdl_button);
mapping[switch_button] =
BuildParamPackageForBinding(joystick->GetPort(), joystick->GetGUID(), binding);
}
// Add the missing bindings for ZL/ZR
std::unordered_map<Settings::NativeButton::Values, SDL_GameControllerAxis> switch_to_sdl_axis =
{
{Settings::NativeButton::ZL, SDL_CONTROLLER_AXIS_TRIGGERLEFT},
{Settings::NativeButton::ZR, SDL_CONTROLLER_AXIS_TRIGGERRIGHT},
};
for (const auto& [switch_button, sdl_axis] : switch_to_sdl_axis) {
const auto& binding = SDL_GameControllerGetBindForAxis(controller, sdl_axis);
mapping[switch_button] =
BuildParamPackageForBinding(joystick->GetPort(), joystick->GetGUID(), binding);
}
return mapping;
}
AnalogMapping SDLState::GetAnalogMappingForDevice(const Common::ParamPackage& params) {
if (!params.Has("guid") || !params.Has("port")) {
return {};
}
const auto joystick = GetSDLJoystickByGUID(params.Get("guid", ""), params.Get("port", 0));
auto controller = joystick->GetSDLGameController();
if (!controller) {
return {};
}
AnalogMapping mapping = {};
const auto& binding_left_x =
SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTX);
const auto& binding_left_y =
SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTY);
mapping[Settings::NativeAnalog::LStick] =
BuildParamPackageForAnalog(joystick->GetPort(), joystick->GetGUID(),
binding_left_x.value.axis, binding_left_y.value.axis);
const auto& binding_right_x =
SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_RIGHTX);
const auto& binding_right_y =
SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_RIGHTY);
mapping[Settings::NativeAnalog::RStick] =
BuildParamPackageForAnalog(joystick->GetPort(), joystick->GetGUID(),
binding_right_x.value.axis, binding_right_y.value.axis);
return mapping;
}
namespace Polling {
class SDLPoller : public InputCommon::Polling::DevicePoller {
public:
explicit SDLPoller(SDLState& state_) : state(state_) {}
void Start() override {
void Start(const std::string& device_id) override {
state.event_queue.Clear();
state.polling = true;
}
@@ -601,71 +777,106 @@ public:
Common::ParamPackage GetNextInput() override {
SDL_Event event;
while (state.event_queue.Pop(event)) {
switch (event.type) {
case SDL_JOYAXISMOTION:
if (std::abs(event.jaxis.value / 32767.0) < 0.5) {
break;
}
[[fallthrough]];
case SDL_JOYBUTTONUP:
case SDL_JOYHATMOTION:
return SDLEventToButtonParamPackage(state, event);
const auto package = FromEvent(event);
if (package) {
return *package;
}
}
return {};
}
std::optional<Common::ParamPackage> FromEvent(const SDL_Event& event) {
switch (event.type) {
case SDL_JOYAXISMOTION:
if (std::abs(event.jaxis.value / 32767.0) < 0.5) {
break;
}
[[fallthrough]];
case SDL_JOYBUTTONUP:
case SDL_JOYHATMOTION:
return {SDLEventToButtonParamPackage(state, event)};
}
return {};
}
};
class SDLAnalogPoller final : public SDLPoller {
/**
* Attempts to match the press to a controller joy axis (left/right stick) and if a match
* isn't found, checks if the event matches anything from SDLButtonPoller and uses that
* instead
*/
class SDLAnalogPreferredPoller final : public SDLPoller {
public:
explicit SDLAnalogPoller(SDLState& state_) : SDLPoller(state_) {}
void Start() override {
SDLPoller::Start();
explicit SDLAnalogPreferredPoller(SDLState& state_)
: SDLPoller(state_), button_poller(state_) {}
void Start(const std::string& device_id) override {
SDLPoller::Start(device_id);
// Load the game controller
// Reset stored axes
analog_x_axis = -1;
analog_y_axis = -1;
analog_axes_joystick = -1;
}
Common::ParamPackage GetNextInput() override {
SDL_Event event;
while (state.event_queue.Pop(event)) {
if (event.type != SDL_JOYAXISMOTION || std::abs(event.jaxis.value / 32767.0) < 0.5) {
// Filter out axis events that are below a threshold
if (event.type == SDL_JOYAXISMOTION && std::abs(event.jaxis.value / 32767.0) < 0.5) {
continue;
}
// An analog device needs two axes, so we need to store the axis for later and wait for
// a second SDL event. The axes also must be from the same joystick.
const int axis = event.jaxis.axis;
if (analog_x_axis == -1) {
analog_x_axis = axis;
analog_axes_joystick = event.jaxis.which;
} else if (analog_y_axis == -1 && analog_x_axis != axis &&
analog_axes_joystick == event.jaxis.which) {
analog_y_axis = axis;
// Simplify controller config by testing if game controller support is enabled.
if (event.type == SDL_JOYAXISMOTION) {
const auto axis = event.jaxis.axis;
const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which);
const auto controller = joystick->GetSDLGameController();
if (controller) {
const auto axis_left_x =
SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTX)
.value.axis;
const auto axis_left_y =
SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTY)
.value.axis;
const auto axis_right_x =
SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_RIGHTX)
.value.axis;
const auto axis_right_y =
SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_RIGHTY)
.value.axis;
if (axis == axis_left_x || axis == axis_left_y) {
analog_x_axis = axis_left_x;
analog_y_axis = axis_left_y;
break;
} else if (axis == axis_right_x || axis == axis_right_y) {
analog_x_axis = axis_right_x;
analog_y_axis = axis_right_y;
break;
}
}
}
// If the press wasn't accepted as a joy axis, check for a button press
auto button_press = button_poller.FromEvent(event);
if (button_press) {
return *button_press;
}
}
Common::ParamPackage params;
if (analog_x_axis != -1 && analog_y_axis != -1) {
const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which);
params.Set("engine", "sdl");
params.Set("port", joystick->GetPort());
params.Set("guid", joystick->GetGUID());
params.Set("axis_x", analog_x_axis);
params.Set("axis_y", analog_y_axis);
auto params = BuildParamPackageForAnalog(joystick->GetPort(), joystick->GetGUID(),
analog_x_axis, analog_y_axis);
analog_x_axis = -1;
analog_y_axis = -1;
analog_axes_joystick = -1;
return params;
}
return params;
return {};
}
private:
int analog_x_axis = -1;
int analog_y_axis = -1;
SDL_JoystickID analog_axes_joystick = -1;
SDLButtonPoller button_poller;
};
} // namespace Polling
@@ -673,8 +884,8 @@ SDLState::Pollers SDLState::GetPollers(InputCommon::Polling::DeviceType type) {
Pollers pollers;
switch (type) {
case InputCommon::Polling::DeviceType::Analog:
pollers.emplace_back(std::make_unique<Polling::SDLAnalogPoller>(*this));
case InputCommon::Polling::DeviceType::AnalogPreferred:
pollers.emplace_back(std::make_unique<Polling::SDLAnalogPreferredPoller>(*this));
break;
case InputCommon::Polling::DeviceType::Button:
pollers.emplace_back(std::make_unique<Polling::SDLButtonPoller>(*this));

View File

@@ -50,6 +50,11 @@ public:
std::atomic<bool> polling = false;
Common::SPSCQueue<SDL_Event> event_queue;
std::vector<Common::ParamPackage> GetInputDevices() override;
ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage& params) override;
AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage& params) override;
private:
void InitJoystick(int joystick_index);
void CloseJoystick(SDL_Joystick* sdl_joystick);
@@ -57,6 +62,9 @@ private:
/// Needs to be called before SDL_QuitSubSystem.
void CloseJoysticks();
// Set to true if SDL supports game controller subsystem
bool has_gamecontroller = false;
/// Map of GUID of a list of corresponding virtual Joysticks
std::unordered_map<std::string, std::vector<std::shared_ptr<SDLJoystick>>> joystick_map;
std::mutex joystick_map_mutex;

View File

@@ -0,0 +1,33 @@
// Copyright 2020 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "input_common/settings.h"
namespace Settings {
namespace NativeButton {
const std::array<const char*, NumButtons> mapping = {{
"button_a", "button_b", "button_x", "button_y", "button_lstick",
"button_rstick", "button_l", "button_r", "button_zl", "button_zr",
"button_plus", "button_minus", "button_dleft", "button_dup", "button_dright",
"button_ddown", "button_sl", "button_sr", "button_home", "button_screenshot",
}};
}
namespace NativeAnalog {
const std::array<const char*, NumAnalogs> mapping = {{
"lstick",
"rstick",
}};
}
namespace NativeMouseButton {
const std::array<const char*, NumMouseButtons> mapping = {{
"left",
"right",
"middle",
"forward",
"back",
}};
}
} // namespace Settings

335
src/input_common/settings.h Normal file
View File

@@ -0,0 +1,335 @@
// Copyright 2020 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <array>
#include <string>
#include "common/common_types.h"
namespace Settings {
namespace NativeButton {
enum Values {
A,
B,
X,
Y,
LStick,
RStick,
L,
R,
ZL,
ZR,
Plus,
Minus,
DLeft,
DUp,
DRight,
DDown,
SL,
SR,
Home,
Screenshot,
NumButtons,
};
constexpr int BUTTON_HID_BEGIN = A;
constexpr int BUTTON_NS_BEGIN = Home;
constexpr int BUTTON_HID_END = BUTTON_NS_BEGIN;
constexpr int BUTTON_NS_END = NumButtons;
constexpr int NUM_BUTTONS_HID = BUTTON_HID_END - BUTTON_HID_BEGIN;
constexpr int NUM_BUTTONS_NS = BUTTON_NS_END - BUTTON_NS_BEGIN;
extern const std::array<const char*, NumButtons> mapping;
} // namespace NativeButton
namespace NativeAnalog {
enum Values {
LStick,
RStick,
NumAnalogs,
};
constexpr int STICK_HID_BEGIN = LStick;
constexpr int STICK_HID_END = NumAnalogs;
constexpr int NUM_STICKS_HID = NumAnalogs;
extern const std::array<const char*, NumAnalogs> mapping;
} // namespace NativeAnalog
namespace NativeMouseButton {
enum Values {
Left,
Right,
Middle,
Forward,
Back,
NumMouseButtons,
};
constexpr int MOUSE_HID_BEGIN = Left;
constexpr int MOUSE_HID_END = NumMouseButtons;
constexpr int NUM_MOUSE_HID = NumMouseButtons;
extern const std::array<const char*, NumMouseButtons> mapping;
} // namespace NativeMouseButton
namespace NativeKeyboard {
enum Keys {
None,
Error,
A = 4,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z,
N1,
N2,
N3,
N4,
N5,
N6,
N7,
N8,
N9,
N0,
Enter,
Escape,
Backspace,
Tab,
Space,
Minus,
Equal,
LeftBrace,
RightBrace,
Backslash,
Tilde,
Semicolon,
Apostrophe,
Grave,
Comma,
Dot,
Slash,
CapsLockKey,
F1,
F2,
F3,
F4,
F5,
F6,
F7,
F8,
F9,
F10,
F11,
F12,
SystemRequest,
ScrollLockKey,
Pause,
Insert,
Home,
PageUp,
Delete,
End,
PageDown,
Right,
Left,
Down,
Up,
NumLockKey,
KPSlash,
KPAsterisk,
KPMinus,
KPPlus,
KPEnter,
KP1,
KP2,
KP3,
KP4,
KP5,
KP6,
KP7,
KP8,
KP9,
KP0,
KPDot,
Key102,
Compose,
Power,
KPEqual,
F13,
F14,
F15,
F16,
F17,
F18,
F19,
F20,
F21,
F22,
F23,
F24,
Open,
Help,
Properties,
Front,
Stop,
Repeat,
Undo,
Cut,
Copy,
Paste,
Find,
Mute,
VolumeUp,
VolumeDown,
CapsLockActive,
NumLockActive,
ScrollLockActive,
KPComma,
KPLeftParenthesis,
KPRightParenthesis,
LeftControlKey = 0xE0,
LeftShiftKey,
LeftAltKey,
LeftMetaKey,
RightControlKey,
RightShiftKey,
RightAltKey,
RightMetaKey,
MediaPlayPause,
MediaStopCD,
MediaPrevious,
MediaNext,
MediaEject,
MediaVolumeUp,
MediaVolumeDown,
MediaMute,
MediaWebsite,
MediaBack,
MediaForward,
MediaStop,
MediaFind,
MediaScrollUp,
MediaScrollDown,
MediaEdit,
MediaSleep,
MediaCoffee,
MediaRefresh,
MediaCalculator,
NumKeyboardKeys,
};
static_assert(NumKeyboardKeys == 0xFC, "Incorrect number of keyboard keys.");
enum Modifiers {
LeftControl,
LeftShift,
LeftAlt,
LeftMeta,
RightControl,
RightShift,
RightAlt,
RightMeta,
CapsLock,
ScrollLock,
NumLock,
NumKeyboardMods,
};
constexpr int KEYBOARD_KEYS_HID_BEGIN = None;
constexpr int KEYBOARD_KEYS_HID_END = NumKeyboardKeys;
constexpr int NUM_KEYBOARD_KEYS_HID = NumKeyboardKeys;
constexpr int KEYBOARD_MODS_HID_BEGIN = LeftControl;
constexpr int KEYBOARD_MODS_HID_END = NumKeyboardMods;
constexpr int NUM_KEYBOARD_MODS_HID = NumKeyboardMods;
} // namespace NativeKeyboard
using ButtonsRaw = std::array<std::string, NativeButton::NumButtons>;
using AnalogsRaw = std::array<std::string, NativeAnalog::NumAnalogs>;
using MouseButtonsRaw = std::array<std::string, NativeMouseButton::NumMouseButtons>;
using KeyboardKeysRaw = std::array<std::string, NativeKeyboard::NumKeyboardKeys>;
using KeyboardModsRaw = std::array<std::string, NativeKeyboard::NumKeyboardMods>;
constexpr u32 JOYCON_BODY_NEON_RED = 0xFF3C28;
constexpr u32 JOYCON_BUTTONS_NEON_RED = 0x1E0A0A;
constexpr u32 JOYCON_BODY_NEON_BLUE = 0x0AB9E6;
constexpr u32 JOYCON_BUTTONS_NEON_BLUE = 0x001E1E;
enum class ControllerType {
ProController,
DualJoyconDetached,
LeftJoycon,
RightJoycon,
Handheld,
};
struct PlayerInput {
bool connected;
ControllerType controller_type;
ButtonsRaw buttons;
AnalogsRaw analogs;
std::string lstick_mod;
std::string rstick_mod;
u32 body_color_left;
u32 body_color_right;
u32 button_color_left;
u32 button_color_right;
};
struct TouchscreenInput {
bool enabled;
std::string device;
u32 finger;
u32 diameter_x;
u32 diameter_y;
u32 rotation_angle;
};
} // namespace Settings

View File

@@ -77,10 +77,11 @@ State::State() {
std::make_unique<Client>(status, Settings::values.udp_input_address,
Settings::values.udp_input_port, Settings::values.udp_pad_index);
Input::RegisterFactory<Input::TouchDevice>("cemuhookudp",
std::make_shared<UDPTouchFactory>(status));
Input::RegisterFactory<Input::MotionDevice>("cemuhookudp",
std::make_shared<UDPMotionFactory>(status));
motion_factory = std::make_shared<UDPMotionFactory>(status);
touch_factory = std::make_shared<UDPTouchFactory>(status);
Input::RegisterFactory<Input::MotionDevice>("cemuhookudp", motion_factory);
Input::RegisterFactory<Input::TouchDevice>("cemuhookudp", touch_factory);
}
State::~State() {
@@ -88,6 +89,11 @@ State::~State() {
Input::UnregisterFactory<Input::MotionDevice>("cemuhookudp");
}
std::vector<Common::ParamPackage> State::GetInputDevices() const {
// TODO support binding udp devices
return {};
}
void State::ReloadUDPClient() {
client->ReloadSocket(Settings::values.udp_input_address, Settings::values.udp_input_port,
Settings::values.udp_pad_index);

View File

@@ -5,19 +5,26 @@
#pragma once
#include <memory>
#include <vector>
#include "common/param_package.h"
namespace InputCommon::CemuhookUDP {
class Client;
class UDPMotionFactory;
class UDPTouchFactory;
class State {
public:
State();
~State();
void ReloadUDPClient();
std::vector<Common::ParamPackage> GetInputDevices() const;
private:
std::unique_ptr<Client> client;
std::shared_ptr<UDPMotionFactory> motion_factory;
std::shared_ptr<UDPTouchFactory> touch_factory;
};
std::unique_ptr<State> Init();

View File

@@ -10,7 +10,13 @@
namespace Tegra::Engines {
Fermi2D::Fermi2D(VideoCore::RasterizerInterface& rasterizer) : rasterizer{rasterizer} {}
Fermi2D::Fermi2D() = default;
Fermi2D::~Fermi2D() = default;
void Fermi2D::BindRasterizer(VideoCore::RasterizerInterface& rasterizer_) {
rasterizer = &rasterizer_;
}
void Fermi2D::CallMethod(u32 method, u32 method_argument, bool is_last_call) {
ASSERT_MSG(method < Regs::NUM_REGS,
@@ -87,7 +93,7 @@ void Fermi2D::HandleSurfaceCopy() {
copy_config.src_rect = src_rect;
copy_config.dst_rect = dst_rect;
if (!rasterizer.AccelerateSurfaceCopy(regs.src, regs.dst, copy_config)) {
if (!rasterizer->AccelerateSurfaceCopy(regs.src, regs.dst, copy_config)) {
UNIMPLEMENTED();
}
}

View File

@@ -34,8 +34,11 @@ namespace Tegra::Engines {
class Fermi2D final : public EngineInterface {
public:
explicit Fermi2D(VideoCore::RasterizerInterface& rasterizer);
~Fermi2D() = default;
explicit Fermi2D();
~Fermi2D();
/// Binds a rasterizer to this engine.
void BindRasterizer(VideoCore::RasterizerInterface& rasterizer);
/// Write the value to the register identified by method.
void CallMethod(u32 method, u32 method_argument, bool is_last_call) override;
@@ -149,7 +152,7 @@ public:
};
private:
VideoCore::RasterizerInterface& rasterizer;
VideoCore::RasterizerInterface* rasterizer;
/// Performs the copy from the source surface to the destination surface as configured in the
/// registers.

View File

@@ -16,14 +16,15 @@
namespace Tegra::Engines {
KeplerCompute::KeplerCompute(Core::System& system, VideoCore::RasterizerInterface& rasterizer,
MemoryManager& memory_manager)
: system{system}, rasterizer{rasterizer}, memory_manager{memory_manager}, upload_state{
memory_manager,
regs.upload} {}
KeplerCompute::KeplerCompute(Core::System& system_, MemoryManager& memory_manager_)
: system{system_}, memory_manager{memory_manager_}, upload_state{memory_manager, regs.upload} {}
KeplerCompute::~KeplerCompute() = default;
void KeplerCompute::BindRasterizer(VideoCore::RasterizerInterface& rasterizer_) {
rasterizer = &rasterizer_;
}
void KeplerCompute::CallMethod(u32 method, u32 method_argument, bool is_last_call) {
ASSERT_MSG(method < Regs::NUM_REGS,
"Invalid KeplerCompute register, increase the size of the Regs structure");
@@ -104,11 +105,11 @@ SamplerDescriptor KeplerCompute::AccessSampler(u32 handle) const {
}
VideoCore::GuestDriverProfile& KeplerCompute::AccessGuestDriverProfile() {
return rasterizer.AccessGuestDriverProfile();
return rasterizer->AccessGuestDriverProfile();
}
const VideoCore::GuestDriverProfile& KeplerCompute::AccessGuestDriverProfile() const {
return rasterizer.AccessGuestDriverProfile();
return rasterizer->AccessGuestDriverProfile();
}
void KeplerCompute::ProcessLaunch() {
@@ -119,7 +120,7 @@ void KeplerCompute::ProcessLaunch() {
const GPUVAddr code_addr = regs.code_loc.Address() + launch_description.program_start;
LOG_TRACE(HW_GPU, "Compute invocation launched at address 0x{:016x}", code_addr);
rasterizer.DispatchCompute(code_addr);
rasterizer->DispatchCompute(code_addr);
}
Texture::TICEntry KeplerCompute::GetTICEntry(u32 tic_index) const {

View File

@@ -42,10 +42,12 @@ namespace Tegra::Engines {
class KeplerCompute final : public ConstBufferEngineInterface, public EngineInterface {
public:
explicit KeplerCompute(Core::System& system, VideoCore::RasterizerInterface& rasterizer,
MemoryManager& memory_manager);
explicit KeplerCompute(Core::System& system, MemoryManager& memory_manager);
~KeplerCompute();
/// Binds a rasterizer to this engine.
void BindRasterizer(VideoCore::RasterizerInterface& rasterizer);
static constexpr std::size_t NumConstBuffers = 8;
struct Regs {
@@ -230,11 +232,6 @@ public:
const VideoCore::GuestDriverProfile& AccessGuestDriverProfile() const override;
private:
Core::System& system;
VideoCore::RasterizerInterface& rasterizer;
MemoryManager& memory_manager;
Upload::State upload_state;
void ProcessLaunch();
/// Retrieves information about a specific TIC entry from the TIC buffer.
@@ -242,6 +239,11 @@ private:
/// Retrieves information about a specific TSC entry from the TSC buffer.
Texture::TSCEntry GetTSCEntry(u32 tsc_index) const;
Core::System& system;
MemoryManager& memory_manager;
VideoCore::RasterizerInterface* rasterizer = nullptr;
Upload::State upload_state;
};
#define ASSERT_REG_POSITION(field_name, position) \

View File

@@ -22,14 +22,19 @@ using VideoCore::QueryType;
/// First register id that is actually a Macro call.
constexpr u32 MacroRegistersStart = 0xE00;
Maxwell3D::Maxwell3D(Core::System& system, VideoCore::RasterizerInterface& rasterizer,
MemoryManager& memory_manager)
: system{system}, rasterizer{rasterizer}, memory_manager{memory_manager},
macro_engine{GetMacroEngine(*this)}, upload_state{memory_manager, regs.upload} {
Maxwell3D::Maxwell3D(Core::System& system_, MemoryManager& memory_manager_)
: system{system_}, memory_manager{memory_manager_}, macro_engine{GetMacroEngine(*this)},
upload_state{memory_manager, regs.upload} {
dirty.flags.flip();
InitializeRegisterDefaults();
}
Maxwell3D::~Maxwell3D() = default;
void Maxwell3D::BindRasterizer(VideoCore::RasterizerInterface& rasterizer_) {
rasterizer = &rasterizer_;
}
void Maxwell3D::InitializeRegisterDefaults() {
// Initializes registers to their default values - what games expect them to be at boot. This is
// 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) {
switch (method) {
case MAXWELL3D_REG_INDEX(wait_for_idle): {
rasterizer.WaitForIdle();
rasterizer->WaitForIdle();
break;
}
case MAXWELL3D_REG_INDEX(shadow_ram_control): {
@@ -402,7 +407,7 @@ void Maxwell3D::FlushMMEInlineDraw() {
const bool is_indexed = mme_draw.current_mode == MMEDrawMode::Indexed;
if (ShouldExecute()) {
rasterizer.Draw(is_indexed, true);
rasterizer->Draw(is_indexed, true);
}
// TODO(bunnei): Below, we reset vertex count so that we can use these registers to determine if
@@ -465,7 +470,7 @@ void Maxwell3D::ProcessQueryGet() {
switch (regs.query.query_get.operation) {
case Regs::QueryOperation::Release:
if (regs.query.query_get.fence == 1) {
rasterizer.SignalSemaphore(regs.query.QueryAddress(), regs.query.query_sequence);
rasterizer->SignalSemaphore(regs.query.QueryAddress(), regs.query.query_sequence);
} else {
StampQueryResult(regs.query.query_sequence, regs.query.query_get.short_query == 0);
}
@@ -533,7 +538,7 @@ void Maxwell3D::ProcessQueryCondition() {
void Maxwell3D::ProcessCounterReset() {
switch (regs.counter_reset) {
case Regs::CounterReset::SampleCnt:
rasterizer.ResetCounter(QueryType::SamplesPassed);
rasterizer->ResetCounter(QueryType::SamplesPassed);
break;
default:
LOG_DEBUG(Render_OpenGL, "Unimplemented counter reset={}",
@@ -547,7 +552,7 @@ void Maxwell3D::ProcessSyncPoint() {
const u32 increment = regs.sync_info.increment.Value();
[[maybe_unused]] const u32 cache_flush = regs.sync_info.unknown.Value();
if (increment) {
rasterizer.SignalSyncPoint(sync_point);
rasterizer->SignalSyncPoint(sync_point);
}
}
@@ -570,7 +575,7 @@ void Maxwell3D::DrawArrays() {
const bool is_indexed{regs.index_array.count && !regs.vertex_buffer.count};
if (ShouldExecute()) {
rasterizer.Draw(is_indexed, false);
rasterizer->Draw(is_indexed, false);
}
// 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() {
return 0;
case Regs::QuerySelect::SamplesPassed:
// Deferred.
rasterizer.Query(regs.query.QueryAddress(), VideoCore::QueryType::SamplesPassed,
system.GPU().GetTicks());
rasterizer->Query(regs.query.QueryAddress(), VideoCore::QueryType::SamplesPassed,
system.GPU().GetTicks());
return {};
default:
LOG_DEBUG(HW_GPU, "Unimplemented query select type {}",
@@ -718,7 +723,7 @@ void Maxwell3D::ProcessClearBuffers() {
regs.clear_buffers.R == regs.clear_buffers.B &&
regs.clear_buffers.R == regs.clear_buffers.A);
rasterizer.Clear();
rasterizer->Clear();
}
u32 Maxwell3D::AccessConstBuffer32(ShaderType stage, u64 const_buffer, u64 offset) const {
@@ -752,11 +757,11 @@ SamplerDescriptor Maxwell3D::AccessSampler(u32 handle) const {
}
VideoCore::GuestDriverProfile& Maxwell3D::AccessGuestDriverProfile() {
return rasterizer.AccessGuestDriverProfile();
return rasterizer->AccessGuestDriverProfile();
}
const VideoCore::GuestDriverProfile& Maxwell3D::AccessGuestDriverProfile() const {
return rasterizer.AccessGuestDriverProfile();
return rasterizer->AccessGuestDriverProfile();
}
} // namespace Tegra::Engines

View File

@@ -51,9 +51,11 @@ namespace Tegra::Engines {
class Maxwell3D final : public ConstBufferEngineInterface, public EngineInterface {
public:
explicit Maxwell3D(Core::System& system, VideoCore::RasterizerInterface& rasterizer,
MemoryManager& memory_manager);
~Maxwell3D() = default;
explicit Maxwell3D(Core::System& system, MemoryManager& memory_manager);
~Maxwell3D();
/// Binds a rasterizer to this engine.
void BindRasterizer(VideoCore::RasterizerInterface& rasterizer);
/// Register structure of the Maxwell3D engine.
/// TODO(Subv): This structure will need to be made bigger as more registers are discovered.
@@ -1418,12 +1420,12 @@ public:
return execute_on;
}
VideoCore::RasterizerInterface& GetRasterizer() {
return rasterizer;
VideoCore::RasterizerInterface& Rasterizer() {
return *rasterizer;
}
const VideoCore::RasterizerInterface& GetRasterizer() const {
return rasterizer;
const VideoCore::RasterizerInterface& Rasterizer() const {
return *rasterizer;
}
/// Notify a memory write has happened.
@@ -1460,11 +1462,10 @@ private:
void InitializeRegisterDefaults();
Core::System& system;
VideoCore::RasterizerInterface& rasterizer;
MemoryManager& memory_manager;
VideoCore::RasterizerInterface* rasterizer = nullptr;
/// Start offsets of each macro in macro_memory
std::array<u32, 0x80> macro_positions = {};

View File

@@ -5,15 +5,10 @@
#pragma once
#include <algorithm>
#include <array>
#include <memory>
#include <queue>
#include "common/assert.h"
#include "common/common_types.h"
#include "core/core.h"
#include "core/memory.h"
#include "core/settings.h"
#include "video_core/gpu.h"
#include "video_core/memory_manager.h"
#include "video_core/rasterizer_interface.h"

View File

@@ -27,21 +27,28 @@ namespace Tegra {
MICROPROFILE_DEFINE(GPU_wait, "GPU", "Wait for the GPU", MP_RGB(128, 128, 192));
GPU::GPU(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer_, bool is_async)
: system{system}, renderer{std::move(renderer_)}, is_async{is_async} {
auto& rasterizer{renderer->Rasterizer()};
memory_manager = std::make_unique<Tegra::MemoryManager>(system, rasterizer);
dma_pusher = std::make_unique<Tegra::DmaPusher>(system, *this);
maxwell_3d = std::make_unique<Engines::Maxwell3D>(system, rasterizer, *memory_manager);
fermi_2d = std::make_unique<Engines::Fermi2D>(rasterizer);
kepler_compute = std::make_unique<Engines::KeplerCompute>(system, rasterizer, *memory_manager);
maxwell_dma = std::make_unique<Engines::MaxwellDMA>(system, *memory_manager);
kepler_memory = std::make_unique<Engines::KeplerMemory>(system, *memory_manager);
shader_notify = std::make_unique<VideoCore::ShaderNotify>();
}
GPU::GPU(Core::System& system_, bool is_async_)
: system{system_}, dma_pusher{std::make_unique<Tegra::DmaPusher>(system, *this)},
memory_manager{std::make_unique<Tegra::MemoryManager>(system)},
maxwell_3d{std::make_unique<Engines::Maxwell3D>(system, *memory_manager)},
fermi_2d{std::make_unique<Engines::Fermi2D>()},
kepler_compute{std::make_unique<Engines::KeplerCompute>(system, *memory_manager)},
maxwell_dma{std::make_unique<Engines::MaxwellDMA>(system, *memory_manager)},
kepler_memory{std::make_unique<Engines::KeplerMemory>(system, *memory_manager)},
shader_notify{std::make_unique<VideoCore::ShaderNotify>()}, is_async{is_async_} {}
GPU::~GPU() = default;
void GPU::BindRenderer(std::unique_ptr<VideoCore::RendererBase> renderer_) {
renderer = std::move(renderer_);
VideoCore::RasterizerInterface& rasterizer = renderer->Rasterizer();
memory_manager->BindRasterizer(rasterizer);
maxwell_3d->BindRasterizer(rasterizer);
fermi_2d->BindRasterizer(rasterizer);
kepler_compute->BindRasterizer(rasterizer);
}
Engines::Maxwell3D& GPU::Maxwell3D() {
return *maxwell_3d;
}

View File

@@ -142,11 +142,6 @@ class MemoryManager;
class GPU {
public:
explicit GPU(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer,
bool is_async);
virtual ~GPU();
struct MethodCall {
u32 method{};
u32 argument{};
@@ -162,6 +157,12 @@ public:
method_count(method_count) {}
};
explicit GPU(Core::System& system, bool is_async);
virtual ~GPU();
/// Binds a renderer to the GPU.
void BindRenderer(std::unique_ptr<VideoCore::RendererBase> renderer);
/// Calls a GPU method.
void CallMethod(const MethodCall& method_call);
@@ -345,8 +346,8 @@ private:
bool ExecuteMethodOnEngine(u32 method);
protected:
std::unique_ptr<Tegra::DmaPusher> dma_pusher;
Core::System& system;
std::unique_ptr<Tegra::DmaPusher> dma_pusher;
std::unique_ptr<VideoCore::RendererBase> renderer;
private:

View File

@@ -10,16 +10,14 @@
namespace VideoCommon {
GPUAsynch::GPUAsynch(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer_,
std::unique_ptr<Core::Frontend::GraphicsContext>&& context)
: GPU(system, std::move(renderer_), true), gpu_thread{system},
cpu_context(renderer->GetRenderWindow().CreateSharedContext()),
gpu_context(std::move(context)) {}
GPUAsynch::GPUAsynch(Core::System& system) : GPU{system, true}, gpu_thread{system} {}
GPUAsynch::~GPUAsynch() = default;
void GPUAsynch::Start() {
gpu_thread.StartThread(*renderer, *gpu_context, *dma_pusher);
gpu_thread.StartThread(*renderer, renderer->Context(), *dma_pusher);
cpu_context = renderer->GetRenderWindow().CreateSharedContext();
cpu_context->MakeCurrent();
}
void GPUAsynch::ObtainContext() {

View File

@@ -20,8 +20,7 @@ namespace VideoCommon {
/// Implementation of GPU interface that runs the GPU asynchronously
class GPUAsynch final : public Tegra::GPU {
public:
explicit GPUAsynch(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer,
std::unique_ptr<Core::Frontend::GraphicsContext>&& context);
explicit GPUAsynch(Core::System& system);
~GPUAsynch() override;
void Start() override;
@@ -42,7 +41,6 @@ protected:
private:
GPUThread::ThreadManager gpu_thread;
std::unique_ptr<Core::Frontend::GraphicsContext> cpu_context;
std::unique_ptr<Core::Frontend::GraphicsContext> gpu_context;
};
} // namespace VideoCommon

View File

@@ -7,20 +7,18 @@
namespace VideoCommon {
GPUSynch::GPUSynch(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer,
std::unique_ptr<Core::Frontend::GraphicsContext>&& context)
: GPU(system, std::move(renderer), false), context{std::move(context)} {}
GPUSynch::GPUSynch(Core::System& system) : GPU{system, false} {}
GPUSynch::~GPUSynch() = default;
void GPUSynch::Start() {}
void GPUSynch::ObtainContext() {
context->MakeCurrent();
renderer->Context().MakeCurrent();
}
void GPUSynch::ReleaseContext() {
context->DoneCurrent();
renderer->Context().DoneCurrent();
}
void GPUSynch::PushGPUEntries(Tegra::CommandList&& entries) {

View File

@@ -19,8 +19,7 @@ namespace VideoCommon {
/// Implementation of GPU interface that runs the GPU synchronously
class GPUSynch final : public Tegra::GPU {
public:
explicit GPUSynch(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer,
std::unique_ptr<Core::Frontend::GraphicsContext>&& context);
explicit GPUSynch(Core::System& system);
~GPUSynch() override;
void Start() override;
@@ -36,9 +35,6 @@ public:
protected:
void TriggerCpuInterrupt([[maybe_unused]] u32 syncpoint_id,
[[maybe_unused]] u32 value) const override {}
private:
std::unique_ptr<Core::Frontend::GraphicsContext> context;
};
} // namespace VideoCommon

View File

@@ -24,7 +24,7 @@ void HLE_771BB18C62444DA0(Engines::Maxwell3D& maxwell3d, const std::vector<u32>&
maxwell3d.regs.index_array.first = parameters[4];
if (maxwell3d.ShouldExecute()) {
maxwell3d.GetRasterizer().Draw(true, true);
maxwell3d.Rasterizer().Draw(true, true);
}
maxwell3d.regs.index_array.count = 0;
maxwell3d.mme_draw.instance_count = 0;
@@ -42,7 +42,7 @@ void HLE_0D61FC9FAAC9FCAD(Engines::Maxwell3D& maxwell3d, const std::vector<u32>&
maxwell3d.mme_draw.instance_count = count;
if (maxwell3d.ShouldExecute()) {
maxwell3d.GetRasterizer().Draw(false, true);
maxwell3d.Rasterizer().Draw(false, true);
}
maxwell3d.regs.vertex_buffer.count = 0;
maxwell3d.mme_draw.instance_count = 0;
@@ -65,7 +65,7 @@ void HLE_0217920100488FF7(Engines::Maxwell3D& maxwell3d, const std::vector<u32>&
maxwell3d.regs.draw.topology.Assign(
static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[0]));
if (maxwell3d.ShouldExecute()) {
maxwell3d.GetRasterizer().Draw(true, true);
maxwell3d.Rasterizer().Draw(true, true);
}
maxwell3d.regs.reg_array[0x446] = 0x0; // vertex id base?
maxwell3d.regs.index_array.count = 0;

View File

@@ -34,7 +34,6 @@ void MacroInterpreterImpl::Execute(const std::vector<u32>& parameters, u32 metho
this->parameters = std::make_unique<u32[]>(num_parameters);
}
std::memcpy(this->parameters.get(), parameters.data(), num_parameters * sizeof(u32));
this->num_parameters = num_parameters;
// Execute the code until we hit an exit condition.
bool keep_executing = true;

View File

@@ -14,11 +14,15 @@
namespace Tegra {
MemoryManager::MemoryManager(Core::System& system, VideoCore::RasterizerInterface& rasterizer)
: system{system}, rasterizer{rasterizer}, page_table(page_table_size) {}
MemoryManager::MemoryManager(Core::System& system_)
: system{system_}, page_table(page_table_size) {}
MemoryManager::~MemoryManager() = default;
void MemoryManager::BindRasterizer(VideoCore::RasterizerInterface& rasterizer_) {
rasterizer = &rasterizer_;
}
GPUVAddr MemoryManager::UpdateRange(GPUVAddr gpu_addr, PageEntry page_entry, std::size_t size) {
u64 remaining_size{size};
for (u64 offset{}; offset < size; offset += page_size) {
@@ -217,7 +221,7 @@ void MemoryManager::ReadBlock(GPUVAddr gpu_src_addr, void* dest_buffer, std::siz
// Flush must happen on the rasterizer interface, such that memory is always synchronous
// when it is read (even when in asynchronous GPU mode). Fixes Dead Cells title menu.
rasterizer.FlushRegion(src_addr, copy_amount);
rasterizer->FlushRegion(src_addr, copy_amount);
system.Memory().ReadBlockUnsafe(src_addr, dest_buffer, copy_amount);
}
@@ -266,7 +270,7 @@ void MemoryManager::WriteBlock(GPUVAddr gpu_dest_addr, const void* src_buffer, s
// Invalidate must happen on the rasterizer interface, such that memory is always
// synchronous when it is written (even when in asynchronous GPU mode).
rasterizer.InvalidateRegion(dest_addr, copy_amount);
rasterizer->InvalidateRegion(dest_addr, copy_amount);
system.Memory().WriteBlockUnsafe(dest_addr, src_buffer, copy_amount);
}
@@ -312,10 +316,10 @@ void MemoryManager::CopyBlockUnsafe(GPUVAddr gpu_dest_addr, GPUVAddr gpu_src_add
WriteBlockUnsafe(gpu_dest_addr, tmp_buffer.data(), size);
}
bool MemoryManager::IsGranularRange(GPUVAddr gpu_addr, std::size_t size) {
bool MemoryManager::IsGranularRange(GPUVAddr gpu_addr, std::size_t size) const {
const auto cpu_addr{GpuToCpuAddress(gpu_addr)};
if (!cpu_addr) {
return {};
return false;
}
const std::size_t page{(*cpu_addr & Core::Memory::PAGE_MASK) + size};
return page <= Core::Memory::PAGE_SIZE;

View File

@@ -68,9 +68,12 @@ static_assert(sizeof(PageEntry) == 4, "PageEntry is too large");
class MemoryManager final {
public:
explicit MemoryManager(Core::System& system, VideoCore::RasterizerInterface& rasterizer);
explicit MemoryManager(Core::System& system);
~MemoryManager();
/// Binds a renderer to the memory manager.
void BindRasterizer(VideoCore::RasterizerInterface& rasterizer);
std::optional<VAddr> GpuToCpuAddress(GPUVAddr addr) const;
template <typename T>
@@ -109,7 +112,7 @@ public:
/**
* IsGranularRange checks if a gpu region can be simply read with a pointer.
*/
bool IsGranularRange(GPUVAddr gpu_addr, std::size_t size);
bool IsGranularRange(GPUVAddr gpu_addr, std::size_t size) const;
GPUVAddr Map(VAddr cpu_addr, GPUVAddr gpu_addr, std::size_t size);
GPUVAddr MapAllocate(VAddr cpu_addr, std::size_t size, std::size_t align);
@@ -141,7 +144,7 @@ private:
Core::System& system;
VideoCore::RasterizerInterface& rasterizer;
VideoCore::RasterizerInterface* rasterizer = nullptr;
std::vector<PageEntry> page_table;
};

View File

@@ -9,7 +9,9 @@
namespace VideoCore {
RendererBase::RendererBase(Core::Frontend::EmuWindow& window) : render_window{window} {
RendererBase::RendererBase(Core::Frontend::EmuWindow& window_,
std::unique_ptr<Core::Frontend::GraphicsContext> context_)
: render_window{window_}, context{std::move(context_)} {
RefreshBaseSettings();
}

View File

@@ -15,7 +15,8 @@
namespace Core::Frontend {
class EmuWindow;
}
class GraphicsContext;
} // namespace Core::Frontend
namespace VideoCore {
@@ -25,14 +26,15 @@ struct RendererSettings {
// Screenshot
std::atomic<bool> screenshot_requested{false};
void* screenshot_bits;
void* screenshot_bits{};
std::function<void()> screenshot_complete_callback;
Layout::FramebufferLayout screenshot_framebuffer_layout;
};
class RendererBase : NonCopyable {
public:
explicit RendererBase(Core::Frontend::EmuWindow& window);
explicit RendererBase(Core::Frontend::EmuWindow& window,
std::unique_ptr<Core::Frontend::GraphicsContext> context);
virtual ~RendererBase();
/// Initialize the renderer
@@ -68,6 +70,14 @@ public:
return *rasterizer;
}
Core::Frontend::GraphicsContext& Context() {
return *context;
}
const Core::Frontend::GraphicsContext& Context() const {
return *context;
}
Core::Frontend::EmuWindow& GetRenderWindow() {
return render_window;
}
@@ -94,6 +104,7 @@ public:
protected:
Core::Frontend::EmuWindow& render_window; ///< Reference to the render window handle.
std::unique_ptr<RasterizerInterface> rasterizer;
std::unique_ptr<Core::Frontend::GraphicsContext> context;
f32 m_current_fps = 0.0f; ///< Current framerate, should be set by the renderer
int m_current_frame = 0; ///< Current frame, should be set by the renderer

View File

@@ -4,16 +4,17 @@
#include "common/assert.h"
#include <glad/glad.h>
#include "video_core/renderer_opengl/gl_buffer_cache.h"
#include "video_core/renderer_opengl/gl_fence_manager.h"
namespace OpenGL {
GLInnerFence::GLInnerFence(u32 payload, bool is_stubbed)
: VideoCommon::FenceBase(payload, is_stubbed), sync_object{} {}
GLInnerFence::GLInnerFence(u32 payload, bool is_stubbed) : FenceBase(payload, is_stubbed) {}
GLInnerFence::GLInnerFence(GPUVAddr address, u32 payload, bool is_stubbed)
: VideoCommon::FenceBase(address, payload, is_stubbed), sync_object{} {}
: FenceBase(address, payload, is_stubbed) {}
GLInnerFence::~GLInnerFence() = default;

View File

@@ -5,7 +5,6 @@
#pragma once
#include <memory>
#include <glad/glad.h>
#include "common/common_types.h"
#include "video_core/fence_manager.h"

View File

@@ -214,20 +214,20 @@ std::optional<std::vector<ShaderDiskCacheEntry>> ShaderDiskCacheOpenGL::LoadTran
// Skip games without title id
const bool has_title_id = system.CurrentProcess()->GetTitleID() != 0;
if (!Settings::values.use_disk_shader_cache.GetValue() || !has_title_id) {
return {};
return std::nullopt;
}
Common::FS::IOFile file(GetTransferablePath(), "rb");
if (!file.IsOpen()) {
LOG_INFO(Render_OpenGL, "No transferable shader cache found");
is_usable = true;
return {};
return std::nullopt;
}
u32 version{};
if (file.ReadBytes(&version, sizeof(version)) != sizeof(version)) {
LOG_ERROR(Render_OpenGL, "Failed to get transferable cache version, skipping it");
return {};
return std::nullopt;
}
if (version < NativeVersion) {
@@ -235,12 +235,12 @@ std::optional<std::vector<ShaderDiskCacheEntry>> ShaderDiskCacheOpenGL::LoadTran
file.Close();
InvalidateTransferable();
is_usable = true;
return {};
return std::nullopt;
}
if (version > NativeVersion) {
LOG_WARNING(Render_OpenGL, "Transferable shader cache was generated with a newer version "
"of the emulator, skipping");
return {};
return std::nullopt;
}
// Version is valid, load the shaders
@@ -249,7 +249,7 @@ std::optional<std::vector<ShaderDiskCacheEntry>> ShaderDiskCacheOpenGL::LoadTran
ShaderDiskCacheEntry& entry = entries.emplace_back();
if (!entry.Load(file)) {
LOG_ERROR(Render_OpenGL, "Failed to load transferable raw entry, skipping");
return {};
return std::nullopt;
}
}
@@ -290,12 +290,12 @@ std::optional<std::vector<ShaderDiskCachePrecompiled>> ShaderDiskCacheOpenGL::Lo
ShaderCacheVersionHash file_hash{};
if (!LoadArrayFromPrecompiled(file_hash.data(), file_hash.size())) {
precompiled_cache_virtual_file_offset = 0;
return {};
return std::nullopt;
}
if (GetShaderCacheVersionHash() != file_hash) {
LOG_INFO(Render_OpenGL, "Precompiled cache is from another version of the emulator");
precompiled_cache_virtual_file_offset = 0;
return {};
return std::nullopt;
}
std::vector<ShaderDiskCachePrecompiled> entries;
@@ -305,15 +305,16 @@ std::optional<std::vector<ShaderDiskCachePrecompiled>> ShaderDiskCacheOpenGL::Lo
if (!LoadObjectFromPrecompiled(entry.unique_identifier) ||
!LoadObjectFromPrecompiled(entry.binary_format) ||
!LoadObjectFromPrecompiled(binary_size)) {
return {};
return std::nullopt;
}
entry.binary.resize(binary_size);
if (!LoadArrayFromPrecompiled(entry.binary.data(), entry.binary.size())) {
return {};
return std::nullopt;
}
}
return entries;
return std::move(entries);
}
void ShaderDiskCacheOpenGL::InvalidateTransferable() {

View File

@@ -403,7 +403,7 @@ void CachedSurface::DecorateSurfaceName() {
LabelGLObject(GL_TEXTURE, texture.handle, GetGpuAddr(), params.TargetName());
}
void CachedSurfaceView::DecorateViewName(GPUVAddr gpu_addr, std::string prefix) {
void CachedSurfaceView::DecorateViewName(GPUVAddr gpu_addr, const std::string& prefix) {
LabelGLObject(GL_TEXTURE, main_view.handle, gpu_addr, prefix);
}

View File

@@ -90,7 +90,7 @@ public:
Tegra::Texture::SwizzleSource z_source,
Tegra::Texture::SwizzleSource w_source);
void DecorateViewName(GPUVAddr gpu_addr, std::string prefix);
void DecorateViewName(GPUVAddr gpu_addr, const std::string& prefix);
void MarkAsModified(u64 tick) {
surface.MarkAsModified(true, tick);

View File

@@ -313,10 +313,11 @@ public:
}
};
RendererOpenGL::RendererOpenGL(Core::Frontend::EmuWindow& emu_window, Core::System& system,
Core::Frontend::GraphicsContext& context)
: RendererBase{emu_window}, emu_window{emu_window}, system{system}, context{context},
program_manager{device}, has_debug_tool{HasDebugTool()} {}
RendererOpenGL::RendererOpenGL(Core::System& system_, Core::Frontend::EmuWindow& emu_window_,
Tegra::GPU& gpu_,
std::unique_ptr<Core::Frontend::GraphicsContext> context_)
: RendererBase{emu_window_, std::move(context_)}, system{system_},
emu_window{emu_window_}, gpu{gpu_}, program_manager{device}, has_debug_tool{HasDebugTool()} {}
RendererOpenGL::~RendererOpenGL() = default;
@@ -384,7 +385,7 @@ void RendererOpenGL::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
if (has_debug_tool) {
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
Present(0);
context.SwapBuffers();
context->SwapBuffers();
}
}

View File

@@ -56,8 +56,9 @@ class FrameMailbox;
class RendererOpenGL final : public VideoCore::RendererBase {
public:
explicit RendererOpenGL(Core::Frontend::EmuWindow& emu_window, Core::System& system,
Core::Frontend::GraphicsContext& context);
explicit RendererOpenGL(Core::System& system, Core::Frontend::EmuWindow& emu_window,
Tegra::GPU& gpu,
std::unique_ptr<Core::Frontend::GraphicsContext> context);
~RendererOpenGL() override;
bool Init() override;
@@ -93,9 +94,9 @@ private:
bool Present(int timeout_ms);
Core::Frontend::EmuWindow& emu_window;
Core::System& system;
Core::Frontend::GraphicsContext& context;
Core::Frontend::EmuWindow& emu_window;
Tegra::GPU& gpu;
const Device device;
StateTracker state_tracker{system};
@@ -120,7 +121,7 @@ private:
std::vector<u8> gl_framebuffer_data;
/// Used for transforming the framebuffer orientation
Tegra::FramebufferConfig::TransformFlags framebuffer_transform_flags;
Tegra::FramebufferConfig::TransformFlags framebuffer_transform_flags{};
Common::Rectangle<int> framebuffer_crop_rect;
/// Frame presentation mailbox

View File

@@ -237,8 +237,10 @@ std::string BuildCommaSeparatedExtensions(std::vector<std::string> available_ext
} // Anonymous namespace
RendererVulkan::RendererVulkan(Core::Frontend::EmuWindow& window, Core::System& system)
: RendererBase(window), system{system} {}
RendererVulkan::RendererVulkan(Core::System& system_, Core::Frontend::EmuWindow& emu_window,
Tegra::GPU& gpu_,
std::unique_ptr<Core::Frontend::GraphicsContext> context)
: RendererBase{emu_window, std::move(context)}, system{system_}, gpu{gpu_} {}
RendererVulkan::~RendererVulkan() {
ShutDown();

Some files were not shown because too many files have changed in this diff Show More