Compare commits

...

104 Commits

Author SHA1 Message Date
GreemDev
ebc775aeb5 update compiling document 2025-11-11 12:54:34 -06:00
GreemDev
e24eb13e07 more partial ObservableProperties 2025-11-11 12:43:34 -06:00
GreemDev
c7572b5d30 chore: change BufferHolder.GetHandle() to a getter for the handle instead 2025-11-11 12:43:34 -06:00
GreemDev
2ea829f17b chore: change MultiRegionHandle GetHandles to an accessor property 2025-11-11 12:43:34 -06:00
GreemDev
9c00ffa4b1 fix conflicts 2025-11-11 12:43:34 -06:00
GreemDev
84f26f7276 language feature: field keyword & partial properties for observable properties in the UI
partial properties are from C# 13 but weren't usable for these properties
2025-11-11 12:43:34 -06:00
GreemDev
f2105d6040 chore: converted BufferHandle ToInt32 extension to an implicit int operator on BufferHandle directly. 2025-11-11 12:43:34 -06:00
GreemDev
1f3e4674b5 chore: Split SoftFloat into multiple partial class parts 2025-11-11 12:43:34 -06:00
GreemDev
342c811aca chore: Split SoftFallback into multiple partial class parts 2025-11-11 12:43:34 -06:00
GreemDev
83502494d9 some more extension members 2025-11-11 12:43:34 -06:00
GreemDev
64238e6ec3 language feature: Extension Members: More converted 2025-11-11 12:43:34 -06:00
GreemDev
36bd919c53 use extension members for StorageProviderExtensions 2025-11-11 12:43:34 -06:00
GreemDev
f1df537e76 language feature: Extension Members: HLE <-> UI enum converters 2025-11-11 12:43:34 -06:00
GreemDev
f9e71a5908 Parse UI enum directly 2025-11-11 12:43:34 -06:00
GreemDev
f20291ddf2 language feature: Extension Members: Misc enum extensions methods converted to properties 2025-11-11 12:43:34 -06:00
GreemDev
cc80621a17 language feature: Extension Members: Ryujinx.Graphics.GAL.Format 2025-11-11 12:43:34 -06:00
GreemDev
6a1dec9f91 language feature: Extension Members: OperandType 2025-11-11 12:43:34 -06:00
GreemDev
274ec74856 language feature: Extension Members: HLE 2025-11-11 12:43:34 -06:00
GreemDev
ac98ade572 language feature: Extension Members: Graphics related, enums 2025-11-11 12:43:34 -06:00
GreemDev
e23213d290 language feature: Extension Members: CPU-related, enums 2025-11-11 12:43:34 -06:00
GreemDev
6467720c5c Add .NET Runtime version in About window under Ryujinx version. 2025-11-11 12:43:34 -06:00
GreemDev
010eab44ba feature: Initial .NET 10 Support
Works as of .NET 10.0.0-preview.3.25171.5
2025-11-11 12:43:34 -06:00
GreemDev
49c70efdd5 UI: App Library: automatically remove nonexistent autoload/game dirs from the configuration upon load. 2025-11-10 19:14:29 -06:00
Babib3l
4677b749b1 fr_FR and es_ES small translation update (ryubing/ryujinx!172)
See merge request ryubing/ryujinx!172
2025-11-10 17:35:17 -06:00
GreemDev
ed32cd6999 fix nested project error when building 2025-11-10 13:32:40 -06:00
GreemDev
d7e2d4534a [ci skip] fix new SDL projects showing up in an src folder in the IDE (idk how I didn't see that before) 2025-11-10 00:12:39 -06:00
LotP
3c3e14c819 Update .gitattributes (ryubing/ryujinx!213)
See merge request ryubing/ryujinx!213
2025-11-09 19:03:01 -06:00
Godzilaa4
dd9ba05e36 Updated PT_BR translation (ryubing/ryujinx!208)
See merge request ryubing/ryujinx!208
2025-11-09 14:36:44 -06:00
Maki
a49822470c fix: crash when connecting a joycon (ryubing/ryujinx!211)
See merge request ryubing/ryujinx!211
2025-11-09 13:35:16 -06:00
GreemDev
58be57bf73 chore: [ci skip] rename InputElement_OnGotFocus/OnLostFocus to fit what it's listening to better 2025-11-08 03:21:54 -06:00
shinyoyo
17d5d6e65a Updated Simplified Chinese translation. (ryubing/ryujinx!209)
See merge request ryubing/ryujinx!209
2025-11-08 03:16:17 -06:00
GreemDev
1dac06e394 misc: [ci skip] remove duplicate log when setting audio backend 2025-11-08 00:18:23 -06:00
GreemDev
ed89ffd3f8 fix: add back compat functionality to the AudioBackend enum as well, and add missing migration comment from config version 70 2025-11-07 22:23:13 -06:00
GreemDev
844d7a9cfe fix: broken arrow in log 2025-11-07 22:14:35 -06:00
GreemDev
cf6acba416 chore: remove debug logging from SDL update 2025-11-07 20:44:25 -06:00
GreemDev
5a9d5ee664 chore: [ci skip] Add more misc logging similar to the "loading content archive" line for loading a base game dump, to updates and DLC. 2025-11-07 15:14:43 -06:00
GreemDev
bbad867319 add back the SDL2 enum for back compatibility so existing configs are not entirely reset upon loading the version with SDL3 2025-11-07 15:02:29 -06:00
Maki
a8ace3d23c chore: SDL3 (ryubing/ryujinx!207)
See merge request ryubing/ryujinx!207
2025-11-07 14:43:48 -06:00
GreemDev
13b69aedfe idea: Catch HorizonResultExceptions of result type ResultFsNonRealDataVerificationFailed
- log a more clear error message as to what 2002-4604 means for the user
- and return the result from the FileSystemProxy IStorage to pass the invalid data handling to the game instead of stopping emulation there and then.
  - this may be changed. i'm pretty sure this error is only thrown when you actually have integrity checking enabled in settings, so maybe it crashing with a friendler message is more desired than potentially continuing execution. we will see
2025-11-06 23:40:16 -06:00
GreemDev
234f7ca298 Fix socket closing on shutdown
Previously, sockets were only ever closed when the game specifically requested it.

Thanks @comex on GitHub for the patch submitted via the issues page.

Co-Authored-By: comex <47517+comex@users.noreply.github.com>
2025-11-04 20:48:36 -06:00
LotP
2c9b193018 Fix compiler warning (ryubing/ryujinx!203)
See merge request ryubing/ryujinx!203
2025-10-30 21:09:24 -05:00
LotP
92b61f9d73 Memory changes 3 (ryubing/ryujinx!202)
See merge request ryubing/ryujinx!202
2025-10-30 20:55:58 -05:00
WilliamWsyHK
ab7aeee67b Add newly translated items for zh-TW (ryubing/ryujinx!200)
See merge request ryubing/ryujinx!200
2025-10-29 18:02:54 -05:00
Hack茶ん
b991fe05d9 Update Korean translation (ryubing/ryujinx!201)
See merge request ryubing/ryujinx!201
2025-10-29 18:01:07 -05:00
GreemDev
3140ec5f05 misc: Also show an error message box and quit if the process was launched with administrator rights. 2025-10-28 20:57:03 -05:00
GreemDev
40f709ff55 misc: Add a launch guard for program files (the emulator does not work properly when put here as it does not require admin) 2025-10-28 19:04:25 -05:00
GreemDev
53aae9b584 hle: Throw a ServiceNotImplementedException instead of ArgumentException if any number arguments provided to ILibraryAppletAccessor are nonzero 2025-10-28 15:37:59 -05:00
LotP
ff9a75f895 ILibraryAppletAccessor:90 tweak (ryubing/ryujinx!199)
See merge request ryubing/ryujinx!199
2025-10-28 13:37:20 -05:00
sh0inx
3394736b07 HLE: Stub ILibraryAppletAccessor Unknown90 (ryubing/ryujinx!197)
See merge request ryubing/ryujinx!197
2025-10-27 12:48:17 -05:00
yeager
b06846aa5e Updated Swedish translation (with updated branch) (ryubing/ryujinx!156)
See merge request ryubing/ryujinx!156
2025-10-27 02:47:59 -05:00
LotP
c94ffaa00a gpu allocation optimizations (ryubing/ryujinx!195)
See merge request ryubing/ryujinx!195
2025-10-26 14:14:51 -05:00
GreemDev
718652599d UI: Prevent null ldn game model arrays from entering the SetEntries method 2025-10-26 12:51:08 -05:00
GreemDev
c8959afa3d chore: Overall code cleanup
Update NuGet packages, fix version string in plist for macOS
2025-10-26 01:22:20 -05:00
Coxxs
7175da8621 UI: [ci skip] Show notifications for options that may cause side effects (ryubing/ryujinx!193)
See merge request ryubing/ryujinx!193
2025-10-26 00:29:38 -05:00
LotP
fd07453887 audio effects fix and audio object pooling (ryubing/ryujinx!192)
See merge request ryubing/ryujinx!192
2025-10-25 21:07:10 -05:00
KeatonTheBot
c6bc77e4bf UI: Update Avalonia to 11.3.6, FluentAvalonia to 2.4.0 (ryubing/ryujinx!118)
See merge request ryubing/ryujinx!118
2025-10-25 00:29:51 -05:00
GreemDev
49cbe4b328 UI: fix "Enable UI logs" not being persisted upon relaunch
Closes ryujinx#5

(it was saved, just not loaded back)
2025-10-24 18:25:29 -05:00
Coxxs
6fd67cdcb7 Fix application list loads slowly when RyuLDN is enabled (ryubing/ryujinx!191)
See merge request ryubing/ryujinx!191
2025-10-24 10:29:33 -05:00
LotP
5ced2bf764 fix wrong bit value (ryubing/ryujinx!190)
See merge request ryubing/ryujinx!190
2025-10-24 10:10:31 -05:00
GreemDev
67e97d1a1a gdb: YACC (yet another cleanup commit) 2025-10-23 19:11:58 -05:00
Coxxs
09d8a411c8 Do not RecurseSubdirectories when finding the icon fallback (ryubing/ryujinx!189)
See merge request ryubing/ryujinx!189
2025-10-23 15:17:29 -05:00
Coxxs
93516df7e6 Skip directories when finding the icon fallback (ryubing/ryujinx!188)
See merge request ryubing/ryujinx!188
2025-10-23 14:56:39 -05:00
Coxxs
0c165c3f62 Move ProcessInfo and Minidump to HleProcessDebugger (ryubing/ryujinx!187)
See merge request ryubing/ryujinx!187
2025-10-22 16:20:13 -05:00
GreemDev
91da244c02 gdb: some more cleanups 2025-10-22 15:04:03 -05:00
GreemDev
904d4a7eb0 gdb: Make waiting for a process to start more forgiving (200ms per poll 10x -> 500ms) 2025-10-22 01:07:19 -05:00
Coxxs
1248a054de gdb: Abort if unable to start GDB server (ryubing/ryujinx!186)
See merge request ryubing/ryujinx!186
2025-10-21 23:16:18 -05:00
GreemDev
1bb2af84ce gdb: Catch SocketException from TcpListener#Start 2025-10-21 22:15:14 -05:00
GreemDev
886981004d chore: I thought I removed these months ago lol 2025-10-21 20:33:35 -05:00
Coxxs
e551dda17e gdb: fix IsProcess32Bit throws exception if called too early (ryubing/ryujinx!185)
See merge request ryubing/ryujinx!185
2025-10-20 21:35:55 -05:00
GreemDev
ed67535227 chore: [si skip] fix in-code typos 2025-10-20 21:32:23 -05:00
GreemDev
7d65611b96 gdb: [ci skip] just had a brain wave 2025-10-20 21:20:41 -05:00
GreemDev
71eb844dd8 gdb: dynamic rcmd system & more cleanups 2025-10-20 21:18:16 -05:00
Coxxs
a0e5edf8ba gdb: Support qAttached; Add missing ReplyOK when detach (ryubing/ryujinx!184)
See merge request ryubing/ryujinx!184
2025-10-20 21:12:16 -05:00
Coxxs
6541ad0726 Implement IUserServiceCreator: 1 (CreateClientProcessMonitor) (ryubing/ryujinx!181)
See merge request ryubing/ryujinx!181
2025-10-20 19:14:42 -05:00
Coxxs
1c084373c9 Update LoadIdTokenCache for 19.0.0+ (ryubing/ryujinx!182)
See merge request ryubing/ryujinx!182
2025-10-20 17:37:16 -05:00
GreemDev
5b3b907fd2 [ci skip] chore: Fix usage of var 2025-10-20 02:42:57 -05:00
Hack茶ん
f46577af58 [ci skip] Update Korean translation (ryubing/ryujinx!174)
See merge request ryubing/ryujinx!174
2025-10-19 17:43:34 -05:00
Xam
0e218754f5 Fix duplicate volume and mode change events in AppHost (ryubing/ryujinx!176)
See merge request ryubing/ryujinx!176
2025-10-19 17:41:21 -05:00
Xam
0c6d4a07b9 Input: AvaloniaMouseDriver: fix native touch inputs (ryubing/ryujinx!178)
See merge request ryubing/ryujinx!178
2025-10-19 17:33:24 -05:00
Xam
8714b010f6 Horizon: Audio: HwopusIpcServer: fix random crashes regression in Pokemon Quest (ryubing/ryujinx!175)
See merge request ryubing/ryujinx!175
2025-10-19 17:17:46 -05:00
GreemDev
d1d4a735a6 docs: use the real repo in COMPILING.md 2025-10-19 14:48:41 -05:00
GreemDev
247e2e03d6 gdb: More cleanup changes
- Move the message handler into its debugger class part,
- Move all message types into one file and collapse 3 of the ones with no data into a generic, stateless message with a single property being its type,
- Add an Fpscr helper property on IExecutionContext along with a comment about what Fpscr is (similar to the other registers in there)
- Moved the Rcmd helpers (such as GetRegisters, GetMinidump, etc) into a dedicated Debugger class part,
- Fixed the double-collection (ToArray being called twice) in GetThreadUids & GetThread in KProcess
2025-10-19 04:26:12 -05:00
GreemDev
6058af5119 chore: cleanup unused usings in Ryujinx.HLE 2025-10-19 04:17:02 -05:00
GreemDev
e11eff0f41 gdb: more cleanups
- convert GdbRegisters utilities into extensions on IExecutionContext

- add a Write/Read Register helper on Debugger that handles 32/64 bit instead of doing that for every usage of register reading/writing
2025-10-18 03:01:21 -05:00
GreemDev
2a2ab523cb gdb: Code cleanup pass #2
Moved the reply functionality into the command processor, move the main debugger thread into a dedicated class part, and more
2025-10-17 00:09:51 -05:00
Coxxs
8e941e4a8f gdb: Cleanup (ryubing/ryujinx!171)
See merge request ryubing/ryujinx!171
2025-10-16 19:53:51 -05:00
Hack茶ん
9aacf9b37b Update Korean translation (ryubing/ryujinx!168)
See merge request ryubing/ryujinx!168
2025-10-16 19:45:14 -05:00
Bluey Enjoyer
2b159dbca8 AHHHHHHHHHHHHHH (ryubing/ryujinx!170)
See merge request ryubing/ryujinx!170
2025-10-16 19:43:56 -05:00
GreemDev
c33a97f01c gdb: Cleanup Debugger.cs
by moving the GDB command handlers and command processor out of the class and into their own
2025-10-16 17:32:04 -05:00
GreemDev
fdbdb05cb5 misc: Update Ryujinx.LibHac 2025-10-16 12:23:15 -05:00
Coxxs
7268acbfb4 gdb: Do not skip CheckInterrupt when gdb stub is enabled (ryubing/ryujinx!169)
See merge request ryubing/ryujinx!169
2025-10-16 07:49:41 -05:00
GreemDev
d4107ac05f UI: Add a startup flag to ignore new Amiibo file updates, useful for testing changes you intend on committing to Ryubing/Nfc.
Flag is `--local-only-amiibo`
2025-10-15 21:51:13 -05:00
LotP
1d409f7127 12 GiB heap support (ryubing/ryujinx!166)
See merge request ryubing/ryujinx!166
2025-10-15 15:37:13 -05:00
GreemDev
2434c55266 UI: Updater: Fix "No" opening the changelog and "Show Changelog" doing nothing (aka doing what "No" should be doing) 2025-10-14 18:38:56 -05:00
GreemDev
99126603ba UI: swap the UI reset checkbox text back to a sentence instead of title cased 2025-10-14 16:12:11 -05:00
GreemDev
a62716002e chore: move HasPtcCacheFiles & HasShaderCacheFiles into ApplicationData, instead of having the weird static dependency helpers 2025-10-14 16:09:51 -05:00
GreemDev
47559cd311 Revert game list rounding
The selected highlight was bugged

https://fs.ryujinx.app/40cl4Ih9RiOWLVi7e4lJsw.png
2025-10-14 15:59:02 -05:00
Coxxs
51584a083b Flush the error log before exit (ryubing/ryujinx!163)
See merge request ryubing/ryujinx!163
2025-10-13 17:40:15 -05:00
Coxxs
ceec9617ef gdb: Fix the crash that occurs when GDB is connected early (ryubing/ryujinx!159)
See merge request ryubing/ryujinx!159
2025-10-11 19:06:14 -05:00
Coxxs
1865be47cf gdb: Add monitor minidump command (ryubing/ryujinx!158)
See merge request ryubing/ryujinx!158
2025-10-11 10:01:30 -05:00
LotP
ef9810582a Sync thread name on Schedule (ryubing/ryujinx!157)
See merge request ryubing/ryujinx!157
2025-10-11 07:47:45 -05:00
KeatonTheBot
13878acdb2 Avoid lookup of invalid textures if pool did not change (ryubing/ryujinx!113)
See merge request ryubing/ryujinx!113
2025-10-11 02:56:13 -05:00
LotP
e2143d43bc SDK20 and REV15 support (ryubing/ryujinx!50)
See merge request ryubing/ryujinx!50
2025-10-11 02:11:39 -05:00
Astell
4444ecae41 fix super mario galaxy 0x25E00040 error (ryubing/ryujinx!155)
See merge request ryubing/ryujinx!155
2025-10-10 17:37:42 -05:00
480 changed files with 14116 additions and 11921 deletions

1
.gitattributes vendored
View File

@@ -2,3 +2,4 @@
# Set default behavior to automatically normalize line endings. # Set default behavior to automatically normalize line endings.
############################################################################### ###############################################################################
* text=auto eol=lf * text=auto eol=lf
*.json text eol=lf

View File

@@ -5,12 +5,12 @@ If you wish to build the emulator yourself, follow these steps:
### Step 1 ### Step 1
Install the [.NET 9.0 (or higher) SDK](https://dotnet.microsoft.com/download/dotnet/9.0). Install the [.NET 10.0 (or higher) SDK](https://dotnet.microsoft.com/en-us/download/dotnet/10.0).
Make sure your SDK version is higher or equal to the required version specified in [global.json](global.json). Make sure your SDK version is higher or equal to the required version specified in [global.json](global.json).
### Step 2 ### Step 2
Either use `git clone https://github.com/Ryubing/Ryujinx` 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/ryubing/ryujinx.git` on the command line to clone the repository or use Code --> Download zip button to get the files.
### Step 3 ### Step 3

View File

@@ -1,6 +1,6 @@
<Project> <Project>
<PropertyGroup> <PropertyGroup>
<TargetFramework>net9.0</TargetFramework> <TargetFramework>net10.0</TargetFramework>
<LangVersion>latest</LangVersion> <LangVersion>preview</LangVersion>
</PropertyGroup> </PropertyGroup>
</Project> </Project>

View File

@@ -3,25 +3,26 @@
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally> <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageVersion Include="Avalonia" Version="11.0.13" /> <PackageVersion Include="Avalonia" Version="11.3.6" />
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.0.13" /> <PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.3.6" />
<PackageVersion Include="Avalonia.Desktop" Version="11.0.13" /> <PackageVersion Include="Avalonia.Desktop" Version="11.3.6" />
<PackageVersion Include="Avalonia.Diagnostics" Version="11.0.13" /> <PackageVersion Include="Avalonia.Diagnostics" Version="11.3.6" />
<PackageVersion Include="Avalonia.Markup.Xaml.Loader" Version="11.0.13" /> <PackageVersion Include="Avalonia.Markup.Xaml.Loader" Version="11.3.6" />
<PackageVersion Include="Avalonia.Svg" Version="11.0.0.19" /> <PackageVersion Include="Svg.Controls.Avalonia" Version="11.3.6.2" />
<PackageVersion Include="Avalonia.Svg.Skia" Version="11.0.0.19" /> <PackageVersion Include="Svg.Controls.Skia.Avalonia" Version="11.3.6.2" />
<PackageVersion Include="Microsoft.Build.Framework" Version="17.11.4" /> <PackageVersion Include="Microsoft.Build.Framework" Version="17.11.4" />
<PackageVersion Include="Microsoft.Build.Utilities.Core" Version="17.12.6" /> <PackageVersion Include="Microsoft.Build.Utilities.Core" Version="17.12.6" />
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" /> <PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
<PackageVersion Include="Projektanker.Icons.Avalonia" Version="9.4.0" /> <PackageVersion Include="Projektanker.Icons.Avalonia" Version="9.6.2" />
<PackageVersion Include="Projektanker.Icons.Avalonia.FontAwesome" Version="9.4.0"/> <PackageVersion Include="Projektanker.Icons.Avalonia.FontAwesome" Version="9.6.2" />
<PackageVersion Include="Projektanker.Icons.Avalonia.MaterialDesign" Version="9.4.0"/> <PackageVersion Include="Projektanker.Icons.Avalonia.MaterialDesign" Version="9.6.2" />
<PackageVersion Include="ppy.SDL3-CS" Version="2025.920.0" />
<PackageVersion Include="CommandLineParser" Version="2.9.1" /> <PackageVersion Include="CommandLineParser" Version="2.9.1" />
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.4.0"/> <PackageVersion Include="CommunityToolkit.Mvvm" Version="8.4.0" />
<PackageVersion Include="Concentus" Version="2.2.2" /> <PackageVersion Include="Concentus" Version="2.2.2" />
<PackageVersion Include="DiscordRichPresence" Version="1.6.1.70" /> <PackageVersion Include="DiscordRichPresence" Version="1.6.1.70" />
<PackageVersion Include="DynamicData" Version="9.4.1" /> <PackageVersion Include="DynamicData" Version="9.4.1" />
<PackageVersion Include="FluentAvaloniaUI" Version="2.0.5" /> <PackageVersion Include="FluentAvaloniaUI.NoAnim" Version="2.4.0-build3" />
<PackageVersion Include="Humanizer" Version="2.14.1" /> <PackageVersion Include="Humanizer" Version="2.14.1" />
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" /> <PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.9.2" /> <PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.9.2" />
@@ -40,11 +41,10 @@
<PackageVersion Include="Ryujinx.Audio.OpenAL.Dependencies" Version="1.21.0.1" /> <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.Nvdec.Dependencies.AllArch" Version="6.1.2-build3" />
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" /> <PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
<PackageVersion Include="Ryujinx.LibHac" Version="0.21.0-alpha.116" /> <PackageVersion Include="Ryujinx.LibHac" Version="0.21.0-alpha.126" />
<PackageVersion Include="Ryujinx.SDL2-CS" Version="2.30.0-build32" />
<PackageVersion Include="Ryujinx.UpdateClient" Version="1.0.44" /> <PackageVersion Include="Ryujinx.UpdateClient" Version="1.0.44" />
<PackageVersion Include="Ryujinx.Systems.Update.Common" Version="1.0.44" /> <PackageVersion Include="Ryujinx.Systems.Update.Common" Version="1.0.44" />
<PackageVersion Include="Gommon" Version="2.7.2.1" /> <PackageVersion Include="Gommon" Version="2.8.0.1" />
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" /> <PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
<PackageVersion Include="Sep" Version="0.11.1" /> <PackageVersion Include="Sep" Version="0.11.1" />
<PackageVersion Include="shaderc.net" Version="0.1.0" /> <PackageVersion Include="shaderc.net" Version="0.1.0" />
@@ -59,4 +59,4 @@
<PackageVersion Include="System.Management" Version="9.0.2" /> <PackageVersion Include="System.Management" Version="9.0.2" />
<PackageVersion Include="UnicornEngine.Unicorn" Version="2.0.2-rc1-fb78016" /> <PackageVersion Include="UnicornEngine.Unicorn" Version="2.0.2-rc1-fb78016" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -66,7 +66,7 @@ If you are planning to contribute or just want to learn more about this project
- **Audio** - **Audio**
Audio output is entirely supported, audio input (microphone) isn't supported. Audio output is entirely supported, audio input (microphone) isn't supported.
We use C# wrappers for [OpenAL](https://openal-soft.org/), and [SDL2](https://www.libsdl.org/) & [libsoundio](http://libsound.io/) as fallbacks. We use C# wrappers for [OpenAL](https://openal-soft.org/), and [SDL3](https://www.libsdl.org/) & [libsoundio](http://libsound.io/) as fallbacks.
- **CPU** - **CPU**

View File

@@ -45,17 +45,15 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Vic", "src
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Video", "src\Ryujinx.Graphics.Video\Ryujinx.Graphics.Video.csproj", "{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Video", "src\Ryujinx.Graphics.Video\Ryujinx.Graphics.Video.csproj", "{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Audio.Backends.SDL3", "src\Ryujinx.Audio.Backends.SDL3\Ryujinx.Audio.Backends.SDL3.csproj", "{988E6191-82E1-4E13-9DDB-CB9FA2FDAF29}"
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}" 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 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}" 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 EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Input", "src\Ryujinx.Input\Ryujinx.Input.csproj", "{C16F112F-38C3-40BC-9F5F-4791112063D6}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Input", "src\Ryujinx.Input\Ryujinx.Input.csproj", "{C16F112F-38C3-40BC-9F5F-4791112063D6}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Input.SDL2", "src\Ryujinx.Input.SDL2\Ryujinx.Input.SDL2.csproj", "{DFAB6F2D-B9BF-4AFF-B22B-7684A328EBA3}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Input.SDL3", "src\Ryujinx.Input.SDL3\Ryujinx.Input.SDL3.csproj", "{D728444C-3D1F-4A0E-B4C9-5C9375D47EA3}"
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 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}" 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 EndProject
@@ -79,12 +77,15 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.HLE.Generators", "s
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ryujinx.BuildValidationTasks", "src\Ryujinx.BuildValidationTasks\Ryujinx.BuildValidationTasks.csproj", "{4A89A234-4F19-497D-A576-DDE8CDFC5B22}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ryujinx.BuildValidationTasks", "src\Ryujinx.BuildValidationTasks\Ryujinx.BuildValidationTasks.csproj", "{4A89A234-4F19-497D-A576-DDE8CDFC5B22}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.SDL3.Common", "src\Ryujinx.SDL3.Common\Ryujinx.SDL3.Common.csproj", "{F6F9826A-BC58-4D78-A700-F358A66B2B06}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{36F870C1-3E5F-485F-B426-F0645AF78751}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{36F870C1-3E5F-485F-B426-F0645AF78751}"
ProjectSection(SolutionItems) = preProject ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig .editorconfig = .editorconfig
.github\workflows\build.yml = .github\workflows\build.yml .github\workflows\build.yml = .github\workflows\build.yml
.github\workflows\canary.yml = .github\workflows\canary.yml .github\workflows\canary.yml = .github\workflows\canary.yml
Directory.Packages.props = Directory.Packages.props Directory.Packages.props = Directory.Packages.props
Directory.Build.props = Directory.Build.props
.github\workflows\release.yml = .github\workflows\release.yml .github\workflows\release.yml = .github\workflows\release.yml
nuget.config = nuget.config nuget.config = nuget.config
EndProjectSection EndProjectSection
@@ -92,164 +93,468 @@ EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution GlobalSection(ProjectConfigurationPlatforms) = postSolution
{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {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}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Debug|x64.ActiveCfg = Debug|Any CPU
{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Debug|x64.Build.0 = Debug|Any CPU
{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Debug|x86.ActiveCfg = Debug|Any CPU
{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Debug|x86.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.ActiveCfg = Release|Any CPU
{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Release|Any CPU.Build.0 = Release|Any CPU {EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Release|Any CPU.Build.0 = Release|Any CPU
{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Release|x64.ActiveCfg = Release|Any CPU
{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Release|x64.Build.0 = Release|Any CPU
{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Release|x86.ActiveCfg = Release|Any CPU
{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Release|x86.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.ActiveCfg = Debug|Any CPU
{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}.Debug|Any CPU.Build.0 = Debug|Any CPU {D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}.Debug|x64.ActiveCfg = Debug|Any CPU
{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}.Debug|x64.Build.0 = Debug|Any CPU
{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}.Debug|x86.ActiveCfg = Debug|Any CPU
{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}.Debug|x86.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.ActiveCfg = Release|Any CPU
{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}.Release|Any CPU.Build.0 = Release|Any CPU {D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}.Release|Any CPU.Build.0 = Release|Any CPU
{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}.Release|x64.ActiveCfg = Release|Any CPU
{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}.Release|x64.Build.0 = Release|Any CPU
{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}.Release|x86.ActiveCfg = Release|Any CPU
{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}.Release|x86.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.ActiveCfg = Debug|Any CPU
{CB92CFF9-1D62-4D4F-9E88-8130EF61E351}.Debug|Any CPU.Build.0 = Debug|Any CPU {CB92CFF9-1D62-4D4F-9E88-8130EF61E351}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CB92CFF9-1D62-4D4F-9E88-8130EF61E351}.Debug|x64.ActiveCfg = Debug|Any CPU
{CB92CFF9-1D62-4D4F-9E88-8130EF61E351}.Debug|x64.Build.0 = Debug|Any CPU
{CB92CFF9-1D62-4D4F-9E88-8130EF61E351}.Debug|x86.ActiveCfg = Debug|Any CPU
{CB92CFF9-1D62-4D4F-9E88-8130EF61E351}.Debug|x86.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.ActiveCfg = Release|Any CPU
{CB92CFF9-1D62-4D4F-9E88-8130EF61E351}.Release|Any CPU.Build.0 = Release|Any CPU {CB92CFF9-1D62-4D4F-9E88-8130EF61E351}.Release|Any CPU.Build.0 = Release|Any CPU
{CB92CFF9-1D62-4D4F-9E88-8130EF61E351}.Release|x64.ActiveCfg = Release|Any CPU
{CB92CFF9-1D62-4D4F-9E88-8130EF61E351}.Release|x64.Build.0 = Release|Any CPU
{CB92CFF9-1D62-4D4F-9E88-8130EF61E351}.Release|x86.ActiveCfg = Release|Any CPU
{CB92CFF9-1D62-4D4F-9E88-8130EF61E351}.Release|x86.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.ActiveCfg = Debug|Any CPU
{3AB294D0-2230-468F-9EB3-BDFCAEAE99A5}.Debug|Any CPU.Build.0 = Debug|Any CPU {3AB294D0-2230-468F-9EB3-BDFCAEAE99A5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3AB294D0-2230-468F-9EB3-BDFCAEAE99A5}.Debug|x64.ActiveCfg = Debug|Any CPU
{3AB294D0-2230-468F-9EB3-BDFCAEAE99A5}.Debug|x64.Build.0 = Debug|Any CPU
{3AB294D0-2230-468F-9EB3-BDFCAEAE99A5}.Debug|x86.ActiveCfg = Debug|Any CPU
{3AB294D0-2230-468F-9EB3-BDFCAEAE99A5}.Debug|x86.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.ActiveCfg = Release|Any CPU
{3AB294D0-2230-468F-9EB3-BDFCAEAE99A5}.Release|Any CPU.Build.0 = Release|Any CPU {3AB294D0-2230-468F-9EB3-BDFCAEAE99A5}.Release|Any CPU.Build.0 = Release|Any CPU
{3AB294D0-2230-468F-9EB3-BDFCAEAE99A5}.Release|x64.ActiveCfg = Release|Any CPU
{3AB294D0-2230-468F-9EB3-BDFCAEAE99A5}.Release|x64.Build.0 = Release|Any CPU
{3AB294D0-2230-468F-9EB3-BDFCAEAE99A5}.Release|x86.ActiveCfg = Release|Any CPU
{3AB294D0-2230-468F-9EB3-BDFCAEAE99A5}.Release|x86.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.ActiveCfg = Debug|Any CPU
{5FD4E4F6-8928-4B3C-BE07-28A675C17226}.Debug|Any CPU.Build.0 = Debug|Any CPU {5FD4E4F6-8928-4B3C-BE07-28A675C17226}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5FD4E4F6-8928-4B3C-BE07-28A675C17226}.Debug|x64.ActiveCfg = Debug|Any CPU
{5FD4E4F6-8928-4B3C-BE07-28A675C17226}.Debug|x64.Build.0 = Debug|Any CPU
{5FD4E4F6-8928-4B3C-BE07-28A675C17226}.Debug|x86.ActiveCfg = Debug|Any CPU
{5FD4E4F6-8928-4B3C-BE07-28A675C17226}.Debug|x86.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.ActiveCfg = Release|Any CPU
{5FD4E4F6-8928-4B3C-BE07-28A675C17226}.Release|Any CPU.Build.0 = Release|Any CPU {5FD4E4F6-8928-4B3C-BE07-28A675C17226}.Release|Any CPU.Build.0 = Release|Any CPU
{5FD4E4F6-8928-4B3C-BE07-28A675C17226}.Release|x64.ActiveCfg = Release|Any CPU
{5FD4E4F6-8928-4B3C-BE07-28A675C17226}.Release|x64.Build.0 = Release|Any CPU
{5FD4E4F6-8928-4B3C-BE07-28A675C17226}.Release|x86.ActiveCfg = Release|Any CPU
{5FD4E4F6-8928-4B3C-BE07-28A675C17226}.Release|x86.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.ActiveCfg = Debug|Any CPU
{ABF09A5E-2D8B-4B6F-A51D-5CE414DDB15A}.Debug|Any CPU.Build.0 = Debug|Any CPU {ABF09A5E-2D8B-4B6F-A51D-5CE414DDB15A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ABF09A5E-2D8B-4B6F-A51D-5CE414DDB15A}.Debug|x64.ActiveCfg = Debug|Any CPU
{ABF09A5E-2D8B-4B6F-A51D-5CE414DDB15A}.Debug|x64.Build.0 = Debug|Any CPU
{ABF09A5E-2D8B-4B6F-A51D-5CE414DDB15A}.Debug|x86.ActiveCfg = Debug|Any CPU
{ABF09A5E-2D8B-4B6F-A51D-5CE414DDB15A}.Debug|x86.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.ActiveCfg = Release|Any CPU
{ABF09A5E-2D8B-4B6F-A51D-5CE414DDB15A}.Release|Any CPU.Build.0 = Release|Any CPU {ABF09A5E-2D8B-4B6F-A51D-5CE414DDB15A}.Release|Any CPU.Build.0 = Release|Any CPU
{ABF09A5E-2D8B-4B6F-A51D-5CE414DDB15A}.Release|x64.ActiveCfg = Release|Any CPU
{ABF09A5E-2D8B-4B6F-A51D-5CE414DDB15A}.Release|x64.Build.0 = Release|Any CPU
{ABF09A5E-2D8B-4B6F-A51D-5CE414DDB15A}.Release|x86.ActiveCfg = Release|Any CPU
{ABF09A5E-2D8B-4B6F-A51D-5CE414DDB15A}.Release|x86.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.ActiveCfg = Debug|Any CPU
{ADA7EA87-0D63-4D97-9433-922A2124401F}.Debug|Any CPU.Build.0 = Debug|Any CPU {ADA7EA87-0D63-4D97-9433-922A2124401F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ADA7EA87-0D63-4D97-9433-922A2124401F}.Debug|x64.ActiveCfg = Debug|Any CPU
{ADA7EA87-0D63-4D97-9433-922A2124401F}.Debug|x64.Build.0 = Debug|Any CPU
{ADA7EA87-0D63-4D97-9433-922A2124401F}.Debug|x86.ActiveCfg = Debug|Any CPU
{ADA7EA87-0D63-4D97-9433-922A2124401F}.Debug|x86.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.ActiveCfg = Release|Any CPU
{ADA7EA87-0D63-4D97-9433-922A2124401F}.Release|Any CPU.Build.0 = Release|Any CPU {ADA7EA87-0D63-4D97-9433-922A2124401F}.Release|Any CPU.Build.0 = Release|Any CPU
{ADA7EA87-0D63-4D97-9433-922A2124401F}.Release|x64.ActiveCfg = Release|Any CPU
{ADA7EA87-0D63-4D97-9433-922A2124401F}.Release|x64.Build.0 = Release|Any CPU
{ADA7EA87-0D63-4D97-9433-922A2124401F}.Release|x86.ActiveCfg = Release|Any CPU
{ADA7EA87-0D63-4D97-9433-922A2124401F}.Release|x86.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.ActiveCfg = Debug|Any CPU
{A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E}.Debug|Any CPU.Build.0 = Debug|Any CPU {A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E}.Debug|x64.ActiveCfg = Debug|Any CPU
{A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E}.Debug|x64.Build.0 = Debug|Any CPU
{A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E}.Debug|x86.ActiveCfg = Debug|Any CPU
{A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E}.Debug|x86.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.ActiveCfg = Release|Any CPU
{A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E}.Release|Any CPU.Build.0 = Release|Any CPU {A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E}.Release|Any CPU.Build.0 = Release|Any CPU
{A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E}.Release|x64.ActiveCfg = Release|Any CPU
{A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E}.Release|x64.Build.0 = Release|Any CPU
{A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E}.Release|x86.ActiveCfg = Release|Any CPU
{A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E}.Release|x86.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.ActiveCfg = Debug|Any CPU
{9558FB96-075D-4219-8FFF-401979DC0B69}.Debug|Any CPU.Build.0 = Debug|Any CPU {9558FB96-075D-4219-8FFF-401979DC0B69}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9558FB96-075D-4219-8FFF-401979DC0B69}.Debug|x64.ActiveCfg = Debug|Any CPU
{9558FB96-075D-4219-8FFF-401979DC0B69}.Debug|x64.Build.0 = Debug|Any CPU
{9558FB96-075D-4219-8FFF-401979DC0B69}.Debug|x86.ActiveCfg = Debug|Any CPU
{9558FB96-075D-4219-8FFF-401979DC0B69}.Debug|x86.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.ActiveCfg = Release|Any CPU
{9558FB96-075D-4219-8FFF-401979DC0B69}.Release|Any CPU.Build.0 = Release|Any CPU {9558FB96-075D-4219-8FFF-401979DC0B69}.Release|Any CPU.Build.0 = Release|Any CPU
{9558FB96-075D-4219-8FFF-401979DC0B69}.Release|x64.ActiveCfg = Release|Any CPU
{9558FB96-075D-4219-8FFF-401979DC0B69}.Release|x64.Build.0 = Release|Any CPU
{9558FB96-075D-4219-8FFF-401979DC0B69}.Release|x86.ActiveCfg = Release|Any CPU
{9558FB96-075D-4219-8FFF-401979DC0B69}.Release|x86.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.ActiveCfg = Debug|Any CPU
{E1B1AD28-289D-47B7-A106-326972240207}.Debug|Any CPU.Build.0 = Debug|Any CPU {E1B1AD28-289D-47B7-A106-326972240207}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E1B1AD28-289D-47B7-A106-326972240207}.Debug|x64.ActiveCfg = Debug|Any CPU
{E1B1AD28-289D-47B7-A106-326972240207}.Debug|x64.Build.0 = Debug|Any CPU
{E1B1AD28-289D-47B7-A106-326972240207}.Debug|x86.ActiveCfg = Debug|Any CPU
{E1B1AD28-289D-47B7-A106-326972240207}.Debug|x86.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.ActiveCfg = Release|Any CPU
{E1B1AD28-289D-47B7-A106-326972240207}.Release|Any CPU.Build.0 = Release|Any CPU {E1B1AD28-289D-47B7-A106-326972240207}.Release|Any CPU.Build.0 = Release|Any CPU
{E1B1AD28-289D-47B7-A106-326972240207}.Release|x64.ActiveCfg = Release|Any CPU
{E1B1AD28-289D-47B7-A106-326972240207}.Release|x64.Build.0 = Release|Any CPU
{E1B1AD28-289D-47B7-A106-326972240207}.Release|x86.ActiveCfg = Release|Any CPU
{E1B1AD28-289D-47B7-A106-326972240207}.Release|x86.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.ActiveCfg = Debug|Any CPU
{03B955CD-AD84-4B93-AAA7-BF17923BBAA5}.Debug|Any CPU.Build.0 = Debug|Any CPU {03B955CD-AD84-4B93-AAA7-BF17923BBAA5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{03B955CD-AD84-4B93-AAA7-BF17923BBAA5}.Debug|x64.ActiveCfg = Debug|Any CPU
{03B955CD-AD84-4B93-AAA7-BF17923BBAA5}.Debug|x64.Build.0 = Debug|Any CPU
{03B955CD-AD84-4B93-AAA7-BF17923BBAA5}.Debug|x86.ActiveCfg = Debug|Any CPU
{03B955CD-AD84-4B93-AAA7-BF17923BBAA5}.Debug|x86.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.ActiveCfg = Release|Any CPU
{03B955CD-AD84-4B93-AAA7-BF17923BBAA5}.Release|Any CPU.Build.0 = Release|Any CPU {03B955CD-AD84-4B93-AAA7-BF17923BBAA5}.Release|Any CPU.Build.0 = Release|Any CPU
{03B955CD-AD84-4B93-AAA7-BF17923BBAA5}.Release|x64.ActiveCfg = Release|Any CPU
{03B955CD-AD84-4B93-AAA7-BF17923BBAA5}.Release|x64.Build.0 = Release|Any CPU
{03B955CD-AD84-4B93-AAA7-BF17923BBAA5}.Release|x86.ActiveCfg = Release|Any CPU
{03B955CD-AD84-4B93-AAA7-BF17923BBAA5}.Release|x86.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.ActiveCfg = Debug|Any CPU
{85A0FA56-DC01-4A42-8808-70DAC76BD66D}.Debug|Any CPU.Build.0 = Debug|Any CPU {85A0FA56-DC01-4A42-8808-70DAC76BD66D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{85A0FA56-DC01-4A42-8808-70DAC76BD66D}.Debug|x64.ActiveCfg = Debug|Any CPU
{85A0FA56-DC01-4A42-8808-70DAC76BD66D}.Debug|x64.Build.0 = Debug|Any CPU
{85A0FA56-DC01-4A42-8808-70DAC76BD66D}.Debug|x86.ActiveCfg = Debug|Any CPU
{85A0FA56-DC01-4A42-8808-70DAC76BD66D}.Debug|x86.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.ActiveCfg = Release|Any CPU
{85A0FA56-DC01-4A42-8808-70DAC76BD66D}.Release|Any CPU.Build.0 = Release|Any CPU {85A0FA56-DC01-4A42-8808-70DAC76BD66D}.Release|Any CPU.Build.0 = Release|Any CPU
{85A0FA56-DC01-4A42-8808-70DAC76BD66D}.Release|x64.ActiveCfg = Release|Any CPU
{85A0FA56-DC01-4A42-8808-70DAC76BD66D}.Release|x64.Build.0 = Release|Any CPU
{85A0FA56-DC01-4A42-8808-70DAC76BD66D}.Release|x86.ActiveCfg = Release|Any CPU
{85A0FA56-DC01-4A42-8808-70DAC76BD66D}.Release|x86.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.ActiveCfg = Debug|Any CPU
{806ACF6D-90B0-45D0-A1AC-5F220F3B3985}.Debug|Any CPU.Build.0 = Debug|Any CPU {806ACF6D-90B0-45D0-A1AC-5F220F3B3985}.Debug|Any CPU.Build.0 = Debug|Any CPU
{806ACF6D-90B0-45D0-A1AC-5F220F3B3985}.Debug|x64.ActiveCfg = Debug|Any CPU
{806ACF6D-90B0-45D0-A1AC-5F220F3B3985}.Debug|x64.Build.0 = Debug|Any CPU
{806ACF6D-90B0-45D0-A1AC-5F220F3B3985}.Debug|x86.ActiveCfg = Debug|Any CPU
{806ACF6D-90B0-45D0-A1AC-5F220F3B3985}.Debug|x86.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.ActiveCfg = Release|Any CPU
{806ACF6D-90B0-45D0-A1AC-5F220F3B3985}.Release|Any CPU.Build.0 = Release|Any CPU {806ACF6D-90B0-45D0-A1AC-5F220F3B3985}.Release|Any CPU.Build.0 = Release|Any CPU
{806ACF6D-90B0-45D0-A1AC-5F220F3B3985}.Release|x64.ActiveCfg = Release|Any CPU
{806ACF6D-90B0-45D0-A1AC-5F220F3B3985}.Release|x64.Build.0 = Release|Any CPU
{806ACF6D-90B0-45D0-A1AC-5F220F3B3985}.Release|x86.ActiveCfg = Release|Any CPU
{806ACF6D-90B0-45D0-A1AC-5F220F3B3985}.Release|x86.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.ActiveCfg = Debug|Any CPU
{A5E6C691-9E22-4263-8F40-42F002CE66BE}.Debug|Any CPU.Build.0 = Debug|Any CPU {A5E6C691-9E22-4263-8F40-42F002CE66BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A5E6C691-9E22-4263-8F40-42F002CE66BE}.Debug|x64.ActiveCfg = Debug|Any CPU
{A5E6C691-9E22-4263-8F40-42F002CE66BE}.Debug|x64.Build.0 = Debug|Any CPU
{A5E6C691-9E22-4263-8F40-42F002CE66BE}.Debug|x86.ActiveCfg = Debug|Any CPU
{A5E6C691-9E22-4263-8F40-42F002CE66BE}.Debug|x86.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.ActiveCfg = Release|Any CPU
{A5E6C691-9E22-4263-8F40-42F002CE66BE}.Release|Any CPU.Build.0 = Release|Any CPU {A5E6C691-9E22-4263-8F40-42F002CE66BE}.Release|Any CPU.Build.0 = Release|Any CPU
{A5E6C691-9E22-4263-8F40-42F002CE66BE}.Release|x64.ActiveCfg = Release|Any CPU
{A5E6C691-9E22-4263-8F40-42F002CE66BE}.Release|x64.Build.0 = Release|Any CPU
{A5E6C691-9E22-4263-8F40-42F002CE66BE}.Release|x86.ActiveCfg = Release|Any CPU
{A5E6C691-9E22-4263-8F40-42F002CE66BE}.Release|x86.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.ActiveCfg = Debug|Any CPU
{D1CC5322-7325-4F6B-9625-194B30BE1296}.Debug|Any CPU.Build.0 = Debug|Any CPU {D1CC5322-7325-4F6B-9625-194B30BE1296}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D1CC5322-7325-4F6B-9625-194B30BE1296}.Debug|x64.ActiveCfg = Debug|Any CPU
{D1CC5322-7325-4F6B-9625-194B30BE1296}.Debug|x64.Build.0 = Debug|Any CPU
{D1CC5322-7325-4F6B-9625-194B30BE1296}.Debug|x86.ActiveCfg = Debug|Any CPU
{D1CC5322-7325-4F6B-9625-194B30BE1296}.Debug|x86.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.ActiveCfg = Release|Any CPU
{D1CC5322-7325-4F6B-9625-194B30BE1296}.Release|Any CPU.Build.0 = Release|Any CPU {D1CC5322-7325-4F6B-9625-194B30BE1296}.Release|Any CPU.Build.0 = Release|Any CPU
{D1CC5322-7325-4F6B-9625-194B30BE1296}.Release|x64.ActiveCfg = Release|Any CPU
{D1CC5322-7325-4F6B-9625-194B30BE1296}.Release|x64.Build.0 = Release|Any CPU
{D1CC5322-7325-4F6B-9625-194B30BE1296}.Release|x86.ActiveCfg = Release|Any CPU
{D1CC5322-7325-4F6B-9625-194B30BE1296}.Release|x86.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.ActiveCfg = Debug|Any CPU
{3DF35E3D-D844-4399-A9A1-A9E923264C17}.Debug|Any CPU.Build.0 = Debug|Any CPU {3DF35E3D-D844-4399-A9A1-A9E923264C17}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3DF35E3D-D844-4399-A9A1-A9E923264C17}.Debug|x64.ActiveCfg = Debug|Any CPU
{3DF35E3D-D844-4399-A9A1-A9E923264C17}.Debug|x64.Build.0 = Debug|Any CPU
{3DF35E3D-D844-4399-A9A1-A9E923264C17}.Debug|x86.ActiveCfg = Debug|Any CPU
{3DF35E3D-D844-4399-A9A1-A9E923264C17}.Debug|x86.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.ActiveCfg = Release|Any CPU
{3DF35E3D-D844-4399-A9A1-A9E923264C17}.Release|Any CPU.Build.0 = Release|Any CPU {3DF35E3D-D844-4399-A9A1-A9E923264C17}.Release|Any CPU.Build.0 = Release|Any CPU
{3DF35E3D-D844-4399-A9A1-A9E923264C17}.Release|x64.ActiveCfg = Release|Any CPU
{3DF35E3D-D844-4399-A9A1-A9E923264C17}.Release|x64.Build.0 = Release|Any CPU
{3DF35E3D-D844-4399-A9A1-A9E923264C17}.Release|x86.ActiveCfg = Release|Any CPU
{3DF35E3D-D844-4399-A9A1-A9E923264C17}.Release|x86.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.ActiveCfg = Debug|Any CPU
{C3002C3C-7B09-4FE7-894A-372EDA22FC6E}.Debug|Any CPU.Build.0 = Debug|Any CPU {C3002C3C-7B09-4FE7-894A-372EDA22FC6E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C3002C3C-7B09-4FE7-894A-372EDA22FC6E}.Debug|x64.ActiveCfg = Debug|Any CPU
{C3002C3C-7B09-4FE7-894A-372EDA22FC6E}.Debug|x64.Build.0 = Debug|Any CPU
{C3002C3C-7B09-4FE7-894A-372EDA22FC6E}.Debug|x86.ActiveCfg = Debug|Any CPU
{C3002C3C-7B09-4FE7-894A-372EDA22FC6E}.Debug|x86.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.ActiveCfg = Release|Any CPU
{C3002C3C-7B09-4FE7-894A-372EDA22FC6E}.Release|Any CPU.Build.0 = Release|Any CPU {C3002C3C-7B09-4FE7-894A-372EDA22FC6E}.Release|Any CPU.Build.0 = Release|Any CPU
{C3002C3C-7B09-4FE7-894A-372EDA22FC6E}.Release|x64.ActiveCfg = Release|Any CPU
{C3002C3C-7B09-4FE7-894A-372EDA22FC6E}.Release|x64.Build.0 = Release|Any CPU
{C3002C3C-7B09-4FE7-894A-372EDA22FC6E}.Release|x86.ActiveCfg = Release|Any CPU
{C3002C3C-7B09-4FE7-894A-372EDA22FC6E}.Release|x86.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.ActiveCfg = Debug|Any CPU
{C35F1536-7DE5-4F9D-9604-B5B4E1561947}.Debug|Any CPU.Build.0 = Debug|Any CPU {C35F1536-7DE5-4F9D-9604-B5B4E1561947}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C35F1536-7DE5-4F9D-9604-B5B4E1561947}.Debug|x64.ActiveCfg = Debug|Any CPU
{C35F1536-7DE5-4F9D-9604-B5B4E1561947}.Debug|x64.Build.0 = Debug|Any CPU
{C35F1536-7DE5-4F9D-9604-B5B4E1561947}.Debug|x86.ActiveCfg = Debug|Any CPU
{C35F1536-7DE5-4F9D-9604-B5B4E1561947}.Debug|x86.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.ActiveCfg = Release|Any CPU
{C35F1536-7DE5-4F9D-9604-B5B4E1561947}.Release|Any CPU.Build.0 = Release|Any CPU {C35F1536-7DE5-4F9D-9604-B5B4E1561947}.Release|Any CPU.Build.0 = Release|Any CPU
{C35F1536-7DE5-4F9D-9604-B5B4E1561947}.Release|x64.ActiveCfg = Release|Any CPU
{C35F1536-7DE5-4F9D-9604-B5B4E1561947}.Release|x64.Build.0 = Release|Any CPU
{C35F1536-7DE5-4F9D-9604-B5B4E1561947}.Release|x86.ActiveCfg = Release|Any CPU
{C35F1536-7DE5-4F9D-9604-B5B4E1561947}.Release|x86.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.ActiveCfg = Debug|Any CPU
{B9AECA11-E248-4886-A10B-81B631CAAF29}.Debug|Any CPU.Build.0 = Debug|Any CPU {B9AECA11-E248-4886-A10B-81B631CAAF29}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B9AECA11-E248-4886-A10B-81B631CAAF29}.Debug|x64.ActiveCfg = Debug|Any CPU
{B9AECA11-E248-4886-A10B-81B631CAAF29}.Debug|x64.Build.0 = Debug|Any CPU
{B9AECA11-E248-4886-A10B-81B631CAAF29}.Debug|x86.ActiveCfg = Debug|Any CPU
{B9AECA11-E248-4886-A10B-81B631CAAF29}.Debug|x86.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.ActiveCfg = Release|Any CPU
{B9AECA11-E248-4886-A10B-81B631CAAF29}.Release|Any CPU.Build.0 = Release|Any CPU {B9AECA11-E248-4886-A10B-81B631CAAF29}.Release|Any CPU.Build.0 = Release|Any CPU
{B9AECA11-E248-4886-A10B-81B631CAAF29}.Release|x64.ActiveCfg = Release|Any CPU
{B9AECA11-E248-4886-A10B-81B631CAAF29}.Release|x64.Build.0 = Release|Any CPU
{B9AECA11-E248-4886-A10B-81B631CAAF29}.Release|x86.ActiveCfg = Release|Any CPU
{B9AECA11-E248-4886-A10B-81B631CAAF29}.Release|x86.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.ActiveCfg = Debug|Any CPU
{81BB2C11-9408-4EA3-822E-42987AF54429}.Debug|Any CPU.Build.0 = Debug|Any CPU {81BB2C11-9408-4EA3-822E-42987AF54429}.Debug|Any CPU.Build.0 = Debug|Any CPU
{81BB2C11-9408-4EA3-822E-42987AF54429}.Debug|x64.ActiveCfg = Debug|Any CPU
{81BB2C11-9408-4EA3-822E-42987AF54429}.Debug|x64.Build.0 = Debug|Any CPU
{81BB2C11-9408-4EA3-822E-42987AF54429}.Debug|x86.ActiveCfg = Debug|Any CPU
{81BB2C11-9408-4EA3-822E-42987AF54429}.Debug|x86.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.ActiveCfg = Release|Any CPU
{81BB2C11-9408-4EA3-822E-42987AF54429}.Release|Any CPU.Build.0 = Release|Any CPU {81BB2C11-9408-4EA3-822E-42987AF54429}.Release|Any CPU.Build.0 = Release|Any CPU
{81BB2C11-9408-4EA3-822E-42987AF54429}.Release|x64.ActiveCfg = Release|Any CPU
{81BB2C11-9408-4EA3-822E-42987AF54429}.Release|x64.Build.0 = Release|Any CPU
{81BB2C11-9408-4EA3-822E-42987AF54429}.Release|x86.ActiveCfg = Release|Any CPU
{81BB2C11-9408-4EA3-822E-42987AF54429}.Release|x86.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.ActiveCfg = Debug|Any CPU
{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}.Debug|Any CPU.Build.0 = Debug|Any CPU {FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}.Debug|x64.ActiveCfg = Debug|Any CPU
{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}.Debug|x64.Build.0 = Debug|Any CPU
{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}.Debug|x86.ActiveCfg = Debug|Any CPU
{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}.Debug|x86.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.ActiveCfg = Release|Any CPU
{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}.Release|Any CPU.Build.0 = Release|Any CPU {FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}.Release|Any CPU.Build.0 = Release|Any CPU
{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}.Release|x64.ActiveCfg = Release|Any CPU
{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}.Release|x64.Build.0 = Release|Any CPU
{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}.Release|x86.ActiveCfg = Release|Any CPU
{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}.Release|x86.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.ActiveCfg = Debug|Any CPU
{0BE11899-DF2D-4BDE-B9EE-2489E8D35E7D}.Debug|Any CPU.Build.0 = Debug|Any CPU {0BE11899-DF2D-4BDE-B9EE-2489E8D35E7D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0BE11899-DF2D-4BDE-B9EE-2489E8D35E7D}.Debug|x64.ActiveCfg = Debug|Any CPU
{0BE11899-DF2D-4BDE-B9EE-2489E8D35E7D}.Debug|x64.Build.0 = Debug|Any CPU
{0BE11899-DF2D-4BDE-B9EE-2489E8D35E7D}.Debug|x86.ActiveCfg = Debug|Any CPU
{0BE11899-DF2D-4BDE-B9EE-2489E8D35E7D}.Debug|x86.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.ActiveCfg = Release|Any CPU
{0BE11899-DF2D-4BDE-B9EE-2489E8D35E7D}.Release|Any CPU.Build.0 = Release|Any CPU {0BE11899-DF2D-4BDE-B9EE-2489E8D35E7D}.Release|Any CPU.Build.0 = Release|Any CPU
{0BE11899-DF2D-4BDE-B9EE-2489E8D35E7D}.Release|x64.ActiveCfg = Release|Any CPU
{0BE11899-DF2D-4BDE-B9EE-2489E8D35E7D}.Release|x64.Build.0 = Release|Any CPU
{0BE11899-DF2D-4BDE-B9EE-2489E8D35E7D}.Release|x86.ActiveCfg = Release|Any CPU
{0BE11899-DF2D-4BDE-B9EE-2489E8D35E7D}.Release|x86.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.ActiveCfg = Debug|Any CPU
{716364DE-B988-41A6-BAB4-327964266ECC}.Debug|Any CPU.Build.0 = Debug|Any CPU {716364DE-B988-41A6-BAB4-327964266ECC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{716364DE-B988-41A6-BAB4-327964266ECC}.Debug|x64.ActiveCfg = Debug|Any CPU
{716364DE-B988-41A6-BAB4-327964266ECC}.Debug|x64.Build.0 = Debug|Any CPU
{716364DE-B988-41A6-BAB4-327964266ECC}.Debug|x86.ActiveCfg = Debug|Any CPU
{716364DE-B988-41A6-BAB4-327964266ECC}.Debug|x86.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.ActiveCfg = Release|Any CPU
{716364DE-B988-41A6-BAB4-327964266ECC}.Release|Any CPU.Build.0 = Release|Any CPU {716364DE-B988-41A6-BAB4-327964266ECC}.Release|Any CPU.Build.0 = Release|Any CPU
{716364DE-B988-41A6-BAB4-327964266ECC}.Release|x64.ActiveCfg = Release|Any CPU
{716364DE-B988-41A6-BAB4-327964266ECC}.Release|x64.Build.0 = Release|Any CPU
{716364DE-B988-41A6-BAB4-327964266ECC}.Release|x86.ActiveCfg = Release|Any CPU
{716364DE-B988-41A6-BAB4-327964266ECC}.Release|x86.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.ActiveCfg = Debug|Any CPU
{C16F112F-38C3-40BC-9F5F-4791112063D6}.Debug|Any CPU.Build.0 = Debug|Any CPU {C16F112F-38C3-40BC-9F5F-4791112063D6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C16F112F-38C3-40BC-9F5F-4791112063D6}.Debug|x64.ActiveCfg = Debug|Any CPU
{C16F112F-38C3-40BC-9F5F-4791112063D6}.Debug|x64.Build.0 = Debug|Any CPU
{C16F112F-38C3-40BC-9F5F-4791112063D6}.Debug|x86.ActiveCfg = Debug|Any CPU
{C16F112F-38C3-40BC-9F5F-4791112063D6}.Debug|x86.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.ActiveCfg = Release|Any CPU
{C16F112F-38C3-40BC-9F5F-4791112063D6}.Release|Any CPU.Build.0 = 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 {C16F112F-38C3-40BC-9F5F-4791112063D6}.Release|x64.ActiveCfg = Release|Any CPU
{DFAB6F2D-B9BF-4AFF-B22B-7684A328EBA3}.Debug|Any CPU.Build.0 = Debug|Any CPU {C16F112F-38C3-40BC-9F5F-4791112063D6}.Release|x64.Build.0 = Release|Any CPU
{DFAB6F2D-B9BF-4AFF-B22B-7684A328EBA3}.Release|Any CPU.ActiveCfg = Release|Any CPU {C16F112F-38C3-40BC-9F5F-4791112063D6}.Release|x86.ActiveCfg = Release|Any CPU
{DFAB6F2D-B9BF-4AFF-B22B-7684A328EBA3}.Release|Any CPU.Build.0 = Release|Any CPU {C16F112F-38C3-40BC-9F5F-4791112063D6}.Release|x86.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
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Debug|Any CPU.ActiveCfg = Debug|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}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Debug|x64.ActiveCfg = Debug|Any CPU
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Debug|x64.Build.0 = Debug|Any CPU
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Debug|x86.ActiveCfg = Debug|Any CPU
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Debug|x86.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.ActiveCfg = Release|Any CPU
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Release|Any CPU.Build.0 = Release|Any CPU {BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Release|Any CPU.Build.0 = Release|Any CPU
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Release|x64.ActiveCfg = Release|Any CPU
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Release|x64.Build.0 = Release|Any CPU
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Release|x86.ActiveCfg = Release|Any CPU
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Release|x86.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.ActiveCfg = Debug|Any CPU
{7C1B2721-13DA-4B62-B046-C626605ECCE6}.Debug|Any CPU.Build.0 = Debug|Any CPU {7C1B2721-13DA-4B62-B046-C626605ECCE6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7C1B2721-13DA-4B62-B046-C626605ECCE6}.Debug|x64.ActiveCfg = Debug|Any CPU
{7C1B2721-13DA-4B62-B046-C626605ECCE6}.Debug|x64.Build.0 = Debug|Any CPU
{7C1B2721-13DA-4B62-B046-C626605ECCE6}.Debug|x86.ActiveCfg = Debug|Any CPU
{7C1B2721-13DA-4B62-B046-C626605ECCE6}.Debug|x86.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.ActiveCfg = Release|Any CPU
{7C1B2721-13DA-4B62-B046-C626605ECCE6}.Release|Any CPU.Build.0 = 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 {7C1B2721-13DA-4B62-B046-C626605ECCE6}.Release|x64.ActiveCfg = Release|Any CPU
{BA161CA0-CD65-4E6E-B644-51C8D1E542DC}.Debug|Any CPU.Build.0 = Debug|Any CPU {7C1B2721-13DA-4B62-B046-C626605ECCE6}.Release|x64.Build.0 = Release|Any CPU
{BA161CA0-CD65-4E6E-B644-51C8D1E542DC}.Release|Any CPU.ActiveCfg = Release|Any CPU {7C1B2721-13DA-4B62-B046-C626605ECCE6}.Release|x86.ActiveCfg = Release|Any CPU
{BA161CA0-CD65-4E6E-B644-51C8D1E542DC}.Release|Any CPU.Build.0 = Release|Any CPU {7C1B2721-13DA-4B62-B046-C626605ECCE6}.Release|x86.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.ActiveCfg = Debug|Any CPU
{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Debug|Any CPU.Build.0 = Debug|Any CPU {6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Debug|x64.ActiveCfg = Debug|Any CPU
{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Debug|x64.Build.0 = Debug|Any CPU
{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Debug|x86.ActiveCfg = Debug|Any CPU
{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Debug|x86.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.ActiveCfg = Release|Any CPU
{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Release|Any CPU.Build.0 = Release|Any CPU {6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Release|Any CPU.Build.0 = Release|Any CPU
{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Release|x64.ActiveCfg = Release|Any CPU
{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Release|x64.Build.0 = Release|Any CPU
{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Release|x86.ActiveCfg = Release|Any CPU
{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Release|x86.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.ActiveCfg = Debug|Any CPU
{D4D09B08-D580-4D69-B886-C35D2853F6C8}.Debug|Any CPU.Build.0 = Debug|Any CPU {D4D09B08-D580-4D69-B886-C35D2853F6C8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D4D09B08-D580-4D69-B886-C35D2853F6C8}.Debug|x64.ActiveCfg = Debug|Any CPU
{D4D09B08-D580-4D69-B886-C35D2853F6C8}.Debug|x64.Build.0 = Debug|Any CPU
{D4D09B08-D580-4D69-B886-C35D2853F6C8}.Debug|x86.ActiveCfg = Debug|Any CPU
{D4D09B08-D580-4D69-B886-C35D2853F6C8}.Debug|x86.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.ActiveCfg = Release|Any CPU
{D4D09B08-D580-4D69-B886-C35D2853F6C8}.Release|Any CPU.Build.0 = Release|Any CPU {D4D09B08-D580-4D69-B886-C35D2853F6C8}.Release|Any CPU.Build.0 = Release|Any CPU
{D4D09B08-D580-4D69-B886-C35D2853F6C8}.Release|x64.ActiveCfg = Release|Any CPU
{D4D09B08-D580-4D69-B886-C35D2853F6C8}.Release|x64.Build.0 = Release|Any CPU
{D4D09B08-D580-4D69-B886-C35D2853F6C8}.Release|x86.ActiveCfg = Release|Any CPU
{D4D09B08-D580-4D69-B886-C35D2853F6C8}.Release|x86.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.ActiveCfg = Debug|Any CPU
{2BCB3D7A-38C0-4FE7-8FDA-374C6AD56D0E}.Debug|Any CPU.Build.0 = Debug|Any CPU {2BCB3D7A-38C0-4FE7-8FDA-374C6AD56D0E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2BCB3D7A-38C0-4FE7-8FDA-374C6AD56D0E}.Debug|x64.ActiveCfg = Debug|Any CPU
{2BCB3D7A-38C0-4FE7-8FDA-374C6AD56D0E}.Debug|x64.Build.0 = Debug|Any CPU
{2BCB3D7A-38C0-4FE7-8FDA-374C6AD56D0E}.Debug|x86.ActiveCfg = Debug|Any CPU
{2BCB3D7A-38C0-4FE7-8FDA-374C6AD56D0E}.Debug|x86.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.ActiveCfg = Release|Any CPU
{2BCB3D7A-38C0-4FE7-8FDA-374C6AD56D0E}.Release|Any CPU.Build.0 = Release|Any CPU {2BCB3D7A-38C0-4FE7-8FDA-374C6AD56D0E}.Release|Any CPU.Build.0 = Release|Any CPU
{2BCB3D7A-38C0-4FE7-8FDA-374C6AD56D0E}.Release|x64.ActiveCfg = Release|Any CPU
{2BCB3D7A-38C0-4FE7-8FDA-374C6AD56D0E}.Release|x64.Build.0 = Release|Any CPU
{2BCB3D7A-38C0-4FE7-8FDA-374C6AD56D0E}.Release|x86.ActiveCfg = Release|Any CPU
{2BCB3D7A-38C0-4FE7-8FDA-374C6AD56D0E}.Release|x86.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.ActiveCfg = Debug|Any CPU
{77D01AD9-2C98-478E-AE1D-8F7100738FB4}.Debug|Any CPU.Build.0 = Debug|Any CPU {77D01AD9-2C98-478E-AE1D-8F7100738FB4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{77D01AD9-2C98-478E-AE1D-8F7100738FB4}.Debug|x64.ActiveCfg = Debug|Any CPU
{77D01AD9-2C98-478E-AE1D-8F7100738FB4}.Debug|x64.Build.0 = Debug|Any CPU
{77D01AD9-2C98-478E-AE1D-8F7100738FB4}.Debug|x86.ActiveCfg = Debug|Any CPU
{77D01AD9-2C98-478E-AE1D-8F7100738FB4}.Debug|x86.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.ActiveCfg = Release|Any CPU
{77D01AD9-2C98-478E-AE1D-8F7100738FB4}.Release|Any CPU.Build.0 = Release|Any CPU {77D01AD9-2C98-478E-AE1D-8F7100738FB4}.Release|Any CPU.Build.0 = Release|Any CPU
{77D01AD9-2C98-478E-AE1D-8F7100738FB4}.Release|x64.ActiveCfg = Release|Any CPU
{77D01AD9-2C98-478E-AE1D-8F7100738FB4}.Release|x64.Build.0 = Release|Any CPU
{77D01AD9-2C98-478E-AE1D-8F7100738FB4}.Release|x86.ActiveCfg = Release|Any CPU
{77D01AD9-2C98-478E-AE1D-8F7100738FB4}.Release|x86.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.ActiveCfg = Debug|Any CPU
{77F96ECE-4952-42DB-A528-DED25572A573}.Debug|Any CPU.Build.0 = Debug|Any CPU {77F96ECE-4952-42DB-A528-DED25572A573}.Debug|Any CPU.Build.0 = Debug|Any CPU
{77F96ECE-4952-42DB-A528-DED25572A573}.Debug|x64.ActiveCfg = Debug|Any CPU
{77F96ECE-4952-42DB-A528-DED25572A573}.Debug|x64.Build.0 = Debug|Any CPU
{77F96ECE-4952-42DB-A528-DED25572A573}.Debug|x86.ActiveCfg = Debug|Any CPU
{77F96ECE-4952-42DB-A528-DED25572A573}.Debug|x86.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.ActiveCfg = Release|Any CPU
{77F96ECE-4952-42DB-A528-DED25572A573}.Release|Any CPU.Build.0 = Release|Any CPU {77F96ECE-4952-42DB-A528-DED25572A573}.Release|Any CPU.Build.0 = Release|Any CPU
{77F96ECE-4952-42DB-A528-DED25572A573}.Release|x64.ActiveCfg = Release|Any CPU
{77F96ECE-4952-42DB-A528-DED25572A573}.Release|x64.Build.0 = Release|Any CPU
{77F96ECE-4952-42DB-A528-DED25572A573}.Release|x86.ActiveCfg = Release|Any CPU
{77F96ECE-4952-42DB-A528-DED25572A573}.Release|x86.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.ActiveCfg = Debug|Any CPU
{AF34127A-3A92-43E5-8496-14960A50B1F1}.Debug|Any CPU.Build.0 = Debug|Any CPU {AF34127A-3A92-43E5-8496-14960A50B1F1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AF34127A-3A92-43E5-8496-14960A50B1F1}.Debug|x64.ActiveCfg = Debug|Any CPU
{AF34127A-3A92-43E5-8496-14960A50B1F1}.Debug|x64.Build.0 = Debug|Any CPU
{AF34127A-3A92-43E5-8496-14960A50B1F1}.Debug|x86.ActiveCfg = Debug|Any CPU
{AF34127A-3A92-43E5-8496-14960A50B1F1}.Debug|x86.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.ActiveCfg = Release|Any CPU
{AF34127A-3A92-43E5-8496-14960A50B1F1}.Release|Any CPU.Build.0 = Release|Any CPU {AF34127A-3A92-43E5-8496-14960A50B1F1}.Release|Any CPU.Build.0 = Release|Any CPU
{AF34127A-3A92-43E5-8496-14960A50B1F1}.Release|x64.ActiveCfg = Release|Any CPU
{AF34127A-3A92-43E5-8496-14960A50B1F1}.Release|x64.Build.0 = Release|Any CPU
{AF34127A-3A92-43E5-8496-14960A50B1F1}.Release|x86.ActiveCfg = Release|Any CPU
{AF34127A-3A92-43E5-8496-14960A50B1F1}.Release|x86.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.ActiveCfg = Debug|Any CPU
{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Debug|Any CPU.Build.0 = Debug|Any CPU {7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Debug|x64.ActiveCfg = Debug|Any CPU
{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Debug|x64.Build.0 = Debug|Any CPU
{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Debug|x86.ActiveCfg = Debug|Any CPU
{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Debug|x86.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.ActiveCfg = Release|Any CPU
{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Release|Any CPU.Build.0 = Release|Any CPU {7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Release|Any CPU.Build.0 = Release|Any CPU
{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Release|x64.ActiveCfg = Release|Any CPU
{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Release|x64.Build.0 = Release|Any CPU
{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Release|x86.ActiveCfg = Release|Any CPU
{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Release|x86.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.ActiveCfg = Debug|Any CPU
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Debug|Any CPU.Build.0 = Debug|Any CPU {B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Debug|x64.ActiveCfg = Debug|Any CPU
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Debug|x64.Build.0 = Debug|Any CPU
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Debug|x86.ActiveCfg = Debug|Any CPU
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Debug|x86.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.ActiveCfg = Release|Any CPU
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Release|Any CPU.Build.0 = Release|Any CPU {B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Release|Any CPU.Build.0 = Release|Any CPU
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Release|x64.ActiveCfg = Release|Any CPU
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Release|x64.Build.0 = Release|Any CPU
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Release|x86.ActiveCfg = Release|Any CPU
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Release|x86.Build.0 = Release|Any CPU
{4A89A234-4F19-497D-A576-DDE8CDFC5B22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4A89A234-4F19-497D-A576-DDE8CDFC5B22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4A89A234-4F19-497D-A576-DDE8CDFC5B22}.Debug|Any CPU.Build.0 = Debug|Any CPU {4A89A234-4F19-497D-A576-DDE8CDFC5B22}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4A89A234-4F19-497D-A576-DDE8CDFC5B22}.Debug|x64.ActiveCfg = Debug|Any CPU
{4A89A234-4F19-497D-A576-DDE8CDFC5B22}.Debug|x64.Build.0 = Debug|Any CPU
{4A89A234-4F19-497D-A576-DDE8CDFC5B22}.Debug|x86.ActiveCfg = Debug|Any CPU
{4A89A234-4F19-497D-A576-DDE8CDFC5B22}.Debug|x86.Build.0 = Debug|Any CPU
{4A89A234-4F19-497D-A576-DDE8CDFC5B22}.Release|Any CPU.ActiveCfg = Release|Any CPU {4A89A234-4F19-497D-A576-DDE8CDFC5B22}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4A89A234-4F19-497D-A576-DDE8CDFC5B22}.Release|x64.ActiveCfg = Release|Any CPU
{4A89A234-4F19-497D-A576-DDE8CDFC5B22}.Release|x64.Build.0 = Release|Any CPU
{4A89A234-4F19-497D-A576-DDE8CDFC5B22}.Release|x86.ActiveCfg = Release|Any CPU
{4A89A234-4F19-497D-A576-DDE8CDFC5B22}.Release|x86.Build.0 = Release|Any CPU
{F6F9826A-BC58-4D78-A700-F358A66B2B06}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F6F9826A-BC58-4D78-A700-F358A66B2B06}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F6F9826A-BC58-4D78-A700-F358A66B2B06}.Debug|x64.ActiveCfg = Debug|Any CPU
{F6F9826A-BC58-4D78-A700-F358A66B2B06}.Debug|x64.Build.0 = Debug|Any CPU
{F6F9826A-BC58-4D78-A700-F358A66B2B06}.Debug|x86.ActiveCfg = Debug|Any CPU
{F6F9826A-BC58-4D78-A700-F358A66B2B06}.Debug|x86.Build.0 = Debug|Any CPU
{F6F9826A-BC58-4D78-A700-F358A66B2B06}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F6F9826A-BC58-4D78-A700-F358A66B2B06}.Release|Any CPU.Build.0 = Release|Any CPU
{F6F9826A-BC58-4D78-A700-F358A66B2B06}.Release|x64.ActiveCfg = Release|Any CPU
{F6F9826A-BC58-4D78-A700-F358A66B2B06}.Release|x64.Build.0 = Release|Any CPU
{F6F9826A-BC58-4D78-A700-F358A66B2B06}.Release|x86.ActiveCfg = Release|Any CPU
{F6F9826A-BC58-4D78-A700-F358A66B2B06}.Release|x86.Build.0 = Release|Any CPU
{D728444C-3D1F-4A0E-B4C9-5C9375D47EA3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D728444C-3D1F-4A0E-B4C9-5C9375D47EA3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D728444C-3D1F-4A0E-B4C9-5C9375D47EA3}.Debug|x64.ActiveCfg = Debug|Any CPU
{D728444C-3D1F-4A0E-B4C9-5C9375D47EA3}.Debug|x64.Build.0 = Debug|Any CPU
{D728444C-3D1F-4A0E-B4C9-5C9375D47EA3}.Debug|x86.ActiveCfg = Debug|Any CPU
{D728444C-3D1F-4A0E-B4C9-5C9375D47EA3}.Debug|x86.Build.0 = Debug|Any CPU
{D728444C-3D1F-4A0E-B4C9-5C9375D47EA3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D728444C-3D1F-4A0E-B4C9-5C9375D47EA3}.Release|Any CPU.Build.0 = Release|Any CPU
{D728444C-3D1F-4A0E-B4C9-5C9375D47EA3}.Release|x64.ActiveCfg = Release|Any CPU
{D728444C-3D1F-4A0E-B4C9-5C9375D47EA3}.Release|x64.Build.0 = Release|Any CPU
{D728444C-3D1F-4A0E-B4C9-5C9375D47EA3}.Release|x86.ActiveCfg = Release|Any CPU
{D728444C-3D1F-4A0E-B4C9-5C9375D47EA3}.Release|x86.Build.0 = Release|Any CPU
{988E6191-82E1-4E13-9DDB-CB9FA2FDAF29}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{988E6191-82E1-4E13-9DDB-CB9FA2FDAF29}.Debug|Any CPU.Build.0 = Debug|Any CPU
{988E6191-82E1-4E13-9DDB-CB9FA2FDAF29}.Debug|x64.ActiveCfg = Debug|Any CPU
{988E6191-82E1-4E13-9DDB-CB9FA2FDAF29}.Debug|x64.Build.0 = Debug|Any CPU
{988E6191-82E1-4E13-9DDB-CB9FA2FDAF29}.Debug|x86.ActiveCfg = Debug|Any CPU
{988E6191-82E1-4E13-9DDB-CB9FA2FDAF29}.Debug|x86.Build.0 = Debug|Any CPU
{988E6191-82E1-4E13-9DDB-CB9FA2FDAF29}.Release|Any CPU.ActiveCfg = Release|Any CPU
{988E6191-82E1-4E13-9DDB-CB9FA2FDAF29}.Release|Any CPU.Build.0 = Release|Any CPU
{988E6191-82E1-4E13-9DDB-CB9FA2FDAF29}.Release|x64.ActiveCfg = Release|Any CPU
{988E6191-82E1-4E13-9DDB-CB9FA2FDAF29}.Release|x64.Build.0 = Release|Any CPU
{988E6191-82E1-4E13-9DDB-CB9FA2FDAF29}.Release|x86.ActiveCfg = Release|Any CPU
{988E6191-82E1-4E13-9DDB-CB9FA2FDAF29}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

File diff suppressed because it is too large Load Diff

View File

@@ -2,8 +2,8 @@
SCRIPT_DIR=$(dirname "$(realpath "$0")") SCRIPT_DIR=$(dirname "$(realpath "$0")")
if [ -f "$SCRIPT_DIR/Ryujinx.Headless.SDL2" ]; then if [ -f "$SCRIPT_DIR/Ryujinx.Headless.SDL3" ]; then
RYUJINX_BIN="Ryujinx.Headless.SDL2" RYUJINX_BIN="Ryujinx.Headless.SDL3"
fi fi
if [ -f "$SCRIPT_DIR/Ryujinx" ]; then if [ -f "$SCRIPT_DIR/Ryujinx" ]; then

View File

@@ -34,7 +34,7 @@
<key>CFBundleInfoDictionaryVersion</key> <key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string> <string>6.0</string>
<key>CFBundleLongVersionString</key> <key>CFBundleLongVersionString</key>
<string>%%RYUJINX_BUILD_VERSION%%-%%RYUJINX_BUILD_GIT_HASH%%"</string> <string>%%RYUJINX_BUILD_VERSION%%-%%RYUJINX_BUILD_GIT_HASH%%</string>
<key>CFBundleName</key> <key>CFBundleName</key>
<string>Ryujinx</string> <string>Ryujinx</string>
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
@@ -44,13 +44,13 @@
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>????</string> <string>????</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>1.2.0</string> <string>%%RYUJINX_BUILD_VERSION%%</string>
<key>NSHighResolutionCapable</key> <key>NSHighResolutionCapable</key>
<true/> <true/>
<key>CSResourcesFileMapped</key> <key>CSResourcesFileMapped</key>
<true/> <true/>
<key>NSHumanReadableCopyright</key> <key>NSHumanReadableCopyright</key>
<string>Copyright © 2018 - 2023 Ryujinx Team and Contributors.</string> <string>Copyright © 2018 - 2024 Ryujinx Team and Contributors. Copyright © 2024 - 2025 Ryubing and Contributors.</string>
<key>LSApplicationCategoryType</key> <key>LSApplicationCategoryType</key>
<string>public.app-category.games</string> <string>public.app-category.games</string>
<key>LSMinimumSystemVersion</key> <key>LSMinimumSystemVersion</key>

View File

@@ -43,7 +43,7 @@ fi
ARM64_OUTPUT="$TEMP_DIRECTORY/publish_arm64" ARM64_OUTPUT="$TEMP_DIRECTORY/publish_arm64"
X64_OUTPUT="$TEMP_DIRECTORY/publish_x64" X64_OUTPUT="$TEMP_DIRECTORY/publish_x64"
UNIVERSAL_OUTPUT="$OUTPUT_DIRECTORY/publish" UNIVERSAL_OUTPUT="$OUTPUT_DIRECTORY/publish"
EXECUTABLE_SUB_PATH=Ryujinx.Headless.SDL2 EXECUTABLE_SUB_PATH=Ryujinx.Headless.SDL3
rm -rf "$TEMP_DIRECTORY" rm -rf "$TEMP_DIRECTORY"
mkdir -p "$TEMP_DIRECTORY" mkdir -p "$TEMP_DIRECTORY"
@@ -51,9 +51,9 @@ mkdir -p "$TEMP_DIRECTORY"
DOTNET_COMMON_ARGS=(-p:DebugType=embedded -p:Version="$VERSION" -p:SourceRevisionId="$SOURCE_REVISION_ID" --self-contained true $EXTRA_ARGS) DOTNET_COMMON_ARGS=(-p:DebugType=embedded -p:Version="$VERSION" -p:SourceRevisionId="$SOURCE_REVISION_ID" --self-contained true $EXTRA_ARGS)
dotnet restore dotnet restore
dotnet build -c "$CONFIGURATION" src/Ryujinx.Headless.SDL2 dotnet build -c "$CONFIGURATION" src/Ryujinx.Headless.SDL3
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-arm64 -o "$TEMP_DIRECTORY/publish_arm64" "${DOTNET_COMMON_ARGS[@]}" src/Ryujinx.Headless.SDL3
dotnet publish -c "$CONFIGURATION" -r osx-x64 -o "$TEMP_DIRECTORY/publish_x64" "${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.SDL3
# Get rid of the support library for ARMeilleure for x64 (that's only for arm64) # Get rid of the support library for ARMeilleure for x64 (that's only for arm64)
rm -rf "$TEMP_DIRECTORY/publish_x64/libarmeilleure-jitsupport.dylib" rm -rf "$TEMP_DIRECTORY/publish_x64/libarmeilleure-jitsupport.dylib"
@@ -115,8 +115,8 @@ fi
echo "Creating archive" echo "Creating archive"
pushd "$OUTPUT_DIRECTORY" pushd "$OUTPUT_DIRECTORY"
tar --exclude "publish/Ryujinx.Headless.SDL2" -cvf "$RELEASE_TAR_FILE_NAME" publish 1> /dev/null tar --exclude "publish/Ryujinx.Headless.SDL3" -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" python3 "$BASE_DIR/distribution/misc/add_tar_exec.py" "$RELEASE_TAR_FILE_NAME" "publish/Ryujinx.Headless.SDL3" "publish/Ryujinx.Headless.SDL3"
gzip -9 < "$RELEASE_TAR_FILE_NAME" > "$RELEASE_TAR_FILE_NAME.gz" gzip -9 < "$RELEASE_TAR_FILE_NAME" > "$RELEASE_TAR_FILE_NAME.gz"
rm "$RELEASE_TAR_FILE_NAME" rm "$RELEASE_TAR_FILE_NAME"
popd popd

View File

@@ -8,7 +8,7 @@ Intro to Ryujinx
Ryujinx is an open-source Nintendo Switch emulator, created by gdkchan, written in C#. Ryujinx is an open-source Nintendo Switch emulator, created by gdkchan, written in C#.
* 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 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. * 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 Getting Started
=============== ===============

View File

@@ -2280,6 +2280,7 @@
01008F6008C5E000,"Pokémon™ Violet",gpu;nvdec;ldn-works;amd-vendor-bug;mac-bug,ingame,2024-07-30 02:51:48 01008F6008C5E000,"Pokémon™ Violet",gpu;nvdec;ldn-works;amd-vendor-bug;mac-bug,ingame,2024-07-30 02:51:48
0100187003A36000,"Pokémon™: Lets Go, Eevee!",crash;nvdec;online-broken;ldn-broken,ingame,2024-06-01 15:03:04 0100187003A36000,"Pokémon™: Lets Go, Eevee!",crash;nvdec;online-broken;ldn-broken,ingame,2024-06-01 15:03:04
010003F003A34000,"Pokémon™: Lets Go, Pikachu!",crash;nvdec;online-broken;ldn-broken,ingame,2024-03-15 07:55:41 010003F003A34000,"Pokémon™: Lets Go, Pikachu!",crash;nvdec;online-broken;ldn-broken,ingame,2024-03-15 07:55:41
0100F43008C44000,"Pokémon Legends: Z-A",gpu;crash;ldn-broken,ingame,2025-10-16 19:13:00
0100B3F000BE2000,"Pokkén Tournament™ DX",nvdec;ldn-works;opengl-backend-bug;LAN;amd-vendor-bug;intel-vendor-bug,playable,2024-07-18 23:11:08 0100B3F000BE2000,"Pokkén Tournament™ DX",nvdec;ldn-works;opengl-backend-bug;LAN;amd-vendor-bug;intel-vendor-bug,playable,2024-07-18 23:11:08
010030D005AE6000,"Pokkén Tournament™ DX Demo",demo;opengl-backend-bug,playable,2022-08-10 12:03:19 010030D005AE6000,"Pokkén Tournament™ DX Demo",demo;opengl-backend-bug,playable,2022-08-10 12:03:19
0100A3500B4EC000,"Polandball: Can Into Space",,playable,2020-06-25 15:13:26 0100A3500B4EC000,"Polandball: Can Into Space",,playable,2020-06-25 15:13:26
1 title_id game_name labels status last_updated
2280 01008F6008C5E000 Pokémon™ Violet gpu;nvdec;ldn-works;amd-vendor-bug;mac-bug ingame 2024-07-30 02:51:48
2281 0100187003A36000 Pokémon™: Let’s Go, Eevee! crash;nvdec;online-broken;ldn-broken ingame 2024-06-01 15:03:04
2282 010003F003A34000 Pokémon™: Let’s Go, Pikachu! crash;nvdec;online-broken;ldn-broken ingame 2024-03-15 07:55:41
2283 0100F43008C44000 Pokémon Legends: Z-A gpu;crash;ldn-broken ingame 2025-10-16 19:13:00
2284 0100B3F000BE2000 Pokkén Tournament™ DX nvdec;ldn-works;opengl-backend-bug;LAN;amd-vendor-bug;intel-vendor-bug playable 2024-07-18 23:11:08
2285 010030D005AE6000 Pokkén Tournament™ DX Demo demo;opengl-backend-bug playable 2022-08-10 12:03:19
2286 0100A3500B4EC000 Polandball: Can Into Space playable 2020-06-25 15:13:26

View File

@@ -1,6 +1,6 @@
{ {
"sdk": { "sdk": {
"version": "9.0.100", "version": "10.0.100",
"rollForward": "latestFeature" "rollForward": "latestFeature"
} }
} }

View File

@@ -25,9 +25,9 @@ namespace ARMeilleure.CodeGen.Arm64
static class ComparisonArm64Extensions static class ComparisonArm64Extensions
{ {
public static ArmCondition ToArmCondition(this Comparison comp) extension(Comparison comparison)
{ {
return comp switch public ArmCondition Arm => comparison switch
{ {
#pragma warning disable IDE0055 // Disable formatting #pragma warning disable IDE0055 // Disable formatting
Comparison.Equal => ArmCondition.Eq, Comparison.Equal => ArmCondition.Eq,
@@ -42,7 +42,7 @@ namespace ARMeilleure.CodeGen.Arm64
Comparison.LessUI => ArmCondition.LtUn, Comparison.LessUI => ArmCondition.LtUn,
#pragma warning restore IDE0055 #pragma warning restore IDE0055
_ => throw new ArgumentException(null, nameof(comp)), _ => throw new ArgumentException(null, nameof(comparison))
}; };
} }
} }

View File

@@ -181,10 +181,10 @@ namespace ARMeilleure.CodeGen.Arm64
public void Fmov(Operand rd, Operand rn, bool topHalf) public void Fmov(Operand rd, Operand rn, bool topHalf)
{ {
Debug.Assert(rd.Type.IsInteger() != rn.Type.IsInteger()); Debug.Assert(rd.Type.IsInteger != rn.Type.IsInteger);
Debug.Assert(rd.Type == OperandType.I64 || rn.Type == OperandType.I64 || !topHalf); Debug.Assert(rd.Type == OperandType.I64 || rn.Type == OperandType.I64 || !topHalf);
uint opcode = rd.Type.IsInteger() ? 0b110u : 0b111u; uint opcode = rd.Type.IsInteger ? 0b110u : 0b111u;
uint rmode = topHalf ? 1u << 19 : 0u; uint rmode = topHalf ? 1u << 19 : 0u;
uint ftype = rd.Type == OperandType.FP64 || rn.Type == OperandType.FP64 ? 1u << 22 : 0u; uint ftype = rd.Type == OperandType.FP64 || rn.Type == OperandType.FP64 ? 1u << 22 : 0u;
@@ -411,7 +411,7 @@ namespace ARMeilleure.CodeGen.Arm64
public void Mov(Operand rd, Operand rn) public void Mov(Operand rd, Operand rn)
{ {
if (rd.Type.IsInteger()) if (rd.Type.IsInteger)
{ {
Orr(rd, Factory.Register(ZrRegister, RegisterType.Integer, rd.Type), rn); Orr(rd, Factory.Register(ZrRegister, RegisterType.Integer, rd.Type), rn);
} }
@@ -973,7 +973,7 @@ namespace ARMeilleure.CodeGen.Arm64
uint instruction; uint instruction;
int scale; int scale;
if (type.IsInteger()) if (type.IsInteger)
{ {
instruction = intInst; instruction = intInst;
@@ -1009,7 +1009,7 @@ namespace ARMeilleure.CodeGen.Arm64
{ {
uint instruction; uint instruction;
if (type.IsInteger()) if (type.IsInteger)
{ {
instruction = intInst; instruction = intInst;

View File

@@ -250,7 +250,7 @@ namespace ARMeilleure.CodeGen.Arm64
// ValidateBinOp(dest, src1, src2); // ValidateBinOp(dest, src1, src2);
if (dest.Type.IsInteger()) if (dest.Type.IsInteger)
{ {
context.Assembler.Add(dest, src1, src2); context.Assembler.Add(dest, src1, src2);
} }
@@ -268,7 +268,7 @@ namespace ARMeilleure.CodeGen.Arm64
ValidateBinOp(dest, src1, src2); ValidateBinOp(dest, src1, src2);
Debug.Assert(dest.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger);
context.Assembler.And(dest, src1, src2); context.Assembler.And(dest, src1, src2);
} }
@@ -281,7 +281,7 @@ namespace ARMeilleure.CodeGen.Arm64
ValidateBinOp(dest, src1, src2); ValidateBinOp(dest, src1, src2);
if (dest.Type.IsInteger()) if (dest.Type.IsInteger)
{ {
context.Assembler.Eor(dest, src1, src2); context.Assembler.Eor(dest, src1, src2);
} }
@@ -298,7 +298,7 @@ namespace ARMeilleure.CodeGen.Arm64
ValidateUnOp(dest, source); ValidateUnOp(dest, source);
Debug.Assert(dest.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger);
context.Assembler.Mvn(dest, source); context.Assembler.Mvn(dest, source);
} }
@@ -311,7 +311,7 @@ namespace ARMeilleure.CodeGen.Arm64
ValidateBinOp(dest, src1, src2); ValidateBinOp(dest, src1, src2);
Debug.Assert(dest.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger);
context.Assembler.Orr(dest, src1, src2); context.Assembler.Orr(dest, src1, src2);
} }
@@ -322,7 +322,7 @@ namespace ARMeilleure.CodeGen.Arm64
Debug.Assert(comp.Kind == OperandKind.Constant); Debug.Assert(comp.Kind == OperandKind.Constant);
ArmCondition cond = ((Comparison)comp.AsInt32()).ToArmCondition(); ArmCondition cond = ((Comparison)comp.AsInt32()).Arm;
GenerateCompareCommon(context, operation); GenerateCompareCommon(context, operation);
@@ -336,7 +336,7 @@ namespace ARMeilleure.CodeGen.Arm64
ValidateUnOp(dest, source); ValidateUnOp(dest, source);
Debug.Assert(dest.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger);
context.Assembler.Rev(dest, source); context.Assembler.Rev(dest, source);
} }
@@ -354,7 +354,7 @@ namespace ARMeilleure.CodeGen.Arm64
Debug.Assert(dest.Type == OperandType.I32); Debug.Assert(dest.Type == OperandType.I32);
Debug.Assert(comp.Kind == OperandKind.Constant); Debug.Assert(comp.Kind == OperandKind.Constant);
ArmCondition cond = ((Comparison)comp.AsInt32()).ToArmCondition(); ArmCondition cond = ((Comparison)comp.AsInt32()).Arm;
GenerateCompareCommon(context, operation); GenerateCompareCommon(context, operation);
@@ -428,7 +428,7 @@ namespace ARMeilleure.CodeGen.Arm64
EnsureSameType(src1, src2); EnsureSameType(src1, src2);
Debug.Assert(src1.Type.IsInteger()); Debug.Assert(src1.Type.IsInteger);
context.Assembler.Cmp(src1, src2); context.Assembler.Cmp(src1, src2);
} }
@@ -442,7 +442,7 @@ namespace ARMeilleure.CodeGen.Arm64
EnsureSameType(dest, src2, src3); EnsureSameType(dest, src2, src3);
Debug.Assert(dest.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger);
Debug.Assert(src1.Type == OperandType.I32); Debug.Assert(src1.Type == OperandType.I32);
context.Assembler.Cmp(src1, Const(src1.Type, 0)); context.Assembler.Cmp(src1, Const(src1.Type, 0));
@@ -468,7 +468,7 @@ namespace ARMeilleure.CodeGen.Arm64
Debug.Assert(dest.Type != source.Type); Debug.Assert(dest.Type != source.Type);
Debug.Assert(source.Type != OperandType.V128); Debug.Assert(source.Type != OperandType.V128);
if (source.Type.IsInteger()) if (source.Type.IsInteger)
{ {
context.Assembler.ScvtfScalar(dest, source); context.Assembler.ScvtfScalar(dest, source);
} }
@@ -485,7 +485,7 @@ namespace ARMeilleure.CodeGen.Arm64
Debug.Assert(dest.Type is OperandType.FP32 or OperandType.FP64); Debug.Assert(dest.Type is OperandType.FP32 or OperandType.FP64);
Debug.Assert(dest.Type != source.Type); Debug.Assert(dest.Type != source.Type);
Debug.Assert(source.Type.IsInteger()); Debug.Assert(source.Type.IsInteger);
context.Assembler.UcvtfScalar(dest, source); context.Assembler.UcvtfScalar(dest, source);
} }
@@ -497,7 +497,7 @@ namespace ARMeilleure.CodeGen.Arm64
EnsureSameType(dest, source); EnsureSameType(dest, source);
Debug.Assert(dest.Type.IsInteger() || source.Kind != OperandKind.Constant); Debug.Assert(dest.Type.IsInteger || source.Kind != OperandKind.Constant);
// Moves to the same register are useless. // Moves to the same register are useless.
if (dest.Kind == source.Kind && dest.Value == source.Value) if (dest.Kind == source.Kind && dest.Value == source.Value)
@@ -529,7 +529,7 @@ namespace ARMeilleure.CodeGen.Arm64
EnsureSameType(dest, source); EnsureSameType(dest, source);
Debug.Assert(dest.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger);
context.Assembler.Clz(dest, source); context.Assembler.Clz(dest, source);
} }
@@ -542,7 +542,7 @@ namespace ARMeilleure.CodeGen.Arm64
ValidateBinOp(dest, dividend, divisor); ValidateBinOp(dest, dividend, divisor);
if (dest.Type.IsInteger()) if (dest.Type.IsInteger)
{ {
context.Assembler.Sdiv(dest, dividend, divisor); context.Assembler.Sdiv(dest, dividend, divisor);
} }
@@ -576,7 +576,7 @@ namespace ARMeilleure.CodeGen.Arm64
Operand value = operation.Destination; Operand value = operation.Destination;
Operand address = operation.GetSource(0); Operand address = operation.GetSource(0);
Debug.Assert(value.Type.IsInteger()); Debug.Assert(value.Type.IsInteger);
context.Assembler.LdrhRiUn(value, address, 0); context.Assembler.LdrhRiUn(value, address, 0);
} }
@@ -586,7 +586,7 @@ namespace ARMeilleure.CodeGen.Arm64
Operand value = operation.Destination; Operand value = operation.Destination;
Operand address = operation.GetSource(0); Operand address = operation.GetSource(0);
Debug.Assert(value.Type.IsInteger()); Debug.Assert(value.Type.IsInteger);
context.Assembler.LdrbRiUn(value, address, 0); context.Assembler.LdrbRiUn(value, address, 0);
} }
@@ -604,7 +604,7 @@ namespace ARMeilleure.CodeGen.Arm64
EnsureSameType(dest, src1, src2); EnsureSameType(dest, src1, src2);
if (dest.Type.IsInteger()) if (dest.Type.IsInteger)
{ {
context.Assembler.Mul(dest, src1, src2); context.Assembler.Mul(dest, src1, src2);
} }
@@ -647,7 +647,7 @@ namespace ARMeilleure.CodeGen.Arm64
ValidateUnOp(dest, source); ValidateUnOp(dest, source);
if (dest.Type.IsInteger()) if (dest.Type.IsInteger)
{ {
context.Assembler.Neg(dest, source); context.Assembler.Neg(dest, source);
} }
@@ -732,7 +732,7 @@ namespace ARMeilleure.CodeGen.Arm64
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger && source.Type.IsInteger);
context.Assembler.Sxth(dest, source); context.Assembler.Sxth(dest, source);
} }
@@ -742,7 +742,7 @@ namespace ARMeilleure.CodeGen.Arm64
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger && source.Type.IsInteger);
context.Assembler.Sxtw(dest, source); context.Assembler.Sxtw(dest, source);
} }
@@ -752,7 +752,7 @@ namespace ARMeilleure.CodeGen.Arm64
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger && source.Type.IsInteger);
context.Assembler.Sxtb(dest, source); context.Assembler.Sxtb(dest, source);
} }
@@ -823,7 +823,7 @@ namespace ARMeilleure.CodeGen.Arm64
Operand value = operation.GetSource(1); Operand value = operation.GetSource(1);
Operand address = operation.GetSource(0); Operand address = operation.GetSource(0);
Debug.Assert(value.Type.IsInteger()); Debug.Assert(value.Type.IsInteger);
context.Assembler.StrhRiUn(value, address, 0); context.Assembler.StrhRiUn(value, address, 0);
} }
@@ -833,7 +833,7 @@ namespace ARMeilleure.CodeGen.Arm64
Operand value = operation.GetSource(1); Operand value = operation.GetSource(1);
Operand address = operation.GetSource(0); Operand address = operation.GetSource(0);
Debug.Assert(value.Type.IsInteger()); Debug.Assert(value.Type.IsInteger);
context.Assembler.StrbRiUn(value, address, 0); context.Assembler.StrbRiUn(value, address, 0);
} }
@@ -858,7 +858,7 @@ namespace ARMeilleure.CodeGen.Arm64
// ValidateBinOp(dest, src1, src2); // ValidateBinOp(dest, src1, src2);
if (dest.Type.IsInteger()) if (dest.Type.IsInteger)
{ {
context.Assembler.Sub(dest, src1, src2); context.Assembler.Sub(dest, src1, src2);
} }
@@ -882,7 +882,7 @@ namespace ARMeilleure.CodeGen.Arm64
if (dest != default) if (dest != default)
{ {
Debug.Assert(!dest.Type.IsInteger() && source.Type.IsInteger()); Debug.Assert(!dest.Type.IsInteger && source.Type.IsInteger);
OperandType destType = source.Type == OperandType.I64 ? OperandType.FP64 : OperandType.FP32; OperandType destType = source.Type == OperandType.I64 ? OperandType.FP64 : OperandType.FP32;
@@ -901,9 +901,9 @@ namespace ARMeilleure.CodeGen.Arm64
byte index = src2.AsByte(); byte index = src2.AsByte();
Debug.Assert(index < OperandType.V128.GetSizeInBytes() / dest.Type.GetSizeInBytes()); Debug.Assert(index < OperandType.V128.ByteSize / dest.Type.ByteSize);
if (dest.Type.IsInteger()) if (dest.Type.IsInteger)
{ {
context.Assembler.Umov(dest, src1, index, dest.Type == OperandType.I64 ? 3 : 2); context.Assembler.Umov(dest, src1, index, dest.Type == OperandType.I64 ? 3 : 2);
} }
@@ -959,7 +959,7 @@ namespace ARMeilleure.CodeGen.Arm64
byte index = src3.AsByte(); byte index = src3.AsByte();
if (src2.Type.IsInteger()) if (src2.Type.IsInteger)
{ {
context.Assembler.Ins(dest, src2, index, src2.Type == OperandType.I64 ? 3 : 2); context.Assembler.Ins(dest, src2, index, src2.Type == OperandType.I64 ? 3 : 2);
} }
@@ -1007,7 +1007,7 @@ namespace ARMeilleure.CodeGen.Arm64
{ {
Operand dest = operation.Destination; Operand dest = operation.Destination;
Debug.Assert(!dest.Type.IsInteger()); Debug.Assert(!dest.Type.IsInteger);
context.Assembler.CmeqVector(dest, dest, dest, 2); context.Assembler.CmeqVector(dest, dest, dest, 2);
} }
@@ -1016,7 +1016,7 @@ namespace ARMeilleure.CodeGen.Arm64
{ {
Operand dest = operation.Destination; Operand dest = operation.Destination;
Debug.Assert(!dest.Type.IsInteger()); Debug.Assert(!dest.Type.IsInteger);
context.Assembler.EorVector(dest, dest, dest); context.Assembler.EorVector(dest, dest, dest);
} }
@@ -1046,7 +1046,7 @@ namespace ARMeilleure.CodeGen.Arm64
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger && source.Type.IsInteger);
context.Assembler.Uxth(dest, source); context.Assembler.Uxth(dest, source);
} }
@@ -1056,7 +1056,7 @@ namespace ARMeilleure.CodeGen.Arm64
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger && source.Type.IsInteger);
// We can eliminate the move if source is already 32-bit and the registers are the same. // We can eliminate the move if source is already 32-bit and the registers are the same.
if (dest.Value == source.Value && source.Type == OperandType.I32) if (dest.Value == source.Value && source.Type == OperandType.I32)
@@ -1072,7 +1072,7 @@ namespace ARMeilleure.CodeGen.Arm64
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger && source.Type.IsInteger);
context.Assembler.Uxtb(dest, source); context.Assembler.Uxtb(dest, source);
} }
@@ -1169,7 +1169,7 @@ namespace ARMeilleure.CodeGen.Arm64
context.Assembler.StrRiPre(Register(reg, type), Register(SpRegister), -calleeSaveRegionSize); context.Assembler.StrRiPre(Register(reg, type), Register(SpRegister), -calleeSaveRegionSize);
} }
offset += type.GetSizeInBytes(); offset += type.ByteSize;
} }
while (mask != 0) while (mask != 0)
@@ -1195,7 +1195,7 @@ namespace ARMeilleure.CodeGen.Arm64
context.Assembler.StpRiPre(Register(reg, type), Register(reg2, type), Register(SpRegister), -calleeSaveRegionSize); context.Assembler.StpRiPre(Register(reg, type), Register(reg2, type), Register(SpRegister), -calleeSaveRegionSize);
} }
offset += type.GetSizeInBytes() * 2; offset += type.ByteSize * 2;
} }
} }
@@ -1273,7 +1273,7 @@ namespace ARMeilleure.CodeGen.Arm64
mask &= ~(1 << reg2); mask &= ~(1 << reg2);
offset -= type.GetSizeInBytes() * 2; offset -= type.ByteSize * 2;
if (offset != 0) if (offset != 0)
{ {
@@ -1286,7 +1286,7 @@ namespace ARMeilleure.CodeGen.Arm64
} }
else else
{ {
offset -= type.GetSizeInBytes(); offset -= type.ByteSize;
if (offset != 0) if (offset != 0)
{ {
@@ -1435,12 +1435,12 @@ namespace ARMeilleure.CodeGen.Arm64
OperandType valueType = GetMemOpValueType(currentOp); OperandType valueType = GetMemOpValueType(currentOp);
if (valueType != GetMemOpValueType(nextOp) || op1Offset + valueType.GetSizeInBytes() != op2Offset) if (valueType != GetMemOpValueType(nextOp) || op1Offset + valueType.ByteSize != op2Offset)
{ {
return false; return false;
} }
if (!CodeGenCommon.ConstFitsOnSImm7(op1Offset, valueType.GetSizeInBytesLog2())) if (!CodeGenCommon.ConstFitsOnSImm7(op1Offset, valueType.ByteSizeLog2))
{ {
return false; return false;
} }
@@ -1549,7 +1549,7 @@ namespace ARMeilleure.CodeGen.Arm64
// EnsureSameReg (dest, src1); // EnsureSameReg (dest, src1);
EnsureSameType(dest, src1); EnsureSameType(dest, src1);
Debug.Assert(dest.Type.IsInteger() && src2.Type == OperandType.I32); Debug.Assert(dest.Type.IsInteger && src2.Type == OperandType.I32);
} }
private static void EnsureSameReg(Operand op1, Operand op2) private static void EnsureSameReg(Operand op1, Operand op2)

View File

@@ -462,7 +462,7 @@ namespace ARMeilleure.CodeGen.Arm64
{ {
instruction |= (sz << 22); instruction |= (sz << 22);
if (rd.Type.IsInteger()) if (rd.Type.IsInteger)
{ {
context.Assembler.WriteInstructionAuto(instruction, rd, rn); context.Assembler.WriteInstructionAuto(instruction, rd, rn);
} }
@@ -490,7 +490,7 @@ namespace ARMeilleure.CodeGen.Arm64
instruction |= (sz << 22); instruction |= (sz << 22);
instruction |= (64 - fBits) << 10; instruction |= (64 - fBits) << 10;
if (rd.Type.IsInteger()) if (rd.Type.IsInteger)
{ {
Debug.Assert(rd.Type != OperandType.I32 || fBits <= 32); Debug.Assert(rd.Type != OperandType.I32 || fBits <= 32);

View File

@@ -112,7 +112,7 @@ namespace ARMeilleure.CodeGen.Arm64
if (src1.Kind == OperandKind.Constant) if (src1.Kind == OperandKind.Constant)
{ {
if (!src1.Type.IsInteger()) if (!src1.Type.IsInteger)
{ {
// Handle non-integer types (FP32, FP64 and V128). // Handle non-integer types (FP32, FP64 and V128).
// For instructions without an immediate operand, we do the following: // For instructions without an immediate operand, we do the following:
@@ -161,7 +161,7 @@ namespace ARMeilleure.CodeGen.Arm64
if (src2.Kind == OperandKind.Constant) if (src2.Kind == OperandKind.Constant)
{ {
if (!src2.Type.IsInteger()) if (!src2.Type.IsInteger)
{ {
src2 = AddFloatConstantCopy(constants, nodes, node, src2); src2 = AddFloatConstantCopy(constants, nodes, node, src2);
@@ -191,7 +191,7 @@ namespace ARMeilleure.CodeGen.Arm64
if (src.Kind == OperandKind.Constant) if (src.Kind == OperandKind.Constant)
{ {
if (!src.Type.IsInteger()) if (!src.Type.IsInteger)
{ {
src = AddFloatConstantCopy(constants, nodes, node, src); src = AddFloatConstantCopy(constants, nodes, node, src);
@@ -282,7 +282,7 @@ namespace ARMeilleure.CodeGen.Arm64
bool passOnReg; bool passOnReg;
if (source.Type.IsInteger()) if (source.Type.IsInteger)
{ {
passOnReg = intCount < intMax; passOnReg = intCount < intMax;
} }
@@ -309,7 +309,7 @@ namespace ARMeilleure.CodeGen.Arm64
if (passOnReg) if (passOnReg)
{ {
Operand argReg = source.Type.IsInteger() Operand argReg = source.Type.IsInteger
? Gpr(CallingConvention.GetIntArgumentRegister(intCount++), source.Type) ? Gpr(CallingConvention.GetIntArgumentRegister(intCount++), source.Type)
: Xmm(CallingConvention.GetVecArgumentRegister(vecCount++), source.Type); : Xmm(CallingConvention.GetVecArgumentRegister(vecCount++), source.Type);
@@ -327,7 +327,7 @@ namespace ARMeilleure.CodeGen.Arm64
InsertConstantRegCopies(constants, nodes, nodes.AddBefore(node, spillOp)); InsertConstantRegCopies(constants, nodes, nodes.AddBefore(node, spillOp));
stackOffset += source.Type.GetSizeInBytes(); stackOffset += source.Type.ByteSize;
} }
} }
@@ -345,7 +345,7 @@ namespace ARMeilleure.CodeGen.Arm64
} }
else else
{ {
Operand retReg = dest.Type.IsInteger() Operand retReg = dest.Type.IsInteger
? Gpr(CallingConvention.GetIntReturnRegister(), dest.Type) ? Gpr(CallingConvention.GetIntReturnRegister(), dest.Type)
: Xmm(CallingConvention.GetVecReturnRegister(), dest.Type); : Xmm(CallingConvention.GetVecReturnRegister(), dest.Type);
@@ -385,7 +385,7 @@ namespace ARMeilleure.CodeGen.Arm64
bool passOnReg; bool passOnReg;
if (source.Type.IsInteger()) if (source.Type.IsInteger)
{ {
passOnReg = intCount + 1 < intMax; passOnReg = intCount + 1 < intMax;
} }
@@ -408,7 +408,7 @@ namespace ARMeilleure.CodeGen.Arm64
if (passOnReg) if (passOnReg)
{ {
Operand argReg = source.Type.IsInteger() Operand argReg = source.Type.IsInteger
? Gpr(CallingConvention.GetIntArgumentRegister(intCount++), source.Type) ? Gpr(CallingConvention.GetIntArgumentRegister(intCount++), source.Type)
: Xmm(CallingConvention.GetVecArgumentRegister(vecCount++), source.Type); : Xmm(CallingConvention.GetVecArgumentRegister(vecCount++), source.Type);
@@ -521,7 +521,7 @@ namespace ARMeilleure.CodeGen.Arm64
} }
else else
{ {
Operand retReg = source.Type.IsInteger() Operand retReg = source.Type.IsInteger
? Gpr(CallingConvention.GetIntReturnRegister(), source.Type) ? Gpr(CallingConvention.GetIntReturnRegister(), source.Type)
: Xmm(CallingConvention.GetVecReturnRegister(), source.Type); : Xmm(CallingConvention.GetVecReturnRegister(), source.Type);
@@ -551,7 +551,7 @@ namespace ARMeilleure.CodeGen.Arm64
{ {
OperandType argType = cctx.FuncArgTypes[cIndex]; OperandType argType = cctx.FuncArgTypes[cIndex];
if (argType.IsInteger()) if (argType.IsInteger)
{ {
intCount++; intCount++;
} }
@@ -567,7 +567,7 @@ namespace ARMeilleure.CodeGen.Arm64
bool passOnReg; bool passOnReg;
if (source.Type.IsInteger()) if (source.Type.IsInteger)
{ {
passOnReg = intCount < CallingConvention.GetArgumentsOnRegsCount(); passOnReg = intCount < CallingConvention.GetArgumentsOnRegsCount();
} }
@@ -606,7 +606,7 @@ namespace ARMeilleure.CodeGen.Arm64
{ {
Operand pArg = Local(dest.Type); Operand pArg = Local(dest.Type);
Operand argReg = dest.Type.IsInteger() Operand argReg = dest.Type.IsInteger
? Gpr(CallingConvention.GetIntArgumentRegister(intCount), dest.Type) ? Gpr(CallingConvention.GetIntArgumentRegister(intCount), dest.Type)
: Xmm(CallingConvention.GetVecArgumentRegister(vecCount), dest.Type); : Xmm(CallingConvention.GetVecArgumentRegister(vecCount), dest.Type);

View File

@@ -51,7 +51,7 @@ namespace ARMeilleure.CodeGen.Optimizations
if (trueSucc == block.ListNext) if (trueSucc == block.ListNext)
{ {
Comparison comp = (Comparison)branchOp.GetSource(2).AsInt32(); Comparison comp = (Comparison)branchOp.GetSource(2).AsInt32();
Comparison compInv = comp.Invert(); Comparison compInv = comp.Inverse;
branchOp.SetSource(2, Const((int)compInv)); branchOp.SetSource(2, Const((int)compInv));

View File

@@ -161,7 +161,7 @@ namespace ARMeilleure.CodeGen.Optimizations
} }
else if (otherCompType == Comparison.Equal) else if (otherCompType == Comparison.Equal)
{ {
propCompType = compType.Invert(); propCompType = compType.Inverse;
} }
else else
{ {

View File

@@ -105,7 +105,7 @@ namespace ARMeilleure.CodeGen.Optimizations
Operand x = operation.GetSource(0); Operand x = operation.GetSource(0);
Operand y = operation.GetSource(1); Operand y = operation.GetSource(1);
if (x == y && x.Type.IsInteger()) if (x == y && x.Type.IsInteger)
{ {
operation.TurnIntoCopy(Const(x.Type, 0)); operation.TurnIntoCopy(Const(x.Type, 0));
} }
@@ -161,7 +161,7 @@ namespace ARMeilleure.CodeGen.Optimizations
private static bool IsConstEqual(Operand operand, ulong comparand) private static bool IsConstEqual(Operand operand, ulong comparand)
{ {
if (operand.Kind != OperandKind.Constant || !operand.Type.IsInteger()) if (operand.Kind != OperandKind.Constant || !operand.Type.IsInteger)
{ {
return false; return false;
} }

View File

@@ -98,7 +98,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{ {
OperandType type = types[copyDest]; OperandType type = types[copyDest];
type = type.IsInteger() ? OperandType.I64 : OperandType.V128; type = type.IsInteger ? OperandType.I64 : OperandType.V128;
EmitXorSwap(sequence, GetRegister(copyDest, type), GetRegister(copySource, type)); EmitXorSwap(sequence, GetRegister(copyDest, type), GetRegister(copySource, type));

View File

@@ -178,7 +178,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
} }
else if (dest.Kind == OperandKind.Register) else if (dest.Kind == OperandKind.Register)
{ {
if (dest.Type.IsInteger()) if (dest.Type.IsInteger)
{ {
intFixedRegisters |= 1 << dest.GetRegister().Index; intFixedRegisters |= 1 << dest.GetRegister().Index;
} }
@@ -236,7 +236,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{ {
Register reg = info.Register.GetRegister(); Register reg = info.Register.GetRegister();
if (local.Type.IsInteger()) if (local.Type.IsInteger)
{ {
intLocalFreeRegisters |= 1 << reg.Index; intLocalFreeRegisters |= 1 << reg.Index;
} }
@@ -254,7 +254,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
if (temp == default || info.Sequence != sequence) if (temp == default || info.Sequence != sequence)
{ {
temp = local.Type.IsInteger() temp = local.Type.IsInteger
? GetSpillTemp(local, intSpillTempRegisters, ref intLocalUse) ? GetSpillTemp(local, intSpillTempRegisters, ref intLocalUse)
: GetSpillTemp(local, vecSpillTempRegisters, ref vecLocalUse); : GetSpillTemp(local, vecSpillTempRegisters, ref vecLocalUse);
@@ -335,7 +335,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
if (info.UsesAllocated == 0) if (info.UsesAllocated == 0)
{ {
int mask = dest.Type.IsInteger() int mask = dest.Type.IsInteger
? intLocalFreeRegisters ? intLocalFreeRegisters
: vecLocalFreeRegisters; : vecLocalFreeRegisters;
@@ -343,9 +343,9 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{ {
int selectedReg = BitOperations.TrailingZeroCount(mask); int selectedReg = BitOperations.TrailingZeroCount(mask);
info.Register = Register(selectedReg, info.Type.ToRegisterType(), info.Type); info.Register = Register(selectedReg, info.Type.Register, info.Type);
if (dest.Type.IsInteger()) if (dest.Type.IsInteger)
{ {
intLocalFreeRegisters &= ~(1 << selectedReg); intLocalFreeRegisters &= ~(1 << selectedReg);
intUsedRegisters |= 1 << selectedReg; intUsedRegisters |= 1 << selectedReg;
@@ -359,7 +359,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
else else
{ {
info.Register = default; info.Register = default;
info.SpillOffset = Const(stackAlloc.Allocate(dest.Type.GetSizeInBytes())); info.SpillOffset = Const(stackAlloc.Allocate(dest.Type.ByteSize));
} }
} }
@@ -377,7 +377,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
if (temp == default || info.Sequence != sequence) if (temp == default || info.Sequence != sequence)
{ {
temp = dest.Type.IsInteger() temp = dest.Type.IsInteger
? GetSpillTemp(dest, intSpillTempRegisters, ref intLocalAsg) ? GetSpillTemp(dest, intSpillTempRegisters, ref intLocalAsg)
: GetSpillTemp(dest, vecSpillTempRegisters, ref vecLocalAsg); : GetSpillTemp(dest, vecSpillTempRegisters, ref vecLocalAsg);
@@ -443,7 +443,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
useMask |= 1 << selectedReg; useMask |= 1 << selectedReg;
return Register(selectedReg, local.Type.ToRegisterType(), local.Type); return Register(selectedReg, local.Type.Register, local.Type);
} }
private static int UsesCount(Operand local) private static int UsesCount(Operand local)

View File

@@ -208,7 +208,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
private bool TryAllocateRegWithoutSpill(AllocationContext context, LiveInterval current, int cIndex, int registersCount) private bool TryAllocateRegWithoutSpill(AllocationContext context, LiveInterval current, int cIndex, int registersCount)
{ {
RegisterType regType = current.Local.Type.ToRegisterType(); RegisterType regType = current.Local.Type.Register;
Span<int> freePositions = stackalloc int[registersCount]; Span<int> freePositions = stackalloc int[registersCount];
@@ -318,7 +318,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
private void AllocateRegWithSpill(AllocationContext context, LiveInterval current, int cIndex, int registersCount) private void AllocateRegWithSpill(AllocationContext context, LiveInterval current, int cIndex, int registersCount)
{ {
RegisterType regType = current.Local.Type.ToRegisterType(); RegisterType regType = current.Local.Type.Register;
Span<int> usePositions = stackalloc int[registersCount]; Span<int> usePositions = stackalloc int[registersCount];
Span<int> blockedPositions = stackalloc int[registersCount]; Span<int> blockedPositions = stackalloc int[registersCount];

View File

@@ -10,7 +10,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
public int Allocate(OperandType type) public int Allocate(OperandType type)
{ {
return Allocate(type.GetSizeInBytes()); return Allocate(type.ByteSize);
} }
public int Allocate(int sizeInBytes) public int Allocate(int sizeInBytes)

View File

@@ -385,7 +385,7 @@ namespace ARMeilleure.CodeGen.X86
{ {
ref readonly InstructionInfo info = ref _instTable[(int)X86Instruction.Movd]; ref readonly InstructionInfo info = ref _instTable[(int)X86Instruction.Movd];
if (source.Type.IsInteger() || source.Kind == OperandKind.Memory) if (source.Type.IsInteger || source.Kind == OperandKind.Memory)
{ {
WriteOpCode(dest, default, source, OperandType.None, info.Flags, info.OpRRM, rrm: true); WriteOpCode(dest, default, source, OperandType.None, info.Flags, info.OpRRM, rrm: true);
} }
@@ -416,11 +416,11 @@ namespace ARMeilleure.CodeGen.X86
InstructionFlags flags = info.Flags | InstructionFlags.RexW; InstructionFlags flags = info.Flags | InstructionFlags.RexW;
if (source.Type.IsInteger() || source.Kind == OperandKind.Memory) if (source.Type.IsInteger || source.Kind == OperandKind.Memory)
{ {
WriteOpCode(dest, default, source, OperandType.None, flags, info.OpRRM, rrm: true); WriteOpCode(dest, default, source, OperandType.None, flags, info.OpRRM, rrm: true);
} }
else if (dest.Type.IsInteger() || dest.Kind == OperandKind.Memory) else if (dest.Type.IsInteger || dest.Kind == OperandKind.Memory)
{ {
WriteOpCode(dest, default, source, OperandType.None, flags, info.OpRMR); WriteOpCode(dest, default, source, OperandType.None, flags, info.OpRMR);
} }
@@ -1107,17 +1107,17 @@ namespace ARMeilleure.CodeGen.X86
} }
else else
{ {
if (flags.HasFlag(InstructionFlags.Prefix66)) if ((flags & InstructionFlags.Prefix66) != 0)
{ {
WriteByte(0x66); WriteByte(0x66);
} }
if (flags.HasFlag(InstructionFlags.PrefixF2)) if ((flags & InstructionFlags.PrefixF2) != 0f)
{ {
WriteByte(0xf2); WriteByte(0xf2);
} }
if (flags.HasFlag(InstructionFlags.PrefixF3)) if ((flags & InstructionFlags.PrefixF3) != 0f)
{ {
WriteByte(0xf3); WriteByte(0xf3);
} }

View File

@@ -1,5 +1,4 @@
using System; using System;
using System.Diagnostics.CodeAnalysis;
namespace ARMeilleure.CodeGen.X86 namespace ARMeilleure.CodeGen.X86
{ {

View File

@@ -2,7 +2,6 @@ using ARMeilleure.CodeGen.RegisterAllocators;
using ARMeilleure.IntermediateRepresentation; using ARMeilleure.IntermediateRepresentation;
using Microsoft.IO; using Microsoft.IO;
using Ryujinx.Common.Memory; using Ryujinx.Common.Memory;
using System.IO;
using System.Numerics; using System.Numerics;
namespace ARMeilleure.CodeGen.X86 namespace ARMeilleure.CodeGen.X86

View File

@@ -289,7 +289,7 @@ namespace ARMeilleure.CodeGen.X86
EnsureSameType(dest, source); EnsureSameType(dest, source);
Debug.Assert(dest.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger);
context.Assembler.Popcnt(dest, source, dest.Type); context.Assembler.Popcnt(dest, source, dest.Type);
@@ -303,7 +303,7 @@ namespace ARMeilleure.CodeGen.X86
EnsureSameType(dest, source); EnsureSameType(dest, source);
Debug.Assert(!dest.Type.IsInteger()); Debug.Assert(!dest.Type.IsInteger);
context.Assembler.WriteInstruction(info.Inst, dest, source); context.Assembler.WriteInstruction(info.Inst, dest, source);
@@ -315,7 +315,7 @@ namespace ARMeilleure.CodeGen.X86
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
Debug.Assert(dest.Type.IsInteger() && !source.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger && !source.Type.IsInteger);
if (operation.Intrinsic == Intrinsic.X86Cvtsi2si) if (operation.Intrinsic == Intrinsic.X86Cvtsi2si)
{ {
@@ -349,8 +349,8 @@ namespace ARMeilleure.CodeGen.X86
EnsureSameReg(dest, src1); EnsureSameReg(dest, src1);
} }
Debug.Assert(!dest.Type.IsInteger()); Debug.Assert(!dest.Type.IsInteger);
Debug.Assert(!src2.Type.IsInteger() || src2.Kind == OperandKind.Constant); Debug.Assert(!src2.Type.IsInteger || src2.Kind == OperandKind.Constant);
context.Assembler.WriteInstruction(info.Inst, dest, src1, src2); context.Assembler.WriteInstruction(info.Inst, dest, src1, src2);
@@ -370,7 +370,7 @@ namespace ARMeilleure.CodeGen.X86
EnsureSameReg(dest, src1); EnsureSameReg(dest, src1);
} }
Debug.Assert(!dest.Type.IsInteger() && src2.Type.IsInteger()); Debug.Assert(!dest.Type.IsInteger && src2.Type.IsInteger);
context.Assembler.WriteInstruction(info.Inst, dest, src1, src2, src2.Type); context.Assembler.WriteInstruction(info.Inst, dest, src1, src2, src2.Type);
@@ -385,7 +385,7 @@ namespace ARMeilleure.CodeGen.X86
EnsureSameReg(dest, src1); EnsureSameReg(dest, src1);
Debug.Assert(dest.Type.IsInteger() && src1.Type.IsInteger() && src2.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger && src1.Type.IsInteger && src2.Type.IsInteger);
context.Assembler.WriteInstruction(info.Inst, dest, src2, dest.Type); context.Assembler.WriteInstruction(info.Inst, dest, src2, dest.Type);
@@ -405,7 +405,7 @@ namespace ARMeilleure.CodeGen.X86
EnsureSameReg(dest, src1); EnsureSameReg(dest, src1);
} }
Debug.Assert(!dest.Type.IsInteger() && src2.Kind == OperandKind.Constant); Debug.Assert(!dest.Type.IsInteger && src2.Kind == OperandKind.Constant);
context.Assembler.WriteInstruction(info.Inst, dest, src1, src2.AsByte()); context.Assembler.WriteInstruction(info.Inst, dest, src1, src2.AsByte());
@@ -421,7 +421,7 @@ namespace ARMeilleure.CodeGen.X86
EnsureSameType(dest, src1, src2, src3); EnsureSameType(dest, src1, src2, src3);
Debug.Assert(!dest.Type.IsInteger()); Debug.Assert(!dest.Type.IsInteger);
if (info.Inst == X86Instruction.Blendvpd && HardwareCapabilities.SupportsVexEncoding) if (info.Inst == X86Instruction.Blendvpd && HardwareCapabilities.SupportsVexEncoding)
{ {
@@ -461,7 +461,7 @@ namespace ARMeilleure.CodeGen.X86
EnsureSameReg(dest, src1); EnsureSameReg(dest, src1);
} }
Debug.Assert(!dest.Type.IsInteger() && src3.Kind == OperandKind.Constant); Debug.Assert(!dest.Type.IsInteger && src3.Kind == OperandKind.Constant);
context.Assembler.WriteInstruction(info.Inst, dest, src1, src2, src3.AsByte()); context.Assembler.WriteInstruction(info.Inst, dest, src1, src2, src3.AsByte());
@@ -512,7 +512,7 @@ namespace ARMeilleure.CodeGen.X86
Operand src1 = operation.GetSource(0); Operand src1 = operation.GetSource(0);
Operand src2 = operation.GetSource(1); Operand src2 = operation.GetSource(1);
if (dest.Type.IsInteger()) if (dest.Type.IsInteger)
{ {
// If Destination and Source 1 Operands are the same, perform a standard add as there are no benefits to using LEA. // If Destination and Source 1 Operands are the same, perform a standard add as there are no benefits to using LEA.
if (dest.Kind == src1.Kind && dest.Value == src1.Value) if (dest.Kind == src1.Kind && dest.Value == src1.Value)
@@ -567,7 +567,7 @@ namespace ARMeilleure.CodeGen.X86
ValidateBinOp(dest, src1, src2); ValidateBinOp(dest, src1, src2);
Debug.Assert(dest.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger);
// Note: GenerateCompareCommon makes the assumption that BitwiseAnd will emit only a single `and` // Note: GenerateCompareCommon makes the assumption that BitwiseAnd will emit only a single `and`
// instruction. // instruction.
@@ -582,7 +582,7 @@ namespace ARMeilleure.CodeGen.X86
ValidateBinOp(dest, src1, src2); ValidateBinOp(dest, src1, src2);
if (dest.Type.IsInteger()) if (dest.Type.IsInteger)
{ {
context.Assembler.Xor(dest, src2, dest.Type); context.Assembler.Xor(dest, src2, dest.Type);
} }
@@ -599,7 +599,7 @@ namespace ARMeilleure.CodeGen.X86
ValidateUnOp(dest, source); ValidateUnOp(dest, source);
Debug.Assert(dest.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger);
context.Assembler.Not(dest); context.Assembler.Not(dest);
} }
@@ -612,7 +612,7 @@ namespace ARMeilleure.CodeGen.X86
ValidateBinOp(dest, src1, src2); ValidateBinOp(dest, src1, src2);
Debug.Assert(dest.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger);
context.Assembler.Or(dest, src2, dest.Type); context.Assembler.Or(dest, src2, dest.Type);
} }
@@ -623,7 +623,7 @@ namespace ARMeilleure.CodeGen.X86
Debug.Assert(comp.Kind == OperandKind.Constant); Debug.Assert(comp.Kind == OperandKind.Constant);
X86Condition cond = ((Comparison)comp.AsInt32()).ToX86Condition(); X86Condition cond = ((Comparison)comp.AsInt32()).X86;
GenerateCompareCommon(context, operation); GenerateCompareCommon(context, operation);
@@ -637,7 +637,7 @@ namespace ARMeilleure.CodeGen.X86
ValidateUnOp(dest, source); ValidateUnOp(dest, source);
Debug.Assert(dest.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger);
context.Assembler.Bswap(dest); context.Assembler.Bswap(dest);
} }
@@ -661,7 +661,7 @@ namespace ARMeilleure.CodeGen.X86
Debug.Assert(dest.Type == OperandType.I32); Debug.Assert(dest.Type == OperandType.I32);
Debug.Assert(comp.Kind == OperandKind.Constant); Debug.Assert(comp.Kind == OperandKind.Constant);
X86Condition cond = ((Comparison)comp.AsInt32()).ToX86Condition(); X86Condition cond = ((Comparison)comp.AsInt32()).X86;
GenerateCompareCommon(context, operation); GenerateCompareCommon(context, operation);
@@ -676,7 +676,7 @@ namespace ARMeilleure.CodeGen.X86
EnsureSameType(src1, src2); EnsureSameType(src1, src2);
Debug.Assert(src1.Type.IsInteger()); Debug.Assert(src1.Type.IsInteger);
if (src2.Kind == OperandKind.Constant && src2.Value == 0) if (src2.Kind == OperandKind.Constant && src2.Value == 0)
{ {
@@ -766,7 +766,7 @@ namespace ARMeilleure.CodeGen.X86
EnsureSameReg(dest, src3); EnsureSameReg(dest, src3);
EnsureSameType(dest, src2, src3); EnsureSameType(dest, src2, src3);
Debug.Assert(dest.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger);
Debug.Assert(src1.Type == OperandType.I32); Debug.Assert(src1.Type == OperandType.I32);
context.Assembler.Test(src1, src1, src1.Type); context.Assembler.Test(src1, src1, src1.Type);
@@ -792,9 +792,9 @@ namespace ARMeilleure.CodeGen.X86
if (dest.Type == OperandType.FP32) if (dest.Type == OperandType.FP32)
{ {
Debug.Assert(source.Type.IsInteger() || source.Type == OperandType.FP64); Debug.Assert(source.Type.IsInteger || source.Type == OperandType.FP64);
if (source.Type.IsInteger()) if (source.Type.IsInteger)
{ {
context.Assembler.Xorps(dest, dest, dest); context.Assembler.Xorps(dest, dest, dest);
context.Assembler.Cvtsi2ss(dest, dest, source, source.Type); context.Assembler.Cvtsi2ss(dest, dest, source, source.Type);
@@ -808,9 +808,9 @@ namespace ARMeilleure.CodeGen.X86
} }
else /* if (dest.Type == OperandType.FP64) */ else /* if (dest.Type == OperandType.FP64) */
{ {
Debug.Assert(source.Type.IsInteger() || source.Type == OperandType.FP32); Debug.Assert(source.Type.IsInteger || source.Type == OperandType.FP32);
if (source.Type.IsInteger()) if (source.Type.IsInteger)
{ {
context.Assembler.Xorps(dest, dest, dest); context.Assembler.Xorps(dest, dest, dest);
context.Assembler.Cvtsi2sd(dest, dest, source, source.Type); context.Assembler.Cvtsi2sd(dest, dest, source, source.Type);
@@ -831,7 +831,7 @@ namespace ARMeilleure.CodeGen.X86
EnsureSameType(dest, source); EnsureSameType(dest, source);
Debug.Assert(dest.Type.IsInteger() || source.Kind != OperandKind.Constant); Debug.Assert(dest.Type.IsInteger || source.Kind != OperandKind.Constant);
// Moves to the same register are useless. // Moves to the same register are useless.
if (dest.Kind == source.Kind && dest.Value == source.Value) if (dest.Kind == source.Kind && dest.Value == source.Value)
@@ -845,7 +845,7 @@ namespace ARMeilleure.CodeGen.X86
// Assemble "mov reg, 0" as "xor reg, reg" as the later is more efficient. // Assemble "mov reg, 0" as "xor reg, reg" as the later is more efficient.
context.Assembler.Xor(dest, dest, OperandType.I32); context.Assembler.Xor(dest, dest, OperandType.I32);
} }
else if (dest.Type.IsInteger()) else if (dest.Type.IsInteger)
{ {
context.Assembler.Mov(dest, source, dest.Type); context.Assembler.Mov(dest, source, dest.Type);
} }
@@ -862,7 +862,7 @@ namespace ARMeilleure.CodeGen.X86
EnsureSameType(dest, source); EnsureSameType(dest, source);
Debug.Assert(dest.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger);
context.Assembler.Bsr(dest, source, dest.Type); context.Assembler.Bsr(dest, source, dest.Type);
@@ -894,12 +894,12 @@ namespace ARMeilleure.CodeGen.X86
Operand dividend = operation.GetSource(0); Operand dividend = operation.GetSource(0);
Operand divisor = operation.GetSource(1); Operand divisor = operation.GetSource(1);
if (!dest.Type.IsInteger()) if (!dest.Type.IsInteger)
{ {
ValidateBinOp(dest, dividend, divisor); ValidateBinOp(dest, dividend, divisor);
} }
if (dest.Type.IsInteger()) if (dest.Type.IsInteger)
{ {
divisor = operation.GetSource(2); divisor = operation.GetSource(2);
@@ -932,7 +932,7 @@ namespace ARMeilleure.CodeGen.X86
Operand rdx = Register(X86Register.Rdx); Operand rdx = Register(X86Register.Rdx);
Debug.Assert(divisor.Type.IsInteger()); Debug.Assert(divisor.Type.IsInteger);
context.Assembler.Xor(rdx, rdx, OperandType.I32); context.Assembler.Xor(rdx, rdx, OperandType.I32);
context.Assembler.Div(divisor); context.Assembler.Div(divisor);
@@ -967,7 +967,7 @@ namespace ARMeilleure.CodeGen.X86
Operand value = operation.Destination; Operand value = operation.Destination;
Operand address = Memory(operation.GetSource(0), value.Type); Operand address = Memory(operation.GetSource(0), value.Type);
Debug.Assert(value.Type.IsInteger()); Debug.Assert(value.Type.IsInteger);
context.Assembler.Movzx16(value, address, value.Type); context.Assembler.Movzx16(value, address, value.Type);
} }
@@ -977,7 +977,7 @@ namespace ARMeilleure.CodeGen.X86
Operand value = operation.Destination; Operand value = operation.Destination;
Operand address = Memory(operation.GetSource(0), value.Type); Operand address = Memory(operation.GetSource(0), value.Type);
Debug.Assert(value.Type.IsInteger()); Debug.Assert(value.Type.IsInteger);
context.Assembler.Movzx8(value, address, value.Type); context.Assembler.Movzx8(value, address, value.Type);
} }
@@ -1000,7 +1000,7 @@ namespace ARMeilleure.CodeGen.X86
EnsureSameType(dest, src1, src2); EnsureSameType(dest, src1, src2);
if (dest.Type.IsInteger()) if (dest.Type.IsInteger)
{ {
if (src2.Kind == OperandKind.Constant) if (src2.Kind == OperandKind.Constant)
{ {
@@ -1046,7 +1046,7 @@ namespace ARMeilleure.CodeGen.X86
ValidateUnOp(dest, source); ValidateUnOp(dest, source);
Debug.Assert(dest.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger);
context.Assembler.Neg(dest); context.Assembler.Neg(dest);
} }
@@ -1107,7 +1107,7 @@ namespace ARMeilleure.CodeGen.X86
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger && source.Type.IsInteger);
context.Assembler.Movsx16(dest, source, dest.Type); context.Assembler.Movsx16(dest, source, dest.Type);
} }
@@ -1117,7 +1117,7 @@ namespace ARMeilleure.CodeGen.X86
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger && source.Type.IsInteger);
context.Assembler.Movsx32(dest, source, dest.Type); context.Assembler.Movsx32(dest, source, dest.Type);
} }
@@ -1127,7 +1127,7 @@ namespace ARMeilleure.CodeGen.X86
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger && source.Type.IsInteger);
context.Assembler.Movsx8(dest, source, dest.Type); context.Assembler.Movsx8(dest, source, dest.Type);
} }
@@ -1187,7 +1187,7 @@ namespace ARMeilleure.CodeGen.X86
Operand value = operation.GetSource(1); Operand value = operation.GetSource(1);
Operand address = Memory(operation.GetSource(0), value.Type); Operand address = Memory(operation.GetSource(0), value.Type);
Debug.Assert(value.Type.IsInteger()); Debug.Assert(value.Type.IsInteger);
context.Assembler.Mov16(address, value); context.Assembler.Mov16(address, value);
} }
@@ -1197,7 +1197,7 @@ namespace ARMeilleure.CodeGen.X86
Operand value = operation.GetSource(1); Operand value = operation.GetSource(1);
Operand address = Memory(operation.GetSource(0), value.Type); Operand address = Memory(operation.GetSource(0), value.Type);
Debug.Assert(value.Type.IsInteger()); Debug.Assert(value.Type.IsInteger);
context.Assembler.Mov8(address, value); context.Assembler.Mov8(address, value);
} }
@@ -1210,7 +1210,7 @@ namespace ARMeilleure.CodeGen.X86
ValidateBinOp(dest, src1, src2); ValidateBinOp(dest, src1, src2);
if (dest.Type.IsInteger()) if (dest.Type.IsInteger)
{ {
context.Assembler.Sub(dest, src2, dest.Type); context.Assembler.Sub(dest, src2, dest.Type);
} }
@@ -1236,7 +1236,7 @@ namespace ARMeilleure.CodeGen.X86
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
Debug.Assert(!dest.Type.IsInteger() && source.Type.IsInteger()); Debug.Assert(!dest.Type.IsInteger && source.Type.IsInteger);
if (source.Type == OperandType.I32) if (source.Type == OperandType.I32)
{ {
@@ -1259,7 +1259,7 @@ namespace ARMeilleure.CodeGen.X86
byte index = src2.AsByte(); byte index = src2.AsByte();
Debug.Assert(index < OperandType.V128.GetSizeInBytes() / dest.Type.GetSizeInBytes()); Debug.Assert(index < OperandType.V128.ByteSize / dest.Type.ByteSize);
if (dest.Type == OperandType.I32) if (dest.Type == OperandType.I32)
{ {
@@ -1541,7 +1541,7 @@ namespace ARMeilleure.CodeGen.X86
{ {
Operand dest = operation.Destination; Operand dest = operation.Destination;
Debug.Assert(!dest.Type.IsInteger()); Debug.Assert(!dest.Type.IsInteger);
context.Assembler.Pcmpeqw(dest, dest, dest); context.Assembler.Pcmpeqw(dest, dest, dest);
} }
@@ -1550,7 +1550,7 @@ namespace ARMeilleure.CodeGen.X86
{ {
Operand dest = operation.Destination; Operand dest = operation.Destination;
Debug.Assert(!dest.Type.IsInteger()); Debug.Assert(!dest.Type.IsInteger);
context.Assembler.Xorps(dest, dest, dest); context.Assembler.Xorps(dest, dest, dest);
} }
@@ -1580,7 +1580,7 @@ namespace ARMeilleure.CodeGen.X86
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger && source.Type.IsInteger);
context.Assembler.Movzx16(dest, source, OperandType.I32); context.Assembler.Movzx16(dest, source, OperandType.I32);
} }
@@ -1590,7 +1590,7 @@ namespace ARMeilleure.CodeGen.X86
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger && source.Type.IsInteger);
// We can eliminate the move if source is already 32-bit and the registers are the same. // We can eliminate the move if source is already 32-bit and the registers are the same.
if (dest.Value == source.Value && source.Type == OperandType.I32) if (dest.Value == source.Value && source.Type == OperandType.I32)
@@ -1606,7 +1606,7 @@ namespace ARMeilleure.CodeGen.X86
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger && source.Type.IsInteger);
context.Assembler.Movzx8(dest, source, OperandType.I32); context.Assembler.Movzx8(dest, source, OperandType.I32);
} }
@@ -1713,12 +1713,12 @@ namespace ARMeilleure.CodeGen.X86
EnsureSameReg(dest, src1); EnsureSameReg(dest, src1);
EnsureSameType(dest, src1); EnsureSameType(dest, src1);
Debug.Assert(dest.Type.IsInteger() && src2.Type == OperandType.I32); Debug.Assert(dest.Type.IsInteger && src2.Type == OperandType.I32);
} }
private static void EnsureSameReg(Operand op1, Operand op2) private static void EnsureSameReg(Operand op1, Operand op2)
{ {
if (!op1.Type.IsInteger() && HardwareCapabilities.SupportsVexEncoding) if (!op1.Type.IsInteger && HardwareCapabilities.SupportsVexEncoding)
{ {
return; return;
} }

View File

@@ -86,7 +86,7 @@ namespace ARMeilleure.CodeGen.X86
break; break;
case Instruction.Negate: case Instruction.Negate:
if (!node.GetSource(0).Type.IsInteger()) if (!node.GetSource(0).Type.IsInteger)
{ {
GenerateNegate(block.Operations, node); GenerateNegate(block.Operations, node);
} }
@@ -159,7 +159,7 @@ namespace ARMeilleure.CodeGen.X86
if (src1.Kind == OperandKind.Constant) if (src1.Kind == OperandKind.Constant)
{ {
if (!src1.Type.IsInteger()) if (!src1.Type.IsInteger)
{ {
// Handle non-integer types (FP32, FP64 and V128). // Handle non-integer types (FP32, FP64 and V128).
// For instructions without an immediate operand, we do the following: // For instructions without an immediate operand, we do the following:
@@ -208,7 +208,7 @@ namespace ARMeilleure.CodeGen.X86
if (src2.Kind == OperandKind.Constant) if (src2.Kind == OperandKind.Constant)
{ {
if (!src2.Type.IsInteger()) if (!src2.Type.IsInteger)
{ {
src2 = AddXmmCopy(nodes, node, src2); src2 = AddXmmCopy(nodes, node, src2);
@@ -298,7 +298,7 @@ namespace ARMeilleure.CodeGen.X86
// - The dividend is always in RDX:RAX. // - The dividend is always in RDX:RAX.
// - The result is always in RAX. // - The result is always in RAX.
// - Additionally it also writes the remainder in RDX. // - Additionally it also writes the remainder in RDX.
if (dest.Type.IsInteger()) if (dest.Type.IsInteger)
{ {
Operand src1 = node.GetSource(0); Operand src1 = node.GetSource(0);
@@ -466,7 +466,7 @@ namespace ARMeilleure.CodeGen.X86
Operand dest = node.Destination; Operand dest = node.Destination;
Operand source = node.GetSource(0); Operand source = node.GetSource(0);
Debug.Assert(source.Type.IsInteger(), $"Invalid source type \"{source.Type}\"."); Debug.Assert(source.Type.IsInteger, $"Invalid source type \"{source.Type}\".");
Operation currentNode = node; Operation currentNode = node;
@@ -654,10 +654,10 @@ namespace ARMeilleure.CodeGen.X86
switch (operation.Instruction) switch (operation.Instruction)
{ {
case Instruction.Add: case Instruction.Add:
return !HardwareCapabilities.SupportsVexEncoding && !operation.Destination.Type.IsInteger(); return !HardwareCapabilities.SupportsVexEncoding && !operation.Destination.Type.IsInteger;
case Instruction.Multiply: case Instruction.Multiply:
case Instruction.Subtract: case Instruction.Subtract:
return !HardwareCapabilities.SupportsVexEncoding || operation.Destination.Type.IsInteger(); return !HardwareCapabilities.SupportsVexEncoding || operation.Destination.Type.IsInteger;
case Instruction.BitwiseAnd: case Instruction.BitwiseAnd:
case Instruction.BitwiseExclusiveOr: case Instruction.BitwiseExclusiveOr:
@@ -672,7 +672,7 @@ namespace ARMeilleure.CodeGen.X86
return true; return true;
case Instruction.Divide: case Instruction.Divide:
return !HardwareCapabilities.SupportsVexEncoding && !operation.Destination.Type.IsInteger(); return !HardwareCapabilities.SupportsVexEncoding && !operation.Destination.Type.IsInteger;
case Instruction.VectorInsert: case Instruction.VectorInsert:
case Instruction.VectorInsert16: case Instruction.VectorInsert16:

View File

@@ -35,7 +35,7 @@ namespace ARMeilleure.CodeGen.X86
bool passOnReg; bool passOnReg;
if (source.Type.IsInteger()) if (source.Type.IsInteger)
{ {
passOnReg = intCount < intMax; passOnReg = intCount < intMax;
} }
@@ -62,7 +62,7 @@ namespace ARMeilleure.CodeGen.X86
if (passOnReg) if (passOnReg)
{ {
Operand argReg = source.Type.IsInteger() Operand argReg = source.Type.IsInteger
? Gpr(CallingConvention.GetIntArgumentRegister(intCount++), source.Type) ? Gpr(CallingConvention.GetIntArgumentRegister(intCount++), source.Type)
: Xmm(CallingConvention.GetVecArgumentRegister(vecCount++), source.Type); : Xmm(CallingConvention.GetVecArgumentRegister(vecCount++), source.Type);
@@ -80,7 +80,7 @@ namespace ARMeilleure.CodeGen.X86
InsertConstantRegCopies(nodes, nodes.AddBefore(node, spillOp)); InsertConstantRegCopies(nodes, nodes.AddBefore(node, spillOp));
stackOffset += source.Type.GetSizeInBytes(); stackOffset += source.Type.ByteSize;
} }
} }
@@ -102,7 +102,7 @@ namespace ARMeilleure.CodeGen.X86
} }
else else
{ {
Operand retReg = dest.Type.IsInteger() Operand retReg = dest.Type.IsInteger
? Gpr(CallingConvention.GetIntReturnRegister(), dest.Type) ? Gpr(CallingConvention.GetIntReturnRegister(), dest.Type)
: Xmm(CallingConvention.GetVecReturnRegister(), dest.Type); : Xmm(CallingConvention.GetVecReturnRegister(), dest.Type);
@@ -137,7 +137,7 @@ namespace ARMeilleure.CodeGen.X86
bool passOnReg; bool passOnReg;
if (source.Type.IsInteger()) if (source.Type.IsInteger)
{ {
passOnReg = intCount + 1 < intMax; passOnReg = intCount + 1 < intMax;
} }
@@ -160,7 +160,7 @@ namespace ARMeilleure.CodeGen.X86
if (passOnReg) if (passOnReg)
{ {
Operand argReg = source.Type.IsInteger() Operand argReg = source.Type.IsInteger
? Gpr(CallingConvention.GetIntArgumentRegister(intCount++), source.Type) ? Gpr(CallingConvention.GetIntArgumentRegister(intCount++), source.Type)
: Xmm(CallingConvention.GetVecArgumentRegister(vecCount++), source.Type); : Xmm(CallingConvention.GetVecArgumentRegister(vecCount++), source.Type);
@@ -210,7 +210,7 @@ namespace ARMeilleure.CodeGen.X86
{ {
OperandType argType = cctx.FuncArgTypes[cIndex]; OperandType argType = cctx.FuncArgTypes[cIndex];
if (argType.IsInteger()) if (argType.IsInteger)
{ {
intCount++; intCount++;
} }
@@ -226,7 +226,7 @@ namespace ARMeilleure.CodeGen.X86
bool passOnReg; bool passOnReg;
if (source.Type.IsInteger()) if (source.Type.IsInteger)
{ {
passOnReg = intCount < CallingConvention.GetIntArgumentsOnRegsCount(); passOnReg = intCount < CallingConvention.GetIntArgumentsOnRegsCount();
} }
@@ -265,7 +265,7 @@ namespace ARMeilleure.CodeGen.X86
{ {
Operand pArg = Local(dest.Type); Operand pArg = Local(dest.Type);
Operand argReg = dest.Type.IsInteger() Operand argReg = dest.Type.IsInteger
? Gpr(CallingConvention.GetIntArgumentRegister(intCount), dest.Type) ? Gpr(CallingConvention.GetIntArgumentRegister(intCount), dest.Type)
: Xmm(CallingConvention.GetVecArgumentRegister(vecCount), dest.Type); : Xmm(CallingConvention.GetVecArgumentRegister(vecCount), dest.Type);
@@ -320,7 +320,7 @@ namespace ARMeilleure.CodeGen.X86
} }
else else
{ {
Operand retReg = source.Type.IsInteger() Operand retReg = source.Type.IsInteger
? Gpr(CallingConvention.GetIntReturnRegister(), source.Type) ? Gpr(CallingConvention.GetIntReturnRegister(), source.Type)
: Xmm(CallingConvention.GetVecReturnRegister(), source.Type); : Xmm(CallingConvention.GetVecReturnRegister(), source.Type);

View File

@@ -40,7 +40,7 @@ namespace ARMeilleure.CodeGen.X86
if (dest != default && dest.Type == OperandType.V128) if (dest != default && dest.Type == OperandType.V128)
{ {
int stackOffset = AllocateOnStack(dest.Type.GetSizeInBytes()); int stackOffset = AllocateOnStack(dest.Type.ByteSize);
arg0Reg = Gpr(CallingConvention.GetIntArgumentRegister(0), OperandType.I64); arg0Reg = Gpr(CallingConvention.GetIntArgumentRegister(0), OperandType.I64);
@@ -76,7 +76,7 @@ namespace ARMeilleure.CodeGen.X86
{ {
Operand stackAddr = Local(OperandType.I64); Operand stackAddr = Local(OperandType.I64);
int stackOffset = AllocateOnStack(source.Type.GetSizeInBytes()); int stackOffset = AllocateOnStack(source.Type.ByteSize);
nodes.AddBefore(node, Operation(Instruction.StackAlloc, stackAddr, Const(stackOffset))); nodes.AddBefore(node, Operation(Instruction.StackAlloc, stackAddr, Const(stackOffset)));
@@ -96,7 +96,7 @@ namespace ARMeilleure.CodeGen.X86
int argIndex = index + retArgs; int argIndex = index + retArgs;
if (source.Type.IsInteger()) if (source.Type.IsInteger)
{ {
argReg = Gpr(CallingConvention.GetIntArgumentRegister(argIndex), source.Type); argReg = Gpr(CallingConvention.GetIntArgumentRegister(argIndex), source.Type);
} }
@@ -140,7 +140,7 @@ namespace ARMeilleure.CodeGen.X86
} }
else else
{ {
Operand retReg = dest.Type.IsInteger() Operand retReg = dest.Type.IsInteger
? Gpr(CallingConvention.GetIntReturnRegister(), dest.Type) ? Gpr(CallingConvention.GetIntReturnRegister(), dest.Type)
: Xmm(CallingConvention.GetVecReturnRegister(), dest.Type); : Xmm(CallingConvention.GetVecReturnRegister(), dest.Type);
@@ -171,7 +171,7 @@ namespace ARMeilleure.CodeGen.X86
for (int index = 0; index < argsCount; index++) for (int index = 0; index < argsCount; index++)
{ {
Operand source = node.GetSource(1 + index); Operand source = node.GetSource(1 + index);
Operand argReg = source.Type.IsInteger() Operand argReg = source.Type.IsInteger
? Gpr(CallingConvention.GetIntArgumentRegister(index), source.Type) ? Gpr(CallingConvention.GetIntArgumentRegister(index), source.Type)
: Xmm(CallingConvention.GetVecArgumentRegister(index), source.Type); : Xmm(CallingConvention.GetVecArgumentRegister(index), source.Type);
@@ -219,7 +219,7 @@ namespace ARMeilleure.CodeGen.X86
{ {
Operand argReg, pArg; Operand argReg, pArg;
if (dest.Type.IsInteger()) if (dest.Type.IsInteger)
{ {
argReg = Gpr(CallingConvention.GetIntArgumentRegister(index), dest.Type); argReg = Gpr(CallingConvention.GetIntArgumentRegister(index), dest.Type);
pArg = Local(dest.Type); pArg = Local(dest.Type);
@@ -283,7 +283,7 @@ namespace ARMeilleure.CodeGen.X86
Operand source = node.GetSource(0); Operand source = node.GetSource(0);
Operand retReg; Operand retReg;
if (source.Type.IsInteger()) if (source.Type.IsInteger)
{ {
retReg = Gpr(CallingConvention.GetIntReturnRegister(), source.Type); retReg = Gpr(CallingConvention.GetIntReturnRegister(), source.Type);
} }

View File

@@ -25,9 +25,9 @@ namespace ARMeilleure.CodeGen.X86
static class ComparisonX86Extensions static class ComparisonX86Extensions
{ {
public static X86Condition ToX86Condition(this Comparison comp) extension(Comparison comparison)
{ {
return comp switch public X86Condition X86 => comparison switch
{ {
#pragma warning disable IDE0055 // Disable formatting #pragma warning disable IDE0055 // Disable formatting
Comparison.Equal => X86Condition.Equal, Comparison.Equal => X86Condition.Equal,
@@ -42,7 +42,7 @@ namespace ARMeilleure.CodeGen.X86
Comparison.LessUI => X86Condition.Below, Comparison.LessUI => X86Condition.Below,
#pragma warning restore IDE0055 #pragma warning restore IDE0055
_ => throw new ArgumentException(null, nameof(comp)), _ => throw new ArgumentException(null, nameof(comparison))
}; };
} }
} }

View File

@@ -1,5 +1,3 @@
using System.Diagnostics.CodeAnalysis;
namespace ARMeilleure.CodeGen.X86 namespace ARMeilleure.CodeGen.X86
{ {
enum X86Register enum X86Register

View File

@@ -22,11 +22,11 @@ namespace ARMeilleure.Decoders
static class ConditionExtensions static class ConditionExtensions
{ {
public static Condition Invert(this Condition cond) extension(Condition condition)
{ {
// Bit 0 of all conditions is basically a negation bit, so // Bit 0 of all conditions is basically a negation bit, so
// inverting this bit has the effect of inverting the condition. // inverting this bit has the effect of inverting the condition.
return (Condition)((int)cond ^ 1); public Condition Inverse => (Condition)((int)condition ^ 1);
} }
} }
} }

View File

@@ -16,7 +16,7 @@ namespace ARMeilleure.Instructions
public static Operand EmitCrc32(ArmEmitterContext context, Operand crc, Operand value, int size, bool castagnoli) public static Operand EmitCrc32(ArmEmitterContext context, Operand crc, Operand value, int size, bool castagnoli)
{ {
Debug.Assert(crc.Type.IsInteger() && value.Type.IsInteger()); Debug.Assert(crc.Type.IsInteger && value.Type.IsInteger);
Debug.Assert(size is >= 0 and < 4); Debug.Assert(size is >= 0 and < 4);
Debug.Assert((size < 3) || (value.Type == OperandType.I64)); Debug.Assert((size < 3) || (value.Type == OperandType.I64));

View File

@@ -157,7 +157,7 @@ namespace ARMeilleure.Instructions
context.Copy(temp, value); context.Copy(temp, value);
if (!context.Memory.Type.IsHostMappedOrTracked()) if (!context.Memory.Type.IsHostMappedOrTracked)
{ {
context.Branch(lblEnd); context.Branch(lblEnd);
@@ -198,7 +198,7 @@ namespace ARMeilleure.Instructions
SetInt(context, rt, value); SetInt(context, rt, value);
if (!context.Memory.Type.IsHostMappedOrTracked()) if (!context.Memory.Type.IsHostMappedOrTracked)
{ {
context.Branch(lblEnd); context.Branch(lblEnd);
@@ -265,7 +265,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(rt), value); context.Copy(GetVec(rt), value);
if (!context.Memory.Type.IsHostMappedOrTracked()) if (!context.Memory.Type.IsHostMappedOrTracked)
{ {
context.Branch(lblEnd); context.Branch(lblEnd);
@@ -312,7 +312,7 @@ namespace ARMeilleure.Instructions
break; break;
} }
if (!context.Memory.Type.IsHostMappedOrTracked()) if (!context.Memory.Type.IsHostMappedOrTracked)
{ {
context.Branch(lblEnd); context.Branch(lblEnd);
@@ -385,7 +385,7 @@ namespace ARMeilleure.Instructions
break; break;
} }
if (!context.Memory.Type.IsHostMappedOrTracked()) if (!context.Memory.Type.IsHostMappedOrTracked)
{ {
context.Branch(lblEnd); context.Branch(lblEnd);
@@ -399,11 +399,11 @@ namespace ARMeilleure.Instructions
public static Operand EmitPtPointerLoad(ArmEmitterContext context, Operand address, Operand lblSlowPath, bool write, int size) public static Operand EmitPtPointerLoad(ArmEmitterContext context, Operand address, Operand lblSlowPath, bool write, int size)
{ {
if (context.Memory.Type.IsHostMapped()) if (context.Memory.Type.IsHostMapped)
{ {
return EmitHostMappedPointer(context, address); return EmitHostMappedPointer(context, address);
} }
else if (context.Memory.Type.IsHostTracked()) else if (context.Memory.Type.IsHostTracked)
{ {
if (address.Type == OperandType.I32) if (address.Type == OperandType.I32)
{ {

View File

@@ -2,7 +2,6 @@ using ARMeilleure.Decoders;
using ARMeilleure.IntermediateRepresentation; using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation; using ARMeilleure.Translation;
using System; using System;
using System.Diagnostics.CodeAnalysis;
using static ARMeilleure.Instructions.InstEmitHelper; using static ARMeilleure.Instructions.InstEmitHelper;
namespace ARMeilleure.Instructions namespace ARMeilleure.Instructions

View File

@@ -201,11 +201,7 @@ namespace ARMeilleure.Instructions
ExecutionContext context = GetContext(); ExecutionContext context = GetContext();
// If debugging, we'll handle interrupts outside context.CheckInterrupt();
if (!Optimizations.EnableDebugging)
{
context.CheckInterrupt();
}
Statistics.ResumeTimer(); Statistics.ResumeTimer();

View File

@@ -1,692 +0,0 @@
using ARMeilleure.State;
using System;
using System.Runtime.InteropServices;
namespace ARMeilleure.Instructions
{
static class SoftFallback
{
#region "ShrImm64"
[UnmanagedCallersOnly]
public static long SignedShrImm64(long value, long roundConst, int shift)
{
if (roundConst == 0L)
{
if (shift <= 63)
{
return value >> shift;
}
else /* if (shift == 64) */
{
if (value < 0L)
{
return -1L;
}
else /* if (value >= 0L) */
{
return 0L;
}
}
}
else /* if (roundConst == 1L << (shift - 1)) */
{
if (shift <= 63)
{
long add = value + roundConst;
if ((~value & (value ^ add)) < 0L)
{
return (long)((ulong)add >> shift);
}
else
{
return add >> shift;
}
}
else /* if (shift == 64) */
{
return 0L;
}
}
}
[UnmanagedCallersOnly]
public static ulong UnsignedShrImm64(ulong value, long roundConst, int shift)
{
if (roundConst == 0L)
{
if (shift <= 63)
{
return value >> shift;
}
else /* if (shift == 64) */
{
return 0UL;
}
}
else /* if (roundConst == 1L << (shift - 1)) */
{
ulong add = value + (ulong)roundConst;
if ((add < value) && (add < (ulong)roundConst))
{
if (shift <= 63)
{
return (add >> shift) | (0x8000000000000000UL >> (shift - 1));
}
else /* if (shift == 64) */
{
return 1UL;
}
}
else
{
if (shift <= 63)
{
return add >> shift;
}
else /* if (shift == 64) */
{
return 0UL;
}
}
}
}
#endregion
#region "Saturation"
[UnmanagedCallersOnly]
public static int SatF32ToS32(float value)
{
if (float.IsNaN(value))
{
return 0;
}
return value >= int.MaxValue ? int.MaxValue :
value <= int.MinValue ? int.MinValue : (int)value;
}
[UnmanagedCallersOnly]
public static long SatF32ToS64(float value)
{
if (float.IsNaN(value))
{
return 0;
}
return value >= long.MaxValue ? long.MaxValue :
value <= long.MinValue ? long.MinValue : (long)value;
}
[UnmanagedCallersOnly]
public static uint SatF32ToU32(float value)
{
if (float.IsNaN(value))
{
return 0;
}
return value >= uint.MaxValue ? uint.MaxValue :
value <= uint.MinValue ? uint.MinValue : (uint)value;
}
[UnmanagedCallersOnly]
public static ulong SatF32ToU64(float value)
{
if (float.IsNaN(value))
{
return 0;
}
return value >= ulong.MaxValue ? ulong.MaxValue :
value <= ulong.MinValue ? ulong.MinValue : (ulong)value;
}
[UnmanagedCallersOnly]
public static int SatF64ToS32(double value)
{
if (double.IsNaN(value))
{
return 0;
}
return value >= int.MaxValue ? int.MaxValue :
value <= int.MinValue ? int.MinValue : (int)value;
}
[UnmanagedCallersOnly]
public static long SatF64ToS64(double value)
{
if (double.IsNaN(value))
{
return 0;
}
return value >= long.MaxValue ? long.MaxValue :
value <= long.MinValue ? long.MinValue : (long)value;
}
[UnmanagedCallersOnly]
public static uint SatF64ToU32(double value)
{
if (double.IsNaN(value))
{
return 0;
}
return value >= uint.MaxValue ? uint.MaxValue :
value <= uint.MinValue ? uint.MinValue : (uint)value;
}
[UnmanagedCallersOnly]
public static ulong SatF64ToU64(double value)
{
if (double.IsNaN(value))
{
return 0;
}
return value >= ulong.MaxValue ? ulong.MaxValue :
value <= ulong.MinValue ? ulong.MinValue : (ulong)value;
}
#endregion
#region "Count"
[UnmanagedCallersOnly]
public static ulong CountLeadingSigns(ulong value, int size) // size is 8, 16, 32 or 64 (SIMD&FP or Base Inst.).
{
value ^= value >> 1;
int highBit = size - 2;
for (int bit = highBit; bit >= 0; bit--)
{
if (((int)(value >> bit) & 0b1) != 0)
{
return (ulong)(highBit - bit);
}
}
return (ulong)(size - 1);
}
private static ReadOnlySpan<byte> ClzNibbleTbl => [4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0];
[UnmanagedCallersOnly]
public static ulong CountLeadingZeros(ulong value, int size) // size is 8, 16, 32 or 64 (SIMD&FP or Base Inst.).
{
if (value == 0ul)
{
return (ulong)size;
}
int nibbleIdx = size;
int preCount, count = 0;
do
{
nibbleIdx -= 4;
preCount = ClzNibbleTbl[(int)(value >> nibbleIdx) & 0b1111];
count += preCount;
}
while (preCount == 4);
return (ulong)count;
}
#endregion
#region "Table"
[UnmanagedCallersOnly]
public static V128 Tbl1(V128 vector, int bytes, V128 tb0)
{
return TblOrTbx(default, vector, bytes, tb0);
}
[UnmanagedCallersOnly]
public static V128 Tbl2(V128 vector, int bytes, V128 tb0, V128 tb1)
{
return TblOrTbx(default, vector, bytes, tb0, tb1);
}
[UnmanagedCallersOnly]
public static V128 Tbl3(V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2)
{
return TblOrTbx(default, vector, bytes, tb0, tb1, tb2);
}
[UnmanagedCallersOnly]
public static V128 Tbl4(V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2, V128 tb3)
{
return TblOrTbx(default, vector, bytes, tb0, tb1, tb2, tb3);
}
[UnmanagedCallersOnly]
public static V128 Tbx1(V128 dest, V128 vector, int bytes, V128 tb0)
{
return TblOrTbx(dest, vector, bytes, tb0);
}
[UnmanagedCallersOnly]
public static V128 Tbx2(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1)
{
return TblOrTbx(dest, vector, bytes, tb0, tb1);
}
[UnmanagedCallersOnly]
public static V128 Tbx3(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2)
{
return TblOrTbx(dest, vector, bytes, tb0, tb1, tb2);
}
[UnmanagedCallersOnly]
public static V128 Tbx4(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2, V128 tb3)
{
return TblOrTbx(dest, vector, bytes, tb0, tb1, tb2, tb3);
}
private static V128 TblOrTbx(V128 dest, V128 vector, int bytes, params ReadOnlySpan<V128> tb)
{
byte[] res = new byte[16];
if (dest != default)
{
Buffer.BlockCopy(dest.ToArray(), 0, res, 0, bytes);
}
byte[] table = new byte[tb.Length * 16];
for (byte index = 0; index < tb.Length; index++)
{
Buffer.BlockCopy(tb[index].ToArray(), 0, table, index * 16, 16);
}
byte[] v = vector.ToArray();
for (byte index = 0; index < bytes; index++)
{
byte tblIndex = v[index];
if (tblIndex < table.Length)
{
res[index] = table[tblIndex];
}
}
return new V128(res);
}
#endregion
#region "Crc32"
private const uint Crc32RevPoly = 0xedb88320;
private const uint Crc32cRevPoly = 0x82f63b78;
[UnmanagedCallersOnly]
public static uint Crc32b(uint crc, byte value) => Crc32(crc, Crc32RevPoly, value);
[UnmanagedCallersOnly]
public static uint Crc32h(uint crc, ushort value) => Crc32h(crc, Crc32RevPoly, value);
[UnmanagedCallersOnly]
public static uint Crc32w(uint crc, uint value) => Crc32w(crc, Crc32RevPoly, value);
[UnmanagedCallersOnly]
public static uint Crc32x(uint crc, ulong value) => Crc32x(crc, Crc32RevPoly, value);
[UnmanagedCallersOnly]
public static uint Crc32cb(uint crc, byte value) => Crc32(crc, Crc32cRevPoly, value);
[UnmanagedCallersOnly]
public static uint Crc32ch(uint crc, ushort value) => Crc32h(crc, Crc32cRevPoly, value);
[UnmanagedCallersOnly]
public static uint Crc32cw(uint crc, uint value) => Crc32w(crc, Crc32cRevPoly, value);
[UnmanagedCallersOnly]
public static uint Crc32cx(uint crc, ulong value) => Crc32x(crc, Crc32cRevPoly, value);
private static uint Crc32h(uint crc, uint poly, ushort val)
{
crc = Crc32(crc, poly, (byte)(val >> 0));
crc = Crc32(crc, poly, (byte)(val >> 8));
return crc;
}
private static uint Crc32w(uint crc, uint poly, uint val)
{
crc = Crc32(crc, poly, (byte)(val >> 0));
crc = Crc32(crc, poly, (byte)(val >> 8));
crc = Crc32(crc, poly, (byte)(val >> 16));
crc = Crc32(crc, poly, (byte)(val >> 24));
return crc;
}
private static uint Crc32x(uint crc, uint poly, ulong val)
{
crc = Crc32(crc, poly, (byte)(val >> 0));
crc = Crc32(crc, poly, (byte)(val >> 8));
crc = Crc32(crc, poly, (byte)(val >> 16));
crc = Crc32(crc, poly, (byte)(val >> 24));
crc = Crc32(crc, poly, (byte)(val >> 32));
crc = Crc32(crc, poly, (byte)(val >> 40));
crc = Crc32(crc, poly, (byte)(val >> 48));
crc = Crc32(crc, poly, (byte)(val >> 56));
return crc;
}
private static uint Crc32(uint crc, uint poly, byte val)
{
crc ^= val;
for (int bit = 7; bit >= 0; bit--)
{
uint mask = (uint)(-(int)(crc & 1));
crc = (crc >> 1) ^ (poly & mask);
}
return crc;
}
#endregion
#region "Aes"
[UnmanagedCallersOnly]
public static V128 Decrypt(V128 value, V128 roundKey)
{
return CryptoHelper.AesInvSubBytes(CryptoHelper.AesInvShiftRows(value ^ roundKey));
}
[UnmanagedCallersOnly]
public static V128 Encrypt(V128 value, V128 roundKey)
{
return CryptoHelper.AesSubBytes(CryptoHelper.AesShiftRows(value ^ roundKey));
}
[UnmanagedCallersOnly]
public static V128 InverseMixColumns(V128 value)
{
return CryptoHelper.AesInvMixColumns(value);
}
[UnmanagedCallersOnly]
public static V128 MixColumns(V128 value)
{
return CryptoHelper.AesMixColumns(value);
}
#endregion
#region "Sha1"
[UnmanagedCallersOnly]
public static V128 HashChoose(V128 hash_abcd, uint hash_e, V128 wk)
{
for (int e = 0; e <= 3; e++)
{
uint t = ShaChoose(hash_abcd.Extract<uint>(1),
hash_abcd.Extract<uint>(2),
hash_abcd.Extract<uint>(3));
hash_e += Rol(hash_abcd.Extract<uint>(0), 5) + t + wk.Extract<uint>(e);
t = Rol(hash_abcd.Extract<uint>(1), 30);
hash_abcd.Insert(1, t);
Rol32_160(ref hash_e, ref hash_abcd);
}
return hash_abcd;
}
[UnmanagedCallersOnly]
public static uint FixedRotate(uint hash_e)
{
return hash_e.Rol(30);
}
[UnmanagedCallersOnly]
public static V128 HashMajority(V128 hash_abcd, uint hash_e, V128 wk)
{
for (int e = 0; e <= 3; e++)
{
uint t = ShaMajority(hash_abcd.Extract<uint>(1),
hash_abcd.Extract<uint>(2),
hash_abcd.Extract<uint>(3));
hash_e += Rol(hash_abcd.Extract<uint>(0), 5) + t + wk.Extract<uint>(e);
t = Rol(hash_abcd.Extract<uint>(1), 30);
hash_abcd.Insert(1, t);
Rol32_160(ref hash_e, ref hash_abcd);
}
return hash_abcd;
}
[UnmanagedCallersOnly]
public static V128 HashParity(V128 hash_abcd, uint hash_e, V128 wk)
{
for (int e = 0; e <= 3; e++)
{
uint t = ShaParity(hash_abcd.Extract<uint>(1),
hash_abcd.Extract<uint>(2),
hash_abcd.Extract<uint>(3));
hash_e += Rol(hash_abcd.Extract<uint>(0), 5) + t + wk.Extract<uint>(e);
t = Rol(hash_abcd.Extract<uint>(1), 30);
hash_abcd.Insert(1, t);
Rol32_160(ref hash_e, ref hash_abcd);
}
return hash_abcd;
}
[UnmanagedCallersOnly]
public static V128 Sha1SchedulePart1(V128 w0_3, V128 w4_7, V128 w8_11)
{
ulong t2 = w4_7.Extract<ulong>(0);
ulong t1 = w0_3.Extract<ulong>(1);
V128 result = new(t1, t2);
return result ^ (w0_3 ^ w8_11);
}
[UnmanagedCallersOnly]
public static V128 Sha1SchedulePart2(V128 tw0_3, V128 w12_15)
{
V128 t = tw0_3 ^ (w12_15 >> 32);
uint tE0 = t.Extract<uint>(0);
uint tE1 = t.Extract<uint>(1);
uint tE2 = t.Extract<uint>(2);
uint tE3 = t.Extract<uint>(3);
return new V128(tE0.Rol(1), tE1.Rol(1), tE2.Rol(1), tE3.Rol(1) ^ tE0.Rol(2));
}
private static void Rol32_160(ref uint y, ref V128 x)
{
uint xE3 = x.Extract<uint>(3);
x <<= 32;
x.Insert(0, y);
y = xE3;
}
private static uint ShaChoose(uint x, uint y, uint z)
{
return ((y ^ z) & x) ^ z;
}
private static uint ShaMajority(uint x, uint y, uint z)
{
return (x & y) | ((x | y) & z);
}
private static uint ShaParity(uint x, uint y, uint z)
{
return x ^ y ^ z;
}
private static uint Rol(this uint value, int count)
{
return (value << count) | (value >> (32 - count));
}
#endregion
#region "Sha256"
[UnmanagedCallersOnly]
public static V128 HashLower(V128 hash_abcd, V128 hash_efgh, V128 wk)
{
return Sha256Hash(hash_abcd, hash_efgh, wk, part1: true);
}
[UnmanagedCallersOnly]
public static V128 HashUpper(V128 hash_abcd, V128 hash_efgh, V128 wk)
{
return Sha256Hash(hash_abcd, hash_efgh, wk, part1: false);
}
[UnmanagedCallersOnly]
public static V128 Sha256SchedulePart1(V128 w0_3, V128 w4_7)
{
V128 result = new();
for (int e = 0; e <= 3; e++)
{
uint elt = (e <= 2 ? w0_3 : w4_7).Extract<uint>(e <= 2 ? e + 1 : 0);
elt = elt.Ror(7) ^ elt.Ror(18) ^ elt.Lsr(3);
elt += w0_3.Extract<uint>(e);
result.Insert(e, elt);
}
return result;
}
[UnmanagedCallersOnly]
public static V128 Sha256SchedulePart2(V128 w0_3, V128 w8_11, V128 w12_15)
{
V128 result = new();
ulong t1 = w12_15.Extract<ulong>(1);
for (int e = 0; e <= 1; e++)
{
uint elt = t1.ULongPart(e);
elt = elt.Ror(17) ^ elt.Ror(19) ^ elt.Lsr(10);
elt += w0_3.Extract<uint>(e) + w8_11.Extract<uint>(e + 1);
result.Insert(e, elt);
}
t1 = result.Extract<ulong>(0);
for (int e = 2; e <= 3; e++)
{
uint elt = t1.ULongPart(e - 2);
elt = elt.Ror(17) ^ elt.Ror(19) ^ elt.Lsr(10);
elt += w0_3.Extract<uint>(e) + (e == 2 ? w8_11 : w12_15).Extract<uint>(e == 2 ? 3 : 0);
result.Insert(e, elt);
}
return result;
}
private static V128 Sha256Hash(V128 x, V128 y, V128 w, bool part1)
{
for (int e = 0; e <= 3; e++)
{
uint chs = ShaChoose(y.Extract<uint>(0),
y.Extract<uint>(1),
y.Extract<uint>(2));
uint maj = ShaMajority(x.Extract<uint>(0),
x.Extract<uint>(1),
x.Extract<uint>(2));
uint t1 = y.Extract<uint>(3) + ShaHashSigma1(y.Extract<uint>(0)) + chs + w.Extract<uint>(e);
uint t2 = t1 + x.Extract<uint>(3);
x.Insert(3, t2);
t2 = t1 + ShaHashSigma0(x.Extract<uint>(0)) + maj;
y.Insert(3, t2);
Rol32_256(ref y, ref x);
}
return part1 ? x : y;
}
private static void Rol32_256(ref V128 y, ref V128 x)
{
uint yE3 = y.Extract<uint>(3);
uint xE3 = x.Extract<uint>(3);
y <<= 32;
x <<= 32;
y.Insert(0, xE3);
x.Insert(0, yE3);
}
private static uint ShaHashSigma0(uint x)
{
return x.Ror(2) ^ x.Ror(13) ^ x.Ror(22);
}
private static uint ShaHashSigma1(uint x)
{
return x.Ror(6) ^ x.Ror(11) ^ x.Ror(25);
}
private static uint Ror(this uint value, int count)
{
return (value >> count) | (value << (32 - count));
}
private static uint Lsr(this uint value, int count)
{
return value >> count;
}
private static uint ULongPart(this ulong value, int part)
{
return part == 0
? (uint)(value & 0xFFFFFFFFUL)
: (uint)(value >> 32);
}
#endregion
[UnmanagedCallersOnly]
public static V128 PolynomialMult64_128(ulong op1, ulong op2)
{
V128 result = V128.Zero;
V128 op2_128 = new(op2, 0);
for (int i = 0; i < 64; i++)
{
if (((op1 >> i) & 1) == 1)
{
result ^= op2_128 << i;
}
}
return result;
}
}
}

View File

@@ -0,0 +1,32 @@
using ARMeilleure.State;
using System.Runtime.InteropServices;
namespace ARMeilleure.Instructions
{
static partial class SoftFallback
{
[UnmanagedCallersOnly]
public static V128 Decrypt(V128 value, V128 roundKey)
{
return CryptoHelper.AesInvSubBytes(CryptoHelper.AesInvShiftRows(value ^ roundKey));
}
[UnmanagedCallersOnly]
public static V128 Encrypt(V128 value, V128 roundKey)
{
return CryptoHelper.AesSubBytes(CryptoHelper.AesShiftRows(value ^ roundKey));
}
[UnmanagedCallersOnly]
public static V128 InverseMixColumns(V128 value)
{
return CryptoHelper.AesInvMixColumns(value);
}
[UnmanagedCallersOnly]
public static V128 MixColumns(V128 value)
{
return CryptoHelper.AesMixColumns(value);
}
}
}

View File

@@ -0,0 +1,50 @@
using System;
using System.Runtime.InteropServices;
namespace ARMeilleure.Instructions
{
static partial class SoftFallback
{
[UnmanagedCallersOnly]
public static ulong CountLeadingSigns(ulong value, int size) // size is 8, 16, 32 or 64 (SIMD&FP or Base Inst.).
{
value ^= value >> 1;
int highBit = size - 2;
for (int bit = highBit; bit >= 0; bit--)
{
if (((int)(value >> bit) & 0b1) != 0)
{
return (ulong)(highBit - bit);
}
}
return (ulong)(size - 1);
}
private static ReadOnlySpan<byte> ClzNibbleTbl => [4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0];
[UnmanagedCallersOnly]
public static ulong CountLeadingZeros(ulong value, int size) // size is 8, 16, 32 or 64 (SIMD&FP or Base Inst.).
{
if (value == 0ul)
{
return (ulong)size;
}
int nibbleIdx = size;
int preCount, count = 0;
do
{
nibbleIdx -= 4;
preCount = ClzNibbleTbl[(int)(value >> nibbleIdx) & 0b1111];
count += preCount;
}
while (preCount == 4);
return (ulong)count;
}
}
}

View File

@@ -0,0 +1,74 @@
using System.Runtime.InteropServices;
namespace ARMeilleure.Instructions
{
static partial class SoftFallback
{
private const uint Crc32RevPoly = 0xedb88320;
private const uint Crc32cRevPoly = 0x82f63b78;
[UnmanagedCallersOnly]
public static uint Crc32b(uint crc, byte value) => Crc32(crc, Crc32RevPoly, value);
[UnmanagedCallersOnly]
public static uint Crc32h(uint crc, ushort value) => Crc32h(crc, Crc32RevPoly, value);
[UnmanagedCallersOnly]
public static uint Crc32w(uint crc, uint value) => Crc32w(crc, Crc32RevPoly, value);
[UnmanagedCallersOnly]
public static uint Crc32x(uint crc, ulong value) => Crc32x(crc, Crc32RevPoly, value);
[UnmanagedCallersOnly]
public static uint Crc32cb(uint crc, byte value) => Crc32(crc, Crc32cRevPoly, value);
[UnmanagedCallersOnly]
public static uint Crc32ch(uint crc, ushort value) => Crc32h(crc, Crc32cRevPoly, value);
[UnmanagedCallersOnly]
public static uint Crc32cw(uint crc, uint value) => Crc32w(crc, Crc32cRevPoly, value);
[UnmanagedCallersOnly]
public static uint Crc32cx(uint crc, ulong value) => Crc32x(crc, Crc32cRevPoly, value);
private static uint Crc32h(uint crc, uint poly, ushort val)
{
crc = Crc32(crc, poly, (byte)(val >> 0));
crc = Crc32(crc, poly, (byte)(val >> 8));
return crc;
}
private static uint Crc32w(uint crc, uint poly, uint val)
{
crc = Crc32(crc, poly, (byte)(val >> 0));
crc = Crc32(crc, poly, (byte)(val >> 8));
crc = Crc32(crc, poly, (byte)(val >> 16));
crc = Crc32(crc, poly, (byte)(val >> 24));
return crc;
}
private static uint Crc32x(uint crc, uint poly, ulong val)
{
crc = Crc32(crc, poly, (byte)(val >> 0));
crc = Crc32(crc, poly, (byte)(val >> 8));
crc = Crc32(crc, poly, (byte)(val >> 16));
crc = Crc32(crc, poly, (byte)(val >> 24));
crc = Crc32(crc, poly, (byte)(val >> 32));
crc = Crc32(crc, poly, (byte)(val >> 40));
crc = Crc32(crc, poly, (byte)(val >> 48));
crc = Crc32(crc, poly, (byte)(val >> 56));
return crc;
}
private static uint Crc32(uint crc, uint poly, byte val)
{
crc ^= val;
for (int bit = 7; bit >= 0; bit--)
{
uint mask = (uint)(-(int)(crc & 1));
crc = (crc >> 1) ^ (poly & mask);
}
return crc;
}
}
}

View File

@@ -0,0 +1,103 @@
using System.Runtime.InteropServices;
namespace ARMeilleure.Instructions
{
static partial class SoftFallback
{
[UnmanagedCallersOnly]
public static int SatF32ToS32(float value)
{
if (float.IsNaN(value))
{
return 0;
}
return value >= int.MaxValue ? int.MaxValue :
value <= int.MinValue ? int.MinValue : (int)value;
}
[UnmanagedCallersOnly]
public static long SatF32ToS64(float value)
{
if (float.IsNaN(value))
{
return 0;
}
return value >= long.MaxValue ? long.MaxValue :
value <= long.MinValue ? long.MinValue : (long)value;
}
[UnmanagedCallersOnly]
public static uint SatF32ToU32(float value)
{
if (float.IsNaN(value))
{
return 0;
}
return value >= uint.MaxValue ? uint.MaxValue :
value <= uint.MinValue ? uint.MinValue : (uint)value;
}
[UnmanagedCallersOnly]
public static ulong SatF32ToU64(float value)
{
if (float.IsNaN(value))
{
return 0;
}
return value >= ulong.MaxValue ? ulong.MaxValue :
value <= ulong.MinValue ? ulong.MinValue : (ulong)value;
}
[UnmanagedCallersOnly]
public static int SatF64ToS32(double value)
{
if (double.IsNaN(value))
{
return 0;
}
return value >= int.MaxValue ? int.MaxValue :
value <= int.MinValue ? int.MinValue : (int)value;
}
[UnmanagedCallersOnly]
public static long SatF64ToS64(double value)
{
if (double.IsNaN(value))
{
return 0;
}
return value >= long.MaxValue ? long.MaxValue :
value <= long.MinValue ? long.MinValue : (long)value;
}
[UnmanagedCallersOnly]
public static uint SatF64ToU32(double value)
{
if (double.IsNaN(value))
{
return 0;
}
return value >= uint.MaxValue ? uint.MaxValue :
value <= uint.MinValue ? uint.MinValue : (uint)value;
}
[UnmanagedCallersOnly]
public static ulong SatF64ToU64(double value)
{
if (double.IsNaN(value))
{
return 0;
}
return value >= ulong.MaxValue ? ulong.MaxValue :
value <= ulong.MinValue ? ulong.MinValue : (ulong)value;
}
}
}

View File

@@ -0,0 +1,131 @@
using ARMeilleure.State;
using System.Runtime.InteropServices;
namespace ARMeilleure.Instructions
{
static partial class SoftFallback
{
[UnmanagedCallersOnly]
public static V128 HashChoose(V128 hash_abcd, uint hash_e, V128 wk)
{
for (int e = 0; e <= 3; e++)
{
uint t = ShaChoose(hash_abcd.Extract<uint>(1),
hash_abcd.Extract<uint>(2),
hash_abcd.Extract<uint>(3));
hash_e += Rol(hash_abcd.Extract<uint>(0), 5) + t + wk.Extract<uint>(e);
t = Rol(hash_abcd.Extract<uint>(1), 30);
hash_abcd.Insert(1, t);
Rol32_160(ref hash_e, ref hash_abcd);
}
return hash_abcd;
}
[UnmanagedCallersOnly]
public static uint FixedRotate(uint hash_e)
{
return hash_e.Rol(30);
}
[UnmanagedCallersOnly]
public static V128 HashMajority(V128 hash_abcd, uint hash_e, V128 wk)
{
for (int e = 0; e <= 3; e++)
{
uint t = ShaMajority(hash_abcd.Extract<uint>(1),
hash_abcd.Extract<uint>(2),
hash_abcd.Extract<uint>(3));
hash_e += Rol(hash_abcd.Extract<uint>(0), 5) + t + wk.Extract<uint>(e);
t = Rol(hash_abcd.Extract<uint>(1), 30);
hash_abcd.Insert(1, t);
Rol32_160(ref hash_e, ref hash_abcd);
}
return hash_abcd;
}
[UnmanagedCallersOnly]
public static V128 HashParity(V128 hash_abcd, uint hash_e, V128 wk)
{
for (int e = 0; e <= 3; e++)
{
uint t = ShaParity(hash_abcd.Extract<uint>(1),
hash_abcd.Extract<uint>(2),
hash_abcd.Extract<uint>(3));
hash_e += Rol(hash_abcd.Extract<uint>(0), 5) + t + wk.Extract<uint>(e);
t = Rol(hash_abcd.Extract<uint>(1), 30);
hash_abcd.Insert(1, t);
Rol32_160(ref hash_e, ref hash_abcd);
}
return hash_abcd;
}
[UnmanagedCallersOnly]
public static V128 Sha1SchedulePart1(V128 w0_3, V128 w4_7, V128 w8_11)
{
ulong t2 = w4_7.Extract<ulong>(0);
ulong t1 = w0_3.Extract<ulong>(1);
V128 result = new(t1, t2);
return result ^ (w0_3 ^ w8_11);
}
[UnmanagedCallersOnly]
public static V128 Sha1SchedulePart2(V128 tw0_3, V128 w12_15)
{
V128 t = tw0_3 ^ (w12_15 >> 32);
uint tE0 = t.Extract<uint>(0);
uint tE1 = t.Extract<uint>(1);
uint tE2 = t.Extract<uint>(2);
uint tE3 = t.Extract<uint>(3);
return new V128(tE0.Rol(1), tE1.Rol(1), tE2.Rol(1), tE3.Rol(1) ^ tE0.Rol(2));
}
private static void Rol32_160(ref uint y, ref V128 x)
{
uint xE3 = x.Extract<uint>(3);
x <<= 32;
x.Insert(0, y);
y = xE3;
}
private static uint ShaChoose(uint x, uint y, uint z)
{
return ((y ^ z) & x) ^ z;
}
private static uint ShaMajority(uint x, uint y, uint z)
{
return (x & y) | ((x | y) & z);
}
private static uint ShaParity(uint x, uint y, uint z)
{
return x ^ y ^ z;
}
private static uint Rol(this uint value, int count)
{
return (value << count) | (value >> (32 - count));
}
}
}

View File

@@ -0,0 +1,140 @@
using ARMeilleure.State;
using System.Runtime.InteropServices;
namespace ARMeilleure.Instructions
{
static partial class SoftFallback
{
[UnmanagedCallersOnly]
public static V128 HashLower(V128 hash_abcd, V128 hash_efgh, V128 wk)
{
return Sha256Hash(hash_abcd, hash_efgh, wk, part1: true);
}
[UnmanagedCallersOnly]
public static V128 HashUpper(V128 hash_abcd, V128 hash_efgh, V128 wk)
{
return Sha256Hash(hash_abcd, hash_efgh, wk, part1: false);
}
[UnmanagedCallersOnly]
public static V128 Sha256SchedulePart1(V128 w0_3, V128 w4_7)
{
V128 result = new();
for (int e = 0; e <= 3; e++)
{
uint elt = (e <= 2 ? w0_3 : w4_7).Extract<uint>(e <= 2 ? e + 1 : 0);
elt = elt.Ror(7) ^ elt.Ror(18) ^ elt.Lsr(3);
elt += w0_3.Extract<uint>(e);
result.Insert(e, elt);
}
return result;
}
[UnmanagedCallersOnly]
public static V128 Sha256SchedulePart2(V128 w0_3, V128 w8_11, V128 w12_15)
{
V128 result = new();
ulong t1 = w12_15.Extract<ulong>(1);
for (int e = 0; e <= 1; e++)
{
uint elt = t1.ULongPart(e);
elt = elt.Ror(17) ^ elt.Ror(19) ^ elt.Lsr(10);
elt += w0_3.Extract<uint>(e) + w8_11.Extract<uint>(e + 1);
result.Insert(e, elt);
}
t1 = result.Extract<ulong>(0);
for (int e = 2; e <= 3; e++)
{
uint elt = t1.ULongPart(e - 2);
elt = elt.Ror(17) ^ elt.Ror(19) ^ elt.Lsr(10);
elt += w0_3.Extract<uint>(e) + (e == 2 ? w8_11 : w12_15).Extract<uint>(e == 2 ? 3 : 0);
result.Insert(e, elt);
}
return result;
}
private static V128 Sha256Hash(V128 x, V128 y, V128 w, bool part1)
{
for (int e = 0; e <= 3; e++)
{
uint chs = ShaChoose(y.Extract<uint>(0),
y.Extract<uint>(1),
y.Extract<uint>(2));
uint maj = ShaMajority(x.Extract<uint>(0),
x.Extract<uint>(1),
x.Extract<uint>(2));
uint t1 = y.Extract<uint>(3) + ShaHashSigma1(y.Extract<uint>(0)) + chs + w.Extract<uint>(e);
uint t2 = t1 + x.Extract<uint>(3);
x.Insert(3, t2);
t2 = t1 + ShaHashSigma0(x.Extract<uint>(0)) + maj;
y.Insert(3, t2);
Rol32_256(ref y, ref x);
}
return part1 ? x : y;
}
private static void Rol32_256(ref V128 y, ref V128 x)
{
uint yE3 = y.Extract<uint>(3);
uint xE3 = x.Extract<uint>(3);
y <<= 32;
x <<= 32;
y.Insert(0, xE3);
x.Insert(0, yE3);
}
private static uint ShaHashSigma0(uint x)
{
return x.Ror(2) ^ x.Ror(13) ^ x.Ror(22);
}
private static uint ShaHashSigma1(uint x)
{
return x.Ror(6) ^ x.Ror(11) ^ x.Ror(25);
}
private static uint Ror(this uint value, int count)
{
return (value >> count) | (value << (32 - count));
}
private static uint Lsr(this uint value, int count)
{
return value >> count;
}
private static uint ULongPart(this ulong value, int part)
{
return part == 0
? (uint)(value & 0xFFFFFFFFUL)
: (uint)(value >> 32);
}
}
}

View File

@@ -0,0 +1,93 @@
using System.Runtime.InteropServices;
namespace ARMeilleure.Instructions
{
static partial class SoftFallback
{
[UnmanagedCallersOnly]
public static long SignedShrImm64(long value, long roundConst, int shift)
{
if (roundConst == 0L)
{
if (shift <= 63)
{
return value >> shift;
}
else /* if (shift == 64) */
{
if (value < 0L)
{
return -1L;
}
else /* if (value >= 0L) */
{
return 0L;
}
}
}
else /* if (roundConst == 1L << (shift - 1)) */
{
if (shift <= 63)
{
long add = value + roundConst;
if ((~value & (value ^ add)) < 0L)
{
return (long)((ulong)add >> shift);
}
else
{
return add >> shift;
}
}
else /* if (shift == 64) */
{
return 0L;
}
}
}
[UnmanagedCallersOnly]
public static ulong UnsignedShrImm64(ulong value, long roundConst, int shift)
{
if (roundConst == 0L)
{
if (shift <= 63)
{
return value >> shift;
}
else /* if (shift == 64) */
{
return 0UL;
}
}
else /* if (roundConst == 1L << (shift - 1)) */
{
ulong add = value + (ulong)roundConst;
if ((add < value) && (add < (ulong)roundConst))
{
if (shift <= 63)
{
return (add >> shift) | (0x8000000000000000UL >> (shift - 1));
}
else /* if (shift == 64) */
{
return 1UL;
}
}
else
{
if (shift <= 63)
{
return add >> shift;
}
else /* if (shift == 64) */
{
return 0UL;
}
}
}
}
}
}

View File

@@ -0,0 +1,88 @@
using ARMeilleure.State;
using System;
using System.Runtime.InteropServices;
namespace ARMeilleure.Instructions
{
static partial class SoftFallback
{
[UnmanagedCallersOnly]
public static V128 Tbl1(V128 vector, int bytes, V128 tb0)
{
return TblOrTbx(default, vector, bytes, tb0);
}
[UnmanagedCallersOnly]
public static V128 Tbl2(V128 vector, int bytes, V128 tb0, V128 tb1)
{
return TblOrTbx(default, vector, bytes, tb0, tb1);
}
[UnmanagedCallersOnly]
public static V128 Tbl3(V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2)
{
return TblOrTbx(default, vector, bytes, tb0, tb1, tb2);
}
[UnmanagedCallersOnly]
public static V128 Tbl4(V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2, V128 tb3)
{
return TblOrTbx(default, vector, bytes, tb0, tb1, tb2, tb3);
}
[UnmanagedCallersOnly]
public static V128 Tbx1(V128 dest, V128 vector, int bytes, V128 tb0)
{
return TblOrTbx(dest, vector, bytes, tb0);
}
[UnmanagedCallersOnly]
public static V128 Tbx2(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1)
{
return TblOrTbx(dest, vector, bytes, tb0, tb1);
}
[UnmanagedCallersOnly]
public static V128 Tbx3(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2)
{
return TblOrTbx(dest, vector, bytes, tb0, tb1, tb2);
}
[UnmanagedCallersOnly]
public static V128 Tbx4(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2, V128 tb3)
{
return TblOrTbx(dest, vector, bytes, tb0, tb1, tb2, tb3);
}
private static V128 TblOrTbx(V128 dest, V128 vector, int bytes, params ReadOnlySpan<V128> tb)
{
byte[] res = new byte[16];
if (dest != default)
{
Buffer.BlockCopy(dest.ToArray(), 0, res, 0, bytes);
}
byte[] table = new byte[tb.Length * 16];
for (byte index = 0; index < tb.Length; index++)
{
Buffer.BlockCopy(tb[index].ToArray(), 0, table, index * 16, 16);
}
byte[] v = vector.ToArray();
for (byte index = 0; index < bytes; index++)
{
byte tblIndex = v[index];
if (tblIndex < table.Length)
{
res[index] = table[tblIndex];
}
}
return new V128(res);
}
}
}

View File

@@ -0,0 +1,26 @@
using ARMeilleure.State;
using System.Runtime.InteropServices;
namespace ARMeilleure.Instructions
{
static partial class SoftFallback
{
[UnmanagedCallersOnly]
public static V128 PolynomialMult64_128(ulong op1, ulong op2)
{
V128 result = V128.Zero;
V128 op2_128 = new(op2, 0);
for (int i = 0; i < 64; i++)
{
if (((op1 >> i) & 1) == 1)
{
result ^= op2_128 << i;
}
}
return result;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,111 @@
using ARMeilleure.State;
using System;
using System.Diagnostics;
namespace ARMeilleure.Instructions
{
static class SoftFloat
{
static SoftFloat()
{
RecipEstimateTable = BuildRecipEstimateTable();
RecipSqrtEstimateTable = BuildRecipSqrtEstimateTable();
}
public static readonly byte[] RecipEstimateTable;
public static readonly byte[] RecipSqrtEstimateTable;
private static byte[] BuildRecipEstimateTable()
{
byte[] tbl = new byte[256];
for (int idx = 0; idx < 256; idx++)
{
uint src = (uint)idx + 256u;
Debug.Assert(src is >= 256u and < 512u);
src = (src << 1) + 1u;
uint aux = (1u << 19) / src;
uint dst = (aux + 1u) >> 1;
Debug.Assert(dst is >= 256u and < 512u);
tbl[idx] = (byte)(dst - 256u);
}
return tbl;
}
private static byte[] BuildRecipSqrtEstimateTable()
{
byte[] tbl = new byte[384];
for (int idx = 0; idx < 384; idx++)
{
uint src = (uint)idx + 128u;
Debug.Assert(src is >= 128u and < 512u);
if (src < 256u)
{
src = (src << 1) + 1u;
}
else
{
src = (src >> 1) << 1;
src = (src + 1u) << 1;
}
uint aux = 512u;
while (src * (aux + 1u) * (aux + 1u) < (1u << 28))
{
aux++;
}
uint dst = (aux + 1u) >> 1;
Debug.Assert(dst is >= 256u and < 512u);
tbl[idx] = (byte)(dst - 256u);
}
return tbl;
}
public static void FPProcessException(FPException exc, ExecutionContext context)
{
FPProcessException(exc, context, context.Fpcr);
}
public static void FPProcessException(FPException exc, ExecutionContext context, FPCR fpcr)
{
int enable = (int)exc + 8;
if ((fpcr & (FPCR)(1 << enable)) != 0)
{
throw new NotImplementedException("Floating-point trap handling.");
}
else
{
context.Fpsr |= (FPSR)(1 << (int)exc);
}
}
extension(FPCR fpcr)
{
public FPRoundingMode RoundingMode
{
get
{
const int RModeShift = 22;
return (FPRoundingMode)(((uint)fpcr >> RModeShift) & 3u);
}
}
}
}
}

View File

@@ -0,0 +1,212 @@
using ARMeilleure.State;
using System;
namespace ARMeilleure.Instructions
{
static class SoftFloat16
{
public static ushort FPDefaultNaN()
{
return (ushort)0x7E00u;
}
public static ushort FPInfinity(bool sign)
{
return sign ? (ushort)0xFC00u : (ushort)0x7C00u;
}
public static ushort FPZero(bool sign)
{
return sign ? (ushort)0x8000u : (ushort)0x0000u;
}
public static ushort FPMaxNormal(bool sign)
{
return sign ? (ushort)0xFBFFu : (ushort)0x7BFFu;
}
public static double FPUnpackCv(
this ushort valueBits,
out FPType type,
out bool sign,
ExecutionContext context)
{
sign = (~(uint)valueBits & 0x8000u) == 0u;
uint exp16 = ((uint)valueBits & 0x7C00u) >> 10;
uint frac16 = (uint)valueBits & 0x03FFu;
double real;
if (exp16 == 0u)
{
if (frac16 == 0u)
{
type = FPType.Zero;
real = 0d;
}
else
{
type = FPType.Nonzero; // Subnormal.
real = Math.Pow(2d, -14) * ((double)frac16 * Math.Pow(2d, -10));
}
}
else if (exp16 == 0x1Fu && (context.Fpcr & FPCR.Ahp) == 0)
{
if (frac16 == 0u)
{
type = FPType.Infinity;
real = Math.Pow(2d, 1000);
}
else
{
type = (~frac16 & 0x0200u) == 0u ? FPType.QNaN : FPType.SNaN;
real = 0d;
}
}
else
{
type = FPType.Nonzero; // Normal.
real = Math.Pow(2d, (int)exp16 - 15) * (1d + (double)frac16 * Math.Pow(2d, -10));
}
return sign ? -real : real;
}
public static ushort FPRoundCv(double real, ExecutionContext context)
{
const int MinimumExp = -14;
const int E = 5;
const int F = 10;
bool sign;
double mantissa;
if (real < 0d)
{
sign = true;
mantissa = -real;
}
else
{
sign = false;
mantissa = real;
}
int exponent = 0;
while (mantissa < 1d)
{
mantissa *= 2d;
exponent--;
}
while (mantissa >= 2d)
{
mantissa /= 2d;
exponent++;
}
uint biasedExp = (uint)Math.Max(exponent - MinimumExp + 1, 0);
if (biasedExp == 0u)
{
mantissa /= Math.Pow(2d, MinimumExp - exponent);
}
uint intMant = (uint)Math.Floor(mantissa * Math.Pow(2d, F));
double error = mantissa * Math.Pow(2d, F) - (double)intMant;
if (biasedExp == 0u && (error != 0d || (context.Fpcr & FPCR.Ufe) != 0))
{
SoftFloat.FPProcessException(FPException.Underflow, context);
}
bool overflowToInf;
bool roundUp;
switch (context.Fpcr.RoundingMode)
{
case FPRoundingMode.ToNearest:
roundUp = (error > 0.5d || (error == 0.5d && (intMant & 1u) == 1u));
overflowToInf = true;
break;
case FPRoundingMode.TowardsPlusInfinity:
roundUp = (error != 0d && !sign);
overflowToInf = !sign;
break;
case FPRoundingMode.TowardsMinusInfinity:
roundUp = (error != 0d && sign);
overflowToInf = sign;
break;
case FPRoundingMode.TowardsZero:
roundUp = false;
overflowToInf = false;
break;
default:
throw new ArgumentException($"Invalid rounding mode \"{context.Fpcr.RoundingMode}\".");
}
if (roundUp)
{
intMant++;
if (intMant == 1u << F)
{
biasedExp = 1u;
}
if (intMant == 1u << (F + 1))
{
biasedExp++;
intMant >>= 1;
}
}
ushort resultBits;
if ((context.Fpcr & FPCR.Ahp) == 0)
{
if (biasedExp >= (1u << E) - 1u)
{
resultBits = overflowToInf ? FPInfinity(sign) : FPMaxNormal(sign);
SoftFloat.FPProcessException(FPException.Overflow, context);
error = 1d;
}
else
{
resultBits = (ushort)((sign ? 1u : 0u) << 15 | (biasedExp & 0x1Fu) << 10 | (intMant & 0x03FFu));
}
}
else
{
if (biasedExp >= 1u << E)
{
resultBits = (ushort)((sign ? 1u : 0u) << 15 | 0x7FFFu);
SoftFloat.FPProcessException(FPException.InvalidOp, context);
error = 0d;
}
else
{
resultBits = (ushort)((sign ? 1u : 0u) << 15 | (biasedExp & 0x1Fu) << 10 | (intMant & 0x03FFu));
}
}
if (error != 0d)
{
SoftFloat.FPProcessException(FPException.Inexact, context);
}
return resultBits;
}
}
}

View File

@@ -0,0 +1,182 @@
using ARMeilleure.State;
using System;
using System.Runtime.InteropServices;
namespace ARMeilleure.Instructions
{
static class SoftFloat16_32
{
[UnmanagedCallersOnly]
public static float FPConvert(ushort valueBits)
{
ExecutionContext context = NativeInterface.GetContext();
double real = valueBits.FPUnpackCv(out FPType type, out bool sign, context);
float result;
if (type is FPType.SNaN or FPType.QNaN)
{
if ((context.Fpcr & FPCR.Dn) != 0)
{
result = SoftFloat32.FPDefaultNaN();
}
else
{
result = FPConvertNaN(valueBits);
}
if (type == FPType.SNaN)
{
SoftFloat.FPProcessException(FPException.InvalidOp, context);
}
}
else if (type == FPType.Infinity)
{
result = SoftFloat32.FPInfinity(sign);
}
else if (type == FPType.Zero)
{
result = SoftFloat32.FPZero(sign);
}
else
{
result = FPRoundCv(real, context);
}
return result;
}
private static float FPRoundCv(double real, ExecutionContext context)
{
const int MinimumExp = -126;
const int E = 8;
const int F = 23;
bool sign;
double mantissa;
if (real < 0d)
{
sign = true;
mantissa = -real;
}
else
{
sign = false;
mantissa = real;
}
int exponent = 0;
while (mantissa < 1d)
{
mantissa *= 2d;
exponent--;
}
while (mantissa >= 2d)
{
mantissa /= 2d;
exponent++;
}
if ((context.Fpcr & FPCR.Fz) != 0 && exponent < MinimumExp)
{
context.Fpsr |= FPSR.Ufc;
return SoftFloat32.FPZero(sign);
}
uint biasedExp = (uint)Math.Max(exponent - MinimumExp + 1, 0);
if (biasedExp == 0u)
{
mantissa /= Math.Pow(2d, MinimumExp - exponent);
}
uint intMant = (uint)Math.Floor(mantissa * Math.Pow(2d, F));
double error = mantissa * Math.Pow(2d, F) - (double)intMant;
if (biasedExp == 0u && (error != 0d || (context.Fpcr & FPCR.Ufe) != 0))
{
SoftFloat.FPProcessException(FPException.Underflow, context);
}
bool overflowToInf;
bool roundUp;
switch (context.Fpcr.RoundingMode)
{
case FPRoundingMode.ToNearest:
roundUp = (error > 0.5d || (error == 0.5d && (intMant & 1u) == 1u));
overflowToInf = true;
break;
case FPRoundingMode.TowardsPlusInfinity:
roundUp = (error != 0d && !sign);
overflowToInf = !sign;
break;
case FPRoundingMode.TowardsMinusInfinity:
roundUp = (error != 0d && sign);
overflowToInf = sign;
break;
case FPRoundingMode.TowardsZero:
roundUp = false;
overflowToInf = false;
break;
default:
throw new ArgumentException($"Invalid rounding mode \"{context.Fpcr.RoundingMode}\".");
}
if (roundUp)
{
intMant++;
if (intMant == 1u << F)
{
biasedExp = 1u;
}
if (intMant == 1u << (F + 1))
{
biasedExp++;
intMant >>= 1;
}
}
float result;
if (biasedExp >= (1u << E) - 1u)
{
result = overflowToInf ? SoftFloat32.FPInfinity(sign) : SoftFloat32.FPMaxNormal(sign);
SoftFloat.FPProcessException(FPException.Overflow, context);
error = 1d;
}
else
{
result = BitConverter.Int32BitsToSingle(
(int)((sign ? 1u : 0u) << 31 | (biasedExp & 0xFFu) << 23 | (intMant & 0x007FFFFFu)));
}
if (error != 0d)
{
SoftFloat.FPProcessException(FPException.Inexact, context);
}
return result;
}
private static float FPConvertNaN(ushort valueBits)
{
return BitConverter.Int32BitsToSingle(
(int)(((uint)valueBits & 0x8000u) << 16 | 0x7FC00000u | ((uint)valueBits & 0x01FFu) << 13));
}
}
}

View File

@@ -0,0 +1,182 @@
using ARMeilleure.State;
using System;
using System.Runtime.InteropServices;
namespace ARMeilleure.Instructions
{
static class SoftFloat16_64
{
[UnmanagedCallersOnly]
public static double FPConvert(ushort valueBits)
{
ExecutionContext context = NativeInterface.GetContext();
double real = valueBits.FPUnpackCv(out FPType type, out bool sign, context);
double result;
if (type is FPType.SNaN or FPType.QNaN)
{
if ((context.Fpcr & FPCR.Dn) != 0)
{
result = SoftFloat64.FPDefaultNaN();
}
else
{
result = FPConvertNaN(valueBits);
}
if (type == FPType.SNaN)
{
SoftFloat.FPProcessException(FPException.InvalidOp, context);
}
}
else if (type == FPType.Infinity)
{
result = SoftFloat64.FPInfinity(sign);
}
else if (type == FPType.Zero)
{
result = SoftFloat64.FPZero(sign);
}
else
{
result = FPRoundCv(real, context);
}
return result;
}
private static double FPRoundCv(double real, ExecutionContext context)
{
const int MinimumExp = -1022;
const int E = 11;
const int F = 52;
bool sign;
double mantissa;
if (real < 0d)
{
sign = true;
mantissa = -real;
}
else
{
sign = false;
mantissa = real;
}
int exponent = 0;
while (mantissa < 1d)
{
mantissa *= 2d;
exponent--;
}
while (mantissa >= 2d)
{
mantissa /= 2d;
exponent++;
}
if ((context.Fpcr & FPCR.Fz) != 0 && exponent < MinimumExp)
{
context.Fpsr |= FPSR.Ufc;
return SoftFloat64.FPZero(sign);
}
uint biasedExp = (uint)Math.Max(exponent - MinimumExp + 1, 0);
if (biasedExp == 0u)
{
mantissa /= Math.Pow(2d, MinimumExp - exponent);
}
ulong intMant = (ulong)Math.Floor(mantissa * Math.Pow(2d, F));
double error = mantissa * Math.Pow(2d, F) - (double)intMant;
if (biasedExp == 0u && (error != 0d || (context.Fpcr & FPCR.Ufe) != 0))
{
SoftFloat.FPProcessException(FPException.Underflow, context);
}
bool overflowToInf;
bool roundUp;
switch (context.Fpcr.RoundingMode)
{
case FPRoundingMode.ToNearest:
roundUp = (error > 0.5d || (error == 0.5d && (intMant & 1u) == 1u));
overflowToInf = true;
break;
case FPRoundingMode.TowardsPlusInfinity:
roundUp = (error != 0d && !sign);
overflowToInf = !sign;
break;
case FPRoundingMode.TowardsMinusInfinity:
roundUp = (error != 0d && sign);
overflowToInf = sign;
break;
case FPRoundingMode.TowardsZero:
roundUp = false;
overflowToInf = false;
break;
default:
throw new ArgumentException($"Invalid rounding mode \"{context.Fpcr.RoundingMode}\".");
}
if (roundUp)
{
intMant++;
if (intMant == 1ul << F)
{
biasedExp = 1u;
}
if (intMant == 1ul << (F + 1))
{
biasedExp++;
intMant >>= 1;
}
}
double result;
if (biasedExp >= (1u << E) - 1u)
{
result = overflowToInf ? SoftFloat64.FPInfinity(sign) : SoftFloat64.FPMaxNormal(sign);
SoftFloat.FPProcessException(FPException.Overflow, context);
error = 1d;
}
else
{
result = BitConverter.Int64BitsToDouble(
(long)((sign ? 1ul : 0ul) << 63 | (biasedExp & 0x7FFul) << 52 | (intMant & 0x000FFFFFFFFFFFFFul)));
}
if (error != 0d)
{
SoftFloat.FPProcessException(FPException.Inexact, context);
}
return result;
}
private static double FPConvertNaN(ushort valueBits)
{
return BitConverter.Int64BitsToDouble(
(long)(((ulong)valueBits & 0x8000ul) << 48 | 0x7FF8000000000000ul | ((ulong)valueBits & 0x01FFul) << 42));
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,126 @@
using ARMeilleure.State;
using System;
using System.Runtime.InteropServices;
namespace ARMeilleure.Instructions
{
static class SoftFloat32_16
{
[UnmanagedCallersOnly]
public static ushort FPConvert(float value)
{
ExecutionContext context = NativeInterface.GetContext();
double real = value.FPUnpackCv(out FPType type, out bool sign, out uint valueBits, context);
bool altHp = (context.Fpcr & FPCR.Ahp) != 0;
ushort resultBits;
if (type is FPType.SNaN or FPType.QNaN)
{
if (altHp)
{
resultBits = SoftFloat16.FPZero(sign);
}
else if ((context.Fpcr & FPCR.Dn) != 0)
{
resultBits = SoftFloat16.FPDefaultNaN();
}
else
{
resultBits = FPConvertNaN(valueBits);
}
if (type == FPType.SNaN || altHp)
{
SoftFloat.FPProcessException(FPException.InvalidOp, context);
}
}
else if (type == FPType.Infinity)
{
if (altHp)
{
resultBits = (ushort)((sign ? 1u : 0u) << 15 | 0x7FFFu);
SoftFloat.FPProcessException(FPException.InvalidOp, context);
}
else
{
resultBits = SoftFloat16.FPInfinity(sign);
}
}
else if (type == FPType.Zero)
{
resultBits = SoftFloat16.FPZero(sign);
}
else
{
resultBits = SoftFloat16.FPRoundCv(real, context);
}
return resultBits;
}
private static double FPUnpackCv(
this float value,
out FPType type,
out bool sign,
out uint valueBits,
ExecutionContext context)
{
valueBits = (uint)BitConverter.SingleToInt32Bits(value);
sign = (~valueBits & 0x80000000u) == 0u;
uint exp32 = (valueBits & 0x7F800000u) >> 23;
uint frac32 = valueBits & 0x007FFFFFu;
double real;
if (exp32 == 0u)
{
if (frac32 == 0u || (context.Fpcr & FPCR.Fz) != 0)
{
type = FPType.Zero;
real = 0d;
if (frac32 != 0u)
{
SoftFloat.FPProcessException(FPException.InputDenorm, context);
}
}
else
{
type = FPType.Nonzero; // Subnormal.
real = Math.Pow(2d, -126) * ((double)frac32 * Math.Pow(2d, -23));
}
}
else if (exp32 == 0xFFu)
{
if (frac32 == 0u)
{
type = FPType.Infinity;
real = Math.Pow(2d, 1000);
}
else
{
type = (~frac32 & 0x00400000u) == 0u ? FPType.QNaN : FPType.SNaN;
real = 0d;
}
}
else
{
type = FPType.Nonzero; // Normal.
real = Math.Pow(2d, (int)exp32 - 127) * (1d + (double)frac32 * Math.Pow(2d, -23));
}
return sign ? -real : real;
}
private static ushort FPConvertNaN(uint valueBits)
{
return (ushort)((valueBits & 0x80000000u) >> 16 | 0x7E00u | (valueBits & 0x003FE000u) >> 13);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,127 @@
using ARMeilleure.State;
using System;
using System.Runtime.InteropServices;
namespace ARMeilleure.Instructions
{
static class SoftFloat64_16
{
[UnmanagedCallersOnly]
public static ushort FPConvert(double value)
{
ExecutionContext context = NativeInterface.GetContext();
double real = value.FPUnpackCv(out FPType type, out bool sign, out ulong valueBits, context);
bool altHp = (context.Fpcr & FPCR.Ahp) != 0;
ushort resultBits;
if (type is FPType.SNaN or FPType.QNaN)
{
if (altHp)
{
resultBits = SoftFloat16.FPZero(sign);
}
else if ((context.Fpcr & FPCR.Dn) != 0)
{
resultBits = SoftFloat16.FPDefaultNaN();
}
else
{
resultBits = FPConvertNaN(valueBits);
}
if (type == FPType.SNaN || altHp)
{
SoftFloat.FPProcessException(FPException.InvalidOp, context);
}
}
else if (type == FPType.Infinity)
{
if (altHp)
{
resultBits = (ushort)((sign ? 1u : 0u) << 15 | 0x7FFFu);
SoftFloat.FPProcessException(FPException.InvalidOp, context);
}
else
{
resultBits = SoftFloat16.FPInfinity(sign);
}
}
else if (type == FPType.Zero)
{
resultBits = SoftFloat16.FPZero(sign);
}
else
{
resultBits = SoftFloat16.FPRoundCv(real, context);
}
return resultBits;
}
private static double FPUnpackCv(
this double value,
out FPType type,
out bool sign,
out ulong valueBits,
ExecutionContext context)
{
valueBits = (ulong)BitConverter.DoubleToInt64Bits(value);
sign = (~valueBits & 0x8000000000000000ul) == 0u;
ulong exp64 = (valueBits & 0x7FF0000000000000ul) >> 52;
ulong frac64 = valueBits & 0x000FFFFFFFFFFFFFul;
double real;
if (exp64 == 0u)
{
if (frac64 == 0u || (context.Fpcr & FPCR.Fz) != 0)
{
type = FPType.Zero;
real = 0d;
if (frac64 != 0u)
{
SoftFloat.FPProcessException(FPException.InputDenorm, context);
}
}
else
{
type = FPType.Nonzero; // Subnormal.
real = Math.Pow(2d, -1022) * ((double)frac64 * Math.Pow(2d, -52));
}
}
else if (exp64 == 0x7FFul)
{
if (frac64 == 0u)
{
type = FPType.Infinity;
real = Math.Pow(2d, 1000000);
}
else
{
type = (~frac64 & 0x0008000000000000ul) == 0u ? FPType.QNaN : FPType.SNaN;
real = 0d;
}
}
else
{
type = FPType.Nonzero; // Normal.
real = Math.Pow(2d, (int)exp64 - 1023) * (1d + (double)frac64 * Math.Pow(2d, -52));
}
return sign ? -real : real;
}
private static ushort FPConvertNaN(ulong valueBits)
{
return (ushort)((valueBits & 0x8000000000000000ul) >> 48 | 0x7E00u |
(valueBits & 0x0007FC0000000000ul) >> 42);
}
}
}

View File

@@ -16,9 +16,9 @@ namespace ARMeilleure.IntermediateRepresentation
static class ComparisonExtensions static class ComparisonExtensions
{ {
public static Comparison Invert(this Comparison comp) extension(Comparison comparison)
{ {
return (Comparison)((int)comp ^ 1); public Comparison Inverse => (Comparison)((int)comparison ^ 1);
} }
} }
} }

View File

@@ -1,5 +1,4 @@
using System; using System;
using System.Diagnostics.CodeAnalysis;
namespace ARMeilleure.IntermediateRepresentation namespace ARMeilleure.IntermediateRepresentation
{ {

View File

@@ -14,48 +14,38 @@ namespace ARMeilleure.IntermediateRepresentation
static class OperandTypeExtensions static class OperandTypeExtensions
{ {
public static bool IsInteger(this OperandType type) extension(OperandType type)
{ {
return type is OperandType.I32 or public bool IsInteger => type is OperandType.I32 or OperandType.I64;
OperandType.I64;
} public RegisterType Register => type switch
public static RegisterType ToRegisterType(this OperandType type)
{
return type switch
{ {
OperandType.FP32 => RegisterType.Vector, OperandType.FP32 => RegisterType.Vector,
OperandType.FP64 => RegisterType.Vector, OperandType.FP64 => RegisterType.Vector,
OperandType.I32 => RegisterType.Integer, OperandType.I32 => RegisterType.Integer,
OperandType.I64 => RegisterType.Integer, OperandType.I64 => RegisterType.Integer,
OperandType.V128 => RegisterType.Vector, OperandType.V128 => RegisterType.Vector,
_ => throw new InvalidOperationException($"Invalid operand type \"{type}\"."), _ => throw new InvalidOperationException($"Invalid operand type \"{type}\".")
}; };
}
public int ByteSize => type switch
public static int GetSizeInBytes(this OperandType type)
{
return type switch
{ {
OperandType.FP32 => 4, OperandType.FP32 => 4,
OperandType.FP64 => 8, OperandType.FP64 => 8,
OperandType.I32 => 4, OperandType.I32 => 4,
OperandType.I64 => 8, OperandType.I64 => 8,
OperandType.V128 => 16, OperandType.V128 => 16,
_ => throw new InvalidOperationException($"Invalid operand type \"{type}\"."), _ => throw new InvalidOperationException($"Invalid operand type \"{type}\".")
}; };
}
public int ByteSizeLog2 => type switch
public static int GetSizeInBytesLog2(this OperandType type)
{
return type switch
{ {
OperandType.FP32 => 2, OperandType.FP32 => 2,
OperandType.FP64 => 3, OperandType.FP64 => 3,
OperandType.I32 => 2, OperandType.I32 => 2,
OperandType.I64 => 3, OperandType.I64 => 3,
OperandType.V128 => 4, OperandType.V128 => 4,
_ => throw new InvalidOperationException($"Invalid operand type \"{type}\"."), _ => throw new InvalidOperationException($"Invalid operand type \"{type}\".")
}; };
} }
} }

View File

@@ -45,19 +45,12 @@ namespace ARMeilleure.Memory
public static class MemoryManagerTypeExtensions public static class MemoryManagerTypeExtensions
{ {
public static bool IsHostMapped(this MemoryManagerType type) extension(MemoryManagerType type)
{ {
return type is MemoryManagerType.HostMapped or MemoryManagerType.HostMappedUnsafe; public bool IsHostMapped => type is MemoryManagerType.HostMapped or MemoryManagerType.HostMappedUnsafe;
} public bool IsHostTracked => type is MemoryManagerType.HostTracked or MemoryManagerType.HostTrackedUnsafe;
public static bool IsHostTracked(this MemoryManagerType type) public bool IsHostMappedOrTracked => type.IsHostMapped || type.IsHostTracked;
{
return type is MemoryManagerType.HostTracked or MemoryManagerType.HostTrackedUnsafe;
}
public static bool IsHostMappedOrTracked(this MemoryManagerType type)
{
return type.IsHostMapped() || type.IsHostTracked();
} }
} }
} }

View File

@@ -412,7 +412,7 @@ namespace ARMeilleure.Translation
{ {
context.SyncQcFlag(); context.SyncQcFlag();
if (block.Branch != null && !block.Branch.Exit && block.Branch.Address <= block.Address) if (block.Branch is { Exit: false } && block.Branch.Address <= block.Address)
{ {
EmitSynchronization(context); EmitSynchronization(context);
} }
@@ -429,14 +429,14 @@ namespace ARMeilleure.Translation
{ {
lblPredicateSkip = Label(); lblPredicateSkip = Label();
InstEmitFlowHelper.EmitCondBranch(context, lblPredicateSkip, context.CurrentIfThenBlockCond.Invert()); InstEmitFlowHelper.EmitCondBranch(context, lblPredicateSkip, context.CurrentIfThenBlockCond.Inverse);
} }
if (opCode is OpCode32 op && op.Cond < Condition.Al) if (opCode is OpCode32 { Cond: < Condition.Al } op)
{ {
lblPredicateSkip = Label(); lblPredicateSkip = Label();
InstEmitFlowHelper.EmitCondBranch(context, lblPredicateSkip, op.Cond.Invert()); InstEmitFlowHelper.EmitCondBranch(context, lblPredicateSkip, op.Cond.Inverse);
} }
if (opCode.Instruction.Emitter != null) if (opCode.Instruction.Emitter != null)

View File

@@ -7,7 +7,7 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Ryujinx.Audio\Ryujinx.Audio.csproj" /> <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> </ItemGroup>
</Project> </Project>

View File

@@ -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 DriverIdentifier;
public readonly ulong SampleCount; public readonly ulong SampleCount;
public ulong SamplePlayed; public ulong SamplePlayed;
public SDL2AudioBuffer(ulong driverIdentifier, ulong sampleCount) public SDL3AudioBuffer(ulong driverIdentifier, ulong sampleCount)
{ {
DriverIdentifier = driverIdentifier; DriverIdentifier = driverIdentifier;
SampleCount = sampleCount; SampleCount = sampleCount;

View File

@@ -2,42 +2,41 @@ using Ryujinx.Audio.Common;
using Ryujinx.Audio.Integration; using Ryujinx.Audio.Integration;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Memory; using Ryujinx.Memory;
using Ryujinx.SDL2.Common; using Ryujinx.SDL3.Common;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Runtime.InteropServices;
using System.Threading; using System.Threading;
using static Ryujinx.Audio.Integration.IHardwareDeviceDriver; using static Ryujinx.Audio.Integration.IHardwareDeviceDriver;
using static SDL2.SDL; using SDL;
using static SDL.SDL3;
using System.Runtime.InteropServices;
namespace Ryujinx.Audio.Backends.SDL2
namespace Ryujinx.Audio.Backends.SDL3
{ {
public class SDL2HardwareDeviceDriver : IHardwareDeviceDriver
using unsafe SDL_AudioStreamCallbackPointer = delegate* unmanaged[Cdecl]<nint, SDL_AudioStream*, int, int, void>;
public class SDL3HardwareDeviceDriver : IHardwareDeviceDriver
{ {
private readonly ManualResetEvent _updateRequiredEvent; private readonly ManualResetEvent _updateRequiredEvent;
private readonly ManualResetEvent _pauseEvent; private readonly ManualResetEvent _pauseEvent;
private readonly ConcurrentDictionary<SDL2HardwareDeviceSession, byte> _sessions; private readonly ConcurrentDictionary<SDL3HardwareDeviceSession, byte> _sessions;
private readonly bool _supportSurroundConfiguration; private readonly bool _supportSurroundConfiguration;
public float Volume { get; set; } public float Volume { get; set; }
// TODO: Add this to SDL2-CS public unsafe SDL3HardwareDeviceDriver()
// NOTE: We use a DllImport here because of marshaling issue for spec.
[DllImport("SDL2")]
private static extern int SDL_GetDefaultAudioInfo(nint name, out SDL_AudioSpec spec, int isCapture);
public SDL2HardwareDeviceDriver()
{ {
_updateRequiredEvent = new ManualResetEvent(false); _updateRequiredEvent = new ManualResetEvent(false);
_pauseEvent = new ManualResetEvent(true); _pauseEvent = new ManualResetEvent(true);
_sessions = new ConcurrentDictionary<SDL2HardwareDeviceSession, byte>(); _sessions = new ConcurrentDictionary<SDL3HardwareDeviceSession, byte>();
SDL2Driver.Instance.Initialize(); SDL3Driver.Instance.Initialize();
int res = SDL_GetDefaultAudioInfo(nint.Zero, out SDL_AudioSpec spec, 0); SDL_AudioSpec spec;
if (!SDL_GetAudioDeviceFormat(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &spec, null))
if (res != 0)
{ {
Logger.Error?.Print(LogClass.Application, Logger.Error?.Print(LogClass.Application,
$"SDL_GetDefaultAudioInfo failed with error \"{SDL_GetError()}\""); $"SDL_GetDefaultAudioInfo failed with error \"{SDL_GetError()}\"");
@@ -54,16 +53,16 @@ namespace Ryujinx.Audio.Backends.SDL2
public static bool IsSupported => IsSupportedInternal(); public static bool IsSupported => IsSupportedInternal();
private static bool IsSupportedInternal() private unsafe static bool IsSupportedInternal()
{ {
uint device = OpenStream(SampleFormat.PcmInt16, Constants.TargetSampleRate, Constants.ChannelCountMax, Constants.TargetSampleCount, null); SDL_AudioStream* device = OpenStream(SampleFormat.PcmInt16, Constants.TargetSampleRate, Constants.ChannelCountMax, Constants.TargetSampleCount, null);
if (device != 0) if (device != null)
{ {
SDL_CloseAudioDevice(device); SDL_DestroyAudioStream(device);
} }
return device != 0; return device != null;
} }
public ManualResetEvent GetUpdateRequiredEvent() public ManualResetEvent GetUpdateRequiredEvent()
@@ -90,67 +89,68 @@ namespace Ryujinx.Audio.Backends.SDL2
if (direction != Direction.Output) if (direction != Direction.Output)
{ {
throw new NotImplementedException("Input direction is currently not implemented on SDL2 backend!"); throw new NotImplementedException("Input direction is currently not implemented on SDL3 backend!");
} }
SDL2HardwareDeviceSession session = new(this, memoryManager, sampleFormat, sampleRate, channelCount); SDL3HardwareDeviceSession session = new(this, memoryManager, sampleFormat, sampleRate, channelCount);
_sessions.TryAdd(session, 0); _sessions.TryAdd(session, 0);
return session; return session;
} }
internal bool Unregister(SDL2HardwareDeviceSession session) internal bool Unregister(SDL3HardwareDeviceSession session)
{ {
return _sessions.TryRemove(session, out _); return _sessions.TryRemove(session, out _);
} }
private static SDL_AudioSpec GetSDL2Spec(SampleFormat requestedSampleFormat, uint requestedSampleRate, uint requestedChannelCount, uint sampleCount) private static SDL_AudioSpec GetSDL3Spec(SampleFormat requestedSampleFormat, uint requestedSampleRate, uint requestedChannelCount)
{ {
return new SDL_AudioSpec return new SDL_AudioSpec
{ {
channels = (byte)requestedChannelCount, channels = (byte)requestedChannelCount,
format = GetSDL2Format(requestedSampleFormat), format = GetSDL3Format(requestedSampleFormat),
freq = (int)requestedSampleRate, freq = (int)requestedSampleRate,
samples = (ushort)sampleCount,
}; };
} }
internal static ushort GetSDL2Format(SampleFormat format) internal static SDL_AudioFormat GetSDL3Format(SampleFormat format)
{ {
return format switch return format switch
{ {
SampleFormat.PcmInt8 => AUDIO_S8, SampleFormat.PcmInt8 => SDL_AudioFormat.SDL_AUDIO_S8,
SampleFormat.PcmInt16 => AUDIO_S16, SampleFormat.PcmInt16 => SDL_AudioFormat.SDL_AUDIO_S16LE,
SampleFormat.PcmInt32 => AUDIO_S32, SampleFormat.PcmInt32 => SDL_AudioFormat.SDL_AUDIO_S32LE,
SampleFormat.PcmFloat => AUDIO_F32, SampleFormat.PcmFloat => SDL_AudioFormat.SDL_AUDIO_F32LE,
_ => throw new ArgumentException($"Unsupported sample format {format}"), _ => throw new ArgumentException($"Unsupported sample format {format}"),
}; };
} }
internal static uint OpenStream(SampleFormat requestedSampleFormat, uint requestedSampleRate, uint requestedChannelCount, uint sampleCount, SDL_AudioCallback callback) internal unsafe static SDL_AudioStream* OpenStream(SampleFormat requestedSampleFormat, uint requestedSampleRate, uint requestedChannelCount, uint sampleCount, SDL3HardwareDeviceSession.SDL_AudioStreamCallback callback)
{ {
SDL_AudioSpec desired = GetSDL2Spec(requestedSampleFormat, requestedSampleRate, requestedChannelCount, sampleCount); SDL_AudioSpec desired = GetSDL3Spec(requestedSampleFormat, requestedSampleRate, requestedChannelCount);
SDL_AudioSpec got = desired;
var pCallback = callback != null ? (SDL_AudioStreamCallbackPointer)Marshal.GetFunctionPointerForDelegate(callback) : null;
desired.callback = callback; // From SDL 3 and on, SDL requires us to set this as a hint
SDL_SetHint(SDL_HINT_AUDIO_DEVICE_SAMPLE_FRAMES, $"{sampleCount}");
SDL_AudioStream* device = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &got, pCallback, 0);
uint device = SDL_OpenAudioDevice(nint.Zero, 0, ref desired, out SDL_AudioSpec got, 0); if (device == null)
if (device == 0)
{ {
Logger.Error?.Print(LogClass.Application, $"SDL2 open audio device initialization failed with error \"{SDL_GetError()}\""); Logger.Error?.Print(LogClass.Application, $"SDL3 open audio device initialization failed with error \"{SDL_GetError()}\"");
return 0; return null;
} }
bool isValid = got.format == desired.format && got.freq == desired.freq && got.channels == desired.channels; bool isValid = got.format == desired.format && got.freq == desired.freq && got.channels == desired.channels;
if (!isValid) if (!isValid)
{ {
Logger.Error?.Print(LogClass.Application, "SDL2 open audio device is not valid"); Logger.Error?.Print(LogClass.Application, "SDL3 open audio device is not valid");
SDL_CloseAudioDevice(device); SDL_DestroyAudioStream(device);
return 0; return null;
} }
return device; return device;
@@ -166,12 +166,12 @@ namespace Ryujinx.Audio.Backends.SDL2
{ {
if (disposing) if (disposing)
{ {
foreach (SDL2HardwareDeviceSession session in _sessions.Keys) foreach (SDL3HardwareDeviceSession session in _sessions.Keys)
{ {
session.Dispose(); session.Dispose();
} }
SDL2Driver.Instance.Dispose(); SDL3Driver.Instance.Dispose();
_pauseEvent.Dispose(); _pauseEvent.Dispose();
} }

View File

@@ -6,36 +6,43 @@ using Ryujinx.Memory;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Threading; using System.Threading;
using SDL;
using static SDL.SDL3;
using System.Runtime.InteropServices;
using static SDL2.SDL; namespace Ryujinx.Audio.Backends.SDL3
namespace Ryujinx.Audio.Backends.SDL2
{ {
class SDL2HardwareDeviceSession : HardwareDeviceSessionOutputBase
unsafe class SDL3HardwareDeviceSession : HardwareDeviceSessionOutputBase
{ {
private readonly SDL2HardwareDeviceDriver _driver; private readonly SDL3HardwareDeviceDriver _driver;
private readonly ConcurrentQueue<SDL2AudioBuffer> _queuedBuffers; private readonly ConcurrentQueue<SDL3AudioBuffer> _queuedBuffers;
private readonly DynamicRingBuffer _ringBuffer; private readonly DynamicRingBuffer _ringBuffer;
private ulong _playedSampleCount; private ulong _playedSampleCount;
private readonly ManualResetEvent _updateRequiredEvent; private readonly ManualResetEvent _updateRequiredEvent;
private uint _outputStream; private SDL_AudioStream* _outputStream;
private bool _hasSetupError; private bool _hasSetupError;
private readonly SDL_AudioCallback _callbackDelegate; private readonly SDL_AudioStreamCallback _callbackDelegate;
private readonly int _bytesPerFrame; private readonly int _bytesPerFrame;
private uint _sampleCount; private uint _sampleCount;
private bool _started; private bool _started;
private float _volume; private float _volume;
private readonly ushort _nativeSampleFormat; private readonly SDL_AudioFormat _nativeSampleFormat;
public SDL2HardwareDeviceSession(SDL2HardwareDeviceDriver driver, IVirtualMemoryManager memoryManager, SampleFormat requestedSampleFormat, uint requestedSampleRate, uint requestedChannelCount) : base(memoryManager, requestedSampleFormat, requestedSampleRate, requestedChannelCount) [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void SDL_AudioStreamCallback(nint session, SDL_AudioStream* stream, int stream_count, int device_count);
public SDL3HardwareDeviceSession(SDL3HardwareDeviceDriver driver, IVirtualMemoryManager memoryManager, SampleFormat requestedSampleFormat, uint requestedSampleRate, uint requestedChannelCount) : base(memoryManager, requestedSampleFormat, requestedSampleRate, requestedChannelCount)
{ {
_driver = driver; _driver = driver;
_updateRequiredEvent = _driver.GetUpdateRequiredEvent(); _updateRequiredEvent = _driver.GetUpdateRequiredEvent();
_queuedBuffers = new ConcurrentQueue<SDL2AudioBuffer>(); _queuedBuffers = new ConcurrentQueue<SDL3AudioBuffer>();
_ringBuffer = new DynamicRingBuffer(); _ringBuffer = new DynamicRingBuffer();
_callbackDelegate = Update; _callbackDelegate = Update;
_bytesPerFrame = BackendHelper.GetSampleSize(RequestedSampleFormat) * (int)RequestedChannelCount; _bytesPerFrame = BackendHelper.GetSampleSize(RequestedSampleFormat) * (int)RequestedChannelCount;
_nativeSampleFormat = SDL2HardwareDeviceDriver.GetSDL2Format(RequestedSampleFormat); _nativeSampleFormat = SDL3HardwareDeviceDriver.GetSDL3Format(RequestedSampleFormat);
_sampleCount = uint.MaxValue; _sampleCount = uint.MaxValue;
_started = false; _started = false;
_volume = 1f; _volume = 1f;
@@ -44,45 +51,51 @@ namespace Ryujinx.Audio.Backends.SDL2
private void EnsureAudioStreamSetup(AudioBuffer buffer) private void EnsureAudioStreamSetup(AudioBuffer buffer)
{ {
uint bufferSampleCount = (uint)GetSampleCount(buffer); uint bufferSampleCount = (uint)GetSampleCount(buffer);
bool needAudioSetup = (_outputStream == 0 && !_hasSetupError) || bool needAudioSetup = (_outputStream == null && !_hasSetupError) ||
(bufferSampleCount >= Constants.TargetSampleCount && bufferSampleCount < _sampleCount); (bufferSampleCount >= Constants.TargetSampleCount && bufferSampleCount < _sampleCount);
if (needAudioSetup) if (needAudioSetup)
{ {
_sampleCount = Math.Max(Constants.TargetSampleCount, bufferSampleCount); _sampleCount = Math.Max(Constants.TargetSampleCount, bufferSampleCount);
uint newOutputStream = SDL2HardwareDeviceDriver.OpenStream(RequestedSampleFormat, RequestedSampleRate, RequestedChannelCount, _sampleCount, _callbackDelegate); SDL_AudioStream* newOutputStream = SDL3HardwareDeviceDriver.OpenStream(RequestedSampleFormat, RequestedSampleRate, RequestedChannelCount, _sampleCount, _callbackDelegate);
_hasSetupError = newOutputStream == 0; _hasSetupError = newOutputStream == null;
if (!_hasSetupError) if (!_hasSetupError)
{ {
if (_outputStream != 0) if (_outputStream != null)
{ {
SDL_CloseAudioDevice(_outputStream); SDL_DestroyAudioStream(_outputStream);
} }
_outputStream = newOutputStream; _outputStream = newOutputStream;
SDL_PauseAudioDevice(_outputStream, _started ? 0 : 1); if (_started) {
SDL_ResumeAudioStreamDevice(_outputStream);
} else {
SDL_PauseAudioStreamDevice(_outputStream);
}
Logger.Info?.Print(LogClass.Audio, $"New audio stream setup with a target sample count of {_sampleCount}"); Logger.Info?.Print(LogClass.Audio, $"New audio stream setup with a target sample count of {_sampleCount}");
} }
} }
} }
private unsafe void Update(nint userdata, nint stream, int streamLength) private unsafe void Update(nint userdata, SDL_AudioStream* streamDevice, int additionalAmount, int totalAmmount)
{ {
Span<byte> streamSpan = new((void*)stream, streamLength); using SpanOwner<byte> stream = SpanOwner<byte>.Rent(additionalAmount);
Span<byte> streamSpan = stream.Span;
int maxFrameCount = (int)GetSampleCount(streamLength);
int maxFrameCount = (int)GetSampleCount(additionalAmount);
int bufferedFrames = _ringBuffer.Length / _bytesPerFrame; int bufferedFrames = _ringBuffer.Length / _bytesPerFrame;
int frameCount = Math.Min(bufferedFrames, maxFrameCount); int frameCount = Math.Min(bufferedFrames, maxFrameCount);
if (frameCount == 0) if (frameCount == 0)
{ {
// SDL2 left the responsibility to the user to clear the buffer. // SDL3 left the responsibility to the user to clear the buffer.
streamSpan.Clear(); streamSpan.Clear();
return; return;
@@ -94,15 +107,17 @@ namespace Ryujinx.Audio.Backends.SDL2
_ringBuffer.Read(samples, 0, samples.Length); _ringBuffer.Read(samples, 0, samples.Length);
fixed (byte* p = samples) // Zero the dest buffer
{ streamSpan.Clear();
nint pStreamSrc = (nint)p;
// Zero the dest buffer fixed (byte* pStreamDst = streamSpan) {
streamSpan.Clear(); fixed (byte* pStreamSrc = samples)
{
// Apply volume to written data // Apply volume to written data
SDL_MixAudioFormat(stream, pStreamSrc, _nativeSampleFormat, (uint)samples.Length, (int)(_driver.Volume * _volume * SDL_MIX_MAXVOLUME)); SDL_MixAudio(pStreamDst, pStreamSrc, _nativeSampleFormat, (uint)samples.Length, _driver.Volume * _volume);
SDL_PutAudioStreamData(streamDevice, (nint)pStreamDst, additionalAmount);
}
} }
ulong sampleCount = GetSampleCount(samples.Length); ulong sampleCount = GetSampleCount(samples.Length);
@@ -111,7 +126,7 @@ namespace Ryujinx.Audio.Backends.SDL2
bool needUpdate = false; bool needUpdate = false;
while (availaibleSampleCount > 0 && _queuedBuffers.TryPeek(out SDL2AudioBuffer driverBuffer)) while (availaibleSampleCount > 0 && _queuedBuffers.TryPeek(out SDL3AudioBuffer driverBuffer))
{ {
ulong sampleStillNeeded = driverBuffer.SampleCount - Interlocked.Read(ref driverBuffer.SamplePlayed); ulong sampleStillNeeded = driverBuffer.SampleCount - Interlocked.Read(ref driverBuffer.SamplePlayed);
ulong playedAudioBufferSampleCount = Math.Min(sampleStillNeeded, availaibleSampleCount); ulong playedAudioBufferSampleCount = Math.Min(sampleStillNeeded, availaibleSampleCount);
@@ -152,9 +167,9 @@ namespace Ryujinx.Audio.Backends.SDL2
{ {
EnsureAudioStreamSetup(buffer); EnsureAudioStreamSetup(buffer);
if (_outputStream != 0) if (_outputStream != null)
{ {
SDL2AudioBuffer driverBuffer = new(buffer.DataPointer, GetSampleCount(buffer)); SDL3AudioBuffer driverBuffer = new(buffer.DataPointer, GetSampleCount(buffer));
_ringBuffer.Write(buffer.Data, 0, buffer.Data.Length); _ringBuffer.Write(buffer.Data, 0, buffer.Data.Length);
@@ -177,9 +192,9 @@ namespace Ryujinx.Audio.Backends.SDL2
{ {
if (!_started) if (!_started)
{ {
if (_outputStream != 0) if (_outputStream != null)
{ {
SDL_PauseAudioDevice(_outputStream, 0); SDL_ResumeAudioStreamDevice(_outputStream);
} }
_started = true; _started = true;
@@ -190,9 +205,9 @@ namespace Ryujinx.Audio.Backends.SDL2
{ {
if (_started) if (_started)
{ {
if (_outputStream != 0) if (_outputStream != null)
{ {
SDL_PauseAudioDevice(_outputStream, 1); SDL_PauseAudioStreamDevice(_outputStream);
} }
_started = false; _started = false;
@@ -203,7 +218,7 @@ namespace Ryujinx.Audio.Backends.SDL2
public override bool WasBufferFullyConsumed(AudioBuffer buffer) public override bool WasBufferFullyConsumed(AudioBuffer buffer)
{ {
if (!_queuedBuffers.TryPeek(out SDL2AudioBuffer driverBuffer)) if (!_queuedBuffers.TryPeek(out SDL3AudioBuffer driverBuffer))
{ {
return true; return true;
} }
@@ -218,9 +233,9 @@ namespace Ryujinx.Audio.Backends.SDL2
PrepareToClose(); PrepareToClose();
Stop(); Stop();
if (_outputStream != 0) if (_outputStream != null)
{ {
SDL_CloseAudioDevice(_outputStream); SDL_DestroyAudioStream(_outputStream);
} }
} }
} }

View File

@@ -58,16 +58,16 @@ namespace Ryujinx.Audio.Backends.CompatLayer
switch (realSampleFormat) switch (realSampleFormat)
{ {
case SampleFormat.PcmInt8: case SampleFormat.PcmInt8:
PcmHelper.ConvertSampleToPcm8(MemoryMarshal.Cast<byte, sbyte>(convertedSamples), samples); PcmHelper.ConvertSampleToPcm8(MemoryMarshal.Cast<byte, sbyte>(new Span<byte>(convertedSamples)), samples);
break; break;
case SampleFormat.PcmInt24: case SampleFormat.PcmInt24:
PcmHelper.ConvertSampleToPcm24(convertedSamples, samples); PcmHelper.ConvertSampleToPcm24(convertedSamples, samples);
break; break;
case SampleFormat.PcmInt32: case SampleFormat.PcmInt32:
PcmHelper.ConvertSampleToPcm32(MemoryMarshal.Cast<byte, int>(convertedSamples), samples); PcmHelper.ConvertSampleToPcm32(MemoryMarshal.Cast<byte, int>(new Span<byte>(convertedSamples)), samples);
break; break;
case SampleFormat.PcmFloat: case SampleFormat.PcmFloat:
PcmHelper.ConvertSampleToPcmFloat(MemoryMarshal.Cast<byte, float>(convertedSamples), samples); PcmHelper.ConvertSampleToPcmFloat(MemoryMarshal.Cast<byte, float>(new Span<byte>(convertedSamples)), samples);
break; break;
default: default:
throw new NotImplementedException($"Sample format conversion from {_userSampleFormat} to {realSampleFormat} not implemented."); throw new NotImplementedException($"Sample format conversion from {_userSampleFormat} to {realSampleFormat} not implemented.");

View File

@@ -27,7 +27,7 @@ namespace Ryujinx.Audio.Integration
public void AppendBuffer(ReadOnlySpan<short> data, uint channelCount) public void AppendBuffer(ReadOnlySpan<short> data, uint channelCount)
{ {
data.CopyTo(MemoryMarshal.Cast<byte, short>(_buffer)); data.CopyTo(MemoryMarshal.Cast<byte, short>(new Span<byte>(_buffer)));
_session.QueueBuffer(new AudioBuffer _session.QueueBuffer(new AudioBuffer
{ {

View File

@@ -1,9 +1,11 @@
using Ryujinx.Audio.Renderer.Server;
using Ryujinx.Audio.Renderer.Server.MemoryPool;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace Ryujinx.Audio.Renderer.Common namespace Ryujinx.Audio.Renderer.Common
{ {
/// <summary> /// <summary>
/// Represents the input parameter for <see cref="Server.BehaviourContext"/>. /// Represents the input parameter for <see cref="BehaviourInfo"/>.
/// </summary> /// </summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)] [StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct BehaviourParameter public struct BehaviourParameter
@@ -21,7 +23,7 @@ namespace Ryujinx.Audio.Renderer.Common
/// <summary> /// <summary>
/// The flags given controlling behaviour of the audio renderer /// The flags given controlling behaviour of the audio renderer
/// </summary> /// </summary>
/// <remarks>See <see cref="Server.BehaviourContext.UpdateFlags(ulong)"/> and <see cref="Server.BehaviourContext.IsMemoryPoolForceMappingEnabled"/>.</remarks> /// <remarks>See <see cref="BehaviourInfo.UpdateFlags(ulong)"/> and <see cref="BehaviourInfo.IsMemoryPoolForceMappingEnabled"/>.</remarks>
public ulong Flags; public ulong Flags;
/// <summary> /// <summary>
@@ -43,7 +45,7 @@ namespace Ryujinx.Audio.Renderer.Common
/// <summary> /// <summary>
/// Extra information given with the <see cref="ResultCode"/> /// Extra information given with the <see cref="ResultCode"/>
/// </summary> /// </summary>
/// <remarks>This is usually used to report a faulting cpu address when a <see cref="Server.MemoryPool.MemoryPoolState"/> mapping fail.</remarks> /// <remarks>This is usually used to report a faulting cpu address when a <see cref="MemoryPoolInfo"/> mapping fail.</remarks>
public ulong ExtraErrorInfo; public ulong ExtraErrorInfo;
} }
} }

View File

@@ -1,4 +1,5 @@
using Ryujinx.Audio.Renderer.Dsp.State; using Ryujinx.Audio.Renderer.Dsp.State;
using Ryujinx.Audio.Renderer.Parameter;
using Ryujinx.Common.Memory; using Ryujinx.Common.Memory;
using Ryujinx.Common.Utilities; using Ryujinx.Common.Utilities;
using System; using System;
@@ -11,7 +12,7 @@ namespace Ryujinx.Audio.Renderer.Common
/// </summary> /// </summary>
/// <remarks>This is shared between the server and audio processor.</remarks> /// <remarks>This is shared between the server and audio processor.</remarks>
[StructLayout(LayoutKind.Sequential, Pack = Align)] [StructLayout(LayoutKind.Sequential, Pack = Align)]
public struct VoiceUpdateState public struct VoiceState
{ {
public const int Align = 0x10; public const int Align = 0x10;
public const int BiquadStateOffset = 0x0; public const int BiquadStateOffset = 0x0;
@@ -25,7 +26,7 @@ namespace Ryujinx.Audio.Renderer.Common
/// The total amount of samples that was played. /// The total amount of samples that was played.
/// </summary> /// </summary>
/// <remarks>This is reset to 0 when a <see cref="WaveBuffer"/> finishes playing and <see cref="WaveBuffer.IsEndOfStream"/> is set.</remarks> /// <remarks>This is reset to 0 when a <see cref="WaveBuffer"/> finishes playing and <see cref="WaveBuffer.IsEndOfStream"/> is set.</remarks>
/// <remarks>This is reset to 0 when looping while <see cref="Parameter.VoiceInParameter.DecodingBehaviour.PlayedSampleCountResetWhenLooping"/> is set.</remarks> /// <remarks>This is reset to 0 when looping while <see cref="VoiceInParameter1.DecodingBehaviour.PlayedSampleCountResetWhenLooping"/> is set.</remarks>
public ulong PlayedSampleCount; public ulong PlayedSampleCount;
/// <summary> /// <summary>

View File

@@ -1,5 +1,7 @@
using Ryujinx.Audio.Renderer.Dsp.State; using Ryujinx.Audio.Renderer.Dsp.State;
using Ryujinx.Audio.Renderer.Parameter; using Ryujinx.Audio.Renderer.Parameter;
using Ryujinx.Audio.Renderer.Parameter.Effect;
using Ryujinx.Common.Memory;
using System; using System;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
@@ -9,6 +11,112 @@ namespace Ryujinx.Audio.Renderer.Dsp
{ {
private const int FixedPointPrecisionForParameter = 14; private const int FixedPointPrecisionForParameter = 14;
public static BiquadFilterParameter1 ToBiquadFilterParameter1(BiquadFilterParameter2 parameter)
{
BiquadFilterParameter1 result = new()
{
Enable = parameter.Enable, Numerator = new Array3<short>(), Denominator = new Array2<short>()
};
Span<short> resultNumeratorSpan = result.Numerator.AsSpan();
Span<short> resultDenominatorSpan = result.Denominator.AsSpan();
Span<float> parameterNumeratorSpan = parameter.Numerator.AsSpan();
Span<float> parameterDenominatorSpan = parameter.Denominator.AsSpan();
resultNumeratorSpan[0] = (short)FixedPointHelper.ToFixed(parameterNumeratorSpan[0], FixedPointPrecisionForParameter);
resultNumeratorSpan[1] = (short)FixedPointHelper.ToFixed(parameterNumeratorSpan[1], FixedPointPrecisionForParameter);
resultNumeratorSpan[2] = (short)FixedPointHelper.ToFixed(parameterNumeratorSpan[2], FixedPointPrecisionForParameter);
resultDenominatorSpan[0] = (short)FixedPointHelper.ToFixed(parameterDenominatorSpan[0], FixedPointPrecisionForParameter);
resultDenominatorSpan[1] = (short)FixedPointHelper.ToFixed(parameterDenominatorSpan[1], FixedPointPrecisionForParameter);
return result;
}
public static BiquadFilterParameter2 ToBiquadFilterParameter2(BiquadFilterParameter1 parameter)
{
BiquadFilterParameter2 result = new()
{
Enable = parameter.Enable, Numerator = new Array3<float>(), Denominator = new Array2<float>()
};
Span<float> resultNumeratorSpan = result.Numerator.AsSpan();
Span<float> resultDenominatorSpan = result.Denominator.AsSpan();
Span<short> parameterNumeratorSpan = parameter.Numerator.AsSpan();
Span<short> parameterDenominatorSpan = parameter.Denominator.AsSpan();
resultNumeratorSpan[0] = FixedPointHelper.ToFloat(parameterNumeratorSpan[0], FixedPointPrecisionForParameter);
resultNumeratorSpan[1] = FixedPointHelper.ToFloat(parameterNumeratorSpan[1], FixedPointPrecisionForParameter);
resultNumeratorSpan[2] = FixedPointHelper.ToFloat(parameterNumeratorSpan[2], FixedPointPrecisionForParameter);
resultDenominatorSpan[0] = FixedPointHelper.ToFloat(parameterDenominatorSpan[0], FixedPointPrecisionForParameter);
resultDenominatorSpan[1] = FixedPointHelper.ToFloat(parameterDenominatorSpan[1], FixedPointPrecisionForParameter);
return result;
}
public static BiquadFilterEffectParameter1 ToBiquadFilterEffectParameter1(BiquadFilterEffectParameter2 parameter)
{
BiquadFilterEffectParameter1 result = new()
{
Input = parameter.Input,
Output = parameter.Output,
Numerator = new Array3<short>(),
Denominator = new Array2<short>(),
ChannelCount = parameter.ChannelCount,
Status = parameter.Status,
};
Span<short> resultNumeratorSpan = result.Numerator.AsSpan();
Span<short> resultDenominatorSpan = result.Denominator.AsSpan();
Span<float> parameterNumeratorSpan = parameter.Numerator.AsSpan();
Span<float> parameterDenominatorSpan = parameter.Denominator.AsSpan();
resultNumeratorSpan[0] = (short)FixedPointHelper.ToFixed(parameterNumeratorSpan[0], FixedPointPrecisionForParameter);
resultNumeratorSpan[1] = (short)FixedPointHelper.ToFixed(parameterNumeratorSpan[1], FixedPointPrecisionForParameter);
resultNumeratorSpan[2] = (short)FixedPointHelper.ToFixed(parameterNumeratorSpan[2], FixedPointPrecisionForParameter);
resultDenominatorSpan[0] = (short)FixedPointHelper.ToFixed(parameterDenominatorSpan[0], FixedPointPrecisionForParameter);
resultDenominatorSpan[1] = (short)FixedPointHelper.ToFixed(parameterDenominatorSpan[1], FixedPointPrecisionForParameter);
return result;
}
public static BiquadFilterEffectParameter2 ToBiquadFilterEffectParameter2(BiquadFilterEffectParameter1 parameter)
{
BiquadFilterEffectParameter2 result = new()
{
Input = parameter.Input,
Output = parameter.Output,
Numerator = new Array3<float>(),
Denominator = new Array2<float>(),
ChannelCount = parameter.ChannelCount,
Status = parameter.Status,
};
Span<float> resultNumeratorSpan = result.Numerator.AsSpan();
Span<float> resultDenominatorSpan = result.Denominator.AsSpan();
Span<short> parameterNumeratorSpan = parameter.Numerator.AsSpan();
Span<short> parameterDenominatorSpan = parameter.Denominator.AsSpan();
resultNumeratorSpan[0] = FixedPointHelper.ToFloat(parameterNumeratorSpan[0], FixedPointPrecisionForParameter);
resultNumeratorSpan[1] = FixedPointHelper.ToFloat(parameterNumeratorSpan[1], FixedPointPrecisionForParameter);
resultNumeratorSpan[2] = FixedPointHelper.ToFloat(parameterNumeratorSpan[2], FixedPointPrecisionForParameter);
resultDenominatorSpan[0] = FixedPointHelper.ToFloat(parameterDenominatorSpan[0], FixedPointPrecisionForParameter);
resultDenominatorSpan[1] = FixedPointHelper.ToFloat(parameterDenominatorSpan[1], FixedPointPrecisionForParameter);
return result;
}
/// <summary> /// <summary>
/// Apply a single biquad filter. /// Apply a single biquad filter.
/// </summary> /// </summary>
@@ -20,21 +128,21 @@ namespace Ryujinx.Audio.Renderer.Dsp
/// <param name="sampleCount">The count of samples to process</param> /// <param name="sampleCount">The count of samples to process</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void ProcessBiquadFilter( public static void ProcessBiquadFilter(
ref BiquadFilterParameter parameter, ref BiquadFilterParameter2 parameter,
ref BiquadFilterState state, ref BiquadFilterState state,
Span<float> outputBuffer, Span<float> outputBuffer,
ReadOnlySpan<float> inputBuffer, ReadOnlySpan<float> inputBuffer,
uint sampleCount) uint sampleCount)
{ {
Span<short> numeratorSpan = parameter.Numerator.AsSpan(); Span<float> numeratorSpan = parameter.Numerator.AsSpan();
Span<short> denominatorSpan = parameter.Denominator.AsSpan(); Span<float> denominatorSpan = parameter.Denominator.AsSpan();
float a0 = FixedPointHelper.ToFloat(numeratorSpan[0], FixedPointPrecisionForParameter); float a0 = numeratorSpan[0];
float a1 = FixedPointHelper.ToFloat(numeratorSpan[1], FixedPointPrecisionForParameter); float a1 = numeratorSpan[1];
float a2 = FixedPointHelper.ToFloat(numeratorSpan[2], FixedPointPrecisionForParameter); float a2 = numeratorSpan[2];
float b1 = FixedPointHelper.ToFloat(denominatorSpan[0], FixedPointPrecisionForParameter); float b1 = denominatorSpan[0];
float b2 = FixedPointHelper.ToFloat(denominatorSpan[1], FixedPointPrecisionForParameter); float b2 = denominatorSpan[1];
for (int i = 0; i < sampleCount; i++) for (int i = 0; i < sampleCount; i++)
{ {
@@ -60,22 +168,22 @@ namespace Ryujinx.Audio.Renderer.Dsp
/// <param name="volume">Mix volume</param> /// <param name="volume">Mix volume</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void ProcessBiquadFilterAndMix( public static void ProcessBiquadFilterAndMix(
ref BiquadFilterParameter parameter, ref BiquadFilterParameter2 parameter,
ref BiquadFilterState state, ref BiquadFilterState state,
Span<float> outputBuffer, Span<float> outputBuffer,
ReadOnlySpan<float> inputBuffer, ReadOnlySpan<float> inputBuffer,
uint sampleCount, uint sampleCount,
float volume) float volume)
{ {
Span<short> numeratorSpan = parameter.Numerator.AsSpan(); Span<float> numeratorSpan = parameter.Numerator.AsSpan();
Span<short> denominatorSpan = parameter.Denominator.AsSpan(); Span<float> denominatorSpan = parameter.Denominator.AsSpan();
float a0 = FixedPointHelper.ToFloat(numeratorSpan[0], FixedPointPrecisionForParameter); float a0 = numeratorSpan[0];
float a1 = FixedPointHelper.ToFloat(numeratorSpan[1], FixedPointPrecisionForParameter); float a1 = numeratorSpan[1];
float a2 = FixedPointHelper.ToFloat(numeratorSpan[2], FixedPointPrecisionForParameter); float a2 = numeratorSpan[2];
float b1 = FixedPointHelper.ToFloat(denominatorSpan[0], FixedPointPrecisionForParameter); float b1 = denominatorSpan[0];
float b2 = FixedPointHelper.ToFloat(denominatorSpan[1], FixedPointPrecisionForParameter); float b2 = denominatorSpan[1];
for (int i = 0; i < sampleCount; i++) for (int i = 0; i < sampleCount; i++)
{ {
@@ -105,7 +213,7 @@ namespace Ryujinx.Audio.Renderer.Dsp
/// <returns>Last filtered sample value</returns> /// <returns>Last filtered sample value</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float ProcessBiquadFilterAndMixRamp( public static float ProcessBiquadFilterAndMixRamp(
ref BiquadFilterParameter parameter, ref BiquadFilterParameter2 parameter,
ref BiquadFilterState state, ref BiquadFilterState state,
Span<float> outputBuffer, Span<float> outputBuffer,
ReadOnlySpan<float> inputBuffer, ReadOnlySpan<float> inputBuffer,
@@ -113,15 +221,15 @@ namespace Ryujinx.Audio.Renderer.Dsp
float volume, float volume,
float ramp) float ramp)
{ {
Span<short> numeratorSpan = parameter.Numerator.AsSpan(); Span<float> numeratorSpan = parameter.Numerator.AsSpan();
Span<short> denominatorSpan = parameter.Denominator.AsSpan(); Span<float> denominatorSpan = parameter.Denominator.AsSpan();
float a0 = FixedPointHelper.ToFloat(numeratorSpan[0], FixedPointPrecisionForParameter); float a0 = numeratorSpan[0];
float a1 = FixedPointHelper.ToFloat(numeratorSpan[1], FixedPointPrecisionForParameter); float a1 = numeratorSpan[1];
float a2 = FixedPointHelper.ToFloat(numeratorSpan[2], FixedPointPrecisionForParameter); float a2 = numeratorSpan[2];
float b1 = FixedPointHelper.ToFloat(denominatorSpan[0], FixedPointPrecisionForParameter); float b1 = denominatorSpan[0];
float b2 = FixedPointHelper.ToFloat(denominatorSpan[1], FixedPointPrecisionForParameter); float b2 = denominatorSpan[1];
float mixState = 0f; float mixState = 0f;
@@ -155,7 +263,7 @@ namespace Ryujinx.Audio.Renderer.Dsp
/// <param name="sampleCount">The count of samples to process</param> /// <param name="sampleCount">The count of samples to process</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void ProcessBiquadFilter( public static void ProcessBiquadFilter(
ReadOnlySpan<BiquadFilterParameter> parameters, ReadOnlySpan<BiquadFilterParameter2> parameters,
Span<BiquadFilterState> states, Span<BiquadFilterState> states,
Span<float> outputBuffer, Span<float> outputBuffer,
ReadOnlySpan<float> inputBuffer, ReadOnlySpan<float> inputBuffer,
@@ -163,19 +271,19 @@ namespace Ryujinx.Audio.Renderer.Dsp
{ {
for (int stageIndex = 0; stageIndex < parameters.Length; stageIndex++) for (int stageIndex = 0; stageIndex < parameters.Length; stageIndex++)
{ {
BiquadFilterParameter parameter = parameters[stageIndex]; BiquadFilterParameter2 parameter = parameters[stageIndex];
ref BiquadFilterState state = ref states[stageIndex]; ref BiquadFilterState state = ref states[stageIndex];
Span<short> numeratorSpan = parameter.Numerator.AsSpan(); Span<float> numeratorSpan = parameter.Numerator.AsSpan();
Span<short> denominatorSpan = parameter.Denominator.AsSpan(); Span<float> denominatorSpan = parameter.Denominator.AsSpan();
float a0 = FixedPointHelper.ToFloat(numeratorSpan[0], FixedPointPrecisionForParameter); float a0 = numeratorSpan[0];
float a1 = FixedPointHelper.ToFloat(numeratorSpan[1], FixedPointPrecisionForParameter); float a1 = numeratorSpan[1];
float a2 = FixedPointHelper.ToFloat(numeratorSpan[2], FixedPointPrecisionForParameter); float a2 = numeratorSpan[2];
float b1 = FixedPointHelper.ToFloat(denominatorSpan[0], FixedPointPrecisionForParameter); float b1 = denominatorSpan[0];
float b2 = FixedPointHelper.ToFloat(denominatorSpan[1], FixedPointPrecisionForParameter); float b2 = denominatorSpan[1];
for (int i = 0; i < sampleCount; i++) for (int i = 0; i < sampleCount; i++)
{ {
@@ -204,8 +312,8 @@ namespace Ryujinx.Audio.Renderer.Dsp
/// <param name="volume">Mix volume</param> /// <param name="volume">Mix volume</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void ProcessDoubleBiquadFilterAndMix( public static void ProcessDoubleBiquadFilterAndMix(
ref BiquadFilterParameter parameter0, ref BiquadFilterParameter2 parameter0,
ref BiquadFilterParameter parameter1, ref BiquadFilterParameter2 parameter1,
ref BiquadFilterState state0, ref BiquadFilterState state0,
ref BiquadFilterState state1, ref BiquadFilterState state1,
Span<float> outputBuffer, Span<float> outputBuffer,
@@ -213,25 +321,25 @@ namespace Ryujinx.Audio.Renderer.Dsp
uint sampleCount, uint sampleCount,
float volume) float volume)
{ {
Span<short> numerator0Span = parameter0.Numerator.AsSpan(); Span<float> numerator0Span = parameter0.Numerator.AsSpan();
Span<short> numerator1Span = parameter1.Numerator.AsSpan(); Span<float> numerator1Span = parameter1.Numerator.AsSpan();
Span<short> denominator0Span = parameter0.Denominator.AsSpan(); Span<float> denominator0Span = parameter0.Denominator.AsSpan();
Span<short> denominator1Span = parameter1.Denominator.AsSpan(); Span<float> denominator1Span = parameter1.Denominator.AsSpan();
float a00 = FixedPointHelper.ToFloat(numerator0Span[0], FixedPointPrecisionForParameter); float a00 = numerator0Span[0];
float a10 = FixedPointHelper.ToFloat(numerator0Span[1], FixedPointPrecisionForParameter); float a10 = numerator0Span[1];
float a20 = FixedPointHelper.ToFloat(numerator0Span[2], FixedPointPrecisionForParameter); float a20 = numerator0Span[2];
float b10 = FixedPointHelper.ToFloat(denominator0Span[0], FixedPointPrecisionForParameter); float b10 = denominator0Span[0];
float b20 = FixedPointHelper.ToFloat(denominator0Span[1], FixedPointPrecisionForParameter); float b20 = denominator0Span[1];
float a01 = FixedPointHelper.ToFloat(numerator1Span[0], FixedPointPrecisionForParameter); float a01 = numerator1Span[0];
float a11 = FixedPointHelper.ToFloat(numerator1Span[1], FixedPointPrecisionForParameter); float a11 = numerator1Span[1];
float a21 = FixedPointHelper.ToFloat(numerator1Span[2], FixedPointPrecisionForParameter); float a21 = numerator1Span[2];
float b11 = FixedPointHelper.ToFloat(denominator1Span[0], FixedPointPrecisionForParameter); float b11 = denominator1Span[0];
float b21 = FixedPointHelper.ToFloat(denominator1Span[1], FixedPointPrecisionForParameter); float b21 = denominator1Span[1];
for (int i = 0; i < sampleCount; i++) for (int i = 0; i < sampleCount; i++)
{ {
@@ -269,8 +377,8 @@ namespace Ryujinx.Audio.Renderer.Dsp
/// <returns>Last filtered sample value</returns> /// <returns>Last filtered sample value</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float ProcessDoubleBiquadFilterAndMixRamp( public static float ProcessDoubleBiquadFilterAndMixRamp(
ref BiquadFilterParameter parameter0, ref BiquadFilterParameter2 parameter0,
ref BiquadFilterParameter parameter1, ref BiquadFilterParameter2 parameter1,
ref BiquadFilterState state0, ref BiquadFilterState state0,
ref BiquadFilterState state1, ref BiquadFilterState state1,
Span<float> outputBuffer, Span<float> outputBuffer,
@@ -279,24 +387,24 @@ namespace Ryujinx.Audio.Renderer.Dsp
float volume, float volume,
float ramp) float ramp)
{ {
Span<short> numerator0Span = parameter0.Numerator.AsSpan(); Span<float> numerator0Span = parameter0.Numerator.AsSpan();
Span<short> numerator1Span = parameter1.Numerator.AsSpan(); Span<float> numerator1Span = parameter1.Numerator.AsSpan();
Span<short> denominator0Span = parameter0.Denominator.AsSpan(); Span<float> denominator0Span = parameter0.Denominator.AsSpan();
Span<short> denominator1Span = parameter1.Denominator.AsSpan(); Span<float> denominator1Span = parameter1.Denominator.AsSpan();
float a00 = FixedPointHelper.ToFloat(numerator0Span[0], FixedPointPrecisionForParameter); float a00 = numerator0Span[0];
float a10 = FixedPointHelper.ToFloat(numerator0Span[1], FixedPointPrecisionForParameter); float a10 = numerator0Span[1];
float a20 = FixedPointHelper.ToFloat(numerator0Span[2], FixedPointPrecisionForParameter); float a20 = numerator0Span[2];
float b10 = FixedPointHelper.ToFloat(denominator0Span[0], FixedPointPrecisionForParameter); float b10 = denominator0Span[0];
float b20 = FixedPointHelper.ToFloat(denominator0Span[1], FixedPointPrecisionForParameter); float b20 = denominator0Span[1];
float a01 = FixedPointHelper.ToFloat(numerator1Span[0], FixedPointPrecisionForParameter); float a01 = numerator1Span[0];
float a11 = FixedPointHelper.ToFloat(numerator1Span[1], FixedPointPrecisionForParameter); float a11 = numerator1Span[1];
float a21 = FixedPointHelper.ToFloat(numerator1Span[2], FixedPointPrecisionForParameter); float a21 = numerator1Span[2];
float b11 = FixedPointHelper.ToFloat(denominator1Span[0], FixedPointPrecisionForParameter); float b11 = denominator1Span[0];
float b21 = FixedPointHelper.ToFloat(denominator1Span[1], FixedPointPrecisionForParameter); float b21 = denominator1Span[1];
float mixState = 0f; float mixState = 0f;

View File

@@ -2,7 +2,7 @@ using Ryujinx.Audio.Common;
using Ryujinx.Audio.Renderer.Common; using Ryujinx.Audio.Renderer.Common;
using Ryujinx.Audio.Renderer.Server.Voice; using Ryujinx.Audio.Renderer.Server.Voice;
using System; using System;
using static Ryujinx.Audio.Renderer.Parameter.VoiceInParameter; using Ryujinx.Audio.Renderer.Parameter;
using WaveBuffer = Ryujinx.Audio.Renderer.Common.WaveBuffer; using WaveBuffer = Ryujinx.Audio.Renderer.Common.WaveBuffer;
namespace Ryujinx.Audio.Renderer.Dsp.Command namespace Ryujinx.Audio.Renderer.Dsp.Command
@@ -11,38 +11,41 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.AdpcmDataSourceVersion1; public CommandType CommandType => CommandType.AdpcmDataSourceVersion1;
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
public ushort OutputBufferIndex { get; } public ushort OutputBufferIndex { get; private set; }
public uint SampleRate { get; } public uint SampleRate { get; private set; }
public float Pitch { get; } public float Pitch { get; private set; }
public WaveBuffer[] WaveBuffers { get; } public WaveBuffer[] WaveBuffers { get; }
public Memory<VoiceUpdateState> State { get; } public Memory<VoiceState> State { get; private set; }
public ulong AdpcmParameter { get; } public ulong AdpcmParameter { get; private set; }
public ulong AdpcmParameterSize { get; } public ulong AdpcmParameterSize { get; private set; }
public DecodingBehaviour DecodingBehaviour { get; } public DecodingBehaviour DecodingBehaviour { get; private set; }
public AdpcmDataSourceCommandVersion1(ref VoiceState serverState, Memory<VoiceUpdateState> state, ushort outputBufferIndex, int nodeId) public AdpcmDataSourceCommandVersion1()
{
WaveBuffers = new WaveBuffer[Constants.VoiceWaveBufferCount];
}
public AdpcmDataSourceCommandVersion1 Initialize(ref VoiceInfo serverInfo, Memory<VoiceState> state, ushort outputBufferIndex, int nodeId)
{ {
Enabled = true; Enabled = true;
NodeId = nodeId; NodeId = nodeId;
OutputBufferIndex = outputBufferIndex; OutputBufferIndex = outputBufferIndex;
SampleRate = serverState.SampleRate; SampleRate = serverInfo.SampleRate;
Pitch = serverState.Pitch; Pitch = serverInfo.Pitch;
Span<Server.Voice.WaveBuffer> waveBufferSpan = serverState.WaveBuffers.AsSpan(); Span<Server.Voice.WaveBuffer> waveBufferSpan = serverInfo.WaveBuffers.AsSpan();
WaveBuffers = new WaveBuffer[Constants.VoiceWaveBufferCount];
for (int i = 0; i < WaveBuffers.Length; i++) for (int i = 0; i < WaveBuffers.Length; i++)
{ {
@@ -51,10 +54,12 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
WaveBuffers[i] = voiceWaveBuffer.ToCommon(1); WaveBuffers[i] = voiceWaveBuffer.ToCommon(1);
} }
AdpcmParameter = serverState.DataSourceStateAddressInfo.GetReference(true); AdpcmParameter = serverInfo.DataSourceStateAddressInfo.GetReference(true);
AdpcmParameterSize = serverState.DataSourceStateAddressInfo.Size; AdpcmParameterSize = serverInfo.DataSourceStateAddressInfo.Size;
State = state; State = state;
DecodingBehaviour = serverState.DecodingBehaviour; DecodingBehaviour = serverInfo.DecodingBehaviour;
return this;
} }
public void Process(CommandList context) public void Process(CommandList context)

View File

@@ -12,26 +12,31 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.AuxiliaryBuffer; public CommandType CommandType => CommandType.AuxiliaryBuffer;
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
public uint InputBufferIndex { get; } public uint InputBufferIndex { get; private set; }
public uint OutputBufferIndex { get; } public uint OutputBufferIndex { get; private set; }
public AuxiliaryBufferAddresses BufferInfo { get; } public AuxiliaryBufferAddresses BufferInfo { get; private set; }
public CpuAddress InputBuffer { get; } public CpuAddress InputBuffer { get; private set; }
public CpuAddress OutputBuffer { get; } public CpuAddress OutputBuffer { get; private set; }
public uint CountMax { get; } public uint CountMax { get; private set; }
public uint UpdateCount { get; } public uint UpdateCount { get; private set; }
public uint WriteOffset { get; } public uint WriteOffset { get; private set; }
public bool IsEffectEnabled { get; } public bool IsEffectEnabled { get; private set; }
public AuxiliaryBufferCommand( public AuxiliaryBufferCommand()
{
}
public AuxiliaryBufferCommand Initialize(
uint bufferOffset, uint bufferOffset,
byte inputBufferOffset, byte inputBufferOffset,
byte outputBufferOffset, byte outputBufferOffset,
@@ -55,6 +60,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
UpdateCount = updateCount; UpdateCount = updateCount;
WriteOffset = writeOffset; WriteOffset = writeOffset;
IsEffectEnabled = isEnabled; IsEffectEnabled = isEnabled;
return this;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]

View File

@@ -9,39 +9,44 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.BiquadFilterAndMix; public CommandType CommandType => CommandType.BiquadFilterAndMix;
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
public ushort InputBufferIndex { get; } public ushort InputBufferIndex { get; private set; }
public ushort OutputBufferIndex { get; } public ushort OutputBufferIndex { get; private set; }
private BiquadFilterParameter _parameter; private BiquadFilterParameter2 _parameter;
public Memory<BiquadFilterState> BiquadFilterState { get; } public Memory<BiquadFilterState> BiquadFilterState { get; private set; }
public Memory<BiquadFilterState> PreviousBiquadFilterState { get; } public Memory<BiquadFilterState> PreviousBiquadFilterState { get; private set; }
public Memory<VoiceUpdateState> State { get; } public Memory<VoiceState> State { get; private set; }
public int LastSampleIndex { get; } public int LastSampleIndex { get; private set; }
public float Volume0 { get; } public float Volume0 { get; private set; }
public float Volume1 { get; } public float Volume1 { get; private set; }
public bool NeedInitialization { get; } public bool NeedInitialization { get; private set; }
public bool HasVolumeRamp { get; } public bool HasVolumeRamp { get; private set; }
public bool IsFirstMixBuffer { get; } public bool IsFirstMixBuffer { get; private set; }
public BiquadFilterAndMixCommand( public BiquadFilterAndMixCommand()
{
}
public BiquadFilterAndMixCommand Initialize(
float volume0, float volume0,
float volume1, float volume1,
uint inputBufferIndex, uint inputBufferIndex,
uint outputBufferIndex, uint outputBufferIndex,
int lastSampleIndex, int lastSampleIndex,
Memory<VoiceUpdateState> state, Memory<VoiceState> state,
ref BiquadFilterParameter filter, ref BiquadFilterParameter2 filter,
Memory<BiquadFilterState> biquadFilterState, Memory<BiquadFilterState> biquadFilterState,
Memory<BiquadFilterState> previousBiquadFilterState, Memory<BiquadFilterState> previousBiquadFilterState,
bool needInitialization, bool needInitialization,
@@ -68,6 +73,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
NeedInitialization = needInitialization; NeedInitialization = needInitialization;
HasVolumeRamp = hasVolumeRamp; HasVolumeRamp = hasVolumeRamp;
IsFirstMixBuffer = isFirstMixBuffer; IsFirstMixBuffer = isFirstMixBuffer;
return this;
} }
public void Process(CommandList context) public void Process(CommandList context)

View File

@@ -8,22 +8,27 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.BiquadFilter; public CommandType CommandType => CommandType.BiquadFilter;
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
public Memory<BiquadFilterState> BiquadFilterState { get; } public Memory<BiquadFilterState> BiquadFilterState { get; private set; }
public int InputBufferIndex { get; } public int InputBufferIndex { get; private set; }
public int OutputBufferIndex { get; } public int OutputBufferIndex { get; private set; }
public bool NeedInitialization { get; } public bool NeedInitialization { get; private set; }
private BiquadFilterParameter _parameter; private BiquadFilterParameter2 _parameter;
public BiquadFilterCommand( public BiquadFilterCommand()
{
}
public BiquadFilterCommand Initialize(
int baseIndex, int baseIndex,
ref BiquadFilterParameter filter, ref BiquadFilterParameter2 filter,
Memory<BiquadFilterState> biquadFilterStateMemory, Memory<BiquadFilterState> biquadFilterStateMemory,
int inputBufferOffset, int inputBufferOffset,
int outputBufferOffset, int outputBufferOffset,
@@ -38,6 +43,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
Enabled = true; Enabled = true;
NodeId = nodeId; NodeId = nodeId;
return this;
} }
public void Process(CommandList context) public void Process(CommandList context)

View File

@@ -12,25 +12,30 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.CaptureBuffer; public CommandType CommandType => CommandType.CaptureBuffer;
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
public uint InputBufferIndex { get; } public uint InputBufferIndex { get; private set; }
public ulong CpuBufferInfoAddress { get; } public ulong CpuBufferInfoAddress { get; private set; }
public ulong DspBufferInfoAddress { get; } public ulong DspBufferInfoAddress { get; private set; }
public CpuAddress OutputBuffer { get; } public CpuAddress OutputBuffer { get; private set; }
public uint CountMax { get; } public uint CountMax { get; private set; }
public uint UpdateCount { get; } public uint UpdateCount { get; private set; }
public uint WriteOffset { get; } public uint WriteOffset { get; private set; }
public bool IsEffectEnabled { get; } public bool IsEffectEnabled { get; private set; }
public CaptureBufferCommand(uint bufferOffset, byte inputBufferOffset, ulong sendBufferInfo, bool isEnabled, public CaptureBufferCommand()
{
}
public CaptureBufferCommand Initialize(uint bufferOffset, byte inputBufferOffset, ulong sendBufferInfo, bool isEnabled,
uint countMax, CpuAddress outputBuffer, uint updateCount, uint writeOffset, int nodeId) uint countMax, CpuAddress outputBuffer, uint updateCount, uint writeOffset, int nodeId)
{ {
Enabled = true; Enabled = true;
@@ -43,6 +48,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
UpdateCount = updateCount; UpdateCount = updateCount;
WriteOffset = writeOffset; WriteOffset = writeOffset;
IsEffectEnabled = isEnabled; IsEffectEnabled = isEnabled;
return this;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]

View File

@@ -9,25 +9,29 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.CircularBufferSink; public CommandType CommandType => CommandType.CircularBufferSink;
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
public ushort[] Input { get; } public ushort[] Input { get; }
public uint InputCount { get; } public uint InputCount { get; private set; }
public ulong CircularBuffer { get; } public ulong CircularBuffer { get; private set; }
public ulong CircularBufferSize { get; } public ulong CircularBufferSize { get; private set; }
public ulong CurrentOffset { get; } public ulong CurrentOffset { get; private set; }
public CircularBufferSinkCommand(uint bufferOffset, ref CircularBufferParameter parameter, ref AddressInfo circularBufferAddressInfo, uint currentOffset, int nodeId) public CircularBufferSinkCommand()
{
Input = new ushort[Constants.ChannelCountMax];
}
public CircularBufferSinkCommand Initialize(uint bufferOffset, ref CircularBufferParameter parameter, ref AddressInfo circularBufferAddressInfo, uint currentOffset, int nodeId)
{ {
Enabled = true; Enabled = true;
NodeId = nodeId; NodeId = nodeId;
Input = new ushort[Constants.ChannelCountMax];
InputCount = parameter.InputCount; InputCount = parameter.InputCount;
Span<byte> inputSpan = parameter.Input.AsSpan(); Span<byte> inputSpan = parameter.Input.AsSpan();
@@ -42,6 +46,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
CurrentOffset = currentOffset; CurrentOffset = currentOffset;
Debug.Assert(CircularBuffer != 0); Debug.Assert(CircularBuffer != 0);
return this;
} }
public void Process(CommandList context) public void Process(CommandList context)

View File

@@ -4,16 +4,23 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.ClearMixBuffer; public CommandType CommandType => CommandType.ClearMixBuffer;
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
public ClearMixBufferCommand(int nodeId) public ClearMixBufferCommand()
{
}
public ClearMixBufferCommand Initialize(int nodeId)
{ {
Enabled = true; Enabled = true;
NodeId = nodeId; NodeId = nodeId;
return this;
} }
public void Process(CommandList context) public void Process(CommandList context)

View File

@@ -20,6 +20,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
public Memory<float> Buffers { get; } public Memory<float> Buffers { get; }
public uint BufferCount { get; } public uint BufferCount { get; }
private readonly static ObjectPool<List<ICommand>> CommandsListPool = new(() => new List<ICommand>(256));
public List<ICommand> Commands { get; } public List<ICommand> Commands { get; }
public IVirtualMemoryManager MemoryManager { get; } public IVirtualMemoryManager MemoryManager { get; }
@@ -46,7 +47,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
SampleRate = sampleRate; SampleRate = sampleRate;
BufferCount = mixBufferCount + voiceChannelCountMax; BufferCount = mixBufferCount + voiceChannelCountMax;
Buffers = mixBuffer; Buffers = mixBuffer;
Commands = []; Commands = CommandsListPool.Allocate();
MemoryManager = memoryManager; MemoryManager = memoryManager;
_buffersEntryCount = Buffers.Length; _buffersEntryCount = Buffers.Length;
@@ -129,7 +130,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
startTime = PerformanceCounter.ElapsedNanoseconds; startTime = PerformanceCounter.ElapsedNanoseconds;
} }
command.Process(this); command.Process(this);
if (shouldMeter) if (shouldMeter)
@@ -142,6 +143,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
} }
} }
} }
CommandBuffer.ReleaseCommand(command);
} }
EndTime = (ulong)PerformanceCounter.ElapsedNanoseconds; EndTime = (ulong)PerformanceCounter.ElapsedNanoseconds;
@@ -149,6 +152,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
public void Dispose() public void Dispose()
{ {
Commands.Clear();
CommandsListPool.Release(Commands);
GC.SuppressFinalize(this); GC.SuppressFinalize(this);
_buffersMemoryHandle.Dispose(); _buffersMemoryHandle.Dispose();
} }

View File

@@ -12,6 +12,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
Volume, Volume,
VolumeRamp, VolumeRamp,
BiquadFilter, BiquadFilter,
BiquadFilterFloatCoeff, // new
Mix, Mix,
MixRamp, MixRamp,
MixRampGrouped, MixRampGrouped,
@@ -31,9 +32,17 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
LimiterVersion1, LimiterVersion1,
LimiterVersion2, LimiterVersion2,
MultiTapBiquadFilter, MultiTapBiquadFilter,
MultiTapBiquadFilterFloatCoeff, // new
CaptureBuffer, CaptureBuffer,
Compressor, Compressor,
BiquadFilterAndMix, BiquadFilterAndMix,
BiquadFilterAndMixFloatCoeff, // new
MultiTapBiquadFilterAndMix, MultiTapBiquadFilterAndMix,
MultiTapBiquadFilterAndMixFloatCoef, // new
AuxiliaryBufferGrouped, // new
FillMixBuffer, // new
BiquadFilterCrossFade, // new
MultiTapBiquadFilterCrossFade, // new
FillBuffer, // new
} }
} }

View File

@@ -15,22 +15,28 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.Compressor; public CommandType CommandType => CommandType.Compressor;
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
public CompressorParameter Parameter => _parameter; public CompressorParameter Parameter => _parameter;
public Memory<CompressorState> State { get; } public Memory<CompressorState> State { get; private set; }
public Memory<EffectResultState> ResultState { get; } public Memory<EffectResultState> ResultState { get; private set; }
public ushort[] OutputBufferIndices { get; } public ushort[] OutputBufferIndices { get; }
public ushort[] InputBufferIndices { get; } public ushort[] InputBufferIndices { get; }
public bool IsEffectEnabled { get; } public bool IsEffectEnabled { get; private set; }
private CompressorParameter _parameter; private CompressorParameter _parameter;
public CompressorCommand(uint bufferOffset, CompressorParameter parameter, Memory<CompressorState> state, Memory<EffectResultState> resultState, bool isEnabled, int nodeId) public CompressorCommand()
{
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
}
public CompressorCommand Initialize(uint bufferOffset, CompressorParameter parameter, Memory<CompressorState> state, Memory<EffectResultState> resultState, bool isEnabled, int nodeId)
{ {
Enabled = true; Enabled = true;
NodeId = nodeId; NodeId = nodeId;
@@ -39,9 +45,6 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
ResultState = resultState; ResultState = resultState;
IsEffectEnabled = isEnabled; IsEffectEnabled = isEnabled;
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
Span<byte> inputSpan = _parameter.Input.AsSpan(); Span<byte> inputSpan = _parameter.Input.AsSpan();
Span<byte> outputSpan = _parameter.Output.AsSpan(); Span<byte> outputSpan = _parameter.Output.AsSpan();
@@ -51,6 +54,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
InputBufferIndices[i] = (ushort)(bufferOffset + inputSpan[i]); InputBufferIndices[i] = (ushort)(bufferOffset + inputSpan[i]);
OutputBufferIndices[i] = (ushort)(bufferOffset + outputSpan[i]); OutputBufferIndices[i] = (ushort)(bufferOffset + outputSpan[i]);
} }
return this;
} }
public void Process(CommandList context) public void Process(CommandList context)

View File

@@ -4,22 +4,29 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.CopyMixBuffer; public CommandType CommandType => CommandType.CopyMixBuffer;
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
public ushort InputBufferIndex { get; } public ushort InputBufferIndex { get; private set; }
public ushort OutputBufferIndex { get; } public ushort OutputBufferIndex { get; private set; }
public CopyMixBufferCommand(uint inputBufferIndex, uint outputBufferIndex, int nodeId) public CopyMixBufferCommand()
{
}
public CopyMixBufferCommand Initialize(uint inputBufferIndex, uint outputBufferIndex, int nodeId)
{ {
Enabled = true; Enabled = true;
NodeId = nodeId; NodeId = nodeId;
InputBufferIndex = (ushort)inputBufferIndex; InputBufferIndex = (ushort)inputBufferIndex;
OutputBufferIndex = (ushort)outputBufferIndex; OutputBufferIndex = (ushort)outputBufferIndex;
return this;
} }
public void Process(CommandList context) public void Process(CommandList context)

View File

@@ -2,7 +2,7 @@ using Ryujinx.Audio.Common;
using Ryujinx.Audio.Renderer.Common; using Ryujinx.Audio.Renderer.Common;
using Ryujinx.Audio.Renderer.Server.Voice; using Ryujinx.Audio.Renderer.Server.Voice;
using System; using System;
using static Ryujinx.Audio.Renderer.Parameter.VoiceInParameter; using Ryujinx.Audio.Renderer.Parameter;
using WaveBuffer = Ryujinx.Audio.Renderer.Common.WaveBuffer; using WaveBuffer = Ryujinx.Audio.Renderer.Common.WaveBuffer;
namespace Ryujinx.Audio.Renderer.Dsp.Command namespace Ryujinx.Audio.Renderer.Dsp.Command
@@ -11,51 +11,54 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType { get; } public CommandType CommandType { get; private set; }
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
public ushort OutputBufferIndex { get; } public ushort OutputBufferIndex { get; private set; }
public uint SampleRate { get; } public uint SampleRate { get; private set; }
public float Pitch { get; } public float Pitch { get; private set; }
public WaveBuffer[] WaveBuffers { get; } public WaveBuffer[] WaveBuffers { get; }
public Memory<VoiceUpdateState> State { get; } public Memory<VoiceState> State { get; private set; }
public ulong ExtraParameter { get; } public ulong ExtraParameter { get; private set; }
public ulong ExtraParameterSize { get; } public ulong ExtraParameterSize { get; private set; }
public uint ChannelIndex { get; } public uint ChannelIndex { get; private set; }
public uint ChannelCount { get; } public uint ChannelCount { get; private set; }
public DecodingBehaviour DecodingBehaviour { get; } public DecodingBehaviour DecodingBehaviour { get; private set; }
public SampleFormat SampleFormat { get; } public SampleFormat SampleFormat { get; private set; }
public SampleRateConversionQuality SrcQuality { get; } public SampleRateConversionQuality SrcQuality { get; private set; }
public DataSourceVersion2Command(ref VoiceState serverState, Memory<VoiceUpdateState> state, ushort outputBufferIndex, ushort channelIndex, int nodeId) public DataSourceVersion2Command()
{
WaveBuffers = new WaveBuffer[Constants.VoiceWaveBufferCount];
}
public DataSourceVersion2Command Initialize(ref VoiceInfo serverInfo, Memory<VoiceState> state, ushort outputBufferIndex, ushort channelIndex, int nodeId)
{ {
Enabled = true; Enabled = true;
NodeId = nodeId; NodeId = nodeId;
ChannelIndex = channelIndex; ChannelIndex = channelIndex;
ChannelCount = serverState.ChannelsCount; ChannelCount = serverInfo.ChannelsCount;
SampleFormat = serverState.SampleFormat; SampleFormat = serverInfo.SampleFormat;
SrcQuality = serverState.SrcQuality; SrcQuality = serverInfo.SrcQuality;
CommandType = GetCommandTypeBySampleFormat(SampleFormat); CommandType = GetCommandTypeBySampleFormat(SampleFormat);
OutputBufferIndex = (ushort)(channelIndex + outputBufferIndex); OutputBufferIndex = (ushort)(channelIndex + outputBufferIndex);
SampleRate = serverState.SampleRate; SampleRate = serverInfo.SampleRate;
Pitch = serverState.Pitch; Pitch = serverInfo.Pitch;
Span<Server.Voice.WaveBuffer> waveBufferSpan = serverState.WaveBuffers.AsSpan(); Span<Server.Voice.WaveBuffer> waveBufferSpan = serverInfo.WaveBuffers.AsSpan();
WaveBuffers = new WaveBuffer[Constants.VoiceWaveBufferCount];
for (int i = 0; i < WaveBuffers.Length; i++) for (int i = 0; i < WaveBuffers.Length; i++)
{ {
@@ -66,12 +69,14 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
if (SampleFormat == SampleFormat.Adpcm) if (SampleFormat == SampleFormat.Adpcm)
{ {
ExtraParameter = serverState.DataSourceStateAddressInfo.GetReference(true); ExtraParameter = serverInfo.DataSourceStateAddressInfo.GetReference(true);
ExtraParameterSize = serverState.DataSourceStateAddressInfo.Size; ExtraParameterSize = serverInfo.DataSourceStateAddressInfo.Size;
} }
State = state; State = state;
DecodingBehaviour = serverState.DecodingBehaviour; DecodingBehaviour = serverInfo.DecodingBehaviour;
return this;
} }
private static CommandType GetCommandTypeBySampleFormat(SampleFormat sampleFormat) private static CommandType GetCommandTypeBySampleFormat(SampleFormat sampleFormat)

View File

@@ -13,24 +13,30 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.Delay; public CommandType CommandType => CommandType.Delay;
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
public DelayParameter Parameter => _parameter; public DelayParameter Parameter => _parameter;
public Memory<DelayState> State { get; } public Memory<DelayState> State { get; private set; }
public ulong WorkBuffer { get; } public ulong WorkBuffer { get; private set; }
public ushort[] OutputBufferIndices { get; } public ushort[] OutputBufferIndices { get; }
public ushort[] InputBufferIndices { get; } public ushort[] InputBufferIndices { get; }
public bool IsEffectEnabled { get; } public bool IsEffectEnabled { get; private set; }
private DelayParameter _parameter; private DelayParameter _parameter;
private const int FixedPointPrecision = 14; private const int FixedPointPrecision = 14;
public DelayCommand(uint bufferOffset, DelayParameter parameter, Memory<DelayState> state, bool isEnabled, ulong workBuffer, int nodeId, bool newEffectChannelMappingSupported) public DelayCommand()
{
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
}
public DelayCommand Initialize(uint bufferOffset, DelayParameter parameter, Memory<DelayState> state, bool isEnabled, ulong workBuffer, int nodeId, bool newEffectChannelMappingSupported)
{ {
Enabled = true; Enabled = true;
NodeId = nodeId; NodeId = nodeId;
@@ -39,9 +45,6 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
WorkBuffer = workBuffer; WorkBuffer = workBuffer;
IsEffectEnabled = isEnabled; IsEffectEnabled = isEnabled;
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
Span<byte> inputSpan = Parameter.Input.AsSpan(); Span<byte> inputSpan = Parameter.Input.AsSpan();
Span<byte> outputSpan = Parameter.Output.AsSpan(); Span<byte> outputSpan = Parameter.Output.AsSpan();
@@ -54,6 +57,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
DataSourceHelper.RemapLegacyChannelEffectMappingToChannelResourceMapping(newEffectChannelMappingSupported, InputBufferIndices, Parameter.ChannelCount); DataSourceHelper.RemapLegacyChannelEffectMappingToChannelResourceMapping(newEffectChannelMappingSupported, InputBufferIndices, Parameter.ChannelCount);
DataSourceHelper.RemapLegacyChannelEffectMappingToChannelResourceMapping(newEffectChannelMappingSupported, OutputBufferIndices, Parameter.ChannelCount); DataSourceHelper.RemapLegacyChannelEffectMappingToChannelResourceMapping(newEffectChannelMappingSupported, OutputBufferIndices, Parameter.ChannelCount);
return this;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]

View File

@@ -7,21 +7,26 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.DepopForMixBuffers; public CommandType CommandType => CommandType.DepopForMixBuffers;
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
public uint MixBufferOffset { get; } public uint MixBufferOffset { get; private set; }
public uint MixBufferCount { get; } public uint MixBufferCount { get; private set; }
public float Decay { get; } public float Decay { get; private set; }
public Memory<float> DepopBuffer { get; } public Memory<float> DepopBuffer { get; private set; }
public DepopForMixBuffersCommand(Memory<float> depopBuffer, uint bufferOffset, uint mixBufferCount, int nodeId, uint sampleRate) public DepopForMixBuffersCommand()
{
}
public DepopForMixBuffersCommand Initialize(Memory<float> depopBuffer, uint bufferOffset, uint mixBufferCount, int nodeId, uint sampleRate)
{ {
Enabled = true; Enabled = true;
NodeId = nodeId; NodeId = nodeId;
@@ -37,6 +42,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
Decay = 0.943695f; Decay = 0.943695f;
} }
return this;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]

View File

@@ -7,27 +7,30 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.DepopPrepare; public CommandType CommandType => CommandType.DepopPrepare;
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
public uint MixBufferCount { get; } public uint MixBufferCount { get; private set; }
public ushort[] OutputBufferIndices { get; } public ushort[] OutputBufferIndices { get; }
public Memory<VoiceUpdateState> State { get; } public Memory<VoiceState> State { get; private set; }
public Memory<float> DepopBuffer { get; } public Memory<float> DepopBuffer { get; private set; }
public DepopPrepareCommand(Memory<VoiceUpdateState> state, Memory<float> depopBuffer, uint mixBufferCount, uint bufferOffset, int nodeId, bool enabled) public DepopPrepareCommand()
{
OutputBufferIndices = new ushort[Constants.MixBufferCountMax];
}
public DepopPrepareCommand Initialize(Memory<VoiceState> state, Memory<float> depopBuffer, uint mixBufferCount, uint bufferOffset, int nodeId, bool enabled)
{ {
Enabled = enabled; Enabled = enabled;
NodeId = nodeId; NodeId = nodeId;
MixBufferCount = mixBufferCount; MixBufferCount = mixBufferCount;
OutputBufferIndices = new ushort[Constants.MixBufferCountMax];
for (int i = 0; i < Constants.MixBufferCountMax; i++) for (int i = 0; i < Constants.MixBufferCountMax; i++)
{ {
OutputBufferIndices[i] = (ushort)(bufferOffset + i); OutputBufferIndices[i] = (ushort)(bufferOffset + i);
@@ -35,11 +38,13 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
State = state; State = state;
DepopBuffer = depopBuffer; DepopBuffer = depopBuffer;
return this;
} }
public void Process(CommandList context) public void Process(CommandList context)
{ {
ref VoiceUpdateState state = ref State.Span[0]; ref VoiceState state = ref State.Span[0];
Span<float> depopBuffer = DepopBuffer.Span; Span<float> depopBuffer = DepopBuffer.Span;
Span<float> lastSamplesSpan = state.LastSamples.AsSpan(); Span<float> lastSamplesSpan = state.LastSamples.AsSpan();

View File

@@ -1,6 +1,7 @@
using Ryujinx.Audio.Integration; using Ryujinx.Audio.Integration;
using Ryujinx.Audio.Renderer.Server.Sink; using Ryujinx.Audio.Renderer.Server.Sink;
using System; using System;
using System.Buffers;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Text; using System.Text;
@@ -10,27 +11,34 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.DeviceSink; public CommandType CommandType => CommandType.DeviceSink;
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
public string DeviceName { get; } public string DeviceName { get; private set; }
public int SessionId { get; } public int SessionId { get; private set; }
public uint InputCount { get; } public uint InputCount { get; private set; }
public ushort[] InputBufferIndices { get; } public ushort[] InputBufferIndices { get; private set; }
public Memory<float> Buffers { get; } public Memory<float> Buffers { get; private set; }
public DeviceSinkCommand(uint bufferOffset, DeviceSink sink, int sessionId, Memory<float> buffers, int nodeId) public DeviceSinkCommand()
{
}
public DeviceSinkCommand Initialize(uint bufferOffset, DeviceSink sink, int sessionId, Memory<float> buffers, int nodeId)
{ {
Enabled = true; Enabled = true;
NodeId = nodeId; NodeId = nodeId;
DeviceName = Encoding.ASCII.GetString(sink.Parameter.DeviceName).TrimEnd('\0'); // Unused and wasting time and memory, re-add if needed
// DeviceName = Encoding.ASCII.GetString(sink.Parameter.DeviceName).TrimEnd('\0');
SessionId = sessionId; SessionId = sessionId;
InputCount = sink.Parameter.InputCount; InputCount = sink.Parameter.InputCount;
InputBufferIndices = new ushort[InputCount]; InputBufferIndices = new ushort[InputCount];
@@ -42,14 +50,16 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
InputBufferIndices[i] = (ushort)(bufferOffset + inputSpan[i]); InputBufferIndices[i] = (ushort)(bufferOffset + inputSpan[i]);
} }
if (sink.UpsamplerState != null) if (sink.UpsamplerInfo != null)
{ {
Buffers = sink.UpsamplerState.OutputBuffer; Buffers = sink.UpsamplerInfo.OutputBuffer;
} }
else else
{ {
Buffers = buffers; Buffers = buffers;
} }
return this;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -81,7 +91,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
inputCount = bufferCount; inputCount = bufferCount;
} }
short[] outputBuffer = new short[inputCount * SampleCount]; short[] outputBuffer = ArrayPool<short>.Shared.Rent((int)inputCount * SampleCount);
for (int i = 0; i < bufferCount; i++) for (int i = 0; i < bufferCount; i++)
{ {
@@ -93,7 +103,9 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
} }
} }
device.AppendBuffer(outputBuffer, inputCount); device.AppendBuffer(outputBuffer.AsSpan(..((int)inputCount * SampleCount)), inputCount);
ArrayPool<short>.Shared.Return(outputBuffer);
} }
else else
{ {

View File

@@ -7,7 +7,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.DownMixSurroundToStereo; public CommandType CommandType => CommandType.DownMixSurroundToStereo;
@@ -16,16 +16,19 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
public ushort[] InputBufferIndices { get; } public ushort[] InputBufferIndices { get; }
public ushort[] OutputBufferIndices { get; } public ushort[] OutputBufferIndices { get; }
public float[] Coefficients { get; } public float[] Coefficients { get; private set; }
public DownMixSurroundToStereoCommand(uint bufferOffset, Span<byte> inputBufferOffset, Span<byte> outputBufferOffset, float[] downMixParameter, int nodeId) public DownMixSurroundToStereoCommand()
{
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
}
public DownMixSurroundToStereoCommand Initialize(uint bufferOffset, Span<byte> inputBufferOffset, Span<byte> outputBufferOffset, float[] downMixParameter, int nodeId)
{ {
Enabled = true; Enabled = true;
NodeId = nodeId; NodeId = nodeId;
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
for (int i = 0; i < Constants.VoiceChannelCountMax; i++) for (int i = 0; i < Constants.VoiceChannelCountMax; i++)
{ {
InputBufferIndices[i] = (ushort)(bufferOffset + inputBufferOffset[i]); InputBufferIndices[i] = (ushort)(bufferOffset + inputBufferOffset[i]);
@@ -33,6 +36,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
} }
Coefficients = downMixParameter; Coefficients = downMixParameter;
return this;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]

View File

@@ -0,0 +1,73 @@
using Ryujinx.Audio.Renderer.Server.Splitter;
using System.Runtime.CompilerServices;
namespace Ryujinx.Audio.Renderer.Dsp.Command
{
public class FillBufferCommand : ICommand
{
public bool Enabled { get; set; }
public int NodeId { get; private set; }
public CommandType CommandType => CommandType.FillBuffer;
public uint EstimatedProcessingTime { get; set; }
public SplitterDestinationVersion1 Destination1 { get; private set; }
public SplitterDestinationVersion2 Destination2 { get; private set; }
public bool IsV2 { get; private set; }
public int Length { get; private set; }
public float Value { get; private set; }
public FillBufferCommand()
{
}
public FillBufferCommand Initialize(SplitterDestination destination, int length, float value, int nodeId)
{
Enabled = true;
NodeId = nodeId;
if (Unsafe.IsNullRef(ref destination.GetV2RefOrNull()))
{
Destination1 = destination.GetV1RefOrNull();
IsV2 = false;
}
else
{
Destination2 = destination.GetV2RefOrNull();
IsV2 = true;
}
Length = length;
Value = value;
return this;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void ProcessFillBuffer()
{
if (IsV2)
{
for (int i = 0; i < Length; i++)
{
Destination2.PreviousMixBufferVolume[i] = Value;
}
}
else
{
for (int i = 0; i < Length; i++)
{
Destination1.PreviousMixBufferVolume[i] = Value;
}
}
}
public void Process(CommandList context)
{
ProcessFillBuffer();
}
}
}

View File

@@ -10,22 +10,28 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.LimiterVersion1; public CommandType CommandType => CommandType.LimiterVersion1;
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
public LimiterParameter Parameter => _parameter; public LimiterParameter Parameter => _parameter;
public Memory<LimiterState> State { get; } public Memory<LimiterState> State { get; private set; }
public ulong WorkBuffer { get; } public ulong WorkBuffer { get; private set; }
public ushort[] OutputBufferIndices { get; } public ushort[] OutputBufferIndices { get; }
public ushort[] InputBufferIndices { get; } public ushort[] InputBufferIndices { get; }
public bool IsEffectEnabled { get; } public bool IsEffectEnabled { get; private set; }
private LimiterParameter _parameter; private LimiterParameter _parameter;
public LimiterCommandVersion1(uint bufferOffset, LimiterParameter parameter, Memory<LimiterState> state, bool isEnabled, ulong workBuffer, int nodeId) public LimiterCommandVersion1()
{
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
}
public LimiterCommandVersion1 Initialize(uint bufferOffset, LimiterParameter parameter, Memory<LimiterState> state, bool isEnabled, ulong workBuffer, int nodeId)
{ {
Enabled = true; Enabled = true;
NodeId = nodeId; NodeId = nodeId;
@@ -35,9 +41,6 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
IsEffectEnabled = isEnabled; IsEffectEnabled = isEnabled;
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
Span<byte> inputSpan = _parameter.Input.AsSpan(); Span<byte> inputSpan = _parameter.Input.AsSpan();
Span<byte> outputSpan = _parameter.Output.AsSpan(); Span<byte> outputSpan = _parameter.Output.AsSpan();
@@ -46,6 +49,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
InputBufferIndices[i] = (ushort)(bufferOffset + inputSpan[i]); InputBufferIndices[i] = (ushort)(bufferOffset + inputSpan[i]);
OutputBufferIndices[i] = (ushort)(bufferOffset + outputSpan[i]); OutputBufferIndices[i] = (ushort)(bufferOffset + outputSpan[i]);
} }
return this;
} }
public void Process(CommandList context) public void Process(CommandList context)

View File

@@ -12,23 +12,29 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.LimiterVersion2; public CommandType CommandType => CommandType.LimiterVersion2;
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
public LimiterParameter Parameter => _parameter; public LimiterParameter Parameter => _parameter;
public Memory<LimiterState> State { get; } public Memory<LimiterState> State { get; private set; }
public Memory<EffectResultState> ResultState { get; } public Memory<EffectResultState> ResultState { get; private set; }
public ulong WorkBuffer { get; } public ulong WorkBuffer { get; private set; }
public ushort[] OutputBufferIndices { get; } public ushort[] OutputBufferIndices { get; }
public ushort[] InputBufferIndices { get; } public ushort[] InputBufferIndices { get; }
public bool IsEffectEnabled { get; } public bool IsEffectEnabled { get; private set; }
private LimiterParameter _parameter; private LimiterParameter _parameter;
public LimiterCommandVersion2( public LimiterCommandVersion2()
{
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
}
public LimiterCommandVersion2 Initialize(
uint bufferOffset, uint bufferOffset,
LimiterParameter parameter, LimiterParameter parameter,
Memory<LimiterState> state, Memory<LimiterState> state,
@@ -45,9 +51,6 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
WorkBuffer = workBuffer; WorkBuffer = workBuffer;
IsEffectEnabled = isEnabled; IsEffectEnabled = isEnabled;
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
Span<byte> inputSpan = _parameter.Input.AsSpan(); Span<byte> inputSpan = _parameter.Input.AsSpan();
Span<byte> outputSpan = _parameter.Output.AsSpan(); Span<byte> outputSpan = _parameter.Output.AsSpan();
@@ -57,6 +60,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
InputBufferIndices[i] = (ushort)(bufferOffset + inputSpan[i]); InputBufferIndices[i] = (ushort)(bufferOffset + inputSpan[i]);
OutputBufferIndices[i] = (ushort)(bufferOffset + outputSpan[i]); OutputBufferIndices[i] = (ushort)(bufferOffset + outputSpan[i]);
} }
return this;
} }
public void Process(CommandList context) public void Process(CommandList context)

View File

@@ -11,18 +11,23 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.Mix; public CommandType CommandType => CommandType.Mix;
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
public ushort InputBufferIndex { get; } public ushort InputBufferIndex { get; private set; }
public ushort OutputBufferIndex { get; } public ushort OutputBufferIndex { get; private set; }
public float Volume { get; } public float Volume { get; private set; }
public MixCommand(uint inputBufferIndex, uint outputBufferIndex, int nodeId, float volume) public MixCommand()
{
}
public MixCommand Initialize(uint inputBufferIndex, uint outputBufferIndex, int nodeId, float volume)
{ {
Enabled = true; Enabled = true;
NodeId = nodeId; NodeId = nodeId;
@@ -31,6 +36,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
OutputBufferIndex = (ushort)outputBufferIndex; OutputBufferIndex = (ushort)outputBufferIndex;
Volume = volume; Volume = volume;
return this;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]

View File

@@ -8,23 +8,28 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.MixRamp; public CommandType CommandType => CommandType.MixRamp;
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
public ushort InputBufferIndex { get; } public ushort InputBufferIndex { get; private set; }
public ushort OutputBufferIndex { get; } public ushort OutputBufferIndex { get; private set; }
public float Volume0 { get; } public float Volume0 { get; private set; }
public float Volume1 { get; } public float Volume1 { get; private set; }
public Memory<VoiceUpdateState> State { get; } public Memory<VoiceState> State { get; private set; }
public int LastSampleIndex { get; } public int LastSampleIndex { get; private set; }
public MixRampCommand(float volume0, float volume1, uint inputBufferIndex, uint outputBufferIndex, int lastSampleIndex, Memory<VoiceUpdateState> state, int nodeId) public MixRampCommand()
{
}
public MixRampCommand Initialize(float volume0, float volume1, uint inputBufferIndex, uint outputBufferIndex, int lastSampleIndex, Memory<VoiceState> state, int nodeId)
{ {
Enabled = true; Enabled = true;
NodeId = nodeId; NodeId = nodeId;
@@ -37,6 +42,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
State = state; State = state;
LastSampleIndex = lastSampleIndex; LastSampleIndex = lastSampleIndex;
return this;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]

View File

@@ -8,29 +8,34 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.MixRampGrouped; public CommandType CommandType => CommandType.MixRampGrouped;
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
public uint MixBufferCount { get; } public uint MixBufferCount { get; private set; }
public ushort[] InputBufferIndices { get; } public ushort[] InputBufferIndices { get; private set; }
public ushort[] OutputBufferIndices { get; } public ushort[] OutputBufferIndices { get; private set; }
public float[] Volume0 { get; } public float[] Volume0 { get; private set; }
public float[] Volume1 { get; } public float[] Volume1 { get; private set; }
public Memory<VoiceUpdateState> State { get; } public Memory<VoiceState> State { get; private set; }
public MixRampGroupedCommand( public MixRampGroupedCommand()
{
}
public MixRampGroupedCommand Initialize(
uint mixBufferCount, uint mixBufferCount,
uint inputBufferIndex, uint inputBufferIndex,
uint outputBufferIndex, uint outputBufferIndex,
ReadOnlySpan<float> volume0, ReadOnlySpan<float> volume0,
ReadOnlySpan<float> volume1, ReadOnlySpan<float> volume1,
Memory<VoiceUpdateState> state, Memory<VoiceState> state,
int nodeId) int nodeId)
{ {
Enabled = true; Enabled = true;
@@ -52,6 +57,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
} }
State = state; State = state;
return this;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -79,7 +86,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
public void Process(CommandList context) public void Process(CommandList context)
{ {
ref VoiceUpdateState state = ref State.Span[0]; ref VoiceState state = ref State.Span[0];
Span<float> lastSamplesSpan = state.LastSamples.AsSpan(); Span<float> lastSamplesSpan = state.LastSamples.AsSpan();

View File

@@ -9,44 +9,49 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.MultiTapBiquadFilterAndMix; public CommandType CommandType => CommandType.MultiTapBiquadFilterAndMix;
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
public ushort InputBufferIndex { get; } public ushort InputBufferIndex { get; private set; }
public ushort OutputBufferIndex { get; } public ushort OutputBufferIndex { get; private set; }
private BiquadFilterParameter _parameter0; private BiquadFilterParameter2 _parameter0;
private BiquadFilterParameter _parameter1; private BiquadFilterParameter2 _parameter1;
public Memory<BiquadFilterState> BiquadFilterState0 { get; } public Memory<BiquadFilterState> BiquadFilterState0 { get; private set; }
public Memory<BiquadFilterState> BiquadFilterState1 { get; } public Memory<BiquadFilterState> BiquadFilterState1 { get; private set; }
public Memory<BiquadFilterState> PreviousBiquadFilterState0 { get; } public Memory<BiquadFilterState> PreviousBiquadFilterState0 { get; private set; }
public Memory<BiquadFilterState> PreviousBiquadFilterState1 { get; } public Memory<BiquadFilterState> PreviousBiquadFilterState1 { get; private set; }
public Memory<VoiceUpdateState> State { get; } public Memory<VoiceState> State { get; private set; }
public int LastSampleIndex { get; } public int LastSampleIndex { get; private set; }
public float Volume0 { get; } public float Volume0 { get; private set; }
public float Volume1 { get; } public float Volume1 { get; private set; }
public bool NeedInitialization0 { get; } public bool NeedInitialization0 { get; private set; }
public bool NeedInitialization1 { get; } public bool NeedInitialization1 { get; private set; }
public bool HasVolumeRamp { get; } public bool HasVolumeRamp { get; private set; }
public bool IsFirstMixBuffer { get; } public bool IsFirstMixBuffer { get; private set; }
public MultiTapBiquadFilterAndMixCommand( public MultiTapBiquadFilterAndMixCommand()
{
}
public MultiTapBiquadFilterAndMixCommand Initialize(
float volume0, float volume0,
float volume1, float volume1,
uint inputBufferIndex, uint inputBufferIndex,
uint outputBufferIndex, uint outputBufferIndex,
int lastSampleIndex, int lastSampleIndex,
Memory<VoiceUpdateState> state, Memory<VoiceState> state,
ref BiquadFilterParameter filter0, ref BiquadFilterParameter2 filter0,
ref BiquadFilterParameter filter1, ref BiquadFilterParameter2 filter1,
Memory<BiquadFilterState> biquadFilterState0, Memory<BiquadFilterState> biquadFilterState0,
Memory<BiquadFilterState> biquadFilterState1, Memory<BiquadFilterState> biquadFilterState1,
Memory<BiquadFilterState> previousBiquadFilterState0, Memory<BiquadFilterState> previousBiquadFilterState0,
@@ -80,6 +85,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
NeedInitialization1 = needInitialization1; NeedInitialization1 = needInitialization1;
HasVolumeRamp = hasVolumeRamp; HasVolumeRamp = hasVolumeRamp;
IsFirstMixBuffer = isFirstMixBuffer; IsFirstMixBuffer = isFirstMixBuffer;
return this;
} }
private void UpdateState(Memory<BiquadFilterState> state, Memory<BiquadFilterState> previousState, bool needInitialization) private void UpdateState(Memory<BiquadFilterState> state, Memory<BiquadFilterState> previousState, bool needInitialization)

View File

@@ -8,40 +8,47 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.MultiTapBiquadFilter; public CommandType CommandType => CommandType.MultiTapBiquadFilter;
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
private readonly BiquadFilterParameter[] _parameters; public BiquadFilterParameter2[] Parameters { get; private set; }
private readonly Memory<BiquadFilterState> _biquadFilterStates; public Memory<BiquadFilterState> BiquadFilterStates { get; private set; }
private readonly int _inputBufferIndex; public int InputBufferIndex { get; private set; }
private readonly int _outputBufferIndex; public int OutputBufferIndex { get; private set; }
private readonly bool[] _isInitialized; public bool[] IsInitialized { get; private set; }
public MultiTapBiquadFilterCommand(int baseIndex, ReadOnlySpan<BiquadFilterParameter> filters, Memory<BiquadFilterState> biquadFilterStateMemory, int inputBufferOffset, int outputBufferOffset, ReadOnlySpan<bool> isInitialized, int nodeId) public MultiTapBiquadFilterCommand()
{ {
_parameters = filters.ToArray();
_biquadFilterStates = biquadFilterStateMemory; }
_inputBufferIndex = baseIndex + inputBufferOffset;
_outputBufferIndex = baseIndex + outputBufferOffset; public MultiTapBiquadFilterCommand Initialize(int baseIndex, ReadOnlySpan<BiquadFilterParameter2> filters, Memory<BiquadFilterState> biquadFilterStateMemory, int inputBufferOffset, int outputBufferOffset, ReadOnlySpan<bool> isInitialized, int nodeId)
_isInitialized = isInitialized.ToArray(); {
Parameters = filters.ToArray();
BiquadFilterStates = biquadFilterStateMemory;
InputBufferIndex = baseIndex + inputBufferOffset;
OutputBufferIndex = baseIndex + outputBufferOffset;
IsInitialized = isInitialized.ToArray();
Enabled = true; Enabled = true;
NodeId = nodeId; NodeId = nodeId;
return this;
} }
public void Process(CommandList context) public void Process(CommandList context)
{ {
Span<BiquadFilterState> states = _biquadFilterStates.Span; Span<BiquadFilterState> states = BiquadFilterStates.Span;
ReadOnlySpan<float> inputBuffer = context.GetBuffer(_inputBufferIndex); ReadOnlySpan<float> inputBuffer = context.GetBuffer(InputBufferIndex);
Span<float> outputBuffer = context.GetBuffer(_outputBufferIndex); Span<float> outputBuffer = context.GetBuffer(OutputBufferIndex);
for (int i = 0; i < _parameters.Length; i++) for (int i = 0; i < Parameters.Length; i++)
{ {
if (!_isInitialized[i]) if (!IsInitialized[i])
{ {
states[i] = new BiquadFilterState(); states[i] = new BiquadFilterState();
} }
@@ -49,13 +56,13 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
// NOTE: Nintendo only implement single and double biquad filters but no generic path when the command definition suggests it could be done. // NOTE: Nintendo only implement single and double biquad filters but no generic path when the command definition suggests it could be done.
// As such we currently only implement a generic path for simplicity for double biquad. // As such we currently only implement a generic path for simplicity for double biquad.
if (_parameters.Length == 1) if (Parameters.Length == 1)
{ {
BiquadFilterHelper.ProcessBiquadFilter(ref _parameters[0], ref states[0], outputBuffer, inputBuffer, context.SampleCount); BiquadFilterHelper.ProcessBiquadFilter(ref Parameters[0], ref states[0], outputBuffer, inputBuffer, context.SampleCount);
} }
else else
{ {
BiquadFilterHelper.ProcessBiquadFilter(_parameters, states, outputBuffer, inputBuffer, context.SampleCount); BiquadFilterHelper.ProcessBiquadFilter(Parameters, states, outputBuffer, inputBuffer, context.SampleCount);
} }
} }
} }

View File

@@ -2,7 +2,7 @@ using Ryujinx.Audio.Common;
using Ryujinx.Audio.Renderer.Common; using Ryujinx.Audio.Renderer.Common;
using Ryujinx.Audio.Renderer.Server.Voice; using Ryujinx.Audio.Renderer.Server.Voice;
using System; using System;
using static Ryujinx.Audio.Renderer.Parameter.VoiceInParameter; using Ryujinx.Audio.Renderer.Parameter;
using WaveBuffer = Ryujinx.Audio.Renderer.Common.WaveBuffer; using WaveBuffer = Ryujinx.Audio.Renderer.Common.WaveBuffer;
namespace Ryujinx.Audio.Renderer.Dsp.Command namespace Ryujinx.Audio.Renderer.Dsp.Command
@@ -11,39 +11,42 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.PcmFloatDataSourceVersion1; public CommandType CommandType => CommandType.PcmFloatDataSourceVersion1;
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
public ushort OutputBufferIndex { get; } public ushort OutputBufferIndex { get; private set; }
public uint SampleRate { get; } public uint SampleRate { get; private set; }
public uint ChannelIndex { get; } public uint ChannelIndex { get; private set; }
public uint ChannelCount { get; } public uint ChannelCount { get; private set; }
public float Pitch { get; } public float Pitch { get; private set; }
public WaveBuffer[] WaveBuffers { get; } public WaveBuffer[] WaveBuffers { get; }
public Memory<VoiceUpdateState> State { get; } public Memory<VoiceState> State { get; private set; }
public DecodingBehaviour DecodingBehaviour { get; } public DecodingBehaviour DecodingBehaviour { get; private set; }
public PcmFloatDataSourceCommandVersion1(ref VoiceState serverState, Memory<VoiceUpdateState> state, ushort outputBufferIndex, ushort channelIndex, int nodeId) public PcmFloatDataSourceCommandVersion1()
{
WaveBuffers = new WaveBuffer[Constants.VoiceWaveBufferCount];
}
public PcmFloatDataSourceCommandVersion1 Initialize(ref VoiceInfo serverInfo, Memory<VoiceState> state, ushort outputBufferIndex, ushort channelIndex, int nodeId)
{ {
Enabled = true; Enabled = true;
NodeId = nodeId; NodeId = nodeId;
OutputBufferIndex = (ushort)(channelIndex + outputBufferIndex); OutputBufferIndex = (ushort)(channelIndex + outputBufferIndex);
SampleRate = serverState.SampleRate; SampleRate = serverInfo.SampleRate;
ChannelIndex = channelIndex; ChannelIndex = channelIndex;
ChannelCount = serverState.ChannelsCount; ChannelCount = serverInfo.ChannelsCount;
Pitch = serverState.Pitch; Pitch = serverInfo.Pitch;
WaveBuffers = new WaveBuffer[Constants.VoiceWaveBufferCount];
Span<Server.Voice.WaveBuffer> waveBufferSpan = serverState.WaveBuffers.AsSpan(); Span<Server.Voice.WaveBuffer> waveBufferSpan = serverInfo.WaveBuffers.AsSpan();
for (int i = 0; i < WaveBuffers.Length; i++) for (int i = 0; i < WaveBuffers.Length; i++)
{ {
@@ -53,7 +56,9 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
} }
State = state; State = state;
DecodingBehaviour = serverState.DecodingBehaviour; DecodingBehaviour = serverInfo.DecodingBehaviour;
return this;
} }
public void Process(CommandList context) public void Process(CommandList context)

View File

@@ -2,7 +2,7 @@ using Ryujinx.Audio.Common;
using Ryujinx.Audio.Renderer.Common; using Ryujinx.Audio.Renderer.Common;
using Ryujinx.Audio.Renderer.Server.Voice; using Ryujinx.Audio.Renderer.Server.Voice;
using System; using System;
using static Ryujinx.Audio.Renderer.Parameter.VoiceInParameter; using Ryujinx.Audio.Renderer.Parameter;
using WaveBuffer = Ryujinx.Audio.Renderer.Common.WaveBuffer; using WaveBuffer = Ryujinx.Audio.Renderer.Common.WaveBuffer;
namespace Ryujinx.Audio.Renderer.Dsp.Command namespace Ryujinx.Audio.Renderer.Dsp.Command
@@ -11,39 +11,42 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.PcmInt16DataSourceVersion1; public CommandType CommandType => CommandType.PcmInt16DataSourceVersion1;
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
public ushort OutputBufferIndex { get; } public ushort OutputBufferIndex { get; private set; }
public uint SampleRate { get; } public uint SampleRate { get; private set; }
public uint ChannelIndex { get; } public uint ChannelIndex { get; private set; }
public uint ChannelCount { get; } public uint ChannelCount { get; private set; }
public float Pitch { get; } public float Pitch { get; private set; }
public WaveBuffer[] WaveBuffers { get; } public WaveBuffer[] WaveBuffers { get; }
public Memory<VoiceUpdateState> State { get; } public Memory<VoiceState> State { get; private set; }
public DecodingBehaviour DecodingBehaviour { get; } public DecodingBehaviour DecodingBehaviour { get; private set; }
public PcmInt16DataSourceCommandVersion1(ref VoiceState serverState, Memory<VoiceUpdateState> state, ushort outputBufferIndex, ushort channelIndex, int nodeId) public PcmInt16DataSourceCommandVersion1()
{
WaveBuffers = new WaveBuffer[Constants.VoiceWaveBufferCount];
}
public PcmInt16DataSourceCommandVersion1 Initialize(ref VoiceInfo serverInfo, Memory<VoiceState> state, ushort outputBufferIndex, ushort channelIndex, int nodeId)
{ {
Enabled = true; Enabled = true;
NodeId = nodeId; NodeId = nodeId;
OutputBufferIndex = (ushort)(channelIndex + outputBufferIndex); OutputBufferIndex = (ushort)(channelIndex + outputBufferIndex);
SampleRate = serverState.SampleRate; SampleRate = serverInfo.SampleRate;
ChannelIndex = channelIndex; ChannelIndex = channelIndex;
ChannelCount = serverState.ChannelsCount; ChannelCount = serverInfo.ChannelsCount;
Pitch = serverState.Pitch; Pitch = serverInfo.Pitch;
WaveBuffers = new WaveBuffer[Constants.VoiceWaveBufferCount];
Span<Server.Voice.WaveBuffer> waveBufferSpan = serverState.WaveBuffers.AsSpan(); Span<Server.Voice.WaveBuffer> waveBufferSpan = serverInfo.WaveBuffers.AsSpan();
for (int i = 0; i < WaveBuffers.Length; i++) for (int i = 0; i < WaveBuffers.Length; i++)
{ {
@@ -53,7 +56,9 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
} }
State = state; State = state;
DecodingBehaviour = serverState.DecodingBehaviour; DecodingBehaviour = serverInfo.DecodingBehaviour;
return this;
} }
public void Process(CommandList context) public void Process(CommandList context)

View File

@@ -13,22 +13,34 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.Performance; public CommandType CommandType => CommandType.Performance;
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
public PerformanceEntryAddresses PerformanceEntryAddresses { get; } public PerformanceEntryAddresses PerformanceEntryAddresses { get; private set; }
public Type PerformanceType { get; set; } public Type PerformanceType { get; set; }
public PerformanceCommand(ref PerformanceEntryAddresses performanceEntryAddresses, Type performanceType, int nodeId) public PerformanceCommand()
{ {
}
public PerformanceCommand Initialize(ref PerformanceEntryAddresses performanceEntryAddresses, Type performanceType, int nodeId)
{
if (PerformanceEntryAddresses is not null)
{
PerformanceEntryAddresses.PerformanceEntryAddressesPool.Release(PerformanceEntryAddresses);
}
Enabled = true; Enabled = true;
PerformanceEntryAddresses = performanceEntryAddresses; PerformanceEntryAddresses = performanceEntryAddresses;
PerformanceType = performanceType; PerformanceType = performanceType;
NodeId = nodeId; NodeId = nodeId;
return this;
} }
public void Process(CommandList context) public void Process(CommandList context)

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