Compare commits
381 Commits
Author | SHA1 | Date | |
---|---|---|---|
210f475484 | |||
ddb6493896 | |||
f631933e60 | |||
5ff6ea6d82 | |||
c2d9c6955d | |||
fbe0c211c1 | |||
db0f3c0b74 | |||
34447d7359 | |||
5f771f5661 | |||
93cd327873 | |||
12cbacffca | |||
437c78e198 | |||
f09bba82b9 | |||
93d78f9ac4 | |||
cd7b52f995 | |||
7f96dbc024 | |||
3e5c211394 | |||
153b8bfc7c | |||
c6a699414a | |||
2563f88de0 | |||
b0b7843d5c | |||
6ed613a6e6 | |||
64079c034c | |||
17354d59d1 | |||
0c445184c1 | |||
511b558ddc | |||
9b8625d999 | |||
b12ea343d0 | |||
abaa35ad3a | |||
effd546331 | |||
492a046335 | |||
550fd4a733 | |||
33f544fd92 | |||
b423197619 | |||
8edfb2bc7b | |||
ddefb4fff4 | |||
2efd74b9cb | |||
8c61ddd49d | |||
7b2225c6b0 | |||
fe15c77d30 | |||
5e9678c8fa | |||
773e239db7 | |||
42750a74f8 | |||
3ab0a71c7b | |||
6e784e0aca | |||
5a0aa074b6 | |||
93aa40f1fb | |||
bedee64af5 | |||
86931cc3f1 | |||
2be8b6ea45 | |||
f95b7c5877 | |||
eb528ae0f0 | |||
487261592e | |||
9e04e6cba1 | |||
4cf2419e6c | |||
440abac9f8 | |||
732714349e | |||
016262514d | |||
326749498b | |||
fec8291c17 | |||
c5d9e67cb2 | |||
e5261228d7 | |||
e61c09bc85 | |||
ac2444f908 | |||
9c6071a645 | |||
fa32ef9275 | |||
7805d27e67 | |||
6c515e1822 | |||
8a363b5df2 | |||
2b5abac809 | |||
c19c8bbade | |||
1c7a90ef35 | |||
3b46bb73f7 | |||
2457cfc911 | |||
515fc32b21 | |||
0684b00b3c | |||
02b5c7ea89 | |||
801b71a128 | |||
12c5f6ee89 | |||
79a1314ee4 | |||
e9848339dd | |||
6e28a4dd13 | |||
7c989f88bd | |||
16fa983704 | |||
40daca5684 | |||
981e0c082d | |||
cebfa54467 | |||
fc20d9b925 | |||
0a75b73fa4 | |||
46b7c905f5 | |||
40f2bd37e3 | |||
9288ffd26d | |||
2cdc82cb91 | |||
6aa8d71588 | |||
9becbd7d72 | |||
e055217292 | |||
fbaf62c230 | |||
b186ec9fc5 | |||
0191e2396a | |||
e96299eef5 | |||
ff53dcf560 | |||
2de78a2d55 | |||
b29ded1d60 | |||
9860bfb2cd | |||
f6ada8d169 | |||
42d31f646d | |||
07fc3ded68 | |||
fd01259d2b | |||
7ffe7f8442 | |||
2b2ce68f07 | |||
bc53d00463 | |||
bddb2a1483 | |||
e3bacfa774 | |||
7c2f07d124 | |||
ede5b3c324 | |||
df5be5812f | |||
bc392e55df | |||
fffc3ed193 | |||
7d160e98fd | |||
bf96bc84a8 | |||
91e4caaa69 | |||
efbd29463d | |||
7608cb37ab | |||
d604e98227 | |||
58907e2c29 | |||
649d372f7d | |||
f9a538bb0f | |||
f92921a6d1 | |||
32d21ddf17 | |||
82f90704a0 | |||
f978d3726a | |||
6f28c4abad | |||
105c9712c1 | |||
4d804ed45e | |||
4a27d29412 | |||
5bd2c58ad6 | |||
cf4c78b9c8 | |||
52aa4b6c22 | |||
5a02433080 | |||
915a0f7173 | |||
0cc266ff19 | |||
9a1b74799d | |||
638f3761f3 | |||
193ca3c9a2 | |||
eb0bb36bbf | |||
0e95a8271a | |||
76b474e97b | |||
27ee86f33b | |||
f7ec310231 | |||
e94d24f508 | |||
2bf4555591 | |||
86de288142 | |||
f35aa8e9d6 | |||
0e8e735a6d | |||
0003a7c118 | |||
2cdcfe46d8 | |||
fe30c03cac | |||
5813b2e354 | |||
af1906ea04 | |||
68848000f7 | |||
d98da47a0f | |||
306f7e93a0 | |||
8954ff3af2 | |||
d2f3adbf69 | |||
d511c845b7 | |||
21c9ac6240 | |||
81c9052847 | |||
9367e3c35d | |||
52cf141874 | |||
8a352df3c6 | |||
c545c59851 | |||
96ea4e8c8e | |||
b8f48bcf64 | |||
6966211e07 | |||
57524a4c8a | |||
f4539c49d8 | |||
12c62fdbc2 | |||
e3c6be5e29 | |||
4741a05df9 | |||
c6676007bf | |||
92b0b7d753 | |||
232237bf28 | |||
c27e453fd3 | |||
0e037d0213 | |||
0dca1fbe12 | |||
35d91a0e58 | |||
a73a5d7e85 | |||
832a5e8852 | |||
96d1f0da2d | |||
597388ecda | |||
1cf6d7b7bb | |||
7bc9d0cdad | |||
dc0dbc50ab | |||
994f4dc77d | |||
c9e297b74c | |||
dd514a115c | |||
7e0b4bd538 | |||
378080eb87 | |||
e8f5e97fa4 | |||
f3873620a3 | |||
986ac9ff83 | |||
42b9c1e8fe | |||
3b375525fb | |||
e6658c133c | |||
5b42a4d2c4 | |||
8f0c89ffd6 | |||
2c9715acf6 | |||
274af65f69 | |||
4ca78eded5 | |||
6cb6b15612 | |||
2725e40838 | |||
c2e4c8f98e | |||
b53e7ffd46 | |||
ac66643346 | |||
21e88f17f6 | |||
5626f2ca1c | |||
402f05b8ef | |||
fb27042e01 | |||
69a9de33d3 | |||
bba51c2eeb | |||
fc26189fe1 | |||
a40c90e7dd | |||
f864a49014 | |||
ecbf303266 | |||
b3bf05356b | |||
cb4b58052f | |||
f8cdd5f484 | |||
22202be394 | |||
17ba217940 | |||
aae4595bdb | |||
880fd3cfcb | |||
f679f25e08 | |||
c2709b3bdd | |||
2b6e81deea | |||
7271f1b18e | |||
5fda543f84 | |||
95c06de4c1 | |||
49c63ea077 | |||
531da8a1c0 | |||
5cbdfbc7a4 | |||
e0544dd9c7 | |||
aa784c3e5e | |||
9205077590 | |||
0ed40c7175 | |||
40d47b7aa2 | |||
ec0bb74968 | |||
42f7f98666 | |||
95bad6995c | |||
3d42995822 | |||
9095941fd1 | |||
ba71141bdc | |||
0a0675a7f6 | |||
a7c6e6a8cf | |||
0bc8151c7e | |||
40c17673f5 | |||
a8950d6ac4 | |||
162798b026 | |||
1b28ecd63e | |||
895d9b53bc | |||
0e06aace45 | |||
adf4ebcd60 | |||
470a8031a4 | |||
5440d4ad5c | |||
dde208b480 | |||
4c3d2d5d75 | |||
fab11ba3f1 | |||
332891b5ff | |||
7df4fcada7 | |||
d6698680be | |||
e5c9838b0b | |||
f8ec878796 | |||
9ff21f9ab6 | |||
aa021085cf | |||
1f5d881860 | |||
1f664100bd | |||
1f5e1ffa80 | |||
264438ff19 | |||
3b8ac1641a | |||
4250732353 | |||
4d1579acbf | |||
6279f5e430 | |||
b7d2bff6aa | |||
7c327fecb3 | |||
cc1a933a2f | |||
dd574146fb | |||
2c94ac455e | |||
e18d258fa0 | |||
36f10df775 | |||
680e548022 | |||
21c4176157 | |||
3b4ff2d6d9 | |||
12504f280c | |||
250fc51374 | |||
206e0882c2 | |||
609abc8b9b | |||
cee7121058 | |||
cd124bda58 | |||
9f12e50a54 | |||
097562bc6c | |||
db4242c5dc | |||
4dd77316f7 | |||
3f98369a17 | |||
c26aeefe03 | |||
666e05f5cb | |||
8d9d508dc7 | |||
e27f5522e2 | |||
add2a9d151 | |||
9e50dd99d7 | |||
0dec91bb42 | |||
d9b63353b0 | |||
eabd0ec93f | |||
138d5dc64a | |||
3e68a87d63 | |||
69b6ef7a4a | |||
40e87c634e | |||
79d1c190db | |||
2bc88467eb | |||
baf8752e74 | |||
d5e4378aea | |||
6dbcdfea47 | |||
c5258cf082 | |||
5c89e22bb9 | |||
11ecff2ff0 | |||
4c3f09644a | |||
e187a8870a | |||
a64fee29dc | |||
9ef94c8292 | |||
915d6d044c | |||
a4780ab33b | |||
a947a45d81 | |||
9db73f74cf | |||
a1efd87c45 | |||
49be977588 | |||
c95be55091 | |||
63dedbda86 | |||
c532118d94 | |||
52d6f2e656 | |||
c9bc4eaf58 | |||
3249f8ff41 | |||
1b41b285ac | |||
f5a6f45b27 | |||
210557951b | |||
4c2d9ff3ff | |||
8198b99935 | |||
460f96967d | |||
7ca779a26d | |||
b5032b3c91 | |||
f0a3dff136 | |||
f659dcb9d8 | |||
a34fb0e939 | |||
21ce8a9b80 | |||
9ecbee8032 | |||
80519af67d | |||
26e30faff3 | |||
0992310b76 | |||
009c1101d2 | |||
ba95ee54ab | |||
4ce4299ca2 | |||
17620d18db | |||
9f1cf6458c | |||
67b4e63cff | |||
c05c688ee8 | |||
b2623dc27d | |||
5131b71437 | |||
7870423671 | |||
b72916fbc1 | |||
da073fce61 | |||
1fc90e57d2 | |||
eafcc314a9 | |||
6e9bd4de13 | |||
05a41b31bc | |||
eed17f963e | |||
c09c0c002d | |||
d56d335c0b | |||
23c844b2aa | |||
81691b9e37 | |||
2dc422bc14 | |||
a80fa5e33f | |||
954e995321 | |||
dad9ab6bb6 | |||
f0562b9c75 |
@ -1,8 +1,7 @@
|
||||
# Remove the line below if you want to inherit .editorconfig settings from higher directories
|
||||
root = true
|
||||
|
||||
# C# files
|
||||
[*.cs]
|
||||
[*]
|
||||
|
||||
#### Core EditorConfig Options ####
|
||||
|
||||
@ -12,8 +11,18 @@ indent_style = space
|
||||
tab_width = 4
|
||||
|
||||
# New line preferences
|
||||
end_of_line = crlf
|
||||
insert_final_newline = false
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
|
||||
# JSON files
|
||||
[*.json]
|
||||
|
||||
# Indentation and spacing
|
||||
indent_size = 2
|
||||
tab_width = 2
|
||||
|
||||
# C# files
|
||||
[*.cs]
|
||||
|
||||
#### .NET Coding Conventions ####
|
||||
|
||||
@ -59,10 +68,14 @@ dotnet_style_prefer_simplified_interpolation = true:suggestion
|
||||
dotnet_style_readonly_field = true:suggestion
|
||||
|
||||
# Parameter preferences
|
||||
dotnet_code_quality_unused_parameters = all:suggestion
|
||||
dotnet_code_quality_unused_parameters = all:silent
|
||||
|
||||
#### C# Coding Conventions ####
|
||||
|
||||
# Namespace preferences
|
||||
csharp_style_namespace_declarations = block_scoped:warning
|
||||
resharper_csharp_namespace_body = block_scoped
|
||||
|
||||
# var preferences
|
||||
csharp_style_var_elsewhere = false:silent
|
||||
csharp_style_var_for_built_in_types = false:silent
|
||||
@ -81,7 +94,7 @@ csharp_style_expression_bodied_properties = true:silent
|
||||
# Pattern matching preferences
|
||||
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
|
||||
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
|
||||
csharp_style_prefer_switch_expression = true:suggestion
|
||||
csharp_style_prefer_switch_expression = false:silent
|
||||
|
||||
# Null-checking preferences
|
||||
csharp_style_conditional_delegate_call = true:suggestion
|
||||
@ -90,6 +103,7 @@ csharp_style_conditional_delegate_call = true:suggestion
|
||||
csharp_prefer_static_local_function = true:suggestion
|
||||
csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:silent
|
||||
csharp_style_prefer_readonly_struct = true
|
||||
csharp_style_prefer_method_group_conversion = true
|
||||
|
||||
# Code-block preferences
|
||||
csharp_prefer_braces = true:silent
|
||||
@ -105,6 +119,7 @@ csharp_style_prefer_range_operator = true:suggestion
|
||||
csharp_style_throw_expression = true:suggestion
|
||||
csharp_style_unused_value_assignment_preference = discard_variable:suggestion
|
||||
csharp_style_unused_value_expression_statement_preference = discard_variable:silent
|
||||
csharp_style_implicit_object_creation_when_type_is_apparent = true
|
||||
|
||||
# 'using' directive preferences
|
||||
csharp_using_directive_placement = outside_namespace:silent
|
||||
@ -136,7 +151,6 @@ csharp_space_after_dot = false
|
||||
csharp_space_after_keywords_in_control_flow_statements = true
|
||||
csharp_space_after_semicolon_in_for_statement = true
|
||||
csharp_space_around_binary_operators = before_and_after
|
||||
csharp_space_around_declaration_statements = false
|
||||
csharp_space_before_colon_in_inheritance_clause = true
|
||||
csharp_space_before_comma = false
|
||||
csharp_space_before_dot = false
|
||||
@ -154,23 +168,31 @@ csharp_space_between_square_brackets = false
|
||||
|
||||
# Wrapping preferences
|
||||
csharp_preserve_single_line_blocks = true
|
||||
csharp_preserve_single_line_statements = true
|
||||
csharp_preserve_single_line_statements = false
|
||||
|
||||
#### Naming styles ####
|
||||
|
||||
# Naming rules
|
||||
|
||||
dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion
|
||||
dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
|
||||
dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
|
||||
dotnet_naming_rule.interfaces_should_be_prefixed_with_I.severity = suggestion
|
||||
dotnet_naming_rule.interfaces_should_be_prefixed_with_I.symbols = interface
|
||||
dotnet_naming_rule.interfaces_should_be_prefixed_with_I.style = IPascalCase
|
||||
|
||||
dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion
|
||||
dotnet_naming_rule.types_should_be_pascal_case.symbols = types
|
||||
dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
|
||||
dotnet_naming_rule.types_should_be_pascal_case.style = PascalCase
|
||||
|
||||
dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion
|
||||
dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
|
||||
dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
|
||||
dotnet_naming_rule.non_field_members_should_be_pascal_case.style = PascalCase
|
||||
|
||||
dotnet_naming_rule.private_static_readonly_fields_should_be_camel_case_and_prefixed_with__.symbols = private_static_readonly_fields
|
||||
dotnet_naming_rule.private_static_readonly_fields_should_be_camel_case_and_prefixed_with__.severity = suggestion
|
||||
dotnet_naming_rule.private_static_readonly_fields_should_be_camel_case_and_prefixed_with__.style = _camelCase
|
||||
|
||||
dotnet_naming_rule.local_constants_should_be_pascal_case.symbols = local_constants
|
||||
dotnet_naming_rule.local_constants_should_be_pascal_case.severity = suggestion
|
||||
dotnet_naming_rule.local_constants_should_be_pascal_case.style = PascalCase
|
||||
|
||||
# Symbol specifications
|
||||
|
||||
@ -186,14 +208,39 @@ dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, meth
|
||||
dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
|
||||
dotnet_naming_symbols.non_field_members.required_modifiers =
|
||||
|
||||
dotnet_naming_symbols.private_static_readonly_fields.applicable_kinds = field
|
||||
dotnet_naming_symbols.private_static_readonly_fields.applicable_accessibilities = private
|
||||
dotnet_naming_symbols.private_static_readonly_fields.required_modifiers = static, readonly
|
||||
|
||||
dotnet_naming_symbols.local_constants.applicable_kinds = local
|
||||
dotnet_naming_symbols.local_constants.applicable_accessibilities = local
|
||||
dotnet_naming_symbols.local_constants.required_modifiers = const
|
||||
|
||||
# Naming styles
|
||||
|
||||
dotnet_naming_style.pascal_case.required_prefix =
|
||||
dotnet_naming_style.pascal_case.required_suffix =
|
||||
dotnet_naming_style.pascal_case.word_separator =
|
||||
dotnet_naming_style.pascal_case.capitalization = pascal_case
|
||||
dotnet_naming_style._camelCase.required_prefix = _
|
||||
dotnet_naming_style._camelCase.required_suffix =
|
||||
dotnet_naming_style._camelCase.word_separator =
|
||||
dotnet_naming_style._camelCase.capitalization = camel_case
|
||||
|
||||
dotnet_naming_style.begins_with_i.required_prefix = I
|
||||
dotnet_naming_style.begins_with_i.required_suffix =
|
||||
dotnet_naming_style.begins_with_i.word_separator =
|
||||
dotnet_naming_style.begins_with_i.capitalization = pascal_case
|
||||
dotnet_naming_style.PascalCase.required_prefix =
|
||||
dotnet_naming_style.PascalCase.required_suffix =
|
||||
dotnet_naming_style.PascalCase.word_separator =
|
||||
dotnet_naming_style.PascalCase.capitalization = pascal_case
|
||||
|
||||
dotnet_naming_style.IPascalCase.required_prefix = I
|
||||
dotnet_naming_style.IPascalCase.required_suffix =
|
||||
dotnet_naming_style.IPascalCase.word_separator =
|
||||
dotnet_naming_style.IPascalCase.capitalization = pascal_case
|
||||
|
||||
[src/Ryujinx.HLE/HOS/Services/**.cs]
|
||||
# Disable "mark members as static" rule for services
|
||||
dotnet_diagnostic.CA1822.severity = none
|
||||
|
||||
[src/Ryujinx.Ava/UI/ViewModels/**.cs]
|
||||
# Disable "mark members as static" rule for ViewModels
|
||||
dotnet_diagnostic.CA1822.severity = none
|
||||
|
||||
[src/Ryujinx.Tests/Cpu/*.cs]
|
||||
# Disable naming rules for CPU tests
|
||||
dotnet_diagnostic.IDE1006.severity = none
|
||||
|
19
.github/ISSUE_TEMPLATE/missing_shader_instruction.yml
vendored
Normal file
19
.github/ISSUE_TEMPLATE/missing_shader_instruction.yml
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
name: Missing Shader Instruction
|
||||
description: Shader Instruction is missing in Ryujinx.
|
||||
title: "[GPU]"
|
||||
labels: [gpu, not-implemented]
|
||||
body:
|
||||
- type: textarea
|
||||
id: instruction
|
||||
attributes:
|
||||
label: Shader instruction
|
||||
description: What shader instruction is missing?
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: required
|
||||
attributes:
|
||||
label: Required by
|
||||
description: Add links to the [compatibility list page(s)](https://github.com/Ryujinx/Ryujinx-Games-List/issues) of the game(s) that require this instruction.
|
||||
validations:
|
||||
required: true
|
18
.github/csc.json
vendored
Normal file
18
.github/csc.json
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"problemMatcher": [
|
||||
{
|
||||
"owner": "csc",
|
||||
"pattern": [
|
||||
{
|
||||
"regexp": "^((?:\\\\|/)(?:[^\\\\/:]+(?:\\\\|/))+[^\\\\/]+)\\((\\d+),(\\d+)\\):\\s+([a-zA-Z]+)\\s+([^:]+):\\s+([^[]+)\\s+\\[",
|
||||
"file": 1,
|
||||
"line": 2,
|
||||
"column": 3,
|
||||
"severity": 4,
|
||||
"code": 5,
|
||||
"message": 6
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
33
.github/labeler.yml
vendored
Normal file
33
.github/labeler.yml
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
audio: 'src/Ryujinx.Audio*/**'
|
||||
|
||||
cpu:
|
||||
- 'src/ARMeilleure/**'
|
||||
- 'src/Ryujinx.Cpu/**'
|
||||
- 'src/Ryujinx.Memory/**'
|
||||
|
||||
gpu:
|
||||
- 'src/Ryujinx.Graphics.*/**'
|
||||
- 'src/Spv.Generator/**'
|
||||
- 'src/Ryujinx.ShaderTools/**'
|
||||
|
||||
'graphics-backend:opengl': 'src/Ryujinx.Graphics.OpenGL/**'
|
||||
'graphics-backend:vulkan':
|
||||
- 'src/Ryujinx.Graphics.Vulkan/**'
|
||||
- 'src/Spv.Generator/**'
|
||||
|
||||
gui:
|
||||
- 'src/Ryujinx/**'
|
||||
- 'src/Ryujinx.Ui.Common/**'
|
||||
- 'src/Ryujinx.Ui.LocaleGenerator/**'
|
||||
- 'src/Ryujinx.Ava/**'
|
||||
|
||||
horizon:
|
||||
- 'src/Ryujinx.HLE/**'
|
||||
- 'src/Ryujinx.Horizon*/**'
|
||||
|
||||
kernel: 'src/Ryujinx.HLE/HOS/Kernel/**'
|
||||
|
||||
infra:
|
||||
- '.github/**'
|
||||
- 'distribution/**'
|
||||
- 'Directory.Packages.props'
|
32
.github/reviewers.yml
vendored
Normal file
32
.github/reviewers.yml
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
audio:
|
||||
- marysaka
|
||||
|
||||
cpu:
|
||||
- gdkchan
|
||||
- riperiperi
|
||||
- marysaka
|
||||
- LDj3SNuD
|
||||
|
||||
gpu:
|
||||
- gdkchan
|
||||
- riperiperi
|
||||
- marysaka
|
||||
|
||||
gui:
|
||||
- Ack77
|
||||
- emmauss
|
||||
- TSRBerry
|
||||
- marysaka
|
||||
|
||||
horizon:
|
||||
- gdkchan
|
||||
- Ack77
|
||||
- marysaka
|
||||
- TSRBerry
|
||||
|
||||
infra:
|
||||
- marysaka
|
||||
- TSRBerry
|
||||
|
||||
default:
|
||||
- '@developers'
|
135
.github/workflows/build.yml
vendored
135
.github/workflows/build.yml
vendored
@ -1,27 +1,18 @@
|
||||
name: Build job
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs: {}
|
||||
#push:
|
||||
# branches: [ master ]
|
||||
# paths-ignore:
|
||||
# - '.github/*'
|
||||
# - '.github/ISSUE_TEMPLATE/**'
|
||||
# - '*.yml'
|
||||
# - 'README.md'
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
paths-ignore:
|
||||
- '.github/*'
|
||||
- '.github/ISSUE_TEMPLATE/**'
|
||||
- '*.yml'
|
||||
- 'README.md'
|
||||
workflow_call:
|
||||
|
||||
env:
|
||||
POWERSHELL_TELEMETRY_OPTOUT: 1
|
||||
DOTNET_CLI_TELEMETRY_OPTOUT: 1
|
||||
RYUJINX_BASE_VERSION: "1.1.0"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: ${{ matrix.os }} (${{ matrix.configuration }})
|
||||
name: ${{ matrix.OS_NAME }} (${{ matrix.configuration }})
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 45
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, macOS-latest, windows-latest]
|
||||
@ -33,7 +24,7 @@ jobs:
|
||||
RELEASE_ZIP_OS_NAME: linux_x64
|
||||
|
||||
- os: macOS-latest
|
||||
OS_NAME: MacOS x64
|
||||
OS_NAME: macOS x64
|
||||
DOTNET_RUNTIME_IDENTIFIER: osx-x64
|
||||
RELEASE_ZIP_OS_NAME: osx_x64
|
||||
|
||||
@ -43,47 +34,125 @@ jobs:
|
||||
RELEASE_ZIP_OS_NAME: win_x64
|
||||
|
||||
fail-fast: false
|
||||
env:
|
||||
POWERSHELL_TELEMETRY_OPTOUT: 1
|
||||
DOTNET_CLI_TELEMETRY_OPTOUT: 1
|
||||
RYUJINX_BASE_VERSION: "1.1.0"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: 7.0.x
|
||||
global-json-file: global.json
|
||||
|
||||
- name: Overwrite csc problem matcher
|
||||
run: echo "::add-matcher::.github/csc.json"
|
||||
|
||||
- name: Get git short hash
|
||||
id: git_short_hash
|
||||
run: echo "result=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
|
||||
shell: bash
|
||||
|
||||
- name: Build
|
||||
run: dotnet build -c "${{ matrix.configuration }}" -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER
|
||||
|
||||
- name: Test
|
||||
run: dotnet test --no-build -c "${{ matrix.configuration }}"
|
||||
uses: TSRBerry/unstable-commands@v1
|
||||
with:
|
||||
commands: dotnet test --no-build -c "${{ matrix.configuration }}"
|
||||
timeout-minutes: 10
|
||||
retry-codes: 139
|
||||
|
||||
- name: Publish Ryujinx
|
||||
run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.DOTNET_RUNTIME_IDENTIFIER }}" -o ./publish -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:DebugType=embedded -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER Ryujinx --self-contained true
|
||||
if: github.event_name == 'pull_request'
|
||||
run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.DOTNET_RUNTIME_IDENTIFIER }}" -o ./publish -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:DebugType=embedded -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER src/Ryujinx --self-contained true
|
||||
if: github.event_name == 'pull_request' && matrix.os != 'macOS-latest'
|
||||
|
||||
- name: Publish Ryujinx.Headless.SDL2
|
||||
run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.DOTNET_RUNTIME_IDENTIFIER }}" -o ./publish_sdl2_headless -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:DebugType=embedded -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER Ryujinx.Headless.SDL2 --self-contained true
|
||||
if: github.event_name == 'pull_request'
|
||||
run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.DOTNET_RUNTIME_IDENTIFIER }}" -o ./publish_sdl2_headless -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:DebugType=embedded -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER src/Ryujinx.Headless.SDL2 --self-contained true
|
||||
if: github.event_name == 'pull_request' && matrix.os != 'macOS-latest'
|
||||
|
||||
- name: Publish Ryujinx.Ava
|
||||
run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.DOTNET_RUNTIME_IDENTIFIER }}" -o ./publish_ava -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:DebugType=embedded -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER Ryujinx.Ava --self-contained true
|
||||
if: github.event_name == 'pull_request'
|
||||
run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.DOTNET_RUNTIME_IDENTIFIER }}" -o ./publish_ava -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:DebugType=embedded -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER src/Ryujinx.Ava --self-contained true
|
||||
if: github.event_name == 'pull_request' && matrix.os != 'macOS-latest'
|
||||
|
||||
- name: Set executable bit
|
||||
run: |
|
||||
chmod +x ./publish/Ryujinx ./publish/Ryujinx.sh
|
||||
chmod +x ./publish_sdl2_headless/Ryujinx.Headless.SDL2 ./publish_sdl2_headless/Ryujinx.sh
|
||||
chmod +x ./publish_ava/Ryujinx.Ava ./publish_ava/Ryujinx.sh
|
||||
if: github.event_name == 'pull_request' && matrix.os == 'ubuntu-latest'
|
||||
|
||||
- name: Upload Ryujinx artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.RELEASE_ZIP_OS_NAME }}
|
||||
path: publish
|
||||
if: github.event_name == 'pull_request'
|
||||
if: github.event_name == 'pull_request' && matrix.os != 'macOS-latest'
|
||||
|
||||
- name: Upload Ryujinx.Headless.SDL2 artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: sdl2-ryujinx-headless-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.RELEASE_ZIP_OS_NAME }}
|
||||
path: publish_sdl2_headless
|
||||
if: github.event_name == 'pull_request'
|
||||
if: github.event_name == 'pull_request' && matrix.os != 'macOS-latest'
|
||||
|
||||
- name: Upload Ryujinx.Ava artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ava-ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.RELEASE_ZIP_OS_NAME }}
|
||||
path: publish_ava
|
||||
if: github.event_name == 'pull_request' && matrix.os != 'macOS-latest'
|
||||
|
||||
build_macos:
|
||||
name: macOS Universal (${{ matrix.configuration }})
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 45
|
||||
strategy:
|
||||
matrix:
|
||||
configuration: [ Debug, Release ]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
global-json-file: global.json
|
||||
|
||||
- name: Setup LLVM 14
|
||||
run: |
|
||||
wget https://apt.llvm.org/llvm.sh
|
||||
chmod +x llvm.sh
|
||||
sudo ./llvm.sh 14
|
||||
|
||||
- name: Install rcodesign
|
||||
run: |
|
||||
mkdir -p $HOME/.bin
|
||||
gh release download -R indygreg/apple-platform-rs -O apple-codesign.tar.gz -p 'apple-codesign-*-x86_64-unknown-linux-musl.tar.gz'
|
||||
tar -xzvf apple-codesign.tar.gz --wildcards '*/rcodesign' --strip-components=1
|
||||
rm apple-codesign.tar.gz
|
||||
mv rcodesign $HOME/.bin/
|
||||
echo "$HOME/.bin" >> $GITHUB_PATH
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Get git short hash
|
||||
id: git_short_hash
|
||||
run: echo "result=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Publish macOS Ryujinx.Ava
|
||||
run: |
|
||||
./distribution/macos/create_macos_build_ava.sh . publish_tmp_ava publish_ava ./distribution/macos/entitlements.xml "${{ env.RYUJINX_BASE_VERSION }}" "${{ steps.git_short_hash.outputs.result }}" "${{ matrix.configuration }}" "-p:ExtraDefineConstants=DISABLE_UPDATER"
|
||||
|
||||
- name: Publish macOS Ryujinx.Headless.SDL2
|
||||
run: |
|
||||
./distribution/macos/create_macos_build_headless.sh . publish_tmp_headless publish_headless ./distribution/macos/entitlements.xml "${{ env.RYUJINX_BASE_VERSION }}" "${{ steps.git_short_hash.outputs.result }}" "${{ matrix.configuration }}" "-p:ExtraDefineConstants=DISABLE_UPDATER"
|
||||
|
||||
- name: Upload Ryujinx.Ava artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ava-ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-macos_universal
|
||||
path: "publish_ava/*.tar.gz"
|
||||
if: github.event_name == 'pull_request'
|
||||
|
||||
- name: Upload Ryujinx.Headless.SDL2 artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: sdl2-ryujinx-headless-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-macos_universal
|
||||
path: "publish_headless/*.tar.gz"
|
||||
if: github.event_name == 'pull_request'
|
74
.github/workflows/checks.yml
vendored
Normal file
74
.github/workflows/checks.yml
vendored
Normal file
@ -0,0 +1,74 @@
|
||||
name: Perform checks
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
paths:
|
||||
- '**'
|
||||
- '!.github/**'
|
||||
- '!*.yml'
|
||||
- '!*.config'
|
||||
- '!README.md'
|
||||
- '.github/workflows/*.yml'
|
||||
|
||||
permissions:
|
||||
pull-requests: write
|
||||
checks: write
|
||||
|
||||
concurrency:
|
||||
group: pr-checks-${{ github.event.number }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
format:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
global-json-file: global.json
|
||||
|
||||
- name: Overwrite csc problem matcher
|
||||
run: echo "::add-matcher::.github/csc.json"
|
||||
|
||||
- run: dotnet restore
|
||||
|
||||
- name: Print dotnet format version
|
||||
run: dotnet format --version
|
||||
|
||||
- name: Run dotnet format whitespace
|
||||
run: |
|
||||
dotnet format whitespace --verify-no-changes --report ./whitespace-report.json -v d
|
||||
|
||||
# For some unknown reason this step sometimes fails with exit code 139 (segfault?),
|
||||
# so in that case we'll try again (3 tries max).
|
||||
- name: Run dotnet format style
|
||||
uses: TSRBerry/unstable-commands@v1
|
||||
with:
|
||||
commands: dotnet format style --severity info --verify-no-changes --report ./style-report.json -v d
|
||||
timeout-minutes: 5
|
||||
retry-codes: 139
|
||||
|
||||
# For some unknown reason this step sometimes fails with exit code 139 (segfault?),
|
||||
# so in that case we'll try again (3 tries max).
|
||||
- name: Run dotnet format analyzers
|
||||
uses: TSRBerry/unstable-commands@v1
|
||||
with:
|
||||
commands: dotnet format analyzers --severity info --verify-no-changes --report ./analyzers-report.json -v d
|
||||
timeout-minutes: 5
|
||||
retry-codes: 139
|
||||
|
||||
- name: Upload report
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: dotnet-format
|
||||
path: ./*-report.json
|
||||
|
||||
pr_build:
|
||||
uses: ./.github/workflows/build.yml
|
||||
needs: format
|
||||
secrets: inherit
|
172
.github/workflows/flatpak.yml
vendored
Normal file
172
.github/workflows/flatpak.yml
vendored
Normal file
@ -0,0 +1,172 @@
|
||||
name: Flatpak release job
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
ryujinx_version:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
|
||||
concurrency: flatpak-release
|
||||
|
||||
jobs:
|
||||
release:
|
||||
timeout-minutes: ${{ fromJSON(vars.JOB_TIMEOUT) }}
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
env:
|
||||
NUGET_PACKAGES: ${{ github.workspace }}/.nuget/packages
|
||||
GIT_COMMITTER_NAME: "RyujinxBot"
|
||||
GIT_COMMITTER_EMAIL: "61127645+RyujinxBot@users.noreply.github.com"
|
||||
RYUJINX_PROJECT_FILE: "src/Ryujinx/Ryujinx.csproj"
|
||||
NUGET_SOURCES_DESTDIR: "nuget-sources"
|
||||
RYUJINX_VERSION: "${{ inputs.ryujinx_version }}"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
path: Ryujinx
|
||||
|
||||
- uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
global-json-file: Ryujinx/global.json
|
||||
|
||||
- name: Get version info
|
||||
id: version_info
|
||||
working-directory: Ryujinx
|
||||
run: |
|
||||
echo "git_hash=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
repository: flathub/org.ryujinx.Ryujinx
|
||||
token: ${{ secrets.RYUJINX_BOT_PAT }}
|
||||
submodules: recursive
|
||||
path: flathub
|
||||
|
||||
- name: Install dependencies
|
||||
run: python -m pip install PyYAML lxml
|
||||
|
||||
- name: Restore Nuget packages
|
||||
run: dotnet restore Ryujinx/${{ env.RYUJINX_PROJECT_FILE }}
|
||||
|
||||
- name: Generate nuget_sources.json
|
||||
shell: python
|
||||
run: |
|
||||
from pathlib import Path
|
||||
import base64
|
||||
import binascii
|
||||
import json
|
||||
import os
|
||||
|
||||
sources = []
|
||||
|
||||
for path in Path(os.environ['NUGET_PACKAGES']).glob('**/*.nupkg.sha512'):
|
||||
name = path.parent.parent.name
|
||||
version = path.parent.name
|
||||
filename = '{}.{}.nupkg'.format(name, version)
|
||||
url = 'https://api.nuget.org/v3-flatcontainer/{}/{}/{}'.format(name, version, filename)
|
||||
|
||||
with path.open() as fp:
|
||||
sha512 = binascii.hexlify(base64.b64decode(fp.read())).decode('ascii')
|
||||
|
||||
sources.append({
|
||||
'type': 'file',
|
||||
'url': url,
|
||||
'sha512': sha512,
|
||||
'dest': os.environ['NUGET_SOURCES_DESTDIR'],
|
||||
'dest-filename': filename,
|
||||
})
|
||||
|
||||
with open('flathub/nuget_sources.json', 'w') as fp:
|
||||
json.dump(sources, fp, indent=4)
|
||||
|
||||
- name: Update flatpak metadata
|
||||
id: metadata
|
||||
env:
|
||||
RYUJINX_GIT_HASH: ${{ steps.version_info.outputs.git_hash }}
|
||||
shell: python
|
||||
run: |
|
||||
import hashlib
|
||||
import hmac
|
||||
import json
|
||||
import os
|
||||
import yaml
|
||||
from datetime import datetime
|
||||
from lxml import etree
|
||||
|
||||
|
||||
# Ensure we don't destroy multiline strings
|
||||
def str_presenter(dumper, data):
|
||||
if len(data.splitlines()) > 1:
|
||||
return dumper.represent_scalar("tag:yaml.org,2002:str", data, style="|")
|
||||
return dumper.represent_scalar("tag:yaml.org,2002:str", data)
|
||||
|
||||
|
||||
yaml.representer.SafeRepresenter.add_representer(str, str_presenter)
|
||||
|
||||
yaml_file = "flathub/org.ryujinx.Ryujinx.yml"
|
||||
xml_file = "flathub/org.ryujinx.Ryujinx.appdata.xml"
|
||||
|
||||
with open(yaml_file, "r") as f:
|
||||
data = yaml.safe_load(f)
|
||||
|
||||
for source in data["modules"][0]["sources"]:
|
||||
if type(source) is str:
|
||||
continue
|
||||
if (
|
||||
source["type"] == "git"
|
||||
and source["url"] == "https://github.com/Ryujinx/Ryujinx.git"
|
||||
):
|
||||
source["commit"] = os.environ['RYUJINX_GIT_HASH']
|
||||
|
||||
is_same_version = data["modules"][0]["build-options"]["env"]["RYUJINX_VERSION"] == os.environ['RYUJINX_VERSION']
|
||||
|
||||
with open(os.environ['GITHUB_OUTPUT'], "a") as gh_out:
|
||||
if is_same_version:
|
||||
gh_out.write(f"commit_message=Retry update to {os.environ['RYUJINX_VERSION']}")
|
||||
else:
|
||||
gh_out.write(f"commit_message=Update to {os.environ['RYUJINX_VERSION']}")
|
||||
|
||||
if not is_same_version:
|
||||
data["modules"][0]["build-options"]["env"]["RYUJINX_VERSION"] = os.environ['RYUJINX_VERSION']
|
||||
|
||||
with open(yaml_file, "w") as f:
|
||||
yaml.safe_dump(data, f, sort_keys=False)
|
||||
|
||||
parser = etree.XMLParser(remove_blank_text=True)
|
||||
tree = etree.parse(xml_file, parser)
|
||||
|
||||
root = tree.getroot()
|
||||
|
||||
releases = root.find("releases")
|
||||
|
||||
element = etree.Element("release")
|
||||
element.set("version", os.environ['RYUJINX_VERSION'])
|
||||
element.set("date", datetime.now().date().isoformat())
|
||||
releases.insert(0, element)
|
||||
|
||||
# Ensure 4 spaces
|
||||
etree.indent(root, space=" ")
|
||||
|
||||
with open(xml_file, "wb") as f:
|
||||
f.write(
|
||||
etree.tostring(
|
||||
tree,
|
||||
pretty_print=True,
|
||||
encoding="UTF-8",
|
||||
doctype='<?xml version="1.0" encoding="UTF-8"?>',
|
||||
)
|
||||
)
|
||||
|
||||
- name: Push flatpak update
|
||||
working-directory: flathub
|
||||
env:
|
||||
COMMIT_MESSAGE: ${{ steps.metadata.outputs.commit_message }}
|
||||
run: |
|
||||
git config user.name "${{ env.GIT_COMMITTER_NAME }}"
|
||||
git config user.email "${{ env.GIT_COMMITTER_EMAIL }}"
|
||||
git add .
|
||||
git commit -m "$COMMIT_MESSAGE"
|
||||
git push origin master
|
5
.github/workflows/nightly_pr_comment.yml
vendored
5
.github/workflows/nightly_pr_comment.yml
vendored
@ -1,12 +1,15 @@
|
||||
name: Comment PR artifacts links
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: ['Build job']
|
||||
workflows: ['Perform checks']
|
||||
types: [completed]
|
||||
|
||||
jobs:
|
||||
pr_comment:
|
||||
if: github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success'
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: ${{ fromJSON(vars.JOB_TIMEOUT) }}
|
||||
steps:
|
||||
- uses: actions/github-script@v6
|
||||
with:
|
||||
|
47
.github/workflows/pr_triage.yml
vendored
Normal file
47
.github/workflows/pr_triage.yml
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
name: "Pull Request Triage"
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened, ready_for_review]
|
||||
|
||||
jobs:
|
||||
triage:
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
# Grab sources to get latest labeler.yml
|
||||
- name: Fetch sources
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
# Ensure we pin the source origin as pull_request_target run under forks.
|
||||
fetch-depth: 0
|
||||
repository: Ryujinx/Ryujinx
|
||||
ref: master
|
||||
|
||||
- name: Checkout Ryujinx-Mako
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: Ryujinx/Ryujinx-Mako
|
||||
ref: master
|
||||
path: '.ryujinx-mako'
|
||||
|
||||
- name: Setup Ryujinx-Mako
|
||||
uses: ./.ryujinx-mako/.github/actions/setup-mako
|
||||
|
||||
- name: Update labels based on changes
|
||||
uses: actions/labeler@v4
|
||||
with:
|
||||
sync-labels: true
|
||||
dot: true
|
||||
|
||||
- name: Assign reviewers
|
||||
run: |
|
||||
poetry -n -C .ryujinx-mako run ryujinx-mako update-reviewers ${{ github.repository }} ${{ github.event.pull_request.number }} .github/reviewers.yml
|
||||
shell: bash
|
||||
env:
|
||||
MAKO_APP_ID: ${{ secrets.MAKO_APP_ID }}
|
||||
MAKO_PRIVATE_KEY: ${{ secrets.MAKO_PRIVATE_KEY }}
|
||||
MAKO_INSTALLATION_ID: ${{ secrets.MAKO_INSTALLATION_ID }}
|
210
.github/workflows/release.yml
vendored
210
.github/workflows/release.yml
vendored
@ -6,96 +6,128 @@ on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
paths-ignore:
|
||||
- '.github/*'
|
||||
- '.github/ISSUE_TEMPLATE/**'
|
||||
- '.github/**'
|
||||
- '*.yml'
|
||||
- '*.json'
|
||||
- '*.config'
|
||||
- 'README.md'
|
||||
|
||||
concurrency: release
|
||||
|
||||
env:
|
||||
POWERSHELL_TELEMETRY_OPTOUT: 1
|
||||
DOTNET_CLI_TELEMETRY_OPTOUT: 1
|
||||
RYUJINX_BASE_VERSION: "1.1"
|
||||
RYUJINX_TARGET_RELEASE_CHANNEL_NAME: "master"
|
||||
RYUJINX_TARGET_RELEASE_CHANNEL_OWNER: "Ryujinx"
|
||||
RYUJINX_TARGET_RELEASE_CHANNEL_REPO: "release-channel-master"
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: windows-latest
|
||||
|
||||
env:
|
||||
POWERSHELL_TELEMETRY_OPTOUT: 1
|
||||
DOTNET_CLI_TELEMETRY_OPTOUT: 1
|
||||
RYUJINX_BASE_VERSION: "1.1"
|
||||
RYUJINX_TARGET_RELEASE_CHANNEL_NAME: "master"
|
||||
RYUJINX_TARGET_RELEASE_CHANNEL_OWNER: "Ryujinx"
|
||||
RYUJINX_TARGET_RELEASE_CHANNEL_REPO: "release-channel-master"
|
||||
|
||||
tag:
|
||||
name: Create tag
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Get version info
|
||||
id: version_info
|
||||
run: |
|
||||
echo "build_version=${{ env.RYUJINX_BASE_VERSION }}.${{ github.run_number }}" >> $GITHUB_OUTPUT
|
||||
shell: bash
|
||||
|
||||
- name: Create tag
|
||||
uses: actions/github-script@v6
|
||||
with:
|
||||
script: |
|
||||
github.rest.git.createRef({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
ref: 'refs/tags/${{ steps.version_info.outputs.build_version }}',
|
||||
sha: context.sha
|
||||
})
|
||||
|
||||
release:
|
||||
name: Release ${{ matrix.OS_NAME }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: ${{ fromJSON(vars.JOB_TIMEOUT) }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ ubuntu-latest, windows-latest ]
|
||||
include:
|
||||
- os: ubuntu-latest
|
||||
OS_NAME: Linux x64
|
||||
DOTNET_RUNTIME_IDENTIFIER: linux-x64
|
||||
RELEASE_ZIP_OS_NAME: linux_x64
|
||||
|
||||
- os: windows-latest
|
||||
OS_NAME: Windows x64
|
||||
DOTNET_RUNTIME_IDENTIFIER: win10-x64
|
||||
RELEASE_ZIP_OS_NAME: win_x64
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: 7.0.x
|
||||
global-json-file: global.json
|
||||
|
||||
- name: Overwrite csc problem matcher
|
||||
run: echo "::add-matcher::.github/csc.json"
|
||||
|
||||
- name: Get version info
|
||||
id: version_info
|
||||
run: |
|
||||
echo "build_version=${{ env.RYUJINX_BASE_VERSION }}.${{ github.run_number }}" >> $GITHUB_OUTPUT
|
||||
echo "git_short_hash=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
|
||||
shell: bash
|
||||
|
||||
- name: Configure for release
|
||||
run: |
|
||||
sed -r --in-place 's/\%\%RYUJINX_BUILD_VERSION\%\%/${{ steps.version_info.outputs.build_version }}/g;' Ryujinx.Common/ReleaseInformation.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_BUILD_GIT_HASH\%\%/${{ steps.version_info.outputs.git_short_hash }}/g;' Ryujinx.Common/ReleaseInformation.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' Ryujinx.Common/ReleaseInformation.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/g;' Ryujinx.Common/ReleaseInformation.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' Ryujinx.Common/ReleaseInformation.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_BUILD_VERSION\%\%/${{ steps.version_info.outputs.build_version }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_BUILD_GIT_HASH\%\%/${{ steps.version_info.outputs.git_short_hash }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
shell: bash
|
||||
|
||||
- name: Create output dir
|
||||
run: "mkdir release_output"
|
||||
- name: Publish Windows
|
||||
|
||||
- name: Publish
|
||||
run: |
|
||||
dotnet publish -c Release -r win10-x64 -o ./publish_windows/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded Ryujinx --self-contained true
|
||||
dotnet publish -c Release -r win10-x64 -o ./publish_windows_sdl2_headless/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded Ryujinx.Headless.SDL2 --self-contained true
|
||||
dotnet publish -c Release -r win10-x64 -o ./publish_windows_ava/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded Ryujinx.Ava --self-contained true
|
||||
dotnet publish -c Release -r "${{ matrix.DOTNET_RUNTIME_IDENTIFIER }}" -o ./publish_gtk/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx --self-contained true
|
||||
dotnet publish -c Release -r "${{ matrix.DOTNET_RUNTIME_IDENTIFIER }}" -o ./publish_sdl2_headless/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx.Headless.SDL2 --self-contained true
|
||||
dotnet publish -c Release -r "${{ matrix.DOTNET_RUNTIME_IDENTIFIER }}" -o ./publish_ava/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx.Ava --self-contained true
|
||||
|
||||
- name: Packing Windows builds
|
||||
if: matrix.os == 'windows-latest'
|
||||
run: |
|
||||
pushd publish_windows
|
||||
pushd publish_gtk
|
||||
7z a ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-win_x64.zip publish
|
||||
popd
|
||||
|
||||
pushd publish_windows_sdl2_headless
|
||||
pushd publish_sdl2_headless
|
||||
7z a ../release_output/sdl2-ryujinx-headless-${{ steps.version_info.outputs.build_version }}-win_x64.zip publish
|
||||
popd
|
||||
|
||||
pushd publish_windows_ava
|
||||
pushd publish_ava
|
||||
7z a ../release_output/test-ava-ryujinx-${{ steps.version_info.outputs.build_version }}-win_x64.zip publish
|
||||
popd
|
||||
shell: bash
|
||||
|
||||
- name: Publish Linux
|
||||
run: |
|
||||
dotnet publish -c Release -r linux-x64 -o ./publish_linux/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded Ryujinx --self-contained true
|
||||
dotnet publish -c Release -r linux-x64 -o ./publish_linux_sdl2_headless/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded Ryujinx.Headless.SDL2 --self-contained true
|
||||
dotnet publish -c Release -r linux-x64 -o ./publish_linux_ava/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded Ryujinx.Ava --self-contained true
|
||||
|
||||
- name: Packing Linux builds
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
run: |
|
||||
pushd publish_linux
|
||||
tar --exclude "publish/Ryujinx" --exclude "publish/Ryujinx.sh" -cvf ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar publish
|
||||
python3 ../distribution/misc/add_tar_exec.py ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar "publish/Ryujinx" "publish/Ryujinx"
|
||||
python3 ../distribution/misc/add_tar_exec.py ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar "publish/Ryujinx.sh" "publish/Ryujinx.sh"
|
||||
gzip -9 < ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar > ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz
|
||||
rm ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar
|
||||
pushd publish_gtk
|
||||
chmod +x publish/Ryujinx.sh publish/Ryujinx
|
||||
tar -czvf ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz publish
|
||||
popd
|
||||
|
||||
pushd publish_linux_sdl2_headless
|
||||
tar --exclude "publish/Ryujinx.Headless.SDL2" --exclude "publish/Ryujinx.sh" -cvf ../release_output/sdl2-ryujinx-headless-${{ steps.version_info.outputs.build_version }}-linux_x64.tar publish
|
||||
python3 ../distribution/misc/add_tar_exec.py ../release_output/sdl2-ryujinx-headless-${{ steps.version_info.outputs.build_version }}-linux_x64.tar "publish/Ryujinx.Headless.SDL2" "publish/Ryujinx.Headless.SDL2"
|
||||
python3 ../distribution/misc/add_tar_exec.py ../release_output/sdl2-ryujinx-headless-${{ steps.version_info.outputs.build_version }}-linux_x64.tar "publish/Ryujinx.sh" "publish/Ryujinx.sh"
|
||||
gzip -9 < ../release_output/sdl2-ryujinx-headless-${{ steps.version_info.outputs.build_version }}-linux_x64.tar > ../release_output/sdl2-ryujinx-headless-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz
|
||||
rm ../release_output/sdl2-ryujinx-headless-${{ steps.version_info.outputs.build_version }}-linux_x64.tar
|
||||
pushd publish_sdl2_headless
|
||||
chmod +x publish/Ryujinx.sh publish/Ryujinx.Headless.SDL2
|
||||
tar -czvf ../release_output/sdl2-ryujinx-headless-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz publish
|
||||
popd
|
||||
|
||||
pushd publish_linux_ava
|
||||
tar --exclude "publish/Ryujinx.Ava" --exclude "publish/Ryujinx.sh" -cvf ../release_output/test-ava-ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar publish
|
||||
python3 ../distribution/misc/add_tar_exec.py ../release_output/test-ava-ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar "publish/Ryujinx.Ava" "publish/Ryujinx.Ava"
|
||||
python3 ../distribution/misc/add_tar_exec.py ../release_output/test-ava-ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar "publish/Ryujinx.sh" "publish/Ryujinx.sh"
|
||||
gzip -9 < ../release_output/test-ava-ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar > ../release_output/test-ava-ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz
|
||||
rm ../release_output/test-ava-ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar
|
||||
pushd publish_ava
|
||||
chmod +x publish/Ryujinx.sh publish/Ryujinx.Ava
|
||||
tar -czvf ../release_output/test-ava-ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz publish
|
||||
popd
|
||||
shell: bash
|
||||
|
||||
@ -105,10 +137,82 @@ jobs:
|
||||
name: ${{ steps.version_info.outputs.build_version }}
|
||||
artifacts: "release_output/*.tar.gz,release_output/*.zip"
|
||||
tag: ${{ steps.version_info.outputs.build_version }}
|
||||
body: "For more informations about this release please check out the official [Changelog](https://github.com/Ryujinx/Ryujinx/wiki/Changelog)."
|
||||
body: "For more information about this release please check out the official [Changelog](https://github.com/Ryujinx/Ryujinx/wiki/Changelog)."
|
||||
omitBodyDuringUpdate: true
|
||||
allowUpdates: true
|
||||
removeArtifacts: true
|
||||
replacesArtifacts: true
|
||||
owner: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}
|
||||
repo: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}
|
||||
token: ${{ secrets.RELEASE_TOKEN }}
|
||||
|
||||
macos_release:
|
||||
name: Release MacOS universal
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: ${{ fromJSON(vars.JOB_TIMEOUT) }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
global-json-file: global.json
|
||||
|
||||
- name: Setup LLVM 14
|
||||
run: |
|
||||
wget https://apt.llvm.org/llvm.sh
|
||||
chmod +x llvm.sh
|
||||
sudo ./llvm.sh 14
|
||||
|
||||
- name: Install rcodesign
|
||||
run: |
|
||||
mkdir -p $HOME/.bin
|
||||
gh release download -R indygreg/apple-platform-rs -O apple-codesign.tar.gz -p 'apple-codesign-*-x86_64-unknown-linux-musl.tar.gz'
|
||||
tar -xzvf apple-codesign.tar.gz --wildcards '*/rcodesign' --strip-components=1
|
||||
rm apple-codesign.tar.gz
|
||||
mv rcodesign $HOME/.bin/
|
||||
echo "$HOME/.bin" >> $GITHUB_PATH
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Get version info
|
||||
id: version_info
|
||||
run: |
|
||||
echo "build_version=${{ env.RYUJINX_BASE_VERSION }}.${{ github.run_number }}" >> $GITHUB_OUTPUT
|
||||
echo "git_short_hash=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Configure for release
|
||||
run: |
|
||||
sed -r --in-place 's/\%\%RYUJINX_BUILD_VERSION\%\%/${{ steps.version_info.outputs.build_version }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_BUILD_GIT_HASH\%\%/${{ steps.version_info.outputs.git_short_hash }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
shell: bash
|
||||
|
||||
- name: Publish macOS Ryujinx.Ava
|
||||
run: |
|
||||
./distribution/macos/create_macos_build_ava.sh . publish_tmp_ava publish_ava ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.build_version }}" "${{ steps.version_info.outputs.git_short_hash }}" Release
|
||||
|
||||
- name: Publish macOS Ryujinx.Headless.SDL2
|
||||
run: |
|
||||
./distribution/macos/create_macos_build_headless.sh . publish_tmp_headless publish_headless ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.build_version }}" "${{ steps.version_info.outputs.git_short_hash }}" Release
|
||||
|
||||
- name: Pushing new release
|
||||
uses: ncipollo/release-action@v1
|
||||
with:
|
||||
name: ${{ steps.version_info.outputs.build_version }}
|
||||
artifacts: "publish_ava/*.tar.gz, publish_headless/*.tar.gz"
|
||||
tag: ${{ steps.version_info.outputs.build_version }}
|
||||
body: "For more information about this release please check out the official [Changelog](https://github.com/Ryujinx/Ryujinx/wiki/Changelog)."
|
||||
omitBodyDuringUpdate: true
|
||||
allowUpdates: true
|
||||
replacesArtifacts: true
|
||||
owner: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}
|
||||
repo: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}
|
||||
token: ${{ secrets.RELEASE_TOKEN }}
|
||||
|
||||
flatpak_release:
|
||||
uses: ./.github/workflows/flatpak.yml
|
||||
needs: release
|
||||
with:
|
||||
ryujinx_version: "1.1.${{ github.run_number }}"
|
||||
secrets: inherit
|
File diff suppressed because it is too large
Load Diff
@ -1,6 +0,0 @@
|
||||
namespace ARMeilleure.Decoders;
|
||||
|
||||
interface IOpCode32Exception
|
||||
{
|
||||
int Id { get; }
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
interface IOpCodeLit : IOpCode
|
||||
{
|
||||
int Rt { get; }
|
||||
long Immediate { get; }
|
||||
int Size { get; }
|
||||
bool Signed { get; }
|
||||
bool Prefetch { get; }
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
class OpCodeMemLit : OpCode, IOpCodeLit
|
||||
{
|
||||
public int Rt { get; }
|
||||
public long Immediate { get; }
|
||||
public int Size { get; }
|
||||
public bool Signed { get; }
|
||||
public bool Prefetch { get; }
|
||||
|
||||
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeMemLit(inst, address, opCode);
|
||||
|
||||
public OpCodeMemLit(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
||||
{
|
||||
Rt = opCode & 0x1f;
|
||||
|
||||
Immediate = (long)address + DecoderHelper.DecodeImmS19_2(opCode);
|
||||
|
||||
switch ((opCode >> 30) & 3)
|
||||
{
|
||||
case 0: Size = 2; Signed = false; Prefetch = false; break;
|
||||
case 1: Size = 3; Signed = false; Prefetch = false; break;
|
||||
case 2: Size = 2; Signed = true; Prefetch = false; break;
|
||||
case 3: Size = 0; Signed = false; Prefetch = true; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
class OpCodeSimdMemMs : OpCodeMemReg, IOpCodeSimd
|
||||
{
|
||||
public int Reps { get; }
|
||||
public int SElems { get; }
|
||||
public int Elems { get; }
|
||||
public bool WBack { get; }
|
||||
|
||||
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeSimdMemMs(inst, address, opCode);
|
||||
|
||||
public OpCodeSimdMemMs(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
||||
{
|
||||
switch ((opCode >> 12) & 0xf)
|
||||
{
|
||||
case 0b0000: Reps = 1; SElems = 4; break;
|
||||
case 0b0010: Reps = 4; SElems = 1; break;
|
||||
case 0b0100: Reps = 1; SElems = 3; break;
|
||||
case 0b0110: Reps = 3; SElems = 1; break;
|
||||
case 0b0111: Reps = 1; SElems = 1; break;
|
||||
case 0b1000: Reps = 1; SElems = 2; break;
|
||||
case 0b1010: Reps = 2; SElems = 1; break;
|
||||
|
||||
default: Instruction = InstDescriptor.Undefined; return;
|
||||
}
|
||||
|
||||
Size = (opCode >> 10) & 3;
|
||||
WBack = ((opCode >> 23) & 1) != 0;
|
||||
|
||||
bool q = ((opCode >> 30) & 1) != 0;
|
||||
|
||||
if (!q && Size == 3 && SElems != 1)
|
||||
{
|
||||
Instruction = InstDescriptor.Undefined;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Extend64 = false;
|
||||
|
||||
RegisterSize = q
|
||||
? RegisterSize.Simd128
|
||||
: RegisterSize.Simd64;
|
||||
|
||||
Elems = (GetBitsCount() >> 3) >> Size;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,97 +0,0 @@
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
class OpCodeSimdMemSs : OpCodeMemReg, IOpCodeSimd
|
||||
{
|
||||
public int SElems { get; }
|
||||
public int Index { get; }
|
||||
public bool Replicate { get; }
|
||||
public bool WBack { get; }
|
||||
|
||||
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeSimdMemSs(inst, address, opCode);
|
||||
|
||||
public OpCodeSimdMemSs(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
||||
{
|
||||
int size = (opCode >> 10) & 3;
|
||||
int s = (opCode >> 12) & 1;
|
||||
int sElems = (opCode >> 12) & 2;
|
||||
int scale = (opCode >> 14) & 3;
|
||||
int l = (opCode >> 22) & 1;
|
||||
int q = (opCode >> 30) & 1;
|
||||
|
||||
sElems |= (opCode >> 21) & 1;
|
||||
|
||||
sElems++;
|
||||
|
||||
int index = (q << 3) | (s << 2) | size;
|
||||
|
||||
switch (scale)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
if ((size & 1) != 0)
|
||||
{
|
||||
Instruction = InstDescriptor.Undefined;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
index >>= 1;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
if ((size & 2) != 0 ||
|
||||
((size & 1) != 0 && s != 0))
|
||||
{
|
||||
Instruction = InstDescriptor.Undefined;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ((size & 1) != 0)
|
||||
{
|
||||
index >>= 3;
|
||||
|
||||
scale = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
index >>= 2;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 3:
|
||||
{
|
||||
if (l == 0 || s != 0)
|
||||
{
|
||||
Instruction = InstDescriptor.Undefined;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
scale = size;
|
||||
|
||||
Replicate = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Index = index;
|
||||
SElems = sElems;
|
||||
Size = scale;
|
||||
|
||||
Extend64 = false;
|
||||
|
||||
WBack = ((opCode >> 23) & 1) != 0;
|
||||
|
||||
RegisterSize = q != 0
|
||||
? RegisterSize.Simd128
|
||||
: RegisterSize.Simd64;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
namespace ARMeilleure.IntermediateRepresentation
|
||||
{
|
||||
enum Comparison
|
||||
{
|
||||
Equal = 0,
|
||||
NotEqual = 1,
|
||||
Greater = 2,
|
||||
LessOrEqual = 3,
|
||||
GreaterUI = 4,
|
||||
LessOrEqualUI = 5,
|
||||
GreaterOrEqual = 6,
|
||||
Less = 7,
|
||||
GreaterOrEqualUI = 8,
|
||||
LessUI = 9
|
||||
}
|
||||
|
||||
static class ComparisonExtensions
|
||||
{
|
||||
public static Comparison Invert(this Comparison comp)
|
||||
{
|
||||
return (Comparison)((int)comp ^ 1);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace ARMeilleure.IntermediateRepresentation
|
||||
{
|
||||
enum OperandType
|
||||
{
|
||||
None,
|
||||
I32,
|
||||
I64,
|
||||
FP32,
|
||||
FP64,
|
||||
V128
|
||||
}
|
||||
|
||||
static class OperandTypeExtensions
|
||||
{
|
||||
public static bool IsInteger(this OperandType type)
|
||||
{
|
||||
return type == OperandType.I32 ||
|
||||
type == OperandType.I64;
|
||||
}
|
||||
|
||||
public static RegisterType ToRegisterType(this OperandType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case OperandType.FP32: return RegisterType.Vector;
|
||||
case OperandType.FP64: return RegisterType.Vector;
|
||||
case OperandType.I32: return RegisterType.Integer;
|
||||
case OperandType.I64: return RegisterType.Integer;
|
||||
case OperandType.V128: return RegisterType.Vector;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException($"Invalid operand type \"{type}\".");
|
||||
}
|
||||
|
||||
public static int GetSizeInBytes(this OperandType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case OperandType.FP32: return 4;
|
||||
case OperandType.FP64: return 8;
|
||||
case OperandType.I32: return 4;
|
||||
case OperandType.I64: return 8;
|
||||
case OperandType.V128: return 16;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException($"Invalid operand type \"{type}\".");
|
||||
}
|
||||
|
||||
public static int GetSizeInBytesLog2(this OperandType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case OperandType.FP32: return 2;
|
||||
case OperandType.FP64: return 3;
|
||||
case OperandType.I32: return 2;
|
||||
case OperandType.I64: return 3;
|
||||
case OperandType.V128: return 4;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException($"Invalid operand type \"{type}\".");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
namespace ARMeilleure.State
|
||||
{
|
||||
enum Aarch32Mode
|
||||
{
|
||||
User = 0b10000,
|
||||
Fiq = 0b10001,
|
||||
Irq = 0b10010,
|
||||
Supervisor = 0b10011,
|
||||
Monitor = 0b10110,
|
||||
Abort = 0b10111,
|
||||
Hypervisor = 0b11010,
|
||||
Undefined = 0b11011,
|
||||
System = 0b11111
|
||||
}
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
namespace ARMeilleure.State
|
||||
{
|
||||
enum FPException
|
||||
{
|
||||
InvalidOp = 0,
|
||||
DivideByZero = 1,
|
||||
Overflow = 2,
|
||||
Underflow = 3,
|
||||
Inexact = 4,
|
||||
InputDenorm = 7
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
namespace ARMeilleure.State
|
||||
{
|
||||
public enum FPRoundingMode
|
||||
{
|
||||
ToNearest = 0, // With ties to even.
|
||||
TowardsPlusInfinity = 1,
|
||||
TowardsMinusInfinity = 2,
|
||||
TowardsZero = 3,
|
||||
ToNearestAway = 4 // With ties to away.
|
||||
}
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
namespace ARMeilleure.State
|
||||
{
|
||||
static class RegisterConsts
|
||||
{
|
||||
public const int IntRegsCount = 32;
|
||||
public const int VecRegsCount = 32;
|
||||
public const int FlagsCount = 32;
|
||||
public const int FpFlagsCount = 32;
|
||||
public const int IntAndVecRegsCount = IntRegsCount + VecRegsCount;
|
||||
public const int FpFlagsOffset = IntRegsCount + VecRegsCount + FlagsCount;
|
||||
public const int TotalCount = IntRegsCount + VecRegsCount + FlagsCount + FpFlagsCount;
|
||||
|
||||
public const int ZeroIndex = 31;
|
||||
}
|
||||
}
|
@ -1,104 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
|
||||
namespace ARMeilleure.Translation
|
||||
{
|
||||
static class DelegateHelper
|
||||
{
|
||||
private const string DelegateTypesAssemblyName = "JitDelegateTypes";
|
||||
|
||||
private static readonly ModuleBuilder _modBuilder;
|
||||
|
||||
private static readonly Dictionary<string, Type> _delegateTypesCache;
|
||||
|
||||
static DelegateHelper()
|
||||
{
|
||||
AssemblyBuilder asmBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName(DelegateTypesAssemblyName), AssemblyBuilderAccess.Run);
|
||||
|
||||
_modBuilder = asmBuilder.DefineDynamicModule(DelegateTypesAssemblyName);
|
||||
|
||||
_delegateTypesCache = new Dictionary<string, Type>();
|
||||
}
|
||||
|
||||
public static Delegate GetDelegate(MethodInfo info)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(info);
|
||||
|
||||
Type[] parameters = info.GetParameters().Select(pI => pI.ParameterType).ToArray();
|
||||
Type returnType = info.ReturnType;
|
||||
|
||||
Type delegateType = GetDelegateType(parameters, returnType);
|
||||
|
||||
return Delegate.CreateDelegate(delegateType, info);
|
||||
}
|
||||
|
||||
private static Type GetDelegateType(Type[] parameters, Type returnType)
|
||||
{
|
||||
string key = GetFunctionSignatureKey(parameters, returnType);
|
||||
|
||||
if (!_delegateTypesCache.TryGetValue(key, out Type delegateType))
|
||||
{
|
||||
delegateType = MakeDelegateType(parameters, returnType, key);
|
||||
|
||||
_delegateTypesCache.TryAdd(key, delegateType);
|
||||
}
|
||||
|
||||
return delegateType;
|
||||
}
|
||||
|
||||
private static string GetFunctionSignatureKey(Type[] parameters, Type returnType)
|
||||
{
|
||||
string sig = GetTypeName(returnType);
|
||||
|
||||
foreach (Type type in parameters)
|
||||
{
|
||||
sig += '_' + GetTypeName(type);
|
||||
}
|
||||
|
||||
return sig;
|
||||
}
|
||||
|
||||
private static string GetTypeName(Type type)
|
||||
{
|
||||
return type.FullName.Replace(".", string.Empty);
|
||||
}
|
||||
|
||||
private const MethodAttributes CtorAttributes =
|
||||
MethodAttributes.RTSpecialName |
|
||||
MethodAttributes.HideBySig |
|
||||
MethodAttributes.Public;
|
||||
|
||||
private const TypeAttributes DelegateTypeAttributes =
|
||||
TypeAttributes.Class |
|
||||
TypeAttributes.Public |
|
||||
TypeAttributes.Sealed |
|
||||
TypeAttributes.AnsiClass |
|
||||
TypeAttributes.AutoClass;
|
||||
|
||||
private const MethodImplAttributes ImplAttributes =
|
||||
MethodImplAttributes.Runtime |
|
||||
MethodImplAttributes.Managed;
|
||||
|
||||
private const MethodAttributes InvokeAttributes =
|
||||
MethodAttributes.Public |
|
||||
MethodAttributes.HideBySig |
|
||||
MethodAttributes.NewSlot |
|
||||
MethodAttributes.Virtual;
|
||||
|
||||
private static readonly Type[] _delegateCtorSignature = { typeof(object), typeof(IntPtr) };
|
||||
|
||||
private static Type MakeDelegateType(Type[] parameters, Type returnType, string name)
|
||||
{
|
||||
TypeBuilder builder = _modBuilder.DefineType(name, DelegateTypeAttributes, typeof(MulticastDelegate));
|
||||
|
||||
builder.DefineConstructor(CtorAttributes, CallingConventions.Standard, _delegateCtorSignature).SetImplementationFlags(ImplAttributes);
|
||||
|
||||
builder.DefineMethod("Invoke", InvokeAttributes, returnType, parameters).SetImplementationFlags(ImplAttributes);
|
||||
|
||||
return builder.CreateTypeInfo();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,267 +0,0 @@
|
||||
using ARMeilleure.Instructions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
namespace ARMeilleure.Translation
|
||||
{
|
||||
static class Delegates
|
||||
{
|
||||
public static bool TryGetDelegateFuncPtrByIndex(int index, out IntPtr funcPtr)
|
||||
{
|
||||
if (index >= 0 && index < _delegates.Count)
|
||||
{
|
||||
funcPtr = _delegates.Values[index].FuncPtr; // O(1).
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
funcPtr = default;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static IntPtr GetDelegateFuncPtrByIndex(int index)
|
||||
{
|
||||
if (index < 0 || index >= _delegates.Count)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException($"({nameof(index)} = {index})");
|
||||
}
|
||||
|
||||
return _delegates.Values[index].FuncPtr; // O(1).
|
||||
}
|
||||
|
||||
public static IntPtr GetDelegateFuncPtr(MethodInfo info)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(info);
|
||||
|
||||
string key = GetKey(info);
|
||||
|
||||
if (!_delegates.TryGetValue(key, out DelegateInfo dlgInfo)) // O(log(n)).
|
||||
{
|
||||
throw new KeyNotFoundException($"({nameof(key)} = {key})");
|
||||
}
|
||||
|
||||
return dlgInfo.FuncPtr;
|
||||
}
|
||||
|
||||
public static int GetDelegateIndex(MethodInfo info)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(info);
|
||||
|
||||
string key = GetKey(info);
|
||||
|
||||
int index = _delegates.IndexOfKey(key); // O(log(n)).
|
||||
|
||||
if (index == -1)
|
||||
{
|
||||
throw new KeyNotFoundException($"({nameof(key)} = {key})");
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
private static void SetDelegateInfo(MethodInfo info)
|
||||
{
|
||||
string key = GetKey(info);
|
||||
|
||||
Delegate dlg = DelegateHelper.GetDelegate(info);
|
||||
|
||||
_delegates.Add(key, new DelegateInfo(dlg)); // ArgumentException (key).
|
||||
}
|
||||
|
||||
private static string GetKey(MethodInfo info)
|
||||
{
|
||||
return $"{info.DeclaringType.Name}.{info.Name}";
|
||||
}
|
||||
|
||||
private static readonly SortedList<string, DelegateInfo> _delegates;
|
||||
|
||||
static Delegates()
|
||||
{
|
||||
_delegates = new SortedList<string, DelegateInfo>();
|
||||
|
||||
SetDelegateInfo(typeof(Math).GetMethod(nameof(Math.Abs), new Type[] { typeof(double) }));
|
||||
SetDelegateInfo(typeof(Math).GetMethod(nameof(Math.Ceiling), new Type[] { typeof(double) }));
|
||||
SetDelegateInfo(typeof(Math).GetMethod(nameof(Math.Floor), new Type[] { typeof(double) }));
|
||||
SetDelegateInfo(typeof(Math).GetMethod(nameof(Math.Round), new Type[] { typeof(double), typeof(MidpointRounding) }));
|
||||
SetDelegateInfo(typeof(Math).GetMethod(nameof(Math.Truncate), new Type[] { typeof(double) }));
|
||||
|
||||
SetDelegateInfo(typeof(MathF).GetMethod(nameof(MathF.Abs), new Type[] { typeof(float) }));
|
||||
SetDelegateInfo(typeof(MathF).GetMethod(nameof(MathF.Ceiling), new Type[] { typeof(float) }));
|
||||
SetDelegateInfo(typeof(MathF).GetMethod(nameof(MathF.Floor), new Type[] { typeof(float) }));
|
||||
SetDelegateInfo(typeof(MathF).GetMethod(nameof(MathF.Round), new Type[] { typeof(float), typeof(MidpointRounding) }));
|
||||
SetDelegateInfo(typeof(MathF).GetMethod(nameof(MathF.Truncate), new Type[] { typeof(float) }));
|
||||
|
||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.Break)));
|
||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.CheckSynchronization)));
|
||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.EnqueueForRejit)));
|
||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntfrqEl0)));
|
||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntpctEl0)));
|
||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntvctEl0)));
|
||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCtrEl0)));
|
||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetDczidEl0)));
|
||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFunctionAddress)));
|
||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.InvalidateCacheLine)));
|
||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetTpidrroEl0)));
|
||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetTpidr32))); // A32 only.
|
||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetTpidrEl0)));
|
||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetTpidrEl032))); // A32 only.
|
||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadByte)));
|
||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt16)));
|
||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt32)));
|
||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt64)));
|
||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadVector128)));
|
||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetTpidrEl0)));
|
||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetTpidrEl032))); // A32 only.
|
||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SignalMemoryTracking)));
|
||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SupervisorCall)));
|
||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ThrowInvalidMemoryAccess)));
|
||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.Undefined)));
|
||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteByte)));
|
||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt16)));
|
||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt32)));
|
||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt64)));
|
||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteVector128)));
|
||||
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.CountLeadingSigns)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.CountLeadingZeros)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32b)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32cb)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32ch)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32cw)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32cx)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32h)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32w)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32x)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Decrypt)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Encrypt)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.FixedRotate)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashChoose)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashLower)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashMajority)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashParity)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashUpper)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.InverseMixColumns)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.MixColumns)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.PolynomialMult64_128)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToS32)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToS64)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToU32)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToU64)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF64ToS32)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF64ToS64)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF64ToU32)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF64ToU64)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha1SchedulePart1)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha1SchedulePart2)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha256SchedulePart1)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha256SchedulePart2)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedShrImm64)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl1)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl2)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl3)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl4)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx1)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx2)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx3)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx4)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedShrImm64)));
|
||||
|
||||
SetDelegateInfo(typeof(SoftFloat16_32).GetMethod(nameof(SoftFloat16_32.FPConvert)));
|
||||
SetDelegateInfo(typeof(SoftFloat16_64).GetMethod(nameof(SoftFloat16_64.FPConvert)));
|
||||
|
||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPAdd)));
|
||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPAddFpscr))); // A32 only.
|
||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompare)));
|
||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareEQ)));
|
||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareEQFpscr))); // A32 only.
|
||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareGE)));
|
||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareGEFpscr))); // A32 only.
|
||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareGT)));
|
||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareGTFpscr))); // A32 only.
|
||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareLE)));
|
||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareLEFpscr))); // A32 only.
|
||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareLT)));
|
||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareLTFpscr))); // A32 only.
|
||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPDiv)));
|
||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMax)));
|
||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMaxFpscr))); // A32 only.
|
||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMaxNum)));
|
||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMaxNumFpscr))); // A32 only.
|
||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMin)));
|
||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMinFpscr))); // A32 only.
|
||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMinNum)));
|
||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMinNumFpscr))); // A32 only.
|
||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMul)));
|
||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulFpscr))); // A32 only.
|
||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulAdd)));
|
||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulAddFpscr))); // A32 only.
|
||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulSub)));
|
||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulSubFpscr))); // A32 only.
|
||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulX)));
|
||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPNegMulAdd)));
|
||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPNegMulSub)));
|
||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRecipEstimate)));
|
||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRecipEstimateFpscr))); // A32 only.
|
||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRecipStep))); // A32 only.
|
||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRecipStepFused)));
|
||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRecpX)));
|
||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRSqrtEstimate)));
|
||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRSqrtEstimateFpscr))); // A32 only.
|
||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRSqrtStep))); // A32 only.
|
||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRSqrtStepFused)));
|
||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPSqrt)));
|
||||
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPSub)));
|
||||
|
||||
SetDelegateInfo(typeof(SoftFloat32_16).GetMethod(nameof(SoftFloat32_16.FPConvert)));
|
||||
|
||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPAdd)));
|
||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPAddFpscr))); // A32 only.
|
||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompare)));
|
||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareEQ)));
|
||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareEQFpscr))); // A32 only.
|
||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareGE)));
|
||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareGEFpscr))); // A32 only.
|
||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareGT)));
|
||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareGTFpscr))); // A32 only.
|
||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareLE)));
|
||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareLEFpscr))); // A32 only.
|
||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareLT)));
|
||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareLTFpscr))); // A32 only.
|
||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPDiv)));
|
||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMax)));
|
||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMaxFpscr))); // A32 only.
|
||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMaxNum)));
|
||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMaxNumFpscr))); // A32 only.
|
||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMin)));
|
||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMinFpscr))); // A32 only.
|
||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMinNum)));
|
||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMinNumFpscr))); // A32 only.
|
||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMul)));
|
||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulFpscr))); // A32 only.
|
||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulAdd)));
|
||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulAddFpscr))); // A32 only.
|
||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulSub)));
|
||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulSubFpscr))); // A32 only.
|
||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulX)));
|
||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPNegMulAdd)));
|
||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPNegMulSub)));
|
||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRecipEstimate)));
|
||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRecipEstimateFpscr))); // A32 only.
|
||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRecipStep))); // A32 only.
|
||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRecipStepFused)));
|
||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRecpX)));
|
||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRSqrtEstimate)));
|
||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRSqrtEstimateFpscr))); // A32 only.
|
||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRSqrtStep))); // A32 only.
|
||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRSqrtStepFused)));
|
||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPSqrt)));
|
||||
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPSub)));
|
||||
|
||||
SetDelegateInfo(typeof(SoftFloat64_16).GetMethod(nameof(SoftFloat64_16.FPConvert)));
|
||||
}
|
||||
}
|
||||
}
|
@ -3,26 +3,26 @@
|
||||
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageVersion Include="Avalonia" Version="0.10.18" />
|
||||
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="0.10.18" />
|
||||
<PackageVersion Include="Avalonia.Desktop" Version="0.10.18" />
|
||||
<PackageVersion Include="Avalonia.Diagnostics" Version="0.10.18" />
|
||||
<PackageVersion Include="Avalonia.Markup.Xaml.Loader" Version="0.10.18" />
|
||||
<PackageVersion Include="Avalonia.Svg" Version="0.10.18" />
|
||||
<PackageVersion Include="Avalonia.Svg.Skia" Version="0.10.18" />
|
||||
<PackageVersion Include="Avalonia" Version="11.0.3" />
|
||||
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.0.3" />
|
||||
<PackageVersion Include="Avalonia.Desktop" Version="11.0.3" />
|
||||
<PackageVersion Include="Avalonia.Diagnostics" Version="11.0.3" />
|
||||
<PackageVersion Include="Avalonia.Markup.Xaml.Loader" Version="11.0.3" />
|
||||
<PackageVersion Include="Avalonia.Svg" Version="11.0.0" />
|
||||
<PackageVersion Include="Avalonia.Svg.Skia" Version="11.0.0" />
|
||||
<PackageVersion Include="CommandLineParser" Version="2.9.1" />
|
||||
<PackageVersion Include="Concentus" Version="1.1.7" />
|
||||
<PackageVersion Include="Crc32.NET" Version="1.2.0" />
|
||||
<PackageVersion Include="DiscordRichPresence" Version="1.1.3.18" />
|
||||
<PackageVersion Include="DynamicData" Version="7.12.11" />
|
||||
<PackageVersion Include="FluentAvaloniaUI" Version="1.4.5" />
|
||||
<PackageVersion Include="DiscordRichPresence" Version="1.2.1.24" />
|
||||
<PackageVersion Include="DynamicData" Version="7.14.2" />
|
||||
<PackageVersion Include="FluentAvaloniaUI" Version="2.0.1" />
|
||||
<PackageVersion Include="GtkSharp.Dependencies" Version="1.1.1" />
|
||||
<PackageVersion Include="GtkSharp.Dependencies.osx" Version="0.0.5" />
|
||||
<PackageVersion Include="jp2masa.Avalonia.Flexbox" Version="0.2.0" />
|
||||
<PackageVersion Include="jp2masa.Avalonia.Flexbox" Version="0.3.0-beta.4" />
|
||||
<PackageVersion Include="LibHac" Version="0.18.0" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.5.0" />
|
||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.6.0" />
|
||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.6.3" />
|
||||
<PackageVersion Include="Microsoft.IO.RecyclableMemoryStream" Version="2.3.2" />
|
||||
<PackageVersion Include="MsgPack.Cli" Version="1.0.1" />
|
||||
<PackageVersion Include="NUnit" Version="3.13.3" />
|
||||
<PackageVersion Include="NUnit3TestAdapter" Version="4.1.0" />
|
||||
@ -34,7 +34,7 @@
|
||||
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.1-build13" />
|
||||
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
|
||||
<PackageVersion Include="Ryujinx.GtkSharp" Version="3.24.24.59-ryujinx" />
|
||||
<PackageVersion Include="Ryujinx.SDL2-CS" Version="2.26.1-build23" />
|
||||
<PackageVersion Include="Ryujinx.SDL2-CS" Version="2.28.1-build28" />
|
||||
<PackageVersion Include="shaderc.net" Version="0.1.0" />
|
||||
<PackageVersion Include="SharpZipLib" Version="1.4.2" />
|
||||
<PackageVersion Include="Silk.NET.Vulkan" Version="2.16.0" />
|
||||
@ -44,12 +44,9 @@
|
||||
<PackageVersion Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta11" />
|
||||
<PackageVersion Include="SPB" Version="0.0.4-build28" />
|
||||
<PackageVersion Include="System.Drawing.Common" Version="7.0.0" />
|
||||
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="6.27.0" />
|
||||
<PackageVersion Include="System.IO.FileSystem.Primitives" Version="4.3.0" />
|
||||
<PackageVersion Include="System.Management" Version="7.0.0" />
|
||||
<PackageVersion Include="System.Net.NameResolution" Version="4.3.0" />
|
||||
<PackageVersion Include="System.Threading.ThreadPool" Version="4.3.0" />
|
||||
<PackageVersion Include="UnicornEngine.Unicorn" Version="2.0.2-rc1-f7c841d" />
|
||||
<PackageVersion Include="XamlNameReferenceGenerator" Version="1.5.1" />
|
||||
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="6.31.0" />
|
||||
<PackageVersion Include="System.IO.Hashing" Version="7.0.0" />
|
||||
<PackageVersion Include="System.Management" Version="7.0.2" />
|
||||
<PackageVersion Include="UnicornEngine.Unicorn" Version="2.0.2-rc1-fb78016" />
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -40,7 +40,7 @@
|
||||
|
||||
## Compatibility
|
||||
|
||||
As of November 2022, Ryujinx has been tested on approximately 3,800 titles; over 3,600 boot past menus and into gameplay, with roughly 3,200 of those being considered playable.
|
||||
As of April 2023, Ryujinx has been tested on approximately 4,050 titles; over 4,000 boot past menus and into gameplay, with roughly 3,400 of those being considered playable.
|
||||
You can check out the compatibility list [here](https://github.com/Ryujinx/Ryujinx-Games-List/issues). Anyone is free to submit a new game test or update an existing game test entry; simply follow the new issue template and testing guidelines, or post as a reply to the applicable game issue. Use the search function to see if a game has been tested already!
|
||||
|
||||
## Usage
|
||||
|
@ -1,756 +0,0 @@
|
||||
using Ryujinx.Audio.Common;
|
||||
using Ryujinx.Audio.Renderer.Dsp.Command;
|
||||
using Ryujinx.Audio.Renderer.Parameter.Effect;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using static Ryujinx.Audio.Renderer.Parameter.VoiceInParameter;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Server
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="ICommandProcessingTimeEstimator"/> version 3. (added with REV8)
|
||||
/// </summary>
|
||||
public class CommandProcessingTimeEstimatorVersion3 : ICommandProcessingTimeEstimator
|
||||
{
|
||||
protected uint _sampleCount;
|
||||
protected uint _bufferCount;
|
||||
|
||||
public CommandProcessingTimeEstimatorVersion3(uint sampleCount, uint bufferCount)
|
||||
{
|
||||
_sampleCount = sampleCount;
|
||||
_bufferCount = bufferCount;
|
||||
}
|
||||
|
||||
public uint Estimate(PerformanceCommand command)
|
||||
{
|
||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
||||
|
||||
if (_sampleCount == 160)
|
||||
{
|
||||
return (uint)498.17f;
|
||||
}
|
||||
|
||||
return (uint)489.42f;
|
||||
}
|
||||
|
||||
public uint Estimate(ClearMixBufferCommand command)
|
||||
{
|
||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
||||
|
||||
float costPerBuffer = 440.68f;
|
||||
float baseCost = 0;
|
||||
|
||||
if (_sampleCount == 160)
|
||||
{
|
||||
costPerBuffer = 266.65f;
|
||||
}
|
||||
|
||||
return (uint)(baseCost + costPerBuffer * _bufferCount);
|
||||
}
|
||||
|
||||
public uint Estimate(BiquadFilterCommand command)
|
||||
{
|
||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
||||
|
||||
if (_sampleCount == 160)
|
||||
{
|
||||
return (uint)4173.2f;
|
||||
}
|
||||
|
||||
return (uint)5585.1f;
|
||||
}
|
||||
|
||||
public uint Estimate(MixRampGroupedCommand command)
|
||||
{
|
||||
float costPerSample = 6.4434f;
|
||||
|
||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
||||
|
||||
if (_sampleCount == 160)
|
||||
{
|
||||
costPerSample = 6.708f;
|
||||
}
|
||||
|
||||
int volumeCount = 0;
|
||||
|
||||
for (int i = 0; i < command.MixBufferCount; i++)
|
||||
{
|
||||
if (command.Volume0[i] != 0.0f || command.Volume1[i] != 0.0f)
|
||||
{
|
||||
volumeCount++;
|
||||
}
|
||||
}
|
||||
|
||||
return (uint)(_sampleCount * costPerSample * volumeCount);
|
||||
}
|
||||
|
||||
public uint Estimate(MixRampCommand command)
|
||||
{
|
||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
||||
|
||||
if (_sampleCount == 160)
|
||||
{
|
||||
return (uint)1968.7f;
|
||||
}
|
||||
|
||||
return (uint)2459.4f;
|
||||
}
|
||||
|
||||
public uint Estimate(DepopPrepareCommand command)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public uint Estimate(VolumeRampCommand command)
|
||||
{
|
||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
||||
|
||||
if (_sampleCount == 160)
|
||||
{
|
||||
return (uint)1425.3f;
|
||||
}
|
||||
|
||||
return (uint)1700.0f;
|
||||
}
|
||||
|
||||
public uint Estimate(PcmInt16DataSourceCommandVersion1 command)
|
||||
{
|
||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
||||
|
||||
float costPerSample = 710.143f;
|
||||
float baseCost = 7853.286f;
|
||||
|
||||
if (_sampleCount == 160)
|
||||
{
|
||||
costPerSample = 427.52f;
|
||||
baseCost = 6329.442f;
|
||||
}
|
||||
|
||||
return (uint)(baseCost + (costPerSample * (((command.SampleRate / 200.0f) / _sampleCount) * (command.Pitch * 0.000030518f))));
|
||||
}
|
||||
|
||||
public uint Estimate(AdpcmDataSourceCommandVersion1 command)
|
||||
{
|
||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
||||
|
||||
float costPerSample = 3564.1f;
|
||||
float baseCost = 9736.702f;
|
||||
|
||||
if (_sampleCount == 160)
|
||||
{
|
||||
costPerSample = 2125.6f;
|
||||
baseCost = 7913.808f;
|
||||
}
|
||||
|
||||
return (uint)(baseCost + (costPerSample * (((command.SampleRate / 200.0f) / _sampleCount) * (command.Pitch * 0.000030518f))));
|
||||
}
|
||||
|
||||
public uint Estimate(DepopForMixBuffersCommand command)
|
||||
{
|
||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
||||
|
||||
if (_sampleCount == 160)
|
||||
{
|
||||
return (uint)739.64f;
|
||||
}
|
||||
|
||||
return (uint)910.97f;
|
||||
}
|
||||
|
||||
public uint Estimate(CopyMixBufferCommand command)
|
||||
{
|
||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
||||
|
||||
if (_sampleCount == 160)
|
||||
{
|
||||
return (uint)842.59f;
|
||||
}
|
||||
|
||||
return (uint)986.72f;
|
||||
}
|
||||
|
||||
public uint Estimate(MixCommand command)
|
||||
{
|
||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
||||
|
||||
if (_sampleCount == 160)
|
||||
{
|
||||
return (uint)1402.8f;
|
||||
}
|
||||
|
||||
return (uint)1853.2f;
|
||||
}
|
||||
|
||||
public virtual uint Estimate(DelayCommand command)
|
||||
{
|
||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
||||
|
||||
if (_sampleCount == 160)
|
||||
{
|
||||
if (command.Enabled)
|
||||
{
|
||||
switch (command.Parameter.ChannelCount)
|
||||
{
|
||||
case 1:
|
||||
return (uint)8929.04f;
|
||||
case 2:
|
||||
return (uint)25500.75f;
|
||||
case 4:
|
||||
return (uint)47759.62f;
|
||||
case 6:
|
||||
return (uint)82203.07f;
|
||||
default:
|
||||
throw new NotImplementedException($"{command.Parameter.ChannelCount}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (command.Parameter.ChannelCount)
|
||||
{
|
||||
case 1:
|
||||
return (uint)1295.20f;
|
||||
case 2:
|
||||
return (uint)1213.60f;
|
||||
case 4:
|
||||
return (uint)942.03f;
|
||||
case 6:
|
||||
return (uint)1001.55f;
|
||||
default:
|
||||
throw new NotImplementedException($"{command.Parameter.ChannelCount}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (command.Enabled)
|
||||
{
|
||||
switch (command.Parameter.ChannelCount)
|
||||
{
|
||||
case 1:
|
||||
return (uint)11941.05f;
|
||||
case 2:
|
||||
return (uint)37197.37f;
|
||||
case 4:
|
||||
return (uint)69749.84f;
|
||||
case 6:
|
||||
return (uint)120042.40f;
|
||||
default:
|
||||
throw new NotImplementedException($"{command.Parameter.ChannelCount}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (command.Parameter.ChannelCount)
|
||||
{
|
||||
case 1:
|
||||
return (uint)997.67f;
|
||||
case 2:
|
||||
return (uint)977.63f;
|
||||
case 4:
|
||||
return (uint)792.30f;
|
||||
case 6:
|
||||
return (uint)875.43f;
|
||||
default:
|
||||
throw new NotImplementedException($"{command.Parameter.ChannelCount}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual uint Estimate(ReverbCommand command)
|
||||
{
|
||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
||||
|
||||
if (_sampleCount == 160)
|
||||
{
|
||||
if (command.Enabled)
|
||||
{
|
||||
switch (command.Parameter.ChannelCount)
|
||||
{
|
||||
case 1:
|
||||
return (uint)81475.05f;
|
||||
case 2:
|
||||
return (uint)84975.0f;
|
||||
case 4:
|
||||
return (uint)91625.15f;
|
||||
case 6:
|
||||
return (uint)95332.27f;
|
||||
default:
|
||||
throw new NotImplementedException($"{command.Parameter.ChannelCount}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (command.Parameter.ChannelCount)
|
||||
{
|
||||
case 1:
|
||||
return (uint)536.30f;
|
||||
case 2:
|
||||
return (uint)588.70f;
|
||||
case 4:
|
||||
return (uint)643.70f;
|
||||
case 6:
|
||||
return (uint)706.0f;
|
||||
default:
|
||||
throw new NotImplementedException($"{command.Parameter.ChannelCount}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (command.Enabled)
|
||||
{
|
||||
switch (command.Parameter.ChannelCount)
|
||||
{
|
||||
case 1:
|
||||
return (uint)120174.47f;
|
||||
case 2:
|
||||
return (uint)25262.22f;
|
||||
case 4:
|
||||
return (uint)135751.23f;
|
||||
case 6:
|
||||
return (uint)141129.23f;
|
||||
default:
|
||||
throw new NotImplementedException($"{command.Parameter.ChannelCount}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (command.Parameter.ChannelCount)
|
||||
{
|
||||
case 1:
|
||||
return (uint)617.64f;
|
||||
case 2:
|
||||
return (uint)659.54f;
|
||||
case 4:
|
||||
return (uint)711.43f;
|
||||
case 6:
|
||||
return (uint)778.07f;
|
||||
default:
|
||||
throw new NotImplementedException($"{command.Parameter.ChannelCount}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual uint Estimate(Reverb3dCommand command)
|
||||
{
|
||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
||||
|
||||
if (_sampleCount == 160)
|
||||
{
|
||||
if (command.Enabled)
|
||||
{
|
||||
switch (command.Parameter.ChannelCount)
|
||||
{
|
||||
case 1:
|
||||
return (uint)116754.0f;
|
||||
case 2:
|
||||
return (uint)125912.05f;
|
||||
case 4:
|
||||
return (uint)146336.03f;
|
||||
case 6:
|
||||
return (uint)165812.66f;
|
||||
default:
|
||||
throw new NotImplementedException($"{command.Parameter.ChannelCount}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (command.Parameter.ChannelCount)
|
||||
{
|
||||
case 1:
|
||||
return (uint)734.0f;
|
||||
case 2:
|
||||
return (uint)766.62f;
|
||||
case 4:
|
||||
return (uint)797.46f;
|
||||
case 6:
|
||||
return (uint)867.43f;
|
||||
default:
|
||||
throw new NotImplementedException($"{command.Parameter.ChannelCount}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (command.Enabled)
|
||||
{
|
||||
switch (command.Parameter.ChannelCount)
|
||||
{
|
||||
case 1:
|
||||
return (uint)170292.34f;
|
||||
case 2:
|
||||
return (uint)183875.63f;
|
||||
case 4:
|
||||
return (uint)214696.19f;
|
||||
case 6:
|
||||
return (uint)243846.77f;
|
||||
default:
|
||||
throw new NotImplementedException($"{command.Parameter.ChannelCount}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (command.Parameter.ChannelCount)
|
||||
{
|
||||
case 1:
|
||||
return (uint)508.47f;
|
||||
case 2:
|
||||
return (uint)582.45f;
|
||||
case 4:
|
||||
return (uint)626.42f;
|
||||
case 6:
|
||||
return (uint)682.47f;
|
||||
default:
|
||||
throw new NotImplementedException($"{command.Parameter.ChannelCount}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public uint Estimate(AuxiliaryBufferCommand command)
|
||||
{
|
||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
||||
|
||||
if (_sampleCount == 160)
|
||||
{
|
||||
if (command.Enabled)
|
||||
{
|
||||
return (uint)7182.14f;
|
||||
}
|
||||
|
||||
return (uint)472.11f;
|
||||
}
|
||||
|
||||
if (command.Enabled)
|
||||
{
|
||||
return (uint)9435.96f;
|
||||
}
|
||||
|
||||
return (uint)462.62f;
|
||||
}
|
||||
|
||||
public uint Estimate(VolumeCommand command)
|
||||
{
|
||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
||||
|
||||
if (_sampleCount == 160)
|
||||
{
|
||||
return (uint)1311.1f;
|
||||
}
|
||||
|
||||
return (uint)1713.6f;
|
||||
}
|
||||
|
||||
public uint Estimate(CircularBufferSinkCommand command)
|
||||
{
|
||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
||||
|
||||
float costPerBuffer = 770.26f;
|
||||
float baseCost = 0f;
|
||||
|
||||
if (_sampleCount == 160)
|
||||
{
|
||||
costPerBuffer = 531.07f;
|
||||
}
|
||||
|
||||
return (uint)(baseCost + costPerBuffer * command.InputCount);
|
||||
}
|
||||
|
||||
public uint Estimate(DownMixSurroundToStereoCommand command)
|
||||
{
|
||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
||||
|
||||
if (_sampleCount == 160)
|
||||
{
|
||||
return (uint)9949.7f;
|
||||
}
|
||||
|
||||
return (uint)14679.0f;
|
||||
}
|
||||
|
||||
public uint Estimate(UpsampleCommand command)
|
||||
{
|
||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
||||
|
||||
if (_sampleCount == 160)
|
||||
{
|
||||
return (uint)312990.0f;
|
||||
}
|
||||
|
||||
return (uint)0.0f;
|
||||
}
|
||||
|
||||
public uint Estimate(DeviceSinkCommand command)
|
||||
{
|
||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
||||
Debug.Assert(command.InputCount == 2 || command.InputCount == 6);
|
||||
|
||||
if (command.InputCount == 2)
|
||||
{
|
||||
if (_sampleCount == 160)
|
||||
{
|
||||
return (uint)8980.0f;
|
||||
}
|
||||
|
||||
return (uint)9221.9f;
|
||||
}
|
||||
|
||||
if (_sampleCount == 160)
|
||||
{
|
||||
return (uint)9177.9f;
|
||||
}
|
||||
|
||||
return (uint)9725.9f;
|
||||
}
|
||||
|
||||
public uint Estimate(PcmFloatDataSourceCommandVersion1 command)
|
||||
{
|
||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
||||
|
||||
float costPerSample = 3490.9f;
|
||||
float baseCost = 10090.9f;
|
||||
|
||||
if (_sampleCount == 160)
|
||||
{
|
||||
costPerSample = 2310.4f;
|
||||
baseCost = 7845.25f;
|
||||
}
|
||||
|
||||
return (uint)(baseCost + (costPerSample * (((command.SampleRate / 200.0f) / _sampleCount) * (command.Pitch * 0.000030518f))));
|
||||
}
|
||||
|
||||
public uint Estimate(DataSourceVersion2Command command)
|
||||
{
|
||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
||||
|
||||
(float baseCost, float costPerSample) = GetCostByFormat(_sampleCount, command.SampleFormat, command.SrcQuality);
|
||||
|
||||
return (uint)(baseCost + (costPerSample * (((command.SampleRate / 200.0f) / _sampleCount) * (command.Pitch * 0.000030518f) - 1.0f)));
|
||||
}
|
||||
|
||||
private static (float, float) GetCostByFormat(uint sampleCount, SampleFormat format, SampleRateConversionQuality quality)
|
||||
{
|
||||
Debug.Assert(sampleCount == 160 || sampleCount == 240);
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case SampleFormat.PcmInt16:
|
||||
switch (quality)
|
||||
{
|
||||
case SampleRateConversionQuality.Default:
|
||||
if (sampleCount == 160)
|
||||
{
|
||||
return (6329.44f, 427.52f);
|
||||
}
|
||||
|
||||
return (7853.28f, 710.14f);
|
||||
case SampleRateConversionQuality.High:
|
||||
if (sampleCount == 160)
|
||||
{
|
||||
return (8049.42f, 371.88f);
|
||||
}
|
||||
|
||||
return (10138.84f, 610.49f);
|
||||
case SampleRateConversionQuality.Low:
|
||||
if (sampleCount == 160)
|
||||
{
|
||||
return (5062.66f, 423.43f);
|
||||
}
|
||||
|
||||
return (5810.96f, 676.72f);
|
||||
default:
|
||||
throw new NotImplementedException($"{format} {quality}");
|
||||
}
|
||||
case SampleFormat.PcmFloat:
|
||||
switch (quality)
|
||||
{
|
||||
case SampleRateConversionQuality.Default:
|
||||
if (sampleCount == 160)
|
||||
{
|
||||
return (7845.25f, 2310.4f);
|
||||
}
|
||||
|
||||
return (10090.9f, 3490.9f);
|
||||
case SampleRateConversionQuality.High:
|
||||
if (sampleCount == 160)
|
||||
{
|
||||
return (9446.36f, 2308.91f);
|
||||
}
|
||||
|
||||
return (12520.85f, 3480.61f);
|
||||
case SampleRateConversionQuality.Low:
|
||||
if (sampleCount == 160)
|
||||
{
|
||||
return (9446.36f, 2308.91f);
|
||||
}
|
||||
|
||||
return (12520.85f, 3480.61f);
|
||||
default:
|
||||
throw new NotImplementedException($"{format} {quality}");
|
||||
}
|
||||
case SampleFormat.Adpcm:
|
||||
switch (quality)
|
||||
{
|
||||
case SampleRateConversionQuality.Default:
|
||||
if (sampleCount == 160)
|
||||
{
|
||||
return (7913.81f, 1827.66f);
|
||||
}
|
||||
|
||||
return (9736.70f, 2756.37f);
|
||||
case SampleRateConversionQuality.High:
|
||||
if (sampleCount == 160)
|
||||
{
|
||||
return (9607.81f, 1829.29f);
|
||||
}
|
||||
|
||||
return (12154.38f, 2731.31f);
|
||||
case SampleRateConversionQuality.Low:
|
||||
if (sampleCount == 160)
|
||||
{
|
||||
return (6517.48f, 1824.61f);
|
||||
}
|
||||
|
||||
return (7929.44f, 2732.15f);
|
||||
default:
|
||||
throw new NotImplementedException($"{format} {quality}");
|
||||
}
|
||||
default:
|
||||
throw new NotImplementedException($"{format}");
|
||||
}
|
||||
}
|
||||
|
||||
private uint EstimateLimiterCommandCommon(LimiterParameter parameter, bool enabled)
|
||||
{
|
||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
||||
|
||||
if (_sampleCount == 160)
|
||||
{
|
||||
if (enabled)
|
||||
{
|
||||
switch (parameter.ChannelCount)
|
||||
{
|
||||
case 1:
|
||||
return (uint)21392.0f;
|
||||
case 2:
|
||||
return (uint)26829.0f;
|
||||
case 4:
|
||||
return (uint)32405.0f;
|
||||
case 6:
|
||||
return (uint)52219.0f;
|
||||
default:
|
||||
throw new NotImplementedException($"{parameter.ChannelCount}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (parameter.ChannelCount)
|
||||
{
|
||||
case 1:
|
||||
return (uint)897.0f;
|
||||
case 2:
|
||||
return (uint)931.55f;
|
||||
case 4:
|
||||
return (uint)975.39f;
|
||||
case 6:
|
||||
return (uint)1016.8f;
|
||||
default:
|
||||
throw new NotImplementedException($"{parameter.ChannelCount}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (enabled)
|
||||
{
|
||||
switch (parameter.ChannelCount)
|
||||
{
|
||||
case 1:
|
||||
return (uint)30556.0f;
|
||||
case 2:
|
||||
return (uint)39011.0f;
|
||||
case 4:
|
||||
return (uint)48270.0f;
|
||||
case 6:
|
||||
return (uint)76712.0f;
|
||||
default:
|
||||
throw new NotImplementedException($"{parameter.ChannelCount}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (parameter.ChannelCount)
|
||||
{
|
||||
case 1:
|
||||
return (uint)874.43f;
|
||||
case 2:
|
||||
return (uint)921.55f;
|
||||
case 4:
|
||||
return (uint)945.26f;
|
||||
case 6:
|
||||
return (uint)992.26f;
|
||||
default:
|
||||
throw new NotImplementedException($"{parameter.ChannelCount}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public uint Estimate(LimiterCommandVersion1 command)
|
||||
{
|
||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
||||
|
||||
return EstimateLimiterCommandCommon(command.Parameter, command.IsEffectEnabled);
|
||||
}
|
||||
|
||||
public uint Estimate(LimiterCommandVersion2 command)
|
||||
{
|
||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
||||
|
||||
if (!command.Parameter.StatisticsEnabled || !command.IsEffectEnabled)
|
||||
{
|
||||
return EstimateLimiterCommandCommon(command.Parameter, command.IsEffectEnabled);
|
||||
}
|
||||
|
||||
if (_sampleCount == 160)
|
||||
{
|
||||
switch (command.Parameter.ChannelCount)
|
||||
{
|
||||
case 1:
|
||||
return (uint)23309.0f;
|
||||
case 2:
|
||||
return (uint)29954.0f;
|
||||
case 4:
|
||||
return (uint)35807.0f;
|
||||
case 6:
|
||||
return (uint)58340.0f;
|
||||
default:
|
||||
throw new NotImplementedException($"{command.Parameter.ChannelCount}");
|
||||
}
|
||||
}
|
||||
|
||||
switch (command.Parameter.ChannelCount)
|
||||
{
|
||||
case 1:
|
||||
return (uint)33526.0f;
|
||||
case 2:
|
||||
return (uint)43549.0f;
|
||||
case 4:
|
||||
return (uint)52190.0f;
|
||||
case 6:
|
||||
return (uint)85527.0f;
|
||||
default:
|
||||
throw new NotImplementedException($"{command.Parameter.ChannelCount}");
|
||||
}
|
||||
}
|
||||
|
||||
public virtual uint Estimate(GroupedBiquadFilterCommand command)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public virtual uint Estimate(CaptureBufferCommand command)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public virtual uint Estimate(CompressorCommand command)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,310 +0,0 @@
|
||||
using Ryujinx.Audio.Renderer.Dsp.Command;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Server
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="ICommandProcessingTimeEstimator"/> version 5. (added with REV11)
|
||||
/// </summary>
|
||||
public class CommandProcessingTimeEstimatorVersion5 : CommandProcessingTimeEstimatorVersion4
|
||||
{
|
||||
public CommandProcessingTimeEstimatorVersion5(uint sampleCount, uint bufferCount) : base(sampleCount, bufferCount) { }
|
||||
|
||||
public override uint Estimate(DelayCommand command)
|
||||
{
|
||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
||||
|
||||
if (_sampleCount == 160)
|
||||
{
|
||||
if (command.Enabled)
|
||||
{
|
||||
switch (command.Parameter.ChannelCount)
|
||||
{
|
||||
case 1:
|
||||
return 8929;
|
||||
case 2:
|
||||
return 25501;
|
||||
case 4:
|
||||
return 47760;
|
||||
case 6:
|
||||
return 82203;
|
||||
default:
|
||||
throw new NotImplementedException($"{command.Parameter.ChannelCount}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (command.Parameter.ChannelCount)
|
||||
{
|
||||
case 1:
|
||||
return (uint)1295.20f;
|
||||
case 2:
|
||||
return (uint)1213.60f;
|
||||
case 4:
|
||||
return (uint)942.03f;
|
||||
case 6:
|
||||
return (uint)1001.6f;
|
||||
default:
|
||||
throw new NotImplementedException($"{command.Parameter.ChannelCount}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (command.Enabled)
|
||||
{
|
||||
switch (command.Parameter.ChannelCount)
|
||||
{
|
||||
case 1:
|
||||
return 11941;
|
||||
case 2:
|
||||
return 37197;
|
||||
case 4:
|
||||
return 69750;
|
||||
case 6:
|
||||
return 12004;
|
||||
default:
|
||||
throw new NotImplementedException($"{command.Parameter.ChannelCount}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (command.Parameter.ChannelCount)
|
||||
{
|
||||
case 1:
|
||||
return (uint)997.67f;
|
||||
case 2:
|
||||
return (uint)977.63f;
|
||||
case 4:
|
||||
return (uint)792.31f;
|
||||
case 6:
|
||||
return (uint)875.43f;
|
||||
default:
|
||||
throw new NotImplementedException($"{command.Parameter.ChannelCount}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override uint Estimate(ReverbCommand command)
|
||||
{
|
||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
||||
|
||||
if (_sampleCount == 160)
|
||||
{
|
||||
if (command.Enabled)
|
||||
{
|
||||
switch (command.Parameter.ChannelCount)
|
||||
{
|
||||
case 1:
|
||||
return 81475;
|
||||
case 2:
|
||||
return 84975;
|
||||
case 4:
|
||||
return 91625;
|
||||
case 6:
|
||||
return 95332;
|
||||
default:
|
||||
throw new NotImplementedException($"{command.Parameter.ChannelCount}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (command.Parameter.ChannelCount)
|
||||
{
|
||||
case 1:
|
||||
return (uint)536.30f;
|
||||
case 2:
|
||||
return (uint)588.80f;
|
||||
case 4:
|
||||
return (uint)643.70f;
|
||||
case 6:
|
||||
return (uint)706.0f;
|
||||
default:
|
||||
throw new NotImplementedException($"{command.Parameter.ChannelCount}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (command.Enabled)
|
||||
{
|
||||
switch (command.Parameter.ChannelCount)
|
||||
{
|
||||
case 1:
|
||||
return 120170;
|
||||
case 2:
|
||||
return 125260;
|
||||
case 4:
|
||||
return 135750;
|
||||
case 6:
|
||||
return 141130;
|
||||
default:
|
||||
throw new NotImplementedException($"{command.Parameter.ChannelCount}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (command.Parameter.ChannelCount)
|
||||
{
|
||||
case 1:
|
||||
return (uint)617.64f;
|
||||
case 2:
|
||||
return (uint)659.54f;
|
||||
case 4:
|
||||
return (uint)711.44f;
|
||||
case 6:
|
||||
return (uint)778.07f;
|
||||
default:
|
||||
throw new NotImplementedException($"{command.Parameter.ChannelCount}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override uint Estimate(Reverb3dCommand command)
|
||||
{
|
||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
||||
|
||||
if (_sampleCount == 160)
|
||||
{
|
||||
if (command.Enabled)
|
||||
{
|
||||
switch (command.Parameter.ChannelCount)
|
||||
{
|
||||
case 1:
|
||||
return 116750;
|
||||
case 2:
|
||||
return 125910;
|
||||
case 4:
|
||||
return 146340;
|
||||
case 6:
|
||||
return 165810;
|
||||
default:
|
||||
throw new NotImplementedException($"{command.Parameter.ChannelCount}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (command.Parameter.ChannelCount)
|
||||
{
|
||||
case 1:
|
||||
return 735;
|
||||
case 2:
|
||||
return (uint)766.62f;
|
||||
case 4:
|
||||
return (uint)834.07f;
|
||||
case 6:
|
||||
return (uint)875.44f;
|
||||
default:
|
||||
throw new NotImplementedException($"{command.Parameter.ChannelCount}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (command.Enabled)
|
||||
{
|
||||
switch (command.Parameter.ChannelCount)
|
||||
{
|
||||
case 1:
|
||||
return 170290;
|
||||
case 2:
|
||||
return 183880;
|
||||
case 4:
|
||||
return 214700;
|
||||
case 6:
|
||||
return 243850;
|
||||
default:
|
||||
throw new NotImplementedException($"{command.Parameter.ChannelCount}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (command.Parameter.ChannelCount)
|
||||
{
|
||||
case 1:
|
||||
return (uint)508.47f;
|
||||
case 2:
|
||||
return (uint)582.45f;
|
||||
case 4:
|
||||
return (uint)626.42f;
|
||||
case 6:
|
||||
return (uint)682.47f;
|
||||
default:
|
||||
throw new NotImplementedException($"{command.Parameter.ChannelCount}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override uint Estimate(CompressorCommand command)
|
||||
{
|
||||
Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
|
||||
|
||||
if (_sampleCount == 160)
|
||||
{
|
||||
if (command.Enabled)
|
||||
{
|
||||
switch (command.Parameter.ChannelCount)
|
||||
{
|
||||
case 1:
|
||||
return 34431;
|
||||
case 2:
|
||||
return 44253;
|
||||
case 4:
|
||||
return 63827;
|
||||
case 6:
|
||||
return 83361;
|
||||
default:
|
||||
throw new NotImplementedException($"{command.Parameter.ChannelCount}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (command.Parameter.ChannelCount)
|
||||
{
|
||||
case 1:
|
||||
return (uint)630.12f;
|
||||
case 2:
|
||||
return (uint)638.27f;
|
||||
case 4:
|
||||
return (uint)705.86f;
|
||||
case 6:
|
||||
return (uint)782.02f;
|
||||
default:
|
||||
throw new NotImplementedException($"{command.Parameter.ChannelCount}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (command.Enabled)
|
||||
{
|
||||
switch (command.Parameter.ChannelCount)
|
||||
{
|
||||
case 1:
|
||||
return 51095;
|
||||
case 2:
|
||||
return 65693;
|
||||
case 4:
|
||||
return 95383;
|
||||
case 6:
|
||||
return 124510;
|
||||
default:
|
||||
throw new NotImplementedException($"{command.Parameter.ChannelCount}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (command.Parameter.ChannelCount)
|
||||
{
|
||||
case 1:
|
||||
return (uint)840.14f;
|
||||
case 2:
|
||||
return (uint)826.1f;
|
||||
case 4:
|
||||
return (uint)901.88f;
|
||||
case 6:
|
||||
return (uint)965.29f;
|
||||
default:
|
||||
throw new NotImplementedException($"{command.Parameter.ChannelCount}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
<Application
|
||||
x:Class="Ryujinx.Ava.App"
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:sty="using:FluentAvalonia.Styling">
|
||||
<Application.Styles>
|
||||
<sty:FluentAvaloniaTheme PreferSystemTheme="False" />
|
||||
</Application.Styles>
|
||||
</Application>
|
@ -1,65 +0,0 @@
|
||||
<Styles xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<StyleInclude Source="avares://Ryujinx.Ava/Assets/Styles/Styles.xaml" />
|
||||
<Design.PreviewWith>
|
||||
<Border Height="2000" Padding="20">
|
||||
<StackPanel Spacing="5">
|
||||
<TextBlock Text="Code Font Family" />
|
||||
<Grid RowDefinitions="*,Auto">
|
||||
<Menu Grid.Row="1" Width="100">
|
||||
<MenuItem Header="File">
|
||||
<MenuItem Header="Test 1" />
|
||||
<MenuItem Header="Test 2" />
|
||||
<MenuItem Header="Test 3">
|
||||
<MenuItem.Icon>
|
||||
<CheckBox Margin="0" IsChecked="{Binding Checkbox, Mode=TwoWay}" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button
|
||||
Name="btnAdd"
|
||||
HorizontalAlignment="Right"
|
||||
Content="Add" />
|
||||
<Button
|
||||
Name="btnRem"
|
||||
HorizontalAlignment="Right"
|
||||
Content="Add" />
|
||||
<TextBox
|
||||
Width="100"
|
||||
VerticalAlignment="Center"
|
||||
Text="Rrrrr"
|
||||
UseFloatingWatermark="True"
|
||||
Watermark="Hello" />
|
||||
<CheckBox>Test Check</CheckBox>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</Design.PreviewWith>
|
||||
<Styles.Resources>
|
||||
<SolidColorBrush x:Key="DataGridSelectionBackgroundBrush" Color="{DynamicResource DataGridSelectionColor}" />
|
||||
<SolidColorBrush x:Key="ThemeAccentColorBrush" Color="{DynamicResource SystemAccentColor}" />
|
||||
<SolidColorBrush x:Key="ThemeAccentBrush4" Color="{DynamicResource ThemeAccentColor4}" />
|
||||
<Color x:Key="ControlFillColorSecondary">#008AA8</Color>
|
||||
<SolidColorBrush x:Key="ControlFillColorSecondaryBrush" Color="{StaticResource ControlFillColorSecondary}" />
|
||||
<StaticResource x:Key="ButtonBackgroundPointerOver" ResourceKey="ControlFillColorSecondaryBrush" />
|
||||
<Color x:Key="SystemAccentColor">#FF00C3E3</Color>
|
||||
<Color x:Key="SystemAccentColorDark1">#FF99b000</Color>
|
||||
<Color x:Key="SystemAccentColorDark2">#FF006d7d</Color>
|
||||
<Color x:Key="SystemAccentColorDark3">#FF00525E</Color>
|
||||
<Color x:Key="SystemAccentColorLight1">#FF00dbff</Color>
|
||||
<Color x:Key="SystemAccentColorLight2">#FF19dfff</Color>
|
||||
<Color x:Key="SystemAccentColorLight3">#FF33e3ff</Color>
|
||||
<Color x:Key="DataGridSelectionColor">#FF00FABB</Color>
|
||||
<Color x:Key="ThemeContentBackgroundColor">#FF2D2D2D</Color>
|
||||
<Color x:Key="ThemeControlBorderColor">#FF505050</Color>
|
||||
<Color x:Key="TextOnAccentFillColorPrimary">#FFFFFFFF</Color>
|
||||
<Color x:Key="SystemChromeWhiteColor">#FFFFFFFF</Color>
|
||||
<Color x:Key="ThemeForegroundColor">#FFFFFFFF</Color>
|
||||
<Color x:Key="MenuFlyoutPresenterBorderColor">#3D3D3D</Color>
|
||||
<Color x:Key="AppListBackgroundColor">#0FFFFFFF</Color>
|
||||
<Color x:Key="AppListHoverBackgroundColor">#1EFFFFFF</Color>
|
||||
<Color x:Key="SecondaryTextColor">#A0FFFFFF</Color>
|
||||
</Styles.Resources>
|
||||
</Styles>
|
@ -1,57 +0,0 @@
|
||||
<Styles xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<StyleInclude Source="avares://Ryujinx.Ava/Assets/Styles/Styles.xaml" />
|
||||
<Design.PreviewWith>
|
||||
<Border Height="2000" Padding="20">
|
||||
<StackPanel Spacing="5">
|
||||
<TextBlock Text="Code Font Family" />
|
||||
<Grid RowDefinitions="*,Auto">
|
||||
<Menu Grid.Row="1" Width="100">
|
||||
<MenuItem Header="File">
|
||||
<MenuItem Header="Test 1" />
|
||||
<MenuItem Header="Test 2" />
|
||||
<MenuItem Header="Test 3">
|
||||
<MenuItem.Icon>
|
||||
<CheckBox Margin="0" IsChecked="{Binding Checkbox, Mode=TwoWay}" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button
|
||||
Name="btnAdd"
|
||||
HorizontalAlignment="Right"
|
||||
Content="Add" />
|
||||
<Button
|
||||
Name="btnRem"
|
||||
HorizontalAlignment="Right"
|
||||
Content="Add" />
|
||||
<TextBox
|
||||
Width="100"
|
||||
VerticalAlignment="Center"
|
||||
Text="Rrrrr"
|
||||
UseFloatingWatermark="True"
|
||||
Watermark="Hello" />
|
||||
<CheckBox>Test Check</CheckBox>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</Design.PreviewWith>
|
||||
<Styles.Resources>
|
||||
<SolidColorBrush x:Key="DataGridSelectionBackgroundBrush" Color="{DynamicResource DataGridSelectionColor}" />
|
||||
<SolidColorBrush x:Key="ThemeAccentColorBrush" Color="{DynamicResource SystemAccentColor}" />
|
||||
<SolidColorBrush x:Key="ThemeAccentBrush4" Color="{DynamicResource ThemeAccentColor4}" />
|
||||
<Color x:Key="SystemAccentColor">#FF00C3E3</Color>
|
||||
<Color x:Key="ThemeAccentColor4">#FFe8e8e8</Color>
|
||||
<Color x:Key="DataGridSelectionColor">#FF00FABB</Color>
|
||||
<Color x:Key="ThemeContentBackgroundColor">#FFF0F0F0</Color>
|
||||
<Color x:Key="ThemeControlBorderColor">#FFd6d6d6</Color>
|
||||
<Color x:Key="TextOnAccentFillColorPrimary">#FFFFFFFF</Color>
|
||||
<Color x:Key="SystemChromeWhiteColor">#FFFFFFFF</Color>
|
||||
<Color x:Key="ThemeForegroundColor">#FF000000</Color>
|
||||
<Color x:Key="MenuFlyoutPresenterBorderColor">#C1C1C1</Color>
|
||||
<Color x:Key="AppListBackgroundColor">#b3ffffff</Color>
|
||||
<Color x:Key="AppListHoverBackgroundColor">#80cccccc</Color>
|
||||
<Color x:Key="SecondaryTextColor">#A0000000</Color>
|
||||
</Styles.Resources>
|
||||
</Styles>
|
@ -1,323 +0,0 @@
|
||||
<Styles
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia">
|
||||
<Design.PreviewWith>
|
||||
<Border Height="2000" Padding="20">
|
||||
<StackPanel Spacing="5">
|
||||
<TextBlock Text="Code Font Family" />
|
||||
<Grid RowDefinitions="*,Auto">
|
||||
<Menu Grid.Row="1" Width="100">
|
||||
<MenuItem Header="File">
|
||||
<MenuItem Header="Test 1" />
|
||||
<MenuItem Header="Test 2" />
|
||||
<MenuItem Header="Test 3">
|
||||
<MenuItem.Icon>
|
||||
<CheckBox Margin="0" IsChecked="{Binding Checkbox, Mode=TwoWay}" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<ToggleButton
|
||||
Name="btnAdd"
|
||||
Height="28"
|
||||
HorizontalAlignment="Right"
|
||||
Content="Addy" />
|
||||
<Button
|
||||
Name="btnRem"
|
||||
HorizontalAlignment="Right"
|
||||
Content="Add" />
|
||||
<TextBox
|
||||
Width="100"
|
||||
VerticalAlignment="Center"
|
||||
Text="Rrrrr"
|
||||
UseFloatingWatermark="True"
|
||||
Watermark="Hello" />
|
||||
<CheckBox>Test Check</CheckBox>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<ui:NumberBox Value="1" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</Design.PreviewWith>
|
||||
<Style Selector="Border.small">
|
||||
<Setter Property="Width" Value="100" />
|
||||
</Style>
|
||||
<Style Selector="Border.normal">
|
||||
<Setter Property="Width" Value="130" />
|
||||
</Style>
|
||||
<Style Selector="Border.large">
|
||||
<Setter Property="Width" Value="160" />
|
||||
</Style>
|
||||
<Style Selector="Border.huge">
|
||||
<Setter Property="Width" Value="200" />
|
||||
</Style>
|
||||
<Style Selector="Border.settings">
|
||||
<Setter Property="Background" Value="{DynamicResource ThemeDarkColor}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource MenuFlyoutPresenterBorderColor}" />
|
||||
<Setter Property="BorderThickness" Value="1" />
|
||||
<Setter Property="CornerRadius" Value="5" />
|
||||
</Style>
|
||||
<Style Selector="Image.small">
|
||||
<Setter Property="Width" Value="50" />
|
||||
</Style>
|
||||
<Style Selector="Image.normal">
|
||||
<Setter Property="Width" Value="80" />
|
||||
</Style>
|
||||
<Style Selector="Image.large">
|
||||
<Setter Property="Width" Value="100" />
|
||||
</Style>
|
||||
<Style Selector="Image.huge">
|
||||
<Setter Property="Width" Value="120" />
|
||||
</Style>
|
||||
<Style Selector="#TitleBarHost > Image">
|
||||
<Setter Property="Margin" Value="10" />
|
||||
</Style>
|
||||
<Style Selector="#TitleBarHost > Label">
|
||||
<Setter Property="Margin" Value="5" />
|
||||
<Setter Property="FontSize" Value="14" />
|
||||
</Style>
|
||||
<Style Selector="Button.SystemCaption">
|
||||
<Setter Property="MinWidth" Value="10" />
|
||||
</Style>
|
||||
<Style Selector="DataGridColumnHeader">
|
||||
<Setter Property="Foreground" Value="{DynamicResource ThemeForegroundBrush}" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Center" />
|
||||
<Setter Property="BorderThickness" Value="1" />
|
||||
<Setter Property="VerticalContentAlignment" Value="Center" />
|
||||
<Setter Property="Background" Value="{DynamicResource ThemeControlBorderColor}" />
|
||||
<Setter Property="SeparatorBrush" Value="{DynamicResource ThemeControlBorderColor}" />
|
||||
<Setter Property="Padding" Value="5" />
|
||||
<Setter Property="Background" Value="{DynamicResource ThemeContentBackgroundColor}" />
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<Grid Background="{TemplateBinding Background}" ColumnDefinitions="*,Auto">
|
||||
<Grid
|
||||
Margin="{TemplateBinding Padding}"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
ColumnDefinitions="*,Auto">
|
||||
<ContentPresenter Content="{TemplateBinding Content}" />
|
||||
<Path
|
||||
Name="SortIcon"
|
||||
Grid.Column="1"
|
||||
Width="8"
|
||||
Margin="4,0,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Data="F1 M -5.215,6.099L 5.215,6.099L 0,0L -5.215,6.099 Z "
|
||||
Fill="{TemplateBinding Foreground}"
|
||||
Stretch="Uniform" />
|
||||
</Grid>
|
||||
<Rectangle
|
||||
Name="VerticalSeparator"
|
||||
Grid.Column="1"
|
||||
Width="1"
|
||||
VerticalAlignment="Stretch"
|
||||
Fill="{TemplateBinding SeparatorBrush}"
|
||||
IsVisible="{TemplateBinding AreSeparatorsVisible}" />
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
</Style>
|
||||
<Style Selector="DataGrid">
|
||||
<Setter Property="RowBackground" Value="{DynamicResource ThemeAccentBrush4}" />
|
||||
<Setter Property="AlternatingRowBackground" Value="#00FFFFFF" />
|
||||
<Setter Property="Background" Value="{DynamicResource ThemeBackgroundBrush}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ThemeBorderLowColor}" />
|
||||
<Setter Property="BorderThickness" Value="{DynamicResource ThemeBorderThickness}" />
|
||||
</Style>
|
||||
<Style Selector="DataGridRow:selected:focus /template/ Rectangle#BackgroundRectangle">
|
||||
<Setter Property="Fill" Value="{DynamicResource SystemAccentColor}" />
|
||||
<Setter Property="Opacity" Value="{DynamicResource DataGridRowSelectedBackgroundOpacity}" />
|
||||
</Style>
|
||||
<Style Selector="DataGridRow:pointerover /template/ Rectangle#BackgroundRectangle">
|
||||
<Setter Property="Fill" Value="{DynamicResource SystemListLowColor}" />
|
||||
</Style>
|
||||
<Style Selector="DataGridRow:selected /template/ Rectangle#BackgroundRectangle">
|
||||
<Setter Property="Fill" Value="{DynamicResource SystemAccentColor}" />
|
||||
<Setter Property="Opacity" Value="{DynamicResource DataGridRowSelectedUnfocusedBackgroundOpacity}" />
|
||||
</Style>
|
||||
<Style Selector="DataGridRow:selected:pointerover /template/ Rectangle#BackgroundRectangle">
|
||||
<Setter Property="Fill" Value="{DynamicResource SystemAccentColor}" />
|
||||
<Setter Property="Opacity" Value="{DynamicResource DataGridRowSelectedHoveredUnfocusedBackgroundOpacity}" />
|
||||
</Style>
|
||||
<Style Selector="DataGridRow:selected:pointerover:focus /template/ Rectangle#BackgroundRectangle">
|
||||
<Setter Property="Fill" Value="{DynamicResource SystemAccentColor}" />
|
||||
<Setter Property="Opacity" Value="{DynamicResource DataGridRowSelectedHoveredBackgroundOpacity}" />
|
||||
</Style>
|
||||
<Style Selector="DataGridCell">
|
||||
<Setter Property="HorizontalAlignment" Value="Center" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Center" />
|
||||
</Style>
|
||||
<Style Selector="DataGridCell.Left">
|
||||
<Setter Property="HorizontalAlignment" Value="Left" />
|
||||
</Style>
|
||||
<Style Selector="CheckBox">
|
||||
<Setter Property="BorderThickness" Value="1" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="MenuItem">
|
||||
<Setter Property="Height" Value="{DynamicResource MenuItemHeight}" />
|
||||
<Setter Property="Padding" Value="{DynamicResource MenuItemPadding}" />
|
||||
<Setter Property="FontSize" Value="12" />
|
||||
</Style>
|
||||
<Style Selector="MenuItem:selected /template/ Border#root">
|
||||
<Setter Property="Background" Value="{DynamicResource ThemeControlBorderColor}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ThemeControlBorderColor}" />
|
||||
</Style>
|
||||
<Style Selector="TabItem > ScrollViewer">
|
||||
<Setter Property="Background" Value="{DynamicResource ThemeBackgroundColor}" />
|
||||
<Setter Property="Margin" Value="0,-5,0,0" />
|
||||
</Style>
|
||||
<Style Selector="TabItem > ScrollViewer > Border">
|
||||
<Setter Property="BorderThickness" Value="0,1,0,0" />
|
||||
<Setter Property="Background" Value="{DynamicResource ThemeBackgroundColor}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource HighlightBrush}" />
|
||||
</Style>
|
||||
<Style Selector="Button">
|
||||
<Setter Property="MinWidth" Value="80" />
|
||||
</Style>
|
||||
<Style Selector="ProgressBar /template/ Border#ProgressBarTrack">
|
||||
<Setter Property="IsVisible" Value="False" />
|
||||
</Style>
|
||||
<Style Selector="ToggleButton">
|
||||
<Setter Property="Padding" Value="0,-5,0,0" />
|
||||
</Style>
|
||||
<Style Selector="TabItem">
|
||||
<Setter Property="FontSize" Value="14" />
|
||||
<Setter Property="BorderThickness" Value="0,0,1,0" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ThemeButtonForegroundColor}" />
|
||||
<Setter Property="Background" Value="{DynamicResource HighlightColor}" />
|
||||
</Style>
|
||||
<Style Selector="TabItem:pointerover">
|
||||
<Setter Property="Foreground" Value="{DynamicResource ThemeButtonForegroundColor}" />
|
||||
</Style>
|
||||
<Style Selector="TabItem:selected">
|
||||
<Setter Property="Background" Value="{DynamicResource HighlightColor}" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource ThemeBackgroundColor}" />
|
||||
</Style>
|
||||
<Style Selector="TextBlock">
|
||||
<Setter Property="Margin" Value="{DynamicResource TextMargin}" />
|
||||
<Setter Property="FontSize" Value="{DynamicResource FontSize}" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
<Setter Property="TextWrapping" Value="WrapWithOverflow" />
|
||||
</Style>
|
||||
<Style Selector="TextBlock.h1">
|
||||
<Setter Property="Margin" Value="{DynamicResource TextMargin}" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
<Setter Property="FontWeight" Value="Bold" />
|
||||
<Setter Property="FontSize" Value="16" />
|
||||
<Setter Property="TextWrapping" Value="WrapWithOverflow" />
|
||||
</Style>
|
||||
<Style Selector="Separator">
|
||||
<Setter Property="Background" Value="{DynamicResource ThemeControlBorderColor}" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource ThemeControlBorderColor}" />
|
||||
<Setter Property="MinHeight" Value="1" />
|
||||
</Style>
|
||||
<Style Selector=":is(Button).DateTimeFlyoutButtonStyle">
|
||||
<Setter Property="Background" Value="{DynamicResource HighlightColor}" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource ThemeBackgroundColor}" />
|
||||
</Style>
|
||||
<Style Selector="DatePickerPresenter">
|
||||
<Setter Property="BorderThickness" Value="1" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ThemeButtonForegroundColor}" />
|
||||
</Style>
|
||||
<Style Selector="DataGridCell">
|
||||
<Setter Property="FontSize" Value="14" />
|
||||
</Style>
|
||||
<Style Selector="CheckBox TextBlock">
|
||||
<Setter Property="Margin" Value="0,5,0,0" />
|
||||
</Style>
|
||||
<Style Selector="ContextMenu">
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource MenuFlyoutPresenterBorderBrush}" />
|
||||
<Setter Property="BorderThickness" Value="{DynamicResource MenuFlyoutPresenterBorderThemeThickness}" />
|
||||
</Style>
|
||||
<Style Selector="TextBox">
|
||||
<Setter Property="VerticalContentAlignment" Value="Center" />
|
||||
</Style>
|
||||
<Style Selector="TextBox.NumberBoxTextBoxStyle">
|
||||
<Setter Property="Foreground" Value="{DynamicResource ThemeForegroundColor}" />
|
||||
</Style>
|
||||
<Style Selector="ListBox ListBoxItem">
|
||||
<Setter Property="Padding" Value="0" />
|
||||
<Setter Property="Margin" Value="0" />
|
||||
<Setter Property="CornerRadius" Value="5" />
|
||||
<Setter Property="Background" Value="{DynamicResource AppListBackgroundColor}" />
|
||||
<Setter Property="BorderThickness" Value="2"/>
|
||||
<Style.Animations>
|
||||
<Animation Duration="0:0:0.7">
|
||||
<KeyFrame Cue="0%">
|
||||
<Setter Property="MaxHeight" Value="0" />
|
||||
<Setter Property="Opacity" Value="0.0" />
|
||||
</KeyFrame>
|
||||
<KeyFrame Cue="50%">
|
||||
<Setter Property="MaxHeight" Value="1000" />
|
||||
<Setter Property="Opacity" Value="0.3" />
|
||||
</KeyFrame>
|
||||
<KeyFrame Cue="100%">
|
||||
<Setter Property="MaxHeight" Value="1000" />
|
||||
<Setter Property="Opacity" Value="1.0" />
|
||||
</KeyFrame>
|
||||
</Animation>
|
||||
</Style.Animations>
|
||||
</Style>
|
||||
<Style Selector="ListBox ListBoxItem:selected /template/ ContentPresenter">
|
||||
<Setter Property="Background" Value="{DynamicResource AppListBackgroundColor}" />
|
||||
</Style>
|
||||
<Style Selector="ListBox ListBoxItem:pointerover /template/ ContentPresenter">
|
||||
<Setter Property="Background" Value="{DynamicResource AppListHoverBackgroundColor}" />
|
||||
</Style>
|
||||
<Styles.Resources>
|
||||
<SolidColorBrush x:Key="ThemeAccentColorBrush" Color="{DynamicResource SystemAccentColor}" />
|
||||
<StaticResource x:Key="ListViewItemBackgroundSelected" ResourceKey="ThemeAccentColorBrush" />
|
||||
<StaticResource x:Key="ListViewItemBackgroundPressed" ResourceKey="SystemAccentColorDark1" />
|
||||
<StaticResource x:Key="ListViewItemBackgroundPointerOver" ResourceKey="SystemAccentColorDark2" />
|
||||
<StaticResource x:Key="ListViewItemBackgroundSelectedPressed" ResourceKey="ThemeAccentColorBrush" />
|
||||
<StaticResource x:Key="ListViewItemBackgroundSelectedPointerOver" ResourceKey="SystemAccentColorDark2" />
|
||||
<SolidColorBrush
|
||||
x:Key="DataGridGridLinesBrush"
|
||||
Opacity="0.4"
|
||||
Color="{DynamicResource SystemBaseMediumLowColor}" />
|
||||
<SolidColorBrush x:Key="DataGridSelectionBackgroundBrush" Color="{DynamicResource DataGridSelectionColor}" />
|
||||
<SolidColorBrush x:Key="MenuFlyoutPresenterBorderBrush" Color="{DynamicResource MenuFlyoutPresenterBorderColor}" />
|
||||
<SolidColorBrush x:Key="FlyoutBorderThemeBrush" Color="{DynamicResource MenuFlyoutPresenterBorderColor}" />
|
||||
<SolidColorBrush x:Key="ListBoxBackground" Color="{DynamicResource ThemeContentBackgroundColor}" />
|
||||
<SolidColorBrush x:Key="ThemeForegroundBrush" Color="{DynamicResource ThemeForegroundColor}" />
|
||||
<SolidColorBrush x:Key="ThemeAccentBrush4" Color="{DynamicResource ThemeAccentColor4}" />
|
||||
<SolidColorBrush x:Key="SplitButtonBackgroundChecked" Color="#00E81123" />
|
||||
<SolidColorBrush x:Key="SplitButtonBackgroundCheckedPointerOver" Color="#00E81123" />
|
||||
<SolidColorBrush x:Key="SplitButtonBackgroundCheckedPressed" Color="#00E81123" />
|
||||
<SolidColorBrush x:Key="SplitButtonBackgroundCheckedDisabled" Color="#00E81123" />
|
||||
<Thickness x:Key="PageMargin">40 0 40 0</Thickness>
|
||||
<Thickness x:Key="Margin">0 5 0 5</Thickness>
|
||||
<Thickness x:Key="MenuItemPadding">5 0 5 0</Thickness>
|
||||
<Color x:Key="MenuFlyoutPresenterBorderColor">#00000000</Color>
|
||||
<Color x:Key="SystemAccentColor">#FF00C3E3</Color>
|
||||
<Color x:Key="SystemAccentColorDark1">#FF00C3E3</Color>
|
||||
<Color x:Key="SystemAccentColorDark2">#FF00C3E3</Color>
|
||||
<Color x:Key="SystemAccentColorDark3">#FF00C3E3</Color>
|
||||
<Color x:Key="SystemAccentColorLight1">#FF00C3E3</Color>
|
||||
<Color x:Key="SystemAccentColorLight2">#FF00C3E3</Color>
|
||||
<Color x:Key="SystemAccentColorLight3">#FF00C3E3</Color>
|
||||
<Color x:Key="DataGridSelectionColor">#FF00FABB</Color>
|
||||
<Color x:Key="ThemeContentBackgroundColor">#FF2D2D2D</Color>
|
||||
<Color x:Key="ThemeControlBorderColor">#FF505050</Color>
|
||||
<Color x:Key="VsyncEnabled">#FF2EEAC9</Color>
|
||||
<Color x:Key="VsyncDisabled">#FFFF4554</Color>
|
||||
<Color x:Key="AppListBackgroundColor">#0FFFFFFF</Color>
|
||||
<Color x:Key="AppListHoverBackgroundColor">#1EFFFFFF</Color>
|
||||
<Color x:Key="SecondaryTextColor">#A0FFFFFF</Color>
|
||||
<x:Double x:Key="ScrollBarThickness">15</x:Double>
|
||||
<x:Double x:Key="FontSizeSmall">8</x:Double>
|
||||
<x:Double x:Key="FontSizeNormal">10</x:Double>
|
||||
<x:Double x:Key="FontSize">12</x:Double>
|
||||
<x:Double x:Key="FontSizeLarge">15</x:Double>
|
||||
<x:Double x:Key="ControlContentThemeFontSize">13</x:Double>
|
||||
<x:Double x:Key="MenuItemHeight">26</x:Double>
|
||||
<x:Double x:Key="TabItemMinHeight">28</x:Double>
|
||||
<x:Double x:Key="ContentDialogMaxWidth">600</x:Double>
|
||||
<x:Double x:Key="ContentDialogMaxHeight">756</x:Double>
|
||||
</Styles.Resources>
|
||||
</Styles>
|
@ -1,177 +0,0 @@
|
||||
<UserControl
|
||||
x:Class="Ryujinx.Ava.UI.Controls.GameGridView"
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:flex="clr-namespace:Avalonia.Flexbox;assembly=Avalonia.Flexbox"
|
||||
xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
|
||||
d:DesignHeight="450"
|
||||
d:DesignWidth="800"
|
||||
mc:Ignorable="d"
|
||||
Focusable="True">
|
||||
<UserControl.Resources>
|
||||
<helpers:BitmapArrayValueConverter x:Key="ByteImage" />
|
||||
<MenuFlyout x:Key="GameContextMenu">
|
||||
<MenuItem
|
||||
Command="{Binding ToggleFavorite}"
|
||||
Header="{locale:Locale GameListContextMenuToggleFavorite}"
|
||||
ToolTip.Tip="{locale:Locale GameListContextMenuToggleFavoriteToolTip}" />
|
||||
<Separator />
|
||||
<MenuItem
|
||||
Command="{Binding OpenUserSaveDirectory}"
|
||||
IsEnabled="{Binding EnabledUserSaveDirectory}"
|
||||
Header="{locale:Locale GameListContextMenuOpenUserSaveDirectory}"
|
||||
ToolTip.Tip="{locale:Locale GameListContextMenuOpenUserSaveDirectoryToolTip}" />
|
||||
<MenuItem
|
||||
Command="{Binding OpenDeviceSaveDirectory}"
|
||||
IsEnabled="{Binding EnabledDeviceSaveDirectory}"
|
||||
Header="{locale:Locale GameListContextMenuOpenDeviceSaveDirectory}"
|
||||
ToolTip.Tip="{locale:Locale GameListContextMenuOpenDeviceSaveDirectoryToolTip}" />
|
||||
<MenuItem
|
||||
Command="{Binding OpenBcatSaveDirectory}"
|
||||
IsEnabled="{Binding EnabledBcatSaveDirectory}"
|
||||
Header="{locale:Locale GameListContextMenuOpenBcatSaveDirectory}"
|
||||
ToolTip.Tip="{locale:Locale GameListContextMenuOpenBcatSaveDirectoryToolTip}" />
|
||||
<Separator />
|
||||
<MenuItem
|
||||
Command="{Binding OpenTitleUpdateManager}"
|
||||
Header="{locale:Locale GameListContextMenuManageTitleUpdates}"
|
||||
ToolTip.Tip="{locale:Locale GameListContextMenuManageTitleUpdatesToolTip}" />
|
||||
<MenuItem
|
||||
Command="{Binding OpenDownloadableContentManager}"
|
||||
Header="{locale:Locale GameListContextMenuManageDlc}"
|
||||
ToolTip.Tip="{locale:Locale GameListContextMenuManageDlcToolTip}" />
|
||||
<MenuItem
|
||||
Command="{Binding OpenCheatManager}"
|
||||
Header="{locale:Locale GameListContextMenuManageCheat}"
|
||||
ToolTip.Tip="{locale:Locale GameListContextMenuManageCheatToolTip}" />
|
||||
<MenuItem
|
||||
Command="{Binding OpenModsDirectory}"
|
||||
Header="{locale:Locale GameListContextMenuOpenModsDirectory}"
|
||||
ToolTip.Tip="{locale:Locale GameListContextMenuOpenModsDirectoryToolTip}" />
|
||||
<MenuItem
|
||||
Command="{Binding OpenSdModsDirectory}"
|
||||
Header="{locale:Locale GameListContextMenuOpenSdModsDirectory}"
|
||||
ToolTip.Tip="{locale:Locale GameListContextMenuOpenSdModsDirectoryToolTip}" />
|
||||
<Separator />
|
||||
<MenuItem Header="{locale:Locale GameListContextMenuCacheManagement}">
|
||||
<MenuItem
|
||||
Command="{Binding PurgePtcCache}"
|
||||
Header="{locale:Locale GameListContextMenuCacheManagementPurgePptc}"
|
||||
ToolTip.Tip="{locale:Locale GameListContextMenuCacheManagementPurgePptcToolTip}" />
|
||||
<MenuItem
|
||||
Command="{Binding PurgeShaderCache}"
|
||||
Header="{locale:Locale GameListContextMenuCacheManagementPurgeShaderCache}"
|
||||
ToolTip.Tip="{locale:Locale GameListContextMenuCacheManagementPurgeShaderCacheToolTip}" />
|
||||
<MenuItem
|
||||
Command="{Binding OpenPtcDirectory}"
|
||||
Header="{locale:Locale GameListContextMenuCacheManagementOpenPptcDirectory}"
|
||||
ToolTip.Tip="{locale:Locale GameListContextMenuCacheManagementOpenPptcDirectoryToolTip}" />
|
||||
<MenuItem
|
||||
Command="{Binding OpenShaderCacheDirectory}"
|
||||
Header="{locale:Locale GameListContextMenuCacheManagementOpenShaderCacheDirectory}"
|
||||
ToolTip.Tip="{locale:Locale GameListContextMenuCacheManagementOpenShaderCacheDirectoryToolTip}" />
|
||||
</MenuItem>
|
||||
<MenuItem Header="{locale:Locale GameListContextMenuExtractData}">
|
||||
<MenuItem
|
||||
Command="{Binding ExtractExeFs}"
|
||||
Header="{locale:Locale GameListContextMenuExtractDataExeFS}"
|
||||
ToolTip.Tip="{locale:Locale GameListContextMenuExtractDataExeFSToolTip}" />
|
||||
<MenuItem
|
||||
Command="{Binding ExtractRomFs}"
|
||||
Header="{locale:Locale GameListContextMenuExtractDataRomFS}"
|
||||
ToolTip.Tip="{locale:Locale GameListContextMenuExtractDataRomFSToolTip}" />
|
||||
<MenuItem
|
||||
Command="{Binding ExtractLogo}"
|
||||
Header="{locale:Locale GameListContextMenuExtractDataLogo}"
|
||||
ToolTip.Tip="{locale:Locale GameListContextMenuExtractDataLogoToolTip}" />
|
||||
</MenuItem>
|
||||
</MenuFlyout>
|
||||
</UserControl.Resources>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<ListBox
|
||||
Grid.Row="0"
|
||||
Padding="8"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
ContextFlyout="{StaticResource GameContextMenu}"
|
||||
DoubleTapped="GameList_DoubleTapped"
|
||||
Items="{Binding AppsObservableList}"
|
||||
SelectionChanged="GameList_SelectionChanged">
|
||||
<ListBox.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<flex:FlexPanel
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
AlignContent="FlexStart"
|
||||
JustifyContent="Center" />
|
||||
</ItemsPanelTemplate>
|
||||
</ListBox.ItemsPanel>
|
||||
<ListBox.Styles>
|
||||
<Style Selector="ListBoxItem">
|
||||
<Setter Property="Margin" Value="5" />
|
||||
<Setter Property="CornerRadius" Value="4" />
|
||||
</Style>
|
||||
<Style Selector="ListBoxItem:selected /template/ Border#SelectionIndicator">
|
||||
<Setter Property="MinHeight" Value="{Binding $parent[UserControl].DataContext.GridItemSelectorSize}" />
|
||||
</Style>
|
||||
</ListBox.Styles>
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Grid>
|
||||
<Border
|
||||
Margin="10"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
Classes.huge="{Binding $parent[UserControl].DataContext.IsGridHuge}"
|
||||
Classes.large="{Binding $parent[UserControl].DataContext.IsGridLarge}"
|
||||
Classes.normal="{Binding $parent[UserControl].DataContext.IsGridMedium}"
|
||||
Classes.small="{Binding $parent[UserControl].DataContext.IsGridSmall}"
|
||||
ClipToBounds="True"
|
||||
CornerRadius="4">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Image
|
||||
Grid.Row="0"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Top"
|
||||
Source="{Binding Icon, Converter={StaticResource ByteImage}}" />
|
||||
<Panel
|
||||
Grid.Row="1"
|
||||
Height="50"
|
||||
Margin="0 10 0 0"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
IsVisible="{Binding $parent[UserControl].DataContext.ShowNames}">
|
||||
<TextBlock
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding TitleName}"
|
||||
TextAlignment="Center"
|
||||
TextWrapping="Wrap" />
|
||||
</Panel>
|
||||
</Grid>
|
||||
</Border>
|
||||
<ui:SymbolIcon
|
||||
Margin="5,5,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top"
|
||||
FontSize="16"
|
||||
Foreground="{DynamicResource SystemAccentColor}"
|
||||
IsVisible="{Binding Favorite}"
|
||||
Symbol="StarFilled" />
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
</Grid>
|
||||
</UserControl>
|
@ -1,32 +0,0 @@
|
||||
<UserControl
|
||||
x:Class="Ryujinx.Ava.UI.Controls.InputDialog"
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d"
|
||||
Focusable="True">
|
||||
<Grid
|
||||
Margin="5,10,5,5"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Center">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock HorizontalAlignment="Center" Text="{Binding Message}" />
|
||||
<TextBox
|
||||
Grid.Row="1"
|
||||
Width="300"
|
||||
Margin="10"
|
||||
HorizontalAlignment="Center"
|
||||
MaxLength="{Binding MaxLength}"
|
||||
Text="{Binding Input, Mode=TwoWay}" />
|
||||
<TextBlock
|
||||
Grid.Row="2"
|
||||
Margin="5,5,5,10"
|
||||
HorizontalAlignment="Center"
|
||||
Text="{Binding SubMessage}" />
|
||||
</Grid>
|
||||
</UserControl>
|
@ -1,57 +0,0 @@
|
||||
using Avalonia.Controls;
|
||||
using FluentAvalonia.UI.Controls;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.Models;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Controls
|
||||
{
|
||||
public partial class InputDialog : UserControl
|
||||
{
|
||||
public string Message { get; set; }
|
||||
public string Input { get; set; }
|
||||
public string SubMessage { get; set; }
|
||||
|
||||
public uint MaxLength { get; }
|
||||
|
||||
public InputDialog(string message, string input = "", string subMessage = "", uint maxLength = int.MaxValue)
|
||||
{
|
||||
Message = message;
|
||||
Input = input;
|
||||
SubMessage = subMessage;
|
||||
MaxLength = maxLength;
|
||||
|
||||
DataContext = this;
|
||||
}
|
||||
|
||||
public InputDialog()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public static async Task<(UserResult Result, string Input)> ShowInputDialog(string title, string message,
|
||||
string input = "", string subMessage = "", uint maxLength = int.MaxValue)
|
||||
{
|
||||
UserResult result = UserResult.Cancel;
|
||||
|
||||
InputDialog content = new InputDialog(message, input, subMessage, maxLength);
|
||||
ContentDialog contentDialog = new ContentDialog
|
||||
{
|
||||
Title = title,
|
||||
PrimaryButtonText = LocaleManager.Instance[LocaleKeys.InputDialogOk],
|
||||
SecondaryButtonText = "",
|
||||
CloseButtonText = LocaleManager.Instance[LocaleKeys.InputDialogCancel],
|
||||
Content = content,
|
||||
PrimaryButtonCommand = MiniCommand.Create(() =>
|
||||
{
|
||||
result = UserResult.Ok;
|
||||
input = content.Input;
|
||||
})
|
||||
};
|
||||
await contentDialog.ShowAsync();
|
||||
|
||||
return (result, input);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using System;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Helpers
|
||||
{
|
||||
public class HotKeyControl : ContentControl, ICommandSource
|
||||
{
|
||||
public static readonly StyledProperty<object> CommandParameterProperty =
|
||||
AvaloniaProperty.Register<HotKeyControl, object>(nameof(CommandParameter));
|
||||
|
||||
public static readonly DirectProperty<HotKeyControl, ICommand> CommandProperty =
|
||||
AvaloniaProperty.RegisterDirect<HotKeyControl, ICommand>(nameof(Command),
|
||||
control => control.Command, (control, command) => control.Command = command, enableDataValidation: true);
|
||||
|
||||
public static readonly StyledProperty<KeyGesture> HotKeyProperty = HotKeyManager.HotKeyProperty.AddOwner<Button>();
|
||||
|
||||
private ICommand _command;
|
||||
private bool _commandCanExecute;
|
||||
|
||||
public ICommand Command
|
||||
{
|
||||
get { return _command; }
|
||||
set { SetAndRaise(CommandProperty, ref _command, value); }
|
||||
}
|
||||
|
||||
public KeyGesture HotKey
|
||||
{
|
||||
get { return GetValue(HotKeyProperty); }
|
||||
set { SetValue(HotKeyProperty, value); }
|
||||
}
|
||||
|
||||
public object CommandParameter
|
||||
{
|
||||
get { return GetValue(CommandParameterProperty); }
|
||||
set { SetValue(CommandParameterProperty, value); }
|
||||
}
|
||||
|
||||
public void CanExecuteChanged(object sender, EventArgs e)
|
||||
{
|
||||
var canExecute = Command == null || Command.CanExecute(CommandParameter);
|
||||
|
||||
if (canExecute != _commandCanExecute)
|
||||
{
|
||||
_commandCanExecute = canExecute;
|
||||
UpdateIsEffectivelyEnabled();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,72 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Models
|
||||
{
|
||||
public class Amiibo
|
||||
{
|
||||
public struct AmiiboJson
|
||||
{
|
||||
[JsonPropertyName("amiibo")] public List<AmiiboApi> Amiibo { get; set; }
|
||||
[JsonPropertyName("lastUpdated")] public DateTime LastUpdated { get; set; }
|
||||
}
|
||||
|
||||
public struct AmiiboApi
|
||||
{
|
||||
[JsonPropertyName("name")] public string Name { get; set; }
|
||||
[JsonPropertyName("head")] public string Head { get; set; }
|
||||
[JsonPropertyName("tail")] public string Tail { get; set; }
|
||||
[JsonPropertyName("image")] public string Image { get; set; }
|
||||
[JsonPropertyName("amiiboSeries")] public string AmiiboSeries { get; set; }
|
||||
[JsonPropertyName("character")] public string Character { get; set; }
|
||||
[JsonPropertyName("gameSeries")] public string GameSeries { get; set; }
|
||||
[JsonPropertyName("type")] public string Type { get; set; }
|
||||
|
||||
[JsonPropertyName("release")] public Dictionary<string, string> Release { get; set; }
|
||||
|
||||
[JsonPropertyName("gamesSwitch")] public List<AmiiboApiGamesSwitch> GamesSwitch { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Name;
|
||||
}
|
||||
|
||||
public string GetId()
|
||||
{
|
||||
return Head + Tail;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj is AmiiboApi amiibo)
|
||||
{
|
||||
return amiibo.Head + amiibo.Tail == Head + Tail;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return base.GetHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
public class AmiiboApiGamesSwitch
|
||||
{
|
||||
[JsonPropertyName("amiiboUsage")] public List<AmiiboApiUsage> AmiiboUsage { get; set; }
|
||||
|
||||
[JsonPropertyName("gameID")] public List<string> GameId { get; set; }
|
||||
|
||||
[JsonPropertyName("gameName")] public string GameName { get; set; }
|
||||
}
|
||||
|
||||
public class AmiiboApiUsage
|
||||
{
|
||||
[JsonPropertyName("Usage")] public string Usage { get; set; }
|
||||
|
||||
[JsonPropertyName("write")] public bool Write { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
@ -1,363 +0,0 @@
|
||||
using Avalonia.Media;
|
||||
using DynamicData;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
using LibHac.FsSystem;
|
||||
using LibHac.Ncm;
|
||||
using LibHac.Tools.Fs;
|
||||
using LibHac.Tools.FsSystem;
|
||||
using LibHac.Tools.FsSystem.NcaUtils;
|
||||
using Ryujinx.Ava.UI.Models;
|
||||
using Ryujinx.HLE.FileSystem;
|
||||
using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.Formats.Png;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
using SixLabors.ImageSharp.Processing;
|
||||
using System;
|
||||
using System.Buffers.Binary;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Color = Avalonia.Media.Color;
|
||||
|
||||
namespace Ryujinx.Ava.UI.ViewModels
|
||||
{
|
||||
internal class AvatarProfileViewModel : BaseModel, IDisposable
|
||||
{
|
||||
private const int MaxImageTasks = 4;
|
||||
|
||||
private static readonly Dictionary<string, byte[]> _avatarStore = new();
|
||||
private static bool _isPreloading;
|
||||
private static Action _loadCompleteAction;
|
||||
|
||||
private ObservableCollection<ProfileImageModel> _images;
|
||||
private Color _backgroundColor = Colors.White;
|
||||
|
||||
private int _selectedIndex;
|
||||
private int _imagesLoaded;
|
||||
private bool _isActive;
|
||||
private byte[] _selectedImage;
|
||||
private bool _isIndeterminate = true;
|
||||
|
||||
public bool IsActive
|
||||
{
|
||||
get => _isActive;
|
||||
set => _isActive = value;
|
||||
}
|
||||
|
||||
public AvatarProfileViewModel()
|
||||
{
|
||||
_images = new ObservableCollection<ProfileImageModel>();
|
||||
}
|
||||
|
||||
public AvatarProfileViewModel(Action loadCompleteAction)
|
||||
{
|
||||
_images = new ObservableCollection<ProfileImageModel>();
|
||||
|
||||
if (_isPreloading)
|
||||
{
|
||||
_loadCompleteAction = loadCompleteAction;
|
||||
}
|
||||
else
|
||||
{
|
||||
ReloadImages();
|
||||
}
|
||||
}
|
||||
|
||||
public Color BackgroundColor
|
||||
{
|
||||
get => _backgroundColor;
|
||||
set
|
||||
{
|
||||
_backgroundColor = value;
|
||||
|
||||
IsActive = false;
|
||||
|
||||
ReloadImages();
|
||||
}
|
||||
}
|
||||
|
||||
public ObservableCollection<ProfileImageModel> Images
|
||||
{
|
||||
get => _images;
|
||||
set
|
||||
{
|
||||
_images = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsIndeterminate
|
||||
{
|
||||
get => _isIndeterminate;
|
||||
set
|
||||
{
|
||||
_isIndeterminate = value;
|
||||
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public int ImageCount => _avatarStore.Count;
|
||||
|
||||
public int ImagesLoaded
|
||||
{
|
||||
get => _imagesLoaded;
|
||||
set
|
||||
{
|
||||
_imagesLoaded = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public int SelectedIndex
|
||||
{
|
||||
get => _selectedIndex;
|
||||
set
|
||||
{
|
||||
_selectedIndex = value;
|
||||
|
||||
if (_selectedIndex == -1)
|
||||
{
|
||||
SelectedImage = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
SelectedImage = _images[_selectedIndex].Data;
|
||||
}
|
||||
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] SelectedImage
|
||||
{
|
||||
get => _selectedImage;
|
||||
private set => _selectedImage = value;
|
||||
}
|
||||
|
||||
public void ReloadImages()
|
||||
{
|
||||
if (_isPreloading)
|
||||
{
|
||||
IsIndeterminate = false;
|
||||
return;
|
||||
}
|
||||
Task.Run(() =>
|
||||
{
|
||||
IsActive = true;
|
||||
|
||||
Images.Clear();
|
||||
int selectedIndex = _selectedIndex;
|
||||
int index = 0;
|
||||
|
||||
ImagesLoaded = 0;
|
||||
IsIndeterminate = false;
|
||||
|
||||
var keys = _avatarStore.Keys.ToList();
|
||||
|
||||
var newImages = new List<ProfileImageModel>();
|
||||
var tasks = new List<Task>();
|
||||
|
||||
for (int i = 0; i < MaxImageTasks; i++)
|
||||
{
|
||||
var start = i;
|
||||
tasks.Add(Task.Run(() => ImageTask(start)));
|
||||
}
|
||||
|
||||
Task.WaitAll(tasks.ToArray());
|
||||
|
||||
Images.AddRange(newImages);
|
||||
|
||||
void ImageTask(int start)
|
||||
{
|
||||
for (int i = start; i < keys.Count; i += MaxImageTasks)
|
||||
{
|
||||
if (!IsActive)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var key = keys[i];
|
||||
var image = _avatarStore[keys[i]];
|
||||
|
||||
var data = ProcessImage(image);
|
||||
newImages.Add(new ProfileImageModel(key, data));
|
||||
if (index++ == selectedIndex)
|
||||
{
|
||||
SelectedImage = data;
|
||||
}
|
||||
|
||||
Interlocked.Increment(ref _imagesLoaded);
|
||||
OnPropertyChanged(nameof(ImagesLoaded));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private byte[] ProcessImage(byte[] data)
|
||||
{
|
||||
using (MemoryStream streamJpg = new())
|
||||
{
|
||||
Image avatarImage = Image.Load(data, new PngDecoder());
|
||||
|
||||
avatarImage.Mutate(x => x.BackgroundColor(new Rgba32(BackgroundColor.R,
|
||||
BackgroundColor.G,
|
||||
BackgroundColor.B,
|
||||
BackgroundColor.A)));
|
||||
avatarImage.SaveAsJpeg(streamJpg);
|
||||
|
||||
return streamJpg.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public static void PreloadAvatars(ContentManager contentManager, VirtualFileSystem virtualFileSystem)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_avatarStore.Count > 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_isPreloading = true;
|
||||
|
||||
string contentPath =
|
||||
contentManager.GetInstalledContentPath(0x010000000000080A, StorageId.BuiltInSystem,
|
||||
NcaContentType.Data);
|
||||
string avatarPath = virtualFileSystem.SwitchPathToSystemPath(contentPath);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(avatarPath))
|
||||
{
|
||||
using (IStorage ncaFileStream = new LocalStorage(avatarPath, FileAccess.Read, FileMode.Open))
|
||||
{
|
||||
Nca nca = new(virtualFileSystem.KeySet, ncaFileStream);
|
||||
IFileSystem romfs = nca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.ErrorOnInvalid);
|
||||
|
||||
foreach (DirectoryEntryEx item in romfs.EnumerateEntries())
|
||||
{
|
||||
// TODO: Parse DatabaseInfo.bin and table.bin files for more accuracy.
|
||||
if (item.Type == DirectoryEntryType.File && item.FullPath.Contains("chara") &&
|
||||
item.FullPath.Contains("szs"))
|
||||
{
|
||||
using var file = new UniqueRef<IFile>();
|
||||
|
||||
romfs.OpenFile(ref file.Ref, ("/" + item.FullPath).ToU8Span(), OpenMode.Read)
|
||||
.ThrowIfFailure();
|
||||
|
||||
using (MemoryStream stream = new())
|
||||
using (MemoryStream streamPng = new())
|
||||
{
|
||||
file.Get.AsStream().CopyTo(stream);
|
||||
|
||||
stream.Position = 0;
|
||||
|
||||
Image avatarImage = Image.LoadPixelData<Rgba32>(DecompressYaz0(stream), 256, 256);
|
||||
|
||||
avatarImage.SaveAsPng(streamPng);
|
||||
|
||||
_avatarStore.Add(item.FullPath, streamPng.ToArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_isPreloading = false;
|
||||
_loadCompleteAction?.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] DecompressYaz0(Stream stream)
|
||||
{
|
||||
using (BinaryReader reader = new(stream))
|
||||
{
|
||||
reader.ReadInt32(); // Magic
|
||||
|
||||
uint decodedLength = BinaryPrimitives.ReverseEndianness(reader.ReadUInt32());
|
||||
|
||||
reader.ReadInt64(); // Padding
|
||||
|
||||
byte[] input = new byte[stream.Length - stream.Position];
|
||||
stream.Read(input, 0, input.Length);
|
||||
|
||||
uint inputOffset = 0;
|
||||
|
||||
byte[] output = new byte[decodedLength];
|
||||
uint outputOffset = 0;
|
||||
|
||||
ushort mask = 0;
|
||||
byte header = 0;
|
||||
|
||||
while (outputOffset < decodedLength)
|
||||
{
|
||||
if ((mask >>= 1) == 0)
|
||||
{
|
||||
header = input[inputOffset++];
|
||||
mask = 0x80;
|
||||
}
|
||||
|
||||
if ((header & mask) != 0)
|
||||
{
|
||||
if (outputOffset == output.Length)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
output[outputOffset++] = input[inputOffset++];
|
||||
}
|
||||
else
|
||||
{
|
||||
byte byte1 = input[inputOffset++];
|
||||
byte byte2 = input[inputOffset++];
|
||||
|
||||
uint dist = (uint)((byte1 & 0xF) << 8) | byte2;
|
||||
uint position = outputOffset - (dist + 1);
|
||||
|
||||
uint length = (uint)byte1 >> 4;
|
||||
if (length == 0)
|
||||
{
|
||||
length = (uint)input[inputOffset++] + 0x12;
|
||||
}
|
||||
else
|
||||
{
|
||||
length += 2;
|
||||
}
|
||||
|
||||
uint gap = outputOffset - position;
|
||||
uint nonOverlappingLength = length;
|
||||
|
||||
if (nonOverlappingLength > gap)
|
||||
{
|
||||
nonOverlappingLength = gap;
|
||||
}
|
||||
|
||||
Buffer.BlockCopy(output, (int)position, output, (int)outputOffset, (int)nonOverlappingLength);
|
||||
outputOffset += nonOverlappingLength;
|
||||
position += nonOverlappingLength;
|
||||
length -= nonOverlappingLength;
|
||||
|
||||
while (length-- > 0)
|
||||
{
|
||||
output[outputOffset++] = output[position++];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_loadCompleteAction = null;
|
||||
IsActive = false;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,250 +0,0 @@
|
||||
using Avalonia.Collections;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.ApplicationLifetimes;
|
||||
using Avalonia.Threading;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
using LibHac.FsSystem;
|
||||
using LibHac.Ns;
|
||||
using LibHac.Tools.FsSystem;
|
||||
using LibHac.Tools.FsSystem.NcaUtils;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.Models;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Common.Utilities;
|
||||
using Ryujinx.HLE.FileSystem;
|
||||
using Ryujinx.HLE.HOS;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Path = System.IO.Path;
|
||||
using SpanHelpers = LibHac.Common.SpanHelpers;
|
||||
|
||||
namespace Ryujinx.Ava.UI.ViewModels;
|
||||
|
||||
public class TitleUpdateViewModel : BaseModel
|
||||
{
|
||||
public TitleUpdateMetadata _titleUpdateWindowData;
|
||||
public readonly string _titleUpdateJsonPath;
|
||||
private VirtualFileSystem _virtualFileSystem { get; }
|
||||
private ulong _titleId { get; }
|
||||
private string _titleName { get; }
|
||||
|
||||
private AvaloniaList<TitleUpdateModel> _titleUpdates = new();
|
||||
private AvaloniaList<object> _views = new();
|
||||
private object _selectedUpdate;
|
||||
|
||||
public AvaloniaList<TitleUpdateModel> TitleUpdates
|
||||
{
|
||||
get => _titleUpdates;
|
||||
set
|
||||
{
|
||||
_titleUpdates = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public AvaloniaList<object> Views
|
||||
{
|
||||
get => _views;
|
||||
set
|
||||
{
|
||||
_views = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public object SelectedUpdate
|
||||
{
|
||||
get => _selectedUpdate;
|
||||
set
|
||||
{
|
||||
_selectedUpdate = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public TitleUpdateViewModel(VirtualFileSystem virtualFileSystem, ulong titleId, string titleName)
|
||||
{
|
||||
_virtualFileSystem = virtualFileSystem;
|
||||
|
||||
_titleId = titleId;
|
||||
_titleName = titleName;
|
||||
|
||||
_titleUpdateJsonPath = Path.Combine(AppDataManager.GamesDirPath, titleId.ToString("x16"), "updates.json");
|
||||
|
||||
try
|
||||
{
|
||||
_titleUpdateWindowData = JsonHelper.DeserializeFromFile<TitleUpdateMetadata>(_titleUpdateJsonPath);
|
||||
}
|
||||
catch
|
||||
{
|
||||
Logger.Warning?.Print(LogClass.Application, $"Failed to deserialize title update data for {_titleId} at {_titleUpdateJsonPath}");
|
||||
|
||||
_titleUpdateWindowData = new TitleUpdateMetadata
|
||||
{
|
||||
Selected = "",
|
||||
Paths = new List<string>()
|
||||
};
|
||||
|
||||
Save();
|
||||
}
|
||||
|
||||
LoadUpdates();
|
||||
}
|
||||
|
||||
private void LoadUpdates()
|
||||
{
|
||||
foreach (string path in _titleUpdateWindowData.Paths)
|
||||
{
|
||||
AddUpdate(path);
|
||||
}
|
||||
|
||||
TitleUpdateModel selected = TitleUpdates.FirstOrDefault(x => x.Path == _titleUpdateWindowData.Selected, null);
|
||||
|
||||
SelectedUpdate = selected;
|
||||
|
||||
// NOTE: Save the list again to remove leftovers.
|
||||
Save();
|
||||
|
||||
SortUpdates();
|
||||
}
|
||||
|
||||
public void SortUpdates()
|
||||
{
|
||||
var list = TitleUpdates.ToList();
|
||||
|
||||
list.Sort((first, second) =>
|
||||
{
|
||||
if (string.IsNullOrEmpty(first.Control.DisplayVersionString.ToString()))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if (string.IsNullOrEmpty(second.Control.DisplayVersionString.ToString()))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return Version.Parse(first.Control.DisplayVersionString.ToString()).CompareTo(Version.Parse(second.Control.DisplayVersionString.ToString())) * -1;
|
||||
});
|
||||
|
||||
Views.Clear();
|
||||
Views.Add(new BaseModel());
|
||||
Views.AddRange(list);
|
||||
|
||||
if (SelectedUpdate == null)
|
||||
{
|
||||
SelectedUpdate = Views[0];
|
||||
}
|
||||
else if (!TitleUpdates.Contains(SelectedUpdate))
|
||||
{
|
||||
if (Views.Count > 1)
|
||||
{
|
||||
SelectedUpdate = Views[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
SelectedUpdate = Views[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void AddUpdate(string path)
|
||||
{
|
||||
if (File.Exists(path) && TitleUpdates.All(x => x.Path != path))
|
||||
{
|
||||
using FileStream file = new(path, FileMode.Open, FileAccess.Read);
|
||||
|
||||
try
|
||||
{
|
||||
(Nca patchNca, Nca controlNca) = ApplicationLoader.GetGameUpdateDataFromPartition(_virtualFileSystem, new PartitionFileSystem(file.AsStorage()), _titleId.ToString("x16"), 0);
|
||||
|
||||
if (controlNca != null && patchNca != null)
|
||||
{
|
||||
ApplicationControlProperty controlData = new();
|
||||
|
||||
using UniqueRef<IFile> nacpFile = new();
|
||||
|
||||
controlNca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.None).OpenFile(ref nacpFile.Ref, "/control.nacp".ToU8Span(), OpenMode.Read).ThrowIfFailure();
|
||||
nacpFile.Get.Read(out _, 0, SpanHelpers.AsByteSpan(ref controlData), ReadOption.None).ThrowIfFailure();
|
||||
|
||||
TitleUpdates.Add(new TitleUpdateModel(controlData, path));
|
||||
}
|
||||
else
|
||||
{
|
||||
Dispatcher.UIThread.Post(async () =>
|
||||
{
|
||||
await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogUpdateAddUpdateErrorMessage]);
|
||||
});
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Dispatcher.UIThread.Post(async () =>
|
||||
{
|
||||
await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogLoadNcaErrorMessage, ex.Message, path));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveUpdate(TitleUpdateModel update)
|
||||
{
|
||||
TitleUpdates.Remove(update);
|
||||
|
||||
SortUpdates();
|
||||
}
|
||||
|
||||
public async void Add()
|
||||
{
|
||||
OpenFileDialog dialog = new()
|
||||
{
|
||||
Title = LocaleManager.Instance[LocaleKeys.SelectUpdateDialogTitle],
|
||||
AllowMultiple = true
|
||||
};
|
||||
|
||||
dialog.Filters.Add(new FileDialogFilter
|
||||
{
|
||||
Name = "NSP",
|
||||
Extensions = { "nsp" }
|
||||
});
|
||||
|
||||
if (Avalonia.Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
|
||||
{
|
||||
string[] files = await dialog.ShowAsync(desktop.MainWindow);
|
||||
|
||||
if (files != null)
|
||||
{
|
||||
foreach (string file in files)
|
||||
{
|
||||
AddUpdate(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SortUpdates();
|
||||
}
|
||||
|
||||
public void Save()
|
||||
{
|
||||
_titleUpdateWindowData.Paths.Clear();
|
||||
_titleUpdateWindowData.Selected = "";
|
||||
|
||||
foreach (TitleUpdateModel update in TitleUpdates)
|
||||
{
|
||||
_titleUpdateWindowData.Paths.Add(update.Path);
|
||||
|
||||
if (update == SelectedUpdate)
|
||||
{
|
||||
_titleUpdateWindowData.Selected = update.Path;
|
||||
}
|
||||
}
|
||||
|
||||
File.WriteAllBytes(_titleUpdateJsonPath, Encoding.UTF8.GetBytes(JsonHelper.Serialize(_titleUpdateWindowData, true)));
|
||||
}
|
||||
}
|
@ -1,230 +0,0 @@
|
||||
using Avalonia.Media;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
using LibHac.FsSystem;
|
||||
using LibHac.Ncm;
|
||||
using LibHac.Tools.Fs;
|
||||
using LibHac.Tools.FsSystem;
|
||||
using LibHac.Tools.FsSystem.NcaUtils;
|
||||
using Ryujinx.Ava.UI.Models;
|
||||
using Ryujinx.HLE.FileSystem;
|
||||
using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
using System;
|
||||
using System.Buffers.Binary;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using Color = Avalonia.Media.Color;
|
||||
|
||||
namespace Ryujinx.Ava.UI.ViewModels
|
||||
{
|
||||
internal class UserFirmwareAvatarSelectorViewModel : BaseModel
|
||||
{
|
||||
private static readonly Dictionary<string, byte[]> _avatarStore = new();
|
||||
|
||||
private ObservableCollection<ProfileImageModel> _images;
|
||||
private Color _backgroundColor = Colors.White;
|
||||
|
||||
private int _selectedIndex;
|
||||
private byte[] _selectedImage;
|
||||
|
||||
public UserFirmwareAvatarSelectorViewModel()
|
||||
{
|
||||
_images = new ObservableCollection<ProfileImageModel>();
|
||||
|
||||
LoadImagesFromStore();
|
||||
}
|
||||
|
||||
public Color BackgroundColor
|
||||
{
|
||||
get => _backgroundColor;
|
||||
set
|
||||
{
|
||||
_backgroundColor = value;
|
||||
OnPropertyChanged();
|
||||
ChangeImageBackground();
|
||||
}
|
||||
}
|
||||
|
||||
public ObservableCollection<ProfileImageModel> Images
|
||||
{
|
||||
get => _images;
|
||||
set
|
||||
{
|
||||
_images = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public int SelectedIndex
|
||||
{
|
||||
get => _selectedIndex;
|
||||
set
|
||||
{
|
||||
_selectedIndex = value;
|
||||
|
||||
if (_selectedIndex == -1)
|
||||
{
|
||||
SelectedImage = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
SelectedImage = _images[_selectedIndex].Data;
|
||||
}
|
||||
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] SelectedImage
|
||||
{
|
||||
get => _selectedImage;
|
||||
private set => _selectedImage = value;
|
||||
}
|
||||
|
||||
private void LoadImagesFromStore()
|
||||
{
|
||||
Images.Clear();
|
||||
|
||||
foreach (var image in _avatarStore)
|
||||
{
|
||||
Images.Add(new ProfileImageModel(image.Key, image.Value));
|
||||
}
|
||||
}
|
||||
|
||||
private void ChangeImageBackground()
|
||||
{
|
||||
foreach (var image in Images)
|
||||
{
|
||||
image.BackgroundColor = new SolidColorBrush(BackgroundColor);
|
||||
}
|
||||
}
|
||||
|
||||
public static void PreloadAvatars(ContentManager contentManager, VirtualFileSystem virtualFileSystem)
|
||||
{
|
||||
if (_avatarStore.Count > 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string contentPath = contentManager.GetInstalledContentPath(0x010000000000080A, StorageId.BuiltInSystem, NcaContentType.Data);
|
||||
string avatarPath = virtualFileSystem.SwitchPathToSystemPath(contentPath);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(avatarPath))
|
||||
{
|
||||
using (IStorage ncaFileStream = new LocalStorage(avatarPath, FileAccess.Read, FileMode.Open))
|
||||
{
|
||||
Nca nca = new(virtualFileSystem.KeySet, ncaFileStream);
|
||||
IFileSystem romfs = nca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.ErrorOnInvalid);
|
||||
|
||||
foreach (DirectoryEntryEx item in romfs.EnumerateEntries())
|
||||
{
|
||||
// TODO: Parse DatabaseInfo.bin and table.bin files for more accuracy.
|
||||
if (item.Type == DirectoryEntryType.File && item.FullPath.Contains("chara") && item.FullPath.Contains("szs"))
|
||||
{
|
||||
using var file = new UniqueRef<IFile>();
|
||||
|
||||
romfs.OpenFile(ref file.Ref, ("/" + item.FullPath).ToU8Span(), OpenMode.Read).ThrowIfFailure();
|
||||
|
||||
using (MemoryStream stream = new())
|
||||
using (MemoryStream streamPng = new())
|
||||
{
|
||||
file.Get.AsStream().CopyTo(stream);
|
||||
|
||||
stream.Position = 0;
|
||||
|
||||
Image avatarImage = Image.LoadPixelData<Rgba32>(DecompressYaz0(stream), 256, 256);
|
||||
|
||||
avatarImage.SaveAsPng(streamPng);
|
||||
|
||||
_avatarStore.Add(item.FullPath, streamPng.ToArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] DecompressYaz0(Stream stream)
|
||||
{
|
||||
using (BinaryReader reader = new(stream))
|
||||
{
|
||||
reader.ReadInt32(); // Magic
|
||||
|
||||
uint decodedLength = BinaryPrimitives.ReverseEndianness(reader.ReadUInt32());
|
||||
|
||||
reader.ReadInt64(); // Padding
|
||||
|
||||
byte[] input = new byte[stream.Length - stream.Position];
|
||||
stream.Read(input, 0, input.Length);
|
||||
|
||||
uint inputOffset = 0;
|
||||
|
||||
byte[] output = new byte[decodedLength];
|
||||
uint outputOffset = 0;
|
||||
|
||||
ushort mask = 0;
|
||||
byte header = 0;
|
||||
|
||||
while (outputOffset < decodedLength)
|
||||
{
|
||||
if ((mask >>= 1) == 0)
|
||||
{
|
||||
header = input[inputOffset++];
|
||||
mask = 0x80;
|
||||
}
|
||||
|
||||
if ((header & mask) != 0)
|
||||
{
|
||||
if (outputOffset == output.Length)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
output[outputOffset++] = input[inputOffset++];
|
||||
}
|
||||
else
|
||||
{
|
||||
byte byte1 = input[inputOffset++];
|
||||
byte byte2 = input[inputOffset++];
|
||||
|
||||
uint dist = (uint)((byte1 & 0xF) << 8) | byte2;
|
||||
uint position = outputOffset - (dist + 1);
|
||||
|
||||
uint length = (uint)byte1 >> 4;
|
||||
if (length == 0)
|
||||
{
|
||||
length = (uint)input[inputOffset++] + 0x12;
|
||||
}
|
||||
else
|
||||
{
|
||||
length += 2;
|
||||
}
|
||||
|
||||
uint gap = outputOffset - position;
|
||||
uint nonOverlappingLength = length;
|
||||
|
||||
if (nonOverlappingLength > gap)
|
||||
{
|
||||
nonOverlappingLength = gap;
|
||||
}
|
||||
|
||||
Buffer.BlockCopy(output, (int)position, output, (int)outputOffset, (int)nonOverlappingLength);
|
||||
outputOffset += nonOverlappingLength;
|
||||
position += nonOverlappingLength;
|
||||
length -= nonOverlappingLength;
|
||||
|
||||
while (length-- > 0)
|
||||
{
|
||||
output[outputOffset++] = output[position++];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
<UserControl
|
||||
x:Class="Ryujinx.Ava.UI.Views.Settings.SettingsInputView"
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
|
||||
xmlns:window="clr-namespace:Ryujinx.Ava.UI.Windows"
|
||||
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
|
||||
mc:Ignorable="d"
|
||||
x:CompileBindings="True"
|
||||
x:DataType="viewModels:SettingsViewModel">
|
||||
<Design.DataContext>
|
||||
<viewModels:SettingsViewModel />
|
||||
</Design.DataContext>
|
||||
<ScrollViewer
|
||||
Name="InputPage"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
HorizontalScrollBarVisibility="Disabled"
|
||||
VerticalScrollBarVisibility="Auto">
|
||||
<Border Classes="settings">
|
||||
<StackPanel Margin="4" Orientation="Vertical">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<CheckBox Margin="5,0"
|
||||
ToolTip.Tip="{locale:Locale DockModeToggleTooltip}"
|
||||
IsChecked="{Binding EnableDockedMode}">
|
||||
<TextBlock VerticalAlignment="Center"
|
||||
Text="{locale:Locale SettingsTabInputEnableDockedMode}" />
|
||||
</CheckBox>
|
||||
<CheckBox Margin="5,0"
|
||||
ToolTip.Tip="{locale:Locale DirectKeyboardTooltip}"
|
||||
IsChecked="{Binding EnableKeyboard}">
|
||||
<TextBlock Text="{locale:Locale SettingsTabInputDirectKeyboardAccess}" />
|
||||
</CheckBox>
|
||||
<CheckBox Margin="5,0"
|
||||
ToolTip.Tip="{locale:Locale DirectMouseTooltip}"
|
||||
IsChecked="{Binding EnableMouse}">
|
||||
<TextBlock Text="{locale:Locale SettingsTabInputDirectMouseAccess}" />
|
||||
</CheckBox>
|
||||
</StackPanel>
|
||||
<window:ControllerSettingsWindow Name="ControllerSettings" Margin="0" MinHeight="600" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</ScrollViewer>
|
||||
</UserControl>
|
@ -1,172 +0,0 @@
|
||||
<window:StyleableWindow
|
||||
x:Class="Ryujinx.Ava.UI.Windows.DownloadableContentManagerWindow"
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:window="clr-namespace:Ryujinx.Ava.UI.Windows"
|
||||
Width="800"
|
||||
Height="500"
|
||||
MinWidth="800"
|
||||
MinHeight="500"
|
||||
MaxWidth="800"
|
||||
MaxHeight="500"
|
||||
SizeToContent="Height"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
mc:Ignorable="d"
|
||||
Focusable="True">
|
||||
<Grid Name="DownloadableContentGrid" Margin="15">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock
|
||||
Name="Heading"
|
||||
Grid.Row="1"
|
||||
MaxWidth="500"
|
||||
Margin="20,15,20,20"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
LineHeight="18"
|
||||
TextAlignment="Center"
|
||||
TextWrapping="Wrap" />
|
||||
<DockPanel
|
||||
Grid.Row="2"
|
||||
Margin="0"
|
||||
HorizontalAlignment="Left">
|
||||
<Button
|
||||
Name="EnableAllButton"
|
||||
MinWidth="90"
|
||||
Margin="5"
|
||||
Command="{Binding EnableAll}">
|
||||
<TextBlock Text="{locale:Locale DlcManagerEnableAllButton}" />
|
||||
</Button>
|
||||
<Button
|
||||
Name="DisableAllButton"
|
||||
MinWidth="90"
|
||||
Margin="5"
|
||||
Command="{Binding DisableAll}">
|
||||
<TextBlock Text="{locale:Locale DlcManagerDisableAllButton}" />
|
||||
</Button>
|
||||
</DockPanel>
|
||||
<Border
|
||||
Grid.Row="3"
|
||||
Margin="5"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
BorderBrush="Gray"
|
||||
BorderThickness="1">
|
||||
<ScrollViewer
|
||||
VerticalAlignment="Stretch"
|
||||
HorizontalScrollBarVisibility="Auto"
|
||||
VerticalScrollBarVisibility="Auto">
|
||||
<DataGrid
|
||||
Name="DlcDataGrid"
|
||||
MinHeight="200"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
CanUserReorderColumns="False"
|
||||
CanUserResizeColumns="True"
|
||||
CanUserSortColumns="True"
|
||||
HorizontalScrollBarVisibility="Auto"
|
||||
Items="{Binding _downloadableContents}"
|
||||
SelectionMode="Extended"
|
||||
VerticalScrollBarVisibility="Auto">
|
||||
<DataGrid.Styles>
|
||||
<Styles>
|
||||
<Style Selector="DataGridCell:nth-child(3), DataGridCell:nth-child(4)">
|
||||
<Setter Property="HorizontalAlignment" Value="Left" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Left" />
|
||||
</Style>
|
||||
</Styles>
|
||||
<Styles>
|
||||
<Style Selector="DataGridCell:nth-child(1)">
|
||||
<Setter Property="HorizontalAlignment" Value="Right" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Right" />
|
||||
</Style>
|
||||
</Styles>
|
||||
</DataGrid.Styles>
|
||||
<DataGrid.Columns>
|
||||
<DataGridTemplateColumn Width="90">
|
||||
<DataGridTemplateColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<CheckBox
|
||||
Width="50"
|
||||
MinWidth="40"
|
||||
HorizontalAlignment="Center"
|
||||
IsChecked="{Binding Enabled}" />
|
||||
</DataTemplate>
|
||||
</DataGridTemplateColumn.CellTemplate>
|
||||
<DataGridTemplateColumn.Header>
|
||||
<TextBlock Text="{locale:Locale DlcManagerTableHeadingEnabledLabel}" />
|
||||
</DataGridTemplateColumn.Header>
|
||||
</DataGridTemplateColumn>
|
||||
<DataGridTextColumn Width="140" Binding="{Binding TitleId}">
|
||||
<DataGridTextColumn.Header>
|
||||
<TextBlock Text="{locale:Locale DlcManagerTableHeadingTitleIdLabel}" />
|
||||
</DataGridTextColumn.Header>
|
||||
</DataGridTextColumn>
|
||||
<DataGridTextColumn Width="280" Binding="{Binding FullPath}">
|
||||
<DataGridTextColumn.Header>
|
||||
<TextBlock Text="{locale:Locale DlcManagerTableHeadingFullPathLabel}" />
|
||||
</DataGridTextColumn.Header>
|
||||
</DataGridTextColumn>
|
||||
<DataGridTextColumn Binding="{Binding ContainerPath}">
|
||||
<DataGridTextColumn.Header>
|
||||
<TextBlock Text="{locale:Locale DlcManagerTableHeadingContainerPathLabel}" />
|
||||
</DataGridTextColumn.Header>
|
||||
</DataGridTextColumn>
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
</ScrollViewer>
|
||||
</Border>
|
||||
<DockPanel
|
||||
Grid.Row="4"
|
||||
Margin="0"
|
||||
HorizontalAlignment="Stretch">
|
||||
<DockPanel Margin="0" HorizontalAlignment="Left">
|
||||
<Button
|
||||
Name="AddButton"
|
||||
MinWidth="90"
|
||||
Margin="5"
|
||||
Command="{Binding Add}">
|
||||
<TextBlock Text="{locale:Locale SettingsTabGeneralAdd}" />
|
||||
</Button>
|
||||
<Button
|
||||
Name="RemoveButton"
|
||||
MinWidth="90"
|
||||
Margin="5"
|
||||
Command="{Binding RemoveSelected}">
|
||||
<TextBlock Text="{locale:Locale SettingsTabGeneralRemove}" />
|
||||
</Button>
|
||||
<Button
|
||||
Name="RemoveAllButton"
|
||||
MinWidth="90"
|
||||
Margin="5"
|
||||
Command="{Binding RemoveAll}">
|
||||
<TextBlock Text="{locale:Locale DlcManagerRemoveAllButton}" />
|
||||
</Button>
|
||||
</DockPanel>
|
||||
<DockPanel Margin="0" HorizontalAlignment="Right">
|
||||
<Button
|
||||
Name="SaveButton"
|
||||
MinWidth="90"
|
||||
Margin="5"
|
||||
Command="{Binding SaveAndClose}">
|
||||
<TextBlock Text="{locale:Locale SettingsButtonSave}" />
|
||||
</Button>
|
||||
<Button
|
||||
Name="CancelButton"
|
||||
MinWidth="90"
|
||||
Margin="5"
|
||||
Command="{Binding Close}">
|
||||
<TextBlock Text="{locale:Locale InputDialogCancel}" />
|
||||
</Button>
|
||||
</DockPanel>
|
||||
</DockPanel>
|
||||
</Grid>
|
||||
</window:StyleableWindow>
|
@ -1,314 +0,0 @@
|
||||
using Avalonia.Collections;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Threading;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
using LibHac.FsSystem;
|
||||
using LibHac.Tools.Fs;
|
||||
using LibHac.Tools.FsSystem;
|
||||
using LibHac.Tools.FsSystem.NcaUtils;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.UI.Controls;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.Models;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Utilities;
|
||||
using Ryujinx.HLE.FileSystem;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reactive.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Path = System.IO.Path;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Windows
|
||||
{
|
||||
public partial class DownloadableContentManagerWindow : StyleableWindow
|
||||
{
|
||||
private readonly List<DownloadableContentContainer> _downloadableContentContainerList;
|
||||
private readonly string _downloadableContentJsonPath;
|
||||
|
||||
private VirtualFileSystem _virtualFileSystem { get; }
|
||||
private AvaloniaList<DownloadableContentModel> _downloadableContents { get; set; }
|
||||
|
||||
private ulong _titleId { get; }
|
||||
private string _titleName { get; }
|
||||
|
||||
public DownloadableContentManagerWindow()
|
||||
{
|
||||
DataContext = this;
|
||||
|
||||
InitializeComponent();
|
||||
|
||||
Title = $"Ryujinx {Program.Version} - {LocaleManager.Instance[LocaleKeys.DlcWindowTitle]} - {_titleName} ({_titleId:X16})";
|
||||
}
|
||||
|
||||
public DownloadableContentManagerWindow(VirtualFileSystem virtualFileSystem, ulong titleId, string titleName)
|
||||
{
|
||||
_virtualFileSystem = virtualFileSystem;
|
||||
_downloadableContents = new AvaloniaList<DownloadableContentModel>();
|
||||
|
||||
_titleId = titleId;
|
||||
_titleName = titleName;
|
||||
|
||||
_downloadableContentJsonPath = Path.Combine(AppDataManager.GamesDirPath, titleId.ToString("x16"), "dlc.json");
|
||||
|
||||
try
|
||||
{
|
||||
_downloadableContentContainerList = JsonHelper.DeserializeFromFile<List<DownloadableContentContainer>>(_downloadableContentJsonPath);
|
||||
}
|
||||
catch
|
||||
{
|
||||
_downloadableContentContainerList = new List<DownloadableContentContainer>();
|
||||
}
|
||||
|
||||
DataContext = this;
|
||||
|
||||
InitializeComponent();
|
||||
|
||||
RemoveButton.IsEnabled = false;
|
||||
|
||||
DlcDataGrid.SelectionChanged += DlcDataGrid_SelectionChanged;
|
||||
|
||||
Title = $"Ryujinx {Program.Version} - {LocaleManager.Instance[LocaleKeys.DlcWindowTitle]} - {_titleName} ({_titleId:X16})";
|
||||
|
||||
LoadDownloadableContents();
|
||||
PrintHeading();
|
||||
}
|
||||
|
||||
private void DlcDataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
RemoveButton.IsEnabled = (DlcDataGrid.SelectedItems.Count > 0);
|
||||
}
|
||||
|
||||
private void PrintHeading()
|
||||
{
|
||||
Heading.Text = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DlcWindowHeading, _downloadableContents.Count, _titleName, _titleId.ToString("X16"));
|
||||
}
|
||||
|
||||
private void LoadDownloadableContents()
|
||||
{
|
||||
foreach (DownloadableContentContainer downloadableContentContainer in _downloadableContentContainerList)
|
||||
{
|
||||
if (File.Exists(downloadableContentContainer.ContainerPath))
|
||||
{
|
||||
using FileStream containerFile = File.OpenRead(downloadableContentContainer.ContainerPath);
|
||||
|
||||
PartitionFileSystem partitionFileSystem = new(containerFile.AsStorage());
|
||||
|
||||
_virtualFileSystem.ImportTickets(partitionFileSystem);
|
||||
|
||||
foreach (DownloadableContentNca downloadableContentNca in downloadableContentContainer.DownloadableContentNcaList)
|
||||
{
|
||||
using UniqueRef<IFile> ncaFile = new();
|
||||
|
||||
partitionFileSystem.OpenFile(ref ncaFile.Ref, downloadableContentNca.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
|
||||
|
||||
Nca nca = TryOpenNca(ncaFile.Get.AsStorage(), downloadableContentContainer.ContainerPath);
|
||||
if (nca != null)
|
||||
{
|
||||
_downloadableContents.Add(new DownloadableContentModel(nca.Header.TitleId.ToString("X16"),
|
||||
downloadableContentContainer.ContainerPath,
|
||||
downloadableContentNca.FullPath,
|
||||
downloadableContentNca.Enabled));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: Save the list again to remove leftovers.
|
||||
Save();
|
||||
}
|
||||
|
||||
private Nca TryOpenNca(IStorage ncaStorage, string containerPath)
|
||||
{
|
||||
try
|
||||
{
|
||||
return new Nca(_virtualFileSystem.KeySet, ncaStorage);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Dispatcher.UIThread.InvokeAsync(async () =>
|
||||
{
|
||||
await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogLoadNcaErrorMessage, ex.Message, containerPath));
|
||||
});
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private async Task AddDownloadableContent(string path)
|
||||
{
|
||||
if (!File.Exists(path) || _downloadableContents.FirstOrDefault(x => x.ContainerPath == path) != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
using FileStream containerFile = File.OpenRead(path);
|
||||
|
||||
PartitionFileSystem partitionFileSystem = new(containerFile.AsStorage());
|
||||
bool containsDownloadableContent = false;
|
||||
|
||||
_virtualFileSystem.ImportTickets(partitionFileSystem);
|
||||
|
||||
foreach (DirectoryEntryEx fileEntry in partitionFileSystem.EnumerateEntries("/", "*.nca"))
|
||||
{
|
||||
using var ncaFile = new UniqueRef<IFile>();
|
||||
|
||||
partitionFileSystem.OpenFile(ref ncaFile.Ref, fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
|
||||
|
||||
Nca nca = TryOpenNca(ncaFile.Get.AsStorage(), path);
|
||||
if (nca == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (nca.Header.ContentType == NcaContentType.PublicData)
|
||||
{
|
||||
if ((nca.Header.TitleId & 0xFFFFFFFFFFFFE000) != _titleId)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
_downloadableContents.Add(new DownloadableContentModel(nca.Header.TitleId.ToString("X16"), path, fileEntry.FullPath, true));
|
||||
|
||||
containsDownloadableContent = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!containsDownloadableContent)
|
||||
{
|
||||
await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogDlcNoDlcErrorMessage]);
|
||||
}
|
||||
}
|
||||
|
||||
private void RemoveDownloadableContents(bool removeSelectedOnly = false)
|
||||
{
|
||||
if (removeSelectedOnly)
|
||||
{
|
||||
AvaloniaList<DownloadableContentModel> removedItems = new();
|
||||
|
||||
foreach (var item in DlcDataGrid.SelectedItems)
|
||||
{
|
||||
removedItems.Add(item as DownloadableContentModel);
|
||||
}
|
||||
|
||||
DlcDataGrid.SelectedItems.Clear();
|
||||
|
||||
foreach (var item in removedItems)
|
||||
{
|
||||
_downloadableContents.RemoveAll(_downloadableContents.Where(x => x.TitleId == item.TitleId).ToList());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_downloadableContents.Clear();
|
||||
}
|
||||
|
||||
PrintHeading();
|
||||
}
|
||||
|
||||
public void RemoveSelected()
|
||||
{
|
||||
RemoveDownloadableContents(true);
|
||||
}
|
||||
|
||||
public void RemoveAll()
|
||||
{
|
||||
RemoveDownloadableContents();
|
||||
}
|
||||
|
||||
public void EnableAll()
|
||||
{
|
||||
foreach(var item in _downloadableContents)
|
||||
{
|
||||
item.Enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void DisableAll()
|
||||
{
|
||||
foreach (var item in _downloadableContents)
|
||||
{
|
||||
item.Enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
public async void Add()
|
||||
{
|
||||
OpenFileDialog dialog = new OpenFileDialog()
|
||||
{
|
||||
Title = LocaleManager.Instance[LocaleKeys.SelectDlcDialogTitle],
|
||||
AllowMultiple = true
|
||||
};
|
||||
|
||||
dialog.Filters.Add(new FileDialogFilter
|
||||
{
|
||||
Name = "NSP",
|
||||
Extensions = { "nsp" }
|
||||
});
|
||||
|
||||
string[] files = await dialog.ShowAsync(this);
|
||||
|
||||
if (files != null)
|
||||
{
|
||||
foreach (string file in files)
|
||||
{
|
||||
await AddDownloadableContent(file);
|
||||
}
|
||||
}
|
||||
|
||||
PrintHeading();
|
||||
}
|
||||
|
||||
public void Save()
|
||||
{
|
||||
_downloadableContentContainerList.Clear();
|
||||
|
||||
DownloadableContentContainer container = default;
|
||||
|
||||
foreach (DownloadableContentModel downloadableContent in _downloadableContents)
|
||||
{
|
||||
if (container.ContainerPath != downloadableContent.ContainerPath)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(container.ContainerPath))
|
||||
{
|
||||
_downloadableContentContainerList.Add(container);
|
||||
}
|
||||
|
||||
container = new DownloadableContentContainer
|
||||
{
|
||||
ContainerPath = downloadableContent.ContainerPath,
|
||||
DownloadableContentNcaList = new List<DownloadableContentNca>()
|
||||
};
|
||||
}
|
||||
|
||||
container.DownloadableContentNcaList.Add(new DownloadableContentNca
|
||||
{
|
||||
Enabled = downloadableContent.Enabled,
|
||||
TitleId = Convert.ToUInt64(downloadableContent.TitleId, 16),
|
||||
FullPath = downloadableContent.FullPath
|
||||
});
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(container.ContainerPath))
|
||||
{
|
||||
_downloadableContentContainerList.Add(container);
|
||||
}
|
||||
|
||||
using (FileStream downloadableContentJsonStream = File.Create(_downloadableContentJsonPath, 4096, FileOptions.WriteThrough))
|
||||
{
|
||||
downloadableContentJsonStream.Write(Encoding.UTF8.GetBytes(JsonHelper.Serialize(_downloadableContentContainerList, true)));
|
||||
}
|
||||
}
|
||||
|
||||
public void SaveAndClose()
|
||||
{
|
||||
Save();
|
||||
Close();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
using Avalonia.Controls;
|
||||
using FluentAvalonia.UI.Controls;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.UI.Models;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Common.Configuration.Hid.Controller;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Windows
|
||||
{
|
||||
public partial class MotionSettingsWindow : UserControl
|
||||
{
|
||||
private readonly InputConfiguration<GamepadInputId, StickInputId> _viewmodel;
|
||||
|
||||
public MotionSettingsWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
DataContext = _viewmodel;
|
||||
}
|
||||
|
||||
public MotionSettingsWindow(ControllerSettingsViewModel viewmodel)
|
||||
{
|
||||
var config = viewmodel.Configuration as InputConfiguration<GamepadInputId, StickInputId>;
|
||||
|
||||
_viewmodel = new InputConfiguration<GamepadInputId, StickInputId>()
|
||||
{
|
||||
Slot = config.Slot,
|
||||
AltSlot = config.AltSlot,
|
||||
DsuServerHost = config.DsuServerHost,
|
||||
DsuServerPort = config.DsuServerPort,
|
||||
MirrorInput = config.MirrorInput,
|
||||
EnableMotion = config.EnableMotion,
|
||||
Sensitivity = config.Sensitivity,
|
||||
GyroDeadzone = config.GyroDeadzone,
|
||||
EnableCemuHookMotion = config.EnableCemuHookMotion
|
||||
};
|
||||
|
||||
InitializeComponent();
|
||||
DataContext = _viewmodel;
|
||||
}
|
||||
|
||||
public static async Task Show(ControllerSettingsViewModel viewmodel)
|
||||
{
|
||||
MotionSettingsWindow content = new MotionSettingsWindow(viewmodel);
|
||||
|
||||
ContentDialog contentDialog = new ContentDialog
|
||||
{
|
||||
Title = LocaleManager.Instance[LocaleKeys.ControllerMotionTitle],
|
||||
PrimaryButtonText = LocaleManager.Instance[LocaleKeys.ControllerSettingsSave],
|
||||
SecondaryButtonText = "",
|
||||
CloseButtonText = LocaleManager.Instance[LocaleKeys.ControllerSettingsClose],
|
||||
Content = content
|
||||
};
|
||||
contentDialog.PrimaryButtonClick += (sender, args) =>
|
||||
{
|
||||
var config = viewmodel.Configuration as InputConfiguration<GamepadInputId, StickInputId>;
|
||||
config.Slot = content._viewmodel.Slot;
|
||||
config.EnableMotion = content._viewmodel.EnableMotion;
|
||||
config.Sensitivity = content._viewmodel.Sensitivity;
|
||||
config.GyroDeadzone = content._viewmodel.GyroDeadzone;
|
||||
config.AltSlot = content._viewmodel.AltSlot;
|
||||
config.DsuServerHost = content._viewmodel.DsuServerHost;
|
||||
config.DsuServerPort = content._viewmodel.DsuServerPort;
|
||||
config.EnableCemuHookMotion = content._viewmodel.EnableCemuHookMotion;
|
||||
config.MirrorInput = content._viewmodel.MirrorInput;
|
||||
};
|
||||
|
||||
await contentDialog.ShowAsync();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
using Avalonia.Controls;
|
||||
using FluentAvalonia.UI.Controls;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.UI.Models;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Common.Configuration.Hid.Controller;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Windows
|
||||
{
|
||||
public partial class RumbleSettingsWindow : UserControl
|
||||
{
|
||||
private readonly InputConfiguration<GamepadInputId, StickInputId> _viewmodel;
|
||||
|
||||
public RumbleSettingsWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
DataContext = _viewmodel;
|
||||
}
|
||||
|
||||
public RumbleSettingsWindow(ControllerSettingsViewModel viewmodel)
|
||||
{
|
||||
var config = viewmodel.Configuration as InputConfiguration<GamepadInputId, StickInputId>;
|
||||
|
||||
_viewmodel = new InputConfiguration<GamepadInputId, StickInputId>()
|
||||
{
|
||||
StrongRumble = config.StrongRumble, WeakRumble = config.WeakRumble
|
||||
};
|
||||
|
||||
InitializeComponent();
|
||||
DataContext = _viewmodel;
|
||||
}
|
||||
|
||||
public static async Task Show(ControllerSettingsViewModel viewmodel)
|
||||
{
|
||||
RumbleSettingsWindow content = new RumbleSettingsWindow(viewmodel);
|
||||
|
||||
ContentDialog contentDialog = new ContentDialog
|
||||
{
|
||||
Title = LocaleManager.Instance[LocaleKeys.ControllerRumbleTitle],
|
||||
PrimaryButtonText = LocaleManager.Instance[LocaleKeys.ControllerSettingsSave],
|
||||
SecondaryButtonText = "",
|
||||
CloseButtonText = LocaleManager.Instance[LocaleKeys.ControllerSettingsClose],
|
||||
Content = content,
|
||||
};
|
||||
|
||||
contentDialog.PrimaryButtonClick += (sender, args) =>
|
||||
{
|
||||
var config = viewmodel.Configuration as InputConfiguration<GamepadInputId, StickInputId>;
|
||||
config.StrongRumble = content._viewmodel.StrongRumble;
|
||||
config.WeakRumble = content._viewmodel.WeakRumble;
|
||||
};
|
||||
|
||||
await contentDialog.ShowAsync();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
namespace Ryujinx.Common.Configuration
|
||||
{
|
||||
public enum AntiAliasing
|
||||
{
|
||||
None,
|
||||
Fxaa,
|
||||
SmaaLow,
|
||||
SmaaMedium,
|
||||
SmaaHigh,
|
||||
SmaaUltra
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
namespace Ryujinx.Common.Configuration
|
||||
{
|
||||
public enum BackendThreading
|
||||
{
|
||||
Auto,
|
||||
Off,
|
||||
On
|
||||
}
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
namespace Ryujinx.Common.Configuration
|
||||
{
|
||||
public enum GraphicsBackend
|
||||
{
|
||||
Vulkan,
|
||||
OpenGl
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
namespace Ryujinx.Common.Configuration
|
||||
{
|
||||
public enum GraphicsDebugLevel
|
||||
{
|
||||
None,
|
||||
Error,
|
||||
Slowdowns,
|
||||
All
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
namespace Ryujinx.Common.Configuration.Hid.Controller.Motion
|
||||
{
|
||||
public enum MotionInputBackendType : byte
|
||||
{
|
||||
Invalid,
|
||||
GamepadDriver,
|
||||
CemuHook
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
namespace Ryujinx.Common.Configuration.Hid.Controller
|
||||
{
|
||||
public enum StickInputId : byte
|
||||
{
|
||||
Unbound,
|
||||
Left,
|
||||
Right,
|
||||
|
||||
Count
|
||||
}
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Common.Configuration.Hid
|
||||
{
|
||||
[Flags]
|
||||
// This enum was duplicated from Ryujinx.HLE.HOS.Services.Hid.PlayerIndex and should be kept identical
|
||||
public enum ControllerType : int
|
||||
{
|
||||
None,
|
||||
ProController = 1 << 0,
|
||||
Handheld = 1 << 1,
|
||||
JoyconPair = 1 << 2,
|
||||
JoyconLeft = 1 << 3,
|
||||
JoyconRight = 1 << 4,
|
||||
Invalid = 1 << 5,
|
||||
Pokeball = 1 << 6,
|
||||
SystemExternal = 1 << 29,
|
||||
System = 1 << 30
|
||||
}
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
namespace Ryujinx.Common.Configuration.Hid
|
||||
{
|
||||
public class GenericInputConfigurationCommon<Button> : InputConfig where Button : unmanaged
|
||||
{
|
||||
/// <summary>
|
||||
/// Left JoyCon Controller Bindings
|
||||
/// </summary>
|
||||
public LeftJoyconCommonConfig<Button> LeftJoycon { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Right JoyCon Controller Bindings
|
||||
/// </summary>
|
||||
public RightJoyconCommonConfig<Button> RightJoycon { get; set; }
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
namespace Ryujinx.Common.Configuration.Hid
|
||||
{
|
||||
public enum InputBackendType
|
||||
{
|
||||
Invalid,
|
||||
WindowKeyboard,
|
||||
GamepadSDL2,
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
namespace Ryujinx.Common.Configuration.Hid.Keyboard
|
||||
{
|
||||
public class JoyconConfigKeyboardStick<Key> where Key: unmanaged
|
||||
{
|
||||
public Key StickUp { get; set; }
|
||||
public Key StickDown { get; set; }
|
||||
public Key StickLeft { get; set; }
|
||||
public Key StickRight { get; set; }
|
||||
public Key StickButton { get; set; }
|
||||
}
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
namespace Ryujinx.Common.Configuration.Hid
|
||||
{
|
||||
public class LeftJoyconCommonConfig<Button>
|
||||
{
|
||||
public Button ButtonMinus { get; set; }
|
||||
public Button ButtonL { get; set; }
|
||||
public Button ButtonZl { get; set; }
|
||||
public Button ButtonSl { get; set; }
|
||||
public Button ButtonSr { get; set; }
|
||||
public Button DpadUp { get; set; }
|
||||
public Button DpadDown { get; set; }
|
||||
public Button DpadLeft { get; set; }
|
||||
public Button DpadRight { get; set; }
|
||||
}
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
namespace Ryujinx.Common.Configuration.Hid
|
||||
{
|
||||
// This enum was duplicated from Ryujinx.HLE.HOS.Services.Hid.PlayerIndex and should be kept identical
|
||||
public enum PlayerIndex : int
|
||||
{
|
||||
Player1 = 0,
|
||||
Player2 = 1,
|
||||
Player3 = 2,
|
||||
Player4 = 3,
|
||||
Player5 = 4,
|
||||
Player6 = 5,
|
||||
Player7 = 6,
|
||||
Player8 = 7,
|
||||
Handheld = 8,
|
||||
Unknown = 9,
|
||||
Auto = 10 // Shouldn't be used directly
|
||||
}
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
namespace Ryujinx.Common.Configuration.Hid
|
||||
{
|
||||
public class RightJoyconCommonConfig<Button>
|
||||
{
|
||||
public Button ButtonPlus { get; set; }
|
||||
public Button ButtonR { get; set; }
|
||||
public Button ButtonZr { get; set; }
|
||||
public Button ButtonSl { get; set; }
|
||||
public Button ButtonSr { get; set; }
|
||||
public Button ButtonX { get; set; }
|
||||
public Button ButtonB { get; set; }
|
||||
public Button ButtonY { get; set; }
|
||||
public Button ButtonA { get; set; }
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
namespace Ryujinx.Common.Configuration
|
||||
{
|
||||
public enum MemoryManagerMode : byte
|
||||
{
|
||||
SoftwarePageTable,
|
||||
HostMapped,
|
||||
HostMappedUnsafe
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
namespace Ryujinx.Common.Configuration
|
||||
{
|
||||
public enum ScalingFilter
|
||||
{
|
||||
Bilinear,
|
||||
Nearest,
|
||||
Fsr
|
||||
}
|
||||
}
|
@ -1,80 +0,0 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace Ryujinx.Common.Logging
|
||||
{
|
||||
internal class DefaultLogFormatter : ILogFormatter
|
||||
{
|
||||
private static readonly ObjectPool<StringBuilder> _stringBuilderPool = SharedPools.Default<StringBuilder>();
|
||||
|
||||
public string Format(LogEventArgs args)
|
||||
{
|
||||
StringBuilder sb = _stringBuilderPool.Allocate();
|
||||
|
||||
try
|
||||
{
|
||||
sb.Clear();
|
||||
|
||||
sb.AppendFormat(@"{0:hh\:mm\:ss\.fff}", args.Time);
|
||||
sb.Append($" |{args.Level.ToString()[0]}| ");
|
||||
|
||||
if (args.ThreadName != null)
|
||||
{
|
||||
sb.Append(args.ThreadName);
|
||||
sb.Append(' ');
|
||||
}
|
||||
|
||||
sb.Append(args.Message);
|
||||
|
||||
if (args.Data != null)
|
||||
{
|
||||
PropertyInfo[] props = args.Data.GetType().GetProperties();
|
||||
|
||||
sb.Append(" {");
|
||||
|
||||
foreach (var prop in props)
|
||||
{
|
||||
sb.Append(prop.Name);
|
||||
sb.Append(": ");
|
||||
|
||||
if (typeof(Array).IsAssignableFrom(prop.PropertyType))
|
||||
{
|
||||
Array array = (Array)prop.GetValue(args.Data);
|
||||
foreach (var item in array)
|
||||
{
|
||||
sb.Append(item.ToString());
|
||||
sb.Append(", ");
|
||||
}
|
||||
|
||||
if (array.Length > 0)
|
||||
{
|
||||
sb.Remove(sb.Length - 2, 2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append(prop.GetValue(args.Data));
|
||||
}
|
||||
|
||||
sb.Append(" ; ");
|
||||
}
|
||||
|
||||
// We remove the final ';' from the string
|
||||
if (props.Length > 0)
|
||||
{
|
||||
sb.Remove(sb.Length - 3, 3);
|
||||
}
|
||||
|
||||
sb.Append('}');
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
finally
|
||||
{
|
||||
_stringBuilderPool.Release(sb);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Common.Logging
|
||||
{
|
||||
public class LogEventArgs : EventArgs
|
||||
{
|
||||
public readonly LogLevel Level;
|
||||
public readonly TimeSpan Time;
|
||||
public readonly string ThreadName;
|
||||
|
||||
public readonly string Message;
|
||||
public readonly object Data;
|
||||
|
||||
public LogEventArgs(LogLevel level, TimeSpan time, string threadName, string message)
|
||||
{
|
||||
Level = level;
|
||||
Time = time;
|
||||
ThreadName = threadName;
|
||||
Message = message;
|
||||
}
|
||||
|
||||
public LogEventArgs(LogLevel level, TimeSpan time, string threadName, string message, object data)
|
||||
{
|
||||
Level = level;
|
||||
Time = time;
|
||||
ThreadName = threadName;
|
||||
Message = message;
|
||||
Data = data;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Common.Memory
|
||||
{
|
||||
public ref struct SpanReader
|
||||
{
|
||||
private ReadOnlySpan<byte> _input;
|
||||
|
||||
public int Length => _input.Length;
|
||||
|
||||
public SpanReader(ReadOnlySpan<byte> input)
|
||||
{
|
||||
_input = input;
|
||||
}
|
||||
|
||||
public T Read<T>() where T : unmanaged
|
||||
{
|
||||
T value = MemoryMarshal.Cast<byte, T>(_input)[0];
|
||||
|
||||
_input = _input.Slice(Unsafe.SizeOf<T>());
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public ReadOnlySpan<byte> GetSpan(int size)
|
||||
{
|
||||
ReadOnlySpan<byte> data = _input.Slice(0, size);
|
||||
|
||||
_input = _input.Slice(size);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
public T ReadAt<T>(int offset) where T : unmanaged
|
||||
{
|
||||
return MemoryMarshal.Cast<byte, T>(_input.Slice(offset))[0];
|
||||
}
|
||||
|
||||
public ReadOnlySpan<byte> GetSpanAt(int offset, int size)
|
||||
{
|
||||
return _input.Slice(offset, size);
|
||||
}
|
||||
|
||||
public void Skip(int size)
|
||||
{
|
||||
_input = _input.Slice(size);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,93 +0,0 @@
|
||||
using Ryujinx.Common.Logging;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Versioning;
|
||||
using System.Threading;
|
||||
|
||||
namespace Ryujinx.Common.SystemInterop
|
||||
{
|
||||
public partial class StdErrAdapter : IDisposable
|
||||
{
|
||||
private bool _disposable = false;
|
||||
private UnixStream _pipeReader;
|
||||
private UnixStream _pipeWriter;
|
||||
private Thread _worker;
|
||||
|
||||
public StdErrAdapter()
|
||||
{
|
||||
if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
|
||||
{
|
||||
RegisterPosix();
|
||||
}
|
||||
}
|
||||
|
||||
[SupportedOSPlatform("linux")]
|
||||
[SupportedOSPlatform("macos")]
|
||||
private void RegisterPosix()
|
||||
{
|
||||
const int stdErrFileno = 2;
|
||||
|
||||
(int readFd, int writeFd) = MakePipe();
|
||||
dup2(writeFd, stdErrFileno);
|
||||
|
||||
_pipeReader = new UnixStream(readFd);
|
||||
_pipeWriter = new UnixStream(writeFd);
|
||||
|
||||
_worker = new Thread(EventWorker);
|
||||
_disposable = true;
|
||||
_worker.Start();
|
||||
}
|
||||
|
||||
[SupportedOSPlatform("linux")]
|
||||
[SupportedOSPlatform("macos")]
|
||||
private void EventWorker()
|
||||
{
|
||||
TextReader reader = new StreamReader(_pipeReader);
|
||||
string line;
|
||||
while ((line = reader.ReadLine()) != null)
|
||||
{
|
||||
Logger.Error?.PrintRawMsg(line);
|
||||
}
|
||||
}
|
||||
|
||||
private void Dispose(bool disposing)
|
||||
{
|
||||
if (_disposable)
|
||||
{
|
||||
if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
|
||||
{
|
||||
_pipeReader?.Close();
|
||||
_pipeWriter?.Close();
|
||||
}
|
||||
|
||||
_disposable = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
}
|
||||
|
||||
[LibraryImport("libc", SetLastError = true)]
|
||||
private static partial int dup2(int fd, int fd2);
|
||||
|
||||
[LibraryImport("libc", SetLastError = true)]
|
||||
private static unsafe partial int pipe(int* pipefd);
|
||||
|
||||
private static unsafe (int, int) MakePipe()
|
||||
{
|
||||
int *pipefd = stackalloc int[2];
|
||||
|
||||
if (pipe(pipefd) == 0)
|
||||
{
|
||||
return (pipefd[0], pipefd[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,155 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Versioning;
|
||||
|
||||
namespace Ryujinx.Common.SystemInterop
|
||||
{
|
||||
[SupportedOSPlatform("linux")]
|
||||
[SupportedOSPlatform("macos")]
|
||||
public partial class UnixStream : Stream, IDisposable
|
||||
{
|
||||
private const int InvalidFd = -1;
|
||||
|
||||
private int _fd;
|
||||
|
||||
[LibraryImport("libc", SetLastError = true)]
|
||||
private static partial long read(int fd, IntPtr buf, ulong count);
|
||||
|
||||
[LibraryImport("libc", SetLastError = true)]
|
||||
private static partial long write(int fd, IntPtr buf, ulong count);
|
||||
|
||||
[LibraryImport("libc", SetLastError = true)]
|
||||
private static partial int close(int fd);
|
||||
|
||||
public UnixStream(int fd)
|
||||
{
|
||||
if (InvalidFd == fd)
|
||||
{
|
||||
throw new ArgumentException("Invalid file descriptor");
|
||||
}
|
||||
|
||||
_fd = fd;
|
||||
|
||||
CanRead = read(fd, IntPtr.Zero, 0) != -1;
|
||||
CanWrite = write(fd, IntPtr.Zero, 0) != -1;
|
||||
}
|
||||
|
||||
~UnixStream()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
public override bool CanRead { get; }
|
||||
public override bool CanWrite { get; }
|
||||
public override bool CanSeek => false;
|
||||
|
||||
public override long Length => throw new NotSupportedException();
|
||||
|
||||
public override long Position
|
||||
{
|
||||
get => throw new NotSupportedException();
|
||||
set => throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
}
|
||||
|
||||
public override unsafe int Read([In, Out] byte[] buffer, int offset, int count)
|
||||
{
|
||||
if (offset < 0 || offset > (buffer.Length - count) || count < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
|
||||
if (buffer.Length == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
long r = 0;
|
||||
fixed (byte* buf = &buffer[offset])
|
||||
{
|
||||
do
|
||||
{
|
||||
r = read(_fd, (IntPtr)buf, (ulong)count);
|
||||
} while (ShouldRetry(r));
|
||||
}
|
||||
|
||||
return (int)r;
|
||||
}
|
||||
|
||||
public override unsafe void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
if (offset < 0 || offset > (buffer.Length - count) || count < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
|
||||
if (buffer.Length == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
fixed (byte* buf = &buffer[offset])
|
||||
{
|
||||
long r = 0;
|
||||
do {
|
||||
r = write(_fd, (IntPtr)buf, (ulong)count);
|
||||
} while (ShouldRetry(r));
|
||||
}
|
||||
}
|
||||
|
||||
public override long Seek(long offset, SeekOrigin origin)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override void SetLength(long value)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override void Close()
|
||||
{
|
||||
if (_fd == InvalidFd)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Flush();
|
||||
|
||||
int r;
|
||||
do {
|
||||
r = close(_fd);
|
||||
} while (ShouldRetry(r));
|
||||
|
||||
_fd = InvalidFd;
|
||||
}
|
||||
|
||||
void IDisposable.Dispose()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
private bool ShouldRetry(long r)
|
||||
{
|
||||
if (r == -1)
|
||||
{
|
||||
const int eintr = 4;
|
||||
|
||||
int errno = Marshal.GetLastPInvokeError();
|
||||
|
||||
if (errno == eintr)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
throw new SystemException($"Operation failed with error 0x{errno:X}");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,110 +0,0 @@
|
||||
using Ryujinx.Common.Configuration.Hid;
|
||||
using Ryujinx.Common.Configuration.Hid.Controller.Motion;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Ryujinx.Common.Utilities
|
||||
{
|
||||
public class JsonHelper
|
||||
{
|
||||
public static JsonNamingPolicy SnakeCase { get; }
|
||||
|
||||
private class SnakeCaseNamingPolicy : JsonNamingPolicy
|
||||
{
|
||||
public override string ConvertName(string name)
|
||||
{
|
||||
if (string.IsNullOrEmpty(name))
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
for (int i = 0; i < name.Length; i++)
|
||||
{
|
||||
char c = name[i];
|
||||
|
||||
if (char.IsUpper(c))
|
||||
{
|
||||
if (i == 0 || char.IsUpper(name[i - 1]))
|
||||
{
|
||||
builder.Append(char.ToLowerInvariant(c));
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.Append("_");
|
||||
builder.Append(char.ToLowerInvariant(c));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.Append(c);
|
||||
}
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
static JsonHelper()
|
||||
{
|
||||
SnakeCase = new SnakeCaseNamingPolicy();
|
||||
}
|
||||
|
||||
public static JsonSerializerOptions GetDefaultSerializerOptions(bool prettyPrint = false)
|
||||
{
|
||||
JsonSerializerOptions options = new JsonSerializerOptions
|
||||
{
|
||||
DictionaryKeyPolicy = SnakeCase,
|
||||
PropertyNamingPolicy = SnakeCase,
|
||||
WriteIndented = prettyPrint,
|
||||
AllowTrailingCommas = true,
|
||||
ReadCommentHandling = JsonCommentHandling.Skip
|
||||
};
|
||||
|
||||
options.Converters.Add(new JsonStringEnumConverter());
|
||||
options.Converters.Add(new JsonInputConfigConverter());
|
||||
options.Converters.Add(new JsonMotionConfigControllerConverter());
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
public static T Deserialize<T>(Stream stream)
|
||||
{
|
||||
using (BinaryReader reader = new BinaryReader(stream))
|
||||
{
|
||||
return JsonSerializer.Deserialize<T>(reader.ReadBytes((int)(stream.Length - stream.Position)), GetDefaultSerializerOptions());
|
||||
}
|
||||
}
|
||||
|
||||
public static T DeserializeFromFile<T>(string path)
|
||||
{
|
||||
return Deserialize<T>(File.ReadAllText(path));
|
||||
}
|
||||
|
||||
public static T Deserialize<T>(string json)
|
||||
{
|
||||
return JsonSerializer.Deserialize<T>(json, GetDefaultSerializerOptions());
|
||||
}
|
||||
|
||||
public static void Serialize<TValue>(Stream stream, TValue obj, bool prettyPrint = false)
|
||||
{
|
||||
using (BinaryWriter writer = new BinaryWriter(stream))
|
||||
{
|
||||
writer.Write(SerializeToUtf8Bytes(obj, prettyPrint));
|
||||
}
|
||||
}
|
||||
|
||||
public static string Serialize<TValue>(TValue obj, bool prettyPrint = false)
|
||||
{
|
||||
return JsonSerializer.Serialize(obj, GetDefaultSerializerOptions(prettyPrint));
|
||||
}
|
||||
|
||||
public static byte[] SerializeToUtf8Bytes<T>(T obj, bool prettyPrint = false)
|
||||
{
|
||||
return JsonSerializer.SerializeToUtf8Bytes(obj, GetDefaultSerializerOptions(prettyPrint));
|
||||
}
|
||||
}
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
using System.IO;
|
||||
|
||||
namespace Ryujinx.Common.Utilities
|
||||
{
|
||||
public static class StreamUtils
|
||||
{
|
||||
public static byte[] StreamToBytes(Stream input)
|
||||
{
|
||||
using (MemoryStream stream = new MemoryStream())
|
||||
{
|
||||
input.CopyTo(stream);
|
||||
|
||||
return stream.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,320 +0,0 @@
|
||||
using ARMeilleure.State;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Cpu.AppleHv
|
||||
{
|
||||
struct hv_vcpu_exit_exception_t
|
||||
{
|
||||
#pragma warning disable CS0649
|
||||
public ulong syndrome;
|
||||
public ulong virtual_address;
|
||||
public ulong physical_address;
|
||||
#pragma warning restore CS0649
|
||||
}
|
||||
|
||||
struct hv_vcpu_exit_t
|
||||
{
|
||||
#pragma warning disable CS0649
|
||||
public uint reason;
|
||||
public hv_vcpu_exit_exception_t exception;
|
||||
#pragma warning restore CS0649
|
||||
}
|
||||
|
||||
enum hv_reg_t : uint
|
||||
{
|
||||
HV_REG_X0,
|
||||
HV_REG_X1,
|
||||
HV_REG_X2,
|
||||
HV_REG_X3,
|
||||
HV_REG_X4,
|
||||
HV_REG_X5,
|
||||
HV_REG_X6,
|
||||
HV_REG_X7,
|
||||
HV_REG_X8,
|
||||
HV_REG_X9,
|
||||
HV_REG_X10,
|
||||
HV_REG_X11,
|
||||
HV_REG_X12,
|
||||
HV_REG_X13,
|
||||
HV_REG_X14,
|
||||
HV_REG_X15,
|
||||
HV_REG_X16,
|
||||
HV_REG_X17,
|
||||
HV_REG_X18,
|
||||
HV_REG_X19,
|
||||
HV_REG_X20,
|
||||
HV_REG_X21,
|
||||
HV_REG_X22,
|
||||
HV_REG_X23,
|
||||
HV_REG_X24,
|
||||
HV_REG_X25,
|
||||
HV_REG_X26,
|
||||
HV_REG_X27,
|
||||
HV_REG_X28,
|
||||
HV_REG_X29,
|
||||
HV_REG_FP = HV_REG_X29,
|
||||
HV_REG_X30,
|
||||
HV_REG_LR = HV_REG_X30,
|
||||
HV_REG_PC,
|
||||
HV_REG_FPCR,
|
||||
HV_REG_FPSR,
|
||||
HV_REG_CPSR,
|
||||
}
|
||||
|
||||
enum hv_simd_fp_reg_t : uint
|
||||
{
|
||||
HV_SIMD_FP_REG_Q0,
|
||||
HV_SIMD_FP_REG_Q1,
|
||||
HV_SIMD_FP_REG_Q2,
|
||||
HV_SIMD_FP_REG_Q3,
|
||||
HV_SIMD_FP_REG_Q4,
|
||||
HV_SIMD_FP_REG_Q5,
|
||||
HV_SIMD_FP_REG_Q6,
|
||||
HV_SIMD_FP_REG_Q7,
|
||||
HV_SIMD_FP_REG_Q8,
|
||||
HV_SIMD_FP_REG_Q9,
|
||||
HV_SIMD_FP_REG_Q10,
|
||||
HV_SIMD_FP_REG_Q11,
|
||||
HV_SIMD_FP_REG_Q12,
|
||||
HV_SIMD_FP_REG_Q13,
|
||||
HV_SIMD_FP_REG_Q14,
|
||||
HV_SIMD_FP_REG_Q15,
|
||||
HV_SIMD_FP_REG_Q16,
|
||||
HV_SIMD_FP_REG_Q17,
|
||||
HV_SIMD_FP_REG_Q18,
|
||||
HV_SIMD_FP_REG_Q19,
|
||||
HV_SIMD_FP_REG_Q20,
|
||||
HV_SIMD_FP_REG_Q21,
|
||||
HV_SIMD_FP_REG_Q22,
|
||||
HV_SIMD_FP_REG_Q23,
|
||||
HV_SIMD_FP_REG_Q24,
|
||||
HV_SIMD_FP_REG_Q25,
|
||||
HV_SIMD_FP_REG_Q26,
|
||||
HV_SIMD_FP_REG_Q27,
|
||||
HV_SIMD_FP_REG_Q28,
|
||||
HV_SIMD_FP_REG_Q29,
|
||||
HV_SIMD_FP_REG_Q30,
|
||||
HV_SIMD_FP_REG_Q31,
|
||||
}
|
||||
|
||||
enum hv_sys_reg_t : ushort
|
||||
{
|
||||
HV_SYS_REG_DBGBVR0_EL1 = 0x8004,
|
||||
HV_SYS_REG_DBGBCR0_EL1 = 0x8005,
|
||||
HV_SYS_REG_DBGWVR0_EL1 = 0x8006,
|
||||
HV_SYS_REG_DBGWCR0_EL1 = 0x8007,
|
||||
HV_SYS_REG_DBGBVR1_EL1 = 0x800c,
|
||||
HV_SYS_REG_DBGBCR1_EL1 = 0x800d,
|
||||
HV_SYS_REG_DBGWVR1_EL1 = 0x800e,
|
||||
HV_SYS_REG_DBGWCR1_EL1 = 0x800f,
|
||||
HV_SYS_REG_MDCCINT_EL1 = 0x8010,
|
||||
HV_SYS_REG_MDSCR_EL1 = 0x8012,
|
||||
HV_SYS_REG_DBGBVR2_EL1 = 0x8014,
|
||||
HV_SYS_REG_DBGBCR2_EL1 = 0x8015,
|
||||
HV_SYS_REG_DBGWVR2_EL1 = 0x8016,
|
||||
HV_SYS_REG_DBGWCR2_EL1 = 0x8017,
|
||||
HV_SYS_REG_DBGBVR3_EL1 = 0x801c,
|
||||
HV_SYS_REG_DBGBCR3_EL1 = 0x801d,
|
||||
HV_SYS_REG_DBGWVR3_EL1 = 0x801e,
|
||||
HV_SYS_REG_DBGWCR3_EL1 = 0x801f,
|
||||
HV_SYS_REG_DBGBVR4_EL1 = 0x8024,
|
||||
HV_SYS_REG_DBGBCR4_EL1 = 0x8025,
|
||||
HV_SYS_REG_DBGWVR4_EL1 = 0x8026,
|
||||
HV_SYS_REG_DBGWCR4_EL1 = 0x8027,
|
||||
HV_SYS_REG_DBGBVR5_EL1 = 0x802c,
|
||||
HV_SYS_REG_DBGBCR5_EL1 = 0x802d,
|
||||
HV_SYS_REG_DBGWVR5_EL1 = 0x802e,
|
||||
HV_SYS_REG_DBGWCR5_EL1 = 0x802f,
|
||||
HV_SYS_REG_DBGBVR6_EL1 = 0x8034,
|
||||
HV_SYS_REG_DBGBCR6_EL1 = 0x8035,
|
||||
HV_SYS_REG_DBGWVR6_EL1 = 0x8036,
|
||||
HV_SYS_REG_DBGWCR6_EL1 = 0x8037,
|
||||
HV_SYS_REG_DBGBVR7_EL1 = 0x803c,
|
||||
HV_SYS_REG_DBGBCR7_EL1 = 0x803d,
|
||||
HV_SYS_REG_DBGWVR7_EL1 = 0x803e,
|
||||
HV_SYS_REG_DBGWCR7_EL1 = 0x803f,
|
||||
HV_SYS_REG_DBGBVR8_EL1 = 0x8044,
|
||||
HV_SYS_REG_DBGBCR8_EL1 = 0x8045,
|
||||
HV_SYS_REG_DBGWVR8_EL1 = 0x8046,
|
||||
HV_SYS_REG_DBGWCR8_EL1 = 0x8047,
|
||||
HV_SYS_REG_DBGBVR9_EL1 = 0x804c,
|
||||
HV_SYS_REG_DBGBCR9_EL1 = 0x804d,
|
||||
HV_SYS_REG_DBGWVR9_EL1 = 0x804e,
|
||||
HV_SYS_REG_DBGWCR9_EL1 = 0x804f,
|
||||
HV_SYS_REG_DBGBVR10_EL1 = 0x8054,
|
||||
HV_SYS_REG_DBGBCR10_EL1 = 0x8055,
|
||||
HV_SYS_REG_DBGWVR10_EL1 = 0x8056,
|
||||
HV_SYS_REG_DBGWCR10_EL1 = 0x8057,
|
||||
HV_SYS_REG_DBGBVR11_EL1 = 0x805c,
|
||||
HV_SYS_REG_DBGBCR11_EL1 = 0x805d,
|
||||
HV_SYS_REG_DBGWVR11_EL1 = 0x805e,
|
||||
HV_SYS_REG_DBGWCR11_EL1 = 0x805f,
|
||||
HV_SYS_REG_DBGBVR12_EL1 = 0x8064,
|
||||
HV_SYS_REG_DBGBCR12_EL1 = 0x8065,
|
||||
HV_SYS_REG_DBGWVR12_EL1 = 0x8066,
|
||||
HV_SYS_REG_DBGWCR12_EL1 = 0x8067,
|
||||
HV_SYS_REG_DBGBVR13_EL1 = 0x806c,
|
||||
HV_SYS_REG_DBGBCR13_EL1 = 0x806d,
|
||||
HV_SYS_REG_DBGWVR13_EL1 = 0x806e,
|
||||
HV_SYS_REG_DBGWCR13_EL1 = 0x806f,
|
||||
HV_SYS_REG_DBGBVR14_EL1 = 0x8074,
|
||||
HV_SYS_REG_DBGBCR14_EL1 = 0x8075,
|
||||
HV_SYS_REG_DBGWVR14_EL1 = 0x8076,
|
||||
HV_SYS_REG_DBGWCR14_EL1 = 0x8077,
|
||||
HV_SYS_REG_DBGBVR15_EL1 = 0x807c,
|
||||
HV_SYS_REG_DBGBCR15_EL1 = 0x807d,
|
||||
HV_SYS_REG_DBGWVR15_EL1 = 0x807e,
|
||||
HV_SYS_REG_DBGWCR15_EL1 = 0x807f,
|
||||
HV_SYS_REG_MIDR_EL1 = 0xc000,
|
||||
HV_SYS_REG_MPIDR_EL1 = 0xc005,
|
||||
HV_SYS_REG_ID_AA64PFR0_EL1 = 0xc020,
|
||||
HV_SYS_REG_ID_AA64PFR1_EL1 = 0xc021,
|
||||
HV_SYS_REG_ID_AA64DFR0_EL1 = 0xc028,
|
||||
HV_SYS_REG_ID_AA64DFR1_EL1 = 0xc029,
|
||||
HV_SYS_REG_ID_AA64ISAR0_EL1 = 0xc030,
|
||||
HV_SYS_REG_ID_AA64ISAR1_EL1 = 0xc031,
|
||||
HV_SYS_REG_ID_AA64MMFR0_EL1 = 0xc038,
|
||||
HV_SYS_REG_ID_AA64MMFR1_EL1 = 0xc039,
|
||||
HV_SYS_REG_ID_AA64MMFR2_EL1 = 0xc03a,
|
||||
HV_SYS_REG_SCTLR_EL1 = 0xc080,
|
||||
HV_SYS_REG_CPACR_EL1 = 0xc082,
|
||||
HV_SYS_REG_TTBR0_EL1 = 0xc100,
|
||||
HV_SYS_REG_TTBR1_EL1 = 0xc101,
|
||||
HV_SYS_REG_TCR_EL1 = 0xc102,
|
||||
HV_SYS_REG_APIAKEYLO_EL1 = 0xc108,
|
||||
HV_SYS_REG_APIAKEYHI_EL1 = 0xc109,
|
||||
HV_SYS_REG_APIBKEYLO_EL1 = 0xc10a,
|
||||
HV_SYS_REG_APIBKEYHI_EL1 = 0xc10b,
|
||||
HV_SYS_REG_APDAKEYLO_EL1 = 0xc110,
|
||||
HV_SYS_REG_APDAKEYHI_EL1 = 0xc111,
|
||||
HV_SYS_REG_APDBKEYLO_EL1 = 0xc112,
|
||||
HV_SYS_REG_APDBKEYHI_EL1 = 0xc113,
|
||||
HV_SYS_REG_APGAKEYLO_EL1 = 0xc118,
|
||||
HV_SYS_REG_APGAKEYHI_EL1 = 0xc119,
|
||||
HV_SYS_REG_SPSR_EL1 = 0xc200,
|
||||
HV_SYS_REG_ELR_EL1 = 0xc201,
|
||||
HV_SYS_REG_SP_EL0 = 0xc208,
|
||||
HV_SYS_REG_AFSR0_EL1 = 0xc288,
|
||||
HV_SYS_REG_AFSR1_EL1 = 0xc289,
|
||||
HV_SYS_REG_ESR_EL1 = 0xc290,
|
||||
HV_SYS_REG_FAR_EL1 = 0xc300,
|
||||
HV_SYS_REG_PAR_EL1 = 0xc3a0,
|
||||
HV_SYS_REG_MAIR_EL1 = 0xc510,
|
||||
HV_SYS_REG_AMAIR_EL1 = 0xc518,
|
||||
HV_SYS_REG_VBAR_EL1 = 0xc600,
|
||||
HV_SYS_REG_CONTEXTIDR_EL1 = 0xc681,
|
||||
HV_SYS_REG_TPIDR_EL1 = 0xc684,
|
||||
HV_SYS_REG_CNTKCTL_EL1 = 0xc708,
|
||||
HV_SYS_REG_CSSELR_EL1 = 0xd000,
|
||||
HV_SYS_REG_TPIDR_EL0 = 0xde82,
|
||||
HV_SYS_REG_TPIDRRO_EL0 = 0xde83,
|
||||
HV_SYS_REG_CNTV_CTL_EL0 = 0xdf19,
|
||||
HV_SYS_REG_CNTV_CVAL_EL0 = 0xdf1a,
|
||||
HV_SYS_REG_SP_EL1 = 0xe208,
|
||||
}
|
||||
|
||||
enum hv_memory_flags_t : ulong
|
||||
{
|
||||
HV_MEMORY_READ = 1UL << 0,
|
||||
HV_MEMORY_WRITE = 1UL << 1,
|
||||
HV_MEMORY_EXEC = 1UL << 2
|
||||
}
|
||||
|
||||
enum hv_result_t : uint
|
||||
{
|
||||
HV_SUCCESS = 0,
|
||||
HV_ERROR = 0xfae94001,
|
||||
HV_BUSY = 0xfae94002,
|
||||
HV_BAD_ARGUMENT = 0xfae94003,
|
||||
HV_NO_RESOURCES = 0xfae94005,
|
||||
HV_NO_DEVICE = 0xfae94006,
|
||||
HV_DENIED = 0xfae94007,
|
||||
HV_UNSUPPORTED = 0xfae9400f
|
||||
}
|
||||
|
||||
enum hv_interrupt_type_t : uint
|
||||
{
|
||||
HV_INTERRUPT_TYPE_IRQ,
|
||||
HV_INTERRUPT_TYPE_FIQ
|
||||
}
|
||||
|
||||
struct hv_simd_fp_uchar16_t
|
||||
{
|
||||
public ulong Low;
|
||||
public ulong High;
|
||||
}
|
||||
|
||||
static class HvResultExtensions
|
||||
{
|
||||
public static void ThrowOnError(this hv_result_t result)
|
||||
{
|
||||
if (result != hv_result_t.HV_SUCCESS)
|
||||
{
|
||||
throw new Exception($"Unexpected result \"{result}\".");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static partial class HvApi
|
||||
{
|
||||
public const string LibraryName = "/System/Library/Frameworks/Hypervisor.framework/Hypervisor";
|
||||
|
||||
[LibraryImport(LibraryName, SetLastError = true)]
|
||||
public static partial hv_result_t hv_vm_get_max_vcpu_count(out uint max_vcpu_count);
|
||||
|
||||
[LibraryImport(LibraryName, SetLastError = true)]
|
||||
public static partial hv_result_t hv_vm_create(IntPtr config);
|
||||
|
||||
[LibraryImport(LibraryName, SetLastError = true)]
|
||||
public static partial hv_result_t hv_vm_destroy();
|
||||
|
||||
[LibraryImport(LibraryName, SetLastError = true)]
|
||||
public static partial hv_result_t hv_vm_map(ulong addr, ulong ipa, ulong size, hv_memory_flags_t flags);
|
||||
|
||||
[LibraryImport(LibraryName, SetLastError = true)]
|
||||
public static partial hv_result_t hv_vm_unmap(ulong ipa, ulong size);
|
||||
|
||||
[LibraryImport(LibraryName, SetLastError = true)]
|
||||
public static partial hv_result_t hv_vm_protect(ulong ipa, ulong size, hv_memory_flags_t flags);
|
||||
|
||||
[LibraryImport(LibraryName, SetLastError = true)]
|
||||
public unsafe static partial hv_result_t hv_vcpu_create(out ulong vcpu, ref hv_vcpu_exit_t* exit, IntPtr config);
|
||||
|
||||
[LibraryImport(LibraryName, SetLastError = true)]
|
||||
public unsafe static partial hv_result_t hv_vcpu_destroy(ulong vcpu);
|
||||
|
||||
[LibraryImport(LibraryName, SetLastError = true)]
|
||||
public static partial hv_result_t hv_vcpu_run(ulong vcpu);
|
||||
|
||||
[LibraryImport(LibraryName, SetLastError = true)]
|
||||
public static partial hv_result_t hv_vcpus_exit(ref ulong vcpus, uint vcpu_count);
|
||||
|
||||
[LibraryImport(LibraryName, SetLastError = true)]
|
||||
public static partial hv_result_t hv_vcpu_set_vtimer_mask(ulong vcpu, [MarshalAs(UnmanagedType.Bool)] bool vtimer_is_masked);
|
||||
|
||||
[LibraryImport(LibraryName, SetLastError = true)]
|
||||
public static partial hv_result_t hv_vcpu_get_reg(ulong vcpu, hv_reg_t reg, out ulong value);
|
||||
|
||||
[LibraryImport(LibraryName, SetLastError = true)]
|
||||
public static partial hv_result_t hv_vcpu_set_reg(ulong vcpu, hv_reg_t reg, ulong value);
|
||||
|
||||
[LibraryImport(LibraryName, SetLastError = true)]
|
||||
public static partial hv_result_t hv_vcpu_get_simd_fp_reg(ulong vcpu, hv_simd_fp_reg_t reg, out hv_simd_fp_uchar16_t value);
|
||||
|
||||
[LibraryImport(LibraryName, SetLastError = true)]
|
||||
public static partial hv_result_t hv_vcpu_set_simd_fp_reg(ulong vcpu, hv_simd_fp_reg_t reg, hv_simd_fp_uchar16_t value); // DO NOT USE DIRECTLY!
|
||||
|
||||
[LibraryImport(LibraryName, SetLastError = true)]
|
||||
public static partial hv_result_t hv_vcpu_get_sys_reg(ulong vcpu, hv_sys_reg_t reg, out ulong value);
|
||||
|
||||
[LibraryImport(LibraryName, SetLastError = true)]
|
||||
public static partial hv_result_t hv_vcpu_set_sys_reg(ulong vcpu, hv_sys_reg_t reg, ulong value);
|
||||
|
||||
[LibraryImport(LibraryName, SetLastError = true)]
|
||||
public static partial hv_result_t hv_vcpu_get_pending_interrupt(ulong vcpu, hv_interrupt_type_t type, [MarshalAs(UnmanagedType.Bool)] out bool pending);
|
||||
|
||||
[LibraryImport(LibraryName, SetLastError = true)]
|
||||
public static partial hv_result_t hv_vcpu_set_pending_interrupt(ulong vcpu, hv_interrupt_type_t type, [MarshalAs(UnmanagedType.Bool)] bool pending);
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
using Ryujinx.Memory.Tracking;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ryujinx.Cpu.Tracking
|
||||
{
|
||||
public class CpuMultiRegionHandle : IMultiRegionHandle
|
||||
{
|
||||
private readonly MultiRegionHandle _impl;
|
||||
|
||||
public bool Dirty => _impl.Dirty;
|
||||
|
||||
internal CpuMultiRegionHandle(MultiRegionHandle impl)
|
||||
{
|
||||
_impl = impl;
|
||||
}
|
||||
|
||||
public void Dispose() => _impl.Dispose();
|
||||
public void ForceDirty(ulong address, ulong size) => _impl.ForceDirty(address, size);
|
||||
public IEnumerable<IRegionHandle> GetHandles() => _impl.GetHandles();
|
||||
public void QueryModified(Action<ulong, ulong> modifiedAction) => _impl.QueryModified(modifiedAction);
|
||||
public void QueryModified(ulong address, ulong size, Action<ulong, ulong> modifiedAction) => _impl.QueryModified(address, size, modifiedAction);
|
||||
public void QueryModified(ulong address, ulong size, Action<ulong, ulong> modifiedAction, int sequenceNumber) => _impl.QueryModified(address, size, modifiedAction, sequenceNumber);
|
||||
public void RegisterAction(ulong address, ulong size, RegionSignal action) => _impl.RegisterAction(address, size, action);
|
||||
public void RegisterPreciseAction(ulong address, ulong size, PreciseRegionSignal action) => _impl.RegisterPreciseAction(address, size, action);
|
||||
public void SignalWrite() => _impl.SignalWrite();
|
||||
}
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
using Ryujinx.Memory.Tracking;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Cpu.Tracking
|
||||
{
|
||||
public class CpuRegionHandle : IRegionHandle
|
||||
{
|
||||
private readonly RegionHandle _impl;
|
||||
|
||||
public bool Dirty => _impl.Dirty;
|
||||
public bool Unmapped => _impl.Unmapped;
|
||||
public ulong Address => _impl.Address;
|
||||
public ulong Size => _impl.Size;
|
||||
public ulong EndAddress => _impl.EndAddress;
|
||||
|
||||
internal CpuRegionHandle(RegionHandle impl)
|
||||
{
|
||||
_impl = impl;
|
||||
}
|
||||
|
||||
public void Dispose() => _impl.Dispose();
|
||||
public bool DirtyOrVolatile() => _impl.DirtyOrVolatile();
|
||||
public void ForceDirty() => _impl.ForceDirty();
|
||||
public IRegionHandle GetHandle() => _impl;
|
||||
public void RegisterAction(RegionSignal action) => _impl.RegisterAction(action);
|
||||
public void RegisterPreciseAction(PreciseRegionSignal action) => _impl.RegisterPreciseAction(action);
|
||||
public void RegisterDirtyEvent(Action action) => _impl.RegisterDirtyEvent(action);
|
||||
public void Reprotect(bool asDirty = false) => _impl.Reprotect(asDirty);
|
||||
|
||||
public bool OverlapsWith(ulong address, ulong size) => _impl.OverlapsWith(address, size);
|
||||
}
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
using Ryujinx.Memory.Tracking;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Cpu.Tracking
|
||||
{
|
||||
public class CpuSmartMultiRegionHandle : IMultiRegionHandle
|
||||
{
|
||||
private readonly SmartMultiRegionHandle _impl;
|
||||
|
||||
public bool Dirty => _impl.Dirty;
|
||||
|
||||
internal CpuSmartMultiRegionHandle(SmartMultiRegionHandle impl)
|
||||
{
|
||||
_impl = impl;
|
||||
}
|
||||
|
||||
public void Dispose() => _impl.Dispose();
|
||||
public void ForceDirty(ulong address, ulong size) => _impl.ForceDirty(address, size);
|
||||
public void RegisterAction(RegionSignal action) => _impl.RegisterAction(action);
|
||||
public void RegisterPreciseAction(PreciseRegionSignal action) => _impl.RegisterPreciseAction(action);
|
||||
public void QueryModified(Action<ulong, ulong> modifiedAction) => _impl.QueryModified(modifiedAction);
|
||||
public void QueryModified(ulong address, ulong size, Action<ulong, ulong> modifiedAction) => _impl.QueryModified(address, size, modifiedAction);
|
||||
public void QueryModified(ulong address, ulong size, Action<ulong, ulong> modifiedAction, int sequenceNumber) => _impl.QueryModified(address, size, modifiedAction, sequenceNumber);
|
||||
public void SignalWrite() => _impl.SignalWrite();
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
namespace Ryujinx.Graphics.GAL
|
||||
{
|
||||
public enum BlendFactor
|
||||
{
|
||||
Zero = 1,
|
||||
One,
|
||||
SrcColor,
|
||||
OneMinusSrcColor,
|
||||
SrcAlpha,
|
||||
OneMinusSrcAlpha,
|
||||
DstAlpha,
|
||||
OneMinusDstAlpha,
|
||||
DstColor,
|
||||
OneMinusDstColor,
|
||||
SrcAlphaSaturate,
|
||||
Src1Color = 0x10,
|
||||
OneMinusSrc1Color,
|
||||
Src1Alpha,
|
||||
OneMinusSrc1Alpha,
|
||||
ConstantColor = 0xc001,
|
||||
OneMinusConstantColor,
|
||||
ConstantAlpha,
|
||||
OneMinusConstantAlpha,
|
||||
|
||||
ZeroGl = 0x4000,
|
||||
OneGl = 0x4001,
|
||||
SrcColorGl = 0x4300,
|
||||
OneMinusSrcColorGl = 0x4301,
|
||||
SrcAlphaGl = 0x4302,
|
||||
OneMinusSrcAlphaGl = 0x4303,
|
||||
DstAlphaGl = 0x4304,
|
||||
OneMinusDstAlphaGl = 0x4305,
|
||||
DstColorGl = 0x4306,
|
||||
OneMinusDstColorGl = 0x4307,
|
||||
SrcAlphaSaturateGl = 0x4308,
|
||||
Src1ColorGl = 0xc900,
|
||||
OneMinusSrc1ColorGl = 0xc901,
|
||||
Src1AlphaGl = 0xc902,
|
||||
OneMinusSrc1AlphaGl = 0xc903
|
||||
}
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
namespace Ryujinx.Graphics.GAL
|
||||
{
|
||||
public enum BlendOp
|
||||
{
|
||||
Add = 1,
|
||||
Subtract,
|
||||
ReverseSubtract,
|
||||
Minimum,
|
||||
Maximum,
|
||||
|
||||
AddGl = 0x8006,
|
||||
MinimumGl = 0x8007,
|
||||
MaximumGl = 0x8008,
|
||||
SubtractGl = 0x800a,
|
||||
ReverseSubtractGl = 0x800b
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
namespace Ryujinx.Graphics.GAL
|
||||
{
|
||||
public enum Face
|
||||
{
|
||||
Front = 0x404,
|
||||
Back = 0x405,
|
||||
FrontAndBack = 0x408
|
||||
}
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
namespace Ryujinx.Graphics.GAL
|
||||
{
|
||||
public readonly struct ImageCrop
|
||||
{
|
||||
public int Left { get; }
|
||||
public int Right { get; }
|
||||
public int Top { get; }
|
||||
public int Bottom { get; }
|
||||
public bool FlipX { get; }
|
||||
public bool FlipY { get; }
|
||||
public bool IsStretched { get; }
|
||||
public float AspectRatioX { get; }
|
||||
public float AspectRatioY { get; }
|
||||
|
||||
public ImageCrop(
|
||||
int left,
|
||||
int right,
|
||||
int top,
|
||||
int bottom,
|
||||
bool flipX,
|
||||
bool flipY,
|
||||
bool isStretched,
|
||||
float aspectRatioX,
|
||||
float aspectRatioY)
|
||||
{
|
||||
Left = left;
|
||||
Right = right;
|
||||
Top = top;
|
||||
Bottom = bottom;
|
||||
FlipX = flipX;
|
||||
FlipY = flipY;
|
||||
IsStretched = isStretched;
|
||||
AspectRatioX = aspectRatioX;
|
||||
AspectRatioY = aspectRatioY;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
|
||||
{
|
||||
struct SetRenderTargetScaleCommand : IGALCommand, IGALCommand<SetRenderTargetScaleCommand>
|
||||
{
|
||||
public CommandType CommandType => CommandType.SetRenderTargetScale;
|
||||
private float _scale;
|
||||
|
||||
public void Set(float scale)
|
||||
{
|
||||
_scale = scale;
|
||||
}
|
||||
|
||||
public static void Run(ref SetRenderTargetScaleCommand command, ThreadedRenderer threaded, IRenderer renderer)
|
||||
{
|
||||
renderer.Pipeline.SetRenderTargetScale(command._scale);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
using Ryujinx.Graphics.GAL.Multithreading.Model;
|
||||
|
||||
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
|
||||
{
|
||||
struct UpdateRenderScaleCommand : IGALCommand, IGALCommand<UpdateRenderScaleCommand>
|
||||
{
|
||||
public CommandType CommandType => CommandType.UpdateRenderScale;
|
||||
private SpanRef<float> _scales;
|
||||
private int _totalCount;
|
||||
private int _fragmentCount;
|
||||
|
||||
public void Set(SpanRef<float> scales, int totalCount, int fragmentCount)
|
||||
{
|
||||
_scales = scales;
|
||||
_totalCount = totalCount;
|
||||
_fragmentCount = fragmentCount;
|
||||
}
|
||||
|
||||
public static void Run(ref UpdateRenderScaleCommand command, ThreadedRenderer threaded, IRenderer renderer)
|
||||
{
|
||||
renderer.Pipeline.UpdateRenderScale(command._scales.Get(threaded), command._totalCount, command._fragmentCount);
|
||||
command._scales.Dispose(threaded);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Graphics.GAL.Multithreading.Model
|
||||
{
|
||||
unsafe struct PinnedSpan<T> where T : unmanaged
|
||||
{
|
||||
private void* _ptr;
|
||||
private int _size;
|
||||
|
||||
public PinnedSpan(ReadOnlySpan<T> span)
|
||||
{
|
||||
_ptr = Unsafe.AsPointer(ref MemoryMarshal.GetReference(span));
|
||||
_size = span.Length;
|
||||
}
|
||||
|
||||
public ReadOnlySpan<T> Get()
|
||||
{
|
||||
return new ReadOnlySpan<T>(_ptr, _size * Unsafe.SizeOf<T>());
|
||||
}
|
||||
}
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
namespace Ryujinx.Graphics.GAL
|
||||
{
|
||||
public readonly struct ScreenCaptureImageInfo
|
||||
{
|
||||
public ScreenCaptureImageInfo(int width, int height, bool isBgra, byte[] data, bool flipX, bool flipY)
|
||||
{
|
||||
Width = width;
|
||||
Height = height;
|
||||
IsBgra = isBgra;
|
||||
Data = data;
|
||||
FlipX = flipX;
|
||||
FlipY = flipY;
|
||||
}
|
||||
|
||||
public int Width { get; }
|
||||
public int Height { get; }
|
||||
public byte[] Data { get; }
|
||||
public bool IsBgra { get; }
|
||||
public bool FlipX { get; }
|
||||
public bool FlipY { get; }
|
||||
}
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ryujinx.Graphics.GAL
|
||||
{
|
||||
public readonly struct ShaderBindings
|
||||
{
|
||||
public IReadOnlyCollection<int> UniformBufferBindings { get; }
|
||||
public IReadOnlyCollection<int> StorageBufferBindings { get; }
|
||||
public IReadOnlyCollection<int> TextureBindings { get; }
|
||||
public IReadOnlyCollection<int> ImageBindings { get; }
|
||||
|
||||
public ShaderBindings(
|
||||
IReadOnlyCollection<int> uniformBufferBindings,
|
||||
IReadOnlyCollection<int> storageBufferBindings,
|
||||
IReadOnlyCollection<int> textureBindings,
|
||||
IReadOnlyCollection<int> imageBindings)
|
||||
{
|
||||
UniformBufferBindings = uniformBufferBindings;
|
||||
StorageBufferBindings = storageBufferBindings;
|
||||
TextureBindings = textureBindings;
|
||||
ImageBindings = imageBindings;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
namespace Ryujinx.Graphics.GAL
|
||||
{
|
||||
public readonly struct StencilTestDescriptor
|
||||
{
|
||||
public bool TestEnable { get; }
|
||||
|
||||
public CompareOp FrontFunc { get; }
|
||||
public StencilOp FrontSFail { get; }
|
||||
public StencilOp FrontDpPass { get; }
|
||||
public StencilOp FrontDpFail { get; }
|
||||
public int FrontFuncRef { get; }
|
||||
public int FrontFuncMask { get; }
|
||||
public int FrontMask { get; }
|
||||
public CompareOp BackFunc { get; }
|
||||
public StencilOp BackSFail { get; }
|
||||
public StencilOp BackDpPass { get; }
|
||||
public StencilOp BackDpFail { get; }
|
||||
public int BackFuncRef { get; }
|
||||
public int BackFuncMask { get; }
|
||||
public int BackMask { get; }
|
||||
|
||||
public StencilTestDescriptor(
|
||||
bool testEnable,
|
||||
CompareOp frontFunc,
|
||||
StencilOp frontSFail,
|
||||
StencilOp frontDpPass,
|
||||
StencilOp frontDpFail,
|
||||
int frontFuncRef,
|
||||
int frontFuncMask,
|
||||
int frontMask,
|
||||
CompareOp backFunc,
|
||||
StencilOp backSFail,
|
||||
StencilOp backDpPass,
|
||||
StencilOp backDpFail,
|
||||
int backFuncRef,
|
||||
int backFuncMask,
|
||||
int backMask)
|
||||
{
|
||||
TestEnable = testEnable;
|
||||
FrontFunc = frontFunc;
|
||||
FrontSFail = frontSFail;
|
||||
FrontDpPass = frontDpPass;
|
||||
FrontDpFail = frontDpFail;
|
||||
FrontFuncRef = frontFuncRef;
|
||||
FrontFuncMask = frontFuncMask;
|
||||
FrontMask = frontMask;
|
||||
BackFunc = backFunc;
|
||||
BackSFail = backSFail;
|
||||
BackDpPass = backDpPass;
|
||||
BackDpFail = backDpFail;
|
||||
BackFuncRef = backFuncRef;
|
||||
BackFuncMask = backFuncMask;
|
||||
BackMask = backMask;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,101 +0,0 @@
|
||||
using Ryujinx.Graphics.Shader;
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Graphics.GAL
|
||||
{
|
||||
public class SupportBufferUpdater : IDisposable
|
||||
{
|
||||
public SupportBuffer Data;
|
||||
public BufferHandle Handle;
|
||||
|
||||
private IRenderer _renderer;
|
||||
private int _startOffset = -1;
|
||||
private int _endOffset = -1;
|
||||
|
||||
public SupportBufferUpdater(IRenderer renderer)
|
||||
{
|
||||
_renderer = renderer;
|
||||
Handle = renderer.CreateBuffer(SupportBuffer.RequiredSize);
|
||||
renderer.Pipeline.ClearBuffer(Handle, 0, SupportBuffer.RequiredSize, 0);
|
||||
}
|
||||
|
||||
private void MarkDirty(int startOffset, int byteSize)
|
||||
{
|
||||
int endOffset = startOffset + byteSize;
|
||||
|
||||
if (_startOffset == -1)
|
||||
{
|
||||
_startOffset = startOffset;
|
||||
_endOffset = endOffset;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (startOffset < _startOffset)
|
||||
{
|
||||
_startOffset = startOffset;
|
||||
}
|
||||
|
||||
if (endOffset > _endOffset)
|
||||
{
|
||||
_endOffset = endOffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateFragmentRenderScaleCount(int count)
|
||||
{
|
||||
if (Data.FragmentRenderScaleCount.X != count)
|
||||
{
|
||||
Data.FragmentRenderScaleCount.X = count;
|
||||
|
||||
MarkDirty(SupportBuffer.FragmentRenderScaleCountOffset, sizeof(int));
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateGenericField<T>(int baseOffset, ReadOnlySpan<T> data, Span<T> target, int offset, int count) where T : unmanaged
|
||||
{
|
||||
data.Slice(0, count).CopyTo(target.Slice(offset));
|
||||
|
||||
int elemSize = Unsafe.SizeOf<T>();
|
||||
|
||||
MarkDirty(baseOffset + offset * elemSize, count * elemSize);
|
||||
}
|
||||
|
||||
public void UpdateRenderScale(ReadOnlySpan<Vector4<float>> data, int offset, int count)
|
||||
{
|
||||
UpdateGenericField(SupportBuffer.GraphicsRenderScaleOffset, data, Data.RenderScale.AsSpan(), offset, count);
|
||||
}
|
||||
|
||||
public void UpdateFragmentIsBgra(ReadOnlySpan<Vector4<int>> data, int offset, int count)
|
||||
{
|
||||
UpdateGenericField(SupportBuffer.FragmentIsBgraOffset, data, Data.FragmentIsBgra.AsSpan(), offset, count);
|
||||
}
|
||||
|
||||
public void UpdateViewportInverse(Vector4<float> data)
|
||||
{
|
||||
Data.ViewportInverse = data;
|
||||
|
||||
MarkDirty(SupportBuffer.ViewportInverseOffset, SupportBuffer.FieldSize);
|
||||
}
|
||||
|
||||
public void Commit()
|
||||
{
|
||||
if (_startOffset != -1)
|
||||
{
|
||||
ReadOnlySpan<byte> data = MemoryMarshal.Cast<SupportBuffer, byte>(MemoryMarshal.CreateSpan(ref Data, 1));
|
||||
|
||||
_renderer.SetBufferData(Handle, _startOffset, data.Slice(_startOffset, _endOffset - _startOffset));
|
||||
|
||||
_startOffset = -1;
|
||||
_endOffset = -1;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_renderer.DeleteBuffer(Handle);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,275 +0,0 @@
|
||||
using Ryujinx.Graphics.Gpu.Engine.Types;
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Ryujinx.Graphics.Gpu.Engine.Compute
|
||||
{
|
||||
/// <summary>
|
||||
/// Type of the dependent Queue Meta Data.
|
||||
/// </summary>
|
||||
enum DependentQmdType
|
||||
{
|
||||
Queue,
|
||||
Grid
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Type of the release memory barrier.
|
||||
/// </summary>
|
||||
enum ReleaseMembarType
|
||||
{
|
||||
FeNone,
|
||||
FeSysmembar
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Type of the CWD memory barrier.
|
||||
/// </summary>
|
||||
enum CwdMembarType
|
||||
{
|
||||
L1None,
|
||||
L1Sysmembar,
|
||||
L1Membar
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// NaN behavior of 32-bits float operations on the shader.
|
||||
/// </summary>
|
||||
enum Fp32NanBehavior
|
||||
{
|
||||
Legacy,
|
||||
Fp64Compatible
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// NaN behavior of 32-bits float to integer conversion on the shader.
|
||||
/// </summary>
|
||||
enum Fp32F2iNanBehavior
|
||||
{
|
||||
PassZero,
|
||||
PassIndefinite
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Limit of calls.
|
||||
/// </summary>
|
||||
enum ApiVisibleCallLimit
|
||||
{
|
||||
_32,
|
||||
NoCheck
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shared memory bank mapping mode.
|
||||
/// </summary>
|
||||
enum SharedMemoryBankMapping
|
||||
{
|
||||
FourBytesPerBank,
|
||||
EightBytesPerBank
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Denormal behavior of 32-bits float narrowing instructions.
|
||||
/// </summary>
|
||||
enum Fp32NarrowInstruction
|
||||
{
|
||||
KeepDenorms,
|
||||
FlushDenorms
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Configuration of the L1 cache.
|
||||
/// </summary>
|
||||
enum L1Configuration
|
||||
{
|
||||
DirectlyAddressableMemorySize16kb,
|
||||
DirectlyAddressableMemorySize32kb,
|
||||
DirectlyAddressableMemorySize48kb
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reduction operation.
|
||||
/// </summary>
|
||||
enum ReductionOp
|
||||
{
|
||||
RedAdd,
|
||||
RedMin,
|
||||
RedMax,
|
||||
RedInc,
|
||||
RedDec,
|
||||
RedAnd,
|
||||
RedOr,
|
||||
RedXor
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reduction format.
|
||||
/// </summary>
|
||||
enum ReductionFormat
|
||||
{
|
||||
Unsigned32,
|
||||
Signed32
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Size of a structure in words.
|
||||
/// </summary>
|
||||
enum StructureSize
|
||||
{
|
||||
FourWords,
|
||||
OneWord
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute Queue Meta Data.
|
||||
/// </summary>
|
||||
unsafe struct ComputeQmd
|
||||
{
|
||||
private fixed int _words[64];
|
||||
|
||||
public int OuterPut => BitRange(30, 0);
|
||||
public bool OuterOverflow => Bit(31);
|
||||
public int OuterGet => BitRange(62, 32);
|
||||
public bool OuterStickyOverflow => Bit(63);
|
||||
public int InnerGet => BitRange(94, 64);
|
||||
public bool InnerOverflow => Bit(95);
|
||||
public int InnerPut => BitRange(126, 96);
|
||||
public bool InnerStickyOverflow => Bit(127);
|
||||
public int QmdReservedAA => BitRange(159, 128);
|
||||
public int DependentQmdPointer => BitRange(191, 160);
|
||||
public int QmdGroupId => BitRange(197, 192);
|
||||
public bool SmGlobalCachingEnable => Bit(198);
|
||||
public bool RunCtaInOneSmPartition => Bit(199);
|
||||
public bool IsQueue => Bit(200);
|
||||
public bool AddToHeadOfQmdGroupLinkedList => Bit(201);
|
||||
public bool SemaphoreReleaseEnable0 => Bit(202);
|
||||
public bool SemaphoreReleaseEnable1 => Bit(203);
|
||||
public bool RequireSchedulingPcas => Bit(204);
|
||||
public bool DependentQmdScheduleEnable => Bit(205);
|
||||
public DependentQmdType DependentQmdType => (DependentQmdType)BitRange(206, 206);
|
||||
public bool DependentQmdFieldCopy => Bit(207);
|
||||
public int QmdReservedB => BitRange(223, 208);
|
||||
public int CircularQueueSize => BitRange(248, 224);
|
||||
public bool QmdReservedC => Bit(249);
|
||||
public bool InvalidateTextureHeaderCache => Bit(250);
|
||||
public bool InvalidateTextureSamplerCache => Bit(251);
|
||||
public bool InvalidateTextureDataCache => Bit(252);
|
||||
public bool InvalidateShaderDataCache => Bit(253);
|
||||
public bool InvalidateInstructionCache => Bit(254);
|
||||
public bool InvalidateShaderConstantCache => Bit(255);
|
||||
public int ProgramOffset => BitRange(287, 256);
|
||||
public int CircularQueueAddrLower => BitRange(319, 288);
|
||||
public int CircularQueueAddrUpper => BitRange(327, 320);
|
||||
public int QmdReservedD => BitRange(335, 328);
|
||||
public int CircularQueueEntrySize => BitRange(351, 336);
|
||||
public int CwdReferenceCountId => BitRange(357, 352);
|
||||
public int CwdReferenceCountDeltaMinusOne => BitRange(365, 358);
|
||||
public ReleaseMembarType ReleaseMembarType => (ReleaseMembarType)BitRange(366, 366);
|
||||
public bool CwdReferenceCountIncrEnable => Bit(367);
|
||||
public CwdMembarType CwdMembarType => (CwdMembarType)BitRange(369, 368);
|
||||
public bool SequentiallyRunCtas => Bit(370);
|
||||
public bool CwdReferenceCountDecrEnable => Bit(371);
|
||||
public bool Throttled => Bit(372);
|
||||
public Fp32NanBehavior Fp32NanBehavior => (Fp32NanBehavior)BitRange(376, 376);
|
||||
public Fp32F2iNanBehavior Fp32F2iNanBehavior => (Fp32F2iNanBehavior)BitRange(377, 377);
|
||||
public ApiVisibleCallLimit ApiVisibleCallLimit => (ApiVisibleCallLimit)BitRange(378, 378);
|
||||
public SharedMemoryBankMapping SharedMemoryBankMapping => (SharedMemoryBankMapping)BitRange(379, 379);
|
||||
public SamplerIndex SamplerIndex => (SamplerIndex)BitRange(382, 382);
|
||||
public Fp32NarrowInstruction Fp32NarrowInstruction => (Fp32NarrowInstruction)BitRange(383, 383);
|
||||
public int CtaRasterWidth => BitRange(415, 384);
|
||||
public int CtaRasterHeight => BitRange(431, 416);
|
||||
public int CtaRasterDepth => BitRange(447, 432);
|
||||
public int CtaRasterWidthResume => BitRange(479, 448);
|
||||
public int CtaRasterHeightResume => BitRange(495, 480);
|
||||
public int CtaRasterDepthResume => BitRange(511, 496);
|
||||
public int QueueEntriesPerCtaMinusOne => BitRange(518, 512);
|
||||
public int CoalesceWaitingPeriod => BitRange(529, 522);
|
||||
public int SharedMemorySize => BitRange(561, 544);
|
||||
public int QmdReservedG => BitRange(575, 562);
|
||||
public int QmdVersion => BitRange(579, 576);
|
||||
public int QmdMajorVersion => BitRange(583, 580);
|
||||
public int QmdReservedH => BitRange(591, 584);
|
||||
public int CtaThreadDimension0 => BitRange(607, 592);
|
||||
public int CtaThreadDimension1 => BitRange(623, 608);
|
||||
public int CtaThreadDimension2 => BitRange(639, 624);
|
||||
public bool ConstantBufferValid(int i) => Bit(640 + i * 1);
|
||||
public int QmdReservedI => BitRange(668, 648);
|
||||
public L1Configuration L1Configuration => (L1Configuration)BitRange(671, 669);
|
||||
public int SmDisableMaskLower => BitRange(703, 672);
|
||||
public int SmDisableMaskUpper => BitRange(735, 704);
|
||||
public int Release0AddressLower => BitRange(767, 736);
|
||||
public int Release0AddressUpper => BitRange(775, 768);
|
||||
public int QmdReservedJ => BitRange(783, 776);
|
||||
public ReductionOp Release0ReductionOp => (ReductionOp)BitRange(790, 788);
|
||||
public bool QmdReservedK => Bit(791);
|
||||
public ReductionFormat Release0ReductionFormat => (ReductionFormat)BitRange(793, 792);
|
||||
public bool Release0ReductionEnable => Bit(794);
|
||||
public StructureSize Release0StructureSize => (StructureSize)BitRange(799, 799);
|
||||
public int Release0Payload => BitRange(831, 800);
|
||||
public int Release1AddressLower => BitRange(863, 832);
|
||||
public int Release1AddressUpper => BitRange(871, 864);
|
||||
public int QmdReservedL => BitRange(879, 872);
|
||||
public ReductionOp Release1ReductionOp => (ReductionOp)BitRange(886, 884);
|
||||
public bool QmdReservedM => Bit(887);
|
||||
public ReductionFormat Release1ReductionFormat => (ReductionFormat)BitRange(889, 888);
|
||||
public bool Release1ReductionEnable => Bit(890);
|
||||
public StructureSize Release1StructureSize => (StructureSize)BitRange(895, 895);
|
||||
public int Release1Payload => BitRange(927, 896);
|
||||
public int ConstantBufferAddrLower(int i) => BitRange(959 + i * 64, 928 + i * 64);
|
||||
public int ConstantBufferAddrUpper(int i) => BitRange(967 + i * 64, 960 + i * 64);
|
||||
public int ConstantBufferReservedAddr(int i) => BitRange(973 + i * 64, 968 + i * 64);
|
||||
public bool ConstantBufferInvalidate(int i) => Bit(974 + i * 64);
|
||||
public int ConstantBufferSize(int i) => BitRange(991 + i * 64, 975 + i * 64);
|
||||
public int ShaderLocalMemoryLowSize => BitRange(1463, 1440);
|
||||
public int QmdReservedN => BitRange(1466, 1464);
|
||||
public int BarrierCount => BitRange(1471, 1467);
|
||||
public int ShaderLocalMemoryHighSize => BitRange(1495, 1472);
|
||||
public int RegisterCount => BitRange(1503, 1496);
|
||||
public int ShaderLocalMemoryCrsSize => BitRange(1527, 1504);
|
||||
public int SassVersion => BitRange(1535, 1528);
|
||||
public int HwOnlyInnerGet => BitRange(1566, 1536);
|
||||
public bool HwOnlyRequireSchedulingPcas => Bit(1567);
|
||||
public int HwOnlyInnerPut => BitRange(1598, 1568);
|
||||
public bool HwOnlyScgType => Bit(1599);
|
||||
public int HwOnlySpanListHeadIndex => BitRange(1629, 1600);
|
||||
public bool QmdReservedQ => Bit(1630);
|
||||
public bool HwOnlySpanListHeadIndexValid => Bit(1631);
|
||||
public int HwOnlySkedNextQmdPointer => BitRange(1663, 1632);
|
||||
public int QmdSpareE => BitRange(1695, 1664);
|
||||
public int QmdSpareF => BitRange(1727, 1696);
|
||||
public int QmdSpareG => BitRange(1759, 1728);
|
||||
public int QmdSpareH => BitRange(1791, 1760);
|
||||
public int QmdSpareI => BitRange(1823, 1792);
|
||||
public int QmdSpareJ => BitRange(1855, 1824);
|
||||
public int QmdSpareK => BitRange(1887, 1856);
|
||||
public int QmdSpareL => BitRange(1919, 1888);
|
||||
public int QmdSpareM => BitRange(1951, 1920);
|
||||
public int QmdSpareN => BitRange(1983, 1952);
|
||||
public int DebugIdUpper => BitRange(2015, 1984);
|
||||
public int DebugIdLower => BitRange(2047, 2016);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private bool Bit(int bit)
|
||||
{
|
||||
if ((uint)bit >= 64 * 32)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(bit));
|
||||
}
|
||||
|
||||
return (_words[bit >> 5] & (1 << (bit & 31))) != 0;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private int BitRange(int upper, int lower)
|
||||
{
|
||||
if ((uint)lower >= 64 * 32)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(lower));
|
||||
}
|
||||
|
||||
int mask = (int)(uint.MaxValue >> (32 - (upper - lower + 1)));
|
||||
|
||||
return (_words[lower >> 5] >> (lower & 31)) & mask;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
// This file was auto-generated from NVIDIA official Maxwell definitions.
|
||||
|
||||
namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
|
||||
{
|
||||
enum TertOp
|
||||
{
|
||||
Grp0IncMethod = 0,
|
||||
Grp0SetSubDevMask = 1,
|
||||
Grp0StoreSubDevMask = 2,
|
||||
Grp0UseSubDevMask = 3,
|
||||
Grp2NonIncMethod = 0
|
||||
}
|
||||
|
||||
enum SecOp
|
||||
{
|
||||
Grp0UseTert = 0,
|
||||
IncMethod = 1,
|
||||
Grp2UseTert = 2,
|
||||
NonIncMethod = 3,
|
||||
ImmdDataMethod = 4,
|
||||
OneInc = 5,
|
||||
Reserved6 = 6,
|
||||
EndPbSegment = 7
|
||||
}
|
||||
|
||||
struct CompressedMethod
|
||||
{
|
||||
#pragma warning disable CS0649
|
||||
public uint Method;
|
||||
#pragma warning restore CS0649
|
||||
public int MethodAddressOld => (int)((Method >> 2) & 0x7FF);
|
||||
public int MethodAddress => (int)((Method >> 0) & 0xFFF);
|
||||
public int SubdeviceMask => (int)((Method >> 4) & 0xFFF);
|
||||
public int MethodSubchannel => (int)((Method >> 13) & 0x7);
|
||||
public TertOp TertOp => (TertOp)((Method >> 16) & 0x3);
|
||||
public int MethodCountOld => (int)((Method >> 18) & 0x7FF);
|
||||
public int MethodCount => (int)((Method >> 16) & 0x1FFF);
|
||||
public int ImmdData => (int)((Method >> 16) & 0x1FFF);
|
||||
public SecOp SecOp => (SecOp)((Method >> 29) & 0x7);
|
||||
}
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
// This file was auto-generated from NVIDIA official Maxwell definitions.
|
||||
|
||||
namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
|
||||
{
|
||||
enum Entry0Fetch
|
||||
{
|
||||
Unconditional = 0,
|
||||
Conditional = 1,
|
||||
}
|
||||
|
||||
enum Entry1Priv
|
||||
{
|
||||
User = 0,
|
||||
Kernel = 1,
|
||||
}
|
||||
|
||||
enum Entry1Level
|
||||
{
|
||||
Main = 0,
|
||||
Subroutine = 1,
|
||||
}
|
||||
|
||||
enum Entry1Sync
|
||||
{
|
||||
Proceed = 0,
|
||||
Wait = 1,
|
||||
}
|
||||
|
||||
enum Entry1Opcode
|
||||
{
|
||||
Nop = 0,
|
||||
Illegal = 1,
|
||||
Crc = 2,
|
||||
PbCrc = 3,
|
||||
}
|
||||
|
||||
struct GPEntry
|
||||
{
|
||||
#pragma warning disable CS0649
|
||||
public uint Entry0;
|
||||
#pragma warning restore CS0649
|
||||
public Entry0Fetch Entry0Fetch => (Entry0Fetch)((Entry0 >> 0) & 0x1);
|
||||
public int Entry0Get => (int)((Entry0 >> 2) & 0x3FFFFFFF);
|
||||
public int Entry0Operand => (int)(Entry0);
|
||||
#pragma warning disable CS0649
|
||||
public uint Entry1;
|
||||
#pragma warning restore CS0649
|
||||
public int Entry1GetHi => (int)((Entry1 >> 0) & 0xFF);
|
||||
public Entry1Priv Entry1Priv => (Entry1Priv)((Entry1 >> 8) & 0x1);
|
||||
public Entry1Level Entry1Level => (Entry1Level)((Entry1 >> 9) & 0x1);
|
||||
public int Entry1Length => (int)((Entry1 >> 10) & 0x1FFFFF);
|
||||
public Entry1Sync Entry1Sync => (Entry1Sync)((Entry1 >> 31) & 0x1);
|
||||
public Entry1Opcode Entry1Opcode => (Entry1Opcode)((Entry1 >> 0) & 0xFF);
|
||||
}
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
namespace Ryujinx.Graphics.Gpu.Memory
|
||||
{
|
||||
public class UnmapEventArgs
|
||||
{
|
||||
public ulong Address { get; }
|
||||
public ulong Size { get; }
|
||||
|
||||
public UnmapEventArgs(ulong address, ulong size)
|
||||
{
|
||||
Address = address;
|
||||
Size = size;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
using Ryujinx.Graphics.GAL;
|
||||
using Ryujinx.Graphics.Shader;
|
||||
using Ryujinx.Graphics.Shader.Translation;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
||||
{
|
||||
static class ShaderBinarySerializer
|
||||
{
|
||||
public static byte[] Pack(ShaderSource[] sources)
|
||||
{
|
||||
using MemoryStream output = new MemoryStream();
|
||||
using BinaryWriter writer = new BinaryWriter(output);
|
||||
|
||||
writer.Write(sources.Length);
|
||||
|
||||
for (int i = 0; i < sources.Length; i++)
|
||||
{
|
||||
writer.Write((int)sources[i].Stage);
|
||||
writer.Write(sources[i].BinaryCode.Length);
|
||||
writer.Write(sources[i].BinaryCode);
|
||||
}
|
||||
|
||||
return output.ToArray();
|
||||
}
|
||||
|
||||
public static ShaderSource[] Unpack(CachedShaderStage[] stages, byte[] code)
|
||||
{
|
||||
using MemoryStream input = new MemoryStream(code);
|
||||
using BinaryReader reader = new BinaryReader(input);
|
||||
|
||||
List<ShaderSource> output = new List<ShaderSource>();
|
||||
|
||||
int count = reader.ReadInt32();
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
ShaderStage stage = (ShaderStage)reader.ReadInt32();
|
||||
int binaryCodeLength = reader.ReadInt32();
|
||||
byte[] binaryCode = reader.ReadBytes(binaryCodeLength);
|
||||
|
||||
output.Add(new ShaderSource(binaryCode, GetBindings(stages, stage), stage, TargetLanguage.Spirv));
|
||||
}
|
||||
|
||||
return output.ToArray();
|
||||
}
|
||||
|
||||
private static ShaderBindings GetBindings(CachedShaderStage[] stages, ShaderStage stage)
|
||||
{
|
||||
for (int i = 0; i < stages.Length; i++)
|
||||
{
|
||||
CachedShaderStage currentStage = stages[i];
|
||||
|
||||
if (currentStage?.Info != null && currentStage.Info.Stage == stage)
|
||||
{
|
||||
return ShaderCache.GetBindings(currentStage.Info);
|
||||
}
|
||||
}
|
||||
|
||||
return new ShaderBindings(Array.Empty<int>(), Array.Empty<int>(), Array.Empty<int>(), Array.Empty<int>());
|
||||
}
|
||||
}
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
{
|
||||
internal enum PredictionMode
|
||||
{
|
||||
DcPred = 0, // Average of above and left pixels
|
||||
VPred = 1, // Vertical
|
||||
HPred = 2, // Horizontal
|
||||
D45Pred = 3, // Directional 45 deg = round(arctan(1 / 1) * 180 / pi)
|
||||
D135Pred = 4, // Directional 135 deg = 180 - 45
|
||||
D117Pred = 5, // Directional 117 deg = 180 - 63
|
||||
D153Pred = 6, // Directional 153 deg = 180 - 27
|
||||
D207Pred = 7, // Directional 207 deg = 180 + 27
|
||||
D63Pred = 8, // Directional 63 deg = round(arctan(2 / 1) * 180 / pi)
|
||||
TmPred = 9, // True-motion
|
||||
NearestMv = 10,
|
||||
NearMv = 11,
|
||||
ZeroMv = 12,
|
||||
NewMv = 13,
|
||||
MbModeCount = 14
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
{
|
||||
internal enum SegLvlFeatures
|
||||
{
|
||||
SegLvlAltQ = 0, // Use alternate Quantizer ....
|
||||
SegLvlAltLf = 1, // Use alternate loop filter value...
|
||||
SegLvlRefFrame = 2, // Optional Segment reference frame
|
||||
SegLvlSkip = 3, // Optional Segment (0,0) + skip mode
|
||||
SegLvlMax = 4 // Number of features supported
|
||||
}
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
{
|
||||
public enum TxMode
|
||||
{
|
||||
Only4X4 = 0, // Only 4x4 transform used
|
||||
Allow8X8 = 1, // Allow block transform size up to 8x8
|
||||
Allow16X16 = 2, // Allow block transform size up to 16x16
|
||||
Allow32X32 = 3, // Allow block transform size up to 32x32
|
||||
TxModeSelect = 4, // Transform specified for each block
|
||||
TxModes = 5
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
{
|
||||
internal enum TxType
|
||||
{
|
||||
DctDct = 0, // DCT in both horizontal and vertical
|
||||
AdstDct = 1, // ADST in vertical, DCT in horizontal
|
||||
DctAdst = 2, // DCT in vertical, ADST in horizontal
|
||||
AdstAdst = 3, // ADST in both directions
|
||||
TxTypes = 4
|
||||
}
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
using OpenTK.Graphics.OpenGL;
|
||||
|
||||
namespace Ryujinx.Graphics.OpenGL
|
||||
{
|
||||
readonly struct FormatInfo
|
||||
{
|
||||
public int Components { get; }
|
||||
public bool Normalized { get; }
|
||||
public bool Scaled { get; }
|
||||
|
||||
public PixelInternalFormat PixelInternalFormat { get; }
|
||||
public PixelFormat PixelFormat { get; }
|
||||
public PixelType PixelType { get; }
|
||||
|
||||
public bool IsCompressed { get; }
|
||||
|
||||
public FormatInfo(
|
||||
int components,
|
||||
bool normalized,
|
||||
bool scaled,
|
||||
All pixelInternalFormat,
|
||||
PixelFormat pixelFormat,
|
||||
PixelType pixelType)
|
||||
{
|
||||
Components = components;
|
||||
Normalized = normalized;
|
||||
Scaled = scaled;
|
||||
PixelInternalFormat = (PixelInternalFormat)pixelInternalFormat;
|
||||
PixelFormat = pixelFormat;
|
||||
PixelType = pixelType;
|
||||
IsCompressed = false;
|
||||
}
|
||||
|
||||
public FormatInfo(int components, bool normalized, bool scaled, All pixelFormat)
|
||||
{
|
||||
Components = components;
|
||||
Normalized = normalized;
|
||||
Scaled = scaled;
|
||||
PixelInternalFormat = 0;
|
||||
PixelFormat = (PixelFormat)pixelFormat;
|
||||
PixelType = 0;
|
||||
IsCompressed = true;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,140 +0,0 @@
|
||||
using OpenTK.Graphics.OpenGL;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Graphics.OpenGL
|
||||
{
|
||||
static class HwCapabilities
|
||||
{
|
||||
private static readonly Lazy<bool> _supportsAlphaToCoverageDitherControl = new Lazy<bool>(() => HasExtension("GL_NV_alpha_to_coverage_dither_control"));
|
||||
private static readonly Lazy<bool> _supportsAstcCompression = new Lazy<bool>(() => HasExtension("GL_KHR_texture_compression_astc_ldr"));
|
||||
private static readonly Lazy<bool> _supportsBlendEquationAdvanced = new Lazy<bool>(() => HasExtension("GL_NV_blend_equation_advanced"));
|
||||
private static readonly Lazy<bool> _supportsDrawTexture = new Lazy<bool>(() => HasExtension("GL_NV_draw_texture"));
|
||||
private static readonly Lazy<bool> _supportsFragmentShaderInterlock = new Lazy<bool>(() => HasExtension("GL_ARB_fragment_shader_interlock"));
|
||||
private static readonly Lazy<bool> _supportsFragmentShaderOrdering = new Lazy<bool>(() => HasExtension("GL_INTEL_fragment_shader_ordering"));
|
||||
private static readonly Lazy<bool> _supportsGeometryShaderPassthrough = new Lazy<bool>(() => HasExtension("GL_NV_geometry_shader_passthrough"));
|
||||
private static readonly Lazy<bool> _supportsImageLoadFormatted = new Lazy<bool>(() => HasExtension("GL_EXT_shader_image_load_formatted"));
|
||||
private static readonly Lazy<bool> _supportsIndirectParameters = new Lazy<bool>(() => HasExtension("GL_ARB_indirect_parameters"));
|
||||
private static readonly Lazy<bool> _supportsParallelShaderCompile = new Lazy<bool>(() => HasExtension("GL_ARB_parallel_shader_compile"));
|
||||
private static readonly Lazy<bool> _supportsPolygonOffsetClamp = new Lazy<bool>(() => HasExtension("GL_EXT_polygon_offset_clamp"));
|
||||
private static readonly Lazy<bool> _supportsQuads = new Lazy<bool>(SupportsQuadsCheck);
|
||||
private static readonly Lazy<bool> _supportsSeamlessCubemapPerTexture = new Lazy<bool>(() => HasExtension("GL_ARB_seamless_cubemap_per_texture"));
|
||||
private static readonly Lazy<bool> _supportsShaderBallot = new Lazy<bool>(() => HasExtension("GL_ARB_shader_ballot"));
|
||||
private static readonly Lazy<bool> _supportsShaderViewportLayerArray = new Lazy<bool>(() => HasExtension("GL_ARB_shader_viewport_layer_array"));
|
||||
private static readonly Lazy<bool> _supportsTextureCompressionBptc = new Lazy<bool>(() => HasExtension("GL_EXT_texture_compression_bptc"));
|
||||
private static readonly Lazy<bool> _supportsTextureCompressionRgtc = new Lazy<bool>(() => HasExtension("GL_EXT_texture_compression_rgtc"));
|
||||
private static readonly Lazy<bool> _supportsTextureCompressionS3tc = new Lazy<bool>(() => HasExtension("GL_EXT_texture_compression_s3tc"));
|
||||
private static readonly Lazy<bool> _supportsTextureShadowLod = new Lazy<bool>(() => HasExtension("GL_EXT_texture_shadow_lod"));
|
||||
private static readonly Lazy<bool> _supportsViewportSwizzle = new Lazy<bool>(() => HasExtension("GL_NV_viewport_swizzle"));
|
||||
|
||||
private static readonly Lazy<int> _maximumComputeSharedMemorySize = new Lazy<int>(() => GetLimit(All.MaxComputeSharedMemorySize));
|
||||
private static readonly Lazy<int> _storageBufferOffsetAlignment = new Lazy<int>(() => GetLimit(All.ShaderStorageBufferOffsetAlignment));
|
||||
|
||||
public enum GpuVendor
|
||||
{
|
||||
Unknown,
|
||||
AmdWindows,
|
||||
AmdUnix,
|
||||
IntelWindows,
|
||||
IntelUnix,
|
||||
Nvidia
|
||||
}
|
||||
|
||||
private static readonly Lazy<GpuVendor> _gpuVendor = new Lazy<GpuVendor>(GetGpuVendor);
|
||||
|
||||
private static bool _isAMD => _gpuVendor.Value == GpuVendor.AmdWindows || _gpuVendor.Value == GpuVendor.AmdUnix;
|
||||
private static bool _isIntel => _gpuVendor.Value == GpuVendor.IntelWindows || _gpuVendor.Value == GpuVendor.IntelUnix;
|
||||
|
||||
public static GpuVendor Vendor => _gpuVendor.Value;
|
||||
|
||||
private static Lazy<float> _maxSupportedAnisotropy = new Lazy<float>(GL.GetFloat((GetPName)All.MaxTextureMaxAnisotropy));
|
||||
|
||||
public static bool UsePersistentBufferForFlush => _gpuVendor.Value == GpuVendor.AmdWindows || _gpuVendor.Value == GpuVendor.Nvidia;
|
||||
|
||||
public static bool SupportsAlphaToCoverageDitherControl => _supportsAlphaToCoverageDitherControl.Value;
|
||||
public static bool SupportsAstcCompression => _supportsAstcCompression.Value;
|
||||
public static bool SupportsBlendEquationAdvanced => _supportsBlendEquationAdvanced.Value;
|
||||
public static bool SupportsDrawTexture => _supportsDrawTexture.Value;
|
||||
public static bool SupportsFragmentShaderInterlock => _supportsFragmentShaderInterlock.Value;
|
||||
public static bool SupportsFragmentShaderOrdering => _supportsFragmentShaderOrdering.Value;
|
||||
public static bool SupportsGeometryShaderPassthrough => _supportsGeometryShaderPassthrough.Value;
|
||||
public static bool SupportsImageLoadFormatted => _supportsImageLoadFormatted.Value;
|
||||
public static bool SupportsIndirectParameters => _supportsIndirectParameters.Value;
|
||||
public static bool SupportsParallelShaderCompile => _supportsParallelShaderCompile.Value;
|
||||
public static bool SupportsPolygonOffsetClamp => _supportsPolygonOffsetClamp.Value;
|
||||
public static bool SupportsQuads => _supportsQuads.Value;
|
||||
public static bool SupportsSeamlessCubemapPerTexture => _supportsSeamlessCubemapPerTexture.Value;
|
||||
public static bool SupportsShaderBallot => _supportsShaderBallot.Value;
|
||||
public static bool SupportsShaderViewportLayerArray => _supportsShaderViewportLayerArray.Value;
|
||||
public static bool SupportsTextureCompressionBptc => _supportsTextureCompressionBptc.Value;
|
||||
public static bool SupportsTextureCompressionRgtc => _supportsTextureCompressionRgtc.Value;
|
||||
public static bool SupportsTextureCompressionS3tc => _supportsTextureCompressionS3tc.Value;
|
||||
public static bool SupportsTextureShadowLod => _supportsTextureShadowLod.Value;
|
||||
public static bool SupportsViewportSwizzle => _supportsViewportSwizzle.Value;
|
||||
|
||||
public static bool SupportsMismatchingViewFormat => _gpuVendor.Value != GpuVendor.AmdWindows && _gpuVendor.Value != GpuVendor.IntelWindows;
|
||||
public static bool SupportsNonConstantTextureOffset => _gpuVendor.Value == GpuVendor.Nvidia;
|
||||
public static bool RequiresSyncFlush => _gpuVendor.Value == GpuVendor.AmdWindows || _isIntel;
|
||||
|
||||
public static int MaximumComputeSharedMemorySize => _maximumComputeSharedMemorySize.Value;
|
||||
public static int StorageBufferOffsetAlignment => _storageBufferOffsetAlignment.Value;
|
||||
|
||||
public static float MaximumSupportedAnisotropy => _maxSupportedAnisotropy.Value;
|
||||
|
||||
private static bool HasExtension(string name)
|
||||
{
|
||||
int numExtensions = GL.GetInteger(GetPName.NumExtensions);
|
||||
|
||||
for (int extension = 0; extension < numExtensions; extension++)
|
||||
{
|
||||
if (GL.GetString(StringNameIndexed.Extensions, extension) == name)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static int GetLimit(All name)
|
||||
{
|
||||
return GL.GetInteger((GetPName)name);
|
||||
}
|
||||
|
||||
private static GpuVendor GetGpuVendor()
|
||||
{
|
||||
string vendor = GL.GetString(StringName.Vendor).ToLower();
|
||||
|
||||
if (vendor == "nvidia corporation")
|
||||
{
|
||||
return GpuVendor.Nvidia;
|
||||
}
|
||||
else if (vendor == "intel")
|
||||
{
|
||||
string renderer = GL.GetString(StringName.Renderer).ToLower();
|
||||
|
||||
return renderer.Contains("mesa") ? GpuVendor.IntelUnix : GpuVendor.IntelWindows;
|
||||
}
|
||||
else if (vendor == "ati technologies inc." || vendor == "advanced micro devices, inc.")
|
||||
{
|
||||
return GpuVendor.AmdWindows;
|
||||
}
|
||||
else if (vendor == "amd" || vendor == "x.org")
|
||||
{
|
||||
return GpuVendor.AmdUnix;
|
||||
}
|
||||
else
|
||||
{
|
||||
return GpuVendor.Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool SupportsQuadsCheck()
|
||||
{
|
||||
GL.GetError(); // Clear any existing error.
|
||||
GL.Begin(PrimitiveType.Quads);
|
||||
GL.End();
|
||||
|
||||
return GL.GetError() == ErrorCode.NoError;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
using Ryujinx.Graphics.Shader.Translation;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Graphics.Shader
|
||||
{
|
||||
public enum AttributeType : byte
|
||||
{
|
||||
// Generic types.
|
||||
Float,
|
||||
Sint,
|
||||
Uint
|
||||
}
|
||||
|
||||
static class AttributeTypeExtensions
|
||||
{
|
||||
public static string ToVec4Type(this AttributeType type)
|
||||
{
|
||||
return type switch
|
||||
{
|
||||
AttributeType.Float => "vec4",
|
||||
AttributeType.Sint => "ivec4",
|
||||
AttributeType.Uint => "uvec4",
|
||||
_ => throw new ArgumentException($"Invalid attribute type \"{type}\".")
|
||||
};
|
||||
}
|
||||
|
||||
public static AggregateType ToAggregateType(this AttributeType type)
|
||||
{
|
||||
return type switch
|
||||
{
|
||||
AttributeType.Float => AggregateType.FP32,
|
||||
AttributeType.Sint => AggregateType.S32,
|
||||
AttributeType.Uint => AggregateType.U32,
|
||||
_ => throw new ArgumentException($"Invalid attribute type \"{type}\".")
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
namespace Ryujinx.Graphics.Shader
|
||||
{
|
||||
public struct BufferDescriptor
|
||||
{
|
||||
// New fields should be added to the end of the struct to keep disk shader cache compatibility.
|
||||
|
||||
public readonly int Binding;
|
||||
public readonly int Slot;
|
||||
public BufferUsageFlags Flags;
|
||||
|
||||
public BufferDescriptor(int binding, int slot)
|
||||
{
|
||||
Binding = binding;
|
||||
Slot = slot;
|
||||
|
||||
Flags = BufferUsageFlags.None;
|
||||
}
|
||||
|
||||
public BufferDescriptor SetFlag(BufferUsageFlags flag)
|
||||
{
|
||||
Flags |= flag;
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,765 +0,0 @@
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Graphics.Shader.StructuredIr;
|
||||
using Ryujinx.Graphics.Shader.Translation;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
{
|
||||
static class Declarations
|
||||
{
|
||||
public static void Declare(CodeGenContext context, StructuredProgramInfo info)
|
||||
{
|
||||
context.AppendLine(context.Config.Options.TargetApi == TargetApi.Vulkan ? "#version 460 core" : "#version 450 core");
|
||||
context.AppendLine("#extension GL_ARB_gpu_shader_int64 : enable");
|
||||
|
||||
if (context.Config.GpuAccessor.QueryHostSupportsShaderBallot())
|
||||
{
|
||||
context.AppendLine("#extension GL_ARB_shader_ballot : enable");
|
||||
}
|
||||
else
|
||||
{
|
||||
context.AppendLine("#extension GL_KHR_shader_subgroup_basic : enable");
|
||||
context.AppendLine("#extension GL_KHR_shader_subgroup_ballot : enable");
|
||||
}
|
||||
|
||||
context.AppendLine("#extension GL_ARB_shader_group_vote : enable");
|
||||
context.AppendLine("#extension GL_EXT_shader_image_load_formatted : enable");
|
||||
context.AppendLine("#extension GL_EXT_texture_shadow_lod : enable");
|
||||
|
||||
if (context.Config.Stage == ShaderStage.Compute)
|
||||
{
|
||||
context.AppendLine("#extension GL_ARB_compute_shader : enable");
|
||||
}
|
||||
else if (context.Config.Stage == ShaderStage.Fragment)
|
||||
{
|
||||
if (context.Config.GpuAccessor.QueryHostSupportsFragmentShaderInterlock())
|
||||
{
|
||||
context.AppendLine("#extension GL_ARB_fragment_shader_interlock : enable");
|
||||
}
|
||||
else if (context.Config.GpuAccessor.QueryHostSupportsFragmentShaderOrderingIntel())
|
||||
{
|
||||
context.AppendLine("#extension GL_INTEL_fragment_shader_ordering : enable");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (context.Config.Stage == ShaderStage.Vertex)
|
||||
{
|
||||
context.AppendLine("#extension GL_ARB_shader_draw_parameters : enable");
|
||||
}
|
||||
|
||||
context.AppendLine("#extension GL_ARB_shader_viewport_layer_array : enable");
|
||||
}
|
||||
|
||||
if (context.Config.GpPassthrough && context.Config.GpuAccessor.QueryHostSupportsGeometryShaderPassthrough())
|
||||
{
|
||||
context.AppendLine("#extension GL_NV_geometry_shader_passthrough : enable");
|
||||
}
|
||||
|
||||
context.AppendLine("#pragma optionNV(fastmath off)");
|
||||
context.AppendLine();
|
||||
|
||||
context.AppendLine($"const int {DefaultNames.UndefinedName} = 0;");
|
||||
context.AppendLine();
|
||||
|
||||
if (context.Config.Stage == ShaderStage.Compute)
|
||||
{
|
||||
int localMemorySize = BitUtils.DivRoundUp(context.Config.GpuAccessor.QueryComputeLocalMemorySize(), 4);
|
||||
|
||||
if (localMemorySize != 0)
|
||||
{
|
||||
string localMemorySizeStr = NumberFormatter.FormatInt(localMemorySize);
|
||||
|
||||
context.AppendLine($"uint {DefaultNames.LocalMemoryName}[{localMemorySizeStr}];");
|
||||
context.AppendLine();
|
||||
}
|
||||
|
||||
int sharedMemorySize = BitUtils.DivRoundUp(context.Config.GpuAccessor.QueryComputeSharedMemorySize(), 4);
|
||||
|
||||
if (sharedMemorySize != 0)
|
||||
{
|
||||
string sharedMemorySizeStr = NumberFormatter.FormatInt(sharedMemorySize);
|
||||
|
||||
context.AppendLine($"shared uint {DefaultNames.SharedMemoryName}[{sharedMemorySizeStr}];");
|
||||
context.AppendLine();
|
||||
}
|
||||
}
|
||||
else if (context.Config.LocalMemorySize != 0)
|
||||
{
|
||||
int localMemorySize = BitUtils.DivRoundUp(context.Config.LocalMemorySize, 4);
|
||||
|
||||
string localMemorySizeStr = NumberFormatter.FormatInt(localMemorySize);
|
||||
|
||||
context.AppendLine($"uint {DefaultNames.LocalMemoryName}[{localMemorySizeStr}];");
|
||||
context.AppendLine();
|
||||
}
|
||||
|
||||
var cBufferDescriptors = context.Config.GetConstantBufferDescriptors();
|
||||
if (cBufferDescriptors.Length != 0)
|
||||
{
|
||||
DeclareUniforms(context, cBufferDescriptors);
|
||||
|
||||
context.AppendLine();
|
||||
}
|
||||
|
||||
var sBufferDescriptors = context.Config.GetStorageBufferDescriptors();
|
||||
if (sBufferDescriptors.Length != 0)
|
||||
{
|
||||
DeclareStorages(context, sBufferDescriptors);
|
||||
|
||||
context.AppendLine();
|
||||
}
|
||||
|
||||
var textureDescriptors = context.Config.GetTextureDescriptors();
|
||||
if (textureDescriptors.Length != 0)
|
||||
{
|
||||
DeclareSamplers(context, textureDescriptors);
|
||||
|
||||
context.AppendLine();
|
||||
}
|
||||
|
||||
var imageDescriptors = context.Config.GetImageDescriptors();
|
||||
if (imageDescriptors.Length != 0)
|
||||
{
|
||||
DeclareImages(context, imageDescriptors);
|
||||
|
||||
context.AppendLine();
|
||||
}
|
||||
|
||||
if (context.Config.Stage != ShaderStage.Compute)
|
||||
{
|
||||
if (context.Config.Stage == ShaderStage.Geometry)
|
||||
{
|
||||
InputTopology inputTopology = context.Config.GpuAccessor.QueryPrimitiveTopology();
|
||||
string inPrimitive = inputTopology.ToGlslString();
|
||||
|
||||
context.AppendLine($"layout (invocations = {context.Config.ThreadsPerInputPrimitive}, {inPrimitive}) in;");
|
||||
|
||||
if (context.Config.GpPassthrough && context.Config.GpuAccessor.QueryHostSupportsGeometryShaderPassthrough())
|
||||
{
|
||||
context.AppendLine($"layout (passthrough) in gl_PerVertex");
|
||||
context.EnterScope();
|
||||
context.AppendLine("vec4 gl_Position;");
|
||||
context.AppendLine("float gl_PointSize;");
|
||||
context.AppendLine("float gl_ClipDistance[];");
|
||||
context.LeaveScope(";");
|
||||
}
|
||||
else
|
||||
{
|
||||
string outPrimitive = context.Config.OutputTopology.ToGlslString();
|
||||
|
||||
int maxOutputVertices = context.Config.GpPassthrough
|
||||
? inputTopology.ToInputVertices()
|
||||
: context.Config.MaxOutputVertices;
|
||||
|
||||
context.AppendLine($"layout ({outPrimitive}, max_vertices = {maxOutputVertices}) out;");
|
||||
}
|
||||
|
||||
context.AppendLine();
|
||||
}
|
||||
else if (context.Config.Stage == ShaderStage.TessellationControl)
|
||||
{
|
||||
int threadsPerInputPrimitive = context.Config.ThreadsPerInputPrimitive;
|
||||
|
||||
context.AppendLine($"layout (vertices = {threadsPerInputPrimitive}) out;");
|
||||
context.AppendLine();
|
||||
}
|
||||
else if (context.Config.Stage == ShaderStage.TessellationEvaluation)
|
||||
{
|
||||
bool tessCw = context.Config.GpuAccessor.QueryTessCw();
|
||||
|
||||
if (context.Config.Options.TargetApi == TargetApi.Vulkan)
|
||||
{
|
||||
// We invert the front face on Vulkan backend, so we need to do that here aswell.
|
||||
tessCw = !tessCw;
|
||||
}
|
||||
|
||||
string patchType = context.Config.GpuAccessor.QueryTessPatchType().ToGlsl();
|
||||
string spacing = context.Config.GpuAccessor.QueryTessSpacing().ToGlsl();
|
||||
string windingOrder = tessCw ? "cw" : "ccw";
|
||||
|
||||
context.AppendLine($"layout ({patchType}, {spacing}, {windingOrder}) in;");
|
||||
context.AppendLine();
|
||||
}
|
||||
|
||||
if (context.Config.UsedInputAttributes != 0 || context.Config.GpPassthrough)
|
||||
{
|
||||
DeclareInputAttributes(context, info);
|
||||
|
||||
context.AppendLine();
|
||||
}
|
||||
|
||||
if (context.Config.UsedOutputAttributes != 0 || context.Config.Stage != ShaderStage.Fragment)
|
||||
{
|
||||
DeclareOutputAttributes(context, info);
|
||||
|
||||
context.AppendLine();
|
||||
}
|
||||
|
||||
if (context.Config.UsedInputAttributesPerPatch.Count != 0)
|
||||
{
|
||||
DeclareInputAttributesPerPatch(context, context.Config.UsedInputAttributesPerPatch);
|
||||
|
||||
context.AppendLine();
|
||||
}
|
||||
|
||||
if (context.Config.UsedOutputAttributesPerPatch.Count != 0)
|
||||
{
|
||||
DeclareUsedOutputAttributesPerPatch(context, context.Config.UsedOutputAttributesPerPatch);
|
||||
|
||||
context.AppendLine();
|
||||
}
|
||||
|
||||
if (context.Config.TransformFeedbackEnabled && context.Config.LastInVertexPipeline)
|
||||
{
|
||||
var tfOutput = context.Info.GetTransformFeedbackOutput(AttributeConsts.PositionX);
|
||||
if (tfOutput.Valid)
|
||||
{
|
||||
context.AppendLine($"layout (xfb_buffer = {tfOutput.Buffer}, xfb_offset = {tfOutput.Offset}, xfb_stride = {tfOutput.Stride}) out gl_PerVertex");
|
||||
context.EnterScope();
|
||||
context.AppendLine("vec4 gl_Position;");
|
||||
context.LeaveScope(context.Config.Stage == ShaderStage.TessellationControl ? " gl_out[];" : ";");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string localSizeX = NumberFormatter.FormatInt(context.Config.GpuAccessor.QueryComputeLocalSizeX());
|
||||
string localSizeY = NumberFormatter.FormatInt(context.Config.GpuAccessor.QueryComputeLocalSizeY());
|
||||
string localSizeZ = NumberFormatter.FormatInt(context.Config.GpuAccessor.QueryComputeLocalSizeZ());
|
||||
|
||||
context.AppendLine(
|
||||
"layout (" +
|
||||
$"local_size_x = {localSizeX}, " +
|
||||
$"local_size_y = {localSizeY}, " +
|
||||
$"local_size_z = {localSizeZ}) in;");
|
||||
context.AppendLine();
|
||||
}
|
||||
|
||||
bool isFragment = context.Config.Stage == ShaderStage.Fragment;
|
||||
|
||||
if (isFragment || context.Config.Stage == ShaderStage.Compute || context.Config.Stage == ShaderStage.Vertex)
|
||||
{
|
||||
if (isFragment && context.Config.GpuAccessor.QueryEarlyZForce())
|
||||
{
|
||||
context.AppendLine("layout(early_fragment_tests) in;");
|
||||
context.AppendLine();
|
||||
}
|
||||
|
||||
if ((context.Config.UsedFeatures & (FeatureFlags.FragCoordXY | FeatureFlags.IntegerSampling)) != 0)
|
||||
{
|
||||
string stage = OperandManager.GetShaderStagePrefix(context.Config.Stage);
|
||||
|
||||
int scaleElements = context.Config.GetTextureDescriptors().Length + context.Config.GetImageDescriptors().Length;
|
||||
|
||||
if (isFragment)
|
||||
{
|
||||
scaleElements++; // Also includes render target scale, for gl_FragCoord.
|
||||
}
|
||||
|
||||
DeclareSupportUniformBlock(context, context.Config.Stage, scaleElements);
|
||||
|
||||
if (context.Config.UsedFeatures.HasFlag(FeatureFlags.IntegerSampling) && scaleElements != 0)
|
||||
{
|
||||
AppendHelperFunction(context, $"Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/TexelFetchScale_{stage}.glsl");
|
||||
context.AppendLine();
|
||||
}
|
||||
}
|
||||
else if (isFragment || context.Config.Stage == ShaderStage.Vertex)
|
||||
{
|
||||
DeclareSupportUniformBlock(context, context.Config.Stage, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if ((info.HelperFunctionsMask & HelperFunctionsMask.AtomicMinMaxS32Shared) != 0)
|
||||
{
|
||||
AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/AtomicMinMaxS32Shared.glsl");
|
||||
}
|
||||
|
||||
if ((info.HelperFunctionsMask & HelperFunctionsMask.AtomicMinMaxS32Storage) != 0)
|
||||
{
|
||||
AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/AtomicMinMaxS32Storage.glsl");
|
||||
}
|
||||
|
||||
if ((info.HelperFunctionsMask & HelperFunctionsMask.MultiplyHighS32) != 0)
|
||||
{
|
||||
AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/MultiplyHighS32.glsl");
|
||||
}
|
||||
|
||||
if ((info.HelperFunctionsMask & HelperFunctionsMask.MultiplyHighU32) != 0)
|
||||
{
|
||||
AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/MultiplyHighU32.glsl");
|
||||
}
|
||||
|
||||
if ((info.HelperFunctionsMask & HelperFunctionsMask.Shuffle) != 0)
|
||||
{
|
||||
AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/Shuffle.glsl");
|
||||
}
|
||||
|
||||
if ((info.HelperFunctionsMask & HelperFunctionsMask.ShuffleDown) != 0)
|
||||
{
|
||||
AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/ShuffleDown.glsl");
|
||||
}
|
||||
|
||||
if ((info.HelperFunctionsMask & HelperFunctionsMask.ShuffleUp) != 0)
|
||||
{
|
||||
AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/ShuffleUp.glsl");
|
||||
}
|
||||
|
||||
if ((info.HelperFunctionsMask & HelperFunctionsMask.ShuffleXor) != 0)
|
||||
{
|
||||
AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/ShuffleXor.glsl");
|
||||
}
|
||||
|
||||
if ((info.HelperFunctionsMask & HelperFunctionsMask.StoreSharedSmallInt) != 0)
|
||||
{
|
||||
AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/StoreSharedSmallInt.glsl");
|
||||
}
|
||||
|
||||
if ((info.HelperFunctionsMask & HelperFunctionsMask.StoreStorageSmallInt) != 0)
|
||||
{
|
||||
AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/StoreStorageSmallInt.glsl");
|
||||
}
|
||||
|
||||
if ((info.HelperFunctionsMask & HelperFunctionsMask.SwizzleAdd) != 0)
|
||||
{
|
||||
AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/SwizzleAdd.glsl");
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetTfLayout(TransformFeedbackOutput tfOutput)
|
||||
{
|
||||
if (tfOutput.Valid)
|
||||
{
|
||||
return $"layout (xfb_buffer = {tfOutput.Buffer}, xfb_offset = {tfOutput.Offset}, xfb_stride = {tfOutput.Stride}) ";
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
public static void DeclareLocals(CodeGenContext context, StructuredFunction function)
|
||||
{
|
||||
foreach (AstOperand decl in function.Locals)
|
||||
{
|
||||
string name = context.OperandManager.DeclareLocal(decl);
|
||||
|
||||
context.AppendLine(GetVarTypeName(context, decl.VarType) + " " + name + ";");
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetVarTypeName(CodeGenContext context, AggregateType type, bool precise = true)
|
||||
{
|
||||
if (context.Config.GpuAccessor.QueryHostReducedPrecision())
|
||||
{
|
||||
precise = false;
|
||||
}
|
||||
|
||||
return type switch
|
||||
{
|
||||
AggregateType.Void => "void",
|
||||
AggregateType.Bool => "bool",
|
||||
AggregateType.FP32 => precise ? "precise float" : "float",
|
||||
AggregateType.FP64 => "double",
|
||||
AggregateType.S32 => "int",
|
||||
AggregateType.U32 => "uint",
|
||||
AggregateType.Vector2 | AggregateType.Bool => "bvec2",
|
||||
AggregateType.Vector2 | AggregateType.FP32 => precise ? "precise vec2" : "vec2",
|
||||
AggregateType.Vector2 | AggregateType.FP64 => "dvec2",
|
||||
AggregateType.Vector2 | AggregateType.S32 => "ivec2",
|
||||
AggregateType.Vector2 | AggregateType.U32 => "uvec2",
|
||||
AggregateType.Vector3 | AggregateType.Bool => "bvec3",
|
||||
AggregateType.Vector3 | AggregateType.FP32 => precise ? "precise vec3" : "vec3",
|
||||
AggregateType.Vector3 | AggregateType.FP64 => "dvec3",
|
||||
AggregateType.Vector3 | AggregateType.S32 => "ivec3",
|
||||
AggregateType.Vector3 | AggregateType.U32 => "uvec3",
|
||||
AggregateType.Vector4 | AggregateType.Bool => "bvec4",
|
||||
AggregateType.Vector4 | AggregateType.FP32 => precise ? "precise vec4" : "vec4",
|
||||
AggregateType.Vector4 | AggregateType.FP64 => "dvec4",
|
||||
AggregateType.Vector4 | AggregateType.S32 => "ivec4",
|
||||
AggregateType.Vector4 | AggregateType.U32 => "uvec4",
|
||||
_ => throw new ArgumentException($"Invalid variable type \"{type}\".")
|
||||
};
|
||||
}
|
||||
|
||||
private static void DeclareUniforms(CodeGenContext context, BufferDescriptor[] descriptors)
|
||||
{
|
||||
string ubSize = "[" + NumberFormatter.FormatInt(Constants.ConstantBufferSize / 16) + "]";
|
||||
|
||||
if (context.Config.UsedFeatures.HasFlag(FeatureFlags.CbIndexing))
|
||||
{
|
||||
string ubName = OperandManager.GetShaderStagePrefix(context.Config.Stage);
|
||||
|
||||
ubName += "_" + DefaultNames.UniformNamePrefix;
|
||||
|
||||
string blockName = $"{ubName}_{DefaultNames.BlockSuffix}";
|
||||
|
||||
context.AppendLine($"layout (binding = {context.Config.FirstConstantBufferBinding}, std140) uniform {blockName}");
|
||||
context.EnterScope();
|
||||
context.AppendLine("vec4 " + DefaultNames.DataName + ubSize + ";");
|
||||
context.LeaveScope($" {ubName}[{NumberFormatter.FormatInt(descriptors.Max(x => x.Slot) + 1)}];");
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var descriptor in descriptors)
|
||||
{
|
||||
string ubName = OperandManager.GetShaderStagePrefix(context.Config.Stage);
|
||||
|
||||
ubName += "_" + DefaultNames.UniformNamePrefix + descriptor.Slot;
|
||||
|
||||
context.AppendLine($"layout (binding = {descriptor.Binding}, std140) uniform {ubName}");
|
||||
context.EnterScope();
|
||||
context.AppendLine("vec4 " + OperandManager.GetUbName(context.Config.Stage, descriptor.Slot, false) + ubSize + ";");
|
||||
context.LeaveScope(";");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void DeclareStorages(CodeGenContext context, BufferDescriptor[] descriptors)
|
||||
{
|
||||
string sbName = OperandManager.GetShaderStagePrefix(context.Config.Stage);
|
||||
|
||||
sbName += "_" + DefaultNames.StorageNamePrefix;
|
||||
|
||||
string blockName = $"{sbName}_{DefaultNames.BlockSuffix}";
|
||||
|
||||
string layout = context.Config.Options.TargetApi == TargetApi.Vulkan ? ", set = 1" : string.Empty;
|
||||
|
||||
context.AppendLine($"layout (binding = {context.Config.FirstStorageBufferBinding}{layout}, std430) buffer {blockName}");
|
||||
context.EnterScope();
|
||||
context.AppendLine("uint " + DefaultNames.DataName + "[];");
|
||||
context.LeaveScope($" {sbName}[{NumberFormatter.FormatInt(descriptors.Max(x => x.Slot) + 1)}];");
|
||||
}
|
||||
|
||||
private static void DeclareSamplers(CodeGenContext context, TextureDescriptor[] descriptors)
|
||||
{
|
||||
int arraySize = 0;
|
||||
foreach (var descriptor in descriptors)
|
||||
{
|
||||
if (descriptor.Type.HasFlag(SamplerType.Indexed))
|
||||
{
|
||||
if (arraySize == 0)
|
||||
{
|
||||
arraySize = ShaderConfig.SamplerArraySize;
|
||||
}
|
||||
else if (--arraySize != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
string indexExpr = NumberFormatter.FormatInt(arraySize);
|
||||
|
||||
string samplerName = OperandManager.GetSamplerName(
|
||||
context.Config.Stage,
|
||||
descriptor.CbufSlot,
|
||||
descriptor.HandleIndex,
|
||||
descriptor.Type.HasFlag(SamplerType.Indexed),
|
||||
indexExpr);
|
||||
|
||||
string samplerTypeName = descriptor.Type.ToGlslSamplerType();
|
||||
|
||||
string layout = string.Empty;
|
||||
|
||||
if (context.Config.Options.TargetApi == TargetApi.Vulkan)
|
||||
{
|
||||
layout = ", set = 2";
|
||||
}
|
||||
|
||||
context.AppendLine($"layout (binding = {descriptor.Binding}{layout}) uniform {samplerTypeName} {samplerName};");
|
||||
}
|
||||
}
|
||||
|
||||
private static void DeclareImages(CodeGenContext context, TextureDescriptor[] descriptors)
|
||||
{
|
||||
int arraySize = 0;
|
||||
foreach (var descriptor in descriptors)
|
||||
{
|
||||
if (descriptor.Type.HasFlag(SamplerType.Indexed))
|
||||
{
|
||||
if (arraySize == 0)
|
||||
{
|
||||
arraySize = ShaderConfig.SamplerArraySize;
|
||||
}
|
||||
else if (--arraySize != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
string indexExpr = NumberFormatter.FormatInt(arraySize);
|
||||
|
||||
string imageName = OperandManager.GetImageName(
|
||||
context.Config.Stage,
|
||||
descriptor.CbufSlot,
|
||||
descriptor.HandleIndex,
|
||||
descriptor.Format,
|
||||
descriptor.Type.HasFlag(SamplerType.Indexed),
|
||||
indexExpr);
|
||||
|
||||
string imageTypeName = descriptor.Type.ToGlslImageType(descriptor.Format.GetComponentType());
|
||||
|
||||
if (descriptor.Flags.HasFlag(TextureUsageFlags.ImageCoherent))
|
||||
{
|
||||
imageTypeName = "coherent " + imageTypeName;
|
||||
}
|
||||
|
||||
string layout = descriptor.Format.ToGlslFormat();
|
||||
|
||||
if (!string.IsNullOrEmpty(layout))
|
||||
{
|
||||
layout = ", " + layout;
|
||||
}
|
||||
|
||||
if (context.Config.Options.TargetApi == TargetApi.Vulkan)
|
||||
{
|
||||
layout = $", set = 3{layout}";
|
||||
}
|
||||
|
||||
context.AppendLine($"layout (binding = {descriptor.Binding}{layout}) uniform {imageTypeName} {imageName};");
|
||||
}
|
||||
}
|
||||
|
||||
private static void DeclareInputAttributes(CodeGenContext context, StructuredProgramInfo info)
|
||||
{
|
||||
if (context.Config.UsedFeatures.HasFlag(FeatureFlags.IaIndexing))
|
||||
{
|
||||
string suffix = context.Config.Stage == ShaderStage.Geometry ? "[]" : string.Empty;
|
||||
|
||||
context.AppendLine($"layout (location = 0) in vec4 {DefaultNames.IAttributePrefix}{suffix}[{Constants.MaxAttributes}];");
|
||||
}
|
||||
else
|
||||
{
|
||||
int usedAttributes = context.Config.UsedInputAttributes | context.Config.PassthroughAttributes;
|
||||
while (usedAttributes != 0)
|
||||
{
|
||||
int index = BitOperations.TrailingZeroCount(usedAttributes);
|
||||
DeclareInputAttribute(context, info, index);
|
||||
usedAttributes &= ~(1 << index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void DeclareInputAttributesPerPatch(CodeGenContext context, HashSet<int> attrs)
|
||||
{
|
||||
foreach (int attr in attrs.Order())
|
||||
{
|
||||
DeclareInputAttributePerPatch(context, attr);
|
||||
}
|
||||
}
|
||||
|
||||
private static void DeclareInputAttribute(CodeGenContext context, StructuredProgramInfo info, int attr)
|
||||
{
|
||||
string suffix = AttributeInfo.IsArrayAttributeGlsl(context.Config.Stage, isOutAttr: false) ? "[]" : string.Empty;
|
||||
string iq = string.Empty;
|
||||
|
||||
if (context.Config.Stage == ShaderStage.Fragment)
|
||||
{
|
||||
iq = context.Config.ImapTypes[attr].GetFirstUsedType() switch
|
||||
{
|
||||
PixelImap.Constant => "flat ",
|
||||
PixelImap.ScreenLinear => "noperspective ",
|
||||
_ => string.Empty
|
||||
};
|
||||
}
|
||||
|
||||
string name = $"{DefaultNames.IAttributePrefix}{attr}";
|
||||
|
||||
if (context.Config.TransformFeedbackEnabled && context.Config.Stage == ShaderStage.Fragment)
|
||||
{
|
||||
for (int c = 0; c < 4; c++)
|
||||
{
|
||||
char swzMask = "xyzw"[c];
|
||||
|
||||
context.AppendLine($"layout (location = {attr}, component = {c}) {iq}in float {name}_{swzMask}{suffix};");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bool passthrough = (context.Config.PassthroughAttributes & (1 << attr)) != 0;
|
||||
string pass = passthrough && context.Config.GpuAccessor.QueryHostSupportsGeometryShaderPassthrough() ? "passthrough, " : string.Empty;
|
||||
string type;
|
||||
|
||||
if (context.Config.Stage == ShaderStage.Vertex)
|
||||
{
|
||||
type = context.Config.GpuAccessor.QueryAttributeType(attr).ToVec4Type();
|
||||
}
|
||||
else
|
||||
{
|
||||
type = AttributeType.Float.ToVec4Type();
|
||||
}
|
||||
|
||||
context.AppendLine($"layout ({pass}location = {attr}) {iq}in {type} {name}{suffix};");
|
||||
}
|
||||
}
|
||||
|
||||
private static void DeclareInputAttributePerPatch(CodeGenContext context, int attr)
|
||||
{
|
||||
int location = context.Config.GetPerPatchAttributeLocation(attr);
|
||||
string name = $"{DefaultNames.PerPatchAttributePrefix}{attr}";
|
||||
|
||||
context.AppendLine($"layout (location = {location}) patch in vec4 {name};");
|
||||
}
|
||||
|
||||
private static void DeclareOutputAttributes(CodeGenContext context, StructuredProgramInfo info)
|
||||
{
|
||||
if (context.Config.UsedFeatures.HasFlag(FeatureFlags.OaIndexing))
|
||||
{
|
||||
context.AppendLine($"layout (location = 0) out vec4 {DefaultNames.OAttributePrefix}[{Constants.MaxAttributes}];");
|
||||
}
|
||||
else
|
||||
{
|
||||
int usedAttributes = context.Config.UsedOutputAttributes;
|
||||
while (usedAttributes != 0)
|
||||
{
|
||||
int index = BitOperations.TrailingZeroCount(usedAttributes);
|
||||
DeclareOutputAttribute(context, index);
|
||||
usedAttributes &= ~(1 << index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void DeclareOutputAttribute(CodeGenContext context, int attr)
|
||||
{
|
||||
string suffix = AttributeInfo.IsArrayAttributeGlsl(context.Config.Stage, isOutAttr: true) ? "[]" : string.Empty;
|
||||
string name = $"{DefaultNames.OAttributePrefix}{attr}{suffix}";
|
||||
|
||||
if (context.Config.TransformFeedbackEnabled && context.Config.LastInVertexPipeline)
|
||||
{
|
||||
int attrOffset = AttributeConsts.UserAttributeBase + attr * 16;
|
||||
int components = context.Config.LastInPipeline ? context.Info.GetTransformFeedbackOutputComponents(attrOffset) : 1;
|
||||
|
||||
if (components > 1)
|
||||
{
|
||||
string type = components switch
|
||||
{
|
||||
2 => "vec2",
|
||||
3 => "vec3",
|
||||
4 => "vec4",
|
||||
_ => "float"
|
||||
};
|
||||
|
||||
string xfb = string.Empty;
|
||||
|
||||
var tfOutput = context.Info.GetTransformFeedbackOutput(attrOffset);
|
||||
if (tfOutput.Valid)
|
||||
{
|
||||
xfb = $", xfb_buffer = {tfOutput.Buffer}, xfb_offset = {tfOutput.Offset}, xfb_stride = {tfOutput.Stride}";
|
||||
}
|
||||
|
||||
context.AppendLine($"layout (location = {attr}{xfb}) out {type} {name};");
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int c = 0; c < 4; c++)
|
||||
{
|
||||
char swzMask = "xyzw"[c];
|
||||
|
||||
string xfb = string.Empty;
|
||||
|
||||
var tfOutput = context.Info.GetTransformFeedbackOutput(attrOffset + c * 4);
|
||||
if (tfOutput.Valid)
|
||||
{
|
||||
xfb = $", xfb_buffer = {tfOutput.Buffer}, xfb_offset = {tfOutput.Offset}, xfb_stride = {tfOutput.Stride}";
|
||||
}
|
||||
|
||||
context.AppendLine($"layout (location = {attr}, component = {c}{xfb}) out float {name}_{swzMask};");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string type = context.Config.Stage != ShaderStage.Fragment ? "vec4" :
|
||||
context.Config.GpuAccessor.QueryFragmentOutputType(attr) switch
|
||||
{
|
||||
AttributeType.Sint => "ivec4",
|
||||
AttributeType.Uint => "uvec4",
|
||||
_ => "vec4"
|
||||
};
|
||||
|
||||
if (context.Config.GpuAccessor.QueryHostReducedPrecision() && context.Config.Stage == ShaderStage.Vertex && attr == 0)
|
||||
{
|
||||
context.AppendLine($"layout (location = {attr}) invariant out {type} {name};");
|
||||
}
|
||||
else
|
||||
{
|
||||
context.AppendLine($"layout (location = {attr}) out {type} {name};");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void DeclareUsedOutputAttributesPerPatch(CodeGenContext context, HashSet<int> attrs)
|
||||
{
|
||||
foreach (int attr in attrs.Order())
|
||||
{
|
||||
DeclareOutputAttributePerPatch(context, attr);
|
||||
}
|
||||
}
|
||||
|
||||
private static void DeclareOutputAttributePerPatch(CodeGenContext context, int attr)
|
||||
{
|
||||
int location = context.Config.GetPerPatchAttributeLocation(attr);
|
||||
string name = $"{DefaultNames.PerPatchAttributePrefix}{attr}";
|
||||
|
||||
context.AppendLine($"layout (location = {location}) patch out vec4 {name};");
|
||||
}
|
||||
|
||||
private static void DeclareSupportUniformBlock(CodeGenContext context, ShaderStage stage, int scaleElements)
|
||||
{
|
||||
bool needsSupportBlock = stage == ShaderStage.Fragment ||
|
||||
(context.Config.LastInVertexPipeline && context.Config.GpuAccessor.QueryViewportTransformDisable());
|
||||
|
||||
if (!needsSupportBlock && scaleElements == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
context.AppendLine($"layout (binding = 0, std140) uniform {DefaultNames.SupportBlockName}");
|
||||
context.EnterScope();
|
||||
|
||||
switch (stage)
|
||||
{
|
||||
case ShaderStage.Fragment:
|
||||
case ShaderStage.Vertex:
|
||||
context.AppendLine($"uint {DefaultNames.SupportBlockAlphaTestName};");
|
||||
context.AppendLine($"bool {DefaultNames.SupportBlockIsBgraName}[{SupportBuffer.FragmentIsBgraCount}];");
|
||||
context.AppendLine($"vec4 {DefaultNames.SupportBlockViewportInverse};");
|
||||
context.AppendLine($"int {DefaultNames.SupportBlockFragmentScaleCount};");
|
||||
break;
|
||||
case ShaderStage.Compute:
|
||||
context.AppendLine($"uint s_reserved[{SupportBuffer.ComputeRenderScaleOffset / SupportBuffer.FieldSize}];");
|
||||
break;
|
||||
}
|
||||
|
||||
context.AppendLine($"float {DefaultNames.SupportBlockRenderScaleName}[{SupportBuffer.RenderScaleMaxCount}];");
|
||||
|
||||
context.LeaveScope(";");
|
||||
context.AppendLine();
|
||||
}
|
||||
|
||||
private static void AppendHelperFunction(CodeGenContext context, string filename)
|
||||
{
|
||||
string code = EmbeddedResources.ReadAllText(filename);
|
||||
|
||||
code = code.Replace("\t", CodeGenContext.Tab);
|
||||
code = code.Replace("$SHARED_MEM$", DefaultNames.SharedMemoryName);
|
||||
code = code.Replace("$STORAGE_MEM$", OperandManager.GetShaderStagePrefix(context.Config.Stage) + "_" + DefaultNames.StorageNamePrefix);
|
||||
|
||||
if (context.Config.GpuAccessor.QueryHostSupportsShaderBallot())
|
||||
{
|
||||
code = code.Replace("$SUBGROUP_INVOCATION$", "gl_SubGroupInvocationARB");
|
||||
code = code.Replace("$SUBGROUP_BROADCAST$", "readInvocationARB");
|
||||
}
|
||||
else
|
||||
{
|
||||
code = code.Replace("$SUBGROUP_INVOCATION$", "gl_SubgroupInvocationID");
|
||||
code = code.Replace("$SUBGROUP_BROADCAST$", "subgroupBroadcast");
|
||||
}
|
||||
|
||||
context.AppendLine(code);
|
||||
context.AppendLine();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
{
|
||||
static class DefaultNames
|
||||
{
|
||||
public const string LocalNamePrefix = "temp";
|
||||
|
||||
public const string SamplerNamePrefix = "tex";
|
||||
public const string ImageNamePrefix = "img";
|
||||
|
||||
public const string PerPatchAttributePrefix = "patch_attr_";
|
||||
public const string IAttributePrefix = "in_attr";
|
||||
public const string OAttributePrefix = "out_attr";
|
||||
|
||||
public const string StorageNamePrefix = "s";
|
||||
|
||||
public const string DataName = "data";
|
||||
|
||||
public const string SupportBlockName = "support_block";
|
||||
public const string SupportBlockAlphaTestName = "s_alpha_test";
|
||||
public const string SupportBlockIsBgraName = "s_is_bgra";
|
||||
public const string SupportBlockViewportInverse = "s_viewport_inverse";
|
||||
public const string SupportBlockFragmentScaleCount = "s_frag_scale_count";
|
||||
public const string SupportBlockRenderScaleName = "s_render_scale";
|
||||
|
||||
public const string BlockSuffix = "block";
|
||||
|
||||
public const string UniformNamePrefix = "c";
|
||||
public const string UniformNameSuffix = "data";
|
||||
|
||||
public const string LocalMemoryName = "local_mem";
|
||||
public const string SharedMemoryName = "shared_mem";
|
||||
|
||||
public const string ArgumentNamePrefix = "a";
|
||||
|
||||
public const string UndefinedName = "undef";
|
||||
}
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
int Helper_AtomicMaxS32(int offset, int value)
|
||||
{
|
||||
uint oldValue, newValue;
|
||||
do
|
||||
{
|
||||
oldValue = $SHARED_MEM$[offset];
|
||||
newValue = uint(max(int(oldValue), value));
|
||||
} while (atomicCompSwap($SHARED_MEM$[offset], oldValue, newValue) != oldValue);
|
||||
return int(oldValue);
|
||||
}
|
||||
|
||||
int Helper_AtomicMinS32(int offset, int value)
|
||||
{
|
||||
uint oldValue, newValue;
|
||||
do
|
||||
{
|
||||
oldValue = $SHARED_MEM$[offset];
|
||||
newValue = uint(min(int(oldValue), value));
|
||||
} while (atomicCompSwap($SHARED_MEM$[offset], oldValue, newValue) != oldValue);
|
||||
return int(oldValue);
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
int Helper_AtomicMaxS32(int index, int offset, int value)
|
||||
{
|
||||
uint oldValue, newValue;
|
||||
do
|
||||
{
|
||||
oldValue = $STORAGE_MEM$[index].data[offset];
|
||||
newValue = uint(max(int(oldValue), value));
|
||||
} while (atomicCompSwap($STORAGE_MEM$[index].data[offset], oldValue, newValue) != oldValue);
|
||||
return int(oldValue);
|
||||
}
|
||||
|
||||
int Helper_AtomicMinS32(int index, int offset, int value)
|
||||
{
|
||||
uint oldValue, newValue;
|
||||
do
|
||||
{
|
||||
oldValue = $STORAGE_MEM$[index].data[offset];
|
||||
newValue = uint(min(int(oldValue), value));
|
||||
} while (atomicCompSwap($STORAGE_MEM$[index].data[offset], oldValue, newValue) != oldValue);
|
||||
return int(oldValue);
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user