279 Commits
Author SHA1 Message Date
Coxxs 280c427c55 Implement CreateLibraryAppletEx in ILibraryAppletCreator 2026-09-18 01:11:26 -05:00
KeatonTheBot 25b4892981 Raise application pool sizes for DRAM selections (again)
- Fixes Ultracam 20+ (beta) support
2026-09-18 01:11:26 -05:00
Neo d16d67f7c4 HLE: Update ProcessResult in ProcessLoader.cs
Some games/applications may crash with a specific error:

00:00:00.690 |E| Application : Unhandled exception caught: System.Collections.Generic.KeyNotFoundException: The given key '0' was not present in the dictionary.

(or a different key)

However, this message is misleading and not indicative of the actual error (it masks it).

As an example, the error above was seen when attempting to load a mod onto Yo-kai Watch 1 (base game + update worked). However, after patching the ProcessResult, the resulting error was more revealing:

00:00:00.716 |E| Application : Unhandled exception caught: LibHac.Common.HorizonResultException: ResultFsInvalidCharacter (2002-6004): Error creating LocalFileSystem. at LibHac.FsSystem.LocalFileSystem..ctor(String rootPath)

(and so forth)

The actual error was due to an incorrect folder name in the Mods folder.
2026-09-18 01:11:26 -05:00
KeatonTheBot e7cb0632c5 Fix build errors in NceCpuContext, LibKenjinx.Input 2026-09-14 14:45:05 -05:00
KeatonTheBot 4ea8c0b280 ContentDialogHelper: Fix explicit type 2026-09-10 23:50:22 -05:00
Max aef309800c Fixed rumble not being sent to the controller
(cherry picked from commit 892fcd9444)
2026-09-10 23:45:47 -05:00
Max a008cd20f1 [HID] Restructure HD Rumble class for future controller support
- Attempted fixing the strength: so far it hasn't been successful.
- Rumble should skip vibrations if they're not in-line with poll-rate: would like to come back to this. Queuing just does exactly what the hid buffer does, but our timer (poll rate) is not in sync with the rate the controller is reading at, which causes excess drops.
- Refactored the class so that implementing support for HD rumble for other controllers (DS5, Steam Controller) is much easier in the future.

(cherry picked from commit e3150d20bb)
2026-09-10 23:45:46 -05:00
Max ec6ce46357 [HID] Fixed HD Rumble latency 2026-09-10 23:45:46 -05:00
stossy11 a7a3a17b48 Fix fragment ClipDistance SPIR-V lookup
- Fixed ClipDistance being treated as VTG gl_PerVertex block, Causing the lookup of Input.Position when it's undeclared.

(cherry picked from commit 5d3e392082)
2026-09-10 23:35:14 -05:00
Neo 94cafdd1f9 Implement: TrySelectUserWithoutInteraction Command 52
Adds support for IAccountServiceForApplication command 52, TrySelectUserWithoutInteraction, introduced in Firmware 19.0.0.

Command 51 (TrySelectUserWithoutInteractionDeprecated) and command 52 use the existing ApplicationServiceServer.TrySelectUserWithoutInteraction implementation.

This prevents newer titles from failing when requesting automatic user selection through the new command.

Tomb Raider: Definitive Edition is now fully playable.

(cherry picked from commit c57e91cc59)
2026-09-10 23:35:11 -05:00
Neo 1b57022694 Fix: GetAllAvailableResources Filtering by Resource Path
Fix EmbeddedResources.GetAllAvailableResources to respect the specified resource path when enumerating embedded resources.

Previously, resources were filtered only by file extension. Adding locale-named JSON files under anywhere else caused them to be included when querying Assets/Locales, resulting in duplicate entries in the language menu.

(cherry picked from commit 0381c7157b)
2026-09-10 23:35:08 -05:00
avan 2bb07a4364 Fix crash on duplicate Build IDs in ModLoader.LoadCheats
Multiple executables may report the same Build ID, causing ToDictionary to throw an ArgumentException while creating the executable lookup.

Build the lookup incrementally and keep the first code address when duplicate Build IDs are encountered. Log a warning if a duplicate Build ID is associated with a different code address.

(cherry picked from commit 93b4c53c8a)
2026-09-10 23:35:05 -05:00
avan 5e67569a6e Fix a hang during the loading stage
In KAddressArbiter, threads were originally inserted into the wait queue according to their DynamicPriority.

When multiple threads had the same DynamicPriority, the original implementation could not guarantee their existing order. Threads with the same dynamic priority are now inserted in FIFO order, preventing unstable wake-up ordering from blocking the guest synchronization flow.

(cherry picked from commit ef14467d1f)
2026-09-10 23:34:59 -05:00
KeatonTheBot 97f0336aa2 Raise application pool sizes for DRAM selections
- Fixes crash with BotW and possibly other games

(cherry picked from commit e07f333a31)
2026-09-05 14:33:15 -05:00
Neo 53d32a761e Improve "Add raw copy dependencies for incompatible textures"
Initial PR was made by Avan for Ryubing.

This allows for Trails in the Sky 1st Chapter (and by extension Trails through Daybreak, Trails through Daybreak II, Trails Beyond the Horizon, and the future Trails in the Sky 2nd Chapter – tested via demo – to be fully playable.

Initial PR caused issues on macOS devices, specifically crashing in certain games (such as Mario Kart 8 Deluxe and the aforementioned Trails games). It was reverted on the original Ryubing project (at the time of writing this description) for causing small rendering issues on The Legend of Zelda: Breath of the Wild.

The rendering issues do not appear on macOS.

This commit improves the original PR by eliminating said macOS crash.

Trails in the Sky 1st writes its exposure/brightness value through an R32G32Float 1x1 texture and later reads the raw bits back through an R32Uint 2x1 texture mapped to the same guest memory. The two texture formats/dimensions are fully incompatible as texture views, so they end
up as separate host textures, and nothing kept their contents coherent - the reader saw stale zeroed data, making the exposure calculation (and the rendered image) too dark. (This is the initial fix for the game)

TextureGroup already had a raw-copy dependency mechanism intended to
handle this class of alias (TextureDependency, TextureGroupHandle
raw-copy plumbing), gated by CanCreateRawCopyDependency's strict same-guest-memory checks. This commit fixes three bugs that kept that mechanism from working correctly (and thus crashing Trails and other games, such as Mario Kart 8 Deluxe):

(1) TextureGroup.InitializeOverlaps() and TextureGroup.RegisterIncompatibleOverlap() only forwarded overlaps to CreateCopyDependency() when compatibility was LayoutIncompatible or better, silently excluding the fully Incompatible case the raw-copy path exists for. Widened both guards to let Incompatible overlaps through so CanCreateRawCopyDependency actually gets a chance to run.

(2) Once Incompatible overlaps were allowed through, CreateCopyDependency(TextureGroup, ...) could still fall back to a regular, non-raw textureCopy for such pairs, since ViewLayoutCompatible/CopySizeMatches only check byte size and were never meant to reason about fully incompatible pairs (e.g. a depth format aliasing a color format with the same byte size). On Vulkan running through MoltenVK on macOS, that non-raw copy path requires a pixel-format-reinterpreting texture view, and MoltenVK/Metal refuses to create any view onto a depth-format texture ("not castable"), aborting emulation. textureCopy is now forced false for Incompatible pairs, leaving raw copy (which already excludes depth/stencil formats) as the only route for that severity level.

(3) TextureGroupHandle.Inherit() copied a handle's pending DeferredCopy to the new handle when a view was recreated, but did not copy DeferredCopyRaw alongside it. A handle that inherited a pending raw copy would then execute it through the regular (non-raw) CopyTo path once acknowledged, reinterpreting the source bytes with the wrong row layout and corrupting the image - visible as vertical flickering stripes whenever a view happened to be recreated with a raw copy still pending. DeferredCopyRaw is now carried over together with DeferredCopy.

(As mentioned earlier, vertical stripes aren't present on macOS, so (3) doesn't negatively have an effect on macOS in any way).
2026-08-29 10:49:56 -05:00
MaxandMythrax 02d8eeb18f HLE: Implemented ILockAccessor and ICommonStateGetter commands and stubs for Virtual Boy – Nintendo Classics #3
- Moves emulation past the initial frame by providing the necessary inputs the game expects. Apparently games like to spin until they get what they want.

Co-authored-by: Mythrax <mythrax@mythrax-rs.org>
2026-08-29 10:49:56 -05:00
Babib3l 54e2f79c16 Hotfix for the PTC version, it's adjacent comment and PTC writer logging 2026-08-29 10:49:21 -05:00
Babib3l 77277442a9 Wire "Start games in fullscreen" option to use the new fullscreen behaviour
Final (hopefully) fix for https://github.com/Ryubing/Issues/issues/415

(cherry picked from commit 7be8829b0a)
2026-08-29 10:39:39 -05:00
Babib3l b707c73f83 River 2 : HLE: Use per-program ownership for PTC disk caches
This PR threads process/program identity into PTC disk cache initialization so cache ownership is selected from the launched process rather than global/shared application state.

Previously, the PTC initialization path only propagated loose title/version information into the CPU layer. That was mostly fine for a single launched application, but will introduce many problems once multiple programs can be launched during the same session, given later processes could inherit cache identity from the first loaded application.
To address this issue, this PR introduces a `PtcCacheInfo` payload and applies it through the process context, CPU context, translator, and PTC initialization paths. Cache ownership is now resolved once the kernel process PID is known and includes:

- PID
- Program ID / Title ID
- Application ID
- Program index
- Display version
- Process kind
- Cache selector

`PtcCacheInfo` now owns its default title/application/version values, and `Ptc` uses that cache info directly instead of mirroring title/version fields internally.

The persistent cache key itself does remains title/version/selector based rather than PID based, so caches remain reusable across launches while still being selected from the correct process context. PID is only used for diagnostics and ownership tracing in logs.

Additional PTC logging has also been added to report cache ownership and selected paths during PTC initialization, Profiling info load/save and translation cache load/save

Both the PTC and profiler internal versions were bumped (a bunch of times lol).

(cherry picked from commit 7101f52c01)
2026-08-24 13:58:01 -05:00
avan 235fb5f8c2 Fix view compatibility for compressed textures with different logical sizes
It has been confirmed that Divinity: Original Sin 2 may describe the same or overlapping guest GPU memory using BCn-compressed textures with different logical dimensions, such as 104×104 and 102×102.

BCn formats store texture data in blocks, with each BC block covering 4×4 texels. After rounding the dimensions up to complete blocks, both 104×104 and 102×102 textures require a 26×26 grid of BC blocks. As a result, they have the same block footprint at the base mip level. Ryujinx originally determined size compatibility in TextureCompatibility.ViewSizeMatches() primarily from this block footprint, which could cause these textures to be classified as Full view-compatible and allowed to share the same Vulkan VkImage directly.

However, because the two textures have different logical dimensions, their mip chains are also different. For example, at mip level 3, a 104×104 texture is reduced to 13×13, while a 102×102 texture is reduced to 12×12. If a 104×104 child texture view shares the backing image of a 102×102 parent texture, a subsequent full mip upload may attempt to write 13×13 compressed data into a Vulkan image subresource whose actual dimensions are only 12×12.

This produces a compressed buffer-to-image copy that does not match the geometry of the backing image. After the invalid command is submitted to the GPU, the Vulkan driver may asynchronously report VK_ERROR_DEVICE_LOST during command buffer submission, waiting, or presentation. In Ryujinx, this eventually appears as: VulkanException: Unexpected API error "ErrorDeviceLost".

The fix adds a logical-dimension check to TextureCompatibility.ViewSizeMatches(). If either the parent or child uses a compressed texture format, and the actual width or height of the corresponding parent mip does not match the logical width or height of the child, the relationship is no longer classified as Full view-compatible. Instead, it is downgraded to CopyOnly.

CopyOnly indicates that the two textures may still describe the same or overlapping guest memory and that their contents must remain synchronized, but they cannot directly share a single fixed-size Vulkan image. Ryujinx instead allows each texture to retain a host texture matching its own logical dimensions and synchronizes their contents through the existing copy-dependency mechanism.

As a result, the 13×13 mip of the 104×104 texture is uploaded to an actual 13×13 destination mip, while the 12×12 mip of the 102×102 texture is uploaded to an actual 12×12 destination mip.

(cherry picked from commit e80fc00462)
2026-08-24 13:58:01 -05:00
avan c2cbd53235 Fix bindless elimination failures observed in OCTOPATH TRAVELER 0:
Failed to find handle source for bindless access of type "textureBuffer".

(cherry picked from commit 33cbd29c23)
2026-08-24 13:58:01 -05:00
avan 4f3c3a7b5d Fix OpenGL program relaunch
The Enhanced and Classic versions of FFT are different program indices within the same application. When the Classic version is launched, the game uses ExecuteProgram to stop the current program, trigger DisposeGpu, create a new renderer and OpenGL context, and then launch the requested program.

Previously, when AppHost executed DisposeGpu, it attempted to bind the old OpenGL context and then called Device.DisposeGpu to destroy GPU resources. During the program relaunch flow, however, the old RendererHost may already have been removed from the visual tree, causing its native window to become detached.

If the old OpenGL context can no longer be bound, a ContextException is thrown, preventing the subsequent AppExit and program relaunch flow from continuing.

The updated implementation handles this case by detecting a ContextException while binding the OpenGL context when ShouldRestart is true. It then skips the destruction of GPU resources that depend on the old OpenGL context, allowing the old context to be released together with the old window. The AppExit and program relaunch flow can then continue without being interrupted.

(cherry picked from commit cfc7c6039f)
2026-08-24 13:58:01 -05:00
avan 2dc1894e1e Fix Vulkan/OpenGL attachmentless rendering
Some fragment passes used by FFT do not have any color or depth/stencil attachments. Instead, the fragment shader writes the results directly to storage images (on OpenGL: through imageStore).

### Vulkan
When SetImage is called and FramebufferParams has no attachments, its virtual size must be updated using the width, height, and layer count of the fragment storage image. Otherwise, the attachmentless framebuffer may retain an incorrect 1x1 extent, causing backgrounds, logos, UI elements, and other rendered content to be missing.

If the first draw occurs before the storage-image descriptor is rebound, SetImage cannot yet provide the correct storage-image dimensions. Therefore, when RecreateGraphicsPipelineIfNeeded finds that FramebufferParams has no attachments and still uses the default 1x1 extent, it initializes the framebuffer dimensions from the active viewport. Otherwise, the first Vulkan draw may be restricted to a 1x1 area and render incorrectly.

The storage-image extent is therefore used as the authoritative size for FramebufferParams, while the active viewport is used as a fallback when the storage-image extent is not yet available before the first draw.

### OpenGL
A storage image is not a framebuffer attachment, so OpenGL cannot derive the framebuffer width and height from it. When the framebuffer has no attachments but a viewport with valid dimensions has already been defined, Pipeline.PreDraw must set the default framebuffer width and height from the active viewport.

Without non-zero default width and height values, the attachmentless framebuffer remains incomplete. Drawing with that framebuffer results in InvalidFramebufferOperation, so rasterization and fragment shader execution do not occur even when the storage images are bound correctly.

(cherry picked from commit ac6db0fe76)
2026-08-24 13:58:00 -05:00
Babib3l db4799e7ab feature: Add GpuDriverVersion to GPU info logging
- The Vulkan backend now reports the driver name and version using VK_KHR_driver_properties when available, with fallbacks for raw Vulkan driverVersion parsing. Intel Windows drivers also get the full package-style version from the driver UUID when exposed by the driver.
  OpenGL now carries its existing OpenGL version string through HardwareInfo.GpuDriverVersion.
2026-08-24 13:58:00 -05:00
LotP 06f049b874 Fix a crash when no controller is connected
Co-authored-by: LotP1 <68976644+LotP1@users.noreply.github.com>
(cherry picked from commit 1a1fe53535)
2026-08-24 13:58:00 -05:00
KeatonTheBot 58f9b6106f Upgrade Android Gradle Plugin to 9.3.1, Gradle to 9.6.1, update dependencies 2026-08-12 21:47:51 -05:00
KeatonTheBot 5422aa35b9 Fix errors in 88cef7e8: misc: chore: Use explicit types & fix object creation 2026-08-12 15:45:13 -05:00
gdkchan 8ccf83d9a3 Prevent waits with zero timeout on Turnip 2026-08-12 14:00:36 -05:00
avan 2eecc18dc7 Reject texture descriptors with unmapped addresses
Fix an "Invalid texture format 0x25A5A (sRGB: True)" error that occurs when running OCTOPATH TRAVELER 0.

The game may leave texture descriptor heap entries filled with 0x5A. Interpreting such uninitialized entries as valid texture descriptors produces an invalid format and causes texture creation to proceed with garbage descriptor data.

Validate the texture address before decoding the descriptor. Descriptors with a zero or unmapped address are marked as invalid and skipped. The invalid state is cleared when the corresponding texture pool entry is modified, allowing the descriptor to be evaluated again.
2026-08-12 13:57:34 -05:00
avan 3ceca9c381 Fix shadow state handling for blend enable updates
Incorrect rendering was observed during loading transitions in Trails in the Sky 1st Chapter. Testing showed that routing the first render target's RT0 BlendEnable transition from disabled to enabled through the normal register write path prevented the issue.

Further investigation found that the normal register write was restoring Shadow RAM behavior that was missing from UpdateBlendEnable.

UpdateBlendEnable uses a fast bulk update path instead of issuing a normal register write for each render target. As a result, it bypasses the Shadow RAM handling provided by DeviceStateWithShadow.WriteWithRedundancyCheck.

A normal register write updates both State and ShadowState in MethodTrack and MethodTrackWithFilter modes. In MethodReplay mode, it ignores the incoming value and restores the value previously stored in ShadowState to State.

UpdateBlendEnable must reproduce the same behavior while retaining its bulk comparison and copy path. In track modes, copy the incoming enable values to shadowState. In replay mode, copy shadowState to the incoming enable span, then let the existing comparison and copy logic update state and mark BlendState dirty when necessary.

The original implementation incorrectly used state for both track and replay handling. This prevented Shadow RAM from correctly recording or replaying BlendEnable values, which could cause rendering state synchronization errors.

Correct the bulk update path to use ShadowState for tracking and replay. This preserves the optimized bulk operation while addressing the underlying issue without requiring an RT0-specific compatibility workaround.

(cherry picked from commit 733bd0951b)
2026-08-12 13:57:34 -05:00
avan a4412346a7 Add raw copy dependencies for incompatible textures
Trails in the Sky 1st uses texture descriptors with different formats and dimensions that map to the same region of guest GPU memory. For example, the game interprets the same underlying data as both an R32Uint 2x1 texture and an R32G32Float 1x1 texture. Both textures have an 8-byte logical payload, but their texel formats and dimensions are different.

Ryubing cannot represent these two descriptors as normally compatible texture views, so it creates separate host texture objects for them. Since these host textures represent the same guest memory, a modification made to one of them should become visible to the other before the other texture is read. However, the existing synchronization mechanism does not fully handle this situation.

The game uses this pattern for its exposure or brightness history. A compute shader first writes the updated exposure data to the R32G32Float 1x1 host texture. A later operation then reads the raw bits of the same data through the R32Uint 2x1 host texture. The original Ryubing implementation did not synchronize the contents of these two separate host textures. As a result, the reading texture received stale zero values, which caused the shader to calculate an incorrectly low exposure value and made the rendered image appear too dark.

TextureGroup already has a guest-memory synchronization mechanism for incompatible overlaps. When _flushIncompatibleOverlaps is enabled, the most recent texture contents are written back to guest memory, after which the other texture reloads the data. However, this mechanism was primarily enabled through IsFormatHostIncompatible, which checks whether an individual texture format can be correctly supported by the host GPU.

In this case, both R32Uint and R32G32Float are individually supported by the host GPU. Therefore, IsFormatHostIncompatible does not enable this synchronization path. The issue is not that either format is unsupported. The issue is that two individually supported aliases, represented by separate host textures, do not maintain coherent contents.

In theory, the latest contents could be flushed to guest memory immediately after every GPU write to a host texture, allowing other textures that map to the same guest memory to reload the updated data. However, doing so could frequently trigger expensive operations such as GPU waits, data readbacks, guest texture layout conversions, and memory-tracking updates. This would be particularly costly for textures that are updated every frame or during every compute dispatch.

For this reason, the fix does not require an immediate flush after every write. Instead, it extends Ryubing's existing TextureDependency and TextureGroupHandle mechanisms. When two fully incompatible textures map to exactly the same guest memory and satisfy a strict set of raw-copy requirements, the program creates a raw-copy dependency between them.

When the source texture is modified, the target texture is only marked as requiring a raw copy. The latest logical raw bytes are copied from the source only when the target texture is actually about to be used. This keeps the contents of the separate host texture aliases coherent while avoiding unnecessary round trips through guest memory.
2026-08-12 13:57:33 -05:00
KeatonTheBot b0eb271b5b SDL: Update game controller database on launch
- Downloads updated gamecontrollerdb.txt file on launch, only updates when a new file is available. This keeps the database updated between SDL releases.

(cherry picked from commit 0657b00622)
2026-08-12 13:57:33 -05:00
KeatonTheBot 88cef7e853 misc: chore: Use explicit types & fix object creation 2026-08-12 13:57:33 -05:00
Renovate Bot 69c088004a Update dependency Ryujinx.SDL3-CS to 2026.707.0 (#16)
This PR contains the following updates:

| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [Ryujinx.SDL3-CS](https://github.com/Kenji-NX/SDL3-CS) | `2026.501.0` → `2026.707.0` | ![age](https://developer.mend.io/api/mc/badges/age/nuget/Ryujinx.SDL3-CS/2026.707.0?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/nuget/Ryujinx.SDL3-CS/2026.501.0/2026.707.0?slim=true) |

---

### Release Notes

<details>
<summary>Kenji-NX/SDL3-CS (Ryujinx.SDL3-CS)</summary>

### [`v2026.707.0`](https://github.com/Kenji-NX/SDL3-CS/compare/2026.501.0...2026.707.0)

[Compare Source](https://github.com/Kenji-NX/SDL3-CS/compare/2026.501.0...2026.707.0)

</details>

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - At any time (no schedule defined)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yNDkuNSIsInVwZGF0ZWRJblZlciI6IjQzLjI0OS41IiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIiwibGFiZWxzIjpbXX0=-->

Reviewed-on: https://git.ryujinx.app/projects/Kenji-NX/pulls/16
2026-08-12 13:53:19 -05:00
KeatonTheBot d3bd888885 Fix MemoryMap/MemoryUnmap/MemoryProtect in UnicornAArch32 and UnicornAArch64
(cherry picked from commit b362f837c5)
2026-08-12 13:52:41 -05:00
LotP b615f50701 fix-tests
- downgrade unicorn to last working version
- update to new cp reg struct system
- remove nonexistent register (used to silently continue)
- fix partial unmap tests
    - InitializeSignalHandler() was moved out of the translator (almost 2.5 years ago), but the test code was never updated to manually call the function as it was changed to do in the real cpu context, so the tests just started failing.
    - by manually initializing the handler we no longer cause tests to fail.
2026-08-12 13:52:41 -05:00
Renovate Bot d5524be27a Update dependency Ryujinx.Audio.OpenAL to 1.25.2 (#8)
This PR contains the following updates:

| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| Ryujinx.Audio.OpenAL | `1.25.1` → `1.25.2` | ![age](https://developer.mend.io/api/mc/badges/age/nuget/Ryujinx.Audio.OpenAL/1.25.2?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/nuget/Ryujinx.Audio.OpenAL/1.25.1/1.25.2?slim=true) |

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - At any time (no schedule defined)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xNzguMCIsInVwZGF0ZWRJblZlciI6IjQzLjE3OC4wIiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIiwibGFiZWxzIjpbXX0=-->

Reviewed-on: https://git.ryujinx.app/projects/Kenji-NX/pulls/8
2026-07-15 11:27:21 -05:00
LotPandLotP1 43b4f3bf12 check for HandleDesc
HandleDesc can be null, make sure to check for that.

Co-authored-by: LotP1 <68976644+LotP1@users.noreply.github.com>
2026-07-15 11:27:06 -05:00
Xam 8d7d8f344c HLE: Applets: Software keyboard: update cursor position on SetInputText
fixes cursor being at 0 position even when text is present, especially annoying for handheld devices with kde virtual keyboard, which is pretty bad, with no way to move the cursor or delete text backward
2026-05-27 18:18:42 -05:00
Babib3l 047dbf3db7 River : HLE: Make process identity explicit for service metadata resolution
This PR is the first in a batch of structural changes to Ryujinx.

**Changes**

- Added `ProcessIdentity` and `ProcessKind` to describe loaded programs by:
  - PID, program ID, application ID, program index, display version, process kind
- Stored identity metadata on `ProcessResult`.
- Added PID-based process lookup helpers to `ProcessLoader`.
- Updated HLE services to resolve application metadata through the caller PID instead of `Processes.ActiveApplication`.
- Added PTC/JIT disk cache initialization logging with PID, title ID, display version, selector, and enabled state.
- Added `ClientProcessId` property to ServiceCtx (/src/Ryujinx.HLE/HOS/ServiceCtx.cs) that uses the handle descriptor PId when available, falling back to `Process.Pid`.
- Updated 15 HLE service files to use `context.ClientProcessId` instead of `context.Process.Pid` for client process access, ensuring services correctly identify the calling process even when invoked via IPC with handle descriptors.

These changes make service metadata resolution more explicit and prepare the emulator for other structural changes later on.
2026-05-27 18:18:36 -05:00
Mabel d0f0007421 Fix Clipboard Copy Operation Crash
Fixes a COM exception crash related to clipboard copy events from changes in Avalonia 11.3

Solves [Ryubing/Issues#294](https://github.com/Ryubing/Issues/issues/294) caused by Avalonia 11.3's changes, see [AvaloniaUI/Avalonia#20007](https://github.com/AvaloniaUI/Avalonia/issues/20007) for more information

I've only tested this on Windows, no idea if this has issues in MacOS or Linux, or if it's even a problem there at all.
2026-05-27 18:18:28 -05:00
LotP 60e553bffa remap joy-cons 2026-05-27 18:18:20 -05:00
KeatonTheBot a8a23b6b2c Revert fix buffer destroy before submit changes (VertexBufferState.cs & VertexBufferUpdater.cs) from 'Fix Vulkan validation errors' 2026-05-17 00:30:34 -05:00
AsperTheDogandAsperTheDog e0f6e207e8 Fix Vulkan validation errors
This PR fixes several validation errors caused by invalid Vulkan usage. These validation errors often end up invoking Undefined Behavior on the driver side, which can lead to artifacts or crashes which are driver specific and otherwise incredibly hard to track. I don't think it should have any impact on performance, but it would be good to test it with as many games as possible (maybe a bug in a game was fixed?).

Each commit fixes an error. I added to each a description with the validation error that was fixed and a small explanation on what was causing it and how I fixed it.

Co-authored-by: AsperTheDog <guillerman0000@gmail.com>
2026-05-16 23:37:11 -05:00
KeatonTheBot 30ab86cb72 Upgrade Android Gradle Plugin to 9.2.1, Gradle to 9.5.1, update dependencies 2026-05-16 23:15:51 -05:00
AsperTheDogandAsperTheDog 2901f9b795 Change non-uniform shader extension to be more conservative
The previous fix for Tomodachi Life (#91) included the extension to all shaders, independently on if it was needed or not. This PR fixes that by lazily adding the extension only when it is actually needed.

This change should not be noticed by anyone, but it avoids having to modify shaders that do not perform any type of dynamic indexing, which apparently is something some modders care about.

Co-authored-by: AsperTheDog <guillerman0000@gmail.com>
2026-05-16 23:11:55 -05:00
Max b08b9eabe6 [HLE] Stub ILibrarySelfAccessor:ExitAndReturn (10) 2026-05-16 23:11:55 -05:00
AsperTheDogandAsperTheDog 83c65c2c06 Add shader non-uniform indexing support
This PR marks ALL texture indexes as nonuniform to fix an issue with the paths in Tomodachi Life: Living the Dream on AMD cards. It should have a negligible impact on performance (and it should not have an impact at all on NVIDIA cards!)

It's caused by what is called 'implicit non-uniform sampler array indexing'. The idea is basically that some GPUs optimize texture lookups from indexed texture arrays, by assuming that you are never going to index different textures within a single workgroup. What this causes is that visual glitch where a subgroup is tasked with rendering a block of the screen, and in the boundaries some cores are indexing the wrong texture.

Co-authored-by: AsperTheDog <guillerman0000@gmail.com>
2026-05-16 23:11:55 -05:00
cookieso 3a6ce7cd1e Input: Implement HD Rumble for compatible Nin devices
This PR addresses [this issue](https://github.com/Ryubing/Issues/issues/231) and implements HD Rumble for compatible Nin devices.
## New Features
- Add the option for Gamepads to implement HD Rumble
- Add the HD rumble capability to SDL3Gamepad and SDL3JoyCon when they meet certain requirements
2026-05-16 23:11:55 -05:00
Max 94cfe6930c Check if the Device is rendering before waiting on it
Fixes an issue where there were missed references and an ``OperationCancelled`` exception when exiting an application.
2026-05-16 23:11:55 -05:00
yell0wsuitandyell0wsuit 9a4bf8f94d [HLE] Match hardware screenshot buffer size behavior for captures
## Description

~~Fixes a fatal CLR crash when `caps` screenshot saving receives an input buffer larger than `0x384000`.~~

~~Resolves a crash in Tomodachi Life: Living the Dream where saving the pictures to the system's album crashes with 0x80131506.~~

Follow up to #18. This PR adjusts the validation and copy behavior to better match real hardware, and adds logging to make invalid screenshot buffer cases easier to diagnose.

Real hardware accepts screenshot buffers with a size greater than or equal to `0x384000`, but only `0x384000` bytes are needed for the 1280x720 RGBA image.

This changes screenshot saving to:

- reject buffers smaller than `0x384000`
- accept buffers equal to or larger than `0x384000`
- copy only the first `0x384000` bytes into the 1280x720 bitmap

## Testing

Tested with a real Switch NRO using `capssuSaveScreenShotEx0`, `capssuSaveScreenShotEx1`, and `capssuSaveScreenShotEx2`.

Observed hardware behavior:

```text
0x384000     => OK
0x384000 - 1 => NullInputBuffer
0x384000 + 1 => OK
0x3C0000     => OK // Tomo life picture size
```

Co-authored-by: yell0wsuit <5692900+yell0wsuit@users.noreply.github.com>
2026-05-16 23:11:55 -05:00
yell0wsuitandyell0wsuit d69d9c3b31 [HLE] Fix StoreData layout and implement IDatabaseService.Append
- Fixes `StoreData` layout/update handling so `UpdateLatest` returns the stored Mii data correctly.

- Implements `IDatabaseService.Append` (https://switchbrew.org/wiki/Shared_Database_services#IDatabaseService)

Also adds regression tests for `UpdateLatest` and `Append`.

(Might) fix Mario Kart 8 Deluxe crashing on first boot due to failed Mii verification check (due to custom Mii from emulator), and potentially Tomodachi Life: Living the Dream for the "Import Mii from system" option.

Co-authored-by: yell0wsuit <5692900+yell0wsuit@users.noreply.github.com>
2026-05-16 23:11:55 -05:00
Frosch d9da38c10b fix: gamepads have the same name
When connecting multiple controllers of the same model, the first device's name ends with (0), the second with (1), the third with (1), the fourth with (1), and so on. To ensure these names are truly unique, GetUniqueGamepadName is now called recursively.
2026-05-16 23:11:54 -05:00
Max ac699e430b [HLE] Implemented ILibraryAppletSelfAccessor:1
Needed for Tomodachi Life: Living the Dream (?)

based on [this](https://www.reddit.com/r/Ryubing/comments/1t4lfc9/comment/ok4e7tu/)
2026-05-16 23:11:54 -05:00
KeatonTheBot 89d7a5c45e UI: RPC: Asset images 2026-05-16 23:11:54 -05:00
Max 93d1eea58d UI: LoadGuestApplication asynchronous cancellation
Fixed LoadGuestApplication hanging when cancelled.
Since startup procedure has technically changed, we should consider testing this with a variety of game formats to ensure regressions do not occur.
2026-05-16 19:45:45 -05:00
KeatonTheBot ad8ab179d2 Update Ryujinx.SDL3-CS to 2026.501.0
- Fixes upstream SDL issue: Crash on Windows when a controller is connected
2026-05-16 19:45:15 -05:00
KeatonTheBot 18c6ec439b misc: Replace IntPtr/UIntPtr with nint/nuint 2026-05-16 18:42:48 -05:00
Xam f2ac50360e HLE: CaptureManager: SaveScreenShot: properly handle screenshot image data
no way this was working before, and if it did, just pure luck, unsafe blind copy of bytes as is and zero checks.

i only tested tomodachi, but should fix all games that were crashing on saving screenshots

the crash was happening because the screenshot buffer was bigger than the bitmap buffer, so marshall.copy() was raising an unhandhled expection crashing the emu.

on top of this, because the data was just copied as is, the result image was garbled.
2026-05-16 18:42:31 -05:00
LotP 8c42f306dd Fix Dual Joy-Con driver and InputView 2026-05-16 18:42:27 -05:00
KeatonTheBot d765d6daa6 Downgrade FluentAvalonia to 2.4.1 2026-05-16 18:41:56 -05:00
KeatonTheBotandMaki e7c720fd2c Update SDL2 to SDL3
- Fix: Crash when connecting a JoyCon

- Fix: Make controller GUIDs match old SDL2 GUIDs

- Fix: Detect face button layout for gamepads

Co-authored-by: Maki <77-maki@users.noreply.git.ryujinx.app>
2026-05-16 18:25:16 -05:00
KeatonTheBot f3a87af51d Use Forgejo badges 2026-05-16 17:27:40 -05:00
KeatonTheBot 1b9615983f Update GitLab references to Forgejo 2026-05-16 17:27:39 -05:00
sh0inx d040492b7a Update BiquadFilterEffectParameterTests.cs 2026-05-16 17:24:52 -05:00
LotP 05f7878699 Accurate Service Names
- Services now use their actual names when creating processes instead of the generic "Service".

- Services now use their names encapsulated in curly brackets for threads, e.g. {HID}, instead of the default "HLE.OsThread", making it easier to see what is actually happening behind the scenes. Client threads should use <> and host threads should use {}.

- Fixed a bug where initiating services would create extra unneeded servers.

This is part 1 of a series of service and Horizon changes i'm working on. More will follow at a later date.
2026-05-16 17:24:42 -05:00
KeatonTheBot 0d8bd2653b Vulkan: Enable VK_EXT_memory_priority for Pageable Memory to work properly 2026-04-01 09:10:46 -05:00
KeatonTheBot b7ffcb3be8 Update NuGet packages
* Avalonia to 11.3.13

* Svg.Controls.Avalonia group to 11.3.9.5

* FluentAvalonia to 2.5.0

* DynamicData to 9.4.31

* Gommon to 2.8.1.1

* Humanizer to 3.0.10

* Microsoft.NET.Test.Sdk to 18.3.0

* NUnit to 4.5.1

* NUnit3TestAdapter to 6.2.0

* Rxmxnx.PInvoke.Extensions to 2.9.0
2026-04-01 09:09:28 -05:00
KeatonTheBot 46c55ee79d UI: Restore FluentAvaloniaUI package, disable animations on app initialization
* Avalonia's built-in color picker is now used when selecting a firmware avatar
2026-04-01 08:58:49 -05:00
KeatonTheBot 6c1c05dc5d Android: Update to 2.1.0-pr.2 2026-03-27 13:21:36 -05:00
KeatonTheBot 637c8130a3 Optimize AutoDeleteCache code 2026-03-27 13:06:59 -05:00
KeatonTheBot 7781911baa Vulkan: Fix Adreno compatibility 2026-03-27 13:06:59 -05:00
KeatonTheBot bd3d4d0566 Add build variants/flavors 2026-03-27 13:06:59 -05:00
KeatonTheBot 63c7d2a0ee Tweak feedback loop restriction logic 2026-03-19 10:49:39 -05:00
Coxxs 5f40a22b0d HLE: Implement CreateContextForSystem
Implement nn::ssl::sf::ISslServiceForSystem -> CreateContextForSystem (100)

Ryujinx implements both ISslService and ISslServiceForSystem in one class so we can just return new ISslContext.

Also fixed the incorrect parameter reading order. (CreateContextForSystem basically has same params as CreateContext)
2026-03-14 23:00:03 -05:00
KeatonTheBot 72955d1aa4 LibKenjinx: Fix possible NullReferenceExceptions 2026-03-09 18:00:40 -05:00
KeatonTheBot ce2f2a14af Upgrade Android Gradle Plugin to 9.1.0, Gradle to 9.4.0, update dependencies 2026-03-06 08:04:23 -06:00
KeatonTheBotandStossy11 b4d0f10568 Vulkan: Add A8B8G8R8 texture format
Co-authored-by: Stossy11 <stossy11@stossy11.com>
2026-03-04 16:44:53 -06:00
KeatonTheBot c2dfc93fa6 Vulkan: Adjust feedback loop restriction to Adreno 6xx/7xx GPUs and not broadly use Qualcomm vendor 2026-03-02 12:24:58 -06:00
KeatonTheBot 29a828c4ef Optimize application pool sizes for DRAM selections 2026-02-28 15:51:47 -06:00
Digote 9995e26ec6 HLE: Return LastUrl for Web/Offline BrowserApplet exit reason
Fixes infinite loop on title screen for Ni no Kuni when no save file exists.
2026-02-28 15:51:22 -06:00
sunshineinabox 59c277bc6c Vulkan: Buffer alignment 2026-02-28 15:51:04 -06:00
sunshineinabox 491fb3ccfb Vulkan: Enable pageable device-local memory 2026-02-28 15:50:47 -06:00
sunshineinabox e96823c9a0 Vulkan: StorageImageExtendedFormats support
(cherry picked from commit caed40d99a)
2026-02-28 14:22:22 -06:00
BeZide93andKeatonTheBot ad0e2c0dea Fix cheat support
Co-authored-by: KeatonTheBot <keaton@ryujinx.app>
2026-02-17 18:38:35 -06:00
KeatonTheBot 59b1989b97 misc: Use nint instead of IntPtr 2026-02-14 12:32:55 -06:00
KeatonTheBot 40c32c7a20 Update dependencies 2026-02-13 16:21:57 -06:00
KeatonTheBot bfe7973d90 Fix log version naming 2026-02-13 15:33:55 -06:00
KeatonTheBot 14c432a416 Android: Update to 2.1.0-pr.1 2026-02-10 17:42:16 -06:00
KeatonTheBot e35ac3fed0 Update Silk.NET to official NuGet 2.23.0 2026-02-10 17:15:24 -06:00
Coxxs e3e46315f0 audio: Fix crash due to invalid Splitter size
Fix crash caused by reading incorrect size of Splitter data.

In most games the crash doesnt happen if you have nn::audio::AudioRendererParameter VoiceCount aligned to 2, as that causes splitter data to be aligned by 0x10, but otherwise, the alignment by 0x10 done in SplitterContext->Update may exceed SplitterSize (which was previously labeled as Unknown24), causing a crash.

(Crash can be replicated by doing AudioRendererParameter.voiceCount++; in any SDK 20.X game that works, which doesn't cause crash on actual hardware)

(This patch is from a friend who makes mods.)
2026-02-07 23:07:28 -06:00
GreemDev a6cb810a92 audio backend projects code cleanup 2026-02-07 23:06:51 -06:00
sh0inx 21b2b2bc03 HLE: Stubbed IUserLocalCommuniationService SetProtocol (106)
Should fix Animal Crossing: New Horizons crashing on LDN connection and potentially other titles with Switch 2 updates.
2026-02-07 23:06:49 -06:00
KeatonTheBotandAaron Robinson d3a6d02ca1 Enable full trimming
Fix trim errors by excluding full assemblies from trimming that use reflection

Co-authored-by: Aaron Robinson <aaronrobin1234@gmail.com>
2026-02-03 23:53:53 -06:00
KeatonTheBot 1b2d471039 Update NuGet packages
* Gommon to 2.8.0.4

* NUnit3TestAdapter to 6.1.0

* Rxmxnx.PInvoke.Extensions to 2.8.5

* Ryujinx.LibHac to 0.21.0-alpha.128
2026-02-03 22:05:23 -06:00
KeatonTheBot 890d5a6e2c Build fixes/updates
* Remove deprecation from build.gradle, settings.gradle

* Update to C++ 20

* Update GIT_TAG for adrenotools
2026-02-01 05:47:45 -06:00
KeatonTheBot 79ab37f282 Tweak app icon 2026-01-31 23:01:54 -06:00
KeatonTheBot 487ef4c163 Disable minify (saves ~2 mins compile time, only adds 1 MB to APK), update dependencies 2026-01-31 18:07:39 -06:00
Coxxs 69908d7bf1 HLE: Implement 10106 and 10107 in IPrepoService
In some games using newer SDK (e.g. Splatoon 3 11.0.0), when `nn::prepo::PlayReport::SetOptInCheckEnabled` is set to False, `nn::prepo::PlayReport::Save` will call `IPrepoService:10106` (SaveReport) and `IPrepoService:10107` (SaveReportWithUser) instead of 10104 (SaveReportOld) and 10105 (SaveReportWithUserOld).

A new param (optInCheckEnabled) is added in 10106/10107 compare to 10104/10105.

This should fix missing service error for Splatoon 3 11.0.0 and other games using newer SDK and has set `nn::prepo::PlayReport::SetOptInCheckEnabled` to False.
2026-01-30 14:51:44 -06:00
sh0inx 395081ae87 HLE: Implement IHidServer IsSixAxisSensorAtRest
Fixes the actually insane amount of log spam in games that check for this, such as Luigi's Mansion 3.

Values in HidDevices.NpadDevices.isAtRest may need to be tuned to a better range for resting detection. I originally set them to 0, and my controller rests at definitely NOT 0.

Will need to be revisited when implementing functionality for the global SixAxisActive bool, IHidServer.StartSixAxisTracking, and IHidServer.StopSixAxisTracking.
2026-01-24 13:06:57 -06:00
KeatonTheBot 1a7be99263 Reduce application size by over 40% 2026-01-23 19:48:39 -06:00
KeatonTheBot d7770e2582 Upgrade to Gradle 9, Kotlin 2.3.0, update dependencies 2026-01-23 19:48:34 -06:00
KeatonTheBot 6a59302104 Kotlin: Code cleanup 2026-01-23 19:48:00 -06:00
blackfa765 e49ef8d60e Improve performance by 5-10% 2026-01-23 19:48:00 -06:00
BeZide 6840ae0c5c Snapdragon 8 Elite (& Adreno 8xx) Fixes
See merge request kenji-nx/ryujinx!20
2026-01-22 03:33:26 -06:00
KeatonTheBot 6f5b351fa0 Android: Update OpenAL to 1.25.1 2026-01-21 21:59:24 -06:00
BeZide 6d36f471dd Revert .NET 10 to .NET 9
See merge request kenji-nx/ryujinx!19
2026-01-21 10:03:25 -06:00
BeZide 2c1b7bc667 single MR with all patches i did, compared to the 2.0.5 release:
See merge request kenji-nx/ryujinx!18
2026-01-20 00:10:38 -06:00
KeatonTheBot dc4a51a462 Android: TakeScreenshot not implemented 2026-01-19 17:38:02 -06:00
KeatonTheBot ea7d680d11 Vulkan: Add ROG Xbox Ally device ID to feedback loop restriction 2026-01-04 18:34:34 -06:00
KeatonTheBot fcf1ba6b9e Update NuGet packages
* Avalonia to 11.3.10

* FluentAvaloniaUI.NoAnim to 2.4.0-build3

* Gommon to 2.8.0.3

* System group to 10.0.1
2025-12-27 23:35:32 -06:00
V380-Ori 99435c8708 Replace shaderc.net with Silk.NET.Shaderc 2025-12-27 23:32:55 -06:00
KeatonTheBot 74011bbb45 Heap adjustments/fixes
* Restore 6 GiB heap for 4 GiB DRAM selection

* Limit heap to 8 GiB for games that crash or won't load with extended heaps
2025-12-26 21:45:18 -06:00
GreemDev 066afe9407 Removed TypedStringEnumConverter; it exists in .NET now.
As per the remark XMLdoc on the type: Get rid of this converter if dotnet supports similar functionality out of the box.
2025-12-26 21:22:23 -06:00
KeatonTheBot 8aa08bc64b Update Silk.NET.Vulkan to 2.23.0
* Add GitLab package registry to nuget.config
2025-12-21 16:10:58 -06:00
KeatonTheBot 940d78a1ad Upgrade Android Gradle Plugin to 8.13.2 2025-12-13 15:02:09 -06:00
KeatonTheBot d0e82aafb1 Migrate SLN to SLNX 2025-12-13 14:36:57 -06:00
KeatonTheBot fe7b601826 misc: chore: Fix possible NullReferenceExceptions, suppress warnings 2025-12-13 14:33:40 -06:00
LotP 9063b4b8db fix pre-action crash
if a buffer is inherited, ignore it and remove it from the list.

fixes a crash when a buffer is inherited during a sync and the containing ranges have been modified to not fit in the old buffer.
2025-12-13 14:33:37 -06:00
LotP e036837211 Fix kaddressarbiter crash
Fixes a crash when trying to access the thread count on a not (yet) existing list of threads.
2025-12-08 20:26:37 -06:00
LotP c6deb3800f Memory Changes 3.2
Fixes a few crashes:
- fixes a crash related to waking threads (priorities were wrong).
- fixes a crash from reusing the SetRenderTargets texture array (left-over data causing issues).
- fixes a mistake and an oversight in the buffer system.
  - buffers were getting updated wrong causing bad data to be stored or some times cut.
  - modified ranges would extend past their old buffers, crashing on syncs. Old buffers are now skipped as the new buffers already sync instead.

Introduces pooling in a few more places to increase memory efficiency.

simplified RangeList item logic.
- removed RangeItem by making all the range objects use the I(NonOverlapping)Range interface.
- BufferCache class no longer locks its RangeList, as the list is only ever accessed synchronously.

Small change to how keyboard snapshots are stored.

Increase ThreadedRenderer SpanPool size to fit slightly more data (4MB -> 8MB).
2025-12-08 20:26:36 -06:00
LotP 75220096e7 Update BiquadFilterEffectParameter2.cs
Fixes audio issues in Metroid Prime 4 and other games
2025-12-08 20:26:34 -06:00
KeatonTheBot 7f805f59fd Fix heap size for kernel check and DRAM selections 2025-12-08 20:26:34 -06:00
Princess Piplup ab571e81b3 Fix SaveCurrentScreenshot
This fixes SaveCurrentScreenshot so it correctly saves the screenshot into the screenshot folder, it's no longer a stub

I was going to add the capture button so all games worked but tbh I only care for spongebob

games tested
Pokemon Z-A: https://files.raychu.xyz/u/1FaUGV.png
Pokemon Violet: https://files.raychu.xyz/u/6swfVS.png
Pokemon Violet: https://files.raychu.xyz/u/JaBBX2.png
Spongebob The Cosmic Shake: https://files.raychu.xyz/u/8z5X2e.png
2025-12-08 20:26:33 -06:00
KeatonTheBot f6adcd2f65 Revert "Sync thread name on Schedule"
This reverts commit c6230fc02e.
2025-11-23 14:13:39 -06:00
KeatonTheBot 85e05bc7b2 misc: chore: Remove unnecessary usings 2025-11-23 14:13:25 -06:00
KeatonTheBot bb0658bba9 nuget: bump packages
* Humanizer to 3.0.1

* Microsoft.IdentityModel.JsonWebTokensto 8.15.0

* Microsoft.NET.Test.Sdk to 18.0.1
2025-11-23 13:48:26 -06:00
KeatonTheBot 50b00e3827 Null-conditional assignments, continued 2025-11-23 13:48:20 -06:00
GreemDev 99c2e672c3 Use the new C# 14 null propagation setter 2025-11-23 13:48:18 -06:00
GreemDev 9ea27c3318 Add .NET Runtime version in About window under Ryujinx version. 2025-11-23 13:48:14 -06:00
KeatonTheBot 203ac3a175 feature: .NET 10 2025-11-23 13:48:10 -06:00
Coxxs bc0c483041 Stub IWriterForApplication: 0 (CreateContextRegistrar)
Fix games that uses ContextRegistrar (e.g. After the socket blocking issue is fixed, Splatoon 3 and other ModuleSystem games will call this when booting, to create a context for the error, after a connection attempt to the server failed.)
2025-11-23 13:47:58 -06:00
LotP dbaf317f15 Memory changes 3.1
Fixes audio bug causing static noise to play in certain games.

Fixes inputs being dropped after a certain amount of playtime.
2025-11-23 13:47:48 -06:00
GreemDev 9357bb1524 UI: App Library: automatically remove nonexistent autoload/game dirs from the configuration upon load. 2025-11-23 13:47:44 -06:00
KeatonTheBot 734aecd711 Add 43:18 aspect ratio (for 3440x1440 [WQHD], 6880×2880 [UW6K+] users) 2025-11-23 13:44:45 -06:00
GreemDevandcomex 1af7ebafc8 Fix socket closing on shutdown
Previously, sockets were only ever closed when the game specifically requested it.

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

Co-Authored-By: comex <47517+comex@users.noreply.github.com>
2025-11-23 13:43:46 -06:00
KeatonTheBot c8a6958ef3 nuget: bump packages
* Gommon to 2.8.0.1

* Microsoft.NET.Test.Sdk to 18.0.0

* Newtonsoft.Json to 13.0.4 (reduces trim warnings by 56)

* Ryujinx.LibHac to 0.21.0-alpha.126

* System group to 9.0.10

* UnicornEngine.Unicorn to 2.1.4-a40db6c
2025-11-23 13:43:41 -06:00
KeatonTheBot 377805579b misc: Tweak NullReferenceException fixes 2025-11-23 13:43:15 -06:00
LotP 35bced8527 Memory changes 3
General memory improvements to decrease GC pressure and frequency.

Pool big arrays and objects that are created and deleted often.

Skip data copies when they aren't needed.

Inline flag checks to skip unneeded allocations.

From my testing the performance is about the same, but the GC frequency is much lower and collection is faster causing less and smaller spikes.
2025-11-23 13:43:14 -06:00
KeatonTheBot c1e24961f9 misc: Use nint/nuint instead of IntPtr/UIntPtr 2025-11-23 13:42:38 -06:00
GreemDev 2d720fea03 hle: Throw a ServiceNotImplementedException instead of ArgumentException if any number arguments provided to ILibraryAppletAccessor are nonzero 2025-11-23 13:40:16 -06:00
LotP 65c740ec4a ILibraryAppletAccessor:90 tweak
Minor update to logic to make our work easier in the future.
2025-11-23 13:40:11 -06:00
sh0inx 0b8d1d5816 HLE: Stub ILibraryAppletAccessor Unknown90
This lets games such as The Legend of Zelda: Tears of the Kingdom (v1.4.2) and other SDK 20+ games successfully circumvent a crash when calling an applet.

Example: No controller connected on boot -> calls Controller Applet -> no stub = crash.
2025-10-27 13:19:55 -05:00
KeatonTheBot 78db4c365f Code cleanup: Audio effects fix and audio object pooling
Commit e1b6cb71
2025-10-27 09:18:01 -05:00
LotP 1bb1c7bba8 gpu allocation optimizations
ObjectPool now uses ConcurrentBag instead if ConcurrentStack, as it has a smaller memory footprint.

Fix compiler warnings related to Audio Command Pools.

Switch gpu command initialization to use pointers, that way skipping the allocation of the command which is unnecessary.

Skip byte array allocation in Ioctl2/3 if it isn't needed (if the source data is all continuous we don't need to copy it to make it continuous).
2025-10-27 09:16:23 -05:00
LotP e1b6cb71f8 audio effects fix and audio object pooling
Revert and reimplement Float BiquadFilterEffect support, fixes infinite load issues in a few games like Splatoon 3.

Fix incorrect string check with the new thread naming system.

Implement object pooling for all Audio Commands and a few other audio related objects and use a growing error list for updating wave buffers instead of always allocating space for 8 errors.
2025-10-27 09:16:23 -05:00
Coxxs f34ab9f043 Fix application list loads slowly when RyuLDN is enabled
Currently, application list will not show until ApplicationLibrary_LdnGameDataReceived calls ViewModel.RefreshView();, forcing a refresh. This makes application list load slowly when RyuLDN is enabled.
2025-10-27 09:16:23 -05:00
Coxxs ebdc2a9e81 Skip directories (and do not RecurseSubdirectories) when finding the icon fallback
Newer applications have a folder for ounce in the Control nca. This fixes Ryujinx trying to open a folder as a file, causing another exception, when trying to find the icon fallback.
2025-10-27 09:16:23 -05:00
KeatonTheBot ebeb6e146c Fix Ori 2 not launching (revert Possible NullReferenceException change) 2025-10-27 09:16:23 -05:00
GreemDev 28b4f45645 gpu: tweak: Do not log missing Votevtg implementation. 2025-10-27 09:16:23 -05:00
GreemDev f3931a789a chore: fix in-code typos 2025-10-27 09:16:23 -05:00
Coxxs 42369a22a3 Implement IUserServiceCreator: 1 (CreateClientProcessMonitor)
This should fix nn::ldn::Initialize in games that use SDK 18 or higher.
2025-10-27 09:16:23 -05:00
Coxxs 7b801bb9d3 Update LoadIdTokenCache for 19.0.0+
This should stub nn::account::LoadNetworkServiceAccountIdTokenCache for games that use SDK 19 or higher.
2025-10-27 09:16:23 -05:00
KeatonTheBot 457b7e77de Update NUnit to 4.4.0
* NUnit3TestAdapter to 5.2.0

* Rename Assert class to ClassicAssert to align with NUnit 4.x changes
2025-10-27 09:16:23 -05:00
Xam 169712a9e8 Fix duplicate volume and mode change events in AppHost 2025-10-27 09:16:22 -05:00
Xam a187ec09d7 Horizon: Audio: HwopusIpcServer: fix random crashes regression in Pokemon Quest 2025-10-27 09:16:22 -05:00
KeatonTheBot 6d9e7fea75 12 GiB heap crash workaround
Using resolution mods, heaps past 8 GiB work in some games (like LoZ: TotK) and not in others (like SMP Jamboree). Setting the heap to a hard limit of 8 GiB on the 10 & 12 GiB DRAM options seems to be the safe bet right now until a better solution is found.
2025-10-27 09:16:22 -05:00
GreemDevandCoxxs ea89fc28da misc: Update Ryujinx.LibHac
Match the behavior with AMS: https://github.com/Atmosphere-NX/Atmosphere/blob/c8e39a54d257bf9875ac852fc1521f046c968339/libraries/libstratosphere/source/fssystem/fssystem_aes_ctr_counter_extended_storage.cpp#L93

This should fix the error ResultFs.InvalidArgument (2002-6001) in some nca.

Co-authored-by: Coxxs <58-coxxs@users.noreply.git.ryujinx.app>
2025-10-27 09:16:22 -05:00
KeatonTheBot 7242cb2449 Restore original application pool sizes for DRAM selections 2025-10-27 09:16:22 -05:00
LotPandKeatonTheBot 4f101170f0 12 GiB heap support
The heap was limited to 6 GiB no matter the memory setting, causing memory configurations above 8 GiB to not actually affect the heap size.

Now when the memory config is set to [10 or] 12 GiB the heap also allocates 12 GiB.

The SetHeapSize SysCall will now allow heap sizes up to 12 GiB (technically slightly less).

Co-authored-by: KeatonTheBot <keaton@ryujinx.app>
2025-10-27 09:16:22 -05:00
Coxxs fc7932ad27 Flush the error log before exit
Currently, some logs can be missing when a fatal error occurs (especially GuestBrokeExecutionException).

This MR attempts to flush logs to console and file before process exit.
2025-10-27 09:16:22 -05:00
GreemDev 0c41346400 UI: Move IgnoreControllerApplet to the System config section object 2025-10-27 09:16:22 -05:00
LotP c6230fc02e Sync thread name on Schedule
Set the name of the HostThread on Schedule() if the thread name isn't already set and if we fetch a valid thread name from the guest thread.
2025-10-27 09:16:21 -05:00
LotP 1ef09717d2 SDK20 and REV15 support
* Fixed an issue where games would boot loop because of an incorrect HID state.

  * Turns out the SamplingNumber of the atomic input storage doesn't match the SamplingNumber of the input state held by the atomic storage, instead it is exactly double the value in the input state.

* Added new Condition struct to the HID Shared memory and populate it with dummy data to fix the no-controller crash (already merged).

* The audio renderer has been mostly updated to rev15, allowing rev15 games to launch.

  * Biquad filters now use floats.

  * Several structures have been renamed to match the SDK names, making it easier to compare functionality. A few names are still missing and will be changed at a later date.

  * The new commands from rev15 have been added to the CommandType enum, but they are still missing from the code itself.

    * Due to changes in the SDK layout, the time estimation functions are either missing or very well hidden (or Ghidra search functionality is useless). We can't fully implement the new commands until the timing data has been located.

  * A few minor tweaks to the code have been made to more accurately match the SDK.
2025-10-27 08:50:57 -05:00
KeatonTheBot 41eb6f5dc4 Android: Update to 2.0.5 2025-10-07 15:17:50 -05:00
KeatonTheBot f47be3342f Remove, replace redundant/deprecated code 2025-10-07 15:09:31 -05:00
BeZide93 4d1620c330 editable Overlay Button (position and opacity) 2025-10-06 11:49:55 -05:00
KeatonTheBot 7a5b5dee6a misc: chore: Fix possible NullReferenceExceptions, InvalidOperationExceptions 2025-10-06 11:48:21 -05:00
BeZide93 fa5b5b127e added stretch to fullscreen 2025-09-29 13:53:26 -05:00
BeZide93 327416c967 reduced logs for orientation changes 2025-09-27 11:56:09 -05:00
BeZide93 c42663115b sensor landscape fix 2025-09-27 11:47:43 -05:00
BeZide93 09bc10b15d use android timezone instead of UTC 2025-09-26 14:20:41 -05:00
KeatonTheBot 75058d850b Remove unused Vulkan Validation Layer binary 2025-09-25 17:15:44 -05:00
KeatonTheBot ab6ccb3d0b Update Kotlin to 1.9.25, Compose Compiler to 1.5.15 2025-09-25 17:15:22 -05:00
KeatonTheBot 07ae239130 Upgrade Android Gradle Plugin to 8.13.0 2025-09-25 17:15:21 -05:00
KeatonTheBot 548ec2c175 Add Android 10 support 2025-09-25 17:10:03 -05:00
KeatonTheBot 925ffc3976 Android: Update packages, bump compileSdk and targetSdk to 36 2025-09-25 17:10:03 -05:00
BeZide93 cf12e5ab82 SystemLanguage+RegionCode Settings 2025-09-25 17:10:03 -05:00
BeZide93 1f283b366b added x0.75 resolution setting 2025-09-25 17:10:03 -05:00
BeZide93 e4d2dea201 removed old L3/R3 settings on virtual controllers (doubletab+hold) 2025-09-25 17:10:03 -05:00
BeZide93 0cf2b1fbda titleid_map.ndjson bloat fixed 2025-09-25 17:10:03 -05:00
BeZide93 8418025b82 fixed screen stretch when switching between landscape and portrait mode 2025-09-25 17:10:03 -05:00
BeZide93 316dc3a9b3 Sensor, portrait, Landscape Settings 2025-09-25 17:10:03 -05:00
BeZide93 d73d82fbc0 Version Badge added 2025-09-25 17:10:03 -05:00
BeZide93 7cc28d0242 Fixed Loading Screen while Compiling Shaders 2025-09-25 17:10:03 -05:00
BeZide93 92c3b72b17 fixed L3+R3 on physical controllers, added L3/R3 on virtual Controllers 2025-09-25 17:10:03 -05:00
BeZide93 8707fd5232 added a titleid_map.ndjson, and game names in titleid.txt 2025-09-25 17:10:03 -05:00
BeZide93 c125d08636 linked titleId to Save File 2025-09-25 17:10:03 -05:00
BeZide93 eee4a6272c Keyboard inputs fixed 2025-09-25 17:10:02 -05:00
BeZide93 be176fd367 merged 2.0.3 Layout into 2.0.4 2025-09-25 17:10:02 -05:00
KeatonTheBot 48ba1cc9ed misc: chore: Merge into pattern 2025-09-25 17:04:08 -05:00
KeatonTheBot a6f3f0718d misc: chore: Remove unnecessary usings 2025-09-25 17:04:07 -05:00
KeatonTheBot 9cdd9f6dbf misc: chore: Fix object creation 2025-09-25 17:04:07 -05:00
KeatonTheBot 0928851966 misc: chore: Discard unused parameters 2025-09-25 17:04:06 -05:00
KeatonTheBot d773bd60f4 misc: chore: Merge duplicated 'if' branches 2025-09-25 17:04:06 -05:00
Mcost45 dfb6164ba5 Include SL/SR default bindings for single joycons
Single L/R Joycons default to unbound for the SL/SR inputs - so by default you can't progress past 'press L + R to continue' type screens.
But

* ConfigGamepadInputId.SingleLeftTrigger0(L)

* ConfigGamepadInputId.SingleRightTrigger0(L)

* ConfigGamepadInputId.SingleLeftTrigger1(R)

* ConfigGamepadInputId.SingleRightTrigger1(R)

already exist (and I verified these are the inputs triggered by the SL/SR buttons), so my change would default to these instead.
2025-09-25 17:04:05 -05:00
Alula 5a9bc0d703 feat: resolve real module names in HLE debugger 2025-09-25 17:03:50 -05:00
KeatonTheBot 2699bcf03e UI: Update Svg.Controls.Avalonia group to 11.3.6.2 2025-09-25 15:48:47 -05:00
KeatonTheBot f45c1e6dcb UI: Update Avalonia to 11.3.6 2025-09-25 15:48:47 -05:00
KeatonTheBot fd75b35496 nuget: bump System group to 9.0.9 2025-09-25 15:48:12 -05:00
LotP 3e8d562182 Memory changes 2.2.1
Cleans up some leftover comments i forgot to remove.

Potentially fixes 1 more crash.
2025-09-12 21:28:07 -05:00
LotP 65caa1e3f2 Memory changes 2.2
A few more internal changes to the RangeList systems.

* No longer using a QuickAccess dictionary.

  * The performance of the dictionary wasn't much faster than just doing binary searches.

  * Using just binary searches allows us to take advantage of span and array returns as they're are faster than linked lists when iterating or copying the overlaps.

Small code optimizations.

Fixes a few leftover crashes.
2025-09-12 21:27:50 -05:00
LotP e3ef1e1fde Memory changes 2.1
* Fixes a few crashes

* Simplifies a few functions

* Changes a few calls to use faster methods

(cherry picked from commit 61da23cb9e)
2025-09-12 21:24:19 -05:00
LotP 3deddbd491 Memory Changes part 2
* Slightly refactors RangeLists from the last Memory Changes MR, which fixes issue 61.

* Convert as many const size array iterators to span iterators as possible. When iterating over a const size array, every iteration created a Span, now only the first iteration does in most places.

* Now using object pooling for a few object types that were rapidly deleted and recreated.

* Converted a few flag checks to binary operations to save memory allocations.
2025-09-12 21:24:19 -05:00
LotP ff0daa9f35 Memory Changes
* Refactors the RangeList and derivative classes used for handling lists of regions

* The Binary searches are now more performant, relying on edge searches instead of just returning the first matching hit and manually iterating until the edge is found

* Most look-ups now return a RangeItem, which acts as a linked list node now, instead where possible, moving away from Array copies. This should help with some specific lag spikes.

* Made IntrusiveRedBlackTreeNodes act like linked list nodes too to improve the lookup time of minimums, maximums and successors.

* Changed a few cases of HasFlag() into binary operations to save on memory allocations.

In general, [these changes] should increase frame time stability and lag spikes, but at the cost of some overhead to memory look-ups, the result being a very slightly better average fps from my testing (~1-2%).

(cherry picked from commit 01cb33f658)
2025-09-12 21:23:24 -05:00
KeatonTheBot faa8fb6642 UI: RPC: Hollow Knight Silksong asset image 2025-09-09 22:30:10 -05:00
LotP 6e7d013903 hle: Basic event handle implementation for IApplicationFunctions 210
Lets Hollow Knight: Silksong boot.

* remove stub

* Add version comment
2025-09-09 22:30:10 -05:00
KeatonTheBot 5db4793c7b UI: Fix Match System Time setting not appropriately disabling/enabling System Time options 2025-09-09 22:30:09 -05:00
KeatonTheBot db8b61106d misc: chore: Replace Gommon functions with standard .NET equivalents (part 3) 2025-09-09 22:30:09 -05:00
KeatonTheBot 55ea9046a2 UI: Update Avalonia to 11.3.5
* Fix text and ComboBox alignment in Save Manager
2025-09-09 22:30:09 -05:00
KeatonTheBot a84dd77dc2 Update SDL to 2.32.10 2025-09-09 22:30:09 -05:00
KeatonTheBot 743eef7ff9 Update FFmpeg runtimes to 6.1.3 for Windows/Linux 2025-09-09 22:30:09 -05:00
GreemDev 39066b846d [ci skip] chore: Change LDN server URL (it's the same server, just a more official URL) 2025-09-09 22:30:09 -05:00
KeatonTheBot 307d048d25 infra: Rename (some) remaining Kenji-NX references back to Ryujinx 2025-08-22 11:42:49 -05:00
KeatonTheBot 7f89429b9f nuget: bump packages
* Microsoft.CodeAnalysis.CSharp to 4.12.0

* Microsoft.IdentityModel.JsonWebTokens to 8.14.0

* UnicornEngine.Unicorn to 2.1.3
2025-08-22 11:35:42 -05:00
gdkchan 6b08ba47c4 Protect against stack overflow caused by deep recursive calls
* PPTC version bump

* Also reset call depth when not using the unmanaged dispatch loop

* Increment call depth on function start rather than before call
2025-08-20 12:18:17 -05:00
gdkchan f63cb962ad Avoid lookup of invalid textures if pool did not change 2025-08-20 12:18:15 -05:00
KeatonTheBot 2c2b37678a nuget: bump System group to 9.0.8 2025-08-06 14:23:41 -05:00
KeatonTheBot 6fed0795b9 nuget: bump DiscordRichPresence to 1.6.1.70 2025-08-06 14:23:13 -05:00
KeatonTheBot c5540f9541 UI: Update FluentAvalonia.NoAnim to 2.4.0-build2, revert ColorPicker changes 2025-08-06 14:23:01 -05:00
KeatonTheBot 4c7a5a7261 UI: Update Avalonia to 11.3.2, FluentAvalonia to 2.4.0
* FluentAvalonia: Disabled NavigationView selection indicator animations due to bugged implementation in 2.1.0+, restoring previous behavior

* Avalonia: Fixed text on certain buttons being larger than normal

* Avalonia: Fixed ComboBox code inserting extra space to the left of selected items
2025-08-06 14:22:54 -05:00
KeatonTheBot 925610723c nuget: bump DiscordRichPresence to 1.4.1.37, Microsoft.IdentityModel.JsonWebTokens to 8.13.0 2025-08-06 14:22:51 -05:00
KeatonTheBot bdc573ab17 UI: RPC: Pokémon Friends asset image 2025-08-06 14:22:46 -05:00
GreemDev f61e340a58 Update Ryujinx.LibHac
This should fix crashes with mods that worked on Ryubing 1.3.1.

Thanks @cyphix!

https://git.ryujinx.app/ryubing/libhac/-/commit/e39169ab5053ff179b7fef38f624dfc608d2596c
2025-08-06 14:22:41 -05:00
KeatonTheBot 0149b71ac9 Android: Fix qualifiers for precise sleep event 2025-07-14 17:14:30 -05:00
KeatonTheBot b4eaa5f262 misc: chore: Android: Remove redundant qualifiers 2025-06-28 17:45:49 -05:00
Evan Husted 2f7406aaca Headless in Avalonia v2
Launch the Ryujinx.exe, first argument --no-gui or nogui, and the rest of the arguments should be your normal headless script. You can include the new option --use-main-config which will provide any arguments that you don't, filled in from your main config made by the UI.
2025-06-22 22:29:39 -05:00
KeatonTheBot a9954c23cc misc: chore: Android: Clean up .NET code, resolve warnings 2025-06-22 22:29:27 -05:00
KeatonTheBot 9955191651 infra: Readjust namespaces/folders/projects/filenames back to Ryujinx 2025-06-22 21:30:22 -05:00
Coxxs 2e0bb4ec56 fix: UI deadlock when launching a game with "Trace Logs" enabled
This fixes https://github.com/Ryubing/Issues/issues/30

* Switch to "Release" build config (PerformanceCheck(); will only be called in Release build config)

* Enable "Trace Logs" in Ryujinx settings

* Double-click a game to launch

* Ryujinx will attempt to open a confirmation dialog box that never opens, causing UI deadlock
2025-06-20 16:33:24 -05:00
KeatonTheBot c417740beb misc: chore: Replace Gommon functions with standard .NET equivalents (part 2) 2025-06-20 16:33:23 -05:00
KeatonTheBot 0d51f4fcb5 misc: chore: Replace additional instances of Gommon ForEach with 'foreach' statements 2025-06-20 16:33:23 -05:00
KeatonTheBot 4626aae70e misc: chore: Use 'foreach' statement in place of Gommon ForEach in "delete all" mod manager crash fix
* Simplify statement for valid mod folder checking
2025-06-20 16:33:22 -05:00
KeatonTheBot d0abbc6da3 misc: chore: Fix numerous NullReferenceExceptions, InvalidOperationExceptions 2025-06-20 16:33:20 -05:00
Coxxs 9b6b9146e2 fix: socket blocking flag is inverted when setting it 2025-06-20 16:33:19 -05:00
KeatonTheBot 4605c8bbd3 nuget: bump packages
* DynamicData to 9.4.1

* Microsoft.IdentityModel.JsonWebTokens to 8.12.0
2025-06-20 16:33:19 -05:00
KeatonTheBot 18743ed661 nuget: bump DiscordRichPresence to 1.3.0.28 2025-06-20 16:33:18 -05:00
KeatonTheBot 3487c4546e nuget: bump System group to 9.0.6 2025-06-20 16:33:18 -05:00
mqudsi c457a2470f Work around Escape hotkey race with exit confirmation dialog 2025-06-20 16:33:17 -05:00
rockingdice 9fb338395a fix: crash caused by cursor overflow
* This fixes a crash that occurred when opening the soft keyboard for the second time
2025-06-20 16:33:17 -05:00
rockingdice ab7e27a4e9 fix: use the correct font family for CJK characters 2025-06-20 16:33:17 -05:00
KeatonTheBot 44b6f162c1 Update SDL2 to 2.32.8 2025-06-20 16:32:45 -05:00
GreemDev 775c7b766c infra: Update to Ryujinx.LibHac 0.20.0
This is identical to the previous version, it's just on NuGet.org so we can comment out the LibHacAlpha source in nuget.config.
2025-06-20 16:26:30 -05:00
GreemDev 3faa22b85a misc: Update LibHac
* _lastFileOffset now correctly stores the offset for the last file in the chain

  * Fixes an issue where a RomFS mod with both overridden and new files in the same folder would load incorrectly

* Renamed a variable with the wrong name

* Now behaves correctly when the same file is added twice in a row compared to V1 MR
2025-06-20 16:26:30 -05:00
LotP 05c3f2a250 fix: use accurate length for enumerating
See merge request ryubing/ryujinx!49
2025-06-20 16:26:30 -05:00
LotP 8611e42a2e Update LibHac
* Fixes Avalonia timeout

* Cuts RomFS rebuilding times by up to a factor of 1000 in games with big RomFS like TotK
2025-06-20 16:26:29 -05:00
KeatonTheBot 620666909f Suppress CA1416 warnings, correct argument kind in IFileSystem 2025-06-20 16:25:22 -05:00
KeatonTheBot ef6f43825d Update OpenTK to 4.9.4, OpenAL to 1.24.3 2025-06-20 16:25:22 -05:00
KeatonTheBot d7b797bf02 Change stick visualizer color to system accent color 2025-06-20 16:25:22 -05:00
KeatonTheBot 0e4f71b2f1 Android: fix: Games not showing in game list 2025-06-04 23:34:08 -05:00
KeatonTheBot 1c23a55937 Update Kenji-NX to 2.0.4 2025-06-04 17:25:46 -05:00
KeatonTheBot 84d7f2d113 Android: Optimize APK file size 2025-06-04 17:14:14 -05:00
KeatonTheBot 78b00e530c misc: chore: Android: Tweak setting names, code 2025-06-04 10:51:32 -05:00
KeatonTheBot b22d771cce Clean up build.gradle 2025-06-02 21:47:57 -05:00
KeatonTheBot 81aa3b769c Android: Update OpenAL to 1.24.3 2025-06-02 21:47:57 -05:00
KeatonTheBot fda90239bc Android fixes and features
* Jit cache eviction (fixes out of memory errors in some games)

* Low power PPTC

* Fix 'unknown' games displayed when using game folder with subfolders

* Turn off NCE and PPTC by default
2025-06-02 21:47:55 -05:00
KeatonTheBot 3af88ad2e6 infra: Remove Ryujinx.Common references from project files that indirectly reference the same file 2025-05-31 02:59:10 -05:00
KeatonTheBot d73be3b927 infra: Fix missing libarmeilleure-jitsupport.dylib on macOS (arm64) builds 2025-05-31 02:59:10 -05:00
KeatonTheBot cc0b704d8e Linux: Fix games not launching (from Bionic code) 2025-05-31 02:59:09 -05:00
MrKev cdd4557343 Fix JWT Claims and Socket Flag Handling to Improve Just Dance® Server Connection 2025-05-31 02:59:09 -05:00
GreemDev e172bdf2eb fix: Super Mario Party Jamboree audio renderer crashing 2025-05-31 02:59:08 -05:00
KeatonTheBot 6e7808a65a ffmpeg: Fix green screen issues on Linux 2025-05-31 02:59:08 -05:00
ChromJ 5a86fb9826 Add Ctrl+Comma shortcut for settings
See merge request kenji-nx/ryujinx!2
2025-05-31 02:59:07 -05:00
KeatonTheBot 45166424fc UI: Fix GitLab logos not showing on git server in Ryujinx.UI.Common\Resources folder due to capitalization error 2025-05-31 02:59:07 -05:00
KeatonTheBot 965c18225b infra: Android: LibHac 0.20.0 code changes 2025-05-30 23:31:49 -05:00
KeatonTheBot 2ea7d32b30 UI: RPC: Add LUNAR Remastered Collection 2025-05-26 21:02:37 -05:00
KeatonTheBot 40cbd19bc3 infra: Update SDL2 to 2.32.6 2025-05-26 21:02:37 -05:00
KeatonTheBot 0255c1f463 nuget: Remove GtkSharp packages 2025-05-26 21:02:36 -05:00
GreemDev 3657e55c70 infra: Update to Ryujinx.LibHac 0.20.0.
This time it's pulled in via GitLab package registry.
2025-05-26 21:02:36 -05:00
KeatonTheBot af3aa8f786 UI: Change the GitHub button in the About window to GitLab 2025-05-26 21:02:35 -05:00
KeatonTheBot 81728f62bb Fix README to point to Android release page 2025-05-26 20:56:31 -05:00
KeatonTheBot a4856f1885 Update README.md and other documents 2025-05-26 18:20:39 -05:00
KeatonTheBot 8fcf430ea8 Merge branch 'libryujinx_bionic' into 'libryujinx_bionic'
Small Kotlin changes

* Use Delegation for KenjinxNative jnaInstance

* rework KenjiNative.updateUiHandler + remove needless companion object

* Small syntactic niceties, general cleanups & code style fixes

See merge request kenji-nx/ryujinx!1
2025-05-23 20:26:17 -05:00
GreemDev fc2f1588d5 Small Kotlin changes
* Use Delegation for KenjinxNative jnaInstance

* rework KenjiNative.updateUiHandler + remove needless companion object

* Small syntactic niceties, general cleanups & code style fixes
2025-05-23 20:26:17 -05:00
KeatonTheBot 6f13e04a24 Switch to mirrored submodules
* Update OpenAL submodule to latest commit
2025-05-17 20:53:45 -05:00
KeatonTheBot 4e669ada26 Bump androidx.compose:compose-bom to 2024.08.00, remove duplicates 2025-05-16 23:42:53 -05:00
KeatonTheBot 575cc233c9 Fix submodules 2025-05-16 23:42:53 -05:00
KeatonTheBot 7a4017d164 Upgrade compileSdk from 34 to 35, bump packages
* androidx.activity:activity-compose to 1.10.1
* androidx.appcompat:appcompat to 1.7.0
* androidx.compose.material:material-icons-extended to 1.7.8
* androidx.constraintlayout:constraintlayout to 2.2.1
* androidx.core:core-ktx to 1.16.0
* androidx.lifecycle:lifecycle-runtime-ktx to 2.9.0
* androidx.navigation:navigation-compose to 2.9.0
* androidx.test.espresso:espresso-core to 3.6.1
* androidx.test.ext:junit to 1.2.1
* br.com.devsrsouza.compose.icons:css-gg to 1.1.1
* com.anggrayudi:storage to 1.5.6
* com.google.code.gson:gson to 2.10.1
* net.java.dev.jna:jna to 5.17.0
2025-05-16 23:42:53 -05:00
KeatonTheBot e8e4c5aa61 Android changes 2025-05-16 23:42:48 -05:00
1166 changed files with 45869 additions and 12954 deletions
+3
View File
@@ -173,3 +173,6 @@ PublishProfiles/
# Glade backup files # Glade backup files
*.glade~ *.glade~
# Log files
/logs/
+9
View File
@@ -0,0 +1,9 @@
[submodule "src/KenjinxAndroid/app/src/main/cpp/libraries/adrenotools"]
path = src/KenjinxAndroid/app/src/main/cpp/libraries/adrenotools
url = https://git.ryujinx.app/kenji-nx/libadrenotools.git
[submodule "src/KenjinxAndroid/app/src/main/cpp/libraries/openal"]
path = src/KenjinxAndroid/app/src/main/cpp/libraries/openal
url = https://git.ryujinx.app/kenji-nx/openal-soft.git
[submodule "src/KenjinxAndroid/app/src/main/cpp/libraries/adrenotools/lib/linkernsbypass"]
path = src/KenjinxAndroid/app/src/main/cpp/libraries/adrenotools/lib/linkernsbypass
url = https://git.ryujinx.app/kenji-nx/liblinkernsbypass.git
+27 -25
View File
@@ -3,52 +3,54 @@
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally> <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageVersion Include="Avalonia" Version="11.3.6" /> <PackageVersion Include="Avalonia" Version="11.3.13" />
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.3.6" /> <PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.3.13" />
<PackageVersion Include="Avalonia.Desktop" Version="11.3.6" /> <PackageVersion Include="Avalonia.Desktop" Version="11.3.13" />
<PackageVersion Include="Avalonia.Diagnostics" Version="11.3.6" /> <PackageVersion Include="Avalonia.Diagnostics" Version="11.3.13" />
<PackageVersion Include="Avalonia.Markup.Xaml.Loader" Version="11.3.6" /> <PackageVersion Include="Avalonia.Markup.Xaml.Loader" Version="11.3.13" />
<PackageVersion Include="Svg.Controls.Avalonia" Version="11.3.6.2" /> <PackageVersion Include="Svg.Controls.Avalonia" Version="11.3.9.5" />
<PackageVersion Include="Svg.Controls.Skia.Avalonia" Version="11.3.6.2" /> <PackageVersion Include="Svg.Controls.Skia.Avalonia" Version="11.3.9.5" />
<PackageVersion Include="CommandLineParser" Version="2.9.1" /> <PackageVersion Include="CommandLineParser" Version="2.9.1" />
<PackageVersion Include="Concentus" Version="2.2.2" /> <PackageVersion Include="Concentus" Version="2.2.2" />
<PackageVersion Include="DiscordRichPresence" Version="1.6.1.70" /> <PackageVersion Include="DiscordRichPresence" Version="1.6.1.70" />
<PackageVersion Include="DynamicData" Version="9.4.1" /> <PackageVersion Include="DynamicData" Version="9.4.31" />
<PackageVersion Include="FluentAvaloniaUI.NoAnim" Version="2.4.0-build2" /> <PackageVersion Include="FluentAvaloniaUI" Version="2.4.1" />
<PackageVersion Include="Gommon" Version="2.7.1.1" /> <PackageVersion Include="Gommon" Version="2.8.1.1" />
<PackageVersion Include="Humanizer" Version="2.14.1" /> <PackageVersion Include="Humanizer" Version="3.0.10" />
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" /> <PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.12.0" /> <PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.12.0" />
<PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.14.0" /> <PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.17.0" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.9.0" /> <PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.3.0" />
<PackageVersion Include="Microsoft.IO.RecyclableMemoryStream" Version="3.0.1" /> <PackageVersion Include="Microsoft.IO.RecyclableMemoryStream" Version="3.0.1" />
<PackageVersion Include="MsgPack.Cli" Version="1.0.1" /> <PackageVersion Include="MsgPack.Cli" Version="1.0.1" />
<PackageVersion Include="NetCoreServer" Version="8.0.7" /> <PackageVersion Include="NetCoreServer" Version="8.0.7" />
<PackageVersion Include="NUnit" Version="3.13.3" /> <PackageVersion Include="Newtonsoft.Json" Version="13.0.4" />
<PackageVersion Include="NUnit3TestAdapter" Version="4.1.0" /> <PackageVersion Include="NUnit" Version="4.5.1" />
<PackageVersion Include="NUnit3TestAdapter" Version="6.2.0" />
<PackageVersion Include="OpenTK.Core" Version="4.9.4" /> <PackageVersion Include="OpenTK.Core" Version="4.9.4" />
<PackageVersion Include="OpenTK.Graphics" Version="4.9.4" /> <PackageVersion Include="OpenTK.Graphics" Version="4.9.4" />
<PackageVersion Include="OpenTK.Audio.OpenAL" Version="4.9.4" /> <PackageVersion Include="OpenTK.Audio.OpenAL" Version="4.9.4" />
<PackageVersion Include="OpenTK.Windowing.GraphicsLibraryFramework" Version="4.9.4" /> <PackageVersion Include="OpenTK.Windowing.GraphicsLibraryFramework" Version="4.9.4" />
<PackageVersion Include="Open.NAT.Core" Version="2.1.0.5" /> <PackageVersion Include="Open.NAT.Core" Version="2.1.0.5" />
<PackageVersion Include="Ryujinx.Audio.OpenAL" Version="1.24.3" /> <PackageVersion Include="Ryujinx.Audio.OpenAL" Version="1.25.2" />
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies.Linux" Version="6.1.3-build5" /> <PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies.Linux" Version="6.1.3-build5" />
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies.macOS" Version="5.0.3-build14" /> <PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies.macOS" Version="5.0.3-build14" />
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies.Windows" Version="6.1.3-build5" /> <PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies.Windows" Version="6.1.3-build5" />
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" /> <PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
<PackageVersion Include="Ryujinx.LibHac" Version="0.21.0-alpha.116" /> <PackageVersion Include="Ryujinx.LibHac" Version="0.21.0-alpha.128" />
<PackageVersion Include="Ryujinx.SDL2-CS-Redux" Version="2.32.10" /> <PackageVersion Include="Ryujinx.SDL3-CS" Version="2026.707.0" />
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" /> <PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
<PackageVersion Include="shaderc.net" Version="0.1.0" />
<PackageVersion Include="SharpZipLib" Version="1.4.2" /> <PackageVersion Include="SharpZipLib" Version="1.4.2" />
<PackageVersion Include="Silk.NET.Vulkan" Version="2.22.0" /> <PackageVersion Include="Silk.NET.Shaderc" Version="2.23.0" />
<PackageVersion Include="Silk.NET.Vulkan.Extensions.EXT" Version="2.22.0" /> <PackageVersion Include="Silk.NET.Vulkan" Version="2.23.0" />
<PackageVersion Include="Silk.NET.Vulkan.Extensions.KHR" Version="2.22.0" /> <PackageVersion Include="Silk.NET.Vulkan.Extensions.EXT" Version="2.23.0" />
<PackageVersion Include="Silk.NET.Vulkan.Extensions.KHR" Version="2.23.0" />
<PackageVersion Include="SkiaSharp" Version="2.88.9" /> <PackageVersion Include="SkiaSharp" Version="2.88.9" />
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="2.88.9" /> <PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="2.88.9" />
<PackageVersion Include="SPB" Version="0.0.4-build32" /> <PackageVersion Include="SPB" Version="0.0.4-build32" />
<PackageVersion Include="System.IO.Hashing" Version="9.0.9" /> <PackageVersion Include="System.IO.Hashing" Version="9.0.12" />
<PackageVersion Include="System.Management" Version="9.0.9" /> <PackageVersion Include="System.Management" Version="9.0.12" />
<PackageVersion Include="UnicornEngine.Unicorn" Version="2.1.3" /> <PackageVersion Include="UnicornEngine.Unicorn" Version="2.1.0" />
<PackageVersion Include="Rxmxnx.PInvoke.Extensions" Version="2.9.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>
+15 -20
View File
@@ -1,31 +1,26 @@
<h1 align="center"> <h1 align="center">
<br> <br>
<img src="https://git.ryujinx.app/kenji-nx/ryujinx/-/raw/master/distribution/misc/Logo.png" alt="Kenji-NX"> <img src="https://git.ryujinx.app/projects/Kenji-NX/raw/branch/master/distribution/misc/Logo.png" alt="Kenji-NX">
<br> <br>
<b>Kenji-NX</b> <b>Kenji-NX</b>
<br> <br>
<a href="https://github.com/Kenji-NX/Releases/releases/latest">
<img src="https://img.shields.io/github/v/release/Kenji-NX/Releases" [![Latest Desktop Release](https://git.ryujinx.app/projects/Kenji-NX/badges/release.svg?label=desktop)](https://git.ryujinx.app/projects/Kenji-NX/releases/latest)
alt="Latest Release"> [![Latest Android Release](https://git.ryujinx.app/Kenji-NX/android/badges/release.svg?label=android)](https://git.ryujinx.app/Kenji-NX/android/releases/latest)
</a> <br>
[![Discord](https://img.shields.io/discord/1294443224030511104?color=5865F2&label=Kenji-NX&logo=discord&logoColor=white)](https://discord.gg/zBSAuZfKqe)
</h1> </h1>
<p>
Kenji-NX is an open-source Nintendo Switch emulator, originally created by gdkchan, written in C#. Kenji-NX is an open-source Nintendo Switch emulator, originally created by gdkchan, written in C#.
This emulator aims at providing excellent accuracy and performance, a user-friendly interface and consistent builds. This emulator aims at providing excellent accuracy and performance, a user-friendly interface and consistent builds.
It was written from scratch and development on the project began in September 2017. It was written from scratch and development on the project began in September 2017.
Kenji-NX is available on GitHub under the <a href="https://git.ryujinx.app/kenji-nx/ryujinx/-/raw/master/LICENSE.txt" target="_blank">MIT license</a>. Kenji-NX is available on GitHub under the [MIT license](LICENSE.txt).
<br><br>
On October 1st 2024, Ryujinx was discontinued as the creator was forced to abandon the project.
<br><br>
This fork is not a Ryujinx revival project; it aims to be a middle ground between GreemDev's <a href="https://git.ryujinx.app/ryubing/ryujinx">Ryujinx</a> fork and the more preservative <a href="https://git.ryujinx.app/archive/ryujinx-mirror">ryujinx-mirror</a> fork.
It brings over many of the front-facing features from the aforementioned forks with <i>additional</i> contributions from KeatonTheBot and others.
<br>
</p>
<p> On October 1st 2024, Ryujinx was discontinued as the creator was forced to abandon the project.
<img src="docs/shell.png">
</p> This fork is not a Ryujinx revival project; it aims to be a middle ground between GreemDev's [Ryujinx](https://git.ryujinx.app/projects/Ryubing) fork and the more preservative [ryujinx-mirror](https://git.ryujinx.app/archive/ryujinx-mirror) fork.
It brings over many of the front-facing features from the aforementioned forks with *additional* contributions from KeatonTheBot and others.
## Compatibility ## Compatibility
@@ -58,12 +53,12 @@ If you wish to build the emulator yourself, follow these steps:
### Step 1 ### Step 1
Install the [.NET 9.0 (or higher) SDK](https://dotnet.microsoft.com/download/dotnet/9.0). Install the [.NET 10.0 (or higher) SDK](https://dotnet.microsoft.com/download/dotnet/10.0).
Make sure your SDK version is higher or equal to the required version specified in [global.json](global.json). Make sure your SDK version is higher or equal to the required version specified in [global.json](global.json).
### Step 2 ### Step 2
Either use `git clone https://git.ryujinx.app/kenji-nx/ryujinx` on the command line to clone the repository or use Code --> Download zip button to get the files. Either use `git clone https://git.ryujinx.app/projects/Kenji-NX` on the command line to clone the repository or use Code --> Download zip button to get the files.
### Step 3 ### Step 3
@@ -125,7 +120,7 @@ See [LICENSE.txt](LICENSE.txt) and [THIRDPARTY.md](distribution/legal/THIRDPARTY
## Credits ## Credits
- [LibHac](https://github.com/Thealexbarney/LibHac) is used for our file-system. - [LibHac](https://git.ryujinx.app/projects/LibHac) is used for our file-system.
- [AmiiboAPI](https://www.amiiboapi.com) is used in our Amiibo emulation. - [AmiiboAPI](https://www.amiiboapi.com) is used in our Amiibo emulation.
- [ldn_mitm](https://github.com/spacemeowx2/ldn_mitm) is used for one of our available multiplayer modes. - [ldn_mitm](https://github.com/spacemeowx2/ldn_mitm) is used for one of our available multiplayer modes.
- [ShellLink](https://github.com/securifybv/ShellLink) is used for Windows shortcut generation. - [ShellLink](https://github.com/securifybv/ShellLink) is used for Windows shortcut generation.
+8
View File
@@ -5,6 +5,8 @@ VisualStudioVersion = 17.1.32228.430
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Tests", "src\Ryujinx.Tests\Ryujinx.Tests.csproj", "{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Tests", "src\Ryujinx.Tests\Ryujinx.Tests.csproj", "{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LibKenjinx", "src\LibKenjinx\LibKenjinx.csproj", "{AF58C1D5-DE16-429B-B155-7CE83B4E8FA6}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Tests.Unicorn", "src\Ryujinx.Tests.Unicorn\Ryujinx.Tests.Unicorn.csproj", "{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Tests.Unicorn", "src\Ryujinx.Tests.Unicorn\Ryujinx.Tests.Unicorn.csproj", "{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.HLE", "src\Ryujinx.HLE\Ryujinx.HLE.csproj", "{CB92CFF9-1D62-4D4F-9E88-8130EF61E351}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.HLE", "src\Ryujinx.HLE\Ryujinx.HLE.csproj", "{CB92CFF9-1D62-4D4F-9E88-8130EF61E351}"
@@ -32,7 +34,9 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{36F870C1-3E5F-485F-B426-F0645AF78751}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{36F870C1-3E5F-485F-B426-F0645AF78751}"
ProjectSection(SolutionItems) = preProject ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig .editorconfig = .editorconfig
Directory.Build.props = Directory.Build.props
Directory.Packages.props = Directory.Packages.props Directory.Packages.props = Directory.Packages.props
nuget.config = nuget.config
EndProjectSection EndProjectSection
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Memory", "src\Ryujinx.Memory\Ryujinx.Memory.csproj", "{A5E6C691-9E22-4263-8F40-42F002CE66BE}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Memory", "src\Ryujinx.Memory\Ryujinx.Memory.csproj", "{A5E6C691-9E22-4263-8F40-42F002CE66BE}"
@@ -95,6 +99,10 @@ Global
{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Debug|Any CPU.Build.0 = Debug|Any CPU {EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Release|Any CPU.ActiveCfg = Release|Any CPU {EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Release|Any CPU.Build.0 = Release|Any CPU {EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Release|Any CPU.Build.0 = Release|Any CPU
{AF58C1D5-DE16-429B-B155-7CE83B4E8FA6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AF58C1D5-DE16-429B-B155-7CE83B4E8FA6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AF58C1D5-DE16-429B-B155-7CE83B4E8FA6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AF58C1D5-DE16-429B-B155-7CE83B4E8FA6}.Release|Any CPU.Build.0 = Release|Any CPU
{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}.Debug|Any CPU.Build.0 = Debug|Any CPU {D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}.Release|Any CPU.ActiveCfg = Release|Any CPU {D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}.Release|Any CPU.ActiveCfg = Release|Any CPU
+47
View File
@@ -0,0 +1,47 @@
<Solution>
<Folder Name="/Solution Items/">
<File Path=".editorconfig" />
<File Path="Directory.Build.props" />
<File Path="Directory.Packages.props" />
<File Path="nuget.config" />
</Folder>
<Project Path="src/ARMeilleure/ARMeilleure.csproj" />
<Project Path="src/LibKenjinx/LibKenjinx.csproj" />
<Project Path="src/Ryujinx.Audio.Backends.OpenAL/Ryujinx.Audio.Backends.OpenAL.csproj" />
<Project Path="src/Ryujinx.Audio.Backends.SDL3/Ryujinx.Audio.Backends.SDL3.csproj" />
<Project Path="src/Ryujinx.Audio.Backends.SoundIo/Ryujinx.Audio.Backends.SoundIo.csproj" />
<Project Path="src/Ryujinx.Audio/Ryujinx.Audio.csproj" />
<Project Path="src/Ryujinx.Common/Ryujinx.Common.csproj" />
<Project Path="src/Ryujinx.Cpu/Ryujinx.Cpu.csproj" />
<Project Path="src/Ryujinx.Graphics.Device/Ryujinx.Graphics.Device.csproj" />
<Project Path="src/Ryujinx.Graphics.GAL/Ryujinx.Graphics.GAL.csproj" />
<Project Path="src/Ryujinx.Graphics.Gpu/Ryujinx.Graphics.Gpu.csproj" />
<Project Path="src/Ryujinx.Graphics.Host1x/Ryujinx.Graphics.Host1x.csproj" />
<Project Path="src/Ryujinx.Graphics.Nvdec.FFmpeg/Ryujinx.Graphics.Nvdec.FFmpeg.csproj" />
<Project Path="src/Ryujinx.Graphics.Nvdec.Vp9/Ryujinx.Graphics.Nvdec.Vp9.csproj" />
<Project Path="src/Ryujinx.Graphics.Nvdec/Ryujinx.Graphics.Nvdec.csproj" />
<Project Path="src/Ryujinx.Graphics.OpenGL/Ryujinx.Graphics.OpenGL.csproj" />
<Project Path="src/Ryujinx.Graphics.Shader/Ryujinx.Graphics.Shader.csproj" />
<Project Path="src/Ryujinx.Graphics.Texture/Ryujinx.Graphics.Texture.csproj" />
<Project Path="src/Ryujinx.Graphics.Vic/Ryujinx.Graphics.Vic.csproj" />
<Project Path="src/Ryujinx.Graphics.Video/Ryujinx.Graphics.Video.csproj" />
<Project Path="src/Ryujinx.Graphics.Vulkan/Ryujinx.Graphics.Vulkan.csproj" />
<Project Path="src/Ryujinx.HLE.Generators/Ryujinx.HLE.Generators.csproj" />
<Project Path="src/Ryujinx.HLE/Ryujinx.HLE.csproj" />
<Project Path="src/Ryujinx.Horizon.Common/Ryujinx.Horizon.Common.csproj" />
<Project Path="src/Ryujinx.Horizon.Generators/Ryujinx.Horizon.Generators.csproj" />
<Project Path="src/Ryujinx.Horizon.Kernel.Generators/Ryujinx.Horizon.Kernel.Generators.csproj" />
<Project Path="src/Ryujinx.Horizon/Ryujinx.Horizon.csproj" />
<Project Path="src/Ryujinx.Input.SDL3/Ryujinx.Input.SDL3.csproj" />
<Project Path="src/Ryujinx.Input/Ryujinx.Input.csproj" />
<Project Path="src/Ryujinx.Memory/Ryujinx.Memory.csproj" />
<Project Path="src/Ryujinx.SDL3.Common/Ryujinx.SDL3.Common.csproj" />
<Project Path="src/Ryujinx.ShaderTools/Ryujinx.ShaderTools.csproj" />
<Project Path="src/Ryujinx.Tests.Memory/Ryujinx.Tests.Memory.csproj" />
<Project Path="src/Ryujinx.Tests.Unicorn/Ryujinx.Tests.Unicorn.csproj" />
<Project Path="src/Ryujinx.Tests/Ryujinx.Tests.csproj" />
<Project Path="src/Ryujinx.UI.Common/Ryujinx.UI.Common.csproj" />
<Project Path="src/Ryujinx.UI.LocaleGenerator/Ryujinx.UI.LocaleGenerator.csproj" />
<Project Path="src/Ryujinx/Ryujinx.csproj" />
<Project Path="src/Spv.Generator/Spv.Generator.csproj" />
</Solution>
+1 -1
View File
@@ -8,7 +8,7 @@ Intro to Kenji-NX
Kenji-NX is an open-source Nintendo Switch emulator written in C#. It is based on Ryujinx, which was originally created by gdkchan. Kenji-NX is an open-source Nintendo Switch emulator written in C#. It is based on Ryujinx, which was originally created by gdkchan.
* The CPU emulator, ARMeilleure, emulates an ARMv8 CPU and currently has support for most 64-bit ARMv8 and some of the ARMv7 (and older) instructions. * The CPU emulator, ARMeilleure, emulates an ARMv8 CPU and currently has support for most 64-bit ARMv8 and some of the ARMv7 (and older) instructions.
* The GPU emulator emulates the Switch's Maxwell GPU using either the OpenGL (version 4.5 minimum), Vulkan, or Metal (via MoltenVK) APIs through a custom build of OpenTK or Silk.NET respectively. * The GPU emulator emulates the Switch's Maxwell GPU using either the OpenGL (version 4.5 minimum), Vulkan, or Metal (via MoltenVK) APIs through a custom build of OpenTK or Silk.NET respectively.
* Audio output is entirely supported via C# wrappers for SDL2, with OpenAL & libsoundio as fallbacks. * Audio output is entirely supported via C# wrappers for SDL3, with OpenAL & libsoundio as fallbacks.
Getting Started Getting Started
=============== ===============
+5 -1
View File
@@ -4,7 +4,8 @@
<clear /> <clear />
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" /> <add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
<!-- Only needed when using pre-release versions of Ryujinx.LibHac. --> <!-- Only needed when using pre-release versions of Ryujinx.LibHac. -->
<add key="LibHacAlpha" value="https://git.ryujinx.app/api/v4/projects/17/packages/nuget/index.json" /> <add key="LibHacAlpha" value="https://git.ryujinx.app/api/packages/projects/nuget/index.json" />
<!--<add key="Silk.NET" value="https://gitlab.com/api/v4/projects/51457475/packages/nuget/index.json" />-->
</packageSources> </packageSources>
<packageSourceMapping> <packageSourceMapping>
<!-- key value for <packageSource> should match key values from <packageSources> element --> <!-- key value for <packageSource> should match key values from <packageSources> element -->
@@ -15,5 +16,8 @@
<packageSource key="LibHacAlpha"> <packageSource key="LibHacAlpha">
<package pattern="Ryujinx.LibHac" /> <package pattern="Ryujinx.LibHac" />
</packageSource> </packageSource>
<!--<packageSource key="Silk.NET">
<package pattern="Silk.*" />
</packageSource>-->
</packageSourceMapping> </packageSourceMapping>
</configuration> </configuration>
@@ -13,13 +13,13 @@ namespace ARMeilleure.CodeGen.Arm64
public static void RunPass(ControlFlowGraph cfg) public static void RunPass(ControlFlowGraph cfg)
{ {
var constants = new Dictionary<ulong, Operand>(); Dictionary<ulong, Operand> constants = new();
Operand GetConstantCopy(BasicBlock block, Operation operation, Operand source) Operand GetConstantCopy(BasicBlock block, Operation operation, Operand source)
{ {
// If the constant has many uses, we also force a new constant mov to be added, in order // If the constant has many uses, we also force a new constant mov to be added, in order
// to avoid overflow of the counts field (that is limited to 16 bits). // to avoid overflow of the counts field (that is limited to 16 bits).
if (!constants.TryGetValue(source.Value, out var constant) || constant.UsesCount > MaxConstantUses) if (!constants.TryGetValue(source.Value, out Operand constant) || constant.UsesCount > MaxConstantUses)
{ {
constant = Local(source.Type); constant = Local(source.Type);
+1 -1
View File
@@ -123,7 +123,7 @@ namespace ARMeilleure.CodeGen.Arm64
public void Cset(Operand rd, ArmCondition condition) public void Cset(Operand rd, ArmCondition condition)
{ {
var zr = Factory.Register(ZrRegister, RegisterType.Integer, rd.Type); Operand zr = Factory.Register(ZrRegister, RegisterType.Integer, rd.Type);
Csinc(rd, zr, zr, (ArmCondition)((int)condition ^ 1)); Csinc(rd, zr, zr, (ArmCondition)((int)condition ^ 1));
} }
@@ -91,7 +91,7 @@ namespace ARMeilleure.CodeGen.Arm64
long target = _stream.Position; long target = _stream.Position;
if (_pendingBranches.TryGetValue(block, out var list)) if (_pendingBranches.TryGetValue(block, out List<(ArmCondition Condition, long BranchPos)> list))
{ {
foreach ((ArmCondition condition, long branchPos) in list) foreach ((ArmCondition condition, long branchPos) in list)
{ {
@@ -119,7 +119,7 @@ namespace ARMeilleure.CodeGen.Arm64
} }
else else
{ {
if (!_pendingBranches.TryGetValue(target, out var list)) if (!_pendingBranches.TryGetValue(target, out List<(ArmCondition Condition, long BranchPos)> list))
{ {
list = new List<(ArmCondition, long)>(); list = new List<(ArmCondition, long)>();
_pendingBranches.Add(target, list); _pendingBranches.Add(target, list);
@@ -321,7 +321,7 @@ namespace ARMeilleure.CodeGen.Arm64
Debug.Assert(comp.Kind == OperandKind.Constant); Debug.Assert(comp.Kind == OperandKind.Constant);
var cond = ((Comparison)comp.AsInt32()).ToArmCondition(); ArmCondition cond = ((Comparison)comp.AsInt32()).ToArmCondition();
GenerateCompareCommon(context, operation); GenerateCompareCommon(context, operation);
@@ -353,7 +353,7 @@ namespace ARMeilleure.CodeGen.Arm64
Debug.Assert(dest.Type == OperandType.I32); Debug.Assert(dest.Type == OperandType.I32);
Debug.Assert(comp.Kind == OperandKind.Constant); Debug.Assert(comp.Kind == OperandKind.Constant);
var cond = ((Comparison)comp.AsInt32()).ToArmCondition(); ArmCondition cond = ((Comparison)comp.AsInt32()).ToArmCondition();
GenerateCompareCommon(context, operation); GenerateCompareCommon(context, operation);
@@ -127,13 +127,13 @@ namespace ARMeilleure.CodeGen.Arm64
#region macOS #region macOS
[LibraryImport("libSystem.dylib", SetLastError = true)] [LibraryImport("libSystem.dylib", SetLastError = true)]
private static unsafe partial int sysctlbyname([MarshalAs(UnmanagedType.LPStr)] string name, out int oldValue, ref ulong oldSize, IntPtr newValue, ulong newValueSize); private static unsafe partial int sysctlbyname([MarshalAs(UnmanagedType.LPStr)] string name, out int oldValue, ref ulong oldSize, nint newValue, ulong newValueSize);
[SupportedOSPlatform("macos")] [SupportedOSPlatform("macos")]
private static bool CheckSysctlName(string name) private static bool CheckSysctlName(string name)
{ {
ulong size = sizeof(int); ulong size = sizeof(int);
if (sysctlbyname(name, out int val, ref size, IntPtr.Zero, 0) == 0 && size == sizeof(int)) if (sysctlbyname(name, out int val, ref size, nint.Zero, 0) == 0 && size == sizeof(int))
{ {
return val != 0; return val != 0;
} }
@@ -847,7 +847,7 @@ namespace ARMeilleure.CodeGen.Arm64
Debug.Assert(comp.Kind == OperandKind.Constant); Debug.Assert(comp.Kind == OperandKind.Constant);
var compType = (Comparison)comp.AsInt32(); Comparison compType = (Comparison)comp.AsInt32();
return compType is Comparison.Equal or Comparison.NotEqual; return compType is Comparison.Equal or Comparison.NotEqual;
} }
+1 -2
View File
@@ -1,7 +1,6 @@
using ARMeilleure.CodeGen.Linking; using ARMeilleure.CodeGen.Linking;
using ARMeilleure.CodeGen.Unwinding; using ARMeilleure.CodeGen.Unwinding;
using ARMeilleure.Translation.Cache; using ARMeilleure.Translation.Cache;
using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace ARMeilleure.CodeGen namespace ARMeilleure.CodeGen
@@ -58,7 +57,7 @@ namespace ARMeilleure.CodeGen
/// <typeparam name="T">Type of delegate</typeparam> /// <typeparam name="T">Type of delegate</typeparam>
/// <param name="codePointer">Pointer to the function code in memory</param> /// <param name="codePointer">Pointer to the function code in memory</param>
/// <returns>A delegate of type <typeparamref name="T"/> pointing to the mapped function</returns> /// <returns>A delegate of type <typeparamref name="T"/> pointing to the mapped function</returns>
public T MapWithPointer<T>(out IntPtr codePointer) public T MapWithPointer<T>(out nint codePointer)
{ {
codePointer = JitCache.Map(this); codePointer = JitCache.Map(this);
@@ -115,7 +115,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{ {
NumberLocals(cfg, regMasks.RegistersCount); NumberLocals(cfg, regMasks.RegistersCount);
var context = new AllocationContext(stackAlloc, regMasks, _intervals.Count); AllocationContext context = new(stackAlloc, regMasks, _intervals.Count);
BuildIntervals(cfg, context); BuildIntervals(cfg, context);
@@ -387,7 +387,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
public override int GetHashCode() public override int GetHashCode()
{ {
return HashCode.Combine((IntPtr)_data); return HashCode.Combine((nint)_data);
} }
public override string ToString() public override string ToString()
@@ -15,12 +15,12 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{ {
if (_count + 1 > _capacity) if (_count + 1 > _capacity)
{ {
var oldSpan = Span; Span<LiveInterval> oldSpan = Span;
_capacity = Math.Max(4, _capacity * 2); _capacity = Math.Max(4, _capacity * 2);
_items = Allocators.References.Allocate<LiveInterval>((uint)_capacity); _items = Allocators.References.Allocate<LiveInterval>((uint)_capacity);
var newSpan = Span; Span<LiveInterval> newSpan = Span;
oldSpan.CopyTo(newSpan); oldSpan.CopyTo(newSpan);
} }
@@ -63,7 +63,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
public override int GetHashCode() public override int GetHashCode()
{ {
return HashCode.Combine((IntPtr)_data); return HashCode.Combine((nint)_data);
} }
public override string ToString() public override string ToString()
@@ -16,12 +16,12 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{ {
if (Count + 1 > _capacity) if (Count + 1 > _capacity)
{ {
var oldSpan = Span; Span<int> oldSpan = Span;
_capacity = Math.Max(4, _capacity * 2); _capacity = Math.Max(4, _capacity * 2);
_items = Allocators.Default.Allocate<int>((uint)_capacity); _items = Allocators.Default.Allocate<int>((uint)_capacity);
var newSpan = Span; Span<int> newSpan = Span;
oldSpan.CopyTo(newSpan); oldSpan.CopyTo(newSpan);
} }
+11 -10
View File
@@ -1,5 +1,6 @@
using ARMeilleure.CodeGen.Linking; using ARMeilleure.CodeGen.Linking;
using ARMeilleure.IntermediateRepresentation; using ARMeilleure.IntermediateRepresentation;
using Microsoft.IO;
using Ryujinx.Common.Memory; using Ryujinx.Common.Memory;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@@ -1106,17 +1107,17 @@ namespace ARMeilleure.CodeGen.X86
} }
else else
{ {
if (flags.HasFlag(InstructionFlags.Prefix66)) if ((flags & InstructionFlags.Prefix66) != 0)
{ {
WriteByte(0x66); WriteByte(0x66);
} }
if (flags.HasFlag(InstructionFlags.PrefixF2)) if ((flags & InstructionFlags.PrefixF2) != 0f)
{ {
WriteByte(0xf2); WriteByte(0xf2);
} }
if (flags.HasFlag(InstructionFlags.PrefixF3)) if ((flags & InstructionFlags.PrefixF3) != 0f)
{ {
WriteByte(0xf3); WriteByte(0xf3);
} }
@@ -1324,8 +1325,8 @@ namespace ARMeilleure.CodeGen.X86
public (byte[], RelocInfo) GetCode() public (byte[], RelocInfo) GetCode()
{ {
var jumps = CollectionsMarshal.AsSpan(_jumps); Span<Jump> jumps = CollectionsMarshal.AsSpan(_jumps);
var relocs = CollectionsMarshal.AsSpan(_relocs); Span<Reloc> relocs = CollectionsMarshal.AsSpan(_relocs);
// Write jump relative offsets. // Write jump relative offsets.
bool modified; bool modified;
@@ -1410,13 +1411,13 @@ namespace ARMeilleure.CodeGen.X86
// Write the code, ignoring the dummy bytes after jumps, into a new stream. // Write the code, ignoring the dummy bytes after jumps, into a new stream.
_stream.Seek(0, SeekOrigin.Begin); _stream.Seek(0, SeekOrigin.Begin);
using var codeStream = MemoryStreamManager.Shared.GetStream(); using RecyclableMemoryStream codeStream = MemoryStreamManager.Shared.GetStream();
var assembler = new Assembler(codeStream, HasRelocs); Assembler assembler = new(codeStream, HasRelocs);
bool hasRelocs = HasRelocs; bool hasRelocs = HasRelocs;
int relocIndex = 0; int relocIndex = 0;
int relocOffset = 0; int relocOffset = 0;
var relocEntries = hasRelocs RelocEntry[] relocEntries = hasRelocs
? new RelocEntry[relocs.Length] ? new RelocEntry[relocs.Length]
: Array.Empty<RelocEntry>(); : Array.Empty<RelocEntry>();
@@ -1469,8 +1470,8 @@ namespace ARMeilleure.CodeGen.X86
_stream.CopyTo(codeStream); _stream.CopyTo(codeStream);
var code = codeStream.ToArray(); byte[] code = codeStream.ToArray();
var relocInfo = new RelocInfo(relocEntries); RelocInfo relocInfo = new(relocEntries);
return (code, relocInfo); return (code, relocInfo);
} }
+2 -2
View File
@@ -622,7 +622,7 @@ namespace ARMeilleure.CodeGen.X86
Debug.Assert(comp.Kind == OperandKind.Constant); Debug.Assert(comp.Kind == OperandKind.Constant);
var cond = ((Comparison)comp.AsInt32()).ToX86Condition(); X86Condition cond = ((Comparison)comp.AsInt32()).ToX86Condition();
GenerateCompareCommon(context, operation); GenerateCompareCommon(context, operation);
@@ -660,7 +660,7 @@ namespace ARMeilleure.CodeGen.X86
Debug.Assert(dest.Type == OperandType.I32); Debug.Assert(dest.Type == OperandType.I32);
Debug.Assert(comp.Kind == OperandKind.Constant); Debug.Assert(comp.Kind == OperandKind.Constant);
var cond = ((Comparison)comp.AsInt32()).ToX86Condition(); X86Condition cond = ((Comparison)comp.AsInt32()).ToX86Condition();
GenerateCompareCommon(context, operation); GenerateCompareCommon(context, operation);
@@ -53,7 +53,7 @@ namespace ARMeilleure.CodeGen.X86
memGetXcr0.Reprotect(0, (ulong)asmGetXcr0.Length, MemoryPermission.ReadAndExecute); memGetXcr0.Reprotect(0, (ulong)asmGetXcr0.Length, MemoryPermission.ReadAndExecute);
var fGetXcr0 = Marshal.GetDelegateForFunctionPointer<GetXcr0>(memGetXcr0.Pointer); GetXcr0 fGetXcr0 = Marshal.GetDelegateForFunctionPointer<GetXcr0>(memGetXcr0.Pointer);
return fGetXcr0(); return fGetXcr0();
} }
+1 -1
View File
@@ -759,7 +759,7 @@ namespace ARMeilleure.CodeGen.X86
Debug.Assert(comp.Kind == OperandKind.Constant); Debug.Assert(comp.Kind == OperandKind.Constant);
var compType = (Comparison)comp.AsInt32(); Comparison compType = (Comparison)comp.AsInt32();
return compType is Comparison.Equal or Comparison.NotEqual; return compType is Comparison.Equal or Comparison.NotEqual;
} }
+2 -2
View File
@@ -13,13 +13,13 @@ namespace ARMeilleure.CodeGen.X86
public static void RunPass(ControlFlowGraph cfg) public static void RunPass(ControlFlowGraph cfg)
{ {
var constants = new Dictionary<ulong, Operand>(); Dictionary<ulong, Operand> constants = new();
Operand GetConstantCopy(BasicBlock block, Operation operation, Operand source) Operand GetConstantCopy(BasicBlock block, Operation operation, Operand source)
{ {
// If the constant has many uses, we also force a new constant mov to be added, in order // If the constant has many uses, we also force a new constant mov to be added, in order
// to avoid overflow of the counts field (that is limited to 16 bits). // to avoid overflow of the counts field (that is limited to 16 bits).
if (!constants.TryGetValue(source.Value, out var constant) || constant.UsesCount > MaxConstantUses) if (!constants.TryGetValue(source.Value, out Operand constant) || constant.UsesCount > MaxConstantUses)
{ {
constant = Local(source.Type); constant = Local(source.Type);
+4 -4
View File
@@ -20,7 +20,7 @@ namespace ARMeilleure.Common
private List<PageInfo> _pages; private List<PageInfo> _pages;
private readonly ulong _pageSize; private readonly ulong _pageSize;
private readonly uint _pageCount; private readonly uint _pageCount;
private readonly List<IntPtr> _extras; private readonly List<nint> _extras;
public ArenaAllocator(uint pageSize, uint pageCount) public ArenaAllocator(uint pageSize, uint pageCount)
{ {
@@ -64,7 +64,7 @@ namespace ARMeilleure.Common
{ {
void* extra = NativeAllocator.Instance.Allocate(size); void* extra = NativeAllocator.Instance.Allocate(size);
_extras.Add((IntPtr)extra); _extras.Add((nint)extra);
return extra; return extra;
} }
@@ -114,7 +114,7 @@ namespace ARMeilleure.Common
} }
// Free extra blocks that are not page-sized // Free extra blocks that are not page-sized
foreach (IntPtr ptr in _extras) foreach (nint ptr in _extras)
{ {
NativeAllocator.Instance.Free((void*)ptr); NativeAllocator.Instance.Free((void*)ptr);
} }
@@ -173,7 +173,7 @@ namespace ARMeilleure.Common
NativeAllocator.Instance.Free(info.Pointer); NativeAllocator.Instance.Free(info.Pointer);
} }
foreach (IntPtr ptr in _extras) foreach (nint ptr in _extras)
{ {
NativeAllocator.Instance.Free((void*)ptr); NativeAllocator.Instance.Free((void*)ptr);
} }
+3 -3
View File
@@ -129,13 +129,13 @@ namespace ARMeilleure.Common
if (count > _count) if (count > _count)
{ {
var oldMask = _masks; long* oldMask = _masks;
var oldSpan = new Span<long>(_masks, _count); Span<long> oldSpan = new(_masks, _count);
_masks = _allocator.Allocate<long>((uint)count); _masks = _allocator.Allocate<long>((uint)count);
_count = count; _count = count;
var newSpan = new Span<long>(_masks, _count); Span<long> newSpan = new(_masks, _count);
oldSpan.CopyTo(newSpan); oldSpan.CopyTo(newSpan);
newSpan[oldSpan.Length..].Clear(); newSpan[oldSpan.Length..].Clear();
+8 -8
View File
@@ -15,7 +15,7 @@ namespace ARMeilleure.Common
private int _freeHint; private int _freeHint;
private readonly int _pageCapacity; // Number of entries per page. private readonly int _pageCapacity; // Number of entries per page.
private readonly int _pageLogCapacity; private readonly int _pageLogCapacity;
private readonly Dictionary<int, IntPtr> _pages; private readonly Dictionary<int, nint> _pages;
private readonly BitMap _allocated; private readonly BitMap _allocated;
/// <summary> /// <summary>
@@ -41,7 +41,7 @@ namespace ARMeilleure.Common
} }
_allocated = new BitMap(NativeAllocator.Instance); _allocated = new BitMap(NativeAllocator.Instance);
_pages = new Dictionary<int, IntPtr>(); _pages = new Dictionary<int, nint>();
_pageLogCapacity = BitOperations.Log2((uint)(pageSize / sizeof(TEntry))); _pageLogCapacity = BitOperations.Log2((uint)(pageSize / sizeof(TEntry)));
_pageCapacity = 1 << _pageLogCapacity; _pageCapacity = 1 << _pageLogCapacity;
} }
@@ -63,7 +63,7 @@ namespace ARMeilleure.Common
} }
int index = _freeHint++; int index = _freeHint++;
var page = GetPage(index); Span<TEntry> page = GetPage(index);
_allocated.Set(index); _allocated.Set(index);
@@ -111,7 +111,7 @@ namespace ARMeilleure.Common
throw new ArgumentException("Entry at the specified index was not allocated", nameof(index)); throw new ArgumentException("Entry at the specified index was not allocated", nameof(index));
} }
var page = GetPage(index); Span<TEntry> page = GetPage(index);
return ref GetValue(page, index); return ref GetValue(page, index);
} }
@@ -136,11 +136,11 @@ namespace ARMeilleure.Common
/// <returns>Page for the specified <see cref="index"/></returns> /// <returns>Page for the specified <see cref="index"/></returns>
private unsafe Span<TEntry> GetPage(int index) private unsafe Span<TEntry> GetPage(int index)
{ {
var pageIndex = (int)((uint)(index & ~(_pageCapacity - 1)) >> _pageLogCapacity); int pageIndex = (int)((uint)(index & ~(_pageCapacity - 1)) >> _pageLogCapacity);
if (!_pages.TryGetValue(pageIndex, out IntPtr page)) if (!_pages.TryGetValue(pageIndex, out nint page))
{ {
page = (IntPtr)NativeAllocator.Instance.Allocate((uint)sizeof(TEntry) * (uint)_pageCapacity); page = (nint)NativeAllocator.Instance.Allocate((uint)sizeof(TEntry) * (uint)_pageCapacity);
_pages.Add(pageIndex, page); _pages.Add(pageIndex, page);
} }
@@ -168,7 +168,7 @@ namespace ARMeilleure.Common
{ {
_allocated.Dispose(); _allocated.Dispose();
foreach (var page in _pages.Values) foreach (IntPtr page in _pages.Values)
{ {
NativeAllocator.Instance.Free((void*)page); NativeAllocator.Instance.Free((void*)page);
} }
+2 -2
View File
@@ -9,7 +9,7 @@ namespace ARMeilleure.Common
public override void* Allocate(ulong size) public override void* Allocate(ulong size)
{ {
void* result = (void*)Marshal.AllocHGlobal((IntPtr)size); void* result = (void*)Marshal.AllocHGlobal((nint)size);
if (result == null) if (result == null)
{ {
@@ -21,7 +21,7 @@ namespace ARMeilleure.Common
public override void Free(void* block) public override void Free(void* block)
{ {
Marshal.FreeHGlobal((IntPtr)block); Marshal.FreeHGlobal((nint)block);
} }
} }
} }
@@ -9,7 +9,7 @@ namespace ARMeilleure.Decoders
public OpCode32SimdDupElem(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb) public OpCode32SimdDupElem(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
{ {
var opc = (opCode >> 16) & 0xf; int opc = (opCode >> 16) & 0xf;
if ((opc & 0b1) == 1) if ((opc & 0b1) == 1)
{ {
@@ -21,7 +21,7 @@ namespace ARMeilleure.Decoders
Op = (opCode >> 20) & 0x1; Op = (opCode >> 20) & 0x1;
U = ((opCode >> 23) & 1) != 0; U = ((opCode >> 23) & 1) != 0;
var opc = (((opCode >> 23) & 1) << 4) | (((opCode >> 21) & 0x3) << 2) | ((opCode >> 5) & 0x3); int opc = (((opCode >> 23) & 1) << 4) | (((opCode >> 21) & 0x3) << 2) | ((opCode >> 5) & 0x3);
if ((opc & 0b01000) == 0b01000) if ((opc & 0b01000) == 0b01000)
{ {
+1 -1
View File
@@ -20,7 +20,7 @@ namespace ARMeilleure.Decoders
} }
else if (DataOp == DataOp.Logical) else if (DataOp == DataOp.Logical)
{ {
var bm = DecoderHelper.DecodeBitMask(opCode, true); DecoderHelper.BitMask bm = DecoderHelper.DecodeBitMask(opCode, true);
if (bm.IsUndefined) if (bm.IsUndefined)
{ {
+1 -1
View File
@@ -11,7 +11,7 @@ namespace ARMeilleure.Decoders
public OpCodeBfm(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCodeBfm(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{ {
var bm = DecoderHelper.DecodeBitMask(opCode, false); DecoderHelper.BitMask bm = DecoderHelper.DecodeBitMask(opCode, false);
if (bm.IsUndefined) if (bm.IsUndefined)
{ {
@@ -69,7 +69,7 @@ namespace ARMeilleure.Decoders.Optimizations
} }
} }
var newBlocks = new List<Block>(blocks.Count); List<Block> newBlocks = new(blocks.Count);
// Finally, rebuild decoded block list, ignoring blocks outside the contiguous range. // Finally, rebuild decoded block list, ignoring blocks outside the contiguous range.
for (int i = 0; i < blocks.Count; i++) for (int i = 0; i < blocks.Count; i++)
+2 -2
View File
@@ -141,7 +141,7 @@ namespace ARMeilleure.Diagnostics
break; break;
case OperandKind.Memory: case OperandKind.Memory:
var memOp = operand.GetMemory(); MemoryOperand memOp = operand.GetMemory();
_builder.Append('['); _builder.Append('[');
@@ -284,7 +284,7 @@ namespace ARMeilleure.Diagnostics
public static string GetDump(ControlFlowGraph cfg) public static string GetDump(ControlFlowGraph cfg)
{ {
var dumper = new IRDumper(1); IRDumper dumper = new(1);
for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext) for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext)
{ {
@@ -415,7 +415,7 @@ namespace ARMeilleure.Instructions
{ {
IOpCode32AluBf op = (IOpCode32AluBf)context.CurrOp; IOpCode32AluBf op = (IOpCode32AluBf)context.CurrOp;
var msb = op.Lsb + op.Msb; // For this instruction, the msb is actually a width. int msb = op.Lsb + op.Msb; // For this instruction, the msb is actually a width.
Operand n = GetIntA32(context, op.Rn); Operand n = GetIntA32(context, op.Rn);
Operand res = context.ShiftRightSI(context.ShiftLeft(n, Const(31 - msb)), Const(31 - op.Msb)); Operand res = context.ShiftRightSI(context.ShiftLeft(n, Const(31 - msb)), Const(31 - op.Msb));
@@ -547,7 +547,7 @@ namespace ARMeilleure.Instructions
{ {
IOpCode32AluBf op = (IOpCode32AluBf)context.CurrOp; IOpCode32AluBf op = (IOpCode32AluBf)context.CurrOp;
var msb = op.Lsb + op.Msb; // For this instruction, the msb is actually a width. int msb = op.Lsb + op.Msb; // For this instruction, the msb is actually a width.
Operand n = GetIntA32(context, op.Rn); Operand n = GetIntA32(context, op.Rn);
Operand res = context.ShiftRightUI(context.ShiftLeft(n, Const(31 - msb)), Const(31 - op.Msb)); Operand res = context.ShiftRightUI(context.ShiftLeft(n, Const(31 - msb)), Const(31 - op.Msb));
@@ -1,4 +1,5 @@
using ARMeilleure.CodeGen.Linking; using ARMeilleure.CodeGen.Linking;
using ARMeilleure.Common;
using ARMeilleure.Decoders; using ARMeilleure.Decoders;
using ARMeilleure.IntermediateRepresentation; using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.State; using ARMeilleure.State;
@@ -146,12 +147,6 @@ namespace ARMeilleure.Instructions
public static void EmitCall(ArmEmitterContext context, ulong immediate) public static void EmitCall(ArmEmitterContext context, ulong immediate)
{ {
if (context.IsSingleStep)
{
context.Return(Const(immediate));
return;
}
bool isRecursive = immediate == context.EntryAddress; bool isRecursive = immediate == context.EntryAddress;
if (isRecursive) if (isRecursive)
@@ -165,25 +160,13 @@ namespace ARMeilleure.Instructions
} }
public static void EmitVirtualCall(ArmEmitterContext context, Operand target) public static void EmitVirtualCall(ArmEmitterContext context, Operand target)
{
if (context.IsSingleStep)
{
if (target.Type == OperandType.I32)
{
target = context.ZeroExtend32(OperandType.I64, target);
}
context.Return(target);
}
else
{ {
EmitTableBranch(context, target, isJump: false); EmitTableBranch(context, target, isJump: false);
} }
}
public static void EmitVirtualJump(ArmEmitterContext context, Operand target, bool isReturn) public static void EmitVirtualJump(ArmEmitterContext context, Operand target, bool isReturn)
{ {
if (isReturn || context.IsSingleStep) if (isReturn)
{ {
EmitReturn(context, target); EmitReturn(context, target);
} }
@@ -223,7 +206,7 @@ namespace ARMeilleure.Instructions
Operand hostAddress; Operand hostAddress;
var table = context.FunctionTable; IAddressTable<ulong> table = context.FunctionTable;
// If address is mapped onto the function table, we can skip the table walk. Otherwise we fallback // If address is mapped onto the function table, we can skip the table walk. Otherwise we fallback
// onto the dispatch stub. // onto the dispatch stub.
@@ -248,7 +231,7 @@ namespace ARMeilleure.Instructions
for (int i = 0; i < table.Levels.Length; i++) for (int i = 0; i < table.Levels.Length; i++)
{ {
var level = table.Levels[i]; AddressTableLevel level = table.Levels[i];
int clearBits = 64 - (level.Index + level.Length); int clearBits = 64 - (level.Index + level.Length);
Operand index = context.ShiftLeft( Operand index = context.ShiftLeft(
@@ -143,8 +143,8 @@ namespace ARMeilleure.Instructions
Operand address = context.Copy(GetIntA32(context, op.Rn)); Operand address = context.Copy(GetIntA32(context, op.Rn));
var exclusive = (accType & AccessType.Exclusive) != 0; bool exclusive = (accType & AccessType.Exclusive) != 0;
var ordered = (accType & AccessType.Ordered) != 0; bool ordered = (accType & AccessType.Ordered) != 0;
if ((accType & AccessType.Load) != 0) if ((accType & AccessType.Load) != 0)
{ {
@@ -229,7 +229,7 @@ namespace ARMeilleure.Instructions
private static Operand ZerosOrOnes(ArmEmitterContext context, Operand fromBool, OperandType baseType) private static Operand ZerosOrOnes(ArmEmitterContext context, Operand fromBool, OperandType baseType)
{ {
var ones = (baseType == OperandType.I64) ? Const(-1L) : Const(-1); Operand ones = (baseType == OperandType.I64) ? Const(-1L) : Const(-1);
return context.ConditionalSelect(fromBool, ones, Const(baseType, 0L)); return context.ConditionalSelect(fromBool, ones, Const(baseType, 0L));
} }
@@ -118,15 +118,15 @@ namespace ARMeilleure.Instructions
{ {
OpCode32SimdCvtFFixed op = (OpCode32SimdCvtFFixed)context.CurrOp; OpCode32SimdCvtFFixed op = (OpCode32SimdCvtFFixed)context.CurrOp;
var toFixed = op.Opc == 1; bool toFixed = op.Opc == 1;
int fracBits = op.Fbits; int fracBits = op.Fbits;
var unsigned = op.U; bool unsigned = op.U;
if (toFixed) // F32 to S32 or U32 (fixed) if (toFixed) // F32 to S32 or U32 (fixed)
{ {
EmitVectorUnaryOpF32(context, (op1) => EmitVectorUnaryOpF32(context, (op1) =>
{ {
var scaledValue = context.Multiply(op1, ConstF(MathF.Pow(2f, fracBits))); Operand scaledValue = context.Multiply(op1, ConstF(MathF.Pow(2f, fracBits)));
MethodInfo info = unsigned ? typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToU32)) : typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToS32)); MethodInfo info = unsigned ? typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToU32)) : typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToS32));
return context.Call(info, scaledValue); return context.Call(info, scaledValue);
@@ -136,7 +136,7 @@ namespace ARMeilleure.Instructions
{ {
EmitVectorUnaryOpI32(context, (op1) => EmitVectorUnaryOpI32(context, (op1) =>
{ {
var floatValue = unsigned ? context.ConvertToFPUI(OperandType.FP32, op1) : context.ConvertToFP(OperandType.FP32, op1); Operand floatValue = unsigned ? context.ConvertToFPUI(OperandType.FP32, op1) : context.ConvertToFP(OperandType.FP32, op1);
return context.Multiply(floatValue, ConstF(1f / MathF.Pow(2f, fracBits))); return context.Multiply(floatValue, ConstF(1f / MathF.Pow(2f, fracBits)));
}, !unsigned); }, !unsigned);
@@ -87,7 +87,7 @@ namespace ARMeilleure.Instructions
{ {
if (op.Replicate) if (op.Replicate)
{ {
var regs = (count > 1) ? 1 : op.Increment; int regs = (count > 1) ? 1 : op.Increment;
for (int reg = 0; reg < regs; reg++) for (int reg = 0; reg < regs; reg++)
{ {
int dreg = reg + d; int dreg = reg + d;
@@ -1,35 +1,59 @@
using System; using System;
#if ANDROID
using System.Runtime.CompilerServices;
#else
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
#endif
namespace ARMeilleure.Instructions namespace ARMeilleure.Instructions
{ {
static class MathHelper static class MathHelper
{ {
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static double Abs(double value) public static double Abs(double value)
{ {
return Math.Abs(value); return Math.Abs(value);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static double Ceiling(double value) public static double Ceiling(double value)
{ {
return Math.Ceiling(value); return Math.Ceiling(value);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static double Floor(double value) public static double Floor(double value)
{ {
return Math.Floor(value); return Math.Floor(value);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static double Round(double value, int mode) public static double Round(double value, int mode)
{ {
return Math.Round(value, (MidpointRounding)mode); return Math.Round(value, (MidpointRounding)mode);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static double Truncate(double value) public static double Truncate(double value)
{ {
return Math.Truncate(value); return Math.Truncate(value);
@@ -38,31 +62,51 @@ namespace ARMeilleure.Instructions
static class MathHelperF static class MathHelperF
{ {
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static float Abs(float value) public static float Abs(float value)
{ {
return MathF.Abs(value); return MathF.Abs(value);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static float Ceiling(float value) public static float Ceiling(float value)
{ {
return MathF.Ceiling(value); return MathF.Ceiling(value);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static float Floor(float value) public static float Floor(float value)
{ {
return MathF.Floor(value); return MathF.Floor(value);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static float Round(float value, int mode) public static float Round(float value, int mode)
{ {
return MathF.Round(value, (MidpointRounding)mode); return MathF.Round(value, (MidpointRounding)mode);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static float Truncate(float value) public static float Truncate(float value)
{ {
return MathF.Truncate(value); return MathF.Truncate(value);
+100 -4
View File
@@ -2,7 +2,11 @@ using ARMeilleure.Memory;
using ARMeilleure.State; using ARMeilleure.State;
using ARMeilleure.Translation; using ARMeilleure.Translation;
using System; using System;
#if ANDROID
using System.Runtime.CompilerServices;
#else
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
#endif
namespace ARMeilleure.Instructions namespace ARMeilleure.Instructions
{ {
@@ -35,7 +39,11 @@ namespace ARMeilleure.Instructions
Context = null; Context = null;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static void Break(ulong address, int imm) public static void Break(ulong address, int imm)
{ {
Statistics.PauseTimer(); Statistics.PauseTimer();
@@ -45,7 +53,11 @@ namespace ARMeilleure.Instructions
Statistics.ResumeTimer(); Statistics.ResumeTimer();
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static void SupervisorCall(ulong address, int imm) public static void SupervisorCall(ulong address, int imm)
{ {
Statistics.PauseTimer(); Statistics.PauseTimer();
@@ -55,7 +67,11 @@ namespace ARMeilleure.Instructions
Statistics.ResumeTimer(); Statistics.ResumeTimer();
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static void Undefined(ulong address, int opCode) public static void Undefined(ulong address, int opCode)
{ {
Statistics.PauseTimer(); Statistics.PauseTimer();
@@ -66,31 +82,51 @@ namespace ARMeilleure.Instructions
} }
#region "System registers" #region "System registers"
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static ulong GetCtrEl0() public static ulong GetCtrEl0()
{ {
return GetContext().CtrEl0; return GetContext().CtrEl0;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static ulong GetDczidEl0() public static ulong GetDczidEl0()
{ {
return GetContext().DczidEl0; return GetContext().DczidEl0;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static ulong GetCntfrqEl0() public static ulong GetCntfrqEl0()
{ {
return GetContext().CntfrqEl0; return GetContext().CntfrqEl0;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static ulong GetCntpctEl0() public static ulong GetCntpctEl0()
{ {
return GetContext().CntpctEl0; return GetContext().CntpctEl0;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static ulong GetCntvctEl0() public static ulong GetCntvctEl0()
{ {
return GetContext().CntvctEl0; return GetContext().CntvctEl0;
@@ -98,31 +134,51 @@ namespace ARMeilleure.Instructions
#endregion #endregion
#region "Read" #region "Read"
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static byte ReadByte(ulong address) public static byte ReadByte(ulong address)
{ {
return GetMemoryManager().ReadGuest<byte>(address); return GetMemoryManager().ReadGuest<byte>(address);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static ushort ReadUInt16(ulong address) public static ushort ReadUInt16(ulong address)
{ {
return GetMemoryManager().ReadGuest<ushort>(address); return GetMemoryManager().ReadGuest<ushort>(address);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static uint ReadUInt32(ulong address) public static uint ReadUInt32(ulong address)
{ {
return GetMemoryManager().ReadGuest<uint>(address); return GetMemoryManager().ReadGuest<uint>(address);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static ulong ReadUInt64(ulong address) public static ulong ReadUInt64(ulong address)
{ {
return GetMemoryManager().ReadGuest<ulong>(address); return GetMemoryManager().ReadGuest<ulong>(address);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static V128 ReadVector128(ulong address) public static V128 ReadVector128(ulong address)
{ {
return GetMemoryManager().ReadGuest<V128>(address); return GetMemoryManager().ReadGuest<V128>(address);
@@ -130,56 +186,92 @@ namespace ARMeilleure.Instructions
#endregion #endregion
#region "Write" #region "Write"
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static void WriteByte(ulong address, byte value) public static void WriteByte(ulong address, byte value)
{ {
GetMemoryManager().WriteGuest(address, value); GetMemoryManager().WriteGuest(address, value);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static void WriteUInt16(ulong address, ushort value) public static void WriteUInt16(ulong address, ushort value)
{ {
GetMemoryManager().WriteGuest(address, value); GetMemoryManager().WriteGuest(address, value);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static void WriteUInt32(ulong address, uint value) public static void WriteUInt32(ulong address, uint value)
{ {
GetMemoryManager().WriteGuest(address, value); GetMemoryManager().WriteGuest(address, value);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static void WriteUInt64(ulong address, ulong value) public static void WriteUInt64(ulong address, ulong value)
{ {
GetMemoryManager().WriteGuest(address, value); GetMemoryManager().WriteGuest(address, value);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static void WriteVector128(ulong address, V128 value) public static void WriteVector128(ulong address, V128 value)
{ {
GetMemoryManager().WriteGuest(address, value); GetMemoryManager().WriteGuest(address, value);
} }
#endregion #endregion
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static void EnqueueForRejit(ulong address) public static void EnqueueForRejit(ulong address)
{ {
Context.Translator.EnqueueForRejit(address, GetContext().ExecutionMode); Context.Translator.EnqueueForRejit(address, GetContext().ExecutionMode);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static void SignalMemoryTracking(ulong address, ulong size, byte write) public static void SignalMemoryTracking(ulong address, ulong size, byte write)
{ {
GetMemoryManager().SignalMemoryTracking(address, size, write == 1); GetMemoryManager().SignalMemoryTracking(address, size, write == 1);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static void ThrowInvalidMemoryAccess(ulong address) public static void ThrowInvalidMemoryAccess(ulong address)
{ {
throw new InvalidAccessException(address); throw new InvalidAccessException(address);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static ulong GetFunctionAddress(ulong address) public static ulong GetFunctionAddress(ulong address)
{ {
TranslatedFunction function = Context.Translator.GetOrTranslate(address, GetContext().ExecutionMode); TranslatedFunction function = Context.Translator.GetOrTranslate(address, GetContext().ExecutionMode);
@@ -187,24 +279,28 @@ namespace ARMeilleure.Instructions
return (ulong)function.FuncPointer.ToInt64(); return (ulong)function.FuncPointer.ToInt64();
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static void InvalidateCacheLine(ulong address) public static void InvalidateCacheLine(ulong address)
{ {
Context.Translator.InvalidateJitCacheRegion(address, InstEmit.DczSizeInBytes); Context.Translator.InvalidateJitCacheRegion(address, InstEmit.DczSizeInBytes);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static byte CheckSynchronization() public static byte CheckSynchronization()
{ {
Statistics.PauseTimer(); Statistics.PauseTimer();
ExecutionContext context = GetContext(); ExecutionContext context = GetContext();
// If debugging, we'll handle interrupts outside
if (!Optimizations.EnableDebugging)
{
context.CheckInterrupt(); context.CheckInterrupt();
}
Statistics.ResumeTimer(); Statistics.ResumeTimer();
@@ -1,13 +1,21 @@
using ARMeilleure.State; using ARMeilleure.State;
using System; using System;
#if ANDROID
using System.Runtime.CompilerServices;
#else
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
#endif
namespace ARMeilleure.Instructions namespace ARMeilleure.Instructions
{ {
static class SoftFallback static class SoftFallback
{ {
#region "ShrImm64" #region "ShrImm64"
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static long SignedShrImm64(long value, long roundConst, int shift) public static long SignedShrImm64(long value, long roundConst, int shift)
{ {
if (roundConst == 0L) if (roundConst == 0L)
@@ -50,7 +58,11 @@ namespace ARMeilleure.Instructions
} }
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static ulong UnsignedShrImm64(ulong value, long roundConst, int shift) public static ulong UnsignedShrImm64(ulong value, long roundConst, int shift)
{ {
if (roundConst == 0L) if (roundConst == 0L)
@@ -95,7 +107,11 @@ namespace ARMeilleure.Instructions
#endregion #endregion
#region "Saturation" #region "Saturation"
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static int SatF32ToS32(float value) public static int SatF32ToS32(float value)
{ {
if (float.IsNaN(value)) if (float.IsNaN(value))
@@ -107,7 +123,11 @@ namespace ARMeilleure.Instructions
value <= int.MinValue ? int.MinValue : (int)value; value <= int.MinValue ? int.MinValue : (int)value;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static long SatF32ToS64(float value) public static long SatF32ToS64(float value)
{ {
if (float.IsNaN(value)) if (float.IsNaN(value))
@@ -119,7 +139,11 @@ namespace ARMeilleure.Instructions
value <= long.MinValue ? long.MinValue : (long)value; value <= long.MinValue ? long.MinValue : (long)value;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static uint SatF32ToU32(float value) public static uint SatF32ToU32(float value)
{ {
if (float.IsNaN(value)) if (float.IsNaN(value))
@@ -131,7 +155,11 @@ namespace ARMeilleure.Instructions
value <= uint.MinValue ? uint.MinValue : (uint)value; value <= uint.MinValue ? uint.MinValue : (uint)value;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static ulong SatF32ToU64(float value) public static ulong SatF32ToU64(float value)
{ {
if (float.IsNaN(value)) if (float.IsNaN(value))
@@ -143,7 +171,11 @@ namespace ARMeilleure.Instructions
value <= ulong.MinValue ? ulong.MinValue : (ulong)value; value <= ulong.MinValue ? ulong.MinValue : (ulong)value;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static int SatF64ToS32(double value) public static int SatF64ToS32(double value)
{ {
if (double.IsNaN(value)) if (double.IsNaN(value))
@@ -155,7 +187,11 @@ namespace ARMeilleure.Instructions
value <= int.MinValue ? int.MinValue : (int)value; value <= int.MinValue ? int.MinValue : (int)value;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static long SatF64ToS64(double value) public static long SatF64ToS64(double value)
{ {
if (double.IsNaN(value)) if (double.IsNaN(value))
@@ -167,7 +203,11 @@ namespace ARMeilleure.Instructions
value <= long.MinValue ? long.MinValue : (long)value; value <= long.MinValue ? long.MinValue : (long)value;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static uint SatF64ToU32(double value) public static uint SatF64ToU32(double value)
{ {
if (double.IsNaN(value)) if (double.IsNaN(value))
@@ -179,7 +219,11 @@ namespace ARMeilleure.Instructions
value <= uint.MinValue ? uint.MinValue : (uint)value; value <= uint.MinValue ? uint.MinValue : (uint)value;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static ulong SatF64ToU64(double value) public static ulong SatF64ToU64(double value)
{ {
if (double.IsNaN(value)) if (double.IsNaN(value))
@@ -193,7 +237,11 @@ namespace ARMeilleure.Instructions
#endregion #endregion
#region "Count" #region "Count"
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static ulong CountLeadingSigns(ulong value, int size) // size is 8, 16, 32 or 64 (SIMD&FP or Base Inst.). public static ulong CountLeadingSigns(ulong value, int size) // size is 8, 16, 32 or 64 (SIMD&FP or Base Inst.).
{ {
value ^= value >> 1; value ^= value >> 1;
@@ -213,7 +261,11 @@ namespace ARMeilleure.Instructions
private static ReadOnlySpan<byte> ClzNibbleTbl => [4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]; private static ReadOnlySpan<byte> ClzNibbleTbl => [4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0];
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static ulong CountLeadingZeros(ulong value, int size) // size is 8, 16, 32 or 64 (SIMD&FP or Base Inst.). public static ulong CountLeadingZeros(ulong value, int size) // size is 8, 16, 32 or 64 (SIMD&FP or Base Inst.).
{ {
if (value == 0ul) if (value == 0ul)
@@ -237,49 +289,81 @@ namespace ARMeilleure.Instructions
#endregion #endregion
#region "Table" #region "Table"
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static V128 Tbl1(V128 vector, int bytes, V128 tb0) public static V128 Tbl1(V128 vector, int bytes, V128 tb0)
{ {
return TblOrTbx(default, vector, bytes, tb0); return TblOrTbx(default, vector, bytes, tb0);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static V128 Tbl2(V128 vector, int bytes, V128 tb0, V128 tb1) public static V128 Tbl2(V128 vector, int bytes, V128 tb0, V128 tb1)
{ {
return TblOrTbx(default, vector, bytes, tb0, tb1); return TblOrTbx(default, vector, bytes, tb0, tb1);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static V128 Tbl3(V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2) public static V128 Tbl3(V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2)
{ {
return TblOrTbx(default, vector, bytes, tb0, tb1, tb2); return TblOrTbx(default, vector, bytes, tb0, tb1, tb2);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static V128 Tbl4(V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2, V128 tb3) public static V128 Tbl4(V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2, V128 tb3)
{ {
return TblOrTbx(default, vector, bytes, tb0, tb1, tb2, tb3); return TblOrTbx(default, vector, bytes, tb0, tb1, tb2, tb3);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static V128 Tbx1(V128 dest, V128 vector, int bytes, V128 tb0) public static V128 Tbx1(V128 dest, V128 vector, int bytes, V128 tb0)
{ {
return TblOrTbx(dest, vector, bytes, tb0); return TblOrTbx(dest, vector, bytes, tb0);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static V128 Tbx2(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1) public static V128 Tbx2(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1)
{ {
return TblOrTbx(dest, vector, bytes, tb0, tb1); return TblOrTbx(dest, vector, bytes, tb0, tb1);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static V128 Tbx3(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2) public static V128 Tbx3(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2)
{ {
return TblOrTbx(dest, vector, bytes, tb0, tb1, tb2); return TblOrTbx(dest, vector, bytes, tb0, tb1, tb2);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static V128 Tbx4(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2, V128 tb3) public static V128 Tbx4(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2, V128 tb3)
{ {
return TblOrTbx(dest, vector, bytes, tb0, tb1, tb2, tb3); return TblOrTbx(dest, vector, bytes, tb0, tb1, tb2, tb3);
@@ -321,22 +405,54 @@ namespace ARMeilleure.Instructions
private const uint Crc32RevPoly = 0xedb88320; private const uint Crc32RevPoly = 0xedb88320;
private const uint Crc32cRevPoly = 0x82f63b78; private const uint Crc32cRevPoly = 0x82f63b78;
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static uint Crc32b(uint crc, byte value) => Crc32(crc, Crc32RevPoly, value); public static uint Crc32b(uint crc, byte value) => Crc32(crc, Crc32RevPoly, value);
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static uint Crc32h(uint crc, ushort value) => Crc32h(crc, Crc32RevPoly, value); public static uint Crc32h(uint crc, ushort value) => Crc32h(crc, Crc32RevPoly, value);
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static uint Crc32w(uint crc, uint value) => Crc32w(crc, Crc32RevPoly, value); public static uint Crc32w(uint crc, uint value) => Crc32w(crc, Crc32RevPoly, value);
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static uint Crc32x(uint crc, ulong value) => Crc32x(crc, Crc32RevPoly, value); public static uint Crc32x(uint crc, ulong value) => Crc32x(crc, Crc32RevPoly, value);
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static uint Crc32cb(uint crc, byte value) => Crc32(crc, Crc32cRevPoly, value); public static uint Crc32cb(uint crc, byte value) => Crc32(crc, Crc32cRevPoly, value);
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static uint Crc32ch(uint crc, ushort value) => Crc32h(crc, Crc32cRevPoly, value); public static uint Crc32ch(uint crc, ushort value) => Crc32h(crc, Crc32cRevPoly, value);
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static uint Crc32cw(uint crc, uint value) => Crc32w(crc, Crc32cRevPoly, value); public static uint Crc32cw(uint crc, uint value) => Crc32w(crc, Crc32cRevPoly, value);
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static uint Crc32cx(uint crc, ulong value) => Crc32x(crc, Crc32cRevPoly, value); public static uint Crc32cx(uint crc, ulong value) => Crc32x(crc, Crc32cRevPoly, value);
private static uint Crc32h(uint crc, uint poly, ushort val) private static uint Crc32h(uint crc, uint poly, ushort val)
@@ -387,25 +503,41 @@ namespace ARMeilleure.Instructions
#endregion #endregion
#region "Aes" #region "Aes"
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static V128 Decrypt(V128 value, V128 roundKey) public static V128 Decrypt(V128 value, V128 roundKey)
{ {
return CryptoHelper.AesInvSubBytes(CryptoHelper.AesInvShiftRows(value ^ roundKey)); return CryptoHelper.AesInvSubBytes(CryptoHelper.AesInvShiftRows(value ^ roundKey));
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static V128 Encrypt(V128 value, V128 roundKey) public static V128 Encrypt(V128 value, V128 roundKey)
{ {
return CryptoHelper.AesSubBytes(CryptoHelper.AesShiftRows(value ^ roundKey)); return CryptoHelper.AesSubBytes(CryptoHelper.AesShiftRows(value ^ roundKey));
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static V128 InverseMixColumns(V128 value) public static V128 InverseMixColumns(V128 value)
{ {
return CryptoHelper.AesInvMixColumns(value); return CryptoHelper.AesInvMixColumns(value);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static V128 MixColumns(V128 value) public static V128 MixColumns(V128 value)
{ {
return CryptoHelper.AesMixColumns(value); return CryptoHelper.AesMixColumns(value);
@@ -413,7 +545,11 @@ namespace ARMeilleure.Instructions
#endregion #endregion
#region "Sha1" #region "Sha1"
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static V128 HashChoose(V128 hash_abcd, uint hash_e, V128 wk) public static V128 HashChoose(V128 hash_abcd, uint hash_e, V128 wk)
{ {
for (int e = 0; e <= 3; e++) for (int e = 0; e <= 3; e++)
@@ -434,13 +570,21 @@ namespace ARMeilleure.Instructions
return hash_abcd; return hash_abcd;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static uint FixedRotate(uint hash_e) public static uint FixedRotate(uint hash_e)
{ {
return hash_e.Rol(30); return hash_e.Rol(30);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static V128 HashMajority(V128 hash_abcd, uint hash_e, V128 wk) public static V128 HashMajority(V128 hash_abcd, uint hash_e, V128 wk)
{ {
for (int e = 0; e <= 3; e++) for (int e = 0; e <= 3; e++)
@@ -461,7 +605,11 @@ namespace ARMeilleure.Instructions
return hash_abcd; return hash_abcd;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static V128 HashParity(V128 hash_abcd, uint hash_e, V128 wk) public static V128 HashParity(V128 hash_abcd, uint hash_e, V128 wk)
{ {
for (int e = 0; e <= 3; e++) for (int e = 0; e <= 3; e++)
@@ -482,7 +630,11 @@ namespace ARMeilleure.Instructions
return hash_abcd; return hash_abcd;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static V128 Sha1SchedulePart1(V128 w0_3, V128 w4_7, V128 w8_11) public static V128 Sha1SchedulePart1(V128 w0_3, V128 w4_7, V128 w8_11)
{ {
ulong t2 = w4_7.Extract<ulong>(0); ulong t2 = w4_7.Extract<ulong>(0);
@@ -493,7 +645,11 @@ namespace ARMeilleure.Instructions
return result ^ (w0_3 ^ w8_11); return result ^ (w0_3 ^ w8_11);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static V128 Sha1SchedulePart2(V128 tw0_3, V128 w12_15) public static V128 Sha1SchedulePart2(V128 tw0_3, V128 w12_15)
{ {
V128 t = tw0_3 ^ (w12_15 >> 32); V128 t = tw0_3 ^ (w12_15 >> 32);
@@ -538,19 +694,31 @@ namespace ARMeilleure.Instructions
#endregion #endregion
#region "Sha256" #region "Sha256"
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static V128 HashLower(V128 hash_abcd, V128 hash_efgh, V128 wk) public static V128 HashLower(V128 hash_abcd, V128 hash_efgh, V128 wk)
{ {
return Sha256Hash(hash_abcd, hash_efgh, wk, part1: true); return Sha256Hash(hash_abcd, hash_efgh, wk, part1: true);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static V128 HashUpper(V128 hash_abcd, V128 hash_efgh, V128 wk) public static V128 HashUpper(V128 hash_abcd, V128 hash_efgh, V128 wk)
{ {
return Sha256Hash(hash_abcd, hash_efgh, wk, part1: false); return Sha256Hash(hash_abcd, hash_efgh, wk, part1: false);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static V128 Sha256SchedulePart1(V128 w0_3, V128 w4_7) public static V128 Sha256SchedulePart1(V128 w0_3, V128 w4_7)
{ {
V128 result = new(); V128 result = new();
@@ -569,7 +737,11 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static V128 Sha256SchedulePart2(V128 w0_3, V128 w8_11, V128 w12_15) public static V128 Sha256SchedulePart2(V128 w0_3, V128 w8_11, V128 w12_15)
{ {
V128 result = new(); V128 result = new();
@@ -671,7 +843,11 @@ namespace ARMeilleure.Instructions
} }
#endregion #endregion
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static V128 PolynomialMult64_128(ulong op1, ulong op2) public static V128 PolynomialMult64_128(ulong op1, ulong op2)
{ {
V128 result = V128.Zero; V128 result = V128.Zero;
+358 -2
View File
@@ -1,7 +1,11 @@
using ARMeilleure.State; using ARMeilleure.State;
using System; using System;
using System.Diagnostics; using System.Diagnostics;
#if ANDROID
using System.Runtime.CompilerServices;
#else
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
#endif
namespace ARMeilleure.Instructions namespace ARMeilleure.Instructions
{ {
@@ -313,7 +317,11 @@ namespace ARMeilleure.Instructions
static class SoftFloat16_32 static class SoftFloat16_32
{ {
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static float FPConvert(ushort valueBits) public static float FPConvert(ushort valueBits)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
@@ -489,7 +497,11 @@ namespace ARMeilleure.Instructions
static class SoftFloat16_64 static class SoftFloat16_64
{ {
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static double FPConvert(ushort valueBits) public static double FPConvert(ushort valueBits)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
@@ -665,7 +677,11 @@ namespace ARMeilleure.Instructions
static class SoftFloat32_16 static class SoftFloat32_16
{ {
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static ushort FPConvert(float value) public static ushort FPConvert(float value)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
@@ -785,13 +801,21 @@ namespace ARMeilleure.Instructions
static class SoftFloat32 static class SoftFloat32
{ {
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static float FPAdd(float value1, float value2) public static float FPAdd(float value1, float value2)
{ {
return FPAddFpscrImpl(value1, value2, false); return FPAddFpscrImpl(value1, value2, false);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static float FPAddFpscr(float value1, float value2, byte standardFpscr) public static float FPAddFpscr(float value1, float value2, byte standardFpscr)
{ {
return FPAddFpscrImpl(value1, value2, standardFpscr == 1); return FPAddFpscrImpl(value1, value2, standardFpscr == 1);
@@ -848,7 +872,11 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static int FPCompare(float value1, float value2, byte signalNaNs) public static int FPCompare(float value1, float value2, byte signalNaNs)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
@@ -887,7 +915,11 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static float FPCompareEQ(float value1, float value2) public static float FPCompareEQ(float value1, float value2)
{ {
return FPCompareEQFpscrImpl(value1, value2, false); return FPCompareEQFpscrImpl(value1, value2, false);
@@ -920,19 +952,31 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static float FPCompareEQFpscr(float value1, float value2, byte standardFpscr) public static float FPCompareEQFpscr(float value1, float value2, byte standardFpscr)
{ {
return FPCompareEQFpscrImpl(value1, value2, standardFpscr == 1); return FPCompareEQFpscrImpl(value1, value2, standardFpscr == 1);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static float FPCompareGE(float value1, float value2) public static float FPCompareGE(float value1, float value2)
{ {
return FPCompareGEFpscrImpl(value1, value2, false); return FPCompareGEFpscrImpl(value1, value2, false);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static float FPCompareGEFpscr(float value1, float value2, byte standardFpscr) public static float FPCompareGEFpscr(float value1, float value2, byte standardFpscr)
{ {
return FPCompareGEFpscrImpl(value1, value2, standardFpscr == 1); return FPCompareGEFpscrImpl(value1, value2, standardFpscr == 1);
@@ -962,13 +1006,21 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static float FPCompareGT(float value1, float value2) public static float FPCompareGT(float value1, float value2)
{ {
return FPCompareGTFpscrImpl(value1, value2, false); return FPCompareGTFpscrImpl(value1, value2, false);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static float FPCompareGTFpscr(float value1, float value2, byte standardFpscr) public static float FPCompareGTFpscr(float value1, float value2, byte standardFpscr)
{ {
return FPCompareGTFpscrImpl(value1, value2, standardFpscr == 1); return FPCompareGTFpscrImpl(value1, value2, standardFpscr == 1);
@@ -998,31 +1050,51 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static float FPCompareLE(float value1, float value2) public static float FPCompareLE(float value1, float value2)
{ {
return FPCompareGEFpscrImpl(value2, value1, false); return FPCompareGEFpscrImpl(value2, value1, false);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static float FPCompareLT(float value1, float value2) public static float FPCompareLT(float value1, float value2)
{ {
return FPCompareGTFpscrImpl(value2, value1, false); return FPCompareGTFpscrImpl(value2, value1, false);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static float FPCompareLEFpscr(float value1, float value2, byte standardFpscr) public static float FPCompareLEFpscr(float value1, float value2, byte standardFpscr)
{ {
return FPCompareGEFpscrImpl(value2, value1, standardFpscr == 1); return FPCompareGEFpscrImpl(value2, value1, standardFpscr == 1);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static float FPCompareLTFpscr(float value1, float value2, byte standardFpscr) public static float FPCompareLTFpscr(float value1, float value2, byte standardFpscr)
{ {
return FPCompareGEFpscrImpl(value2, value1, standardFpscr == 1); return FPCompareGEFpscrImpl(value2, value1, standardFpscr == 1);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static float FPDiv(float value1, float value2) public static float FPDiv(float value1, float value2)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
@@ -1075,13 +1147,21 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static float FPMax(float value1, float value2) public static float FPMax(float value1, float value2)
{ {
return FPMaxFpscrImpl(value1, value2, false); return FPMaxFpscrImpl(value1, value2, false);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static float FPMaxFpscr(float value1, float value2, byte standardFpscr) public static float FPMaxFpscr(float value1, float value2, byte standardFpscr)
{ {
return FPMaxFpscrImpl(value1, value2, standardFpscr == 1); return FPMaxFpscrImpl(value1, value2, standardFpscr == 1);
@@ -1148,7 +1228,11 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static float FPMaxNum(float value1, float value2) public static float FPMaxNum(float value1, float value2)
{ {
return FPMaxNumFpscrImpl(value1, value2, false); return FPMaxNumFpscrImpl(value1, value2, false);
@@ -1174,19 +1258,31 @@ namespace ARMeilleure.Instructions
return FPMaxFpscrImpl(value1, value2, standardFpscr); return FPMaxFpscrImpl(value1, value2, standardFpscr);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static float FPMaxNumFpscr(float value1, float value2, byte standardFpscr) public static float FPMaxNumFpscr(float value1, float value2, byte standardFpscr)
{ {
return FPMaxNumFpscrImpl(value1, value2, standardFpscr == 1); return FPMaxNumFpscrImpl(value1, value2, standardFpscr == 1);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static float FPMin(float value1, float value2) public static float FPMin(float value1, float value2)
{ {
return FPMinFpscrImpl(value1, value2, false); return FPMinFpscrImpl(value1, value2, false);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static float FPMinFpscr(float value1, float value2, byte standardFpscr) public static float FPMinFpscr(float value1, float value2, byte standardFpscr)
{ {
return FPMinFpscrImpl(value1, value2, standardFpscr == 1); return FPMinFpscrImpl(value1, value2, standardFpscr == 1);
@@ -1253,13 +1349,21 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static float FPMinNum(float value1, float value2) public static float FPMinNum(float value1, float value2)
{ {
return FPMinNumFpscrImpl(value1, value2, false); return FPMinNumFpscrImpl(value1, value2, false);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static float FPMinNumFpscr(float value1, float value2, byte standardFpscr) public static float FPMinNumFpscr(float value1, float value2, byte standardFpscr)
{ {
return FPMinNumFpscrImpl(value1, value2, standardFpscr == 1); return FPMinNumFpscrImpl(value1, value2, standardFpscr == 1);
@@ -1285,13 +1389,21 @@ namespace ARMeilleure.Instructions
return FPMinFpscrImpl(value1, value2, standardFpscr); return FPMinFpscrImpl(value1, value2, standardFpscr);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static float FPMul(float value1, float value2) public static float FPMul(float value1, float value2)
{ {
return FPMulFpscrImpl(value1, value2, false); return FPMulFpscrImpl(value1, value2, false);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static float FPMulFpscr(float value1, float value2, byte standardFpscr) public static float FPMulFpscr(float value1, float value2, byte standardFpscr)
{ {
return FPMulFpscrImpl(value1, value2, standardFpscr == 1); return FPMulFpscrImpl(value1, value2, standardFpscr == 1);
@@ -1344,13 +1456,21 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static float FPMulAdd(float valueA, float value1, float value2) public static float FPMulAdd(float valueA, float value1, float value2)
{ {
return FPMulAddFpscrImpl(valueA, value1, value2, false); return FPMulAddFpscrImpl(valueA, value1, value2, false);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static float FPMulAddFpscr(float valueA, float value1, float value2, byte standardFpscr) public static float FPMulAddFpscr(float valueA, float value1, float value2, byte standardFpscr)
{ {
return FPMulAddFpscrImpl(valueA, value1, value2, standardFpscr == 1); return FPMulAddFpscrImpl(valueA, value1, value2, standardFpscr == 1);
@@ -1422,7 +1542,11 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static float FPMulSub(float valueA, float value1, float value2) public static float FPMulSub(float valueA, float value1, float value2)
{ {
value1 = value1.FPNeg(); value1 = value1.FPNeg();
@@ -1430,7 +1554,11 @@ namespace ARMeilleure.Instructions
return FPMulAddFpscrImpl(valueA, value1, value2, false); return FPMulAddFpscrImpl(valueA, value1, value2, false);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static float FPMulSubFpscr(float valueA, float value1, float value2, byte standardFpscr) public static float FPMulSubFpscr(float valueA, float value1, float value2, byte standardFpscr)
{ {
value1 = value1.FPNeg(); value1 = value1.FPNeg();
@@ -1438,7 +1566,11 @@ namespace ARMeilleure.Instructions
return FPMulAddFpscrImpl(valueA, value1, value2, standardFpscr == 1); return FPMulAddFpscrImpl(valueA, value1, value2, standardFpscr == 1);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static float FPMulX(float value1, float value2) public static float FPMulX(float value1, float value2)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
@@ -1484,7 +1616,11 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static float FPNegMulAdd(float valueA, float value1, float value2) public static float FPNegMulAdd(float valueA, float value1, float value2)
{ {
valueA = valueA.FPNeg(); valueA = valueA.FPNeg();
@@ -1493,7 +1629,11 @@ namespace ARMeilleure.Instructions
return FPMulAddFpscrImpl(valueA, value1, value2, false); return FPMulAddFpscrImpl(valueA, value1, value2, false);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static float FPNegMulSub(float valueA, float value1, float value2) public static float FPNegMulSub(float valueA, float value1, float value2)
{ {
valueA = valueA.FPNeg(); valueA = valueA.FPNeg();
@@ -1501,13 +1641,21 @@ namespace ARMeilleure.Instructions
return FPMulAddFpscrImpl(valueA, value1, value2, false); return FPMulAddFpscrImpl(valueA, value1, value2, false);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static float FPRecipEstimate(float value) public static float FPRecipEstimate(float value)
{ {
return FPRecipEstimateFpscrImpl(value, false); return FPRecipEstimateFpscrImpl(value, false);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static float FPRecipEstimateFpscr(float value, byte standardFpscr) public static float FPRecipEstimateFpscr(float value, byte standardFpscr)
{ {
return FPRecipEstimateFpscrImpl(value, standardFpscr == 1); return FPRecipEstimateFpscrImpl(value, standardFpscr == 1);
@@ -1538,7 +1686,7 @@ namespace ARMeilleure.Instructions
} }
else if (MathF.Abs(value) < MathF.Pow(2f, -128)) else if (MathF.Abs(value) < MathF.Pow(2f, -128))
{ {
var overflowToInf = fpcr.GetRoundingMode() switch bool overflowToInf = fpcr.GetRoundingMode() switch
{ {
FPRoundingMode.ToNearest => true, FPRoundingMode.ToNearest => true,
FPRoundingMode.TowardsPlusInfinity => !sign, FPRoundingMode.TowardsPlusInfinity => !sign,
@@ -1600,7 +1748,11 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static float FPRecipStep(float value1, float value2) public static float FPRecipStep(float value1, float value2)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
@@ -1635,7 +1787,11 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static float FPRecipStepFused(float value1, float value2) public static float FPRecipStepFused(float value1, float value2)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
@@ -1679,7 +1835,11 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static float FPRecpX(float value) public static float FPRecpX(float value)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
@@ -1705,13 +1865,21 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static float FPRSqrtEstimate(float value) public static float FPRSqrtEstimate(float value)
{ {
return FPRSqrtEstimateFpscrImpl(value, false); return FPRSqrtEstimateFpscrImpl(value, false);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static float FPRSqrtEstimateFpscr(float value, byte standardFpscr) public static float FPRSqrtEstimateFpscr(float value, byte standardFpscr)
{ {
return FPRSqrtEstimateFpscrImpl(value, standardFpscr == 1); return FPRSqrtEstimateFpscrImpl(value, standardFpscr == 1);
@@ -1831,7 +1999,11 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static float FPRSqrtStep(float value1, float value2) public static float FPRSqrtStep(float value1, float value2)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
@@ -1866,7 +2038,11 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static float FPRSqrtStepFused(float value1, float value2) public static float FPRSqrtStepFused(float value1, float value2)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
@@ -1910,7 +2086,11 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static float FPSqrt(float value) public static float FPSqrt(float value)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
@@ -1953,7 +2133,11 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static float FPSub(float value1, float value2) public static float FPSub(float value1, float value2)
{ {
return FPSubFpscrImpl(value1, value2, false); return FPSubFpscrImpl(value1, value2, false);
@@ -2200,7 +2384,11 @@ namespace ARMeilleure.Instructions
static class SoftFloat64_16 static class SoftFloat64_16
{ {
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static ushort FPConvert(double value) public static ushort FPConvert(double value)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
@@ -2320,13 +2508,21 @@ namespace ARMeilleure.Instructions
static class SoftFloat64 static class SoftFloat64
{ {
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static double FPAdd(double value1, double value2) public static double FPAdd(double value1, double value2)
{ {
return FPAddFpscrImpl(value1, value2, false); return FPAddFpscrImpl(value1, value2, false);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static double FPAddFpscr(double value1, double value2, byte standardFpscr) public static double FPAddFpscr(double value1, double value2, byte standardFpscr)
{ {
return FPAddFpscrImpl(value1, value2, standardFpscr == 1); return FPAddFpscrImpl(value1, value2, standardFpscr == 1);
@@ -2383,7 +2579,11 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static int FPCompare(double value1, double value2, byte signalNaNs) public static int FPCompare(double value1, double value2, byte signalNaNs)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
@@ -2422,13 +2622,21 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static double FPCompareEQ(double value1, double value2) public static double FPCompareEQ(double value1, double value2)
{ {
return FPCompareEQFpscrImpl(value1, value2, false); return FPCompareEQFpscrImpl(value1, value2, false);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static double FPCompareEQFpscr(double value1, double value2, byte standardFpscr) public static double FPCompareEQFpscr(double value1, double value2, byte standardFpscr)
{ {
return FPCompareEQFpscrImpl(value1, value2, standardFpscr == 1); return FPCompareEQFpscrImpl(value1, value2, standardFpscr == 1);
@@ -2461,13 +2669,21 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static double FPCompareGE(double value1, double value2) public static double FPCompareGE(double value1, double value2)
{ {
return FPCompareGEFpscrImpl(value1, value2, false); return FPCompareGEFpscrImpl(value1, value2, false);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static double FPCompareGEFpscr(double value1, double value2, byte standardFpscr) public static double FPCompareGEFpscr(double value1, double value2, byte standardFpscr)
{ {
return FPCompareGEFpscrImpl(value1, value2, standardFpscr == 1); return FPCompareGEFpscrImpl(value1, value2, standardFpscr == 1);
@@ -2497,13 +2713,21 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static double FPCompareGT(double value1, double value2) public static double FPCompareGT(double value1, double value2)
{ {
return FPCompareGTFpscrImpl(value1, value2, false); return FPCompareGTFpscrImpl(value1, value2, false);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static double FPCompareGTFpscr(double value1, double value2, byte standardFpscr) public static double FPCompareGTFpscr(double value1, double value2, byte standardFpscr)
{ {
return FPCompareGTFpscrImpl(value1, value2, standardFpscr == 1); return FPCompareGTFpscrImpl(value1, value2, standardFpscr == 1);
@@ -2533,31 +2757,51 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static double FPCompareLE(double value1, double value2) public static double FPCompareLE(double value1, double value2)
{ {
return FPCompareGEFpscrImpl(value2, value1, false); return FPCompareGEFpscrImpl(value2, value1, false);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static double FPCompareLT(double value1, double value2) public static double FPCompareLT(double value1, double value2)
{ {
return FPCompareGTFpscrImpl(value2, value1, false); return FPCompareGTFpscrImpl(value2, value1, false);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static double FPCompareLEFpscr(double value1, double value2, byte standardFpscr) public static double FPCompareLEFpscr(double value1, double value2, byte standardFpscr)
{ {
return FPCompareGEFpscrImpl(value2, value1, standardFpscr == 1); return FPCompareGEFpscrImpl(value2, value1, standardFpscr == 1);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static double FPCompareLTFpscr(double value1, double value2, byte standardFpscr) public static double FPCompareLTFpscr(double value1, double value2, byte standardFpscr)
{ {
return FPCompareGTFpscrImpl(value2, value1, standardFpscr == 1); return FPCompareGTFpscrImpl(value2, value1, standardFpscr == 1);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static double FPDiv(double value1, double value2) public static double FPDiv(double value1, double value2)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
@@ -2610,13 +2854,21 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static double FPMax(double value1, double value2) public static double FPMax(double value1, double value2)
{ {
return FPMaxFpscrImpl(value1, value2, false); return FPMaxFpscrImpl(value1, value2, false);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static double FPMaxFpscr(double value1, double value2, byte standardFpscr) public static double FPMaxFpscr(double value1, double value2, byte standardFpscr)
{ {
return FPMaxFpscrImpl(value1, value2, standardFpscr == 1); return FPMaxFpscrImpl(value1, value2, standardFpscr == 1);
@@ -2683,13 +2935,21 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static double FPMaxNum(double value1, double value2) public static double FPMaxNum(double value1, double value2)
{ {
return FPMaxNumFpscrImpl(value1, value2, false); return FPMaxNumFpscrImpl(value1, value2, false);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static double FPMaxNumFpscr(double value1, double value2, byte standardFpscr) public static double FPMaxNumFpscr(double value1, double value2, byte standardFpscr)
{ {
return FPMaxNumFpscrImpl(value1, value2, standardFpscr == 1); return FPMaxNumFpscrImpl(value1, value2, standardFpscr == 1);
@@ -2715,13 +2975,21 @@ namespace ARMeilleure.Instructions
return FPMaxFpscrImpl(value1, value2, standardFpscr); return FPMaxFpscrImpl(value1, value2, standardFpscr);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static double FPMin(double value1, double value2) public static double FPMin(double value1, double value2)
{ {
return FPMinFpscrImpl(value1, value2, false); return FPMinFpscrImpl(value1, value2, false);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static double FPMinFpscr(double value1, double value2, byte standardFpscr) public static double FPMinFpscr(double value1, double value2, byte standardFpscr)
{ {
return FPMinFpscrImpl(value1, value2, standardFpscr == 1); return FPMinFpscrImpl(value1, value2, standardFpscr == 1);
@@ -2788,13 +3056,21 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static double FPMinNum(double value1, double value2) public static double FPMinNum(double value1, double value2)
{ {
return FPMinNumFpscrImpl(value1, value2, false); return FPMinNumFpscrImpl(value1, value2, false);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static double FPMinNumFpscr(double value1, double value2, byte standardFpscr) public static double FPMinNumFpscr(double value1, double value2, byte standardFpscr)
{ {
return FPMinNumFpscrImpl(value1, value2, standardFpscr == 1); return FPMinNumFpscrImpl(value1, value2, standardFpscr == 1);
@@ -2820,13 +3096,21 @@ namespace ARMeilleure.Instructions
return FPMinFpscrImpl(value1, value2, standardFpscr); return FPMinFpscrImpl(value1, value2, standardFpscr);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static double FPMul(double value1, double value2) public static double FPMul(double value1, double value2)
{ {
return FPMulFpscrImpl(value1, value2, false); return FPMulFpscrImpl(value1, value2, false);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static double FPMulFpscr(double value1, double value2, byte standardFpscr) public static double FPMulFpscr(double value1, double value2, byte standardFpscr)
{ {
return FPMulFpscrImpl(value1, value2, standardFpscr == 1); return FPMulFpscrImpl(value1, value2, standardFpscr == 1);
@@ -2879,13 +3163,21 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static double FPMulAdd(double valueA, double value1, double value2) public static double FPMulAdd(double valueA, double value1, double value2)
{ {
return FPMulAddFpscrImpl(valueA, value1, value2, false); return FPMulAddFpscrImpl(valueA, value1, value2, false);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static double FPMulAddFpscr(double valueA, double value1, double value2, byte standardFpscr) public static double FPMulAddFpscr(double valueA, double value1, double value2, byte standardFpscr)
{ {
return FPMulAddFpscrImpl(valueA, value1, value2, standardFpscr == 1); return FPMulAddFpscrImpl(valueA, value1, value2, standardFpscr == 1);
@@ -2957,7 +3249,11 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static double FPMulSub(double valueA, double value1, double value2) public static double FPMulSub(double valueA, double value1, double value2)
{ {
value1 = value1.FPNeg(); value1 = value1.FPNeg();
@@ -2965,7 +3261,11 @@ namespace ARMeilleure.Instructions
return FPMulAddFpscrImpl(valueA, value1, value2, false); return FPMulAddFpscrImpl(valueA, value1, value2, false);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static double FPMulSubFpscr(double valueA, double value1, double value2, byte standardFpscr) public static double FPMulSubFpscr(double valueA, double value1, double value2, byte standardFpscr)
{ {
value1 = value1.FPNeg(); value1 = value1.FPNeg();
@@ -2973,7 +3273,11 @@ namespace ARMeilleure.Instructions
return FPMulAddFpscrImpl(valueA, value1, value2, standardFpscr == 1); return FPMulAddFpscrImpl(valueA, value1, value2, standardFpscr == 1);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static double FPMulX(double value1, double value2) public static double FPMulX(double value1, double value2)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
@@ -3019,7 +3323,11 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static double FPNegMulAdd(double valueA, double value1, double value2) public static double FPNegMulAdd(double valueA, double value1, double value2)
{ {
valueA = valueA.FPNeg(); valueA = valueA.FPNeg();
@@ -3028,7 +3336,11 @@ namespace ARMeilleure.Instructions
return FPMulAddFpscrImpl(valueA, value1, value2, false); return FPMulAddFpscrImpl(valueA, value1, value2, false);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static double FPNegMulSub(double valueA, double value1, double value2) public static double FPNegMulSub(double valueA, double value1, double value2)
{ {
valueA = valueA.FPNeg(); valueA = valueA.FPNeg();
@@ -3036,13 +3348,21 @@ namespace ARMeilleure.Instructions
return FPMulAddFpscrImpl(valueA, value1, value2, false); return FPMulAddFpscrImpl(valueA, value1, value2, false);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static double FPRecipEstimate(double value) public static double FPRecipEstimate(double value)
{ {
return FPRecipEstimateFpscrImpl(value, false); return FPRecipEstimateFpscrImpl(value, false);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static double FPRecipEstimateFpscr(double value, byte standardFpscr) public static double FPRecipEstimateFpscr(double value, byte standardFpscr)
{ {
return FPRecipEstimateFpscrImpl(value, standardFpscr == 1); return FPRecipEstimateFpscrImpl(value, standardFpscr == 1);
@@ -3073,7 +3393,7 @@ namespace ARMeilleure.Instructions
} }
else if (Math.Abs(value) < Math.Pow(2d, -1024)) else if (Math.Abs(value) < Math.Pow(2d, -1024))
{ {
var overflowToInf = fpcr.GetRoundingMode() switch bool overflowToInf = fpcr.GetRoundingMode() switch
{ {
FPRoundingMode.ToNearest => true, FPRoundingMode.ToNearest => true,
FPRoundingMode.TowardsPlusInfinity => !sign, FPRoundingMode.TowardsPlusInfinity => !sign,
@@ -3135,7 +3455,11 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static double FPRecipStep(double value1, double value2) public static double FPRecipStep(double value1, double value2)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
@@ -3170,7 +3494,11 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static double FPRecipStepFused(double value1, double value2) public static double FPRecipStepFused(double value1, double value2)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
@@ -3214,7 +3542,11 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static double FPRecpX(double value) public static double FPRecpX(double value)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
@@ -3240,13 +3572,21 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static double FPRSqrtEstimate(double value) public static double FPRSqrtEstimate(double value)
{ {
return FPRSqrtEstimateFpscrImpl(value, false); return FPRSqrtEstimateFpscrImpl(value, false);
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static double FPRSqrtEstimateFpscr(double value, byte standardFpscr) public static double FPRSqrtEstimateFpscr(double value, byte standardFpscr)
{ {
return FPRSqrtEstimateFpscrImpl(value, standardFpscr == 1); return FPRSqrtEstimateFpscrImpl(value, standardFpscr == 1);
@@ -3366,7 +3706,11 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static double FPRSqrtStep(double value1, double value2) public static double FPRSqrtStep(double value1, double value2)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
@@ -3401,7 +3745,11 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static double FPRSqrtStepFused(double value1, double value2) public static double FPRSqrtStepFused(double value1, double value2)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
@@ -3445,7 +3793,11 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static double FPSqrt(double value) public static double FPSqrt(double value)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
@@ -3488,7 +3840,11 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
#if ANDROID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
#endif
public static double FPSub(double value1, double value2) public static double FPSub(double value1, double value2)
{ {
return FPSubFpscr(value1, value2, false); return FPSubFpscr(value1, value2, false);
@@ -32,7 +32,7 @@ namespace ARMeilleure.IntermediateRepresentation
/// <exception cref="ArgumentException"><typeparamref name="T"/> is not pointer sized.</exception> /// <exception cref="ArgumentException"><typeparamref name="T"/> is not pointer sized.</exception>
public IntrusiveList() public IntrusiveList()
{ {
if (Unsafe.SizeOf<T>() != IntPtr.Size) if (Unsafe.SizeOf<T>() != nint.Size)
{ {
throw new ArgumentException("T must be a reference type or a pointer sized struct."); throw new ArgumentException("T must be a reference type or a pointer sized struct.");
} }
@@ -1,4 +1,3 @@
using System;
using System.Diagnostics; using System.Diagnostics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
@@ -24,7 +23,7 @@ namespace ARMeilleure.IntermediateRepresentation
{ {
Debug.Assert(operand.Kind == OperandKind.Memory); Debug.Assert(operand.Kind == OperandKind.Memory);
_data = (Data*)Unsafe.As<Operand, IntPtr>(ref operand); _data = (Data*)Unsafe.As<Operand, nint>(ref operand);
} }
public Operand BaseAddress public Operand BaseAddress
@@ -304,7 +304,7 @@ namespace ARMeilleure.IntermediateRepresentation
ushort newCount = checked((ushort)(count + 1)); ushort newCount = checked((ushort)(count + 1));
ushort newCapacity = (ushort)Math.Min(capacity * 2, ushort.MaxValue); ushort newCapacity = (ushort)Math.Min(capacity * 2, ushort.MaxValue);
var oldSpan = new Span<T>(data, count); Span<T> oldSpan = new(data, count);
capacity = newCapacity; capacity = newCapacity;
data = Allocators.References.Allocate<T>(capacity); data = Allocators.References.Allocate<T>(capacity);
@@ -338,7 +338,7 @@ namespace ARMeilleure.IntermediateRepresentation
throw new OverflowException(); throw new OverflowException();
} }
var oldSpan = new Span<T>(data, (int)count); Span<T> oldSpan = new(data, (int)count);
capacity = newCapacity; capacity = newCapacity;
data = Allocators.References.Allocate<T>(capacity); data = Allocators.References.Allocate<T>(capacity);
@@ -352,7 +352,7 @@ namespace ARMeilleure.IntermediateRepresentation
private static void Remove<T>(in T item, ref T* data, ref ushort count) where T : unmanaged private static void Remove<T>(in T item, ref T* data, ref ushort count) where T : unmanaged
{ {
var span = new Span<T>(data, count); Span<T> span = new(data, count);
for (int i = 0; i < span.Length; i++) for (int i = 0; i < span.Length; i++)
{ {
@@ -372,7 +372,7 @@ namespace ARMeilleure.IntermediateRepresentation
private static void Remove<T>(in T item, ref T* data, ref uint count) where T : unmanaged private static void Remove<T>(in T item, ref T* data, ref uint count) where T : unmanaged
{ {
var span = new Span<T>(data, (int)count); Span<T> span = new(data, (int)count);
for (int i = 0; i < span.Length; i++) for (int i = 0; i < span.Length; i++)
{ {
@@ -228,7 +228,7 @@ namespace ARMeilleure.IntermediateRepresentation
public readonly override int GetHashCode() public readonly override int GetHashCode()
{ {
return HashCode.Combine((IntPtr)_data); return HashCode.Combine((nint)_data);
} }
public static bool operator ==(Operation a, Operation b) public static bool operator ==(Operation a, Operation b)
+1 -1
View File
@@ -4,7 +4,7 @@ namespace ARMeilleure.Memory
{ {
public interface IJitMemoryBlock : IDisposable public interface IJitMemoryBlock : IDisposable
{ {
IntPtr Pointer { get; } nint Pointer { get; }
void Commit(ulong offset, ulong size); void Commit(ulong offset, ulong size);
+1 -1
View File
@@ -6,7 +6,7 @@ namespace ARMeilleure.Memory
{ {
int AddressSpaceBits { get; } int AddressSpaceBits { get; }
IntPtr PageTablePointer { get; } nint PageTablePointer { get; }
MemoryManagerType Type { get; } MemoryManagerType Type { get; }
+1 -1
View File
@@ -9,7 +9,7 @@ namespace ARMeilleure.Memory
public IJitMemoryBlock Block { get; } public IJitMemoryBlock Block { get; }
public IJitMemoryAllocator Allocator { get; } public IJitMemoryAllocator Allocator { get; }
public IntPtr Pointer => Block.Pointer; public nint Pointer => Block.Pointer;
private readonly ulong _maxSize; private readonly ulong _maxSize;
private readonly ulong _sizeGranularity; private readonly ulong _sizeGranularity;
+1 -2
View File
@@ -1,4 +1,3 @@
using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Runtime.Versioning; using System.Runtime.Versioning;
@@ -8,6 +7,6 @@ namespace ARMeilleure.Native
static partial class JitSupportDarwin static partial class JitSupportDarwin
{ {
[LibraryImport("libarmeilleure-jitsupport", EntryPoint = "armeilleure_jit_memcpy")] [LibraryImport("libarmeilleure-jitsupport", EntryPoint = "armeilleure_jit_memcpy")]
public static partial void Copy(IntPtr dst, IntPtr src, ulong n); public static partial void Copy(nint dst, nint src, ulong n);
} }
} }
+3 -1
View File
@@ -8,11 +8,13 @@ namespace ARMeilleure
// low-core count PPTC // low-core count PPTC
public static bool EcoFriendly { get; set; } = false; public static bool EcoFriendly { get; set; } = false;
// Jit cache eviction
public static bool CacheEviction { get; set; } = false;
public static bool FastFP { get; set; } = true; public static bool FastFP { get; set; } = true;
public static bool AllowLcqInFunctionTable { get; set; } = true; public static bool AllowLcqInFunctionTable { get; set; } = true;
public static bool UseUnmanagedDispatchLoop { get; set; } = true; public static bool UseUnmanagedDispatchLoop { get; set; } = true;
public static bool EnableDebugging { get; set; } = false;
public static bool EnableDeepCallRecursionProtection { get; set; } = true; public static bool EnableDeepCallRecursionProtection { get; set; } = true;
public static bool UseAdvSimdIfAvailable { get; set; } = true; public static bool UseAdvSimdIfAvailable { get; set; } = true;
@@ -8,7 +8,7 @@ namespace ARMeilleure.Signal
{ {
public static class NativeSignalHandlerGenerator public static class NativeSignalHandlerGenerator
{ {
public const int MaxTrackedRanges = 16; public const int MaxTrackedRanges = 8;
private const int StructAddressOffset = 0; private const int StructAddressOffset = 0;
private const int StructWriteOffset = 4; private const int StructWriteOffset = 4;
@@ -21,7 +21,7 @@ namespace ARMeilleure.Signal
private const uint EXCEPTION_ACCESS_VIOLATION = 0xc0000005; private const uint EXCEPTION_ACCESS_VIOLATION = 0xc0000005;
private static Operand EmitGenericRegionCheck(EmitterContext context, IntPtr signalStructPtr, Operand faultAddress, Operand isWrite, int rangeStructSize) private static Operand EmitGenericRegionCheck(EmitterContext context, nint signalStructPtr, Operand faultAddress, Operand isWrite, int rangeStructSize)
{ {
Operand inRegionLocal = context.AllocateLocal(OperandType.I32); Operand inRegionLocal = context.AllocateLocal(OperandType.I32);
context.Copy(inRegionLocal, Const(0)); context.Copy(inRegionLocal, Const(0));
@@ -155,7 +155,7 @@ namespace ARMeilleure.Signal
throw new PlatformNotSupportedException(); throw new PlatformNotSupportedException();
} }
public static byte[] GenerateUnixSignalHandler(IntPtr signalStructPtr, int rangeStructSize) public static byte[] GenerateUnixSignalHandler(nint signalStructPtr, int rangeStructSize)
{ {
EmitterContext context = new(); EmitterContext context = new();
@@ -203,7 +203,7 @@ namespace ARMeilleure.Signal
return Compiler.Compile(cfg, argTypes, OperandType.None, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Code; return Compiler.Compile(cfg, argTypes, OperandType.None, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Code;
} }
public static byte[] GenerateWindowsSignalHandler(IntPtr signalStructPtr, int rangeStructSize) public static byte[] GenerateWindowsSignalHandler(nint signalStructPtr, int rangeStructSize)
{ {
EmitterContext context = new(); EmitterContext context = new();
+4 -5
View File
@@ -1,6 +1,5 @@
using ARMeilleure.IntermediateRepresentation; using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation; using ARMeilleure.Translation;
using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory; using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
@@ -16,13 +15,13 @@ namespace ARMeilleure.Signal
{ {
public delegate bool DebugPartialUnmap(); public delegate bool DebugPartialUnmap();
public delegate int DebugThreadLocalMapGetOrReserve(int threadId, int initialState); public delegate int DebugThreadLocalMapGetOrReserve(int threadId, int initialState);
public delegate void DebugNativeWriteLoop(IntPtr nativeWriteLoopPtr, IntPtr writePtr); public delegate void DebugNativeWriteLoop(nint nativeWriteLoopPtr, nint writePtr);
public static DebugPartialUnmap GenerateDebugPartialUnmap() public static DebugPartialUnmap GenerateDebugPartialUnmap()
{ {
EmitterContext context = new(); EmitterContext context = new();
var result = WindowsPartialUnmapHandler.EmitRetryFromAccessViolation(context); Operand result = WindowsPartialUnmapHandler.EmitRetryFromAccessViolation(context);
context.Return(result); context.Return(result);
@@ -35,11 +34,11 @@ namespace ARMeilleure.Signal
return Compiler.Compile(cfg, argTypes, OperandType.I32, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<DebugPartialUnmap>(); return Compiler.Compile(cfg, argTypes, OperandType.I32, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<DebugPartialUnmap>();
} }
public static DebugThreadLocalMapGetOrReserve GenerateDebugThreadLocalMapGetOrReserve(IntPtr structPtr) public static DebugThreadLocalMapGetOrReserve GenerateDebugThreadLocalMapGetOrReserve(nint structPtr)
{ {
EmitterContext context = new(); EmitterContext context = new();
var result = WindowsPartialUnmapHandler.EmitThreadLocalMapIntGetOrReserve(context, structPtr, context.LoadArgument(OperandType.I32, 0), context.LoadArgument(OperandType.I32, 1)); Operand result = WindowsPartialUnmapHandler.EmitThreadLocalMapIntGetOrReserve(context, structPtr, context.LoadArgument(OperandType.I32, 0), context.LoadArgument(OperandType.I32, 1));
context.Return(result); context.Return(result);
@@ -1,7 +1,6 @@
using ARMeilleure.IntermediateRepresentation; using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation; using ARMeilleure.Translation;
using Ryujinx.Common.Memory.PartialUnmaps; using Ryujinx.Common.Memory.PartialUnmaps;
using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory; using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
@@ -13,18 +12,18 @@ namespace ARMeilleure.Signal
internal static partial class WindowsPartialUnmapHandler internal static partial class WindowsPartialUnmapHandler
{ {
[LibraryImport("kernel32.dll", SetLastError = true, EntryPoint = "LoadLibraryA")] [LibraryImport("kernel32.dll", SetLastError = true, EntryPoint = "LoadLibraryA")]
private static partial IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string lpFileName); private static partial nint LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string lpFileName);
[LibraryImport("kernel32.dll", SetLastError = true)] [LibraryImport("kernel32.dll", SetLastError = true)]
private static partial IntPtr GetProcAddress(IntPtr hModule, [MarshalAs(UnmanagedType.LPStr)] string procName); private static partial nint GetProcAddress(nint hModule, [MarshalAs(UnmanagedType.LPStr)] string procName);
private static IntPtr _getCurrentThreadIdPtr; private static nint _getCurrentThreadIdPtr;
public static IntPtr GetCurrentThreadIdFunc() public static nint GetCurrentThreadIdFunc()
{ {
if (_getCurrentThreadIdPtr == IntPtr.Zero) if (_getCurrentThreadIdPtr == nint.Zero)
{ {
IntPtr handle = LoadLibrary("kernel32.dll"); nint handle = LoadLibrary("kernel32.dll");
_getCurrentThreadIdPtr = GetProcAddress(handle, "GetCurrentThreadId"); _getCurrentThreadIdPtr = GetProcAddress(handle, "GetCurrentThreadId");
} }
@@ -34,13 +33,13 @@ namespace ARMeilleure.Signal
public static Operand EmitRetryFromAccessViolation(EmitterContext context) public static Operand EmitRetryFromAccessViolation(EmitterContext context)
{ {
IntPtr partialRemapStatePtr = PartialUnmapState.GlobalState; nint partialRemapStatePtr = PartialUnmapState.GlobalState;
IntPtr localCountsPtr = IntPtr.Add(partialRemapStatePtr, PartialUnmapState.LocalCountsOffset); nint localCountsPtr = nint.Add(partialRemapStatePtr, PartialUnmapState.LocalCountsOffset);
// Get the lock first. // Get the lock first.
EmitNativeReaderLockAcquire(context, IntPtr.Add(partialRemapStatePtr, PartialUnmapState.PartialUnmapLockOffset)); EmitNativeReaderLockAcquire(context, nint.Add(partialRemapStatePtr, PartialUnmapState.PartialUnmapLockOffset));
IntPtr getCurrentThreadId = GetCurrentThreadIdFunc(); nint getCurrentThreadId = GetCurrentThreadIdFunc();
Operand threadId = context.Call(Const((ulong)getCurrentThreadId), OperandType.I32); Operand threadId = context.Call(Const((ulong)getCurrentThreadId), OperandType.I32);
Operand threadIndex = EmitThreadLocalMapIntGetOrReserve(context, localCountsPtr, threadId, Const(0)); Operand threadIndex = EmitThreadLocalMapIntGetOrReserve(context, localCountsPtr, threadId, Const(0));
@@ -58,7 +57,7 @@ namespace ARMeilleure.Signal
Operand threadLocalPartialUnmapsPtr = EmitThreadLocalMapIntGetValuePtr(context, localCountsPtr, threadIndex); Operand threadLocalPartialUnmapsPtr = EmitThreadLocalMapIntGetValuePtr(context, localCountsPtr, threadIndex);
Operand threadLocalPartialUnmaps = context.Load(OperandType.I32, threadLocalPartialUnmapsPtr); Operand threadLocalPartialUnmaps = context.Load(OperandType.I32, threadLocalPartialUnmapsPtr);
Operand partialUnmapsCount = context.Load(OperandType.I32, Const((ulong)IntPtr.Add(partialRemapStatePtr, PartialUnmapState.PartialUnmapsCountOffset))); Operand partialUnmapsCount = context.Load(OperandType.I32, Const((ulong)nint.Add(partialRemapStatePtr, PartialUnmapState.PartialUnmapsCountOffset)));
context.Copy(retry, context.ICompareNotEqual(threadLocalPartialUnmaps, partialUnmapsCount)); context.Copy(retry, context.ICompareNotEqual(threadLocalPartialUnmaps, partialUnmapsCount));
@@ -79,14 +78,14 @@ namespace ARMeilleure.Signal
context.MarkLabel(endLabel); context.MarkLabel(endLabel);
// Finally, release the lock and return the retry value. // Finally, release the lock and return the retry value.
EmitNativeReaderLockRelease(context, IntPtr.Add(partialRemapStatePtr, PartialUnmapState.PartialUnmapLockOffset)); EmitNativeReaderLockRelease(context, nint.Add(partialRemapStatePtr, PartialUnmapState.PartialUnmapLockOffset));
return retry; return retry;
} }
public static Operand EmitThreadLocalMapIntGetOrReserve(EmitterContext context, IntPtr threadLocalMapPtr, Operand threadId, Operand initialState) public static Operand EmitThreadLocalMapIntGetOrReserve(EmitterContext context, nint threadLocalMapPtr, Operand threadId, Operand initialState)
{ {
Operand idsPtr = Const((ulong)IntPtr.Add(threadLocalMapPtr, ThreadLocalMap<int>.ThreadIdsOffset)); Operand idsPtr = Const((ulong)nint.Add(threadLocalMapPtr, ThreadLocalMap<int>.ThreadIdsOffset));
Operand i = context.AllocateLocal(OperandType.I32); Operand i = context.AllocateLocal(OperandType.I32);
@@ -130,7 +129,7 @@ namespace ARMeilleure.Signal
// If it was 0, then we need to initialize the struct entry and return i. // If it was 0, then we need to initialize the struct entry and return i.
context.BranchIfFalse(idNot0Label, context.ICompareEqual(existingId2, Const(0))); context.BranchIfFalse(idNot0Label, context.ICompareEqual(existingId2, Const(0)));
Operand structsPtr = Const((ulong)IntPtr.Add(threadLocalMapPtr, ThreadLocalMap<int>.StructsOffset)); Operand structsPtr = Const((ulong)nint.Add(threadLocalMapPtr, ThreadLocalMap<int>.StructsOffset));
Operand structPtr = context.Add(structsPtr, context.SignExtend32(OperandType.I64, offset2)); Operand structPtr = context.Add(structsPtr, context.SignExtend32(OperandType.I64, offset2));
context.Store(structPtr, initialState); context.Store(structPtr, initialState);
@@ -149,10 +148,10 @@ namespace ARMeilleure.Signal
return context.Copy(i); return context.Copy(i);
} }
private static Operand EmitThreadLocalMapIntGetValuePtr(EmitterContext context, IntPtr threadLocalMapPtr, Operand index) private static Operand EmitThreadLocalMapIntGetValuePtr(EmitterContext context, nint threadLocalMapPtr, Operand index)
{ {
Operand offset = context.Multiply(index, Const(sizeof(int))); Operand offset = context.Multiply(index, Const(sizeof(int)));
Operand structsPtr = Const((ulong)IntPtr.Add(threadLocalMapPtr, ThreadLocalMap<int>.StructsOffset)); Operand structsPtr = Const((ulong)nint.Add(threadLocalMapPtr, ThreadLocalMap<int>.StructsOffset));
return context.Add(structsPtr, context.SignExtend32(OperandType.I64, offset)); return context.Add(structsPtr, context.SignExtend32(OperandType.I64, offset));
} }
@@ -170,9 +169,9 @@ namespace ARMeilleure.Signal
context.BranchIfFalse(loop, context.ICompareEqual(initial, replaced)); context.BranchIfFalse(loop, context.ICompareEqual(initial, replaced));
} }
private static void EmitNativeReaderLockAcquire(EmitterContext context, IntPtr nativeReaderLockPtr) private static void EmitNativeReaderLockAcquire(EmitterContext context, nint nativeReaderLockPtr)
{ {
Operand writeLockPtr = Const((ulong)IntPtr.Add(nativeReaderLockPtr, NativeReaderWriterLock.WriteLockOffset)); Operand writeLockPtr = Const((ulong)nint.Add(nativeReaderLockPtr, NativeReaderWriterLock.WriteLockOffset));
// Spin until we can acquire the write lock. // Spin until we can acquire the write lock.
Operand spinLabel = Label(); Operand spinLabel = Label();
@@ -182,16 +181,16 @@ namespace ARMeilleure.Signal
context.BranchIfTrue(spinLabel, context.CompareAndSwap(writeLockPtr, Const(0), Const(1))); context.BranchIfTrue(spinLabel, context.CompareAndSwap(writeLockPtr, Const(0), Const(1)));
// Increment reader count. // Increment reader count.
EmitAtomicAddI32(context, Const((ulong)IntPtr.Add(nativeReaderLockPtr, NativeReaderWriterLock.ReaderCountOffset)), Const(1)); EmitAtomicAddI32(context, Const((ulong)nint.Add(nativeReaderLockPtr, NativeReaderWriterLock.ReaderCountOffset)), Const(1));
// Release write lock. // Release write lock.
context.CompareAndSwap(writeLockPtr, Const(1), Const(0)); context.CompareAndSwap(writeLockPtr, Const(1), Const(0));
} }
private static void EmitNativeReaderLockRelease(EmitterContext context, IntPtr nativeReaderLockPtr) private static void EmitNativeReaderLockRelease(EmitterContext context, nint nativeReaderLockPtr)
{ {
// Decrement reader count. // Decrement reader count.
EmitAtomicAddI32(context, Const((ulong)IntPtr.Add(nativeReaderLockPtr, NativeReaderWriterLock.ReaderCountOffset)), Const(-1)); EmitAtomicAddI32(context, Const((ulong)nint.Add(nativeReaderLockPtr, NativeReaderWriterLock.ReaderCountOffset)), Const(-1));
} }
} }
} }
+5 -36
View File
@@ -1,6 +1,4 @@
using ARMeilleure.Memory; using ARMeilleure.Memory;
using System;
using System.Threading;
namespace ARMeilleure.State namespace ARMeilleure.State
{ {
@@ -10,9 +8,9 @@ namespace ARMeilleure.State
private readonly NativeContext _nativeContext; private readonly NativeContext _nativeContext;
internal IntPtr NativeContextPtr => _nativeContext.BasePtr; internal nint NativeContextPtr => _nativeContext.BasePtr;
internal bool Interrupted { get; private set; } private bool _interrupted;
private readonly ICounter _counter; private readonly ICounter _counter;
@@ -69,8 +67,6 @@ namespace ARMeilleure.State
public bool IsAarch32 { get; set; } public bool IsAarch32 { get; set; }
public ulong ThreadUid { get; set; }
internal ExecutionMode ExecutionMode internal ExecutionMode ExecutionMode
{ {
get get
@@ -96,19 +92,14 @@ namespace ARMeilleure.State
private readonly ExceptionCallbackNoArgs _interruptCallback; private readonly ExceptionCallbackNoArgs _interruptCallback;
private readonly ExceptionCallback _breakCallback; private readonly ExceptionCallback _breakCallback;
private readonly ExceptionCallbackNoArgs _stepCallback;
private readonly ExceptionCallback _supervisorCallback; private readonly ExceptionCallback _supervisorCallback;
private readonly ExceptionCallback _undefinedCallback; private readonly ExceptionCallback _undefinedCallback;
internal int ShouldStep;
public ulong DebugPc { get; set; }
public ExecutionContext( public ExecutionContext(
IJitMemoryAllocator allocator, IJitMemoryAllocator allocator,
ICounter counter, ICounter counter,
ExceptionCallbackNoArgs interruptCallback = null, ExceptionCallbackNoArgs interruptCallback = null,
ExceptionCallback breakCallback = null, ExceptionCallback breakCallback = null,
ExceptionCallbackNoArgs stepCallback = null,
ExceptionCallback supervisorCallback = null, ExceptionCallback supervisorCallback = null,
ExceptionCallback undefinedCallback = null) ExceptionCallback undefinedCallback = null)
{ {
@@ -116,7 +107,6 @@ namespace ARMeilleure.State
_counter = counter; _counter = counter;
_interruptCallback = interruptCallback; _interruptCallback = interruptCallback;
_breakCallback = breakCallback; _breakCallback = breakCallback;
_stepCallback = stepCallback;
_supervisorCallback = supervisorCallback; _supervisorCallback = supervisorCallback;
_undefinedCallback = undefinedCallback; _undefinedCallback = undefinedCallback;
@@ -144,9 +134,9 @@ namespace ARMeilleure.State
internal void CheckInterrupt() internal void CheckInterrupt()
{ {
if (Interrupted) if (_interrupted)
{ {
Interrupted = false; _interrupted = false;
_interruptCallback?.Invoke(this); _interruptCallback?.Invoke(this);
} }
@@ -156,37 +146,16 @@ namespace ARMeilleure.State
public void RequestInterrupt() public void RequestInterrupt()
{ {
Interrupted = true; _interrupted = true;
}
public void StepHandler()
{
_stepCallback?.Invoke(this);
}
public void RequestDebugStep()
{
Interlocked.Exchange(ref ShouldStep, 1);
RequestInterrupt();
} }
internal void OnBreak(ulong address, int imm) internal void OnBreak(ulong address, int imm)
{ {
if (Optimizations.EnableDebugging)
{
DebugPc = Pc;
}
_breakCallback?.Invoke(this, address, imm); _breakCallback?.Invoke(this, address, imm);
} }
internal void OnSupervisorCall(ulong address, int imm) internal void OnSupervisorCall(ulong address, int imm)
{ {
if (Optimizations.EnableDebugging)
{
DebugPc = Pc;
}
_supervisorCallback?.Invoke(this, address, imm); _supervisorCallback?.Invoke(this, address, imm);
} }
+1 -17
View File
@@ -23,19 +23,13 @@ namespace ARMeilleure.State
public int Running; public int Running;
public int CallDepth; public int CallDepth;
public long Tpidr2El0; public long Tpidr2El0;
/// <summary>
/// Precise PC value used for debugging.
/// This will only be set when Optimizations.EnableDebugging is true.
/// </summary>
public ulong DebugPrecisePc;
} }
private static NativeCtxStorage _dummyStorage = new(); private static NativeCtxStorage _dummyStorage = new();
private readonly IJitMemoryBlock _block; private readonly IJitMemoryBlock _block;
public IntPtr BasePtr => _block.Pointer; public nint BasePtr => _block.Pointer;
public NativeContext(IJitMemoryAllocator allocator) public NativeContext(IJitMemoryAllocator allocator)
{ {
@@ -46,11 +40,6 @@ namespace ARMeilleure.State
public ulong GetPc() public ulong GetPc()
{ {
if (Optimizations.EnableDebugging)
{
return GetStorage().DebugPrecisePc;
}
// TODO: More precise tracking of PC value. // TODO: More precise tracking of PC value.
return GetStorage().DispatchAddress; return GetStorage().DispatchAddress;
} }
@@ -280,11 +269,6 @@ namespace ARMeilleure.State
return StorageOffset(ref _dummyStorage, ref _dummyStorage.Running); return StorageOffset(ref _dummyStorage, ref _dummyStorage.Running);
} }
public static int GetDebugPrecisePcOffset()
{
return StorageOffset(ref _dummyStorage, ref _dummyStorage.DebugPrecisePc);
}
public static int GetCallDepthOffset() public static int GetCallDepthOffset()
{ {
return StorageOffset(ref _dummyStorage, ref _dummyStorage.CallDepth); return StorageOffset(ref _dummyStorage, ref _dummyStorage.CallDepth);
@@ -6,7 +6,6 @@ using ARMeilleure.Instructions;
using ARMeilleure.IntermediateRepresentation; using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Memory; using ARMeilleure.Memory;
using ARMeilleure.State; using ARMeilleure.State;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection; using System.Reflection;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory; using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
@@ -53,7 +52,6 @@ namespace ARMeilleure.Translation
public bool HighCq { get; } public bool HighCq { get; }
public bool HasPtc { get; } public bool HasPtc { get; }
public Aarch32Mode Mode { get; } public Aarch32Mode Mode { get; }
public bool IsSingleStep { get; }
private int _ifThenBlockStateIndex = 0; private int _ifThenBlockStateIndex = 0;
private Condition[] _ifThenBlockState = []; private Condition[] _ifThenBlockState = [];
@@ -68,8 +66,7 @@ namespace ARMeilleure.Translation
ulong entryAddress, ulong entryAddress,
bool highCq, bool highCq,
bool hasPtc, bool hasPtc,
Aarch32Mode mode, Aarch32Mode mode)
bool isSingleStep)
{ {
Memory = memory; Memory = memory;
CountTable = countTable; CountTable = countTable;
@@ -79,7 +76,6 @@ namespace ARMeilleure.Translation
HighCq = highCq; HighCq = highCq;
HasPtc = hasPtc; HasPtc = hasPtc;
Mode = mode; Mode = mode;
IsSingleStep = isSingleStep;
_labels = new Dictionary<ulong, Operand>(); _labels = new Dictionary<ulong, Operand>();
} }
@@ -95,7 +91,7 @@ namespace ARMeilleure.Translation
else else
{ {
int index = Delegates.GetDelegateIndex(info); int index = Delegates.GetDelegateIndex(info);
IntPtr funcPtr = Delegates.GetDelegateFuncPtrByIndex(index); nint funcPtr = Delegates.GetDelegateFuncPtrByIndex(index);
OperandType returnType = GetOperandType(info.ReturnType); OperandType returnType = GetOperandType(info.ReturnType);
+197 -84
View File
@@ -2,12 +2,12 @@ using ARMeilleure.CodeGen;
using ARMeilleure.CodeGen.Unwinding; using ARMeilleure.CodeGen.Unwinding;
using ARMeilleure.Memory; using ARMeilleure.Memory;
using ARMeilleure.Native; using ARMeilleure.Native;
using Humanizer;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Memory; using Ryujinx.Memory;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Runtime.Versioning; using System.Runtime.Versioning;
using System.Threading; using System.Threading;
@@ -19,83 +19,123 @@ namespace ARMeilleure.Translation.Cache
private static readonly int _pageSize = (int)MemoryBlock.GetPageSize(); private static readonly int _pageSize = (int)MemoryBlock.GetPageSize();
private static readonly int _pageMask = _pageSize - 1; private static readonly int _pageMask = _pageSize - 1;
private const int CodeAlignment = 4; // Bytes. private const int CodeAlignment = 4;
private const int CacheSize = 256 * 1024 * 1024; private const int FullCacheSize = 2047 * 1024 * 1024;
private const int ReducedCacheSize = FullCacheSize / 8;
private const float EvictionTargetPercentage = 0.20f;
private const int MaxEntriesToEvictAtOnce = 100;
// Simple logging configuration
private const int LogInterval = 5000; // Log every 5000 allocations
private static ReservedRegion _jitRegion;
private static JitCacheInvalidation _jitCacheInvalidator; private static JitCacheInvalidation _jitCacheInvalidator;
private static List<CacheMemoryAllocator> _cacheAllocators = []; private static CacheMemoryAllocator _cacheAllocator;
private static readonly List<CacheEntry> _cacheEntries = []; private static readonly List<CacheEntry> _cacheEntries = [];
private static readonly Dictionary<int, EntryUsageStats> _entryUsageStats = [];
private static readonly Lock _lock = new(); private static readonly Lock _lock = new();
private static bool _initialized; private static bool _initialized;
private static int _cacheSize;
private static readonly List<ReservedRegion> _jitRegions = []; // Basic statistics
private static int _activeRegionIndex = 0; private static int _totalAllocations = 0;
private static int _totalEvictions = 0;
private class EntryUsageStats
{
public long LastAccessTime { get; private set; }
public int UsageCount { get; private set; }
public EntryUsageStats()
{
LastAccessTime = DateTime.UtcNow.Ticks;
UsageCount = 1;
}
public void UpdateUsage()
{
LastAccessTime = DateTime.UtcNow.Ticks;
UsageCount++;
}
}
[SupportedOSPlatform("windows")] [SupportedOSPlatform("windows")]
[LibraryImport("kernel32.dll", SetLastError = true)] [LibraryImport("kernel32.dll", SetLastError = true)]
public static partial IntPtr FlushInstructionCache(IntPtr hProcess, IntPtr lpAddress, UIntPtr dwSize); public static partial nint FlushInstructionCache(nint hProcess, nint lpAddress, nuint dwSize);
public static void Initialize(IJitMemoryAllocator allocator) public static void Initialize(IJitMemoryAllocator allocator)
{ {
if (_initialized)
{
return;
}
lock (_lock) lock (_lock)
{ {
if (_initialized) if (_initialized)
{ {
if (OperatingSystem.IsWindows()) return;
{
JitUnwindWindows.RemoveFunctionTableHandler(
_jitRegions[0].Pointer);
} }
for (int i = 0; i < _jitRegions.Count; i++) _cacheSize = Optimizations.CacheEviction ? ReducedCacheSize : FullCacheSize;
{ _jitRegion = new ReservedRegion(allocator, (ulong)_cacheSize);
_jitRegions[i].Dispose();
}
_jitRegions.Clear();
_cacheAllocators.Clear();
}
else
{
_initialized = true;
}
_activeRegionIndex = 0;
var firstRegion = new ReservedRegion(allocator, CacheSize);
_jitRegions.Add(firstRegion);
CacheMemoryAllocator firstCacheAllocator = new(CacheSize);
_cacheAllocators.Add(firstCacheAllocator);
if (!OperatingSystem.IsWindows() && !OperatingSystem.IsMacOS()) if (!OperatingSystem.IsWindows() && !OperatingSystem.IsMacOS())
{ {
_jitCacheInvalidator = new JitCacheInvalidation(allocator); _jitCacheInvalidator = new JitCacheInvalidation(allocator);
} }
_cacheAllocator = new CacheMemoryAllocator(_cacheSize);
if (OperatingSystem.IsWindows()) if (OperatingSystem.IsWindows())
{ {
JitUnwindWindows.InstallFunctionTableHandler( JitUnwindWindows.InstallFunctionTableHandler(_jitRegion.Pointer, (uint)_cacheSize, _jitRegion.Pointer + Allocate(_pageSize));
firstRegion.Pointer, CacheSize, firstRegion.Pointer + Allocate(_pageSize)
);
} }
Logger.Info?.Print(LogClass.Cpu, $"JIT Cache initialized: Size={_cacheSize / (1024 * 1024)} MB, Eviction={Optimizations.CacheEviction}");
_initialized = true;
} }
} }
public static IntPtr Map(CompiledFunction func) public static nint Map(CompiledFunction func)
{ {
byte[] code = func.Code; byte[] code = func.Code;
lock (_lock) lock (_lock)
{ {
Debug.Assert(_initialized); Debug.Assert(_initialized);
_totalAllocations++;
int funcOffset = Allocate(code.Length); int funcOffset;
ReservedRegion targetRegion = _jitRegions[_activeRegionIndex];
IntPtr funcPtr = targetRegion.Pointer + funcOffset; if (Optimizations.CacheEviction)
{
int codeSize = AlignCodeSize(code.Length);
funcOffset = _cacheAllocator.Allocate(codeSize);
if (funcOffset < 0)
{
EvictEntries(codeSize);
funcOffset = _cacheAllocator.Allocate(codeSize);
if (funcOffset < 0)
{
throw new OutOfMemoryException("JIT Cache exhausted even after eviction.");
}
}
_jitRegion.ExpandIfNeeded((ulong)funcOffset + (ulong)codeSize);
}
else
{
funcOffset = Allocate(code.Length);
}
nint funcPtr = _jitRegion.Pointer + funcOffset;
if (OperatingSystem.IsMacOS() && RuntimeInformation.ProcessArchitecture == Architecture.Arm64) if (OperatingSystem.IsMacOS() && RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
{ {
@@ -103,19 +143,19 @@ namespace ARMeilleure.Translation.Cache
{ {
fixed (byte* codePtr = code) fixed (byte* codePtr = code)
{ {
JitSupportDarwin.Copy(funcPtr, (IntPtr)codePtr, (ulong)code.Length); JitSupportDarwin.Copy(funcPtr, (nint)codePtr, (ulong)code.Length);
} }
} }
} }
else else
{ {
ReprotectAsWritable(targetRegion, funcOffset, code.Length); ReprotectAsWritable(funcOffset, code.Length);
Marshal.Copy(code, 0, funcPtr, code.Length); Marshal.Copy(code, 0, funcPtr, code.Length);
ReprotectAsExecutable(targetRegion, funcOffset, code.Length); ReprotectAsExecutable(funcOffset, code.Length);
if (OperatingSystem.IsWindows() && RuntimeInformation.ProcessArchitecture == Architecture.Arm64) if (OperatingSystem.IsWindows() && RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
{ {
FlushInstructionCache(Process.GetCurrentProcess().Handle, funcPtr, (UIntPtr)code.Length); FlushInstructionCache(Process.GetCurrentProcess().Handle, funcPtr, (nuint)code.Length);
} }
else else
{ {
@@ -125,86 +165,73 @@ namespace ARMeilleure.Translation.Cache
Add(funcOffset, code.Length, func.UnwindInfo); Add(funcOffset, code.Length, func.UnwindInfo);
// Simple periodic logging
if (_totalAllocations % LogInterval == 0)
{
LogCacheStatus();
}
return funcPtr; return funcPtr;
} }
} }
public static void Unmap(IntPtr pointer) public static void Unmap(nint pointer)
{ {
lock (_lock) lock (_lock)
{ {
Debug.Assert(_initialized); Debug.Assert(_initialized);
foreach (var region in _jitRegions) int funcOffset = (int)(pointer.ToInt64() - _jitRegion.Pointer.ToInt64());
{
if (pointer.ToInt64() < region.Pointer.ToInt64() ||
pointer.ToInt64() >= (region.Pointer + CacheSize).ToInt64())
{
continue;
}
int funcOffset = (int)(pointer.ToInt64() - region.Pointer.ToInt64());
if (TryFind(funcOffset, out CacheEntry entry, out int entryIndex) && entry.Offset == funcOffset) if (TryFind(funcOffset, out CacheEntry entry, out int entryIndex) && entry.Offset == funcOffset)
{ {
_cacheAllocators[_activeRegionIndex].Free(funcOffset, AlignCodeSize(entry.Size)); _cacheAllocator.Free(funcOffset, AlignCodeSize(entry.Size));
_cacheEntries.RemoveAt(entryIndex); _cacheEntries.RemoveAt(entryIndex);
}
return; if (Optimizations.CacheEviction)
{
_entryUsageStats.Remove(funcOffset);
}
} }
} }
} }
private static void ReprotectAsWritable(ReservedRegion region, int offset, int size) private static void ReprotectAsWritable(int offset, int size)
{ {
int endOffs = offset + size; int endOffs = offset + size;
int regionStart = offset & ~_pageMask; int regionStart = offset & ~_pageMask;
int regionEnd = (endOffs + _pageMask) & ~_pageMask; int regionEnd = (endOffs + _pageMask) & ~_pageMask;
region.Block.MapAsRwx((ulong)regionStart, (ulong)(regionEnd - regionStart)); _jitRegion.Block.MapAsRwx((ulong)regionStart, (ulong)(regionEnd - regionStart));
} }
private static void ReprotectAsExecutable(ReservedRegion region, int offset, int size) private static void ReprotectAsExecutable(int offset, int size)
{ {
int endOffs = offset + size; int endOffs = offset + size;
int regionStart = offset & ~_pageMask; int regionStart = offset & ~_pageMask;
int regionEnd = (endOffs + _pageMask) & ~_pageMask; int regionEnd = (endOffs + _pageMask) & ~_pageMask;
region.Block.MapAsRx((ulong)regionStart, (ulong)(regionEnd - regionStart)); _jitRegion.Block.MapAsRx((ulong)regionStart, (ulong)(regionEnd - regionStart));
} }
private static int Allocate(int codeSize) private static int Allocate(int codeSize)
{ {
codeSize = AlignCodeSize(codeSize); codeSize = AlignCodeSize(codeSize);
int allocOffset = _cacheAllocators[_activeRegionIndex].Allocate(codeSize); int allocOffset = _cacheAllocator.Allocate(codeSize);
if (allocOffset >= 0) if (allocOffset < 0)
{ {
_jitRegions[_activeRegionIndex].ExpandIfNeeded((ulong)allocOffset + (ulong)codeSize); throw new OutOfMemoryException("JIT Cache exhausted.");
}
_jitRegion.ExpandIfNeeded((ulong)allocOffset + (ulong)codeSize);
return allocOffset; return allocOffset;
} }
int exhaustedRegion = _activeRegionIndex;
var newRegion = new ReservedRegion(_jitRegions[0].Allocator, CacheSize);
_jitRegions.Add(newRegion);
_activeRegionIndex = _jitRegions.Count - 1;
Logger.Warning?.Print(LogClass.Cpu, $"JIT Cache Region {exhaustedRegion} exhausted, creating new Cache Region {_activeRegionIndex} ({((long)(_activeRegionIndex + 1) * CacheSize).Bytes()} Total Allocation).");
_cacheAllocators.Add(new CacheMemoryAllocator(CacheSize));
int allocOffsetNew = _cacheAllocators[_activeRegionIndex].Allocate(codeSize);
if (allocOffsetNew < 0)
{
throw new OutOfMemoryException("Failed to allocate in new Cache Region!");
}
newRegion.ExpandIfNeeded((ulong)allocOffsetNew + (ulong)codeSize);
return allocOffsetNew;
}
private static int AlignCodeSize(int codeSize) private static int AlignCodeSize(int codeSize)
{ {
return checked(codeSize + (CodeAlignment - 1)) & ~(CodeAlignment - 1); return checked(codeSize + (CodeAlignment - 1)) & ~(CodeAlignment - 1);
@@ -222,13 +249,16 @@ namespace ARMeilleure.Translation.Cache
} }
_cacheEntries.Insert(index, entry); _cacheEntries.Insert(index, entry);
if (Optimizations.CacheEviction)
{
_entryUsageStats[offset] = new EntryUsageStats();
}
} }
public static bool TryFind(int offset, out CacheEntry entry, out int entryIndex) public static bool TryFind(int offset, out CacheEntry entry, out int entryIndex)
{ {
lock (_lock) lock (_lock)
{
foreach (var region in _jitRegions)
{ {
int index = _cacheEntries.BinarySearch(new CacheEntry(offset, 0, default)); int index = _cacheEntries.BinarySearch(new CacheEntry(offset, 0, default));
@@ -240,15 +270,98 @@ namespace ARMeilleure.Translation.Cache
if (index >= 0) if (index >= 0)
{ {
entry = _cacheEntries[index]; entry = _cacheEntries[index];
if (Optimizations.CacheEviction && _entryUsageStats.TryGetValue(offset, out EntryUsageStats stats))
{
stats.UpdateUsage();
}
entryIndex = index; entryIndex = index;
return true; return true;
} }
} }
}
entry = default; entry = default;
entryIndex = 0; entryIndex = 0;
return false; return false;
} }
private static void EvictEntries(int requiredSize)
{
if (!Optimizations.CacheEviction)
{
return;
}
lock (_lock)
{
int targetSpace = Math.Max(requiredSize, (int)(_cacheSize * EvictionTargetPercentage));
int freedSpace = 0;
int evictedCount = 0;
var entriesWithStats = _cacheEntries
.Where(e => _entryUsageStats.ContainsKey(e.Offset))
.Select(e => new {
Entry = e,
Stats = _entryUsageStats[e.Offset],
Score = CalculateEvictionScore(_entryUsageStats[e.Offset])
})
.OrderBy(x => x.Score)
.Take(MaxEntriesToEvictAtOnce)
.ToList();
foreach (var item in entriesWithStats)
{
int entrySize = AlignCodeSize(item.Entry.Size);
int entryIndex = _cacheEntries.BinarySearch(item.Entry);
if (entryIndex >= 0)
{
_cacheAllocator.Free(item.Entry.Offset, entrySize);
_cacheEntries.RemoveAt(entryIndex);
_entryUsageStats.Remove(item.Entry.Offset);
freedSpace += entrySize;
evictedCount++;
if (freedSpace >= targetSpace)
{
break;
}
}
}
_totalEvictions += evictedCount;
Logger.Info?.Print(LogClass.Cpu, $"JIT Cache: Evicted {evictedCount} entries, freed {freedSpace / (1024 * 1024.0):F2} MB");
}
}
private static double CalculateEvictionScore(EntryUsageStats stats)
{
long currentTime = DateTime.UtcNow.Ticks;
long ageInTicks = currentTime - stats.LastAccessTime;
double ageInSeconds = ageInTicks / 10_000_000.0;
const double usageWeight = 1.0;
const double ageWeight = 2.0;
double usageScore = Math.Log10(stats.UsageCount + 1) * usageWeight;
double ageScore = (10.0 / (ageInSeconds + 1.0)) * ageWeight;
return usageScore + ageScore;
}
private static void LogCacheStatus()
{
int estimatedUsedSize = _cacheEntries.Sum(e => AlignCodeSize(e.Size));
double usagePercentage = 100.0 * estimatedUsedSize / _cacheSize;
Logger.Info?.Print(LogClass.Cpu,
$"JIT Cache status: entries={_cacheEntries.Count}, " +
$"est. used={estimatedUsedSize / (1024 * 1024.0):F2} MB ({usagePercentage:F1}%), " +
$"evictions={_totalEvictions}, allocations={_totalAllocations}");
}
} }
} }
@@ -1,5 +1,4 @@
using ARMeilleure.Memory; using ARMeilleure.Memory;
using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace ARMeilleure.Translation.Cache namespace ARMeilleure.Translation.Cache
@@ -68,7 +67,7 @@ namespace ARMeilleure.Translation.Cache
} }
} }
public void Invalidate(IntPtr basePointer, ulong size) public void Invalidate(nint basePointer, ulong size)
{ {
if (_needsInvalidation) if (_needsInvalidation)
{ {
@@ -40,7 +40,7 @@ namespace ARMeilleure.Translation.Cache
PushMachframe = 10, PushMachframe = 10,
} }
private unsafe delegate RuntimeFunction* GetRuntimeFunctionCallback(ulong controlPc, IntPtr context); private unsafe delegate RuntimeFunction* GetRuntimeFunctionCallback(ulong controlPc, nint context);
[LibraryImport("kernel32.dll")] [LibraryImport("kernel32.dll")]
[return: MarshalAs(UnmanagedType.Bool)] [return: MarshalAs(UnmanagedType.Bool)]
@@ -49,7 +49,7 @@ namespace ARMeilleure.Translation.Cache
ulong baseAddress, ulong baseAddress,
uint length, uint length,
GetRuntimeFunctionCallback callback, GetRuntimeFunctionCallback callback,
IntPtr context, nint context,
[MarshalAs(UnmanagedType.LPWStr)] string outOfProcessCallbackDll); [MarshalAs(UnmanagedType.LPWStr)] string outOfProcessCallbackDll);
[LibraryImport("kernel32.dll")] [LibraryImport("kernel32.dll")]
@@ -65,7 +65,7 @@ namespace ARMeilleure.Translation.Cache
private unsafe static UnwindInfo* _unwindInfo; private unsafe static UnwindInfo* _unwindInfo;
public static void InstallFunctionTableHandler(IntPtr codeCachePointer, uint codeCacheLength, IntPtr workBufferPtr) public static void InstallFunctionTableHandler(nint codeCachePointer, uint codeCacheLength, nint workBufferPtr)
{ {
ulong codeCachePtr = (ulong)codeCachePointer.ToInt64(); ulong codeCachePtr = (ulong)codeCachePointer.ToInt64();
@@ -96,7 +96,7 @@ namespace ARMeilleure.Translation.Cache
} }
} }
public static void RemoveFunctionTableHandler(IntPtr codeCachePointer) public static void RemoveFunctionTableHandler(nint codeCachePointer)
{ {
ulong codeCachePtr = (ulong)codeCachePointer.ToInt64(); ulong codeCachePtr = (ulong)codeCachePointer.ToInt64();
@@ -113,7 +113,7 @@ namespace ARMeilleure.Translation.Cache
} }
} }
private static unsafe RuntimeFunction* FunctionTableHandler(ulong controlPc, IntPtr context) private static unsafe RuntimeFunction* FunctionTableHandler(ulong controlPc, nint context)
{ {
int offset = (int)((long)controlPc - context.ToInt64()); int offset = (int)((long)controlPc - context.ToInt64());
@@ -122,13 +122,13 @@ namespace ARMeilleure.Translation.Cache
return null; // Not found. return null; // Not found.
} }
var unwindInfo = funcEntry.UnwindInfo; CodeGen.Unwinding.UnwindInfo unwindInfo = funcEntry.UnwindInfo;
int codeIndex = 0; int codeIndex = 0;
for (int index = unwindInfo.PushEntries.Length - 1; index >= 0; index--) for (int index = unwindInfo.PushEntries.Length - 1; index >= 0; index--)
{ {
var entry = unwindInfo.PushEntries[index]; UnwindPushEntry entry = unwindInfo.PushEntries[index];
switch (entry.PseudoOp) switch (entry.PseudoOp)
{ {
@@ -47,8 +47,8 @@ namespace ARMeilleure.Translation
{ {
RemoveUnreachableBlocks(Blocks); RemoveUnreachableBlocks(Blocks);
var visited = new HashSet<BasicBlock>(); HashSet<BasicBlock> visited = new();
var blockStack = new Stack<BasicBlock>(); Stack<BasicBlock> blockStack = new();
Array.Resize(ref _postOrderBlocks, Blocks.Count); Array.Resize(ref _postOrderBlocks, Blocks.Count);
Array.Resize(ref _postOrderMap, Blocks.Count); Array.Resize(ref _postOrderMap, Blocks.Count);
@@ -88,8 +88,8 @@ namespace ARMeilleure.Translation
private void RemoveUnreachableBlocks(IntrusiveList<BasicBlock> blocks) private void RemoveUnreachableBlocks(IntrusiveList<BasicBlock> blocks)
{ {
var visited = new HashSet<BasicBlock>(); HashSet<BasicBlock> visited = new();
var workQueue = new Queue<BasicBlock>(); Queue<BasicBlock> workQueue = new();
visited.Add(Entry); visited.Add(Entry);
workQueue.Enqueue(Entry); workQueue.Enqueue(Entry);
+3 -5
View File
@@ -1,12 +1,10 @@
using System;
namespace ARMeilleure.Translation namespace ARMeilleure.Translation
{ {
class DelegateInfo public class DelegateInfo
{ {
public IntPtr FuncPtr { get; } public nint FuncPtr { get; }
public DelegateInfo(IntPtr funcPtr) public DelegateInfo(nint funcPtr)
{ {
FuncPtr = funcPtr; FuncPtr = funcPtr;
} }
+593 -37
View File
@@ -2,12 +2,359 @@ using ARMeilleure.Instructions;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection; using System.Reflection;
#if ANDROID
using ARMeilleure.State;
using System.Runtime.InteropServices;
#endif
namespace ARMeilleure.Translation namespace ARMeilleure.Translation
{ {
static class Delegates static class Delegates
{ {
public static bool TryGetDelegateFuncPtrByIndex(int index, out IntPtr funcPtr) #if ANDROID
// MathHelper delegates
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate double MathHelperAbsDelegate(double value);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate double MathHelperCeilingDelegate(double value);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate double MathHelperFloorDelegate(double value);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate double MathHelperRoundDelegate(double value, int mode);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate double MathHelperTruncateDelegate(double value);
// MathHelperF delegates
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate float MathHelperFAbsDelegate(float value);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate float MathHelperFCeilingDelegate(float value);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate float MathHelperFFloorDelegate(float value);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate float MathHelperFRoundDelegate(float value, int mode);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate float MathHelperFTruncateDelegate(float value);
// NativeInterface delegates
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void NativeInterfaceBreakDelegate(ulong address, int imm);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate byte NativeInterfaceCheckSynchronizationDelegate();
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void NativeInterfaceEnqueueForRejitDelegate(ulong address);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate ulong NativeInterfaceGetCntfrqEl0Delegate();
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate ulong NativeInterfaceGetCntpctEl0Delegate();
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate ulong NativeInterfaceGetCntvctEl0Delegate();
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate ulong NativeInterfaceGetCtrEl0Delegate();
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate ulong NativeInterfaceGetDczidEl0Delegate();
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate ulong NativeInterfaceGetFunctionAddressDelegate(ulong address);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void NativeInterfaceInvalidateCacheLineDelegate(ulong address);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate byte NativeInterfaceReadByteDelegate(ulong address);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate ushort NativeInterfaceReadUInt16Delegate(ulong address);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate uint NativeInterfaceReadUInt32Delegate(ulong address);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate ulong NativeInterfaceReadUInt64Delegate(ulong address);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate V128 NativeInterfaceReadVector128Delegate(ulong address);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void NativeInterfaceSignalMemoryTrackingDelegate(ulong address, ulong size, byte write);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void NativeInterfaceSupervisorCallDelegate(ulong address, int imm);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void NativeInterfaceThrowInvalidMemoryAccessDelegate(ulong address);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void NativeInterfaceUndefinedDelegate(ulong address, int opCode);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void NativeInterfaceWriteByteDelegate(ulong address, byte value);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void NativeInterfaceWriteUInt16Delegate(ulong address, ushort value);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void NativeInterfaceWriteUInt32Delegate(ulong address, uint value);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void NativeInterfaceWriteUInt64Delegate(ulong address, ulong value);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void NativeInterfaceWriteVector128Delegate(ulong address, V128 value);
// SoftFallback delegates
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate ulong SoftFallbackCountLeadingSignsDelegate(ulong value, int size);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate ulong SoftFallbackCountLeadingZerosDelegate(ulong value, int size);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate uint SoftFallbackCrc32bDelegate(uint crc, byte val);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate uint SoftFallbackCrc32cbDelegate(uint crc, byte val);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate uint SoftFallbackCrc32chDelegate(uint crc, ushort val);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate uint SoftFallbackCrc32cwDelegate(uint crc, uint val);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate uint SoftFallbackCrc32cxDelegate(uint crc, ulong val);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate uint SoftFallbackCrc32hDelegate(uint crc, ushort val);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate uint SoftFallbackCrc32wDelegate(uint crc, uint val);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate uint SoftFallbackCrc32xDelegate(uint crc, ulong val);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate V128 SoftFallbackDecryptDelegate(V128 value, V128 roundKey);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate V128 SoftFallbackEncryptDelegate(V128 value, V128 roundKey);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate uint SoftFallbackFixedRotateDelegate(uint hash_e);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate V128 SoftFallbackHashChooseDelegate(V128 hash_abcd, uint hash_e, V128 wk);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate V128 SoftFallbackHashLowerDelegate(V128 hash_abcd, V128 hash_efgh, V128 wk);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate V128 SoftFallbackHashMajorityDelegate(V128 hash_abcd, uint hash_e, V128 wk);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate V128 SoftFallbackHashParityDelegate(V128 hash_abcd, uint hash_e, V128 wk);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate V128 SoftFallbackHashUpperDelegate(V128 hash_abcd, V128 hash_efgh, V128 wk);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate V128 SoftFallbackInverseMixColumnsDelegate(V128 value);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate V128 SoftFallbackMixColumnsDelegate(V128 value);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate V128 SoftFallbackPolynomialMult64_128Delegate(ulong op1, ulong op2);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate int SoftFallbackSatF32ToS32Delegate(float value);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate long SoftFallbackSatF32ToS64Delegate(float value);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate uint SoftFallbackSatF32ToU32Delegate(float value);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate ulong SoftFallbackSatF32ToU64Delegate(float value);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate int SoftFallbackSatF64ToS32Delegate(double value);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate long SoftFallbackSatF64ToS64Delegate(double value);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate uint SoftFallbackSatF64ToU32Delegate(double value);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate ulong SoftFallbackSatF64ToU64Delegate(double value);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate V128 SoftFallbackSha1SchedulePart1Delegate(V128 w0_3, V128 w4_7, V128 w8_11);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate V128 SoftFallbackSha1SchedulePart2Delegate(V128 tw0_3, V128 w12_15);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate V128 SoftFallbackSha256SchedulePart1Delegate(V128 w0_3, V128 w4_7);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate V128 SoftFallbackSha256SchedulePart2Delegate(V128 w0_3, V128 w8_11, V128 w12_15);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate long SoftFallbackSignedShrImm64Delegate(long value, long roundConst, int shift);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate V128 SoftFallbackTbl1Delegate(V128 vector, int bytes, V128 table);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate V128 SoftFallbackTbl2Delegate(V128 vector, int bytes, V128 table0, V128 table1);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate V128 SoftFallbackTbl3Delegate(V128 vector, int bytes, V128 table0, V128 table1, V128 table2);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate V128 SoftFallbackTbl4Delegate(V128 vector, int bytes, V128 table0, V128 table1, V128 table2, V128 table3);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate V128 SoftFallbackTbx1Delegate(V128 dest, V128 vector, int bytes, V128 table);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate V128 SoftFallbackTbx2Delegate(V128 dest, V128 vector, int bytes, V128 table0, V128 table1);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate V128 SoftFallbackTbx3Delegate(V128 dest, V128 vector, int bytes, V128 table0, V128 table1, V128 table2);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate V128 SoftFallbackTbx4Delegate(V128 dest, V128 vector, int bytes, V128 table0, V128 table1, V128 table2, V128 table3);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate ulong SoftFallbackUnsignedShrImm64Delegate(ulong value, long roundConst, int shift);
// SoftFloat delegates
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate float SoftFloat16_32FPConvertDelegate(ushort value);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate double SoftFloat16_64FPConvertDelegate(ushort value);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate float SoftFloat32FPAddDelegate(float a, float b);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate float SoftFloat32FPAddFpscrDelegate(float a, float b, byte standardFpscr);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate int SoftFloat32FPCompareDelegate(float a, float b, byte signalNaNs);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate float SoftFloat32FPCompareEQDelegate(float a, float b);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate float SoftFloat32FPCompareEQFpscrDelegate(float a, float b, byte standardFpscr);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate float SoftFloat32FPCompareGEDelegate(float a, float b);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate float SoftFloat32FPCompareGEFpscrDelegate(float a, float b, byte standardFpscr);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate float SoftFloat32FPCompareGTDelegate(float a, float b);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate float SoftFloat32FPCompareGTFpscrDelegate(float a, float b, byte standardFpscr);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate float SoftFloat32FPCompareLEDelegate(float a, float b);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate float SoftFloat32FPCompareLEFpscrDelegate(float a, float b, byte standardFpscr);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate float SoftFloat32FPCompareLTDelegate(float a, float b);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate float SoftFloat32FPCompareLTFpscrDelegate(float a, float b, byte standardFpscr);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate float SoftFloat32FPDivDelegate(float a, float b);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate float SoftFloat32FPMaxDelegate(float a, float b);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate float SoftFloat32FPMaxFpscrDelegate(float a, float b, byte standardFpscr);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate float SoftFloat32FPMaxNumDelegate(float a, float b);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate float SoftFloat32FPMaxNumFpscrDelegate(float a, float b, byte standardFpscr);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate float SoftFloat32FPMinDelegate(float a, float b);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate float SoftFloat32FPMinFpscrDelegate(float a, float b, byte standardFpscr);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate float SoftFloat32FPMinNumDelegate(float a, float b);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate float SoftFloat32FPMinNumFpscrDelegate(float a, float b, byte standardFpscr);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate float SoftFloat32FPMulDelegate(float a, float b);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate float SoftFloat32FPMulFpscrDelegate(float a, float b, byte standardFpscr);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate float SoftFloat32FPMulAddDelegate(float a, float b, float c);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate float SoftFloat32FPMulAddFpscrDelegate(float a, float b, float c, byte standardFpscr);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate float SoftFloat32FPMulSubDelegate(float a, float b, float c);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate float SoftFloat32FPMulSubFpscrDelegate(float a, float b, float c, byte standardFpscr);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate float SoftFloat32FPMulXDelegate(float a, float b);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate float SoftFloat32FPNegMulAddDelegate(float a, float b, float c);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate float SoftFloat32FPNegMulSubDelegate(float a, float b, float c);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate float SoftFloat32FPRecipEstimateDelegate(float a);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate float SoftFloat32FPRecipEstimateFpscrDelegate(float a, byte standardFpscr);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate float SoftFloat32FPRecipStepDelegate(float a, float b);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate float SoftFloat32FPRecipStepFusedDelegate(float a, float b);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate float SoftFloat32FPRecpXDelegate(float a);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate float SoftFloat32FPRSqrtEstimateDelegate(float a);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate float SoftFloat32FPRSqrtEstimateFpscrDelegate(float a, byte standardFpscr);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate float SoftFloat32FPRSqrtStepDelegate(float a, float b);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate float SoftFloat32FPRSqrtStepFusedDelegate(float a, float b);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate float SoftFloat32FPSqrtDelegate(float a);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate float SoftFloat32FPSubDelegate(float a, float b);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate ushort SoftFloat32_16FPConvertDelegate(float value);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate double SoftFloat64FPAddDelegate(double a, double b);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate double SoftFloat64FPAddFpscrDelegate(double a, double b, byte standardFpscr);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate int SoftFloat64FPCompareDelegate(double a, double b, byte signalNaNs);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate double SoftFloat64FPCompareEQDelegate(double a, double b);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate double SoftFloat64FPCompareEQFpscrDelegate(double a, double b, byte standardFpscr);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate double SoftFloat64FPCompareGEDelegate(double a, double b);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate double SoftFloat64FPCompareGEFpscrDelegate(double a, double b, byte standardFpscr);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate double SoftFloat64FPCompareGTDelegate(double a, double b);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate double SoftFloat64FPCompareGTFpscrDelegate(double a, double b, byte standardFpscr);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate double SoftFloat64FPCompareLEDelegate(double a, double b);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate double SoftFloat64FPCompareLEFpscrDelegate(double a, double b, byte standardFpscr);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate double SoftFloat64FPCompareLTDelegate(double a, double b);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate double SoftFloat64FPCompareLTFpscrDelegate(double a, double b, byte standardFpscr);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate double SoftFloat64FPDivDelegate(double a, double b);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate double SoftFloat64FPMaxDelegate(double a, double b);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate double SoftFloat64FPMaxFpscrDelegate(double a, double b, byte standardFpscr);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate double SoftFloat64FPMaxNumDelegate(double a, double b);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate double SoftFloat64FPMaxNumFpscrDelegate(double a, double b, byte standardFpscr);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate double SoftFloat64FPMinDelegate(double a, double b);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate double SoftFloat64FPMinFpscrDelegate(double a, double b, byte standardFpscr);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate double SoftFloat64FPMinNumDelegate(double a, double b);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate double SoftFloat64FPMinNumFpscrDelegate(double a, double b, byte standardFpscr);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate double SoftFloat64FPMulDelegate(double a, double b);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate double SoftFloat64FPMulFpscrDelegate(double a, double b, byte standardFpscr);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate double SoftFloat64FPMulAddDelegate(double a, double b, double c);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate double SoftFloat64FPMulAddFpscrDelegate(double a, double b, double c, byte standardFpscr);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate double SoftFloat64FPMulSubDelegate(double a, double b, double c);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate double SoftFloat64FPMulSubFpscrDelegate(double a, double b, double c, byte standardFpscr);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate double SoftFloat64FPMulXDelegate(double a, double b);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate double SoftFloat64FPNegMulAddDelegate(double a, double b, double c);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate double SoftFloat64FPNegMulSubDelegate(double a, double b, double c);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate double SoftFloat64FPRecipEstimateDelegate(double a);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate double SoftFloat64FPRecipEstimateFpscrDelegate(double a, byte standardFpscr);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate double SoftFloat64FPRecipStepDelegate(double a, double b);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate double SoftFloat64FPRecipStepFusedDelegate(double a, double b);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate double SoftFloat64FPRecpXDelegate(double a);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate double SoftFloat64FPRSqrtEstimateDelegate(double a);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate double SoftFloat64FPRSqrtEstimateFpscrDelegate(double a, byte standardFpscr);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate double SoftFloat64FPRSqrtStepDelegate(double a, double b);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate double SoftFloat64FPRSqrtStepFusedDelegate(double a, double b);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate double SoftFloat64FPSqrtDelegate(double a);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate double SoftFloat64FPSubDelegate(double a, double b);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate ushort SoftFloat64_16FPConvertDelegate(double value);
private static readonly Dictionary<string, Delegate> _androidDelegates;
#endif
public static bool TryGetDelegateFuncPtrByIndex(int index, out nint funcPtr)
{ {
if (index >= 0 && index < _delegates.Count) if (index >= 0 && index < _delegates.Count)
{ {
@@ -23,7 +370,7 @@ namespace ARMeilleure.Translation
} }
} }
public static IntPtr GetDelegateFuncPtrByIndex(int index) public static nint GetDelegateFuncPtrByIndex(int index)
{ {
if (index < 0 || index >= _delegates.Count) if (index < 0 || index >= _delegates.Count)
{ {
@@ -53,7 +400,32 @@ namespace ARMeilleure.Translation
{ {
string key = GetKey(method); string key = GetKey(method);
_delegates.Add(key, new DelegateInfo(method.MethodHandle.GetFunctionPointer())); // ArgumentException (key). #if ANDROID
if (_androidDelegates.TryGetValue(key, out Delegate del))
{
nint funcPtr = Marshal.GetFunctionPointerForDelegate(del);
_delegates.Add(key, new DelegateInfo(funcPtr));
return;
}
#endif
try
{
_delegates.Add(key, new DelegateInfo(method.MethodHandle.GetFunctionPointer()));
}
catch (NotSupportedException) when (IsRunningOnAndroid())
{
throw new PlatformNotSupportedException($"Cannot obtain function pointer {key}: it must be registered.");
}
}
private static bool IsRunningOnAndroid()
{
#if ANDROID
return true;
#else
return false;
#endif
} }
private static string GetKey(MethodInfo info) private static string GetKey(MethodInfo info)
@@ -67,6 +439,190 @@ namespace ARMeilleure.Translation
{ {
_delegates = new SortedList<string, DelegateInfo>(); _delegates = new SortedList<string, DelegateInfo>();
#if ANDROID
_androidDelegates = new Dictionary<string, Delegate>
{
// MathHelper delegates
{ "MathHelper.Abs", new MathHelperAbsDelegate(Math.Abs) },
{ "MathHelper.Ceiling", new MathHelperCeilingDelegate(Math.Ceiling) },
{ "MathHelper.Floor", new MathHelperFloorDelegate(Math.Floor) },
{ "MathHelper.Round", new MathHelperRoundDelegate((value, mode) => Math.Round(value, (MidpointRounding)mode)) },
{ "MathHelper.Truncate", new MathHelperTruncateDelegate(Math.Truncate) },
// MathHelperF delegates
{ "MathHelperF.Abs", new MathHelperFAbsDelegate(MathF.Abs) },
{ "MathHelperF.Ceiling", new MathHelperFCeilingDelegate(MathF.Ceiling) },
{ "MathHelperF.Floor", new MathHelperFFloorDelegate(MathF.Floor) },
{ "MathHelperF.Round", new MathHelperFRoundDelegate((value, mode) => MathF.Round(value, (MidpointRounding)mode)) },
{ "MathHelperF.Truncate", new MathHelperFTruncateDelegate(MathF.Truncate) },
// NativeInterface delegates
{ "NativeInterface.Break", new NativeInterfaceBreakDelegate(NativeInterface.Break) },
{ "NativeInterface.CheckSynchronization", new NativeInterfaceCheckSynchronizationDelegate(NativeInterface.CheckSynchronization) },
{ "NativeInterface.EnqueueForRejit", new NativeInterfaceEnqueueForRejitDelegate(NativeInterface.EnqueueForRejit) },
{ "NativeInterface.GetCntfrqEl0", new NativeInterfaceGetCntfrqEl0Delegate(NativeInterface.GetCntfrqEl0) },
{ "NativeInterface.GetCntpctEl0", new NativeInterfaceGetCntpctEl0Delegate(NativeInterface.GetCntpctEl0) },
{ "NativeInterface.GetCntvctEl0", new NativeInterfaceGetCntvctEl0Delegate(NativeInterface.GetCntvctEl0) },
{ "NativeInterface.GetCtrEl0", new NativeInterfaceGetCtrEl0Delegate(NativeInterface.GetCtrEl0) },
{ "NativeInterface.GetDczidEl0", new NativeInterfaceGetDczidEl0Delegate(NativeInterface.GetDczidEl0) },
{ "NativeInterface.GetFunctionAddress", new NativeInterfaceGetFunctionAddressDelegate(NativeInterface.GetFunctionAddress) },
{ "NativeInterface.InvalidateCacheLine", new NativeInterfaceInvalidateCacheLineDelegate(NativeInterface.InvalidateCacheLine) },
{ "NativeInterface.ReadByte", new NativeInterfaceReadByteDelegate(NativeInterface.ReadByte) },
{ "NativeInterface.ReadUInt16", new NativeInterfaceReadUInt16Delegate(NativeInterface.ReadUInt16) },
{ "NativeInterface.ReadUInt32", new NativeInterfaceReadUInt32Delegate(NativeInterface.ReadUInt32) },
{ "NativeInterface.ReadUInt64", new NativeInterfaceReadUInt64Delegate(NativeInterface.ReadUInt64) },
{ "NativeInterface.ReadVector128", new NativeInterfaceReadVector128Delegate(NativeInterface.ReadVector128) },
{ "NativeInterface.SignalMemoryTracking", new NativeInterfaceSignalMemoryTrackingDelegate(NativeInterface.SignalMemoryTracking) },
{ "NativeInterface.SupervisorCall", new NativeInterfaceSupervisorCallDelegate(NativeInterface.SupervisorCall) },
{ "NativeInterface.ThrowInvalidMemoryAccess", new NativeInterfaceThrowInvalidMemoryAccessDelegate(NativeInterface.ThrowInvalidMemoryAccess) },
{ "NativeInterface.Undefined", new NativeInterfaceUndefinedDelegate(NativeInterface.Undefined) },
{ "NativeInterface.WriteByte", new NativeInterfaceWriteByteDelegate(NativeInterface.WriteByte) },
{ "NativeInterface.WriteUInt16", new NativeInterfaceWriteUInt16Delegate(NativeInterface.WriteUInt16) },
{ "NativeInterface.WriteUInt32", new NativeInterfaceWriteUInt32Delegate(NativeInterface.WriteUInt32) },
{ "NativeInterface.WriteUInt64", new NativeInterfaceWriteUInt64Delegate(NativeInterface.WriteUInt64) },
{ "NativeInterface.WriteVector128", new NativeInterfaceWriteVector128Delegate(NativeInterface.WriteVector128) },
// SoftFallback delegates
{ "SoftFallback.CountLeadingSigns", new SoftFallbackCountLeadingSignsDelegate(SoftFallback.CountLeadingSigns) },
{ "SoftFallback.CountLeadingZeros", new SoftFallbackCountLeadingZerosDelegate(SoftFallback.CountLeadingZeros) },
{ "SoftFallback.Crc32b", new SoftFallbackCrc32bDelegate(SoftFallback.Crc32b) },
{ "SoftFallback.Crc32cb", new SoftFallbackCrc32cbDelegate(SoftFallback.Crc32cb) },
{ "SoftFallback.Crc32ch", new SoftFallbackCrc32chDelegate(SoftFallback.Crc32ch) },
{ "SoftFallback.Crc32cw", new SoftFallbackCrc32cwDelegate(SoftFallback.Crc32cw) },
{ "SoftFallback.Crc32cx", new SoftFallbackCrc32cxDelegate(SoftFallback.Crc32cx) },
{ "SoftFallback.Crc32h", new SoftFallbackCrc32hDelegate(SoftFallback.Crc32h) },
{ "SoftFallback.Crc32w", new SoftFallbackCrc32wDelegate(SoftFallback.Crc32w) },
{ "SoftFallback.Crc32x", new SoftFallbackCrc32xDelegate(SoftFallback.Crc32x) },
{ "SoftFallback.Decrypt", new SoftFallbackDecryptDelegate(SoftFallback.Decrypt) },
{ "SoftFallback.Encrypt", new SoftFallbackEncryptDelegate(SoftFallback.Encrypt) },
{ "SoftFallback.FixedRotate", new SoftFallbackFixedRotateDelegate(SoftFallback.FixedRotate) },
{ "SoftFallback.HashChoose", new SoftFallbackHashChooseDelegate(SoftFallback.HashChoose) },
{ "SoftFallback.HashLower", new SoftFallbackHashLowerDelegate(SoftFallback.HashLower) },
{ "SoftFallback.HashMajority", new SoftFallbackHashMajorityDelegate(SoftFallback.HashMajority) },
{ "SoftFallback.HashParity", new SoftFallbackHashParityDelegate(SoftFallback.HashParity) },
{ "SoftFallback.HashUpper", new SoftFallbackHashUpperDelegate(SoftFallback.HashUpper) },
{ "SoftFallback.InverseMixColumns", new SoftFallbackInverseMixColumnsDelegate(SoftFallback.InverseMixColumns) },
{ "SoftFallback.MixColumns", new SoftFallbackMixColumnsDelegate(SoftFallback.MixColumns) },
{ "SoftFallback.PolynomialMult64_128", new SoftFallbackPolynomialMult64_128Delegate(SoftFallback.PolynomialMult64_128) },
{ "SoftFallback.SatF32ToS32", new SoftFallbackSatF32ToS32Delegate(SoftFallback.SatF32ToS32) },
{ "SoftFallback.SatF32ToS64", new SoftFallbackSatF32ToS64Delegate(SoftFallback.SatF32ToS64) },
{ "SoftFallback.SatF32ToU32", new SoftFallbackSatF32ToU32Delegate(SoftFallback.SatF32ToU32) },
{ "SoftFallback.SatF32ToU64", new SoftFallbackSatF32ToU64Delegate(SoftFallback.SatF32ToU64) },
{ "SoftFallback.SatF64ToS32", new SoftFallbackSatF64ToS32Delegate(SoftFallback.SatF64ToS32) },
{ "SoftFallback.SatF64ToS64", new SoftFallbackSatF64ToS64Delegate(SoftFallback.SatF64ToS64) },
{ "SoftFallback.SatF64ToU32", new SoftFallbackSatF64ToU32Delegate(SoftFallback.SatF64ToU32) },
{ "SoftFallback.SatF64ToU64", new SoftFallbackSatF64ToU64Delegate(SoftFallback.SatF64ToU64) },
{ "SoftFallback.Sha1SchedulePart1", new SoftFallbackSha1SchedulePart1Delegate(SoftFallback.Sha1SchedulePart1) },
{ "SoftFallback.Sha1SchedulePart2", new SoftFallbackSha1SchedulePart2Delegate(SoftFallback.Sha1SchedulePart2) },
{ "SoftFallback.Sha256SchedulePart1", new SoftFallbackSha256SchedulePart1Delegate(SoftFallback.Sha256SchedulePart1) },
{ "SoftFallback.Sha256SchedulePart2", new SoftFallbackSha256SchedulePart2Delegate(SoftFallback.Sha256SchedulePart2) },
{ "SoftFallback.SignedShrImm64", new SoftFallbackSignedShrImm64Delegate(SoftFallback.SignedShrImm64) },
{ "SoftFallback.Tbl1", new SoftFallbackTbl1Delegate(SoftFallback.Tbl1) },
{ "SoftFallback.Tbl2", new SoftFallbackTbl2Delegate(SoftFallback.Tbl2) },
{ "SoftFallback.Tbl3", new SoftFallbackTbl3Delegate(SoftFallback.Tbl3) },
{ "SoftFallback.Tbl4", new SoftFallbackTbl4Delegate(SoftFallback.Tbl4) },
{ "SoftFallback.Tbx1", new SoftFallbackTbx1Delegate(SoftFallback.Tbx1) },
{ "SoftFallback.Tbx2", new SoftFallbackTbx2Delegate(SoftFallback.Tbx2) },
{ "SoftFallback.Tbx3", new SoftFallbackTbx3Delegate(SoftFallback.Tbx3) },
{ "SoftFallback.Tbx4", new SoftFallbackTbx4Delegate(SoftFallback.Tbx4) },
{ "SoftFallback.UnsignedShrImm64", new SoftFallbackUnsignedShrImm64Delegate(SoftFallback.UnsignedShrImm64) },
// SoftFloat delegates
{ "SoftFloat16_32.FPConvert", new SoftFloat16_32FPConvertDelegate(SoftFloat16_32.FPConvert) },
{ "SoftFloat16_64.FPConvert", new SoftFloat16_64FPConvertDelegate(SoftFloat16_64.FPConvert) },
{ "SoftFloat32.FPAdd", new SoftFloat32FPAddDelegate(SoftFloat32.FPAdd) },
{ "SoftFloat32.FPAddFpscr", new SoftFloat32FPAddFpscrDelegate(SoftFloat32.FPAddFpscr) },
{ "SoftFloat32.FPCompare", new SoftFloat32FPCompareDelegate(SoftFloat32.FPCompare) },
{ "SoftFloat32.FPCompareEQ", new SoftFloat32FPCompareEQDelegate(SoftFloat32.FPCompareEQ) },
{ "SoftFloat32.FPCompareEQFpscr", new SoftFloat32FPCompareEQFpscrDelegate(SoftFloat32.FPCompareEQFpscr) },
{ "SoftFloat32.FPCompareGE", new SoftFloat32FPCompareGEDelegate(SoftFloat32.FPCompareGE) },
{ "SoftFloat32.FPCompareGEFpscr", new SoftFloat32FPCompareGEFpscrDelegate(SoftFloat32.FPCompareGEFpscr) },
{ "SoftFloat32.FPCompareGT", new SoftFloat32FPCompareGTDelegate(SoftFloat32.FPCompareGT) },
{ "SoftFloat32.FPCompareGTFpscr", new SoftFloat32FPCompareGTFpscrDelegate(SoftFloat32.FPCompareGTFpscr) },
{ "SoftFloat32.FPCompareLE", new SoftFloat32FPCompareLEDelegate(SoftFloat32.FPCompareLE) },
{ "SoftFloat32.FPCompareLEFpscr", new SoftFloat32FPCompareLEFpscrDelegate(SoftFloat32.FPCompareLEFpscr) },
{ "SoftFloat32.FPCompareLT", new SoftFloat32FPCompareLTDelegate(SoftFloat32.FPCompareLT) },
{ "SoftFloat32.FPCompareLTFpscr", new SoftFloat32FPCompareLTFpscrDelegate(SoftFloat32.FPCompareLTFpscr) },
{ "SoftFloat32.FPDiv", new SoftFloat32FPDivDelegate(SoftFloat32.FPDiv) },
{ "SoftFloat32.FPMax", new SoftFloat32FPMaxDelegate(SoftFloat32.FPMax) },
{ "SoftFloat32.FPMaxFpscr", new SoftFloat32FPMaxFpscrDelegate(SoftFloat32.FPMaxFpscr) },
{ "SoftFloat32.FPMaxNum", new SoftFloat32FPMaxNumDelegate(SoftFloat32.FPMaxNum) },
{ "SoftFloat32.FPMaxNumFpscr", new SoftFloat32FPMaxNumFpscrDelegate(SoftFloat32.FPMaxNumFpscr) },
{ "SoftFloat32.FPMin", new SoftFloat32FPMinDelegate(SoftFloat32.FPMin) },
{ "SoftFloat32.FPMinFpscr", new SoftFloat32FPMinFpscrDelegate(SoftFloat32.FPMinFpscr) },
{ "SoftFloat32.FPMinNum", new SoftFloat32FPMinNumDelegate(SoftFloat32.FPMinNum) },
{ "SoftFloat32.FPMinNumFpscr", new SoftFloat32FPMinNumFpscrDelegate(SoftFloat32.FPMinNumFpscr) },
{ "SoftFloat32.FPMul", new SoftFloat32FPMulDelegate(SoftFloat32.FPMul) },
{ "SoftFloat32.FPMulFpscr", new SoftFloat32FPMulFpscrDelegate(SoftFloat32.FPMulFpscr) },
{ "SoftFloat32.FPMulAdd", new SoftFloat32FPMulAddDelegate(SoftFloat32.FPMulAdd) },
{ "SoftFloat32.FPMulAddFpscr", new SoftFloat32FPMulAddFpscrDelegate(SoftFloat32.FPMulAddFpscr) },
{ "SoftFloat32.FPMulSub", new SoftFloat32FPMulSubDelegate(SoftFloat32.FPMulSub) },
{ "SoftFloat32.FPMulSubFpscr", new SoftFloat32FPMulSubFpscrDelegate(SoftFloat32.FPMulSubFpscr) },
{ "SoftFloat32.FPMulX", new SoftFloat32FPMulXDelegate(SoftFloat32.FPMulX) },
{ "SoftFloat32.FPNegMulAdd", new SoftFloat32FPNegMulAddDelegate(SoftFloat32.FPNegMulAdd) },
{ "SoftFloat32.FPNegMulSub", new SoftFloat32FPNegMulSubDelegate(SoftFloat32.FPNegMulSub) },
{ "SoftFloat32.FPRecipEstimate", new SoftFloat32FPRecipEstimateDelegate(SoftFloat32.FPRecipEstimate) },
{ "SoftFloat32.FPRecipEstimateFpscr", new SoftFloat32FPRecipEstimateFpscrDelegate(SoftFloat32.FPRecipEstimateFpscr) },
{ "SoftFloat32.FPRecipStep", new SoftFloat32FPRecipStepDelegate(SoftFloat32.FPRecipStep) },
{ "SoftFloat32.FPRecipStepFused", new SoftFloat32FPRecipStepFusedDelegate(SoftFloat32.FPRecipStepFused) },
{ "SoftFloat32.FPRecpX", new SoftFloat32FPRecpXDelegate(SoftFloat32.FPRecpX) },
{ "SoftFloat32.FPRSqrtEstimate", new SoftFloat32FPRSqrtEstimateDelegate(SoftFloat32.FPRSqrtEstimate) },
{ "SoftFloat32.FPRSqrtEstimateFpscr", new SoftFloat32FPRSqrtEstimateFpscrDelegate(SoftFloat32.FPRSqrtEstimateFpscr) },
{ "SoftFloat32.FPRSqrtStep", new SoftFloat32FPRSqrtStepDelegate(SoftFloat32.FPRSqrtStep) },
{ "SoftFloat32.FPRSqrtStepFused", new SoftFloat32FPRSqrtStepFusedDelegate(SoftFloat32.FPRSqrtStepFused) },
{ "SoftFloat32.FPSqrt", new SoftFloat32FPSqrtDelegate(SoftFloat32.FPSqrt) },
{ "SoftFloat32.FPSub", new SoftFloat32FPSubDelegate(SoftFloat32.FPSub) },
{ "SoftFloat32_16.FPConvert", new SoftFloat32_16FPConvertDelegate(SoftFloat32_16.FPConvert) },
{ "SoftFloat64.FPAdd", new SoftFloat64FPAddDelegate(SoftFloat64.FPAdd) },
{ "SoftFloat64.FPAddFpscr", new SoftFloat64FPAddFpscrDelegate(SoftFloat64.FPAddFpscr) },
{ "SoftFloat64.FPCompare", new SoftFloat64FPCompareDelegate(SoftFloat64.FPCompare) },
{ "SoftFloat64.FPCompareEQ", new SoftFloat64FPCompareEQDelegate(SoftFloat64.FPCompareEQ) },
{ "SoftFloat64.FPCompareEQFpscr", new SoftFloat64FPCompareEQFpscrDelegate(SoftFloat64.FPCompareEQFpscr) },
{ "SoftFloat64.FPCompareGE", new SoftFloat64FPCompareGEDelegate(SoftFloat64.FPCompareGE) },
{ "SoftFloat64.FPCompareGEFpscr", new SoftFloat64FPCompareGEFpscrDelegate(SoftFloat64.FPCompareGEFpscr) },
{ "SoftFloat64.FPCompareGT", new SoftFloat64FPCompareGTDelegate(SoftFloat64.FPCompareGT) },
{ "SoftFloat64.FPCompareGTFpscr", new SoftFloat64FPCompareGTFpscrDelegate(SoftFloat64.FPCompareGTFpscr) },
{ "SoftFloat64.FPCompareLE", new SoftFloat64FPCompareLEDelegate(SoftFloat64.FPCompareLE) },
{ "SoftFloat64.FPCompareLEFpscr", new SoftFloat64FPCompareLEFpscrDelegate(SoftFloat64.FPCompareLEFpscr) },
{ "SoftFloat64.FPCompareLT", new SoftFloat64FPCompareLTDelegate(SoftFloat64.FPCompareLT) },
{ "SoftFloat64.FPCompareLTFpscr", new SoftFloat64FPCompareLTFpscrDelegate(SoftFloat64.FPCompareLTFpscr) },
{ "SoftFloat64.FPDiv", new SoftFloat64FPDivDelegate(SoftFloat64.FPDiv) },
{ "SoftFloat64.FPMax", new SoftFloat64FPMaxDelegate(SoftFloat64.FPMax) },
{ "SoftFloat64.FPMaxFpscr", new SoftFloat64FPMaxFpscrDelegate(SoftFloat64.FPMaxFpscr) },
{ "SoftFloat64.FPMaxNum", new SoftFloat64FPMaxNumDelegate(SoftFloat64.FPMaxNum) },
{ "SoftFloat64.FPMaxNumFpscr", new SoftFloat64FPMaxNumFpscrDelegate(SoftFloat64.FPMaxNumFpscr) },
{ "SoftFloat64.FPMin", new SoftFloat64FPMinDelegate(SoftFloat64.FPMin) },
{ "SoftFloat64.FPMinFpscr", new SoftFloat64FPMinFpscrDelegate(SoftFloat64.FPMinFpscr) },
{ "SoftFloat64.FPMinNum", new SoftFloat64FPMinNumDelegate(SoftFloat64.FPMinNum) },
{ "SoftFloat64.FPMinNumFpscr", new SoftFloat64FPMinNumFpscrDelegate(SoftFloat64.FPMinNumFpscr) },
{ "SoftFloat64.FPMul", new SoftFloat64FPMulDelegate(SoftFloat64.FPMul) },
{ "SoftFloat64.FPMulFpscr", new SoftFloat64FPMulFpscrDelegate(SoftFloat64.FPMulFpscr) },
{ "SoftFloat64.FPMulAdd", new SoftFloat64FPMulAddDelegate(SoftFloat64.FPMulAdd) },
{ "SoftFloat64.FPMulAddFpscr", new SoftFloat64FPMulAddFpscrDelegate(SoftFloat64.FPMulAddFpscr) },
{ "SoftFloat64.FPMulSub", new SoftFloat64FPMulSubDelegate(SoftFloat64.FPMulSub) },
{ "SoftFloat64.FPMulSubFpscr", new SoftFloat64FPMulSubFpscrDelegate(SoftFloat64.FPMulSubFpscr) },
{ "SoftFloat64.FPMulX", new SoftFloat64FPMulXDelegate(SoftFloat64.FPMulX) },
{ "SoftFloat64.FPNegMulAdd", new SoftFloat64FPNegMulAddDelegate(SoftFloat64.FPNegMulAdd) },
{ "SoftFloat64.FPNegMulSub", new SoftFloat64FPNegMulSubDelegate(SoftFloat64.FPNegMulSub) },
{ "SoftFloat64.FPRecipEstimate", new SoftFloat64FPRecipEstimateDelegate(SoftFloat64.FPRecipEstimate) },
{ "SoftFloat64.FPRecipEstimateFpscr", new SoftFloat64FPRecipEstimateFpscrDelegate(SoftFloat64.FPRecipEstimateFpscr) },
{ "SoftFloat64.FPRecipStep", new SoftFloat64FPRecipStepDelegate(SoftFloat64.FPRecipStep) },
{ "SoftFloat64.FPRecipStepFused", new SoftFloat64FPRecipStepFusedDelegate(SoftFloat64.FPRecipStepFused) },
{ "SoftFloat64.FPRecpX", new SoftFloat64FPRecpXDelegate(SoftFloat64.FPRecpX) },
{ "SoftFloat64.FPRSqrtEstimate", new SoftFloat64FPRSqrtEstimateDelegate(SoftFloat64.FPRSqrtEstimate) },
{ "SoftFloat64.FPRSqrtEstimateFpscr", new SoftFloat64FPRSqrtEstimateFpscrDelegate(SoftFloat64.FPRSqrtEstimateFpscr) },
{ "SoftFloat64.FPRSqrtStep", new SoftFloat64FPRSqrtStepDelegate(SoftFloat64.FPRSqrtStep) },
{ "SoftFloat64.FPRSqrtStepFused", new SoftFloat64FPRSqrtStepFusedDelegate(SoftFloat64.FPRSqrtStepFused) },
{ "SoftFloat64.FPSqrt", new SoftFloat64FPSqrtDelegate(SoftFloat64.FPSqrt) },
{ "SoftFloat64.FPSub", new SoftFloat64FPSubDelegate(SoftFloat64.FPSub) },
{ "SoftFloat64_16.FPConvert", new SoftFloat64_16FPConvertDelegate(SoftFloat64_16.FPConvert) }
};
#endif
SetDelegateInfo(typeof(MathHelper).GetMethod(nameof(MathHelper.Abs))); SetDelegateInfo(typeof(MathHelper).GetMethod(nameof(MathHelper.Abs)));
SetDelegateInfo(typeof(MathHelper).GetMethod(nameof(MathHelper.Ceiling))); SetDelegateInfo(typeof(MathHelper).GetMethod(nameof(MathHelper.Ceiling)));
SetDelegateInfo(typeof(MathHelper).GetMethod(nameof(MathHelper.Floor))); SetDelegateInfo(typeof(MathHelper).GetMethod(nameof(MathHelper.Floor)));
@@ -152,44 +708,44 @@ namespace ARMeilleure.Translation
SetDelegateInfo(typeof(SoftFloat16_64).GetMethod(nameof(SoftFloat16_64.FPConvert))); SetDelegateInfo(typeof(SoftFloat16_64).GetMethod(nameof(SoftFloat16_64.FPConvert)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPAdd))); SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPAdd)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPAddFpscr))); // A32 only. SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPAddFpscr)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompare))); SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompare)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareEQ))); SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareEQ)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareEQFpscr))); // A32 only. SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareEQFpscr)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareGE))); SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareGE)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareGEFpscr))); // A32 only. SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareGEFpscr)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareGT))); SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareGT)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareGTFpscr))); // A32 only. SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareGTFpscr)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareLE))); SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareLE)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareLEFpscr))); // A32 only. SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareLEFpscr)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareLT))); SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareLT)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareLTFpscr))); // A32 only. SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareLTFpscr)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPDiv))); SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPDiv)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMax))); SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMax)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMaxFpscr))); // A32 only. SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMaxFpscr)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMaxNum))); SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMaxNum)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMaxNumFpscr))); // A32 only. SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMaxNumFpscr)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMin))); SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMin)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMinFpscr))); // A32 only. SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMinFpscr)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMinNum))); SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMinNum)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMinNumFpscr))); // A32 only. SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMinNumFpscr)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMul))); SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMul)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulFpscr))); // A32 only. SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulFpscr)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulAdd))); SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulAdd)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulAddFpscr))); // A32 only. SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulAddFpscr)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulSub))); SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulSub)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulSubFpscr))); // A32 only. SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulSubFpscr)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulX))); SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulX)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPNegMulAdd))); SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPNegMulAdd)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPNegMulSub))); SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPNegMulSub)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRecipEstimate))); SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRecipEstimate)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRecipEstimateFpscr))); // A32 only. SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRecipEstimateFpscr)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRecipStep))); // A32 only. SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRecipStep)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRecipStepFused))); SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRecipStepFused)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRecpX))); SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRecpX)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRSqrtEstimate))); SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRSqrtEstimate)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRSqrtEstimateFpscr))); // A32 only. SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRSqrtEstimateFpscr)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRSqrtStep))); // A32 only. SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRSqrtStep)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRSqrtStepFused))); SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRSqrtStepFused)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPSqrt))); SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPSqrt)));
SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPSub))); SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPSub)));
@@ -197,44 +753,44 @@ namespace ARMeilleure.Translation
SetDelegateInfo(typeof(SoftFloat32_16).GetMethod(nameof(SoftFloat32_16.FPConvert))); SetDelegateInfo(typeof(SoftFloat32_16).GetMethod(nameof(SoftFloat32_16.FPConvert)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPAdd))); SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPAdd)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPAddFpscr))); // A32 only. SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPAddFpscr)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompare))); SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompare)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareEQ))); SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareEQ)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareEQFpscr))); // A32 only. SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareEQFpscr)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareGE))); SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareGE)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareGEFpscr))); // A32 only. SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareGEFpscr)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareGT))); SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareGT)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareGTFpscr))); // A32 only. SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareGTFpscr)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareLE))); SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareLE)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareLEFpscr))); // A32 only. SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareLEFpscr)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareLT))); SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareLT)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareLTFpscr))); // A32 only. SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareLTFpscr)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPDiv))); SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPDiv)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMax))); SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMax)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMaxFpscr))); // A32 only. SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMaxFpscr)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMaxNum))); SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMaxNum)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMaxNumFpscr))); // A32 only. SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMaxNumFpscr)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMin))); SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMin)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMinFpscr))); // A32 only. SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMinFpscr)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMinNum))); SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMinNum)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMinNumFpscr))); // A32 only. SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMinNumFpscr)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMul))); SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMul)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulFpscr))); // A32 only. SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulFpscr)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulAdd))); SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulAdd)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulAddFpscr))); // A32 only. SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulAddFpscr)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulSub))); SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulSub)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulSubFpscr))); // A32 only. SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulSubFpscr)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulX))); SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulX)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPNegMulAdd))); SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPNegMulAdd)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPNegMulSub))); SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPNegMulSub)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRecipEstimate))); SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRecipEstimate)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRecipEstimateFpscr))); // A32 only. SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRecipEstimateFpscr)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRecipStep))); // A32 only. SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRecipStep)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRecipStepFused))); SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRecipStepFused)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRecpX))); SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRecpX)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRSqrtEstimate))); SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRSqrtEstimate)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRSqrtEstimateFpscr))); // A32 only. SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRSqrtEstimateFpscr)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRSqrtStep))); // A32 only. SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRSqrtStep)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRSqrtStepFused))); SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRSqrtStepFused)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPSqrt))); SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPSqrt)));
SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPSub))); SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPSub)));
@@ -1,7 +1,5 @@
using System;
namespace ARMeilleure.Translation namespace ARMeilleure.Translation
{ {
delegate void DispatcherFunction(IntPtr nativeContext, ulong startAddress); delegate void DispatcherFunction(nint nativeContext, ulong startAddress);
delegate ulong WrapperFunction(IntPtr nativeContext, ulong startAddress); delegate ulong WrapperFunction(nint nativeContext, ulong startAddress);
} }
@@ -97,7 +97,14 @@ namespace ARMeilleure.Translation
public virtual Operand Call(MethodInfo info, params Operand[] callArgs) public virtual Operand Call(MethodInfo info, params Operand[] callArgs)
{ {
IntPtr funcPtr = info.MethodHandle.GetFunctionPointer(); #if ANDROID
// For Android, use the Delegates class to get the function pointer
int index = Delegates.GetDelegateIndex(info);
nint funcPtr = Delegates.GetDelegateFuncPtrByIndex(index);
#else
// For other platforms, use direct method handle approach
nint funcPtr = info.MethodHandle.GetFunctionPointer();
#endif
OperandType returnType = GetOperandType(info.ReturnType); OperandType returnType = GetOperandType(info.ReturnType);
+1 -3
View File
@@ -1,6 +1,4 @@
using System;
namespace ARMeilleure.Translation namespace ARMeilleure.Translation
{ {
delegate ulong GuestFunction(IntPtr nativeContextPtr); delegate ulong GuestFunction(nint nativeContextPtr);
} }
+1 -1
View File
@@ -316,7 +316,7 @@ namespace ARMeilleure.Translation
{ {
_root = newNode; _root = newNode;
} }
else if (start.CompareTo(parent.Start) < 0) else if (start.CompareTo(parent!.Start) < 0)
{ {
parent.Left = newNode; parent.Left = newNode;
} }
+51 -47
View File
@@ -10,6 +10,7 @@ using Ryujinx.Common.Logging;
using Ryujinx.Common.Memory; using Ryujinx.Common.Memory;
using System; using System;
using System.Buffers.Binary; using System.Buffers.Binary;
using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
@@ -30,14 +31,11 @@ namespace ARMeilleure.Translation.PTC
private const string OuterHeaderMagicString = "PTCohd\0\0"; private const string OuterHeaderMagicString = "PTCohd\0\0";
private const string InnerHeaderMagicString = "PTCihd\0\0"; private const string InnerHeaderMagicString = "PTCihd\0\0";
private const uint InternalVersion = 7010; //! To be incremented manually for each change to the ARMeilleure project. private const uint InternalVersion = 7031; //! To be incremented manually for each change to the ARMeilleure project.
private const string ActualDir = "0"; private const string ActualDir = "0";
private const string BackupDir = "1"; private const string BackupDir = "1";
private const string TitleIdTextDefault = "0000000000000000";
private const string DisplayVersionDefault = "0";
public static readonly Symbol PageTableSymbol = new(SymbolType.Special, 1); public static readonly Symbol PageTableSymbol = new(SymbolType.Special, 1);
public static readonly Symbol CountTableSymbol = new(SymbolType.Special, 2); public static readonly Symbol CountTableSymbol = new(SymbolType.Special, 2);
public static readonly Symbol DispatchStubSymbol = new(SymbolType.Special, 3); public static readonly Symbol DispatchStubSymbol = new(SymbolType.Special, 3);
@@ -63,8 +61,7 @@ namespace ARMeilleure.Translation.PTC
private bool _disposed; private bool _disposed;
public string TitleIdText { get; private set; } public PtcCacheInfo CacheInfo { get; private set; }
public string DisplayVersion { get; private set; }
private MemoryManagerType _memoryMode; private MemoryManagerType _memoryMode;
@@ -91,8 +88,7 @@ namespace ARMeilleure.Translation.PTC
_disposed = false; _disposed = false;
TitleIdText = TitleIdTextDefault; CacheInfo = new PtcCacheInfo(0, null, null, 0, null, "Unknown", "default");
DisplayVersion = DisplayVersionDefault;
CachePathActual = string.Empty; CachePathActual = string.Empty;
CachePathBackup = string.Empty; CachePathBackup = string.Empty;
@@ -100,20 +96,24 @@ namespace ARMeilleure.Translation.PTC
Disable(); Disable();
} }
public void Initialize(string titleIdText, string displayVersion, bool enabled, MemoryManagerType memoryMode, string cacheSelector) public void Initialize(PtcCacheInfo cacheInfo, bool enabled, MemoryManagerType memoryMode)
{ {
Wait(); Wait();
Profiler.Wait(); Profiler.Wait();
Profiler.ClearEntries(); Profiler.ClearEntries();
Logger.Info?.Print(LogClass.Ptc, $"Initializing Profiled Persistent Translation Cache (enabled: {enabled})."); CacheInfo = cacheInfo;
if (!enabled || string.IsNullOrEmpty(titleIdText) || titleIdText == TitleIdTextDefault) Logger.Info?.Print(
LogClass.Ptc,
$"Initializing Profiled Persistent Translation Cache v{InternalVersion}\n\t\t " +
$"(pid: {cacheInfo.ProcessId}, title: {cacheInfo.TitleIdText}, application: {cacheInfo.ApplicationIdText}, " +
$"programIndex: {cacheInfo.ProgramIndex}, version: '{cacheInfo.DisplayVersion}', kind: {cacheInfo.ProcessKind}, " +
$"selector: '{cacheInfo.CacheSelector}', key: '{cacheInfo.CacheKey}', enabled: {enabled}).");
if (!enabled || cacheInfo.TitleIdText == PtcCacheInfo.TitleIdTextDefault)
{ {
TitleIdText = TitleIdTextDefault;
DisplayVersion = DisplayVersionDefault;
CachePathActual = string.Empty; CachePathActual = string.Empty;
CachePathBackup = string.Empty; CachePathBackup = string.Empty;
@@ -122,14 +122,10 @@ namespace ARMeilleure.Translation.PTC
return; return;
} }
TitleIdText = titleIdText;
DisplayVersion = !string.IsNullOrEmpty(displayVersion) ? displayVersion : DisplayVersionDefault;
_memoryMode = memoryMode; _memoryMode = memoryMode;
Logger.Info?.Print(LogClass.Ptc, $"PPTC (v{InternalVersion}) Profile: {DisplayVersion}-{cacheSelector}"); string workPathActual = Path.Combine(AppDataManager.GamesDirPath, CacheInfo.TitleIdText, "cache", "cpu", ActualDir);
string workPathBackup = Path.Combine(AppDataManager.GamesDirPath, CacheInfo.TitleIdText, "cache", "cpu", BackupDir);
string workPathActual = Path.Combine(AppDataManager.GamesDirPath, TitleIdText, "cache", "cpu", ActualDir);
string workPathBackup = Path.Combine(AppDataManager.GamesDirPath, TitleIdText, "cache", "cpu", BackupDir);
if (!Directory.Exists(workPathActual)) if (!Directory.Exists(workPathActual))
{ {
@@ -141,8 +137,14 @@ namespace ARMeilleure.Translation.PTC
Directory.CreateDirectory(workPathBackup); Directory.CreateDirectory(workPathBackup);
} }
CachePathActual = Path.Combine(workPathActual, DisplayVersion) + "-" + cacheSelector; CachePathActual = Path.Combine(workPathActual, CacheInfo.DisplayVersion) + "-" + CacheInfo.CacheSelector;
CachePathBackup = Path.Combine(workPathBackup, DisplayVersion) + "-" + cacheSelector; CachePathBackup = Path.Combine(workPathBackup, CacheInfo.DisplayVersion) + "-" + CacheInfo.CacheSelector;
Logger.Info?.Print(
LogClass.Ptc,
$"PPTC cache owner selected (pid: {CacheInfo.ProcessId}, title: {CacheInfo.TitleIdText}, application: {CacheInfo.ApplicationIdText}, " +
$"version: '{CacheInfo.DisplayVersion}', kind: {CacheInfo.ProcessKind}, selector: '{CacheInfo.CacheSelector}', " +
$"key: '{CacheInfo.CacheKey}', path: '{CachePathActual}').");
PreLoad(); PreLoad();
Profiler.PreLoad(); Profiler.PreLoad();
@@ -251,19 +253,18 @@ namespace ARMeilleure.Translation.PTC
outerHeader.FeatureInfo != GetFeatureInfo() || outerHeader.FeatureInfo != GetFeatureInfo() ||
outerHeader.MemoryManagerMode != GetMemoryManagerMode() || outerHeader.MemoryManagerMode != GetMemoryManagerMode() ||
outerHeader.OSPlatform != GetOSPlatform() || outerHeader.OSPlatform != GetOSPlatform() ||
outerHeader.Architecture != (uint)RuntimeInformation.ProcessArchitecture || outerHeader.Architecture != (uint)RuntimeInformation.ProcessArchitecture)
outerHeader.DebuggerMode != Optimizations.EnableDebugging)
{ {
InvalidateCompressedStream(compressedStream); InvalidateCompressedStream(compressedStream);
return false; return false;
} }
IntPtr intPtr = IntPtr.Zero; nint intPtr = nint.Zero;
try try
{ {
intPtr = Marshal.AllocHGlobal(new IntPtr(outerHeader.UncompressedStreamSize)); intPtr = Marshal.AllocHGlobal(new nint(outerHeader.UncompressedStreamSize));
using UnmanagedMemoryStream stream = new((byte*)intPtr.ToPointer(), outerHeader.UncompressedStreamSize, outerHeader.UncompressedStreamSize, FileAccess.ReadWrite); using UnmanagedMemoryStream stream = new((byte*)intPtr.ToPointer(), outerHeader.UncompressedStreamSize, outerHeader.UncompressedStreamSize, FileAccess.ReadWrite);
try try
@@ -357,7 +358,7 @@ namespace ARMeilleure.Translation.PTC
} }
finally finally
{ {
if (intPtr != IntPtr.Zero) if (intPtr != nint.Zero)
{ {
Marshal.FreeHGlobal(intPtr); Marshal.FreeHGlobal(intPtr);
} }
@@ -366,7 +367,12 @@ namespace ARMeilleure.Translation.PTC
long fileSize = new FileInfo(fileName).Length; long fileSize = new FileInfo(fileName).Length;
Logger.Info?.Print(LogClass.Ptc, $"{(isBackup ? "Loaded Backup Translation Cache" : "Loaded Translation Cache")} (size: {fileSize} bytes, translated functions: {GetEntriesCount()})."); Logger.Info?.Print(
LogClass.Ptc,
$"{(isBackup ? "Loaded Backup Translation Cache" : "Loaded Translation Cache")} " +
$"(pid: {CacheInfo.ProcessId}, title: {CacheInfo.TitleIdText}, version: '{CacheInfo.DisplayVersion}', kind: {CacheInfo.ProcessKind}, " +
$"selector: '{CacheInfo.CacheSelector}', key: '{CacheInfo.CacheKey}', path: '{fileName}', " +
$"size: {fileSize} bytes, translated functions: {GetEntriesCount()}).");
return true; return true;
} }
@@ -428,7 +434,6 @@ namespace ARMeilleure.Translation.PTC
MemoryManagerMode = GetMemoryManagerMode(), MemoryManagerMode = GetMemoryManagerMode(),
OSPlatform = GetOSPlatform(), OSPlatform = GetOSPlatform(),
Architecture = (uint)RuntimeInformation.ProcessArchitecture, Architecture = (uint)RuntimeInformation.ProcessArchitecture,
DebuggerMode = Optimizations.EnableDebugging,
UncompressedStreamSize = UncompressedStreamSize =
(long)Unsafe.SizeOf<InnerHeader>() + (long)Unsafe.SizeOf<InnerHeader>() +
@@ -440,11 +445,11 @@ namespace ARMeilleure.Translation.PTC
outerHeader.SetHeaderHash(); outerHeader.SetHeaderHash();
IntPtr intPtr = IntPtr.Zero; nint intPtr = nint.Zero;
try try
{ {
intPtr = Marshal.AllocHGlobal(new IntPtr(outerHeader.UncompressedStreamSize)); intPtr = Marshal.AllocHGlobal(new nint(outerHeader.UncompressedStreamSize));
using UnmanagedMemoryStream stream = new((byte*)intPtr.ToPointer(), outerHeader.UncompressedStreamSize, outerHeader.UncompressedStreamSize, FileAccess.ReadWrite); using UnmanagedMemoryStream stream = new((byte*)intPtr.ToPointer(), outerHeader.UncompressedStreamSize, outerHeader.UncompressedStreamSize, FileAccess.ReadWrite);
stream.Seek((long)Unsafe.SizeOf<InnerHeader>(), SeekOrigin.Begin); stream.Seek((long)Unsafe.SizeOf<InnerHeader>(), SeekOrigin.Begin);
@@ -498,7 +503,7 @@ namespace ARMeilleure.Translation.PTC
} }
finally finally
{ {
if (intPtr != IntPtr.Zero) if (intPtr != nint.Zero)
{ {
Marshal.FreeHGlobal(intPtr); Marshal.FreeHGlobal(intPtr);
} }
@@ -546,7 +551,7 @@ namespace ARMeilleure.Translation.PTC
bool isEntryChanged = infoEntry.Hash != ComputeHash(translator.Memory, infoEntry.Address, infoEntry.GuestSize); bool isEntryChanged = infoEntry.Hash != ComputeHash(translator.Memory, infoEntry.Address, infoEntry.GuestSize);
if (isEntryChanged || (!infoEntry.HighCq && Profiler.ProfiledFuncs.TryGetValue(infoEntry.Address, out var value) && value.HighCq)) if (isEntryChanged || (!infoEntry.HighCq && Profiler.ProfiledFuncs.TryGetValue(infoEntry.Address, out PtcProfiler.FuncProfile value) && value.HighCq))
{ {
infoEntry.Stubbed = true; infoEntry.Stubbed = true;
infoEntry.CodeLength = 0; infoEntry.CodeLength = 0;
@@ -650,7 +655,7 @@ namespace ARMeilleure.Translation.PTC
foreach (RelocEntry relocEntry in relocEntries) foreach (RelocEntry relocEntry in relocEntries)
{ {
IntPtr? imm = null; nint? imm = null;
Symbol symbol = relocEntry.Symbol; Symbol symbol = relocEntry.Symbol;
if (symbol.Type == SymbolType.FunctionTable) if (symbol.Type == SymbolType.FunctionTable)
@@ -661,7 +666,7 @@ namespace ARMeilleure.Translation.PTC
{ {
unsafe unsafe
{ {
imm = (IntPtr)Unsafe.AsPointer(ref translator.FunctionTable.GetValue(guestAddress)); imm = (nint)Unsafe.AsPointer(ref translator.FunctionTable.GetValue(guestAddress));
} }
} }
} }
@@ -669,7 +674,7 @@ namespace ARMeilleure.Translation.PTC
{ {
int index = (int)symbol.Value; int index = (int)symbol.Value;
if (Delegates.TryGetDelegateFuncPtrByIndex(index, out IntPtr funcPtr)) if (Delegates.TryGetDelegateFuncPtrByIndex(index, out nint funcPtr))
{ {
imm = funcPtr; imm = funcPtr;
} }
@@ -684,7 +689,7 @@ namespace ARMeilleure.Translation.PTC
unsafe unsafe
{ {
imm = (IntPtr)Unsafe.AsPointer(ref callCounter.Value); imm = (nint)Unsafe.AsPointer(ref callCounter.Value);
} }
} }
else if (symbol == DispatchStubSymbol) else if (symbol == DispatchStubSymbol)
@@ -733,8 +738,8 @@ namespace ARMeilleure.Translation.PTC
UnwindInfo unwindInfo, UnwindInfo unwindInfo,
bool highCq) bool highCq)
{ {
var cFunc = new CompiledFunction(code, unwindInfo, RelocInfo.Empty); CompiledFunction cFunc = new(code, unwindInfo, RelocInfo.Empty);
var gFunc = cFunc.MapWithPointer<GuestFunction>(out IntPtr gFuncPointer); GuestFunction gFunc = cFunc.MapWithPointer<GuestFunction>(out nint gFuncPointer);
return new TranslatedFunction(gFunc, gFuncPointer, callCounter, guestSize, highCq); return new TranslatedFunction(gFunc, gFuncPointer, callCounter, guestSize, highCq);
} }
@@ -771,7 +776,7 @@ namespace ARMeilleure.Translation.PTC
public void MakeAndSaveTranslations(Translator translator) public void MakeAndSaveTranslations(Translator translator)
{ {
var profiledFuncsToTranslate = Profiler.GetProfiledFuncsToTranslate(translator.Functions); ConcurrentQueue<(ulong address, PtcProfiler.FuncProfile funcProfile)> profiledFuncsToTranslate = Profiler.GetProfiledFuncsToTranslate(translator.Functions);
_translateCount = 0; _translateCount = 0;
_translateTotalCount = profiledFuncsToTranslate.Count; _translateTotalCount = profiledFuncsToTranslate.Count;
@@ -815,7 +820,7 @@ namespace ARMeilleure.Translation.PTC
void TranslateFuncs() void TranslateFuncs()
{ {
while (profiledFuncsToTranslate.TryDequeue(out var item)) while (profiledFuncsToTranslate.TryDequeue(out (ulong address, PtcProfiler.FuncProfile funcProfile) item))
{ {
ulong address = item.address; ulong address = item.address;
ExecutionMode executionMode = item.funcProfile.Mode; ExecutionMode executionMode = item.funcProfile.Mode;
@@ -860,11 +865,11 @@ namespace ARMeilleure.Translation.PTC
Stopwatch sw = Stopwatch.StartNew(); Stopwatch sw = Stopwatch.StartNew();
foreach (var thread in threads) foreach (Thread thread in threads)
{ {
thread.Start(); thread.Start();
} }
foreach (var thread in threads) foreach (Thread thread in threads)
{ {
thread.Join(); thread.Join();
} }
@@ -944,7 +949,7 @@ namespace ARMeilleure.Translation.PTC
WriteCode(code.AsSpan()); WriteCode(code.AsSpan());
// WriteReloc. // WriteReloc.
using var relocInfoWriter = new BinaryWriter(_relocsStream, EncodingCache.UTF8NoBOM, true); using BinaryWriter relocInfoWriter = new(_relocsStream, EncodingCache.UTF8NoBOM, true);
foreach (RelocEntry entry in relocInfo.Entries) foreach (RelocEntry entry in relocInfo.Entries)
{ {
@@ -954,7 +959,7 @@ namespace ARMeilleure.Translation.PTC
} }
// WriteUnwindInfo. // WriteUnwindInfo.
using var unwindInfoWriter = new BinaryWriter(_unwindInfosStream, EncodingCache.UTF8NoBOM, true); using BinaryWriter unwindInfoWriter = new(_unwindInfosStream, EncodingCache.UTF8NoBOM, true);
unwindInfoWriter.Write(unwindInfo.PushEntries.Length); unwindInfoWriter.Write(unwindInfo.PushEntries.Length);
@@ -1025,7 +1030,7 @@ namespace ARMeilleure.Translation.PTC
return osPlatform; return osPlatform;
} }
[StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 87*/)] [StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 86*/)]
private struct OuterHeader private struct OuterHeader
{ {
public ulong Magic; public ulong Magic;
@@ -1037,7 +1042,6 @@ namespace ARMeilleure.Translation.PTC
public byte MemoryManagerMode; public byte MemoryManagerMode;
public uint OSPlatform; public uint OSPlatform;
public uint Architecture; public uint Architecture;
public bool DebuggerMode;
public long UncompressedStreamSize; public long UncompressedStreamSize;
@@ -0,0 +1,37 @@
namespace ARMeilleure.Translation.PTC
{
public readonly struct PtcCacheInfo
{
public const string TitleIdTextDefault = "0000000000000000";
public const string ApplicationIdTextDefault = "0000000000000000";
public const string DisplayVersionDefault = "0";
public ulong ProcessId { get; }
public string TitleIdText { get; }
public string ApplicationIdText { get; }
public byte ProgramIndex { get; }
public string DisplayVersion { get; }
public string ProcessKind { get; }
public string CacheSelector { get; }
public string CacheKey => $"{DisplayVersion}-{CacheSelector}";
public PtcCacheInfo(
ulong processId,
string titleIdText,
string applicationIdText,
byte programIndex,
string displayVersion,
string processKind,
string cacheSelector)
{
ProcessId = processId;
TitleIdText = !string.IsNullOrEmpty(titleIdText) ? titleIdText : TitleIdTextDefault;
ApplicationIdText = !string.IsNullOrEmpty(applicationIdText) ? applicationIdText : ApplicationIdTextDefault;
ProgramIndex = programIndex;
DisplayVersion = !string.IsNullOrEmpty(displayVersion) ? displayVersion : DisplayVersionDefault;
ProcessKind = processKind ?? string.Empty;
CacheSelector = string.IsNullOrEmpty(cacheSelector) ? "default" : cacheSelector;
}
}
}
+16 -7
View File
@@ -9,13 +9,13 @@ using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.IO.Compression; using System.IO.Compression;
using System.Linq;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Threading; using System.Threading;
using System.Timers; using System.Timers;
using static ARMeilleure.Translation.PTC.PtcFormatter; using static ARMeilleure.Translation.PTC.PtcFormatter;
using Timer = System.Timers.Timer; using Timer = System.Timers.Timer;
using System.Linq;
namespace ARMeilleure.Translation.PTC namespace ARMeilleure.Translation.PTC
{ {
@@ -23,7 +23,7 @@ namespace ARMeilleure.Translation.PTC
{ {
private const string OuterHeaderMagicString = "Pohd\0\0\0\0"; private const string OuterHeaderMagicString = "Pohd\0\0\0\0";
private const uint InternalVersion = 6698; //! Not to be incremented manually for each change to the ARMeilleure project. private const uint InternalVersion = 7031; //! Not to be incremented manually for each change to the ARMeilleure project.
private static readonly uint[] _migrateInternalVersions = private static readonly uint[] _migrateInternalVersions =
[ [
@@ -119,9 +119,9 @@ namespace ARMeilleure.Translation.PTC
public ConcurrentQueue<(ulong address, FuncProfile funcProfile)> GetProfiledFuncsToTranslate(TranslatorCache<TranslatedFunction> funcs) public ConcurrentQueue<(ulong address, FuncProfile funcProfile)> GetProfiledFuncsToTranslate(TranslatorCache<TranslatedFunction> funcs)
{ {
var profiledFuncsToTranslate = new ConcurrentQueue<(ulong address, FuncProfile funcProfile)>(); ConcurrentQueue<(ulong address, FuncProfile funcProfile)> profiledFuncsToTranslate = new();
foreach (var profiledFunc in ProfiledFuncs) foreach (KeyValuePair<ulong, FuncProfile> profiledFunc in ProfiledFuncs)
{ {
if (!funcs.ContainsKey(profiledFunc.Key) && !profiledFunc.Value.Blacklist) if (!funcs.ContainsKey(profiledFunc.Key) && !profiledFunc.Value.Blacklist)
{ {
@@ -142,7 +142,7 @@ namespace ARMeilleure.Translation.PTC
{ {
List<ulong> funcs = []; List<ulong> funcs = [];
foreach (var profiledFunc in ProfiledFuncs) foreach (KeyValuePair<ulong, FuncProfile> profiledFunc in ProfiledFuncs)
{ {
if (profiledFunc.Value.Blacklist) if (profiledFunc.Value.Blacklist)
{ {
@@ -254,7 +254,12 @@ namespace ARMeilleure.Translation.PTC
long fileSize = new FileInfo(fileName).Length; 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})."); Logger.Info?.Print(
LogClass.Ptc,
$"{(isBackup ? "Loaded Backup Profiling Info" : "Loaded Profiling Info")} " +
$"(pid: {_ptc.CacheInfo.ProcessId}, title: {_ptc.CacheInfo.TitleIdText}, version: '{_ptc.CacheInfo.DisplayVersion}', " +
$"kind: {_ptc.CacheInfo.ProcessKind}, selector: '{_ptc.CacheInfo.CacheSelector}', key: '{_ptc.CacheInfo.CacheKey}', " +
$"path: '{fileName}', size: {fileSize} bytes, profiled functions: {ProfiledFuncs.Count}).");
return true; return true;
} }
@@ -375,7 +380,11 @@ namespace ARMeilleure.Translation.PTC
if (fileSize != 0L) if (fileSize != 0L)
{ {
Logger.Info?.Print(LogClass.Ptc, $"Saved Profiling Info (size: {fileSize} bytes, profiled functions: {profiledFuncsCount})."); Logger.Info?.Print(
LogClass.Ptc,
$"Saved Profiling Info (pid: {_ptc.CacheInfo.ProcessId}, title: {_ptc.CacheInfo.TitleIdText}, version: '{_ptc.CacheInfo.DisplayVersion}', " +
$"kind: {_ptc.CacheInfo.ProcessKind}, selector: '{_ptc.CacheInfo.CacheSelector}', key: '{_ptc.CacheInfo.CacheKey}', " +
$"path: '{fileName}', size: {fileSize} bytes, profiled functions: {profiledFuncsCount}).");
} }
} }
@@ -44,10 +44,10 @@ namespace ARMeilleure.Translation
public static void Construct(ControlFlowGraph cfg) public static void Construct(ControlFlowGraph cfg)
{ {
var globalDefs = new DefMap[cfg.Blocks.Count]; DefMap[] globalDefs = new DefMap[cfg.Blocks.Count];
var localDefs = new Operand[cfg.LocalsCount + RegisterConsts.TotalCount]; Operand[] localDefs = new Operand[cfg.LocalsCount + RegisterConsts.TotalCount];
var dfPhiBlocks = new Queue<BasicBlock>(); Queue<BasicBlock> dfPhiBlocks = new();
for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext) for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext)
{ {
@@ -1,5 +1,4 @@
using ARMeilleure.Common; using ARMeilleure.Common;
using System;
namespace ARMeilleure.Translation namespace ARMeilleure.Translation
{ {
@@ -7,12 +6,12 @@ namespace ARMeilleure.Translation
{ {
private readonly GuestFunction _func; // Ensure that this delegate will not be garbage collected. private readonly GuestFunction _func; // Ensure that this delegate will not be garbage collected.
public IntPtr FuncPointer { get; } public nint FuncPointer { get; }
public Counter<uint> CallCounter { get; } public Counter<uint> CallCounter { get; }
public ulong GuestSize { get; } public ulong GuestSize { get; }
public bool HighCq { get; } public bool HighCq { get; }
public TranslatedFunction(GuestFunction func, IntPtr funcPointer, Counter<uint> callCounter, ulong guestSize, bool highCq) public TranslatedFunction(GuestFunction func, nint funcPointer, Counter<uint> callCounter, ulong guestSize, bool highCq)
{ {
_func = func; _func = func;
FuncPointer = funcPointer; FuncPointer = funcPointer;
+16 -54
View File
@@ -57,9 +57,9 @@ namespace ARMeilleure.Translation
FunctionTable.Fill = (ulong)Stubs.SlowDispatchStub; FunctionTable.Fill = (ulong)Stubs.SlowDispatchStub;
} }
public IPtcLoadState LoadDiskCache(string titleIdText, string displayVersion, bool enabled, string cacheSelector) public IPtcLoadState LoadDiskCache(PtcCacheInfo cacheInfo, bool enabled)
{ {
_ptc.Initialize(titleIdText, displayVersion, enabled, Memory.Type, cacheSelector); _ptc.Initialize(cacheInfo, enabled, Memory.Type);
return _ptc; return _ptc;
} }
@@ -119,25 +119,7 @@ namespace ARMeilleure.Translation
NativeInterface.RegisterThread(context, Memory, this); NativeInterface.RegisterThread(context, Memory, this);
if (Optimizations.EnableDebugging) if (Optimizations.UseUnmanagedDispatchLoop)
{
context.DebugPc = address;
do
{
if (Interlocked.CompareExchange(ref context.ShouldStep, 0, 1) == 1)
{
context.DebugPc = Step(context, context.DebugPc);
context.StepHandler();
}
else
{
context.DebugPc = ExecuteSingle(context, context.DebugPc);
}
context.CheckInterrupt();
}
while (context.Running && context.DebugPc != 0);
}
else if (Optimizations.UseUnmanagedDispatchLoop)
{ {
Stubs.DispatchLoop(context.NativeContextPtr, address); Stubs.DispatchLoop(context.NativeContextPtr, address);
} }
@@ -194,7 +176,7 @@ namespace ARMeilleure.Translation
return nextAddr; return nextAddr;
} }
private ulong Step(State.ExecutionContext context, ulong address) public ulong Step(State.ExecutionContext context, ulong address)
{ {
TranslatedFunction func = Translate(address, context.ExecutionMode, highCq: false, singleStep: true); TranslatedFunction func = Translate(address, context.ExecutionMode, highCq: false, singleStep: true);
@@ -205,8 +187,6 @@ namespace ARMeilleure.Translation
return address; return address;
} }
internal TranslatedFunction GetOrTranslate(ulong address, ExecutionMode mode) internal TranslatedFunction GetOrTranslate(ulong address, ExecutionMode mode)
{ {
if (!Functions.TryGetValue(address, out TranslatedFunction func)) if (!Functions.TryGetValue(address, out TranslatedFunction func))
@@ -242,7 +222,7 @@ namespace ARMeilleure.Translation
internal TranslatedFunction Translate(ulong address, ExecutionMode mode, bool highCq, bool singleStep = false, bool pptcTranslation = false) internal TranslatedFunction Translate(ulong address, ExecutionMode mode, bool highCq, bool singleStep = false, bool pptcTranslation = false)
{ {
var context = new ArmEmitterContext( ArmEmitterContext context = new(
Memory, Memory,
CountTable, CountTable,
FunctionTable, FunctionTable,
@@ -250,8 +230,7 @@ namespace ARMeilleure.Translation
address, address,
highCq, highCq,
_ptc.State != PtcState.Disabled, _ptc.State != PtcState.Disabled,
mode: Aarch32Mode.User, mode: Aarch32Mode.User);
isSingleStep: singleStep);
Logger.StartPass(PassName.Decoding); Logger.StartPass(PassName.Decoding);
@@ -286,10 +265,10 @@ namespace ARMeilleure.Translation
Logger.EndPass(PassName.RegisterUsage); Logger.EndPass(PassName.RegisterUsage);
var retType = OperandType.I64; OperandType retType = OperandType.I64;
var argTypes = new OperandType[] { OperandType.I64 }; OperandType[] argTypes = new OperandType[] { OperandType.I64 };
var options = highCq ? CompilerOptions.HighCq : CompilerOptions.None; CompilerOptions options = highCq ? CompilerOptions.HighCq : CompilerOptions.None;
if (context.HasPtc && !singleStep) if (context.HasPtc && !singleStep)
{ {
@@ -305,7 +284,7 @@ namespace ARMeilleure.Translation
_ptc.WriteCompiledFunction(address, funcSize, hash, highCq, compiledFunc); _ptc.WriteCompiledFunction(address, funcSize, hash, highCq, compiledFunc);
} }
GuestFunction func = compiledFunc.MapWithPointer<GuestFunction>(out IntPtr funcPointer); GuestFunction func = compiledFunc.MapWithPointer<GuestFunction>(out nint funcPointer);
Allocators.ResetAll(); Allocators.ResetAll();
@@ -390,13 +369,9 @@ namespace ARMeilleure.Translation
if (block.Exit) if (block.Exit)
{ {
// Return to managed rather than tail call. // Left option here as it may be useful if we need to return to managed rather than tail call in
bool useReturns = Optimizations.EnableDebugging; // future. (eg. for debug)
bool useReturns = false;
if (Optimizations.EnableDebugging)
{
EmitDebugPrecisePcUpdate(context, block.Address);
}
InstEmitFlowHelper.EmitVirtualJump(context, Const(block.Address), isReturn: useReturns); InstEmitFlowHelper.EmitVirtualJump(context, Const(block.Address), isReturn: useReturns);
} }
@@ -420,11 +395,6 @@ namespace ARMeilleure.Translation
} }
} }
if (Optimizations.EnableDebugging)
{
EmitDebugPrecisePcUpdate(context, opCode.Address);
}
Operand lblPredicateSkip = default; Operand lblPredicateSkip = default;
if (context.IsInIfThenBlock && context.CurrentIfThenBlockCond != Condition.Al) if (context.IsInIfThenBlock && context.CurrentIfThenBlockCond != Condition.Al)
@@ -521,14 +491,6 @@ namespace ARMeilleure.Translation
context.MarkLabel(lblExit); context.MarkLabel(lblExit);
} }
internal static void EmitDebugPrecisePcUpdate(EmitterContext context, ulong address)
{
long debugPrecisePcOffs = NativeContext.GetDebugPrecisePcOffset();
Operand debugPrecisePcAddr = context.Add(context.LoadArgument(OperandType.I64, 0), Const(debugPrecisePcOffs));
context.Store(debugPrecisePcAddr, Const(address));
}
public void InvalidateJitCacheRegion(ulong address, ulong size) public void InvalidateJitCacheRegion(ulong address, ulong size)
{ {
ulong[] overlapAddresses = []; ulong[] overlapAddresses = [];
@@ -574,7 +536,7 @@ namespace ARMeilleure.Translation
List<TranslatedFunction> functions = Functions.AsList(); List<TranslatedFunction> functions = Functions.AsList();
foreach (var func in functions) foreach (TranslatedFunction func in functions)
{ {
JitCache.Unmap(func.FuncPointer); JitCache.Unmap(func.FuncPointer);
@@ -583,7 +545,7 @@ namespace ARMeilleure.Translation
Functions.Clear(); Functions.Clear();
while (_oldFuncs.TryDequeue(out var kv)) while (_oldFuncs.TryDequeue(out KeyValuePair<ulong, TranslatedFunction> kv))
{ {
JitCache.Unmap(kv.Value.FuncPointer); JitCache.Unmap(kv.Value.FuncPointer);
@@ -604,7 +566,7 @@ namespace ARMeilleure.Translation
{ {
while (Queue.Count > 0 && Queue.TryDequeue(out RejitRequest request)) while (Queue.Count > 0 && Queue.TryDequeue(out RejitRequest request))
{ {
if (Functions.TryGetValue(request.Address, out var func) && func.CallCounter != null) if (Functions.TryGetValue(request.Address, out TranslatedFunction func) && func.CallCounter != null)
{ {
Volatile.Write(ref func.CallCounter.Value, 0); Volatile.Write(ref func.CallCounter.Value, 0);
} }
+24 -24
View File
@@ -14,7 +14,7 @@ namespace ARMeilleure.Translation
/// </summary> /// </summary>
class TranslatorStubs : IDisposable class TranslatorStubs : IDisposable
{ {
private readonly Lazy<IntPtr> _slowDispatchStub; private readonly Lazy<nint> _slowDispatchStub;
private bool _disposed; private bool _disposed;
@@ -27,7 +27,7 @@ namespace ARMeilleure.Translation
/// Gets the dispatch stub. /// Gets the dispatch stub.
/// </summary> /// </summary>
/// <exception cref="ObjectDisposedException"><see cref="TranslatorStubs"/> instance was disposed</exception> /// <exception cref="ObjectDisposedException"><see cref="TranslatorStubs"/> instance was disposed</exception>
public IntPtr DispatchStub public nint DispatchStub
{ {
get get
{ {
@@ -41,7 +41,7 @@ namespace ARMeilleure.Translation
/// Gets the slow dispatch stub. /// Gets the slow dispatch stub.
/// </summary> /// </summary>
/// <exception cref="ObjectDisposedException"><see cref="TranslatorStubs"/> instance was disposed</exception> /// <exception cref="ObjectDisposedException"><see cref="TranslatorStubs"/> instance was disposed</exception>
public IntPtr SlowDispatchStub public nint SlowDispatchStub
{ {
get get
{ {
@@ -139,9 +139,9 @@ namespace ARMeilleure.Translation
/// Generates a <see cref="DispatchStub"/>. /// Generates a <see cref="DispatchStub"/>.
/// </summary> /// </summary>
/// <returns>Generated <see cref="DispatchStub"/></returns> /// <returns>Generated <see cref="DispatchStub"/></returns>
private IntPtr GenerateDispatchStub() private nint GenerateDispatchStub()
{ {
var context = new EmitterContext(); EmitterContext context = new();
Operand lblFallback = Label(); Operand lblFallback = Label();
Operand lblEnd = Label(); Operand lblEnd = Label();
@@ -160,7 +160,7 @@ namespace ARMeilleure.Translation
for (int i = 0; i < _functionTable.Levels.Length; i++) for (int i = 0; i < _functionTable.Levels.Length; i++)
{ {
ref var level = ref _functionTable.Levels[i]; ref AddressTableLevel level = ref _functionTable.Levels[i];
// level.Mask is not used directly because it is more often bigger than 32-bits, so it will not // level.Mask is not used directly because it is more often bigger than 32-bits, so it will not
// be encoded as an immediate on x86's bitwise and operation. // be encoded as an immediate on x86's bitwise and operation.
@@ -184,11 +184,11 @@ namespace ARMeilleure.Translation
hostAddress = context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFunctionAddress)), guestAddress); hostAddress = context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFunctionAddress)), guestAddress);
context.Tailcall(hostAddress, nativeContext); context.Tailcall(hostAddress, nativeContext);
var cfg = context.GetControlFlowGraph(); ControlFlowGraph cfg = context.GetControlFlowGraph();
var retType = OperandType.I64; OperandType retType = OperandType.I64;
var argTypes = new[] { OperandType.I64 }; OperandType[] argTypes = new[] { OperandType.I64 };
var func = Compiler.Compile(cfg, argTypes, retType, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<GuestFunction>(); GuestFunction func = Compiler.Compile(cfg, argTypes, retType, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<GuestFunction>();
return Marshal.GetFunctionPointerForDelegate(func); return Marshal.GetFunctionPointerForDelegate(func);
} }
@@ -197,9 +197,9 @@ namespace ARMeilleure.Translation
/// Generates a <see cref="SlowDispatchStub"/>. /// Generates a <see cref="SlowDispatchStub"/>.
/// </summary> /// </summary>
/// <returns>Generated <see cref="SlowDispatchStub"/></returns> /// <returns>Generated <see cref="SlowDispatchStub"/></returns>
private IntPtr GenerateSlowDispatchStub() private nint GenerateSlowDispatchStub()
{ {
var context = new EmitterContext(); EmitterContext context = new();
// Load the target guest address from the native context. // Load the target guest address from the native context.
Operand nativeContext = context.LoadArgument(OperandType.I64, 0); Operand nativeContext = context.LoadArgument(OperandType.I64, 0);
@@ -209,11 +209,11 @@ namespace ARMeilleure.Translation
Operand hostAddress = context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFunctionAddress)), guestAddress); Operand hostAddress = context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFunctionAddress)), guestAddress);
context.Tailcall(hostAddress, nativeContext); context.Tailcall(hostAddress, nativeContext);
var cfg = context.GetControlFlowGraph(); ControlFlowGraph cfg = context.GetControlFlowGraph();
var retType = OperandType.I64; OperandType retType = OperandType.I64;
var argTypes = new[] { OperandType.I64 }; OperandType[] argTypes = new[] { OperandType.I64 };
var func = Compiler.Compile(cfg, argTypes, retType, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<GuestFunction>(); GuestFunction func = Compiler.Compile(cfg, argTypes, retType, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<GuestFunction>();
return Marshal.GetFunctionPointerForDelegate(func); return Marshal.GetFunctionPointerForDelegate(func);
} }
@@ -250,7 +250,7 @@ namespace ARMeilleure.Translation
/// <returns><see cref="DispatchLoop"/> function</returns> /// <returns><see cref="DispatchLoop"/> function</returns>
private DispatcherFunction GenerateDispatchLoop() private DispatcherFunction GenerateDispatchLoop()
{ {
var context = new EmitterContext(); EmitterContext context = new();
Operand beginLbl = Label(); Operand beginLbl = Label();
Operand endLbl = Label(); Operand endLbl = Label();
@@ -286,9 +286,9 @@ namespace ARMeilleure.Translation
context.Return(); context.Return();
var cfg = context.GetControlFlowGraph(); ControlFlowGraph cfg = context.GetControlFlowGraph();
var retType = OperandType.None; OperandType retType = OperandType.None;
var argTypes = new[] { OperandType.I64, OperandType.I64 }; OperandType[] argTypes = new[] { OperandType.I64, OperandType.I64 };
return Compiler.Compile(cfg, argTypes, retType, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<DispatcherFunction>(); return Compiler.Compile(cfg, argTypes, retType, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<DispatcherFunction>();
} }
@@ -299,7 +299,7 @@ namespace ARMeilleure.Translation
/// <returns><see cref="ContextWrapper"/> function</returns> /// <returns><see cref="ContextWrapper"/> function</returns>
private WrapperFunction GenerateContextWrapper() private WrapperFunction GenerateContextWrapper()
{ {
var context = new EmitterContext(); EmitterContext context = new();
Operand nativeContext = context.LoadArgument(OperandType.I64, 0); Operand nativeContext = context.LoadArgument(OperandType.I64, 0);
Operand guestMethod = context.LoadArgument(OperandType.I64, 1); Operand guestMethod = context.LoadArgument(OperandType.I64, 1);
@@ -310,9 +310,9 @@ namespace ARMeilleure.Translation
context.Return(returnValue); context.Return(returnValue);
var cfg = context.GetControlFlowGraph(); ControlFlowGraph cfg = context.GetControlFlowGraph();
var retType = OperandType.I64; OperandType retType = OperandType.I64;
var argTypes = new[] { OperandType.I64, OperandType.I64 }; OperandType[] argTypes = new[] { OperandType.I64, OperandType.I64 };
return Compiler.Compile(cfg, argTypes, retType, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<WrapperFunction>(); return Compiler.Compile(cfg, argTypes, retType, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<WrapperFunction>();
} }
@@ -9,7 +9,7 @@ namespace ARMeilleure.Translation
{ {
public static class TranslatorTestMethods public static class TranslatorTestMethods
{ {
public delegate int FpFlagsPInvokeTest(IntPtr managedMethod); public delegate int FpFlagsPInvokeTest(nint managedMethod);
private static bool SetPlatformFtz(EmitterContext context, bool ftz) private static bool SetPlatformFtz(EmitterContext context, bool ftz)
{ {
+12
View File
@@ -0,0 +1,12 @@
.idea/
*.iml
.gradle
local.properties
.DS_Store
build/
captures
.externalNativeBuild
.cxx/
app/src/main/jniLibs/arm64-v8a/**
!app/src/main/jniLibs/arm64-v8a/.gitkeep
+175
View File
@@ -0,0 +1,175 @@
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.plugin.compose'
}
android {
namespace = 'org.kenjinx.android'
compileSdk 37
defaultConfig {
applicationId "org.kenjinx.android"
minSdk 29
targetSdk 37
versionCode 20100
versionName '2.1.0-pr.2'
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
ndk {
//noinspection ChromeOsAbiSupport
abiFilters 'arm64-v8a'
}
externalNativeBuild {
cmake {
cppFlags "-std=c++20 -O3",
"-fno-math-errno -fno-trapping-math -fno-signed-zeros -ffinite-math-only"
arguments "-DANDROID_STL=c++_shared",
"-DCMAKE_BUILD_TYPE=Release",
"-DANDROID_ARM_NEON=TRUE",
"-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON"
}
}
}
buildTypes {
release {
// minifyEnabled false
// proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
signingConfig = signingConfigs.debug
debuggable false
jniDebuggable false
}
}
def deviceFlavors = [
armv8 : "-march=armv8-a",
armv82 : "-march=armv8.2-a",
armv87 : "-march=armv8.7-a",
sd8eg5 : "-march=armv8.7-a+sve+sve2",
]
flavorDimensions "appid", "device"
productFlavors {
mainline {
dimension "appid"
applicationId "org.kenjinx.android"
manifestPlaceholders = [applicationLabel: "@string/app_name"]
}
optimized {
dimension "appid"
applicationId "com.garena.game.codm"
manifestPlaceholders = [applicationLabel: "@string/app_name_optimized"]
}
}
deviceFlavors.each { name, flags ->
productFlavors.create(name) {
dimension "device"
externalNativeBuild {
cmake {
cppFlags flags
}
}
}
}
androidComponents {
onVariants(selector().withBuildType("debug")) {
packaging.dex.useLegacyPackaging.set(false)
}
beforeVariants(selector().all()) { variant ->
def flavors = variant.productFlavors.collect { it.second }.toSet()
def invalidCombos = [
["optimized", "armv8"],
["optimized", "armv87"],
["optimized", "sd8eg5"]
]
if (invalidCombos.any { combo -> flavors.containsAll(combo) }) {
enable = false
}
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_21
targetCompatibility JavaVersion.VERSION_21
}
buildFeatures {
compose = true
prefab = true
buildConfig = true
}
packagingOptions {
jniLibs {
keepDebugSymbols += '**/libkenjinx.so'
useLegacyPackaging true
}
dex {
useLegacyPackaging true
}
resources {
excludes += '/META-INF/{AL2.0,LGPL2.1}'
}
}
externalNativeBuild {
cmake {
path file('src/main/cpp/CMakeLists.txt')
version = '4.1.2'
}
}
sourceSets {
main {
jniLibs.srcDirs = ['src/main/extLibs', 'src/main/jniLibs']
}
}
}
tasks.named("preBuild") {
dependsOn ':libkenjinx:assemble'
}
dependencies {
runtimeOnly project(":libkenjinx")
implementation 'androidx.activity:activity-compose:1.13.0'
implementation 'androidx.appcompat:appcompat:1.8.0'
implementation 'androidx.compose.material3:material3'
implementation 'androidx.compose.material:material-icons-extended:1.7.8'
implementation 'androidx.compose.ui:ui'
implementation 'androidx.compose.ui:ui-graphics'
implementation 'androidx.compose.ui:ui-tooling-preview'
implementation 'androidx.constraintlayout:constraintlayout:2.2.2'
implementation 'androidx.core:core-ktx:1.19.0'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.11.0'
implementation 'androidx.navigation:navigation-compose:2.9.8'
implementation 'androidx.preference:preference-ktx:1.2.1'
implementation 'br.com.devsrsouza.compose.icons:css-gg:1.1.1'
implementation 'com.anggrayudi:storage:2.2.0'
implementation 'com.github.swordfish90:radialgamepad:2.0.0'
implementation 'com.google.android.material:material:1.14.0'
implementation 'com.google.code.gson:gson:2.14.0'
implementation 'com.halilibo.compose-richtext:richtext-commonmark:0.20.0'
implementation 'com.halilibo.compose-richtext:richtext-ui-material3:0.20.0'
implementation 'com.halilibo.compose-richtext:richtext-ui:0.20.0'
implementation 'io.coil-kt:coil-compose:2.7.0'
implementation 'net.java.dev.jna:jna:5.19.1@aar'
implementation 'net.lingala.zip4j:zip4j:2.11.6'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.11.0'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.11.0'
implementation platform('androidx.compose:compose-bom:2026.08.00')
implementation platform('org.jetbrains.kotlin:kotlin-bom:2.3.10')
androidTestImplementation 'androidx.compose.ui:ui-test-junit4'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.7.0'
androidTestImplementation 'androidx.test.ext:junit:1.3.0'
androidTestImplementation platform('androidx.compose:compose-bom:2026.08.00')
testImplementation 'junit:junit:4.13.2'
debugImplementation 'androidx.compose.ui:ui-test-manifest'
debugImplementation 'androidx.compose.ui:ui-tooling'
}
+37
View File
@@ -0,0 +1,37 @@
-optimizationpasses 5
-optimizations !code/simplification/arithmetic
-optimizations !code/simplification/cast
-optimizations !field/*
-optimizations !class/merging/*
-optimizations !method/inlining/short
-optimizations !method/inlining/unique
-optimizations method/inlining/tailrecursion
-optimizations method/removal/parameter
-optimizations code/merging
-optimizations code/simplification/variable
-allowaccessmodification
-repackageclasses ''
-keepattributes Exceptions,InnerClasses,Signature,*Annotation*
-dontpreverify
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends androidx.fragment.app.Fragment
-dontwarn java.awt.Component
-dontwarn java.awt.GraphicsEnvironment
-dontwarn java.awt.HeadlessException
-dontwarn java.awt.Window
-dontwarn javax.lang.model.element.Modifier
-assumenosideeffects class java.lang.Math {
public static double random();
public static double sin(...);
public static double cos(...);
public static double sqrt(...);
}
-assumenosideeffects public class ** {
public boolean is*();
public boolean get*();
public boolean has*();
}
@@ -0,0 +1,116 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<!-- Android 11+ Package Visibility: What this app is allowed to see/access -->
<queries>
<!-- If other flavors/starters are involved, make them visible here -->
<package android:name="org.kenjinx.android"/>
<!-- General: Make LAUNCHER activities and ACTION_VIEW files resolvable -->
<intent>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent>
</queries>
<uses-feature
android:name="android.hardware.audio.output"
android:required="true" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission
android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<!-- Notifications + special-use Foreground Service (Android 14+) -->
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<!-- Required for startForeground() -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<application
android:name=".KenjinxApplication"
android:allowBackup="true"
android:appCategory="game"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:isGame="true"
android:label="${applicationLabel}"
android:supportsRtl="true"
android:theme="@style/Theme.KenjinxAndroid"
android:largeHeap="true"
android:requestLegacyExternalStorage="true"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:exported="true"
android:screenOrientation="unspecified"
android:resizeableActivity="true"
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|uiMode"
android:hardwareAccelerated="true"
android:theme="@style/Theme.KenjinxAndroid">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<action android:name="org.kenjinx.android.LAUNCH_GAME" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<!--
<intent-filter>
<action android:name="org.kenji.android.action.CREATE_SHORTCUT" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
-->
<!-- Shortcut Wizard Activity (transparent, freely rotatable) -->
<activity
android:name=".ShortcutWizardActivity"
android:exported="false"
android:theme="@style/Theme.KenjinxAndroid.Transparent"
android:screenOrientation="unspecified"
android:configChanges="orientation|screenSize|keyboardHidden|uiMode" />
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths" />
</provider>
<provider
android:name=".providers.DocumentProvider"
android:authorities="${applicationId}.providers"
android:exported="true"
android:grantUriPermissions="true"
android:permission="android.permission.MANAGE_DOCUMENTS">
<intent-filter>
<action android:name="android.content.action.DOCUMENTS_PROVIDER" />
</intent-filter>
</provider>
<service
android:name=".service.EmulationService"
android:exported="false"
android:stopWithTask="true"
android:foregroundServiceType="mediaPlayback" />
</application>
</manifest>
@@ -0,0 +1,80 @@
include(FetchContent)
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.31.5)
# Declares and names the project.
project("kenjinxjni")
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
FetchContent_Declare(
adrenotools
GIT_REPOSITORY https://github.com/bylaws/libadrenotools.git
GIT_TAG 8fae8ce254dfc1344527e05301e43f37dea2df80
)
FetchContent_MakeAvailable(adrenotools)
# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.
add_library( # Sets the name of the library.
kenjinxjni
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
vulkan_wrapper.cpp
kenjinx.cpp)
# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log )
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.
target_link_libraries( # Specifies the target library.
kenjinxjni
# Links the target library to the log library
# included in the NDK.
${log-lib}
-lvulkan
-landroid
adrenotools
)
# Build external libraries if prebuilt files don't exist
set(JNI_PATH ../jniLibs/${CMAKE_ANDROID_ARCH_ABI})
cmake_path(ABSOLUTE_PATH JNI_PATH NORMALIZE)
cmake_path(APPEND JNI_PATH libcrypto.so OUTPUT_VARIABLE LIBCRYPTO_JNI_PATH)
cmake_path(APPEND JNI_PATH libssl.so OUTPUT_VARIABLE LIBSSL_JNI_PATH)
# Add OpenAL
add_subdirectory(libraries/openal)
set_target_properties(OpenAL PROPERTIES
LIBRARY_OUTPUT_DIRECTORY ${JNI_PATH}
ARCHIVE_OUTPUT_DIRECTORY ${JNI_PATH}
RUNTIME_OUTPUT_DIRECTORY ${JNI_PATH}
)
@@ -0,0 +1,254 @@
// Write C++ code here.
//
// Do not forget to dynamically load the C++ library into your application.
//
// For instance,
//
// In MainActivity.java:
// static {
// System.loadLibrary("kenjinxjni");
// }
//
// Or, in MainActivity.kt:
// companion object {
// init {
// System.loadLibrary("kenjinxjni")
// }
// }
#include "kenjinx.h"
#include "pthread.h"
#include <chrono>
#include <csignal>
std::chrono::time_point<std::chrono::steady_clock, std::chrono::nanoseconds> _currentTimePoint;
extern "C"
{
JNIEXPORT jlong JNICALL
Java_org_kenjinx_android_NativeHelpers_getNativeWindow(
JNIEnv *env,
jobject instance,
jobject surface) {
auto nativeWindow = ANativeWindow_fromSurface(env, surface);
return nativeWindow == nullptr ? -1 : (jlong) nativeWindow;
}
JNIEXPORT void JNICALL
Java_org_kenjinx_android_NativeHelpers_releaseNativeWindow(
JNIEnv *env,
jobject instance,
jlong window) {
auto nativeWindow = (ANativeWindow *) window;
if (nativeWindow != nullptr)
ANativeWindow_release(nativeWindow);
}
long createSurface(long native_surface, long instance) {
auto nativeWindow = (ANativeWindow *) native_surface;
VkSurfaceKHR surface;
auto vkInstance = (VkInstance) instance;
auto fpCreateAndroidSurfaceKHR =
reinterpret_cast<PFN_vkCreateAndroidSurfaceKHR>(vkGetInstanceProcAddr(vkInstance,
"vkCreateAndroidSurfaceKHR"));
if (fpCreateAndroidSurfaceKHR == nullptr)
LOGE("Could not get function pointer to CreateAndroidSurfaceKHR");
VkAndroidSurfaceCreateInfoKHR info;
info.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR;
info.pNext = nullptr;
info.flags = 0;
info.window = nativeWindow;
VK_CHECK(fpCreateAndroidSurfaceKHR(vkInstance, &info, nullptr, &surface));
return (long) surface;
}
JNIEXPORT jlong JNICALL
Java_org_kenjinx_android_NativeHelpers_getCreateSurfacePtr(
JNIEnv *env,
jobject instance) {
return (jlong) createSurface;
}
char *getStringPointer(
JNIEnv *env,
jstring jS) {
const char *cparam = env->GetStringUTFChars(jS, nullptr);
auto len = env->GetStringUTFLength(jS);
char *s = new char[len + 1]; //null terminator
strcpy(s, cparam);
env->ReleaseStringUTFChars(jS, cparam);
return s;
}
jstring createString(
JNIEnv *env,
char *ch) {
auto str = env->NewStringUTF(ch);
return str;
}
jstring createStringFromStdString(
JNIEnv *env,
std::string s) {
auto str = env->NewStringUTF(s.c_str());
return str;
}
}
extern "C"
void setRenderingThread() {
auto currentId = pthread_self();
_renderingThreadId = currentId;
_currentTimePoint = std::chrono::high_resolution_clock::now();
}
extern "C"
JNIEXPORT void JNICALL
Java_org_kenjinx_android_MainActivity_initVm(JNIEnv *env, jobject thiz) {
JavaVM *vm = nullptr;
env->GetJavaVM(&vm);
_vm = vm;
_mainActivity = thiz;
_mainActivityClass = env->GetObjectClass(thiz);
}
bool isInitialOrientationFlipped = true;
extern "C"
void setCurrentTransform(long native_window, int transform) {
if (native_window == 0 || native_window == -1)
return;
auto nativeWindow = (ANativeWindow *) native_window;
auto nativeTransform = ANativeWindowTransform::ANATIVEWINDOW_TRANSFORM_IDENTITY;
transform = transform >> 1;
// transform is a valid VkSurfaceTransformFlagBitsKHR
switch (transform) {
case 0x1:
nativeTransform = ANativeWindowTransform::ANATIVEWINDOW_TRANSFORM_IDENTITY;
break;
case 0x2:
nativeTransform = ANativeWindowTransform::ANATIVEWINDOW_TRANSFORM_ROTATE_90;
break;
case 0x4:
nativeTransform = isInitialOrientationFlipped
? ANativeWindowTransform::ANATIVEWINDOW_TRANSFORM_IDENTITY
: ANativeWindowTransform::ANATIVEWINDOW_TRANSFORM_ROTATE_180;
break;
case 0x8:
nativeTransform = ANativeWindowTransform::ANATIVEWINDOW_TRANSFORM_ROTATE_270;
break;
case 0x10:
nativeTransform = ANativeWindowTransform::ANATIVEWINDOW_TRANSFORM_MIRROR_HORIZONTAL;
break;
case 0x20:
nativeTransform = static_cast<ANativeWindowTransform>(
ANativeWindowTransform::ANATIVEWINDOW_TRANSFORM_MIRROR_HORIZONTAL |
ANATIVEWINDOW_TRANSFORM_ROTATE_90);
break;
case 0x40:
nativeTransform = ANativeWindowTransform::ANATIVEWINDOW_TRANSFORM_MIRROR_VERTICAL;
break;
case 0x80:
nativeTransform = static_cast<ANativeWindowTransform>(
ANativeWindowTransform::ANATIVEWINDOW_TRANSFORM_MIRROR_VERTICAL |
ANATIVEWINDOW_TRANSFORM_ROTATE_90);
break;
case 0x100:
nativeTransform = ANativeWindowTransform::ANATIVEWINDOW_TRANSFORM_IDENTITY;
break;
}
nativeWindow->perform(nativeWindow, NATIVE_WINDOW_SET_BUFFERS_TRANSFORM,
static_cast<int32_t>(nativeTransform));
}
extern "C"
JNIEXPORT jlong JNICALL
Java_org_kenjinx_android_NativeHelpers_loadDriver(JNIEnv *env, jobject thiz,
jstring native_lib_path,
jstring private_apps_path,
jstring driver_name) {
auto libPath = getStringPointer(env, native_lib_path);
auto privateAppsPath = getStringPointer(env, private_apps_path);
auto driverName = getStringPointer(env, driver_name);
auto handle = adrenotools_open_libvulkan(
RTLD_NOW,
ADRENOTOOLS_DRIVER_CUSTOM,
nullptr,
libPath,
privateAppsPath,
driverName,
nullptr,
nullptr
);
delete libPath;
delete privateAppsPath;
delete driverName;
return (jlong) handle;
}
extern "C"
void debug_break(int code) {
if (code >= 3)
int r = 0;
}
extern "C"
JNIEXPORT void JNICALL
Java_org_kenjinx_android_NativeHelpers_setTurboMode(JNIEnv *env, jobject thiz, jboolean enable) {
adrenotools_set_turbo(enable);
}
extern "C"
JNIEXPORT jint JNICALL
Java_org_kenjinx_android_NativeHelpers_getMaxSwapInterval(JNIEnv *env, jobject thiz,
jlong native_window) {
auto nativeWindow = (ANativeWindow *) native_window;
return nativeWindow->maxSwapInterval;
}
extern "C"
JNIEXPORT jint JNICALL
Java_org_kenjinx_android_NativeHelpers_getMinSwapInterval(JNIEnv *env, jobject thiz,
jlong native_window) {
auto nativeWindow = (ANativeWindow *) native_window;
return nativeWindow->minSwapInterval;
}
extern "C"
JNIEXPORT jint JNICALL
Java_org_kenjinx_android_NativeHelpers_setSwapInterval(JNIEnv *env, jobject thiz,
jlong native_window, jint swap_interval) {
auto nativeWindow = (ANativeWindow *) native_window;
return nativeWindow->setSwapInterval(nativeWindow, swap_interval);
}
extern "C"
JNIEXPORT jstring JNICALL
Java_org_kenjinx_android_NativeHelpers_getStringJava(JNIEnv *env, jobject thiz, jlong ptr) {
return createString(env, (char*)ptr);
}
extern "C"
JNIEXPORT void JNICALL
Java_org_kenjinx_android_NativeHelpers_setIsInitialOrientationFlipped(JNIEnv *env, jobject thiz,
jboolean is_flipped) {
isInitialOrientationFlipped = is_flipped;
}
@@ -0,0 +1,60 @@
//
// Created by Emmanuel Hansen on 6/19/2023.
//
#ifndef KENJINXNATIVE_KENJINX_H
#define KENJINXNATIVE_KENJINX_H
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <dlfcn.h>
#include <exception>
#include <fcntl.h>
#include <jni.h>
#include <string>
#include <android/log.h>
#include <android/native_window.h>
#include <android/native_window_jni.h>
#include "vulkan_wrapper.h"
#include <vulkan/vulkan_android.h>
#include "adrenotools/driver.h"
#include "native_window.h"
// Android log function wrappers
static const char* TAG = "Kenjinx";
#define LOGI(...) \
((void)__android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__))
#define LOGW(...) \
((void)__android_log_print(ANDROID_LOG_WARN, TAG, __VA_ARGS__))
#define LOGE(...) \
((void)__android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__))
// A macro to pass call to Vulkan and check for return value for success
#define CALL_VK(func) \
if (VK_SUCCESS != (func)) { \
__android_log_print(ANDROID_LOG_ERROR, "Tutorial ", \
"Vulkan error. File[%s], line[%d]", __FILE__, \
__LINE__); \
assert(false); \
}
// A macro to check value is VK_SUCCESS
// Used also for non-vulkan functions but return VK_SUCCESS
#define VK_CHECK(x) CALL_VK(x)
#define LoadLib(a) dlopen(a, RTLD_NOW)
void *_kenjinxNative = nullptr;
// Kenjinx imported functions
bool (*initialize)(char *) = nullptr;
long _renderingThreadId = 0;
JavaVM *_vm = nullptr;
jobject _mainActivity = nullptr;
jclass _mainActivityClass = nullptr;
#endif //KENJINXNATIVE_KENJINX_H
@@ -0,0 +1,305 @@
// SPDX-License-Identifier: MPL-2.0
// Copyright © 2021 Skyline Team and Contributors (https://github.com/skyline-emu/)
// Copyright © 2021 The Android Open Source Project
#pragma once
/* A collection of various types from AOSP that allow us to access private APIs for Native Window which we utilize for emulating the guest SF more accurately */
/**
* @url https://cs.android.com/android/platform/superproject/+/android11-release:frameworks/native/libs/nativebase/include/nativebase/nativebase.h;l=29;drc=cb496acbe593326e8d5d563847067d02b2df40ec
*/
#define ANDROID_NATIVE_UNSIGNED_CAST(x) static_cast<unsigned int>(x)
/**
* @url https://cs.android.com/android/platform/superproject/+/android11-release:frameworks/native/libs/nativebase/include/nativebase/nativebase.h;l=34-38;drc=cb496acbe593326e8d5d563847067d02b2df40ec
*/
#define ANDROID_NATIVE_MAKE_CONSTANT(a, b, c, d) \
((ANDROID_NATIVE_UNSIGNED_CAST(a) << 24) | \
(ANDROID_NATIVE_UNSIGNED_CAST(b) << 16) | \
(ANDROID_NATIVE_UNSIGNED_CAST(c) << 8) | \
(ANDROID_NATIVE_UNSIGNED_CAST(d)))
/**
* @url https://cs.android.com/android/platform/superproject/+/android11-release:frameworks/native/libs/nativewindow/include/system/window.h;l=60;drc=401cda638e7d17f6697b5a65c9a5ad79d056202d
*/
#define ANDROID_NATIVE_WINDOW_MAGIC ANDROID_NATIVE_MAKE_CONSTANT('_','w','n','d')
constexpr int AndroidNativeWindowMagic{ANDROID_NATIVE_WINDOW_MAGIC};
#undef ANDROID_NATIVE_WINDOW_MAGIC
#undef ANDROID_NATIVE_MAKE_CONSTANT
#undef ANDROID_NATIVE_UNSIGNED_CAST
/**
* @url https://cs.android.com/android/platform/superproject/+/android11-release:frameworks/native/libs/nativewindow/include/system/window.h;l=325-331;drc=401cda638e7d17f6697b5a65c9a5ad79d056202d
*/
constexpr int64_t NativeWindowTimestampAuto{-9223372036854775807LL - 1};
/**
* @url https://cs.android.com/android/platform/superproject/+/android11-release:frameworks/native/libs/nativewindow/include/system/window.h;l=198-259;drc=401cda638e7d17f6697b5a65c9a5ad79d056202d
*/
enum {
NATIVE_WINDOW_CONNECT = 1, /* deprecated */
NATIVE_WINDOW_DISCONNECT = 2, /* deprecated */
NATIVE_WINDOW_SET_CROP = 3, /* private */
NATIVE_WINDOW_SET_BUFFER_COUNT = 4,
NATIVE_WINDOW_SET_BUFFERS_TRANSFORM = 6,
NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP = 7,
NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS = 8,
NATIVE_WINDOW_SET_SCALING_MODE = 10, /* private */
NATIVE_WINDOW_LOCK = 11, /* private */
NATIVE_WINDOW_UNLOCK_AND_POST = 12, /* private */
NATIVE_WINDOW_API_CONNECT = 13, /* private */
NATIVE_WINDOW_API_DISCONNECT = 14, /* private */
NATIVE_WINDOW_SET_BUFFERS_USER_DIMENSIONS = 15, /* private */
NATIVE_WINDOW_SET_POST_TRANSFORM_CROP = 16, /* deprecated, unimplemented */
NATIVE_WINDOW_SET_BUFFERS_STICKY_TRANSFORM = 17, /* private */
NATIVE_WINDOW_SET_SIDEBAND_STREAM = 18,
NATIVE_WINDOW_SET_BUFFERS_DATASPACE = 19,
NATIVE_WINDOW_SET_SURFACE_DAMAGE = 20, /* private */
NATIVE_WINDOW_SET_SHARED_BUFFER_MODE = 21,
NATIVE_WINDOW_SET_AUTO_REFRESH = 22,
NATIVE_WINDOW_GET_REFRESH_CYCLE_DURATION = 23,
NATIVE_WINDOW_GET_NEXT_FRAME_ID = 24,
NATIVE_WINDOW_ENABLE_FRAME_TIMESTAMPS = 25,
NATIVE_WINDOW_GET_COMPOSITOR_TIMING = 26,
NATIVE_WINDOW_GET_FRAME_TIMESTAMPS = 27,
NATIVE_WINDOW_GET_WIDE_COLOR_SUPPORT = 28,
NATIVE_WINDOW_GET_HDR_SUPPORT = 29,
NATIVE_WINDOW_GET_CONSUMER_USAGE64 = 31,
NATIVE_WINDOW_SET_BUFFERS_SMPTE2086_METADATA = 32,
NATIVE_WINDOW_SET_BUFFERS_CTA861_3_METADATA = 33,
NATIVE_WINDOW_SET_BUFFERS_HDR10_PLUS_METADATA = 34,
NATIVE_WINDOW_SET_AUTO_PREROTATION = 35,
NATIVE_WINDOW_GET_LAST_DEQUEUE_START = 36, /* private */
NATIVE_WINDOW_SET_DEQUEUE_TIMEOUT = 37, /* private */
NATIVE_WINDOW_GET_LAST_DEQUEUE_DURATION = 38, /* private */
NATIVE_WINDOW_GET_LAST_QUEUE_DURATION = 39, /* private */
NATIVE_WINDOW_SET_FRAME_RATE = 40,
NATIVE_WINDOW_SET_CANCEL_INTERCEPTOR = 41, /* private */
NATIVE_WINDOW_SET_DEQUEUE_INTERCEPTOR = 42, /* private */
NATIVE_WINDOW_SET_PERFORM_INTERCEPTOR = 43, /* private */
NATIVE_WINDOW_SET_QUEUE_INTERCEPTOR = 44, /* private */
NATIVE_WINDOW_ALLOCATE_BUFFERS = 45, /* private */
NATIVE_WINDOW_GET_LAST_QUEUED_BUFFER = 46, /* private */
NATIVE_WINDOW_SET_QUERY_INTERCEPTOR = 47, /* private */
NATIVE_WINDOW_GET_LAST_QUEUED_BUFFER2 = 50, /* private */
};
/**
* @url https://cs.android.com/android/platform/superproject/+/android11-release:frameworks/native/libs/nativebase/include/nativebase/nativebase.h;l=43-56;drc=cb496acbe593326e8d5d563847067d02b2df40ec
*/
struct android_native_base_t {
int magic;
int version;
void *reserved[4];
void (*incRef)(android_native_base_t *);
void (*decRef)(android_native_base_t *);
};
/**
* @url https://cs.android.com/android/platform/superproject/+/android11-release:frameworks/native/libs/nativewindow/include/system/window.h;l=341-560;drc=401cda638e7d17f6697b5a65c9a5ad79d056202d
*/
struct ANativeWindow {
struct android_native_base_t common;
/* flags describing some attributes of this surface or its updater */
const uint32_t flags;
/* min swap interval supported by this updated */
const int minSwapInterval;
/* max swap interval supported by this updated */
const int maxSwapInterval;
/* horizontal and vertical resolution in DPI */
const float xdpi;
const float ydpi;
/* Some storage reserved for the OEM's driver. */
intptr_t oem[4];
/*
* Set the swap interval for this surface.
*
* Returns 0 on success or -errno on error.
*/
int (*setSwapInterval)(struct ANativeWindow *window,
int interval);
/*
* Hook called by EGL to acquire a buffer. After this call, the buffer
* is not locked, so its content cannot be modified. This call may block if
* no buffers are available.
*
* The window holds a reference to the buffer between dequeueBuffer and
* either queueBuffer or cancelBuffer, so clients only need their own
* reference if they might use the buffer after queueing or canceling it.
* Holding a reference to a buffer after queueing or canceling it is only
* allowed if a specific buffer count has been set.
*
* Returns 0 on success or -errno on error.
*
* XXX: This function is deprecated. It will continue to work for some
* time for binary compatibility, but the new dequeueBuffer function that
* outputs a fence file descriptor should be used in its place.
*/
int (*dequeueBuffer_DEPRECATED)(struct ANativeWindow *window,
struct ANativeWindowBuffer **buffer);
/*
* hook called by EGL to lock a buffer. This MUST be called before modifying
* the content of a buffer. The buffer must have been acquired with
* dequeueBuffer first.
*
* Returns 0 on success or -errno on error.
*
* XXX: This function is deprecated. It will continue to work for some
* time for binary compatibility, but it is essentially a no-op, and calls
* to it should be removed.
*/
int (*lockBuffer_DEPRECATED)(struct ANativeWindow *window,
struct ANativeWindowBuffer *buffer);
/*
* Hook called by EGL when modifications to the render buffer are done.
* This unlocks and post the buffer.
*
* The window holds a reference to the buffer between dequeueBuffer and
* either queueBuffer or cancelBuffer, so clients only need their own
* reference if they might use the buffer after queueing or canceling it.
* Holding a reference to a buffer after queueing or canceling it is only
* allowed if a specific buffer count has been set.
*
* Buffers MUST be queued in the same order than they were dequeued.
*
* Returns 0 on success or -errno on error.
*
* XXX: This function is deprecated. It will continue to work for some
* time for binary compatibility, but the new queueBuffer function that
* takes a fence file descriptor should be used in its place (pass a value
* of -1 for the fence file descriptor if there is no valid one to pass).
*/
int (*queueBuffer_DEPRECATED)(struct ANativeWindow *window,
struct ANativeWindowBuffer *buffer);
/*
* hook used to retrieve information about the native window.
*
* Returns 0 on success or -errno on error.
*/
int (*query)(const struct ANativeWindow *window,
int what, int *value);
/*
* hook used to perform various operations on the surface.
* (*perform)() is a generic mechanism to add functionality to
* ANativeWindow while keeping backward binary compatibility.
*
* DO NOT CALL THIS HOOK DIRECTLY. Instead, use the helper functions
* defined below.
*
* (*perform)() returns -ENOENT if the 'what' parameter is not supported
* by the surface's implementation.
*
* See above for a list of valid operations, such as
* NATIVE_WINDOW_SET_USAGE or NATIVE_WINDOW_CONNECT
*/
int (*perform)(struct ANativeWindow *window,
int operation, ...);
/*
* Hook used to cancel a buffer that has been dequeued.
* No synchronization is performed between dequeue() and cancel(), so
* either external synchronization is needed, or these functions must be
* called from the same thread.
*
* The window holds a reference to the buffer between dequeueBuffer and
* either queueBuffer or cancelBuffer, so clients only need their own
* reference if they might use the buffer after queueing or canceling it.
* Holding a reference to a buffer after queueing or canceling it is only
* allowed if a specific buffer count has been set.
*
* XXX: This function is deprecated. It will continue to work for some
* time for binary compatibility, but the new cancelBuffer function that
* takes a fence file descriptor should be used in its place (pass a value
* of -1 for the fence file descriptor if there is no valid one to pass).
*/
int (*cancelBuffer_DEPRECATED)(struct ANativeWindow *window,
struct ANativeWindowBuffer *buffer);
/*
* Hook called by EGL to acquire a buffer. This call may block if no
* buffers are available.
*
* The window holds a reference to the buffer between dequeueBuffer and
* either queueBuffer or cancelBuffer, so clients only need their own
* reference if they might use the buffer after queueing or canceling it.
* Holding a reference to a buffer after queueing or canceling it is only
* allowed if a specific buffer count has been set.
*
* The libsync fence file descriptor returned in the int pointed to by the
* fenceFd argument will refer to the fence that must signal before the
* dequeued buffer may be written to. A value of -1 indicates that the
* caller may access the buffer immediately without waiting on a fence. If
* a valid file descriptor is returned (i.e. any value except -1) then the
* caller is responsible for closing the file descriptor.
*
* Returns 0 on success or -errno on error.
*/
int (*dequeueBuffer)(struct ANativeWindow *window,
struct ANativeWindowBuffer **buffer, int *fenceFd);
/*
* Hook called by EGL when modifications to the render buffer are done.
* This unlocks and post the buffer.
*
* The window holds a reference to the buffer between dequeueBuffer and
* either queueBuffer or cancelBuffer, so clients only need their own
* reference if they might use the buffer after queueing or canceling it.
* Holding a reference to a buffer after queueing or canceling it is only
* allowed if a specific buffer count has been set.
*
* The fenceFd argument specifies a libsync fence file descriptor for a
* fence that must signal before the buffer can be accessed. If the buffer
* can be accessed immediately then a value of -1 should be used. The
* caller must not use the file descriptor after it is passed to
* queueBuffer, and the ANativeWindow implementation is responsible for
* closing it.
*
* Returns 0 on success or -errno on error.
*/
int (*queueBuffer)(struct ANativeWindow *window,
struct ANativeWindowBuffer *buffer, int fenceFd);
/*
* Hook used to cancel a buffer that has been dequeued.
* No synchronization is performed between dequeue() and cancel(), so
* either external synchronization is needed, or these functions must be
* called from the same thread.
*
* The window holds a reference to the buffer between dequeueBuffer and
* either queueBuffer or cancelBuffer, so clients only need their own
* reference if they might use the buffer after queueing or canceling it.
* Holding a reference to a buffer after queueing or canceling it is only
* allowed if a specific buffer count has been set.
*
* The fenceFd argument specifies a libsync fence file decsriptor for a
* fence that must signal before the buffer can be accessed. If the buffer
* can be accessed immediately then a value of -1 should be used.
*
* Note that if the client has not waited on the fence that was returned
* from dequeueBuffer, that same fence should be passed to cancelBuffer to
* ensure that future uses of the buffer are preceded by a wait on that
* fence. The caller must not use the file descriptor after it is passed
* to cancelBuffer, and the ANativeWindow implementation is responsible for
* closing it.
*
* Returns 0 on success or -errno on error.
*/
int (*cancelBuffer)(struct ANativeWindow *window,
struct ANativeWindowBuffer *buffer, int fenceFd);
};
@@ -0,0 +1,404 @@
// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// This file is generated.
#include "vulkan_wrapper.h"
#include <dlfcn.h>
int InitVulkan(void) {
void* libvulkan = dlopen("libvulkan.so", RTLD_NOW | RTLD_LOCAL);
if (!libvulkan)
return 0;
// Vulkan supported, set function addresses
vkCreateInstance = reinterpret_cast<PFN_vkCreateInstance>(dlsym(libvulkan, "vkCreateInstance"));
vkDestroyInstance = reinterpret_cast<PFN_vkDestroyInstance>(dlsym(libvulkan, "vkDestroyInstance"));
vkEnumeratePhysicalDevices = reinterpret_cast<PFN_vkEnumeratePhysicalDevices>(dlsym(libvulkan, "vkEnumeratePhysicalDevices"));
vkGetPhysicalDeviceFeatures = reinterpret_cast<PFN_vkGetPhysicalDeviceFeatures>(dlsym(libvulkan, "vkGetPhysicalDeviceFeatures"));
vkGetPhysicalDeviceFormatProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceFormatProperties>(dlsym(libvulkan, "vkGetPhysicalDeviceFormatProperties"));
vkGetPhysicalDeviceImageFormatProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceImageFormatProperties>(dlsym(libvulkan, "vkGetPhysicalDeviceImageFormatProperties"));
vkGetPhysicalDeviceProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceProperties>(dlsym(libvulkan, "vkGetPhysicalDeviceProperties"));
vkGetPhysicalDeviceQueueFamilyProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceQueueFamilyProperties>(dlsym(libvulkan, "vkGetPhysicalDeviceQueueFamilyProperties"));
vkGetPhysicalDeviceMemoryProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceMemoryProperties>(dlsym(libvulkan, "vkGetPhysicalDeviceMemoryProperties"));
vkGetInstanceProcAddr = reinterpret_cast<PFN_vkGetInstanceProcAddr>(dlsym(libvulkan, "vkGetInstanceProcAddr"));
vkGetDeviceProcAddr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(dlsym(libvulkan, "vkGetDeviceProcAddr"));
vkCreateDevice = reinterpret_cast<PFN_vkCreateDevice>(dlsym(libvulkan, "vkCreateDevice"));
vkDestroyDevice = reinterpret_cast<PFN_vkDestroyDevice>(dlsym(libvulkan, "vkDestroyDevice"));
vkEnumerateInstanceExtensionProperties = reinterpret_cast<PFN_vkEnumerateInstanceExtensionProperties>(dlsym(libvulkan, "vkEnumerateInstanceExtensionProperties"));
vkEnumerateDeviceExtensionProperties = reinterpret_cast<PFN_vkEnumerateDeviceExtensionProperties>(dlsym(libvulkan, "vkEnumerateDeviceExtensionProperties"));
vkEnumerateInstanceLayerProperties = reinterpret_cast<PFN_vkEnumerateInstanceLayerProperties>(dlsym(libvulkan, "vkEnumerateInstanceLayerProperties"));
vkEnumerateDeviceLayerProperties = reinterpret_cast<PFN_vkEnumerateDeviceLayerProperties>(dlsym(libvulkan, "vkEnumerateDeviceLayerProperties"));
vkGetDeviceQueue = reinterpret_cast<PFN_vkGetDeviceQueue>(dlsym(libvulkan, "vkGetDeviceQueue"));
vkQueueSubmit = reinterpret_cast<PFN_vkQueueSubmit>(dlsym(libvulkan, "vkQueueSubmit"));
vkQueueWaitIdle = reinterpret_cast<PFN_vkQueueWaitIdle>(dlsym(libvulkan, "vkQueueWaitIdle"));
vkDeviceWaitIdle = reinterpret_cast<PFN_vkDeviceWaitIdle>(dlsym(libvulkan, "vkDeviceWaitIdle"));
vkAllocateMemory = reinterpret_cast<PFN_vkAllocateMemory>(dlsym(libvulkan, "vkAllocateMemory"));
vkFreeMemory = reinterpret_cast<PFN_vkFreeMemory>(dlsym(libvulkan, "vkFreeMemory"));
vkMapMemory = reinterpret_cast<PFN_vkMapMemory>(dlsym(libvulkan, "vkMapMemory"));
vkUnmapMemory = reinterpret_cast<PFN_vkUnmapMemory>(dlsym(libvulkan, "vkUnmapMemory"));
vkFlushMappedMemoryRanges = reinterpret_cast<PFN_vkFlushMappedMemoryRanges>(dlsym(libvulkan, "vkFlushMappedMemoryRanges"));
vkInvalidateMappedMemoryRanges = reinterpret_cast<PFN_vkInvalidateMappedMemoryRanges>(dlsym(libvulkan, "vkInvalidateMappedMemoryRanges"));
vkGetDeviceMemoryCommitment = reinterpret_cast<PFN_vkGetDeviceMemoryCommitment>(dlsym(libvulkan, "vkGetDeviceMemoryCommitment"));
vkBindBufferMemory = reinterpret_cast<PFN_vkBindBufferMemory>(dlsym(libvulkan, "vkBindBufferMemory"));
vkBindImageMemory = reinterpret_cast<PFN_vkBindImageMemory>(dlsym(libvulkan, "vkBindImageMemory"));
vkGetBufferMemoryRequirements = reinterpret_cast<PFN_vkGetBufferMemoryRequirements>(dlsym(libvulkan, "vkGetBufferMemoryRequirements"));
vkGetImageMemoryRequirements = reinterpret_cast<PFN_vkGetImageMemoryRequirements>(dlsym(libvulkan, "vkGetImageMemoryRequirements"));
vkGetImageSparseMemoryRequirements = reinterpret_cast<PFN_vkGetImageSparseMemoryRequirements>(dlsym(libvulkan, "vkGetImageSparseMemoryRequirements"));
vkGetPhysicalDeviceSparseImageFormatProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceSparseImageFormatProperties>(dlsym(libvulkan, "vkGetPhysicalDeviceSparseImageFormatProperties"));
vkQueueBindSparse = reinterpret_cast<PFN_vkQueueBindSparse>(dlsym(libvulkan, "vkQueueBindSparse"));
vkCreateFence = reinterpret_cast<PFN_vkCreateFence>(dlsym(libvulkan, "vkCreateFence"));
vkDestroyFence = reinterpret_cast<PFN_vkDestroyFence>(dlsym(libvulkan, "vkDestroyFence"));
vkResetFences = reinterpret_cast<PFN_vkResetFences>(dlsym(libvulkan, "vkResetFences"));
vkGetFenceStatus = reinterpret_cast<PFN_vkGetFenceStatus>(dlsym(libvulkan, "vkGetFenceStatus"));
vkWaitForFences = reinterpret_cast<PFN_vkWaitForFences>(dlsym(libvulkan, "vkWaitForFences"));
vkCreateSemaphore = reinterpret_cast<PFN_vkCreateSemaphore>(dlsym(libvulkan, "vkCreateSemaphore"));
vkDestroySemaphore = reinterpret_cast<PFN_vkDestroySemaphore>(dlsym(libvulkan, "vkDestroySemaphore"));
vkCreateEvent = reinterpret_cast<PFN_vkCreateEvent>(dlsym(libvulkan, "vkCreateEvent"));
vkDestroyEvent = reinterpret_cast<PFN_vkDestroyEvent>(dlsym(libvulkan, "vkDestroyEvent"));
vkGetEventStatus = reinterpret_cast<PFN_vkGetEventStatus>(dlsym(libvulkan, "vkGetEventStatus"));
vkSetEvent = reinterpret_cast<PFN_vkSetEvent>(dlsym(libvulkan, "vkSetEvent"));
vkResetEvent = reinterpret_cast<PFN_vkResetEvent>(dlsym(libvulkan, "vkResetEvent"));
vkCreateQueryPool = reinterpret_cast<PFN_vkCreateQueryPool>(dlsym(libvulkan, "vkCreateQueryPool"));
vkDestroyQueryPool = reinterpret_cast<PFN_vkDestroyQueryPool>(dlsym(libvulkan, "vkDestroyQueryPool"));
vkGetQueryPoolResults = reinterpret_cast<PFN_vkGetQueryPoolResults>(dlsym(libvulkan, "vkGetQueryPoolResults"));
vkCreateBuffer = reinterpret_cast<PFN_vkCreateBuffer>(dlsym(libvulkan, "vkCreateBuffer"));
vkDestroyBuffer = reinterpret_cast<PFN_vkDestroyBuffer>(dlsym(libvulkan, "vkDestroyBuffer"));
vkCreateBufferView = reinterpret_cast<PFN_vkCreateBufferView>(dlsym(libvulkan, "vkCreateBufferView"));
vkDestroyBufferView = reinterpret_cast<PFN_vkDestroyBufferView>(dlsym(libvulkan, "vkDestroyBufferView"));
vkCreateImage = reinterpret_cast<PFN_vkCreateImage>(dlsym(libvulkan, "vkCreateImage"));
vkDestroyImage = reinterpret_cast<PFN_vkDestroyImage>(dlsym(libvulkan, "vkDestroyImage"));
vkGetImageSubresourceLayout = reinterpret_cast<PFN_vkGetImageSubresourceLayout>(dlsym(libvulkan, "vkGetImageSubresourceLayout"));
vkCreateImageView = reinterpret_cast<PFN_vkCreateImageView>(dlsym(libvulkan, "vkCreateImageView"));
vkDestroyImageView = reinterpret_cast<PFN_vkDestroyImageView>(dlsym(libvulkan, "vkDestroyImageView"));
vkCreateShaderModule = reinterpret_cast<PFN_vkCreateShaderModule>(dlsym(libvulkan, "vkCreateShaderModule"));
vkDestroyShaderModule = reinterpret_cast<PFN_vkDestroyShaderModule>(dlsym(libvulkan, "vkDestroyShaderModule"));
vkCreatePipelineCache = reinterpret_cast<PFN_vkCreatePipelineCache>(dlsym(libvulkan, "vkCreatePipelineCache"));
vkDestroyPipelineCache = reinterpret_cast<PFN_vkDestroyPipelineCache>(dlsym(libvulkan, "vkDestroyPipelineCache"));
vkGetPipelineCacheData = reinterpret_cast<PFN_vkGetPipelineCacheData>(dlsym(libvulkan, "vkGetPipelineCacheData"));
vkMergePipelineCaches = reinterpret_cast<PFN_vkMergePipelineCaches>(dlsym(libvulkan, "vkMergePipelineCaches"));
vkCreateGraphicsPipelines = reinterpret_cast<PFN_vkCreateGraphicsPipelines>(dlsym(libvulkan, "vkCreateGraphicsPipelines"));
vkCreateComputePipelines = reinterpret_cast<PFN_vkCreateComputePipelines>(dlsym(libvulkan, "vkCreateComputePipelines"));
vkDestroyPipeline = reinterpret_cast<PFN_vkDestroyPipeline>(dlsym(libvulkan, "vkDestroyPipeline"));
vkCreatePipelineLayout = reinterpret_cast<PFN_vkCreatePipelineLayout>(dlsym(libvulkan, "vkCreatePipelineLayout"));
vkDestroyPipelineLayout = reinterpret_cast<PFN_vkDestroyPipelineLayout>(dlsym(libvulkan, "vkDestroyPipelineLayout"));
vkCreateSampler = reinterpret_cast<PFN_vkCreateSampler>(dlsym(libvulkan, "vkCreateSampler"));
vkDestroySampler = reinterpret_cast<PFN_vkDestroySampler>(dlsym(libvulkan, "vkDestroySampler"));
vkCreateDescriptorSetLayout = reinterpret_cast<PFN_vkCreateDescriptorSetLayout>(dlsym(libvulkan, "vkCreateDescriptorSetLayout"));
vkDestroyDescriptorSetLayout = reinterpret_cast<PFN_vkDestroyDescriptorSetLayout>(dlsym(libvulkan, "vkDestroyDescriptorSetLayout"));
vkCreateDescriptorPool = reinterpret_cast<PFN_vkCreateDescriptorPool>(dlsym(libvulkan, "vkCreateDescriptorPool"));
vkDestroyDescriptorPool = reinterpret_cast<PFN_vkDestroyDescriptorPool>(dlsym(libvulkan, "vkDestroyDescriptorPool"));
vkResetDescriptorPool = reinterpret_cast<PFN_vkResetDescriptorPool>(dlsym(libvulkan, "vkResetDescriptorPool"));
vkAllocateDescriptorSets = reinterpret_cast<PFN_vkAllocateDescriptorSets>(dlsym(libvulkan, "vkAllocateDescriptorSets"));
vkFreeDescriptorSets = reinterpret_cast<PFN_vkFreeDescriptorSets>(dlsym(libvulkan, "vkFreeDescriptorSets"));
vkUpdateDescriptorSets = reinterpret_cast<PFN_vkUpdateDescriptorSets>(dlsym(libvulkan, "vkUpdateDescriptorSets"));
vkCreateFramebuffer = reinterpret_cast<PFN_vkCreateFramebuffer>(dlsym(libvulkan, "vkCreateFramebuffer"));
vkDestroyFramebuffer = reinterpret_cast<PFN_vkDestroyFramebuffer>(dlsym(libvulkan, "vkDestroyFramebuffer"));
vkCreateRenderPass = reinterpret_cast<PFN_vkCreateRenderPass>(dlsym(libvulkan, "vkCreateRenderPass"));
vkDestroyRenderPass = reinterpret_cast<PFN_vkDestroyRenderPass>(dlsym(libvulkan, "vkDestroyRenderPass"));
vkGetRenderAreaGranularity = reinterpret_cast<PFN_vkGetRenderAreaGranularity>(dlsym(libvulkan, "vkGetRenderAreaGranularity"));
vkCreateCommandPool = reinterpret_cast<PFN_vkCreateCommandPool>(dlsym(libvulkan, "vkCreateCommandPool"));
vkDestroyCommandPool = reinterpret_cast<PFN_vkDestroyCommandPool>(dlsym(libvulkan, "vkDestroyCommandPool"));
vkResetCommandPool = reinterpret_cast<PFN_vkResetCommandPool>(dlsym(libvulkan, "vkResetCommandPool"));
vkAllocateCommandBuffers = reinterpret_cast<PFN_vkAllocateCommandBuffers>(dlsym(libvulkan, "vkAllocateCommandBuffers"));
vkFreeCommandBuffers = reinterpret_cast<PFN_vkFreeCommandBuffers>(dlsym(libvulkan, "vkFreeCommandBuffers"));
vkBeginCommandBuffer = reinterpret_cast<PFN_vkBeginCommandBuffer>(dlsym(libvulkan, "vkBeginCommandBuffer"));
vkEndCommandBuffer = reinterpret_cast<PFN_vkEndCommandBuffer>(dlsym(libvulkan, "vkEndCommandBuffer"));
vkResetCommandBuffer = reinterpret_cast<PFN_vkResetCommandBuffer>(dlsym(libvulkan, "vkResetCommandBuffer"));
vkCmdBindPipeline = reinterpret_cast<PFN_vkCmdBindPipeline>(dlsym(libvulkan, "vkCmdBindPipeline"));
vkCmdSetViewport = reinterpret_cast<PFN_vkCmdSetViewport>(dlsym(libvulkan, "vkCmdSetViewport"));
vkCmdSetScissor = reinterpret_cast<PFN_vkCmdSetScissor>(dlsym(libvulkan, "vkCmdSetScissor"));
vkCmdSetLineWidth = reinterpret_cast<PFN_vkCmdSetLineWidth>(dlsym(libvulkan, "vkCmdSetLineWidth"));
vkCmdSetDepthBias = reinterpret_cast<PFN_vkCmdSetDepthBias>(dlsym(libvulkan, "vkCmdSetDepthBias"));
vkCmdSetBlendConstants = reinterpret_cast<PFN_vkCmdSetBlendConstants>(dlsym(libvulkan, "vkCmdSetBlendConstants"));
vkCmdSetDepthBounds = reinterpret_cast<PFN_vkCmdSetDepthBounds>(dlsym(libvulkan, "vkCmdSetDepthBounds"));
vkCmdSetStencilCompareMask = reinterpret_cast<PFN_vkCmdSetStencilCompareMask>(dlsym(libvulkan, "vkCmdSetStencilCompareMask"));
vkCmdSetStencilWriteMask = reinterpret_cast<PFN_vkCmdSetStencilWriteMask>(dlsym(libvulkan, "vkCmdSetStencilWriteMask"));
vkCmdSetStencilReference = reinterpret_cast<PFN_vkCmdSetStencilReference>(dlsym(libvulkan, "vkCmdSetStencilReference"));
vkCmdBindDescriptorSets = reinterpret_cast<PFN_vkCmdBindDescriptorSets>(dlsym(libvulkan, "vkCmdBindDescriptorSets"));
vkCmdBindIndexBuffer = reinterpret_cast<PFN_vkCmdBindIndexBuffer>(dlsym(libvulkan, "vkCmdBindIndexBuffer"));
vkCmdBindVertexBuffers = reinterpret_cast<PFN_vkCmdBindVertexBuffers>(dlsym(libvulkan, "vkCmdBindVertexBuffers"));
vkCmdDraw = reinterpret_cast<PFN_vkCmdDraw>(dlsym(libvulkan, "vkCmdDraw"));
vkCmdDrawIndexed = reinterpret_cast<PFN_vkCmdDrawIndexed>(dlsym(libvulkan, "vkCmdDrawIndexed"));
vkCmdDrawIndirect = reinterpret_cast<PFN_vkCmdDrawIndirect>(dlsym(libvulkan, "vkCmdDrawIndirect"));
vkCmdDrawIndexedIndirect = reinterpret_cast<PFN_vkCmdDrawIndexedIndirect>(dlsym(libvulkan, "vkCmdDrawIndexedIndirect"));
vkCmdDispatch = reinterpret_cast<PFN_vkCmdDispatch>(dlsym(libvulkan, "vkCmdDispatch"));
vkCmdDispatchIndirect = reinterpret_cast<PFN_vkCmdDispatchIndirect>(dlsym(libvulkan, "vkCmdDispatchIndirect"));
vkCmdCopyBuffer = reinterpret_cast<PFN_vkCmdCopyBuffer>(dlsym(libvulkan, "vkCmdCopyBuffer"));
vkCmdCopyImage = reinterpret_cast<PFN_vkCmdCopyImage>(dlsym(libvulkan, "vkCmdCopyImage"));
vkCmdBlitImage = reinterpret_cast<PFN_vkCmdBlitImage>(dlsym(libvulkan, "vkCmdBlitImage"));
vkCmdCopyBufferToImage = reinterpret_cast<PFN_vkCmdCopyBufferToImage>(dlsym(libvulkan, "vkCmdCopyBufferToImage"));
vkCmdCopyImageToBuffer = reinterpret_cast<PFN_vkCmdCopyImageToBuffer>(dlsym(libvulkan, "vkCmdCopyImageToBuffer"));
vkCmdUpdateBuffer = reinterpret_cast<PFN_vkCmdUpdateBuffer>(dlsym(libvulkan, "vkCmdUpdateBuffer"));
vkCmdFillBuffer = reinterpret_cast<PFN_vkCmdFillBuffer>(dlsym(libvulkan, "vkCmdFillBuffer"));
vkCmdClearColorImage = reinterpret_cast<PFN_vkCmdClearColorImage>(dlsym(libvulkan, "vkCmdClearColorImage"));
vkCmdClearDepthStencilImage = reinterpret_cast<PFN_vkCmdClearDepthStencilImage>(dlsym(libvulkan, "vkCmdClearDepthStencilImage"));
vkCmdClearAttachments = reinterpret_cast<PFN_vkCmdClearAttachments>(dlsym(libvulkan, "vkCmdClearAttachments"));
vkCmdResolveImage = reinterpret_cast<PFN_vkCmdResolveImage>(dlsym(libvulkan, "vkCmdResolveImage"));
vkCmdSetEvent = reinterpret_cast<PFN_vkCmdSetEvent>(dlsym(libvulkan, "vkCmdSetEvent"));
vkCmdResetEvent = reinterpret_cast<PFN_vkCmdResetEvent>(dlsym(libvulkan, "vkCmdResetEvent"));
vkCmdWaitEvents = reinterpret_cast<PFN_vkCmdWaitEvents>(dlsym(libvulkan, "vkCmdWaitEvents"));
vkCmdPipelineBarrier = reinterpret_cast<PFN_vkCmdPipelineBarrier>(dlsym(libvulkan, "vkCmdPipelineBarrier"));
vkCmdBeginQuery = reinterpret_cast<PFN_vkCmdBeginQuery>(dlsym(libvulkan, "vkCmdBeginQuery"));
vkCmdEndQuery = reinterpret_cast<PFN_vkCmdEndQuery>(dlsym(libvulkan, "vkCmdEndQuery"));
vkCmdResetQueryPool = reinterpret_cast<PFN_vkCmdResetQueryPool>(dlsym(libvulkan, "vkCmdResetQueryPool"));
vkCmdWriteTimestamp = reinterpret_cast<PFN_vkCmdWriteTimestamp>(dlsym(libvulkan, "vkCmdWriteTimestamp"));
vkCmdCopyQueryPoolResults = reinterpret_cast<PFN_vkCmdCopyQueryPoolResults>(dlsym(libvulkan, "vkCmdCopyQueryPoolResults"));
vkCmdPushConstants = reinterpret_cast<PFN_vkCmdPushConstants>(dlsym(libvulkan, "vkCmdPushConstants"));
vkCmdBeginRenderPass = reinterpret_cast<PFN_vkCmdBeginRenderPass>(dlsym(libvulkan, "vkCmdBeginRenderPass"));
vkCmdNextSubpass = reinterpret_cast<PFN_vkCmdNextSubpass>(dlsym(libvulkan, "vkCmdNextSubpass"));
vkCmdEndRenderPass = reinterpret_cast<PFN_vkCmdEndRenderPass>(dlsym(libvulkan, "vkCmdEndRenderPass"));
vkCmdExecuteCommands = reinterpret_cast<PFN_vkCmdExecuteCommands>(dlsym(libvulkan, "vkCmdExecuteCommands"));
vkDestroySurfaceKHR = reinterpret_cast<PFN_vkDestroySurfaceKHR>(dlsym(libvulkan, "vkDestroySurfaceKHR"));
vkGetPhysicalDeviceSurfaceSupportKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceSupportKHR>(dlsym(libvulkan, "vkGetPhysicalDeviceSurfaceSupportKHR"));
vkGetPhysicalDeviceSurfaceCapabilitiesKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR>(dlsym(libvulkan, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR"));
vkGetPhysicalDeviceSurfaceFormatsKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceFormatsKHR>(dlsym(libvulkan, "vkGetPhysicalDeviceSurfaceFormatsKHR"));
vkGetPhysicalDeviceSurfacePresentModesKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfacePresentModesKHR>(dlsym(libvulkan, "vkGetPhysicalDeviceSurfacePresentModesKHR"));
vkCreateSwapchainKHR = reinterpret_cast<PFN_vkCreateSwapchainKHR>(dlsym(libvulkan, "vkCreateSwapchainKHR"));
vkDestroySwapchainKHR = reinterpret_cast<PFN_vkDestroySwapchainKHR>(dlsym(libvulkan, "vkDestroySwapchainKHR"));
vkGetSwapchainImagesKHR = reinterpret_cast<PFN_vkGetSwapchainImagesKHR>(dlsym(libvulkan, "vkGetSwapchainImagesKHR"));
vkAcquireNextImageKHR = reinterpret_cast<PFN_vkAcquireNextImageKHR>(dlsym(libvulkan, "vkAcquireNextImageKHR"));
vkQueuePresentKHR = reinterpret_cast<PFN_vkQueuePresentKHR>(dlsym(libvulkan, "vkQueuePresentKHR"));
vkGetPhysicalDeviceDisplayPropertiesKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceDisplayPropertiesKHR>(dlsym(libvulkan, "vkGetPhysicalDeviceDisplayPropertiesKHR"));
vkGetPhysicalDeviceDisplayPlanePropertiesKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR>(dlsym(libvulkan, "vkGetPhysicalDeviceDisplayPlanePropertiesKHR"));
vkGetDisplayPlaneSupportedDisplaysKHR = reinterpret_cast<PFN_vkGetDisplayPlaneSupportedDisplaysKHR>(dlsym(libvulkan, "vkGetDisplayPlaneSupportedDisplaysKHR"));
vkGetDisplayModePropertiesKHR = reinterpret_cast<PFN_vkGetDisplayModePropertiesKHR>(dlsym(libvulkan, "vkGetDisplayModePropertiesKHR"));
vkCreateDisplayModeKHR = reinterpret_cast<PFN_vkCreateDisplayModeKHR>(dlsym(libvulkan, "vkCreateDisplayModeKHR"));
vkGetDisplayPlaneCapabilitiesKHR = reinterpret_cast<PFN_vkGetDisplayPlaneCapabilitiesKHR>(dlsym(libvulkan, "vkGetDisplayPlaneCapabilitiesKHR"));
vkCreateDisplayPlaneSurfaceKHR = reinterpret_cast<PFN_vkCreateDisplayPlaneSurfaceKHR>(dlsym(libvulkan, "vkCreateDisplayPlaneSurfaceKHR"));
vkCreateSharedSwapchainsKHR = reinterpret_cast<PFN_vkCreateSharedSwapchainsKHR>(dlsym(libvulkan, "vkCreateSharedSwapchainsKHR"));
#ifdef VK_USE_PLATFORM_XLIB_KHR
vkCreateXlibSurfaceKHR = reinterpret_cast<PFN_vkCreateXlibSurfaceKHR>(dlsym(libvulkan, "vkCreateXlibSurfaceKHR"));
vkGetPhysicalDeviceXlibPresentationSupportKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR>(dlsym(libvulkan, "vkGetPhysicalDeviceXlibPresentationSupportKHR"));
#endif
#ifdef VK_USE_PLATFORM_XCB_KHR
vkCreateXcbSurfaceKHR = reinterpret_cast<PFN_vkCreateXcbSurfaceKHR>(dlsym(libvulkan, "vkCreateXcbSurfaceKHR"));
vkGetPhysicalDeviceXcbPresentationSupportKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR>(dlsym(libvulkan, "vkGetPhysicalDeviceXcbPresentationSupportKHR"));
#endif
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
vkCreateWaylandSurfaceKHR = reinterpret_cast<PFN_vkCreateWaylandSurfaceKHR>(dlsym(libvulkan, "vkCreateWaylandSurfaceKHR"));
vkGetPhysicalDeviceWaylandPresentationSupportKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR>(dlsym(libvulkan, "vkGetPhysicalDeviceWaylandPresentationSupportKHR"));
#endif
#ifdef VK_USE_PLATFORM_MIR_KHR
vkCreateMirSurfaceKHR = reinterpret_cast<PFN_vkCreateMirSurfaceKHR>(dlsym(libvulkan, "vkCreateMirSurfaceKHR"));
vkGetPhysicalDeviceMirPresentationSupportKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceMirPresentationSupportKHR>(dlsym(libvulkan, "vkGetPhysicalDeviceMirPresentationSupportKHR"));
#endif
#ifdef VK_USE_PLATFORM_ANDROID_KHR
vkCreateAndroidSurfaceKHR = reinterpret_cast<PFN_vkCreateAndroidSurfaceKHR>(dlsym(libvulkan, "vkCreateAndroidSurfaceKHR"));
#endif
#ifdef VK_USE_PLATFORM_WIN32_KHR
vkCreateWin32SurfaceKHR = reinterpret_cast<PFN_vkCreateWin32SurfaceKHR>(dlsym(libvulkan, "vkCreateWin32SurfaceKHR"));
vkGetPhysicalDeviceWin32PresentationSupportKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR>(dlsym(libvulkan, "vkGetPhysicalDeviceWin32PresentationSupportKHR"));
#endif
#ifdef USE_DEBUG_EXTENTIONS
vkCreateDebugReportCallbackEXT = reinterpret_cast<PFN_vkCreateDebugReportCallbackEXT>(dlsym(libvulkan, "vkCreateDebugReportCallbackEXT"));
vkDestroyDebugReportCallbackEXT = reinterpret_cast<PFN_vkDestroyDebugReportCallbackEXT>(dlsym(libvulkan, "vkDestroyDebugReportCallbackEXT"));
vkDebugReportMessageEXT = reinterpret_cast<PFN_vkDebugReportMessageEXT>(dlsym(libvulkan, "vkDebugReportMessageEXT"));
#endif
return 1;
}
// No Vulkan support, do not set function addresses
PFN_vkCreateInstance vkCreateInstance;
PFN_vkDestroyInstance vkDestroyInstance;
PFN_vkEnumeratePhysicalDevices vkEnumeratePhysicalDevices;
PFN_vkGetPhysicalDeviceFeatures vkGetPhysicalDeviceFeatures;
PFN_vkGetPhysicalDeviceFormatProperties vkGetPhysicalDeviceFormatProperties;
PFN_vkGetPhysicalDeviceImageFormatProperties vkGetPhysicalDeviceImageFormatProperties;
PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties;
PFN_vkGetPhysicalDeviceQueueFamilyProperties vkGetPhysicalDeviceQueueFamilyProperties;
PFN_vkGetPhysicalDeviceMemoryProperties vkGetPhysicalDeviceMemoryProperties;
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr;
PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr;
PFN_vkCreateDevice vkCreateDevice;
PFN_vkDestroyDevice vkDestroyDevice;
PFN_vkEnumerateInstanceExtensionProperties vkEnumerateInstanceExtensionProperties;
PFN_vkEnumerateDeviceExtensionProperties vkEnumerateDeviceExtensionProperties;
PFN_vkEnumerateInstanceLayerProperties vkEnumerateInstanceLayerProperties;
PFN_vkEnumerateDeviceLayerProperties vkEnumerateDeviceLayerProperties;
PFN_vkGetDeviceQueue vkGetDeviceQueue;
PFN_vkQueueSubmit vkQueueSubmit;
PFN_vkQueueWaitIdle vkQueueWaitIdle;
PFN_vkDeviceWaitIdle vkDeviceWaitIdle;
PFN_vkAllocateMemory vkAllocateMemory;
PFN_vkFreeMemory vkFreeMemory;
PFN_vkMapMemory vkMapMemory;
PFN_vkUnmapMemory vkUnmapMemory;
PFN_vkFlushMappedMemoryRanges vkFlushMappedMemoryRanges;
PFN_vkInvalidateMappedMemoryRanges vkInvalidateMappedMemoryRanges;
PFN_vkGetDeviceMemoryCommitment vkGetDeviceMemoryCommitment;
PFN_vkBindBufferMemory vkBindBufferMemory;
PFN_vkBindImageMemory vkBindImageMemory;
PFN_vkGetBufferMemoryRequirements vkGetBufferMemoryRequirements;
PFN_vkGetImageMemoryRequirements vkGetImageMemoryRequirements;
PFN_vkGetImageSparseMemoryRequirements vkGetImageSparseMemoryRequirements;
PFN_vkGetPhysicalDeviceSparseImageFormatProperties vkGetPhysicalDeviceSparseImageFormatProperties;
PFN_vkQueueBindSparse vkQueueBindSparse;
PFN_vkCreateFence vkCreateFence;
PFN_vkDestroyFence vkDestroyFence;
PFN_vkResetFences vkResetFences;
PFN_vkGetFenceStatus vkGetFenceStatus;
PFN_vkWaitForFences vkWaitForFences;
PFN_vkCreateSemaphore vkCreateSemaphore;
PFN_vkDestroySemaphore vkDestroySemaphore;
PFN_vkCreateEvent vkCreateEvent;
PFN_vkDestroyEvent vkDestroyEvent;
PFN_vkGetEventStatus vkGetEventStatus;
PFN_vkSetEvent vkSetEvent;
PFN_vkResetEvent vkResetEvent;
PFN_vkCreateQueryPool vkCreateQueryPool;
PFN_vkDestroyQueryPool vkDestroyQueryPool;
PFN_vkGetQueryPoolResults vkGetQueryPoolResults;
PFN_vkCreateBuffer vkCreateBuffer;
PFN_vkDestroyBuffer vkDestroyBuffer;
PFN_vkCreateBufferView vkCreateBufferView;
PFN_vkDestroyBufferView vkDestroyBufferView;
PFN_vkCreateImage vkCreateImage;
PFN_vkDestroyImage vkDestroyImage;
PFN_vkGetImageSubresourceLayout vkGetImageSubresourceLayout;
PFN_vkCreateImageView vkCreateImageView;
PFN_vkDestroyImageView vkDestroyImageView;
PFN_vkCreateShaderModule vkCreateShaderModule;
PFN_vkDestroyShaderModule vkDestroyShaderModule;
PFN_vkCreatePipelineCache vkCreatePipelineCache;
PFN_vkDestroyPipelineCache vkDestroyPipelineCache;
PFN_vkGetPipelineCacheData vkGetPipelineCacheData;
PFN_vkMergePipelineCaches vkMergePipelineCaches;
PFN_vkCreateGraphicsPipelines vkCreateGraphicsPipelines;
PFN_vkCreateComputePipelines vkCreateComputePipelines;
PFN_vkDestroyPipeline vkDestroyPipeline;
PFN_vkCreatePipelineLayout vkCreatePipelineLayout;
PFN_vkDestroyPipelineLayout vkDestroyPipelineLayout;
PFN_vkCreateSampler vkCreateSampler;
PFN_vkDestroySampler vkDestroySampler;
PFN_vkCreateDescriptorSetLayout vkCreateDescriptorSetLayout;
PFN_vkDestroyDescriptorSetLayout vkDestroyDescriptorSetLayout;
PFN_vkCreateDescriptorPool vkCreateDescriptorPool;
PFN_vkDestroyDescriptorPool vkDestroyDescriptorPool;
PFN_vkResetDescriptorPool vkResetDescriptorPool;
PFN_vkAllocateDescriptorSets vkAllocateDescriptorSets;
PFN_vkFreeDescriptorSets vkFreeDescriptorSets;
PFN_vkUpdateDescriptorSets vkUpdateDescriptorSets;
PFN_vkCreateFramebuffer vkCreateFramebuffer;
PFN_vkDestroyFramebuffer vkDestroyFramebuffer;
PFN_vkCreateRenderPass vkCreateRenderPass;
PFN_vkDestroyRenderPass vkDestroyRenderPass;
PFN_vkGetRenderAreaGranularity vkGetRenderAreaGranularity;
PFN_vkCreateCommandPool vkCreateCommandPool;
PFN_vkDestroyCommandPool vkDestroyCommandPool;
PFN_vkResetCommandPool vkResetCommandPool;
PFN_vkAllocateCommandBuffers vkAllocateCommandBuffers;
PFN_vkFreeCommandBuffers vkFreeCommandBuffers;
PFN_vkBeginCommandBuffer vkBeginCommandBuffer;
PFN_vkEndCommandBuffer vkEndCommandBuffer;
PFN_vkResetCommandBuffer vkResetCommandBuffer;
PFN_vkCmdBindPipeline vkCmdBindPipeline;
PFN_vkCmdSetViewport vkCmdSetViewport;
PFN_vkCmdSetScissor vkCmdSetScissor;
PFN_vkCmdSetLineWidth vkCmdSetLineWidth;
PFN_vkCmdSetDepthBias vkCmdSetDepthBias;
PFN_vkCmdSetBlendConstants vkCmdSetBlendConstants;
PFN_vkCmdSetDepthBounds vkCmdSetDepthBounds;
PFN_vkCmdSetStencilCompareMask vkCmdSetStencilCompareMask;
PFN_vkCmdSetStencilWriteMask vkCmdSetStencilWriteMask;
PFN_vkCmdSetStencilReference vkCmdSetStencilReference;
PFN_vkCmdBindDescriptorSets vkCmdBindDescriptorSets;
PFN_vkCmdBindIndexBuffer vkCmdBindIndexBuffer;
PFN_vkCmdBindVertexBuffers vkCmdBindVertexBuffers;
PFN_vkCmdDraw vkCmdDraw;
PFN_vkCmdDrawIndexed vkCmdDrawIndexed;
PFN_vkCmdDrawIndirect vkCmdDrawIndirect;
PFN_vkCmdDrawIndexedIndirect vkCmdDrawIndexedIndirect;
PFN_vkCmdDispatch vkCmdDispatch;
PFN_vkCmdDispatchIndirect vkCmdDispatchIndirect;
PFN_vkCmdCopyBuffer vkCmdCopyBuffer;
PFN_vkCmdCopyImage vkCmdCopyImage;
PFN_vkCmdBlitImage vkCmdBlitImage;
PFN_vkCmdCopyBufferToImage vkCmdCopyBufferToImage;
PFN_vkCmdCopyImageToBuffer vkCmdCopyImageToBuffer;
PFN_vkCmdUpdateBuffer vkCmdUpdateBuffer;
PFN_vkCmdFillBuffer vkCmdFillBuffer;
PFN_vkCmdClearColorImage vkCmdClearColorImage;
PFN_vkCmdClearDepthStencilImage vkCmdClearDepthStencilImage;
PFN_vkCmdClearAttachments vkCmdClearAttachments;
PFN_vkCmdResolveImage vkCmdResolveImage;
PFN_vkCmdSetEvent vkCmdSetEvent;
PFN_vkCmdResetEvent vkCmdResetEvent;
PFN_vkCmdWaitEvents vkCmdWaitEvents;
PFN_vkCmdPipelineBarrier vkCmdPipelineBarrier;
PFN_vkCmdBeginQuery vkCmdBeginQuery;
PFN_vkCmdEndQuery vkCmdEndQuery;
PFN_vkCmdResetQueryPool vkCmdResetQueryPool;
PFN_vkCmdWriteTimestamp vkCmdWriteTimestamp;
PFN_vkCmdCopyQueryPoolResults vkCmdCopyQueryPoolResults;
PFN_vkCmdPushConstants vkCmdPushConstants;
PFN_vkCmdBeginRenderPass vkCmdBeginRenderPass;
PFN_vkCmdNextSubpass vkCmdNextSubpass;
PFN_vkCmdEndRenderPass vkCmdEndRenderPass;
PFN_vkCmdExecuteCommands vkCmdExecuteCommands;
PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR;
PFN_vkGetPhysicalDeviceSurfaceSupportKHR vkGetPhysicalDeviceSurfaceSupportKHR;
PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vkGetPhysicalDeviceSurfaceCapabilitiesKHR;
PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vkGetPhysicalDeviceSurfaceFormatsKHR;
PFN_vkGetPhysicalDeviceSurfacePresentModesKHR vkGetPhysicalDeviceSurfacePresentModesKHR;
PFN_vkCreateSwapchainKHR vkCreateSwapchainKHR;
PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR;
PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR;
PFN_vkAcquireNextImageKHR vkAcquireNextImageKHR;
PFN_vkQueuePresentKHR vkQueuePresentKHR;
PFN_vkGetPhysicalDeviceDisplayPropertiesKHR vkGetPhysicalDeviceDisplayPropertiesKHR;
PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR vkGetPhysicalDeviceDisplayPlanePropertiesKHR;
PFN_vkGetDisplayPlaneSupportedDisplaysKHR vkGetDisplayPlaneSupportedDisplaysKHR;
PFN_vkGetDisplayModePropertiesKHR vkGetDisplayModePropertiesKHR;
PFN_vkCreateDisplayModeKHR vkCreateDisplayModeKHR;
PFN_vkGetDisplayPlaneCapabilitiesKHR vkGetDisplayPlaneCapabilitiesKHR;
PFN_vkCreateDisplayPlaneSurfaceKHR vkCreateDisplayPlaneSurfaceKHR;
PFN_vkCreateSharedSwapchainsKHR vkCreateSharedSwapchainsKHR;
#ifdef VK_USE_PLATFORM_XLIB_KHR
PFN_vkCreateXlibSurfaceKHR vkCreateXlibSurfaceKHR;
PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR vkGetPhysicalDeviceXlibPresentationSupportKHR;
#endif
#ifdef VK_USE_PLATFORM_XCB_KHR
PFN_vkCreateXcbSurfaceKHR vkCreateXcbSurfaceKHR;
PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR vkGetPhysicalDeviceXcbPresentationSupportKHR;
#endif
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
PFN_vkCreateWaylandSurfaceKHR vkCreateWaylandSurfaceKHR;
PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR vkGetPhysicalDeviceWaylandPresentationSupportKHR;
#endif
#ifdef VK_USE_PLATFORM_MIR_KHR
PFN_vkCreateMirSurfaceKHR vkCreateMirSurfaceKHR;
PFN_vkGetPhysicalDeviceMirPresentationSupportKHR vkGetPhysicalDeviceMirPresentationSupportKHR;
#endif
#ifdef VK_USE_PLATFORM_ANDROID_KHR
PFN_vkCreateAndroidSurfaceKHR vkCreateAndroidSurfaceKHR;
#endif
#ifdef VK_USE_PLATFORM_WIN32_KHR
PFN_vkCreateWin32SurfaceKHR vkCreateWin32SurfaceKHR;
PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR vkGetPhysicalDeviceWin32PresentationSupportKHR;
#endif
PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT;
PFN_vkDestroyDebugReportCallbackEXT vkDestroyDebugReportCallbackEXT;
PFN_vkDebugReportMessageEXT vkDebugReportMessageEXT;
@@ -0,0 +1,236 @@
// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// This file is generated.
#ifndef VULKAN_WRAPPER_H
#define VULKAN_WRAPPER_H
#define VK_NO_PROTOTYPES 1
#include <vulkan/vulkan.h>
/* Initialize the Vulkan function pointer variables declared in this header.
* Returns 0 if vulkan is not available, non-zero if it is available.
*/
int InitVulkan(void);
// VK_core
extern PFN_vkCreateInstance vkCreateInstance;
extern PFN_vkDestroyInstance vkDestroyInstance;
extern PFN_vkEnumeratePhysicalDevices vkEnumeratePhysicalDevices;
extern PFN_vkGetPhysicalDeviceFeatures vkGetPhysicalDeviceFeatures;
extern PFN_vkGetPhysicalDeviceFormatProperties vkGetPhysicalDeviceFormatProperties;
extern PFN_vkGetPhysicalDeviceImageFormatProperties vkGetPhysicalDeviceImageFormatProperties;
extern PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties;
extern PFN_vkGetPhysicalDeviceQueueFamilyProperties vkGetPhysicalDeviceQueueFamilyProperties;
extern PFN_vkGetPhysicalDeviceMemoryProperties vkGetPhysicalDeviceMemoryProperties;
extern PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr;
extern PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr;
extern PFN_vkCreateDevice vkCreateDevice;
extern PFN_vkDestroyDevice vkDestroyDevice;
extern PFN_vkEnumerateInstanceExtensionProperties vkEnumerateInstanceExtensionProperties;
extern PFN_vkEnumerateDeviceExtensionProperties vkEnumerateDeviceExtensionProperties;
extern PFN_vkEnumerateInstanceLayerProperties vkEnumerateInstanceLayerProperties;
extern PFN_vkEnumerateDeviceLayerProperties vkEnumerateDeviceLayerProperties;
extern PFN_vkGetDeviceQueue vkGetDeviceQueue;
extern PFN_vkQueueSubmit vkQueueSubmit;
extern PFN_vkQueueWaitIdle vkQueueWaitIdle;
extern PFN_vkDeviceWaitIdle vkDeviceWaitIdle;
extern PFN_vkAllocateMemory vkAllocateMemory;
extern PFN_vkFreeMemory vkFreeMemory;
extern PFN_vkMapMemory vkMapMemory;
extern PFN_vkUnmapMemory vkUnmapMemory;
extern PFN_vkFlushMappedMemoryRanges vkFlushMappedMemoryRanges;
extern PFN_vkInvalidateMappedMemoryRanges vkInvalidateMappedMemoryRanges;
extern PFN_vkGetDeviceMemoryCommitment vkGetDeviceMemoryCommitment;
extern PFN_vkBindBufferMemory vkBindBufferMemory;
extern PFN_vkBindImageMemory vkBindImageMemory;
extern PFN_vkGetBufferMemoryRequirements vkGetBufferMemoryRequirements;
extern PFN_vkGetImageMemoryRequirements vkGetImageMemoryRequirements;
extern PFN_vkGetImageSparseMemoryRequirements vkGetImageSparseMemoryRequirements;
extern PFN_vkGetPhysicalDeviceSparseImageFormatProperties vkGetPhysicalDeviceSparseImageFormatProperties;
extern PFN_vkQueueBindSparse vkQueueBindSparse;
extern PFN_vkCreateFence vkCreateFence;
extern PFN_vkDestroyFence vkDestroyFence;
extern PFN_vkResetFences vkResetFences;
extern PFN_vkGetFenceStatus vkGetFenceStatus;
extern PFN_vkWaitForFences vkWaitForFences;
extern PFN_vkCreateSemaphore vkCreateSemaphore;
extern PFN_vkDestroySemaphore vkDestroySemaphore;
extern PFN_vkCreateEvent vkCreateEvent;
extern PFN_vkDestroyEvent vkDestroyEvent;
extern PFN_vkGetEventStatus vkGetEventStatus;
extern PFN_vkSetEvent vkSetEvent;
extern PFN_vkResetEvent vkResetEvent;
extern PFN_vkCreateQueryPool vkCreateQueryPool;
extern PFN_vkDestroyQueryPool vkDestroyQueryPool;
extern PFN_vkGetQueryPoolResults vkGetQueryPoolResults;
extern PFN_vkCreateBuffer vkCreateBuffer;
extern PFN_vkDestroyBuffer vkDestroyBuffer;
extern PFN_vkCreateBufferView vkCreateBufferView;
extern PFN_vkDestroyBufferView vkDestroyBufferView;
extern PFN_vkCreateImage vkCreateImage;
extern PFN_vkDestroyImage vkDestroyImage;
extern PFN_vkGetImageSubresourceLayout vkGetImageSubresourceLayout;
extern PFN_vkCreateImageView vkCreateImageView;
extern PFN_vkDestroyImageView vkDestroyImageView;
extern PFN_vkCreateShaderModule vkCreateShaderModule;
extern PFN_vkDestroyShaderModule vkDestroyShaderModule;
extern PFN_vkCreatePipelineCache vkCreatePipelineCache;
extern PFN_vkDestroyPipelineCache vkDestroyPipelineCache;
extern PFN_vkGetPipelineCacheData vkGetPipelineCacheData;
extern PFN_vkMergePipelineCaches vkMergePipelineCaches;
extern PFN_vkCreateGraphicsPipelines vkCreateGraphicsPipelines;
extern PFN_vkCreateComputePipelines vkCreateComputePipelines;
extern PFN_vkDestroyPipeline vkDestroyPipeline;
extern PFN_vkCreatePipelineLayout vkCreatePipelineLayout;
extern PFN_vkDestroyPipelineLayout vkDestroyPipelineLayout;
extern PFN_vkCreateSampler vkCreateSampler;
extern PFN_vkDestroySampler vkDestroySampler;
extern PFN_vkCreateDescriptorSetLayout vkCreateDescriptorSetLayout;
extern PFN_vkDestroyDescriptorSetLayout vkDestroyDescriptorSetLayout;
extern PFN_vkCreateDescriptorPool vkCreateDescriptorPool;
extern PFN_vkDestroyDescriptorPool vkDestroyDescriptorPool;
extern PFN_vkResetDescriptorPool vkResetDescriptorPool;
extern PFN_vkAllocateDescriptorSets vkAllocateDescriptorSets;
extern PFN_vkFreeDescriptorSets vkFreeDescriptorSets;
extern PFN_vkUpdateDescriptorSets vkUpdateDescriptorSets;
extern PFN_vkCreateFramebuffer vkCreateFramebuffer;
extern PFN_vkDestroyFramebuffer vkDestroyFramebuffer;
extern PFN_vkCreateRenderPass vkCreateRenderPass;
extern PFN_vkDestroyRenderPass vkDestroyRenderPass;
extern PFN_vkGetRenderAreaGranularity vkGetRenderAreaGranularity;
extern PFN_vkCreateCommandPool vkCreateCommandPool;
extern PFN_vkDestroyCommandPool vkDestroyCommandPool;
extern PFN_vkResetCommandPool vkResetCommandPool;
extern PFN_vkAllocateCommandBuffers vkAllocateCommandBuffers;
extern PFN_vkFreeCommandBuffers vkFreeCommandBuffers;
extern PFN_vkBeginCommandBuffer vkBeginCommandBuffer;
extern PFN_vkEndCommandBuffer vkEndCommandBuffer;
extern PFN_vkResetCommandBuffer vkResetCommandBuffer;
extern PFN_vkCmdBindPipeline vkCmdBindPipeline;
extern PFN_vkCmdSetViewport vkCmdSetViewport;
extern PFN_vkCmdSetScissor vkCmdSetScissor;
extern PFN_vkCmdSetLineWidth vkCmdSetLineWidth;
extern PFN_vkCmdSetDepthBias vkCmdSetDepthBias;
extern PFN_vkCmdSetBlendConstants vkCmdSetBlendConstants;
extern PFN_vkCmdSetDepthBounds vkCmdSetDepthBounds;
extern PFN_vkCmdSetStencilCompareMask vkCmdSetStencilCompareMask;
extern PFN_vkCmdSetStencilWriteMask vkCmdSetStencilWriteMask;
extern PFN_vkCmdSetStencilReference vkCmdSetStencilReference;
extern PFN_vkCmdBindDescriptorSets vkCmdBindDescriptorSets;
extern PFN_vkCmdBindIndexBuffer vkCmdBindIndexBuffer;
extern PFN_vkCmdBindVertexBuffers vkCmdBindVertexBuffers;
extern PFN_vkCmdDraw vkCmdDraw;
extern PFN_vkCmdDrawIndexed vkCmdDrawIndexed;
extern PFN_vkCmdDrawIndirect vkCmdDrawIndirect;
extern PFN_vkCmdDrawIndexedIndirect vkCmdDrawIndexedIndirect;
extern PFN_vkCmdDispatch vkCmdDispatch;
extern PFN_vkCmdDispatchIndirect vkCmdDispatchIndirect;
extern PFN_vkCmdCopyBuffer vkCmdCopyBuffer;
extern PFN_vkCmdCopyImage vkCmdCopyImage;
extern PFN_vkCmdBlitImage vkCmdBlitImage;
extern PFN_vkCmdCopyBufferToImage vkCmdCopyBufferToImage;
extern PFN_vkCmdCopyImageToBuffer vkCmdCopyImageToBuffer;
extern PFN_vkCmdUpdateBuffer vkCmdUpdateBuffer;
extern PFN_vkCmdFillBuffer vkCmdFillBuffer;
extern PFN_vkCmdClearColorImage vkCmdClearColorImage;
extern PFN_vkCmdClearDepthStencilImage vkCmdClearDepthStencilImage;
extern PFN_vkCmdClearAttachments vkCmdClearAttachments;
extern PFN_vkCmdResolveImage vkCmdResolveImage;
extern PFN_vkCmdSetEvent vkCmdSetEvent;
extern PFN_vkCmdResetEvent vkCmdResetEvent;
extern PFN_vkCmdWaitEvents vkCmdWaitEvents;
extern PFN_vkCmdPipelineBarrier vkCmdPipelineBarrier;
extern PFN_vkCmdBeginQuery vkCmdBeginQuery;
extern PFN_vkCmdEndQuery vkCmdEndQuery;
extern PFN_vkCmdResetQueryPool vkCmdResetQueryPool;
extern PFN_vkCmdWriteTimestamp vkCmdWriteTimestamp;
extern PFN_vkCmdCopyQueryPoolResults vkCmdCopyQueryPoolResults;
extern PFN_vkCmdPushConstants vkCmdPushConstants;
extern PFN_vkCmdBeginRenderPass vkCmdBeginRenderPass;
extern PFN_vkCmdNextSubpass vkCmdNextSubpass;
extern PFN_vkCmdEndRenderPass vkCmdEndRenderPass;
extern PFN_vkCmdExecuteCommands vkCmdExecuteCommands;
// VK_KHR_surface
extern PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR;
extern PFN_vkGetPhysicalDeviceSurfaceSupportKHR vkGetPhysicalDeviceSurfaceSupportKHR;
extern PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vkGetPhysicalDeviceSurfaceCapabilitiesKHR;
extern PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vkGetPhysicalDeviceSurfaceFormatsKHR;
extern PFN_vkGetPhysicalDeviceSurfacePresentModesKHR vkGetPhysicalDeviceSurfacePresentModesKHR;
// VK_KHR_swapchain
extern PFN_vkCreateSwapchainKHR vkCreateSwapchainKHR;
extern PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR;
extern PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR;
extern PFN_vkAcquireNextImageKHR vkAcquireNextImageKHR;
extern PFN_vkQueuePresentKHR vkQueuePresentKHR;
// VK_KHR_display
extern PFN_vkGetPhysicalDeviceDisplayPropertiesKHR vkGetPhysicalDeviceDisplayPropertiesKHR;
extern PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR vkGetPhysicalDeviceDisplayPlanePropertiesKHR;
extern PFN_vkGetDisplayPlaneSupportedDisplaysKHR vkGetDisplayPlaneSupportedDisplaysKHR;
extern PFN_vkGetDisplayModePropertiesKHR vkGetDisplayModePropertiesKHR;
extern PFN_vkCreateDisplayModeKHR vkCreateDisplayModeKHR;
extern PFN_vkGetDisplayPlaneCapabilitiesKHR vkGetDisplayPlaneCapabilitiesKHR;
extern PFN_vkCreateDisplayPlaneSurfaceKHR vkCreateDisplayPlaneSurfaceKHR;
// VK_KHR_display_swapchain
extern PFN_vkCreateSharedSwapchainsKHR vkCreateSharedSwapchainsKHR;
#ifdef VK_USE_PLATFORM_XLIB_KHR
// VK_KHR_xlib_surface
extern PFN_vkCreateXlibSurfaceKHR vkCreateXlibSurfaceKHR;
extern PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR vkGetPhysicalDeviceXlibPresentationSupportKHR;
#endif
#ifdef VK_USE_PLATFORM_XCB_KHR
// VK_KHR_xcb_surface
extern PFN_vkCreateXcbSurfaceKHR vkCreateXcbSurfaceKHR;
extern PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR vkGetPhysicalDeviceXcbPresentationSupportKHR;
#endif
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
// VK_KHR_wayland_surface
extern PFN_vkCreateWaylandSurfaceKHR vkCreateWaylandSurfaceKHR;
extern PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR vkGetPhysicalDeviceWaylandPresentationSupportKHR;
#endif
#ifdef VK_USE_PLATFORM_MIR_KHR
// VK_KHR_mir_surface
extern PFN_vkCreateMirSurfaceKHR vkCreateMirSurfaceKHR;
extern PFN_vkGetPhysicalDeviceMirPresentationSupportKHR vkGetPhysicalDeviceMirPresentationSupportKHR;
#endif
#ifdef VK_USE_PLATFORM_ANDROID_KHR
// VK_KHR_android_surface
extern PFN_vkCreateAndroidSurfaceKHR vkCreateAndroidSurfaceKHR;
#endif
#ifdef VK_USE_PLATFORM_WIN32_KHR
// VK_KHR_win32_surface
extern PFN_vkCreateWin32SurfaceKHR vkCreateWin32SurfaceKHR;
extern PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR vkGetPhysicalDeviceWin32PresentationSupportKHR;
#endif
#ifdef USE_DEBUG_EXTENTIONS
#include <vulkan/vk_sdk_platform.h>
// VK_EXT_debug_report
extern PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT;
extern PFN_vkDestroyDebugReportCallbackEXT vkDestroyDebugReportCallbackEXT;
extern PFN_vkDebugReportMessageEXT vkDebugReportMessageEXT;
#endif
#endif // VULKAN_WRAPPER_H
Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

@@ -0,0 +1,7 @@
package org.kenjinx.android
enum class BackendThreading {
Auto,
Off,
On
}
@@ -0,0 +1,9 @@
package org.kenjinx.android
import androidx.activity.ComponentActivity
abstract class BaseActivity : ComponentActivity() {
companion object {
val crashHandler = CrashHandler()
}
}

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