mirror of
https://git.ryujinx.app/projects/Kenji-NX.git
synced 2026-10-04 10:58:54 +02:00
Compare commits
290
Commits
2.0.3
...
72ecef8b9f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
72ecef8b9f | ||
|
|
472b0e2bdb | ||
|
|
8f6d22d92d | ||
|
|
645a4c99af | ||
|
|
a94c18bc0a | ||
|
|
74d6b310b8 | ||
|
|
3289715b8c | ||
|
|
3a3129252a | ||
|
|
ff47cb1d66 | ||
|
|
d440ff41d2 | ||
|
|
46308c32e7 | ||
|
|
bf09e153f1 | ||
|
|
0d1eebad31 | ||
|
|
b1b260ed17 | ||
|
|
a57756f447 | ||
|
|
be405de436 | ||
|
|
e88fd3273d | ||
|
|
79f55b12bf | ||
|
|
0bc515e4ff | ||
|
|
541fa63330 | ||
|
|
55aded3a05 | ||
|
|
61e0aba325 | ||
|
|
23fb4924e3 | ||
|
|
8fcc539ed9 | ||
|
|
51e4323a73 | ||
|
|
fcd55edf93 | ||
|
|
44872f45e0 | ||
|
|
1950b34e39 | ||
|
|
4aa8e249f1 | ||
|
|
3c13bdb4af | ||
|
|
7dec9a2f09 | ||
|
|
af6dd5b64c | ||
|
|
c6fba938bb | ||
|
|
4b4fd560ed | ||
|
|
7f99e32a0a | ||
|
|
4b8c74be10 | ||
|
|
2af1bc1808 | ||
|
|
1d19b318c1 | ||
|
|
36767d7fce | ||
|
|
20a9ecaebf | ||
|
|
77c947eb88 | ||
|
|
251b65771a | ||
|
|
7aa27b2ca5 | ||
|
|
3a479a437d | ||
|
|
5359ab77e1 | ||
|
|
3d5682375e | ||
|
|
bc777e1968 | ||
|
|
e729014cfa | ||
|
|
39b7242ef7 | ||
|
|
d55c0a702b | ||
|
|
f39b53982a | ||
|
|
46a57538c6 | ||
|
|
9b93b6fe18 | ||
|
|
d207d43768 | ||
|
|
d7f90f9f1f | ||
|
|
1b714ab1aa | ||
|
|
a6af70baa1 | ||
|
|
8c9cdfe9ce | ||
|
|
5b3a620bb0 | ||
|
|
d977208b19 | ||
|
|
477be704bb | ||
|
|
5c8be1b927 | ||
|
|
adc8ed594a | ||
|
|
9104a75a48 | ||
|
|
c0ba4e64cf | ||
|
|
6cf0a413a0 | ||
|
|
caed40d99a | ||
|
|
f764ae2d58 | ||
|
|
b16f74ffd9 | ||
|
|
bd96f2f51f | ||
|
|
3bf8a17f01 | ||
|
|
d5bd8871a2 | ||
|
|
dcafe32d5c | ||
|
|
18bd84c463 | ||
|
|
9a684ff066 | ||
|
|
60c867622e | ||
|
|
3cdae775b1 | ||
|
|
061bfb4074 | ||
|
|
2b15dfc473 | ||
|
|
a948308a2f | ||
|
|
a91f60b6ad | ||
|
|
56eef239a4 | ||
|
|
bef07155dc | ||
|
|
253f47c971 | ||
|
|
7d0947cac6 | ||
|
|
0d29b77a14 | ||
|
|
2aecce018c | ||
|
|
8ac2b1e497 | ||
|
|
9a1d33dde5 | ||
|
|
899c99740d | ||
|
|
1390fd02d7 | ||
|
|
5ecdd197cd | ||
|
|
546082128f | ||
|
|
2aae771ab3 | ||
|
|
a2c53ed6cf | ||
|
|
fba786cd38 | ||
|
|
292d42d394 | ||
|
|
afa4782493 | ||
|
|
b6cd6770ff | ||
|
|
fecb02647d | ||
|
|
bf12b601b0 | ||
|
|
4a5729cc01 | ||
|
|
5a16e24450 | ||
|
|
2dfa040d92 | ||
|
|
da6b58b9fa | ||
|
|
ad516777d9 | ||
|
|
812cecd713 | ||
|
|
d00bda7e53 | ||
|
|
c70f692324 | ||
|
|
9920619ff6 | ||
|
|
2ba33ec2ef | ||
|
|
e404954f88 | ||
|
|
6b383873e8 | ||
|
|
32d1653af9 | ||
|
|
298e2cdefd | ||
|
|
5a53d36992 | ||
|
|
8c99b90926 | ||
|
|
e287c9fc85 | ||
|
|
e349ef72fb | ||
|
|
b7c13715f1 | ||
|
|
139e18a8e1 | ||
|
|
58a76a0b9f | ||
|
|
6292192cc0 | ||
|
|
a926a31133 | ||
|
|
17b7eadb91 | ||
|
|
61a783e10a | ||
|
|
9b8517caf3 | ||
|
|
457f62d773 | ||
|
|
a6c0eabf49 | ||
|
|
e3ee28605d | ||
|
|
2c50fbcc1f | ||
|
|
90cb9d42db | ||
|
|
1a3b407839 | ||
|
|
46a0783293 | ||
|
|
82ae055fe5 | ||
|
|
f98af9e175 | ||
|
|
cdbe568620 | ||
|
|
86f47b8333 | ||
|
|
2993dba583 | ||
|
|
e720e4a87b | ||
|
|
f30d832847 | ||
|
|
afa1ab95c2 | ||
|
|
52b6fcf1a4 | ||
|
|
35449846d9 | ||
|
|
5d68312b54 | ||
|
|
b8aaadac5f | ||
|
|
a369b246a3 | ||
|
|
d96e93ef0d | ||
|
|
0bfd2ad3ef | ||
|
|
df36c23652 | ||
|
|
843a7113d1 | ||
|
|
2d420ee561 | ||
|
|
b958044e4e | ||
|
|
d659bec27a | ||
|
|
107df58666 | ||
|
|
280461dc78 | ||
|
|
1724149443 | ||
|
|
b44e2a87fd | ||
|
|
b1f767b2d5 | ||
|
|
ec9713b111 | ||
|
|
a7af26bc1f | ||
|
|
91a5f69805 | ||
|
|
f908bfe150 | ||
|
|
a2c494e216 | ||
|
|
e489e0d19f | ||
|
|
f362e33293 | ||
|
|
1e2fd6f4c2 | ||
|
|
35a8116ae8 | ||
|
|
41b8b6961c | ||
|
|
42727fca07 | ||
|
|
f5822c16af | ||
|
|
66a5719e10 | ||
|
|
cc2fb8f0b6 | ||
|
|
c9c78841b9 | ||
|
|
f26bd3d321 | ||
|
|
b28f52387a | ||
|
|
83412689b7 | ||
|
|
0b5f312b20 | ||
|
|
c0b7452cb5 | ||
|
|
6ba8ae53f2 | ||
|
|
d3bce3f361 | ||
|
|
2471bb8ede | ||
|
|
c3bfce3378 | ||
|
|
88e8d1309c | ||
|
|
ebeb532099 | ||
|
|
c501fe264b | ||
|
|
61d0430006 | ||
|
|
cd477cf744 | ||
|
|
0487b781dc | ||
|
|
51b32981b6 | ||
|
|
fa682d406e | ||
|
|
503dea74c2 | ||
|
|
1f979e5c6f | ||
|
|
378dc33cca | ||
|
|
9c37a557dd | ||
|
|
6e5bd0c9f2 | ||
|
|
0f2b11d4d5 | ||
|
|
1abf5b82c5 | ||
|
|
d751cfa81a | ||
|
|
af14fadb2f | ||
|
|
4fd4e3a4ff | ||
|
|
a1834900be | ||
|
|
fe7a30c747 | ||
|
|
3a387309b4 | ||
|
|
867a92a8bc | ||
|
|
45bf443c01 | ||
|
|
a09568d1b7 | ||
|
|
dae7ae7eaf | ||
|
|
c2f54d0a5c | ||
|
|
f4dfdd35b2 | ||
|
|
c56d04a9a9 | ||
|
|
5c6175cebf | ||
|
|
9addccb50f | ||
|
|
17946c78e6 | ||
|
|
29647b6351 | ||
|
|
6e6983799e | ||
|
|
61da23cb9e | ||
|
|
a62deb8cfd | ||
|
|
8ea79ae5d5 | ||
|
|
09f3bf4b55 | ||
|
|
171624e7f0 | ||
|
|
01cb33f658 | ||
|
|
121bb5dc76 | ||
|
|
d73ef0e3fb | ||
|
|
46b2da2435 | ||
|
|
aca897c70c | ||
|
|
e7d423cd07 | ||
|
|
48c809a80d | ||
|
|
7fd01214cf | ||
|
|
ef72e9b790 | ||
|
|
d5c9bc662c | ||
|
|
3cf90e808d | ||
|
|
326f744093 | ||
|
|
6cecbaa625 | ||
|
|
1443e1a2ff | ||
|
|
12d7f95468 | ||
|
|
b59a833467 | ||
|
|
50a2caf799 | ||
|
|
7d1fd99d3d | ||
|
|
c16559f20e | ||
|
|
6ecd6111d5 | ||
|
|
0ee71fa064 | ||
|
|
6e8f7e7fcb | ||
|
|
f9780b33bb | ||
|
|
d2a532f971 | ||
|
|
a90db3464d | ||
|
|
c61d171e52 | ||
|
|
8927a78c4d | ||
|
|
aa836dd924 | ||
|
|
878ea70aa9 | ||
|
|
9f0a35ee9b | ||
|
|
ed0ebdec5b | ||
|
|
b5a1272141 | ||
|
|
6768e1fa71 | ||
|
|
5c2d710fbb | ||
|
|
d3f3eacc41 | ||
|
|
5983cb9e5f | ||
|
|
e09f16838e | ||
|
|
18f302c0b0 | ||
|
|
8f77076117 | ||
|
|
39544e323c | ||
|
|
24932b7e1b | ||
|
|
2aaf34937d | ||
|
|
bce3426d26 | ||
|
|
51ca73cb10 | ||
|
|
cd3221abdc | ||
|
|
19dd23c288 | ||
|
|
20f1cef9b2 | ||
|
|
2f400491d5 | ||
|
|
f6351e3fff | ||
|
|
f15ddcf9c4 | ||
|
|
88d904acde | ||
|
|
fbcf57bef5 | ||
|
|
8bfb670e65 | ||
|
|
e00bece65a | ||
|
|
2a03f7b1d4 | ||
|
|
6c7b7d6fc4 | ||
|
|
c43db7d5f6 | ||
|
|
cc92af12a4 | ||
|
|
df21f6019e | ||
|
|
232dc2653e | ||
|
|
98b4ff331c | ||
|
|
846b5b6e8a | ||
|
|
fc0528876f | ||
|
|
299b4cfe1d | ||
|
|
d640f50203 | ||
|
|
95ac0a7a51 | ||
|
|
0dc506317c | ||
|
|
3e3b7d22e6 | ||
|
|
e02463d779 |
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends": [
|
||||
"renovate/config"
|
||||
],
|
||||
"enabledManagers": ["nuget"],
|
||||
"packageRules": [
|
||||
{
|
||||
// require approval for *all* NuGet package updates, not just major versions.
|
||||
"matchDepTypes": "nuget",
|
||||
"dependencyDashboardApproval": true
|
||||
},
|
||||
{
|
||||
// Ignore Gommon for automatic updates. I make breaking changes on minor updates not infrequently.
|
||||
"matchDepNames": "Gommon",
|
||||
"matchDepTypes": "nuget",
|
||||
"enabled": false
|
||||
},
|
||||
{
|
||||
"description": "group Silk.NET packages",
|
||||
"extends": ["renovate/config//groups/silkdotnet.json"],
|
||||
"groupName": "Silk.NET"
|
||||
},
|
||||
{
|
||||
"description": "group OpenTK packages",
|
||||
"extends": ["renovate/config//groups/opentk.json"],
|
||||
"groupName": "OpenTK"
|
||||
},
|
||||
{
|
||||
"description": "group Svg.Controls packages",
|
||||
"extends": ["renovate/config//groups/svgcontrols.json"],
|
||||
"groupName": "Svg.Controls"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -16,6 +16,10 @@ x64/
|
||||
build/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
AppDir/
|
||||
publish_appimage/
|
||||
publish_ava/
|
||||
publish_tmp_ava/
|
||||
|
||||
# Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets
|
||||
!packages/*/build/
|
||||
|
||||
+20
-34
@@ -1,6 +1,6 @@
|
||||
# Contribution to Ryujinx
|
||||
# Contribution to Kenji-NX
|
||||
|
||||
You can contribute to Ryujinx with PRs, testing of PRs and issues. Contributing code and other implementations is greatly appreciated alongside simply filing issues for problems you encounter.
|
||||
You can contribute to Kenji-NX with PRs, testing of PRs and issues. Contributing code and other implementations is greatly appreciated alongside simply filing issues for problems you encounter.
|
||||
Please read the entire document before continuing as it can potentially save everyone involved a significant amount of time.
|
||||
|
||||
# Quick Links
|
||||
@@ -14,17 +14,17 @@ We always welcome bug reports, feature proposals and overall feedback. Here are
|
||||
|
||||
### Finding Existing Issues
|
||||
|
||||
Before filing a new issue, please search our [open issues](https://github.com/KeatonTheBot/Ryujinx/issues) to check if it already exists.
|
||||
Before filing a new issue, please search our [open issues](https://git.ryujinx.app/kenji-nx/ryujinx/-/issues) to check if it already exists.
|
||||
|
||||
If you do find an existing issue, please include your own feedback in the discussion. Do consider upvoting (👍 reaction) the original post, as this helps us prioritize popular issues in our backlog.
|
||||
|
||||
### Writing a Good Feature Request
|
||||
|
||||
Please review any feature requests already opened to both check it has not already been suggested, and to familiarize yourself with the format. When ready to submit a proposal, please use the [Feature Request issue template](https://github.com/Ryujinx/Ryujinx/issues/new?assignees=&labels=&projects=&template=feature_request.yml&title=%5BFeature+Request%5D).
|
||||
Please review any feature requests already opened to both check it has not already been suggested, and to familiarize yourself with the format. When ready to submit a proposal, please go [here](https://git.ryujinx.app/kenji-nx/ryujinx/-/issues).
|
||||
|
||||
### Writing a Good Bug Report
|
||||
|
||||
Good bug reports make it easier for maintainers to verify and root cause the underlying problem. The better a bug report, the faster the problem will be resolved.
|
||||
Good bug reports make it easier for maintainers to verify and root cause the underlying problem. The better a bug report, the faster the problem will be resolved.
|
||||
Ideally, a bug report should contain the following information:
|
||||
|
||||
* A high-level description of the problem.
|
||||
@@ -34,13 +34,13 @@ Ideally, a bug report should contain the following information:
|
||||
* A Ryujinx log file of the run instance where the issue occurred. Log files can be found in `[Executable Folder]/Logs` and are named chronologically.
|
||||
* Additional information, e.g. is it a regression from previous versions? Are there any known workarounds?
|
||||
|
||||
When ready to submit a bug report, please use the [Bug Report issue template](https://github.com/KeatonTheBot/Ryujinx/issues/new?assignees=&labels=bug&projects=&template=bug_report.yml&title=%5BBug%5D).
|
||||
When ready to submit a bug report, please go [here](https://git.ryujinx.app/kenji-nx/ryujinx/-/issues.
|
||||
|
||||
## Contributing Changes
|
||||
|
||||
Project maintainers will merge changes that both improve the project and meet our standards for code quality.
|
||||
|
||||
The [Pull Request Guide](docs/workflow/pr-guide.md) and [License](https://github.com/KeatonTheBot/Ryujinx/blob/master/LICENSE.txt) docs define additional guidance.
|
||||
The [Pull Request Guide](docs/workflow/pr-guide.md) and [License](LICENSE.txt) docs define additional guidance.
|
||||
|
||||
### DOs and DON'Ts
|
||||
|
||||
@@ -67,30 +67,25 @@ Please do not:
|
||||
We use and recommend the following workflow:
|
||||
|
||||
1. Create or find an issue for your work.
|
||||
- You can skip this step for trivial changes.
|
||||
- Get agreement from the team and the community that your proposed change is a good one if it is of significant size or changes core functionality.
|
||||
- Clearly state that you are going to take on implementing it, if that's the case. You can request that the issue be assigned to you. Note: The issue filer and the implementer don't have to be the same person.
|
||||
- You can skip this step for trivial changes.
|
||||
- Get agreement from the team and the community that your proposed change is a good one if it is of significant size or changes core functionality.
|
||||
- Clearly state that you are going to take on implementing it, if that's the case. You can request that the issue be assigned to you. Note: The issue filer and the implementer don't have to be the same person.
|
||||
2. Create a personal fork of the repository on GitHub (if you don't already have one).
|
||||
3. In your fork, create a branch off of main (`git checkout -b mybranch`).
|
||||
- Branches are useful since they isolate your changes from incoming changes from upstream. They also enable you to create multiple PRs from the same fork.
|
||||
- Branches are useful since they isolate your changes from incoming changes from upstream. They also enable you to create multiple PRs from the same fork.
|
||||
4. Make and commit your changes to your branch.
|
||||
- [Build Instructions](https://github.com/KeatonTheBot/Ryujinx#building) explains how to build and test.
|
||||
- Commit messages should be clear statements of action and intent.
|
||||
- [Build Instructions](https://git.ryujinx.app/kenji-nx/ryujinx#building) explains how to build and test.
|
||||
- Commit messages should be clear statements of action and intent.
|
||||
6. Build the repository with your changes.
|
||||
- Make sure that the builds are clean.
|
||||
- Make sure that `dotnet format` has been run and any corrections tested and committed.
|
||||
- Make sure that the builds are clean.
|
||||
- Make sure that `dotnet format` has been run and any corrections tested and committed.
|
||||
7. Create a pull request (PR) against the Ryujinx/Ryujinx repository's **main** branch.
|
||||
- State in the description what issue or improvement your change is addressing.
|
||||
- Check if all the Continuous Integration checks are passing. Refer to [Actions](https://github.com/KeatonTheBot/Ryujinx/actions) to check for outstanding errors.
|
||||
- State in the description what issue or improvement your change is addressing.
|
||||
8. Wait for feedback or approval of your changes from the core development team
|
||||
- Details about the pull request [review procedure](docs/workflow/ci/pr-guide.md).
|
||||
- Details about the pull request [review procedure](docs/workflow/ci/pr-guide.md).
|
||||
9. When the team members have signed off, and all checks are green, your PR will be merged.
|
||||
- The next official build will automatically include your change.
|
||||
- You can delete the branch you used for making the change.
|
||||
|
||||
### Good First Issues
|
||||
|
||||
The team marks the most straightforward issues as [good first issues](https://github.com/KeatonTheBot/Ryujinx/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22). This set of issues is the place to start if you are interested in contributing but new to the codebase.
|
||||
- The next official build will automatically include your change.
|
||||
- You can delete the branch you used for making the change.
|
||||
|
||||
### Commit Messages
|
||||
|
||||
@@ -111,15 +106,6 @@ Fix #42
|
||||
|
||||
Also do your best to factor commits appropriately, not too large with unrelated things in the same commit, and not too small with the same small change applied N times in N different commits.
|
||||
|
||||
### PR - CI Process
|
||||
|
||||
The [Ryujinx continuous integration](https://github.com/KeatonTheBot/Ryujinx/actions) (CI) system will automatically perform the required builds and run tests (including the ones you are expected to run) for PRs. Builds and test runs must be clean or have bugs properly filed against flaky/unexpected failures that are unrelated to your change.
|
||||
|
||||
If the CI build fails for any reason, the PR actions tab should be consulted for further information on the failure. There are a few usual suspects for such a failure:
|
||||
* `dotnet format` has not been run on the PR and has outstanding stylistic issues.
|
||||
* There is an error within the PR that fails a test or errors the compiler.
|
||||
* Random failure of the workflow can occasionally result in a CI failure. In this scenario a maintainer will manually restart the job.
|
||||
|
||||
### PR Feedback
|
||||
|
||||
Ryujinx team and community members will provide feedback on your change. Community feedback is highly valued. You may see the absence of team feedback if the community has already provided good review feedback.
|
||||
@@ -134,5 +120,5 @@ Ryujinx uses some implementations and frameworks from other projects. The follow
|
||||
|
||||
- The license of the file is [permissive](https://en.wikipedia.org/wiki/Permissive_free_software_licence).
|
||||
- The license of the file is left in-tact.
|
||||
- The contribution is correctly attributed in the [3rd party notices](https://github.com/KeatonTheBot/Ryujinx/blob/master/distribution/legal/THIRDPARTY.md) file in the repository, as needed.
|
||||
- The contribution is correctly attributed in the [3rd party notices](distribution/legal/THIRDPARTY.md) file in the repository, as needed.
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<DebugType Condition="'$(Configuration)'=='Release'">none</DebugType>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
||||
+38
-38
@@ -3,53 +3,53 @@
|
||||
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageVersion Include="Avalonia" Version="11.0.13" />
|
||||
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.0.13" />
|
||||
<PackageVersion Include="Avalonia.Desktop" Version="11.0.13" />
|
||||
<PackageVersion Include="Avalonia.Diagnostics" Version="11.0.13" />
|
||||
<PackageVersion Include="Avalonia.Markup.Xaml.Loader" Version="11.0.13" />
|
||||
<PackageVersion Include="Avalonia.Svg" Version="11.0.0.19" />
|
||||
<PackageVersion Include="Avalonia.Svg.Skia" Version="11.0.0.19" />
|
||||
<PackageVersion Include="Avalonia" Version="11.3.16" />
|
||||
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.3.13" />
|
||||
<PackageVersion Include="Avalonia.Desktop" Version="11.3.16" />
|
||||
<PackageVersion Include="Avalonia.Diagnostics" Version="11.3.16" />
|
||||
<PackageVersion Include="Avalonia.Markup.Xaml.Loader" Version="11.3.16" />
|
||||
<PackageVersion Include="Svg.Controls.Avalonia" Version="11.3.9.5" />
|
||||
<PackageVersion Include="Svg.Controls.Skia.Avalonia" Version="11.3.9.5" />
|
||||
<PackageVersion Include="CommandLineParser" Version="2.9.1" />
|
||||
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.4.2" />
|
||||
<PackageVersion Include="Concentus" Version="2.2.2" />
|
||||
<PackageVersion Include="DiscordRichPresence" Version="1.2.1.24" />
|
||||
<PackageVersion Include="DynamicData" Version="9.0.4" />
|
||||
<PackageVersion Include="FluentAvaloniaUI" Version="2.0.5" />
|
||||
<PackageVersion Include="Gommon" Version="2.7.1.1" />
|
||||
<PackageVersion Include="GtkSharp.Dependencies" Version="1.1.1" />
|
||||
<PackageVersion Include="GtkSharp.Dependencies.osx" Version="0.0.5" />
|
||||
<PackageVersion Include="Humanizer" Version="2.14.1" />
|
||||
<PackageVersion Include="LibHac" Version="0.19.0" />
|
||||
<PackageVersion Include="DiscordRichPresence" Version="1.6.1.70" />
|
||||
<PackageVersion Include="DynamicData" Version="9.4.31" />
|
||||
<PackageVersion Include="FluentAvaloniaUI" Version="2.5.1" />
|
||||
<PackageVersion Include="Gommon" Version="2.8.1.2" />
|
||||
<PackageVersion Include="Humanizer" Version="3.0.10" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.9.2" />
|
||||
<PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.9.0" />
|
||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.12.0" />
|
||||
<PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.18.0" />
|
||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.5.1" />
|
||||
<PackageVersion Include="Microsoft.IO.RecyclableMemoryStream" Version="3.0.1" />
|
||||
<PackageVersion Include="MsgPack.Cli" Version="1.0.1" />
|
||||
<PackageVersion Include="NetCoreServer" Version="8.0.7" />
|
||||
<PackageVersion Include="NUnit" Version="3.13.3" />
|
||||
<PackageVersion Include="NUnit3TestAdapter" Version="4.1.0" />
|
||||
<PackageVersion Include="OpenTK.Core" Version="4.8.2" />
|
||||
<PackageVersion Include="OpenTK.Graphics" Version="4.8.2" />
|
||||
<PackageVersion Include="OpenTK.Audio.OpenAL" Version="4.8.2" />
|
||||
<PackageVersion Include="OpenTK.Windowing.GraphicsLibraryFramework" Version="4.8.2" />
|
||||
<PackageVersion Include="Newtonsoft.Json" Version="13.0.4" />
|
||||
<PackageVersion Include="NUnit" Version="4.6.1" />
|
||||
<PackageVersion Include="NUnit3TestAdapter" Version="6.2.0" />
|
||||
<PackageVersion Include="OpenTK.Core" Version="4.9.4" />
|
||||
<PackageVersion Include="OpenTK.Graphics" Version="4.9.4" />
|
||||
<PackageVersion Include="OpenTK.Audio.OpenAL" Version="4.9.4" />
|
||||
<PackageVersion Include="OpenTK.Windowing.GraphicsLibraryFramework" Version="4.9.4" />
|
||||
<PackageVersion Include="Open.NAT.Core" Version="2.1.0.5" />
|
||||
<PackageVersion Include="Ryujinx.Audio.OpenAL.Dependencies" Version="1.21.0.1" />
|
||||
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies.AllArch" Version="6.1.2-build3" />
|
||||
<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.30.0-build32" />
|
||||
<PackageVersion Include="Ryujinx.Audio.OpenAL" Version="1.25.1" />
|
||||
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies.Linux" Version="6.1.4-build6" />
|
||||
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies.macOS" Version="5.0.3-build14" />
|
||||
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies.Windows" Version="6.1.4-build6" />
|
||||
<PackageVersion Include="Ryujinx.Graphics.Vulkan.MoltenVK" Version="1.4.2-ryujinx.3" />
|
||||
<PackageVersion Include="Ryujinx.LibHac" Version="0.21.0-alpha.133" />
|
||||
<PackageVersion Include="Ryujinx.SDL3-CS" Version="2026.501.0" />
|
||||
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
|
||||
<PackageVersion Include="shaderc.net" Version="0.1.0" />
|
||||
<PackageVersion Include="SharpZipLib" Version="1.4.2" />
|
||||
<PackageVersion Include="Silk.NET.Vulkan" Version="2.22.0" />
|
||||
<PackageVersion Include="Silk.NET.Vulkan.Extensions.EXT" Version="2.22.0" />
|
||||
<PackageVersion Include="Silk.NET.Vulkan.Extensions.KHR" Version="2.22.0" />
|
||||
<PackageVersion Include="SkiaSharp" Version="2.88.9" />
|
||||
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="2.88.9" />
|
||||
<PackageVersion Include="Silk.NET.Shaderc" Version="2.23.0" />
|
||||
<PackageVersion Include="Silk.NET.Vulkan" Version="2.23.0" />
|
||||
<PackageVersion Include="Silk.NET.Vulkan.Extensions.EXT" Version="2.23.0" />
|
||||
<PackageVersion Include="Silk.NET.Vulkan.Extensions.KHR" Version="2.23.0" />
|
||||
<PackageVersion Include="SkiaSharp" Version="3.119.2" />
|
||||
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="3.119.2" />
|
||||
<PackageVersion Include="SPB" Version="0.0.4-build32" />
|
||||
<PackageVersion Include="System.IO.Hashing" Version="9.0.4" />
|
||||
<PackageVersion Include="System.Management" Version="9.0.4" />
|
||||
<PackageVersion Include="UnicornEngine.Unicorn" Version="2.0.2-rc1-fb78016" />
|
||||
<PackageVersion Include="System.IO.Hashing" Version="10.0.8" />
|
||||
<PackageVersion Include="UnicornEngine.Unicorn" Version="2.1.4-a40db6c" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -1,31 +1,26 @@
|
||||
<h1 align="center">
|
||||
<br>
|
||||
<img src="distribution/misc/Logo.png" alt="Kenji-NX">
|
||||
<img src="https://git.ryujinx.app/projects/Kenji-NX/raw/branch/master/distribution/misc/Logo.png" alt="Kenji-NX">
|
||||
<br>
|
||||
<b>Kenji-NX</b>
|
||||
<br>
|
||||
<a href="https://github.com/KeatonTheBot/Kenji-NX/releases/latest">
|
||||
<img src="https://img.shields.io/github/v/release/KeatonTheBot/Kenji-NX"
|
||||
alt="Latest Release">
|
||||
</a>
|
||||
|
||||
[](https://git.ryujinx.app/projects/Kenji-NX/releases/latest)
|
||||
[](https://git.ryujinx.app/Kenji-NX/android/releases/latest)
|
||||
<br>
|
||||
[](https://discord.gg/zBSAuZfKqe)
|
||||
|
||||
</h1>
|
||||
|
||||
<p>
|
||||
Kenji-NX is an open-source Nintendo Switch emulator, originally created by gdkchan, written in C#.
|
||||
This emulator aims at providing excellent accuracy and performance, a user-friendly interface and consistent builds.
|
||||
It was written from scratch and development on the project began in September 2017.
|
||||
Kenji-NX is available on GitHub under the <a href="https://github.com/KeatonTheBot/Kenji-NX/blob/master/LICENSE.txt" target="_blank">MIT license</a>.
|
||||
<br><br>
|
||||
On October 1st 2024, Ryujinx was discontinued as the creator was forced to abandon the project.
|
||||
<br><br>
|
||||
This fork is not a Ryujinx revival project; it aims to be a middle ground between GreemDev's <a href="https://git.ryujinx.app/ryubing/ryujinx">Ryujinx</a> fork and the more preservative <a href="https://git.ryujinx.app/archive/ryujinx-mirror">ryujinx-mirror</a> fork.
|
||||
It brings over many of the front-facing features from the aforementioned forks with <i>additional</i> contributions from KeatonTheBot and others.
|
||||
<br>
|
||||
</p>
|
||||
Kenji-NX is an open-source Nintendo Switch emulator, originally created by gdkchan, written in C#.
|
||||
This emulator aims at providing excellent accuracy and performance, a user-friendly interface and consistent builds.
|
||||
It was written from scratch and development on the project began in September 2017.
|
||||
Kenji-NX is available on GitHub under the [MIT license](LICENSE.txt).
|
||||
|
||||
<p>
|
||||
<img src="docs/shell.png">
|
||||
</p>
|
||||
On October 1st 2024, Ryujinx was discontinued as the creator was forced to abandon the project.
|
||||
|
||||
This fork is not a Ryujinx revival project; it aims to be a middle ground between GreemDev's [Ryujinx](https://git.ryujinx.app/projects/Ryubing) fork and the more preservative [ryujinx-mirror](https://git.ryujinx.app/archive/ryujinx-mirror) fork.
|
||||
It brings over many of the front-facing features from the aforementioned forks with *additional* contributions from KeatonTheBot and others.
|
||||
|
||||
## Compatibility
|
||||
|
||||
@@ -58,12 +53,12 @@ If you wish to build the emulator yourself, follow these steps:
|
||||
|
||||
### Step 1
|
||||
|
||||
Install the [.NET 9.0 (or higher) SDK](https://dotnet.microsoft.com/download/dotnet/9.0).
|
||||
Make sure your SDK version is higher or equal to the required version specified in [global.json](global.json).
|
||||
Install the [.NET 10.0 (or higher) SDK](https://dotnet.microsoft.com/download/dotnet/10.0).
|
||||
Make sure your SDK version is higher or equal to the required version specified in [global.json](global.json).
|
||||
|
||||
### Step 2
|
||||
|
||||
Either use `git clone https://github.com/KeatonTheBot/Kenji-NX` on the command line to clone the repository or use Code --> Download zip button to get the files.
|
||||
Either use `git clone https://git.ryujinx.app/projects/Kenji-NX` on the command line to clone the repository or use Code --> Download zip button to get the files.
|
||||
|
||||
### Step 3
|
||||
|
||||
@@ -125,7 +120,7 @@ See [LICENSE.txt](LICENSE.txt) and [THIRDPARTY.md](distribution/legal/THIRDPARTY
|
||||
|
||||
## Credits
|
||||
|
||||
- [LibHac](https://github.com/Thealexbarney/LibHac) is used for our file-system.
|
||||
- [LibHac](https://git.ryujinx.app/projects/LibHac) is used for our file-system.
|
||||
- [AmiiboAPI](https://www.amiiboapi.com) is used in our Amiibo emulation.
|
||||
- [ldn_mitm](https://github.com/spacemeowx2/ldn_mitm) is used for one of our available multiplayer modes.
|
||||
- [ShellLink](https://github.com/securifybv/ShellLink) is used for Windows shortcut generation.
|
||||
|
||||
-259
@@ -1,259 +0,0 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.1.32228.430
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Tests", "src\Ryujinx.Tests\Ryujinx.Tests.csproj", "{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Tests.Unicorn", "src\Ryujinx.Tests.Unicorn\Ryujinx.Tests.Unicorn.csproj", "{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.HLE", "src\Ryujinx.HLE\Ryujinx.HLE.csproj", "{CB92CFF9-1D62-4D4F-9E88-8130EF61E351}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.ShaderTools", "src\Ryujinx.ShaderTools\Ryujinx.ShaderTools.csproj", "{3AB294D0-2230-468F-9EB3-BDFCAEAE99A5}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Common", "src\Ryujinx.Common\Ryujinx.Common.csproj", "{5FD4E4F6-8928-4B3C-BE07-28A675C17226}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ARMeilleure", "src\ARMeilleure\ARMeilleure.csproj", "{ABF09A5E-2D8B-4B6F-A51D-5CE414DDB15A}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Gpu", "src\Ryujinx.Graphics.Gpu\Ryujinx.Graphics.Gpu.csproj", "{ADA7EA87-0D63-4D97-9433-922A2124401F}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.GAL", "src\Ryujinx.Graphics.GAL\Ryujinx.Graphics.GAL.csproj", "{A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.OpenGL", "src\Ryujinx.Graphics.OpenGL\Ryujinx.Graphics.OpenGL.csproj", "{9558FB96-075D-4219-8FFF-401979DC0B69}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Texture", "src\Ryujinx.Graphics.Texture\Ryujinx.Graphics.Texture.csproj", "{E1B1AD28-289D-47B7-A106-326972240207}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Shader", "src\Ryujinx.Graphics.Shader\Ryujinx.Graphics.Shader.csproj", "{03B955CD-AD84-4B93-AAA7-BF17923BBAA5}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Nvdec", "src\Ryujinx.Graphics.Nvdec\Ryujinx.Graphics.Nvdec.csproj", "{85A0FA56-DC01-4A42-8808-70DAC76BD66D}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Audio", "src\Ryujinx.Audio\Ryujinx.Audio.csproj", "{806ACF6D-90B0-45D0-A1AC-5F220F3B3985}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{36F870C1-3E5F-485F-B426-F0645AF78751}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
.editorconfig = .editorconfig
|
||||
Directory.Packages.props = Directory.Packages.props
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Memory", "src\Ryujinx.Memory\Ryujinx.Memory.csproj", "{A5E6C691-9E22-4263-8F40-42F002CE66BE}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Tests.Memory", "src\Ryujinx.Tests.Memory\Ryujinx.Tests.Memory.csproj", "{D1CC5322-7325-4F6B-9625-194B30BE1296}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Cpu", "src\Ryujinx.Cpu\Ryujinx.Cpu.csproj", "{3DF35E3D-D844-4399-A9A1-A9E923264C17}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Device", "src\Ryujinx.Graphics.Device\Ryujinx.Graphics.Device.csproj", "{C3002C3C-7B09-4FE7-894A-372EDA22FC6E}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Host1x", "src\Ryujinx.Graphics.Host1x\Ryujinx.Graphics.Host1x.csproj", "{C35F1536-7DE5-4F9D-9604-B5B4E1561947}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Nvdec.Vp9", "src\Ryujinx.Graphics.Nvdec.Vp9\Ryujinx.Graphics.Nvdec.Vp9.csproj", "{B9AECA11-E248-4886-A10B-81B631CAAF29}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Vic", "src\Ryujinx.Graphics.Vic\Ryujinx.Graphics.Vic.csproj", "{81BB2C11-9408-4EA3-822E-42987AF54429}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Video", "src\Ryujinx.Graphics.Video\Ryujinx.Graphics.Video.csproj", "{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Audio.Backends.OpenAL", "src\Ryujinx.Audio.Backends.OpenAL\Ryujinx.Audio.Backends.OpenAL.csproj", "{0BE11899-DF2D-4BDE-B9EE-2489E8D35E7D}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Audio.Backends.SoundIo", "src\Ryujinx.Audio.Backends.SoundIo\Ryujinx.Audio.Backends.SoundIo.csproj", "{716364DE-B988-41A6-BAB4-327964266ECC}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Input", "src\Ryujinx.Input\Ryujinx.Input.csproj", "{C16F112F-38C3-40BC-9F5F-4791112063D6}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Input.SDL2", "src\Ryujinx.Input.SDL2\Ryujinx.Input.SDL2.csproj", "{DFAB6F2D-B9BF-4AFF-B22B-7684A328EBA3}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.SDL2.Common", "src\Ryujinx.SDL2.Common\Ryujinx.SDL2.Common.csproj", "{2D5D3A1D-5730-4648-B0AB-06C53CB910C0}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Audio.Backends.SDL2", "src\Ryujinx.Audio.Backends.SDL2\Ryujinx.Audio.Backends.SDL2.csproj", "{D99A395A-8569-4DB0-B336-900647890052}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Headless.SDL2", "src\Ryujinx.Headless.SDL2\Ryujinx.Headless.SDL2.csproj", "{390DC343-5CB4-4C79-A5DD-E3ED235E4C49}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Nvdec.FFmpeg", "src\Ryujinx.Graphics.Nvdec.FFmpeg\Ryujinx.Graphics.Nvdec.FFmpeg.csproj", "{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx", "src\Ryujinx\Ryujinx.csproj", "{7C1B2721-13DA-4B62-B046-C626605ECCE6}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.UI.Common", "src\Ryujinx.UI.Common\Ryujinx.UI.Common.csproj", "{BA161CA0-CD65-4E6E-B644-51C8D1E542DC}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon.Generators", "src\Ryujinx.Horizon.Generators\Ryujinx.Horizon.Generators.csproj", "{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Vulkan", "src\Ryujinx.Graphics.Vulkan\Ryujinx.Graphics.Vulkan.csproj", "{D4D09B08-D580-4D69-B886-C35D2853F6C8}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Spv.Generator", "src\Spv.Generator\Spv.Generator.csproj", "{2BCB3D7A-38C0-4FE7-8FDA-374C6AD56D0E}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.UI.LocaleGenerator", "src\Ryujinx.UI.LocaleGenerator\Ryujinx.UI.LocaleGenerator.csproj", "{77D01AD9-2C98-478E-AE1D-8F7100738FB4}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon.Common", "src\Ryujinx.Horizon.Common\Ryujinx.Horizon.Common.csproj", "{77F96ECE-4952-42DB-A528-DED25572A573}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon", "src\Ryujinx.Horizon\Ryujinx.Horizon.csproj", "{AF34127A-3A92-43E5-8496-14960A50B1F1}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon.Kernel.Generators", "src\Ryujinx.Horizon.Kernel.Generators\Ryujinx.Horizon.Kernel.Generators.csproj", "{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.HLE.Generators", "src\Ryujinx.HLE.Generators\Ryujinx.HLE.Generators.csproj", "{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{CB92CFF9-1D62-4D4F-9E88-8130EF61E351}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{CB92CFF9-1D62-4D4F-9E88-8130EF61E351}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CB92CFF9-1D62-4D4F-9E88-8130EF61E351}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CB92CFF9-1D62-4D4F-9E88-8130EF61E351}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{3AB294D0-2230-468F-9EB3-BDFCAEAE99A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3AB294D0-2230-468F-9EB3-BDFCAEAE99A5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3AB294D0-2230-468F-9EB3-BDFCAEAE99A5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3AB294D0-2230-468F-9EB3-BDFCAEAE99A5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{5FD4E4F6-8928-4B3C-BE07-28A675C17226}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{5FD4E4F6-8928-4B3C-BE07-28A675C17226}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{5FD4E4F6-8928-4B3C-BE07-28A675C17226}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{5FD4E4F6-8928-4B3C-BE07-28A675C17226}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{ABF09A5E-2D8B-4B6F-A51D-5CE414DDB15A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{ABF09A5E-2D8B-4B6F-A51D-5CE414DDB15A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{ABF09A5E-2D8B-4B6F-A51D-5CE414DDB15A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{ABF09A5E-2D8B-4B6F-A51D-5CE414DDB15A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{ADA7EA87-0D63-4D97-9433-922A2124401F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{ADA7EA87-0D63-4D97-9433-922A2124401F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{ADA7EA87-0D63-4D97-9433-922A2124401F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{ADA7EA87-0D63-4D97-9433-922A2124401F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9558FB96-075D-4219-8FFF-401979DC0B69}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9558FB96-075D-4219-8FFF-401979DC0B69}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9558FB96-075D-4219-8FFF-401979DC0B69}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9558FB96-075D-4219-8FFF-401979DC0B69}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E1B1AD28-289D-47B7-A106-326972240207}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E1B1AD28-289D-47B7-A106-326972240207}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E1B1AD28-289D-47B7-A106-326972240207}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E1B1AD28-289D-47B7-A106-326972240207}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{03B955CD-AD84-4B93-AAA7-BF17923BBAA5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{03B955CD-AD84-4B93-AAA7-BF17923BBAA5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{03B955CD-AD84-4B93-AAA7-BF17923BBAA5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{03B955CD-AD84-4B93-AAA7-BF17923BBAA5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{85A0FA56-DC01-4A42-8808-70DAC76BD66D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{85A0FA56-DC01-4A42-8808-70DAC76BD66D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{85A0FA56-DC01-4A42-8808-70DAC76BD66D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{85A0FA56-DC01-4A42-8808-70DAC76BD66D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{806ACF6D-90B0-45D0-A1AC-5F220F3B3985}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{806ACF6D-90B0-45D0-A1AC-5F220F3B3985}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{806ACF6D-90B0-45D0-A1AC-5F220F3B3985}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{806ACF6D-90B0-45D0-A1AC-5F220F3B3985}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A5E6C691-9E22-4263-8F40-42F002CE66BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A5E6C691-9E22-4263-8F40-42F002CE66BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A5E6C691-9E22-4263-8F40-42F002CE66BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A5E6C691-9E22-4263-8F40-42F002CE66BE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D1CC5322-7325-4F6B-9625-194B30BE1296}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D1CC5322-7325-4F6B-9625-194B30BE1296}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D1CC5322-7325-4F6B-9625-194B30BE1296}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D1CC5322-7325-4F6B-9625-194B30BE1296}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{3DF35E3D-D844-4399-A9A1-A9E923264C17}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3DF35E3D-D844-4399-A9A1-A9E923264C17}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3DF35E3D-D844-4399-A9A1-A9E923264C17}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3DF35E3D-D844-4399-A9A1-A9E923264C17}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C3002C3C-7B09-4FE7-894A-372EDA22FC6E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C3002C3C-7B09-4FE7-894A-372EDA22FC6E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C3002C3C-7B09-4FE7-894A-372EDA22FC6E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C3002C3C-7B09-4FE7-894A-372EDA22FC6E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C35F1536-7DE5-4F9D-9604-B5B4E1561947}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C35F1536-7DE5-4F9D-9604-B5B4E1561947}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C35F1536-7DE5-4F9D-9604-B5B4E1561947}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C35F1536-7DE5-4F9D-9604-B5B4E1561947}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B9AECA11-E248-4886-A10B-81B631CAAF29}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B9AECA11-E248-4886-A10B-81B631CAAF29}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B9AECA11-E248-4886-A10B-81B631CAAF29}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B9AECA11-E248-4886-A10B-81B631CAAF29}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{81BB2C11-9408-4EA3-822E-42987AF54429}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{81BB2C11-9408-4EA3-822E-42987AF54429}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{81BB2C11-9408-4EA3-822E-42987AF54429}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{81BB2C11-9408-4EA3-822E-42987AF54429}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{0BE11899-DF2D-4BDE-B9EE-2489E8D35E7D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0BE11899-DF2D-4BDE-B9EE-2489E8D35E7D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0BE11899-DF2D-4BDE-B9EE-2489E8D35E7D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0BE11899-DF2D-4BDE-B9EE-2489E8D35E7D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{716364DE-B988-41A6-BAB4-327964266ECC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{716364DE-B988-41A6-BAB4-327964266ECC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{716364DE-B988-41A6-BAB4-327964266ECC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{716364DE-B988-41A6-BAB4-327964266ECC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C16F112F-38C3-40BC-9F5F-4791112063D6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C16F112F-38C3-40BC-9F5F-4791112063D6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C16F112F-38C3-40BC-9F5F-4791112063D6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C16F112F-38C3-40BC-9F5F-4791112063D6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{DFAB6F2D-B9BF-4AFF-B22B-7684A328EBA3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{DFAB6F2D-B9BF-4AFF-B22B-7684A328EBA3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{DFAB6F2D-B9BF-4AFF-B22B-7684A328EBA3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{DFAB6F2D-B9BF-4AFF-B22B-7684A328EBA3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2D5D3A1D-5730-4648-B0AB-06C53CB910C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2D5D3A1D-5730-4648-B0AB-06C53CB910C0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2D5D3A1D-5730-4648-B0AB-06C53CB910C0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2D5D3A1D-5730-4648-B0AB-06C53CB910C0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D99A395A-8569-4DB0-B336-900647890052}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D99A395A-8569-4DB0-B336-900647890052}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D99A395A-8569-4DB0-B336-900647890052}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D99A395A-8569-4DB0-B336-900647890052}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{390DC343-5CB4-4C79-A5DD-E3ED235E4C49}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{390DC343-5CB4-4C79-A5DD-E3ED235E4C49}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{390DC343-5CB4-4C79-A5DD-E3ED235E4C49}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{390DC343-5CB4-4C79-A5DD-E3ED235E4C49}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7C1B2721-13DA-4B62-B046-C626605ECCE6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7C1B2721-13DA-4B62-B046-C626605ECCE6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7C1B2721-13DA-4B62-B046-C626605ECCE6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7C1B2721-13DA-4B62-B046-C626605ECCE6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BA161CA0-CD65-4E6E-B644-51C8D1E542DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BA161CA0-CD65-4E6E-B644-51C8D1E542DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BA161CA0-CD65-4E6E-B644-51C8D1E542DC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BA161CA0-CD65-4E6E-B644-51C8D1E542DC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D4D09B08-D580-4D69-B886-C35D2853F6C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D4D09B08-D580-4D69-B886-C35D2853F6C8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D4D09B08-D580-4D69-B886-C35D2853F6C8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D4D09B08-D580-4D69-B886-C35D2853F6C8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2BCB3D7A-38C0-4FE7-8FDA-374C6AD56D0E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2BCB3D7A-38C0-4FE7-8FDA-374C6AD56D0E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2BCB3D7A-38C0-4FE7-8FDA-374C6AD56D0E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2BCB3D7A-38C0-4FE7-8FDA-374C6AD56D0E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{77D01AD9-2C98-478E-AE1D-8F7100738FB4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{77D01AD9-2C98-478E-AE1D-8F7100738FB4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{77D01AD9-2C98-478E-AE1D-8F7100738FB4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{77D01AD9-2C98-478E-AE1D-8F7100738FB4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{77F96ECE-4952-42DB-A528-DED25572A573}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{77F96ECE-4952-42DB-A528-DED25572A573}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{77F96ECE-4952-42DB-A528-DED25572A573}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{77F96ECE-4952-42DB-A528-DED25572A573}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{AF34127A-3A92-43E5-8496-14960A50B1F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AF34127A-3A92-43E5-8496-14960A50B1F1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AF34127A-3A92-43E5-8496-14960A50B1F1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{AF34127A-3A92-43E5-8496-14960A50B1F1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {110169B3-3328-4730-8AB0-BA05BEF75C1A}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,47 @@
|
||||
<Solution>
|
||||
<Folder Name="/Solution Items/">
|
||||
<File Path=".editorconfig" />
|
||||
<File Path="Directory.Build.props" />
|
||||
<File Path="Directory.Packages.props" />
|
||||
<File Path="nuget.config" />
|
||||
</Folder>
|
||||
<Project Path="src/ARMeilleure/ARMeilleure.csproj" />
|
||||
<Project Path="src/Ryujinx.Audio.Backends.Apple/Ryujinx.Audio.Backends.Apple.csproj" />
|
||||
<Project Path="src/Ryujinx.Audio.Backends.OpenAL/Ryujinx.Audio.Backends.OpenAL.csproj" />
|
||||
<Project Path="src/Ryujinx.Audio.Backends.SDL3/Ryujinx.Audio.Backends.SDL3.csproj" />
|
||||
<Project Path="src/Ryujinx.Audio.Backends.SoundIo/Ryujinx.Audio.Backends.SoundIo.csproj" />
|
||||
<Project Path="src/Ryujinx.Audio/Ryujinx.Audio.csproj" />
|
||||
<Project Path="src/Ryujinx.Common/Ryujinx.Common.csproj" />
|
||||
<Project Path="src/Ryujinx.Cpu/Ryujinx.Cpu.csproj" />
|
||||
<Project Path="src/Ryujinx.Graphics.Device/Ryujinx.Graphics.Device.csproj" />
|
||||
<Project Path="src/Ryujinx.Graphics.GAL/Ryujinx.Graphics.GAL.csproj" />
|
||||
<Project Path="src/Ryujinx.Graphics.Gpu/Ryujinx.Graphics.Gpu.csproj" />
|
||||
<Project Path="src/Ryujinx.Graphics.Host1x/Ryujinx.Graphics.Host1x.csproj" />
|
||||
<Project Path="src/Ryujinx.Graphics.Nvdec.FFmpeg/Ryujinx.Graphics.Nvdec.FFmpeg.csproj" />
|
||||
<Project Path="src/Ryujinx.Graphics.Nvdec.Vp9/Ryujinx.Graphics.Nvdec.Vp9.csproj" />
|
||||
<Project Path="src/Ryujinx.Graphics.Nvdec/Ryujinx.Graphics.Nvdec.csproj" />
|
||||
<Project Path="src/Ryujinx.Graphics.OpenGL/Ryujinx.Graphics.OpenGL.csproj" />
|
||||
<Project Path="src/Ryujinx.Graphics.Shader/Ryujinx.Graphics.Shader.csproj" />
|
||||
<Project Path="src/Ryujinx.Graphics.Texture/Ryujinx.Graphics.Texture.csproj" />
|
||||
<Project Path="src/Ryujinx.Graphics.Vic/Ryujinx.Graphics.Vic.csproj" />
|
||||
<Project Path="src/Ryujinx.Graphics.Video/Ryujinx.Graphics.Video.csproj" />
|
||||
<Project Path="src/Ryujinx.Graphics.Vulkan/Ryujinx.Graphics.Vulkan.csproj" />
|
||||
<Project Path="src/Ryujinx.HLE.Generators/Ryujinx.HLE.Generators.csproj" />
|
||||
<Project Path="src/Ryujinx.HLE/Ryujinx.HLE.csproj" />
|
||||
<Project Path="src/Ryujinx.Horizon.Common/Ryujinx.Horizon.Common.csproj" />
|
||||
<Project Path="src/Ryujinx.Horizon.Generators/Ryujinx.Horizon.Generators.csproj" />
|
||||
<Project Path="src/Ryujinx.Horizon.Kernel.Generators/Ryujinx.Horizon.Kernel.Generators.csproj" />
|
||||
<Project Path="src/Ryujinx.Horizon/Ryujinx.Horizon.csproj" />
|
||||
<Project Path="src/Ryujinx.Input.SDL3/Ryujinx.Input.SDL3.csproj" />
|
||||
<Project Path="src/Ryujinx.Input/Ryujinx.Input.csproj" />
|
||||
<Project Path="src/Ryujinx.Memory/Ryujinx.Memory.csproj" />
|
||||
<Project Path="src/Ryujinx.SDL3.Common/Ryujinx.SDL3.Common.csproj" />
|
||||
<Project Path="src/Ryujinx.ShaderTools/Ryujinx.ShaderTools.csproj" />
|
||||
<Project Path="src/Ryujinx.Tests.Memory/Ryujinx.Tests.Memory.csproj" />
|
||||
<Project Path="src/Ryujinx.Tests.Unicorn/Ryujinx.Tests.Unicorn.csproj" />
|
||||
<Project Path="src/Ryujinx.Tests/Ryujinx.Tests.csproj" />
|
||||
<Project Path="src/Ryujinx.UI.Common/Ryujinx.UI.Common.csproj" />
|
||||
<Project Path="src/Ryujinx.UI.LocaleGenerator/Ryujinx.UI.LocaleGenerator.csproj" />
|
||||
<Project Path="src/Ryujinx/Ryujinx.csproj" />
|
||||
<Project Path="src/Spv.Generator/Spv.Generator.csproj" />
|
||||
</Solution>
|
||||
@@ -2,10 +2,6 @@
|
||||
|
||||
SCRIPT_DIR=$(dirname "$(realpath "$0")")
|
||||
|
||||
if [ -f "$SCRIPT_DIR/Ryujinx.Headless.SDL2" ]; then
|
||||
RYUJINX_BIN="Ryujinx.Headless.SDL2"
|
||||
fi
|
||||
|
||||
if [ -f "$SCRIPT_DIR/Ryujinx" ]; then
|
||||
RYUJINX_BIN="Ryujinx"
|
||||
fi
|
||||
|
||||
Executable
+3
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
CURRENTDIR="$(readlink -f "$(dirname "$0")")"
|
||||
exec "$CURRENTDIR"/usr/bin/Ryujinx.sh "$@"
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
ROOTDIR="$(readlink -f "$(dirname "$0")")"/../../../
|
||||
cd "$ROOTDIR"
|
||||
|
||||
BUILDDIR=${BUILDDIR:-publish}
|
||||
OUTDIR=${OUTDIR:-publish_appimage}
|
||||
|
||||
rm -rf AppDir
|
||||
mkdir -p AppDir/usr/bin
|
||||
|
||||
cp distribution/linux/Ryujinx.desktop AppDir/Ryujinx.desktop
|
||||
cp distribution/linux/appimage/AppRun AppDir/AppRun
|
||||
cp src/Ryujinx.UI.Common/Resources/Logo_Ryujinx.png AppDir/Ryujinx.svg
|
||||
|
||||
|
||||
cp -r "$BUILDDIR"/* AppDir/usr/bin/
|
||||
|
||||
# Ensure necessary bins are set as executable
|
||||
chmod +x AppDir/AppRun AppDir/usr/bin/Ryujinx*
|
||||
|
||||
mkdir -p "$OUTDIR"
|
||||
|
||||
appimagetool -n --comp zstd --mksquashfs-opt -Xcompression-level --mksquashfs-opt 21 \
|
||||
AppDir "$OUTDIR"/Ryujinx.AppImage
|
||||
Binary file not shown.
@@ -10,6 +10,8 @@
|
||||
<string>Ryujinx</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>Ryujinx.icns</string>
|
||||
<key>CFBundleIconName</key>
|
||||
<string>Ryujinx</string>
|
||||
<key>CFBundleDocumentTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
@@ -40,17 +42,17 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.1</string>
|
||||
<string>2.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.1.0</string>
|
||||
<string>2.0.0</string>
|
||||
<key>NSHighResolutionCapable</key>
|
||||
<true/>
|
||||
<key>CSResourcesFileMapped</key>
|
||||
<true/>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>Copyright © 2018 - 2023 Ryujinx Team and Contributors.</string>
|
||||
<string>Copyright © 2018 - 2024 Ryujinx Team and Contributors. Copyright © 2024 - 2025 Kenji-NX and Contributors.</string>
|
||||
<key>LSApplicationCategoryType</key>
|
||||
<string>public.app-category.games</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
|
||||
Binary file not shown.
@@ -19,7 +19,7 @@ if platform.system() == "Darwin":
|
||||
else:
|
||||
OTOOL = shutil.which("llvm-otool")
|
||||
if OTOOL is None:
|
||||
for llvm_ver in [15, 14, 13]:
|
||||
for llvm_ver in [17, 16, 15, 14, 13]:
|
||||
otool_path = shutil.which(f"llvm-otool-{llvm_ver}")
|
||||
if otool_path is not None:
|
||||
OTOOL = otool_path
|
||||
@@ -562,26 +562,29 @@ search_path = [
|
||||
|
||||
|
||||
for path in content_directory.rglob("**/*.dylib"):
|
||||
current_search_path = [path.parent]
|
||||
current_search_path.extend(search_path)
|
||||
if not path.name.startswith("._"):
|
||||
current_search_path = [path.parent]
|
||||
current_search_path.extend(search_path)
|
||||
|
||||
fixup_dylib(
|
||||
path,
|
||||
get_path_related_to_target_exec(content_directory, path),
|
||||
current_search_path,
|
||||
content_directory,
|
||||
)
|
||||
print(f"Fixing path '{path}' using search path of '{current_search_path}' for context of '{content_directory}'.")
|
||||
fixup_dylib(
|
||||
path,
|
||||
get_path_related_to_target_exec(content_directory, path),
|
||||
current_search_path,
|
||||
content_directory,
|
||||
)
|
||||
|
||||
for path in content_directory.rglob("**/*.so"):
|
||||
current_search_path = [path.parent]
|
||||
current_search_path.extend(search_path)
|
||||
if not path.name.startswith("._"):
|
||||
current_search_path = [path.parent]
|
||||
current_search_path.extend(search_path)
|
||||
|
||||
fixup_dylib(
|
||||
path,
|
||||
get_path_related_to_target_exec(content_directory, path),
|
||||
current_search_path,
|
||||
content_directory,
|
||||
)
|
||||
fixup_dylib(
|
||||
path,
|
||||
get_path_related_to_target_exec(content_directory, path),
|
||||
current_search_path,
|
||||
content_directory,
|
||||
)
|
||||
|
||||
|
||||
with open(executable_path, "rb") as input:
|
||||
|
||||
@@ -26,7 +26,7 @@ else:
|
||||
LIPO = shutil.which("llvm-lipo")
|
||||
|
||||
if LIPO is None:
|
||||
for llvm_ver in [15, 14, 13]:
|
||||
for llvm_ver in [17, 16, 15, 14, 13]:
|
||||
lipo_path = shutil.which(f"llvm-lipo-{llvm_ver}")
|
||||
if lipo_path is not None:
|
||||
LIPO = lipo_path
|
||||
@@ -47,14 +47,12 @@ def get_new_name(
|
||||
input_component = str(input_dylib_path).replace(str(input_directory), "")[1:]
|
||||
return Path(os.path.join(output_directory, input_component))
|
||||
|
||||
|
||||
def is_fat_file(dylib_path: Path) -> str:
|
||||
res = subprocess.check_output([LIPO, "-info", str(dylib_path.absolute())]).decode(
|
||||
"utf-8"
|
||||
)
|
||||
|
||||
return not res.split("\n")[0].startswith("Non-fat file")
|
||||
|
||||
def get_archs(dylib_path: Path) -> list[str]:
|
||||
res = subprocess.check_output([LIPO, "-info", str(dylib_path)]).decode("utf-8")
|
||||
if res.startswith("Non-fat file"):
|
||||
return [res.split(":")[-1].strip()]
|
||||
else:
|
||||
return res.split("are:")[-1].strip().split()
|
||||
|
||||
def construct_universal_dylib(
|
||||
arm64_input_dylib_path: Path, x86_64_input_dylib_path: Path, output_dylib_path: Path
|
||||
@@ -69,11 +67,12 @@ def construct_universal_dylib(
|
||||
os.path.basename(arm64_input_dylib_path.resolve()), output_dylib_path
|
||||
)
|
||||
else:
|
||||
if is_fat_file(arm64_input_dylib_path) or not x86_64_input_dylib_path.exists():
|
||||
with open(output_dylib_path, "wb") as dst:
|
||||
with open(arm64_input_dylib_path, "rb") as src:
|
||||
dst.write(src.read())
|
||||
else:
|
||||
arm64_archs = get_archs(arm64_input_dylib_path)
|
||||
x86_64_archs = get_archs(x86_64_input_dylib_path) if x86_64_input_dylib_path.exists() else []
|
||||
|
||||
if "arm64" in arm64_archs and "x86_64" in arm64_archs:
|
||||
shutil.copy2(arm64_input_dylib_path, output_dylib_path)
|
||||
elif x86_64_archs:
|
||||
subprocess.check_call(
|
||||
[
|
||||
LIPO,
|
||||
|
||||
@@ -25,26 +25,41 @@ cp "$PUBLISH_DIRECTORY"/*.dylib "$APP_BUNDLE_DIRECTORY/Contents/Frameworks"
|
||||
cp Info.plist "$APP_BUNDLE_DIRECTORY/Contents"
|
||||
cp Ryujinx.icns "$APP_BUNDLE_DIRECTORY/Contents/Resources/Ryujinx.icns"
|
||||
cp updater.sh "$APP_BUNDLE_DIRECTORY/Contents/Resources/updater.sh"
|
||||
cp Assets.car "$APP_BUNDLE_DIRECTORY/Contents/Resources/Assets.car"
|
||||
cp -r "$PUBLISH_DIRECTORY/THIRDPARTY.md" "$APP_BUNDLE_DIRECTORY/Contents/Resources"
|
||||
|
||||
echo -n "APPL????" > "$APP_BUNDLE_DIRECTORY/Contents/PkgInfo"
|
||||
|
||||
# Fixup libraries and executable
|
||||
echo "Running bundle fix up python script"
|
||||
python3 bundle_fix_up.py "$APP_BUNDLE_DIRECTORY" MacOS/Ryujinx
|
||||
|
||||
# Resign all dyplib files as ad-hoc after changing them
|
||||
find "$APP_BUNDLE_DIRECTORY/Contents/Frameworks" -type f -name "*.dylib" -exec codesign --force --sign - {} \;
|
||||
|
||||
# Now sign it
|
||||
echo "Starting signing process"
|
||||
if ! [ -x "$(command -v codesign)" ];
|
||||
then
|
||||
if ! [ -x "$(command -v rcodesign)" ];
|
||||
then
|
||||
echo "Cannot find rcodesign on your system, please install rcodesign."
|
||||
echo "Cannot find rcodesign on your system, please install rcodesign and ensure it is in your search path."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# cargo install apple-codesign
|
||||
echo "Usign rcodesign for ad-hoc signing"
|
||||
echo "Using rcodesign for ad-hoc signing"
|
||||
|
||||
echo "Resigning all frameworks dylib files as ad-hoc"
|
||||
find "$APP_BUNDLE_DIRECTORY/Contents/Frameworks" -type f -name "*.dylib" -exec rcodesign sign {} \;
|
||||
|
||||
echo "Signing app bundle as ad-hoc"
|
||||
rcodesign sign --entitlements-xml-path "$ENTITLEMENTS_FILE_PATH" "$APP_BUNDLE_DIRECTORY"
|
||||
else
|
||||
echo "Usign codesign for ad-hoc signing"
|
||||
echo "Using codesign for ad-hoc signing"
|
||||
|
||||
echo "Resigning all frameworks dylib files as ad-hoc"
|
||||
find "$APP_BUNDLE_DIRECTORY/Contents/Frameworks" -type f -name "*.dylib" -exec codesign --force --sign - {} \;
|
||||
|
||||
echo "Signing app bundle as ad-hoc"
|
||||
codesign --entitlements "$ENTITLEMENTS_FILE_PATH" -f --deep -s - "$APP_BUNDLE_DIRECTORY"
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -20,7 +20,19 @@ SOURCE_REVISION_ID=$6
|
||||
CONFIGURATION=$7
|
||||
EXTRA_ARGS=$8
|
||||
|
||||
if [ "$VERSION" == "1.1.0" ];
|
||||
if [[ "$(uname)" == "Darwin" ]]; then
|
||||
echo "Clearing xattr on all dot underscore files"
|
||||
find "$BASE_DIR" -type f -name "._*" -exec sh -c '
|
||||
for f; do
|
||||
dir=$(dirname "$f")
|
||||
base=$(basename "$f")
|
||||
orig="$dir/${base#._}"
|
||||
[ -f "$orig" ] && xattr -c "$orig" || true
|
||||
done
|
||||
' sh {} +
|
||||
fi
|
||||
|
||||
if [ "$VERSION" == "2.0.0" ];
|
||||
then
|
||||
RELEASE_TAR_FILE_NAME=ryujinx-$CONFIGURATION-$VERSION+$SOURCE_REVISION_ID-macos_universal.app.tar
|
||||
else
|
||||
@@ -66,11 +78,11 @@ python3 "$BASE_DIR/distribution/macos/construct_universal_dylib.py" "$ARM64_APP_
|
||||
|
||||
if ! [ -x "$(command -v lipo)" ];
|
||||
then
|
||||
if ! [ -x "$(command -v llvm-lipo-14)" ];
|
||||
if ! [ -x "$(command -v llvm-lipo-17)" ];
|
||||
then
|
||||
LIPO=llvm-lipo
|
||||
else
|
||||
LIPO=llvm-lipo-14
|
||||
LIPO=llvm-lipo-17
|
||||
fi
|
||||
else
|
||||
LIPO=lipo
|
||||
@@ -109,12 +121,6 @@ python3 "$BASE_DIR/distribution/misc/add_tar_exec.py" "$RELEASE_TAR_FILE_NAME" "
|
||||
gzip -9 < "$RELEASE_TAR_FILE_NAME" > "$RELEASE_TAR_FILE_NAME.gz"
|
||||
rm "$RELEASE_TAR_FILE_NAME"
|
||||
|
||||
# Create legacy update package for Avalonia to not left behind old testers.
|
||||
if [ "$VERSION" != "1.1.0" ];
|
||||
then
|
||||
cp $RELEASE_TAR_FILE_NAME.gz test-ava-ryujinx-$VERSION-macos_universal.app.tar.gz
|
||||
fi
|
||||
|
||||
popd
|
||||
|
||||
echo "Done"
|
||||
echo "Done"
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
if [ "$#" -lt 7 ]; then
|
||||
echo "usage <BASE_DIR> <TEMP_DIRECTORY> <OUTPUT_DIRECTORY> <ENTITLEMENTS_FILE_PATH> <VERSION> <SOURCE_REVISION_ID> <CONFIGURATION> <EXTRA_ARGS>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p "$1"
|
||||
mkdir -p "$2"
|
||||
mkdir -p "$3"
|
||||
|
||||
BASE_DIR=$(readlink -f "$1")
|
||||
TEMP_DIRECTORY=$(readlink -f "$2")
|
||||
OUTPUT_DIRECTORY=$(readlink -f "$3")
|
||||
ENTITLEMENTS_FILE_PATH=$(readlink -f "$4")
|
||||
VERSION=$5
|
||||
SOURCE_REVISION_ID=$6
|
||||
CONFIGURATION=$7
|
||||
EXTRA_ARGS=$8
|
||||
|
||||
if [ "$VERSION" == "1.1.0" ];
|
||||
then
|
||||
RELEASE_TAR_FILE_NAME=sdl2-ryujinx-headless-$CONFIGURATION-$VERSION+$SOURCE_REVISION_ID-macos_universal.tar
|
||||
else
|
||||
RELEASE_TAR_FILE_NAME=sdl2-ryujinx-headless-$VERSION-macos_universal.tar
|
||||
fi
|
||||
|
||||
ARM64_OUTPUT="$TEMP_DIRECTORY/publish_arm64"
|
||||
X64_OUTPUT="$TEMP_DIRECTORY/publish_x64"
|
||||
UNIVERSAL_OUTPUT="$OUTPUT_DIRECTORY/publish"
|
||||
EXECUTABLE_SUB_PATH=Ryujinx.Headless.SDL2
|
||||
|
||||
rm -rf "$TEMP_DIRECTORY"
|
||||
mkdir -p "$TEMP_DIRECTORY"
|
||||
|
||||
DOTNET_COMMON_ARGS=(-p:DebugType=embedded -p:Version="$VERSION" -p:SourceRevisionId="$SOURCE_REVISION_ID" --self-contained true $EXTRA_ARGS)
|
||||
|
||||
dotnet restore
|
||||
dotnet build -c "$CONFIGURATION" src/Ryujinx.Headless.SDL2
|
||||
dotnet publish -c "$CONFIGURATION" -r osx-arm64 -o "$TEMP_DIRECTORY/publish_arm64" "${DOTNET_COMMON_ARGS[@]}" src/Ryujinx.Headless.SDL2
|
||||
dotnet publish -c "$CONFIGURATION" -r osx-x64 -o "$TEMP_DIRECTORY/publish_x64" "${DOTNET_COMMON_ARGS[@]}" src/Ryujinx.Headless.SDL2
|
||||
|
||||
# Get rid of the support library for ARMeilleure for x64 (that's only for arm64)
|
||||
rm -rf "$TEMP_DIRECTORY/publish_x64/libarmeilleure-jitsupport.dylib"
|
||||
|
||||
# Get rid of libsoundio from arm64 builds as we don't have a arm64 variant
|
||||
# TODO: remove this once done
|
||||
rm -rf "$TEMP_DIRECTORY/publish_arm64/libsoundio.dylib"
|
||||
|
||||
rm -rf "$OUTPUT_DIRECTORY"
|
||||
mkdir -p "$OUTPUT_DIRECTORY"
|
||||
|
||||
# Let's copy one of the two different outputs and remove the executable
|
||||
cp -R "$ARM64_OUTPUT/" "$UNIVERSAL_OUTPUT"
|
||||
rm "$UNIVERSAL_OUTPUT/$EXECUTABLE_SUB_PATH"
|
||||
|
||||
# Make it libraries universal
|
||||
python3 "$BASE_DIR/distribution/macos/construct_universal_dylib.py" "$ARM64_OUTPUT" "$X64_OUTPUT" "$UNIVERSAL_OUTPUT" "**/*.dylib"
|
||||
|
||||
if ! [ -x "$(command -v lipo)" ];
|
||||
then
|
||||
if ! [ -x "$(command -v llvm-lipo-14)" ];
|
||||
then
|
||||
LIPO=llvm-lipo
|
||||
else
|
||||
LIPO=llvm-lipo-14
|
||||
fi
|
||||
else
|
||||
LIPO=lipo
|
||||
fi
|
||||
|
||||
# Make the executable universal
|
||||
$LIPO "$ARM64_OUTPUT/$EXECUTABLE_SUB_PATH" "$X64_OUTPUT/$EXECUTABLE_SUB_PATH" -output "$UNIVERSAL_OUTPUT/$EXECUTABLE_SUB_PATH" -create
|
||||
|
||||
# Now sign it
|
||||
if ! [ -x "$(command -v codesign)" ];
|
||||
then
|
||||
if ! [ -x "$(command -v rcodesign)" ];
|
||||
then
|
||||
echo "Cannot find rcodesign on your system, please install rcodesign."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# NOTE: Currently require https://github.com/indygreg/apple-platform-rs/pull/44 to work on other OSes.
|
||||
# cargo install --git "https://github.com/marysaka/apple-platform-rs" --branch "fix/adhoc-app-bundle" apple-codesign --bin "rcodesign"
|
||||
echo "Using rcodesign for ad-hoc signing"
|
||||
for FILE in "$UNIVERSAL_OUTPUT"/*; do
|
||||
if [[ $(file "$FILE") == *"Mach-O"* ]]; then
|
||||
rcodesign sign --entitlements-xml-path "$ENTITLEMENTS_FILE_PATH" "$FILE"
|
||||
fi
|
||||
done
|
||||
else
|
||||
echo "Using codesign for ad-hoc signing"
|
||||
for FILE in "$UNIVERSAL_OUTPUT"/*; do
|
||||
if [[ $(file "$FILE") == *"Mach-O"* ]]; then
|
||||
codesign --entitlements "$ENTITLEMENTS_FILE_PATH" -f --deep -s - "$FILE"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
echo "Creating archive"
|
||||
pushd "$OUTPUT_DIRECTORY"
|
||||
tar --exclude "publish/Ryujinx.Headless.SDL2" -cvf "$RELEASE_TAR_FILE_NAME" publish 1> /dev/null
|
||||
python3 "$BASE_DIR/distribution/misc/add_tar_exec.py" "$RELEASE_TAR_FILE_NAME" "publish/Ryujinx.Headless.SDL2" "publish/Ryujinx.Headless.SDL2"
|
||||
gzip -9 < "$RELEASE_TAR_FILE_NAME" > "$RELEASE_TAR_FILE_NAME.gz"
|
||||
rm "$RELEASE_TAR_FILE_NAME"
|
||||
popd
|
||||
|
||||
echo "Done"
|
||||
+4
-4
@@ -1,14 +1,14 @@
|
||||
# Documents Index
|
||||
|
||||
This repo includes several documents that explain both high-level and low-level concepts about Ryujinx and its functions. These are very useful for contributors, to get context that can be very difficult to acquire from just reading code.
|
||||
This repo includes several documents that explain both high-level and low-level concepts about Kenji-NX and its functions. These are very useful for contributors, to get context that can be very difficult to acquire from just reading code.
|
||||
|
||||
Intro to Ryujinx
|
||||
Intro to Kenji-NX
|
||||
==================
|
||||
|
||||
Ryujinx is an open-source Nintendo Switch emulator, created by gdkchan, written in C#.
|
||||
Kenji-NX is an open-source Nintendo Switch emulator written in C#. It is based on Ryujinx, which was originally created by gdkchan.
|
||||
* The CPU emulator, ARMeilleure, emulates an ARMv8 CPU and currently has support for most 64-bit ARMv8 and some of the ARMv7 (and older) instructions.
|
||||
* The GPU emulator emulates the Switch's Maxwell GPU using either the OpenGL (version 4.5 minimum), Vulkan, or Metal (via MoltenVK) APIs through a custom build of OpenTK or Silk.NET respectively.
|
||||
* Audio output is entirely supported via C# wrappers for SDL2, with OpenAL & libsoundio as fallbacks.
|
||||
* Audio output is entirely supported via C# wrappers for SDL3, with OpenAL & libsoundio as fallbacks.
|
||||
|
||||
Getting Started
|
||||
===============
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
## Contributing Rules
|
||||
|
||||
All contributions to KeatonTheBot/Ryujinx repository are made via pull requests (PRs) rather than through direct commits. The pull requests are reviewed and merged by the maintainers after a review and at least two approvals from the core development team.
|
||||
All contributions to Kenji-NX repository are made via pull requests (PRs) rather than through direct commits. The pull requests are reviewed and merged by the maintainers after a review and at least two approvals from the core development team.
|
||||
|
||||
To merge pull requests, you must have write permissions in the repository.
|
||||
|
||||
@@ -18,17 +18,13 @@ To merge pull requests, you must have write permissions in the repository.
|
||||
|
||||
## Pull Request Ownership
|
||||
|
||||
Every pull request will have automatically have labels and reviewers assigned. The label not only indicates the code segment which the change touches but also the area reviewers to be assigned.
|
||||
Every pull request will automatically have labels and reviewers assigned. The label not only indicates the code segment which the change touches but also the area reviewers to be assigned.
|
||||
|
||||
If during the code review process a merge conflict occurs, the PR author is responsible for its resolution. Help will be provided if necessary although GitHub makes this easier by allowing simple conflict resolution using the [conflict-editor](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/resolving-a-merge-conflict-on-github).
|
||||
|
||||
## Pull Request Builds
|
||||
|
||||
When submitting a PR to the `KeatonTheBot/Ryujinx` repository, various builds will run validating many areas to ensure we keep developer productivity and product quality high. These various workflows can be tracked in the [Actions](https://github.com/KeatonTheBot/Ryujinx/actions) tab of the repository. If the job continues to completion, the build artifacts will be uploaded and posted as a comment in the PR discussion.
|
||||
|
||||
## Review Turnaround Times
|
||||
|
||||
Ryujinx is a project that is maintained by volunteers on a completely free-time basis. As such we cannot guarantee any particular timeframe for pull request review and approval. Weeks to months are common for larger (>500 line) PRs but there are some additional best practises to avoid review purgatory.
|
||||
Kenji-NX is a project that is maintained by volunteers on a completely free-time basis. As such we cannot guarantee any particular timeframe for pull request review and approval. Weeks to months are common for larger (>500 line) PRs but there are some additional best practises to avoid review purgatory.
|
||||
|
||||
* Make the reviewers life easier wherever possible. Make use of descriptive commit names, code comments and XML docs where applicable.
|
||||
* If there is disagreement on feedback then always lean on the side of the development team and community over any personal opinion.
|
||||
@@ -41,8 +37,7 @@ To re-iterate, make the review as easy for us as possible, respond promptly and
|
||||
Anyone with write access can merge a pull request manually when the following conditions have been met:
|
||||
|
||||
* The PR has been approved by two reviewers and any other objections are addressed.
|
||||
* You can request follow up reviews from the original reviewers if they requested changes.
|
||||
* The PR successfully builds and passes all tests in the Continuous Integration (CI) system. In case of failures, refer to the [Actions](https://github.com/KeatonTheBot/Ryujinx/actions) tab of your PR.
|
||||
* You can request follow-up reviews from the original reviewers if they requested changes.
|
||||
|
||||
Typically, PRs are merged as one commit (squash merges). It creates a simpler history than a Merge Commit. "Special circumstances" are rare, and typically mean that there are a series of cleanly separated changes that will be too hard to understand if squashed together, or for some reason we want to preserve the ability to dissect them.
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"sdk": {
|
||||
"version": "9.0.100",
|
||||
"version": "10.0.100",
|
||||
"rollForward": "latestFeature"
|
||||
}
|
||||
}
|
||||
|
||||
+20
-4
@@ -1,7 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<clear />
|
||||
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
|
||||
</packageSources>
|
||||
<packageSources>
|
||||
<clear />
|
||||
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
|
||||
<!-- Only needed when using pre-release versions of Ryujinx.LibHac. -->
|
||||
<add key="LibHacAlpha" value="https://git.ryujinx.app/api/packages/projects/nuget/index.json" />
|
||||
<!--<add key="Silk.NET" value="https://gitlab.com/api/v4/projects/51457475/packages/nuget/index.json" />-->
|
||||
</packageSources>
|
||||
<packageSourceMapping>
|
||||
<!-- key value for <packageSource> should match key values from <packageSources> element -->
|
||||
<!-- These are defined and .NET still yells about multiple package sources with no mappings. Not sure what to do, this is in the docs lol -->
|
||||
<packageSource key="nuget.org">
|
||||
<package pattern="*" />
|
||||
</packageSource>
|
||||
<packageSource key="LibHacAlpha">
|
||||
<package pattern="Ryujinx.LibHac" />
|
||||
</packageSource>
|
||||
<!--<packageSource key="Silk.NET">
|
||||
<package pattern="Silk.*" />
|
||||
</packageSource>-->
|
||||
</packageSourceMapping>
|
||||
</configuration>
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<RuntimeIdentifiers>osx-arm64</RuntimeIdentifiers>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Ryujinx.Common\Ryujinx.Common.csproj" />
|
||||
<ProjectReference Include="..\Ryujinx.Memory\Ryujinx.Memory.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -254,7 +254,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
|
||||
private static bool IsMemoryLoadOrStore(Instruction inst)
|
||||
{
|
||||
return inst == Instruction.Load || inst == Instruction.Store;
|
||||
return inst is Instruction.Load or Instruction.Store;
|
||||
}
|
||||
|
||||
private static bool ConstTooLong(Operand constOp, OperandType accessType)
|
||||
|
||||
@@ -52,7 +52,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
// Any value AND all ones will be equal itself, so it's effectively a no-op.
|
||||
// Any value OR all ones will be equal all ones, so one can just use MOV.
|
||||
// Any value XOR all ones will be equal its inverse, so one can just use MVN.
|
||||
if (value == 0 || value == ulong.MaxValue)
|
||||
if (value is 0 or ulong.MaxValue)
|
||||
{
|
||||
immN = 0;
|
||||
immS = 0;
|
||||
|
||||
@@ -189,8 +189,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
// The only blocks which can have 0 successors are exit blocks.
|
||||
Operation last = block.Operations.Last;
|
||||
|
||||
Debug.Assert(last.Instruction == Instruction.Tailcall ||
|
||||
last.Instruction == Instruction.Return);
|
||||
Debug.Assert(last.Instruction is Instruction.Tailcall or Instruction.Return);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -464,7 +463,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
Operand dest = operation.Destination;
|
||||
Operand source = operation.GetSource(0);
|
||||
|
||||
Debug.Assert(dest.Type == OperandType.FP32 || dest.Type == OperandType.FP64);
|
||||
Debug.Assert(dest.Type is OperandType.FP32 or OperandType.FP64);
|
||||
Debug.Assert(dest.Type != source.Type);
|
||||
Debug.Assert(source.Type != OperandType.V128);
|
||||
|
||||
@@ -483,7 +482,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
Operand dest = operation.Destination;
|
||||
Operand source = operation.GetSource(0);
|
||||
|
||||
Debug.Assert(dest.Type == OperandType.FP32 || dest.Type == OperandType.FP64);
|
||||
Debug.Assert(dest.Type is OperandType.FP32 or OperandType.FP64);
|
||||
Debug.Assert(dest.Type != source.Type);
|
||||
Debug.Assert(source.Type.IsInteger());
|
||||
|
||||
@@ -1463,7 +1462,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
|
||||
private static bool IsLoadOrStore(Operation operation)
|
||||
{
|
||||
return operation.Instruction == Instruction.Load || operation.Instruction == Instruction.Store;
|
||||
return operation.Instruction is Instruction.Load or Instruction.Store;
|
||||
}
|
||||
|
||||
private static OperandType GetMemOpValueType(Operation operation)
|
||||
@@ -1553,7 +1552,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
|
||||
private static void EnsureSameReg(Operand op1, Operand op2)
|
||||
{
|
||||
Debug.Assert(op1.Kind == OperandKind.Register || op1.Kind == OperandKind.Memory);
|
||||
Debug.Assert(op1.Kind is OperandKind.Register or OperandKind.Memory);
|
||||
Debug.Assert(op1.Kind == op2.Kind);
|
||||
Debug.Assert(op1.Value == op2.Value);
|
||||
}
|
||||
|
||||
@@ -127,13 +127,13 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
#region macOS
|
||||
|
||||
[LibraryImport("libSystem.dylib", SetLastError = true)]
|
||||
private static unsafe partial int sysctlbyname([MarshalAs(UnmanagedType.LPStr)] string name, out int oldValue, ref ulong oldSize, IntPtr newValue, ulong newValueSize);
|
||||
private static unsafe partial int sysctlbyname([MarshalAs(UnmanagedType.LPStr)] string name, out int oldValue, ref ulong oldSize, nint newValue, ulong newValueSize);
|
||||
|
||||
[SupportedOSPlatform("macos")]
|
||||
private static bool CheckSysctlName(string name)
|
||||
{
|
||||
ulong size = sizeof(int);
|
||||
if (sysctlbyname(name, out int val, ref size, IntPtr.Zero, 0) == 0 && size == sizeof(int))
|
||||
if (sysctlbyname(name, out int val, ref size, nint.Zero, 0) == 0 && size == sizeof(int))
|
||||
{
|
||||
return val != 0;
|
||||
}
|
||||
|
||||
@@ -736,19 +736,19 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
{
|
||||
IntrinsicInfo info = IntrinsicTable.GetInfo(intrinsic & ~(Intrinsic.Arm64VTypeMask | Intrinsic.Arm64VSizeMask));
|
||||
|
||||
return info.Type == IntrinsicType.ScalarBinaryRd ||
|
||||
info.Type == IntrinsicType.ScalarTernaryFPRdByElem ||
|
||||
info.Type == IntrinsicType.ScalarTernaryShlRd ||
|
||||
info.Type == IntrinsicType.ScalarTernaryShrRd ||
|
||||
info.Type == IntrinsicType.Vector128BinaryRd ||
|
||||
info.Type == IntrinsicType.VectorBinaryRd ||
|
||||
info.Type == IntrinsicType.VectorInsertByElem ||
|
||||
info.Type == IntrinsicType.VectorTernaryRd ||
|
||||
info.Type == IntrinsicType.VectorTernaryRdBitwise ||
|
||||
info.Type == IntrinsicType.VectorTernaryFPRdByElem ||
|
||||
info.Type == IntrinsicType.VectorTernaryRdByElem ||
|
||||
info.Type == IntrinsicType.VectorTernaryShlRd ||
|
||||
info.Type == IntrinsicType.VectorTernaryShrRd;
|
||||
return info.Type is IntrinsicType.ScalarBinaryRd
|
||||
or IntrinsicType.ScalarTernaryFPRdByElem
|
||||
or IntrinsicType.ScalarTernaryShlRd
|
||||
or IntrinsicType.ScalarTernaryShrRd
|
||||
or IntrinsicType.Vector128BinaryRd
|
||||
or IntrinsicType.VectorBinaryRd
|
||||
or IntrinsicType.VectorInsertByElem
|
||||
or IntrinsicType.VectorTernaryRd
|
||||
or IntrinsicType.VectorTernaryRdBitwise
|
||||
or IntrinsicType.VectorTernaryFPRdByElem
|
||||
or IntrinsicType.VectorTernaryRdByElem
|
||||
or IntrinsicType.VectorTernaryShlRd
|
||||
or IntrinsicType.VectorTernaryShrRd;
|
||||
}
|
||||
|
||||
private static bool HasConstSrc1(Operation node, ulong value)
|
||||
@@ -849,7 +849,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
|
||||
var compType = (Comparison)comp.AsInt32();
|
||||
|
||||
return compType == Comparison.Equal || compType == Comparison.NotEqual;
|
||||
return compType is Comparison.Equal or Comparison.NotEqual;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using ARMeilleure.CodeGen.Linking;
|
||||
using ARMeilleure.CodeGen.Unwinding;
|
||||
using ARMeilleure.Translation.Cache;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace ARMeilleure.CodeGen
|
||||
@@ -58,7 +57,7 @@ namespace ARMeilleure.CodeGen
|
||||
/// <typeparam name="T">Type of delegate</typeparam>
|
||||
/// <param name="codePointer">Pointer to the function code in memory</param>
|
||||
/// <returns>A delegate of type <typeparamref name="T"/> pointing to the mapped function</returns>
|
||||
public T MapWithPointer<T>(out IntPtr codePointer)
|
||||
public T MapWithPointer<T>(out nint codePointer)
|
||||
{
|
||||
codePointer = JitCache.Map(this);
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace ARMeilleure.CodeGen.Linking
|
||||
/// <summary>
|
||||
/// Gets an empty <see cref="RelocInfo"/>.
|
||||
/// </summary>
|
||||
public static RelocInfo Empty { get; } = new RelocInfo(null);
|
||||
public static RelocInfo Empty { get; } = new(null);
|
||||
|
||||
private readonly RelocEntry[] _entries;
|
||||
|
||||
|
||||
@@ -227,11 +227,11 @@ namespace ARMeilleure.CodeGen.Optimizations
|
||||
|
||||
private static bool HasSideEffects(Operation node)
|
||||
{
|
||||
return node.Instruction == Instruction.Call
|
||||
|| node.Instruction == Instruction.Tailcall
|
||||
|| node.Instruction == Instruction.CompareAndSwap
|
||||
|| node.Instruction == Instruction.CompareAndSwap16
|
||||
|| node.Instruction == Instruction.CompareAndSwap8;
|
||||
return node.Instruction is Instruction.Call
|
||||
or Instruction.Tailcall
|
||||
or Instruction.CompareAndSwap
|
||||
or Instruction.CompareAndSwap16
|
||||
or Instruction.CompareAndSwap8;
|
||||
}
|
||||
|
||||
private static bool IsPropagableCompare(Operation operation)
|
||||
|
||||
@@ -839,7 +839,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||
{
|
||||
dest.NumberLocal(_intervals.Count);
|
||||
|
||||
LiveInterval interval = new LiveInterval(dest);
|
||||
LiveInterval interval = new(dest);
|
||||
_intervals.Add(interval);
|
||||
|
||||
SetVisited(dest);
|
||||
@@ -847,7 +847,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||
// If this is a copy (or copy-like operation), set the copy source interval as well.
|
||||
// This is used for register preferencing later on, which allows the copy to be eliminated
|
||||
// in some cases.
|
||||
if (node.Instruction == Instruction.Copy || node.Instruction == Instruction.ZeroExtend32)
|
||||
if (node.Instruction is Instruction.Copy or Instruction.ZeroExtend32)
|
||||
{
|
||||
Operand source = node.GetSource(0);
|
||||
|
||||
@@ -1120,8 +1120,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||
|
||||
private static bool IsLocalOrRegister(OperandKind kind)
|
||||
{
|
||||
return kind == OperandKind.LocalVariable ||
|
||||
kind == OperandKind.Register;
|
||||
return kind is OperandKind.LocalVariable or OperandKind.Register;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -387,7 +387,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return HashCode.Combine((IntPtr)_data);
|
||||
return HashCode.Combine((nint)_data);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
|
||||
@@ -63,7 +63,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return HashCode.Combine((IntPtr)_data);
|
||||
return HashCode.Combine((nint)_data);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
|
||||
@@ -1106,17 +1106,17 @@ namespace ARMeilleure.CodeGen.X86
|
||||
}
|
||||
else
|
||||
{
|
||||
if (flags.HasFlag(InstructionFlags.Prefix66))
|
||||
if ((flags & InstructionFlags.Prefix66) != 0)
|
||||
{
|
||||
WriteByte(0x66);
|
||||
}
|
||||
|
||||
if (flags.HasFlag(InstructionFlags.PrefixF2))
|
||||
if ((flags & InstructionFlags.PrefixF2) != 0f)
|
||||
{
|
||||
WriteByte(0xf2);
|
||||
}
|
||||
|
||||
if (flags.HasFlag(InstructionFlags.PrefixF3))
|
||||
if ((flags & InstructionFlags.PrefixF3) != 0f)
|
||||
{
|
||||
WriteByte(0xf3);
|
||||
}
|
||||
@@ -1477,7 +1477,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
|
||||
private static bool Is64Bits(OperandType type)
|
||||
{
|
||||
return type == OperandType.I64 || type == OperandType.FP64;
|
||||
return type is OperandType.I64 or OperandType.FP64;
|
||||
}
|
||||
|
||||
private static bool IsImm8(ulong immediate, OperandType type)
|
||||
|
||||
@@ -175,8 +175,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
// The only blocks which can have 0 successors are exit blocks.
|
||||
Operation last = block.Operations.Last;
|
||||
|
||||
Debug.Assert(last.Instruction == Instruction.Tailcall ||
|
||||
last.Instruction == Instruction.Return);
|
||||
Debug.Assert(last.Instruction is Instruction.Tailcall or Instruction.Return);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -478,7 +477,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
Debug.Assert(HardwareCapabilities.SupportsVexEncoding);
|
||||
|
||||
Debug.Assert(dest.Kind == OperandKind.Register && src1.Kind == OperandKind.Register && src2.Kind == OperandKind.Register);
|
||||
Debug.Assert(src3.Kind == OperandKind.Register || src3.Kind == OperandKind.Memory);
|
||||
Debug.Assert(src3.Kind is OperandKind.Register or OperandKind.Memory);
|
||||
|
||||
EnsureSameType(dest, src1, src2, src3);
|
||||
Debug.Assert(dest.Type == OperandType.V128);
|
||||
@@ -788,7 +787,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
Operand dest = operation.Destination;
|
||||
Operand source = operation.GetSource(0);
|
||||
|
||||
Debug.Assert(dest.Type == OperandType.FP32 || dest.Type == OperandType.FP64);
|
||||
Debug.Assert(dest.Type is OperandType.FP32 or OperandType.FP64);
|
||||
|
||||
if (dest.Type == OperandType.FP32)
|
||||
{
|
||||
@@ -1723,7 +1722,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.Assert(op1.Kind == OperandKind.Register || op1.Kind == OperandKind.Memory);
|
||||
Debug.Assert(op1.Kind is OperandKind.Register or OperandKind.Memory);
|
||||
Debug.Assert(op1.Kind == op2.Kind);
|
||||
Debug.Assert(op1.Value == op2.Value);
|
||||
}
|
||||
|
||||
@@ -312,9 +312,9 @@ namespace ARMeilleure.CodeGen.X86
|
||||
|
||||
case Instruction.Extended:
|
||||
{
|
||||
bool isBlend = node.Intrinsic == Intrinsic.X86Blendvpd ||
|
||||
node.Intrinsic == Intrinsic.X86Blendvps ||
|
||||
node.Intrinsic == Intrinsic.X86Pblendvb;
|
||||
bool isBlend = node.Intrinsic is Intrinsic.X86Blendvpd
|
||||
or Intrinsic.X86Blendvps
|
||||
or Intrinsic.X86Pblendvb;
|
||||
|
||||
// BLENDVPD, BLENDVPS, PBLENDVB last operand is always implied to be XMM0 when VEX is not supported.
|
||||
// SHA256RNDS2 always has an implied XMM0 as a last operand.
|
||||
@@ -513,8 +513,8 @@ namespace ARMeilleure.CodeGen.X86
|
||||
Operand dest = node.Destination;
|
||||
Operand source = node.GetSource(0);
|
||||
|
||||
Debug.Assert(dest.Type == OperandType.FP32 ||
|
||||
dest.Type == OperandType.FP64, $"Invalid destination type \"{dest.Type}\".");
|
||||
Debug.Assert(dest.Type is OperandType.FP32 or OperandType.FP64,
|
||||
$"Invalid destination type \"{dest.Type}\".");
|
||||
|
||||
Operation currentNode = node;
|
||||
|
||||
@@ -761,7 +761,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
|
||||
var compType = (Comparison)comp.AsInt32();
|
||||
|
||||
return compType == Comparison.Equal || compType == Comparison.NotEqual;
|
||||
return compType is Comparison.Equal or Comparison.NotEqual;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -248,12 +248,12 @@ namespace ARMeilleure.CodeGen.X86
|
||||
|
||||
private static bool IsMemoryLoadOrStore(Instruction inst)
|
||||
{
|
||||
return inst == Instruction.Load ||
|
||||
inst == Instruction.Load16 ||
|
||||
inst == Instruction.Load8 ||
|
||||
inst == Instruction.Store ||
|
||||
inst == Instruction.Store16 ||
|
||||
inst == Instruction.Store8;
|
||||
return inst is Instruction.Load
|
||||
or Instruction.Load16
|
||||
or Instruction.Load8
|
||||
or Instruction.Store
|
||||
or Instruction.Store16
|
||||
or Instruction.Store8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace ARMeilleure.Common
|
||||
private List<PageInfo> _pages;
|
||||
private readonly ulong _pageSize;
|
||||
private readonly uint _pageCount;
|
||||
private readonly List<IntPtr> _extras;
|
||||
private readonly List<nint> _extras;
|
||||
|
||||
public ArenaAllocator(uint pageSize, uint pageCount)
|
||||
{
|
||||
@@ -64,7 +64,7 @@ namespace ARMeilleure.Common
|
||||
{
|
||||
void* extra = NativeAllocator.Instance.Allocate(size);
|
||||
|
||||
_extras.Add((IntPtr)extra);
|
||||
_extras.Add((nint)extra);
|
||||
|
||||
return extra;
|
||||
}
|
||||
@@ -114,7 +114,7 @@ namespace ARMeilleure.Common
|
||||
}
|
||||
|
||||
// Free extra blocks that are not page-sized
|
||||
foreach (IntPtr ptr in _extras)
|
||||
foreach (nint ptr in _extras)
|
||||
{
|
||||
NativeAllocator.Instance.Free((void*)ptr);
|
||||
}
|
||||
@@ -173,7 +173,7 @@ namespace ARMeilleure.Common
|
||||
NativeAllocator.Instance.Free(info.Pointer);
|
||||
}
|
||||
|
||||
foreach (IntPtr ptr in _extras)
|
||||
foreach (nint ptr in _extras)
|
||||
{
|
||||
NativeAllocator.Instance.Free((void*)ptr);
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace ARMeilleure.Common
|
||||
private int _freeHint;
|
||||
private readonly int _pageCapacity; // Number of entries per page.
|
||||
private readonly int _pageLogCapacity;
|
||||
private readonly Dictionary<int, IntPtr> _pages;
|
||||
private readonly Dictionary<int, nint> _pages;
|
||||
private readonly BitMap _allocated;
|
||||
|
||||
/// <summary>
|
||||
@@ -41,7 +41,7 @@ namespace ARMeilleure.Common
|
||||
}
|
||||
|
||||
_allocated = new BitMap(NativeAllocator.Instance);
|
||||
_pages = new Dictionary<int, IntPtr>();
|
||||
_pages = new Dictionary<int, nint>();
|
||||
_pageLogCapacity = BitOperations.Log2((uint)(pageSize / sizeof(TEntry)));
|
||||
_pageCapacity = 1 << _pageLogCapacity;
|
||||
}
|
||||
@@ -138,9 +138,9 @@ namespace ARMeilleure.Common
|
||||
{
|
||||
var pageIndex = (int)((uint)(index & ~(_pageCapacity - 1)) >> _pageLogCapacity);
|
||||
|
||||
if (!_pages.TryGetValue(pageIndex, out IntPtr page))
|
||||
if (!_pages.TryGetValue(pageIndex, out nint page))
|
||||
{
|
||||
page = (IntPtr)NativeAllocator.Instance.Allocate((uint)sizeof(TEntry) * (uint)_pageCapacity);
|
||||
page = (nint)NativeAllocator.Instance.Allocate((uint)sizeof(TEntry) * (uint)_pageCapacity);
|
||||
|
||||
_pages.Add(pageIndex, page);
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace ARMeilleure.Common
|
||||
|
||||
public override void* Allocate(ulong size)
|
||||
{
|
||||
void* result = (void*)Marshal.AllocHGlobal((IntPtr)size);
|
||||
void* result = (void*)Marshal.AllocHGlobal((nint)size);
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
@@ -21,7 +21,7 @@ namespace ARMeilleure.Common
|
||||
|
||||
public override void Free(void* block)
|
||||
{
|
||||
Marshal.FreeHGlobal((IntPtr)block);
|
||||
Marshal.FreeHGlobal((nint)block);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -254,8 +254,7 @@ namespace ARMeilleure.Decoders
|
||||
}
|
||||
|
||||
// Compare and branch instructions are always conditional.
|
||||
if (opCode.Instruction.Name == InstName.Cbz ||
|
||||
opCode.Instruction.Name == InstName.Cbnz)
|
||||
if (opCode.Instruction.Name is InstName.Cbz or InstName.Cbnz)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -284,7 +283,7 @@ namespace ARMeilleure.Decoders
|
||||
// register (Rt == 15 or (mask & (1 << 15)) != 0), and cases where there is
|
||||
// a write back to PC (wback == true && Rn == 15), however the later may
|
||||
// be "undefined" depending on the CPU, so compilers should not produce that.
|
||||
if (opCode is IOpCode32Mem || opCode is IOpCode32MemMult)
|
||||
if (opCode is IOpCode32Mem or IOpCode32MemMult)
|
||||
{
|
||||
int rt, rn;
|
||||
|
||||
@@ -326,15 +325,12 @@ namespace ARMeilleure.Decoders
|
||||
}
|
||||
|
||||
// Explicit branch instructions.
|
||||
return opCode is IOpCode32BImm ||
|
||||
opCode is IOpCode32BReg;
|
||||
return opCode is IOpCode32BImm or IOpCode32BReg;
|
||||
}
|
||||
|
||||
private static bool IsCall(OpCode opCode)
|
||||
{
|
||||
return opCode.Instruction.Name == InstName.Bl ||
|
||||
opCode.Instruction.Name == InstName.Blr ||
|
||||
opCode.Instruction.Name == InstName.Blx;
|
||||
return opCode.Instruction.Name is InstName.Bl or InstName.Blr or InstName.Blx;
|
||||
}
|
||||
|
||||
private static bool IsException(OpCode opCode)
|
||||
@@ -344,9 +340,7 @@ namespace ARMeilleure.Decoders
|
||||
|
||||
private static bool IsTrap(OpCode opCode)
|
||||
{
|
||||
return opCode.Instruction.Name == InstName.Brk ||
|
||||
opCode.Instruction.Name == InstName.Trap ||
|
||||
opCode.Instruction.Name == InstName.Und;
|
||||
return opCode.Instruction.Name is InstName.Brk or InstName.Trap or InstName.Und;
|
||||
}
|
||||
|
||||
public static OpCode DecodeOpCode(IMemoryManager memory, ulong address, ExecutionMode mode)
|
||||
|
||||
@@ -28,8 +28,7 @@ namespace ARMeilleure.Decoders
|
||||
MemOp type = WBack ? (MemOp)((opCode >> 10) & 3) : MemOp.Unsigned;
|
||||
|
||||
PostIdx = type == MemOp.PostIndexed;
|
||||
Unscaled = type == MemOp.Unscaled ||
|
||||
type == MemOp.Unprivileged;
|
||||
Unscaled = type is MemOp.Unscaled or MemOp.Unprivileged;
|
||||
|
||||
// Unscaled and Unprivileged doesn't write back,
|
||||
// but they do use the 9-bits Signed Immediate.
|
||||
|
||||
@@ -235,8 +235,7 @@ namespace ARMeilleure.Diagnostics
|
||||
{
|
||||
_builder.Append('.').Append(operation.Intrinsic);
|
||||
}
|
||||
else if (operation.Instruction == Instruction.BranchIf ||
|
||||
operation.Instruction == Instruction.Compare)
|
||||
else if (operation.Instruction is Instruction.BranchIf or Instruction.Compare)
|
||||
{
|
||||
comparison = true;
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
context.LoadFromContext();
|
||||
|
||||
context.Return(Const(op.Address));
|
||||
InstEmitFlowHelper.EmitReturn(context, Const(op.Address));
|
||||
}
|
||||
|
||||
public static void Svc(ArmEmitterContext context)
|
||||
@@ -49,7 +49,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
context.LoadFromContext();
|
||||
|
||||
context.Return(Const(op.Address));
|
||||
InstEmitFlowHelper.EmitReturn(context, Const(op.Address));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
context.LoadFromContext();
|
||||
|
||||
context.Return(Const(context.CurrOp.Address));
|
||||
InstEmitFlowHelper.EmitReturn(context, Const(context.CurrOp.Address));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
OpCodeBReg op = (OpCodeBReg)context.CurrOp;
|
||||
|
||||
context.Return(GetIntOrZR(context, op.Rn));
|
||||
EmitReturn(context, GetIntOrZR(context, op.Rn));
|
||||
}
|
||||
|
||||
public static void Tbnz(ArmEmitterContext context) => EmitTb(context, onNotZero: true);
|
||||
|
||||
@@ -12,6 +12,10 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
static class InstEmitFlowHelper
|
||||
{
|
||||
// How many calls we can have in our call stack before we give up and return to the dispatcher.
|
||||
// This prevents stack overflows caused by deep recursive calls.
|
||||
private const int MaxCallDepth = 200;
|
||||
|
||||
public static void EmitCondBranch(ArmEmitterContext context, Operand target, Condition cond)
|
||||
{
|
||||
if (cond != Condition.Al)
|
||||
@@ -142,6 +146,12 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void EmitCall(ArmEmitterContext context, ulong immediate)
|
||||
{
|
||||
if (context.IsSingleStep)
|
||||
{
|
||||
context.Return(Const(immediate));
|
||||
return;
|
||||
}
|
||||
|
||||
bool isRecursive = immediate == context.EntryAddress;
|
||||
|
||||
if (isRecursive)
|
||||
@@ -156,12 +166,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void EmitVirtualCall(ArmEmitterContext context, Operand target)
|
||||
{
|
||||
EmitTableBranch(context, target, isJump: false);
|
||||
}
|
||||
|
||||
public static void EmitVirtualJump(ArmEmitterContext context, Operand target, bool isReturn)
|
||||
{
|
||||
if (isReturn)
|
||||
if (context.IsSingleStep)
|
||||
{
|
||||
if (target.Type == OperandType.I32)
|
||||
{
|
||||
@@ -171,11 +176,36 @@ namespace ARMeilleure.Instructions
|
||||
context.Return(target);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitTableBranch(context, target, isJump: false);
|
||||
}
|
||||
}
|
||||
|
||||
public static void EmitVirtualJump(ArmEmitterContext context, Operand target, bool isReturn)
|
||||
{
|
||||
if (isReturn || context.IsSingleStep)
|
||||
{
|
||||
EmitReturn(context, target);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitTableBranch(context, target, isJump: true);
|
||||
}
|
||||
}
|
||||
|
||||
public static void EmitReturn(ArmEmitterContext context, Operand target)
|
||||
{
|
||||
Operand nativeContext = context.LoadArgument(OperandType.I64, 0);
|
||||
DecreaseCallDepth(context, nativeContext);
|
||||
|
||||
if (target.Type == OperandType.I32)
|
||||
{
|
||||
target = context.ZeroExtend32(OperandType.I64, target);
|
||||
}
|
||||
|
||||
context.Return(target);
|
||||
}
|
||||
|
||||
private static void EmitTableBranch(ArmEmitterContext context, Operand guestAddress, bool isJump)
|
||||
{
|
||||
context.StoreToContext();
|
||||
@@ -238,6 +268,8 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
if (isJump)
|
||||
{
|
||||
DecreaseCallDepth(context, nativeContext);
|
||||
|
||||
context.Tailcall(hostAddress, nativeContext);
|
||||
}
|
||||
else
|
||||
@@ -259,8 +291,42 @@ namespace ARMeilleure.Instructions
|
||||
Operand lblContinue = context.GetLabel(nextAddr.Value);
|
||||
context.BranchIf(lblContinue, returnAddress, nextAddr, Comparison.Equal, BasicBlockFrequency.Cold);
|
||||
|
||||
DecreaseCallDepth(context, nativeContext);
|
||||
|
||||
context.Return(returnAddress);
|
||||
}
|
||||
}
|
||||
|
||||
public static void EmitCallDepthCheckAndIncrement(EmitterContext context, Operand guestAddress)
|
||||
{
|
||||
if (!Optimizations.EnableDeepCallRecursionProtection)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Operand nativeContext = context.LoadArgument(OperandType.I64, 0);
|
||||
Operand callDepthAddr = context.Add(nativeContext, Const((ulong)NativeContext.GetCallDepthOffset()));
|
||||
Operand currentCallDepth = context.Load(OperandType.I32, callDepthAddr);
|
||||
Operand lblDoCall = Label();
|
||||
|
||||
context.BranchIf(lblDoCall, currentCallDepth, Const(MaxCallDepth), Comparison.LessUI);
|
||||
context.Store(callDepthAddr, context.Subtract(currentCallDepth, Const(1)));
|
||||
context.Return(guestAddress);
|
||||
|
||||
context.MarkLabel(lblDoCall);
|
||||
context.Store(callDepthAddr, context.Add(currentCallDepth, Const(1)));
|
||||
}
|
||||
|
||||
private static void DecreaseCallDepth(EmitterContext context, Operand nativeContext)
|
||||
{
|
||||
if (!Optimizations.EnableDeepCallRecursionProtection)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Operand callDepthAddr = context.Add(nativeContext, Const((ulong)NativeContext.GetCallDepthOffset()));
|
||||
Operand currentCallDepth = context.Load(OperandType.I32, callDepthAddr);
|
||||
context.Store(callDepthAddr, context.Subtract(currentCallDepth, Const(1)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,7 +140,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
if (pair)
|
||||
{
|
||||
Debug.Assert(op.Size == 2 || op.Size == 3, "Invalid size for pairwise store.");
|
||||
Debug.Assert(op.Size is 2 or 3, "Invalid size for pairwise store.");
|
||||
|
||||
Operand t2 = GetIntOrZR(context, op.Rt2);
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
Operand value = GetInt(context, rt);
|
||||
|
||||
if (ext == Extension.Sx32 || ext == Extension.Sx64)
|
||||
if (ext is Extension.Sx32 or Extension.Sx64)
|
||||
{
|
||||
OperandType destType = ext == Extension.Sx64 ? OperandType.I64 : OperandType.I32;
|
||||
|
||||
@@ -124,8 +124,7 @@ namespace ARMeilleure.Instructions
|
||||
private static bool IsSimd(ArmEmitterContext context)
|
||||
{
|
||||
return context.CurrOp is IOpCodeSimd &&
|
||||
!(context.CurrOp is OpCodeSimdMemMs ||
|
||||
context.CurrOp is OpCodeSimdMemSs);
|
||||
!(context.CurrOp is OpCodeSimdMemMs or OpCodeSimdMemSs);
|
||||
}
|
||||
|
||||
public static Operand EmitReadInt(ArmEmitterContext context, Operand address, int size)
|
||||
|
||||
@@ -1119,7 +1119,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
private static Operand EmitFPConvert(ArmEmitterContext context, Operand value, int size, bool signed)
|
||||
{
|
||||
Debug.Assert(value.Type == OperandType.I32 || value.Type == OperandType.I64);
|
||||
Debug.Assert(value.Type is OperandType.I32 or OperandType.I64);
|
||||
Debug.Assert((uint)size < 2);
|
||||
|
||||
OperandType type = size == 0 ? OperandType.FP32 : OperandType.FP64;
|
||||
@@ -1136,7 +1136,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
private static Operand EmitScalarFcvts(ArmEmitterContext context, Operand value, int fBits)
|
||||
{
|
||||
Debug.Assert(value.Type == OperandType.FP32 || value.Type == OperandType.FP64);
|
||||
Debug.Assert(value.Type is OperandType.FP32 or OperandType.FP64);
|
||||
|
||||
value = EmitF2iFBitsMul(context, value, fBits);
|
||||
|
||||
@@ -1160,7 +1160,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
private static Operand EmitScalarFcvtu(ArmEmitterContext context, Operand value, int fBits)
|
||||
{
|
||||
Debug.Assert(value.Type == OperandType.FP32 || value.Type == OperandType.FP64);
|
||||
Debug.Assert(value.Type is OperandType.FP32 or OperandType.FP64);
|
||||
|
||||
value = EmitF2iFBitsMul(context, value, fBits);
|
||||
|
||||
@@ -1184,7 +1184,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
private static Operand EmitF2iFBitsMul(ArmEmitterContext context, Operand value, int fBits)
|
||||
{
|
||||
Debug.Assert(value.Type == OperandType.FP32 || value.Type == OperandType.FP64);
|
||||
Debug.Assert(value.Type is OperandType.FP32 or OperandType.FP64);
|
||||
|
||||
if (fBits == 0)
|
||||
{
|
||||
@@ -1203,7 +1203,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
private static Operand EmitI2fFBitsMul(ArmEmitterContext context, Operand value, int fBits)
|
||||
{
|
||||
Debug.Assert(value.Type == OperandType.FP32 || value.Type == OperandType.FP64);
|
||||
Debug.Assert(value.Type is OperandType.FP32 or OperandType.FP64);
|
||||
|
||||
if (fBits == 0)
|
||||
{
|
||||
|
||||
@@ -635,7 +635,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
private static Operand EmitFPConvert(ArmEmitterContext context, Operand value, OperandType type, bool signed)
|
||||
{
|
||||
Debug.Assert(value.Type == OperandType.I32 || value.Type == OperandType.I64);
|
||||
Debug.Assert(value.Type is OperandType.I32 or OperandType.I64);
|
||||
|
||||
if (signed)
|
||||
{
|
||||
|
||||
@@ -363,7 +363,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static Operand EmitCountSetBits8(ArmEmitterContext context, Operand op) // "size" is 8 (SIMD&FP Inst.).
|
||||
{
|
||||
Debug.Assert(op.Type == OperandType.I32 || op.Type == OperandType.I64);
|
||||
Debug.Assert(op.Type is OperandType.I32 or OperandType.I64);
|
||||
|
||||
Operand op0 = context.Subtract(op, context.BitwiseAnd(context.ShiftRightUI(op, Const(1)), Const(op.Type, 0x55L)));
|
||||
|
||||
@@ -489,7 +489,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static Operand EmitRoundByRMode(ArmEmitterContext context, Operand op)
|
||||
{
|
||||
Debug.Assert(op.Type == OperandType.FP32 || op.Type == OperandType.FP64);
|
||||
Debug.Assert(op.Type is OperandType.FP32 or OperandType.FP64);
|
||||
|
||||
Operand lbl1 = Label();
|
||||
Operand lbl2 = Label();
|
||||
@@ -1676,7 +1676,7 @@ namespace ARMeilleure.Instructions
|
||||
int eSize = 8 << size;
|
||||
|
||||
Debug.Assert(op.Type == OperandType.I64);
|
||||
Debug.Assert(eSize == 8 || eSize == 16 || eSize == 32 || eSize == 64);
|
||||
Debug.Assert(eSize is 8 or 16 or 32 or 64);
|
||||
|
||||
Operand lbl1 = Label();
|
||||
Operand lblEnd = Label();
|
||||
@@ -1709,7 +1709,7 @@ namespace ARMeilleure.Instructions
|
||||
int eSize = 8 << size;
|
||||
|
||||
Debug.Assert(op.Type == OperandType.I64);
|
||||
Debug.Assert(eSize == 8 || eSize == 16 || eSize == 32 || eSize == 64);
|
||||
Debug.Assert(eSize is 8 or 16 or 32 or 64);
|
||||
|
||||
Operand lblEnd = Label();
|
||||
|
||||
@@ -1735,7 +1735,7 @@ namespace ARMeilleure.Instructions
|
||||
int eSizeDst = 8 << sizeDst;
|
||||
|
||||
Debug.Assert(op.Type == OperandType.I64);
|
||||
Debug.Assert(eSizeDst == 8 || eSizeDst == 16 || eSizeDst == 32);
|
||||
Debug.Assert(eSizeDst is 8 or 16 or 32);
|
||||
|
||||
Operand lbl1 = Label();
|
||||
Operand lblEnd = Label();
|
||||
@@ -1768,7 +1768,7 @@ namespace ARMeilleure.Instructions
|
||||
int eSizeDst = 8 << sizeDst;
|
||||
|
||||
Debug.Assert(op.Type == OperandType.I64);
|
||||
Debug.Assert(eSizeDst == 8 || eSizeDst == 16 || eSizeDst == 32);
|
||||
Debug.Assert(eSizeDst is 8 or 16 or 32);
|
||||
|
||||
Operand lblEnd = Label();
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
Debug.Assert(type != OperandType.V128);
|
||||
|
||||
if (type == OperandType.FP64 || type == OperandType.I64)
|
||||
if (type is OperandType.FP64 or OperandType.I64)
|
||||
{
|
||||
// From dreg.
|
||||
return context.VectorExtract(type, GetVecA32(reg >> 1), reg & 1);
|
||||
@@ -48,7 +48,7 @@ namespace ARMeilleure.Instructions
|
||||
Debug.Assert(value.Type != OperandType.V128);
|
||||
|
||||
Operand vec, insert;
|
||||
if (value.Type == OperandType.FP64 || value.Type == OperandType.I64)
|
||||
if (value.Type is OperandType.FP64 or OperandType.I64)
|
||||
{
|
||||
// From dreg.
|
||||
vec = GetVecA32(reg >> 1);
|
||||
@@ -71,7 +71,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void InsertScalar16(ArmEmitterContext context, int reg, bool top, Operand value)
|
||||
{
|
||||
Debug.Assert(value.Type == OperandType.FP32 || value.Type == OperandType.I32);
|
||||
Debug.Assert(value.Type is OperandType.FP32 or OperandType.I32);
|
||||
|
||||
Operand vec, insert;
|
||||
vec = GetVecA32(reg >> 2);
|
||||
|
||||
@@ -1634,7 +1634,7 @@ namespace ARMeilleure.Instructions
|
||||
int eSize = 8 << size;
|
||||
|
||||
Debug.Assert(op.Type == OperandType.I64);
|
||||
Debug.Assert(eSize == 8 || eSize == 16 || eSize == 32 || eSize == 64);
|
||||
Debug.Assert(eSize is 8 or 16 or 32 or 64);
|
||||
|
||||
Operand res = context.AllocateLocal(OperandType.I64);
|
||||
|
||||
@@ -1657,7 +1657,7 @@ namespace ARMeilleure.Instructions
|
||||
int eSize = 8 << size;
|
||||
|
||||
Debug.Assert(op.Type == OperandType.I64);
|
||||
Debug.Assert(eSize == 8 || eSize == 16 || eSize == 32 || eSize == 64);
|
||||
Debug.Assert(eSize is 8 or 16 or 32 or 64);
|
||||
|
||||
Operand lblEnd = Label();
|
||||
|
||||
@@ -1732,7 +1732,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
Debug.Assert(op.Type == OperandType.I64);
|
||||
Debug.Assert(shiftLsB.Type == OperandType.I32);
|
||||
Debug.Assert(eSize == 8 || eSize == 16 || eSize == 32 || eSize == 64);
|
||||
Debug.Assert(eSize is 8 or 16 or 32 or 64);
|
||||
|
||||
Operand lbl1 = Label();
|
||||
Operand lblEnd = Label();
|
||||
@@ -1769,7 +1769,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
Debug.Assert(op.Type == OperandType.I64);
|
||||
Debug.Assert(shiftLsB.Type == OperandType.I32);
|
||||
Debug.Assert(eSize == 8 || eSize == 16 || eSize == 32 || eSize == 64);
|
||||
Debug.Assert(eSize is 8 or 16 or 32 or 64);
|
||||
|
||||
Operand lbl1 = Label();
|
||||
Operand lbl2 = Label();
|
||||
|
||||
@@ -322,7 +322,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
float result;
|
||||
|
||||
if (type == FPType.SNaN || type == FPType.QNaN)
|
||||
if (type is FPType.SNaN or FPType.QNaN)
|
||||
{
|
||||
if ((context.Fpcr & FPCR.Dn) != 0)
|
||||
{
|
||||
@@ -498,7 +498,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
double result;
|
||||
|
||||
if (type == FPType.SNaN || type == FPType.QNaN)
|
||||
if (type is FPType.SNaN or FPType.QNaN)
|
||||
{
|
||||
if ((context.Fpcr & FPCR.Dn) != 0)
|
||||
{
|
||||
@@ -676,7 +676,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
ushort resultBits;
|
||||
|
||||
if (type == FPType.SNaN || type == FPType.QNaN)
|
||||
if (type is FPType.SNaN or FPType.QNaN)
|
||||
{
|
||||
if (altHp)
|
||||
{
|
||||
@@ -1522,7 +1522,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
float result;
|
||||
|
||||
if (type == FPType.SNaN || type == FPType.QNaN)
|
||||
if (type is FPType.SNaN or FPType.QNaN)
|
||||
{
|
||||
result = FPProcessNaN(type, op, context, fpcr);
|
||||
}
|
||||
@@ -1689,7 +1689,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
float result;
|
||||
|
||||
if (type == FPType.SNaN || type == FPType.QNaN)
|
||||
if (type is FPType.SNaN or FPType.QNaN)
|
||||
{
|
||||
result = FPProcessNaN(type, op, context, fpcr);
|
||||
}
|
||||
@@ -1726,7 +1726,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
float result;
|
||||
|
||||
if (type == FPType.SNaN || type == FPType.QNaN)
|
||||
if (type is FPType.SNaN or FPType.QNaN)
|
||||
{
|
||||
result = FPProcessNaN(type, op, context, fpcr);
|
||||
}
|
||||
@@ -1920,7 +1920,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
float result;
|
||||
|
||||
if (type == FPType.SNaN || type == FPType.QNaN)
|
||||
if (type is FPType.SNaN or FPType.QNaN)
|
||||
{
|
||||
result = FPProcessNaN(type, op, context, fpcr);
|
||||
}
|
||||
@@ -2211,7 +2211,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
ushort resultBits;
|
||||
|
||||
if (type == FPType.SNaN || type == FPType.QNaN)
|
||||
if (type is FPType.SNaN or FPType.QNaN)
|
||||
{
|
||||
if (altHp)
|
||||
{
|
||||
@@ -3057,7 +3057,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
double result;
|
||||
|
||||
if (type == FPType.SNaN || type == FPType.QNaN)
|
||||
if (type is FPType.SNaN or FPType.QNaN)
|
||||
{
|
||||
result = FPProcessNaN(type, op, context, fpcr);
|
||||
}
|
||||
@@ -3224,7 +3224,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
double result;
|
||||
|
||||
if (type == FPType.SNaN || type == FPType.QNaN)
|
||||
if (type is FPType.SNaN or FPType.QNaN)
|
||||
{
|
||||
result = FPProcessNaN(type, op, context, fpcr);
|
||||
}
|
||||
@@ -3261,7 +3261,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
double result;
|
||||
|
||||
if (type == FPType.SNaN || type == FPType.QNaN)
|
||||
if (type is FPType.SNaN or FPType.QNaN)
|
||||
{
|
||||
result = FPProcessNaN(type, op, context, fpcr);
|
||||
}
|
||||
@@ -3455,7 +3455,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
double result;
|
||||
|
||||
if (type == FPType.SNaN || type == FPType.QNaN)
|
||||
if (type is FPType.SNaN or FPType.QNaN)
|
||||
{
|
||||
result = FPProcessNaN(type, op, context, fpcr);
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace ARMeilleure.IntermediateRepresentation
|
||||
/// <exception cref="ArgumentException"><typeparamref name="T"/> is not pointer sized.</exception>
|
||||
public IntrusiveList()
|
||||
{
|
||||
if (Unsafe.SizeOf<T>() != IntPtr.Size)
|
||||
if (Unsafe.SizeOf<T>() != nint.Size)
|
||||
{
|
||||
throw new ArgumentException("T must be a reference type or a pointer sized struct.");
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
@@ -24,7 +23,7 @@ namespace ARMeilleure.IntermediateRepresentation
|
||||
{
|
||||
Debug.Assert(operand.Kind == OperandKind.Memory);
|
||||
|
||||
_data = (Data*)Unsafe.As<Operand, IntPtr>(ref operand);
|
||||
_data = (Data*)Unsafe.As<Operand, nint>(ref operand);
|
||||
}
|
||||
|
||||
public Operand BaseAddress
|
||||
|
||||
@@ -446,7 +446,7 @@ namespace ARMeilleure.IntermediateRepresentation
|
||||
Data* data = null;
|
||||
|
||||
// If constant or register, then try to look up in the intern table before allocating.
|
||||
if (kind == OperandKind.Constant || kind == OperandKind.Register)
|
||||
if (kind is OperandKind.Constant or OperandKind.Register)
|
||||
{
|
||||
uint hash = (uint)HashCode.Combine(kind, type, value);
|
||||
|
||||
|
||||
@@ -16,8 +16,7 @@ namespace ARMeilleure.IntermediateRepresentation
|
||||
{
|
||||
public static bool IsInteger(this OperandType type)
|
||||
{
|
||||
return type == OperandType.I32 ||
|
||||
type == OperandType.I64;
|
||||
return type is OperandType.I32 or OperandType.I64;
|
||||
}
|
||||
|
||||
public static RegisterType ToRegisterType(this OperandType type)
|
||||
|
||||
@@ -228,7 +228,7 @@ namespace ARMeilleure.IntermediateRepresentation
|
||||
|
||||
public readonly override int GetHashCode()
|
||||
{
|
||||
return HashCode.Combine((IntPtr)_data);
|
||||
return HashCode.Combine((nint)_data);
|
||||
}
|
||||
|
||||
public static bool operator ==(Operation a, Operation b)
|
||||
|
||||
@@ -4,7 +4,7 @@ namespace ARMeilleure.Memory
|
||||
{
|
||||
public interface IJitMemoryBlock : IDisposable
|
||||
{
|
||||
IntPtr Pointer { get; }
|
||||
nint Pointer { get; }
|
||||
|
||||
void Commit(ulong offset, ulong size);
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace ARMeilleure.Memory
|
||||
{
|
||||
int AddressSpaceBits { get; }
|
||||
|
||||
IntPtr PageTablePointer { get; }
|
||||
nint PageTablePointer { get; }
|
||||
|
||||
MemoryManagerType Type { get; }
|
||||
|
||||
|
||||
@@ -47,12 +47,12 @@ namespace ARMeilleure.Memory
|
||||
{
|
||||
public static bool IsHostMapped(this MemoryManagerType type)
|
||||
{
|
||||
return type == MemoryManagerType.HostMapped || type == MemoryManagerType.HostMappedUnsafe;
|
||||
return type is MemoryManagerType.HostMapped or MemoryManagerType.HostMappedUnsafe;
|
||||
}
|
||||
|
||||
public static bool IsHostTracked(this MemoryManagerType type)
|
||||
{
|
||||
return type == MemoryManagerType.HostTracked || type == MemoryManagerType.HostTrackedUnsafe;
|
||||
return type is MemoryManagerType.HostTracked or MemoryManagerType.HostTrackedUnsafe;
|
||||
}
|
||||
|
||||
public static bool IsHostMappedOrTracked(this MemoryManagerType type)
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace ARMeilleure.Memory
|
||||
public IJitMemoryBlock Block { get; }
|
||||
public IJitMemoryAllocator Allocator { get; }
|
||||
|
||||
public IntPtr Pointer => Block.Pointer;
|
||||
public nint Pointer => Block.Pointer;
|
||||
|
||||
private readonly ulong _maxSize;
|
||||
private readonly ulong _sizeGranularity;
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Versioning;
|
||||
|
||||
@@ -8,6 +7,6 @@ namespace ARMeilleure.Native
|
||||
static partial class JitSupportDarwin
|
||||
{
|
||||
[LibraryImport("libarmeilleure-jitsupport", EntryPoint = "armeilleure_jit_memcpy")]
|
||||
public static partial void Copy(IntPtr dst, IntPtr src, ulong n);
|
||||
public static partial void Copy(nint dst, nint src, ulong n);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,8 @@ namespace ARMeilleure
|
||||
|
||||
public static bool AllowLcqInFunctionTable { get; set; } = true;
|
||||
public static bool UseUnmanagedDispatchLoop { get; set; } = true;
|
||||
public static bool EnableDebugging { get; set; } = false;
|
||||
public static bool EnableDeepCallRecursionProtection { get; set; } = true;
|
||||
|
||||
public static bool UseAdvSimdIfAvailable { get; set; } = true;
|
||||
public static bool UseArm64AesIfAvailable { get; set; } = true;
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace ARMeilleure.Signal
|
||||
|
||||
private const uint EXCEPTION_ACCESS_VIOLATION = 0xc0000005;
|
||||
|
||||
private static Operand EmitGenericRegionCheck(EmitterContext context, IntPtr signalStructPtr, Operand faultAddress, Operand isWrite, int rangeStructSize)
|
||||
private static Operand EmitGenericRegionCheck(EmitterContext context, nint signalStructPtr, Operand faultAddress, Operand isWrite, int rangeStructSize)
|
||||
{
|
||||
Operand inRegionLocal = context.AllocateLocal(OperandType.I32);
|
||||
context.Copy(inRegionLocal, Const(0));
|
||||
@@ -155,7 +155,7 @@ namespace ARMeilleure.Signal
|
||||
throw new PlatformNotSupportedException();
|
||||
}
|
||||
|
||||
public static byte[] GenerateUnixSignalHandler(IntPtr signalStructPtr, int rangeStructSize)
|
||||
public static byte[] GenerateUnixSignalHandler(nint signalStructPtr, int rangeStructSize)
|
||||
{
|
||||
EmitterContext context = new();
|
||||
|
||||
@@ -203,7 +203,7 @@ namespace ARMeilleure.Signal
|
||||
return Compiler.Compile(cfg, argTypes, OperandType.None, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Code;
|
||||
}
|
||||
|
||||
public static byte[] GenerateWindowsSignalHandler(IntPtr signalStructPtr, int rangeStructSize)
|
||||
public static byte[] GenerateWindowsSignalHandler(nint signalStructPtr, int rangeStructSize)
|
||||
{
|
||||
EmitterContext context = new();
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
||||
@@ -16,7 +15,7 @@ namespace ARMeilleure.Signal
|
||||
{
|
||||
public delegate bool DebugPartialUnmap();
|
||||
public delegate int DebugThreadLocalMapGetOrReserve(int threadId, int initialState);
|
||||
public delegate void DebugNativeWriteLoop(IntPtr nativeWriteLoopPtr, IntPtr writePtr);
|
||||
public delegate void DebugNativeWriteLoop(nint nativeWriteLoopPtr, nint writePtr);
|
||||
|
||||
public static DebugPartialUnmap GenerateDebugPartialUnmap()
|
||||
{
|
||||
@@ -35,7 +34,7 @@ namespace ARMeilleure.Signal
|
||||
return Compiler.Compile(cfg, argTypes, OperandType.I32, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<DebugPartialUnmap>();
|
||||
}
|
||||
|
||||
public static DebugThreadLocalMapGetOrReserve GenerateDebugThreadLocalMapGetOrReserve(IntPtr structPtr)
|
||||
public static DebugThreadLocalMapGetOrReserve GenerateDebugThreadLocalMapGetOrReserve(nint structPtr)
|
||||
{
|
||||
EmitterContext context = new();
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.Translation;
|
||||
using Ryujinx.Common.Memory.PartialUnmaps;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
||||
@@ -13,18 +12,18 @@ namespace ARMeilleure.Signal
|
||||
internal static partial class WindowsPartialUnmapHandler
|
||||
{
|
||||
[LibraryImport("kernel32.dll", SetLastError = true, EntryPoint = "LoadLibraryA")]
|
||||
private static partial IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string lpFileName);
|
||||
private static partial nint LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string lpFileName);
|
||||
|
||||
[LibraryImport("kernel32.dll", SetLastError = true)]
|
||||
private static partial IntPtr GetProcAddress(IntPtr hModule, [MarshalAs(UnmanagedType.LPStr)] string procName);
|
||||
private static partial nint GetProcAddress(nint hModule, [MarshalAs(UnmanagedType.LPStr)] string procName);
|
||||
|
||||
private static IntPtr _getCurrentThreadIdPtr;
|
||||
private static nint _getCurrentThreadIdPtr;
|
||||
|
||||
public static IntPtr GetCurrentThreadIdFunc()
|
||||
public static nint GetCurrentThreadIdFunc()
|
||||
{
|
||||
if (_getCurrentThreadIdPtr == IntPtr.Zero)
|
||||
if (_getCurrentThreadIdPtr == nint.Zero)
|
||||
{
|
||||
IntPtr handle = LoadLibrary("kernel32.dll");
|
||||
nint handle = LoadLibrary("kernel32.dll");
|
||||
|
||||
_getCurrentThreadIdPtr = GetProcAddress(handle, "GetCurrentThreadId");
|
||||
}
|
||||
@@ -34,13 +33,13 @@ namespace ARMeilleure.Signal
|
||||
|
||||
public static Operand EmitRetryFromAccessViolation(EmitterContext context)
|
||||
{
|
||||
IntPtr partialRemapStatePtr = PartialUnmapState.GlobalState;
|
||||
IntPtr localCountsPtr = IntPtr.Add(partialRemapStatePtr, PartialUnmapState.LocalCountsOffset);
|
||||
nint partialRemapStatePtr = PartialUnmapState.GlobalState;
|
||||
nint localCountsPtr = nint.Add(partialRemapStatePtr, PartialUnmapState.LocalCountsOffset);
|
||||
|
||||
// Get the lock first.
|
||||
EmitNativeReaderLockAcquire(context, IntPtr.Add(partialRemapStatePtr, PartialUnmapState.PartialUnmapLockOffset));
|
||||
EmitNativeReaderLockAcquire(context, nint.Add(partialRemapStatePtr, PartialUnmapState.PartialUnmapLockOffset));
|
||||
|
||||
IntPtr getCurrentThreadId = GetCurrentThreadIdFunc();
|
||||
nint getCurrentThreadId = GetCurrentThreadIdFunc();
|
||||
Operand threadId = context.Call(Const((ulong)getCurrentThreadId), OperandType.I32);
|
||||
Operand threadIndex = EmitThreadLocalMapIntGetOrReserve(context, localCountsPtr, threadId, Const(0));
|
||||
|
||||
@@ -58,7 +57,7 @@ namespace ARMeilleure.Signal
|
||||
|
||||
Operand threadLocalPartialUnmapsPtr = EmitThreadLocalMapIntGetValuePtr(context, localCountsPtr, threadIndex);
|
||||
Operand threadLocalPartialUnmaps = context.Load(OperandType.I32, threadLocalPartialUnmapsPtr);
|
||||
Operand partialUnmapsCount = context.Load(OperandType.I32, Const((ulong)IntPtr.Add(partialRemapStatePtr, PartialUnmapState.PartialUnmapsCountOffset)));
|
||||
Operand partialUnmapsCount = context.Load(OperandType.I32, Const((ulong)nint.Add(partialRemapStatePtr, PartialUnmapState.PartialUnmapsCountOffset)));
|
||||
|
||||
context.Copy(retry, context.ICompareNotEqual(threadLocalPartialUnmaps, partialUnmapsCount));
|
||||
|
||||
@@ -79,14 +78,14 @@ namespace ARMeilleure.Signal
|
||||
context.MarkLabel(endLabel);
|
||||
|
||||
// Finally, release the lock and return the retry value.
|
||||
EmitNativeReaderLockRelease(context, IntPtr.Add(partialRemapStatePtr, PartialUnmapState.PartialUnmapLockOffset));
|
||||
EmitNativeReaderLockRelease(context, nint.Add(partialRemapStatePtr, PartialUnmapState.PartialUnmapLockOffset));
|
||||
|
||||
return retry;
|
||||
}
|
||||
|
||||
public static Operand EmitThreadLocalMapIntGetOrReserve(EmitterContext context, IntPtr threadLocalMapPtr, Operand threadId, Operand initialState)
|
||||
public static Operand EmitThreadLocalMapIntGetOrReserve(EmitterContext context, nint threadLocalMapPtr, Operand threadId, Operand initialState)
|
||||
{
|
||||
Operand idsPtr = Const((ulong)IntPtr.Add(threadLocalMapPtr, ThreadLocalMap<int>.ThreadIdsOffset));
|
||||
Operand idsPtr = Const((ulong)nint.Add(threadLocalMapPtr, ThreadLocalMap<int>.ThreadIdsOffset));
|
||||
|
||||
Operand i = context.AllocateLocal(OperandType.I32);
|
||||
|
||||
@@ -130,7 +129,7 @@ namespace ARMeilleure.Signal
|
||||
// If it was 0, then we need to initialize the struct entry and return i.
|
||||
context.BranchIfFalse(idNot0Label, context.ICompareEqual(existingId2, Const(0)));
|
||||
|
||||
Operand structsPtr = Const((ulong)IntPtr.Add(threadLocalMapPtr, ThreadLocalMap<int>.StructsOffset));
|
||||
Operand structsPtr = Const((ulong)nint.Add(threadLocalMapPtr, ThreadLocalMap<int>.StructsOffset));
|
||||
Operand structPtr = context.Add(structsPtr, context.SignExtend32(OperandType.I64, offset2));
|
||||
context.Store(structPtr, initialState);
|
||||
|
||||
@@ -149,10 +148,10 @@ namespace ARMeilleure.Signal
|
||||
return context.Copy(i);
|
||||
}
|
||||
|
||||
private static Operand EmitThreadLocalMapIntGetValuePtr(EmitterContext context, IntPtr threadLocalMapPtr, Operand index)
|
||||
private static Operand EmitThreadLocalMapIntGetValuePtr(EmitterContext context, nint threadLocalMapPtr, Operand index)
|
||||
{
|
||||
Operand offset = context.Multiply(index, Const(sizeof(int)));
|
||||
Operand structsPtr = Const((ulong)IntPtr.Add(threadLocalMapPtr, ThreadLocalMap<int>.StructsOffset));
|
||||
Operand structsPtr = Const((ulong)nint.Add(threadLocalMapPtr, ThreadLocalMap<int>.StructsOffset));
|
||||
|
||||
return context.Add(structsPtr, context.SignExtend32(OperandType.I64, offset));
|
||||
}
|
||||
@@ -170,9 +169,9 @@ namespace ARMeilleure.Signal
|
||||
context.BranchIfFalse(loop, context.ICompareEqual(initial, replaced));
|
||||
}
|
||||
|
||||
private static void EmitNativeReaderLockAcquire(EmitterContext context, IntPtr nativeReaderLockPtr)
|
||||
private static void EmitNativeReaderLockAcquire(EmitterContext context, nint nativeReaderLockPtr)
|
||||
{
|
||||
Operand writeLockPtr = Const((ulong)IntPtr.Add(nativeReaderLockPtr, NativeReaderWriterLock.WriteLockOffset));
|
||||
Operand writeLockPtr = Const((ulong)nint.Add(nativeReaderLockPtr, NativeReaderWriterLock.WriteLockOffset));
|
||||
|
||||
// Spin until we can acquire the write lock.
|
||||
Operand spinLabel = Label();
|
||||
@@ -182,16 +181,16 @@ namespace ARMeilleure.Signal
|
||||
context.BranchIfTrue(spinLabel, context.CompareAndSwap(writeLockPtr, Const(0), Const(1)));
|
||||
|
||||
// Increment reader count.
|
||||
EmitAtomicAddI32(context, Const((ulong)IntPtr.Add(nativeReaderLockPtr, NativeReaderWriterLock.ReaderCountOffset)), Const(1));
|
||||
EmitAtomicAddI32(context, Const((ulong)nint.Add(nativeReaderLockPtr, NativeReaderWriterLock.ReaderCountOffset)), Const(1));
|
||||
|
||||
// Release write lock.
|
||||
context.CompareAndSwap(writeLockPtr, Const(1), Const(0));
|
||||
}
|
||||
|
||||
private static void EmitNativeReaderLockRelease(EmitterContext context, IntPtr nativeReaderLockPtr)
|
||||
private static void EmitNativeReaderLockRelease(EmitterContext context, nint nativeReaderLockPtr)
|
||||
{
|
||||
// Decrement reader count.
|
||||
EmitAtomicAddI32(context, Const((ulong)IntPtr.Add(nativeReaderLockPtr, NativeReaderWriterLock.ReaderCountOffset)), Const(-1));
|
||||
EmitAtomicAddI32(context, Const((ulong)nint.Add(nativeReaderLockPtr, NativeReaderWriterLock.ReaderCountOffset)), Const(-1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using ARMeilleure.Memory;
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
namespace ARMeilleure.State
|
||||
{
|
||||
@@ -9,9 +9,9 @@ namespace ARMeilleure.State
|
||||
|
||||
private readonly NativeContext _nativeContext;
|
||||
|
||||
internal IntPtr NativeContextPtr => _nativeContext.BasePtr;
|
||||
internal nint NativeContextPtr => _nativeContext.BasePtr;
|
||||
|
||||
private bool _interrupted;
|
||||
internal bool Interrupted { get; private set; }
|
||||
|
||||
private readonly ICounter _counter;
|
||||
|
||||
@@ -68,6 +68,8 @@ namespace ARMeilleure.State
|
||||
|
||||
public bool IsAarch32 { get; set; }
|
||||
|
||||
public ulong ThreadUid { get; set; }
|
||||
|
||||
internal ExecutionMode ExecutionMode
|
||||
{
|
||||
get
|
||||
@@ -93,14 +95,19 @@ namespace ARMeilleure.State
|
||||
|
||||
private readonly ExceptionCallbackNoArgs _interruptCallback;
|
||||
private readonly ExceptionCallback _breakCallback;
|
||||
private readonly ExceptionCallbackNoArgs _stepCallback;
|
||||
private readonly ExceptionCallback _supervisorCallback;
|
||||
private readonly ExceptionCallback _undefinedCallback;
|
||||
|
||||
internal int ShouldStep;
|
||||
public ulong DebugPc { get; set; }
|
||||
|
||||
public ExecutionContext(
|
||||
IJitMemoryAllocator allocator,
|
||||
ICounter counter,
|
||||
ExceptionCallbackNoArgs interruptCallback = null,
|
||||
ExceptionCallback breakCallback = null,
|
||||
ExceptionCallbackNoArgs stepCallback = null,
|
||||
ExceptionCallback supervisorCallback = null,
|
||||
ExceptionCallback undefinedCallback = null)
|
||||
{
|
||||
@@ -108,6 +115,7 @@ namespace ARMeilleure.State
|
||||
_counter = counter;
|
||||
_interruptCallback = interruptCallback;
|
||||
_breakCallback = breakCallback;
|
||||
_stepCallback = stepCallback;
|
||||
_supervisorCallback = supervisorCallback;
|
||||
_undefinedCallback = undefinedCallback;
|
||||
|
||||
@@ -128,11 +136,16 @@ namespace ARMeilleure.State
|
||||
public bool GetFPstateFlag(FPState flag) => _nativeContext.GetFPStateFlag(flag);
|
||||
public void SetFPstateFlag(FPState flag, bool value) => _nativeContext.SetFPStateFlag(flag, value);
|
||||
|
||||
internal void ResetCallDepth()
|
||||
{
|
||||
_nativeContext.ResetCallDepth();
|
||||
}
|
||||
|
||||
internal void CheckInterrupt()
|
||||
{
|
||||
if (_interrupted)
|
||||
if (Interrupted)
|
||||
{
|
||||
_interrupted = false;
|
||||
Interrupted = false;
|
||||
|
||||
_interruptCallback?.Invoke(this);
|
||||
}
|
||||
@@ -142,16 +155,37 @@ namespace ARMeilleure.State
|
||||
|
||||
public void RequestInterrupt()
|
||||
{
|
||||
_interrupted = true;
|
||||
Interrupted = true;
|
||||
}
|
||||
|
||||
public void StepHandler()
|
||||
{
|
||||
_stepCallback?.Invoke(this);
|
||||
}
|
||||
|
||||
public void RequestDebugStep()
|
||||
{
|
||||
Interlocked.Exchange(ref ShouldStep, 1);
|
||||
RequestInterrupt();
|
||||
}
|
||||
|
||||
internal void OnBreak(ulong address, int imm)
|
||||
{
|
||||
if (Optimizations.EnableDebugging)
|
||||
{
|
||||
DebugPc = Pc;
|
||||
}
|
||||
|
||||
_breakCallback?.Invoke(this, address, imm);
|
||||
}
|
||||
|
||||
internal void OnSupervisorCall(ulong address, int imm)
|
||||
{
|
||||
if (Optimizations.EnableDebugging)
|
||||
{
|
||||
DebugPc = Pc;
|
||||
}
|
||||
|
||||
_supervisorCallback?.Invoke(this, address, imm);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,14 +21,21 @@ namespace ARMeilleure.State
|
||||
public ulong ExclusiveValueLow;
|
||||
public ulong ExclusiveValueHigh;
|
||||
public int Running;
|
||||
public int CallDepth;
|
||||
public long Tpidr2El0;
|
||||
|
||||
/// <summary>
|
||||
/// Precise PC value used for debugging.
|
||||
/// This will only be set when Optimizations.EnableDebugging is true.
|
||||
/// </summary>
|
||||
public ulong DebugPrecisePc;
|
||||
}
|
||||
|
||||
private static NativeCtxStorage _dummyStorage = new();
|
||||
|
||||
private readonly IJitMemoryBlock _block;
|
||||
|
||||
public IntPtr BasePtr => _block.Pointer;
|
||||
public nint BasePtr => _block.Pointer;
|
||||
|
||||
public NativeContext(IJitMemoryAllocator allocator)
|
||||
{
|
||||
@@ -39,6 +46,11 @@ namespace ARMeilleure.State
|
||||
|
||||
public ulong GetPc()
|
||||
{
|
||||
if (Optimizations.EnableDebugging)
|
||||
{
|
||||
return GetStorage().DebugPrecisePc;
|
||||
}
|
||||
|
||||
// TODO: More precise tracking of PC value.
|
||||
return GetStorage().DispatchAddress;
|
||||
}
|
||||
@@ -186,6 +198,8 @@ namespace ARMeilleure.State
|
||||
public bool GetRunning() => GetStorage().Running != 0;
|
||||
public void SetRunning(bool value) => GetStorage().Running = value ? 1 : 0;
|
||||
|
||||
public void ResetCallDepth() => GetStorage().CallDepth = 0;
|
||||
|
||||
public unsafe static int GetRegisterOffset(Register reg)
|
||||
{
|
||||
if (reg.Type == RegisterType.Integer)
|
||||
@@ -266,6 +280,16 @@ namespace ARMeilleure.State
|
||||
return StorageOffset(ref _dummyStorage, ref _dummyStorage.Running);
|
||||
}
|
||||
|
||||
public static int GetDebugPrecisePcOffset()
|
||||
{
|
||||
return StorageOffset(ref _dummyStorage, ref _dummyStorage.DebugPrecisePc);
|
||||
}
|
||||
|
||||
public static int GetCallDepthOffset()
|
||||
{
|
||||
return StorageOffset(ref _dummyStorage, ref _dummyStorage.CallDepth);
|
||||
}
|
||||
|
||||
private static int StorageOffset<T>(ref NativeCtxStorage storage, ref T target)
|
||||
{
|
||||
return (int)Unsafe.ByteOffset(ref Unsafe.As<NativeCtxStorage, T>(ref storage), ref target);
|
||||
|
||||
@@ -6,7 +6,6 @@ using ARMeilleure.Instructions;
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.Memory;
|
||||
using ARMeilleure.State;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
@@ -53,6 +52,7 @@ namespace ARMeilleure.Translation
|
||||
public bool HighCq { get; }
|
||||
public bool HasPtc { get; }
|
||||
public Aarch32Mode Mode { get; }
|
||||
public bool IsSingleStep { get; }
|
||||
|
||||
private int _ifThenBlockStateIndex = 0;
|
||||
private Condition[] _ifThenBlockState = [];
|
||||
@@ -67,7 +67,8 @@ namespace ARMeilleure.Translation
|
||||
ulong entryAddress,
|
||||
bool highCq,
|
||||
bool hasPtc,
|
||||
Aarch32Mode mode)
|
||||
Aarch32Mode mode,
|
||||
bool isSingleStep)
|
||||
{
|
||||
Memory = memory;
|
||||
CountTable = countTable;
|
||||
@@ -77,6 +78,7 @@ namespace ARMeilleure.Translation
|
||||
HighCq = highCq;
|
||||
HasPtc = hasPtc;
|
||||
Mode = mode;
|
||||
IsSingleStep = isSingleStep;
|
||||
|
||||
_labels = new Dictionary<ulong, Operand>();
|
||||
}
|
||||
@@ -92,7 +94,7 @@ namespace ARMeilleure.Translation
|
||||
else
|
||||
{
|
||||
int index = Delegates.GetDelegateIndex(info);
|
||||
IntPtr funcPtr = Delegates.GetDelegateFuncPtrByIndex(index);
|
||||
nint funcPtr = Delegates.GetDelegateFuncPtrByIndex(index);
|
||||
|
||||
OperandType returnType = GetOperandType(info.ReturnType);
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace ARMeilleure.Translation.Cache
|
||||
|
||||
[SupportedOSPlatform("windows")]
|
||||
[LibraryImport("kernel32.dll", SetLastError = true)]
|
||||
public static partial IntPtr FlushInstructionCache(IntPtr hProcess, IntPtr lpAddress, UIntPtr dwSize);
|
||||
public static partial nint FlushInstructionCache(nint hProcess, nint lpAddress, nuint dwSize);
|
||||
|
||||
public static void Initialize(IJitMemoryAllocator allocator)
|
||||
{
|
||||
@@ -85,7 +85,7 @@ namespace ARMeilleure.Translation.Cache
|
||||
}
|
||||
}
|
||||
|
||||
public static IntPtr Map(CompiledFunction func)
|
||||
public static nint Map(CompiledFunction func)
|
||||
{
|
||||
byte[] code = func.Code;
|
||||
|
||||
@@ -95,7 +95,7 @@ namespace ARMeilleure.Translation.Cache
|
||||
|
||||
int funcOffset = Allocate(code.Length);
|
||||
ReservedRegion targetRegion = _jitRegions[_activeRegionIndex];
|
||||
IntPtr funcPtr = targetRegion.Pointer + funcOffset;
|
||||
nint funcPtr = targetRegion.Pointer + funcOffset;
|
||||
|
||||
if (OperatingSystem.IsMacOS() && RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
|
||||
{
|
||||
@@ -103,7 +103,7 @@ namespace ARMeilleure.Translation.Cache
|
||||
{
|
||||
fixed (byte* codePtr = code)
|
||||
{
|
||||
JitSupportDarwin.Copy(funcPtr, (IntPtr)codePtr, (ulong)code.Length);
|
||||
JitSupportDarwin.Copy(funcPtr, (nint)codePtr, (ulong)code.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -115,7 +115,7 @@ namespace ARMeilleure.Translation.Cache
|
||||
|
||||
if (OperatingSystem.IsWindows() && RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
|
||||
{
|
||||
FlushInstructionCache(Process.GetCurrentProcess().Handle, funcPtr, (UIntPtr)code.Length);
|
||||
FlushInstructionCache(Process.GetCurrentProcess().Handle, funcPtr, (nuint)code.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -129,7 +129,7 @@ namespace ARMeilleure.Translation.Cache
|
||||
}
|
||||
}
|
||||
|
||||
public static void Unmap(IntPtr pointer)
|
||||
public static void Unmap(nint pointer)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using ARMeilleure.Memory;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace ARMeilleure.Translation.Cache
|
||||
@@ -68,7 +67,7 @@ namespace ARMeilleure.Translation.Cache
|
||||
}
|
||||
}
|
||||
|
||||
public void Invalidate(IntPtr basePointer, ulong size)
|
||||
public void Invalidate(nint basePointer, ulong size)
|
||||
{
|
||||
if (_needsInvalidation)
|
||||
{
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace ARMeilleure.Translation.Cache
|
||||
PushMachframe = 10,
|
||||
}
|
||||
|
||||
private unsafe delegate RuntimeFunction* GetRuntimeFunctionCallback(ulong controlPc, IntPtr context);
|
||||
private unsafe delegate RuntimeFunction* GetRuntimeFunctionCallback(ulong controlPc, nint context);
|
||||
|
||||
[LibraryImport("kernel32.dll")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
@@ -49,7 +49,7 @@ namespace ARMeilleure.Translation.Cache
|
||||
ulong baseAddress,
|
||||
uint length,
|
||||
GetRuntimeFunctionCallback callback,
|
||||
IntPtr context,
|
||||
nint context,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] string outOfProcessCallbackDll);
|
||||
|
||||
[LibraryImport("kernel32.dll")]
|
||||
@@ -65,7 +65,7 @@ namespace ARMeilleure.Translation.Cache
|
||||
|
||||
private unsafe static UnwindInfo* _unwindInfo;
|
||||
|
||||
public static void InstallFunctionTableHandler(IntPtr codeCachePointer, uint codeCacheLength, IntPtr workBufferPtr)
|
||||
public static void InstallFunctionTableHandler(nint codeCachePointer, uint codeCacheLength, nint workBufferPtr)
|
||||
{
|
||||
ulong codeCachePtr = (ulong)codeCachePointer.ToInt64();
|
||||
|
||||
@@ -96,7 +96,7 @@ namespace ARMeilleure.Translation.Cache
|
||||
}
|
||||
}
|
||||
|
||||
public static void RemoveFunctionTableHandler(IntPtr codeCachePointer)
|
||||
public static void RemoveFunctionTableHandler(nint codeCachePointer)
|
||||
{
|
||||
ulong codeCachePtr = (ulong)codeCachePointer.ToInt64();
|
||||
|
||||
@@ -113,7 +113,7 @@ namespace ARMeilleure.Translation.Cache
|
||||
}
|
||||
}
|
||||
|
||||
private static unsafe RuntimeFunction* FunctionTableHandler(ulong controlPc, IntPtr context)
|
||||
private static unsafe RuntimeFunction* FunctionTableHandler(ulong controlPc, nint context)
|
||||
{
|
||||
int offset = (int)((long)controlPc - context.ToInt64());
|
||||
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
using System;
|
||||
|
||||
namespace ARMeilleure.Translation
|
||||
{
|
||||
class DelegateInfo
|
||||
{
|
||||
public IntPtr FuncPtr { get; }
|
||||
public nint FuncPtr { get; }
|
||||
|
||||
public DelegateInfo(IntPtr funcPtr)
|
||||
public DelegateInfo(nint funcPtr)
|
||||
{
|
||||
FuncPtr = funcPtr;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace ARMeilleure.Translation
|
||||
{
|
||||
static class Delegates
|
||||
{
|
||||
public static bool TryGetDelegateFuncPtrByIndex(int index, out IntPtr funcPtr)
|
||||
public static bool TryGetDelegateFuncPtrByIndex(int index, out nint funcPtr)
|
||||
{
|
||||
if (index >= 0 && index < _delegates.Count)
|
||||
{
|
||||
@@ -23,7 +23,7 @@ namespace ARMeilleure.Translation
|
||||
}
|
||||
}
|
||||
|
||||
public static IntPtr GetDelegateFuncPtrByIndex(int index)
|
||||
public static nint GetDelegateFuncPtrByIndex(int index)
|
||||
{
|
||||
if (index < 0 || index >= _delegates.Count)
|
||||
{
|
||||
@@ -58,7 +58,7 @@ namespace ARMeilleure.Translation
|
||||
|
||||
private static string GetKey(MethodInfo info)
|
||||
{
|
||||
return $"{info.DeclaringType.Name}.{info.Name}";
|
||||
return $"{info.DeclaringType?.Name}.{info.Name}";
|
||||
}
|
||||
|
||||
private static readonly SortedList<string, DelegateInfo> _delegates;
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
using System;
|
||||
|
||||
namespace ARMeilleure.Translation
|
||||
{
|
||||
delegate void DispatcherFunction(IntPtr nativeContext, ulong startAddress);
|
||||
delegate ulong WrapperFunction(IntPtr nativeContext, ulong startAddress);
|
||||
delegate void DispatcherFunction(nint nativeContext, ulong startAddress);
|
||||
delegate ulong WrapperFunction(nint nativeContext, ulong startAddress);
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ namespace ARMeilleure.Translation
|
||||
|
||||
public virtual Operand Call(MethodInfo info, params Operand[] callArgs)
|
||||
{
|
||||
IntPtr funcPtr = info.MethodHandle.GetFunctionPointer();
|
||||
nint funcPtr = info.MethodHandle.GetFunctionPointer();
|
||||
|
||||
OperandType returnType = GetOperandType(info.ReturnType);
|
||||
|
||||
@@ -668,8 +668,7 @@ namespace ARMeilleure.Translation
|
||||
Operation last = block.Operations.Last;
|
||||
|
||||
return last != default &&
|
||||
(last.Instruction == Instruction.Return ||
|
||||
last.Instruction == Instruction.Tailcall);
|
||||
last.Instruction is Instruction.Return or Instruction.Tailcall;
|
||||
}
|
||||
|
||||
public ControlFlowGraph GetControlFlowGraph()
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
using System;
|
||||
|
||||
namespace ARMeilleure.Translation
|
||||
{
|
||||
delegate ulong GuestFunction(IntPtr nativeContextPtr);
|
||||
delegate ulong GuestFunction(nint nativeContextPtr);
|
||||
}
|
||||
|
||||
@@ -316,7 +316,7 @@ namespace ARMeilleure.Translation
|
||||
{
|
||||
_root = newNode;
|
||||
}
|
||||
else if (start.CompareTo(parent.Start) < 0)
|
||||
else if (start.CompareTo(parent!.Start) < 0)
|
||||
{
|
||||
parent.Left = newNode;
|
||||
}
|
||||
@@ -359,10 +359,7 @@ namespace ARMeilleure.Translation
|
||||
|
||||
IntervalTreeNode<TK, TV> tmp = LeftOf(replacementNode) ?? RightOf(replacementNode);
|
||||
|
||||
if (tmp != null)
|
||||
{
|
||||
tmp.Parent = ParentOf(replacementNode);
|
||||
}
|
||||
tmp?.Parent = ParentOf(replacementNode);
|
||||
|
||||
if (ParentOf(replacementNode) == null)
|
||||
{
|
||||
@@ -570,10 +567,7 @@ namespace ARMeilleure.Translation
|
||||
{
|
||||
IntervalTreeNode<TK, TV> right = RightOf(node);
|
||||
node.Right = LeftOf(right);
|
||||
if (node.Right != null)
|
||||
{
|
||||
node.Right.Parent = node;
|
||||
}
|
||||
node.Right?.Parent = node;
|
||||
IntervalTreeNode<TK, TV> nodeParent = ParentOf(node);
|
||||
right.Parent = nodeParent;
|
||||
if (nodeParent == null)
|
||||
@@ -601,10 +595,7 @@ namespace ARMeilleure.Translation
|
||||
{
|
||||
IntervalTreeNode<TK, TV> left = LeftOf(node);
|
||||
node.Left = RightOf(left);
|
||||
if (node.Left != null)
|
||||
{
|
||||
node.Left.Parent = node;
|
||||
}
|
||||
node.Left?.Parent = node;
|
||||
IntervalTreeNode<TK, TV> nodeParent = ParentOf(node);
|
||||
left.Parent = nodeParent;
|
||||
if (nodeParent == null)
|
||||
@@ -651,10 +642,7 @@ namespace ARMeilleure.Translation
|
||||
/// <param name="color">Color (Boolean)</param>
|
||||
private static void SetColor(IntervalTreeNode<TK, TV> node, bool color)
|
||||
{
|
||||
if (node != null)
|
||||
{
|
||||
node.Color = color;
|
||||
}
|
||||
node?.Color = color;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
private const string OuterHeaderMagicString = "PTCohd\0\0";
|
||||
private const string InnerHeaderMagicString = "PTCihd\0\0";
|
||||
|
||||
private const uint InternalVersion = 7008; //! To be incremented manually for each change to the ARMeilleure project.
|
||||
private const uint InternalVersion = 7010; //! To be incremented manually for each change to the ARMeilleure project.
|
||||
|
||||
private const string ActualDir = "0";
|
||||
private const string BackupDir = "1";
|
||||
@@ -107,7 +107,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
Profiler.Wait();
|
||||
Profiler.ClearEntries();
|
||||
|
||||
Logger.Info?.Print(LogClass.Ptc, $"Initializing Profiled Persistent Translation Cache (enabled: {enabled}).");
|
||||
Logger.Info?.Print(LogClass.Ptc, $"Initializing Profiled Persistent Translation Cache v{InternalVersion}\n\t\t (title: {titleIdText}, version: '{displayVersion}', selector: '{cacheSelector}', enabled: {enabled}).");
|
||||
|
||||
if (!enabled || string.IsNullOrEmpty(titleIdText) || titleIdText == TitleIdTextDefault)
|
||||
{
|
||||
@@ -126,8 +126,6 @@ namespace ARMeilleure.Translation.PTC
|
||||
DisplayVersion = !string.IsNullOrEmpty(displayVersion) ? displayVersion : DisplayVersionDefault;
|
||||
_memoryMode = memoryMode;
|
||||
|
||||
Logger.Info?.Print(LogClass.Ptc, $"PPTC (v{InternalVersion}) Profile: {DisplayVersion}-{cacheSelector}");
|
||||
|
||||
string workPathActual = Path.Combine(AppDataManager.GamesDirPath, TitleIdText, "cache", "cpu", ActualDir);
|
||||
string workPathBackup = Path.Combine(AppDataManager.GamesDirPath, TitleIdText, "cache", "cpu", BackupDir);
|
||||
|
||||
@@ -190,7 +188,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
_infosStream.Seek(0L, SeekOrigin.Begin);
|
||||
bool foundBadFunction = false;
|
||||
|
||||
for (int index = 0; index < GetEntriesCount(); index++)
|
||||
for (int index = 0; index < _infosStream.Length / Unsafe.SizeOf<InfoEntry>(); index++)
|
||||
{
|
||||
InfoEntry infoEntry = DeserializeStructure<InfoEntry>(_infosStream);
|
||||
foreach (ulong address in blacklist)
|
||||
@@ -244,67 +242,26 @@ namespace ARMeilleure.Translation.PTC
|
||||
{
|
||||
OuterHeader outerHeader = DeserializeStructure<OuterHeader>(compressedStream);
|
||||
|
||||
if (!outerHeader.IsHeaderValid())
|
||||
if (!outerHeader.IsHeaderValid() ||
|
||||
outerHeader.Magic != _outerHeaderMagic ||
|
||||
outerHeader.CacheFileVersion != InternalVersion ||
|
||||
outerHeader.Endianness != GetEndianness() ||
|
||||
outerHeader.FeatureInfo != GetFeatureInfo() ||
|
||||
outerHeader.MemoryManagerMode != GetMemoryManagerMode() ||
|
||||
outerHeader.OSPlatform != GetOSPlatform() ||
|
||||
outerHeader.Architecture != (uint)RuntimeInformation.ProcessArchitecture ||
|
||||
outerHeader.DebuggerMode != Optimizations.EnableDebugging)
|
||||
{
|
||||
InvalidateCompressedStream(compressedStream);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (outerHeader.Magic != _outerHeaderMagic)
|
||||
{
|
||||
InvalidateCompressedStream(compressedStream);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (outerHeader.CacheFileVersion != InternalVersion)
|
||||
{
|
||||
InvalidateCompressedStream(compressedStream);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (outerHeader.Endianness != GetEndianness())
|
||||
{
|
||||
InvalidateCompressedStream(compressedStream);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (outerHeader.FeatureInfo != GetFeatureInfo())
|
||||
{
|
||||
InvalidateCompressedStream(compressedStream);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (outerHeader.MemoryManagerMode != GetMemoryManagerMode())
|
||||
{
|
||||
InvalidateCompressedStream(compressedStream);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (outerHeader.OSPlatform != GetOSPlatform())
|
||||
{
|
||||
InvalidateCompressedStream(compressedStream);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (outerHeader.Architecture != (uint)RuntimeInformation.ProcessArchitecture)
|
||||
{
|
||||
InvalidateCompressedStream(compressedStream);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
IntPtr intPtr = IntPtr.Zero;
|
||||
nint intPtr = nint.Zero;
|
||||
|
||||
try
|
||||
{
|
||||
intPtr = Marshal.AllocHGlobal(new IntPtr(outerHeader.UncompressedStreamSize));
|
||||
intPtr = Marshal.AllocHGlobal(new nint(outerHeader.UncompressedStreamSize));
|
||||
|
||||
using UnmanagedMemoryStream stream = new((byte*)intPtr.ToPointer(), outerHeader.UncompressedStreamSize, outerHeader.UncompressedStreamSize, FileAccess.ReadWrite);
|
||||
try
|
||||
@@ -324,14 +281,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
|
||||
InnerHeader innerHeader = DeserializeStructure<InnerHeader>(stream);
|
||||
|
||||
if (!innerHeader.IsHeaderValid())
|
||||
{
|
||||
InvalidateCompressedStream(compressedStream);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (innerHeader.Magic != _innerHeaderMagic)
|
||||
if (!innerHeader.IsHeaderValid() || innerHeader.Magic != _innerHeaderMagic)
|
||||
{
|
||||
InvalidateCompressedStream(compressedStream);
|
||||
|
||||
@@ -405,7 +355,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (intPtr != IntPtr.Zero)
|
||||
if (intPtr != nint.Zero)
|
||||
{
|
||||
Marshal.FreeHGlobal(intPtr);
|
||||
}
|
||||
@@ -476,6 +426,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
MemoryManagerMode = GetMemoryManagerMode(),
|
||||
OSPlatform = GetOSPlatform(),
|
||||
Architecture = (uint)RuntimeInformation.ProcessArchitecture,
|
||||
DebuggerMode = Optimizations.EnableDebugging,
|
||||
|
||||
UncompressedStreamSize =
|
||||
(long)Unsafe.SizeOf<InnerHeader>() +
|
||||
@@ -487,11 +438,11 @@ namespace ARMeilleure.Translation.PTC
|
||||
|
||||
outerHeader.SetHeaderHash();
|
||||
|
||||
IntPtr intPtr = IntPtr.Zero;
|
||||
nint intPtr = nint.Zero;
|
||||
|
||||
try
|
||||
{
|
||||
intPtr = Marshal.AllocHGlobal(new IntPtr(outerHeader.UncompressedStreamSize));
|
||||
intPtr = Marshal.AllocHGlobal(new nint(outerHeader.UncompressedStreamSize));
|
||||
|
||||
using UnmanagedMemoryStream stream = new((byte*)intPtr.ToPointer(), outerHeader.UncompressedStreamSize, outerHeader.UncompressedStreamSize, FileAccess.ReadWrite);
|
||||
stream.Seek((long)Unsafe.SizeOf<InnerHeader>(), SeekOrigin.Begin);
|
||||
@@ -545,7 +496,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (intPtr != IntPtr.Zero)
|
||||
if (intPtr != nint.Zero)
|
||||
{
|
||||
Marshal.FreeHGlobal(intPtr);
|
||||
}
|
||||
@@ -697,7 +648,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
|
||||
foreach (RelocEntry relocEntry in relocEntries)
|
||||
{
|
||||
IntPtr? imm = null;
|
||||
nint? imm = null;
|
||||
Symbol symbol = relocEntry.Symbol;
|
||||
|
||||
if (symbol.Type == SymbolType.FunctionTable)
|
||||
@@ -708,7 +659,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
imm = (IntPtr)Unsafe.AsPointer(ref translator.FunctionTable.GetValue(guestAddress));
|
||||
imm = (nint)Unsafe.AsPointer(ref translator.FunctionTable.GetValue(guestAddress));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -716,7 +667,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
{
|
||||
int index = (int)symbol.Value;
|
||||
|
||||
if (Delegates.TryGetDelegateFuncPtrByIndex(index, out IntPtr funcPtr))
|
||||
if (Delegates.TryGetDelegateFuncPtrByIndex(index, out nint funcPtr))
|
||||
{
|
||||
imm = funcPtr;
|
||||
}
|
||||
@@ -731,7 +682,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
|
||||
unsafe
|
||||
{
|
||||
imm = (IntPtr)Unsafe.AsPointer(ref callCounter.Value);
|
||||
imm = (nint)Unsafe.AsPointer(ref callCounter.Value);
|
||||
}
|
||||
}
|
||||
else if (symbol == DispatchStubSymbol)
|
||||
@@ -781,7 +732,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
bool highCq)
|
||||
{
|
||||
var cFunc = new CompiledFunction(code, unwindInfo, RelocInfo.Empty);
|
||||
var gFunc = cFunc.MapWithPointer<GuestFunction>(out IntPtr gFuncPointer);
|
||||
var gFunc = cFunc.MapWithPointer<GuestFunction>(out nint gFuncPointer);
|
||||
|
||||
return new TranslatedFunction(gFunc, gFuncPointer, callCounter, guestSize, highCq);
|
||||
}
|
||||
@@ -1072,7 +1023,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
return osPlatform;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 86*/)]
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 87*/)]
|
||||
private struct OuterHeader
|
||||
{
|
||||
public ulong Magic;
|
||||
@@ -1084,6 +1035,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
public byte MemoryManagerMode;
|
||||
public uint OSPlatform;
|
||||
public uint Architecture;
|
||||
public bool DebuggerMode;
|
||||
|
||||
public long UncompressedStreamSize;
|
||||
|
||||
@@ -1166,8 +1118,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
|
||||
public void Close()
|
||||
{
|
||||
if (State == PtcState.Enabled ||
|
||||
State == PtcState.Continuing)
|
||||
if (State is PtcState.Enabled or PtcState.Continuing)
|
||||
{
|
||||
State = PtcState.Closing;
|
||||
}
|
||||
|
||||
@@ -189,28 +189,10 @@ namespace ARMeilleure.Translation.PTC
|
||||
{
|
||||
OuterHeader outerHeader = DeserializeStructure<OuterHeader>(compressedStream);
|
||||
|
||||
if (!outerHeader.IsHeaderValid())
|
||||
{
|
||||
InvalidateCompressedStream(compressedStream);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (outerHeader.Magic != _outerHeaderMagic)
|
||||
{
|
||||
InvalidateCompressedStream(compressedStream);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (outerHeader.InfoFileVersion != InternalVersion && !_migrateInternalVersions.Contains(outerHeader.InfoFileVersion))
|
||||
{
|
||||
InvalidateCompressedStream(compressedStream);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (outerHeader.Endianness != Ptc.GetEndianness())
|
||||
if (!outerHeader.IsHeaderValid() ||
|
||||
outerHeader.Magic != _outerHeaderMagic ||
|
||||
outerHeader.InfoFileVersion != InternalVersion && !_migrateInternalVersions.Contains(outerHeader.InfoFileVersion) ||
|
||||
outerHeader.Endianness != Ptc.GetEndianness())
|
||||
{
|
||||
InvalidateCompressedStream(compressedStream);
|
||||
|
||||
@@ -465,8 +447,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
|
||||
public void Start()
|
||||
{
|
||||
if (_ptc.State == PtcState.Enabled ||
|
||||
_ptc.State == PtcState.Continuing)
|
||||
if (_ptc.State is PtcState.Enabled or PtcState.Continuing)
|
||||
{
|
||||
Enabled = true;
|
||||
|
||||
|
||||
@@ -95,7 +95,7 @@ namespace ARMeilleure.Translation
|
||||
// This is required because we have a implicit context load at the start of the function,
|
||||
// but if there is a jump to the start of the function, the context load would trash the modified values.
|
||||
// Here we insert a new entry block that will jump to the existing entry block.
|
||||
BasicBlock newEntry = new BasicBlock(cfg.Blocks.Count);
|
||||
BasicBlock newEntry = new(cfg.Blocks.Count);
|
||||
|
||||
cfg.UpdateEntry(newEntry);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using ARMeilleure.Common;
|
||||
using System;
|
||||
|
||||
namespace ARMeilleure.Translation
|
||||
{
|
||||
@@ -7,12 +6,12 @@ namespace ARMeilleure.Translation
|
||||
{
|
||||
private readonly GuestFunction _func; // Ensure that this delegate will not be garbage collected.
|
||||
|
||||
public IntPtr FuncPointer { get; }
|
||||
public nint FuncPointer { get; }
|
||||
public Counter<uint> CallCounter { get; }
|
||||
public ulong GuestSize { get; }
|
||||
public bool HighCq { get; }
|
||||
|
||||
public TranslatedFunction(GuestFunction func, IntPtr funcPointer, Counter<uint> callCounter, ulong guestSize, bool highCq)
|
||||
public TranslatedFunction(GuestFunction func, nint funcPointer, Counter<uint> callCounter, ulong guestSize, bool highCq)
|
||||
{
|
||||
_func = func;
|
||||
FuncPointer = funcPointer;
|
||||
|
||||
@@ -119,7 +119,25 @@ namespace ARMeilleure.Translation
|
||||
|
||||
NativeInterface.RegisterThread(context, Memory, this);
|
||||
|
||||
if (Optimizations.UseUnmanagedDispatchLoop)
|
||||
if (Optimizations.EnableDebugging)
|
||||
{
|
||||
context.DebugPc = address;
|
||||
do
|
||||
{
|
||||
if (Interlocked.CompareExchange(ref context.ShouldStep, 0, 1) == 1)
|
||||
{
|
||||
context.DebugPc = Step(context, context.DebugPc);
|
||||
context.StepHandler();
|
||||
}
|
||||
else
|
||||
{
|
||||
context.DebugPc = ExecuteSingle(context, context.DebugPc);
|
||||
}
|
||||
context.CheckInterrupt();
|
||||
}
|
||||
while (context.Running && context.DebugPc != 0);
|
||||
}
|
||||
else if (Optimizations.UseUnmanagedDispatchLoop)
|
||||
{
|
||||
Stubs.DispatchLoop(context.NativeContextPtr, address);
|
||||
}
|
||||
@@ -168,6 +186,7 @@ namespace ARMeilleure.Translation
|
||||
|
||||
Statistics.StartTimer();
|
||||
|
||||
context.ResetCallDepth();
|
||||
ulong nextAddr = func.Execute(Stubs.ContextWrapper, context);
|
||||
|
||||
Statistics.StopTimer(address);
|
||||
@@ -175,7 +194,7 @@ namespace ARMeilleure.Translation
|
||||
return nextAddr;
|
||||
}
|
||||
|
||||
public ulong Step(State.ExecutionContext context, ulong address)
|
||||
private ulong Step(State.ExecutionContext context, ulong address)
|
||||
{
|
||||
TranslatedFunction func = Translate(address, context.ExecutionMode, highCq: false, singleStep: true);
|
||||
|
||||
@@ -186,6 +205,8 @@ namespace ARMeilleure.Translation
|
||||
return address;
|
||||
}
|
||||
|
||||
|
||||
|
||||
internal TranslatedFunction GetOrTranslate(ulong address, ExecutionMode mode)
|
||||
{
|
||||
if (!Functions.TryGetValue(address, out TranslatedFunction func))
|
||||
@@ -229,7 +250,8 @@ namespace ARMeilleure.Translation
|
||||
address,
|
||||
highCq,
|
||||
_ptc.State != PtcState.Disabled,
|
||||
mode: Aarch32Mode.User);
|
||||
mode: Aarch32Mode.User,
|
||||
isSingleStep: singleStep);
|
||||
|
||||
Logger.StartPass(PassName.Decoding);
|
||||
|
||||
@@ -239,6 +261,7 @@ namespace ARMeilleure.Translation
|
||||
|
||||
Logger.StartPass(PassName.Translation);
|
||||
|
||||
InstEmitFlowHelper.EmitCallDepthCheckAndIncrement(context, Const(address));
|
||||
EmitSynchronization(context);
|
||||
|
||||
if (blocks[0].Address != address)
|
||||
@@ -282,7 +305,7 @@ namespace ARMeilleure.Translation
|
||||
_ptc.WriteCompiledFunction(address, funcSize, hash, highCq, compiledFunc);
|
||||
}
|
||||
|
||||
GuestFunction func = compiledFunc.MapWithPointer<GuestFunction>(out IntPtr funcPointer);
|
||||
GuestFunction func = compiledFunc.MapWithPointer<GuestFunction>(out nint funcPointer);
|
||||
|
||||
Allocators.ResetAll();
|
||||
|
||||
@@ -367,9 +390,13 @@ namespace ARMeilleure.Translation
|
||||
|
||||
if (block.Exit)
|
||||
{
|
||||
// Left option here as it may be useful if we need to return to managed rather than tail call in
|
||||
// future. (eg. for debug)
|
||||
bool useReturns = false;
|
||||
// Return to managed rather than tail call.
|
||||
bool useReturns = Optimizations.EnableDebugging;
|
||||
|
||||
if (Optimizations.EnableDebugging)
|
||||
{
|
||||
EmitDebugPrecisePcUpdate(context, block.Address);
|
||||
}
|
||||
|
||||
InstEmitFlowHelper.EmitVirtualJump(context, Const(block.Address), isReturn: useReturns);
|
||||
}
|
||||
@@ -393,6 +420,11 @@ namespace ARMeilleure.Translation
|
||||
}
|
||||
}
|
||||
|
||||
if (Optimizations.EnableDebugging)
|
||||
{
|
||||
EmitDebugPrecisePcUpdate(context, opCode.Address);
|
||||
}
|
||||
|
||||
Operand lblPredicateSkip = default;
|
||||
|
||||
if (context.IsInIfThenBlock && context.CurrentIfThenBlockCond != Condition.Al)
|
||||
@@ -489,6 +521,14 @@ namespace ARMeilleure.Translation
|
||||
context.MarkLabel(lblExit);
|
||||
}
|
||||
|
||||
internal static void EmitDebugPrecisePcUpdate(EmitterContext context, ulong address)
|
||||
{
|
||||
long debugPrecisePcOffs = NativeContext.GetDebugPrecisePcOffset();
|
||||
|
||||
Operand debugPrecisePcAddr = context.Add(context.LoadArgument(OperandType.I64, 0), Const(debugPrecisePcOffs));
|
||||
context.Store(debugPrecisePcAddr, Const(address));
|
||||
}
|
||||
|
||||
public void InvalidateJitCacheRegion(ulong address, ulong size)
|
||||
{
|
||||
ulong[] overlapAddresses = [];
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace ARMeilleure.Translation
|
||||
/// </summary>
|
||||
class TranslatorStubs : IDisposable
|
||||
{
|
||||
private readonly Lazy<IntPtr> _slowDispatchStub;
|
||||
private readonly Lazy<nint> _slowDispatchStub;
|
||||
|
||||
private bool _disposed;
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace ARMeilleure.Translation
|
||||
/// Gets the dispatch stub.
|
||||
/// </summary>
|
||||
/// <exception cref="ObjectDisposedException"><see cref="TranslatorStubs"/> instance was disposed</exception>
|
||||
public IntPtr DispatchStub
|
||||
public nint DispatchStub
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -41,7 +41,7 @@ namespace ARMeilleure.Translation
|
||||
/// Gets the slow dispatch stub.
|
||||
/// </summary>
|
||||
/// <exception cref="ObjectDisposedException"><see cref="TranslatorStubs"/> instance was disposed</exception>
|
||||
public IntPtr SlowDispatchStub
|
||||
public nint SlowDispatchStub
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -139,7 +139,7 @@ namespace ARMeilleure.Translation
|
||||
/// Generates a <see cref="DispatchStub"/>.
|
||||
/// </summary>
|
||||
/// <returns>Generated <see cref="DispatchStub"/></returns>
|
||||
private IntPtr GenerateDispatchStub()
|
||||
private nint GenerateDispatchStub()
|
||||
{
|
||||
var context = new EmitterContext();
|
||||
|
||||
@@ -197,7 +197,7 @@ namespace ARMeilleure.Translation
|
||||
/// Generates a <see cref="SlowDispatchStub"/>.
|
||||
/// </summary>
|
||||
/// <returns>Generated <see cref="SlowDispatchStub"/></returns>
|
||||
private IntPtr GenerateSlowDispatchStub()
|
||||
private nint GenerateSlowDispatchStub()
|
||||
{
|
||||
var context = new EmitterContext();
|
||||
|
||||
@@ -262,10 +262,18 @@ namespace ARMeilleure.Translation
|
||||
|
||||
Operand runningAddress = context.Add(nativeContext, Const((ulong)NativeContext.GetRunningOffset()));
|
||||
Operand dispatchAddress = context.Add(nativeContext, Const((ulong)NativeContext.GetDispatchAddressOffset()));
|
||||
Operand callDepthAddress = context.Add(nativeContext, Const((ulong)NativeContext.GetCallDepthOffset()));
|
||||
|
||||
EmitSyncFpContext(context, nativeContext, true);
|
||||
|
||||
context.MarkLabel(beginLbl);
|
||||
|
||||
if (Optimizations.EnableDeepCallRecursionProtection)
|
||||
{
|
||||
// Reset the call depth counter, since this is our first guest function call.
|
||||
context.Store(callDepthAddress, Const(0));
|
||||
}
|
||||
|
||||
context.Store(dispatchAddress, guestAddress);
|
||||
context.Copy(guestAddress, context.Call(Const((ulong)DispatchStub), OperandType.I64, nativeContext));
|
||||
context.BranchIfFalse(endLbl, guestAddress);
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace ARMeilleure.Translation
|
||||
{
|
||||
public static class TranslatorTestMethods
|
||||
{
|
||||
public delegate int FpFlagsPInvokeTest(IntPtr managedMethod);
|
||||
public delegate int FpFlagsPInvokeTest(nint managedMethod);
|
||||
|
||||
private static bool SetPlatformFtz(EmitterContext context, bool ftz)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
namespace Ryujinx.Audio.Backends.Apple
|
||||
{
|
||||
class AppleAudioBuffer
|
||||
{
|
||||
public readonly ulong DriverIdentifier;
|
||||
public readonly ulong SampleCount;
|
||||
public ulong SamplePlayed;
|
||||
|
||||
public AppleAudioBuffer(ulong driverIdentifier, ulong sampleCount)
|
||||
{
|
||||
DriverIdentifier = driverIdentifier;
|
||||
SampleCount = sampleCount;
|
||||
SamplePlayed = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
using Ryujinx.Audio.Common;
|
||||
using Ryujinx.Audio.Integration;
|
||||
using Ryujinx.Memory;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Versioning;
|
||||
using System.Threading;
|
||||
using static Ryujinx.Audio.Backends.Apple.Native.AudioToolbox;
|
||||
using static Ryujinx.Audio.Integration.IHardwareDeviceDriver;
|
||||
|
||||
namespace Ryujinx.Audio.Backends.Apple
|
||||
{
|
||||
[SupportedOSPlatform("macos")]
|
||||
[SupportedOSPlatform("ios")]
|
||||
public sealed class AppleHardwareDeviceDriver : IHardwareDeviceDriver
|
||||
{
|
||||
private readonly ManualResetEvent _updateRequiredEvent;
|
||||
private readonly ManualResetEvent _pauseEvent;
|
||||
private readonly ConcurrentDictionary<AppleHardwareDeviceSession, byte> _sessions;
|
||||
private readonly bool _supportSurroundConfiguration;
|
||||
|
||||
public float Volume { get; set; }
|
||||
|
||||
public AppleHardwareDeviceDriver()
|
||||
{
|
||||
_updateRequiredEvent = new ManualResetEvent(false);
|
||||
_pauseEvent = new ManualResetEvent(true);
|
||||
_sessions = new ConcurrentDictionary<AppleHardwareDeviceSession, byte>();
|
||||
|
||||
_supportSurroundConfiguration = TestSurroundSupport();
|
||||
|
||||
Volume = 1f;
|
||||
}
|
||||
|
||||
private bool TestSurroundSupport()
|
||||
{
|
||||
try
|
||||
{
|
||||
AudioStreamBasicDescription format =
|
||||
GetAudioFormat(SampleFormat.PcmFloat, Constants.TargetSampleRate, 6);
|
||||
|
||||
int result = AudioQueueNewOutput(
|
||||
ref format,
|
||||
nint.Zero,
|
||||
nint.Zero,
|
||||
nint.Zero,
|
||||
nint.Zero,
|
||||
0,
|
||||
out nint testQueue);
|
||||
|
||||
if (result == 0)
|
||||
{
|
||||
AudioChannelLayout layout = new AudioChannelLayout
|
||||
{
|
||||
AudioChannelLayoutTag = kAudioChannelLayoutTag_MPEG_5_1_A,
|
||||
AudioChannelBitmap = 0,
|
||||
NumberChannelDescriptions = 0
|
||||
};
|
||||
|
||||
int layoutResult = AudioQueueSetProperty(
|
||||
testQueue,
|
||||
kAudioQueueProperty_ChannelLayout,
|
||||
ref layout,
|
||||
(uint)Marshal.SizeOf<AudioChannelLayout>());
|
||||
|
||||
if (layoutResult == 0)
|
||||
{
|
||||
AudioQueueDispose(testQueue, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
AudioQueueDispose(testQueue, true);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsSupported => OperatingSystem.IsMacOSVersionAtLeast(10, 5);
|
||||
|
||||
public ManualResetEvent GetUpdateRequiredEvent()
|
||||
=> _updateRequiredEvent;
|
||||
|
||||
public ManualResetEvent GetPauseEvent()
|
||||
=> _pauseEvent;
|
||||
|
||||
public IHardwareDeviceSession OpenDeviceSession(Direction direction, IVirtualMemoryManager memoryManager,
|
||||
SampleFormat sampleFormat, uint sampleRate, uint channelCount)
|
||||
{
|
||||
if (channelCount == 0)
|
||||
{
|
||||
channelCount = 2;
|
||||
}
|
||||
|
||||
if (sampleRate == 0)
|
||||
{
|
||||
sampleRate = Constants.TargetSampleRate;
|
||||
}
|
||||
|
||||
if (direction != Direction.Output)
|
||||
{
|
||||
throw new NotImplementedException("Input direction is currently not implemented on Apple backend!");
|
||||
}
|
||||
|
||||
AppleHardwareDeviceSession session = new(this, memoryManager, sampleFormat, sampleRate, channelCount);
|
||||
|
||||
_sessions.TryAdd(session, 0);
|
||||
|
||||
return session;
|
||||
}
|
||||
|
||||
internal bool Unregister(AppleHardwareDeviceSession session)
|
||||
=> _sessions.TryRemove(session, out _);
|
||||
|
||||
internal static AudioStreamBasicDescription GetAudioFormat(SampleFormat sampleFormat, uint sampleRate,
|
||||
uint channelCount)
|
||||
{
|
||||
uint formatFlags;
|
||||
uint bitsPerChannel;
|
||||
|
||||
switch (sampleFormat)
|
||||
{
|
||||
case SampleFormat.PcmInt8:
|
||||
formatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
|
||||
bitsPerChannel = 8;
|
||||
break;
|
||||
case SampleFormat.PcmInt16:
|
||||
formatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
|
||||
bitsPerChannel = 16;
|
||||
break;
|
||||
case SampleFormat.PcmInt32:
|
||||
formatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
|
||||
bitsPerChannel = 32;
|
||||
break;
|
||||
case SampleFormat.PcmFloat:
|
||||
formatFlags = kAudioFormatFlagIsFloat | kAudioFormatFlagIsPacked;
|
||||
bitsPerChannel = 32;
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException($"Unsupported sample format {sampleFormat}");
|
||||
}
|
||||
|
||||
uint bytesPerFrame = (bitsPerChannel / 8) * channelCount;
|
||||
|
||||
return new AudioStreamBasicDescription
|
||||
{
|
||||
SampleRate = sampleRate,
|
||||
FormatID = kAudioFormatLinearPCM,
|
||||
FormatFlags = formatFlags,
|
||||
BytesPerPacket = bytesPerFrame,
|
||||
FramesPerPacket = 1,
|
||||
BytesPerFrame = bytesPerFrame,
|
||||
ChannelsPerFrame = channelCount,
|
||||
BitsPerChannel = bitsPerChannel,
|
||||
Reserved = 0
|
||||
};
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
GC.SuppressFinalize(this);
|
||||
Dispose(true);
|
||||
}
|
||||
|
||||
private void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
foreach (AppleHardwareDeviceSession session in _sessions.Keys)
|
||||
{
|
||||
session.Dispose();
|
||||
}
|
||||
|
||||
_pauseEvent.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public bool SupportsDirection(Direction direction)
|
||||
=> direction != Direction.Input;
|
||||
|
||||
public bool SupportsSampleRate(uint sampleRate) => true;
|
||||
|
||||
public bool SupportsSampleFormat(SampleFormat sampleFormat)
|
||||
=> sampleFormat != SampleFormat.PcmInt24;
|
||||
|
||||
public bool SupportsChannelCount(uint channelCount)
|
||||
=> channelCount != 6 || _supportSurroundConfiguration;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,285 @@
|
||||
using Ryujinx.Audio.Backends.Common;
|
||||
using Ryujinx.Audio.Common;
|
||||
using Ryujinx.Memory;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Runtime.Versioning;
|
||||
using static Ryujinx.Audio.Backends.Apple.Native.AudioToolbox;
|
||||
|
||||
namespace Ryujinx.Audio.Backends.Apple
|
||||
{
|
||||
[SupportedOSPlatform("macos")]
|
||||
[SupportedOSPlatform("ios")]
|
||||
class AppleHardwareDeviceSession : HardwareDeviceSessionOutputBase
|
||||
{
|
||||
private const int NumBuffers = 3;
|
||||
|
||||
private readonly AppleHardwareDeviceDriver _driver;
|
||||
private readonly ConcurrentQueue<AppleAudioBuffer> _queuedBuffers = new();
|
||||
private readonly DynamicRingBuffer _ringBuffer = new();
|
||||
private readonly ManualResetEvent _updateRequiredEvent;
|
||||
|
||||
private readonly AudioQueueOutputCallback _callbackDelegate;
|
||||
private readonly GCHandle _gcHandle;
|
||||
|
||||
private nint _audioQueue;
|
||||
private readonly nint[] _audioQueueBuffers = new nint[NumBuffers];
|
||||
private readonly int[] _bufferBytesFilled = new int[NumBuffers];
|
||||
|
||||
private readonly int _bytesPerFrame;
|
||||
|
||||
private ulong _playedSampleCount;
|
||||
private bool _started;
|
||||
private float _volume = 1f;
|
||||
|
||||
private readonly object _lock = new();
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
private delegate void AudioQueueOutputCallback(
|
||||
nint userData,
|
||||
nint audioQueue,
|
||||
nint buffer);
|
||||
|
||||
public AppleHardwareDeviceSession(
|
||||
AppleHardwareDeviceDriver driver,
|
||||
IVirtualMemoryManager memoryManager,
|
||||
SampleFormat requestedSampleFormat,
|
||||
uint requestedSampleRate,
|
||||
uint requestedChannelCount)
|
||||
: base(memoryManager, requestedSampleFormat, requestedSampleRate, requestedChannelCount)
|
||||
{
|
||||
_driver = driver;
|
||||
_updateRequiredEvent = driver.GetUpdateRequiredEvent();
|
||||
_callbackDelegate = OutputCallback;
|
||||
_bytesPerFrame = BackendHelper.GetSampleSize(requestedSampleFormat) * (int)requestedChannelCount;
|
||||
|
||||
_gcHandle = GCHandle.Alloc(this, GCHandleType.Normal);
|
||||
|
||||
SetupAudioQueue();
|
||||
}
|
||||
|
||||
private void SetupAudioQueue()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
AudioStreamBasicDescription format = AppleHardwareDeviceDriver.GetAudioFormat(
|
||||
RequestedSampleFormat,
|
||||
RequestedSampleRate,
|
||||
RequestedChannelCount);
|
||||
|
||||
nint callbackPtr = Marshal.GetFunctionPointerForDelegate(_callbackDelegate);
|
||||
nint userData = GCHandle.ToIntPtr(_gcHandle);
|
||||
|
||||
int result = AudioQueueNewOutput(
|
||||
ref format,
|
||||
callbackPtr,
|
||||
userData,
|
||||
nint.Zero,
|
||||
nint.Zero,
|
||||
0,
|
||||
out _audioQueue);
|
||||
|
||||
if (result != 0)
|
||||
{
|
||||
throw new InvalidOperationException($"AudioQueueNewOutput failed: {result}");
|
||||
}
|
||||
|
||||
uint framesPerBuffer = RequestedSampleRate / 100;
|
||||
uint bufferSize = framesPerBuffer * (uint)_bytesPerFrame;
|
||||
|
||||
for (int i = 0; i < NumBuffers; i++)
|
||||
{
|
||||
AudioQueueAllocateBuffer(_audioQueue, bufferSize, out _audioQueueBuffers[i]);
|
||||
_bufferBytesFilled[i] = 0;
|
||||
|
||||
PrimeBuffer(_audioQueueBuffers[i], i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private unsafe void PrimeBuffer(nint bufferPtr, int bufferIndex)
|
||||
{
|
||||
AudioQueueBuffer* buffer = (AudioQueueBuffer*)bufferPtr;
|
||||
|
||||
int capacityBytes = (int)buffer->AudioDataBytesCapacity;
|
||||
int framesPerBuffer = capacityBytes / _bytesPerFrame;
|
||||
|
||||
int availableFrames = _ringBuffer.Length / _bytesPerFrame;
|
||||
int framesToRead = Math.Min(availableFrames, framesPerBuffer);
|
||||
int bytesToRead = framesToRead * _bytesPerFrame;
|
||||
|
||||
Span<byte> dst = new((void*)buffer->AudioData, capacityBytes);
|
||||
dst.Clear();
|
||||
|
||||
if (bytesToRead > 0)
|
||||
{
|
||||
Span<byte> audio = dst.Slice(0, bytesToRead);
|
||||
_ringBuffer.Read(audio, 0, bytesToRead);
|
||||
ApplyVolume(buffer->AudioData, bytesToRead);
|
||||
}
|
||||
|
||||
buffer->AudioDataByteSize = (uint)capacityBytes;
|
||||
_bufferBytesFilled[bufferIndex] = bytesToRead;
|
||||
|
||||
AudioQueueEnqueueBuffer(_audioQueue, bufferPtr, 0, nint.Zero);
|
||||
}
|
||||
|
||||
private void OutputCallback(nint userData, nint audioQueue, nint bufferPtr)
|
||||
{
|
||||
if (!_started || bufferPtr == nint.Zero)
|
||||
return;
|
||||
|
||||
int bufferIndex = Array.IndexOf(_audioQueueBuffers, bufferPtr);
|
||||
if (bufferIndex < 0)
|
||||
return;
|
||||
|
||||
int bytesPlayed = _bufferBytesFilled[bufferIndex];
|
||||
if (bytesPlayed > 0)
|
||||
{
|
||||
ProcessPlayedSamples(bytesPlayed);
|
||||
}
|
||||
|
||||
PrimeBuffer(bufferPtr, bufferIndex);
|
||||
}
|
||||
|
||||
private void ProcessPlayedSamples(int bytesPlayed)
|
||||
{
|
||||
ulong samplesPlayed = GetSampleCount(bytesPlayed);
|
||||
ulong remaining = samplesPlayed;
|
||||
bool needUpdate = false;
|
||||
|
||||
while (remaining > 0 && _queuedBuffers.TryPeek(out AppleAudioBuffer buffer))
|
||||
{
|
||||
ulong needed = buffer.SampleCount - Interlocked.Read(ref buffer.SamplePlayed);
|
||||
ulong take = Math.Min(needed, remaining);
|
||||
|
||||
ulong played = Interlocked.Add(ref buffer.SamplePlayed, take);
|
||||
remaining -= take;
|
||||
|
||||
if (played == buffer.SampleCount)
|
||||
{
|
||||
_queuedBuffers.TryDequeue(out _);
|
||||
needUpdate = true;
|
||||
}
|
||||
|
||||
Interlocked.Add(ref _playedSampleCount, take);
|
||||
}
|
||||
|
||||
if (needUpdate)
|
||||
{
|
||||
_updateRequiredEvent.Set();
|
||||
}
|
||||
}
|
||||
|
||||
private unsafe void ApplyVolume(nint dataPtr, int byteSize)
|
||||
{
|
||||
float volume = Math.Clamp(_volume * _driver.Volume, 0f, 1f);
|
||||
if (volume >= 0.999f)
|
||||
return;
|
||||
|
||||
int sampleCount = byteSize / BackendHelper.GetSampleSize(RequestedSampleFormat);
|
||||
|
||||
switch (RequestedSampleFormat)
|
||||
{
|
||||
case SampleFormat.PcmInt16:
|
||||
short* s16 = (short*)dataPtr;
|
||||
for (int i = 0; i < sampleCount; i++)
|
||||
s16[i] = (short)(s16[i] * volume);
|
||||
break;
|
||||
|
||||
case SampleFormat.PcmFloat:
|
||||
float* f32 = (float*)dataPtr;
|
||||
for (int i = 0; i < sampleCount; i++)
|
||||
f32[i] *= volume;
|
||||
break;
|
||||
|
||||
case SampleFormat.PcmInt32:
|
||||
int* s32 = (int*)dataPtr;
|
||||
for (int i = 0; i < sampleCount; i++)
|
||||
s32[i] = (int)(s32[i] * volume);
|
||||
break;
|
||||
|
||||
case SampleFormat.PcmInt8:
|
||||
sbyte* s8 = (sbyte*)dataPtr;
|
||||
for (int i = 0; i < sampleCount; i++)
|
||||
s8[i] = (sbyte)(s8[i] * volume);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override void QueueBuffer(AudioBuffer buffer)
|
||||
{
|
||||
_ringBuffer.Write(buffer.Data, 0, buffer.Data.Length);
|
||||
_queuedBuffers.Enqueue(new AppleAudioBuffer(buffer.DataPointer, GetSampleCount(buffer)));
|
||||
}
|
||||
|
||||
public override void Start()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (_started)
|
||||
return;
|
||||
|
||||
_started = true;
|
||||
AudioQueueStart(_audioQueue, nint.Zero);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Stop()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (!_started)
|
||||
return;
|
||||
|
||||
_started = false;
|
||||
AudioQueuePause(_audioQueue);
|
||||
}
|
||||
}
|
||||
|
||||
public override ulong GetPlayedSampleCount()
|
||||
=> Interlocked.Read(ref _playedSampleCount);
|
||||
|
||||
public override float GetVolume() => _volume;
|
||||
public override void SetVolume(float volume) => _volume = volume;
|
||||
|
||||
public override bool WasBufferFullyConsumed(AudioBuffer buffer)
|
||||
{
|
||||
if (!_queuedBuffers.TryPeek(out AppleAudioBuffer driverBuffer))
|
||||
return true;
|
||||
|
||||
return driverBuffer.DriverIdentifier != buffer.DataPointer;
|
||||
}
|
||||
|
||||
public override void PrepareToClose() { }
|
||||
public override void UnregisterBuffer(AudioBuffer buffer) { }
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
Stop();
|
||||
|
||||
if (_audioQueue != nint.Zero)
|
||||
{
|
||||
AudioQueueStop(_audioQueue, true);
|
||||
AudioQueueDispose(_audioQueue, true);
|
||||
_audioQueue = nint.Zero;
|
||||
}
|
||||
|
||||
if (_gcHandle.IsAllocated)
|
||||
{
|
||||
_gcHandle.Free();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
using System.Runtime.InteropServices;
|
||||
// ReSharper disable InconsistentNaming
|
||||
|
||||
namespace Ryujinx.Audio.Backends.Apple.Native
|
||||
{
|
||||
public static partial class AudioToolbox
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct AudioStreamBasicDescription
|
||||
{
|
||||
public double SampleRate;
|
||||
public uint FormatID;
|
||||
public uint FormatFlags;
|
||||
public uint BytesPerPacket;
|
||||
public uint FramesPerPacket;
|
||||
public uint BytesPerFrame;
|
||||
public uint ChannelsPerFrame;
|
||||
public uint BitsPerChannel;
|
||||
public uint Reserved;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct AudioChannelLayout
|
||||
{
|
||||
public uint AudioChannelLayoutTag;
|
||||
public uint AudioChannelBitmap;
|
||||
public uint NumberChannelDescriptions;
|
||||
}
|
||||
|
||||
internal const uint kAudioFormatLinearPCM = 0x6C70636D;
|
||||
internal const uint kAudioQueueProperty_ChannelLayout = 0x6171636c;
|
||||
internal const uint kAudioChannelLayoutTag_MPEG_5_1_A = 0x650006;
|
||||
internal const uint kAudioFormatFlagIsFloat = (1 << 0);
|
||||
internal const uint kAudioFormatFlagIsSignedInteger = (1 << 2);
|
||||
internal const uint kAudioFormatFlagIsPacked = (1 << 3);
|
||||
internal const uint kAudioFormatFlagIsBigEndian = (1 << 1);
|
||||
internal const uint kAudioFormatFlagIsAlignedHigh = (1 << 4);
|
||||
internal const uint kAudioFormatFlagIsNonInterleaved = (1 << 5);
|
||||
|
||||
[LibraryImport("/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox")]
|
||||
internal static partial int AudioQueueNewOutput(
|
||||
ref AudioStreamBasicDescription format,
|
||||
nint callback,
|
||||
nint userData,
|
||||
nint callbackRunLoop,
|
||||
nint callbackRunLoopMode,
|
||||
uint flags,
|
||||
out nint audioQueue);
|
||||
|
||||
[LibraryImport("/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox")]
|
||||
internal static partial int AudioQueueSetProperty(
|
||||
nint audioQueue,
|
||||
uint propertyID,
|
||||
ref AudioChannelLayout layout,
|
||||
uint layoutSize);
|
||||
|
||||
[LibraryImport("/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox")]
|
||||
internal static partial int AudioQueueDispose(nint audioQueue, [MarshalAs(UnmanagedType.I1)] bool immediate);
|
||||
|
||||
[LibraryImport("/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox")]
|
||||
internal static partial int AudioQueueAllocateBuffer(
|
||||
nint audioQueue,
|
||||
uint bufferByteSize,
|
||||
out nint buffer);
|
||||
|
||||
[LibraryImport("/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox")]
|
||||
internal static partial int AudioQueueStart(nint audioQueue, nint startTime);
|
||||
|
||||
[LibraryImport("/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox")]
|
||||
internal static partial int AudioQueuePause(nint audioQueue);
|
||||
|
||||
[LibraryImport("/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox")]
|
||||
internal static partial int AudioQueueStop(nint audioQueue, [MarshalAs(UnmanagedType.I1)] bool immediate);
|
||||
|
||||
[LibraryImport("/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox")]
|
||||
internal static partial int AudioQueueSetParameter(
|
||||
nint audioQueue,
|
||||
uint parameterID,
|
||||
float value);
|
||||
|
||||
[LibraryImport("/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox")]
|
||||
internal static partial int AudioQueueEnqueueBuffer(
|
||||
nint audioQueue,
|
||||
nint buffer,
|
||||
uint numPacketDescs,
|
||||
nint packetDescs);
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct AudioQueueBuffer
|
||||
{
|
||||
public uint AudioDataBytesCapacity;
|
||||
public nint AudioData;
|
||||
public uint AudioDataByteSize;
|
||||
public nint UserData;
|
||||
public uint PacketDescriptionCapacity;
|
||||
public nint PacketDescriptions;
|
||||
public uint PacketDescriptionCount;
|
||||
}
|
||||
|
||||
internal const uint kAudioQueueParam_Volume = 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Ryujinx.Audio\Ryujinx.Audio.csproj" />
|
||||
<ProjectReference Include="..\Ryujinx.Common\Ryujinx.Common.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -10,7 +10,8 @@ using static Ryujinx.Audio.Integration.IHardwareDeviceDriver;
|
||||
|
||||
namespace Ryujinx.Audio.Backends.OpenAL
|
||||
{
|
||||
public class OpenALHardwareDeviceDriver : IHardwareDeviceDriver
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public sealed class OpenALHardwareDeviceDriver : IHardwareDeviceDriver
|
||||
{
|
||||
private readonly ALDevice _device;
|
||||
private readonly ALContext _context;
|
||||
@@ -148,7 +149,7 @@ namespace Ryujinx.Audio.Backends.OpenAL
|
||||
Dispose(true);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
private void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
@@ -178,7 +179,7 @@ namespace Ryujinx.Audio.Backends.OpenAL
|
||||
|
||||
public bool SupportsChannelCount(uint channelCount)
|
||||
{
|
||||
return channelCount == 1 || channelCount == 2 || channelCount == 6;
|
||||
return channelCount is 1 or 2 or 6;
|
||||
}
|
||||
|
||||
public bool SupportsDirection(Direction direction)
|
||||
|
||||
@@ -9,7 +9,8 @@ using System.Threading;
|
||||
|
||||
namespace Ryujinx.Audio.Backends.OpenAL
|
||||
{
|
||||
class OpenALHardwareDeviceSession : HardwareDeviceSessionOutputBase
|
||||
// ReSharper disable once InconsistentNaming
|
||||
sealed class OpenALHardwareDeviceSession : HardwareDeviceSessionOutputBase
|
||||
{
|
||||
private readonly OpenALHardwareDeviceDriver _driver;
|
||||
private readonly int _sourceId;
|
||||
@@ -190,7 +191,7 @@ namespace Ryujinx.Audio.Backends.OpenAL
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
private void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && _driver.Unregister(this))
|
||||
{
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Ryujinx.Audio\Ryujinx.Audio.csproj" />
|
||||
<ProjectReference Include="..\Ryujinx.SDL2.Common\Ryujinx.SDL2.Common.csproj" />
|
||||
<ProjectReference Include="..\Ryujinx.SDL3.Common\Ryujinx.SDL3.Common.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+3
-3
@@ -1,12 +1,12 @@
|
||||
namespace Ryujinx.Audio.Backends.SDL2
|
||||
namespace Ryujinx.Audio.Backends.SDL3
|
||||
{
|
||||
class SDL2AudioBuffer
|
||||
class SDL3AudioBuffer
|
||||
{
|
||||
public readonly ulong DriverIdentifier;
|
||||
public readonly ulong SampleCount;
|
||||
public ulong SamplePlayed;
|
||||
|
||||
public SDL2AudioBuffer(ulong driverIdentifier, ulong sampleCount)
|
||||
public SDL3AudioBuffer(ulong driverIdentifier, ulong sampleCount)
|
||||
{
|
||||
DriverIdentifier = driverIdentifier;
|
||||
SampleCount = sampleCount;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user