Compare commits

...

64 Commits

Author SHA1 Message Date
Evan Husted
8bfcebebf1 Merge remote-tracking branch 'origin/master' 2025-01-25 22:44:26 -06:00
Evan Husted
e3f20abd23 UI: RPC: Maintain game started timestamp for the duration of the AppHost 2025-01-25 22:44:16 -06:00
Daenorth
0c36bcd7d4 Added more titles to RPC (#569)
Added some more titles to the RPC environment

-Brawlhalla
-Minecraft
-Risk
-Stardew Vallet
-Valkyria Chronicles 4
-Super bomberman R
-Arcade archives Super mario bros
-Divinity Original sin 2 DE
-Monopoly
-titan Quest
2025-01-25 22:02:24 -06:00
shinyoyo
050b9a0da4 Updated Zh_CN Simplified Chinese (#578) 2025-01-25 21:59:20 -06:00
Dehunc
a1291f1061 Improved Simplified Chinese translation (#568)
Co-authored-by: Cwood <Cwood@DoVirt.org>
2025-01-25 21:59:06 -06:00
Otozinclus
f15aa8fba0 Fix LED turning on in input settings, despite TurnOffLed being set to true (#583)
The ColorPicker auotmatically sets the LED to the selected Color
whenever the Input Settings are opened. Therefore it now checks if the
setting is turned off before changing the color.
2025-01-25 17:15:17 -06:00
Evan Husted
250acab7a7 misc: chore: Use explicit types in Tests projects 2025-01-25 14:15:47 -06:00
Evan Husted
93539e7d45 misc: chore: Use explicit types in GAL 2025-01-25 14:14:40 -06:00
Evan Husted
69e0b79bd9 misc: chore: Use explicit types in Horizon project 2025-01-25 14:14:13 -06:00
Evan Husted
5eba42fa06 misc: chore: Use explicit types in HLE project 2025-01-25 14:13:18 -06:00
Evan Husted
58c1ab7989 misc: chore: Use explicit types in OpenGL project 2025-01-25 14:12:37 -06:00
Evan Husted
2d1a4c3ce5 misc: chore: Use explicit types in Vulkan project 2025-01-25 14:12:17 -06:00
Evan Husted
e6b393e420 misc: chore: Use explicit types in Generator projects 2025-01-25 14:11:46 -06:00
Evan Husted
fe661dc750 misc: chore: Use explicit types in Memory project 2025-01-25 14:09:36 -06:00
Evan Husted
ac401034d7 misc: chore: Use explicit types in input projects 2025-01-25 14:09:05 -06:00
Evan Husted
1712d69dcd misc: chore: Use explicit types in Texture & Vic 2025-01-25 14:08:35 -06:00
Evan Husted
f2aa6b3a5b misc: chore: Use explicit types in Shader project 2025-01-25 14:07:59 -06:00
Evan Husted
68bbb29be6 misc: chore: Use explicit types in NVDEC projects (except VP9 because there's an open PR and I don't want to cause conflicts) 2025-01-25 14:07:20 -06:00
Evan Husted
76ec047eb7 misc: chore: Use explicit types in Metal project 2025-01-25 14:06:26 -06:00
Evan Husted
1ae349efb1 misc: chore: Use explicit types in GPU, Device, and Host1x projects 2025-01-25 14:05:44 -06:00
Evan Husted
5099548856 misc: chore: Use explicit types in CPU project 2025-01-25 14:04:43 -06:00
Evan Husted
a97fd4beb1 misc: chore: Use explicit types in common project 2025-01-25 14:04:12 -06:00
Evan Husted
97188556d8 misc: chore: Use explicit types in audio projects 2025-01-25 14:03:38 -06:00
Evan Husted
e0567c5ce9 misc: chore: Use explicit types in ARMeilleure project 2025-01-25 14:01:13 -06:00
Evan Husted
be3bd0bcb5 misc: chore: Use explicit types in the Avalonia project 2025-01-25 14:00:23 -06:00
Evan Husted
3b5f6170d1 misc: chore: move Rainbow updating to a separate task started/stopped as needed
update gommon & use the Event class from it to allow easily clearing all handlers when the apphost exits to avoid leftover invalid event handlers in the rainbow event handler list.
More robust config application logic to ensure what needs to happen only happens once
2025-01-24 23:06:59 -06:00
Evan Husted
9b6afa0ea2 misc: chore: Add log line to the other parts of the Updater that represent "up to date" 2025-01-24 17:00:50 -06:00
Evan Husted
3541e282ea Fully disconnect gamepad handler for rainbow color if configuration is set with UseRainbowLed false
Also check if its even enabled before setting the rainbow color
Fixes strobing
2025-01-24 16:52:20 -06:00
Otozinclus
1ce37ec317 Add option to change controller LED color (#572)
This allows the user to change the controller LED while using Ryujinx.
Useful for PS4 and PS5 controllers as an example.

You can also use a spectrum-cycling Rainbow color option, or turn the LED off for DualSense controllers.

---------

Co-authored-by: Evan Husted <greem@greemdev.net>
2025-01-24 14:47:36 -06:00
Evan Husted
c06f16c5e6 infra: chore: Raise minimum required Windows 10 version
Inspired by the breakages covered in #409
2025-01-23 17:39:34 -06:00
Evan Husted
7829fd8ee7 misc: chore: OS + CPU arch helpers 2025-01-23 16:58:48 -06:00
Evan Husted
33079422fe misc: chore: code cleanups 2025-01-23 16:47:11 -06:00
Evan Husted
f81cb093fc misc: chore: Change references of GreemDev/Ryujinx to Ryubing/Ryujinx 2025-01-23 16:27:49 -06:00
Evan Husted
dc0c7a2912 infra: clarify how stable builds are made now 2025-01-23 16:27:25 -06:00
Evan Husted
1fbee5a584 infra: Metal label 2025-01-23 14:39:36 -06:00
Evan Husted
c140e9b23c UI: Localize LED color & hide it until it's functional
Also moved IgnoreApplet to the System config section object.
2025-01-23 00:48:42 -06:00
Evan Husted
9c8055440e HLE: TryAdd firmware NCAs 2025-01-22 23:58:11 -06:00
Evan Husted
c03cd50fa3 UI: Add the ability to change a DualSense/DualShock 4's LED color.
Not functional yet. This is the UI & persistence side of #572.
2025-01-22 19:53:39 -06:00
Evan Husted
069f630776 docs: compat: boots: ENDER MAGNOLIA: Bloom in the Mist 2025-01-22 18:00:14 -06:00
Evan Husted
13d411e4de misc: chore: also ToLower the titleID for the OpenShaderDirectory button 2025-01-22 08:54:39 -06:00
Evan Husted
9f53b07491 misc: chore: Fix shader cache & CPU cache being in different folders on non-Windows
fixes #565
2025-01-22 08:52:21 -06:00
Evan Husted
cd8113dadf misc: chore: Collapse adding a game/autoload dir into a single reusable method. 2025-01-21 18:59:56 -06:00
Evan Husted
9089c4ffe5 misc: chore: Multi/Single file/folder picker extensions (for convenience)
The result of these extensions is an empty Optional when the user hits Cancel on the shown file picker.
2025-01-21 18:59:19 -06:00
Evan Husted
fe9d8d05bd UI: Fixed the Amiibo keybind only working when the UI had been updated. 2025-01-21 18:00:51 -06:00
Evan Husted
880a8ae748 misc: chore: Remove duplicated styling blocks in MainMenuBarView in favor of a reusable Avalonia Style. 2025-01-21 17:50:55 -06:00
asfasagag
11531dacb6 UI: Option to automatically Hide UI when game launches (#462)
Quality of life feature
Similar in function to the "Start Games in Fullscreen" toggle
For users who want to run games in windowed/non-fullscreen mode with
menu UI hidden, this eliminates the need to always click "Hide UI"
2025-01-21 17:36:51 -06:00
Evan Husted
3974739ed3 More descriptive classification 2025-01-21 17:35:22 -06:00
Evan Husted
440a3447fb docs: compat: Update South Park: The Fractured but Whole: playable -> boots 2025-01-21 17:10:54 -06:00
Evan Husted
65374ed6cb UI: [ci skip] clarify dirty hacks subtext 2025-01-21 16:57:05 -06:00
Evan Husted
789d6ab959 misc: chore: Improve autoloading DLC/updates logging, deliberately switch to Vulkan if Metal was somehow chosen on a non-mac system, add logger lines in the updater, cleanup enabled logs printing 2025-01-21 14:59:08 -06:00
Evan Husted
182db31343 metal: Added Persona 4 Arena Ultimax to Auto 2025-01-21 14:07:05 -06:00
Evan Husted
ea296b134d Use specific Ubuntu version in build script 2025-01-21 14:05:49 -06:00
Evan Husted
bf584442b2 misc: chore: remove needless call to string.Format 2025-01-21 14:05:49 -06:00
Otozinclus
cb7c294dbf Add more games to metal game list (#558)
Link's awakening I have played through most of the game with 0 issues.

In LEGO City undercover I have played multiple missions and explored the
map, I was unable to spot any issue. Except shadows flickering
sometimes, but that seems to happen on Vulkan and the PC version as well
and is propably normal.

Bayonetta seems to work flawless so far.

In Fast RMX, some tracks have flickering issues, like the second track
of the first cup. This happens on Vulkan as well.

-

Mario Bros. Wonder has following issues:

Overall issues:
- Sometimes there is short white flickering/artifacts, but they happen
on Vulkan as well.

Metal specific issue:
- In 2 underwater levels, a specific location causes a FPS drop not
present on Vulkan. But this is very minor and on all current M chips you
get on average better FPS with Metal (On my M3, there are occasional
drops that are worse with Vulkan), reducing stutter quite noticeably,
which is why I think it should get added to auto regardless.

- Isaac mentioned there is a issue in level 2, where the flowers singing
desync somehow. However, I was after lot of testing unable to replicate
this issue at all. More testing could be useful.

Fix: Fixed 2 typos in the comments
2025-01-21 14:05:41 -06:00
Daenorth
eaf1e7efd2 Cleanup in TitleIDs.cs (#546)
Just a little cleanup in TitleID.cs, adding a franchise title to most
franchises + sorting in alphabetical on all games.
2025-01-21 11:20:43 -06:00
Judas Drekonym
471e7ed2e4 Add TitleID sort method (#553)
Adds an additional application list sorting method for the TitleID. A
bit of a niche choice for sorting but I think the TID is a relevant
enough piece of metadata that it should be there. (And I personally
would be using it)

- Using existing TitleId constant in ApplicationSort, implying this was
meant to be in the sorting options at some point?
- Reuses the "DlcManagerTableHeadingTitleIdLabel" locale for fulfilling
the need already, might be better to make a unique one for this in the
long run but this codebase is new to me so I wanted to make the changes
as unobtrusive as possible
- Using app.Id for the comparer seems to work fine, not sure if using
something else like IdString would be better?
2025-01-21 11:06:40 -06:00
Matt Zinkevicius
ad3e80b383 Log .NET runtime version (#552)
I was looking into a crash, and found out it was an issue that was fixed
in .NET 9.0.1. Since Ryujinx embeds the runtime into the executable, it
not obvious which runtime a build uses. This logs the .NET runtime
version immediately after the build version.
2025-01-20 19:19:19 -06:00
Evan Husted
ed64a63094 UI: Visually merge "Actions" and "Tools" menu bar items into Actions
The contents of the menu item are dependent on whether you're in a game.
No functionality has been removed.
2025-01-20 16:56:05 -06:00
Evan Husted
8df7ba2d56 i18n: Norwegian DLC RomFS dumping translation 2025-01-20 15:55:37 -06:00
LotP1
e743d78115 Add/fix service reported info (#551)
fixes the GetConfig service call, which now returns success correctly
adds support for getting the device serial number (which is fake and
reports as "RYU00000000000")
2025-01-20 14:59:54 -06:00
Evan Husted
04ba762710 UI: Move DLC RomFS dumping under normal RomFS dumping.
Also removed it from DLC manager.
2025-01-20 14:30:28 -06:00
Evan Husted
f42b2ed59d misc: chore: more correct last used user checking 2025-01-20 13:33:59 -06:00
Evan Husted
d135385cab Leftovers, oops 2025-01-20 09:32:38 -06:00
Evan Husted
b360f4e721 UI: Dump DLC RomFS.
You can access this in the Manage DLC screen, it's the new button on each DLC line.

Closes #548
2025-01-20 09:28:58 -06:00
540 changed files with 4866 additions and 3723 deletions

4
.github/labeler.yml vendored
View File

@@ -18,6 +18,10 @@ gpu:
- changed-files: - changed-files:
- any-glob-to-any-file: ['src/Ryujinx.Graphics.Vulkan/**', 'src/Spv.Generator/**'] - any-glob-to-any-file: ['src/Ryujinx.Graphics.Vulkan/**', 'src/Spv.Generator/**']
'graphics-backend:metal':
- changed-files:
- any-glob-to-any-file: ['src/Ryujinx.Graphics.Metal/**', 'src/Ryujinx.Graphics.Metal.SharpMetalExtensions/**']
gui: gui:
- changed-files: - changed-files:
- any-glob-to-any-file: ['src/Ryujinx/**', 'src/Ryujinx.UI.Common/**', 'src/Ryujinx.UI.LocaleGenerator/**'] - any-glob-to-any-file: ['src/Ryujinx/**', 'src/Ryujinx.UI.Common/**', 'src/Ryujinx.UI.LocaleGenerator/**']

View File

@@ -202,7 +202,7 @@ jobs:
macos_release: macos_release:
name: Release MacOS universal name: Release MacOS universal
runs-on: ubuntu-latest runs-on: ubuntu-20.04
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4

View File

@@ -183,7 +183,7 @@ jobs:
macos_release: macos_release:
name: Release MacOS universal name: Release MacOS universal
runs-on: ubuntu-latest runs-on: ubuntu-20.04
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4

View File

@@ -42,7 +42,7 @@
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.3-build14" /> <PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.3-build14" />
<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.SDL2-CS" Version="2.30.0-build32" /> <PackageVersion Include="Ryujinx.SDL2-CS" Version="2.30.0-build32" />
<PackageVersion Include="Gommon" Version="2.7.0.2" /> <PackageVersion Include="Gommon" Version="2.7.1" />
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" /> <PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
<PackageVersion Include="Sep" Version="0.6.0" /> <PackageVersion Include="Sep" Version="0.6.0" />
<PackageVersion Include="shaderc.net" Version="0.1.0" /> <PackageVersion Include="shaderc.net" Version="0.1.0" />

View File

@@ -54,12 +54,13 @@ failing to meet this requirement may result in a poor gameplay experience or une
## Latest build ## Latest build
Stable builds are made every so often onto a separate "release" branch that then gets put into the releases you know and love. Stable builds are made every so often, based on the `master` branch, that then gets put into the releases you know and love.
These stable builds exist so that the end user can get a more **enjoyable and stable experience**. These stable builds exist so that the end user can get a more **enjoyable and stable experience**.
They are released every month or so, to ensure consistent updates, while not being an annoying amount of individual updates to download over the course of that month.
You can find the latest stable release [here](https://github.com/GreemDev/Ryujinx/releases/latest). You can find the latest stable release [here](https://github.com/GreemDev/Ryujinx/releases/latest).
Canary builds are compiled automatically for each commit on the master branch. Canary builds are compiled automatically for each commit on the `master` branch.
While we strive to ensure optimal stability and performance prior to pushing an update, these builds **may be unstable or completely broken**. While we strive to ensure optimal stability and performance prior to pushing an update, these builds **may be unstable or completely broken**.
These canary builds are only recommended for experienced users. These canary builds are only recommended for experienced users.
@@ -109,7 +110,7 @@ If you are planning to contribute or just want to learn more about this project
- **Configuration** - **Configuration**
The emulator has settings for enabling or disabling some logging, remapping controllers, and more. The emulator has settings for enabling or disabling some logging, remapping controllers, and more.
You can configure all of them through the graphical interface or manually through the config file, `Config.json`, found in the user folder which can be accessed by clicking `Open Ryujinx Folder` under the File menu in the GUI. You can configure all of them through the graphical interface or manually through the config file, `Config.json`, found in the Ryujinx data folder which can be accessed by clicking `Open Ryujinx Folder` under the File menu in the GUI.
## License ## License

View File

@@ -1070,6 +1070,7 @@
010017B0102A8000,"Emma: Lost in Memories",nvdec,playable,2021-01-28 16:19:10 010017B0102A8000,"Emma: Lost in Memories",nvdec,playable,2021-01-28 16:19:10
010068300E08E000,"Enchanted in the Moonlight - Kiryu, Chikage & Yukinojo -",gpu;nvdec,ingame,2022-11-20 16:18:45 010068300E08E000,"Enchanted in the Moonlight - Kiryu, Chikage & Yukinojo -",gpu;nvdec,ingame,2022-11-20 16:18:45
01007A4008486000,"Enchanting Mahjong Match",gpu,ingame,2020-04-17 22:01:31 01007A4008486000,"Enchanting Mahjong Match",gpu,ingame,2020-04-17 22:01:31
0100EF901E552000,"ENDER MAGNOLIA: Bloom in the Mist",deadlock,boots,2025-01-22 17:59:00
01004F3011F92000,"Endless Fables: Dark Moor",gpu;nvdec,ingame,2021-03-07 15:31:03 01004F3011F92000,"Endless Fables: Dark Moor",gpu;nvdec,ingame,2021-03-07 15:31:03
010067B017588000,"Endless Ocean™ Luminous",services-horizon;crash,ingame,2024-05-30 02:05:57 010067B017588000,"Endless Ocean™ Luminous",services-horizon;crash,ingame,2024-05-30 02:05:57
0100B8700BD14000,"Energy Cycle Edge",services,ingame,2021-11-30 05:02:31 0100B8700BD14000,"Energy Cycle Edge",services,ingame,2021-11-30 05:02:31
@@ -2681,7 +2682,7 @@
01005EA01C0FC000,"SONIC X SHADOW GENERATIONS",crash,ingame,2025-01-07 04:20:45 01005EA01C0FC000,"SONIC X SHADOW GENERATIONS",crash,ingame,2025-01-07 04:20:45
010064F00C212000,"Soul Axiom Rebooted",nvdec;slow,ingame,2020-09-04 12:41:01 010064F00C212000,"Soul Axiom Rebooted",nvdec;slow,ingame,2020-09-04 12:41:01
0100F2100F0B2000,"Soul Searching",,playable,2020-07-09 18:39:07 0100F2100F0B2000,"Soul Searching",,playable,2020-07-09 18:39:07
01008F2005154000,"South Park™: The Fractured but Whole™ - Standard Edition",slow;online-broken,playable,2024-07-08 17:47:28 01008F2005154000,"South Park™: The Fractured but Whole™ - Standard Edition",slow;online-broken;vulkan-backend-bug;gpu,ingame,2025-01-21 17:35:10
0100B9F00C162000,"Space Blaze",,playable,2020-08-30 16:18:05 0100B9F00C162000,"Space Blaze",,playable,2020-08-30 16:18:05
010005500E81E000,"Space Cows",UE4;crash,menus,2020-06-15 11:33:20 010005500E81E000,"Space Cows",UE4;crash,menus,2020-06-15 11:33:20
0100707011722000,"Space Elite Force",,playable,2020-11-27 15:21:05 0100707011722000,"Space Elite Force",,playable,2020-11-27 15:21:05
1 title_id game_name labels status last_updated
1070 010017B0102A8000 Emma: Lost in Memories nvdec playable 2021-01-28 16:19:10
1071 010068300E08E000 Enchanted in the Moonlight - Kiryu, Chikage & Yukinojo - gpu;nvdec ingame 2022-11-20 16:18:45
1072 01007A4008486000 Enchanting Mahjong Match gpu ingame 2020-04-17 22:01:31
1073 0100EF901E552000 ENDER MAGNOLIA: Bloom in the Mist deadlock boots 2025-01-22 17:59:00
1074 01004F3011F92000 Endless Fables: Dark Moor gpu;nvdec ingame 2021-03-07 15:31:03
1075 010067B017588000 Endless Ocean™ Luminous services-horizon;crash ingame 2024-05-30 02:05:57
1076 0100B8700BD14000 Energy Cycle Edge services ingame 2021-11-30 05:02:31
2682 01005EA01C0FC000 SONIC X SHADOW GENERATIONS crash ingame 2025-01-07 04:20:45
2683 010064F00C212000 Soul Axiom Rebooted nvdec;slow ingame 2020-09-04 12:41:01
2684 0100F2100F0B2000 Soul Searching playable 2020-07-09 18:39:07
2685 01008F2005154000 South Park™: The Fractured but Whole™ - Standard Edition slow;online-broken slow;online-broken;vulkan-backend-bug;gpu playable ingame 2024-07-08 17:47:28 2025-01-21 17:35:10
2686 0100B9F00C162000 Space Blaze playable 2020-08-30 16:18:05
2687 010005500E81E000 Space Cows UE4;crash menus 2020-06-15 11:33:20
2688 0100707011722000 Space Elite Force playable 2020-11-27 15:21:05

View File

@@ -13,13 +13,13 @@ namespace ARMeilleure.CodeGen.Arm64
public static void RunPass(ControlFlowGraph cfg) public static void RunPass(ControlFlowGraph cfg)
{ {
var constants = new Dictionary<ulong, Operand>(); Dictionary<ulong, Operand> constants = new Dictionary<ulong, Operand>();
Operand GetConstantCopy(BasicBlock block, Operation operation, Operand source) Operand GetConstantCopy(BasicBlock block, Operation operation, Operand source)
{ {
// If the constant has many uses, we also force a new constant mov to be added, in order // If the constant has many uses, we also force a new constant mov to be added, in order
// to avoid overflow of the counts field (that is limited to 16 bits). // to avoid overflow of the counts field (that is limited to 16 bits).
if (!constants.TryGetValue(source.Value, out var constant) || constant.UsesCount > MaxConstantUses) if (!constants.TryGetValue(source.Value, out Operand constant) || constant.UsesCount > MaxConstantUses)
{ {
constant = Local(source.Type); constant = Local(source.Type);

View File

@@ -123,7 +123,7 @@ namespace ARMeilleure.CodeGen.Arm64
public void Cset(Operand rd, ArmCondition condition) public void Cset(Operand rd, ArmCondition condition)
{ {
var zr = Factory.Register(ZrRegister, RegisterType.Integer, rd.Type); Operand zr = Factory.Register(ZrRegister, RegisterType.Integer, rd.Type);
Csinc(rd, zr, zr, (ArmCondition)((int)condition ^ 1)); Csinc(rd, zr, zr, (ArmCondition)((int)condition ^ 1));
} }

View File

@@ -91,7 +91,7 @@ namespace ARMeilleure.CodeGen.Arm64
long target = _stream.Position; long target = _stream.Position;
if (_pendingBranches.TryGetValue(block, out var list)) if (_pendingBranches.TryGetValue(block, out List<(ArmCondition Condition, long BranchPos)> list))
{ {
foreach ((ArmCondition condition, long branchPos) in list) foreach ((ArmCondition condition, long branchPos) in list)
{ {
@@ -119,7 +119,7 @@ namespace ARMeilleure.CodeGen.Arm64
} }
else else
{ {
if (!_pendingBranches.TryGetValue(target, out var list)) if (!_pendingBranches.TryGetValue(target, out List<(ArmCondition Condition, long BranchPos)> list))
{ {
list = new List<(ArmCondition, long)>(); list = new List<(ArmCondition, long)>();
_pendingBranches.Add(target, list); _pendingBranches.Add(target, list);

View File

@@ -322,7 +322,7 @@ namespace ARMeilleure.CodeGen.Arm64
Debug.Assert(comp.Kind == OperandKind.Constant); Debug.Assert(comp.Kind == OperandKind.Constant);
var cond = ((Comparison)comp.AsInt32()).ToArmCondition(); ArmCondition cond = ((Comparison)comp.AsInt32()).ToArmCondition();
GenerateCompareCommon(context, operation); GenerateCompareCommon(context, operation);
@@ -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);
var cond = ((Comparison)comp.AsInt32()).ToArmCondition(); ArmCondition cond = ((Comparison)comp.AsInt32()).ToArmCondition();
GenerateCompareCommon(context, operation); GenerateCompareCommon(context, operation);

View File

@@ -847,7 +847,7 @@ namespace ARMeilleure.CodeGen.Arm64
Debug.Assert(comp.Kind == OperandKind.Constant); Debug.Assert(comp.Kind == OperandKind.Constant);
var compType = (Comparison)comp.AsInt32(); Comparison compType = (Comparison)comp.AsInt32();
return compType == Comparison.Equal || compType == Comparison.NotEqual; return compType == Comparison.Equal || compType == Comparison.NotEqual;
} }

View File

@@ -115,7 +115,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{ {
NumberLocals(cfg, regMasks.RegistersCount); NumberLocals(cfg, regMasks.RegistersCount);
var context = new AllocationContext(stackAlloc, regMasks, _intervals.Count); AllocationContext context = new AllocationContext(stackAlloc, regMasks, _intervals.Count);
BuildIntervals(cfg, context); BuildIntervals(cfg, context);

View File

@@ -15,12 +15,12 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{ {
if (_count + 1 > _capacity) if (_count + 1 > _capacity)
{ {
var oldSpan = Span; Span<LiveInterval> oldSpan = Span;
_capacity = Math.Max(4, _capacity * 2); _capacity = Math.Max(4, _capacity * 2);
_items = Allocators.References.Allocate<LiveInterval>((uint)_capacity); _items = Allocators.References.Allocate<LiveInterval>((uint)_capacity);
var newSpan = Span; Span<LiveInterval> newSpan = Span;
oldSpan.CopyTo(newSpan); oldSpan.CopyTo(newSpan);
} }

View File

@@ -16,12 +16,12 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{ {
if (Count + 1 > _capacity) if (Count + 1 > _capacity)
{ {
var oldSpan = Span; Span<int> oldSpan = Span;
_capacity = Math.Max(4, _capacity * 2); _capacity = Math.Max(4, _capacity * 2);
_items = Allocators.Default.Allocate<int>((uint)_capacity); _items = Allocators.Default.Allocate<int>((uint)_capacity);
var newSpan = Span; Span<int> newSpan = Span;
oldSpan.CopyTo(newSpan); oldSpan.CopyTo(newSpan);
} }

View File

@@ -1,5 +1,6 @@
using ARMeilleure.CodeGen.Linking; using ARMeilleure.CodeGen.Linking;
using ARMeilleure.IntermediateRepresentation; using ARMeilleure.IntermediateRepresentation;
using Microsoft.IO;
using Ryujinx.Common.Memory; using Ryujinx.Common.Memory;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@@ -1324,8 +1325,8 @@ namespace ARMeilleure.CodeGen.X86
public (byte[], RelocInfo) GetCode() public (byte[], RelocInfo) GetCode()
{ {
var jumps = CollectionsMarshal.AsSpan(_jumps); Span<Jump> jumps = CollectionsMarshal.AsSpan(_jumps);
var relocs = CollectionsMarshal.AsSpan(_relocs); Span<Reloc> relocs = CollectionsMarshal.AsSpan(_relocs);
// Write jump relative offsets. // Write jump relative offsets.
bool modified; bool modified;
@@ -1410,13 +1411,13 @@ namespace ARMeilleure.CodeGen.X86
// Write the code, ignoring the dummy bytes after jumps, into a new stream. // Write the code, ignoring the dummy bytes after jumps, into a new stream.
_stream.Seek(0, SeekOrigin.Begin); _stream.Seek(0, SeekOrigin.Begin);
using var codeStream = MemoryStreamManager.Shared.GetStream(); using RecyclableMemoryStream codeStream = MemoryStreamManager.Shared.GetStream();
var assembler = new Assembler(codeStream, HasRelocs); Assembler assembler = new Assembler(codeStream, HasRelocs);
bool hasRelocs = HasRelocs; bool hasRelocs = HasRelocs;
int relocIndex = 0; int relocIndex = 0;
int relocOffset = 0; int relocOffset = 0;
var relocEntries = hasRelocs RelocEntry[] relocEntries = hasRelocs
? new RelocEntry[relocs.Length] ? new RelocEntry[relocs.Length]
: Array.Empty<RelocEntry>(); : Array.Empty<RelocEntry>();
@@ -1469,8 +1470,8 @@ namespace ARMeilleure.CodeGen.X86
_stream.CopyTo(codeStream); _stream.CopyTo(codeStream);
var code = codeStream.ToArray(); byte[] code = codeStream.ToArray();
var relocInfo = new RelocInfo(relocEntries); RelocInfo relocInfo = new RelocInfo(relocEntries);
return (code, relocInfo); return (code, relocInfo);
} }

View File

@@ -623,7 +623,7 @@ namespace ARMeilleure.CodeGen.X86
Debug.Assert(comp.Kind == OperandKind.Constant); Debug.Assert(comp.Kind == OperandKind.Constant);
var cond = ((Comparison)comp.AsInt32()).ToX86Condition(); X86Condition cond = ((Comparison)comp.AsInt32()).ToX86Condition();
GenerateCompareCommon(context, operation); GenerateCompareCommon(context, operation);
@@ -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);
var cond = ((Comparison)comp.AsInt32()).ToX86Condition(); X86Condition cond = ((Comparison)comp.AsInt32()).ToX86Condition();
GenerateCompareCommon(context, operation); GenerateCompareCommon(context, operation);

View File

@@ -53,7 +53,7 @@ namespace ARMeilleure.CodeGen.X86
memGetXcr0.Reprotect(0, (ulong)asmGetXcr0.Length, MemoryPermission.ReadAndExecute); memGetXcr0.Reprotect(0, (ulong)asmGetXcr0.Length, MemoryPermission.ReadAndExecute);
var fGetXcr0 = Marshal.GetDelegateForFunctionPointer<GetXcr0>(memGetXcr0.Pointer); GetXcr0 fGetXcr0 = Marshal.GetDelegateForFunctionPointer<GetXcr0>(memGetXcr0.Pointer);
return fGetXcr0(); return fGetXcr0();
} }

View File

@@ -759,7 +759,7 @@ namespace ARMeilleure.CodeGen.X86
Debug.Assert(comp.Kind == OperandKind.Constant); Debug.Assert(comp.Kind == OperandKind.Constant);
var compType = (Comparison)comp.AsInt32(); Comparison compType = (Comparison)comp.AsInt32();
return compType == Comparison.Equal || compType == Comparison.NotEqual; return compType == Comparison.Equal || compType == Comparison.NotEqual;
} }

View File

@@ -13,13 +13,13 @@ namespace ARMeilleure.CodeGen.X86
public static void RunPass(ControlFlowGraph cfg) public static void RunPass(ControlFlowGraph cfg)
{ {
var constants = new Dictionary<ulong, Operand>(); Dictionary<ulong, Operand> constants = new Dictionary<ulong, Operand>();
Operand GetConstantCopy(BasicBlock block, Operation operation, Operand source) Operand GetConstantCopy(BasicBlock block, Operation operation, Operand source)
{ {
// If the constant has many uses, we also force a new constant mov to be added, in order // If the constant has many uses, we also force a new constant mov to be added, in order
// to avoid overflow of the counts field (that is limited to 16 bits). // to avoid overflow of the counts field (that is limited to 16 bits).
if (!constants.TryGetValue(source.Value, out var constant) || constant.UsesCount > MaxConstantUses) if (!constants.TryGetValue(source.Value, out Operand constant) || constant.UsesCount > MaxConstantUses)
{ {
constant = Local(source.Type); constant = Local(source.Type);

View File

@@ -129,13 +129,13 @@ namespace ARMeilleure.Common
if (count > _count) if (count > _count)
{ {
var oldMask = _masks; long* oldMask = _masks;
var oldSpan = new Span<long>(_masks, _count); Span<long> oldSpan = new Span<long>(_masks, _count);
_masks = _allocator.Allocate<long>((uint)count); _masks = _allocator.Allocate<long>((uint)count);
_count = count; _count = count;
var newSpan = new Span<long>(_masks, _count); Span<long> newSpan = new Span<long>(_masks, _count);
oldSpan.CopyTo(newSpan); oldSpan.CopyTo(newSpan);
newSpan[oldSpan.Length..].Clear(); newSpan[oldSpan.Length..].Clear();

View File

@@ -63,7 +63,7 @@ namespace ARMeilleure.Common
} }
int index = _freeHint++; int index = _freeHint++;
var page = GetPage(index); Span<TEntry> page = GetPage(index);
_allocated.Set(index); _allocated.Set(index);
@@ -111,7 +111,7 @@ namespace ARMeilleure.Common
throw new ArgumentException("Entry at the specified index was not allocated", nameof(index)); throw new ArgumentException("Entry at the specified index was not allocated", nameof(index));
} }
var page = GetPage(index); Span<TEntry> page = GetPage(index);
return ref GetValue(page, index); return ref GetValue(page, index);
} }
@@ -136,7 +136,7 @@ namespace ARMeilleure.Common
/// <returns>Page for the specified <see cref="index"/></returns> /// <returns>Page for the specified <see cref="index"/></returns>
private unsafe Span<TEntry> GetPage(int index) private unsafe Span<TEntry> GetPage(int index)
{ {
var pageIndex = (int)((uint)(index & ~(_pageCapacity - 1)) >> _pageLogCapacity); int pageIndex = (int)((uint)(index & ~(_pageCapacity - 1)) >> _pageLogCapacity);
if (!_pages.TryGetValue(pageIndex, out nint page)) if (!_pages.TryGetValue(pageIndex, out nint page))
{ {
@@ -168,7 +168,7 @@ namespace ARMeilleure.Common
{ {
_allocated.Dispose(); _allocated.Dispose();
foreach (var page in _pages.Values) foreach (IntPtr page in _pages.Values)
{ {
NativeAllocator.Instance.Free((void*)page); NativeAllocator.Instance.Free((void*)page);
} }

View File

@@ -9,7 +9,7 @@ namespace ARMeilleure.Decoders
public OpCode32SimdDupElem(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb) public OpCode32SimdDupElem(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
{ {
var opc = (opCode >> 16) & 0xf; int opc = (opCode >> 16) & 0xf;
if ((opc & 0b1) == 1) if ((opc & 0b1) == 1)
{ {

View File

@@ -21,7 +21,7 @@ namespace ARMeilleure.Decoders
Op = (opCode >> 20) & 0x1; Op = (opCode >> 20) & 0x1;
U = ((opCode >> 23) & 1) != 0; U = ((opCode >> 23) & 1) != 0;
var opc = (((opCode >> 23) & 1) << 4) | (((opCode >> 21) & 0x3) << 2) | ((opCode >> 5) & 0x3); int opc = (((opCode >> 23) & 1) << 4) | (((opCode >> 21) & 0x3) << 2) | ((opCode >> 5) & 0x3);
if ((opc & 0b01000) == 0b01000) if ((opc & 0b01000) == 0b01000)
{ {

View File

@@ -20,7 +20,7 @@ namespace ARMeilleure.Decoders
} }
else if (DataOp == DataOp.Logical) else if (DataOp == DataOp.Logical)
{ {
var bm = DecoderHelper.DecodeBitMask(opCode, true); DecoderHelper.BitMask bm = DecoderHelper.DecodeBitMask(opCode, true);
if (bm.IsUndefined) if (bm.IsUndefined)
{ {

View File

@@ -11,7 +11,7 @@ namespace ARMeilleure.Decoders
public OpCodeBfm(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCodeBfm(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{ {
var bm = DecoderHelper.DecodeBitMask(opCode, false); DecoderHelper.BitMask bm = DecoderHelper.DecodeBitMask(opCode, false);
if (bm.IsUndefined) if (bm.IsUndefined)
{ {

View File

@@ -69,7 +69,7 @@ namespace ARMeilleure.Decoders.Optimizations
} }
} }
var newBlocks = new List<Block>(blocks.Count); List<Block> newBlocks = new List<Block>(blocks.Count);
// Finally, rebuild decoded block list, ignoring blocks outside the contiguous range. // Finally, rebuild decoded block list, ignoring blocks outside the contiguous range.
for (int i = 0; i < blocks.Count; i++) for (int i = 0; i < blocks.Count; i++)

View File

@@ -141,7 +141,7 @@ namespace ARMeilleure.Diagnostics
break; break;
case OperandKind.Memory: case OperandKind.Memory:
var memOp = operand.GetMemory(); MemoryOperand memOp = operand.GetMemory();
_builder.Append('['); _builder.Append('[');
@@ -285,7 +285,7 @@ namespace ARMeilleure.Diagnostics
public static string GetDump(ControlFlowGraph cfg) public static string GetDump(ControlFlowGraph cfg)
{ {
var dumper = new IRDumper(1); IRDumper dumper = new IRDumper(1);
for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext) for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext)
{ {

View File

@@ -415,7 +415,7 @@ namespace ARMeilleure.Instructions
{ {
IOpCode32AluBf op = (IOpCode32AluBf)context.CurrOp; IOpCode32AluBf op = (IOpCode32AluBf)context.CurrOp;
var msb = op.Lsb + op.Msb; // For this instruction, the msb is actually a width. int msb = op.Lsb + op.Msb; // For this instruction, the msb is actually a width.
Operand n = GetIntA32(context, op.Rn); Operand n = GetIntA32(context, op.Rn);
Operand res = context.ShiftRightSI(context.ShiftLeft(n, Const(31 - msb)), Const(31 - op.Msb)); Operand res = context.ShiftRightSI(context.ShiftLeft(n, Const(31 - msb)), Const(31 - op.Msb));
@@ -547,7 +547,7 @@ namespace ARMeilleure.Instructions
{ {
IOpCode32AluBf op = (IOpCode32AluBf)context.CurrOp; IOpCode32AluBf op = (IOpCode32AluBf)context.CurrOp;
var msb = op.Lsb + op.Msb; // For this instruction, the msb is actually a width. int msb = op.Lsb + op.Msb; // For this instruction, the msb is actually a width.
Operand n = GetIntA32(context, op.Rn); Operand n = GetIntA32(context, op.Rn);
Operand res = context.ShiftRightUI(context.ShiftLeft(n, Const(31 - msb)), Const(31 - op.Msb)); Operand res = context.ShiftRightUI(context.ShiftLeft(n, Const(31 - msb)), Const(31 - op.Msb));

View File

@@ -1,4 +1,5 @@
using ARMeilleure.CodeGen.Linking; using ARMeilleure.CodeGen.Linking;
using ARMeilleure.Common;
using ARMeilleure.Decoders; using ARMeilleure.Decoders;
using ARMeilleure.IntermediateRepresentation; using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.State; using ARMeilleure.State;
@@ -193,7 +194,7 @@ namespace ARMeilleure.Instructions
Operand hostAddress; Operand hostAddress;
var table = context.FunctionTable; IAddressTable<ulong> table = context.FunctionTable;
// If address is mapped onto the function table, we can skip the table walk. Otherwise we fallback // If address is mapped onto the function table, we can skip the table walk. Otherwise we fallback
// onto the dispatch stub. // onto the dispatch stub.
@@ -218,7 +219,7 @@ namespace ARMeilleure.Instructions
for (int i = 0; i < table.Levels.Length; i++) for (int i = 0; i < table.Levels.Length; i++)
{ {
var level = table.Levels[i]; AddressTableLevel level = table.Levels[i];
int clearBits = 64 - (level.Index + level.Length); int clearBits = 64 - (level.Index + level.Length);
Operand index = context.ShiftLeft( Operand index = context.ShiftLeft(

View File

@@ -143,8 +143,8 @@ namespace ARMeilleure.Instructions
Operand address = context.Copy(GetIntA32(context, op.Rn)); Operand address = context.Copy(GetIntA32(context, op.Rn));
var exclusive = (accType & AccessType.Exclusive) != 0; bool exclusive = (accType & AccessType.Exclusive) != 0;
var ordered = (accType & AccessType.Ordered) != 0; bool ordered = (accType & AccessType.Ordered) != 0;
if ((accType & AccessType.Load) != 0) if ((accType & AccessType.Load) != 0)
{ {

View File

@@ -229,7 +229,7 @@ namespace ARMeilleure.Instructions
private static Operand ZerosOrOnes(ArmEmitterContext context, Operand fromBool, OperandType baseType) private static Operand ZerosOrOnes(ArmEmitterContext context, Operand fromBool, OperandType baseType)
{ {
var ones = (baseType == OperandType.I64) ? Const(-1L) : Const(-1); Operand ones = (baseType == OperandType.I64) ? Const(-1L) : Const(-1);
return context.ConditionalSelect(fromBool, ones, Const(baseType, 0L)); return context.ConditionalSelect(fromBool, ones, Const(baseType, 0L));
} }

View File

@@ -118,15 +118,15 @@ namespace ARMeilleure.Instructions
{ {
OpCode32SimdCvtFFixed op = (OpCode32SimdCvtFFixed)context.CurrOp; OpCode32SimdCvtFFixed op = (OpCode32SimdCvtFFixed)context.CurrOp;
var toFixed = op.Opc == 1; bool toFixed = op.Opc == 1;
int fracBits = op.Fbits; int fracBits = op.Fbits;
var unsigned = op.U; bool unsigned = op.U;
if (toFixed) // F32 to S32 or U32 (fixed) if (toFixed) // F32 to S32 or U32 (fixed)
{ {
EmitVectorUnaryOpF32(context, (op1) => EmitVectorUnaryOpF32(context, (op1) =>
{ {
var scaledValue = context.Multiply(op1, ConstF(MathF.Pow(2f, fracBits))); Operand scaledValue = context.Multiply(op1, ConstF(MathF.Pow(2f, fracBits)));
MethodInfo info = unsigned ? typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToU32)) : typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToS32)); MethodInfo info = unsigned ? typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToU32)) : typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToS32));
return context.Call(info, scaledValue); return context.Call(info, scaledValue);
@@ -136,7 +136,7 @@ namespace ARMeilleure.Instructions
{ {
EmitVectorUnaryOpI32(context, (op1) => EmitVectorUnaryOpI32(context, (op1) =>
{ {
var floatValue = unsigned ? context.ConvertToFPUI(OperandType.FP32, op1) : context.ConvertToFP(OperandType.FP32, op1); Operand floatValue = unsigned ? context.ConvertToFPUI(OperandType.FP32, op1) : context.ConvertToFP(OperandType.FP32, op1);
return context.Multiply(floatValue, ConstF(1f / MathF.Pow(2f, fracBits))); return context.Multiply(floatValue, ConstF(1f / MathF.Pow(2f, fracBits)));
}, !unsigned); }, !unsigned);

View File

@@ -87,7 +87,7 @@ namespace ARMeilleure.Instructions
{ {
if (op.Replicate) if (op.Replicate)
{ {
var regs = (count > 1) ? 1 : op.Increment; int regs = (count > 1) ? 1 : op.Increment;
for (int reg = 0; reg < regs; reg++) for (int reg = 0; reg < regs; reg++)
{ {
int dreg = reg + d; int dreg = reg + d;

View File

@@ -1538,7 +1538,7 @@ namespace ARMeilleure.Instructions
} }
else if (MathF.Abs(value) < MathF.Pow(2f, -128)) else if (MathF.Abs(value) < MathF.Pow(2f, -128))
{ {
var overflowToInf = fpcr.GetRoundingMode() switch bool overflowToInf = fpcr.GetRoundingMode() switch
{ {
FPRoundingMode.ToNearest => true, FPRoundingMode.ToNearest => true,
FPRoundingMode.TowardsPlusInfinity => !sign, FPRoundingMode.TowardsPlusInfinity => !sign,
@@ -3073,7 +3073,7 @@ namespace ARMeilleure.Instructions
} }
else if (Math.Abs(value) < Math.Pow(2d, -1024)) else if (Math.Abs(value) < Math.Pow(2d, -1024))
{ {
var overflowToInf = fpcr.GetRoundingMode() switch bool overflowToInf = fpcr.GetRoundingMode() switch
{ {
FPRoundingMode.ToNearest => true, FPRoundingMode.ToNearest => true,
FPRoundingMode.TowardsPlusInfinity => !sign, FPRoundingMode.TowardsPlusInfinity => !sign,

View File

@@ -304,7 +304,7 @@ namespace ARMeilleure.IntermediateRepresentation
ushort newCount = checked((ushort)(count + 1)); ushort newCount = checked((ushort)(count + 1));
ushort newCapacity = (ushort)Math.Min(capacity * 2, ushort.MaxValue); ushort newCapacity = (ushort)Math.Min(capacity * 2, ushort.MaxValue);
var oldSpan = new Span<T>(data, count); Span<T> oldSpan = new Span<T>(data, count);
capacity = newCapacity; capacity = newCapacity;
data = Allocators.References.Allocate<T>(capacity); data = Allocators.References.Allocate<T>(capacity);
@@ -338,7 +338,7 @@ namespace ARMeilleure.IntermediateRepresentation
throw new OverflowException(); throw new OverflowException();
} }
var oldSpan = new Span<T>(data, (int)count); Span<T> oldSpan = new Span<T>(data, (int)count);
capacity = newCapacity; capacity = newCapacity;
data = Allocators.References.Allocate<T>(capacity); data = Allocators.References.Allocate<T>(capacity);
@@ -352,7 +352,7 @@ namespace ARMeilleure.IntermediateRepresentation
private static void Remove<T>(in T item, ref T* data, ref ushort count) where T : unmanaged private static void Remove<T>(in T item, ref T* data, ref ushort count) where T : unmanaged
{ {
var span = new Span<T>(data, count); Span<T> span = new Span<T>(data, count);
for (int i = 0; i < span.Length; i++) for (int i = 0; i < span.Length; i++)
{ {
@@ -372,7 +372,7 @@ namespace ARMeilleure.IntermediateRepresentation
private static void Remove<T>(in T item, ref T* data, ref uint count) where T : unmanaged private static void Remove<T>(in T item, ref T* data, ref uint count) where T : unmanaged
{ {
var span = new Span<T>(data, (int)count); Span<T> span = new Span<T>(data, (int)count);
for (int i = 0; i < span.Length; i++) for (int i = 0; i < span.Length; i++)
{ {

View File

@@ -22,7 +22,7 @@ namespace ARMeilleure.Signal
{ {
EmitterContext context = new(); EmitterContext context = new();
var result = WindowsPartialUnmapHandler.EmitRetryFromAccessViolation(context); Operand result = WindowsPartialUnmapHandler.EmitRetryFromAccessViolation(context);
context.Return(result); context.Return(result);
@@ -39,7 +39,7 @@ namespace ARMeilleure.Signal
{ {
EmitterContext context = new(); EmitterContext context = new();
var result = WindowsPartialUnmapHandler.EmitThreadLocalMapIntGetOrReserve(context, structPtr, context.LoadArgument(OperandType.I32, 0), context.LoadArgument(OperandType.I32, 1)); Operand result = WindowsPartialUnmapHandler.EmitThreadLocalMapIntGetOrReserve(context, structPtr, context.LoadArgument(OperandType.I32, 0), context.LoadArgument(OperandType.I32, 1));
context.Return(result); context.Return(result);

View File

@@ -100,13 +100,13 @@ namespace ARMeilleure.Translation.Cache
return null; // Not found. return null; // Not found.
} }
var unwindInfo = funcEntry.UnwindInfo; CodeGen.Unwinding.UnwindInfo unwindInfo = funcEntry.UnwindInfo;
int codeIndex = 0; int codeIndex = 0;
for (int index = unwindInfo.PushEntries.Length - 1; index >= 0; index--) for (int index = unwindInfo.PushEntries.Length - 1; index >= 0; index--)
{ {
var entry = unwindInfo.PushEntries[index]; UnwindPushEntry entry = unwindInfo.PushEntries[index];
switch (entry.PseudoOp) switch (entry.PseudoOp)
{ {

View File

@@ -47,8 +47,8 @@ namespace ARMeilleure.Translation
{ {
RemoveUnreachableBlocks(Blocks); RemoveUnreachableBlocks(Blocks);
var visited = new HashSet<BasicBlock>(); HashSet<BasicBlock> visited = new HashSet<BasicBlock>();
var blockStack = new Stack<BasicBlock>(); Stack<BasicBlock> blockStack = new Stack<BasicBlock>();
Array.Resize(ref _postOrderBlocks, Blocks.Count); Array.Resize(ref _postOrderBlocks, Blocks.Count);
Array.Resize(ref _postOrderMap, Blocks.Count); Array.Resize(ref _postOrderMap, Blocks.Count);
@@ -88,8 +88,8 @@ namespace ARMeilleure.Translation
private void RemoveUnreachableBlocks(IntrusiveList<BasicBlock> blocks) private void RemoveUnreachableBlocks(IntrusiveList<BasicBlock> blocks)
{ {
var visited = new HashSet<BasicBlock>(); HashSet<BasicBlock> visited = new HashSet<BasicBlock>();
var workQueue = new Queue<BasicBlock>(); Queue<BasicBlock> workQueue = new Queue<BasicBlock>();
visited.Add(Entry); visited.Add(Entry);
workQueue.Enqueue(Entry); workQueue.Enqueue(Entry);

View File

@@ -9,6 +9,7 @@ using Ryujinx.Common.Logging;
using Ryujinx.Common.Memory; using Ryujinx.Common.Memory;
using System; using System;
using System.Buffers.Binary; using System.Buffers.Binary;
using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
@@ -562,7 +563,7 @@ namespace ARMeilleure.Translation.PTC
bool isEntryChanged = infoEntry.Hash != ComputeHash(translator.Memory, infoEntry.Address, infoEntry.GuestSize); bool isEntryChanged = infoEntry.Hash != ComputeHash(translator.Memory, infoEntry.Address, infoEntry.GuestSize);
if (isEntryChanged || (!infoEntry.HighCq && Profiler.ProfiledFuncs.TryGetValue(infoEntry.Address, out var value) && value.HighCq)) if (isEntryChanged || (!infoEntry.HighCq && Profiler.ProfiledFuncs.TryGetValue(infoEntry.Address, out PtcProfiler.FuncProfile value) && value.HighCq))
{ {
infoEntry.Stubbed = true; infoEntry.Stubbed = true;
infoEntry.CodeLength = 0; infoEntry.CodeLength = 0;
@@ -749,8 +750,8 @@ namespace ARMeilleure.Translation.PTC
UnwindInfo unwindInfo, UnwindInfo unwindInfo,
bool highCq) bool highCq)
{ {
var cFunc = new CompiledFunction(code, unwindInfo, RelocInfo.Empty); CompiledFunction cFunc = new CompiledFunction(code, unwindInfo, RelocInfo.Empty);
var gFunc = cFunc.MapWithPointer<GuestFunction>(out nint gFuncPointer); GuestFunction gFunc = cFunc.MapWithPointer<GuestFunction>(out nint gFuncPointer);
return new TranslatedFunction(gFunc, gFuncPointer, callCounter, guestSize, highCq); return new TranslatedFunction(gFunc, gFuncPointer, callCounter, guestSize, highCq);
} }
@@ -787,7 +788,7 @@ namespace ARMeilleure.Translation.PTC
public void MakeAndSaveTranslations(Translator translator) public void MakeAndSaveTranslations(Translator translator)
{ {
var profiledFuncsToTranslate = Profiler.GetProfiledFuncsToTranslate(translator.Functions); ConcurrentQueue<(ulong address, PtcProfiler.FuncProfile funcProfile)> profiledFuncsToTranslate = Profiler.GetProfiledFuncsToTranslate(translator.Functions);
_translateCount = 0; _translateCount = 0;
_translateTotalCount = profiledFuncsToTranslate.Count; _translateTotalCount = profiledFuncsToTranslate.Count;
@@ -831,7 +832,7 @@ namespace ARMeilleure.Translation.PTC
void TranslateFuncs() void TranslateFuncs()
{ {
while (profiledFuncsToTranslate.TryDequeue(out var item)) while (profiledFuncsToTranslate.TryDequeue(out (ulong address, PtcProfiler.FuncProfile funcProfile) item))
{ {
ulong address = item.address; ulong address = item.address;
@@ -866,11 +867,11 @@ namespace ARMeilleure.Translation.PTC
Stopwatch sw = Stopwatch.StartNew(); Stopwatch sw = Stopwatch.StartNew();
foreach (var thread in threads) foreach (Thread thread in threads)
{ {
thread.Start(); thread.Start();
} }
foreach (var thread in threads) foreach (Thread thread in threads)
{ {
thread.Join(); thread.Join();
} }
@@ -944,7 +945,7 @@ namespace ARMeilleure.Translation.PTC
WriteCode(code.AsSpan()); WriteCode(code.AsSpan());
// WriteReloc. // WriteReloc.
using var relocInfoWriter = new BinaryWriter(_relocsStream, EncodingCache.UTF8NoBOM, true); using BinaryWriter relocInfoWriter = new BinaryWriter(_relocsStream, EncodingCache.UTF8NoBOM, true);
foreach (RelocEntry entry in relocInfo.Entries) foreach (RelocEntry entry in relocInfo.Entries)
{ {
@@ -954,7 +955,7 @@ namespace ARMeilleure.Translation.PTC
} }
// WriteUnwindInfo. // WriteUnwindInfo.
using var unwindInfoWriter = new BinaryWriter(_unwindInfosStream, EncodingCache.UTF8NoBOM, true); using BinaryWriter unwindInfoWriter = new BinaryWriter(_unwindInfosStream, EncodingCache.UTF8NoBOM, true);
unwindInfoWriter.Write(unwindInfo.PushEntries.Length); unwindInfoWriter.Write(unwindInfo.PushEntries.Length);

View File

@@ -111,9 +111,9 @@ namespace ARMeilleure.Translation.PTC
public ConcurrentQueue<(ulong address, FuncProfile funcProfile)> GetProfiledFuncsToTranslate(TranslatorCache<TranslatedFunction> funcs) public ConcurrentQueue<(ulong address, FuncProfile funcProfile)> GetProfiledFuncsToTranslate(TranslatorCache<TranslatedFunction> funcs)
{ {
var profiledFuncsToTranslate = new ConcurrentQueue<(ulong address, FuncProfile funcProfile)>(); ConcurrentQueue<(ulong address, FuncProfile funcProfile)> profiledFuncsToTranslate = new ConcurrentQueue<(ulong address, FuncProfile funcProfile)>();
foreach (var profiledFunc in ProfiledFuncs) foreach (KeyValuePair<ulong, FuncProfile> profiledFunc in ProfiledFuncs)
{ {
if (!funcs.ContainsKey(profiledFunc.Key)) if (!funcs.ContainsKey(profiledFunc.Key))
{ {

View File

@@ -44,10 +44,10 @@ namespace ARMeilleure.Translation
public static void Construct(ControlFlowGraph cfg) public static void Construct(ControlFlowGraph cfg)
{ {
var globalDefs = new DefMap[cfg.Blocks.Count]; DefMap[] globalDefs = new DefMap[cfg.Blocks.Count];
var localDefs = new Operand[cfg.LocalsCount + RegisterConsts.TotalCount]; Operand[] localDefs = new Operand[cfg.LocalsCount + RegisterConsts.TotalCount];
var dfPhiBlocks = new Queue<BasicBlock>(); Queue<BasicBlock> dfPhiBlocks = new Queue<BasicBlock>();
for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext) for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext)
{ {

View File

@@ -222,7 +222,7 @@ namespace ARMeilleure.Translation
internal TranslatedFunction Translate(ulong address, ExecutionMode mode, bool highCq, bool singleStep = false) internal TranslatedFunction Translate(ulong address, ExecutionMode mode, bool highCq, bool singleStep = false)
{ {
var context = new ArmEmitterContext( ArmEmitterContext context = new ArmEmitterContext(
Memory, Memory,
CountTable, CountTable,
FunctionTable, FunctionTable,
@@ -259,10 +259,10 @@ namespace ARMeilleure.Translation
Logger.EndPass(PassName.RegisterUsage); Logger.EndPass(PassName.RegisterUsage);
var retType = OperandType.I64; OperandType retType = OperandType.I64;
var argTypes = new OperandType[] { OperandType.I64 }; OperandType[] argTypes = new OperandType[] { OperandType.I64 };
var options = highCq ? CompilerOptions.HighCq : CompilerOptions.None; CompilerOptions options = highCq ? CompilerOptions.HighCq : CompilerOptions.None;
if (context.HasPtc && !singleStep) if (context.HasPtc && !singleStep)
{ {
@@ -521,7 +521,7 @@ namespace ARMeilleure.Translation
List<TranslatedFunction> functions = Functions.AsList(); List<TranslatedFunction> functions = Functions.AsList();
foreach (var func in functions) foreach (TranslatedFunction func in functions)
{ {
JitCache.Unmap(func.FuncPointer); JitCache.Unmap(func.FuncPointer);
@@ -530,7 +530,7 @@ namespace ARMeilleure.Translation
Functions.Clear(); Functions.Clear();
while (_oldFuncs.TryDequeue(out var kv)) while (_oldFuncs.TryDequeue(out KeyValuePair<ulong, TranslatedFunction> kv))
{ {
JitCache.Unmap(kv.Value.FuncPointer); JitCache.Unmap(kv.Value.FuncPointer);
@@ -551,7 +551,7 @@ namespace ARMeilleure.Translation
{ {
while (Queue.Count > 0 && Queue.TryDequeue(out RejitRequest request)) while (Queue.Count > 0 && Queue.TryDequeue(out RejitRequest request))
{ {
if (Functions.TryGetValue(request.Address, out var func) && func.CallCounter != null) if (Functions.TryGetValue(request.Address, out TranslatedFunction func) && func.CallCounter != null)
{ {
Volatile.Write(ref func.CallCounter.Value, 0); Volatile.Write(ref func.CallCounter.Value, 0);
} }

View File

@@ -142,7 +142,7 @@ namespace ARMeilleure.Translation
/// <returns>Generated <see cref="DispatchStub"/></returns> /// <returns>Generated <see cref="DispatchStub"/></returns>
private nint GenerateDispatchStub() private nint GenerateDispatchStub()
{ {
var context = new EmitterContext(); EmitterContext context = new EmitterContext();
Operand lblFallback = Label(); Operand lblFallback = Label();
Operand lblEnd = Label(); Operand lblEnd = Label();
@@ -161,7 +161,7 @@ namespace ARMeilleure.Translation
for (int i = 0; i < _functionTable.Levels.Length; i++) for (int i = 0; i < _functionTable.Levels.Length; i++)
{ {
ref var level = ref _functionTable.Levels[i]; ref AddressTableLevel level = ref _functionTable.Levels[i];
// level.Mask is not used directly because it is more often bigger than 32-bits, so it will not // level.Mask is not used directly because it is more often bigger than 32-bits, so it will not
// be encoded as an immediate on x86's bitwise and operation. // be encoded as an immediate on x86's bitwise and operation.
@@ -185,11 +185,11 @@ namespace ARMeilleure.Translation
hostAddress = context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFunctionAddress)), guestAddress); hostAddress = context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFunctionAddress)), guestAddress);
context.Tailcall(hostAddress, nativeContext); context.Tailcall(hostAddress, nativeContext);
var cfg = context.GetControlFlowGraph(); ControlFlowGraph cfg = context.GetControlFlowGraph();
var retType = OperandType.I64; OperandType retType = OperandType.I64;
var argTypes = new[] { OperandType.I64 }; OperandType[] argTypes = new[] { OperandType.I64 };
var func = Compiler.Compile(cfg, argTypes, retType, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<GuestFunction>(); GuestFunction func = Compiler.Compile(cfg, argTypes, retType, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<GuestFunction>();
return Marshal.GetFunctionPointerForDelegate(func); return Marshal.GetFunctionPointerForDelegate(func);
} }
@@ -200,7 +200,7 @@ namespace ARMeilleure.Translation
/// <returns>Generated <see cref="SlowDispatchStub"/></returns> /// <returns>Generated <see cref="SlowDispatchStub"/></returns>
private nint GenerateSlowDispatchStub() private nint GenerateSlowDispatchStub()
{ {
var context = new EmitterContext(); EmitterContext context = new EmitterContext();
// Load the target guest address from the native context. // Load the target guest address from the native context.
Operand nativeContext = context.LoadArgument(OperandType.I64, 0); Operand nativeContext = context.LoadArgument(OperandType.I64, 0);
@@ -210,11 +210,11 @@ namespace ARMeilleure.Translation
Operand hostAddress = context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFunctionAddress)), guestAddress); Operand hostAddress = context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFunctionAddress)), guestAddress);
context.Tailcall(hostAddress, nativeContext); context.Tailcall(hostAddress, nativeContext);
var cfg = context.GetControlFlowGraph(); ControlFlowGraph cfg = context.GetControlFlowGraph();
var retType = OperandType.I64; OperandType retType = OperandType.I64;
var argTypes = new[] { OperandType.I64 }; OperandType[] argTypes = new[] { OperandType.I64 };
var func = Compiler.Compile(cfg, argTypes, retType, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<GuestFunction>(); GuestFunction func = Compiler.Compile(cfg, argTypes, retType, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<GuestFunction>();
return Marshal.GetFunctionPointerForDelegate(func); return Marshal.GetFunctionPointerForDelegate(func);
} }
@@ -251,7 +251,7 @@ namespace ARMeilleure.Translation
/// <returns><see cref="DispatchLoop"/> function</returns> /// <returns><see cref="DispatchLoop"/> function</returns>
private DispatcherFunction GenerateDispatchLoop() private DispatcherFunction GenerateDispatchLoop()
{ {
var context = new EmitterContext(); EmitterContext context = new EmitterContext();
Operand beginLbl = Label(); Operand beginLbl = Label();
Operand endLbl = Label(); Operand endLbl = Label();
@@ -279,9 +279,9 @@ namespace ARMeilleure.Translation
context.Return(); context.Return();
var cfg = context.GetControlFlowGraph(); ControlFlowGraph cfg = context.GetControlFlowGraph();
var retType = OperandType.None; OperandType retType = OperandType.None;
var argTypes = new[] { OperandType.I64, OperandType.I64 }; OperandType[] argTypes = new[] { OperandType.I64, OperandType.I64 };
return Compiler.Compile(cfg, argTypes, retType, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<DispatcherFunction>(); return Compiler.Compile(cfg, argTypes, retType, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<DispatcherFunction>();
} }
@@ -292,7 +292,7 @@ namespace ARMeilleure.Translation
/// <returns><see cref="ContextWrapper"/> function</returns> /// <returns><see cref="ContextWrapper"/> function</returns>
private WrapperFunction GenerateContextWrapper() private WrapperFunction GenerateContextWrapper()
{ {
var context = new EmitterContext(); EmitterContext context = new EmitterContext();
Operand nativeContext = context.LoadArgument(OperandType.I64, 0); Operand nativeContext = context.LoadArgument(OperandType.I64, 0);
Operand guestMethod = context.LoadArgument(OperandType.I64, 1); Operand guestMethod = context.LoadArgument(OperandType.I64, 1);
@@ -303,9 +303,9 @@ namespace ARMeilleure.Translation
context.Return(returnValue); context.Return(returnValue);
var cfg = context.GetControlFlowGraph(); ControlFlowGraph cfg = context.GetControlFlowGraph();
var retType = OperandType.I64; OperandType retType = OperandType.I64;
var argTypes = new[] { OperandType.I64, OperandType.I64 }; OperandType[] argTypes = new[] { OperandType.I64, OperandType.I64 };
return Compiler.Compile(cfg, argTypes, retType, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<WrapperFunction>(); return Compiler.Compile(cfg, argTypes, retType, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<WrapperFunction>();
} }

View File

@@ -37,7 +37,7 @@ namespace Ryujinx.Audio.Backends.SDL2
SDL2Driver.Instance.Initialize(); SDL2Driver.Instance.Initialize();
int res = SDL_GetDefaultAudioInfo(nint.Zero, out var spec, 0); int res = SDL_GetDefaultAudioInfo(nint.Zero, out SDL_AudioSpec spec, 0);
if (res != 0) if (res != 0)
{ {

View File

@@ -38,7 +38,7 @@ namespace Ryujinx.Audio.Backends.SoundIo.Native
get => Marshal.PtrToStringAnsi(GetOutContext().Name); get => Marshal.PtrToStringAnsi(GetOutContext().Name);
set set
{ {
var context = GetOutContext(); SoundIoOutStream context = GetOutContext();
if (_nameStored != nint.Zero && context.Name == _nameStored) if (_nameStored != nint.Zero && context.Name == _nameStored)
{ {
@@ -129,8 +129,8 @@ namespace Ryujinx.Audio.Backends.SoundIo.Native
unsafe unsafe
{ {
var frameCountPtr = &nativeFrameCount; int* frameCountPtr = &nativeFrameCount;
var arenasPtr = &arenas; IntPtr* arenasPtr = &arenas;
CheckError(soundio_outstream_begin_write(_context, (nint)arenasPtr, (nint)frameCountPtr)); CheckError(soundio_outstream_begin_write(_context, (nint)arenasPtr, (nint)frameCountPtr));
frameCount = *frameCountPtr; frameCount = *frameCountPtr;

View File

@@ -27,7 +27,7 @@ namespace Ryujinx.Audio.Renderer.Utils
private void UpdateHeader() private void UpdateHeader()
{ {
var writer = new BinaryWriter(_stream); BinaryWriter writer = new(_stream);
long currentPos = writer.Seek(0, SeekOrigin.Current); long currentPos = writer.Seek(0, SeekOrigin.Current);

View File

@@ -34,7 +34,7 @@ namespace Ryujinx.Common
{ {
try try
{ {
foreach (var item in _queue.GetConsumingEnumerable(_cts.Token)) foreach (T item in _queue.GetConsumingEnumerable(_cts.Token))
{ {
_workerAction(item); _workerAction(item);
} }

View File

@@ -23,8 +23,9 @@ namespace Ryujinx.Common.Configuration
public static EnabledDirtyHack Unpack(ulong packedHack) public static EnabledDirtyHack Unpack(ulong packedHack)
{ {
var unpackedFields = packedHack.UnpackBitFields(PackedFormat); uint[] unpackedFields = packedHack.UnpackBitFields(PackedFormat);
if (unpackedFields is not [var hack, var value]) // ReSharper disable once PatternAlwaysMatches
if (unpackedFields is not [uint hack, uint value])
throw new Exception("The unpack operation on the integer resulted in an invalid unpacked result."); throw new Exception("The unpack operation on the integer resulted in an invalid unpacked result.");
return new EnabledDirtyHack((DirtyHack)hack, (int)value); return new EnabledDirtyHack((DirtyHack)hack, (int)value);
@@ -53,7 +54,7 @@ namespace Ryujinx.Common.Configuration
public static implicit operator DirtyHacks(EnabledDirtyHack[] hacks) => new(hacks); public static implicit operator DirtyHacks(EnabledDirtyHack[] hacks) => new(hacks);
public static implicit operator DirtyHacks(ulong[] packedHacks) => new(packedHacks); public static implicit operator DirtyHacks(ulong[] packedHacks) => new(packedHacks);
public new int this[DirtyHack hack] => TryGetValue(hack, out var value) ? value : -1; public new int this[DirtyHack hack] => TryGetValue(hack, out int value) ? value : -1;
public bool IsEnabled(DirtyHack hack) => ContainsKey(hack); public bool IsEnabled(DirtyHack hack) => ContainsKey(hack);
} }

View File

@@ -78,5 +78,10 @@ namespace Ryujinx.Common.Configuration.Hid.Controller
/// Controller Rumble Settings /// Controller Rumble Settings
/// </summary> /// </summary>
public RumbleConfigController Rumble { get; set; } public RumbleConfigController Rumble { get; set; }
/// <summary>
/// Controller LED Settings
/// </summary>
public LedConfigController Led { get; set; }
} }
} }

View File

@@ -0,0 +1,25 @@
namespace Ryujinx.Common.Configuration.Hid.Controller
{
public class LedConfigController
{
/// <summary>
/// Enable LED color changing by the emulator
/// </summary>
public bool EnableLed { get; set; }
/// <summary>
/// Ignores the color and disables the LED entirely.
/// </summary>
public bool TurnOffLed { get; set; }
/// <summary>
/// Ignores the color and uses the rainbow color functionality for the LED.
/// </summary>
public bool UseRainbow { get; set; }
/// <summary>
/// Packed RGB int of the color
/// </summary>
public uint LedColor { get; set; }
}
}

View File

@@ -1,6 +1,7 @@
using System; using System;
using System.Buffers; using System.Buffers;
using System.Diagnostics; using System.Diagnostics;
using System.IO;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
@@ -16,15 +17,15 @@ namespace Ryujinx.Common.Extensions
/// <param name="fileFullName">The path and name of the file to create and dump to</param> /// <param name="fileFullName">The path and name of the file to create and dump to</param>
public static void DumpToFile(this ref SequenceReader<byte> reader, string fileFullName) public static void DumpToFile(this ref SequenceReader<byte> reader, string fileFullName)
{ {
var initialConsumed = reader.Consumed; long initialConsumed = reader.Consumed;
reader.Rewind(initialConsumed); reader.Rewind(initialConsumed);
using (var fileStream = System.IO.File.Create(fileFullName, 4096, System.IO.FileOptions.None)) using (FileStream fileStream = System.IO.File.Create(fileFullName, 4096, System.IO.FileOptions.None))
{ {
while (reader.End == false) while (reader.End == false)
{ {
var span = reader.CurrentSpan; ReadOnlySpan<byte> span = reader.CurrentSpan;
fileStream.Write(span); fileStream.Write(span);
reader.Advance(span.Length); reader.Advance(span.Length);
} }

View File

@@ -101,7 +101,7 @@ namespace Ryujinx.Common.Helper
{ {
RegistryKey key = Registry.CurrentUser.OpenSubKey(@$"Software\Classes\{ext}"); RegistryKey key = Registry.CurrentUser.OpenSubKey(@$"Software\Classes\{ext}");
var openCmd = key?.OpenSubKey(@"shell\open\command"); RegistryKey openCmd = key?.OpenSubKey(@"shell\open\command");
if (openCmd is null) if (openCmd is null)
{ {
@@ -143,7 +143,7 @@ namespace Ryujinx.Common.Helper
} }
else else
{ {
using var key = Registry.CurrentUser.CreateSubKey(keyString); using RegistryKey key = Registry.CurrentUser.CreateSubKey(keyString);
if (key is null) if (key is null)
{ {
@@ -151,7 +151,7 @@ namespace Ryujinx.Common.Helper
} }
Logger.Debug?.Print(LogClass.Application, $"Adding type association {ext}"); Logger.Debug?.Print(LogClass.Application, $"Adding type association {ext}");
using var openCmd = key.CreateSubKey(@"shell\open\command"); using RegistryKey openCmd = key.CreateSubKey(@"shell\open\command");
openCmd.SetValue(string.Empty, $"\"{Environment.ProcessPath}\" \"%1\""); openCmd.SetValue(string.Empty, $"\"{Environment.ProcessPath}\" \"%1\"");
Logger.Debug?.Print(LogClass.Application, $"Added type association {ext}"); Logger.Debug?.Print(LogClass.Application, $"Added type association {ext}");

View File

@@ -24,7 +24,7 @@ namespace Ryujinx.Common.Helper
return null; return null;
} }
foreach (var searchPath in pathVar.Split(":", StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries)) foreach (string searchPath in pathVar.Split(":", StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries))
{ {
string binaryPath = Path.Combine(searchPath, binary); string binaryPath = Path.Combine(searchPath, binary);

View File

@@ -60,7 +60,7 @@ namespace Ryujinx.Common.Helper
{ {
ObjectiveC.NSString nsStringPath = new(path); ObjectiveC.NSString nsStringPath = new(path);
ObjectiveC.Object nsUrl = new("NSURL"); ObjectiveC.Object nsUrl = new("NSURL");
var urlPtr = nsUrl.GetFromMessage("fileURLWithPath:", nsStringPath); ObjectiveC.Object urlPtr = nsUrl.GetFromMessage("fileURLWithPath:", nsStringPath);
ObjectiveC.Object nsArray = new("NSArray"); ObjectiveC.Object nsArray = new("NSArray");
ObjectiveC.Object urlArray = nsArray.GetFromMessage("arrayWithObject:", urlPtr); ObjectiveC.Object urlArray = nsArray.GetFromMessage("arrayWithObject:", urlPtr);
@@ -99,7 +99,7 @@ namespace Ryujinx.Common.Helper
{ {
ObjectiveC.NSString nsStringPath = new(url); ObjectiveC.NSString nsStringPath = new(url);
ObjectiveC.Object nsUrl = new("NSURL"); ObjectiveC.Object nsUrl = new("NSURL");
var urlPtr = nsUrl.GetFromMessage("URLWithString:", nsStringPath); ObjectiveC.Object urlPtr = nsUrl.GetFromMessage("URLWithString:", nsStringPath);
ObjectiveC.Object nsWorkspace = new("NSWorkspace"); ObjectiveC.Object nsWorkspace = new("NSWorkspace");
ObjectiveC.Object sharedWorkspace = nsWorkspace.GetFromMessage("sharedWorkspace"); ObjectiveC.Object sharedWorkspace = nsWorkspace.GetFromMessage("sharedWorkspace");

View File

@@ -0,0 +1,23 @@
using System;
using System.Runtime.InteropServices;
// ReSharper disable MemberCanBePrivate.Global
// ReSharper disable InconsistentNaming
namespace Ryujinx.Common.Helper
{
public static class RunningPlatform
{
public static bool IsMacOS => OperatingSystem.IsMacOS();
public static bool IsWindows => OperatingSystem.IsWindows();
public static bool IsLinux => OperatingSystem.IsLinux();
public static bool IsIntelMac => IsMacOS && RuntimeInformation.OSArchitecture is Architecture.X64;
public static bool IsArmMac => IsMacOS && RuntimeInformation.OSArchitecture is Architecture.Arm64;
public static bool IsX64Windows => IsWindows && (RuntimeInformation.OSArchitecture is Architecture.X64);
public static bool IsArmWindows => IsWindows && (RuntimeInformation.OSArchitecture is Architecture.Arm64);
public static bool IsX64Linux => IsLinux && (RuntimeInformation.OSArchitecture is Architecture.X64);
public static bool IsArmLinux => IsLinux && (RuntimeInformation.OSArchitecture is Architecture.Arm64);
}
}

View File

@@ -41,7 +41,7 @@ namespace Ryujinx.Common.Logging.Formatters
sb.Append('{'); sb.Append('{');
foreach (var prop in props) foreach (PropertyInfo prop in props)
{ {
sb.Append(prop.Name); sb.Append(prop.Name);
sb.Append(": "); sb.Append(": ");
@@ -52,7 +52,7 @@ namespace Ryujinx.Common.Logging.Formatters
if (array is not null) if (array is not null)
{ {
foreach (var item in array) foreach (object? item in array)
{ {
sb.Append(item); sb.Append(item);
sb.Append(", "); sb.Append(", ");

View File

@@ -193,7 +193,7 @@ namespace Ryujinx.Common.Logging
_stdErrAdapter.Dispose(); _stdErrAdapter.Dispose();
foreach (var target in _logTargets) foreach (ILogTarget target in _logTargets)
{ {
target.Dispose(); target.Dispose();
} }
@@ -203,9 +203,9 @@ namespace Ryujinx.Common.Logging
public static IReadOnlyCollection<LogLevel> GetEnabledLevels() public static IReadOnlyCollection<LogLevel> GetEnabledLevels()
{ {
var logs = new[] { Debug, Info, Warning, Error, Guest, AccessLog, Stub, Trace }; Log?[] logs = new[] { Debug, Info, Warning, Error, Guest, AccessLog, Stub, Trace };
List<LogLevel> levels = new(logs.Length); List<LogLevel> levels = new(logs.Length);
foreach (var log in logs) foreach (Log? log in logs)
{ {
if (log.HasValue) if (log.HasValue)
levels.Add(log.Value.Level); levels.Add(log.Value.Level);

View File

@@ -26,7 +26,7 @@ namespace Ryujinx.Common.Logging.Targets
public void Log(object sender, LogEventArgs e) public void Log(object sender, LogEventArgs e)
{ {
var logEventArgsJson = LogEventArgsJson.FromLogEventArgs(e); LogEventArgsJson logEventArgsJson = LogEventArgsJson.FromLogEventArgs(e);
JsonHelper.SerializeToStream(_stream, logEventArgsJson, LogEventJsonSerializerContext.Default.LogEventArgsJson); JsonHelper.SerializeToStream(_stream, logEventArgsJson, LogEventJsonSerializerContext.Default.LogEventArgsJson);
} }

View File

@@ -1,5 +1,6 @@
using Gommon; using Gommon;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Helper;
using System; using System;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
@@ -8,19 +9,20 @@ namespace Ryujinx.Common
{ {
public static class TitleIDs public static class TitleIDs
{ {
public static ReactiveObject<Optional<string>> CurrentApplication { get; set; } = new(); public static ReactiveObject<Optional<string>> CurrentApplication { get; } = new();
public static GraphicsBackend SelectGraphicsBackend(string titleId, GraphicsBackend currentBackend) public static GraphicsBackend SelectGraphicsBackend(string titleId, GraphicsBackend currentBackend)
{ {
switch (currentBackend) switch (currentBackend)
{ {
case GraphicsBackend.Metal when !OperatingSystem.IsMacOS():
case GraphicsBackend.OpenGl when OperatingSystem.IsMacOS(): case GraphicsBackend.OpenGl when OperatingSystem.IsMacOS():
return GraphicsBackend.Vulkan; return GraphicsBackend.Vulkan;
case GraphicsBackend.Vulkan or GraphicsBackend.OpenGl or GraphicsBackend.Metal: case GraphicsBackend.Vulkan or GraphicsBackend.OpenGl or GraphicsBackend.Metal:
return currentBackend; return currentBackend;
} }
if (!(OperatingSystem.IsMacOS() && RuntimeInformation.ProcessArchitecture is Architecture.Arm64)) if (!RunningPlatform.IsArmMac)
return GraphicsBackend.Vulkan; return GraphicsBackend.Vulkan;
return GreatMetalTitles.ContainsIgnoreCase(titleId) ? GraphicsBackend.Metal : GraphicsBackend.Vulkan; return GreatMetalTitles.ContainsIgnoreCase(titleId) ? GraphicsBackend.Metal : GraphicsBackend.Vulkan;
@@ -28,18 +30,28 @@ namespace Ryujinx.Common
public static readonly string[] GreatMetalTitles = public static readonly string[] GreatMetalTitles =
[ [
"01006f8002326000", // Animal Crossings: New Horizons "010076f0049a2000", // Bayonetta
"01009bf0072d4000", // Captain Toad: Treasure Tracker
"0100a5c00d162000", // Cuphead "0100a5c00d162000", // Cuphead
"010023800d64a000", // Deltarune "010023800d64a000", // Deltarune
"01003a30012c0000", // LEGO City Undercover
"010028600EBDA000", // Mario 3D World "010028600EBDA000", // Mario 3D World
"0100152000022000", // Mario Kart 8 Deluxe "0100152000022000", // Mario Kart 8 Deluxe
"01005CA01580E000", // Persona 5 "010075a016a3a000", // Persona 4 Arena Ultimax
"0100187003A36000", // Pokémon: Let's Go, Evoli! "0100187003A36000", // Pokémon: Let's Go, Eevee!
"010003f003a34000", // Pokémon: Let's Go, Pikachu! "010003f003a34000", // Pokémon: Let's Go, Pikachu!
"01008C0016544000", // Sea of Stars "01008C0016544000", // Sea of Stars
"01006A800016E000", // Smash Ultimate "01006A800016E000", // Smash Ultimate
"0100000000010000", // Super Mario Odyessy "01006bb00c6f0000", // The Legend of Zelda: Link's Awakening
// These ones have small issues, but those happen on Vulkan as well:
"01006f8002326000", // Animal Crossings: New Horizons
"01009bf0072d4000", // Captain Toad: Treasure Tracker
"01009510001ca000", // Fast RMX
"01005CA01580E000", // Persona 5 Royale
"0100000000010000", // Super Mario Odyssey
//Isaac claims it has a issue in level 2, but I am not able to replicate it on my M3. More testing would be appreciated:
"010015100b514000", // Super Mario Bros. Wonder
]; ];
public static string GetDiscordGameAsset(string titleId) public static string GetDiscordGameAsset(string titleId)
@@ -47,72 +59,88 @@ namespace Ryujinx.Common
public static readonly string[] DiscordGameAssetKeys = public static readonly string[] DiscordGameAssetKeys =
[ [
//All games are in Alphabetical order by Game name.
//Dragon Quest Franchise
"010008900705c000", // Dragon Quest Builders "010008900705c000", // Dragon Quest Builders
"010042000a986000", // Dragon Quest Builders 2 "010042000a986000", // Dragon Quest Builders 2
"010055d009f78000", // Fire Emblem: Three Houses //Fire Emblem Franchise
"0100a12011cc8000", // Fire Emblem: Shadow Dragon
"0100a6301214e000", // Fire Emblem Engage "0100a6301214e000", // Fire Emblem Engage
"0100a12011cc8000", // Fire Emblem: Shadow Dragon
"010055d009f78000", // Fire Emblem: Three Houses
"0100f15003e64000", // Fire Emblem Warriors "0100f15003e64000", // Fire Emblem Warriors
"010071f0143ea000", // Fire Emblem Warriors: Three Hopes "010071f0143ea000", // Fire Emblem Warriors: Three Hopes
"01007e3006dda000", // Kirby Star Allies //Kirby Franchise
"01004d300c5ae000", // Kirby and the Forgotten Land "01004d300c5ae000", // Kirby and the Forgotten Land
"01006b601380e000", // Kirby's Return to Dream Land Deluxe
"01003fb00c5a8000", // Super Kirby Clash
"0100227010460000", // Kirby Fighters 2
"0100a8e016236000", // Kirby's Dream Buffet "0100a8e016236000", // Kirby's Dream Buffet
"0100227010460000", // Kirby Fighters 2
"01006b601380e000", // Kirby's Return to Dream Land Deluxe
"01007e3006dda000", // Kirby Star Allies
"01003fb00c5a8000", // Super Kirby Clash
//The Zelda Franchise
"01000b900d8b0000", // Cadence of Hyrule
"0100ae00096ea000", // Hyrule Warriors: Definitive Edition
"01002b00111a2000", // Hyrule Warriors: Age of Calamity
"01007ef00011e000", // The Legend of Zelda: Breath of the Wild "01007ef00011e000", // The Legend of Zelda: Breath of the Wild
"01006bb00c6f0000", // The Legend of Zelda: Link's Awakening "01006bb00c6f0000", // The Legend of Zelda: Link's Awakening
"01002da013484000", // The Legend of Zelda: Skyward Sword HD "01002da013484000", // The Legend of Zelda: Skyward Sword HD
"0100f2c0115b6000", // The Legend of Zelda: Tears of the Kingdom "0100f2c0115b6000", // The Legend of Zelda: Tears of the Kingdom
"01008cf01baac000", // The Legend of Zelda: Echoes of Wisdom "01008cf01baac000", // The Legend of Zelda: Echoes of Wisdom
"01000b900d8b0000", // Cadence of Hyrule
"0100ae00096ea000", // Hyrule Warriors: Definitive Edition
"01002b00111a2000", // Hyrule Warriors: Age of Calamity
//Luigi Franchise
"010048701995e000", // Luigi's Mansion 2 HD "010048701995e000", // Luigi's Mansion 2 HD
"0100dca0064a6000", // Luigi's Mansion 3 "0100dca0064a6000", // Luigi's Mansion 3
//Metroid Franchise
"010093801237c000", // Metroid Dread "010093801237c000", // Metroid Dread
"010012101468c000", // Metroid Prime Remastered "010012101468c000", // Metroid Prime Remastered
"0100000000010000", // SUPER MARIO ODYSSEY //Monster Hunter Franchise
"0100ea80032ea000", // Super Mario Bros. U Deluxe "0100770008dd8000", // Monster Hunter Generations Ultimate
"01009b90006dc000", // Super Mario Maker 2 "0100b04011742000", // Monster Hunter Rise
"010049900f546000", // Super Mario 3D All-Stars
"010049900F546001", // ^ 64 //Mario Franchise
"010049900F546002", // ^ Sunshine "010021d00812a000", // Arcade Archives VS. SUPER MARIO BROS.
"010049900F546003", // ^ Galaxy
"010028600ebda000", // Super Mario 3D World + Bowser's Fury
"010015100b514000", // Super Mario Bros. Wonder
"0100152000022000", // Mario Kart 8 Deluxe
"010036b0034e4000", // Super Mario Party
"01006fe013472000", // Mario Party Superstars
"0100965017338000", // Super Mario Party Jamboree
"01006d0017f7a000", // Mario & Luigi: Brothership "01006d0017f7a000", // Mario & Luigi: Brothership
"010003000e146000", // Mario & Sonic at the Olympic Games Tokyo 2020
"010067300059a000", // Mario + Rabbids: Kingdom Battle "010067300059a000", // Mario + Rabbids: Kingdom Battle
"0100317013770000", // Mario + Rabbids: Sparks of Hope "0100317013770000", // Mario + Rabbids: Sparks of Hope
"0100c9c00e25c000", // Mario Golf: Super Rush
"0100152000022000", // Mario Kart 8 Deluxe
"01006fe013472000", // Mario Party Superstars
"010019401051c000", // Mario Strikers: Battle League
"0100bde00862a000", // Mario Tennis Aces
"0100b99019412000", // Mario vs. Donkey Kong
"010049900f546000", // Super Mario 3D All-Stars
"010028600ebda000", // Super Mario 3D World + Bowser's Fury
"010049900F546001", // Super Mario 64
"0100ea80032ea000", // Super Mario Bros. U Deluxe
"010015100b514000", // Super Mario Bros. Wonder
"010049900F546003", // Super Mario Galaxy
"01009b90006dc000", // Super Mario Maker 2
"0100000000010000", // SUPER MARIO ODYSSEY
"010036b0034e4000", // Super Mario Party
"0100965017338000", // Super Mario Party Jamboree
"0100bc0018138000", // Super Mario RPG
"010049900F546002", // Super Mario Sunshine
"0100a3900c3e2000", // Paper Mario: The Origami King "0100a3900c3e2000", // Paper Mario: The Origami King
"0100ecd018ebe000", // Paper Mario: The Thousand-Year Door "0100ecd018ebe000", // Paper Mario: The Thousand-Year Door
"0100bc0018138000", // Super Mario RPG
"0100bde00862a000", // Mario Tennis Aces
"0100c9c00e25c000", // Mario Golf: Super Rush
"010019401051c000", // Mario Strikers: Battle League
"010003000e146000", // Mario & Sonic at the Olympic Games Tokyo 2020
"0100b99019412000", // Mario vs. Donkey Kong
//Pikmin Franchise
"0100aa80194b0000", // Pikmin 1 "0100aa80194b0000", // Pikmin 1
"0100d680194b2000", // Pikmin 2 "0100d680194b2000", // Pikmin 2
"0100f4c009322000", // Pikmin 3 Deluxe "0100f4c009322000", // Pikmin 3 Deluxe
"0100b7c00933a000", // Pikmin 4 "0100b7c00933a000", // Pikmin 4
//The Pokémon Franchise
"0100f4300bf2c000", // New Pokémon Snap "0100f4300bf2c000", // New Pokémon Snap
"0100000011d90000", // Pokémon Brilliant Diamond "0100000011d90000", // Pokémon Brilliant Diamond
"01001f5010dfa000", // Pokémon Legends: Arceus "01001f5010dfa000", // Pokémon Legends: Arceus
"010003f003a34000", // Pokémon: Let's Go Pikachu!
"0100187003a36000", // Pokémon: Let's Go Eevee!
"01003d200baa2000", // Pokémon Mystery Dungeon - Rescue Team DX "01003d200baa2000", // Pokémon Mystery Dungeon - Rescue Team DX
"0100a3d008c5c000", // Pokémon Scarlet "0100a3d008c5c000", // Pokémon Scarlet
"01008db008c2c000", // Pokémon Shield "01008db008c2c000", // Pokémon Shield
@@ -120,24 +148,29 @@ namespace Ryujinx.Common
"0100abf008968000", // Pokémon Sword "0100abf008968000", // Pokémon Sword
"01008f6008c5e000", // Pokémon Violet "01008f6008c5e000", // Pokémon Violet
"0100b3f000be2000", // Pokkén Tournament DX "0100b3f000be2000", // Pokkén Tournament DX
"0100187003a36000", // Pokémon: Let's Go Eevee!
"010003f003a34000", // Pokémon: Let's Go Pikachu!
"01003bc0000a0000", // Splatoon 2 (US) //Splatoon Franchise
"0100f8f0000a2000", // Splatoon 2 (EU) "0100f8f0000a2000", // Splatoon 2 (EU)
"01003c700009c000", // Splatoon 2 (JP) "01003c700009c000", // Splatoon 2 (JP)
"01003bc0000a0000", // Splatoon 2 (US)
"0100c2500fc20000", // Splatoon 3 "0100c2500fc20000", // Splatoon 3
"0100ba0018500000", // Splatoon 3: Splatfest World Premiere "0100ba0018500000", // Splatoon 3: Splatfest World Premiere
"010040600c5ce000", // Tetris 99 //NSO Membership games
"0100277011f1a000", // Super Mario Bros. 35
"0100ad9012510000", // PAC-MAN 99
"0100ccf019c8c000", // F-ZERO 99 "0100ccf019c8c000", // F-ZERO 99
"0100d870045b6000", // NES - Nintendo Switch Online
"01008d300c50c000", // SNES - Nintendo Switch Online
"0100c9a00ece6000", // N64 - Nintendo Switch Online
"0100e0601c632000", // N64 - Nintendo Switch Online 18+
"0100c62011050000", // GB - Nintendo Switch Online "0100c62011050000", // GB - Nintendo Switch Online
"010012f017576000", // GBA - Nintendo Switch Online "010012f017576000", // GBA - Nintendo Switch Online
"0100c9a00ece6000", // N64 - Nintendo Switch Online
"0100e0601c632000", // N64 - Nintendo Switch Online 18+
"0100d870045b6000", // NES - Nintendo Switch Online
"0100ad9012510000", // PAC-MAN 99
"010040600c5ce000", // Tetris 99
"01008d300c50c000", // SNES - Nintendo Switch Online
"0100277011f1a000", // Super Mario Bros. 35
//Misc Nintendo 1st party games
"01000320000cc000", // 1-2 Switch "01000320000cc000", // 1-2 Switch
"0100300012f2a000", // Advance Wars 1+2: Re-Boot Camp "0100300012f2a000", // Advance Wars 1+2: Re-Boot Camp
"01006f8002326000", // Animal Crossing: New Horizons "01006f8002326000", // Animal Crossing: New Horizons
@@ -152,57 +185,69 @@ namespace Ryujinx.Common
"01006a800016e000", // Super Smash Bros. Ultimate "01006a800016e000", // Super Smash Bros. Ultimate
"0100a9400c9c2000", // Tokyo Mirage Sessions #FE Encore "0100a9400c9c2000", // Tokyo Mirage Sessions #FE Encore
//Bayonetta Franchise
"010076f0049a2000", // Bayonetta "010076f0049a2000", // Bayonetta
"01007960049a0000", // Bayonetta 2 "01007960049a0000", // Bayonetta 2
"01004a4010fea000", // Bayonetta 3 "01004a4010fea000", // Bayonetta 3
"0100cf5010fec000", // Bayonetta Origins: Cereza and the Lost Demon "0100cf5010fec000", // Bayonetta Origins: Cereza and the Lost Demon
//Persona Franchise
"0100dcd01525a000", // Persona 3 Portable "0100dcd01525a000", // Persona 3 Portable
"010062b01525c000", // Persona 4 Golden
"010075a016a3a000", // Persona 4 Arena Ultimax "010075a016a3a000", // Persona 4 Arena Ultimax
"010062b01525c000", // Persona 4 Golden
"01005ca01580e000", // Persona 5 Royal "01005ca01580e000", // Persona 5 Royal
"0100801011c3e000", // Persona 5 Strikers "0100801011c3e000", // Persona 5 Strikers
"010087701b092000", // Persona 5 Tactica "010087701b092000", // Persona 5 Tactica
"01009aa000faa000", // Sonic Mania //Sonic Franchise
"01004ad014bf0000", // Sonic Frontiers "01004ad014bf0000", // Sonic Frontiers
"01009aa000faa000", // Sonic Mania
"01005ea01c0fc000", // SONIC X SHADOW GENERATIONS "01005ea01c0fc000", // SONIC X SHADOW GENERATIONS
"01005ea01c0fc001", // ^ "01005ea01c0fc001", // ^
//Xenoblade Franchise
"0100ff500e34a000", // Xenoblade Chronicles - Definitive Edition "0100ff500e34a000", // Xenoblade Chronicles - Definitive Edition
"0100e95004038000", // Xenoblade Chronicles 2 "0100e95004038000", // Xenoblade Chronicles 2
"010074f013262000", // Xenoblade Chronicles 3 "010074f013262000", // Xenoblade Chronicles 3
//Misc Games
"010056e00853a000", // A Hat in Time "010056e00853a000", // A Hat in Time
"0100fd1014726000", // Baldurs Gate: Dark Alliance "0100fd1014726000", // Baldurs Gate: Dark Alliance
"0100c6800b934000", // Brawlhalla
"0100dbf01000a000", // Burnout Paradise Remastered "0100dbf01000a000", // Burnout Paradise Remastered
"0100744001588000", // Cars 3: Driven to Win "0100744001588000", // Cars 3: Driven to Win
"0100b41013c82000", // Cruis'n Blast "0100b41013c82000", // Cruis'n Blast
"010085900337e000", // Death Squared "010085900337e000", // Death Squared
"01001b300b9be000", // Diablo III: Eternal Collection "01001b300b9be000", // Diablo III: Eternal Collection
"010027400cdc6000", // Divinity Original 2 - Definitive Edition
"01008c8012920000", // Dying Light Platinum Edition "01008c8012920000", // Dying Light Platinum Edition
"01001cc01b2d4000", // Goat Simulator 3 "01001cc01b2d4000", // Goat Simulator 3
"01003620068ea000", // Hand of Fate 2 "01003620068ea000", // Hand of Fate 2
"010085500130a000", // Lego City: Undercover "010085500130a000", // Lego City: Undercover
"010073c01af34000", // LEGO Horizon Adventures "010073c01af34000", // LEGO Horizon Adventures
"0100770008dd8000", // Monster Hunter Generations Ultimate "0100d71004694000", // Minecraft
"0100b04011742000", // Monster Hunter Rise "01007430037f6000", // Monopoly
"0100853015e86000", // No Man's Sky "0100853015e86000", // No Man's Sky
"01007bb017812000", // Portal "01007bb017812000", // Portal
"0100abd01785c000", // Portal 2 "0100abd01785c000", // Portal 2
"01008e200c5c2000", // Muse Dash "01008e200c5c2000", // Muse Dash
"01007820196a6000", // Red Dead Redemption "01007820196a6000", // Red Dead Redemption
"0100e8300a67a000", // Risk
"01002f7013224000", // Rune Factory 5 "01002f7013224000", // Rune Factory 5
"01008d100d43e000", // Saints Row IV "01008d100d43e000", // Saints Row IV
"0100de600beee000", // Saints Row: The Third - The Full Package "0100de600beee000", // Saints Row: The Third - The Full Package
"01001180021fa000", // Shovel Knight: Specter of Torment "01001180021fa000", // Shovel Knight: Specter of Torment
"0100e65002bb8000", // Stardew Valley
"0100d7a01b7a2000", // Star Wars: Bounty Hunter "0100d7a01b7a2000", // Star Wars: Bounty Hunter
"0100800015926000", // Suika Game "0100800015926000", // Suika Game
"01007ad00013e000", // Super Bomberman R
"0100e46006708000", // Terraria "0100e46006708000", // Terraria
"0100605008268000", // Titan Quest
"01000a10041ea000", // The Elder Scrolls V: Skyrim "01000a10041ea000", // The Elder Scrolls V: Skyrim
"010057a01e4d4000", // TSUKIHIME -A piece of blue glass moon- "010057a01e4d4000", // TSUKIHIME -A piece of blue glass moon-
"010080b00ad66000", // Undertale "010080b00ad66000", // Undertale
"010069401adb8000", // Unicorn Overlord "010069401adb8000", // Unicorn Overlord
"01005c600ac68000", // Valkyria Chronicles 4
"0100534009ff2000", // Yonder - The cloud catcher chronicles "0100534009ff2000", // Yonder - The cloud catcher chronicles
]; ];
} }

View File

@@ -19,21 +19,21 @@ namespace Ryujinx.Common
public static byte[] Read(string filename) public static byte[] Read(string filename)
{ {
var (assembly, path) = ResolveManifestPath(filename); (Assembly assembly, string path) = ResolveManifestPath(filename);
return Read(assembly, path); return Read(assembly, path);
} }
public static Task<byte[]> ReadAsync(string filename) public static Task<byte[]> ReadAsync(string filename)
{ {
var (assembly, path) = ResolveManifestPath(filename); (Assembly assembly, string path) = ResolveManifestPath(filename);
return ReadAsync(assembly, path); return ReadAsync(assembly, path);
} }
public static byte[] Read(Assembly assembly, string filename) public static byte[] Read(Assembly assembly, string filename)
{ {
using var stream = GetStream(assembly, filename); using Stream stream = GetStream(assembly, filename);
if (stream == null) if (stream == null)
{ {
return null; return null;
@@ -44,14 +44,14 @@ namespace Ryujinx.Common
public static MemoryOwner<byte> ReadFileToRentedMemory(string filename) public static MemoryOwner<byte> ReadFileToRentedMemory(string filename)
{ {
var (assembly, path) = ResolveManifestPath(filename); (Assembly assembly, string path) = ResolveManifestPath(filename);
return ReadFileToRentedMemory(assembly, path); return ReadFileToRentedMemory(assembly, path);
} }
public static MemoryOwner<byte> ReadFileToRentedMemory(Assembly assembly, string filename) public static MemoryOwner<byte> ReadFileToRentedMemory(Assembly assembly, string filename)
{ {
using var stream = GetStream(assembly, filename); using Stream stream = GetStream(assembly, filename);
return stream is null return stream is null
? null ? null
@@ -60,7 +60,7 @@ namespace Ryujinx.Common
public async static Task<byte[]> ReadAsync(Assembly assembly, string filename) public async static Task<byte[]> ReadAsync(Assembly assembly, string filename)
{ {
using var stream = GetStream(assembly, filename); using Stream stream = GetStream(assembly, filename);
if (stream == null) if (stream == null)
{ {
return null; return null;
@@ -71,55 +71,55 @@ namespace Ryujinx.Common
public static string ReadAllText(string filename) public static string ReadAllText(string filename)
{ {
var (assembly, path) = ResolveManifestPath(filename); (Assembly assembly, string path) = ResolveManifestPath(filename);
return ReadAllText(assembly, path); return ReadAllText(assembly, path);
} }
public static Task<string> ReadAllTextAsync(string filename) public static Task<string> ReadAllTextAsync(string filename)
{ {
var (assembly, path) = ResolveManifestPath(filename); (Assembly assembly, string path) = ResolveManifestPath(filename);
return ReadAllTextAsync(assembly, path); return ReadAllTextAsync(assembly, path);
} }
public static string ReadAllText(Assembly assembly, string filename) public static string ReadAllText(Assembly assembly, string filename)
{ {
using var stream = GetStream(assembly, filename); using Stream stream = GetStream(assembly, filename);
if (stream == null) if (stream == null)
{ {
return null; return null;
} }
using var reader = new StreamReader(stream); using StreamReader reader = new StreamReader(stream);
return reader.ReadToEnd(); return reader.ReadToEnd();
} }
public async static Task<string> ReadAllTextAsync(Assembly assembly, string filename) public async static Task<string> ReadAllTextAsync(Assembly assembly, string filename)
{ {
using var stream = GetStream(assembly, filename); using Stream stream = GetStream(assembly, filename);
if (stream == null) if (stream == null)
{ {
return null; return null;
} }
using var reader = new StreamReader(stream); using StreamReader reader = new StreamReader(stream);
return await reader.ReadToEndAsync(); return await reader.ReadToEndAsync();
} }
public static Stream GetStream(string filename) public static Stream GetStream(string filename)
{ {
var (assembly, path) = ResolveManifestPath(filename); (Assembly assembly, string path) = ResolveManifestPath(filename);
return GetStream(assembly, path); return GetStream(assembly, path);
} }
public static Stream GetStream(Assembly assembly, string filename) public static Stream GetStream(Assembly assembly, string filename)
{ {
var @namespace = assembly.GetName().Name; string @namespace = assembly.GetName().Name;
var manifestUri = @namespace + "." + filename.Replace('/', '.'); string manifestUri = @namespace + "." + filename.Replace('/', '.');
var stream = assembly.GetManifestResourceStream(manifestUri); Stream stream = assembly.GetManifestResourceStream(manifestUri);
return stream; return stream;
} }
@@ -133,11 +133,11 @@ namespace Ryujinx.Common
private static (Assembly, string) ResolveManifestPath(string filename) private static (Assembly, string) ResolveManifestPath(string filename)
{ {
var segments = filename.Split('/', 2, StringSplitOptions.RemoveEmptyEntries); string[] segments = filename.Split('/', 2, StringSplitOptions.RemoveEmptyEntries);
if (segments.Length >= 2) if (segments.Length >= 2)
{ {
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
{ {
if (assembly.GetName().Name == segments[0]) if (assembly.GetName().Name == segments[0])
{ {

View File

@@ -9,7 +9,7 @@ namespace Ryujinx.Common.Utilities
public static void CopyDirectory(string sourceDir, string destinationDir, bool recursive) public static void CopyDirectory(string sourceDir, string destinationDir, bool recursive)
{ {
// Get information about the source directory // Get information about the source directory
var dir = new DirectoryInfo(sourceDir); DirectoryInfo dir = new DirectoryInfo(sourceDir);
// Check if the source directory exists // Check if the source directory exists
if (!dir.Exists) if (!dir.Exists)
@@ -49,7 +49,7 @@ namespace Ryujinx.Common.Utilities
public static string SanitizeFileName(string fileName) public static string SanitizeFileName(string fileName)
{ {
var reservedChars = new HashSet<char>(Path.GetInvalidFileNameChars()); HashSet<char> reservedChars = new HashSet<char>(Path.GetInvalidFileNameChars());
return string.Concat(fileName.Select(c => reservedChars.Contains(c) ? '_' : c)); return string.Concat(fileName.Select(c => reservedChars.Contains(c) ? '_' : c));
} }
} }

View File

@@ -1,5 +1,6 @@
using MsgPack; using MsgPack;
using System; using System;
using System.Collections.Generic;
using System.Text; using System.Text;
namespace Ryujinx.Common.Utilities namespace Ryujinx.Common.Utilities
@@ -18,7 +19,7 @@ namespace Ryujinx.Common.Utilities
public static string Format(MessagePackObject obj) public static string Format(MessagePackObject obj)
{ {
var builder = new IndentedStringBuilder(); IndentedStringBuilder builder = new IndentedStringBuilder();
FormatMsgPackObj(obj, builder); FormatMsgPackObj(obj, builder);
@@ -41,7 +42,7 @@ namespace Ryujinx.Common.Utilities
} }
else else
{ {
var literal = obj.ToObject(); object literal = obj.ToObject();
if (literal is String) if (literal is String)
{ {
@@ -88,7 +89,7 @@ namespace Ryujinx.Common.Utilities
{ {
builder.Append("[ "); builder.Append("[ ");
foreach (var b in arr) foreach (byte b in arr)
{ {
builder.Append("0x"); builder.Append("0x");
builder.Append(ToHexChar(b >> 4)); builder.Append(ToHexChar(b >> 4));
@@ -111,7 +112,7 @@ namespace Ryujinx.Common.Utilities
builder.Append("0x"); builder.Append("0x");
} }
foreach (var b in arr) foreach (byte b in arr)
{ {
builder.Append(ToHexChar(b >> 4)); builder.Append(ToHexChar(b >> 4));
builder.Append(ToHexChar(b & 0xF)); builder.Append(ToHexChar(b & 0xF));
@@ -122,7 +123,7 @@ namespace Ryujinx.Common.Utilities
private static void FormatMsgPackMap(MessagePackObject obj, IndentedStringBuilder builder) private static void FormatMsgPackMap(MessagePackObject obj, IndentedStringBuilder builder)
{ {
var map = obj.AsDictionary(); MessagePackObjectDictionary map = obj.AsDictionary();
builder.Append('{'); builder.Append('{');
@@ -130,7 +131,7 @@ namespace Ryujinx.Common.Utilities
builder.IncreaseIndent() builder.IncreaseIndent()
.AppendLine(); .AppendLine();
foreach (var item in map) foreach (KeyValuePair<MessagePackObject, MessagePackObject> item in map)
{ {
FormatMsgPackObj(item.Key, builder); FormatMsgPackObj(item.Key, builder);
@@ -154,11 +155,11 @@ namespace Ryujinx.Common.Utilities
private static void FormatMsgPackArray(MessagePackObject obj, IndentedStringBuilder builder) private static void FormatMsgPackArray(MessagePackObject obj, IndentedStringBuilder builder)
{ {
var arr = obj.AsList(); IList<MessagePackObject> arr = obj.AsList();
builder.Append("[ "); builder.Append("[ ");
foreach (var item in arr) foreach (MessagePackObject item in arr)
{ {
FormatMsgPackObj(item, builder); FormatMsgPackObj(item, builder);

View File

@@ -0,0 +1,110 @@
using Gommon;
using System;
using System.Drawing;
using System.Threading.Tasks;
namespace Ryujinx.Common.Utilities
{
public static class Rainbow
{
public static bool CyclingEnabled { get; set; }
public static void Enable()
{
if (!CyclingEnabled)
{
CyclingEnabled = true;
Executor.ExecuteBackgroundAsync(async () =>
{
while (CyclingEnabled)
{
await Task.Delay(15);
Tick();
}
});
}
}
public static void Disable()
{
CyclingEnabled = false;
}
public static float Speed { get; set; } = 1;
public static Color Color { get; private set; } = Color.Blue;
public static void Tick()
{
Color = HsbToRgb((Color.GetHue() + Speed) / 360);
UpdatedHandler.Call(Color.ToArgb());
}
public static void Reset()
{
Color = Color.Blue;
UpdatedHandler.Clear();
}
public static event Action<int> Updated
{
add => UpdatedHandler.Add(value);
remove => UpdatedHandler.Remove(value);
}
internal static Event<int> UpdatedHandler = new();
private static Color HsbToRgb(float hue, float saturation = 1, float brightness = 1)
{
int r = 0, g = 0, b = 0;
if (saturation == 0)
{
r = g = b = (int)(brightness * 255.0f + 0.5f);
}
else
{
float h = (hue - (float)Math.Floor(hue)) * 6.0f;
float f = h - (float)Math.Floor(h);
float p = brightness * (1.0f - saturation);
float q = brightness * (1.0f - saturation * f);
float t = brightness * (1.0f - (saturation * (1.0f - f)));
switch ((int)h)
{
case 0:
r = (int)(brightness * 255.0f + 0.5f);
g = (int)(t * 255.0f + 0.5f);
b = (int)(p * 255.0f + 0.5f);
break;
case 1:
r = (int)(q * 255.0f + 0.5f);
g = (int)(brightness * 255.0f + 0.5f);
b = (int)(p * 255.0f + 0.5f);
break;
case 2:
r = (int)(p * 255.0f + 0.5f);
g = (int)(brightness * 255.0f + 0.5f);
b = (int)(t * 255.0f + 0.5f);
break;
case 3:
r = (int)(p * 255.0f + 0.5f);
g = (int)(q * 255.0f + 0.5f);
b = (int)(brightness * 255.0f + 0.5f);
break;
case 4:
r = (int)(t * 255.0f + 0.5f);
g = (int)(p * 255.0f + 0.5f);
b = (int)(brightness * 255.0f + 0.5f);
break;
case 5:
r = (int)(brightness * 255.0f + 0.5f);
g = (int)(p * 255.0f + 0.5f);
b = (int)(q * 255.0f + 0.5f);
break;
}
}
return Color.FromArgb(Convert.ToByte(255), Convert.ToByte(r), Convert.ToByte(g), Convert.ToByte(b));
}
}
}

View File

@@ -1,5 +1,6 @@
using Microsoft.IO; using Microsoft.IO;
using Ryujinx.Common.Memory; using Ryujinx.Common.Memory;
using System;
using System.IO; using System.IO;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@@ -27,7 +28,7 @@ namespace Ryujinx.Common.Utilities
MemoryOwner<byte> ownedMemory = MemoryOwner<byte>.Rent(checked((int)bytesExpected)); MemoryOwner<byte> ownedMemory = MemoryOwner<byte>.Rent(checked((int)bytesExpected));
var destSpan = ownedMemory.Span; Span<byte> destSpan = ownedMemory.Span;
int totalBytesRead = 0; int totalBytesRead = 0;

View File

@@ -18,7 +18,7 @@ namespace Ryujinx.Common.Utilities
{ {
public override TEnum Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) public override TEnum Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{ {
var enumValue = reader.GetString(); string? enumValue = reader.GetString();
if (Enum.TryParse(enumValue, out TEnum value)) if (Enum.TryParse(enumValue, out TEnum value))
{ {

View File

@@ -46,7 +46,7 @@ namespace Ryujinx.Common.Utilities
{ {
if (Path.GetExtension(filename).Equals(".XCI", StringComparison.InvariantCultureIgnoreCase)) if (Path.GetExtension(filename).Equals(".XCI", StringComparison.InvariantCultureIgnoreCase))
{ {
var trimmer = new XCIFileTrimmer(filename, log); XCIFileTrimmer trimmer = new XCIFileTrimmer(filename, log);
return trimmer.CanBeTrimmed; return trimmer.CanBeTrimmed;
} }
@@ -57,7 +57,7 @@ namespace Ryujinx.Common.Utilities
{ {
if (Path.GetExtension(filename).Equals(".XCI", StringComparison.InvariantCultureIgnoreCase)) if (Path.GetExtension(filename).Equals(".XCI", StringComparison.InvariantCultureIgnoreCase))
{ {
var trimmer = new XCIFileTrimmer(filename, log); XCIFileTrimmer trimmer = new XCIFileTrimmer(filename, log);
return trimmer.CanBeUntrimmed; return trimmer.CanBeUntrimmed;
} }
@@ -201,7 +201,7 @@ namespace Ryujinx.Common.Utilities
{ {
long maxReads = readSizeB / XCIFileTrimmer.BufferSize; long maxReads = readSizeB / XCIFileTrimmer.BufferSize;
long read = 0; long read = 0;
var buffer = new byte[BufferSize]; byte[] buffer = new byte[BufferSize];
while (true) while (true)
{ {
@@ -267,7 +267,7 @@ namespace Ryujinx.Common.Utilities
try try
{ {
var info = new FileInfo(Filename); FileInfo info = new FileInfo(Filename);
if ((info.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly) if ((info.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
{ {
try try
@@ -288,7 +288,7 @@ namespace Ryujinx.Common.Utilities
return OperationOutcome.FileSizeChanged; return OperationOutcome.FileSizeChanged;
} }
var outfileStream = new FileStream(_filename, FileMode.Open, FileAccess.Write, FileShare.Write); FileStream outfileStream = new FileStream(_filename, FileMode.Open, FileAccess.Write, FileShare.Write);
try try
{ {
@@ -327,7 +327,7 @@ namespace Ryujinx.Common.Utilities
{ {
Log?.Write(LogType.Info, "Untrimming..."); Log?.Write(LogType.Info, "Untrimming...");
var info = new FileInfo(Filename); FileInfo info = new FileInfo(Filename);
if ((info.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly) if ((info.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
{ {
try try
@@ -348,7 +348,7 @@ namespace Ryujinx.Common.Utilities
return OperationOutcome.FileSizeChanged; return OperationOutcome.FileSizeChanged;
} }
var outfileStream = new FileStream(_filename, FileMode.Append, FileAccess.Write, FileShare.Write); FileStream outfileStream = new FileStream(_filename, FileMode.Append, FileAccess.Write, FileShare.Write);
long bytesToWriteB = UntrimmedFileSizeB - FileSizeB; long bytesToWriteB = UntrimmedFileSizeB - FileSizeB;
try try
@@ -393,7 +393,7 @@ namespace Ryujinx.Common.Utilities
try try
{ {
var buffer = new byte[BufferSize]; byte[] buffer = new byte[BufferSize];
Array.Fill<byte>(buffer, XCIFileTrimmer.PaddingByte); Array.Fill<byte>(buffer, XCIFileTrimmer.PaddingByte);
while (bytesLeftToWriteB > 0) while (bytesLeftToWriteB > 0)

View File

@@ -49,7 +49,7 @@ namespace ARMeilleure.Common
public TableSparseBlock(ulong size, Action<IntPtr> ensureMapped, PageInitDelegate pageInit) public TableSparseBlock(ulong size, Action<IntPtr> ensureMapped, PageInitDelegate pageInit)
{ {
var block = new SparseMemoryBlock(size, pageInit, null); SparseMemoryBlock block = new SparseMemoryBlock(size, pageInit, null);
_trackingEvent = (ulong address, ulong size, bool write) => _trackingEvent = (ulong address, ulong size, bool write) =>
{ {
@@ -146,7 +146,7 @@ namespace ARMeilleure.Common
Levels = levels; Levels = levels;
Mask = 0; Mask = 0;
foreach (var level in Levels) foreach (AddressTableLevel level in Levels)
{ {
Mask |= level.Mask; Mask |= level.Mask;
} }
@@ -363,7 +363,7 @@ namespace ARMeilleure.Common
/// <returns>The new sparse block that was added</returns> /// <returns>The new sparse block that was added</returns>
private TableSparseBlock ReserveNewSparseBlock() private TableSparseBlock ReserveNewSparseBlock()
{ {
var block = new TableSparseBlock(_sparseBlockSize, EnsureMapped, InitLeafPage); TableSparseBlock block = new TableSparseBlock(_sparseBlockSize, EnsureMapped, InitLeafPage);
_sparseReserved.Add(block); _sparseReserved.Add(block);
_sparseReservedOffset = 0; _sparseReservedOffset = 0;
@@ -381,7 +381,7 @@ namespace ARMeilleure.Common
/// <returns>Allocated block</returns> /// <returns>Allocated block</returns>
private IntPtr Allocate<T>(int length, T fill, bool leaf) where T : unmanaged private IntPtr Allocate<T>(int length, T fill, bool leaf) where T : unmanaged
{ {
var size = sizeof(T) * length; int size = sizeof(T) * length;
AddressTablePage page; AddressTablePage page;
@@ -413,10 +413,10 @@ namespace ARMeilleure.Common
} }
else else
{ {
var address = (IntPtr)NativeAllocator.Instance.Allocate((uint)size); IntPtr address = (IntPtr)NativeAllocator.Instance.Allocate((uint)size);
page = new AddressTablePage(false, address); page = new AddressTablePage(false, address);
var span = new Span<T>((void*)page.Address, length); Span<T> span = new Span<T>((void*)page.Address, length);
span.Fill(fill); span.Fill(fill);
} }
@@ -445,7 +445,7 @@ namespace ARMeilleure.Common
{ {
if (!_disposed) if (!_disposed)
{ {
foreach (var page in _pages) foreach (AddressTablePage page in _pages)
{ {
if (!page.IsSparse) if (!page.IsSparse)
{ {

View File

@@ -29,7 +29,7 @@ namespace Ryujinx.Cpu.AppleHv
public HvAddressSpace(MemoryBlock backingMemory, ulong asSize) public HvAddressSpace(MemoryBlock backingMemory, ulong asSize)
{ {
(_asBase, var ipaAllocator) = HvVm.CreateAddressSpace(backingMemory); (_asBase, HvIpaAllocator ipaAllocator) = HvVm.CreateAddressSpace(backingMemory);
_backingSize = backingMemory.Size; _backingSize = backingMemory.Size;
_userRange = new HvAddressSpaceRange(ipaAllocator); _userRange = new HvAddressSpaceRange(ipaAllocator);

View File

@@ -45,7 +45,7 @@ namespace Ryujinx.Cpu.AppleHv
public HvMemoryBlockAllocation Allocate(ulong size, ulong alignment) public HvMemoryBlockAllocation Allocate(ulong size, ulong alignment)
{ {
var allocation = Allocate(size, alignment, CreateBlock); Allocation allocation = Allocate(size, alignment, CreateBlock);
return new HvMemoryBlockAllocation(this, allocation.Block, allocation.Offset, allocation.Size); return new HvMemoryBlockAllocation(this, allocation.Block, allocation.Offset, allocation.Size);
} }

View File

@@ -233,13 +233,13 @@ namespace Ryujinx.Cpu.AppleHv
yield break; yield break;
} }
var guestRegions = GetPhysicalRegionsImpl(va, size); IEnumerable<MemoryRange> guestRegions = GetPhysicalRegionsImpl(va, size);
if (guestRegions == null) if (guestRegions == null)
{ {
yield break; yield break;
} }
foreach (var guestRegion in guestRegions) foreach (MemoryRange guestRegion in guestRegions)
{ {
nint pointer = _backingMemory.GetPointer(guestRegion.Address, guestRegion.Size); nint pointer = _backingMemory.GetPointer(guestRegion.Address, guestRegion.Size);
yield return new HostMemoryRange((nuint)(ulong)pointer, guestRegion.Size); yield return new HostMemoryRange((nuint)(ulong)pointer, guestRegion.Size);
@@ -254,7 +254,7 @@ namespace Ryujinx.Cpu.AppleHv
yield break; yield break;
} }
foreach (var physicalRegion in GetPhysicalRegionsImpl(va, size)) foreach (MemoryRange physicalRegion in GetPhysicalRegionsImpl(va, size))
{ {
yield return physicalRegion; yield return physicalRegion;
} }

View File

@@ -41,7 +41,7 @@ namespace Ryujinx.Cpu.AppleHv
{ {
// Calculate our time delta in ticks based on the current clock frequency. // Calculate our time delta in ticks based on the current clock frequency.
int result = TimeApi.mach_timebase_info(out var timeBaseInfo); int result = TimeApi.mach_timebase_info(out MachTimebaseInfo timeBaseInfo);
Debug.Assert(result == 0); Debug.Assert(result == 0);

View File

@@ -39,7 +39,7 @@ namespace Ryujinx.Cpu.AppleHv
baseAddress = ipaAllocator.Allocate(block.Size, AsIpaAlignment); baseAddress = ipaAllocator.Allocate(block.Size, AsIpaAlignment);
} }
var rwx = HvMemoryFlags.Read | HvMemoryFlags.Write | HvMemoryFlags.Exec; HvMemoryFlags rwx = HvMemoryFlags.Read | HvMemoryFlags.Write | HvMemoryFlags.Exec;
HvApi.hv_vm_map((ulong)block.Pointer, baseAddress, block.Size, rwx).ThrowOnError(); HvApi.hv_vm_map((ulong)block.Pointer, baseAddress, block.Size, rwx).ThrowOnError();

View File

@@ -127,7 +127,7 @@ namespace Ryujinx.Cpu.Jit.HostTracked
Debug.Assert(leftSize > 0); Debug.Assert(leftSize > 0);
Debug.Assert(rightSize > 0); Debug.Assert(rightSize > 0);
(var leftAllocation, PrivateAllocation) = PrivateAllocation.Split(leftSize); (PrivateMemoryAllocation leftAllocation, PrivateAllocation) = PrivateAllocation.Split(leftSize);
PrivateMapping left = new(Address, leftSize, leftAllocation); PrivateMapping left = new(Address, leftSize, leftAllocation);

View File

@@ -253,13 +253,13 @@ namespace Ryujinx.Cpu.Jit
yield break; yield break;
} }
var guestRegions = GetPhysicalRegionsImpl(va, size); IEnumerable<MemoryRange> guestRegions = GetPhysicalRegionsImpl(va, size);
if (guestRegions == null) if (guestRegions == null)
{ {
yield break; yield break;
} }
foreach (var guestRegion in guestRegions) foreach (MemoryRange guestRegion in guestRegions)
{ {
nint pointer = _backingMemory.GetPointer(guestRegion.Address, guestRegion.Size); nint pointer = _backingMemory.GetPointer(guestRegion.Address, guestRegion.Size);
yield return new HostMemoryRange((nuint)(ulong)pointer, guestRegion.Size); yield return new HostMemoryRange((nuint)(ulong)pointer, guestRegion.Size);
@@ -274,7 +274,7 @@ namespace Ryujinx.Cpu.Jit
yield break; yield break;
} }
foreach (var physicalRegion in GetPhysicalRegionsImpl(va, size)) foreach (MemoryRange physicalRegion in GetPhysicalRegionsImpl(va, size))
{ {
yield return physicalRegion; yield return physicalRegion;
} }

View File

@@ -340,7 +340,7 @@ namespace Ryujinx.Cpu.Jit
{ {
int pages = GetPagesCount(va, (uint)size, out va); int pages = GetPagesCount(va, (uint)size, out va);
var regions = new List<MemoryRange>(); List<MemoryRange> regions = new List<MemoryRange>();
ulong regionStart = GetPhysicalAddressChecked(va); ulong regionStart = GetPhysicalAddressChecked(va);
ulong regionSize = PageSize; ulong regionSize = PageSize;

View File

@@ -240,7 +240,7 @@ namespace Ryujinx.Cpu.Jit
if (TryGetVirtualContiguous(va, data.Length, out MemoryBlock memoryBlock, out ulong offset)) if (TryGetVirtualContiguous(va, data.Length, out MemoryBlock memoryBlock, out ulong offset))
{ {
var target = memoryBlock.GetSpan(offset, data.Length); Span<byte> target = memoryBlock.GetSpan(offset, data.Length);
bool changed = !data.SequenceEqual(target); bool changed = !data.SequenceEqual(target);
@@ -443,7 +443,7 @@ namespace Ryujinx.Cpu.Jit
return null; return null;
} }
var regions = new List<HostMemoryRange>(); List<HostMemoryRange> regions = new List<HostMemoryRange>();
ulong endVa = va + size; ulong endVa = va + size;
try try

View File

@@ -205,7 +205,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
for (int i = 0; i < funcTable.Levels.Length; i++) for (int i = 0; i < funcTable.Levels.Length; i++)
{ {
var level = funcTable.Levels[i]; AddressTableLevel level = funcTable.Levels[i];
asm.Ubfx(indexReg, guestAddress, level.Index, level.Length); asm.Ubfx(indexReg, guestAddress, level.Index, level.Length);
asm.Lsl(indexReg, indexReg, Const(3)); asm.Lsl(indexReg, indexReg, Const(3));

View File

@@ -370,7 +370,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
for (int i = 0; i < funcTable.Levels.Length; i++) for (int i = 0; i < funcTable.Levels.Length; i++)
{ {
var level = funcTable.Levels[i]; AddressTableLevel level = funcTable.Levels[i];
asm.Ubfx(indexReg, guestAddress, level.Index, level.Length); asm.Ubfx(indexReg, guestAddress, level.Index, level.Length);
asm.Lsl(indexReg, indexReg, Const(3)); asm.Lsl(indexReg, indexReg, Const(3));

View File

@@ -190,7 +190,7 @@ namespace Ryujinx.Cpu.LightningJit.Cache
private bool TryGetThreadLocalFunction(ulong guestAddress, out nint funcPtr) private bool TryGetThreadLocalFunction(ulong guestAddress, out nint funcPtr)
{ {
if ((_threadLocalCache ??= new()).TryGetValue(guestAddress, out var entry)) if ((_threadLocalCache ??= new()).TryGetValue(guestAddress, out ThreadLocalCacheEntry entry))
{ {
if (entry.IncrementUseCount() >= MinCallsForPad) if (entry.IncrementUseCount() >= MinCallsForPad)
{ {

View File

@@ -41,7 +41,7 @@ namespace Ryujinx.Cpu.LightningJit.CodeGen.Arm64
{ {
int targetIndex = _code.Count; int targetIndex = _code.Count;
var state = _labels[label.AsInt32()]; LabelState state = _labels[label.AsInt32()];
state.TargetIndex = targetIndex; state.TargetIndex = targetIndex;
state.HasTarget = true; state.HasTarget = true;
@@ -68,7 +68,7 @@ namespace Ryujinx.Cpu.LightningJit.CodeGen.Arm64
{ {
int branchIndex = _code.Count; int branchIndex = _code.Count;
var state = _labels[label.AsInt32()]; LabelState state = _labels[label.AsInt32()];
state.BranchIndex = branchIndex; state.BranchIndex = branchIndex;
state.HasBranch = true; state.HasBranch = true;
@@ -94,7 +94,7 @@ namespace Ryujinx.Cpu.LightningJit.CodeGen.Arm64
{ {
int branchIndex = _code.Count; int branchIndex = _code.Count;
var state = _labels[label.AsInt32()]; LabelState state = _labels[label.AsInt32()];
state.BranchIndex = branchIndex; state.BranchIndex = branchIndex;
state.HasBranch = true; state.HasBranch = true;
@@ -113,7 +113,7 @@ namespace Ryujinx.Cpu.LightningJit.CodeGen.Arm64
{ {
int branchIndex = _code.Count; int branchIndex = _code.Count;
var state = _labels[label.AsInt32()]; LabelState state = _labels[label.AsInt32()];
state.BranchIndex = branchIndex; state.BranchIndex = branchIndex;
state.HasBranch = true; state.HasBranch = true;
@@ -342,7 +342,7 @@ namespace Ryujinx.Cpu.LightningJit.CodeGen.Arm64
public readonly void Cset(Operand rd, ArmCondition condition) public readonly void Cset(Operand rd, ArmCondition condition)
{ {
var zr = new Operand(ZrRegister, RegisterType.Integer, rd.Type); Operand zr = new Operand(ZrRegister, RegisterType.Integer, rd.Type);
Csinc(rd, zr, zr, (ArmCondition)((int)condition ^ 1)); Csinc(rd, zr, zr, (ArmCondition)((int)condition ^ 1));
} }

View File

@@ -163,14 +163,14 @@ namespace Ryujinx.Cpu.LightningJit
{ {
List<TranslatedFunction> functions = Functions.AsList(); List<TranslatedFunction> functions = Functions.AsList();
foreach (var func in functions) foreach (TranslatedFunction func in functions)
{ {
JitCache.Unmap(func.FuncPointer); JitCache.Unmap(func.FuncPointer);
} }
Functions.Clear(); Functions.Clear();
while (_oldFuncs.TryDequeue(out var kv)) while (_oldFuncs.TryDequeue(out KeyValuePair<ulong, TranslatedFunction> kv))
{ {
JitCache.Unmap(kv.Value.FuncPointer); JitCache.Unmap(kv.Value.FuncPointer);
} }

View File

@@ -174,7 +174,7 @@ namespace Ryujinx.Cpu.LightningJit
for (int i = 0; i < _functionTable.Levels.Length; i++) for (int i = 0; i < _functionTable.Levels.Length; i++)
{ {
ref var level = ref _functionTable.Levels[i]; ref AddressTableLevel level = ref _functionTable.Levels[i];
asm.Mov(mask, level.Mask >> level.Index); asm.Mov(mask, level.Mask >> level.Index);
asm.And(index, mask, guestAddress, ArmShiftType.Lsr, level.Index); asm.And(index, mask, guestAddress, ArmShiftType.Lsr, level.Index);

View File

@@ -48,7 +48,7 @@ namespace Ryujinx.Cpu
{ {
for (int i = 0; i < _freeRanges.Count; i++) for (int i = 0; i < _freeRanges.Count; i++)
{ {
var range = _freeRanges[i]; Range range = _freeRanges[i];
ulong alignedOffset = BitUtils.AlignUp(range.Offset, alignment); ulong alignedOffset = BitUtils.AlignUp(range.Offset, alignment);
ulong sizeDelta = alignedOffset - range.Offset; ulong sizeDelta = alignedOffset - range.Offset;
@@ -84,7 +84,7 @@ namespace Ryujinx.Cpu
private void InsertFreeRange(ulong offset, ulong size) private void InsertFreeRange(ulong offset, ulong size)
{ {
var range = new Range(offset, size); Range range = new Range(offset, size);
int index = _freeRanges.BinarySearch(range); int index = _freeRanges.BinarySearch(range);
if (index < 0) if (index < 0)
{ {
@@ -97,7 +97,7 @@ namespace Ryujinx.Cpu
private void InsertFreeRangeComingled(ulong offset, ulong size) private void InsertFreeRangeComingled(ulong offset, ulong size)
{ {
ulong endOffset = offset + size; ulong endOffset = offset + size;
var range = new Range(offset, size); Range range = new Range(offset, size);
int index = _freeRanges.BinarySearch(range); int index = _freeRanges.BinarySearch(range);
if (index < 0) if (index < 0)
{ {
@@ -149,7 +149,7 @@ namespace Ryujinx.Cpu
public PrivateMemoryAllocation Allocate(ulong size, ulong alignment) public PrivateMemoryAllocation Allocate(ulong size, ulong alignment)
{ {
var allocation = Allocate(size, alignment, CreateBlock); Allocation allocation = Allocate(size, alignment, CreateBlock);
return new PrivateMemoryAllocation(this, allocation.Block, allocation.Offset, allocation.Size); return new PrivateMemoryAllocation(this, allocation.Block, allocation.Offset, allocation.Size);
} }
@@ -200,7 +200,7 @@ namespace Ryujinx.Cpu
for (int i = 0; i < _blocks.Count; i++) for (int i = 0; i < _blocks.Count; i++)
{ {
var block = _blocks[i]; T block = _blocks[i];
if (block.Size >= size) if (block.Size >= size)
{ {
@@ -214,8 +214,8 @@ namespace Ryujinx.Cpu
ulong blockAlignedSize = BitUtils.AlignUp(size, _blockAlignment); ulong blockAlignedSize = BitUtils.AlignUp(size, _blockAlignment);
var memory = new MemoryBlock(blockAlignedSize, _allocationFlags); MemoryBlock memory = new MemoryBlock(blockAlignedSize, _allocationFlags);
var newBlock = createBlock(memory, blockAlignedSize); T newBlock = createBlock(memory, blockAlignedSize);
InsertBlock(newBlock); InsertBlock(newBlock);

View File

@@ -98,7 +98,7 @@ namespace Ryujinx.Cpu.Signal
_signalHandlerPtr = customSignalHandlerFactory(UnixSignalHandlerRegistration.GetSegfaultExceptionHandler().sa_handler, _signalHandlerPtr); _signalHandlerPtr = customSignalHandlerFactory(UnixSignalHandlerRegistration.GetSegfaultExceptionHandler().sa_handler, _signalHandlerPtr);
} }
var old = UnixSignalHandlerRegistration.RegisterExceptionHandler(_signalHandlerPtr); UnixSignalHandlerRegistration.SigAction old = UnixSignalHandlerRegistration.RegisterExceptionHandler(_signalHandlerPtr);
config.UnixOldSigaction = (nuint)(ulong)old.sa_handler; config.UnixOldSigaction = (nuint)(ulong)old.sa_handler;
config.UnixOldSigaction3Arg = old.sa_flags & 4; config.UnixOldSigaction3Arg = old.sa_flags & 4;

View File

@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
@@ -32,15 +33,15 @@ namespace Ryujinx.Graphics.Device
_debugLogCallback = debugLogCallback; _debugLogCallback = debugLogCallback;
} }
var fields = typeof(TState).GetFields(); FieldInfo[] fields = typeof(TState).GetFields();
int offset = 0; int offset = 0;
for (int fieldIndex = 0; fieldIndex < fields.Length; fieldIndex++) for (int fieldIndex = 0; fieldIndex < fields.Length; fieldIndex++)
{ {
var field = fields[fieldIndex]; FieldInfo field = fields[fieldIndex];
var currentFieldOffset = (int)Marshal.OffsetOf<TState>(field.Name); int currentFieldOffset = (int)Marshal.OffsetOf<TState>(field.Name);
var nextFieldOffset = fieldIndex + 1 == fields.Length ? Unsafe.SizeOf<TState>() : (int)Marshal.OffsetOf<TState>(fields[fieldIndex + 1].Name); int nextFieldOffset = fieldIndex + 1 == fields.Length ? Unsafe.SizeOf<TState>() : (int)Marshal.OffsetOf<TState>(fields[fieldIndex + 1].Name);
int sizeOfField = nextFieldOffset - currentFieldOffset; int sizeOfField = nextFieldOffset - currentFieldOffset;
@@ -48,7 +49,7 @@ namespace Ryujinx.Graphics.Device
{ {
int index = (offset + i) / RegisterSize; int index = (offset + i) / RegisterSize;
if (callbacks != null && callbacks.TryGetValue(field.Name, out var cb)) if (callbacks != null && callbacks.TryGetValue(field.Name, out RwCallback cb))
{ {
if (cb.Read != null) if (cb.Read != null)
{ {
@@ -81,7 +82,7 @@ namespace Ryujinx.Graphics.Device
{ {
uint alignedOffset = index * RegisterSize; uint alignedOffset = index * RegisterSize;
var readCallback = Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(_readCallbacks), (nint)index); Func<int> readCallback = Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(_readCallbacks), (nint)index);
if (readCallback != null) if (readCallback != null)
{ {
return readCallback(); return readCallback();
@@ -119,7 +120,7 @@ namespace Ryujinx.Graphics.Device
uint alignedOffset = index * RegisterSize; uint alignedOffset = index * RegisterSize;
DebugWrite(alignedOffset, data); DebugWrite(alignedOffset, data);
ref var storage = ref GetRefIntAlignedUncheck(index); ref int storage = ref GetRefIntAlignedUncheck(index);
changed = storage != data; changed = storage != data;
storage = data; storage = data;

View File

@@ -359,7 +359,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading
public bool TryHostConditionalRendering(ICounterEvent value, ulong compare, bool isEqual) public bool TryHostConditionalRendering(ICounterEvent value, ulong compare, bool isEqual)
{ {
var evt = value as ThreadedCounterEvent; ThreadedCounterEvent evt = value as ThreadedCounterEvent;
if (evt != null) if (evt != null)
{ {
if (compare == 0 && evt.Type == CounterType.SamplesPassed && evt.ClearCounter) if (compare == 0 && evt.Type == CounterType.SamplesPassed && evt.ClearCounter)

View File

@@ -294,7 +294,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading
public IImageArray CreateImageArray(int size, bool isBuffer) public IImageArray CreateImageArray(int size, bool isBuffer)
{ {
var imageArray = new ThreadedImageArray(this); ThreadedImageArray imageArray = new(this);
New<CreateImageArrayCommand>().Set(Ref(imageArray), size, isBuffer); New<CreateImageArrayCommand>().Set(Ref(imageArray), size, isBuffer);
QueueCommand(); QueueCommand();
@@ -303,7 +303,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading
public IProgram CreateProgram(ShaderSource[] shaders, ShaderInfo info) public IProgram CreateProgram(ShaderSource[] shaders, ShaderInfo info)
{ {
var program = new ThreadedProgram(this); ThreadedProgram program = new(this);
SourceProgramRequest request = new(program, shaders, info); SourceProgramRequest request = new(program, shaders, info);
@@ -319,7 +319,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading
public ISampler CreateSampler(SamplerCreateInfo info) public ISampler CreateSampler(SamplerCreateInfo info)
{ {
var sampler = new ThreadedSampler(this); ThreadedSampler sampler = new(this);
New<CreateSamplerCommand>().Set(Ref(sampler), info); New<CreateSamplerCommand>().Set(Ref(sampler), info);
QueueCommand(); QueueCommand();
@@ -337,7 +337,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading
{ {
if (IsGpuThread()) if (IsGpuThread())
{ {
var texture = new ThreadedTexture(this, info); ThreadedTexture texture = new ThreadedTexture(this, info);
New<CreateTextureCommand>().Set(Ref(texture), info); New<CreateTextureCommand>().Set(Ref(texture), info);
QueueCommand(); QueueCommand();
@@ -345,7 +345,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading
} }
else else
{ {
var texture = new ThreadedTexture(this, info) ThreadedTexture texture = new ThreadedTexture(this, info)
{ {
Base = _baseRenderer.CreateTexture(info), Base = _baseRenderer.CreateTexture(info),
}; };
@@ -355,7 +355,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading
} }
public ITextureArray CreateTextureArray(int size, bool isBuffer) public ITextureArray CreateTextureArray(int size, bool isBuffer)
{ {
var textureArray = new ThreadedTextureArray(this); ThreadedTextureArray textureArray = new ThreadedTextureArray(this);
New<CreateTextureArrayCommand>().Set(Ref(textureArray), size, isBuffer); New<CreateTextureArrayCommand>().Set(Ref(textureArray), size, isBuffer);
QueueCommand(); QueueCommand();
@@ -414,7 +414,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading
public IProgram LoadProgramBinary(byte[] programBinary, bool hasFragmentShader, ShaderInfo info) public IProgram LoadProgramBinary(byte[] programBinary, bool hasFragmentShader, ShaderInfo info)
{ {
var program = new ThreadedProgram(this); ThreadedProgram program = new ThreadedProgram(this);
BinaryProgramRequest request = new(program, programBinary, hasFragmentShader, info); BinaryProgramRequest request = new(program, programBinary, hasFragmentShader, info);
Programs.Add(request); Programs.Add(request);

View File

@@ -126,7 +126,7 @@ namespace Ryujinx.Graphics.GAL
if (Descriptors != null) if (Descriptors != null)
{ {
foreach (var descriptor in Descriptors) foreach (ResourceDescriptor descriptor in Descriptors)
{ {
hasher.Add(descriptor); hasher.Add(descriptor);
} }

View File

@@ -2,6 +2,7 @@ using Ryujinx.Graphics.Device;
using Ryujinx.Graphics.Gpu.Engine.InlineToMemory; using Ryujinx.Graphics.Gpu.Engine.InlineToMemory;
using Ryujinx.Graphics.Gpu.Engine.Threed; using Ryujinx.Graphics.Gpu.Engine.Threed;
using Ryujinx.Graphics.Gpu.Engine.Types; using Ryujinx.Graphics.Gpu.Engine.Types;
using Ryujinx.Graphics.Gpu.Memory;
using Ryujinx.Graphics.Gpu.Shader; using Ryujinx.Graphics.Gpu.Shader;
using Ryujinx.Graphics.Shader; using Ryujinx.Graphics.Shader;
using System; using System;
@@ -90,7 +91,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
/// <param name="argument">Method call argument</param> /// <param name="argument">Method call argument</param>
private void SendSignalingPcasB(int argument) private void SendSignalingPcasB(int argument)
{ {
var memoryManager = _channel.MemoryManager; MemoryManager memoryManager = _channel.MemoryManager;
// Since we're going to change the state, make sure any pending instanced draws are done. // Since we're going to change the state, make sure any pending instanced draws are done.
_3dEngine.PerformDeferredDraws(); _3dEngine.PerformDeferredDraws();
@@ -100,7 +101,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
uint qmdAddress = _state.State.SendPcasA; uint qmdAddress = _state.State.SendPcasA;
var qmd = _channel.MemoryManager.Read<ComputeQmd>((ulong)qmdAddress << 8); ComputeQmd qmd = _channel.MemoryManager.Read<ComputeQmd>((ulong)qmdAddress << 8);
ulong shaderGpuVa = ((ulong)_state.State.SetProgramRegionAAddressUpper << 32) | _state.State.SetProgramRegionB; ulong shaderGpuVa = ((ulong)_state.State.SetProgramRegionAAddressUpper << 32) | _state.State.SetProgramRegionB;

View File

@@ -80,7 +80,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void WriteWithRedundancyCheck(int offset, int value, out bool changed) public void WriteWithRedundancyCheck(int offset, int value, out bool changed)
{ {
var shadowRamControl = _state.State.SetMmeShadowRamControlMode; SetMmeShadowRamControlMode shadowRamControl = _state.State.SetMmeShadowRamControlMode;
if (shadowRamControl == SetMmeShadowRamControlMode.MethodPassthrough || offset < 0x200) if (shadowRamControl == SetMmeShadowRamControlMode.MethodPassthrough || offset < 0x200)
{ {
_state.WriteWithRedundancyCheck(offset, value, out changed); _state.WriteWithRedundancyCheck(offset, value, out changed);

View File

@@ -190,7 +190,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
/// <param name="argument">The LaunchDma call argument</param> /// <param name="argument">The LaunchDma call argument</param>
private void DmaCopy(int argument) private void DmaCopy(int argument)
{ {
var memoryManager = _channel.MemoryManager; MemoryManager memoryManager = _channel.MemoryManager;
CopyFlags copyFlags = (CopyFlags)argument; CopyFlags copyFlags = (CopyFlags)argument;
@@ -225,8 +225,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
int srcBpp = remap ? srcComponents * componentSize : 1; int srcBpp = remap ? srcComponents * componentSize : 1;
int dstBpp = remap ? dstComponents * componentSize : 1; int dstBpp = remap ? dstComponents * componentSize : 1;
var dst = Unsafe.As<uint, DmaTexture>(ref _state.State.SetDstBlockSize); DmaTexture dst = Unsafe.As<uint, DmaTexture>(ref _state.State.SetDstBlockSize);
var src = Unsafe.As<uint, DmaTexture>(ref _state.State.SetSrcBlockSize); DmaTexture src = Unsafe.As<uint, DmaTexture>(ref _state.State.SetSrcBlockSize);
int srcRegionX = 0, srcRegionY = 0, dstRegionX = 0, dstRegionY = 0; int srcRegionX = 0, srcRegionY = 0, dstRegionX = 0, dstRegionY = 0;
@@ -245,7 +245,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
int srcStride = (int)_state.State.PitchIn; int srcStride = (int)_state.State.PitchIn;
int dstStride = (int)_state.State.PitchOut; int dstStride = (int)_state.State.PitchOut;
var srcCalculator = new OffsetCalculator( OffsetCalculator srcCalculator = new OffsetCalculator(
src.Width, src.Width,
src.Height, src.Height,
srcStride, srcStride,
@@ -254,7 +254,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
src.MemoryLayout.UnpackGobBlocksInZ(), src.MemoryLayout.UnpackGobBlocksInZ(),
srcBpp); srcBpp);
var dstCalculator = new OffsetCalculator( OffsetCalculator dstCalculator = new OffsetCalculator(
dst.Width, dst.Width,
dst.Height, dst.Height,
dstStride, dstStride,
@@ -293,7 +293,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
if (completeSource && completeDest && !srcLinear && isIdentityRemap) if (completeSource && completeDest && !srcLinear && isIdentityRemap)
{ {
var source = memoryManager.Physical.TextureCache.FindTexture( Image.Texture source = memoryManager.Physical.TextureCache.FindTexture(
memoryManager, memoryManager,
srcGpuVa, srcGpuVa,
srcBpp, srcBpp,
@@ -309,7 +309,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
{ {
source.SynchronizeMemory(); source.SynchronizeMemory();
var target = memoryManager.Physical.TextureCache.FindOrCreateTexture( Image.Texture target = memoryManager.Physical.TextureCache.FindOrCreateTexture(
memoryManager, memoryManager,
source.Info.FormatInfo, source.Info.FormatInfo,
dstGpuVa, dstGpuVa,
@@ -339,7 +339,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
if (completeSource && completeDest && !(dstLinear && !srcLinear) && isIdentityRemap) if (completeSource && completeDest && !(dstLinear && !srcLinear) && isIdentityRemap)
{ {
var target = memoryManager.Physical.TextureCache.FindTexture( Image.Texture target = memoryManager.Physical.TextureCache.FindTexture(
memoryManager, memoryManager,
dstGpuVa, dstGpuVa,
dstBpp, dstBpp,

View File

@@ -159,7 +159,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
int availableCount = commandBuffer.Length - offset; int availableCount = commandBuffer.Length - offset;
int consumeCount = Math.Min(_state.MethodCount, availableCount); int consumeCount = Math.Min(_state.MethodCount, availableCount);
var data = commandBuffer.Slice(offset, consumeCount); ReadOnlySpan<int> data = commandBuffer.Slice(offset, consumeCount);
if (_state.SubChannel == 0) if (_state.SubChannel == 0)
{ {

View File

@@ -1,6 +1,7 @@
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Common.Memory; using Ryujinx.Common.Memory;
using Ryujinx.Graphics.Device; using Ryujinx.Graphics.Device;
using Ryujinx.Graphics.Gpu.Memory;
using Ryujinx.Graphics.Texture; using Ryujinx.Graphics.Texture;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@@ -168,9 +169,9 @@ namespace Ryujinx.Graphics.Gpu.Engine.InlineToMemory
/// </summary> /// </summary>
private void FinishTransfer() private void FinishTransfer()
{ {
var memoryManager = _channel.MemoryManager; MemoryManager memoryManager = _channel.MemoryManager;
var data = MemoryMarshal.Cast<int, byte>(_buffer)[.._size]; Span<byte> data = MemoryMarshal.Cast<int, byte>(_buffer)[.._size];
if (_isLinear && _lineCount == 1) if (_isLinear && _lineCount == 1)
{ {
@@ -184,7 +185,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.InlineToMemory
// Right now the copy code at the bottom assumes that it is used on both which might be incorrect. // Right now the copy code at the bottom assumes that it is used on both which might be incorrect.
if (!_isLinear) if (!_isLinear)
{ {
var target = memoryManager.Physical.TextureCache.FindTexture( Image.Texture target = memoryManager.Physical.TextureCache.FindTexture(
memoryManager, memoryManager,
_dstGpuVa, _dstGpuVa,
1, 1,
@@ -199,7 +200,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.InlineToMemory
if (target != null) if (target != null)
{ {
target.SynchronizeMemory(); target.SynchronizeMemory();
var dataCopy = MemoryOwner<byte>.RentCopy(data); MemoryOwner<byte> dataCopy = MemoryOwner<byte>.RentCopy(data);
target.SetData(dataCopy, 0, 0, new GAL.Rectangle<int>(_dstX, _dstY, _lineLengthIn / target.Info.FormatInfo.BytesPerPixel, _lineCount)); target.SetData(dataCopy, 0, 0, new GAL.Rectangle<int>(_dstX, _dstY, _lineLengthIn / target.Info.FormatInfo.BytesPerPixel, _lineCount));
target.SignalModified(); target.SignalModified();
@@ -207,7 +208,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.InlineToMemory
} }
} }
var dstCalculator = new OffsetCalculator( OffsetCalculator dstCalculator = new OffsetCalculator(
_dstWidth, _dstWidth,
_dstHeight, _dstHeight,
_dstStride, _dstStride,

View File

@@ -285,12 +285,12 @@ namespace Ryujinx.Graphics.Gpu.Engine.MME
/// <param name="arg0">First argument of the call</param> /// <param name="arg0">First argument of the call</param>
private void DrawArraysInstanced(IDeviceState state, int arg0) private void DrawArraysInstanced(IDeviceState state, int arg0)
{ {
var topology = (PrimitiveTopology)arg0; PrimitiveTopology topology = (PrimitiveTopology)arg0;
var count = FetchParam(); FifoWord count = FetchParam();
var instanceCount = FetchParam(); FifoWord instanceCount = FetchParam();
var firstVertex = FetchParam(); FifoWord firstVertex = FetchParam();
var firstInstance = FetchParam(); FifoWord firstInstance = FetchParam();
if (ShouldSkipDraw(state, instanceCount.Word)) if (ShouldSkipDraw(state, instanceCount.Word))
{ {
@@ -314,13 +314,13 @@ namespace Ryujinx.Graphics.Gpu.Engine.MME
/// <param name="arg0">First argument of the call</param> /// <param name="arg0">First argument of the call</param>
private void DrawElements(IDeviceState state, int arg0) private void DrawElements(IDeviceState state, int arg0)
{ {
var topology = (PrimitiveTopology)arg0; PrimitiveTopology topology = (PrimitiveTopology)arg0;
var indexAddressHigh = FetchParam(); FifoWord indexAddressHigh = FetchParam();
var indexAddressLow = FetchParam(); FifoWord indexAddressLow = FetchParam();
var indexType = FetchParam(); FifoWord indexType = FetchParam();
var firstIndex = 0; int firstIndex = 0;
var indexCount = FetchParam(); FifoWord indexCount = FetchParam();
_processor.ThreedClass.UpdateIndexBuffer( _processor.ThreedClass.UpdateIndexBuffer(
(uint)indexAddressHigh.Word, (uint)indexAddressHigh.Word,
@@ -344,13 +344,13 @@ namespace Ryujinx.Graphics.Gpu.Engine.MME
/// <param name="arg0">First argument of the call</param> /// <param name="arg0">First argument of the call</param>
private void DrawElementsInstanced(IDeviceState state, int arg0) private void DrawElementsInstanced(IDeviceState state, int arg0)
{ {
var topology = (PrimitiveTopology)arg0; PrimitiveTopology topology = (PrimitiveTopology)arg0;
var count = FetchParam(); FifoWord count = FetchParam();
var instanceCount = FetchParam(); FifoWord instanceCount = FetchParam();
var firstIndex = FetchParam(); FifoWord firstIndex = FetchParam();
var firstVertex = FetchParam(); FifoWord firstVertex = FetchParam();
var firstInstance = FetchParam(); FifoWord firstInstance = FetchParam();
if (ShouldSkipDraw(state, instanceCount.Word)) if (ShouldSkipDraw(state, instanceCount.Word))
{ {
@@ -374,17 +374,17 @@ namespace Ryujinx.Graphics.Gpu.Engine.MME
/// <param name="arg0">First argument of the call</param> /// <param name="arg0">First argument of the call</param>
private void DrawElementsIndirect(IDeviceState state, int arg0) private void DrawElementsIndirect(IDeviceState state, int arg0)
{ {
var topology = (PrimitiveTopology)arg0; PrimitiveTopology topology = (PrimitiveTopology)arg0;
var count = FetchParam(); FifoWord count = FetchParam();
var instanceCount = FetchParam(); FifoWord instanceCount = FetchParam();
var firstIndex = FetchParam(); FifoWord firstIndex = FetchParam();
var firstVertex = FetchParam(); FifoWord firstVertex = FetchParam();
var firstInstance = FetchParam(); FifoWord firstInstance = FetchParam();
ulong indirectBufferGpuVa = count.GpuVa; ulong indirectBufferGpuVa = count.GpuVa;
var bufferCache = _processor.MemoryManager.Physical.BufferCache; BufferCache bufferCache = _processor.MemoryManager.Physical.BufferCache;
bool useBuffer = bufferCache.CheckModified(_processor.MemoryManager, indirectBufferGpuVa, IndirectIndexedDataEntrySize, out ulong indirectBufferAddress); bool useBuffer = bufferCache.CheckModified(_processor.MemoryManager, indirectBufferGpuVa, IndirectIndexedDataEntrySize, out ulong indirectBufferAddress);
@@ -432,7 +432,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.MME
int startDraw = arg0; int startDraw = arg0;
int endDraw = arg1; int endDraw = arg1;
var topology = (PrimitiveTopology)arg2; PrimitiveTopology topology = (PrimitiveTopology)arg2;
int paddingWords = arg3; int paddingWords = arg3;
int stride = paddingWords * 4 + 0x14; int stride = paddingWords * 4 + 0x14;
@@ -468,12 +468,12 @@ namespace Ryujinx.Graphics.Gpu.Engine.MME
for (int i = 0; i < maxDrawCount; i++) for (int i = 0; i < maxDrawCount; i++)
{ {
var count = FetchParam(); FifoWord count = FetchParam();
#pragma warning disable IDE0059 // Remove unnecessary value assignment #pragma warning disable IDE0059 // Remove unnecessary value assignment
var instanceCount = FetchParam(); FifoWord instanceCount = FetchParam();
var firstIndex = FetchParam(); FifoWord firstIndex = FetchParam();
var firstVertex = FetchParam(); FifoWord firstVertex = FetchParam();
var firstInstance = FetchParam(); FifoWord firstInstance = FetchParam();
#pragma warning restore IDE0059 #pragma warning restore IDE0059
if (i == 0) if (i == 0)
@@ -492,7 +492,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.MME
} }
} }
var bufferCache = _processor.MemoryManager.Physical.BufferCache; BufferCache bufferCache = _processor.MemoryManager.Physical.BufferCache;
ulong indirectBufferSize = (ulong)maxDrawCount * (ulong)stride; ulong indirectBufferSize = (ulong)maxDrawCount * (ulong)stride;
@@ -526,7 +526,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.MME
/// <returns>The call argument, or a 0 value with null address if the FIFO is empty</returns> /// <returns>The call argument, or a 0 value with null address if the FIFO is empty</returns>
private FifoWord FetchParam() private FifoWord FetchParam()
{ {
if (!Fifo.TryDequeue(out var value)) if (!Fifo.TryDequeue(out FifoWord value))
{ {
Logger.Warning?.Print(LogClass.Gpu, "Macro attempted to fetch an inexistent argument."); Logger.Warning?.Print(LogClass.Gpu, "Macro attempted to fetch an inexistent argument.");

View File

@@ -90,13 +90,13 @@ namespace Ryujinx.Graphics.Gpu.Engine.MME
/// <returns>True if there is a implementation available and supported, false otherwise</returns> /// <returns>True if there is a implementation available and supported, false otherwise</returns>
public static bool TryGetMacroHLEFunction(ReadOnlySpan<int> code, Capabilities caps, out MacroHLEFunctionName name) public static bool TryGetMacroHLEFunction(ReadOnlySpan<int> code, Capabilities caps, out MacroHLEFunctionName name)
{ {
var mc = MemoryMarshal.Cast<int, byte>(code); ReadOnlySpan<byte> mc = MemoryMarshal.Cast<int, byte>(code);
for (int i = 0; i < _table.Length; i++) for (int i = 0; i < _table.Length; i++)
{ {
ref var entry = ref _table[i]; ref TableEntry entry = ref _table[i];
var hash = Hash128.ComputeHash(mc[..entry.Length]); Hash128 hash = Hash128.ComputeHash(mc[..entry.Length]);
if (hash == entry.Hash) if (hash == entry.Hash)
{ {
if (IsMacroHLESupported(caps, entry.Name)) if (IsMacroHLESupported(caps, entry.Name))

View File

@@ -369,7 +369,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.MME
/// <returns>The call argument, or 0 if the FIFO is empty</returns> /// <returns>The call argument, or 0 if the FIFO is empty</returns>
private int FetchParam() private int FetchParam()
{ {
if (!Fifo.TryDequeue(out var value)) if (!Fifo.TryDequeue(out FifoWord value))
{ {
Logger.Warning?.Print(LogClass.Gpu, "Macro attempted to fetch an inexistent argument."); Logger.Warning?.Print(LogClass.Gpu, "Macro attempted to fetch an inexistent argument.");

View File

@@ -20,7 +20,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.MME
/// <returns>The call argument, or 0 if the FIFO is empty</returns> /// <returns>The call argument, or 0 if the FIFO is empty</returns>
public int FetchParam() public int FetchParam()
{ {
if (!Fifo.TryDequeue(out var value)) if (!Fifo.TryDequeue(out FifoWord value))
{ {
Logger.Warning?.Print(LogClass.Gpu, "Macro attempted to fetch an inexistent argument."); Logger.Warning?.Print(LogClass.Gpu, "Macro attempted to fetch an inexistent argument.");

View File

@@ -221,7 +221,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.Blender
sb.AppendLine($"private static Dictionary<Hash128, AdvancedBlendEntry> _entries = new()"); sb.AppendLine($"private static Dictionary<Hash128, AdvancedBlendEntry> _entries = new()");
sb.AppendLine("{"); sb.AppendLine("{");
foreach (var entry in Table) foreach (AdvancedBlendUcode entry in Table)
{ {
Hash128 hash = Hash128.ComputeHash(MemoryMarshal.Cast<uint, byte>(entry.Code)); Hash128 hash = Hash128.ComputeHash(MemoryMarshal.Cast<uint, byte>(entry.Code));

View File

@@ -66,7 +66,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.Blender
descriptor = default; descriptor = default;
if (!AdvancedBlendPreGenTable.Entries.TryGetValue(hash, out var entry)) if (!AdvancedBlendPreGenTable.Entries.TryGetValue(hash, out AdvancedBlendEntry entry))
{ {
return false; return false;
} }

View File

@@ -65,7 +65,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw
{ {
if (disposing) if (disposing)
{ {
foreach (var texture in _cache.Values) foreach (ITexture texture in _cache.Values)
{ {
texture.Release(); texture.Release();
} }
@@ -603,7 +603,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw
DestroyIfNotNull(ref _geometryIndexDataBuffer.Handle); DestroyIfNotNull(ref _geometryIndexDataBuffer.Handle);
DestroyIfNotNull(ref _sequentialIndexBuffer); DestroyIfNotNull(ref _sequentialIndexBuffer);
foreach (var indexBuffer in _topologyRemapBuffers.Values) foreach (IndexBuffer indexBuffer in _topologyRemapBuffers.Values)
{ {
_context.Renderer.DeleteBuffer(indexBuffer.Handle); _context.Renderer.DeleteBuffer(indexBuffer.Handle);
} }

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