Compare commits

..

280 Commits

Author SHA1 Message Date
2435043xia
42f7f98666 Fix the issue of unequal check for amiibo file date due to the lack o… (#4832)
* Fix the issue of unequal check for amiibo file date due to the lack of sub-second units in the header, causing slow opening of the amiibo interface.

* Supplement the unrepaired.
2023-05-11 19:10:24 +02:00
riperiperi
95bad6995c GPU: Fix shader cache assuming past shader data was mapped (#4885)
This fixes a potential issue where a shader lookup could match the address of a previous _different_ shader, but that shader is now partially unmapped. This would just crash with an invalid region exception.

To compare a shader in the address cache with one in memory, we get the memory at the location with the previous shader's size. However, it's possible it has been unmapped and then remapped with a smaller size. In this case, we should just get back the mapped portion of the shader, which will then fail the comparison immediately and get to compile/lookup for the new one.

This might fix a random crash in TOTK that was reported by Piplup. I don't know if it does, because I don't have the game yet.
2023-05-11 18:41:34 +02:00
Mary
3d42995822 Attempt to fix release.yml after merge 2023-05-11 17:42:33 +02:00
TSRBerry
9095941fd1 Update release workflow & Add jobs for macOS (#4837)
* Add build config and extra args to create_macos_build.sh

* Use matrix strategy for releases

* Add macOS jobs

Co-authored-by: Mary <thog@protonmail.com>

* Fix wrong version argument

* Fix check for the correct amount of args

* Install latest rcodesign release

Co-authored-by: Mary <thog@protonmail.com>

* Set executable bits for PR builds on linux

---------

Co-authored-by: Mary <thog@protonmail.com>
2023-05-11 17:36:53 +02:00
gdkchan
ba71141bdc Ensure background translation threads exited before disposing JIT (#4874) 2023-05-10 21:46:38 -03:00
gdkchan
0a0675a7f6 Fix missing domain service object dispose (#4879) 2023-05-11 00:29:17 +00:00
Aaron O'Mullan
a7c6e6a8cf fix(mvk): resumeLostDevice (#4800)
Command buffer errors currently trigger an exception "DeviceLost" crashing the process.

Looking at [MKV's code](53a4eb26f2/MoltenVK/MoltenVK/GPUObjects/MVKQueue.mm (L392-L408)) we observe that:
- It hard fails if error is:
  ```
   MTLCommandBufferErrorBlacklisted || MTLCommandBufferErrorNotPermitted || MTLCommandBufferErrorDeviceRemoved
   ```
- Otherwise fails conditionally if `config.resumeLostDevice == false` (current default)

For Ryujinx's use-case it's more graceful to resume on those errors rather than crashing the app, the error isn't totally silenced since `mvk` still logs it

Fixes #4704, #4575
2023-05-10 03:31:52 +02:00
Emmanuel Hansen
0bc8151c7e IPC - Refactor Bcat service to use new ipc - Revisit (#4803)
* bcat ipc

* fix hipc buffer flags

* add buffer fixed size flag on generator
2023-05-09 21:46:23 +00:00
gdkchan
40c17673f5 Replace DelegateHelper with pre-generated delegates (#4867) 2023-05-09 09:02:39 +00:00
Mary
a8950d6ac4 vulkan: Pass Vk instance to VulkanRenderer (#4859)
This will allow possible multiple driver selection without any need of
LD preload. (useful when testing custom version of mesa for example)
2023-05-08 13:05:37 +02:00
Mary
162798b026 vulkan: Avoid hardcoding features in CreateDevice (#4858)
Those shouldn't have been hardcoded.
2023-05-08 10:48:16 +00:00
riperiperi
1b28ecd63e Vulkan: Simplify MultiFenceHolder and managing them (#4845)
* Vulkan: Simplify waitable add/remove

Removal of unnecessary hashset and dictionary

* Thread safety for GetBufferData in PersistentFlushBuffer

* Fix WaitForFencesImpl thread safety

* Proper methods for risky reference increments

* Wrong type of CB.

* Address feedback
2023-05-08 12:45:12 +02:00
riperiperi
895d9b53bc Vulkan: Batch vertex buffer updates (#4843)
* Vulkan: Batch vertex buffer updates

Some games can bind a large number of vertex buffers for draws. This PR allows for vertex buffers to be updated with one call rather than one per buffer.

This mostly affects the AMD Mesa driver, the testing platform was Steam Deck with Super Mario Odyssey. It was taking about 12% before, should be greatly reduced now.

A small optimization has been added to avoid looking up the same buffer multiple times, as a common pattern is for the same buffer to be bound many times in a row with different ranges.

* Only rebind vertex buffers if they have changed

* Address feedback
2023-05-08 10:59:26 +02:00
Mary
0e06aace45 misc: Avoid copy of ApplicationControlProperty (#4849)
Avoid more giant copy when passing it around.
2023-05-08 01:50:07 +02:00
Ac_K
adf4ebcd60 Ava: Fix SystemTimeOffset calculation (#4848)
* Ava: Fix SystemTimeOffset calculation

During testing of #4822, Mary pointed out the way we calculate time offset is wrong in our Avalonia UI. This PR fixed that.
The axaml file is autoformatted too.

* DateTime.Now in local var
2023-05-08 00:31:08 +02:00
Mary
470a8031a4 time: Update for 15.0.0 changes and fixes long standing issues (#4822)
* time: Update for 15.0.0 changes

Last time we did an upgrade on the time service was during 9.x era, it was about time to take back that reverse again!

15.0.0 added a new structure on the shared memory to get steady clock raw timepoints with a granularity in nanoseconds.

This commit implements this new part.

I plan to write a follow up with a bit of refactoring of this ancient part of the emulator.

As always, reverse and work done by your truly.

PS: As a reminder, if this change is reused anywhere else, work should be credited as Ryujinx and not my person.

* time: Do not set setup value to posix time

This should fix local and network clock returning 0 under usage with
shared memory.

This probably fix #2430.

* Address gdkchan's comment

* Fix internal offset not working since changes and ensure that user clock have a valid clock id

* time: Report auto correcting clock and hardcode steady clock unique id

Fix Pokemon Sword Pokejobs for real.

* Address gdkchan's comment
2023-05-08 00:15:58 +02:00
Mary
5440d4ad5c misc: Switch ProcessResult to a class (#4846)
This avoid giant copies being performed when being returned or passed.
2023-05-07 20:50:45 +00:00
gnisman
dde208b480 UI: Expose games build ID for cheat management (#4340)
* Ava UI: Expose games build ID for cheat management

* Fix bad merge

* Change integrity check level to error on invalid

* Add support for GDK

* Remove whitespace

* Add BID identifier

* PR Comments fix

* Restore title id in cheats GTK window

* use halign center instead of margin_left

* Merge

* fix after merge

* PR comments fix - design AVA

* PR fix - Move GetApplicationBuildId to ApplicationData class

* PR comment fix - Add empty line before method

* Align with PR #4755

* PR comments fix

* Change BuildId label to support translation

* Comments fix

* Remove unused BuildIdLabel property
2023-05-07 14:36:44 +00:00
Nico
4c3d2d5d75 UI: Add progress bar for re-packaging shaders (#4805)
* feat: introduce new shader loading state for progress tracking when writing shaders to disk

* fix: move translation to bottom of locale file

* fix: change back to foreach and add requested spacing between lines

* style: fix formatting

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

---------

Co-authored-by: gdkchan <gab.dark.100@gmail.com>
2023-05-06 15:35:46 +02:00
Ac_K
fab11ba3f1 AM: Stub some service calls (#4825)
* AM: Stub some service call

Some IPC I have stubbed during private testing and I don't want to deal with them anymore. Nothing more.

* ICommonStateGetter disposable
2023-05-06 03:33:50 +02:00
riperiperi
332891b5ff Use correct offset for storage constant buffer elimination (#4821) 2023-05-05 23:59:36 +02:00
riperiperi
7df4fcada7 GPU: Remove CPU region handle containers (#4817)
* GPU: Remove CPU region handle containers.

Another one for the "I don't know why I didn't do this earlier" pile.

This removes the "Cpu" prefixed region handle classes, which each mirror a region handle type from Ryujinx.Memory.

Originally, not all projects had a reference to Ryujinx.Memory, so these classes were introduced to bridge the gap. Someone else crossed that bridge since, so these classes don't have much of a purpose anymore.

This PR replaces all uses of CpuRegionHandle etc to their direct Ryujinx.Memory versions.

RegionHandle methods (specifically QueryModified) are about the hottest path there is in the entire emulator, so there is a nice boost from doing this.

* Add docs
2023-05-05 23:40:46 +02:00
Ac_K
d6698680be UI: Fix sections extraction (#4820)
* UI: Fix sections extraction

There is currently an issue when the update NCA doesn't contains the section we want to extract, this is fixed by adding a check.
I have fixed the inverted handler of ExeFs/Logo introduced in #4755.

Fixes #4521

* Addresses feedback
2023-05-05 21:24:35 +00:00
ashuk
e5c9838b0b Correct tooltips for add,remove,removeall buttons (#4819) 2023-05-05 22:38:57 +02:00
Ikko Eltociear Ashimine
f8ec878796 Fix typo in TextureBindingsManager.cs (#4798)
accomodate -> accommodate
2023-05-05 22:17:36 +02:00
Skyth (Asilkan)
9ff21f9ab6 Use ToLowerInvariant when detecting GPU vendor. (#4815) 2023-05-05 16:35:59 +00:00
gdkchan
aa021085cf Allow any shader SSBO constant buffer slot and offset (#2237)
* Allow any shader SSBO constant buffer slot and offset

* Fix slot value passed to SetUsedStorageBuffer on fallback case

* Shader cache version

* Ensure that the storage buffer source constant buffer offset is word aligned

* Fix FirstBinding on GetUniformBufferDescriptors
2023-05-05 14:20:20 +00:00
riperiperi
1f5d881860 GPU: Allow granular buffer updates from the constant buffer updater (#4749)
* GPU: Allow granular buffer updates from the constant buffer updater

Sometimes, constant buffer updates can't be avoided, either due to a cb0 access that cannot be eliminated, or the game updating a buffer between draws to the detriment of everyone.

To avoid uploading the full 4096 bytes each time, this PR remembers the offset and size containing all constant buffer updates since the last sync. It will then upload that range after sync.

* Allow clearing the dirty range

* Always use precise

Might want to not do this if distance between the existing range and new one is too high.

* Use old force dirty mechanism when distance between regions is too great

* Update src/Ryujinx.Graphics.Gpu/Memory/Buffer.cs

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

* Fix inheritance of _dirtyStart and _dirtyEnd

---------

Co-authored-by: gdkchan <gab.dark.100@gmail.com>
2023-05-05 13:47:15 +00:00
TSRBerry
1f664100bd ModLoader: Fix case sensitivy issues without breaking cheats (#4783)
* Fix case sensitivity for mod subdirectories

* Small refactoring of ModLoader

* Don't share instruction list between all cheats

Co-authored-by: riperiperi <rhy3756547@hotmail.com>

---------

Co-authored-by: riperiperi <rhy3756547@hotmail.com>
2023-05-05 09:39:08 +02:00
Horizon
1f5e1ffa80 fix: linux launcher breaks when there are spaces in the directory path (#4795)
* fix: linux launcher breaks when there are spaces in the directory path

* Add quotes around $0 as well

---------

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>
2023-05-05 09:06:15 +02:00
gdkchan
264438ff19 Revert "bcat ipc (#4446)" (#4801)
This reverts commit 4250732353.
2023-05-04 18:16:51 +02:00
Ac_K
3b8ac1641a UI: Move ApplicationContextMenu in a separated class (#4755)
* UI: Move ApplicationContextMenu in a separated class

This PR remove duplicated code related to the context menu on the Application list/grid by create a control for the menu which include related handler.

I've renamed "GameList/GameGrid" by "Application" for consistencies. And I've removed all uneeded field from the project file too.

While I cleaned up things, I've found an issue about purging Ptc/Shader cache, both methods list files even if the user say "No", shader cache is purged even if the user say "No". It's fixed.

* Adresses feedbacks
2023-05-04 14:41:06 +00:00
Emmanuel Hansen
4250732353 bcat ipc (#4446) 2023-05-04 16:26:10 +02:00
gdkchan
4d1579acbf Fix some invalid blits involving depth textures (#4723) 2023-05-03 21:20:12 -03:00
Erdem Keskin
6279f5e430 Update SettingsWindow.cs (#4785)
fix saving if directory path directly pasted in to the text field instead of using FileChooser.
2023-05-03 16:04:40 +02:00
Mary
b7d2bff6aa Revert "ModLoader: Fix case sensitivy issues (#4720)" (#4781)
This reverts commit cc1a933a2f.
2023-05-03 11:20:05 +02:00
riperiperi
7c327fecb3 Vulkan: Record modifications after changing the framebuffer (#4775)
Our Vulkan backend inserts image barriers when a texture is sampled after it is rendered. This is done via a "modification flag" which is set when a render target is unbound (presuming that a texture has finished drawing to it).

Imagine the following scenario:
- Game sets render target to texture A
- Game renders to texture A
- (render pass ends)
- Game binds texture A to a sampler
- Game sets render target to texture B
- Renders to texture B using texture A (barrier required)

Because of the previous behaviour, the check to add a barrier for sampling a texture actually happens before it is registered as modified, meaning no barrier was added at all. This isn't always the case, but it was definitely causing issues in Xenoblade 2.

This doesn't fix any more complicated issues where a texture is repeatedly sampled while it is currently being rendered.

Fixes visual glitches at lower resolutions in Xenoblade 2. May fix other cases.
2023-05-03 10:42:21 +02:00
TSRBerry
cc1a933a2f ModLoader: Fix case sensitivy issues (#4720)
* Fix case sensitivity for mod subdirectories

* Small refactoring of ModLoader
2023-05-03 02:07:16 +02:00
TSRBerry
dd574146fb Add hide-cursor command line argument & always hide cursor option (#4613)
* Add hide-cursor command line argument

* gtk: Adjust SettingsWindow for hide cursor options

* ava: Adjust SettingsWindow for hide cursor options

* ava: Add override check for HideCursor arg

* Remove copy&paste sins

* ava: Leave a little more room between the options

* gtk: Fix hide cursor issues

* ava: Only hide cursor if it's within the embedded window
2023-05-02 03:29:47 +02:00
riperiperi
2c94ac455e GPU: Keep rendered textures without any pool references alive (#4662)
* GPU: Keep sampled textures without any pool references alive

Occasionally games are very wasteful and clear/write to a texture without ever sampling it. As rendered textures in NVN games seem to all have overlapping memory ranges, the texture will eventually get overwritten.

Normally, this would trigger a removal from the auto delete cache, but a pool entry would keep the texture alive. However, with these textures that are never used, they will get deleted immediately and recreated on the next frame.

This change makes it so the ShortTextureCache can keep textures that have naver had a pool reference alive for a few frames, so they're not constantly being created and deleted.

This improves performance in Zelda BOTW a little.

* Cleanup
2023-05-01 16:27:51 -03:00
riperiperi
e18d258fa0 GPU: Pre-emptively flush textures that are flushed often (to imported memory when available) (#4711)
* WIP texture pre-flush

Improve performance of TextureView GetData to buffer

Fix copy/sync ordering

Fix minor bug

Make this actually work

WIP host mapping stuff

* Fix usage flags

* message

* Cleanup 1

* Fix rebase

* Fix

* Improve pre-flush rules

* Fix pre-flush

* A lot of cleanup

* Use the host memory bits

* Select the correct memory type

* Cleanup TextureGroupHandle

* Missing comment

* Remove debugging logs

* Revert BufferHandle _value access modifier

* One interrupt action at a time.

* Support D32S8 to D24S8 conversion, safeguards

* Interrupt cannot happen in sync handle's lock

Waitable needs to be checked twice now, but this should stop it from deadlocking.

* Remove unused using

* Address some feedback

* Address feedback

* Address more feedback

* Address more feedback

* Improve sync rules

Should allow for faster sync in some cases.
2023-05-01 16:05:12 -03:00
riperiperi
36f10df775 GPU: Fix errors handling texture remapping (#4745)
* GPU: Fix errors handling texture remapping

- Fixes an error where a pool entry and memory mapping changing at the same time could cause a texture to rebind its data from the wrong GPU VA (data swaps)
- Fixes an error where the texture pool could act on a mapping change before the mapping has actually been changed ("Unmapped" event happens before change, we need to signal it changed _after_ it completes)

TODO: remove textures from partially mapped list... if they aren't.

* Add Remap actions for handling post-mapping behaviours

* Remove unused code.

* Address feedback

* Nit
2023-05-01 15:32:32 -03:00
al81-ru
680e548022 Uneven frame pacing with vsync (#4744)
fixes issue #3906
2023-04-29 21:54:41 +01:00
MutantAura
21c4176157 Allow window to remember its size, position and state (GTK + Avalonia) (#4657)
* Update ConfigurationState.cs

* Update ConfigurationFileFormat.cs

* Update MainWindow.cs

* Update ConfigurationFileFormat.cs

* Update ConfigurationState.cs

* Update MainWindow.cs

* Update MainWindow.cs

* Update Ryujinx.Ui.Common/Configuration/ConfigurationState.cs

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

* Update MainWindow.cs

* Update Ryujinx/Ui/MainWindow.cs

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

* Initial properties

* Viewmodel adjustments and additions

* abstract and monitor dimension changes

* Remove position from ViewModel and simplify methods

* Remove unused dep

* Update configuration and fix typo from AA

* review changes

* Review changes

* Screensize checks - Ava

* Review changes 2

* basic review changes

* Standardise GTK/Ava functions

* Actually call function

---------

Co-authored-by: HaizenTrist <123991082+HaizenTrist@users.noreply.github.com>
Co-authored-by: gdkchan <gab.dark.100@gmail.com>
2023-04-28 22:59:53 +02:00
dependabot[bot]
3b4ff2d6d9 nuget: bump System.IdentityModel.Tokens.Jwt from 6.29.0 to 6.30.0 (#4736)
Bumps [System.IdentityModel.Tokens.Jwt](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet) from 6.29.0 to 6.30.0.
- [Release notes](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/releases)
- [Changelog](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/compare/6.29.0...6.30.0)

---
updated-dependencies:
- dependency-name: System.IdentityModel.Tokens.Jwt
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-28 11:54:19 +02:00
TSRBerry
12504f280c Fix paths and typos for macOS scripts (#4738)
* Fix paths and typos for macOS scripts

* Update outdated comments about rcodesign

---------

Co-authored-by: Mary <thog@protonmail.com>
2023-04-28 08:14:44 +00:00
TSR Berry
250fc51374 Adjust github workflows for new src directory 2023-04-27 23:51:14 +02:00
TSR Berry
206e0882c2 Adjust Ryujinx.Tests.Memory namespace 2023-04-27 23:51:14 +02:00
TSR Berry
609abc8b9b Rename Ryujinx.Memory.Tests to Ryujinx.Tests.Memory 2023-04-27 23:51:14 +02:00
TSR Berry
cee7121058 Move solution and projects to src 2023-04-27 23:51:14 +02:00
gdkchan
cd124bda58 Fix geometry shader layer passthrough regression (#4735)
* Fix geometry shader layer passthrough regression

* Shader cache version bump
2023-04-27 11:09:49 -03:00
gdkchan
9f12e50a54 Refactor attribute handling on the shader generator (#4565)
* Refactor attribute handling on the shader generator

* Implement gl_ViewportMask[]

* Add back the Intel FrontFacing bug workaround

* Fix GLSL transform feedback outputs mistmatch with fragment stage

* Shader cache version bump

* Fix geometry shader recognition

* PR feedback

* Delete GetOperandDef and GetOperandUse

* Remove replacements that are no longer needed on GLSL compilation on Vulkan

* Fix incorrect load for per-patch outputs

* Fix build
2023-04-25 19:51:07 -03:00
gdkchan
097562bc6c Add missing check for thread termination on ArbitrateLock (#4722)
* Add missing check for thread termination on ArbitrateLock

* Use TerminationRequested in all places where it can be used
2023-04-25 19:33:14 -03:00
gdkchan
db4242c5dc Implement DMA texture copy component shuffle (#4717)
* Implement DMA texture copy component shuffle

* Set UInt24 alignment to 1
2023-04-24 15:28:03 +02:00
gdkchan
4dd77316f7 Use vector transform feedback outputs with fragment shaders (#4708)
* Use vector transform feedback outputs with fragment shaders

* Shader cache version bump

* Fix missing outputs when vector transform feedback outputs are used
2023-04-24 08:34:38 +02:00
TSRBerry
3f98369a17 Set the console title for GTK again (#4706)
Fixes a regression from #3707 where I accidentally removed that line.
2023-04-24 08:15:19 +02:00
TSRBerry
c26aeefe03 Fix amiibo timeout issues & log errors/exceptions (#4712) 2023-04-24 02:08:31 +00:00
jhorv
666e05f5cb Reducing Memory Allocations 202303 (#4624)
* use ArrayPool, avoid 6000-7000 allocs/sec of runtime

* use ArrayPool, avoid ~7k allocs/second during game execution

* use ArrayPool, avoid ~3000 allocs/sec during game execution

* use MemoryPool, reduce 0.5 MB/sec of new allocations during game execution

* avoid over-allocation by setting List<> Capacity when known

* remove LINQ in KTimeManager.UnscheduleFutureInvocation

* KTimeManager - avoid spinning one more time when the time has arrived

* KTimeManager - let SpinWait decide when to Thread.Yield(), and don't SpinOnce() immediately after Thread.Yield()

* use MemoryPool, reduce ~175k bytes/sec allocation during game execution

* IpcService - call commands via dynamic methods instead of reflection .Invoke(). Faster to call and with fewer allocations because parameters can be passed directly instead of as an array

* Make ButtonMappingEntry a record struct to avoid allocations. Set the List<ButtonMappingEntry> capacity according to use.

* add MemoryBuffer type for working with MemoryPool<byte>

* update changes to use MemoryBuffer

* make parameter ReadOnlySpan instead of Span

* whitespace fix

* Revert "IpcService - call commands via dynamic methods instead of reflection .Invoke(). Faster to call and with fewer allocations because parameters can be passed directly instead of as an array"

This reverts commit f2c698bdf65f049e8481c9f2ec7138d9b9a8261d.

* tweak KTimeManager spin behavior

* replace MemoryBuffer with ByteMemoryPool modeled after System.Buffers.ArrayMemoryPool<T>

* make ByteMemoryPoolBuffer responsible for renting memory
2023-04-24 02:06:23 +00:00
riperiperi
8d9d508dc7 Shader: Bias textureGather instructions on AMD/Intel (#4703)
* Experimental (GLSL, forced)

* SPIR-V attempt

* Add capability

* Fix pCount == 1 on glsl

* Fix typo
2023-04-22 18:02:39 -03:00
SpicerXD
e27f5522e2 Removed MotionInput Calibration (#4705)
Don't know why this is here.
It just seems to set the filter to an identity. Which then quickly returns to where its supposed to be anyways.
2023-04-22 15:31:28 +02:00
gdkchan
add2a9d151 Avoid LM service crashes by not reading more than the buffer size (#4701) 2023-04-20 17:10:17 +02:00
dependabot[bot]
9e50dd99d7 nuget: bump System.IdentityModel.Tokens.Jwt from 6.28.1 to 6.29.0 (#4694)
Bumps [System.IdentityModel.Tokens.Jwt](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet) from 6.28.1 to 6.29.0.
- [Release notes](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/releases)
- [Changelog](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/compare/6.28.1...6.29.0)

---
updated-dependencies:
- dependency-name: System.IdentityModel.Tokens.Jwt
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-17 21:31:12 +02:00
dependabot[bot]
0dec91bb42 nuget: bump System.Management from 7.0.0 to 7.0.1 (#4695)
Bumps [System.Management](https://github.com/dotnet/runtime) from 7.0.0 to 7.0.1.
- [Release notes](https://github.com/dotnet/runtime/releases)
- [Commits](https://github.com/dotnet/runtime/compare/v7.0.0...v7.0.1)

---
updated-dependencies:
- dependency-name: System.Management
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-17 21:30:40 +02:00
gdkchan
d9b63353b0 Support copy between multisample and non-multisample depth textures (#4676)
* Support copy between multisample and non-multisample depth textures

* PR feedback
2023-04-17 08:13:53 +00:00
gdkchan
eabd0ec93f Revert "chore: Update Silk.NET to 2.17.1 (#4686)" (#4690)
This reverts commit 79d1c190db.
2023-04-16 20:56:27 -03:00
riperiperi
138d5dc64a Vulkan: HashTableSlim lookup optimization (#4688) 2023-04-16 14:57:01 -03:00
gdkchan
3e68a87d63 Change SMAA filter texture clear method (#4685)
* Change SMAA filter texture clear method

* Alpha should be 1

* Delete more unnecessary code
2023-04-16 14:26:22 -03:00
TSRBerry
69b6ef7a4a [GUI] Add network interface dropdown (#4597)
* Add network adapter dropdown from LDN build

* Ava: Add NetworkInterfaces to SettingsNetworkTab

* Add headless network interface option

* Add network interface dropdown to Avalonia

* Fix handling network interfaces without a gateway address

* gtk: Actually save selected network interface to config

* Increment config version
2023-04-16 15:25:20 +00:00
Mary
40e87c634e Fix a crash in Ryujinx.Headless.SDL2 when loading an app (#4687)
Caused by the recent application loader changes.
2023-04-16 16:50:30 +02:00
Mary
79d1c190db chore: Update Silk.NET to 2.17.1 (#4686) 2023-04-16 09:38:07 +00:00
Ac_K
2bc88467eb Update README.md 2023-04-16 09:37:31 +00:00
Vincenzo Nizza
baf8752e74 Ensure the updater doesn't delete hidden or system files (#4626)
* Copy desktop.ini to update directory if it exists in HomeDir

* EnumerateFilesToDelete() exclude files with "Hidden" and "System" attributes
2023-04-16 09:19:33 +00:00
dependabot[bot]
d5e4378aea nuget: bump DynamicData from 7.13.1 to 7.13.5 (#4654)
Bumps [DynamicData](https://github.com/reactiveui/DynamicData) from 7.13.1 to 7.13.5.
- [Release notes](https://github.com/reactiveui/DynamicData/releases)
- [Changelog](https://github.com/reactivemarbles/DynamicData/blob/main/ReleaseNotes.md)
- [Commits](https://github.com/reactiveui/DynamicData/compare/7.13.1...7.13.5)

---
updated-dependencies:
- dependency-name: DynamicData
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-16 09:02:06 +00:00
TSRBerry
6dbcdfea47 Ava: Fix nca extraction window never closing & minor cleanup (#4569)
* ava: Remove unused doWhileDeferred parameters

* ava: Minimally improve swkbd dialog

It's currently impossible to get the dialog to redirect focus to the InputBox.

* ava: Fix nca extraction dialog never closing

Also contains some minor cleanup
2023-04-16 07:09:02 +00:00
NitroTears
c5258cf082 Ability to hide file types in Game List (#4555)
* Added HiddenFileTypes to config state, and check to file enumeration

* Added hiddenfiletypes checkboxes to the UI

* Added Ava version of HiddenFileTypes

* Inverted Hide to Show with file types, minor formatting

* all variables with a reference to 'hidden' is now 'shown'

* one more variable name changed

* review feedback

* added FileTypes extension methof to get the correlating config value

* moved extension method to new folder and file in Ryujinx.Ui.Common

* added default case for ToggleFileType

* changed exception type to OutOfRangeException
2023-04-16 01:03:35 +00:00
Daniel Shala
5c89e22bb9 Added check for eventual symlink when displaying game files. (#4526)
* Added check for eventual symlink when displaying game files.

* Moved symlink check logic

* Moved symlink check logic

* Fixed prev commit

---------

Co-authored-by: Daniel Shala <danielshala00@gmail.com>
2023-04-15 16:11:24 +00:00
Alex Barney
11ecff2ff0 Rename Hipc to Cmif where appropriate (#3880) 2023-04-14 20:00:34 -03:00
MutantAura
4c3f09644a Move swkbd message null check into constructor (#4671) 2023-04-12 21:18:40 +02:00
TSRBerry
e187a8870a HLE: Deal with empty title names properly (#4643)
* hle: Deal with empty titleNames in some languages

* gui: Fix displaying the wrong title name

* Remove unnecessary bounds check

* Fix a NRE when getting the version string

* Restore empty string logic
2023-04-12 01:09:47 +00:00
riperiperi
a64fee29dc Vulkan: add situational "Fast Flush" mode (#4667)
* Flush in the middle of long command buffers.

* Vulkan: add situational "Fast Flush" mode

The AutoFlushCounter class was added to periodically flush Vulkan command buffers throughout a frame, which reduces latency to the GPU as commands are submitted and processed much sooner. This was done by allowing command buffers to flush when framebuffer attachments changed.

However, some games have incredibly long render passes with a large number of draws, and really aggressive data access that forces GPU sync.

The Vulkan backend could potentially end up building a single command buffer for 4-5ms if a pass has enough draws, such as in BOTW. In the scenario where sync is waited on immediately after submission, this would have to wait for the completion of a much longer command buffer than usual.

The solution is to force command buffer submission periodically in a "fast flush" mode. This will end up splitting render passes, but it will only enable if sync is aggressive enough.

This should improve performance in GPU limited scenarios, or in games that aggressively wait on synchronization. In some games, it may only kick in when res scaling. It won't trigger in games like SMO where sync is not an issue.

Improves performance in Pokemon Scarlet/Violet (res scaled) and BOTW (in general).

* Add conversions in milliseconds next to flush timers.
2023-04-11 09:23:41 +02:00
riperiperi
9ef94c8292 ARMeilleure: Move TPIDR_EL0 and TPIDRRO_EL0 to NativeContext (#4661)
* ARMeilleure: Move TPIDR_EL0 and TPIDRRO_EL0 to NativeContext

Some games access these system registers several tens of thousands of times in a second from many different threads. While this isn't really crippling, it is a lot of wasted time spent in a reverse pinvoke transition.

Example games are Pokemon Scarlet/Violet and BOTW. These games have a lot of different potential bottlenecks so it's unlikely you will see a consistent improvement, but it definitely disappears from the cpu profile.

* Remove unreachable code.

* Add ulong conversion for offsets

* Nit
2023-04-11 08:55:04 +02:00
riperiperi
915d6d044c OpenGL: Fix OBS/Overlays again by binding FB before present (#4668)
This seems to have been removed by the Post-Processing PR, but it is required for the display in OBS to be the right way up and properly scaled.

I've tested this with AA and FSR on MK8D and it seems to behave properly. Testing is welcome.
2023-04-11 08:32:31 +02:00
MutantAura
a4780ab33b Force activate parent window before dialog is shown (#4663) 2023-04-11 00:04:31 +02:00
TSRBerry
a947a45d81 gtk: Fix a NRE when disposing OpenGL (#4648) 2023-04-10 17:00:23 +02:00
riperiperi
9db73f74cf ARMeilleure: Respect FZ/RM flags for all floating point operations (#4618)
* ARMeilleure: Respect Fz flag for all floating point operations.

This is a change in strategy for emulating the Fz FPCR flag. Before, it was set before instructions that "needed it" and reset after. However, this missed a few hot instructions like the multiplication instruction, and the entirety of A32.

The new strategy is to set the Fz flag only in the following circumstances:

- Set to match FPCR before translated functions/loop are executed.
- Reset when calling SoftFloat methods, set when returning.
- Reset when exiting execution.

This allows us to remove the code around the existing Fz aware instructions, and get the accuracy benefits on all floating point instructions executed while in translated code.

Single step executions now need to be called with a context wrapper - right now it just contains the Fz flag initialization, and won't actually do anything on ARM.

This fixes a bug in Breath of the Wild where some physics interactions could randomly crash the game due to subnormal values not flushing to zero.

This is draft right now because I need to answer the questions:
- Does dotnet avoid changing the value of Mxcsr?
- Is it a good idea to assume that? Or should the flag set/restore be done on every managed method call, not just softfloat?
- If we assume that, do we want a unit test to verify the behaviour?

I recommend testing a bunch of games, especially games affected when this was originally added, such as #1611.

* Remove unused method

* Use FMA for Fmadd, Fmsub, Fnmadd, Fnmsub, Fmla, Fmls

...when available.

Similar implementation to A32

* Use FMA for Frecps, Frsqrts

* Don't set DAZ.

* Add round mode to ARM FP mode

* Fix mistakes

* Add test for FP state when calling managed methods

* Add explanatory comment to test.

* Cleanup

* Add A64 FPCR flags

* Vrintx_S A32 fast path on A64 backend

* Address feedback 1, re-enable DAZ

* Fix FMA instructions By Elem

* Address feedback
2023-04-10 12:22:58 +02:00
gdkchan
a1efd87c45 Implement remaining Arm64 HINT instructions as NOP (#4658)
* Implement remaining HINT instructions as NOP

* Split HINT encodings more to account for CSDB
2023-04-09 13:21:16 -03:00
jhorv
49be977588 Eliminate boxing allocations caused by ISampledData structs (#4556)
* Redesign use of ISampledData for accessing the SamplingNumber value on input data structs.

* Always read SamplingNumber as little-endian

* Restored field order for SixAxisSensorState. Rework to allow possibility of non-zero offsets for the SamplingNumber field. Set StructLayout Pack=8 - the KeyboardState struct is 4 bytes shorter with any other value.

* fix spelling

Co-authored-by: riperiperi <rhy3756547@hotmail.com>

* set Pack = 1 for ISampledDataStruct types, added Unknown field to KeyboardState

* extend size of KeyboardModifier

---------

Co-authored-by: riperiperi <rhy3756547@hotmail.com>
2023-04-05 17:42:32 -03:00
Mary
c95be55091 vulkan: Cleanup PhysicalDevice and Instance querying (#4632)
* vulkan: Move most of the properties enumeration to VulkanPhysicalDevice

That clean up a bit of duplicate logic.
Also move to use an hashset for device extensions.

* vulkan: Move instance querying to VulkanInstance

Also cleanup code to use span when possible instead of unsafe pointers.

* Address gdkchan's comments
2023-04-05 14:48:38 -03:00
dependabot[bot]
63dedbda86 nuget: bump System.IdentityModel.Tokens.Jwt from 6.27.0 to 6.28.1 (#4639)
Bumps [System.IdentityModel.Tokens.Jwt](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet) from 6.27.0 to 6.28.1.
- [Release notes](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/releases)
- [Changelog](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/compare/6.27.0...6.28.1)

---
updated-dependencies:
- dependency-name: System.IdentityModel.Tokens.Jwt
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-05 07:55:57 +02:00
gdkchan
c532118d94 Use index fragment shader output when dual source blend is enabled (#4404)
* Use index fragment shader output when dual source blend is enabled

* Shader cache version bump

* Actually set DualSourceBlendEnabled to true

* Fix XML doc

---------

Co-authored-by: Ac_K <Acoustik666@gmail.com>
2023-04-05 05:25:19 +02:00
TSRBerry
52d6f2e656 hle: Set ProcessResult name from NACP (#4633)
* Extract titleName from nacp

* Address formatting feedback

* Check if the desired language is actually available
2023-04-05 03:34:21 +02:00
TSRBerry
c9bc4eaf58 Fix missing string enum converters for the config (#4634)
* Fix missing string enum converters for the config

* Revert changing KeyboardHotkeys to struct

This needs to be done because
Avalonia's TwoWay Binding breaks otherwise.
2023-04-03 15:37:27 +02:00
Andrey Sukharev
3249f8ff41 Source generated json serializers (#4582)
* Use source generated json serializers in order to improve code trimming

* Use strongly typed github releases model to fetch updates instead of raw Newtonsoft.Json parsing

* Use separate model for LogEventArgs serialization

* Make dynamic object formatter static. Fix string builder pooling.

* Do not inherit json version of LogEventArgs from EventArgs

* Fix extra space in object formatting

* Write log json directly to stream instead of using buffer writer

* Rebase fixes

* Rebase fixes

* Rebase fixes

* Enforce block-scoped namespaces in the solution. Convert style for existing code

* Apply suggestions from code review

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Rebase indent fix

* Fix indent

* Delete unnecessary json properties

* Rebase fix

* Remove overridden json property names as they are handled in the options

* Apply suggestions from code review

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Use default json options in github api calls

* Indentation and spacing fixes

* Fix json serialization

* Fix missing JsonConverter for config enums

* Add double \n\n after the whole string, not inside join

---------

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>
2023-04-03 10:14:19 +00:00
dependabot[bot]
1b41b285ac nuget: bump DynamicData from 7.12.11 to 7.13.1 (#4490)
Bumps [DynamicData](https://github.com/reactiveui/DynamicData) from 7.12.11 to 7.13.1.
- [Release notes](https://github.com/reactiveui/DynamicData/releases)
- [Changelog](https://github.com/reactivemarbles/DynamicData/blob/main/ReleaseNotes.md)
- [Commits](https://github.com/reactiveui/DynamicData/compare/7.12.11...7.13.1)

---
updated-dependencies:
- dependency-name: DynamicData
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-01 08:23:09 +00:00
Mary
f5a6f45b27 vulkan: Separate debug utils logic from VulkanInitialization (#4609)
* vulkan: Separate debug utils logic from VulkanInitialization

Also checks for VK_EXT_debug_utils existence instead of force enabling it and allow possible error during messenger init

* Address gdkchan's comment

* Use CreateDebugUtilsMessenger Span variant
2023-04-01 08:05:02 +00:00
TSRBerry
210557951b nuget: bump Avalonia dependencies from 0.10.18 to 0.10.19 (#4602)
* infra: Update Avalonia to 0.10.19

* infra: Update XamlNameReferenceGenerator to 1.6.1
2023-04-01 07:27:34 +00:00
Ac_K
4c2d9ff3ff HLE: Refactoring of ApplicationLoader (#4480)
* HLE: Refactoring of ApplicationLoader

* Fix SDL2 Headless

* Addresses gdkchan feedback

* Fixes LoadUnpackedNca RomFS loading

* remove useless casting

* Cleanup and fixe empty application name

* Remove ProcessInfo

* Fixes typo

* ActiveProcess to ActiveApplication

* Update check

* Clean using.

* Use the correct filepath when loading Homebrew.npdm

* Fix NRE in ProcessResult if MetaLoader is null

* Add more checks for valid processId & return success

* Add missing logging statement for npdm error

* Return result for LoadKip()

* Move error logging out of PFS load extension method

This avoids logging "Could not find Main NCA"
followed by "Loading main..." when trying to start hbl.

* Fix GUIs not checking load results

* Fix style and formatting issues

* Fix formatting and wording

* gtk: Refactor LoadApplication()

---------

Co-authored-by: TSR Berry <20988865+TSRBerry@users.noreply.github.com>
2023-03-31 21:16:46 +02:00
jhorv
8198b99935 Fix Linux hang on shutdown (#4617)
* Rework StdErr-to-log redirection to use built-in FileStream, and do reads asynchronously to avoid hanging the process shutdown.

* set _disposable to false ASAP
2023-03-30 22:07:07 +02:00
ACGNnsj
460f96967d Slight Code Refactoring (#4373)
* Simplify return statements by using ternary expressions

* Remove a redundant type conversion

* Reduce nesting by inverting "if" statements

* Try to improve code readability by using LINQ and inverting "if" statements

* Try to improve code readability by using LINQ, using ternary expressions, and inverting "if" statements

* Add line breaks to long LINQ

* Add line breaks to long LINQ
2023-03-28 14:59:43 +02:00
Mary
7ca779a26d audout: Fix a possible crash with SDL2 when the SDL2 audio backend is dummy (#4605)
This change makes audio device error not fatal.
In case of error, the SDL2 audio backend will behave like the dummy
backend.
2023-03-27 20:56:36 +02:00
Mary
b5032b3c91 vulkan: Fix access level of extensions fields and make them readonly (#4608) 2023-03-27 08:40:27 +02:00
Mary
f0a3dff136 vulkan: Remove CreateCommandBufferPool from VulkanInitialization (#4606)
It was only called in one place, that can be simplified.
2023-03-27 02:16:31 +00:00
Mary
f659dcb9d8 vulkan: fix broken "VK_EXT_subgroup_size_control" support check (#4607)
Not sure since when it was broken...
2023-03-26 19:01:30 +02:00
riperiperi
a34fb0e939 Vulkan: Insert barriers before clears (#4596)
* Vulkan: Insert barriers before clears

Newer NVIDIA GPUs seem to be able to start clearing render targets before the last rasterization task is completed, which can cause it to clear a texture while it is being sampled.

This change adds a barrier from read to write when doing a clear, assuming it has been sampled in the past. It could be possible for this to be needed for sample into draw by some GPU, but it's not right now afaik.

This should fix visual artifacts on newer NVIDIA GPUs and driver combos. Contrary to popular belief, Tetris® Effect: Connected is not affected. Testing welcome, hopefully should fix most cases of this and not cost too much performance.

* Visual Studio Moment

* Address feedback

* Address Feedback 2
2023-03-26 12:51:02 +02:00
Mary
21ce8a9b80 chore: Update Ryujinx.SDL2-CS to 2.26.3 (#4479) 2023-03-24 22:42:24 +01:00
gdkchan
9ecbee8032 Batch inline index buffer update (#4587) 2023-03-24 14:19:54 +01:00
gdkchan
80519af67d Update short cache textures if modified (#4586) 2023-03-24 12:54:58 +01:00
gdkchan
26e30faff3 Fix handle leak on IShopServiceAccessServerInterface.CreateServerInterface (#4591) 2023-03-24 11:56:54 +01:00
Wunk
0992310b76 ARMeilleure: Check for XSAVE cpuid flag for AVX{2,512} (#4584)
Protection for the `xgetbv` instruction for systems that do not support
`xcr0` such as nehalem processors.

The `XSAVE` cpuid indicates support for `XSAVE`, `XRESTOR`, `XSETBV`,
`XGETBV` while `OSXSAVE` indicates if the operating system itself has
`XSAVE` turned on. Both must be checked at the same time.
2023-03-22 14:51:21 -03:00
Andrew Glaze
009c1101d2 CI: add a version tag to correlate release versions with commits (#4572)
* add step to tag commit with release version

* add step to tag commit with release version

* Rename step to “Create Tag”

* Fix name
2023-03-22 13:17:28 +01:00
gdkchan
ba95ee54ab Revert "Use source generated json serializers in order to improve code trimming (#4094)" (#4576)
This reverts commit 4ce4299ca2.
2023-03-21 20:14:46 -03:00
Andrey Sukharev
4ce4299ca2 Use source generated json serializers in order to improve code trimming (#4094)
* Use source generated json serializers in order to improve code trimming

* Use strongly typed github releases model to fetch updates instead of raw Newtonsoft.Json parsing

* Use separate model for LogEventArgs serialization

* Make dynamic object formatter static. Fix string builder pooling.

* Do not inherit json version of LogEventArgs from EventArgs

* Fix extra space in object formatting

* Write log json directly to stream instead of using buffer writer

* Rebase fixes

* Rebase fixes

* Rebase fixes

* Enforce block-scoped namespaces in the solution. Convert style for existing code

* Apply suggestions from code review

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Rebase indent fix

* Fix indent

* Delete unnecessary json properties

* Rebase fix

* Remove overridden json property names as they are handled in the options

* Apply suggestions from code review

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Use default json options in github api calls

* Indentation and spacing fixes

---------

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>
2023-03-21 19:41:19 -03:00
Wunk
17620d18db ARMeilleure: Add initial support for AVX512 (EVEX encoding) (cont) (#4147)
* ARMeilleure: Add AVX512{F,VL,DQ,BW} detection

Add `UseAvx512Ortho` and `UseAvx512OrthoFloat` optimization flags as
short-hands for `F+VL` and `F+VL+DQ`.

* ARMeilleure: Add initial support for EVEX instruction encoding

Does not implement rounding, or exception controls.

* ARMeilleure: Add `X86Vpternlogd`

Accelerates the vector-`Not` instruction.

* ARMeilleure: Add check for `OSXSAVE` for AVX{2,512}

* ARMeilleure: Add check for `XCR0` flags

Add XCR0 register checks for AVX and AVX512F, following the guidelines
from section 14.3 and 15.2 from the Intel Architecture Software
Developer's Manual.

* ARMeilleure: Remove redundant `ReProtect` and `Dispose`, formatting

* ARMeilleure: Move XCR0 procedure to GetXcr0Eax

* ARMeilleure: Add `XCR0` to `FeatureInfo` structure

* ARMeilleure: Utilize `ReadOnlySpan` for Xcr0 assembly

Avoids an additional allocation

* ARMeilleure: Formatting fixes

* ARMeilleure: Fix EVEX encoding src2 register index

> Just like in VEX prefix, vvvv is provided in inverted form.

* ARMeilleure: Add `X86Vpternlogd` acceleration to `Vmvn_I`

Passes unit tests, verified instruction utilization

* ARMeilleure: Fix EVEX register operand designations

Operand 2 was being sourced improperly.

EVEX encoded instructions source their operands like so:
Operand 1: ModRM:reg
Operand 2: EVEX.vvvvv
Operand 3: ModRM:r/m
Operand 4: Imm

This fixes the improper register designations when emitting vpternlog.
Now "dest", "src1", "src2" arguments emit in the proper order in EVEX instructions.

* ARMeilleure: Add `X86Vpternlogd` acceleration to `Orn_V`

* ARMeilleure: PTC version bump

* ARMeilleure: Update EVEX encoding Debug.Assert to Debug.Fail

* ARMeilleure: Update EVEX encoding comment capitalization
2023-03-20 16:09:24 -03:00
riperiperi
9f1cf6458c Vulkan: Migrate buffers between memory types to improve GPU performance (#4540)
* Initial implementation of migration between memory heaps

- Missing OOM handling
- Missing `_map` data safety when remapping
  - Copy may not have completed yet (needs some kind of fence)
  - Map may be unmapped before it is done being used. (needs scoped access)
- SSBO accesses are all "writes" - maybe pass info in another way.
- Missing keeping map type when resizing buffers (should this be done?)

* Ensure migrated data is in place before flushing.

* Fix issue where old waitable would be signalled.

- There is a real issue where existing Auto<> references need to be replaced.

* Swap bound Auto<> instances when swapping buffer backing

* Fix conversion buffers

* Don't try move buffers if the host has shared memory.

* Make GPU methods return PinnedSpan with scope

* Storage Hint

* Fix stupidity

* Fix rebase

* Tweak rules

Attempt to sidestep BOTW slowdown

* Remove line

* Migrate only when command buffers flush

* Change backing swap log to debug

* Address some feedback

* Disallow backing swap when the flush lock is held by the current thread

* Make PinnedSpan from ReadOnlySpan explicitly unsafe

* Fix some small issues

- Index buffer swap fixed
- Allocate DeviceLocal buffers using a separate block list to images.

* Remove alternative flags

* Address feedback
2023-03-19 17:56:48 -03:00
gdkchan
67b4e63cff Remove MultiRange Min/MaxAddress and rename GetSlice to Slice (#4566)
* Delete MinAddress and MaxAddress from MultiRange

* Rename MultiRange.GetSlice to MultiRange.Slice
2023-03-19 17:31:35 +01:00
TSRBerry
c05c688ee8 Avoid copying more handles than we have space for (#4564)
* Avoid copying more handles than we have space for

* Use locks instead

* Reduce nesting by combining the lock statements

* Add locks for other uses of _sessionHandles and _portHandles

* Use one object to lock instead of locking twice

* Release the lock as soon as possible
2023-03-19 11:30:04 +01:00
riperiperi
b2623dc27d OpenGL: Fix inverted conditional for counter flush from #4471 (#4560)
Fixes OpenGL.
2023-03-18 20:39:05 -03:00
jhorv
5131b71437 Reducing memory allocations (#4537)
* add RecyclableMemoryStream dependency and MemoryStreamManager

* organize BinaryReader/BinaryWriter extensions

* add StreamExtensions to reduce need for BinaryWriter

* simple replacments of MemoryStream with RecyclableMemoryStream

* add write ReadOnlySequence<byte> support to IVirtualMemoryManager

* avoid 0-length array creation

* rework IpcMessage and related types to greatly reduce memory allocation by using RecylableMemoryStream, keeping streams around longer, avoiding their creation when possible, and avoiding creation of BinaryReader and BinaryWriter when possible

* reduce LINQ-induced memory allocations with custom methods to query KPriorityQueue

* use RecyclableMemoryStream in StreamUtils, and use StreamUtils in EmbeddedResources

* add constants for nanosecond/millisecond conversions

* code formatting

* XML doc adjustments

* fix: StreamExtension.WriteByte not writing non-zero values for lengths <= 16

* XML Doc improvements. Implement StreamExtensions.WriteByte() block writes for large-enough count values.

* add copyless path for StreamExtension.Write(ReadOnlySpan<int>)

* add default implementation of IVirtualMemoryManager.Write(ulong, ReadOnlySequence<byte>); remove previous explicit implementations

* code style fixes

* remove LINQ completely from KScheduler/KPriorityQueue by implementing a custom struct-based enumerator
2023-03-17 13:14:50 +01:00
TSRBerry
7870423671 Update syscall capabilites to include SVCs from FW 15.0.0 (#4530)
* Add CapabilityType enum

* Add SupervisorCallCount

* kernel: Add CapabilityExtensions & Change type of capabilities to uint

* Remove private setter from Mask arrays

* Pass ReadOnlySpan directly & Remove redundant type casts
2023-03-17 12:55:19 +01:00
dependabot[bot]
b72916fbc1 nuget: bump UnicornEngine.Unicorn (#4543)
Bumps [UnicornEngine.Unicorn](https://github.com/unicorn-engine/unicorn) from 2.0.2-rc1-f7c841d to 2.0.2-rc1-fb78016.
- [Release notes](https://github.com/unicorn-engine/unicorn/releases)
- [Changelog](https://github.com/unicorn-engine/unicorn/blob/master/ChangeLog)
- [Commits](https://github.com/unicorn-engine/unicorn/commits)

---
updated-dependencies:
- dependency-name: UnicornEngine.Unicorn
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-17 12:50:52 +01:00
riperiperi
da073fce61 GPU: Fast path for adding one texture view to a group (#4528)
* GPU: Fast path for adding one texture view to a group

Texture group handles must store a list of their overlapping views, so they can be properly notified when a write is detected, and a few other things relating to texture readback. This is generally created when the group is established, with each handle looping over all views to find its overlaps. This whole process was also done when only a single view was added (and no handles were changed), however...

Sonic Frontiers had a huge cubemap array with 7350 faces (175 cubemaps * 6 faces * 7 levels), so iterating over both handles and existing views added up very fast. Since we are only adding a single view, we only need to _add_ that view to the existing overlaps, rather than recalculate them all.

This greatly improves performance during loading screens and a few seconds into gameplay on the "open zone" sections of Sonic Frontiers. May improve loading times or stutters on some other games.

Note that the current texture cache rules will cause these views to fall out of the cache, as there are more than the hard cap, so the cost will be repaid when reloading the open zone.

I also added some code to properly remove overlaps when texture views are removed, since it seems that was missing.

This can be improved further by only iterating handles that overlap the view (filter by range), but so can a few places in TextureGroup, so better to do all at once. The full generation of overlaps could probably be improved in a similar way.

I recommend testing a few games to make sure nothing breaks.

* Address feedback
2023-03-14 17:33:44 -03:00
riperiperi
1fc90e57d2 Update range for remapped sparse textures instead of recreating them (#4442)
* Update sparsely mapped texture ranges without recreating

Important TODO in TexturePool. Smaller TODO: should I look into making textures with views also do this? It needs to be able to detect if the views can be instantly deleted without issue if they're now remapped.

* Actually do partial updates

* Signal group dirty after mappings changed

* Fix various issues (should work now)

* Further optimisation

Should load a lot less data (16x) when partial updating 3d textures.

* Improve stability

* Allow granular uploads on large textures, improve rules

* Actually avoid updating slices that aren't modified.

* Address some feedback, minor optimisation

* Small tweak

* Refactor DereferenceRequest

More specific initialization methods.

* Improve code for resetting handles

* Explain data loading a bit more

* Add some safety for setting null from different threads.

All texture sets come from the one thread, but null sets can come from multiple. Only decrement ref count if we succeeded the null set first.

* Address feedback 1

* Make a bit safer
2023-03-14 17:08:44 -03:00
Isaac Marovitz
eafcc314a9 Ava UI: DownloadableContentManager Refactor (#4300)
* Start refactor

* Move around functions

* It builds

* Menu opens

* Buttons

* Fix overlapping text

* SaveAndClose and Close buttons

* Remove button

* Layout

* It’s a little funky but it works

* Enable all/disable all buttons

* Fix UpdateCount desyncs

* Search bar

* Search by title id

* Fix fuck ups

* Fix selection mode

* Update Ryujinx.Ava/UI/ViewModels/DownloadableContentManagerViewModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/ViewModels/DownloadableContentManagerViewModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/ViewModels/DownloadableContentManagerViewModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Fix search bar

* Log corrupted DLC json

* Fix LibHac changes

---------

Co-authored-by: Ac_K <Acoustik666@gmail.com>
2023-03-14 17:04:38 +01:00
riperiperi
6e9bd4de13 GPU: Scale counter results before addition (#4471)
* GPU: Scale counter results before addition

Counter results were being scaled on ReportCounter, which meant that the _total_ value of the counter was being scaled. Not only could this result in very large numbers and weird overflows if the game doesn't clear the counter, but it also caused the result to change drastically.

This PR changes scaling to be done when the value is added to the counter on the backend. This should evaluate the scale at the same time as before, on report counter, but avoiding the issue with scaling the total.

Fixes scaling in Warioware, at least in the demo, where it seems to compare old/new counters and broke down when scaling was enabled.

* Fix issues when result is partially uploaded.

Drivers tend to write the low half first, then the high half. Retry if the high half is FFFFFFFF.
2023-03-12 18:01:15 +01:00
TimeZlicer
05a41b31bc Misc: Support space in path on macOS distribution (#4462)
* .

* Apply suggestions from code review

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* wildcard(*) needs to be outside of quotes(") for cp to work

---------

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>
2023-03-12 17:21:21 +01:00
MutantAura
eed17f963e Increase access permissions for Ava timezones (#4538) 2023-03-12 17:20:09 +01:00
TSRBerry
c09c0c002d [Flatpak] Beautify multiline strings again & Add full git commit hash (#4535)
* Don't destroy multiline strings

* Use full git commit hash
2023-03-12 10:42:33 +01:00
Mary
d56d335c0b misc: Some dependencies cleanup (#4507)
* Remove dependencies on libraries provided by .NET standard library

* Use System.IO.Hashing instead of Crc32.NET
2023-03-12 03:24:11 +01:00
jhorv
23c844b2aa Misc performance tweaks (#4509)
* use Array.Empty() where instead of allocating new zero-length arrays

* structure for loops in a way that the JIT will elide array/Span bounds checking

* avoiding function calls in for loop condition tests

* avoid LINQ in a hot path

* conform with code style

* fix mistake in GetNextWaitingObject()

* fix GetNextWaitingObject() possibility of returning null if all list items have TimePoint == long.MaxValue

* make GetNextWaitingObject() behave FIFO behavior for multiple items with the same TimePoint
2023-03-11 17:05:48 -03:00
Mary
81691b9e37 gha(release): Attempt to fix flathub pusher 2023-03-11 20:11:09 +01:00
Mary
2dc422bc14 gha(release): Hopefully fixes it 2023-03-11 19:16:08 +01:00
Mary
a80fa5e33f gha(release): Makes environment variables global 2023-03-11 19:09:48 +01:00
Mary
954e995321 Attempt to fix syntax error of previous merge 2023-03-11 19:06:42 +01:00
TSRBerry
dad9ab6bb6 [Flatpak] Add release github workflow (#4529)
* Add flatpak release workflow

Co-authored-by: Mary <mary@mary.zone>

* infra: Update required SDK version to 7.0.200

---------

Co-authored-by: Mary <mary@mary.zone>
2023-03-11 19:04:13 +01:00
gdkchan
f0562b9c75 CPU: Avoid argument value copies on the JIT (#4484)
* Minor refactoring of the pre-allocator

* Avoid LoadArgument copies

* PPTC version bump
2023-03-08 23:25:35 +01:00
dependabot[bot]
b8556530f2 nuget: bump Microsoft.CodeAnalysis.CSharp from 4.4.0 to 4.5.0 (#4488)
Bumps [Microsoft.CodeAnalysis.CSharp](https://github.com/dotnet/roslyn) from 4.4.0 to 4.5.0.
- [Release notes](https://github.com/dotnet/roslyn/releases)
- [Changelog](https://github.com/dotnet/roslyn/blob/main/docs/Breaking%20API%20Changes.md)
- [Commits](https://github.com/dotnet/roslyn/commits)

---
updated-dependencies:
- dependency-name: Microsoft.CodeAnalysis.CSharp
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-04 15:37:08 +01:00
gdkchan
4f3af839be Minor code formatting (#4498) 2023-03-04 14:43:08 +01:00
dependabot[bot]
155736c986 nuget: bump UnicornEngine.Unicorn (#4500)
Bumps [UnicornEngine.Unicorn](https://github.com/unicorn-engine/unicorn) from 2.0.2-rc1-a913199 to 2.0.2-rc1-f7c841d.
- [Release notes](https://github.com/unicorn-engine/unicorn/releases)
- [Changelog](https://github.com/unicorn-engine/unicorn/blob/master/ChangeLog)
- [Commits](https://github.com/unicorn-engine/unicorn/commits)

---
updated-dependencies:
- dependency-name: UnicornEngine.Unicorn
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-04 11:32:30 +00:00
MetrosexualGarbodor
dba908dc78 Add post processing feature to the readme (#4499)
* Add post processing feature to the readme

Adds post processing information to the GPU section in the readme.

* correct "Anti-Aliasing"
2023-03-04 02:15:29 +00:00
Steveice10
ecee34a50c Update LibHac to 0.18.0 (#4414)
* Update LibHac to 0.18.0

* Change instance of AsBytes(CreateReadOnlySpan(...)) to AsReadOnlyByteSpan(...)
2023-03-01 23:42:27 -03:00
riperiperi
9b5a0c3889 Sockets: Properly convert error codes on MacOS (#4491)
* Sockets: Properly convert error codes on MacOS

The error codes for MacOS are very different to how they are on windows or linux. An alternate mapping is used when the host operating system is MacOS.

This PR also defaults IsDhcpEnabled to true when interfaceProperties.DhcpServerAddresses is not available.

This change was already in `macos1`.

* Address feedback
2023-02-28 03:41:44 +00:00
Emmanuel Hansen
80b4972139 Add Support for Post Processing Effects (#3616)
* Add Post Processing Effects

* fix events and shader issues

* fix gtk upscale slider value

* fix bgra games

* don't swap swizzle if already swapped

* restore opengl texture state after effects run

* addressed review

* use single pipeline for smaa and fsr

* call finish on all pipelines

* addressed review

* attempt fix file case

* attempt fixing file case

* fix filter level tick frequency

* adjust filter slider margins

* replace fxaa shaders with original shader

* addressed review
2023-02-27 18:11:55 -03:00
gdkchan
5d85468302 Vulkan: Support list topology primitive restart (#4483) 2023-02-26 19:19:00 -03:00
merry
9b1cc2cec6 Logging: Redirect StdErr into logging system (#4427)
* Logging: Redirect StdErr into logging system

* Remove Mono.Unix

* Apply suggestions from code review

Co-authored-by: riperiperi <rhy3756547@hotmail.com>

* Address comments

---------

Co-authored-by: Mary <thog@protonmail.com>
Co-authored-by: riperiperi <rhy3756547@hotmail.com>
Co-authored-by: Mary <mary@mary.zone>
2023-02-25 15:07:23 +00:00
Mary
e691622f0a misc: Add missing DefineConstants definition in Ryujinx.Common
Fix flathub and nixpkgs build hopefully now.
2023-02-25 13:32:20 +01:00
Mary
f663a5cd38 macos: Add updater support (#4464)
This is a very basic updater but should be enough for now.

---------

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>
2023-02-25 12:30:48 +01:00
Mary
f7c2e867f4 chore: Update OpenTK to 4.7.7 (#4478) 2023-02-25 10:55:57 +00:00
gdkchan
cedd200745 Move gl_Layer to vertex shader if geometry is not supported (#4368)
* Set gl_Layer on vertex shader if it's set on the geometry shader and it does nothing else

* Shader cache version bump

* PR feedback

* Fix typo
2023-02-25 10:39:51 +00:00
jhorv
58207685c0 Perform bounds checking before list indexer to avoid frequent exceptions (#4438)
* Perform bounds checking before list indexer to avoid frequent ArgumentOutOfRangeExceptions

* do a single compare after casting id and .Count to uint
2023-02-25 10:26:39 +00:00
gdkchan
095ad923ad Account for multisample when calculating render target size hint (#4467) 2023-02-23 10:08:54 +01:00
Isaac Marovitz
f07ae7d53f Fix Title Update Manager not selecting right update (#4452) 2023-02-22 17:58:32 -03:00
dependabot[bot]
c308f09722 nuget: bump Microsoft.NET.Test.Sdk from 17.4.1 to 17.5.0 (#4458)
Bumps [Microsoft.NET.Test.Sdk](https://github.com/microsoft/vstest) from 17.4.1 to 17.5.0.
- [Release notes](https://github.com/microsoft/vstest/releases)
- [Changelog](https://github.com/microsoft/vstest/blob/main/docs/releases.md)
- [Commits](https://github.com/microsoft/vstest/compare/v17.4.1...v17.5.0)

---
updated-dependencies:
- dependency-name: Microsoft.NET.Test.Sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-22 16:08:25 +01:00
dependabot[bot]
f1eef29409 nuget: bump UnicornEngine.Unicorn (#4459)
Bumps [UnicornEngine.Unicorn](https://github.com/unicorn-engine/unicorn) from 2.0.2-rc1-9c9356d to 2.0.2-rc1-a913199.
- [Release notes](https://github.com/unicorn-engine/unicorn/releases)
- [Changelog](https://github.com/unicorn-engine/unicorn/blob/master/ChangeLog)
- [Commits](https://github.com/unicorn-engine/unicorn/commits)

---
updated-dependencies:
- dependency-name: UnicornEngine.Unicorn
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-22 13:30:53 +01:00
TSRBerry
1f8d66db7c Ava: Fix Updater crashing on Linux (#4457) 2023-02-22 09:13:50 +01:00
gdkchan
c3a5716a95 Add copy dependency for some incompatible texture formats (#4380)
* Add copy dependency for some incompatible texture formats

* Simplify compatibility check
2023-02-21 19:21:57 -03:00
Mary
1f1e2a7f03 misc: changes base application directory behaviour (#4460)
This allows changing base application directory behavior at build time via FORCE_EXTERNAL_BASE_DIR.

This is intended to be used by nixpkgs and flathub builds.

I also added the missing patch for macOS that we have on macos1 to avoid invalidating code signature.
2023-02-21 22:38:34 +01:00
Andrew Glaze
e54f9dc4b4 Move Ryujinx Folder from ~/.config to ~/Library/Application Support on macOS (#4296)
* Move Ryujinx folder to Application Support on macOS

* Create a symlink to preserve back compat

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Remove extra whitespace

* Don’t create a symlink

* Update Ryujinx.Common/Configuration/AppDataManager.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Revert "Don’t create a symlink"

This reverts commit 31752fe8ab.

---------

Co-authored-by: Ac_K <Acoustik666@gmail.com>
2023-02-21 12:14:31 +01:00
Logan Stromberg
edfd4d70c0 Use SIMD acceleration for audio upsampler (#4410)
* Use SIMD acceleration for audio upsampler filter kernel for a moderate speedup

* Address formatting. Implement AVX2 fast path for high quality resampling in ResamplerHelper

* now really, are we really getting the benefit of inlining 50+ line methods?

* adding unit tests for resampler + upsampler. The upsampler ones fail for some reason

* Fixing upsampler test. Apparently this algo only works at specific ratios

---------

Co-authored-by: Logan Stromberg <lostromb@microsoft.com>
2023-02-21 11:44:57 +01:00
riperiperi
fc43aecbbd Memory: Faster Split for NonOverlappingRangeList (#4451)
I noticed that in Xenoblade 2, the game can end up spending a lot of time adding and removing tracking handles. One of the main causes of this is actually splitting existing handles, which does the following:

- Remove existing handle from list
- Update existing handle to end at split address, create new handle starting at split address
- Add updated handle (left) to list
- Add new handle (right) to list

This costs 1 deletion and 2 insertions. When there are more handles, this gets a lot more expensive, as insertions are done by copying all values to the right, and deletions by copying values to the left.

This PR simply allows it to look up the handle being split, and replace its entry with the new end address without insertion or deletion. This makes a split only cost one insertion and a binary search lookup (very cheap). This isn't all of the cost on Xenoblade 2, but it does significantly reduce it.

There might be something else to this - we could find a way to reduce the handle count for the game (merging on deletion? buffer deletion?), we could use a different structure for virtual regions, as the current one is optimal for buffer lookups which nearly always read, memory tracking has more of a balance between read/write. That's for a later date though, this was an easy improvment.
2023-02-21 10:53:38 +01:00
gdkchan
58d7a1fe97 Mark texture as modified and sync on I2M fast path (#4449) 2023-02-21 10:40:23 +01:00
gdkchan
7aa430f1a5 Add support for advanced blend (part 1/2) (#2801)
* Add blend microcode registers

* Add advanced blend support using host extension

* Remove debug message

* Use pre-generated table for blend functions

* XML docs

* Rename AdvancedBlendMode to AdvancedBlendOp for consistency

* Remove redundant code

* Fix some advanced blend related issues on Vulkan

* Formatting
2023-02-19 22:37:37 -03:00
dependabot[bot]
6bf460e104 nuget: bump System.IdentityModel.Tokens.Jwt from 6.26.1 to 6.27.0 (#4441)
Bumps [System.IdentityModel.Tokens.Jwt](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet) from 6.26.1 to 6.27.0.
- [Release notes](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/releases)
- [Changelog](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/commits)

---
updated-dependencies:
- dependency-name: System.IdentityModel.Tokens.Jwt
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-18 02:35:02 +01:00
gdkchan
efb135b74c Clear CPU side data on GPU buffer clears (#4125)
* Clear CPU side data on GPU buffer clears

* Implement tracked fill operation that can signal other resource types except buffer

* Fix tests, add missing XML doc

* PR feedback
2023-02-16 18:28:49 -03:00
gdkchan
a707842e14 Validate dimensions before creating texture (#4430) 2023-02-16 11:16:31 -03:00
TSRBerry
a5a9b9bc8b GUI: Small Updater refactor & Set correct permissions on Linux when extracting files (#4315)
* ava: Refactor Updater.cs

Fix typos
Remove unused usings
Rename variables to follow naming scheme

* ava: Set file permissions when extracting update files

* gtk: Apply the same refactor to Updater.cs

* updater: Replace assert with if statement

* updater: Remove await usings again
2023-02-15 22:36:35 +00:00
Mary
17078ad929 vulkan: Respect VK_KHR_portability_subset vertex stride alignment (#4419)
* vulkan: Respect VK_KHR_portability_subset vertex stride alignment

We were hardcoding alignment to 4, but by specs it can be any values that
is a power of 2.

This also enable VK_KHR_portability_subset if present as per specs
requirements.

* address gdkchan's comment

* Make NeedsVertexBufferAlignment internal
2023-02-15 08:41:48 +00:00
Mary
32450d45de vulkan: Clean up MemoryAllocator (#4418)
This started as an attempt to remove vkGetPhysicalDeviceMemoryProperties
in FindSuitableMemoryTypeIndex (As this could have some overhead and
shouldn't change at runtime) and turned in a little bigger cleanup.
2023-02-15 07:50:26 +01:00
Ac_K
ed7a0474c6 Infra: Issues template cleanup (#4421)
* Infra: Issues template cleanup

* applied
2023-02-14 15:58:57 +01:00
Mary
fe9c49949a vulkan: Enforce Vulkan 1.2+ at instance API level and 1.1+ at device level (#4408)
* vulkan: Enforce Vulkan 1.2+ at instance API level and 1.1+ at device level

This ensure we don't end up trying to initialize with anything currently incompatible.

* Address riperiperi's comment
2023-02-13 22:04:55 +00:00
Mary
052b23c83c vulkan: Do not call vkCmdSetViewport when viewportCount is 0 (#4406)
This fix validation error "VUID-vkCmdSetViewport-viewportCount-arraylength".
2023-02-13 20:32:20 +00:00
riperiperi
e4f68592c3 Fix partial updates for textures. (#4401)
I was forcing some types of texture to partially update when investigating performance with games that stream in data, and noticed that partially loading texture data was really broken on both backends.

Fixes Vulkan texture set by getting the correct expected size for the texture. Fixes partial upload on both backends for both Texture 2D Array and Cubemap using the wrong offset and uploading to the first layer/level for a handle. 3D might also be affected.

This might fix textures randomly having incorrect data in games that render to it - jumbled in the case of OpenGL, and outdated/black in the case of Vulkan. This case typically happens in UE4 games.
2023-02-12 10:30:26 +01:00
Logan Stromberg
1dcd44b94f Treat NpadIdType < 0 as invalid. Filter invalid SupportedPlayers inside IHidServer.SetSupportedNpadIdType(). (#4377)
Co-authored-by: Logan Stromberg <lostromb@microsoft.com>
2023-02-10 12:37:20 -03:00
gdkchan
61b1ce252f Allow partially mapped textures with unmapped start (#4394) 2023-02-10 11:47:59 -03:00
gdkchan
5f38086f94 Fix SPIR-V when all inputs/outputs are indexed (#4389) 2023-02-09 04:48:25 +01:00
Isaac Marovitz
7bae440d3a ObjectiveC Helper Class (#4286)
* `NativeMacOS` Helper Class

* Corrections

* Make CFString IDisposable

* Fix `openURL:`

* `dealloc` metal layer

* Remove releases

* Use NSString

* Update Ryujinx.Ui.Common/Helper/NativeMacOS.cs

Co-authored-by: merry <git@mary.rs>

* Programatically select updates in Finder

* Address feedback

* Feedback

* Ptr

* Fix whoopsie

* Ack suggestions

* Update Ryujinx.Ava/UI/Renderer/EmbeddedWindow.cs

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

* GDK Suggestions

---------

Co-authored-by: merry <git@mary.rs>
Co-authored-by: gdkchan <gab.dark.100@gmail.com>
2023-02-09 04:08:15 +01:00
riperiperi
f1943fd0b6 Log shader compile errors with Warning level (#2617)
* Log shader compile errors with Warning level

These are infrequent enough that I think it's worth dumping any errors into the log. They also keep causing graphical glitches, and the only indication that anything went wrong is a debug log that is never enabled.

* Add maximum length for shader log
2023-02-09 03:50:18 +01:00
TSRBerry
ec8d4f3af5 Replace unicorn bindings with Nuget package (#4378)
* Replace unicorn bindings with Nuget package

* Use nameof for ValueSource args

* Remove redundant code from test projects

* Fix wrong values for EmuStart()

Add notes to address this later again

* Improve formatting

* Fix formatting/alignment issues
2023-02-09 02:24:32 +01:00
riperiperi
b3f0978869 Vulkan: Flush command buffers for queries less aggressively (#4387)
The AutoFlushCounter would flush command buffers on any attachment change (write mask or bindings change) if there was a pending query. This is to get query results as soon as possible for draw skips, but it's assuming that a full occlusion query _pass_ happened, that we want to flush it's data before getting onto draws, rather than the queries being randomly interspersed throughout a pass that also draws.

Xenoblade 2 repeatedly switches between performing a samples passed query and outputting to a render target on each draw, and flips the write mask to do so. Flushing the command buffer every 2 draws isn't ideal, so it's best that we only do this if the pattern matches the large block style of occlusion query.

This change makes this flush only happen after a few consecutive query reports. "Consecutive" is interrupted by attachment changes or command buffer flush.

This doesn't really solve the issue where it resets more queries than it uses, it just stops the game doing it as often. I'm not sure of the best way to do that. The cost of resetting could probably be reduced by using query pools with more than one element and resetting in bulk.
2023-02-09 02:03:41 +01:00
Ac_K
f614d2c435 bug_report.yml hotfix 2023-02-09 02:02:00 +01:00
Ac_K
40c9416097 Misc: Update issues form (#4383) 2023-02-09 00:52:43 +00:00
dependabot[bot]
618c8edc79 nuget: bump System.IdentityModel.Tokens.Jwt from 6.26.0 to 6.26.1 (#4384)
Bumps [System.IdentityModel.Tokens.Jwt](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet) from 6.26.0 to 6.26.1.
- [Release notes](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/releases)
- [Changelog](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/compare/6.26.0...v6.26.1)

---
updated-dependencies:
- dependency-name: System.IdentityModel.Tokens.Jwt
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-08 22:51:07 +01:00
Berkan Diler
99fc4fa61b Replace BitConverter.ToString(bytes).Replace("-", "") with Convert.ToHexString(bytes) (#4382) 2023-02-08 14:54:58 +01:00
gdkchan
f6d5499a16 Fix some Vulkan validation errors (#4357) 2023-02-08 14:34:22 +01:00
gdkchan
26bf13a65d Limit texture cache based on total texture size (#4350)
* Limit texture cache based on total texture size

* Formatting
2023-02-08 14:19:43 +01:00
gdkchan
96cf242bcf Handle mismatching texture size with copy dependencies (#4364)
* Handle mismatching texture size with copy dependencies

* Create copy and render textures with the minimum possible size

* Only align width for comparisons, assume that height is always exact

* Fix IsExactMatch size check

* Allow sampler and copy textures to match textures with larger width

* Delete texture ChangeSize related code

* Move AdjustSize to TextureInfo and give it a better name, adjust usages

* Fix GetMinimumWidthInGob when minimumWidth > width

* Only update render targets that are actually cleared for clear

Avoids creating textures with incorrect sizes

* Delete UpdateRenderTargetState method that is not needed anymore

Clears now only ever sets the render targets that will be cleared rather than all of them
2023-02-08 08:48:09 +01:00
TSRBerry
59755818ef Add ChangeVSyncMode() call to Avalonia render loop (#4379) 2023-02-08 01:28:53 +01:00
gdkchan
f8beeeb7d3 Support safe blit on non-2D textures (#4374)
* Support safe blit on non-2D textures (except multisample)

* Change safe blit with different levels and layers to match CmdBlitImage path

* Remove now unused variables

* Multisample safe blit support
2023-02-07 13:55:59 -03:00
gdkchan
cb250162cb Accelerate NVDEC VIC surface read/write and colorspace conversion with Arm64 HW intrinsics (#4351)
* Accelerate NVDEC VIC surface read/write and colorspace conversion with Arm64 HW intrinsics

* Improve ReadNv12 x86 SSE path
2023-02-07 02:38:54 +00:00
gdkchan
7528f94536 Implement safe depth-stencil blit using stencil export extension (#4356)
* Implement safe depth-stencil blit using stencil export extension

* Delete depth-stencil blit with buffer path
2023-02-06 00:19:31 -03:00
gdkchan
43081c16c4 Insert bitcast for assignment of fragment integer outputs on GLSL (#4369)
* Insert bitcast for assignment of fragment integer outputs on GLSL

* Shader cache version bump
2023-02-05 18:52:57 -03:00
gdkchan
780627e7b0 Implement Account LoadOpenContext (#4359)
* Implement Account LoadOpenContext

* Formatting
2023-02-01 12:52:36 -03:00
dependabot[bot]
9044cb38d1 nuget: bump SharpZipLib from 1.4.1 to 1.4.2 (#4353)
Bumps [SharpZipLib](https://github.com/icsharpcode/SharpZipLib) from 1.4.1 to 1.4.2.
- [Release notes](https://github.com/icsharpcode/SharpZipLib/releases)
- [Changelog](https://github.com/icsharpcode/SharpZipLib/blob/master/docs/Changes.txt)
- [Commits](https://github.com/icsharpcode/SharpZipLib/compare/v1.4.1...v1.4.2)

---
updated-dependencies:
- dependency-name: SharpZipLib
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-31 01:58:25 +01:00
gdkchan
a53cfdab78 Initial Apple Hypervisor based CPU emulation (#4332)
* Initial Apple Hypervisor based CPU emulation implementation

* Add UseHypervisor Setting

* Add basic MacOS support to Avalonia

* Fix initialization

* Fix GTK build

* Fix/silence warnings

* Change exceptions to asserts on HvAddressSpaceRange

* Replace DllImport with LibraryImport

* Fix LibraryImport

* Remove unneeded usings

* Revert outdated change

* Set DiskCacheLoadState when using hypervisor too

* Fix HvExecutionContext PC value

* Address PR feedback

* Use existing entitlements.xml file on distribution folder

---------

Co-authored-by: riperiperi <rhy3756547@hotmail.com>
2023-01-29 08:37:52 -03:00
Piplup
c7f9962dde converts the templates into forms (#4068)
* Create bug_report.yml

* Update bug_report.yml

* Update bug_report.yml

* Create feature_request.yml

* Update feature_request.yml

* Update feature_request.yml

* Update feature_request.yml

* Update feature_request.yml

* a

* Update missing_cpu_instruction.yml

* Update missing_cpu_instruction.yml

* Update missing_cpu_instruction.yml

* Update missing_cpu_instruction.yml

* b

* addressed some of the feedback

* forget the label

* added missing text inputs

* formatting changes

* dropdown menu

added dropdown menu for os, idk if we will keep this

* addressed feedback

addressed the long overdue feedback, sorry about that

* added markdowns

everything should be addressed now i hope

* game version optional

made game version optional after further feedback

* feature request checkbox
2023-01-27 18:23:55 +00:00
gdkchan
296c4a3d01 Relax Vulkan requirements (#4282)
* Relax Vulkan requirements

* Fix MaxColorAttachmentIndex

* Fix ColorBlendAttachmentStateCount value mismatch for background pipelines

* Change query capability check to check for pipeline statistics query rather than geometry shader support
2023-01-26 18:34:35 -03:00
riperiperi
e7cf4e6eaf Vulkan: Reset queries on same command buffer (#4329)
* Reset queries on same command buffer

Vulkan seems to complain when the queries are reset on another command buffer. No idea why, the spec really could be written better in this regard. This fixes complaints, and hopefully any implementations that care extensively about them.

This change _guesses_ how many queries need to be reset and resets as many as possible at the same time to avoid splitting render passes. If it resets too many queries, we didn't waste too much time - if it runs out of resets it will batch reset 10 more.

The number of queries reset is the maximum number of queries in the last 3 frames. This has been worked into the AutoFlushCounter so that it only resets up to 32 if it is yet to force a command buffer submission in this attachment.

This is only done for samples passed queries right now, as they have by far the most resets.

* Address Feedback
2023-01-24 13:32:56 -03:00
gdkchan
a1a4771ac1 Remove use of GetFunctionPointerForDelegate to get JIT cache function pointer (#4337)
* Remove use of GetFunctionPointerForDelegate to get JIT cache function pointer

* Rename FuncPtr to FuncPointer
2023-01-23 22:37:53 +00:00
gdkchan
2fd819613f SPIR-V: Change BitfieldExtract and BitfieldInsert for SPIRV-Cross (#4336)
* SPIR-V: Change BitfieldExtract and BitfieldInsert types to make Metal MSL compiler happy

* Shader cache version bump
2023-01-23 19:20:40 -03:00
TSRBerry
ad6ff6ce99 GUI: Add option to register file types (#4250)
* Add FileAssociationHelper.cs

* Add register file types option to gtk

* Add register file types option to avalonia

* Add Windows support to FileAssociationHelper.cs

* linux: Add uninstall support for file types

* Ignore .glade~ backup files

* Rename Register/Unregister methods

* gtk: Add manage file types submenu

* ava: Add manage file types submenu

* windows: Add uninstall support for file types

* Don't invert uninstall condition (formatting change)

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

* Add IsTypesRegisteredWindows & Fix Windows install function

* Add AreMimeTypesRegisteredLinux()

* Fix wrong indention

Co-authored-by: AcK77 <acoustik666@gmail.com>
Co-authored-by: gdkchan <gab.dark.100@gmail.com>
2023-01-22 17:39:00 +00:00
gnisman
dc30d94852 Handle parsing of corrupt Config.json and prevent crash on launch (#4309)
* Handle parsing of corrupt Config.json and prevent crash on launch

* Implement a cleaner solution to handle empty json object
2023-01-22 17:04:33 +01:00
merry
4f293f8cbe Arm64: Simplify TryEncodeBitMask and use for constants (#4328)
* Arm64: Simplify TryEncodeBitMask

* CodeGenerator: Use TryEncodeBitMask in GenerateConstantCopy

* Ptc: Bump version
2023-01-22 14:15:49 +00:00
merry
32a1cd83fd AvaloniaKeyboardDriver: Swallow TextInput events to avoid bell (#4320) 2023-01-22 11:21:52 +01:00
riperiperi
e3d0ccf8d5 Allow setting texture data from 1x to fix some textures resetting randomly (#2860)
* Allow setting texture data from 1x to fix some textures resetting randomly

Expected targets:

- Deltarune 1+2
- Crash Team Racing
- Those new pokemon games idk

* Allow scaling of MSAA textures, propagate scale on copy.

* Fix Rebase

Oops

* Automatic disable

* A bit more aggressive

* Without the debug log

* Actually decrement the score when writing.
2023-01-22 02:03:30 +00:00
Ac_K
c14844d12c Ava UI: Various Fixes (#4326)
* Ava UI: Various Fixes

* use WriteAllBytes
2023-01-22 01:42:55 +01:00
gdkchan
7fea26e97e Remove use of reflection on GAL multithreading (#4287)
* Introduce new IGALCommand<T> interface and use it

* Remove use of reflection on GAL multithreading

* Unmanaged constraint
2023-01-22 01:07:43 +01:00
dependabot[bot]
7b7f62c776 nuget: bump Microsoft.CodeAnalysis.Analyzers from 3.3.3 to 3.3.4 (#4310)
* nuget: bump Microsoft.CodeAnalysis.Analyzers from 3.3.3 to 3.3.4

Bumps [Microsoft.CodeAnalysis.Analyzers](https://github.com/dotnet/roslyn-analyzers) from 3.3.3 to 3.3.4.
- [Release notes](https://github.com/dotnet/roslyn-analyzers/releases)
- [Changelog](https://github.com/dotnet/roslyn-analyzers/blob/main/PostReleaseActivities.md)
- [Commits](https://github.com/dotnet/roslyn-analyzers/compare/v3.3.3...v3.3.4)

---
updated-dependencies:
- dependency-name: Microsoft.CodeAnalysis.Analyzers
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* Fixes warning

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Ac_K <Acoustik666@gmail.com>
2023-01-21 20:04:39 +00:00
riperiperi
423dbc8888 Use volatile read/writes for GAL threading (#4327) 2023-01-21 19:49:55 +00:00
gdkchan
6adf15e479 Implement CSET and CSETP shader instructions (#4318)
* Implement CSET and CSETP shader instructions

* Shader cache version bump

* Fix CC.HI
2023-01-21 12:18:05 -03:00
dependabot[bot]
2747f12591 nuget: bump System.IdentityModel.Tokens.Jwt from 6.25.1 to 6.26.0 (#4322)
Bumps [System.IdentityModel.Tokens.Jwt](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet) from 6.25.1 to 6.26.0.
- [Release notes](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/releases)
- [Changelog](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/commits)

---
updated-dependencies:
- dependency-name: System.IdentityModel.Tokens.Jwt
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-21 05:24:57 +01:00
Ac_K
a47824f961 Ava UI: Add Notifications and Cleanup (#4275)
* Ava UI: Add Notifications and Cleanup

* Revert notifications on ErrorDialog

* remove unused code from game list views

* Fix cast
2023-01-21 02:57:37 +01:00
Ac_K
8474d52778 Ava UI: Fix string.Format issues in Locale (#4305)
* Ava UI: Fix `string.Format` issues in Locale

* LoacLanguage everytime now

* Apply suggestions from code review

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* fix UpdateAndGetDynamicValue

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>
2023-01-21 02:06:19 +01:00
Phi
dd7a924596 Catch Profile.json parse to prevent crash on launch (#3393)
* Catch Profile.json parse to prevent crash on launch

* Update Ryujinx.HLE/HOS/Services/Account/Acc/AccountSaveDataManager.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

Co-authored-by: PhiZero <wolkan.craanen@gmail.com>
Co-authored-by: Ac_K <Acoustik666@gmail.com>
2023-01-21 01:36:57 +01:00
gnisman
a76eaf9a9a Ava UI: Add Control+Cmd+F HotKey for Mac OS (#4317)
* Ava UI: Add Control+Cmd+F HotKey for Mac OS

* fix aligned

* Remove comment from code
2023-01-20 22:18:01 +01:00
merry
009e6bcd1b Audio: Implement PCM24 output (#4321) 2023-01-20 21:46:13 +01:00
Ac_K
eb2cc159fa Ava UI: Fixes and cleanup Updater (#4269)
* ava: Fixes and cleanup Updater

* _updateSuccessful
2023-01-20 21:30:21 +01:00
Fliperworld
bb89e36fd8 Vulkan: Destroy old swapchain on swapchain recreation (#3889)
* Destroy old swapchain on swapchain recreation

* vkDeviceWaitIdle before DestroySwapchain

* Update Ryujinx.Graphics.Vulkan/Window.cs

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

* Avoid unsafe code on RecreateSwapchain()

* Destroying old Swapchain on a queue.

* Cleanup and fix on destroying old Swapchain.

* Update Ryujinx.Graphics.Vulkan/Window.cs

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

* Update Ryujinx.Graphics.Vulkan/Window.cs

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

* Update Ryujinx.Graphics.Vulkan/Window.cs

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

* Update Window.cs

Done.

Co-authored-by: gdkchan <gab.dark.100@gmail.com>
2023-01-19 21:31:25 -03:00
riperiperi
de3134adbe Vulkan: Explicitly enable precise occlusion queries (#4292)
The only guarantee of the occlusion query type in Vulkan is that it will be zero when no samples pass, and non-zero when any samples pass. Of course, most GPUs implement this by just placing the # of samples in the result and calling it a day. However, this lax restriction means that GPUs could just report a boolean (1/0) or report a value after one is recorded, but before all samples have been counted.

MoltenVK falls in the first category - by default it only reports 1/0 for occlusion queries. Thankfully, there is a feature and flag that you can use to force compatible drivers to provide a "precise" query result, that being the real # of samples passed.

Should fix ink collision in Splatoon 2/3 on MoltenVK.
2023-01-19 00:30:42 +00:00
merry
36d53819a4 NativeSignalHandler: Fix write flag (#4306)
* NativeSignalHandler: Fix write flag

* address comments
2023-01-19 00:13:17 +00:00
Andrey Sukharev
ae4324032a Optimize string memory usage. Use Spans and StringBuilders where possible (#3933)
* Optimize string memory usage. Use ReadOnlySpan<char> and StringBuilder where possible.

* Fix copypaste error

* Code generator review fixes

* Use if statement instead of switch

* Code style fixes

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Another code style fix

* Styling fix

Co-authored-by: Mary-nyan <thog@protonmail.com>

* Styling fix

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>
Co-authored-by: Mary-nyan <thog@protonmail.com>
Co-authored-by: gdkchan <gab.dark.100@gmail.com>
2023-01-18 22:25:16 +00:00
Ac_K
f449895e6d HOS: Load RomFs by pid (#4301)
We currently loading only one RomFs at a time, which could be wrong if one day we want to load more than one guest at time.
This PR fixes that by loading romfs by pid.
2023-01-18 13:50:42 +00:00
TSRBerry
410be95ab6 Fix NRE when disposing AddressSpace with 4KB pages support (#4307) 2023-01-17 14:50:39 +00:00
merry
cff9046fc7 ConfigurationState: Default to Vulkan on macOS (#4299) 2023-01-17 05:32:08 +01:00
gdkchan
86fd0643c2 Implement support for page sizes > 4KB (#4252)
* Implement support for page sizes > 4KB

* Check and work around more alignment issues

* Was not meant to change this

* Use MemoryBlock.GetPageSize() value for signal handler code

* Do not take the path for private allocations if host supports 4KB pages

* Add Flags attribute on MemoryMapFlags

* Fix dirty region size with 16kb pages

Would accidentally report a size that was too high (generally 16k instead of 4k, uploading 4x as much data)

Co-authored-by: riperiperi <rhy3756547@hotmail.com>
2023-01-17 05:13:24 +01:00
Ac_K
43a83a401e Ava UI: Readd some infos to the GameList (#4302) 2023-01-17 04:57:21 +01:00
riperiperi
f0e27a23a5 Add short duration texture cache (#3754)
* Add short duration texture cache

This texture cache takes textures that lose their last pool reference and keeps them alive until the next frame, or until an incompatible overlap removes it. This is done since under certain circumstances, a texture's reference can be wiped from a pool despite it still being in use - though typically the reference will return when rendering the next frame.

While this may slightly increase texture memory usage when quickly going through a bunch of temporary textures, it's still bounded due to the overlap removal rule.

This greatly increases performance in Hyrule Warriors: Age of Calamity. It may positively affect some UE4 games which dip framerate severely under certain circumstances.

* Small optimization

* Don't forget this.

* Add short cache dictionary

* Address feedback

* Address some feedback
2023-01-17 04:39:46 +01:00
TSRBerry
e68650237d Ava: Fix Linux Vulkan renderer regression (#4303)
* ava: Fix Linux Vulkan renderer staying transparent

* ava: Minor Renderer cleanup

* Don't supress potential NRE warning

Co-authored-by: Ac_K <Acoustik666@gmail.com>

Co-authored-by: Ac_K <Acoustik666@gmail.com>
2023-01-16 03:59:41 +01:00
Ac_K
1faff14e73 UI: Fixes GTK sorting regression of #4294 2023-01-16 03:09:52 +01:00
Ac_K
784cf9d594 Ava UI: Renderer refactoring (#4297)
* Ava UI: `Renderer` refactoring

* Fix Vulkan CreateSurface
2023-01-16 01:14:01 +01:00
Ac_K
64263c5218 UI: Fix applications times (#4294)
* Fix applications times

* Add spaces

* Fix TimeString formatting
2023-01-16 00:11:16 +01:00
gdkchan
065c4e520d Specify image view usage flags on Vulkan (#4283)
* Specify image view usage flags on Vulkan

* PR feedback
2023-01-15 23:12:52 +01:00
Isaac Marovitz
139a930407 Implement missing service calls in pm (#4210)
* Implement `GetTitleId`

Fixes #2516

* Null check + Proper result code

* Better comment

* Implement `GetApplicationProcessId`

* Add TODOs

* Update Ryujinx.HLE/HOS/Services/Pm/IInformationInterface.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.HLE/HOS/Services/Pm/IDebugMonitorInterface.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Remove new function from KernelStatic

Co-authored-by: Ac_K <Acoustik666@gmail.com>
2023-01-15 22:16:24 +01:00
Isaac Marovitz
719dc97bbd Ava UI: TitleUpdateWindow Refactor (#4276)
* Start Refactor

* Dialogue opens

* Changes

* Switch to ListBox

* Fix bugs and stuff

* Fix spacing

* Implement OpenLocation

* Change icon

* Color

* Color

* Remove background

* Make no update the same height

* Fix height and smooth scroll

* Height

* Fix update selection

* Make window smaller

* Add back remove all button

* Make selection more obvious

* Hide selection bar on SaveManager

* Fix autoscroll

* Fix no update not staying selected

* Better file opener

* Fix

* Revert that

* Update Ryujinx.Ava/UI/ViewModels/TitleUpdateViewModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Log warning

* Update Ryujinx.Ava/UI/ViewModels/TitleUpdateViewModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

Co-authored-by: Ac_K <Acoustik666@gmail.com>
2023-01-15 11:11:52 +00:00
merry
41bba5310a Audren: Implement polyphase upsampler (#4256)
* Audren: Implement polyphase upsampler

* prefer shifting to modulo

* prefer MathF

* fix nits

* rm ResampleForUpsampler

* oop

* Array20

* nits
2023-01-15 05:20:49 +01:00
Ac_K
8071c8c8c0 Ava UI: Fixes "Hide Cursor on Idle" for Windows (#4266)
* Ava: Fixes "Hide Cursor on Idle" for Windows

* Add check in MouseDriver and reduce the time of idling

* Fix linux error

* Change idle time everywhere for consistencies
2023-01-15 01:05:44 +01:00
gnisman
b402b4e7f6 Change GetPageSize to use Environment.SystemPageSize (#4291)
* Change GetPageSize to use Environment.SystemPageSize

* Fix PR comment
2023-01-14 15:37:04 -03:00
gdkchan
93df366b2c Fix texture flush from CPU WaitSync regression on OpenGL (#4289) 2023-01-14 11:23:57 -03:00
gdkchan
cd3a15aea5 Fix NRE when MemoryUnmappedHandler is called for a destroyed channel (#4285) 2023-01-14 00:16:06 -03:00
gdkchan
070136b3f7 Fix texture modified on CPU from GPU thread after being modified on GPU not being updated (#4284) 2023-01-13 23:46:45 -03:00
Ac_K
08ab47c6c0 Update Program.cs 2023-01-13 07:56:41 +01:00
Ac_K
85faa9d8fa Revert "Relax Vulkan requirements (#4228)" (#4279)
This reverts commit dca5b14493.
2023-01-13 06:04:59 +00:00
gdkchan
dca5b14493 Relax Vulkan requirements (#4228) 2023-01-13 06:09:48 +01:00
Ac_K
4d2c8e2a44 Prepo: Fix SaveSystemReport* IPC definitions (#4278)
* Prepo: Fix SaveSystemReport IPC definitions

* Follow original code

* Fix args index in HipcGenerator

* Addresses feedback

* oops
2023-01-13 01:50:14 +01:00
riperiperi
8fa248ceb4 Vulkan: Add workarounds for MoltenVK (#4202)
* Add MVK basics.

* Use appropriate output attribute types

* 4kb vertex alignment, bunch of fixes

* Add reduced shader precision mode for mvk.

* Disable ASTC on MVK for now

* Only request robustnes2 when it is available.

* It's just the one feature actually

* Add triangle fan conversion

* Allow NullDescriptor on MVK for some reason.

* Force safe blit on MoltenVK

* Use ASTC only when formats are all available.

* Disable multilevel 3d texture views

* Filter duplicate render targets (on backend)

* Add Automatic MoltenVK Configuration

* Do not create color attachment views with formats that are not RT compatible

* Make sure that the host format matches the vertex shader input types for invalid/unknown guest formats

* FIx rebase for Vertex Attrib State

* Fix 4b alignment for vertex

* Use asynchronous queue submits for MVK

* Ensure color clear shader has correct output type

* Update MoltenVK config

* Always use MoltenVK workarounds on MacOS

* Make MVK supersede all vendors

* Fix rebase

* Various fixes on rebase

* Get portability flags from extension

* Fix some minor rebasing issues

* Style change

* Use LibraryImport for MVKConfiguration

* Rename MoltenVK vendor to Apple

Intel and AMD GPUs on moltenvk report with the those vendors - only apple silicon reports with vendor 0x106B.

* Fix features2 rebase conflict

* Rename fragment output type

* Add missing check for fragment output types

Might have caused the crash in MK8

* Only do fragment output specialization on MoltenVK

* Avoid copy when passing capabilities

* Self feedback

* Address feedback

Co-authored-by: gdk <gab.dark.100@gmail.com>
Co-authored-by: nastys <nastys@users.noreply.github.com>
2023-01-13 01:31:21 +01:00
Ac_K
30862b5ffd ava: Reorder settings of Resolution Scaler (#4270) 2023-01-13 00:07:53 +01:00
Isaac Marovitz
9f57747c57 Ava UI: Various Fixes (#4268)
* Fix saves disappearing

* Better size formatter

* Move TextBox alignment fix to Styles

* Fix bug

* Left align

* Add border

* Update Ryujinx.Ava/UI/Models/SaveModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/Models/SaveModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/Models/SaveModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Whitespace

Co-authored-by: Ac_K <Acoustik666@gmail.com>
2023-01-12 12:23:24 +00:00
Isaac Marovitz
fe29a2ff6e Ava UI: Settings Adjustments (#4273)
* Visual adjustments

* Match border to rest of app

* Fix overlapping controls

* Fix

* Fix
2023-01-12 12:09:32 +00:00
merry
e9a173e00c Ptc: Check process architecture (#4272) 2023-01-12 07:50:45 +00:00
merry
a11784fcbf Arm64: Cpu feature detection (#4264)
* Arm64: Cpu feature detection

* Ptc: Add Arm64 feature info

* nits

* simplify CheckSysctlName

* restore some macos flags

* feedback
2023-01-12 08:05:18 +01:00
Ac_K
fd36c8deca lm: Handle Tail flag in LogPacket (#4274)
* lm: Handle TailFlag in LogPacket

* Addresses feedback
2023-01-12 07:42:05 +01:00
Ac_K
70638340b3 Ava UI: Move Ava logging to Logger.Debug (#4255)
* Ava: Move Ava logging to Logger.Debug

Since #4231 we currently redirect Avalonia logs to our Logger, which is pretty nice. But since it uses our Logging level too, it now leads to a massive flood in our Log files.
To avoid that, I've included all `AvaLogLevel` to the log message, and make all Ava Logs using `Logger.Debug`.

* Logs errors to Error and other to Debug

* missing level

* keep var
2023-01-11 23:27:26 +01:00
Ac_K
4b495f3333 Ava UI: Fixes PerformanceCheck condition (#4271) 2023-01-11 20:47:15 +00:00
Isaac Marovitz
934b5a64e5 Ava GUI: User Profile Manager + Other Fixes (#4166)
* Fix redundancies

* Add back elses

* Loading Screen fixes

* Redesign User Profile Manager

- Backported long selection bar in Grid/List view not working
- Backported UserSelector is jank

* Fix SelectionIndicator

* Fix DataType

* Fix SaveManager bug

* Remove debug log

* Load saves on UIThread

* Reduce UI thread blocking

* Fix locale keys

* Use block namespaces

* Fix close button width

* Make UserProfile ordering consistent

* Alphabetical order

* Adjust layout, remove green circle for blue selector

* Fix some inconsistencies

* Fix no inital selected profile

* Adjust appearance of edit button

* Adjust SaveManager

* Remove redundant warning dialog

* Make firmware avatar selector clearer

* View redesign again :hero_depressed:

* Consistency adjustments

* Adjust margins

* Make `UserProfileImageSelector` consistent

* Make `UserFirmwareAvatarSelector` consistent

* Fix long grid view selector

* Switch case

* Remove long selection bar

Handled in #4178

* Consistency

* Started dialog titles

* Fixes

* Remaining titles

* Update Ryujinx.Ava/UI/Controls/NavigationDialogHost.axaml

Co-authored-by: Mary-nyan <thog@protonmail.com>

* Fix build

* Hide UserRecoverer if no LostProfiles are found

* UserEditor Avatar Placeholder

* Watermark + locale adjustment

* Border radius

* Remove unnecessary styles

* Fix firmware avatar image order

* Cleanup `ColorPickerButton`

* Make `UserId` copy/paste able

* Make `FirmwareAvatarSelector` 6 images wide

* Make selection bar better

* Unsaved changes dialogue

* Fix indentation

* Remove extra check

* Address suggestions

* Reorganise

- Remove unused views
- Rename views to match convention
- Fix weird namespacing

* Update Ryujinx.Ava/UI/Views/User/UserFirmwareAvatarSelectorView.axaml

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/Views/User/UserFirmwareAvatarSelectorView.axaml

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* UserRecovererView empty placeholder

* Update Ryujinx.Ava/UI/Views/User/UserSelectorView.axaml.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/Views/User/UserSaveManagerView.axaml.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/Views/User/UserSaveManagerView.axaml.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/Views/User/UserSaveManagerView.axaml.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/Views/User/UserRecovererView.axaml.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/Views/User/UserFirmwareAvatarSelectorView.axaml.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/ViewModels/UserFirmwareAvatarSelectorViewModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/ViewModels/UserFirmwareAvatarSelectorViewModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/ViewModels/UserFirmwareAvatarSelectorViewModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/Models/UserProfile.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/Controls/NavigationDialogHost.axaml.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/Controls/NavigationDialogHost.axaml.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Remove AddModel

* Update Ryujinx.Ava/Assets/Locales/en_US.json

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Fix bug

Co-authored-by: Mary-nyan <thog@protonmail.com>
Co-authored-by: Ac_K <Acoustik666@gmail.com>
2023-01-11 06:20:19 +01:00
Ac_K
cee667b491 Ava: Fixes Update count in heading (#4265) 2023-01-11 05:39:25 +01:00
gdkchan
94a64f2aea Remove textures from cache on unmap if not mapped and modified (#4211) 2023-01-11 01:53:56 +00:00
Ac_K
2355c2af62 ava: Generate Locale menu automatically (#4243)
Currently in `MenuMainBarView.axaml` we list all available languages and hardcode the language name with the language key.
It's a bit bad beause if we want to add a new language, we have to edit the `csproj` and the `axaml` with the translated language name and the language code.
I've put all translations in their respective locale files, add code into `MainMenuBarView` constructor to generate the menu automatically. Now we just have to edit the `csproj` if we want to add a new language.
2023-01-11 01:29:22 +01:00
gdkchan
5e0f8e8738 Implement JIT Arm64 backend (#4114)
* Implement JIT Arm64 backend

* PPTC version bump

* Address some feedback from Arm64 JIT PR

* Address even more PR feedback

* Remove unused IsPageAligned function

* Sync Qc flag before calls

* Fix comment and remove unused enum

* Address riperiperi PR feedback

* Delete Breakpoint IR instruction that was only implemented for Arm64
2023-01-10 19:16:59 -03:00
UltraHDR
d16288a2a8 Set LSApplicationCategoryType to games (#4257)
https://developer.apple.com/documentation/bundleresources/information_property_list/lsapplicationcategorytype
Makes it auto-add to the macOS Launchpad games folder
2023-01-10 21:49:46 +00:00
Isaac Marovitz
600f86dc7b Fix context menu locales (#4242) 2023-01-10 19:15:15 +01:00
Mary-nyan
7210c17c5e misc: Enforce LF (#4253)
Because we are building everything on Windows for release at the moment,
git default line ending to CRLF causing issues when packing the
Ryujinx.sh script.

This addresses this by enforcing all files to use LF via .gitattributes.
2023-01-10 19:00:14 +01:00
Ac_K
a16854e55a ava: Cleanup AppHost (#4240)
* ava: Cleanup AppHost

This PR cleaned up the AppHost file a bit (adding the infamous extra spaces to improve readability), resorting private vars, remove useless vars, and improve the code here and there, like the AudioBackend check.

Co-Authored-By: gdkchan <5624669+gdkchan@users.noreply.github.com>

* Remove 'renderer"

* Revert currentTime

* revert if condition

Co-authored-by: gdkchan <5624669+gdkchan@users.noreply.github.com>
2023-01-10 18:45:55 +01:00
TSRBerry
3e455a90a1 Ava: Add missing null check to ContentDialogHelper.ShowAsync() (#4248)
* ava: Add missing null check to ContentDialogHelper.ShowAsync()

* Replace "is not" with != operator

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

Co-authored-by: gdkchan <gab.dark.100@gmail.com>
2023-01-10 09:22:25 +01:00
TSRBerry
e4413542b2 Add command line arguments to override docked mode (#4239)
* Add command line args for docked mode

* Apply suggestions from code review

Co-authored-by: Ac_K <Acoustik666@gmail.com>

Co-authored-by: Ac_K <Acoustik666@gmail.com>
2023-01-10 00:59:23 +01:00
TSRBerry
8c720783f5 linux: Fix packaging step for CI & Add Ryujinx.Headless.SDL2 to Ryujinx.sh (#4249) 2023-01-09 23:45:46 +00:00
TSRBerry
8734ea9dd4 Linux: Add Avalonia detection to Ryujinx.sh (#4224)
* Revert "ava: Fix regression caused by #4013 (#4222)"

This reverts commit b9f2a96595.

* linux: Detect Ryujinx.Ava and don't rename the Ryujinx.Ava assembly
2023-01-09 22:58:51 +01:00
gdkchan
c586e6d2b7 Replace tabs with spaces across the project (#4244)
* Replace tabs with spaces across the project

* Include AXAML files too
2023-01-09 22:58:29 +01:00
TSRBerry
3a4eeb77fe headless: Change window icon size to 48x48 (#4247) 2023-01-09 18:02:41 +00:00
TSRBerry
51b3953cfc [Headless] Add missing arguments & Fix typos (#4193)
* headless: Fix typos in command line options

* Remove nullable from command line options

Add EnableMacroHLE option
Add HideCursorOnIdle option

* headless: Adjust enable-ptc help text

* headless: Use switch statement instead of if-else chain

* headless: Improve formatting for long constructors

* headless: Remove discards from SDL_ShowCursor()

* headless: Add window icon

* Fix hiding cursor on idle

At least on Wayland, SDL2 doesn't produce any mouse motion events.

* Add new command line args: BaseDataDir and UserProfile

* headless: Read icon from embedded resource

* headless: Skip SetWindowIcon() on Windows if dll isn't present

* headless: Fix division by zero

* headless: Fix command line options not working correctly

* headless: Fix crash when viewing command line options

* headless: Load window icon bmp from memory

* Add comment to the workaround for SDL_LoadBMP_RW

* headless: Enable logging to file by default

* headless: Add 3 options for --hide-cursor

Replaces --disable-hide-cursor-on-idle
2023-01-09 04:55:37 +01:00
Ac_K
610eecc1c1 ava: Fixes regressions from refactoring (#4237)
* ava: Fix regressions from #4178

* Remove duplicated code

* real fix for right click menu

Co-Authored-By: Isaac Marovitz <42140194+IsaacMarovitz@users.noreply.github.com>

* Remove ContentDialogOverlay

Co-authored-by: Isaac Marovitz <42140194+IsaacMarovitz@users.noreply.github.com>
2023-01-09 03:37:20 +00:00
merry
492056abf6 Ava: Make Avalonia use our logging system (#4231)
* Ava: Make Avalonia use our logging system

* LoggerAdapter: Address review comments

* Update Ryujinx.Common/Logging/LogClass.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>
2023-01-09 04:32:20 +01:00
Isaac Marovitz
ee6e682ab4 Fix selection bar (#4236) 2023-01-09 03:36:11 +01:00
gdkchan
6f60e102a2 HIPC: Fix reply possibly also receiving one request (#4232) 2023-01-08 15:34:49 -03:00
Isaac Marovitz
eeb2af9953 Ava GUI: MainWindow Refactor (#4178)
* Fix redundancies

* Add back elses

* `MainWindow` Refactor

* Switch commands to `ReflectionBinding`

Not required in Ava 11

* Update Ryujinx.Ava/AppHost.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/AppHost.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/Windows/MainWindow.axaml.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/Windows/MainWindow.axaml.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/Windows/MainWindow.axaml.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/AppHost.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/Views/Main/MainViewControls.axaml.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/AppHost.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/AppHost.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/AppHost.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/Views/Main/MainMenuBarView.axaml.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/Views/Main/MainViewControls.axaml.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Resolve issues

* Remove Ava 11 Fix

* Update Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

* Update Ryujinx.Ava/UI/Windows/MainWindow.axaml.cs

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

* Fix whitespace + other suggestions

* Move Vsync colours to `Styles.xaml`

* Remove catch all

* Use `switch` instead of `if`

* Update locale keys

* Use block-scoped namespaces

* Fix improper Ava api usage then

* Static PTC

* Fix `GridItemSelectorSize` with `ShowNames`

* Update for new About Window

* Add back search fix

Co-authored-by: Ac_K <Acoustik666@gmail.com>
Co-authored-by: gdkchan <gab.dark.100@gmail.com>
2023-01-08 18:46:25 +01:00
Ac_K
550747eac6 Horizon: Impl Prepo, Fixes bugs, Clean things (#4220)
* Horizon: Impl Prepo, Fixes bugs, Clean things

* remove ToArray()

* resultCode > status

* Remove old services

* Addresses gdkchan's comments and more cleanup

* Addresses Gdkchan's feedback 2

* Reorganize services, make sure service are loaded before guest

Co-Authored-By: gdkchan <5624669+gdkchan@users.noreply.github.com>

* Create interfaces for lm and sm

Co-authored-by: gdkchan <5624669+gdkchan@users.noreply.github.com>
2023-01-08 12:13:39 +00:00
merry
3ffceab1fb MainWindow: Vertically center SearchBox TextPresenter (#4223) 2023-01-07 16:01:53 +00:00
Mary-nyan
b9f2a96595 ava: Fix regression caused by #4013 (#4222)
Avalonia seems to not like when the artifact doesns't match the root namespace...

Address that by moving the binary to "Ryujinx" like we do on macOS build.
2023-01-07 12:24:21 +01:00
RMED24
cbaa845f5d Include a start.sh file with correct launch options (#4013)
* Include reference to start.sh to be bundled

* Add start.sh

* Fix silly mistake I made on windows-x64

* ... I cannot read properly

* Make same changes for avalonia csproj

* Remove notice from start.sh

Co-authored-by: Mary-nyan <thog@protonmail.com>

* Update Ryujinx/Ryujinx.csproj

Co-authored-by: Mary-nyan <thog@protonmail.com>

* Update Ryujinx.Ava/Ryujinx.Ava.csproj

Co-authored-by: Mary-nyan <thog@protonmail.com>

* Update distribution/linux/start.sh

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Update distribution/linux/start.sh

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Update Ryujinx.Ava/Ryujinx.Ava.csproj

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Update Ryujinx.csproj

* Update Ryujinx.Ava.csproj

* Rename start.sh to Ryujinx.sh

* Update Ryujinx.csproj

* Update Ryujinx.Ava.csproj

* Update Ryujinx.Ava.csproj

* Update Ryujinx.Ava/Ryujinx.Ava.csproj

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Add `GDK_BACKEND` variable

* Update Ryujinx.Ava.csproj

* Update Program.cs

* Update Program.cs

* Update Ryujinx.sh

* Update Program.cs

* linux: Register mime types on launch

* Add DOTNET_EnableAlternateStackCheck=1 to desktop file

* linux: Add exclusion for RegisterMimeTypes for flathub builds

* Update logo path

* Cleanup Ryujinx.sh

* Fix typo in ReleaseInformation

* gha: Fix permissions for linux release binaries

* ava: Rename output assembly to Ryujinx

* Update mime database after installing new types

Wait until logging is available before registering mime types

* Copy mime types to output directory

Co-authored-by: Mary-nyan <thog@protonmail.com>
Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>
2023-01-07 09:06:13 +01:00
Isaac Marovitz
9e2681f2d7 Ava GUI: AboutWindow Refactor (#4196)
* Start `AboutWindow` refactor

* Redesign

* Update logos + ViewModel

* Fix GTK

* Cleanup usings

* Fix mismatched font size

* Update LocaleKeys

* Block scoped namespace

* Fix appearence on German

* Update Ryujinx.Ava/UI/ViewModels/AboutWindowViewModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/ViewModels/AboutWindowViewModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Move version number up

* Move see all contributors button left

* Add a couple `\n`

* Tooltips

* Layout fix

* Update Ryujinx.Ava/UI/ViewModels/AboutWindowViewModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

Co-authored-by: Ac_K <Acoustik666@gmail.com>
2023-01-07 01:29:18 +01:00
TSRBerry
81fae0d1a6 [hipc] Fix 'Unexpected result code Success returned' in Reply() (#4215)
* horizon: Add AbortOnFailureUnless()

* hipc: Replace AbortUnless() with AbortOnFailureUnless() in Reply()
2023-01-07 00:57:21 +01:00
Isaac Marovitz
38519f3b9a Ava GUI: SettingsWindow Refactor (#4177)
* Fix redundancies

* Add back elses

* Settings Refactor

* Fix Disposal functions

* Use `ReflectionBinding` instead of redundant funcs

* Ac_K suggestions

* Update Ryujinx.Ava/UI/ViewModels/SettingsViewModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update locale keys

* Update Ryujinx.Ava/UI/Windows/SettingsWindow.axaml.cs

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Update Ryujinx.Ava/UI/Views/Settings/SettingsSystemView.axaml.cs

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Update Ryujinx.Ava/UI/Views/Settings/SettingsSystemView.axaml.cs

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Update Ryujinx.Ava/UI/Windows/SettingsWindow.axaml.cs

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Use block-scoped namespaces

* Fix typo

* Make `TimeZone` internal again

Co-authored-by: Ac_K <Acoustik666@gmail.com>
Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>
2023-01-07 00:35:21 +01:00
Mary-nyan
7f27aabbd0 chore: Update Ryujinx.SDL2-CS to 2.26.1 (#4199) 2023-01-06 17:52:25 +01:00
4449 changed files with 304532 additions and 249254 deletions

View File

@@ -63,6 +63,10 @@ dotnet_code_quality_unused_parameters = all:suggestion
#### C# Coding Conventions ####
# Namespace preferences
csharp_style_namespace_declarations = block_scoped:warning
resharper_csharp_namespace_body = block_scoped
# var preferences
csharp_style_var_elsewhere = false:silent
csharp_style_var_for_built_in_types = false:silent

61
.gitattributes vendored
View File

@@ -1,63 +1,4 @@
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto
###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs diff=csharp
###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln merge=binary
#*.csproj merge=binary
#*.vbproj merge=binary
#*.vcxproj merge=binary
#*.vcproj merge=binary
#*.dbproj merge=binary
#*.fsproj merge=binary
#*.lsproj merge=binary
#*.wixproj merge=binary
#*.modelproj merge=binary
#*.sqlproj merge=binary
#*.wwaproj merge=binary
###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg binary
#*.png binary
#*.gif binary
###############################################################################
# diff behavior for common document formats
#
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the
# entries below.
###############################################################################
#*.doc diff=astextplain
#*.DOC diff=astextplain
#*.docx diff=astextplain
#*.DOCX diff=astextplain
#*.dot diff=astextplain
#*.DOT diff=astextplain
#*.pdf diff=astextplain
#*.PDF diff=astextplain
#*.rtf diff=astextplain
#*.RTF diff=astextplain
* text=auto eol=lf

View File

@@ -1,43 +0,0 @@
---
name: Bug Report
about: Something doesn't work correctly in Ryujinx. Game-specific issues should be posted at https://github.com/Ryujinx/Ryujinx-Games-List instead, unless it is a provable regression.
#assignees:
---
## Bug Report
[ If any section does not apply, replace its contents with "N/A". ]</br>
[ Lines between [ ] (square brackets) should be removed before posting. ]
### What's the issue you encountered?
[ Describe the issue in detail and what you were doing beforehand. ]</br>
[ Did you make any changes related to Ryujinx itself? ]</br>
[ If so, make sure to include details relating to what exactly you changed. ]
### How can the issue be reproduced?
[ Include a detailed step by step process for recreating your issue. ]
### Log file
[ Logs files can be found under ``Logs`` folder in Ryujinx program folder. ]</br>
[ If you don't include a crash report in instances of crash related issues, we will ask you one to provide one. ]
### Environment?
- Ryujinx version: 1.0.X</br>
[ Replace X's with the Ryujinx version at time of crash. ]
- Game version: X.X.X</br>
[ Replace X's with the game version at time of crash. ]
- System Specs:
- OS: *(e.g. Windows 10)*
- CPU: *(e.g. i7-6700)*
- GPU: *(e.g. NVIDIA RTX 2070)*
- RAM: *(e.g. 16GiB)*
- Applied Mods : [ Yes (Which ones) / No ]
### Additional context?
Additional info about your environment:</br>
[ Any other information relevant to your issue. ]

86
.github/ISSUE_TEMPLATE/bug_report.yml vendored Normal file
View File

@@ -0,0 +1,86 @@
name: Bug Report
description: File a bug report
title: "[Bug]"
labels: bug
body:
- type: textarea
id: issue
attributes:
label: Description of the issue
description: What's the issue you encountered?
validations:
required: true
- type: textarea
id: repro
attributes:
label: Reproduction steps
description: How can the issue be reproduced?
placeholder: Describe each step as precisely as possible
validations:
required: true
- type: textarea
id: log
attributes:
label: Log file
description: A log file will help our developers to better diagnose and fix the issue.
placeholder: Logs files can be found under "Logs" folder in Ryujinx program folder. You can drag and drop the log on to the text area
validations:
required: true
- type: input
id: os
attributes:
label: OS
placeholder: "e.g. Windows 10"
validations:
required: true
- type: input
id: ryujinx-version
attributes:
label: Ryujinx version
placeholder: "e.g. 1.0.470"
validations:
required: true
- type: input
id: game-version
attributes:
label: Game version
placeholder: "e.g. 1.1.1"
validations:
required: false
- type: input
id: cpu
attributes:
label: CPU
placeholder: "e.g. i7-6700"
validations:
required: false
- type: input
id: gpu
attributes:
label: GPU
placeholder: "e.g. NVIDIA RTX 2070"
validations:
required: false
- type: input
id: ram
attributes:
label: RAM
placeholder: "e.g. 16GB"
validations:
required: false
- type: textarea
id: mods
attributes:
label: List of applied mods
placeholder: You can list applied mods here.
validations:
required: false
- type: textarea
id: additional-context
attributes:
label: Additional context?
description: |
- Additional info about your environment:
- Any other information relevant to your issue.
validations:
required: false

View File

@@ -1,34 +0,0 @@
---
name: Feature Request
about: Suggest a new feature for Ryujinx.
#assignees:
---
## Feature Request
[ If any section does not apply, replace its contents with "N/A". ]</br>
[ If you do not have the information needed for a section, replace its contents with "Unknown". ]</br>
[ Lines between [ ] (square brackets) are to be removed before posting. ]</br>
[ Please search for existing [feature requests](https://github.com/Ryujinx/Ryujinx/issues) before you make your own request. ]</br>
[ Duplicate requests will be marked as such and you will be referred to the original request. ]
### What feature are you suggesting?
#### Overview:
- [ Include the basic, high-level concepts for this feature here. ]
#### Smaller Details:
- [ These may include specific methods of implementation etc. ]
#### Nature of Request:
[ Remove all that do not apply to your request. ]
- Addition
- [ Ex: Addition of certain original features or features from other community projects. ]
- [ If you are suggesting porting features or including features from other projects, include what license they are distributed under and what, if any libraries those project use. ]
- Change
- Removal
- [Ex: Removal of certain features or implementation due to a specific issue/bug or because of low quality code, etc.]
### Why would this feature be useful?
[ If this is a feature for an end-user, how does it benefit the end-user? ]</br>
[ If this feature is for developers, what does it add to Ryujinx that did not already exist? ]

View File

@@ -0,0 +1,30 @@
name: Feature Request
description: Suggest a new feature for Ryujinx.
title: "[Feature Request]"
body:
- type: textarea
id: overview
attributes:
label: Overview
description: Include the basic, high-level concepts for this feature here.
validations:
required: true
- type: textarea
id: details
attributes:
label: Smaller details
description: These may include specific methods of implementation etc.
validations:
required: true
- type: textarea
id: request
attributes:
label: Nature of request
validations:
required: true
- type: textarea
id: feature
attributes:
label: Why would this feature be useful?
validations:
required: true

View File

@@ -1,34 +0,0 @@
---
name: Missing CPU Instruction
about: CPU Instruction is missing in Ryujinx.
#assignees:
---
## Missing CPU Instruction
[ If any section does not apply, replace its contents with "N/A". ]</br>
[ If you do not have the information needed for a section, replace its contents with "Unknown". ]</br>
[ Lines between [ ] (square brackets) are to be removed before posting. ]
[ Please search for existing [missing CPU instruction](https://github.com/Ryujinx/Ryujinx/issues) before you make your own issue. ]</br>
[ See the following [issue](https://github.com/Ryujinx/Ryujinx/issues/1405) as an example ]</br>
[ Duplicate issue will be marked as such and you will be referred to the original request. ]
### What CPU instruction is missing?
Requires the *INSTRUCTION* instruction.</br>
[ Replace *INSTRUCTION* by the instruction name, e.g. VADDL.U16 ]
```
*
```
[ Add the undefined instruction error message in the above code block ]
### Instruction name
```
*
```
[ Include the name from [armconverter.com](https://armconverter.com/?disasm) or [shell-storm.org](http://shell-storm.org/online/Online-Assembler-and-Disassembler/?arch=arm64&endianness=big&dis_with_raw=True&dis_with_ins=True) in the above code block ]
### Required by:
[ Add our (games list database)[https://github.com/Ryujinx/Ryujinx-Games-List/issues] links of games who require this instruction ]

View File

@@ -0,0 +1,26 @@
name: Missing CPU Instruction
description: CPU Instruction is missing in Ryujinx.
title: "[CPU]"
labels: [cpu, not-implemented]
body:
- type: textarea
id: instruction
attributes:
label: CPU instruction
description: What CPU instruction is missing?
validations:
required: true
- type: textarea
id: name
attributes:
label: Instruction name
description: Include the name from [armconverter.com](https://armconverter.com/?disasm) or [shell-storm.org](http://shell-storm.org/online/Online-Assembler-and-Disassembler/?arch=arm64&endianness=big&dis_with_raw=True&dis_with_ins=True) in the above code block
validations:
required: true
- type: textarea
id: required
attributes:
label: Required by
description: Add links to the [compatibility list page(s)](https://github.com/Ryujinx/Ryujinx-Games-List/issues) of the game(s) that require this instruction.
validations:
required: true

View File

@@ -1,35 +0,0 @@
---
name: Missing Service Call
about: Service call is missing in Ryujinx.
#assignees:
---
## Missing Service Call
[ If any section does not apply, replace its contents with "N/A". ]</br>
[ If you do not have the information needed for a section, replace its contents with "Unknown". ]</br>
[ Lines between [ ] (square brackets) are to be removed before posting. ]
[ Please search for existing [missing service call](https://github.com/Ryujinx/Ryujinx/issues) before you make your own issue. ]</br>
[ See the following [issue](https://github.com/Ryujinx/Ryujinx/issues/1431) as an example ]</br>
[ Duplicate issue will be marked as such and you will be referred to the original request. ]
### What service call is missing?
*SERVICE* *INTERFACE*: *NUMBER* (*NAME*) is not implemented.</br>
[ Replace *SERVICE* by the service name, e.g. appletAE ]</br>
[ Replace *INTERFACE* by the interface name, e.g. IAllSystemAppletProxiesService ]</br>
[ Replace *NUMBER* by the call number, e.g. 100 ]</br>
[ Replace *NAME* by the call name, e.g. OpenSystemAppletProxy ]</br>
[ e.g. appletAE IAllSystemAppletProxiesService: 100 (OpenSystemAppletProxy) ]
[ Add related links to the specific call from [Switchbrew](https://switchbrew.org/w/index.php?title=Services_API) and/or [SwIPC](https://reswitched.github.io/SwIPC/) ]
### Service description
```
*
```
[ Include the description/explanation from [Switchbrew](https://switchbrew.org/w/index.php?title=Services_API) and/or [SwIPC](https://reswitched.github.io/SwIPC/) in the above code block ]
### Required by:
[ Add our (games list database)[https://github.com/Ryujinx/Ryujinx-Games-List/issues] links of games who require this call ]

View File

@@ -0,0 +1,25 @@
name: Missing Service Call
description: Service call is missing in Ryujinx.
labels: not-implemented
body:
- type: textarea
id: instruction
attributes:
label: Service call
description: What service call is missing?
validations:
required: true
- type: textarea
id: name
attributes:
label: Service description
description: Include the description/explanation from [Switchbrew](https://switchbrew.org/w/index.php?title=Services_API) and/or [SwIPC](https://reswitched.github.io/SwIPC/) in the above code block
validations:
required: true
- type: textarea
id: required
attributes:
label: Required by
description: Add links to the [compatibility list page(s)](https://github.com/Ryujinx/Ryujinx-Games-List/issues) of the game(s) that require this service.
validations:
required: true

View File

@@ -18,9 +18,14 @@ on:
- '*.yml'
- 'README.md'
env:
POWERSHELL_TELEMETRY_OPTOUT: 1
DOTNET_CLI_TELEMETRY_OPTOUT: 1
RYUJINX_BASE_VERSION: "1.1.0"
jobs:
build:
name: ${{ matrix.os }} (${{ matrix.configuration }})
name: ${{ matrix.OS_NAME }} (${{ matrix.configuration }})
runs-on: ${{ matrix.os }}
strategy:
matrix:
@@ -43,47 +48,106 @@ jobs:
RELEASE_ZIP_OS_NAME: win_x64
fail-fast: false
env:
POWERSHELL_TELEMETRY_OPTOUT: 1
DOTNET_CLI_TELEMETRY_OPTOUT: 1
RYUJINX_BASE_VERSION: "1.1.0"
steps:
- uses: actions/checkout@v3
- uses: actions/setup-dotnet@v3
with:
dotnet-version: 7.0.x
global-json-file: global.json
- name: Get git short hash
id: git_short_hash
run: echo "result=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
shell: bash
- name: Build
run: dotnet build -c "${{ matrix.configuration }}" -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER
- name: Test
run: dotnet test --no-build -c "${{ matrix.configuration }}"
- name: Publish Ryujinx
run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.DOTNET_RUNTIME_IDENTIFIER }}" -o ./publish -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:DebugType=embedded -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER Ryujinx --self-contained true
run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.DOTNET_RUNTIME_IDENTIFIER }}" -o ./publish -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:DebugType=embedded -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER src/Ryujinx --self-contained true
if: github.event_name == 'pull_request'
- name: Publish Ryujinx.Headless.SDL2
run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.DOTNET_RUNTIME_IDENTIFIER }}" -o ./publish_sdl2_headless -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:DebugType=embedded -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER Ryujinx.Headless.SDL2 --self-contained true
run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.DOTNET_RUNTIME_IDENTIFIER }}" -o ./publish_sdl2_headless -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:DebugType=embedded -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER src/Ryujinx.Headless.SDL2 --self-contained true
if: github.event_name == 'pull_request'
- name: Publish Ryujinx.Ava
run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.DOTNET_RUNTIME_IDENTIFIER }}" -o ./publish_ava -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:DebugType=embedded -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER Ryujinx.Ava --self-contained true
run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.DOTNET_RUNTIME_IDENTIFIER }}" -o ./publish_ava -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:DebugType=embedded -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER src/Ryujinx.Ava --self-contained true
if: github.event_name == 'pull_request'
- name: Set executable bit
run: |
chmod +x ./publish/Ryujinx ./publish/Ryujinx.sh
chmod +x ./publish_sdl2_headless/Ryujinx.Headless.SDL2 ./publish_sdl2_headless/Ryujinx.sh
chmod +x ./publish_ava/Ryujinx.Ava ./publish_ava/Ryujinx.sh
if: github.event_name == 'pull_request' && matrix.os == 'ubuntu-latest'
- name: Upload Ryujinx artifact
uses: actions/upload-artifact@v3
with:
name: ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.RELEASE_ZIP_OS_NAME }}
path: publish
if: github.event_name == 'pull_request'
- name: Upload Ryujinx.Headless.SDL2 artifact
uses: actions/upload-artifact@v3
with:
name: sdl2-ryujinx-headless-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.RELEASE_ZIP_OS_NAME }}
path: publish_sdl2_headless
if: github.event_name == 'pull_request'
- name: Upload Ryujinx.Ava artifact
uses: actions/upload-artifact@v3
with:
name: ava-ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.RELEASE_ZIP_OS_NAME }}
path: publish_ava
if: github.event_name == 'pull_request'
build_macos:
name: MacOS universal (${{ matrix.configuration }})
runs-on: ubuntu-latest
strategy:
matrix:
configuration: [ Debug, Release ]
steps:
- uses: actions/checkout@v3
- uses: actions/setup-dotnet@v3
with:
global-json-file: global.json
- name: Setup LLVM 14
run: |
wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
sudo ./llvm.sh 14
- name: Install rcodesign
run: |
mkdir -p $HOME/.bin
gh release download -R indygreg/apple-platform-rs -O apple-codesign.tar.gz -p 'apple-codesign-*-x86_64-unknown-linux-musl.tar.gz'
tar -xzvf apple-codesign.tar.gz --wildcards '*/rcodesign' --strip-components=1
rm apple-codesign.tar.gz
mv rcodesign $HOME/.bin/
echo "$HOME/.bin" >> $GITHUB_PATH
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Get git short hash
id: git_short_hash
run: echo "result=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
- name: Publish macOS
run: |
./distribution/macos/create_macos_build.sh . publish_tmp publish_ava ./distribution/macos/entitlements.xml "${{ env.RYUJINX_BASE_VERSION }}" "${{ steps.git_short_hash.outputs.result }}" "${{ matrix.configuration }}" "-p:ExtraDefineConstants=DISABLE_UPDATER"
- name: Upload Ryujinx.Ava artifact
uses: actions/upload-artifact@v3
with:
name: ava-ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-macos_universal
path: "publish_ava/*.tar.gz"
if: github.event_name == 'pull_request'

171
.github/workflows/flatpak.yml vendored Normal file
View File

@@ -0,0 +1,171 @@
name: Flatpak release job
on:
workflow_call:
inputs:
ryujinx_version:
required: true
type: string
concurrency: flatpak-release
jobs:
release:
runs-on: ubuntu-latest
env:
NUGET_PACKAGES: ${{ github.workspace }}/.nuget/packages
GIT_COMMITTER_NAME: "RyujinxBot"
GIT_COMMITTER_EMAIL: "61127645+RyujinxBot@users.noreply.github.com"
RYUJINX_PROJECT_FILE: "src/Ryujinx/Ryujinx.csproj"
NUGET_SOURCES_DESTDIR: "nuget-sources"
RYUJINX_VERSION: "${{ inputs.ryujinx_version }}"
steps:
- uses: actions/checkout@v3
with:
path: Ryujinx
- uses: actions/setup-dotnet@v3
with:
global-json-file: Ryujinx/global.json
- name: Get version info
id: version_info
working-directory: Ryujinx
run: |
echo "git_hash=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
- uses: actions/checkout@v3
with:
repository: flathub/org.ryujinx.Ryujinx
token: ${{ secrets.RYUJINX_BOT_PAT }}
submodules: recursive
path: flathub
- name: Install dependencies
run: python -m pip install PyYAML lxml
- name: Restore Nuget packages
run: dotnet restore Ryujinx/${{ env.RYUJINX_PROJECT_FILE }}
- name: Generate nuget_sources.json
shell: python
run: |
from pathlib import Path
import base64
import binascii
import json
import os
sources = []
for path in Path(os.environ['NUGET_PACKAGES']).glob('**/*.nupkg.sha512'):
name = path.parent.parent.name
version = path.parent.name
filename = '{}.{}.nupkg'.format(name, version)
url = 'https://api.nuget.org/v3-flatcontainer/{}/{}/{}'.format(name, version, filename)
with path.open() as fp:
sha512 = binascii.hexlify(base64.b64decode(fp.read())).decode('ascii')
sources.append({
'type': 'file',
'url': url,
'sha512': sha512,
'dest': os.environ['NUGET_SOURCES_DESTDIR'],
'dest-filename': filename,
})
with open('flathub/nuget_sources.json', 'w') as fp:
json.dump(sources, fp, indent=4)
- name: Update flatpak metadata
id: metadata
env:
RYUJINX_GIT_HASH: ${{ steps.version_info.outputs.git_hash }}
shell: python
run: |
import hashlib
import hmac
import json
import os
import yaml
from datetime import datetime
from lxml import etree
# Ensure we don't destroy multiline strings
def str_presenter(dumper, data):
if len(data.splitlines()) > 1:
return dumper.represent_scalar("tag:yaml.org,2002:str", data, style="|")
return dumper.represent_scalar("tag:yaml.org,2002:str", data)
yaml.representer.SafeRepresenter.add_representer(str, str_presenter)
yaml_file = "flathub/org.ryujinx.Ryujinx.yml"
xml_file = "flathub/org.ryujinx.Ryujinx.appdata.xml"
with open(yaml_file, "r") as f:
data = yaml.safe_load(f)
for source in data["modules"][0]["sources"]:
if type(source) is str:
continue
if (
source["type"] == "git"
and source["url"] == "https://github.com/Ryujinx/Ryujinx.git"
):
source["commit"] = os.environ['RYUJINX_GIT_HASH']
is_same_version = data["modules"][0]["build-options"]["env"]["RYUJINX_VERSION"] == os.environ['RYUJINX_VERSION']
with open(os.environ['GITHUB_OUTPUT'], "a") as gh_out:
if is_same_version:
gh_out.write(f"commit_message=Retry update to {os.environ['RYUJINX_VERSION']}")
else:
gh_out.write(f"commit_message=Update to {os.environ['RYUJINX_VERSION']}")
if not is_same_version:
data["modules"][0]["build-options"]["env"]["RYUJINX_VERSION"] = os.environ['RYUJINX_VERSION']
with open(yaml_file, "w") as f:
yaml.safe_dump(data, f, sort_keys=False)
parser = etree.XMLParser(remove_blank_text=True)
tree = etree.parse(xml_file, parser)
root = tree.getroot()
releases = root.find("releases")
element = etree.Element("release")
element.set("version", os.environ['RYUJINX_VERSION'])
element.set("date", datetime.now().date().isoformat())
releases.insert(0, element)
# Ensure 4 spaces
etree.indent(root, space=" ")
with open(xml_file, "wb") as f:
f.write(
etree.tostring(
tree,
pretty_print=True,
encoding="UTF-8",
doctype='<?xml version="1.0" encoding="UTF-8"?>',
)
)
- name: Push flatpak update
working-directory: flathub
env:
COMMIT_MESSAGE: ${{ steps.metadata.outputs.commit_message }}
run: |
git config user.name "${{ env.GIT_COMMITTER_NAME }}"
git config user.email "${{ env.GIT_COMMITTER_EMAIL }}"
git add .
git commit -m "$COMMIT_MESSAGE"
git push origin master

View File

@@ -13,76 +13,115 @@ on:
concurrency: release
env:
POWERSHELL_TELEMETRY_OPTOUT: 1
DOTNET_CLI_TELEMETRY_OPTOUT: 1
RYUJINX_BASE_VERSION: "1.1"
RYUJINX_TARGET_RELEASE_CHANNEL_NAME: "master"
RYUJINX_TARGET_RELEASE_CHANNEL_OWNER: "Ryujinx"
RYUJINX_TARGET_RELEASE_CHANNEL_REPO: "release-channel-master"
jobs:
tag:
name: Create tag
runs-on: ubuntu-latest
steps:
- name: Get version info
id: version_info
run: |
echo "build_version=${{ env.RYUJINX_BASE_VERSION }}.${{ github.run_number }}" >> $GITHUB_OUTPUT
shell: bash
- name: Create tag
uses: actions/github-script@v5
with:
script: |
github.rest.git.createRef({
owner: context.repo.owner,
repo: context.repo.repo,
ref: 'refs/tags/${{ steps.version_info.outputs.build_version }}',
sha: context.sha
})
release:
runs-on: windows-latest
env:
POWERSHELL_TELEMETRY_OPTOUT: 1
DOTNET_CLI_TELEMETRY_OPTOUT: 1
RYUJINX_BASE_VERSION: "1.1"
RYUJINX_TARGET_RELEASE_CHANNEL_NAME: "master"
RYUJINX_TARGET_RELEASE_CHANNEL_OWNER: "Ryujinx"
RYUJINX_TARGET_RELEASE_CHANNEL_REPO: "release-channel-master"
name: Release ${{ matrix.OS_NAME }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ ubuntu-latest, windows-latest ]
include:
- os: ubuntu-latest
OS_NAME: Linux x64
DOTNET_RUNTIME_IDENTIFIER: linux-x64
RELEASE_ZIP_OS_NAME: linux_x64
- os: windows-latest
OS_NAME: Windows x64
DOTNET_RUNTIME_IDENTIFIER: win10-x64
RELEASE_ZIP_OS_NAME: win_x64
steps:
- uses: actions/checkout@v3
- uses: actions/setup-dotnet@v3
with:
dotnet-version: 7.0.x
global-json-file: global.json
- name: Get version info
id: version_info
run: |
echo "build_version=${{ env.RYUJINX_BASE_VERSION }}.${{ github.run_number }}" >> $GITHUB_OUTPUT
echo "git_short_hash=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
shell: bash
- name: Configure for release
run: |
sed -r --in-place 's/\%\%RYUJINX_BUILD_VERSION\%\%/${{ steps.version_info.outputs.build_version }}/g;' Ryujinx.Common/ReleaseInformations.cs
sed -r --in-place 's/\%\%RYUJINX_BUILD_GIT_HASH\%\%/${{ steps.version_info.outputs.git_short_hash }}/g;' Ryujinx.Common/ReleaseInformations.cs
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' Ryujinx.Common/ReleaseInformations.cs
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/g;' Ryujinx.Common/ReleaseInformations.cs
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' Ryujinx.Common/ReleaseInformations.cs
sed -r --in-place 's/\%\%RYUJINX_BUILD_VERSION\%\%/${{ steps.version_info.outputs.build_version }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
sed -r --in-place 's/\%\%RYUJINX_BUILD_GIT_HASH\%\%/${{ steps.version_info.outputs.git_short_hash }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
shell: bash
- name: Create output dir
run: "mkdir release_output"
- name: Publish Windows
- name: Publish
run: |
dotnet publish -c Release -r win10-x64 -o ./publish_windows/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded Ryujinx --self-contained true
dotnet publish -c Release -r win10-x64 -o ./publish_windows_sdl2_headless/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded Ryujinx.Headless.SDL2 --self-contained true
dotnet publish -c Release -r win10-x64 -o ./publish_windows_ava/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded Ryujinx.Ava --self-contained true
dotnet publish -c Release -r "${{ matrix.DOTNET_RUNTIME_IDENTIFIER }}" -o ./publish_gtk/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx --self-contained true
dotnet publish -c Release -r "${{ matrix.DOTNET_RUNTIME_IDENTIFIER }}" -o ./publish_sdl2_headless/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx.Headless.SDL2 --self-contained true
dotnet publish -c Release -r "${{ matrix.DOTNET_RUNTIME_IDENTIFIER }}" -o ./publish_ava/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx.Ava --self-contained true
- name: Packing Windows builds
if: matrix.os == 'windows-latest'
run: |
pushd publish_windows
pushd publish_gtk
7z a ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-win_x64.zip publish
popd
pushd publish_windows_sdl2_headless
pushd publish_sdl2_headless
7z a ../release_output/sdl2-ryujinx-headless-${{ steps.version_info.outputs.build_version }}-win_x64.zip publish
popd
pushd publish_windows_ava
pushd publish_ava
7z a ../release_output/test-ava-ryujinx-${{ steps.version_info.outputs.build_version }}-win_x64.zip publish
popd
shell: bash
- name: Publish Linux
run: |
dotnet publish -c Release -r linux-x64 -o ./publish_linux/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded Ryujinx --self-contained true
dotnet publish -c Release -r linux-x64 -o ./publish_linux_sdl2_headless/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded Ryujinx.Headless.SDL2 --self-contained true
dotnet publish -c Release -r linux-x64 -o ./publish_linux_ava/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded Ryujinx.Ava --self-contained true
- name: Packing Linux builds
if: matrix.os == 'ubuntu-latest'
run: |
pushd publish_linux
pushd publish_gtk
chmod +x publish/Ryujinx.sh publish/Ryujinx
tar -czvf ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz publish
popd
pushd publish_linux_sdl2_headless
pushd publish_sdl2_headless
chmod +x publish/Ryujinx.sh publish/Ryujinx.Headless.SDL2
tar -czvf ../release_output/sdl2-ryujinx-headless-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz publish
popd
pushd publish_linux_ava
pushd publish_ava
chmod +x publish/Ryujinx.sh publish/Ryujinx.Ava
tar -czvf ../release_output/test-ava-ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz publish
popd
shell: bash
@@ -93,10 +132,77 @@ jobs:
name: ${{ steps.version_info.outputs.build_version }}
artifacts: "release_output/*.tar.gz,release_output/*.zip"
tag: ${{ steps.version_info.outputs.build_version }}
body: "For more informations about this release please check out the official [Changelog](https://github.com/Ryujinx/Ryujinx/wiki/Changelog)."
body: "For more information about this release please check out the official [Changelog](https://github.com/Ryujinx/Ryujinx/wiki/Changelog)."
omitBodyDuringUpdate: true
allowUpdates: true
removeArtifacts: true
replacesArtifacts: true
owner: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}
repo: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}
token: ${{ secrets.RELEASE_TOKEN }}
macos_release:
name: Release MacOS universal
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-dotnet@v3
with:
global-json-file: global.json
- name: Setup LLVM 14
run: |
wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
sudo ./llvm.sh 14
- name: Install rcodesign
run: |
mkdir -p $HOME/.bin
gh release download -R indygreg/apple-platform-rs -O apple-codesign.tar.gz -p 'apple-codesign-*-x86_64-unknown-linux-musl.tar.gz'
tar -xzvf apple-codesign.tar.gz --wildcards '*/rcodesign' --strip-components=1
rm apple-codesign.tar.gz
mv rcodesign $HOME/.bin/
echo "$HOME/.bin" >> $GITHUB_PATH
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Get version info
id: version_info
run: |
echo "build_version=${{ env.RYUJINX_BASE_VERSION }}.${{ github.run_number }}" >> $GITHUB_OUTPUT
echo "git_short_hash=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
- name: Configure for release
run: |
sed -r --in-place 's/\%\%RYUJINX_BUILD_VERSION\%\%/${{ steps.version_info.outputs.build_version }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
sed -r --in-place 's/\%\%RYUJINX_BUILD_GIT_HASH\%\%/${{ steps.version_info.outputs.git_short_hash }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
shell: bash
- name: Publish macOS
run: |
./distribution/macos/create_macos_build.sh . publish_tmp publish_ava ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.build_version }}" "${{ steps.version_info.outputs.git_short_hash }}" Release
- name: Pushing new release
uses: ncipollo/release-action@v1
with:
name: ${{ steps.version_info.outputs.build_version }}
artifacts: "publish_ava/*.tar.gz"
tag: ${{ steps.version_info.outputs.build_version }}
body: "For more information about this release please check out the official [Changelog](https://github.com/Ryujinx/Ryujinx/wiki/Changelog)."
omitBodyDuringUpdate: true
allowUpdates: true
replacesArtifacts: true
owner: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}
repo: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}
token: ${{ secrets.RELEASE_TOKEN }}
flatpak_release:
uses: ./.github/workflows/flatpak.yml
needs: release
with:
ryujinx_version: "1.1.${{ github.run_number }}"
secrets: inherit

3
.gitignore vendored
View File

@@ -170,3 +170,6 @@ launchSettings.json
# NetCore Publishing Profiles
PublishProfiles/
# Glade backup files
*.glade~

View File

@@ -1,12 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Ryujinx.Common\Ryujinx.Common.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,56 +0,0 @@
using ARMeilleure.CodeGen.Linking;
using ARMeilleure.CodeGen.Unwinding;
using ARMeilleure.Translation.Cache;
using System;
using System.Runtime.InteropServices;
namespace ARMeilleure.CodeGen
{
/// <summary>
/// Represents a compiled function.
/// </summary>
readonly struct CompiledFunction
{
/// <summary>
/// Gets the machine code of the <see cref="CompiledFunction"/>.
/// </summary>
public byte[] Code { get; }
/// <summary>
/// Gets the <see cref="Unwinding.UnwindInfo"/> of the <see cref="CompiledFunction"/>.
/// </summary>
public UnwindInfo UnwindInfo { get; }
/// <summary>
/// Gets the <see cref="Linking.RelocInfo"/> of the <see cref="CompiledFunction"/>.
/// </summary>
public RelocInfo RelocInfo { get; }
/// <summary>
/// Initializes a new instance of the <see cref="CompiledFunction"/> struct with the specified machine code,
/// unwind info and relocation info.
/// </summary>
/// <param name="code">Machine code</param>
/// <param name="unwindInfo">Unwind info</param>
/// <param name="relocInfo">Relocation info</param>
internal CompiledFunction(byte[] code, UnwindInfo unwindInfo, RelocInfo relocInfo)
{
Code = code;
UnwindInfo = unwindInfo;
RelocInfo = relocInfo;
}
/// <summary>
/// Maps the <see cref="CompiledFunction"/> onto the <see cref="JitCache"/> and returns a delegate of type
/// <typeparamref name="T"/> pointing to the mapped function.
/// </summary>
/// <typeparam name="T">Type of delegate</typeparam>
/// <returns>A delegate of type <typeparamref name="T"/> pointing to the mapped function</returns>
public T Map<T>()
{
IntPtr codePtr = JitCache.Map(this);
return Marshal.GetDelegateForFunctionPointer<T>(codePtr);
}
}
}

View File

@@ -1,305 +0,0 @@
using ARMeilleure.IntermediateRepresentation;
using System;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
namespace ARMeilleure.CodeGen.Optimizations
{
static class ConstantFolding
{
public static void RunPass(Operation operation)
{
if (operation.Destination == default || operation.SourcesCount == 0)
{
return;
}
if (!AreAllSourcesConstant(operation))
{
return;
}
OperandType type = operation.Destination.Type;
switch (operation.Instruction)
{
case Instruction.Add:
if (operation.GetSource(0).Relocatable ||
operation.GetSource(1).Relocatable)
{
break;
}
if (type == OperandType.I32)
{
EvaluateBinaryI32(operation, (x, y) => x + y);
}
else if (type == OperandType.I64)
{
EvaluateBinaryI64(operation, (x, y) => x + y);
}
break;
case Instruction.BitwiseAnd:
if (type == OperandType.I32)
{
EvaluateBinaryI32(operation, (x, y) => x & y);
}
else if (type == OperandType.I64)
{
EvaluateBinaryI64(operation, (x, y) => x & y);
}
break;
case Instruction.BitwiseExclusiveOr:
if (type == OperandType.I32)
{
EvaluateBinaryI32(operation, (x, y) => x ^ y);
}
else if (type == OperandType.I64)
{
EvaluateBinaryI64(operation, (x, y) => x ^ y);
}
break;
case Instruction.BitwiseNot:
if (type == OperandType.I32)
{
EvaluateUnaryI32(operation, (x) => ~x);
}
else if (type == OperandType.I64)
{
EvaluateUnaryI64(operation, (x) => ~x);
}
break;
case Instruction.BitwiseOr:
if (type == OperandType.I32)
{
EvaluateBinaryI32(operation, (x, y) => x | y);
}
else if (type == OperandType.I64)
{
EvaluateBinaryI64(operation, (x, y) => x | y);
}
break;
case Instruction.ConvertI64ToI32:
if (type == OperandType.I32)
{
EvaluateUnaryI32(operation, (x) => x);
}
break;
case Instruction.Copy:
if (type == OperandType.I32)
{
EvaluateUnaryI32(operation, (x) => x);
}
else if (type == OperandType.I64)
{
EvaluateUnaryI64(operation, (x) => x);
}
break;
case Instruction.Divide:
if (type == OperandType.I32)
{
EvaluateBinaryI32(operation, (x, y) => y != 0 ? x / y : 0);
}
else if (type == OperandType.I64)
{
EvaluateBinaryI64(operation, (x, y) => y != 0 ? x / y : 0);
}
break;
case Instruction.DivideUI:
if (type == OperandType.I32)
{
EvaluateBinaryI32(operation, (x, y) => y != 0 ? (int)((uint)x / (uint)y) : 0);
}
else if (type == OperandType.I64)
{
EvaluateBinaryI64(operation, (x, y) => y != 0 ? (long)((ulong)x / (ulong)y) : 0);
}
break;
case Instruction.Multiply:
if (type == OperandType.I32)
{
EvaluateBinaryI32(operation, (x, y) => x * y);
}
else if (type == OperandType.I64)
{
EvaluateBinaryI64(operation, (x, y) => x * y);
}
break;
case Instruction.Negate:
if (type == OperandType.I32)
{
EvaluateUnaryI32(operation, (x) => -x);
}
else if (type == OperandType.I64)
{
EvaluateUnaryI64(operation, (x) => -x);
}
break;
case Instruction.ShiftLeft:
if (type == OperandType.I32)
{
EvaluateBinaryI32(operation, (x, y) => x << y);
}
else if (type == OperandType.I64)
{
EvaluateBinaryI64(operation, (x, y) => x << (int)y);
}
break;
case Instruction.ShiftRightSI:
if (type == OperandType.I32)
{
EvaluateBinaryI32(operation, (x, y) => x >> y);
}
else if (type == OperandType.I64)
{
EvaluateBinaryI64(operation, (x, y) => x >> (int)y);
}
break;
case Instruction.ShiftRightUI:
if (type == OperandType.I32)
{
EvaluateBinaryI32(operation, (x, y) => (int)((uint)x >> y));
}
else if (type == OperandType.I64)
{
EvaluateBinaryI64(operation, (x, y) => (long)((ulong)x >> (int)y));
}
break;
case Instruction.SignExtend16:
if (type == OperandType.I32)
{
EvaluateUnaryI32(operation, (x) => (short)x);
}
else if (type == OperandType.I64)
{
EvaluateUnaryI64(operation, (x) => (short)x);
}
break;
case Instruction.SignExtend32:
if (type == OperandType.I32)
{
EvaluateUnaryI32(operation, (x) => x);
}
else if (type == OperandType.I64)
{
EvaluateUnaryI64(operation, (x) => (int)x);
}
break;
case Instruction.SignExtend8:
if (type == OperandType.I32)
{
EvaluateUnaryI32(operation, (x) => (sbyte)x);
}
else if (type == OperandType.I64)
{
EvaluateUnaryI64(operation, (x) => (sbyte)x);
}
break;
case Instruction.ZeroExtend16:
if (type == OperandType.I32)
{
EvaluateUnaryI32(operation, (x) => (ushort)x);
}
else if (type == OperandType.I64)
{
EvaluateUnaryI64(operation, (x) => (ushort)x);
}
break;
case Instruction.ZeroExtend32:
if (type == OperandType.I32)
{
EvaluateUnaryI32(operation, (x) => x);
}
else if (type == OperandType.I64)
{
EvaluateUnaryI64(operation, (x) => (uint)x);
}
break;
case Instruction.ZeroExtend8:
if (type == OperandType.I32)
{
EvaluateUnaryI32(operation, (x) => (byte)x);
}
else if (type == OperandType.I64)
{
EvaluateUnaryI64(operation, (x) => (byte)x);
}
break;
case Instruction.Subtract:
if (type == OperandType.I32)
{
EvaluateBinaryI32(operation, (x, y) => x - y);
}
else if (type == OperandType.I64)
{
EvaluateBinaryI64(operation, (x, y) => x - y);
}
break;
}
}
private static bool AreAllSourcesConstant(Operation operation)
{
for (int index = 0; index < operation.SourcesCount; index++)
{
Operand srcOp = operation.GetSource(index);
if (srcOp.Kind != OperandKind.Constant)
{
return false;
}
}
return true;
}
private static void EvaluateUnaryI32(Operation operation, Func<int, int> op)
{
int x = operation.GetSource(0).AsInt32();
operation.TurnIntoCopy(Const(op(x)));
}
private static void EvaluateUnaryI64(Operation operation, Func<long, long> op)
{
long x = operation.GetSource(0).AsInt64();
operation.TurnIntoCopy(Const(op(x)));
}
private static void EvaluateBinaryI32(Operation operation, Func<int, int, int> op)
{
int x = operation.GetSource(0).AsInt32();
int y = operation.GetSource(1).AsInt32();
operation.TurnIntoCopy(Const(op(x, y)));
}
private static void EvaluateBinaryI64(Operation operation, Func<long, long, long> op)
{
long x = operation.GetSource(0).AsInt64();
long y = operation.GetSource(1).AsInt64();
operation.TurnIntoCopy(Const(op(x, y)));
}
}
}

View File

@@ -1,266 +0,0 @@
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation;
using System;
using System.Diagnostics;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
namespace ARMeilleure.CodeGen.Optimizations
{
static class Optimizer
{
public static void RunPass(ControlFlowGraph cfg)
{
// Scratch buffer used to store uses.
Span<Operation> buffer = default;
bool modified;
do
{
modified = false;
for (BasicBlock block = cfg.Blocks.Last; block != null; block = block.ListPrevious)
{
Operation node;
Operation prevNode;
for (node = block.Operations.Last; node != default; node = prevNode)
{
prevNode = node.ListPrevious;
if (IsUnused(node))
{
RemoveNode(block, node);
modified = true;
continue;
}
else if (node.Instruction == Instruction.Phi)
{
continue;
}
ConstantFolding.RunPass(node);
Simplification.RunPass(node);
if (DestIsLocalVar(node))
{
if (IsPropagableCompare(node))
{
modified |= PropagateCompare(ref buffer, node);
if (modified && IsUnused(node))
{
RemoveNode(block, node);
}
}
else if (IsPropagableCopy(node))
{
PropagateCopy(ref buffer, node);
RemoveNode(block, node);
modified = true;
}
}
}
}
}
while (modified);
}
public static void RemoveUnusedNodes(ControlFlowGraph cfg)
{
bool modified;
do
{
modified = false;
for (BasicBlock block = cfg.Blocks.Last; block != null; block = block.ListPrevious)
{
Operation node;
Operation prevNode;
for (node = block.Operations.Last; node != default; node = prevNode)
{
prevNode = node.ListPrevious;
if (IsUnused(node))
{
RemoveNode(block, node);
modified = true;
}
}
}
}
while (modified);
}
private static Span<Operation> GetUses(ref Span<Operation> buffer, Operand operand)
{
ReadOnlySpan<Operation> uses = operand.Uses;
if (buffer.Length < uses.Length)
{
buffer = Allocators.Default.AllocateSpan<Operation>((uint)uses.Length);
}
uses.CopyTo(buffer);
return buffer.Slice(0, uses.Length);
}
private static bool PropagateCompare(ref Span<Operation> buffer, Operation compOp)
{
// Try to propagate Compare operations into their BranchIf uses, when these BranchIf uses are in the form
// of:
//
// - BranchIf %x, 0x0, Equal ;; i.e BranchIfFalse %x
// - BranchIf %x, 0x0, NotEqual ;; i.e BranchIfTrue %x
//
// The commutative property of Equal and NotEqual is taken into consideration as well.
//
// For example:
//
// %x = Compare %a, %b, comp
// BranchIf %x, 0x0, NotEqual
//
// =>
//
// BranchIf %a, %b, comp
static bool IsZeroBranch(Operation operation, out Comparison compType)
{
compType = Comparison.Equal;
if (operation.Instruction != Instruction.BranchIf)
{
return false;
}
Operand src1 = operation.GetSource(0);
Operand src2 = operation.GetSource(1);
Operand comp = operation.GetSource(2);
compType = (Comparison)comp.AsInt32();
return (src1.Kind == OperandKind.Constant && src1.Value == 0) ||
(src2.Kind == OperandKind.Constant && src2.Value == 0);
}
bool modified = false;
Operand dest = compOp.Destination;
Operand src1 = compOp.GetSource(0);
Operand src2 = compOp.GetSource(1);
Operand comp = compOp.GetSource(2);
Comparison compType = (Comparison)comp.AsInt32();
Span<Operation> uses = GetUses(ref buffer, dest);
foreach (Operation use in uses)
{
// If operation is a BranchIf and has a constant value 0 in its RHS or LHS source operands.
if (IsZeroBranch(use, out Comparison otherCompType))
{
Comparison propCompType;
if (otherCompType == Comparison.NotEqual)
{
propCompType = compType;
}
else if (otherCompType == Comparison.Equal)
{
propCompType = compType.Invert();
}
else
{
continue;
}
use.SetSource(0, src1);
use.SetSource(1, src2);
use.SetSource(2, Const((int)propCompType));
modified = true;
}
}
return modified;
}
private static void PropagateCopy(ref Span<Operation> buffer, Operation copyOp)
{
// Propagate copy source operand to all uses of the destination operand.
Operand dest = copyOp.Destination;
Operand source = copyOp.GetSource(0);
Span<Operation> uses = GetUses(ref buffer, dest);
foreach (Operation use in uses)
{
for (int index = 0; index < use.SourcesCount; index++)
{
if (use.GetSource(index) == dest)
{
use.SetSource(index, source);
}
}
}
}
private static void RemoveNode(BasicBlock block, Operation node)
{
// Remove a node from the nodes list, and also remove itself
// from all the use lists on the operands that this node uses.
block.Operations.Remove(node);
for (int index = 0; index < node.SourcesCount; index++)
{
node.SetSource(index, default);
}
Debug.Assert(node.Destination == default || node.Destination.UsesCount == 0);
node.Destination = default;
}
private static bool IsUnused(Operation node)
{
return DestIsLocalVar(node) && node.Destination.UsesCount == 0 && !HasSideEffects(node);
}
private static bool DestIsLocalVar(Operation node)
{
return node.Destination != default && node.Destination.Kind == OperandKind.LocalVariable;
}
private static bool HasSideEffects(Operation node)
{
return node.Instruction == Instruction.Call
|| node.Instruction == Instruction.Tailcall
|| node.Instruction == Instruction.CompareAndSwap
|| node.Instruction == Instruction.CompareAndSwap16
|| node.Instruction == Instruction.CompareAndSwap8;
}
private static bool IsPropagableCompare(Operation operation)
{
return operation.Instruction == Instruction.Compare;
}
private static bool IsPropagableCopy(Operation operation)
{
if (operation.Instruction != Instruction.Copy)
{
return false;
}
return operation.Destination.Type == operation.GetSource(0).Type;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,394 +0,0 @@
using ARMeilleure.IntermediateRepresentation;
using System;
using System.Collections.Generic;
using System.Diagnostics;
namespace ARMeilleure.CodeGen.RegisterAllocators
{
unsafe readonly struct LiveInterval : IComparable<LiveInterval>
{
public const int NotFound = -1;
private struct Data
{
public int End;
public int SpillOffset;
public LiveRange FirstRange;
public LiveRange PrevRange;
public LiveRange CurrRange;
public LiveInterval Parent;
public UseList Uses;
public LiveIntervalList Children;
public Operand Local;
public Register Register;
public bool IsFixed;
}
private readonly Data* _data;
private ref int End => ref _data->End;
private ref LiveRange FirstRange => ref _data->FirstRange;
private ref LiveRange CurrRange => ref _data->CurrRange;
private ref LiveRange PrevRange => ref _data->PrevRange;
private ref LiveInterval Parent => ref _data->Parent;
private ref UseList Uses => ref _data->Uses;
private ref LiveIntervalList Children => ref _data->Children;
public Operand Local => _data->Local;
public ref Register Register => ref _data->Register;
public ref int SpillOffset => ref _data->SpillOffset;
public bool IsFixed => _data->IsFixed;
public bool IsEmpty => FirstRange == default;
public bool IsSplit => Children.Count != 0;
public bool IsSpilled => SpillOffset != -1;
public int UsesCount => Uses.Count;
public LiveInterval(Operand local = default, LiveInterval parent = default)
{
_data = Allocators.LiveIntervals.Allocate<Data>();
*_data = default;
_data->IsFixed = false;
_data->Local = local;
Parent = parent == default ? this : parent;
Uses = new UseList();
Children = new LiveIntervalList();
FirstRange = default;
CurrRange = default;
PrevRange = default;
SpillOffset = -1;
}
public LiveInterval(Register register) : this(local: default, parent: default)
{
_data->IsFixed = true;
Register = register;
}
public void Reset()
{
PrevRange = default;
CurrRange = FirstRange;
}
public void Forward(int position)
{
LiveRange prev = PrevRange;
LiveRange curr = CurrRange;
while (curr != default && curr.Start < position && !curr.Overlaps(position))
{
prev = curr;
curr = curr.Next;
}
PrevRange = prev;
CurrRange = curr;
}
public int GetStart()
{
Debug.Assert(!IsEmpty, "Empty LiveInterval cannot have a start position.");
return FirstRange.Start;
}
public void SetStart(int position)
{
if (FirstRange != default)
{
Debug.Assert(position != FirstRange.End);
FirstRange.Start = position;
}
else
{
FirstRange = new LiveRange(position, position + 1);
End = position + 1;
}
}
public int GetEnd()
{
Debug.Assert(!IsEmpty, "Empty LiveInterval cannot have an end position.");
return End;
}
public void AddRange(int start, int end)
{
Debug.Assert(start < end, $"Invalid range start position {start}, {end}");
if (FirstRange != default)
{
// If the new range ends exactly where the first range start, then coalesce together.
if (end == FirstRange.Start)
{
FirstRange.Start = start;
return;
}
// If the new range is already contained, then coalesce together.
else if (FirstRange.Overlaps(start, end))
{
FirstRange.Start = Math.Min(FirstRange.Start, start);
FirstRange.End = Math.Max(FirstRange.End, end);
End = Math.Max(End, end);
Debug.Assert(FirstRange.Next == default || !FirstRange.Overlaps(FirstRange.Next));
return;
}
}
FirstRange = new LiveRange(start, end, FirstRange);
End = Math.Max(End, end);
Debug.Assert(FirstRange.Next == default || !FirstRange.Overlaps(FirstRange.Next));
}
public void AddUsePosition(int position)
{
Uses.Add(position);
}
public bool Overlaps(int position)
{
LiveRange curr = CurrRange;
while (curr != default && curr.Start <= position)
{
if (curr.Overlaps(position))
{
return true;
}
curr = curr.Next;
}
return false;
}
public bool Overlaps(LiveInterval other)
{
return GetOverlapPosition(other) != NotFound;
}
public int GetOverlapPosition(LiveInterval other)
{
LiveRange a = CurrRange;
LiveRange b = other.CurrRange;
while (a != default)
{
while (b != default && b.Start < a.Start)
{
if (a.Overlaps(b))
{
return a.Start;
}
b = b.Next;
}
if (b == default)
{
break;
}
else if (a.Overlaps(b))
{
return a.Start;
}
a = a.Next;
}
return NotFound;
}
public ReadOnlySpan<LiveInterval> SplitChildren()
{
return Parent.Children.Span;
}
public ReadOnlySpan<int> UsePositions()
{
return Uses.Span;
}
public int FirstUse()
{
return Uses.FirstUse;
}
public int NextUseAfter(int position)
{
return Uses.NextUse(position);
}
public LiveInterval Split(int position)
{
LiveInterval result = new(Local, Parent);
result.End = End;
LiveRange prev = PrevRange;
LiveRange curr = CurrRange;
while (curr != default && curr.Start < position && !curr.Overlaps(position))
{
prev = curr;
curr = curr.Next;
}
if (curr.Start >= position)
{
prev.Next = default;
result.FirstRange = curr;
End = prev.End;
}
else
{
result.FirstRange = new LiveRange(position, curr.End, curr.Next);
curr.End = position;
curr.Next = default;
End = curr.End;
}
result.Uses = Uses.Split(position);
AddSplitChild(result);
Debug.Assert(!IsEmpty, "Left interval is empty after split.");
Debug.Assert(!result.IsEmpty, "Right interval is empty after split.");
// Make sure the iterator in the new split is pointing to the start.
result.Reset();
return result;
}
private void AddSplitChild(LiveInterval child)
{
Debug.Assert(!child.IsEmpty, "Trying to insert an empty interval.");
Parent.Children.Add(child);
}
public LiveInterval GetSplitChild(int position)
{
if (Overlaps(position))
{
return this;
}
foreach (LiveInterval splitChild in SplitChildren())
{
if (splitChild.Overlaps(position))
{
return splitChild;
}
else if (splitChild.GetStart() > position)
{
break;
}
}
return default;
}
public bool TrySpillWithSiblingOffset()
{
foreach (LiveInterval splitChild in SplitChildren())
{
if (splitChild.IsSpilled)
{
Spill(splitChild.SpillOffset);
return true;
}
}
return false;
}
public void Spill(int offset)
{
SpillOffset = offset;
}
public int CompareTo(LiveInterval interval)
{
if (FirstRange == default || interval.FirstRange == default)
{
return 0;
}
return GetStart().CompareTo(interval.GetStart());
}
public bool Equals(LiveInterval interval)
{
return interval._data == _data;
}
public override bool Equals(object obj)
{
return obj is LiveInterval interval && Equals(interval);
}
public static bool operator ==(LiveInterval a, LiveInterval b)
{
return a.Equals(b);
}
public static bool operator !=(LiveInterval a, LiveInterval b)
{
return !a.Equals(b);
}
public override int GetHashCode()
{
return HashCode.Combine((IntPtr)_data);
}
public override string ToString()
{
LiveInterval self = this;
IEnumerable<string> GetRanges()
{
LiveRange curr = self.CurrRange;
while (curr != default)
{
if (curr == self.CurrRange)
{
yield return "*" + curr;
}
else
{
yield return curr.ToString();
}
curr = curr.Next;
}
}
return string.Join(", ", GetRanges());
}
}
}

View File

@@ -1,47 +0,0 @@
using ARMeilleure.IntermediateRepresentation;
using System;
namespace ARMeilleure.CodeGen.RegisterAllocators
{
readonly struct RegisterMasks
{
public int IntAvailableRegisters { get; }
public int VecAvailableRegisters { get; }
public int IntCallerSavedRegisters { get; }
public int VecCallerSavedRegisters { get; }
public int IntCalleeSavedRegisters { get; }
public int VecCalleeSavedRegisters { get; }
public RegisterMasks(
int intAvailableRegisters,
int vecAvailableRegisters,
int intCallerSavedRegisters,
int vecCallerSavedRegisters,
int intCalleeSavedRegisters,
int vecCalleeSavedRegisters)
{
IntAvailableRegisters = intAvailableRegisters;
VecAvailableRegisters = vecAvailableRegisters;
IntCallerSavedRegisters = intCallerSavedRegisters;
VecCallerSavedRegisters = vecCallerSavedRegisters;
IntCalleeSavedRegisters = intCalleeSavedRegisters;
VecCalleeSavedRegisters = vecCalleeSavedRegisters;
}
public int GetAvailableRegisters(RegisterType type)
{
if (type == RegisterType.Integer)
{
return IntAvailableRegisters;
}
else if (type == RegisterType.Vector)
{
return VecAvailableRegisters;
}
else
{
throw new ArgumentException($"Invalid register type \"{type}\".");
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,291 +0,0 @@
using System;
namespace ARMeilleure.CodeGen.X86
{
partial class Assembler
{
public static bool SupportsVexPrefix(X86Instruction inst)
{
return _instTable[(int)inst].Flags.HasFlag(InstructionFlags.Vex);
}
private const int BadOp = 0;
[Flags]
private enum InstructionFlags
{
None = 0,
RegOnly = 1 << 0,
Reg8Src = 1 << 1,
Reg8Dest = 1 << 2,
RexW = 1 << 3,
Vex = 1 << 4,
PrefixBit = 16,
PrefixMask = 7 << PrefixBit,
Prefix66 = 1 << PrefixBit,
PrefixF3 = 2 << PrefixBit,
PrefixF2 = 4 << PrefixBit
}
private readonly struct InstructionInfo
{
public int OpRMR { get; }
public int OpRMImm8 { get; }
public int OpRMImm32 { get; }
public int OpRImm64 { get; }
public int OpRRM { get; }
public InstructionFlags Flags { get; }
public InstructionInfo(
int opRMR,
int opRMImm8,
int opRMImm32,
int opRImm64,
int opRRM,
InstructionFlags flags)
{
OpRMR = opRMR;
OpRMImm8 = opRMImm8;
OpRMImm32 = opRMImm32;
OpRImm64 = opRImm64;
OpRRM = opRRM;
Flags = flags;
}
}
private readonly static InstructionInfo[] _instTable;
static Assembler()
{
_instTable = new InstructionInfo[(int)X86Instruction.Count];
// Name RM/R RM/I8 RM/I32 R/I64 R/RM Flags
Add(X86Instruction.Add, new InstructionInfo(0x00000001, 0x00000083, 0x00000081, BadOp, 0x00000003, InstructionFlags.None));
Add(X86Instruction.Addpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f58, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Addps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f58, InstructionFlags.Vex));
Add(X86Instruction.Addsd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f58, InstructionFlags.Vex | InstructionFlags.PrefixF2));
Add(X86Instruction.Addss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f58, InstructionFlags.Vex | InstructionFlags.PrefixF3));
Add(X86Instruction.Aesdec, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38de, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Aesdeclast, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38df, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Aesenc, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38dc, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Aesenclast, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38dd, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Aesimc, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38db, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.And, new InstructionInfo(0x00000021, 0x04000083, 0x04000081, BadOp, 0x00000023, InstructionFlags.None));
Add(X86Instruction.Andnpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f55, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Andnps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f55, InstructionFlags.Vex));
Add(X86Instruction.Andpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f54, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Andps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f54, InstructionFlags.Vex));
Add(X86Instruction.Blendvpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3815, InstructionFlags.Prefix66));
Add(X86Instruction.Blendvps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3814, InstructionFlags.Prefix66));
Add(X86Instruction.Bsr, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fbd, InstructionFlags.None));
Add(X86Instruction.Bswap, new InstructionInfo(0x00000fc8, BadOp, BadOp, BadOp, BadOp, InstructionFlags.RegOnly));
Add(X86Instruction.Call, new InstructionInfo(0x020000ff, BadOp, BadOp, BadOp, BadOp, InstructionFlags.None));
Add(X86Instruction.Cmovcc, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f40, InstructionFlags.None));
Add(X86Instruction.Cmp, new InstructionInfo(0x00000039, 0x07000083, 0x07000081, BadOp, 0x0000003b, InstructionFlags.None));
Add(X86Instruction.Cmppd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc2, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Cmpps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc2, InstructionFlags.Vex));
Add(X86Instruction.Cmpsd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc2, InstructionFlags.Vex | InstructionFlags.PrefixF2));
Add(X86Instruction.Cmpss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc2, InstructionFlags.Vex | InstructionFlags.PrefixF3));
Add(X86Instruction.Cmpxchg, new InstructionInfo(0x00000fb1, BadOp, BadOp, BadOp, BadOp, InstructionFlags.None));
Add(X86Instruction.Cmpxchg16b, new InstructionInfo(0x01000fc7, BadOp, BadOp, BadOp, BadOp, InstructionFlags.RexW));
Add(X86Instruction.Cmpxchg8, new InstructionInfo(0x00000fb0, BadOp, BadOp, BadOp, BadOp, InstructionFlags.Reg8Src));
Add(X86Instruction.Comisd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f2f, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Comiss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f2f, InstructionFlags.Vex));
Add(X86Instruction.Crc32, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38f1, InstructionFlags.PrefixF2));
Add(X86Instruction.Crc32_16, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38f1, InstructionFlags.PrefixF2 | InstructionFlags.Prefix66));
Add(X86Instruction.Crc32_8, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38f0, InstructionFlags.PrefixF2 | InstructionFlags.Reg8Src));
Add(X86Instruction.Cvtdq2pd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fe6, InstructionFlags.Vex | InstructionFlags.PrefixF3));
Add(X86Instruction.Cvtdq2ps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5b, InstructionFlags.Vex));
Add(X86Instruction.Cvtpd2dq, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fe6, InstructionFlags.Vex | InstructionFlags.PrefixF2));
Add(X86Instruction.Cvtpd2ps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5a, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Cvtps2dq, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5b, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Cvtps2pd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5a, InstructionFlags.Vex));
Add(X86Instruction.Cvtsd2si, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f2d, InstructionFlags.Vex | InstructionFlags.PrefixF2));
Add(X86Instruction.Cvtsd2ss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5a, InstructionFlags.Vex | InstructionFlags.PrefixF2));
Add(X86Instruction.Cvtsi2sd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f2a, InstructionFlags.Vex | InstructionFlags.PrefixF2));
Add(X86Instruction.Cvtsi2ss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f2a, InstructionFlags.Vex | InstructionFlags.PrefixF3));
Add(X86Instruction.Cvtss2sd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5a, InstructionFlags.Vex | InstructionFlags.PrefixF3));
Add(X86Instruction.Cvtss2si, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f2d, InstructionFlags.Vex | InstructionFlags.PrefixF3));
Add(X86Instruction.Div, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x060000f7, InstructionFlags.None));
Add(X86Instruction.Divpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5e, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Divps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5e, InstructionFlags.Vex));
Add(X86Instruction.Divsd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5e, InstructionFlags.Vex | InstructionFlags.PrefixF2));
Add(X86Instruction.Divss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5e, InstructionFlags.Vex | InstructionFlags.PrefixF3));
Add(X86Instruction.Gf2p8affineqb, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3ace, InstructionFlags.Prefix66));
Add(X86Instruction.Haddpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f7c, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Haddps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f7c, InstructionFlags.Vex | InstructionFlags.PrefixF2));
Add(X86Instruction.Idiv, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x070000f7, InstructionFlags.None));
Add(X86Instruction.Imul, new InstructionInfo(BadOp, 0x0000006b, 0x00000069, BadOp, 0x00000faf, InstructionFlags.None));
Add(X86Instruction.Imul128, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x050000f7, InstructionFlags.None));
Add(X86Instruction.Insertps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a21, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Jmp, new InstructionInfo(0x040000ff, BadOp, BadOp, BadOp, BadOp, InstructionFlags.None));
Add(X86Instruction.Ldmxcsr, new InstructionInfo(0x02000fae, BadOp, BadOp, BadOp, BadOp, InstructionFlags.Vex));
Add(X86Instruction.Lea, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x0000008d, InstructionFlags.None));
Add(X86Instruction.Maxpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5f, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Maxps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5f, InstructionFlags.Vex));
Add(X86Instruction.Maxsd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5f, InstructionFlags.Vex | InstructionFlags.PrefixF2));
Add(X86Instruction.Maxss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5f, InstructionFlags.Vex | InstructionFlags.PrefixF3));
Add(X86Instruction.Minpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5d, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Minps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5d, InstructionFlags.Vex));
Add(X86Instruction.Minsd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5d, InstructionFlags.Vex | InstructionFlags.PrefixF2));
Add(X86Instruction.Minss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5d, InstructionFlags.Vex | InstructionFlags.PrefixF3));
Add(X86Instruction.Mov, new InstructionInfo(0x00000089, BadOp, 0x000000c7, 0x000000b8, 0x0000008b, InstructionFlags.None));
Add(X86Instruction.Mov16, new InstructionInfo(0x00000089, BadOp, 0x000000c7, BadOp, 0x0000008b, InstructionFlags.Prefix66));
Add(X86Instruction.Mov8, new InstructionInfo(0x00000088, 0x000000c6, BadOp, BadOp, 0x0000008a, InstructionFlags.Reg8Src | InstructionFlags.Reg8Dest));
Add(X86Instruction.Movd, new InstructionInfo(0x00000f7e, BadOp, BadOp, BadOp, 0x00000f6e, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Movdqu, new InstructionInfo(0x00000f7f, BadOp, BadOp, BadOp, 0x00000f6f, InstructionFlags.Vex | InstructionFlags.PrefixF3));
Add(X86Instruction.Movhlps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f12, InstructionFlags.Vex));
Add(X86Instruction.Movlhps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f16, InstructionFlags.Vex));
Add(X86Instruction.Movq, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f7e, InstructionFlags.Vex | InstructionFlags.PrefixF3));
Add(X86Instruction.Movsd, new InstructionInfo(0x00000f11, BadOp, BadOp, BadOp, 0x00000f10, InstructionFlags.Vex | InstructionFlags.PrefixF2));
Add(X86Instruction.Movss, new InstructionInfo(0x00000f11, BadOp, BadOp, BadOp, 0x00000f10, InstructionFlags.Vex | InstructionFlags.PrefixF3));
Add(X86Instruction.Movsx16, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fbf, InstructionFlags.None));
Add(X86Instruction.Movsx32, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000063, InstructionFlags.None));
Add(X86Instruction.Movsx8, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fbe, InstructionFlags.Reg8Src));
Add(X86Instruction.Movzx16, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fb7, InstructionFlags.None));
Add(X86Instruction.Movzx8, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fb6, InstructionFlags.Reg8Src));
Add(X86Instruction.Mul128, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x040000f7, InstructionFlags.None));
Add(X86Instruction.Mulpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f59, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Mulps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f59, InstructionFlags.Vex));
Add(X86Instruction.Mulsd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f59, InstructionFlags.Vex | InstructionFlags.PrefixF2));
Add(X86Instruction.Mulss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f59, InstructionFlags.Vex | InstructionFlags.PrefixF3));
Add(X86Instruction.Neg, new InstructionInfo(0x030000f7, BadOp, BadOp, BadOp, BadOp, InstructionFlags.None));
Add(X86Instruction.Not, new InstructionInfo(0x020000f7, BadOp, BadOp, BadOp, BadOp, InstructionFlags.None));
Add(X86Instruction.Or, new InstructionInfo(0x00000009, 0x01000083, 0x01000081, BadOp, 0x0000000b, InstructionFlags.None));
Add(X86Instruction.Paddb, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ffc, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Paddd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ffe, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Paddq, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fd4, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Paddw, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ffd, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Palignr, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a0f, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Pand, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fdb, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Pandn, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fdf, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Pavgb, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fe0, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Pavgw, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fe3, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Pblendvb, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3810, InstructionFlags.Prefix66));
Add(X86Instruction.Pclmulqdq, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a44, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Pcmpeqb, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f74, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Pcmpeqd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f76, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Pcmpeqq, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3829, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Pcmpeqw, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f75, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Pcmpgtb, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f64, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Pcmpgtd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f66, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Pcmpgtq, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3837, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Pcmpgtw, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f65, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Pextrb, new InstructionInfo(0x000f3a14, BadOp, BadOp, BadOp, BadOp, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Pextrd, new InstructionInfo(0x000f3a16, BadOp, BadOp, BadOp, BadOp, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Pextrq, new InstructionInfo(0x000f3a16, BadOp, BadOp, BadOp, BadOp, InstructionFlags.Vex | InstructionFlags.RexW | InstructionFlags.Prefix66));
Add(X86Instruction.Pextrw, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc5, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Pinsrb, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a20, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Pinsrd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a22, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Pinsrq, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a22, InstructionFlags.Vex | InstructionFlags.RexW | InstructionFlags.Prefix66));
Add(X86Instruction.Pinsrw, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc4, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Pmaxsb, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f383c, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Pmaxsd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f383d, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Pmaxsw, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fee, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Pmaxub, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fde, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Pmaxud, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f383f, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Pmaxuw, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f383e, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Pminsb, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3838, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Pminsd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3839, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Pminsw, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fea, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Pminub, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fda, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Pminud, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f383b, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Pminuw, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f383a, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Pmovsxbw, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3820, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Pmovsxdq, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3825, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Pmovsxwd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3823, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Pmovzxbw, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3830, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Pmovzxdq, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3835, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Pmovzxwd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3833, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Pmulld, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3840, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Pmullw, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fd5, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Pop, new InstructionInfo(0x0000008f, BadOp, BadOp, BadOp, BadOp, InstructionFlags.None));
Add(X86Instruction.Popcnt, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fb8, InstructionFlags.PrefixF3));
Add(X86Instruction.Por, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000feb, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Pshufb, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3800, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Pshufd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f70, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Pslld, new InstructionInfo(BadOp, 0x06000f72, BadOp, BadOp, 0x00000ff2, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Pslldq, new InstructionInfo(BadOp, 0x07000f73, BadOp, BadOp, BadOp, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Psllq, new InstructionInfo(BadOp, 0x06000f73, BadOp, BadOp, 0x00000ff3, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Psllw, new InstructionInfo(BadOp, 0x06000f71, BadOp, BadOp, 0x00000ff1, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Psrad, new InstructionInfo(BadOp, 0x04000f72, BadOp, BadOp, 0x00000fe2, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Psraw, new InstructionInfo(BadOp, 0x04000f71, BadOp, BadOp, 0x00000fe1, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Psrld, new InstructionInfo(BadOp, 0x02000f72, BadOp, BadOp, 0x00000fd2, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Psrlq, new InstructionInfo(BadOp, 0x02000f73, BadOp, BadOp, 0x00000fd3, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Psrldq, new InstructionInfo(BadOp, 0x03000f73, BadOp, BadOp, BadOp, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Psrlw, new InstructionInfo(BadOp, 0x02000f71, BadOp, BadOp, 0x00000fd1, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Psubb, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ff8, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Psubd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ffa, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Psubq, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ffb, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Psubw, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ff9, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Punpckhbw, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f68, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Punpckhdq, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f6a, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Punpckhqdq, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f6d, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Punpckhwd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f69, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Punpcklbw, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f60, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Punpckldq, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f62, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Punpcklqdq, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f6c, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Punpcklwd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f61, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Push, new InstructionInfo(BadOp, 0x0000006a, 0x00000068, BadOp, 0x060000ff, InstructionFlags.None));
Add(X86Instruction.Pxor, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fef, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Rcpps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f53, InstructionFlags.Vex));
Add(X86Instruction.Rcpss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f53, InstructionFlags.Vex | InstructionFlags.PrefixF3));
Add(X86Instruction.Ror, new InstructionInfo(0x010000d3, 0x010000c1, BadOp, BadOp, BadOp, InstructionFlags.None));
Add(X86Instruction.Roundpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a09, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Roundps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a08, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Roundsd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a0b, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Roundss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a0a, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Rsqrtps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f52, InstructionFlags.Vex));
Add(X86Instruction.Rsqrtss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f52, InstructionFlags.Vex | InstructionFlags.PrefixF3));
Add(X86Instruction.Sar, new InstructionInfo(0x070000d3, 0x070000c1, BadOp, BadOp, BadOp, InstructionFlags.None));
Add(X86Instruction.Setcc, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f90, InstructionFlags.Reg8Dest));
Add(X86Instruction.Sha256Msg1, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38cc, InstructionFlags.None));
Add(X86Instruction.Sha256Msg2, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38cd, InstructionFlags.None));
Add(X86Instruction.Sha256Rnds2, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38cb, InstructionFlags.None));
Add(X86Instruction.Shl, new InstructionInfo(0x040000d3, 0x040000c1, BadOp, BadOp, BadOp, InstructionFlags.None));
Add(X86Instruction.Shr, new InstructionInfo(0x050000d3, 0x050000c1, BadOp, BadOp, BadOp, InstructionFlags.None));
Add(X86Instruction.Shufpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc6, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Shufps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc6, InstructionFlags.Vex));
Add(X86Instruction.Sqrtpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f51, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Sqrtps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f51, InstructionFlags.Vex));
Add(X86Instruction.Sqrtsd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f51, InstructionFlags.Vex | InstructionFlags.PrefixF2));
Add(X86Instruction.Sqrtss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f51, InstructionFlags.Vex | InstructionFlags.PrefixF3));
Add(X86Instruction.Stmxcsr, new InstructionInfo(0x03000fae, BadOp, BadOp, BadOp, BadOp, InstructionFlags.Vex));
Add(X86Instruction.Sub, new InstructionInfo(0x00000029, 0x05000083, 0x05000081, BadOp, 0x0000002b, InstructionFlags.None));
Add(X86Instruction.Subpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5c, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Subps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5c, InstructionFlags.Vex));
Add(X86Instruction.Subsd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5c, InstructionFlags.Vex | InstructionFlags.PrefixF2));
Add(X86Instruction.Subss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5c, InstructionFlags.Vex | InstructionFlags.PrefixF3));
Add(X86Instruction.Test, new InstructionInfo(0x00000085, BadOp, 0x000000f7, BadOp, BadOp, InstructionFlags.None));
Add(X86Instruction.Unpckhpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f15, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Unpckhps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f15, InstructionFlags.Vex));
Add(X86Instruction.Unpcklpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f14, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Unpcklps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f14, InstructionFlags.Vex));
Add(X86Instruction.Vblendvpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a4b, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Vblendvps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a4a, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Vcvtph2ps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3813, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Vcvtps2ph, new InstructionInfo(0x000f3a1d, BadOp, BadOp, BadOp, BadOp, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Vfmadd231ps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38b8, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Vfmadd231sd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38b9, InstructionFlags.Vex | InstructionFlags.Prefix66 | InstructionFlags.RexW));
Add(X86Instruction.Vfmadd231ss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38b9, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Vfmsub231sd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38bb, InstructionFlags.Vex | InstructionFlags.Prefix66 | InstructionFlags.RexW));
Add(X86Instruction.Vfmsub231ss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38bb, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Vfnmadd231ps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38bc, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Vfnmadd231sd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38bd, InstructionFlags.Vex | InstructionFlags.Prefix66 | InstructionFlags.RexW));
Add(X86Instruction.Vfnmadd231ss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38bd, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Vfnmsub231sd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38bf, InstructionFlags.Vex | InstructionFlags.Prefix66 | InstructionFlags.RexW));
Add(X86Instruction.Vfnmsub231ss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38bf, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Vpblendvb, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a4c, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Xor, new InstructionInfo(0x00000031, 0x06000083, 0x06000081, BadOp, 0x00000033, InstructionFlags.None));
Add(X86Instruction.Xorpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f57, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Xorps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f57, InstructionFlags.Vex));
static void Add(X86Instruction inst, in InstructionInfo info)
{
_instTable[(int)inst] = info;
}
}
}
}

View File

@@ -1,104 +0,0 @@
using ARMeilleure.CodeGen.RegisterAllocators;
using ARMeilleure.IntermediateRepresentation;
using System.IO;
using System.Numerics;
namespace ARMeilleure.CodeGen.X86
{
class CodeGenContext
{
private readonly Stream _stream;
private readonly Operand[] _blockLabels;
public int StreamOffset => (int)_stream.Length;
public AllocationResult AllocResult { get; }
public Assembler Assembler { get; }
public BasicBlock CurrBlock { get; private set; }
public int CallArgsRegionSize { get; }
public int XmmSaveRegionSize { get; }
public CodeGenContext(AllocationResult allocResult, int maxCallArgs, int blocksCount, bool relocatable)
{
_stream = new MemoryStream();
_blockLabels = new Operand[blocksCount];
AllocResult = allocResult;
Assembler = new Assembler(_stream, relocatable);
CallArgsRegionSize = GetCallArgsRegionSize(allocResult, maxCallArgs, out int xmmSaveRegionSize);
XmmSaveRegionSize = xmmSaveRegionSize;
}
private static int GetCallArgsRegionSize(AllocationResult allocResult, int maxCallArgs, out int xmmSaveRegionSize)
{
// We need to add 8 bytes to the total size, as the call to this function already pushed 8 bytes (the
// return address).
int intMask = CallingConvention.GetIntCalleeSavedRegisters() & allocResult.IntUsedRegisters;
int vecMask = CallingConvention.GetVecCalleeSavedRegisters() & allocResult.VecUsedRegisters;
xmmSaveRegionSize = BitOperations.PopCount((uint)vecMask) * 16;
int calleeSaveRegionSize = BitOperations.PopCount((uint)intMask) * 8 + xmmSaveRegionSize + 8;
int argsCount = maxCallArgs;
if (argsCount < 0)
{
// When the function has no calls, argsCount is -1. In this case, we don't need to allocate the shadow
// space.
argsCount = 0;
}
else if (argsCount < 4)
{
// The ABI mandates that the space for at least 4 arguments is reserved on the stack (this is called
// shadow space).
argsCount = 4;
}
// TODO: Align XMM save region to 16 bytes because unwinding on Windows requires it.
int frameSize = calleeSaveRegionSize + allocResult.SpillRegionSize;
// TODO: Instead of always multiplying by 16 (the largest possible size of a variable, since a V128 has 16
// bytes), we should calculate the exact size consumed by the arguments passed to the called functions on
// the stack.
int callArgsAndFrameSize = frameSize + argsCount * 16;
// Ensure that the Stack Pointer will be aligned to 16 bytes.
callArgsAndFrameSize = (callArgsAndFrameSize + 0xf) & ~0xf;
return callArgsAndFrameSize - frameSize;
}
public void EnterBlock(BasicBlock block)
{
Assembler.MarkLabel(GetLabel(block));
CurrBlock = block;
}
public void JumpTo(BasicBlock target)
{
Assembler.Jmp(GetLabel(target));
}
public void JumpTo(X86Condition condition, BasicBlock target)
{
Assembler.Jcc(condition, GetLabel(target));
}
private Operand GetLabel(BasicBlock block)
{
ref Operand label = ref _blockLabels[block.Index];
if (label == default)
{
label = Operand.Factory.Label();
}
return label;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,89 +0,0 @@
using System;
using System.Runtime.Intrinsics.X86;
namespace ARMeilleure.CodeGen.X86
{
static class HardwareCapabilities
{
static HardwareCapabilities()
{
if (!X86Base.IsSupported)
{
return;
}
(int maxNum, _, _, _) = X86Base.CpuId(0x00000000, 0x00000000);
(_, _, int ecx1, int edx1) = X86Base.CpuId(0x00000001, 0x00000000);
FeatureInfo1Edx = (FeatureFlags1Edx)edx1;
FeatureInfo1Ecx = (FeatureFlags1Ecx)ecx1;
if (maxNum >= 7)
{
(_, int ebx7, int ecx7, _) = X86Base.CpuId(0x00000007, 0x00000000);
FeatureInfo7Ebx = (FeatureFlags7Ebx)ebx7;
FeatureInfo7Ecx = (FeatureFlags7Ecx)ecx7;
}
}
[Flags]
public enum FeatureFlags1Edx
{
Sse = 1 << 25,
Sse2 = 1 << 26
}
[Flags]
public enum FeatureFlags1Ecx
{
Sse3 = 1 << 0,
Pclmulqdq = 1 << 1,
Ssse3 = 1 << 9,
Fma = 1 << 12,
Sse41 = 1 << 19,
Sse42 = 1 << 20,
Popcnt = 1 << 23,
Aes = 1 << 25,
Avx = 1 << 28,
F16c = 1 << 29
}
[Flags]
public enum FeatureFlags7Ebx
{
Avx2 = 1 << 5,
Sha = 1 << 29
}
[Flags]
public enum FeatureFlags7Ecx
{
Gfni = 1 << 8,
}
public static FeatureFlags1Edx FeatureInfo1Edx { get; }
public static FeatureFlags1Ecx FeatureInfo1Ecx { get; }
public static FeatureFlags7Ebx FeatureInfo7Ebx { get; } = 0;
public static FeatureFlags7Ecx FeatureInfo7Ecx { get; } = 0;
public static bool SupportsSse => FeatureInfo1Edx.HasFlag(FeatureFlags1Edx.Sse);
public static bool SupportsSse2 => FeatureInfo1Edx.HasFlag(FeatureFlags1Edx.Sse2);
public static bool SupportsSse3 => FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.Sse3);
public static bool SupportsPclmulqdq => FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.Pclmulqdq);
public static bool SupportsSsse3 => FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.Ssse3);
public static bool SupportsFma => FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.Fma);
public static bool SupportsSse41 => FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.Sse41);
public static bool SupportsSse42 => FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.Sse42);
public static bool SupportsPopcnt => FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.Popcnt);
public static bool SupportsAesni => FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.Aes);
public static bool SupportsAvx => FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.Avx);
public static bool SupportsAvx2 => FeatureInfo7Ebx.HasFlag(FeatureFlags7Ebx.Avx2) && SupportsAvx;
public static bool SupportsF16c => FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.F16c);
public static bool SupportsSha => FeatureInfo7Ebx.HasFlag(FeatureFlags7Ebx.Sha);
public static bool SupportsGfni => FeatureInfo7Ecx.HasFlag(FeatureFlags7Ecx.Gfni);
public static bool ForceLegacySse { get; set; }
public static bool SupportsVexEncoding => SupportsAvx && !ForceLegacySse;
}
}

View File

@@ -1,199 +0,0 @@
using ARMeilleure.Common;
using ARMeilleure.IntermediateRepresentation;
namespace ARMeilleure.CodeGen.X86
{
static class IntrinsicTable
{
private const int BadOp = 0;
private static IntrinsicInfo[] _intrinTable;
static IntrinsicTable()
{
_intrinTable = new IntrinsicInfo[EnumUtils.GetCount(typeof(Intrinsic))];
Add(Intrinsic.X86Addpd, new IntrinsicInfo(X86Instruction.Addpd, IntrinsicType.Binary));
Add(Intrinsic.X86Addps, new IntrinsicInfo(X86Instruction.Addps, IntrinsicType.Binary));
Add(Intrinsic.X86Addsd, new IntrinsicInfo(X86Instruction.Addsd, IntrinsicType.Binary));
Add(Intrinsic.X86Addss, new IntrinsicInfo(X86Instruction.Addss, IntrinsicType.Binary));
Add(Intrinsic.X86Aesdec, new IntrinsicInfo(X86Instruction.Aesdec, IntrinsicType.Binary));
Add(Intrinsic.X86Aesdeclast, new IntrinsicInfo(X86Instruction.Aesdeclast, IntrinsicType.Binary));
Add(Intrinsic.X86Aesenc, new IntrinsicInfo(X86Instruction.Aesenc, IntrinsicType.Binary));
Add(Intrinsic.X86Aesenclast, new IntrinsicInfo(X86Instruction.Aesenclast, IntrinsicType.Binary));
Add(Intrinsic.X86Aesimc, new IntrinsicInfo(X86Instruction.Aesimc, IntrinsicType.Unary));
Add(Intrinsic.X86Andnpd, new IntrinsicInfo(X86Instruction.Andnpd, IntrinsicType.Binary));
Add(Intrinsic.X86Andnps, new IntrinsicInfo(X86Instruction.Andnps, IntrinsicType.Binary));
Add(Intrinsic.X86Andpd, new IntrinsicInfo(X86Instruction.Andpd, IntrinsicType.Binary));
Add(Intrinsic.X86Andps, new IntrinsicInfo(X86Instruction.Andps, IntrinsicType.Binary));
Add(Intrinsic.X86Blendvpd, new IntrinsicInfo(X86Instruction.Blendvpd, IntrinsicType.Ternary));
Add(Intrinsic.X86Blendvps, new IntrinsicInfo(X86Instruction.Blendvps, IntrinsicType.Ternary));
Add(Intrinsic.X86Cmppd, new IntrinsicInfo(X86Instruction.Cmppd, IntrinsicType.TernaryImm));
Add(Intrinsic.X86Cmpps, new IntrinsicInfo(X86Instruction.Cmpps, IntrinsicType.TernaryImm));
Add(Intrinsic.X86Cmpsd, new IntrinsicInfo(X86Instruction.Cmpsd, IntrinsicType.TernaryImm));
Add(Intrinsic.X86Cmpss, new IntrinsicInfo(X86Instruction.Cmpss, IntrinsicType.TernaryImm));
Add(Intrinsic.X86Comisdeq, new IntrinsicInfo(X86Instruction.Comisd, IntrinsicType.Comis_));
Add(Intrinsic.X86Comisdge, new IntrinsicInfo(X86Instruction.Comisd, IntrinsicType.Comis_));
Add(Intrinsic.X86Comisdlt, new IntrinsicInfo(X86Instruction.Comisd, IntrinsicType.Comis_));
Add(Intrinsic.X86Comisseq, new IntrinsicInfo(X86Instruction.Comiss, IntrinsicType.Comis_));
Add(Intrinsic.X86Comissge, new IntrinsicInfo(X86Instruction.Comiss, IntrinsicType.Comis_));
Add(Intrinsic.X86Comisslt, new IntrinsicInfo(X86Instruction.Comiss, IntrinsicType.Comis_));
Add(Intrinsic.X86Crc32, new IntrinsicInfo(X86Instruction.Crc32, IntrinsicType.Crc32));
Add(Intrinsic.X86Crc32_16, new IntrinsicInfo(X86Instruction.Crc32_16, IntrinsicType.Crc32));
Add(Intrinsic.X86Crc32_8, new IntrinsicInfo(X86Instruction.Crc32_8, IntrinsicType.Crc32));
Add(Intrinsic.X86Cvtdq2pd, new IntrinsicInfo(X86Instruction.Cvtdq2pd, IntrinsicType.Unary));
Add(Intrinsic.X86Cvtdq2ps, new IntrinsicInfo(X86Instruction.Cvtdq2ps, IntrinsicType.Unary));
Add(Intrinsic.X86Cvtpd2dq, new IntrinsicInfo(X86Instruction.Cvtpd2dq, IntrinsicType.Unary));
Add(Intrinsic.X86Cvtpd2ps, new IntrinsicInfo(X86Instruction.Cvtpd2ps, IntrinsicType.Unary));
Add(Intrinsic.X86Cvtps2dq, new IntrinsicInfo(X86Instruction.Cvtps2dq, IntrinsicType.Unary));
Add(Intrinsic.X86Cvtps2pd, new IntrinsicInfo(X86Instruction.Cvtps2pd, IntrinsicType.Unary));
Add(Intrinsic.X86Cvtsd2si, new IntrinsicInfo(X86Instruction.Cvtsd2si, IntrinsicType.UnaryToGpr));
Add(Intrinsic.X86Cvtsd2ss, new IntrinsicInfo(X86Instruction.Cvtsd2ss, IntrinsicType.Binary));
Add(Intrinsic.X86Cvtsi2sd, new IntrinsicInfo(X86Instruction.Cvtsi2sd, IntrinsicType.BinaryGpr));
Add(Intrinsic.X86Cvtsi2si, new IntrinsicInfo(X86Instruction.Movd, IntrinsicType.UnaryToGpr));
Add(Intrinsic.X86Cvtsi2ss, new IntrinsicInfo(X86Instruction.Cvtsi2ss, IntrinsicType.BinaryGpr));
Add(Intrinsic.X86Cvtss2sd, new IntrinsicInfo(X86Instruction.Cvtss2sd, IntrinsicType.Binary));
Add(Intrinsic.X86Cvtss2si, new IntrinsicInfo(X86Instruction.Cvtss2si, IntrinsicType.UnaryToGpr));
Add(Intrinsic.X86Divpd, new IntrinsicInfo(X86Instruction.Divpd, IntrinsicType.Binary));
Add(Intrinsic.X86Divps, new IntrinsicInfo(X86Instruction.Divps, IntrinsicType.Binary));
Add(Intrinsic.X86Divsd, new IntrinsicInfo(X86Instruction.Divsd, IntrinsicType.Binary));
Add(Intrinsic.X86Divss, new IntrinsicInfo(X86Instruction.Divss, IntrinsicType.Binary));
Add(Intrinsic.X86Gf2p8affineqb, new IntrinsicInfo(X86Instruction.Gf2p8affineqb, IntrinsicType.TernaryImm));
Add(Intrinsic.X86Haddpd, new IntrinsicInfo(X86Instruction.Haddpd, IntrinsicType.Binary));
Add(Intrinsic.X86Haddps, new IntrinsicInfo(X86Instruction.Haddps, IntrinsicType.Binary));
Add(Intrinsic.X86Insertps, new IntrinsicInfo(X86Instruction.Insertps, IntrinsicType.TernaryImm));
Add(Intrinsic.X86Maxpd, new IntrinsicInfo(X86Instruction.Maxpd, IntrinsicType.Binary));
Add(Intrinsic.X86Maxps, new IntrinsicInfo(X86Instruction.Maxps, IntrinsicType.Binary));
Add(Intrinsic.X86Maxsd, new IntrinsicInfo(X86Instruction.Maxsd, IntrinsicType.Binary));
Add(Intrinsic.X86Maxss, new IntrinsicInfo(X86Instruction.Maxss, IntrinsicType.Binary));
Add(Intrinsic.X86Minpd, new IntrinsicInfo(X86Instruction.Minpd, IntrinsicType.Binary));
Add(Intrinsic.X86Minps, new IntrinsicInfo(X86Instruction.Minps, IntrinsicType.Binary));
Add(Intrinsic.X86Minsd, new IntrinsicInfo(X86Instruction.Minsd, IntrinsicType.Binary));
Add(Intrinsic.X86Minss, new IntrinsicInfo(X86Instruction.Minss, IntrinsicType.Binary));
Add(Intrinsic.X86Movhlps, new IntrinsicInfo(X86Instruction.Movhlps, IntrinsicType.Binary));
Add(Intrinsic.X86Movlhps, new IntrinsicInfo(X86Instruction.Movlhps, IntrinsicType.Binary));
Add(Intrinsic.X86Movss, new IntrinsicInfo(X86Instruction.Movss, IntrinsicType.Binary));
Add(Intrinsic.X86Mulpd, new IntrinsicInfo(X86Instruction.Mulpd, IntrinsicType.Binary));
Add(Intrinsic.X86Mulps, new IntrinsicInfo(X86Instruction.Mulps, IntrinsicType.Binary));
Add(Intrinsic.X86Mulsd, new IntrinsicInfo(X86Instruction.Mulsd, IntrinsicType.Binary));
Add(Intrinsic.X86Mulss, new IntrinsicInfo(X86Instruction.Mulss, IntrinsicType.Binary));
Add(Intrinsic.X86Mxcsrmb, new IntrinsicInfo(X86Instruction.None, IntrinsicType.Mxcsr)); // Mask bits.
Add(Intrinsic.X86Mxcsrub, new IntrinsicInfo(X86Instruction.None, IntrinsicType.Mxcsr)); // Unmask bits.
Add(Intrinsic.X86Paddb, new IntrinsicInfo(X86Instruction.Paddb, IntrinsicType.Binary));
Add(Intrinsic.X86Paddd, new IntrinsicInfo(X86Instruction.Paddd, IntrinsicType.Binary));
Add(Intrinsic.X86Paddq, new IntrinsicInfo(X86Instruction.Paddq, IntrinsicType.Binary));
Add(Intrinsic.X86Paddw, new IntrinsicInfo(X86Instruction.Paddw, IntrinsicType.Binary));
Add(Intrinsic.X86Palignr, new IntrinsicInfo(X86Instruction.Palignr, IntrinsicType.TernaryImm));
Add(Intrinsic.X86Pand, new IntrinsicInfo(X86Instruction.Pand, IntrinsicType.Binary));
Add(Intrinsic.X86Pandn, new IntrinsicInfo(X86Instruction.Pandn, IntrinsicType.Binary));
Add(Intrinsic.X86Pavgb, new IntrinsicInfo(X86Instruction.Pavgb, IntrinsicType.Binary));
Add(Intrinsic.X86Pavgw, new IntrinsicInfo(X86Instruction.Pavgw, IntrinsicType.Binary));
Add(Intrinsic.X86Pblendvb, new IntrinsicInfo(X86Instruction.Pblendvb, IntrinsicType.Ternary));
Add(Intrinsic.X86Pclmulqdq, new IntrinsicInfo(X86Instruction.Pclmulqdq, IntrinsicType.TernaryImm));
Add(Intrinsic.X86Pcmpeqb, new IntrinsicInfo(X86Instruction.Pcmpeqb, IntrinsicType.Binary));
Add(Intrinsic.X86Pcmpeqd, new IntrinsicInfo(X86Instruction.Pcmpeqd, IntrinsicType.Binary));
Add(Intrinsic.X86Pcmpeqq, new IntrinsicInfo(X86Instruction.Pcmpeqq, IntrinsicType.Binary));
Add(Intrinsic.X86Pcmpeqw, new IntrinsicInfo(X86Instruction.Pcmpeqw, IntrinsicType.Binary));
Add(Intrinsic.X86Pcmpgtb, new IntrinsicInfo(X86Instruction.Pcmpgtb, IntrinsicType.Binary));
Add(Intrinsic.X86Pcmpgtd, new IntrinsicInfo(X86Instruction.Pcmpgtd, IntrinsicType.Binary));
Add(Intrinsic.X86Pcmpgtq, new IntrinsicInfo(X86Instruction.Pcmpgtq, IntrinsicType.Binary));
Add(Intrinsic.X86Pcmpgtw, new IntrinsicInfo(X86Instruction.Pcmpgtw, IntrinsicType.Binary));
Add(Intrinsic.X86Pmaxsb, new IntrinsicInfo(X86Instruction.Pmaxsb, IntrinsicType.Binary));
Add(Intrinsic.X86Pmaxsd, new IntrinsicInfo(X86Instruction.Pmaxsd, IntrinsicType.Binary));
Add(Intrinsic.X86Pmaxsw, new IntrinsicInfo(X86Instruction.Pmaxsw, IntrinsicType.Binary));
Add(Intrinsic.X86Pmaxub, new IntrinsicInfo(X86Instruction.Pmaxub, IntrinsicType.Binary));
Add(Intrinsic.X86Pmaxud, new IntrinsicInfo(X86Instruction.Pmaxud, IntrinsicType.Binary));
Add(Intrinsic.X86Pmaxuw, new IntrinsicInfo(X86Instruction.Pmaxuw, IntrinsicType.Binary));
Add(Intrinsic.X86Pminsb, new IntrinsicInfo(X86Instruction.Pminsb, IntrinsicType.Binary));
Add(Intrinsic.X86Pminsd, new IntrinsicInfo(X86Instruction.Pminsd, IntrinsicType.Binary));
Add(Intrinsic.X86Pminsw, new IntrinsicInfo(X86Instruction.Pminsw, IntrinsicType.Binary));
Add(Intrinsic.X86Pminub, new IntrinsicInfo(X86Instruction.Pminub, IntrinsicType.Binary));
Add(Intrinsic.X86Pminud, new IntrinsicInfo(X86Instruction.Pminud, IntrinsicType.Binary));
Add(Intrinsic.X86Pminuw, new IntrinsicInfo(X86Instruction.Pminuw, IntrinsicType.Binary));
Add(Intrinsic.X86Pmovsxbw, new IntrinsicInfo(X86Instruction.Pmovsxbw, IntrinsicType.Unary));
Add(Intrinsic.X86Pmovsxdq, new IntrinsicInfo(X86Instruction.Pmovsxdq, IntrinsicType.Unary));
Add(Intrinsic.X86Pmovsxwd, new IntrinsicInfo(X86Instruction.Pmovsxwd, IntrinsicType.Unary));
Add(Intrinsic.X86Pmovzxbw, new IntrinsicInfo(X86Instruction.Pmovzxbw, IntrinsicType.Unary));
Add(Intrinsic.X86Pmovzxdq, new IntrinsicInfo(X86Instruction.Pmovzxdq, IntrinsicType.Unary));
Add(Intrinsic.X86Pmovzxwd, new IntrinsicInfo(X86Instruction.Pmovzxwd, IntrinsicType.Unary));
Add(Intrinsic.X86Pmulld, new IntrinsicInfo(X86Instruction.Pmulld, IntrinsicType.Binary));
Add(Intrinsic.X86Pmullw, new IntrinsicInfo(X86Instruction.Pmullw, IntrinsicType.Binary));
Add(Intrinsic.X86Popcnt, new IntrinsicInfo(X86Instruction.Popcnt, IntrinsicType.PopCount));
Add(Intrinsic.X86Por, new IntrinsicInfo(X86Instruction.Por, IntrinsicType.Binary));
Add(Intrinsic.X86Pshufb, new IntrinsicInfo(X86Instruction.Pshufb, IntrinsicType.Binary));
Add(Intrinsic.X86Pshufd, new IntrinsicInfo(X86Instruction.Pshufd, IntrinsicType.BinaryImm));
Add(Intrinsic.X86Pslld, new IntrinsicInfo(X86Instruction.Pslld, IntrinsicType.Binary));
Add(Intrinsic.X86Pslldq, new IntrinsicInfo(X86Instruction.Pslldq, IntrinsicType.Binary));
Add(Intrinsic.X86Psllq, new IntrinsicInfo(X86Instruction.Psllq, IntrinsicType.Binary));
Add(Intrinsic.X86Psllw, new IntrinsicInfo(X86Instruction.Psllw, IntrinsicType.Binary));
Add(Intrinsic.X86Psrad, new IntrinsicInfo(X86Instruction.Psrad, IntrinsicType.Binary));
Add(Intrinsic.X86Psraw, new IntrinsicInfo(X86Instruction.Psraw, IntrinsicType.Binary));
Add(Intrinsic.X86Psrld, new IntrinsicInfo(X86Instruction.Psrld, IntrinsicType.Binary));
Add(Intrinsic.X86Psrlq, new IntrinsicInfo(X86Instruction.Psrlq, IntrinsicType.Binary));
Add(Intrinsic.X86Psrldq, new IntrinsicInfo(X86Instruction.Psrldq, IntrinsicType.Binary));
Add(Intrinsic.X86Psrlw, new IntrinsicInfo(X86Instruction.Psrlw, IntrinsicType.Binary));
Add(Intrinsic.X86Psubb, new IntrinsicInfo(X86Instruction.Psubb, IntrinsicType.Binary));
Add(Intrinsic.X86Psubd, new IntrinsicInfo(X86Instruction.Psubd, IntrinsicType.Binary));
Add(Intrinsic.X86Psubq, new IntrinsicInfo(X86Instruction.Psubq, IntrinsicType.Binary));
Add(Intrinsic.X86Psubw, new IntrinsicInfo(X86Instruction.Psubw, IntrinsicType.Binary));
Add(Intrinsic.X86Punpckhbw, new IntrinsicInfo(X86Instruction.Punpckhbw, IntrinsicType.Binary));
Add(Intrinsic.X86Punpckhdq, new IntrinsicInfo(X86Instruction.Punpckhdq, IntrinsicType.Binary));
Add(Intrinsic.X86Punpckhqdq, new IntrinsicInfo(X86Instruction.Punpckhqdq, IntrinsicType.Binary));
Add(Intrinsic.X86Punpckhwd, new IntrinsicInfo(X86Instruction.Punpckhwd, IntrinsicType.Binary));
Add(Intrinsic.X86Punpcklbw, new IntrinsicInfo(X86Instruction.Punpcklbw, IntrinsicType.Binary));
Add(Intrinsic.X86Punpckldq, new IntrinsicInfo(X86Instruction.Punpckldq, IntrinsicType.Binary));
Add(Intrinsic.X86Punpcklqdq, new IntrinsicInfo(X86Instruction.Punpcklqdq, IntrinsicType.Binary));
Add(Intrinsic.X86Punpcklwd, new IntrinsicInfo(X86Instruction.Punpcklwd, IntrinsicType.Binary));
Add(Intrinsic.X86Pxor, new IntrinsicInfo(X86Instruction.Pxor, IntrinsicType.Binary));
Add(Intrinsic.X86Rcpps, new IntrinsicInfo(X86Instruction.Rcpps, IntrinsicType.Unary));
Add(Intrinsic.X86Rcpss, new IntrinsicInfo(X86Instruction.Rcpss, IntrinsicType.Unary));
Add(Intrinsic.X86Roundpd, new IntrinsicInfo(X86Instruction.Roundpd, IntrinsicType.BinaryImm));
Add(Intrinsic.X86Roundps, new IntrinsicInfo(X86Instruction.Roundps, IntrinsicType.BinaryImm));
Add(Intrinsic.X86Roundsd, new IntrinsicInfo(X86Instruction.Roundsd, IntrinsicType.BinaryImm));
Add(Intrinsic.X86Roundss, new IntrinsicInfo(X86Instruction.Roundss, IntrinsicType.BinaryImm));
Add(Intrinsic.X86Rsqrtps, new IntrinsicInfo(X86Instruction.Rsqrtps, IntrinsicType.Unary));
Add(Intrinsic.X86Rsqrtss, new IntrinsicInfo(X86Instruction.Rsqrtss, IntrinsicType.Unary));
Add(Intrinsic.X86Sha256Msg1, new IntrinsicInfo(X86Instruction.Sha256Msg1, IntrinsicType.Binary));
Add(Intrinsic.X86Sha256Msg2, new IntrinsicInfo(X86Instruction.Sha256Msg2, IntrinsicType.Binary));
Add(Intrinsic.X86Sha256Rnds2, new IntrinsicInfo(X86Instruction.Sha256Rnds2, IntrinsicType.Ternary));
Add(Intrinsic.X86Shufpd, new IntrinsicInfo(X86Instruction.Shufpd, IntrinsicType.TernaryImm));
Add(Intrinsic.X86Shufps, new IntrinsicInfo(X86Instruction.Shufps, IntrinsicType.TernaryImm));
Add(Intrinsic.X86Sqrtpd, new IntrinsicInfo(X86Instruction.Sqrtpd, IntrinsicType.Unary));
Add(Intrinsic.X86Sqrtps, new IntrinsicInfo(X86Instruction.Sqrtps, IntrinsicType.Unary));
Add(Intrinsic.X86Sqrtsd, new IntrinsicInfo(X86Instruction.Sqrtsd, IntrinsicType.Unary));
Add(Intrinsic.X86Sqrtss, new IntrinsicInfo(X86Instruction.Sqrtss, IntrinsicType.Unary));
Add(Intrinsic.X86Subpd, new IntrinsicInfo(X86Instruction.Subpd, IntrinsicType.Binary));
Add(Intrinsic.X86Subps, new IntrinsicInfo(X86Instruction.Subps, IntrinsicType.Binary));
Add(Intrinsic.X86Subsd, new IntrinsicInfo(X86Instruction.Subsd, IntrinsicType.Binary));
Add(Intrinsic.X86Subss, new IntrinsicInfo(X86Instruction.Subss, IntrinsicType.Binary));
Add(Intrinsic.X86Unpckhpd, new IntrinsicInfo(X86Instruction.Unpckhpd, IntrinsicType.Binary));
Add(Intrinsic.X86Unpckhps, new IntrinsicInfo(X86Instruction.Unpckhps, IntrinsicType.Binary));
Add(Intrinsic.X86Unpcklpd, new IntrinsicInfo(X86Instruction.Unpcklpd, IntrinsicType.Binary));
Add(Intrinsic.X86Unpcklps, new IntrinsicInfo(X86Instruction.Unpcklps, IntrinsicType.Binary));
Add(Intrinsic.X86Vcvtph2ps, new IntrinsicInfo(X86Instruction.Vcvtph2ps, IntrinsicType.Unary));
Add(Intrinsic.X86Vcvtps2ph, new IntrinsicInfo(X86Instruction.Vcvtps2ph, IntrinsicType.BinaryImm));
Add(Intrinsic.X86Vfmadd231ps, new IntrinsicInfo(X86Instruction.Vfmadd231ps, IntrinsicType.Fma));
Add(Intrinsic.X86Vfmadd231sd, new IntrinsicInfo(X86Instruction.Vfmadd231sd, IntrinsicType.Fma));
Add(Intrinsic.X86Vfmadd231ss, new IntrinsicInfo(X86Instruction.Vfmadd231ss, IntrinsicType.Fma));
Add(Intrinsic.X86Vfmsub231sd, new IntrinsicInfo(X86Instruction.Vfmsub231sd, IntrinsicType.Fma));
Add(Intrinsic.X86Vfmsub231ss, new IntrinsicInfo(X86Instruction.Vfmsub231ss, IntrinsicType.Fma));
Add(Intrinsic.X86Vfnmadd231ps, new IntrinsicInfo(X86Instruction.Vfnmadd231ps, IntrinsicType.Fma));
Add(Intrinsic.X86Vfnmadd231sd, new IntrinsicInfo(X86Instruction.Vfnmadd231sd, IntrinsicType.Fma));
Add(Intrinsic.X86Vfnmadd231ss, new IntrinsicInfo(X86Instruction.Vfnmadd231ss, IntrinsicType.Fma));
Add(Intrinsic.X86Vfnmsub231sd, new IntrinsicInfo(X86Instruction.Vfnmsub231sd, IntrinsicType.Fma));
Add(Intrinsic.X86Vfnmsub231ss, new IntrinsicInfo(X86Instruction.Vfnmsub231ss, IntrinsicType.Fma));
Add(Intrinsic.X86Xorpd, new IntrinsicInfo(X86Instruction.Xorpd, IntrinsicType.Binary));
Add(Intrinsic.X86Xorps, new IntrinsicInfo(X86Instruction.Xorps, IntrinsicType.Binary));
}
private static void Add(Intrinsic intrin, IntrinsicInfo info)
{
_intrinTable[(int)intrin] = info;
}
public static IntrinsicInfo GetInfo(Intrinsic intrin)
{
return _intrinTable[(int)intrin];
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,228 +0,0 @@
namespace ARMeilleure.CodeGen.X86
{
enum X86Instruction
{
None,
Add,
Addpd,
Addps,
Addsd,
Addss,
Aesdec,
Aesdeclast,
Aesenc,
Aesenclast,
Aesimc,
And,
Andnpd,
Andnps,
Andpd,
Andps,
Blendvpd,
Blendvps,
Bsr,
Bswap,
Call,
Cmovcc,
Cmp,
Cmppd,
Cmpps,
Cmpsd,
Cmpss,
Cmpxchg,
Cmpxchg16b,
Cmpxchg8,
Comisd,
Comiss,
Crc32,
Crc32_16,
Crc32_8,
Cvtdq2pd,
Cvtdq2ps,
Cvtpd2dq,
Cvtpd2ps,
Cvtps2dq,
Cvtps2pd,
Cvtsd2si,
Cvtsd2ss,
Cvtsi2sd,
Cvtsi2ss,
Cvtss2sd,
Cvtss2si,
Div,
Divpd,
Divps,
Divsd,
Divss,
Gf2p8affineqb,
Haddpd,
Haddps,
Idiv,
Imul,
Imul128,
Insertps,
Jmp,
Ldmxcsr,
Lea,
Maxpd,
Maxps,
Maxsd,
Maxss,
Minpd,
Minps,
Minsd,
Minss,
Mov,
Mov16,
Mov8,
Movd,
Movdqu,
Movhlps,
Movlhps,
Movq,
Movsd,
Movss,
Movsx16,
Movsx32,
Movsx8,
Movzx16,
Movzx8,
Mul128,
Mulpd,
Mulps,
Mulsd,
Mulss,
Neg,
Not,
Or,
Paddb,
Paddd,
Paddq,
Paddw,
Palignr,
Pand,
Pandn,
Pavgb,
Pavgw,
Pblendvb,
Pclmulqdq,
Pcmpeqb,
Pcmpeqd,
Pcmpeqq,
Pcmpeqw,
Pcmpgtb,
Pcmpgtd,
Pcmpgtq,
Pcmpgtw,
Pextrb,
Pextrd,
Pextrq,
Pextrw,
Pinsrb,
Pinsrd,
Pinsrq,
Pinsrw,
Pmaxsb,
Pmaxsd,
Pmaxsw,
Pmaxub,
Pmaxud,
Pmaxuw,
Pminsb,
Pminsd,
Pminsw,
Pminub,
Pminud,
Pminuw,
Pmovsxbw,
Pmovsxdq,
Pmovsxwd,
Pmovzxbw,
Pmovzxdq,
Pmovzxwd,
Pmulld,
Pmullw,
Pop,
Popcnt,
Por,
Pshufb,
Pshufd,
Pslld,
Pslldq,
Psllq,
Psllw,
Psrad,
Psraw,
Psrld,
Psrlq,
Psrldq,
Psrlw,
Psubb,
Psubd,
Psubq,
Psubw,
Punpckhbw,
Punpckhdq,
Punpckhqdq,
Punpckhwd,
Punpcklbw,
Punpckldq,
Punpcklqdq,
Punpcklwd,
Push,
Pxor,
Rcpps,
Rcpss,
Ror,
Roundpd,
Roundps,
Roundsd,
Roundss,
Rsqrtps,
Rsqrtss,
Sar,
Setcc,
Sha256Msg1,
Sha256Msg2,
Sha256Rnds2,
Shl,
Shr,
Shufpd,
Shufps,
Sqrtpd,
Sqrtps,
Sqrtsd,
Sqrtss,
Stmxcsr,
Sub,
Subpd,
Subps,
Subsd,
Subss,
Test,
Unpckhpd,
Unpckhps,
Unpcklpd,
Unpcklps,
Vblendvpd,
Vblendvps,
Vcvtph2ps,
Vcvtps2ph,
Vfmadd231ps,
Vfmadd231sd,
Vfmadd231ss,
Vfmsub231sd,
Vfmsub231ss,
Vfnmadd231ps,
Vfnmadd231sd,
Vfnmadd231ss,
Vfnmsub231sd,
Vfnmsub231ss,
Vpblendvb,
Xor,
Xorpd,
Xorps,
Count
}
}

View File

@@ -1,167 +0,0 @@
using ARMeilleure.Common;
namespace ARMeilleure.Decoders
{
static class DecoderHelper
{
static DecoderHelper()
{
Imm8ToFP32Table = BuildImm8ToFP32Table();
Imm8ToFP64Table = BuildImm8ToFP64Table();
}
public static readonly uint[] Imm8ToFP32Table;
public static readonly ulong[] Imm8ToFP64Table;
private static uint[] BuildImm8ToFP32Table()
{
uint[] tbl = new uint[256];
for (int idx = 0; idx < 256; idx++)
{
tbl[idx] = ExpandImm8ToFP32((uint)idx);
}
return tbl;
}
private static ulong[] BuildImm8ToFP64Table()
{
ulong[] tbl = new ulong[256];
for (int idx = 0; idx < 256; idx++)
{
tbl[idx] = ExpandImm8ToFP64((ulong)idx);
}
return tbl;
}
// abcdefgh -> aBbbbbbc defgh000 00000000 00000000 (B = ~b)
private static uint ExpandImm8ToFP32(uint imm)
{
uint MoveBit(uint bits, int from, int to)
{
return ((bits >> from) & 1U) << to;
}
return MoveBit(imm, 7, 31) | MoveBit(~imm, 6, 30) |
MoveBit(imm, 6, 29) | MoveBit( imm, 6, 28) |
MoveBit(imm, 6, 27) | MoveBit( imm, 6, 26) |
MoveBit(imm, 6, 25) | MoveBit( imm, 5, 24) |
MoveBit(imm, 4, 23) | MoveBit( imm, 3, 22) |
MoveBit(imm, 2, 21) | MoveBit( imm, 1, 20) |
MoveBit(imm, 0, 19);
}
// abcdefgh -> aBbbbbbb bbcdefgh 00000000 00000000 00000000 00000000 00000000 00000000 (B = ~b)
private static ulong ExpandImm8ToFP64(ulong imm)
{
ulong MoveBit(ulong bits, int from, int to)
{
return ((bits >> from) & 1UL) << to;
}
return MoveBit(imm, 7, 63) | MoveBit(~imm, 6, 62) |
MoveBit(imm, 6, 61) | MoveBit( imm, 6, 60) |
MoveBit(imm, 6, 59) | MoveBit( imm, 6, 58) |
MoveBit(imm, 6, 57) | MoveBit( imm, 6, 56) |
MoveBit(imm, 6, 55) | MoveBit( imm, 6, 54) |
MoveBit(imm, 5, 53) | MoveBit( imm, 4, 52) |
MoveBit(imm, 3, 51) | MoveBit( imm, 2, 50) |
MoveBit(imm, 1, 49) | MoveBit( imm, 0, 48);
}
public struct BitMask
{
public long WMask;
public long TMask;
public int Pos;
public int Shift;
public bool IsUndefined;
public static BitMask Invalid => new BitMask { IsUndefined = true };
}
public static BitMask DecodeBitMask(int opCode, bool immediate)
{
int immS = (opCode >> 10) & 0x3f;
int immR = (opCode >> 16) & 0x3f;
int n = (opCode >> 22) & 1;
int sf = (opCode >> 31) & 1;
int length = BitUtils.HighestBitSet((~immS & 0x3f) | (n << 6));
if (length < 1 || (sf == 0 && n != 0))
{
return BitMask.Invalid;
}
int size = 1 << length;
int levels = size - 1;
int s = immS & levels;
int r = immR & levels;
if (immediate && s == levels)
{
return BitMask.Invalid;
}
long wMask = BitUtils.FillWithOnes(s + 1);
long tMask = BitUtils.FillWithOnes(((s - r) & levels) + 1);
if (r > 0)
{
wMask = BitUtils.RotateRight(wMask, r, size);
wMask &= BitUtils.FillWithOnes(size);
}
return new BitMask()
{
WMask = BitUtils.Replicate(wMask, size),
TMask = BitUtils.Replicate(tMask, size),
Pos = immS,
Shift = immR
};
}
public static long DecodeImm24_2(int opCode)
{
return ((long)opCode << 40) >> 38;
}
public static long DecodeImm26_2(int opCode)
{
return ((long)opCode << 38) >> 36;
}
public static long DecodeImmS19_2(int opCode)
{
return (((long)opCode << 40) >> 43) & ~3;
}
public static long DecodeImmS14_2(int opCode)
{
return (((long)opCode << 45) >> 48) & ~3;
}
public static bool VectorArgumentsInvalid(bool q, params int[] args)
{
if (q)
{
for (int i = 0; i < args.Length; i++)
{
if ((args[i] & 1) == 1)
{
return true;
}
}
}
return false;
}
}
}

View File

@@ -1,6 +0,0 @@
namespace ARMeilleure.Decoders;
interface IOpCode32Exception
{
int Id { get; }
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,54 +0,0 @@
using ARMeilleure.Decoders;
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation;
using static ARMeilleure.Instructions.InstEmitHelper;
using static ARMeilleure.Instructions.InstEmitHashHelper;
namespace ARMeilleure.Instructions
{
static partial class InstEmit32
{
public static void Crc32b(ArmEmitterContext context)
{
EmitCrc32Call(context, ByteSizeLog2, false);
}
public static void Crc32h(ArmEmitterContext context)
{
EmitCrc32Call(context, HWordSizeLog2, false);
}
public static void Crc32w(ArmEmitterContext context)
{
EmitCrc32Call(context, WordSizeLog2, false);
}
public static void Crc32cb(ArmEmitterContext context)
{
EmitCrc32Call(context, ByteSizeLog2, true);
}
public static void Crc32ch(ArmEmitterContext context)
{
EmitCrc32Call(context, HWordSizeLog2, true);
}
public static void Crc32cw(ArmEmitterContext context)
{
EmitCrc32Call(context, WordSizeLog2, true);
}
private static void EmitCrc32Call(ArmEmitterContext context, int size, bool c)
{
IOpCode32AluReg op = (IOpCode32AluReg)context.CurrOp;
Operand n = GetIntA32(context, op.Rn);
Operand m = GetIntA32(context, op.Rm);
Operand d = EmitCrc32(context, n, m, size, c);
EmitAluStore(context, d);
}
}
}

View File

@@ -1,119 +0,0 @@
// https://www.intel.com/content/dam/www/public/us/en/documents/white-papers/fast-crc-computation-generic-polynomials-pclmulqdq-paper.pdf
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation;
using System;
using System.Diagnostics;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
using static ARMeilleure.Instructions.InstEmitSimdHelper;
namespace ARMeilleure.Instructions
{
static class InstEmitHashHelper
{
public const uint Crc32RevPoly = 0xedb88320;
public const uint Crc32cRevPoly = 0x82f63b78;
public static Operand EmitCrc32(ArmEmitterContext context, Operand crc, Operand value, int size, bool castagnoli)
{
Debug.Assert(crc.Type.IsInteger() && value.Type.IsInteger());
Debug.Assert(size >= 0 && size < 4);
Debug.Assert((size < 3) || (value.Type == OperandType.I64));
if (castagnoli && Optimizations.UseSse42)
{
// The CRC32 instruction does not have an immediate variant, so ensure both inputs are in registers.
value = (value.Kind == OperandKind.Constant) ? context.Copy(value) : value;
crc = (crc.Kind == OperandKind.Constant) ? context.Copy(crc) : crc;
Intrinsic op = size switch
{
0 => Intrinsic.X86Crc32_8,
1 => Intrinsic.X86Crc32_16,
_ => Intrinsic.X86Crc32,
};
return (size == 3) ? context.ConvertI64ToI32(context.AddIntrinsicLong(op, crc, value)) : context.AddIntrinsicInt(op, crc, value);
}
else if (Optimizations.UsePclmulqdq)
{
return size switch
{
3 => EmitCrc32Optimized64(context, crc, value, castagnoli),
_ => EmitCrc32Optimized(context, crc, value, castagnoli, size),
};
}
else
{
string name = (size, castagnoli) switch
{
(0, false) => nameof(SoftFallback.Crc32b),
(1, false) => nameof(SoftFallback.Crc32h),
(2, false) => nameof(SoftFallback.Crc32w),
(3, false) => nameof(SoftFallback.Crc32x),
(0, true) => nameof(SoftFallback.Crc32cb),
(1, true) => nameof(SoftFallback.Crc32ch),
(2, true) => nameof(SoftFallback.Crc32cw),
(3, true) => nameof(SoftFallback.Crc32cx),
_ => throw new ArgumentOutOfRangeException(nameof(size))
};
return context.Call(typeof(SoftFallback).GetMethod(name), crc, value);
}
}
private static Operand EmitCrc32Optimized(ArmEmitterContext context, Operand crc, Operand data, bool castagnoli, int size)
{
long mu = castagnoli ? 0x0DEA713F1 : 0x1F7011641; // mu' = floor(x^64/P(x))'
long polynomial = castagnoli ? 0x105EC76F0 : 0x1DB710641; // P'(x) << 1
crc = context.VectorInsert(context.VectorZero(), crc, 0);
switch (size)
{
case 0: data = context.VectorInsert8(context.VectorZero(), data, 0); break;
case 1: data = context.VectorInsert16(context.VectorZero(), data, 0); break;
case 2: data = context.VectorInsert(context.VectorZero(), data, 0); break;
}
int bitsize = 8 << size;
Operand tmp = context.AddIntrinsic(Intrinsic.X86Pxor, crc, data);
tmp = context.AddIntrinsic(Intrinsic.X86Psllq, tmp, Const(64 - bitsize));
tmp = context.AddIntrinsic(Intrinsic.X86Pclmulqdq, tmp, X86GetScalar(context, mu), Const(0));
tmp = context.AddIntrinsic(Intrinsic.X86Pclmulqdq, tmp, X86GetScalar(context, polynomial), Const(0));
if (bitsize < 32)
{
crc = context.AddIntrinsic(Intrinsic.X86Pslldq, crc, Const((64 - bitsize) / 8));
tmp = context.AddIntrinsic(Intrinsic.X86Pxor, tmp, crc);
}
return context.VectorExtract(OperandType.I32, tmp, 2);
}
private static Operand EmitCrc32Optimized64(ArmEmitterContext context, Operand crc, Operand data, bool castagnoli)
{
long mu = castagnoli ? 0x0DEA713F1 : 0x1F7011641; // mu' = floor(x^64/P(x))'
long polynomial = castagnoli ? 0x105EC76F0 : 0x1DB710641; // P'(x) << 1
crc = context.VectorInsert(context.VectorZero(), crc, 0);
data = context.VectorInsert(context.VectorZero(), data, 0);
Operand tmp = context.AddIntrinsic(Intrinsic.X86Pxor, crc, data);
Operand res = context.AddIntrinsic(Intrinsic.X86Pslldq, tmp, Const(4));
tmp = context.AddIntrinsic(Intrinsic.X86Pclmulqdq, res, X86GetScalar(context, mu), Const(0));
tmp = context.AddIntrinsic(Intrinsic.X86Pclmulqdq, tmp, X86GetScalar(context, polynomial), Const(0));
tmp = context.AddIntrinsic(Intrinsic.X86Pxor, tmp, res);
tmp = context.AddIntrinsic(Intrinsic.X86Psllq, tmp, Const(32));
tmp = context.AddIntrinsic(Intrinsic.X86Pclmulqdq, tmp, X86GetScalar(context, mu), Const(1));
tmp = context.AddIntrinsic(Intrinsic.X86Pclmulqdq, tmp, X86GetScalar(context, polynomial), Const(0));
return context.VectorExtract(OperandType.I32, tmp, 2);
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,785 +0,0 @@
using ARMeilleure.Decoders;
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.State;
using ARMeilleure.Translation;
using System;
using static ARMeilleure.Instructions.InstEmitHelper;
using static ARMeilleure.Instructions.InstEmitSimdHelper;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
namespace ARMeilleure.Instructions
{
using Func2I = Func<Operand, Operand, Operand>;
static partial class InstEmit
{
public static void Cmeq_S(ArmEmitterContext context)
{
EmitCmpOp(context, (op1, op2) => context.ICompareEqual(op1, op2), scalar: true);
}
public static void Cmeq_V(ArmEmitterContext context)
{
if (Optimizations.UseSse41)
{
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
Operand n = GetVec(op.Rn);
Operand m;
if (op is OpCodeSimdReg binOp)
{
m = GetVec(binOp.Rm);
}
else
{
m = context.VectorZero();
}
Intrinsic cmpInst = X86PcmpeqInstruction[op.Size];
Operand res = context.AddIntrinsic(cmpInst, n, m);
if (op.RegisterSize == RegisterSize.Simd64)
{
res = context.VectorZeroUpper64(res);
}
context.Copy(GetVec(op.Rd), res);
}
else
{
EmitCmpOp(context, (op1, op2) => context.ICompareEqual(op1, op2), scalar: false);
}
}
public static void Cmge_S(ArmEmitterContext context)
{
EmitCmpOp(context, (op1, op2) => context.ICompareGreaterOrEqual(op1, op2), scalar: true);
}
public static void Cmge_V(ArmEmitterContext context)
{
if (Optimizations.UseSse42)
{
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
Operand n = GetVec(op.Rn);
Operand m;
if (op is OpCodeSimdReg binOp)
{
m = GetVec(binOp.Rm);
}
else
{
m = context.VectorZero();
}
Intrinsic cmpInst = X86PcmpgtInstruction[op.Size];
Operand res = context.AddIntrinsic(cmpInst, m, n);
Operand mask = X86GetAllElements(context, -1L);
res = context.AddIntrinsic(Intrinsic.X86Pandn, res, mask);
if (op.RegisterSize == RegisterSize.Simd64)
{
res = context.VectorZeroUpper64(res);
}
context.Copy(GetVec(op.Rd), res);
}
else
{
EmitCmpOp(context, (op1, op2) => context.ICompareGreaterOrEqual(op1, op2), scalar: false);
}
}
public static void Cmgt_S(ArmEmitterContext context)
{
EmitCmpOp(context, (op1, op2) => context.ICompareGreater(op1, op2), scalar: true);
}
public static void Cmgt_V(ArmEmitterContext context)
{
if (Optimizations.UseSse42)
{
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
Operand n = GetVec(op.Rn);
Operand m;
if (op is OpCodeSimdReg binOp)
{
m = GetVec(binOp.Rm);
}
else
{
m = context.VectorZero();
}
Intrinsic cmpInst = X86PcmpgtInstruction[op.Size];
Operand res = context.AddIntrinsic(cmpInst, n, m);
if (op.RegisterSize == RegisterSize.Simd64)
{
res = context.VectorZeroUpper64(res);
}
context.Copy(GetVec(op.Rd), res);
}
else
{
EmitCmpOp(context, (op1, op2) => context.ICompareGreater(op1, op2), scalar: false);
}
}
public static void Cmhi_S(ArmEmitterContext context)
{
EmitCmpOp(context, (op1, op2) => context.ICompareGreaterUI(op1, op2), scalar: true);
}
public static void Cmhi_V(ArmEmitterContext context)
{
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
if (Optimizations.UseSse41 && op.Size < 3)
{
Operand n = GetVec(op.Rn);
Operand m = GetVec(op.Rm);
Intrinsic maxInst = X86PmaxuInstruction[op.Size];
Operand res = context.AddIntrinsic(maxInst, m, n);
Intrinsic cmpInst = X86PcmpeqInstruction[op.Size];
res = context.AddIntrinsic(cmpInst, res, m);
Operand mask = X86GetAllElements(context, -1L);
res = context.AddIntrinsic(Intrinsic.X86Pandn, res, mask);
if (op.RegisterSize == RegisterSize.Simd64)
{
res = context.VectorZeroUpper64(res);
}
context.Copy(GetVec(op.Rd), res);
}
else
{
EmitCmpOp(context, (op1, op2) => context.ICompareGreaterUI(op1, op2), scalar: false);
}
}
public static void Cmhs_S(ArmEmitterContext context)
{
EmitCmpOp(context, (op1, op2) => context.ICompareGreaterOrEqualUI(op1, op2), scalar: true);
}
public static void Cmhs_V(ArmEmitterContext context)
{
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
if (Optimizations.UseSse41 && op.Size < 3)
{
Operand n = GetVec(op.Rn);
Operand m = GetVec(op.Rm);
Intrinsic maxInst = X86PmaxuInstruction[op.Size];
Operand res = context.AddIntrinsic(maxInst, n, m);
Intrinsic cmpInst = X86PcmpeqInstruction[op.Size];
res = context.AddIntrinsic(cmpInst, res, n);
if (op.RegisterSize == RegisterSize.Simd64)
{
res = context.VectorZeroUpper64(res);
}
context.Copy(GetVec(op.Rd), res);
}
else
{
EmitCmpOp(context, (op1, op2) => context.ICompareGreaterOrEqualUI(op1, op2), scalar: false);
}
}
public static void Cmle_S(ArmEmitterContext context)
{
EmitCmpOp(context, (op1, op2) => context.ICompareLessOrEqual(op1, op2), scalar: true);
}
public static void Cmle_V(ArmEmitterContext context)
{
if (Optimizations.UseSse42)
{
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
Operand n = GetVec(op.Rn);
Intrinsic cmpInst = X86PcmpgtInstruction[op.Size];
Operand res = context.AddIntrinsic(cmpInst, n, context.VectorZero());
Operand mask = X86GetAllElements(context, -1L);
res = context.AddIntrinsic(Intrinsic.X86Pandn, res, mask);
if (op.RegisterSize == RegisterSize.Simd64)
{
res = context.VectorZeroUpper64(res);
}
context.Copy(GetVec(op.Rd), res);
}
else
{
EmitCmpOp(context, (op1, op2) => context.ICompareLessOrEqual(op1, op2), scalar: false);
}
}
public static void Cmlt_S(ArmEmitterContext context)
{
EmitCmpOp(context, (op1, op2) => context.ICompareLess(op1, op2), scalar: true);
}
public static void Cmlt_V(ArmEmitterContext context)
{
if (Optimizations.UseSse42)
{
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
Operand n = GetVec(op.Rn);
Intrinsic cmpInst = X86PcmpgtInstruction[op.Size];
Operand res = context.AddIntrinsic(cmpInst, context.VectorZero(), n);
if (op.RegisterSize == RegisterSize.Simd64)
{
res = context.VectorZeroUpper64(res);
}
context.Copy(GetVec(op.Rd), res);
}
else
{
EmitCmpOp(context, (op1, op2) => context.ICompareLess(op1, op2), scalar: false);
}
}
public static void Cmtst_S(ArmEmitterContext context)
{
EmitCmtstOp(context, scalar: true);
}
public static void Cmtst_V(ArmEmitterContext context)
{
EmitCmtstOp(context, scalar: false);
}
public static void Facge_S(ArmEmitterContext context)
{
if (Optimizations.FastFP && Optimizations.UseAvx)
{
EmitSse2OrAvxCmpOpF(context, CmpCondition.GreaterThanOrEqual, scalar: true, absolute: true);
}
else
{
EmitCmpOpF(context, nameof(SoftFloat32.FPCompareGE), scalar: true, absolute: true);
}
}
public static void Facge_V(ArmEmitterContext context)
{
if (Optimizations.FastFP && Optimizations.UseAvx)
{
EmitSse2OrAvxCmpOpF(context, CmpCondition.GreaterThanOrEqual, scalar: false, absolute: true);
}
else
{
EmitCmpOpF(context, nameof(SoftFloat32.FPCompareGE), scalar: false, absolute: true);
}
}
public static void Facgt_S(ArmEmitterContext context)
{
if (Optimizations.FastFP && Optimizations.UseAvx)
{
EmitSse2OrAvxCmpOpF(context, CmpCondition.GreaterThan, scalar: true, absolute: true);
}
else
{
EmitCmpOpF(context, nameof(SoftFloat32.FPCompareGT), scalar: true, absolute: true);
}
}
public static void Facgt_V(ArmEmitterContext context)
{
if (Optimizations.FastFP && Optimizations.UseAvx)
{
EmitSse2OrAvxCmpOpF(context, CmpCondition.GreaterThan, scalar: false, absolute: true);
}
else
{
EmitCmpOpF(context, nameof(SoftFloat32.FPCompareGT), scalar: false, absolute: true);
}
}
public static void Fccmp_S(ArmEmitterContext context)
{
EmitFccmpOrFccmpe(context, signalNaNs: false);
}
public static void Fccmpe_S(ArmEmitterContext context)
{
EmitFccmpOrFccmpe(context, signalNaNs: true);
}
public static void Fcmeq_S(ArmEmitterContext context)
{
if (Optimizations.FastFP && Optimizations.UseSse2)
{
EmitSse2OrAvxCmpOpF(context, CmpCondition.Equal, scalar: true);
}
else
{
EmitCmpOpF(context, nameof(SoftFloat32.FPCompareEQ), scalar: true);
}
}
public static void Fcmeq_V(ArmEmitterContext context)
{
if (Optimizations.FastFP && Optimizations.UseSse2)
{
EmitSse2OrAvxCmpOpF(context, CmpCondition.Equal, scalar: false);
}
else
{
EmitCmpOpF(context, nameof(SoftFloat32.FPCompareEQ), scalar: false);
}
}
public static void Fcmge_S(ArmEmitterContext context)
{
if (Optimizations.FastFP && Optimizations.UseAvx)
{
EmitSse2OrAvxCmpOpF(context, CmpCondition.GreaterThanOrEqual, scalar: true);
}
else
{
EmitCmpOpF(context, nameof(SoftFloat32.FPCompareGE), scalar: true);
}
}
public static void Fcmge_V(ArmEmitterContext context)
{
if (Optimizations.FastFP && Optimizations.UseAvx)
{
EmitSse2OrAvxCmpOpF(context, CmpCondition.GreaterThanOrEqual, scalar: false);
}
else
{
EmitCmpOpF(context, nameof(SoftFloat32.FPCompareGE), scalar: false);
}
}
public static void Fcmgt_S(ArmEmitterContext context)
{
if (Optimizations.FastFP && Optimizations.UseAvx)
{
EmitSse2OrAvxCmpOpF(context, CmpCondition.GreaterThan, scalar: true);
}
else
{
EmitCmpOpF(context, nameof(SoftFloat32.FPCompareGT), scalar: true);
}
}
public static void Fcmgt_V(ArmEmitterContext context)
{
if (Optimizations.FastFP && Optimizations.UseAvx)
{
EmitSse2OrAvxCmpOpF(context, CmpCondition.GreaterThan, scalar: false);
}
else
{
EmitCmpOpF(context, nameof(SoftFloat32.FPCompareGT), scalar: false);
}
}
public static void Fcmle_S(ArmEmitterContext context)
{
if (Optimizations.FastFP && Optimizations.UseSse2)
{
EmitSse2OrAvxCmpOpF(context, CmpCondition.LessThanOrEqual, scalar: true);
}
else
{
EmitCmpOpF(context, nameof(SoftFloat32.FPCompareLE), scalar: true);
}
}
public static void Fcmle_V(ArmEmitterContext context)
{
if (Optimizations.FastFP && Optimizations.UseSse2)
{
EmitSse2OrAvxCmpOpF(context, CmpCondition.LessThanOrEqual, scalar: false);
}
else
{
EmitCmpOpF(context, nameof(SoftFloat32.FPCompareLE), scalar: false);
}
}
public static void Fcmlt_S(ArmEmitterContext context)
{
if (Optimizations.FastFP && Optimizations.UseSse2)
{
EmitSse2OrAvxCmpOpF(context, CmpCondition.LessThan, scalar: true);
}
else
{
EmitCmpOpF(context, nameof(SoftFloat32.FPCompareLT), scalar: true);
}
}
public static void Fcmlt_V(ArmEmitterContext context)
{
if (Optimizations.FastFP && Optimizations.UseSse2)
{
EmitSse2OrAvxCmpOpF(context, CmpCondition.LessThan, scalar: false);
}
else
{
EmitCmpOpF(context, nameof(SoftFloat32.FPCompareLT), scalar: false);
}
}
public static void Fcmp_S(ArmEmitterContext context)
{
EmitFcmpOrFcmpe(context, signalNaNs: false);
}
public static void Fcmpe_S(ArmEmitterContext context)
{
EmitFcmpOrFcmpe(context, signalNaNs: true);
}
private static void EmitFccmpOrFccmpe(ArmEmitterContext context, bool signalNaNs)
{
OpCodeSimdFcond op = (OpCodeSimdFcond)context.CurrOp;
Operand lblTrue = Label();
Operand lblEnd = Label();
context.BranchIfTrue(lblTrue, InstEmitFlowHelper.GetCondTrue(context, op.Cond));
EmitSetNzcv(context, op.Nzcv);
context.Branch(lblEnd);
context.MarkLabel(lblTrue);
EmitFcmpOrFcmpe(context, signalNaNs);
context.MarkLabel(lblEnd);
}
private static void EmitSetNzcv(ArmEmitterContext context, int nzcv)
{
Operand Extract(int value, int bit)
{
if (bit != 0)
{
value >>= bit;
}
value &= 1;
return Const(value);
}
SetFlag(context, PState.VFlag, Extract(nzcv, 0));
SetFlag(context, PState.CFlag, Extract(nzcv, 1));
SetFlag(context, PState.ZFlag, Extract(nzcv, 2));
SetFlag(context, PState.NFlag, Extract(nzcv, 3));
}
private static void EmitFcmpOrFcmpe(ArmEmitterContext context, bool signalNaNs)
{
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
bool cmpWithZero = !(op is OpCodeSimdFcond) ? op.Bit3 : false;
if (Optimizations.FastFP && (signalNaNs ? Optimizations.UseAvx : Optimizations.UseSse2))
{
Operand n = GetVec(op.Rn);
Operand m = cmpWithZero ? context.VectorZero() : GetVec(op.Rm);
CmpCondition cmpOrdered = signalNaNs ? CmpCondition.OrderedS : CmpCondition.OrderedQ;
Operand lblNaN = Label();
Operand lblEnd = Label();
if (op.Size == 0)
{
Operand ordMask = context.AddIntrinsic(Intrinsic.X86Cmpss, n, m, Const((int)cmpOrdered));
Operand isOrdered = context.AddIntrinsicInt(Intrinsic.X86Cvtsi2si, ordMask);
context.BranchIfFalse(lblNaN, isOrdered);
Operand nCopy = context.Copy(n);
Operand mCopy = cmpWithZero ? context.VectorZero() : context.Copy(m);
Operand cf = context.AddIntrinsicInt(Intrinsic.X86Comissge, nCopy, mCopy);
Operand zf = context.AddIntrinsicInt(Intrinsic.X86Comisseq, nCopy, mCopy);
Operand nf = context.AddIntrinsicInt(Intrinsic.X86Comisslt, nCopy, mCopy);
SetFlag(context, PState.VFlag, Const(0));
SetFlag(context, PState.CFlag, cf);
SetFlag(context, PState.ZFlag, zf);
SetFlag(context, PState.NFlag, nf);
}
else /* if (op.Size == 1) */
{
Operand ordMask = context.AddIntrinsic(Intrinsic.X86Cmpsd, n, m, Const((int)cmpOrdered));
Operand isOrdered = context.AddIntrinsicLong(Intrinsic.X86Cvtsi2si, ordMask);
context.BranchIfFalse(lblNaN, isOrdered);
Operand nCopy = context.Copy(n);
Operand mCopy = cmpWithZero ? context.VectorZero() : context.Copy(m);
Operand cf = context.AddIntrinsicInt(Intrinsic.X86Comisdge, nCopy, mCopy);
Operand zf = context.AddIntrinsicInt(Intrinsic.X86Comisdeq, nCopy, mCopy);
Operand nf = context.AddIntrinsicInt(Intrinsic.X86Comisdlt, nCopy, mCopy);
SetFlag(context, PState.VFlag, Const(0));
SetFlag(context, PState.CFlag, cf);
SetFlag(context, PState.ZFlag, zf);
SetFlag(context, PState.NFlag, nf);
}
context.Branch(lblEnd);
context.MarkLabel(lblNaN);
SetFlag(context, PState.VFlag, Const(1));
SetFlag(context, PState.CFlag, Const(1));
SetFlag(context, PState.ZFlag, Const(0));
SetFlag(context, PState.NFlag, Const(0));
context.MarkLabel(lblEnd);
}
else
{
OperandType type = op.Size != 0 ? OperandType.FP64 : OperandType.FP32;
Operand ne = context.VectorExtract(type, GetVec(op.Rn), 0);
Operand me;
if (cmpWithZero)
{
me = op.Size == 0 ? ConstF(0f) : ConstF(0d);
}
else
{
me = context.VectorExtract(type, GetVec(op.Rm), 0);
}
Operand nzcv = EmitSoftFloatCall(context, nameof(SoftFloat32.FPCompare), ne, me, Const(signalNaNs));
EmitSetNzcv(context, nzcv);
}
}
private static void EmitSetNzcv(ArmEmitterContext context, Operand nzcv)
{
Operand Extract(Operand value, int bit)
{
if (bit != 0)
{
value = context.ShiftRightUI(value, Const(bit));
}
value = context.BitwiseAnd(value, Const(1));
return value;
}
SetFlag(context, PState.VFlag, Extract(nzcv, 0));
SetFlag(context, PState.CFlag, Extract(nzcv, 1));
SetFlag(context, PState.ZFlag, Extract(nzcv, 2));
SetFlag(context, PState.NFlag, Extract(nzcv, 3));
}
private static void EmitCmpOp(ArmEmitterContext context, Func2I emitCmp, bool scalar)
{
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
Operand res = context.VectorZero();
int elems = !scalar ? op.GetBytesCount() >> op.Size : 1;
ulong szMask = ulong.MaxValue >> (64 - (8 << op.Size));
for (int index = 0; index < elems; index++)
{
Operand ne = EmitVectorExtractSx(context, op.Rn, index, op.Size);
Operand me;
if (op is OpCodeSimdReg binOp)
{
me = EmitVectorExtractSx(context, binOp.Rm, index, op.Size);
}
else
{
me = Const(0L);
}
Operand isTrue = emitCmp(ne, me);
Operand mask = context.ConditionalSelect(isTrue, Const(szMask), Const(0L));
res = EmitVectorInsert(context, res, mask, index, op.Size);
}
context.Copy(GetVec(op.Rd), res);
}
private static void EmitCmtstOp(ArmEmitterContext context, bool scalar)
{
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
Operand res = context.VectorZero();
int elems = !scalar ? op.GetBytesCount() >> op.Size : 1;
ulong szMask = ulong.MaxValue >> (64 - (8 << op.Size));
for (int index = 0; index < elems; index++)
{
Operand ne = EmitVectorExtractZx(context, op.Rn, index, op.Size);
Operand me = EmitVectorExtractZx(context, op.Rm, index, op.Size);
Operand test = context.BitwiseAnd(ne, me);
Operand isTrue = context.ICompareNotEqual(test, Const(0L));
Operand mask = context.ConditionalSelect(isTrue, Const(szMask), Const(0L));
res = EmitVectorInsert(context, res, mask, index, op.Size);
}
context.Copy(GetVec(op.Rd), res);
}
private static void EmitCmpOpF(ArmEmitterContext context, string name, bool scalar, bool absolute = false)
{
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
Operand res = context.VectorZero();
int sizeF = op.Size & 1;
OperandType type = sizeF != 0 ? OperandType.FP64 : OperandType.FP32;
int elems = !scalar ? op.GetBytesCount() >> sizeF + 2 : 1;
for (int index = 0; index < elems; index++)
{
Operand ne = context.VectorExtract(type, GetVec(op.Rn), index);
Operand me;
if (op is OpCodeSimdReg binOp)
{
me = context.VectorExtract(type, GetVec(binOp.Rm), index);
}
else
{
me = sizeF == 0 ? ConstF(0f) : ConstF(0d);
}
if (absolute)
{
ne = EmitUnaryMathCall(context, nameof(Math.Abs), ne);
me = EmitUnaryMathCall(context, nameof(Math.Abs), me);
}
Operand e = EmitSoftFloatCall(context, name, ne, me);
res = context.VectorInsert(res, e, index);
}
context.Copy(GetVec(op.Rd), res);
}
private static void EmitSse2OrAvxCmpOpF(ArmEmitterContext context, CmpCondition cond, bool scalar, bool absolute = false)
{
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
Operand n = GetVec(op.Rn);
Operand m = op is OpCodeSimdReg binOp ? GetVec(binOp.Rm) : context.VectorZero();
int sizeF = op.Size & 1;
if (sizeF == 0)
{
if (absolute)
{
Operand mask = scalar ? X86GetScalar(context, int.MaxValue) : X86GetAllElements(context, int.MaxValue);
n = context.AddIntrinsic(Intrinsic.X86Andps, n, mask);
m = context.AddIntrinsic(Intrinsic.X86Andps, m, mask);
}
Intrinsic inst = scalar ? Intrinsic.X86Cmpss : Intrinsic.X86Cmpps;
Operand res = context.AddIntrinsic(inst, n, m, Const((int)cond));
if (scalar)
{
res = context.VectorZeroUpper96(res);
}
else if (op.RegisterSize == RegisterSize.Simd64)
{
res = context.VectorZeroUpper64(res);
}
context.Copy(GetVec(op.Rd), res);
}
else /* if (sizeF == 1) */
{
if (absolute)
{
Operand mask = scalar ? X86GetScalar(context, long.MaxValue) : X86GetAllElements(context, long.MaxValue);
n = context.AddIntrinsic(Intrinsic.X86Andpd, n, mask);
m = context.AddIntrinsic(Intrinsic.X86Andpd, m, mask);
}
Intrinsic inst = scalar ? Intrinsic.X86Cmpsd : Intrinsic.X86Cmppd;
Operand res = context.AddIntrinsic(inst, n, m, Const((int)cond));
if (scalar)
{
res = context.VectorZeroUpper64(res);
}
context.Copy(GetVec(op.Rd), res);
}
}
}
}

View File

@@ -1,391 +0,0 @@
using ARMeilleure.Decoders;
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.State;
using ARMeilleure.Translation;
using System;
using static ARMeilleure.Instructions.InstEmitHelper;
using static ARMeilleure.Instructions.InstEmitSimdHelper;
using static ARMeilleure.Instructions.InstEmitSimdHelper32;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
namespace ARMeilleure.Instructions
{
using Func2I = Func<Operand, Operand, Operand>;
static partial class InstEmit32
{
public static void Vceq_V(ArmEmitterContext context)
{
if (Optimizations.FastFP && Optimizations.UseSse2)
{
EmitSse2OrAvxCmpOpF32(context, CmpCondition.Equal, false);
}
else
{
EmitCmpOpF32(context, nameof(SoftFloat32.FPCompareEQFpscr), false);
}
}
public static void Vceq_I(ArmEmitterContext context)
{
EmitCmpOpI32(context, context.ICompareEqual, context.ICompareEqual, false, false);
}
public static void Vceq_Z(ArmEmitterContext context)
{
OpCode32Simd op = (OpCode32Simd)context.CurrOp;
if (op.F)
{
if (Optimizations.FastFP && Optimizations.UseSse2)
{
EmitSse2OrAvxCmpOpF32(context, CmpCondition.Equal, true);
}
else
{
EmitCmpOpF32(context, nameof(SoftFloat32.FPCompareEQFpscr), true);
}
}
else
{
EmitCmpOpI32(context, context.ICompareEqual, context.ICompareEqual, true, false);
}
}
public static void Vcge_V(ArmEmitterContext context)
{
if (Optimizations.FastFP && Optimizations.UseAvx)
{
EmitSse2OrAvxCmpOpF32(context, CmpCondition.GreaterThanOrEqual, false);
}
else
{
EmitCmpOpF32(context, nameof(SoftFloat32.FPCompareGEFpscr), false);
}
}
public static void Vcge_I(ArmEmitterContext context)
{
OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;
EmitCmpOpI32(context, context.ICompareGreaterOrEqual, context.ICompareGreaterOrEqualUI, false, !op.U);
}
public static void Vcge_Z(ArmEmitterContext context)
{
OpCode32Simd op = (OpCode32Simd)context.CurrOp;
if (op.F)
{
if (Optimizations.FastFP && Optimizations.UseAvx)
{
EmitSse2OrAvxCmpOpF32(context, CmpCondition.GreaterThanOrEqual, true);
}
else
{
EmitCmpOpF32(context, nameof(SoftFloat32.FPCompareGEFpscr), true);
}
}
else
{
EmitCmpOpI32(context, context.ICompareGreaterOrEqual, context.ICompareGreaterOrEqualUI, true, true);
}
}
public static void Vcgt_V(ArmEmitterContext context)
{
if (Optimizations.FastFP && Optimizations.UseAvx)
{
EmitSse2OrAvxCmpOpF32(context, CmpCondition.GreaterThan, false);
}
else
{
EmitCmpOpF32(context, nameof(SoftFloat32.FPCompareGTFpscr), false);
}
}
public static void Vcgt_I(ArmEmitterContext context)
{
OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;
EmitCmpOpI32(context, context.ICompareGreater, context.ICompareGreaterUI, false, !op.U);
}
public static void Vcgt_Z(ArmEmitterContext context)
{
OpCode32Simd op = (OpCode32Simd)context.CurrOp;
if (op.F)
{
if (Optimizations.FastFP && Optimizations.UseAvx)
{
EmitSse2OrAvxCmpOpF32(context, CmpCondition.GreaterThan, true);
}
else
{
EmitCmpOpF32(context, nameof(SoftFloat32.FPCompareGTFpscr), true);
}
}
else
{
EmitCmpOpI32(context, context.ICompareGreater, context.ICompareGreaterUI, true, true);
}
}
public static void Vcle_Z(ArmEmitterContext context)
{
OpCode32Simd op = (OpCode32Simd)context.CurrOp;
if (op.F)
{
if (Optimizations.FastFP && Optimizations.UseSse2)
{
EmitSse2OrAvxCmpOpF32(context, CmpCondition.LessThanOrEqual, true);
}
else
{
EmitCmpOpF32(context, nameof(SoftFloat32.FPCompareLEFpscr), true);
}
}
else
{
EmitCmpOpI32(context, context.ICompareLessOrEqual, context.ICompareLessOrEqualUI, true, true);
}
}
public static void Vclt_Z(ArmEmitterContext context)
{
OpCode32Simd op = (OpCode32Simd)context.CurrOp;
if (op.F)
{
if (Optimizations.FastFP && Optimizations.UseSse2)
{
EmitSse2OrAvxCmpOpF32(context, CmpCondition.LessThan, true);
}
else
{
EmitCmpOpF32(context, nameof(SoftFloat32.FPCompareLTFpscr), true);
}
}
else
{
EmitCmpOpI32(context, context.ICompareLess, context.ICompareLessUI, true, true);
}
}
private static void EmitCmpOpF32(ArmEmitterContext context, string name, bool zero)
{
if (zero)
{
EmitVectorUnaryOpF32(context, (m) =>
{
Operand zeroOp = m.Type == OperandType.FP64 ? ConstF(0.0d) : ConstF(0.0f);
return EmitSoftFloatCallDefaultFpscr(context, name, m, zeroOp);
});
}
else
{
EmitVectorBinaryOpF32(context, (n, m) =>
{
return EmitSoftFloatCallDefaultFpscr(context, name, n, m);
});
}
}
private static Operand ZerosOrOnes(ArmEmitterContext context, Operand fromBool, OperandType baseType)
{
var ones = (baseType == OperandType.I64) ? Const(-1L) : Const(-1);
return context.ConditionalSelect(fromBool, ones, Const(baseType, 0L));
}
private static void EmitCmpOpI32(
ArmEmitterContext context,
Func2I signedOp,
Func2I unsignedOp,
bool zero,
bool signed)
{
if (zero)
{
if (signed)
{
EmitVectorUnaryOpSx32(context, (m) =>
{
OperandType type = m.Type;
Operand zeroV = (type == OperandType.I64) ? Const(0L) : Const(0);
return ZerosOrOnes(context, signedOp(m, zeroV), type);
});
}
else
{
EmitVectorUnaryOpZx32(context, (m) =>
{
OperandType type = m.Type;
Operand zeroV = (type == OperandType.I64) ? Const(0L) : Const(0);
return ZerosOrOnes(context, unsignedOp(m, zeroV), type);
});
}
}
else
{
if (signed)
{
EmitVectorBinaryOpSx32(context, (n, m) => ZerosOrOnes(context, signedOp(n, m), n.Type));
}
else
{
EmitVectorBinaryOpZx32(context, (n, m) => ZerosOrOnes(context, unsignedOp(n, m), n.Type));
}
}
}
public static void Vcmp(ArmEmitterContext context)
{
EmitVcmpOrVcmpe(context, false);
}
public static void Vcmpe(ArmEmitterContext context)
{
EmitVcmpOrVcmpe(context, true);
}
private static void EmitVcmpOrVcmpe(ArmEmitterContext context, bool signalNaNs)
{
OpCode32SimdS op = (OpCode32SimdS)context.CurrOp;
bool cmpWithZero = (op.Opc & 2) != 0;
int sizeF = op.Size & 1;
if (Optimizations.FastFP && (signalNaNs ? Optimizations.UseAvx : Optimizations.UseSse2))
{
CmpCondition cmpOrdered = signalNaNs ? CmpCondition.OrderedS : CmpCondition.OrderedQ;
bool doubleSize = sizeF != 0;
int shift = doubleSize ? 1 : 2;
Operand m = GetVecA32(op.Vm >> shift);
Operand n = GetVecA32(op.Vd >> shift);
n = EmitSwapScalar(context, n, op.Vd, doubleSize);
m = cmpWithZero ? context.VectorZero() : EmitSwapScalar(context, m, op.Vm, doubleSize);
Operand lblNaN = Label();
Operand lblEnd = Label();
if (!doubleSize)
{
Operand ordMask = context.AddIntrinsic(Intrinsic.X86Cmpss, n, m, Const((int)cmpOrdered));
Operand isOrdered = context.AddIntrinsicInt(Intrinsic.X86Cvtsi2si, ordMask);
context.BranchIfFalse(lblNaN, isOrdered);
Operand cf = context.AddIntrinsicInt(Intrinsic.X86Comissge, n, m);
Operand zf = context.AddIntrinsicInt(Intrinsic.X86Comisseq, n, m);
Operand nf = context.AddIntrinsicInt(Intrinsic.X86Comisslt, n, m);
SetFpFlag(context, FPState.VFlag, Const(0));
SetFpFlag(context, FPState.CFlag, cf);
SetFpFlag(context, FPState.ZFlag, zf);
SetFpFlag(context, FPState.NFlag, nf);
}
else
{
Operand ordMask = context.AddIntrinsic(Intrinsic.X86Cmpsd, n, m, Const((int)cmpOrdered));
Operand isOrdered = context.AddIntrinsicLong(Intrinsic.X86Cvtsi2si, ordMask);
context.BranchIfFalse(lblNaN, isOrdered);
Operand cf = context.AddIntrinsicInt(Intrinsic.X86Comisdge, n, m);
Operand zf = context.AddIntrinsicInt(Intrinsic.X86Comisdeq, n, m);
Operand nf = context.AddIntrinsicInt(Intrinsic.X86Comisdlt, n, m);
SetFpFlag(context, FPState.VFlag, Const(0));
SetFpFlag(context, FPState.CFlag, cf);
SetFpFlag(context, FPState.ZFlag, zf);
SetFpFlag(context, FPState.NFlag, nf);
}
context.Branch(lblEnd);
context.MarkLabel(lblNaN);
SetFpFlag(context, FPState.VFlag, Const(1));
SetFpFlag(context, FPState.CFlag, Const(1));
SetFpFlag(context, FPState.ZFlag, Const(0));
SetFpFlag(context, FPState.NFlag, Const(0));
context.MarkLabel(lblEnd);
}
else
{
OperandType type = sizeF != 0 ? OperandType.FP64 : OperandType.FP32;
Operand ne = ExtractScalar(context, type, op.Vd);
Operand me;
if (cmpWithZero)
{
me = sizeF == 0 ? ConstF(0f) : ConstF(0d);
}
else
{
me = ExtractScalar(context, type, op.Vm);
}
Operand nzcv = EmitSoftFloatCall(context, nameof(SoftFloat32.FPCompare), ne, me, Const(signalNaNs));
EmitSetFpscrNzcv(context, nzcv);
}
}
private static void EmitSetFpscrNzcv(ArmEmitterContext context, Operand nzcv)
{
Operand Extract(Operand value, int bit)
{
if (bit != 0)
{
value = context.ShiftRightUI(value, Const(bit));
}
value = context.BitwiseAnd(value, Const(1));
return value;
}
SetFpFlag(context, FPState.VFlag, Extract(nzcv, 0));
SetFpFlag(context, FPState.CFlag, Extract(nzcv, 1));
SetFpFlag(context, FPState.ZFlag, Extract(nzcv, 2));
SetFpFlag(context, FPState.NFlag, Extract(nzcv, 3));
}
private static void EmitSse2OrAvxCmpOpF32(ArmEmitterContext context, CmpCondition cond, bool zero)
{
OpCode32Simd op = (OpCode32Simd)context.CurrOp;
int sizeF = op.Size & 1;
Intrinsic inst = (sizeF == 0) ? Intrinsic.X86Cmpps : Intrinsic.X86Cmppd;
if (zero)
{
EmitVectorUnaryOpSimd32(context, (m) =>
{
return context.AddIntrinsic(inst, m, context.VectorZero(), Const((int)cond));
});
}
else
{
EmitVectorBinaryOpSimd32(context, (n, m) =>
{
return context.AddIntrinsic(inst, n, m, Const((int)cond));
});
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,712 +0,0 @@
using ARMeilleure.Decoders;
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.State;
using ARMeilleure.Translation;
using System;
using System.Diagnostics;
using System.Reflection;
using static ARMeilleure.Instructions.InstEmitHelper;
using static ARMeilleure.Instructions.InstEmitSimdHelper;
using static ARMeilleure.Instructions.InstEmitSimdHelper32;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
namespace ARMeilleure.Instructions
{
static partial class InstEmit32
{
private static int FlipVdBits(int vd, bool lowBit)
{
if (lowBit)
{
// Move the low bit to the top.
return ((vd & 0x1) << 4) | (vd >> 1);
}
else
{
// Move the high bit to the bottom.
return ((vd & 0xf) << 1) | (vd >> 4);
}
}
private static Operand EmitSaturateFloatToInt(ArmEmitterContext context, Operand op1, bool unsigned)
{
MethodInfo info;
if (op1.Type == OperandType.FP64)
{
info = unsigned
? typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF64ToU32))
: typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF64ToS32));
}
else
{
info = unsigned
? typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToU32))
: typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToS32));
}
return context.Call(info, op1);
}
public static void Vcvt_V(ArmEmitterContext context)
{
OpCode32Simd op = (OpCode32Simd)context.CurrOp;
bool unsigned = (op.Opc & 1) != 0;
bool toInteger = (op.Opc & 2) != 0;
OperandType floatSize = (op.Size == 2) ? OperandType.FP32 : OperandType.FP64;
if (toInteger)
{
if (Optimizations.UseSse41)
{
EmitSse41ConvertVector32(context, FPRoundingMode.TowardsZero, !unsigned);
}
else
{
EmitVectorUnaryOpF32(context, (op1) =>
{
return EmitSaturateFloatToInt(context, op1, unsigned);
});
}
}
else
{
if (Optimizations.UseSse2)
{
EmitVectorUnaryOpSimd32(context, (n) =>
{
if (unsigned)
{
Operand mask = X86GetAllElements(context, 0x47800000);
Operand res = context.AddIntrinsic(Intrinsic.X86Psrld, n, Const(16));
res = context.AddIntrinsic(Intrinsic.X86Cvtdq2ps, res);
res = context.AddIntrinsic(Intrinsic.X86Mulps, res, mask);
Operand res2 = context.AddIntrinsic(Intrinsic.X86Pslld, n, Const(16));
res2 = context.AddIntrinsic(Intrinsic.X86Psrld, res2, Const(16));
res2 = context.AddIntrinsic(Intrinsic.X86Cvtdq2ps, res2);
return context.AddIntrinsic(Intrinsic.X86Addps, res, res2);
}
else
{
return context.AddIntrinsic(Intrinsic.X86Cvtdq2ps, n);
}
});
}
else
{
if (unsigned)
{
EmitVectorUnaryOpZx32(context, (op1) => EmitFPConvert(context, op1, floatSize, false));
}
else
{
EmitVectorUnaryOpSx32(context, (op1) => EmitFPConvert(context, op1, floatSize, true));
}
}
}
}
public static void Vcvt_FD(ArmEmitterContext context)
{
OpCode32SimdS op = (OpCode32SimdS)context.CurrOp;
int vm = op.Vm;
int vd;
if (op.Size == 3)
{
vd = FlipVdBits(op.Vd, false);
// Double to single.
Operand fp = ExtractScalar(context, OperandType.FP64, vm);
Operand res = context.ConvertToFP(OperandType.FP32, fp);
InsertScalar(context, vd, res);
}
else
{
vd = FlipVdBits(op.Vd, true);
// Single to double.
Operand fp = ExtractScalar(context, OperandType.FP32, vm);
Operand res = context.ConvertToFP(OperandType.FP64, fp);
InsertScalar(context, vd, res);
}
}
// VCVT (floating-point to integer, floating-point) | VCVT (integer to floating-point, floating-point).
public static void Vcvt_FI(ArmEmitterContext context)
{
OpCode32SimdCvtFI op = (OpCode32SimdCvtFI)context.CurrOp;
bool toInteger = (op.Opc2 & 0b100) != 0;
OperandType floatSize = op.RegisterSize == RegisterSize.Int64 ? OperandType.FP64 : OperandType.FP32;
if (toInteger)
{
bool unsigned = (op.Opc2 & 1) == 0;
bool roundWithFpscr = op.Opc != 1;
if (!roundWithFpscr && Optimizations.UseSse41)
{
EmitSse41ConvertInt32(context, FPRoundingMode.TowardsZero, !unsigned);
}
else
{
Operand toConvert = ExtractScalar(context, floatSize, op.Vm);
// TODO: Fast Path.
if (roundWithFpscr)
{
toConvert = EmitRoundByRMode(context, toConvert);
}
// Round towards zero.
Operand asInteger = EmitSaturateFloatToInt(context, toConvert, unsigned);
InsertScalar(context, op.Vd, asInteger);
}
}
else
{
bool unsigned = op.Opc == 0;
Operand toConvert = ExtractScalar(context, OperandType.I32, op.Vm);
Operand asFloat = EmitFPConvert(context, toConvert, floatSize, !unsigned);
InsertScalar(context, op.Vd, asFloat);
}
}
private static Operand EmitRoundMathCall(ArmEmitterContext context, MidpointRounding roundMode, Operand n)
{
IOpCode32Simd op = (IOpCode32Simd)context.CurrOp;
string name = nameof(Math.Round);
MethodInfo info = (op.Size & 1) == 0
? typeof(MathF).GetMethod(name, new Type[] { typeof(float), typeof(MidpointRounding) })
: typeof(Math). GetMethod(name, new Type[] { typeof(double), typeof(MidpointRounding) });
return context.Call(info, n, Const((int)roundMode));
}
private static FPRoundingMode RMToRoundMode(int rm)
{
FPRoundingMode roundMode;
switch (rm)
{
case 0b00:
roundMode = FPRoundingMode.ToNearestAway;
break;
case 0b01:
roundMode = FPRoundingMode.ToNearest;
break;
case 0b10:
roundMode = FPRoundingMode.TowardsPlusInfinity;
break;
case 0b11:
roundMode = FPRoundingMode.TowardsMinusInfinity;
break;
default:
throw new ArgumentOutOfRangeException(nameof(rm));
}
return roundMode;
}
// VCVTA/M/N/P (floating-point).
public static void Vcvt_RM(ArmEmitterContext context)
{
OpCode32SimdCvtFI op = (OpCode32SimdCvtFI)context.CurrOp; // toInteger == true (opCode<18> == 1 => Opc2<2> == 1).
OperandType floatSize = op.RegisterSize == RegisterSize.Int64 ? OperandType.FP64 : OperandType.FP32;
bool unsigned = op.Opc == 0;
int rm = op.Opc2 & 3;
if (Optimizations.UseSse41)
{
EmitSse41ConvertInt32(context, RMToRoundMode(rm), !unsigned);
}
else
{
Operand toConvert = ExtractScalar(context, floatSize, op.Vm);
switch (rm)
{
case 0b00: // Away
toConvert = EmitRoundMathCall(context, MidpointRounding.AwayFromZero, toConvert);
break;
case 0b01: // Nearest
toConvert = EmitRoundMathCall(context, MidpointRounding.ToEven, toConvert);
break;
case 0b10: // Towards positive infinity
toConvert = EmitUnaryMathCall(context, nameof(Math.Ceiling), toConvert);
break;
case 0b11: // Towards negative infinity
toConvert = EmitUnaryMathCall(context, nameof(Math.Floor), toConvert);
break;
}
Operand asInteger = EmitSaturateFloatToInt(context, toConvert, unsigned);
InsertScalar(context, op.Vd, asInteger);
}
}
public static void Vcvt_TB(ArmEmitterContext context)
{
OpCode32SimdCvtTB op = (OpCode32SimdCvtTB)context.CurrOp;
if (Optimizations.UseF16c)
{
Debug.Assert(!Optimizations.ForceLegacySse);
if (op.Op)
{
Operand res = ExtractScalar(context, op.Size == 1 ? OperandType.FP64 : OperandType.FP32, op.Vm);
if (op.Size == 1)
{
res = context.AddIntrinsic(Intrinsic.X86Cvtsd2ss, context.VectorZero(), res);
}
res = context.AddIntrinsic(Intrinsic.X86Vcvtps2ph, res, Const(X86GetRoundControl(FPRoundingMode.ToNearest)));
res = context.VectorExtract16(res, 0);
InsertScalar16(context, op.Vd, op.T, res);
}
else
{
Operand res = context.VectorCreateScalar(ExtractScalar16(context, op.Vm, op.T));
res = context.AddIntrinsic(Intrinsic.X86Vcvtph2ps, res);
if (op.Size == 1)
{
res = context.AddIntrinsic(Intrinsic.X86Cvtss2sd, context.VectorZero(), res);
}
res = context.VectorExtract(op.Size == 1 ? OperandType.I64 : OperandType.I32, res, 0);
InsertScalar(context, op.Vd, res);
}
}
else
{
if (op.Op)
{
// Convert to half.
Operand src = ExtractScalar(context, op.Size == 1 ? OperandType.FP64 : OperandType.FP32, op.Vm);
MethodInfo method = op.Size == 1
? typeof(SoftFloat64_16).GetMethod(nameof(SoftFloat64_16.FPConvert))
: typeof(SoftFloat32_16).GetMethod(nameof(SoftFloat32_16.FPConvert));
context.StoreToContext();
Operand res = context.Call(method, src);
context.LoadFromContext();
InsertScalar16(context, op.Vd, op.T, res);
}
else
{
// Convert from half.
Operand src = ExtractScalar16(context, op.Vm, op.T);
MethodInfo method = op.Size == 1
? typeof(SoftFloat16_64).GetMethod(nameof(SoftFloat16_64.FPConvert))
: typeof(SoftFloat16_32).GetMethod(nameof(SoftFloat16_32.FPConvert));
context.StoreToContext();
Operand res = context.Call(method, src);
context.LoadFromContext();
InsertScalar(context, op.Vd, res);
}
}
}
// VRINTA/M/N/P (floating-point).
public static void Vrint_RM(ArmEmitterContext context)
{
OpCode32SimdS op = (OpCode32SimdS)context.CurrOp;
OperandType floatSize = op.RegisterSize == RegisterSize.Int64 ? OperandType.FP64 : OperandType.FP32;
int rm = op.Opc2 & 3;
if (Optimizations.UseSse41)
{
EmitScalarUnaryOpSimd32(context, (m) =>
{
FPRoundingMode roundMode = RMToRoundMode(rm);
if (roundMode != FPRoundingMode.ToNearestAway)
{
Intrinsic inst = (op.Size & 1) == 0 ? Intrinsic.X86Roundss : Intrinsic.X86Roundsd;
return context.AddIntrinsic(inst, m, Const(X86GetRoundControl(roundMode)));
}
else
{
return EmitSse41RoundToNearestWithTiesToAwayOpF(context, m, scalar: true);
}
});
}
else
{
Operand toConvert = ExtractScalar(context, floatSize, op.Vm);
switch (rm)
{
case 0b00: // Away
toConvert = EmitRoundMathCall(context, MidpointRounding.AwayFromZero, toConvert);
break;
case 0b01: // Nearest
toConvert = EmitRoundMathCall(context, MidpointRounding.ToEven, toConvert);
break;
case 0b10: // Towards positive infinity
toConvert = EmitUnaryMathCall(context, nameof(Math.Ceiling), toConvert);
break;
case 0b11: // Towards negative infinity
toConvert = EmitUnaryMathCall(context, nameof(Math.Floor), toConvert);
break;
}
InsertScalar(context, op.Vd, toConvert);
}
}
// VRINTA (vector).
public static void Vrinta_V(ArmEmitterContext context)
{
if (Optimizations.UseSse41)
{
EmitVectorUnaryOpSimd32(context, (m) =>
{
return EmitSse41RoundToNearestWithTiesToAwayOpF(context, m, scalar: false);
});
}
else
{
EmitVectorUnaryOpF32(context, (m) => EmitRoundMathCall(context, MidpointRounding.AwayFromZero, m));
}
}
// VRINTM (vector).
public static void Vrintm_V(ArmEmitterContext context)
{
if (Optimizations.UseSse2)
{
EmitVectorUnaryOpSimd32(context, (m) =>
{
return context.AddIntrinsic(Intrinsic.X86Roundps, m, Const(X86GetRoundControl(FPRoundingMode.TowardsMinusInfinity)));
});
}
else
{
EmitVectorUnaryOpF32(context, (m) => EmitUnaryMathCall(context, nameof(Math.Floor), m));
}
}
// VRINTN (vector).
public static void Vrintn_V(ArmEmitterContext context)
{
if (Optimizations.UseSse2)
{
EmitVectorUnaryOpSimd32(context, (m) =>
{
return context.AddIntrinsic(Intrinsic.X86Roundps, m, Const(X86GetRoundControl(FPRoundingMode.ToNearest)));
});
}
else
{
EmitVectorUnaryOpF32(context, (m) => EmitRoundMathCall(context, MidpointRounding.ToEven, m));
}
}
// VRINTP (vector).
public static void Vrintp_V(ArmEmitterContext context)
{
if (Optimizations.UseSse2)
{
EmitVectorUnaryOpSimd32(context, (m) =>
{
return context.AddIntrinsic(Intrinsic.X86Roundps, m, Const(X86GetRoundControl(FPRoundingMode.TowardsPlusInfinity)));
});
}
else
{
EmitVectorUnaryOpF32(context, (m) => EmitUnaryMathCall(context, nameof(Math.Ceiling), m));
}
}
// VRINTZ (floating-point).
public static void Vrint_Z(ArmEmitterContext context)
{
OpCode32SimdS op = (OpCode32SimdS)context.CurrOp;
if (Optimizations.UseSse2)
{
EmitScalarUnaryOpSimd32(context, (m) =>
{
Intrinsic inst = (op.Size & 1) == 0 ? Intrinsic.X86Roundss : Intrinsic.X86Roundsd;
return context.AddIntrinsic(inst, m, Const(X86GetRoundControl(FPRoundingMode.TowardsZero)));
});
}
else
{
EmitScalarUnaryOpF32(context, (op1) => EmitUnaryMathCall(context, nameof(Math.Truncate), op1));
}
}
// VRINTX (floating-point).
public static void Vrintx_S(ArmEmitterContext context)
{
EmitScalarUnaryOpF32(context, (op1) =>
{
return EmitRoundByRMode(context, op1);
});
}
private static Operand EmitFPConvert(ArmEmitterContext context, Operand value, OperandType type, bool signed)
{
Debug.Assert(value.Type == OperandType.I32 || value.Type == OperandType.I64);
if (signed)
{
return context.ConvertToFP(type, value);
}
else
{
return context.ConvertToFPUI(type, value);
}
}
private static void EmitSse41ConvertInt32(ArmEmitterContext context, FPRoundingMode roundMode, bool signed)
{
// A port of the similar round function in InstEmitSimdCvt.
OpCode32SimdCvtFI op = (OpCode32SimdCvtFI)context.CurrOp;
bool doubleSize = (op.Size & 1) != 0;
int shift = doubleSize ? 1 : 2;
Operand n = GetVecA32(op.Vm >> shift);
n = EmitSwapScalar(context, n, op.Vm, doubleSize);
if (!doubleSize)
{
Operand nRes = context.AddIntrinsic(Intrinsic.X86Cmpss, n, n, Const((int)CmpCondition.OrderedQ));
nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, n);
if (roundMode != FPRoundingMode.ToNearestAway)
{
nRes = context.AddIntrinsic(Intrinsic.X86Roundss, nRes, Const(X86GetRoundControl(roundMode)));
}
else
{
nRes = EmitSse41RoundToNearestWithTiesToAwayOpF(context, nRes, scalar: true);
}
Operand zero = context.VectorZero();
Operand nCmp;
Operand nIntOrLong2 = default;
if (!signed)
{
nCmp = context.AddIntrinsic(Intrinsic.X86Cmpss, nRes, zero, Const((int)CmpCondition.NotLessThanOrEqual));
nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, nCmp);
}
int fpMaxVal = 0x4F000000; // 2.14748365E9f (2147483648)
Operand fpMaxValMask = X86GetScalar(context, fpMaxVal);
Operand nIntOrLong = context.AddIntrinsicInt(Intrinsic.X86Cvtss2si, nRes);
if (!signed)
{
nRes = context.AddIntrinsic(Intrinsic.X86Subss, nRes, fpMaxValMask);
nCmp = context.AddIntrinsic(Intrinsic.X86Cmpss, nRes, zero, Const((int)CmpCondition.NotLessThanOrEqual));
nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, nCmp);
nIntOrLong2 = context.AddIntrinsicInt(Intrinsic.X86Cvtss2si, nRes);
}
nRes = context.AddIntrinsic(Intrinsic.X86Cmpss, nRes, fpMaxValMask, Const((int)CmpCondition.NotLessThan));
Operand nInt = context.AddIntrinsicInt(Intrinsic.X86Cvtsi2si, nRes);
Operand dRes;
if (signed)
{
dRes = context.BitwiseExclusiveOr(nIntOrLong, nInt);
}
else
{
dRes = context.BitwiseExclusiveOr(nIntOrLong2, nInt);
dRes = context.Add(dRes, nIntOrLong);
}
InsertScalar(context, op.Vd, dRes);
}
else
{
Operand nRes = context.AddIntrinsic(Intrinsic.X86Cmpsd, n, n, Const((int)CmpCondition.OrderedQ));
nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, n);
if (roundMode != FPRoundingMode.ToNearestAway)
{
nRes = context.AddIntrinsic(Intrinsic.X86Roundsd, nRes, Const(X86GetRoundControl(roundMode)));
}
else
{
nRes = EmitSse41RoundToNearestWithTiesToAwayOpF(context, nRes, scalar: true);
}
Operand zero = context.VectorZero();
Operand nCmp;
Operand nIntOrLong2 = default;
if (!signed)
{
nCmp = context.AddIntrinsic(Intrinsic.X86Cmpsd, nRes, zero, Const((int)CmpCondition.NotLessThanOrEqual));
nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, nCmp);
}
long fpMaxVal = 0x41E0000000000000L; // 2147483648.0000000d (2147483648)
Operand fpMaxValMask = X86GetScalar(context, fpMaxVal);
Operand nIntOrLong = context.AddIntrinsicInt(Intrinsic.X86Cvtsd2si, nRes);
if (!signed)
{
nRes = context.AddIntrinsic(Intrinsic.X86Subsd, nRes, fpMaxValMask);
nCmp = context.AddIntrinsic(Intrinsic.X86Cmpsd, nRes, zero, Const((int)CmpCondition.NotLessThanOrEqual));
nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, nCmp);
nIntOrLong2 = context.AddIntrinsicInt(Intrinsic.X86Cvtsd2si, nRes);
}
nRes = context.AddIntrinsic(Intrinsic.X86Cmpsd, nRes, fpMaxValMask, Const((int)CmpCondition.NotLessThan));
Operand nLong = context.AddIntrinsicLong(Intrinsic.X86Cvtsi2si, nRes);
nLong = context.ConvertI64ToI32(nLong);
Operand dRes;
if (signed)
{
dRes = context.BitwiseExclusiveOr(nIntOrLong, nLong);
}
else
{
dRes = context.BitwiseExclusiveOr(nIntOrLong2, nLong);
dRes = context.Add(dRes, nIntOrLong);
}
InsertScalar(context, op.Vd, dRes);
}
}
private static void EmitSse41ConvertVector32(ArmEmitterContext context, FPRoundingMode roundMode, bool signed)
{
OpCode32Simd op = (OpCode32Simd)context.CurrOp;
EmitVectorUnaryOpSimd32(context, (n) =>
{
int sizeF = op.Size & 1;
if (sizeF == 0)
{
Operand nRes = context.AddIntrinsic(Intrinsic.X86Cmpps, n, n, Const((int)CmpCondition.OrderedQ));
nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, n);
nRes = context.AddIntrinsic(Intrinsic.X86Roundps, nRes, Const(X86GetRoundControl(roundMode)));
Operand zero = context.VectorZero();
Operand nCmp;
if (!signed)
{
nCmp = context.AddIntrinsic(Intrinsic.X86Cmpps, nRes, zero, Const((int)CmpCondition.NotLessThanOrEqual));
nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, nCmp);
}
Operand fpMaxValMask = X86GetAllElements(context, 0x4F000000); // 2.14748365E9f (2147483648)
Operand nInt = context.AddIntrinsic(Intrinsic.X86Cvtps2dq, nRes);
Operand nInt2 = default;
if (!signed)
{
nRes = context.AddIntrinsic(Intrinsic.X86Subps, nRes, fpMaxValMask);
nCmp = context.AddIntrinsic(Intrinsic.X86Cmpps, nRes, zero, Const((int)CmpCondition.NotLessThanOrEqual));
nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, nCmp);
nInt2 = context.AddIntrinsic(Intrinsic.X86Cvtps2dq, nRes);
}
nRes = context.AddIntrinsic(Intrinsic.X86Cmpps, nRes, fpMaxValMask, Const((int)CmpCondition.NotLessThan));
if (signed)
{
return context.AddIntrinsic(Intrinsic.X86Pxor, nInt, nRes);
}
else
{
Operand dRes = context.AddIntrinsic(Intrinsic.X86Pxor, nInt2, nRes);
return context.AddIntrinsic(Intrinsic.X86Paddd, dRes, nInt);
}
}
else /* if (sizeF == 1) */
{
Operand nRes = context.AddIntrinsic(Intrinsic.X86Cmppd, n, n, Const((int)CmpCondition.OrderedQ));
nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, n);
nRes = context.AddIntrinsic(Intrinsic.X86Roundpd, nRes, Const(X86GetRoundControl(roundMode)));
Operand zero = context.VectorZero();
Operand nCmp;
if (!signed)
{
nCmp = context.AddIntrinsic(Intrinsic.X86Cmppd, nRes, zero, Const((int)CmpCondition.NotLessThanOrEqual));
nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, nCmp);
}
Operand fpMaxValMask = X86GetAllElements(context, 0x43E0000000000000L); // 9.2233720368547760E18d (9223372036854775808)
Operand nLong = InstEmit.EmitSse2CvtDoubleToInt64OpF(context, nRes, false);
Operand nLong2 = default;
if (!signed)
{
nRes = context.AddIntrinsic(Intrinsic.X86Subpd, nRes, fpMaxValMask);
nCmp = context.AddIntrinsic(Intrinsic.X86Cmppd, nRes, zero, Const((int)CmpCondition.NotLessThanOrEqual));
nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, nCmp);
nLong2 = InstEmit.EmitSse2CvtDoubleToInt64OpF(context, nRes, false);
}
nRes = context.AddIntrinsic(Intrinsic.X86Cmppd, nRes, fpMaxValMask, Const((int)CmpCondition.NotLessThan));
if (signed)
{
return context.AddIntrinsic(Intrinsic.X86Pxor, nLong, nRes);
}
else
{
Operand dRes = context.AddIntrinsic(Intrinsic.X86Pxor, nLong2, nRes);
return context.AddIntrinsic(Intrinsic.X86Paddq, dRes, nLong);
}
}
});
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,543 +0,0 @@
using ARMeilleure.Decoders;
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation;
using System;
using System.Diagnostics;
using static ARMeilleure.Instructions.InstEmitHelper;
using static ARMeilleure.Instructions.InstEmitSimdHelper;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
namespace ARMeilleure.Instructions
{
static partial class InstEmit
{
public static void And_V(ArmEmitterContext context)
{
if (Optimizations.UseSse2)
{
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
Operand n = GetVec(op.Rn);
Operand m = GetVec(op.Rm);
Operand res = context.AddIntrinsic(Intrinsic.X86Pand, n, m);
if (op.RegisterSize == RegisterSize.Simd64)
{
res = context.VectorZeroUpper64(res);
}
context.Copy(GetVec(op.Rd), res);
}
else
{
EmitVectorBinaryOpZx(context, (op1, op2) => context.BitwiseAnd(op1, op2));
}
}
public static void Bic_V(ArmEmitterContext context)
{
if (Optimizations.UseSse2)
{
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
Operand n = GetVec(op.Rn);
Operand m = GetVec(op.Rm);
Operand res = context.AddIntrinsic(Intrinsic.X86Pandn, m, n);
if (op.RegisterSize == RegisterSize.Simd64)
{
res = context.VectorZeroUpper64(res);
}
context.Copy(GetVec(op.Rd), res);
}
else
{
EmitVectorBinaryOpZx(context, (op1, op2) =>
{
return context.BitwiseAnd(op1, context.BitwiseNot(op2));
});
}
}
public static void Bic_Vi(ArmEmitterContext context)
{
if (Optimizations.UseSse2)
{
OpCodeSimdImm op = (OpCodeSimdImm)context.CurrOp;
int eSize = 8 << op.Size;
Operand d = GetVec(op.Rd);
Operand imm = eSize switch {
16 => X86GetAllElements(context, (short)~op.Immediate),
32 => X86GetAllElements(context, (int)~op.Immediate),
_ => throw new InvalidOperationException($"Invalid element size {eSize}.")
};
Operand res = context.AddIntrinsic(Intrinsic.X86Pand, d, imm);
if (op.RegisterSize == RegisterSize.Simd64)
{
res = context.VectorZeroUpper64(res);
}
context.Copy(GetVec(op.Rd), res);
}
else
{
EmitVectorImmBinaryOp(context, (op1, op2) =>
{
return context.BitwiseAnd(op1, context.BitwiseNot(op2));
});
}
}
public static void Bif_V(ArmEmitterContext context)
{
EmitBifBit(context, notRm: true);
}
public static void Bit_V(ArmEmitterContext context)
{
EmitBifBit(context, notRm: false);
}
private static void EmitBifBit(ArmEmitterContext context, bool notRm)
{
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
if (Optimizations.UseSse2)
{
Operand d = GetVec(op.Rd);
Operand n = GetVec(op.Rn);
Operand m = GetVec(op.Rm);
Operand res = context.AddIntrinsic(Intrinsic.X86Pxor, n, d);
if (notRm)
{
res = context.AddIntrinsic(Intrinsic.X86Pandn, m, res);
}
else
{
res = context.AddIntrinsic(Intrinsic.X86Pand, m, res);
}
res = context.AddIntrinsic(Intrinsic.X86Pxor, d, res);
if (op.RegisterSize == RegisterSize.Simd64)
{
res = context.VectorZeroUpper64(res);
}
context.Copy(d, res);
}
else
{
Operand res = context.VectorZero();
int elems = op.RegisterSize == RegisterSize.Simd128 ? 2 : 1;
for (int index = 0; index < elems; index++)
{
Operand d = EmitVectorExtractZx(context, op.Rd, index, 3);
Operand n = EmitVectorExtractZx(context, op.Rn, index, 3);
Operand m = EmitVectorExtractZx(context, op.Rm, index, 3);
if (notRm)
{
m = context.BitwiseNot(m);
}
Operand e = context.BitwiseExclusiveOr(d, n);
e = context.BitwiseAnd(e, m);
e = context.BitwiseExclusiveOr(e, d);
res = EmitVectorInsert(context, res, e, index, 3);
}
context.Copy(GetVec(op.Rd), res);
}
}
public static void Bsl_V(ArmEmitterContext context)
{
if (Optimizations.UseSse2)
{
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
Operand d = GetVec(op.Rd);
Operand n = GetVec(op.Rn);
Operand m = GetVec(op.Rm);
Operand res = context.AddIntrinsic(Intrinsic.X86Pxor, n, m);
res = context.AddIntrinsic(Intrinsic.X86Pand, res, d);
res = context.AddIntrinsic(Intrinsic.X86Pxor, res, m);
if (op.RegisterSize == RegisterSize.Simd64)
{
res = context.VectorZeroUpper64(res);
}
context.Copy(d, res);
}
else
{
EmitVectorTernaryOpZx(context, (op1, op2, op3) =>
{
return context.BitwiseExclusiveOr(
context.BitwiseAnd(op1,
context.BitwiseExclusiveOr(op2, op3)), op3);
});
}
}
public static void Eor_V(ArmEmitterContext context)
{
if (Optimizations.UseSse2)
{
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
Operand n = GetVec(op.Rn);
Operand m = GetVec(op.Rm);
Operand res = context.AddIntrinsic(Intrinsic.X86Pxor, n, m);
if (op.RegisterSize == RegisterSize.Simd64)
{
res = context.VectorZeroUpper64(res);
}
context.Copy(GetVec(op.Rd), res);
}
else
{
EmitVectorBinaryOpZx(context, (op1, op2) => context.BitwiseExclusiveOr(op1, op2));
}
}
public static void Not_V(ArmEmitterContext context)
{
if (Optimizations.UseSse2)
{
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
Operand n = GetVec(op.Rn);
Operand mask = X86GetAllElements(context, -1L);
Operand res = context.AddIntrinsic(Intrinsic.X86Pandn, n, mask);
if (op.RegisterSize == RegisterSize.Simd64)
{
res = context.VectorZeroUpper64(res);
}
context.Copy(GetVec(op.Rd), res);
}
else
{
EmitVectorUnaryOpZx(context, (op1) => context.BitwiseNot(op1));
}
}
public static void Orn_V(ArmEmitterContext context)
{
if (Optimizations.UseSse2)
{
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
Operand n = GetVec(op.Rn);
Operand m = GetVec(op.Rm);
Operand mask = X86GetAllElements(context, -1L);
Operand res = context.AddIntrinsic(Intrinsic.X86Pandn, m, mask);
res = context.AddIntrinsic(Intrinsic.X86Por, res, n);
if (op.RegisterSize == RegisterSize.Simd64)
{
res = context.VectorZeroUpper64(res);
}
context.Copy(GetVec(op.Rd), res);
}
else
{
EmitVectorBinaryOpZx(context, (op1, op2) =>
{
return context.BitwiseOr(op1, context.BitwiseNot(op2));
});
}
}
public static void Orr_V(ArmEmitterContext context)
{
if (Optimizations.UseSse2)
{
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
Operand n = GetVec(op.Rn);
Operand m = GetVec(op.Rm);
Operand res = context.AddIntrinsic(Intrinsic.X86Por, n, m);
if (op.RegisterSize == RegisterSize.Simd64)
{
res = context.VectorZeroUpper64(res);
}
context.Copy(GetVec(op.Rd), res);
}
else
{
EmitVectorBinaryOpZx(context, (op1, op2) => context.BitwiseOr(op1, op2));
}
}
public static void Orr_Vi(ArmEmitterContext context)
{
if (Optimizations.UseSse2)
{
OpCodeSimdImm op = (OpCodeSimdImm)context.CurrOp;
int eSize = 8 << op.Size;
Operand d = GetVec(op.Rd);
Operand imm = eSize switch {
16 => X86GetAllElements(context, (short)op.Immediate),
32 => X86GetAllElements(context, (int)op.Immediate),
_ => throw new InvalidOperationException($"Invalid element size {eSize}.")
};
Operand res = context.AddIntrinsic(Intrinsic.X86Por, d, imm);
if (op.RegisterSize == RegisterSize.Simd64)
{
res = context.VectorZeroUpper64(res);
}
context.Copy(GetVec(op.Rd), res);
}
else
{
EmitVectorImmBinaryOp(context, (op1, op2) => context.BitwiseOr(op1, op2));
}
}
public static void Rbit_V(ArmEmitterContext context)
{
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
if (Optimizations.UseGfni)
{
const long bitMatrix =
(0b10000000L << 56) |
(0b01000000L << 48) |
(0b00100000L << 40) |
(0b00010000L << 32) |
(0b00001000L << 24) |
(0b00000100L << 16) |
(0b00000010L << 8) |
(0b00000001L << 0);
Operand vBitMatrix = X86GetAllElements(context, bitMatrix);
Operand res = context.AddIntrinsic(Intrinsic.X86Gf2p8affineqb, GetVec(op.Rn), vBitMatrix, Const(0));
if (op.RegisterSize == RegisterSize.Simd64)
{
res = context.VectorZeroUpper64(res);
}
context.Copy(GetVec(op.Rd), res);
}
else
{
Operand res = context.VectorZero();
int elems = op.RegisterSize == RegisterSize.Simd128 ? 16 : 8;
for (int index = 0; index < elems; index++)
{
Operand ne = EmitVectorExtractZx(context, op.Rn, index, 0);
Operand de = EmitReverseBits8Op(context, ne);
res = EmitVectorInsert(context, res, de, index, 0);
}
context.Copy(GetVec(op.Rd), res);
}
}
private static Operand EmitReverseBits8Op(ArmEmitterContext context, Operand op)
{
Debug.Assert(op.Type == OperandType.I64);
Operand val = context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(op, Const(0xaaul)), Const(1)),
context.ShiftLeft (context.BitwiseAnd(op, Const(0x55ul)), Const(1)));
val = context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(val, Const(0xccul)), Const(2)),
context.ShiftLeft (context.BitwiseAnd(val, Const(0x33ul)), Const(2)));
return context.BitwiseOr(context.ShiftRightUI(val, Const(4)),
context.ShiftLeft (context.BitwiseAnd(val, Const(0x0ful)), Const(4)));
}
public static void Rev16_V(ArmEmitterContext context)
{
if (Optimizations.UseSsse3)
{
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
Operand n = GetVec(op.Rn);
const long maskE0 = 06L << 56 | 07L << 48 | 04L << 40 | 05L << 32 | 02L << 24 | 03L << 16 | 00L << 8 | 01L << 0;
const long maskE1 = 14L << 56 | 15L << 48 | 12L << 40 | 13L << 32 | 10L << 24 | 11L << 16 | 08L << 8 | 09L << 0;
Operand mask = X86GetScalar(context, maskE0);
mask = EmitVectorInsert(context, mask, Const(maskE1), 1, 3);
Operand res = context.AddIntrinsic(Intrinsic.X86Pshufb, n, mask);
if (op.RegisterSize == RegisterSize.Simd64)
{
res = context.VectorZeroUpper64(res);
}
context.Copy(GetVec(op.Rd), res);
}
else
{
EmitRev_V(context, containerSize: 1);
}
}
public static void Rev32_V(ArmEmitterContext context)
{
if (Optimizations.UseSsse3)
{
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
Operand n = GetVec(op.Rn);
Operand mask;
if (op.Size == 0)
{
const long maskE0 = 04L << 56 | 05L << 48 | 06L << 40 | 07L << 32 | 00L << 24 | 01L << 16 | 02L << 8 | 03L << 0;
const long maskE1 = 12L << 56 | 13L << 48 | 14L << 40 | 15L << 32 | 08L << 24 | 09L << 16 | 10L << 8 | 11L << 0;
mask = X86GetScalar(context, maskE0);
mask = EmitVectorInsert(context, mask, Const(maskE1), 1, 3);
}
else /* if (op.Size == 1) */
{
const long maskE0 = 05L << 56 | 04L << 48 | 07L << 40 | 06L << 32 | 01L << 24 | 00L << 16 | 03L << 8 | 02L << 0;
const long maskE1 = 13L << 56 | 12L << 48 | 15L << 40 | 14L << 32 | 09L << 24 | 08L << 16 | 11L << 8 | 10L << 0;
mask = X86GetScalar(context, maskE0);
mask = EmitVectorInsert(context, mask, Const(maskE1), 1, 3);
}
Operand res = context.AddIntrinsic(Intrinsic.X86Pshufb, n, mask);
if (op.RegisterSize == RegisterSize.Simd64)
{
res = context.VectorZeroUpper64(res);
}
context.Copy(GetVec(op.Rd), res);
}
else
{
EmitRev_V(context, containerSize: 2);
}
}
public static void Rev64_V(ArmEmitterContext context)
{
if (Optimizations.UseSsse3)
{
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
Operand n = GetVec(op.Rn);
Operand mask;
if (op.Size == 0)
{
const long maskE0 = 00L << 56 | 01L << 48 | 02L << 40 | 03L << 32 | 04L << 24 | 05L << 16 | 06L << 8 | 07L << 0;
const long maskE1 = 08L << 56 | 09L << 48 | 10L << 40 | 11L << 32 | 12L << 24 | 13L << 16 | 14L << 8 | 15L << 0;
mask = X86GetScalar(context, maskE0);
mask = EmitVectorInsert(context, mask, Const(maskE1), 1, 3);
}
else if (op.Size == 1)
{
const long maskE0 = 01L << 56 | 00L << 48 | 03L << 40 | 02L << 32 | 05L << 24 | 04L << 16 | 07L << 8 | 06L << 0;
const long maskE1 = 09L << 56 | 08L << 48 | 11L << 40 | 10L << 32 | 13L << 24 | 12L << 16 | 15L << 8 | 14L << 0;
mask = X86GetScalar(context, maskE0);
mask = EmitVectorInsert(context, mask, Const(maskE1), 1, 3);
}
else /* if (op.Size == 2) */
{
const long maskE0 = 03L << 56 | 02L << 48 | 01L << 40 | 00L << 32 | 07L << 24 | 06L << 16 | 05L << 8 | 04L << 0;
const long maskE1 = 11L << 56 | 10L << 48 | 09L << 40 | 08L << 32 | 15L << 24 | 14L << 16 | 13L << 8 | 12L << 0;
mask = X86GetScalar(context, maskE0);
mask = EmitVectorInsert(context, mask, Const(maskE1), 1, 3);
}
Operand res = context.AddIntrinsic(Intrinsic.X86Pshufb, n, mask);
if (op.RegisterSize == RegisterSize.Simd64)
{
res = context.VectorZeroUpper64(res);
}
context.Copy(GetVec(op.Rd), res);
}
else
{
EmitRev_V(context, containerSize: 3);
}
}
private static void EmitRev_V(ArmEmitterContext context, int containerSize)
{
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
Operand res = context.VectorZero();
int elems = op.GetBytesCount() >> op.Size;
int containerMask = (1 << (containerSize - op.Size)) - 1;
for (int index = 0; index < elems; index++)
{
int revIndex = index ^ containerMask;
Operand ne = EmitVectorExtractZx(context, op.Rn, revIndex, op.Size);
res = EmitVectorInsert(context, res, ne, index, op.Size);
}
context.Copy(GetVec(op.Rd), res);
}
}
}

View File

@@ -1,221 +0,0 @@
using ARMeilleure.Decoders;
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation;
using static ARMeilleure.Instructions.InstEmitHelper;
using static ARMeilleure.Instructions.InstEmitSimdHelper;
using static ARMeilleure.Instructions.InstEmitSimdHelper32;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
namespace ARMeilleure.Instructions
{
static partial class InstEmit32
{
public static void Vand_I(ArmEmitterContext context)
{
if (Optimizations.UseSse2)
{
EmitVectorBinaryOpSimd32(context, (n, m) => context.AddIntrinsic(Intrinsic.X86Pand, n, m));
}
else
{
EmitVectorBinaryOpZx32(context, (op1, op2) => context.BitwiseAnd(op1, op2));
}
}
public static void Vbic_I(ArmEmitterContext context)
{
if (Optimizations.UseSse2)
{
EmitVectorBinaryOpSimd32(context, (n, m) => context.AddIntrinsic(Intrinsic.X86Pandn, m, n));
}
else
{
EmitVectorBinaryOpZx32(context, (op1, op2) => context.BitwiseAnd(op1, context.BitwiseNot(op2)));
}
}
public static void Vbic_II(ArmEmitterContext context)
{
OpCode32SimdImm op = (OpCode32SimdImm)context.CurrOp;
long immediate = op.Immediate;
// Replicate fields to fill the 64-bits, if size is < 64-bits.
switch (op.Size)
{
case 0: immediate *= 0x0101010101010101L; break;
case 1: immediate *= 0x0001000100010001L; break;
case 2: immediate *= 0x0000000100000001L; break;
}
Operand imm = Const(immediate);
Operand res = GetVecA32(op.Qd);
if (op.Q)
{
for (int elem = 0; elem < 2; elem++)
{
Operand de = EmitVectorExtractZx(context, op.Qd, elem, 3);
res = EmitVectorInsert(context, res, context.BitwiseAnd(de, context.BitwiseNot(imm)), elem, 3);
}
}
else
{
Operand de = EmitVectorExtractZx(context, op.Qd, op.Vd & 1, 3);
res = EmitVectorInsert(context, res, context.BitwiseAnd(de, context.BitwiseNot(imm)), op.Vd & 1, 3);
}
context.Copy(GetVecA32(op.Qd), res);
}
public static void Vbif(ArmEmitterContext context)
{
EmitBifBit(context, true);
}
public static void Vbit(ArmEmitterContext context)
{
EmitBifBit(context, false);
}
public static void Vbsl(ArmEmitterContext context)
{
if (Optimizations.UseSse2)
{
EmitVectorTernaryOpSimd32(context, (d, n, m) =>
{
Operand res = context.AddIntrinsic(Intrinsic.X86Pxor, n, m);
res = context.AddIntrinsic(Intrinsic.X86Pand, res, d);
return context.AddIntrinsic(Intrinsic.X86Pxor, res, m);
});
}
else
{
EmitVectorTernaryOpZx32(context, (op1, op2, op3) =>
{
return context.BitwiseExclusiveOr(
context.BitwiseAnd(op1,
context.BitwiseExclusiveOr(op2, op3)), op3);
});
}
}
public static void Veor_I(ArmEmitterContext context)
{
if (Optimizations.UseSse2)
{
EmitVectorBinaryOpSimd32(context, (n, m) => context.AddIntrinsic(Intrinsic.X86Pxor, n, m));
}
else
{
EmitVectorBinaryOpZx32(context, (op1, op2) => context.BitwiseExclusiveOr(op1, op2));
}
}
public static void Vorn_I(ArmEmitterContext context)
{
if (Optimizations.UseSse2)
{
Operand mask = context.VectorOne();
EmitVectorBinaryOpSimd32(context, (n, m) =>
{
m = context.AddIntrinsic(Intrinsic.X86Pandn, m, mask);
return context.AddIntrinsic(Intrinsic.X86Por, n, m);
});
}
else
{
EmitVectorBinaryOpZx32(context, (op1, op2) => context.BitwiseOr(op1, context.BitwiseNot(op2)));
}
}
public static void Vorr_I(ArmEmitterContext context)
{
if (Optimizations.UseSse2)
{
EmitVectorBinaryOpSimd32(context, (n, m) => context.AddIntrinsic(Intrinsic.X86Por, n, m));
}
else
{
EmitVectorBinaryOpZx32(context, (op1, op2) => context.BitwiseOr(op1, op2));
}
}
public static void Vorr_II(ArmEmitterContext context)
{
OpCode32SimdImm op = (OpCode32SimdImm)context.CurrOp;
long immediate = op.Immediate;
// Replicate fields to fill the 64-bits, if size is < 64-bits.
switch (op.Size)
{
case 0: immediate *= 0x0101010101010101L; break;
case 1: immediate *= 0x0001000100010001L; break;
case 2: immediate *= 0x0000000100000001L; break;
}
Operand imm = Const(immediate);
Operand res = GetVecA32(op.Qd);
if (op.Q)
{
for (int elem = 0; elem < 2; elem++)
{
Operand de = EmitVectorExtractZx(context, op.Qd, elem, 3);
res = EmitVectorInsert(context, res, context.BitwiseOr(de, imm), elem, 3);
}
}
else
{
Operand de = EmitVectorExtractZx(context, op.Qd, op.Vd & 1, 3);
res = EmitVectorInsert(context, res, context.BitwiseOr(de, imm), op.Vd & 1, 3);
}
context.Copy(GetVecA32(op.Qd), res);
}
public static void Vtst(ArmEmitterContext context)
{
EmitVectorBinaryOpZx32(context, (op1, op2) =>
{
Operand isZero = context.ICompareEqual(context.BitwiseAnd(op1, op2), Const(0));
return context.ConditionalSelect(isZero, Const(0), Const(-1));
});
}
private static void EmitBifBit(ArmEmitterContext context, bool notRm)
{
OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;
if (Optimizations.UseSse2)
{
EmitVectorTernaryOpSimd32(context, (d, n, m) =>
{
Operand res = context.AddIntrinsic(Intrinsic.X86Pxor, n, d);
res = context.AddIntrinsic((notRm) ? Intrinsic.X86Pandn : Intrinsic.X86Pand, m, res);
return context.AddIntrinsic(Intrinsic.X86Pxor, d, res);
});
}
else
{
EmitVectorTernaryOpZx32(context, (d, n, m) =>
{
if (notRm)
{
m = context.BitwiseNot(m);
}
return context.BitwiseExclusiveOr(
context.BitwiseAnd(m,
context.BitwiseExclusiveOr(d, n)), d);
});
}
}
}
}

View File

@@ -1,595 +0,0 @@
using ARMeilleure.Decoders;
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation;
using System;
using static ARMeilleure.Instructions.InstEmitHelper;
using static ARMeilleure.Instructions.InstEmitSimdHelper;
using static ARMeilleure.Instructions.InstEmitSimdHelper32;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
namespace ARMeilleure.Instructions
{
static partial class InstEmit32
{
#region "Masks"
// Same as InstEmitSimdMove, as the instructions do the same thing.
private static readonly long[] _masksE0_Uzp = new long[]
{
13L << 56 | 09L << 48 | 05L << 40 | 01L << 32 | 12L << 24 | 08L << 16 | 04L << 8 | 00L << 0,
11L << 56 | 10L << 48 | 03L << 40 | 02L << 32 | 09L << 24 | 08L << 16 | 01L << 8 | 00L << 0
};
private static readonly long[] _masksE1_Uzp = new long[]
{
15L << 56 | 11L << 48 | 07L << 40 | 03L << 32 | 14L << 24 | 10L << 16 | 06L << 8 | 02L << 0,
15L << 56 | 14L << 48 | 07L << 40 | 06L << 32 | 13L << 24 | 12L << 16 | 05L << 8 | 04L << 0
};
#endregion
public static void Vmov_I(ArmEmitterContext context)
{
EmitVectorImmUnaryOp32(context, (op1) => op1);
}
public static void Vmvn_I(ArmEmitterContext context)
{
if (Optimizations.UseSse2)
{
EmitVectorUnaryOpSimd32(context, (op1) =>
{
Operand mask = X86GetAllElements(context, -1L);
return context.AddIntrinsic(Intrinsic.X86Pandn, op1, mask);
});
}
else
{
EmitVectorUnaryOpZx32(context, (op1) => context.BitwiseNot(op1));
}
}
public static void Vmvn_II(ArmEmitterContext context)
{
EmitVectorImmUnaryOp32(context, (op1) => context.BitwiseNot(op1));
}
public static void Vmov_GS(ArmEmitterContext context)
{
OpCode32SimdMovGp op = (OpCode32SimdMovGp)context.CurrOp;
Operand vec = GetVecA32(op.Vn >> 2);
if (op.Op == 1)
{
// To general purpose.
Operand value = context.VectorExtract(OperandType.I32, vec, op.Vn & 0x3);
SetIntA32(context, op.Rt, value);
}
else
{
// From general purpose.
Operand value = GetIntA32(context, op.Rt);
context.Copy(vec, context.VectorInsert(vec, value, op.Vn & 0x3));
}
}
public static void Vmov_G1(ArmEmitterContext context)
{
OpCode32SimdMovGpElem op = (OpCode32SimdMovGpElem)context.CurrOp;
int index = op.Index + ((op.Vd & 1) << (3 - op.Size));
if (op.Op == 1)
{
// To general purpose.
Operand value = EmitVectorExtract32(context, op.Vd >> 1, index, op.Size, !op.U);
SetIntA32(context, op.Rt, value);
}
else
{
// From general purpose.
Operand vec = GetVecA32(op.Vd >> 1);
Operand value = GetIntA32(context, op.Rt);
context.Copy(vec, EmitVectorInsert(context, vec, value, index, op.Size));
}
}
public static void Vmov_G2(ArmEmitterContext context)
{
OpCode32SimdMovGpDouble op = (OpCode32SimdMovGpDouble)context.CurrOp;
Operand vec = GetVecA32(op.Vm >> 2);
int vm1 = op.Vm + 1;
bool sameOwnerVec = (op.Vm >> 2) == (vm1 >> 2);
Operand vec2 = sameOwnerVec ? vec : GetVecA32(vm1 >> 2);
if (op.Op == 1)
{
// To general purpose.
Operand lowValue = context.VectorExtract(OperandType.I32, vec, op.Vm & 3);
SetIntA32(context, op.Rt, lowValue);
Operand highValue = context.VectorExtract(OperandType.I32, vec2, vm1 & 3);
SetIntA32(context, op.Rt2, highValue);
}
else
{
// From general purpose.
Operand lowValue = GetIntA32(context, op.Rt);
Operand resultVec = context.VectorInsert(vec, lowValue, op.Vm & 3);
Operand highValue = GetIntA32(context, op.Rt2);
if (sameOwnerVec)
{
context.Copy(vec, context.VectorInsert(resultVec, highValue, vm1 & 3));
}
else
{
context.Copy(vec, resultVec);
context.Copy(vec2, context.VectorInsert(vec2, highValue, vm1 & 3));
}
}
}
public static void Vmov_GD(ArmEmitterContext context)
{
OpCode32SimdMovGpDouble op = (OpCode32SimdMovGpDouble)context.CurrOp;
Operand vec = GetVecA32(op.Vm >> 1);
if (op.Op == 1)
{
// To general purpose.
Operand value = context.VectorExtract(OperandType.I64, vec, op.Vm & 1);
SetIntA32(context, op.Rt, context.ConvertI64ToI32(value));
SetIntA32(context, op.Rt2, context.ConvertI64ToI32(context.ShiftRightUI(value, Const(32))));
}
else
{
// From general purpose.
Operand lowValue = GetIntA32(context, op.Rt);
Operand highValue = GetIntA32(context, op.Rt2);
Operand value = context.BitwiseOr(
context.ZeroExtend32(OperandType.I64, lowValue),
context.ShiftLeft(context.ZeroExtend32(OperandType.I64, highValue), Const(32)));
context.Copy(vec, context.VectorInsert(vec, value, op.Vm & 1));
}
}
public static void Vmovl(ArmEmitterContext context)
{
OpCode32SimdLong op = (OpCode32SimdLong)context.CurrOp;
Operand res = context.VectorZero();
int elems = op.GetBytesCount() >> op.Size;
for (int index = 0; index < elems; index++)
{
Operand me = EmitVectorExtract32(context, op.Qm, op.Im + index, op.Size, !op.U);
if (op.Size == 2)
{
if (op.U)
{
me = context.ZeroExtend32(OperandType.I64, me);
}
else
{
me = context.SignExtend32(OperandType.I64, me);
}
}
res = EmitVectorInsert(context, res, me, index, op.Size + 1);
}
context.Copy(GetVecA32(op.Qd), res);
}
public static void Vtbl(ArmEmitterContext context)
{
OpCode32SimdTbl op = (OpCode32SimdTbl)context.CurrOp;
bool extension = op.Opc == 1;
int length = op.Length + 1;
if (Optimizations.UseSsse3)
{
Operand d = GetVecA32(op.Qd);
Operand m = EmitMoveDoubleWordToSide(context, GetVecA32(op.Qm), op.Vm, 0);
Operand res;
Operand mask = X86GetAllElements(context, 0x0707070707070707L);
// Fast path for single register table.
{
Operand n = EmitMoveDoubleWordToSide(context, GetVecA32(op.Qn), op.Vn, 0);
Operand mMask = context.AddIntrinsic(Intrinsic.X86Pcmpgtb, m, mask);
mMask = context.AddIntrinsic(Intrinsic.X86Por, mMask, m);
res = context.AddIntrinsic(Intrinsic.X86Pshufb, n, mMask);
}
for (int index = 1; index < length; index++)
{
int newVn = (op.Vn + index) & 0x1F;
(int qn, int ind) = GetQuadwordAndSubindex(newVn, op.RegisterSize);
Operand ni = EmitMoveDoubleWordToSide(context, GetVecA32(qn), newVn, 0);
Operand idxMask = X86GetAllElements(context, 0x0808080808080808L * index);
Operand mSubMask = context.AddIntrinsic(Intrinsic.X86Psubb, m, idxMask);
Operand mMask = context.AddIntrinsic(Intrinsic.X86Pcmpgtb, mSubMask, mask);
mMask = context.AddIntrinsic(Intrinsic.X86Por, mMask, mSubMask);
Operand res2 = context.AddIntrinsic(Intrinsic.X86Pshufb, ni, mMask);
res = context.AddIntrinsic(Intrinsic.X86Por, res, res2);
}
if (extension)
{
Operand idxMask = X86GetAllElements(context, (0x0808080808080808L * length) - 0x0101010101010101L);
Operand zeroMask = context.VectorZero();
Operand mPosMask = context.AddIntrinsic(Intrinsic.X86Pcmpgtb, m, idxMask);
Operand mNegMask = context.AddIntrinsic(Intrinsic.X86Pcmpgtb, zeroMask, m);
Operand mMask = context.AddIntrinsic(Intrinsic.X86Por, mPosMask, mNegMask);
Operand dMask = context.AddIntrinsic(Intrinsic.X86Pand, EmitMoveDoubleWordToSide(context, d, op.Vd, 0), mMask);
res = context.AddIntrinsic(Intrinsic.X86Por, res, dMask);
}
res = EmitMoveDoubleWordToSide(context, res, 0, op.Vd);
context.Copy(d, EmitDoubleWordInsert(context, d, res, op.Vd));
}
else
{
int elems = op.GetBytesCount() >> op.Size;
(int Qx, int Ix)[] tableTuples = new (int, int)[length];
for (int i = 0; i < length; i++)
{
tableTuples[i] = GetQuadwordAndSubindex(op.Vn + i, op.RegisterSize);
}
int byteLength = length * 8;
Operand res = GetVecA32(op.Qd);
Operand m = GetVecA32(op.Qm);
for (int index = 0; index < elems; index++)
{
Operand selectedIndex = context.ZeroExtend8(OperandType.I32, context.VectorExtract8(m, index + op.Im));
Operand inRange = context.ICompareLess(selectedIndex, Const(byteLength));
Operand elemRes = default; // Note: This is I64 for ease of calculation.
// TODO: Branching rather than conditional select.
// Get indexed byte.
// To simplify (ha) the il, we get bytes from every vector and use a nested conditional select to choose the right result.
// This does have to extract `length` times for every element but certainly not as bad as it could be.
// Which vector number is the index on.
Operand vecIndex = context.ShiftRightUI(selectedIndex, Const(3));
// What should we shift by to extract it.
Operand subVecIndexShift = context.ShiftLeft(context.BitwiseAnd(selectedIndex, Const(7)), Const(3));
for (int i = 0; i < length; i++)
{
(int qx, int ix) = tableTuples[i];
// Get the whole vector, we'll get a byte out of it.
Operand lookupResult;
if (qx == op.Qd)
{
// Result contains the current state of the vector.
lookupResult = context.VectorExtract(OperandType.I64, res, ix);
}
else
{
lookupResult = EmitVectorExtract32(context, qx, ix, 3, false); // I64
}
lookupResult = context.ShiftRightUI(lookupResult, subVecIndexShift); // Get the relevant byte from this vector.
if (i == 0)
{
elemRes = lookupResult; // First result is always default.
}
else
{
Operand isThisElem = context.ICompareEqual(vecIndex, Const(i));
elemRes = context.ConditionalSelect(isThisElem, lookupResult, elemRes);
}
}
Operand fallback = (extension) ? context.ZeroExtend32(OperandType.I64, EmitVectorExtract32(context, op.Qd, index + op.Id, 0, false)) : Const(0L);
res = EmitVectorInsert(context, res, context.ConditionalSelect(inRange, elemRes, fallback), index + op.Id, 0);
}
context.Copy(GetVecA32(op.Qd), res);
}
}
public static void Vtrn(ArmEmitterContext context)
{
OpCode32SimdCmpZ op = (OpCode32SimdCmpZ)context.CurrOp;
if (Optimizations.UseSsse3)
{
EmitVectorShuffleOpSimd32(context, (m, d) =>
{
Operand mask = default;
if (op.Size < 3)
{
long maskE0 = EvenMasks[op.Size];
long maskE1 = OddMasks[op.Size];
mask = X86GetScalar(context, maskE0);
mask = EmitVectorInsert(context, mask, Const(maskE1), 1, 3);
}
if (op.Size < 3)
{
d = context.AddIntrinsic(Intrinsic.X86Pshufb, d, mask);
m = context.AddIntrinsic(Intrinsic.X86Pshufb, m, mask);
}
Operand resD = context.AddIntrinsic(X86PunpcklInstruction[op.Size], d, m);
Operand resM = context.AddIntrinsic(X86PunpckhInstruction[op.Size], d, m);
return (resM, resD);
});
}
else
{
int elems = op.GetBytesCount() >> op.Size;
int pairs = elems >> 1;
bool overlap = op.Qm == op.Qd;
Operand resD = GetVecA32(op.Qd);
Operand resM = GetVecA32(op.Qm);
for (int index = 0; index < pairs; index++)
{
int pairIndex = index << 1;
Operand d2 = EmitVectorExtract32(context, op.Qd, pairIndex + 1 + op.Id, op.Size, false);
Operand m1 = EmitVectorExtract32(context, op.Qm, pairIndex + op.Im, op.Size, false);
resD = EmitVectorInsert(context, resD, m1, pairIndex + 1 + op.Id, op.Size);
if (overlap)
{
resM = resD;
}
resM = EmitVectorInsert(context, resM, d2, pairIndex + op.Im, op.Size);
if (overlap)
{
resD = resM;
}
}
context.Copy(GetVecA32(op.Qd), resD);
if (!overlap)
{
context.Copy(GetVecA32(op.Qm), resM);
}
}
}
public static void Vzip(ArmEmitterContext context)
{
OpCode32SimdCmpZ op = (OpCode32SimdCmpZ)context.CurrOp;
if (Optimizations.UseSse2)
{
EmitVectorShuffleOpSimd32(context, (m, d) =>
{
if (op.RegisterSize == RegisterSize.Simd128)
{
Operand resD = context.AddIntrinsic(X86PunpcklInstruction[op.Size], d, m);
Operand resM = context.AddIntrinsic(X86PunpckhInstruction[op.Size], d, m);
return (resM, resD);
}
else
{
Operand res = context.AddIntrinsic(X86PunpcklInstruction[op.Size], d, m);
Operand resD = context.AddIntrinsic(Intrinsic.X86Punpcklqdq, res, context.VectorZero());
Operand resM = context.AddIntrinsic(Intrinsic.X86Punpckhqdq, res, context.VectorZero());
return (resM, resD);
}
});
}
else
{
int elems = op.GetBytesCount() >> op.Size;
int pairs = elems >> 1;
bool overlap = op.Qm == op.Qd;
Operand resD = GetVecA32(op.Qd);
Operand resM = GetVecA32(op.Qm);
for (int index = 0; index < pairs; index++)
{
int pairIndex = index << 1;
Operand dRowD = EmitVectorExtract32(context, op.Qd, index + op.Id, op.Size, false);
Operand mRowD = EmitVectorExtract32(context, op.Qm, index + op.Im, op.Size, false);
Operand dRowM = EmitVectorExtract32(context, op.Qd, index + op.Id + pairs, op.Size, false);
Operand mRowM = EmitVectorExtract32(context, op.Qm, index + op.Im + pairs, op.Size, false);
resD = EmitVectorInsert(context, resD, dRowD, pairIndex + op.Id, op.Size);
resD = EmitVectorInsert(context, resD, mRowD, pairIndex + 1 + op.Id, op.Size);
if (overlap)
{
resM = resD;
}
resM = EmitVectorInsert(context, resM, dRowM, pairIndex + op.Im, op.Size);
resM = EmitVectorInsert(context, resM, mRowM, pairIndex + 1 + op.Im, op.Size);
if (overlap)
{
resD = resM;
}
}
context.Copy(GetVecA32(op.Qd), resD);
if (!overlap)
{
context.Copy(GetVecA32(op.Qm), resM);
}
}
}
public static void Vuzp(ArmEmitterContext context)
{
OpCode32SimdCmpZ op = (OpCode32SimdCmpZ)context.CurrOp;
if (Optimizations.UseSsse3)
{
EmitVectorShuffleOpSimd32(context, (m, d) =>
{
if (op.RegisterSize == RegisterSize.Simd128)
{
Operand mask = default;
if (op.Size < 3)
{
long maskE0 = EvenMasks[op.Size];
long maskE1 = OddMasks[op.Size];
mask = X86GetScalar(context, maskE0);
mask = EmitVectorInsert(context, mask, Const(maskE1), 1, 3);
d = context.AddIntrinsic(Intrinsic.X86Pshufb, d, mask);
m = context.AddIntrinsic(Intrinsic.X86Pshufb, m, mask);
}
Operand resD = context.AddIntrinsic(Intrinsic.X86Punpcklqdq, d, m);
Operand resM = context.AddIntrinsic(Intrinsic.X86Punpckhqdq, d, m);
return (resM, resD);
}
else
{
Intrinsic punpcklInst = X86PunpcklInstruction[op.Size];
Operand res = context.AddIntrinsic(punpcklInst, d, m);
if (op.Size < 2)
{
long maskE0 = _masksE0_Uzp[op.Size];
long maskE1 = _masksE1_Uzp[op.Size];
Operand mask = X86GetScalar(context, maskE0);
mask = EmitVectorInsert(context, mask, Const(maskE1), 1, 3);
res = context.AddIntrinsic(Intrinsic.X86Pshufb, res, mask);
}
Operand resD = context.AddIntrinsic(Intrinsic.X86Punpcklqdq, res, context.VectorZero());
Operand resM = context.AddIntrinsic(Intrinsic.X86Punpckhqdq, res, context.VectorZero());
return (resM, resD);
}
});
}
else
{
int elems = op.GetBytesCount() >> op.Size;
int pairs = elems >> 1;
bool overlap = op.Qm == op.Qd;
Operand resD = GetVecA32(op.Qd);
Operand resM = GetVecA32(op.Qm);
for (int index = 0; index < elems; index++)
{
Operand dIns, mIns;
if (index >= pairs)
{
int pairIndex = index - pairs;
dIns = EmitVectorExtract32(context, op.Qm, (pairIndex << 1) + op.Im, op.Size, false);
mIns = EmitVectorExtract32(context, op.Qm, ((pairIndex << 1) | 1) + op.Im, op.Size, false);
}
else
{
dIns = EmitVectorExtract32(context, op.Qd, (index << 1) + op.Id, op.Size, false);
mIns = EmitVectorExtract32(context, op.Qd, ((index << 1) | 1) + op.Id, op.Size, false);
}
resD = EmitVectorInsert(context, resD, dIns, index + op.Id, op.Size);
if (overlap)
{
resM = resD;
}
resM = EmitVectorInsert(context, resM, mIns, index + op.Im, op.Size);
if (overlap)
{
resD = resM;
}
}
context.Copy(GetVecA32(op.Qd), resD);
if (!overlap)
{
context.Copy(GetVecA32(op.Qm), resM);
}
}
}
private static void EmitVectorShuffleOpSimd32(ArmEmitterContext context, Func<Operand, Operand, (Operand, Operand)> shuffleFunc)
{
OpCode32Simd op = (OpCode32Simd)context.CurrOp;
Operand m = GetVecA32(op.Qm);
Operand d = GetVecA32(op.Qd);
Operand initialM = m;
Operand initialD = d;
if (!op.Q) // Register swap: move relevant doubleword to side 0, for consistency.
{
m = EmitMoveDoubleWordToSide(context, m, op.Vm, 0);
d = EmitMoveDoubleWordToSide(context, d, op.Vd, 0);
}
(Operand resM, Operand resD) = shuffleFunc(m, d);
bool overlap = op.Qm == op.Qd;
if (!op.Q) // Register insert.
{
resM = EmitDoubleWordInsert(context, initialM, EmitMoveDoubleWordToSide(context, resM, 0, op.Vm), op.Vm);
resD = EmitDoubleWordInsert(context, overlap ? resM : initialD, EmitMoveDoubleWordToSide(context, resD, 0, op.Vd), op.Vd);
}
if (!overlap)
{
context.Copy(initialM, resM);
}
context.Copy(initialD, resD);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,211 +0,0 @@
using ARMeilleure.Decoders;
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.State;
using ARMeilleure.Translation;
using System;
using System.Reflection;
using static ARMeilleure.Instructions.InstEmitHelper;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
namespace ARMeilleure.Instructions
{
static partial class InstEmit
{
private const int DczSizeLog2 = 4; // Log2 size in words
public const int DczSizeInBytes = 4 << DczSizeLog2;
public static void Isb(ArmEmitterContext context)
{
// Execute as no-op.
}
public static void Mrs(ArmEmitterContext context)
{
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
MethodInfo info;
switch (GetPackedId(op))
{
case 0b11_011_0000_0000_001: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCtrEl0)); break;
case 0b11_011_0000_0000_111: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetDczidEl0)); break;
case 0b11_011_0100_0010_000: EmitGetNzcv(context); return;
case 0b11_011_0100_0100_000: EmitGetFpcr(context); return;
case 0b11_011_0100_0100_001: EmitGetFpsr(context); return;
case 0b11_011_1101_0000_010: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetTpidrEl0)); break;
case 0b11_011_1101_0000_011: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetTpidrroEl0)); break;
case 0b11_011_1110_0000_000: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntfrqEl0)); break;
case 0b11_011_1110_0000_001: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntpctEl0)); break;
case 0b11_011_1110_0000_010: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntvctEl0)); break;
default: throw new NotImplementedException($"Unknown MRS 0x{op.RawOpCode:X8} at 0x{op.Address:X16}.");
}
SetIntOrZR(context, op.Rt, context.Call(info));
}
public static void Msr(ArmEmitterContext context)
{
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
MethodInfo info;
switch (GetPackedId(op))
{
case 0b11_011_0100_0010_000: EmitSetNzcv(context); return;
case 0b11_011_0100_0100_000: EmitSetFpcr(context); return;
case 0b11_011_0100_0100_001: EmitSetFpsr(context); return;
case 0b11_011_1101_0000_010: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetTpidrEl0)); break;
default: throw new NotImplementedException($"Unknown MSR 0x{op.RawOpCode:X8} at 0x{op.Address:X16}.");
}
context.Call(info, GetIntOrZR(context, op.Rt));
}
public static void Nop(ArmEmitterContext context)
{
// Do nothing.
}
public static void Sys(ArmEmitterContext context)
{
// This instruction is used to do some operations on the CPU like cache invalidation,
// address translation and the like.
// We treat it as no-op here since we don't have any cache being emulated anyway.
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
switch (GetPackedId(op))
{
case 0b11_011_0111_0100_001:
{
// DC ZVA
Operand t = GetIntOrZR(context, op.Rt);
for (long offset = 0; offset < DczSizeInBytes; offset += 8)
{
Operand address = context.Add(t, Const(offset));
InstEmitMemoryHelper.EmitStore(context, address, RegisterConsts.ZeroIndex, 3);
}
break;
}
// No-op
case 0b11_011_0111_1110_001: // DC CIVAC
break;
case 0b11_011_0111_0101_001: // IC IVAU
Operand target = Register(op.Rt, RegisterType.Integer, OperandType.I64);
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.InvalidateCacheLine)), target);
break;
}
}
private static int GetPackedId(OpCodeSystem op)
{
int id;
id = op.Op2 << 0;
id |= op.CRm << 3;
id |= op.CRn << 7;
id |= op.Op1 << 11;
id |= op.Op0 << 14;
return id;
}
private static void EmitGetNzcv(ArmEmitterContext context)
{
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
Operand nzcv = context.ShiftLeft(GetFlag(PState.VFlag), Const((int)PState.VFlag));
nzcv = context.BitwiseOr(nzcv, context.ShiftLeft(GetFlag(PState.CFlag), Const((int)PState.CFlag)));
nzcv = context.BitwiseOr(nzcv, context.ShiftLeft(GetFlag(PState.ZFlag), Const((int)PState.ZFlag)));
nzcv = context.BitwiseOr(nzcv, context.ShiftLeft(GetFlag(PState.NFlag), Const((int)PState.NFlag)));
SetIntOrZR(context, op.Rt, nzcv);
}
private static void EmitGetFpcr(ArmEmitterContext context)
{
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
Operand fpcr = Const(0);
for (int flag = 0; flag < RegisterConsts.FpFlagsCount; flag++)
{
if (FPCR.Mask.HasFlag((FPCR)(1u << flag)))
{
fpcr = context.BitwiseOr(fpcr, context.ShiftLeft(GetFpFlag((FPState)flag), Const(flag)));
}
}
SetIntOrZR(context, op.Rt, fpcr);
}
private static void EmitGetFpsr(ArmEmitterContext context)
{
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
Operand fpsr = Const(0);
for (int flag = 0; flag < RegisterConsts.FpFlagsCount; flag++)
{
if (FPSR.Mask.HasFlag((FPSR)(1u << flag)))
{
fpsr = context.BitwiseOr(fpsr, context.ShiftLeft(GetFpFlag((FPState)flag), Const(flag)));
}
}
SetIntOrZR(context, op.Rt, fpsr);
}
private static void EmitSetNzcv(ArmEmitterContext context)
{
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
Operand nzcv = GetIntOrZR(context, op.Rt);
nzcv = context.ConvertI64ToI32(nzcv);
SetFlag(context, PState.VFlag, context.BitwiseAnd(context.ShiftRightUI(nzcv, Const((int)PState.VFlag)), Const(1)));
SetFlag(context, PState.CFlag, context.BitwiseAnd(context.ShiftRightUI(nzcv, Const((int)PState.CFlag)), Const(1)));
SetFlag(context, PState.ZFlag, context.BitwiseAnd(context.ShiftRightUI(nzcv, Const((int)PState.ZFlag)), Const(1)));
SetFlag(context, PState.NFlag, context.BitwiseAnd(context.ShiftRightUI(nzcv, Const((int)PState.NFlag)), Const(1)));
}
private static void EmitSetFpcr(ArmEmitterContext context)
{
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
Operand fpcr = GetIntOrZR(context, op.Rt);
fpcr = context.ConvertI64ToI32(fpcr);
for (int flag = 0; flag < RegisterConsts.FpFlagsCount; flag++)
{
if (FPCR.Mask.HasFlag((FPCR)(1u << flag)))
{
SetFpFlag(context, (FPState)flag, context.BitwiseAnd(context.ShiftRightUI(fpcr, Const(flag)), Const(1)));
}
}
}
private static void EmitSetFpsr(ArmEmitterContext context)
{
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
Operand fpsr = GetIntOrZR(context, op.Rt);
fpsr = context.ConvertI64ToI32(fpsr);
for (int flag = 0; flag < RegisterConsts.FpFlagsCount; flag++)
{
if (FPSR.Mask.HasFlag((FPSR)(1u << flag)))
{
SetFpFlag(context, (FPState)flag, context.BitwiseAnd(context.ShiftRightUI(fpsr, Const(flag)), Const(1)));
}
}
}
}
}

View File

@@ -1,326 +0,0 @@
using ARMeilleure.Decoders;
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.State;
using ARMeilleure.Translation;
using System;
using System.Reflection;
using static ARMeilleure.Instructions.InstEmitHelper;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
namespace ARMeilleure.Instructions
{
static partial class InstEmit32
{
public static void Mcr(ArmEmitterContext context)
{
OpCode32System op = (OpCode32System)context.CurrOp;
if (op.Coproc != 15 || op.Opc1 != 0)
{
InstEmit.Und(context);
return;
}
MethodInfo info;
switch (op.CRn)
{
case 13: // Process and Thread Info.
if (op.CRm != 0)
{
throw new NotImplementedException($"Unknown MRC CRm 0x{op.CRm:X} at 0x{op.Address:X} (0x{op.RawOpCode:X}).");
}
switch (op.Opc2)
{
case 2:
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetTpidrEl032)); break;
default:
throw new NotImplementedException($"Unknown MRC Opc2 0x{op.Opc2:X} at 0x{op.Address:X} (0x{op.RawOpCode:X}).");
}
break;
case 7:
switch (op.CRm) // Cache and Memory barrier.
{
case 10:
switch (op.Opc2)
{
case 5: // Data Memory Barrier Register.
return; // No-op.
default:
throw new NotImplementedException($"Unknown MRC Opc2 0x{op.Opc2:X16} at 0x{op.Address:X16} (0x{op.RawOpCode:X}).");
}
default:
throw new NotImplementedException($"Unknown MRC CRm 0x{op.CRm:X16} at 0x{op.Address:X16} (0x{op.RawOpCode:X}).");
}
default:
throw new NotImplementedException($"Unknown MRC 0x{op.RawOpCode:X8} at 0x{op.Address:X16}.");
}
context.Call(info, GetIntA32(context, op.Rt));
}
public static void Mrc(ArmEmitterContext context)
{
OpCode32System op = (OpCode32System)context.CurrOp;
if (op.Coproc != 15 || op.Opc1 != 0)
{
InstEmit.Und(context);
return;
}
MethodInfo info;
switch (op.CRn)
{
case 13: // Process and Thread Info.
if (op.CRm != 0)
{
throw new NotImplementedException($"Unknown MRC CRm 0x{op.CRm:X} at 0x{op.Address:X} (0x{op.RawOpCode:X}).");
}
switch (op.Opc2)
{
case 2:
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetTpidrEl032)); break;
case 3:
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetTpidr32)); break;
default:
throw new NotImplementedException($"Unknown MRC Opc2 0x{op.Opc2:X} at 0x{op.Address:X} (0x{op.RawOpCode:X}).");
}
break;
default:
throw new NotImplementedException($"Unknown MRC 0x{op.RawOpCode:X} at 0x{op.Address:X}.");
}
if (op.Rt == RegisterAlias.Aarch32Pc)
{
// Special behavior: copy NZCV flags into APSR.
EmitSetNzcv(context, context.Call(info));
return;
}
else
{
SetIntA32(context, op.Rt, context.Call(info));
}
}
public static void Mrrc(ArmEmitterContext context)
{
OpCode32System op = (OpCode32System)context.CurrOp;
if (op.Coproc != 15)
{
InstEmit.Und(context);
return;
}
int opc = op.MrrcOp;
MethodInfo info;
switch (op.CRm)
{
case 14: // Timer.
switch (opc)
{
case 0:
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntpctEl0)); break;
default:
throw new NotImplementedException($"Unknown MRRC Opc1 0x{opc:X} at 0x{op.Address:X} (0x{op.RawOpCode:X}).");
}
break;
default:
throw new NotImplementedException($"Unknown MRRC 0x{op.RawOpCode:X} at 0x{op.Address:X}.");
}
Operand result = context.Call(info);
SetIntA32(context, op.Rt, context.ConvertI64ToI32(result));
SetIntA32(context, op.CRn, context.ConvertI64ToI32(context.ShiftRightUI(result, Const(32))));
}
public static void Mrs(ArmEmitterContext context)
{
OpCode32Mrs op = (OpCode32Mrs)context.CurrOp;
if (op.R)
{
throw new NotImplementedException("SPSR");
}
else
{
Operand spsr = context.ShiftLeft(GetFlag(PState.VFlag), Const((int)PState.VFlag));
spsr = context.BitwiseOr(spsr, context.ShiftLeft(GetFlag(PState.CFlag), Const((int)PState.CFlag)));
spsr = context.BitwiseOr(spsr, context.ShiftLeft(GetFlag(PState.ZFlag), Const((int)PState.ZFlag)));
spsr = context.BitwiseOr(spsr, context.ShiftLeft(GetFlag(PState.NFlag), Const((int)PState.NFlag)));
spsr = context.BitwiseOr(spsr, context.ShiftLeft(GetFlag(PState.QFlag), Const((int)PState.QFlag)));
// TODO: Remaining flags.
SetIntA32(context, op.Rd, spsr);
}
}
public static void Msr(ArmEmitterContext context)
{
OpCode32MsrReg op = (OpCode32MsrReg)context.CurrOp;
if (op.R)
{
throw new NotImplementedException("SPSR");
}
else
{
if ((op.Mask & 8) != 0)
{
Operand value = GetIntA32(context, op.Rn);
EmitSetNzcv(context, value);
Operand q = context.BitwiseAnd(context.ShiftRightUI(value, Const((int)PState.QFlag)), Const(1));
SetFlag(context, PState.QFlag, q);
}
if ((op.Mask & 4) != 0)
{
throw new NotImplementedException("APSR_g");
}
if ((op.Mask & 2) != 0)
{
throw new NotImplementedException("CPSR_x");
}
if ((op.Mask & 1) != 0)
{
throw new NotImplementedException("CPSR_c");
}
}
}
public static void Nop(ArmEmitterContext context) { }
public static void Vmrs(ArmEmitterContext context)
{
OpCode32SimdSpecial op = (OpCode32SimdSpecial)context.CurrOp;
if (op.Rt == RegisterAlias.Aarch32Pc && op.Sreg == 0b0001)
{
// Special behavior: copy NZCV flags into APSR.
SetFlag(context, PState.VFlag, GetFpFlag(FPState.VFlag));
SetFlag(context, PState.CFlag, GetFpFlag(FPState.CFlag));
SetFlag(context, PState.ZFlag, GetFpFlag(FPState.ZFlag));
SetFlag(context, PState.NFlag, GetFpFlag(FPState.NFlag));
return;
}
switch (op.Sreg)
{
case 0b0000: // FPSID
throw new NotImplementedException("Supervisor Only");
case 0b0001: // FPSCR
EmitGetFpscr(context); return;
case 0b0101: // MVFR2
throw new NotImplementedException("MVFR2");
case 0b0110: // MVFR1
throw new NotImplementedException("MVFR1");
case 0b0111: // MVFR0
throw new NotImplementedException("MVFR0");
case 0b1000: // FPEXC
throw new NotImplementedException("Supervisor Only");
default:
throw new NotImplementedException($"Unknown VMRS 0x{op.RawOpCode:X} at 0x{op.Address:X}.");
}
}
public static void Vmsr(ArmEmitterContext context)
{
OpCode32SimdSpecial op = (OpCode32SimdSpecial)context.CurrOp;
switch (op.Sreg)
{
case 0b0000: // FPSID
throw new NotImplementedException("Supervisor Only");
case 0b0001: // FPSCR
EmitSetFpscr(context); return;
case 0b0101: // MVFR2
throw new NotImplementedException("MVFR2");
case 0b0110: // MVFR1
throw new NotImplementedException("MVFR1");
case 0b0111: // MVFR0
throw new NotImplementedException("MVFR0");
case 0b1000: // FPEXC
throw new NotImplementedException("Supervisor Only");
default:
throw new NotImplementedException($"Unknown VMSR 0x{op.RawOpCode:X} at 0x{op.Address:X}.");
}
}
private static void EmitSetNzcv(ArmEmitterContext context, Operand t)
{
Operand v = context.BitwiseAnd(context.ShiftRightUI(t, Const((int)PState.VFlag)), Const(1));
Operand c = context.BitwiseAnd(context.ShiftRightUI(t, Const((int)PState.CFlag)), Const(1));
Operand z = context.BitwiseAnd(context.ShiftRightUI(t, Const((int)PState.ZFlag)), Const(1));
Operand n = context.BitwiseAnd(context.ShiftRightUI(t, Const((int)PState.NFlag)), Const(1));
SetFlag(context, PState.VFlag, v);
SetFlag(context, PState.CFlag, c);
SetFlag(context, PState.ZFlag, z);
SetFlag(context, PState.NFlag, n);
}
private static void EmitGetFpscr(ArmEmitterContext context)
{
OpCode32SimdSpecial op = (OpCode32SimdSpecial)context.CurrOp;
Operand fpscr = Const(0);
for (int flag = 0; flag < RegisterConsts.FpFlagsCount; flag++)
{
if (FPSCR.Mask.HasFlag((FPSCR)(1u << flag)))
{
fpscr = context.BitwiseOr(fpscr, context.ShiftLeft(GetFpFlag((FPState)flag), Const(flag)));
}
}
SetIntA32(context, op.Rt, fpscr);
}
private static void EmitSetFpscr(ArmEmitterContext context)
{
OpCode32SimdSpecial op = (OpCode32SimdSpecial)context.CurrOp;
Operand fpscr = GetIntA32(context, op.Rt);
for (int flag = 0; flag < RegisterConsts.FpFlagsCount; flag++)
{
if (FPSCR.Mask.HasFlag((FPSCR)(1u << flag)))
{
SetFpFlag(context, (FPState)flag, context.BitwiseAnd(context.ShiftRightUI(fpscr, Const(flag)), Const(1)));
}
}
}
}
}

View File

@@ -1,225 +0,0 @@
using ARMeilleure.Memory;
using ARMeilleure.State;
using ARMeilleure.Translation;
using System;
namespace ARMeilleure.Instructions
{
static class NativeInterface
{
private class ThreadContext
{
public ExecutionContext Context { get; }
public IMemoryManager Memory { get; }
public Translator Translator { get; }
public ThreadContext(ExecutionContext context, IMemoryManager memory, Translator translator)
{
Context = context;
Memory = memory;
Translator = translator;
}
}
[ThreadStatic]
private static ThreadContext Context;
public static void RegisterThread(ExecutionContext context, IMemoryManager memory, Translator translator)
{
Context = new ThreadContext(context, memory, translator);
}
public static void UnregisterThread()
{
Context = null;
}
public static void Break(ulong address, int imm)
{
Statistics.PauseTimer();
GetContext().OnBreak(address, imm);
Statistics.ResumeTimer();
}
public static void SupervisorCall(ulong address, int imm)
{
Statistics.PauseTimer();
GetContext().OnSupervisorCall(address, imm);
Statistics.ResumeTimer();
}
public static void Undefined(ulong address, int opCode)
{
Statistics.PauseTimer();
GetContext().OnUndefined(address, opCode);
Statistics.ResumeTimer();
}
#region "System registers"
public static ulong GetCtrEl0()
{
return (ulong)GetContext().CtrEl0;
}
public static ulong GetDczidEl0()
{
return (ulong)GetContext().DczidEl0;
}
public static ulong GetTpidrEl0()
{
return (ulong)GetContext().TpidrEl0;
}
public static uint GetTpidrEl032()
{
return (uint)GetContext().TpidrEl0;
}
public static ulong GetTpidrroEl0()
{
return (ulong)GetContext().TpidrroEl0;
}
public static uint GetTpidr32()
{
return (uint)GetContext().TpidrroEl0;
}
public static ulong GetCntfrqEl0()
{
return GetContext().CntfrqEl0;
}
public static ulong GetCntpctEl0()
{
return GetContext().CntpctEl0;
}
public static ulong GetCntvctEl0()
{
return GetContext().CntvctEl0;
}
public static void SetTpidrEl0(ulong value)
{
GetContext().TpidrEl0 = (long)value;
}
public static void SetTpidrEl032(uint value)
{
GetContext().TpidrEl0 = (long)value;
}
#endregion
#region "Read"
public static byte ReadByte(ulong address)
{
return GetMemoryManager().ReadTracked<byte>(address);
}
public static ushort ReadUInt16(ulong address)
{
return GetMemoryManager().ReadTracked<ushort>(address);
}
public static uint ReadUInt32(ulong address)
{
return GetMemoryManager().ReadTracked<uint>(address);
}
public static ulong ReadUInt64(ulong address)
{
return GetMemoryManager().ReadTracked<ulong>(address);
}
public static V128 ReadVector128(ulong address)
{
return GetMemoryManager().ReadTracked<V128>(address);
}
#endregion
#region "Write"
public static void WriteByte(ulong address, byte value)
{
GetMemoryManager().Write(address, value);
}
public static void WriteUInt16(ulong address, ushort value)
{
GetMemoryManager().Write(address, value);
}
public static void WriteUInt32(ulong address, uint value)
{
GetMemoryManager().Write(address, value);
}
public static void WriteUInt64(ulong address, ulong value)
{
GetMemoryManager().Write(address, value);
}
public static void WriteVector128(ulong address, V128 value)
{
GetMemoryManager().Write(address, value);
}
#endregion
public static void EnqueueForRejit(ulong address)
{
Context.Translator.EnqueueForRejit(address, GetContext().ExecutionMode);
}
public static void SignalMemoryTracking(ulong address, ulong size, bool write)
{
GetMemoryManager().SignalMemoryTracking(address, size, write);
}
public static void ThrowInvalidMemoryAccess(ulong address)
{
throw new InvalidAccessException(address);
}
public static ulong GetFunctionAddress(ulong address)
{
TranslatedFunction function = Context.Translator.GetOrTranslate(address, GetContext().ExecutionMode);
return (ulong)function.FuncPtr.ToInt64();
}
public static void InvalidateCacheLine(ulong address)
{
Context.Translator.InvalidateJitCacheRegion(address, InstEmit.DczSizeInBytes);
}
public static bool CheckSynchronization()
{
Statistics.PauseTimer();
ExecutionContext context = GetContext();
context.CheckInterrupt();
Statistics.ResumeTimer();
return context.Running;
}
public static ExecutionContext GetContext()
{
return Context.Context;
}
public static IMemoryManager GetMemoryManager()
{
return Context.Memory;
}
}
}

View File

@@ -1,177 +0,0 @@
namespace ARMeilleure.IntermediateRepresentation
{
enum Intrinsic : ushort
{
X86Addpd,
X86Addps,
X86Addsd,
X86Addss,
X86Aesdec,
X86Aesdeclast,
X86Aesenc,
X86Aesenclast,
X86Aesimc,
X86Andnpd,
X86Andnps,
X86Andpd,
X86Andps,
X86Blendvpd,
X86Blendvps,
X86Cmppd,
X86Cmpps,
X86Cmpsd,
X86Cmpss,
X86Comisdeq,
X86Comisdge,
X86Comisdlt,
X86Comisseq,
X86Comissge,
X86Comisslt,
X86Crc32,
X86Crc32_16,
X86Crc32_8,
X86Cvtdq2pd,
X86Cvtdq2ps,
X86Cvtpd2dq,
X86Cvtpd2ps,
X86Cvtps2dq,
X86Cvtps2pd,
X86Cvtsd2si,
X86Cvtsd2ss,
X86Cvtsi2sd,
X86Cvtsi2si,
X86Cvtsi2ss,
X86Cvtss2sd,
X86Cvtss2si,
X86Divpd,
X86Divps,
X86Divsd,
X86Divss,
X86Gf2p8affineqb,
X86Haddpd,
X86Haddps,
X86Insertps,
X86Maxpd,
X86Maxps,
X86Maxsd,
X86Maxss,
X86Minpd,
X86Minps,
X86Minsd,
X86Minss,
X86Movhlps,
X86Movlhps,
X86Movss,
X86Mulpd,
X86Mulps,
X86Mulsd,
X86Mulss,
X86Mxcsrmb,
X86Mxcsrub,
X86Paddb,
X86Paddd,
X86Paddq,
X86Paddw,
X86Palignr,
X86Pand,
X86Pandn,
X86Pavgb,
X86Pavgw,
X86Pblendvb,
X86Pclmulqdq,
X86Pcmpeqb,
X86Pcmpeqd,
X86Pcmpeqq,
X86Pcmpeqw,
X86Pcmpgtb,
X86Pcmpgtd,
X86Pcmpgtq,
X86Pcmpgtw,
X86Pmaxsb,
X86Pmaxsd,
X86Pmaxsw,
X86Pmaxub,
X86Pmaxud,
X86Pmaxuw,
X86Pminsb,
X86Pminsd,
X86Pminsw,
X86Pminub,
X86Pminud,
X86Pminuw,
X86Pmovsxbw,
X86Pmovsxdq,
X86Pmovsxwd,
X86Pmovzxbw,
X86Pmovzxdq,
X86Pmovzxwd,
X86Pmulld,
X86Pmullw,
X86Popcnt,
X86Por,
X86Pshufb,
X86Pshufd,
X86Pslld,
X86Pslldq,
X86Psllq,
X86Psllw,
X86Psrad,
X86Psraw,
X86Psrld,
X86Psrlq,
X86Psrldq,
X86Psrlw,
X86Psubb,
X86Psubd,
X86Psubq,
X86Psubw,
X86Punpckhbw,
X86Punpckhdq,
X86Punpckhqdq,
X86Punpckhwd,
X86Punpcklbw,
X86Punpckldq,
X86Punpcklqdq,
X86Punpcklwd,
X86Pxor,
X86Rcpps,
X86Rcpss,
X86Roundpd,
X86Roundps,
X86Roundsd,
X86Roundss,
X86Rsqrtps,
X86Rsqrtss,
X86Sha256Msg1,
X86Sha256Msg2,
X86Sha256Rnds2,
X86Shufpd,
X86Shufps,
X86Sqrtpd,
X86Sqrtps,
X86Sqrtsd,
X86Sqrtss,
X86Subpd,
X86Subps,
X86Subsd,
X86Subss,
X86Unpckhpd,
X86Unpckhps,
X86Unpcklpd,
X86Unpcklps,
X86Vcvtph2ps,
X86Vcvtps2ph,
X86Vfmadd231ps,
X86Vfmadd231sd,
X86Vfmadd231ss,
X86Vfmsub231sd,
X86Vfmsub231ss,
X86Vfnmadd231ps,
X86Vfnmadd231sd,
X86Vfnmadd231ss,
X86Vfnmsub231sd,
X86Vfnmsub231ss,
X86Xorpd,
X86Xorps
}
}

View File

@@ -1,10 +0,0 @@
namespace ARMeilleure.IntermediateRepresentation
{
enum Multiplier
{
x1 = 0,
x2 = 1,
x4 = 2,
x8 = 3
}
}

View File

@@ -1,580 +0,0 @@
using ARMeilleure.CodeGen.Linking;
using ARMeilleure.Common;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.CompilerServices;
namespace ARMeilleure.IntermediateRepresentation
{
unsafe struct Operand : IEquatable<Operand>
{
internal struct Data
{
public byte Kind;
public byte Type;
public byte SymbolType;
public byte Padding; // Unused space.
public ushort AssignmentsCount;
public ushort AssignmentsCapacity;
public uint UsesCount;
public uint UsesCapacity;
public Operation* Assignments;
public Operation* Uses;
public ulong Value;
public ulong SymbolValue;
}
private Data* _data;
public OperandKind Kind
{
get => (OperandKind)_data->Kind;
private set => _data->Kind = (byte)value;
}
public OperandType Type
{
get => (OperandType)_data->Type;
private set => _data->Type = (byte)value;
}
public ulong Value
{
get => _data->Value;
private set => _data->Value = value;
}
public Symbol Symbol
{
get
{
Debug.Assert(Kind != OperandKind.Memory);
return new Symbol((SymbolType)_data->SymbolType, _data->SymbolValue);
}
private set
{
Debug.Assert(Kind != OperandKind.Memory);
if (value.Type == SymbolType.None)
{
_data->SymbolType = (byte)SymbolType.None;
}
else
{
_data->SymbolType = (byte)value.Type;
_data->SymbolValue = value.Value;
}
}
}
public ReadOnlySpan<Operation> Assignments
{
get
{
Debug.Assert(Kind != OperandKind.Memory);
return new ReadOnlySpan<Operation>(_data->Assignments, _data->AssignmentsCount);
}
}
public ReadOnlySpan<Operation> Uses
{
get
{
Debug.Assert(Kind != OperandKind.Memory);
return new ReadOnlySpan<Operation>(_data->Uses, (int)_data->UsesCount);
}
}
public int UsesCount => (int)_data->UsesCount;
public int AssignmentsCount => _data->AssignmentsCount;
public bool Relocatable => Symbol.Type != SymbolType.None;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Register GetRegister()
{
Debug.Assert(Kind == OperandKind.Register);
return new Register((int)Value & 0xffffff, (RegisterType)(Value >> 24));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public MemoryOperand GetMemory()
{
Debug.Assert(Kind == OperandKind.Memory);
return new MemoryOperand(this);
}
public int GetLocalNumber()
{
Debug.Assert(Kind == OperandKind.LocalVariable);
return (int)Value;
}
public byte AsByte()
{
return (byte)Value;
}
public short AsInt16()
{
return (short)Value;
}
public int AsInt32()
{
return (int)Value;
}
public long AsInt64()
{
return (long)Value;
}
public float AsFloat()
{
return BitConverter.Int32BitsToSingle((int)Value);
}
public double AsDouble()
{
return BitConverter.Int64BitsToDouble((long)Value);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal ref ulong GetValueUnsafe()
{
return ref _data->Value;
}
internal void NumberLocal(int number)
{
if (Kind != OperandKind.LocalVariable)
{
throw new InvalidOperationException("The operand is not a local variable.");
}
Value = (ulong)number;
}
public void AddAssignment(Operation operation)
{
if (Kind == OperandKind.LocalVariable)
{
Add(operation, ref _data->Assignments, ref _data->AssignmentsCount, ref _data->AssignmentsCapacity);
}
else if (Kind == OperandKind.Memory)
{
MemoryOperand memOp = GetMemory();
Operand addr = memOp.BaseAddress;
Operand index = memOp.Index;
if (addr != default)
{
Add(operation, ref addr._data->Assignments, ref addr._data->AssignmentsCount, ref addr._data->AssignmentsCapacity);
}
if (index != default)
{
Add(operation, ref index._data->Assignments, ref index._data->AssignmentsCount, ref index._data->AssignmentsCapacity);
}
}
}
public void RemoveAssignment(Operation operation)
{
if (Kind == OperandKind.LocalVariable)
{
Remove(operation, ref _data->Assignments, ref _data->AssignmentsCount);
}
else if (Kind == OperandKind.Memory)
{
MemoryOperand memOp = GetMemory();
Operand addr = memOp.BaseAddress;
Operand index = memOp.Index;
if (addr != default)
{
Remove(operation, ref addr._data->Assignments, ref addr._data->AssignmentsCount);
}
if (index != default)
{
Remove(operation, ref index._data->Assignments, ref index._data->AssignmentsCount);
}
}
}
public void AddUse(Operation operation)
{
if (Kind == OperandKind.LocalVariable)
{
Add(operation, ref _data->Uses, ref _data->UsesCount, ref _data->UsesCapacity);
}
else if (Kind == OperandKind.Memory)
{
MemoryOperand memOp = GetMemory();
Operand addr = memOp.BaseAddress;
Operand index = memOp.Index;
if (addr != default)
{
Add(operation, ref addr._data->Uses, ref addr._data->UsesCount, ref addr._data->UsesCapacity);
}
if (index != default)
{
Add(operation, ref index._data->Uses, ref index._data->UsesCount, ref index._data->UsesCapacity);
}
}
}
public void RemoveUse(Operation operation)
{
if (Kind == OperandKind.LocalVariable)
{
Remove(operation, ref _data->Uses, ref _data->UsesCount);
}
else if (Kind == OperandKind.Memory)
{
MemoryOperand memOp = GetMemory();
Operand addr = memOp.BaseAddress;
Operand index = memOp.Index;
if (addr != default)
{
Remove(operation, ref addr._data->Uses, ref addr._data->UsesCount);
}
if (index != default)
{
Remove(operation, ref index._data->Uses, ref index._data->UsesCount);
}
}
}
private static void New<T>(ref T* data, ref ushort count, ref ushort capacity, ushort initialCapacity) where T : unmanaged
{
count = 0;
capacity = initialCapacity;
data = Allocators.References.Allocate<T>(initialCapacity);
}
private static void New<T>(ref T* data, ref uint count, ref uint capacity, uint initialCapacity) where T : unmanaged
{
count = 0;
capacity = initialCapacity;
data = Allocators.References.Allocate<T>(initialCapacity);
}
private static void Add<T>(T item, ref T* data, ref ushort count, ref ushort capacity) where T : unmanaged
{
if (count < capacity)
{
data[(uint)count++] = item;
return;
}
// Could not add item in the fast path, fallback onto the slow path.
ExpandAdd(item, ref data, ref count, ref capacity);
static void ExpandAdd(T item, ref T* data, ref ushort count, ref ushort capacity)
{
ushort newCount = checked((ushort)(count + 1));
ushort newCapacity = (ushort)Math.Min(capacity * 2, ushort.MaxValue);
var oldSpan = new Span<T>(data, count);
capacity = newCapacity;
data = Allocators.References.Allocate<T>(capacity);
oldSpan.CopyTo(new Span<T>(data, count));
data[count] = item;
count = newCount;
}
}
private static void Add<T>(T item, ref T* data, ref uint count, ref uint capacity) where T : unmanaged
{
if (count < capacity)
{
data[count++] = item;
return;
}
// Could not add item in the fast path, fallback onto the slow path.
ExpandAdd(item, ref data, ref count, ref capacity);
static void ExpandAdd(T item, ref T* data, ref uint count, ref uint capacity)
{
uint newCount = checked(count + 1);
uint newCapacity = (uint)Math.Min(capacity * 2, int.MaxValue);
if (newCapacity <= capacity)
{
throw new OverflowException();
}
var oldSpan = new Span<T>(data, (int)count);
capacity = newCapacity;
data = Allocators.References.Allocate<T>(capacity);
oldSpan.CopyTo(new Span<T>(data, (int)count));
data[count] = item;
count = newCount;
}
}
private static void Remove<T>(in T item, ref T* data, ref ushort count) where T : unmanaged
{
var span = new Span<T>(data, count);
for (int i = 0; i < span.Length; i++)
{
if (EqualityComparer<T>.Default.Equals(span[i], item))
{
if (i + 1 < count)
{
span.Slice(i + 1).CopyTo(span.Slice(i));
}
count--;
return;
}
}
}
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);
for (int i = 0; i < span.Length; i++)
{
if (EqualityComparer<T>.Default.Equals(span[i], item))
{
if (i + 1 < count)
{
span.Slice(i + 1).CopyTo(span.Slice(i));
}
count--;
return;
}
}
}
public override int GetHashCode()
{
return ((ulong)_data).GetHashCode();
}
public bool Equals(Operand operand)
{
return operand._data == _data;
}
public override bool Equals(object obj)
{
return obj is Operand operand && Equals(operand);
}
public static bool operator ==(Operand a, Operand b)
{
return a.Equals(b);
}
public static bool operator !=(Operand a, Operand b)
{
return !a.Equals(b);
}
public static class Factory
{
private const int InternTableSize = 256;
private const int InternTableProbeLength = 8;
[ThreadStatic]
private static Data* _internTable;
private static Data* InternTable
{
get
{
if (_internTable == null)
{
_internTable = (Data*)NativeAllocator.Instance.Allocate((uint)sizeof(Data) * InternTableSize);
// Make sure the table is zeroed.
new Span<Data>(_internTable, InternTableSize).Clear();
}
return _internTable;
}
}
private static Operand Make(OperandKind kind, OperandType type, ulong value, Symbol symbol = default)
{
Debug.Assert(kind != OperandKind.None);
Data* data = null;
// If constant or register, then try to look up in the intern table before allocating.
if (kind == OperandKind.Constant || kind == OperandKind.Register)
{
uint hash = (uint)HashCode.Combine(kind, type, value);
// Look in the next InternTableProbeLength slots for a match.
for (uint i = 0; i < InternTableProbeLength; i++)
{
Operand interned = new();
interned._data = &InternTable[(hash + i) % InternTableSize];
// If slot matches the allocation request then return that slot.
if (interned.Kind == kind && interned.Type == type && interned.Value == value && interned.Symbol == symbol)
{
return interned;
}
// Otherwise if the slot is not occupied, we store in that slot.
else if (interned.Kind == OperandKind.None)
{
data = interned._data;
break;
}
}
}
// If we could not get a slot from the intern table, we allocate somewhere else and store there.
if (data == null)
{
data = Allocators.Operands.Allocate<Data>();
}
*data = default;
Operand result = new();
result._data = data;
result.Value = value;
result.Kind = kind;
result.Type = type;
if (kind != OperandKind.Memory)
{
result.Symbol = symbol;
}
// If local variable, then the use and def list is initialized with default sizes.
if (kind == OperandKind.LocalVariable)
{
New(ref result._data->Assignments, ref result._data->AssignmentsCount, ref result._data->AssignmentsCapacity, 1);
New(ref result._data->Uses, ref result._data->UsesCount, ref result._data->UsesCapacity, 4);
}
return result;
}
public static Operand Const(OperandType type, long value)
{
Debug.Assert(type is OperandType.I32 or OperandType.I64);
return type == OperandType.I32 ? Const((int)value) : Const(value);
}
public static Operand Const(bool value)
{
return Const(value ? 1 : 0);
}
public static Operand Const(int value)
{
return Const((uint)value);
}
public static Operand Const(uint value)
{
return Make(OperandKind.Constant, OperandType.I32, value);
}
public static Operand Const(long value)
{
return Const(value, symbol: default);
}
public static Operand Const<T>(ref T reference, Symbol symbol = default)
{
return Const((long)Unsafe.AsPointer(ref reference), symbol);
}
public static Operand Const(long value, Symbol symbol)
{
return Make(OperandKind.Constant, OperandType.I64, (ulong)value, symbol);
}
public static Operand Const(ulong value)
{
return Make(OperandKind.Constant, OperandType.I64, value);
}
public static Operand ConstF(float value)
{
return Make(OperandKind.Constant, OperandType.FP32, (ulong)BitConverter.SingleToInt32Bits(value));
}
public static Operand ConstF(double value)
{
return Make(OperandKind.Constant, OperandType.FP64, (ulong)BitConverter.DoubleToInt64Bits(value));
}
public static Operand Label()
{
return Make(OperandKind.Label, OperandType.None, 0);
}
public static Operand Local(OperandType type)
{
return Make(OperandKind.LocalVariable, type, 0);
}
public static Operand Register(int index, RegisterType regType, OperandType type)
{
return Make(OperandKind.Register, type, (ulong)((int)regType << 24 | index));
}
public static Operand Undef()
{
return Make(OperandKind.Undefined, OperandType.None, 0);
}
public static Operand MemoryOp(
OperandType type,
Operand baseAddress,
Operand index = default,
Multiplier scale = Multiplier.x1,
int displacement = 0)
{
Operand result = Make(OperandKind.Memory, type, 0);
MemoryOperand memory = result.GetMemory();
memory.BaseAddress = baseAddress;
memory.Index = index;
memory.Scale = scale;
memory.Displacement = displacement;
return result;
}
}
}
}

View File

@@ -1,51 +0,0 @@
using System;
namespace ARMeilleure.IntermediateRepresentation
{
enum OperandType
{
None,
I32,
I64,
FP32,
FP64,
V128
}
static class OperandTypeExtensions
{
public static bool IsInteger(this OperandType type)
{
return type == OperandType.I32 ||
type == OperandType.I64;
}
public static RegisterType ToRegisterType(this OperandType type)
{
switch (type)
{
case OperandType.FP32: return RegisterType.Vector;
case OperandType.FP64: return RegisterType.Vector;
case OperandType.I32: return RegisterType.Integer;
case OperandType.I64: return RegisterType.Integer;
case OperandType.V128: return RegisterType.Vector;
}
throw new InvalidOperationException($"Invalid operand type \"{type}\".");
}
public static int GetSizeInBytes(this OperandType type)
{
switch (type)
{
case OperandType.FP32: return 4;
case OperandType.FP64: return 8;
case OperandType.I32: return 4;
case OperandType.I64: return 8;
case OperandType.V128: return 16;
}
throw new InvalidOperationException($"Invalid operand type \"{type}\".");
}
}
}

View File

@@ -1,8 +0,0 @@
namespace ARMeilleure.Memory
{
public interface IJitMemoryAllocator
{
IJitMemoryBlock Allocate(ulong size);
IJitMemoryBlock Reserve(ulong size);
}
}

View File

@@ -1,76 +0,0 @@
using System;
namespace ARMeilleure.Memory
{
public interface IMemoryManager
{
int AddressSpaceBits { get; }
IntPtr PageTablePointer { get; }
MemoryManagerType Type { get; }
event Action<ulong, ulong> UnmapEvent;
/// <summary>
/// Reads data from CPU mapped memory.
/// </summary>
/// <typeparam name="T">Type of the data being read</typeparam>
/// <param name="va">Virtual address of the data in memory</param>
/// <returns>The data</returns>
T Read<T>(ulong va) where T : unmanaged;
/// <summary>
/// Reads data from CPU mapped memory, with read tracking
/// </summary>
/// <typeparam name="T">Type of the data being read</typeparam>
/// <param name="va">Virtual address of the data in memory</param>
/// <returns>The data</returns>
T ReadTracked<T>(ulong va) where T : unmanaged;
/// <summary>
/// Writes data to CPU mapped memory.
/// </summary>
/// <typeparam name="T">Type of the data being written</typeparam>
/// <param name="va">Virtual address to write the data into</param>
/// <param name="value">Data to be written</param>
void Write<T>(ulong va, T value) where T : unmanaged;
/// <summary>
/// Gets a read-only span of data from CPU mapped memory.
/// </summary>
/// <param name="va">Virtual address of the data</param>
/// <param name="size">Size of the data</param>
/// <param name="tracked">True if read tracking is triggered on the span</param>
/// <returns>A read-only span of the data</returns>
ReadOnlySpan<byte> GetSpan(ulong va, int size, bool tracked = false);
/// <summary>
/// Gets a reference for the given type at the specified virtual memory address.
/// </summary>
/// <remarks>
/// The data must be located at a contiguous memory region.
/// </remarks>
/// <typeparam name="T">Type of the data to get the reference</typeparam>
/// <param name="va">Virtual address of the data</param>
/// <returns>A reference to the data in memory</returns>
ref T GetRef<T>(ulong va) where T : unmanaged;
/// <summary>
/// Checks if the page at a given CPU virtual address is mapped.
/// </summary>
/// <param name="va">Virtual address to check</param>
/// <returns>True if the address is mapped, false otherwise</returns>
bool IsMapped(ulong va);
/// <summary>
/// Alerts the memory tracking that a given region has been read from or written to.
/// This should be called before read/write is performed.
/// </summary>
/// <param name="va">Virtual address of the region</param>
/// <param name="size">Size of the region</param>
/// <param name="write">True if the region was written, false if read</param>
/// <param name="precise">True if the access is precise, false otherwise</param>
void SignalMemoryTracking(ulong va, ulong size, bool write, bool precise = false);
}
}

View File

@@ -1,58 +0,0 @@
using System;
namespace ARMeilleure.Memory
{
class ReservedRegion
{
private const int DefaultGranularity = 65536; // Mapping granularity in Windows.
public IJitMemoryBlock Block { get; }
public IntPtr Pointer => Block.Pointer;
private readonly ulong _maxSize;
private readonly ulong _sizeGranularity;
private ulong _currentSize;
public ReservedRegion(IJitMemoryAllocator allocator, ulong maxSize, ulong granularity = 0)
{
if (granularity == 0)
{
granularity = DefaultGranularity;
}
Block = allocator.Reserve(maxSize);
_maxSize = maxSize;
_sizeGranularity = granularity;
_currentSize = 0;
}
public void ExpandIfNeeded(ulong desiredSize)
{
if (desiredSize > _maxSize)
{
throw new OutOfMemoryException();
}
if (desiredSize > _currentSize)
{
// Lock, and then check again. We only want to commit once.
lock (this)
{
if (desiredSize >= _currentSize)
{
ulong overflowBytes = desiredSize - _currentSize;
ulong moreToCommit = (((_sizeGranularity - 1) + overflowBytes) / _sizeGranularity) * _sizeGranularity; // Round up.
Block.Commit(_currentSize, moreToCommit);
_currentSize += moreToCommit;
}
}
}
}
public void Dispose()
{
Block.Dispose();
}
}
}

View File

@@ -1,48 +0,0 @@
using ARMeilleure.CodeGen.X86;
namespace ARMeilleure
{
public static class Optimizations
{
public static bool FastFP { get; set; } = true;
public static bool AllowLcqInFunctionTable { get; set; } = true;
public static bool UseUnmanagedDispatchLoop { get; set; } = true;
public static bool UseSseIfAvailable { get; set; } = true;
public static bool UseSse2IfAvailable { get; set; } = true;
public static bool UseSse3IfAvailable { get; set; } = true;
public static bool UseSsse3IfAvailable { get; set; } = true;
public static bool UseSse41IfAvailable { get; set; } = true;
public static bool UseSse42IfAvailable { get; set; } = true;
public static bool UsePopCntIfAvailable { get; set; } = true;
public static bool UseAvxIfAvailable { get; set; } = true;
public static bool UseF16cIfAvailable { get; set; } = true;
public static bool UseFmaIfAvailable { get; set; } = true;
public static bool UseAesniIfAvailable { get; set; } = true;
public static bool UsePclmulqdqIfAvailable { get; set; } = true;
public static bool UseShaIfAvailable { get; set; } = true;
public static bool UseGfniIfAvailable { get; set; } = true;
public static bool ForceLegacySse
{
get => HardwareCapabilities.ForceLegacySse;
set => HardwareCapabilities.ForceLegacySse = value;
}
internal static bool UseSse => UseSseIfAvailable && HardwareCapabilities.SupportsSse;
internal static bool UseSse2 => UseSse2IfAvailable && HardwareCapabilities.SupportsSse2;
internal static bool UseSse3 => UseSse3IfAvailable && HardwareCapabilities.SupportsSse3;
internal static bool UseSsse3 => UseSsse3IfAvailable && HardwareCapabilities.SupportsSsse3;
internal static bool UseSse41 => UseSse41IfAvailable && HardwareCapabilities.SupportsSse41;
internal static bool UseSse42 => UseSse42IfAvailable && HardwareCapabilities.SupportsSse42;
internal static bool UsePopCnt => UsePopCntIfAvailable && HardwareCapabilities.SupportsPopcnt;
internal static bool UseAvx => UseAvxIfAvailable && HardwareCapabilities.SupportsAvx && !ForceLegacySse;
internal static bool UseF16c => UseF16cIfAvailable && HardwareCapabilities.SupportsF16c;
internal static bool UseFma => UseFmaIfAvailable && HardwareCapabilities.SupportsFma;
internal static bool UseAesni => UseAesniIfAvailable && HardwareCapabilities.SupportsAesni;
internal static bool UsePclmulqdq => UsePclmulqdqIfAvailable && HardwareCapabilities.SupportsPclmulqdq;
internal static bool UseSha => UseShaIfAvailable && HardwareCapabilities.SupportsSha;
internal static bool UseGfni => UseGfniIfAvailable && HardwareCapabilities.SupportsGfni;
}
}

View File

@@ -1,338 +0,0 @@
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation;
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
namespace ARMeilleure.Signal
{
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct SignalHandlerRange
{
public int IsActive;
public nuint RangeAddress;
public nuint RangeEndAddress;
public IntPtr ActionPointer;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct SignalHandlerConfig
{
/// <summary>
/// The byte offset of the faulting address in the SigInfo or ExceptionRecord struct.
/// </summary>
public int StructAddressOffset;
/// <summary>
/// The byte offset of the write flag in the SigInfo or ExceptionRecord struct.
/// </summary>
public int StructWriteOffset;
/// <summary>
/// The sigaction handler that was registered before this one. (unix only)
/// </summary>
public nuint UnixOldSigaction;
/// <summary>
/// The type of the previous sigaction. True for the 3 argument variant. (unix only)
/// </summary>
public int UnixOldSigaction3Arg;
public SignalHandlerRange Range0;
public SignalHandlerRange Range1;
public SignalHandlerRange Range2;
public SignalHandlerRange Range3;
public SignalHandlerRange Range4;
public SignalHandlerRange Range5;
public SignalHandlerRange Range6;
public SignalHandlerRange Range7;
}
public static class NativeSignalHandler
{
private delegate void UnixExceptionHandler(int sig, IntPtr info, IntPtr ucontext);
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
private delegate int VectoredExceptionHandler(IntPtr exceptionInfo);
private const int MaxTrackedRanges = 8;
private const int StructAddressOffset = 0;
private const int StructWriteOffset = 4;
private const int UnixOldSigaction = 8;
private const int UnixOldSigaction3Arg = 16;
private const int RangeOffset = 20;
private const int EXCEPTION_CONTINUE_SEARCH = 0;
private const int EXCEPTION_CONTINUE_EXECUTION = -1;
private const uint EXCEPTION_ACCESS_VIOLATION = 0xc0000005;
private const ulong PageSize = 0x1000;
private const ulong PageMask = PageSize - 1;
private static IntPtr _handlerConfig;
private static IntPtr _signalHandlerPtr;
private static IntPtr _signalHandlerHandle;
private static readonly object _lock = new object();
private static bool _initialized;
static NativeSignalHandler()
{
_handlerConfig = Marshal.AllocHGlobal(Unsafe.SizeOf<SignalHandlerConfig>());
ref SignalHandlerConfig config = ref GetConfigRef();
config = new SignalHandlerConfig();
}
public static void InitializeSignalHandler()
{
if (_initialized) return;
lock (_lock)
{
if (_initialized) return;
bool unix = OperatingSystem.IsLinux() || OperatingSystem.IsMacOS();
ref SignalHandlerConfig config = ref GetConfigRef();
if (unix)
{
// Unix siginfo struct locations.
// NOTE: These are incredibly likely to be different between kernel version and architectures.
config.StructAddressOffset = OperatingSystem.IsMacOS() ? 24 : 16; // si_addr
config.StructWriteOffset = 8; // si_code
_signalHandlerPtr = Marshal.GetFunctionPointerForDelegate(GenerateUnixSignalHandler(_handlerConfig));
SigAction old = UnixSignalHandlerRegistration.RegisterExceptionHandler(_signalHandlerPtr);
config.UnixOldSigaction = (nuint)(ulong)old.sa_handler;
config.UnixOldSigaction3Arg = old.sa_flags & 4;
}
else
{
config.StructAddressOffset = 40; // ExceptionInformation1
config.StructWriteOffset = 32; // ExceptionInformation0
_signalHandlerPtr = Marshal.GetFunctionPointerForDelegate(GenerateWindowsSignalHandler(_handlerConfig));
_signalHandlerHandle = WindowsSignalHandlerRegistration.RegisterExceptionHandler(_signalHandlerPtr);
}
_initialized = true;
}
}
private static unsafe ref SignalHandlerConfig GetConfigRef()
{
return ref Unsafe.AsRef<SignalHandlerConfig>((void*)_handlerConfig);
}
public static unsafe bool AddTrackedRegion(nuint address, nuint endAddress, IntPtr action)
{
var ranges = &((SignalHandlerConfig*)_handlerConfig)->Range0;
for (int i = 0; i < MaxTrackedRanges; i++)
{
if (ranges[i].IsActive == 0)
{
ranges[i].RangeAddress = address;
ranges[i].RangeEndAddress = endAddress;
ranges[i].ActionPointer = action;
ranges[i].IsActive = 1;
return true;
}
}
return false;
}
public static unsafe bool RemoveTrackedRegion(nuint address)
{
var ranges = &((SignalHandlerConfig*)_handlerConfig)->Range0;
for (int i = 0; i < MaxTrackedRanges; i++)
{
if (ranges[i].IsActive == 1 && ranges[i].RangeAddress == address)
{
ranges[i].IsActive = 0;
return true;
}
}
return false;
}
private static Operand EmitGenericRegionCheck(EmitterContext context, IntPtr signalStructPtr, Operand faultAddress, Operand isWrite)
{
Operand inRegionLocal = context.AllocateLocal(OperandType.I32);
context.Copy(inRegionLocal, Const(0));
Operand endLabel = Label();
for (int i = 0; i < MaxTrackedRanges; i++)
{
ulong rangeBaseOffset = (ulong)(RangeOffset + i * Unsafe.SizeOf<SignalHandlerRange>());
Operand nextLabel = Label();
Operand isActive = context.Load(OperandType.I32, Const((ulong)signalStructPtr + rangeBaseOffset));
context.BranchIfFalse(nextLabel, isActive);
Operand rangeAddress = context.Load(OperandType.I64, Const((ulong)signalStructPtr + rangeBaseOffset + 4));
Operand rangeEndAddress = context.Load(OperandType.I64, Const((ulong)signalStructPtr + rangeBaseOffset + 12));
// Is the fault address within this tracked region?
Operand inRange = context.BitwiseAnd(
context.ICompare(faultAddress, rangeAddress, Comparison.GreaterOrEqualUI),
context.ICompare(faultAddress, rangeEndAddress, Comparison.LessUI)
);
// Only call tracking if in range.
context.BranchIfFalse(nextLabel, inRange, BasicBlockFrequency.Cold);
Operand offset = context.BitwiseAnd(context.Subtract(faultAddress, rangeAddress), Const(~PageMask));
// Call the tracking action, with the pointer's relative offset to the base address.
Operand trackingActionPtr = context.Load(OperandType.I64, Const((ulong)signalStructPtr + rangeBaseOffset + 20));
context.Copy(inRegionLocal, Const(0));
Operand skipActionLabel = Label();
// Tracking action should be non-null to call it, otherwise assume false return.
context.BranchIfFalse(skipActionLabel, trackingActionPtr);
Operand result = context.Call(trackingActionPtr, OperandType.I32, offset, Const(PageSize), isWrite, Const(0));
context.Copy(inRegionLocal, result);
context.MarkLabel(skipActionLabel);
// If the tracking action returns false or does not exist, it might be an invalid access due to a partial overlap on Windows.
if (OperatingSystem.IsWindows())
{
context.BranchIfTrue(endLabel, inRegionLocal);
context.Copy(inRegionLocal, WindowsPartialUnmapHandler.EmitRetryFromAccessViolation(context));
}
context.Branch(endLabel);
context.MarkLabel(nextLabel);
}
context.MarkLabel(endLabel);
return context.Copy(inRegionLocal);
}
private static UnixExceptionHandler GenerateUnixSignalHandler(IntPtr signalStructPtr)
{
EmitterContext context = new EmitterContext();
// (int sig, SigInfo* sigInfo, void* ucontext)
Operand sigInfoPtr = context.LoadArgument(OperandType.I64, 1);
Operand structAddressOffset = context.Load(OperandType.I64, Const((ulong)signalStructPtr + StructAddressOffset));
Operand structWriteOffset = context.Load(OperandType.I64, Const((ulong)signalStructPtr + StructWriteOffset));
Operand faultAddress = context.Load(OperandType.I64, context.Add(sigInfoPtr, context.ZeroExtend32(OperandType.I64, structAddressOffset)));
Operand writeFlag = context.Load(OperandType.I64, context.Add(sigInfoPtr, context.ZeroExtend32(OperandType.I64, structWriteOffset)));
Operand isWrite = context.ICompareNotEqual(writeFlag, Const(0L)); // Normalize to 0/1.
Operand isInRegion = EmitGenericRegionCheck(context, signalStructPtr, faultAddress, isWrite);
Operand endLabel = Label();
context.BranchIfTrue(endLabel, isInRegion);
Operand unixOldSigaction = context.Load(OperandType.I64, Const((ulong)signalStructPtr + UnixOldSigaction));
Operand unixOldSigaction3Arg = context.Load(OperandType.I64, Const((ulong)signalStructPtr + UnixOldSigaction3Arg));
Operand threeArgLabel = Label();
context.BranchIfTrue(threeArgLabel, unixOldSigaction3Arg);
context.Call(unixOldSigaction, OperandType.None, context.LoadArgument(OperandType.I32, 0));
context.Branch(endLabel);
context.MarkLabel(threeArgLabel);
context.Call(unixOldSigaction,
OperandType.None,
context.LoadArgument(OperandType.I32, 0),
sigInfoPtr,
context.LoadArgument(OperandType.I64, 2)
);
context.MarkLabel(endLabel);
context.Return();
ControlFlowGraph cfg = context.GetControlFlowGraph();
OperandType[] argTypes = new OperandType[] { OperandType.I32, OperandType.I64, OperandType.I64 };
return Compiler.Compile(cfg, argTypes, OperandType.None, CompilerOptions.HighCq).Map<UnixExceptionHandler>();
}
private static VectoredExceptionHandler GenerateWindowsSignalHandler(IntPtr signalStructPtr)
{
EmitterContext context = new EmitterContext();
// (ExceptionPointers* exceptionInfo)
Operand exceptionInfoPtr = context.LoadArgument(OperandType.I64, 0);
Operand exceptionRecordPtr = context.Load(OperandType.I64, exceptionInfoPtr);
// First thing's first - this catches a number of exceptions, but we only want access violations.
Operand validExceptionLabel = Label();
Operand exceptionCode = context.Load(OperandType.I32, exceptionRecordPtr);
context.BranchIf(validExceptionLabel, exceptionCode, Const(EXCEPTION_ACCESS_VIOLATION), Comparison.Equal);
context.Return(Const(EXCEPTION_CONTINUE_SEARCH)); // Don't handle this one.
context.MarkLabel(validExceptionLabel);
// Next, read the address of the invalid access, and whether it is a write or not.
Operand structAddressOffset = context.Load(OperandType.I32, Const((ulong)signalStructPtr + StructAddressOffset));
Operand structWriteOffset = context.Load(OperandType.I32, Const((ulong)signalStructPtr + StructWriteOffset));
Operand faultAddress = context.Load(OperandType.I64, context.Add(exceptionRecordPtr, context.ZeroExtend32(OperandType.I64, structAddressOffset)));
Operand writeFlag = context.Load(OperandType.I64, context.Add(exceptionRecordPtr, context.ZeroExtend32(OperandType.I64, structWriteOffset)));
Operand isWrite = context.ICompareNotEqual(writeFlag, Const(0L)); // Normalize to 0/1.
Operand isInRegion = EmitGenericRegionCheck(context, signalStructPtr, faultAddress, isWrite);
Operand endLabel = Label();
// If the region check result is false, then run the next vectored exception handler.
context.BranchIfTrue(endLabel, isInRegion);
context.Return(Const(EXCEPTION_CONTINUE_SEARCH));
context.MarkLabel(endLabel);
// Otherwise, return to execution.
context.Return(Const(EXCEPTION_CONTINUE_EXECUTION));
// Compile and return the function.
ControlFlowGraph cfg = context.GetControlFlowGraph();
OperandType[] argTypes = new OperandType[] { OperandType.I64 };
return Compiler.Compile(cfg, argTypes, OperandType.I32, CompilerOptions.HighCq).Map<VectoredExceptionHandler>();
}
}
}

View File

@@ -1,84 +0,0 @@
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation;
using System;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
namespace ARMeilleure.Signal
{
public struct NativeWriteLoopState
{
public int Running;
public int Error;
}
public static class TestMethods
{
public delegate bool DebugPartialUnmap();
public delegate int DebugThreadLocalMapGetOrReserve(int threadId, int initialState);
public delegate void DebugNativeWriteLoop(IntPtr nativeWriteLoopPtr, IntPtr writePtr);
public static DebugPartialUnmap GenerateDebugPartialUnmap()
{
EmitterContext context = new EmitterContext();
var result = WindowsPartialUnmapHandler.EmitRetryFromAccessViolation(context);
context.Return(result);
// Compile and return the function.
ControlFlowGraph cfg = context.GetControlFlowGraph();
OperandType[] argTypes = new OperandType[] { OperandType.I64 };
return Compiler.Compile(cfg, argTypes, OperandType.I32, CompilerOptions.HighCq).Map<DebugPartialUnmap>();
}
public static DebugThreadLocalMapGetOrReserve GenerateDebugThreadLocalMapGetOrReserve(IntPtr structPtr)
{
EmitterContext context = new EmitterContext();
var result = WindowsPartialUnmapHandler.EmitThreadLocalMapIntGetOrReserve(context, structPtr, context.LoadArgument(OperandType.I32, 0), context.LoadArgument(OperandType.I32, 1));
context.Return(result);
// Compile and return the function.
ControlFlowGraph cfg = context.GetControlFlowGraph();
OperandType[] argTypes = new OperandType[] { OperandType.I64 };
return Compiler.Compile(cfg, argTypes, OperandType.I32, CompilerOptions.HighCq).Map<DebugThreadLocalMapGetOrReserve>();
}
public static DebugNativeWriteLoop GenerateDebugNativeWriteLoop()
{
EmitterContext context = new EmitterContext();
// Loop a write to the target address until "running" is false.
Operand structPtr = context.Copy(context.LoadArgument(OperandType.I64, 0));
Operand writePtr = context.Copy(context.LoadArgument(OperandType.I64, 1));
Operand loopLabel = Label();
context.MarkLabel(loopLabel);
context.Store(writePtr, Const(12345));
Operand running = context.Load(OperandType.I32, structPtr);
context.BranchIfTrue(loopLabel, running);
context.Return();
// Compile and return the function.
ControlFlowGraph cfg = context.GetControlFlowGraph();
OperandType[] argTypes = new OperandType[] { OperandType.I64 };
return Compiler.Compile(cfg, argTypes, OperandType.None, CompilerOptions.HighCq).Map<DebugNativeWriteLoop>();
}
}
}

View File

@@ -1,68 +0,0 @@
using System;
using System.Runtime.InteropServices;
namespace ARMeilleure.Signal
{
[StructLayout(LayoutKind.Sequential, Pack = 1)]
unsafe struct SigSet
{
fixed long sa_mask[16];
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct SigAction
{
public IntPtr sa_handler;
public SigSet sa_mask;
public int sa_flags;
public IntPtr sa_restorer;
}
static partial class UnixSignalHandlerRegistration
{
private const int SIGSEGV = 11;
private const int SIGBUS = 10;
private const int SA_SIGINFO = 0x00000004;
[LibraryImport("libc", SetLastError = true)]
private static partial int sigaction(int signum, ref SigAction sigAction, out SigAction oldAction);
[LibraryImport("libc", SetLastError = true)]
private static partial int sigemptyset(ref SigSet set);
public static SigAction RegisterExceptionHandler(IntPtr action)
{
SigAction sig = new SigAction
{
sa_handler = action,
sa_flags = SA_SIGINFO
};
sigemptyset(ref sig.sa_mask);
int result = sigaction(SIGSEGV, ref sig, out SigAction old);
if (result != 0)
{
throw new InvalidOperationException($"Could not register SIGSEGV sigaction. Error: {result}");
}
if (OperatingSystem.IsMacOS())
{
result = sigaction(SIGBUS, ref sig, out SigAction oldb);
if (result != 0)
{
throw new InvalidOperationException($"Could not register SIGBUS sigaction. Error: {result}");
}
}
return old;
}
public static bool RestoreExceptionHandler(SigAction oldAction)
{
return sigaction(SIGSEGV, ref oldAction, out SigAction _) == 0 && (!OperatingSystem.IsMacOS() || sigaction(SIGBUS, ref oldAction, out SigAction _) == 0);
}
}
}

View File

@@ -1,164 +0,0 @@
using ARMeilleure.Memory;
using System;
namespace ARMeilleure.State
{
public class ExecutionContext
{
private const int MinCountForCheck = 4000;
private NativeContext _nativeContext;
internal IntPtr NativeContextPtr => _nativeContext.BasePtr;
private bool _interrupted;
private readonly ICounter _counter;
public ulong Pc => _nativeContext.GetPc();
public uint CtrEl0 => 0x8444c004;
public uint DczidEl0 => 0x00000004;
public ulong CntfrqEl0 => _counter.Frequency;
public ulong CntpctEl0 => _counter.Counter;
// CNTVCT_EL0 = CNTPCT_EL0 - CNTVOFF_EL2
// Since EL2 isn't implemented, CNTVOFF_EL2 = 0
public ulong CntvctEl0 => CntpctEl0;
public long TpidrEl0 { get; set; }
public long TpidrroEl0 { get; set; }
public uint Pstate
{
get => _nativeContext.GetPstate();
set => _nativeContext.SetPstate(value);
}
public FPSR Fpsr
{
get => (FPSR)_nativeContext.GetFPState((uint)FPSR.Mask);
set => _nativeContext.SetFPState((uint)value, (uint)FPSR.Mask);
}
public FPCR Fpcr
{
get => (FPCR)_nativeContext.GetFPState((uint)FPCR.Mask);
set => _nativeContext.SetFPState((uint)value, (uint)FPCR.Mask);
}
public FPCR StandardFpcrValue => (Fpcr & (FPCR.Ahp)) | FPCR.Dn | FPCR.Fz;
public FPSCR Fpscr
{
get => (FPSCR)_nativeContext.GetFPState((uint)FPSCR.Mask);
set => _nativeContext.SetFPState((uint)value, (uint)FPSCR.Mask);
}
public bool IsAarch32 { get; set; }
internal ExecutionMode ExecutionMode
{
get
{
if (IsAarch32)
{
return GetPstateFlag(PState.TFlag)
? ExecutionMode.Aarch32Thumb
: ExecutionMode.Aarch32Arm;
}
else
{
return ExecutionMode.Aarch64;
}
}
}
public bool Running
{
get => _nativeContext.GetRunning();
private set => _nativeContext.SetRunning(value);
}
private readonly ExceptionCallbackNoArgs _interruptCallback;
private readonly ExceptionCallback _breakCallback;
private readonly ExceptionCallback _supervisorCallback;
private readonly ExceptionCallback _undefinedCallback;
public ExecutionContext(
IJitMemoryAllocator allocator,
ICounter counter,
ExceptionCallbackNoArgs interruptCallback = null,
ExceptionCallback breakCallback = null,
ExceptionCallback supervisorCallback = null,
ExceptionCallback undefinedCallback = null)
{
_nativeContext = new NativeContext(allocator);
_counter = counter;
_interruptCallback = interruptCallback;
_breakCallback = breakCallback;
_supervisorCallback = supervisorCallback;
_undefinedCallback = undefinedCallback;
Running = true;
_nativeContext.SetCounter(MinCountForCheck);
}
public ulong GetX(int index) => _nativeContext.GetX(index);
public void SetX(int index, ulong value) => _nativeContext.SetX(index, value);
public V128 GetV(int index) => _nativeContext.GetV(index);
public void SetV(int index, V128 value) => _nativeContext.SetV(index, value);
public bool GetPstateFlag(PState flag) => _nativeContext.GetPstateFlag(flag);
public void SetPstateFlag(PState flag, bool value) => _nativeContext.SetPstateFlag(flag, value);
public bool GetFPstateFlag(FPState flag) => _nativeContext.GetFPStateFlag(flag);
public void SetFPstateFlag(FPState flag, bool value) => _nativeContext.SetFPStateFlag(flag, value);
internal void CheckInterrupt()
{
if (_interrupted)
{
_interrupted = false;
_interruptCallback?.Invoke(this);
}
_nativeContext.SetCounter(MinCountForCheck);
}
public void RequestInterrupt()
{
_interrupted = true;
}
internal void OnBreak(ulong address, int imm)
{
_breakCallback?.Invoke(this, address, imm);
}
internal void OnSupervisorCall(ulong address, int imm)
{
_supervisorCallback?.Invoke(this, address, imm);
}
internal void OnUndefined(ulong address, int opCode)
{
_undefinedCallback?.Invoke(this, address, opCode);
}
public void StopRunning()
{
Running = false;
_nativeContext.SetCounter(0);
}
public void Dispose()
{
_nativeContext.Dispose();
}
}
}

View File

@@ -1,251 +0,0 @@
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Memory;
using System;
using System.Runtime.CompilerServices;
namespace ARMeilleure.State
{
class NativeContext : IDisposable
{
private unsafe struct NativeCtxStorage
{
public fixed ulong X[RegisterConsts.IntRegsCount];
public fixed ulong V[RegisterConsts.VecRegsCount * 2];
public fixed uint Flags[RegisterConsts.FlagsCount];
public fixed uint FpFlags[RegisterConsts.FpFlagsCount];
public int Counter;
public ulong DispatchAddress;
public ulong ExclusiveAddress;
public ulong ExclusiveValueLow;
public ulong ExclusiveValueHigh;
public int Running;
}
private static NativeCtxStorage _dummyStorage = new NativeCtxStorage();
private readonly IJitMemoryBlock _block;
public IntPtr BasePtr => _block.Pointer;
public NativeContext(IJitMemoryAllocator allocator)
{
_block = allocator.Allocate((ulong)Unsafe.SizeOf<NativeCtxStorage>());
GetStorage().ExclusiveAddress = ulong.MaxValue;
}
public ulong GetPc()
{
// TODO: More precise tracking of PC value.
return GetStorage().DispatchAddress;
}
public unsafe ulong GetX(int index)
{
if ((uint)index >= RegisterConsts.IntRegsCount)
{
throw new ArgumentOutOfRangeException(nameof(index));
}
return GetStorage().X[index];
}
public unsafe void SetX(int index, ulong value)
{
if ((uint)index >= RegisterConsts.IntRegsCount)
{
throw new ArgumentOutOfRangeException(nameof(index));
}
GetStorage().X[index] = value;
}
public unsafe V128 GetV(int index)
{
if ((uint)index >= RegisterConsts.VecRegsCount)
{
throw new ArgumentOutOfRangeException(nameof(index));
}
return new V128(GetStorage().V[index * 2 + 0], GetStorage().V[index * 2 + 1]);
}
public unsafe void SetV(int index, V128 value)
{
if ((uint)index >= RegisterConsts.VecRegsCount)
{
throw new ArgumentOutOfRangeException(nameof(index));
}
GetStorage().V[index * 2 + 0] = value.Extract<ulong>(0);
GetStorage().V[index * 2 + 1] = value.Extract<ulong>(1);
}
public unsafe bool GetPstateFlag(PState flag)
{
if ((uint)flag >= RegisterConsts.FlagsCount)
{
throw new ArgumentException($"Invalid flag \"{flag}\" specified.");
}
return GetStorage().Flags[(int)flag] != 0;
}
public unsafe void SetPstateFlag(PState flag, bool value)
{
if ((uint)flag >= RegisterConsts.FlagsCount)
{
throw new ArgumentException($"Invalid flag \"{flag}\" specified.");
}
GetStorage().Flags[(int)flag] = value ? 1u : 0u;
}
public unsafe uint GetPstate()
{
uint value = 0;
for (int flag = 0; flag < RegisterConsts.FlagsCount; flag++)
{
value |= GetStorage().Flags[flag] != 0 ? 1u << flag : 0u;
}
return value;
}
public unsafe void SetPstate(uint value)
{
for (int flag = 0; flag < RegisterConsts.FlagsCount; flag++)
{
uint bit = 1u << flag;
GetStorage().Flags[flag] = (value & bit) == bit ? 1u : 0u;
}
}
public unsafe bool GetFPStateFlag(FPState flag)
{
if ((uint)flag >= RegisterConsts.FpFlagsCount)
{
throw new ArgumentException($"Invalid flag \"{flag}\" specified.");
}
return GetStorage().FpFlags[(int)flag] != 0;
}
public unsafe void SetFPStateFlag(FPState flag, bool value)
{
if ((uint)flag >= RegisterConsts.FpFlagsCount)
{
throw new ArgumentException($"Invalid flag \"{flag}\" specified.");
}
GetStorage().FpFlags[(int)flag] = value ? 1u : 0u;
}
public unsafe uint GetFPState(uint mask = uint.MaxValue)
{
uint value = 0;
for (int flag = 0; flag < RegisterConsts.FpFlagsCount; flag++)
{
uint bit = 1u << flag;
if ((mask & bit) == bit)
{
value |= GetStorage().FpFlags[flag] != 0 ? bit : 0u;
}
}
return value;
}
public unsafe void SetFPState(uint value, uint mask = uint.MaxValue)
{
for (int flag = 0; flag < RegisterConsts.FpFlagsCount; flag++)
{
uint bit = 1u << flag;
if ((mask & bit) == bit)
{
GetStorage().FpFlags[flag] = (value & bit) == bit ? 1u : 0u;
}
}
}
public int GetCounter() => GetStorage().Counter;
public void SetCounter(int value) => GetStorage().Counter = value;
public bool GetRunning() => GetStorage().Running != 0;
public void SetRunning(bool value) => GetStorage().Running = value ? 1 : 0;
public unsafe static int GetRegisterOffset(Register reg)
{
if (reg.Type == RegisterType.Integer)
{
if ((uint)reg.Index >= RegisterConsts.IntRegsCount)
{
throw new ArgumentException("Invalid register.");
}
return StorageOffset(ref _dummyStorage, ref _dummyStorage.X[reg.Index]);
}
else if (reg.Type == RegisterType.Vector)
{
if ((uint)reg.Index >= RegisterConsts.VecRegsCount)
{
throw new ArgumentException("Invalid register.");
}
return StorageOffset(ref _dummyStorage, ref _dummyStorage.V[reg.Index * 2]);
}
else if (reg.Type == RegisterType.Flag)
{
if ((uint)reg.Index >= RegisterConsts.FlagsCount)
{
throw new ArgumentException("Invalid register.");
}
return StorageOffset(ref _dummyStorage, ref _dummyStorage.Flags[reg.Index]);
}
else /* if (reg.Type == RegisterType.FpFlag) */
{
if ((uint)reg.Index >= RegisterConsts.FpFlagsCount)
{
throw new ArgumentException("Invalid register.");
}
return StorageOffset(ref _dummyStorage, ref _dummyStorage.FpFlags[reg.Index]);
}
}
public static int GetCounterOffset()
{
return StorageOffset(ref _dummyStorage, ref _dummyStorage.Counter);
}
public static int GetDispatchAddressOffset()
{
return StorageOffset(ref _dummyStorage, ref _dummyStorage.DispatchAddress);
}
public static int GetExclusiveAddressOffset()
{
return StorageOffset(ref _dummyStorage, ref _dummyStorage.ExclusiveAddress);
}
public static int GetExclusiveValueOffset()
{
return StorageOffset(ref _dummyStorage, ref _dummyStorage.ExclusiveValueLow);
}
public static int GetRunningOffset()
{
return StorageOffset(ref _dummyStorage, ref _dummyStorage.Running);
}
private static int StorageOffset<T>(ref NativeCtxStorage storage, ref T target)
{
return (int)Unsafe.ByteOffset(ref Unsafe.As<NativeCtxStorage, T>(ref storage), ref target);
}
private unsafe ref NativeCtxStorage GetStorage() => ref Unsafe.AsRef<NativeCtxStorage>((void*)_block.Pointer);
public void Dispose() => _block.Dispose();
}
}

View File

@@ -1,218 +0,0 @@
using ARMeilleure.CodeGen.Linking;
using ARMeilleure.Common;
using ARMeilleure.Decoders;
using ARMeilleure.Diagnostics;
using ARMeilleure.Instructions;
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Memory;
using ARMeilleure.State;
using System;
using System.Collections.Generic;
using System.Reflection;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
namespace ARMeilleure.Translation
{
class ArmEmitterContext : EmitterContext
{
private readonly Dictionary<ulong, Operand> _labels;
private OpCode _optOpLastCompare;
private OpCode _optOpLastFlagSet;
private Operand _optCmpTempN;
private Operand _optCmpTempM;
private Block _currBlock;
public Block CurrBlock
{
get
{
return _currBlock;
}
set
{
_currBlock = value;
ResetBlockState();
}
}
public OpCode CurrOp { get; set; }
public IMemoryManager Memory { get; }
public EntryTable<uint> CountTable { get; }
public AddressTable<ulong> FunctionTable { get; }
public TranslatorStubs Stubs { get; }
public ulong EntryAddress { get; }
public bool HighCq { get; }
public bool HasPtc { get; }
public Aarch32Mode Mode { get; }
private int _ifThenBlockStateIndex = 0;
private Condition[] _ifThenBlockState = { };
public bool IsInIfThenBlock => _ifThenBlockStateIndex < _ifThenBlockState.Length;
public Condition CurrentIfThenBlockCond => _ifThenBlockState[_ifThenBlockStateIndex];
public ArmEmitterContext(
IMemoryManager memory,
EntryTable<uint> countTable,
AddressTable<ulong> funcTable,
TranslatorStubs stubs,
ulong entryAddress,
bool highCq,
bool hasPtc,
Aarch32Mode mode)
{
Memory = memory;
CountTable = countTable;
FunctionTable = funcTable;
Stubs = stubs;
EntryAddress = entryAddress;
HighCq = highCq;
HasPtc = hasPtc;
Mode = mode;
_labels = new Dictionary<ulong, Operand>();
}
public override Operand Call(MethodInfo info, params Operand[] callArgs)
{
if (!HasPtc)
{
return base.Call(info, callArgs);
}
else
{
int index = Delegates.GetDelegateIndex(info);
IntPtr funcPtr = Delegates.GetDelegateFuncPtrByIndex(index);
OperandType returnType = GetOperandType(info.ReturnType);
Symbol symbol = new Symbol(SymbolType.DelegateTable, (ulong)index);
Symbols.Add((ulong)funcPtr.ToInt64(), info.Name);
return Call(Const(funcPtr.ToInt64(), symbol), returnType, callArgs);
}
}
public Operand GetLabel(ulong address)
{
if (!_labels.TryGetValue(address, out Operand label))
{
label = Label();
_labels.Add(address, label);
}
return label;
}
public void MarkComparison(Operand n, Operand m)
{
_optOpLastCompare = CurrOp;
_optCmpTempN = Copy(n);
_optCmpTempM = Copy(m);
}
public void MarkFlagSet(PState stateFlag)
{
// Set this only if any of the NZCV flag bits were modified.
// This is used to ensure that when emiting a direct IL branch
// instruction for compare + branch sequences, we're not expecting
// to use comparison values from an old instruction, when in fact
// the flags were already overwritten by another instruction further along.
if (stateFlag >= PState.VFlag)
{
_optOpLastFlagSet = CurrOp;
}
}
private void ResetBlockState()
{
_optOpLastCompare = null;
_optOpLastFlagSet = null;
}
public Operand TryGetComparisonResult(Condition condition)
{
if (_optOpLastCompare == null || _optOpLastCompare != _optOpLastFlagSet)
{
return default;
}
Operand n = _optCmpTempN;
Operand m = _optCmpTempM;
InstName cmpName = _optOpLastCompare.Instruction.Name;
if (cmpName == InstName.Subs)
{
switch (condition)
{
case Condition.Eq: return ICompareEqual (n, m);
case Condition.Ne: return ICompareNotEqual (n, m);
case Condition.GeUn: return ICompareGreaterOrEqualUI(n, m);
case Condition.LtUn: return ICompareLessUI (n, m);
case Condition.GtUn: return ICompareGreaterUI (n, m);
case Condition.LeUn: return ICompareLessOrEqualUI (n, m);
case Condition.Ge: return ICompareGreaterOrEqual (n, m);
case Condition.Lt: return ICompareLess (n, m);
case Condition.Gt: return ICompareGreater (n, m);
case Condition.Le: return ICompareLessOrEqual (n, m);
}
}
else if (cmpName == InstName.Adds && _optOpLastCompare is IOpCodeAluImm op)
{
// There are several limitations that needs to be taken into account for CMN comparisons:
// - The unsigned comparisons are not valid, as they depend on the
// carry flag value, and they will have different values for addition and
// subtraction. For addition, it's carry, and for subtraction, it's borrow.
// So, we need to make sure we're not doing a unsigned compare for the CMN case.
// - We can only do the optimization for the immediate variants,
// because when the second operand value is exactly INT_MIN, we can't
// negate the value as theres no positive counterpart.
// Such invalid values can't be encoded on the immediate encodings.
if (op.RegisterSize == RegisterSize.Int32)
{
m = Const((int)-op.Immediate);
}
else
{
m = Const(-op.Immediate);
}
switch (condition)
{
case Condition.Eq: return ICompareEqual (n, m);
case Condition.Ne: return ICompareNotEqual (n, m);
case Condition.Ge: return ICompareGreaterOrEqual(n, m);
case Condition.Lt: return ICompareLess (n, m);
case Condition.Gt: return ICompareGreater (n, m);
case Condition.Le: return ICompareLessOrEqual (n, m);
}
}
return default;
}
public void SetIfThenBlockState(Condition[] state)
{
_ifThenBlockState = state;
_ifThenBlockStateIndex = 0;
}
public void AdvanceIfThenBlockState()
{
if (IsInIfThenBlock)
{
_ifThenBlockStateIndex++;
}
}
}
}

View File

@@ -1,184 +0,0 @@
using ARMeilleure.CodeGen;
using ARMeilleure.CodeGen.Unwinding;
using ARMeilleure.Memory;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace ARMeilleure.Translation.Cache
{
static class JitCache
{
private const int PageSize = 4 * 1024;
private const int PageMask = PageSize - 1;
private const int CodeAlignment = 4; // Bytes.
private const int CacheSize = 2047 * 1024 * 1024;
private static ReservedRegion _jitRegion;
private static CacheMemoryAllocator _cacheAllocator;
private static readonly List<CacheEntry> _cacheEntries = new List<CacheEntry>();
private static readonly object _lock = new object();
private static bool _initialized;
public static IntPtr Base => _jitRegion.Pointer;
public static void Initialize(IJitMemoryAllocator allocator)
{
if (_initialized) return;
lock (_lock)
{
if (_initialized) return;
_jitRegion = new ReservedRegion(allocator, CacheSize);
_cacheAllocator = new CacheMemoryAllocator(CacheSize);
if (OperatingSystem.IsWindows())
{
JitUnwindWindows.InstallFunctionTableHandler(_jitRegion.Pointer, CacheSize, _jitRegion.Pointer + Allocate(PageSize));
}
_initialized = true;
}
}
public static IntPtr Map(CompiledFunction func)
{
byte[] code = func.Code;
lock (_lock)
{
Debug.Assert(_initialized);
int funcOffset = Allocate(code.Length);
IntPtr funcPtr = _jitRegion.Pointer + funcOffset;
ReprotectAsWritable(funcOffset, code.Length);
Marshal.Copy(code, 0, funcPtr, code.Length);
ReprotectAsExecutable(funcOffset, code.Length);
Add(funcOffset, code.Length, func.UnwindInfo);
return funcPtr;
}
}
public static void Unmap(IntPtr pointer)
{
lock (_lock)
{
Debug.Assert(_initialized);
int funcOffset = (int)(pointer.ToInt64() - _jitRegion.Pointer.ToInt64());
bool result = TryFind(funcOffset, out CacheEntry entry);
Debug.Assert(result);
_cacheAllocator.Free(funcOffset, AlignCodeSize(entry.Size));
Remove(funcOffset);
}
}
private static void ReprotectAsWritable(int offset, int size)
{
int endOffs = offset + size;
int regionStart = offset & ~PageMask;
int regionEnd = (endOffs + PageMask) & ~PageMask;
_jitRegion.Block.MapAsRwx((ulong)regionStart, (ulong)(regionEnd - regionStart));
}
private static void ReprotectAsExecutable(int offset, int size)
{
int endOffs = offset + size;
int regionStart = offset & ~PageMask;
int regionEnd = (endOffs + PageMask) & ~PageMask;
_jitRegion.Block.MapAsRx((ulong)regionStart, (ulong)(regionEnd - regionStart));
}
private static int Allocate(int codeSize)
{
codeSize = AlignCodeSize(codeSize);
int allocOffset = _cacheAllocator.Allocate(codeSize);
if (allocOffset < 0)
{
throw new OutOfMemoryException("JIT Cache exhausted.");
}
_jitRegion.ExpandIfNeeded((ulong)allocOffset + (ulong)codeSize);
return allocOffset;
}
private static int AlignCodeSize(int codeSize)
{
return checked(codeSize + (CodeAlignment - 1)) & ~(CodeAlignment - 1);
}
private static void Add(int offset, int size, UnwindInfo unwindInfo)
{
CacheEntry entry = new CacheEntry(offset, size, unwindInfo);
int index = _cacheEntries.BinarySearch(entry);
if (index < 0)
{
index = ~index;
}
_cacheEntries.Insert(index, entry);
}
private static void Remove(int offset)
{
int index = _cacheEntries.BinarySearch(new CacheEntry(offset, 0, default));
if (index < 0)
{
index = ~index - 1;
}
if (index >= 0)
{
_cacheEntries.RemoveAt(index);
}
}
public static bool TryFind(int offset, out CacheEntry entry)
{
lock (_lock)
{
int index = _cacheEntries.BinarySearch(new CacheEntry(offset, 0, default));
if (index < 0)
{
index = ~index - 1;
}
if (index >= 0)
{
entry = _cacheEntries[index];
return true;
}
}
entry = default;
return false;
}
}
}

View File

@@ -1,55 +0,0 @@
using ARMeilleure.CodeGen;
using ARMeilleure.CodeGen.Optimizations;
using ARMeilleure.CodeGen.X86;
using ARMeilleure.Diagnostics;
using ARMeilleure.IntermediateRepresentation;
namespace ARMeilleure.Translation
{
static class Compiler
{
public static CompiledFunction Compile(
ControlFlowGraph cfg,
OperandType[] argTypes,
OperandType retType,
CompilerOptions options)
{
CompilerContext cctx = new(cfg, argTypes, retType, options);
if (options.HasFlag(CompilerOptions.Optimize))
{
Logger.StartPass(PassName.TailMerge);
TailMerge.RunPass(cctx);
Logger.EndPass(PassName.TailMerge, cfg);
}
if (options.HasFlag(CompilerOptions.SsaForm))
{
Logger.StartPass(PassName.Dominance);
Dominance.FindDominators(cfg);
Dominance.FindDominanceFrontiers(cfg);
Logger.EndPass(PassName.Dominance);
Logger.StartPass(PassName.SsaConstruction);
Ssa.Construct(cfg);
Logger.EndPass(PassName.SsaConstruction, cfg);
}
else
{
Logger.StartPass(PassName.RegisterToLocal);
RegisterToLocal.Rename(cfg);
Logger.EndPass(PassName.RegisterToLocal, cfg);
}
return CodeGenerator.Generate(cctx);
}
}
}

View File

@@ -1,104 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
namespace ARMeilleure.Translation
{
static class DelegateHelper
{
private const string DelegateTypesAssemblyName = "JitDelegateTypes";
private static readonly ModuleBuilder _modBuilder;
private static readonly Dictionary<string, Type> _delegateTypesCache;
static DelegateHelper()
{
AssemblyBuilder asmBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName(DelegateTypesAssemblyName), AssemblyBuilderAccess.Run);
_modBuilder = asmBuilder.DefineDynamicModule(DelegateTypesAssemblyName);
_delegateTypesCache = new Dictionary<string, Type>();
}
public static Delegate GetDelegate(MethodInfo info)
{
ArgumentNullException.ThrowIfNull(info);
Type[] parameters = info.GetParameters().Select(pI => pI.ParameterType).ToArray();
Type returnType = info.ReturnType;
Type delegateType = GetDelegateType(parameters, returnType);
return Delegate.CreateDelegate(delegateType, info);
}
private static Type GetDelegateType(Type[] parameters, Type returnType)
{
string key = GetFunctionSignatureKey(parameters, returnType);
if (!_delegateTypesCache.TryGetValue(key, out Type delegateType))
{
delegateType = MakeDelegateType(parameters, returnType, key);
_delegateTypesCache.TryAdd(key, delegateType);
}
return delegateType;
}
private static string GetFunctionSignatureKey(Type[] parameters, Type returnType)
{
string sig = GetTypeName(returnType);
foreach (Type type in parameters)
{
sig += '_' + GetTypeName(type);
}
return sig;
}
private static string GetTypeName(Type type)
{
return type.FullName.Replace(".", string.Empty);
}
private const MethodAttributes CtorAttributes =
MethodAttributes.RTSpecialName |
MethodAttributes.HideBySig |
MethodAttributes.Public;
private const TypeAttributes DelegateTypeAttributes =
TypeAttributes.Class |
TypeAttributes.Public |
TypeAttributes.Sealed |
TypeAttributes.AnsiClass |
TypeAttributes.AutoClass;
private const MethodImplAttributes ImplAttributes =
MethodImplAttributes.Runtime |
MethodImplAttributes.Managed;
private const MethodAttributes InvokeAttributes =
MethodAttributes.Public |
MethodAttributes.HideBySig |
MethodAttributes.NewSlot |
MethodAttributes.Virtual;
private static readonly Type[] _delegateCtorSignature = { typeof(object), typeof(IntPtr) };
private static Type MakeDelegateType(Type[] parameters, Type returnType, string name)
{
TypeBuilder builder = _modBuilder.DefineType(name, DelegateTypeAttributes, typeof(MulticastDelegate));
builder.DefineConstructor(CtorAttributes, CallingConventions.Standard, _delegateCtorSignature).SetImplementationFlags(ImplAttributes);
builder.DefineMethod("Invoke", InvokeAttributes, returnType, parameters).SetImplementationFlags(ImplAttributes);
return builder.CreateTypeInfo();
}
}
}

View File

@@ -1,267 +0,0 @@
using ARMeilleure.Instructions;
using System;
using System.Collections.Generic;
using System.Reflection;
namespace ARMeilleure.Translation
{
static class Delegates
{
public static bool TryGetDelegateFuncPtrByIndex(int index, out IntPtr funcPtr)
{
if (index >= 0 && index < _delegates.Count)
{
funcPtr = _delegates.Values[index].FuncPtr; // O(1).
return true;
}
else
{
funcPtr = default;
return false;
}
}
public static IntPtr GetDelegateFuncPtrByIndex(int index)
{
if (index < 0 || index >= _delegates.Count)
{
throw new ArgumentOutOfRangeException($"({nameof(index)} = {index})");
}
return _delegates.Values[index].FuncPtr; // O(1).
}
public static IntPtr GetDelegateFuncPtr(MethodInfo info)
{
ArgumentNullException.ThrowIfNull(info);
string key = GetKey(info);
if (!_delegates.TryGetValue(key, out DelegateInfo dlgInfo)) // O(log(n)).
{
throw new KeyNotFoundException($"({nameof(key)} = {key})");
}
return dlgInfo.FuncPtr;
}
public static int GetDelegateIndex(MethodInfo info)
{
ArgumentNullException.ThrowIfNull(info);
string key = GetKey(info);
int index = _delegates.IndexOfKey(key); // O(log(n)).
if (index == -1)
{
throw new KeyNotFoundException($"({nameof(key)} = {key})");
}
return index;
}
private static void SetDelegateInfo(MethodInfo info)
{
string key = GetKey(info);
Delegate dlg = DelegateHelper.GetDelegate(info);
_delegates.Add(key, new DelegateInfo(dlg)); // ArgumentException (key).
}
private static string GetKey(MethodInfo info)
{
return $"{info.DeclaringType.Name}.{info.Name}";
}
private static readonly SortedList<string, DelegateInfo> _delegates;
static Delegates()
{
_delegates = new SortedList<string, DelegateInfo>();
SetDelegateInfo(typeof(Math).GetMethod(nameof(Math.Abs), new Type[] { typeof(double) }));
SetDelegateInfo(typeof(Math).GetMethod(nameof(Math.Ceiling), new Type[] { typeof(double) }));
SetDelegateInfo(typeof(Math).GetMethod(nameof(Math.Floor), new Type[] { typeof(double) }));
SetDelegateInfo(typeof(Math).GetMethod(nameof(Math.Round), new Type[] { typeof(double), typeof(MidpointRounding) }));
SetDelegateInfo(typeof(Math).GetMethod(nameof(Math.Truncate), new Type[] { typeof(double) }));
SetDelegateInfo(typeof(MathF).GetMethod(nameof(MathF.Abs), new Type[] { typeof(float) }));
SetDelegateInfo(typeof(MathF).GetMethod(nameof(MathF.Ceiling), new Type[] { typeof(float) }));
SetDelegateInfo(typeof(MathF).GetMethod(nameof(MathF.Floor), new Type[] { typeof(float) }));
SetDelegateInfo(typeof(MathF).GetMethod(nameof(MathF.Round), new Type[] { typeof(float), typeof(MidpointRounding) }));
SetDelegateInfo(typeof(MathF).GetMethod(nameof(MathF.Truncate), new Type[] { typeof(float) }));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.Break)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.CheckSynchronization)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.EnqueueForRejit)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntfrqEl0)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntpctEl0)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntvctEl0)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCtrEl0)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetDczidEl0)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFunctionAddress)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.InvalidateCacheLine)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetTpidrroEl0)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetTpidr32))); // A32 only.
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetTpidrEl0)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetTpidrEl032))); // A32 only.
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadByte)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt16)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt32)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt64)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadVector128)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetTpidrEl0)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetTpidrEl032))); // A32 only.
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SignalMemoryTracking)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SupervisorCall)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ThrowInvalidMemoryAccess)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.Undefined)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteByte)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt16)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt32)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt64)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteVector128)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.CountLeadingSigns)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.CountLeadingZeros)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32b)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32cb)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32ch)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32cw)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32cx)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32h)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32w)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32x)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Decrypt)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Encrypt)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.FixedRotate)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashChoose)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashLower)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashMajority)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashParity)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashUpper)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.InverseMixColumns)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.MixColumns)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.PolynomialMult64_128)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToS32)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToS64)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToU32)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToU64)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF64ToS32)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF64ToS64)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF64ToU32)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF64ToU64)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha1SchedulePart1)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha1SchedulePart2)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha256SchedulePart1)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha256SchedulePart2)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedShrImm64)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl1)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl2)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl3)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl4)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx1)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx2)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx3)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx4)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedShrImm64)));
SetDelegateInfo(typeof(SoftFloat16_32).GetMethod(nameof(SoftFloat16_32.FPConvert)));
SetDelegateInfo(typeof(SoftFloat16_64).GetMethod(nameof(SoftFloat16_64.FPConvert)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPAdd)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPAddFpscr))); // A32 only.
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompare)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareEQ)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareEQFpscr))); // A32 only.
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareGE)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareGEFpscr))); // A32 only.
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareGT)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareGTFpscr))); // A32 only.
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareLE)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareLEFpscr))); // A32 only.
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareLT)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareLTFpscr))); // A32 only.
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPDiv)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMax)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMaxFpscr))); // A32 only.
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMaxNum)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMaxNumFpscr))); // A32 only.
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMin)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMinFpscr))); // A32 only.
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMinNum)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMinNumFpscr))); // A32 only.
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMul)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulFpscr))); // A32 only.
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulAdd)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulAddFpscr))); // A32 only.
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulSub)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulSubFpscr))); // A32 only.
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulX)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPNegMulAdd)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPNegMulSub)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRecipEstimate)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRecipEstimateFpscr))); // A32 only.
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRecipStep))); // A32 only.
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRecipStepFused)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRecpX)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRSqrtEstimate)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRSqrtEstimateFpscr))); // A32 only.
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRSqrtStep))); // A32 only.
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRSqrtStepFused)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPSqrt)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPSub)));
SetDelegateInfo(typeof(SoftFloat32_16).GetMethod(nameof(SoftFloat32_16.FPConvert)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPAdd)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPAddFpscr))); // A32 only.
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompare)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareEQ)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareEQFpscr))); // A32 only.
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareGE)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareGEFpscr))); // A32 only.
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareGT)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareGTFpscr))); // A32 only.
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareLE)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareLEFpscr))); // A32 only.
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareLT)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareLTFpscr))); // A32 only.
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPDiv)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMax)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMaxFpscr))); // A32 only.
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMaxNum)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMaxNumFpscr))); // A32 only.
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMin)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMinFpscr))); // A32 only.
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMinNum)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMinNumFpscr))); // A32 only.
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMul)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulFpscr))); // A32 only.
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulAdd)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulAddFpscr))); // A32 only.
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulSub)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulSubFpscr))); // A32 only.
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulX)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPNegMulAdd)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPNegMulSub)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRecipEstimate)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRecipEstimateFpscr))); // A32 only.
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRecipStep))); // A32 only.
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRecipStepFused)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRecpX)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRSqrtEstimate)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRSqrtEstimateFpscr))); // A32 only.
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRSqrtStep))); // A32 only.
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRSqrtStepFused)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPSqrt)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPSub)));
SetDelegateInfo(typeof(SoftFloat64_16).GetMethod(nameof(SoftFloat64_16.FPConvert)));
}
}
}

View File

@@ -1,6 +0,0 @@
using System;
namespace ARMeilleure.Translation
{
delegate void DispatcherFunction(IntPtr nativeContext, ulong startAddress);
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,420 +0,0 @@
using ARMeilleure.State;
using Ryujinx.Common;
using Ryujinx.Common.Logging;
using System;
using System.Buffers.Binary;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading;
using static ARMeilleure.Translation.PTC.PtcFormatter;
namespace ARMeilleure.Translation.PTC
{
class PtcProfiler
{
private const string OuterHeaderMagicString = "Pohd\0\0\0\0";
private const uint InternalVersion = 1866; //! Not to be incremented manually for each change to the ARMeilleure project.
private const int SaveInterval = 30; // Seconds.
private const CompressionLevel SaveCompressionLevel = CompressionLevel.Fastest;
private readonly Ptc _ptc;
private readonly System.Timers.Timer _timer;
private readonly ulong _outerHeaderMagic;
private readonly ManualResetEvent _waitEvent;
private readonly object _lock;
private bool _disposed;
private Hash128 _lastHash;
public Dictionary<ulong, FuncProfile> ProfiledFuncs { get; private set; }
public bool Enabled { get; private set; }
public ulong StaticCodeStart { get; set; }
public ulong StaticCodeSize { get; set; }
public PtcProfiler(Ptc ptc)
{
_ptc = ptc;
_timer = new System.Timers.Timer((double)SaveInterval * 1000d);
_timer.Elapsed += PreSave;
_outerHeaderMagic = BinaryPrimitives.ReadUInt64LittleEndian(EncodingCache.UTF8NoBOM.GetBytes(OuterHeaderMagicString).AsSpan());
_waitEvent = new ManualResetEvent(true);
_lock = new object();
_disposed = false;
ProfiledFuncs = new Dictionary<ulong, FuncProfile>();
Enabled = false;
}
public void AddEntry(ulong address, ExecutionMode mode, bool highCq)
{
if (IsAddressInStaticCodeRange(address))
{
Debug.Assert(!highCq);
lock (_lock)
{
ProfiledFuncs.TryAdd(address, new FuncProfile(mode, highCq: false));
}
}
}
public void UpdateEntry(ulong address, ExecutionMode mode, bool highCq)
{
if (IsAddressInStaticCodeRange(address))
{
Debug.Assert(highCq);
lock (_lock)
{
Debug.Assert(ProfiledFuncs.ContainsKey(address));
ProfiledFuncs[address] = new FuncProfile(mode, highCq: true);
}
}
}
public bool IsAddressInStaticCodeRange(ulong address)
{
return address >= StaticCodeStart && address < StaticCodeStart + StaticCodeSize;
}
public ConcurrentQueue<(ulong address, FuncProfile funcProfile)> GetProfiledFuncsToTranslate(TranslatorCache<TranslatedFunction> funcs)
{
var profiledFuncsToTranslate = new ConcurrentQueue<(ulong address, FuncProfile funcProfile)>();
foreach (var profiledFunc in ProfiledFuncs)
{
if (!funcs.ContainsKey(profiledFunc.Key))
{
profiledFuncsToTranslate.Enqueue((profiledFunc.Key, profiledFunc.Value));
}
}
return profiledFuncsToTranslate;
}
public void ClearEntries()
{
ProfiledFuncs.Clear();
ProfiledFuncs.TrimExcess();
}
public void PreLoad()
{
_lastHash = default;
string fileNameActual = string.Concat(_ptc.CachePathActual, ".info");
string fileNameBackup = string.Concat(_ptc.CachePathBackup, ".info");
FileInfo fileInfoActual = new FileInfo(fileNameActual);
FileInfo fileInfoBackup = new FileInfo(fileNameBackup);
if (fileInfoActual.Exists && fileInfoActual.Length != 0L)
{
if (!Load(fileNameActual, false))
{
if (fileInfoBackup.Exists && fileInfoBackup.Length != 0L)
{
Load(fileNameBackup, true);
}
}
}
else if (fileInfoBackup.Exists && fileInfoBackup.Length != 0L)
{
Load(fileNameBackup, true);
}
}
private bool Load(string fileName, bool isBackup)
{
using (FileStream compressedStream = new(fileName, FileMode.Open))
using (DeflateStream deflateStream = new(compressedStream, CompressionMode.Decompress, true))
{
OuterHeader outerHeader = DeserializeStructure<OuterHeader>(compressedStream);
if (!outerHeader.IsHeaderValid())
{
InvalidateCompressedStream(compressedStream);
return false;
}
if (outerHeader.Magic != _outerHeaderMagic)
{
InvalidateCompressedStream(compressedStream);
return false;
}
if (outerHeader.InfoFileVersion != InternalVersion)
{
InvalidateCompressedStream(compressedStream);
return false;
}
if (outerHeader.Endianness != Ptc.GetEndianness())
{
InvalidateCompressedStream(compressedStream);
return false;
}
using (MemoryStream stream = new MemoryStream())
{
Debug.Assert(stream.Seek(0L, SeekOrigin.Begin) == 0L && stream.Length == 0L);
try
{
deflateStream.CopyTo(stream);
}
catch
{
InvalidateCompressedStream(compressedStream);
return false;
}
Debug.Assert(stream.Position == stream.Length);
stream.Seek(0L, SeekOrigin.Begin);
Hash128 expectedHash = DeserializeStructure<Hash128>(stream);
Hash128 actualHash = XXHash128.ComputeHash(GetReadOnlySpan(stream));
if (actualHash != expectedHash)
{
InvalidateCompressedStream(compressedStream);
return false;
}
ProfiledFuncs = Deserialize(stream);
Debug.Assert(stream.Position == stream.Length);
_lastHash = actualHash;
}
}
long fileSize = new FileInfo(fileName).Length;
Logger.Info?.Print(LogClass.Ptc, $"{(isBackup ? "Loaded Backup Profiling Info" : "Loaded Profiling Info")} (size: {fileSize} bytes, profiled functions: {ProfiledFuncs.Count}).");
return true;
}
private static Dictionary<ulong, FuncProfile> Deserialize(Stream stream)
{
return DeserializeDictionary<ulong, FuncProfile>(stream, (stream) => DeserializeStructure<FuncProfile>(stream));
}
private ReadOnlySpan<byte> GetReadOnlySpan(MemoryStream memoryStream)
{
return new(memoryStream.GetBuffer(), (int)memoryStream.Position, (int)memoryStream.Length - (int)memoryStream.Position);
}
private void InvalidateCompressedStream(FileStream compressedStream)
{
compressedStream.SetLength(0L);
}
private void PreSave(object source, System.Timers.ElapsedEventArgs e)
{
_waitEvent.Reset();
string fileNameActual = string.Concat(_ptc.CachePathActual, ".info");
string fileNameBackup = string.Concat(_ptc.CachePathBackup, ".info");
FileInfo fileInfoActual = new FileInfo(fileNameActual);
if (fileInfoActual.Exists && fileInfoActual.Length != 0L)
{
File.Copy(fileNameActual, fileNameBackup, true);
}
Save(fileNameActual);
_waitEvent.Set();
}
private void Save(string fileName)
{
int profiledFuncsCount;
OuterHeader outerHeader = new OuterHeader();
outerHeader.Magic = _outerHeaderMagic;
outerHeader.InfoFileVersion = InternalVersion;
outerHeader.Endianness = Ptc.GetEndianness();
outerHeader.SetHeaderHash();
using (MemoryStream stream = new MemoryStream())
{
Debug.Assert(stream.Seek(0L, SeekOrigin.Begin) == 0L && stream.Length == 0L);
stream.Seek((long)Unsafe.SizeOf<Hash128>(), SeekOrigin.Begin);
lock (_lock)
{
Serialize(stream, ProfiledFuncs);
profiledFuncsCount = ProfiledFuncs.Count;
}
Debug.Assert(stream.Position == stream.Length);
stream.Seek((long)Unsafe.SizeOf<Hash128>(), SeekOrigin.Begin);
Hash128 hash = XXHash128.ComputeHash(GetReadOnlySpan(stream));
stream.Seek(0L, SeekOrigin.Begin);
SerializeStructure(stream, hash);
if (hash == _lastHash)
{
return;
}
using (FileStream compressedStream = new(fileName, FileMode.OpenOrCreate))
using (DeflateStream deflateStream = new(compressedStream, SaveCompressionLevel, true))
{
try
{
SerializeStructure(compressedStream, outerHeader);
stream.WriteTo(deflateStream);
_lastHash = hash;
}
catch
{
compressedStream.Position = 0L;
_lastHash = default;
}
if (compressedStream.Position < compressedStream.Length)
{
compressedStream.SetLength(compressedStream.Position);
}
}
}
long fileSize = new FileInfo(fileName).Length;
if (fileSize != 0L)
{
Logger.Info?.Print(LogClass.Ptc, $"Saved Profiling Info (size: {fileSize} bytes, profiled functions: {profiledFuncsCount}).");
}
}
private void Serialize(Stream stream, Dictionary<ulong, FuncProfile> profiledFuncs)
{
SerializeDictionary(stream, profiledFuncs, (stream, structure) => SerializeStructure(stream, structure));
}
[StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 29*/)]
private struct OuterHeader
{
public ulong Magic;
public uint InfoFileVersion;
public bool Endianness;
public Hash128 HeaderHash;
public void SetHeaderHash()
{
Span<OuterHeader> spanHeader = MemoryMarshal.CreateSpan(ref this, 1);
HeaderHash = XXHash128.ComputeHash(MemoryMarshal.AsBytes(spanHeader).Slice(0, Unsafe.SizeOf<OuterHeader>() - Unsafe.SizeOf<Hash128>()));
}
public bool IsHeaderValid()
{
Span<OuterHeader> spanHeader = MemoryMarshal.CreateSpan(ref this, 1);
return XXHash128.ComputeHash(MemoryMarshal.AsBytes(spanHeader).Slice(0, Unsafe.SizeOf<OuterHeader>() - Unsafe.SizeOf<Hash128>())) == HeaderHash;
}
}
[StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 5*/)]
public struct FuncProfile
{
public ExecutionMode Mode;
public bool HighCq;
public FuncProfile(ExecutionMode mode, bool highCq)
{
Mode = mode;
HighCq = highCq;
}
}
public void Start()
{
if (_ptc.State == PtcState.Enabled ||
_ptc.State == PtcState.Continuing)
{
Enabled = true;
_timer.Enabled = true;
}
}
public void Stop()
{
Enabled = false;
if (!_disposed)
{
_timer.Enabled = false;
}
}
public void Wait()
{
_waitEvent.WaitOne();
}
public void Dispose()
{
if (!_disposed)
{
_disposed = true;
_timer.Elapsed -= PreSave;
_timer.Dispose();
Wait();
_waitEvent.Dispose();
}
}
}
}

View File

@@ -1,30 +0,0 @@
using ARMeilleure.Common;
using System;
using System.Runtime.InteropServices;
namespace ARMeilleure.Translation
{
class TranslatedFunction
{
private readonly GuestFunction _func; // Ensure that this delegate will not be garbage collected.
public Counter<uint> CallCounter { get; }
public ulong GuestSize { get; }
public bool HighCq { get; }
public IntPtr FuncPtr { get; }
public TranslatedFunction(GuestFunction func, Counter<uint> callCounter, ulong guestSize, bool highCq)
{
_func = func;
CallCounter = callCounter;
GuestSize = guestSize;
HighCq = highCq;
FuncPtr = Marshal.GetFunctionPointerForDelegate(func);
}
public ulong Execute(State.ExecutionContext context)
{
return _func(context.NativeContextPtr);
}
}
}

View File

@@ -1,565 +0,0 @@
using ARMeilleure.CodeGen;
using ARMeilleure.Common;
using ARMeilleure.Decoders;
using ARMeilleure.Diagnostics;
using ARMeilleure.Instructions;
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Memory;
using ARMeilleure.Signal;
using ARMeilleure.State;
using ARMeilleure.Translation.Cache;
using ARMeilleure.Translation.PTC;
using Ryujinx.Common;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
namespace ARMeilleure.Translation
{
public class Translator
{
private static readonly AddressTable<ulong>.Level[] Levels64Bit =
new AddressTable<ulong>.Level[]
{
new(31, 17),
new(23, 8),
new(15, 8),
new( 7, 8),
new( 2, 5)
};
private static readonly AddressTable<ulong>.Level[] Levels32Bit =
new AddressTable<ulong>.Level[]
{
new(31, 17),
new(23, 8),
new(15, 8),
new( 7, 8),
new( 1, 6)
};
private readonly IJitMemoryAllocator _allocator;
private readonly ConcurrentQueue<KeyValuePair<ulong, TranslatedFunction>> _oldFuncs;
private readonly Ptc _ptc;
internal TranslatorCache<TranslatedFunction> Functions { get; }
internal AddressTable<ulong> FunctionTable { get; }
internal EntryTable<uint> CountTable { get; }
internal TranslatorStubs Stubs { get; }
internal TranslatorQueue Queue { get; }
internal IMemoryManager Memory { get; }
private volatile int _threadCount;
// FIXME: Remove this once the init logic of the emulator will be redone.
public static readonly ManualResetEvent IsReadyForTranslation = new(false);
public Translator(IJitMemoryAllocator allocator, IMemoryManager memory, bool for64Bits)
{
_allocator = allocator;
Memory = memory;
_oldFuncs = new ConcurrentQueue<KeyValuePair<ulong, TranslatedFunction>>();
_ptc = new Ptc();
Queue = new TranslatorQueue();
JitCache.Initialize(allocator);
CountTable = new EntryTable<uint>();
Functions = new TranslatorCache<TranslatedFunction>();
FunctionTable = new AddressTable<ulong>(for64Bits ? Levels64Bit : Levels32Bit);
Stubs = new TranslatorStubs(this);
FunctionTable.Fill = (ulong)Stubs.SlowDispatchStub;
if (memory.Type.IsHostMapped())
{
NativeSignalHandler.InitializeSignalHandler();
}
}
public IPtcLoadState LoadDiskCache(string titleIdText, string displayVersion, bool enabled)
{
_ptc.Initialize(titleIdText, displayVersion, enabled, Memory.Type);
return _ptc;
}
public void PrepareCodeRange(ulong address, ulong size)
{
if (_ptc.Profiler.StaticCodeSize == 0)
{
_ptc.Profiler.StaticCodeStart = address;
_ptc.Profiler.StaticCodeSize = size;
}
}
public void Execute(State.ExecutionContext context, ulong address)
{
if (Interlocked.Increment(ref _threadCount) == 1)
{
IsReadyForTranslation.WaitOne();
if (_ptc.State == PtcState.Enabled)
{
Debug.Assert(Functions.Count == 0);
_ptc.LoadTranslations(this);
_ptc.MakeAndSaveTranslations(this);
}
_ptc.Profiler.Start();
_ptc.Disable();
// Simple heuristic, should be user configurable in future. (1 for 4 core/ht or less, 2 for 6 core + ht
// etc). All threads are normal priority except from the last, which just fills as much of the last core
// as the os lets it with a low priority. If we only have one rejit thread, it should be normal priority
// as highCq code is performance critical.
//
// TODO: Use physical cores rather than logical. This only really makes sense for processors with
// hyperthreading. Requires OS specific code.
int unboundedThreadCount = Math.Max(1, (Environment.ProcessorCount - 6) / 3);
int threadCount = Math.Min(4, unboundedThreadCount);
for (int i = 0; i < threadCount; i++)
{
bool last = i != 0 && i == unboundedThreadCount - 1;
Thread backgroundTranslatorThread = new Thread(BackgroundTranslate)
{
Name = "CPU.BackgroundTranslatorThread." + i,
Priority = last ? ThreadPriority.Lowest : ThreadPriority.Normal
};
backgroundTranslatorThread.Start();
}
}
Statistics.InitializeTimer();
NativeInterface.RegisterThread(context, Memory, this);
if (Optimizations.UseUnmanagedDispatchLoop)
{
Stubs.DispatchLoop(context.NativeContextPtr, address);
}
else
{
do
{
address = ExecuteSingle(context, address);
}
while (context.Running && address != 0);
}
NativeInterface.UnregisterThread();
if (Interlocked.Decrement(ref _threadCount) == 0)
{
ClearJitCache();
Queue.Dispose();
Stubs.Dispose();
FunctionTable.Dispose();
CountTable.Dispose();
_ptc.Close();
_ptc.Profiler.Stop();
_ptc.Dispose();
_ptc.Profiler.Dispose();
}
}
private ulong ExecuteSingle(State.ExecutionContext context, ulong address)
{
TranslatedFunction func = GetOrTranslate(address, context.ExecutionMode);
Statistics.StartTimer();
ulong nextAddr = func.Execute(context);
Statistics.StopTimer(address);
return nextAddr;
}
public ulong Step(State.ExecutionContext context, ulong address)
{
TranslatedFunction func = Translate(address, context.ExecutionMode, highCq: false, singleStep: true);
address = func.Execute(context);
EnqueueForDeletion(address, func);
return address;
}
internal TranslatedFunction GetOrTranslate(ulong address, ExecutionMode mode)
{
if (!Functions.TryGetValue(address, out TranslatedFunction func))
{
func = Translate(address, mode, highCq: false);
TranslatedFunction oldFunc = Functions.GetOrAdd(address, func.GuestSize, func);
if (oldFunc != func)
{
JitCache.Unmap(func.FuncPtr);
func = oldFunc;
}
if (_ptc.Profiler.Enabled)
{
_ptc.Profiler.AddEntry(address, mode, highCq: false);
}
RegisterFunction(address, func);
}
return func;
}
internal void RegisterFunction(ulong guestAddress, TranslatedFunction func)
{
if (FunctionTable.IsValid(guestAddress) && (Optimizations.AllowLcqInFunctionTable || func.HighCq))
{
Volatile.Write(ref FunctionTable.GetValue(guestAddress), (ulong)func.FuncPtr);
}
}
internal TranslatedFunction Translate(ulong address, ExecutionMode mode, bool highCq, bool singleStep = false)
{
var context = new ArmEmitterContext(
Memory,
CountTable,
FunctionTable,
Stubs,
address,
highCq,
_ptc.State != PtcState.Disabled,
mode: Aarch32Mode.User);
Logger.StartPass(PassName.Decoding);
Block[] blocks = Decoder.Decode(Memory, address, mode, highCq, singleStep ? DecoderMode.SingleInstruction : DecoderMode.MultipleBlocks);
Logger.EndPass(PassName.Decoding);
Logger.StartPass(PassName.Translation);
EmitSynchronization(context);
if (blocks[0].Address != address)
{
context.Branch(context.GetLabel(address));
}
ControlFlowGraph cfg = EmitAndGetCFG(context, blocks, out Range funcRange, out Counter<uint> counter);
ulong funcSize = funcRange.End - funcRange.Start;
Logger.EndPass(PassName.Translation, cfg);
Logger.StartPass(PassName.RegisterUsage);
RegisterUsage.RunPass(cfg, mode);
Logger.EndPass(PassName.RegisterUsage);
var retType = OperandType.I64;
var argTypes = new OperandType[] { OperandType.I64 };
var options = highCq ? CompilerOptions.HighCq : CompilerOptions.None;
if (context.HasPtc && !singleStep)
{
options |= CompilerOptions.Relocatable;
}
CompiledFunction compiledFunc = Compiler.Compile(cfg, argTypes, retType, options);
if (context.HasPtc && !singleStep)
{
Hash128 hash = Ptc.ComputeHash(Memory, address, funcSize);
_ptc.WriteCompiledFunction(address, funcSize, hash, highCq, compiledFunc);
}
GuestFunction func = compiledFunc.Map<GuestFunction>();
Allocators.ResetAll();
return new TranslatedFunction(func, counter, funcSize, highCq);
}
private void BackgroundTranslate()
{
while (_threadCount != 0 && Queue.TryDequeue(out RejitRequest request))
{
TranslatedFunction func = Translate(request.Address, request.Mode, highCq: true);
Functions.AddOrUpdate(request.Address, func.GuestSize, func, (key, oldFunc) =>
{
EnqueueForDeletion(key, oldFunc);
return func;
});
if (_ptc.Profiler.Enabled)
{
_ptc.Profiler.UpdateEntry(request.Address, request.Mode, highCq: true);
}
RegisterFunction(request.Address, func);
}
}
private readonly struct Range
{
public ulong Start { get; }
public ulong End { get; }
public Range(ulong start, ulong end)
{
Start = start;
End = end;
}
}
private static ControlFlowGraph EmitAndGetCFG(
ArmEmitterContext context,
Block[] blocks,
out Range range,
out Counter<uint> counter)
{
counter = null;
ulong rangeStart = ulong.MaxValue;
ulong rangeEnd = 0;
for (int blkIndex = 0; blkIndex < blocks.Length; blkIndex++)
{
Block block = blocks[blkIndex];
if (!block.Exit)
{
if (rangeStart > block.Address)
{
rangeStart = block.Address;
}
if (rangeEnd < block.EndAddress)
{
rangeEnd = block.EndAddress;
}
}
if (block.Address == context.EntryAddress && !context.HighCq)
{
EmitRejitCheck(context, out counter);
}
context.CurrBlock = block;
context.MarkLabel(context.GetLabel(block.Address));
if (block.Exit)
{
// Left option here as it may be useful if we need to return to managed rather than tail call in
// future. (eg. for debug)
bool useReturns = false;
InstEmitFlowHelper.EmitVirtualJump(context, Const(block.Address), isReturn: useReturns);
}
else
{
for (int opcIndex = 0; opcIndex < block.OpCodes.Count; opcIndex++)
{
OpCode opCode = block.OpCodes[opcIndex];
context.CurrOp = opCode;
bool isLastOp = opcIndex == block.OpCodes.Count - 1;
if (isLastOp && block.Branch != null && !block.Branch.Exit && block.Branch.Address <= block.Address)
{
EmitSynchronization(context);
}
Operand lblPredicateSkip = default;
if (context.IsInIfThenBlock && context.CurrentIfThenBlockCond != Condition.Al)
{
lblPredicateSkip = Label();
InstEmitFlowHelper.EmitCondBranch(context, lblPredicateSkip, context.CurrentIfThenBlockCond.Invert());
}
if (opCode is OpCode32 op && op.Cond < Condition.Al)
{
lblPredicateSkip = Label();
InstEmitFlowHelper.EmitCondBranch(context, lblPredicateSkip, op.Cond.Invert());
}
if (opCode.Instruction.Emitter != null)
{
opCode.Instruction.Emitter(context);
}
else
{
throw new InvalidOperationException($"Invalid instruction \"{opCode.Instruction.Name}\".");
}
if (lblPredicateSkip != default)
{
context.MarkLabel(lblPredicateSkip);
}
if (context.IsInIfThenBlock && opCode.Instruction.Name != InstName.It)
{
context.AdvanceIfThenBlockState();
}
}
}
}
range = new Range(rangeStart, rangeEnd);
return context.GetControlFlowGraph();
}
internal static void EmitRejitCheck(ArmEmitterContext context, out Counter<uint> counter)
{
const int MinsCallForRejit = 100;
counter = new Counter<uint>(context.CountTable);
Operand lblEnd = Label();
Operand address = !context.HasPtc ?
Const(ref counter.Value) :
Const(ref counter.Value, Ptc.CountTableSymbol);
Operand curCount = context.Load(OperandType.I32, address);
Operand count = context.Add(curCount, Const(1));
context.Store(address, count);
context.BranchIf(lblEnd, curCount, Const(MinsCallForRejit), Comparison.NotEqual, BasicBlockFrequency.Cold);
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.EnqueueForRejit)), Const(context.EntryAddress));
context.MarkLabel(lblEnd);
}
internal static void EmitSynchronization(EmitterContext context)
{
long countOffs = NativeContext.GetCounterOffset();
Operand lblNonZero = Label();
Operand lblExit = Label();
Operand countAddr = context.Add(context.LoadArgument(OperandType.I64, 0), Const(countOffs));
Operand count = context.Load(OperandType.I32, countAddr);
context.BranchIfTrue(lblNonZero, count, BasicBlockFrequency.Cold);
Operand running = context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.CheckSynchronization)));
context.BranchIfTrue(lblExit, running, BasicBlockFrequency.Cold);
context.Return(Const(0L));
context.MarkLabel(lblNonZero);
count = context.Subtract(count, Const(1));
context.Store(countAddr, count);
context.MarkLabel(lblExit);
}
public void InvalidateJitCacheRegion(ulong address, ulong size)
{
ulong[] overlapAddresses = Array.Empty<ulong>();
int overlapsCount = Functions.GetOverlaps(address, size, ref overlapAddresses);
if (overlapsCount != 0)
{
// If rejit is running, stop it as it may be trying to rejit a function on the invalidated region.
ClearRejitQueue(allowRequeue: true);
}
for (int index = 0; index < overlapsCount; index++)
{
ulong overlapAddress = overlapAddresses[index];
if (Functions.TryGetValue(overlapAddress, out TranslatedFunction overlap))
{
Functions.Remove(overlapAddress);
Volatile.Write(ref FunctionTable.GetValue(overlapAddress), FunctionTable.Fill);
EnqueueForDeletion(overlapAddress, overlap);
}
}
// TODO: Remove overlapping functions from the JitCache aswell.
// This should be done safely, with a mechanism to ensure the function is not being executed.
}
internal void EnqueueForRejit(ulong guestAddress, ExecutionMode mode)
{
Queue.Enqueue(guestAddress, mode);
}
private void EnqueueForDeletion(ulong guestAddress, TranslatedFunction func)
{
_oldFuncs.Enqueue(new(guestAddress, func));
}
private void ClearJitCache()
{
// Ensure no attempt will be made to compile new functions due to rejit.
ClearRejitQueue(allowRequeue: false);
List<TranslatedFunction> functions = Functions.AsList();
foreach (var func in functions)
{
JitCache.Unmap(func.FuncPtr);
func.CallCounter?.Dispose();
}
Functions.Clear();
while (_oldFuncs.TryDequeue(out var kv))
{
JitCache.Unmap(kv.Value.FuncPtr);
kv.Value.CallCounter?.Dispose();
}
}
private void ClearRejitQueue(bool allowRequeue)
{
if (!allowRequeue)
{
Queue.Clear();
return;
}
lock (Queue.Sync)
{
while (Queue.Count > 0 && Queue.TryDequeue(out RejitRequest request))
{
if (Functions.TryGetValue(request.Address, out var func) && func.CallCounter != null)
{
Volatile.Write(ref func.CallCounter.Value, 0);
}
}
}
}
}
}

View File

@@ -1,241 +0,0 @@
using ARMeilleure.Instructions;
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.State;
using ARMeilleure.Translation.Cache;
using System;
using System.Reflection;
using System.Runtime.InteropServices;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
namespace ARMeilleure.Translation
{
/// <summary>
/// Represents a stub manager.
/// </summary>
class TranslatorStubs : IDisposable
{
private static readonly Lazy<IntPtr> _slowDispatchStub = new(GenerateSlowDispatchStub, isThreadSafe: true);
private bool _disposed;
private readonly Translator _translator;
private readonly Lazy<IntPtr> _dispatchStub;
private readonly Lazy<DispatcherFunction> _dispatchLoop;
/// <summary>
/// Gets the dispatch stub.
/// </summary>
/// <exception cref="ObjectDisposedException"><see cref="TranslatorStubs"/> instance was disposed</exception>
public IntPtr DispatchStub
{
get
{
ObjectDisposedException.ThrowIf(_disposed, this);
return _dispatchStub.Value;
}
}
/// <summary>
/// Gets the slow dispatch stub.
/// </summary>
/// <exception cref="ObjectDisposedException"><see cref="TranslatorStubs"/> instance was disposed</exception>
public IntPtr SlowDispatchStub
{
get
{
ObjectDisposedException.ThrowIf(_disposed, this);
return _slowDispatchStub.Value;
}
}
/// <summary>
/// Gets the dispatch loop function.
/// </summary>
/// <exception cref="ObjectDisposedException"><see cref="TranslatorStubs"/> instance was disposed</exception>
public DispatcherFunction DispatchLoop
{
get
{
ObjectDisposedException.ThrowIf(_disposed, this);
return _dispatchLoop.Value;
}
}
/// <summary>
/// Initializes a new instance of the <see cref="TranslatorStubs"/> class with the specified
/// <see cref="Translator"/> instance.
/// </summary>
/// <param name="translator"><see cref="Translator"/> instance to use</param>
/// <exception cref="ArgumentNullException"><paramref name="translator"/> is null</exception>
public TranslatorStubs(Translator translator)
{
ArgumentNullException.ThrowIfNull(translator);
_translator = translator;
_dispatchStub = new(GenerateDispatchStub, isThreadSafe: true);
_dispatchLoop = new(GenerateDispatchLoop, isThreadSafe: true);
}
/// <summary>
/// Releases all resources used by the <see cref="TranslatorStubs"/> instance.
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Releases all unmanaged and optionally managed resources used by the <see cref="TranslatorStubs"/> instance.
/// </summary>
/// <param name="disposing"><see langword="true"/> to dispose managed resources also; otherwise just unmanaged resouces</param>
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (_dispatchStub.IsValueCreated)
{
JitCache.Unmap(_dispatchStub.Value);
}
if (_dispatchLoop.IsValueCreated)
{
JitCache.Unmap(Marshal.GetFunctionPointerForDelegate(_dispatchLoop.Value));
}
_disposed = true;
}
}
/// <summary>
/// Frees resources used by the <see cref="TranslatorStubs"/> instance.
/// </summary>
~TranslatorStubs()
{
Dispose(false);
}
/// <summary>
/// Generates a <see cref="DispatchStub"/>.
/// </summary>
/// <returns>Generated <see cref="DispatchStub"/></returns>
private IntPtr GenerateDispatchStub()
{
var context = new EmitterContext();
Operand lblFallback = Label();
Operand lblEnd = Label();
// Load the target guest address from the native context.
Operand nativeContext = context.LoadArgument(OperandType.I64, 0);
Operand guestAddress = context.Load(OperandType.I64,
context.Add(nativeContext, Const((ulong)NativeContext.GetDispatchAddressOffset())));
// Check if guest address is within range of the AddressTable.
Operand masked = context.BitwiseAnd(guestAddress, Const(~_translator.FunctionTable.Mask));
context.BranchIfTrue(lblFallback, masked);
Operand index = default;
Operand page = Const((long)_translator.FunctionTable.Base);
for (int i = 0; i < _translator.FunctionTable.Levels.Length; i++)
{
ref var level = ref _translator.FunctionTable.Levels[i];
// 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.
Operand mask = Const(level.Mask >> level.Index);
index = context.BitwiseAnd(context.ShiftRightUI(guestAddress, Const(level.Index)), mask);
if (i < _translator.FunctionTable.Levels.Length - 1)
{
page = context.Load(OperandType.I64, context.Add(page, context.ShiftLeft(index, Const(3))));
context.BranchIfFalse(lblFallback, page);
}
}
Operand hostAddress;
Operand hostAddressAddr = context.Add(page, context.ShiftLeft(index, Const(3)));
hostAddress = context.Load(OperandType.I64, hostAddressAddr);
context.Tailcall(hostAddress, nativeContext);
context.MarkLabel(lblFallback);
hostAddress = context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFunctionAddress)), guestAddress);
context.Tailcall(hostAddress, nativeContext);
var cfg = context.GetControlFlowGraph();
var retType = OperandType.I64;
var argTypes = new[] { OperandType.I64 };
var func = Compiler.Compile(cfg, argTypes, retType, CompilerOptions.HighCq).Map<GuestFunction>();
return Marshal.GetFunctionPointerForDelegate(func);
}
/// <summary>
/// Generates a <see cref="SlowDispatchStub"/>.
/// </summary>
/// <returns>Generated <see cref="SlowDispatchStub"/></returns>
private static IntPtr GenerateSlowDispatchStub()
{
var context = new EmitterContext();
// Load the target guest address from the native context.
Operand nativeContext = context.LoadArgument(OperandType.I64, 0);
Operand guestAddress = context.Load(OperandType.I64,
context.Add(nativeContext, Const((ulong)NativeContext.GetDispatchAddressOffset())));
MethodInfo getFuncAddress = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFunctionAddress));
Operand hostAddress = context.Call(getFuncAddress, guestAddress);
context.Tailcall(hostAddress, nativeContext);
var cfg = context.GetControlFlowGraph();
var retType = OperandType.I64;
var argTypes = new[] { OperandType.I64 };
var func = Compiler.Compile(cfg, argTypes, retType, CompilerOptions.HighCq).Map<GuestFunction>();
return Marshal.GetFunctionPointerForDelegate(func);
}
/// <summary>
/// Generates a <see cref="DispatchLoop"/> function.
/// </summary>
/// <returns><see cref="DispatchLoop"/> function</returns>
private DispatcherFunction GenerateDispatchLoop()
{
var context = new EmitterContext();
Operand beginLbl = Label();
Operand endLbl = Label();
Operand nativeContext = context.LoadArgument(OperandType.I64, 0);
Operand guestAddress = context.Copy(
context.AllocateLocal(OperandType.I64),
context.LoadArgument(OperandType.I64, 1));
Operand runningAddress = context.Add(nativeContext, Const((ulong)NativeContext.GetRunningOffset()));
Operand dispatchAddress = context.Add(nativeContext, Const((ulong)NativeContext.GetDispatchAddressOffset()));
context.MarkLabel(beginLbl);
context.Store(dispatchAddress, guestAddress);
context.Copy(guestAddress, context.Call(Const((ulong)DispatchStub), OperandType.I64, nativeContext));
context.BranchIfFalse(endLbl, guestAddress);
context.BranchIfFalse(endLbl, context.Load(OperandType.I32, runningAddress));
context.Branch(beginLbl);
context.MarkLabel(endLbl);
context.Return();
var cfg = context.GetControlFlowGraph();
var retType = OperandType.None;
var argTypes = new[] { OperandType.I64, OperandType.I64 };
return Compiler.Compile(cfg, argTypes, retType, CompilerOptions.HighCq).Map<DispatcherFunction>();
}
}
}

View File

@@ -3,40 +3,40 @@
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Avalonia" Version="0.10.18" />
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="0.10.18" />
<PackageVersion Include="Avalonia.Desktop" Version="0.10.18" />
<PackageVersion Include="Avalonia.Diagnostics" Version="0.10.18" />
<PackageVersion Include="Avalonia.Markup.Xaml.Loader" Version="0.10.18" />
<PackageVersion Include="Avalonia" Version="0.10.19" />
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="0.10.19" />
<PackageVersion Include="Avalonia.Desktop" Version="0.10.19" />
<PackageVersion Include="Avalonia.Diagnostics" Version="0.10.19" />
<PackageVersion Include="Avalonia.Markup.Xaml.Loader" Version="0.10.19" />
<PackageVersion Include="Avalonia.Svg" Version="0.10.18" />
<PackageVersion Include="Avalonia.Svg.Skia" Version="0.10.18" />
<PackageVersion Include="CommandLineParser" Version="2.9.1" />
<PackageVersion Include="Concentus" Version="1.1.7" />
<PackageVersion Include="Crc32.NET" Version="1.2.0" />
<PackageVersion Include="DiscordRichPresence" Version="1.1.3.18" />
<PackageVersion Include="DynamicData" Version="7.12.11" />
<PackageVersion Include="DynamicData" Version="7.13.5" />
<PackageVersion Include="FluentAvaloniaUI" Version="1.4.5" />
<PackageVersion Include="GtkSharp.Dependencies" Version="1.1.1" />
<PackageVersion Include="GtkSharp.Dependencies.osx" Version="0.0.5" />
<PackageVersion Include="jp2masa.Avalonia.Flexbox" Version="0.2.0" />
<PackageVersion Include="LibHac" Version="0.17.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.3" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.4.0" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.4.1" />
<PackageVersion Include="LibHac" Version="0.18.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.5.0" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
<PackageVersion Include="Microsoft.IO.RecyclableMemoryStream" Version="2.3.2" />
<PackageVersion Include="MsgPack.Cli" Version="1.0.1" />
<PackageVersion Include="NUnit" Version="3.13.3" />
<PackageVersion Include="NUnit3TestAdapter" Version="4.1.0" />
<PackageVersion Include="OpenTK.Core" Version="4.7.5" />
<PackageVersion Include="OpenTK.Graphics" Version="4.7.5" />
<PackageVersion Include="OpenTK.OpenAL" Version="4.7.5" />
<PackageVersion Include="OpenTK.Windowing.GraphicsLibraryFramework" Version="4.7.5" />
<PackageVersion Include="OpenTK.Core" Version="4.7.7" />
<PackageVersion Include="OpenTK.Graphics" Version="4.7.7" />
<PackageVersion Include="OpenTK.OpenAL" Version="4.7.7" />
<PackageVersion Include="OpenTK.Windowing.GraphicsLibraryFramework" Version="4.7.7" />
<PackageVersion Include="Ryujinx.Audio.OpenAL.Dependencies" Version="1.21.0.1" />
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.1-build13" />
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
<PackageVersion Include="Ryujinx.GtkSharp" Version="3.24.24.59-ryujinx" />
<PackageVersion Include="Ryujinx.SDL2-CS" Version="2.24.2-build21" />
<PackageVersion Include="Ryujinx.SDL2-CS" Version="2.26.3-build25" />
<PackageVersion Include="shaderc.net" Version="0.1.0" />
<PackageVersion Include="SharpZipLib" Version="1.4.1" />
<PackageVersion Include="SharpZipLib" Version="1.4.2" />
<PackageVersion Include="Silk.NET.Vulkan" Version="2.16.0" />
<PackageVersion Include="Silk.NET.Vulkan.Extensions.EXT" Version="2.16.0" />
<PackageVersion Include="Silk.NET.Vulkan.Extensions.KHR" Version="2.16.0" />
@@ -44,11 +44,10 @@
<PackageVersion Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta11" />
<PackageVersion Include="SPB" Version="0.0.4-build28" />
<PackageVersion Include="System.Drawing.Common" Version="7.0.0" />
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="6.25.1" />
<PackageVersion Include="System.IO.FileSystem.Primitives" Version="4.3.0" />
<PackageVersion Include="System.Management" Version="7.0.0" />
<PackageVersion Include="System.Net.NameResolution" Version="4.3.0" />
<PackageVersion Include="System.Threading.ThreadPool" Version="4.3.0" />
<PackageVersion Include="XamlNameReferenceGenerator" Version="1.5.1" />
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="6.30.0" />
<PackageVersion Include="System.IO.Hashing" Version="7.0.0" />
<PackageVersion Include="System.Management" Version="7.0.1" />
<PackageVersion Include="UnicornEngine.Unicorn" Version="2.0.2-rc1-fb78016" />
<PackageVersion Include="XamlNameReferenceGenerator" Version="1.6.1" />
</ItemGroup>
</Project>

View File

@@ -40,7 +40,7 @@
## Compatibility
As of November 2022, Ryujinx has been tested on approximately 3,800 titles; over 3,600 boot past menus and into gameplay, with roughly 3,200 of those being considered playable.
As of April 2023, Ryujinx has been tested on approximately 4,050 titles; over 4,000 boot past menus and into gameplay, with roughly 3,400 of those being considered playable.
You can check out the compatibility list [here](https://github.com/Ryujinx/Ryujinx-Games-List/issues). Anyone is free to submit a new game test or update an existing game test entry; simply follow the new issue template and testing guidelines, or post as a reply to the applicable game issue. Use the search function to see if a game has been tested already!
## Usage
@@ -96,7 +96,7 @@ Ryujinx system files are stored in the `Ryujinx` folder. This folder is located
- **GPU**
The GPU emulator emulates the Switch's Maxwell GPU using either the OpenGL (version 4.5 minimum), Vulkan, or Metal (via MoltenVK) APIs through a custom build of OpenTK or Silk.NET respectively. There are currently four graphics enhancements available to the end user in Ryujinx: Disk Shader Caching, Resolution Scaling, Aspect Ratio Adjustment, and Anisotropic Filtering. These enhancements can be adjusted or toggled as desired in the GUI.
The GPU emulator emulates the Switch's Maxwell GPU using either the OpenGL (version 4.5 minimum), Vulkan, or Metal (via MoltenVK) APIs through a custom build of OpenTK or Silk.NET respectively. There are currently six graphics enhancements available to the end user in Ryujinx: Disk Shader Caching, Resolution Scaling, Anti-Aliasing, Scaling Filters (including FSR), Anisotropic Filtering and Aspect Ratio Adjustment. These enhancements can be adjusted or toggled as desired in the GUI.
- **Input**

View File

@@ -1,223 +0,0 @@
using Ryujinx.Audio.Backends.Common;
using Ryujinx.Audio.Common;
using Ryujinx.Common.Logging;
using Ryujinx.Memory;
using System;
using System.Collections.Concurrent;
using System.Threading;
using static SDL2.SDL;
namespace Ryujinx.Audio.Backends.SDL2
{
class SDL2HardwareDeviceSession : HardwareDeviceSessionOutputBase
{
private SDL2HardwareDeviceDriver _driver;
private ConcurrentQueue<SDL2AudioBuffer> _queuedBuffers;
private DynamicRingBuffer _ringBuffer;
private ulong _playedSampleCount;
private ManualResetEvent _updateRequiredEvent;
private uint _outputStream;
private SDL_AudioCallback _callbackDelegate;
private int _bytesPerFrame;
private uint _sampleCount;
private bool _started;
private float _volume;
private ushort _nativeSampleFormat;
public SDL2HardwareDeviceSession(SDL2HardwareDeviceDriver driver, IVirtualMemoryManager memoryManager, SampleFormat requestedSampleFormat, uint requestedSampleRate, uint requestedChannelCount, float requestedVolume) : base(memoryManager, requestedSampleFormat, requestedSampleRate, requestedChannelCount)
{
_driver = driver;
_updateRequiredEvent = _driver.GetUpdateRequiredEvent();
_queuedBuffers = new ConcurrentQueue<SDL2AudioBuffer>();
_ringBuffer = new DynamicRingBuffer();
_callbackDelegate = Update;
_bytesPerFrame = BackendHelper.GetSampleSize(RequestedSampleFormat) * (int)RequestedChannelCount;
_nativeSampleFormat = SDL2HardwareDeviceDriver.GetSDL2Format(RequestedSampleFormat);
_sampleCount = uint.MaxValue;
_started = false;
_volume = requestedVolume;
}
private void EnsureAudioStreamSetup(AudioBuffer buffer)
{
uint bufferSampleCount = (uint)GetSampleCount(buffer);
bool needAudioSetup = _outputStream == 0 ||
(bufferSampleCount >= Constants.TargetSampleCount && bufferSampleCount < _sampleCount);
if (needAudioSetup)
{
_sampleCount = Math.Max(Constants.TargetSampleCount, bufferSampleCount);
uint newOutputStream = SDL2HardwareDeviceDriver.OpenStream(RequestedSampleFormat, RequestedSampleRate, RequestedChannelCount, _sampleCount, _callbackDelegate);
if (newOutputStream == 0)
{
// No stream in place, this is unexpected.
throw new InvalidOperationException($"OpenStream failed with error: \"{SDL_GetError()}\"");
}
else
{
if (_outputStream != 0)
{
SDL_CloseAudioDevice(_outputStream);
}
_outputStream = newOutputStream;
SDL_PauseAudioDevice(_outputStream, _started ? 0 : 1);
Logger.Info?.Print(LogClass.Audio, $"New audio stream setup with a target sample count of {_sampleCount}");
}
}
}
private unsafe void Update(IntPtr userdata, IntPtr stream, int streamLength)
{
Span<byte> streamSpan = new Span<byte>((void*)stream, streamLength);
int maxFrameCount = (int)GetSampleCount(streamLength);
int bufferedFrames = _ringBuffer.Length / _bytesPerFrame;
int frameCount = Math.Min(bufferedFrames, maxFrameCount);
if (frameCount == 0)
{
// SDL2 left the responsibility to the user to clear the buffer.
streamSpan.Fill(0);
return;
}
byte[] samples = new byte[frameCount * _bytesPerFrame];
_ringBuffer.Read(samples, 0, samples.Length);
fixed (byte* p = samples)
{
IntPtr pStreamSrc = (IntPtr)p;
// Zero the dest buffer
streamSpan.Fill(0);
// Apply volume to written data
SDL_MixAudioFormat(stream, pStreamSrc, _nativeSampleFormat, (uint)samples.Length, (int)(_volume * SDL_MIX_MAXVOLUME));
}
ulong sampleCount = GetSampleCount(samples.Length);
ulong availaibleSampleCount = sampleCount;
bool needUpdate = false;
while (availaibleSampleCount > 0 && _queuedBuffers.TryPeek(out SDL2AudioBuffer driverBuffer))
{
ulong sampleStillNeeded = driverBuffer.SampleCount - Interlocked.Read(ref driverBuffer.SamplePlayed);
ulong playedAudioBufferSampleCount = Math.Min(sampleStillNeeded, availaibleSampleCount);
ulong currentSamplePlayed = Interlocked.Add(ref driverBuffer.SamplePlayed, playedAudioBufferSampleCount);
availaibleSampleCount -= playedAudioBufferSampleCount;
if (currentSamplePlayed == driverBuffer.SampleCount)
{
_queuedBuffers.TryDequeue(out _);
needUpdate = true;
}
Interlocked.Add(ref _playedSampleCount, playedAudioBufferSampleCount);
}
// Notify the output if needed.
if (needUpdate)
{
_updateRequiredEvent.Set();
}
}
public override ulong GetPlayedSampleCount()
{
return Interlocked.Read(ref _playedSampleCount);
}
public override float GetVolume()
{
return _volume;
}
public override void PrepareToClose() { }
public override void QueueBuffer(AudioBuffer buffer)
{
EnsureAudioStreamSetup(buffer);
SDL2AudioBuffer driverBuffer = new SDL2AudioBuffer(buffer.DataPointer, GetSampleCount(buffer));
_ringBuffer.Write(buffer.Data, 0, buffer.Data.Length);
_queuedBuffers.Enqueue(driverBuffer);
}
public override void SetVolume(float volume)
{
_volume = volume;
}
public override void Start()
{
if (!_started)
{
if (_outputStream != 0)
{
SDL_PauseAudioDevice(_outputStream, 0);
}
_started = true;
}
}
public override void Stop()
{
if (_started)
{
if (_outputStream != 0)
{
SDL_PauseAudioDevice(_outputStream, 1);
}
_started = false;
}
}
public override void UnregisterBuffer(AudioBuffer buffer) { }
public override bool WasBufferFullyConsumed(AudioBuffer buffer)
{
if (!_queuedBuffers.TryPeek(out SDL2AudioBuffer driverBuffer))
{
return true;
}
return driverBuffer.DriverIdentifier != buffer.DataPointer;
}
protected virtual void Dispose(bool disposing)
{
if (disposing && _driver.Unregister(this))
{
PrepareToClose();
Stop();
if (_outputStream != 0)
{
SDL_CloseAudioDevice(_outputStream);
}
}
}
public override void Dispose()
{
Dispose(true);
}
}
}

View File

@@ -1,248 +0,0 @@
using Ryujinx.Audio.Backends.SoundIo.Native;
using Ryujinx.Audio.Common;
using Ryujinx.Audio.Integration;
using Ryujinx.Memory;
using System;
using System.Collections.Concurrent;
using System.Threading;
using static Ryujinx.Audio.Integration.IHardwareDeviceDriver;
using static Ryujinx.Audio.Backends.SoundIo.Native.SoundIo;
namespace Ryujinx.Audio.Backends.SoundIo
{
public class SoundIoHardwareDeviceDriver : IHardwareDeviceDriver
{
private readonly SoundIoContext _audioContext;
private readonly SoundIoDeviceContext _audioDevice;
private readonly ManualResetEvent _updateRequiredEvent;
private readonly ManualResetEvent _pauseEvent;
private readonly ConcurrentDictionary<SoundIoHardwareDeviceSession, byte> _sessions;
private int _disposeState;
public SoundIoHardwareDeviceDriver()
{
_audioContext = SoundIoContext.Create();
_updateRequiredEvent = new ManualResetEvent(false);
_pauseEvent = new ManualResetEvent(true);
_sessions = new ConcurrentDictionary<SoundIoHardwareDeviceSession, byte>();
_audioContext.Connect();
_audioContext.FlushEvents();
_audioDevice = FindValidAudioDevice(_audioContext, true);
}
public static bool IsSupported => IsSupportedInternal();
private static bool IsSupportedInternal()
{
SoundIoContext context = null;
SoundIoDeviceContext device = null;
SoundIoOutStreamContext stream = null;
bool backendDisconnected = false;
try
{
context = SoundIoContext.Create();
context.OnBackendDisconnect = err =>
{
backendDisconnected = true;
};
context.Connect();
context.FlushEvents();
if (backendDisconnected)
{
return false;
}
if (context.OutputDeviceCount == 0)
{
return false;
}
device = FindValidAudioDevice(context);
if (device == null || backendDisconnected)
{
return false;
}
stream = device.CreateOutStream();
if (stream == null || backendDisconnected)
{
return false;
}
return true;
}
catch
{
return false;
}
finally
{
stream?.Dispose();
context?.Dispose();
}
}
private static SoundIoDeviceContext FindValidAudioDevice(SoundIoContext audioContext, bool fallback = false)
{
SoundIoDeviceContext defaultAudioDevice = audioContext.GetOutputDevice(audioContext.DefaultOutputDeviceIndex);
if (!defaultAudioDevice.IsRaw)
{
return defaultAudioDevice;
}
for (int i = 0; i < audioContext.OutputDeviceCount; i++)
{
SoundIoDeviceContext audioDevice = audioContext.GetOutputDevice(i);
if (audioDevice.Id == defaultAudioDevice.Id && !audioDevice.IsRaw)
{
return audioDevice;
}
}
return fallback ? defaultAudioDevice : null;
}
public ManualResetEvent GetUpdateRequiredEvent()
{
return _updateRequiredEvent;
}
public ManualResetEvent GetPauseEvent()
{
return _pauseEvent;
}
public IHardwareDeviceSession OpenDeviceSession(Direction direction, IVirtualMemoryManager memoryManager, SampleFormat sampleFormat, uint sampleRate, uint channelCount, float volume)
{
if (channelCount == 0)
{
channelCount = 2;
}
if (sampleRate == 0)
{
sampleRate = Constants.TargetSampleRate;
}
volume = Math.Clamp(volume, 0, 1);
if (direction != Direction.Output)
{
throw new NotImplementedException("Input direction is currently not implemented on SoundIO backend!");
}
SoundIoHardwareDeviceSession session = new SoundIoHardwareDeviceSession(this, memoryManager, sampleFormat, sampleRate, channelCount, volume);
_sessions.TryAdd(session, 0);
return session;
}
internal bool Unregister(SoundIoHardwareDeviceSession session)
{
return _sessions.TryRemove(session, out _);
}
public static SoundIoFormat GetSoundIoFormat(SampleFormat format)
{
return format switch
{
SampleFormat.PcmInt8 => SoundIoFormat.S8,
SampleFormat.PcmInt16 => SoundIoFormat.S16LE,
SampleFormat.PcmInt24 => SoundIoFormat.S24LE,
SampleFormat.PcmInt32 => SoundIoFormat.S32LE,
SampleFormat.PcmFloat => SoundIoFormat.Float32LE,
_ => throw new ArgumentException ($"Unsupported sample format {format}"),
};
}
internal SoundIoOutStreamContext OpenStream(SampleFormat requestedSampleFormat, uint requestedSampleRate, uint requestedChannelCount)
{
SoundIoFormat driverSampleFormat = GetSoundIoFormat(requestedSampleFormat);
if (!_audioDevice.SupportsSampleRate((int)requestedSampleRate))
{
throw new ArgumentException($"This sound device does not support a sample rate of {requestedSampleRate}Hz");
}
if (!_audioDevice.SupportsFormat(driverSampleFormat))
{
throw new ArgumentException($"This sound device does not support {requestedSampleFormat}");
}
if (!_audioDevice.SupportsChannelCount((int)requestedChannelCount))
{
throw new ArgumentException($"This sound device does not support channel count {requestedChannelCount}");
}
SoundIoOutStreamContext result = _audioDevice.CreateOutStream();
result.Name = "Ryujinx";
result.Layout = SoundIoChannelLayout.GetDefaultValue((int)requestedChannelCount);
result.Format = driverSampleFormat;
result.SampleRate = (int)requestedSampleRate;
return result;
}
internal void FlushContextEvents()
{
_audioContext.FlushEvents();
}
public void Dispose()
{
if (Interlocked.CompareExchange(ref _disposeState, 1, 0) == 0)
{
Dispose(true);
}
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
foreach (SoundIoHardwareDeviceSession session in _sessions.Keys)
{
session.Dispose();
}
_audioContext.Disconnect();
_audioContext.Dispose();
_pauseEvent.Dispose();
}
}
public bool SupportsSampleRate(uint sampleRate)
{
return _audioDevice.SupportsSampleRate((int)sampleRate);
}
public bool SupportsSampleFormat(SampleFormat sampleFormat)
{
return _audioDevice.SupportsFormat(GetSoundIoFormat(sampleFormat));
}
public bool SupportsChannelCount(uint channelCount)
{
return _audioDevice.SupportsChannelCount((int)channelCount);
}
public bool SupportsDirection(Direction direction)
{
// TODO: add direction input when supported.
return direction == Direction.Output;
}
}
}

View File

@@ -1,181 +0,0 @@
using Ryujinx.Audio.Backends.Common;
using Ryujinx.Audio.Backends.Dummy;
using Ryujinx.Audio.Common;
using Ryujinx.Audio.Integration;
using Ryujinx.Common.Logging;
using Ryujinx.Memory;
using System;
using System.Threading;
using static Ryujinx.Audio.Integration.IHardwareDeviceDriver;
namespace Ryujinx.Audio.Backends.CompatLayer
{
public class CompatLayerHardwareDeviceDriver : IHardwareDeviceDriver
{
private IHardwareDeviceDriver _realDriver;
public CompatLayerHardwareDeviceDriver(IHardwareDeviceDriver realDevice)
{
_realDriver = realDevice;
}
public void Dispose()
{
_realDriver.Dispose();
}
public ManualResetEvent GetUpdateRequiredEvent()
{
return _realDriver.GetUpdateRequiredEvent();
}
public ManualResetEvent GetPauseEvent()
{
return _realDriver.GetPauseEvent();
}
private uint SelectHardwareChannelCount(uint targetChannelCount)
{
if (_realDriver.SupportsChannelCount(targetChannelCount))
{
return targetChannelCount;
}
return targetChannelCount switch
{
6 => SelectHardwareChannelCount(2),
2 => SelectHardwareChannelCount(1),
1 => throw new ArgumentException("No valid channel configuration found!"),
_ => throw new ArgumentException($"Invalid targetChannelCount {targetChannelCount}")
};
}
private SampleFormat SelectHardwareSampleFormat(SampleFormat targetSampleFormat)
{
if (_realDriver.SupportsSampleFormat(targetSampleFormat))
{
return targetSampleFormat;
}
// Attempt conversion from PCM16.
if (targetSampleFormat == SampleFormat.PcmInt16)
{
// Prefer PCM32 if we need to convert.
if (_realDriver.SupportsSampleFormat(SampleFormat.PcmInt32))
{
return SampleFormat.PcmInt32;
}
// If not supported, PCM float provides the best quality with a cost lower than PCM24.
if (_realDriver.SupportsSampleFormat(SampleFormat.PcmFloat))
{
return SampleFormat.PcmFloat;
}
// TODO: Implement PCM24 conversion.
// If nothing is truly supported, attempt PCM8 at the cost of loosing quality.
if (_realDriver.SupportsSampleFormat(SampleFormat.PcmInt8))
{
return SampleFormat.PcmInt8;
}
}
throw new ArgumentException("No valid sample format configuration found!");
}
public IHardwareDeviceSession OpenDeviceSession(Direction direction, IVirtualMemoryManager memoryManager, SampleFormat sampleFormat, uint sampleRate, uint channelCount, float volume)
{
if (channelCount == 0)
{
channelCount = 2;
}
if (sampleRate == 0)
{
sampleRate = Constants.TargetSampleRate;
}
volume = Math.Clamp(volume, 0, 1);
if (!_realDriver.SupportsDirection(direction))
{
if (direction == Direction.Input)
{
Logger.Warning?.Print(LogClass.Audio, "The selected audio backend doesn't support audio input, fallback to dummy...");
return new DummyHardwareDeviceSessionInput(this, memoryManager, sampleFormat, sampleRate, channelCount);
}
throw new NotImplementedException();
}
SampleFormat hardwareSampleFormat = SelectHardwareSampleFormat(sampleFormat);
uint hardwareChannelCount = SelectHardwareChannelCount(channelCount);
IHardwareDeviceSession realSession = _realDriver.OpenDeviceSession(direction, memoryManager, hardwareSampleFormat, sampleRate, hardwareChannelCount, volume);
if (hardwareChannelCount == channelCount && hardwareSampleFormat == sampleFormat)
{
return realSession;
}
if (hardwareSampleFormat != sampleFormat)
{
Logger.Warning?.Print(LogClass.Audio, $"{sampleFormat} isn't supported by the audio device, conversion to {hardwareSampleFormat} will happen.");
if (hardwareSampleFormat < sampleFormat)
{
Logger.Warning?.Print(LogClass.Audio, $"{hardwareSampleFormat} has lower quality than {sampleFormat}, expect some loss in audio fidelity.");
}
}
if (direction == Direction.Input)
{
Logger.Warning?.Print(LogClass.Audio, $"The selected audio backend doesn't support the requested audio input configuration, fallback to dummy...");
// TODO: We currently don't support audio input upsampling/downsampling, implement this.
realSession.Dispose();
return new DummyHardwareDeviceSessionInput(this, memoryManager, sampleFormat, sampleRate, channelCount);
}
// It must be a HardwareDeviceSessionOutputBase.
if (realSession is not HardwareDeviceSessionOutputBase realSessionOutputBase)
{
throw new InvalidOperationException($"Real driver session class type isn't based on {typeof(HardwareDeviceSessionOutputBase).Name}.");
}
// If we need to do post processing before sending to the hardware device, wrap around it.
return new CompatLayerHardwareDeviceSession(realSessionOutputBase, sampleFormat, channelCount);
}
public bool SupportsChannelCount(uint channelCount)
{
return channelCount == 1 || channelCount == 2 || channelCount == 6;
}
public bool SupportsSampleFormat(SampleFormat sampleFormat)
{
// TODO: More formats.
return sampleFormat == SampleFormat.PcmInt16;
}
public bool SupportsSampleRate(uint sampleRate)
{
// TODO: More sample rates.
return sampleRate == Constants.TargetSampleRate;
}
public IHardwareDeviceDriver GetRealDeviceDriver()
{
return _realDriver;
}
public bool SupportsDirection(Direction direction)
{
return direction == Direction.Input || direction == Direction.Output;
}
}
}

View File

@@ -1,159 +0,0 @@
using Ryujinx.Audio.Backends.Common;
using Ryujinx.Audio.Common;
using Ryujinx.Audio.Renderer.Dsp;
using System;
using System.Runtime.InteropServices;
namespace Ryujinx.Audio.Backends.CompatLayer
{
class CompatLayerHardwareDeviceSession : HardwareDeviceSessionOutputBase
{
private HardwareDeviceSessionOutputBase _realSession;
private SampleFormat _userSampleFormat;
private uint _userChannelCount;
public CompatLayerHardwareDeviceSession(HardwareDeviceSessionOutputBase realSession, SampleFormat userSampleFormat, uint userChannelCount) : base(realSession.MemoryManager, realSession.RequestedSampleFormat, realSession.RequestedSampleRate, userChannelCount)
{
_realSession = realSession;
_userSampleFormat = userSampleFormat;
_userChannelCount = userChannelCount;
}
public override void Dispose()
{
_realSession.Dispose();
}
public override ulong GetPlayedSampleCount()
{
return _realSession.GetPlayedSampleCount();
}
public override float GetVolume()
{
return _realSession.GetVolume();
}
public override void PrepareToClose()
{
_realSession.PrepareToClose();
}
public override void QueueBuffer(AudioBuffer buffer)
{
SampleFormat realSampleFormat = _realSession.RequestedSampleFormat;
if (_userSampleFormat != realSampleFormat)
{
if (_userSampleFormat != SampleFormat.PcmInt16)
{
throw new NotImplementedException("Converting formats other than PCM16 is not supported.");
}
int userSampleCount = buffer.Data.Length / BackendHelper.GetSampleSize(_userSampleFormat);
ReadOnlySpan<short> samples = MemoryMarshal.Cast<byte, short>(buffer.Data);
byte[] convertedSamples = new byte[BackendHelper.GetSampleSize(realSampleFormat) * userSampleCount];
switch (realSampleFormat)
{
case SampleFormat.PcmInt8:
PcmHelper.Convert(MemoryMarshal.Cast<byte, sbyte>(convertedSamples), samples);
break;
case SampleFormat.PcmInt32:
PcmHelper.Convert(MemoryMarshal.Cast<byte, int>(convertedSamples), samples);
break;
case SampleFormat.PcmFloat:
PcmHelper.ConvertSampleToPcmFloat(MemoryMarshal.Cast<byte, float>(convertedSamples), samples);
break;
default:
throw new NotImplementedException($"Sample format conversion from {_userSampleFormat} to {realSampleFormat} not implemented.");
}
buffer.Data = convertedSamples;
}
_realSession.QueueBuffer(buffer);
}
public override bool RegisterBuffer(AudioBuffer buffer, byte[] samples)
{
if (samples == null)
{
return false;
}
if (_userChannelCount != _realSession.RequestedChannelCount)
{
if (_userSampleFormat != SampleFormat.PcmInt16)
{
throw new NotImplementedException("Downmixing formats other than PCM16 is not supported.");
}
ReadOnlySpan<short> samplesPCM16 = MemoryMarshal.Cast<byte, short>(samples);
if (_userChannelCount == 6)
{
samplesPCM16 = Downmixing.DownMixSurroundToStereo(samplesPCM16);
if (_realSession.RequestedChannelCount == 1)
{
samplesPCM16 = Downmixing.DownMixStereoToMono(samplesPCM16);
}
}
else if (_userChannelCount == 2 && _realSession.RequestedChannelCount == 1)
{
samplesPCM16 = Downmixing.DownMixStereoToMono(samplesPCM16);
}
else
{
throw new NotImplementedException($"Downmixing from {_userChannelCount} to {_realSession.RequestedChannelCount} not implemented.");
}
samples = MemoryMarshal.Cast<short, byte>(samplesPCM16).ToArray();
}
AudioBuffer fakeBuffer = new AudioBuffer
{
BufferTag = buffer.BufferTag,
DataPointer = buffer.DataPointer,
DataSize = (ulong)samples.Length
};
bool result = _realSession.RegisterBuffer(fakeBuffer, samples);
if (result)
{
buffer.Data = fakeBuffer.Data;
buffer.DataSize = fakeBuffer.DataSize;
}
return result;
}
public override void SetVolume(float volume)
{
_realSession.SetVolume(volume);
}
public override void Start()
{
_realSession.Start();
}
public override void Stop()
{
_realSession.Stop();
}
public override void UnregisterBuffer(AudioBuffer buffer)
{
_realSession.UnregisterBuffer(buffer);
}
public override bool WasBufferFullyConsumed(AudioBuffer buffer)
{
return _realSession.WasBufferFullyConsumed(buffer);
}
}
}

View File

@@ -1,87 +0,0 @@
using Ryujinx.Audio.Common;
using Ryujinx.Audio.Integration;
using Ryujinx.Memory;
using System.Threading;
using static Ryujinx.Audio.Integration.IHardwareDeviceDriver;
namespace Ryujinx.Audio.Backends.Dummy
{
public class DummyHardwareDeviceDriver : IHardwareDeviceDriver
{
private ManualResetEvent _updateRequiredEvent;
private ManualResetEvent _pauseEvent;
public DummyHardwareDeviceDriver()
{
_updateRequiredEvent = new ManualResetEvent(false);
_pauseEvent = new ManualResetEvent(true);
}
public IHardwareDeviceSession OpenDeviceSession(Direction direction, IVirtualMemoryManager memoryManager, SampleFormat sampleFormat, uint sampleRate, uint channelCount, float volume)
{
if (sampleRate == 0)
{
sampleRate = Constants.TargetSampleRate;
}
if (channelCount == 0)
{
channelCount = 2;
}
if (direction == Direction.Output)
{
return new DummyHardwareDeviceSessionOutput(this, memoryManager, sampleFormat, sampleRate, channelCount, volume);
}
else
{
return new DummyHardwareDeviceSessionInput(this, memoryManager, sampleFormat, sampleRate, channelCount);
}
}
public ManualResetEvent GetUpdateRequiredEvent()
{
return _updateRequiredEvent;
}
public ManualResetEvent GetPauseEvent()
{
return _pauseEvent;
}
public void Dispose()
{
Dispose(true);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
// NOTE: The _updateRequiredEvent will be disposed somewhere else.
_pauseEvent.Dispose();
}
}
public bool SupportsSampleRate(uint sampleRate)
{
return true;
}
public bool SupportsSampleFormat(SampleFormat sampleFormat)
{
return true;
}
public bool SupportsDirection(Direction direction)
{
return direction == Direction.Output || direction == Direction.Input;
}
public bool SupportsChannelCount(uint channelCount)
{
return channelCount == 1 || channelCount == 2 || channelCount == 6;
}
}
}

View File

@@ -1,516 +0,0 @@
using Ryujinx.Audio.Integration;
using Ryujinx.Common;
using System;
using System.Diagnostics;
namespace Ryujinx.Audio.Common
{
/// <summary>
/// An audio device session.
/// </summary>
class AudioDeviceSession : IDisposable
{
/// <summary>
/// The volume of the <see cref="AudioDeviceSession"/>.
/// </summary>
private float _volume;
/// <summary>
/// The state of the <see cref="AudioDeviceSession"/>.
/// </summary>
private AudioDeviceState _state;
/// <summary>
/// Array of all buffers currently used or released.
/// </summary>
private AudioBuffer[] _buffers;
/// <summary>
/// The server index inside <see cref="_buffers"/> (appended but not queued to device driver).
/// </summary>
private uint _serverBufferIndex;
/// <summary>
/// The hardware index inside <see cref="_buffers"/> (queued to device driver).
/// </summary>
private uint _hardwareBufferIndex;
/// <summary>
/// The released index inside <see cref="_buffers"/> (released by the device driver).
/// </summary>
private uint _releasedBufferIndex;
/// <summary>
/// The count of buffer appended (server side).
/// </summary>
private uint _bufferAppendedCount;
/// <summary>
/// The count of buffer registered (driver side).
/// </summary>
private uint _bufferRegisteredCount;
/// <summary>
/// The count of buffer released (released by the driver side).
/// </summary>
private uint _bufferReleasedCount;
/// <summary>
/// The released buffer event.
/// </summary>
private IWritableEvent _bufferEvent;
/// <summary>
/// The session on the device driver.
/// </summary>
private IHardwareDeviceSession _hardwareDeviceSession;
/// <summary>
/// Max number of buffers that can be registered to the device driver at a time.
/// </summary>
private uint _bufferRegisteredLimit;
/// <summary>
/// Create a new <see cref="AudioDeviceSession"/>.
/// </summary>
/// <param name="deviceSession">The device driver session associated</param>
/// <param name="bufferEvent">The release buffer event</param>
/// <param name="bufferRegisteredLimit">The max number of buffers that can be registered to the device driver at a time</param>
public AudioDeviceSession(IHardwareDeviceSession deviceSession, IWritableEvent bufferEvent, uint bufferRegisteredLimit = 4)
{
_bufferEvent = bufferEvent;
_hardwareDeviceSession = deviceSession;
_bufferRegisteredLimit = bufferRegisteredLimit;
_buffers = new AudioBuffer[Constants.AudioDeviceBufferCountMax];
_serverBufferIndex = 0;
_hardwareBufferIndex = 0;
_releasedBufferIndex = 0;
_bufferAppendedCount = 0;
_bufferRegisteredCount = 0;
_bufferReleasedCount = 0;
_volume = deviceSession.GetVolume();
_state = AudioDeviceState.Stopped;
}
/// <summary>
/// Get the released buffer event.
/// </summary>
/// <returns>The released buffer event</returns>
public IWritableEvent GetBufferEvent()
{
return _bufferEvent;
}
/// <summary>
/// Get the state of the session.
/// </summary>
/// <returns>The state of the session</returns>
public AudioDeviceState GetState()
{
Debug.Assert(_state == AudioDeviceState.Started || _state == AudioDeviceState.Stopped);
return _state;
}
/// <summary>
/// Get the total buffer count (server + driver + released).
/// </summary>
/// <returns>Return the total buffer count</returns>
private uint GetTotalBufferCount()
{
uint bufferCount = _bufferAppendedCount + _bufferRegisteredCount + _bufferReleasedCount;
Debug.Assert(bufferCount <= Constants.AudioDeviceBufferCountMax);
return bufferCount;
}
/// <summary>
/// Register a new <see cref="AudioBuffer"/> on the server side.
/// </summary>
/// <param name="buffer">The <see cref="AudioBuffer"/> to register</param>
/// <returns>True if the operation succeeded</returns>
private bool RegisterBuffer(AudioBuffer buffer)
{
if (GetTotalBufferCount() == Constants.AudioDeviceBufferCountMax)
{
return false;
}
_buffers[_serverBufferIndex] = buffer;
_serverBufferIndex = (_serverBufferIndex + 1) % Constants.AudioDeviceBufferCountMax;
_bufferAppendedCount++;
return true;
}
/// <summary>
/// Flush server buffers to hardware.
/// </summary>
private void FlushToHardware()
{
uint bufferToFlushCount = Math.Min(Math.Min(_bufferAppendedCount, 4), _bufferRegisteredLimit - _bufferRegisteredCount);
AudioBuffer[] buffersToFlush = new AudioBuffer[bufferToFlushCount];
uint hardwareBufferIndex = _hardwareBufferIndex;
for (int i = 0; i < buffersToFlush.Length; i++)
{
buffersToFlush[i] = _buffers[hardwareBufferIndex];
_bufferAppendedCount--;
_bufferRegisteredCount++;
hardwareBufferIndex = (hardwareBufferIndex + 1) % Constants.AudioDeviceBufferCountMax;
}
_hardwareBufferIndex = hardwareBufferIndex;
for (int i = 0; i < buffersToFlush.Length; i++)
{
_hardwareDeviceSession.QueueBuffer(buffersToFlush[i]);
}
}
/// <summary>
/// Get the current index of the <see cref="AudioBuffer"/> playing on the driver side.
/// </summary>
/// <param name="playingIndex">The output index of the <see cref="AudioBuffer"/> playing on the driver side</param>
/// <returns>True if any buffer is playing</returns>
private bool TryGetPlayingBufferIndex(out uint playingIndex)
{
if (_bufferRegisteredCount > 0)
{
playingIndex = (_hardwareBufferIndex - _bufferRegisteredCount) % Constants.AudioDeviceBufferCountMax;
return true;
}
playingIndex = 0;
return false;
}
/// <summary>
/// Try to pop the <see cref="AudioBuffer"/> playing on the driver side.
/// </summary>
/// <param name="buffer">The output <see cref="AudioBuffer"/> playing on the driver side</param>
/// <returns>True if any buffer is playing</returns>
private bool TryPopPlayingBuffer(out AudioBuffer buffer)
{
if (_bufferRegisteredCount > 0)
{
uint bufferIndex = (_hardwareBufferIndex - _bufferRegisteredCount) % Constants.AudioDeviceBufferCountMax;
buffer = _buffers[bufferIndex];
_buffers[bufferIndex] = null;
_bufferRegisteredCount--;
return true;
}
buffer = null;
return false;
}
/// <summary>
/// Try to pop a <see cref="AudioBuffer"/> released by the driver side.
/// </summary>
/// <param name="buffer">The output <see cref="AudioBuffer"/> released by the driver side</param>
/// <returns>True if any buffer has been released</returns>
public bool TryPopReleasedBuffer(out AudioBuffer buffer)
{
if (_bufferReleasedCount > 0)
{
uint bufferIndex = (_releasedBufferIndex - _bufferReleasedCount) % Constants.AudioDeviceBufferCountMax;
buffer = _buffers[bufferIndex];
_buffers[bufferIndex] = null;
_bufferReleasedCount--;
return true;
}
buffer = null;
return false;
}
/// <summary>
/// Release a <see cref="AudioBuffer"/>.
/// </summary>
/// <param name="buffer">The <see cref="AudioBuffer"/> to release</param>
private void ReleaseBuffer(AudioBuffer buffer)
{
buffer.PlayedTimestamp = (ulong)PerformanceCounter.ElapsedNanoseconds;
_bufferRegisteredCount--;
_bufferReleasedCount++;
_releasedBufferIndex = (_releasedBufferIndex + 1) % Constants.AudioDeviceBufferCountMax;
}
/// <summary>
/// Update the released buffers.
/// </summary>
/// <param name="updateForStop">True if the session is currently stopping</param>
private void UpdateReleaseBuffers(bool updateForStop = false)
{
bool wasAnyBuffersReleased = false;
while (TryGetPlayingBufferIndex(out uint playingIndex))
{
if (!updateForStop && !_hardwareDeviceSession.WasBufferFullyConsumed(_buffers[playingIndex]))
{
break;
}
if (updateForStop)
{
_hardwareDeviceSession.UnregisterBuffer(_buffers[playingIndex]);
}
ReleaseBuffer(_buffers[playingIndex]);
wasAnyBuffersReleased = true;
}
if (wasAnyBuffersReleased)
{
_bufferEvent.Signal();
}
}
/// <summary>
/// Append a new <see cref="AudioBuffer"/>.
/// </summary>
/// <param name="buffer">The <see cref="AudioBuffer"/> to append</param>
/// <returns>True if the buffer was appended</returns>
public bool AppendBuffer(AudioBuffer buffer)
{
if (_hardwareDeviceSession.RegisterBuffer(buffer))
{
if (RegisterBuffer(buffer))
{
FlushToHardware();
return true;
}
_hardwareDeviceSession.UnregisterBuffer(buffer);
}
return false;
}
public bool AppendUacBuffer(AudioBuffer buffer, uint handle)
{
// NOTE: On hardware, there is another RegisterBuffer method taking an handle.
// This variant of the call always return false (stubbed?) as a result this logic will never succeed.
return false;
}
/// <summary>
/// Start the audio session.
/// </summary>
/// <returns>A <see cref="ResultCode"/> reporting an error or a success</returns>
public ResultCode Start()
{
if (_state == AudioDeviceState.Started)
{
return ResultCode.OperationFailed;
}
_hardwareDeviceSession.Start();
_state = AudioDeviceState.Started;
FlushToHardware();
_hardwareDeviceSession.SetVolume(_volume);
return ResultCode.Success;
}
/// <summary>
/// Stop the audio session.
/// </summary>
/// <returns>A <see cref="ResultCode"/> reporting an error or a success</returns>
public ResultCode Stop()
{
if (_state == AudioDeviceState.Started)
{
_hardwareDeviceSession.Stop();
UpdateReleaseBuffers(true);
_state = AudioDeviceState.Stopped;
}
return ResultCode.Success;
}
/// <summary>
/// Get the volume of the session.
/// </summary>
/// <returns>The volume of the session</returns>
public float GetVolume()
{
return _hardwareDeviceSession.GetVolume();
}
/// <summary>
/// Set the volume of the session.
/// </summary>
/// <param name="volume">The new volume to set</param>
public void SetVolume(float volume)
{
_volume = volume;
if (_state == AudioDeviceState.Started)
{
_hardwareDeviceSession.SetVolume(volume);
}
}
/// <summary>
/// Get the count of buffer currently in use (server + driver side).
/// </summary>
/// <returns>The count of buffer currently in use</returns>
public uint GetBufferCount()
{
return _bufferAppendedCount + _bufferRegisteredCount;
}
/// <summary>
/// Check if a buffer is present.
/// </summary>
/// <param name="bufferTag">The unique tag of the buffer</param>
/// <returns>Return true if a buffer is present</returns>
public bool ContainsBuffer(ulong bufferTag)
{
uint bufferIndex = (_releasedBufferIndex - _bufferReleasedCount) % Constants.AudioDeviceBufferCountMax;
for (int i = 0; i < GetTotalBufferCount(); i++)
{
if (_buffers[bufferIndex].BufferTag == bufferTag)
{
return true;
}
bufferIndex = (bufferIndex + 1) % Constants.AudioDeviceBufferCountMax;
}
return false;
}
/// <summary>
/// Get the count of sample played in this session.
/// </summary>
/// <returns>The count of sample played in this session</returns>
public ulong GetPlayedSampleCount()
{
if (_state == AudioDeviceState.Stopped)
{
return 0;
}
else
{
return _hardwareDeviceSession.GetPlayedSampleCount();
}
}
/// <summary>
/// Flush all buffers to the initial state.
/// </summary>
/// <returns>True if any buffer was flushed</returns>
public bool FlushBuffers()
{
if (_state == AudioDeviceState.Stopped)
{
return false;
}
uint bufferCount = GetBufferCount();
while (TryPopReleasedBuffer(out AudioBuffer buffer))
{
_hardwareDeviceSession.UnregisterBuffer(buffer);
}
while (TryPopPlayingBuffer(out AudioBuffer buffer))
{
_hardwareDeviceSession.UnregisterBuffer(buffer);
}
if (_bufferRegisteredCount == 0 || (_bufferReleasedCount + _bufferAppendedCount) > Constants.AudioDeviceBufferCountMax)
{
return false;
}
_bufferReleasedCount += _bufferAppendedCount;
_releasedBufferIndex = (_releasedBufferIndex + _bufferAppendedCount) % Constants.AudioDeviceBufferCountMax;
_bufferAppendedCount = 0;
_hardwareBufferIndex = _serverBufferIndex;
if (bufferCount > 0)
{
_bufferEvent.Signal();
}
return true;
}
/// <summary>
/// Update the session.
/// </summary>
public void Update()
{
if (_state == AudioDeviceState.Started)
{
UpdateReleaseBuffers();
FlushToHardware();
}
}
public void Dispose()
{
Dispose(true);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
// Tell the hardware session that we are ending.
_hardwareDeviceSession.PrepareToClose();
// Unregister all buffers
while (TryPopReleasedBuffer(out AudioBuffer buffer))
{
_hardwareDeviceSession.UnregisterBuffer(buffer);
}
while (TryPopPlayingBuffer(out AudioBuffer buffer))
{
_hardwareDeviceSession.UnregisterBuffer(buffer);
}
// Finally dispose hardware session.
_hardwareDeviceSession.Dispose();
_bufferEvent.Signal();
}
}
}
}

View File

@@ -1,34 +0,0 @@
using Ryujinx.Audio.Common;
using Ryujinx.Memory;
using System;
using System.Threading;
namespace Ryujinx.Audio.Integration
{
/// <summary>
/// Represent an hardware device driver used in <see cref="Output.AudioOutputSystem"/>.
/// </summary>
public interface IHardwareDeviceDriver : IDisposable
{
public enum Direction
{
Input,
Output
}
IHardwareDeviceSession OpenDeviceSession(Direction direction, IVirtualMemoryManager memoryManager, SampleFormat sampleFormat, uint sampleRate, uint channelCount, float volume = 1f);
ManualResetEvent GetUpdateRequiredEvent();
ManualResetEvent GetPauseEvent();
bool SupportsDirection(Direction direction);
bool SupportsSampleRate(uint sampleRate);
bool SupportsSampleFormat(SampleFormat sampleFormat);
bool SupportsChannelCount(uint channelCount);
IHardwareDeviceDriver GetRealDeviceDriver()
{
return this;
}
}
}

View File

@@ -1,173 +0,0 @@
using System;
using System.Diagnostics;
using Ryujinx.Audio.Renderer.Dsp.Effect;
using Ryujinx.Audio.Renderer.Dsp.State;
using Ryujinx.Audio.Renderer.Parameter.Effect;
namespace Ryujinx.Audio.Renderer.Dsp.Command
{
public class CompressorCommand : ICommand
{
private const int FixedPointPrecision = 15;
public bool Enabled { get; set; }
public int NodeId { get; }
public CommandType CommandType => CommandType.Compressor;
public uint EstimatedProcessingTime { get; set; }
public CompressorParameter Parameter => _parameter;
public Memory<CompressorState> State { get; }
public ushort[] OutputBufferIndices { get; }
public ushort[] InputBufferIndices { get; }
public bool IsEffectEnabled { get; }
private CompressorParameter _parameter;
public CompressorCommand(uint bufferOffset, CompressorParameter parameter, Memory<CompressorState> state, bool isEnabled, int nodeId)
{
Enabled = true;
NodeId = nodeId;
_parameter = parameter;
State = state;
IsEffectEnabled = isEnabled;
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
for (int i = 0; i < _parameter.ChannelCount; i++)
{
InputBufferIndices[i] = (ushort)(bufferOffset + _parameter.Input[i]);
OutputBufferIndices[i] = (ushort)(bufferOffset + _parameter.Output[i]);
}
}
public void Process(CommandList context)
{
ref CompressorState state = ref State.Span[0];
if (IsEffectEnabled)
{
if (_parameter.Status == Server.Effect.UsageState.Invalid)
{
state = new CompressorState(ref _parameter);
}
else if (_parameter.Status == Server.Effect.UsageState.New)
{
state.UpdateParameter(ref _parameter);
}
}
ProcessCompressor(context, ref state);
}
private unsafe void ProcessCompressor(CommandList context, ref CompressorState state)
{
Debug.Assert(_parameter.IsChannelCountValid());
if (IsEffectEnabled && _parameter.IsChannelCountValid())
{
Span<IntPtr> inputBuffers = stackalloc IntPtr[Parameter.ChannelCount];
Span<IntPtr> outputBuffers = stackalloc IntPtr[Parameter.ChannelCount];
Span<float> channelInput = stackalloc float[Parameter.ChannelCount];
ExponentialMovingAverage inputMovingAverage = state.InputMovingAverage;
float unknown4 = state.Unknown4;
ExponentialMovingAverage compressionGainAverage = state.CompressionGainAverage;
float previousCompressionEmaAlpha = state.PreviousCompressionEmaAlpha;
for (int i = 0; i < _parameter.ChannelCount; i++)
{
inputBuffers[i] = context.GetBufferPointer(InputBufferIndices[i]);
outputBuffers[i] = context.GetBufferPointer(OutputBufferIndices[i]);
}
for (int sampleIndex = 0; sampleIndex < context.SampleCount; sampleIndex++)
{
for (int channelIndex = 0; channelIndex < _parameter.ChannelCount; channelIndex++)
{
channelInput[channelIndex] = *((float*)inputBuffers[channelIndex] + sampleIndex);
}
float newMean = inputMovingAverage.Update(FloatingPointHelper.MeanSquare(channelInput), _parameter.InputGain);
float y = FloatingPointHelper.Log10(newMean) * 10.0f;
float z = 0.0f;
bool unknown10OutOfRange = false;
if (newMean < 1.0e-10f)
{
z = 1.0f;
unknown10OutOfRange = state.Unknown10 < -100.0f;
}
if (y >= state.Unknown10 || unknown10OutOfRange)
{
float tmpGain;
if (y >= state.Unknown14)
{
tmpGain = ((1.0f / Parameter.Ratio) - 1.0f) * (y - Parameter.Threshold);
}
else
{
tmpGain = (y - state.Unknown10) * ((y - state.Unknown10) * -state.CompressorGainReduction);
}
z = FloatingPointHelper.DecibelToLinearExtended(tmpGain);
}
float unknown4New = z;
float compressionEmaAlpha;
if ((unknown4 - z) <= 0.08f)
{
compressionEmaAlpha = Parameter.ReleaseCoefficient;
if ((unknown4 - z) >= -0.08f)
{
if (MathF.Abs(compressionGainAverage.Read() - z) >= 0.001f)
{
unknown4New = unknown4;
}
compressionEmaAlpha = previousCompressionEmaAlpha;
}
}
else
{
compressionEmaAlpha = Parameter.AttackCoefficient;
}
float compressionGain = compressionGainAverage.Update(z, compressionEmaAlpha);
for (int channelIndex = 0; channelIndex < Parameter.ChannelCount; channelIndex++)
{
*((float*)outputBuffers[channelIndex] + sampleIndex) = channelInput[channelIndex] * compressionGain * state.OutputGain;
}
unknown4 = unknown4New;
previousCompressionEmaAlpha = compressionEmaAlpha;
}
state.InputMovingAverage = inputMovingAverage;
state.Unknown4 = unknown4;
state.CompressionGainAverage = compressionGainAverage;
state.PreviousCompressionEmaAlpha = previousCompressionEmaAlpha;
}
else
{
for (int i = 0; i < Parameter.ChannelCount; i++)
{
if (InputBufferIndices[i] != OutputBufferIndices[i])
{
context.CopyBuffer(OutputBufferIndices[i], InputBufferIndices[i]);
}
}
}
}
}
}

View File

@@ -1,68 +0,0 @@
using Ryujinx.Audio.Renderer.Server.Upsampler;
using System;
namespace Ryujinx.Audio.Renderer.Dsp.Command
{
public class UpsampleCommand : ICommand
{
public bool Enabled { get; set; }
public int NodeId { get; }
public CommandType CommandType => CommandType.Upsample;
public uint EstimatedProcessingTime { get; set; }
public uint BufferCount { get; }
public uint InputBufferIndex { get; }
public uint InputSampleCount { get; }
public uint InputSampleRate { get; }
public UpsamplerState UpsamplerInfo { get; }
public Memory<float> OutBuffer { get; }
public UpsampleCommand(uint bufferOffset, UpsamplerState info, uint inputCount, Span<byte> inputBufferOffset, uint bufferCount, uint sampleCount, uint sampleRate, int nodeId)
{
Enabled = true;
NodeId = nodeId;
InputBufferIndex = 0;
OutBuffer = info.OutputBuffer;
BufferCount = bufferCount;
InputSampleCount = sampleCount;
InputSampleRate = sampleRate;
info.SourceSampleCount = inputCount;
info.InputBufferIndices = new ushort[inputCount];
for (int i = 0; i < inputCount; i++)
{
info.InputBufferIndices[i] = (ushort)(bufferOffset + inputBufferOffset[i]);
}
UpsamplerInfo = info;
}
private Span<float> GetBuffer(int index, int sampleCount)
{
return UpsamplerInfo.OutputBuffer.Span.Slice(index * sampleCount, sampleCount);
}
public void Process(CommandList context)
{
float ratio = (float)InputSampleRate / Constants.TargetSampleRate;
uint bufferCount = Math.Min(BufferCount, UpsamplerInfo.SourceSampleCount);
for (int i = 0; i < bufferCount; i++)
{
Span<float> inputBuffer = context.GetBuffer(UpsamplerInfo.InputBufferIndices[i]);
Span<float> outputBuffer = GetBuffer(UpsamplerInfo.InputBufferIndices[i], (int)UpsamplerInfo.SampleCount);
float fraction = 0.0f;
ResamplerHelper.ResampleForUpsampler(outputBuffer, inputBuffer, ratio, ref fraction, (int)(InputSampleCount / ratio));
}
}
}
}

View File

@@ -1,117 +0,0 @@
using System;
using System.Numerics;
using System.Runtime.CompilerServices;
namespace Ryujinx.Audio.Renderer.Dsp
{
public static class PcmHelper
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int GetCountToDecode(int startSampleOffset, int endSampleOffset, int offset, int count)
{
return Math.Min(count, endSampleOffset - startSampleOffset - offset);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ulong GetBufferOffset<T>(int startSampleOffset, int offset, int channelCount) where T : unmanaged
{
return (ulong)(Unsafe.SizeOf<T>() * channelCount * (startSampleOffset + offset));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int GetBufferSize<T>(int startSampleOffset, int endSampleOffset, int offset, int count) where T : unmanaged
{
return GetCountToDecode(startSampleOffset, endSampleOffset, offset, count) * Unsafe.SizeOf<T>();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float ConvertSampleToPcmFloat(short sample)
{
return (float)sample / short.MaxValue;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static short ConvertSampleToPcmInt16(float sample)
{
return Saturate(sample * short.MaxValue);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static TOutput ConvertSample<TInput, TOutput>(TInput value) where TInput: INumber<TInput>, IMinMaxValue<TInput> where TOutput : INumber<TOutput>, IMinMaxValue<TOutput>
{
TInput conversionRate = TInput.CreateSaturating(TOutput.MaxValue / TOutput.CreateSaturating(TInput.MaxValue));
return TOutput.CreateSaturating(value * conversionRate);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Convert<TInput, TOutput>(Span<TOutput> output, ReadOnlySpan<TInput> input) where TInput : INumber<TInput>, IMinMaxValue<TInput> where TOutput : INumber<TOutput>, IMinMaxValue<TOutput>
{
for (int i = 0; i < input.Length; i++)
{
output[i] = ConvertSample<TInput, TOutput>(input[i]);
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void ConvertSampleToPcmFloat(Span<float> output, ReadOnlySpan<short> input)
{
for (int i = 0; i < input.Length; i++)
{
output[i] = ConvertSampleToPcmFloat(input[i]);
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int Decode(Span<short> output, ReadOnlySpan<short> input, int startSampleOffset, int endSampleOffset, int channelIndex, int channelCount)
{
if (input.IsEmpty || endSampleOffset < startSampleOffset)
{
return 0;
}
int decodedCount = input.Length / channelCount;
for (int i = 0; i < decodedCount; i++)
{
output[i] = input[i * channelCount + channelIndex];
}
return decodedCount;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int Decode(Span<short> output, ReadOnlySpan<float> input, int startSampleOffset, int endSampleOffset, int channelIndex, int channelCount)
{
if (input.IsEmpty || endSampleOffset < startSampleOffset)
{
return 0;
}
int decodedCount = input.Length / channelCount;
for (int i = 0; i < decodedCount; i++)
{
output[i] = ConvertSampleToPcmInt16(input[i * channelCount + channelIndex]);
}
return decodedCount;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static short Saturate(float value)
{
if (value > short.MaxValue)
{
return short.MaxValue;
}
if (value < short.MinValue)
{
return short.MinValue;
}
return (short)value;
}
}
}

View File

@@ -1,630 +0,0 @@
using System;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;
using static Ryujinx.Audio.Renderer.Parameter.VoiceInParameter;
namespace Ryujinx.Audio.Renderer.Dsp
{
public static class ResamplerHelper
{
#region "Default Quality Lookup Tables"
private static short[] _normalCurveLut0 = new short[]
{
6600, 19426, 6722, 3, 6479, 19424, 6845, 9, 6359, 19419, 6968, 15, 6239, 19412, 7093, 22,
6121, 19403, 7219, 28, 6004, 19391, 7345, 34, 5888, 19377, 7472, 41, 5773, 19361, 7600, 48,
5659, 19342, 7728, 55, 5546, 19321, 7857, 62, 5434, 19298, 7987, 69, 5323, 19273, 8118, 77,
5213, 19245, 8249, 84, 5104, 19215, 8381, 92, 4997, 19183, 8513, 101, 4890, 19148, 8646, 109,
4785, 19112, 8780, 118, 4681, 19073, 8914, 127, 4579, 19031, 9048, 137, 4477, 18988, 9183, 147,
4377, 18942, 9318, 157, 4277, 18895, 9454, 168, 4179, 18845, 9590, 179, 4083, 18793, 9726, 190,
3987, 18738, 9863, 202, 3893, 18682, 10000, 215, 3800, 18624, 10137, 228, 3709, 18563, 10274, 241,
3618, 18500, 10411, 255, 3529, 18436, 10549, 270, 3441, 18369, 10687, 285, 3355, 18300, 10824, 300,
3269, 18230, 10962, 317, 3186, 18157, 11100, 334, 3103, 18082, 11238, 351, 3022, 18006, 11375, 369,
2942, 17927, 11513, 388, 2863, 17847, 11650, 408, 2785, 17765, 11788, 428, 2709, 17681, 11925, 449,
2635, 17595, 12062, 471, 2561, 17507, 12198, 494, 2489, 17418, 12334, 517, 2418, 17327, 12470, 541,
2348, 17234, 12606, 566, 2280, 17140, 12741, 592, 2213, 17044, 12876, 619, 2147, 16946, 13010, 647,
2083, 16846, 13144, 675, 2020, 16745, 13277, 704, 1958, 16643, 13409, 735, 1897, 16539, 13541, 766,
1838, 16434, 13673, 798, 1780, 16327, 13803, 832, 1723, 16218, 13933, 866, 1667, 16109, 14062, 901,
1613, 15998, 14191, 937, 1560, 15885, 14318, 975, 1508, 15772, 14445, 1013, 1457, 15657, 14571, 1052,
1407, 15540, 14695, 1093, 1359, 15423, 14819, 1134, 1312, 15304, 14942, 1177, 1266, 15185, 15064, 1221,
1221, 15064, 15185, 1266, 1177, 14942, 15304, 1312, 1134, 14819, 15423, 1359, 1093, 14695, 15540, 1407,
1052, 14571, 15657, 1457, 1013, 14445, 15772, 1508, 975, 14318, 15885, 1560, 937, 14191, 15998, 1613,
901, 14062, 16109, 1667, 866, 13933, 16218, 1723, 832, 13803, 16327, 1780, 798, 13673, 16434, 1838,
766, 13541, 16539, 1897, 735, 13409, 16643, 1958, 704, 13277, 16745, 2020, 675, 13144, 16846, 2083,
647, 13010, 16946, 2147, 619, 12876, 17044, 2213, 592, 12741, 17140, 2280, 566, 12606, 17234, 2348,
541, 12470, 17327, 2418, 517, 12334, 17418, 2489, 494, 12198, 17507, 2561, 471, 12062, 17595, 2635,
449, 11925, 17681, 2709, 428, 11788, 17765, 2785, 408, 11650, 17847, 2863, 388, 11513, 17927, 2942,
369, 11375, 18006, 3022, 351, 11238, 18082, 3103, 334, 11100, 18157, 3186, 317, 10962, 18230, 3269,
300, 10824, 18300, 3355, 285, 10687, 18369, 3441, 270, 10549, 18436, 3529, 255, 10411, 18500, 3618,
241, 10274, 18563, 3709, 228, 10137, 18624, 3800, 215, 10000, 18682, 3893, 202, 9863, 18738, 3987,
190, 9726, 18793, 4083, 179, 9590, 18845, 4179, 168, 9454, 18895, 4277, 157, 9318, 18942, 4377,
147, 9183, 18988, 4477, 137, 9048, 19031, 4579, 127, 8914, 19073, 4681, 118, 8780, 19112, 4785,
109, 8646, 19148, 4890, 101, 8513, 19183, 4997, 92, 8381, 19215, 5104, 84, 8249, 19245, 5213,
77, 8118, 19273, 5323, 69, 7987, 19298, 5434, 62, 7857, 19321, 5546, 55, 7728, 19342, 5659,
48, 7600, 19361, 5773, 41, 7472, 19377, 5888, 34, 7345, 19391, 6004, 28, 7219, 19403, 6121,
22, 7093, 19412, 6239, 15, 6968, 19419, 6359, 9, 6845, 19424, 6479, 3, 6722, 19426, 6600
};
private static short[] _normalCurveLut1 = new short[]
{
-68, 32639, 69, -5, -200, 32630, 212, -15, -328, 32613, 359, -26, -450, 32586, 512, -36,
-568, 32551, 669, -47, -680, 32507, 832, -58, -788, 32454, 1000, -69, -891, 32393, 1174, -80,
-990, 32323, 1352, -92, -1084, 32244, 1536, -103, -1173, 32157, 1724, -115, -1258, 32061, 1919, -128,
-1338, 31956, 2118, -140, -1414, 31844, 2322, -153, -1486, 31723, 2532, -167, -1554, 31593, 2747, -180,
-1617, 31456, 2967, -194, -1676, 31310, 3192, -209, -1732, 31157, 3422, -224, -1783, 30995, 3657, -240,
-1830, 30826, 3897, -256, -1874, 30649, 4143, -272, -1914, 30464, 4393, -289, -1951, 30272, 4648, -307,
-1984, 30072, 4908, -325, -2014, 29866, 5172, -343, -2040, 29652, 5442, -362, -2063, 29431, 5716, -382,
-2083, 29203, 5994, -403, -2100, 28968, 6277, -424, -2114, 28727, 6565, -445, -2125, 28480, 6857, -468,
-2133, 28226, 7153, -490, -2139, 27966, 7453, -514, -2142, 27700, 7758, -538, -2142, 27428, 8066, -563,
-2141, 27151, 8378, -588, -2136, 26867, 8694, -614, -2130, 26579, 9013, -641, -2121, 26285, 9336, -668,
-2111, 25987, 9663, -696, -2098, 25683, 9993, -724, -2084, 25375, 10326, -753, -2067, 25063, 10662, -783,
-2049, 24746, 11000, -813, -2030, 24425, 11342, -844, -2009, 24100, 11686, -875, -1986, 23771, 12033, -907,
-1962, 23438, 12382, -939, -1937, 23103, 12733, -972, -1911, 22764, 13086, -1005, -1883, 22422, 13441, -1039,
-1855, 22077, 13798, -1072, -1825, 21729, 14156, -1107, -1795, 21380, 14516, -1141, -1764, 21027, 14877, -1176,
-1732, 20673, 15239, -1211, -1700, 20317, 15602, -1246, -1667, 19959, 15965, -1282, -1633, 19600, 16329, -1317,
-1599, 19239, 16694, -1353, -1564, 18878, 17058, -1388, -1530, 18515, 17423, -1424, -1495, 18151, 17787, -1459,
-1459, 17787, 18151, -1495, -1424, 17423, 18515, -1530, -1388, 17058, 18878, -1564, -1353, 16694, 19239, -1599,
-1317, 16329, 19600, -1633, -1282, 15965, 19959, -1667, -1246, 15602, 20317, -1700, -1211, 15239, 20673, -1732,
-1176, 14877, 21027, -1764, -1141, 14516, 21380, -1795, -1107, 14156, 21729, -1825, -1072, 13798, 22077, -1855,
-1039, 13441, 22422, -1883, -1005, 13086, 22764, -1911, -972, 12733, 23103, -1937, -939, 12382, 23438, -1962,
-907, 12033, 23771, -1986, -875, 11686, 24100, -2009, -844, 11342, 24425, -2030, -813, 11000, 24746, -2049,
-783, 10662, 25063, -2067, -753, 10326, 25375, -2084, -724, 9993, 25683, -2098, -696, 9663, 25987, -2111,
-668, 9336, 26285, -2121, -641, 9013, 26579, -2130, -614, 8694, 26867, -2136, -588, 8378, 27151, -2141,
-563, 8066, 27428, -2142, -538, 7758, 27700, -2142, -514, 7453, 27966, -2139, -490, 7153, 28226, -2133,
-468, 6857, 28480, -2125, -445, 6565, 28727, -2114, -424, 6277, 28968, -2100, -403, 5994, 29203, -2083,
-382, 5716, 29431, -2063, -362, 5442, 29652, -2040, -343, 5172, 29866, -2014, -325, 4908, 30072, -1984,
-307, 4648, 30272, -1951, -289, 4393, 30464, -1914, -272, 4143, 30649, -1874, -256, 3897, 30826, -1830,
-240, 3657, 30995, -1783, -224, 3422, 31157, -1732, -209, 3192, 31310, -1676, -194, 2967, 31456, -1617,
-180, 2747, 31593, -1554, -167, 2532, 31723, -1486, -153, 2322, 31844, -1414, -140, 2118, 31956, -1338,
-128, 1919, 32061, -1258, -115, 1724, 32157, -1173, -103, 1536, 32244, -1084, -92, 1352, 32323, -990,
-80, 1174, 32393, -891, -69, 1000, 32454, -788, -58, 832, 32507, -680, -47, 669, 32551, -568,
-36, 512, 32586, -450, -26, 359, 32613, -328, -15, 212, 32630, -200, -5, 69, 32639, -68
};
private static short[] _normalCurveLut2 = new short[]
{
3195, 26287, 3329, -32, 3064, 26281, 3467, -34, 2936, 26270, 3608, -38, 2811, 26253, 3751, -42,
2688, 26230, 3897, -46, 2568, 26202, 4046, -50, 2451, 26169, 4199, -54, 2338, 26130, 4354, -58,
2227, 26085, 4512, -63, 2120, 26035, 4673, -67, 2015, 25980, 4837, -72, 1912, 25919, 5004, -76,
1813, 25852, 5174, -81, 1716, 25780, 5347, -87, 1622, 25704, 5522, -92, 1531, 25621, 5701, -98,
1442, 25533, 5882, -103, 1357, 25440, 6066, -109, 1274, 25342, 6253, -115, 1193, 25239, 6442, -121,
1115, 25131, 6635, -127, 1040, 25018, 6830, -133, 967, 24899, 7027, -140, 897, 24776, 7227, -146,
829, 24648, 7430, -153, 764, 24516, 7635, -159, 701, 24379, 7842, -166, 641, 24237, 8052, -174,
583, 24091, 8264, -181, 526, 23940, 8478, -187, 472, 23785, 8695, -194, 420, 23626, 8914, -202,
371, 23462, 9135, -209, 324, 23295, 9358, -215, 279, 23123, 9583, -222, 236, 22948, 9809, -230,
194, 22769, 10038, -237, 154, 22586, 10269, -243, 117, 22399, 10501, -250, 81, 22208, 10735, -258,
47, 22015, 10970, -265, 15, 21818, 11206, -271, -16, 21618, 11444, -277, -44, 21415, 11684, -283,
-71, 21208, 11924, -290, -97, 20999, 12166, -296, -121, 20786, 12409, -302, -143, 20571, 12653, -306,
-163, 20354, 12898, -311, -183, 20134, 13143, -316, -201, 19911, 13389, -321, -218, 19686, 13635, -325,
-234, 19459, 13882, -328, -248, 19230, 14130, -332, -261, 18998, 14377, -335, -273, 18765, 14625, -337,
-284, 18531, 14873, -339, -294, 18295, 15121, -341, -302, 18057, 15369, -341, -310, 17817, 15617, -341,
-317, 17577, 15864, -340, -323, 17335, 16111, -340, -328, 17092, 16357, -338, -332, 16848, 16603, -336,
-336, 16603, 16848, -332, -338, 16357, 17092, -328, -340, 16111, 17335, -323, -340, 15864, 17577, -317,
-341, 15617, 17817, -310, -341, 15369, 18057, -302, -341, 15121, 18295, -294, -339, 14873, 18531, -284,
-337, 14625, 18765, -273, -335, 14377, 18998, -261, -332, 14130, 19230, -248, -328, 13882, 19459, -234,
-325, 13635, 19686, -218, -321, 13389, 19911, -201, -316, 13143, 20134, -183, -311, 12898, 20354, -163,
-306, 12653, 20571, -143, -302, 12409, 20786, -121, -296, 12166, 20999, -97, -290, 11924, 21208, -71,
-283, 11684, 21415, -44, -277, 11444, 21618, -16, -271, 11206, 21818, 15, -265, 10970, 22015, 47,
-258, 10735, 22208, 81, -250, 10501, 22399, 117, -243, 10269, 22586, 154, -237, 10038, 22769, 194,
-230, 9809, 22948, 236, -222, 9583, 23123, 279, -215, 9358, 23295, 324, -209, 9135, 23462, 371,
-202, 8914, 23626, 420, -194, 8695, 23785, 472, -187, 8478, 23940, 526, -181, 8264, 24091, 583,
-174, 8052, 24237, 641, -166, 7842, 24379, 701, -159, 7635, 24516, 764, -153, 7430, 24648, 829,
-146, 7227, 24776, 897, -140, 7027, 24899, 967, -133, 6830, 25018, 1040, -127, 6635, 25131, 1115,
-121, 6442, 25239, 1193, -115, 6253, 25342, 1274, -109, 6066, 25440, 1357, -103, 5882, 25533, 1442,
-98, 5701, 25621, 1531, -92, 5522, 25704, 1622, -87, 5347, 25780, 1716, -81, 5174, 25852, 1813,
-76, 5004, 25919, 1912, -72, 4837, 25980, 2015, -67, 4673, 26035, 2120, -63, 4512, 26085, 2227,
-58, 4354, 26130, 2338, -54, 4199, 26169, 2451, -50, 4046, 26202, 2568, -46, 3897, 26230, 2688,
-42, 3751, 26253, 2811, -38, 3608, 26270, 2936, -34, 3467, 26281, 3064, -32, 3329, 26287, 3195
};
#endregion
#region "High Quality Lookup Tables"
private static short[] _highCurveLut0 = new short[]
{
-582, -23, 8740, 16386, 8833, 8, -590, 0, -573, -54, 8647, 16385, 8925, 40, -598, -1,
-565, -84, 8555, 16383, 9018, 72, -606, -1, -557, -113, 8462, 16379, 9110, 105, -614, -2,
-549, -142, 8370, 16375, 9203, 139, -622, -2, -541, -170, 8277, 16369, 9295, 173, -630, -3,
-533, -198, 8185, 16362, 9387, 208, -638, -4, -525, -225, 8093, 16354, 9480, 244, -646, -5,
-516, -251, 8000, 16344, 9572, 280, -654, -5, -508, -277, 7908, 16334, 9664, 317, -662, -6,
-500, -302, 7816, 16322, 9756, 355, -670, -7, -492, -327, 7724, 16310, 9847, 393, -678, -8,
-484, -351, 7632, 16296, 9939, 432, -686, -9, -476, -374, 7540, 16281, 10030, 471, -694, -10,
-468, -397, 7449, 16265, 10121, 511, -702, -11, -460, -419, 7357, 16247, 10212, 552, -709, -13,
-452, -441, 7266, 16229, 10303, 593, -717, -14, -445, -462, 7175, 16209, 10394, 635, -724, -15,
-437, -483, 7084, 16189, 10484, 678, -732, -16, -429, -503, 6994, 16167, 10574, 722, -739, -18,
-421, -523, 6903, 16144, 10664, 766, -747, -19, -414, -542, 6813, 16120, 10754, 810, -754, -21,
-406, -560, 6723, 16095, 10843, 856, -761, -22, -398, -578, 6633, 16068, 10932, 902, -768, -24,
-391, -596, 6544, 16041, 11021, 949, -775, -26, -383, -612, 6454, 16012, 11109, 996, -782, -27,
-376, -629, 6366, 15983, 11197, 1044, -789, -29, -368, -645, 6277, 15952, 11285, 1093, -796, -31,
-361, -660, 6189, 15920, 11372, 1142, -802, -33, -354, -675, 6100, 15887, 11459, 1192, -809, -35,
-347, -689, 6013, 15853, 11546, 1243, -815, -37, -339, -703, 5925, 15818, 11632, 1294, -821, -39,
-332, -717, 5838, 15782, 11718, 1346, -827, -41, -325, -730, 5751, 15745, 11803, 1399, -833, -43,
-318, -742, 5665, 15707, 11888, 1452, -839, -46, -312, -754, 5579, 15668, 11973, 1506, -845, -48,
-305, -766, 5493, 15627, 12057, 1561, -850, -50, -298, -777, 5408, 15586, 12140, 1616, -855, -53,
-291, -787, 5323, 15544, 12224, 1672, -861, -56, -285, -798, 5239, 15500, 12306, 1729, -866, -58,
-278, -807, 5155, 15456, 12388, 1786, -871, -61, -272, -817, 5071, 15410, 12470, 1844, -875, -64,
-265, -826, 4988, 15364, 12551, 1902, -880, -67, -259, -834, 4905, 15317, 12631, 1962, -884, -70,
-253, -842, 4823, 15268, 12711, 2022, -888, -73, -247, -850, 4741, 15219, 12790, 2082, -892, -76,
-241, -857, 4659, 15168, 12869, 2143, -896, -79, -235, -864, 4578, 15117, 12947, 2205, -899, -82,
-229, -870, 4498, 15065, 13025, 2267, -903, -85, -223, -876, 4417, 15012, 13102, 2331, -906, -89,
-217, -882, 4338, 14958, 13178, 2394, -909, -92, -211, -887, 4259, 14903, 13254, 2459, -911, -96,
-206, -892, 4180, 14847, 13329, 2523, -914, -100, -200, -896, 4102, 14790, 13403, 2589, -916, -103,
-195, -900, 4024, 14732, 13477, 2655, -918, -107, -190, -904, 3947, 14673, 13550, 2722, -919, -111,
-184, -908, 3871, 14614, 13622, 2789, -921, -115, -179, -911, 3795, 14553, 13693, 2857, -922, -119,
-174, -913, 3719, 14492, 13764, 2926, -923, -123, -169, -916, 3644, 14430, 13834, 2995, -923, -127,
-164, -918, 3570, 14367, 13904, 3065, -924, -132, -159, -920, 3496, 14303, 13972, 3136, -924, -136,
-154, -921, 3423, 14239, 14040, 3207, -924, -140, -150, -922, 3350, 14173, 14107, 3278, -923, -145,
-145, -923, 3278, 14107, 14173, 3350, -922, -150, -140, -924, 3207, 14040, 14239, 3423, -921, -154,
-136, -924, 3136, 13972, 14303, 3496, -920, -159, -132, -924, 3065, 13904, 14367, 3570, -918, -164,
-127, -923, 2995, 13834, 14430, 3644, -916, -169, -123, -923, 2926, 13764, 14492, 3719, -913, -174,
-119, -922, 2857, 13693, 14553, 3795, -911, -179, -115, -921, 2789, 13622, 14614, 3871, -908, -184,
-111, -919, 2722, 13550, 14673, 3947, -904, -190, -107, -918, 2655, 13477, 14732, 4024, -900, -195,
-103, -916, 2589, 13403, 14790, 4102, -896, -200, -100, -914, 2523, 13329, 14847, 4180, -892, -206,
-96, -911, 2459, 13254, 14903, 4259, -887, -211, -92, -909, 2394, 13178, 14958, 4338, -882, -217,
-89, -906, 2331, 13102, 15012, 4417, -876, -223, -85, -903, 2267, 13025, 15065, 4498, -870, -229,
-82, -899, 2205, 12947, 15117, 4578, -864, -235, -79, -896, 2143, 12869, 15168, 4659, -857, -241,
-76, -892, 2082, 12790, 15219, 4741, -850, -247, -73, -888, 2022, 12711, 15268, 4823, -842, -253,
-70, -884, 1962, 12631, 15317, 4905, -834, -259, -67, -880, 1902, 12551, 15364, 4988, -826, -265,
-64, -875, 1844, 12470, 15410, 5071, -817, -272, -61, -871, 1786, 12388, 15456, 5155, -807, -278,
-58, -866, 1729, 12306, 15500, 5239, -798, -285, -56, -861, 1672, 12224, 15544, 5323, -787, -291,
-53, -855, 1616, 12140, 15586, 5408, -777, -298, -50, -850, 1561, 12057, 15627, 5493, -766, -305,
-48, -845, 1506, 11973, 15668, 5579, -754, -312, -46, -839, 1452, 11888, 15707, 5665, -742, -318,
-43, -833, 1399, 11803, 15745, 5751, -730, -325, -41, -827, 1346, 11718, 15782, 5838, -717, -332,
-39, -821, 1294, 11632, 15818, 5925, -703, -339, -37, -815, 1243, 11546, 15853, 6013, -689, -347,
-35, -809, 1192, 11459, 15887, 6100, -675, -354, -33, -802, 1142, 11372, 15920, 6189, -660, -361,
-31, -796, 1093, 11285, 15952, 6277, -645, -368, -29, -789, 1044, 11197, 15983, 6366, -629, -376,
-27, -782, 996, 11109, 16012, 6454, -612, -383, -26, -775, 949, 11021, 16041, 6544, -596, -391,
-24, -768, 902, 10932, 16068, 6633, -578, -398, -22, -761, 856, 10843, 16095, 6723, -560, -406,
-21, -754, 810, 10754, 16120, 6813, -542, -414, -19, -747, 766, 10664, 16144, 6903, -523, -421,
-18, -739, 722, 10574, 16167, 6994, -503, -429, -16, -732, 678, 10484, 16189, 7084, -483, -437,
-15, -724, 635, 10394, 16209, 7175, -462, -445, -14, -717, 593, 10303, 16229, 7266, -441, -452,
-13, -709, 552, 10212, 16247, 7357, -419, -460, -11, -702, 511, 10121, 16265, 7449, -397, -468,
-10, -694, 471, 10030, 16281, 7540, -374, -476, -9, -686, 432, 9939, 16296, 7632, -351, -484,
-8, -678, 393, 9847, 16310, 7724, -327, -492, -7, -670, 355, 9756, 16322, 7816, -302, -500,
-6, -662, 317, 9664, 16334, 7908, -277, -508, -5, -654, 280, 9572, 16344, 8000, -251, -516,
-5, -646, 244, 9480, 16354, 8093, -225, -525, -4, -638, 208, 9387, 16362, 8185, -198, -533,
-3, -630, 173, 9295, 16369, 8277, -170, -541, -2, -622, 139, 9203, 16375, 8370, -142, -549,
-2, -614, 105, 9110, 16379, 8462, -113, -557, -1, -606, 72, 9018, 16383, 8555, -84, -565,
-1, -598, 40, 8925, 16385, 8647, -54, -573, 0, -590, 8, 8833, 16386, 8740, -23, -582,
};
private static short[] _highCurveLut1 = new short[]
{
-12, 47, -134, 32767, 81, -16, 2, 0, -26, 108, -345, 32760, 301, -79, 17, -1,
-40, 168, -552, 32745, 526, -144, 32, -2, -53, 226, -753, 32723, 755, -210, 47, -3,
-66, 284, -950, 32694, 989, -277, 63, -5, -78, 340, -1143, 32658, 1226, -346, 79, -6,
-90, 394, -1331, 32615, 1469, -415, 96, -8, -101, 447, -1514, 32564, 1715, -486, 113, -9,
-112, 499, -1692, 32506, 1966, -557, 130, -11, -123, 550, -1865, 32441, 2221, -630, 148, -13,
-133, 599, -2034, 32369, 2480, -703, 166, -14, -143, 646, -2198, 32290, 2743, -778, 185, -16,
-152, 693, -2357, 32204, 3010, -853, 204, -18, -162, 738, -2512, 32110, 3281, -929, 223, -20,
-170, 781, -2662, 32010, 3555, -1007, 242, -23, -178, 823, -2807, 31903, 3834, -1084, 262, -25,
-186, 864, -2947, 31789, 4116, -1163, 282, -27, -194, 903, -3082, 31668, 4403, -1242, 303, -30,
-201, 940, -3213, 31540, 4692, -1322, 323, -32, -207, 977, -3339, 31406, 4985, -1403, 344, -35,
-214, 1011, -3460, 31265, 5282, -1484, 365, -37, -220, 1045, -3577, 31117, 5582, -1566, 387, -40,
-225, 1077, -3688, 30963, 5885, -1648, 409, -43, -230, 1107, -3796, 30802, 6191, -1730, 431, -46,
-235, 1136, -3898, 30635, 6501, -1813, 453, -49, -240, 1164, -3996, 30462, 6813, -1896, 475, -52,
-244, 1190, -4089, 30282, 7128, -1980, 498, -55, -247, 1215, -4178, 30097, 7446, -2064, 520, -58,
-251, 1239, -4262, 29905, 7767, -2148, 543, -62, -254, 1261, -4342, 29707, 8091, -2231, 566, -65,
-257, 1281, -4417, 29503, 8416, -2315, 589, -69, -259, 1301, -4488, 29293, 8745, -2399, 613, -72,
-261, 1319, -4555, 29078, 9075, -2483, 636, -76, -263, 1336, -4617, 28857, 9408, -2567, 659, -80,
-265, 1351, -4674, 28631, 9743, -2651, 683, -83, -266, 1365, -4728, 28399, 10080, -2734, 706, -87,
-267, 1378, -4777, 28161, 10418, -2817, 730, -91, -267, 1389, -4822, 27919, 10759, -2899, 753, -95,
-268, 1400, -4863, 27671, 11100, -2981, 777, -99, -268, 1409, -4900, 27418, 11444, -3063, 800, -103,
-268, 1416, -4933, 27161, 11789, -3144, 824, -107, -267, 1423, -4962, 26898, 12135, -3224, 847, -112,
-267, 1428, -4987, 26631, 12482, -3303, 870, -116, -266, 1433, -5008, 26359, 12830, -3382, 893, -120,
-265, 1436, -5026, 26083, 13179, -3460, 916, -125, -264, 1438, -5039, 25802, 13529, -3537, 939, -129,
-262, 1438, -5049, 25517, 13880, -3613, 962, -133, -260, 1438, -5055, 25228, 14231, -3687, 984, -138,
-258, 1437, -5058, 24935, 14582, -3761, 1006, -142, -256, 1435, -5058, 24639, 14934, -3833, 1028, -147,
-254, 1431, -5053, 24338, 15286, -3904, 1049, -151, -252, 1427, -5046, 24034, 15638, -3974, 1071, -155,
-249, 1422, -5035, 23726, 15989, -4042, 1091, -160, -246, 1416, -5021, 23415, 16341, -4109, 1112, -164,
-243, 1408, -5004, 23101, 16691, -4174, 1132, -169, -240, 1400, -4984, 22783, 17042, -4237, 1152, -173,
-237, 1392, -4960, 22463, 17392, -4299, 1171, -178, -234, 1382, -4934, 22140, 17740, -4358, 1190, -182,
-230, 1371, -4905, 21814, 18088, -4416, 1209, -186, -227, 1360, -4873, 21485, 18435, -4472, 1226, -191,
-223, 1348, -4839, 21154, 18781, -4526, 1244, -195, -219, 1335, -4801, 20821, 19125, -4578, 1260, -199,
-215, 1321, -4761, 20486, 19468, -4627, 1277, -203, -211, 1307, -4719, 20148, 19809, -4674, 1292, -207,
-207, 1292, -4674, 19809, 20148, -4719, 1307, -211, -203, 1277, -4627, 19468, 20486, -4761, 1321, -215,
-199, 1260, -4578, 19125, 20821, -4801, 1335, -219, -195, 1244, -4526, 18781, 21154, -4839, 1348, -223,
-191, 1226, -4472, 18435, 21485, -4873, 1360, -227, -186, 1209, -4416, 18088, 21814, -4905, 1371, -230,
-182, 1190, -4358, 17740, 22140, -4934, 1382, -234, -178, 1171, -4299, 17392, 22463, -4960, 1392, -237,
-173, 1152, -4237, 17042, 22783, -4984, 1400, -240, -169, 1132, -4174, 16691, 23101, -5004, 1408, -243,
-164, 1112, -4109, 16341, 23415, -5021, 1416, -246, -160, 1091, -4042, 15989, 23726, -5035, 1422, -249,
-155, 1071, -3974, 15638, 24034, -5046, 1427, -252, -151, 1049, -3904, 15286, 24338, -5053, 1431, -254,
-147, 1028, -3833, 14934, 24639, -5058, 1435, -256, -142, 1006, -3761, 14582, 24935, -5058, 1437, -258,
-138, 984, -3687, 14231, 25228, -5055, 1438, -260, -133, 962, -3613, 13880, 25517, -5049, 1438, -262,
-129, 939, -3537, 13529, 25802, -5039, 1438, -264, -125, 916, -3460, 13179, 26083, -5026, 1436, -265,
-120, 893, -3382, 12830, 26359, -5008, 1433, -266, -116, 870, -3303, 12482, 26631, -4987, 1428, -267,
-112, 847, -3224, 12135, 26898, -4962, 1423, -267, -107, 824, -3144, 11789, 27161, -4933, 1416, -268,
-103, 800, -3063, 11444, 27418, -4900, 1409, -268, -99, 777, -2981, 11100, 27671, -4863, 1400, -268,
-95, 753, -2899, 10759, 27919, -4822, 1389, -267, -91, 730, -2817, 10418, 28161, -4777, 1378, -267,
-87, 706, -2734, 10080, 28399, -4728, 1365, -266, -83, 683, -2651, 9743, 28631, -4674, 1351, -265,
-80, 659, -2567, 9408, 28857, -4617, 1336, -263, -76, 636, -2483, 9075, 29078, -4555, 1319, -261,
-72, 613, -2399, 8745, 29293, -4488, 1301, -259, -69, 589, -2315, 8416, 29503, -4417, 1281, -257,
-65, 566, -2231, 8091, 29707, -4342, 1261, -254, -62, 543, -2148, 7767, 29905, -4262, 1239, -251,
-58, 520, -2064, 7446, 30097, -4178, 1215, -247, -55, 498, -1980, 7128, 30282, -4089, 1190, -244,
-52, 475, -1896, 6813, 30462, -3996, 1164, -240, -49, 453, -1813, 6501, 30635, -3898, 1136, -235,
-46, 431, -1730, 6191, 30802, -3796, 1107, -230, -43, 409, -1648, 5885, 30963, -3688, 1077, -225,
-40, 387, -1566, 5582, 31117, -3577, 1045, -220, -37, 365, -1484, 5282, 31265, -3460, 1011, -214,
-35, 344, -1403, 4985, 31406, -3339, 977, -207, -32, 323, -1322, 4692, 31540, -3213, 940, -201,
-30, 303, -1242, 4403, 31668, -3082, 903, -194, -27, 282, -1163, 4116, 31789, -2947, 864, -186,
-25, 262, -1084, 3834, 31903, -2807, 823, -178, -23, 242, -1007, 3555, 32010, -2662, 781, -170,
-20, 223, -929, 3281, 32110, -2512, 738, -162, -18, 204, -853, 3010, 32204, -2357, 693, -152,
-16, 185, -778, 2743, 32290, -2198, 646, -143, -14, 166, -703, 2480, 32369, -2034, 599, -133,
-13, 148, -630, 2221, 32441, -1865, 550, -123, -11, 130, -557, 1966, 32506, -1692, 499, -112,
-9, 113, -486, 1715, 32564, -1514, 447, -101, -8, 96, -415, 1469, 32615, -1331, 394, -90,
-6, 79, -346, 1226, 32658, -1143, 340, -78, -5, 63, -277, 989, 32694, -950, 284, -66,
-3, 47, -210, 755, 32723, -753, 226, -53, -2, 32, -144, 526, 32745, -552, 168, -40,
-1, 17, -79, 301, 32760, -345, 108, -26, 0, 2, -16, 81, 32767, -134, 47, -12,
};
private static short[] _highCurveLut2 = new short[]
{
418, -2538, 6118, 24615, 6298, -2563, 417, 0, 420, -2512, 5939, 24611, 6479, -2588, 415, 1,
421, -2485, 5761, 24605, 6662, -2612, 412, 2, 422, -2458, 5585, 24595, 6846, -2635, 409, 3,
423, -2430, 5410, 24582, 7030, -2658, 406, 4, 423, -2402, 5236, 24565, 7216, -2680, 403, 5,
423, -2373, 5064, 24546, 7403, -2701, 399, 6, 423, -2343, 4893, 24523, 7591, -2721, 395, 7,
423, -2313, 4724, 24496, 7780, -2741, 391, 8, 422, -2283, 4556, 24467, 7970, -2759, 386, 9,
421, -2252, 4390, 24434, 8161, -2777, 381, 11, 420, -2221, 4225, 24398, 8353, -2794, 376, 12,
419, -2190, 4062, 24359, 8545, -2810, 370, 14, 418, -2158, 3900, 24316, 8739, -2825, 364, 15,
416, -2126, 3740, 24271, 8933, -2839, 358, 17, 414, -2093, 3582, 24222, 9127, -2851, 351, 19,
412, -2060, 3425, 24170, 9323, -2863, 344, 21, 410, -2027, 3270, 24115, 9519, -2874, 336, 22,
407, -1993, 3117, 24056, 9715, -2884, 328, 24, 404, -1960, 2966, 23995, 9912, -2893, 319, 26,
402, -1926, 2816, 23930, 10110, -2900, 311, 29, 398, -1892, 2668, 23863, 10308, -2907, 301, 31,
395, -1858, 2522, 23792, 10506, -2912, 292, 33, 392, -1823, 2378, 23718, 10705, -2916, 282, 35,
389, -1789, 2235, 23641, 10904, -2919, 271, 38, 385, -1754, 2095, 23561, 11103, -2920, 261, 40,
381, -1719, 1956, 23478, 11303, -2921, 249, 43, 377, -1684, 1819, 23393, 11502, -2920, 238, 45,
373, -1649, 1684, 23304, 11702, -2917, 225, 48, 369, -1615, 1551, 23212, 11902, -2914, 213, 51,
365, -1580, 1420, 23118, 12102, -2909, 200, 54, 361, -1545, 1291, 23020, 12302, -2902, 186, 57,
356, -1510, 1163, 22920, 12502, -2895, 173, 60, 352, -1475, 1038, 22817, 12702, -2885, 158, 63,
347, -1440, 915, 22711, 12901, -2875, 143, 66, 342, -1405, 793, 22602, 13101, -2863, 128, 69,
338, -1370, 674, 22491, 13300, -2849, 113, 73, 333, -1335, 557, 22377, 13499, -2834, 97, 76,
328, -1301, 441, 22260, 13698, -2817, 80, 80, 323, -1266, 328, 22141, 13896, -2799, 63, 83,
318, -1232, 217, 22019, 14094, -2779, 46, 87, 313, -1197, 107, 21894, 14291, -2758, 28, 91,
307, -1163, 0, 21767, 14488, -2735, 9, 95, 302, -1129, -105, 21637, 14684, -2710, -9, 98,
297, -1096, -208, 21506, 14879, -2684, -29, 102, 292, -1062, -310, 21371, 15074, -2656, -48, 106,
286, -1029, -409, 21234, 15268, -2626, -69, 111, 281, -996, -506, 21095, 15461, -2595, -89, 115,
276, -963, -601, 20954, 15654, -2562, -110, 119, 270, -930, -694, 20810, 15846, -2527, -132, 123,
265, -898, -785, 20664, 16036, -2490, -154, 128, 260, -866, -874, 20516, 16226, -2452, -176, 132,
254, -834, -961, 20366, 16415, -2411, -199, 137, 249, -803, -1046, 20213, 16602, -2369, -222, 141,
243, -771, -1129, 20059, 16789, -2326, -246, 146, 238, -740, -1209, 19902, 16974, -2280, -270, 151,
233, -710, -1288, 19744, 17158, -2232, -294, 156, 227, -680, -1365, 19583, 17341, -2183, -319, 160,
222, -650, -1440, 19421, 17523, -2132, -345, 165, 217, -620, -1513, 19257, 17703, -2079, -370, 170,
211, -591, -1583, 19091, 17882, -2023, -396, 175, 206, -562, -1652, 18923, 18059, -1966, -423, 180,
201, -533, -1719, 18754, 18235, -1907, -450, 185, 196, -505, -1784, 18582, 18410, -1847, -477, 191,
191, -477, -1847, 18410, 18582, -1784, -505, 196, 185, -450, -1907, 18235, 18754, -1719, -533, 201,
180, -423, -1966, 18059, 18923, -1652, -562, 206, 175, -396, -2023, 17882, 19091, -1583, -591, 211,
170, -370, -2079, 17703, 19257, -1513, -620, 217, 165, -345, -2132, 17523, 19421, -1440, -650, 222,
160, -319, -2183, 17341, 19583, -1365, -680, 227, 156, -294, -2232, 17158, 19744, -1288, -710, 233,
151, -270, -2280, 16974, 19902, -1209, -740, 238, 146, -246, -2326, 16789, 20059, -1129, -771, 243,
141, -222, -2369, 16602, 20213, -1046, -803, 249, 137, -199, -2411, 16415, 20366, -961, -834, 254,
132, -176, -2452, 16226, 20516, -874, -866, 260, 128, -154, -2490, 16036, 20664, -785, -898, 265,
123, -132, -2527, 15846, 20810, -694, -930, 270, 119, -110, -2562, 15654, 20954, -601, -963, 276,
115, -89, -2595, 15461, 21095, -506, -996, 281, 111, -69, -2626, 15268, 21234, -409, -1029, 286,
106, -48, -2656, 15074, 21371, -310, -1062, 292, 102, -29, -2684, 14879, 21506, -208, -1096, 297,
98, -9, -2710, 14684, 21637, -105, -1129, 302, 95, 9, -2735, 14488, 21767, 0, -1163, 307,
91, 28, -2758, 14291, 21894, 107, -1197, 313, 87, 46, -2779, 14094, 22019, 217, -1232, 318,
83, 63, -2799, 13896, 22141, 328, -1266, 323, 80, 80, -2817, 13698, 22260, 441, -1301, 328,
76, 97, -2834, 13499, 22377, 557, -1335, 333, 73, 113, -2849, 13300, 22491, 674, -1370, 338,
69, 128, -2863, 13101, 22602, 793, -1405, 342, 66, 143, -2875, 12901, 22711, 915, -1440, 347,
63, 158, -2885, 12702, 22817, 1038, -1475, 352, 60, 173, -2895, 12502, 22920, 1163, -1510, 356,
57, 186, -2902, 12302, 23020, 1291, -1545, 361, 54, 200, -2909, 12102, 23118, 1420, -1580, 365,
51, 213, -2914, 11902, 23212, 1551, -1615, 369, 48, 225, -2917, 11702, 23304, 1684, -1649, 373,
45, 238, -2920, 11502, 23393, 1819, -1684, 377, 43, 249, -2921, 11303, 23478, 1956, -1719, 381,
40, 261, -2920, 11103, 23561, 2095, -1754, 385, 38, 271, -2919, 10904, 23641, 2235, -1789, 389,
35, 282, -2916, 10705, 23718, 2378, -1823, 392, 33, 292, -2912, 10506, 23792, 2522, -1858, 395,
31, 301, -2907, 10308, 23863, 2668, -1892, 398, 29, 311, -2900, 10110, 23930, 2816, -1926, 402,
26, 319, -2893, 9912, 23995, 2966, -1960, 404, 24, 328, -2884, 9715, 24056, 3117, -1993, 407,
22, 336, -2874, 9519, 24115, 3270, -2027, 410, 21, 344, -2863, 9323, 24170, 3425, -2060, 412,
19, 351, -2851, 9127, 24222, 3582, -2093, 414, 17, 358, -2839, 8933, 24271, 3740, -2126, 416,
15, 364, -2825, 8739, 24316, 3900, -2158, 418, 14, 370, -2810, 8545, 24359, 4062, -2190, 419,
12, 376, -2794, 8353, 24398, 4225, -2221, 420, 11, 381, -2777, 8161, 24434, 4390, -2252, 421,
9, 386, -2759, 7970, 24467, 4556, -2283, 422, 8, 391, -2741, 7780, 24496, 4724, -2313, 423,
7, 395, -2721, 7591, 24523, 4893, -2343, 423, 6, 399, -2701, 7403, 24546, 5064, -2373, 423,
5, 403, -2680, 7216, 24565, 5236, -2402, 423, 4, 406, -2658, 7030, 24582, 5410, -2430, 423,
3, 409, -2635, 6846, 24595, 5585, -2458, 422, 2, 412, -2612, 6662, 24605, 5761, -2485, 421,
1, 415, -2588, 6479, 24611, 5939, -2512, 420, 0, 417, -2563, 6298, 24615, 6118, -2538, 418,
};
#endregion
private static float[] _normalCurveLut0F;
private static float[] _normalCurveLut1F;
private static float[] _normalCurveLut2F;
private static float[] _highCurveLut0F;
private static float[] _highCurveLut1F;
private static float[] _highCurveLut2F;
static ResamplerHelper()
{
_normalCurveLut0F = _normalCurveLut0.Select(x => x / 32768f).ToArray();
_normalCurveLut1F = _normalCurveLut1.Select(x => x / 32768f).ToArray();
_normalCurveLut2F = _normalCurveLut2.Select(x => x / 32768f).ToArray();
_highCurveLut0F = _highCurveLut0.Select(x => x / 32768f).ToArray();
_highCurveLut1F = _highCurveLut1.Select(x => x / 32768f).ToArray();
_highCurveLut2F = _highCurveLut2.Select(x => x / 32768f).ToArray();
}
private const int FixedPointPrecision = 15;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Resample(Span<float> outputBuffer, ReadOnlySpan<short> inputBuffer, float ratio, ref float fraction, int sampleCount, SampleRateConversionQuality srcQuality, bool needPitch)
{
switch (srcQuality)
{
case SampleRateConversionQuality.Default:
ResampleDefaultQuality(outputBuffer, inputBuffer, ratio, ref fraction, sampleCount, needPitch);
break;
case SampleRateConversionQuality.Low:
ResampleLowQuality(outputBuffer, inputBuffer, ratio, ref fraction, sampleCount);
break;
case SampleRateConversionQuality.High:
ResampleHighQuality(outputBuffer, inputBuffer, ratio, ref fraction, sampleCount);
break;
default:
throw new NotImplementedException($"{srcQuality}");
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static ReadOnlySpan<float> GetDefaultParameter(float ratio)
{
if (ratio <= 1.0f)
{
return _normalCurveLut1F;
}
else if (ratio > 1.333313f)
{
return _normalCurveLut0F;
}
return _normalCurveLut2F;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private unsafe static void ResampleDefaultQuality(Span<float> outputBuffer, ReadOnlySpan<short> inputBuffer, float ratio, ref float fraction, int sampleCount, bool needPitch)
{
ReadOnlySpan<float> parameters = GetDefaultParameter(ratio);
int inputBufferIndex = 0, i = 0;
// TODO: REV8 fast path (when needPitch == false the input index progression is constant + we need SIMD)
if (Sse41.IsSupported)
{
if (ratio == 1f)
{
fixed (short* pInput = inputBuffer)
{
fixed (float* pOutput = outputBuffer, pParameters = parameters)
{
Vector128<float> parameter = Sse.LoadVector128(pParameters);
for (; i < (sampleCount & ~3); i += 4)
{
Vector128<int> intInput0 = Sse41.ConvertToVector128Int32(pInput + (uint)i);
Vector128<int> intInput1 = Sse41.ConvertToVector128Int32(pInput + (uint)i + 1);
Vector128<int> intInput2 = Sse41.ConvertToVector128Int32(pInput + (uint)i + 2);
Vector128<int> intInput3 = Sse41.ConvertToVector128Int32(pInput + (uint)i + 3);
Vector128<float> input0 = Sse2.ConvertToVector128Single(intInput0);
Vector128<float> input1 = Sse2.ConvertToVector128Single(intInput1);
Vector128<float> input2 = Sse2.ConvertToVector128Single(intInput2);
Vector128<float> input3 = Sse2.ConvertToVector128Single(intInput3);
Vector128<float> mix0 = Sse.Multiply(input0, parameter);
Vector128<float> mix1 = Sse.Multiply(input1, parameter);
Vector128<float> mix2 = Sse.Multiply(input2, parameter);
Vector128<float> mix3 = Sse.Multiply(input3, parameter);
Vector128<float> mix01 = Sse3.HorizontalAdd(mix0, mix1);
Vector128<float> mix23 = Sse3.HorizontalAdd(mix2, mix3);
Vector128<float> mix0123 = Sse3.HorizontalAdd(mix01, mix23);
Sse.Store(pOutput + (uint)i, Sse41.RoundToNearestInteger(mix0123));
}
}
}
inputBufferIndex = i;
}
else
{
fixed (short* pInput = inputBuffer)
{
fixed (float* pOutput = outputBuffer, pParameters = parameters)
{
for (; i < (sampleCount & ~3); i += 4)
{
uint baseIndex0 = (uint)(fraction * 128) * 4;
uint inputIndex0 = (uint)inputBufferIndex;
fraction += ratio;
uint baseIndex1 = ((uint)(fraction * 128) & 127) * 4;
uint inputIndex1 = (uint)inputBufferIndex + (uint)fraction;
fraction += ratio;
uint baseIndex2 = ((uint)(fraction * 128) & 127) * 4;
uint inputIndex2 = (uint)inputBufferIndex + (uint)fraction;
fraction += ratio;
uint baseIndex3 = ((uint)(fraction * 128) & 127) * 4;
uint inputIndex3 = (uint)inputBufferIndex + (uint)fraction;
fraction += ratio;
inputBufferIndex += (int)fraction;
// Only keep lower part (safe as fraction isn't supposed to be negative)
fraction -= (int)fraction;
Vector128<float> parameter0 = Sse.LoadVector128(pParameters + baseIndex0);
Vector128<float> parameter1 = Sse.LoadVector128(pParameters + baseIndex1);
Vector128<float> parameter2 = Sse.LoadVector128(pParameters + baseIndex2);
Vector128<float> parameter3 = Sse.LoadVector128(pParameters + baseIndex3);
Vector128<int> intInput0 = Sse41.ConvertToVector128Int32(pInput + inputIndex0);
Vector128<int> intInput1 = Sse41.ConvertToVector128Int32(pInput + inputIndex1);
Vector128<int> intInput2 = Sse41.ConvertToVector128Int32(pInput + inputIndex2);
Vector128<int> intInput3 = Sse41.ConvertToVector128Int32(pInput + inputIndex3);
Vector128<float> input0 = Sse2.ConvertToVector128Single(intInput0);
Vector128<float> input1 = Sse2.ConvertToVector128Single(intInput1);
Vector128<float> input2 = Sse2.ConvertToVector128Single(intInput2);
Vector128<float> input3 = Sse2.ConvertToVector128Single(intInput3);
Vector128<float> mix0 = Sse.Multiply(input0, parameter0);
Vector128<float> mix1 = Sse.Multiply(input1, parameter1);
Vector128<float> mix2 = Sse.Multiply(input2, parameter2);
Vector128<float> mix3 = Sse.Multiply(input3, parameter3);
Vector128<float> mix01 = Sse3.HorizontalAdd(mix0, mix1);
Vector128<float> mix23 = Sse3.HorizontalAdd(mix2, mix3);
Vector128<float> mix0123 = Sse3.HorizontalAdd(mix01, mix23);
Sse.Store(pOutput + (uint)i, Sse41.RoundToNearestInteger(mix0123));
}
}
}
}
}
for (; i < sampleCount; i++)
{
int baseIndex = (int)(fraction * 128) * 4;
ReadOnlySpan<float> parameter = parameters.Slice(baseIndex, 4);
ReadOnlySpan<short> currentInput = inputBuffer.Slice(inputBufferIndex, 4);
outputBuffer[i] = (float)Math.Round(currentInput[0] * parameter[0] +
currentInput[1] * parameter[1] +
currentInput[2] * parameter[2] +
currentInput[3] * parameter[3]);
fraction += ratio;
inputBufferIndex += (int)fraction;
// Only keep lower part (safe as fraction isn't supposed to be negative)
fraction -= (int)fraction;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static ReadOnlySpan<float> GetHighParameter(float ratio)
{
if (ratio <= 1.0f)
{
return _highCurveLut1F;
}
else if (ratio > 1.333313f)
{
return _highCurveLut0F;
}
return _highCurveLut2F;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void ResampleHighQuality(Span<float> outputBuffer, ReadOnlySpan<short> inputBuffer, float ratio, ref float fraction, int sampleCount)
{
ReadOnlySpan<float> parameters = GetHighParameter(ratio);
int inputBufferIndex = 0;
// TODO: fast path
for (int i = 0; i < sampleCount; i++)
{
int baseIndex = (int)(fraction * 128) * 8;
ReadOnlySpan<float> parameter = parameters.Slice(baseIndex, 8);
ReadOnlySpan<short> currentInput = inputBuffer.Slice(inputBufferIndex, 8);
outputBuffer[i] = (float)Math.Round(currentInput[0] * parameter[0] +
currentInput[1] * parameter[1] +
currentInput[2] * parameter[2] +
currentInput[3] * parameter[3] +
currentInput[4] * parameter[4] +
currentInput[5] * parameter[5] +
currentInput[6] * parameter[6] +
currentInput[7] * parameter[7]);
fraction += ratio;
inputBufferIndex += (int)MathF.Truncate(fraction);
fraction -= (int)fraction;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void ResampleLowQuality(Span<float> outputBuffer, ReadOnlySpan<short> inputBuffer, float ratio, ref float fraction, int sampleCount)
{
int inputBufferIndex = 0;
for (int i = 0; i < sampleCount; i++)
{
int outputData = inputBuffer[inputBufferIndex];
if (fraction > 1.0f)
{
outputData = inputBuffer[inputBufferIndex + 1];
}
outputBuffer[i] = outputData;
fraction += ratio;
inputBufferIndex += (int)MathF.Truncate(fraction);
fraction -= (int)fraction;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void ResampleForUpsampler(Span<float> outputBuffer, ReadOnlySpan<float> inputBuffer, float ratio, ref float fraction, int sampleCount)
{
// Currently a simple cubic interpolation, assuming duplicated values at edges.
// TODO: Discover and use algorithm that the switch uses.
int inputBufferIndex = 0;
int maxIndex = inputBuffer.Length - 1;
int cubicEnd = inputBuffer.Length - 3;
for (int i = 0; i < sampleCount; i++)
{
float s0, s1, s2, s3;
s1 = inputBuffer[inputBufferIndex];
if (inputBufferIndex == 0 || inputBufferIndex > cubicEnd)
{
// Clamp interplation values at the ends of the input buffer.
s0 = inputBuffer[Math.Max(0, inputBufferIndex - 1)];
s2 = inputBuffer[Math.Min(maxIndex, inputBufferIndex + 1)];
s3 = inputBuffer[Math.Min(maxIndex, inputBufferIndex + 2)];
}
else
{
s0 = inputBuffer[inputBufferIndex - 1];
s2 = inputBuffer[inputBufferIndex + 1];
s3 = inputBuffer[inputBufferIndex + 2];
}
float a = s3 - s2 - s0 + s1;
float b = s0 - s1 - a;
float c = s2 - s0;
float d = s1;
float f2 = fraction * fraction;
float f3 = f2 * fraction;
outputBuffer[i] = a * f3 + b * f2 + c * fraction + d;
fraction += ratio;
inputBufferIndex += (int)MathF.Truncate(fraction);
fraction -= (int)fraction;
}
}
}
}

View File

@@ -1,67 +0,0 @@
using Ryujinx.Audio.Renderer.Common;
using Ryujinx.Audio.Renderer.Dsp.State;
using Ryujinx.Audio.Renderer.Parameter.Effect;
using Ryujinx.Audio.Renderer.Parameter;
using Ryujinx.Audio.Renderer.Server.MemoryPool;
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace Ryujinx.Audio.Renderer.Server.Effect
{
/// <summary>
/// Server state for a compressor effect.
/// </summary>
public class CompressorEffect : BaseEffect
{
/// <summary>
/// The compressor parameter.
/// </summary>
public CompressorParameter Parameter;
/// <summary>
/// The compressor state.
/// </summary>
public Memory<CompressorState> State { get; }
/// <summary>
/// Create a new <see cref="CompressorEffect"/>.
/// </summary>
public CompressorEffect()
{
State = new CompressorState[1];
}
public override EffectType TargetEffectType => EffectType.Compressor;
public override ulong GetWorkBuffer(int index)
{
return GetSingleBuffer();
}
public override void Update(out BehaviourParameter.ErrorInfo updateErrorInfo, ref EffectInParameterVersion1 parameter, PoolMapper mapper)
{
// Nintendo doesn't do anything here but we still require updateErrorInfo to be initialised.
updateErrorInfo = new BehaviourParameter.ErrorInfo();
}
public override void Update(out BehaviourParameter.ErrorInfo updateErrorInfo, ref EffectInParameterVersion2 parameter, PoolMapper mapper)
{
Debug.Assert(IsTypeValid(ref parameter));
UpdateParameterBase(ref parameter);
Parameter = MemoryMarshal.Cast<byte, CompressorParameter>(parameter.SpecificData)[0];
IsEnabled = parameter.IsEnabled;
updateErrorInfo = new BehaviourParameter.ErrorInfo();
}
public override void UpdateForCommandGeneration()
{
UpdateUsageStateForCommandGeneration();
Parameter.Status = UsageState.Enabled;
}
}
}

View File

@@ -1,636 +0,0 @@
using Ryujinx.Audio.Renderer.Common;
using Ryujinx.Audio.Renderer.Parameter;
using Ryujinx.Audio.Renderer.Parameter.Performance;
using Ryujinx.Audio.Renderer.Server.Effect;
using Ryujinx.Audio.Renderer.Server.MemoryPool;
using Ryujinx.Audio.Renderer.Server.Mix;
using Ryujinx.Audio.Renderer.Server.Performance;
using Ryujinx.Audio.Renderer.Server.Sink;
using Ryujinx.Audio.Renderer.Server.Splitter;
using Ryujinx.Audio.Renderer.Server.Voice;
using Ryujinx.Audio.Renderer.Utils;
using Ryujinx.Common.Logging;
using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using static Ryujinx.Audio.Renderer.Common.BehaviourParameter;
namespace Ryujinx.Audio.Renderer.Server
{
public class StateUpdater
{
private readonly ReadOnlyMemory<byte> _inputOrigin;
private ReadOnlyMemory<byte> _outputOrigin;
private ReadOnlyMemory<byte> _input;
private Memory<byte> _output;
private uint _processHandle;
private BehaviourContext _behaviourContext;
private UpdateDataHeader _inputHeader;
private Memory<UpdateDataHeader> _outputHeader;
private ref UpdateDataHeader OutputHeader => ref _outputHeader.Span[0];
public StateUpdater(ReadOnlyMemory<byte> input, Memory<byte> output, uint processHandle, BehaviourContext behaviourContext)
{
_input = input;
_inputOrigin = _input;
_output = output;
_outputOrigin = _output;
_processHandle = processHandle;
_behaviourContext = behaviourContext;
_inputHeader = SpanIOHelper.Read<UpdateDataHeader>(ref _input);
_outputHeader = SpanMemoryManager<UpdateDataHeader>.Cast(_output.Slice(0, Unsafe.SizeOf<UpdateDataHeader>()));
OutputHeader.Initialize(_behaviourContext.UserRevision);
_output = _output.Slice(Unsafe.SizeOf<UpdateDataHeader>());
}
public ResultCode UpdateBehaviourContext()
{
BehaviourParameter parameter = SpanIOHelper.Read<BehaviourParameter>(ref _input);
if (!BehaviourContext.CheckValidRevision(parameter.UserRevision) || parameter.UserRevision != _behaviourContext.UserRevision)
{
return ResultCode.InvalidUpdateInfo;
}
_behaviourContext.ClearError();
_behaviourContext.UpdateFlags(parameter.Flags);
if (_inputHeader.BehaviourSize != Unsafe.SizeOf<BehaviourParameter>())
{
return ResultCode.InvalidUpdateInfo;
}
return ResultCode.Success;
}
public ResultCode UpdateMemoryPools(Span<MemoryPoolState> memoryPools)
{
PoolMapper mapper = new PoolMapper(_processHandle, _behaviourContext.IsMemoryPoolForceMappingEnabled());
if (memoryPools.Length * Unsafe.SizeOf<MemoryPoolInParameter>() != _inputHeader.MemoryPoolsSize)
{
return ResultCode.InvalidUpdateInfo;
}
foreach (ref MemoryPoolState memoryPool in memoryPools)
{
MemoryPoolInParameter parameter = SpanIOHelper.Read<MemoryPoolInParameter>(ref _input);
ref MemoryPoolOutStatus outStatus = ref SpanIOHelper.GetWriteRef<MemoryPoolOutStatus>(ref _output)[0];
PoolMapper.UpdateResult updateResult = mapper.Update(ref memoryPool, ref parameter, ref outStatus);
if (updateResult != PoolMapper.UpdateResult.Success &&
updateResult != PoolMapper.UpdateResult.MapError &&
updateResult != PoolMapper.UpdateResult.UnmapError)
{
if (updateResult != PoolMapper.UpdateResult.InvalidParameter)
{
throw new InvalidOperationException($"{updateResult}");
}
return ResultCode.InvalidUpdateInfo;
}
}
OutputHeader.MemoryPoolsSize = (uint)(Unsafe.SizeOf<MemoryPoolOutStatus>() * memoryPools.Length);
OutputHeader.TotalSize += OutputHeader.MemoryPoolsSize;
return ResultCode.Success;
}
public ResultCode UpdateVoiceChannelResources(VoiceContext context)
{
if (context.GetCount() * Unsafe.SizeOf<VoiceChannelResourceInParameter>() != _inputHeader.VoiceResourcesSize)
{
return ResultCode.InvalidUpdateInfo;
}
for (int i = 0; i < context.GetCount(); i++)
{
VoiceChannelResourceInParameter parameter = SpanIOHelper.Read<VoiceChannelResourceInParameter>(ref _input);
ref VoiceChannelResource resource = ref context.GetChannelResource(i);
resource.Id = parameter.Id;
parameter.Mix.AsSpan().CopyTo(resource.Mix.AsSpan());
resource.IsUsed = parameter.IsUsed;
}
return ResultCode.Success;
}
public ResultCode UpdateVoices(VoiceContext context, Memory<MemoryPoolState> memoryPools)
{
if (context.GetCount() * Unsafe.SizeOf<VoiceInParameter>() != _inputHeader.VoicesSize)
{
return ResultCode.InvalidUpdateInfo;
}
int initialOutputSize = _output.Length;
ReadOnlySpan<VoiceInParameter> parameters = MemoryMarshal.Cast<byte, VoiceInParameter>(_input.Slice(0, (int)_inputHeader.VoicesSize).Span);
_input = _input.Slice((int)_inputHeader.VoicesSize);
PoolMapper mapper = new PoolMapper(_processHandle, memoryPools, _behaviourContext.IsMemoryPoolForceMappingEnabled());
// First make everything not in use.
for (int i = 0; i < context.GetCount(); i++)
{
ref VoiceState state = ref context.GetState(i);
state.InUse = false;
}
// Start processing
for (int i = 0; i < context.GetCount(); i++)
{
VoiceInParameter parameter = parameters[i];
Memory<VoiceUpdateState>[] voiceUpdateStates = new Memory<VoiceUpdateState>[Constants.VoiceChannelCountMax];
ref VoiceOutStatus outStatus = ref SpanIOHelper.GetWriteRef<VoiceOutStatus>(ref _output)[0];
if (parameter.InUse)
{
ref VoiceState currentVoiceState = ref context.GetState(i);
for (int channelResourceIndex = 0; channelResourceIndex < parameter.ChannelCount; channelResourceIndex++)
{
int channelId = parameter.ChannelResourceIds[channelResourceIndex];
Debug.Assert(channelId >= 0 && channelId < context.GetCount());
voiceUpdateStates[channelResourceIndex] = context.GetUpdateStateForCpu(channelId);
}
if (parameter.IsNew)
{
currentVoiceState.Initialize();
}
currentVoiceState.UpdateParameters(out ErrorInfo updateParameterError, ref parameter, ref mapper, ref _behaviourContext);
if (updateParameterError.ErrorCode != ResultCode.Success)
{
_behaviourContext.AppendError(ref updateParameterError);
}
currentVoiceState.UpdateWaveBuffers(out ErrorInfo[] waveBufferUpdateErrorInfos, ref parameter, voiceUpdateStates, ref mapper, ref _behaviourContext);
foreach (ref ErrorInfo errorInfo in waveBufferUpdateErrorInfos.AsSpan())
{
if (errorInfo.ErrorCode != ResultCode.Success)
{
_behaviourContext.AppendError(ref errorInfo);
}
}
currentVoiceState.WriteOutStatus(ref outStatus, ref parameter, voiceUpdateStates);
}
}
int currentOutputSize = _output.Length;
OutputHeader.VoicesSize = (uint)(Unsafe.SizeOf<VoiceOutStatus>() * context.GetCount());
OutputHeader.TotalSize += OutputHeader.VoicesSize;
Debug.Assert((initialOutputSize - currentOutputSize) == OutputHeader.VoicesSize);
return ResultCode.Success;
}
private static void ResetEffect<T>(ref BaseEffect effect, ref T parameter, PoolMapper mapper) where T : unmanaged, IEffectInParameter
{
effect.ForceUnmapBuffers(mapper);
switch (parameter.Type)
{
case EffectType.Invalid:
effect = new BaseEffect();
break;
case EffectType.BufferMix:
effect = new BufferMixEffect();
break;
case EffectType.AuxiliaryBuffer:
effect = new AuxiliaryBufferEffect();
break;
case EffectType.Delay:
effect = new DelayEffect();
break;
case EffectType.Reverb:
effect = new ReverbEffect();
break;
case EffectType.Reverb3d:
effect = new Reverb3dEffect();
break;
case EffectType.BiquadFilter:
effect = new BiquadFilterEffect();
break;
case EffectType.Limiter:
effect = new LimiterEffect();
break;
case EffectType.CaptureBuffer:
effect = new CaptureBufferEffect();
break;
case EffectType.Compressor:
effect = new CompressorEffect();
break;
default:
throw new NotImplementedException($"EffectType {parameter.Type} not implemented!");
}
}
public ResultCode UpdateEffects(EffectContext context, bool isAudioRendererActive, Memory<MemoryPoolState> memoryPools)
{
if (_behaviourContext.IsEffectInfoVersion2Supported())
{
return UpdateEffectsVersion2(context, isAudioRendererActive, memoryPools);
}
else
{
return UpdateEffectsVersion1(context, isAudioRendererActive, memoryPools);
}
}
public ResultCode UpdateEffectsVersion2(EffectContext context, bool isAudioRendererActive, Memory<MemoryPoolState> memoryPools)
{
if (context.GetCount() * Unsafe.SizeOf<EffectInParameterVersion2>() != _inputHeader.EffectsSize)
{
return ResultCode.InvalidUpdateInfo;
}
int initialOutputSize = _output.Length;
ReadOnlySpan<EffectInParameterVersion2> parameters = MemoryMarshal.Cast<byte, EffectInParameterVersion2>(_input.Slice(0, (int)_inputHeader.EffectsSize).Span);
_input = _input.Slice((int)_inputHeader.EffectsSize);
PoolMapper mapper = new PoolMapper(_processHandle, memoryPools, _behaviourContext.IsMemoryPoolForceMappingEnabled());
for (int i = 0; i < context.GetCount(); i++)
{
EffectInParameterVersion2 parameter = parameters[i];
ref EffectOutStatusVersion2 outStatus = ref SpanIOHelper.GetWriteRef<EffectOutStatusVersion2>(ref _output)[0];
ref BaseEffect effect = ref context.GetEffect(i);
if (!effect.IsTypeValid(ref parameter))
{
ResetEffect(ref effect, ref parameter, mapper);
}
effect.Update(out ErrorInfo updateErrorInfo, ref parameter, mapper);
if (updateErrorInfo.ErrorCode != ResultCode.Success)
{
_behaviourContext.AppendError(ref updateErrorInfo);
}
effect.StoreStatus(ref outStatus, isAudioRendererActive);
if (parameter.IsNew)
{
effect.InitializeResultState(ref context.GetDspState(i));
effect.InitializeResultState(ref context.GetState(i));
}
effect.UpdateResultState(ref outStatus.ResultState, ref context.GetState(i));
}
int currentOutputSize = _output.Length;
OutputHeader.EffectsSize = (uint)(Unsafe.SizeOf<EffectOutStatusVersion2>() * context.GetCount());
OutputHeader.TotalSize += OutputHeader.EffectsSize;
Debug.Assert((initialOutputSize - currentOutputSize) == OutputHeader.EffectsSize);
return ResultCode.Success;
}
public ResultCode UpdateEffectsVersion1(EffectContext context, bool isAudioRendererActive, Memory<MemoryPoolState> memoryPools)
{
if (context.GetCount() * Unsafe.SizeOf<EffectInParameterVersion1>() != _inputHeader.EffectsSize)
{
return ResultCode.InvalidUpdateInfo;
}
int initialOutputSize = _output.Length;
ReadOnlySpan<EffectInParameterVersion1> parameters = MemoryMarshal.Cast<byte, EffectInParameterVersion1>(_input.Slice(0, (int)_inputHeader.EffectsSize).Span);
_input = _input.Slice((int)_inputHeader.EffectsSize);
PoolMapper mapper = new PoolMapper(_processHandle, memoryPools, _behaviourContext.IsMemoryPoolForceMappingEnabled());
for (int i = 0; i < context.GetCount(); i++)
{
EffectInParameterVersion1 parameter = parameters[i];
ref EffectOutStatusVersion1 outStatus = ref SpanIOHelper.GetWriteRef<EffectOutStatusVersion1>(ref _output)[0];
ref BaseEffect effect = ref context.GetEffect(i);
if (!effect.IsTypeValid(ref parameter))
{
ResetEffect(ref effect, ref parameter, mapper);
}
effect.Update(out ErrorInfo updateErrorInfo, ref parameter, mapper);
if (updateErrorInfo.ErrorCode != ResultCode.Success)
{
_behaviourContext.AppendError(ref updateErrorInfo);
}
effect.StoreStatus(ref outStatus, isAudioRendererActive);
}
int currentOutputSize = _output.Length;
OutputHeader.EffectsSize = (uint)(Unsafe.SizeOf<EffectOutStatusVersion1>() * context.GetCount());
OutputHeader.TotalSize += OutputHeader.EffectsSize;
Debug.Assert((initialOutputSize - currentOutputSize) == OutputHeader.EffectsSize);
return ResultCode.Success;
}
public ResultCode UpdateSplitter(SplitterContext context)
{
if (context.Update(_input.Span, out int consumedSize))
{
_input = _input.Slice(consumedSize);
return ResultCode.Success;
}
else
{
return ResultCode.InvalidUpdateInfo;
}
}
private bool CheckMixParametersValidity(MixContext mixContext, uint mixBufferCount, uint inputMixCount, ReadOnlySpan<MixParameter> parameters)
{
uint maxMixStateCount = mixContext.GetCount();
uint totalRequiredMixBufferCount = 0;
for (int i = 0; i < inputMixCount; i++)
{
if (parameters[i].IsUsed)
{
if (parameters[i].DestinationMixId != Constants.UnusedMixId &&
parameters[i].DestinationMixId > maxMixStateCount &&
parameters[i].MixId != Constants.FinalMixId)
{
return true;
}
totalRequiredMixBufferCount += parameters[i].BufferCount;
}
}
return totalRequiredMixBufferCount > mixBufferCount;
}
public ResultCode UpdateMixes(MixContext mixContext, uint mixBufferCount, EffectContext effectContext, SplitterContext splitterContext)
{
uint mixCount;
uint inputMixSize;
uint inputSize = 0;
if (_behaviourContext.IsMixInParameterDirtyOnlyUpdateSupported())
{
MixInParameterDirtyOnlyUpdate parameter = MemoryMarshal.Cast<byte, MixInParameterDirtyOnlyUpdate>(_input.Span)[0];
mixCount = parameter.MixCount;
inputSize += (uint)Unsafe.SizeOf<MixInParameterDirtyOnlyUpdate>();
}
else
{
mixCount = mixContext.GetCount();
}
inputMixSize = mixCount * (uint)Unsafe.SizeOf<MixParameter>();
inputSize += inputMixSize;
if (inputSize != _inputHeader.MixesSize)
{
return ResultCode.InvalidUpdateInfo;
}
if (_behaviourContext.IsMixInParameterDirtyOnlyUpdateSupported())
{
_input = _input.Slice(Unsafe.SizeOf<MixInParameterDirtyOnlyUpdate>());
}
ReadOnlySpan<MixParameter> parameters = MemoryMarshal.Cast<byte, MixParameter>(_input.Span.Slice(0, (int)inputMixSize));
_input = _input.Slice((int)inputMixSize);
if (CheckMixParametersValidity(mixContext, mixBufferCount, mixCount, parameters))
{
return ResultCode.InvalidUpdateInfo;
}
bool isMixContextDirty = false;
for (int i = 0; i < parameters.Length; i++)
{
MixParameter parameter = parameters[i];
int mixId = i;
if (_behaviourContext.IsMixInParameterDirtyOnlyUpdateSupported())
{
mixId = parameter.MixId;
}
ref MixState mix = ref mixContext.GetState(mixId);
if (parameter.IsUsed != mix.IsUsed)
{
mix.IsUsed = parameter.IsUsed;
if (parameter.IsUsed)
{
mix.ClearEffectProcessingOrder();
}
isMixContextDirty = true;
}
if (mix.IsUsed)
{
isMixContextDirty |= mix.Update(mixContext.EdgeMatrix, ref parameter, effectContext, splitterContext, _behaviourContext);
}
}
if (isMixContextDirty)
{
if (_behaviourContext.IsSplitterSupported() && splitterContext.UsingSplitter())
{
if (!mixContext.Sort(splitterContext))
{
return ResultCode.InvalidMixSorting;
}
}
else
{
mixContext.Sort();
}
}
return ResultCode.Success;
}
private static void ResetSink(ref BaseSink sink, ref SinkInParameter parameter)
{
sink.CleanUp();
switch (parameter.Type)
{
case SinkType.Invalid:
sink = new BaseSink();
break;
case SinkType.CircularBuffer:
sink = new CircularBufferSink();
break;
case SinkType.Device:
sink = new DeviceSink();
break;
default:
throw new NotImplementedException($"SinkType {parameter.Type} not implemented!");
}
}
public ResultCode UpdateSinks(SinkContext context, Memory<MemoryPoolState> memoryPools)
{
PoolMapper mapper = new PoolMapper(_processHandle, memoryPools, _behaviourContext.IsMemoryPoolForceMappingEnabled());
if (context.GetCount() * Unsafe.SizeOf<SinkInParameter>() != _inputHeader.SinksSize)
{
return ResultCode.InvalidUpdateInfo;
}
int initialOutputSize = _output.Length;
ReadOnlySpan<SinkInParameter> parameters = MemoryMarshal.Cast<byte, SinkInParameter>(_input.Slice(0, (int)_inputHeader.SinksSize).Span);
_input = _input.Slice((int)_inputHeader.SinksSize);
for (int i = 0; i < context.GetCount(); i++)
{
SinkInParameter parameter = parameters[i];
ref SinkOutStatus outStatus = ref SpanIOHelper.GetWriteRef<SinkOutStatus>(ref _output)[0];
ref BaseSink sink = ref context.GetSink(i);
if (!sink.IsTypeValid(ref parameter))
{
ResetSink(ref sink, ref parameter);
}
sink.Update(out ErrorInfo updateErrorInfo, ref parameter, ref outStatus, mapper);
if (updateErrorInfo.ErrorCode != ResultCode.Success)
{
_behaviourContext.AppendError(ref updateErrorInfo);
}
}
int currentOutputSize = _output.Length;
OutputHeader.SinksSize = (uint)(Unsafe.SizeOf<SinkOutStatus>() * context.GetCount());
OutputHeader.TotalSize += OutputHeader.SinksSize;
Debug.Assert((initialOutputSize - currentOutputSize) == OutputHeader.SinksSize);
return ResultCode.Success;
}
public ResultCode UpdatePerformanceBuffer(PerformanceManager manager, Span<byte> performanceOutput)
{
if (Unsafe.SizeOf<PerformanceInParameter>() != _inputHeader.PerformanceBufferSize)
{
return ResultCode.InvalidUpdateInfo;
}
PerformanceInParameter parameter = SpanIOHelper.Read<PerformanceInParameter>(ref _input);
ref PerformanceOutStatus outStatus = ref SpanIOHelper.GetWriteRef<PerformanceOutStatus>(ref _output)[0];
if (manager != null)
{
outStatus.HistorySize = manager.CopyHistories(performanceOutput);
manager.SetTargetNodeId(parameter.TargetNodeId);
}
else
{
outStatus.HistorySize = 0;
}
OutputHeader.PerformanceBufferSize = (uint)Unsafe.SizeOf<PerformanceOutStatus>();
OutputHeader.TotalSize += OutputHeader.PerformanceBufferSize;
return ResultCode.Success;
}
public ResultCode UpdateErrorInfo()
{
ref BehaviourErrorInfoOutStatus outStatus = ref SpanIOHelper.GetWriteRef<BehaviourErrorInfoOutStatus>(ref _output)[0];
_behaviourContext.CopyErrorInfo(outStatus.ErrorInfos.AsSpan(), out outStatus.ErrorInfosCount);
OutputHeader.BehaviourSize = (uint)Unsafe.SizeOf<BehaviourErrorInfoOutStatus>();
OutputHeader.TotalSize += OutputHeader.BehaviourSize;
return ResultCode.Success;
}
public ResultCode UpdateRendererInfo(ulong elapsedFrameCount)
{
ref RendererInfoOutStatus outStatus = ref SpanIOHelper.GetWriteRef<RendererInfoOutStatus>(ref _output)[0];
outStatus.ElapsedFrameCount = elapsedFrameCount;
OutputHeader.RenderInfoSize = (uint)Unsafe.SizeOf<RendererInfoOutStatus>();
OutputHeader.TotalSize += OutputHeader.RenderInfoSize;
return ResultCode.Success;
}
public ResultCode CheckConsumedSize()
{
int consumedInputSize = _inputOrigin.Length - _input.Length;
int consumedOutputSize = _outputOrigin.Length - _output.Length;
if (consumedInputSize != _inputHeader.TotalSize)
{
Logger.Error?.Print(LogClass.AudioRenderer, $"Consumed input size mismatch (got {consumedInputSize} expected {_inputHeader.TotalSize})");
return ResultCode.InvalidUpdateInfo;
}
if (consumedOutputSize != OutputHeader.TotalSize)
{
Logger.Error?.Print(LogClass.AudioRenderer, $"Consumed output size mismatch (got {consumedOutputSize} expected {OutputHeader.TotalSize})");
return ResultCode.InvalidUpdateInfo;
}
return ResultCode.Success;
}
}
}

View File

@@ -1,63 +0,0 @@
using System;
namespace Ryujinx.Audio.Renderer.Server.Upsampler
{
/// <summary>
/// Server state for a upsampling.
/// </summary>
public class UpsamplerState
{
/// <summary>
/// The output buffer containing the target samples.
/// </summary>
public Memory<float> OutputBuffer { get; }
/// <summary>
/// The target sample count.
/// </summary>
public uint SampleCount { get; }
/// <summary>
/// The index of the <see cref="UpsamplerState"/>. (used to free it)
/// </summary>
private int _index;
/// <summary>
/// The <see cref="UpsamplerManager"/>.
/// </summary>
private UpsamplerManager _manager;
/// <summary>
/// The source sample count.
/// </summary>
public uint SourceSampleCount;
/// <summary>
/// The input buffer indices of the buffers holding the samples that need upsampling.
/// </summary>
public ushort[] InputBufferIndices;
/// <summary>
/// Create a new <see cref="UpsamplerState"/>.
/// </summary>
/// <param name="manager">The upsampler manager.</param>
/// <param name="index">The index of the <see cref="UpsamplerState"/>. (used to free it)</param>
/// <param name="outputBuffer">The output buffer used to contain the target samples.</param>
/// <param name="sampleCount">The target sample count.</param>
public UpsamplerState(UpsamplerManager manager, int index, Memory<float> outputBuffer, uint sampleCount)
{
_manager = manager;
_index = index;
OutputBuffer = outputBuffer;
SampleCount = sampleCount;
}
/// <summary>
/// Release the <see cref="UpsamplerState"/>.
/// </summary>
public void Release()
{
_manager.Free(_index);
}
}
}

View File

@@ -1,699 +0,0 @@
using Ryujinx.Audio.Common;
using Ryujinx.Audio.Renderer.Common;
using Ryujinx.Audio.Renderer.Parameter;
using Ryujinx.Audio.Renderer.Server.MemoryPool;
using Ryujinx.Common.Memory;
using Ryujinx.Common.Utilities;
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using static Ryujinx.Audio.Renderer.Common.BehaviourParameter;
using static Ryujinx.Audio.Renderer.Parameter.VoiceInParameter;
namespace Ryujinx.Audio.Renderer.Server.Voice
{
[StructLayout(LayoutKind.Sequential, Pack = Alignment)]
public struct VoiceState
{
public const int Alignment = 0x10;
/// <summary>
/// Set to true if the voice is used.
/// </summary>
[MarshalAs(UnmanagedType.I1)]
public bool InUse;
/// <summary>
/// Set to true if the voice is new.
/// </summary>
[MarshalAs(UnmanagedType.I1)]
public bool IsNew;
[MarshalAs(UnmanagedType.I1)]
public bool WasPlaying;
/// <summary>
/// The <see cref="SampleFormat"/> of the voice.
/// </summary>
public SampleFormat SampleFormat;
/// <summary>
/// The sample rate of the voice.
/// </summary>
public uint SampleRate;
/// <summary>
/// The total channel count used.
/// </summary>
public uint ChannelsCount;
/// <summary>
/// Id of the voice.
/// </summary>
public int Id;
/// <summary>
/// Node id of the voice.
/// </summary>
public int NodeId;
/// <summary>
/// The target mix id of the voice.
/// </summary>
public int MixId;
/// <summary>
/// The current voice <see cref="Types.PlayState"/>.
/// </summary>
public Types.PlayState PlayState;
/// <summary>
/// The previous voice <see cref="Types.PlayState"/>.
/// </summary>
public Types.PlayState PreviousPlayState;
/// <summary>
/// The priority of the voice.
/// </summary>
public uint Priority;
/// <summary>
/// Target sorting position of the voice. (used to sort voice with the same <see cref="Priority"/>)
/// </summary>
public uint SortingOrder;
/// <summary>
/// The pitch used on the voice.
/// </summary>
public float Pitch;
/// <summary>
/// The output volume of the voice.
/// </summary>
public float Volume;
/// <summary>
/// The previous output volume of the voice.
/// </summary>
public float PreviousVolume;
/// <summary>
/// Biquad filters to apply to the output of the voice.
/// </summary>
public Array2<BiquadFilterParameter> BiquadFilters;
/// <summary>
/// Total count of <see cref="WaveBufferInternal"/> of the voice.
/// </summary>
public uint WaveBuffersCount;
/// <summary>
/// Current playing <see cref="WaveBufferInternal"/> of the voice.
/// </summary>
public uint WaveBuffersIndex;
/// <summary>
/// Change the behaviour of the voice.
/// </summary>
/// <remarks>This was added on REV5.</remarks>
public DecodingBehaviour DecodingBehaviour;
/// <summary>
/// User state <see cref="AddressInfo"/> required by the data source.
/// </summary>
/// <remarks>Only used for <see cref="SampleFormat.Adpcm"/> as the GC-ADPCM coefficients.</remarks>
public AddressInfo DataSourceStateAddressInfo;
/// <summary>
/// The wavebuffers of this voice.
/// </summary>
public Array4<WaveBuffer> WaveBuffers;
/// <summary>
/// The channel resource ids associated to the voice.
/// </summary>
public Array6<int> ChannelResourceIds;
/// <summary>
/// The target splitter id of the voice.
/// </summary>
public uint SplitterId;
/// <summary>
/// Change the Sample Rate Conversion (SRC) quality of the voice.
/// </summary>
/// <remarks>This was added on REV8.</remarks>
public SampleRateConversionQuality SrcQuality;
/// <summary>
/// If set to true, the voice was dropped.
/// </summary>
[MarshalAs(UnmanagedType.I1)]
public bool VoiceDropFlag;
/// <summary>
/// Set to true if the data source state work buffer wasn't mapped.
/// </summary>
[MarshalAs(UnmanagedType.I1)]
public bool DataSourceStateUnmapped;
/// <summary>
/// Set to true if any of the <see cref="WaveBuffer.BufferAddressInfo"/> work buffer wasn't mapped.
/// </summary>
[MarshalAs(UnmanagedType.I1)]
public bool BufferInfoUnmapped;
/// <summary>
/// The biquad filter initialization state storage.
/// </summary>
private BiquadFilterNeedInitializationArrayStruct _biquadFilterNeedInitialization;
/// <summary>
/// Flush the amount of wavebuffer specified. This will result in the wavebuffer being skipped and marked played.
/// </summary>
/// <remarks>This was added on REV5.</remarks>
public byte FlushWaveBufferCount;
[StructLayout(LayoutKind.Sequential, Size = Constants.VoiceBiquadFilterCount)]
private struct BiquadFilterNeedInitializationArrayStruct { }
/// <summary>
/// The biquad filter initialization state array.
/// </summary>
public Span<bool> BiquadFilterNeedInitialization => SpanHelpers.AsSpan<BiquadFilterNeedInitializationArrayStruct, bool>(ref _biquadFilterNeedInitialization);
/// <summary>
/// Initialize the <see cref="VoiceState"/>.
/// </summary>
public void Initialize()
{
IsNew = false;
VoiceDropFlag = false;
DataSourceStateUnmapped = false;
BufferInfoUnmapped = false;
FlushWaveBufferCount = 0;
PlayState = Types.PlayState.Stopped;
Priority = Constants.VoiceLowestPriority;
Id = 0;
NodeId = 0;
SampleRate = 0;
SampleFormat = SampleFormat.Invalid;
ChannelsCount = 0;
Pitch = 0.0f;
Volume = 0.0f;
PreviousVolume = 0.0f;
BiquadFilters.AsSpan().Fill(new BiquadFilterParameter());
WaveBuffersCount = 0;
WaveBuffersIndex = 0;
MixId = Constants.UnusedMixId;
SplitterId = Constants.UnusedSplitterId;
DataSourceStateAddressInfo.Setup(0, 0);
InitializeWaveBuffers();
}
/// <summary>
/// Initialize the <see cref="WaveBuffer"/> in this <see cref="VoiceState"/>.
/// </summary>
private void InitializeWaveBuffers()
{
for (int i = 0; i < WaveBuffers.Length; i++)
{
WaveBuffers[i].StartSampleOffset = 0;
WaveBuffers[i].EndSampleOffset = 0;
WaveBuffers[i].ShouldLoop = false;
WaveBuffers[i].IsEndOfStream = false;
WaveBuffers[i].BufferAddressInfo.Setup(0, 0);
WaveBuffers[i].ContextAddressInfo.Setup(0, 0);
WaveBuffers[i].IsSendToAudioProcessor = true;
}
}
/// <summary>
/// Check if the voice needs to be skipped.
/// </summary>
/// <returns>Returns true if the voice needs to be skipped.</returns>
public bool ShouldSkip()
{
return !InUse || WaveBuffersCount == 0 || DataSourceStateUnmapped || BufferInfoUnmapped || VoiceDropFlag;
}
/// <summary>
/// Return true if the mix has any destinations.
/// </summary>
/// <returns>True if the mix has any destinations.</returns>
public bool HasAnyDestination()
{
return MixId != Constants.UnusedMixId || SplitterId != Constants.UnusedSplitterId;
}
/// <summary>
/// Indicate if the server voice information needs to be updated.
/// </summary>
/// <param name="parameter">The user parameter.</param>
/// <returns>Return true, if the server voice information needs to be updated.</returns>
private bool ShouldUpdateParameters(ref VoiceInParameter parameter)
{
if (DataSourceStateAddressInfo.CpuAddress == parameter.DataSourceStateAddress)
{
return DataSourceStateAddressInfo.Size != parameter.DataSourceStateSize;
}
return DataSourceStateAddressInfo.CpuAddress != parameter.DataSourceStateAddress ||
DataSourceStateAddressInfo.Size != parameter.DataSourceStateSize ||
DataSourceStateUnmapped;
}
/// <summary>
/// Update the internal state from a user parameter.
/// </summary>
/// <param name="outErrorInfo">The possible <see cref="ErrorInfo"/> that was generated.</param>
/// <param name="parameter">The user parameter.</param>
/// <param name="poolMapper">The mapper to use.</param>
/// <param name="behaviourContext">The behaviour context.</param>
public void UpdateParameters(out ErrorInfo outErrorInfo, ref VoiceInParameter parameter, ref PoolMapper poolMapper, ref BehaviourContext behaviourContext)
{
InUse = parameter.InUse;
Id = parameter.Id;
NodeId = parameter.NodeId;
UpdatePlayState(parameter.PlayState);
SrcQuality = parameter.SrcQuality;
Priority = parameter.Priority;
SortingOrder = parameter.SortingOrder;
SampleRate = parameter.SampleRate;
SampleFormat = parameter.SampleFormat;
ChannelsCount = parameter.ChannelCount;
Pitch = parameter.Pitch;
Volume = parameter.Volume;
parameter.BiquadFilters.AsSpan().CopyTo(BiquadFilters.AsSpan());
WaveBuffersCount = parameter.WaveBuffersCount;
WaveBuffersIndex = parameter.WaveBuffersIndex;
if (behaviourContext.IsFlushVoiceWaveBuffersSupported())
{
FlushWaveBufferCount += parameter.FlushWaveBufferCount;
}
MixId = parameter.MixId;
if (behaviourContext.IsSplitterSupported())
{
SplitterId = parameter.SplitterId;
}
else
{
SplitterId = Constants.UnusedSplitterId;
}
parameter.ChannelResourceIds.AsSpan().CopyTo(ChannelResourceIds.AsSpan());
DecodingBehaviour behaviour = DecodingBehaviour.Default;
if (behaviourContext.IsDecodingBehaviourFlagSupported())
{
behaviour = parameter.DecodingBehaviourFlags;
}
DecodingBehaviour = behaviour;
if (parameter.ResetVoiceDropFlag)
{
VoiceDropFlag = false;
}
if (ShouldUpdateParameters(ref parameter))
{
DataSourceStateUnmapped = !poolMapper.TryAttachBuffer(out outErrorInfo, ref DataSourceStateAddressInfo, parameter.DataSourceStateAddress, parameter.DataSourceStateSize);
}
else
{
outErrorInfo = new ErrorInfo();
}
}
/// <summary>
/// Update the internal play state from user play state.
/// </summary>
/// <param name="userPlayState">The target user play state.</param>
public void UpdatePlayState(PlayState userPlayState)
{
Types.PlayState oldServerPlayState = PlayState;
PreviousPlayState = oldServerPlayState;
Types.PlayState newServerPlayState;
switch (userPlayState)
{
case Common.PlayState.Start:
newServerPlayState = Types.PlayState.Started;
break;
case Common.PlayState.Stop:
if (oldServerPlayState == Types.PlayState.Stopped)
{
return;
}
newServerPlayState = Types.PlayState.Stopping;
break;
case Common.PlayState.Pause:
newServerPlayState = Types.PlayState.Paused;
break;
default:
throw new NotImplementedException($"Unhandled PlayState.{userPlayState}");
}
PlayState = newServerPlayState;
}
/// <summary>
/// Write the status of the voice to the given user output.
/// </summary>
/// <param name="outStatus">The given user output.</param>
/// <param name="parameter">The user parameter.</param>
/// <param name="voiceUpdateStates">The voice states associated to the <see cref="VoiceState"/>.</param>
public void WriteOutStatus(ref VoiceOutStatus outStatus, ref VoiceInParameter parameter, Memory<VoiceUpdateState>[] voiceUpdateStates)
{
#if DEBUG
// Sanity check in debug mode of the internal state
if (!parameter.IsNew && !IsNew)
{
for (int i = 1; i < ChannelsCount; i++)
{
ref VoiceUpdateState stateA = ref voiceUpdateStates[i - 1].Span[0];
ref VoiceUpdateState stateB = ref voiceUpdateStates[i].Span[0];
Debug.Assert(stateA.WaveBufferConsumed == stateB.WaveBufferConsumed);
Debug.Assert(stateA.PlayedSampleCount == stateB.PlayedSampleCount);
Debug.Assert(stateA.Offset == stateB.Offset);
Debug.Assert(stateA.WaveBufferIndex == stateB.WaveBufferIndex);
Debug.Assert(stateA.Fraction == stateB.Fraction);
Debug.Assert(stateA.IsWaveBufferValid.SequenceEqual(stateB.IsWaveBufferValid));
}
}
#endif
if (parameter.IsNew || IsNew)
{
IsNew = true;
outStatus.VoiceDropFlag = false;
outStatus.PlayedWaveBuffersCount = 0;
outStatus.PlayedSampleCount = 0;
}
else
{
ref VoiceUpdateState state = ref voiceUpdateStates[0].Span[0];
outStatus.VoiceDropFlag = VoiceDropFlag;
outStatus.PlayedWaveBuffersCount = state.WaveBufferConsumed;
outStatus.PlayedSampleCount = state.PlayedSampleCount;
}
}
/// <summary>
/// Update the internal state of all the <see cref="WaveBuffer"/> of the <see cref="VoiceState"/>.
/// </summary>
/// <param name="errorInfos">An array of <see cref="ErrorInfo"/> used to report errors when mapping any of the <see cref="WaveBuffer"/>.</param>
/// <param name="parameter">The user parameter.</param>
/// <param name="voiceUpdateStates">The voice states associated to the <see cref="VoiceState"/>.</param>
/// <param name="mapper">The mapper to use.</param>
/// <param name="behaviourContext">The behaviour context.</param>
public void UpdateWaveBuffers(out ErrorInfo[] errorInfos, ref VoiceInParameter parameter, Memory<VoiceUpdateState>[] voiceUpdateStates, ref PoolMapper mapper, ref BehaviourContext behaviourContext)
{
errorInfos = new ErrorInfo[Constants.VoiceWaveBufferCount * 2];
if (parameter.IsNew)
{
InitializeWaveBuffers();
for (int i = 0; i < parameter.ChannelCount; i++)
{
voiceUpdateStates[i].Span[0].IsWaveBufferValid.Fill(false);
}
}
ref VoiceUpdateState voiceUpdateState = ref voiceUpdateStates[0].Span[0];
for (int i = 0; i < Constants.VoiceWaveBufferCount; i++)
{
UpdateWaveBuffer(errorInfos.AsSpan(i * 2, 2), ref WaveBuffers[i], ref parameter.WaveBuffers[i], parameter.SampleFormat, voiceUpdateState.IsWaveBufferValid[i], ref mapper, ref behaviourContext);
}
}
/// <summary>
/// Update the internal state of one of the <see cref="WaveBuffer"/> of the <see cref="VoiceState"/>.
/// </summary>
/// <param name="errorInfos">A <see cref="Span{ErrorInfo}"/> used to report errors when mapping the <see cref="WaveBuffer"/>.</param>
/// <param name="waveBuffer">The <see cref="WaveBuffer"/> to update.</param>
/// <param name="inputWaveBuffer">The <see cref="WaveBufferInternal"/> from the user input.</param>
/// <param name="sampleFormat">The <see cref="SampleFormat"/> from the user input.</param>
/// <param name="isValid">If set to true, the server side wavebuffer is considered valid.</param>
/// <param name="mapper">The mapper to use.</param>
/// <param name="behaviourContext">The behaviour context.</param>
private void UpdateWaveBuffer(Span<ErrorInfo> errorInfos, ref WaveBuffer waveBuffer, ref WaveBufferInternal inputWaveBuffer, SampleFormat sampleFormat, bool isValid, ref PoolMapper mapper, ref BehaviourContext behaviourContext)
{
if (!isValid && waveBuffer.IsSendToAudioProcessor && waveBuffer.BufferAddressInfo.CpuAddress != 0)
{
mapper.ForceUnmap(ref waveBuffer.BufferAddressInfo);
waveBuffer.BufferAddressInfo.Setup(0, 0);
}
if (!inputWaveBuffer.SentToServer || BufferInfoUnmapped)
{
if (inputWaveBuffer.IsSampleOffsetValid(sampleFormat))
{
Debug.Assert(waveBuffer.IsSendToAudioProcessor);
waveBuffer.IsSendToAudioProcessor = false;
waveBuffer.StartSampleOffset = inputWaveBuffer.StartSampleOffset;
waveBuffer.EndSampleOffset = inputWaveBuffer.EndSampleOffset;
waveBuffer.ShouldLoop = inputWaveBuffer.ShouldLoop;
waveBuffer.IsEndOfStream = inputWaveBuffer.IsEndOfStream;
waveBuffer.LoopStartSampleOffset = inputWaveBuffer.LoopFirstSampleOffset;
waveBuffer.LoopEndSampleOffset = inputWaveBuffer.LoopLastSampleOffset;
waveBuffer.LoopCount = inputWaveBuffer.LoopCount;
BufferInfoUnmapped = !mapper.TryAttachBuffer(out ErrorInfo bufferInfoError, ref waveBuffer.BufferAddressInfo, inputWaveBuffer.Address, inputWaveBuffer.Size);
errorInfos[0] = bufferInfoError;
if (sampleFormat == SampleFormat.Adpcm && behaviourContext.IsAdpcmLoopContextBugFixed() && inputWaveBuffer.ContextAddress != 0)
{
bool adpcmLoopContextMapped = mapper.TryAttachBuffer(out ErrorInfo adpcmLoopContextInfoError,
ref waveBuffer.ContextAddressInfo,
inputWaveBuffer.ContextAddress,
inputWaveBuffer.ContextSize);
errorInfos[1] = adpcmLoopContextInfoError;
if (adpcmLoopContextMapped)
{
BufferInfoUnmapped = DataSourceStateUnmapped;
}
else
{
BufferInfoUnmapped = true;
}
}
else
{
waveBuffer.ContextAddressInfo.Setup(0, 0);
}
}
else
{
errorInfos[0].ErrorCode = ResultCode.InvalidAddressInfo;
errorInfos[0].ExtraErrorInfo = inputWaveBuffer.Address;
}
}
}
/// <summary>
/// Reset the resources associated to this <see cref="VoiceState"/>.
/// </summary>
/// <param name="context">The voice context.</param>
private void ResetResources(VoiceContext context)
{
for (int i = 0; i < ChannelsCount; i++)
{
int channelResourceId = ChannelResourceIds[i];
ref VoiceChannelResource voiceChannelResource = ref context.GetChannelResource(channelResourceId);
Debug.Assert(voiceChannelResource.IsUsed);
Memory<VoiceUpdateState> dspSharedState = context.GetUpdateStateForDsp(channelResourceId);
MemoryMarshal.Cast<VoiceUpdateState, byte>(dspSharedState.Span).Fill(0);
voiceChannelResource.UpdateState();
}
}
/// <summary>
/// Flush a certain amount of <see cref="WaveBuffer"/>.
/// </summary>
/// <param name="waveBufferCount">The amount of wavebuffer to flush.</param>
/// <param name="voiceUpdateStates">The voice states associated to the <see cref="VoiceState"/>.</param>
/// <param name="channelCount">The channel count from user input.</param>
private void FlushWaveBuffers(uint waveBufferCount, Memory<VoiceUpdateState>[] voiceUpdateStates, uint channelCount)
{
uint waveBufferIndex = WaveBuffersIndex;
for (int i = 0; i < waveBufferCount; i++)
{
WaveBuffers[(int)waveBufferIndex].IsSendToAudioProcessor = true;
for (int j = 0; j < channelCount; j++)
{
ref VoiceUpdateState voiceUpdateState = ref voiceUpdateStates[j].Span[0];
voiceUpdateState.WaveBufferIndex = (voiceUpdateState.WaveBufferIndex + 1) % Constants.VoiceWaveBufferCount;
voiceUpdateState.WaveBufferConsumed++;
voiceUpdateState.IsWaveBufferValid[(int)waveBufferIndex] = false;
}
waveBufferIndex = (waveBufferIndex + 1) % Constants.VoiceWaveBufferCount;
}
}
/// <summary>
/// Update the internal parameters for command generation.
/// </summary>
/// <param name="voiceUpdateStates">The voice states associated to the <see cref="VoiceState"/>.</param>
/// <returns>Return true if this voice should be played.</returns>
public bool UpdateParametersForCommandGeneration(Memory<VoiceUpdateState>[] voiceUpdateStates)
{
if (FlushWaveBufferCount != 0)
{
FlushWaveBuffers(FlushWaveBufferCount, voiceUpdateStates, ChannelsCount);
FlushWaveBufferCount = 0;
}
switch (PlayState)
{
case Types.PlayState.Started:
for (int i = 0; i < WaveBuffers.Length; i++)
{
ref WaveBuffer wavebuffer = ref WaveBuffers[i];
if (!wavebuffer.IsSendToAudioProcessor)
{
for (int y = 0; y < ChannelsCount; y++)
{
Debug.Assert(!voiceUpdateStates[y].Span[0].IsWaveBufferValid[i]);
voiceUpdateStates[y].Span[0].IsWaveBufferValid[i] = true;
}
wavebuffer.IsSendToAudioProcessor = true;
}
}
WasPlaying = false;
ref VoiceUpdateState primaryVoiceUpdateState = ref voiceUpdateStates[0].Span[0];
for (int i = 0; i < primaryVoiceUpdateState.IsWaveBufferValid.Length; i++)
{
if (primaryVoiceUpdateState.IsWaveBufferValid[i])
{
return true;
}
}
return false;
case Types.PlayState.Stopping:
for (int i = 0; i < WaveBuffers.Length; i++)
{
ref WaveBuffer wavebuffer = ref WaveBuffers[i];
wavebuffer.IsSendToAudioProcessor = true;
for (int j = 0; j < ChannelsCount; j++)
{
ref VoiceUpdateState voiceUpdateState = ref voiceUpdateStates[j].Span[0];
if (voiceUpdateState.IsWaveBufferValid[i])
{
voiceUpdateState.WaveBufferIndex = (voiceUpdateState.WaveBufferIndex + 1) % Constants.VoiceWaveBufferCount;
voiceUpdateState.WaveBufferConsumed++;
}
voiceUpdateState.IsWaveBufferValid[i] = false;
}
}
for (int i = 0; i < ChannelsCount; i++)
{
ref VoiceUpdateState voiceUpdateState = ref voiceUpdateStates[i].Span[0];
voiceUpdateState.Offset = 0;
voiceUpdateState.PlayedSampleCount = 0;
voiceUpdateState.Pitch.AsSpan().Fill(0);
voiceUpdateState.Fraction = 0;
voiceUpdateState.LoopContext = new Dsp.State.AdpcmLoopContext();
}
PlayState = Types.PlayState.Stopped;
WasPlaying = PreviousPlayState == Types.PlayState.Started;
return WasPlaying;
case Types.PlayState.Stopped:
case Types.PlayState.Paused:
foreach (ref WaveBuffer wavebuffer in WaveBuffers.AsSpan())
{
wavebuffer.BufferAddressInfo.GetReference(true);
wavebuffer.ContextAddressInfo.GetReference(true);
}
if (SampleFormat == SampleFormat.Adpcm)
{
if (DataSourceStateAddressInfo.CpuAddress != 0)
{
DataSourceStateAddressInfo.GetReference(true);
}
}
WasPlaying = PreviousPlayState == Types.PlayState.Started;
return WasPlaying;
default:
throw new NotImplementedException($"{PlayState}");
}
}
/// <summary>
/// Update the internal state for command generation.
/// </summary>
/// <param name="context">The voice context.</param>
/// <returns>Return true if this voice should be played.</returns>
public bool UpdateForCommandGeneration(VoiceContext context)
{
if (IsNew)
{
ResetResources(context);
PreviousVolume = Volume;
IsNew = false;
}
Memory<VoiceUpdateState>[] voiceUpdateStates = new Memory<VoiceUpdateState>[Constants.VoiceChannelCountMax];
for (int i = 0; i < ChannelsCount; i++)
{
voiceUpdateStates[i] = context.GetUpdateStateForDsp(ChannelResourceIds[i]);
}
return UpdateParametersForCommandGeneration(voiceUpdateStates);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,613 +0,0 @@
{
"MenuBarFileOpenApplet": "Applet öffnen",
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Öffnet das Mii Editor Applet im Standalone Modus",
"SettingsTabInputDirectMouseAccess": "Direkter Mauszugriff",
"SettingsTabSystemMemoryManagerMode": "Speichermanagermodus:",
"SettingsTabSystemMemoryManagerModeSoftware": "Software",
"SettingsTabSystemMemoryManagerModeHost": "Host (schnell)",
"SettingsTabSystemMemoryManagerModeHostUnchecked": "Host ungeprüft (am schnellsten, unsicher)",
"MenuBarFile": "_Datei",
"MenuBarFileOpenFromFile": "_Datei öffnen",
"MenuBarFileOpenUnpacked": "_Entpacktes Spiel öffnen",
"MenuBarFileOpenEmuFolder": "Ryujinx-Ordner öffnen",
"MenuBarFileOpenLogsFolder": "Logs-Ordner öffnen",
"MenuBarFileExit": "_Beenden",
"MenuBarOptions": "Optionen",
"MenuBarOptionsToggleFullscreen": "Vollbild",
"MenuBarOptionsStartGamesInFullscreen": "Spiele im Vollbildmodus starten",
"MenuBarOptionsStopEmulation": "Emulation beenden",
"MenuBarOptionsSettings": "_Einstellungen",
"MenuBarOptionsManageUserProfiles": "_Profilverwaltung",
"MenuBarActions": "_Aktionen",
"MenuBarOptionsSimulateWakeUpMessage": "Aufwachnachricht",
"MenuBarActionsScanAmiibo": "Scanne ein Amiibo",
"MenuBarTools": "_Werkzeuge",
"MenuBarToolsInstallFirmware": "Firmware installieren",
"MenuBarFileToolsInstallFirmwareFromFile": "Installiere Firmware von einer XCI oder einer ZIP Datei",
"MenuBarFileToolsInstallFirmwareFromDirectory": "Installiere Firmware aus einem Verzeichnis",
"MenuBarHelp": "Hilfe",
"MenuBarHelpCheckForUpdates": "Nach Updates suchen",
"MenuBarHelpAbout": "Über Ryujinx",
"MenuSearch": "Suchen...",
"GameListHeaderFavorite": "Favorit",
"GameListHeaderIcon": "Icon",
"GameListHeaderApplication": "Name",
"GameListHeaderDeveloper": "Entwickler",
"GameListHeaderVersion": "Version",
"GameListHeaderTimePlayed": "Spielzeit",
"GameListHeaderLastPlayed": "Zuletzt gespielt",
"GameListHeaderFileExtension": "Dateiformat",
"GameListHeaderFileSize": "Dateigröße",
"GameListHeaderPath": "Pfad",
"GameListContextMenuOpenUserSaveDirectory": "Spielstand-Verzeichnis öffnen",
"GameListContextMenuOpenUserSaveDirectoryToolTip": "Öffnet das Verzeichnis, welches den Benutzer-Spielstand beinhaltet",
"GameListContextMenuOpenUserDeviceDirectory": "Benutzer-Geräte-Verzeichnis öffnen",
"GameListContextMenuOpenUserDeviceDirectoryToolTip": "Öffnet das Verzeichnis, welches den Geräte-Spielstände beinhaltet",
"GameListContextMenuOpenUserBcatDirectory": "Benutzer-BCAT-Vezeichnis öffnen",
"GameListContextMenuOpenUserBcatDirectoryToolTip": "Öffnet das Verzeichnis, welches den BCAT Cache des Spiels beinhaltet",
"GameListContextMenuManageTitleUpdates": "Verwalten von Spiel Updates",
"GameListContextMenuManageTitleUpdatesToolTip": "Öffnet den Spiel-Update-Manager",
"GameListContextMenuManageDlc": "Verwalten von DLC",
"GameListContextMenuManageDlcToolTip": "Öffnet den DLC-Manager",
"GameListContextMenuOpenModsDirectory": "Mod-Verzeichnis öffnen",
"GameListContextMenuOpenModsDirectoryToolTip": "Öffnet das Verzeichnis, welches Mods für die Spiele beinhaltet",
"GameListContextMenuCacheManagement": "Cache Verwaltung",
"GameListContextMenuCacheManagementPurgePptc": "PPTC als ungültig markieren",
"GameListContextMenuCacheManagementPurgePptcToolTip": "Markiert den PPTC als ungültig, sodass dieser beim nächsten Spielstart neu erstellt wird",
"GameListContextMenuCacheManagementPurgeShaderCache": "Shader Cache löschen",
"GameListContextMenuCacheManagementPurgeShaderCacheToolTip": "Löscht den Shader Cache der Anwendung",
"GameListContextMenuCacheManagementOpenPptcDirectory": "PPTC Verzeichnis öffnen",
"GameListContextMenuCacheManagementOpenPptcDirectoryToolTip": "Öffnet das Verzeichnis, das den PPTC Cache der Anwendung beinhaltet",
"GameListContextMenuCacheManagementOpenShaderCacheDirectory": "Shader Cache Verzeichnis öffnen",
"GameListContextMenuCacheManagementOpenShaderCacheDirectoryToolTip": "Öffnet das Verzeichnis, das den Shader Cache der Anwendung beinhaltet",
"GameListContextMenuExtractData": "Daten extrahieren",
"GameListContextMenuExtractDataExeFS": "ExeFS",
"GameListContextMenuExtractDataExeFSToolTip": "Extrahiert das ExeFS aus der aktuellen Anwendungskonfiguration (einschließlich Updates)",
"GameListContextMenuExtractDataRomFS": "RomFS",
"GameListContextMenuExtractDataRomFSToolTip": "Extrahiert das RomFS aus der aktuellen Anwendungskonfiguration (einschließlich Updates)",
"GameListContextMenuExtractDataLogo": "Logo",
"GameListContextMenuExtractDataLogoToolTip": "Extrahiert das Logo aus der aktuellen Anwendungskonfiguration (einschließlich Updates)",
"StatusBarGamesLoaded": "{0}/{1} Spiele geladen",
"StatusBarSystemVersion": "Systemversion: {0}",
"Settings": "Einstellungen",
"SettingsTabGeneral": "Allgemein",
"SettingsTabGeneralGeneral": "Allgemein",
"SettingsTabGeneralEnableDiscordRichPresence": "Aktiviere Discord Rich Presence",
"SettingsTabGeneralCheckUpdatesOnLaunch": "Beim Start nach Updates suchen",
"SettingsTabGeneralShowConfirmExitDialog": "Zeige den \"Beenden bestätigen\" Dialog",
"SettingsTabGeneralHideCursorOnIdle": "Mauszeiger bei Inaktivität ausblenden",
"SettingsTabGeneralGameDirectories": "Spielverzeichnisse",
"SettingsTabGeneralAdd": "Hinzufügen",
"SettingsTabGeneralRemove": "Entfernen",
"SettingsTabSystem": "System",
"SettingsTabSystemCore": "Kern",
"SettingsTabSystemSystemRegion": "Systemregion:",
"SettingsTabSystemSystemRegionJapan": "Japan",
"SettingsTabSystemSystemRegionUSA": "USA",
"SettingsTabSystemSystemRegionEurope": "Europa",
"SettingsTabSystemSystemRegionAustralia": "Australien",
"SettingsTabSystemSystemRegionChina": "China",
"SettingsTabSystemSystemRegionKorea": "Korea",
"SettingsTabSystemSystemRegionTaiwan": "Taiwan",
"SettingsTabSystemSystemLanguage": "Systemsprache:",
"SettingsTabSystemSystemLanguageJapanese": "Japanisch",
"SettingsTabSystemSystemLanguageAmericanEnglish": "Amerikanisches Englisch",
"SettingsTabSystemSystemLanguageFrench": "Französisch",
"SettingsTabSystemSystemLanguageGerman": "Deutsch",
"SettingsTabSystemSystemLanguageItalian": "Italienisch",
"SettingsTabSystemSystemLanguageSpanish": "Spanisch",
"SettingsTabSystemSystemLanguageChinese": "Chinesisch",
"SettingsTabSystemSystemLanguageKorean": "Koreanisch",
"SettingsTabSystemSystemLanguageDutch": "Niederländisch",
"SettingsTabSystemSystemLanguagePortuguese": "Portugiesisch",
"SettingsTabSystemSystemLanguageRussian": "Russisch",
"SettingsTabSystemSystemLanguageTaiwanese": "Taiwanesisch",
"SettingsTabSystemSystemLanguageBritishEnglish": "Britisches Englisch",
"SettingsTabSystemSystemLanguageCanadianFrench": "Kanadisches Französisch",
"SettingsTabSystemSystemLanguageLatinAmericanSpanish": "Lateinamerikanisches Spanisch",
"SettingsTabSystemSystemLanguageSimplifiedChinese": "Vereinfachtes Chinesisch",
"SettingsTabSystemSystemLanguageTraditionalChinese": "Traditionelles Chinesisch",
"SettingsTabSystemSystemTimeZone": "System Zeitzone:",
"SettingsTabSystemSystemTime": "System Zeit:",
"SettingsTabSystemEnableVsync": "VSync",
"SettingsTabSystemEnablePptc": "PPTC Cache (Profiled Persistent Translation Cache)",
"SettingsTabSystemEnableFsIntegrityChecks": "FS Integritätsprüfung",
"SettingsTabSystemAudioBackend": "Audio-Backend:",
"SettingsTabSystemAudioBackendDummy": "Ohne Funktion",
"SettingsTabSystemAudioBackendOpenAL": "OpenAL",
"SettingsTabSystemAudioBackendSoundIO": "SoundIO",
"SettingsTabSystemAudioBackendSDL2": "SDL2",
"SettingsTabSystemHacks": "Hacks",
"SettingsTabSystemHacksNote": " (Kann Fehler verursachen)",
"SettingsTabSystemExpandDramSize": "Erweitere DRAM Größe auf 6GiB",
"SettingsTabSystemIgnoreMissingServices": "Ignoriere fehlende Dienste",
"SettingsTabGraphics": "Grafik",
"SettingsTabGraphicsAPI": "Grafik-API",
"SettingsTabGraphicsEnableShaderCache": "Shader Cache",
"SettingsTabGraphicsAnisotropicFiltering": "Anisotrope Filterung:",
"SettingsTabGraphicsAnisotropicFilteringAuto": "Auto",
"SettingsTabGraphicsAnisotropicFiltering2x": "2x",
"SettingsTabGraphicsAnisotropicFiltering4x": "4x",
"SettingsTabGraphicsAnisotropicFiltering8x": "8x",
"SettingsTabGraphicsAnisotropicFiltering16x": "16x",
"SettingsTabGraphicsResolutionScale": "Auflösungsskalierung:",
"SettingsTabGraphicsResolutionScaleCustom": "Benutzerdefiniert (nicht empfohlen)",
"SettingsTabGraphicsResolutionScaleNative": "Nativ (720p/1080p)",
"SettingsTabGraphicsResolutionScale2x": "2x (1440p/2160p)",
"SettingsTabGraphicsResolutionScale3x": "3x (2160p/3240p)",
"SettingsTabGraphicsResolutionScale4x": "4x (2880p/4320p)",
"SettingsTabGraphicsAspectRatio": "Bildseitenverhältnis:",
"SettingsTabGraphicsAspectRatio4x3": "4:3",
"SettingsTabGraphicsAspectRatio16x9": "16:9",
"SettingsTabGraphicsAspectRatio16x10": "16:10",
"SettingsTabGraphicsAspectRatio21x9": "21:9",
"SettingsTabGraphicsAspectRatio32x9": "32:9",
"SettingsTabGraphicsAspectRatioStretch": "Dehnen, um sich an das Fenster anzupassen",
"SettingsTabGraphicsDeveloperOptions": "Optionen für Entwickler",
"SettingsTabGraphicsShaderDumpPath": "Grafik-Shader Dump Pfad:",
"SettingsTabLogging": "Logs",
"SettingsTabLoggingLogging": "Logs",
"SettingsTabLoggingEnableLoggingToFile": "Aktiviere Erstellung von Log-Datei",
"SettingsTabLoggingEnableStubLogs": "Aktiviere Stub-Logs",
"SettingsTabLoggingEnableInfoLogs": "Aktiviere Info-Logs",
"SettingsTabLoggingEnableWarningLogs": "Aktiviere Warn-Logs",
"SettingsTabLoggingEnableErrorLogs": "Aktiviere Fehler-Logs",
"SettingsTabLoggingEnableTraceLogs": "Aktiviere Trace-Logs",
"SettingsTabLoggingEnableGuestLogs": "Aktiviere Gast-Logs",
"SettingsTabLoggingEnableFsAccessLogs": "Aktiviere Fs Zugriff-Logs",
"SettingsTabLoggingFsGlobalAccessLogMode": "Fs Globaler Zugriff-Log-Modus:",
"SettingsTabLoggingDeveloperOptions": "Entwickleroptionen (WARNUNG: Beeinträchtigt die Leistung)",
"SettingsTabLoggingGraphicsBackendLogLevel": "Graphics Backend Log Level:",
"SettingsTabLoggingGraphicsBackendLogLevelNone": "Keine",
"SettingsTabLoggingGraphicsBackendLogLevelError": "Fehler",
"SettingsTabLoggingGraphicsBackendLogLevelPerformance": "Verlangsamungen",
"SettingsTabLoggingGraphicsBackendLogLevelAll": "Alle",
"SettingsTabLoggingEnableDebugLogs": "Aktiviere Debug-Log",
"SettingsTabInput": "Eingabe",
"SettingsTabInputEnableDockedMode": "Docked Modus",
"SettingsTabInputDirectKeyboardAccess": "Direkter Tastaturzugriff",
"SettingsButtonSave": "Speichern",
"SettingsButtonClose": "Schließen",
"SettingsButtonOk": "OK",
"SettingsButtonCancel": "Abbrechen",
"SettingsButtonApply": "Übernehmen",
"ControllerSettingsPlayer": "Spieler",
"ControllerSettingsPlayer1": "Spieler 1",
"ControllerSettingsPlayer2": "Spieler 2",
"ControllerSettingsPlayer3": "Spieler 3",
"ControllerSettingsPlayer4": "Spieler 4",
"ControllerSettingsPlayer5": "Spieler 5",
"ControllerSettingsPlayer6": "Spieler 6",
"ControllerSettingsPlayer7": "Spieler 7",
"ControllerSettingsPlayer8": "Spieler 8",
"ControllerSettingsHandheld": "Handheld",
"ControllerSettingsInputDevice": "Eingabegerät",
"ControllerSettingsRefresh": "Aktualisieren",
"ControllerSettingsDeviceDisabled": "Deaktiviert",
"ControllerSettingsControllerType": "Controller Typ",
"ControllerSettingsControllerTypeHandheld": "Handheld",
"ControllerSettingsControllerTypeProController": "Pro Controller",
"ControllerSettingsControllerTypeJoyConPair": "Joy-Con Paar",
"ControllerSettingsControllerTypeJoyConLeft": "Joy-Con Links",
"ControllerSettingsControllerTypeJoyConRight": "Joy-Con Rechts",
"ControllerSettingsProfile": "Profil",
"ControllerSettingsProfileDefault": "Standard",
"ControllerSettingsLoad": "Laden",
"ControllerSettingsAdd": "Hinzufügen",
"ControllerSettingsRemove": "Entfernen",
"ControllerSettingsButtons": "Aktionstasten",
"ControllerSettingsButtonA": "A",
"ControllerSettingsButtonB": "B",
"ControllerSettingsButtonX": "X",
"ControllerSettingsButtonY": "Y",
"ControllerSettingsButtonPlus": "+",
"ControllerSettingsButtonMinus": "-",
"ControllerSettingsDPad": "Steuerkreuz",
"ControllerSettingsDPadUp": "Hoch",
"ControllerSettingsDPadDown": "Runter",
"ControllerSettingsDPadLeft": "Links",
"ControllerSettingsDPadRight": "Rechts",
"ControllerSettingsLStick": "Linker Analogstick",
"ControllerSettingsLStickButton": "L3",
"ControllerSettingsLStickUp": "Hoch",
"ControllerSettingsLStickDown": "Runter",
"ControllerSettingsLStickLeft": "Links",
"ControllerSettingsLStickRight": "Rechts",
"ControllerSettingsLStickStick": "Analogstick",
"ControllerSettingsLStickInvertXAxis": "X-Achse invertieren",
"ControllerSettingsLStickInvertYAxis": "Y-Achse invertieren",
"ControllerSettingsLStickDeadzone": "Deadzone:",
"ControllerSettingsRStick": "Rechter Analogstick",
"ControllerSettingsRStickButton": "R3",
"ControllerSettingsRStickUp": "Hoch",
"ControllerSettingsRStickDown": "Runter",
"ControllerSettingsRStickLeft": "Links",
"ControllerSettingsRStickRight": "Rechts",
"ControllerSettingsRStickStick": "Analogstick",
"ControllerSettingsRStickInvertXAxis": "X-Achse invertieren",
"ControllerSettingsRStickInvertYAxis": "Y-Achse invertieren",
"ControllerSettingsRStickDeadzone": "Deadzone:",
"ControllerSettingsTriggersLeft": "Linker Trigger",
"ControllerSettingsTriggersRight": "Rechter Trigger",
"ControllerSettingsTriggersButtonsLeft": "Linke Schultertaste",
"ControllerSettingsTriggersButtonsRight": "Rechte Schultertaste",
"ControllerSettingsTriggers": "Trigger",
"ControllerSettingsTriggerL": "L",
"ControllerSettingsTriggerR": "R",
"ControllerSettingsTriggerZL": "ZL",
"ControllerSettingsTriggerZR": "ZR",
"ControllerSettingsLeftSL": "SL",
"ControllerSettingsLeftSR": "SR",
"ControllerSettingsRightSL": "SL",
"ControllerSettingsRightSR": "SR",
"ControllerSettingsExtraButtonsLeft": "Linke Aktionstasten",
"ControllerSettingsExtraButtonsRight": "Rechte Aktionstasten",
"ControllerSettingsMisc": "Verschiedenes",
"ControllerSettingsTriggerThreshold": "Empfindlichkeit:",
"ControllerSettingsMotion": "Bewegung",
"ControllerSettingsMotionUseCemuhookCompatibleMotion": "CemuHook kompatible Bewegungssteuerung",
"ControllerSettingsMotionControllerSlot": "Kontroller Slot:",
"ControllerSettingsMotionMirrorInput": "Spiegele Eingabe",
"ControllerSettingsMotionRightJoyConSlot": "Rechter Joy-Con Slot:",
"ControllerSettingsMotionServerHost": "Server Host:",
"ControllerSettingsMotionGyroSensitivity": "Gyro Empfindlichkeit:",
"ControllerSettingsMotionGyroDeadzone": "Gyro Deadzone:",
"ControllerSettingsSave": "Speichern",
"ControllerSettingsClose": "Schließen",
"UserProfilesSelectedUserProfile": "Ausgewähltes Profil:",
"UserProfilesSaveProfileName": "Profilname speichern",
"UserProfilesChangeProfileImage": "Profilbild ändern",
"UserProfilesAvailableUserProfiles": "Verfügbare Profile:",
"UserProfilesAddNewProfile": "Neues Profil",
"UserProfilesDeleteSelectedProfile": "Profil löschen",
"UserProfilesClose": "Schließen",
"ProfileImageSelectionTitle": "Auswahl des Profilbildes",
"ProfileImageSelectionHeader": "Wähle ein Profilbild aus",
"ProfileImageSelectionNote": "Es kann ein eigenes Profilbild importiert werden oder ein Avatar aus der System-Firmware",
"ProfileImageSelectionImportImage": "Bilddatei importieren",
"ProfileImageSelectionSelectAvatar": "Firmware Avatar auswählen",
"InputDialogTitle": "Eingabe Dialog",
"InputDialogOk": "OK",
"InputDialogCancel": "Abbrechen",
"InputDialogAddNewProfileTitle": "Wähle den Profilnamen",
"InputDialogAddNewProfileHeader": "Bitte gebe einen Profilnamen ein",
"InputDialogAddNewProfileSubtext": "(Maximale Länge: {0})",
"AvatarChoose": "Bestätigen",
"AvatarSetBackgroundColor": "Hintergrundfarbe einstellen",
"AvatarClose": "Schließen",
"ControllerSettingsLoadProfileToolTip": "Lädt ein Profil",
"ControllerSettingsAddProfileToolTip": "Fügt ein Profil hinzu",
"ControllerSettingsRemoveProfileToolTip": "Entfernt ein Profil",
"ControllerSettingsSaveProfileToolTip": "Speichert ein Profil",
"MenuBarFileToolsTakeScreenshot": "Screenshot aufnehmen",
"MenuBarFileToolsHideUi": "Hide UI",
"GameListContextMenuToggleFavorite": "Als Favoriten hinzufügen/entfernen",
"GameListContextMenuToggleFavoriteToolTip": "Aktiviert den Favoriten-Status des Spiels",
"SettingsTabGeneralTheme": "Design",
"SettingsTabGeneralThemeCustomTheme": "Pfad für das benutzerdefinierte Design",
"SettingsTabGeneralThemeBaseStyle": "Farbschema",
"SettingsTabGeneralThemeBaseStyleDark": "Dunkel",
"SettingsTabGeneralThemeBaseStyleLight": "Hell",
"SettingsTabGeneralThemeEnableCustomTheme": "Design für die Emulator-Benutzeroberfläche",
"ButtonBrowse": "Durchsuchen",
"ControllerSettingsConfigureGeneral": "Konfigurieren",
"ControllerSettingsRumble": "Vibration",
"ControllerSettingsRumbleStrongMultiplier": "Starker Vibrations-Multiplikator",
"ControllerSettingsRumbleWeakMultiplier": "Schwacher Vibrations-Multiplikator",
"DialogMessageSaveNotAvailableMessage": "Es existieren keine Speicherdaten für {0} [{1:x16}]",
"DialogMessageSaveNotAvailableCreateSaveMessage": "Soll Ryujinx Speicherdaten für dieses Spiel erstellen?",
"DialogConfirmationTitle": "Ryujinx - Bestätigung",
"DialogUpdaterTitle": "Ryujinx - Updater",
"DialogErrorTitle": "Ryujinx - Fehler",
"DialogWarningTitle": "Ryujinx - Warnung",
"DialogExitTitle": "Ryujinx - Beenden",
"DialogErrorMessage": "Ein Fehler ist aufgetreten",
"DialogExitMessage": "Ryujinx wirklich schließen?",
"DialogExitSubMessage": "Alle nicht gespeicherten Daten gehen verloren!",
"DialogMessageCreateSaveErrorMessage": "Es ist ein Fehler bei der Erstellung der angegebenen Speicherdaten aufgetreten: {0}",
"DialogMessageFindSaveErrorMessage": "Es ist ein Fehler beim Auffinden der angegebenen Speicherdaten aufgetreten: {0}",
"FolderDialogExtractTitle": "Wähle den Ordner, in welchen die Dateien entpackt werden sollen",
"DialogNcaExtractionMessage": "Extrahiert {0} abschnitt von {1}...",
"DialogNcaExtractionTitle": "Ryujinx - NCA-Abschnitt-Extraktor",
"DialogNcaExtractionMainNcaNotFoundErrorMessage": "Extraktion fehlgeschlagen. Der Hauptheader der NCA war in der ausgewählten Datei nicht vorhanden.",
"DialogNcaExtractionCheckLogErrorMessage": "Extraktion fehlgeschlagen. Überprüfe die Logs für weitere Informationen.",
"DialogNcaExtractionSuccessMessage": "Extraktion erfolgreich abgeschlossen.",
"DialogUpdaterConvertFailedMessage": "Die Konvertierung der aktuellen Ryujinx Version ist fehlgeschlagen.",
"DialogUpdaterCancelUpdateMessage": "Download wird abgebrochen!",
"DialogUpdaterAlreadyOnLatestVersionMessage": "Es wird bereits die aktuellste Version von Ryujinx benutzt",
"DialogUpdaterFailedToGetVersionMessage": "An error has occurred when trying to get release information from GitHub Release. This can be caused if a new release is being compiled by GitHub Actions. Try again in a few minutes.",
"DialogUpdaterConvertFailedGithubMessage": "Failed to convert the received Ryujinx version from Github Release.",
"DialogUpdaterDownloadingMessage": "Update wird Heruntergeladen...",
"DialogUpdaterExtractionMessage": "Update wird entpackt...",
"DialogUpdaterRenamingMessage": "Update wird umbenannt...",
"DialogUpdaterAddingFilesMessage": "Update wird hinzugefügt...",
"DialogUpdaterCompleteMessage": "Update abgeschlossen!",
"DialogUpdaterRestartMessage": "Ryujinx jetzt neu starten?",
"DialogUpdaterArchNotSupportedMessage": "Eine nicht unterstützte Systemarchitektur wird benutzt!",
"DialogUpdaterArchNotSupportedSubMessage": "Nur x64 Systeme werden unterstützt!",
"DialogUpdaterNoInternetMessage": "Es besteht keine Verbindung mit dem Internet!",
"DialogUpdaterNoInternetSubMessage": "Bitte vergewissern, dass eine funktionierende Internetverbindung existiert!",
"DialogUpdaterDirtyBuildMessage": "Inoffizielle Versionen von Ryujinx können nicht aktualisiert werden",
"DialogUpdaterDirtyBuildSubMessage": "Lade Ryujinx bitte von hier herunter, um eine unterstützte Version zu erhalten: https://ryujinx.org/",
"DialogRestartRequiredMessage": "Neustart erforderlich",
"DialogThemeRestartMessage": "Das Design wurde gespeichert. Ein Neustart ist erforderlich, um das Design anzuwenden.",
"DialogThemeRestartSubMessage": "Jetzt neu starten?",
"DialogFirmwareInstallEmbeddedMessage": "Die in diesem Spiel enthaltene Firmware installieren? (Firmware {0})",
"DialogFirmwareInstallEmbeddedSuccessMessage": "Es wurde keine installierte Firmware gefunden, aber Ryujinx konnte die Firmware {0} aus dem bereitgestellten Spiel installieren.\nRyujinx wird nun gestartet.",
"DialogFirmwareNoFirmwareInstalledMessage": "Keine Firmware installiert",
"DialogFirmwareInstalledMessage": "Firmware {0} wurde installiert",
"DialogOpenSettingsWindowLabel": "Fenster-Einstellungen öffnen",
"DialogControllerAppletTitle": "Controller-Applet",
"DialogMessageDialogErrorExceptionMessage": "Fehler bei der Anzeige des Meldungs-Dialogs: {0}",
"DialogSoftwareKeyboardErrorExceptionMessage": "Fehler bei der Anzeige der Software-Tastatur: {0}",
"DialogErrorAppletErrorExceptionMessage": "Fehler beim Anzeigen des ErrorApplet-Dialogs: {0}",
"DialogUserErrorDialogMessage": "{0}: {1}",
"DialogUserErrorDialogInfoMessage": "\nWeitere Informationen zur Behebung dieses Fehlers können in unserem Setup-Guide gefunden werden.",
"DialogUserErrorDialogTitle": "Ryujinx Fehler ({0})",
"DialogAmiiboApiTitle": "Amiibo API",
"DialogAmiiboApiFailFetchMessage": "Beim Abrufen von Informationen aus der API ist ein Fehler aufgetreten.",
"DialogAmiiboApiConnectErrorMessage": "Verbindung zum Amiibo API Server kann nicht hergestellt werden. Der Dienst ist möglicherweise nicht verfügbar oder es existiert keine Internetverbindung.",
"DialogProfileInvalidProfileErrorMessage": "Das Profil {0} ist mit dem aktuellen Eingabekonfigurationssystem nicht kompatibel.",
"DialogProfileDefaultProfileOverwriteErrorMessage": "Das Standardprofil kann nicht überschrieben werden",
"DialogProfileDeleteProfileTitle": "Profil löschen",
"DialogProfileDeleteProfileMessage": "Diese Aktion kann nicht rückgängig gemacht werden. Wirklich fortfahren?",
"DialogWarning": "Warnung",
"DialogPPTCDeletionMessage": "Du bist dabei den PPTC für das folgende Spiel als ungültig zu markieren:\n\n{0}\n\nWirklich fortfahren?",
"DialogPPTCDeletionErrorMessage": "Fehler bei der Löschung des PPTC Caches bei {0}: {1}",
"DialogShaderDeletionMessage": "Du bist dabei, den Shader Cache zu löschen für :\n\n{0}\n\nWirklich fortfahren?",
"DialogShaderDeletionErrorMessage": "Es ist ein Fehler bei der Löschung des Shader Caches bei {0}: {1} aufgetreten",
"DialogRyujinxErrorMessage": "Ein Fehler ist aufgetreten",
"DialogInvalidTitleIdErrorMessage": "UI Fehler: Das ausgewählte Spiel hat keine gültige Titel-ID",
"DialogFirmwareInstallerFirmwareNotFoundErrorMessage": "Es wurde keine gültige System-Firmware gefunden in {0}.",
"DialogFirmwareInstallerFirmwareInstallTitle": "Installiere Firmware {0}",
"DialogFirmwareInstallerFirmwareInstallMessage": "Systemversion {0} wird jetzt installiert.",
"DialogFirmwareInstallerFirmwareInstallSubMessage": "\n\nDies wird die aktuelle Systemversion {0} ersetzen.",
"DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\nMöchtest du fortfahren?",
"DialogFirmwareInstallerFirmwareInstallWaitMessage": "Firmware wird installiert...",
"DialogFirmwareInstallerFirmwareInstallSuccessMessage": "Systemversion {0} wurde erfolgreich installiert.",
"DialogUserProfileDeletionWarningMessage": "Es können keine anderen Profile geöffnet werden, wenn das ausgewählte Profil gelöscht wird.",
"DialogUserProfileDeletionConfirmMessage": "Möchtest du das ausgewählte Profil löschen?",
"DialogControllerSettingsModifiedConfirmMessage": "Die aktuellen Controller-Einstellungen wurden aktualisiert.",
"DialogControllerSettingsModifiedConfirmSubMessage": "Controller-Einstellungen speichern?",
"DialogDlcLoadNcaErrorMessage": "{0}. Fehlerhafte Datei: {1}",
"DialogDlcNoDlcErrorMessage": "Die angegebene Datei enthält keinen DLC für den ausgewählten Titel!",
"DialogPerformanceCheckLoggingEnabledMessage": "Es wurde die Debug Protokollierung aktiviert",
"DialogPerformanceCheckLoggingEnabledConfirmMessage": "Um eine optimale Leistung zu erzielen, wird empfohlen, die Debug Protokollierung zu deaktivieren. Debug Protokollierung jetzt deaktivieren?",
"DialogPerformanceCheckShaderDumpEnabledMessage": "Es wurde das Shader Dumping aktiviert, das nur von Entwicklern verwendet werden soll.",
"DialogPerformanceCheckShaderDumpEnabledConfirmMessage": "Für eine optimale Leistung wird empfohlen, das Shader Dumping zu deaktivieren. Shader Dumping jetzt deaktivieren?",
"DialogLoadAppGameAlreadyLoadedMessage": "Es wurde bereits ein Spiel gestartet",
"DialogLoadAppGameAlreadyLoadedSubMessage": "Bitte beende die Emulation oder schließe den Emulator, vor dem Starten eines neuen Spiels",
"DialogUpdateAddUpdateErrorMessage": "Die angegebene Datei enthält keine Updates für den ausgewählten Titel!",
"DialogSettingsBackendThreadingWarningTitle": "Warnung - Render Threading",
"DialogSettingsBackendThreadingWarningMessage": "Ryujinx muss muss neu gestartet werden, damit die Änderungen wirksam werden. Abhängig von dem Betriebssystem muss möglicherweise das Multithreading des Treibers manuell deaktiviert werden, wenn Ryujinx verwendet wird.",
"SettingsTabGraphicsFeaturesOptions": "Erweiterungen",
"SettingsTabGraphicsBackendMultithreading": "Grafik-Backend Multithreading:",
"CommonAuto": "Auto",
"CommonOff": "Aus",
"CommonOn": "An",
"InputDialogYes": "Ja",
"InputDialogNo": "Nein",
"DialogProfileInvalidProfileNameErrorMessage": "Der Dateiname enthält ungültige Zeichen. Bitte erneut versuchen.",
"MenuBarOptionsPauseEmulation": "Pause",
"MenuBarOptionsResumeEmulation": "Fortsetzen",
"AboutUrlTooltipMessage": "Klicke hier, um die Ryujinx Website im Standardbrowser zu öffnen.",
"AboutDisclaimerMessage": "Ryujinx ist in keinster Weise weder mit Nintendo™, \nnoch mit deren Partnern verbunden.",
"AboutAmiiboDisclaimerMessage": "AmiiboAPI (www.amiiboapi.com) wird in unserer Amiibo \nEmulation benutzt.",
"AboutPatreonUrlTooltipMessage": "Klicke hier, um die Ryujinx Patreon Seite im Standardbrowser zu öffnen.",
"AboutGithubUrlTooltipMessage": "Klicke hier, um die Ryujinx GitHub Seite im Standardbrowser zu öffnen.",
"AboutDiscordUrlTooltipMessage": "Klicke hier, um eine Einladung zum Ryujinx Discord Server im Standardbrowser zu öffnen.",
"AboutTwitterUrlTooltipMessage": "Klicke hier, um die Ryujinx Twitter Seite im Standardbrowser zu öffnen.",
"AboutRyujinxAboutTitle": "Über:",
"AboutRyujinxAboutContent": "Ryujinx ist ein Nintendo Switch™ Emulator.\nBitte unterstütze uns auf Patreon.\nAuf Twitter oder Discord erfährst du alle Neuigkeiten.\nEntwickler, die an einer Mitarbeit interessiert sind, können auf GitHub oder Discord mehr erfahren.",
"AboutRyujinxMaintainersTitle": "Entwickelt von:",
"AboutRyujinxMaintainersContentTooltipMessage": "Klicke hier, um die Liste der Mitwirkenden im Standardbrowser zu öffnen.",
"AboutRyujinxSupprtersTitle": "Unterstützt auf Patreon von:",
"AmiiboSeriesLabel": "Amiibo Serie",
"AmiiboCharacterLabel": "Charakter",
"AmiiboScanButtonLabel": "Einscannen",
"AmiiboOptionsShowAllLabel": "Zeige alle Amiibos",
"AmiiboOptionsUsRandomTagLabel": "Hack: Benutze zufällige Tag-UUID",
"DlcManagerTableHeadingEnabledLabel": "Aktiviert",
"DlcManagerTableHeadingTitleIdLabel": "Title-ID",
"DlcManagerTableHeadingContainerPathLabel": "Container-Pfad",
"DlcManagerTableHeadingFullPathLabel": "Vollständiger-Pfad",
"DlcManagerRemoveAllButton": "Entferne alle",
"DlcManagerEnableAllButton": "Alle aktivieren",
"DlcManagerDisableAllButton": "Alle deaktivieren",
"MenuBarOptionsChangeLanguage": "Sprache ändern",
"CommonSort": "Sortieren",
"CommonShowNames": "Spiel-Namen anzeigen",
"CommonFavorite": "Favoriten",
"OrderAscending": "Aufsteigend",
"OrderDescending": "Absteigend",
"SettingsTabGraphicsFeatures": "Erweiterungen",
"ErrorWindowTitle": "Fehler-Fenster",
"ToggleDiscordTooltip": "Zeige momentanes Spiel auf Discord",
"AddGameDirBoxTooltip": "Gibt das Spielverzeichnis an, das der Liste hinzuzufügt wird",
"AddGameDirTooltip": "Fügt ein neues Spielverzeichnis hinzu",
"RemoveGameDirTooltip": "Entfernt das ausgewähltes Spielverzeichnis",
"CustomThemeCheckTooltip": "Verwende ein eigenes Design für die Emulator-Benutzeroberfläche",
"CustomThemePathTooltip": "Gibt den Pfad zum Design für die Emulator-Benutzeroberfläche an",
"CustomThemeBrowseTooltip": "Ermöglicht die Suche nach einem benutzerdefinierten Design für die Emulator-Benutzeroberfläche",
"DockModeToggleTooltip": "Im gedockten Modus verhält sich das emulierte System wie eine Nintendo Switch im TV Modus. Dies verbessert die grafische Qualität der meisten Spiele. Umgekehrt führt die Deaktivierung dazu, dass sich das emulierte System wie eine Nintendo Switch im Handheld Modus verhält, was die Grafikqualität beeinträchtigt.\n\nKonfiguriere das Eingabegerät für Spieler 1, um im Docked Modus zu spielen; konfiguriere das Controllerprofil via der Handheld Option, wenn geplant wird den Handheld Modus zu nutzen.\n\nIm Zweifelsfall AN lassen.",
"DirectKeyboardTooltip": "Aktiviert/Deaktiviert den \"Direkter Tastaturzugriff (HID) Unterstützung\" (Ermöglicht die Benutzung der Tastaur als Eingabegerät in Spielen)",
"DirectMouseTooltip": "Aktiviert/Deaktiviert den \"Direkten Mauszugriff (HID) Unterstützung\" (Ermöglicht die Benutzung der Maus als Eingabegerät in Spielen)",
"RegionTooltip": "Ändert die Systemregion",
"LanguageTooltip": "Ändert die Systemsprache",
"TimezoneTooltip": "Ändert die Systemzeitzone",
"TimeTooltip": "Ändert die Systemzeit",
"VSyncToggleTooltip": "Vertikale Synchronisierung der emulierten Konsole. Diese Option ist ein Frame-Limiter für die meisten Spiele; die Deaktivierung kann dazu führen, dass Spiele mit höherer Geschwindigkeit laufen, Ladebildschirme länger benötigen oder hängen bleiben.\n\nKann beim Spielen mit einem frei wählbaren Hotkey ein- und ausgeschaltet werden.\n\nIm Zweifelsfall AN lassen.",
"PptcToggleTooltip": "Speichert übersetzte JIT-Funktionen, sodass jene nicht jedes Mal übersetzt werden müssen, wenn das Spiel geladen wird.\n\nVerringert Stottern und die Zeit beim zweiten und den darauffolgenden Startvorgängen eines Spiels erheblich.\n\nIm Zweifelsfall AN lassen.",
"FsIntegrityToggleTooltip": "Prüft beim Startvorgang auf beschädigte Dateien und zeigt bei beschädigten Dateien einen Hash-Fehler (Hash Error) im Log an.\n\nDiese Einstellung hat keinen Einfluss auf die Leistung und hilft bei der Fehlersuche.\n\nIm Zweifelsfall AN lassen.",
"AudioBackendTooltip": "Ändert das Backend, das zum Rendern von Audio verwendet wird.\n\nSDL2 ist das bevorzugte Audio-Backend, OpenAL und SoundIO sind als Alternativen vorhanden. Dummy wird keinen Audio-Output haben.\n\nIm Zweifelsfall SDL2 auswählen.",
"MemoryManagerTooltip": "Ändert wie der Gastspeicher abgebildet wird und wie auf ihn zugegriffen wird. Beinflusst die Leistung der emulierten CPU erheblich.\n\nIm Zweifelsfall Host ungeprüft auswählen.",
"MemoryManagerSoftwareTooltip": "Verwendung einer Software-Seitentabelle für die Adressumsetzung. Höchste Genauigkeit, aber langsamste Leistung.",
"MemoryManagerHostTooltip": "Direkte Zuordnung von Speicher im Host-Adressraum. Viel schnellere JIT-Kompilierung und Ausführung.",
"MemoryManagerUnsafeTooltip": "Direkte Zuordnung des Speichers, aber keine Maskierung der Adresse innerhalb des Gastadressraums vor dem Zugriff. Schneller, aber auf Kosten der Sicherheit. Die Gastanwendung kann von überall in Ryujinx auf den Speicher zugreifen, daher sollte in diesem Modus nur Programme ausgeführt werden denen vertraut wird.",
"DRamTooltip": "Erhöht den Arbeitsspeicher des emulierten Systems von 4 GiB auf 6 GiB.\n\nDies ist nur für Texturenpakete mit höherer Auflösung oder Mods mit 4K-Auflösung nützlich. Diese Option verbessert NICHT die Leistung.\n\nIm Zweifelsfall AUS lassen.",
"IgnoreMissingServicesTooltip": "Durch diese Option werden nicht implementierte Dienste der Switch-Firmware ignoriert. Dies kann dabei helfen, Abstürze beim Starten bestimmter Spiele zu umgehen.\n\nIm Zweifelsfall AUS lassen.",
"GraphicsBackendThreadingTooltip": "Führt Grafik-Backend Befehle auf einem zweiten Thread aus.\n\nDies beschleunigt die Shader-Kompilierung, reduziert Stottern und verbessert die Leistung auf GPU-Treibern ohne eigene Multithreading-Unterstützung. Geringfügig bessere Leistung bei Treibern mit Multithreading.\n\nIm Zweifelsfall auf AUTO stellen.",
"GalThreadingTooltip": "Führt Grafik-Backend Befehle auf einem zweiten Thread aus.\n\nDies Beschleunigt die Shader-Kompilierung, reduziert Stottern und verbessert die Leistung auf GPU-Treibern ohne eigene Multithreading-Unterstützung. Geringfügig bessere Leistung bei Treibern mit Multithreading.\n\nIm Zweifelsfall auf auf AUTO stellen.",
"ShaderCacheToggleTooltip": "Speichert einen persistenten Shader Cache, der das Stottern bei nachfolgenden Durchläufen reduziert.\n\nIm Zweifelsfall AN lassen.",
"ResolutionScaleTooltip": "Wendet die Auflösungsskalierung auf anwendbare Render Ziele",
"ResolutionScaleEntryTooltip": "Fließkomma Auflösungsskalierung, wie 1,5.\n Bei nicht ganzzahligen Werten ist die Wahrscheinlichkeit größer, dass Probleme entstehen, die auch zum Absturz führen können.",
"AnisotropyTooltip": "Stufe der Anisotropen Filterung (Auf Auto setzen, um den vom Spiel geforderten Wert zu verwenden)",
"AspectRatioTooltip": "Auf das Renderer-Fenster angewandtes Seitenverhältnis.",
"ShaderDumpPathTooltip": "Grafik-Shader-Dump-Pfad",
"FileLogTooltip": "Speichert die Konsolenausgabe in einer Log-Datei auf der Festplatte. Hat keinen Einfluss auf die Leistung.",
"StubLogTooltip": "Ausgabe von Stub-Logs in der Konsole. Hat keinen Einfluss auf die Leistung.",
"InfoLogTooltip": "Ausgabe von Info-Logs in der Konsole. Hat keinen Einfluss auf die Leistung.",
"WarnLogTooltip": "Ausgabe von Warn-Logs in der Konsole. Hat keinen Einfluss auf die Leistung.",
"ErrorLogTooltip": "Ausgabe von Fehler-Logs in der Konsole. Hat keinen Einfluss auf die Leistung.",
"TraceLogTooltip": "Ausgabe von Trace-Log in der Konsole. Hat keinen Einfluss auf die Leistung.",
"GuestLogTooltip": "Ausgabe von Gast-Logs in der Konsole. Hat keinen Einfluss auf die Leistung.",
"FileAccessLogTooltip": "Ausgabe von FS-Zugriff-Logs in der Konsole.",
"FSAccessLogModeTooltip": "Aktiviert die Ausgabe des FS-Zugriff-Logs in der Konsole. Mögliche Modi sind 0-3",
"DeveloperOptionTooltip": "Mit Vorsicht verwenden",
"OpenGlLogLevel": "Erfordert die Aktivierung der entsprechenden Log-Level",
"DebugLogTooltip": "Ausgabe von Debug-Logs in der Konsole.\n\nVerwende diese Option nur auf ausdrückliche Anweisung von Ryujinx Entwicklern, da sie das Lesen der Protokolle erschwert und die Leistung des Emulators verschlechtert.",
"LoadApplicationFileTooltip": "Öffnet die Dateiauswahl um Datei zu laden, welche mit der Switch kompatibel ist",
"LoadApplicationFolderTooltip": "Öffnet die Dateiauswahl um ein Spiel zu laden, welches mit der Switch kompatibel ist",
"OpenRyujinxFolderTooltip": "Öffnet den Ordner, der das Ryujinx Dateisystem enthält",
"OpenRyujinxLogsTooltip": "Öffnet den Ordner, in welchem die Logs gespeichert werden",
"ExitTooltip": "Beendet Ryujinx",
"OpenSettingsTooltip": "Öffnet das Einstellungsfenster",
"OpenProfileManagerTooltip": "Öffnet das Profilverwaltungsfenster",
"StopEmulationTooltip": "Beendet die Emulation des derzeitigen Spiels und kehrt zu der Spielauswahl zurück",
"CheckUpdatesTooltip": "Sucht nach Updates für Ryujinx",
"OpenAboutTooltip": "Öffnet das 'Über Ryujinx'-Fenster",
"GridSize": "Rastergröße",
"GridSizeTooltip": "Ändert die Größe der Rasterelemente",
"SettingsTabSystemSystemLanguageBrazilianPortuguese": "Brasilianisches Portugiesisch",
"AboutRyujinxContributorsButtonHeader": "Alle Mitwirkenden anzeigen",
"SettingsTabSystemAudioVolume": "Lautstärke: ",
"AudioVolumeTooltip": "Ändert die Lautstärke",
"SettingsTabSystemEnableInternetAccess": "Gast-Internet-Zugang/LAN Modus",
"EnableInternetAccessTooltip": "Erlaubt es der emulierten Anwendung sich mit dem Internet zu verbinden.\n\nSpiele die den LAN-Modus unterstützen, ermöglichen es Ryujinx sich sowohl mit anderen Ryujinx-Systemen, als auch mit offiziellen Nintendo Switch Konsolen zu verbinden. Allerdings nur, wenn diese Option aktiviert ist und die Systeme mit demselben lokalen Netzwerk verbunden sind.\n\nDies erlaubt KEINE Verbindung zu Nintendo-Servern. Kann bei bestimmten Spielen die versuchen sich mit dem Internet zu verbinden zum Absturz führen.\n\nIm Zweifelsfall AUS lassen",
"GameListContextMenuManageCheatToolTip": "Öffnet den Cheat-Manager",
"GameListContextMenuManageCheat": "Cheats verwalten",
"ControllerSettingsStickRange": "Bereich:",
"DialogStopEmulationTitle": "Ryujinx - Beende Emulation",
"DialogStopEmulationMessage": "Emulation wirklich beenden?",
"SettingsTabCpu": "CPU",
"SettingsTabAudio": "Audio",
"SettingsTabNetwork": "Netzwerk",
"SettingsTabNetworkConnection": "Netwerkverbindung",
"SettingsTabCpuCache": "CPU-Cache",
"SettingsTabCpuMemory": "CPU-Speicher",
"DialogUpdaterFlatpakNotSupportedMessage": "Bitte aktualisiere Ryujinx mit FlatHub",
"UpdaterDisabledWarningTitle": "Updater deaktiviert!",
"GameListContextMenuOpenSdModsDirectory": "Atmosphere-Mod-Verzeichnis öffnen",
"GameListContextMenuOpenSdModsDirectoryToolTip": "Öffnet das alternative SD-Karten-Atmosphere-Verzeichnis, das die Mods der Anwendung enthält. Dieser Ordner ist nützlich für Mods, die für einen gemoddete Switch erstellt worden sind.",
"ControllerSettingsRotate90": "Um 90° rotieren",
"IconSize": "Cover Größe",
"IconSizeTooltip": "Ändert die Größe der Spiel-Cover",
"MenuBarOptionsShowConsole": "Zeige Konsole",
"ShaderCachePurgeError": "Es ist ein Fehler beim löschen des Shader Caches aufgetreten bei {0}: {1}",
"UserErrorNoKeys": "Keys nicht gefunden",
"UserErrorNoFirmware": "Firmware nicht gefunden",
"UserErrorFirmwareParsingFailed": "Firmware-Analysierung-Fehler",
"UserErrorApplicationNotFound": "Anwendung nicht gefunden",
"UserErrorUnknown": "Unbekannter Fehler",
"UserErrorUndefined": "Undefinierter Fehler",
"UserErrorNoKeysDescription": "Ryujinx konnte deine 'prod.keys' Datei nicht finden",
"UserErrorNoFirmwareDescription": "Ryujinx konnte keine installierte Firmware finden!",
"UserErrorFirmwareParsingFailedDescription": "Ryujinx konnte die zu verfügung gestellte Firmware nicht analysieren. Ein möglicher Grund dafür sind veraltete keys.",
"UserErrorApplicationNotFoundDescription": "Ryujinx konnte keine valide Anwendung an dem gegeben Pfad finden.",
"UserErrorUnknownDescription": "Ein unbekannter Fehler ist aufgetreten!",
"UserErrorUndefinedDescription": "Ein undefinierter Fehler ist aufgetreten! Dies sollte nicht passieren. Bitte kontaktiere einen Entwickler!",
"OpenSetupGuideMessage": "Öffne den 'Setup Guide'",
"NoUpdate": "Kein Update",
"TitleUpdateVersionLabel": "Version {0} - {1}",
"RyujinxInfo": "Ryujinx - Info",
"RyujinxConfirm": "Ryujinx - Bestätigung",
"FileDialogAllTypes": "Alle Typen",
"Never": "Niemals",
"SwkbdMinCharacters": "Muss mindestens {0} Zeichen lang sein",
"SwkbdMinRangeCharacters": "Muss {0}-{1} Zeichen lang sein",
"SoftwareKeyboard": "Software-Tastatur",
"DialogControllerAppletMessagePlayerRange": "Die Anwendung benötigt {0} Spieler mit:\n\nTYPEN: {1}\n\nSPIELER: {2}\n\n{3}Bitte öffne die Einstellungen und rekonfiguriere die Controller Einstellungen oder drücke auf schließen.",
"DialogControllerAppletMessage": "Die Anwendung benötigt genau {0} Speieler mit:\n\nTYPEN: {1}\n\nSPIELER: {2}\n\n{3}Bitte öffne die Einstellungen und rekonfiguriere die Controller Einstellungen oder drücke auf schließen.",
"DialogControllerAppletDockModeSet": "Der 'Docked Modus' ist ausgewählt. Handheld ist ebenfalls ungültig.\n\n",
"UpdaterRenaming": "Alte Dateien umbenennen...",
"UpdaterRenameFailed": "Der Updater konnte die folgende Datei nicht umbenennen: {0}",
"UpdaterAddingFiles": "Neue Dateien hinzufügen...",
"UpdaterExtracting": "Update extrahieren...",
"UpdaterDownloading": "Update herunterladen...",
"Game": "Spiel",
"Docked": "Docked",
"Handheld": "Handheld",
"ConnectionError": "Verbindungsfehler.",
"AboutPageDeveloperListMore": "{0} und mehr...",
"ApiError": "API Fehler.",
"LoadingHeading": "{0} wird gestartet",
"CompilingPPTC": "PTC wird kompiliert",
"CompilingShaders": "Shader werden kompiliert",
"AllKeyboards": "Alle Tastaturen",
"OpenFileDialogTitle": "Wähle eine unterstützte Datei",
"OpenFolderDialogTitle": "Wähle einen Ordner mit einem entpackten Spiel",
"AllSupportedFormats": "Alle unterstützten Formate",
"RyujinxUpdater": "Ryujinx - Updater",
"SettingsTabHotkeys": "Tastatur Hotkeys",
"SettingsTabHotkeysHotkeys": "Tastatur Hotkeys",
"SettingsTabHotkeysToggleVsyncHotkey": "VSync:",
"SettingsTabHotkeysScreenshotHotkey": "Screenshot:",
"SettingsTabHotkeysShowUiHotkey": "Zeige UI:",
"SettingsTabHotkeysPauseHotkey": "Pausieren:",
"SettingsTabHotkeysToggleMuteHotkey": "Stummschalten:",
"ControllerMotionTitle": "Bewegungssteuerung - Einstellungen",
"ControllerRumbleTitle": "Vibration - Einstellungen",
"SettingsSelectThemeFileDialogTitle": "Wähle ein Design für die Emulator-Benutzeroberfläche",
"SettingsXamlThemeFile": "Xaml Design-Datei",
"AvatarWindowTitle": "Profile verwalten - Avatar",
"Amiibo": "Amiibo",
"Unknown": "Unbekannt",
"Usage": "Nutzung",
"Writable": "Beschreibbar",
"SelectDlcDialogTitle": "DLC-Dateien auswählen",
"SelectUpdateDialogTitle": "Update-Datei auswählen",
"UserProfileWindowTitle": "Benutzerprofile verwalten",
"CheatWindowTitle": "Spiel-Cheats verwalten",
"DlcWindowTitle": "Spiel-DLC verwalten",
"UpdateWindowTitle": "Spiel-Updates verwalten",
"CheatWindowHeading": "Cheats verfügbar für {0} [{1}]",
"DlcWindowHeading": "DLC verfügbar für {0} [{1}]",
"UserProfilesEditProfile": "Profil bearbeiten",
"Cancel": "Abbrechen",
"Save": "Speichern",
"Discard": "Verwerfen",
"UserProfilesSetProfileImage": "Profilbild einrichten",
"UserProfileEmptyNameError": "Name ist erforderlich",
"UserProfileNoImageError": "Bitte ein Profilbild auswählen",
"GameUpdateWindowHeading": "Update verfügbar für {0} [{1}]",
"SettingsTabHotkeysResScaleUpHotkey": "Auflösung erhöhen:",
"SettingsTabHotkeysResScaleDownHotkey": "Auflösung verringern:",
"UserProfilesName": "Name:",
"UserProfilesUserId": "Benutzer Id:",
"SettingsTabGraphicsBackend": "Grafik-Backend:",
"SettingsTabGraphicsBackendTooltip": "Verwendendetes Grafik-Backend",
"SettingsEnableTextureRecompression": "Textur-Rekompression",
"SettingsEnableTextureRecompressionTooltip": "Komprimiert bestimmte Texturen, um den VRAM-Verbrauch zu reduzieren.\n\nEmpfohlen für die Verwendung von GPUs, die weniger als 4 GiB VRAM haben.\n\nIm Zweifelsfall AUS lassen",
"SettingsTabGraphicsPreferredGpu": "Bevorzugte GPU:",
"SettingsTabGraphicsPreferredGpuTooltip": "Wähle die Grafikkarte aus, die mit dem Vulkan Grafik-Backend verwendet werden soll.\n\nDies hat keinen Einfluss auf die GPU die OpenGL verwendet.\n\nIm Zweifelsfall die als \"dGPU\" gekennzeichnete GPU auswählen. Diese Einstellung unberührt lassen, wenn keine zur Auswahl steht.",
"SettingsAppRequiredRestartMessage": "Ein Neustart von Ryujinx ist erforderlich",
"SettingsGpuBackendRestartMessage": "Das Grafik-Backend oder die Grafikkarteneinstellungen wurden geändert. Ein Neustart ist erforderlich um diese Einstellungen anzuwenden.",
"SettingsGpuBackendRestartSubMessage": "Ryujinx jetzt neu starten?",
"RyujinxUpdaterMessage": "Möchtest du Ryujinx auf die neueste Version aktualisieren?",
"SettingsTabHotkeysVolumeUpHotkey": "Lautstärke erhöhen:",
"SettingsTabHotkeysVolumeDownHotkey": "Lautstärke verringern:",
"SettingsEnableMacroHLE": "HLE Makros aktivieren",
"SettingsEnableMacroHLETooltip": "High-level emulation of GPU Macro code.\n\nImproves performance, but may cause graphical glitches in some games.\n\nLeave ON if unsure.",
"VolumeShort": "Vol",
"UserProfilesManageSaves": "Speicherstände verwalten",
"DeleteUserSave": "Möchtest du den Spielerstand für dieses Spiel löschen?",
"IrreversibleActionNote": "Diese Option kann nicht rückgängig gemacht werden.",
"SaveManagerHeading": "Spielstände für {0} verwalten",
"SaveManagerTitle": "Speicherdaten Manager",
"Name": "Name",
"Size": "Größe",
"Search": "Suche",
"UserProfilesRecoverLostAccounts": "Konto wiederherstellen",
"Recover": "Wiederherstellen",
"UserProfilesRecoverHeading": "Speicherstände wurden für die folgenden Konten gefunden"
}

View File

@@ -1,613 +0,0 @@
{
"MenuBarFileOpenApplet": "Άνοιγμα Applet",
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Άνοιγμα του Mii Editor Applet σε Αυτόνομη λειτουργία",
"SettingsTabInputDirectMouseAccess": "Άμεση Πρόσβαση Ποντικιού",
"SettingsTabSystemMemoryManagerMode": "Λειτουργία Διαχείρισης Μνήμης:",
"SettingsTabSystemMemoryManagerModeSoftware": "Λογισμικό",
"SettingsTabSystemMemoryManagerModeHost": "Υπολογιστής (γρήγορο)",
"SettingsTabSystemMemoryManagerModeHostUnchecked": "Χωρίς Ελέγχους (γρηγορότερο, μη ασφαλές)",
"MenuBarFile": "_Αρχείο",
"MenuBarFileOpenFromFile": "_Φόρτωση Αρχείου Εφαρμογής",
"MenuBarFileOpenUnpacked": "Φόρτωση Απακετάριστου _Παιχνιδιού",
"MenuBarFileOpenEmuFolder": "Άνοιγμα Φακέλου Ryujinx",
"MenuBarFileOpenLogsFolder": "Άνοιγμα Φακέλου Καταγραφής",
"MenuBarFileExit": "_Έξοδος",
"MenuBarOptions": "Επιλογές",
"MenuBarOptionsToggleFullscreen": "Λειτουργία Πλήρους Οθόνης",
"MenuBarOptionsStartGamesInFullscreen": "Εκκίνηση Παιχνιδιών σε Πλήρη Οθόνη",
"MenuBarOptionsStopEmulation": "Διακοπή Εξομοίωσης",
"MenuBarOptionsSettings": "_Ρυθμίσεις",
"MenuBarOptionsManageUserProfiles": "Διαχείριση Προφίλ _Χρηστών",
"MenuBarActions": "_Δράσεις",
"MenuBarOptionsSimulateWakeUpMessage": "Προσομοίωση Μηνύματος Αφύπνισης",
"MenuBarActionsScanAmiibo": "Σάρωση Amiibo",
"MenuBarTools": "Εργα_λεία",
"MenuBarToolsInstallFirmware": "Εγκατάσταση Firmware",
"MenuBarFileToolsInstallFirmwareFromFile": "Εγκατάσταση Firmware από XCI ή ZIP",
"MenuBarFileToolsInstallFirmwareFromDirectory": "Εγκατάσταση Firmware από τοποθεσία",
"MenuBarHelp": "Βοήθεια",
"MenuBarHelpCheckForUpdates": "Έλεγχος για Ενημερώσεις",
"MenuBarHelpAbout": "Σχετικά με",
"MenuSearch": "Αναζήτηση...",
"GameListHeaderFavorite": "Αγαπημένο",
"GameListHeaderIcon": "Εικονίδιο",
"GameListHeaderApplication": "Όνομα",
"GameListHeaderDeveloper": "Προγραμματιστής",
"GameListHeaderVersion": "Έκδοση",
"GameListHeaderTimePlayed": "Χρόνος",
"GameListHeaderLastPlayed": "Παίχτηκε",
"GameListHeaderFileExtension": "Κατάληξη",
"GameListHeaderFileSize": "Μέγεθος",
"GameListHeaderPath": "Τοποθεσία",
"GameListContextMenuOpenUserSaveDirectory": "Άνοιγμα Τοποθεσίας Αποθήκευσης Χρήστη",
"GameListContextMenuOpenUserSaveDirectoryToolTip": "Ανοίγει την τοποθεσία που περιέχει την Αποθήκευση Χρήστη της εφαρμογής",
"GameListContextMenuOpenUserDeviceDirectory": "Άνοιγμα Τοποθεσίας Συσκευής Χρήστη",
"GameListContextMenuOpenUserDeviceDirectoryToolTip": "Ανοίγει την τοποθεσία που περιέχει την Αποθήκευση Συσκευής της εφαρμογής",
"GameListContextMenuOpenUserBcatDirectory": "Άνοιγμα Τοποθεσίας BCAT",
"GameListContextMenuOpenUserBcatDirectoryToolTip": "Ανοίγει την τοποθεσία που περιέχει την Αποθήκευση BCAT της εφαρμογής",
"GameListContextMenuManageTitleUpdates": "Διαχείριση Ενημερώσεων Παιχνιδιού",
"GameListContextMenuManageTitleUpdatesToolTip": "Ανοίγει το παράθυρο διαχείρισης Ενημερώσεων Παιχνιδιού",
"GameListContextMenuManageDlc": "Διαχείριση DLC",
"GameListContextMenuManageDlcToolTip": "Ανοίγει το παράθυρο διαχείρισης DLC",
"GameListContextMenuOpenModsDirectory": "Άνοιγμα Τοποθεσίας Τροποποιήσεων",
"GameListContextMenuOpenModsDirectoryToolTip": "Ανοίγει την τοποθεσία που περιέχει τις Τροποποιήσεις της εφαρμογής",
"GameListContextMenuCacheManagement": "Διαχείριση Προσωρινής Μνήμης",
"GameListContextMenuCacheManagementPurgePptc": "Εκκαθάριση Προσωρινής Μνήμης PPTC",
"GameListContextMenuCacheManagementPurgePptcToolTip": "Διαγράφει την προσωρινή μνήμη PPTC της εφαρμογής",
"GameListContextMenuCacheManagementPurgeShaderCache": "Εκκαθάριση Προσωρινής Μνήμης Shader",
"GameListContextMenuCacheManagementPurgeShaderCacheToolTip": "Διαγράφει την προσωρινή μνήμη Shader της εφαρμογής",
"GameListContextMenuCacheManagementOpenPptcDirectory": "Άνοιγμα Τοποθεσίας PPTC",
"GameListContextMenuCacheManagementOpenPptcDirectoryToolTip": "Ανοίγει την τοποθεσία που περιέχει τη προσωρινή μνήμη PPTC της εφαρμογής",
"GameListContextMenuCacheManagementOpenShaderCacheDirectory": "Άνοιγμα τοποθεσίας προσωρινής μνήμης Shader",
"GameListContextMenuCacheManagementOpenShaderCacheDirectoryToolTip": "Ανοίγει την τοποθεσία που περιέχει την προσωρινή μνήμη Shader της εφαρμογής",
"GameListContextMenuExtractData": "Εξαγωγή Δεδομένων",
"GameListContextMenuExtractDataExeFS": "ExeFS",
"GameListContextMenuExtractDataExeFSToolTip": "Εξαγωγή της ενότητας ExeFS από την τρέχουσα διαμόρφωση της εφαρμογής (συμπεριλαμβανομένου ενημερώσεων)",
"GameListContextMenuExtractDataRomFS": "RomFS",
"GameListContextMenuExtractDataRomFSToolTip": "Εξαγωγή της ενότητας RomFS από την τρέχουσα διαμόρφωση της εφαρμογής (συμπεριλαμβανομένου ενημερώσεων)",
"GameListContextMenuExtractDataLogo": "Λογότυπο",
"GameListContextMenuExtractDataLogoToolTip": "Εξαγωγή της ενότητας Logo από την τρέχουσα διαμόρφωση της εφαρμογής (συμπεριλαμβανομένου ενημερώσεων)",
"StatusBarGamesLoaded": "{0}/{1} Φορτωμένα Παιχνίδια",
"StatusBarSystemVersion": "Έκδοση Συστήματος: {0}",
"Settings": "Ρυθμίσεις",
"SettingsTabGeneral": "Εμφάνιση",
"SettingsTabGeneralGeneral": "Γενικά",
"SettingsTabGeneralEnableDiscordRichPresence": "Ενεργοποίηση Εμπλουτισμένης Παρουσίας Discord",
"SettingsTabGeneralCheckUpdatesOnLaunch": "Έλεγχος για Ενημερώσεις στην Εκκίνηση",
"SettingsTabGeneralShowConfirmExitDialog": "Εμφάνιση διαλόγου \"Επιβεβαίωση Εξόδου\".",
"SettingsTabGeneralHideCursorOnIdle": "Απόκρυψη Δρομέα στην Αδράνεια",
"SettingsTabGeneralGameDirectories": "Τοποθεσίες παιχνιδιών",
"SettingsTabGeneralAdd": "Προσθήκη",
"SettingsTabGeneralRemove": "Αφαίρεση",
"SettingsTabSystem": "Σύστημα",
"SettingsTabSystemCore": "Πυρήνας",
"SettingsTabSystemSystemRegion": "Περιοχή Συστήματος:",
"SettingsTabSystemSystemRegionJapan": "Ιαπωνία",
"SettingsTabSystemSystemRegionUSA": "ΗΠΑ",
"SettingsTabSystemSystemRegionEurope": "Ευρώπη",
"SettingsTabSystemSystemRegionAustralia": "Αυστραλία",
"SettingsTabSystemSystemRegionChina": "Κίνα",
"SettingsTabSystemSystemRegionKorea": "Κορέα",
"SettingsTabSystemSystemRegionTaiwan": "Ταϊβάν",
"SettingsTabSystemSystemLanguage": "Γλώσσα Συστήματος:",
"SettingsTabSystemSystemLanguageJapanese": "Ιαπωνικά",
"SettingsTabSystemSystemLanguageAmericanEnglish": "Αμερικάνικα Αγγλικά",
"SettingsTabSystemSystemLanguageFrench": "Γαλλικά",
"SettingsTabSystemSystemLanguageGerman": "Γερμανικά",
"SettingsTabSystemSystemLanguageItalian": "Ιταλικά",
"SettingsTabSystemSystemLanguageSpanish": "Ισπανικά",
"SettingsTabSystemSystemLanguageChinese": "Κινέζικα",
"SettingsTabSystemSystemLanguageKorean": "Κορεάτικα",
"SettingsTabSystemSystemLanguageDutch": "Ολλανδικά",
"SettingsTabSystemSystemLanguagePortuguese": "Πορτογαλικά",
"SettingsTabSystemSystemLanguageRussian": "Ρώσικα",
"SettingsTabSystemSystemLanguageTaiwanese": "Ταϊβανέζικα",
"SettingsTabSystemSystemLanguageBritishEnglish": "Βρετανικά Αγγλικά",
"SettingsTabSystemSystemLanguageCanadianFrench": "Καναδικά Γαλλικά",
"SettingsTabSystemSystemLanguageLatinAmericanSpanish": "Λατινοαμερικάνικα Ισπανικά",
"SettingsTabSystemSystemLanguageSimplifiedChinese": "Απλοποιημένα Κινέζικα",
"SettingsTabSystemSystemLanguageTraditionalChinese": "Παραδοσιακά Κινεζικά",
"SettingsTabSystemSystemTimeZone": "Ζώνη Ώρας Συστήματος:",
"SettingsTabSystemSystemTime": "Ώρα Συστήματος:",
"SettingsTabSystemEnableVsync": "Ενεργοποίηση Κατακόρυφου Συγχρονισμού",
"SettingsTabSystemEnablePptc": "Ενεργοποίηση PPTC (Profiled Persistent Translation Cache)",
"SettingsTabSystemEnableFsIntegrityChecks": "Ενεργοποίηση Ελέγχων Ακεραιότητας FS",
"SettingsTabSystemAudioBackend": "Backend Ήχου:",
"SettingsTabSystemAudioBackendDummy": "Απενεργοποιημένο",
"SettingsTabSystemAudioBackendOpenAL": "OpenAL",
"SettingsTabSystemAudioBackendSoundIO": "SoundIO",
"SettingsTabSystemAudioBackendSDL2": "SDL2",
"SettingsTabSystemHacks": "Μικροδιορθώσεις",
"SettingsTabSystemHacksNote": " (Μπορεί να προκαλέσουν αστάθεια)",
"SettingsTabSystemExpandDramSize": "Επέκταση μεγέθους DRAM στα 6GiB",
"SettingsTabSystemIgnoreMissingServices": "Αγνόηση υπηρεσιών που λείπουν",
"SettingsTabGraphics": "Γραφικά",
"SettingsTabGraphicsAPI": "API Γραφικά",
"SettingsTabGraphicsEnableShaderCache": "Ενεργοποίηση Προσωρινής Μνήμης Shader",
"SettingsTabGraphicsAnisotropicFiltering": "Ανισότροπο Φιλτράρισμα:",
"SettingsTabGraphicsAnisotropicFilteringAuto": "Αυτόματο",
"SettingsTabGraphicsAnisotropicFiltering2x": "2x",
"SettingsTabGraphicsAnisotropicFiltering4x": "4x",
"SettingsTabGraphicsAnisotropicFiltering8x": "8x",
"SettingsTabGraphicsAnisotropicFiltering16x": "16x",
"SettingsTabGraphicsResolutionScale": "Κλίμακα Ανάλυσης:",
"SettingsTabGraphicsResolutionScaleCustom": "Προσαρμοσμένο (Δεν συνιστάται)",
"SettingsTabGraphicsResolutionScaleNative": "Εγγενής (720p/1080p)",
"SettingsTabGraphicsResolutionScale2x": "2x (1440p/2160p)",
"SettingsTabGraphicsResolutionScale3x": "3x (2160p/3240p)",
"SettingsTabGraphicsResolutionScale4x": "4x (2880p/4320p)",
"SettingsTabGraphicsAspectRatio": "Αναλογία Απεικόνισης:",
"SettingsTabGraphicsAspectRatio4x3": "4:3",
"SettingsTabGraphicsAspectRatio16x9": "16:9",
"SettingsTabGraphicsAspectRatio16x10": "16:10",
"SettingsTabGraphicsAspectRatio21x9": "21:9",
"SettingsTabGraphicsAspectRatio32x9": "32:9",
"SettingsTabGraphicsAspectRatioStretch": "Έκταση σε όλο το παράθυρο",
"SettingsTabGraphicsDeveloperOptions": "Επιλογές Προγραμματιστή",
"SettingsTabGraphicsShaderDumpPath": "Τοποθεσία Shaders Γραφικών:",
"SettingsTabLogging": "Καταγραφή",
"SettingsTabLoggingLogging": "Καταγραφή",
"SettingsTabLoggingEnableLoggingToFile": "Ενεργοποίηση Καταγραφής Αρχείου",
"SettingsTabLoggingEnableStubLogs": "Ενεργοποίηση Καταγραφής Stub",
"SettingsTabLoggingEnableInfoLogs": "Ενεργοποίηση Καταγραφής Πληροφοριών",
"SettingsTabLoggingEnableWarningLogs": "Ενεργοποίηση Καταγραφής Προειδοποίησης",
"SettingsTabLoggingEnableErrorLogs": "Ενεργοποίηση Καταγραφής Σφαλμάτων",
"SettingsTabLoggingEnableTraceLogs": "Ενεργοποίηση Καταγραφής Ιχνών",
"SettingsTabLoggingEnableGuestLogs": "Ενεργοποίηση Καταγραφής Επισκεπτών",
"SettingsTabLoggingEnableFsAccessLogs": "Ενεργοποίηση Καταγραφής Πρόσβασης FS",
"SettingsTabLoggingFsGlobalAccessLogMode": "Λειτουργία Καταγραφής Καθολικής Πρόσβασης FS:",
"SettingsTabLoggingDeveloperOptions": "Επιλογές Προγραμματιστή (ΠΡΟΕΙΔΟΠΟΙΗΣΗ: Η απόδοση Θα μειωθεί)",
"SettingsTabLoggingGraphicsBackendLogLevel": "Επίπεδο Καταγραφής Διεπαφής Γραφικών:",
"SettingsTabLoggingGraphicsBackendLogLevelNone": "Κανένα",
"SettingsTabLoggingGraphicsBackendLogLevelError": "Σφάλμα",
"SettingsTabLoggingGraphicsBackendLogLevelPerformance": "Επιβραδύνσεις",
"SettingsTabLoggingGraphicsBackendLogLevelAll": "Όλα",
"SettingsTabLoggingEnableDebugLogs": "Ενεργοποίηση Αρχείων Καταγραφής Εντοπισμού Σφαλμάτων",
"SettingsTabInput": "Χειρισμός",
"SettingsTabInputEnableDockedMode": "Ενεργοποίηση Docked Mode",
"SettingsTabInputDirectKeyboardAccess": "Άμεση Πρόσβαση στο Πληκτρολόγιο",
"SettingsButtonSave": "Αποθήκευση",
"SettingsButtonClose": "Κλείσιμο",
"SettingsButtonOk": "ΟΚ",
"SettingsButtonCancel": "Ακύρωση",
"SettingsButtonApply": "Εφαρμογή",
"ControllerSettingsPlayer": "Παίχτης",
"ControllerSettingsPlayer1": "Παίχτης 1",
"ControllerSettingsPlayer2": "Παίχτης 2",
"ControllerSettingsPlayer3": "Παίχτης 3",
"ControllerSettingsPlayer4": "Παίχτης 4",
"ControllerSettingsPlayer5": "Παίχτης 5",
"ControllerSettingsPlayer6": "Παίχτης 6",
"ControllerSettingsPlayer7": "Παίχτης 7",
"ControllerSettingsPlayer8": "Παίχτης 8",
"ControllerSettingsHandheld": "Χειροκίνητο",
"ControllerSettingsInputDevice": "Συσκευή Χειρισμού",
"ControllerSettingsRefresh": "Ανανέωση",
"ControllerSettingsDeviceDisabled": "Απενεργοποιημένο",
"ControllerSettingsControllerType": "Τύπος Χειριστηρίου",
"ControllerSettingsControllerTypeHandheld": "Φορητό",
"ControllerSettingsControllerTypeProController": "Pro Controller",
"ControllerSettingsControllerTypeJoyConPair": "Ζεύγος JoyCon",
"ControllerSettingsControllerTypeJoyConLeft": "Αριστερό JoyCon",
"ControllerSettingsControllerTypeJoyConRight": "Δεξί JoyCon",
"ControllerSettingsProfile": "Προφίλ",
"ControllerSettingsProfileDefault": "Προκαθορισμένο",
"ControllerSettingsLoad": "Φόρτωση",
"ControllerSettingsAdd": "Προσθήκη",
"ControllerSettingsRemove": "Αφαίρεση",
"ControllerSettingsButtons": "Κουμπιά",
"ControllerSettingsButtonA": "Α",
"ControllerSettingsButtonB": "B",
"ControllerSettingsButtonX": "X",
"ControllerSettingsButtonY": "Y",
"ControllerSettingsButtonPlus": "+",
"ControllerSettingsButtonMinus": "-",
"ControllerSettingsDPad": "Κατευθυντικό Pad",
"ControllerSettingsDPadUp": "Πάνω",
"ControllerSettingsDPadDown": "Κάτω",
"ControllerSettingsDPadLeft": "Αριστερά",
"ControllerSettingsDPadRight": "Δεξιά",
"ControllerSettingsLStick": "Αριστερός Μοχλός",
"ControllerSettingsLStickButton": "Κουμπί",
"ControllerSettingsLStickUp": "Πάνω",
"ControllerSettingsLStickDown": "Κάτω",
"ControllerSettingsLStickLeft": "Αριστερά",
"ControllerSettingsLStickRight": "Δεξιά",
"ControllerSettingsLStickStick": "Μοχλός",
"ControllerSettingsLStickInvertXAxis": "Αντιστροφή Μοχλού X",
"ControllerSettingsLStickInvertYAxis": "Αντιστροφή Μοχλού Y",
"ControllerSettingsLStickDeadzone": "Νεκρή Ζώνη:",
"ControllerSettingsRStick": "Δεξιός Μοχλός",
"ControllerSettingsRStickButton": "Κουμπί",
"ControllerSettingsRStickUp": "Πάνω",
"ControllerSettingsRStickDown": "Κάτω",
"ControllerSettingsRStickLeft": "Αριστερά",
"ControllerSettingsRStickRight": "Δεξιά",
"ControllerSettingsRStickStick": "Μοχλός",
"ControllerSettingsRStickInvertXAxis": "Αντιστροφή Μοχλού X",
"ControllerSettingsRStickInvertYAxis": "Αντιστροφή Μοχλού Y",
"ControllerSettingsRStickDeadzone": "Νεκρή Ζώνη:",
"ControllerSettingsTriggersLeft": "Αριστερή Σκανδάλη",
"ControllerSettingsTriggersRight": "Δεξιά Σκανδάλη",
"ControllerSettingsTriggersButtonsLeft": "Αριστερά Κουμπιά Σκανδάλης",
"ControllerSettingsTriggersButtonsRight": "Δεξιά Κουμπιά Σκανδάλης",
"ControllerSettingsTriggers": "Σκανδάλες",
"ControllerSettingsTriggerL": "L",
"ControllerSettingsTriggerR": "R",
"ControllerSettingsTriggerZL": "ZL",
"ControllerSettingsTriggerZR": "ZR",
"ControllerSettingsLeftSL": "SL",
"ControllerSettingsLeftSR": "SR",
"ControllerSettingsRightSL": "SL",
"ControllerSettingsRightSR": "SR",
"ControllerSettingsExtraButtonsLeft": "Αριστερά Κουμπιά",
"ControllerSettingsExtraButtonsRight": "Δεξιά Κουμπιά",
"ControllerSettingsMisc": "Διάφορα",
"ControllerSettingsTriggerThreshold": "Κατώφλι Σκανδάλης:",
"ControllerSettingsMotion": "Κίνηση",
"ControllerSettingsMotionUseCemuhookCompatibleMotion": "Κίνηση συμβατή με CemuHook",
"ControllerSettingsMotionControllerSlot": "Υποδοχή Χειριστηρίου:",
"ControllerSettingsMotionMirrorInput": "Καθρεπτισμός Χειρισμού",
"ControllerSettingsMotionRightJoyConSlot": "Δεξιά Υποδοχή JoyCon:",
"ControllerSettingsMotionServerHost": "Κεντρικός Υπολογιστής Διακομιστή:",
"ControllerSettingsMotionGyroSensitivity": "Ευαισθησία Γυροσκοπίου:",
"ControllerSettingsMotionGyroDeadzone": "Νεκρή Ζώνη Γυροσκοπίου:",
"ControllerSettingsSave": "Αποθήκευση",
"ControllerSettingsClose": "Κλείσιμο",
"UserProfilesSelectedUserProfile": "Επιλεγμένο Προφίλ Χρήστη:",
"UserProfilesSaveProfileName": "Αποθήκευση Ονόματος Προφίλ",
"UserProfilesChangeProfileImage": "Αλλαγή Εικόνας Προφίλ",
"UserProfilesAvailableUserProfiles": "Διαθέσιμα Προφίλ Χρηστών:",
"UserProfilesAddNewProfile": "Προσθήκη Νέου Προφίλ",
"UserProfilesDeleteSelectedProfile": "Διαγραφή Επιλεγμένου Προφίλ",
"UserProfilesClose": "Κλείσιμο",
"ProfileImageSelectionTitle": "Επιλογή Εικόνας Προφίλ",
"ProfileImageSelectionHeader": "Επιλέξτε μία Εικόνα Προφίλ",
"ProfileImageSelectionNote": "Μπορείτε να εισαγάγετε μία προσαρμοσμένη εικόνα προφίλ ή να επιλέξετε ένα avatar από το Firmware",
"ProfileImageSelectionImportImage": "Εισαγωγή Αρχείου Εικόνας",
"ProfileImageSelectionSelectAvatar": "Επιλέξτε Avatar από Firmware",
"InputDialogTitle": "Διάλογος Εισαγωγής",
"InputDialogOk": "ΟΚ",
"InputDialogCancel": "Ακύρωση",
"InputDialogAddNewProfileTitle": "Επιλογή Ονόματος Προφίλ",
"InputDialogAddNewProfileHeader": "Εισαγωγή Ονόματος Προφίλ",
"InputDialogAddNewProfileSubtext": "(Σύνολο Χαρακτήρων: {0})",
"AvatarChoose": "Επιλογή",
"AvatarSetBackgroundColor": "Ορισμός Χρώματος Φόντου",
"AvatarClose": "Κλείσιμο",
"ControllerSettingsLoadProfileToolTip": "Φόρτωση Προφίλ",
"ControllerSettingsAddProfileToolTip": "Προσθήκη Προφίλ",
"ControllerSettingsRemoveProfileToolTip": "Κατάργηση Προφίλ",
"ControllerSettingsSaveProfileToolTip": "Αποθήκευση Προφίλ",
"MenuBarFileToolsTakeScreenshot": "Λήψη Στιγμιότυπου",
"MenuBarFileToolsHideUi": "Απόκρυψη UI",
"GameListContextMenuToggleFavorite": "Εναλλαγή Αγαπημένου",
"GameListContextMenuToggleFavoriteToolTip": "Εναλλαγή της Κατάστασης Αγαπημένο του Παιχνιδιού",
"SettingsTabGeneralTheme": "Θέμα",
"SettingsTabGeneralThemeCustomTheme": "Προσαρμοσμένη Τοποθεσία Θέματος",
"SettingsTabGeneralThemeBaseStyle": "Βασικό Στυλ",
"SettingsTabGeneralThemeBaseStyleDark": "Σκούρο",
"SettingsTabGeneralThemeBaseStyleLight": "Ανοιχτό",
"SettingsTabGeneralThemeEnableCustomTheme": "Ενεργοποίηση Προσαρμοσμένου Θέματος",
"ButtonBrowse": "Αναζήτηση",
"ControllerSettingsConfigureGeneral": "Παραμέτρων",
"ControllerSettingsRumble": "Δόνηση",
"ControllerSettingsRumbleStrongMultiplier": "Ισχυρός Πολλαπλασιαστής Δόνησης",
"ControllerSettingsRumbleWeakMultiplier": "Αδύναμος Πολλαπλασιαστής Δόνησης",
"DialogMessageSaveNotAvailableMessage": "Δεν υπάρχουν αποθηκευμένα δεδομένα για το {0} [{1:x16}]",
"DialogMessageSaveNotAvailableCreateSaveMessage": "Θέλετε να αποθηκεύσετε δεδομένα για αυτό το παιχνίδι;",
"DialogConfirmationTitle": "Ryujinx - Επιβεβαίωση",
"DialogUpdaterTitle": "Ryujinx - Ενημερωτής",
"DialogErrorTitle": "Ryujinx - Σφάλμα",
"DialogWarningTitle": "Ryujinx - Προειδοποίηση",
"DialogExitTitle": "Ryujinx - Έξοδος",
"DialogErrorMessage": "Το Ryujinx αντιμετώπισε σφάλμα",
"DialogExitMessage": "Είστε βέβαιοι ότι θέλετε να κλείσετε το Ryujinx;",
"DialogExitSubMessage": "Όλα τα μη αποθηκευμένα δεδομένα θα χαθούν!",
"DialogMessageCreateSaveErrorMessage": "Σφάλμα κατά τη δημιουργία των αποθηκευμένων δεδομένων: {0}",
"DialogMessageFindSaveErrorMessage": "Σφάλμα κατά την εύρεση των αποθηκευμένων δεδομένων: {0}",
"FolderDialogExtractTitle": "Επιλέξτε τον φάκελο στον οποίο θέλετε να εξαγάγετε",
"DialogNcaExtractionMessage": "Εξαγωγή ενότητας {0} από {1}...",
"DialogNcaExtractionTitle": "Ryujinx - NCA Εξαγωγέας Τμημάτων",
"DialogNcaExtractionMainNcaNotFoundErrorMessage": "Αποτυχία εξαγωγής. Η κύρια NCA δεν υπήρχε στο επιλεγμένο αρχείο.",
"DialogNcaExtractionCheckLogErrorMessage": "Αποτυχία εξαγωγής. Διαβάστε το αρχείο καταγραφής για περισσότερες πληροφορίες.",
"DialogNcaExtractionSuccessMessage": "Η εξαγωγή ολοκληρώθηκε με επιτυχία.",
"DialogUpdaterConvertFailedMessage": "Αποτυχία μετατροπής της τρέχουσας έκδοσης Ryujinx.",
"DialogUpdaterCancelUpdateMessage": "Ακύρωση Ενημέρωσης!",
"DialogUpdaterAlreadyOnLatestVersionMessage": "Χρησιμοποιείτε ήδη την πιο ενημερωμένη έκδοση του Ryujinx!",
"DialogUpdaterFailedToGetVersionMessage": "Προέκυψε ένα σφάλμα στη λήψη πληροφοριών έκδοσης από τα GitHub Releases. Αυτό δύναται να συμβεί αν μία έκδοση χτίζεται αυτή τη στιγμή στα GitHub Actions. Παρακαλούμε προσπαθήστε αργότερα.",
"DialogUpdaterConvertFailedGithubMessage": "Αποτυχία μετατροπής της ληφθείσας έκδοσης Ryujinx από την έκδοση GitHub.",
"DialogUpdaterDownloadingMessage": "Λήψη Ενημέρωσης...",
"DialogUpdaterExtractionMessage": "Εξαγωγή Ενημέρωσης...",
"DialogUpdaterRenamingMessage": "Μετονομασία Ενημέρωσης...",
"DialogUpdaterAddingFilesMessage": "Προσθήκη Νέας Ενημέρωσης...",
"DialogUpdaterCompleteMessage": "Η Ενημέρωση Ολοκληρώθηκε!",
"DialogUpdaterRestartMessage": "Θέλετε να επανεκκινήσετε το Ryujinx τώρα;",
"DialogUpdaterArchNotSupportedMessage": "Δεν υπάρχει υποστηριζόμενη αρχιτεκτονική συστήματος!",
"DialogUpdaterArchNotSupportedSubMessage": "(Υποστηρίζονται μόνο συστήματα x64!)",
"DialogUpdaterNoInternetMessage": "Δεν είστε συνδεδεμένοι στο Διαδίκτυο!",
"DialogUpdaterNoInternetSubMessage": "Επαληθεύστε ότι έχετε σύνδεση στο Διαδίκτυο που λειτουργεί!",
"DialogUpdaterDirtyBuildMessage": "Δεν μπορείτε να ενημερώσετε μία Πρόχειρη Έκδοση του Ryujinx!",
"DialogUpdaterDirtyBuildSubMessage": "Κάντε λήψη του Ryujinx στη διεύθυνση https://ryujinx.org/ εάν αναζητάτε μία υποστηριζόμενη έκδοση.",
"DialogRestartRequiredMessage": "Απαιτείται Επανεκκίνηση",
"DialogThemeRestartMessage": "Το θέμα έχει αποθηκευτεί. Απαιτείται επανεκκίνηση για την εφαρμογή του θέματος.",
"DialogThemeRestartSubMessage": "Θέλετε να κάνετε επανεκκίνηση",
"DialogFirmwareInstallEmbeddedMessage": "Θα θέλατε να εγκαταστήσετε το Firmware που είναι ενσωματωμένο σε αυτό το παιχνίδι; (Firmware {0})",
"DialogFirmwareInstallEmbeddedSuccessMessage": "Δεν βρέθηκε εγκατεστημένο Firmware, αλλά το Ryujinx μπόρεσε να εγκαταστήσει το Firmware {0} από το παρεχόμενο παιχνίδι.\nΟ εξομοιωτής θα ξεκινήσει τώρα.",
"DialogFirmwareNoFirmwareInstalledMessage": "Δεν έχει εγκατασταθεί Firmware",
"DialogFirmwareInstalledMessage": "Το Firmware {0} εγκαταστάθηκε",
"DialogOpenSettingsWindowLabel": "Άνοιγμα Παραθύρου Ρυθμίσεων",
"DialogControllerAppletTitle": "Applet Χειρισμού",
"DialogMessageDialogErrorExceptionMessage": "Σφάλμα εμφάνισης του διαλόγου Μηνυμάτων: {0}",
"DialogSoftwareKeyboardErrorExceptionMessage": "Σφάλμα εμφάνισης Λογισμικού Πληκτρολογίου: {0}",
"DialogErrorAppletErrorExceptionMessage": "Σφάλμα εμφάνισης του διαλόγου ErrorApplet: {0}",
"DialogUserErrorDialogMessage": "{0}: {1}",
"DialogUserErrorDialogInfoMessage": "\nΓια πληροφορίες σχετικά με τον τρόπο διόρθωσης του σφάλματος, ακολουθήστε τον Οδηγό Εγκατάστασης.",
"DialogUserErrorDialogTitle": "Σφάλμα Ryujinx ({0})",
"DialogAmiiboApiTitle": "Amiibo API",
"DialogAmiiboApiFailFetchMessage": "Παρουσιάστηκε σφάλμα κατά την ανάκτηση πληροφοριών από το API.",
"DialogAmiiboApiConnectErrorMessage": "Δεν είναι δυνατή η σύνδεση με τον διακομιστή Amiibo API. Η υπηρεσία μπορεί να είναι εκτός λειτουργίας ή μπορεί να χρειαστεί να επαληθεύσετε ότι έχετε ενεργή σύνδεσή στο Διαδίκτυο.",
"DialogProfileInvalidProfileErrorMessage": "Το προφίλ {0} δεν είναι συμβατό με το τρέχον σύστημα χειρισμού.",
"DialogProfileDefaultProfileOverwriteErrorMessage": "Το προεπιλεγμένο προφίλ δεν μπορεί να αντικατασταθεί",
"DialogProfileDeleteProfileTitle": "Διαγραφή Προφίλ",
"DialogProfileDeleteProfileMessage": "Αυτή η ενέργεια είναι μη αναστρέψιμη, είστε βέβαιοι ότι θέλετε να συνεχίσετε;",
"DialogWarning": "Προειδοποίηση",
"DialogPPTCDeletionMessage": "Πρόκειται να διαγράψετε την προσωρινή μνήμη PPTC για :\n\n{0}\n\nΕίστε βέβαιοι ότι θέλετε να συνεχίσετε;",
"DialogPPTCDeletionErrorMessage": "Σφάλμα κατά την εκκαθάριση προσωρινής μνήμης PPTC στο {0}: {1}",
"DialogShaderDeletionMessage": "Πρόκειται να διαγράψετε την προσωρινή μνήμη Shader για :\n\n{0}\n\nΕίστε βέβαιοι ότι θέλετε να συνεχίσετε;",
"DialogShaderDeletionErrorMessage": "Σφάλμα κατά την εκκαθάριση προσωρινής μνήμης Shader στο {0}: {1}",
"DialogRyujinxErrorMessage": "Το Ryujinx αντιμετώπισε σφάλμα",
"DialogInvalidTitleIdErrorMessage": "Σφάλμα UI: Το επιλεγμένο παιχνίδι δεν έχει έγκυρο αναγνωριστικό τίτλου",
"DialogFirmwareInstallerFirmwareNotFoundErrorMessage": "Δεν βρέθηκε έγκυρο Firmware συστήματος στο {0}.",
"DialogFirmwareInstallerFirmwareInstallTitle": "Εγκατάσταση Firmware {0}",
"DialogFirmwareInstallerFirmwareInstallMessage": "Θα εγκατασταθεί η έκδοση συστήματος {0}.",
"DialogFirmwareInstallerFirmwareInstallSubMessage": "\n\nΑυτό θα αντικαταστήσει την τρέχουσα έκδοση συστήματος {0}.",
"DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\nΘέλετε να συνεχίσετε;",
"DialogFirmwareInstallerFirmwareInstallWaitMessage": "Εγκατάσταση Firmware...",
"DialogFirmwareInstallerFirmwareInstallSuccessMessage": "Η έκδοση συστήματος {0} εγκαταστάθηκε με επιτυχία.",
"DialogUserProfileDeletionWarningMessage": "Δεν θα υπάρχουν άλλα προφίλ εάν διαγραφεί το επιλεγμένο",
"DialogUserProfileDeletionConfirmMessage": "Θέλετε να διαγράψετε το επιλεγμένο προφίλ",
"DialogControllerSettingsModifiedConfirmMessage": "Οι τρέχουσες ρυθμίσεις χειρισμού έχουν ενημερωθεί.",
"DialogControllerSettingsModifiedConfirmSubMessage": "Θέλετε να αποθηκεύσετε;",
"DialogDlcLoadNcaErrorMessage": "{0}. Σφάλμα Αρχείου: {1}",
"DialogDlcNoDlcErrorMessage": "Το αρχείο δεν περιέχει DLC για τον επιλεγμένο τίτλο!",
"DialogPerformanceCheckLoggingEnabledMessage": "Έχετε ενεργοποιημένη την καταγραφή εντοπισμού σφαλμάτων, η οποία έχει σχεδιαστεί για χρήση μόνο από προγραμματιστές.",
"DialogPerformanceCheckLoggingEnabledConfirmMessage": "Για βέλτιστη απόδοση, συνιστάται η απενεργοποίηση καταγραφής εντοπισμού σφαλμάτων. Θέλετε να απενεργοποιήσετε την καταγραφή τώρα;",
"DialogPerformanceCheckShaderDumpEnabledMessage": "Έχετε ενεργοποιήσει το Shader Dumping, το οποίο έχει σχεδιαστεί για χρήση μόνο από προγραμματιστές.",
"DialogPerformanceCheckShaderDumpEnabledConfirmMessage": "Για βέλτιστη απόδοση, συνιστάται να απενεργοποιήσετε το Shader Dumping. Θέλετε να απενεργοποιήσετε τώρα το Shader Dumping;",
"DialogLoadAppGameAlreadyLoadedMessage": "Ένα παιχνίδι έχει ήδη φορτωθεί",
"DialogLoadAppGameAlreadyLoadedSubMessage": "Σταματήστε την εξομοίωση ή κλείστε τον εξομοιωτή πριν ξεκινήσετε ένα άλλο παιχνίδι.",
"DialogUpdateAddUpdateErrorMessage": "Το αρχείο δεν περιέχει ενημέρωση για τον επιλεγμένο τίτλο!",
"DialogSettingsBackendThreadingWarningTitle": "Προειδοποίηση - Backend Threading",
"DialogSettingsBackendThreadingWarningMessage": "Το Ryujinx πρέπει να επανεκκινηθεί αφού αλλάξει αυτή η επιλογή για να εφαρμοστεί πλήρως. Ανάλογα με την πλατφόρμα σας, μπορεί να χρειαστεί να απενεργοποιήσετε με μη αυτόματο τρόπο το multithreading του ίδιου του προγράμματος οδήγησης όταν χρησιμοποιείτε το Ryujinx.",
"SettingsTabGraphicsFeaturesOptions": "Χαρακτηριστικά",
"SettingsTabGraphicsBackendMultithreading": "Πολυνηματική Επεξεργασία Γραφικών:",
"CommonAuto": "Αυτόματο",
"CommonOff": "Ανενεργό",
"CommonOn": "Ενεργό",
"InputDialogYes": "Ναί",
"InputDialogNo": "Όχι",
"DialogProfileInvalidProfileNameErrorMessage": "Το όνομα αρχείου περιέχει μη έγκυρους χαρακτήρες. Παρακαλώ προσπαθήστε ξανά.",
"MenuBarOptionsPauseEmulation": "Παύση",
"MenuBarOptionsResumeEmulation": "Συνέχιση",
"AboutUrlTooltipMessage": "Κάντε κλικ για να ανοίξετε τον ιστότοπο Ryujinx στο προεπιλεγμένο πρόγραμμα περιήγησης.",
"AboutDisclaimerMessage": "Το Ryujinx δεν είναι συνδεδεμένο με τη Nintendo™,\nούτε με κανέναν από τους συνεργάτες της, με οποιονδήποτε τρόπο.",
"AboutAmiiboDisclaimerMessage": "Το AmiiboAPI (www.amiiboapi.com) χρησιμοποιείται\nστην προσομοίωση Amiibo.",
"AboutPatreonUrlTooltipMessage": "Κάντε κλικ για να ανοίξετε τη σελίδα Ryujinx Patreon στο προεπιλεγμένο πρόγραμμα περιήγησης.",
"AboutGithubUrlTooltipMessage": "Κάντε κλικ για να ανοίξετε τη σελίδα Ryujinx GitHub στο προεπιλεγμένο πρόγραμμα περιήγησης.",
"AboutDiscordUrlTooltipMessage": "Κάντε κλικ για να ανοίξετε μία πρόσκληση στον διακομιστή Ryujinx Discord στο προεπιλεγμένο πρόγραμμα περιήγησης.",
"AboutTwitterUrlTooltipMessage": "Κάντε κλικ για να ανοίξετε τη σελίδα Ryujinx Twitter στο προεπιλεγμένο πρόγραμμα περιήγησης.",
"AboutRyujinxAboutTitle": "Σχετικά με:",
"AboutRyujinxAboutContent": "Το Ryujinx είναι ένας εξομοιωτής για το Nintendo Switch™.\nΥποστηρίξτε μας στο Patreon.\nΛάβετε όλα τα τελευταία νέα στο Twitter ή στο Discord.\nΟι προγραμματιστές που ενδιαφέρονται να συνεισφέρουν μπορούν να μάθουν περισσότερα στο GitHub ή στο Discord μας.",
"AboutRyujinxMaintainersTitle": "Συντηρείται από:",
"AboutRyujinxMaintainersContentTooltipMessage": "Κάντε κλικ για να ανοίξετε τη σελίδα Συνεισφέροντες στο προεπιλεγμένο πρόγραμμα περιήγησης.",
"AboutRyujinxSupprtersTitle": "Υποστηρίζεται στο Patreon από:",
"AmiiboSeriesLabel": "Σειρά Amiibo",
"AmiiboCharacterLabel": "Χαρακτήρας",
"AmiiboScanButtonLabel": "Σαρώστε το",
"AmiiboOptionsShowAllLabel": "Εμφάνιση όλων των Amiibo",
"AmiiboOptionsUsRandomTagLabel": "Hack: Χρησιμοποιήστε τυχαίο αναγνωριστικό UUID",
"DlcManagerTableHeadingEnabledLabel": "Ενεργοποιήθηκε",
"DlcManagerTableHeadingTitleIdLabel": "Αναγνωριστικό τίτλου",
"DlcManagerTableHeadingContainerPathLabel": "Τοποθεσία DLC",
"DlcManagerTableHeadingFullPathLabel": "Πλήρης τοποθεσία",
"DlcManagerRemoveAllButton": "Αφαίρεση όλων",
"DlcManagerEnableAllButton": "Ενεργοποίηση Όλων",
"DlcManagerDisableAllButton": "Απενεργοποίηση Όλων",
"MenuBarOptionsChangeLanguage": "Αλλαξε γλώσσα",
"CommonSort": "Κατάταξη",
"CommonShowNames": "Εμφάνιση ονομάτων",
"CommonFavorite": "Αγαπημένα",
"OrderAscending": "Αύξουσα",
"OrderDescending": "Φθίνουσα",
"SettingsTabGraphicsFeatures": "Χαρακτηριστικά & Βελτιώσεις",
"ErrorWindowTitle": "Παράθυρο σφάλματος",
"ToggleDiscordTooltip": "Ενεργοποιεί ή απενεργοποιεί την Εμπλουτισμένη Παρουσία σας στο Discord",
"AddGameDirBoxTooltip": "Εισαγάγετε μία τοποθεσία παιχνιδιών για προσθήκη στη λίστα",
"AddGameDirTooltip": "Προσθέστε μία τοποθεσία παιχνιδιών στη λίστα",
"RemoveGameDirTooltip": "Αφαιρέστε την επιλεγμένη τοποθεσία παιχνιδιών",
"CustomThemeCheckTooltip": "Ενεργοποίηση ή απενεργοποίηση προσαρμοσμένων θεμάτων στο GUI",
"CustomThemePathTooltip": "Διαδρομή προς το προσαρμοσμένο θέμα GUI",
"CustomThemeBrowseTooltip": "Αναζητήστε ένα προσαρμοσμένο θέμα GUI",
"DockModeToggleTooltip": "Ενεργοποιήστε ή απενεργοποιήστε τη λειτουργία σύνδεσης",
"DirectKeyboardTooltip": "Ενεργοποίηση ή απενεργοποίηση της \"υποστήριξης άμεσης πρόσβασης πληκτρολογίου (HID)\" (Παρέχει πρόσβαση στα παιχνίδια στο πληκτρολόγιό σας ως συσκευή εισαγωγής κειμένου)",
"DirectMouseTooltip": "Ενεργοποίηση ή απενεργοποίηση της \"υποστήριξης άμεσης πρόσβασης ποντικιού (HID)\" (Παρέχει πρόσβαση στα παιχνίδια στο ποντίκι σας ως συσκευή κατάδειξης)",
"RegionTooltip": "Αλλαγή Περιοχής Συστήματος",
"LanguageTooltip": "Αλλαγή Γλώσσας Συστήματος",
"TimezoneTooltip": "Αλλαγή Ζώνης Ώρας Συστήματος",
"TimeTooltip": "Αλλαγή Ώρας Συστήματος",
"VSyncToggleTooltip": "Ενεργοποιεί ή απενεργοποιεί τον κατακόρυφο συγχρονισμό",
"PptcToggleTooltip": "Ενεργοποιεί ή απενεργοποιεί το PPTC",
"FsIntegrityToggleTooltip": "Ενεργοποιεί τους ελέγχους ακεραιότητας σε αρχεία περιεχομένου παιχνιδιού",
"AudioBackendTooltip": "Αλλαγή ήχου υποστήριξης",
"MemoryManagerTooltip": "Αλλάξτε τον τρόπο αντιστοίχισης και πρόσβασης στη μνήμη επισκέπτη. Επηρεάζει σε μεγάλο βαθμό την απόδοση της προσομοίωσης της CPU.",
"MemoryManagerSoftwareTooltip": "Χρησιμοποιήστε έναν πίνακα σελίδων λογισμικού για τη μετάφραση διευθύνσεων. Υψηλότερη ακρίβεια αλλά πιο αργή απόδοση.",
"MemoryManagerHostTooltip": "Απευθείας αντιστοίχιση της μνήμης στον χώρο διευθύνσεων υπολογιστή υποδοχής. Πολύ πιο γρήγορη μεταγλώττιση και εκτέλεση JIT.",
"MemoryManagerUnsafeTooltip": "Απευθείας χαρτογράφηση της μνήμης, αλλά μην καλύπτετε τη διεύθυνση εντός του χώρου διευθύνσεων επισκέπτη πριν από την πρόσβαση. Πιο γρήγορα, αλλά με κόστος ασφάλειας. Η εφαρμογή μπορεί να έχει πρόσβαση στη μνήμη από οπουδήποτε στο Ryujinx, επομένως εκτελείτε μόνο προγράμματα που εμπιστεύεστε με αυτήν τη λειτουργία.",
"DRamTooltip": "Επεκτείνει την ποσότητα της μνήμης στο εξομοιούμενο σύστημα από 4 GiB σε 6 GiB",
"IgnoreMissingServicesTooltip": "Ενεργοποίηση ή απενεργοποίηση της αγνοώησης για υπηρεσίες που λείπουν",
"GraphicsBackendThreadingTooltip": "Ενεργοποίηση Πολυνηματικής Επεξεργασίας Γραφικών",
"GalThreadingTooltip": "Εκτελεί εντολές γραφικών σε ένα δεύτερο νήμα. Επιτρέπει την πολυνηματική μεταγλώττιση Shader σε χρόνο εκτέλεσης, μειώνει το τρεμόπαιγμα και βελτιώνει την απόδοση των προγραμμάτων οδήγησης χωρίς τη δική τους υποστήριξη πολλαπλών νημάτων. Ποικίλες κορυφαίες επιδόσεις σε προγράμματα οδήγησης με multithreading. Μπορεί να χρειαστεί επανεκκίνηση του Ryujinx για να απενεργοποιήσετε σωστά την ενσωματωμένη λειτουργία πολλαπλών νημάτων του προγράμματος οδήγησης ή ίσως χρειαστεί να το κάνετε χειροκίνητα για να έχετε την καλύτερη απόδοση.",
"ShaderCacheToggleTooltip": "Ενεργοποιεί ή απενεργοποιεί την Προσωρινή Μνήμη Shader",
"ResolutionScaleTooltip": "Κλίμακα ανάλυσης που εφαρμόστηκε σε ισχύοντες στόχους απόδοσης",
"ResolutionScaleEntryTooltip": "Κλίμακα ανάλυσης κινητής υποδιαστολής, όπως 1,5. Οι μη αναπόσπαστες τιμές είναι πιθανό να προκαλέσουν προβλήματα ή σφάλματα.",
"AnisotropyTooltip": "Επίπεδο Ανισότροπου Φιλτραρίσματος (ρυθμίστε το στο Αυτόματο για να χρησιμοποιηθεί η τιμή που ζητήθηκε από το παιχνίδι)",
"AspectRatioTooltip": "Λόγος διαστάσεων που εφαρμόστηκε στο παράθυρο απόδοσης.",
"ShaderDumpPathTooltip": "Τοποθεσία Εναπόθεσης Προσωρινής Μνήμης Shaders",
"FileLogTooltip": "Ενεργοποιεί ή απενεργοποιεί την καταγραφή σε ένα αρχείο στο δίσκο",
"StubLogTooltip": "Ενεργοποιεί την εκτύπωση μηνυμάτων καταγραφής ατελειών",
"InfoLogTooltip": "Ενεργοποιεί την εκτύπωση μηνυμάτων αρχείου καταγραφής πληροφοριών",
"WarnLogTooltip": "Ενεργοποιεί την εκτύπωση μηνυμάτων καταγραφής προειδοποιήσεων",
"ErrorLogTooltip": "Ενεργοποιεί την εκτύπωση μηνυμάτων αρχείου καταγραφής σφαλμάτων",
"TraceLogTooltip": "Ενεργοποιεί την εκτύπωση μηνυμάτων αρχείου καταγραφής ιχνών",
"GuestLogTooltip": "Ενεργοποιεί την εκτύπωση μηνυμάτων καταγραφής επισκεπτών",
"FileAccessLogTooltip": "Ενεργοποιεί την εκτύπωση μηνυμάτων αρχείου καταγραφής πρόσβασης",
"FSAccessLogModeTooltip": "Ενεργοποιεί την έξοδο καταγραφής πρόσβασης FS στην κονσόλα. Οι πιθανοί τρόποι λειτουργίας είναι 0-3",
"DeveloperOptionTooltip": "Χρησιμοποιήστε με προσοχή",
"OpenGlLogLevel": "Απαιτεί τα κατάλληλα επίπεδα καταγραφής ενεργοποιημένα",
"DebugLogTooltip": "Ενεργοποιεί την εκτύπωση μηνυμάτων αρχείου καταγραφής εντοπισμού σφαλμάτων",
"LoadApplicationFileTooltip": "Ανοίξτε έναν επιλογέα αρχείων για να επιλέξετε ένα αρχείο συμβατό με το Switch για φόρτωση",
"LoadApplicationFolderTooltip": "Ανοίξτε έναν επιλογέα αρχείων για να επιλέξετε μία μη συσκευασμένη εφαρμογή, συμβατή με το Switch για φόρτωση",
"OpenRyujinxFolderTooltip": "Ανοίξτε το φάκελο συστήματος αρχείων Ryujinx",
"OpenRyujinxLogsTooltip": "Ανοίξτε το φάκελο στον οποίο διατηρούνται τα αρχεία καταγραφής",
"ExitTooltip": "Έξοδος από το Ryujinx",
"OpenSettingsTooltip": "Ανοίξτε το παράθυρο Ρυθμίσεων",
"OpenProfileManagerTooltip": "Ανοίξτε το παράθυρο Διαχείρισης Προφίλ Χρήστη",
"StopEmulationTooltip": "Σταματήστε την εξομοίωση του τρέχοντος παιχνιδιού και επιστρέψτε στην επιλογή παιχνιδιού",
"CheckUpdatesTooltip": "Ελέγξτε για ενημερώσεις του Ryujinx",
"OpenAboutTooltip": "Ανοίξτε το Παράθυρο Σχετικά",
"GridSize": "Μέγεθος Πλέγματος",
"GridSizeTooltip": "Αλλαγή μεγέθους στοιχείων πλέγματος",
"SettingsTabSystemSystemLanguageBrazilianPortuguese": "Πορτογαλικά Βραζιλίας",
"AboutRyujinxContributorsButtonHeader": "Δείτε Όλους τους Συντελεστές",
"SettingsTabSystemAudioVolume": "Ενταση Ήχου: ",
"AudioVolumeTooltip": "Αλλαγή Έντασης Ήχου",
"SettingsTabSystemEnableInternetAccess": "Ενεργοποίηση πρόσβασης επισκέπτη στο Διαδίκτυο",
"EnableInternetAccessTooltip": "Επιτρέπει την πρόσβαση επισκέπτη στο Διαδίκτυο. Εάν ενεργοποιηθεί, η εξομοιωμένη κονσόλα Switch θα συμπεριφέρεται σαν να είναι συνδεδεμένη στο Διαδίκτυο. Λάβετε υπόψη ότι σε ορισμένες περιπτώσεις, οι εφαρμογές ενδέχεται να εξακολουθούν να έχουν πρόσβαση στο Διαδίκτυο, ακόμη και όταν αυτή η επιλογή είναι απενεργοποιημένη",
"GameListContextMenuManageCheatToolTip": "Διαχείριση Κόλπων",
"GameListContextMenuManageCheat": "Διαχείριση Κόλπων",
"ControllerSettingsStickRange": "Εύρος:",
"DialogStopEmulationTitle": "Ryujinx - Διακοπή εξομοίωσης",
"DialogStopEmulationMessage": "Είστε βέβαιοι ότι θέλετε να σταματήσετε την εξομοίωση;",
"SettingsTabCpu": "Επεξεργαστής",
"SettingsTabAudio": "Ήχος",
"SettingsTabNetwork": "Δίκτυο",
"SettingsTabNetworkConnection": "Σύνδεση δικτύου",
"SettingsTabCpuCache": "Προσωρινή Μνήμη CPU",
"SettingsTabCpuMemory": "Μνήμη CPU",
"DialogUpdaterFlatpakNotSupportedMessage": "Παρακαλούμε ενημερώστε το Ryujinx μέσω FlatHub.",
"UpdaterDisabledWarningTitle": "Ο Διαχειριστής Ενημερώσεων Είναι Απενεργοποιημένος!",
"GameListContextMenuOpenSdModsDirectory": "Άνοιγμα Της Τοποθεσίας Των Atmosphere Mods",
"GameListContextMenuOpenSdModsDirectoryToolTip": "Opens the alternative SD card Atmosphere directory which contains Application's Mods. Useful for mods that are packaged for real hardware.",
"ControllerSettingsRotate90": "Rotate 90° Clockwise",
"IconSize": "Icon Size",
"IconSizeTooltip": "Change the size of game icons",
"MenuBarOptionsShowConsole": "Show Console",
"ShaderCachePurgeError": "Error purging shader cache at {0}: {1}",
"UserErrorNoKeys": "Keys not found",
"UserErrorNoFirmware": "Firmware not found",
"UserErrorFirmwareParsingFailed": "Firmware parsing error",
"UserErrorApplicationNotFound": "Application not found",
"UserErrorUnknown": "Unknown error",
"UserErrorUndefined": "Undefined error",
"UserErrorNoKeysDescription": "Ryujinx was unable to find your 'prod.keys' file",
"UserErrorNoFirmwareDescription": "Ryujinx was unable to find any firmwares installed",
"UserErrorFirmwareParsingFailedDescription": "Ryujinx was unable to parse the provided firmware. This is usually caused by outdated keys.",
"UserErrorApplicationNotFoundDescription": "Ryujinx couldn't find a valid application at the given path.",
"UserErrorUnknownDescription": "An unknown error occured!",
"UserErrorUndefinedDescription": "An undefined error occured! This shouldn't happen, please contact a dev!",
"OpenSetupGuideMessage": "Open the Setup Guide",
"NoUpdate": "No Update",
"TitleUpdateVersionLabel": "Version {0} - {1}",
"RyujinxInfo": "Ryujinx - Info",
"RyujinxConfirm": "Ryujinx - Confirmation",
"FileDialogAllTypes": "All types",
"Never": "Never",
"SwkbdMinCharacters": "Must be at least {0} characters long",
"SwkbdMinRangeCharacters": "Must be {0}-{1} characters long",
"SoftwareKeyboard": "Software Keyboard",
"DialogControllerAppletMessagePlayerRange": "Application requests {0} player(s) with:\n\nTYPES: {1}\n\nPLAYERS: {2}\n\n{3}Please open Settings and reconfigure Input now or press Close.",
"DialogControllerAppletMessage": "Application requests exactly {0} player(s) with:\n\nTYPES: {1}\n\nPLAYERS: {2}\n\n{3}Please open Settings and reconfigure Input now or press Close.",
"DialogControllerAppletDockModeSet": "Docked mode set. Handheld is also invalid.\n\n",
"UpdaterRenaming": "Renaming Old Files...",
"UpdaterRenameFailed": "Updater was unable to rename file: {0}",
"UpdaterAddingFiles": "Adding New Files...",
"UpdaterExtracting": "Extracting Update...",
"UpdaterDownloading": "Downloading Update...",
"Game": "Game",
"Docked": "Docked",
"Handheld": "Handheld",
"ConnectionError": "Connection Error.",
"AboutPageDeveloperListMore": "{0} and more...",
"ApiError": "API Error.",
"LoadingHeading": "Loading {0}",
"CompilingPPTC": "Compiling PTC",
"CompilingShaders": "Compiling Shaders",
"AllKeyboards": "All keyboards",
"OpenFileDialogTitle": "Select a supported file to open",
"OpenFolderDialogTitle": "Select a folder with an unpacked game",
"AllSupportedFormats": "All Supported Formats",
"RyujinxUpdater": "Ryujinx Updater",
"SettingsTabHotkeys": "Keyboard Hotkeys",
"SettingsTabHotkeysHotkeys": "Keyboard Hotkeys",
"SettingsTabHotkeysToggleVsyncHotkey": "Toggle VSync:",
"SettingsTabHotkeysScreenshotHotkey": "Screenshot:",
"SettingsTabHotkeysShowUiHotkey": "Show UI:",
"SettingsTabHotkeysPauseHotkey": "Pause:",
"SettingsTabHotkeysToggleMuteHotkey": "Mute:",
"ControllerMotionTitle": "Motion Control Settings",
"ControllerRumbleTitle": "Rumble Settings",
"SettingsSelectThemeFileDialogTitle": "Select Theme File",
"SettingsXamlThemeFile": "Xaml Theme File",
"AvatarWindowTitle": "Manage Accounts - Avatar",
"Amiibo": "Amiibo",
"Unknown": "Unknown",
"Usage": "Usage",
"Writable": "Writable",
"SelectDlcDialogTitle": "Select DLC files",
"SelectUpdateDialogTitle": "Select update files",
"UserProfileWindowTitle": "User Profiles Manager",
"CheatWindowTitle": "Cheats Manager",
"DlcWindowTitle": "Downloadable Content Manager",
"UpdateWindowTitle": "Title Update Manager",
"CheatWindowHeading": "Cheats Available for {0} [{1}]",
"DlcWindowHeading": "{0} Downloadable Content(s) available for {1} ({2})",
"UserProfilesEditProfile": "Edit Selected",
"Cancel": "Cancel",
"Save": "Save",
"Discard": "Discard",
"UserProfilesSetProfileImage": "Set Profile Image",
"UserProfileEmptyNameError": "Name is required",
"UserProfileNoImageError": "Profile image must be set",
"GameUpdateWindowHeading": "{0} Update(s) available for {1} ({2})",
"SettingsTabHotkeysResScaleUpHotkey": "Increase resolution:",
"SettingsTabHotkeysResScaleDownHotkey": "Decrease resolution:",
"UserProfilesName": "Name:",
"UserProfilesUserId": "User Id:",
"SettingsTabGraphicsBackend": "Graphics Backend",
"SettingsTabGraphicsBackendTooltip": "Graphics Backend to use",
"SettingsEnableTextureRecompression": "Enable Texture Recompression",
"SettingsEnableTextureRecompressionTooltip": "Compresses certain textures in order to reduce VRAM usage.\n\nRecommended for use with GPUs that have less than 4GiB VRAM.\n\nLeave OFF if unsure.",
"SettingsTabGraphicsPreferredGpu": "Preferred GPU",
"SettingsTabGraphicsPreferredGpuTooltip": "Select the graphics card that will be used with the Vulkan graphics backend.\n\nDoes not affect the GPU that OpenGL will use.\n\nSet to the GPU flagged as \"dGPU\" if unsure. If there isn't one, leave untouched.",
"SettingsAppRequiredRestartMessage": "Ryujinx Restart Required",
"SettingsGpuBackendRestartMessage": "Graphics Backend or GPU settings have been modified. This will require a restart to be applied",
"SettingsGpuBackendRestartSubMessage": "Do you want to restart now?",
"RyujinxUpdaterMessage": "Do you want to update Ryujinx to the latest version?",
"SettingsTabHotkeysVolumeUpHotkey": "Increase Volume:",
"SettingsTabHotkeysVolumeDownHotkey": "Decrease Volume:",
"SettingsEnableMacroHLE": "Enable Macro HLE",
"SettingsEnableMacroHLETooltip": "High-level emulation of GPU Macro code.\n\nImproves performance, but may cause graphical glitches in some games.\n\nLeave ON if unsure.",
"VolumeShort": "Vol",
"UserProfilesManageSaves": "Manage Saves",
"DeleteUserSave": "Do you want to delete user save for this game?",
"IrreversibleActionNote": "This action is not reversible.",
"SaveManagerHeading": "Manage Saves for {0}",
"SaveManagerTitle": "Save Manager",
"Name": "Name",
"Size": "Size",
"Search": "Search",
"UserProfilesRecoverLostAccounts": "Recover Lost Accounts",
"Recover": "Recover",
"UserProfilesRecoverHeading": "Saves were found for the following accounts"
}

View File

@@ -1,613 +0,0 @@
{
"MenuBarFileOpenApplet": "Open Applet",
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Open Mii Editor Applet in Standalone mode",
"SettingsTabInputDirectMouseAccess": "Direct Mouse Access",
"SettingsTabSystemMemoryManagerMode": "Memory Manager Mode:",
"SettingsTabSystemMemoryManagerModeSoftware": "Software",
"SettingsTabSystemMemoryManagerModeHost": "Host (fast)",
"SettingsTabSystemMemoryManagerModeHostUnchecked": "Host Unchecked (fastest, unsafe)",
"MenuBarFile": "_File",
"MenuBarFileOpenFromFile": "_Load Application From File",
"MenuBarFileOpenUnpacked": "Load _Unpacked Game",
"MenuBarFileOpenEmuFolder": "Open Ryujinx Folder",
"MenuBarFileOpenLogsFolder": "Open Logs Folder",
"MenuBarFileExit": "_Exit",
"MenuBarOptions": "Options",
"MenuBarOptionsToggleFullscreen": "Toggle Fullscreen",
"MenuBarOptionsStartGamesInFullscreen": "Start Games in Fullscreen Mode",
"MenuBarOptionsStopEmulation": "Stop Emulation",
"MenuBarOptionsSettings": "_Settings",
"MenuBarOptionsManageUserProfiles": "_Manage User Profiles",
"MenuBarActions": "_Actions",
"MenuBarOptionsSimulateWakeUpMessage": "Simulate Wake-up message",
"MenuBarActionsScanAmiibo": "Scan An Amiibo",
"MenuBarTools": "_Tools",
"MenuBarToolsInstallFirmware": "Install Firmware",
"MenuBarFileToolsInstallFirmwareFromFile": "Install a firmware from XCI or ZIP",
"MenuBarFileToolsInstallFirmwareFromDirectory": "Install a firmware from a directory",
"MenuBarHelp": "Help",
"MenuBarHelpCheckForUpdates": "Check for Updates",
"MenuBarHelpAbout": "About",
"MenuSearch": "Search...",
"GameListHeaderFavorite": "Fav",
"GameListHeaderIcon": "Icon",
"GameListHeaderApplication": "Name",
"GameListHeaderDeveloper": "Developer",
"GameListHeaderVersion": "Version",
"GameListHeaderTimePlayed": "Play Time",
"GameListHeaderLastPlayed": "Last Played",
"GameListHeaderFileExtension": "File Ext",
"GameListHeaderFileSize": "File Size",
"GameListHeaderPath": "Path",
"GameListContextMenuOpenUserSaveDirectory": "Open User Save Directory",
"GameListContextMenuOpenUserSaveDirectoryToolTip": "Opens the directory which contains Application's User Save",
"GameListContextMenuOpenUserDeviceDirectory": "Open User Device Directory",
"GameListContextMenuOpenUserDeviceDirectoryToolTip": "Opens the directory which contains Application's Device Save",
"GameListContextMenuOpenUserBcatDirectory": "Open User BCAT Directory",
"GameListContextMenuOpenUserBcatDirectoryToolTip": "Opens the directory which contains Application's BCAT Save",
"GameListContextMenuManageTitleUpdates": "Manage Title Updates",
"GameListContextMenuManageTitleUpdatesToolTip": "Opens the Title Update management window",
"GameListContextMenuManageDlc": "Manage DLC",
"GameListContextMenuManageDlcToolTip": "Opens the DLC management window",
"GameListContextMenuOpenModsDirectory": "Open Mods Directory",
"GameListContextMenuOpenModsDirectoryToolTip": "Opens the directory which contains Application's Mods",
"GameListContextMenuCacheManagement": "Cache Management",
"GameListContextMenuCacheManagementPurgePptc": "Queue PPTC Rebuild",
"GameListContextMenuCacheManagementPurgePptcToolTip": "Trigger PPTC to rebuild at boot time on the next game launch",
"GameListContextMenuCacheManagementPurgeShaderCache": "Purge Shader Cache",
"GameListContextMenuCacheManagementPurgeShaderCacheToolTip": "Deletes Application's shader cache",
"GameListContextMenuCacheManagementOpenPptcDirectory": "Open PPTC Directory",
"GameListContextMenuCacheManagementOpenPptcDirectoryToolTip": "Opens the directory which contains Application's PPTC cache",
"GameListContextMenuCacheManagementOpenShaderCacheDirectory": "Open Shader Cache Directory",
"GameListContextMenuCacheManagementOpenShaderCacheDirectoryToolTip": "Opens the directory which contains Application's shader cache",
"GameListContextMenuExtractData": "Extract Data",
"GameListContextMenuExtractDataExeFS": "ExeFS",
"GameListContextMenuExtractDataExeFSToolTip": "Extract the ExeFS section from Application's current config (including updates)",
"GameListContextMenuExtractDataRomFS": "RomFS",
"GameListContextMenuExtractDataRomFSToolTip": "Extract the RomFS section from Application's current config (including updates)",
"GameListContextMenuExtractDataLogo": "Logo",
"GameListContextMenuExtractDataLogoToolTip": "Extract the Logo section from Application's current config (including updates)",
"StatusBarGamesLoaded": "{0}/{1} Games Loaded",
"StatusBarSystemVersion": "System Version: {0}",
"Settings": "Settings",
"SettingsTabGeneral": "User Interface",
"SettingsTabGeneralGeneral": "General",
"SettingsTabGeneralEnableDiscordRichPresence": "Enable Discord Rich Presence",
"SettingsTabGeneralCheckUpdatesOnLaunch": "Check for Updates on Launch",
"SettingsTabGeneralShowConfirmExitDialog": "Show \"Confirm Exit\" Dialog",
"SettingsTabGeneralHideCursorOnIdle": "Hide Cursor on Idle",
"SettingsTabGeneralGameDirectories": "Game Directories",
"SettingsTabGeneralAdd": "Add",
"SettingsTabGeneralRemove": "Remove",
"SettingsTabSystem": "System",
"SettingsTabSystemCore": "Core",
"SettingsTabSystemSystemRegion": "System Region:",
"SettingsTabSystemSystemRegionJapan": "Japan",
"SettingsTabSystemSystemRegionUSA": "USA",
"SettingsTabSystemSystemRegionEurope": "Europe",
"SettingsTabSystemSystemRegionAustralia": "Australia",
"SettingsTabSystemSystemRegionChina": "China",
"SettingsTabSystemSystemRegionKorea": "Korea",
"SettingsTabSystemSystemRegionTaiwan": "Taiwan",
"SettingsTabSystemSystemLanguage": "System Language:",
"SettingsTabSystemSystemLanguageJapanese": "Japanese",
"SettingsTabSystemSystemLanguageAmericanEnglish": "American English",
"SettingsTabSystemSystemLanguageFrench": "French",
"SettingsTabSystemSystemLanguageGerman": "German",
"SettingsTabSystemSystemLanguageItalian": "Italian",
"SettingsTabSystemSystemLanguageSpanish": "Spanish",
"SettingsTabSystemSystemLanguageChinese": "Chinese",
"SettingsTabSystemSystemLanguageKorean": "Korean",
"SettingsTabSystemSystemLanguageDutch": "Dutch",
"SettingsTabSystemSystemLanguagePortuguese": "Portuguese",
"SettingsTabSystemSystemLanguageRussian": "Russian",
"SettingsTabSystemSystemLanguageTaiwanese": "Taiwanese",
"SettingsTabSystemSystemLanguageBritishEnglish": "British English",
"SettingsTabSystemSystemLanguageCanadianFrench": "Canadian French",
"SettingsTabSystemSystemLanguageLatinAmericanSpanish": "Latin American Spanish",
"SettingsTabSystemSystemLanguageSimplifiedChinese": "Simplified Chinese",
"SettingsTabSystemSystemLanguageTraditionalChinese": "Traditional Chinese",
"SettingsTabSystemSystemTimeZone": "System TimeZone:",
"SettingsTabSystemSystemTime": "System Time:",
"SettingsTabSystemEnableVsync": "VSync",
"SettingsTabSystemEnablePptc": "PPTC (Profiled Persistent Translation Cache)",
"SettingsTabSystemEnableFsIntegrityChecks": "FS Integrity Checks",
"SettingsTabSystemAudioBackend": "Audio Backend:",
"SettingsTabSystemAudioBackendDummy": "Dummy",
"SettingsTabSystemAudioBackendOpenAL": "OpenAL",
"SettingsTabSystemAudioBackendSoundIO": "SoundIO",
"SettingsTabSystemAudioBackendSDL2": "SDL2",
"SettingsTabSystemHacks": "Hacks",
"SettingsTabSystemHacksNote": " (may cause instability)",
"SettingsTabSystemExpandDramSize": "Use alternative memory layout (Developers)",
"SettingsTabSystemIgnoreMissingServices": "Ignore Missing Services",
"SettingsTabGraphics": "Graphics",
"SettingsTabGraphicsAPI": "Graphics API",
"SettingsTabGraphicsEnableShaderCache": "Enable Shader Cache",
"SettingsTabGraphicsAnisotropicFiltering": "Anisotropic Filtering:",
"SettingsTabGraphicsAnisotropicFilteringAuto": "Auto",
"SettingsTabGraphicsAnisotropicFiltering2x": "2x",
"SettingsTabGraphicsAnisotropicFiltering4x": "4x",
"SettingsTabGraphicsAnisotropicFiltering8x": "8x",
"SettingsTabGraphicsAnisotropicFiltering16x": "16x",
"SettingsTabGraphicsResolutionScale": "Resolution Scale:",
"SettingsTabGraphicsResolutionScaleCustom": "Custom (Not recommended)",
"SettingsTabGraphicsResolutionScaleNative": "Native (720p/1080p)",
"SettingsTabGraphicsResolutionScale2x": "2x (1440p/2160p)",
"SettingsTabGraphicsResolutionScale3x": "3x (2160p/3240p)",
"SettingsTabGraphicsResolutionScale4x": "4x (2880p/4320p)",
"SettingsTabGraphicsAspectRatio": "Aspect Ratio:",
"SettingsTabGraphicsAspectRatio4x3": "4:3",
"SettingsTabGraphicsAspectRatio16x9": "16:9",
"SettingsTabGraphicsAspectRatio16x10": "16:10",
"SettingsTabGraphicsAspectRatio21x9": "21:9",
"SettingsTabGraphicsAspectRatio32x9": "32:9",
"SettingsTabGraphicsAspectRatioStretch": "Stretch to Fit Window",
"SettingsTabGraphicsDeveloperOptions": "Developer Options",
"SettingsTabGraphicsShaderDumpPath": "Graphics Shader Dump Path:",
"SettingsTabLogging": "Logging",
"SettingsTabLoggingLogging": "Logging",
"SettingsTabLoggingEnableLoggingToFile": "Enable Logging to File",
"SettingsTabLoggingEnableStubLogs": "Enable Stub Logs",
"SettingsTabLoggingEnableInfoLogs": "Enable Info Logs",
"SettingsTabLoggingEnableWarningLogs": "Enable Warning Logs",
"SettingsTabLoggingEnableErrorLogs": "Enable Error Logs",
"SettingsTabLoggingEnableTraceLogs": "Enable Trace Logs",
"SettingsTabLoggingEnableGuestLogs": "Enable Guest Logs",
"SettingsTabLoggingEnableFsAccessLogs": "Enable Fs Access Logs",
"SettingsTabLoggingFsGlobalAccessLogMode": "Fs Global Access Log Mode:",
"SettingsTabLoggingDeveloperOptions": "Developer Options (WARNING: Will reduce performance)",
"SettingsTabLoggingGraphicsBackendLogLevel": "Graphics Backend Log Level:",
"SettingsTabLoggingGraphicsBackendLogLevelNone": "None",
"SettingsTabLoggingGraphicsBackendLogLevelError": "Error",
"SettingsTabLoggingGraphicsBackendLogLevelPerformance": "Slowdowns",
"SettingsTabLoggingGraphicsBackendLogLevelAll": "All",
"SettingsTabLoggingEnableDebugLogs": "Enable Debug Logs",
"SettingsTabInput": "Input",
"SettingsTabInputEnableDockedMode": "Docked Mode",
"SettingsTabInputDirectKeyboardAccess": "Direct Keyboard Access",
"SettingsButtonSave": "Save",
"SettingsButtonClose": "Close",
"SettingsButtonOk": "OK",
"SettingsButtonCancel": "Cancel",
"SettingsButtonApply": "Apply",
"ControllerSettingsPlayer": "Player",
"ControllerSettingsPlayer1": "Player 1",
"ControllerSettingsPlayer2": "Player 2",
"ControllerSettingsPlayer3": "Player 3",
"ControllerSettingsPlayer4": "Player 4",
"ControllerSettingsPlayer5": "Player 5",
"ControllerSettingsPlayer6": "Player 6",
"ControllerSettingsPlayer7": "Player 7",
"ControllerSettingsPlayer8": "Player 8",
"ControllerSettingsHandheld": "Handheld",
"ControllerSettingsInputDevice": "Input Device",
"ControllerSettingsRefresh": "Refresh",
"ControllerSettingsDeviceDisabled": "Disabled",
"ControllerSettingsControllerType": "Controller Type",
"ControllerSettingsControllerTypeHandheld": "Handheld",
"ControllerSettingsControllerTypeProController": "Pro Controller",
"ControllerSettingsControllerTypeJoyConPair": "JoyCon Pair",
"ControllerSettingsControllerTypeJoyConLeft": "JoyCon Left",
"ControllerSettingsControllerTypeJoyConRight": "JoyCon Right",
"ControllerSettingsProfile": "Profile",
"ControllerSettingsProfileDefault": "Default",
"ControllerSettingsLoad": "Load",
"ControllerSettingsAdd": "Add",
"ControllerSettingsRemove": "Remove",
"ControllerSettingsButtons": "Buttons",
"ControllerSettingsButtonA": "A",
"ControllerSettingsButtonB": "B",
"ControllerSettingsButtonX": "X",
"ControllerSettingsButtonY": "Y",
"ControllerSettingsButtonPlus": "+",
"ControllerSettingsButtonMinus": "-",
"ControllerSettingsDPad": "Directional Pad",
"ControllerSettingsDPadUp": "Up",
"ControllerSettingsDPadDown": "Down",
"ControllerSettingsDPadLeft": "Left",
"ControllerSettingsDPadRight": "Right",
"ControllerSettingsLStick": "Left Stick",
"ControllerSettingsLStickButton": "Button",
"ControllerSettingsLStickUp": "Up",
"ControllerSettingsLStickDown": "Down",
"ControllerSettingsLStickLeft": "Left",
"ControllerSettingsLStickRight": "Right",
"ControllerSettingsLStickStick": "Stick",
"ControllerSettingsLStickInvertXAxis": "Invert Stick X",
"ControllerSettingsLStickInvertYAxis": "Invert Stick Y",
"ControllerSettingsLStickDeadzone": "Deadzone:",
"ControllerSettingsRStick": "Right Stick",
"ControllerSettingsRStickButton": "Button",
"ControllerSettingsRStickUp": "Up",
"ControllerSettingsRStickDown": "Down",
"ControllerSettingsRStickLeft": "Left",
"ControllerSettingsRStickRight": "Right",
"ControllerSettingsRStickStick": "Stick",
"ControllerSettingsRStickInvertXAxis": "Invert Stick X",
"ControllerSettingsRStickInvertYAxis": "Invert Stick Y",
"ControllerSettingsRStickDeadzone": "Deadzone:",
"ControllerSettingsTriggersLeft": "Triggers Left",
"ControllerSettingsTriggersRight": "Triggers Right",
"ControllerSettingsTriggersButtonsLeft": "Trigger Buttons Left",
"ControllerSettingsTriggersButtonsRight": "Trigger Buttons Right",
"ControllerSettingsTriggers": "Triggers",
"ControllerSettingsTriggerL": "L",
"ControllerSettingsTriggerR": "R",
"ControllerSettingsTriggerZL": "ZL",
"ControllerSettingsTriggerZR": "ZR",
"ControllerSettingsLeftSL": "SL",
"ControllerSettingsLeftSR": "SR",
"ControllerSettingsRightSL": "SL",
"ControllerSettingsRightSR": "SR",
"ControllerSettingsExtraButtonsLeft": "Buttons Left",
"ControllerSettingsExtraButtonsRight": "Buttons Right",
"ControllerSettingsMisc": "Miscellaneous",
"ControllerSettingsTriggerThreshold": "Trigger Threshold:",
"ControllerSettingsMotion": "Motion",
"ControllerSettingsMotionUseCemuhookCompatibleMotion": "Use CemuHook compatible motion",
"ControllerSettingsMotionControllerSlot": "Controller Slot:",
"ControllerSettingsMotionMirrorInput": "Mirror Input",
"ControllerSettingsMotionRightJoyConSlot": "Right JoyCon Slot:",
"ControllerSettingsMotionServerHost": "Server Host:",
"ControllerSettingsMotionGyroSensitivity": "Gyro Sensitivity:",
"ControllerSettingsMotionGyroDeadzone": "Gyro Deadzone:",
"ControllerSettingsSave": "Save",
"ControllerSettingsClose": "Close",
"UserProfilesSelectedUserProfile": "Selected User Profile:",
"UserProfilesSaveProfileName": "Save Profile Name",
"UserProfilesChangeProfileImage": "Change Profile Image",
"UserProfilesAvailableUserProfiles": "Available User Profiles:",
"UserProfilesAddNewProfile": "Create Profile",
"UserProfilesDeleteSelectedProfile": "Delete Selected",
"UserProfilesClose": "Close",
"ProfileImageSelectionTitle": "Profile Image Selection",
"ProfileImageSelectionHeader": "Choose a profile Image",
"ProfileImageSelectionNote": "You may import a custom profile image, or select an avatar from system firmware",
"ProfileImageSelectionImportImage": "Import Image File",
"ProfileImageSelectionSelectAvatar": "Select Firmware Avatar",
"InputDialogTitle": "Input Dialog",
"InputDialogOk": "OK",
"InputDialogCancel": "Cancel",
"InputDialogAddNewProfileTitle": "Choose the Profile Name",
"InputDialogAddNewProfileHeader": "Please Enter a Profile Name",
"InputDialogAddNewProfileSubtext": "(Max Length: {0})",
"AvatarChoose": "Choose",
"AvatarSetBackgroundColor": "Set Background Color",
"AvatarClose": "Close",
"ControllerSettingsLoadProfileToolTip": "Load Profile",
"ControllerSettingsAddProfileToolTip": "Add Profile",
"ControllerSettingsRemoveProfileToolTip": "Remove Profile",
"ControllerSettingsSaveProfileToolTip": "Save Profile",
"MenuBarFileToolsTakeScreenshot": "Take Screenshot",
"MenuBarFileToolsHideUi": "Hide UI",
"GameListContextMenuToggleFavorite": "Toggle Favorite",
"GameListContextMenuToggleFavoriteToolTip": "Toggle Favorite status of Game",
"SettingsTabGeneralTheme": "Theme",
"SettingsTabGeneralThemeCustomTheme": "Custom Theme Path",
"SettingsTabGeneralThemeBaseStyle": "Base Style",
"SettingsTabGeneralThemeBaseStyleDark": "Dark",
"SettingsTabGeneralThemeBaseStyleLight": "Light",
"SettingsTabGeneralThemeEnableCustomTheme": "Enable Custom Theme",
"ButtonBrowse": "Browse",
"ControllerSettingsConfigureGeneral": "Configure",
"ControllerSettingsRumble": "Rumble",
"ControllerSettingsRumbleStrongMultiplier": "Strong Rumble Multiplier",
"ControllerSettingsRumbleWeakMultiplier": "Weak Rumble Multiplier",
"DialogMessageSaveNotAvailableMessage": "There is no savedata for {0} [{1:x16}]",
"DialogMessageSaveNotAvailableCreateSaveMessage": "Would you like to create savedata for this game?",
"DialogConfirmationTitle": "Ryujinx - Confirmation",
"DialogUpdaterTitle": "Ryujinx - Updater",
"DialogErrorTitle": "Ryujinx - Error",
"DialogWarningTitle": "Ryujinx - Warning",
"DialogExitTitle": "Ryujinx - Exit",
"DialogErrorMessage": "Ryujinx has encountered an error",
"DialogExitMessage": "Are you sure you want to close Ryujinx?",
"DialogExitSubMessage": "All unsaved data will be lost!",
"DialogMessageCreateSaveErrorMessage": "There was an error creating the specified savedata: {0}",
"DialogMessageFindSaveErrorMessage": "There was an error finding the specified savedata: {0}",
"FolderDialogExtractTitle": "Choose the folder to extract into",
"DialogNcaExtractionMessage": "Extracting {0} section from {1}...",
"DialogNcaExtractionTitle": "Ryujinx - NCA Section Extractor",
"DialogNcaExtractionMainNcaNotFoundErrorMessage": "Extraction failure. The main NCA was not present in the selected file.",
"DialogNcaExtractionCheckLogErrorMessage": "Extraction failure. Read the log file for further information.",
"DialogNcaExtractionSuccessMessage": "Extraction completed successfully.",
"DialogUpdaterConvertFailedMessage": "Failed to convert the current Ryujinx version.",
"DialogUpdaterCancelUpdateMessage": "Cancelling Update!",
"DialogUpdaterAlreadyOnLatestVersionMessage": "You are already using the most updated version of Ryujinx!",
"DialogUpdaterFailedToGetVersionMessage": "An error has occurred when trying to get release information from GitHub Release. This can be caused if a new release is being compiled by GitHub Actions. Try again in a few minutes.",
"DialogUpdaterConvertFailedGithubMessage": "Failed to convert the received Ryujinx version from Github Release.",
"DialogUpdaterDownloadingMessage": "Downloading Update...",
"DialogUpdaterExtractionMessage": "Extracting Update...",
"DialogUpdaterRenamingMessage": "Renaming Update...",
"DialogUpdaterAddingFilesMessage": "Adding New Update...",
"DialogUpdaterCompleteMessage": "Update Complete!",
"DialogUpdaterRestartMessage": "Do you want to restart Ryujinx now?",
"DialogUpdaterArchNotSupportedMessage": "You are not running a supported system architecture!",
"DialogUpdaterArchNotSupportedSubMessage": "(Only x64 systems are supported!)",
"DialogUpdaterNoInternetMessage": "You are not connected to the Internet!",
"DialogUpdaterNoInternetSubMessage": "Please verify that you have a working Internet connection!",
"DialogUpdaterDirtyBuildMessage": "You Cannot update a Dirty build of Ryujinx!",
"DialogUpdaterDirtyBuildSubMessage": "Please download Ryujinx at https://ryujinx.org/ if you are looking for a supported version.",
"DialogRestartRequiredMessage": "Restart Required",
"DialogThemeRestartMessage": "Theme has been saved. A restart is needed to apply the theme.",
"DialogThemeRestartSubMessage": "Do you want to restart",
"DialogFirmwareInstallEmbeddedMessage": "Would you like to install the firmware embedded in this game? (Firmware {0})",
"DialogFirmwareInstallEmbeddedSuccessMessage": "No installed firmware was found but Ryujinx was able to install firmware {0} from the provided game.\\nThe emulator will now start.",
"DialogFirmwareNoFirmwareInstalledMessage": "No Firmware Installed",
"DialogFirmwareInstalledMessage": "Firmware {0} was installed",
"DialogOpenSettingsWindowLabel": "Open Settings Window",
"DialogControllerAppletTitle": "Controller Applet",
"DialogMessageDialogErrorExceptionMessage": "Error displaying Message Dialog: {0}",
"DialogSoftwareKeyboardErrorExceptionMessage": "Error displaying Software Keyboard: {0}",
"DialogErrorAppletErrorExceptionMessage": "Error displaying ErrorApplet Dialog: {0}",
"DialogUserErrorDialogMessage": "{0}: {1}",
"DialogUserErrorDialogInfoMessage": "\nFor more information on how to fix this error, follow our Setup Guide.",
"DialogUserErrorDialogTitle": "Ryujinx Error ({0})",
"DialogAmiiboApiTitle": "Amiibo API",
"DialogAmiiboApiFailFetchMessage": "An error occured while fetching information from the API.",
"DialogAmiiboApiConnectErrorMessage": "Unable to connect to Amiibo API server. The service may be down or you may need to verify your internet connection is online.",
"DialogProfileInvalidProfileErrorMessage": "Profile {0} is incompatible with the current input configuration system.",
"DialogProfileDefaultProfileOverwriteErrorMessage": "Default Profile can not be overwritten",
"DialogProfileDeleteProfileTitle": "Deleting Profile",
"DialogProfileDeleteProfileMessage": "This action is irreversible, are you sure you want to continue?",
"DialogWarning": "Warning",
"DialogPPTCDeletionMessage": "You are about to queue a PPTC rebuild on the next boot of:\n\n{0}\n\nAre you sure you want to proceed?",
"DialogPPTCDeletionErrorMessage": "Error purging PPTC cache at {0}: {1}",
"DialogShaderDeletionMessage": "You are about to delete the Shader cache for :\n\n{0}\n\nAre you sure you want to proceed?",
"DialogShaderDeletionErrorMessage": "Error purging Shader cache at {0}: {1}",
"DialogRyujinxErrorMessage": "Ryujinx has encountered an error",
"DialogInvalidTitleIdErrorMessage": "UI error: The selected game did not have a valid title ID",
"DialogFirmwareInstallerFirmwareNotFoundErrorMessage": "A valid system firmware was not found in {0}.",
"DialogFirmwareInstallerFirmwareInstallTitle": "Install Firmware {0}",
"DialogFirmwareInstallerFirmwareInstallMessage": "System version {0} will be installed.",
"DialogFirmwareInstallerFirmwareInstallSubMessage": "\n\nThis will replace the current system version {0}.",
"DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\nDo you want to continue?",
"DialogFirmwareInstallerFirmwareInstallWaitMessage": "Installing firmware...",
"DialogFirmwareInstallerFirmwareInstallSuccessMessage": "System version {0} successfully installed.",
"DialogUserProfileDeletionWarningMessage": "There would be no other profiles to be opened if selected profile is deleted",
"DialogUserProfileDeletionConfirmMessage": "Do you want to delete the selected profile",
"DialogControllerSettingsModifiedConfirmMessage": "The current controller settings has been updated.",
"DialogControllerSettingsModifiedConfirmSubMessage": "Do you want to save?",
"DialogDlcLoadNcaErrorMessage": "{0}. Errored File: {1}",
"DialogDlcNoDlcErrorMessage": "The specified file does not contain a DLC for the selected title!",
"DialogPerformanceCheckLoggingEnabledMessage": "You have trace logging enabled, which is designed to be used by developers only.",
"DialogPerformanceCheckLoggingEnabledConfirmMessage": "For optimal performance, it's recommended to disable trace logging. Would you like to disable trace logging now?",
"DialogPerformanceCheckShaderDumpEnabledMessage": "You have shader dumping enabled, which is designed to be used by developers only.",
"DialogPerformanceCheckShaderDumpEnabledConfirmMessage": "For optimal performance, it's recommended to disable shader dumping. Would you like to disable shader dumping now?",
"DialogLoadAppGameAlreadyLoadedMessage": "A game has already been loaded",
"DialogLoadAppGameAlreadyLoadedSubMessage": "Please stop emulation or close the emulator before launching another game.",
"DialogUpdateAddUpdateErrorMessage": "The specified file does not contain an update for the selected title!",
"DialogSettingsBackendThreadingWarningTitle": "Warning - Backend Threading",
"DialogSettingsBackendThreadingWarningMessage": "Ryujinx must be restarted after changing this option for it to apply fully. Depending on your platform, you may need to manually disable your driver's own multithreading when using Ryujinx's.",
"SettingsTabGraphicsFeaturesOptions": "Features",
"SettingsTabGraphicsBackendMultithreading": "Graphics Backend Multithreading:",
"CommonAuto": "Auto",
"CommonOff": "Off",
"CommonOn": "On",
"InputDialogYes": "Yes",
"InputDialogNo": "No",
"DialogProfileInvalidProfileNameErrorMessage": "The file name contains invalid characters. Please try again.",
"MenuBarOptionsPauseEmulation": "Pause",
"MenuBarOptionsResumeEmulation": "Resume",
"AboutUrlTooltipMessage": "Click to open the Ryujinx website in your default browser.",
"AboutDisclaimerMessage": "Ryujinx is not affiliated with Nintendo™,\nor any of its partners, in any way.",
"AboutAmiiboDisclaimerMessage": "AmiiboAPI (www.amiiboapi.com) is used\nin our Amiibo emulation.",
"AboutPatreonUrlTooltipMessage": "Click to open the Ryujinx Patreon page in your default browser.",
"AboutGithubUrlTooltipMessage": "Click to open the Ryujinx GitHub page in your default browser.",
"AboutDiscordUrlTooltipMessage": "Click to open an invite to the Ryujinx Discord server in your default browser.",
"AboutTwitterUrlTooltipMessage": "Click to open the Ryujinx Twitter page in your default browser.",
"AboutRyujinxAboutTitle": "About:",
"AboutRyujinxAboutContent": "Ryujinx is an emulator for the Nintendo Switch™.\nPlease support us on Patreon.\nGet all the latest news on our Twitter or Discord.\nDevelopers interested in contributing can find out more on our GitHub or Discord.",
"AboutRyujinxMaintainersTitle": "Maintained By:",
"AboutRyujinxMaintainersContentTooltipMessage": "Click to open the Contributors page in your default browser.",
"AboutRyujinxSupprtersTitle": "Supported on Patreon By:",
"AmiiboSeriesLabel": "Amiibo Series",
"AmiiboCharacterLabel": "Character",
"AmiiboScanButtonLabel": "Scan It",
"AmiiboOptionsShowAllLabel": "Show All Amiibo",
"AmiiboOptionsUsRandomTagLabel": "Hack: Use Random tag Uuid",
"DlcManagerTableHeadingEnabledLabel": "Enabled",
"DlcManagerTableHeadingTitleIdLabel": "Title ID",
"DlcManagerTableHeadingContainerPathLabel": "Container Path",
"DlcManagerTableHeadingFullPathLabel": "Full Path",
"DlcManagerRemoveAllButton": "Remove All",
"DlcManagerEnableAllButton": "Enable All",
"DlcManagerDisableAllButton": "Disable All",
"MenuBarOptionsChangeLanguage": "Change Language",
"CommonSort": "Sort",
"CommonShowNames": "Show Names",
"CommonFavorite": "Favorite",
"OrderAscending": "Ascending",
"OrderDescending": "Descending",
"SettingsTabGraphicsFeatures": "Features & Enhancements",
"ErrorWindowTitle": "Error Window",
"ToggleDiscordTooltip": "Choose whether or not to display Ryujinx on your \"currently playing\" Discord activity",
"AddGameDirBoxTooltip": "Enter a game directory to add to the list",
"AddGameDirTooltip": "Add a game directory to the list",
"RemoveGameDirTooltip": "Remove selected game directory",
"CustomThemeCheckTooltip": "Use a custom Avalonia theme for the GUI to change the appearance of the emulator menus",
"CustomThemePathTooltip": "Path to custom GUI theme",
"CustomThemeBrowseTooltip": "Browse for a custom GUI theme",
"DockModeToggleTooltip": "Docked mode makes the emulated system behave as a docked Nintendo Switch. This improves graphical fidelity in most games. Conversely, disabling this will make the emulated system behave as a handheld Nintendo Switch, reducing graphics quality.\n\nConfigure player 1 controls if planning to use docked mode; configure handheld controls if planning to use handheld mode.\n\nLeave ON if unsure.",
"DirectKeyboardTooltip": "Direct keyboard access (HID) support. Provides games access to your keyboard as a text entry device.",
"DirectMouseTooltip": "Direct mouse access (HID) support. Provides games access to your mouse as a pointing device.",
"RegionTooltip": "Change System Region",
"LanguageTooltip": "Change System Language",
"TimezoneTooltip": "Change System TimeZone",
"TimeTooltip": "Change System Time",
"VSyncToggleTooltip": "Emulated console's Vertical Sync. Essentially a frame-limiter for the majority of games; disabling it may cause games to run at higher speed or make loading screens take longer or get stuck.\n\nCan be toggled in-game with a hotkey of your preference. We recommend doing this if you plan on disabling it.\n\nLeave ON if unsure.",
"PptcToggleTooltip": "Saves translated JIT functions so that they do not need to be translated every time the game loads.\n\nReduces stuttering and significantly speeds up boot times after the first boot of a game.\n\nLeave ON if unsure.",
"FsIntegrityToggleTooltip": "Checks for corrupt files when booting a game, and if corrupt files are detected, displays a hash error in the log.\n\nHas no impact on performance and is meant to help troubleshooting.\n\nLeave ON if unsure.",
"AudioBackendTooltip": "Changes the backend used to render audio.\n\nSDL2 is the preferred one, while OpenAL and SoundIO are used as fallbacks. Dummy will have no sound.\n\nSet to SDL2 if unsure.",
"MemoryManagerTooltip": "Change how guest memory is mapped and accessed. Greatly affects emulated CPU performance.\n\nSet to HOST UNCHECKED if unsure.",
"MemoryManagerSoftwareTooltip": "Use a software page table for address translation. Highest accuracy but slowest performance.",
"MemoryManagerHostTooltip": "Directly map memory in the host address space. Much faster JIT compilation and execution.",
"MemoryManagerUnsafeTooltip": "Directly map memory, but do not mask the address within the guest address space before access. Faster, but at the cost of safety. The guest application can access memory from anywhere in Ryujinx, so only run programs you trust with this mode.",
"DRamTooltip": "Utilizes an alternative MemoryMode layout to mimic a Switch development model.\n\nThis is only useful for higher-resolution texture packs or 4k resolution mods. Does NOT improve performance.\n\nLeave OFF if unsure.",
"IgnoreMissingServicesTooltip": "Ignores unimplemented Horizon OS services. This may help in bypassing crashes when booting certain games.\n\nLeave OFF if unsure.",
"GraphicsBackendThreadingTooltip": "Executes graphics backend commands on a second thread.\n\nSpeeds up shader compilation, reduces stuttering, and improves performance on GPU drivers without multithreading support of their own. Slightly better performance on drivers with multithreading.\n\nSet to AUTO if unsure.",
"GalThreadingTooltip": "Executes graphics backend commands on a second thread.\n\nSpeeds up shader compilation, reduces stuttering, and improves performance on GPU drivers without multithreading support of their own. Slightly better performance on drivers with multithreading.\n\nSet to AUTO if unsure.",
"ShaderCacheToggleTooltip": "Saves a disk shader cache which reduces stuttering in subsequent runs.\n\nLeave ON if unsure.",
"ResolutionScaleTooltip": "Resolution Scale applied to applicable render targets",
"ResolutionScaleEntryTooltip": "Floating point resolution scale, such as 1.5. Non-integral scales are more likely to cause issues or crash.",
"AnisotropyTooltip": "Level of Anisotropic Filtering (set to Auto to use the value requested by the game)",
"AspectRatioTooltip": "Aspect Ratio applied to the renderer window.",
"ShaderDumpPathTooltip": "Graphics Shaders Dump Path",
"FileLogTooltip": "Saves console logging to a log file on disk. Does not affect performance.",
"StubLogTooltip": "Prints stub log messages in the console. Does not affect performance.",
"InfoLogTooltip": "Prints info log messages in the console. Does not affect performance.",
"WarnLogTooltip": "Prints warning log messages in the console. Does not affect performance.",
"ErrorLogTooltip": "Prints error log messages in the console. Does not affect performance.",
"TraceLogTooltip": "Prints trace log messages in the console. Does not affect performance.",
"GuestLogTooltip": "Prints guest log messages in the console. Does not affect performance.",
"FileAccessLogTooltip": "Prints file access log messages in the console.",
"FSAccessLogModeTooltip": "Enables FS access log output to the console. Possible modes are 0-3",
"DeveloperOptionTooltip": "Use with care",
"OpenGlLogLevel": "Requires appropriate log levels enabled",
"DebugLogTooltip": "Prints debug log messages in the console.\n\nOnly use this if specifically instructed by a staff member, as it will make logs difficult to read and worsen emulator performance.",
"LoadApplicationFileTooltip": "Open a file explorer to choose a Switch compatible file to load",
"LoadApplicationFolderTooltip": "Open a file explorer to choose a Switch compatible, unpacked application to load",
"OpenRyujinxFolderTooltip": "Open Ryujinx filesystem folder",
"OpenRyujinxLogsTooltip": "Opens the folder where logs are written to",
"ExitTooltip": "Exit Ryujinx",
"OpenSettingsTooltip": "Open settings window",
"OpenProfileManagerTooltip": "Open User Profiles Manager window",
"StopEmulationTooltip": "Stop emulation of the current game and return to game selection",
"CheckUpdatesTooltip": "Check for updates to Ryujinx",
"OpenAboutTooltip": "Open About Window",
"GridSize": "Grid Size",
"GridSizeTooltip": "Change the size of grid items",
"SettingsTabSystemSystemLanguageBrazilianPortuguese": "Brazilian Portuguese",
"AboutRyujinxContributorsButtonHeader": "See All Contributors",
"SettingsTabSystemAudioVolume": "Volume: ",
"AudioVolumeTooltip": "Change Audio Volume",
"SettingsTabSystemEnableInternetAccess": "Guest Internet Access/LAN Mode",
"EnableInternetAccessTooltip": "Allows the emulated application to connect to the Internet.\n\nGames with a LAN mode can connect to each other when this is enabled and the systems are connected to the same access point. This includes real consoles as well.\n\nDoes NOT allow connecting to Nintendo servers. May cause crashing in certain games that try to connect to the Internet.\n\nLeave OFF if unsure.",
"GameListContextMenuManageCheatToolTip": "Manage Cheats",
"GameListContextMenuManageCheat": "Manage Cheats",
"ControllerSettingsStickRange": "Range:",
"DialogStopEmulationTitle": "Ryujinx - Stop Emulation",
"DialogStopEmulationMessage": "Are you sure you want to stop emulation?",
"SettingsTabCpu": "CPU",
"SettingsTabAudio": "Audio",
"SettingsTabNetwork": "Network",
"SettingsTabNetworkConnection": "Network Connection",
"SettingsTabCpuCache": "CPU Cache",
"SettingsTabCpuMemory": "CPU Memory",
"DialogUpdaterFlatpakNotSupportedMessage": "Please update Ryujinx via FlatHub.",
"UpdaterDisabledWarningTitle": "Updater Disabled!",
"GameListContextMenuOpenSdModsDirectory": "Open Atmosphere Mods Directory",
"GameListContextMenuOpenSdModsDirectoryToolTip": "Opens the alternative SD card Atmosphere directory which contains Application's Mods. Useful for mods that are packaged for real hardware.",
"ControllerSettingsRotate90": "Rotate 90° Clockwise",
"IconSize": "Icon Size",
"IconSizeTooltip": "Change the size of game icons",
"MenuBarOptionsShowConsole": "Show Console",
"ShaderCachePurgeError": "Error purging shader cache at {0}: {1}",
"UserErrorNoKeys": "Keys not found",
"UserErrorNoFirmware": "Firmware not found",
"UserErrorFirmwareParsingFailed": "Firmware parsing error",
"UserErrorApplicationNotFound": "Application not found",
"UserErrorUnknown": "Unknown error",
"UserErrorUndefined": "Undefined error",
"UserErrorNoKeysDescription": "Ryujinx was unable to find your 'prod.keys' file",
"UserErrorNoFirmwareDescription": "Ryujinx was unable to find any firmwares installed",
"UserErrorFirmwareParsingFailedDescription": "Ryujinx was unable to parse the provided firmware. This is usually caused by outdated keys.",
"UserErrorApplicationNotFoundDescription": "Ryujinx couldn't find a valid application at the given path.",
"UserErrorUnknownDescription": "An unknown error occured!",
"UserErrorUndefinedDescription": "An undefined error occured! This shouldn't happen, please contact a dev!",
"OpenSetupGuideMessage": "Open the Setup Guide",
"NoUpdate": "No Update",
"TitleUpdateVersionLabel": "Version {0} - {1}",
"RyujinxInfo": "Ryujinx - Info",
"RyujinxConfirm": "Ryujinx - Confirmation",
"FileDialogAllTypes": "All types",
"Never": "Never",
"SwkbdMinCharacters": "Must be at least {0} characters long",
"SwkbdMinRangeCharacters": "Must be {0}-{1} characters long",
"SoftwareKeyboard": "Software Keyboard",
"DialogControllerAppletMessagePlayerRange": "Application requests {0} player(s) with:\n\nTYPES: {1}\n\nPLAYERS: {2}\n\n{3}Please open Settings and reconfigure Input now or press Close.",
"DialogControllerAppletMessage": "Application requests exactly {0} player(s) with:\n\nTYPES: {1}\n\nPLAYERS: {2}\n\n{3}Please open Settings and reconfigure Input now or press Close.",
"DialogControllerAppletDockModeSet": "Docked mode set. Handheld is also invalid.\n\n",
"UpdaterRenaming": "Renaming Old Files...",
"UpdaterRenameFailed": "Updater was unable to rename file: {0}",
"UpdaterAddingFiles": "Adding New Files...",
"UpdaterExtracting": "Extracting Update...",
"UpdaterDownloading": "Downloading Update...",
"Game": "Game",
"Docked": "Docked",
"Handheld": "Handheld",
"ConnectionError": "Connection Error.",
"AboutPageDeveloperListMore": "{0} and more...",
"ApiError": "API Error.",
"LoadingHeading": "Loading {0}",
"CompilingPPTC": "Compiling PTC",
"CompilingShaders": "Compiling Shaders",
"AllKeyboards": "All keyboards",
"OpenFileDialogTitle": "Select a supported file to open",
"OpenFolderDialogTitle": "Select a folder with an unpacked game",
"AllSupportedFormats": "All Supported Formats",
"RyujinxUpdater": "Ryujinx Updater",
"SettingsTabHotkeys": "Keyboard Hotkeys",
"SettingsTabHotkeysHotkeys": "Keyboard Hotkeys",
"SettingsTabHotkeysToggleVsyncHotkey": "Toggle VSync:",
"SettingsTabHotkeysScreenshotHotkey": "Screenshot:",
"SettingsTabHotkeysShowUiHotkey": "Show UI:",
"SettingsTabHotkeysPauseHotkey": "Pause:",
"SettingsTabHotkeysToggleMuteHotkey": "Mute:",
"ControllerMotionTitle": "Motion Control Settings",
"ControllerRumbleTitle": "Rumble Settings",
"SettingsSelectThemeFileDialogTitle": "Select Theme File",
"SettingsXamlThemeFile": "Xaml Theme File",
"AvatarWindowTitle": "Manage Accounts - Avatar",
"Amiibo": "Amiibo",
"Unknown": "Unknown",
"Usage": "Usage",
"Writable": "Writable",
"SelectDlcDialogTitle": "Select DLC files",
"SelectUpdateDialogTitle": "Select update files",
"UserProfileWindowTitle": "User Profiles Manager",
"CheatWindowTitle": "Cheats Manager",
"DlcWindowTitle": "Downloadable Content Manager",
"UpdateWindowTitle": "Title Update Manager",
"CheatWindowHeading": "Cheats Available for {0} [{1}]",
"DlcWindowHeading": "{0} Downloadable Content(s) available for {1} ({2})",
"UserProfilesEditProfile": "Edit Selected",
"Cancel": "Cancel",
"Save": "Save",
"Discard": "Discard",
"UserProfilesSetProfileImage": "Set Profile Image",
"UserProfileEmptyNameError": "Name is required",
"UserProfileNoImageError": "Profile image must be set",
"GameUpdateWindowHeading": "{0} Update(s) available for {1} ({2})",
"SettingsTabHotkeysResScaleUpHotkey": "Increase resolution:",
"SettingsTabHotkeysResScaleDownHotkey": "Decrease resolution:",
"UserProfilesName": "Name:",
"UserProfilesUserId": "User Id:",
"SettingsTabGraphicsBackend": "Graphics Backend",
"SettingsTabGraphicsBackendTooltip": "Graphics Backend to use",
"SettingsEnableTextureRecompression": "Enable Texture Recompression",
"SettingsEnableTextureRecompressionTooltip": "Compresses certain textures in order to reduce VRAM usage.\n\nRecommended for use with GPUs that have less than 4GiB VRAM.\n\nLeave OFF if unsure.",
"SettingsTabGraphicsPreferredGpu": "Preferred GPU",
"SettingsTabGraphicsPreferredGpuTooltip": "Select the graphics card that will be used with the Vulkan graphics backend.\n\nDoes not affect the GPU that OpenGL will use.\n\nSet to the GPU flagged as \"dGPU\" if unsure. If there isn't one, leave untouched.",
"SettingsAppRequiredRestartMessage": "Ryujinx Restart Required",
"SettingsGpuBackendRestartMessage": "Graphics Backend or GPU settings have been modified. This will require a restart to be applied",
"SettingsGpuBackendRestartSubMessage": "Do you want to restart now?",
"RyujinxUpdaterMessage": "Do you want to update Ryujinx to the latest version?",
"SettingsTabHotkeysVolumeUpHotkey": "Increase Volume:",
"SettingsTabHotkeysVolumeDownHotkey": "Decrease Volume:",
"SettingsEnableMacroHLE": "Enable Macro HLE",
"SettingsEnableMacroHLETooltip": "High-level emulation of GPU Macro code.\n\nImproves performance, but may cause graphical glitches in some games.\n\nLeave ON if unsure.",
"VolumeShort": "Vol",
"UserProfilesManageSaves": "Manage Saves",
"DeleteUserSave": "Do you want to delete user save for this game?",
"IrreversibleActionNote": "This action is not reversible.",
"SaveManagerHeading": "Manage Saves for {0}",
"SaveManagerTitle": "Save Manager",
"Name": "Name",
"Size": "Size",
"Search": "Search",
"UserProfilesRecoverLostAccounts": "Recover Lost Accounts",
"Recover": "Recover",
"UserProfilesRecoverHeading" : "Saves were found for the following accounts"
}

View File

@@ -1,613 +0,0 @@
{
"MenuBarFileOpenApplet": "Abrir applet",
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Abre el editor de Mii en modo autónomo",
"SettingsTabInputDirectMouseAccess": "Acceso directo al ratón",
"SettingsTabSystemMemoryManagerMode": "Modo del administrador de memoria:",
"SettingsTabSystemMemoryManagerModeSoftware": "Software",
"SettingsTabSystemMemoryManagerModeHost": "Host (rápido)",
"SettingsTabSystemMemoryManagerModeHostUnchecked": "Host sin verificación (más rápido, inseguro)",
"MenuBarFile": "_Archivo",
"MenuBarFileOpenFromFile": "_Cargar aplicación desde un archivo",
"MenuBarFileOpenUnpacked": "Cargar juego _desempaquetado",
"MenuBarFileOpenEmuFolder": "Abrir carpeta de Ryujinx",
"MenuBarFileOpenLogsFolder": "Abrir carpeta de registros",
"MenuBarFileExit": "_Salir",
"MenuBarOptions": "_Opciones",
"MenuBarOptionsToggleFullscreen": "Cambiar a pantalla completa.",
"MenuBarOptionsStartGamesInFullscreen": "Iniciar juegos en pantalla completa",
"MenuBarOptionsStopEmulation": "Detener emulación",
"MenuBarOptionsSettings": "_Configuración",
"MenuBarOptionsManageUserProfiles": "_Gestionar perfiles de usuario",
"MenuBarActions": "_Acciones",
"MenuBarOptionsSimulateWakeUpMessage": "Simular mensaje de reactivación",
"MenuBarActionsScanAmiibo": "Escanear Amiibo",
"MenuBarTools": "_Herramientas",
"MenuBarToolsInstallFirmware": "Instalar firmware",
"MenuBarFileToolsInstallFirmwareFromFile": "Instalar firmware desde un archivo XCI o ZIP",
"MenuBarFileToolsInstallFirmwareFromDirectory": "Instalar firmware desde una carpeta",
"MenuBarHelp": "Ayuda",
"MenuBarHelpCheckForUpdates": "Buscar actualizaciones",
"MenuBarHelpAbout": "Acerca de",
"MenuSearch": "Buscar...",
"GameListHeaderFavorite": "Favoritos",
"GameListHeaderIcon": "Icono",
"GameListHeaderApplication": "Nombre",
"GameListHeaderDeveloper": "Desarrollador",
"GameListHeaderVersion": "Versión",
"GameListHeaderTimePlayed": "Tiempo jugado",
"GameListHeaderLastPlayed": "Jugado por última vez",
"GameListHeaderFileExtension": "Extensión",
"GameListHeaderFileSize": "Tamaño del archivo",
"GameListHeaderPath": "Directorio",
"GameListContextMenuOpenUserSaveDirectory": "Abrir carpeta de guardado de este usuario",
"GameListContextMenuOpenUserSaveDirectoryToolTip": "Abre la carpeta que contiene la partida guardada del usuario para esta aplicación",
"GameListContextMenuOpenUserDeviceDirectory": "Abrir carpeta de guardado del sistema para el usuario actual",
"GameListContextMenuOpenUserDeviceDirectoryToolTip": "Abre la carpeta que contiene la partida guardada del sistema para esta aplicación",
"GameListContextMenuOpenUserBcatDirectory": "Abrir carpeta de guardado BCAT del usuario",
"GameListContextMenuOpenUserBcatDirectoryToolTip": "Abrir la carpeta que contiene el guardado BCAT de esta aplicación",
"GameListContextMenuManageTitleUpdates": "Gestionar actualizaciones del juego",
"GameListContextMenuManageTitleUpdatesToolTip": "Abrir la ventana de gestión de actualizaciones de esta aplicación",
"GameListContextMenuManageDlc": "Gestionar DLC",
"GameListContextMenuManageDlcToolTip": "Abrir la ventana de gestión del DLC",
"GameListContextMenuOpenModsDirectory": "Abrir carpeta de mods",
"GameListContextMenuOpenModsDirectoryToolTip": "Abrir la carpeta que contiene los mods (archivos modificantes) de esta aplicación",
"GameListContextMenuCacheManagement": "Gestión de caché ",
"GameListContextMenuCacheManagementPurgePptc": "Reconstruir PPTC en cola",
"GameListContextMenuCacheManagementPurgePptcToolTip": "Elimina la caché de PPTC de esta aplicación",
"GameListContextMenuCacheManagementPurgeShaderCache": "Limpiar caché de sombras",
"GameListContextMenuCacheManagementPurgeShaderCacheToolTip": "Eliminar la caché de sombras de esta aplicación",
"GameListContextMenuCacheManagementOpenPptcDirectory": "Abrir carpeta de PPTC",
"GameListContextMenuCacheManagementOpenPptcDirectoryToolTip": "Abrir la carpeta que contiene la caché de PPTC de esta aplicación",
"GameListContextMenuCacheManagementOpenShaderCacheDirectory": "Abrir carpeta de caché de sombras",
"GameListContextMenuCacheManagementOpenShaderCacheDirectoryToolTip": "Abrir la carpeta que contiene la caché de sombras de esta aplicación",
"GameListContextMenuExtractData": "Extraer datos",
"GameListContextMenuExtractDataExeFS": "ExeFS",
"GameListContextMenuExtractDataExeFSToolTip": "Extraer la sección ExeFS de la configuración actual de la aplicación (incluyendo actualizaciones)",
"GameListContextMenuExtractDataRomFS": "RomFS",
"GameListContextMenuExtractDataRomFSToolTip": "Extraer la sección RomFS de la configuración actual de la aplicación (incluyendo actualizaciones)",
"GameListContextMenuExtractDataLogo": "Logotipo",
"GameListContextMenuExtractDataLogoToolTip": "Extraer la sección Logo de la configuración actual de la aplicación (incluyendo actualizaciones)",
"StatusBarGamesLoaded": "{0}/{1} juegos cargados",
"StatusBarSystemVersion": "Versión del sistema: {0}",
"Settings": "Configuración",
"SettingsTabGeneral": "Interfaz de usuario",
"SettingsTabGeneralGeneral": "General",
"SettingsTabGeneralEnableDiscordRichPresence": "Habilitar estado en Discord",
"SettingsTabGeneralCheckUpdatesOnLaunch": "Buscar actualizaciones al iniciar",
"SettingsTabGeneralShowConfirmExitDialog": "Mostrar diálogo de confirmación al cerrar",
"SettingsTabGeneralHideCursorOnIdle": "Ocultar cursor cuando esté inactivo",
"SettingsTabGeneralGameDirectories": "Carpetas de juegos",
"SettingsTabGeneralAdd": "Agregar",
"SettingsTabGeneralRemove": "Quitar",
"SettingsTabSystem": "Sistema",
"SettingsTabSystemCore": "Núcleo",
"SettingsTabSystemSystemRegion": "Región del sistema:",
"SettingsTabSystemSystemRegionJapan": "Japón",
"SettingsTabSystemSystemRegionUSA": "EEUU",
"SettingsTabSystemSystemRegionEurope": "Europa",
"SettingsTabSystemSystemRegionAustralia": "Australia",
"SettingsTabSystemSystemRegionChina": "China",
"SettingsTabSystemSystemRegionKorea": "Corea",
"SettingsTabSystemSystemRegionTaiwan": "Taiwán",
"SettingsTabSystemSystemLanguage": "Idioma del sistema:",
"SettingsTabSystemSystemLanguageJapanese": "Japonés",
"SettingsTabSystemSystemLanguageAmericanEnglish": "Inglés americano",
"SettingsTabSystemSystemLanguageFrench": "Francés",
"SettingsTabSystemSystemLanguageGerman": "Alemán",
"SettingsTabSystemSystemLanguageItalian": "Italiano",
"SettingsTabSystemSystemLanguageSpanish": "Español",
"SettingsTabSystemSystemLanguageChinese": "Chino",
"SettingsTabSystemSystemLanguageKorean": "Coreano",
"SettingsTabSystemSystemLanguageDutch": "Neerlandés/Holandés",
"SettingsTabSystemSystemLanguagePortuguese": "Portugués",
"SettingsTabSystemSystemLanguageRussian": "Ruso",
"SettingsTabSystemSystemLanguageTaiwanese": "Taiwanés",
"SettingsTabSystemSystemLanguageBritishEnglish": "Inglés británico",
"SettingsTabSystemSystemLanguageCanadianFrench": "Francés canadiense",
"SettingsTabSystemSystemLanguageLatinAmericanSpanish": "Español latinoamericano",
"SettingsTabSystemSystemLanguageSimplifiedChinese": "Chino simplificado",
"SettingsTabSystemSystemLanguageTraditionalChinese": "Chino tradicional",
"SettingsTabSystemSystemTimeZone": "Zona horaria del sistema:",
"SettingsTabSystemSystemTime": "Hora del sistema:",
"SettingsTabSystemEnableVsync": "Sincronización vertical",
"SettingsTabSystemEnablePptc": "PPTC (Cache de Traducción de Perfil Persistente)",
"SettingsTabSystemEnableFsIntegrityChecks": "Comprobar integridad de los archivos",
"SettingsTabSystemAudioBackend": "Motor de audio:",
"SettingsTabSystemAudioBackendDummy": "Vacio",
"SettingsTabSystemAudioBackendOpenAL": "OpenAL",
"SettingsTabSystemAudioBackendSoundIO": "SoundIO",
"SettingsTabSystemAudioBackendSDL2": "SDL2",
"SettingsTabSystemHacks": "Hacks",
"SettingsTabSystemHacksNote": " (Pueden causar inestabilidad)",
"SettingsTabSystemExpandDramSize": "Usar diseño alternativo de memoria (Desarrolladores)",
"SettingsTabSystemIgnoreMissingServices": "Ignorar servicios no implementados",
"SettingsTabGraphics": "Gráficos",
"SettingsTabGraphicsAPI": "API de gráficos",
"SettingsTabGraphicsEnableShaderCache": "Habilitar caché de sombras",
"SettingsTabGraphicsAnisotropicFiltering": "Filtro anisotrópico:",
"SettingsTabGraphicsAnisotropicFilteringAuto": "Automático",
"SettingsTabGraphicsAnisotropicFiltering2x": "x2",
"SettingsTabGraphicsAnisotropicFiltering4x": "x4",
"SettingsTabGraphicsAnisotropicFiltering8x": "x8",
"SettingsTabGraphicsAnisotropicFiltering16x": "x16",
"SettingsTabGraphicsResolutionScale": "Escala de resolución:",
"SettingsTabGraphicsResolutionScaleCustom": "Personalizada (no recomendado)",
"SettingsTabGraphicsResolutionScaleNative": "Nativa (720p/1080p)",
"SettingsTabGraphicsResolutionScale2x": "x2 (1440p/2160p)",
"SettingsTabGraphicsResolutionScale3x": "x3 (2160p/3240p)",
"SettingsTabGraphicsResolutionScale4x": "x4 (2880p/4320p)",
"SettingsTabGraphicsAspectRatio": "Relación de aspecto:",
"SettingsTabGraphicsAspectRatio4x3": "4:3",
"SettingsTabGraphicsAspectRatio16x9": "16:9",
"SettingsTabGraphicsAspectRatio16x10": "16:10",
"SettingsTabGraphicsAspectRatio21x9": "21:9",
"SettingsTabGraphicsAspectRatio32x9": "32:9",
"SettingsTabGraphicsAspectRatioStretch": "Estirar a la ventana",
"SettingsTabGraphicsDeveloperOptions": "Opciones de desarrollador",
"SettingsTabGraphicsShaderDumpPath": "Directorio de volcado de sombras:",
"SettingsTabLogging": "Registros",
"SettingsTabLoggingLogging": "Registros",
"SettingsTabLoggingEnableLoggingToFile": "Habilitar registro a archivo",
"SettingsTabLoggingEnableStubLogs": "Habilitar registros de Stub",
"SettingsTabLoggingEnableInfoLogs": "Habilitar registros de Info",
"SettingsTabLoggingEnableWarningLogs": "Habilitar registros de Advertencia",
"SettingsTabLoggingEnableErrorLogs": "Habilitar registros de Error",
"SettingsTabLoggingEnableTraceLogs": "Habilitar registros de Rastro",
"SettingsTabLoggingEnableGuestLogs": "Habilitar registros de Guest",
"SettingsTabLoggingEnableFsAccessLogs": "Habilitar registros de Fs Access",
"SettingsTabLoggingFsGlobalAccessLogMode": "Modo de registros Fs Global Access:",
"SettingsTabLoggingDeveloperOptions": "Opciones de desarrollador (ADVERTENCIA: empeorarán el rendimiento)",
"SettingsTabLoggingGraphicsBackendLogLevel": "Nivel de registro de backend gráficos:",
"SettingsTabLoggingGraphicsBackendLogLevelNone": "Nada",
"SettingsTabLoggingGraphicsBackendLogLevelError": "Errores",
"SettingsTabLoggingGraphicsBackendLogLevelPerformance": "Ralentizaciones",
"SettingsTabLoggingGraphicsBackendLogLevelAll": "Todo",
"SettingsTabLoggingEnableDebugLogs": "Habilitar registros de debug",
"SettingsTabInput": "Entrada",
"SettingsTabInputEnableDockedMode": "Modo dock/TV",
"SettingsTabInputDirectKeyboardAccess": "Acceso directo al teclado",
"SettingsButtonSave": "Guardar",
"SettingsButtonClose": "Cerrar",
"SettingsButtonOk": "Aceptar",
"SettingsButtonCancel": "Cancelar",
"SettingsButtonApply": "Aplicar",
"ControllerSettingsPlayer": "Jugador",
"ControllerSettingsPlayer1": "Jugador 1",
"ControllerSettingsPlayer2": "Jugador 2",
"ControllerSettingsPlayer3": "Jugador 3",
"ControllerSettingsPlayer4": "Jugador 4",
"ControllerSettingsPlayer5": "Jugador 5",
"ControllerSettingsPlayer6": "Jugador 6",
"ControllerSettingsPlayer7": "Jugador 7",
"ControllerSettingsPlayer8": "Jugador 8",
"ControllerSettingsHandheld": "Portátil",
"ControllerSettingsInputDevice": "Dispositivo de entrada",
"ControllerSettingsRefresh": "Actualizar",
"ControllerSettingsDeviceDisabled": "Deshabilitado",
"ControllerSettingsControllerType": "Tipo de Mando",
"ControllerSettingsControllerTypeHandheld": "Portátil",
"ControllerSettingsControllerTypeProController": "Mando Pro",
"ControllerSettingsControllerTypeJoyConPair": "Doble Joy-Con",
"ControllerSettingsControllerTypeJoyConLeft": "Joy-Con Izquierdo",
"ControllerSettingsControllerTypeJoyConRight": "Joy-Con Derecho",
"ControllerSettingsProfile": "Perfil",
"ControllerSettingsProfileDefault": "Predeterminado",
"ControllerSettingsLoad": "Cargar",
"ControllerSettingsAdd": "Agregar",
"ControllerSettingsRemove": "Quitar",
"ControllerSettingsButtons": "Botones",
"ControllerSettingsButtonA": "A",
"ControllerSettingsButtonB": "B",
"ControllerSettingsButtonX": "X",
"ControllerSettingsButtonY": "Y",
"ControllerSettingsButtonPlus": "+",
"ControllerSettingsButtonMinus": "-",
"ControllerSettingsDPad": "Pad direccional",
"ControllerSettingsDPadUp": "Arriba",
"ControllerSettingsDPadDown": "Abajo",
"ControllerSettingsDPadLeft": "Izquierda",
"ControllerSettingsDPadRight": "Derecha",
"ControllerSettingsLStick": "Palanca izquierda",
"ControllerSettingsLStickButton": "Botón (L3)",
"ControllerSettingsLStickUp": "Arriba",
"ControllerSettingsLStickDown": "Abajo",
"ControllerSettingsLStickLeft": "Izquierda",
"ControllerSettingsLStickRight": "Derecha",
"ControllerSettingsLStickStick": "Palanca",
"ControllerSettingsLStickInvertXAxis": "Invertir eje X",
"ControllerSettingsLStickInvertYAxis": "Invertir eje Y",
"ControllerSettingsLStickDeadzone": "Zona muerta:",
"ControllerSettingsRStick": "Palanca derecha",
"ControllerSettingsRStickButton": "Botón (R3)",
"ControllerSettingsRStickUp": "Arriba",
"ControllerSettingsRStickDown": "Abajo",
"ControllerSettingsRStickLeft": "Izquierda",
"ControllerSettingsRStickRight": "Derecha",
"ControllerSettingsRStickStick": "Palanca",
"ControllerSettingsRStickInvertXAxis": "Invertir eje X",
"ControllerSettingsRStickInvertYAxis": "Invertir eje Y",
"ControllerSettingsRStickDeadzone": "Zona muerta:",
"ControllerSettingsTriggersLeft": "Gatillos izquierdos",
"ControllerSettingsTriggersRight": "Gatillos derechos",
"ControllerSettingsTriggersButtonsLeft": "Botones de gatillo izquierdos",
"ControllerSettingsTriggersButtonsRight": "Botones de gatillo derechos",
"ControllerSettingsTriggers": "Gatillos",
"ControllerSettingsTriggerL": "L",
"ControllerSettingsTriggerR": "R",
"ControllerSettingsTriggerZL": "ZL",
"ControllerSettingsTriggerZR": "ZR",
"ControllerSettingsLeftSL": "SL",
"ControllerSettingsLeftSR": "SR",
"ControllerSettingsRightSL": "SL",
"ControllerSettingsRightSR": "SR",
"ControllerSettingsExtraButtonsLeft": "Botones izquierdos",
"ControllerSettingsExtraButtonsRight": "Botones derechos",
"ControllerSettingsMisc": "Misceláneo",
"ControllerSettingsTriggerThreshold": "Límite de gatillos:",
"ControllerSettingsMotion": "Movimiento",
"ControllerSettingsMotionUseCemuhookCompatibleMotion": "Usar movimiento compatible con CemuHook",
"ControllerSettingsMotionControllerSlot": "Puerto del mando:",
"ControllerSettingsMotionMirrorInput": "Paralelizar derecho e izquierdo",
"ControllerSettingsMotionRightJoyConSlot": "Puerto del Joy-Con derecho:",
"ControllerSettingsMotionServerHost": "Host del servidor:",
"ControllerSettingsMotionGyroSensitivity": "Sensibilidad de Gyro:",
"ControllerSettingsMotionGyroDeadzone": "Zona muerta de Gyro:",
"ControllerSettingsSave": "Guardar",
"ControllerSettingsClose": "Cerrar",
"UserProfilesSelectedUserProfile": "Perfil de usuario seleccionado:",
"UserProfilesSaveProfileName": "Guardar nombre de perfil",
"UserProfilesChangeProfileImage": "Cambiar imagen de perfil",
"UserProfilesAvailableUserProfiles": "Perfiles de usuario disponibles:",
"UserProfilesAddNewProfile": "Añadir nuevo perfil",
"UserProfilesDeleteSelectedProfile": "Eliminar perfil seleccionado",
"UserProfilesClose": "Cerrar",
"ProfileImageSelectionTitle": "Selección de imagen de perfil",
"ProfileImageSelectionHeader": "Elige una imagen de perfil",
"ProfileImageSelectionNote": "Puedes importar una imagen de perfil personalizada, o seleccionar un avatar del firmware de sistema",
"ProfileImageSelectionImportImage": "Importar imagen",
"ProfileImageSelectionSelectAvatar": "Seleccionar avatar del firmware",
"InputDialogTitle": "Cuadro de diálogo de entrada",
"InputDialogOk": "Aceptar",
"InputDialogCancel": "Cancelar",
"InputDialogAddNewProfileTitle": "Introducir nombre de perfil",
"InputDialogAddNewProfileHeader": "Por favor elige un nombre de usuario",
"InputDialogAddNewProfileSubtext": "(Máximo de caracteres: {0})",
"AvatarChoose": "Escoger",
"AvatarSetBackgroundColor": "Establecer color de fondo",
"AvatarClose": "Cerrar",
"ControllerSettingsLoadProfileToolTip": "Cargar perfil",
"ControllerSettingsAddProfileToolTip": "Agregar perfil",
"ControllerSettingsRemoveProfileToolTip": "Eliminar perfil",
"ControllerSettingsSaveProfileToolTip": "Guardar perfil",
"MenuBarFileToolsTakeScreenshot": "Captura de pantalla",
"MenuBarFileToolsHideUi": "Ocultar interfaz",
"GameListContextMenuToggleFavorite": "Marcar favorito",
"GameListContextMenuToggleFavoriteToolTip": "Marca o desmarca el juego como favorito",
"SettingsTabGeneralTheme": "Tema",
"SettingsTabGeneralThemeCustomTheme": "Directorio de tema personalizado",
"SettingsTabGeneralThemeBaseStyle": "Estilo base",
"SettingsTabGeneralThemeBaseStyleDark": "Oscuro",
"SettingsTabGeneralThemeBaseStyleLight": "Claro",
"SettingsTabGeneralThemeEnableCustomTheme": "Habilitar tema personalizado",
"ButtonBrowse": "Buscar",
"ControllerSettingsConfigureGeneral": "Configurar",
"ControllerSettingsRumble": "Vibración",
"ControllerSettingsRumbleStrongMultiplier": "Multiplicador de vibraciones fuertes",
"ControllerSettingsRumbleWeakMultiplier": "Multiplicador de vibraciones débiles",
"DialogMessageSaveNotAvailableMessage": "No hay datos de guardado para {0} [{1:x16}]",
"DialogMessageSaveNotAvailableCreateSaveMessage": "¿Quieres crear datos de guardado para este juego?",
"DialogConfirmationTitle": "Ryujinx - Confirmación",
"DialogUpdaterTitle": "Ryujinx - Actualizador",
"DialogErrorTitle": "Ryujinx - Error",
"DialogWarningTitle": "Ryujinx - Advertencia",
"DialogExitTitle": "Ryujinx - Salir",
"DialogErrorMessage": "Ryujinx encontró un error",
"DialogExitMessage": "¿Seguro que quieres cerrar Ryujinx?",
"DialogExitSubMessage": "¡Se perderán los datos no guardados!",
"DialogMessageCreateSaveErrorMessage": "Hubo un error al crear los datos de guardado especificados: {0}",
"DialogMessageFindSaveErrorMessage": "Hubo un error encontrando los datos de guardado especificados: {0}",
"FolderDialogExtractTitle": "Elige la carpeta en la que deseas extraer",
"DialogNcaExtractionMessage": "Extrayendo {0} sección de {1}...",
"DialogNcaExtractionTitle": "Ryujinx - Extractor de sección NCA",
"DialogNcaExtractionMainNcaNotFoundErrorMessage": "Fallo de extracción. El NCA principal no estaba presente en el archivo seleccionado.",
"DialogNcaExtractionCheckLogErrorMessage": "Fallo de extracción. Lee el registro para más información.",
"DialogNcaExtractionSuccessMessage": "Se completó la extracción con éxito.",
"DialogUpdaterConvertFailedMessage": "No se pudo convertir la versión actual de Ryujinx.",
"DialogUpdaterCancelUpdateMessage": "¡Cancelando actualización!",
"DialogUpdaterAlreadyOnLatestVersionMessage": "¡Ya tienes la versión más reciente de Ryujinx!",
"DialogUpdaterFailedToGetVersionMessage": "Se ha producido un error al intentar obtener información de liberación de GitHub Release. Esto puede ser causado si una nueva versión está siendo compilada por GitHub Actions. Inténtalo de nuevo en unos minutos.",
"DialogUpdaterConvertFailedGithubMessage": "No se pudo convertir la versión de Ryujinx recibida de GitHub Release.",
"DialogUpdaterDownloadingMessage": "Descargando actualización...",
"DialogUpdaterExtractionMessage": "Extrayendo actualización...",
"DialogUpdaterRenamingMessage": "Renombrando actualización...",
"DialogUpdaterAddingFilesMessage": "Aplicando actualización...",
"DialogUpdaterCompleteMessage": "¡Actualización completa!",
"DialogUpdaterRestartMessage": "¿Quieres reiniciar Ryujinx?",
"DialogUpdaterArchNotSupportedMessage": "¡Tu arquitectura de sistema no es compatible!",
"DialogUpdaterArchNotSupportedSubMessage": "(¡Solo son compatibles los sistemas x64!)",
"DialogUpdaterNoInternetMessage": "¡No estás conectado a internet!",
"DialogUpdaterNoInternetSubMessage": "¡Por favor, verifica que tu conexión a Internet funciona!",
"DialogUpdaterDirtyBuildMessage": "¡No puedes actualizar una versión \"dirty\" de Ryujinx!",
"DialogUpdaterDirtyBuildSubMessage": "Por favor, descarga Ryujinx en https://ryujinx.org/ si buscas una versión con soporte.",
"DialogRestartRequiredMessage": "Se necesita reiniciar",
"DialogThemeRestartMessage": "Tema guardado. Se necesita reiniciar para aplicar el tema.",
"DialogThemeRestartSubMessage": "¿Quieres reiniciar?",
"DialogFirmwareInstallEmbeddedMessage": "¿Quieres instalar el firmware incluido en este juego? (Firmware versión {0})",
"DialogFirmwareInstallEmbeddedSuccessMessage": "No se encontró firmware instalado pero Ryujinx pudo instalar el firmware {0} a partir de este juego.\nA continuación, se iniciará el emulador.",
"DialogFirmwareNoFirmwareInstalledMessage": "No hay firmware instalado",
"DialogFirmwareInstalledMessage": "Se instaló el firmware {0}",
"DialogOpenSettingsWindowLabel": "Abrir ventana de opciones",
"DialogControllerAppletTitle": "Applet de mandos",
"DialogMessageDialogErrorExceptionMessage": "Error al mostrar cuadro de diálogo: {0}",
"DialogSoftwareKeyboardErrorExceptionMessage": "Error al mostrar teclado de software: {0}",
"DialogErrorAppletErrorExceptionMessage": "Error al mostrar díalogo ErrorApplet: {0}",
"DialogUserErrorDialogMessage": "{0}: {1}",
"DialogUserErrorDialogInfoMessage": "\nPara más información sobre cómo arreglar este error, sigue nuestra Guía de Instalación.",
"DialogUserErrorDialogTitle": "Ryujinx Error ({0})",
"DialogAmiiboApiTitle": "Amiibo API",
"DialogAmiiboApiFailFetchMessage": "Ocurrió un error al recibir información de la API.",
"DialogAmiiboApiConnectErrorMessage": "No se pudo conectar al servidor de la API Amiibo. El servicio puede estar caído o tu conexión a internet puede haberse desconectado.",
"DialogProfileInvalidProfileErrorMessage": "El perfil {0} no es compatible con el sistema actual de configuración de entrada.",
"DialogProfileDefaultProfileOverwriteErrorMessage": "El perfil predeterminado no se puede sobreescribir",
"DialogProfileDeleteProfileTitle": "Eliminando perfil",
"DialogProfileDeleteProfileMessage": "Esta acción es irreversible, ¿estás seguro de querer continuar?",
"DialogWarning": "Advertencia",
"DialogPPTCDeletionMessage": "Vas a borrar la caché de PPTC para:\n\n{0}\n\n¿Estás seguro de querer continuar?",
"DialogPPTCDeletionErrorMessage": "Error purgando la caché de PPTC en {0}: {1}",
"DialogShaderDeletionMessage": "Vas a borrar la caché de sombreadores para:\n\n{0}\n\n¿Estás seguro de querer continuar?",
"DialogShaderDeletionErrorMessage": "Error purgando la caché de sombreadores en {0}: {1}",
"DialogRyujinxErrorMessage": "Ryujinx ha encontrado un error",
"DialogInvalidTitleIdErrorMessage": "Error de interfaz: El juego seleccionado no tiene una ID válida",
"DialogFirmwareInstallerFirmwareNotFoundErrorMessage": "No se pudo encontrar un firmware válido en {0}.",
"DialogFirmwareInstallerFirmwareInstallTitle": "Instalar firmware {0}",
"DialogFirmwareInstallerFirmwareInstallMessage": "Se instalará la versión de sistema {0}.",
"DialogFirmwareInstallerFirmwareInstallSubMessage": "\n\nEsto reemplazará la versión de sistema actual, {0}.",
"DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\n¿Continuar?",
"DialogFirmwareInstallerFirmwareInstallWaitMessage": "Instalando firmware...",
"DialogFirmwareInstallerFirmwareInstallSuccessMessage": "Versión de sistema {0} instalada con éxito.",
"DialogUserProfileDeletionWarningMessage": "Si eliminas el perfil seleccionado no quedará ningún otro perfil",
"DialogUserProfileDeletionConfirmMessage": "¿Quieres eliminar el perfil seleccionado?",
"DialogControllerSettingsModifiedConfirmMessage": "Se ha actualizado la configuración del mando actual.",
"DialogControllerSettingsModifiedConfirmSubMessage": "¿Guardar cambios?",
"DialogDlcLoadNcaErrorMessage": "{0}. Archivo con error: {1}",
"DialogDlcNoDlcErrorMessage": "¡Ese archivo no contiene contenido descargable para el título seleccionado!",
"DialogPerformanceCheckLoggingEnabledMessage": "Has habilitado los registros debug, diseñados solo para uso de los desarrolladores.",
"DialogPerformanceCheckLoggingEnabledConfirmMessage": "Para un rendimiento óptimo, se recomienda deshabilitar los registros debug. ¿Quieres deshabilitarlos ahora?",
"DialogPerformanceCheckShaderDumpEnabledMessage": "Has habilitado el volcado de sombras, diseñado solo para uso de los desarrolladores.",
"DialogPerformanceCheckShaderDumpEnabledConfirmMessage": "Para un rendimiento óptimo, se recomienda deshabilitar el volcado de sombraa. ¿Quieres deshabilitarlo ahora?",
"DialogLoadAppGameAlreadyLoadedMessage": "Ya has cargado un juego",
"DialogLoadAppGameAlreadyLoadedSubMessage": "Por favor, detén la emulación o cierra el emulador antes de iniciar otro juego.",
"DialogUpdateAddUpdateErrorMessage": "¡Ese archivo no contiene una actualización para el título seleccionado!",
"DialogSettingsBackendThreadingWarningTitle": "Advertencia - multihilado de gráficos",
"DialogSettingsBackendThreadingWarningMessage": "Ryujinx debe reiniciarse para aplicar este cambio. Dependiendo de tu plataforma, puede que tengas que desactivar manualmente la optimización enlazada de tus controladores gráficos para usar el multihilo de Ryujinx.",
"SettingsTabGraphicsFeaturesOptions": "Funcionalidades",
"SettingsTabGraphicsBackendMultithreading": "Multihilado del motor gráfico:",
"CommonAuto": "Automático",
"CommonOff": "Desactivado",
"CommonOn": "Activado",
"InputDialogYes": "Sí",
"InputDialogNo": "No",
"DialogProfileInvalidProfileNameErrorMessage": "El nombre de archivo contiene caracteres inválidos. Por favor, inténtalo de nuevo.",
"MenuBarOptionsPauseEmulation": "Pausar",
"MenuBarOptionsResumeEmulation": "Reanudar",
"AboutUrlTooltipMessage": "Haz clic para abrir el sitio web de Ryujinx en tu navegador predeterminado.",
"AboutDisclaimerMessage": "Ryujinx no tiene afiliación alguna con Nintendo™,\nni con ninguno de sus socios.",
"AboutAmiiboDisclaimerMessage": "Utilizamos AmiiboAPI (www.amiiboapi.com)\nen nuestra emulación de Amiibo.",
"AboutPatreonUrlTooltipMessage": "Haz clic para abrir el Patreon de Ryujinx en tu navegador predeterminado.",
"AboutGithubUrlTooltipMessage": "Haz clic para abrir el GitHub de Ryujinx en tu navegador predeterminado.",
"AboutDiscordUrlTooltipMessage": "Haz clic para recibir una invitación al Discord de Ryujinx en tu navegador predeterminado.",
"AboutTwitterUrlTooltipMessage": "Haz clic para abrir el Twitter de Ryujinx en tu navegador predeterminado.",
"AboutRyujinxAboutTitle": "Acerca de:",
"AboutRyujinxAboutContent": "Ryujinx es un emulador para Nintendo Switch™.\nPor favor, apóyanos en Patreon.\nEncuentra las noticias más recientes en nuestro Twitter o Discord.\nDesarrolladores interesados en contribuir pueden encontrar más información en GitHub o Discord.",
"AboutRyujinxMaintainersTitle": "Mantenido por:",
"AboutRyujinxMaintainersContentTooltipMessage": "Haz clic para abrir la página de contribuidores en tu navegador predeterminado.",
"AboutRyujinxSupprtersTitle": "Apoyado en Patreon Por:",
"AmiiboSeriesLabel": "Serie de Amiibo",
"AmiiboCharacterLabel": "Personaje",
"AmiiboScanButtonLabel": "Escanear",
"AmiiboOptionsShowAllLabel": "Mostrar todos los Amiibo",
"AmiiboOptionsUsRandomTagLabel": "Hack: usar etiqueta aleatoria Uuid",
"DlcManagerTableHeadingEnabledLabel": "Habilitado",
"DlcManagerTableHeadingTitleIdLabel": "ID de título",
"DlcManagerTableHeadingContainerPathLabel": "Directorio del contenedor",
"DlcManagerTableHeadingFullPathLabel": "Directorio completo",
"DlcManagerRemoveAllButton": "Quitar todo",
"DlcManagerEnableAllButton": "Activar todas",
"DlcManagerDisableAllButton": "Desactivar todos",
"MenuBarOptionsChangeLanguage": "Cambiar idioma",
"CommonSort": "Orden",
"CommonShowNames": "Mostrar nombres",
"CommonFavorite": "Favorito",
"OrderAscending": "Ascendente",
"OrderDescending": "Descendente",
"SettingsTabGraphicsFeatures": "Funcionalidades Y Mejoras",
"ErrorWindowTitle": "Ventana de error",
"ToggleDiscordTooltip": "Elige si muestras Ryujinx o no en tu actividad de Discord cuando lo estés usando",
"AddGameDirBoxTooltip": "Elige un directorio de juegos para mostrar en la ventana principal",
"AddGameDirTooltip": "Agrega un directorio de juegos a la lista",
"RemoveGameDirTooltip": "Quita el directorio seleccionado de la lista",
"CustomThemeCheckTooltip": "Activa o desactiva los temas personalizados para la interfaz",
"CustomThemePathTooltip": "Carpeta que contiene los temas personalizados para la interfaz",
"CustomThemeBrowseTooltip": "Busca un tema personalizado para la interfaz",
"DockModeToggleTooltip": "El modo dock o modo TV hace que la consola emulada se comporte como una Nintendo Switch en su dock. Esto mejora la calidad gráfica en la mayoría de los juegos. Del mismo modo, si lo desactivas, el sistema emulado se comportará como una Nintendo Switch en modo portátil, reduciendo la cálidad de los gráficos.\n\nConfigura los controles de \"Jugador\" 1 si planeas jugar en modo dock/TV; configura los controles de \"Portátil\" si planeas jugar en modo portátil.\n\nActívalo si no sabes qué hacer.",
"DirectKeyboardTooltip": "Activa o desactiva \"soporte para acceso directo al teclado (HID)\" (Permite a los juegos utilizar tu teclado como entrada de texto)",
"DirectMouseTooltip": "Activa o desactiva \"soporte para acceso directo al ratón (HID)\" (Permite a los juegos utilizar tu ratón como cursor)",
"RegionTooltip": "Cambia la región del sistema",
"LanguageTooltip": "Cambia el idioma del sistema",
"TimezoneTooltip": "Cambia la zona horaria del sistema",
"TimeTooltip": "Cambia la hora del sistema",
"VSyncToggleTooltip": "Sincronización vertical del sistema emulado. A efectos prácticos es un límite de fotogramas para la mayoría de juegos; deshabilitarlo puede hacer que los juegos se aceleren o que las pantallas de carga tarden más o se atasquen.\n\nPuedes activar y desactivar esto mientras el emulador está funcionando con un atajo de teclado a tu elección. Recomendamos hacer esto en vez de deshabilitarlo.\n\nActívalo si no sabes qué hacer.",
"PptcToggleTooltip": "Guarda funciones de JIT traducidas para que no sea necesario traducirlas cada vez que el juego carga.\n\nReduce los tirones y acelera significativamente el tiempo de inicio de los juegos después de haberlos ejecutado al menos una vez.\n\nActívalo si no sabes qué hacer.",
"FsIntegrityToggleTooltip": "Comprueba si hay archivos corruptos en los juegos que ejecutes al abrirlos, y si detecta archivos corruptos, muestra un error de Hash en los registros.\n\nEsto no tiene impacto alguno en el rendimiento y está pensado para ayudar a resolver problemas.\n\nActívalo si no sabes qué hacer.",
"AudioBackendTooltip": "Cambia el motor usado para renderizar audio.\n\nSDL2 es el preferido, mientras que OpenAL y SoundIO se usan si hay problemas con este. Dummy no produce audio.\n\nSelecciona SDL2 si no sabes qué hacer.",
"MemoryManagerTooltip": "Cambia la forma de mapear y acceder a la memoria del guest. Afecta en gran medida al rendimiento de la CPU emulada.\n\nSelecciona \"Host sin verificación\" si no sabes qué hacer.",
"MemoryManagerSoftwareTooltip": "Usa una tabla de paginación de software para traducir direcciones. Ofrece la precisión más exacta pero el rendimiento más lento.",
"MemoryManagerHostTooltip": "Mapea la memoria directamente en la dirección de espacio del host. Compilación y ejecución JIT mucho más rápida.",
"MemoryManagerUnsafeTooltip": "Mapea la memoria directamente, pero no enmascara la dirección dentro del espacio de dirección del guest antes del acceso. El modo más rápido, pero a costa de seguridad. La aplicación guest puede acceder a la memoria desde cualquier parte en Ryujinx, así que ejecuta solo programas en los que confíes cuando uses este modo.",
"DRamTooltip": "Expande la memoria DRAM del sistema emulado de 4GiB a 6GiB.\n\nUtilizar solo con packs de texturas HD o mods de resolución 4K. NO mejora el rendimiento.\n\nDesactívalo si no sabes qué hacer.",
"IgnoreMissingServicesTooltip": "Hack para ignorar servicios no implementados del Horizon OS. Esto puede ayudar a sobrepasar crasheos cuando inicies ciertos juegos.\n\nDesactívalo si no sabes qué hacer.",
"GraphicsBackendThreadingTooltip": "Ejecuta los comandos del motor gráfico en un segundo hilo. Acelera la compilación de sombreadores, reduce los tirones, y mejora el rendimiento en controladores gráficos que no realicen su propio multihilado. Rendimiento máximo ligeramente superior en controladores gráficos que soporten multihilado.\n\nSelecciona \"Auto\" si no sabes qué hacer.",
"GalThreadingTooltip": "Ejecuta los comandos del motor gráfico en un segundo hilo. Acelera la compilación de sombreadores, reduce los tirones, y mejora el rendimiento en controladores gráficos que no realicen su propio multihilado. Rendimiento máximo ligeramente superior en controladores gráficos que soporten multihilado.\n\nSelecciona \"Auto\" si no sabes qué hacer.",
"ShaderCacheToggleTooltip": "Guarda una caché de sombreadores en disco, la cual reduce los tirones a medida que vas jugando.\n\nActívalo si no sabes qué hacer.",
"ResolutionScaleTooltip": "Escala de resolución aplicada a objetivos aplicables en el renderizado",
"ResolutionScaleEntryTooltip": "Escalado de resolución de coma flotante, como por ejemplo 1,5. Los valores no íntegros pueden causar errores gráficos o crashes.",
"AnisotropyTooltip": "Nivel de filtrado anisotrópico (selecciona Auto para utilizar el valor solicitado por el juego)",
"AspectRatioTooltip": "Relación de aspecto aplicada a la ventana de renderizado.",
"ShaderDumpPathTooltip": "Directorio en el cual se volcarán los sombreadores de los gráficos",
"FileLogTooltip": "Guarda los registros de la consola en archivos en disco. No afectan al rendimiento.",
"StubLogTooltip": "Escribe mensajes de Stub en la consola. No afectan al rendimiento.",
"InfoLogTooltip": "Escribe mensajes de Info en la consola. No afectan al rendimiento.",
"WarnLogTooltip": "Escribe mensajes de Advertencia en la consola. No afectan al rendimiento.",
"ErrorLogTooltip": "Escribe mensajes de Error en la consola. No afectan al rendimiento.",
"TraceLogTooltip": "Escribe mensajes de Rastro en la consola. No afectan al rendimiento.",
"GuestLogTooltip": "Escribe mensajes de Guest en la consola. No afectan al rendimiento.",
"FileAccessLogTooltip": "Activa mensajes de acceso a archivo en la consola",
"FSAccessLogModeTooltip": "Activa registros FS Access en la consola. Los modos posibles son entre 0 y 3",
"DeveloperOptionTooltip": "Usar con cuidado",
"OpenGlLogLevel": "Requiere activar los niveles de registro apropiados",
"DebugLogTooltip": "Escribe mensajes de debug en la consola\n\nActiva esto solo si un miembro del equipo te lo pide expresamente, pues hará que el registro sea difícil de leer y empeorará el rendimiento del emulador.",
"LoadApplicationFileTooltip": "Abre el explorador de archivos para elegir un archivo compatible con Switch para cargar",
"LoadApplicationFolderTooltip": "Abre el explorador de archivos para elegir un archivo desempaquetado y compatible con Switch para cargar",
"OpenRyujinxFolderTooltip": "Abre la carpeta de sistema de Ryujinx",
"OpenRyujinxLogsTooltip": "Abre la carpeta en la que se guardan los registros",
"ExitTooltip": "Cierra Ryujinx",
"OpenSettingsTooltip": "Abre la ventana de configuración",
"OpenProfileManagerTooltip": "Abre la ventana para gestionar los perfiles de usuario",
"StopEmulationTooltip": "Detiene la emulación del juego actual y regresa a la selección de juegos",
"CheckUpdatesTooltip": "Busca actualizaciones para Ryujinx",
"OpenAboutTooltip": "Abre la ventana \"Acerca de\"",
"GridSize": "Tamaño de cuadrícula",
"GridSizeTooltip": "Cambia el tamaño de los objetos en la cuadrícula",
"SettingsTabSystemSystemLanguageBrazilianPortuguese": "Portugués brasileño",
"AboutRyujinxContributorsButtonHeader": "Ver todos los contribuidores",
"SettingsTabSystemAudioVolume": "Volumen: ",
"AudioVolumeTooltip": "Ajusta el nivel de volumen",
"SettingsTabSystemEnableInternetAccess": "Conectar guest a Internet/Modo LAN",
"EnableInternetAccessTooltip": "Permite a la aplicación emulada conectarse a Internet.\n\nLos juegos que tengan modo LAN podrán conectarse entre sí habilitando esta opción y estando conectados al mismo módem. Asimismo, esto permite conexiones con consolas reales.\n\nNO permite conectar con los servidores de Nintendo Online. Puede causar que ciertos juegos crasheen al intentar conectarse a sus servidores.\n\nDesactívalo si no estás seguro.",
"GameListContextMenuManageCheatToolTip": "Activa o desactiva los cheats",
"GameListContextMenuManageCheat": "Administrar cheats",
"ControllerSettingsStickRange": "Alcance:",
"DialogStopEmulationTitle": "Ryujinx - Detener emulación",
"DialogStopEmulationMessage": "¿Seguro que quieres detener la emulación actual?",
"SettingsTabCpu": "CPU",
"SettingsTabAudio": "Sonido",
"SettingsTabNetwork": "Red",
"SettingsTabNetworkConnection": "Conexión de red",
"SettingsTabCpuCache": "Caché de CPU",
"SettingsTabCpuMemory": "Memoria de CPU",
"DialogUpdaterFlatpakNotSupportedMessage": "Por favor, actualiza Ryujinx a través de FlatHub.",
"UpdaterDisabledWarningTitle": "¡Actualizador deshabilitado!",
"GameListContextMenuOpenSdModsDirectory": "Abrir carpeta de mods Atmosphere",
"GameListContextMenuOpenSdModsDirectoryToolTip": "Abre la carpeta alternativa de mods en la que puedes insertar mods de Atmosphere. Útil para mods que vengan organizados para uso en consola.",
"ControllerSettingsRotate90": "Rotar 90° en el sentido de las agujas del reloj",
"IconSize": "Tamaño de iconos",
"IconSizeTooltip": "Cambia el tamaño de los iconos de juegos",
"MenuBarOptionsShowConsole": "Mostrar consola",
"ShaderCachePurgeError": "Error al eliminar la caché en {0}: {1}",
"UserErrorNoKeys": "No se encontraron keys",
"UserErrorNoFirmware": "No se encontró firmware",
"UserErrorFirmwareParsingFailed": "Error al analizar el firmware",
"UserErrorApplicationNotFound": "No se encontró la aplicación",
"UserErrorUnknown": "Error desconocido",
"UserErrorUndefined": "Error indefinido",
"UserErrorNoKeysDescription": "Ryujinx no pudo encontrar tus 'prod.keys'.",
"UserErrorNoFirmwareDescription": "Ryujinx no pudo encontrar un firmware instalado.",
"UserErrorFirmwareParsingFailedDescription": "Ryujinx no pudo analizar el firmware. Normalmente esto ocurre debido a keys desfasadas.",
"UserErrorApplicationNotFoundDescription": "Ryujinx no pudo encontrar una aplicación válida en ese camino.",
"UserErrorUnknownDescription": "¡Ocurrió un error desconocido!",
"UserErrorUndefinedDescription": "¡Ocurrió un error indefinido! Esto no debería pasar, por favor, ¡contacta con un desarrollador!",
"OpenSetupGuideMessage": "Abrir la guía de instalación",
"NoUpdate": "No actualizado",
"TitleUpdateVersionLabel": "Versión {0} - {1}",
"RyujinxInfo": "Ryujinx - Info",
"RyujinxConfirm": "Ryujinx - Confirmación",
"FileDialogAllTypes": "Todos los tipos",
"Never": "Nunca",
"SwkbdMinCharacters": "Debe tener al menos {0} caracteres",
"SwkbdMinRangeCharacters": "Debe tener {0}-{1} caracteres",
"SoftwareKeyboard": "Teclado de software",
"DialogControllerAppletMessagePlayerRange": "La aplicación require {0} jugador(es) con:\n\nTYPES: {1}\n\nPLAYERS: {2}\n\n{3}Por favor abre las opciones y reconfigura los dispositivos de entrada o presiona 'Cerrar'.",
"DialogControllerAppletMessage": "La aplicación require exactamente {0} jugador(es) con:\n\nTYPES: {1}\n\nPLAYERS: {2}\n\n{3}Por favor abre las opciones y reconfigura los dispositivos de entrada o presiona 'Cerrar'.",
"DialogControllerAppletDockModeSet": "Modo dock/TV activo. El control portátil también es inválido.\n\n",
"UpdaterRenaming": "Renombrando archivos viejos...",
"UpdaterRenameFailed": "El actualizador no pudo renombrar el archivo: {0}",
"UpdaterAddingFiles": "Añadiendo nuevos archivos...",
"UpdaterExtracting": "Extrayendo actualización...",
"UpdaterDownloading": "Descargando actualización...",
"Game": "Juego",
"Docked": "Dock/TV",
"Handheld": "Portátil",
"ConnectionError": "Error de conexión.",
"AboutPageDeveloperListMore": "{0} y más...",
"ApiError": "Error de API.",
"LoadingHeading": "Cargando {0}",
"CompilingPPTC": "Compilando PTC",
"CompilingShaders": "Compilando sombreadores",
"AllKeyboards": "Todos los teclados",
"OpenFileDialogTitle": "Selecciona un archivo soportado para cargar",
"OpenFolderDialogTitle": "Selecciona una carpeta con un juego desempaquetado",
"AllSupportedFormats": "Todos los formatos soportados",
"RyujinxUpdater": "Actualizador de Ryujinx",
"SettingsTabHotkeys": "Atajos de teclado",
"SettingsTabHotkeysHotkeys": "Atajos de teclado",
"SettingsTabHotkeysToggleVsyncHotkey": "Alternar la sincronización vertical:",
"SettingsTabHotkeysScreenshotHotkey": "Captura de pantalla:",
"SettingsTabHotkeysShowUiHotkey": "Mostrar interfaz:",
"SettingsTabHotkeysPauseHotkey": "Pausar:",
"SettingsTabHotkeysToggleMuteHotkey": "Silenciar:",
"ControllerMotionTitle": "Opciones de controles de movimiento",
"ControllerRumbleTitle": "Opciones de vibración",
"SettingsSelectThemeFileDialogTitle": "Selecciona un archivo de tema",
"SettingsXamlThemeFile": "Archivo de tema Xaml",
"AvatarWindowTitle": "Administrar cuentas - Avatar",
"Amiibo": "Amiibo",
"Unknown": "Desconocido",
"Usage": "Uso",
"Writable": "Escribible",
"SelectDlcDialogTitle": "Selecciona archivo(s) de DLC",
"SelectUpdateDialogTitle": "Selecciona archivo(s) de actualización",
"UserProfileWindowTitle": "Administrar perfiles de usuario",
"CheatWindowTitle": "Administrar cheats",
"DlcWindowTitle": "Administrar contenido descargable",
"UpdateWindowTitle": "Administrar actualizaciones",
"CheatWindowHeading": "Cheats disponibles para {0} [{1}]",
"DlcWindowHeading": "Contenido descargable disponible para {0} [{1}]",
"UserProfilesEditProfile": "Editar selección",
"Cancel": "Cancelar",
"Save": "Guardar",
"Discard": "Descartar",
"UserProfilesSetProfileImage": "Elegir Imagen de Perfil ",
"UserProfileEmptyNameError": "El nombre es obligatorio",
"UserProfileNoImageError": "Debe establecerse la imagen de perfil",
"GameUpdateWindowHeading": "Actualizaciones disponibles para {0} [{1}]",
"SettingsTabHotkeysResScaleUpHotkey": "Aumentar la resolución:",
"SettingsTabHotkeysResScaleDownHotkey": "Disminuir la resolución:",
"UserProfilesName": "Nombre:",
"UserProfilesUserId": "Id de Usuario:",
"SettingsTabGraphicsBackend": "Fondo de gráficos",
"SettingsTabGraphicsBackendTooltip": "Graphics Backend to use",
"SettingsEnableTextureRecompression": "Enable Texture Recompression",
"SettingsEnableTextureRecompressionTooltip": "Compresses certain textures in order to reduce VRAM usage.\n\nRecommended for use with GPUs that have less than 4GiB VRAM.\n\nLeave OFF if unsure.",
"SettingsTabGraphicsPreferredGpu": "Preferred GPU",
"SettingsTabGraphicsPreferredGpuTooltip": "Select the graphics card that will be used with the Vulkan graphics backend.\n\nDoes not affect the GPU that OpenGL will use.\n\nSet to the GPU flagged as \"dGPU\" if unsure. If there isn't one, leave untouched.",
"SettingsAppRequiredRestartMessage": "Ryujinx Restart Required",
"SettingsGpuBackendRestartMessage": "Graphics Backend or GPU settings have been modified. This will require a restart to be applied",
"SettingsGpuBackendRestartSubMessage": "Do you want to restart now?",
"RyujinxUpdaterMessage": "Do you want to update Ryujinx to the latest version?",
"SettingsTabHotkeysVolumeUpHotkey": "Increase Volume:",
"SettingsTabHotkeysVolumeDownHotkey": "Decrease Volume:",
"SettingsEnableMacroHLE": "Enable Macro HLE",
"SettingsEnableMacroHLETooltip": "High-level emulation of GPU Macro code.\n\nImproves performance, but may cause graphical glitches in some games.\n\nLeave ON if unsure.",
"VolumeShort": "Vol",
"UserProfilesManageSaves": "Manage Saves",
"DeleteUserSave": "Do you want to delete user save for this game?",
"IrreversibleActionNote": "This action is not reversible.",
"SaveManagerHeading": "Manage Saves for {0}",
"SaveManagerTitle": "Save Manager",
"Name": "Name",
"Size": "Size",
"Search": "Search",
"UserProfilesRecoverLostAccounts": "Recover Lost Accounts",
"Recover": "Recover",
"UserProfilesRecoverHeading": "Saves were found for the following accounts"
}

View File

@@ -1,613 +0,0 @@
{
"MenuBarFileOpenApplet": "Ouvrir Applet",
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Ouvrir l'Applet Mii Editor en mode Standalone",
"SettingsTabInputDirectMouseAccess": "Accès direct à la souris",
"SettingsTabSystemMemoryManagerMode": "Mode de gestion mémoire :",
"SettingsTabSystemMemoryManagerModeSoftware": "Logiciel",
"SettingsTabSystemMemoryManagerModeHost": "Hôte (rapide)",
"SettingsTabSystemMemoryManagerModeHostUnchecked": "Hôte non vérifié (plus rapide, non sécurisé)",
"MenuBarFile": "_Fichier",
"MenuBarFileOpenFromFile": "_Charger un jeu depuis un fichier",
"MenuBarFileOpenUnpacked": "Charger un jeu _extrait",
"MenuBarFileOpenEmuFolder": "Ouvrir le dossier Ryujinx",
"MenuBarFileOpenLogsFolder": "Ouvrir le dossier des journaux",
"MenuBarFileExit": "_Quitter",
"MenuBarOptions": "Options",
"MenuBarOptionsToggleFullscreen": "Basculer en plein écran",
"MenuBarOptionsStartGamesInFullscreen": "Démarrer le jeu en plein écran",
"MenuBarOptionsStopEmulation": "Arrêter l'émulation",
"MenuBarOptionsSettings": "_Paramètres",
"MenuBarOptionsManageUserProfiles": "_Gêrer les profils d'utilisateurs",
"MenuBarActions": "_Actions",
"MenuBarOptionsSimulateWakeUpMessage": "Simuler une sortie de veille",
"MenuBarActionsScanAmiibo": "Scanner un Amiibo",
"MenuBarTools": "_Outils",
"MenuBarToolsInstallFirmware": "Installer un firmware",
"MenuBarFileToolsInstallFirmwareFromFile": "Installer un firmware depuis un fichier XCI ou ZIP",
"MenuBarFileToolsInstallFirmwareFromDirectory": "Installer un firmware depuis un dossier",
"MenuBarHelp": "Aide",
"MenuBarHelpCheckForUpdates": "Vérifier les mises à jour",
"MenuBarHelpAbout": "Á propos",
"MenuSearch": "Rechercher...",
"GameListHeaderFavorite": "Favoris",
"GameListHeaderIcon": "Icône",
"GameListHeaderApplication": "Application",
"GameListHeaderDeveloper": "Développeur",
"GameListHeaderVersion": "Version",
"GameListHeaderTimePlayed": "Temps de jeu",
"GameListHeaderLastPlayed": "Dernière partie",
"GameListHeaderFileExtension": "Extension du Fichier",
"GameListHeaderFileSize": "Taille du Fichier",
"GameListHeaderPath": "Chemin",
"GameListContextMenuOpenUserSaveDirectory": "Ouvrir le dossier de sauvegarde utilisateur",
"GameListContextMenuOpenUserSaveDirectoryToolTip": "Ouvre le dossier contenant la sauvegarde utilisateur du jeu",
"GameListContextMenuOpenUserDeviceDirectory": "Ouvrir le dossier de sauvegarde console",
"GameListContextMenuOpenUserDeviceDirectoryToolTip": "Ouvre le dossier contenant la sauvegarde console du jeu",
"GameListContextMenuOpenUserBcatDirectory": "Ouvrir le dossier de sauvegarde BCAT",
"GameListContextMenuOpenUserBcatDirectoryToolTip": "Ouvre le dossier contenant la sauvegarde BCAT du jeu",
"GameListContextMenuManageTitleUpdates": "Gérer les mises à jour",
"GameListContextMenuManageTitleUpdatesToolTip": "Ouvre la fenêtre de gestion des mises à jour",
"GameListContextMenuManageDlc": "Gérer les DLC",
"GameListContextMenuManageDlcToolTip": "Ouvre la fenêtre de gestion des DLC",
"GameListContextMenuOpenModsDirectory": "Ouvrir le dossier des Mods",
"GameListContextMenuOpenModsDirectoryToolTip": "Ouvre le dossier contenant les mods du jeu",
"GameListContextMenuCacheManagement": "Gestion des caches",
"GameListContextMenuCacheManagementPurgePptc": "Purger le PPTC",
"GameListContextMenuCacheManagementPurgePptcToolTip": "Supprime le PPTC du jeu",
"GameListContextMenuCacheManagementPurgeShaderCache": "Purger le cache des Shaders",
"GameListContextMenuCacheManagementPurgeShaderCacheToolTip": "Supprime le cache des shaders du jeu",
"GameListContextMenuCacheManagementOpenPptcDirectory": "Ouvrir le dossier du PPTC",
"GameListContextMenuCacheManagementOpenPptcDirectoryToolTip": "Ouvre le dossier contenant le PPTC du jeu",
"GameListContextMenuCacheManagementOpenShaderCacheDirectory": "Ouvrir le dossier du cache des shaders",
"GameListContextMenuCacheManagementOpenShaderCacheDirectoryToolTip": "Ouvre le dossier contenant le cache des shaders du jeu",
"GameListContextMenuExtractData": "Extraire les données",
"GameListContextMenuExtractDataExeFS": "ExeFS",
"GameListContextMenuExtractDataExeFSToolTip": "Extrait la section ExeFS du jeu (mise à jour incluse)",
"GameListContextMenuExtractDataRomFS": "RomFS",
"GameListContextMenuExtractDataRomFSToolTip": "Extrait la section RomFS du jeu (mise à jour incluse)",
"GameListContextMenuExtractDataLogo": "Logo",
"GameListContextMenuExtractDataLogoToolTip": "Extrait la section Logo du jeu (mise à jour incluse)",
"StatusBarGamesLoaded": "{0}/{1} Jeux chargés",
"StatusBarSystemVersion": "Version du Firmware: {0}",
"Settings": "Paramètres",
"SettingsTabGeneral": "Général",
"SettingsTabGeneralGeneral": "Général",
"SettingsTabGeneralEnableDiscordRichPresence": "Active Discord Rich Presence",
"SettingsTabGeneralCheckUpdatesOnLaunch": "Vérifier les mises à jour au démarrage",
"SettingsTabGeneralShowConfirmExitDialog": "Afficher le message de \"Confirmation de fermeture\"",
"SettingsTabGeneralHideCursorOnIdle": "Masquer le curseur si inactif",
"SettingsTabGeneralGameDirectories": "Dossiers de Jeux",
"SettingsTabGeneralAdd": "Ajouter",
"SettingsTabGeneralRemove": "Supprimer",
"SettingsTabSystem": "Système",
"SettingsTabSystemCore": "Cœur",
"SettingsTabSystemSystemRegion": "Région du système:",
"SettingsTabSystemSystemRegionJapan": "Japon",
"SettingsTabSystemSystemRegionUSA": "USA",
"SettingsTabSystemSystemRegionEurope": "Europe",
"SettingsTabSystemSystemRegionAustralia": "Australie",
"SettingsTabSystemSystemRegionChina": "Chine",
"SettingsTabSystemSystemRegionKorea": "Corée",
"SettingsTabSystemSystemRegionTaiwan": "Taïwan",
"SettingsTabSystemSystemLanguage": "Langue du système:",
"SettingsTabSystemSystemLanguageJapanese": "Japonais",
"SettingsTabSystemSystemLanguageAmericanEnglish": "Américain",
"SettingsTabSystemSystemLanguageFrench": "Français",
"SettingsTabSystemSystemLanguageGerman": "Allemand",
"SettingsTabSystemSystemLanguageItalian": "Italien",
"SettingsTabSystemSystemLanguageSpanish": "Espagnol",
"SettingsTabSystemSystemLanguageChinese": "Chinois",
"SettingsTabSystemSystemLanguageKorean": "Coréen",
"SettingsTabSystemSystemLanguageDutch": "Néerlandais",
"SettingsTabSystemSystemLanguagePortuguese": "Portugais",
"SettingsTabSystemSystemLanguageRussian": "Russe",
"SettingsTabSystemSystemLanguageTaiwanese": "Taïwanais",
"SettingsTabSystemSystemLanguageBritishEnglish": "Anglais",
"SettingsTabSystemSystemLanguageCanadianFrench": "Canadien",
"SettingsTabSystemSystemLanguageLatinAmericanSpanish": "Espagnol latino-américain",
"SettingsTabSystemSystemLanguageSimplifiedChinese": "Chinois simplifié",
"SettingsTabSystemSystemLanguageTraditionalChinese": "Chinois traditionnel",
"SettingsTabSystemSystemTimeZone": "Fuseau horaire du système:",
"SettingsTabSystemSystemTime": "Heure du système:",
"SettingsTabSystemEnableVsync": "Activer la VSync",
"SettingsTabSystemEnablePptc": "Activer le PPTC (Profiled Persistent Translation Cache)",
"SettingsTabSystemEnableFsIntegrityChecks": "Activer la vérification de l'intégrité du système de fichiers",
"SettingsTabSystemAudioBackend": "Bibliothèque Audio :",
"SettingsTabSystemAudioBackendDummy": "Factice",
"SettingsTabSystemAudioBackendOpenAL": "OpenAL",
"SettingsTabSystemAudioBackendSoundIO": "SoundIO",
"SettingsTabSystemAudioBackendSDL2": "SDL2",
"SettingsTabSystemHacks": "Hacks",
"SettingsTabSystemHacksNote": " (Cela peut causer des instabilités)",
"SettingsTabSystemExpandDramSize": "Augmenter la taille de la DRAM à 6GiB",
"SettingsTabSystemIgnoreMissingServices": "Ignorer les services manquant",
"SettingsTabGraphics": "Graphique",
"SettingsTabGraphicsAPI": "API Graphique",
"SettingsTabGraphicsEnableShaderCache": "Activer le cache des shaders",
"SettingsTabGraphicsAnisotropicFiltering": "Filtrage anisotrope:",
"SettingsTabGraphicsAnisotropicFilteringAuto": "Auto",
"SettingsTabGraphicsAnisotropicFiltering2x": "x2",
"SettingsTabGraphicsAnisotropicFiltering4x": "x4",
"SettingsTabGraphicsAnisotropicFiltering8x": "x8",
"SettingsTabGraphicsAnisotropicFiltering16x": "x16",
"SettingsTabGraphicsResolutionScale": "Échelle de résolution:",
"SettingsTabGraphicsResolutionScaleCustom": "Customisée (Non recommandée)",
"SettingsTabGraphicsResolutionScaleNative": "Natif (720p/1080p)",
"SettingsTabGraphicsResolutionScale2x": "x2 (1440p/2160p)",
"SettingsTabGraphicsResolutionScale3x": "x3 (2160p/3240p)",
"SettingsTabGraphicsResolutionScale4x": "x4 (2880p/4320p)",
"SettingsTabGraphicsAspectRatio": "Format:",
"SettingsTabGraphicsAspectRatio4x3": "4:3",
"SettingsTabGraphicsAspectRatio16x9": "16:9",
"SettingsTabGraphicsAspectRatio16x10": "16:10",
"SettingsTabGraphicsAspectRatio21x9": "21:9",
"SettingsTabGraphicsAspectRatio32x9": "32:9",
"SettingsTabGraphicsAspectRatioStretch": "Écran étiré",
"SettingsTabGraphicsDeveloperOptions": "Options développeur",
"SettingsTabGraphicsShaderDumpPath": "Chemin du dossier de dump des shaders:",
"SettingsTabLogging": "Journaux",
"SettingsTabLoggingLogging": "Journaux",
"SettingsTabLoggingEnableLoggingToFile": "Activer la sauvegarde des journaux vers un fichier",
"SettingsTabLoggingEnableStubLogs": "Activer les journaux stub",
"SettingsTabLoggingEnableInfoLogs": "Activer les journaux d'informations",
"SettingsTabLoggingEnableWarningLogs": "Activer les journaux d'avertissements",
"SettingsTabLoggingEnableErrorLogs": "Activer les journaux d'erreurs",
"SettingsTabLoggingEnableTraceLogs": "Activer journaux d'erreurs Trace",
"SettingsTabLoggingEnableGuestLogs": "Activer les journaux du programme simulé",
"SettingsTabLoggingEnableFsAccessLogs": "Activer les journaux des accès au système de fichiers",
"SettingsTabLoggingFsGlobalAccessLogMode": "Niveau des journaux des accès au système de fichiers:",
"SettingsTabLoggingDeveloperOptions": "Options développeur (ATTENTION: Cela peut réduire les performances)",
"SettingsTabLoggingGraphicsBackendLogLevel": "Niveau du journal du backend graphique :",
"SettingsTabLoggingGraphicsBackendLogLevelNone": "Aucun",
"SettingsTabLoggingGraphicsBackendLogLevelError": "Erreur",
"SettingsTabLoggingGraphicsBackendLogLevelPerformance": "Ralentissements",
"SettingsTabLoggingGraphicsBackendLogLevelAll": "Tout",
"SettingsTabLoggingEnableDebugLogs": "Activer les journaux de debug",
"SettingsTabInput": "Contrôles",
"SettingsTabInputEnableDockedMode": "Active le mode station d'accueil",
"SettingsTabInputDirectKeyboardAccess": "Accès direct au clavier",
"SettingsButtonSave": "Enregistrer",
"SettingsButtonClose": "Fermer",
"SettingsButtonOk": "OK",
"SettingsButtonCancel": "Annuler",
"SettingsButtonApply": "Appliquer",
"ControllerSettingsPlayer": "Joueur",
"ControllerSettingsPlayer1": "Joueur 1",
"ControllerSettingsPlayer2": "Joueur 2",
"ControllerSettingsPlayer3": "Joueur 3",
"ControllerSettingsPlayer4": "Joueur 4",
"ControllerSettingsPlayer5": "Joueur 5",
"ControllerSettingsPlayer6": "Joueur 6",
"ControllerSettingsPlayer7": "Joueur 7",
"ControllerSettingsPlayer8": "Joueur 8",
"ControllerSettingsHandheld": "Portable",
"ControllerSettingsInputDevice": "Périphériques",
"ControllerSettingsRefresh": "Actualiser",
"ControllerSettingsDeviceDisabled": "Désactivé",
"ControllerSettingsControllerType": "Type de Controleur",
"ControllerSettingsControllerTypeHandheld": "Portable",
"ControllerSettingsControllerTypeProController": "Pro Controller",
"ControllerSettingsControllerTypeJoyConPair": "JoyCon Joints",
"ControllerSettingsControllerTypeJoyConLeft": "JoyCon Gauche",
"ControllerSettingsControllerTypeJoyConRight": "JoyCon Droite",
"ControllerSettingsProfile": "Profil",
"ControllerSettingsProfileDefault": "Défaut",
"ControllerSettingsLoad": "Charger",
"ControllerSettingsAdd": "Ajouter",
"ControllerSettingsRemove": "Supprimer",
"ControllerSettingsButtons": "Boutons",
"ControllerSettingsButtonA": "A",
"ControllerSettingsButtonB": "B",
"ControllerSettingsButtonX": "X",
"ControllerSettingsButtonY": "Y",
"ControllerSettingsButtonPlus": "+",
"ControllerSettingsButtonMinus": "-",
"ControllerSettingsDPad": "Croix Directionnelle",
"ControllerSettingsDPadUp": "Haut",
"ControllerSettingsDPadDown": "Bas",
"ControllerSettingsDPadLeft": "Gauche",
"ControllerSettingsDPadRight": "Droite",
"ControllerSettingsLStick": "Joystick Gauche",
"ControllerSettingsLStickButton": "Bouton",
"ControllerSettingsLStickUp": "Haut",
"ControllerSettingsLStickDown": "Bas",
"ControllerSettingsLStickLeft": "Gauche",
"ControllerSettingsLStickRight": "Droite",
"ControllerSettingsLStickStick": "Joystick",
"ControllerSettingsLStickInvertXAxis": "Inverser l'axe X",
"ControllerSettingsLStickInvertYAxis": "Inverser l'axe Y",
"ControllerSettingsLStickDeadzone": "Zone morte:",
"ControllerSettingsRStick": "Joystick Droit",
"ControllerSettingsRStickButton": "Bouton",
"ControllerSettingsRStickUp": "Haut",
"ControllerSettingsRStickDown": "Bas",
"ControllerSettingsRStickLeft": "Gauche",
"ControllerSettingsRStickRight": "Droite",
"ControllerSettingsRStickStick": "Joystick",
"ControllerSettingsRStickInvertXAxis": "Inverser l'axe X",
"ControllerSettingsRStickInvertYAxis": "Inverser l'axe Y",
"ControllerSettingsRStickDeadzone": "Zone morte:",
"ControllerSettingsTriggersLeft": "Gachettes Gauche",
"ControllerSettingsTriggersRight": "Gachettes Droite",
"ControllerSettingsTriggersButtonsLeft": "Boutons Gachettes Gauche",
"ControllerSettingsTriggersButtonsRight": "Boutons Gachettes Droite",
"ControllerSettingsTriggers": "Gachettes",
"ControllerSettingsTriggerL": "L",
"ControllerSettingsTriggerR": "R",
"ControllerSettingsTriggerZL": "ZL",
"ControllerSettingsTriggerZR": "ZR",
"ControllerSettingsLeftSL": "SL",
"ControllerSettingsLeftSR": "SR",
"ControllerSettingsRightSL": "SL",
"ControllerSettingsRightSR": "SR",
"ControllerSettingsExtraButtonsLeft": "Boutons Gauche",
"ControllerSettingsExtraButtonsRight": "Boutons Droite",
"ControllerSettingsMisc": "Divers",
"ControllerSettingsTriggerThreshold": "Seuil de gachettes:",
"ControllerSettingsMotion": "Mouvements",
"ControllerSettingsMotionUseCemuhookCompatibleMotion": "Utiliser un capteur de mouvements CemuHook",
"ControllerSettingsMotionControllerSlot": "Contrôleur ID:",
"ControllerSettingsMotionMirrorInput": "Inverser les contrôles",
"ControllerSettingsMotionRightJoyConSlot": "JoyCon Droit ID:",
"ControllerSettingsMotionServerHost": "Addresse du Server:",
"ControllerSettingsMotionGyroSensitivity": "Sensibilitée du gyroscope:",
"ControllerSettingsMotionGyroDeadzone": "Zone morte du gyroscope:",
"ControllerSettingsSave": "Enregistrer",
"ControllerSettingsClose": "Fermer",
"UserProfilesSelectedUserProfile": "Choisir un profil utilisateur:",
"UserProfilesSaveProfileName": "Enregistrer le nom du profil",
"UserProfilesChangeProfileImage": "Changer l'image du profil",
"UserProfilesAvailableUserProfiles": "Profils utilisateurs disponible:",
"UserProfilesAddNewProfile": "Ajouter un nouveau profil",
"UserProfilesDeleteSelectedProfile": "Supprimer le profil sélectionné",
"UserProfilesClose": "Fermer",
"ProfileImageSelectionTitle": "Sélection de l'image du profil",
"ProfileImageSelectionHeader": "Choisir l'image du profil",
"ProfileImageSelectionNote": "Vous pouvez importer une image de profil personnalisée ou sélectionner un avatar à partir du firmware",
"ProfileImageSelectionImportImage": "Importer une image",
"ProfileImageSelectionSelectAvatar": "Choisir un avatar du firmware",
"InputDialogTitle": "Fenêtre d'entrée de texte",
"InputDialogOk": "OK",
"InputDialogCancel": "Annuler",
"InputDialogAddNewProfileTitle": "Choisir un nom de profil",
"InputDialogAddNewProfileHeader": "Merci d'entrer un nom de profil",
"InputDialogAddNewProfileSubtext": "(Longueur max.: {0})",
"AvatarChoose": "Choisir",
"AvatarSetBackgroundColor": "Choisir une couleur de fond",
"AvatarClose": "Fermer",
"ControllerSettingsLoadProfileToolTip": "Charger un profil",
"ControllerSettingsAddProfileToolTip": "Ajouter un profil",
"ControllerSettingsRemoveProfileToolTip": "Supprimer un profil",
"ControllerSettingsSaveProfileToolTip": "Enregistrer un profil",
"MenuBarFileToolsTakeScreenshot": "Prendre une Capture d'Écran",
"MenuBarFileToolsHideUi": "Masquer l'interface utilisateur",
"GameListContextMenuToggleFavorite": "Ajouter/Retirer des favoris",
"GameListContextMenuToggleFavoriteToolTip": "Activer/désactiver le statut favori du jeu",
"SettingsTabGeneralTheme": "Thème",
"SettingsTabGeneralThemeCustomTheme": "Chemin du thème personnalisé",
"SettingsTabGeneralThemeBaseStyle": "Style par défaut",
"SettingsTabGeneralThemeBaseStyleDark": "Sombre",
"SettingsTabGeneralThemeBaseStyleLight": "Lumière",
"SettingsTabGeneralThemeEnableCustomTheme": "Activer un Thème Personnalisé",
"ButtonBrowse": "Parcourir",
"ControllerSettingsConfigureGeneral": "Configurer",
"ControllerSettingsRumble": "Vibreur",
"ControllerSettingsRumbleStrongMultiplier": "Multiplicateur de vibrations fortes",
"ControllerSettingsRumbleWeakMultiplier": "Multiplicateur de vibrations faibles",
"DialogMessageSaveNotAvailableMessage": "Il n'y a aucune sauvegarde pour {0} [{1:x16}]",
"DialogMessageSaveNotAvailableCreateSaveMessage": "Voulez-vous créer une sauvegarde pour ce jeu ?",
"DialogConfirmationTitle": "Ryujinx - Confirmation",
"DialogUpdaterTitle": "Ryujinx - Mise à Jour",
"DialogErrorTitle": "Ryujinx - Erreur",
"DialogWarningTitle": "Ryujinx - Avertissement",
"DialogExitTitle": "Ryujinx - Quitter",
"DialogErrorMessage": "Ryujinx a rencontré une erreur",
"DialogExitMessage": "Êtes-vous sûr de vouloir fermer Ryujinx ?",
"DialogExitSubMessage": "Toute progression non sauvegardée sera perdue.",
"DialogMessageCreateSaveErrorMessage": "Une erreur s'est produite lors de la création de la sauvegarde spécifiée : {0}",
"DialogMessageFindSaveErrorMessage": "Une erreur s'est produite lors de la recherche de la sauvegarde spécifiée : {0}",
"FolderDialogExtractTitle": "Choisissez le dossier dans lequel extraire",
"DialogNcaExtractionMessage": "Extraction de la section {0} depuis {1}...",
"DialogNcaExtractionTitle": "Ryujinx - Extracteur de la section NCA",
"DialogNcaExtractionMainNcaNotFoundErrorMessage": "Échec de l'extraction. Le NCA principal n'était pas présent dans le fichier sélectionné.",
"DialogNcaExtractionCheckLogErrorMessage": "Échec de l'extraction. Lisez le fichier journal pour plus d'informations.",
"DialogNcaExtractionSuccessMessage": "Extraction terminée avec succès.",
"DialogUpdaterConvertFailedMessage": "Échec de la conversion de la version actuelle de Ryujinx.",
"DialogUpdaterCancelUpdateMessage": "Annuler la mise à jour!",
"DialogUpdaterAlreadyOnLatestVersionMessage": "Vous utilisez déjà la version la plus mise à jour de Ryujinx!",
"DialogUpdaterFailedToGetVersionMessage": "Une erreur s'est produite lors de la tentative d'obtention des informations de publication de la version GitHub. Cela peut survenir lorsqu'une nouvelle version est en cours de compilation par GitHub Actions. Réessayez dans quelques minutes.",
"DialogUpdaterConvertFailedGithubMessage": "Impossible de convertir la version reçue de Ryujinx depuis Github Release.",
"DialogUpdaterDownloadingMessage": "Téléchargement de la mise à jour...",
"DialogUpdaterExtractionMessage": "Extraction de la mise à jour…",
"DialogUpdaterRenamingMessage": "Renommage de la mise à jour...",
"DialogUpdaterAddingFilesMessage": "Ajout d'une nouvelle mise à jour...",
"DialogUpdaterCompleteMessage": "Mise à jour terminée !",
"DialogUpdaterRestartMessage": "Voulez-vous redémarrer Ryujinx maintenant ?",
"DialogUpdaterArchNotSupportedMessage": "Vous n'utilisez pas d'architecture système prise en charge !",
"DialogUpdaterArchNotSupportedSubMessage": "(Seuls les systèmes x64 sont pris en charge!)",
"DialogUpdaterNoInternetMessage": "Vous n'êtes pas connecté à Internet !",
"DialogUpdaterNoInternetSubMessage": "Veuillez vérifier que vous avez une connexion Internet fonctionnelle!",
"DialogUpdaterDirtyBuildMessage": "Vous ne pouvez pas mettre à jour une version Dirty de Ryujinx!",
"DialogUpdaterDirtyBuildSubMessage": "Veuillez télécharger Ryujinx sur https://ryujinx.org/ si vous recherchez une version prise en charge.",
"DialogRestartRequiredMessage": "Redémarrage Requis",
"DialogThemeRestartMessage": "Le thème a été enregistré. Un redémarrage est requis pour appliquer le thème.",
"DialogThemeRestartSubMessage": "Voulez-vous redémarrer",
"DialogFirmwareInstallEmbeddedMessage": "Voulez-vous installer le firmware intégré dans ce jeu ? (Firmware {0})",
"DialogFirmwareInstallEmbeddedSuccessMessage": "Aucun firmware installé n'a été trouvé mais Ryujinx a pu installer le firmware {0} à partir du jeu fourni.\\nL'émulateur va maintenant démarrer.",
"DialogFirmwareNoFirmwareInstalledMessage": "Aucun Firmware installé",
"DialogFirmwareInstalledMessage": "Le firmware {0} a été installé",
"DialogOpenSettingsWindowLabel": "Ouvrir la fenêtre de configuration",
"DialogControllerAppletTitle": "Controller Applet",
"DialogMessageDialogErrorExceptionMessage": "Erreur lors de l'affichage de la boîte de dialogue : {0}",
"DialogSoftwareKeyboardErrorExceptionMessage": "Erreur lors de l'affichage du clavier logiciel: {0}",
"DialogErrorAppletErrorExceptionMessage": "Erreur lors de l'affichage de la boîte de dialogue ErrorApplet: {0}",
"DialogUserErrorDialogMessage": "{0}: {1}",
"DialogUserErrorDialogInfoMessage": "\nPour plus d'informations sur la manière de corriger cette erreur, suivez notre Guide d'Installation.",
"DialogUserErrorDialogTitle": "Erreur Ryujinx ({0})",
"DialogAmiiboApiTitle": "Amiibo API",
"DialogAmiiboApiFailFetchMessage": "Une erreur est survenue lors de la récupération des informations de l'API.",
"DialogAmiiboApiConnectErrorMessage": "Impossible de se connecter au serveur API Amiibo. Le service est peut-être hors service ou vous devriez peut-être vérifier que votre connexion internet est connectée.",
"DialogProfileInvalidProfileErrorMessage": "Le profil {0} est incompatible avec le système de configuration de manette actuel.",
"DialogProfileDefaultProfileOverwriteErrorMessage": "Le profil par défaut ne peut pas être écrasé",
"DialogProfileDeleteProfileTitle": "Supprimer le profil",
"DialogProfileDeleteProfileMessage": "Cette action est irréversible, êtes-vous sûr de vouloir continuer ?",
"DialogWarning": "Avertissement",
"DialogPPTCDeletionMessage": "Vous êtes sur le point de mettre en file d'attente une reconstruction PPTC au prochain démarrage de :\n\n{0}\n\nÊtes-vous sûr de vouloir continuer ?",
"DialogPPTCDeletionErrorMessage": "Erreur lors de la purge du cache PPTC à {0}: {1}",
"DialogShaderDeletionMessage": "Vous êtes sur le point de supprimer le cache du Shader pour :\n\n{0}\n\nÊtes-vous sûr de vouloir continuer ?",
"DialogShaderDeletionErrorMessage": "Erreur lors de la purge du cache du Shader à {0}: {1}",
"DialogRyujinxErrorMessage": "Ryujinx a rencontré une erreur",
"DialogInvalidTitleIdErrorMessage": "Erreur d'UI : le jeu sélectionné n'a pas d'ID de titre valide",
"DialogFirmwareInstallerFirmwareNotFoundErrorMessage": "Un firmware valide n'a pas été trouvé dans {0}.",
"DialogFirmwareInstallerFirmwareInstallTitle": "Installer le Firmware {0}",
"DialogFirmwareInstallerFirmwareInstallMessage": "La version {0} du système sera installée.",
"DialogFirmwareInstallerFirmwareInstallSubMessage": "\n\nCela remplacera la version actuelle du système {0}.",
"DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\nVoulez-vous continuer ?",
"DialogFirmwareInstallerFirmwareInstallWaitMessage": "Installation du firmware...",
"DialogFirmwareInstallerFirmwareInstallSuccessMessage": "Version du système {0} installée avec succès.",
"DialogUserProfileDeletionWarningMessage": "Il n'y aurait aucun autre profil à ouvrir si le profil sélectionné est supprimé",
"DialogUserProfileDeletionConfirmMessage": "Voulez-vous supprimer le profil sélectionné ?",
"DialogControllerSettingsModifiedConfirmMessage": "Les paramètres actuels du contrôleur ont été mis à jour.",
"DialogControllerSettingsModifiedConfirmSubMessage": "Voulez-vous sauvegarder?",
"DialogDlcLoadNcaErrorMessage": "{0}. Fichier erroné : {1}",
"DialogDlcNoDlcErrorMessage": "Le fichier spécifié ne contient pas de DLC pour le titre sélectionné !",
"DialogPerformanceCheckLoggingEnabledMessage": "Vous avez activé la journalisation des traces, conçue pour être utilisée uniquement par les développeurs.",
"DialogPerformanceCheckLoggingEnabledConfirmMessage": "Pour des performances optimales, il est recommandé de désactiver la journalisation des traces. Souhaitez-vous désactiver la journalisation des traces maintenant ?",
"DialogPerformanceCheckShaderDumpEnabledMessage": "Vous avez activé l'extraction des shaders, qui est conçu pour être utilisé par les développeurs uniquement.",
"DialogPerformanceCheckShaderDumpEnabledConfirmMessage": "Pour des performances optimales, il est recommandé de désactiver l'extraction des shaders. Souhaitez-vous désactiver l'extraction des shaders maintenant ?",
"DialogLoadAppGameAlreadyLoadedMessage": "Un jeu a déjà été chargé",
"DialogLoadAppGameAlreadyLoadedSubMessage": "Veuillez arrêter l'émulation ou fermer l'émulateur avant de lancer un autre jeu.",
"DialogUpdateAddUpdateErrorMessage": "Le fichier spécifié ne contient pas de mise à jour pour le titre sélectionné !",
"DialogSettingsBackendThreadingWarningTitle": "Avertissement - Backend Threading ",
"DialogSettingsBackendThreadingWarningMessage": "Ryujinx doit être redémarré après avoir changé cette option pour qu'elle s'applique complètement. Selon votre plate-forme, vous devrez peut-être désactiver manuellement le multithreading de votre pilote lorsque vous utilisez Ryujinx.",
"SettingsTabGraphicsFeaturesOptions": "Fonctionnalités",
"SettingsTabGraphicsBackendMultithreading": "Interface graphique multithread",
"CommonAuto": "Auto",
"CommonOff": "Désactivé",
"CommonOn": "Activé",
"InputDialogYes": "Oui",
"InputDialogNo": "Non",
"DialogProfileInvalidProfileNameErrorMessage": "Le nom du fichier contient des caractères invalides. Veuillez réessayer.",
"MenuBarOptionsPauseEmulation": "Suspendre",
"MenuBarOptionsResumeEmulation": "Reprendre",
"AboutUrlTooltipMessage": "Cliquez pour ouvrir le site de Ryujinx dans votre navigateur par défaut.",
"AboutDisclaimerMessage": "Ryujinx n'est pas affilié à Nintendo™,\nou à aucun de ses partenaires, de quelque manière que ce soit.",
"AboutAmiiboDisclaimerMessage": "AmiiboAPI (www.amiiboapi.com) est utilisé\ndans notre émulation Amiibo.",
"AboutPatreonUrlTooltipMessage": "Cliquez pour ouvrir la page Patreon de Ryujinx dans votre navigateur par défaut.",
"AboutGithubUrlTooltipMessage": "Cliquez pour ouvrir la page GitHub de Ryujinx dans votre navigateur par défaut.",
"AboutDiscordUrlTooltipMessage": "Cliquez pour ouvrir une invitation au serveur Discord de Ryujinx dans votre navigateur par défaut.",
"AboutTwitterUrlTooltipMessage": "Cliquez pour ouvrir la page Twitter de Ryujinx dans votre navigateur par défaut.",
"AboutRyujinxAboutTitle": "Á propos:",
"AboutRyujinxAboutContent": "Ryujinx est un émulateur pour la Nintendo Switch™.\nMerci de nous soutenir sur Patreon.\nObtenez toutes les dernières actualités sur notre Twitter ou notre Discord.\nLes développeurs intéressés à contribuer peuvent en savoir plus sur notre GitHub ou notre Discord.",
"AboutRyujinxMaintainersTitle": "Maintenu par :",
"AboutRyujinxMaintainersContentTooltipMessage": "Cliquez pour ouvrir la page Contributeurs dans votre navigateur par défaut.",
"AboutRyujinxSupprtersTitle": "Supporté sur Patreon par :",
"AmiiboSeriesLabel": "Séries Amiibo",
"AmiiboCharacterLabel": "Personnage",
"AmiiboScanButtonLabel": "Scanner",
"AmiiboOptionsShowAllLabel": "Afficher tous les Amiibo",
"AmiiboOptionsUsRandomTagLabel": "Hack : Utiliser un tag Uuid aléatoire",
"DlcManagerTableHeadingEnabledLabel": "Activé",
"DlcManagerTableHeadingTitleIdLabel": "ID du titre",
"DlcManagerTableHeadingContainerPathLabel": "Chemin du conteneur",
"DlcManagerTableHeadingFullPathLabel": "Chemin complet",
"DlcManagerRemoveAllButton": "Tout supprimer",
"DlcManagerEnableAllButton": "Activer Tout",
"DlcManagerDisableAllButton": "Désactiver Tout",
"MenuBarOptionsChangeLanguage": "Changer la Langue",
"CommonSort": "Trier",
"CommonShowNames": "Afficher les noms",
"CommonFavorite": "Favoris",
"OrderAscending": "Croissant",
"OrderDescending": "Décroissant",
"SettingsTabGraphicsFeatures": "Fonctionnalités & Améliorations",
"ErrorWindowTitle": "Fenêtre d'erreur",
"ToggleDiscordTooltip": "Choisissez d'afficher ou non Ryujinx sur votre activité « en cours de jeu » Discord",
"AddGameDirBoxTooltip": "Entrez un répertoire de jeux à ajouter à la liste",
"AddGameDirTooltip": "Ajouter un répertoire de jeux à la liste",
"RemoveGameDirTooltip": "Supprimer le dossier sélectionné",
"CustomThemeCheckTooltip": "Use a custom Avalonia theme for the GUI to change the appearance of the emulator menus",
"CustomThemePathTooltip": "Chemin vers le thème personnalisé de l'interface utilisateur",
"CustomThemeBrowseTooltip": "Parcourir vers un thème personnalisé pour l'interface utilisateur",
"DockModeToggleTooltip": "Le mode station d'accueil permet à la console émulée de se comporter comme une Nintendo Switch en mode station d'accueil, ce qui améliore la fidélité graphique dans la plupart des jeux. Inversement, la désactivation de cette option rendra la console émulée comme une console Nintendo Switch portable, réduisant la qualité graphique.\n\nConfigurer les controles du joueur 1 si vous prévoyez d'utiliser le mode station d'accueil; configurez les commandes portable si vous prévoyez d'utiliser le mode portable.\n\nLaissez ACTIVER si vous n'êtes pas sûr.",
"DirectKeyboardTooltip": "Direct keyboard access (HID) support. Provides games access to your keyboard as a text entry device.",
"DirectMouseTooltip": "Direct mouse access (HID) support. Provides games access to your mouse as a pointing device.",
"RegionTooltip": "Changer la région du système",
"LanguageTooltip": "Changer la langue du système",
"TimezoneTooltip": "Changer le fuseau horaire du système",
"TimeTooltip": "Changer l'heure du système",
"VSyncToggleTooltip": "Emulated console's Vertical Sync. Essentially a frame-limiter for the majority of games; disabling it may cause games to run at higher speed or make loading screens take longer or get stuck.\n\nCan be toggled in-game with a hotkey of your preference. We recommend doing this if you plan on disabling it.\n\nLeave ON if unsure.",
"PptcToggleTooltip": "Saves translated JIT functions so that they do not need to be translated every time the game loads.\n\nReduces stuttering and significantly speeds up boot times after the first boot of a game.\n\nLeave ON if unsure.",
"FsIntegrityToggleTooltip": "Checks for corrupt files when booting a game, and if corrupt files are detected, displays a hash error in the log.\n\nHas no impact on performance and is meant to help troubleshooting.\n\nLeave ON if unsure.",
"AudioBackendTooltip": "Changes the backend used to render audio.\n\nSDL2 is the preferred one, while OpenAL and SoundIO are used as fallbacks. Dummy will have no sound.\n\nSet to SDL2 if unsure.",
"MemoryManagerTooltip": "Change how guest memory is mapped and accessed. Greatly affects emulated CPU performance.\n\nSet to HOST UNCHECKED if unsure.",
"MemoryManagerSoftwareTooltip": "Use a software page table for address translation. Highest accuracy but slowest performance.",
"MemoryManagerHostTooltip": "Directly map memory in the host address space. Much faster JIT compilation and execution.",
"MemoryManagerUnsafeTooltip": "Directly map memory, but do not mask the address within the guest address space before access. Faster, but at the cost of safety. The guest application can access memory from anywhere in Ryujinx, so only run programs you trust with this mode.",
"DRamTooltip": "Utilizes an alternative MemoryMode layout to mimic a Switch development model.\n\nThis is only useful for higher-resolution texture packs or 4k resolution mods. Does NOT improve performance.\n\nLeave OFF if unsure.",
"IgnoreMissingServicesTooltip": "Ignores unimplemented Horizon OS services. This may help in bypassing crashes when booting certain games.\n\nLeave OFF if unsure.",
"GraphicsBackendThreadingTooltip": "Executes graphics backend commands on a second thread.\n\nSpeeds up shader compilation, reduces stuttering, and improves performance on GPU drivers without multithreading support of their own. Slightly better performance on drivers with multithreading.\n\nSet to AUTO if unsure.",
"GalThreadingTooltip": "Executes graphics backend commands on a second thread.\n\nSpeeds up shader compilation, reduces stuttering, and improves performance on GPU drivers without multithreading support of their own. Slightly better performance on drivers with multithreading.\n\nSet to AUTO if unsure.",
"ShaderCacheToggleTooltip": "Saves a disk shader cache which reduces stuttering in subsequent runs.\n\nLeave ON if unsure.",
"ResolutionScaleTooltip": "Resolution Scale applied to applicable render targets",
"ResolutionScaleEntryTooltip": "Floating point resolution scale, such as 1.5. Non-integral scales are more likely to cause issues or crash.",
"AnisotropyTooltip": "Level of Anisotropic Filtering (set to Auto to use the value requested by the game)",
"AspectRatioTooltip": "Ratio d'aspect appliqué à la fenêtre de rendu",
"ShaderDumpPathTooltip": "Chemin de copie des Shaders Graphiques",
"FileLogTooltip": "Sauver le journal de la console dans un fichier journal sur le disque. Cela n'affecte pas les performances.",
"StubLogTooltip": "Prints stub log messages in the console. Does not affect performance.",
"InfoLogTooltip": "Prints info log messages in the console. Does not affect performance.",
"WarnLogTooltip": "Prints warning log messages in the console. Does not affect performance.",
"ErrorLogTooltip": "Prints error log messages in the console. Does not affect performance.",
"TraceLogTooltip": "Prints trace log messages in the console. Does not affect performance.",
"GuestLogTooltip": "Prints guest log messages in the console. Does not affect performance.",
"FileAccessLogTooltip": "Prints file access log messages in the console.",
"FSAccessLogModeTooltip": "Enables FS access log output to the console. Possible modes are 0-3",
"DeveloperOptionTooltip": "Utiliser avec précaution",
"OpenGlLogLevel": "Nécessite l'activation des niveaux de journalisation appropriés",
"DebugLogTooltip": "Prints debug log messages in the console.\n\nOnly use this if specifically instructed by a staff member, as it will make logs difficult to read and worsen emulator performance.",
"LoadApplicationFileTooltip": "Ouvrir un explorateur de fichiers pour choisir un fichier compatible Switch à charger",
"LoadApplicationFolderTooltip": "Ouvrir un explorateur de fichiers pour choisir une application Switch compatible et décompressée à charger",
"OpenRyujinxFolderTooltip": "Ouvrir le dossier du système de fichiers Ryujinx",
"OpenRyujinxLogsTooltip": "Ouvre le dossier dans lequel les journaux sont écrits",
"ExitTooltip": "Quitter Ryujinx",
"OpenSettingsTooltip": "Ouvrir la fenêtre de configuration",
"OpenProfileManagerTooltip": "Ouvrir la fenêtre du gestionnaire de profils d'utilisateurs",
"StopEmulationTooltip": "Arrêter l'émulation du jeu en cours et revenir à la sélection des jeux",
"CheckUpdatesTooltip": "Vérifier les mises à jour de Ryujinx",
"OpenAboutTooltip": "Ouvrir la fenêtre À Propos",
"GridSize": "Taille de la grille",
"GridSizeTooltip": "Modifier la taille des éléments de la grille",
"SettingsTabSystemSystemLanguageBrazilianPortuguese": "Portugais brésilien",
"AboutRyujinxContributorsButtonHeader": "Voir tous les contributeurs",
"SettingsTabSystemAudioVolume": "Volume :",
"AudioVolumeTooltip": "Modifier le volume audio",
"SettingsTabSystemEnableInternetAccess": "Accès Internet Invité/Mode LAN",
"EnableInternetAccessTooltip": "Permet à l'application émulée de se connecter à Internet.\n\nLes jeux avec un mode LAN peuvent se connecter les uns aux autres lorsque cette option est cochée et que les systèmes sont connectés au même point d'accès. Cela inclut également les vrais consoles.\n\nCette option n'autorise PAS la connexion aux serveurs Nintendo. Elle peut faire planter certains jeux qui essaient de se connecter à l'Internet.\n\nLaissez DÉSACTIVÉ si vous n'êtes pas sûr.",
"GameListContextMenuManageCheatToolTip": "Gérer la triche",
"GameListContextMenuManageCheat": "Gérer la triche",
"ControllerSettingsStickRange": "Intervalle:",
"DialogStopEmulationTitle": "Ryujinx - Arrêt de l'émulation",
"DialogStopEmulationMessage": "Êtes-vous sûr de vouloir arrêter l'émulation ?",
"SettingsTabCpu": "CPU",
"SettingsTabAudio": "Audio",
"SettingsTabNetwork": "Réseau",
"SettingsTabNetworkConnection": "Connexion réseau",
"SettingsTabCpuCache": "Cache CPU",
"SettingsTabCpuMemory": "Mémoire CPU",
"DialogUpdaterFlatpakNotSupportedMessage": "Merci de mettre à jour Ryujinx via FlatHub.",
"UpdaterDisabledWarningTitle": "Mise à jour désactivée !",
"GameListContextMenuOpenSdModsDirectory": "Ouvrir le dossier Mods d'Atmosphère",
"GameListContextMenuOpenSdModsDirectoryToolTip": "Ouvre le répertoire alternatif de carte SD Atmosphère qui contient les Mods d'Application. Utile pour les mods qui sont conçu pour le vrai matériel.",
"ControllerSettingsRotate90": "Rotation 90° horaire",
"IconSize": "Taille d'icône",
"IconSizeTooltip": "Changer la taille des icônes de jeu",
"MenuBarOptionsShowConsole": "Afficher la console",
"ShaderCachePurgeError": "Erreur lors de la purge du cache du Shader à {0}: {1}",
"UserErrorNoKeys": "Clés introuvables",
"UserErrorNoFirmware": "Firmware introuvable",
"UserErrorFirmwareParsingFailed": "Erreur d'analyse du firmware",
"UserErrorApplicationNotFound": " Application introuvable",
"UserErrorUnknown": "Erreur inconnue",
"UserErrorUndefined": "Erreur non définie",
"UserErrorNoKeysDescription": "Ryujinx n'a pas trouvé votre fichier 'prod.keys'",
"UserErrorNoFirmwareDescription": "Ryujinx n'a pas trouvé de firmwares installés",
"UserErrorFirmwareParsingFailedDescription": "Ryujinx n'a pas pu analyser le firmware fourni. Cela est généralement dû à des clés obsolètes.",
"UserErrorApplicationNotFoundDescription": "Ryujinx n'a pas pu trouver une application valide dans le chemin indiqué.",
"UserErrorUnknownDescription": "Une erreur inconnue est survenue!",
"UserErrorUndefinedDescription": "Une erreur inconnue est survenue ! Cela ne devrait pas se produire, merci de contacter un développeur !",
"OpenSetupGuideMessage": "Ouvrir le guide d'installation",
"NoUpdate": "Aucune mise à jour",
"TitleUpdateVersionLabel": "Version {0} - {1}",
"RyujinxInfo": "Ryujinx - Info",
"RyujinxConfirm": "Ryujinx - Confirmation",
"FileDialogAllTypes": "Tous les types",
"Never": "Jamais",
"SwkbdMinCharacters": "Doit comporter au moins {0} caractères",
"SwkbdMinRangeCharacters": "Doit contenir {0}-{1} caractères en longueur",
"SoftwareKeyboard": "Clavier logiciel",
"DialogControllerAppletMessagePlayerRange": "L'application demande {0} joueur(s) avec :\n\nTYPES : {1}\n\nJOUEURS : {2}\n\n{3}Merci d'ouvrir les Paramètres et de reconfigurer les Périphériques maintenant ou appuyez sur Fermer.",
"DialogControllerAppletMessage": "L'application demande exactement {0} joueur(s) avec :\n\nTYPES : {1}\n\nJOUEURS : {2}\n\n{3}Merci d'ouvrir les Paramètres et de reconfigurer les Périphériques maintenant ou appuyez sur Fermer.",
"DialogControllerAppletDockModeSet": "Mode station d'accueil défini. Le portable est également invalide.\n\n",
"UpdaterRenaming": "Renommage des anciens fichiers...",
"UpdaterRenameFailed": "Impossible de renommer le fichier : {0}",
"UpdaterAddingFiles": "Ajout des nouveaux fichiers...",
"UpdaterExtracting": "Extraction de la mise à jour…",
"UpdaterDownloading": "Téléchargement de la mise à jour...",
"Game": "Jeu",
"Docked": "Attaché",
"Handheld": "Portable",
"ConnectionError": "Erreur de connexion.",
"AboutPageDeveloperListMore": "{0} et plus...",
"ApiError": "Erreur API.",
"LoadingHeading": "Chargement {0}",
"CompilingPPTC": "Compilation PTC",
"CompilingShaders": "Compilation des Shaders",
"AllKeyboards": "Tous les claviers",
"OpenFileDialogTitle": "Sélectionnez un fichier supporté à ouvrir",
"OpenFolderDialogTitle": "Sélectionnez un dossier avec un jeu décompressé",
"AllSupportedFormats": "Tous les formats supportés",
"RyujinxUpdater": "Mise à jour de Ryujinx",
"SettingsTabHotkeys": "Raccourcis clavier",
"SettingsTabHotkeysHotkeys": "Raccourcis clavier",
"SettingsTabHotkeysToggleVsyncHotkey": "Activer/désactiver la VSync :",
"SettingsTabHotkeysScreenshotHotkey": "Captures d'écran :",
"SettingsTabHotkeysShowUiHotkey": "Afficher UI :",
"SettingsTabHotkeysPauseHotkey": "Suspendre :",
"SettingsTabHotkeysToggleMuteHotkey": "Muet : ",
"ControllerMotionTitle": "Réglages du contrôle par mouvement",
"ControllerRumbleTitle": "Paramètres de Vibration",
"SettingsSelectThemeFileDialogTitle": "Sélectionnez un Fichier de Thème",
"SettingsXamlThemeFile": "Fichier thème Xaml",
"AvatarWindowTitle": "Gérer les Comptes - Avatar",
"Amiibo": "Amiibo",
"Unknown": "Inconnu",
"Usage": "Utilisation",
"Writable": "Ecriture possible",
"SelectDlcDialogTitle": "Sélectionner les fichiers DLC",
"SelectUpdateDialogTitle": "Sélectionner les fichiers de mise à jour",
"UserProfileWindowTitle": "Gestionnaire de profils utilisateur",
"CheatWindowTitle": "Gestionnaire de triches",
"DlcWindowTitle": "Gestionnaire de contenus téléchargeables",
"UpdateWindowTitle": "Gestionnaire de mises à jour",
"CheatWindowHeading": "Cheats disponibles pour {0} [{1}]",
"DlcWindowHeading": "{0} Contenu(s) téléchargeable(s) disponible pour {1} ({2})",
"UserProfilesEditProfile": "Éditer la sélection",
"Cancel": "Annuler",
"Save": "Enregistrer",
"Discard": "Abandonner",
"UserProfilesSetProfileImage": "Modifier l'image du profil",
"UserProfileEmptyNameError": "Le nom est requis",
"UserProfileNoImageError": "L'image du profil doit être définie",
"GameUpdateWindowHeading": "{0} mise(s) à jour disponible pour {1} ({2})",
"SettingsTabHotkeysResScaleUpHotkey": "Augmenter la résolution:",
"SettingsTabHotkeysResScaleDownHotkey": "Diminuer la résolution :",
"UserProfilesName": "Nom :",
"UserProfilesUserId": "Identifiant de l'utilisateur :",
"SettingsTabGraphicsBackend": "API de Rendu",
"SettingsTabGraphicsBackendTooltip": "Interface Graphique à utiliser",
"SettingsEnableTextureRecompression": "Activer la recompression des textures",
"SettingsEnableTextureRecompressionTooltip": "Compresse certaines textures afin de réduire l'utilisation de la VRAM.\n\nRecommandé pour une utilisation avec des GPU qui ont moins de 4 Go de VRAM.\n\nLaissez DÉSACTIVÉ si vous n'êtes pas sûr.",
"SettingsTabGraphicsPreferredGpu": "GPU préféré",
"SettingsTabGraphicsPreferredGpuTooltip": "Sélectionnez la carte graphique qui sera utilisée avec l'interface graphique Vulkan.\n\nCela ne change pas le GPU qu'OpenGL utilisera.\n\nChoisissez le GPU noté \"dGPU\" si vous n'êtes pas sûr. S'il n'y en a pas, ne pas modifier.",
"SettingsAppRequiredRestartMessage": "Redémarrage de Ryujinx requis",
"SettingsGpuBackendRestartMessage": "Les paramètres de l'interface graphique ou du GPU ont été modifiés. Cela nécessitera un redémarrage pour être appliqué",
"SettingsGpuBackendRestartSubMessage": "\n\nVoulez-vous redémarrer maintenant?",
"RyujinxUpdaterMessage": "Voulez-vous mettre à jour Ryujinx vers la dernière version ?",
"SettingsTabHotkeysVolumeUpHotkey": "Augmenter le volume :",
"SettingsTabHotkeysVolumeDownHotkey": "Diminuer le volume :",
"SettingsEnableMacroHLE": "Activer les macros HLE",
"SettingsEnableMacroHLETooltip": "Émulation de haut niveau du code de Macro GPU.\n\nAméliore les performances, mais peut causer des bugs graphiques dans certains jeux.\n\nLaissez ACTIVER si vous n'êtes pas sûr.",
"VolumeShort": "Vol",
"UserProfilesManageSaves": "Gérer les sauvegardes",
"DeleteUserSave": "Voulez-vous supprimer la sauvegarde de l'utilisateur pour ce jeu?",
"IrreversibleActionNote": "Cette action n'est pas réversible.",
"SaveManagerHeading": "Gérer les sauvegardes pour {0}",
"SaveManagerTitle": "Gestionnaire de sauvegarde",
"Name": "Nom ",
"Size": "Taille",
"Search": "Rechercher",
"UserProfilesRecoverLostAccounts": "Récupérer les comptes perdus",
"Recover": "Récupérer",
"UserProfilesRecoverHeading": "Des sauvegardes ont été trouvées pour les comptes suivants"
}

View File

@@ -1,613 +0,0 @@
{
"MenuBarFileOpenApplet": "Apri Applet",
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Apri l'applet Mii Editor in modalità Standalone",
"SettingsTabInputDirectMouseAccess": "Accesso diretto al mouse",
"SettingsTabSystemMemoryManagerMode": "Modalità di gestione della memoria:",
"SettingsTabSystemMemoryManagerModeSoftware": "Software",
"SettingsTabSystemMemoryManagerModeHost": "Host (veloce)",
"SettingsTabSystemMemoryManagerModeHostUnchecked": "Host Unchecked (più veloce, non sicura)",
"MenuBarFile": "_File",
"MenuBarFileOpenFromFile": "_Carica applicazione da un file",
"MenuBarFileOpenUnpacked": "Carica _gioco estratto",
"MenuBarFileOpenEmuFolder": "Apri cartella di Ryujinx",
"MenuBarFileOpenLogsFolder": "Apri cartella dei logs",
"MenuBarFileExit": "_Esci",
"MenuBarOptions": "Opzioni",
"MenuBarOptionsToggleFullscreen": "Schermo intero",
"MenuBarOptionsStartGamesInFullscreen": "Avvia i giochi a schermo intero",
"MenuBarOptionsStopEmulation": "Ferma emulazione",
"MenuBarOptionsSettings": "_Impostazioni",
"MenuBarOptionsManageUserProfiles": "_Gestisci i profili utente",
"MenuBarActions": "_Azioni",
"MenuBarOptionsSimulateWakeUpMessage": "Simula messaggio Wake-up",
"MenuBarActionsScanAmiibo": "Scansiona un Amiibo",
"MenuBarTools": "_Strumenti",
"MenuBarToolsInstallFirmware": "Installa firmware",
"MenuBarFileToolsInstallFirmwareFromFile": "Installa un firmware da file XCI o ZIP",
"MenuBarFileToolsInstallFirmwareFromDirectory": "Installa un firmare da una cartella",
"MenuBarHelp": "Aiuto",
"MenuBarHelpCheckForUpdates": "Controlla aggiornamenti",
"MenuBarHelpAbout": "Informazioni",
"MenuSearch": "Cerca...",
"GameListHeaderFavorite": "Pref",
"GameListHeaderIcon": "Icona",
"GameListHeaderApplication": "Nome",
"GameListHeaderDeveloper": "Sviluppatore",
"GameListHeaderVersion": "Versione",
"GameListHeaderTimePlayed": "Tempo di gioco",
"GameListHeaderLastPlayed": "Giocato l'ultima volta",
"GameListHeaderFileExtension": "Estensione",
"GameListHeaderFileSize": "Dimensione file",
"GameListHeaderPath": "Percorso",
"GameListContextMenuOpenUserSaveDirectory": "Apri la cartella salvataggi dell'utente",
"GameListContextMenuOpenUserSaveDirectoryToolTip": "Apre la cartella che contiene i salvataggi di gioco dell'utente",
"GameListContextMenuOpenUserDeviceDirectory": "Apri la cartella dispositivo dell'utente",
"GameListContextMenuOpenUserDeviceDirectoryToolTip": "Apre la cartella che contiene i salvataggi di gioco del dispositivo",
"GameListContextMenuOpenUserBcatDirectory": "Apri la cartella BCAT dell'utente",
"GameListContextMenuOpenUserBcatDirectoryToolTip": "Apre la cartella che contiene i salvataggi BCAT dell'applicazione",
"GameListContextMenuManageTitleUpdates": "Gestisci aggiornamenti del gioco",
"GameListContextMenuManageTitleUpdatesToolTip": "Apre la finestra di gestione aggiornamenti del gioco",
"GameListContextMenuManageDlc": "Gestici DLC",
"GameListContextMenuManageDlcToolTip": "Apre la finestra di gestione DLC",
"GameListContextMenuOpenModsDirectory": "Apri cartella delle mod",
"GameListContextMenuOpenModsDirectoryToolTip": "Apre la cartella che contiene le mod dell'applicazione",
"GameListContextMenuCacheManagement": "Gestione della cache",
"GameListContextMenuCacheManagementPurgePptc": "Pulisci PPTC cache",
"GameListContextMenuCacheManagementPurgePptcToolTip": "Elimina la PPTC cache dell'applicazione",
"GameListContextMenuCacheManagementPurgeShaderCache": "Pulisci shader cache",
"GameListContextMenuCacheManagementPurgeShaderCacheToolTip": "Elimina la shader cache dell'applicazione",
"GameListContextMenuCacheManagementOpenPptcDirectory": "Apri cartella PPTC",
"GameListContextMenuCacheManagementOpenPptcDirectoryToolTip": "Apre la cartella che contiene la PPTC cache dell'applicazione",
"GameListContextMenuCacheManagementOpenShaderCacheDirectory": "Apri cartella shader cache",
"GameListContextMenuCacheManagementOpenShaderCacheDirectoryToolTip": "Apre la cartella che contiene la shader cache dell'applicazione",
"GameListContextMenuExtractData": "Estrai dati",
"GameListContextMenuExtractDataExeFS": "ExeFS",
"GameListContextMenuExtractDataExeFSToolTip": "Estrae la sezione ExeFS dall'attuale configurazione dell'applicazione (includendo aggiornamenti)",
"GameListContextMenuExtractDataRomFS": "RomFS",
"GameListContextMenuExtractDataRomFSToolTip": "Estrae la sezione RomFS dall'attuale configurazione dell'applicazione (includendo aggiornamenti)",
"GameListContextMenuExtractDataLogo": "Logo",
"GameListContextMenuExtractDataLogoToolTip": "Estrae la sezione Logo dall'attuale configurazione dell'applicazione (includendo aggiornamenti)",
"StatusBarGamesLoaded": "{0}/{1} Giochi caricati",
"StatusBarSystemVersion": "Versione di sistema: {0}",
"Settings": "Impostazioni",
"SettingsTabGeneral": "Interfaccia utente",
"SettingsTabGeneralGeneral": "Generali",
"SettingsTabGeneralEnableDiscordRichPresence": "Attiva Discord Rich Presence",
"SettingsTabGeneralCheckUpdatesOnLaunch": "Controlla aggiornamenti all'avvio",
"SettingsTabGeneralShowConfirmExitDialog": "Mostra dialogo \"Conferma Uscita\"",
"SettingsTabGeneralHideCursorOnIdle": "Nascondi cursore inattivo",
"SettingsTabGeneralGameDirectories": "Cartelle dei giochi",
"SettingsTabGeneralAdd": "Aggiungi",
"SettingsTabGeneralRemove": "Rimuovi",
"SettingsTabSystem": "Sistema",
"SettingsTabSystemCore": "Principale",
"SettingsTabSystemSystemRegion": "Regione del sistema:",
"SettingsTabSystemSystemRegionJapan": "Giappone",
"SettingsTabSystemSystemRegionUSA": "Stati Uniti d'America",
"SettingsTabSystemSystemRegionEurope": "Europa",
"SettingsTabSystemSystemRegionAustralia": "Australia",
"SettingsTabSystemSystemRegionChina": "Cina",
"SettingsTabSystemSystemRegionKorea": "Corea",
"SettingsTabSystemSystemRegionTaiwan": "Tailandia",
"SettingsTabSystemSystemLanguage": "Lingua del sistema:",
"SettingsTabSystemSystemLanguageJapanese": "Giapponese",
"SettingsTabSystemSystemLanguageAmericanEnglish": "Inglese americano",
"SettingsTabSystemSystemLanguageFrench": "Francese",
"SettingsTabSystemSystemLanguageGerman": "Tedesco",
"SettingsTabSystemSystemLanguageItalian": "Italiano",
"SettingsTabSystemSystemLanguageSpanish": "Spagnolo",
"SettingsTabSystemSystemLanguageChinese": "Cinese",
"SettingsTabSystemSystemLanguageKorean": "Coreano",
"SettingsTabSystemSystemLanguageDutch": "Olandese",
"SettingsTabSystemSystemLanguagePortuguese": "Portoghese",
"SettingsTabSystemSystemLanguageRussian": "Russo",
"SettingsTabSystemSystemLanguageTaiwanese": "Taiwanese",
"SettingsTabSystemSystemLanguageBritishEnglish": "Inglese britannico",
"SettingsTabSystemSystemLanguageCanadianFrench": "Francese canadese",
"SettingsTabSystemSystemLanguageLatinAmericanSpanish": "Spagnolo latino americano",
"SettingsTabSystemSystemLanguageSimplifiedChinese": "Cinese semplificato",
"SettingsTabSystemSystemLanguageTraditionalChinese": "Cinese tradizionale",
"SettingsTabSystemSystemTimeZone": "Fuso orario del sistema:",
"SettingsTabSystemSystemTime": "Data e ora del sistema:",
"SettingsTabSystemEnableVsync": "Attiva VSync",
"SettingsTabSystemEnablePptc": "Attiva PPTC (Profiled Persistent Translation Cache)",
"SettingsTabSystemEnableFsIntegrityChecks": "Attiva controlli d'integrità FS",
"SettingsTabSystemAudioBackend": "Backend audio:",
"SettingsTabSystemAudioBackendDummy": "Manichino",
"SettingsTabSystemAudioBackendOpenAL": "OpenAL",
"SettingsTabSystemAudioBackendSoundIO": "AudioIO",
"SettingsTabSystemAudioBackendSDL2": "SDL2",
"SettingsTabSystemHacks": "Trucchi",
"SettingsTabSystemHacksNote": " (Possono causare instabilità)",
"SettingsTabSystemExpandDramSize": "Espandi dimensione DRAM a 6GiB",
"SettingsTabSystemIgnoreMissingServices": "Ignora servizi mancanti",
"SettingsTabGraphics": "Grafica",
"SettingsTabGraphicsAPI": "API Grafiche",
"SettingsTabGraphicsEnableShaderCache": "Attiva Shader Cache",
"SettingsTabGraphicsAnisotropicFiltering": "Filtro anisotropico:",
"SettingsTabGraphicsAnisotropicFilteringAuto": "Auto",
"SettingsTabGraphicsAnisotropicFiltering2x": "2x",
"SettingsTabGraphicsAnisotropicFiltering4x": "4x",
"SettingsTabGraphicsAnisotropicFiltering8x": "8x",
"SettingsTabGraphicsAnisotropicFiltering16x": "16x",
"SettingsTabGraphicsResolutionScale": "Scala della risoluzione:",
"SettingsTabGraphicsResolutionScaleCustom": "Personalizzata (Non raccomandata)",
"SettingsTabGraphicsResolutionScaleNative": "Nativa (720p/1080p)",
"SettingsTabGraphicsResolutionScale2x": "2x (1440p/2160p)",
"SettingsTabGraphicsResolutionScale3x": "3x (2160p/3240p)",
"SettingsTabGraphicsResolutionScale4x": "4x (2880p/4320p)",
"SettingsTabGraphicsAspectRatio": "Rapporto d'aspetto:",
"SettingsTabGraphicsAspectRatio4x3": "4:3",
"SettingsTabGraphicsAspectRatio16x9": "16:9",
"SettingsTabGraphicsAspectRatio16x10": "16:10",
"SettingsTabGraphicsAspectRatio21x9": "21:9",
"SettingsTabGraphicsAspectRatio32x9": "32:9",
"SettingsTabGraphicsAspectRatioStretch": "Adatta alla finestra",
"SettingsTabGraphicsDeveloperOptions": "Opzioni da sviluppatore",
"SettingsTabGraphicsShaderDumpPath": "Percorso di dump degli shaders:",
"SettingsTabLogging": "Log",
"SettingsTabLoggingLogging": "Log",
"SettingsTabLoggingEnableLoggingToFile": "Salva i log su file",
"SettingsTabLoggingEnableStubLogs": "Attiva Stub Logs",
"SettingsTabLoggingEnableInfoLogs": "Attiva Info Logs",
"SettingsTabLoggingEnableWarningLogs": "Attiva Warning Logs",
"SettingsTabLoggingEnableErrorLogs": "Attiva Error Logs",
"SettingsTabLoggingEnableTraceLogs": "Attiva Trace Logs",
"SettingsTabLoggingEnableGuestLogs": "Attiva Guest Logs",
"SettingsTabLoggingEnableFsAccessLogs": "Attiva Fs Access Logs",
"SettingsTabLoggingFsGlobalAccessLogMode": "Modalità log accesso globale Fs:",
"SettingsTabLoggingDeveloperOptions": "Opzioni da sviluppatore (AVVISO: Ridurrà le prestazioni)",
"SettingsTabLoggingGraphicsBackendLogLevel": "Livello registro backend grafico:",
"SettingsTabLoggingGraphicsBackendLogLevelNone": "Nessuno",
"SettingsTabLoggingGraphicsBackendLogLevelError": "Errore",
"SettingsTabLoggingGraphicsBackendLogLevelPerformance": "Rallentamenti",
"SettingsTabLoggingGraphicsBackendLogLevelAll": "Tutto",
"SettingsTabLoggingEnableDebugLogs": "Attiva logs di debug",
"SettingsTabInput": "Input",
"SettingsTabInputEnableDockedMode": "Attiva modalità TV",
"SettingsTabInputDirectKeyboardAccess": "Accesso diretto alla tastiera",
"SettingsButtonSave": "Salva",
"SettingsButtonClose": "Chiudi",
"SettingsButtonOk": "OK",
"SettingsButtonCancel": "Cancella",
"SettingsButtonApply": "Applica",
"ControllerSettingsPlayer": "Giocatore",
"ControllerSettingsPlayer1": "Giocatore 1",
"ControllerSettingsPlayer2": "Giocatore 2",
"ControllerSettingsPlayer3": "Giocatore 3",
"ControllerSettingsPlayer4": "Giocatore 4",
"ControllerSettingsPlayer5": "Giocatore 5",
"ControllerSettingsPlayer6": "Giocatore 6",
"ControllerSettingsPlayer7": "Giocatore 7",
"ControllerSettingsPlayer8": "Giocatore 8",
"ControllerSettingsHandheld": "Portatile",
"ControllerSettingsInputDevice": "Dispositivo di input",
"ControllerSettingsRefresh": "Ricarica",
"ControllerSettingsDeviceDisabled": "Disabilitato",
"ControllerSettingsControllerType": "Tipo di controller",
"ControllerSettingsControllerTypeHandheld": "Portatile",
"ControllerSettingsControllerTypeProController": "Pro Controller",
"ControllerSettingsControllerTypeJoyConPair": "Coppia di JoyCon",
"ControllerSettingsControllerTypeJoyConLeft": "JoyCon sinistro",
"ControllerSettingsControllerTypeJoyConRight": "JoyCon destro",
"ControllerSettingsProfile": "Profilo",
"ControllerSettingsProfileDefault": "Predefinito",
"ControllerSettingsLoad": "Carica",
"ControllerSettingsAdd": "Aggiungi",
"ControllerSettingsRemove": "Rimuovi",
"ControllerSettingsButtons": "Pulsanti",
"ControllerSettingsButtonA": "A",
"ControllerSettingsButtonB": "B",
"ControllerSettingsButtonX": "X",
"ControllerSettingsButtonY": "Y",
"ControllerSettingsButtonPlus": "+",
"ControllerSettingsButtonMinus": "-",
"ControllerSettingsDPad": "Croce direzionale",
"ControllerSettingsDPadUp": "Su",
"ControllerSettingsDPadDown": "Giù",
"ControllerSettingsDPadLeft": "Sinistra",
"ControllerSettingsDPadRight": "Destra",
"ControllerSettingsLStick": "Stick sinistro",
"ControllerSettingsLStickButton": "Pulsante",
"ControllerSettingsLStickUp": "Su",
"ControllerSettingsLStickDown": "Giù",
"ControllerSettingsLStickLeft": "Sinistra",
"ControllerSettingsLStickRight": "Destra",
"ControllerSettingsLStickStick": "Levetta",
"ControllerSettingsLStickInvertXAxis": "Inverti stick X",
"ControllerSettingsLStickInvertYAxis": "Inverti stick Y",
"ControllerSettingsLStickDeadzone": "Zona morta:",
"ControllerSettingsRStick": "Stick destro",
"ControllerSettingsRStickButton": "Pulsante",
"ControllerSettingsRStickUp": "Su",
"ControllerSettingsRStickDown": "Giù",
"ControllerSettingsRStickLeft": "Sinistra",
"ControllerSettingsRStickRight": "Destra",
"ControllerSettingsRStickStick": "Levetta",
"ControllerSettingsRStickInvertXAxis": "Inverti stick X",
"ControllerSettingsRStickInvertYAxis": "Inverti stick Y",
"ControllerSettingsRStickDeadzone": "Zona morta:",
"ControllerSettingsTriggersLeft": "Grilletto sinistro",
"ControllerSettingsTriggersRight": "Grilletto destro",
"ControllerSettingsTriggersButtonsLeft": "Pulsante dorsale sinistro",
"ControllerSettingsTriggersButtonsRight": "Pulsante dorsale destro",
"ControllerSettingsTriggers": "Grilletti",
"ControllerSettingsTriggerL": "L",
"ControllerSettingsTriggerR": "R",
"ControllerSettingsTriggerZL": "ZL",
"ControllerSettingsTriggerZR": "ZR",
"ControllerSettingsLeftSL": "SL",
"ControllerSettingsLeftSR": "SR",
"ControllerSettingsRightSL": "SL",
"ControllerSettingsRightSR": "SR",
"ControllerSettingsExtraButtonsLeft": "Tasto sinitro",
"ControllerSettingsExtraButtonsRight": "Tasto destro",
"ControllerSettingsMisc": "Varie",
"ControllerSettingsTriggerThreshold": "Sensibilità dei grilletti:",
"ControllerSettingsMotion": "Movimento",
"ControllerSettingsMotionUseCemuhookCompatibleMotion": "Usa sensore compatibile con CemuHook",
"ControllerSettingsMotionControllerSlot": "Slot del controller:",
"ControllerSettingsMotionMirrorInput": "Input specchiato",
"ControllerSettingsMotionRightJoyConSlot": "Slot JoyCon destro:",
"ControllerSettingsMotionServerHost": "Server:",
"ControllerSettingsMotionGyroSensitivity": "Sensibilità del giroscopio:",
"ControllerSettingsMotionGyroDeadzone": "Zona morta del giroscopio:",
"ControllerSettingsSave": "Salva",
"ControllerSettingsClose": "Chiudi",
"UserProfilesSelectedUserProfile": "Profilo utente selezionato:",
"UserProfilesSaveProfileName": "Salva nome del profilo",
"UserProfilesChangeProfileImage": "Cambia immagine profilo",
"UserProfilesAvailableUserProfiles": "Profili utente disponibili:",
"UserProfilesAddNewProfile": "Aggiungi nuovo profilo",
"UserProfilesDeleteSelectedProfile": "Elimina il profilo selezionato",
"UserProfilesClose": "Chiudi",
"ProfileImageSelectionTitle": "Selezione dell'immagine profilo",
"ProfileImageSelectionHeader": "Scegli un'immagine profilo",
"ProfileImageSelectionNote": "Puoi importare un'immagine profilo personalizzata o selezionare un avatar dal firmware del sistema",
"ProfileImageSelectionImportImage": "Importa file immagine",
"ProfileImageSelectionSelectAvatar": "Seleziona avatar dal firmware",
"InputDialogTitle": "Finestra di dialogo ",
"InputDialogOk": "OK",
"InputDialogCancel": "Annulla",
"InputDialogAddNewProfileTitle": "Scegli il nome profilo",
"InputDialogAddNewProfileHeader": "Digita un nome profilo",
"InputDialogAddNewProfileSubtext": "(Lunghezza massima: {0})",
"AvatarChoose": "Scegli",
"AvatarSetBackgroundColor": "Imposta colore di sfondo",
"AvatarClose": "Chiudi",
"ControllerSettingsLoadProfileToolTip": "Carica profilo",
"ControllerSettingsAddProfileToolTip": "Aggiungi profilo",
"ControllerSettingsRemoveProfileToolTip": "Rimuovi profilo",
"ControllerSettingsSaveProfileToolTip": "Salva profilo",
"MenuBarFileToolsTakeScreenshot": "Fai uno screenshot",
"MenuBarFileToolsHideUi": "Nascondi UI",
"GameListContextMenuToggleFavorite": "Preferito",
"GameListContextMenuToggleFavoriteToolTip": "Segna il gioco come preferito",
"SettingsTabGeneralTheme": "Tema",
"SettingsTabGeneralThemeCustomTheme": "Percorso del tema personalizzato",
"SettingsTabGeneralThemeBaseStyle": "Modalità",
"SettingsTabGeneralThemeBaseStyleDark": "Scura",
"SettingsTabGeneralThemeBaseStyleLight": "Chiara",
"SettingsTabGeneralThemeEnableCustomTheme": "Attiva tema personalizzato",
"ButtonBrowse": "Sfoglia",
"ControllerSettingsConfigureGeneral": "Configura",
"ControllerSettingsRumble": "Vibrazione",
"ControllerSettingsRumbleStrongMultiplier": "Moltiplicatore vibrazione forte",
"ControllerSettingsRumbleWeakMultiplier": "Moltiplicatore vibrazione debole",
"DialogMessageSaveNotAvailableMessage": "Non ci sono dati di salvataggio per {0} [{1:x16}]",
"DialogMessageSaveNotAvailableCreateSaveMessage": "Vuoi creare dei dati di salvataggio per questo gioco?",
"DialogConfirmationTitle": "Ryujinx - Conferma",
"DialogUpdaterTitle": "Ryujinx - Aggiornamento",
"DialogErrorTitle": "Ryujinx - Errore",
"DialogWarningTitle": "Ryujinx - Avviso",
"DialogExitTitle": "Ryujinx - Esci",
"DialogErrorMessage": "Ryujinx ha riscontrato un problema",
"DialogExitMessage": "Sei sicuro di voler chiudere Ryujinx?",
"DialogExitSubMessage": "Tutti i dati non salvati andranno persi!",
"DialogMessageCreateSaveErrorMessage": "C'è stato un errore durante la creazione dei dati di salvataggio: {0}",
"DialogMessageFindSaveErrorMessage": "C'è stato un errore durante la ricerca dei dati di salvataggio: {0}",
"FolderDialogExtractTitle": "Scegli una cartella in cui estrarre",
"DialogNcaExtractionMessage": "Estrazione della sezione {0} da {1}...",
"DialogNcaExtractionTitle": "Ryujinx - Estrattore sezione NCA",
"DialogNcaExtractionMainNcaNotFoundErrorMessage": "L'estrazione è fallita. L'NCA principale non era presente nel file selezionato.",
"DialogNcaExtractionCheckLogErrorMessage": "L'estrazione è fallita. Leggi il log per più informazioni.",
"DialogNcaExtractionSuccessMessage": "Estrazione completata con successo.",
"DialogUpdaterConvertFailedMessage": "La conversione dell'attuale versione di Ryujinx è fallita.",
"DialogUpdaterCancelUpdateMessage": "Annullando l'aggiornamento!",
"DialogUpdaterAlreadyOnLatestVersionMessage": "Stai già usando la versione più recente di Ryujinx!",
"DialogUpdaterFailedToGetVersionMessage": "Si è verificato un errore durante il tentativo di ottenere informazioni sulla versione da GitHub Release. Ciò può essere causato se una nuova versione viene compilata da GitHub Actions. Riprova tra qualche minuto.",
"DialogUpdaterConvertFailedGithubMessage": "La conversione della versione di Ryujinx ricevuta da Github Release è fallita.",
"DialogUpdaterDownloadingMessage": "Download dell'aggiornamento...",
"DialogUpdaterExtractionMessage": "Estrazione dell'aggiornamento...",
"DialogUpdaterRenamingMessage": "Rinominazione dell'aggiornamento...",
"DialogUpdaterAddingFilesMessage": "Aggiunta del nuovo aggiornamento...",
"DialogUpdaterCompleteMessage": "Aggiornamento completato!",
"DialogUpdaterRestartMessage": "Vuoi riavviare Ryujinx adesso?",
"DialogUpdaterArchNotSupportedMessage": "Non stai usando un'architettura di sistema supportata!",
"DialogUpdaterArchNotSupportedSubMessage": "(Solo sistemi x64 sono supportati!)",
"DialogUpdaterNoInternetMessage": "Non sei connesso ad Internet!",
"DialogUpdaterNoInternetSubMessage": "Verifica di avere una connessione ad Internet funzionante!",
"DialogUpdaterDirtyBuildMessage": "Non puoi aggiornare una Dirty build di Ryujinx!",
"DialogUpdaterDirtyBuildSubMessage": "Scarica Ryujinx da https://ryujinx.org/ se stai cercando una versione supportata.",
"DialogRestartRequiredMessage": "Riavvio richiesto",
"DialogThemeRestartMessage": "Il tema è stato salvato. E' richiesto un riavvio per applicare un tema.",
"DialogThemeRestartSubMessage": "Vuoi riavviare?",
"DialogFirmwareInstallEmbeddedMessage": "Vuoi installare il firmware incorporato in questo gioco? (Firmware {0})",
"DialogFirmwareInstallEmbeddedSuccessMessage": "Non è stato trovato alcun firmware installato, ma Ryujinx è riuscito ad installare il firmware {0} dal gioco fornito.\nL'emulatore si avvierà adesso.",
"DialogFirmwareNoFirmwareInstalledMessage": "Nessun firmware installato",
"DialogFirmwareInstalledMessage": "Il firmware {0} è stato installato",
"DialogOpenSettingsWindowLabel": "Apri finestra delle impostazioni",
"DialogControllerAppletTitle": "Applet del controller",
"DialogMessageDialogErrorExceptionMessage": "Errore nella visualizzazione del Message Dialog: {0}",
"DialogSoftwareKeyboardErrorExceptionMessage": "Errore nella visualizzazione della tastiera software: {0}",
"DialogErrorAppletErrorExceptionMessage": "Errore nella visualizzazione dell'ErrorApplet Dialog: {0}",
"DialogUserErrorDialogMessage": "{0}: {1}",
"DialogUserErrorDialogInfoMessage": "\nPer più informazioni su come risolvere questo errore, segui la nostra guida all'installazione.",
"DialogUserErrorDialogTitle": "Errore di Ryujinx ({0})",
"DialogAmiiboApiTitle": "Amiibo API",
"DialogAmiiboApiFailFetchMessage": "Si è verificato un errore durante il recupero delle informazioni dall'API.",
"DialogAmiiboApiConnectErrorMessage": "Impossibile connettersi al server Amiibo API. Il servizio potrebbe essere fuori uso o potresti dover verificare che la tua connessione internet sia online.",
"DialogProfileInvalidProfileErrorMessage": "Il profilo {0} è incompatibile con l'attuale sistema di configurazione input.",
"DialogProfileDefaultProfileOverwriteErrorMessage": "Il profilo predefinito non può essere sovrascritto",
"DialogProfileDeleteProfileTitle": "Eliminazione profilo",
"DialogProfileDeleteProfileMessage": "Quest'azione è irreversibile, sei sicuro di voler continuare?",
"DialogWarning": "Avviso",
"DialogPPTCDeletionMessage": "Stai per eliminare la PPTC cache per :\n\n{0}\n\nSei sicuro di voler proseguire?",
"DialogPPTCDeletionErrorMessage": "Errore nell'eliminazione della PPTC cache a {0}: {1}",
"DialogShaderDeletionMessage": "Stai per eliminare la Shader cache per :\n\n{0}\n\nSei sicuro di voler proseguire?",
"DialogShaderDeletionErrorMessage": "Errore nell'eliminazione della Shader cache a {0}: {1}",
"DialogRyujinxErrorMessage": "Ryujinx ha incontrato un errore",
"DialogInvalidTitleIdErrorMessage": "Errore UI: Il gioco selezionato non ha un ID titolo valido",
"DialogFirmwareInstallerFirmwareNotFoundErrorMessage": "Un firmware del sistema valido non è stato trovato in {0}.",
"DialogFirmwareInstallerFirmwareInstallTitle": "Installa firmware {0}",
"DialogFirmwareInstallerFirmwareInstallMessage": "La versione del sistema {0} sarà installata.",
"DialogFirmwareInstallerFirmwareInstallSubMessage": "\n\nQuesta sostituirà l'attuale versione di sistema {0}.",
"DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\nVuoi continuare?",
"DialogFirmwareInstallerFirmwareInstallWaitMessage": "Installazione del firmware...",
"DialogFirmwareInstallerFirmwareInstallSuccessMessage": "La versione del sistema {0} è stata installata.",
"DialogUserProfileDeletionWarningMessage": "Non ci sarebbero altri profili da aprire se il profilo selezionato viene cancellato",
"DialogUserProfileDeletionConfirmMessage": "Vuoi eliminare il profilo selezionato?",
"DialogControllerSettingsModifiedConfirmMessage": "Le attuali impostazioni del controller sono state aggiornate.",
"DialogControllerSettingsModifiedConfirmSubMessage": "Vuoi salvare?",
"DialogDlcLoadNcaErrorMessage": "{0}. File errato: {1}",
"DialogDlcNoDlcErrorMessage": "Il file specificato non contiene un DLC per il titolo selezionato!",
"DialogPerformanceCheckLoggingEnabledMessage": "Hai abilitato il trace logging, che è progettato per essere usato solo dagli sviluppatori.",
"DialogPerformanceCheckLoggingEnabledConfirmMessage": "Per prestazioni ottimali, si raccomanda di disabilitare il trace logging. Vuoi disabilitare il debug logging adesso?",
"DialogPerformanceCheckShaderDumpEnabledMessage": "Hai abilitato lo shader dumping, che è progettato per essere usato solo dagli sviluppatori.",
"DialogPerformanceCheckShaderDumpEnabledConfirmMessage": "Per prestazioni ottimali, si raccomanda di disabilitare lo shader dumping. Vuoi disabilitare lo shader dumping adesso?",
"DialogLoadAppGameAlreadyLoadedMessage": "Un gioco è già stato caricato",
"DialogLoadAppGameAlreadyLoadedSubMessage": "Ferma l'emulazione o chiudi l'emulatore prima di avviare un altro gioco.",
"DialogUpdateAddUpdateErrorMessage": "Il file specificato non contiene un aggiornamento per il titolo selezionato!",
"DialogSettingsBackendThreadingWarningTitle": "Avviso - Backend Threading",
"DialogSettingsBackendThreadingWarningMessage": "Ryujinx deve essere riavviato dopo aver cambiato questa opzione per applicarla completamente. A seconda della tua piattaforma, potrebbe essere necessario disabilitare manualmente il multithreading del driver quando usi quello di Ryujinx.",
"SettingsTabGraphicsFeaturesOptions": "Funzionalità",
"SettingsTabGraphicsBackendMultithreading": "Graphics Backend Multithreading",
"CommonAuto": "Auto",
"CommonOff": "Spento",
"CommonOn": "Acceso",
"InputDialogYes": "Si",
"InputDialogNo": "No",
"DialogProfileInvalidProfileNameErrorMessage": "Il nome del file contiene caratteri non validi. Riprova.",
"MenuBarOptionsPauseEmulation": "Pausa",
"MenuBarOptionsResumeEmulation": "Riprendi",
"AboutUrlTooltipMessage": "Clicca per aprire il sito web di Ryujinx nel tuo browser predefinito.",
"AboutDisclaimerMessage": "Ryujinx non è affiliato con Nintendo™,\no i suoi partner, in alcun modo.",
"AboutAmiiboDisclaimerMessage": "AmiiboAPI (www.amiiboapi.com) è usata\nnella nostra emulazione Amiibo.",
"AboutPatreonUrlTooltipMessage": "Clicca per aprire la pagina Patreon di Ryujinx nel tuo browser predefinito.",
"AboutGithubUrlTooltipMessage": "Clicca per aprire la pagina GitHub di Ryujinx nel tuo browser predefinito.",
"AboutDiscordUrlTooltipMessage": "Clicca per aprire un invito al server Discord di Ryujinx nel tuo browser predefinito.",
"AboutTwitterUrlTooltipMessage": "Clicca per aprire la pagina Twitter di Ryujinx nel tuo browser predefinito.",
"AboutRyujinxAboutTitle": "Informazioni:",
"AboutRyujinxAboutContent": "Ryujinx è un emulatore per la Nintendo Switch™.\nPer favore supportaci su Patreon.\nRicevi tutte le ultime notizie sul nostro Twitter o su Discord.\nGli sviluppatori interessati a contribuire possono trovare più informazioni sul nostro GitHub o Discord.",
"AboutRyujinxMaintainersTitle": "Mantenuto da:",
"AboutRyujinxMaintainersContentTooltipMessage": "Clicca per aprire la pagina dei Contributors nel tuo browser predefinito.",
"AboutRyujinxSupprtersTitle": "Supportato su Patreon da:",
"AmiiboSeriesLabel": "Serie Amiibo",
"AmiiboCharacterLabel": "Personaggio",
"AmiiboScanButtonLabel": "Scannerizza",
"AmiiboOptionsShowAllLabel": "Mostra tutti gli amiibo",
"AmiiboOptionsUsRandomTagLabel": "Hack: Usa un tag uuid casuale",
"DlcManagerTableHeadingEnabledLabel": "Abilitato",
"DlcManagerTableHeadingTitleIdLabel": "Titolo ID",
"DlcManagerTableHeadingContainerPathLabel": "Percorso del contenitore",
"DlcManagerTableHeadingFullPathLabel": "Percorso completo",
"DlcManagerRemoveAllButton": "Rimuovi tutti",
"DlcManagerEnableAllButton": "Abilita tutto",
"DlcManagerDisableAllButton": "Disabilita tutto",
"MenuBarOptionsChangeLanguage": "Cambia lingua",
"CommonSort": "Ordina",
"CommonShowNames": "Mostra nomi",
"CommonFavorite": "Preferito",
"OrderAscending": "Crescente",
"OrderDescending": "Decrescente",
"SettingsTabGraphicsFeatures": "Funzionalità & Miglioramenti",
"ErrorWindowTitle": "Finestra errore",
"ToggleDiscordTooltip": "Attiva o disattiva Discord Rich Presence",
"AddGameDirBoxTooltip": "Inserisci la directory di un gioco per aggiungerlo alla lista",
"AddGameDirTooltip": "Aggiungi la directory di un gioco alla lista",
"RemoveGameDirTooltip": "Rimuovi la directory di gioco selezionata",
"CustomThemeCheckTooltip": "Attiva o disattiva temi personalizzati nella GUI",
"CustomThemePathTooltip": "Percorso al tema GUI personalizzato",
"CustomThemeBrowseTooltip": "Sfoglia per cercare un tema GUI personalizzato",
"DockModeToggleTooltip": "Attiva o disabilta modalità TV",
"DirectKeyboardTooltip": "Attiva o disattiva \"il supporto all'accesso diretto alla tastiera (HID)\" (Fornisce l'accesso ai giochi alla tua tastiera come dispositivo di immissione del testo)",
"DirectMouseTooltip": "Attiva o disattiva \"il supporto all'accesso diretto al mouse (HID)\" (Fornisce l'accesso ai giochi al tuo mouse come dispositivo di puntamento)",
"RegionTooltip": "Cambia regione di sistema",
"LanguageTooltip": "Cambia lingua di sistema",
"TimezoneTooltip": "Cambia fuso orario di sistema",
"TimeTooltip": "Cambia data e ora di sistema",
"VSyncToggleTooltip": "Attiva o disattiva sincronizzazione verticale",
"PptcToggleTooltip": "Attiva o disattiva PPTC",
"FsIntegrityToggleTooltip": "Attiva controlli d'integrità sui file dei contenuti di gioco",
"AudioBackendTooltip": "Cambia backend audio",
"MemoryManagerTooltip": "Cambia il modo in cui la memoria guest è mappata e vi si accede. Influisce notevolmente sulle prestazioni della CPU emulata.",
"MemoryManagerSoftwareTooltip": "Usa una software page table per la traduzione degli indirizzi. Massima precisione ma prestazioni più lente.",
"MemoryManagerHostTooltip": "Mappa direttamente la memoria nello spazio degli indirizzi dell'host. Compilazione ed esecuzione JIT molto più veloce.",
"MemoryManagerUnsafeTooltip": "Mappa direttamente la memoria, ma non maschera l'indirizzo all'interno dello spazio degli indirizzi guest prima dell'accesso. Più veloce, ma a costo della sicurezza. L'applicazione guest può accedere alla memoria da qualsiasi punto di Ryujinx, quindi esegui solo programmi di cui ti fidi con questa modalità.",
"DRamTooltip": "Espande l'ammontare di memoria sul sistema emulato da 4GiB A 6GiB",
"IgnoreMissingServicesTooltip": "Attiva o disattiva l'opzione di ignorare i servizi mancanti",
"GraphicsBackendThreadingTooltip": "Attiva il Graphics Backend Multithreading",
"GalThreadingTooltip": "Esegue i comandi del backend grafico su un secondo thread. Permette il multithreading runtime della compilazione degli shader, riduce lo stuttering e migliora le prestazioni sui driver senza supporto multithreading proprio. Varia leggermente le prestazioni di picco sui driver con multithreading. Ryujinx potrebbe aver bisogno di essere riavviato per disabilitare correttamente il multithreading integrato nel driver, o potrebbe essere necessario farlo manualmente per ottenere le migliori prestazioni.",
"ShaderCacheToggleTooltip": "Attiva o disattiva la Shader Cache",
"ResolutionScaleTooltip": "Scala della risoluzione applicata ai render targets applicabili",
"ResolutionScaleEntryTooltip": "Scala della risoluzione in virgola mobile, come 1,5. Le scale non integrali hanno maggiori probabilità di causare problemi o crash.",
"AnisotropyTooltip": "Livello del filtro anisotropico (imposta su Auto per usare il valore richiesto dal gioco)",
"AspectRatioTooltip": "Rapporto d'aspetto applicato alla finestra del renderer.",
"ShaderDumpPathTooltip": "Percorso di dump Graphics Shaders",
"FileLogTooltip": "Attiva o disattiva il logging su file",
"StubLogTooltip": "Attiva messaggi stub log",
"InfoLogTooltip": "Attiva messaggi info log",
"WarnLogTooltip": "Attiva messaggi warning log",
"ErrorLogTooltip": "Attiva messaggi error log",
"TraceLogTooltip": "Attiva messaggi trace log",
"GuestLogTooltip": "Attiva messaggi guest log",
"FileAccessLogTooltip": "Attiva messaggi file access log",
"FSAccessLogModeTooltip": "Attiva output FS access log alla console. Le modalità possibili sono 0-3",
"DeveloperOptionTooltip": "Usa con attenzione",
"OpenGlLogLevel": "Richiede livelli di log appropriati abilitati",
"DebugLogTooltip": "Attiva messaggi debug log",
"LoadApplicationFileTooltip": "Apri un file explorer per scegliere un file compatibile Switch da caricare",
"LoadApplicationFolderTooltip": "Apri un file explorer per scegliere un file compatibile Switch, applicazione sfusa da caricare",
"OpenRyujinxFolderTooltip": "Apri la cartella del filesystem di Ryujinx",
"OpenRyujinxLogsTooltip": "Apre la cartella dove vengono scritti i log",
"ExitTooltip": "Esci da Ryujinx",
"OpenSettingsTooltip": "Apri finestra delle impostazioni",
"OpenProfileManagerTooltip": "Apri la finestra di gestione dei profili utente",
"StopEmulationTooltip": "Ferma l'emulazione del gioco attuale e torna alla selezione dei giochi",
"CheckUpdatesTooltip": "Controlla la presenza di aggiornamenti di Ryujinx",
"OpenAboutTooltip": "Apri finestra delle informazioni",
"GridSize": "Dimensione griglia",
"GridSizeTooltip": "Cambia la dimensione dei riquardi della griglia",
"SettingsTabSystemSystemLanguageBrazilianPortuguese": "Portoghese Brasiliano",
"AboutRyujinxContributorsButtonHeader": "Vedi tutti i Contributors",
"SettingsTabSystemAudioVolume": "Volume: ",
"AudioVolumeTooltip": "Cambia volume audio",
"SettingsTabSystemEnableInternetAccess": "Attiva Guest Internet Access",
"EnableInternetAccessTooltip": "Attiva il guest Internet access. Se abilitato, l'applicazione si comporterà come se la console Switch emulata fosse collegata a Internet. Si noti che in alcuni casi, le applicazioni possono comunque accedere a Internet anche con questa opzione disabilitata",
"GameListContextMenuManageCheatToolTip": "Gestisci Cheats",
"GameListContextMenuManageCheat": "Gestisci Cheats",
"ControllerSettingsStickRange": "Raggio:",
"DialogStopEmulationTitle": "Ryujinx - Ferma emulazione",
"DialogStopEmulationMessage": "Sei sicuro di voler fermare l'emulazione?",
"SettingsTabCpu": "CPU",
"SettingsTabAudio": "Audio",
"SettingsTabNetwork": "Rete",
"SettingsTabNetworkConnection": "Connessione di rete",
"SettingsTabCpuCache": "Cache CPU",
"SettingsTabCpuMemory": "Memoria CPU",
"DialogUpdaterFlatpakNotSupportedMessage": "Per favore aggiorna Ryujinx via FlatHub.",
"UpdaterDisabledWarningTitle": "Updater disabilitato!",
"GameListContextMenuOpenSdModsDirectory": "Apri cartella delle mods Atmosphere",
"GameListContextMenuOpenSdModsDirectoryToolTip": "Apre la cartella Atmosphere della scheda SD alternativa che contiene le Mod dell'applicazione. Utile per mod confezionate per hardware reale",
"ControllerSettingsRotate90": "Ruota in senso orario di 90°",
"IconSize": "Dimensioni icona",
"IconSizeTooltip": "Cambia le dimensioni dell'icona di un gioco",
"MenuBarOptionsShowConsole": "Mostra console",
"ShaderCachePurgeError": "Errore nella pulizia della shader cache a {0}: {1}",
"UserErrorNoKeys": "Chiavi non trovate",
"UserErrorNoFirmware": "Firmware non trovato",
"UserErrorFirmwareParsingFailed": "Errori di analisi del firmware",
"UserErrorApplicationNotFound": "Applicazione non trovata",
"UserErrorUnknown": "Errore sconosciuto",
"UserErrorUndefined": "Errore non definito",
"UserErrorNoKeysDescription": "Ryujinx non è riuscito a trovare il file 'prod.keys'",
"UserErrorNoFirmwareDescription": "Ryujinx non è riuscito a trovare alcun firmware installato",
"UserErrorFirmwareParsingFailedDescription": "Ryujinx non è riuscito ad analizzare il firmware. Questo di solito è causato da chiavi non aggiornate.",
"UserErrorApplicationNotFoundDescription": "Ryujinx non è riuscito a trovare un'applicazione valida nel percorso specificato.",
"UserErrorUnknownDescription": "Si è verificato un errore sconosciuto!",
"UserErrorUndefinedDescription": "Si è verificato un errore sconosciuto! Non dovrebbe succedere, per favore contatta uno sviluppatore!",
"OpenSetupGuideMessage": "Apri la guida all'installazione",
"NoUpdate": "Nessun aggiornamento",
"TitleUpdateVersionLabel": "Versione {0} - {1}",
"RyujinxInfo": "Ryujinx - Info",
"RyujinxConfirm": "Ryujinx - Conferma",
"FileDialogAllTypes": "Tutti i tipi",
"Never": "Mai",
"SwkbdMinCharacters": "Non può avere meno di {0} caratteri",
"SwkbdMinRangeCharacters": "Può avere da {0} a {1} caratteri",
"SoftwareKeyboard": "Tastiera software",
"DialogControllerAppletMessagePlayerRange": "L'applicazione richiede {0} giocatori con:\n\nTIPI: {1}\n\nGIOCATORI: {2}\n\n{3}Apri le impostazioni e riconfigura l'input adesso o premi Chiudi.",
"DialogControllerAppletMessage": "L'applicazione richiede esattamente {0} giocatori con:\n\nTIPI: {1}\n\nGIOCATORI: {2}\n\n{3}Apri le impostazioni e riconfigura l'input adesso o premi Chiudi.",
"DialogControllerAppletDockModeSet": "Modalità TV attivata. Neanche portatile è valida.\n\n",
"UpdaterRenaming": "Rinominazione dei vecchi files...",
"UpdaterRenameFailed": "L'updater non è riuscito a rinominare il file: {0}",
"UpdaterAddingFiles": "Aggiunta nuovi files...",
"UpdaterExtracting": "Estrazione aggiornamento...",
"UpdaterDownloading": "Download aggiornamento...",
"Game": "Gioco",
"Docked": "TV",
"Handheld": "Portatile",
"ConnectionError": "Errore di connessione.",
"AboutPageDeveloperListMore": "{0} e altri ancora...",
"ApiError": "Errore dell'API.",
"LoadingHeading": "Caricamento di {0}",
"CompilingPPTC": "Compilazione PTC",
"CompilingShaders": "Compilazione Shaders",
"AllKeyboards": "Tutte le tastiere",
"OpenFileDialogTitle": "Seleziona un file supportato da aprire",
"OpenFolderDialogTitle": "Seleziona una cartella con un gioco estratto",
"AllSupportedFormats": "Tutti i formati supportati",
"RyujinxUpdater": "Aggiornamento Ryujinx",
"SettingsTabHotkeys": "Tasti di scelta rapida",
"SettingsTabHotkeysHotkeys": "Tasti di scelta rapida",
"SettingsTabHotkeysToggleVsyncHotkey": "VSync:",
"SettingsTabHotkeysScreenshotHotkey": "Cattura Schermo:",
"SettingsTabHotkeysShowUiHotkey": "Mostra UI:",
"SettingsTabHotkeysPauseHotkey": "Metti in pausa:",
"SettingsTabHotkeysToggleMuteHotkey": "Muta:",
"ControllerMotionTitle": "Impostazioni dei sensori di movimento",
"ControllerRumbleTitle": "Impostazioni di vibrazione",
"SettingsSelectThemeFileDialogTitle": "Seleziona file del tema",
"SettingsXamlThemeFile": "File del tema xaml",
"AvatarWindowTitle": "Gestisci account - Avatar",
"Amiibo": "Amiibo",
"Unknown": "Sconosciuto",
"Usage": "Utilizzo",
"Writable": "Scrivibile",
"SelectDlcDialogTitle": "Seleziona file dei DLC",
"SelectUpdateDialogTitle": "Seleziona file di aggiornamento",
"UserProfileWindowTitle": "Gestisci profili degli utenti",
"CheatWindowTitle": "Gestisci cheat dei giochi",
"DlcWindowTitle": "Gestisci DLC dei giochi",
"UpdateWindowTitle": "Gestisci aggiornamenti dei giochi",
"CheatWindowHeading": "Cheat disponibiili per {0} [{1}]",
"DlcWindowHeading": "DLC disponibili per {0} [{1}]",
"UserProfilesEditProfile": "Modifica selezionati",
"Cancel": "Annulla",
"Save": "Salva",
"Discard": "Scarta",
"UserProfilesSetProfileImage": "Imposta immagine profilo",
"UserProfileEmptyNameError": "È richiesto un nome",
"UserProfileNoImageError": "Dev'essere impostata un'immagine profilo",
"GameUpdateWindowHeading": "Aggiornamenti disponibili per {0} [{1}]",
"SettingsTabHotkeysResScaleUpHotkey": "Aumentare la risoluzione:",
"SettingsTabHotkeysResScaleDownHotkey": "Diminuire la risoluzione:",
"UserProfilesName": "Nome:",
"UserProfilesUserId": "ID utente:",
"SettingsTabGraphicsBackend": "Backend grafica",
"SettingsTabGraphicsBackendTooltip": "Backend grafica da usare",
"SettingsEnableTextureRecompression": "Abilita Ricompressione Texture",
"SettingsEnableTextureRecompressionTooltip": "Comprime alcune texture per ridurre l'utilizzo della VRAM.\n\nL'utilizzo è consigliato con GPU con meno di 4GB di VRAM.\n\nLascia su OFF se non sei sicuro.",
"SettingsTabGraphicsPreferredGpu": "GPU preferita",
"SettingsTabGraphicsPreferredGpuTooltip": "Seleziona la scheda grafica che verrà usata con la backend grafica Vulkan.\n\nNon influenza la GPU che userà OpenGL.\n\nImposta la GPU contrassegnata come \"dGPU\" se non sei sicuro. Se non ce n'è una, lascia intatta quest'impostazione.",
"SettingsAppRequiredRestartMessage": "È richiesto un riavvio di Ryujinx",
"SettingsGpuBackendRestartMessage": "Le impostazioni della backend grafica o della GPU sono state modificate. Questo richiederà un riavvio perché le modifiche siano applicate",
"SettingsGpuBackendRestartSubMessage": "Vuoi riavviare ora?",
"RyujinxUpdaterMessage": "Vuoi aggiornare Ryujinx all'ultima versione?",
"SettingsTabHotkeysVolumeUpHotkey": "Aumentare il volume:",
"SettingsTabHotkeysVolumeDownHotkey": "Diminuire il volume:",
"SettingsEnableMacroHLE": "Abilita Macro HLE",
"SettingsEnableMacroHLETooltip": "Emulazione di alto livello del codice Macro GPU.\n\nMigliora le prestazioni, ma può causare anomalie grafiche in alcuni giochi.\n\nLasciare ON se non sei sicuro.",
"VolumeShort": "Vol",
"UserProfilesManageSaves": "Gestisci i salvataggi",
"DeleteUserSave": "Vuoi eliminare il salvataggio utente per questo gioco?",
"IrreversibleActionNote": "Questa azione non è reversibile.",
"SaveManagerHeading": "Gestisci i salvataggi per {0}",
"SaveManagerTitle": "Gestione Salvataggi",
"Name": "Nome",
"Size": "Dimensione",
"Search": "Cerca",
"UserProfilesRecoverLostAccounts": "Recupera il tuo account",
"Recover": "Recupera",
"UserProfilesRecoverHeading": "Sono stati trovati dei salvataggi per i seguenti account"
}

View File

@@ -1,613 +0,0 @@
{
"MenuBarFileOpenApplet": "アプレットを開く",
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "スタンドアロンモードで Mii エディタアプレットを開きます",
"SettingsTabInputDirectMouseAccess": "マウス直接アクセス",
"SettingsTabSystemMemoryManagerMode": "メモリ管理モード:",
"SettingsTabSystemMemoryManagerModeSoftware": "ソフトウェア",
"SettingsTabSystemMemoryManagerModeHost": "ホスト (高速)",
"SettingsTabSystemMemoryManagerModeHostUnchecked": "ホスト, チェックなし (最高速, 安全でない)",
"MenuBarFile": "ファイル(_F)",
"MenuBarFileOpenFromFile": "ファイルからアプリケーションをロード(_L)",
"MenuBarFileOpenUnpacked": "展開されたゲームをロード",
"MenuBarFileOpenEmuFolder": "Ryujinx フォルダを開く",
"MenuBarFileOpenLogsFolder": "ログフォルダを開く",
"MenuBarFileExit": "終了(_E)",
"MenuBarOptions": "オプション",
"MenuBarOptionsToggleFullscreen": "全画面切り替え",
"MenuBarOptionsStartGamesInFullscreen": "全画面モードでゲームを開始",
"MenuBarOptionsStopEmulation": "エミュレーションを停止",
"MenuBarOptionsSettings": "設定(_S)",
"MenuBarOptionsManageUserProfiles": "ユーザプロファイルを管理(_M)",
"MenuBarActions": "アクション(_A)",
"MenuBarOptionsSimulateWakeUpMessage": "スリープ復帰メッセージをシミュレート",
"MenuBarActionsScanAmiibo": "Amiibo をスキャン",
"MenuBarTools": "ツール(_T)",
"MenuBarToolsInstallFirmware": "ファームウェアをインストール",
"MenuBarFileToolsInstallFirmwareFromFile": "XCI または ZIP からファームウェアをインストール",
"MenuBarFileToolsInstallFirmwareFromDirectory": "ディレクトリからファームウェアをインストール",
"MenuBarHelp": "ヘルプ",
"MenuBarHelpCheckForUpdates": "アップデートを確認",
"MenuBarHelpAbout": "Ryujinx について",
"MenuSearch": "検索...",
"GameListHeaderFavorite": "お気に入り",
"GameListHeaderIcon": "アイコン",
"GameListHeaderApplication": "名称",
"GameListHeaderDeveloper": "開発元",
"GameListHeaderVersion": "バージョン",
"GameListHeaderTimePlayed": "プレイ時間",
"GameListHeaderLastPlayed": "最終プレイ日時",
"GameListHeaderFileExtension": "ファイル拡張子",
"GameListHeaderFileSize": "ファイルサイズ",
"GameListHeaderPath": "パス",
"GameListContextMenuOpenUserSaveDirectory": "セーブディレクトリを開く",
"GameListContextMenuOpenUserSaveDirectoryToolTip": "アプリケーションのユーザセーブデータを格納するディレクトリを開きます",
"GameListContextMenuOpenUserDeviceDirectory": "デバイスディレクトリを開く",
"GameListContextMenuOpenUserDeviceDirectoryToolTip": "アプリケーションのデバイスセーブデータを格納するディレクトリを開きます",
"GameListContextMenuOpenUserBcatDirectory": "BCATディレクトリを開く",
"GameListContextMenuOpenUserBcatDirectoryToolTip": "アプリケーションの BCAT セーブデータを格納するディレクトリを開きます",
"GameListContextMenuManageTitleUpdates": "アップデートを管理",
"GameListContextMenuManageTitleUpdatesToolTip": "タイトルのアップデート管理ウインドウを開きます",
"GameListContextMenuManageDlc": "DLCを管理",
"GameListContextMenuManageDlcToolTip": "DLC管理ウインドウを開きます",
"GameListContextMenuOpenModsDirectory": "Modディレクトリを開く",
"GameListContextMenuOpenModsDirectoryToolTip": "アプリケーションの Mod データを格納するディレクトリを開きます",
"GameListContextMenuCacheManagement": "キャッシュ管理",
"GameListContextMenuCacheManagementPurgePptc": "PPTC を再構築",
"GameListContextMenuCacheManagementPurgePptcToolTip": "次回のゲーム起動時に PPTC を再構築します",
"GameListContextMenuCacheManagementPurgeShaderCache": "シェーダキャッシュを破棄",
"GameListContextMenuCacheManagementPurgeShaderCacheToolTip": "アプリケーションのシェーダキャッシュを破棄します",
"GameListContextMenuCacheManagementOpenPptcDirectory": "PPTC ディレクトリを開く",
"GameListContextMenuCacheManagementOpenPptcDirectoryToolTip": "アプリケーションの PPTC キャッシュを格納するディレクトリを開きます",
"GameListContextMenuCacheManagementOpenShaderCacheDirectory": "シェーダキャッシュディレクトリを開く",
"GameListContextMenuCacheManagementOpenShaderCacheDirectoryToolTip": "アプリケーションのシェーダキャッシュを格納するディレクトリを開きます",
"GameListContextMenuExtractData": "データを展開",
"GameListContextMenuExtractDataExeFS": "ExeFS",
"GameListContextMenuExtractDataExeFSToolTip": "現在のアプリケーション設定(アップデート含む)から ExeFS セクションを展開します",
"GameListContextMenuExtractDataRomFS": "RomFS",
"GameListContextMenuExtractDataRomFSToolTip": "現在のアプリケーション設定(アップデート含む)から RomFS セクションを展開します",
"GameListContextMenuExtractDataLogo": "ロゴ",
"GameListContextMenuExtractDataLogoToolTip": "現在のアプリケーション設定(アップデート含む)からロゴセクションを展開します",
"StatusBarGamesLoaded": "{0}/{1} ゲーム",
"StatusBarSystemVersion": "システムバージョン: {0}",
"Settings": "設定",
"SettingsTabGeneral": "ユーザインタフェース",
"SettingsTabGeneralGeneral": "一般",
"SettingsTabGeneralEnableDiscordRichPresence": "Discord リッチプレゼンスを有効",
"SettingsTabGeneralCheckUpdatesOnLaunch": "起動時にアップデートを確認",
"SettingsTabGeneralShowConfirmExitDialog": "\"終了を確認\" ダイアログを表示",
"SettingsTabGeneralHideCursorOnIdle": "アイドル時にカーソルを隠す",
"SettingsTabGeneralGameDirectories": "ゲームディレクトリ",
"SettingsTabGeneralAdd": "追加",
"SettingsTabGeneralRemove": "削除",
"SettingsTabSystem": "システム",
"SettingsTabSystemCore": "コア",
"SettingsTabSystemSystemRegion": "地域:",
"SettingsTabSystemSystemRegionJapan": "日本",
"SettingsTabSystemSystemRegionUSA": "アメリカ",
"SettingsTabSystemSystemRegionEurope": "ヨーロッパ",
"SettingsTabSystemSystemRegionAustralia": "オーストラリア",
"SettingsTabSystemSystemRegionChina": "中国",
"SettingsTabSystemSystemRegionKorea": "韓国",
"SettingsTabSystemSystemRegionTaiwan": "台湾",
"SettingsTabSystemSystemLanguage": "言語:",
"SettingsTabSystemSystemLanguageJapanese": "日本語",
"SettingsTabSystemSystemLanguageAmericanEnglish": "英語(アメリカ)",
"SettingsTabSystemSystemLanguageFrench": "フランス語",
"SettingsTabSystemSystemLanguageGerman": "ドイツ語",
"SettingsTabSystemSystemLanguageItalian": "イタリア語",
"SettingsTabSystemSystemLanguageSpanish": "スペイン語",
"SettingsTabSystemSystemLanguageChinese": "中国語",
"SettingsTabSystemSystemLanguageKorean": "韓国語",
"SettingsTabSystemSystemLanguageDutch": "オランダ語",
"SettingsTabSystemSystemLanguagePortuguese": "ポルトガル語",
"SettingsTabSystemSystemLanguageRussian": "ロシア語",
"SettingsTabSystemSystemLanguageTaiwanese": "台湾語",
"SettingsTabSystemSystemLanguageBritishEnglish": "英語(イギリス)",
"SettingsTabSystemSystemLanguageCanadianFrench": "フランス語(カナダ)",
"SettingsTabSystemSystemLanguageLatinAmericanSpanish": "スペイン語(ラテンアメリカ)",
"SettingsTabSystemSystemLanguageSimplifiedChinese": "中国語",
"SettingsTabSystemSystemLanguageTraditionalChinese": "台湾語",
"SettingsTabSystemSystemTimeZone": "タイムゾーン:",
"SettingsTabSystemSystemTime": "時刻:",
"SettingsTabSystemEnableVsync": "VSync",
"SettingsTabSystemEnablePptc": "PPTC (Profiled Persistent Translation Cache)",
"SettingsTabSystemEnableFsIntegrityChecks": "ファイルシステム整合性チェック",
"SettingsTabSystemAudioBackend": "音声バックエンド:",
"SettingsTabSystemAudioBackendDummy": "ダミー",
"SettingsTabSystemAudioBackendOpenAL": "OpenAL",
"SettingsTabSystemAudioBackendSoundIO": "SoundIO",
"SettingsTabSystemAudioBackendSDL2": "SDL2",
"SettingsTabSystemHacks": "ハック",
"SettingsTabSystemHacksNote": " (挙動が不安定になる可能性があります)",
"SettingsTabSystemExpandDramSize": "DRAMサイズを6GiBに拡大",
"SettingsTabSystemIgnoreMissingServices": "未実装サービスを無視",
"SettingsTabGraphics": "グラフィックス",
"SettingsTabGraphicsAPI": "グラフィックスAPI",
"SettingsTabGraphicsEnableShaderCache": "シェーダキャッシュを有効",
"SettingsTabGraphicsAnisotropicFiltering": "異方性フィルタリング:",
"SettingsTabGraphicsAnisotropicFilteringAuto": "自動",
"SettingsTabGraphicsAnisotropicFiltering2x": "2x",
"SettingsTabGraphicsAnisotropicFiltering4x": "4x",
"SettingsTabGraphicsAnisotropicFiltering8x": "8x",
"SettingsTabGraphicsAnisotropicFiltering16x": "16x",
"SettingsTabGraphicsResolutionScale": "解像度:",
"SettingsTabGraphicsResolutionScaleCustom": "カスタム (非推奨)",
"SettingsTabGraphicsResolutionScaleNative": "ネイティブ (720p/1080p)",
"SettingsTabGraphicsResolutionScale2x": "2x (1440p/2160p)",
"SettingsTabGraphicsResolutionScale3x": "3x (2160p/3240p)",
"SettingsTabGraphicsResolutionScale4x": "4x (2880p/4320p)",
"SettingsTabGraphicsAspectRatio": "アスペクト比:",
"SettingsTabGraphicsAspectRatio4x3": "4:3",
"SettingsTabGraphicsAspectRatio16x9": "16:9",
"SettingsTabGraphicsAspectRatio16x10": "16:10",
"SettingsTabGraphicsAspectRatio21x9": "21:9",
"SettingsTabGraphicsAspectRatio32x9": "32:9",
"SettingsTabGraphicsAspectRatioStretch": "ウインドウサイズに合わせる",
"SettingsTabGraphicsDeveloperOptions": "開発者向けオプション",
"SettingsTabGraphicsShaderDumpPath": "グラフィックス シェーダダンプパス:",
"SettingsTabLogging": "ロギング",
"SettingsTabLoggingLogging": "ロギング",
"SettingsTabLoggingEnableLoggingToFile": "ファイルへのロギングを有効",
"SettingsTabLoggingEnableStubLogs": "Stub ログを有効",
"SettingsTabLoggingEnableInfoLogs": "Info ログを有効",
"SettingsTabLoggingEnableWarningLogs": "Warning ログを有効",
"SettingsTabLoggingEnableErrorLogs": "Error ログを有効",
"SettingsTabLoggingEnableTraceLogs": "Trace ログを有効",
"SettingsTabLoggingEnableGuestLogs": "Guest ログを有効",
"SettingsTabLoggingEnableFsAccessLogs": "Fs アクセスログを有効",
"SettingsTabLoggingFsGlobalAccessLogMode": "Fs グローバルアクセスログモード:",
"SettingsTabLoggingDeveloperOptions": "開発者オプション (警告: パフォーマンスが低下します)",
"SettingsTabLoggingGraphicsBackendLogLevel": "グラフィックスバックエンド ログレベル:",
"SettingsTabLoggingGraphicsBackendLogLevelNone": "なし",
"SettingsTabLoggingGraphicsBackendLogLevelError": "エラー",
"SettingsTabLoggingGraphicsBackendLogLevelPerformance": "パフォーマンス低下",
"SettingsTabLoggingGraphicsBackendLogLevelAll": "すべて",
"SettingsTabLoggingEnableDebugLogs": "デバッグログを有効",
"SettingsTabInput": "入力",
"SettingsTabInputEnableDockedMode": "ドッキングモード",
"SettingsTabInputDirectKeyboardAccess": "キーボード直接アクセス",
"SettingsButtonSave": "セーブ",
"SettingsButtonClose": "閉じる",
"SettingsButtonOk": "OK",
"SettingsButtonCancel": "キャンセル",
"SettingsButtonApply": "適用",
"ControllerSettingsPlayer": "プレイヤー",
"ControllerSettingsPlayer1": "プレイヤー 1",
"ControllerSettingsPlayer2": "プレイヤー 2",
"ControllerSettingsPlayer3": "プレイヤー 3",
"ControllerSettingsPlayer4": "プレイヤー 4",
"ControllerSettingsPlayer5": "プレイヤー 5",
"ControllerSettingsPlayer6": "プレイヤー 6",
"ControllerSettingsPlayer7": "プレイヤー 7",
"ControllerSettingsPlayer8": "プレイヤー 8",
"ControllerSettingsHandheld": "携帯",
"ControllerSettingsInputDevice": "入力デバイス",
"ControllerSettingsRefresh": "更新",
"ControllerSettingsDeviceDisabled": "無効",
"ControllerSettingsControllerType": "コントローラ種別",
"ControllerSettingsControllerTypeHandheld": "携帯",
"ControllerSettingsControllerTypeProController": "Pro コントローラ",
"ControllerSettingsControllerTypeJoyConPair": "JoyCon ペア",
"ControllerSettingsControllerTypeJoyConLeft": "JoyCon 左",
"ControllerSettingsControllerTypeJoyConRight": "JoyCon 右",
"ControllerSettingsProfile": "プロファイル",
"ControllerSettingsProfileDefault": "デフォルト",
"ControllerSettingsLoad": "ロード",
"ControllerSettingsAdd": "追加",
"ControllerSettingsRemove": "削除",
"ControllerSettingsButtons": "ボタン",
"ControllerSettingsButtonA": "A",
"ControllerSettingsButtonB": "B",
"ControllerSettingsButtonX": "X",
"ControllerSettingsButtonY": "Y",
"ControllerSettingsButtonPlus": "+",
"ControllerSettingsButtonMinus": "-",
"ControllerSettingsDPad": "十字キー",
"ControllerSettingsDPadUp": "上",
"ControllerSettingsDPadDown": "下",
"ControllerSettingsDPadLeft": "左",
"ControllerSettingsDPadRight": "右",
"ControllerSettingsLStick": "左スティック",
"ControllerSettingsLStickButton": "ボタン",
"ControllerSettingsLStickUp": "上",
"ControllerSettingsLStickDown": "下",
"ControllerSettingsLStickLeft": "左",
"ControllerSettingsLStickRight": "右",
"ControllerSettingsLStickStick": "スティック",
"ControllerSettingsLStickInvertXAxis": "X軸を反転",
"ControllerSettingsLStickInvertYAxis": "Y軸を反転",
"ControllerSettingsLStickDeadzone": "遊び:",
"ControllerSettingsRStick": "右スティック",
"ControllerSettingsRStickButton": "ボタン",
"ControllerSettingsRStickUp": "上",
"ControllerSettingsRStickDown": "下",
"ControllerSettingsRStickLeft": "左",
"ControllerSettingsRStickRight": "右",
"ControllerSettingsRStickStick": "スティック",
"ControllerSettingsRStickInvertXAxis": "X軸を反転",
"ControllerSettingsRStickInvertYAxis": "Y軸を反転",
"ControllerSettingsRStickDeadzone": "遊び:",
"ControllerSettingsTriggersLeft": "左トリガー",
"ControllerSettingsTriggersRight": "右トリガー",
"ControllerSettingsTriggersButtonsLeft": "左トリガーボタン",
"ControllerSettingsTriggersButtonsRight": "右トリガーボタン",
"ControllerSettingsTriggers": "トリガー",
"ControllerSettingsTriggerL": "L",
"ControllerSettingsTriggerR": "R",
"ControllerSettingsTriggerZL": "ZL",
"ControllerSettingsTriggerZR": "ZR",
"ControllerSettingsLeftSL": "SL",
"ControllerSettingsLeftSR": "SR",
"ControllerSettingsRightSL": "SL",
"ControllerSettingsRightSR": "SR",
"ControllerSettingsExtraButtonsLeft": "左ボタン",
"ControllerSettingsExtraButtonsRight": "右ボタン",
"ControllerSettingsMisc": "その他",
"ControllerSettingsTriggerThreshold": "トリガーしきい値:",
"ControllerSettingsMotion": "モーション",
"ControllerSettingsMotionUseCemuhookCompatibleMotion": "CemuHook 互換モーションを使用",
"ControllerSettingsMotionControllerSlot": "コントローラ スロット:",
"ControllerSettingsMotionMirrorInput": "入力反転",
"ControllerSettingsMotionRightJoyConSlot": "JoyCon 右 スロット:",
"ControllerSettingsMotionServerHost": "サーバ:",
"ControllerSettingsMotionGyroSensitivity": "ジャイロ感度:",
"ControllerSettingsMotionGyroDeadzone": "ジャイロ遊び:",
"ControllerSettingsSave": "セーブ",
"ControllerSettingsClose": "閉じる",
"UserProfilesSelectedUserProfile": "選択されたユーザプロファイル:",
"UserProfilesSaveProfileName": "プロファイル名をセーブ",
"UserProfilesChangeProfileImage": "プロファイル画像を変更",
"UserProfilesAvailableUserProfiles": "利用可能なユーザプロファイル:",
"UserProfilesAddNewProfile": "プロファイルを作成",
"UserProfilesDeleteSelectedProfile": "削除",
"UserProfilesClose": "閉じる",
"ProfileImageSelectionTitle": "プロファイル画像選択",
"ProfileImageSelectionHeader": "プロファイル画像を選択",
"ProfileImageSelectionNote": "カスタム画像をインポート, またはファームウェア内のアバターを選択できます",
"ProfileImageSelectionImportImage": "画像ファイルをインポート",
"ProfileImageSelectionSelectAvatar": "ファームウェア内のアバターを選択",
"InputDialogTitle": "入力ダイアログ",
"InputDialogOk": "OK",
"InputDialogCancel": "キャンセル",
"InputDialogAddNewProfileTitle": "プロファイル名を選択",
"InputDialogAddNewProfileHeader": "プロファイル名を入力してください",
"InputDialogAddNewProfileSubtext": "(最大長: {0})",
"AvatarChoose": "選択",
"AvatarSetBackgroundColor": "背景色を指定",
"AvatarClose": "閉じる",
"ControllerSettingsLoadProfileToolTip": "プロファイルをロード",
"ControllerSettingsAddProfileToolTip": "プロファイルを追加",
"ControllerSettingsRemoveProfileToolTip": "プロファイルを削除",
"ControllerSettingsSaveProfileToolTip": "プロファイルをセーブ",
"MenuBarFileToolsTakeScreenshot": "スクリーンショットを撮影",
"MenuBarFileToolsHideUi": "Hide UI",
"GameListContextMenuToggleFavorite": "お気に入りを切り替え",
"GameListContextMenuToggleFavoriteToolTip": "ゲームをお気に入りに含めるかどうかを切り替えます",
"SettingsTabGeneralTheme": "テーマ",
"SettingsTabGeneralThemeCustomTheme": "カスタムテーマパス",
"SettingsTabGeneralThemeBaseStyle": "基本スタイル",
"SettingsTabGeneralThemeBaseStyleDark": "ダーク",
"SettingsTabGeneralThemeBaseStyleLight": "ライト",
"SettingsTabGeneralThemeEnableCustomTheme": "カスタムテーマを有効",
"ButtonBrowse": "参照",
"ControllerSettingsConfigureGeneral": "設定",
"ControllerSettingsRumble": "振動",
"ControllerSettingsRumbleStrongMultiplier": "強振動の補正値",
"ControllerSettingsRumbleWeakMultiplier": "弱振動の補正値",
"DialogMessageSaveNotAvailableMessage": "{0} [{1:x16}] のセーブデータはありません",
"DialogMessageSaveNotAvailableCreateSaveMessage": "このゲームのセーブデータを作成してよろしいですか?",
"DialogConfirmationTitle": "Ryujinx - 確認",
"DialogUpdaterTitle": "Ryujinx - アップデータ",
"DialogErrorTitle": "Ryujinx - エラー",
"DialogWarningTitle": "Ryujinx - 警告",
"DialogExitTitle": "Ryujinx - 終了",
"DialogErrorMessage": "エラーが発生しました",
"DialogExitMessage": "Ryujinx を閉じてよろしいですか?",
"DialogExitSubMessage": "セーブされていないデータはすべて失われます!",
"DialogMessageCreateSaveErrorMessage": "セーブデータ: {0} の作成中にエラーが発生しました",
"DialogMessageFindSaveErrorMessage": "セーブデータ: {0} の検索中にエラーが発生しました",
"FolderDialogExtractTitle": "展開フォルダを選択",
"DialogNcaExtractionMessage": "{1} から {0} セクションを展開中...",
"DialogNcaExtractionTitle": "Ryujinx - NCA セクション展開",
"DialogNcaExtractionMainNcaNotFoundErrorMessage": "展開に失敗しました. 選択されたファイルにはメイン NCA が存在しません.",
"DialogNcaExtractionCheckLogErrorMessage": "展開に失敗しました. 詳細はログを確認してください.",
"DialogNcaExtractionSuccessMessage": "展開が正常終了しました",
"DialogUpdaterConvertFailedMessage": "現在の Ryujinx バージョンの変換に失敗しました.",
"DialogUpdaterCancelUpdateMessage": "アップデータをキャンセル中!",
"DialogUpdaterAlreadyOnLatestVersionMessage": "最新バージョンの Ryujinx を使用中です!",
"DialogUpdaterFailedToGetVersionMessage": "An error has occurred when trying to get release information from GitHub Release. This can be caused if a new release is being compiled by GitHub Actions. Try again in a few minutes.",
"DialogUpdaterConvertFailedGithubMessage": "Github から取得した Ryujinx バージョンの変換に失敗しました.",
"DialogUpdaterDownloadingMessage": "アップデートをダウンロード中...",
"DialogUpdaterExtractionMessage": "アップデートを展開中...",
"DialogUpdaterRenamingMessage": "アップデートをリネーム中...",
"DialogUpdaterAddingFilesMessage": "新規アップデートを追加中...",
"DialogUpdaterCompleteMessage": "アップデート完了!",
"DialogUpdaterRestartMessage": "すぐに Ryujinx を再起動しますか?",
"DialogUpdaterArchNotSupportedMessage": "サポート外のアーキテクチャです!",
"DialogUpdaterArchNotSupportedSubMessage": "(x64 システムのみサポートしています!)",
"DialogUpdaterNoInternetMessage": "インターネットに接続されていません!",
"DialogUpdaterNoInternetSubMessage": "インターネット接続が正常動作しているか確認してください!",
"DialogUpdaterDirtyBuildMessage": "Dirty ビルドの Ryujinx はアップデートできません!",
"DialogUpdaterDirtyBuildSubMessage": "サポートされているバージョンをお探しなら, https://ryujinx.org/ で Ryujinx をダウンロードしてください.",
"DialogRestartRequiredMessage": "再起動が必要",
"DialogThemeRestartMessage": "テーマがセーブされました. テーマを適用するには再起動が必要です.",
"DialogThemeRestartSubMessage": "再起動しますか",
"DialogFirmwareInstallEmbeddedMessage": "このゲームに含まれるファームウェアをインストールしてよろしいですか? (ファームウェア {0})",
"DialogFirmwareInstallEmbeddedSuccessMessage": "ファームウェアがインストールされていませんが, ゲームに含まれるファームウェア {0} をインストールできます.\\nエミュレータが開始します.",
"DialogFirmwareNoFirmwareInstalledMessage": "ファームウェアがインストールされていません",
"DialogFirmwareInstalledMessage": "ファームウェア {0} がインストールされました",
"DialogOpenSettingsWindowLabel": "設定ウインドウを開く",
"DialogControllerAppletTitle": "コントローラアプレット",
"DialogMessageDialogErrorExceptionMessage": "メッセージダイアログ表示エラー: {0}",
"DialogSoftwareKeyboardErrorExceptionMessage": "ソフトウェアキーボード表示エラー: {0}",
"DialogErrorAppletErrorExceptionMessage": "エラーアプレットダイアログ表示エラー: {0}",
"DialogUserErrorDialogMessage": "{0}: {1}",
"DialogUserErrorDialogInfoMessage": "\nこのエラーへの対処方法については, セットアップガイドを参照してください.",
"DialogUserErrorDialogTitle": "Ryujinx エラー ({0})",
"DialogAmiiboApiTitle": "Amiibo API",
"DialogAmiiboApiFailFetchMessage": "API からの情報取得中にエラーが発生しました.",
"DialogAmiiboApiConnectErrorMessage": "Amiibo API サーバに接続できませんでした. サーバがダウンしているか, インターネット接続に問題があるかもしれません.",
"DialogProfileInvalidProfileErrorMessage": "プロファイル {0} は現在の入力設定システムと互換性がありません.",
"DialogProfileDefaultProfileOverwriteErrorMessage": "デフォルトのプロファイルは上書きできません",
"DialogProfileDeleteProfileTitle": "プロファイルを削除中",
"DialogProfileDeleteProfileMessage": "このアクションは元に戻せません. 本当に続けてよろしいですか?",
"DialogWarning": "警告",
"DialogPPTCDeletionMessage": "次回起動時に PPTC を再構築します:\n\n{0}\n\n実行してよろしいですか?",
"DialogPPTCDeletionErrorMessage": "PPTC キャッシュ破棄エラー {0}: {1}",
"DialogShaderDeletionMessage": "シェーダキャッシュを破棄しようとしています:\n\n{0}\n\n実行してよろしいですか?",
"DialogShaderDeletionErrorMessage": "シェーダキャッシュ破棄エラー {0}: {1}",
"DialogRyujinxErrorMessage": "エラーが発生しました",
"DialogInvalidTitleIdErrorMessage": "UI エラー: 選択されたゲームは有効なタイトル ID を保持していません",
"DialogFirmwareInstallerFirmwareNotFoundErrorMessage": "{0} には有効なシステムファームウェアがありません.",
"DialogFirmwareInstallerFirmwareInstallTitle": "ファームウェア {0} をインストール",
"DialogFirmwareInstallerFirmwareInstallMessage": "システムバージョン {0} がインストールされます.",
"DialogFirmwareInstallerFirmwareInstallSubMessage": "\n\n現在のシステムバージョン {0} を置き換えます.",
"DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\n続けてよろしいですか?",
"DialogFirmwareInstallerFirmwareInstallWaitMessage": "ファームウェアをインストール中...",
"DialogFirmwareInstallerFirmwareInstallSuccessMessage": "システムバージョン {0} が正常にインストールされました.",
"DialogUserProfileDeletionWarningMessage": "選択されたプロファイルを削除すると,プロファイルがひとつも存在しなくなります",
"DialogUserProfileDeletionConfirmMessage": "選択されたプロファイルを削除しますか",
"DialogControllerSettingsModifiedConfirmMessage": "現在のコントローラ設定が更新されました.",
"DialogControllerSettingsModifiedConfirmSubMessage": "セーブしますか?",
"DialogDlcLoadNcaErrorMessage": "{0}. エラー発生ファイル: {1}",
"DialogDlcNoDlcErrorMessage": "選択されたファイルはこのタイトル用の DLC ではありません!",
"DialogPerformanceCheckLoggingEnabledMessage": "トレースロギングを有効にします. これは開発者のみに有用な機能です.",
"DialogPerformanceCheckLoggingEnabledConfirmMessage": "パフォーマンス最適化のためには,トレースロギングを無効にすることを推奨します. トレースロギングを無効にしてよろしいですか?",
"DialogPerformanceCheckShaderDumpEnabledMessage": "シェーダダンプを有効にします. これは開発者のみに有用な機能です.",
"DialogPerformanceCheckShaderDumpEnabledConfirmMessage": "パフォーマンス最適化のためには, シェーダダンプを無効にすることを推奨します. シェーダダンプを無効にしてよろしいですか?",
"DialogLoadAppGameAlreadyLoadedMessage": "ゲームはすでにロード済みです",
"DialogLoadAppGameAlreadyLoadedSubMessage": "別のゲームを起動する前に, エミュレーションを停止またはエミュレータを閉じてください.",
"DialogUpdateAddUpdateErrorMessage": "選択されたファイルはこのタイトル用のアップデートではありません!",
"DialogSettingsBackendThreadingWarningTitle": "警告 - バックエンドスレッディング",
"DialogSettingsBackendThreadingWarningMessage": "このオプションの変更を完全に適用するには Ryujinx の再起動が必要です. プラットフォームによっては, Ryujinx のものを使用する前に手動でドライバ自身のマルチスレッディングを無効にする必要があるかもしれません.",
"SettingsTabGraphicsFeaturesOptions": "機能",
"SettingsTabGraphicsBackendMultithreading": "グラフィックスバックエンドのマルチスレッド実行:",
"CommonAuto": "自動",
"CommonOff": "オフ",
"CommonOn": "オン",
"InputDialogYes": "はい",
"InputDialogNo": "いいえ",
"DialogProfileInvalidProfileNameErrorMessage": "プロファイル名に無効な文字が含まれています. 再度試してみてください.",
"MenuBarOptionsPauseEmulation": "中断",
"MenuBarOptionsResumeEmulation": "再開",
"AboutUrlTooltipMessage": "クリックするとデフォルトのブラウザで Ryujinx のウェブサイトを開きます.",
"AboutDisclaimerMessage": "Ryujinx は Nintendo™ および\nそのパートナー企業とは一切関係ありません.",
"AboutAmiiboDisclaimerMessage": "AmiiboAPI (www.amiiboapi.com) は\nAmiibo エミュレーションに使用されています.",
"AboutPatreonUrlTooltipMessage": "クリックするとデフォルトのブラウザで Ryujinx の Patreon ページを開きます.",
"AboutGithubUrlTooltipMessage": "クリックするとデフォルトのブラウザで Ryujinx の Github ページを開きます.",
"AboutDiscordUrlTooltipMessage": "クリックするとデフォルトのブラウザで Ryujinx の Discord サーバを開きます.",
"AboutTwitterUrlTooltipMessage": "クリックするとデフォルトのブラウザで Ryujinx の Twitter ページを開きます.",
"AboutRyujinxAboutTitle": "Ryujinx について:",
"AboutRyujinxAboutContent": "Ryujinx は Nintendo Switch™ のエミュレータです.\nPatreon で私達の活動を支援してください.\n最新の情報は Twitter または Discord から取得できます.\n貢献したい開発者の方は GitHub または Discord で詳細をご確認ください.",
"AboutRyujinxMaintainersTitle": "開発者:",
"AboutRyujinxMaintainersContentTooltipMessage": "クリックするとデフォルトのブラウザで 貢献者のページを開きます.",
"AboutRyujinxSupprtersTitle": "Patreon での支援者:",
"AmiiboSeriesLabel": "Amiibo シリーズ",
"AmiiboCharacterLabel": "キャラクタ",
"AmiiboScanButtonLabel": "スキャン",
"AmiiboOptionsShowAllLabel": "すべての Amiibo を表示",
"AmiiboOptionsUsRandomTagLabel": "ハック: ランダムな Uuid を使用",
"DlcManagerTableHeadingEnabledLabel": "有効",
"DlcManagerTableHeadingTitleIdLabel": "タイトルID",
"DlcManagerTableHeadingContainerPathLabel": "コンテナパス",
"DlcManagerTableHeadingFullPathLabel": "フルパス",
"DlcManagerRemoveAllButton": "すべて削除",
"DlcManagerEnableAllButton": "すべて有効",
"DlcManagerDisableAllButton": "すべて無効",
"MenuBarOptionsChangeLanguage": "言語を変更",
"CommonSort": "並べ替え",
"CommonShowNames": "名称を表示",
"CommonFavorite": "お気に入り",
"OrderAscending": "昇順",
"OrderDescending": "降順",
"SettingsTabGraphicsFeatures": "機能",
"ErrorWindowTitle": "エラーウインドウ",
"ToggleDiscordTooltip": "Discord の \"現在プレイ中\" アクティビティに Ryujinx を表示するかどうかを選択します",
"AddGameDirBoxTooltip": "リストに追加するゲームディレクトリを入力します",
"AddGameDirTooltip": "リストにゲームディレクトリを追加します",
"RemoveGameDirTooltip": "選択したゲームディレクトリを削除します",
"CustomThemeCheckTooltip": "エミュレータのメニュー外観を変更するためカスタム Avalonia テーマを使用します",
"CustomThemePathTooltip": "カスタム GUI テーマのパスです",
"CustomThemeBrowseTooltip": "カスタム GUI テーマを参照します",
"DockModeToggleTooltip": "有効にすると,ドッキングされた Nintendo Switch をエミュレートします.多くのゲームではグラフィックス品質が向上します.\n無効にすると,携帯モードの Nintendo Switch をエミュレートします.グラフィックスの品質は低下します.\n\nドッキングモード有効ならプレイヤー1の,無効なら携帯の入力を設定してください.\n\nよくわからない場合はオンのままにしてください.",
"DirectKeyboardTooltip": "キーボード直接アクセス (HID) に対応します. キーボードをテキスト入力デバイスとして使用できます.",
"DirectMouseTooltip": "マウス直接アクセス (HID) に対応します. マウスをポインティングデバイスとして使用できます.",
"RegionTooltip": "システムの地域を変更します",
"LanguageTooltip": "システムの言語を変更します",
"TimezoneTooltip": "システムのタイムゾーンを変更します",
"TimeTooltip": "システムの時刻を変更します",
"VSyncToggleTooltip": "エミュレートされたゲーム機の垂直同期です. 多くのゲームにおいて, フレームリミッタとして機能します. 無効にすると, ゲームが高速で実行されたり, ロード中に時間がかかったり, 止まったりすることがあります.\n\n設定したホットキーで, ゲーム内で切り替え可能です. 無効にする場合は, この操作を行うことをおすすめします.\n\nよくわからない場合はオンのままにしてください.",
"PptcToggleTooltip": "翻訳されたJIT関数をセーブすることで, ゲームをロードするたびに毎回翻訳する処理を不要とします.\n\n一度ゲームを起動すれば,二度目以降の起動時遅延を大きく軽減できます.\n\nよくわからない場合はオンのままにしてください.",
"FsIntegrityToggleTooltip": "ゲーム起動時にファイル破損をチェックし,破損が検出されたらログにハッシュエラーを表示します..\n\nパフォーマンスには影響なく, トラブルシューティングに役立ちます.\n\nよくわからない場合はオンのままにしてください.",
"AudioBackendTooltip": "音声レンダリングに使用するバックエンドを変更します.\n\nSDL2 が優先され, OpenAL と SoundIO はフォールバックとして使用されます. ダミーは音声出力しません.\n\nよくわからない場合は SDL2 を設定してください.",
"MemoryManagerTooltip": "ゲストメモリのマップ/アクセス方式を変更します. エミュレートされるCPUのパフォーマンスに大きな影響を与えます.\n\nよくわからない場合は「ホスト,チェックなし」を設定してください.",
"MemoryManagerSoftwareTooltip": "アドレス変換にソフトウェアページテーブルを使用します. 非常に正確ですがパフォーマンスが大きく低下します.",
"MemoryManagerHostTooltip": "ホストのアドレス空間にメモリを直接マップします.JITのコンパイルと実行速度が大きく向上します.",
"MemoryManagerUnsafeTooltip": "メモリを直接マップしますが, アクセス前にゲストのアドレス空間内のアドレスをマスクしません. より高速になりますが, 安全性が犠牲になります. ゲストアプリケーションは Ryujinx のどこからでもメモリにアクセスできるので,このモードでは信頼できるプログラムだけを実行するようにしてください.",
"DRamTooltip": "エミュレートされたシステムのメモリ容量を 4GiB から 6GiB に増加します.\n\n高解像度のテクスチャパックや 4K解像度の mod を使用する場合に有用です. パフォーマンスを改善するものではありません.\n\nよくわからない場合はオフのままにしてください.",
"IgnoreMissingServicesTooltip": "未実装の Horizon OS サービスを無視します. 特定のゲームにおいて起動時のクラッシュを回避できる場合があります.\n\nよくわからない場合はオフのままにしてください.",
"GraphicsBackendThreadingTooltip": "グラフィックスバックエンドのコマンドを別スレッドで実行します.\n\nシェーダのコンパイルを高速化し, 遅延を軽減し, マルチスレッド非対応の GPU ドライバにおいてパフォーマンスを改善します. マルチスレッド対応のドライバでも若干パフォーマンス改善が見られます.\n\nよくわからない場合は自動に設定してください.",
"GalThreadingTooltip": "グラフィックスバックエンドのコマンドを別スレッドで実行します.\n\nシェーダのコンパイルを高速化し, 遅延を軽減し, マルチスレッド非対応の GPU ドライバにおいてパフォーマンスを改善します. マルチスレッド対応のドライバでも若干パフォーマンス改善が見られます.\n\nよくわからない場合は自動に設定してください.",
"ShaderCacheToggleTooltip": "ディスクシェーダキャッシュをセーブし,次回以降の実行時遅延を軽減します.\n\nよくわからない場合はオンのままにしてください.",
"ResolutionScaleTooltip": "レンダリングに適用される解像度の倍率です",
"ResolutionScaleEntryTooltip": "1.5 のような整数でない倍率を指定すると,問題が発生したりクラッシュしたりする場合があります.",
"AnisotropyTooltip": "異方性フィルタリングのレベルです (ゲームが要求する値を使用する場合は「自動」を設定してください)",
"AspectRatioTooltip": "レンダリングに適用されるアスペクト比です.",
"ShaderDumpPathTooltip": "グラフィックス シェーダダンプのパスです",
"FileLogTooltip": "コンソール出力されるログをディスク上のログファイルにセーブします. パフォーマンスには影響を与えません.",
"StubLogTooltip": "stub ログメッセージをコンソールに出力します. パフォーマンスには影響を与えません.",
"InfoLogTooltip": "info ログメッセージをコンソールに出力します. パフォーマンスには影響を与えません.",
"WarnLogTooltip": "warning ログメッセージをコンソールに出力します. パフォーマンスには影響を与えません.",
"ErrorLogTooltip": "error ログメッセージをコンソールに出力します. パフォーマンスには影響を与えません.",
"TraceLogTooltip": "trace ログメッセージをコンソールに出力します. パフォーマンスには影響を与えません.",
"GuestLogTooltip": "guest ログメッセージをコンソールに出力します. パフォーマンスには影響を与えません.",
"FileAccessLogTooltip": "ファイルアクセスログメッセージをコンソールに出力します.",
"FSAccessLogModeTooltip": "コンソールへのファイルシステムアクセスログ出力を有効にします.0-3 のモードが有効です",
"DeveloperOptionTooltip": "使用上の注意",
"OpenGlLogLevel": "適切なログレベルを有効にする必要があります",
"DebugLogTooltip": "デバッグログメッセージをコンソールに出力します.\n\nログが読みづらくなり,エミュレータのパフォーマンスが低下するため,開発者から特別な指示がある場合のみ使用してください.",
"LoadApplicationFileTooltip": "ロードする Switch 互換のファイルを選択するためファイルエクスプローラを開きます",
"LoadApplicationFolderTooltip": "ロードする Switch 互換の展開済みアプリケーションを選択するためファイルエクスプローラを開きます",
"OpenRyujinxFolderTooltip": "Ryujinx ファイルシステムフォルダを開きます",
"OpenRyujinxLogsTooltip": "ログが格納されるフォルダを開きます",
"ExitTooltip": "Ryujinx を終了します",
"OpenSettingsTooltip": "設定ウインドウを開きます",
"OpenProfileManagerTooltip": "ユーザプロファイル管理ウインドウを開きます",
"StopEmulationTooltip": "ゲームのエミュレーションを停止してゲーム選択画面に戻ります",
"CheckUpdatesTooltip": "Ryujinx のアップデートを確認します",
"OpenAboutTooltip": "Ryujinx についてのウインドウを開きます",
"GridSize": "グリッドサイズ",
"GridSizeTooltip": "グリッドサイズを変更します",
"SettingsTabSystemSystemLanguageBrazilianPortuguese": "ポルトガル語(ブラジル)",
"AboutRyujinxContributorsButtonHeader": "すべての貢献者を確認",
"SettingsTabSystemAudioVolume": "音量: ",
"AudioVolumeTooltip": "音量を変更します",
"SettingsTabSystemEnableInternetAccess": "ゲストインターネットアクセス / LAN モード",
"EnableInternetAccessTooltip": "エミュレートしたアプリケーションをインターネットに接続できるようにします.\n\nLAN モードを持つゲーム同士は,この機能を有効にして同じアクセスポイントに接続すると接続できます. 実機も含まれます.\n\n任天堂のサーバーには接続できません. インターネットに接続しようとすると,特定のゲームでクラッシュすることがあります.\n\nよくわからない場合はオフのままにしてください.",
"GameListContextMenuManageCheatToolTip": "チートを管理します",
"GameListContextMenuManageCheat": "チートを管理",
"ControllerSettingsStickRange": "範囲:",
"DialogStopEmulationTitle": "Ryujinx - エミュレーションを停止",
"DialogStopEmulationMessage": "エミュレーションを停止してよろしいですか?",
"SettingsTabCpu": "CPU",
"SettingsTabAudio": "音声",
"SettingsTabNetwork": "ネットワーク",
"SettingsTabNetworkConnection": "ネットワーク接続",
"SettingsTabCpuCache": "CPU キャッシュ",
"SettingsTabCpuMemory": "CPU メモリ",
"DialogUpdaterFlatpakNotSupportedMessage": "FlatHub を使用して Ryujinx をアップデートしてください.",
"UpdaterDisabledWarningTitle": "アップデータは無効です!",
"GameListContextMenuOpenSdModsDirectory": "Atmosphere Mods ディレクトリを開く",
"GameListContextMenuOpenSdModsDirectoryToolTip": "アプリケーションの Mod データを格納する SD カードの Atmosphere ディレクトリを開きます. 実際のハードウェア用にパッケージされた Mod データに有用です.",
"ControllerSettingsRotate90": "時計回りに 90° 回転",
"IconSize": "アイコンサイズ",
"IconSizeTooltip": "ゲームアイコンのサイズを変更します",
"MenuBarOptionsShowConsole": "コンソールを表示",
"ShaderCachePurgeError": "シェーダキャッシュの破棄エラー {0}: {1}",
"UserErrorNoKeys": "Keys がありません",
"UserErrorNoFirmware": "ファームウェアがありません",
"UserErrorFirmwareParsingFailed": "ファームウェアのパーズエラー",
"UserErrorApplicationNotFound": "アプリケーションがありません",
"UserErrorUnknown": "不明なエラー",
"UserErrorUndefined": "未定義エラー",
"UserErrorNoKeysDescription": "'prod.keys' が見つかりませんでした",
"UserErrorNoFirmwareDescription": "インストールされたファームウェアが見つかりませんでした",
"UserErrorFirmwareParsingFailedDescription": "ファームウェアをパーズできませんでした.通常,古いキーが原因です.",
"UserErrorApplicationNotFoundDescription": "指定されたパスに有効なアプリケーションがありませんでした.",
"UserErrorUnknownDescription": "不明なエラーが発生しました!",
"UserErrorUndefinedDescription": "未定義のエラーが発生しました! 発生すべきものではないので,開発者にご連絡ください!",
"OpenSetupGuideMessage": "セットアップガイドを開く",
"NoUpdate": "アップデートなし",
"TitleUpdateVersionLabel": "バージョン {0} - {1}",
"RyujinxInfo": "Ryujinx - 情報",
"RyujinxConfirm": "Ryujinx - 確認",
"FileDialogAllTypes": "すべての種別",
"Never": "Never",
"SwkbdMinCharacters": "最低 {0} 文字必要です",
"SwkbdMinRangeCharacters": "{0}-{1} 文字にしてください",
"SoftwareKeyboard": "ソフトウェアキーボード",
"DialogControllerAppletMessagePlayerRange": "アプリケーションは {0} 名のプレイヤーを要求しています:\n\n種別: {1}\n\nプレイヤー: {2}\n\n{3}設定を開き各プレイヤーの入力設定を行ってから閉じるを押してください.",
"DialogControllerAppletMessage": "アプリケーションは {0} 名のプレイヤーを要求しています:\n\n種別: {1}\n\nプレイヤー: {2}\n\n{3}設定を開き各プレイヤーの入力設定を行ってから閉じるを押してください.",
"DialogControllerAppletDockModeSet": "ドッキングモードに設定されました. 携帯モードは無効になります.\n\n",
"UpdaterRenaming": "古いファイルをリネーム中...",
"UpdaterRenameFailed": "ファイルをリネームできませんでした: {0}",
"UpdaterAddingFiles": "新規ファイルを追加中...",
"UpdaterExtracting": "アップデートを展開中...",
"UpdaterDownloading": "アップデートをダウンロード中...",
"Game": "ゲーム",
"Docked": "ドッキング",
"Handheld": "携帯",
"ConnectionError": "接続エラー.",
"AboutPageDeveloperListMore": "{0}, その他大勢...",
"ApiError": "API エラー.",
"LoadingHeading": "ロード中: {0}",
"CompilingPPTC": "PTC をコンパイル中",
"CompilingShaders": "シェーダをコンパイル中",
"AllKeyboards": "すべてのキーボード",
"OpenFileDialogTitle": "開くファイルを選択",
"OpenFolderDialogTitle": "展開されたゲームフォルダを選択",
"AllSupportedFormats": "すべての対応フォーマット",
"RyujinxUpdater": "Ryujinx アップデータ",
"SettingsTabHotkeys": "キーボード ホットキー",
"SettingsTabHotkeysHotkeys": "キーボード ホットキー",
"SettingsTabHotkeysToggleVsyncHotkey": "VSync 切り替え:",
"SettingsTabHotkeysScreenshotHotkey": "スクリーンショット:",
"SettingsTabHotkeysShowUiHotkey": "UI表示:",
"SettingsTabHotkeysPauseHotkey": "中断:",
"SettingsTabHotkeysToggleMuteHotkey": "ミュート:",
"ControllerMotionTitle": "モーションコントロール設定",
"ControllerRumbleTitle": "振動設定",
"SettingsSelectThemeFileDialogTitle": "テーマファイルを選択",
"SettingsXamlThemeFile": "Xaml テーマファイル",
"AvatarWindowTitle": "アカウント - アバター管理",
"Amiibo": "Amiibo",
"Unknown": "不明",
"Usage": "使用法",
"Writable": "書き込み可能",
"SelectDlcDialogTitle": "DLC ファイルを選択",
"SelectUpdateDialogTitle": "アップデートファイルを選択",
"UserProfileWindowTitle": "ユーザプロファイルを管理",
"CheatWindowTitle": "チート管理",
"DlcWindowTitle": "DLC 管理",
"UpdateWindowTitle": "アップデート管理",
"CheatWindowHeading": "利用可能なチート {0} [{1}]",
"DlcWindowHeading": "利用可能な DLC {0} [{1}]",
"UserProfilesEditProfile": "編集",
"Cancel": "キャンセル",
"Save": "セーブ",
"Discard": "破棄",
"UserProfilesSetProfileImage": "プロファイル画像を設定",
"UserProfileEmptyNameError": "名称が必要です",
"UserProfileNoImageError": "プロファイル画像が必要です",
"GameUpdateWindowHeading": "利用可能なアップデート {0} [{1}]",
"SettingsTabHotkeysResScaleUpHotkey": "解像度を上げる:",
"SettingsTabHotkeysResScaleDownHotkey": "解像度を下げる:",
"UserProfilesName": "名称:",
"UserProfilesUserId": "ユーザID:",
"SettingsTabGraphicsBackend": "グラフィックスバックエンド",
"SettingsTabGraphicsBackendTooltip": "使用するグラフィックスバックエンドです",
"SettingsEnableTextureRecompression": "テクスチャの再圧縮を有効",
"SettingsEnableTextureRecompressionTooltip": "VRAMの使用量を削減するためテクスチャを圧縮します.\n\nGPUのVRAMが4GiB未満の場合は使用を推奨します.\n\nよくわからない場合はオフのままにしてください.",
"SettingsTabGraphicsPreferredGpu": "優先使用するGPU",
"SettingsTabGraphicsPreferredGpuTooltip": "Vulkanグラフィックスバックエンドで使用されるグラフィックスカードを選択します.\n\nOpenGLが使用するGPUには影響しません.\n\n不明な場合は, \"dGPU\" としてフラグが立っているGPUに設定します. ない場合はそのままにします.",
"SettingsAppRequiredRestartMessage": "Ryujinx の再起動が必要です",
"SettingsGpuBackendRestartMessage": "グラフィックスバックエンドまたはGPUの設定が変更されました. 変更を適用するには再起動する必要があります",
"SettingsGpuBackendRestartSubMessage": "今すぐ再起動しますか?",
"RyujinxUpdaterMessage": "Ryujinx を最新版にアップデートしますか?",
"SettingsTabHotkeysVolumeUpHotkey": "音量を上げる:",
"SettingsTabHotkeysVolumeDownHotkey": "音量を下げる:",
"SettingsEnableMacroHLE": "マクロの高レベルエミュレーション (HLE) を有効",
"SettingsEnableMacroHLETooltip": "GPU マクロコードの高レベルエミュレーションです.\n\nパフォーマンスを向上させますが, 一部のゲームでグラフィックに不具合が発生する可能性があります.\n\nよくわからない場合はオンのままにしてください.",
"VolumeShort": "音量",
"UserProfilesManageSaves": "セーブデータの管理",
"DeleteUserSave": "このゲームのユーザセーブデータを削除しますか?",
"IrreversibleActionNote": "この操作は元に戻せません.",
"SaveManagerHeading": "{0} のセーブデータを管理",
"SaveManagerTitle": "セーブデータマネージャ",
"Name": "名称",
"Size": "サイズ",
"Search": "検索",
"UserProfilesRecoverLostAccounts": "アカウントの復旧",
"Recover": "復旧",
"UserProfilesRecoverHeading": "以下のアカウントのセーブデータが見つかりました"
}

View File

@@ -1,613 +0,0 @@
{
"MenuBarFileOpenApplet": "애플릿 열기",
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "독립 실행형 모드에서 Mii 편집기 애플릿 열기",
"SettingsTabInputDirectMouseAccess": "직접 마우스 접속",
"SettingsTabSystemMemoryManagerMode": "메모리 관리자 모드 :",
"SettingsTabSystemMemoryManagerModeSoftware": "소프트웨어",
"SettingsTabSystemMemoryManagerModeHost": "호스트 (빠름)",
"SettingsTabSystemMemoryManagerModeHostUnchecked": "호스트가 확인되지 않음 (가장 빠르나 안전하지 않음)",
"MenuBarFile": "_파일",
"MenuBarFileOpenFromFile": "_파일에서 응용 프로그램 불러오기",
"MenuBarFileOpenUnpacked": "_압축을 푼 게임 불러오기",
"MenuBarFileOpenEmuFolder": "Ryujinx 폴더 열기",
"MenuBarFileOpenLogsFolder": "로그 폴더 열기",
"MenuBarFileExit": "_종료",
"MenuBarOptions": "옵션",
"MenuBarOptionsToggleFullscreen": "전체화면 전환",
"MenuBarOptionsStartGamesInFullscreen": "전체 화면 모드에서 게임 시작",
"MenuBarOptionsStopEmulation": "에뮬레이션 중지",
"MenuBarOptionsSettings": "_설정",
"MenuBarOptionsManageUserProfiles": "_사용자 프로파일 관리\n",
"MenuBarActions": "_동작",
"MenuBarOptionsSimulateWakeUpMessage": "모닝콜 메세지 시뮬레이션\n",
"MenuBarActionsScanAmiibo": "Amiibo 스캔",
"MenuBarTools": "_도구",
"MenuBarToolsInstallFirmware": "펌웨어 설치",
"MenuBarFileToolsInstallFirmwareFromFile": "XCI 또는 ZIP에서 펌웨어 설치",
"MenuBarFileToolsInstallFirmwareFromDirectory": "디렉토리에서 펌웨어 설치",
"MenuBarHelp": "도움",
"MenuBarHelpCheckForUpdates": "업데이트 확인",
"MenuBarHelpAbout": "정보",
"MenuSearch": "검색...",
"GameListHeaderFavorite": "즐겨찾기",
"GameListHeaderIcon": "아이콘",
"GameListHeaderApplication": "이름",
"GameListHeaderDeveloper": "개발자",
"GameListHeaderVersion": "버전",
"GameListHeaderTimePlayed": "플레이 시간",
"GameListHeaderLastPlayed": "마지막 플레이",
"GameListHeaderFileExtension": "파일 확장자",
"GameListHeaderFileSize": "파일 크기",
"GameListHeaderPath": "경로",
"GameListContextMenuOpenUserSaveDirectory": "사용자 저장 디렉토리 열기\n",
"GameListContextMenuOpenUserSaveDirectoryToolTip": "응용 프로그램의 사용자 저장이 포함된 디렉토리 열기\n",
"GameListContextMenuOpenUserDeviceDirectory": "사용자 장치 디렉토리 열기",
"GameListContextMenuOpenUserDeviceDirectoryToolTip": "응용 프로그램의 장치 저장이 포함된 디렉토리 열기\n",
"GameListContextMenuOpenUserBcatDirectory": "사용자의 BCAT 디렉토리 열기\n",
"GameListContextMenuOpenUserBcatDirectoryToolTip": "응용 프로그램의 BCAT 저장이 포함된 디렉토리 열기\n",
"GameListContextMenuManageTitleUpdates": "타이틀 업데이트 관리\n",
"GameListContextMenuManageTitleUpdatesToolTip": "타이틀 업데이트 관리 창 열기",
"GameListContextMenuManageDlc": "DLC 관리",
"GameListContextMenuManageDlcToolTip": "DLC 관리 창 열기",
"GameListContextMenuOpenModsDirectory": "Mod 디렉토리 열기",
"GameListContextMenuOpenModsDirectoryToolTip": "응용 프로그램의 Mod들이 포함된 디렉터리 열기",
"GameListContextMenuCacheManagement": "캐시 관리",
"GameListContextMenuCacheManagementPurgePptc": "대기열 PPTC 재구성",
"GameListContextMenuCacheManagementPurgePptcToolTip": "다음 게임 시작 시 부팅 시 PPTC가 다시 빌드되도록 트리거\n",
"GameListContextMenuCacheManagementPurgeShaderCache": "셰이더 캐시 제거",
"GameListContextMenuCacheManagementPurgeShaderCacheToolTip": "응용 프로그램 셰이더 캐시 삭제\n",
"GameListContextMenuCacheManagementOpenPptcDirectory": "PPTC 디렉토리 열기",
"GameListContextMenuCacheManagementOpenPptcDirectoryToolTip": "응용 프로그램 PPTC 캐시가 포함된 디렉터리 열기\n",
"GameListContextMenuCacheManagementOpenShaderCacheDirectory": "셰이더 캐시 디렉토리 열기",
"GameListContextMenuCacheManagementOpenShaderCacheDirectoryToolTip": "응용 프로그램 셰이더 캐시가 포함된 디렉터리 열기\n",
"GameListContextMenuExtractData": "데이터 추출",
"GameListContextMenuExtractDataExeFS": "ExeFS",
"GameListContextMenuExtractDataExeFSToolTip": "애플리케이션의 현재 구성에서 ExeFS 추출 (업데이트 포함)",
"GameListContextMenuExtractDataRomFS": "RomFS",
"GameListContextMenuExtractDataRomFSToolTip": "응용 프로그램의 현재 구성에서 RomFS 추출 (업데이트 포함)\n",
"GameListContextMenuExtractDataLogo": "로고",
"GameListContextMenuExtractDataLogoToolTip": "응용 프로그램의 현재 구성에서 로고 섹션 추출 (업데이트 포함)\n",
"StatusBarGamesLoaded": "불러온 {0}/{1} 개의 게임",
"StatusBarSystemVersion": "시스템 버전 : {0}",
"Settings": "설정",
"SettingsTabGeneral": "사용자 인터페이스",
"SettingsTabGeneralGeneral": "일반",
"SettingsTabGeneralEnableDiscordRichPresence": "디스코드 활동 상태 활성화\n",
"SettingsTabGeneralCheckUpdatesOnLaunch": "실행 시 업데이트 확인\n",
"SettingsTabGeneralShowConfirmExitDialog": "\"종료 확인\" 대화 상자 표시",
"SettingsTabGeneralHideCursorOnIdle": "유휴 상태에서 커서 숨기기",
"SettingsTabGeneralGameDirectories": "게임 디렉토리",
"SettingsTabGeneralAdd": "추가",
"SettingsTabGeneralRemove": "제거",
"SettingsTabSystem": "시스템",
"SettingsTabSystemCore": "코어",
"SettingsTabSystemSystemRegion": "시스템 지역 :",
"SettingsTabSystemSystemRegionJapan": "일본",
"SettingsTabSystemSystemRegionUSA": "미국",
"SettingsTabSystemSystemRegionEurope": "유럽",
"SettingsTabSystemSystemRegionAustralia": "호주",
"SettingsTabSystemSystemRegionChina": "중국",
"SettingsTabSystemSystemRegionKorea": "한국",
"SettingsTabSystemSystemRegionTaiwan": "대만",
"SettingsTabSystemSystemLanguage": "시스템 언어 :",
"SettingsTabSystemSystemLanguageJapanese": "일본어",
"SettingsTabSystemSystemLanguageAmericanEnglish": "영어(미국)",
"SettingsTabSystemSystemLanguageFrench": "프랑스어",
"SettingsTabSystemSystemLanguageGerman": "독일어",
"SettingsTabSystemSystemLanguageItalian": "이탈리아어",
"SettingsTabSystemSystemLanguageSpanish": "스페인어",
"SettingsTabSystemSystemLanguageChinese": "중국어",
"SettingsTabSystemSystemLanguageKorean": "한국어",
"SettingsTabSystemSystemLanguageDutch": "네덜란드어",
"SettingsTabSystemSystemLanguagePortuguese": "포르투갈어",
"SettingsTabSystemSystemLanguageRussian": "러시아어",
"SettingsTabSystemSystemLanguageTaiwanese": "대만어",
"SettingsTabSystemSystemLanguageBritishEnglish": "영어 (영국)",
"SettingsTabSystemSystemLanguageCanadianFrench": "프랑스어 (캐나다)",
"SettingsTabSystemSystemLanguageLatinAmericanSpanish": "스페인어 (라틴 아메리카)",
"SettingsTabSystemSystemLanguageSimplifiedChinese": "중국어 간체",
"SettingsTabSystemSystemLanguageTraditionalChinese": "중국어 번체",
"SettingsTabSystemSystemTimeZone": "시스템 시간대 :",
"SettingsTabSystemSystemTime": "시스템 시간 :",
"SettingsTabSystemEnableVsync": "수직 동기화",
"SettingsTabSystemEnablePptc": "PPTC (프로파일된 영구 번역 캐시) 활성화",
"SettingsTabSystemEnableFsIntegrityChecks": "FS 무결성 검사",
"SettingsTabSystemAudioBackend": "오디오 백엔드:",
"SettingsTabSystemAudioBackendDummy": "더미",
"SettingsTabSystemAudioBackendOpenAL": "OpenAL",
"SettingsTabSystemAudioBackendSoundIO": "사운드IO",
"SettingsTabSystemAudioBackendSDL2": "SDL2",
"SettingsTabSystemHacks": "해킹",
"SettingsTabSystemHacksNote": " (불안정을 일으킬 수 있음)",
"SettingsTabSystemExpandDramSize": "대체 메모리 레이아웃 사용 (개발자)\n",
"SettingsTabSystemIgnoreMissingServices": "누락된 서비스 무시",
"SettingsTabGraphics": "그래픽",
"SettingsTabGraphicsAPI": "그래픽 API",
"SettingsTabGraphicsEnableShaderCache": "셰이더 캐시 활성화",
"SettingsTabGraphicsAnisotropicFiltering": "이방성 필터링:",
"SettingsTabGraphicsAnisotropicFilteringAuto": "자동",
"SettingsTabGraphicsAnisotropicFiltering2x": "2 배",
"SettingsTabGraphicsAnisotropicFiltering4x": "4 배",
"SettingsTabGraphicsAnisotropicFiltering8x": "8 배",
"SettingsTabGraphicsAnisotropicFiltering16x": "16 배",
"SettingsTabGraphicsResolutionScale": "해상도 스케일:",
"SettingsTabGraphicsResolutionScaleCustom": "사용자 지정 (권장하지 않음)",
"SettingsTabGraphicsResolutionScaleNative": "기본 (720p/1080p)",
"SettingsTabGraphicsResolutionScale2x": "2 배 (1440p/2160p)",
"SettingsTabGraphicsResolutionScale3x": "3 배 (2160p/3240p)",
"SettingsTabGraphicsResolutionScale4x": "4 배 (2880p/4320p)",
"SettingsTabGraphicsAspectRatio": "화면비:",
"SettingsTabGraphicsAspectRatio4x3": "4:3",
"SettingsTabGraphicsAspectRatio16x9": "16:9",
"SettingsTabGraphicsAspectRatio16x10": "16:10",
"SettingsTabGraphicsAspectRatio21x9": "21:9",
"SettingsTabGraphicsAspectRatio32x9": "32:9",
"SettingsTabGraphicsAspectRatioStretch": "창에 맞게 늘리기",
"SettingsTabGraphicsDeveloperOptions": "개발자 옵션",
"SettingsTabGraphicsShaderDumpPath": "그래픽 쉐이더 덤프 경로:",
"SettingsTabLogging": "로깅",
"SettingsTabLoggingLogging": "로깅",
"SettingsTabLoggingEnableLoggingToFile": "파일에 로깅 활성화",
"SettingsTabLoggingEnableStubLogs": "스텁 로그 활성화",
"SettingsTabLoggingEnableInfoLogs": "정보 로그 활성화",
"SettingsTabLoggingEnableWarningLogs": "경고 로그 활성화",
"SettingsTabLoggingEnableErrorLogs": "오류 로그 활성화",
"SettingsTabLoggingEnableTraceLogs": "추적 로그 활성화",
"SettingsTabLoggingEnableGuestLogs": "게스트 로그 활성화",
"SettingsTabLoggingEnableFsAccessLogs": "Fs 접속 로그 활성화",
"SettingsTabLoggingFsGlobalAccessLogMode": "Fs 글로벌 접속 로그 모드:",
"SettingsTabLoggingDeveloperOptions": "개발자 옵션 (경고 : 성능이 저하됨)",
"SettingsTabLoggingGraphicsBackendLogLevel": "그래픽 백엔드 로그 수준:",
"SettingsTabLoggingGraphicsBackendLogLevelNone": "없음",
"SettingsTabLoggingGraphicsBackendLogLevelError": "오류",
"SettingsTabLoggingGraphicsBackendLogLevelPerformance": "감속",
"SettingsTabLoggingGraphicsBackendLogLevelAll": "모두",
"SettingsTabLoggingEnableDebugLogs": "디버그 로그 활성화",
"SettingsTabInput": "입력",
"SettingsTabInputEnableDockedMode": "도킹 모드",
"SettingsTabInputDirectKeyboardAccess": "직접 키보드 접속",
"SettingsButtonSave": "저장",
"SettingsButtonClose": "닫기",
"SettingsButtonOk": "확인",
"SettingsButtonCancel": "취소",
"SettingsButtonApply": "적용",
"ControllerSettingsPlayer": "플레이어",
"ControllerSettingsPlayer1": "플레이어 1",
"ControllerSettingsPlayer2": "플레이어 2",
"ControllerSettingsPlayer3": "플레이어 3",
"ControllerSettingsPlayer4": "플레이어 4",
"ControllerSettingsPlayer5": "플레이어 5",
"ControllerSettingsPlayer6": "플레이어 6",
"ControllerSettingsPlayer7": "플레이어 7",
"ControllerSettingsPlayer8": "플레이어 8",
"ControllerSettingsHandheld": "휴대용",
"ControllerSettingsInputDevice": "입력 장치",
"ControllerSettingsRefresh": "새로 고침",
"ControllerSettingsDeviceDisabled": "비활성화됨",
"ControllerSettingsControllerType": "컨트롤러 유형",
"ControllerSettingsControllerTypeHandheld": "휴대용",
"ControllerSettingsControllerTypeProController": "프로 컨트롤러",
"ControllerSettingsControllerTypeJoyConPair": "조이콘 페어링",
"ControllerSettingsControllerTypeJoyConLeft": "왼쪽 조이콘",
"ControllerSettingsControllerTypeJoyConRight": "오른쪽 조이콘",
"ControllerSettingsProfile": "프로파일",
"ControllerSettingsProfileDefault": "기본",
"ControllerSettingsLoad": "불러오기",
"ControllerSettingsAdd": "추가",
"ControllerSettingsRemove": "제거",
"ControllerSettingsButtons": "버튼",
"ControllerSettingsButtonA": "A 버튼",
"ControllerSettingsButtonB": "B 버튼",
"ControllerSettingsButtonX": "X 버튼",
"ControllerSettingsButtonY": "Y 버튼",
"ControllerSettingsButtonPlus": "+ 버튼",
"ControllerSettingsButtonMinus": "- 버튼",
"ControllerSettingsDPad": "방향 패드",
"ControllerSettingsDPadUp": "위쪽",
"ControllerSettingsDPadDown": "아래쪽",
"ControllerSettingsDPadLeft": "왼쪽",
"ControllerSettingsDPadRight": "오른쪽",
"ControllerSettingsLStick": "왼쪽 스틱",
"ControllerSettingsLStickButton": "버튼",
"ControllerSettingsLStickUp": "위쪽",
"ControllerSettingsLStickDown": "아래쪽",
"ControllerSettingsLStickLeft": "왼쪽",
"ControllerSettingsLStickRight": "오른쪽",
"ControllerSettingsLStickStick": "스틱",
"ControllerSettingsLStickInvertXAxis": "스틱 X 축 반전",
"ControllerSettingsLStickInvertYAxis": "스틱 Y 축 반전",
"ControllerSettingsLStickDeadzone": "데드존:",
"ControllerSettingsRStick": "오른쪽 스틱",
"ControllerSettingsRStickButton": "버튼",
"ControllerSettingsRStickUp": "위쪽",
"ControllerSettingsRStickDown": "아래쪽",
"ControllerSettingsRStickLeft": "왼쪽",
"ControllerSettingsRStickRight": "오른쪽",
"ControllerSettingsRStickStick": "스틱",
"ControllerSettingsRStickInvertXAxis": "스틱 X 축 반전",
"ControllerSettingsRStickInvertYAxis": "스틱 Y 축 반전",
"ControllerSettingsRStickDeadzone": "데드존:",
"ControllerSettingsTriggersLeft": "왼쪽 트리거",
"ControllerSettingsTriggersRight": "오른쪽 트리거",
"ControllerSettingsTriggersButtonsLeft": "왼쪽 트리거 버튼",
"ControllerSettingsTriggersButtonsRight": "오른쪽 트리거 버튼",
"ControllerSettingsTriggers": "트리거 버튼",
"ControllerSettingsTriggerL": "L 버튼",
"ControllerSettingsTriggerR": "R 버튼",
"ControllerSettingsTriggerZL": "ZL 버튼",
"ControllerSettingsTriggerZR": "ZR 버튼",
"ControllerSettingsLeftSL": "SL 버튼",
"ControllerSettingsLeftSR": "SR 버튼",
"ControllerSettingsRightSL": "SL 버튼",
"ControllerSettingsRightSR": "SR 버튼",
"ControllerSettingsExtraButtonsLeft": "왼쪽 버튼",
"ControllerSettingsExtraButtonsRight": "오른쪽 버튼",
"ControllerSettingsMisc": "기타",
"ControllerSettingsTriggerThreshold": "트리거 임계값 :",
"ControllerSettingsMotion": "동작",
"ControllerSettingsMotionUseCemuhookCompatibleMotion": "CemuHook 호환 모션 사용",
"ControllerSettingsMotionControllerSlot": "컨트롤러 슬롯:",
"ControllerSettingsMotionMirrorInput": "미러 입력",
"ControllerSettingsMotionRightJoyConSlot": "오른쪽 조이콘 슬롯 :",
"ControllerSettingsMotionServerHost": "서버 호스트:",
"ControllerSettingsMotionGyroSensitivity": "자이로 감도:",
"ControllerSettingsMotionGyroDeadzone": "자이로 데드존:",
"ControllerSettingsSave": "저장",
"ControllerSettingsClose": "닫기",
"UserProfilesSelectedUserProfile": "선택한 사용자 프로파일:",
"UserProfilesSaveProfileName": "프로파일 이름 저장",
"UserProfilesChangeProfileImage": "프로파일 이미지 변경",
"UserProfilesAvailableUserProfiles": "사용 가능한 사용자 프로파일:",
"UserProfilesAddNewProfile": "프로파일 생성",
"UserProfilesDeleteSelectedProfile": "선택한 프로파일 삭제",
"UserProfilesClose": "닫기",
"ProfileImageSelectionTitle": "프로파일 이미지 선택",
"ProfileImageSelectionHeader": "프로파일 이미지 선택",
"ProfileImageSelectionNote": "사용자 지정 프로파일 이미지를 가져오거나 시스템 펌웨어에서 아바타를 선택할 수 있음\n",
"ProfileImageSelectionImportImage": "이미지 파일 가져오기",
"ProfileImageSelectionSelectAvatar": "펌웨어 아바타 선택",
"InputDialogTitle": "입력 대화상자",
"InputDialogOk": "확인",
"InputDialogCancel": "취소",
"InputDialogAddNewProfileTitle": "프로파일 이름 선택",
"InputDialogAddNewProfileHeader": "프로파일 이름 입력",
"InputDialogAddNewProfileSubtext": "(최대 길이: {0})\n",
"AvatarChoose": "선택",
"AvatarSetBackgroundColor": "배경색 설정",
"AvatarClose": "닫기",
"ControllerSettingsLoadProfileToolTip": "프로파일 불러오기",
"ControllerSettingsAddProfileToolTip": "프로파일 추가",
"ControllerSettingsRemoveProfileToolTip": "프로파일 제거",
"ControllerSettingsSaveProfileToolTip": "프로파일 저장",
"MenuBarFileToolsTakeScreenshot": "스크린 샷 찍기",
"MenuBarFileToolsHideUi": "Hide UI",
"GameListContextMenuToggleFavorite": "즐겨찾기 전환",
"GameListContextMenuToggleFavoriteToolTip": "게임 즐겨찾기 상태 전환\n",
"SettingsTabGeneralTheme": "테마",
"SettingsTabGeneralThemeCustomTheme": "사용자 정의 테마 경로",
"SettingsTabGeneralThemeBaseStyle": "기본 스타일",
"SettingsTabGeneralThemeBaseStyleDark": "어두움",
"SettingsTabGeneralThemeBaseStyleLight": "밝음",
"SettingsTabGeneralThemeEnableCustomTheme": "사용자 정의 테마 활성화",
"ButtonBrowse": "찾아보기",
"ControllerSettingsConfigureGeneral": "구성",
"ControllerSettingsRumble": "진동",
"ControllerSettingsRumbleStrongMultiplier": "강력한 진동 증폭기",
"ControllerSettingsRumbleWeakMultiplier": "약한 진동 증폭기",
"DialogMessageSaveNotAvailableMessage": "{0} [{1:x16}]에 대한 저장 데이터가 없음\n",
"DialogMessageSaveNotAvailableCreateSaveMessage": "이 게임에 대한 저장 데이터를 생성하겠습니까?\n",
"DialogConfirmationTitle": "Ryujinx - 확인",
"DialogUpdaterTitle": "Ryujinx - 업데이터",
"DialogErrorTitle": "Ryujinx - 오류",
"DialogWarningTitle": "Ryujinx - 경고",
"DialogExitTitle": "Ryujinx - 종료",
"DialogErrorMessage": "Ryujinx 오류 발생",
"DialogExitMessage": "Ryujinx를 종료하겠습니까?",
"DialogExitSubMessage": "저장하지 않은 모든 데이터는 손실됩니다!",
"DialogMessageCreateSaveErrorMessage": "지정된 저장 데이터를 작성하는 중에 오류 발생: {0}\n",
"DialogMessageFindSaveErrorMessage": "지정된 저장 데이터를 찾는 중에 오류 발생: {0}\n",
"FolderDialogExtractTitle": "추출할 폴더 선택",
"DialogNcaExtractionMessage": "{1}에서 {0} 섹션을 추출하는 중...\n",
"DialogNcaExtractionTitle": "Ryujinx - NCA 섹션 추출기",
"DialogNcaExtractionMainNcaNotFoundErrorMessage": "추출 실패하였습니다. 선택한 파일에 기본 NCA가 없습니다.\n",
"DialogNcaExtractionCheckLogErrorMessage": "추출 실패하였습니다. 자세한 내용은 로그 파일을 읽으세요.\n",
"DialogNcaExtractionSuccessMessage": "추출이 성공적으로 완료되었습니다.",
"DialogUpdaterConvertFailedMessage": "현재 Ryujinx 버전을 변환하지 못했습니다.",
"DialogUpdaterCancelUpdateMessage": "업데이트 취소 중 입니다!",
"DialogUpdaterAlreadyOnLatestVersionMessage": "이미 최신 버전의 Ryujinx를 사용하고 있습니다!",
"DialogUpdaterFailedToGetVersionMessage": "GitHub 릴리스에서 릴리스 정보를 가져오는 중에 오류가 발생했습니다. 이는 GitHub Actions에서 새 릴리스를 컴파일하는 경우 발생할 수 있습니다. 몇 분 후에 다시 시도하세요.",
"DialogUpdaterConvertFailedGithubMessage": "Github 개정에서 받은 Ryujinx 버전을 변환하지 못했습니다.\n",
"DialogUpdaterDownloadingMessage": "업데이트 다운로드 중...\n",
"DialogUpdaterExtractionMessage": "업데이트 추출 중...\n",
"DialogUpdaterRenamingMessage": "업데이트 이름 바꾸는 중...\n",
"DialogUpdaterAddingFilesMessage": "새 업데이트 추가 중...\n",
"DialogUpdaterCompleteMessage": "업데이트 완료하였습니다!\n",
"DialogUpdaterRestartMessage": "지금 Ryujinx를 다시 시작하겠습니까?",
"DialogUpdaterArchNotSupportedMessage": "지원되는 시스템 아키텍처를 실행하고 있지 않습니다!",
"DialogUpdaterArchNotSupportedSubMessage": "(x64 시스템만 지원됩니다!)\n",
"DialogUpdaterNoInternetMessage": "인터넷에 연결되어 있지 않습니다!",
"DialogUpdaterNoInternetSubMessage": "인터넷 연결이 작동하는지 확인하세요!",
"DialogUpdaterDirtyBuildMessage": "Ryujinx의 나쁜 빌드는 업데이트할 수 없습니다!\n",
"DialogUpdaterDirtyBuildSubMessage": "지원되는 버전을 찾고 있다면 https://ryujinx.org/에서 Ryujinx를 다운로드하세요.",
"DialogRestartRequiredMessage": "재시작 필요",
"DialogThemeRestartMessage": "테마가 저장되었습니다. 테마를 적용하려면 다시 시작해야 합니다.",
"DialogThemeRestartSubMessage": "다시 시작하겠습니까?\n",
"DialogFirmwareInstallEmbeddedMessage": "이 게임에 내장된 펌웨어를 설치하겠습니까? (펌웨어 {0})",
"DialogFirmwareInstallEmbeddedSuccessMessage": "설치된 펌웨어가 없지만 Ryujinx가 제공된 게임에서 펌웨어 {0}을(를) 설치할 수 있었습니다.\\n이제 에뮬레이터가 시작됩니다.",
"DialogFirmwareNoFirmwareInstalledMessage": "설치된 펌웨어 없음",
"DialogFirmwareInstalledMessage": "펌웨어 {0}이(가) 설치됨",
"DialogOpenSettingsWindowLabel": "설정 창 열기",
"DialogControllerAppletTitle": "컨트롤러 애플릿",
"DialogMessageDialogErrorExceptionMessage": "메시지 대화상자를 표시하는 동안 오류 발생: {0}\n",
"DialogSoftwareKeyboardErrorExceptionMessage": "소프트웨어 키보드를 표시하는 동안 오류 발생: {0}",
"DialogErrorAppletErrorExceptionMessage": "오류에플릿 대화상자를 표시하는 동안 오류 발생: {0}",
"DialogUserErrorDialogMessage": "{0}: {1}",
"DialogUserErrorDialogInfoMessage": "\n이 오류를 수정하는 방법에 대한 자세한 내용은 설정 가이드를 따르세요.",
"DialogUserErrorDialogTitle": "Ryuijnx 오류 ({0})",
"DialogAmiiboApiTitle": "Amiibo API",
"DialogAmiiboApiFailFetchMessage": "API에서 정보를 가져오는 동안 오류가 발생했습니다.",
"DialogAmiiboApiConnectErrorMessage": "Amiibo API 서버에 연결할 수 없습니다. 서비스가 다운되었거나 인터넷 연결이 오프라인인지 확인해야 할 수 있습니다.",
"DialogProfileInvalidProfileErrorMessage": "{0} 프로파일은 현재 입력 구성 시스템과 호환되지 않습니다.",
"DialogProfileDefaultProfileOverwriteErrorMessage": "기본 프로파일을 덮어쓸 수 없음",
"DialogProfileDeleteProfileTitle": "프로파일 삭제",
"DialogProfileDeleteProfileMessage": "이 작업은 되돌릴 수 없습니다. 계속하겠습니까?",
"DialogWarning": "경고",
"DialogPPTCDeletionMessage": "다음에 부팅할 때 PPTC 재구축을 대기시키려고 합니다:\n\n{0}\n\n계속하겠습니까?",
"DialogPPTCDeletionErrorMessage": "{0}에서 PPTC 캐시 삭제 오류: {1}",
"DialogShaderDeletionMessage": "다음에 대한 셰이더 캐시를 삭제하려고 합니다:\n\n{0}\n\n계속하겠습니까?",
"DialogShaderDeletionErrorMessage": "{0}에서 셰이더 캐시 제거 오류: {1}",
"DialogRyujinxErrorMessage": "Ryujinx에 오류 발생",
"DialogInvalidTitleIdErrorMessage": "UI 오류: 선택한 게임에 유효한 타이틀 ID가 없음",
"DialogFirmwareInstallerFirmwareNotFoundErrorMessage": "{0}에서 유효한 시스템 펌웨어를 찾을 수 없습니다.",
"DialogFirmwareInstallerFirmwareInstallTitle": "펌웨어 {0} 설치",
"DialogFirmwareInstallerFirmwareInstallMessage": "시스템 버전 {0}이(가) 설치됩니다.",
"DialogFirmwareInstallerFirmwareInstallSubMessage": "\n\n이것은 현재 시스템 버전 {0}을(를) 대체합니다.",
"DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\n계속하겠습니까?",
"DialogFirmwareInstallerFirmwareInstallWaitMessage": "펌웨어 설치 중...",
"DialogFirmwareInstallerFirmwareInstallSuccessMessage": "시스템 버전 {0}이(가) 성공적으로 설치되었습니다.",
"DialogUserProfileDeletionWarningMessage": "선택한 프로파일이 삭제되면 사용 가능한 다른 프로파일이 없음",
"DialogUserProfileDeletionConfirmMessage": "선택한 프로파일을 삭제하겠습니까?",
"DialogControllerSettingsModifiedConfirmMessage": "현재 컨트롤러 설정이 업데이트되었습니다.",
"DialogControllerSettingsModifiedConfirmSubMessage": "저장하겠습니까?",
"DialogDlcLoadNcaErrorMessage": "{0}입니다. 오류 발생 파일: {1}",
"DialogDlcNoDlcErrorMessage": "지정된 파일에 선택한 타이틀에 대한 DLC가 포함되어 있지 않습니다!",
"DialogPerformanceCheckLoggingEnabledMessage": "개발자만 사용하도록 설계된 추적 로깅이 활성화되어 있습니다.",
"DialogPerformanceCheckLoggingEnabledConfirmMessage": "최적의 성능을 위해 추적 로깅을 비활성화하는 것이 좋습니다. 지금 추적 로깅을 비활성화하겠습니까?",
"DialogPerformanceCheckShaderDumpEnabledMessage": "개발자만 사용하도록 설계된 셰이더 덤프를 활성화했습니다.",
"DialogPerformanceCheckShaderDumpEnabledConfirmMessage": "최적의 성능을 위해 세이더 덤핑을 비활성화하는 것이 좋습니다. 지금 세이더 덤핑을 비활성화하겠습니까?",
"DialogLoadAppGameAlreadyLoadedMessage": "게임을 이미 불러 왔습니다.",
"DialogLoadAppGameAlreadyLoadedSubMessage": "다른 게임을 시작하기 전에 에뮬레이션을 중지하거나 에뮬레이터를 닫으세요.",
"DialogUpdateAddUpdateErrorMessage": "지정된 파일에 선택한 제목에 대한 업데이트가 포함되어 있지 않습니다!",
"DialogSettingsBackendThreadingWarningTitle": "경고 - 백엔드 스레딩",
"DialogSettingsBackendThreadingWarningMessage": "변경 사항을 완전히 적용하려면 이 옵션을 변경한 후 Ryujinx를 다시 시작해야 합니다. 플랫폼에 따라 Ryujinx를 사용할 때 드라이버 자체의 멀티스레딩을 수동으로 비활성화해야 할 수도 있습니다.",
"SettingsTabGraphicsFeaturesOptions": "기능",
"SettingsTabGraphicsBackendMultithreading": "그래픽 백엔드 멀티스레딩:",
"CommonAuto": "자동",
"CommonOff": "끔",
"CommonOn": "켬",
"InputDialogYes": "네",
"InputDialogNo": "아니오",
"DialogProfileInvalidProfileNameErrorMessage": "파일 이름에 잘못된 문자가 포함되어 있습니다. 다시 시도하세요.",
"MenuBarOptionsPauseEmulation": "일시 정지",
"MenuBarOptionsResumeEmulation": "다시 시작",
"AboutUrlTooltipMessage": "기본 브라우저에서 Ryujinx 웹사이트를 열려면 클릭하세요.",
"AboutDisclaimerMessage": "Ryujinx는 닌텐도™,\n또는 그 파트너와 제휴하지 않습니다.",
"AboutAmiiboDisclaimerMessage": "AmiiboAPI (www.amiiboapi.com)는\nAmiibo 에뮬레이션에 사용됩니다.",
"AboutPatreonUrlTooltipMessage": "기본 브라우저에서 Ryujinx Patreon 페이지를 열려면 클릭하세요.",
"AboutGithubUrlTooltipMessage": "기본 브라우저에서 Ryujinx GitHub 페이지를 열려면 클릭하세요.",
"AboutDiscordUrlTooltipMessage": "기본 브라우저에서 Ryujinx 디스코드 서버에 대한 초대를 열려면 클릭하세요.",
"AboutTwitterUrlTooltipMessage": "기본 브라우저에서 Ryujinx 트위터 페이지를 열려면 클릭하세요.",
"AboutRyujinxAboutTitle": "정보:",
"AboutRyujinxAboutContent": "Ryujinx는 닌텐도 스위치™용 에뮬레이터입니다.\nPatreon에서 지원해 주세요.\n모든 최신 뉴스는 트위터 또는 디스코드에서 확인하세요.\n기여에 관심이 있는 개발자는 GitHub 또는 디스코드에서 자세한 내용을 확인할 수 있습니다",
"AboutRyujinxMaintainersTitle": "유지 관리:",
"AboutRyujinxMaintainersContentTooltipMessage": "기본 브라우저에서 기여자 페이지를 열려면 클릭하세요.",
"AboutRyujinxSupprtersTitle": "Patreon에서 후원:",
"AmiiboSeriesLabel": "Amiibo 시리즈",
"AmiiboCharacterLabel": "캐릭터",
"AmiiboScanButtonLabel": "스캔",
"AmiiboOptionsShowAllLabel": "모든 Amiibo 표시",
"AmiiboOptionsUsRandomTagLabel": "해킹: 임의의 태그 UUID 사용",
"DlcManagerTableHeadingEnabledLabel": "활성화됨",
"DlcManagerTableHeadingTitleIdLabel": "타이틀 ID",
"DlcManagerTableHeadingContainerPathLabel": "컨테이너 경로",
"DlcManagerTableHeadingFullPathLabel": "전체 경로",
"DlcManagerRemoveAllButton": "모두 제거",
"DlcManagerEnableAllButton": "모두 활성화",
"DlcManagerDisableAllButton": "모두 비활성화",
"MenuBarOptionsChangeLanguage": "언어 변경",
"CommonSort": "정렬",
"CommonShowNames": "이름 표시",
"CommonFavorite": "즐겨찾기",
"OrderAscending": "오름차순",
"OrderDescending": "내림차순",
"SettingsTabGraphicsFeatures": "기능ㆍ개선 사항",
"ErrorWindowTitle": "오류 창",
"ToggleDiscordTooltip": "\"현재 재생 중인\" 디스코드 활동에 Ryujinx를 표시할지 여부 선택",
"AddGameDirBoxTooltip": "목록에 추가할 게임 디렉토리 입력",
"AddGameDirTooltip": "목록에 게임 디렉토리 추가",
"RemoveGameDirTooltip": "선택한 게임 디렉토리 제거",
"CustomThemeCheckTooltip": "GUI에 사용자 지정 Avalonia 테마를 사용하여 에뮬레이터 메뉴의 모양 변경",
"CustomThemePathTooltip": "사용자 정의 GUI 테마 경로",
"CustomThemeBrowseTooltip": "사용자 정의 GUI 테마 찾아보기",
"DockModeToggleTooltip": "도킹 모드에서는 에뮬레이트된 시스템이 도킹된 닌텐도 스위치처럼 작동합니다. 이것은 대부분의 게임에서 그래픽 충실도를 향상시킵니다. 반대로 이 기능을 비활성화하면 에뮬레이트된 시스템이 휴대용 닌텐도 스위치처럼 작동하여 그래픽 품질이 저하됩니다.\n\n도킹 모드를 사용하려는 경우 플레이어 1 컨트롤을 구성하세요. 휴대용 모드를 사용하려는 경우 휴대용 컨트롤을 구성합니다.\n\n확실하지 않으면 켜 두세요.",
"DirectKeyboardTooltip": "직접 키보드 접속 (HID) 지원합니다. 텍스트 입력 장치로 키보드에 대한 게임 접속을 제공합니다.",
"DirectMouseTooltip": "직접 마우스 접속 (HID) 지원합니다. 포인팅 장치로 마우스에 대한 게임 접속을 제공합니다.",
"RegionTooltip": "시스템 지역 변경",
"LanguageTooltip": "시스템 언어 변경",
"TimezoneTooltip": "시스템 시간대 변경",
"TimeTooltip": "시스템 시간 변경",
"VSyncToggleTooltip": "에뮬레이트된 콘솔의 수직 동기화입니다. 기본적으로 대부분의 게임에 대한 프레임 제한 장치입니다. 비활성화하면 게임이 더 빠른 속도로 실행되거나 로딩 화면이 더 오래 걸리거나 멈출 수 있습니다.\n\n게임 내에서 선호하는 핫키로 전환할 수 있습니다. 비활성화할 계획이라면 이 작업을 수행하는 것이 좋습니다.\n\n확실하지 않으면 켜 두세요.",
"PptcToggleTooltip": "게임이 불러올 때마다 번역할 필요가 없도록 번역된 JIT 기능을 저장합니다.\n\n게임을 처음 부팅한 후 끊김 현상을 줄이고 부팅 시간을 크게 단축합니다.\n\n확실하지 않으면 켜 두세요.",
"FsIntegrityToggleTooltip": "게임을 부팅할 때 손상된 파일을 확인하고 손상된 파일이 감지되면 로그에 해시 오류를 표시합니다.\n\n성능에 영향을 미치지 않으며 문제 해결에 도움이 됩니다.\n\n확실하지 않으면 켜 두세요.",
"AudioBackendTooltip": "오디오를 렌더링하는 데 사용되는 백엔드를 변경합니다.\n\nSDL2가 선호되는 반면 OpenAL 및 사운드IO는 폴백으로 사용됩니다. 더미는 소리가 나지 않습니다.\n\n확실하지 않으면 SDL2로 설정하세요.",
"MemoryManagerTooltip": "게스트 메모리가 매핑되고 접속되는 방식을 변경합니다. 에뮬레이트된 CPU 성능에 크게 영향을 미칩니다.\n\n확실하지 않은 경우 호스트 확인 안함으로 설정하십시오.",
"MemoryManagerSoftwareTooltip": "주소 변환을 위해 소프트웨어 페이지 테이블을 사용하세요. 정확도는 가장 높지만 성능은 가장 느립니다.",
"MemoryManagerHostTooltip": "호스트 주소 공간의 메모리를 직접 매핑합니다. 훨씬 빠른 JIT 컴파일 및 실행합니다.",
"MemoryManagerUnsafeTooltip": "메모리를 직접 매핑하지만 접속하기 전에 게스트 주소 공간 내의 주소를 마스킹하지 마십시오. 더 빠르지만 안전을 희생해야 합니다. 게스트 응용 프로그램은 Ryujinx의 어디에서나 메모리에 접속할 수 있으므로 이 모드에서는 신뢰할 수 있는 프로그램만 실행하세요.",
"DRamTooltip": "대체 메모리모드 레이아웃을 활용하여 스위치 개발 모델을 모방합니다.\n\n고해상도 텍스처 팩 또는 4k 해상도 모드에만 유용합니다. 성능을 향상시키지 않습니다.\n\n확실하지 않으면 꺼 두세요.",
"IgnoreMissingServicesTooltip": "구현되지 않은 호라이즌 OS 서비스를 무시합니다. 이것은 특정 게임을 부팅할 때 충돌을 우회하는 데 도움이 될 수 있습니다.\n\n확실하지 않으면 꺼 두세요.",
"GraphicsBackendThreadingTooltip": "두 번째 스레드에서 그래픽 백엔드 명령을 실행합니다.\n\n세이더 컴파일 속도를 높이고 끊김 현상을 줄이며 자체 멀티스레딩 지원 없이 GPU 드라이버의 성능을 향상시킵니다. 멀티스레딩이 있는 드라이버에서 성능이 약간 향상되었습니다.\n\n잘 모르겠으면 자동으로 설정하세요.",
"GalThreadingTooltip": "두 번째 스레드에서 그래픽 백엔드 명령을 실행합니다.\n\n세이더 컴파일 속도를 높이고 끊김 현상을 줄이며 자체 멀티스레딩 지원 없이 GPU 드라이버의 성능을 향상시킵니다. 멀티스레딩이 있는 드라이버에서 성능이 약간 향상되었습니다.\n\n잘 모르겠으면 자동으로 설정하세요.",
"ShaderCacheToggleTooltip": "후속 실행에서 끊김 현상을 줄이는 디스크 세이더 캐시를 저장합니다.\n\n확실하지 않으면 켜 두세요.",
"ResolutionScaleTooltip": "적용 가능한 렌더 타겟에 적용된 해상도 스케일",
"ResolutionScaleEntryTooltip": "1.5와 같은 부동 소수점 분해능 스케일입니다. 비통합 척도는 문제나 충돌을 일으킬 가능성이 더 큽니다.",
"AnisotropyTooltip": "이방성 필터링 수준 (게임에서 요청한 값을 사용하려면 자동으로 설정)",
"AspectRatioTooltip": "렌더러 창에 적용된 화면비입니다.",
"ShaderDumpPathTooltip": "그래픽 셰이더 덤프 경로",
"FileLogTooltip": "디스크의 로그 파일에 콘솔 로깅을 저장합니다. 성능에 영향을 미치지 않습니다.",
"StubLogTooltip": "콘솔에 스텁 로그 메시지를 인쇄합니다. 성능에 영향을 미치지 않습니다.",
"InfoLogTooltip": "콘솔에 정보 로그 메시지를 인쇄합니다. 성능에 영향을 미치지 않습니다.",
"WarnLogTooltip": "콘솔에 경고 로그 메시지를 인쇄합니다. 성능에 영향을 미치지 않습니다.",
"ErrorLogTooltip": "콘솔에 오류 로그 메시지를 인쇄합니다. 성능에 영향을 미치지 않습니다.",
"TraceLogTooltip": "콘솔에 추적 로그 메시지를 인쇄합니다. 성능에 영향을 미치지 않습니다.",
"GuestLogTooltip": "콘솔에 게스트 로그 메시지를 인쇄합니다. 성능에 영향을 미치지 않습니다.",
"FileAccessLogTooltip": "콘솔에 파일 액세스 로그 메시지를 인쇄합니다.",
"FSAccessLogModeTooltip": "콘솔에 대한 FS 접속 로그 출력을 활성화합니다. 가능한 모드는 0-3\t\t\t\t",
"DeveloperOptionTooltip": "주의해서 사용",
"OpenGlLogLevel": "적절한 로그 수준을 활성화해야 함",
"DebugLogTooltip": "콘솔에 디버그 로그 메시지를 인쇄합니다.\n\n로그를 읽기 어렵게 만들고 에뮬레이터 성능을 악화시키므로 직원이 구체적으로 지시한 경우에만 사용하세요.",
"LoadApplicationFileTooltip": "파일 탐색기를 열어 불러올 스위치 호환 파일 선택",
"LoadApplicationFolderTooltip": "파일 탐색기를 열어 불러올 스위치 호환 압축 해제 애플리케이션 선택",
"OpenRyujinxFolderTooltip": "Ryujinx 파일 시스템 폴더 열기",
"OpenRyujinxLogsTooltip": "로그가 기록된 폴더 열기",
"ExitTooltip": "Ryujinx 종료",
"OpenSettingsTooltip": "설정 창 열기",
"OpenProfileManagerTooltip": "사용자 프로파일 관리자 창 열기",
"StopEmulationTooltip": "현재 게임의 에뮬레이션을 중지하고 게임 선택으로 돌아감",
"CheckUpdatesTooltip": "Ryujinx 업데이트 확인",
"OpenAboutTooltip": "정보 창 열기",
"GridSize": "격자 크기",
"GridSizeTooltip": "격자 항목의 크기 변경\n",
"SettingsTabSystemSystemLanguageBrazilianPortuguese": "포르투갈어 (브라질)",
"AboutRyujinxContributorsButtonHeader": "모든 기여자 보기",
"SettingsTabSystemAudioVolume": "볼륨 : ",
"AudioVolumeTooltip": "오디오 볼륨 변경",
"SettingsTabSystemEnableInternetAccess": "게스트 인터넷 접속/LAN 모드",
"EnableInternetAccessTooltip": "에뮬레이션된 애플리케이션이 인터넷에 연결되도록 허용합니다.\n\nLAN 모드가 있는 게임은 이 모드가 활성화되고 시스템이 동일한 접속 포인트에 연결된 경우 서로 연결할 수 있습니다. 여기에는 실제 콘솔도 포함됩니다.\n\n닌텐도 서버에 연결할 수 없습니다. 인터넷에 연결을 시도하는 특정 게임에서 충돌이 발생할 수 있습니다.\n\n확실하지 않으면 꺼두세요.",
"GameListContextMenuManageCheatToolTip": "치트 관리",
"GameListContextMenuManageCheat": "치트 관리",
"ControllerSettingsStickRange": "범위:",
"DialogStopEmulationTitle": "Ryujinx - 에뮬레이션 중지",
"DialogStopEmulationMessage": "에뮬레이션을 중지하겠습니까?",
"SettingsTabCpu": "CPU",
"SettingsTabAudio": "오디오",
"SettingsTabNetwork": "네트워크",
"SettingsTabNetworkConnection": "네트워크 연결",
"SettingsTabCpuCache": "CPU 캐시",
"SettingsTabCpuMemory": "CPU 메모리",
"DialogUpdaterFlatpakNotSupportedMessage": "FlatHub를 통해 Ryujinx를 업데이트하세요.",
"UpdaterDisabledWarningTitle": "업데이터 비활성화입니다!",
"GameListContextMenuOpenSdModsDirectory": "엣모스피어 Mod 디렉토리 열기",
"GameListContextMenuOpenSdModsDirectoryToolTip": "응용 프로그램의 모드가 포함된 대체 SD 카드 Atmosphere 디렉토리를 엽니다. 실제 하드웨어용으로 패키징된 모드에 유용합니다.\n",
"ControllerSettingsRotate90": "시계 방향으로 90° 회전",
"IconSize": "아이콘 크기",
"IconSizeTooltip": "게임 아이콘 크기 변경",
"MenuBarOptionsShowConsole": "콘솔 표시",
"ShaderCachePurgeError": "{0}에서 셰이더 캐시를 제거하는 중 오류 발생: {1}",
"UserErrorNoKeys": "키를 찾을 수 없음",
"UserErrorNoFirmware": "펌웨어를 찾을 수 없음",
"UserErrorFirmwareParsingFailed": "펌웨어 구문 분석 오류",
"UserErrorApplicationNotFound": "응용 프로그램을 찾을 수 없음",
"UserErrorUnknown": "알 수 없는 오류",
"UserErrorUndefined": "정의되지 않은 오류",
"UserErrorNoKeysDescription": "Ryujinx가 'prod.keys' 파일을 찾을 수 없음",
"UserErrorNoFirmwareDescription": "Ryujinx가 설치된 펌웨어를 찾을 수 없음",
"UserErrorFirmwareParsingFailedDescription": "Ryujinx가 제공된 펌웨어를 구문 분석할 수 없습니다. 일반적으로 오래된 키가 원인입니다.\n",
"UserErrorApplicationNotFoundDescription": "Ryujinx가 지정된 경로에서 유효한 응용 프로그램을 찾을 수 없습니다.\n",
"UserErrorUnknownDescription": "알 수 없는 오류가 발생했습니다!\n",
"UserErrorUndefinedDescription": "정의되지 않은 오류가 발생했습니다! 이런 일이 발생하면 안 되므로, 개발자에게 문의하세요!\n",
"OpenSetupGuideMessage": "설정 가이드 열기",
"NoUpdate": "업데이트 없음",
"TitleUpdateVersionLabel": "버전 {0} - {1}",
"RyujinxInfo": "Ryujinx - 정보",
"RyujinxConfirm": "Ryujinx - 확인",
"FileDialogAllTypes": "모든 유형",
"Never": "절대 안 함",
"SwkbdMinCharacters": "{0} 자 이상이어야 함",
"SwkbdMinRangeCharacters": "{0}-{1} 자여야 함",
"SoftwareKeyboard": "소프트웨어 키보드",
"DialogControllerAppletMessagePlayerRange": "응용 프로그램은 다음을 사용하여 {0} 플레이어를 요청합니다:\n\n유형: {1}\n\n플레이어: {2}\n\n{3} 지금 설정을 열고 입력을 재구성하거나 닫기를 누르세요.\n",
"DialogControllerAppletMessage": "애플리케이션은 다음을 사용하여 정확히 {0}명의 플레이어를 요청합니다:\n\n유형: {1}\n\n플레이어: {2}\n\n{3} 지금 설정을 열고 입력을 재구성하거나 닫기를 누르세요.\n",
"DialogControllerAppletDockModeSet": "도킹 모드가 설정되었습니다. 휴대용도 유효하지 않습니다.\n\n\n",
"UpdaterRenaming": "이전 파일 이름 바꾸는 중...",
"UpdaterRenameFailed": "업데이터가 파일 이름을 바꿀 수 없습니다: {0}",
"UpdaterAddingFiles": "새로운 파일을 추가하는 중...",
"UpdaterExtracting": "업데이트를 추출하는 중...",
"UpdaterDownloading": "업데이트 다운로드 중...",
"Game": "게임",
"Docked": "도킹됨",
"Handheld": "휴대용",
"ConnectionError": "연결 오류입니다.",
"AboutPageDeveloperListMore": "{0} 등...",
"ApiError": "API 오류입니다.",
"LoadingHeading": "{0} 로딩 중",
"CompilingPPTC": "PTC 컴파일 중",
"CompilingShaders": "세이더 컴파일",
"AllKeyboards": "모든 키보드",
"OpenFileDialogTitle": "지원되는 파일을 선택",
"OpenFolderDialogTitle": "압축을 푼 게임이 있는 폴더 선택",
"AllSupportedFormats": "지원되는 모든 형식",
"RyujinxUpdater": "Ryujinx 업데이터",
"SettingsTabHotkeys": "키보드 단축키",
"SettingsTabHotkeysHotkeys": "키보드 단축키",
"SettingsTabHotkeysToggleVsyncHotkey": "수직 동기화 전환:",
"SettingsTabHotkeysScreenshotHotkey": "스크린샷:",
"SettingsTabHotkeysShowUiHotkey": "UI 표시:",
"SettingsTabHotkeysPauseHotkey": "일시정지:",
"SettingsTabHotkeysToggleMuteHotkey": "음소거:",
"ControllerMotionTitle": "동작 제어 설정",
"ControllerRumbleTitle": "진동 설정",
"SettingsSelectThemeFileDialogTitle": "테마 파일 선택",
"SettingsXamlThemeFile": "Xaml 테마 파일",
"AvatarWindowTitle": "계정 관리 - 아바타",
"Amiibo": "Amiibo",
"Unknown": "알 수 없음",
"Usage": "사용법",
"Writable": "쓰기 가능",
"SelectDlcDialogTitle": "DLC 파일 선택",
"SelectUpdateDialogTitle": "업데이트 파일 선택",
"UserProfileWindowTitle": "사용자 프로파일 관리자",
"CheatWindowTitle": "치트 관리자",
"DlcWindowTitle": "다운로드 가능한 콘텐츠 관리자",
"UpdateWindowTitle": "타이틀 업데이트 관리자",
"CheatWindowHeading": "{0} [{1}]에 사용할 수 있는 치트",
"DlcWindowHeading": "{1} ({2})에 사용할 수 있는 {0} 다운로드 가능한 콘텐츠",
"UserProfilesEditProfile": "선택 항목 편집",
"Cancel": "취소",
"Save": "저장",
"Discard": "삭제",
"UserProfilesSetProfileImage": "프로파일 이미지 설정",
"UserProfileEmptyNameError": "이름 필요",
"UserProfileNoImageError": "프로파일 이미지를 설정해야 함",
"GameUpdateWindowHeading": "{1} ({2})에 대한 {0} 업데이트 사용 가능",
"SettingsTabHotkeysResScaleUpHotkey": "해상도 증가:",
"SettingsTabHotkeysResScaleDownHotkey": "해상도 감소:",
"UserProfilesName": "이름:",
"UserProfilesUserId": "사용자 Id:",
"SettingsTabGraphicsBackend": "그래픽 백엔드",
"SettingsTabGraphicsBackendTooltip": "사용할 그래픽 백엔드",
"SettingsEnableTextureRecompression": "텍스처 재압축 활성화",
"SettingsEnableTextureRecompressionTooltip": "VRAM 사용량을 줄이기 위해 특정 텍스처를 압축합니다.\n\n4GiB VRAM 미만의 GPU와 함께 사용하는 것이 좋습니다.\n\n확실하지 않으면 꺼 두세요.",
"SettingsTabGraphicsPreferredGpu": "선호하는 GPU",
"SettingsTabGraphicsPreferredGpuTooltip": "Vulkan 그래픽 백엔드와 함께 사용할 그래픽 카드를 선택하세요.\n\nOpenGL이 사용할 GPU에는 영향을 미치지 않습니다.\n\n확실하지 않은 경우 \"dGPU\" 플래그가 지정된 GPU로 설정하세요. 없는 경우, 그대로 두세요.\n",
"SettingsAppRequiredRestartMessage": "Ryujinx 재시작 필요",
"SettingsGpuBackendRestartMessage": "그래픽 백엔드 또는 GPU 설정이 수정되었습니다. 적용하려면 다시 시작해야 함\n",
"SettingsGpuBackendRestartSubMessage": "지금 다시 시작하겠습니까?",
"RyujinxUpdaterMessage": "Ryujinx를 최신 버전으로 업데이트하겠습니까?",
"SettingsTabHotkeysVolumeUpHotkey": "볼륨 증가:",
"SettingsTabHotkeysVolumeDownHotkey": "볼륨 감소:",
"SettingsEnableMacroHLE": "매크로 HLE 활성화",
"SettingsEnableMacroHLETooltip": "GPU 매크로 코드의 높은 수준 에뮬레이션입니다.\n\n성능이 향상되지만 일부 게임에서 그래픽 결함이 발생할 수 있습니다.\n\n확실하지 않으면 켜 두세요.",
"VolumeShort": "볼륨",
"UserProfilesManageSaves": "저장 관리",
"DeleteUserSave": "이 게임에 대한 사용자 저장을 삭제하겠습니까?",
"IrreversibleActionNote": "이 작업은 되돌릴 수 없습니다.",
"SaveManagerHeading": "{0}의 저장 관리",
"SaveManagerTitle": "저장 관리자",
"Name": "이름",
"Size": "크기",
"Search": "검색",
"UserProfilesRecoverLostAccounts": "잃어버린 계정 복구",
"Recover": "복구",
"UserProfilesRecoverHeading": "다음 계정에 대한 저장 발견"
}

View File

@@ -1,613 +0,0 @@
{
"MenuBarFileOpenApplet": "Otwórz Aplet",
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Otwórz aplet Mii Editor w trybie Indywidualnym",
"SettingsTabInputDirectMouseAccess": "Bezpośredni Dostęp do Myszy",
"SettingsTabSystemMemoryManagerMode": "Tryb Menedżera Pamięci:",
"SettingsTabSystemMemoryManagerModeSoftware": "Oprogramowania",
"SettingsTabSystemMemoryManagerModeHost": "Host (szybko)",
"SettingsTabSystemMemoryManagerModeHostUnchecked": "Host Niesprawdzony (najszybciej, niebezpiecznie)",
"MenuBarFile": "_Plik",
"MenuBarFileOpenFromFile": "_Załaduj Aplikację z Pliku",
"MenuBarFileOpenUnpacked": "Załaduj _Rozpakowaną Grę",
"MenuBarFileOpenEmuFolder": "Otwórz Folder Ryujinx",
"MenuBarFileOpenLogsFolder": "Otwórz Folder Logów",
"MenuBarFileExit": "_Wyjdź",
"MenuBarOptions": "Opcje",
"MenuBarOptionsToggleFullscreen": "Przełącz Tryb Pełnoekranowy",
"MenuBarOptionsStartGamesInFullscreen": "Uruchamiaj Gry w Trybie Pełnoekranowym",
"MenuBarOptionsStopEmulation": "Zatrzymaj Emulację",
"MenuBarOptionsSettings": "_Ustawienia",
"MenuBarOptionsManageUserProfiles": "_Zarządzaj Profilami Użytkowników",
"MenuBarActions": "_Akcje",
"MenuBarOptionsSimulateWakeUpMessage": "Symuluj Wiadomość Budzenia",
"MenuBarActionsScanAmiibo": "Skanuj Amiibo",
"MenuBarTools": "_Narzędzia",
"MenuBarToolsInstallFirmware": "Zainstaluj Firmware",
"MenuBarFileToolsInstallFirmwareFromFile": "Zainstaluj Firmware z XCI lub ZIP",
"MenuBarFileToolsInstallFirmwareFromDirectory": "Zainstaluj Firmware z Katalogu",
"MenuBarHelp": "Pomoc",
"MenuBarHelpCheckForUpdates": "Sprawdź Aktualizacje",
"MenuBarHelpAbout": "O Aplikacji",
"MenuSearch": "Wyszukaj...",
"GameListHeaderFavorite": "Ulub",
"GameListHeaderIcon": "Ikona",
"GameListHeaderApplication": "Nazwa",
"GameListHeaderDeveloper": "Deweloper",
"GameListHeaderVersion": "Wersja",
"GameListHeaderTimePlayed": "Czas Gry",
"GameListHeaderLastPlayed": "Ostatnio Grane",
"GameListHeaderFileExtension": "Rozsz. Pliku",
"GameListHeaderFileSize": "Rozm. Pliku",
"GameListHeaderPath": "Ścieżka",
"GameListContextMenuOpenUserSaveDirectory": "Otwórz Katalog Zapisów Użytkownika",
"GameListContextMenuOpenUserSaveDirectoryToolTip": "Otwiera katalog, który zawiera Zapis Użytkownika Aplikacji",
"GameListContextMenuOpenUserDeviceDirectory": "Otwórz Katalog Urządzeń Użytkownika",
"GameListContextMenuOpenUserDeviceDirectoryToolTip": "Otwiera katalog, który zawiera Zapis Urządzenia Aplikacji",
"GameListContextMenuOpenUserBcatDirectory": "Otwórz Katalog BCAT Użytkownika",
"GameListContextMenuOpenUserBcatDirectoryToolTip": "Otwiera katalog, który zawiera Zapis BCAT Aplikacji",
"GameListContextMenuManageTitleUpdates": "Zarządzaj Aktualizacjami Tytułów",
"GameListContextMenuManageTitleUpdatesToolTip": "Otwiera okno zarządzania Aktualizacjami Tytułu",
"GameListContextMenuManageDlc": "Zarządzaj DLC",
"GameListContextMenuManageDlcToolTip": "Otwiera okno zarządzania DLC",
"GameListContextMenuOpenModsDirectory": "Otwórz Katalog Modów",
"GameListContextMenuOpenModsDirectoryToolTip": "Otwiera katalog zawierający Mody Aplikacji",
"GameListContextMenuCacheManagement": "Zarządzanie Cache",
"GameListContextMenuCacheManagementPurgePptc": "Dodaj Rekompilację PPTC do Kolejki",
"GameListContextMenuCacheManagementPurgePptcToolTip": "Zainicjuj Rekompilację PPTC przy następnym uruchomieniu gry",
"GameListContextMenuCacheManagementPurgeShaderCache": "Wyczyść Cache Shaderów",
"GameListContextMenuCacheManagementPurgeShaderCacheToolTip": "Usuwa cache shaderów aplikacji",
"GameListContextMenuCacheManagementOpenPptcDirectory": "Otwórz Katalog PPTC",
"GameListContextMenuCacheManagementOpenPptcDirectoryToolTip": "Otwiera katalog, który zawiera cache PPTC aplikacji",
"GameListContextMenuCacheManagementOpenShaderCacheDirectory": "Otwórz Katalog Cache Shaderów",
"GameListContextMenuCacheManagementOpenShaderCacheDirectoryToolTip": "Otwiera katalog, który zawiera cache shaderów aplikacji",
"GameListContextMenuExtractData": "Wyodrębnij Dane",
"GameListContextMenuExtractDataExeFS": "ExeFS",
"GameListContextMenuExtractDataExeFSToolTip": "Wyodrębnij sekcję ExeFS z bieżącej konfiguracji aplikacji (w tym aktualizacje)",
"GameListContextMenuExtractDataRomFS": "RomFS",
"GameListContextMenuExtractDataRomFSToolTip": "Wyodrębnij sekcję RomFS z bieżącej konfiguracji aplikacji (w tym aktualizacje)",
"GameListContextMenuExtractDataLogo": "Logo",
"GameListContextMenuExtractDataLogoToolTip": "Wyodrębnij sekcję Logo z bieżącej konfiguracji aplikacji (w tym aktualizacje)",
"StatusBarGamesLoaded": "{0}/{1} Załadowane Gry",
"StatusBarSystemVersion": "Wersja Systemu: {0}",
"Settings": "Ustawienia",
"SettingsTabGeneral": "Interfejs Użytkownika",
"SettingsTabGeneralGeneral": "Ogólne",
"SettingsTabGeneralEnableDiscordRichPresence": "Włącz Bogatą Obecność Discord",
"SettingsTabGeneralCheckUpdatesOnLaunch": "Sprawdź Aktualizacje przy Uruchomieniu",
"SettingsTabGeneralShowConfirmExitDialog": "Pokaż Okno Dialogowe \"Potwierdzenia Wyjścia\"",
"SettingsTabGeneralHideCursorOnIdle": "Ukryj Kursor Podczas Bezczynności",
"SettingsTabGeneralGameDirectories": "Katalogi Gier",
"SettingsTabGeneralAdd": "Dodaj",
"SettingsTabGeneralRemove": "Usuń",
"SettingsTabSystem": "System",
"SettingsTabSystemCore": "Główne",
"SettingsTabSystemSystemRegion": "Region Systemu:",
"SettingsTabSystemSystemRegionJapan": "Japonia",
"SettingsTabSystemSystemRegionUSA": "USA",
"SettingsTabSystemSystemRegionEurope": "Europa",
"SettingsTabSystemSystemRegionAustralia": "Australia",
"SettingsTabSystemSystemRegionChina": "Chiny",
"SettingsTabSystemSystemRegionKorea": "Korea",
"SettingsTabSystemSystemRegionTaiwan": "Tajwan",
"SettingsTabSystemSystemLanguage": "Język Systemu:",
"SettingsTabSystemSystemLanguageJapanese": "Japoński",
"SettingsTabSystemSystemLanguageAmericanEnglish": "Amerykański Angielski",
"SettingsTabSystemSystemLanguageFrench": "Francuski",
"SettingsTabSystemSystemLanguageGerman": "Niemiecki",
"SettingsTabSystemSystemLanguageItalian": "Włoski",
"SettingsTabSystemSystemLanguageSpanish": "Hiszpański",
"SettingsTabSystemSystemLanguageChinese": "Chiński",
"SettingsTabSystemSystemLanguageKorean": "Koreański",
"SettingsTabSystemSystemLanguageDutch": "Holenderski",
"SettingsTabSystemSystemLanguagePortuguese": "Portugalski",
"SettingsTabSystemSystemLanguageRussian": "Rosyjski",
"SettingsTabSystemSystemLanguageTaiwanese": "Tajwański",
"SettingsTabSystemSystemLanguageBritishEnglish": "Brytyjski Angielski",
"SettingsTabSystemSystemLanguageCanadianFrench": "Kanadyjski Francuski",
"SettingsTabSystemSystemLanguageLatinAmericanSpanish": "Hiszpański Latynoamerykański",
"SettingsTabSystemSystemLanguageSimplifiedChinese": "Chiński Uproszczony",
"SettingsTabSystemSystemLanguageTraditionalChinese": "Chiński Tradycyjny",
"SettingsTabSystemSystemTimeZone": "Strefa Czasowa Systemu:",
"SettingsTabSystemSystemTime": "Czas Systemu:",
"SettingsTabSystemEnableVsync": "VSync",
"SettingsTabSystemEnablePptc": "PPTC (Profilowany Cache Trwałych Tłumaczeń)",
"SettingsTabSystemEnableFsIntegrityChecks": "Kontrole Integralności Systemu Plików",
"SettingsTabSystemAudioBackend": "Backend Dżwięku:",
"SettingsTabSystemAudioBackendDummy": "Atrapa",
"SettingsTabSystemAudioBackendOpenAL": "OpenAL",
"SettingsTabSystemAudioBackendSoundIO": "SoundIO",
"SettingsTabSystemAudioBackendSDL2": "SDL2",
"SettingsTabSystemHacks": "Hacki",
"SettingsTabSystemHacksNote": " (mogą powodować niestabilność)",
"SettingsTabSystemExpandDramSize": "Użyj alternatywnego układu pamięci (Deweloperzy)",
"SettingsTabSystemIgnoreMissingServices": "Ignoruj Brakujące Usługi",
"SettingsTabGraphics": "Grafika",
"SettingsTabGraphicsAPI": "Graficzne API",
"SettingsTabGraphicsEnableShaderCache": "Włącz Cache Shaderów",
"SettingsTabGraphicsAnisotropicFiltering": "Filtrowanie Anizotropowe:",
"SettingsTabGraphicsAnisotropicFilteringAuto": "Auto",
"SettingsTabGraphicsAnisotropicFiltering2x": "2x",
"SettingsTabGraphicsAnisotropicFiltering4x": "4x",
"SettingsTabGraphicsAnisotropicFiltering8x": "8x",
"SettingsTabGraphicsAnisotropicFiltering16x": "16x",
"SettingsTabGraphicsResolutionScale": "Skala Rozdzielczości:",
"SettingsTabGraphicsResolutionScaleCustom": "Niestandardowa (Niezalecane)",
"SettingsTabGraphicsResolutionScaleNative": "Natywna (720p/1080p)",
"SettingsTabGraphicsResolutionScale2x": "2x (1440p/2160p)",
"SettingsTabGraphicsResolutionScale3x": "3x (2160p/3240p)",
"SettingsTabGraphicsResolutionScale4x": "4x (2880p/4320p)",
"SettingsTabGraphicsAspectRatio": "Współczynnik Proporcji:",
"SettingsTabGraphicsAspectRatio4x3": "4:3",
"SettingsTabGraphicsAspectRatio16x9": "16:9",
"SettingsTabGraphicsAspectRatio16x10": "16:10",
"SettingsTabGraphicsAspectRatio21x9": "21:9",
"SettingsTabGraphicsAspectRatio32x9": "32:9",
"SettingsTabGraphicsAspectRatioStretch": "Rozciągnij do Okna",
"SettingsTabGraphicsDeveloperOptions": "Opcje Programistyczne",
"SettingsTabGraphicsShaderDumpPath": "Ścieżka Zrzutu Shaderów Grafiki:",
"SettingsTabLogging": "Logowanie",
"SettingsTabLoggingLogging": "Logowanie",
"SettingsTabLoggingEnableLoggingToFile": "Włącz Logowanie do Pliku",
"SettingsTabLoggingEnableStubLogs": "Wlącz Skróty Logów",
"SettingsTabLoggingEnableInfoLogs": "Włącz Logi Informacyjne",
"SettingsTabLoggingEnableWarningLogs": "Włącz Logi Ostrzeżeń",
"SettingsTabLoggingEnableErrorLogs": "Włącz Logi Błędów",
"SettingsTabLoggingEnableTraceLogs": "Włącz Logi Śledzenia",
"SettingsTabLoggingEnableGuestLogs": "Włącz Logi Gości",
"SettingsTabLoggingEnableFsAccessLogs": "Włącz Logi Dostępu do Systemu Plików",
"SettingsTabLoggingFsGlobalAccessLogMode": "Tryb Globalnych Logów Systemu Plików:",
"SettingsTabLoggingDeveloperOptions": "Opcje programistyczne (OSTRZEŻENIE: Zmniejszą wydajność)",
"SettingsTabLoggingGraphicsBackendLogLevel": "Ilość Logów Backendu Graficznego:",
"SettingsTabLoggingGraphicsBackendLogLevelNone": "Żadne",
"SettingsTabLoggingGraphicsBackendLogLevelError": "Błędy",
"SettingsTabLoggingGraphicsBackendLogLevelPerformance": "Spowolnienia",
"SettingsTabLoggingGraphicsBackendLogLevelAll": "Wszystkie",
"SettingsTabLoggingEnableDebugLogs": "Włącz Logi Debugowania",
"SettingsTabInput": "Sterowanie",
"SettingsTabInputEnableDockedMode": "Tryb Zadokowany",
"SettingsTabInputDirectKeyboardAccess": "Bezpośredni Dostęp do Klawiatury",
"SettingsButtonSave": "Zapisz",
"SettingsButtonClose": "Zamknij",
"SettingsButtonOk": "OK",
"SettingsButtonCancel": "Anuluj",
"SettingsButtonApply": "Zastosuj",
"ControllerSettingsPlayer": "Gracz",
"ControllerSettingsPlayer1": "Gracz 1",
"ControllerSettingsPlayer2": "Gracz 2",
"ControllerSettingsPlayer3": "Gracz 3",
"ControllerSettingsPlayer4": "Gracz 4",
"ControllerSettingsPlayer5": "Gracz 5",
"ControllerSettingsPlayer6": "Gracz 6",
"ControllerSettingsPlayer7": "Gracz 7",
"ControllerSettingsPlayer8": "Gracz 8",
"ControllerSettingsHandheld": "Przenośny",
"ControllerSettingsInputDevice": "Urządzenie Wejściowe",
"ControllerSettingsRefresh": "Odśwież",
"ControllerSettingsDeviceDisabled": "Wyłączone",
"ControllerSettingsControllerType": "Typ Kontrolera",
"ControllerSettingsControllerTypeHandheld": "Przenośny",
"ControllerSettingsControllerTypeProController": "Pro Controller",
"ControllerSettingsControllerTypeJoyConPair": "Para JoyCon-ów",
"ControllerSettingsControllerTypeJoyConLeft": "Lewy JoyCon",
"ControllerSettingsControllerTypeJoyConRight": "Prawy JoyCon",
"ControllerSettingsProfile": "Profil",
"ControllerSettingsProfileDefault": "Domyślny",
"ControllerSettingsLoad": "Wczytaj",
"ControllerSettingsAdd": "Dodaj",
"ControllerSettingsRemove": "Usuń",
"ControllerSettingsButtons": "Przyciski",
"ControllerSettingsButtonA": "A",
"ControllerSettingsButtonB": "B",
"ControllerSettingsButtonX": "X",
"ControllerSettingsButtonY": "Y",
"ControllerSettingsButtonPlus": "+",
"ControllerSettingsButtonMinus": "-",
"ControllerSettingsDPad": "Pad Kierunkowy",
"ControllerSettingsDPadUp": "Góra",
"ControllerSettingsDPadDown": "Dół",
"ControllerSettingsDPadLeft": "Lewo",
"ControllerSettingsDPadRight": "Prawo",
"ControllerSettingsLStick": "Lewa Gałka",
"ControllerSettingsLStickButton": "Przycisk",
"ControllerSettingsLStickUp": "Góra",
"ControllerSettingsLStickDown": "Dół",
"ControllerSettingsLStickLeft": "Lewo",
"ControllerSettingsLStickRight": "Prawo",
"ControllerSettingsLStickStick": "Gałka",
"ControllerSettingsLStickInvertXAxis": "Odwróć X Gałki",
"ControllerSettingsLStickInvertYAxis": "Odwróć Y Gałki",
"ControllerSettingsLStickDeadzone": "Martwa Strefa:",
"ControllerSettingsRStick": "Prawa Gałka",
"ControllerSettingsRStickButton": "Przycisk",
"ControllerSettingsRStickUp": "Góra",
"ControllerSettingsRStickDown": "Dół",
"ControllerSettingsRStickLeft": "Lewo",
"ControllerSettingsRStickRight": "Prawo",
"ControllerSettingsRStickStick": "Gałka",
"ControllerSettingsRStickInvertXAxis": "Odwróć X Gałki",
"ControllerSettingsRStickInvertYAxis": "Odwróć Y Gałki",
"ControllerSettingsRStickDeadzone": "Martwa Strefa:",
"ControllerSettingsTriggersLeft": "Lewe Triggery",
"ControllerSettingsTriggersRight": "Prawe Triggery",
"ControllerSettingsTriggersButtonsLeft": "Lewe Przyciski Triggerów",
"ControllerSettingsTriggersButtonsRight": "Prawe Przyciski Triggerów",
"ControllerSettingsTriggers": "Triggery",
"ControllerSettingsTriggerL": "L",
"ControllerSettingsTriggerR": "R",
"ControllerSettingsTriggerZL": "ZL",
"ControllerSettingsTriggerZR": "ZR",
"ControllerSettingsLeftSL": "SL",
"ControllerSettingsLeftSR": "SR",
"ControllerSettingsRightSL": "SL",
"ControllerSettingsRightSR": "SR",
"ControllerSettingsExtraButtonsLeft": "Lewe Przyciski",
"ControllerSettingsExtraButtonsRight": "Prawe Przyciski",
"ControllerSettingsMisc": "Różne",
"ControllerSettingsTriggerThreshold": "Próg Triggerów:",
"ControllerSettingsMotion": "Ruch",
"ControllerSettingsMotionUseCemuhookCompatibleMotion": "Użyj ruchu zgodnego z CemuHook",
"ControllerSettingsMotionControllerSlot": "Slot Kontrolera:",
"ControllerSettingsMotionMirrorInput": "Odzwierciedlaj Sterowanie",
"ControllerSettingsMotionRightJoyConSlot": "Prawy Slot JoyCon:",
"ControllerSettingsMotionServerHost": "Host Serwera:",
"ControllerSettingsMotionGyroSensitivity": "Czułość Żyroskopu:",
"ControllerSettingsMotionGyroDeadzone": "Deadzone Żyroskopu:",
"ControllerSettingsSave": "Zapisz",
"ControllerSettingsClose": "Zamknij",
"UserProfilesSelectedUserProfile": "Wybrany Profil Użytkownika:",
"UserProfilesSaveProfileName": "Zapisz Nazwę Profilu",
"UserProfilesChangeProfileImage": "Zmień Obraz Profilu",
"UserProfilesAvailableUserProfiles": "Dostępne Profile Użytkowników:",
"UserProfilesAddNewProfile": "Utwórz Profil",
"UserProfilesDeleteSelectedProfile": "Usuń Zaznaczone",
"UserProfilesClose": "Zamknij",
"ProfileImageSelectionTitle": "Wybór Obrazu Profilu",
"ProfileImageSelectionHeader": "Wybierz zdjęcie profilowe",
"ProfileImageSelectionNote": "Możesz zaimportować niestandardowy obraz profilu lub wybrać awatar z firmware'u systemowego",
"ProfileImageSelectionImportImage": "Importuj Plik Obrazu",
"ProfileImageSelectionSelectAvatar": "Wybierz Awatar z Firmware'u",
"InputDialogTitle": "Okno Dialogowe Wprowadzania",
"InputDialogOk": "OK",
"InputDialogCancel": "Anuluj",
"InputDialogAddNewProfileTitle": "Wybierz Nazwę Profilu",
"InputDialogAddNewProfileHeader": "Wprowadź Nazwę Profilu",
"InputDialogAddNewProfileSubtext": "(Maksymalna Długość: {0})",
"AvatarChoose": "Wybierz",
"AvatarSetBackgroundColor": "Ustaw Kolor Tła",
"AvatarClose": "Zamknij",
"ControllerSettingsLoadProfileToolTip": "Załaduj Profil",
"ControllerSettingsAddProfileToolTip": "Dodaj Profil",
"ControllerSettingsRemoveProfileToolTip": "Usuń Profil",
"ControllerSettingsSaveProfileToolTip": "Zapisz Profil",
"MenuBarFileToolsTakeScreenshot": "Zrób Zrzut Ekranu",
"MenuBarFileToolsHideUi": "Ukryj UI",
"GameListContextMenuToggleFavorite": "Przełącz Ulubione",
"GameListContextMenuToggleFavoriteToolTip": "Przełącz status Ulubionej Gry",
"SettingsTabGeneralTheme": "Motyw",
"SettingsTabGeneralThemeCustomTheme": "Ścieżka Niestandardowych Motywów",
"SettingsTabGeneralThemeBaseStyle": "Styl Podstawowy",
"SettingsTabGeneralThemeBaseStyleDark": "Ciemny",
"SettingsTabGeneralThemeBaseStyleLight": "Jasny",
"SettingsTabGeneralThemeEnableCustomTheme": "Włącz Niestandardowy Motyw",
"ButtonBrowse": "Przeglądaj",
"ControllerSettingsConfigureGeneral": "Konfiguruj",
"ControllerSettingsRumble": "Wibracje",
"ControllerSettingsRumbleStrongMultiplier": "Mocny Mnożnik Wibracji",
"ControllerSettingsRumbleWeakMultiplier": "Słaby Mnożnik Wibracji",
"DialogMessageSaveNotAvailableMessage": "Nie ma danych zapisu dla {0} [{1:x16}]",
"DialogMessageSaveNotAvailableCreateSaveMessage": "Czy chcesz utworzyć dane zapisu dla tej gry?",
"DialogConfirmationTitle": "Ryujinx - Potwierdzenie",
"DialogUpdaterTitle": "Ryujinx - Aktualizator",
"DialogErrorTitle": "Ryujinx - Błąd",
"DialogWarningTitle": "Ryujinx - Uwaga",
"DialogExitTitle": "Ryujinx - Wyjdź",
"DialogErrorMessage": "Ryujinx napotkał błąd",
"DialogExitMessage": "Czy na pewno chcesz zamknąć Ryujinx?",
"DialogExitSubMessage": "Wszystkie niezapisane dane zostaną utracone!",
"DialogMessageCreateSaveErrorMessage": "Wystąpił błąd podczas tworzenia określonych danych zapisu: {0}",
"DialogMessageFindSaveErrorMessage": "Wystąpił błąd podczas znajdowania określonych danych zapisu: {0}",
"FolderDialogExtractTitle": "Wybierz folder do rozpakowania",
"DialogNcaExtractionMessage": "Wyodrębnianie sekcji {0} z {1}...",
"DialogNcaExtractionTitle": "Ryujinx - Ekstraktor Sekcji NCA",
"DialogNcaExtractionMainNcaNotFoundErrorMessage": "Niepowodzenie ekstrakcji. W wybranym pliku nie było głównego NCA.",
"DialogNcaExtractionCheckLogErrorMessage": "Niepowodzenie ekstrakcji. Przeczytaj plik dziennika, aby uzyskać więcej informacji.",
"DialogNcaExtractionSuccessMessage": "Ekstrakcja zakończona pomyślnie.",
"DialogUpdaterConvertFailedMessage": "Nie udało się przekonwertować obecnej wersji Ryujinx.",
"DialogUpdaterCancelUpdateMessage": "Anulowanie Aktualizacji!",
"DialogUpdaterAlreadyOnLatestVersionMessage": "Używasz już najnowszej wersji Ryujinx!",
"DialogUpdaterFailedToGetVersionMessage": "Wystąpił błąd podczas próby uzyskania informacji o wydaniu z GitHub Release. Może to być spowodowane nową wersją kompilowaną przez GitHub Actions. Spróbuj ponownie za kilka minut.",
"DialogUpdaterConvertFailedGithubMessage": "Nie udało się przekonwertować otrzymanej wersji Ryujinx z Github Release.",
"DialogUpdaterDownloadingMessage": "Pobieranie Aktualizacji...",
"DialogUpdaterExtractionMessage": "Wypakowywanie Aktualizacji...",
"DialogUpdaterRenamingMessage": "Zmiana Nazwy Aktualizacji...",
"DialogUpdaterAddingFilesMessage": "Dodawanie Nowej Aktualizacji...",
"DialogUpdaterCompleteMessage": "Aktualizacja Zakończona!",
"DialogUpdaterRestartMessage": "Czy chcesz teraz zrestartować Ryujinx?",
"DialogUpdaterArchNotSupportedMessage": "Nie używasz obsługiwanej architektury systemu!",
"DialogUpdaterArchNotSupportedSubMessage": "(Obsługiwane są tylko systemy x64!)",
"DialogUpdaterNoInternetMessage": "Nie masz połączenia z Internetem!",
"DialogUpdaterNoInternetSubMessage": "Sprawdź, czy masz działające połączenie internetowe!",
"DialogUpdaterDirtyBuildMessage": "Nie możesz zaktualizować Dirty wersji Ryujinx!",
"DialogUpdaterDirtyBuildSubMessage": "Pobierz Ryujinx ze strony https://ryujinx.org/, jeśli szukasz obsługiwanej wersji.",
"DialogRestartRequiredMessage": "Wymagane Ponowne Uruchomienie",
"DialogThemeRestartMessage": "Motyw został zapisany. Aby zastosować motyw, konieczne jest ponowne uruchomienie.",
"DialogThemeRestartSubMessage": "Czy chcesz uruchomić ponownie?",
"DialogFirmwareInstallEmbeddedMessage": "Czy chcesz zainstalować firmware wbudowany w tę grę? (Firmware {0})",
"DialogFirmwareInstallEmbeddedSuccessMessage": "Nie znaleziono zainstalowanego firmware'u, ale Ryujinx był w stanie zainstalować firmware {0} z dostarczonej gry.\n\nEmulator uruchomi się teraz.",
"DialogFirmwareNoFirmwareInstalledMessage": "Brak Zainstalowanego Firmware'u",
"DialogFirmwareInstalledMessage": "Firmware {0} został zainstalowany",
"DialogOpenSettingsWindowLabel": "Otwórz Okno Ustawień",
"DialogControllerAppletTitle": "Aplet Kontrolera",
"DialogMessageDialogErrorExceptionMessage": "Błąd wyświetlania okna Dialogowego Wiadomości: {0}",
"DialogSoftwareKeyboardErrorExceptionMessage": "Błąd wyświetlania Klawiatury Oprogramowania: {0}",
"DialogErrorAppletErrorExceptionMessage": "Błąd wyświetlania okna Dialogowego ErrorApplet: {0}",
"DialogUserErrorDialogMessage": "{0}: {1}",
"DialogUserErrorDialogInfoMessage": "\nAby uzyskać więcej informacji o tym, jak naprawić ten błąd, zapoznaj się z naszym Przewodnikiem instalacji.",
"DialogUserErrorDialogTitle": "Błąd Ryujinxa ({0})",
"DialogAmiiboApiTitle": "API Amiibo",
"DialogAmiiboApiFailFetchMessage": "Wystąpił błąd podczas pobierania informacji z API.",
"DialogAmiiboApiConnectErrorMessage": "Nie można połączyć się z serwerem API Amiibo. Usługa może nie działać lub może być konieczne sprawdzenie, czy połączenie internetowe jest online.",
"DialogProfileInvalidProfileErrorMessage": "Profil {0} jest niezgodny z bieżącym systemem konfiguracji sterowania.",
"DialogProfileDefaultProfileOverwriteErrorMessage": "Profil Domyślny nie może zostać nadpisany",
"DialogProfileDeleteProfileTitle": "Usuwanie Profilu",
"DialogProfileDeleteProfileMessage": "Ta czynność jest nieodwracalna, czy na pewno chcesz kontynuować?",
"DialogWarning": "Uwaga",
"DialogPPTCDeletionMessage": "Masz zamiar umieścić w kolejce rekompilację PPTC przy następnym uruchomieniu:\n\n{0}\n\nCzy na pewno chcesz kontynuować?",
"DialogPPTCDeletionErrorMessage": "Błąd czyszczenia cache PPTC w {0}: {1}",
"DialogShaderDeletionMessage": "Zamierzasz usunąć cache Shaderów dla :\n\n{0}\n\nNa pewno chcesz kontynuować?",
"DialogShaderDeletionErrorMessage": "Błąd czyszczenia cache Shaderów w {0}: {1}",
"DialogRyujinxErrorMessage": "Ryujinx napotkał błąd",
"DialogInvalidTitleIdErrorMessage": "Błąd UI: Wybrana gra nie miała prawidłowego ID tytułu",
"DialogFirmwareInstallerFirmwareNotFoundErrorMessage": "Nie znaleziono prawidłowego firmware'u systemowego w {0}.",
"DialogFirmwareInstallerFirmwareInstallTitle": "Zainstaluj Firmware {0}",
"DialogFirmwareInstallerFirmwareInstallMessage": "Wersja systemu {0} zostanie zainstalowana.",
"DialogFirmwareInstallerFirmwareInstallSubMessage": "\n\nZastąpi to obecną wersję systemu {0}.",
"DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\nCzy chcesz kontynuować?",
"DialogFirmwareInstallerFirmwareInstallWaitMessage": "Instalowanie firmware'u...",
"DialogFirmwareInstallerFirmwareInstallSuccessMessage": "Wersja systemu {0} została pomyślnie zainstalowana.",
"DialogUserProfileDeletionWarningMessage": "Nie będzie innych profili do otwarcia, jeśli wybrany profil zostanie usunięty",
"DialogUserProfileDeletionConfirmMessage": "Czy chcesz usunąć wybrany profil",
"DialogControllerSettingsModifiedConfirmMessage": "Aktualne ustawienia kontrolera zostały zaktualizowane.",
"DialogControllerSettingsModifiedConfirmSubMessage": "Czy chcesz zapisać?",
"DialogDlcLoadNcaErrorMessage": "{0}. Błędny Plik: {1}",
"DialogDlcNoDlcErrorMessage": "Określony plik nie zawiera DLC dla wybranego tytułu!",
"DialogPerformanceCheckLoggingEnabledMessage": "Masz włączone rejestrowanie śledzenia, które jest przeznaczone tylko dla programistów.",
"DialogPerformanceCheckLoggingEnabledConfirmMessage": "Aby uzyskać optymalną wydajność, zaleca się wyłączenie rejestrowania śledzenia. Czy chcesz teraz wyłączyć rejestrowanie śledzenia?",
"DialogPerformanceCheckShaderDumpEnabledMessage": "Masz włączone zrzucanie shaderów, które jest przeznaczone tylko dla programistów.",
"DialogPerformanceCheckShaderDumpEnabledConfirmMessage": "Aby uzyskać optymalną wydajność, zaleca się wyłączenie zrzucania shaderów. Czy chcesz teraz wyłączyć zrzucanie shaderów?",
"DialogLoadAppGameAlreadyLoadedMessage": "Gra została już załadowana",
"DialogLoadAppGameAlreadyLoadedSubMessage": "Zatrzymaj emulację lub zamknij emulator przed uruchomieniem innej gry.",
"DialogUpdateAddUpdateErrorMessage": "Określony plik nie zawiera aktualizacji dla wybranego tytułu!",
"DialogSettingsBackendThreadingWarningTitle": "Ostrzeżenie — Wątki Backend",
"DialogSettingsBackendThreadingWarningMessage": "Ryujinx musi zostać ponownie uruchomiony po zmianie tej opcji, aby działał w pełni. W zależności od platformy może być konieczne ręczne wyłączenie sterownika wielowątkowości podczas korzystania z Ryujinx.",
"SettingsTabGraphicsFeaturesOptions": "Funkcje",
"SettingsTabGraphicsBackendMultithreading": "Wielowątkowość Backendu Graficznego:",
"CommonAuto": "Auto",
"CommonOff": "Wyłączone",
"CommonOn": "Włączone",
"InputDialogYes": "Tak",
"InputDialogNo": "Nie",
"DialogProfileInvalidProfileNameErrorMessage": "Nazwa pliku zawiera nieprawidłowe znaki. Proszę spróbuj ponownie.",
"MenuBarOptionsPauseEmulation": "Pauza",
"MenuBarOptionsResumeEmulation": "Wznów",
"AboutUrlTooltipMessage": "Kliknij, aby otworzyć stronę Ryujinx w domyślnej przeglądarce.",
"AboutDisclaimerMessage": "Ryujinx nie jest w żaden sposób powiązany z Nintendo™,\nani z żadnym z jej partnerów.",
"AboutAmiiboDisclaimerMessage": "AmiiboAPI (www.amiiboapi.com) jest używane\nw naszej emulacji Amiibo.",
"AboutPatreonUrlTooltipMessage": "Kliknij, aby otworzyć stronę Patreon Ryujinx w domyślnej przeglądarce.",
"AboutGithubUrlTooltipMessage": "Kliknij, aby otworzyć stronę GitHub Ryujinx w domyślnej przeglądarce.",
"AboutDiscordUrlTooltipMessage": "Kliknij, aby otworzyć zaproszenie na serwer Discord Ryujinx w domyślnej przeglądarce.",
"AboutTwitterUrlTooltipMessage": "Kliknij, aby otworzyć stronę Twitter Ryujinx w domyślnej przeglądarce.",
"AboutRyujinxAboutTitle": "O Aplikacji:",
"AboutRyujinxAboutContent": "Ryujinx to emulator Nintendo Switch™.\nWspieraj nas na Patreonie.\nOtrzymuj najnowsze wiadomości na naszym Twitterze lub Discordzie.\nDeweloperzy zainteresowani współpracą mogą dowiedzieć się więcej na naszym GitHubie lub Discordzie.",
"AboutRyujinxMaintainersTitle": "Utrzymywany Przez:",
"AboutRyujinxMaintainersContentTooltipMessage": "Kliknij, aby otworzyć stronę Współtwórcy w domyślnej przeglądarce.",
"AboutRyujinxSupprtersTitle": "Wspierani na Patreonie Przez:",
"AmiiboSeriesLabel": "Seria Amiibo",
"AmiiboCharacterLabel": "Postać",
"AmiiboScanButtonLabel": "Zeskanuj",
"AmiiboOptionsShowAllLabel": "Pokaż Wszystkie Amiibo",
"AmiiboOptionsUsRandomTagLabel": "Hack: Użyj losowego UUID tagu",
"DlcManagerTableHeadingEnabledLabel": "Włączone",
"DlcManagerTableHeadingTitleIdLabel": "ID Tytułu",
"DlcManagerTableHeadingContainerPathLabel": "Ścieżka Kontenera",
"DlcManagerTableHeadingFullPathLabel": "Pełna Ścieżka",
"DlcManagerRemoveAllButton": "Usuń Wszystkie",
"DlcManagerEnableAllButton": "Włącz Wszystkie",
"DlcManagerDisableAllButton": "Wyłącz Wszystkie",
"MenuBarOptionsChangeLanguage": "Zmień Język",
"CommonSort": "Sortuj",
"CommonShowNames": "Pokaż Nazwy",
"CommonFavorite": "Ulubione",
"OrderAscending": "Rosnąco",
"OrderDescending": "Malejąco",
"SettingsTabGraphicsFeatures": "Funkcje i Ulepszenia",
"ErrorWindowTitle": "Okno Błędu",
"ToggleDiscordTooltip": "Wybierz, czy chcesz wyświetlać Ryujinx w swojej \"aktualnie grane\" aktywności Discord",
"AddGameDirBoxTooltip": "Wprowadź katalog gier aby dodać go do listy",
"AddGameDirTooltip": "Dodaj katalog gier do listy",
"RemoveGameDirTooltip": "Usuń wybrany katalog gier",
"CustomThemeCheckTooltip": "Użyj niestandardowego motywu Avalonia dla GUI, aby zmienić wygląd menu emulatora",
"CustomThemePathTooltip": "Ścieżka do niestandardowego motywu GUI",
"CustomThemeBrowseTooltip": "Wyszukaj niestandardowy motyw GUI",
"DockModeToggleTooltip": "Tryb Zadokowany sprawia, że emulowany system zachowuje się jak zadokowany Nintendo Switch. Poprawia to jakość grafiki w większości gier. I odwrotnie, wyłączenie tej opcji sprawi, że emulowany system będzie zachowywał się jak przenośny Nintendo Switch, zmniejszając jakość grafiki.\n\nSkonfiguruj sterowanie gracza 1, jeśli planujesz używać trybu Zadokowanego; Skonfiguruj sterowanie przenośne, jeśli planujesz używać trybu przenośnego.\n\nPozostaw WŁĄCZONY, jeśli nie masz pewności.",
"DirectKeyboardTooltip": "Obsługa bezpośredniego dostępu klawiatury (HID). Zapewnia dostęp gier do klawiatury jako urządzenia do wprowadzania tekstu.",
"DirectMouseTooltip": "Obsługa bezpośredniego dostępu myszy (HID). Zapewnia grom dostęp do myszy jako urządzenia wskazującego.",
"RegionTooltip": "Zmień Region Systemu",
"LanguageTooltip": "Zmień Język Systemu",
"TimezoneTooltip": "Zmień Strefę Czasową Systemu",
"TimeTooltip": "Zmień Czas Systemu",
"VSyncToggleTooltip": "Pionowa synchronizacja emulowanej konsoli. Zasadniczo ogranicznik klatek dla większości gier; wyłączenie jej może spowodować, że gry będą działać z większą szybkością, ekrany wczytywania wydłużą się lub nawet utkną.\n\nMoże być przełączana w grze za pomocą preferowanego skrótu klawiszowego. Zalecamy to zrobić, jeśli planujesz ją wyłączyć.\n\nW razie wątpliwości pozostaw WŁĄCZONĄ",
"PptcToggleTooltip": "Zapisuje przetłumaczone funkcje JIT, dzięki czemu nie muszą być tłumaczone za każdym razem, gdy gra się ładuje.\n\nZmniejsza zacinanie się i znacznie przyspiesza uruchamianie po pierwszym uruchomieniu gry.\n\nJeśli nie masz pewności, pozostaw WŁĄCZONE",
"FsIntegrityToggleTooltip": "Sprawdza pliki podczas uruchamiania gry i jeśli zostaną wykryte uszkodzone pliki, wyświetla w dzienniku błąd hash.\n\nNie ma wpływu na wydajność i ma pomóc w rozwiązywaniu problemów.\n\nPozostaw WŁĄCZONE, jeśli nie masz pewności.",
"AudioBackendTooltip": "Zmienia backend używany do renderowania dźwięku.\n\nSDL2 jest preferowany, podczas gdy OpenAL i SoundIO są używane jako rezerwy. Dummy nie będzie odtwarzać dźwięku.\n\nW razie wątpliwości ustaw SDL2.",
"MemoryManagerTooltip": "Zmień sposób mapowania i uzyskiwania dostępu do pamięci gości. Znacznie wpływa na wydajność emulowanego procesora.\n\nUstaw na HOST UNCHECKED, jeśli nie masz pewności.",
"MemoryManagerSoftwareTooltip": "Użyj tabeli stron oprogramowania do translacji adresów. Najwyższa celność, ale najwolniejsza wydajność.",
"MemoryManagerHostTooltip": "Bezpośrednio mapuj pamięć w przestrzeni adresowej hosta. Znacznie szybsza kompilacja i wykonanie JIT.",
"MemoryManagerUnsafeTooltip": "Bezpośrednio mapuj pamięć, ale nie maskuj adresu w przestrzeni adresowej gościa przed uzyskaniem dostępu. Szybciej, ale kosztem bezpieczeństwa. Aplikacja gościa może uzyskać dostęp do pamięci z dowolnego miejsca w Ryujinx, więc w tym trybie uruchamiaj tylko programy, którym ufasz.",
"DRamTooltip": "Wykorzystuje alternatywny układ MemoryMode, aby naśladować model rozwojowy Switcha.\n\nJest to przydatne tylko w przypadku pakietów tekstur o wyższej rozdzielczości lub modów w rozdzielczości 4k. NIE poprawia wydajności.\n\nW razie wątpliwości pozostaw WYŁĄCZONE.",
"IgnoreMissingServicesTooltip": "Ignoruje niezaimplementowane usługi Horizon OS. Może to pomóc w ominięciu awarii podczas uruchamiania niektórych gier.\n\nW razie wątpliwości pozostaw WYŁĄCZONE.",
"GraphicsBackendThreadingTooltip": "Wykonuje polecenia backend'u graficznego w drugim wątku.\n\nPrzyspiesza kompilację shaderów, zmniejsza zacinanie się i poprawia wydajność sterowników GPU bez własnej obsługi wielowątkowości. Nieco lepsza wydajność w sterownikach z wielowątkowością.\n\nUstaw na AUTO, jeśli nie masz pewności.",
"GalThreadingTooltip": "Wykonuje polecenia backend'u graficznego w drugim wątku.\n\nPrzyspiesza kompilację shaderów, zmniejsza zacinanie się i poprawia wydajność sterowników GPU bez własnej obsługi wielowątkowości. Nieco lepsza wydajność w sterownikach z wielowątkowością.\n\nUstaw na AUTO, jeśli nie masz pewności.",
"ShaderCacheToggleTooltip": "Zapisuje pamięć podręczną shaderów na dysku, co zmniejsza zacinanie się w kolejnych uruchomieniach.\n\nPozostaw WŁĄCZONE, jeśli nie masz pewności.",
"ResolutionScaleTooltip": "Skala Rozdzielczości zastosowana do odpowiednich celów renderowania",
"ResolutionScaleEntryTooltip": "Skala rozdzielczości zmiennoprzecinkowej, np. 1,5. Skale niecałkowite częściej powodują problemy lub awarie.",
"AnisotropyTooltip": "Poziom filtrowania anizotropowego (ustaw na Auto, aby użyć wartości wymaganej przez grę)",
"AspectRatioTooltip": "Współczynnik proporcji zastosowany do okna renderowania.",
"ShaderDumpPathTooltip": "Ścieżka Zrzutu Shaderów Grafiki",
"FileLogTooltip": "Zapisuje logowanie konsoli w pliku dziennika na dysku. Nie wpływa na wydajność.",
"StubLogTooltip": "Wyświetla w konsoli skrótowe komunikaty dziennika. Nie wpływa na wydajność.",
"InfoLogTooltip": "Wyświetla komunikaty dziennika informacyjnego w konsoli. Nie wpływa na wydajność.",
"WarnLogTooltip": "Wyświetla komunikaty dziennika ostrzeżeń w konsoli. Nie wpływa na wydajność.",
"ErrorLogTooltip": "Wyświetla w konsoli komunikaty dziennika błędów. Nie wpływa na wydajność.",
"TraceLogTooltip": "Wyświetla komunikaty dziennika śledzenia w konsoli. Nie wpływa na wydajność.",
"GuestLogTooltip": "Wyświetla komunikaty dziennika gości w konsoli. Nie wpływa na wydajność.",
"FileAccessLogTooltip": "Wyświetla w konsoli komunikaty dziennika dostępu do plików.",
"FSAccessLogModeTooltip": "Włącza wyjście dziennika dostępu FS do konsoli. Możliwe tryby to 0-3",
"DeveloperOptionTooltip": "Używaj ostrożnie",
"OpenGlLogLevel": "Wymaga włączonych odpowiednich poziomów logów",
"DebugLogTooltip": "Wyświetla komunikaty dziennika debugowania w konsoli.\n\nUżywaj tego tylko na wyraźne polecenie członka załogi, ponieważ utrudni to odczytanie dzienników i pogorszy wydajność emulatora.",
"LoadApplicationFileTooltip": "Otwórz eksplorator plików, aby wybrać plik kompatybilny z Switch do wczytania",
"LoadApplicationFolderTooltip": "Otwórz eksplorator plików, aby wybrać zgodną z Switch, rozpakowaną aplikację do załadowania",
"OpenRyujinxFolderTooltip": "Otwórz folder systemu plików Ryujinx",
"OpenRyujinxLogsTooltip": "Otwiera folder, w którym zapisywane są logi",
"ExitTooltip": "Wyjdź z Ryujinx",
"OpenSettingsTooltip": "Otwórz okno ustawień",
"OpenProfileManagerTooltip": "Otwórz okno Menedżera Profili Użytkownika",
"StopEmulationTooltip": "Zatrzymaj emulację bieżącej gry i wróć do wyboru gier",
"CheckUpdatesTooltip": "Sprawdź aktualizacje Ryujinx",
"OpenAboutTooltip": "Otwórz Okno Informacje",
"GridSize": "Wielkość siatki",
"GridSizeTooltip": "Zmień rozmiar elementów siatki",
"SettingsTabSystemSystemLanguageBrazilianPortuguese": "Brazylijski Portugalski",
"AboutRyujinxContributorsButtonHeader": "Zobacz Wszystkich Współtwórców",
"SettingsTabSystemAudioVolume": "Głośność: ",
"AudioVolumeTooltip": "Zmień Głośność Dźwięku",
"SettingsTabSystemEnableInternetAccess": "Dostęp do Internetu Gościa/Tryb LAN",
"EnableInternetAccessTooltip": "Pozwala emulowanej aplikacji na łączenie się z Internetem.\n\nGry w trybie LAN mogą łączyć się ze sobą, gdy ta opcja jest włączona, a systemy są połączone z tym samym punktem dostępu. Dotyczy to również prawdziwych konsol.\n\nNie pozwala na łączenie się z serwerami Nintendo. Może powodować awarie niektórych gier, które próbują połączyć się z Internetem.\n\nPozostaw WYŁĄCZONE, jeśli nie masz pewności.",
"GameListContextMenuManageCheatToolTip": "Zarządzaj Kodami",
"GameListContextMenuManageCheat": "Zarządzaj Kodami",
"ControllerSettingsStickRange": "Zasięg:",
"DialogStopEmulationTitle": "Ryujinx - Zatrzymaj Emulację",
"DialogStopEmulationMessage": "Czy na pewno chcesz zatrzymać emulację?",
"SettingsTabCpu": "CPU",
"SettingsTabAudio": "Dżwięk",
"SettingsTabNetwork": "Sieć",
"SettingsTabNetworkConnection": "Połączenie Sieciowe",
"SettingsTabCpuCache": "Cache CPU",
"SettingsTabCpuMemory": "Pamięć CPU",
"DialogUpdaterFlatpakNotSupportedMessage": "Zaktualizuj Ryujinx przez FlatHub.",
"UpdaterDisabledWarningTitle": "Aktualizator Wyłączony!",
"GameListContextMenuOpenSdModsDirectory": "Otwórz Katalog Modów Atmosphere",
"GameListContextMenuOpenSdModsDirectoryToolTip": "Otwiera alternatywny katalog Atmosphere na karcie SD, który zawiera modyfikacje aplikacji. Przydatne dla modów, które są pakowane dla prawdziwego sprzętu.",
"ControllerSettingsRotate90": "Obróć o 90° w Prawo",
"IconSize": "Rozmiar Ikon",
"IconSizeTooltip": "Zmień rozmiar ikon gry",
"MenuBarOptionsShowConsole": "Pokaż Konsolę",
"ShaderCachePurgeError": "Błąd podczas czyszczenia cache shaderów w {0}: {1}",
"UserErrorNoKeys": "Nie znaleziono kluczy",
"UserErrorNoFirmware": "Nie znaleziono firmware'u",
"UserErrorFirmwareParsingFailed": "Błąd parsowania firmware'u",
"UserErrorApplicationNotFound": "Aplikacja nie znaleziona",
"UserErrorUnknown": "Nieznany błąd",
"UserErrorUndefined": "Niezdefiniowany błąd",
"UserErrorNoKeysDescription": "Ryujinx nie mógł znaleźć twojego pliku 'prod.keys'",
"UserErrorNoFirmwareDescription": "Ryujinx nie mógł znaleźć żadnego zainstalowanego firmware'u",
"UserErrorFirmwareParsingFailedDescription": "Ryujinx nie był w stanie zparsować dostarczonego firmware'u. Jest to zwykle spowodowane nieaktualnymi kluczami.",
"UserErrorApplicationNotFoundDescription": "Ryujinx nie mógł znaleźć prawidłowej aplikacji na podanej ścieżce.",
"UserErrorUnknownDescription": "Wystąpił nieznany błąd!",
"UserErrorUndefinedDescription": "Wystąpił niezdefiniowany błąd! To nie powinno się zdarzyć, skontaktuj się z deweloperem!",
"OpenSetupGuideMessage": "Otwórz Podręcznik Konfiguracji",
"NoUpdate": "Brak Aktualizacji",
"TitleUpdateVersionLabel": "Wersja {0} - {1}",
"RyujinxInfo": "Ryujinx - Info",
"RyujinxConfirm": "Ryujinx - Potwierdzenie",
"FileDialogAllTypes": "Wszystkie typy",
"Never": "Nigdy",
"SwkbdMinCharacters": "Musi mieć co najmniej {0} znaków",
"SwkbdMinRangeCharacters": "Musi mieć długość od {0}-{1} znaków",
"SoftwareKeyboard": "Klawiatura Oprogramowania",
"DialogControllerAppletMessagePlayerRange": "Aplikacja żąda {0} graczy z:\n\nTYPY: {1}\n\nGRACZE: {2}\n\n{3}Otwórz Ustawienia i ponownie skonfiguruj Sterowanie lub naciśnij Zamknij.",
"DialogControllerAppletMessage": "Aplikacja żąda dokładnie {0} graczy z:\n\nTYPY: {1}\n\nGRACZE: {2}\n\n{3}Otwórz teraz Ustawienia i ponownie skonfiguruj Sterowanie lub naciśnij Zamknij.",
"DialogControllerAppletDockModeSet": "Ustawiono tryb Zadokowane. Przenośny też jest nieprawidłowy.\n\n",
"UpdaterRenaming": "Zmienianie Nazw Starych Plików...",
"UpdaterRenameFailed": "Aktualizator nie mógł zmienić nazwy pliku: {0}",
"UpdaterAddingFiles": "Dodawanie Nowych Plików...",
"UpdaterExtracting": "Wypakowywanie Aktualizacji...",
"UpdaterDownloading": "Pobieranie Aktualizacji...",
"Game": "Gra",
"Docked": "Zadokowany",
"Handheld": "Przenośny",
"ConnectionError": "Błąd Połączenia.",
"AboutPageDeveloperListMore": "{0} i więcej...",
"ApiError": "Błąd API.",
"LoadingHeading": "Wczytywanie {0}",
"CompilingPPTC": "Kompilowanie PTC",
"CompilingShaders": "Kompilowanie Shaderów",
"AllKeyboards": "Wszystkie klawiatury",
"OpenFileDialogTitle": "Wybierz obsługiwany plik do otwarcia",
"OpenFolderDialogTitle": "Wybierz folder z rozpakowaną grą",
"AllSupportedFormats": "Wszystkie Obsługiwane Formaty",
"RyujinxUpdater": "Aktualizator Ryujinx",
"SettingsTabHotkeys": "Skróty Klawiszowe Klawiatury",
"SettingsTabHotkeysHotkeys": "Skróty Klawiszowe Klawiatury",
"SettingsTabHotkeysToggleVsyncHotkey": "Przełącz VSync:",
"SettingsTabHotkeysScreenshotHotkey": "Zrzut Ekranu:",
"SettingsTabHotkeysShowUiHotkey": "Pokaż UI:",
"SettingsTabHotkeysPauseHotkey": "Pauza:",
"SettingsTabHotkeysToggleMuteHotkey": "Wycisz:",
"ControllerMotionTitle": "Ustawienia Sterowania Ruchowego",
"ControllerRumbleTitle": "Ustawienia Wibracji",
"SettingsSelectThemeFileDialogTitle": "Wybierz Plik Motywu",
"SettingsXamlThemeFile": "Plik Motywu Xaml",
"AvatarWindowTitle": "Zarządzaj Kontami — Avatar",
"Amiibo": "Amiibo",
"Unknown": "Nieznane",
"Usage": "Użycie",
"Writable": "Zapisywalne",
"SelectDlcDialogTitle": "Wybierz pliki DLC",
"SelectUpdateDialogTitle": "Wybierz pliki aktualizacji",
"UserProfileWindowTitle": "Menedżer Profili Użytkowników",
"CheatWindowTitle": "Menedżer Kodów",
"DlcWindowTitle": "Menedżer Zawartości do Pobrania",
"UpdateWindowTitle": "Menedżer Aktualizacji Tytułu",
"CheatWindowHeading": "Kody Dostępne dla {0} [{1}]",
"DlcWindowHeading": "{0} Zawartości do Pobrania dostępna dla {1} ({2})",
"UserProfilesEditProfile": "Edytuj Zaznaczone",
"Cancel": "Anuluj",
"Save": "Zapisz",
"Discard": "Odrzuć",
"UserProfilesSetProfileImage": "Ustaw Obraz Profilu",
"UserProfileEmptyNameError": "Nazwa jest wymagana",
"UserProfileNoImageError": "Należy ustawić obraz profilowy",
"GameUpdateWindowHeading": "{0} Aktualizacje dostępne dla {1} ({2})",
"SettingsTabHotkeysResScaleUpHotkey": "Zwiększ Rozdzielczość:",
"SettingsTabHotkeysResScaleDownHotkey": "Zmniejsz Rozdzielczość:",
"UserProfilesName": "Nazwa:",
"UserProfilesUserId": "ID Użytkownika:",
"SettingsTabGraphicsBackend": "Backend Graficzny",
"SettingsTabGraphicsBackendTooltip": "Używalne Backendy Graficzne",
"SettingsEnableTextureRecompression": "Włącz Rekompresję Tekstur",
"SettingsEnableTextureRecompressionTooltip": "Kompresuje niektóre tekstury w celu zmniejszenia zużycia pamięci VRAM.\n\nZalecane do użytku z GPU, które mają mniej niż 4 GiB pamięci VRAM.\n\nW razie wątpliwości pozostaw WYŁĄCZONE.",
"SettingsTabGraphicsPreferredGpu": "Preferowane GPU",
"SettingsTabGraphicsPreferredGpuTooltip": "Wybierz kartę graficzną, która będzie używana z backendem graficznym Vulkan.\n\nNie wpływa na GPU używane przez OpenGL.\n\nW razie wątpliwości ustaw flagę GPU jako \"dGPU\". Jeśli żadnej nie ma, pozostaw nietknięte.",
"SettingsAppRequiredRestartMessage": "Wymagane Zrestartowanie Ryujinx",
"SettingsGpuBackendRestartMessage": "Zmieniono ustawienia Backendu Graficznego lub GPU. Będzie to wymagało ponownego uruchomienia",
"SettingsGpuBackendRestartSubMessage": "Czy chcesz zrestartować teraz?",
"RyujinxUpdaterMessage": "Czy chcesz zaktualizować Ryujinx do najnowszej wersji?",
"SettingsTabHotkeysVolumeUpHotkey": "Zwiększ Głośność:",
"SettingsTabHotkeysVolumeDownHotkey": "Zmniejsz Głośność:",
"SettingsEnableMacroHLE": "Włącz Macro HLE",
"SettingsEnableMacroHLETooltip": "Wysokopoziomowa emulacja kodu GPU Macro.\n\nPoprawia wydajność, ale może powodować błędy graficzne w niektórych grach.\n\nW razie wątpliwości pozostaw WŁĄCZONE.",
"VolumeShort": "Głoś",
"UserProfilesManageSaves": "Zarządzaj Zapisami",
"DeleteUserSave": "Czy chcesz usunąć zapis użytkownika dla tej gry?",
"IrreversibleActionNote": "Ta czynność nie jest odwracalna.",
"SaveManagerHeading": "Zarządzaj Zapisami dla {0}",
"SaveManagerTitle": "Menedżer Zapisów",
"Name": "Nazwa",
"Size": "Rozmiar",
"Search": "Wyszukaj",
"UserProfilesRecoverLostAccounts": "Odzyskaj Utracone Konta",
"Recover": "Odzyskaj",
"UserProfilesRecoverHeading": "Znaleziono zapisy dla następujących kont"
}

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