forked from MeloNX/MeloNX
Compare commits
152 Commits
libryujinx
...
XC-ios-ht
Author | SHA1 | Date | |
---|---|---|---|
|
27aaea0d68 | ||
|
994f6c0732 | ||
|
c5131d9850 | ||
|
09a757c445 | ||
|
71551adf2d | ||
|
d13dc50a10 | ||
|
2901f462aa | ||
|
160a58e127 | ||
|
9eae1ab594 | ||
|
d2e406fa56 | ||
|
054cb50b22 | ||
|
05b131b33f | ||
|
ccf89aa324 | ||
|
ace6616067 | ||
|
0968360e08 | ||
|
81941f9e9f | ||
|
6e7e5dbfca | ||
|
e76e927b28 | ||
|
b6bad055a8 | ||
|
2fbe6eb9da | ||
|
86c93fe163 | ||
|
2e6e4eb2a0 | ||
|
438c1a896f | ||
|
c5736f9b15 | ||
|
1662bcbc96 | ||
|
63427eb744 | ||
|
06f3c6d20e | ||
|
3e657d7229 | ||
|
ec16e150f6 | ||
|
aca5ee8305 | ||
|
a61e2a3992 | ||
1735216de6 | |||
20547bc412 | |||
|
ed027f1649 | ||
|
e02037d9c3 | ||
|
e74ab3a602 | ||
|
7025c32c4a | ||
|
de19cc29d8 | ||
|
f55d596688 | ||
|
209d0f1a15 | ||
|
db86daef39 | ||
|
9e09cb5767 | ||
b089fda22d | |||
|
94dc643f26 | ||
|
e81ee8f8bf | ||
|
fdbcc483b3 | ||
|
5163737886 | ||
|
6a45d469db | ||
|
658bdd7bec | ||
|
d64ef5eed9 | ||
|
11c3d31764 | ||
|
61344e731e | ||
|
ddcb7a8f77 | ||
|
531446a6ce | ||
|
249e7104f6 | ||
|
3e0c86b047 | ||
|
51a2dfd27d | ||
|
31b10799a3 | ||
|
11ec203e9f | ||
|
de6c0a43b0 | ||
|
663ec73028 | ||
|
aed7a06f0d | ||
|
e0785922d5 | ||
|
abcad02f3e | ||
a5a543f06c | |||
|
c000541be1 | ||
|
4149c329ea | ||
|
300efe5f55 | ||
|
bb4e7314a5 | ||
|
73f14cf59c | ||
|
464f14f143 | ||
|
860d4d363d | ||
|
c419381e63 | ||
|
9a86b2000a | ||
|
b2424a9652 | ||
|
1d70417281 | ||
|
95da853b7f | ||
|
a14aadf878 | ||
|
45e2785e93 | ||
|
d3031752be | ||
|
c4c71a4cb6 | ||
|
8e229fe454 | ||
|
e02927cadb | ||
|
098467f3f3 | ||
|
8ebde3f921 | ||
|
ab28f9a24a | ||
|
674824184a | ||
1bc0d3dba9 | |||
|
0a3b4f71a9 | ||
|
b9163f9fde | ||
|
05d1730c17 | ||
|
e170ed01ad | ||
|
8d4f004a59 | ||
|
437f7f8c04 | ||
2ba59b2ce9 | |||
|
d9099429f2 | ||
|
bea7528eb6 | ||
|
05880cc8a5 | ||
|
10e45533e1 | ||
|
b86e3301bb | ||
|
165bb0c5d2 | ||
|
a1cb1dfdc9 | ||
|
c97686924b | ||
|
10ee46744b | ||
|
f16abe6dac | ||
|
87b314a7ca | ||
|
092af4585c | ||
|
e9abc7e59e | ||
|
19d6bddc25 | ||
|
57949d03e5 | ||
|
3cd42f99aa | ||
|
87ba82691c | ||
|
60442064e4 | ||
|
7ac6b8e742 | ||
|
6334c3f90c | ||
|
e9ab106f8f | ||
|
2bbf829a09 | ||
|
c47ce6f697 | ||
|
942efbb6d6 | ||
|
afcfba498c | ||
|
df92f2052a | ||
|
85f83592c7 | ||
|
2feecd05a3 | ||
|
98c16ed3b0 | ||
|
133f7d10de | ||
|
cabf434c5f | ||
|
f9ed8f860e | ||
|
5cc0b317f9 | ||
|
acc22c769d | ||
|
94bd78f48a | ||
|
689eadaece | ||
|
339d9ca83d | ||
|
1251f03575 | ||
|
5b6893b1ed | ||
|
cee2e2f600 | ||
|
ffdb90a1f4 | ||
|
59d6ceb9ee | ||
|
259f5da0fb | ||
|
ab7ebecfc8 | ||
|
6b2f1b7d4f | ||
|
5bb1c40e99 | ||
|
3ba86e1fa9 | ||
|
84dab5f717 | ||
|
344817cb54 | ||
|
3f57753af0 | ||
|
38b8b44c60 | ||
|
6a28c20862 | ||
|
7c0182ec8b | ||
|
c0e12fda94 | ||
|
f4c2343edd | ||
|
a09160abfd | ||
|
184db0430c |
3
.gitignore
vendored
3
.gitignore
vendored
@ -10,6 +10,8 @@
|
||||
|
||||
# Build results
|
||||
|
||||
dotnet.xcconfig
|
||||
|
||||
[Dd]ebug/
|
||||
[Rr]elease/
|
||||
x64/
|
||||
@ -173,3 +175,4 @@ PublishProfiles/
|
||||
|
||||
# Glade backup files
|
||||
*.glade~
|
||||
src/MeloNX/MeloNX/Dependencies/Dynamic Libraries/Ryujinx.Headless.SDL2.dylib
|
||||
|
33
Compile.md
Normal file
33
Compile.md
Normal file
@ -0,0 +1,33 @@
|
||||
# How to compile MeloNX using macOS
|
||||
|
||||
## Prerequisites
|
||||
- [.NET 8.0](<https://dotnet.microsoft.com/en-us/download/dotnet/8.0>)
|
||||
- A computer with macOS
|
||||
|
||||
## Compiling
|
||||
1. Clone the Git Repo and build Ryujinx
|
||||
```
|
||||
git clone https://github.com/melonx-emu/melonx/tree/XC-ios-ht
|
||||
cd melonx
|
||||
./compile.sh -x
|
||||
```
|
||||
|
||||
2. Open the Xcode project, stored at MeloNX/src/MeloNX
|
||||
|
||||
3. Make sure `Ryujinx.SDL2.Headless.dylib` is set to `Embed & Sign` in the General settings for the Xcode project
|
||||
|
||||
4. Signing & Capabilities
|
||||
Change your 'Team' to your Developer Account (free or paid) and change Bundle Identifier to
|
||||
`com.*your name*.MeloNX`
|
||||
|
||||
6. Build and Run
|
||||
`CMD+R`
|
||||
|
||||
7. Check the [post-setup guide](<https://github.com/melonx-emu/melonx/tree/XC-ios-ht/postsetup.md>)
|
||||
|
||||
## If you don't have a paid developer account
|
||||
Make sure these entitlements are removed if you don't have a paid Apple Developer account
|
||||
```
|
||||
Extended Virtual Addressing
|
||||
Increased Debugging Memory Limit
|
||||
```
|
@ -33,15 +33,15 @@
|
||||
<PackageVersion Include="OpenTK.Windowing.GraphicsLibraryFramework" Version="4.8.1" />
|
||||
<PackageVersion Include="Ryujinx.Audio.OpenAL.Dependencies" Version="1.21.0.1" />
|
||||
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.1-build13" />
|
||||
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
|
||||
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.3" />
|
||||
<PackageVersion Include="Ryujinx.GtkSharp" Version="3.24.24.59-ryujinx" />
|
||||
<PackageVersion Include="Ryujinx.SDL2-CS" Version="2.28.1-build28" />
|
||||
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
|
||||
<PackageVersion Include="shaderc.net" Version="0.1.0" />
|
||||
<PackageVersion Include="SharpZipLib" Version="1.4.2" />
|
||||
<PackageVersion Include="Silk.NET.Vulkan" Version="2.16.0" />
|
||||
<PackageVersion Include="Silk.NET.Vulkan.Extensions.EXT" Version="2.16.0" />
|
||||
<PackageVersion Include="Silk.NET.Vulkan.Extensions.KHR" Version="2.16.0" />
|
||||
<PackageVersion Include="Silk.NET.Vulkan" Version="2.22.0" />
|
||||
<PackageVersion Include="Silk.NET.Vulkan.Extensions.EXT" Version="2.22.0" />
|
||||
<PackageVersion Include="Silk.NET.Vulkan.Extensions.KHR" Version="2.22.0" />
|
||||
<PackageVersion Include="SixLabors.ImageSharp" Version="1.0.4" />
|
||||
<PackageVersion Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta11" />
|
||||
<PackageVersion Include="SPB" Version="0.0.4-build28" />
|
||||
|
145
README.md
145
README.md
@ -1,145 +1,22 @@
|
||||
|
||||
<h1 align="center">
|
||||
<br>
|
||||
<a href="https://ryujinx.org/"><img src="https://i.imgur.com/WcCj6Rt.png" alt="Ryujinx" width="150"></a>
|
||||
<br>
|
||||
<b>Ryujinx</b>
|
||||
<br>
|
||||
<sub><sup><b>(REE-YOU-JINX)</b></sup></sub>
|
||||
<br>
|
||||
|
||||
</h1>
|
||||
|
||||
<p align="center">
|
||||
Ryujinx is an open-source Nintendo Switch emulator, created by gdkchan, written in C#.
|
||||
This emulator aims at providing excellent accuracy and performance, a user-friendly interface and consistent builds.
|
||||
It was written from scratch and development on the project began in September 2017. Ryujinx is available on Github under the <a href="https://github.com/Ryujinx/Ryujinx/blob/master/LICENSE.txt" target="_blank">MIT license</a>. <br />
|
||||
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://github.com/Ryujinx/Ryujinx/actions/workflows/release.yml">
|
||||
<img src="https://github.com/Ryujinx/Ryujinx/actions/workflows/release.yml/badge.svg"
|
||||
alt="">
|
||||
<a href="https://github.com/MeloNX-Emu/MeloNX">
|
||||
<img src="https://github.com/MeloNX-Emu/melonx-emu.github.io/blob/main/favicon.png?raw=true" alt="MeloNX Logo" width="120">
|
||||
</a>
|
||||
<a href="https://crwd.in/ryujinx">
|
||||
<img src="https://badges.crowdin.net/ryujinx/localized.svg"
|
||||
alt="">
|
||||
</a>
|
||||
<a href="https://discord.com/invite/VkQYXAZ">
|
||||
<img src="https://img.shields.io/discord/410208534861447168?color=5865F2&label=Ryujinx&logo=discord&logoColor=white"
|
||||
alt="Discord">
|
||||
</a>
|
||||
<br>
|
||||
<br>
|
||||
<img src="https://raw.githubusercontent.com/Ryujinx/Ryujinx-Website/master/public/assets/images/shell.png">
|
||||
</p>
|
||||
|
||||
<h5 align="center">
|
||||
<p align="center">
|
||||
MeloNX enables Nintendo Switch game emulation on iOS using the Ryujinx iOS code base.
|
||||
</p>
|
||||
|
||||
</h5>
|
||||
<p align="center">
|
||||
MeloNX is an iOS Nintendo Switch emulator based on Ryujinx, written primarily in C#. Designed to bring accurate performance and a user-friendly interface to iOS, MeloNX makes Switch games accessible on Apple devices.
|
||||
Developed from the ground up, MeloNX is open-source and available on Github under the <a href="https://github.com/MeloNX-Emu/MeloNX/blob/master/LICENSE.txt" target="_blank">MIT license</a>. <br
|
||||
</p>
|
||||
|
||||
## Compatibility
|
||||
|
||||
As of April 2023, Ryujinx has been tested on approximately 4,050 titles; over 4,000 boot past menus and into gameplay, with roughly 3,400 of those being considered playable.
|
||||
You can check out the compatibility list [here](https://github.com/Ryujinx/Ryujinx-Games-List/issues). Anyone is free to submit a new game test or update an existing game test entry; simply follow the new issue template and testing guidelines, or post as a reply to the applicable game issue. Use the search function to see if a game has been tested already!
|
||||
MeloNX works on iPhone X and later and iPad 7th Gen and later. A lot of games work.
|
||||
|
||||
## Usage
|
||||
|
||||
To run this emulator, your PC must be equipped with at least 8GiB of RAM; failing to meet this requirement may result in a poor gameplay experience or unexpected crashes.
|
||||
|
||||
See our [Setup & Configuration Guide](https://github.com/Ryujinx/Ryujinx/wiki/Ryujinx-Setup-&-Configuration-Guide) on how to set up the emulator.
|
||||
|
||||
For our Local Wireless and LAN builds, see our [Multiplayer: Local Play/Local Wireless Guide
|
||||
](https://github.com/Ryujinx/Ryujinx/wiki/Multiplayer-(LDN-Local-Wireless)-Guide).
|
||||
|
||||
Avalonia UI comes with translations for various languages. See [Crowdin](https://crwd.in/ryujinx) for more information.
|
||||
|
||||
## Latest build
|
||||
|
||||
These builds are compiled automatically for each commit on the master branch. While we strive to ensure optimal stability and performance prior to pushing an update, our automated builds **may be unstable or completely broken.**
|
||||
|
||||
If you want to see details on updates to the emulator, you can visit our [Changelog](https://github.com/Ryujinx/Ryujinx/wiki/Changelog).
|
||||
|
||||
The latest automatic build for Windows, macOS, and Linux can be found on the [Official Website](https://ryujinx.org/download).
|
||||
|
||||
|
||||
## Building
|
||||
|
||||
If you wish to build the emulator yourself, follow these steps:
|
||||
|
||||
### Step 1
|
||||
Install the X64 version of [.NET 8.0 (or higher) SDK](https://dotnet.microsoft.com/download/dotnet/8.0).
|
||||
|
||||
### Step 2
|
||||
Either use `git clone https://github.com/Ryujinx/Ryujinx` on the command line to clone the repository or use Code --> Download zip button to get the files.
|
||||
|
||||
### Step 3
|
||||
|
||||
To build Ryujinx, open a command prompt inside the project directory. You can quickly access it on Windows by holding shift in File Explorer, then right clicking and selecting `Open command window here`. Then type the following command:
|
||||
`dotnet build -c Release -o build`
|
||||
the built files will be found in the newly created build directory.
|
||||
|
||||
Ryujinx system files are stored in the `Ryujinx` folder. This folder is located in the user folder, which can be accessed by clicking `Open Ryujinx Folder` under the File menu in the GUI.
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
- **Audio**
|
||||
|
||||
Audio output is entirely supported, audio input (microphone) isn't supported. We use C# wrappers for [OpenAL](https://openal-soft.org/), and [SDL2](https://www.libsdl.org/) & [libsoundio](http://libsound.io/) as fallbacks.
|
||||
|
||||
- **CPU**
|
||||
|
||||
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, including partial 32-bit support. It translates the ARM code to a custom IR, performs a few optimizations, and turns that into x86 code.
|
||||
There are three memory manager options available depending on the user's preference, leveraging both software-based (slower) and host-mapped modes (much faster). The fastest option (host, unchecked) is set by default.
|
||||
Ryujinx also features an optional Profiled Persistent Translation Cache, which essentially caches translated functions so that they do not need to be translated every time the game loads. The net result is a significant reduction in load times (the amount of time between launching a game and arriving at the title screen) for nearly every game. NOTE: this feature is enabled by default in the Options menu > System tab. You must launch the game at least twice to the title screen or beyond before performance improvements are unlocked on the third launch! These improvements are permanent and do not require any extra launches going forward.
|
||||
|
||||
- **GPU**
|
||||
|
||||
The GPU emulator emulates the Switch's Maxwell GPU using either the OpenGL (version 4.5 minimum), Vulkan, or Metal (via MoltenVK) APIs through a custom build of OpenTK or Silk.NET respectively. There are currently six graphics enhancements available to the end user in Ryujinx: Disk Shader Caching, Resolution Scaling, Anti-Aliasing, Scaling Filters (including FSR), Anisotropic Filtering and Aspect Ratio Adjustment. These enhancements can be adjusted or toggled as desired in the GUI.
|
||||
|
||||
- **Input**
|
||||
|
||||
We currently have support for keyboard, mouse, touch input, JoyCon input support, and nearly all controllers. Motion controls are natively supported in most cases; for dual-JoyCon motion support, DS4Windows or BetterJoy are currently required.
|
||||
In all scenarios, you can set up everything inside the input configuration menu.
|
||||
|
||||
- **DLC & Modifications**
|
||||
|
||||
Ryujinx is able to manage add-on content/downloadable content through the GUI. Mods (romfs, exefs, and runtime mods such as cheats) are also supported; the GUI contains a shortcut to open the respective mods folder for a particular game.
|
||||
|
||||
- **Configuration**
|
||||
|
||||
The emulator has settings for enabling or disabling some logging, remapping controllers, and more. You can configure all of them through the graphical interface or manually through the config file, `Config.json`, found in the user folder which can be accessed by clicking `Open Ryujinx Folder` under the File menu in the GUI.
|
||||
|
||||
|
||||
## Contact
|
||||
|
||||
If you have contributions, suggestions, need emulator support or just want to get in touch with the team, join our [Discord server](https://discord.com/invite/Ryujinx). You may also review our [FAQ](https://github.com/Ryujinx/Ryujinx/wiki/Frequently-Asked-Questions).
|
||||
|
||||
## Donations
|
||||
|
||||
If you'd like to support the project financially, Ryujinx has an active Patreon campaign.
|
||||
|
||||
<a href="https://www.patreon.com/ryujinx">
|
||||
<img src="https://images.squarespace-cdn.com/content/v1/560c1d39e4b0b4fae0c9cf2a/1567548955044-WVD994WZP76EWF15T0L3/Patreon+Button.png?format=500w" width="150">
|
||||
</a>
|
||||
|
||||
All developers working on the project do so in their free time, but the project has several expenses:
|
||||
* Hackable Nintendo Switch consoles to reverse-engineer the hardware
|
||||
* Additional computer hardware for testing purposes (e.g. GPUs to diagnose graphical bugs, etc.)
|
||||
* Licenses for various software development tools (e.g. Jetbrains, IDA)
|
||||
* Web hosting and infrastructure maintenance (e.g. LDN servers)
|
||||
|
||||
All funds received through Patreon are considered a donation to support the project. Patrons receive early access to progress reports and exclusive access to developer interviews.
|
||||
|
||||
## License
|
||||
|
||||
This software is licensed under the terms of the <a href="https://github.com/Ryujinx/Ryujinx/blob/master/LICENSE.txt" target="_blank">MIT license.</a></i><br />
|
||||
This project makes use of code authored by the libvpx project, licensed under BSD and the ffmpeg project, licensed under LGPLv3.
|
||||
See [LICENSE.txt](LICENSE.txt) and [THIRDPARTY.md](distribution/legal/THIRDPARTY.md) for more details.
|
||||
## Credits
|
||||
|
||||
- [LibHac](https://github.com/Thealexbarney/LibHac) is used for our file-system.
|
||||
- [AmiiboAPI](https://www.amiiboapi.com) is used in our Amiibo emulation.
|
||||
- [ldn_mitm](https://github.com/spacemeowx2/ldn_mitm) is used for one of our available multiplayer modes.
|
||||
- [ShellLink](https://github.com/securifybv/ShellLink) is used for Windows shortcut generation.
|
||||
To run MeloNX on your iOS device, at least 4GB of RAM is recommended to ensure stability. For full instructions, refer to our [Setup Guide](https://github.com/MeloNX-Emu/MeloNX/wiki/Setup-Guide).
|
||||
|
18
compile.sh
Executable file
18
compile.sh
Executable file
@ -0,0 +1,18 @@
|
||||
#!/bin/bash
|
||||
|
||||
|
||||
# Define the destination directory (hardcoded)
|
||||
DESTINATION_DIR="src/MeloNX/Dependencies/Dynamic\ Libraries/Ryujinx.Headless.SDL2.dylib"
|
||||
|
||||
# Restore the project
|
||||
dotnet restore
|
||||
|
||||
# Build the project with the specified version
|
||||
dotnet build -c Release
|
||||
|
||||
# Publish the project with the specified runtime and settings
|
||||
dotnet publish -c Release -r ios-arm64 -p:ExtraDefineConstants=DISABLE_UPDATER src/Ryujinx.Headless.SDL2 --self-contained true
|
||||
|
||||
# Move the published .dylib to the specified location
|
||||
mv src/Ryujinx.Headless.SDL2/bin/Release/net8.0/ios-arm64/native/Ryujinx.Headless.SDL2.dylib src/MeloNX/MeloNX/Dependencies/Dynamic\ Libraries/Ryujinx.Headless.SDL2.dylib
|
||||
|
@ -20,7 +20,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
LinuxFeatureInfoHwCap2 = (LinuxFeatureFlagsHwCap2)getauxval(AT_HWCAP2);
|
||||
}
|
||||
|
||||
if (OperatingSystem.IsMacOS())
|
||||
if (OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
|
||||
{
|
||||
for (int i = 0; i < _sysctlNames.Length; i++)
|
||||
{
|
||||
@ -130,6 +130,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
private static unsafe partial int sysctlbyname([MarshalAs(UnmanagedType.LPStr)] string name, out int oldValue, ref ulong oldSize, IntPtr newValue, ulong newValueSize);
|
||||
|
||||
[SupportedOSPlatform("macos")]
|
||||
[SupportedOSPlatform("ios")]
|
||||
private static bool CheckSysctlName(string name)
|
||||
{
|
||||
ulong size = sizeof(int);
|
||||
|
@ -58,9 +58,9 @@ namespace ARMeilleure.CodeGen
|
||||
/// <typeparam name="T">Type of delegate</typeparam>
|
||||
/// <param name="codePointer">Pointer to the function code in memory</param>
|
||||
/// <returns>A delegate of type <typeparamref name="T"/> pointing to the mapped function</returns>
|
||||
public T MapWithPointer<T>(out IntPtr codePointer)
|
||||
public T MapWithPointer<T>(out IntPtr codePointer, bool deferProtect = false)
|
||||
{
|
||||
codePointer = JitCache.Map(this);
|
||||
codePointer = JitCache.Map(this, deferProtect);
|
||||
|
||||
return Marshal.GetDelegateForFunctionPointer<T>(codePointer);
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ namespace ARMeilleure.Common
|
||||
/// Represents a table of guest address to a value.
|
||||
/// </summary>
|
||||
/// <typeparam name="TEntry">Type of the value</typeparam>
|
||||
unsafe class AddressTable<TEntry> : IDisposable where TEntry : unmanaged
|
||||
public unsafe class AddressTable<TEntry> : IDisposable where TEntry : unmanaged
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a level in an <see cref="AddressTable{TEntry}"/>.
|
||||
|
@ -157,7 +157,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
context.Copy(temp, value);
|
||||
|
||||
if (!context.Memory.Type.IsHostMapped())
|
||||
if (!context.Memory.Type.IsHostMappedOrTracked())
|
||||
{
|
||||
context.Branch(lblEnd);
|
||||
|
||||
@ -198,7 +198,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
SetInt(context, rt, value);
|
||||
|
||||
if (!context.Memory.Type.IsHostMapped())
|
||||
if (!context.Memory.Type.IsHostMappedOrTracked())
|
||||
{
|
||||
context.Branch(lblEnd);
|
||||
|
||||
@ -265,7 +265,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
context.Copy(GetVec(rt), value);
|
||||
|
||||
if (!context.Memory.Type.IsHostMapped())
|
||||
if (!context.Memory.Type.IsHostMappedOrTracked())
|
||||
{
|
||||
context.Branch(lblEnd);
|
||||
|
||||
@ -312,7 +312,7 @@ namespace ARMeilleure.Instructions
|
||||
break;
|
||||
}
|
||||
|
||||
if (!context.Memory.Type.IsHostMapped())
|
||||
if (!context.Memory.Type.IsHostMappedOrTracked())
|
||||
{
|
||||
context.Branch(lblEnd);
|
||||
|
||||
@ -385,7 +385,7 @@ namespace ARMeilleure.Instructions
|
||||
break;
|
||||
}
|
||||
|
||||
if (!context.Memory.Type.IsHostMapped())
|
||||
if (!context.Memory.Type.IsHostMappedOrTracked())
|
||||
{
|
||||
context.Branch(lblEnd);
|
||||
|
||||
@ -403,6 +403,21 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
return EmitHostMappedPointer(context, address);
|
||||
}
|
||||
else if (context.Memory.Type == MemoryManagerType.HostTracked)
|
||||
{
|
||||
Operand ptBase = !context.HasPtc
|
||||
? Const(context.Memory.PageTablePointer.ToInt64())
|
||||
: Const(context.Memory.PageTablePointer.ToInt64(), Ptc.PageTableSymbol);
|
||||
|
||||
Operand ptOffset = context.ShiftRightUI(address, Const(PageBits));
|
||||
|
||||
if (ptOffset.Type == OperandType.I32)
|
||||
{
|
||||
ptOffset = context.ZeroExtend32(OperandType.I64, ptOffset);
|
||||
}
|
||||
|
||||
return context.Add(address, context.Load(OperandType.I64, context.Add(ptBase, context.ShiftLeft(ptOffset, Const(3)))));
|
||||
}
|
||||
|
||||
int ptLevelBits = context.Memory.AddressSpaceBits - PageBits;
|
||||
int ptLevelSize = 1 << ptLevelBits;
|
||||
|
@ -8,6 +8,7 @@ namespace ARMeilleure.Memory
|
||||
|
||||
void Commit(ulong offset, ulong size);
|
||||
|
||||
void MapAsRw(ulong offset, ulong size);
|
||||
void MapAsRx(ulong offset, ulong size);
|
||||
void MapAsRwx(ulong offset, ulong size);
|
||||
}
|
||||
|
@ -18,6 +18,12 @@ namespace ARMeilleure.Memory
|
||||
/// </summary>
|
||||
SoftwarePageTable,
|
||||
|
||||
/// <summary>
|
||||
/// High level implementation using a software flat page table for address translation,
|
||||
/// no support for handling invalid or non-contiguous memory access.
|
||||
/// </summary>
|
||||
HostTracked,
|
||||
|
||||
/// <summary>
|
||||
/// High level implementation with mappings managed by the host OS, effectively using hardware
|
||||
/// page tables. No address translation is performed in software and the memory is just accessed directly.
|
||||
@ -37,5 +43,10 @@ namespace ARMeilleure.Memory
|
||||
{
|
||||
return type == MemoryManagerType.HostMapped || type == MemoryManagerType.HostMappedUnsafe;
|
||||
}
|
||||
|
||||
public static bool IsHostMappedOrTracked(this MemoryManagerType type)
|
||||
{
|
||||
return type == MemoryManagerType.HostTracked || type == MemoryManagerType.HostMapped || type == MemoryManagerType.HostMappedUnsafe;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ using System;
|
||||
|
||||
namespace ARMeilleure.Memory
|
||||
{
|
||||
class ReservedRegion
|
||||
public class ReservedRegion
|
||||
{
|
||||
public const int DefaultGranularity = 65536; // Mapping granularity in Windows.
|
||||
|
||||
|
@ -5,9 +5,41 @@ using System.Runtime.Versioning;
|
||||
namespace ARMeilleure.Native
|
||||
{
|
||||
[SupportedOSPlatform("macos")]
|
||||
internal static partial class JitSupportDarwin
|
||||
[SupportedOSPlatform("ios")]
|
||||
static partial class JitSupportDarwin
|
||||
{
|
||||
[LibraryImport("libarmeilleure-jitsupport", EntryPoint = "armeilleure_jit_memcpy")]
|
||||
public static partial void Copy(IntPtr dst, IntPtr src, ulong n);
|
||||
}
|
||||
|
||||
[SupportedOSPlatform("ios")]
|
||||
internal static partial class JitSupportDarwinAot
|
||||
{
|
||||
[LibraryImport("pthread", EntryPoint = "pthread_jit_write_protect_np")]
|
||||
private static partial void pthread_jit_write_protect_np(int enabled);
|
||||
|
||||
[LibraryImport("libc", EntryPoint = "sys_icache_invalidate")]
|
||||
private static partial void sys_icache_invalidate(IntPtr start, IntPtr length);
|
||||
|
||||
public static unsafe void Copy(IntPtr dst, IntPtr src, ulong n) {
|
||||
// When NativeAOT is in use, we can toggle per-thread write protection without worrying about breaking .NET code.
|
||||
|
||||
// pthread_jit_write_protect_np(0);
|
||||
|
||||
var srcSpan = new Span<byte>(src.ToPointer(), (int)n);
|
||||
var dstSpan = new Span<byte>(dst.ToPointer(), (int)n);
|
||||
srcSpan.CopyTo(dstSpan);
|
||||
|
||||
// pthread_jit_write_protect_np(1);
|
||||
|
||||
// Ensure that the instruction cache for this range is invalidated.
|
||||
sys_icache_invalidate(dst, (IntPtr)n);
|
||||
}
|
||||
|
||||
public static unsafe void Invalidate(IntPtr dst, ulong n)
|
||||
{
|
||||
// Ensure that the instruction cache for this range is invalidated.
|
||||
sys_icache_invalidate(dst, (IntPtr)n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.Memory;
|
||||
using ARMeilleure.Translation;
|
||||
using ARMeilleure.Translation.Cache;
|
||||
@ -112,7 +112,7 @@ namespace ARMeilleure.Signal
|
||||
|
||||
ref SignalHandlerConfig config = ref GetConfigRef();
|
||||
|
||||
if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
|
||||
if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
|
||||
{
|
||||
_signalHandlerPtr = Marshal.GetFunctionPointerForDelegate(GenerateUnixSignalHandler(_handlerConfig));
|
||||
|
||||
@ -252,13 +252,13 @@ namespace ARMeilleure.Signal
|
||||
|
||||
private static Operand GenerateUnixFaultAddress(EmitterContext context, Operand sigInfoPtr)
|
||||
{
|
||||
ulong structAddressOffset = OperatingSystem.IsMacOS() ? 24ul : 16ul; // si_addr
|
||||
ulong structAddressOffset = (OperatingSystem.IsMacOS() || OperatingSystem.IsIOS()) ? 24ul : 16ul; // si_addr
|
||||
return context.Load(OperandType.I64, context.Add(sigInfoPtr, Const(structAddressOffset)));
|
||||
}
|
||||
|
||||
private static Operand GenerateUnixWriteFlag(EmitterContext context, Operand ucontextPtr)
|
||||
{
|
||||
if (OperatingSystem.IsMacOS())
|
||||
if (OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
|
||||
{
|
||||
const ulong McontextOffset = 48; // uc_mcontext
|
||||
Operand ctxPtr = context.Load(OperandType.I64, context.Add(ucontextPtr, Const(McontextOffset)));
|
||||
|
@ -62,7 +62,7 @@ namespace ARMeilleure.Signal
|
||||
throw new InvalidOperationException($"Could not register SIGSEGV sigaction. Error: {result}");
|
||||
}
|
||||
|
||||
if (OperatingSystem.IsMacOS())
|
||||
if (OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
|
||||
{
|
||||
result = sigaction(SIGBUS, ref sig, out _);
|
||||
|
||||
@ -77,7 +77,7 @@ namespace ARMeilleure.Signal
|
||||
|
||||
public static bool RestoreExceptionHandler(SigAction oldAction)
|
||||
{
|
||||
return sigaction(SIGSEGV, ref oldAction, out SigAction _) == 0 && (!OperatingSystem.IsMacOS() || sigaction(SIGBUS, ref oldAction, out SigAction _) == 0);
|
||||
return sigaction(SIGSEGV, ref oldAction, out SigAction _) == 0 && (!OperatingSystem.IsMacOS() || OperatingSystem.IsIOS() || sigaction(SIGBUS, ref oldAction, out SigAction _) == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -30,21 +30,26 @@ namespace ARMeilleure.Translation.Cache
|
||||
_blocks.Add(new MemoryBlock(0, capacity));
|
||||
}
|
||||
|
||||
public int Allocate(int size)
|
||||
public int Allocate(ref int size, int alignment)
|
||||
{
|
||||
int alignM1 = alignment - 1;
|
||||
for (int i = 0; i < _blocks.Count; i++)
|
||||
{
|
||||
MemoryBlock block = _blocks[i];
|
||||
int misAlignment = ((block.Offset + alignM1) & (~alignM1)) - block.Offset;
|
||||
int alignedSize = size + misAlignment;
|
||||
|
||||
if (block.Size > size)
|
||||
if (block.Size > alignedSize)
|
||||
{
|
||||
_blocks[i] = new MemoryBlock(block.Offset + size, block.Size - size);
|
||||
return block.Offset;
|
||||
size = alignedSize;
|
||||
_blocks[i] = new MemoryBlock(block.Offset + alignedSize, block.Size - alignedSize);
|
||||
return block.Offset + misAlignment;
|
||||
}
|
||||
else if (block.Size == size)
|
||||
else if (block.Size == alignedSize)
|
||||
{
|
||||
size = alignedSize;
|
||||
_blocks.RemoveAt(i);
|
||||
return block.Offset;
|
||||
return block.Offset + misAlignment;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@ using ARMeilleure.Memory;
|
||||
using ARMeilleure.Native;
|
||||
using Ryujinx.Memory;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
@ -14,10 +15,11 @@ namespace ARMeilleure.Translation.Cache
|
||||
static partial class JitCache
|
||||
{
|
||||
private static readonly int _pageSize = (int)MemoryBlock.GetPageSize();
|
||||
private static readonly int _pageMask = _pageSize - 1;
|
||||
private static readonly int _pageMask = _pageSize - 2;
|
||||
|
||||
private const int CodeAlignment = 4; // Bytes.
|
||||
private const int CacheSize = 2047 * 1024 * 1024;
|
||||
private const int CacheSizeIOS = 64 * 1024 * 1024;
|
||||
|
||||
private static ReservedRegion _jitRegion;
|
||||
private static JitCacheInvalidation _jitCacheInvalidator;
|
||||
@ -47,9 +49,9 @@ namespace ARMeilleure.Translation.Cache
|
||||
return;
|
||||
}
|
||||
|
||||
_jitRegion = new ReservedRegion(allocator, CacheSize);
|
||||
_jitRegion = new ReservedRegion(allocator, (ulong)(OperatingSystem.IsIOS() ? CacheSizeIOS : CacheSize));
|
||||
|
||||
if (!OperatingSystem.IsWindows() && !OperatingSystem.IsMacOS())
|
||||
if (!OperatingSystem.IsWindows() && !OperatingSystem.IsMacOS() && !OperatingSystem.IsIOS())
|
||||
{
|
||||
_jitCacheInvalidator = new JitCacheInvalidation(allocator);
|
||||
}
|
||||
@ -65,7 +67,17 @@ namespace ARMeilleure.Translation.Cache
|
||||
}
|
||||
}
|
||||
|
||||
public static IntPtr Map(CompiledFunction func)
|
||||
static ConcurrentQueue<(int funcOffset, int length)> _deferredRxProtect = new();
|
||||
|
||||
public static void RunDeferredRxProtects()
|
||||
{
|
||||
while (_deferredRxProtect.TryDequeue(out var result))
|
||||
{
|
||||
ReprotectAsExecutable(result.funcOffset, result.length);
|
||||
}
|
||||
}
|
||||
|
||||
public static IntPtr Map(CompiledFunction func, bool deferProtect)
|
||||
{
|
||||
byte[] code = func.Code;
|
||||
|
||||
@ -73,11 +85,25 @@ namespace ARMeilleure.Translation.Cache
|
||||
{
|
||||
Debug.Assert(_initialized);
|
||||
|
||||
int funcOffset = Allocate(code.Length);
|
||||
int funcOffset = Allocate(code.Length, deferProtect);
|
||||
|
||||
IntPtr funcPtr = _jitRegion.Pointer + funcOffset;
|
||||
|
||||
if (OperatingSystem.IsMacOS() && RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
|
||||
if (OperatingSystem.IsIOS())
|
||||
{
|
||||
Marshal.Copy(code, 0, funcPtr, code.Length);
|
||||
if (deferProtect)
|
||||
{
|
||||
_deferredRxProtect.Enqueue((funcOffset, code.Length));
|
||||
}
|
||||
else
|
||||
{
|
||||
ReprotectAsExecutable(funcOffset, code.Length);
|
||||
|
||||
JitSupportDarwinAot.Invalidate(funcPtr, (ulong)code.Length);
|
||||
}
|
||||
}
|
||||
else if (OperatingSystem.IsMacOS()&& RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
@ -111,6 +137,11 @@ namespace ARMeilleure.Translation.Cache
|
||||
|
||||
public static void Unmap(IntPtr pointer)
|
||||
{
|
||||
if (OperatingSystem.IsIOS())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
Debug.Assert(_initialized);
|
||||
@ -145,11 +176,22 @@ namespace ARMeilleure.Translation.Cache
|
||||
_jitRegion.Block.MapAsRx((ulong)regionStart, (ulong)(regionEnd - regionStart));
|
||||
}
|
||||
|
||||
private static int Allocate(int codeSize)
|
||||
private static int Allocate(int codeSize, bool deferProtect = false)
|
||||
{
|
||||
codeSize = AlignCodeSize(codeSize);
|
||||
codeSize = AlignCodeSize(codeSize, deferProtect);
|
||||
|
||||
int allocOffset = _cacheAllocator.Allocate(codeSize);
|
||||
int alignment = CodeAlignment;
|
||||
|
||||
if (OperatingSystem.IsIOS() && !deferProtect)
|
||||
{
|
||||
alignment = 0x4000;
|
||||
}
|
||||
|
||||
int allocOffset = _cacheAllocator.Allocate(ref codeSize, alignment);
|
||||
|
||||
//DEBUG: Show JIT Memory Allocation
|
||||
|
||||
//Console.WriteLine($"{allocOffset:x8}: {codeSize:x8} {alignment:x8}");
|
||||
|
||||
if (allocOffset < 0)
|
||||
{
|
||||
@ -161,9 +203,16 @@ namespace ARMeilleure.Translation.Cache
|
||||
return allocOffset;
|
||||
}
|
||||
|
||||
private static int AlignCodeSize(int codeSize)
|
||||
private static int AlignCodeSize(int codeSize, bool deferProtect = false)
|
||||
{
|
||||
return checked(codeSize + (CodeAlignment - 1)) & ~(CodeAlignment - 1);
|
||||
int alignment = CodeAlignment;
|
||||
|
||||
if (OperatingSystem.IsIOS() && !deferProtect)
|
||||
{
|
||||
alignment = 0x4000;
|
||||
}
|
||||
|
||||
return checked(codeSize + (alignment - 1)) & ~(alignment - 1);
|
||||
}
|
||||
|
||||
private static void Add(int offset, int size, UnwindInfo unwindInfo)
|
||||
|
@ -114,7 +114,7 @@ namespace ARMeilleure.Translation.Cache
|
||||
{
|
||||
int stackOffset = entry.StackOffsetOrAllocSize;
|
||||
|
||||
Debug.Assert(stackOffset % 16 == 0);
|
||||
// Debug.Assert(stackOffset % 16 == 0);
|
||||
|
||||
if (stackOffset <= 0xFFFF0)
|
||||
{
|
||||
@ -135,7 +135,7 @@ namespace ARMeilleure.Translation.Cache
|
||||
{
|
||||
int allocSize = entry.StackOffsetOrAllocSize;
|
||||
|
||||
Debug.Assert(allocSize % 8 == 0);
|
||||
// Debug.Assert(allocSize % 8 == 0);
|
||||
|
||||
if (allocSize <= 128)
|
||||
{
|
||||
|
@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace ARMeilleure.Translation
|
||||
{
|
||||
@ -11,11 +10,10 @@ namespace ARMeilleure.Translation
|
||||
|
||||
public IntPtr FuncPtr { get; }
|
||||
|
||||
public DelegateInfo(Delegate dlg)
|
||||
public DelegateInfo(Delegate dlg, IntPtr funcPtr)
|
||||
{
|
||||
_dlg = dlg;
|
||||
|
||||
FuncPtr = Marshal.GetFunctionPointerForDelegate<Delegate>(dlg);
|
||||
FuncPtr = funcPtr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ using ARMeilleure.State;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace ARMeilleure.Translation
|
||||
{
|
||||
@ -64,11 +65,11 @@ namespace ARMeilleure.Translation
|
||||
return index;
|
||||
}
|
||||
|
||||
private static void SetDelegateInfo(Delegate dlg)
|
||||
private static void SetDelegateInfo(Delegate dlg, IntPtr funcPtr)
|
||||
{
|
||||
string key = GetKey(dlg.Method);
|
||||
|
||||
_delegates.Add(key, new DelegateInfo(dlg)); // ArgumentException (key).
|
||||
_delegates.Add(key, new DelegateInfo(dlg, funcPtr)); // ArgumentException (key).
|
||||
}
|
||||
|
||||
private static string GetKey(MethodInfo info)
|
||||
@ -82,179 +83,353 @@ namespace ARMeilleure.Translation
|
||||
{
|
||||
_delegates = new SortedList<string, DelegateInfo>();
|
||||
|
||||
SetDelegateInfo(new MathAbs(Math.Abs));
|
||||
SetDelegateInfo(new MathCeiling(Math.Ceiling));
|
||||
SetDelegateInfo(new MathFloor(Math.Floor));
|
||||
SetDelegateInfo(new MathRound(Math.Round));
|
||||
SetDelegateInfo(new MathTruncate(Math.Truncate));
|
||||
var dlgMathAbs = new MathAbs(Math.Abs);
|
||||
var dlgMathCeiling = new MathCeiling(Math.Ceiling);
|
||||
var dlgMathFloor = new MathFloor(Math.Floor);
|
||||
var dlgMathRound = new MathRound(Math.Round);
|
||||
var dlgMathTruncate = new MathTruncate(Math.Truncate);
|
||||
|
||||
SetDelegateInfo(new MathFAbs(MathF.Abs));
|
||||
SetDelegateInfo(new MathFCeiling(MathF.Ceiling));
|
||||
SetDelegateInfo(new MathFFloor(MathF.Floor));
|
||||
SetDelegateInfo(new MathFRound(MathF.Round));
|
||||
SetDelegateInfo(new MathFTruncate(MathF.Truncate));
|
||||
var dlgMathFAbs = new MathFAbs(MathF.Abs);
|
||||
var dlgMathFCeiling = new MathFCeiling(MathF.Ceiling);
|
||||
var dlgMathFFloor = new MathFFloor(MathF.Floor);
|
||||
var dlgMathFRound = new MathFRound(MathF.Round);
|
||||
var dlgMathFTruncate = new MathFTruncate(MathF.Truncate);
|
||||
|
||||
SetDelegateInfo(new NativeInterfaceBreak(NativeInterface.Break));
|
||||
SetDelegateInfo(new NativeInterfaceCheckSynchronization(NativeInterface.CheckSynchronization));
|
||||
SetDelegateInfo(new NativeInterfaceEnqueueForRejit(NativeInterface.EnqueueForRejit));
|
||||
SetDelegateInfo(new NativeInterfaceGetCntfrqEl0(NativeInterface.GetCntfrqEl0));
|
||||
SetDelegateInfo(new NativeInterfaceGetCntpctEl0(NativeInterface.GetCntpctEl0));
|
||||
SetDelegateInfo(new NativeInterfaceGetCntvctEl0(NativeInterface.GetCntvctEl0));
|
||||
SetDelegateInfo(new NativeInterfaceGetCtrEl0(NativeInterface.GetCtrEl0));
|
||||
SetDelegateInfo(new NativeInterfaceGetDczidEl0(NativeInterface.GetDczidEl0));
|
||||
SetDelegateInfo(new NativeInterfaceGetFunctionAddress(NativeInterface.GetFunctionAddress));
|
||||
SetDelegateInfo(new NativeInterfaceInvalidateCacheLine(NativeInterface.InvalidateCacheLine));
|
||||
SetDelegateInfo(new NativeInterfaceReadByte(NativeInterface.ReadByte));
|
||||
SetDelegateInfo(new NativeInterfaceReadUInt16(NativeInterface.ReadUInt16));
|
||||
SetDelegateInfo(new NativeInterfaceReadUInt32(NativeInterface.ReadUInt32));
|
||||
SetDelegateInfo(new NativeInterfaceReadUInt64(NativeInterface.ReadUInt64));
|
||||
SetDelegateInfo(new NativeInterfaceReadVector128(NativeInterface.ReadVector128));
|
||||
SetDelegateInfo(new NativeInterfaceSignalMemoryTracking(NativeInterface.SignalMemoryTracking));
|
||||
SetDelegateInfo(new NativeInterfaceSupervisorCall(NativeInterface.SupervisorCall));
|
||||
SetDelegateInfo(new NativeInterfaceThrowInvalidMemoryAccess(NativeInterface.ThrowInvalidMemoryAccess));
|
||||
SetDelegateInfo(new NativeInterfaceUndefined(NativeInterface.Undefined));
|
||||
SetDelegateInfo(new NativeInterfaceWriteByte(NativeInterface.WriteByte));
|
||||
SetDelegateInfo(new NativeInterfaceWriteUInt16(NativeInterface.WriteUInt16));
|
||||
SetDelegateInfo(new NativeInterfaceWriteUInt32(NativeInterface.WriteUInt32));
|
||||
SetDelegateInfo(new NativeInterfaceWriteUInt64(NativeInterface.WriteUInt64));
|
||||
SetDelegateInfo(new NativeInterfaceWriteVector128(NativeInterface.WriteVector128));
|
||||
var dlgNativeInterfaceBreak = new NativeInterfaceBreak(NativeInterface.Break);
|
||||
var dlgNativeInterfaceCheckSynchronization = new NativeInterfaceCheckSynchronization(NativeInterface.CheckSynchronization);
|
||||
var dlgNativeInterfaceEnqueueForRejit = new NativeInterfaceEnqueueForRejit(NativeInterface.EnqueueForRejit);
|
||||
var dlgNativeInterfaceGetCntfrqEl0 = new NativeInterfaceGetCntfrqEl0(NativeInterface.GetCntfrqEl0);
|
||||
var dlgNativeInterfaceGetCntpctEl0 = new NativeInterfaceGetCntpctEl0(NativeInterface.GetCntpctEl0);
|
||||
var dlgNativeInterfaceGetCntvctEl0 = new NativeInterfaceGetCntvctEl0(NativeInterface.GetCntvctEl0);
|
||||
var dlgNativeInterfaceGetCtrEl0 = new NativeInterfaceGetCtrEl0(NativeInterface.GetCtrEl0);
|
||||
var dlgNativeInterfaceGetDczidEl0 = new NativeInterfaceGetDczidEl0(NativeInterface.GetDczidEl0);
|
||||
var dlgNativeInterfaceGetFunctionAddress = new NativeInterfaceGetFunctionAddress(NativeInterface.GetFunctionAddress);
|
||||
var dlgNativeInterfaceInvalidateCacheLine = new NativeInterfaceInvalidateCacheLine(NativeInterface.InvalidateCacheLine);
|
||||
var dlgNativeInterfaceReadByte = new NativeInterfaceReadByte(NativeInterface.ReadByte);
|
||||
var dlgNativeInterfaceReadUInt16 = new NativeInterfaceReadUInt16(NativeInterface.ReadUInt16);
|
||||
var dlgNativeInterfaceReadUInt32 = new NativeInterfaceReadUInt32(NativeInterface.ReadUInt32);
|
||||
var dlgNativeInterfaceReadUInt64 = new NativeInterfaceReadUInt64(NativeInterface.ReadUInt64);
|
||||
var dlgNativeInterfaceReadVector128 = new NativeInterfaceReadVector128(NativeInterface.ReadVector128);
|
||||
var dlgNativeInterfaceSignalMemoryTracking = new NativeInterfaceSignalMemoryTracking(NativeInterface.SignalMemoryTracking);
|
||||
var dlgNativeInterfaceSupervisorCall = new NativeInterfaceSupervisorCall(NativeInterface.SupervisorCall);
|
||||
var dlgNativeInterfaceThrowInvalidMemoryAccess = new NativeInterfaceThrowInvalidMemoryAccess(NativeInterface.ThrowInvalidMemoryAccess);
|
||||
var dlgNativeInterfaceUndefined = new NativeInterfaceUndefined(NativeInterface.Undefined);
|
||||
var dlgNativeInterfaceWriteByte = new NativeInterfaceWriteByte(NativeInterface.WriteByte);
|
||||
var dlgNativeInterfaceWriteUInt16 = new NativeInterfaceWriteUInt16(NativeInterface.WriteUInt16);
|
||||
var dlgNativeInterfaceWriteUInt32 = new NativeInterfaceWriteUInt32(NativeInterface.WriteUInt32);
|
||||
var dlgNativeInterfaceWriteUInt64 = new NativeInterfaceWriteUInt64(NativeInterface.WriteUInt64);
|
||||
var dlgNativeInterfaceWriteVector128 = new NativeInterfaceWriteVector128(NativeInterface.WriteVector128);
|
||||
|
||||
SetDelegateInfo(new SoftFallbackCountLeadingSigns(SoftFallback.CountLeadingSigns));
|
||||
SetDelegateInfo(new SoftFallbackCountLeadingZeros(SoftFallback.CountLeadingZeros));
|
||||
SetDelegateInfo(new SoftFallbackCrc32b(SoftFallback.Crc32b));
|
||||
SetDelegateInfo(new SoftFallbackCrc32cb(SoftFallback.Crc32cb));
|
||||
SetDelegateInfo(new SoftFallbackCrc32ch(SoftFallback.Crc32ch));
|
||||
SetDelegateInfo(new SoftFallbackCrc32cw(SoftFallback.Crc32cw));
|
||||
SetDelegateInfo(new SoftFallbackCrc32cx(SoftFallback.Crc32cx));
|
||||
SetDelegateInfo(new SoftFallbackCrc32h(SoftFallback.Crc32h));
|
||||
SetDelegateInfo(new SoftFallbackCrc32w(SoftFallback.Crc32w));
|
||||
SetDelegateInfo(new SoftFallbackCrc32x(SoftFallback.Crc32x));
|
||||
SetDelegateInfo(new SoftFallbackDecrypt(SoftFallback.Decrypt));
|
||||
SetDelegateInfo(new SoftFallbackEncrypt(SoftFallback.Encrypt));
|
||||
SetDelegateInfo(new SoftFallbackFixedRotate(SoftFallback.FixedRotate));
|
||||
SetDelegateInfo(new SoftFallbackHashChoose(SoftFallback.HashChoose));
|
||||
SetDelegateInfo(new SoftFallbackHashLower(SoftFallback.HashLower));
|
||||
SetDelegateInfo(new SoftFallbackHashMajority(SoftFallback.HashMajority));
|
||||
SetDelegateInfo(new SoftFallbackHashParity(SoftFallback.HashParity));
|
||||
SetDelegateInfo(new SoftFallbackHashUpper(SoftFallback.HashUpper));
|
||||
SetDelegateInfo(new SoftFallbackInverseMixColumns(SoftFallback.InverseMixColumns));
|
||||
SetDelegateInfo(new SoftFallbackMixColumns(SoftFallback.MixColumns));
|
||||
SetDelegateInfo(new SoftFallbackPolynomialMult64_128(SoftFallback.PolynomialMult64_128));
|
||||
SetDelegateInfo(new SoftFallbackSatF32ToS32(SoftFallback.SatF32ToS32));
|
||||
SetDelegateInfo(new SoftFallbackSatF32ToS64(SoftFallback.SatF32ToS64));
|
||||
SetDelegateInfo(new SoftFallbackSatF32ToU32(SoftFallback.SatF32ToU32));
|
||||
SetDelegateInfo(new SoftFallbackSatF32ToU64(SoftFallback.SatF32ToU64));
|
||||
SetDelegateInfo(new SoftFallbackSatF64ToS32(SoftFallback.SatF64ToS32));
|
||||
SetDelegateInfo(new SoftFallbackSatF64ToS64(SoftFallback.SatF64ToS64));
|
||||
SetDelegateInfo(new SoftFallbackSatF64ToU32(SoftFallback.SatF64ToU32));
|
||||
SetDelegateInfo(new SoftFallbackSatF64ToU64(SoftFallback.SatF64ToU64));
|
||||
SetDelegateInfo(new SoftFallbackSha1SchedulePart1(SoftFallback.Sha1SchedulePart1));
|
||||
SetDelegateInfo(new SoftFallbackSha1SchedulePart2(SoftFallback.Sha1SchedulePart2));
|
||||
SetDelegateInfo(new SoftFallbackSha256SchedulePart1(SoftFallback.Sha256SchedulePart1));
|
||||
SetDelegateInfo(new SoftFallbackSha256SchedulePart2(SoftFallback.Sha256SchedulePart2));
|
||||
SetDelegateInfo(new SoftFallbackSignedShrImm64(SoftFallback.SignedShrImm64));
|
||||
SetDelegateInfo(new SoftFallbackTbl1(SoftFallback.Tbl1));
|
||||
SetDelegateInfo(new SoftFallbackTbl2(SoftFallback.Tbl2));
|
||||
SetDelegateInfo(new SoftFallbackTbl3(SoftFallback.Tbl3));
|
||||
SetDelegateInfo(new SoftFallbackTbl4(SoftFallback.Tbl4));
|
||||
SetDelegateInfo(new SoftFallbackTbx1(SoftFallback.Tbx1));
|
||||
SetDelegateInfo(new SoftFallbackTbx2(SoftFallback.Tbx2));
|
||||
SetDelegateInfo(new SoftFallbackTbx3(SoftFallback.Tbx3));
|
||||
SetDelegateInfo(new SoftFallbackTbx4(SoftFallback.Tbx4));
|
||||
SetDelegateInfo(new SoftFallbackUnsignedShrImm64(SoftFallback.UnsignedShrImm64));
|
||||
var dlgSoftFallbackCountLeadingSigns = new SoftFallbackCountLeadingSigns(SoftFallback.CountLeadingSigns);
|
||||
var dlgSoftFallbackCountLeadingZeros = new SoftFallbackCountLeadingZeros(SoftFallback.CountLeadingZeros);
|
||||
var dlgSoftFallbackCrc32b = new SoftFallbackCrc32b(SoftFallback.Crc32b);
|
||||
var dlgSoftFallbackCrc32cb = new SoftFallbackCrc32cb(SoftFallback.Crc32cb);
|
||||
var dlgSoftFallbackCrc32ch = new SoftFallbackCrc32ch(SoftFallback.Crc32ch);
|
||||
var dlgSoftFallbackCrc32cw = new SoftFallbackCrc32cw(SoftFallback.Crc32cw);
|
||||
var dlgSoftFallbackCrc32cx = new SoftFallbackCrc32cx(SoftFallback.Crc32cx);
|
||||
var dlgSoftFallbackCrc32h = new SoftFallbackCrc32h(SoftFallback.Crc32h);
|
||||
var dlgSoftFallbackCrc32w = new SoftFallbackCrc32w(SoftFallback.Crc32w);
|
||||
var dlgSoftFallbackCrc32x = new SoftFallbackCrc32x(SoftFallback.Crc32x);
|
||||
var dlgSoftFallbackDecrypt = new SoftFallbackDecrypt(SoftFallback.Decrypt);
|
||||
var dlgSoftFallbackEncrypt = new SoftFallbackEncrypt(SoftFallback.Encrypt);
|
||||
var dlgSoftFallbackFixedRotate = new SoftFallbackFixedRotate(SoftFallback.FixedRotate);
|
||||
var dlgSoftFallbackHashChoose = new SoftFallbackHashChoose(SoftFallback.HashChoose);
|
||||
var dlgSoftFallbackHashLower = new SoftFallbackHashLower(SoftFallback.HashLower);
|
||||
var dlgSoftFallbackHashMajority = new SoftFallbackHashMajority(SoftFallback.HashMajority);
|
||||
var dlgSoftFallbackHashParity = new SoftFallbackHashParity(SoftFallback.HashParity);
|
||||
var dlgSoftFallbackHashUpper = new SoftFallbackHashUpper(SoftFallback.HashUpper);
|
||||
var dlgSoftFallbackInverseMixColumns = new SoftFallbackInverseMixColumns(SoftFallback.InverseMixColumns);
|
||||
var dlgSoftFallbackMixColumns = new SoftFallbackMixColumns(SoftFallback.MixColumns);
|
||||
var dlgSoftFallbackPolynomialMult64_128 = new SoftFallbackPolynomialMult64_128(SoftFallback.PolynomialMult64_128);
|
||||
var dlgSoftFallbackSatF32ToS32 = new SoftFallbackSatF32ToS32(SoftFallback.SatF32ToS32);
|
||||
var dlgSoftFallbackSatF32ToS64 = new SoftFallbackSatF32ToS64(SoftFallback.SatF32ToS64);
|
||||
var dlgSoftFallbackSatF32ToU32 = new SoftFallbackSatF32ToU32(SoftFallback.SatF32ToU32);
|
||||
var dlgSoftFallbackSatF32ToU64 = new SoftFallbackSatF32ToU64(SoftFallback.SatF32ToU64);
|
||||
var dlgSoftFallbackSatF64ToS32 = new SoftFallbackSatF64ToS32(SoftFallback.SatF64ToS32);
|
||||
var dlgSoftFallbackSatF64ToS64 = new SoftFallbackSatF64ToS64(SoftFallback.SatF64ToS64);
|
||||
var dlgSoftFallbackSatF64ToU32 = new SoftFallbackSatF64ToU32(SoftFallback.SatF64ToU32);
|
||||
var dlgSoftFallbackSatF64ToU64 = new SoftFallbackSatF64ToU64(SoftFallback.SatF64ToU64);
|
||||
var dlgSoftFallbackSha1SchedulePart1 = new SoftFallbackSha1SchedulePart1(SoftFallback.Sha1SchedulePart1);
|
||||
var dlgSoftFallbackSha1SchedulePart2 = new SoftFallbackSha1SchedulePart2(SoftFallback.Sha1SchedulePart2);
|
||||
var dlgSoftFallbackSha256SchedulePart1 = new SoftFallbackSha256SchedulePart1(SoftFallback.Sha256SchedulePart1);
|
||||
var dlgSoftFallbackSha256SchedulePart2 = new SoftFallbackSha256SchedulePart2(SoftFallback.Sha256SchedulePart2);
|
||||
var dlgSoftFallbackSignedShrImm64 = new SoftFallbackSignedShrImm64(SoftFallback.SignedShrImm64);
|
||||
var dlgSoftFallbackTbl1 = new SoftFallbackTbl1(SoftFallback.Tbl1);
|
||||
var dlgSoftFallbackTbl2 = new SoftFallbackTbl2(SoftFallback.Tbl2);
|
||||
var dlgSoftFallbackTbl3 = new SoftFallbackTbl3(SoftFallback.Tbl3);
|
||||
var dlgSoftFallbackTbl4 = new SoftFallbackTbl4(SoftFallback.Tbl4);
|
||||
var dlgSoftFallbackTbx1 = new SoftFallbackTbx1(SoftFallback.Tbx1);
|
||||
var dlgSoftFallbackTbx2 = new SoftFallbackTbx2(SoftFallback.Tbx2);
|
||||
var dlgSoftFallbackTbx3 = new SoftFallbackTbx3(SoftFallback.Tbx3);
|
||||
var dlgSoftFallbackTbx4 = new SoftFallbackTbx4(SoftFallback.Tbx4);
|
||||
var dlgSoftFallbackUnsignedShrImm64 = new SoftFallbackUnsignedShrImm64(SoftFallback.UnsignedShrImm64);
|
||||
|
||||
SetDelegateInfo(new SoftFloat16_32FPConvert(SoftFloat16_32.FPConvert));
|
||||
SetDelegateInfo(new SoftFloat16_64FPConvert(SoftFloat16_64.FPConvert));
|
||||
var dlgSoftFloat16_32FPConvert = new SoftFloat16_32FPConvert(SoftFloat16_32.FPConvert);
|
||||
var dlgSoftFloat16_64FPConvert = new SoftFloat16_64FPConvert(SoftFloat16_64.FPConvert);
|
||||
|
||||
SetDelegateInfo(new SoftFloat32FPAdd(SoftFloat32.FPAdd));
|
||||
SetDelegateInfo(new SoftFloat32FPAddFpscr(SoftFloat32.FPAddFpscr)); // A32 only.
|
||||
SetDelegateInfo(new SoftFloat32FPCompare(SoftFloat32.FPCompare));
|
||||
SetDelegateInfo(new SoftFloat32FPCompareEQ(SoftFloat32.FPCompareEQ));
|
||||
SetDelegateInfo(new SoftFloat32FPCompareEQFpscr(SoftFloat32.FPCompareEQFpscr)); // A32 only.
|
||||
SetDelegateInfo(new SoftFloat32FPCompareGE(SoftFloat32.FPCompareGE));
|
||||
SetDelegateInfo(new SoftFloat32FPCompareGEFpscr(SoftFloat32.FPCompareGEFpscr)); // A32 only.
|
||||
SetDelegateInfo(new SoftFloat32FPCompareGT(SoftFloat32.FPCompareGT));
|
||||
SetDelegateInfo(new SoftFloat32FPCompareGTFpscr(SoftFloat32.FPCompareGTFpscr)); // A32 only.
|
||||
SetDelegateInfo(new SoftFloat32FPCompareLE(SoftFloat32.FPCompareLE));
|
||||
SetDelegateInfo(new SoftFloat32FPCompareLEFpscr(SoftFloat32.FPCompareLEFpscr)); // A32 only.
|
||||
SetDelegateInfo(new SoftFloat32FPCompareLT(SoftFloat32.FPCompareLT));
|
||||
SetDelegateInfo(new SoftFloat32FPCompareLTFpscr(SoftFloat32.FPCompareLTFpscr)); // A32 only.
|
||||
SetDelegateInfo(new SoftFloat32FPDiv(SoftFloat32.FPDiv));
|
||||
SetDelegateInfo(new SoftFloat32FPMax(SoftFloat32.FPMax));
|
||||
SetDelegateInfo(new SoftFloat32FPMaxFpscr(SoftFloat32.FPMaxFpscr)); // A32 only.
|
||||
SetDelegateInfo(new SoftFloat32FPMaxNum(SoftFloat32.FPMaxNum));
|
||||
SetDelegateInfo(new SoftFloat32FPMaxNumFpscr(SoftFloat32.FPMaxNumFpscr)); // A32 only.
|
||||
SetDelegateInfo(new SoftFloat32FPMin(SoftFloat32.FPMin));
|
||||
SetDelegateInfo(new SoftFloat32FPMinFpscr(SoftFloat32.FPMinFpscr)); // A32 only.
|
||||
SetDelegateInfo(new SoftFloat32FPMinNum(SoftFloat32.FPMinNum));
|
||||
SetDelegateInfo(new SoftFloat32FPMinNumFpscr(SoftFloat32.FPMinNumFpscr)); // A32 only.
|
||||
SetDelegateInfo(new SoftFloat32FPMul(SoftFloat32.FPMul));
|
||||
SetDelegateInfo(new SoftFloat32FPMulFpscr(SoftFloat32.FPMulFpscr)); // A32 only.
|
||||
SetDelegateInfo(new SoftFloat32FPMulAdd(SoftFloat32.FPMulAdd));
|
||||
SetDelegateInfo(new SoftFloat32FPMulAddFpscr(SoftFloat32.FPMulAddFpscr)); // A32 only.
|
||||
SetDelegateInfo(new SoftFloat32FPMulSub(SoftFloat32.FPMulSub));
|
||||
SetDelegateInfo(new SoftFloat32FPMulSubFpscr(SoftFloat32.FPMulSubFpscr)); // A32 only.
|
||||
SetDelegateInfo(new SoftFloat32FPMulX(SoftFloat32.FPMulX));
|
||||
SetDelegateInfo(new SoftFloat32FPNegMulAdd(SoftFloat32.FPNegMulAdd));
|
||||
SetDelegateInfo(new SoftFloat32FPNegMulSub(SoftFloat32.FPNegMulSub));
|
||||
SetDelegateInfo(new SoftFloat32FPRecipEstimate(SoftFloat32.FPRecipEstimate));
|
||||
SetDelegateInfo(new SoftFloat32FPRecipEstimateFpscr(SoftFloat32.FPRecipEstimateFpscr)); // A32 only.
|
||||
SetDelegateInfo(new SoftFloat32FPRecipStep(SoftFloat32.FPRecipStep)); // A32 only.
|
||||
SetDelegateInfo(new SoftFloat32FPRecipStepFused(SoftFloat32.FPRecipStepFused));
|
||||
SetDelegateInfo(new SoftFloat32FPRecpX(SoftFloat32.FPRecpX));
|
||||
SetDelegateInfo(new SoftFloat32FPRSqrtEstimate(SoftFloat32.FPRSqrtEstimate));
|
||||
SetDelegateInfo(new SoftFloat32FPRSqrtEstimateFpscr(SoftFloat32.FPRSqrtEstimateFpscr)); // A32 only.
|
||||
SetDelegateInfo(new SoftFloat32FPRSqrtStep(SoftFloat32.FPRSqrtStep)); // A32 only.
|
||||
SetDelegateInfo(new SoftFloat32FPRSqrtStepFused(SoftFloat32.FPRSqrtStepFused));
|
||||
SetDelegateInfo(new SoftFloat32FPSqrt(SoftFloat32.FPSqrt));
|
||||
SetDelegateInfo(new SoftFloat32FPSub(SoftFloat32.FPSub));
|
||||
var dlgSoftFloat32FPAdd = new SoftFloat32FPAdd(SoftFloat32.FPAdd);
|
||||
var dlgSoftFloat32FPAddFpscr = new SoftFloat32FPAddFpscr(SoftFloat32.FPAddFpscr); // A32 only.
|
||||
var dlgSoftFloat32FPCompare = new SoftFloat32FPCompare(SoftFloat32.FPCompare);
|
||||
var dlgSoftFloat32FPCompareEQ = new SoftFloat32FPCompareEQ(SoftFloat32.FPCompareEQ);
|
||||
var dlgSoftFloat32FPCompareEQFpscr = new SoftFloat32FPCompareEQFpscr(SoftFloat32.FPCompareEQFpscr); // A32 only.
|
||||
var dlgSoftFloat32FPCompareGE = new SoftFloat32FPCompareGE(SoftFloat32.FPCompareGE);
|
||||
var dlgSoftFloat32FPCompareGEFpscr = new SoftFloat32FPCompareGEFpscr(SoftFloat32.FPCompareGEFpscr); // A32 only.
|
||||
var dlgSoftFloat32FPCompareGT = new SoftFloat32FPCompareGT(SoftFloat32.FPCompareGT);
|
||||
var dlgSoftFloat32FPCompareGTFpscr = new SoftFloat32FPCompareGTFpscr(SoftFloat32.FPCompareGTFpscr); // A32 only.
|
||||
var dlgSoftFloat32FPCompareLE = new SoftFloat32FPCompareLE(SoftFloat32.FPCompareLE);
|
||||
var dlgSoftFloat32FPCompareLEFpscr = new SoftFloat32FPCompareLEFpscr(SoftFloat32.FPCompareLEFpscr); // A32 only.
|
||||
var dlgSoftFloat32FPCompareLT = new SoftFloat32FPCompareLT(SoftFloat32.FPCompareLT);
|
||||
var dlgSoftFloat32FPCompareLTFpscr = new SoftFloat32FPCompareLTFpscr(SoftFloat32.FPCompareLTFpscr); // A32 only.
|
||||
var dlgSoftFloat32FPDiv = new SoftFloat32FPDiv(SoftFloat32.FPDiv);
|
||||
var dlgSoftFloat32FPMax = new SoftFloat32FPMax(SoftFloat32.FPMax);
|
||||
var dlgSoftFloat32FPMaxFpscr = new SoftFloat32FPMaxFpscr(SoftFloat32.FPMaxFpscr); // A32 only.
|
||||
var dlgSoftFloat32FPMaxNum = new SoftFloat32FPMaxNum(SoftFloat32.FPMaxNum);
|
||||
var dlgSoftFloat32FPMaxNumFpscr = new SoftFloat32FPMaxNumFpscr(SoftFloat32.FPMaxNumFpscr); // A32 only.
|
||||
var dlgSoftFloat32FPMin = new SoftFloat32FPMin(SoftFloat32.FPMin);
|
||||
var dlgSoftFloat32FPMinFpscr = new SoftFloat32FPMinFpscr(SoftFloat32.FPMinFpscr); // A32 only.
|
||||
var dlgSoftFloat32FPMinNum = new SoftFloat32FPMinNum(SoftFloat32.FPMinNum);
|
||||
var dlgSoftFloat32FPMinNumFpscr = new SoftFloat32FPMinNumFpscr(SoftFloat32.FPMinNumFpscr); // A32 only.
|
||||
var dlgSoftFloat32FPMul = new SoftFloat32FPMul(SoftFloat32.FPMul);
|
||||
var dlgSoftFloat32FPMulFpscr = new SoftFloat32FPMulFpscr(SoftFloat32.FPMulFpscr); // A32 only.
|
||||
var dlgSoftFloat32FPMulAdd = new SoftFloat32FPMulAdd(SoftFloat32.FPMulAdd);
|
||||
var dlgSoftFloat32FPMulAddFpscr = new SoftFloat32FPMulAddFpscr(SoftFloat32.FPMulAddFpscr); // A32 only.
|
||||
var dlgSoftFloat32FPMulSub = new SoftFloat32FPMulSub(SoftFloat32.FPMulSub);
|
||||
var dlgSoftFloat32FPMulSubFpscr = new SoftFloat32FPMulSubFpscr(SoftFloat32.FPMulSubFpscr); // A32 only.
|
||||
var dlgSoftFloat32FPMulX = new SoftFloat32FPMulX(SoftFloat32.FPMulX);
|
||||
var dlgSoftFloat32FPNegMulAdd = new SoftFloat32FPNegMulAdd(SoftFloat32.FPNegMulAdd);
|
||||
var dlgSoftFloat32FPNegMulSub = new SoftFloat32FPNegMulSub(SoftFloat32.FPNegMulSub);
|
||||
var dlgSoftFloat32FPRecipEstimate = new SoftFloat32FPRecipEstimate(SoftFloat32.FPRecipEstimate);
|
||||
var dlgSoftFloat32FPRecipEstimateFpscr = new SoftFloat32FPRecipEstimateFpscr(SoftFloat32.FPRecipEstimateFpscr); // A32 only.
|
||||
var dlgSoftFloat32FPRecipStep = new SoftFloat32FPRecipStep(SoftFloat32.FPRecipStep); // A32 only.
|
||||
var dlgSoftFloat32FPRecipStepFused = new SoftFloat32FPRecipStepFused(SoftFloat32.FPRecipStepFused);
|
||||
var dlgSoftFloat32FPRecpX = new SoftFloat32FPRecpX(SoftFloat32.FPRecpX);
|
||||
var dlgSoftFloat32FPRSqrtEstimate = new SoftFloat32FPRSqrtEstimate(SoftFloat32.FPRSqrtEstimate);
|
||||
var dlgSoftFloat32FPRSqrtEstimateFpscr = new SoftFloat32FPRSqrtEstimateFpscr(SoftFloat32.FPRSqrtEstimateFpscr); // A32 only.
|
||||
var dlgSoftFloat32FPRSqrtStep = new SoftFloat32FPRSqrtStep(SoftFloat32.FPRSqrtStep); // A32 only.
|
||||
var dlgSoftFloat32FPRSqrtStepFused = new SoftFloat32FPRSqrtStepFused(SoftFloat32.FPRSqrtStepFused);
|
||||
var dlgSoftFloat32FPSqrt = new SoftFloat32FPSqrt(SoftFloat32.FPSqrt);
|
||||
var dlgSoftFloat32FPSub = new SoftFloat32FPSub(SoftFloat32.FPSub);
|
||||
|
||||
SetDelegateInfo(new SoftFloat32_16FPConvert(SoftFloat32_16.FPConvert));
|
||||
var dlgSoftFloat32_16FPConvert = new SoftFloat32_16FPConvert(SoftFloat32_16.FPConvert);
|
||||
|
||||
SetDelegateInfo(new SoftFloat64FPAdd(SoftFloat64.FPAdd));
|
||||
SetDelegateInfo(new SoftFloat64FPAddFpscr(SoftFloat64.FPAddFpscr)); // A32 only.
|
||||
SetDelegateInfo(new SoftFloat64FPCompare(SoftFloat64.FPCompare));
|
||||
SetDelegateInfo(new SoftFloat64FPCompareEQ(SoftFloat64.FPCompareEQ));
|
||||
SetDelegateInfo(new SoftFloat64FPCompareEQFpscr(SoftFloat64.FPCompareEQFpscr)); // A32 only.
|
||||
SetDelegateInfo(new SoftFloat64FPCompareGE(SoftFloat64.FPCompareGE));
|
||||
SetDelegateInfo(new SoftFloat64FPCompareGEFpscr(SoftFloat64.FPCompareGEFpscr)); // A32 only.
|
||||
SetDelegateInfo(new SoftFloat64FPCompareGT(SoftFloat64.FPCompareGT));
|
||||
SetDelegateInfo(new SoftFloat64FPCompareGTFpscr(SoftFloat64.FPCompareGTFpscr)); // A32 only.
|
||||
SetDelegateInfo(new SoftFloat64FPCompareLE(SoftFloat64.FPCompareLE));
|
||||
SetDelegateInfo(new SoftFloat64FPCompareLEFpscr(SoftFloat64.FPCompareLEFpscr)); // A32 only.
|
||||
SetDelegateInfo(new SoftFloat64FPCompareLT(SoftFloat64.FPCompareLT));
|
||||
SetDelegateInfo(new SoftFloat64FPCompareLTFpscr(SoftFloat64.FPCompareLTFpscr)); // A32 only.
|
||||
SetDelegateInfo(new SoftFloat64FPDiv(SoftFloat64.FPDiv));
|
||||
SetDelegateInfo(new SoftFloat64FPMax(SoftFloat64.FPMax));
|
||||
SetDelegateInfo(new SoftFloat64FPMaxFpscr(SoftFloat64.FPMaxFpscr)); // A32 only.
|
||||
SetDelegateInfo(new SoftFloat64FPMaxNum(SoftFloat64.FPMaxNum));
|
||||
SetDelegateInfo(new SoftFloat64FPMaxNumFpscr(SoftFloat64.FPMaxNumFpscr)); // A32 only.
|
||||
SetDelegateInfo(new SoftFloat64FPMin(SoftFloat64.FPMin));
|
||||
SetDelegateInfo(new SoftFloat64FPMinFpscr(SoftFloat64.FPMinFpscr)); // A32 only.
|
||||
SetDelegateInfo(new SoftFloat64FPMinNum(SoftFloat64.FPMinNum));
|
||||
SetDelegateInfo(new SoftFloat64FPMinNumFpscr(SoftFloat64.FPMinNumFpscr)); // A32 only.
|
||||
SetDelegateInfo(new SoftFloat64FPMul(SoftFloat64.FPMul));
|
||||
SetDelegateInfo(new SoftFloat64FPMulFpscr(SoftFloat64.FPMulFpscr)); // A32 only.
|
||||
SetDelegateInfo(new SoftFloat64FPMulAdd(SoftFloat64.FPMulAdd));
|
||||
SetDelegateInfo(new SoftFloat64FPMulAddFpscr(SoftFloat64.FPMulAddFpscr)); // A32 only.
|
||||
SetDelegateInfo(new SoftFloat64FPMulSub(SoftFloat64.FPMulSub));
|
||||
SetDelegateInfo(new SoftFloat64FPMulSubFpscr(SoftFloat64.FPMulSubFpscr)); // A32 only.
|
||||
SetDelegateInfo(new SoftFloat64FPMulX(SoftFloat64.FPMulX));
|
||||
SetDelegateInfo(new SoftFloat64FPNegMulAdd(SoftFloat64.FPNegMulAdd));
|
||||
SetDelegateInfo(new SoftFloat64FPNegMulSub(SoftFloat64.FPNegMulSub));
|
||||
SetDelegateInfo(new SoftFloat64FPRecipEstimate(SoftFloat64.FPRecipEstimate));
|
||||
SetDelegateInfo(new SoftFloat64FPRecipEstimateFpscr(SoftFloat64.FPRecipEstimateFpscr)); // A32 only.
|
||||
SetDelegateInfo(new SoftFloat64FPRecipStep(SoftFloat64.FPRecipStep)); // A32 only.
|
||||
SetDelegateInfo(new SoftFloat64FPRecipStepFused(SoftFloat64.FPRecipStepFused));
|
||||
SetDelegateInfo(new SoftFloat64FPRecpX(SoftFloat64.FPRecpX));
|
||||
SetDelegateInfo(new SoftFloat64FPRSqrtEstimate(SoftFloat64.FPRSqrtEstimate));
|
||||
SetDelegateInfo(new SoftFloat64FPRSqrtEstimateFpscr(SoftFloat64.FPRSqrtEstimateFpscr)); // A32 only.
|
||||
SetDelegateInfo(new SoftFloat64FPRSqrtStep(SoftFloat64.FPRSqrtStep)); // A32 only.
|
||||
SetDelegateInfo(new SoftFloat64FPRSqrtStepFused(SoftFloat64.FPRSqrtStepFused));
|
||||
SetDelegateInfo(new SoftFloat64FPSqrt(SoftFloat64.FPSqrt));
|
||||
SetDelegateInfo(new SoftFloat64FPSub(SoftFloat64.FPSub));
|
||||
var dlgSoftFloat64FPAdd = new SoftFloat64FPAdd(SoftFloat64.FPAdd);
|
||||
var dlgSoftFloat64FPAddFpscr = new SoftFloat64FPAddFpscr(SoftFloat64.FPAddFpscr); // A32 only.
|
||||
var dlgSoftFloat64FPCompare = new SoftFloat64FPCompare(SoftFloat64.FPCompare);
|
||||
var dlgSoftFloat64FPCompareEQ = new SoftFloat64FPCompareEQ(SoftFloat64.FPCompareEQ);
|
||||
var dlgSoftFloat64FPCompareEQFpscr = new SoftFloat64FPCompareEQFpscr(SoftFloat64.FPCompareEQFpscr); // A32 only.
|
||||
var dlgSoftFloat64FPCompareGE = new SoftFloat64FPCompareGE(SoftFloat64.FPCompareGE);
|
||||
var dlgSoftFloat64FPCompareGEFpscr = new SoftFloat64FPCompareGEFpscr(SoftFloat64.FPCompareGEFpscr); // A32 only.
|
||||
var dlgSoftFloat64FPCompareGT = new SoftFloat64FPCompareGT(SoftFloat64.FPCompareGT);
|
||||
var dlgSoftFloat64FPCompareGTFpscr = new SoftFloat64FPCompareGTFpscr(SoftFloat64.FPCompareGTFpscr); // A32 only.
|
||||
var dlgSoftFloat64FPCompareLE = new SoftFloat64FPCompareLE(SoftFloat64.FPCompareLE);
|
||||
var dlgSoftFloat64FPCompareLEFpscr = new SoftFloat64FPCompareLEFpscr(SoftFloat64.FPCompareLEFpscr); // A32 only.
|
||||
var dlgSoftFloat64FPCompareLT = new SoftFloat64FPCompareLT(SoftFloat64.FPCompareLT);
|
||||
var dlgSoftFloat64FPCompareLTFpscr = new SoftFloat64FPCompareLTFpscr(SoftFloat64.FPCompareLTFpscr); // A32 only.
|
||||
var dlgSoftFloat64FPDiv = new SoftFloat64FPDiv(SoftFloat64.FPDiv);
|
||||
var dlgSoftFloat64FPMax = new SoftFloat64FPMax(SoftFloat64.FPMax);
|
||||
var dlgSoftFloat64FPMaxFpscr = new SoftFloat64FPMaxFpscr(SoftFloat64.FPMaxFpscr); // A32 only.
|
||||
var dlgSoftFloat64FPMaxNum = new SoftFloat64FPMaxNum(SoftFloat64.FPMaxNum);
|
||||
var dlgSoftFloat64FPMaxNumFpscr = new SoftFloat64FPMaxNumFpscr(SoftFloat64.FPMaxNumFpscr); // A32 only.
|
||||
var dlgSoftFloat64FPMin = new SoftFloat64FPMin(SoftFloat64.FPMin);
|
||||
var dlgSoftFloat64FPMinFpscr = new SoftFloat64FPMinFpscr(SoftFloat64.FPMinFpscr); // A32 only.
|
||||
var dlgSoftFloat64FPMinNum = new SoftFloat64FPMinNum(SoftFloat64.FPMinNum);
|
||||
var dlgSoftFloat64FPMinNumFpscr = new SoftFloat64FPMinNumFpscr(SoftFloat64.FPMinNumFpscr); // A32 only.
|
||||
var dlgSoftFloat64FPMul = new SoftFloat64FPMul(SoftFloat64.FPMul);
|
||||
var dlgSoftFloat64FPMulFpscr = new SoftFloat64FPMulFpscr(SoftFloat64.FPMulFpscr); // A32 only.
|
||||
var dlgSoftFloat64FPMulAdd = new SoftFloat64FPMulAdd(SoftFloat64.FPMulAdd);
|
||||
var dlgSoftFloat64FPMulAddFpscr = new SoftFloat64FPMulAddFpscr(SoftFloat64.FPMulAddFpscr); // A32 only.
|
||||
var dlgSoftFloat64FPMulSub = new SoftFloat64FPMulSub(SoftFloat64.FPMulSub);
|
||||
var dlgSoftFloat64FPMulSubFpscr = new SoftFloat64FPMulSubFpscr(SoftFloat64.FPMulSubFpscr); // A32 only.
|
||||
var dlgSoftFloat64FPMulX = new SoftFloat64FPMulX(SoftFloat64.FPMulX);
|
||||
var dlgSoftFloat64FPNegMulAdd = new SoftFloat64FPNegMulAdd(SoftFloat64.FPNegMulAdd);
|
||||
var dlgSoftFloat64FPNegMulSub = new SoftFloat64FPNegMulSub(SoftFloat64.FPNegMulSub);
|
||||
var dlgSoftFloat64FPRecipEstimate = new SoftFloat64FPRecipEstimate(SoftFloat64.FPRecipEstimate);
|
||||
var dlgSoftFloat64FPRecipEstimateFpscr = new SoftFloat64FPRecipEstimateFpscr(SoftFloat64.FPRecipEstimateFpscr); // A32 only.
|
||||
var dlgSoftFloat64FPRecipStep = new SoftFloat64FPRecipStep(SoftFloat64.FPRecipStep); // A32 only.
|
||||
var dlgSoftFloat64FPRecipStepFused = new SoftFloat64FPRecipStepFused(SoftFloat64.FPRecipStepFused);
|
||||
var dlgSoftFloat64FPRecpX = new SoftFloat64FPRecpX(SoftFloat64.FPRecpX);
|
||||
var dlgSoftFloat64FPRSqrtEstimate = new SoftFloat64FPRSqrtEstimate(SoftFloat64.FPRSqrtEstimate);
|
||||
var dlgSoftFloat64FPRSqrtEstimateFpscr = new SoftFloat64FPRSqrtEstimateFpscr(SoftFloat64.FPRSqrtEstimateFpscr); // A32 only.
|
||||
var dlgSoftFloat64FPRSqrtStep = new SoftFloat64FPRSqrtStep(SoftFloat64.FPRSqrtStep); // A32 only.
|
||||
var dlgSoftFloat64FPRSqrtStepFused = new SoftFloat64FPRSqrtStepFused(SoftFloat64.FPRSqrtStepFused);
|
||||
var dlgSoftFloat64FPSqrt = new SoftFloat64FPSqrt(SoftFloat64.FPSqrt);
|
||||
var dlgSoftFloat64FPSub = new SoftFloat64FPSub(SoftFloat64.FPSub);
|
||||
|
||||
SetDelegateInfo(new SoftFloat64_16FPConvert(SoftFloat64_16.FPConvert));
|
||||
var dlgSoftFloat64_16FPConvert = new SoftFloat64_16FPConvert(SoftFloat64_16.FPConvert);
|
||||
|
||||
SetDelegateInfo(dlgMathAbs, Marshal.GetFunctionPointerForDelegate<MathAbs>(dlgMathAbs));
|
||||
SetDelegateInfo(dlgMathCeiling, Marshal.GetFunctionPointerForDelegate<MathCeiling>(dlgMathCeiling));
|
||||
SetDelegateInfo(dlgMathFloor, Marshal.GetFunctionPointerForDelegate<MathFloor>(dlgMathFloor));
|
||||
SetDelegateInfo(dlgMathRound, Marshal.GetFunctionPointerForDelegate<MathRound>(dlgMathRound));
|
||||
SetDelegateInfo(dlgMathTruncate, Marshal.GetFunctionPointerForDelegate<MathTruncate>(dlgMathTruncate));
|
||||
|
||||
SetDelegateInfo(dlgMathFAbs, Marshal.GetFunctionPointerForDelegate<MathFAbs>(dlgMathFAbs));
|
||||
SetDelegateInfo(dlgMathFCeiling, Marshal.GetFunctionPointerForDelegate<MathFCeiling>(dlgMathFCeiling));
|
||||
SetDelegateInfo(dlgMathFFloor, Marshal.GetFunctionPointerForDelegate<MathFFloor>(dlgMathFFloor));
|
||||
SetDelegateInfo(dlgMathFRound, Marshal.GetFunctionPointerForDelegate<MathFRound>(dlgMathFRound));
|
||||
SetDelegateInfo(dlgMathFTruncate, Marshal.GetFunctionPointerForDelegate<MathFTruncate>(dlgMathFTruncate));
|
||||
|
||||
SetDelegateInfo(dlgNativeInterfaceBreak, Marshal.GetFunctionPointerForDelegate<NativeInterfaceBreak>(dlgNativeInterfaceBreak));
|
||||
SetDelegateInfo(dlgNativeInterfaceCheckSynchronization, Marshal.GetFunctionPointerForDelegate<NativeInterfaceCheckSynchronization>(dlgNativeInterfaceCheckSynchronization));
|
||||
SetDelegateInfo(dlgNativeInterfaceEnqueueForRejit, Marshal.GetFunctionPointerForDelegate<NativeInterfaceEnqueueForRejit>(dlgNativeInterfaceEnqueueForRejit));
|
||||
SetDelegateInfo(dlgNativeInterfaceGetCntfrqEl0, Marshal.GetFunctionPointerForDelegate<NativeInterfaceGetCntfrqEl0>(dlgNativeInterfaceGetCntfrqEl0));
|
||||
SetDelegateInfo(dlgNativeInterfaceGetCntpctEl0, Marshal.GetFunctionPointerForDelegate<NativeInterfaceGetCntpctEl0>(dlgNativeInterfaceGetCntpctEl0));
|
||||
SetDelegateInfo(dlgNativeInterfaceGetCntvctEl0, Marshal.GetFunctionPointerForDelegate<NativeInterfaceGetCntvctEl0>(dlgNativeInterfaceGetCntvctEl0));
|
||||
SetDelegateInfo(dlgNativeInterfaceGetCtrEl0, Marshal.GetFunctionPointerForDelegate<NativeInterfaceGetCtrEl0>(dlgNativeInterfaceGetCtrEl0));
|
||||
SetDelegateInfo(dlgNativeInterfaceGetDczidEl0, Marshal.GetFunctionPointerForDelegate<NativeInterfaceGetDczidEl0>(dlgNativeInterfaceGetDczidEl0));
|
||||
SetDelegateInfo(dlgNativeInterfaceGetFunctionAddress, Marshal.GetFunctionPointerForDelegate<NativeInterfaceGetFunctionAddress>(dlgNativeInterfaceGetFunctionAddress));
|
||||
SetDelegateInfo(dlgNativeInterfaceInvalidateCacheLine, Marshal.GetFunctionPointerForDelegate<NativeInterfaceInvalidateCacheLine>(dlgNativeInterfaceInvalidateCacheLine));
|
||||
SetDelegateInfo(dlgNativeInterfaceReadByte, Marshal.GetFunctionPointerForDelegate<NativeInterfaceReadByte>(dlgNativeInterfaceReadByte));
|
||||
SetDelegateInfo(dlgNativeInterfaceReadUInt16, Marshal.GetFunctionPointerForDelegate<NativeInterfaceReadUInt16>(dlgNativeInterfaceReadUInt16));
|
||||
SetDelegateInfo(dlgNativeInterfaceReadUInt32, Marshal.GetFunctionPointerForDelegate<NativeInterfaceReadUInt32>(dlgNativeInterfaceReadUInt32));
|
||||
SetDelegateInfo(dlgNativeInterfaceReadUInt64, Marshal.GetFunctionPointerForDelegate<NativeInterfaceReadUInt64>(dlgNativeInterfaceReadUInt64));
|
||||
SetDelegateInfo(dlgNativeInterfaceReadVector128, Marshal.GetFunctionPointerForDelegate<NativeInterfaceReadVector128>(dlgNativeInterfaceReadVector128));
|
||||
SetDelegateInfo(dlgNativeInterfaceSignalMemoryTracking, Marshal.GetFunctionPointerForDelegate<NativeInterfaceSignalMemoryTracking>(dlgNativeInterfaceSignalMemoryTracking));
|
||||
SetDelegateInfo(dlgNativeInterfaceSupervisorCall, Marshal.GetFunctionPointerForDelegate<NativeInterfaceSupervisorCall>(dlgNativeInterfaceSupervisorCall));
|
||||
SetDelegateInfo(dlgNativeInterfaceThrowInvalidMemoryAccess, Marshal.GetFunctionPointerForDelegate<NativeInterfaceThrowInvalidMemoryAccess>(dlgNativeInterfaceThrowInvalidMemoryAccess));
|
||||
SetDelegateInfo(dlgNativeInterfaceUndefined, Marshal.GetFunctionPointerForDelegate<NativeInterfaceUndefined>(dlgNativeInterfaceUndefined));
|
||||
SetDelegateInfo(dlgNativeInterfaceWriteByte, Marshal.GetFunctionPointerForDelegate<NativeInterfaceWriteByte>(dlgNativeInterfaceWriteByte));
|
||||
SetDelegateInfo(dlgNativeInterfaceWriteUInt16, Marshal.GetFunctionPointerForDelegate<NativeInterfaceWriteUInt16>(dlgNativeInterfaceWriteUInt16));
|
||||
SetDelegateInfo(dlgNativeInterfaceWriteUInt32, Marshal.GetFunctionPointerForDelegate<NativeInterfaceWriteUInt32>(dlgNativeInterfaceWriteUInt32));
|
||||
SetDelegateInfo(dlgNativeInterfaceWriteUInt64, Marshal.GetFunctionPointerForDelegate<NativeInterfaceWriteUInt64>(dlgNativeInterfaceWriteUInt64));
|
||||
SetDelegateInfo(dlgNativeInterfaceWriteVector128, Marshal.GetFunctionPointerForDelegate<NativeInterfaceWriteVector128>(dlgNativeInterfaceWriteVector128));
|
||||
|
||||
SetDelegateInfo(dlgSoftFallbackCountLeadingSigns, Marshal.GetFunctionPointerForDelegate<SoftFallbackCountLeadingSigns>(dlgSoftFallbackCountLeadingSigns));
|
||||
SetDelegateInfo(dlgSoftFallbackCountLeadingZeros, Marshal.GetFunctionPointerForDelegate<SoftFallbackCountLeadingZeros>(dlgSoftFallbackCountLeadingZeros));
|
||||
SetDelegateInfo(dlgSoftFallbackCrc32b, Marshal.GetFunctionPointerForDelegate<SoftFallbackCrc32b>(dlgSoftFallbackCrc32b));
|
||||
SetDelegateInfo(dlgSoftFallbackCrc32cb, Marshal.GetFunctionPointerForDelegate<SoftFallbackCrc32cb>(dlgSoftFallbackCrc32cb));
|
||||
SetDelegateInfo(dlgSoftFallbackCrc32ch, Marshal.GetFunctionPointerForDelegate<SoftFallbackCrc32ch>(dlgSoftFallbackCrc32ch));
|
||||
SetDelegateInfo(dlgSoftFallbackCrc32cw, Marshal.GetFunctionPointerForDelegate<SoftFallbackCrc32cw>(dlgSoftFallbackCrc32cw));
|
||||
SetDelegateInfo(dlgSoftFallbackCrc32cx, Marshal.GetFunctionPointerForDelegate<SoftFallbackCrc32cx>(dlgSoftFallbackCrc32cx));
|
||||
SetDelegateInfo(dlgSoftFallbackCrc32h, Marshal.GetFunctionPointerForDelegate<SoftFallbackCrc32h>(dlgSoftFallbackCrc32h));
|
||||
SetDelegateInfo(dlgSoftFallbackCrc32w, Marshal.GetFunctionPointerForDelegate<SoftFallbackCrc32w>(dlgSoftFallbackCrc32w));
|
||||
SetDelegateInfo(dlgSoftFallbackCrc32x, Marshal.GetFunctionPointerForDelegate<SoftFallbackCrc32x>(dlgSoftFallbackCrc32x));
|
||||
SetDelegateInfo(dlgSoftFallbackDecrypt, Marshal.GetFunctionPointerForDelegate<SoftFallbackDecrypt>(dlgSoftFallbackDecrypt));
|
||||
SetDelegateInfo(dlgSoftFallbackEncrypt, Marshal.GetFunctionPointerForDelegate<SoftFallbackEncrypt>(dlgSoftFallbackEncrypt));
|
||||
SetDelegateInfo(dlgSoftFallbackFixedRotate, Marshal.GetFunctionPointerForDelegate<SoftFallbackFixedRotate>(dlgSoftFallbackFixedRotate));
|
||||
SetDelegateInfo(dlgSoftFallbackHashChoose, Marshal.GetFunctionPointerForDelegate<SoftFallbackHashChoose>(dlgSoftFallbackHashChoose));
|
||||
SetDelegateInfo(dlgSoftFallbackHashLower, Marshal.GetFunctionPointerForDelegate<SoftFallbackHashLower>(dlgSoftFallbackHashLower));
|
||||
SetDelegateInfo(dlgSoftFallbackHashMajority, Marshal.GetFunctionPointerForDelegate<SoftFallbackHashMajority>(dlgSoftFallbackHashMajority));
|
||||
SetDelegateInfo(dlgSoftFallbackHashParity, Marshal.GetFunctionPointerForDelegate<SoftFallbackHashParity>(dlgSoftFallbackHashParity));
|
||||
SetDelegateInfo(dlgSoftFallbackHashUpper, Marshal.GetFunctionPointerForDelegate<SoftFallbackHashUpper>(dlgSoftFallbackHashUpper));
|
||||
SetDelegateInfo(dlgSoftFallbackInverseMixColumns, Marshal.GetFunctionPointerForDelegate<SoftFallbackInverseMixColumns>(dlgSoftFallbackInverseMixColumns));
|
||||
SetDelegateInfo(dlgSoftFallbackMixColumns, Marshal.GetFunctionPointerForDelegate<SoftFallbackMixColumns>(dlgSoftFallbackMixColumns));
|
||||
SetDelegateInfo(dlgSoftFallbackPolynomialMult64_128, Marshal.GetFunctionPointerForDelegate<SoftFallbackPolynomialMult64_128>(dlgSoftFallbackPolynomialMult64_128));
|
||||
SetDelegateInfo(dlgSoftFallbackSatF32ToS32, Marshal.GetFunctionPointerForDelegate<SoftFallbackSatF32ToS32>(dlgSoftFallbackSatF32ToS32));
|
||||
SetDelegateInfo(dlgSoftFallbackSatF32ToS64, Marshal.GetFunctionPointerForDelegate<SoftFallbackSatF32ToS64>(dlgSoftFallbackSatF32ToS64));
|
||||
SetDelegateInfo(dlgSoftFallbackSatF32ToU32, Marshal.GetFunctionPointerForDelegate<SoftFallbackSatF32ToU32>(dlgSoftFallbackSatF32ToU32));
|
||||
SetDelegateInfo(dlgSoftFallbackSatF32ToU64, Marshal.GetFunctionPointerForDelegate<SoftFallbackSatF32ToU64>(dlgSoftFallbackSatF32ToU64));
|
||||
SetDelegateInfo(dlgSoftFallbackSatF64ToS32, Marshal.GetFunctionPointerForDelegate<SoftFallbackSatF64ToS32>(dlgSoftFallbackSatF64ToS32));
|
||||
SetDelegateInfo(dlgSoftFallbackSatF64ToS64, Marshal.GetFunctionPointerForDelegate<SoftFallbackSatF64ToS64>(dlgSoftFallbackSatF64ToS64));
|
||||
SetDelegateInfo(dlgSoftFallbackSatF64ToU32, Marshal.GetFunctionPointerForDelegate<SoftFallbackSatF64ToU32>(dlgSoftFallbackSatF64ToU32));
|
||||
SetDelegateInfo(dlgSoftFallbackSatF64ToU64, Marshal.GetFunctionPointerForDelegate<SoftFallbackSatF64ToU64>(dlgSoftFallbackSatF64ToU64));
|
||||
SetDelegateInfo(dlgSoftFallbackSha1SchedulePart1, Marshal.GetFunctionPointerForDelegate<SoftFallbackSha1SchedulePart1>(dlgSoftFallbackSha1SchedulePart1));
|
||||
SetDelegateInfo(dlgSoftFallbackSha1SchedulePart2, Marshal.GetFunctionPointerForDelegate<SoftFallbackSha1SchedulePart2>(dlgSoftFallbackSha1SchedulePart2));
|
||||
SetDelegateInfo(dlgSoftFallbackSha256SchedulePart1, Marshal.GetFunctionPointerForDelegate<SoftFallbackSha256SchedulePart1>(dlgSoftFallbackSha256SchedulePart1));
|
||||
SetDelegateInfo(dlgSoftFallbackSha256SchedulePart2, Marshal.GetFunctionPointerForDelegate<SoftFallbackSha256SchedulePart2>(dlgSoftFallbackSha256SchedulePart2));
|
||||
SetDelegateInfo(dlgSoftFallbackSignedShrImm64, Marshal.GetFunctionPointerForDelegate<SoftFallbackSignedShrImm64>(dlgSoftFallbackSignedShrImm64));
|
||||
SetDelegateInfo(dlgSoftFallbackTbl1, Marshal.GetFunctionPointerForDelegate<SoftFallbackTbl1>(dlgSoftFallbackTbl1));
|
||||
SetDelegateInfo(dlgSoftFallbackTbl2, Marshal.GetFunctionPointerForDelegate<SoftFallbackTbl2>(dlgSoftFallbackTbl2));
|
||||
SetDelegateInfo(dlgSoftFallbackTbl3, Marshal.GetFunctionPointerForDelegate<SoftFallbackTbl3>(dlgSoftFallbackTbl3));
|
||||
SetDelegateInfo(dlgSoftFallbackTbl4, Marshal.GetFunctionPointerForDelegate<SoftFallbackTbl4>(dlgSoftFallbackTbl4));
|
||||
SetDelegateInfo(dlgSoftFallbackTbx1, Marshal.GetFunctionPointerForDelegate<SoftFallbackTbx1>(dlgSoftFallbackTbx1));
|
||||
SetDelegateInfo(dlgSoftFallbackTbx2, Marshal.GetFunctionPointerForDelegate<SoftFallbackTbx2>(dlgSoftFallbackTbx2));
|
||||
SetDelegateInfo(dlgSoftFallbackTbx3, Marshal.GetFunctionPointerForDelegate<SoftFallbackTbx3>(dlgSoftFallbackTbx3));
|
||||
SetDelegateInfo(dlgSoftFallbackTbx4, Marshal.GetFunctionPointerForDelegate<SoftFallbackTbx4>(dlgSoftFallbackTbx4));
|
||||
SetDelegateInfo(dlgSoftFallbackUnsignedShrImm64, Marshal.GetFunctionPointerForDelegate<SoftFallbackUnsignedShrImm64>(dlgSoftFallbackUnsignedShrImm64));
|
||||
|
||||
SetDelegateInfo(dlgSoftFloat16_32FPConvert, Marshal.GetFunctionPointerForDelegate<SoftFloat16_32FPConvert>(dlgSoftFloat16_32FPConvert));
|
||||
SetDelegateInfo(dlgSoftFloat16_64FPConvert, Marshal.GetFunctionPointerForDelegate<SoftFloat16_64FPConvert>(dlgSoftFloat16_64FPConvert));
|
||||
|
||||
SetDelegateInfo(dlgSoftFloat32FPAdd, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPAdd>(dlgSoftFloat32FPAdd));
|
||||
SetDelegateInfo(dlgSoftFloat32FPAddFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPAddFpscr>(dlgSoftFloat32FPAddFpscr)); // A32 only.
|
||||
SetDelegateInfo(dlgSoftFloat32FPCompare, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompare>(dlgSoftFloat32FPCompare));
|
||||
SetDelegateInfo(dlgSoftFloat32FPCompareEQ, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompareEQ>(dlgSoftFloat32FPCompareEQ));
|
||||
SetDelegateInfo(dlgSoftFloat32FPCompareEQFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompareEQFpscr>(dlgSoftFloat32FPCompareEQFpscr)); // A32 only.
|
||||
SetDelegateInfo(dlgSoftFloat32FPCompareGE, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompareGE>(dlgSoftFloat32FPCompareGE));
|
||||
SetDelegateInfo(dlgSoftFloat32FPCompareGEFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompareGEFpscr>(dlgSoftFloat32FPCompareGEFpscr)); // A32 only.
|
||||
SetDelegateInfo(dlgSoftFloat32FPCompareGT, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompareGT>(dlgSoftFloat32FPCompareGT));
|
||||
SetDelegateInfo(dlgSoftFloat32FPCompareGTFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompareGTFpscr>(dlgSoftFloat32FPCompareGTFpscr)); // A32 only.
|
||||
SetDelegateInfo(dlgSoftFloat32FPCompareLE, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompareLE>(dlgSoftFloat32FPCompareLE));
|
||||
SetDelegateInfo(dlgSoftFloat32FPCompareLEFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompareLEFpscr>(dlgSoftFloat32FPCompareLEFpscr)); // A32 only.
|
||||
SetDelegateInfo(dlgSoftFloat32FPCompareLT, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompareLT>(dlgSoftFloat32FPCompareLT));
|
||||
SetDelegateInfo(dlgSoftFloat32FPCompareLTFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompareLTFpscr>(dlgSoftFloat32FPCompareLTFpscr)); // A32 only.
|
||||
SetDelegateInfo(dlgSoftFloat32FPDiv, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPDiv>(dlgSoftFloat32FPDiv));
|
||||
SetDelegateInfo(dlgSoftFloat32FPMax, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMax>(dlgSoftFloat32FPMax));
|
||||
SetDelegateInfo(dlgSoftFloat32FPMaxFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMaxFpscr>(dlgSoftFloat32FPMaxFpscr)); // A32 only.
|
||||
SetDelegateInfo(dlgSoftFloat32FPMaxNum, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMaxNum>(dlgSoftFloat32FPMaxNum));
|
||||
SetDelegateInfo(dlgSoftFloat32FPMaxNumFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMaxNumFpscr>(dlgSoftFloat32FPMaxNumFpscr)); // A32 only.
|
||||
SetDelegateInfo(dlgSoftFloat32FPMin, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMin>(dlgSoftFloat32FPMin));
|
||||
SetDelegateInfo(dlgSoftFloat32FPMinFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMinFpscr>(dlgSoftFloat32FPMinFpscr)); // A32 only.
|
||||
SetDelegateInfo(dlgSoftFloat32FPMinNum, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMinNum>(dlgSoftFloat32FPMinNum));
|
||||
SetDelegateInfo(dlgSoftFloat32FPMinNumFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMinNumFpscr>(dlgSoftFloat32FPMinNumFpscr)); // A32 only.
|
||||
SetDelegateInfo(dlgSoftFloat32FPMul, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMul>(dlgSoftFloat32FPMul));
|
||||
SetDelegateInfo(dlgSoftFloat32FPMulFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMulFpscr>(dlgSoftFloat32FPMulFpscr)); // A32 only.
|
||||
SetDelegateInfo(dlgSoftFloat32FPMulAdd, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMulAdd>(dlgSoftFloat32FPMulAdd));
|
||||
SetDelegateInfo(dlgSoftFloat32FPMulAddFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMulAddFpscr>(dlgSoftFloat32FPMulAddFpscr)); // A32 only.
|
||||
SetDelegateInfo(dlgSoftFloat32FPMulSub, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMulSub>(dlgSoftFloat32FPMulSub));
|
||||
SetDelegateInfo(dlgSoftFloat32FPMulSubFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMulSubFpscr>(dlgSoftFloat32FPMulSubFpscr)); // A32 only.
|
||||
SetDelegateInfo(dlgSoftFloat32FPMulX, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMulX>(dlgSoftFloat32FPMulX));
|
||||
SetDelegateInfo(dlgSoftFloat32FPNegMulAdd, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPNegMulAdd>(dlgSoftFloat32FPNegMulAdd));
|
||||
SetDelegateInfo(dlgSoftFloat32FPNegMulSub, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPNegMulSub>(dlgSoftFloat32FPNegMulSub));
|
||||
SetDelegateInfo(dlgSoftFloat32FPRecipEstimate, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPRecipEstimate>(dlgSoftFloat32FPRecipEstimate));
|
||||
SetDelegateInfo(dlgSoftFloat32FPRecipEstimateFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPRecipEstimateFpscr>(dlgSoftFloat32FPRecipEstimateFpscr)); // A32 only.
|
||||
SetDelegateInfo(dlgSoftFloat32FPRecipStep, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPRecipStep>(dlgSoftFloat32FPRecipStep)); // A32 only.
|
||||
SetDelegateInfo(dlgSoftFloat32FPRecipStepFused, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPRecipStepFused>(dlgSoftFloat32FPRecipStepFused));
|
||||
SetDelegateInfo(dlgSoftFloat32FPRecpX, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPRecpX>(dlgSoftFloat32FPRecpX));
|
||||
SetDelegateInfo(dlgSoftFloat32FPRSqrtEstimate, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPRSqrtEstimate>(dlgSoftFloat32FPRSqrtEstimate));
|
||||
SetDelegateInfo(dlgSoftFloat32FPRSqrtEstimateFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPRSqrtEstimateFpscr>(dlgSoftFloat32FPRSqrtEstimateFpscr)); // A32 only.
|
||||
SetDelegateInfo(dlgSoftFloat32FPRSqrtStep, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPRSqrtStep>(dlgSoftFloat32FPRSqrtStep)); // A32 only.
|
||||
SetDelegateInfo(dlgSoftFloat32FPRSqrtStepFused, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPRSqrtStepFused>(dlgSoftFloat32FPRSqrtStepFused));
|
||||
SetDelegateInfo(dlgSoftFloat32FPSqrt, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPSqrt>(dlgSoftFloat32FPSqrt));
|
||||
SetDelegateInfo(dlgSoftFloat32FPSub, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPSub>(dlgSoftFloat32FPSub));
|
||||
|
||||
SetDelegateInfo(dlgSoftFloat32_16FPConvert, Marshal.GetFunctionPointerForDelegate<SoftFloat32_16FPConvert>(dlgSoftFloat32_16FPConvert));
|
||||
|
||||
SetDelegateInfo(dlgSoftFloat64FPAdd, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPAdd>(dlgSoftFloat64FPAdd));
|
||||
SetDelegateInfo(dlgSoftFloat64FPAddFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPAddFpscr>(dlgSoftFloat64FPAddFpscr)); // A32 only.
|
||||
SetDelegateInfo(dlgSoftFloat64FPCompare, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompare>(dlgSoftFloat64FPCompare));
|
||||
SetDelegateInfo(dlgSoftFloat64FPCompareEQ, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompareEQ>(dlgSoftFloat64FPCompareEQ));
|
||||
SetDelegateInfo(dlgSoftFloat64FPCompareEQFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompareEQFpscr>(dlgSoftFloat64FPCompareEQFpscr)); // A32 only.
|
||||
SetDelegateInfo(dlgSoftFloat64FPCompareGE, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompareGE>(dlgSoftFloat64FPCompareGE));
|
||||
SetDelegateInfo(dlgSoftFloat64FPCompareGEFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompareGEFpscr>(dlgSoftFloat64FPCompareGEFpscr)); // A32 only.
|
||||
SetDelegateInfo(dlgSoftFloat64FPCompareGT, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompareGT>(dlgSoftFloat64FPCompareGT));
|
||||
SetDelegateInfo(dlgSoftFloat64FPCompareGTFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompareGTFpscr>(dlgSoftFloat64FPCompareGTFpscr)); // A32 only.
|
||||
SetDelegateInfo(dlgSoftFloat64FPCompareLE, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompareLE>(dlgSoftFloat64FPCompareLE));
|
||||
SetDelegateInfo(dlgSoftFloat64FPCompareLEFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompareLEFpscr>(dlgSoftFloat64FPCompareLEFpscr)); // A32 only.
|
||||
SetDelegateInfo(dlgSoftFloat64FPCompareLT, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompareLT>(dlgSoftFloat64FPCompareLT));
|
||||
SetDelegateInfo(dlgSoftFloat64FPCompareLTFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompareLTFpscr>(dlgSoftFloat64FPCompareLTFpscr)); // A32 only.
|
||||
SetDelegateInfo(dlgSoftFloat64FPDiv, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPDiv>(dlgSoftFloat64FPDiv));
|
||||
SetDelegateInfo(dlgSoftFloat64FPMax, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMax>(dlgSoftFloat64FPMax));
|
||||
SetDelegateInfo(dlgSoftFloat64FPMaxFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMaxFpscr>(dlgSoftFloat64FPMaxFpscr)); // A32 only.
|
||||
SetDelegateInfo(dlgSoftFloat64FPMaxNum, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMaxNum>(dlgSoftFloat64FPMaxNum));
|
||||
SetDelegateInfo(dlgSoftFloat64FPMaxNumFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMaxNumFpscr>(dlgSoftFloat64FPMaxNumFpscr)); // A32 only.
|
||||
SetDelegateInfo(dlgSoftFloat64FPMin, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMin>(dlgSoftFloat64FPMin));
|
||||
SetDelegateInfo(dlgSoftFloat64FPMinFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMinFpscr>(dlgSoftFloat64FPMinFpscr)); // A32 only.
|
||||
SetDelegateInfo(dlgSoftFloat64FPMinNum, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMinNum>(dlgSoftFloat64FPMinNum));
|
||||
SetDelegateInfo(dlgSoftFloat64FPMinNumFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMinNumFpscr>(dlgSoftFloat64FPMinNumFpscr)); // A32 only.
|
||||
SetDelegateInfo(dlgSoftFloat64FPMul, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMul>(dlgSoftFloat64FPMul));
|
||||
SetDelegateInfo(dlgSoftFloat64FPMulFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMulFpscr>(dlgSoftFloat64FPMulFpscr)); // A32 only.
|
||||
SetDelegateInfo(dlgSoftFloat64FPMulAdd, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMulAdd>(dlgSoftFloat64FPMulAdd));
|
||||
SetDelegateInfo(dlgSoftFloat64FPMulAddFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMulAddFpscr>(dlgSoftFloat64FPMulAddFpscr)); // A32 only.
|
||||
SetDelegateInfo(dlgSoftFloat64FPMulSub, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMulSub>(dlgSoftFloat64FPMulSub));
|
||||
SetDelegateInfo(dlgSoftFloat64FPMulSubFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMulSubFpscr>(dlgSoftFloat64FPMulSubFpscr)); // A32 only.
|
||||
SetDelegateInfo(dlgSoftFloat64FPMulX, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMulX>(dlgSoftFloat64FPMulX));
|
||||
SetDelegateInfo(dlgSoftFloat64FPNegMulAdd, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPNegMulAdd>(dlgSoftFloat64FPNegMulAdd));
|
||||
SetDelegateInfo(dlgSoftFloat64FPNegMulSub, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPNegMulSub>(dlgSoftFloat64FPNegMulSub));
|
||||
SetDelegateInfo(dlgSoftFloat64FPRecipEstimate, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPRecipEstimate>(dlgSoftFloat64FPRecipEstimate));
|
||||
SetDelegateInfo(dlgSoftFloat64FPRecipEstimateFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPRecipEstimateFpscr>(dlgSoftFloat64FPRecipEstimateFpscr)); // A32 only.
|
||||
SetDelegateInfo(dlgSoftFloat64FPRecipStep, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPRecipStep>(dlgSoftFloat64FPRecipStep)); // A32 only.
|
||||
SetDelegateInfo(dlgSoftFloat64FPRecipStepFused, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPRecipStepFused>(dlgSoftFloat64FPRecipStepFused));
|
||||
SetDelegateInfo(dlgSoftFloat64FPRecpX, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPRecpX>(dlgSoftFloat64FPRecpX));
|
||||
SetDelegateInfo(dlgSoftFloat64FPRSqrtEstimate, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPRSqrtEstimate>(dlgSoftFloat64FPRSqrtEstimate));
|
||||
SetDelegateInfo(dlgSoftFloat64FPRSqrtEstimateFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPRSqrtEstimateFpscr>(dlgSoftFloat64FPRSqrtEstimateFpscr)); // A32 only.
|
||||
SetDelegateInfo(dlgSoftFloat64FPRSqrtStep, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPRSqrtStep>(dlgSoftFloat64FPRSqrtStep)); // A32 only.
|
||||
SetDelegateInfo(dlgSoftFloat64FPRSqrtStepFused, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPRSqrtStepFused>(dlgSoftFloat64FPRSqrtStepFused));
|
||||
SetDelegateInfo(dlgSoftFloat64FPSqrt, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPSqrt>(dlgSoftFloat64FPSqrt));
|
||||
SetDelegateInfo(dlgSoftFloat64FPSub, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPSub>(dlgSoftFloat64FPSub));
|
||||
|
||||
SetDelegateInfo(dlgSoftFloat64_16FPConvert, Marshal.GetFunctionPointerForDelegate<SoftFloat64_16FPConvert>(dlgSoftFloat64_16FPConvert));
|
||||
}
|
||||
|
||||
private delegate double MathAbs(double value);
|
||||
|
@ -8,7 +8,7 @@ namespace ARMeilleure.Translation
|
||||
/// </summary>
|
||||
/// <typeparam name="TK">Key</typeparam>
|
||||
/// <typeparam name="TV">Value</typeparam>
|
||||
class IntervalTree<TK, TV> where TK : IComparable<TK>
|
||||
public class IntervalTree<TK, TV> where TK : IComparable<TK>
|
||||
{
|
||||
private const int ArrayGrowthSize = 32;
|
||||
|
||||
|
@ -3,6 +3,7 @@ using ARMeilleure.CodeGen.Linking;
|
||||
using ARMeilleure.CodeGen.Unwinding;
|
||||
using ARMeilleure.Common;
|
||||
using ARMeilleure.Memory;
|
||||
using ARMeilleure.Translation.Cache;
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Logging;
|
||||
@ -744,7 +745,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
bool highCq)
|
||||
{
|
||||
var cFunc = new CompiledFunction(code, unwindInfo, RelocInfo.Empty);
|
||||
var gFunc = cFunc.MapWithPointer<GuestFunction>(out IntPtr gFuncPointer);
|
||||
var gFunc = cFunc.MapWithPointer<GuestFunction>(out IntPtr gFuncPointer, true);
|
||||
|
||||
return new TranslatedFunction(gFunc, gFuncPointer, callCounter, guestSize, highCq);
|
||||
}
|
||||
@ -826,7 +827,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
|
||||
Debug.Assert(Profiler.IsAddressInStaticCodeRange(address));
|
||||
|
||||
TranslatedFunction func = translator.Translate(address, item.funcProfile.Mode, item.funcProfile.HighCq);
|
||||
TranslatedFunction func = translator.Translate(address, item.funcProfile.Mode, item.funcProfile.HighCq, deferProtect: true);
|
||||
|
||||
bool isAddressUnique = translator.Functions.TryAdd(address, func.GuestSize, func);
|
||||
|
||||
@ -1004,6 +1005,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
osPlatform |= (OperatingSystem.IsLinux() ? 1u : 0u) << 1;
|
||||
osPlatform |= (OperatingSystem.IsMacOS() ? 1u : 0u) << 2;
|
||||
osPlatform |= (OperatingSystem.IsWindows() ? 1u : 0u) << 3;
|
||||
osPlatform |= (OperatingSystem.IsIOS() ? 1u : 0u) << 4;
|
||||
#pragma warning restore IDE0055
|
||||
|
||||
return osPlatform;
|
||||
|
@ -76,11 +76,11 @@ namespace ARMeilleure.Translation
|
||||
CountTable = new EntryTable<uint>();
|
||||
Functions = new TranslatorCache<TranslatedFunction>();
|
||||
FunctionTable = new AddressTable<ulong>(for64Bits ? _levels64Bit : _levels32Bit);
|
||||
Stubs = new TranslatorStubs(this);
|
||||
Stubs = new TranslatorStubs(FunctionTable);
|
||||
|
||||
FunctionTable.Fill = (ulong)Stubs.SlowDispatchStub;
|
||||
|
||||
if (memory.Type.IsHostMapped())
|
||||
if (memory.Type.IsHostMappedOrTracked())
|
||||
{
|
||||
NativeSignalHandler.InitializeSignalHandler(allocator.GetPageSize());
|
||||
}
|
||||
@ -112,6 +112,8 @@ namespace ARMeilleure.Translation
|
||||
Debug.Assert(Functions.Count == 0);
|
||||
_ptc.LoadTranslations(this);
|
||||
_ptc.MakeAndSaveTranslations(this);
|
||||
|
||||
JitCache.RunDeferredRxProtects();
|
||||
}
|
||||
|
||||
_ptc.Profiler.Start();
|
||||
@ -250,7 +252,7 @@ namespace ARMeilleure.Translation
|
||||
}
|
||||
}
|
||||
|
||||
internal TranslatedFunction Translate(ulong address, ExecutionMode mode, bool highCq, bool singleStep = false)
|
||||
internal TranslatedFunction Translate(ulong address, ExecutionMode mode, bool highCq, bool singleStep = false, bool deferProtect = false)
|
||||
{
|
||||
var context = new ArmEmitterContext(
|
||||
Memory,
|
||||
@ -308,7 +310,7 @@ namespace ARMeilleure.Translation
|
||||
_ptc.WriteCompiledFunction(address, funcSize, hash, highCq, compiledFunc);
|
||||
}
|
||||
|
||||
GuestFunction func = compiledFunc.MapWithPointer<GuestFunction>(out IntPtr funcPointer);
|
||||
GuestFunction func = compiledFunc.MapWithPointer<GuestFunction>(out IntPtr funcPointer, deferProtect);
|
||||
|
||||
Allocators.ResetAll();
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
using ARMeilleure.Common;
|
||||
using ARMeilleure.Instructions;
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.State;
|
||||
@ -14,11 +15,11 @@ namespace ARMeilleure.Translation
|
||||
/// </summary>
|
||||
class TranslatorStubs : IDisposable
|
||||
{
|
||||
private static readonly Lazy<IntPtr> _slowDispatchStub = new(GenerateSlowDispatchStub, isThreadSafe: true);
|
||||
private readonly Lazy<IntPtr> _slowDispatchStub;
|
||||
|
||||
private bool _disposed;
|
||||
|
||||
private readonly Translator _translator;
|
||||
private readonly AddressTable<ulong> _functionTable;
|
||||
private readonly Lazy<IntPtr> _dispatchStub;
|
||||
private readonly Lazy<DispatcherFunction> _dispatchLoop;
|
||||
private readonly Lazy<WrapperFunction> _contextWrapper;
|
||||
@ -83,13 +84,14 @@ namespace ARMeilleure.Translation
|
||||
/// Initializes a new instance of the <see cref="TranslatorStubs"/> class with the specified
|
||||
/// <see cref="Translator"/> instance.
|
||||
/// </summary>
|
||||
/// <param name="translator"><see cref="Translator"/> instance to use</param>
|
||||
/// <param name="functionTable">Function table used to store pointers to the functions that the guest code will call</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="translator"/> is null</exception>
|
||||
public TranslatorStubs(Translator translator)
|
||||
public TranslatorStubs(AddressTable<ulong> functionTable)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(translator);
|
||||
ArgumentNullException.ThrowIfNull(functionTable);
|
||||
|
||||
_translator = translator;
|
||||
_functionTable = functionTable;
|
||||
_slowDispatchStub = new(GenerateSlowDispatchStub, isThreadSafe: true);
|
||||
_dispatchStub = new(GenerateDispatchStub, isThreadSafe: true);
|
||||
_dispatchLoop = new(GenerateDispatchLoop, isThreadSafe: true);
|
||||
_contextWrapper = new(GenerateContextWrapper, isThreadSafe: true);
|
||||
@ -151,15 +153,15 @@ namespace ARMeilleure.Translation
|
||||
context.Add(nativeContext, Const((ulong)NativeContext.GetDispatchAddressOffset())));
|
||||
|
||||
// Check if guest address is within range of the AddressTable.
|
||||
Operand masked = context.BitwiseAnd(guestAddress, Const(~_translator.FunctionTable.Mask));
|
||||
Operand masked = context.BitwiseAnd(guestAddress, Const(~_functionTable.Mask));
|
||||
context.BranchIfTrue(lblFallback, masked);
|
||||
|
||||
Operand index = default;
|
||||
Operand page = Const((long)_translator.FunctionTable.Base);
|
||||
Operand page = Const((long)_functionTable.Base);
|
||||
|
||||
for (int i = 0; i < _translator.FunctionTable.Levels.Length; i++)
|
||||
for (int i = 0; i < _functionTable.Levels.Length; i++)
|
||||
{
|
||||
ref var level = ref _translator.FunctionTable.Levels[i];
|
||||
ref var level = ref _functionTable.Levels[i];
|
||||
|
||||
// level.Mask is not used directly because it is more often bigger than 32-bits, so it will not
|
||||
// be encoded as an immediate on x86's bitwise and operation.
|
||||
@ -167,7 +169,7 @@ namespace ARMeilleure.Translation
|
||||
|
||||
index = context.BitwiseAnd(context.ShiftRightUI(guestAddress, Const(level.Index)), mask);
|
||||
|
||||
if (i < _translator.FunctionTable.Levels.Length - 1)
|
||||
if (i < _functionTable.Levels.Length - 1)
|
||||
{
|
||||
page = context.Load(OperandType.I64, context.Add(page, context.ShiftLeft(index, Const(3))));
|
||||
context.BranchIfFalse(lblFallback, page);
|
||||
@ -196,7 +198,7 @@ namespace ARMeilleure.Translation
|
||||
/// Generates a <see cref="SlowDispatchStub"/>.
|
||||
/// </summary>
|
||||
/// <returns>Generated <see cref="SlowDispatchStub"/></returns>
|
||||
private static IntPtr GenerateSlowDispatchStub()
|
||||
private IntPtr GenerateSlowDispatchStub()
|
||||
{
|
||||
var context = new EmitterContext();
|
||||
|
||||
@ -205,8 +207,7 @@ namespace ARMeilleure.Translation
|
||||
Operand guestAddress = context.Load(OperandType.I64,
|
||||
context.Add(nativeContext, Const((ulong)NativeContext.GetDispatchAddressOffset())));
|
||||
|
||||
MethodInfo getFuncAddress = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFunctionAddress));
|
||||
Operand hostAddress = context.Call(getFuncAddress, guestAddress);
|
||||
Operand hostAddress = context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFunctionAddress)), guestAddress);
|
||||
context.Tailcall(hostAddress, nativeContext);
|
||||
|
||||
var cfg = context.GetControlFlowGraph();
|
||||
|
1267
src/MeloNX/MeloNX.xcodeproj/project.pbxproj
Normal file
1267
src/MeloNX/MeloNX.xcodeproj/project.pbxproj
Normal file
File diff suppressed because it is too large
Load Diff
7
src/MeloNX/MeloNX.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
7
src/MeloNX/MeloNX.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:">
|
||||
</FileRef>
|
||||
</Workspace>
|
@ -0,0 +1,24 @@
|
||||
{
|
||||
"originHash" : "1b46f7a56d6f994a826e31441c25b929398800cf38b3e9be23ae6e0ef8fc32c7",
|
||||
"pins" : [
|
||||
{
|
||||
"identity" : "swiftsvg",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/mchoe/SwiftSVG",
|
||||
"state" : {
|
||||
"branch" : "master",
|
||||
"revision" : "88b9ee086b29019e35f6f49c8e30e5552eb8fa9d"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "swiftuijoystick",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/michael94ellis/SwiftUIJoystick",
|
||||
"state" : {
|
||||
"revision" : "5bd303cdafb369a70a45c902538b42dd3c5f4d65",
|
||||
"version" : "1.5.0"
|
||||
}
|
||||
}
|
||||
],
|
||||
"version" : 3
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<array/>
|
||||
</plist>
|
Binary file not shown.
Binary file not shown.
BIN
src/MeloNX/MeloNX.xcodeproj/project.xcworkspace/xcuserdata/ls.xcuserdatad/UserInterfaceState.xcuserstate
generated
Normal file
BIN
src/MeloNX/MeloNX.xcodeproj/project.xcworkspace/xcuserdata/ls.xcuserdatad/UserInterfaceState.xcuserstate
generated
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,104 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1610"
|
||||
version = "1.7">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES"
|
||||
buildArchitectures = "Automatic">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "4E80A98C2CD6F54500029585"
|
||||
BuildableName = "MeloNX.app"
|
||||
BlueprintName = "MeloNX"
|
||||
ReferencedContainer = "container:MeloNX.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
shouldAutocreateTestPlan = "YES">
|
||||
<Testables>
|
||||
<TestableReference
|
||||
skipped = "NO"
|
||||
parallelizable = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "4E80A99C2CD6F54700029585"
|
||||
BuildableName = "MeloNXTests.xctest"
|
||||
BlueprintName = "MeloNXTests"
|
||||
ReferencedContainer = "container:MeloNX.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
<TestableReference
|
||||
skipped = "NO"
|
||||
parallelizable = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "4E80A9A62CD6F54700029585"
|
||||
BuildableName = "MeloNXUITests.xctest"
|
||||
BlueprintName = "MeloNXUITests"
|
||||
ReferencedContainer = "container:MeloNX.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Release"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
enableGPUValidationMode = "1"
|
||||
showGraphicsOverview = "Yes"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "4E80A98C2CD6F54500029585"
|
||||
BuildableName = "MeloNX.app"
|
||||
BlueprintName = "MeloNX"
|
||||
ReferencedContainer = "container:MeloNX.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "4E80A98C2CD6F54500029585"
|
||||
BuildableName = "MeloNX.app"
|
||||
BlueprintName = "MeloNX"
|
||||
ReferencedContainer = "container:MeloNX.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>SchemeUserState</key>
|
||||
<dict>
|
||||
<key>MeloNX.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<key>Ryujinx.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>3</integer>
|
||||
</dict>
|
||||
<key>com.Stossy11.MeloNX.RyujinxAg.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>4</integer>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Bucket
|
||||
uuid = "271EB822-2830-4016-A3D7-CA2DEBEDCD27"
|
||||
type = "1"
|
||||
version = "2.0">
|
||||
<Breakpoints>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
uuid = "499F5405-B63B-4623-9332-1E44FC449FD0"
|
||||
shouldBeEnabled = "No"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "MeloNX/Views/GamesList/GameListView.swift"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "309"
|
||||
endingLineNumber = "309"
|
||||
landmarkName = "loadGames()"
|
||||
landmarkType = "7">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
uuid = "0BB7C122-8933-48E8-ABA3-1ABB39594258"
|
||||
shouldBeEnabled = "No"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "MeloNX/Models/Game.swift"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "37"
|
||||
endingLineNumber = "37"
|
||||
landmarkName = "createImage(from:)"
|
||||
landmarkType = "7">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
</Breakpoints>
|
||||
</Bucket>
|
@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>SchemeUserState</key>
|
||||
<dict>
|
||||
<key>MeloNX.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<key>Ryujinx.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>2</integer>
|
||||
</dict>
|
||||
<key>com.Stossy11.MeloNX.RyujinxAg.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>1</integer>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>SuppressBuildableAutocreation</key>
|
||||
<dict>
|
||||
<key>4E80A98C2CD6F54500029585</key>
|
||||
<dict>
|
||||
<key>primary</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>4E80A99C2CD6F54700029585</key>
|
||||
<dict>
|
||||
<key>primary</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>4E80A9A62CD6F54700029585</key>
|
||||
<dict>
|
||||
<key>primary</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>SchemeUserState</key>
|
||||
<dict>
|
||||
<key>MeloNX.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<key>Ryujinx.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>2</integer>
|
||||
</dict>
|
||||
<key>com.Stossy11.MeloNX.RyujinxAg.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>1</integer>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
49
src/MeloNX/MeloNX/App/Core/Headers/Ryujinx-Header.h
Normal file
49
src/MeloNX/MeloNX/App/Core/Headers/Ryujinx-Header.h
Normal file
@ -0,0 +1,49 @@
|
||||
//
|
||||
// Ryujinx-Header.h
|
||||
// MeloNX
|
||||
//
|
||||
// Created by Stossy11 on 3/11/2024.
|
||||
//
|
||||
|
||||
#ifndef RyujinxHeader
|
||||
#define RyujinxHeader
|
||||
|
||||
|
||||
#import "SDL2/SDL.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct GameInfo {
|
||||
long FileSize;
|
||||
char TitleName[512];
|
||||
long TitleId;
|
||||
char Developer[256];
|
||||
int Version;
|
||||
unsigned char* ImageData;
|
||||
unsigned int ImageSize;
|
||||
};
|
||||
|
||||
extern struct GameInfo get_game_info(int, char*);
|
||||
|
||||
void install_firmware(const char* inputPtr);
|
||||
|
||||
char* installed_firmware_version();
|
||||
|
||||
void stop_emulation();
|
||||
|
||||
int main_ryujinx_sdl(int argc, char **argv);
|
||||
|
||||
int get_current_fps();
|
||||
|
||||
void initialize();
|
||||
|
||||
const char* get_game_controllers();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* RyujinxSDL_h */
|
||||
|
25
src/MeloNX/MeloNX/App/Core/JIT/AskForJIT.swift
Normal file
25
src/MeloNX/MeloNX/App/Core/JIT/AskForJIT.swift
Normal file
@ -0,0 +1,25 @@
|
||||
//
|
||||
// AskForJIT.swift
|
||||
// MeloNX
|
||||
//
|
||||
// Created by Stossy11 on 9/10/2024.
|
||||
// Copyright © 2024 Stossy11. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
|
||||
func askForJIT() {
|
||||
// Check if TrollStore exists by checking the presence of the directory
|
||||
let urlScheme = "apple-magnifier://enable-jit?bundle-id=\(Bundle.main.bundleIdentifier!)"
|
||||
if let launchURL = URL(string: urlScheme) {
|
||||
if UIApplication.shared.canOpenURL(launchURL) {
|
||||
// Open the URL to enable JIT
|
||||
UIApplication.shared.open(launchURL, options: [:], completionHandler: nil)
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
27
src/MeloNX/MeloNX/App/Core/JIT/utils.h
Normal file
27
src/MeloNX/MeloNX/App/Core/JIT/utils.h
Normal file
@ -0,0 +1,27 @@
|
||||
#if __has_feature(modules)
|
||||
@import UIKit;
|
||||
@import Foundation;
|
||||
#else
|
||||
#import "UIKit/UIKit.h"
|
||||
#import "Foundation/Foundation.h"
|
||||
#endif
|
||||
|
||||
#define DISPATCH_ASYNC_START dispatch_async(dispatch_get_main_queue(), ^{
|
||||
#define DISPATCH_ASYNC_CLOSE });
|
||||
|
||||
#define PT_TRACE_ME 0
|
||||
extern int ptrace(int, pid_t, caddr_t, int);
|
||||
|
||||
#define CS_DEBUGGED 0x10000000
|
||||
extern int csops(
|
||||
pid_t pid,
|
||||
unsigned int ops,
|
||||
void *useraddr,
|
||||
size_t usersize
|
||||
);
|
||||
|
||||
extern BOOL getEntitlementValue(NSString *key);
|
||||
extern BOOL isJITEnabled(void);
|
||||
|
||||
#define DLOG(format, ...) ShowAlert(@"DEBUG", [NSString stringWithFormat:@"\n %s [Line %d] \n %@", __PRETTY_FUNCTION__, __LINE__, [NSString stringWithFormat:format, ##__VA_ARGS__]])
|
||||
void ShowAlert(NSString* title, NSString* message, _Bool* showok);
|
91
src/MeloNX/MeloNX/App/Core/JIT/utils.m
Normal file
91
src/MeloNX/MeloNX/App/Core/JIT/utils.m
Normal file
@ -0,0 +1,91 @@
|
||||
#import "utils.h"
|
||||
|
||||
typedef struct __SecTask * SecTaskRef;
|
||||
extern CFTypeRef SecTaskCopyValueForEntitlement(
|
||||
SecTaskRef task,
|
||||
NSString* entitlement,
|
||||
CFErrorRef _Nullable *error
|
||||
)
|
||||
__attribute__((weak_import));
|
||||
|
||||
extern SecTaskRef SecTaskCreateFromSelf(CFAllocatorRef allocator)
|
||||
__attribute__((weak_import));
|
||||
|
||||
BOOL getEntitlementValue(NSString *key)
|
||||
{
|
||||
if (SecTaskCreateFromSelf == NULL || SecTaskCopyValueForEntitlement == NULL)
|
||||
return NO;
|
||||
SecTaskRef sec_task = SecTaskCreateFromSelf(NULL);
|
||||
if(!sec_task) return NO;
|
||||
CFTypeRef value = SecTaskCopyValueForEntitlement(sec_task, key, nil);
|
||||
if (value != nil)
|
||||
{
|
||||
CFRelease(value);
|
||||
}
|
||||
CFRelease(sec_task);
|
||||
return value != nil && [(__bridge id)value boolValue];
|
||||
}
|
||||
|
||||
BOOL isJITEnabled(void)
|
||||
{
|
||||
if (getEntitlementValue(@"dynamic-codesigning"))
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
int flags;
|
||||
csops(getpid(), 0, &flags, sizeof(flags));
|
||||
return (flags & CS_DEBUGGED) != 0;
|
||||
}
|
||||
|
||||
void ShowAlert(NSString* title, NSString* message, _Bool* showok)
|
||||
{
|
||||
DISPATCH_ASYNC_START
|
||||
UIWindow* mainWindow = [[UIApplication sharedApplication] windows].lastObject;
|
||||
UIAlertController *alert = [UIAlertController alertControllerWithTitle:title
|
||||
message:message
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
if (showok) {
|
||||
[alert addAction:[UIAlertAction actionWithTitle:@"ok!"
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:nil]];
|
||||
}
|
||||
[mainWindow.rootViewController presentViewController:alert
|
||||
animated:true
|
||||
completion:nil];
|
||||
DISPATCH_ASYNC_CLOSE
|
||||
}
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
__attribute__((constructor)) static void entry(int argc, char **argv)
|
||||
{
|
||||
if (isJITEnabled()) {
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
[defaults setBool:YES forKey:@"JIT"];
|
||||
[defaults synchronize]; // Ensure the value is saved immediately
|
||||
} else {
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
[defaults setBool:NO forKey:@"JIT"];
|
||||
[defaults synchronize]; // Ensure the value is saved immediately
|
||||
}
|
||||
|
||||
if (getEntitlementValue(@"com.apple.developer.kernel.increased-memory-limit")) {
|
||||
NSLog(@"Entitlement Does Exist");
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
[defaults setBool:YES forKey:@"increased-memory-limit"];
|
||||
[defaults synchronize]; // Ensure the value is saved immediately
|
||||
}
|
||||
|
||||
if (getEntitlementValue(@"com.apple.developer.kernel.increased-debugging-memory-limit")) {
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
[defaults setBool:YES forKey:@"increased-debugging-memory-limit"];
|
||||
[defaults synchronize]; // Ensure the value is saved immediately
|
||||
}
|
||||
if (getEntitlementValue(@"com.apple.developer.kernel.extended-virtual-addressing")) {
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
[defaults setBool:YES forKey:@"extended-virtual-addressing"];
|
||||
[defaults synchronize]; // Ensure the value is saved immediately
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,189 @@
|
||||
//
|
||||
// VirtualController.swift
|
||||
// MeloNX
|
||||
//
|
||||
// Created by Stossy11 on 8/12/2024.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CoreHaptics
|
||||
import UIKit
|
||||
|
||||
class VirtualController {
|
||||
private var instanceID: SDL_JoystickID = -1
|
||||
private var controller: OpaquePointer?
|
||||
|
||||
public let controllername = "MeloNX Touch Controller"
|
||||
|
||||
init() {
|
||||
setupVirtualController()
|
||||
}
|
||||
|
||||
private func setupVirtualController() {
|
||||
// Initialize SDL if not already initialized
|
||||
if SDL_WasInit(Uint32(SDL_INIT_GAMECONTROLLER)) == 0 {
|
||||
SDL_InitSubSystem(Uint32(SDL_INIT_GAMECONTROLLER))
|
||||
}
|
||||
|
||||
// Create virtual controller
|
||||
var joystickDesc = SDL_VirtualJoystickDesc(
|
||||
version: UInt16(SDL_VIRTUAL_JOYSTICK_DESC_VERSION),
|
||||
type: Uint16(SDL_JOYSTICK_TYPE_GAMECONTROLLER.rawValue),
|
||||
naxes: 6,
|
||||
nbuttons: 15,
|
||||
nhats: 1,
|
||||
vendor_id: 0,
|
||||
product_id: 0,
|
||||
padding: 0,
|
||||
button_mask: 0,
|
||||
axis_mask: 0,
|
||||
name: controllername.withCString { $0 },
|
||||
userdata: nil,
|
||||
Update: { userdata in
|
||||
// Update joystick state here
|
||||
},
|
||||
SetPlayerIndex: { userdata, playerIndex in
|
||||
print("Player index set to \(playerIndex)")
|
||||
},
|
||||
Rumble: { userdata, lowFreq, highFreq in
|
||||
print("Rumble with \(lowFreq), \(highFreq)")
|
||||
VirtualController.rumble(lowFreq: Float(lowFreq), highFreq: Float(highFreq))
|
||||
return 0
|
||||
},
|
||||
RumbleTriggers: { userdata, leftRumble, rightRumble in
|
||||
print("Trigger rumble with \(leftRumble), \(rightRumble)")
|
||||
return 0
|
||||
},
|
||||
SetLED: { userdata, red, green, blue in
|
||||
print("Set LED to RGB(\(red), \(green), \(blue))")
|
||||
return 0
|
||||
},
|
||||
SendEffect: { userdata, data, size in
|
||||
print("Effect sent with size \(size)")
|
||||
return 0
|
||||
}
|
||||
)
|
||||
|
||||
instanceID = SDL_JoystickAttachVirtualEx(&joystickDesc)// SDL_JoystickAttachVirtual(SDL_JoystickType(SDL_JOYSTICK_TYPE_GAMECONTROLLER.rawValue), 6, 15, 1)
|
||||
if instanceID < 0 {
|
||||
print("Failed to create virtual joystick: \(String(cString: SDL_GetError()))")
|
||||
return
|
||||
}
|
||||
|
||||
// Open a game controller for the virtual joystick
|
||||
let joystick = SDL_JoystickFromInstanceID(instanceID)
|
||||
controller = SDL_GameControllerOpen(Int32(instanceID))
|
||||
|
||||
if controller == nil {
|
||||
print("Failed to create virtual controller: \(String(cString: SDL_GetError()))")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
static func rumble(lowFreq: Float, highFreq: Float) {
|
||||
do {
|
||||
// Low-frequency haptic pattern
|
||||
let lowFreqPattern = try CHHapticPattern(events: [
|
||||
CHHapticEvent(eventType: .hapticTransient, parameters: [
|
||||
CHHapticEventParameter(parameterID: .hapticIntensity, value: lowFreq),
|
||||
CHHapticEventParameter(parameterID: .hapticSharpness, value: 0.5)
|
||||
], relativeTime: 0, duration: 0.2)
|
||||
], parameters: [])
|
||||
|
||||
// High-frequency haptic pattern
|
||||
let highFreqPattern = try CHHapticPattern(events: [
|
||||
CHHapticEvent(eventType: .hapticTransient, parameters: [
|
||||
CHHapticEventParameter(parameterID: .hapticIntensity, value: highFreq),
|
||||
CHHapticEventParameter(parameterID: .hapticSharpness, value: 1.0)
|
||||
], relativeTime: 0.2, duration: 0.2)
|
||||
], parameters: [])
|
||||
|
||||
// Create and start the haptic engine
|
||||
let engine = try CHHapticEngine()
|
||||
try engine.start()
|
||||
|
||||
// Create and play the low-frequency player
|
||||
let lowFreqPlayer = try engine.makePlayer(with: lowFreqPattern)
|
||||
try lowFreqPlayer.start(atTime: 0)
|
||||
|
||||
// Create and play the high-frequency player after a short delay
|
||||
let highFreqPlayer = try engine.makePlayer(with: highFreqPattern)
|
||||
try highFreqPlayer.start(atTime: 0.2)
|
||||
|
||||
} catch {
|
||||
print("Error creating haptic patterns: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func updateAxisValue(value: Sint16, forAxis axis: SDL_GameControllerAxis) {
|
||||
guard controller != nil else { return }
|
||||
let joystick = SDL_JoystickFromInstanceID(instanceID)
|
||||
SDL_JoystickSetVirtualAxis(joystick, axis.rawValue, value)
|
||||
}
|
||||
|
||||
func thumbstickMoved(_ stick: ThumbstickType, x: Double, y: Double) {
|
||||
let scaleFactor = 32767.0 / 160
|
||||
|
||||
let scaledX = Int16(min(32767.0, max(-32768.0, x * scaleFactor)))
|
||||
let scaledY = Int16(min(32767.0, max(-32768.0, y * scaleFactor)))
|
||||
|
||||
if stick == .right {
|
||||
updateAxisValue(value: scaledX, forAxis: SDL_GameControllerAxis(SDL_CONTROLLER_AXIS_RIGHTX.rawValue))
|
||||
updateAxisValue(value: scaledY, forAxis: SDL_GameControllerAxis(SDL_CONTROLLER_AXIS_RIGHTY.rawValue))
|
||||
} else { // ThumbstickType.left
|
||||
updateAxisValue(value: scaledX, forAxis: SDL_GameControllerAxis(SDL_CONTROLLER_AXIS_LEFTX.rawValue))
|
||||
updateAxisValue(value: scaledY, forAxis: SDL_GameControllerAxis(SDL_CONTROLLER_AXIS_LEFTY.rawValue))
|
||||
}
|
||||
}
|
||||
|
||||
func setButtonState(_ state: Uint8, for button: VirtualControllerButton) {
|
||||
guard controller != nil else { return }
|
||||
|
||||
print("Button: \(button.rawValue) {state: \(state)}")
|
||||
if (button == .leftTrigger || button == .rightTrigger) && (state == 1 || state == 0) {
|
||||
let axis: SDL_GameControllerAxis = (button == .leftTrigger) ? SDL_CONTROLLER_AXIS_TRIGGERLEFT : SDL_CONTROLLER_AXIS_TRIGGERRIGHT
|
||||
let value: Int = (state == 1) ? 32767 : 0
|
||||
updateAxisValue(value: Sint16(value), forAxis: axis)
|
||||
} else {
|
||||
let joystick = SDL_JoystickFromInstanceID(instanceID)
|
||||
SDL_JoystickSetVirtualButton(joystick, Int32(button.rawValue), state)
|
||||
}
|
||||
}
|
||||
|
||||
func cleanup() {
|
||||
if let controller = controller {
|
||||
SDL_GameControllerClose(controller)
|
||||
self.controller = nil
|
||||
}
|
||||
}
|
||||
|
||||
deinit {
|
||||
cleanup()
|
||||
}
|
||||
}
|
||||
|
||||
enum VirtualControllerButton: Int {
|
||||
case B
|
||||
case A
|
||||
case Y
|
||||
case X
|
||||
case back
|
||||
case guide
|
||||
case start
|
||||
case leftStick
|
||||
case rightStick
|
||||
case leftShoulder
|
||||
case rightShoulder
|
||||
case dPadUp
|
||||
case dPadDown
|
||||
case dPadLeft
|
||||
case dPadRight
|
||||
case leftTrigger
|
||||
case rightTrigger
|
||||
}
|
||||
|
||||
enum ThumbstickType: Int {
|
||||
case left
|
||||
case right
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
//
|
||||
// VirtualController.swift
|
||||
// MeloNX
|
||||
//
|
||||
// Created by Stossy11 on 28/11/2024.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import GameController
|
||||
import UIKit
|
||||
import SwiftUI
|
||||
|
||||
func waitforcontroller() {
|
||||
if let window = theWindow {
|
||||
|
||||
|
||||
|
||||
// Function to recursively search for GCControllerView
|
||||
func findGCControllerView(in view: UIView) -> UIView? {
|
||||
// Check if current view is GCControllerView
|
||||
if String(describing: type(of: view)) == "ControllerView" {
|
||||
return view
|
||||
}
|
||||
|
||||
// Search through subviews
|
||||
for subview in view.subviews {
|
||||
if let found = findGCControllerView(in: subview) {
|
||||
return found
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
let controllerView = ControllerView()
|
||||
let controllerHostingController = UIHostingController(rootView: controllerView)
|
||||
let containerView = TransparentHostingContainerView(frame: window.bounds)
|
||||
containerView.backgroundColor = .clear
|
||||
|
||||
controllerHostingController.view.frame = containerView.bounds
|
||||
controllerHostingController.view.backgroundColor = .clear
|
||||
containerView.addSubview(controllerHostingController.view)
|
||||
|
||||
Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { timer in
|
||||
if findGCControllerView(in: window) == nil {
|
||||
window.addSubview(containerView)
|
||||
} else {
|
||||
timer.invalidate()
|
||||
}
|
||||
|
||||
window.bringSubviewToFront(containerView)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class TransparentHostingContainerView: UIView {
|
||||
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
||||
// Check if the point is within the subviews of this container
|
||||
let view = super.hitTest(point, with: event)
|
||||
|
||||
// Return nil if the touch is outside visible content (passes through to views below)
|
||||
return view === self ? nil : view
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
//
|
||||
// Untitled.swift
|
||||
// MeloNX
|
||||
//
|
||||
// Created by Stossy11 on 28/11/2024.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import GameController
|
||||
import UIKit
|
||||
|
||||
|
||||
|
||||
var theWindow: UIWindow? = nil
|
||||
extension UIWindow {
|
||||
@objc func wdb_makeKeyAndVisible() {
|
||||
if #available(iOS 13.0, *) {
|
||||
self.windowScene = (UIApplication.shared.connectedScenes.first! as! UIWindowScene)
|
||||
}
|
||||
self.wdb_makeKeyAndVisible()
|
||||
theWindow = self
|
||||
|
||||
|
||||
if UserDefaults.standard.bool(forKey: "isVirtualController") {
|
||||
if let window = theWindow {
|
||||
|
||||
class LandscapeViewController: UIViewController {
|
||||
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
|
||||
return .landscape
|
||||
}
|
||||
|
||||
override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
|
||||
return .landscapeLeft
|
||||
}
|
||||
}
|
||||
|
||||
let landscapeVC = LandscapeViewController()
|
||||
landscapeVC.modalPresentationStyle = .fullScreen
|
||||
theWindow?.rootViewController?.present(landscapeVC, animated: false, completion: nil)
|
||||
waitforcontroller()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func patchMakeKeyAndVisible() {
|
||||
let uiwindowClass = UIWindow.self
|
||||
if let m1 = class_getInstanceMethod(uiwindowClass, #selector(UIWindow.makeKeyAndVisible)),
|
||||
let m2 = class_getInstanceMethod(uiwindowClass, #selector(UIWindow.wdb_makeKeyAndVisible)) {
|
||||
method_exchangeImplementations(m1, m2)
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,41 @@
|
||||
//
|
||||
// FPSMonitor.swift
|
||||
// MeloNX
|
||||
//
|
||||
// Created by Stossy11 on 21/12/2024.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
|
||||
class FPSMonitor: ObservableObject {
|
||||
@Published private(set) var currentFPS: UInt64 = 0
|
||||
private var timer: Timer?
|
||||
|
||||
init() {
|
||||
timer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { [weak self] _ in
|
||||
self?.updateFPS()
|
||||
}
|
||||
}
|
||||
|
||||
deinit {
|
||||
timer?.invalidate()
|
||||
}
|
||||
|
||||
private func updateFPS() {
|
||||
let currentfps = UInt64(get_current_fps())
|
||||
|
||||
self.currentFPS = currentfps
|
||||
}
|
||||
|
||||
|
||||
func formatFPS() -> String {
|
||||
let fps = Double(currentFPS)
|
||||
let fpsString = String(format: "FPS: %.2f", fps)
|
||||
|
||||
return fpsString
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -0,0 +1,52 @@
|
||||
//
|
||||
// MemoryUsageMonitor.swift
|
||||
// MeloNX
|
||||
//
|
||||
// Created by Stossy11 on 21/12/2024.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
|
||||
class MemoryUsageMonitor: ObservableObject {
|
||||
@Published private(set) var memoryUsage: UInt64 = 0
|
||||
private var timer: Timer?
|
||||
|
||||
init() {
|
||||
timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { [weak self] _ in
|
||||
self?.updateMemoryUsage()
|
||||
}
|
||||
}
|
||||
|
||||
deinit {
|
||||
timer?.invalidate()
|
||||
}
|
||||
|
||||
private func updateMemoryUsage() {
|
||||
var taskInfo = task_vm_info_data_t()
|
||||
var count = mach_msg_type_number_t(MemoryLayout<task_vm_info>.size) / 4
|
||||
let result: kern_return_t = withUnsafeMutablePointer(to: &taskInfo) {
|
||||
$0.withMemoryRebound(to: integer_t.self, capacity: 1) {
|
||||
task_info(mach_task_self_, task_flavor_t(TASK_VM_INFO), $0, &count)
|
||||
}
|
||||
}
|
||||
|
||||
if result == KERN_SUCCESS {
|
||||
memoryUsage = taskInfo.phys_footprint
|
||||
}
|
||||
else {
|
||||
print("Error with task_info(): " +
|
||||
(String(cString: mach_error_string(result), encoding: String.Encoding.ascii) ?? "unknown error"))
|
||||
}
|
||||
}
|
||||
|
||||
func formatMemorySize(_ bytes: UInt64) -> String {
|
||||
let formatter = ByteCountFormatter()
|
||||
formatter.allowedUnits = [.useMB, .useGB]
|
||||
formatter.countStyle = .memory
|
||||
return formatter.string(fromByteCount: Int64(bytes))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,22 @@
|
||||
//
|
||||
// Untitled.swift
|
||||
// MeloNX
|
||||
//
|
||||
// Created by Stossy11 on 21/12/2024.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct PerformanceOverlayView: View {
|
||||
@StateObject private var memorymonitor = MemoryUsageMonitor()
|
||||
|
||||
@StateObject private var fpsmonitor = FPSMonitor()
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
Text("\(fpsmonitor.formatFPS())")
|
||||
Text(memorymonitor.formatMemorySize(memorymonitor.memoryUsage))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
60
src/MeloNX/MeloNX/App/Core/Ryujinx/MetalHUD/MTLHUD.swift
Normal file
60
src/MeloNX/MeloNX/App/Core/Ryujinx/MetalHUD/MTLHUD.swift
Normal file
@ -0,0 +1,60 @@
|
||||
//
|
||||
// MTLHUD.swift
|
||||
// MeloNX
|
||||
//
|
||||
// Created by Stossy11 on 26/11/2024.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
class MTLHud {
|
||||
|
||||
var canMetalHud: Bool {
|
||||
return openMetalDylib()
|
||||
}
|
||||
|
||||
var isEnabled: Bool {
|
||||
if let getenv = getenv("MTL_HUD_ENABLED") {
|
||||
return String(cString: getenv).contains("1")
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
static let shared = MTLHud()
|
||||
|
||||
private init() {
|
||||
openMetalDylib()
|
||||
if UserDefaults.standard.bool(forKey: "MTL_HUD_ENABLED") {
|
||||
enable()
|
||||
} else {
|
||||
disable()
|
||||
}
|
||||
}
|
||||
|
||||
func openMetalDylib() -> Bool {
|
||||
let path = "/usr/lib/libMTLHud.dylib"
|
||||
|
||||
// Load the dynamic library
|
||||
if dlopen(path, RTLD_NOW) != nil {
|
||||
// Library loaded successfully
|
||||
print("Library loaded from \(path)")
|
||||
return true
|
||||
} else {
|
||||
// Handle error
|
||||
if let error = String(validatingUTF8: dlerror()) {
|
||||
print("Error loading library: \(error)")
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func enable() {
|
||||
setenv("MTL_HUD_ENABLED", "1", 1)
|
||||
}
|
||||
|
||||
func disable() {
|
||||
setenv("MTL_HUD_ENABLED", "0", 1)
|
||||
}
|
||||
}
|
316
src/MeloNX/MeloNX/App/Core/Ryujinx/Ryujinx.swift
Normal file
316
src/MeloNX/MeloNX/App/Core/Ryujinx/Ryujinx.swift
Normal file
@ -0,0 +1,316 @@
|
||||
//
|
||||
// Ryujinx.swift
|
||||
// MeloNX
|
||||
//
|
||||
// Created by Stossy11 on 3/11/2024.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
import GameController
|
||||
|
||||
struct Controller: Identifiable, Hashable {
|
||||
var id: String
|
||||
var name: String
|
||||
}
|
||||
|
||||
struct iOSNav<Content: View>: View {
|
||||
@ViewBuilder var content: () -> Content
|
||||
|
||||
var body: some View {
|
||||
if #available(iOS 16, *) {
|
||||
NavigationStack(root: content)
|
||||
} else {
|
||||
NavigationView(content: content)
|
||||
.navigationViewStyle(StackNavigationViewStyle())
|
||||
.navigationViewStyle(.stack)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Ryujinx {
|
||||
private var isRunning = false
|
||||
|
||||
let virtualController = VirtualController()
|
||||
|
||||
@Published var controllerMap: [Controller] = []
|
||||
@State var firmwareversion = "0"
|
||||
|
||||
static let shared = Ryujinx()
|
||||
|
||||
private init() {}
|
||||
|
||||
public struct Configuration : Codable, Equatable {
|
||||
var gamepath: String
|
||||
var inputids: [String]
|
||||
var resscale: Float
|
||||
var debuglogs: Bool
|
||||
var tracelogs: Bool
|
||||
var nintendoinput: Bool
|
||||
var enableInternet: Bool
|
||||
var listinputids: Bool
|
||||
var fullscreen: Bool
|
||||
var memoryManagerMode: String
|
||||
var disableShaderCache: Bool
|
||||
var disableDockedMode: Bool
|
||||
var enableTextureRecompression: Bool
|
||||
var additionalArgs: [String]
|
||||
|
||||
|
||||
init(gamepath: String,
|
||||
inputids: [String] = [],
|
||||
debuglogs: Bool = false,
|
||||
tracelogs: Bool = false,
|
||||
listinputids: Bool = false,
|
||||
fullscreen: Bool = true,
|
||||
memoryManagerMode: String = "HostMapped",
|
||||
disableShaderCache: Bool = false,
|
||||
disableDockedMode: Bool = false,
|
||||
nintendoinput: Bool = true,
|
||||
enableInternet: Bool = false,
|
||||
enableTextureRecompression: Bool = true,
|
||||
additionalArgs: [String] = [],
|
||||
resscale: Float = 1.00
|
||||
) {
|
||||
self.gamepath = gamepath
|
||||
self.inputids = inputids
|
||||
self.debuglogs = debuglogs
|
||||
self.tracelogs = tracelogs
|
||||
self.listinputids = listinputids
|
||||
self.fullscreen = fullscreen
|
||||
self.disableShaderCache = disableShaderCache
|
||||
self.disableDockedMode = disableDockedMode
|
||||
self.enableTextureRecompression = enableTextureRecompression
|
||||
self.additionalArgs = additionalArgs
|
||||
self.memoryManagerMode = memoryManagerMode
|
||||
self.resscale = resscale
|
||||
self.nintendoinput = nintendoinput
|
||||
self.enableInternet = enableInternet
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func start(with config: Configuration) throws {
|
||||
guard !isRunning else {
|
||||
throw RyujinxError.alreadyRunning
|
||||
}
|
||||
|
||||
isRunning = true
|
||||
|
||||
RunLoop.current.perform {
|
||||
let url = URL(string: config.gamepath)!
|
||||
|
||||
do {
|
||||
let args = self.buildCommandLineArgs(from: config)
|
||||
let accessing = url.startAccessingSecurityScopedResource()
|
||||
|
||||
// Convert Arguments to ones that Ryujinx can Read
|
||||
let cArgs = args.map { strdup($0) }
|
||||
defer { cArgs.forEach { free($0) } }
|
||||
var argvPtrs = cArgs
|
||||
|
||||
// Start the emulation
|
||||
let result = main_ryujinx_sdl(Int32(args.count), &argvPtrs)
|
||||
|
||||
if result != 0 {
|
||||
self.isRunning = false
|
||||
if accessing {
|
||||
url.stopAccessingSecurityScopedResource()
|
||||
}
|
||||
|
||||
throw RyujinxError.executionError(code: result)
|
||||
}
|
||||
} catch {
|
||||
self.isRunning = false
|
||||
Self.log("Emulation failed to start: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func stop() throws {
|
||||
guard isRunning else {
|
||||
throw RyujinxError.notRunning
|
||||
}
|
||||
|
||||
isRunning = false
|
||||
}
|
||||
|
||||
var running: Bool {
|
||||
return isRunning
|
||||
}
|
||||
|
||||
private func buildCommandLineArgs(from config: Configuration) -> [String] {
|
||||
var args: [String] = []
|
||||
|
||||
// Add the game path
|
||||
args.append(config.gamepath)
|
||||
|
||||
// Starts with vulkan
|
||||
args.append("--graphics-backend")
|
||||
args.append("Vulkan")
|
||||
|
||||
args.append(contentsOf: ["--memory-manager-mode", config.memoryManagerMode])
|
||||
|
||||
args.append(contentsOf: ["--exclusive-fullscreen", String(true)])
|
||||
args.append(contentsOf: ["--exclusive-fullscreen-width", "\(Int(UIScreen.main.bounds.width))"])
|
||||
args.append(contentsOf: ["--exclusive-fullscreen-height", "\(Int(UIScreen.main.bounds.height))"])
|
||||
// We don't need this. Ryujinx should handle it fine :3
|
||||
|
||||
if config.fullscreen {
|
||||
args.append(contentsOf: ["--aspect-ratio", "Stretched"])
|
||||
}
|
||||
|
||||
|
||||
if config.nintendoinput {
|
||||
args.append("--correct-controller")
|
||||
}
|
||||
|
||||
|
||||
args.append("--disable-vsync")
|
||||
|
||||
|
||||
if config.resscale != 1.0 {
|
||||
args.append(contentsOf: ["--resolution-scale", String(config.resscale)])
|
||||
}
|
||||
|
||||
if !config.disableShaderCache { // same with disableShaderCache
|
||||
args.append("--disable-shader-cache")
|
||||
}
|
||||
|
||||
if !config.disableDockedMode { // disableDockedMode is actually enableDockedMode, i just have flipped it around in the settings page to make it easier to understand :3
|
||||
args.append("--disable-docked-mode")
|
||||
}
|
||||
if config.enableTextureRecompression {
|
||||
args.append("--enable-texture-recompression")
|
||||
}
|
||||
|
||||
if config.debuglogs {
|
||||
args.append(contentsOf: ["--enable-debug-logs"])
|
||||
}
|
||||
if config.tracelogs {
|
||||
args.append(contentsOf: ["--enable-trace-logs"])
|
||||
}
|
||||
|
||||
// List the input ids
|
||||
if config.listinputids {
|
||||
args.append(contentsOf: ["--list-inputs-ids"])
|
||||
}
|
||||
|
||||
// Append the input ids (limit to 4 just in case)
|
||||
if !config.inputids.isEmpty {
|
||||
config.inputids.prefix(4).enumerated().forEach { index, inputId in
|
||||
args.append(contentsOf: ["--input-id-\(index + 1)", inputId])
|
||||
}
|
||||
}
|
||||
|
||||
// Apped any additional arguments
|
||||
args.append(contentsOf: config.additionalArgs)
|
||||
|
||||
return args
|
||||
}
|
||||
|
||||
func fetchFirmwareVersion() -> String {
|
||||
do {
|
||||
let firmwareVersionPointer = installed_firmware_version()
|
||||
if let pointer = firmwareVersionPointer {
|
||||
let firmwareVersion = String(cString: pointer)
|
||||
DispatchQueue.main.async {
|
||||
self.firmwareversion = firmwareVersion
|
||||
}
|
||||
return firmwareVersion
|
||||
}
|
||||
|
||||
} catch {
|
||||
print(error)
|
||||
}
|
||||
|
||||
return "0"
|
||||
}
|
||||
|
||||
func installFirmware(firmwarePath: String) {
|
||||
guard let cString = firmwarePath.cString(using: .utf8) else {
|
||||
print("Invalid firmware path")
|
||||
return
|
||||
}
|
||||
|
||||
install_firmware(cString)
|
||||
|
||||
let version = fetchFirmwareVersion()
|
||||
if !version.isEmpty {
|
||||
self.firmwareversion = version
|
||||
}
|
||||
}
|
||||
|
||||
func getConnectedControllers() -> [Controller] {
|
||||
|
||||
|
||||
guard let jsonPtr = get_game_controllers() else {
|
||||
return []
|
||||
}
|
||||
|
||||
// Convert the unmanaged memory (C string) to a Swift String
|
||||
let jsonString = String(cString: jsonPtr)
|
||||
|
||||
var controllers: [Controller] = []
|
||||
|
||||
// Splitting the string by newline
|
||||
let lines = jsonString.components(separatedBy: "\n")
|
||||
|
||||
// Parsing each line
|
||||
for line in lines {
|
||||
if line.contains(":") {
|
||||
let parts = line.components(separatedBy: ":")
|
||||
if parts.count == 2 {
|
||||
let id = parts[0].trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
let name = parts[1].trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
controllers.append(Controller(id: id, name: name))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return controllers
|
||||
|
||||
}
|
||||
|
||||
func removeFirmware() {
|
||||
let fileManager = FileManager.default
|
||||
|
||||
let documentsfolder = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first!
|
||||
|
||||
|
||||
let bisFolder = documentsfolder.appendingPathComponent("bis")
|
||||
let systemFolder = bisFolder.appendingPathComponent("system")
|
||||
let contentsFolder = systemFolder.appendingPathComponent("Contents")
|
||||
let registeredFolder = contentsFolder.appendingPathComponent("registered").path
|
||||
|
||||
|
||||
do {
|
||||
if fileManager.fileExists(atPath: registeredFolder) {
|
||||
try fileManager.removeItem(atPath: registeredFolder)
|
||||
print("Folder removed successfully.")
|
||||
let version = fetchFirmwareVersion()
|
||||
|
||||
if version.isEmpty {
|
||||
self.firmwareversion = "0"
|
||||
} else {
|
||||
print("Firmware eeeeee \(version)")
|
||||
}
|
||||
|
||||
} else {
|
||||
print("Folder does not exist.")
|
||||
}
|
||||
} catch {
|
||||
print("Error removing folder: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static func log(_ message: String) {
|
||||
print("[Ryujinx] \(message)")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
15
src/MeloNX/MeloNX/App/Core/Ryujinx/RyujinxError.swift
Normal file
15
src/MeloNX/MeloNX/App/Core/Ryujinx/RyujinxError.swift
Normal file
@ -0,0 +1,15 @@
|
||||
//
|
||||
// RyujinxError.swift
|
||||
// MeloNX
|
||||
//
|
||||
// Created by Stossy11 on 3/11/2024.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
enum RyujinxError: Error {
|
||||
case libraryLoadError
|
||||
case executionError(code: Int32)
|
||||
case alreadyRunning
|
||||
case notRunning
|
||||
}
|
309
src/MeloNX/MeloNX/App/Views/ContentView.swift
Normal file
309
src/MeloNX/MeloNX/App/Views/ContentView.swift
Normal file
@ -0,0 +1,309 @@
|
||||
//
|
||||
// ContentView.swift
|
||||
// MeloNX
|
||||
//
|
||||
// Created by Stossy11 on 3/11/2024.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
// import SDL2
|
||||
import GameController
|
||||
import Darwin
|
||||
import UIKit
|
||||
import MetalKit
|
||||
// import SDL
|
||||
import SoftwareKeyboard
|
||||
|
||||
struct MoltenVKSettings: Codable, Hashable {
|
||||
let string: String
|
||||
var value: String
|
||||
}
|
||||
|
||||
struct ContentView: View {
|
||||
// MARK: - Properties
|
||||
@State private var theWindow: UIWindow?
|
||||
@State private var game: Game?
|
||||
@State private var controllersList: [Controller] = []
|
||||
@State private var currentControllers: [Controller] = []
|
||||
@State private var config: Ryujinx.Configuration
|
||||
@State var settings: [MoltenVKSettings]
|
||||
@AppStorage("useTrollStore") var useTrollStore: Bool = false
|
||||
@State private var isVirtualControllerActive: Bool = false
|
||||
@AppStorage("isVirtualController") var isVCA: Bool = true
|
||||
@State var onscreencontroller: Controller = Controller(id: "", name: "")
|
||||
@AppStorage("JIT") var isJITEnabled: Bool = false
|
||||
@State var isMK8: Bool = false
|
||||
@AppStorage("quit") var quit: Bool = false
|
||||
|
||||
@State var quits: Bool = false
|
||||
@State private var clumpOffset: CGFloat = -100
|
||||
private let clumpWidth: CGFloat = 100
|
||||
private let animationDuration: Double = 1.0
|
||||
@State private var isAnimating = false
|
||||
@State var isLoading = true
|
||||
|
||||
// MARK: - Initialization
|
||||
init() {
|
||||
let defaultConfig = loadSettings() ?? Ryujinx.Configuration(gamepath: "")
|
||||
_config = State(initialValue: defaultConfig)
|
||||
|
||||
let defaultSettings: [MoltenVKSettings] = [
|
||||
MoltenVKSettings(string: "MVK_CONFIG_USE_METAL_PRIVATE_API", value: "1"),
|
||||
MoltenVKSettings(string: "MVK_CONFIG_RESUME_LOST_DEVICE", value: "1")
|
||||
]
|
||||
|
||||
_settings = State(initialValue: defaultSettings)
|
||||
|
||||
print("JIT Enabled: \(isJITEnabled)")
|
||||
|
||||
initializeSDL()
|
||||
}
|
||||
|
||||
// MARK: - Body
|
||||
var body: some View {
|
||||
if let game, quits == false {
|
||||
if isLoading {
|
||||
emulationView
|
||||
.onAppear() {
|
||||
Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { timer in
|
||||
timer.invalidate()
|
||||
quits = quit
|
||||
|
||||
if quits {
|
||||
quit = false
|
||||
timer.invalidate()
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
VStack {
|
||||
|
||||
}
|
||||
.onAppear() {
|
||||
isAnimating = false
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mainMenuView
|
||||
.onAppear() {
|
||||
quits = false
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - View Components
|
||||
private var emulationView: some View {
|
||||
GeometryReader { screenGeometry in
|
||||
ZStack {
|
||||
HStack(spacing: screenGeometry.size.width * 0.04) {
|
||||
if let icon = game?.icon {
|
||||
Image(uiImage: icon)
|
||||
.resizable()
|
||||
.frame(
|
||||
width: min(screenGeometry.size.width * 0.25, 250),
|
||||
height: min(screenGeometry.size.width * 0.25, 250)
|
||||
)
|
||||
.clipShape(RoundedRectangle(cornerRadius: 16))
|
||||
.shadow(color: .black.opacity(0.5), radius: 10, x: 0, y: 5)
|
||||
}
|
||||
|
||||
VStack(alignment: .leading, spacing: screenGeometry.size.height * 0.015) {
|
||||
Text("Loading \(game?.titleName ?? "Game")")
|
||||
.font(.system(size: min(screenGeometry.size.width * 0.04, 32)))
|
||||
.foregroundColor(.white)
|
||||
|
||||
GeometryReader { geometry in
|
||||
let containerWidth = min(screenGeometry.size.width * 0.35, 350)
|
||||
|
||||
ZStack(alignment: .leading) {
|
||||
// Background track
|
||||
Rectangle()
|
||||
.cornerRadius(10)
|
||||
.frame(width: containerWidth, height: min(screenGeometry.size.height * 0.015, 12))
|
||||
.foregroundColor(.gray.opacity(0.3))
|
||||
.shadow(color: .black.opacity(0.2), radius: 4, x: 0, y: 2)
|
||||
|
||||
// Animated loading bar
|
||||
Rectangle()
|
||||
.cornerRadius(10)
|
||||
.frame(width: clumpWidth, height: min(screenGeometry.size.height * 0.015, 12))
|
||||
.foregroundColor(.blue)
|
||||
.shadow(color: .blue.opacity(0.5), radius: 4, x: 0, y: 2)
|
||||
.offset(x: isAnimating ? containerWidth : -clumpWidth)
|
||||
.animation(
|
||||
Animation.linear(duration: 1.0)
|
||||
.repeatForever(autoreverses: false),
|
||||
value: isAnimating
|
||||
)
|
||||
}
|
||||
.clipShape(RoundedRectangle(cornerRadius: 16))
|
||||
.onAppear {
|
||||
isAnimating = true
|
||||
|
||||
setupEmulation()
|
||||
|
||||
|
||||
Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { timer in
|
||||
if get_current_fps() != 0 {
|
||||
isLoading = false
|
||||
isAnimating = false
|
||||
timer.invalidate()
|
||||
}
|
||||
print(get_current_fps())
|
||||
}
|
||||
}
|
||||
}
|
||||
.frame(height: min(screenGeometry.size.height * 0.015, 12))
|
||||
.frame(width: min(screenGeometry.size.width * 0.35, 350))
|
||||
}
|
||||
}
|
||||
.padding(.horizontal, screenGeometry.size.width * 0.06)
|
||||
.padding(.vertical, screenGeometry.size.height * 0.05)
|
||||
.position(
|
||||
x: screenGeometry.size.width / 2,
|
||||
y: screenGeometry.size.height * 0.5
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var mainMenuView: some View {
|
||||
MainTabView(startemu: $game, config: $config, MVKconfig: $settings, controllersList: $controllersList, currentControllers: $currentControllers, onscreencontroller: $onscreencontroller)
|
||||
.onAppear() {
|
||||
refreshControllersList()
|
||||
|
||||
|
||||
let isJIT = UserDefaults.standard.bool(forKey: "JIT-ENABLED")
|
||||
|
||||
if !isJIT, useTrollStore {
|
||||
askForJIT()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Helper Methods
|
||||
var SdlInitFlags: uint = SDL_INIT_EVENTS | SDL_INIT_GAMECONTROLLER | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO | SDL_INIT_VIDEO;
|
||||
private func initializeSDL() {
|
||||
setMoltenVKSettings()
|
||||
SDL_SetMainReady()
|
||||
SDL_iPhoneSetEventPump(SDL_TRUE)
|
||||
SDL_Init(SdlInitFlags)
|
||||
initialize()
|
||||
}
|
||||
|
||||
private func setupEmulation() {
|
||||
patchMakeKeyAndVisible()
|
||||
|
||||
if (currentControllers.first(where: { $0 == onscreencontroller }) != nil) {
|
||||
|
||||
isVCA = true
|
||||
|
||||
DispatchQueue.main.async {
|
||||
start(displayid: 1)
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
isVCA = false
|
||||
|
||||
DispatchQueue.main.async {
|
||||
start(displayid: 1)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private func refreshControllersList() {
|
||||
controllersList = Ryujinx.shared.getConnectedControllers()
|
||||
|
||||
if let onscreen = controllersList.first(where: { $0.name == Ryujinx.shared.virtualController.controllername }) {
|
||||
self.onscreencontroller = onscreen
|
||||
}
|
||||
|
||||
controllersList.removeAll(where: { $0.id == "0"})
|
||||
|
||||
if controllersList.count > 2 {
|
||||
let controller = controllersList[2]
|
||||
currentControllers.append(controller)
|
||||
} else if let controller = controllersList.first(where: { $0.id == onscreencontroller.id }), !controllersList.isEmpty {
|
||||
currentControllers.append(controller)
|
||||
}
|
||||
}
|
||||
|
||||
func showAlert(title: String, message: String, showOk: Bool, completion: @escaping (Bool) -> Void) {
|
||||
DispatchQueue.main.async {
|
||||
if let mainWindow = UIApplication.shared.windows.last {
|
||||
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
|
||||
|
||||
if showOk {
|
||||
let okAction = UIAlertAction(title: "OK", style: .default) { _ in
|
||||
completion(true)
|
||||
}
|
||||
|
||||
alert.addAction(okAction)
|
||||
} else {
|
||||
completion(false)
|
||||
}
|
||||
|
||||
mainWindow.rootViewController?.present(alert, animated: true, completion: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private func start(displayid: UInt32) {
|
||||
guard let game else { return }
|
||||
|
||||
config.gamepath = game.fileURL.path
|
||||
config.inputids = Array(Set(currentControllers.map(\.id)))
|
||||
var setting: MoltenVKSettings
|
||||
|
||||
if game.titleName.lowercased() != "super mario odyssey" {
|
||||
setting = (MoltenVKSettings(string: "MVK_CONFIG_SYNCHRONOUS_QUEUE_SUBMITS", value: "0"))
|
||||
} else {
|
||||
setting = (MoltenVKSettings(string: "MVK_CONFIG_SYNCHRONOUS_QUEUE_SUBMITS", value: "1"))
|
||||
}
|
||||
setenv(setting.string, setting.value, 1)
|
||||
|
||||
|
||||
|
||||
if config.inputids.isEmpty {
|
||||
config.inputids.append("0")
|
||||
}
|
||||
|
||||
do {
|
||||
try Ryujinx.shared.start(with: config)
|
||||
} catch {
|
||||
print("Error: \(error.localizedDescription)")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private func setMoltenVKSettings() {
|
||||
|
||||
settings.forEach { setting in
|
||||
setenv(setting.string, setting.value, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Helper Functions
|
||||
func loadSettings() -> Ryujinx.Configuration? {
|
||||
guard let jsonString = UserDefaults.standard.string(forKey: "config"),
|
||||
let data = jsonString.data(using: .utf8) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
do {
|
||||
return try JSONDecoder().decode(Ryujinx.Configuration.self, from: data)
|
||||
} catch {
|
||||
print("Failed to load settings: \(error)")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
304
src/MeloNX/MeloNX/App/Views/ControllerView/ControllerView.swift
Normal file
304
src/MeloNX/MeloNX/App/Views/ControllerView/ControllerView.swift
Normal file
@ -0,0 +1,304 @@
|
||||
//
|
||||
// ControllerView.swift
|
||||
// Pomelo-V2
|
||||
//
|
||||
// Created by Stossy11 on 16/7/2024.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import GameController
|
||||
import SwiftUIJoystick
|
||||
import CoreMotion
|
||||
|
||||
struct ControllerView: View {
|
||||
|
||||
@AppStorage("performacehud") var performacehud: Bool = false
|
||||
@AppStorage("quit") var quit: Bool = false
|
||||
var body: some View {
|
||||
GeometryReader { geometry in
|
||||
if geometry.size.height > geometry.size.width && UIDevice.current.userInterfaceIdiom != .pad {
|
||||
VStack {
|
||||
if performacehud {
|
||||
HStack {
|
||||
|
||||
PerformanceOverlayView()
|
||||
|
||||
Spacer()
|
||||
|
||||
// Button("Stop emulation") {
|
||||
// DispatchQueue.main.async {
|
||||
// stop_emulation()
|
||||
// quit = true
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Spacer()
|
||||
VStack {
|
||||
HStack {
|
||||
VStack {
|
||||
ShoulderButtonsViewLeft()
|
||||
ZStack {
|
||||
Joystick()
|
||||
DPadView()
|
||||
}
|
||||
}
|
||||
.padding()
|
||||
VStack {
|
||||
ShoulderButtonsViewRight()
|
||||
ZStack {
|
||||
Joystick(iscool: true) // hope this works
|
||||
ABXYView()
|
||||
}
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
|
||||
HStack {
|
||||
ButtonView(button: .start) // Adding the + button
|
||||
.padding(.horizontal, 40)
|
||||
ButtonView(button: .back) // Adding the - button
|
||||
.padding(.horizontal, 40)
|
||||
}
|
||||
}
|
||||
.padding(.bottom, geometry.size.height / 3.2) // very broken
|
||||
}
|
||||
} else {
|
||||
// could be landscape
|
||||
VStack {
|
||||
if performacehud {
|
||||
HStack {
|
||||
PerformanceOverlayView()
|
||||
|
||||
Spacer()
|
||||
|
||||
// Button("Stop emulation") {
|
||||
// DispatchQueue.main.async {
|
||||
// stop_emulation()
|
||||
// quit = true
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Spacer()
|
||||
VStack {
|
||||
HStack {
|
||||
|
||||
// gotta fuckin add + and - now
|
||||
VStack {
|
||||
ShoulderButtonsViewLeft()
|
||||
ZStack {
|
||||
Joystick()
|
||||
DPadView()
|
||||
}
|
||||
}
|
||||
HStack {
|
||||
// Spacer()
|
||||
VStack {
|
||||
// Spacer()
|
||||
ButtonView(button: .back) // Adding the + button
|
||||
}
|
||||
Spacer()
|
||||
VStack {
|
||||
// Spacer()
|
||||
ButtonView(button: .start) // Adding the - button
|
||||
}
|
||||
// Spacer()
|
||||
}
|
||||
VStack {
|
||||
ShoulderButtonsViewRight()
|
||||
ZStack {
|
||||
Joystick(iscool: true) // hope this work s
|
||||
ABXYView()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// .padding(.bottom, geometry.size.height / 11) // also extremally broken (
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
}
|
||||
|
||||
struct ShoulderButtonsViewLeft: View {
|
||||
@State var width: CGFloat = 160
|
||||
@State var height: CGFloat = 20
|
||||
var body: some View {
|
||||
HStack {
|
||||
ButtonView(button: .leftTrigger)
|
||||
.padding(.horizontal)
|
||||
ButtonView(button: .leftShoulder)
|
||||
.padding(.horizontal)
|
||||
}
|
||||
.frame(width: width, height: height)
|
||||
.onAppear() {
|
||||
if UIDevice.current.systemName.contains("iPadOS") {
|
||||
width *= 1.2
|
||||
height *= 1.2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ShoulderButtonsViewRight: View {
|
||||
@State var width: CGFloat = 160
|
||||
@State var height: CGFloat = 20
|
||||
var body: some View {
|
||||
HStack {
|
||||
ButtonView(button: .rightShoulder)
|
||||
.padding(.horizontal)
|
||||
ButtonView(button: .rightTrigger)
|
||||
.padding(.horizontal)
|
||||
}
|
||||
.frame(width: width, height: height)
|
||||
.onAppear() {
|
||||
if UIDevice.current.systemName.contains("iPadOS") {
|
||||
width *= 1.2
|
||||
height *= 1.2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct DPadView: View {
|
||||
@State var size: CGFloat = 145
|
||||
var body: some View {
|
||||
VStack {
|
||||
ButtonView(button: .dPadUp)
|
||||
HStack {
|
||||
ButtonView(button: .dPadLeft)
|
||||
Spacer(minLength: 20)
|
||||
ButtonView(button: .dPadRight)
|
||||
}
|
||||
ButtonView(button: .dPadDown)
|
||||
.padding(.horizontal)
|
||||
}
|
||||
.frame(width: size, height: size)
|
||||
.onAppear() {
|
||||
if UIDevice.current.systemName.contains("iPadOS") {
|
||||
size *= 1.2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ABXYView: View {
|
||||
@State var size: CGFloat = 145
|
||||
var body: some View {
|
||||
VStack {
|
||||
ButtonView(button: .X)
|
||||
HStack {
|
||||
ButtonView(button: .Y)
|
||||
Spacer(minLength: 20)
|
||||
ButtonView(button: .A)
|
||||
}
|
||||
ButtonView(button: .B)
|
||||
.padding(.horizontal)
|
||||
}
|
||||
.frame(width: size, height: size)
|
||||
.onAppear() {
|
||||
if UIDevice.current.systemName.contains("iPadOS") {
|
||||
size *= 1.2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ButtonView: View {
|
||||
var button: VirtualControllerButton
|
||||
@State var width: CGFloat = 45
|
||||
@State var height: CGFloat = 45
|
||||
@State var isPressed = false
|
||||
@AppStorage("onscreenhandheld") var onscreenjoy: Bool = false
|
||||
@Environment(\.colorScheme) var colorScheme
|
||||
@Environment(\.presentationMode) var presentationMode
|
||||
|
||||
|
||||
|
||||
var body: some View {
|
||||
Image(systemName: buttonText)
|
||||
.resizable()
|
||||
.frame(width: width, height: height)
|
||||
.foregroundColor(colorScheme == .dark ? Color.gray : Color.gray)
|
||||
.opacity(isPressed ? 0.4 : 0.7)
|
||||
.gesture(
|
||||
DragGesture(minimumDistance: 0)
|
||||
.onChanged { _ in
|
||||
if !self.isPressed {
|
||||
self.isPressed = true
|
||||
Ryujinx.shared.virtualController.setButtonState(1, for: button)
|
||||
Haptics.shared.play(.heavy)
|
||||
}
|
||||
}
|
||||
.onEnded { _ in
|
||||
self.isPressed = false
|
||||
Ryujinx.shared.virtualController.setButtonState(0, for: button)
|
||||
}
|
||||
)
|
||||
.onAppear() {
|
||||
if button == .leftTrigger || button == .rightTrigger || button == .leftShoulder || button == .rightShoulder {
|
||||
width = 65
|
||||
}
|
||||
|
||||
|
||||
if button == .back || button == .start || button == .guide {
|
||||
width = 35
|
||||
height = 35
|
||||
}
|
||||
|
||||
if UIDevice.current.systemName.contains("iPadOS") {
|
||||
width *= 1.2
|
||||
height *= 1.2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private var buttonText: String {
|
||||
switch button {
|
||||
case .A:
|
||||
return "a.circle.fill"
|
||||
case .B:
|
||||
return "b.circle.fill"
|
||||
case .X:
|
||||
return "x.circle.fill"
|
||||
case .Y:
|
||||
return "y.circle.fill"
|
||||
case .dPadUp:
|
||||
return "arrowtriangle.up.circle.fill"
|
||||
case .dPadDown:
|
||||
return "arrowtriangle.down.circle.fill"
|
||||
case .dPadLeft:
|
||||
return "arrowtriangle.left.circle.fill"
|
||||
case .dPadRight:
|
||||
return "arrowtriangle.right.circle.fill"
|
||||
case .leftTrigger:
|
||||
return"zl.rectangle.roundedtop.fill"
|
||||
case .rightTrigger:
|
||||
return "zr.rectangle.roundedtop.fill"
|
||||
case .leftShoulder:
|
||||
return "l.rectangle.roundedbottom.fill"
|
||||
case .rightShoulder:
|
||||
return "r.rectangle.roundedbottom.fill"
|
||||
case .start:
|
||||
return "plus.circle.fill" // System symbol for +
|
||||
case .back:
|
||||
return "minus.circle.fill" // System symbol for -
|
||||
case .guide:
|
||||
return "house.circle.fill"
|
||||
// This should be all the cases
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,27 @@
|
||||
//
|
||||
// Haptics.swift
|
||||
// Pomelo
|
||||
//
|
||||
// Created by Stossy11 on 11/9/2024.
|
||||
// Copyright © 2024 Stossy11. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SwiftUI
|
||||
|
||||
class Haptics {
|
||||
static let shared = Haptics()
|
||||
|
||||
private init() { }
|
||||
|
||||
func play(_ feedbackStyle: UIImpactFeedbackGenerator.FeedbackStyle) {
|
||||
print("haptics")
|
||||
UIImpactFeedbackGenerator(style: feedbackStyle).impactOccurred()
|
||||
}
|
||||
|
||||
func notify(_ feedbackType: UINotificationFeedbackGenerator.FeedbackType) {
|
||||
UINotificationFeedbackGenerator().notificationOccurred(feedbackType)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,53 @@
|
||||
//
|
||||
// JoystickView.swift
|
||||
// Pomelo
|
||||
//
|
||||
// Created by Stossy11 on 30/9/2024.
|
||||
// Copyright © 2024 Stossy11. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import SwiftUIJoystick
|
||||
|
||||
public struct Joystick: View {
|
||||
@State var iscool: Bool? = nil
|
||||
|
||||
@ObservedObject public var joystickMonitor = JoystickMonitor()
|
||||
var dragDiameter: CGFloat {
|
||||
var selfs = CGFloat(160)
|
||||
if UIDevice.current.systemName.contains("iPadOS") {
|
||||
return selfs * 1.2
|
||||
}
|
||||
return selfs
|
||||
}
|
||||
private let shape: JoystickShape = .circle
|
||||
|
||||
public var body: some View {
|
||||
VStack{
|
||||
JoystickBuilder(
|
||||
monitor: self.joystickMonitor,
|
||||
width: self.dragDiameter,
|
||||
shape: .circle,
|
||||
background: {
|
||||
Text("")
|
||||
.hidden()
|
||||
},
|
||||
foreground: {
|
||||
Circle().fill(Color.gray)
|
||||
.opacity(0.7)
|
||||
},
|
||||
locksInPlace: false)
|
||||
.onChange(of: self.joystickMonitor.xyPoint) { newValue in
|
||||
let scaledX = Float(newValue.x)
|
||||
let scaledY = Float(newValue.y) // my dumbass broke this by having -y instead of y :/
|
||||
print("Joystick Position: (\(scaledX), \(scaledY))")
|
||||
|
||||
if iscool != nil {
|
||||
Ryujinx.shared.virtualController.thumbstickMoved(.right, x: newValue.x, y: newValue.y)
|
||||
} else {
|
||||
Ryujinx.shared.virtualController.thumbstickMoved(.left, x: newValue.x, y: newValue.y)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
493
src/MeloNX/MeloNX/App/Views/GamesList/GameListView.swift
Normal file
493
src/MeloNX/MeloNX/App/Views/GamesList/GameListView.swift
Normal file
@ -0,0 +1,493 @@
|
||||
//
|
||||
// GameListView.swift
|
||||
// MeloNX
|
||||
//
|
||||
// Created by Stossy11 on 3/11/2024.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import UniformTypeIdentifiers
|
||||
|
||||
|
||||
struct GameLibraryView: View {
|
||||
@Binding var startemu: Game?
|
||||
@State private var games: [Game] = []
|
||||
@State private var searchText = ""
|
||||
@State private var isSearching = false
|
||||
@AppStorage("recentGames") private var recentGamesData: Data = Data()
|
||||
@State private var recentGames: [Game] = []
|
||||
@Environment(\.colorScheme) var colorScheme
|
||||
@State var firmwareInstaller = false
|
||||
@State var firmwareversion = "0"
|
||||
@State var isImporting: Bool = false
|
||||
@State var startgame = false
|
||||
|
||||
|
||||
var filteredGames: [Game] {
|
||||
if searchText.isEmpty {
|
||||
return games
|
||||
}
|
||||
return games.filter {
|
||||
$0.titleName.localizedCaseInsensitiveContains(searchText) ||
|
||||
$0.developer.localizedCaseInsensitiveContains(searchText)
|
||||
}
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
iOSNav {
|
||||
ScrollView {
|
||||
LazyVStack(alignment: .leading, spacing: 20) {
|
||||
if !isSearching {
|
||||
Text("Games")
|
||||
.font(.system(size: 34, weight: .bold))
|
||||
.padding(.horizontal)
|
||||
.padding(.top, 12)
|
||||
}
|
||||
|
||||
if games.isEmpty {
|
||||
VStack(spacing: 16) {
|
||||
Image(systemName: "gamecontroller.fill")
|
||||
.font(.system(size: 64))
|
||||
.foregroundColor(.secondary.opacity(0.7))
|
||||
.padding(.top, 60)
|
||||
Text("No Games Found")
|
||||
.font(.title2.bold())
|
||||
.foregroundColor(.primary)
|
||||
Text("Add ROM, Keys and Firmware to get started")
|
||||
.font(.subheadline)
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
.frame(maxWidth: .infinity)
|
||||
.padding(.top, 40)
|
||||
} else {
|
||||
if !isSearching && !recentGames.isEmpty {
|
||||
VStack(alignment: .leading, spacing: 12) {
|
||||
Text("Recent")
|
||||
.font(.title2.bold())
|
||||
.padding(.horizontal)
|
||||
|
||||
ScrollView(.horizontal, showsIndicators: false) {
|
||||
LazyHStack(spacing: 16) {
|
||||
ForEach(recentGames) { game in
|
||||
RecentGameCard(game: game, startemu: $startemu)
|
||||
.onTapGesture {
|
||||
addToRecentGames(game)
|
||||
startemu = game
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding(.horizontal)
|
||||
}
|
||||
}
|
||||
|
||||
VStack(alignment: .leading, spacing: 12) {
|
||||
Text("All Games")
|
||||
.font(.title2.bold())
|
||||
.padding(.horizontal)
|
||||
|
||||
LazyVStack(spacing: 2) {
|
||||
ForEach(filteredGames) { game in
|
||||
GameListRow(game: game, startemu: $startemu)
|
||||
.onTapGesture {
|
||||
addToRecentGames(game)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LazyVStack(spacing: 2) {
|
||||
ForEach(filteredGames) { game in
|
||||
GameListRow(game: game, startemu: $startemu)
|
||||
.onTapGesture {
|
||||
addToRecentGames(game)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.onAppear {
|
||||
loadGames()
|
||||
loadRecentGames()
|
||||
|
||||
|
||||
let firmware = Ryujinx.shared.fetchFirmwareVersion()
|
||||
firmwareversion = (firmware == "" ? "0" : firmware)
|
||||
}
|
||||
}
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .topBarLeading) {
|
||||
Menu {
|
||||
|
||||
Text("Firmware Version: \(firmwareversion)")
|
||||
.tint(.white)
|
||||
|
||||
if firmwareversion == "0" {
|
||||
Button {
|
||||
firmwareInstaller.toggle()
|
||||
} label: {
|
||||
Text("Install Firmware")
|
||||
}
|
||||
|
||||
} else {
|
||||
Button {
|
||||
Ryujinx.shared.removeFirmware()
|
||||
let firmware = Ryujinx.shared.fetchFirmwareVersion()
|
||||
firmwareversion = (firmware == "" ? "0" : firmware)
|
||||
} label: {
|
||||
Text("Remove Firmware")
|
||||
}
|
||||
|
||||
|
||||
Button {
|
||||
let game = Game(containerFolder: URL(string: "none")!, fileType: .item, fileURL: URL(string: "MiiMaker")!, titleName: "Mii Maker", titleId: "0", developer: "Nintendo", version: firmwareversion)
|
||||
|
||||
self.startemu = game
|
||||
} label: {
|
||||
Text("Mii Maker")
|
||||
}
|
||||
Button {
|
||||
|
||||
isImporting.toggle()
|
||||
} label: {
|
||||
Text("Open game from system")
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
let documentsUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
|
||||
let sharedurl = documentsUrl.absoluteString.replacingOccurrences(of: "file://", with: "shareddocuments://")
|
||||
let furl = URL(string: sharedurl)!
|
||||
if UIApplication.shared.canOpenURL(furl) {
|
||||
UIApplication.shared.open(furl, options: [:])
|
||||
}
|
||||
} label: {
|
||||
Text("Show MeloNX Folder")
|
||||
}
|
||||
} label: {
|
||||
Image(systemName: "ellipsis.circle")
|
||||
.foregroundColor(.blue)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
.background(Color(.systemGroupedBackground))
|
||||
.searchable(text: $searchText)
|
||||
.onChange(of: searchText) { _ in
|
||||
isSearching = !searchText.isEmpty
|
||||
}
|
||||
.fileImporter(isPresented: $firmwareInstaller, allowedContentTypes: [.item]) { result in
|
||||
switch result {
|
||||
|
||||
case .success(let url):
|
||||
|
||||
do {
|
||||
|
||||
let fun = url.startAccessingSecurityScopedResource()
|
||||
let path = url.path
|
||||
|
||||
Ryujinx.shared.installFirmware(firmwarePath: path)
|
||||
|
||||
firmwareversion = (Ryujinx.shared.fetchFirmwareVersion() == "" ? "0" : Ryujinx.shared.fetchFirmwareVersion())
|
||||
if fun {
|
||||
url.stopAccessingSecurityScopedResource()
|
||||
}
|
||||
}
|
||||
|
||||
case .failure(let error):
|
||||
print(error)
|
||||
}
|
||||
}
|
||||
.fileImporter(isPresented: $isImporting, allowedContentTypes: [.zip, .data]) { result in
|
||||
switch result {
|
||||
case .success(let url):
|
||||
guard url.startAccessingSecurityScopedResource() else {
|
||||
print("Failed to access security-scoped resource")
|
||||
return
|
||||
}
|
||||
defer { url.stopAccessingSecurityScopedResource() }
|
||||
|
||||
do {
|
||||
let handle = try FileHandle(forReadingFrom: url)
|
||||
let fileExtension = (url.pathExtension as NSString).utf8String
|
||||
let extensionPtr = UnsafeMutablePointer<CChar>(mutating: fileExtension)
|
||||
|
||||
var gameInfo = get_game_info(handle.fileDescriptor, extensionPtr)
|
||||
|
||||
var game = Game(containerFolder: url.deletingLastPathComponent(), fileType: .item, fileURL: url, titleName: "", titleId: "", developer: "", version: "")
|
||||
|
||||
game.titleName = withUnsafePointer(to: &gameInfo.TitleName) {
|
||||
$0.withMemoryRebound(to: UInt8.self, capacity: MemoryLayout.size(ofValue: $0)) {
|
||||
String(cString: $0)
|
||||
}
|
||||
}
|
||||
|
||||
game.developer = withUnsafePointer(to: &gameInfo.Developer) {
|
||||
$0.withMemoryRebound(to: UInt8.self, capacity: MemoryLayout.size(ofValue: $0)) {
|
||||
String(cString: $0)
|
||||
}
|
||||
}
|
||||
|
||||
game.titleId = String(gameInfo.TitleId)
|
||||
|
||||
print(String(gameInfo.TitleId))
|
||||
|
||||
|
||||
game.version = String(gameInfo.Version)
|
||||
|
||||
game.icon = game.createImage(from: gameInfo)
|
||||
|
||||
|
||||
DispatchQueue.main.async {
|
||||
startemu = game
|
||||
}
|
||||
} catch {
|
||||
print(error)
|
||||
}
|
||||
|
||||
|
||||
case .failure(let err):
|
||||
print("File import failed: \(err.localizedDescription)")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
private func addToRecentGames(_ game: Game) {
|
||||
recentGames.removeAll { $0.id == game.id }
|
||||
|
||||
recentGames.insert(game, at: 0)
|
||||
|
||||
if recentGames.count > 5 {
|
||||
recentGames = Array(recentGames.prefix(5))
|
||||
}
|
||||
|
||||
saveRecentGames()
|
||||
}
|
||||
|
||||
private func saveRecentGames() {
|
||||
do {
|
||||
let encoder = JSONEncoder()
|
||||
let data = try encoder.encode(recentGames)
|
||||
recentGamesData = data
|
||||
} catch {
|
||||
print("Error saving recent games: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
private func loadRecentGames() {
|
||||
do {
|
||||
let decoder = JSONDecoder()
|
||||
recentGames = try decoder.decode([Game].self, from: recentGamesData)
|
||||
} catch {
|
||||
print("Error loading recent games: \(error)")
|
||||
recentGames = []
|
||||
}
|
||||
}
|
||||
|
||||
private func loadGames() {
|
||||
let fileManager = FileManager.default
|
||||
guard let documentsDirectory = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first else { return }
|
||||
|
||||
let romsDirectory = documentsDirectory.appendingPathComponent("roms")
|
||||
|
||||
// Check if "roms" folder exists; if not, create it
|
||||
if !fileManager.fileExists(atPath: romsDirectory.path) {
|
||||
do {
|
||||
try fileManager.createDirectory(at: romsDirectory, withIntermediateDirectories: true, attributes: nil)
|
||||
} catch {
|
||||
print("Failed to create roms directory: \(error)")
|
||||
}
|
||||
}
|
||||
games = []
|
||||
// Load games only from "roms" folder
|
||||
do {
|
||||
let files = try fileManager.contentsOfDirectory(at: romsDirectory, includingPropertiesForKeys: nil)
|
||||
|
||||
files.forEach { fileURLCandidate in
|
||||
do {
|
||||
let handle = try FileHandle(forReadingFrom: fileURLCandidate)
|
||||
let fileExtension = (fileURLCandidate.pathExtension as NSString).utf8String
|
||||
let extensionPtr = UnsafeMutablePointer<CChar>(mutating: fileExtension)
|
||||
|
||||
var gameInfo = get_game_info(handle.fileDescriptor, extensionPtr)
|
||||
|
||||
var game = Game(containerFolder: romsDirectory, fileType: .item, fileURL: fileURLCandidate, titleName: "", titleId: "", developer: "", version: "")
|
||||
|
||||
game.titleName = withUnsafePointer(to: &gameInfo.TitleName) {
|
||||
$0.withMemoryRebound(to: UInt8.self, capacity: MemoryLayout.size(ofValue: $0)) {
|
||||
String(cString: $0)
|
||||
}
|
||||
}
|
||||
|
||||
game.developer = withUnsafePointer(to: &gameInfo.Developer) {
|
||||
$0.withMemoryRebound(to: UInt8.self, capacity: MemoryLayout.size(ofValue: $0)) {
|
||||
String(cString: $0)
|
||||
}
|
||||
}
|
||||
|
||||
game.titleId = String(gameInfo.TitleId)
|
||||
|
||||
|
||||
game.version = String(gameInfo.Version)
|
||||
|
||||
game.icon = game.createImage(from: gameInfo)
|
||||
|
||||
|
||||
games.append(game)
|
||||
} catch {
|
||||
print(error)
|
||||
}
|
||||
}
|
||||
|
||||
} catch {
|
||||
print("Error loading games from roms folder: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Game: Codable {
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case titleName, titleId, developer, version, fileURL
|
||||
}
|
||||
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
titleName = try container.decode(String.self, forKey: .titleName)
|
||||
titleId = try container.decode(String.self, forKey: .titleId)
|
||||
developer = try container.decode(String.self, forKey: .developer)
|
||||
version = try container.decode(String.self, forKey: .version)
|
||||
fileURL = try container.decode(URL.self, forKey: .fileURL)
|
||||
|
||||
// Initialize other properties
|
||||
self.containerFolder = fileURL.deletingLastPathComponent()
|
||||
self.fileType = .item
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(titleName, forKey: .titleName)
|
||||
try container.encode(titleId, forKey: .titleId)
|
||||
try container.encode(developer, forKey: .developer)
|
||||
try container.encode(version, forKey: .version)
|
||||
try container.encode(fileURL, forKey: .fileURL)
|
||||
}
|
||||
}
|
||||
|
||||
struct RecentGameCard: View {
|
||||
let game: Game
|
||||
@Binding var startemu: Game?
|
||||
@Environment(\.colorScheme) var colorScheme
|
||||
|
||||
var body: some View {
|
||||
Button(action: {
|
||||
startemu = game
|
||||
}) {
|
||||
VStack(alignment: .leading, spacing: 8) {
|
||||
if let icon = game.icon {
|
||||
Image(uiImage: icon)
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fill)
|
||||
.frame(width: 140, height: 140)
|
||||
.cornerRadius(12)
|
||||
} else {
|
||||
ZStack {
|
||||
RoundedRectangle(cornerRadius: 12)
|
||||
.fill(colorScheme == .dark ?
|
||||
Color(.systemGray5) : Color(.systemGray6))
|
||||
.frame(width: 140, height: 140)
|
||||
|
||||
Image(systemName: "gamecontroller.fill")
|
||||
.font(.system(size: 40))
|
||||
.foregroundColor(.gray)
|
||||
}
|
||||
}
|
||||
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
Text(game.titleName)
|
||||
.font(.subheadline.bold())
|
||||
.lineLimit(1)
|
||||
|
||||
Text(game.developer)
|
||||
.font(.caption)
|
||||
.foregroundColor(.secondary)
|
||||
.lineLimit(1)
|
||||
}
|
||||
.padding(.horizontal, 4)
|
||||
}
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
}
|
||||
}
|
||||
|
||||
struct GameListRow: View {
|
||||
let game: Game
|
||||
@Binding var startemu: Game?
|
||||
@Environment(\.colorScheme) var colorScheme
|
||||
|
||||
var body: some View {
|
||||
Button(action: {
|
||||
startemu = game
|
||||
}) {
|
||||
HStack(spacing: 16) {
|
||||
// Game Icon
|
||||
if let icon = game.icon {
|
||||
Image(uiImage: icon)
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fill)
|
||||
.frame(width: 45, height: 45)
|
||||
.cornerRadius(8)
|
||||
} else {
|
||||
ZStack {
|
||||
RoundedRectangle(cornerRadius: 8)
|
||||
.fill(colorScheme == .dark ?
|
||||
Color(.systemGray5) : Color(.systemGray6))
|
||||
.frame(width: 45, height: 45)
|
||||
|
||||
Image(systemName: "gamecontroller.fill")
|
||||
.font(.system(size: 20))
|
||||
.foregroundColor(.gray)
|
||||
}
|
||||
}
|
||||
|
||||
// Game Info
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
Text(game.titleName)
|
||||
.font(.body)
|
||||
.foregroundColor(.primary)
|
||||
|
||||
Text(game.developer)
|
||||
.font(.subheadline)
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
|
||||
Spacer()
|
||||
|
||||
Image(systemName: "play.circle.fill")
|
||||
.font(.title2)
|
||||
.foregroundColor(.accentColor)
|
||||
.opacity(0.8)
|
||||
}
|
||||
.padding(.horizontal)
|
||||
.padding(.vertical, 8)
|
||||
.background(Color(.systemBackground))
|
||||
.contextMenu {
|
||||
Button {
|
||||
startemu = game
|
||||
} label: {
|
||||
Label("Play Now", systemImage: "play.fill")
|
||||
}
|
||||
|
||||
Button {
|
||||
// Add info action
|
||||
} label: {
|
||||
Label("Game Info", systemImage: "info.circle")
|
||||
}
|
||||
}
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
}
|
||||
}
|
430
src/MeloNX/MeloNX/App/Views/SettingsView/SettingsView.swift
Normal file
430
src/MeloNX/MeloNX/App/Views/SettingsView/SettingsView.swift
Normal file
@ -0,0 +1,430 @@
|
||||
//
|
||||
// SettingsView.swift
|
||||
// MeloNX
|
||||
//
|
||||
// Created by Stossy11 on 25/11/2024.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import SwiftSVG
|
||||
|
||||
struct SettingsView: View {
|
||||
@Binding var config: Ryujinx.Configuration
|
||||
@Binding var MoltenVKSettings: [MoltenVKSettings]
|
||||
|
||||
@Binding var controllersList: [Controller]
|
||||
@Binding var currentControllers: [Controller]
|
||||
|
||||
@Binding var onscreencontroller: Controller
|
||||
@AppStorage("useTrollStore") var useTrollStore: Bool = false
|
||||
|
||||
@AppStorage("ignoreJIT") var ignoreJIT: Bool = false
|
||||
|
||||
var memoryManagerModes = [
|
||||
("HostMapped", "Host (fast)"),
|
||||
("HostMappedUnsafe", "Host Unchecked (fast, unstable / unsafe)"),
|
||||
("SoftwarePageTable", "Software (slow)"),
|
||||
]
|
||||
|
||||
@AppStorage("RyuDemoControls") var ryuDemo: Bool = false
|
||||
@AppStorage("MTL_HUD_ENABLED") var metalHUDEnabled: Bool = false
|
||||
|
||||
@AppStorage("performacehud") var performacehud: Bool = false
|
||||
|
||||
@State private var showResolutionInfo = false
|
||||
@State private var searchText = ""
|
||||
|
||||
var filteredMemoryModes: [(String, String)] {
|
||||
guard !searchText.isEmpty else { return memoryManagerModes }
|
||||
return memoryManagerModes.filter { $0.1.localizedCaseInsensitiveContains(searchText) }
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
iOSNav {
|
||||
List {
|
||||
|
||||
|
||||
// Graphics & Performance
|
||||
Section {
|
||||
Toggle(isOn: $config.fullscreen) {
|
||||
labelWithIcon("Fullscreen", iconName: "rectangle.expand.vertical")
|
||||
}
|
||||
.tint(.blue)
|
||||
|
||||
Toggle(isOn: $config.disableShaderCache) {
|
||||
labelWithIcon("Shader Cache", iconName: "memorychip")
|
||||
}
|
||||
.tint(.blue)
|
||||
|
||||
Toggle(isOn: $config.enableTextureRecompression) {
|
||||
labelWithIcon("Texture Recompression", iconName: "rectangle.compress.vertical")
|
||||
}
|
||||
.tint(.blue)
|
||||
|
||||
Toggle(isOn: $config.disableDockedMode) {
|
||||
labelWithIcon("Docked Mode", iconName: "dock.rectangle")
|
||||
}
|
||||
.tint(.blue)
|
||||
|
||||
VStack(alignment: .leading, spacing: 10) {
|
||||
HStack {
|
||||
labelWithIcon("Resolution Scale", iconName: "magnifyingglass")
|
||||
.font(.headline)
|
||||
Spacer()
|
||||
Button {
|
||||
showResolutionInfo.toggle()
|
||||
} label: {
|
||||
Image(systemName: "info.circle")
|
||||
.symbolRenderingMode(.hierarchical)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
.help("Learn more about Resolution Scale")
|
||||
.alert(isPresented: $showResolutionInfo) {
|
||||
Alert(
|
||||
title: Text("Resolution Scale"),
|
||||
message: Text("Adjust the internal rendering resolution. Higher values improve visuals but may reduce performance."),
|
||||
dismissButton: .default(Text("OK"))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Slider(value: $config.resscale, in: 0.1...3.0, step: 0.1) {
|
||||
Text("Resolution Scale")
|
||||
} minimumValueLabel: {
|
||||
Text("0.1x")
|
||||
.font(.footnote)
|
||||
.foregroundColor(.secondary)
|
||||
} maximumValueLabel: {
|
||||
Text("3.0x")
|
||||
.font(.footnote)
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
Text("\(config.resscale, specifier: "%.2f")x")
|
||||
.font(.subheadline)
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
.padding(.vertical, 8)
|
||||
|
||||
Toggle(isOn: $performacehud) {
|
||||
labelWithIcon("Performance Overlay", iconName: "speedometer")
|
||||
}
|
||||
.tint(.blue)
|
||||
} header: {
|
||||
Text("Graphics & Performance")
|
||||
.font(.title3.weight(.semibold))
|
||||
.textCase(nil)
|
||||
.headerProminence(.increased)
|
||||
} footer: {
|
||||
Text("Fine-tune graphics and performance to suit your device and preferences.")
|
||||
}
|
||||
|
||||
// Input Selector
|
||||
Section {
|
||||
if !controllersList.filter({ !currentControllers.contains($0) }).isEmpty {
|
||||
DisclosureGroup("Unselected Controllers") {
|
||||
ForEach(controllersList.filter { !currentControllers.contains($0) }) { controller in
|
||||
var customBinding: Binding<Bool> {
|
||||
Binding(
|
||||
get: { currentControllers.contains(controller) },
|
||||
set: { bool in
|
||||
if !bool {
|
||||
currentControllers.removeAll(where: { $0.id == controller.id })
|
||||
} else {
|
||||
currentControllers.append(controller)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
Toggle(isOn: customBinding) {
|
||||
Text(controller.name)
|
||||
.font(.body)
|
||||
}
|
||||
.tint(.blue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
ForEach(controllersList) { controller in
|
||||
|
||||
var customBinding: Binding<Bool> {
|
||||
Binding(
|
||||
get: { currentControllers.contains(controller) },
|
||||
set: { bool in
|
||||
if !bool {
|
||||
currentControllers.removeAll(where: { $0.id == controller.id })
|
||||
} else {
|
||||
currentControllers.append(controller)
|
||||
}
|
||||
// toggleController(controller)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
if customBinding.wrappedValue {
|
||||
DisclosureGroup {
|
||||
Toggle(isOn: customBinding) {
|
||||
Text(controller.name)
|
||||
.font(.body)
|
||||
}
|
||||
.tint(.blue)
|
||||
} label: {
|
||||
let controller = String((controllersList.firstIndex(where: { $0.id == controller.id }) ?? 0) + 1)
|
||||
|
||||
|
||||
Text("Player \(controller)")
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} header: {
|
||||
Text("Input Selector")
|
||||
.font(.title3.weight(.semibold))
|
||||
.textCase(nil)
|
||||
.headerProminence(.increased)
|
||||
} footer: {
|
||||
Text("Select input devices and on-screen controls to play with. ")
|
||||
}
|
||||
|
||||
// Input Settings
|
||||
Section {
|
||||
|
||||
Toggle(isOn: $config.listinputids) {
|
||||
labelWithIcon("List Input IDs", iconName: "list.bullet")
|
||||
}
|
||||
.tint(.blue)
|
||||
|
||||
Toggle(isOn: $ryuDemo) {
|
||||
labelWithIcon("On-Screen Controller (Demo)", iconName: "hand.draw")
|
||||
}
|
||||
.tint(.blue)
|
||||
.disabled(true)
|
||||
} header: {
|
||||
Text("Input Settings")
|
||||
.font(.title3.weight(.semibold))
|
||||
.textCase(nil)
|
||||
.headerProminence(.increased)
|
||||
} footer: {
|
||||
Text("Configure input devices and on-screen controls for easier navigation and play.")
|
||||
}
|
||||
|
||||
// CPU Mode
|
||||
Section {
|
||||
if filteredMemoryModes.isEmpty {
|
||||
Text("No matches for \"\(searchText)\"")
|
||||
.foregroundColor(.secondary)
|
||||
} else {
|
||||
Picker(selection: $config.memoryManagerMode) {
|
||||
ForEach(filteredMemoryModes, id: \.0) { key, displayName in
|
||||
Text(displayName).tag(key)
|
||||
}
|
||||
} label: {
|
||||
labelWithIcon("Memory Manager Mode", iconName: "gearshape")
|
||||
}
|
||||
}
|
||||
} header: {
|
||||
Text("CPU Mode")
|
||||
.font(.title3.weight(.semibold))
|
||||
.textCase(nil)
|
||||
.headerProminence(.increased)
|
||||
} footer: {
|
||||
Text("Select how memory is managed. 'Host (fast)' is best for most users.")
|
||||
}
|
||||
|
||||
|
||||
// Other Settings
|
||||
Section {
|
||||
|
||||
Toggle(isOn: $useTrollStore) {
|
||||
labelWithIcon("TrollStore", iconName: "troll.svg")
|
||||
}
|
||||
.tint(.blue)
|
||||
|
||||
Toggle(isOn: $config.debuglogs) {
|
||||
labelWithIcon("Debug Logs", iconName: "exclamationmark.bubble")
|
||||
}
|
||||
.tint(.blue)
|
||||
|
||||
Toggle(isOn: $config.tracelogs) {
|
||||
labelWithIcon("Trace Logs", iconName: "waveform.path")
|
||||
}
|
||||
.tint(.blue)
|
||||
} header: {
|
||||
Text("Miscellaneous Options")
|
||||
.font(.title3.weight(.semibold))
|
||||
.textCase(nil)
|
||||
.headerProminence(.increased)
|
||||
} footer: {
|
||||
Text("Enable logs for troubleshooting and Enable automatic TrollStore JIT.")
|
||||
}
|
||||
|
||||
// Advanced
|
||||
Section {
|
||||
DisclosureGroup {
|
||||
|
||||
HStack {
|
||||
labelWithIcon("Page Size", iconName: "textformat.size")
|
||||
Spacer()
|
||||
Text("\(String(Int(getpagesize())))")
|
||||
.foregroundColor(.secondary)
|
||||
|
||||
}
|
||||
|
||||
TextField("Additional Arguments", text: Binding(
|
||||
get: {
|
||||
config.additionalArgs.joined(separator: " ")
|
||||
},
|
||||
set: { newValue in
|
||||
config.additionalArgs = newValue
|
||||
.split(separator: ",")
|
||||
.map { $0.trimmingCharacters(in: .whitespaces) }
|
||||
}
|
||||
))
|
||||
.textInputAutocapitalization(.none)
|
||||
.disableAutocorrection(true)
|
||||
|
||||
|
||||
Button {
|
||||
Ryujinx.shared.removeFirmware()
|
||||
|
||||
} label: {
|
||||
Text("Remove Firmware")
|
||||
.font(.body)
|
||||
}
|
||||
} label: {
|
||||
Text("Advanced Options")
|
||||
}
|
||||
} header: {
|
||||
Text("Advanced")
|
||||
.font(.title3.weight(.semibold))
|
||||
.textCase(nil)
|
||||
.headerProminence(.increased)
|
||||
} footer: {
|
||||
Text("For advanced users. See page size or add custom arguments for experimental features. (Please don't touch this if you don't know what you're doing)")
|
||||
}
|
||||
|
||||
}
|
||||
.searchable(text: $searchText, placement: .navigationBarDrawer(displayMode: .always))
|
||||
.navigationTitle("Settings")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.listStyle(.insetGrouped)
|
||||
.onAppear {
|
||||
if let configs = loadSettings() {
|
||||
self.config = configs
|
||||
}
|
||||
}
|
||||
.onChange(of: config) { _ in
|
||||
saveSettings()
|
||||
}
|
||||
}
|
||||
.navigationViewStyle(.stack)
|
||||
}
|
||||
|
||||
private func toggleController(_ controller: Controller) {
|
||||
if currentControllers.contains(where: { $0.id == controller.id }) {
|
||||
currentControllers.removeAll(where: { $0.id == controller.id })
|
||||
} else {
|
||||
currentControllers.append(controller)
|
||||
}
|
||||
}
|
||||
|
||||
func saveSettings() {
|
||||
#if targetEnvironment(simulator)
|
||||
|
||||
print("Saving Settings")
|
||||
#else
|
||||
do {
|
||||
let encoder = JSONEncoder()
|
||||
encoder.outputFormatting = .prettyPrinted
|
||||
let data = try encoder.encode(config)
|
||||
let jsonString = String(data: data, encoding: .utf8)
|
||||
UserDefaults.standard.set(jsonString, forKey: "config")
|
||||
} catch {
|
||||
print("Failed to save settings: \(error)")
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Original loadSettings function assumed to exist
|
||||
func loadSettings() -> Ryujinx.Configuration? {
|
||||
|
||||
#if targetEnvironment(simulator)
|
||||
print("Running on Simulator")
|
||||
|
||||
return Ryujinx.Configuration(gamepath: "")
|
||||
#else
|
||||
guard let jsonString = UserDefaults.standard.string(forKey: "config"),
|
||||
let data = jsonString.data(using: .utf8) else {
|
||||
return nil
|
||||
}
|
||||
do {
|
||||
let decoder = JSONDecoder()
|
||||
let configs = try decoder.decode(Ryujinx.Configuration.self, from: data)
|
||||
return configs
|
||||
} catch {
|
||||
print("Failed to load settings: \(error)")
|
||||
return nil
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private func labelWithIcon(_ text: String, iconName: String, flipimage: Bool? = nil) -> some View {
|
||||
HStack(spacing: 8) {
|
||||
if iconName.hasSuffix(".svg"){
|
||||
if let flipimage, flipimage {
|
||||
SVGView(svgName: iconName, color: .blue)
|
||||
.symbolRenderingMode(.hierarchical)
|
||||
.frame(width: 20, height: 20)
|
||||
.rotation3DEffect(.degrees(180), axis: (x: 0, y: 1, z: 0))
|
||||
} else {
|
||||
SVGView(svgName: iconName, color: .blue)
|
||||
.symbolRenderingMode(.hierarchical)
|
||||
.frame(width: 20, height: 20)
|
||||
}
|
||||
} else if !iconName.isEmpty {
|
||||
Image(systemName: iconName)
|
||||
.symbolRenderingMode(.hierarchical)
|
||||
.foregroundStyle(.blue)
|
||||
}
|
||||
Text(text)
|
||||
}
|
||||
.font(.body)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct SVGView: UIViewRepresentable {
|
||||
var svgName: String
|
||||
var color: Color = Color.black
|
||||
|
||||
func makeUIView(context: Context) -> UIView {
|
||||
var svgName = svgName
|
||||
var hammock = UIView()
|
||||
|
||||
if svgName.hasSuffix(".svg") {
|
||||
svgName.removeLast(4)
|
||||
}
|
||||
|
||||
|
||||
|
||||
let svgLayer = UIView(SVGNamed: svgName) { svgLayer in
|
||||
svgLayer.fillColor = UIColor(color).cgColor // Apply the provided color
|
||||
svgLayer.resizeToFit(hammock.frame)
|
||||
hammock.layer.addSublayer(svgLayer)
|
||||
}
|
||||
|
||||
return hammock
|
||||
}
|
||||
|
||||
func updateUIView(_ uiView: UIView, context: Context) {
|
||||
// Update the SVG view's fill color when the color changes
|
||||
if let svgLayer = uiView.layer.sublayers?.first as? CAShapeLayer {
|
||||
svgLayer.fillColor = UIColor(color).cgColor
|
||||
}
|
||||
}
|
||||
}
|
34
src/MeloNX/MeloNX/App/Views/TabView/TabView.swift
Normal file
34
src/MeloNX/MeloNX/App/Views/TabView/TabView.swift
Normal file
@ -0,0 +1,34 @@
|
||||
//
|
||||
// TabView.swift
|
||||
// MeloNX
|
||||
//
|
||||
// Created by Stossy11 on 10/12/2024.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import UniformTypeIdentifiers
|
||||
|
||||
|
||||
struct MainTabView: View {
|
||||
@Binding var startemu: Game?
|
||||
@Binding var config: Ryujinx.Configuration
|
||||
@Binding var MVKconfig: [MoltenVKSettings]
|
||||
@Binding var controllersList: [Controller]
|
||||
@Binding var currentControllers: [Controller]
|
||||
|
||||
@Binding var onscreencontroller: Controller
|
||||
|
||||
var body: some View {
|
||||
TabView {
|
||||
GameLibraryView(startemu: $startemu)
|
||||
.tabItem {
|
||||
Label("Games", systemImage: "gamecontroller.fill")
|
||||
}
|
||||
|
||||
SettingsView(config: $config, MoltenVKSettings: $MVKconfig, controllersList: $controllersList, currentControllers: $currentControllers, onscreencontroller: $onscreencontroller)
|
||||
.tabItem {
|
||||
Label("Settings", systemImage: "gear")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "nxgradientpng.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"size" : "1024x1024"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"size" : "1024x1024"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "tinted"
|
||||
}
|
||||
],
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"size" : "1024x1024"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 98 KiB |
6
src/MeloNX/MeloNX/Assets/Assets.xcassets/Contents.json
Normal file
6
src/MeloNX/MeloNX/Assets/Assets.xcassets/Contents.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
{
|
||||
"data" : [
|
||||
{
|
||||
"filename" : "Troll-Face.svg",
|
||||
"idiom" : "universal",
|
||||
"universal-type-identifier" : "public.svg-image"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 26 KiB |
@ -0,0 +1,18 @@
|
||||
//
|
||||
// SoftwareKeyboard.h
|
||||
// SoftwareKeyboard
|
||||
//
|
||||
// Created by Stossy11 on 19/12/2024.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
//! Project version number for SoftwareKeyboard.
|
||||
FOUNDATION_EXPORT double SoftwareKeyboardVersionNumber;
|
||||
|
||||
//! Project version string for SoftwareKeyboard.
|
||||
FOUNDATION_EXPORT const unsigned char SoftwareKeyboardVersionString[];
|
||||
|
||||
// In this header, you should import all the public headers of your framework using statements like #import <SoftwareKeyboard/PublicHeader.h>
|
||||
|
||||
|
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,38 @@
|
||||
// swift-interface-format-version: 1.0
|
||||
// swift-compiler-version: Apple Swift version 6.0.3 effective-5.10 (swiftlang-6.0.3.1.4 clang-1600.0.30)
|
||||
// swift-module-flags: -target arm64-apple-ios14.0 -enable-objc-interop -enable-library-evolution -swift-version 5 -enforce-exclusivity=checked -Onone -enable-experimental-feature OpaqueTypeErasure -enable-bare-slash-regex -module-name SoftwareKeyboard
|
||||
@_exported import SoftwareKeyboard
|
||||
import Swift
|
||||
import UIKit
|
||||
import _Concurrency
|
||||
import _StringProcessing
|
||||
import _SwiftConcurrencyShims
|
||||
@objc public enum KeyboardMode : Swift.UInt32 {
|
||||
case `default` = 0
|
||||
case numeric = 1
|
||||
case ascii = 2
|
||||
case fullLatin = 3
|
||||
case alphabet = 4
|
||||
case simplifiedChinese = 5
|
||||
case traditionalChinese = 6
|
||||
case korean = 7
|
||||
case languageSet2 = 8
|
||||
case languageSet2Latin = 9
|
||||
public init?(rawValue: Swift.UInt32)
|
||||
public typealias RawValue = Swift.UInt32
|
||||
public var rawValue: Swift.UInt32 {
|
||||
get
|
||||
}
|
||||
}
|
||||
public struct SoftwareKeyboardUiArgs {
|
||||
public var keyboardMode: SoftwareKeyboard.KeyboardMode
|
||||
public var headerText: Swift.String
|
||||
public var subtitleText: Swift.String
|
||||
public var submitText: Swift.String
|
||||
public var stringLengthMin: Swift.Int32
|
||||
public var stringLengthMax: Swift.Int32
|
||||
public var initialText: Swift.String?
|
||||
}
|
||||
extension SoftwareKeyboard.KeyboardMode : Swift.Equatable {}
|
||||
extension SoftwareKeyboard.KeyboardMode : Swift.Hashable {}
|
||||
extension SoftwareKeyboard.KeyboardMode : Swift.RawRepresentable {}
|
Binary file not shown.
@ -0,0 +1,38 @@
|
||||
// swift-interface-format-version: 1.0
|
||||
// swift-compiler-version: Apple Swift version 6.0.3 effective-5.10 (swiftlang-6.0.3.1.4 clang-1600.0.30)
|
||||
// swift-module-flags: -target arm64-apple-ios14.0 -enable-objc-interop -enable-library-evolution -swift-version 5 -enforce-exclusivity=checked -Onone -enable-experimental-feature OpaqueTypeErasure -enable-bare-slash-regex -module-name SoftwareKeyboard
|
||||
@_exported import SoftwareKeyboard
|
||||
import Swift
|
||||
import UIKit
|
||||
import _Concurrency
|
||||
import _StringProcessing
|
||||
import _SwiftConcurrencyShims
|
||||
@objc public enum KeyboardMode : Swift.UInt32 {
|
||||
case `default` = 0
|
||||
case numeric = 1
|
||||
case ascii = 2
|
||||
case fullLatin = 3
|
||||
case alphabet = 4
|
||||
case simplifiedChinese = 5
|
||||
case traditionalChinese = 6
|
||||
case korean = 7
|
||||
case languageSet2 = 8
|
||||
case languageSet2Latin = 9
|
||||
public init?(rawValue: Swift.UInt32)
|
||||
public typealias RawValue = Swift.UInt32
|
||||
public var rawValue: Swift.UInt32 {
|
||||
get
|
||||
}
|
||||
}
|
||||
public struct SoftwareKeyboardUiArgs {
|
||||
public var keyboardMode: SoftwareKeyboard.KeyboardMode
|
||||
public var headerText: Swift.String
|
||||
public var subtitleText: Swift.String
|
||||
public var submitText: Swift.String
|
||||
public var stringLengthMin: Swift.Int32
|
||||
public var stringLengthMax: Swift.Int32
|
||||
public var initialText: Swift.String?
|
||||
}
|
||||
extension SoftwareKeyboard.KeyboardMode : Swift.Equatable {}
|
||||
extension SoftwareKeyboard.KeyboardMode : Swift.Hashable {}
|
||||
extension SoftwareKeyboard.KeyboardMode : Swift.RawRepresentable {}
|
Binary file not shown.
@ -0,0 +1,6 @@
|
||||
framework module SoftwareKeyboard {
|
||||
umbrella header "SoftwareKeyboard.h"
|
||||
export *
|
||||
|
||||
module * { export * }
|
||||
}
|
Binary file not shown.
BIN
src/MeloNX/MeloNX/Dependencies/Dynamic Libraries/libMoltenVK.dylib
Executable file
BIN
src/MeloNX/MeloNX/Dependencies/Dynamic Libraries/libMoltenVK.dylib
Executable file
Binary file not shown.
BIN
src/MeloNX/MeloNX/Dependencies/Dynamic Libraries/libavcodec.dylib
Executable file
BIN
src/MeloNX/MeloNX/Dependencies/Dynamic Libraries/libavcodec.dylib
Executable file
Binary file not shown.
BIN
src/MeloNX/MeloNX/Dependencies/Dynamic Libraries/libavutil.dylib
Executable file
BIN
src/MeloNX/MeloNX/Dependencies/Dynamic Libraries/libavutil.dylib
Executable file
Binary file not shown.
BIN
src/MeloNX/MeloNX/Dependencies/Ryujinx.Headless.SDL2.dylib
Normal file
BIN
src/MeloNX/MeloNX/Dependencies/Ryujinx.Headless.SDL2.dylib
Normal file
Binary file not shown.
@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>AvailableLibraries</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>BinaryPath</key>
|
||||
<string>MoltenVK.framework/MoltenVK</string>
|
||||
<key>LibraryIdentifier</key>
|
||||
<string>ios-arm64</string>
|
||||
<key>LibraryPath</key>
|
||||
<string>MoltenVK.framework</string>
|
||||
<key>SupportedArchitectures</key>
|
||||
<array>
|
||||
<string>arm64</string>
|
||||
</array>
|
||||
<key>SupportedPlatform</key>
|
||||
<string>ios</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>XFWK</string>
|
||||
<key>XCFrameworkFormatVersion</key>
|
||||
<string>1.0</string>
|
||||
</dict>
|
||||
</plist>
|
Binary file not shown.
Binary file not shown.
@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>AvailableLibraries</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>BinaryPath</key>
|
||||
<string>SDL2.framework/SDL2</string>
|
||||
<key>LibraryIdentifier</key>
|
||||
<string>ios-arm64_x86_64-simulator</string>
|
||||
<key>LibraryPath</key>
|
||||
<string>SDL2.framework</string>
|
||||
<key>SupportedArchitectures</key>
|
||||
<array>
|
||||
<string>arm64</string>
|
||||
<string>x86_64</string>
|
||||
</array>
|
||||
<key>SupportedPlatform</key>
|
||||
<string>ios</string>
|
||||
<key>SupportedPlatformVariant</key>
|
||||
<string>simulator</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>BinaryPath</key>
|
||||
<string>SDL2.framework/SDL2</string>
|
||||
<key>LibraryIdentifier</key>
|
||||
<string>ios-arm64</string>
|
||||
<key>LibraryPath</key>
|
||||
<string>SDL2.framework</string>
|
||||
<key>SupportedArchitectures</key>
|
||||
<array>
|
||||
<string>arm64</string>
|
||||
</array>
|
||||
<key>SupportedPlatform</key>
|
||||
<string>ios</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>XFWK</string>
|
||||
<key>XCFrameworkFormatVersion</key>
|
||||
<string>1.0</string>
|
||||
</dict>
|
||||
</plist>
|
@ -0,0 +1,48 @@
|
||||
# based on the files generated by CMake's write_basic_package_version_file
|
||||
|
||||
# SDL2 CMake version configuration file:
|
||||
# This file is meant to be placed in Resources/CMake of a SDL2 framework
|
||||
|
||||
if(NOT EXISTS "${CMAKE_CURRENT_LIST_DIR}/../../Headers/SDL_version.h")
|
||||
message(AUTHOR_WARNING "Could not find SDL_version.h. This script is meant to be placed in the Resources/CMake directory of SDL2.framework")
|
||||
return()
|
||||
endif()
|
||||
|
||||
file(READ "${CMAKE_CURRENT_LIST_DIR}/../../Headers/SDL_version.h" _sdl_version_h)
|
||||
string(REGEX MATCH "#define[ \t]+SDL_MAJOR_VERSION[ \t]+([0-9]+)" _sdl_major_re "${_sdl_version_h}")
|
||||
set(_sdl_major "${CMAKE_MATCH_1}")
|
||||
string(REGEX MATCH "#define[ \t]+SDL_MINOR_VERSION[ \t]+([0-9]+)" _sdl_minor_re "${_sdl_version_h}")
|
||||
set(_sdl_minor "${CMAKE_MATCH_1}")
|
||||
string(REGEX MATCH "#define[ \t]+SDL_PATCHLEVEL[ \t]+([0-9]+)" _sdl_patch_re "${_sdl_version_h}")
|
||||
set(_sdl_patch "${CMAKE_MATCH_1}")
|
||||
if(_sdl_major_re AND _sdl_minor_re AND _sdl_patch_re)
|
||||
set(PACKAGE_VERSION "${_sdl_major}.${_sdl_minor}.${_sdl_patch}")
|
||||
else()
|
||||
message(AUTHOR_WARNING "Could not extract version from SDL_version.h.")
|
||||
return()
|
||||
endif()
|
||||
|
||||
if(PACKAGE_FIND_VERSION_RANGE)
|
||||
# Package version must be in the requested version range
|
||||
if ((PACKAGE_FIND_VERSION_RANGE_MIN STREQUAL "INCLUDE" AND PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION_MIN)
|
||||
OR ((PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "INCLUDE" AND PACKAGE_VERSION VERSION_GREATER PACKAGE_FIND_VERSION_MAX)
|
||||
OR (PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "EXCLUDE" AND PACKAGE_VERSION VERSION_GREATER_EQUAL PACKAGE_FIND_VERSION_MAX)))
|
||||
set(PACKAGE_VERSION_COMPATIBLE FALSE)
|
||||
else()
|
||||
set(PACKAGE_VERSION_COMPATIBLE TRUE)
|
||||
endif()
|
||||
else()
|
||||
if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION)
|
||||
set(PACKAGE_VERSION_COMPATIBLE FALSE)
|
||||
else()
|
||||
set(PACKAGE_VERSION_COMPATIBLE TRUE)
|
||||
if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION)
|
||||
set(PACKAGE_VERSION_EXACT TRUE)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# if the using project doesn't have CMAKE_SIZEOF_VOID_P set, fail.
|
||||
if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "")
|
||||
set(PACKAGE_VERSION_UNSUITABLE TRUE)
|
||||
endif()
|
@ -0,0 +1,69 @@
|
||||
# SDL2 CMake configuration file:
|
||||
# This file is meant to be placed in Resources/CMake of a SDL2 framework
|
||||
|
||||
# INTERFACE_LINK_OPTIONS needs CMake 3.12
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
|
||||
include(FeatureSummary)
|
||||
set_package_properties(SDL2 PROPERTIES
|
||||
URL "https://www.libsdl.org/"
|
||||
DESCRIPTION "low level access to audio, keyboard, mouse, joystick, and graphics hardware"
|
||||
)
|
||||
|
||||
# Copied from `configure_package_config_file`
|
||||
macro(set_and_check _var _file)
|
||||
set(${_var} "${_file}")
|
||||
if(NOT EXISTS "${_file}")
|
||||
message(FATAL_ERROR "File or directory ${_file} referenced by variable ${_var} does not exist !")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
# Copied from `configure_package_config_file`
|
||||
macro(check_required_components _NAME)
|
||||
foreach(comp ${${_NAME}_FIND_COMPONENTS})
|
||||
if(NOT ${_NAME}_${comp}_FOUND)
|
||||
if(${_NAME}_FIND_REQUIRED_${comp})
|
||||
set(${_NAME}_FOUND FALSE)
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
||||
set(SDL2_FOUND TRUE)
|
||||
|
||||
string(REGEX REPLACE "SDL2\\.framework.*" "SDL2.framework" SDL2_FRAMEWORK_PATH "${CMAKE_CURRENT_LIST_DIR}")
|
||||
string(REGEX REPLACE "SDL2\\.framework.*" "" SDL2_FRAMEWORK_PARENT_PATH "${CMAKE_CURRENT_LIST_DIR}")
|
||||
|
||||
# For compatibility with autotools sdl2-config.cmake, provide SDL2_* variables.
|
||||
|
||||
set_and_check(SDL2_PREFIX "${SDL2_FRAMEWORK_PATH}")
|
||||
set_and_check(SDL2_EXEC_PREFIX "${SDL2_FRAMEWORK_PATH}")
|
||||
set_and_check(SDL2_INCLUDE_DIR "${SDL2_FRAMEWORK_PATH}/Headers")
|
||||
set(SDL2_INCLUDE_DIRS "${SDL2_INCLUDE_DIR};${SDL2_FRAMEWORK_PATH}")
|
||||
set_and_check(SDL2_BINDIR "${SDL2_FRAMEWORK_PATH}")
|
||||
set_and_check(SDL2_LIBDIR "${SDL2_FRAMEWORK_PATH}")
|
||||
|
||||
set(SDL2_LIBRARIES "SDL2::SDL2")
|
||||
|
||||
# All targets are created, even when some might not be requested though COMPONENTS.
|
||||
# This is done for compatibility with CMake generated SDL2-target.cmake files.
|
||||
|
||||
if(NOT TARGET SDL2::SDL2)
|
||||
add_library(SDL2::SDL2 INTERFACE IMPORTED)
|
||||
set_target_properties(SDL2::SDL2
|
||||
PROPERTIES
|
||||
INTERFACE_COMPILE_OPTIONS "SHELL:-F \"${SDL2_FRAMEWORK_PARENT_PATH}\""
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${SDL2_INCLUDE_DIRS}"
|
||||
INTERFACE_LINK_OPTIONS "SHELL:-F \"${SDL2_FRAMEWORK_PARENT_PATH}\";SHELL:-framework SDL2"
|
||||
COMPATIBLE_INTERFACE_BOOL "SDL2_SHARED"
|
||||
INTERFACE_SDL2_SHARED "ON"
|
||||
)
|
||||
endif()
|
||||
set(SDL2_SDL2_FOUND TRUE)
|
||||
|
||||
if(NOT TARGET SDL2::SDL2main)
|
||||
add_library(SDL2::SDL2main INTERFACE IMPORTED)
|
||||
endif()
|
||||
set(SDL2_SDL2main_FOUND TRUE)
|
||||
|
||||
check_required_components(SDL2)
|
@ -0,0 +1,233 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file SDL.h
|
||||
*
|
||||
* Main include header for the SDL library
|
||||
*/
|
||||
|
||||
|
||||
#ifndef SDL_h_
|
||||
#define SDL_h_
|
||||
|
||||
#include <SDL2/SDL_main.h>
|
||||
#include <SDL2/SDL_stdinc.h>
|
||||
#include <SDL2/SDL_assert.h>
|
||||
#include <SDL2/SDL_atomic.h>
|
||||
#include <SDL2/SDL_audio.h>
|
||||
#include <SDL2/SDL_clipboard.h>
|
||||
#include <SDL2/SDL_cpuinfo.h>
|
||||
#include <SDL2/SDL_endian.h>
|
||||
#include <SDL2/SDL_error.h>
|
||||
#include <SDL2/SDL_events.h>
|
||||
#include <SDL2/SDL_filesystem.h>
|
||||
#include <SDL2/SDL_gamecontroller.h>
|
||||
#include <SDL2/SDL_guid.h>
|
||||
#include <SDL2/SDL_haptic.h>
|
||||
#include <SDL2/SDL_hidapi.h>
|
||||
#include <SDL2/SDL_hints.h>
|
||||
#include <SDL2/SDL_joystick.h>
|
||||
#include <SDL2/SDL_loadso.h>
|
||||
#include <SDL2/SDL_log.h>
|
||||
#include <SDL2/SDL_messagebox.h>
|
||||
#include <SDL2/SDL_metal.h>
|
||||
#include <SDL2/SDL_mutex.h>
|
||||
#include <SDL2/SDL_power.h>
|
||||
#include <SDL2/SDL_render.h>
|
||||
#include <SDL2/SDL_rwops.h>
|
||||
#include <SDL2/SDL_sensor.h>
|
||||
#include <SDL2/SDL_shape.h>
|
||||
#include <SDL2/SDL_system.h>
|
||||
#include <SDL2/SDL_thread.h>
|
||||
#include <SDL2/SDL_timer.h>
|
||||
#include <SDL2/SDL_version.h>
|
||||
#include <SDL2/SDL_video.h>
|
||||
#include <SDL2/SDL_locale.h>
|
||||
#include <SDL2/SDL_misc.h>
|
||||
|
||||
#include <SDL2/begin_code.h>
|
||||
/* Set up for C function definitions, even when using C++ */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* As of version 0.5, SDL is loaded dynamically into the application */
|
||||
|
||||
/**
|
||||
* \name SDL_INIT_*
|
||||
*
|
||||
* These are the flags which may be passed to SDL_Init(). You should
|
||||
* specify the subsystems which you will be using in your application.
|
||||
*/
|
||||
/* @{ */
|
||||
#define SDL_INIT_TIMER 0x00000001u
|
||||
#define SDL_INIT_AUDIO 0x00000010u
|
||||
#define SDL_INIT_VIDEO 0x00000020u /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
|
||||
#define SDL_INIT_JOYSTICK 0x00000200u /**< SDL_INIT_JOYSTICK implies SDL_INIT_EVENTS */
|
||||
#define SDL_INIT_HAPTIC 0x00001000u
|
||||
#define SDL_INIT_GAMECONTROLLER 0x00002000u /**< SDL_INIT_GAMECONTROLLER implies SDL_INIT_JOYSTICK */
|
||||
#define SDL_INIT_EVENTS 0x00004000u
|
||||
#define SDL_INIT_SENSOR 0x00008000u
|
||||
#define SDL_INIT_NOPARACHUTE 0x00100000u /**< compatibility; this flag is ignored. */
|
||||
#define SDL_INIT_EVERYTHING ( \
|
||||
SDL_INIT_TIMER | SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_EVENTS | \
|
||||
SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMECONTROLLER | SDL_INIT_SENSOR \
|
||||
)
|
||||
/* @} */
|
||||
|
||||
/**
|
||||
* Initialize the SDL library.
|
||||
*
|
||||
* SDL_Init() simply forwards to calling SDL_InitSubSystem(). Therefore, the
|
||||
* two may be used interchangeably. Though for readability of your code
|
||||
* SDL_InitSubSystem() might be preferred.
|
||||
*
|
||||
* The file I/O (for example: SDL_RWFromFile) and threading (SDL_CreateThread)
|
||||
* subsystems are initialized by default. Message boxes
|
||||
* (SDL_ShowSimpleMessageBox) also attempt to work without initializing the
|
||||
* video subsystem, in hopes of being useful in showing an error dialog when
|
||||
* SDL_Init fails. You must specifically initialize other subsystems if you
|
||||
* use them in your application.
|
||||
*
|
||||
* Logging (such as SDL_Log) works without initialization, too.
|
||||
*
|
||||
* `flags` may be any of the following OR'd together:
|
||||
*
|
||||
* - `SDL_INIT_TIMER`: timer subsystem
|
||||
* - `SDL_INIT_AUDIO`: audio subsystem
|
||||
* - `SDL_INIT_VIDEO`: video subsystem; automatically initializes the events
|
||||
* subsystem
|
||||
* - `SDL_INIT_JOYSTICK`: joystick subsystem; automatically initializes the
|
||||
* events subsystem
|
||||
* - `SDL_INIT_HAPTIC`: haptic (force feedback) subsystem
|
||||
* - `SDL_INIT_GAMECONTROLLER`: controller subsystem; automatically
|
||||
* initializes the joystick subsystem
|
||||
* - `SDL_INIT_EVENTS`: events subsystem
|
||||
* - `SDL_INIT_EVERYTHING`: all of the above subsystems
|
||||
* - `SDL_INIT_NOPARACHUTE`: compatibility; this flag is ignored
|
||||
*
|
||||
* Subsystem initialization is ref-counted, you must call SDL_QuitSubSystem()
|
||||
* for each SDL_InitSubSystem() to correctly shutdown a subsystem manually (or
|
||||
* call SDL_Quit() to force shutdown). If a subsystem is already loaded then
|
||||
* this call will increase the ref-count and return.
|
||||
*
|
||||
* \param flags subsystem initialization flags
|
||||
* \returns 0 on success or a negative error code on failure; call
|
||||
* SDL_GetError() for more information.
|
||||
*
|
||||
* \since This function is available since SDL 2.0.0.
|
||||
*
|
||||
* \sa SDL_InitSubSystem
|
||||
* \sa SDL_Quit
|
||||
* \sa SDL_SetMainReady
|
||||
* \sa SDL_WasInit
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL SDL_Init(Uint32 flags);
|
||||
|
||||
/**
|
||||
* Compatibility function to initialize the SDL library.
|
||||
*
|
||||
* In SDL2, this function and SDL_Init() are interchangeable.
|
||||
*
|
||||
* \param flags any of the flags used by SDL_Init(); see SDL_Init for details.
|
||||
* \returns 0 on success or a negative error code on failure; call
|
||||
* SDL_GetError() for more information.
|
||||
*
|
||||
* \since This function is available since SDL 2.0.0.
|
||||
*
|
||||
* \sa SDL_Init
|
||||
* \sa SDL_Quit
|
||||
* \sa SDL_QuitSubSystem
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL SDL_InitSubSystem(Uint32 flags);
|
||||
|
||||
/**
|
||||
* Shut down specific SDL subsystems.
|
||||
*
|
||||
* If you start a subsystem using a call to that subsystem's init function
|
||||
* (for example SDL_VideoInit()) instead of SDL_Init() or SDL_InitSubSystem(),
|
||||
* SDL_QuitSubSystem() and SDL_WasInit() will not work. You will need to use
|
||||
* that subsystem's quit function (SDL_VideoQuit()) directly instead. But
|
||||
* generally, you should not be using those functions directly anyhow; use
|
||||
* SDL_Init() instead.
|
||||
*
|
||||
* You still need to call SDL_Quit() even if you close all open subsystems
|
||||
* with SDL_QuitSubSystem().
|
||||
*
|
||||
* \param flags any of the flags used by SDL_Init(); see SDL_Init for details.
|
||||
*
|
||||
* \since This function is available since SDL 2.0.0.
|
||||
*
|
||||
* \sa SDL_InitSubSystem
|
||||
* \sa SDL_Quit
|
||||
*/
|
||||
extern DECLSPEC void SDLCALL SDL_QuitSubSystem(Uint32 flags);
|
||||
|
||||
/**
|
||||
* Get a mask of the specified subsystems which are currently initialized.
|
||||
*
|
||||
* \param flags any of the flags used by SDL_Init(); see SDL_Init for details.
|
||||
* \returns a mask of all initialized subsystems if `flags` is 0, otherwise it
|
||||
* returns the initialization status of the specified subsystems.
|
||||
*
|
||||
* The return value does not include SDL_INIT_NOPARACHUTE.
|
||||
*
|
||||
* \since This function is available since SDL 2.0.0.
|
||||
*
|
||||
* \sa SDL_Init
|
||||
* \sa SDL_InitSubSystem
|
||||
*/
|
||||
extern DECLSPEC Uint32 SDLCALL SDL_WasInit(Uint32 flags);
|
||||
|
||||
/**
|
||||
* Clean up all initialized subsystems.
|
||||
*
|
||||
* You should call this function even if you have already shutdown each
|
||||
* initialized subsystem with SDL_QuitSubSystem(). It is safe to call this
|
||||
* function even in the case of errors in initialization.
|
||||
*
|
||||
* If you start a subsystem using a call to that subsystem's init function
|
||||
* (for example SDL_VideoInit()) instead of SDL_Init() or SDL_InitSubSystem(),
|
||||
* then you must use that subsystem's quit function (SDL_VideoQuit()) to shut
|
||||
* it down before calling SDL_Quit(). But generally, you should not be using
|
||||
* those functions directly anyhow; use SDL_Init() instead.
|
||||
*
|
||||
* You can use this function with atexit() to ensure that it is run when your
|
||||
* application is shutdown, but it is not wise to do this from a library or
|
||||
* other dynamically loaded code.
|
||||
*
|
||||
* \since This function is available since SDL 2.0.0.
|
||||
*
|
||||
* \sa SDL_Init
|
||||
* \sa SDL_QuitSubSystem
|
||||
*/
|
||||
extern DECLSPEC void SDLCALL SDL_Quit(void);
|
||||
|
||||
/* Ends C function definitions when using C++ */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#include <SDL2/close_code.h>
|
||||
|
||||
#endif /* SDL_h_ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
@ -0,0 +1,326 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef SDL_assert_h_
|
||||
#define SDL_assert_h_
|
||||
|
||||
#include <SDL2/SDL_stdinc.h>
|
||||
|
||||
#include <SDL2/begin_code.h>
|
||||
/* Set up for C function definitions, even when using C++ */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef SDL_ASSERT_LEVEL
|
||||
#ifdef SDL_DEFAULT_ASSERT_LEVEL
|
||||
#define SDL_ASSERT_LEVEL SDL_DEFAULT_ASSERT_LEVEL
|
||||
#elif defined(_DEBUG) || defined(DEBUG) || \
|
||||
(defined(__GNUC__) && !defined(__OPTIMIZE__))
|
||||
#define SDL_ASSERT_LEVEL 2
|
||||
#else
|
||||
#define SDL_ASSERT_LEVEL 1
|
||||
#endif
|
||||
#endif /* SDL_ASSERT_LEVEL */
|
||||
|
||||
/*
|
||||
These are macros and not first class functions so that the debugger breaks
|
||||
on the assertion line and not in some random guts of SDL, and so each
|
||||
assert can have unique static variables associated with it.
|
||||
*/
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
/* Don't include intrin.h here because it contains C++ code */
|
||||
extern void __cdecl __debugbreak(void);
|
||||
#define SDL_TriggerBreakpoint() __debugbreak()
|
||||
#elif _SDL_HAS_BUILTIN(__builtin_debugtrap)
|
||||
#define SDL_TriggerBreakpoint() __builtin_debugtrap()
|
||||
#elif ( (!defined(__NACL__)) && ((defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__))) )
|
||||
#define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "int $3\n\t" )
|
||||
#elif ( defined(__APPLE__) && (defined(__arm64__) || defined(__aarch64__)) ) /* this might work on other ARM targets, but this is a known quantity... */
|
||||
#define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "brk #22\n\t" )
|
||||
#elif defined(__APPLE__) && defined(__arm__)
|
||||
#define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "bkpt #22\n\t" )
|
||||
#elif defined(__386__) && defined(__WATCOMC__)
|
||||
#define SDL_TriggerBreakpoint() { _asm { int 0x03 } }
|
||||
#elif defined(HAVE_SIGNAL_H) && !defined(__WATCOMC__)
|
||||
#include <signal.h>
|
||||
#define SDL_TriggerBreakpoint() raise(SIGTRAP)
|
||||
#else
|
||||
/* How do we trigger breakpoints on this platform? */
|
||||
#define SDL_TriggerBreakpoint()
|
||||
#endif
|
||||
|
||||
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 supports __func__ as a standard. */
|
||||
# define SDL_FUNCTION __func__
|
||||
#elif ((defined(__GNUC__) && (__GNUC__ >= 2)) || defined(_MSC_VER) || defined (__WATCOMC__))
|
||||
# define SDL_FUNCTION __FUNCTION__
|
||||
#else
|
||||
# define SDL_FUNCTION "???"
|
||||
#endif
|
||||
#define SDL_FILE __FILE__
|
||||
#define SDL_LINE __LINE__
|
||||
|
||||
/*
|
||||
sizeof (x) makes the compiler still parse the expression even without
|
||||
assertions enabled, so the code is always checked at compile time, but
|
||||
doesn't actually generate code for it, so there are no side effects or
|
||||
expensive checks at run time, just the constant size of what x WOULD be,
|
||||
which presumably gets optimized out as unused.
|
||||
This also solves the problem of...
|
||||
|
||||
int somevalue = blah();
|
||||
SDL_assert(somevalue == 1);
|
||||
|
||||
...which would cause compiles to complain that somevalue is unused if we
|
||||
disable assertions.
|
||||
*/
|
||||
|
||||
/* "while (0,0)" fools Microsoft's compiler's /W4 warning level into thinking
|
||||
this condition isn't constant. And looks like an owl's face! */
|
||||
#ifdef _MSC_VER /* stupid /W4 warnings. */
|
||||
#define SDL_NULL_WHILE_LOOP_CONDITION (0,0)
|
||||
#else
|
||||
#define SDL_NULL_WHILE_LOOP_CONDITION (0)
|
||||
#endif
|
||||
|
||||
#define SDL_disabled_assert(condition) \
|
||||
do { (void) sizeof ((condition)); } while (SDL_NULL_WHILE_LOOP_CONDITION)
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SDL_ASSERTION_RETRY, /**< Retry the assert immediately. */
|
||||
SDL_ASSERTION_BREAK, /**< Make the debugger trigger a breakpoint. */
|
||||
SDL_ASSERTION_ABORT, /**< Terminate the program. */
|
||||
SDL_ASSERTION_IGNORE, /**< Ignore the assert. */
|
||||
SDL_ASSERTION_ALWAYS_IGNORE /**< Ignore the assert from now on. */
|
||||
} SDL_AssertState;
|
||||
|
||||
typedef struct SDL_AssertData
|
||||
{
|
||||
int always_ignore;
|
||||
unsigned int trigger_count;
|
||||
const char *condition;
|
||||
const char *filename;
|
||||
int linenum;
|
||||
const char *function;
|
||||
const struct SDL_AssertData *next;
|
||||
} SDL_AssertData;
|
||||
|
||||
#if (SDL_ASSERT_LEVEL > 0)
|
||||
|
||||
/* Never call this directly. Use the SDL_assert* macros. */
|
||||
extern DECLSPEC SDL_AssertState SDLCALL SDL_ReportAssertion(SDL_AssertData *,
|
||||
const char *,
|
||||
const char *, int)
|
||||
#if defined(__clang__)
|
||||
#if __has_feature(attribute_analyzer_noreturn)
|
||||
/* this tells Clang's static analysis that we're a custom assert function,
|
||||
and that the analyzer should assume the condition was always true past this
|
||||
SDL_assert test. */
|
||||
__attribute__((analyzer_noreturn))
|
||||
#endif
|
||||
#endif
|
||||
;
|
||||
|
||||
/* the do {} while(0) avoids dangling else problems:
|
||||
if (x) SDL_assert(y); else blah();
|
||||
... without the do/while, the "else" could attach to this macro's "if".
|
||||
We try to handle just the minimum we need here in a macro...the loop,
|
||||
the static vars, and break points. The heavy lifting is handled in
|
||||
SDL_ReportAssertion(), in SDL_assert.c.
|
||||
*/
|
||||
#define SDL_enabled_assert(condition) \
|
||||
do { \
|
||||
while ( !(condition) ) { \
|
||||
static struct SDL_AssertData sdl_assert_data = { \
|
||||
0, 0, #condition, 0, 0, 0, 0 \
|
||||
}; \
|
||||
const SDL_AssertState sdl_assert_state = SDL_ReportAssertion(&sdl_assert_data, SDL_FUNCTION, SDL_FILE, SDL_LINE); \
|
||||
if (sdl_assert_state == SDL_ASSERTION_RETRY) { \
|
||||
continue; /* go again. */ \
|
||||
} else if (sdl_assert_state == SDL_ASSERTION_BREAK) { \
|
||||
SDL_TriggerBreakpoint(); \
|
||||
} \
|
||||
break; /* not retrying. */ \
|
||||
} \
|
||||
} while (SDL_NULL_WHILE_LOOP_CONDITION)
|
||||
|
||||
#endif /* enabled assertions support code */
|
||||
|
||||
/* Enable various levels of assertions. */
|
||||
#if SDL_ASSERT_LEVEL == 0 /* assertions disabled */
|
||||
# define SDL_assert(condition) SDL_disabled_assert(condition)
|
||||
# define SDL_assert_release(condition) SDL_disabled_assert(condition)
|
||||
# define SDL_assert_paranoid(condition) SDL_disabled_assert(condition)
|
||||
#elif SDL_ASSERT_LEVEL == 1 /* release settings. */
|
||||
# define SDL_assert(condition) SDL_disabled_assert(condition)
|
||||
# define SDL_assert_release(condition) SDL_enabled_assert(condition)
|
||||
# define SDL_assert_paranoid(condition) SDL_disabled_assert(condition)
|
||||
#elif SDL_ASSERT_LEVEL == 2 /* normal settings. */
|
||||
# define SDL_assert(condition) SDL_enabled_assert(condition)
|
||||
# define SDL_assert_release(condition) SDL_enabled_assert(condition)
|
||||
# define SDL_assert_paranoid(condition) SDL_disabled_assert(condition)
|
||||
#elif SDL_ASSERT_LEVEL == 3 /* paranoid settings. */
|
||||
# define SDL_assert(condition) SDL_enabled_assert(condition)
|
||||
# define SDL_assert_release(condition) SDL_enabled_assert(condition)
|
||||
# define SDL_assert_paranoid(condition) SDL_enabled_assert(condition)
|
||||
#else
|
||||
# error Unknown assertion level.
|
||||
#endif
|
||||
|
||||
/* this assertion is never disabled at any level. */
|
||||
#define SDL_assert_always(condition) SDL_enabled_assert(condition)
|
||||
|
||||
|
||||
/**
|
||||
* A callback that fires when an SDL assertion fails.
|
||||
*
|
||||
* \param data a pointer to the SDL_AssertData structure corresponding to the
|
||||
* current assertion
|
||||
* \param userdata what was passed as `userdata` to SDL_SetAssertionHandler()
|
||||
* \returns an SDL_AssertState value indicating how to handle the failure.
|
||||
*/
|
||||
typedef SDL_AssertState (SDLCALL *SDL_AssertionHandler)(
|
||||
const SDL_AssertData* data, void* userdata);
|
||||
|
||||
/**
|
||||
* Set an application-defined assertion handler.
|
||||
*
|
||||
* This function allows an application to show its own assertion UI and/or
|
||||
* force the response to an assertion failure. If the application doesn't
|
||||
* provide this, SDL will try to do the right thing, popping up a
|
||||
* system-specific GUI dialog, and probably minimizing any fullscreen windows.
|
||||
*
|
||||
* This callback may fire from any thread, but it runs wrapped in a mutex, so
|
||||
* it will only fire from one thread at a time.
|
||||
*
|
||||
* This callback is NOT reset to SDL's internal handler upon SDL_Quit()!
|
||||
*
|
||||
* \param handler the SDL_AssertionHandler function to call when an assertion
|
||||
* fails or NULL for the default handler
|
||||
* \param userdata a pointer that is passed to `handler`
|
||||
*
|
||||
* \since This function is available since SDL 2.0.0.
|
||||
*
|
||||
* \sa SDL_GetAssertionHandler
|
||||
*/
|
||||
extern DECLSPEC void SDLCALL SDL_SetAssertionHandler(
|
||||
SDL_AssertionHandler handler,
|
||||
void *userdata);
|
||||
|
||||
/**
|
||||
* Get the default assertion handler.
|
||||
*
|
||||
* This returns the function pointer that is called by default when an
|
||||
* assertion is triggered. This is an internal function provided by SDL, that
|
||||
* is used for assertions when SDL_SetAssertionHandler() hasn't been used to
|
||||
* provide a different function.
|
||||
*
|
||||
* \returns the default SDL_AssertionHandler that is called when an assert
|
||||
* triggers.
|
||||
*
|
||||
* \since This function is available since SDL 2.0.2.
|
||||
*
|
||||
* \sa SDL_GetAssertionHandler
|
||||
*/
|
||||
extern DECLSPEC SDL_AssertionHandler SDLCALL SDL_GetDefaultAssertionHandler(void);
|
||||
|
||||
/**
|
||||
* Get the current assertion handler.
|
||||
*
|
||||
* This returns the function pointer that is called when an assertion is
|
||||
* triggered. This is either the value last passed to
|
||||
* SDL_SetAssertionHandler(), or if no application-specified function is set,
|
||||
* is equivalent to calling SDL_GetDefaultAssertionHandler().
|
||||
*
|
||||
* The parameter `puserdata` is a pointer to a void*, which will store the
|
||||
* "userdata" pointer that was passed to SDL_SetAssertionHandler(). This value
|
||||
* will always be NULL for the default handler. If you don't care about this
|
||||
* data, it is safe to pass a NULL pointer to this function to ignore it.
|
||||
*
|
||||
* \param puserdata pointer which is filled with the "userdata" pointer that
|
||||
* was passed to SDL_SetAssertionHandler()
|
||||
* \returns the SDL_AssertionHandler that is called when an assert triggers.
|
||||
*
|
||||
* \since This function is available since SDL 2.0.2.
|
||||
*
|
||||
* \sa SDL_SetAssertionHandler
|
||||
*/
|
||||
extern DECLSPEC SDL_AssertionHandler SDLCALL SDL_GetAssertionHandler(void **puserdata);
|
||||
|
||||
/**
|
||||
* Get a list of all assertion failures.
|
||||
*
|
||||
* This function gets all assertions triggered since the last call to
|
||||
* SDL_ResetAssertionReport(), or the start of the program.
|
||||
*
|
||||
* The proper way to examine this data looks something like this:
|
||||
*
|
||||
* ```c
|
||||
* const SDL_AssertData *item = SDL_GetAssertionReport();
|
||||
* while (item) {
|
||||
* printf("'%s', %s (%s:%d), triggered %u times, always ignore: %s.\\n",
|
||||
* item->condition, item->function, item->filename,
|
||||
* item->linenum, item->trigger_count,
|
||||
* item->always_ignore ? "yes" : "no");
|
||||
* item = item->next;
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* \returns a list of all failed assertions or NULL if the list is empty. This
|
||||
* memory should not be modified or freed by the application.
|
||||
*
|
||||
* \since This function is available since SDL 2.0.0.
|
||||
*
|
||||
* \sa SDL_ResetAssertionReport
|
||||
*/
|
||||
extern DECLSPEC const SDL_AssertData * SDLCALL SDL_GetAssertionReport(void);
|
||||
|
||||
/**
|
||||
* Clear the list of all assertion failures.
|
||||
*
|
||||
* This function will clear the list of all assertions triggered up to that
|
||||
* point. Immediately following this call, SDL_GetAssertionReport will return
|
||||
* no items. In addition, any previously-triggered assertions will be reset to
|
||||
* a trigger_count of zero, and their always_ignore state will be false.
|
||||
*
|
||||
* \since This function is available since SDL 2.0.0.
|
||||
*
|
||||
* \sa SDL_GetAssertionReport
|
||||
*/
|
||||
extern DECLSPEC void SDLCALL SDL_ResetAssertionReport(void);
|
||||
|
||||
|
||||
/* these had wrong naming conventions until 2.0.4. Please update your app! */
|
||||
#define SDL_assert_state SDL_AssertState
|
||||
#define SDL_assert_data SDL_AssertData
|
||||
|
||||
|
||||
/* Ends C function definitions when using C++ */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#include <SDL2/close_code.h>
|
||||
|
||||
#endif /* SDL_assert_h_ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
@ -0,0 +1,415 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file SDL_atomic.h
|
||||
*
|
||||
* Atomic operations.
|
||||
*
|
||||
* IMPORTANT:
|
||||
* If you are not an expert in concurrent lockless programming, you should
|
||||
* only be using the atomic lock and reference counting functions in this
|
||||
* file. In all other cases you should be protecting your data structures
|
||||
* with full mutexes.
|
||||
*
|
||||
* The list of "safe" functions to use are:
|
||||
* SDL_AtomicLock()
|
||||
* SDL_AtomicUnlock()
|
||||
* SDL_AtomicIncRef()
|
||||
* SDL_AtomicDecRef()
|
||||
*
|
||||
* Seriously, here be dragons!
|
||||
* ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
*
|
||||
* You can find out a little more about lockless programming and the
|
||||
* subtle issues that can arise here:
|
||||
* http://msdn.microsoft.com/en-us/library/ee418650%28v=vs.85%29.aspx
|
||||
*
|
||||
* There's also lots of good information here:
|
||||
* http://www.1024cores.net/home/lock-free-algorithms
|
||||
* http://preshing.com/
|
||||
*
|
||||
* These operations may or may not actually be implemented using
|
||||
* processor specific atomic operations. When possible they are
|
||||
* implemented as true processor specific atomic operations. When that
|
||||
* is not possible the are implemented using locks that *do* use the
|
||||
* available atomic operations.
|
||||
*
|
||||
* All of the atomic operations that modify memory are full memory barriers.
|
||||
*/
|
||||
|
||||
#ifndef SDL_atomic_h_
|
||||
#define SDL_atomic_h_
|
||||
|
||||
#include <SDL2/SDL_stdinc.h>
|
||||
#include <SDL2/SDL_platform.h>
|
||||
|
||||
#include <SDL2/begin_code.h>
|
||||
|
||||
/* Set up for C function definitions, even when using C++ */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \name SDL AtomicLock
|
||||
*
|
||||
* The atomic locks are efficient spinlocks using CPU instructions,
|
||||
* but are vulnerable to starvation and can spin forever if a thread
|
||||
* holding a lock has been terminated. For this reason you should
|
||||
* minimize the code executed inside an atomic lock and never do
|
||||
* expensive things like API or system calls while holding them.
|
||||
*
|
||||
* The atomic locks are not safe to lock recursively.
|
||||
*
|
||||
* Porting Note:
|
||||
* The spin lock functions and type are required and can not be
|
||||
* emulated because they are used in the atomic emulation code.
|
||||
*/
|
||||
/* @{ */
|
||||
|
||||
typedef int SDL_SpinLock;
|
||||
|
||||
/**
|
||||
* Try to lock a spin lock by setting it to a non-zero value.
|
||||
*
|
||||
* ***Please note that spinlocks are dangerous if you don't know what you're
|
||||
* doing. Please be careful using any sort of spinlock!***
|
||||
*
|
||||
* \param lock a pointer to a lock variable
|
||||
* \returns SDL_TRUE if the lock succeeded, SDL_FALSE if the lock is already
|
||||
* held.
|
||||
*
|
||||
* \since This function is available since SDL 2.0.0.
|
||||
*
|
||||
* \sa SDL_AtomicLock
|
||||
* \sa SDL_AtomicUnlock
|
||||
*/
|
||||
extern DECLSPEC SDL_bool SDLCALL SDL_AtomicTryLock(SDL_SpinLock *lock);
|
||||
|
||||
/**
|
||||
* Lock a spin lock by setting it to a non-zero value.
|
||||
*
|
||||
* ***Please note that spinlocks are dangerous if you don't know what you're
|
||||
* doing. Please be careful using any sort of spinlock!***
|
||||
*
|
||||
* \param lock a pointer to a lock variable
|
||||
*
|
||||
* \since This function is available since SDL 2.0.0.
|
||||
*
|
||||
* \sa SDL_AtomicTryLock
|
||||
* \sa SDL_AtomicUnlock
|
||||
*/
|
||||
extern DECLSPEC void SDLCALL SDL_AtomicLock(SDL_SpinLock *lock);
|
||||
|
||||
/**
|
||||
* Unlock a spin lock by setting it to 0.
|
||||
*
|
||||
* Always returns immediately.
|
||||
*
|
||||
* ***Please note that spinlocks are dangerous if you don't know what you're
|
||||
* doing. Please be careful using any sort of spinlock!***
|
||||
*
|
||||
* \param lock a pointer to a lock variable
|
||||
*
|
||||
* \since This function is available since SDL 2.0.0.
|
||||
*
|
||||
* \sa SDL_AtomicLock
|
||||
* \sa SDL_AtomicTryLock
|
||||
*/
|
||||
extern DECLSPEC void SDLCALL SDL_AtomicUnlock(SDL_SpinLock *lock);
|
||||
|
||||
/* @} *//* SDL AtomicLock */
|
||||
|
||||
|
||||
/**
|
||||
* The compiler barrier prevents the compiler from reordering
|
||||
* reads and writes to globally visible variables across the call.
|
||||
*/
|
||||
#if defined(_MSC_VER) && (_MSC_VER > 1200) && !defined(__clang__)
|
||||
void _ReadWriteBarrier(void);
|
||||
#pragma intrinsic(_ReadWriteBarrier)
|
||||
#define SDL_CompilerBarrier() _ReadWriteBarrier()
|
||||
#elif (defined(__GNUC__) && !defined(__EMSCRIPTEN__)) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x5120))
|
||||
/* This is correct for all CPUs when using GCC or Solaris Studio 12.1+. */
|
||||
#define SDL_CompilerBarrier() __asm__ __volatile__ ("" : : : "memory")
|
||||
#elif defined(__WATCOMC__)
|
||||
extern __inline void SDL_CompilerBarrier(void);
|
||||
#pragma aux SDL_CompilerBarrier = "" parm [] modify exact [];
|
||||
#else
|
||||
#define SDL_CompilerBarrier() \
|
||||
{ SDL_SpinLock _tmp = 0; SDL_AtomicLock(&_tmp); SDL_AtomicUnlock(&_tmp); }
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Memory barriers are designed to prevent reads and writes from being
|
||||
* reordered by the compiler and being seen out of order on multi-core CPUs.
|
||||
*
|
||||
* A typical pattern would be for thread A to write some data and a flag, and
|
||||
* for thread B to read the flag and get the data. In this case you would
|
||||
* insert a release barrier between writing the data and the flag,
|
||||
* guaranteeing that the data write completes no later than the flag is
|
||||
* written, and you would insert an acquire barrier between reading the flag
|
||||
* and reading the data, to ensure that all the reads associated with the flag
|
||||
* have completed.
|
||||
*
|
||||
* In this pattern you should always see a release barrier paired with an
|
||||
* acquire barrier and you should gate the data reads/writes with a single
|
||||
* flag variable.
|
||||
*
|
||||
* For more information on these semantics, take a look at the blog post:
|
||||
* http://preshing.com/20120913/acquire-and-release-semantics
|
||||
*
|
||||
* \since This function is available since SDL 2.0.6.
|
||||
*/
|
||||
extern DECLSPEC void SDLCALL SDL_MemoryBarrierReleaseFunction(void);
|
||||
extern DECLSPEC void SDLCALL SDL_MemoryBarrierAcquireFunction(void);
|
||||
|
||||
#if defined(__GNUC__) && (defined(__powerpc__) || defined(__ppc__))
|
||||
#define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("lwsync" : : : "memory")
|
||||
#define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("lwsync" : : : "memory")
|
||||
#elif defined(__GNUC__) && defined(__aarch64__)
|
||||
#define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("dmb ish" : : : "memory")
|
||||
#define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("dmb ish" : : : "memory")
|
||||
#elif defined(__GNUC__) && defined(__arm__)
|
||||
#if 0 /* defined(__LINUX__) || defined(__ANDROID__) */
|
||||
/* Information from:
|
||||
https://chromium.googlesource.com/chromium/chromium/+/trunk/base/atomicops_internals_arm_gcc.h#19
|
||||
|
||||
The Linux kernel provides a helper function which provides the right code for a memory barrier,
|
||||
hard-coded at address 0xffff0fa0
|
||||
*/
|
||||
typedef void (*SDL_KernelMemoryBarrierFunc)();
|
||||
#define SDL_MemoryBarrierRelease() ((SDL_KernelMemoryBarrierFunc)0xffff0fa0)()
|
||||
#define SDL_MemoryBarrierAcquire() ((SDL_KernelMemoryBarrierFunc)0xffff0fa0)()
|
||||
#elif 0 /* defined(__QNXNTO__) */
|
||||
#include <sys/cpuinline.h>
|
||||
|
||||
#define SDL_MemoryBarrierRelease() __cpu_membarrier()
|
||||
#define SDL_MemoryBarrierAcquire() __cpu_membarrier()
|
||||
#else
|
||||
#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) || defined(__ARM_ARCH_8A__)
|
||||
#define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("dmb ish" : : : "memory")
|
||||
#define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("dmb ish" : : : "memory")
|
||||
#elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_5TE__)
|
||||
#ifdef __thumb__
|
||||
/* The mcr instruction isn't available in thumb mode, use real functions */
|
||||
#define SDL_MEMORY_BARRIER_USES_FUNCTION
|
||||
#define SDL_MemoryBarrierRelease() SDL_MemoryBarrierReleaseFunction()
|
||||
#define SDL_MemoryBarrierAcquire() SDL_MemoryBarrierAcquireFunction()
|
||||
#else
|
||||
#define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" : : "r"(0) : "memory")
|
||||
#define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" : : "r"(0) : "memory")
|
||||
#endif /* __thumb__ */
|
||||
#else
|
||||
#define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("" : : : "memory")
|
||||
#define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("" : : : "memory")
|
||||
#endif /* __LINUX__ || __ANDROID__ */
|
||||
#endif /* __GNUC__ && __arm__ */
|
||||
#else
|
||||
#if (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x5120))
|
||||
/* This is correct for all CPUs on Solaris when using Solaris Studio 12.1+. */
|
||||
#include <mbarrier.h>
|
||||
#define SDL_MemoryBarrierRelease() __machine_rel_barrier()
|
||||
#define SDL_MemoryBarrierAcquire() __machine_acq_barrier()
|
||||
#else
|
||||
/* This is correct for the x86 and x64 CPUs, and we'll expand this over time. */
|
||||
#define SDL_MemoryBarrierRelease() SDL_CompilerBarrier()
|
||||
#define SDL_MemoryBarrierAcquire() SDL_CompilerBarrier()
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* "REP NOP" is PAUSE, coded for tools that don't know it by that name. */
|
||||
#if (defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__))
|
||||
#define SDL_CPUPauseInstruction() __asm__ __volatile__("pause\n") /* Some assemblers can't do REP NOP, so go with PAUSE. */
|
||||
#elif (defined(__arm__) && __ARM_ARCH >= 7) || defined(__aarch64__)
|
||||
#define SDL_CPUPauseInstruction() __asm__ __volatile__("yield" ::: "memory")
|
||||
#elif (defined(__powerpc__) || defined(__powerpc64__))
|
||||
#define SDL_CPUPauseInstruction() __asm__ __volatile__("or 27,27,27");
|
||||
#elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
|
||||
#define SDL_CPUPauseInstruction() _mm_pause() /* this is actually "rep nop" and not a SIMD instruction. No inline asm in MSVC x86-64! */
|
||||
#elif defined(_MSC_VER) && (defined(_M_ARM) || defined(_M_ARM64))
|
||||
#define SDL_CPUPauseInstruction() __yield()
|
||||
#elif defined(__WATCOMC__) && defined(__386__)
|
||||
/* watcom assembler rejects PAUSE if CPU < i686, and it refuses REP NOP as an invalid combination. Hardcode the bytes. */
|
||||
extern __inline void SDL_CPUPauseInstruction(void);
|
||||
#pragma aux SDL_CPUPauseInstruction = "db 0f3h,90h"
|
||||
#else
|
||||
#define SDL_CPUPauseInstruction()
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* \brief A type representing an atomic integer value. It is a struct
|
||||
* so people don't accidentally use numeric operations on it.
|
||||
*/
|
||||
typedef struct { int value; } SDL_atomic_t;
|
||||
|
||||
/**
|
||||
* Set an atomic variable to a new value if it is currently an old value.
|
||||
*
|
||||
* ***Note: If you don't know what this function is for, you shouldn't use
|
||||
* it!***
|
||||
*
|
||||
* \param a a pointer to an SDL_atomic_t variable to be modified
|
||||
* \param oldval the old value
|
||||
* \param newval the new value
|
||||
* \returns SDL_TRUE if the atomic variable was set, SDL_FALSE otherwise.
|
||||
*
|
||||
* \since This function is available since SDL 2.0.0.
|
||||
*
|
||||
* \sa SDL_AtomicCASPtr
|
||||
* \sa SDL_AtomicGet
|
||||
* \sa SDL_AtomicSet
|
||||
*/
|
||||
extern DECLSPEC SDL_bool SDLCALL SDL_AtomicCAS(SDL_atomic_t *a, int oldval, int newval);
|
||||
|
||||
/**
|
||||
* Set an atomic variable to a value.
|
||||
*
|
||||
* This function also acts as a full memory barrier.
|
||||
*
|
||||
* ***Note: If you don't know what this function is for, you shouldn't use
|
||||
* it!***
|
||||
*
|
||||
* \param a a pointer to an SDL_atomic_t variable to be modified
|
||||
* \param v the desired value
|
||||
* \returns the previous value of the atomic variable.
|
||||
*
|
||||
* \since This function is available since SDL 2.0.2.
|
||||
*
|
||||
* \sa SDL_AtomicGet
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL SDL_AtomicSet(SDL_atomic_t *a, int v);
|
||||
|
||||
/**
|
||||
* Get the value of an atomic variable.
|
||||
*
|
||||
* ***Note: If you don't know what this function is for, you shouldn't use
|
||||
* it!***
|
||||
*
|
||||
* \param a a pointer to an SDL_atomic_t variable
|
||||
* \returns the current value of an atomic variable.
|
||||
*
|
||||
* \since This function is available since SDL 2.0.2.
|
||||
*
|
||||
* \sa SDL_AtomicSet
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL SDL_AtomicGet(SDL_atomic_t *a);
|
||||
|
||||
/**
|
||||
* Add to an atomic variable.
|
||||
*
|
||||
* This function also acts as a full memory barrier.
|
||||
*
|
||||
* ***Note: If you don't know what this function is for, you shouldn't use
|
||||
* it!***
|
||||
*
|
||||
* \param a a pointer to an SDL_atomic_t variable to be modified
|
||||
* \param v the desired value to add
|
||||
* \returns the previous value of the atomic variable.
|
||||
*
|
||||
* \since This function is available since SDL 2.0.2.
|
||||
*
|
||||
* \sa SDL_AtomicDecRef
|
||||
* \sa SDL_AtomicIncRef
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL SDL_AtomicAdd(SDL_atomic_t *a, int v);
|
||||
|
||||
/**
|
||||
* \brief Increment an atomic variable used as a reference count.
|
||||
*/
|
||||
#ifndef SDL_AtomicIncRef
|
||||
#define SDL_AtomicIncRef(a) SDL_AtomicAdd(a, 1)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Decrement an atomic variable used as a reference count.
|
||||
*
|
||||
* \return SDL_TRUE if the variable reached zero after decrementing,
|
||||
* SDL_FALSE otherwise
|
||||
*/
|
||||
#ifndef SDL_AtomicDecRef
|
||||
#define SDL_AtomicDecRef(a) (SDL_AtomicAdd(a, -1) == 1)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Set a pointer to a new value if it is currently an old value.
|
||||
*
|
||||
* ***Note: If you don't know what this function is for, you shouldn't use
|
||||
* it!***
|
||||
*
|
||||
* \param a a pointer to a pointer
|
||||
* \param oldval the old pointer value
|
||||
* \param newval the new pointer value
|
||||
* \returns SDL_TRUE if the pointer was set, SDL_FALSE otherwise.
|
||||
*
|
||||
* \since This function is available since SDL 2.0.0.
|
||||
*
|
||||
* \sa SDL_AtomicCAS
|
||||
* \sa SDL_AtomicGetPtr
|
||||
* \sa SDL_AtomicSetPtr
|
||||
*/
|
||||
extern DECLSPEC SDL_bool SDLCALL SDL_AtomicCASPtr(void **a, void *oldval, void *newval);
|
||||
|
||||
/**
|
||||
* Set a pointer to a value atomically.
|
||||
*
|
||||
* ***Note: If you don't know what this function is for, you shouldn't use
|
||||
* it!***
|
||||
*
|
||||
* \param a a pointer to a pointer
|
||||
* \param v the desired pointer value
|
||||
* \returns the previous value of the pointer.
|
||||
*
|
||||
* \since This function is available since SDL 2.0.2.
|
||||
*
|
||||
* \sa SDL_AtomicCASPtr
|
||||
* \sa SDL_AtomicGetPtr
|
||||
*/
|
||||
extern DECLSPEC void* SDLCALL SDL_AtomicSetPtr(void **a, void* v);
|
||||
|
||||
/**
|
||||
* Get the value of a pointer atomically.
|
||||
*
|
||||
* ***Note: If you don't know what this function is for, you shouldn't use
|
||||
* it!***
|
||||
*
|
||||
* \param a a pointer to a pointer
|
||||
* \returns the current value of a pointer.
|
||||
*
|
||||
* \since This function is available since SDL 2.0.2.
|
||||
*
|
||||
* \sa SDL_AtomicCASPtr
|
||||
* \sa SDL_AtomicSetPtr
|
||||
*/
|
||||
extern DECLSPEC void* SDLCALL SDL_AtomicGetPtr(void **a);
|
||||
|
||||
/* Ends C function definitions when using C++ */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#include <SDL2/close_code.h>
|
||||
|
||||
#endif /* SDL_atomic_h_ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,126 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file SDL_bits.h
|
||||
*
|
||||
* Functions for fiddling with bits and bitmasks.
|
||||
*/
|
||||
|
||||
#ifndef SDL_bits_h_
|
||||
#define SDL_bits_h_
|
||||
|
||||
#include <SDL2/SDL_stdinc.h>
|
||||
|
||||
#include <SDL2/begin_code.h>
|
||||
/* Set up for C function definitions, even when using C++ */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \file SDL_bits.h
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get the index of the most significant bit. Result is undefined when called
|
||||
* with 0. This operation can also be stated as "count leading zeroes" and
|
||||
* "log base 2".
|
||||
*
|
||||
* \return the index of the most significant bit, or -1 if the value is 0.
|
||||
*/
|
||||
#if defined(__WATCOMC__) && defined(__386__)
|
||||
extern __inline int _SDL_bsr_watcom(Uint32);
|
||||
#pragma aux _SDL_bsr_watcom = \
|
||||
"bsr eax, eax" \
|
||||
parm [eax] nomemory \
|
||||
value [eax] \
|
||||
modify exact [eax] nomemory;
|
||||
#endif
|
||||
|
||||
SDL_FORCE_INLINE int
|
||||
SDL_MostSignificantBitIndex32(Uint32 x)
|
||||
{
|
||||
#if defined(__GNUC__) && (__GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
|
||||
/* Count Leading Zeroes builtin in GCC.
|
||||
* http://gcc.gnu.org/onlinedocs/gcc-4.3.4/gcc/Other-Builtins.html
|
||||
*/
|
||||
if (x == 0) {
|
||||
return -1;
|
||||
}
|
||||
return 31 - __builtin_clz(x);
|
||||
#elif defined(__WATCOMC__) && defined(__386__)
|
||||
if (x == 0) {
|
||||
return -1;
|
||||
}
|
||||
return _SDL_bsr_watcom(x);
|
||||
#elif defined(_MSC_VER)
|
||||
unsigned long index;
|
||||
if (_BitScanReverse(&index, x)) {
|
||||
return index;
|
||||
}
|
||||
return -1;
|
||||
#else
|
||||
/* Based off of Bit Twiddling Hacks by Sean Eron Anderson
|
||||
* <seander@cs.stanford.edu>, released in the public domain.
|
||||
* http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog
|
||||
*/
|
||||
const Uint32 b[] = {0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000};
|
||||
const int S[] = {1, 2, 4, 8, 16};
|
||||
|
||||
int msbIndex = 0;
|
||||
int i;
|
||||
|
||||
if (x == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 4; i >= 0; i--)
|
||||
{
|
||||
if (x & b[i])
|
||||
{
|
||||
x >>= S[i];
|
||||
msbIndex |= S[i];
|
||||
}
|
||||
}
|
||||
|
||||
return msbIndex;
|
||||
#endif
|
||||
}
|
||||
|
||||
SDL_FORCE_INLINE SDL_bool
|
||||
SDL_HasExactlyOneBitSet32(Uint32 x)
|
||||
{
|
||||
if (x && !(x & (x - 1))) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
/* Ends C function definitions when using C++ */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#include <SDL2/close_code.h>
|
||||
|
||||
#endif /* SDL_bits_h_ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
@ -0,0 +1,198 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file SDL_blendmode.h
|
||||
*
|
||||
* Header file declaring the SDL_BlendMode enumeration
|
||||
*/
|
||||
|
||||
#ifndef SDL_blendmode_h_
|
||||
#define SDL_blendmode_h_
|
||||
|
||||
#include <SDL2/begin_code.h>
|
||||
/* Set up for C function definitions, even when using C++ */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief The blend mode used in SDL_RenderCopy() and drawing operations.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
SDL_BLENDMODE_NONE = 0x00000000, /**< no blending
|
||||
dstRGBA = srcRGBA */
|
||||
SDL_BLENDMODE_BLEND = 0x00000001, /**< alpha blending
|
||||
dstRGB = (srcRGB * srcA) + (dstRGB * (1-srcA))
|
||||
dstA = srcA + (dstA * (1-srcA)) */
|
||||
SDL_BLENDMODE_ADD = 0x00000002, /**< additive blending
|
||||
dstRGB = (srcRGB * srcA) + dstRGB
|
||||
dstA = dstA */
|
||||
SDL_BLENDMODE_MOD = 0x00000004, /**< color modulate
|
||||
dstRGB = srcRGB * dstRGB
|
||||
dstA = dstA */
|
||||
SDL_BLENDMODE_MUL = 0x00000008, /**< color multiply
|
||||
dstRGB = (srcRGB * dstRGB) + (dstRGB * (1-srcA))
|
||||
dstA = (srcA * dstA) + (dstA * (1-srcA)) */
|
||||
SDL_BLENDMODE_INVALID = 0x7FFFFFFF
|
||||
|
||||
/* Additional custom blend modes can be returned by SDL_ComposeCustomBlendMode() */
|
||||
|
||||
} SDL_BlendMode;
|
||||
|
||||
/**
|
||||
* \brief The blend operation used when combining source and destination pixel components
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
SDL_BLENDOPERATION_ADD = 0x1, /**< dst + src: supported by all renderers */
|
||||
SDL_BLENDOPERATION_SUBTRACT = 0x2, /**< dst - src : supported by D3D9, D3D11, OpenGL, OpenGLES */
|
||||
SDL_BLENDOPERATION_REV_SUBTRACT = 0x3, /**< src - dst : supported by D3D9, D3D11, OpenGL, OpenGLES */
|
||||
SDL_BLENDOPERATION_MINIMUM = 0x4, /**< min(dst, src) : supported by D3D9, D3D11 */
|
||||
SDL_BLENDOPERATION_MAXIMUM = 0x5 /**< max(dst, src) : supported by D3D9, D3D11 */
|
||||
} SDL_BlendOperation;
|
||||
|
||||
/**
|
||||
* \brief The normalized factor used to multiply pixel components
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
SDL_BLENDFACTOR_ZERO = 0x1, /**< 0, 0, 0, 0 */
|
||||
SDL_BLENDFACTOR_ONE = 0x2, /**< 1, 1, 1, 1 */
|
||||
SDL_BLENDFACTOR_SRC_COLOR = 0x3, /**< srcR, srcG, srcB, srcA */
|
||||
SDL_BLENDFACTOR_ONE_MINUS_SRC_COLOR = 0x4, /**< 1-srcR, 1-srcG, 1-srcB, 1-srcA */
|
||||
SDL_BLENDFACTOR_SRC_ALPHA = 0x5, /**< srcA, srcA, srcA, srcA */
|
||||
SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA = 0x6, /**< 1-srcA, 1-srcA, 1-srcA, 1-srcA */
|
||||
SDL_BLENDFACTOR_DST_COLOR = 0x7, /**< dstR, dstG, dstB, dstA */
|
||||
SDL_BLENDFACTOR_ONE_MINUS_DST_COLOR = 0x8, /**< 1-dstR, 1-dstG, 1-dstB, 1-dstA */
|
||||
SDL_BLENDFACTOR_DST_ALPHA = 0x9, /**< dstA, dstA, dstA, dstA */
|
||||
SDL_BLENDFACTOR_ONE_MINUS_DST_ALPHA = 0xA /**< 1-dstA, 1-dstA, 1-dstA, 1-dstA */
|
||||
} SDL_BlendFactor;
|
||||
|
||||
/**
|
||||
* Compose a custom blend mode for renderers.
|
||||
*
|
||||
* The functions SDL_SetRenderDrawBlendMode and SDL_SetTextureBlendMode accept
|
||||
* the SDL_BlendMode returned by this function if the renderer supports it.
|
||||
*
|
||||
* A blend mode controls how the pixels from a drawing operation (source) get
|
||||
* combined with the pixels from the render target (destination). First, the
|
||||
* components of the source and destination pixels get multiplied with their
|
||||
* blend factors. Then, the blend operation takes the two products and
|
||||
* calculates the result that will get stored in the render target.
|
||||
*
|
||||
* Expressed in pseudocode, it would look like this:
|
||||
*
|
||||
* ```c
|
||||
* dstRGB = colorOperation(srcRGB * srcColorFactor, dstRGB * dstColorFactor);
|
||||
* dstA = alphaOperation(srcA * srcAlphaFactor, dstA * dstAlphaFactor);
|
||||
* ```
|
||||
*
|
||||
* Where the functions `colorOperation(src, dst)` and `alphaOperation(src,
|
||||
* dst)` can return one of the following:
|
||||
*
|
||||
* - `src + dst`
|
||||
* - `src - dst`
|
||||
* - `dst - src`
|
||||
* - `min(src, dst)`
|
||||
* - `max(src, dst)`
|
||||
*
|
||||
* The red, green, and blue components are always multiplied with the first,
|
||||
* second, and third components of the SDL_BlendFactor, respectively. The
|
||||
* fourth component is not used.
|
||||
*
|
||||
* The alpha component is always multiplied with the fourth component of the
|
||||
* SDL_BlendFactor. The other components are not used in the alpha
|
||||
* calculation.
|
||||
*
|
||||
* Support for these blend modes varies for each renderer. To check if a
|
||||
* specific SDL_BlendMode is supported, create a renderer and pass it to
|
||||
* either SDL_SetRenderDrawBlendMode or SDL_SetTextureBlendMode. They will
|
||||
* return with an error if the blend mode is not supported.
|
||||
*
|
||||
* This list describes the support of custom blend modes for each renderer in
|
||||
* SDL 2.0.6. All renderers support the four blend modes listed in the
|
||||
* SDL_BlendMode enumeration.
|
||||
*
|
||||
* - **direct3d**: Supports all operations with all factors. However, some
|
||||
* factors produce unexpected results with `SDL_BLENDOPERATION_MINIMUM` and
|
||||
* `SDL_BLENDOPERATION_MAXIMUM`.
|
||||
* - **direct3d11**: Same as Direct3D 9.
|
||||
* - **opengl**: Supports the `SDL_BLENDOPERATION_ADD` operation with all
|
||||
* factors. OpenGL versions 1.1, 1.2, and 1.3 do not work correctly with SDL
|
||||
* 2.0.6.
|
||||
* - **opengles**: Supports the `SDL_BLENDOPERATION_ADD` operation with all
|
||||
* factors. Color and alpha factors need to be the same. OpenGL ES 1
|
||||
* implementation specific: May also support `SDL_BLENDOPERATION_SUBTRACT`
|
||||
* and `SDL_BLENDOPERATION_REV_SUBTRACT`. May support color and alpha
|
||||
* operations being different from each other. May support color and alpha
|
||||
* factors being different from each other.
|
||||
* - **opengles2**: Supports the `SDL_BLENDOPERATION_ADD`,
|
||||
* `SDL_BLENDOPERATION_SUBTRACT`, `SDL_BLENDOPERATION_REV_SUBTRACT`
|
||||
* operations with all factors.
|
||||
* - **psp**: No custom blend mode support.
|
||||
* - **software**: No custom blend mode support.
|
||||
*
|
||||
* Some renderers do not provide an alpha component for the default render
|
||||
* target. The `SDL_BLENDFACTOR_DST_ALPHA` and
|
||||
* `SDL_BLENDFACTOR_ONE_MINUS_DST_ALPHA` factors do not have an effect in this
|
||||
* case.
|
||||
*
|
||||
* \param srcColorFactor the SDL_BlendFactor applied to the red, green, and
|
||||
* blue components of the source pixels
|
||||
* \param dstColorFactor the SDL_BlendFactor applied to the red, green, and
|
||||
* blue components of the destination pixels
|
||||
* \param colorOperation the SDL_BlendOperation used to combine the red,
|
||||
* green, and blue components of the source and
|
||||
* destination pixels
|
||||
* \param srcAlphaFactor the SDL_BlendFactor applied to the alpha component of
|
||||
* the source pixels
|
||||
* \param dstAlphaFactor the SDL_BlendFactor applied to the alpha component of
|
||||
* the destination pixels
|
||||
* \param alphaOperation the SDL_BlendOperation used to combine the alpha
|
||||
* component of the source and destination pixels
|
||||
* \returns an SDL_BlendMode that represents the chosen factors and
|
||||
* operations.
|
||||
*
|
||||
* \since This function is available since SDL 2.0.6.
|
||||
*
|
||||
* \sa SDL_SetRenderDrawBlendMode
|
||||
* \sa SDL_GetRenderDrawBlendMode
|
||||
* \sa SDL_SetTextureBlendMode
|
||||
* \sa SDL_GetTextureBlendMode
|
||||
*/
|
||||
extern DECLSPEC SDL_BlendMode SDLCALL SDL_ComposeCustomBlendMode(SDL_BlendFactor srcColorFactor,
|
||||
SDL_BlendFactor dstColorFactor,
|
||||
SDL_BlendOperation colorOperation,
|
||||
SDL_BlendFactor srcAlphaFactor,
|
||||
SDL_BlendFactor dstAlphaFactor,
|
||||
SDL_BlendOperation alphaOperation);
|
||||
|
||||
/* Ends C function definitions when using C++ */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#include <SDL2/close_code.h>
|
||||
|
||||
#endif /* SDL_blendmode_h_ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
@ -0,0 +1,141 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file SDL_clipboard.h
|
||||
*
|
||||
* Include file for SDL clipboard handling
|
||||
*/
|
||||
|
||||
#ifndef SDL_clipboard_h_
|
||||
#define SDL_clipboard_h_
|
||||
|
||||
#include <SDL2/SDL_stdinc.h>
|
||||
|
||||
#include <SDL2/begin_code.h>
|
||||
/* Set up for C function definitions, even when using C++ */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Function prototypes */
|
||||
|
||||
/**
|
||||
* Put UTF-8 text into the clipboard.
|
||||
*
|
||||
* \param text the text to store in the clipboard
|
||||
* \returns 0 on success or a negative error code on failure; call
|
||||
* SDL_GetError() for more information.
|
||||
*
|
||||
* \since This function is available since SDL 2.0.0.
|
||||
*
|
||||
* \sa SDL_GetClipboardText
|
||||
* \sa SDL_HasClipboardText
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL SDL_SetClipboardText(const char *text);
|
||||
|
||||
/**
|
||||
* Get UTF-8 text from the clipboard, which must be freed with SDL_free().
|
||||
*
|
||||
* This functions returns empty string if there was not enough memory left for
|
||||
* a copy of the clipboard's content.
|
||||
*
|
||||
* \returns the clipboard text on success or an empty string on failure; call
|
||||
* SDL_GetError() for more information. Caller must call SDL_free()
|
||||
* on the returned pointer when done with it (even if there was an
|
||||
* error).
|
||||
*
|
||||
* \since This function is available since SDL 2.0.0.
|
||||
*
|
||||
* \sa SDL_HasClipboardText
|
||||
* \sa SDL_SetClipboardText
|
||||
*/
|
||||
extern DECLSPEC char * SDLCALL SDL_GetClipboardText(void);
|
||||
|
||||
/**
|
||||
* Query whether the clipboard exists and contains a non-empty text string.
|
||||
*
|
||||
* \returns SDL_TRUE if the clipboard has text, or SDL_FALSE if it does not.
|
||||
*
|
||||
* \since This function is available since SDL 2.0.0.
|
||||
*
|
||||
* \sa SDL_GetClipboardText
|
||||
* \sa SDL_SetClipboardText
|
||||
*/
|
||||
extern DECLSPEC SDL_bool SDLCALL SDL_HasClipboardText(void);
|
||||
|
||||
/**
|
||||
* Put UTF-8 text into the primary selection.
|
||||
*
|
||||
* \param text the text to store in the primary selection
|
||||
* \returns 0 on success or a negative error code on failure; call
|
||||
* SDL_GetError() for more information.
|
||||
*
|
||||
* \since This function is available since SDL 2.26.0.
|
||||
*
|
||||
* \sa SDL_GetPrimarySelectionText
|
||||
* \sa SDL_HasPrimarySelectionText
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL SDL_SetPrimarySelectionText(const char *text);
|
||||
|
||||
/**
|
||||
* Get UTF-8 text from the primary selection, which must be freed with
|
||||
* SDL_free().
|
||||
*
|
||||
* This functions returns empty string if there was not enough memory left for
|
||||
* a copy of the primary selection's content.
|
||||
*
|
||||
* \returns the primary selection text on success or an empty string on
|
||||
* failure; call SDL_GetError() for more information. Caller must
|
||||
* call SDL_free() on the returned pointer when done with it (even if
|
||||
* there was an error).
|
||||
*
|
||||
* \since This function is available since SDL 2.26.0.
|
||||
*
|
||||
* \sa SDL_HasPrimarySelectionText
|
||||
* \sa SDL_SetPrimarySelectionText
|
||||
*/
|
||||
extern DECLSPEC char * SDLCALL SDL_GetPrimarySelectionText(void);
|
||||
|
||||
/**
|
||||
* Query whether the primary selection exists and contains a non-empty text
|
||||
* string.
|
||||
*
|
||||
* \returns SDL_TRUE if the primary selection has text, or SDL_FALSE if it
|
||||
* does not.
|
||||
*
|
||||
* \since This function is available since SDL 2.26.0.
|
||||
*
|
||||
* \sa SDL_GetPrimarySelectionText
|
||||
* \sa SDL_SetPrimarySelectionText
|
||||
*/
|
||||
extern DECLSPEC SDL_bool SDLCALL SDL_HasPrimarySelectionText(void);
|
||||
|
||||
|
||||
/* Ends C function definitions when using C++ */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#include <SDL2/close_code.h>
|
||||
|
||||
#endif /* SDL_clipboard_h_ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
@ -0,0 +1,61 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef SDL_config_h_
|
||||
#define SDL_config_h_
|
||||
|
||||
#include <SDL2/SDL_platform.h>
|
||||
|
||||
/**
|
||||
* \file SDL_config.h
|
||||
*/
|
||||
|
||||
/* Add any platform that doesn't build using the configure system. */
|
||||
#if defined(__WIN32__)
|
||||
#include <SDL2/SDL_config_windows.h>
|
||||
#elif defined(__WINRT__)
|
||||
#include <SDL2/SDL_config_winrt.h>
|
||||
#elif defined(__WINGDK__)
|
||||
#include <SDL2/SDL_config_wingdk.h>
|
||||
#elif defined(__XBOXONE__) || defined(__XBOXSERIES__)
|
||||
#include <SDL2/SDL_config_xbox.h>
|
||||
#elif defined(__MACOSX__)
|
||||
#include <SDL2/SDL_config_macosx.h>
|
||||
#elif defined(__IPHONEOS__)
|
||||
#include <SDL2/SDL_config_iphoneos.h>
|
||||
#elif defined(__ANDROID__)
|
||||
#include <SDL2/SDL_config_android.h>
|
||||
#elif defined(__OS2__)
|
||||
#include <SDL2/SDL_config_os2.h>
|
||||
#elif defined(__EMSCRIPTEN__)
|
||||
#include <SDL2/SDL_config_emscripten.h>
|
||||
#elif defined(__NGAGE__)
|
||||
#include <SDL2/SDL_config_ngage.h>
|
||||
#else
|
||||
/* This is a minimal configuration just to get SDL running on new platforms. */
|
||||
#include <SDL2/SDL_config_minimal.h>
|
||||
#endif /* platform config */
|
||||
|
||||
#ifdef USING_GENERATED_CONFIG_H
|
||||
#error Wrong SDL_config.h, check your include path?
|
||||
#endif
|
||||
|
||||
#endif /* SDL_config_h_ */
|
@ -0,0 +1,217 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef SDL_config_iphoneos_h_
|
||||
#define SDL_config_iphoneos_h_
|
||||
#define SDL_config_h_
|
||||
|
||||
#include <SDL2/SDL_platform.h>
|
||||
|
||||
#ifdef __LP64__
|
||||
#define SIZEOF_VOIDP 8
|
||||
#else
|
||||
#define SIZEOF_VOIDP 4
|
||||
#endif
|
||||
|
||||
#define HAVE_GCC_ATOMICS 1
|
||||
|
||||
#define STDC_HEADERS 1
|
||||
#define HAVE_ALLOCA_H 1
|
||||
#define HAVE_CTYPE_H 1
|
||||
#define HAVE_INTTYPES_H 1
|
||||
#define HAVE_LIMITS_H 1
|
||||
#define HAVE_MATH_H 1
|
||||
#define HAVE_SIGNAL_H 1
|
||||
#define HAVE_STDINT_H 1
|
||||
#define HAVE_STDIO_H 1
|
||||
#define HAVE_STRING_H 1
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
/* The libunwind functions are only available on x86 */
|
||||
/* #undef HAVE_LIBUNWIND_H */
|
||||
|
||||
/* C library functions */
|
||||
#define HAVE_DLOPEN 1
|
||||
#define HAVE_MALLOC 1
|
||||
#define HAVE_CALLOC 1
|
||||
#define HAVE_REALLOC 1
|
||||
#define HAVE_FREE 1
|
||||
#define HAVE_ALLOCA 1
|
||||
#define HAVE_GETENV 1
|
||||
#define HAVE_SETENV 1
|
||||
#define HAVE_PUTENV 1
|
||||
#define HAVE_SETENV 1
|
||||
#define HAVE_UNSETENV 1
|
||||
#define HAVE_QSORT 1
|
||||
#define HAVE_BSEARCH 1
|
||||
#define HAVE_ABS 1
|
||||
#define HAVE_BCOPY 1
|
||||
#define HAVE_MEMSET 1
|
||||
#define HAVE_MEMCPY 1
|
||||
#define HAVE_MEMMOVE 1
|
||||
#define HAVE_MEMCMP 1
|
||||
#define HAVE_STRLEN 1
|
||||
#define HAVE_STRLCPY 1
|
||||
#define HAVE_STRLCAT 1
|
||||
#define HAVE_STRCHR 1
|
||||
#define HAVE_STRRCHR 1
|
||||
#define HAVE_STRSTR 1
|
||||
#define HAVE_STRTOK_R 1
|
||||
#define HAVE_STRTOL 1
|
||||
#define HAVE_STRTOUL 1
|
||||
#define HAVE_STRTOLL 1
|
||||
#define HAVE_STRTOULL 1
|
||||
#define HAVE_STRTOD 1
|
||||
#define HAVE_ATOI 1
|
||||
#define HAVE_ATOF 1
|
||||
#define HAVE_STRCMP 1
|
||||
#define HAVE_STRNCMP 1
|
||||
#define HAVE_STRCASECMP 1
|
||||
#define HAVE_STRNCASECMP 1
|
||||
#define HAVE_STRCASESTR 1
|
||||
#define HAVE_VSSCANF 1
|
||||
#define HAVE_VSNPRINTF 1
|
||||
#define HAVE_M_PI 1
|
||||
#define HAVE_ACOS 1
|
||||
#define HAVE_ACOSF 1
|
||||
#define HAVE_ASIN 1
|
||||
#define HAVE_ASINF 1
|
||||
#define HAVE_ATAN 1
|
||||
#define HAVE_ATANF 1
|
||||
#define HAVE_ATAN2 1
|
||||
#define HAVE_ATAN2F 1
|
||||
#define HAVE_CEIL 1
|
||||
#define HAVE_CEILF 1
|
||||
#define HAVE_COPYSIGN 1
|
||||
#define HAVE_COPYSIGNF 1
|
||||
#define HAVE_COS 1
|
||||
#define HAVE_COSF 1
|
||||
#define HAVE_EXP 1
|
||||
#define HAVE_EXPF 1
|
||||
#define HAVE_FABS 1
|
||||
#define HAVE_FABSF 1
|
||||
#define HAVE_FLOOR 1
|
||||
#define HAVE_FLOORF 1
|
||||
#define HAVE_FMOD 1
|
||||
#define HAVE_FMODF 1
|
||||
#define HAVE_LOG 1
|
||||
#define HAVE_LOGF 1
|
||||
#define HAVE_LOG10 1
|
||||
#define HAVE_LOG10F 1
|
||||
#define HAVE_LROUND 1
|
||||
#define HAVE_LROUNDF 1
|
||||
#define HAVE_POW 1
|
||||
#define HAVE_POWF 1
|
||||
#define HAVE_ROUND 1
|
||||
#define HAVE_ROUNDF 1
|
||||
#define HAVE_SCALBN 1
|
||||
#define HAVE_SCALBNF 1
|
||||
#define HAVE_SIN 1
|
||||
#define HAVE_SINF 1
|
||||
#define HAVE_SQRT 1
|
||||
#define HAVE_SQRTF 1
|
||||
#define HAVE_TAN 1
|
||||
#define HAVE_TANF 1
|
||||
#define HAVE_TRUNC 1
|
||||
#define HAVE_TRUNCF 1
|
||||
#define HAVE_SIGACTION 1
|
||||
#define HAVE_SETJMP 1
|
||||
#define HAVE_NANOSLEEP 1
|
||||
#define HAVE_SYSCONF 1
|
||||
#define HAVE_SYSCTLBYNAME 1
|
||||
#define HAVE_O_CLOEXEC 1
|
||||
|
||||
/* enable iPhone version of Core Audio driver */
|
||||
#define SDL_AUDIO_DRIVER_COREAUDIO 1
|
||||
/* Enable the dummy audio driver (src/audio/dummy/\*.c) */
|
||||
#define SDL_AUDIO_DRIVER_DUMMY 1
|
||||
|
||||
/* Enable the stub haptic driver (src/haptic/dummy/\*.c) */
|
||||
#define SDL_HAPTIC_DUMMY 1
|
||||
|
||||
/* Enable joystick support */
|
||||
/* Only enable HIDAPI support if you want to support Steam Controllers on iOS and tvOS */
|
||||
/*#define SDL_JOYSTICK_HIDAPI 1*/
|
||||
#define SDL_JOYSTICK_MFI 1
|
||||
#define SDL_JOYSTICK_VIRTUAL 1
|
||||
|
||||
#ifdef __TVOS__
|
||||
#define SDL_SENSOR_DUMMY 1
|
||||
#else
|
||||
/* Enable the CoreMotion sensor driver */
|
||||
#define SDL_SENSOR_COREMOTION 1
|
||||
#endif
|
||||
|
||||
/* Enable Unix style SO loading */
|
||||
#define SDL_LOADSO_DLOPEN 1
|
||||
|
||||
/* Enable various threading systems */
|
||||
#define SDL_THREAD_PTHREAD 1
|
||||
#define SDL_THREAD_PTHREAD_RECURSIVE_MUTEX 1
|
||||
|
||||
/* Enable various timer systems */
|
||||
#define SDL_TIMER_UNIX 1
|
||||
|
||||
/* Supported video drivers */
|
||||
#define SDL_VIDEO_DRIVER_UIKIT 1
|
||||
#define SDL_VIDEO_DRIVER_DUMMY 1
|
||||
|
||||
/* Enable OpenGL ES */
|
||||
#if !TARGET_OS_MACCATALYST
|
||||
#define SDL_VIDEO_OPENGL_ES2 1
|
||||
#define SDL_VIDEO_OPENGL_ES 1
|
||||
#define SDL_VIDEO_RENDER_OGL_ES 1
|
||||
#define SDL_VIDEO_RENDER_OGL_ES2 1
|
||||
#endif
|
||||
|
||||
/* Metal supported on 64-bit devices running iOS 8.0 and tvOS 9.0 and newer
|
||||
Also supported in simulator from iOS 13.0 and tvOS 13.0
|
||||
*/
|
||||
#if (TARGET_OS_SIMULATOR && ((__IPHONE_OS_VERSION_MIN_REQUIRED >= 130000) || (__TV_OS_VERSION_MIN_REQUIRED >= 130000))) || (!TARGET_CPU_ARM && ((__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 90000)))
|
||||
#define SDL_PLATFORM_SUPPORTS_METAL 1
|
||||
#else
|
||||
#define SDL_PLATFORM_SUPPORTS_METAL 0
|
||||
#endif
|
||||
|
||||
#if SDL_PLATFORM_SUPPORTS_METAL
|
||||
#define SDL_VIDEO_RENDER_METAL 1
|
||||
#endif
|
||||
|
||||
#if SDL_PLATFORM_SUPPORTS_METAL
|
||||
#define SDL_VIDEO_VULKAN 1
|
||||
#endif
|
||||
|
||||
#if SDL_PLATFORM_SUPPORTS_METAL
|
||||
#define SDL_VIDEO_METAL 1
|
||||
#endif
|
||||
|
||||
/* Enable system power support */
|
||||
#define SDL_POWER_UIKIT 1
|
||||
|
||||
/* enable iPhone keyboard support */
|
||||
#define SDL_IPHONE_KEYBOARD 1
|
||||
|
||||
/* enable iOS extended launch screen */
|
||||
#define SDL_IPHONE_LAUNCHSCREEN 1
|
||||
|
||||
/* enable filesystem support */
|
||||
#define SDL_FILESYSTEM_COCOA 1
|
||||
|
||||
#endif /* SDL_config_iphoneos_h_ */
|
@ -0,0 +1,20 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
@ -0,0 +1,594 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file SDL_cpuinfo.h
|
||||
*
|
||||
* CPU feature detection for SDL.
|
||||
*/
|
||||
|
||||
#ifndef SDL_cpuinfo_h_
|
||||
#define SDL_cpuinfo_h_
|
||||
|
||||
#include <SDL2/SDL_stdinc.h>
|
||||
|
||||
/* Need to do this here because intrin.h has C++ code in it */
|
||||
/* Visual Studio 2005 has a bug where intrin.h conflicts with winnt.h */
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1500) && (defined(_M_IX86) || defined(_M_X64))
|
||||
#ifdef __clang__
|
||||
/* As of Clang 11, '_m_prefetchw' is conflicting with the winnt.h's version,
|
||||
so we define the needed '_m_prefetch' here as a pseudo-header, until the issue is fixed. */
|
||||
|
||||
#ifndef __PRFCHWINTRIN_H
|
||||
#define __PRFCHWINTRIN_H
|
||||
|
||||
static __inline__ void __attribute__((__always_inline__, __nodebug__))
|
||||
_m_prefetch(void *__P)
|
||||
{
|
||||
__builtin_prefetch (__P, 0, 3 /* _MM_HINT_T0 */);
|
||||
}
|
||||
|
||||
#endif /* __PRFCHWINTRIN_H */
|
||||
#endif /* __clang__ */
|
||||
#include <intrin.h>
|
||||
#ifndef _WIN64
|
||||
#ifndef __MMX__
|
||||
#define __MMX__
|
||||
#endif
|
||||
#ifndef __3dNOW__
|
||||
#define __3dNOW__
|
||||
#endif
|
||||
#endif
|
||||
#ifndef __SSE__
|
||||
#define __SSE__
|
||||
#endif
|
||||
#ifndef __SSE2__
|
||||
#define __SSE2__
|
||||
#endif
|
||||
#ifndef __SSE3__
|
||||
#define __SSE3__
|
||||
#endif
|
||||
#elif defined(__MINGW64_VERSION_MAJOR)
|
||||
#include <intrin.h>
|
||||
#if !defined(SDL_DISABLE_ARM_NEON_H) && defined(__ARM_NEON)
|
||||
# include <arm_neon.h>
|
||||
#endif
|
||||
#else
|
||||
/* altivec.h redefining bool causes a number of problems, see bugs 3993 and 4392, so you need to explicitly define SDL_ENABLE_ALTIVEC_H to have it included. */
|
||||
#if defined(HAVE_ALTIVEC_H) && defined(__ALTIVEC__) && !defined(__APPLE_ALTIVEC__) && defined(SDL_ENABLE_ALTIVEC_H)
|
||||
#include <altivec.h>
|
||||
#endif
|
||||
#if !defined(SDL_DISABLE_ARM_NEON_H)
|
||||
# if defined(__ARM_NEON)
|
||||
# include <arm_neon.h>
|
||||
# elif defined(__WINDOWS__) || defined(__WINRT__) || defined(__GDK__)
|
||||
/* Visual Studio doesn't define __ARM_ARCH, but _M_ARM (if set, always 7), and _M_ARM64 (if set, always 1). */
|
||||
# if defined(_M_ARM)
|
||||
# include <armintr.h>
|
||||
# include <arm_neon.h>
|
||||
# define __ARM_NEON 1 /* Set __ARM_NEON so that it can be used elsewhere, at compile time */
|
||||
# endif
|
||||
# if defined (_M_ARM64)
|
||||
# include <arm64intr.h>
|
||||
# include <arm64_neon.h>
|
||||
# define __ARM_NEON 1 /* Set __ARM_NEON so that it can be used elsewhere, at compile time */
|
||||
# define __ARM_ARCH 8
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
#endif /* compiler version */
|
||||
|
||||
#if defined(__3dNOW__) && !defined(SDL_DISABLE_MM3DNOW_H)
|
||||
#include <mm3dnow.h>
|
||||
#endif
|
||||
#if defined(__loongarch_sx) && !defined(SDL_DISABLE_LSX_H)
|
||||
#include <lsxintrin.h>
|
||||
#define __LSX__
|
||||
#endif
|
||||
#if defined(__loongarch_asx) && !defined(SDL_DISABLE_LASX_H)
|
||||
#include <lasxintrin.h>
|
||||
#define __LASX__
|
||||
#endif
|
||||
#if defined(HAVE_IMMINTRIN_H) && !defined(SDL_DISABLE_IMMINTRIN_H)
|
||||
#include <immintrin.h>
|
||||
#else
|
||||
#if defined(__MMX__) && !defined(SDL_DISABLE_MMINTRIN_H)
|
||||
#include <mmintrin.h>
|
||||
#endif
|
||||
#if defined(__SSE__) && !defined(SDL_DISABLE_XMMINTRIN_H)
|
||||
#include <xmmintrin.h>
|
||||
#endif
|
||||
#if defined(__SSE2__) && !defined(SDL_DISABLE_EMMINTRIN_H)
|
||||
#include <emmintrin.h>
|
||||
#endif
|
||||
#if defined(__SSE3__) && !defined(SDL_DISABLE_PMMINTRIN_H)
|
||||
#include <pmmintrin.h>
|
||||
#endif
|
||||
#endif /* HAVE_IMMINTRIN_H */
|
||||
|
||||
#include <SDL2/begin_code.h>
|
||||
/* Set up for C function definitions, even when using C++ */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* This is a guess for the cacheline size used for padding.
|
||||
* Most x86 processors have a 64 byte cache line.
|
||||
* The 64-bit PowerPC processors have a 128 byte cache line.
|
||||
* We'll use the larger value to be generally safe.
|
||||
*/
|
||||
#define SDL_CACHELINE_SIZE 128
|
||||
|
||||
/**
|
||||
* Get the number of CPU cores available.
|
||||
*
|
||||
* \returns the total number of logical CPU cores. On CPUs that include
|
||||
* technologies such as hyperthreading, the number of logical cores
|
||||
* may be more than the number of physical cores.
|
||||
*
|
||||
* \since This function is available since SDL 2.0.0.
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL SDL_GetCPUCount(void);
|
||||
|
||||
/**
|
||||
* Determine the L1 cache line size of the CPU.
|
||||
*
|
||||
* This is useful for determining multi-threaded structure padding or SIMD
|
||||
* prefetch sizes.
|
||||
*
|
||||
* \returns the L1 cache line size of the CPU, in bytes.
|
||||
*
|
||||
* \since This function is available since SDL 2.0.0.
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL SDL_GetCPUCacheLineSize(void);
|
||||
|
||||
/**
|
||||
* Determine whether the CPU has the RDTSC instruction.
|
||||
*
|
||||
* This always returns false on CPUs that aren't using Intel instruction sets.
|
||||
*
|
||||
* \returns SDL_TRUE if the CPU has the RDTSC instruction or SDL_FALSE if not.
|
||||
*
|
||||
* \since This function is available since SDL 2.0.0.
|
||||
*
|
||||
* \sa SDL_Has3DNow
|
||||
* \sa SDL_HasAltiVec
|
||||
* \sa SDL_HasAVX
|
||||
* \sa SDL_HasAVX2
|
||||
* \sa SDL_HasMMX
|
||||
* \sa SDL_HasSSE
|
||||
* \sa SDL_HasSSE2
|
||||
* \sa SDL_HasSSE3
|
||||
* \sa SDL_HasSSE41
|
||||
* \sa SDL_HasSSE42
|
||||
*/
|
||||
extern DECLSPEC SDL_bool SDLCALL SDL_HasRDTSC(void);
|
||||
|
||||
/**
|
||||
* Determine whether the CPU has AltiVec features.
|
||||
*
|
||||
* This always returns false on CPUs that aren't using PowerPC instruction
|
||||
* sets.
|
||||
*
|
||||
* \returns SDL_TRUE if the CPU has AltiVec features or SDL_FALSE if not.
|
||||
*
|
||||
* \since This function is available since SDL 2.0.0.
|
||||
*
|
||||
* \sa SDL_Has3DNow
|
||||
* \sa SDL_HasAVX
|
||||
* \sa SDL_HasAVX2
|
||||
* \sa SDL_HasMMX
|
||||
* \sa SDL_HasRDTSC
|
||||
* \sa SDL_HasSSE
|
||||
* \sa SDL_HasSSE2
|
||||
* \sa SDL_HasSSE3
|
||||
* \sa SDL_HasSSE41
|
||||
* \sa SDL_HasSSE42
|
||||
*/
|
||||
extern DECLSPEC SDL_bool SDLCALL SDL_HasAltiVec(void);
|
||||
|
||||
/**
|
||||
* Determine whether the CPU has MMX features.
|
||||
*
|
||||
* This always returns false on CPUs that aren't using Intel instruction sets.
|
||||
*
|
||||
* \returns SDL_TRUE if the CPU has MMX features or SDL_FALSE if not.
|
||||
*
|
||||
* \since This function is available since SDL 2.0.0.
|
||||
*
|
||||
* \sa SDL_Has3DNow
|
||||
* \sa SDL_HasAltiVec
|
||||
* \sa SDL_HasAVX
|
||||
* \sa SDL_HasAVX2
|
||||
* \sa SDL_HasRDTSC
|
||||
* \sa SDL_HasSSE
|
||||
* \sa SDL_HasSSE2
|
||||
* \sa SDL_HasSSE3
|
||||
* \sa SDL_HasSSE41
|
||||
* \sa SDL_HasSSE42
|
||||
*/
|
||||
extern DECLSPEC SDL_bool SDLCALL SDL_HasMMX(void);
|
||||
|
||||
/**
|
||||
* Determine whether the CPU has 3DNow! features.
|
||||
*
|
||||
* This always returns false on CPUs that aren't using AMD instruction sets.
|
||||
*
|
||||
* \returns SDL_TRUE if the CPU has 3DNow! features or SDL_FALSE if not.
|
||||
*
|
||||
* \since This function is available since SDL 2.0.0.
|
||||
*
|
||||
* \sa SDL_HasAltiVec
|
||||
* \sa SDL_HasAVX
|
||||
* \sa SDL_HasAVX2
|
||||
* \sa SDL_HasMMX
|
||||
* \sa SDL_HasRDTSC
|
||||
* \sa SDL_HasSSE
|
||||
* \sa SDL_HasSSE2
|
||||
* \sa SDL_HasSSE3
|
||||
* \sa SDL_HasSSE41
|
||||
* \sa SDL_HasSSE42
|
||||
*/
|
||||
extern DECLSPEC SDL_bool SDLCALL SDL_Has3DNow(void);
|
||||
|
||||
/**
|
||||
* Determine whether the CPU has SSE features.
|
||||
*
|
||||
* This always returns false on CPUs that aren't using Intel instruction sets.
|
||||
*
|
||||
* \returns SDL_TRUE if the CPU has SSE features or SDL_FALSE if not.
|
||||
*
|
||||
* \since This function is available since SDL 2.0.0.
|
||||
*
|
||||
* \sa SDL_Has3DNow
|
||||
* \sa SDL_HasAltiVec
|
||||
* \sa SDL_HasAVX
|
||||
* \sa SDL_HasAVX2
|
||||
* \sa SDL_HasMMX
|
||||
* \sa SDL_HasRDTSC
|
||||
* \sa SDL_HasSSE2
|
||||
* \sa SDL_HasSSE3
|
||||
* \sa SDL_HasSSE41
|
||||
* \sa SDL_HasSSE42
|
||||
*/
|
||||
extern DECLSPEC SDL_bool SDLCALL SDL_HasSSE(void);
|
||||
|
||||
/**
|
||||
* Determine whether the CPU has SSE2 features.
|
||||
*
|
||||
* This always returns false on CPUs that aren't using Intel instruction sets.
|
||||
*
|
||||
* \returns SDL_TRUE if the CPU has SSE2 features or SDL_FALSE if not.
|
||||
*
|
||||
* \since This function is available since SDL 2.0.0.
|
||||
*
|
||||
* \sa SDL_Has3DNow
|
||||
* \sa SDL_HasAltiVec
|
||||
* \sa SDL_HasAVX
|
||||
* \sa SDL_HasAVX2
|
||||
* \sa SDL_HasMMX
|
||||
* \sa SDL_HasRDTSC
|
||||
* \sa SDL_HasSSE
|
||||
* \sa SDL_HasSSE3
|
||||
* \sa SDL_HasSSE41
|
||||
* \sa SDL_HasSSE42
|
||||
*/
|
||||
extern DECLSPEC SDL_bool SDLCALL SDL_HasSSE2(void);
|
||||
|
||||
/**
|
||||
* Determine whether the CPU has SSE3 features.
|
||||
*
|
||||
* This always returns false on CPUs that aren't using Intel instruction sets.
|
||||
*
|
||||
* \returns SDL_TRUE if the CPU has SSE3 features or SDL_FALSE if not.
|
||||
*
|
||||
* \since This function is available since SDL 2.0.0.
|
||||
*
|
||||
* \sa SDL_Has3DNow
|
||||
* \sa SDL_HasAltiVec
|
||||
* \sa SDL_HasAVX
|
||||
* \sa SDL_HasAVX2
|
||||
* \sa SDL_HasMMX
|
||||
* \sa SDL_HasRDTSC
|
||||
* \sa SDL_HasSSE
|
||||
* \sa SDL_HasSSE2
|
||||
* \sa SDL_HasSSE41
|
||||
* \sa SDL_HasSSE42
|
||||
*/
|
||||
extern DECLSPEC SDL_bool SDLCALL SDL_HasSSE3(void);
|
||||
|
||||
/**
|
||||
* Determine whether the CPU has SSE4.1 features.
|
||||
*
|
||||
* This always returns false on CPUs that aren't using Intel instruction sets.
|
||||
*
|
||||
* \returns SDL_TRUE if the CPU has SSE4.1 features or SDL_FALSE if not.
|
||||
*
|
||||
* \since This function is available since SDL 2.0.0.
|
||||
*
|
||||
* \sa SDL_Has3DNow
|
||||
* \sa SDL_HasAltiVec
|
||||
* \sa SDL_HasAVX
|
||||
* \sa SDL_HasAVX2
|
||||
* \sa SDL_HasMMX
|
||||
* \sa SDL_HasRDTSC
|
||||
* \sa SDL_HasSSE
|
||||
* \sa SDL_HasSSE2
|
||||
* \sa SDL_HasSSE3
|
||||
* \sa SDL_HasSSE42
|
||||
*/
|
||||
extern DECLSPEC SDL_bool SDLCALL SDL_HasSSE41(void);
|
||||
|
||||
/**
|
||||
* Determine whether the CPU has SSE4.2 features.
|
||||
*
|
||||
* This always returns false on CPUs that aren't using Intel instruction sets.
|
||||
*
|
||||
* \returns SDL_TRUE if the CPU has SSE4.2 features or SDL_FALSE if not.
|
||||
*
|
||||
* \since This function is available since SDL 2.0.0.
|
||||
*
|
||||
* \sa SDL_Has3DNow
|
||||
* \sa SDL_HasAltiVec
|
||||
* \sa SDL_HasAVX
|
||||
* \sa SDL_HasAVX2
|
||||
* \sa SDL_HasMMX
|
||||
* \sa SDL_HasRDTSC
|
||||
* \sa SDL_HasSSE
|
||||
* \sa SDL_HasSSE2
|
||||
* \sa SDL_HasSSE3
|
||||
* \sa SDL_HasSSE41
|
||||
*/
|
||||
extern DECLSPEC SDL_bool SDLCALL SDL_HasSSE42(void);
|
||||
|
||||
/**
|
||||
* Determine whether the CPU has AVX features.
|
||||
*
|
||||
* This always returns false on CPUs that aren't using Intel instruction sets.
|
||||
*
|
||||
* \returns SDL_TRUE if the CPU has AVX features or SDL_FALSE if not.
|
||||
*
|
||||
* \since This function is available since SDL 2.0.2.
|
||||
*
|
||||
* \sa SDL_Has3DNow
|
||||
* \sa SDL_HasAltiVec
|
||||
* \sa SDL_HasAVX2
|
||||
* \sa SDL_HasMMX
|
||||
* \sa SDL_HasRDTSC
|
||||
* \sa SDL_HasSSE
|
||||
* \sa SDL_HasSSE2
|
||||
* \sa SDL_HasSSE3
|
||||
* \sa SDL_HasSSE41
|
||||
* \sa SDL_HasSSE42
|
||||
*/
|
||||
extern DECLSPEC SDL_bool SDLCALL SDL_HasAVX(void);
|
||||
|
||||
/**
|
||||
* Determine whether the CPU has AVX2 features.
|
||||
*
|
||||
* This always returns false on CPUs that aren't using Intel instruction sets.
|
||||
*
|
||||
* \returns SDL_TRUE if the CPU has AVX2 features or SDL_FALSE if not.
|
||||
*
|
||||
* \since This function is available since SDL 2.0.4.
|
||||
*
|
||||
* \sa SDL_Has3DNow
|
||||
* \sa SDL_HasAltiVec
|
||||
* \sa SDL_HasAVX
|
||||
* \sa SDL_HasMMX
|
||||
* \sa SDL_HasRDTSC
|
||||
* \sa SDL_HasSSE
|
||||
* \sa SDL_HasSSE2
|
||||
* \sa SDL_HasSSE3
|
||||
* \sa SDL_HasSSE41
|
||||
* \sa SDL_HasSSE42
|
||||
*/
|
||||
extern DECLSPEC SDL_bool SDLCALL SDL_HasAVX2(void);
|
||||
|
||||
/**
|
||||
* Determine whether the CPU has AVX-512F (foundation) features.
|
||||
*
|
||||
* This always returns false on CPUs that aren't using Intel instruction sets.
|
||||
*
|
||||
* \returns SDL_TRUE if the CPU has AVX-512F features or SDL_FALSE if not.
|
||||
*
|
||||
* \since This function is available since SDL 2.0.9.
|
||||
*
|
||||
* \sa SDL_HasAVX
|
||||
*/
|
||||
extern DECLSPEC SDL_bool SDLCALL SDL_HasAVX512F(void);
|
||||
|
||||
/**
|
||||
* Determine whether the CPU has ARM SIMD (ARMv6) features.
|
||||
*
|
||||
* This is different from ARM NEON, which is a different instruction set.
|
||||
*
|
||||
* This always returns false on CPUs that aren't using ARM instruction sets.
|
||||
*
|
||||
* \returns SDL_TRUE if the CPU has ARM SIMD features or SDL_FALSE if not.
|
||||
*
|
||||
* \since This function is available since SDL 2.0.12.
|
||||
*
|
||||
* \sa SDL_HasNEON
|
||||
*/
|
||||
extern DECLSPEC SDL_bool SDLCALL SDL_HasARMSIMD(void);
|
||||
|
||||
/**
|
||||
* Determine whether the CPU has NEON (ARM SIMD) features.
|
||||
*
|
||||
* This always returns false on CPUs that aren't using ARM instruction sets.
|
||||
*
|
||||
* \returns SDL_TRUE if the CPU has ARM NEON features or SDL_FALSE if not.
|
||||
*
|
||||
* \since This function is available since SDL 2.0.6.
|
||||
*/
|
||||
extern DECLSPEC SDL_bool SDLCALL SDL_HasNEON(void);
|
||||
|
||||
/**
|
||||
* Determine whether the CPU has LSX (LOONGARCH SIMD) features.
|
||||
*
|
||||
* This always returns false on CPUs that aren't using LOONGARCH instruction
|
||||
* sets.
|
||||
*
|
||||
* \returns SDL_TRUE if the CPU has LOONGARCH LSX features or SDL_FALSE if
|
||||
* not.
|
||||
*
|
||||
* \since This function is available since SDL 2.24.0.
|
||||
*/
|
||||
extern DECLSPEC SDL_bool SDLCALL SDL_HasLSX(void);
|
||||
|
||||
/**
|
||||
* Determine whether the CPU has LASX (LOONGARCH SIMD) features.
|
||||
*
|
||||
* This always returns false on CPUs that aren't using LOONGARCH instruction
|
||||
* sets.
|
||||
*
|
||||
* \returns SDL_TRUE if the CPU has LOONGARCH LASX features or SDL_FALSE if
|
||||
* not.
|
||||
*
|
||||
* \since This function is available since SDL 2.24.0.
|
||||
*/
|
||||
extern DECLSPEC SDL_bool SDLCALL SDL_HasLASX(void);
|
||||
|
||||
/**
|
||||
* Get the amount of RAM configured in the system.
|
||||
*
|
||||
* \returns the amount of RAM configured in the system in MiB.
|
||||
*
|
||||
* \since This function is available since SDL 2.0.1.
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL SDL_GetSystemRAM(void);
|
||||
|
||||
/**
|
||||
* Report the alignment this system needs for SIMD allocations.
|
||||
*
|
||||
* This will return the minimum number of bytes to which a pointer must be
|
||||
* aligned to be compatible with SIMD instructions on the current machine. For
|
||||
* example, if the machine supports SSE only, it will return 16, but if it
|
||||
* supports AVX-512F, it'll return 64 (etc). This only reports values for
|
||||
* instruction sets SDL knows about, so if your SDL build doesn't have
|
||||
* SDL_HasAVX512F(), then it might return 16 for the SSE support it sees and
|
||||
* not 64 for the AVX-512 instructions that exist but SDL doesn't know about.
|
||||
* Plan accordingly.
|
||||
*
|
||||
* \returns the alignment in bytes needed for available, known SIMD
|
||||
* instructions.
|
||||
*
|
||||
* \since This function is available since SDL 2.0.10.
|
||||
*/
|
||||
extern DECLSPEC size_t SDLCALL SDL_SIMDGetAlignment(void);
|
||||
|
||||
/**
|
||||
* Allocate memory in a SIMD-friendly way.
|
||||
*
|
||||
* This will allocate a block of memory that is suitable for use with SIMD
|
||||
* instructions. Specifically, it will be properly aligned and padded for the
|
||||
* system's supported vector instructions.
|
||||
*
|
||||
* The memory returned will be padded such that it is safe to read or write an
|
||||
* incomplete vector at the end of the memory block. This can be useful so you
|
||||
* don't have to drop back to a scalar fallback at the end of your SIMD
|
||||
* processing loop to deal with the final elements without overflowing the
|
||||
* allocated buffer.
|
||||
*
|
||||
* You must free this memory with SDL_FreeSIMD(), not free() or SDL_free() or
|
||||
* delete[], etc.
|
||||
*
|
||||
* Note that SDL will only deal with SIMD instruction sets it is aware of; for
|
||||
* example, SDL 2.0.8 knows that SSE wants 16-byte vectors (SDL_HasSSE()), and
|
||||
* AVX2 wants 32 bytes (SDL_HasAVX2()), but doesn't know that AVX-512 wants
|
||||
* 64. To be clear: if you can't decide to use an instruction set with an
|
||||
* SDL_Has*() function, don't use that instruction set with memory allocated
|
||||
* through here.
|
||||
*
|
||||
* SDL_AllocSIMD(0) will return a non-NULL pointer, assuming the system isn't
|
||||
* out of memory, but you are not allowed to dereference it (because you only
|
||||
* own zero bytes of that buffer).
|
||||
*
|
||||
* \param len The length, in bytes, of the block to allocate. The actual
|
||||
* allocated block might be larger due to padding, etc.
|
||||
* \returns a pointer to the newly-allocated block, NULL if out of memory.
|
||||
*
|
||||
* \since This function is available since SDL 2.0.10.
|
||||
*
|
||||
* \sa SDL_SIMDGetAlignment
|
||||
* \sa SDL_SIMDRealloc
|
||||
* \sa SDL_SIMDFree
|
||||
*/
|
||||
extern DECLSPEC void * SDLCALL SDL_SIMDAlloc(const size_t len);
|
||||
|
||||
/**
|
||||
* Reallocate memory obtained from SDL_SIMDAlloc
|
||||
*
|
||||
* It is not valid to use this function on a pointer from anything but
|
||||
* SDL_SIMDAlloc(). It can't be used on pointers from malloc, realloc,
|
||||
* SDL_malloc, memalign, new[], etc.
|
||||
*
|
||||
* \param mem The pointer obtained from SDL_SIMDAlloc. This function also
|
||||
* accepts NULL, at which point this function is the same as
|
||||
* calling SDL_SIMDAlloc with a NULL pointer.
|
||||
* \param len The length, in bytes, of the block to allocated. The actual
|
||||
* allocated block might be larger due to padding, etc. Passing 0
|
||||
* will return a non-NULL pointer, assuming the system isn't out of
|
||||
* memory.
|
||||
* \returns a pointer to the newly-reallocated block, NULL if out of memory.
|
||||
*
|
||||
* \since This function is available since SDL 2.0.14.
|
||||
*
|
||||
* \sa SDL_SIMDGetAlignment
|
||||
* \sa SDL_SIMDAlloc
|
||||
* \sa SDL_SIMDFree
|
||||
*/
|
||||
extern DECLSPEC void * SDLCALL SDL_SIMDRealloc(void *mem, const size_t len);
|
||||
|
||||
/**
|
||||
* Deallocate memory obtained from SDL_SIMDAlloc
|
||||
*
|
||||
* It is not valid to use this function on a pointer from anything but
|
||||
* SDL_SIMDAlloc() or SDL_SIMDRealloc(). It can't be used on pointers from
|
||||
* malloc, realloc, SDL_malloc, memalign, new[], etc.
|
||||
*
|
||||
* However, SDL_SIMDFree(NULL) is a legal no-op.
|
||||
*
|
||||
* The memory pointed to by `ptr` is no longer valid for access upon return,
|
||||
* and may be returned to the system or reused by a future allocation. The
|
||||
* pointer passed to this function is no longer safe to dereference once this
|
||||
* function returns, and should be discarded.
|
||||
*
|
||||
* \param ptr The pointer, returned from SDL_SIMDAlloc or SDL_SIMDRealloc, to
|
||||
* deallocate. NULL is a legal no-op.
|
||||
*
|
||||
* \since This function is available since SDL 2.0.10.
|
||||
*
|
||||
* \sa SDL_SIMDAlloc
|
||||
* \sa SDL_SIMDRealloc
|
||||
*/
|
||||
extern DECLSPEC void SDLCALL SDL_SIMDFree(void *ptr);
|
||||
|
||||
/* Ends C function definitions when using C++ */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#include <SDL2/close_code.h>
|
||||
|
||||
#endif /* SDL_cpuinfo_h_ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
@ -0,0 +1,348 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file SDL_endian.h
|
||||
*
|
||||
* Functions for reading and writing endian-specific values
|
||||
*/
|
||||
|
||||
#ifndef SDL_endian_h_
|
||||
#define SDL_endian_h_
|
||||
|
||||
#include <SDL2/SDL_stdinc.h>
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1400)
|
||||
/* As of Clang 11, '_m_prefetchw' is conflicting with the winnt.h's version,
|
||||
so we define the needed '_m_prefetch' here as a pseudo-header, until the issue is fixed. */
|
||||
#ifdef __clang__
|
||||
#ifndef __PRFCHWINTRIN_H
|
||||
#define __PRFCHWINTRIN_H
|
||||
static __inline__ void __attribute__((__always_inline__, __nodebug__))
|
||||
_m_prefetch(void *__P)
|
||||
{
|
||||
__builtin_prefetch(__P, 0, 3 /* _MM_HINT_T0 */);
|
||||
}
|
||||
#endif /* __PRFCHWINTRIN_H */
|
||||
#endif /* __clang__ */
|
||||
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \name The two types of endianness
|
||||
*/
|
||||
/* @{ */
|
||||
#define SDL_LIL_ENDIAN 1234
|
||||
#define SDL_BIG_ENDIAN 4321
|
||||
/* @} */
|
||||
|
||||
#ifndef SDL_BYTEORDER /* Not defined in SDL_config.h? */
|
||||
#ifdef __linux__
|
||||
#include <endian.h>
|
||||
#define SDL_BYTEORDER __BYTE_ORDER
|
||||
#elif defined(__OpenBSD__) || defined(__DragonFly__)
|
||||
#include <endian.h>
|
||||
#define SDL_BYTEORDER BYTE_ORDER
|
||||
#elif defined(__FreeBSD__) || defined(__NetBSD__)
|
||||
#include <sys/endian.h>
|
||||
#define SDL_BYTEORDER BYTE_ORDER
|
||||
/* predefs from newer gcc and clang versions: */
|
||||
#elif defined(__ORDER_LITTLE_ENDIAN__) && defined(__ORDER_BIG_ENDIAN__) && defined(__BYTE_ORDER__)
|
||||
#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
|
||||
#define SDL_BYTEORDER SDL_LIL_ENDIAN
|
||||
#elif (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
|
||||
#define SDL_BYTEORDER SDL_BIG_ENDIAN
|
||||
#else
|
||||
#error Unsupported endianness
|
||||
#endif /**/
|
||||
#else
|
||||
#if defined(__hppa__) || \
|
||||
defined(__m68k__) || defined(mc68000) || defined(_M_M68K) || \
|
||||
(defined(__MIPS__) && defined(__MIPSEB__)) || \
|
||||
defined(__ppc__) || defined(__POWERPC__) || defined(__powerpc__) || defined(__PPC__) || \
|
||||
defined(__sparc__)
|
||||
#define SDL_BYTEORDER SDL_BIG_ENDIAN
|
||||
#else
|
||||
#define SDL_BYTEORDER SDL_LIL_ENDIAN
|
||||
#endif
|
||||
#endif /* __linux__ */
|
||||
#endif /* !SDL_BYTEORDER */
|
||||
|
||||
#ifndef SDL_FLOATWORDORDER /* Not defined in SDL_config.h? */
|
||||
/* predefs from newer gcc versions: */
|
||||
#if defined(__ORDER_LITTLE_ENDIAN__) && defined(__ORDER_BIG_ENDIAN__) && defined(__FLOAT_WORD_ORDER__)
|
||||
#if (__FLOAT_WORD_ORDER__ == __ORDER_LITTLE_ENDIAN__)
|
||||
#define SDL_FLOATWORDORDER SDL_LIL_ENDIAN
|
||||
#elif (__FLOAT_WORD_ORDER__ == __ORDER_BIG_ENDIAN__)
|
||||
#define SDL_FLOATWORDORDER SDL_BIG_ENDIAN
|
||||
#else
|
||||
#error Unsupported endianness
|
||||
#endif /**/
|
||||
#elif defined(__MAVERICK__)
|
||||
/* For Maverick, float words are always little-endian. */
|
||||
#define SDL_FLOATWORDORDER SDL_LIL_ENDIAN
|
||||
#elif (defined(__arm__) || defined(__thumb__)) && !defined(__VFP_FP__) && !defined(__ARM_EABI__)
|
||||
/* For FPA, float words are always big-endian. */
|
||||
#define SDL_FLOATWORDORDER SDL_BIG_ENDIAN
|
||||
#else
|
||||
/* By default, assume that floats words follow the memory system mode. */
|
||||
#define SDL_FLOATWORDORDER SDL_BYTEORDER
|
||||
#endif /* __FLOAT_WORD_ORDER__ */
|
||||
#endif /* !SDL_FLOATWORDORDER */
|
||||
|
||||
|
||||
#include <SDL2/begin_code.h>
|
||||
/* Set up for C function definitions, even when using C++ */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \file SDL_endian.h
|
||||
*/
|
||||
|
||||
/* various modern compilers may have builtin swap */
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
# define HAS_BUILTIN_BSWAP16 (_SDL_HAS_BUILTIN(__builtin_bswap16)) || \
|
||||
(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))
|
||||
# define HAS_BUILTIN_BSWAP32 (_SDL_HAS_BUILTIN(__builtin_bswap32)) || \
|
||||
(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
|
||||
# define HAS_BUILTIN_BSWAP64 (_SDL_HAS_BUILTIN(__builtin_bswap64)) || \
|
||||
(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
|
||||
|
||||
/* this one is broken */
|
||||
# define HAS_BROKEN_BSWAP (__GNUC__ == 2 && __GNUC_MINOR__ <= 95)
|
||||
#else
|
||||
# define HAS_BUILTIN_BSWAP16 0
|
||||
# define HAS_BUILTIN_BSWAP32 0
|
||||
# define HAS_BUILTIN_BSWAP64 0
|
||||
# define HAS_BROKEN_BSWAP 0
|
||||
#endif
|
||||
|
||||
#if HAS_BUILTIN_BSWAP16
|
||||
#define SDL_Swap16(x) __builtin_bswap16(x)
|
||||
#elif defined(_MSC_VER) && (_MSC_VER >= 1400)
|
||||
#pragma intrinsic(_byteswap_ushort)
|
||||
#define SDL_Swap16(x) _byteswap_ushort(x)
|
||||
#elif defined(__i386__) && !HAS_BROKEN_BSWAP
|
||||
SDL_FORCE_INLINE Uint16
|
||||
SDL_Swap16(Uint16 x)
|
||||
{
|
||||
__asm__("xchgb %b0,%h0": "=q"(x):"0"(x));
|
||||
return x;
|
||||
}
|
||||
#elif defined(__x86_64__)
|
||||
SDL_FORCE_INLINE Uint16
|
||||
SDL_Swap16(Uint16 x)
|
||||
{
|
||||
__asm__("xchgb %b0,%h0": "=Q"(x):"0"(x));
|
||||
return x;
|
||||
}
|
||||
#elif (defined(__powerpc__) || defined(__ppc__))
|
||||
SDL_FORCE_INLINE Uint16
|
||||
SDL_Swap16(Uint16 x)
|
||||
{
|
||||
int result;
|
||||
|
||||
__asm__("rlwimi %0,%2,8,16,23": "=&r"(result):"0"(x >> 8), "r"(x));
|
||||
return (Uint16)result;
|
||||
}
|
||||
#elif (defined(__m68k__) && !defined(__mcoldfire__))
|
||||
SDL_FORCE_INLINE Uint16
|
||||
SDL_Swap16(Uint16 x)
|
||||
{
|
||||
__asm__("rorw #8,%0": "=d"(x): "0"(x):"cc");
|
||||
return x;
|
||||
}
|
||||
#elif defined(__WATCOMC__) && defined(__386__)
|
||||
extern __inline Uint16 SDL_Swap16(Uint16);
|
||||
#pragma aux SDL_Swap16 = \
|
||||
"xchg al, ah" \
|
||||
parm [ax] \
|
||||
modify [ax];
|
||||
#else
|
||||
SDL_FORCE_INLINE Uint16
|
||||
SDL_Swap16(Uint16 x)
|
||||
{
|
||||
return SDL_static_cast(Uint16, ((x << 8) | (x >> 8)));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HAS_BUILTIN_BSWAP32
|
||||
#define SDL_Swap32(x) __builtin_bswap32(x)
|
||||
#elif defined(_MSC_VER) && (_MSC_VER >= 1400)
|
||||
#pragma intrinsic(_byteswap_ulong)
|
||||
#define SDL_Swap32(x) _byteswap_ulong(x)
|
||||
#elif defined(__i386__) && !HAS_BROKEN_BSWAP
|
||||
SDL_FORCE_INLINE Uint32
|
||||
SDL_Swap32(Uint32 x)
|
||||
{
|
||||
__asm__("bswap %0": "=r"(x):"0"(x));
|
||||
return x;
|
||||
}
|
||||
#elif defined(__x86_64__)
|
||||
SDL_FORCE_INLINE Uint32
|
||||
SDL_Swap32(Uint32 x)
|
||||
{
|
||||
__asm__("bswapl %0": "=r"(x):"0"(x));
|
||||
return x;
|
||||
}
|
||||
#elif (defined(__powerpc__) || defined(__ppc__))
|
||||
SDL_FORCE_INLINE Uint32
|
||||
SDL_Swap32(Uint32 x)
|
||||
{
|
||||
Uint32 result;
|
||||
|
||||
__asm__("rlwimi %0,%2,24,16,23": "=&r"(result): "0" (x>>24), "r"(x));
|
||||
__asm__("rlwimi %0,%2,8,8,15" : "=&r"(result): "0" (result), "r"(x));
|
||||
__asm__("rlwimi %0,%2,24,0,7" : "=&r"(result): "0" (result), "r"(x));
|
||||
return result;
|
||||
}
|
||||
#elif (defined(__m68k__) && !defined(__mcoldfire__))
|
||||
SDL_FORCE_INLINE Uint32
|
||||
SDL_Swap32(Uint32 x)
|
||||
{
|
||||
__asm__("rorw #8,%0\n\tswap %0\n\trorw #8,%0": "=d"(x): "0"(x):"cc");
|
||||
return x;
|
||||
}
|
||||
#elif defined(__WATCOMC__) && defined(__386__)
|
||||
extern __inline Uint32 SDL_Swap32(Uint32);
|
||||
#pragma aux SDL_Swap32 = \
|
||||
"bswap eax" \
|
||||
parm [eax] \
|
||||
modify [eax];
|
||||
#else
|
||||
SDL_FORCE_INLINE Uint32
|
||||
SDL_Swap32(Uint32 x)
|
||||
{
|
||||
return SDL_static_cast(Uint32, ((x << 24) | ((x << 8) & 0x00FF0000) |
|
||||
((x >> 8) & 0x0000FF00) | (x >> 24)));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HAS_BUILTIN_BSWAP64
|
||||
#define SDL_Swap64(x) __builtin_bswap64(x)
|
||||
#elif defined(_MSC_VER) && (_MSC_VER >= 1400)
|
||||
#pragma intrinsic(_byteswap_uint64)
|
||||
#define SDL_Swap64(x) _byteswap_uint64(x)
|
||||
#elif defined(__i386__) && !HAS_BROKEN_BSWAP
|
||||
SDL_FORCE_INLINE Uint64
|
||||
SDL_Swap64(Uint64 x)
|
||||
{
|
||||
union {
|
||||
struct {
|
||||
Uint32 a, b;
|
||||
} s;
|
||||
Uint64 u;
|
||||
} v;
|
||||
v.u = x;
|
||||
__asm__("bswapl %0 ; bswapl %1 ; xchgl %0,%1"
|
||||
: "=r"(v.s.a), "=r"(v.s.b)
|
||||
: "0" (v.s.a), "1"(v.s.b));
|
||||
return v.u;
|
||||
}
|
||||
#elif defined(__x86_64__)
|
||||
SDL_FORCE_INLINE Uint64
|
||||
SDL_Swap64(Uint64 x)
|
||||
{
|
||||
__asm__("bswapq %0": "=r"(x):"0"(x));
|
||||
return x;
|
||||
}
|
||||
#elif defined(__WATCOMC__) && defined(__386__)
|
||||
extern __inline Uint64 SDL_Swap64(Uint64);
|
||||
#pragma aux SDL_Swap64 = \
|
||||
"bswap eax" \
|
||||
"bswap edx" \
|
||||
"xchg eax,edx" \
|
||||
parm [eax edx] \
|
||||
modify [eax edx];
|
||||
#else
|
||||
SDL_FORCE_INLINE Uint64
|
||||
SDL_Swap64(Uint64 x)
|
||||
{
|
||||
Uint32 hi, lo;
|
||||
|
||||
/* Separate into high and low 32-bit values and swap them */
|
||||
lo = SDL_static_cast(Uint32, x & 0xFFFFFFFF);
|
||||
x >>= 32;
|
||||
hi = SDL_static_cast(Uint32, x & 0xFFFFFFFF);
|
||||
x = SDL_Swap32(lo);
|
||||
x <<= 32;
|
||||
x |= SDL_Swap32(hi);
|
||||
return (x);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
SDL_FORCE_INLINE float
|
||||
SDL_SwapFloat(float x)
|
||||
{
|
||||
union {
|
||||
float f;
|
||||
Uint32 ui32;
|
||||
} swapper;
|
||||
swapper.f = x;
|
||||
swapper.ui32 = SDL_Swap32(swapper.ui32);
|
||||
return swapper.f;
|
||||
}
|
||||
|
||||
/* remove extra macros */
|
||||
#undef HAS_BROKEN_BSWAP
|
||||
#undef HAS_BUILTIN_BSWAP16
|
||||
#undef HAS_BUILTIN_BSWAP32
|
||||
#undef HAS_BUILTIN_BSWAP64
|
||||
|
||||
/**
|
||||
* \name Swap to native
|
||||
* Byteswap item from the specified endianness to the native endianness.
|
||||
*/
|
||||
/* @{ */
|
||||
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
|
||||
#define SDL_SwapLE16(X) (X)
|
||||
#define SDL_SwapLE32(X) (X)
|
||||
#define SDL_SwapLE64(X) (X)
|
||||
#define SDL_SwapFloatLE(X) (X)
|
||||
#define SDL_SwapBE16(X) SDL_Swap16(X)
|
||||
#define SDL_SwapBE32(X) SDL_Swap32(X)
|
||||
#define SDL_SwapBE64(X) SDL_Swap64(X)
|
||||
#define SDL_SwapFloatBE(X) SDL_SwapFloat(X)
|
||||
#else
|
||||
#define SDL_SwapLE16(X) SDL_Swap16(X)
|
||||
#define SDL_SwapLE32(X) SDL_Swap32(X)
|
||||
#define SDL_SwapLE64(X) SDL_Swap64(X)
|
||||
#define SDL_SwapFloatLE(X) SDL_SwapFloat(X)
|
||||
#define SDL_SwapBE16(X) (X)
|
||||
#define SDL_SwapBE32(X) (X)
|
||||
#define SDL_SwapBE64(X) (X)
|
||||
#define SDL_SwapFloatBE(X) (X)
|
||||
#endif
|
||||
/* @} *//* Swap to native */
|
||||
|
||||
/* Ends C function definitions when using C++ */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#include <SDL2/close_code.h>
|
||||
|
||||
#endif /* SDL_endian_h_ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
@ -0,0 +1,163 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file SDL_error.h
|
||||
*
|
||||
* Simple error message routines for SDL.
|
||||
*/
|
||||
|
||||
#ifndef SDL_error_h_
|
||||
#define SDL_error_h_
|
||||
|
||||
#include <SDL2/SDL_stdinc.h>
|
||||
|
||||
#include <SDL2/begin_code.h>
|
||||
/* Set up for C function definitions, even when using C++ */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Public functions */
|
||||
|
||||
|
||||
/**
|
||||
* Set the SDL error message for the current thread.
|
||||
*
|
||||
* Calling this function will replace any previous error message that was set.
|
||||
*
|
||||
* This function always returns -1, since SDL frequently uses -1 to signify an
|
||||
* failing result, leading to this idiom:
|
||||
*
|
||||
* ```c
|
||||
* if (error_code) {
|
||||
* return SDL_SetError("This operation has failed: %d", error_code);
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* \param fmt a printf()-style message format string
|
||||
* \param ... additional parameters matching % tokens in the `fmt` string, if
|
||||
* any
|
||||
* \returns always -1.
|
||||
*
|
||||
* \since This function is available since SDL 2.0.0.
|
||||
*
|
||||
* \sa SDL_ClearError
|
||||
* \sa SDL_GetError
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL SDL_SetError(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(1);
|
||||
|
||||
/**
|
||||
* Retrieve a message about the last error that occurred on the current
|
||||
* thread.
|
||||
*
|
||||
* It is possible for multiple errors to occur before calling SDL_GetError().
|
||||
* Only the last error is returned.
|
||||
*
|
||||
* The message is only applicable when an SDL function has signaled an error.
|
||||
* You must check the return values of SDL function calls to determine when to
|
||||
* appropriately call SDL_GetError(). You should *not* use the results of
|
||||
* SDL_GetError() to decide if an error has occurred! Sometimes SDL will set
|
||||
* an error string even when reporting success.
|
||||
*
|
||||
* SDL will *not* clear the error string for successful API calls. You *must*
|
||||
* check return values for failure cases before you can assume the error
|
||||
* string applies.
|
||||
*
|
||||
* Error strings are set per-thread, so an error set in a different thread
|
||||
* will not interfere with the current thread's operation.
|
||||
*
|
||||
* The returned string is internally allocated and must not be freed by the
|
||||
* application.
|
||||
*
|
||||
* \returns a message with information about the specific error that occurred,
|
||||
* or an empty string if there hasn't been an error message set since
|
||||
* the last call to SDL_ClearError(). The message is only applicable
|
||||
* when an SDL function has signaled an error. You must check the
|
||||
* return values of SDL function calls to determine when to
|
||||
* appropriately call SDL_GetError().
|
||||
*
|
||||
* \since This function is available since SDL 2.0.0.
|
||||
*
|
||||
* \sa SDL_ClearError
|
||||
* \sa SDL_SetError
|
||||
*/
|
||||
extern DECLSPEC const char *SDLCALL SDL_GetError(void);
|
||||
|
||||
/**
|
||||
* Get the last error message that was set for the current thread.
|
||||
*
|
||||
* This allows the caller to copy the error string into a provided buffer, but
|
||||
* otherwise operates exactly the same as SDL_GetError().
|
||||
*
|
||||
* \param errstr A buffer to fill with the last error message that was set for
|
||||
* the current thread
|
||||
* \param maxlen The size of the buffer pointed to by the errstr parameter
|
||||
* \returns the pointer passed in as the `errstr` parameter.
|
||||
*
|
||||
* \since This function is available since SDL 2.0.14.
|
||||
*
|
||||
* \sa SDL_GetError
|
||||
*/
|
||||
extern DECLSPEC char * SDLCALL SDL_GetErrorMsg(char *errstr, int maxlen);
|
||||
|
||||
/**
|
||||
* Clear any previous error message for this thread.
|
||||
*
|
||||
* \since This function is available since SDL 2.0.0.
|
||||
*
|
||||
* \sa SDL_GetError
|
||||
* \sa SDL_SetError
|
||||
*/
|
||||
extern DECLSPEC void SDLCALL SDL_ClearError(void);
|
||||
|
||||
/**
|
||||
* \name Internal error functions
|
||||
*
|
||||
* \internal
|
||||
* Private error reporting function - used internally.
|
||||
*/
|
||||
/* @{ */
|
||||
#define SDL_OutOfMemory() SDL_Error(SDL_ENOMEM)
|
||||
#define SDL_Unsupported() SDL_Error(SDL_UNSUPPORTED)
|
||||
#define SDL_InvalidParamError(param) SDL_SetError("Parameter '%s' is invalid", (param))
|
||||
typedef enum
|
||||
{
|
||||
SDL_ENOMEM,
|
||||
SDL_EFREAD,
|
||||
SDL_EFWRITE,
|
||||
SDL_EFSEEK,
|
||||
SDL_UNSUPPORTED,
|
||||
SDL_LASTERROR
|
||||
} SDL_errorcode;
|
||||
/* SDL_Error() unconditionally returns -1. */
|
||||
extern DECLSPEC int SDLCALL SDL_Error(SDL_errorcode code);
|
||||
/* @} *//* Internal error functions */
|
||||
|
||||
/* Ends C function definitions when using C++ */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#include <SDL2/close_code.h>
|
||||
|
||||
#endif /* SDL_error_h_ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,149 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file SDL_filesystem.h
|
||||
*
|
||||
* \brief Include file for filesystem SDL API functions
|
||||
*/
|
||||
|
||||
#ifndef SDL_filesystem_h_
|
||||
#define SDL_filesystem_h_
|
||||
|
||||
#include <SDL2/SDL_stdinc.h>
|
||||
|
||||
#include <SDL2/begin_code.h>
|
||||
|
||||
/* Set up for C function definitions, even when using C++ */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Get the directory where the application was run from.
|
||||
*
|
||||
* This is not necessarily a fast call, so you should call this once near
|
||||
* startup and save the string if you need it.
|
||||
*
|
||||
* **Mac OS X and iOS Specific Functionality**: If the application is in a
|
||||
* ".app" bundle, this function returns the Resource directory (e.g.
|
||||
* MyApp.app/Contents/Resources/). This behaviour can be overridden by adding
|
||||
* a property to the Info.plist file. Adding a string key with the name
|
||||
* SDL_FILESYSTEM_BASE_DIR_TYPE with a supported value will change the
|
||||
* behaviour.
|
||||
*
|
||||
* Supported values for the SDL_FILESYSTEM_BASE_DIR_TYPE property (Given an
|
||||
* application in /Applications/SDLApp/MyApp.app):
|
||||
*
|
||||
* - `resource`: bundle resource directory (the default). For example:
|
||||
* `/Applications/SDLApp/MyApp.app/Contents/Resources`
|
||||
* - `bundle`: the Bundle directory. For example:
|
||||
* `/Applications/SDLApp/MyApp.app/`
|
||||
* - `parent`: the containing directory of the bundle. For example:
|
||||
* `/Applications/SDLApp/`
|
||||
*
|
||||
* **Nintendo 3DS Specific Functionality**: This function returns "romfs"
|
||||
* directory of the application as it is uncommon to store resources outside
|
||||
* the executable. As such it is not a writable directory.
|
||||
*
|
||||
* The returned path is guaranteed to end with a path separator ('\' on
|
||||
* Windows, '/' on most other platforms).
|
||||
*
|
||||
* The pointer returned is owned by the caller. Please call SDL_free() on the
|
||||
* pointer when done with it.
|
||||
*
|
||||
* \returns an absolute path in UTF-8 encoding to the application data
|
||||
* directory. NULL will be returned on error or when the platform
|
||||
* doesn't implement this functionality, call SDL_GetError() for more
|
||||
* information.
|
||||
*
|
||||
* \since This function is available since SDL 2.0.1.
|
||||
*
|
||||
* \sa SDL_GetPrefPath
|
||||
*/
|
||||
extern DECLSPEC char *SDLCALL SDL_GetBasePath(void);
|
||||
|
||||
/**
|
||||
* Get the user-and-app-specific path where files can be written.
|
||||
*
|
||||
* Get the "pref dir". This is meant to be where users can write personal
|
||||
* files (preferences and save games, etc) that are specific to your
|
||||
* application. This directory is unique per user, per application.
|
||||
*
|
||||
* This function will decide the appropriate location in the native
|
||||
* filesystem, create the directory if necessary, and return a string of the
|
||||
* absolute path to the directory in UTF-8 encoding.
|
||||
*
|
||||
* On Windows, the string might look like:
|
||||
*
|
||||
* `C:\\Users\\bob\\AppData\\Roaming\\My Company\\My Program Name\\`
|
||||
*
|
||||
* On Linux, the string might look like:
|
||||
*
|
||||
* `/home/bob/.local/share/My Program Name/`
|
||||
*
|
||||
* On Mac OS X, the string might look like:
|
||||
*
|
||||
* `/Users/bob/Library/Application Support/My Program Name/`
|
||||
*
|
||||
* You should assume the path returned by this function is the only safe place
|
||||
* to write files (and that SDL_GetBasePath(), while it might be writable, or
|
||||
* even the parent of the returned path, isn't where you should be writing
|
||||
* things).
|
||||
*
|
||||
* Both the org and app strings may become part of a directory name, so please
|
||||
* follow these rules:
|
||||
*
|
||||
* - Try to use the same org string (_including case-sensitivity_) for all
|
||||
* your applications that use this function.
|
||||
* - Always use a unique app string for each one, and make sure it never
|
||||
* changes for an app once you've decided on it.
|
||||
* - Unicode characters are legal, as long as it's UTF-8 encoded, but...
|
||||
* - ...only use letters, numbers, and spaces. Avoid punctuation like "Game
|
||||
* Name 2: Bad Guy's Revenge!" ... "Game Name 2" is sufficient.
|
||||
*
|
||||
* The returned path is guaranteed to end with a path separator ('\' on
|
||||
* Windows, '/' on most other platforms).
|
||||
*
|
||||
* The pointer returned is owned by the caller. Please call SDL_free() on the
|
||||
* pointer when done with it.
|
||||
*
|
||||
* \param org the name of your organization
|
||||
* \param app the name of your application
|
||||
* \returns a UTF-8 string of the user directory in platform-dependent
|
||||
* notation. NULL if there's a problem (creating directory failed,
|
||||
* etc.).
|
||||
*
|
||||
* \since This function is available since SDL 2.0.1.
|
||||
*
|
||||
* \sa SDL_GetBasePath
|
||||
*/
|
||||
extern DECLSPEC char *SDLCALL SDL_GetPrefPath(const char *org, const char *app);
|
||||
|
||||
/* Ends C function definitions when using C++ */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#include <SDL2/close_code.h>
|
||||
|
||||
#endif /* SDL_filesystem_h_ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user