Archived
1
0
forked from MeloNX/MeloNX

Compare commits

...
This repository has been archived on 2025-04-07. You can view files and clone it, but cannot push or open issues or pull requests.

402 Commits

Author SHA1 Message Date
ee179cacc4 Merge branch 'XC-ios-ht' into test
# Conflicts:
#	.gitignore
#	Directory.Packages.props
#	README.md
#	src/ARMeilleure/Instructions/InstEmitMemoryHelper.cs
#	src/ARMeilleure/Memory/MemoryManagerType.cs
#	src/ARMeilleure/Signal/NativeSignalHandlerGenerator.cs
#	src/ARMeilleure/Signal/UnixSignalHandlerRegistration.cs
#	src/ARMeilleure/Translation/PTC/Ptc.cs
#	src/ARMeilleure/Translation/Translator.cs
#	src/Ryujinx.Ava/Ryujinx.Ava.csproj
#	src/Ryujinx.Ava/UI/Models/InputConfiguration.cs
#	src/Ryujinx.Ava/UI/Views/Input/ControllerInputView.axaml.cs
#	src/Ryujinx.Common/Configuration/AppDataManager.cs
#	src/Ryujinx.Common/Logging/Targets/ConsoleLogTarget.cs
#	src/Ryujinx.Common/ReleaseInformation.cs
#	src/Ryujinx.Cpu/AppleHv/HvMemoryManager.cs
#	src/Ryujinx.Cpu/Jit/JitCpuContext.cs
#	src/Ryujinx.Cpu/Jit/JitMemoryAllocator.cs
#	src/Ryujinx.Cpu/Jit/MemoryManagerHostTracked.cs
#	src/Ryujinx.Cpu/LightningJit/Arm32/Block.cs
#	src/Ryujinx.Cpu/LightningJit/Arm32/Decoder.cs
#	src/Ryujinx.Cpu/LightningJit/Arm32/MultiBlock.cs
#	src/Ryujinx.Cpu/LightningJit/Arm32/RegisterAllocator.cs
#	src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/Compiler.cs
#	src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitFlow.cs
#	src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitMemory.cs
#	src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitMove.cs
#	src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonMemory.cs
#	src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitSaturate.cs
#	src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitSystem.cs
#	src/Ryujinx.Cpu/LightningJit/Arm64/InstName.cs
#	src/Ryujinx.Cpu/LightningJit/Arm64/RegisterAllocator.cs
#	src/Ryujinx.Cpu/LightningJit/Arm64/RegisterUtils.cs
#	src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/Compiler.cs
#	src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/Decoder.cs
#	src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/InstEmitMemory.cs
#	src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/InstEmitSystem.cs
#	src/Ryujinx.Cpu/LightningJit/Cache/CacheEntry.cs
#	src/Ryujinx.Cpu/LightningJit/Cache/NoWxCache.cs
#	src/Ryujinx.Cpu/LightningJit/LightningJitCpuContext.cs
#	src/Ryujinx.Cpu/LightningJit/LightningJitEngine.cs
#	src/Ryujinx.Cpu/LightningJit/Translator.cs
#	src/Ryujinx.Cpu/MemoryEhMeilleure.cs
#	src/Ryujinx.Graphics.Device/DeviceState.cs
#	src/Ryujinx.Graphics.GAL/ITexture.cs
#	src/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureSetDataCommand.cs
#	src/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureSetDataSliceCommand.cs
#	src/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureSetDataSliceRegionCommand.cs
#	src/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedTexture.cs
#	src/Ryujinx.Graphics.Gpu/Engine/InlineToMemory/InlineToMemoryClass.cs
#	src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdateTracker.cs
#	src/Ryujinx.Graphics.Gpu/Image/Texture.cs
#	src/Ryujinx.Graphics.Gpu/Image/TextureGroup.cs
#	src/Ryujinx.Graphics.OpenGL/Image/TextureBuffer.cs
#	src/Ryujinx.Graphics.OpenGL/Image/TextureView.cs
#	src/Ryujinx.Graphics.Texture/Astc/AstcDecoder.cs
#	src/Ryujinx.Graphics.Texture/BCnDecoder.cs
#	src/Ryujinx.Graphics.Texture/BCnEncoder.cs
#	src/Ryujinx.Graphics.Texture/ETC2Decoder.cs
#	src/Ryujinx.Graphics.Texture/LayoutConverter.cs
#	src/Ryujinx.Graphics.Texture/PixelConverter.cs
#	src/Ryujinx.Graphics.Vulkan/CommandBufferPool.cs
#	src/Ryujinx.Graphics.Vulkan/DescriptorSetCollection.cs
#	src/Ryujinx.Graphics.Vulkan/DescriptorSetManager.cs
#	src/Ryujinx.Graphics.Vulkan/DescriptorSetUpdater.cs
#	src/Ryujinx.Graphics.Vulkan/PipelineState.cs
#	src/Ryujinx.Graphics.Vulkan/TextureBuffer.cs
#	src/Ryujinx.Graphics.Vulkan/TextureView.cs
#	src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs
#	src/Ryujinx.Gtk3/UI/Applet/GtkHostUIHandler.cs
#	src/Ryujinx.HLE.Generators/CodeGenerator.cs
#	src/Ryujinx.HLE.Generators/IpcServiceGenerator.cs
#	src/Ryujinx.HLE.Generators/ServiceSyntaxReceiver.cs
#	src/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardApplet.cs
#	src/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardRendererBase.cs
#	src/Ryujinx.HLE/HOS/ArmProcessContextFactory.cs
#	src/Ryujinx.HLE/HOS/Services/Nifm/StaticService/Types/IpAddressSetting.cs
#	src/Ryujinx.HLE/Loaders/Processes/Extensions/PartitionFileSystemExtensions.cs
#	src/Ryujinx.HLE/Ryujinx.HLE.csproj
#	src/Ryujinx.HLE/UI/IHostUIHandler.cs
#	src/Ryujinx.Headless.SDL2/Program.cs
#	src/Ryujinx.Headless.SDL2/WindowBase.cs
#	src/Ryujinx.Memory/MemoryBlock.cs
#	src/Ryujinx.Memory/MemoryManagement.cs
#	src/Ryujinx.Memory/MemoryManagementUnix.cs
#	src/Ryujinx.SDL2.Common/SDL2Driver.cs
#	src/Ryujinx.Ui.Common/App/ApplicationLibrary.cs
#	src/Ryujinx/Assets/Styles/Styles.xaml
#	src/Ryujinx/UI/Applet/AvaHostUIHandler.cs
#	src/Ryujinx/UI/ViewModels/GamePadInputViewModel.cs
#	src/Ryujinx/UI/ViewModels/Input/InputViewModel.cs
#	src/Ryujinx/UI/ViewModels/InputViewModel.cs
#	src/Ryujinx/UI/ViewModels/KeyboardInputViewModel.cs
#	src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs
#	src/Ryujinx/UI/Views/Input/ControllerInputView.axaml
#	src/Ryujinx/UI/Views/Input/GamePadInputView.axaml
#	src/Ryujinx/UI/Views/Input/GamePadInputView.axaml.cs
#	src/Ryujinx/UI/Views/Input/KeyboardInputView.axaml
#	src/Ryujinx/UI/Views/Input/KeyboardInputView.axaml.cs
#	src/Ryujinx/UI/Views/Input/MotionInputView.axaml.cs
#	src/Ryujinx/UI/Views/Input/RumbleInputView.axaml.cs
#	src/Ryujinx/UI/Windows/IconColorPicker.cs
#	src/Ryujinx/rd.xml
2025-03-01 21:58:58 +01:00
Stossy11
e924da52ec add back SDL Window option 2025-03-01 21:31:33 +11:00
Stossy11
ea2eff15c6 New gitignore 2025-03-01 21:06:09 +11:00
Stossy11
c6ff0b60bf Adds pull #12 and changes version number 2025-03-01 21:03:07 +11:00
Stossy11
edc56316cc add iOS 15 support back, fix the need for SDL Window and more 2025-03-01 20:54:57 +11:00
Stossy11
8df465a959 implement an all-swift approach for detecting JIT (adds support for detecting JIT on iOS 18.4+), adds an easter egg, and more 2025-03-01 20:54:57 +11:00
527ac3fb23 Update README.md 2025-02-20 20:54:03 +00:00
8e60f6dc50 Update README.md 2025-02-19 07:42:45 +00:00
Stossy11
3b99631dfb Implement JIT Cache Regions and Add Handheld Input 2025-02-19 11:16:50 +11:00
cb33b04f2b Merge pull request 'GCController wrapper' (#6) from XITRIX/MeloNX:Controller-fix into XC-ios-ht
Reviewed-on: MeloNX/MeloNX#6
2025-02-17 01:20:48 +00:00
500f3d5b9e Fix for virtual controller detach | pass gamepad haptic engine 2025-02-17 00:39:04 +01:00
ac4e5d394e Hide non wrapped controllers 2025-02-17 00:39:03 +01:00
f2d078f80b GCController wrapper 2025-02-17 00:39:03 +01:00
004a81fa60 Merge pull request 'DLC manager implemented' (#11) from XITRIX/MeloNX:DLC-support into XC-ios-ht
Reviewed-on: MeloNX/MeloNX#11
2025-02-16 23:33:30 +00:00
ddf634ecb6 DLC manager implemented 2025-02-17 00:28:05 +01:00
Stossy11
cce876c6f5 Change version number 2025-02-17 07:40:56 +11:00
ebfb39c132 Merge pull request 'Correct device req + Add Xcode to compiling req' (#10) from C4ndyF1sh/MeloNX:device-req-and-compiling-req into XC-ios-ht
Reviewed-on: MeloNX/MeloNX#10
2025-02-16 20:15:56 +00:00
b3bb9cefcf Merge pull request 'Update manager fix' (#8) from XITRIX/MeloNX:Update-manager-fix into XC-ios-ht
Reviewed-on: MeloNX/MeloNX#8
2025-02-16 20:14:58 +00:00
8c54134699 Update Compile.md 2025-02-16 17:57:59 +00:00
e8537df246 Update README.md 2025-02-16 17:55:44 +00:00
8c6dd455f2 Game update path fix 2025-02-16 15:46:46 +01:00
2a7cfa5650 GameInfo UI enhancement 2025-02-16 13:52:12 +01:00
df2b17ddd6 UI enhancements 2025-02-16 13:41:57 +01:00
757fb1f6d1 Update manager fix 2025-02-16 13:41:57 +01:00
Stossy11
e741039304 Add Entitlement Checker and Memory 2025-02-16 17:29:09 +11:00
Stossy11
fd0ce75f67 Fix whatever happened 2025-02-16 16:22:20 +11:00
Stossy11
0e80bd3d51 Add game update manager 2025-02-16 14:01:31 +11:00
Stossy11
f95281899c a bunch of changes 2025-02-16 12:17:12 +11:00
802a8d7bae Merge pull request 'Added title update functionality' (#7) from XITRIX/MeloNX:Title-update into XC-ios-ht
Reviewed-on: MeloNX/MeloNX#7
2025-02-16 00:04:42 +00:00
7277e1fa9b Add title update functionality 2025-02-15 20:34:36 +01:00
27312d4f31 Null pointer fix 2025-02-15 20:34:36 +01:00
dhlalit11
932a4a24d3
Update dotnet.yml 2024-10-04 11:00:34 +05:30
dhlalit11
7137063277
Create dotnet.yml 2024-10-04 10:55:48 +05:30
Emmanuel Hansen
c825ab4d6f remove unused class 2024-09-15 19:06:03 +00:00
Emmanuel Hansen
59c34f10aa android - replace surface pointer query with jni callback 2024-09-10 09:11:42 +00:00
Emmanuel Hansen
5053ead4b3 android - use direct calls for progress update 2024-09-10 09:11:42 +00:00
Emmanuel Hansen
e2f584a7ff android - update ui handler to call back into java 2024-09-10 09:11:41 +00:00
Emmanuel Hansen
b7deaefff7 android - update jni 2024-09-10 09:11:41 +00:00
Emmanuel Hansen
4a47481e7a bionic - fix rotation 2024-09-10 09:11:40 +00:00
Emmanuel Hansen
cca7cd02cf bionic - remove dupped method 2024-09-10 09:11:40 +00:00
Emmanuel Hansen
f38093a1f7 pin bionic version to dotnet 9 2024-09-10 09:11:40 +00:00
Emmanuel Hansen
7e426c4377 test
# Conflicts:
#	src/RyujinxAndroid/app/src/main/cpp/ryujinx.cpp
2024-09-10 09:11:40 +00:00
Emmanuel Hansen
ba5b26c5cf android - bump version 2024-09-10 09:11:39 +00:00
Emmanuel Hansen
85c4450eb2 android - bump version 2024-09-10 09:11:39 +00:00
Emmanuel Hansen
ab0845d732 android - fix cpu and mem stats update 2024-09-10 09:11:39 +00:00
Emmanuel Hansen
08853515af android - bump version 2024-09-10 09:11:38 +00:00
Emmanuel Hansen
1a94e37816 android - update version
android - stop loading game if update fails

android - add refresh list button

android - fix update error return code

android - fix compose error with game list

android - add progress indicator for game list

android - fix game list loading

android - adjust virtual controller button positions. added stick sensitivity option

android - bump version

android - fix vulkan driver install
2024-09-10 09:11:38 +00:00
Emmanuel Hansen
d19582b055 fix helper shader using unsupported shader feature 2024-09-10 09:11:38 +00:00
Emmanuel Hansen
330dfdc131 android - add option to clear all cache for a game 2024-09-10 09:11:37 +00:00
Emmanuel Hansen
3ff7b1d32d update build version 2024-09-10 09:11:37 +00:00
Emmanuel Hansen
affefc35a8 fix usage stat update 2024-09-10 09:11:36 +00:00
Emmanuel Hansen
a00c8c909f android - replace jni with jna 2024-09-10 09:11:36 +00:00
Emmanuel Hansen
8888edde5c improve homeview extra options
update gradle deps
cleanup search bar
2024-09-10 09:10:32 +00:00
TSR Berry
d19b391ca6 Find nmake on Windows using vswhere 2024-09-10 09:10:32 +00:00
TSR Berry
9bcc48646a Convert Android toolchain path to native path style 2024-09-10 09:10:32 +00:00
TSR Berry
a18bb5f31a Improve searching for requirements 2024-09-10 09:10:31 +00:00
TSR Berry
ce2f577f1b Fix issues with semicolon-separated lists 2024-09-10 09:10:31 +00:00
Gabriel A
d5aff40a2e android - Fix rebase 2024-09-10 09:10:31 +00:00
TSR Berry
fa0a9ca889 Use prebuilt OpenSSL libraries if available 2024-09-10 09:10:31 +00:00
TSR Berry
5ef97ca444 Compile OpenSSL libraries during build 2024-09-10 09:10:30 +00:00
TSR Berry
407c67a512 iOS : fix xcode paths 2024-09-10 09:10:30 +00:00
Emmanuel Hansen
06a7c0217f fix audio rebase
remove redundant sdk performance session usage

remove debug code and formatting
2024-09-10 09:10:30 +00:00
Emmanuel Hansen
d40dc00769 android - add performance monitor
android - update dependencies

android - set isStarted check early

android - add performance stats

android - close file handles in performance monitor
2024-09-10 09:10:30 +00:00
Emmanuel Hansen
896851e909 android - fix rebase 2024-09-10 09:10:29 +00:00
Isaac Marovitz
5fa2f30ac6 android - Expose InstallFirmware 2024-09-10 09:10:29 +00:00
Isaac Marovitz
e4a3187aac android - Expose GetInstalledFirmwareVersion 2024-09-10 09:10:29 +00:00
Isaac Marovitz
d2d8e3f208 iOS - Disable StdErrAdapter
Enabling fills the logs with uneeded spam
2024-09-10 09:10:28 +00:00
Isaac Marovitz
31af1e194f iOS - Set Silk.NET SearchPathContainer 2024-09-10 09:10:28 +00:00
Isaac Marovitz
6884a14b32 iOS - Platform Checks
Co-authored-by: riperiperi <rhy3756547@hotmail.com>
2024-09-10 09:10:27 +00:00
Isaac Marovitz
d589a18c08 iOS - Linker Fixes 2024-09-10 09:10:26 +00:00
TSR Berry
9a40df6cf9 cmake: Use FetchContent to include adrenotools 2024-09-10 09:10:26 +00:00
Emmanuel Hansen
28df6f1c4e android - add grid list option
android - adjust grid view design, remove bottom app bar

android - reload list if game folder changed, fix game updates scanning

android - set nativeaot instruction set support

android - bump version

android - bump version

android - add log export, providers to browse app data

android - add log settings

android - add button to open ryujinx app folder

android - allow sensor to change orientation during emulation

android - add support for nro

android - add motion support

android - implement firmware installation

android -  ensure controller respects users controller visibility settings at launch

android - fix settings app action buttons. fix dlc manager add button missing

android - add hack to fix orientation issue

android - fix stick showing as dpad

android - set controller event as handled

android - add option to swap button layouts to nintendo style

android - add basic software keyboard support

android - add option to disable motion

android - remote developer name from grid items

android - fix dpad input on generic android controllers

android - move title updates support to SAF

android - change game stats background color
2024-09-10 09:10:25 +00:00
Emmanuel Hansen
eac63c756e android - add uihandler 2024-09-10 09:10:25 +00:00
Emmanuel Hansen
4d7356efe0 rebase with upstream 2024-09-10 09:10:24 +00:00
Emmanuel Hansen
adda73f061 android - drop game activity, replace with compose view
android - add string map

android - fixes a few crashes in the user and home views

android - bumb version

android - bumb version, rebase over master

android - remove oboe
2024-09-10 09:10:23 +00:00
Emmanuel Hansen
a583d6bf46 android - load firmware version at launch
clean main ui, add option to import app data

android - add basic user management

android - fix app menu

android - fix game update icon, add app icon

android - add crash handler

android - fix crash when no user is available at launch

android - improve game update selection

android - make settings view scrollable, bump version
2024-09-10 09:10:23 +00:00
Emmanuel Hansen
898f88350c android - sanitize stick input
use file descriptors to load game list

improve async loading. add game load progress
2024-09-10 09:10:22 +00:00
Gabriel A
9eaa683ae4 Add spin lock to prevent waiting for fences on multiple threads at once on Adreno
Support ballot operations with divergent control flow on Adreno

Extend Adreno binding workaround to buffer textures
2024-09-10 09:09:25 +00:00
Emmanuel Hansen
7cfd5dc902 don't request storage usage for surface on bionic 2024-09-10 09:09:25 +00:00
Emmanuel Hansen
dedecebc6b create a copy of updates when added
fix rebase
2024-09-10 09:09:24 +00:00
Emmanuel Hansen
aa34233634 android - some optimizations. apply current transform to native window instead of defaulting to Identity 2024-09-10 09:09:23 +00:00
Emmanuel Hansen
eb8cdde8dd switch to using stream base game loading
add game searching

add bottom popup ingame

move game view to new activity

fix manifest error

reduced virtual controller deadzone

enable hardware accel for activity
2024-09-10 09:09:23 +00:00
TSR Berry
8ac307166a Update Android gradle plugins
Fix gradle build issues when multiple configurations are present
2024-09-10 09:09:23 +00:00
Emmanuel Hansen
b28f9a6331 android - add adrenotools module
test

restore driver selection

fix adreno hooking

fix adreno hooking

fix unzip code

refactor virtual pad composition

separate game loading from surface creation

add closing emulation(starting a new one is still broken), disabled audio

safely close audio on game exit

add dlc manager

fix AsFlags rename conflict
2024-09-10 09:09:22 +00:00
TSR Berry
f28f2dfeeb Replace Helpers.getPath() with file.getAbsolutePath() 2024-09-10 09:09:21 +00:00
TSR Berry
8b7beb6f22 Cleanup gitignore and project file structure
Switch to Java 17 LTS

Keep libryujinx symbols

Add gradle module for libryujinx

Update dependencies

Raise minSdk to 30 to fix linter errors

Make stripSymbols a gradle property

Preserve other jni libraries

Fix file trees

Fix AndroidManifest.xml warnings

Suppress Google Play permission warning

Add preBuild dependency on libryujinx for app

Add toolchain path to all operating systems correctly

Make dotnet executable path configurable

Fix OS detection

Only build LibRyujinx if source or project files changed

Add toolchain path to output

Fix PATH variable on Windows

I spent ~7 hours debugging this.
I searched for a bug in the Exec task and found nothing.
I tried different ways to invoke the dotnet command
to make sure PATH is always set before.
I also modified Microsoft.NETCore.Native.Unix.targets to echo PATH via Exec and via Text.
But in the end I was confused about seeing two PATH variables
when checking the dotnet.exe subprocess with ProcessHacker.
This made me try setting the Path variable instead of PATH
and to my surprise this just worked.
Turns out Windows environment variables are case-sensitive and
Windows uses Path instead of PATH like Unix.

God, I love Microsoft Windows. :)

Cleanup LibRyujinx and add more verbose logging

Cleanup RyujinxAndroid
2024-09-10 09:09:19 +00:00
Emmanuel Hansen
fcb511bbca android - add physical controller support
add performance hints

expand full screen to behind cutouts

fix touch, add toggle for virtual gamepad

remove safe area margins
2024-09-10 09:09:17 +00:00
Gabriel A
c57f6a7fe3 Remove address space mirror and tweak address space layout when host has small adress space 2024-09-10 09:08:03 +00:00
Gabriel A
bbe460cecd Use alternate stack for the segfault handler too 2024-09-10 09:08:02 +00:00
Gabriel A
0ffb074d9a Work around Adreno compute dispatch crash when changing grpahics state with a compute pipeline bound 2024-09-10 09:08:02 +00:00
Gabriel A
51aec9a2ed Allocate NCE patch region dynamically to avoid not having enough space 2024-09-10 09:08:01 +00:00
Gabriel A
282ba31810 Rewrite NceAsmTable using dynamic generation instead to be more robust, fix bugs 2024-09-10 09:08:00 +00:00
Gabriel A
498bb95cf1 Fix incorrect AslrRegionStart when using NCE
(cherry picked from commit 0f34b8e78e2cfca99f6a25553a1fedebbfd3adae)
2024-09-10 09:05:08 +00:00
Gabriel A
88c45e1e86 Add work around for Adreno batched texture + sampler descriptor updates bug
(cherry picked from commit 93abc5ac47fedc413a3437c65de9fecf0555afa6)
2024-09-10 09:05:02 +00:00
Emmanuel Hansen
32064ccba5 move android kotlin project over
(cherry picked from commit de59e13fc267e3e9b2f9f08a88aa6dee21b0e7f3)
2024-09-10 09:04:55 +00:00
Emmanuel Hansen
115f366609 add android bionic nce support
(cherry picked from commit d4c3cd03167922a7255e34892a4954f53c7b8aa2)
2024-09-10 09:04:48 +00:00
gdk
b5a82ac607 Add back IsApplication flag
(cherry picked from commit 64e302e6b14806fb44be17a216ef621d0b85cecd)
2024-09-10 09:04:41 +00:00
gdk
7a2869ab6e Add NCE code
(cherry picked from commit 555f9a2db23751da924be7ed5bb63874a976237e)
2024-09-10 09:02:25 +00:00
gdk
1dd2d68be8 Minor refactoring of KPageTableBase to make custom address space layouts easier to implement
(cherry picked from commit a29acdb593f4426d5a05cf1659ace11361378638)
2024-09-10 09:01:06 +00:00
Emmanuel Hansen
8af1066a55 android - add file logs
android - add game stats helper

(cherry picked from commit 211a8f9defaa73b4dad8e99a67c5d11b480f4a1b)
2024-09-10 09:00:59 +00:00
Emmanuel Hansen
ae5fd72e5c disable network change notification on bionic
(cherry picked from commit 183183d0742f961e9799a6b0f4aa415cd666fec6)
2024-09-10 09:00:52 +00:00
Emmanuel Hansen
839d192635 add bionic nativeaot support
(cherry picked from commit 0aed709520c49d51c5c894b72ee3837680cc1d50)
2024-09-10 09:00:46 +00:00
Emmanuel Hansen
b8125859ed add helper for checking bionic
(cherry picked from commit 5e67c3f56949244d72705c9436950ad9896e302b)
2024-09-10 09:00:39 +00:00
Mary
bab815ab6f armeilleure: Do not call GCSettings.LargeObjectHeapCompactionMode on Android
Mono only support Default as argument and will throw otherwise.

(cherry picked from commit 872a33fd39a6fe9e4be19d612d348d1bc46bd0a7)
2024-09-10 09:00:19 +00:00
Mary
909558859d armeilleure: Add Android to GetOSPlatform for PTC
(cherry picked from commit 6b6e62bf9624badbfda356f083d0e7f503c8208e)
2024-09-10 09:00:12 +00:00
Mary
3042cabb02 armeilleure: Add Android signal handler
(cherry picked from commit 12d7315b54880a4b412b1e6aeb25ef58076c8e02)
2024-09-10 09:00:03 +00:00
Mary
3a7a9e4456 armeilleure: Add support for Android in HardwareCapabilities
(cherry picked from commit ef932749b0a49d0cf59bf5a5cc5315c2f2870910)
2024-09-10 08:58:54 +00:00
Mary
463411546a memory: Add Android support
(cherry picked from commit c800a90eb3eaa99b8b3cfa70661539a10a36af40)
2024-09-10 08:58:43 +00:00
Emmanuel Hansen
0a54501974 libryujinx - fix branch
fix libryujinx content manager rebase
disable trim warning suppression
libryujinx - add graphics logging
libryujinx - use pointers for game info struct
libryujinx - update rd
LibRyujinx: Fix path to Ryujinx.UI.Common project
libryujinx - cleanup
Start GameInfoNative
Expand InitializeDeviceNative Signature
libryujinx - Expose InstallFirmware
libryujinx - Expose GetInstalledFirmwareVersion
Don’t crash if no firmware is installed
libryujinx - Expose Accelerometer & Gyro Functions
libryujinx - add stream support
libryujinx - add motion controls
libryujinx - add openal reference, mii applet launch api
rebase fix
libryujinx - load firmware version at launch, add user manager api
libryujinx - fix whitespace and remove unused usings
libryuijinx - fix rd.xml
libryujinx - some optimizations. apply current transform to native window instead of defaulting to Identity
libryujinx - update
libryujinx - Add more debug information when loading game files
libryujinx - call swapbuffer callback
libryujinx - update input
add file logs
add game stats helper
libryujinx-update
add basic touch and button input interface
remove armeilleire reference in rd file
libryujinx - disable shader cache
remove redundant project reference
add nativaot libryujinx project

(cherry picked from commit a3cc23b41858bdfc17d8c9631a31c33f8d1b34cc)
2024-09-10 08:57:35 +00:00
Emmanuel Hansen
0394a39342 replace opentk deprecated size property
(cherry picked from commit e65dc4521353b5cc275ece53fa6367d471fdecba)
2024-09-10 08:49:39 +00:00
Emmanuel Hansen
c90b78499b move unmanaged methods to separate file and expose more api
(cherry picked from commit 4a6b7ffbe55da614ca1a8b8dd693f60e17e99cb0)
2024-09-10 08:49:32 +00:00
gdk
235a90aed8 Make GetFunctionPointerForDelegate as explicit as possible
(cherry picked from commit 49608b7afee445ff20215c029e0515cfc495ba79)
2024-09-10 08:49:08 +00:00
Emmanuel Hansen
0dbca88e08 libryujinx - fix branch
fix libryujinx content manager rebase
disable trim warning suppression
libryujinx - add graphics logging
libryujinx - use pointers for game info struct
libryujinx - update rd
LibRyujinx: Fix path to Ryujinx.UI.Common project
libryujinx - cleanup
Start GameInfoNative
Expand InitializeDeviceNative Signature
libryujinx - Expose InstallFirmware
libryujinx - Expose GetInstalledFirmwareVersion
Don’t crash if no firmware is installed
libryujinx - Expose Accelerometer & Gyro Functions
libryujinx - add stream support
libryujinx - add motion controls
libryujinx - add openal reference, mii applet launch api
rebase fix
libryujinx - load firmware version at launch, add user manager api
libryujinx - fix whitespace and remove unused usings
libryuijinx - fix rd.xml
libryujinx - some optimizations. apply current transform to native window instead of defaulting to Identity
libryujinx - update
libryujinx - Add more debug information when loading game files
libryujinx - call swapbuffer callback
libryujinx - update input
add file logs
add game stats helper
libryujinx-update
add basic touch and button input interface
remove armeilleire reference in rd file
libryujinx - disable shader cache
remove redundant project reference
add nativaot libryujinx project

(cherry picked from commit 6288d793c6d9322c7ea188d689f524a9b73eaa9c)
2024-09-10 08:48:32 +00:00
Emmanuel Hansen
45c4f56c1d fix update searching
(cherry picked from commit c078a561ef781115ee5c7087e071ec141ee9f278)
2024-09-10 08:46:57 +00:00
Emmanuel Hansen
8226f77ddd fix content manager rebase
(cherry picked from commit 086fa8f79be35bc3bcce88764dd56e5ff185d75a)
2024-09-10 08:46:47 +00:00
Emmanuel Hansen
7de794cf81 extend stream loading support
(cherry picked from commit cff4a63e5a6deb33734f296b550723f0c6a9a693)
2024-09-10 08:46:24 +00:00
Emmanuel Hansen
6919b123b7 add stream based loaders
(cherry picked from commit e86dec9112b5e1b58a8241aadcf37bf2e3acd14c)
2024-09-10 08:45:21 +00:00
riperiperi
ca59c3f499
Vulkan: Feedback loop detection and barriers (#7226)
* Vulkan: Feedback loop improvements

This PR allows the Vulkan backend to detect attachment feedback loops. These are currently used in the following ways:

- Partial use of VK_EXT_attachment_feedback_loop_layout
  - All renderable textures have AttachmentFeedbackLoopBitExt
  - Compile pipelines with Color/DepthStencil feedback loop flags when present
- Support using FragmentBarrier for feedback loops (fixes regressions from https://github.com/Ryujinx/Ryujinx/pull/7012 )

TODO:
- AMD GPUs may need layout transitions for it to properly allow textures to be used in feedback loops.
- Use dynamic state for feedback loops. The background pipeline will always miss since feedback loop state isn't known on the GPU project.
- How is the barrier dependency flag used? (DXVK just ignores it, there's no vulkan validation...)
- Improve subpass dependencies to fix validation errors

* Mark field readonly

* Add feedback loop dynamic state

* fix: add MoltenVK resolver workaround

fix: add MoltenVK resolver workaround

* Formatting

* Fix more complaints

* RADV dcc workaround

* Use dynamic state properly, cleanup.

* Use aspects flags in more places
2024-09-01 21:28:16 -03:00
gdkchan
fdd7ee791c
Fix incorrect depth texture 3D flag (#7262) 2024-09-01 17:58:01 -03:00
riperiperi
398fa1c238
Vulkan: Update Silk.NET to 2.21 (#7266)
* Update Silk.NET version

* fix: add MoltenVK resolver workaround

fix: add MoltenVK resolver workaround

* Cleanup

* Readonly ref warnings

* Remove driver id todo
2024-09-01 17:33:11 -03:00
Emmanuel Hansen
2c5c0392f9
Make HLE project AOT friendly (#7085)
* add hle service generator

remove usage of reflection in device state

* remove rd.xml generation

* make applet manager reflection free

* fix typos

* fix encoding

* fix style report

* remove rogue generator reference

* remove double assignment
2024-08-31 11:39:26 -03:00
Emmanuel Hansen
e0acde04bb
Replace ImageSharp with SkiaSharp everywhere (#7030)
* replace ImageSharp with SkiaSharp for inline keyboard applet rendering

* fix avalonia inline keyboard input

* remove image sharp from gtk3 project

* add skiasharp linux assets

* fix whitespace

* fix format

* fix ico image offset when saving shortcut to windows
2024-08-31 11:32:53 -03:00
David McFarland
3c61d560c3
Fix deadlock in background translation thread shutdown (#7239)
TryDequeue checks for _disposed before taking the lock.  If another
thread calls Dispose before it takes the lock, it won't get woken up by
the PulseAll call, and will deadlock in Monitor.Wait.

Double-checking _disposed with the lock taken should avoid this.
2024-08-27 19:10:24 +02:00
dependabot[bot]
b45a81458a
nuget: bump DynamicData from 9.0.1 to 9.0.4 (#7220)
Bumps [DynamicData](https://github.com/reactiveui/DynamicData) from 9.0.1 to 9.0.4.
- [Release notes](https://github.com/reactiveui/DynamicData/releases)
- [Changelog](https://github.com/reactivemarbles/DynamicData/blob/main/ReleaseNotes.md)
- [Commits](https://github.com/reactiveui/DynamicData/compare/9.0.1...9.0.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-21 12:30:43 +02:00
gdkchan
460f9faf4e
Fix NRE when using buffer image array (#7159) 2024-08-21 00:49:17 +01:00
Toni Förster
552c15739c
nuget: bump ImageSharp from 2.1.8 to 2.1.9 (#7160)
While building I got some warnings, so I updated the dependency.

`warning NU1903: Package 'SixLabors.ImageSharp' 2.1.8 has a known high severity vulnerability, https://github.com/advisories/GHSA-63p8-c4ww-9cg7`
2024-08-20 22:26:32 +01:00
Tsubasa0504
0137c9e635
nim:eca : Stub CreateServerInterface2 (#7128)
* Add files via upload

* Add files via upload

* Update src/Ryujinx.HLE/HOS/Services/Nim/IShopServiceAccessServerInterface.cs

---------

Co-authored-by: Ac_K <Acoustik666@gmail.com>
2024-08-17 09:57:22 +01:00
Logan Stromberg
23fa5f4c9c
Fix arbitrary game ordering when sorting by Favorites (#7170)
* Fix arbitrary sorting by "Favorite" in the UI by making it the same as sorting alphabetically while giving favorites priority.

* Use a more engineered solution rather than string hacks.

* Address code style warnings. Add null checking. Make title name comparison case insensitive.

* one more style fix

---------

Co-authored-by: Logan Stromberg <lostromb@microsoft.com>
2024-08-13 15:23:11 +02:00
gdkchan
4f75e26ec7
Clamp amount of mipmap levels to max allowed for all backends (#7197)
* Clamp amount of mipmap levels to max allowed for all backends

* XML docs

* Remove using
2024-08-12 17:45:25 -03:00
gdkchan
8d8983049e
Implement UQADD16, UQADD8, UQSUB16, UQSUB8, VQRDMULH, VSLI and VSWP Arm32 instructions (#7174) 2024-08-08 17:07:24 -03:00
jhorv
7969fb6bba
Replace and remove obsolete ByteMemoryPool type (#7155)
* refactor: replace usage of ByteMemoryPool with MemoryOwner<byte>

* refactor: delete unused ByteMemoryPool and ByteMemoryPool.ByteMemoryPoolBuffer types

* refactor: change IMemoryOwner<byte> return types to MemoryOwner<byte>

* fix(perf): get span via `MemoryOwner<T>.Span` directly instead of `MemoryOwner<T>.Memory.Span`

* fix(perf): get span via MemoryOwner<T>.Span directly instead of `MemoryOwner<T>.Memory.Span`

* fix(perf): get span via MemoryOwner<T>.Span directly instead of `MemoryOwner<T>.Memory.Span`
2024-08-05 21:09:08 -03:00
gdkchan
4a4b11871e
Fix same textures with unmapped start being considered different (#7141)
* Fix same textures with unmapped start being considered different

* Consolidate IsInvalid check

* InvalidAddress const

* Fix typo

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

---------

Co-authored-by: riperiperi <rhy3756547@hotmail.com>
2024-08-05 11:00:41 -03:00
Julien Lebosquain
e85ee673b1
Fix LocaleExtension SetRawSource usages + language perf improvement (#7121)
* Avoid Avalonia CompiledBindingPathBuilder.SetRawSource

* Improve UI language change performance
2024-08-04 19:04:12 +01:00
Isaac Marovitz
42f22fe5d7
Infra: Update Microsoft.IdentityModel.JsonWebTokens (#7070)
* Update Microsoft.IdentityModel.JsonWebTokens

* Update
2024-08-04 18:56:27 +01:00
TSRBerry
263eb97f79
Avoid race conditions while launching games directly from the command line (#7116)
* optimization: Load application metadata only for applications with IDs

* Load applications when necessary

This prevents loading applications when launching an application
directly from the command line (or a shortcut).
Instead, applications will be loaded after the emulation was stopped by the user.

* Show the title in the configured language when launching an application

* Rename DesiredTitleLanguage to DesiredLanguage
2024-08-03 22:31:34 +01:00
dependabot[bot]
3004902257
nuget: bump DynamicData from 8.4.1 to 9.0.1 (#7040)
Bumps [DynamicData](https://github.com/reactiveui/DynamicData) from 8.4.1 to 9.0.1.
- [Release notes](https://github.com/reactiveui/DynamicData/releases)
- [Changelog](https://github.com/reactivemarbles/DynamicData/blob/main/ReleaseNotes.md)
- [Commits](https://github.com/reactiveui/DynamicData/compare/8.4.1...9.0.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-03 22:34:41 +02:00
jhorv
59ddb26628
replace ByteMemoryPool usage in Ryujinx.Graphics (#7129)
* chore: replace `ByteMemoryPool` usage with `MemoryOwner<byte>`

* refactor: `PixelConverter.ConvertR4G4ToR4G4B4A4()` - rename old `outputSpan` to `outputSpanUInt16`, reuse same output `Span<byte>` as newly-freed name `outputSpan`

* eliminate temporary buffer allocations

* chore, perf: use MemoryOwner<byte> instead of IMemoryOwner<byte>
2024-08-03 19:50:53 +01:00
TSRBerry
83fda10f6e
Fix FileNotFoundException in TryGetApplicationsFromFile() and improve loading applications (#7145)
* Don't load files from hidden subdirectories

* Catch FileNotFoundException in TryGetApplicationsFromFile()

* Skip non-existent files and bad symlinks when loading applications
2024-08-03 19:46:59 +02:00
gdkchan
d97e995e59
Fix off-by-one on audio renderer PerformanceManager.GetNextEntry (#7139) 2024-07-31 22:22:11 -03:00
gdkchan
56b2f84702
Fix shader RegisterUsage pass only taking first operation dest into account (#7131)
* Fix shader RegisterUsage pass only taking first operation dest into account

* Shader cache version bump
2024-07-30 21:57:55 -03:00
riperiperi
698e36bbd2
Vulkan: Force topology to PatchList for Tessellation (#7102)
Vulkan spec states that input topology should always be PatchList when a tessellation pipeline is present. The AMD GPU on windows crashes so hard it BSODs the machine if this isn't the case, so it's forced here just in case.

I'm not sure what providing a different topology here would even do, as you'd think it would always be a patch list input.
2024-07-30 21:48:30 -03:00
Isaac Marovitz
6ce49a2dc7
Ava UI: Handle updates containing non numeric characters (#7043)
* Handle updates containing non numeric characters

Smh

Dont be stupid

* Use Berry’s method

* Thanks gdk

* Remove using
2024-07-25 16:44:33 -03:00
riperiperi
ccd330ba0f
Vulkan: Add missing barriers for texture to buffer copy (#7092)
This barrier has always been missing, but it only became apparent when #7012 merged.

I also added some barriers in case the target buffer used here is used by other commands, though right now it isn't.

Fixes a regression where water would turn white on AMD GPUs with the proprietary driver. May fix other issues on this driver.
2024-07-25 16:34:30 -03:00
gdkchan
95d252b7b8
Update kernel GetInfo SVC for firmware 18.0.0 (#7075)
* Implement kernel GetInfo AliasRegionExtraSize

* Implement IsSvcPermitted

* Remove warning supressions that are no longer needed

* Remove useless cast
2024-07-22 12:46:04 -03:00
TSRBerry
add681144b
Fix checking for the wrong metadata files for applications launched with a different program index (#7055)
* Fix checking for the wrong update metadata file

* Apply the same fix for dlc.json

* Use the base application ids for updates and DLCs in the GUI too

This shouldn't actually change anything, since the program index part of the application id
should always be 0 for all applications currently seen by the GUI.

This was just done for completeness.
2024-07-21 14:42:23 -03:00
TSRBerry
c6dc00815a
Make sure TryGetApplicationsFromFile() doesn't throw exceptions anymore (#7046)
* Add docstrings for exceptions to methods near TryGetApplicationsFromFile()

* Make sure TryGetApplicationsFromFile() doesn't throw exceptions anymore

* Add missing filePath to ApplicationData when loading applications from ExeFS

* Fix typo

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

---------

Co-authored-by: riperiperi <rhy3756547@hotmail.com>
2024-07-20 16:35:43 -03:00
gdkchan
99f04ac1a6
Fix Skia saving screenshot with transparent background and incorrect origin (#7073)
* Fix Skia saving screenshot with transparent background and incorrect origin

* Remove code that is no longer necessary
2024-07-20 16:27:40 -03:00
gdkchan
ce09450743
Unlink server sessions from multi-wait when service stops processing requests (#7072) 2024-07-20 16:17:40 -03:00
Isaac Marovitz
2cb80f37d4
Ava UI: Auto select newly added updates & DLC (#7026)
* Fix DLC not being selected

* FIx conflicts

* Apply suggestions from code review

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

---------

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>
2024-07-19 19:00:15 +02:00
gdkchan
827069e784
Add missing Buffer attribute on NGC Check method (#7051) 2024-07-18 15:11:00 -03:00
riperiperi
1a919e99b2
Vulkan: Defer guest barriers, and improve image barrier timings (#7012)
* More guarantees for buffer correct placement, defer guest requested buffers

* Split RP on indirect barrier rn

* Better handling for feedback loops.

* Qualcomm barriers suck too

* Fix condition

* Remove unused field

* Allow render pass barriers on turnip for now
2024-07-17 20:21:32 -03:00
TSRBerry
f77bebac80
Include content data foreach-loop in try-catch (#7036) 2024-07-17 19:02:20 -03:00
TSRBerry
6fbf279fac
Add support for multi game XCIs (second try) (#6515)
* Add default values to ApplicationData directly

* Refactor application loading

It should now be possible to load multi game XCIs.
Included updates won't be detected for now.
Opening a game from the command line currently only opens the first one.

* Only include program NCAs where at least one tuple item is not null

* Get application data by title id and add programIndex check back

* Refactor application loading again and remove duplicate code

* Actually use patch ncas for updates

* Fix number of applications found with multi game xcis

* Don't load bundled updates from multi game xcis

* Change ApplicationData.TitleId type to ulong & Add TitleIdString property

* Use cnmt files and ContentCollection to load programs

* Ava: Add updates and DLCs from gamecarts

* Get the cnmt file from its NCA

* Ava: Identify bundled updates in updater window

* Fix the (hopefully) last few bugs

* Add idOffset parameter to GetNcaByType

* Handle missing file for dlc.json

* Ava: Shorten error message for invalid files

* Gtk: Add additional string for bundled updates in TitleUpdateWindow

* Hopefully fix DLC issues

* Apply formatting

* Finally fix DLC issues

* Adjust property names and fileSize field

* Read the correct update file

* Fix wrong casing for application id strings

* Rename TitleId to ApplicationId

* Address review comments

* Apply suggestions from code review

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

* Gracefully fail when loading pfs for update and dlc window

* Fix applications with multiple programs

* Fix DLCWindow crash on GTK

* Fix some GUI issues

* Remove IsXci again

* Don't add duplicates to update/dlc windows

* Avoid double lookup

* Preserve DLC enabled state for bundled DLCs

* Fix DLCWindow not opening using GTK

* Fix missing information when loading applications from file

* Address review feedback

Rename ContentCollection to ContentMetaData
Fix casing issues in log messages
Use null as the default value for updatePath

* Fix re-adding bundled DLCs every time

* Fix bundled DLCs disappearing

* Abstract common code to open application pfs

* Remove unused imports

* Fix file exists check when loading DLCs

* Load bundled DLCs only using dlc.json

* Load AoC items correctly

* Add all DLCs from a PFS

* Add argument to launch a specific application id

* Use application-id argument for shortcuts if necessary

* Return the application id from the control NCA if possible

* GetApplicationInformation: Don't overwrite application ids

Move SaveDataOwnerId check to the top, since it seems to be more reliable.

* Get application ids from CNMT again

This commit reverts some parts of 61615b8f0d6f90ae86778958ddc38eaf6dc280ab.
Since the issue wasn't actually related to the application id in CMNTs, we can remove the wrong assumptions.

* Revert erroneous axaml change from adca8900

* Rename title to application

* Wrap nsp/pfs0 case with curly braces

* Check if _applicationData.ControlHolder.ByteSpan is zeros only once

* Catch exceptions while loading applications from nsps

---------

Co-authored-by: gdkchan <gab.dark.100@gmail.com>
2024-07-16 18:17:32 -03:00
Isaac Marovitz
344f4f52c1
Remove CommandBufferScoped Dependencies (#6958) 2024-07-16 17:01:06 -03:00
MutantAura
eb212aa91b
misc: Re-order and manually update DriverID to name. (#7027)
* Re-order and update DriverID -> Name.

* Fix whitespace
2024-07-15 19:27:59 -03:00
jhorv
a6dbb2ad2b
replace ByteMemoryPool usage in Ryujinx.HLE (#6953) 2024-07-15 19:21:53 -03:00
sunshineinabox
595e514f18
Use SkiaSharp for Avalonia in place of ImageSharp (#6269)
* Rebased

Transformation all at once

Use SkiaSharp instead of ImageSharp

* Apply suggestions from code review

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

* Change back unintentionally changed comment

---------

Co-authored-by: Ac_K <Acoustik666@gmail.com>
Co-authored-by: Emmanuel Hansen <emmausssss@gmail.com>
2024-07-14 08:16:14 +00:00
gdkchan
07435ad844
Use draw clear on Adreno, instead of vkCmdClearAttachments (#7013)
* Use draw clear on Adreno, instead of vkCmdClearAttachments

* Fix GTX TITAN detection
2024-07-10 17:52:45 -03:00
gdkchan
1668ba913f
Force dynamic state update after rasterizer discard disable (#7007) 2024-07-09 23:31:01 -03:00
gdkchan
a830eb666b
Disallow concurrent fence waits on Adreno (#7001)
* Disallow concurrent fence waits on Adreno

* Ensure locks are released if exceptions are thrown
2024-07-07 19:33:28 -03:00
gdkchan
cfc75d7e78
Disable descriptor set template updates for buffer textures on Adreno (#7002)
* Do not use template updates for buffer textures and buffer images

* No need to do it for images

* Simply buffer texture existence check

* Pipeline is now unused on DescriptorSetUpdater
2024-07-07 19:19:55 -03:00
gdkchan
c525d7d9a9
Force Vulkan swapchain re-creation when window size changes (#7003) 2024-07-07 19:02:11 -03:00
sunshineinabox
1a0a351a15
Resolve some Vulkan validation errors (#6915)
* Fix some validation errors

* Whitespace correction

* Resolve some runtime validation errors.

* Whitespace

* Properly fix usage realted validation error by setting Extended Usage image creation flag.

* Only if supported

* Remove checking extension for features that are core functionality of Vulkan 1.2
2024-06-26 09:21:44 -03:00
TSRBerry
bd3335c143
Make sure the string is long enough before performing basic trim (#6982) 2024-06-26 11:27:23 +02:00
dependabot[bot]
a94445b23e
nuget: bump Microsoft.IdentityModel.JsonWebTokens from 7.6.0 to 7.6.2 (#6965)
Bumps [Microsoft.IdentityModel.JsonWebTokens](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet) from 7.6.0 to 7.6.2.
- [Release notes](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/releases)
- [Changelog](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/7.6.2/CHANGELOG.md)
- [Commits](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/compare/7.6.0...7.6.2)

---
updated-dependencies:
- dependency-name: Microsoft.IdentityModel.JsonWebTokens
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Ac_K <Acoustik666@gmail.com>
2024-06-26 10:45:51 +02:00
Rafa
0c3421973c
SetProcessMemoryPermission address and size are always 64-bit (#6977) 2024-06-25 09:40:53 +02:00
gdkchan
0afa8f2c14
JIT: Coalesce copies on LSRA with simple register preferencing (#6950)
* JIT: Coalesce copies on LSRA with simple register preferencing

* PPTC version bump
2024-06-19 09:39:29 -03:00
gdkchan
d25a084858
JIT: Ensure entry block has no predecessors on RegisterUsage pass (#6951) 2024-06-19 09:25:47 -03:00
jhorv
311ca3c3f1
fix: for pooled memory used for reference types, clear it on return to the pool so that it doesn't prevent GC of the instances it contained (#6937) 2024-06-16 17:47:47 -03:00
gdkchan
3193ef1083
Extend bindless elimination to catch a few more specific cases (#6921)
* Catch more cases on bindless elimination

* Match blocks with the same comparison condition

* Shader cache version bump
2024-06-16 14:46:27 -03:00
jhorv
5a878ae9af
replace ByteMemoryPool use with MemoryOwner<byte> and SpanOwner<byte> (#6911) 2024-06-15 23:00:13 +02:00
dependabot[bot]
1828bc949e
nuget: bump Microsoft.IO.RecyclableMemoryStream from 3.0.0 to 3.0.1 (#6936)
Bumps [Microsoft.IO.RecyclableMemoryStream](https://github.com/Microsoft/Microsoft.IO.RecyclableMemoryStream) from 3.0.0 to 3.0.1.
- [Release notes](https://github.com/Microsoft/Microsoft.IO.RecyclableMemoryStream/releases)
- [Changelog](https://github.com/microsoft/Microsoft.IO.RecyclableMemoryStream/blob/master/CHANGES.md)
- [Commits](https://github.com/Microsoft/Microsoft.IO.RecyclableMemoryStream/compare/3.0.0...v3.0.1)

---
updated-dependencies:
- dependency-name: Microsoft.IO.RecyclableMemoryStream
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-15 22:51:50 +02:00
gdkchan
c0f2491eae
Vulkan separate descriptor set fixes (#6895)
* Ensure descriptor sets are only re-used when all command buffers using it have completed

* Fix some SPIR-V capabilities

* Set update after bind flag if we exceed limits

* Simpler fix for Intel

* Format whitespace

* Make struct readonly

* Add barriers for extra set arrays too
2024-06-02 22:40:28 -03:00
sunshineinabox
d7c6474729
GPU: Remove unused dynamic state and pipeline settings (#6796)
* Dynamic state for Depth Bounds should not be passed to PipelineDynamicStateCreateInfo as the command to set them is never called.

Do not pass pointer to viewport and scissor as those dynamic states should be supported on all devices.

Same as above for DepthBias values.

* Code Review Suggestion

* Pipeline derivation is not implemented and is not suggested.

* Depth Bounds are not used.
2024-06-02 22:32:10 -03:00
jhorv
1ecc8fbc3b
New pooled memory types (#6821)
* feat: add new types MemoryOwner and SpanOwner

* use SpanOwner instead of new array allocation

* change for loop condition to `fences.Length` instead of `count` to elide Span boundary checks on `fences`
2024-06-02 22:24:14 -03:00
Marco Carvalho
888402ecaf
Avoid inexact read with 'Stream.Read' (#6847) 2024-06-02 22:16:48 +02:00
dependabot[bot]
971d24aef0
nuget: bump Microsoft.IdentityModel.JsonWebTokens from 7.5.2 to 7.6.0 (#6893)
Bumps [Microsoft.IdentityModel.JsonWebTokens](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet) from 7.5.2 to 7.6.0.
- [Release notes](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/releases)
- [Changelog](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/compare/7.5.2...7.6.0)

---
updated-dependencies:
- dependency-name: Microsoft.IdentityModel.JsonWebTokens
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-02 22:10:47 +02:00
gdkchan
c41fddd25e
Vulkan: Extend full bindless to cover cases with phi nodes (#6853)
* Key textures using set and binding (rather than just binding)

* Extend full bindless to cover cases with phi nodes

* Log error on bindless access failure

* Shader cache version bump

* Remove constant buffer match to reduce the chances of full bindless triggering

* Re-enable it for constant buffers, paper mario does actually need it

* Format whitespace
2024-05-26 15:20:10 -03:00
MutantAura
2ebe929fa5
misc: Change disk shader cache compression algorithm to Brotli (RFC 7932) (#6841)
* Prefer `Brotli` compression for disk shader cache.

* Final default case for decompression switch.

* Prefer fastest compression.
2024-05-26 20:06:41 +02:00
gdkchan
53d096e392
Allow texture arrays to use separate descriptor sets on Vulkan (#6870)
* Report base and extra sets from the backend

* Pass texture set index everywhere

* Key textures using set and binding (rather than just binding)

* Start using extra sets for array textures

* Shader cache version bump

* Separate new commands, some PR feedback

* Introduce new manual descriptor set reservation method that prevents it from being used by something else while owned by an array

* Move bind extra sets logic to new method

* Should only use separate array is MaximumExtraSets is not zero

* Format whitespace
2024-05-26 13:30:19 -03:00
dependabot[bot]
4cc00bb4b1
nuget: bump Microsoft.IdentityModel.JsonWebTokens from 7.5.1 to 7.5.2 (#6809)
Bumps [Microsoft.IdentityModel.JsonWebTokens](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet) from 7.5.1 to 7.5.2.
- [Release notes](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/releases)
- [Changelog](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/compare/7.5.1...7.5.2)

---
updated-dependencies:
- dependency-name: Microsoft.IdentityModel.JsonWebTokens
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-25 05:35:49 +02:00
Piplup
c98b7fc702
Workaround bug on logic op with float framebuffer (#6858)
* intel workaround

built on top of the amd workaround

* forgot to update the note

* Logic Change

Enabled workaround for all vendors that aren't nvidia

* Applied Suggestions
2024-05-23 22:57:26 -03:00
gdkchan
e65effcb05
Workaround AMD bug on logic op with float framebuffer (#6852)
* Workaround AMD bug on logic op with float framebuffer

* Format whitespace

* Update comment
2024-05-23 01:05:32 -03:00
riperiperi
c1ed150949
Kernel: Wake cores from idle directly rather than through a host thread (#6837)
* Kernel: Wake cores from idle directly rather than through a host thread

Right now when a core enters an idle state, leaving that idle state requires us to first signal the core's idle thread, which then signals the correct thread that we want to run on the core. This means that in a lot of cases, we're paying double for a thread to be woken from an idle state.

This PR moves this process to happen on the thread that is waking others out of idle, instead of an idle thread that needs to be woken first.

For compatibility the process has been kept as similar as possible - the process for IdleThreadLoop has been migrated to TryLeaveIdle, and is gated by a condition variable that lets it run only once at a time for each core. A core is only considered for wake from idle if idle is both active and has been signalled - the signal is consumed and the active state is cleared when the core leaves idle.

Dummy threads (just the idle thread at the moment) have been changed to have no host thread, as the work is now done by threads entering idle and signalling out of it.

This could put a bit of extra work on threads that would have triggered `_idleInterruptEvent` before, but I'd expect less work than signalling all those reset events and the OS overhead that follows. Worst case is that other threads performing these signals at the same time will have to wait for each other, but it's still going to be a very short amount of time.

Improvements are best seen in games with heavy (or very misguided) multithreading, such as Pokemon: Legends Arceus. Improvements are expected in Scarlet/Violet and TOTK, but are harder to measure.

Testing on Linux/MacOS still to be done, definitely need to test more games as this affects all of them (obviously) and any issues might be rare to encounter.

* Remove _idleThread entirely

* Use spinwait so we don't completely blast the CPU with cmpxchg

* Didn't I already do this

* Cleanup
2024-05-22 17:47:27 -03:00
Logan Stromberg
c634eb4054
Updating Concentus dependency to speed up Opus decoding (#6757)
* Implementing new features in the latest Concentus library - span-in, span-out Opus decoding (so we don't have to make temporary buffer copies), returning a more precise error code from the decoder, and automatically linking the native opus library with P/invoke if supported on the current system

* Remove stub log messages and commit package upgrade to 2.1.0

* use more correct disposal pattern

* Bump to Concentus 2.1.1

* Bump to Concentus 2.1.2

* Don't bother pulling in native opus binaries from Concentus package (using ExcludeAssets).

* Fix opus MS channel count. Explicitly disable native lib probe in OpusCodecFactory.

* Bump to package 2.2.0 which has split out the native libs, as suggested.

---------

Co-authored-by: Logan Stromberg <lostromb@microsoft.com>
2024-05-20 18:38:38 -03:00
riperiperi
eb1ce41b00
GPU: Migrate buffers on GPU project, pre-emptively flush device local mappings (#6794)
* GPU: Migrate buffers on GPU project, pre-emptively flush device local mappings

Essentially retreading #4540, but it's on the GPU project now instead of the backend. This allows us to have a lot more control + knowledge of where the buffer backing has been changed and allows us to pre-emptively flush pages to host memory for quicker readback. It will allow us to do other stuff in the future, but we'll get there when we get there.

Performance greatly improved in Hyrule Warriors: Age of Calamity. Performance notably improved in TOTK (average). Performance for BOTW restored to how it was before #4911, perhaps a bit better.

- Rewrites a bunch of buffer migration stuff. Might want to tighten up how dispose stuff works.
- Fixed an issue where the copy for texture pre-flush would happen _after_ the syncpoint.

TODO: remove a page from pre-flush if it isn't flushed after a certain number of copies.

* Add copy deactivation

* Fix dependent virtual buffers

* Remove logging

* Fix format issues (maybe)

* Vulkan: Remove backing swap

* Add explicit memory access types for most buffers

* Fix typo

* Add device local force expiry, change buffer inheritance behaviour

* General cleanup, OGL fix

* BufferPreFlush comments

* BufferBackingState comments

* Add an extra precaution to BufferMigration

This is very unlikely, but it's important to cover loose ends like this.

* Address some feedback

* Docs
2024-05-19 16:53:37 -03:00
TSRBerry
2f427deb67
Fix another NullReferenceException (#6826) 2024-05-17 20:11:30 -03:00
TSRBerry
8f51938e2b
Disable keyboard controller input while swkbd is open (foreground) (second attempt) (#6808)
* Block input updates while swkbd is open in foreground mode

* Flush internal driver state before unblocking input updates

* Rename Flush to Clear and remove unnecessary attribute

* Clear the driver state only if the GamepadDriver isn't null
2024-05-17 16:58:03 -03:00
gdkchan
4d84df9487
Update audio renderer to REV12: Add support for splitter biquad filter (#6813)
* Update audio renderer to REV12: Add support for splitter biquad filter

* Formatting

* Official names

* Update BiquadFilterState size + other fixes

* Update tests

* Update comment for version 2

* Size test for SplitterDestinationVersion2

* Should use Volume1 if no ramp
2024-05-17 16:46:43 -03:00
MutantAura
9ec8b2c01a
Change Deflate compression level to Fastest. (#6812) 2024-05-16 14:19:37 -03:00
SamusAranX
091230af22
Improves some log messages and fixes a typo (#6773)
* Improves some log messages and fixes a typo

* oops

* Update src/Ryujinx.UI.Common/Configuration/ConfigurationState.cs

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

* Log config file path

---------

Co-authored-by: Ac_K <Acoustik666@gmail.com>
Co-authored-by: TSR Berry <20988865+TSRBerry@users.noreply.github.com>
2024-05-15 18:10:47 +02:00
Isaac Marovitz
3aea194606
Add Enhancement label to Feature Requests (#6804) 2024-05-15 12:06:58 +02:00
gdkchan
cdccf89e10
Revert "Disable keyboard controller input while swkbd is open (foreground) (#…" (#6805)
This reverts commit a3dc295c5f867bddb56a38f3a848ceb61ff30d32.
2024-05-15 02:20:24 -03:00
Ac_K
2ca0b17339
New Crowdin updates (#6590)
* New translations en_us.json (Arabic)

* New translations en_us.json (Russian)

* New translations en_us.json (Chinese Traditional)

* New translations en_us.json (French)

* New translations en_us.json (Russian)

* New translations en_us.json (Spanish)

* New translations en_us.json (Arabic)

* New translations en_us.json (German)

* New translations en_us.json (Greek)

* New translations en_us.json (Hebrew)

* New translations en_us.json (Italian)

* New translations en_us.json (Japanese)

* New translations en_us.json (Korean)

* New translations en_us.json (Polish)

* New translations en_us.json (Russian)

* New translations en_us.json (Turkish)

* New translations en_us.json (Ukrainian)

* New translations en_us.json (Chinese Simplified)

* New translations en_us.json (Chinese Traditional)

* New translations en_us.json (Portuguese, Brazilian)

* New translations en_us.json (Thai)

* New translations en_us.json (French)

* New translations en_us.json (Arabic)

* New translations en_us.json (Italian)

* New translations en_us.json (Korean)

* New translations en_us.json (Russian)

* New translations en_us.json (Ukrainian)

* New translations en_us.json (Chinese Simplified)

* New translations en_us.json (Arabic)

* New translations en_us.json (Polish)

* New translations en_us.json (Turkish)

* New translations en_us.json (Arabic)

* New translations en_us.json (Chinese Traditional)

* New translations en_us.json (Russian)

* New translations en_us.json (French)

* New translations en_us.json (Thai)

* New translations en_us.json (Spanish)

* New translations en_us.json (Arabic)

* New translations en_us.json (German)

* New translations en_us.json (Greek)

* New translations en_us.json (Hebrew)

* New translations en_us.json (Italian)

* New translations en_us.json (Japanese)

* New translations en_us.json (Korean)

* New translations en_us.json (Polish)

* New translations en_us.json (Russian)

* New translations en_us.json (Turkish)

* New translations en_us.json (Ukrainian)

* New translations en_us.json (Chinese Simplified)

* New translations en_us.json (Chinese Traditional)

* New translations en_us.json (Portuguese, Brazilian)

* New translations en_us.json (Thai)

* New translations en_us.json (French)

* New translations en_us.json (Arabic)

* New translations en_us.json (Chinese Traditional)

* New translations en_us.json (Arabic)

* New translations en_us.json (Italian)

* New translations en_us.json (Arabic)

* New translations en_us.json (Italian)

* New translations en_us.json (Spanish)

* New translations en_us.json (Russian)

* New translations en_us.json (Russian)

* New translations en_us.json (Thai)

* New translations en_us.json (Spanish)

* New translations en_us.json (Arabic)

* New translations en_us.json (German)

* New translations en_us.json (Greek)

* New translations en_us.json (Hebrew)

* New translations en_us.json (Italian)

* New translations en_us.json (Japanese)

* New translations en_us.json (Korean)

* New translations en_us.json (Polish)

* New translations en_us.json (Russian)

* New translations en_us.json (Turkish)

* New translations en_us.json (Ukrainian)

* New translations en_us.json (Chinese Simplified)

* New translations en_us.json (Chinese Traditional)

* New translations en_us.json (Portuguese, Brazilian)

* New translations en_us.json (Thai)

* New translations en_us.json (French)

* New translations en_us.json (Chinese Traditional)

* New translations en_us.json (Arabic)

* New translations en_us.json (Russian)

* New translations en_us.json (Turkish)

* New translations en_us.json (Chinese Simplified)

* New translations en_us.json (Russian)

* New translations en_us.json (Chinese Simplified)

* New translations en_us.json (Russian)

* New translations en_us.json (Portuguese, Brazilian)

* New translations en_us.json (German)
2024-05-14 17:47:03 +02:00
Isaac Marovitz
47639e6eeb
Bump Avalonia.Svg (#6603)
* Bump Avalonia.Svg

* Remove using

* Bump Version

* Remove other reload
2024-05-14 17:36:11 +02:00
gdkchan
cd78adf07f
Add missing lock on texture cache UpdateMapping method (#6657) 2024-05-14 17:23:13 +02:00
TSRBerry
a3dc295c5f
Disable keyboard controller input while swkbd is open (foreground) (#6646)
* Block input updates while swkbd is open in foreground mode

* Flush internal driver state before unblocking input updates

* Rename Flush to Clear and remove unnecessary attribute
2024-05-14 17:14:39 +02:00
gdkchan
2ef4f92b07
Make TextureGroup.ClearModified thread safe (#6686) 2024-05-14 17:06:36 +02:00
yell0wsuit
2b6cc4b353
Add the "Auto" theme option in setting (#6611)
* Add "Follow OS theme" option

* Update App.axaml.cs

* Add "Follow OS theme" option

* Update App.axaml.cs

* Remove `this`

* Remove annotation for nullable reference

* Change into switch expression to make it concise

* Change comments to XML docs

* Update en_US.json

* Fix icons in About dialog do not response to "auto" theme

The theme icons seemingly use Dark variant event when the OS theme is light. In addition, I added ThemeManager common to make it accessible for both App and AboutWindow

* Newline at the end

* newline moment

* Update ThemeManager.cs

* bait to switch to lf

* change to lf

* temp. revert

* Add back ThemeManager.cs common, pls pass the format check

* I found the mistake: should have put `ThemeManager.OnThemeChanged();` in try block

Finally solve the formatting check

* test formatting

* Update App.axaml.cs

* Ok i seem to forget to add version lol

* Fix info CA1816
2024-05-14 17:00:03 +02:00
Gavin Zyonse
075575200d
Update compatibility information in README.md (#6801) 2024-05-14 16:58:48 +02:00
gdkchan
3a3b51893e
Add support for bindless textures from storage buffer on Vulkan (#6721)
* Halve primitive ID when converting quads to triangles

* Shader cache version bump

* Add support for bindless textures from storage buffer on Vulkan
2024-05-14 16:47:16 +02:00
MutantAura
44dbab3848
discordRPC: Truncate game title and details if they exceed discord byte limit. (#6581)
* Truncate game title and details if they exceed DiscordRPC limit.

* Update implementation to a byte total check.

* Track if the string has actually been modified correctly.

* Allow an early function return and simplify logic.

* Better handling of large input strings and minimise loop opportunities.

* Remove unused using.

* Update to `applicationName` over `titleName`.
2024-05-14 16:36:44 +02:00
Tsubasa0504
cada4d04ef
HID: Stub IHidServer: 134 (SetNpadAnalogStickUseCenterClamp) (#6664)
* Add files via upload

* Update IHidServer.cs

mistakes...

* format

how do i do it

* Update src/Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs

Co-authored-by: Agatem <agaatem@outlook.com>

* Update src/Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs

Co-authored-by: Agatem <agaatem@outlook.com>

* bruh

* Apply suggestions from code review

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

* use readuint32 instead

* second thought

* i hope it works

thanks someone higher up with the same thing

* pid

* Apply suggestions from code review

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

* styles i think

* Apply suggestions from code review

Co-authored-by: makigumo <makigumo@users.noreply.github.com>

---------

Co-authored-by: Agatem <agaatem@outlook.com>
Co-authored-by: gdkchan <gab.dark.100@gmail.com>
Co-authored-by: Ac_K <Acoustik666@gmail.com>
Co-authored-by: makigumo <makigumo@users.noreply.github.com>
2024-05-14 16:26:49 +02:00
Luke Warner
e9edf0ab7f
Update outdated Windows version warning (#6481)
* Change text

* clarify version number

* update gtk
2024-05-14 16:19:43 +02:00
TSRBerry
6e40b64554
Add linux specific files to local builds (#6762) 2024-05-14 16:06:40 +02:00
Isaac Marovitz
1a676ee913
Update DotSettings (#6535) 2024-05-14 15:59:28 +02:00
Marco Carvalho
a23d8cb92f
Replace "List.ForEach" for "foreach" (#6783)
* Replace "List.ForEach" for "foreach"

* dotnet format

* Update Ptc.cs

* Update GpuContext.cs
2024-05-08 13:53:25 +02:00
Nicolas Abram
ab12fbe963
Fix system dateTime loading in avalonia LoadCurrentConfiguration (#6676)
* Fix system dateTime loading in avalonia LoadCurrentConfiguration

* Rename local var to not use upper camel case
2024-05-02 13:33:28 +02:00
MutantAura
d0cc13ce0b
UI: Fix some MainWindow bugs and implement menubar items to change window size. (#6750)
* Do not save window dimensions when maximized.

* Implement option to disable window size/position memory.

* Remove logging statements

* Implement menubar items for common window sizes.

* formatting fixes

* Set 720p window as a composite value.

* Remove unused using

* Fix exception paramter.

* Force restore window when a size change is requested

* Fix some resizing bugs.
2024-05-01 18:21:24 +02:00
Andrew Glaze
65c035cdf8
Fix alt key appearing as control in settings menus (#6742) 2024-04-29 18:18:27 +01:00
Exhigh
56c5dbe557
Fix Cursor States On Windows (#6725)
* [Ava]: Fix Cursor States On Windows

It's been sometime since the last PR #5415 was made and last time i was waiting for Ava 11 to be merged before re-writing the code and along the way forgot about the PR.

Anyway this PR supersedes both #5288 and #5415, and fixes issue: #5136

* Now, the bounds for which the cursor should be detected in renderer should be accurate to any scaling / resolution, taking into account the status and the menu bar. ( This issue was partially resolved by #6450 )

* Reduced the number of times the cursor updates from per frame update to updating only when the cursor state needs to be changed.

* Fixed the issue wherein you weren't able to resize the window, because of the cursor passthrough which caused the cursor to reset from the reset icon or flicker.

* Fixed the issue caused by #6450 which caused the cursor to disappear over the submenus while cursor was set to always hide.

* Changed the cursor state to not disappear while the game is being loaded. ( Needs Feedback ).

* Removed an unused library import.

* PR feedback

* Fix excessive line breaks and whitespaces and other feedback
* Add a check before calculating cursor idle time, such that it calculates only while the cursor mode is OnIdle.

* PR Feedback

* Rework the cursor state check code block

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

* PR Feedback

* A simpler version of the previous implementation.

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

* PR Feedback

* PR Feedback

---------

Co-authored-by: gdkchan <5624669+gdkchan@users.noreply.github.com>
2024-04-28 20:21:08 -03:00
MaxLastBreath
5976a5161b
Fix direct keyboard not working when using a Controller. (#6716)
* Fix direct keyboard not working when connected with a controller

- Pass KeyboardDriver to NpadController.GetHLEKeyboardInput().
- Always fetch all keyboards if Direct Keyboard is turned on.
- Remove unnecessary return null.

* Get Keyboard Inputs outside of the controller loop.

- Moved GetHLEKeyboardInput outside of the controller loop.
- Made GetHLEKeyboardInput public static from public

* Removed extra newline

* Update src/Ryujinx.Input/HLE/NpadManager.cs

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

* Update src/Ryujinx.Input/HLE/NpadController.cs

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

---------

Co-authored-by: gdkchan <gab.dark.100@gmail.com>
Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>
2024-04-28 19:02:29 +02:00
riperiperi
3d4dea624d
HID: Correct direct mouse deltas (#6736)
The delta position of the mouse should be the difference between the current and last position. Subtracting the last deltas doesn't really make sense.

Won't implement pointer lock for first person games, but might stop some super weird behaviour with the mouse values appearing totally random.
2024-04-28 18:55:37 +02:00
TSRBerry
89a274c6a6
ci: Replace macos-latest label with macos-13 (#6729)
Due to a change to the GitHub runner labels a few days ago (see: actions/runner#3256) our build workflows for macOS x64 didn't work anymore.
According to https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners/about-github-hosted-runners#standard-github-hosted-runners-for-public-repositories the macos-13 label is not using arm64 yet.

Until a better solution is offered in the linked issue above, we'll keep using the macos-13 label which hopefully doesn't switch to arm64 soon.
2024-04-26 20:36:35 -03:00
gdkchan
c6f8bfed90
Add support for bindless textures from shader input (vertex buffer) on Vulkan (#6577)
* Add support for bindless textures from shader input (vertex buffer)

* Shader cache version bump

* Format whitespace

* Remove cache entries on pool removal, disable for OpenGL

* PR feedback
2024-04-22 15:05:55 -03:00
jhorv
9b94662b4b
implement MemoryManagerHostTracked.GetReadOnlySequence() (#6695)
* implement `MemoryManagerHostTracked.GetReadOnlySequence()`, fixes crashes on game starts on MacOS

* whitespace fixes

* whitespace fixes

* add missing call to `SignalMemoryTracking()`

* adjust call to `SignalMemoryTracking()``

* don't use GetPhysicalAddressMemory()

* add newline for consistency
2024-04-21 16:34:04 -03:00
jhorv
216026c096
Use pooled memory and avoid memory copies (#6691)
* perf: use ByteMemoryPool

* feat: KPageTableBase/KPageTable new methods to read and write `ReadOnlySequence<byte>`

* new: add IWritableBlock.Write(ulong, ReadOnlySequence<byte>) with default impl

* perf: use GetReadOnlySequence() instead of GetSpan()

* perf: make `Parcel` IDisposable, use `ByteMemoryPool` for internal allocation, and make Parcel consumers dispose of it

* remove comment about copySize

* remove unnecessary Clear()
2024-04-21 12:57:35 +02:00
gdkchan
7070cf6ae5
End render target lifetime on syncpoint increment (#6687) 2024-04-20 22:35:20 -03:00
toofooboo
9839cd56fb
chore: remove repetitive words (#6690)
Signed-off-by: toofooboo <cmaker@foxmail.com>
2024-04-19 09:45:51 -03:00
Marco Carvalho
99f46e22e2
Do not compare Span<T> to 'null' or 'default' (#6683) 2024-04-19 09:21:21 -03:00
Marco Carvalho
22fb8c9d4f
Update to new standard for volatility operations (#6682) 2024-04-19 09:03:52 -03:00
gdkchan
2f93ae9a19
Fix unmapped address check when reading texture handles (#6679) 2024-04-18 19:28:16 -03:00
Marco Carvalho
3224ddeeb4
Update "SixLabors.ImageSharp" (#6680) 2024-04-18 19:52:57 +02:00
Isaac Marovitz
446f2854a5
Ava UI: Input Menu Refactor (#5826)
* Refactor

* Apply suggestions from code review

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

* Update src/Ryujinx/UI/Views/Settings/SettingsHotkeysView.axaml.cs

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

* Update src/Ryujinx.Input/ButtonValueType.cs

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

* Add empty line

* Requested renames

* Update src/Ryujinx/UI/Views/Settings/SettingsHotkeysView.axaml.cs

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

* Make parent models private readonly

* Fix ControllerInputView

* Make line shorter

* Mac keys in locale

* Double line break

* Fix build

* Get rid of _isValid

* Fix potential race condition

* Rename HasAnyButtonPressed to IsAnyButtonPressed

* Use switches

* Simplify enumeration

---------

Co-authored-by: Ac_K <Acoustik666@gmail.com>
Co-authored-by: gdkchan <gab.dark.100@gmail.com>
Co-authored-by: TSR Berry <20988865+TSRBerry@users.noreply.github.com>
2024-04-17 18:52:12 -03:00
Luke
8884d1fd73
Fix crash when changing controller config (#6654)
* fix needsMotionInputUpdate conditions

* Fix formatting

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

---------

Co-authored-by: gdkchan <gab.dark.100@gmail.com>
2024-04-15 18:02:09 -03:00
jhorv
268c9aecf8
Texture loading: reduce memory allocations (#6623)
* rebase

* add methods Ryyjinx.Common EmbeddedResources and SteamUtils

* GAL changes - change SetData() methods and ThreadedTexture commands to use IMemoryOwner<byte> instead of SpanOrArray<byte>

* Ryujinx.Graphics.Texture: change texture conversion methods to return IMemoryOwner<byte> and allocate from ByteMemoryPool

* Ryujinx.Graphics.OpenGL: update ITexture and Texture-like types with SetData() methods to take IMemoryOwner<byte> instead of SpanOrArray<byte>

* Ryujinx.Graphics.Vulkan: update ITexture and Texture-like types with SetData() methods to take IMemoryOwner<byte> instead of SpanOrArray<byte>

* Ryujinx.Graphics.Gpu: update ITexture and Texture-like types with SetData() methods to take IMemoryOwner<byte> instead of SpanOrArray<byte>

* Remove now-unused SpanOrArray<T>

* post-rebase cleanup

* PixelConverter: remove unsafe modifier on safe methods, and remove one unnecessary cast

* use ByteMemoryPool.Rent() in GetWritableRegion() impls

* fix formatting, rename `ReadRentedMemory()` to `ReadFileToRentedMemory()``

* Texture.ConvertToHostCompatibleFormat(): dispose of `result` in Astc decode branch
2024-04-14 17:06:14 -03:00
gdkchan
e916662b0f
Account for swapchain image count change after re-creation (#6652) 2024-04-11 17:24:19 -03:00
gdkchan
2ddd3dd4a7
Allow BSD sockets Poll to exit when emulation ends (#6650) 2024-04-11 14:56:21 +02:00
gdkchan
a8f7ababb5
Revert "Update StoreConstantToMemory to match StoreConstantToAddress on value…" (#6649)
This reverts commit 22e3ff06b51db0fa72e9f2dc2aee395a5d1aa2df.
2024-04-10 21:50:06 -03:00
WilliamWsyHK
22e3ff06b5
Update StoreConstantToMemory to match StoreConstantToAddress on value read (#6642) 2024-04-11 00:03:37 +02:00
Isaac Marovitz
9480e5c5ce
Ava UI: Prevent Status Bar Backend Update (#6506)
* Prevent Status Bar Backend Update

* Make it a switch
2024-04-10 23:40:17 +02:00
dependabot[bot]
0652813b0f
nuget: bump Microsoft.IdentityModel.JsonWebTokens from 7.4.0 to 7.5.1 (#6627)
Bumps [Microsoft.IdentityModel.JsonWebTokens](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet) from 7.4.0 to 7.5.1.
- [Release notes](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/releases)
- [Changelog](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/compare/v7.4.0...7.5.1)

---
updated-dependencies:
- dependency-name: Microsoft.IdentityModel.JsonWebTokens
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-10 23:30:17 +02:00
gdkchan
e7f2342eba
Fix input consumed by audio renderer SplitterState.Update (#6640)
* Fix input consumed by audio renderer SplitterState.Update

* Use sizeof(int) to make clear what the value is
2024-04-10 12:07:31 -03:00
gdkchan
543d75a587
CPU: Produce non-inf results for RSQRTE instruction with subnormal inputs (#6634)
* CPU: Produce non-inf results for RSQRTE instruction with subnormal inputs

* PPTC version bump
2024-04-09 14:34:14 -03:00
gdkchan
338ff79e1e
Use ResScaleUnsupported flag for texture arrays (#6626) 2024-04-09 14:24:46 -03:00
gdkchan
80201466ae
Fast D32S8 2D depth texture copy (#6636) 2024-04-09 14:03:55 -03:00
gdkchan
7a971edb57
Pin audio renderer update output buffers (#6633) 2024-04-08 20:26:47 -03:00
MutantAura
c1b0ab805a
Disable CLI setting persistence for HW-accelerated GUI. (#6620) 2024-04-07 20:58:05 -03:00
gdkchan
3e6e0e4afa
Add support for large sampler arrays on Vulkan (#6489)
* Add support for large sampler arrays on Vulkan

* Shader cache version bump

* Format whitespace

* Move DescriptorSetManager to PipelineLayoutCacheEntry to allow different pool sizes per layout

* Handle array textures with different types on the same buffer

* Somewhat better caching system

* Avoid useless buffer data modification checks

* Move redundant bindings update checking to the backend

* Fix an issue where texture arrays would get the same bindings across stages on Vulkan

* Backport some fixes from part 2

* Fix typo

* PR feedback

* Format whitespace

* Add some missing XML docs
2024-04-07 18:25:55 -03:00
gdkchan
808803d97a
CPU: Fix PC alignment for ADR thumb instruction (#6613)
* Fix PC alignment for ADR thumb instruction

* PPTC version bump
2024-04-07 18:17:49 -03:00
jhorv
ead9a25141
Audio rendering: reduce memory allocations (#6604)
* - WritableRegion: enable wrapping IMemoryOwner<byte>
- IVirtualMemoryManager impls of GetWritableRegion() use pooled memory when region is non-contiguous.
- IVirtualMemoryManager: add GetReadOnlySequence() and impls
- ByteMemoryPool: add new method RentCopy()
- ByteMemoryPool: make class static, remove ctor and singleton field from earlier impl

* - BytesReadOnlySequenceSegment: move from Ryujinx.Common.Memory to Ryujinx.Memory
- BytesReadOnlySequenceSegment: add IsContiguousWith() and Replace() methods
- VirtualMemoryManagerBase:
  - remove generic type parameters, instead use ulong for virtual addresses and nuint for host/physical addresses
  - implement IWritableBlock
  - add virtual GetReadOnlySequence() with coalescing of contiguous segments
  - add virtual GetSpan()
  - add virtual GetWritableRegion()
  - add abstract IsMapped()
  - add virtual MapForeign(ulong, nuint, ulong)
  - add virtual Read<T>()
  - add virtual Read(ulong, Span<byte>)
  - add virtual ReadTracked<T>()
  - add virtual SignalMemoryTracking()
  - add virtual Write()
  - add virtual Write<T>()
  - add virtual WriteUntracked()
  - add virtual WriteWithRedundancyCheck()
- VirtualMemoryManagerRefCountedBase: remove generic type parameters
- AddressSpaceManager: remove redundant methods, add required overrides
- HvMemoryManager: remove redundant methods, add required overrides, add overrides for _invalidAccessHandler handling
- MemoryManager: remove redundant methods, add required overrides, add overrides for _invalidAccessHandler handling
- MemoryManagerHostMapped: remove redundant methods, add required overrides, add overrides for _invalidAccessHandler handling
- NativeMemoryManager: add get properties for Pointer and Length
- throughout: removed invalid <inheritdoc/> comments

* - WritableRegion: enable wrapping IMemoryOwner<byte>
- IVirtualMemoryManager impls of GetWritableRegion() use pooled memory when region is non-contiguous.
- IVirtualMemoryManager: add GetReadOnlySequence() and impls
- ByteMemoryPool: add new method RentCopy()
- ByteMemoryPool: make class static, remove ctor and singleton field from earlier impl

* add PagedMemoryRange enumerator types, use them in IVirtualMemoryManager implementations to consolidate page-handling logic and add a new capability - the coalescing of pages for consolidating memory copies and segmentation.

* new: more tests for PagedMemoryRangeCoalescingEnumerator showing coalescing of contiguous segments

* make some struct properties readonly

* put braces around `foreach` bodies

* encourage inlining of some PagedMemoryRange*Enumerator members

* DynamicRingBuffer:
 - use ByteMemoryPool
 - make some methods return without locking when size/count argument = 0
 - make generic Read<T>()/Write<T>() non-generic because its only usage is as T = byte
 - change Read(byte[]...) to Read(Span<byte>...)
 - change Write(byte[]...) to Write(Span<byte>...)

* change IAudioRenderer.RequestUpdate() to take a ReadOnlySequence<byte>, enabling zero-copy audio rendering

* HipcGenerator: support ReadOnlySequence<byte> as IPC method parameter

* change IAudioRenderer/AudioRenderer RequestUpdate* methods to take input as ReadOnlySequence<byte>

* MemoryManagerHostTracked: use rented memory when contiguous in `GetWritableRegion()`

* rebase cleanup

* dotnet format fixes

* format and comment fixes

* format long parameter list - take 2

* - add support to HipcGenerator for buffers of type `Memory<byte>`
- change `AudioRenderer` `RequestUpdate()` and `RequestUpdateAuto()` to use Memory<byte> for output buffers, removing another memory block allocation/copy

* SplitterContext `UpdateState()` and `UpdateData()` smooth out advance/rewind logic, only rewind if magic is invalid

* DynamicRingBuffer.Write(): change Span<byte> to ReadOnlySpan<byte>
2024-04-07 18:07:32 -03:00
Marco Carvalho
3e0d67533f
Enhance Error Handling with Try-Pattern Refactoring (#6610)
* Enhance Error Handling with Try-Pattern Refactoring

* refactoring

* refactoring

* Update src/Ryujinx.HLE/FileSystem/ContentPath.cs

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

---------

Co-authored-by: gdkchan <gab.dark.100@gmail.com>
2024-04-07 17:55:34 -03:00
Marco Carvalho
0b55914864
Replacing the try-catch block with null-conditional and null-coalescing operators (#6612)
* Replacing the try-catch block with null-conditional and null-coalescing operators

* repeating
2024-04-07 16:49:14 -03:00
MutantAura
451a28afb8
misc: Add ANGLE configuration option to JSON and CLI (#6520)
* Add hardware-acceleration toggle to ConfigurationState.

* Add command line override for easier RenderDoc use.

* Adjust CLI arguments.

* fix whitespace format check

* fix copypasta in comment

* Add X11 rendering mode toggle

* Remove ANGLE specific comments.
2024-04-06 14:58:02 -03:00
gdkchan
12b235700c
Delete old 16KB page workarounds (#6584)
* Delete old 16KB page workarounds

* Rename Supports4KBPage to UsesPrivateAllocations

* Format whitespace

* This one should be false too

* Update XML doc
2024-04-06 13:51:44 -03:00
gdkchan
3be616207d
Vulkan: Fix swapchain image view leak (#6509) 2024-04-06 13:38:52 -03:00
gdkchan
791bf22109
Vulkan: Skip draws when patches topology is used without a tessellation shader (#6508) 2024-04-06 13:25:51 -03:00
dependabot[bot]
66b1d59c66
nuget: bump DynamicData from 8.3.27 to 8.4.1 (#6536)
Bumps [DynamicData](https://github.com/reactiveui/DynamicData) from 8.3.27 to 8.4.1.
- [Release notes](https://github.com/reactiveui/DynamicData/releases)
- [Changelog](https://github.com/reactivemarbles/DynamicData/blob/main/ReleaseNotes.md)
- [Commits](https://github.com/reactiveui/DynamicData/compare/8.3.27...8.4.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-06 14:07:06 +02:00
WilliamWsyHK
c8bb05633e
Add mod enablement status in the log message (#6571) 2024-04-06 13:47:01 +02:00
czcx
fb1171a21e
Update README.md (#6575) 2024-04-06 13:45:24 +02:00
Marco Carvalho
22c0aa9c90
"Task.Wait()" synchronously blocks, use "await" instead (#6598) 2024-04-06 13:36:18 +02:00
Ac_K
6d28b64312
ts: Migrate service to Horizon project (#6514)
* ts: Migrate service to Horizon project

This PR migrate the `ts` service (stored in `ptm`) to the Horizon project:
- It stubs all known IPCs.
- IpcServer consts are checked by RE.

Closes #6480

* Fix args
2024-04-05 15:45:43 -03:00
gdkchan
05c041feeb
Ignore diacritics on game search (#6602) 2024-04-05 15:26:45 -03:00
gdkchan
8c2da1aa04
Add missing ModWindowTitle locale key (#6601)
* Add missing ModWindowTitle locale key

* Fix this while I'm at it
2024-04-05 12:54:08 -03:00
jhorv
5def0429f8
Add support to IVirtualMemoryManager for zero-copy reads (#6251)
* - WritableRegion: enable wrapping IMemoryOwner<byte>
- IVirtualMemoryManager impls of GetWritableRegion() use pooled memory when region is non-contiguous.
- IVirtualMemoryManager: add GetReadOnlySequence() and impls
- ByteMemoryPool: add new method RentCopy()
- ByteMemoryPool: make class static, remove ctor and singleton field from earlier impl

* - BytesReadOnlySequenceSegment: move from Ryujinx.Common.Memory to Ryujinx.Memory
- BytesReadOnlySequenceSegment: add IsContiguousWith() and Replace() methods
- VirtualMemoryManagerBase:
  - remove generic type parameters, instead use ulong for virtual addresses and nuint for host/physical addresses
  - implement IWritableBlock
  - add virtual GetReadOnlySequence() with coalescing of contiguous segments
  - add virtual GetSpan()
  - add virtual GetWritableRegion()
  - add abstract IsMapped()
  - add virtual MapForeign(ulong, nuint, ulong)
  - add virtual Read<T>()
  - add virtual Read(ulong, Span<byte>)
  - add virtual ReadTracked<T>()
  - add virtual SignalMemoryTracking()
  - add virtual Write()
  - add virtual Write<T>()
  - add virtual WriteUntracked()
  - add virtual WriteWithRedundancyCheck()
- VirtualMemoryManagerRefCountedBase: remove generic type parameters
- AddressSpaceManager: remove redundant methods, add required overrides
- HvMemoryManager: remove redundant methods, add required overrides, add overrides for _invalidAccessHandler handling
- MemoryManager: remove redundant methods, add required overrides, add overrides for _invalidAccessHandler handling
- MemoryManagerHostMapped: remove redundant methods, add required overrides, add overrides for _invalidAccessHandler handling
- NativeMemoryManager: add get properties for Pointer and Length
- throughout: removed invalid <inheritdoc/> comments

* make HvMemoryManager class sealed

* remove unused method

* adjust MemoryManagerHostTracked

* let MemoryManagerHostTracked override WriteImpl()
2024-04-04 22:23:03 -03:00
gdkchan
8e74fa3456
Stop clearing Modified flag on DiscardData (#6591) 2024-04-03 21:30:46 -03:00
Ac_K
6208c3e6f0
New Crowdin updates (#6550)
* New translations en_us.json (Spanish)

* New translations en_us.json (Arabic)

* New translations en_us.json (German)

* New translations en_us.json (Greek)

* New translations en_us.json (Italian)

* New translations en_us.json (Korean)

* New translations en_us.json (Polish)

* New translations en_us.json (Russian)

* New translations en_us.json (Turkish)

* New translations en_us.json (Ukrainian)

* New translations en_us.json (Chinese Traditional)

* New translations en_us.json (Portuguese, Brazilian)

* New translations en_us.json (Spanish)

* New translations en_us.json (Arabic)

* New translations en_us.json (German)

* New translations en_us.json (Greek)

* New translations en_us.json (Hebrew)

* New translations en_us.json (Italian)

* New translations en_us.json (Japanese)

* New translations en_us.json (Korean)

* New translations en_us.json (Polish)

* New translations en_us.json (Russian)

* New translations en_us.json (Turkish)

* New translations en_us.json (French)

* New translations en_us.json (Ukrainian)

* New translations en_us.json (Chinese Simplified)

* New translations en_us.json (Chinese Traditional)

* New translations en_us.json (Portuguese, Brazilian)

* New translations en_us.json (Thai)

* New translations en_us.json (Italian)

* New translations en_us.json (Japanese)

* New translations en_us.json (Polish)

* New translations en_us.json (Ukrainian)

* New translations en_us.json (Chinese Simplified)

* New translations en_us.json (Arabic)

* New translations en_us.json (Italian)

* New translations en_us.json (Russian)

* New translations en_us.json (Chinese Simplified)

* New translations en_us.json (Italian)

* New translations en_us.json (German)

* New translations en_us.json (Korean)

* New translations en_us.json (Chinese Simplified)

* New translations en_us.json (Arabic)

* New translations en_us.json (Hebrew)

* New translations en_us.json (Chinese Simplified)

* New translations en_us.json (Arabic)
2024-04-02 13:21:14 -03:00
MutantAura
7124d679fd
UI: Friendly driver name reporting. (#6530)
* Implement friendly VkDriverID names for UI.

* Capitalise NVIDIA

* Prefer vendor name on macOS

* Typo fix

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

---------

Co-authored-by: gdkchan <gab.dark.100@gmail.com>
2024-03-27 14:55:34 -03:00
gdkchan
b323a01738
Implement host tracked memory manager mode (#6356)
* Add host tracked memory manager mode

* Skipping flush is no longer needed

* Formatting + revert unrelated change

* LightningJit: Ensure that dest register is saved for load ops that do partial updates

* avoid allocations when doing address space lookup

Add missing improvement

* IsRmwMemory -> IsPartialRegisterUpdateMemory

* Ensure we iterate all private allocations in range

* PR feedback and potential fixes

* Simplified bridges a lot

* Skip calling SignalMappingChanged if Guest is true

* Late map bridge too

* Force address masking for prefetch instructions

* Reprotection for bridges

* Move partition list validation to separate debug method

* Move host tracked related classes to HostTracked folder

* New HostTracked namespace

* Move host tracked modes to the end of enum to avoid PPTC invalidation

---------

Co-authored-by: riperiperi <rhy3756547@hotmail.com>
2024-03-26 23:33:24 -03:00
jcm
f6d24449b6
Recreate swapchain correctly when toggling VSync (#6521)
Co-authored-by: jcm <butt@butts.com>
2024-03-26 22:54:13 -03:00
gdkchan
72bdc24db8
Disable push descriptors for Intel ARC GPUs on Windows (#6551)
* Move some init logic out of PrintGpuInformation, then delete it

* Disable push descriptors for Intel ARC on Windows

* Re-add PrintGpuInformation just to show it in the log
2024-03-26 22:27:48 -03:00
SamusAranX
43514771bf
New gamecard icons (#6557)
* Replaced all gamecard images and added a blank variant

* File optimization
2024-03-23 21:33:27 +01:00
gdkchan
dbfe859ed7
Add a few missing locale strings on Avalonia (#6556)
* Add a few missing locale strings on Avalonia

* Rename LDN MitM to ldn_mitm
2024-03-23 16:31:54 -03:00
Matt Heins
c94a73ec60
Updates the default value for BufferedQuery (#6351)
AMD GPUs (possibly just RDNA 3) could hang with the previous value
until the MaxQueryRetries was hit.

Fix #6056

Co-authored-by: riperiperi <rhy3756547@hotmail.com>
2024-03-21 21:44:11 -03:00
WilliamWsyHK
20a280525f
[UI] Fix Display Name Translations & Update some Chinese Translations (#6388)
* Remove incorrect additional back-slash

* Touch-up on TChinese translations

* Little touch-up on SChinese translations
2024-03-21 20:08:25 +01:00
Ac_K
75a4ea3370
New Crowdin updates (#6541)
* New translations en_us.json (French)

* New translations en_us.json (Spanish)

* New translations en_us.json (Arabic)

* New translations en_us.json (German)

* New translations en_us.json (Greek)

* New translations en_us.json (Hebrew)

* New translations en_us.json (Italian)

* New translations en_us.json (Japanese)

* New translations en_us.json (Korean)

* New translations en_us.json (Polish)

* New translations en_us.json (Russian)

* New translations en_us.json (Turkish)

* New translations en_us.json (Ukrainian)

* New translations en_us.json (Chinese Simplified)

* New translations en_us.json (Chinese Traditional)

* New translations en_us.json (Portuguese, Brazilian)

* New translations en_us.json (Thai)

* Add missing Thai language name

* Add new languages

* Enable RTL for Arabic

---------

Co-authored-by: gdkchan <gab.dark.100@gmail.com>
2024-03-20 21:07:27 -03:00
dependabot[bot]
d26ef2eec3
nuget: bump Microsoft.CodeAnalysis.CSharp from 4.8.0 to 4.9.2 (#6397)
Bumps [Microsoft.CodeAnalysis.CSharp](https://github.com/dotnet/roslyn) from 4.8.0 to 4.9.2.
- [Release notes](https://github.com/dotnet/roslyn/releases)
- [Changelog](https://github.com/dotnet/roslyn/blob/main/docs/Breaking%20API%20Changes.md)
- [Commits](https://github.com/dotnet/roslyn/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-17 02:55:11 +01:00
Isaac Marovitz
a0552fd78b
Ava UI: Fix locale crash (#6385)
* Fix locale crash

* Apply suggestions from code review

---------

Co-authored-by: Ac_K <Acoustik666@gmail.com>
2024-03-17 02:27:14 +01:00
Isaac Marovitz
bb8c5ebae1
Ava UI: Content Dialog Fixes (#6482)
* Don’t use ContentDialogHelper when not necessary

* Remove `ExtendClientAreaToDecorationsHint`
2024-03-16 20:34:26 +01:00
dependabot[bot]
50bdda5baa
nuget: bump Microsoft.IdentityModel.JsonWebTokens from 7.3.0 to 7.4.0 (#6366)
Bumps [Microsoft.IdentityModel.JsonWebTokens](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet) from 7.3.0 to 7.4.0.
- [Release notes](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/releases)
- [Changelog](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/compare/7.3.0...v7.4.0)

---
updated-dependencies:
- dependency-name: Microsoft.IdentityModel.JsonWebTokens
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-16 20:13:30 +01:00
dependabot[bot]
18df25f66f
nuget: bump the avalonia group with 2 updates (#6505)
Bumps the avalonia group with 2 updates: [Avalonia.Svg](https://github.com/wieslawsoltes/Svg.Skia) and [Avalonia.Svg.Skia](https://github.com/wieslawsoltes/Svg.Skia).


Updates `Avalonia.Svg` from 11.0.0.14 to 11.0.0.16
- [Release notes](https://github.com/wieslawsoltes/Svg.Skia/releases)
- [Changelog](https://github.com/wieslawsoltes/Svg.Skia/blob/master/CHANGELOG.md)
- [Commits](https://github.com/wieslawsoltes/Svg.Skia/commits)

Updates `Avalonia.Svg.Skia` from 11.0.0.14 to 11.0.0.16
- [Release notes](https://github.com/wieslawsoltes/Svg.Skia/releases)
- [Changelog](https://github.com/wieslawsoltes/Svg.Skia/blob/master/CHANGELOG.md)
- [Commits](https://github.com/wieslawsoltes/Svg.Skia/commits)

---
updated-dependencies:
- dependency-name: Avalonia.Svg
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: avalonia
- dependency-name: Avalonia.Svg.Skia
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: avalonia
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-16 20:02:18 +01:00
standstaff
e19e7622a3
chore: remove repetitive words (#6500)
Signed-off-by: standstaff <zhengxingru@yeah.net>
2024-03-16 19:49:54 +01:00
Isaac Marovitz
26026d1357
Fix Title Update Manager not refreshing app list (#6507) 2024-03-16 19:46:03 +01:00
TSRBerry
24068b023c
discord: Update ApplicationID (#6513) 2024-03-16 19:41:38 +01:00
riperiperi
1217a8e69b
GPU: Rebind RTs if scale changes when binding textures (#6493)
This fixes a longstanding issue with resolution scale that could result in flickering graphics, typically the first frame something is drawn, or on camera cuts in cutscenes.

The root cause of the issue is that texture scale can be changed when binding textures or images. This typically happens because a texture becomes a view of a larger texture, such as a 400x225 texture becoming a view of a 800x450 texture with two levels. If the 400x225 texture is bound as a render target and has state [1x Undesired], but the storage texture is [2x Scaled], the render target texture's scale is changed to [2x Scaled] to match its new storage. This means the scale changed after the render target state was processed...

This can cause a number of issues. When render target state is processed, texture scales are examined and potentially changed so that they are all the same value. If one texture is scaled, all textures must be. If one texture is blacklisted from scaling, all of them must be. This results in a single resolution scale value being assigned to the TextureManager, which also scales the scissor and viewport values.

If the scale is chosen as 1x, and a later texture binding changes one of the textures to be 2x, the scale in TextureManager no longer matches all of the bound textures. What's worse, the scales in these textures could mismatch entirely. This typically results in the support buffer scale, viewport and scissor being wrong for at least one of the bound render targets.

This PR fixes the issue by re-evaluating render target state if any scale mismatches the expected scale after texture bindings happen. This can actually cause scale to change again, so it must loop back to perform texture bindings again. This can happen as many times as it needs to, but I don't expect it to happen more than once. Problematic bindings will just result in a blacklist, which will propagate to other bound targets.
2024-03-14 19:59:09 -03:00
gdkchan
732db7581f
Consider Polygon as unsupported is triangle fans are unsupported on Vulkan (#6490) 2024-03-14 19:46:57 -03:00
riperiperi
fdd3263e31
Separate guest/host tracking + unaligned protection (#6486)
* WIP: Separate guest/host tracking + unaligned protection

Allow memory manager to define support for single byte guest tracking

* Formatting

* Improve docs

* Properly handle cases where the address space bits are too low

* Address feedback
2024-03-14 19:38:27 -03:00
Isaac Marovitz
ce607db944
Ava UI: Update Ava (#6430)
* Update Ava

* Newline
2024-03-14 02:29:13 +01:00
TSRBerry
6b4ee82e5d
infra: Fix updater for old Ava users (#6441)
* Add binaries with both names to release archives

* Add migration code for the new filename

* Add Ryujinx.Ava to all win/linux releases for a while
2024-03-13 23:26:35 +01:00
Keaton
e2a655f1a4
Update AutoDeleteCache.cs (#6471)
Increase the texture cache limit from 512 MB to 1 GB.
2024-03-13 17:39:39 -03:00
Nicolas Abram
d9a18919b0
Fix geometry shader passthrough issue (#6462)
* Fix geometry shader passthrough issue (Diagnosed by gdkchan)

* Fix whitespace formatting

* Fix whitespace formatting

* Bump shader cache version

* Don't apply PassthroughNV decorations to output geometry shader variables
2024-03-13 17:26:19 -03:00
Emmanuel Hansen
8354434a37
Passthrough mouse for win32 (#6450)
* passthrough mouse for win32

* remove unused enums
2024-03-11 21:21:39 -03:00
gdkchan
5a900f38c5
Fix lost copy and swap problem on shader SSA deconstruction (#6455)
* Fix lost copy on shader SSA deconstruction

* Shader cache version bump
2024-03-10 21:16:40 -03:00
jhorv
a3a63d4394
Refactor memory managers to a common base class, consolidate Read() method logic (#6360)
* - add new abstract class `VirtualMemoryManagerBase`
- rename `MemoryManagerBase` to `VirtualMemoryManagerRefCountedBase` and derive from `VirtualMemoryManagerBase`
- change `AddressSpaceManager`, `HvMemoryManager`, `MemoryManager`, and `MemoryManagerHostMapped` to implement abstract members and use the inherited `void VirtualMemoryManagerBase.Read(TVirtual va, Span<byte> data)` implementation.

* move property `AddressSpaceSize` up by the other properties
2024-03-09 21:01:51 -03:00
TSRBerry
3924bd1a43
Update dependencies from SixLabors to the latest version before the license change (#6440)
* nuget: bump SixLabors.ImageSharp from 1.0.4 to 2.1.3 (#3976)

* nuget: bump SixLabors.ImageSharp from 1.0.4 to 2.1.3

Bumps [SixLabors.ImageSharp](https://github.com/SixLabors/ImageSharp) from 1.0.4 to 2.1.3.
- [Release notes](https://github.com/SixLabors/ImageSharp/releases)
- [Commits](https://github.com/SixLabors/ImageSharp/compare/v1.0.4...v2.1.3)

---
updated-dependencies:
- dependency-name: SixLabors.ImageSharp
  dependency-type: direct:production
  update-type: version-update:semver-major
...

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

* Update for 2.x changes

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Mary <mary@mary.zone>

* Update SixLabors.ImageSharp to 2.1.7

This is the latest version we can update to without the license change.

* Update SixLabors.ImageSharp.Drawing to v1.0.0

This is the latest version we can update to without the license change.

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Mary <mary@mary.zone>
2024-03-08 13:16:32 -03:00
gdkchan
50458b2472
LightningJit: Disable some cache ops and CTR_EL0 access on Windows Arm (#6326)
* LightningJit: Disable some cache ops and CTR_EL0 access on Windows Arm

* Format whitespace

* Delete unused code

* Fix typo

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

---------

Co-authored-by: riperiperi <rhy3756547@hotmail.com>
2024-03-07 20:55:54 -03:00
MutantAura
dda0f26067
UI: Update minimum window size to 800x500 (#6425) 2024-03-07 20:38:56 -03:00
Kyle
4e1a60328e
Add title of game to screenshot text (#6266)
* Add sanitize method

* Add app name to screenshot text output

* Add app name to screenshot text
2024-03-07 22:49:57 +00:00
Mary Guillemard
2505a1abcd misc: Remove myself from reviews
I have been mostly inactive on the project for the past year and a half
apart from handling CI and reviews because of a lack of motivation and
time.
2024-03-05 17:54:35 +01:00
Mary Guillemard
bc4d99a078 ci: try to fix toctou on release creation
Signed-off-by: Mary Guillemard <mary@mary.zone>
2024-03-02 12:58:03 +01:00
Mary Guillemard
ec6cb0abb4
infra: Make Avalonia the default UI (#6375)
* misc: Move Ryujinx project to Ryujinx.Gtk3

This breaks release CI for now but that's fine.

Signed-off-by: Mary Guillemard <mary@mary.zone>

* misc: Move Ryujinx.Ava project to Ryujinx

This breaks CI for now, but it's fine.

Signed-off-by: Mary Guillemard <mary@mary.zone>

* infra: Make Avalonia the default UI

Should fix CI after the previous changes.

GTK3 isn't build by the release job anymore, only by PR CI.

This also ensure that the test-ava update package is still generated to
allow update from the old testing channel.

Signed-off-by: Mary Guillemard <mary@mary.zone>

* Fix missing copy in create_app_bundle.sh

Signed-off-by: Mary Guillemard <mary@mary.zone>

* Fix syntax error

Signed-off-by: Mary Guillemard <mary@mary.zone>

---------

Signed-off-by: Mary Guillemard <mary@mary.zone>
2024-03-02 12:51:05 +01:00
Mary Guillemard
53b5985da6
Avalonia: only enable gamescope workaround under it (#6374)
Signed-off-by: Mary Guillemard <mary@mary.zone>
2024-03-02 11:16:46 +01:00
gdkchan
87f238be60
Change packed aliasing formats to UInt (#6358) 2024-02-24 19:02:20 -03:00
dependabot[bot]
4d0dbbfae2
nuget: bump System.Drawing.Common from 8.0.1 to 8.0.2 (#6308)
Bumps [System.Drawing.Common](https://github.com/dotnet/winforms) from 8.0.1 to 8.0.2.
- [Release notes](https://github.com/dotnet/winforms/releases)
- [Changelog](https://github.com/dotnet/winforms/blob/main/docs/release-activity.md)
- [Commits](https://github.com/dotnet/winforms/compare/v8.0.1...v8.0.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-24 01:17:24 +01:00
jhorv
08384ee5a8
IPC code gen improvements (#6352)
* HipcGenerator: skip do-nothing call to MemoryMarshal.Cast<byte, byte>() in generated code

* HipcGenerator: fix method name typos

* HipcGenerator: make generated methods use stackalloc for `isBufferMapAlias` bool array

* HipcGenerator: make generated GetCommandHandlers() method return a FrozenDictionary<int, CommandHandler>

* HipcGenerator: return `FrozenDictionary<,>.Empty` when there are no command implementations, otherwise create `FrozenDictionary` from a `IEnumerable<KeyValuePair<,>>`` instead of a `Dictionary<,>``
2024-02-23 21:12:24 -03:00
gdkchan
d4d0a48bfe
Migrate Audio service to new IPC (#6285)
* Migrate audren to new IPC

* Migrate audout

* Migrate audin

* Migrate hwopus

* Bye bye old audio service

* Switch volume control to IHardwareDeviceDriver

* Somewhat unrelated changes

* Remove Concentus reference from HLE

* Implement OpenAudioRendererForManualExecution

* Remove SetVolume/GetVolume methods that are not necessary

* Remove SetVolume/GetVolume methods that are not necessary (2)

* Fix incorrect volume update

* PR feedback

* PR feedback

* Stub audrec

* Init outParameter

* Make FinalOutputRecorderParameter/Internal readonly

* Make FinalOutputRecorder IDisposable

* Fix HardwareOpusDecoderManager parameter buffers

* Opus work buffer size and error handling improvements

* Add AudioInProtocolName enum

* Fix potential divisions by zero
2024-02-22 16:58:33 -03:00
riperiperi
57d8afd0c9
OpenGL: Mask out all color outputs with no fragment shader (#6341)
* OpenGL: Mask out all color outputs with no fragment shader

This appears to match Vulkan's behaviour, which is needed for stencil shadows in Penny's Big Breakaway. It's far from the only issue, you can try the Full Bindless PR if you want to see it in a more intact state.

* Remove unused member
2024-02-22 18:43:19 +01:00
gdkchan
c43fb92bbf
Ensure service init runs after Horizon constructor (#6342) 2024-02-22 13:55:29 -03:00
gdkchan
167f50bbcd
Implement virtual buffer dependencies (#6190)
* Implement virtual buffer copies

* Introduce TranslateAndCreateMultiBuffersPhysicalOnly, use it for copy and clear

* Rename VirtualBufferCache to VirtualRangeCache

* Fix potential issue where virtual range could exist in the cache, without a physical buffer

* Fix bug that could cause copy with negative size on CopyToDependantVirtualBuffer

* Remove virtual copy back for SyncAction

* GetData XML docs

* Make field readonly

* Fix virtual buffer modification tracking

* Remove CopyFromDependantVirtualBuffers from ExternalFlush

* Move things around a little to avoid perf impact

- Inline null check for CopyFromDependantVirtualBuffers
- Remove extra method call for SynchronizeMemoryWithVirtualCopyBack, prefer calling CopyFromDependantVirtualBuffers separately

* Fix up XML doc

---------

Co-authored-by: riperiperi <rhy3756547@hotmail.com>
2024-02-22 11:03:07 -03:00
riperiperi
ba91f5d401
Vulkan: Properly reset barrier batch when splitting due to mismatching flags (#6345)
Forgot to set the end variable here. Should stop it from crashing when this path is taken.
2024-02-22 10:43:22 +01:00
riperiperi
79f6c18a9b
Vulkan: Disable push descriptors on older NVIDIA GPUs (#6340)
Disables push descriptors on older NVIDIA GPUs (10xx and below), since it is clearly broken beyond comprehension. The existing workaround wasn't good enough and a more thorough one will probably cost more performance than the feature gains. The workaround has been removed.

Fixes #6331.
2024-02-21 23:52:13 -03:00
riperiperi
4f63782bac
Vulkan: Fix barrier batching past limit (#6339)
If more than 16 barriers were queued at one time, the _queuedBarrierCount would no longer match the number of remaining barriers, because when breaking out of the loop consuming them it deleted all barriers, not just the 16 that were consumed.

Should fix freezes that started occurring with #6240. Fixes issue #6338.
2024-02-21 23:41:08 -03:00
MetrosexualGarbodor
6f5fcb7970
Avalonia UI: Update English tooltips (#6305)
* update English tooltips

* missed a dot
2024-02-19 23:27:15 +01:00
Mary Guillemard
6ef8946169
Avalonia: Fix gamescope once and for all (#6301)
Enable input focus proxy, makes WM_TAKE_FOCUS capability to be exposed.

This fix menu on gamescope, for real this time....

Signed-off-by: Mary Guillemard <mary@mary.zone>
2024-02-19 21:18:46 +01:00
gdkchan
42340fc743
LightningJit: Add a limit on the number of instructions per function for Arm64 (#6328) 2024-02-17 17:30:54 -03:00
Exhigh
103e7cb021
hid: Stub SetTouchScreenResolution (#6322)
* hid: Implement SetTouchScreenResolution

* Fix Tomb Raider I-III Remastered from crashing without enabling Ignore Missing Services

* PR Feedback: Update Comments
2024-02-17 14:49:50 -03:00
riperiperi
31ed061bea
Vulkan: Improve texture barrier usage, timing and batching (#6240)
* WIP barrier batch

* Add store op to image usage barrier

* Dispose the barrier batch

* Fix encoding?

* Handle read and write on the load op barrier.

Load op consumes read accesses but does not add one, as the only other operation that can read is another load.

* Simplify null check

* Insert barriers on program change in case stale bindings are reintroduced

* Not sure how I messed this one up

* Improve location of bindings barrier update

This is also important for emergency deferred clear

* Update src/Ryujinx.Graphics.Vulkan/BarrierBatch.cs

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

---------

Co-authored-by: Mary Guillemard <thog@protonmail.com>
2024-02-17 00:21:37 -03:00
riperiperi
4218311e6a
Vulkan: Use push descriptors for uniform bindings when possible (#6154)
* Fix Push Descriptors

* Use push descriptor templates

* Use reserved bindings

* Formatting

* Disable when using MVK

("my heart will go on" starts playing as thousands of mac users shed a tear in unison)

* Introduce limit on push descriptor binding number

The bitmask used for updating push descriptors is ulong, so only 64 bindings can be tracked for now.

* Address feedback

* Fix logic for binding rejection

Should only offset limit when reserved bindings are less than the requested one.

* Workaround pascal and older nv bug

* Add GPU number detection for nvidia

* Only do workaround if it's valid to do so.
2024-02-16 21:41:30 -03:00
gdkchan
e37735ed26
Implement X8Z24 texture format (#6315) 2024-02-15 19:06:26 -03:00
gdkchan
74a18b7c18
Fix PermissionLocked check on UnmapProcessCodeMemory (#6314) 2024-02-15 16:16:01 -03:00
gdkchan
74fe814329
Remove Vulkan SubgroupSizeControl enablement code (#6317) 2024-02-15 16:04:30 -03:00
gdkchan
d1a093e5ca
Stub VSMS related ioctls (#6313)
* Stub VSMS related ioctls

* Clean up usings
2024-02-15 19:48:22 +01:00
Isaac Marovitz
dfb14a5607
Updaters: Fix ARM Linux Updater (#6316)
* Remove Arch Checks

* Fix ARM Linux updater
2024-02-15 10:41:43 +01:00
jcm
904a5ffcb4
Handle exceptions when checking user data directory for symlink (#6304)
Co-authored-by: jcm <butt@butts.com>
2024-02-12 00:10:21 +01:00
jcm
946633276b
macOS: Stop storing user data in Documents for some users; fix symlinks (#6241)
* macOS: Stop storing user data in Documents for some users; fix symlinks

* Use SupportedOSPlatform tag, catch exceptions, log warning instead of error

* Provide best path hints to user if symlink fixup fails

---------

Co-authored-by: jcm <butt@butts.com>
2024-02-11 19:04:39 +01:00
Mary Guillemard
baf94e0e3e
infra: Force add linux-x64 apphost in flathub nuget source (#6302)
Required when building on the arm64 runner.

Signed-off-by: Mary Guillemard <mary@mary.zone>
2024-02-11 16:45:58 +01:00
Mary Guillemard
cf6201a4a6 infra: Restore Nuget packages for linux-arm64 for Flatpak
Signed-off-by: Mary Guillemard <mary@mary.zone>
2024-02-11 13:21:54 +01:00
Isaac Marovitz
18909195d1
Old buttons (#6237) 2024-02-11 03:12:43 +01:00
Isaac Marovitz
f06d22d6f0
Infra: Capitalisation Consistency (#6296)
* Rename Ryujinx.UI.Common

* Rename Ryujinx.UI.LocaleGenerator

* Update in Files

AboutWindow

* Configuration State

* Rename projects

* Ryujinx/UI

* Fix build

* Main remaining inconsistencies

* HLE.UI Namespace

* HLE.UI Files

* Namespace

* Ryujinx.UI.Common.Configuration.UI

* Ryujinx.UI.Common,Configuration.UI Files

* More instances
2024-02-11 03:09:18 +01:00
jcm
84d6e8d121
Standardize logging locations across desktop platforms (#6238)
* Standardize logging locations across desktop platforms

* Return null instead of empty literal on exceptions

* Remove LogDirectoryPath from LoggerModule

* Catch exception when creating DirectoryInfo in FileLogTarget

* Remove redundant log path vars, handle exception better, add null check

* Address styling issues

* Remove extra newline, quote file path in log, move directory check to OpenHelper

* Add GetOrCreateLogsDir to get/create log directory during runtime

* misc format changes

* Update src/Ryujinx.Common/Configuration/AppDataManager.cs

---------

Co-authored-by: jcm <butt@butts.com>
Co-authored-by: TSR Berry <20988865+TSRBerry@users.noreply.github.com>
Co-authored-by: Ac_K <Acoustik666@gmail.com>
2024-02-11 02:17:19 +01:00
lasers
95c4912d58
Linux: Reorder available executables in Ryujinx.sh (#6171)
* Avoid Ryujinx.Headless.SDL2 as a last resort in Ryujinx.desktop when you
  have more than one executable installed.
2024-02-11 00:57:23 +01:00
Isaac Marovitz
356a75af0b
Remove ReflectionBinding in Mod Manager (#6280) 2024-02-11 00:52:11 +01:00
sunshineinabox
4ae9921063
Update Avalonia About Window like requested in PR #6267 (#6278)
* Update About Window like requested in PR #6267

* Feedback

* Apply suggestions from code review

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

* Fix indents

---------

Co-authored-by: Isaac Marovitz <42140194+IsaacMarovitz@users.noreply.github.com>
2024-02-11 00:45:14 +01:00
gdkchan
6a8ac389e5
Fix mip offset/size for full 3D texture upload on Vulkan (#6294) 2024-02-11 00:41:17 +01:00
Mary Guillemard
8dd1eb333c
Add missing RID exclusions for linux-arm64 (#6298)
* Add missing RID exclusions for linux-arm64

Signed-off-by: Mary Guillemard <mary@mary.zone>

* Remove libsoundio.so from linux-arm64 deployment

This is a x86_64 library.

Signed-off-by: Mary Guillemard <mary@mary.zone>

---------

Signed-off-by: Mary Guillemard <mary@mary.zone>
2024-02-10 22:49:32 +01:00
Mary Guillemard
7dc3a62c14
ci: Enable Linux ARM64 on build and release (#6291)
* ci: Enable Linux ARM64 on build and release

Signed-off-by: Mary <mary@mary.zone>

* Address gdkchan comment

Signed-off-by: Mary <mary@mary.zone>

---------

Signed-off-by: Mary <mary@mary.zone>
2024-02-10 22:05:46 +01:00
Mary Guillemard
e59dba42ef
Set PointSize in shader on OpenGL (#6292)
Previously we were only doing it for Vulkan, but it turns out that
not setting it when PROGRAM_POINT_SIZE is set is considered UB
on OpenGL Core.

Signed-off-by: Mary <mary@mary.zone>
2024-02-10 20:27:17 +01:00
Mary Guillemard
bd6937ae5c
Make IOpenGLContext.HasContext context dependent (#6290)
This makes IOpenGLContext.HasContext not static and be implementable.

By doing this, we can support more than WGL and WGL.

This also allows the SDL2 headless version to run under Wayland.

Signed-off-by: Mary <mary@mary.zone>
2024-02-10 20:13:10 +01:00
jcm
b82e789d4f
Load custom SDL mappings from application data folder (#6295)
Co-authored-by: jcm <butt@butts.com>
2024-02-10 19:41:02 +01:00
gdkchan
4a6724622e
Force CPU copy for non-identity DMA remap (#6293) 2024-02-10 15:38:58 -03:00
Mary Guillemard
0c73eba3db
misc: Update to Ryujinx.Graphics.Nvdec.Dependencies 5.0.3-build14 (#6279)
Signed-off-by: Mary Guillemard <mary@mary.zone>
2024-02-10 11:23:44 +01:00
Mary Guillemard
a082e14ede Revert "Bump Ava (#6271)"
This reverts commit dfc0819e7273e6887135546d32e2fed6e6d26073.

X popup position broke entirely (my fault oops), waiting for next release with a fix
(see https://github.com/AvaloniaUI/Avalonia/pull/14551)
2024-02-08 22:14:56 +01:00
Isaac Marovitz
d29da11d5f
Remove SDC (#6275) 2024-02-08 20:36:59 +01:00
gdkchan
ea07328aea
LightningJit: Reduce stack usage for Arm32 code (#6245)
* Write/read guest state to context for sync points, stop reserving stack for them

* Fix UsedGprsMask not being updated when allocating with preferencing

* POP should be also considered a return
2024-02-08 20:17:47 +01:00
Isaac Marovitz
a0b3d82ee0
Remove Vic Reference to Host1x (#6277) 2024-02-08 20:01:03 +01:00
gdkchan
609de33b0b
Implement BGR10A2 render target format (#6273) 2024-02-08 19:52:38 +01:00
Isaac Marovitz
dfc0819e72
Bump Ava (#6271) 2024-02-08 19:45:18 +01:00
dependabot[bot]
d4803356bb
nuget: bump Microsoft.NET.Test.Sdk from 17.8.0 to 17.9.0 (#6265)
Bumps [Microsoft.NET.Test.Sdk](https://github.com/microsoft/vstest) from 17.8.0 to 17.9.0.
- [Release notes](https://github.com/microsoft/vstest/releases)
- [Changelog](https://github.com/microsoft/vstest/blob/main/docs/releases.md)
- [Commits](https://github.com/microsoft/vstest/compare/v17.8.0...v17.9.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-08 19:38:51 +01:00
sunshineinabox
459efd0db7
Replace Flex Panels in favor of Wrap Panels for Avalonia (#6267)
* Switch from using Flex panel to a Wrap panel for Grid view. This allows keyboard navigation.

* Stop using Flex panel in favor of Avalonia Wrap Panel.
2024-02-08 19:34:48 +01:00
gdkchan
8bb7a3fc97
Clamp vertex buffer size to mapped size if too high (#6272)
* Clamp vertex buffer size to mapped size if too high

* Update comment
2024-02-08 18:27:12 +01:00
Mary Guillemard
628d092fc6
chore: Update Ryujinx.SDL2-CS to 2.30.0 (#6261)
Also add linux-arm64 support.

Signed-off-by: Mary Guillemard <mary@mary.zone>
2024-02-07 22:43:44 +01:00
SamusAranX
6c90d50c8e
Redact usernames from logs (#6255)
* Redact usernames from logs

* Changed internal vars to private and applied naming rules

* Use Directory.GetParent() instead of DirectoryInfo

* Update src/Ryujinx.Common/Logging/Logger.cs

---------

Co-authored-by: Ac_K <Acoustik666@gmail.com>
2024-02-06 23:29:50 +01:00
riperiperi
d56bab1e24
AccountService: Cache token data (#6260)
* AccountService: Cache token data

This method appears to indicate that the token returned should be cached. I've made it so that it generates a token that lasts until its expiration time, and reuses it on subsequent calls.

* Private naming convention
2024-02-06 23:11:20 +01:00
sharmander
a37e2d6e44
Resolve an issue where changes to the main window's positioning could cause the application to crash if a modal was dismissed beforehand. (#6223) 2024-02-06 18:05:32 +01:00
dependabot[bot]
25123232bd
nuget: bump SPB from 0.0.4-build28 to 0.0.4-build32 (#6235)
Bumps [SPB](https://github.com/marysaka/SPB) from 0.0.4-build28 to 0.0.4-build32.
- [Release notes](https://github.com/marysaka/SPB/releases)
- [Commits](https://github.com/marysaka/SPB/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-05 15:39:45 +01:00
gdkchan
8927e0669f
Revert change to skip flush when range size is 0 (#6254) 2024-02-04 18:12:12 -03:00
gdkchan
bbed3b9926
Fix depth compare value for TLD4S shader instruction with offset (#6253)
* Fix depth compare value for TLD4S shader instruction with offset

* Shader cache version bump
2024-02-04 20:58:17 +01:00
gdkchan
24c8b0edc0
Remove component operand for texture gather with depth compare (#6247) 2024-02-04 11:10:45 +01:00
gdkchan
e5066449a5
Limit remote closed session removal to SM service (#6248) 2024-02-03 19:40:09 +01:00
gdkchan
d704bcd93b
Ensure SM service won't listen to closed sessions (#6246)
* Ensure SM service won't listen to closed sessions

* PR feedback
2024-02-02 20:56:51 -03:00
riperiperi
c94f0fbb83
Vulkan: Add Render Pass / Framebuffer Cache (#6182)
* Vulkan: Add Render Pass / Framebuffer Cache

Cache is owned by each texture view.

- Window's way of getting framebuffer cache for swapchain images is really messy - it creates a TextureView out of just a vk image view, with invalid info and no storage.

* Clear up limited use of alternate TextureView constructor

* Formatting and messages

* More formatting and messages

I apologize for `_colorsCanonical[index]?.Storage?.InsertReadToWriteBarrier`, the compiler made me do it

* Self review, change GetFramebuffer to GetPassAndFramebuffer

* Avoid allocations on Remove for HashTableSlim

* Member can be readonly

* Generate texture create info for swapchain images

* Improve hashcode

* Remove format, samples, size and isDepthStencil when possible

Tested in a number of games, seems fine.

* Removed load op barriers

These can be introduced later.

* Reintroduce UpdateModifications

Technically meant to be replaced by load op stuff.
2024-01-31 23:49:50 +01:00
dependabot[bot]
d1b30fbe08
nuget: bump Microsoft.IdentityModel.JsonWebTokens from 7.2.0 to 7.3.0 (#6227)
Bumps [Microsoft.IdentityModel.JsonWebTokens](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet) from 7.2.0 to 7.3.0.
- [Release notes](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/releases)
- [Changelog](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/compare/7.2.0...7.3.0)

---
updated-dependencies:
- dependency-name: Microsoft.IdentityModel.JsonWebTokens
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-31 23:46:48 +01:00
TSRBerry
4505a7f162
Fix opening the wrong log directory (#6220) 2024-01-30 17:52:45 +01:00
gdkchan
ccbbaddbcb
Fix exception when trying to read output pointer buffer size (#6221)
* Fix exception when trying to read output pointer buffer size

* Better name
2024-01-29 21:19:39 -03:00
Ac_K
8bf102d2cd
Cpu: Implement Vpadal and Vrintr instructions (#6185)
* Cpu: Implement Vpadal and Vrintr instructions

This PR superseed last instructions left in #2242.
Since I'm not a CPU guy I've just ported the code and nothing more.
Please be precise during review if there are some changes to be done.

It should fixes #1781

Co-Authored-By: Piyachet Kanda <piyachetk@gmail.com>

* Addresses gdkchan's feedback

* Addresses gdkchan's feedback 2

* Apply suggestions from code review

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

* another fix

* Update InstEmitSimdHelper32.cs

* Correct fix

* Addresses gdkchan's feedback

* Update CpuTestSimdCvt32.cs

---------

Co-authored-by: Piyachet Kanda <piyachetk@gmail.com>
Co-authored-by: gdkchan <gab.dark.100@gmail.com>
2024-01-30 00:51:05 +01:00
Ac_K
2adf031830
deps: Update Avalonia.Svg (#6218)
Updates `Avalonia.Svg` from 11.0.0.10 to 11.0.0.13
Updates `Avalonia.Svg.Skia` from 11.0.0.10 to 11.0.0.13

And reflect update changes as dependabot can't do it.

Superseed #6209
2024-01-29 23:22:42 +01:00
Isaac Marovitz
bb4a28b525
Ava UI: Mod Manager Fixes (Again) (#6187)
* Fix typo + Fix deleting from old dir

* Avoid double enumeration

* Break when parentDir is found

* Fix deleting non subdirectory mods

* Typo
2024-01-29 23:14:19 +01:00
merry
a8fbcdae9f
UI: Clarify Create Application Shortcut tooltip text (#6217) 2024-01-29 23:08:24 +01:00
TSRBerry
4e81ab4229
Avalonia: Fix dialog issues caused by 1.1.1105 (#6211)
* Set _contentDialogOverlayWindow to null

* Make CheckLaunchState async
2024-01-29 22:57:20 +01:00
gdkchan
4117c13377
Migrate friends service to new IPC (#6174)
* Migrate friends service to new IPC

* Add a note that the pointer buffer size and domain counts are wrong

* Wrong length

* Format whitespace

* PR feedback

* Fill in structs from PR feedback

* Missed that one

* Somehow forgot to save that one

* Fill in enums from PR review

* Language enum, NotificationTime

* Format whitespace

* Fix the warning
2024-01-29 22:45:40 +01:00
TSRBerry
20a392ad55
Remove events that trigger from a forked repository (#6213)
[skip ci]
2024-01-29 20:10:29 +01:00
TSRBerry
70fcba39de
Make config filename changable for releases & Log to Ryujinx directory if application directory is not writable (#4707)
* Remove GetBaseApplicationDirectory() & Move logs directory to user base path

We should assume the application directory might be write-protected.

* Use Ryujinx.sh in Ryujinx.desktop

This desktop file isn't really used right now,
so this changes effectively nothing.

* Use properties in ReleaseInformation.cs and add ConfigName property

* Configure config filename in Github workflows

* Add a separate config step for macOS

Because they use BSD sed instead of GNU sed

* Keep log directory at the old location for dev environments

* Add FileSystemUtils since Directory.Move() doesn't work across filesystems

Steal CopyDirectory code from https://learn.microsoft.com/en-us/dotnet/standard/io/how-to-copy-directories

* Fix "Open Logs folder" button pointing to the wrong directory

* Add execute permissions to Ryujinx.sh

* Fix missing newlines

* AppDataManager: Use FileSystemUtils.MoveDirectory()

* Make dotnet format happy

* Add a fallback for the logging directory
2024-01-29 19:58:18 +01:00
Ac_K
7795b662a9
Mod: Do LayeredFs loading Parallel to improve speed (#6180)
* Mod: Do LayeredFs loading Parallel to improve speed

This fixes and superseed #5672 due to inactivity, nothing more.
(See original PR for description)

Testing are welcome.

Close #5661

* Addresses gdkchan's feedback

* commit to test mako change

* Revert "commit to test mako change"

This reverts commit 8b0caa8a21db298db3dfcbe5b7e9029c4f066c46.
2024-01-29 16:32:34 +01:00
gdkchan
30bdc4544e
Fix NRE when calling GetSockName before Bind (#6206) 2024-01-29 16:28:32 +01:00
TSRBerry
f6475cca17
infra: Reformat README.md & add new generic Mako workflow (#5791)
* Adjust workflow paths to exclude all markdown files

* editorconfig: Add default charset and adjust indention for a few file types

* Reformat README.md and add a link to our documentation

* Add generic Mako workflow and remove old Mako steps

* editorconfig: Move charset change to a different PR

* Update compatibility stats

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

---------

Co-authored-by: Ac_K <Acoustik666@gmail.com>
2024-01-27 20:50:28 +01:00
dependabot[bot]
0335c52254
nuget: bump NetCoreServer from 7.0.0 to 8.0.7 (#6119)
Bumps [NetCoreServer](https://github.com/chronoxor/NetCoreServer) from 7.0.0 to 8.0.7.
- [Release notes](https://github.com/chronoxor/NetCoreServer/releases)
- [Commits](https://github.com/chronoxor/NetCoreServer/commits)

---
updated-dependencies:
- dependency-name: NetCoreServer
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-27 02:02:12 +01:00
gdkchan
b8d992e5a7
Allow skipping draws with broken pipeline variants on Vulkan (#5807)
* Allow skipping draws with broken pipeline variants on Vulkan

* Move IsLinked check to CreatePipeline

* Restore throw on error behaviour for background compile

* Can't remove SetAlphaTest pragmas yet

* Double new line
2024-01-26 13:58:57 -03:00
Isaac Marovitz
a620cbcc90
Ava UI: Mod Manager Fixes (#6179)
* Fix string format + Crash

* Better Logging

* Properly Delete Mods

Rename

* Catch when trying to access bad directory
2024-01-26 15:25:48 +01:00
Ac_K
cea204d48e
Fs: Log when Commit fails due to PathAlreadyInUse (#6178)
* Fs: Log when Commit fails due to PathAlreadyInUse

This fixes and superseed #5418, nothing more.
(See original PR for description)

Co-Authored-By: James R T <jamestiotio@gmail.com>

* Update IFileSystem.cs

---------

Co-authored-by: James R T <jamestiotio@gmail.com>
2024-01-26 02:43:15 +01:00
Isaac Marovitz
35fb409e85
Ava UI: Mod Manager (#4390)
* Let’s start again

* Read folders and such

* Remove Open Mod Folder menu items

* Fix folder opening, Selecting/deselecting

* She works

* Fix GTK

* AddMod

* Delete

* Fix duplicate entries

* Fix file check

* Avalonia 11

* Style fixes

* Final style fixes

* Might be too general

* Remove unnecessary using

* Enable new mods by default

* More cleanup

* Fix saving metadata

* Dont deseralise ModMetadata several times

* Avalonia I hate you

* Confirmation dialgoues

* Allow selecting multiple folders

* Add back secondary folder

* Search both paths

* Fix formatting

* Apply suggestions from code review

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

* Rename Title to Application

* Generic locale key

* Apply suggestions from code review

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

* Locale Updates

* GDK Feedback

* Fix

---------

Co-authored-by: Ac_K <Acoustik666@gmail.com>
2024-01-26 02:02:28 +01:00
Elijah
d7ec4308b4
Use driver name instead of vendor name in the status bar for Vulkan. (#6146)
* Replace vendor id lookup with driver name

* Create separate field for driver name, handle OpenGL

* Document changes in VulkanPhysicalDevice.cs

* Always display driver over vendor

* Replace Vulkan 1.2 requirement with VK_KHR_driver_properties

* Remove empty line

* Remove redundant unsafe block

* Apply suggestions from code review

---------

Co-authored-by: Ac_K <Acoustik666@gmail.com>
2024-01-26 01:07:20 +01:00
dependabot[bot]
fbdd390f90
nuget: bump System.Drawing.Common from 8.0.0 to 8.0.1 (#6117)
Bumps [System.Drawing.Common](https://github.com/dotnet/winforms) from 8.0.0 to 8.0.1.
- [Release notes](https://github.com/dotnet/winforms/releases)
- [Changelog](https://github.com/dotnet/winforms/blob/main/docs/release-activity.md)
- [Commits](https://github.com/dotnet/winforms/compare/v8.0.0...v8.0.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-26 00:26:44 +01:00
Isaac Marovitz
f33fea3287
Remove Custom Theming (#6175) 2024-01-26 00:20:50 +01:00
dependabot[bot]
5d3eea40be
nuget: bump DynamicData from 7.14.2 to 8.3.27 (#6028)
Bumps [DynamicData](https://github.com/reactiveui/DynamicData) from 7.14.2 to 8.3.27.
- [Release notes](https://github.com/reactiveui/DynamicData/releases)
- [Changelog](https://github.com/reactivemarbles/DynamicData/blob/main/ReleaseNotes.md)
- [Commits](https://github.com/reactiveui/DynamicData/compare/7.14.2...8.3.27)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Ac_K <Acoustik666@gmail.com>
2024-01-26 00:17:02 +01:00
Ac_K
cd37c75b82
Horizon: Implement arp:r and arp:w services (#5802)
* Horizon: Implement arp:r and arp:w services

* Fix formatting

* Remove HLE arp services

* Revert "Remove HLE arp services"

This reverts commit c576fcccadb963db56b96bacabd1c1ac7abfb1ab.

* Keep LibHac impl since it's used in bcat

* Addresses gdkchan's feedback

* ArpApi in PrepoIpcServer and remove LmApi

* Fix 2

* Fixes ArpApi init

* Fix encoding

* Update PrepoService.cs

* Fix prepo
2024-01-25 23:06:53 +01:00
TSRBerry
43705c2320
ssl: Work around missing remote hostname for authentication (#5988)
* ssl: Retrieve remote hostnames if the provided hostname is empty

 This avoids crashing with an AuthenticationException.

* ssl: Remove unused variable from RetrieveHostName
2024-01-25 20:10:51 +01:00
dependabot[bot]
371e6fa24c
nuget: bump Microsoft.IO.RecyclableMemoryStream from 2.3.2 to 3.0.0 (#6120)
Bumps [Microsoft.IO.RecyclableMemoryStream](https://github.com/Microsoft/Microsoft.IO.RecyclableMemoryStream) from 2.3.2 to 3.0.0.
- [Release notes](https://github.com/Microsoft/Microsoft.IO.RecyclableMemoryStream/releases)
- [Changelog](https://github.com/microsoft/Microsoft.IO.RecyclableMemoryStream/blob/master/CHANGES.md)
- [Commits](https://github.com/Microsoft/Microsoft.IO.RecyclableMemoryStream/compare/2.3.2...3.0.0)

---
updated-dependencies:
- dependency-name: Microsoft.IO.RecyclableMemoryStream
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-25 19:41:24 +01:00
dependabot[bot]
1d9b63cc6a
nuget: bump Microsoft.CodeAnalysis.CSharp from 4.7.0 to 4.8.0 (#6118)
Bumps [Microsoft.CodeAnalysis.CSharp](https://github.com/dotnet/roslyn) from 4.7.0 to 4.8.0.
- [Release notes](https://github.com/dotnet/roslyn/releases)
- [Changelog](https://github.com/dotnet/roslyn/blob/main/docs/Breaking%20API%20Changes.md)
- [Commits](https://github.com/dotnet/roslyn/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-25 19:35:10 +01:00
riperiperi
795539bc82
Vulkan: Use staging buffer for temporary constants (#6168)
* Vulkan: Use staging buffer for temporary constants

Helper shaders and post processing effects typically need some parameters to tell them what to do, which we pass via constant buffers that are created and destroyed each time.

This can vary in cost between different Vulkan drivers. It shows up on profiles on mesa and MoltenVK, so it's worth avoiding. Some games only do it once (BlitColor for present), others multiple times. It's also done for post processing filters and FSR upscaling, which creates two buffers.

For mirrors, I added the ability to reserve a range on the staging buffer for use as any type of binding. This PR allows these constant buffers to be instead temporarily allocated on the staging buffer, skipping allocation and buffer management costs entirely.

Two temporary allocations do remain:
- DrawTexture, because it doesn't have access to the command buffer scope
- Index buffer indirect conversion, because one of them is a storage buffer and thus is a little more complicated.

There's a small cost in that the uniform buffer takes up more space due to alignment requirements. At worst that's 256 bytes (on a GTX 1070) but more modern GPUs should have a better time.

Worth testing across different games and post effects to make sure they still work.

* Use temporary buffer for ConvertIndexBufferIndirect

* Simplify alignment passing for now

* Fix shader params length for CopyIncompatibleFormats

* Set data for helpershaders without overlap checks

The data is in the staging buffer, so its usage range is guarded using that.
2024-01-25 19:29:53 +01:00
Isaac Marovitz
dd2e851e95
OpenTK (#6143) 2024-01-25 19:25:47 +01:00
gdkchan
2ca70eb9a0
Implement SQSHL (immediate) CPU instruction (#6155)
* Implement SQSHL (immediate) CPU instruction

* Fix test
2024-01-24 23:50:43 +01:00
riperiperi
6575952432
Vulkan: Enumerate Query Pool properly (#6167)
Turns out that ElementAt for Queue<T> runs the default implementation as it doesn't implement IList, which enumerates elements of the queue up to the given index. This code was creating `count` enumerators and iterating way more queue items than it needed to at higher counts. The solution is just to use one enumerator and break out of the loop when we get the count that we need.

3.5% of backend time was being spent _just_ enumerating at the usual spot in SMO.
2024-01-24 19:33:52 -03:00
gdkchan
9a28ba72b1
Use unix timestamps on GetFileTimeStampRaw (#6169) 2024-01-24 19:26:59 -03:00
Alex0007
34a9922b57
Fix architecture preference for MacOS game shortcuts (#6145)
* Fix architecture preference for MacOS game shortcuts

* Detect arch and then pass it to script

Co-authored-by: jcm <john.moody@coloradocollege.edu>

* Remove old script write call in `CreateShortcutMacos`

* Turn launch script into EmbeddedResource

* Added final newline

---------

Co-authored-by: jcm <john.moody@coloradocollege.edu>
2024-01-22 23:10:25 +01:00
gdkchan
4df22eb867
Fix missing data for new copy dependency textures with mismatching size (#6161) 2024-01-22 17:42:26 -03:00
gdkchan
f241f88558
Add a separate device memory manager (#6153)
* Add a separate device memory manager

* Still need this

* Device writes are always tracked

* Device writes are always tracked (2)

* Rename more instances of gmm to mm
2024-01-22 17:14:46 -03:00
riperiperi
90455a05e6
Input: Improve controller identification (#6029)
* Input: Improve controller identification

Controllers were identified before by a combination of their _global_ index in the list of controllers and their GUID. The problem is, disconnecting and reconnecting a controller can change its global index; the controller can appear at the end. This would give it another ID, and the controller would need to be reconfigured.

This happened to me a lot with a switch pro controller and a USB game controller, it was essentially random which appeared first. Now, it consistently detects them.

This PR changes the controller identification to be a combination of an index of controllers with the same GUID (generally 0), and its GUID. It also reworks managing the list of controllers to properly consider instance IDs.

This also changes the NpadManager to attempt to reuse old controllers when refreshing input configuration, which can prevent input from going dead for seconds whenever a controller connects or disconnects (and the switch pro controller just entirely dying).

Testing with different controller types, OS and Avalonia is welcome. Remember that the target is connecting a ton of controllers, and pulling/reconnecting them.

* Remove double empty line
2024-01-22 17:02:44 -03:00
gdkchan
edc76883db
Fix integer overflow on downsample surround to stereo (#6160) 2024-01-21 21:11:46 +01:00
gdkchan
427b7d06b5
Implement a new JIT for Arm devices (#6057)
* Implement a new JIT for Arm devices

* Auto-format

* Make a lot of Assembler members read-only

* More read-only

* Fix more warnings

* ObjectDisposedException.ThrowIf

* New JIT cache for platforms that enforce W^X, currently unused

* Remove unused using

* Fix assert

* Pass memory manager type around

* Safe memory manager mode support + other improvements

* Actual safe memory manager mode masking support

* PR feedback
2024-01-20 11:11:28 -03:00
riperiperi
331c07807f
Vulkan: Use templates for descriptor updates (#6014)
* WIP: Descriptor template update

* Make configurable

* Wording

* Simplify template creation

* Whitespace

* UTF-8 whatever

* Leave only templated path, better template updater
2024-01-20 11:07:33 -03:00
Steveice10
a772b073ec
Support portable mode using the macOS app bundle. (#6147)
* Support portable mode using the macOS app bundle.

* Apply suggestion

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

---------

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>
2024-01-20 03:09:51 +01:00
gdkchan
870d9599cc
Change shader cache init wait method (#6131)
* Change shader cache init wait method

* Make field readonly
2024-01-18 14:17:38 -03:00
gdkchan
2dbbc9bc05
Move most of signal handling to Ryujinx.Cpu project (#6128)
* Move most of signal handling to Ryujinx.Cpu project

* Format whitespace

* Remove unused member

* Format whitespace

* This does not need to be public anymore
2024-01-18 14:08:40 -03:00
Isaac Marovitz
72634c80f4
Ava UI: Update Ava & Friends (#6109)
* Update Ava & Friends

* FA 2.0.5

* Ava 11.0.7

* Fix
2024-01-17 23:50:31 +01:00
riperiperi
bebd8eb822
Vulkan: Cache delegate for EndRenderPass (#6132)
This prevents a small allocation each time this method is called. This is a top 3 SOH allocation during gameplay in most games, and eliminating it is pretty free.
2024-01-16 13:22:20 +01:00
gdkchan
f4b74e9ce1
Fix vertex buffer size when switching between inline and state draw parameters (#6101)
* Fix vertex buffer size when switching between inline and state draw parameters

* Format whitespace
2024-01-14 09:37:19 +01:00
Isaac Marovitz
4e19b36ad7
CI: Dependabot Groups (#6110)
* CI: Dependabot Groups

* NUnit

* Limit of 10

* Whoops

* Missing wildcard

* Remove Ryujank group
2024-01-13 15:28:57 +01:00
gdkchan
b16923a902
Revert Apple hypervisor force ordered memory change (#6068) 2024-01-13 11:58:09 +01:00
TSRBerry
7e58b21f3d
Fix Amiibo regression and some minor code improvements (#6107)
* Remove redundant code and fix small issues

* Log amiibo exceptions

* Add more checks when getting Amiibo data

* Fall back to online data if local file is inaccessible

* Make dotnet format happy
2024-01-13 11:45:38 +01:00
Isaac Marovitz
4fbc978e73
Switch to Microsoft.IdentityModel.JsonWebTokens (#6108)
* Switch to `Microsoft.IdentityModel.JsonWebTokens`

* Formatting
2024-01-13 11:39:00 +01:00
Isaac Marovitz
1a45dc8df8
Ava UI: RTL Language Support (#5619)
* Add Hebrew locale files to ItemGroups

* Align all windows RTL for testing

This should be controlled with a binding that selects the appropriate layout based on current language

* Update FlowDirection as Locale changes

* Fix Settings NavigationViewItem FlowDirection

* Fix remaining text

* Fix input menu directionality

* Fix RTL not rendering

* Fix rebase errors
2024-01-13 01:42:42 +01:00
Isaac Marovitz
f037fcba9a
Ava UI: Better Controller Applet (#5756)
* Start work on better Controller Applet

* Don’t require title

* UI improvements

* Border around TBD area

* Formatting

* Better SVGs

* Add missing margin

* Use Locale

* Rename function

* Make buttons ourselves

* Make the buttons do shit

* Formatting

* Adjust SVGs

* Fix Open Settings Window

* Make field readonly

* Final tweaks

* Update src/Ryujinx.Ava/UI/Applet/AvaHostUiHandler.cs

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

* Update src/Ryujinx.Ava/UI/Applet/ControllerAppletDialog.axaml.cs

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

* Apply suggestions from code review

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

* Update src/Ryujinx.Ava/UI/Applet/ControllerAppletDialog.axaml.cs

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

* Move icons to Ava project

* Reorder arguments

* Try to focus Settings Window

* Fix icons

Project shenangians

* Add ContentDialogHelper.ShowWindowAsync method

* Fix closed SettingsWindow reference in MainWindow

* Fix SettingsWindow dialog

* Suggestion

---------

Co-authored-by: Ac_K <Acoustik666@gmail.com>
Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>
2024-01-13 01:41:57 +01:00
1430 changed files with 69051 additions and 19801 deletions

View File

@ -17,8 +17,8 @@ tab_width = 4
end_of_line = lf
insert_final_newline = true
# JSON files
[*.json]
# Markdown, JSON, YAML, props and csproj files
[*.{md,json,yml,props,csproj}]
# Indentation and spacing
indent_size = 2
@ -259,12 +259,12 @@ dotnet_diagnostic.CA1861.severity = none
# Disable "Prefer using 'string.Equals(string, StringComparison)' to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'"
dotnet_diagnostic.CA1862.severity = none
[src/Ryujinx.HLE/HOS/Services/**.cs]
# Disable "mark members as static" rule for services
[src/Ryujinx/UI/ViewModels/**.cs]
# Disable "mark members as static" rule for ViewModels
dotnet_diagnostic.CA1822.severity = none
[src/Ryujinx.Ava/UI/ViewModels/**.cs]
# Disable "mark members as static" rule for ViewModels
[src/Ryujinx.HLE/HOS/Services/**.cs]
# Disable "mark members as static" rule for services
dotnet_diagnostic.CA1822.severity = none
[src/Ryujinx.Tests/Cpu/*.cs]

View File

@ -1,6 +1,7 @@
name: Feature Request
description: Suggest a new feature for Ryujinx.
title: "[Feature Request]"
labels: enhancement
body:
- type: textarea
id: overview

View File

@ -7,18 +7,34 @@ updates:
labels:
- "infra"
reviewers:
- marysaka
- TSRBerry
commit-message:
prefix: "ci"
- package-ecosystem: nuget
directory: /
open-pull-requests-limit: 5
open-pull-requests-limit: 10
schedule:
interval: daily
labels:
- "infra"
reviewers:
- marysaka
- TSRBerry
commit-message:
prefix: nuget
groups:
Avalonia:
patterns:
- "*Avalonia*"
Silk.NET:
patterns:
- "Silk.NET*"
OpenTK:
patterns:
- "OpenTK*"
SixLabors:
patterns:
- "SixLabors*"
NUnit:
patterns:
- "NUnit*"

2
.github/labeler.yml vendored
View File

@ -20,7 +20,7 @@ gpu:
gui:
- changed-files:
- any-glob-to-any-file: ['src/Ryujinx/**', 'src/Ryujinx.Ui.Common/**', 'src/Ryujinx.Ui.LocaleGenerator/**', 'src/Ryujinx.Ava/**']
- any-glob-to-any-file: ['src/Ryujinx/**', 'src/Ryujinx.UI.Common/**', 'src/Ryujinx.UI.LocaleGenerator/**', 'src/Ryujinx.Gtk3/**']
horizon:
- changed-files:

View File

@ -1,31 +1,24 @@
audio:
- marysaka
cpu:
- gdkchan
- riperiperi
- marysaka
- LDj3SNuD
gpu:
- gdkchan
- riperiperi
- marysaka
gui:
- Ack77
- emmauss
- TSRBerry
- marysaka
horizon:
- gdkchan
- Ack77
- marysaka
- TSRBerry
infra:
- marysaka
- TSRBerry
default:

View File

@ -10,28 +10,17 @@ env:
jobs:
build:
name: ${{ matrix.OS_NAME }} (${{ matrix.configuration }})
runs-on: ${{ matrix.os }}
name: ${{ matrix.platform.name }} (${{ matrix.configuration }})
runs-on: ${{ matrix.platform.os }}
timeout-minutes: 45
strategy:
matrix:
os: [ubuntu-latest, macOS-latest, windows-latest]
configuration: [Debug, Release]
include:
- os: ubuntu-latest
OS_NAME: Linux x64
DOTNET_RUNTIME_IDENTIFIER: linux-x64
RELEASE_ZIP_OS_NAME: linux_x64
- os: macOS-latest
OS_NAME: macOS x64
DOTNET_RUNTIME_IDENTIFIER: osx-x64
RELEASE_ZIP_OS_NAME: osx_x64
- os: windows-latest
OS_NAME: Windows x64
DOTNET_RUNTIME_IDENTIFIER: win-x64
RELEASE_ZIP_OS_NAME: win_x64
platform:
- { name: win-x64, os: windows-latest, zip_os_name: win_x64 }
- { name: linux-x64, os: ubuntu-latest, zip_os_name: linux_x64 }
- { name: linux-arm64, os: ubuntu-latest, zip_os_name: linux_arm64 }
- { name: osx-x64, os: macos-13, zip_os_name: osx_x64 }
fail-fast: false
steps:
@ -40,7 +29,7 @@ jobs:
- uses: actions/setup-dotnet@v4
with:
global-json-file: global.json
- name: Overwrite csc problem matcher
run: echo "::add-matcher::.github/csc.json"
@ -49,6 +38,16 @@ jobs:
run: echo "result=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
shell: bash
- name: Change config filename
run: sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/PRConfig\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs
shell: bash
if: github.event_name == 'pull_request' && matrix.platform.os != 'macos-13'
- name: Change config filename for macOS
run: sed -r -i '' 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/PRConfig\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs
shell: bash
if: github.event_name == 'pull_request' && matrix.platform.os == 'macos-13'
- name: Build
run: dotnet build -c "${{ matrix.configuration }}" -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER
@ -58,46 +57,47 @@ jobs:
commands: dotnet test --no-build -c "${{ matrix.configuration }}"
timeout-minutes: 10
retry-codes: 139
if: matrix.platform.name != 'linux-arm64'
- name: Publish Ryujinx
run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.DOTNET_RUNTIME_IDENTIFIER }}" -o ./publish -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:DebugType=embedded -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER src/Ryujinx --self-contained true
if: github.event_name == 'pull_request' && matrix.os != 'macOS-latest'
run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.platform.name }}" -o ./publish -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:DebugType=embedded -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER src/Ryujinx --self-contained true
if: github.event_name == 'pull_request' && matrix.platform.os != 'macos-13'
- name: Publish Ryujinx.Headless.SDL2
run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.DOTNET_RUNTIME_IDENTIFIER }}" -o ./publish_sdl2_headless -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:DebugType=embedded -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER src/Ryujinx.Headless.SDL2 --self-contained true
if: github.event_name == 'pull_request' && matrix.os != 'macOS-latest'
run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.platform.name }}" -o ./publish_sdl2_headless -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:DebugType=embedded -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER src/Ryujinx.Headless.SDL2 --self-contained true
if: github.event_name == 'pull_request' && matrix.platform.os != 'macos-13'
- name: Publish Ryujinx.Ava
run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.DOTNET_RUNTIME_IDENTIFIER }}" -o ./publish_ava -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:DebugType=embedded -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER src/Ryujinx.Ava --self-contained true
if: github.event_name == 'pull_request' && matrix.os != 'macOS-latest'
- name: Publish Ryujinx.Gtk3
run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.platform.name }}" -o ./publish_gtk -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:DebugType=embedded -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER src/Ryujinx.Gtk3 --self-contained true
if: github.event_name == 'pull_request' && matrix.platform.os != 'macos-13'
- name: Set executable bit
run: |
chmod +x ./publish/Ryujinx ./publish/Ryujinx.sh
chmod +x ./publish_sdl2_headless/Ryujinx.Headless.SDL2 ./publish_sdl2_headless/Ryujinx.sh
chmod +x ./publish_ava/Ryujinx.Ava ./publish_ava/Ryujinx.sh
if: github.event_name == 'pull_request' && matrix.os == 'ubuntu-latest'
chmod +x ./publish_gtk/Ryujinx.Gtk3 ./publish_gtk/Ryujinx.sh
if: github.event_name == 'pull_request' && matrix.platform.os == 'ubuntu-latest'
- name: Upload Ryujinx artifact
uses: actions/upload-artifact@v4
with:
name: ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.RELEASE_ZIP_OS_NAME }}
name: ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.platform.zip_os_name }}
path: publish
if: github.event_name == 'pull_request' && matrix.os != 'macOS-latest'
if: github.event_name == 'pull_request' && matrix.platform.os != 'macos-13'
- name: Upload Ryujinx.Headless.SDL2 artifact
uses: actions/upload-artifact@v4
with:
name: sdl2-ryujinx-headless-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.RELEASE_ZIP_OS_NAME }}
name: sdl2-ryujinx-headless-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.platform.zip_os_name }}
path: publish_sdl2_headless
if: github.event_name == 'pull_request' && matrix.os != 'macOS-latest'
if: github.event_name == 'pull_request' && matrix.platform.os != 'macos-13'
- name: Upload Ryujinx.Ava artifact
- name: Upload Ryujinx.Gtk3 artifact
uses: actions/upload-artifact@v4
with:
name: ava-ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.RELEASE_ZIP_OS_NAME }}
path: publish_ava
if: github.event_name == 'pull_request' && matrix.os != 'macOS-latest'
name: gtk-ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.platform.zip_os_name }}
path: publish_gtk
if: github.event_name == 'pull_request' && matrix.platform.os != 'macos-13'
build_macos:
name: macOS Universal (${{ matrix.configuration }})
@ -135,19 +135,24 @@ jobs:
id: git_short_hash
run: echo "result=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
- name: Publish macOS Ryujinx.Ava
- name: Change config filename
run: sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/PRConfig\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs
shell: bash
if: github.event_name == 'pull_request'
- name: Publish macOS Ryujinx
run: |
./distribution/macos/create_macos_build_ava.sh . publish_tmp_ava publish_ava ./distribution/macos/entitlements.xml "${{ env.RYUJINX_BASE_VERSION }}" "${{ steps.git_short_hash.outputs.result }}" "${{ matrix.configuration }}" "-p:ExtraDefineConstants=DISABLE_UPDATER"
./distribution/macos/create_macos_build_ava.sh . publish_tmp publish ./distribution/macos/entitlements.xml "${{ env.RYUJINX_BASE_VERSION }}" "${{ steps.git_short_hash.outputs.result }}" "${{ matrix.configuration }}" "-p:ExtraDefineConstants=DISABLE_UPDATER"
- name: Publish macOS Ryujinx.Headless.SDL2
run: |
./distribution/macos/create_macos_build_headless.sh . publish_tmp_headless publish_headless ./distribution/macos/entitlements.xml "${{ env.RYUJINX_BASE_VERSION }}" "${{ steps.git_short_hash.outputs.result }}" "${{ matrix.configuration }}" "-p:ExtraDefineConstants=DISABLE_UPDATER"
- name: Upload Ryujinx.Ava artifact
- name: Upload Ryujinx artifact
uses: actions/upload-artifact@v4
with:
name: ava-ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-macos_universal
path: "publish_ava/*.tar.gz"
name: ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-macos_universal
path: "publish/*.tar.gz"
if: github.event_name == 'pull_request'
- name: Upload Ryujinx.Headless.SDL2 artifact

View File

@ -8,7 +8,7 @@ on:
- '!.github/**'
- '!*.yml'
- '!*.config'
- '!README.md'
- '!*.md'
- '.github/workflows/*.yml'
permissions:

28
.github/workflows/dotnet.yml vendored Normal file
View File

@ -0,0 +1,28 @@
# This workflow will build a .NET project
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-net
name: .NET
on:
push:
branches: [ "libryujinx_bionic" ]
pull_request:
branches: [ "libryujinx_bionic" ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 9.0.x
- name: Restore dependencies
run: dotnet restore
- name: Build
run: dotnet build -c Release -o build
- name: Test
run: dotnet test --no-build --verbosity normal

View File

@ -51,38 +51,76 @@ jobs:
- name: Restore Nuget packages
# With .NET 8.0.100, Microsoft.NET.ILLink.Tasks isn't restored by default and only seems to appears when publishing.
# So we just publish to grab the dependencies
run: dotnet publish -c Release -r linux-x64 Ryujinx/${{ env.RYUJINX_PROJECT_FILE }} --self-contained
run: |
dotnet publish -c Release -r linux-x64 Ryujinx/${{ env.RYUJINX_PROJECT_FILE }} --self-contained
dotnet publish -c Release -r linux-arm64 Ryujinx/${{ env.RYUJINX_PROJECT_FILE }} --self-contained
- name: Generate nuget_sources.json
shell: python
run: |
import hashlib
from pathlib import Path
import base64
import binascii
import json
import os
import urllib.request
sources = []
for path in Path(os.environ['NUGET_PACKAGES']).glob('**/*.nupkg.sha512'):
name = path.parent.parent.name
version = path.parent.name
filename = '{}.{}.nupkg'.format(name, version)
url = 'https://api.nuget.org/v3-flatcontainer/{}/{}/{}'.format(name, version, filename)
with path.open() as fp:
sha512 = binascii.hexlify(base64.b64decode(fp.read())).decode('ascii')
def create_source_from_external(name, version):
full_dir_path = Path(os.environ["NUGET_PACKAGES"]).joinpath(name).joinpath(version)
os.makedirs(full_dir_path, exist_ok=True)
sources.append({
'type': 'file',
'url': url,
'sha512': sha512,
'dest': os.environ['NUGET_SOURCES_DESTDIR'],
'dest-filename': filename,
})
filename = "{}.{}.nupkg".format(name, version)
url = "https://api.nuget.org/v3-flatcontainer/{}/{}/{}".format(
name, version, filename
)
with open('flathub/nuget_sources.json', 'w') as fp:
json.dump(sources, fp, indent=4)
print(f"Processing {url}...")
response = urllib.request.urlopen(url)
sha512 = hashlib.sha512(response.read()).hexdigest()
return {
"type": "file",
"url": url,
"sha512": sha512,
"dest": os.environ["NUGET_SOURCES_DESTDIR"],
"dest-filename": filename,
}
has_added_x64_apphost = False
for path in Path(os.environ["NUGET_PACKAGES"]).glob("**/*.nupkg.sha512"):
name = path.parent.parent.name
version = path.parent.name
filename = "{}.{}.nupkg".format(name, version)
url = "https://api.nuget.org/v3-flatcontainer/{}/{}/{}".format(
name, version, filename
)
with path.open() as fp:
sha512 = binascii.hexlify(base64.b64decode(fp.read())).decode("ascii")
sources.append(
{
"type": "file",
"url": url,
"sha512": sha512,
"dest": os.environ["NUGET_SOURCES_DESTDIR"],
"dest-filename": filename,
}
)
# .NET will not add current installed application host to the list, force inject it here.
if not has_added_x64_apphost and name.startswith('microsoft.netcore.app.host'):
sources.append(create_source_from_external("microsoft.netcore.app.host.linux-x64", version))
has_added_x64_apphost = True
with open("flathub/nuget_sources.json", "w") as fp:
json.dump(sources, fp, indent=4)
- name: Update flatpak metadata
id: metadata

41
.github/workflows/mako.yml vendored Normal file
View File

@ -0,0 +1,41 @@
name: Mako
on:
discussion:
types: [created, edited, answered, unanswered, category_changed]
discussion_comment:
types: [created, edited]
gollum:
issue_comment:
types: [created, edited]
issues:
types: [opened, edited, reopened, pinned, milestoned, demilestoned, assigned, unassigned, labeled, unlabeled]
pull_request_target:
types: [opened, edited, reopened, synchronize, ready_for_review, assigned, unassigned]
jobs:
tasks:
name: Run Ryujinx tasks
permissions:
actions: read
contents: read
discussions: write
issues: write
pull-requests: write
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
if: github.event_name == 'pull_request_target'
with:
# Ensure we pin the source origin as pull_request_target run under forks.
fetch-depth: 0
repository: Ryujinx/Ryujinx
ref: master
- name: Run Mako command
uses: Ryujinx/Ryujinx-Mako@master
with:
command: exec-ryujinx-tasks
args: --event-name "${{ github.event_name }}" --event-path "${{ github.event_path }}" -w "${{ github.workspace }}" "${{ github.repository }}" "${{ github.run_id }}"
app_id: ${{ secrets.MAKO_APP_ID }}
private_key: ${{ secrets.MAKO_PRIVATE_KEY }}
installation_id: ${{ secrets.MAKO_INSTALLATION_ID }}

View File

@ -39,24 +39,24 @@ jobs:
return core.error(`No artifacts found`);
}
let body = `Download the artifacts for this pull request:\n`;
let hidden_avalonia_artifacts = `\n\n <details><summary>Experimental GUI (Avalonia)</summary>\n`;
let hidden_gtk_artifacts = `\n\n <details><summary>Old GUI (GTK3)</summary>\n`;
let hidden_headless_artifacts = `\n\n <details><summary>GUI-less (SDL2)</summary>\n`;
let hidden_debug_artifacts = `\n\n <details><summary>Only for Developers</summary>\n`;
for (const art of artifacts) {
if(art.name.includes('Debug')) {
hidden_debug_artifacts += `\n* [${art.name}](https://nightly.link/${owner}/${repo}/actions/artifacts/${art.id}.zip)`;
} else if(art.name.includes('ava-ryujinx')) {
hidden_avalonia_artifacts += `\n* [${art.name}](https://nightly.link/${owner}/${repo}/actions/artifacts/${art.id}.zip)`;
} else if(art.name.includes('gtk-ryujinx')) {
hidden_gtk_artifacts += `\n* [${art.name}](https://nightly.link/${owner}/${repo}/actions/artifacts/${art.id}.zip)`;
} else if(art.name.includes('sdl2-ryujinx-headless')) {
hidden_headless_artifacts += `\n* [${art.name}](https://nightly.link/${owner}/${repo}/actions/artifacts/${art.id}.zip)`;
} else {
body += `\n* [${art.name}](https://nightly.link/${owner}/${repo}/actions/artifacts/${art.id}.zip)`;
}
}
hidden_avalonia_artifacts += `\n</details>`;
hidden_gtk_artifacts += `\n</details>`;
hidden_headless_artifacts += `\n</details>`;
hidden_debug_artifacts += `\n</details>`;
body += hidden_avalonia_artifacts;
body += hidden_gtk_artifacts;
body += hidden_headless_artifacts;
body += hidden_debug_artifacts;

View File

@ -21,27 +21,8 @@ jobs:
repository: Ryujinx/Ryujinx
ref: master
- name: Checkout Ryujinx-Mako
uses: actions/checkout@v4
with:
repository: Ryujinx/Ryujinx-Mako
ref: master
path: '.ryujinx-mako'
- name: Setup Ryujinx-Mako
uses: ./.ryujinx-mako/.github/actions/setup-mako
- name: Update labels based on changes
uses: actions/labeler@v5
with:
sync-labels: true
dot: true
- name: Assign reviewers
run: |
poetry -n -C .ryujinx-mako run ryujinx-mako update-reviewers ${{ github.repository }} ${{ github.event.pull_request.number }} .github/reviewers.yml
shell: bash
env:
MAKO_APP_ID: ${{ secrets.MAKO_APP_ID }}
MAKO_PRIVATE_KEY: ${{ secrets.MAKO_PRIVATE_KEY }}
MAKO_INSTALLATION_ID: ${{ secrets.MAKO_INSTALLATION_ID }}

View File

@ -10,7 +10,7 @@ on:
- '*.yml'
- '*.json'
- '*.config'
- 'README.md'
- '*.md'
concurrency: release
@ -44,30 +44,34 @@ jobs:
sha: context.sha
})
- name: Create release
uses: ncipollo/release-action@v1
with:
name: ${{ steps.version_info.outputs.build_version }}
tag: ${{ steps.version_info.outputs.build_version }}
body: "For more information about this release please check out the official [Changelog](https://github.com/Ryujinx/Ryujinx/wiki/Changelog)."
omitBodyDuringUpdate: true
owner: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}
repo: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}
token: ${{ secrets.RELEASE_TOKEN }}
release:
name: Release ${{ matrix.OS_NAME }}
runs-on: ${{ matrix.os }}
name: Release for ${{ matrix.platform.name }}
runs-on: ${{ matrix.platform.os }}
timeout-minutes: ${{ fromJSON(vars.JOB_TIMEOUT) }}
strategy:
matrix:
os: [ ubuntu-latest, windows-latest ]
include:
- os: ubuntu-latest
OS_NAME: Linux x64
DOTNET_RUNTIME_IDENTIFIER: linux-x64
RELEASE_ZIP_OS_NAME: linux_x64
- os: windows-latest
OS_NAME: Windows x64
DOTNET_RUNTIME_IDENTIFIER: win-x64
RELEASE_ZIP_OS_NAME: win_x64
platform:
- { name: win-x64, os: windows-latest, zip_os_name: win_x64 }
- { name: linux-x64, os: ubuntu-latest, zip_os_name: linux_x64 }
- { name: linux-arm64, os: ubuntu-latest, zip_os_name: linux_arm64 }
steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v4
with:
global-json-file: global.json
- name: Overwrite csc problem matcher
run: echo "::add-matcher::.github/csc.json"
@ -85,6 +89,7 @@ jobs:
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/Config\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs
shell: bash
- name: Create output dir
@ -92,42 +97,36 @@ jobs:
- name: Publish
run: |
dotnet publish -c Release -r "${{ matrix.DOTNET_RUNTIME_IDENTIFIER }}" -o ./publish_gtk/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx --self-contained true
dotnet publish -c Release -r "${{ matrix.DOTNET_RUNTIME_IDENTIFIER }}" -o ./publish_sdl2_headless/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx.Headless.SDL2 --self-contained true
dotnet publish -c Release -r "${{ matrix.DOTNET_RUNTIME_IDENTIFIER }}" -o ./publish_ava/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx.Ava --self-contained true
dotnet publish -c Release -r "${{ matrix.platform.name }}" -o ./publish_ava/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx --self-contained true
dotnet publish -c Release -r "${{ matrix.platform.name }}" -o ./publish_sdl2_headless/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx.Headless.SDL2 --self-contained true
- name: Packing Windows builds
if: matrix.os == 'windows-latest'
if: matrix.platform.os == 'windows-latest'
run: |
pushd publish_gtk
7z a ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-win_x64.zip publish
pushd publish_ava
cp publish/Ryujinx.exe publish/Ryujinx.Ava.exe
7z a ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip publish
7z a ../release_output/test-ava-ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip publish
popd
pushd publish_sdl2_headless
7z a ../release_output/sdl2-ryujinx-headless-${{ steps.version_info.outputs.build_version }}-win_x64.zip publish
popd
pushd publish_ava
7z a ../release_output/test-ava-ryujinx-${{ steps.version_info.outputs.build_version }}-win_x64.zip publish
7z a ../release_output/sdl2-ryujinx-headless-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip publish
popd
shell: bash
- name: Packing Linux builds
if: matrix.os == 'ubuntu-latest'
if: matrix.platform.os == 'ubuntu-latest'
run: |
pushd publish_gtk
chmod +x publish/Ryujinx.sh publish/Ryujinx
tar -czvf ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz publish
pushd publish_ava
cp publish/Ryujinx publish/Ryujinx.Ava
chmod +x publish/Ryujinx.sh publish/Ryujinx.Ava publish/Ryujinx
tar -czvf ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz publish
tar -czvf ../release_output/test-ava-ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz publish
popd
pushd publish_sdl2_headless
chmod +x publish/Ryujinx.sh publish/Ryujinx.Headless.SDL2
tar -czvf ../release_output/sdl2-ryujinx-headless-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz publish
popd
pushd publish_ava
chmod +x publish/Ryujinx.sh publish/Ryujinx.Ava
tar -czvf ../release_output/test-ava-ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz publish
tar -czvf ../release_output/sdl2-ryujinx-headless-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz publish
popd
shell: bash
@ -186,12 +185,13 @@ jobs:
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/Config\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs
shell: bash
- name: Publish macOS Ryujinx.Ava
- name: Publish macOS Ryujinx
run: |
./distribution/macos/create_macos_build_ava.sh . publish_tmp_ava publish_ava ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.build_version }}" "${{ steps.version_info.outputs.git_short_hash }}" Release
- name: Publish macOS Ryujinx.Headless.SDL2
run: |
./distribution/macos/create_macos_build_headless.sh . publish_tmp_headless publish_headless ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.build_version }}" "${{ steps.version_info.outputs.git_short_hash }}" Release

67
.gitignore vendored
View File

@ -47,7 +47,6 @@ build/
*.vssscc
.builds
*.pidb
*.log
*.scc
# Visual C++ cache files
@ -176,3 +175,69 @@ PublishProfiles/
# Glade backup files
*.glade~
src/MeloNX/MeloNX/Dependencies/Dynamic Libraries/Ryujinx.Headless.SDL2.dylib
# SWIFT GITIGNORE
# Xcode
#
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
## User settings
xcuserdata/
## Obj-C/Swift specific
*.hmap
## App packaging
*.ipa
*.dSYM.zip
*.dSYM
## Playgrounds
timeline.xctimeline
playground.xcworkspace
# Swift Package Manager
#
# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
# Packages/
# Package.pins
# Package.resolved
# *.xcodeproj
#
# Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata
# hence it is not needed unless you have added a package configuration file to your project
# .swiftpm
.build/
# CocoaPods
#
# We recommend against adding the Pods directory to your .gitignore. However
# you should judge for yourself, the pros and cons are mentioned at:
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
#
# Pods/
#
# Add this line if you want to avoid checking in source code from the Xcode workspace
# *.xcworkspace
# Carthage
#
# Add this line if you want to avoid checking in source code from Carthage dependencies.
# Carthage/Checkouts
Carthage/Build/
# fastlane
#
# It is recommended to not store the screenshots in the git repo.
# Instead, use fastlane to re-generate the screenshots whenever they are needed.
# For more information about the recommended setup visit:
# https://docs.fastlane.tools/best-practices/source-control/#source-control
fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots/**/*.png
fastlane/test_output
/src/RyujinxAndroid/.idea
/src/RyujinxAndroid/app/src/main/jniLibs/arm64-v8a

View File

@ -5,6 +5,7 @@
Before you begin, ensure you have the following installed:
- [**.NET 8.0**](https://dotnet.microsoft.com/en-us/download/dotnet/8.0)
- [**Xcode**](https://apps.apple.com/de/app/xcode/id497799835?l=en-GB&mt=12$0)
- A Mac running **macOS**
## Compilation Steps

View File

@ -3,39 +3,40 @@
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Avalonia" Version="11.0.5" />
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.0.5" />
<PackageVersion Include="Avalonia.Desktop" Version="11.0.5" />
<PackageVersion Include="Avalonia.Diagnostics" Version="11.0.5" />
<PackageVersion Include="Avalonia.Markup.Xaml.Loader" Version="11.0.5" />
<PackageVersion Include="Avalonia.Svg" Version="11.0.0.3" />
<PackageVersion Include="Avalonia.Svg.Skia" Version="11.0.0.3" />
<PackageVersion Include="Avalonia" Version="11.0.10" />
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.0.10" />
<PackageVersion Include="Avalonia.Desktop" Version="11.0.10" />
<PackageVersion Include="Avalonia.Diagnostics" Version="11.0.10" />
<PackageVersion Include="Avalonia.Markup.Xaml.Loader" Version="11.0.10" />
<PackageVersion Include="Avalonia.Svg" Version="11.0.0.18" />
<PackageVersion Include="Avalonia.Svg.Skia" Version="11.0.0.18" />
<PackageVersion Include="CommandLineParser" Version="2.9.1" />
<PackageVersion Include="Concentus" Version="1.1.7" />
<PackageVersion Include="Concentus" Version="2.2.0" />
<PackageVersion Include="DiscordRichPresence" Version="1.2.1.24" />
<PackageVersion Include="DynamicData" Version="7.14.2" />
<PackageVersion Include="FluentAvaloniaUI" Version="2.0.4" />
<PackageVersion Include="DynamicData" Version="9.0.4" />
<PackageVersion Include="FluentAvaloniaUI" Version="2.0.5" />
<PackageVersion Include="GtkSharp.Dependencies" Version="1.1.1" />
<PackageVersion Include="GtkSharp.Dependencies.osx" Version="0.0.5" />
<PackageVersion Include="jp2masa.Avalonia.Flexbox" Version="0.3.0-beta.4" />
<PackageVersion Include="LibHac" Version="0.19.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.7.0" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageVersion Include="Microsoft.IO.RecyclableMemoryStream" Version="2.3.2" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.9.2" />
<PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.0.1" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
<PackageVersion Include="Microsoft.IO.RecyclableMemoryStream" Version="3.0.1" />
<PackageVersion Include="MsgPack.Cli" Version="1.0.1" />
<PackageVersion Include="NetCoreServer" Version="7.0.0" />
<PackageVersion Include="NetCoreServer" Version="8.0.7" />
<PackageVersion Include="NUnit" Version="3.13.3" />
<PackageVersion Include="NUnit3TestAdapter" Version="4.1.0" />
<PackageVersion Include="OpenTK.Core" Version="4.8.1" />
<PackageVersion Include="OpenTK.Graphics" Version="4.8.1" />
<PackageVersion Include="OpenTK.Audio.OpenAL" Version="4.8.1" />
<PackageVersion Include="OpenTK.Windowing.GraphicsLibraryFramework" Version="4.8.1" />
<PackageVersion Include="OpenTK" Version="4.8.2" />
<PackageVersion Include="OpenTK.Core" Version="4.8.2" />
<PackageVersion Include="OpenTK.Graphics" Version="4.8.2" />
<PackageVersion Include="OpenTK.Audio.OpenAL" Version="4.8.2" />
<PackageVersion Include="OpenTK.Windowing.GraphicsLibraryFramework" Version="4.8.2" />
<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.Nvdec.Dependencies" Version="5.0.3-build14" />
<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="Ryujinx.SDL2-CS" Version="2.30.0-build32" />
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
<PackageVersion Include="shaderc.net" Version="0.1.0" />
<PackageVersion Include="SharpZipLib" Version="1.4.2" />
@ -50,5 +51,6 @@
<PackageVersion Include="System.IO.Hashing" Version="8.0.0" />
<PackageVersion Include="System.Management" Version="8.0.0" />
<PackageVersion Include="UnicornEngine.Unicorn" Version="2.0.2-rc1-fb78016" />
<PackageVersion Include="Rxmxnx.PInvoke.Extensions" Version="1.5.0" />
</ItemGroup>
</Project>

View File

@ -6,6 +6,9 @@
<h1 align="center">MeloNX</h1>
## Documentation
If you are planning to contribute or just want to learn more about this project please read through our [documentation](docs/README.md).
<p align="center">
@ -17,14 +20,15 @@
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">MeloNX license (Based on MIT)</a>. <br
</p>
### Step 3
# Compatibility
MeloNX works on iPhone X and later and iPad 7th Gen and later. Check out the Compatibility on the <a href="https://melonx.org/compatibility/" target="_blank">website</a>.
MeloNX works on iPhone XS/XR and later and iPad 8th Gen and later. Check out the Compatibility on the <a href="https://melonx.org/compatibility/" target="_blank">website</a>.
# Usage
## FAQ
- MeloNX is made for iOS 17+, iOS 15 - 16 is supported but will have issues.
- MeloNX is made for iOS 17+, on iOS 15 - 16 MeloNX can be installed but will have issues or may not work at all.
- MeloNX needs Xcode or a Paid Apple Developer Account. SideStore support may come soon (SideStore Side Issue)
- MeloNX needs JIT
- Recommended Device: iPhone 15 Pro or newer.
@ -60,6 +64,8 @@ If having Issues installing firmware (Make sure your Keys are installed first)
### Xcode
**NOTE: These Xcode builds are nightly and may have unfinished features.**
1. **Compile Guide**
- Visit the [guide here](https://git.743378673.xyz/MeloNX/MeloNX/src/branch/XC-ios-ht/Compile.md).

View File

@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.1.32228.430
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx", "src\Ryujinx\Ryujinx.csproj", "{074045D4-3ED2-4711-9169-E385F2BFB5A0}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Gtk3", "src\Ryujinx.Gtk3\Ryujinx.Gtk3.csproj", "{074045D4-3ED2-4711-9169-E385F2BFB5A0}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Tests", "src\Ryujinx.Tests\Ryujinx.Tests.csproj", "{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}"
EndProject
@ -69,9 +69,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Headless.SDL2", "sr
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Nvdec.FFmpeg", "src\Ryujinx.Graphics.Nvdec.FFmpeg\Ryujinx.Graphics.Nvdec.FFmpeg.csproj", "{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Ava", "src\Ryujinx.Ava\Ryujinx.Ava.csproj", "{7C1B2721-13DA-4B62-B046-C626605ECCE6}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx", "src\Ryujinx\Ryujinx.csproj", "{7C1B2721-13DA-4B62-B046-C626605ECCE6}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Ui.Common", "src\Ryujinx.Ui.Common\Ryujinx.Ui.Common.csproj", "{BA161CA0-CD65-4E6E-B644-51C8D1E542DC}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.UI.Common", "src\Ryujinx.UI.Common\Ryujinx.UI.Common.csproj", "{BA161CA0-CD65-4E6E-B644-51C8D1E542DC}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon.Generators", "src\Ryujinx.Horizon.Generators\Ryujinx.Horizon.Generators.csproj", "{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}"
EndProject
@ -79,7 +79,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Vulkan", "
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Spv.Generator", "src\Spv.Generator\Spv.Generator.csproj", "{2BCB3D7A-38C0-4FE7-8FDA-374C6AD56D0E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Ui.LocaleGenerator", "src\Ryujinx.Ui.LocaleGenerator\Ryujinx.Ui.LocaleGenerator.csproj", "{77D01AD9-2C98-478E-AE1D-8F7100738FB4}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.UI.LocaleGenerator", "src\Ryujinx.UI.LocaleGenerator\Ryujinx.UI.LocaleGenerator.csproj", "{77D01AD9-2C98-478E-AE1D-8F7100738FB4}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon.Common", "src\Ryujinx.Horizon.Common\Ryujinx.Horizon.Common.csproj", "{77F96ECE-4952-42DB-A528-DED25572A573}"
EndProject
@ -87,6 +87,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon", "src\Ryuj
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon.Kernel.Generators", "src\Ryujinx.Horizon.Kernel.Generators\Ryujinx.Horizon.Kernel.Generators.csproj", "{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.HLE.Generators", "src\Ryujinx.HLE.Generators\Ryujinx.HLE.Generators.csproj", "{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LibRyujinx", "src\LibRyujinx\LibRyujinx.csproj", "{5BBF478C-A520-41E7-9B88-890AD26766B8}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LibRyujinx.NativeSample", "src\LibRyujinx.NativeSample\LibRyujinx.NativeSample.csproj", "{63D2C96B-5194-4592-BC91-30BEB11C06BD}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -249,6 +255,17 @@ Global
{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Release|Any CPU.Build.0 = Release|Any CPU
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Release|Any CPU.Build.0 = Release|Any CPU
{5BBF478C-A520-41E7-9B88-890AD26766B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5BBF478C-A520-41E7-9B88-890AD26766B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5BBF478C-A520-41E7-9B88-890AD26766B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5BBF478C-A520-41E7-9B88-890AD26766B8}.Release|Any CPU.Build.0 = Release|Any CPU
{63D2C96B-5194-4592-BC91-30BEB11C06BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{63D2C96B-5194-4592-BC91-30BEB11C06BD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{63D2C96B-5194-4592-BC91-30BEB11C06BD}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -4,6 +4,8 @@
<s:String x:Key="/Default/CodeStyle/CSharpVarKeywordUsage/ForOtherTypes/@EntryValue">UseExplicitType</s:String>
<s:String x:Key="/Default/CodeStyle/CSharpVarKeywordUsage/ForSimpleTypes/@EntryValue">UseExplicitType</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=TypesAndNamespaces/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"&gt;&lt;ExtraRule Prefix="I" Suffix="" Style="AaBb" /&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=a0b4bc4d_002Dd13b_002D4a37_002Db37e_002Dc9c6864e4302/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Any" AccessRightKinds="Any" Description="Types and namespaces"&gt;&lt;ElementKinds&gt;&lt;Kind Name="NAMESPACE" /&gt;&lt;Kind Name="CLASS" /&gt;&lt;Kind Name="STRUCT" /&gt;&lt;Kind Name="ENUM" /&gt;&lt;Kind Name="DELEGATE" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"&gt;&lt;ExtraRule Prefix="I" Suffix="" Style="AaBb" /&gt;&lt;/Policy&gt;&lt;/Policy&gt;</s:String>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EPredefinedNamingRulesToUserRulesUpgrade/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=ASET/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Astc/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Luma/@EntryIndexedValue">True</s:Boolean>

View File

@ -4,7 +4,7 @@ Name=Ryujinx
Type=Application
Icon=Ryujinx
Exec=Ryujinx.sh %f
Comment=Plays Nintendo Switch applications
Comment=A Nintendo Switch Emulator
GenericName=Nintendo Switch Emulator
Terminal=false
Categories=Game;Emulator;

15
distribution/linux/Ryujinx.sh Normal file → Executable file
View File

@ -1,20 +1,23 @@
#!/bin/sh
SCRIPT_DIR=$(dirname "$(realpath "$0")")
RYUJINX_BIN="Ryujinx"
if [ -f "$SCRIPT_DIR/Ryujinx.Ava" ]; then
RYUJINX_BIN="Ryujinx.Ava"
fi
if [ -f "$SCRIPT_DIR/Ryujinx.Headless.SDL2" ]; then
RYUJINX_BIN="Ryujinx.Headless.SDL2"
fi
if [ -f "$SCRIPT_DIR/Ryujinx" ]; then
RYUJINX_BIN="Ryujinx"
fi
if [ -z "$RYUJINX_BIN" ]; then
exit 1
fi
COMMAND="env DOTNET_EnableAlternateStackCheck=1"
if command -v gamemoderun > /dev/null 2>&1; then
COMMAND="$COMMAND gamemoderun"
fi
$COMMAND "$SCRIPT_DIR/$RYUJINX_BIN" "$@"
exec $COMMAND "$SCRIPT_DIR/$RYUJINX_BIN" "$@"

View File

@ -14,8 +14,8 @@ mkdir "$APP_BUNDLE_DIRECTORY/Contents/Frameworks"
mkdir "$APP_BUNDLE_DIRECTORY/Contents/MacOS"
mkdir "$APP_BUNDLE_DIRECTORY/Contents/Resources"
# Copy executables first
cp "$PUBLISH_DIRECTORY/Ryujinx.Ava" "$APP_BUNDLE_DIRECTORY/Contents/MacOS/Ryujinx"
# Copy executable and nsure executable can be executed
cp "$PUBLISH_DIRECTORY/Ryujinx" "$APP_BUNDLE_DIRECTORY/Contents/MacOS/Ryujinx"
chmod u+x "$APP_BUNDLE_DIRECTORY/Contents/MacOS/Ryujinx"
# Then all libraries

View File

@ -22,9 +22,9 @@ EXTRA_ARGS=$8
if [ "$VERSION" == "1.1.0" ];
then
RELEASE_TAR_FILE_NAME=test-ava-ryujinx-$CONFIGURATION-$VERSION+$SOURCE_REVISION_ID-macos_universal.app.tar
RELEASE_TAR_FILE_NAME=ryujinx-$CONFIGURATION-$VERSION+$SOURCE_REVISION_ID-macos_universal.app.tar
else
RELEASE_TAR_FILE_NAME=test-ava-ryujinx-$VERSION-macos_universal.app.tar
RELEASE_TAR_FILE_NAME=ryujinx-$VERSION-macos_universal.app.tar
fi
ARM64_APP_BUNDLE="$TEMP_DIRECTORY/output_arm64/Ryujinx.app"
@ -38,9 +38,9 @@ mkdir -p "$TEMP_DIRECTORY"
DOTNET_COMMON_ARGS=(-p:DebugType=embedded -p:Version="$VERSION" -p:SourceRevisionId="$SOURCE_REVISION_ID" --self-contained true $EXTRA_ARGS)
dotnet restore
dotnet build -c "$CONFIGURATION" src/Ryujinx.Ava
dotnet publish -c "$CONFIGURATION" -r osx-arm64 -o "$TEMP_DIRECTORY/publish_arm64" "${DOTNET_COMMON_ARGS[@]}" src/Ryujinx.Ava
dotnet publish -c "$CONFIGURATION" -r osx-x64 -o "$TEMP_DIRECTORY/publish_x64" "${DOTNET_COMMON_ARGS[@]}" src/Ryujinx.Ava
dotnet build -c "$CONFIGURATION" src/Ryujinx
dotnet publish -c "$CONFIGURATION" -r osx-arm64 -o "$TEMP_DIRECTORY/publish_arm64" "${DOTNET_COMMON_ARGS[@]}" src/Ryujinx
dotnet publish -c "$CONFIGURATION" -r osx-x64 -o "$TEMP_DIRECTORY/publish_x64" "${DOTNET_COMMON_ARGS[@]}" src/Ryujinx
# Get rid of the support library for ARMeilleure for x64 (that's only for arm64)
rm -rf "$TEMP_DIRECTORY/publish_x64/libarmeilleure-jitsupport.dylib"
@ -108,6 +108,13 @@ tar --exclude "Ryujinx.app/Contents/MacOS/Ryujinx" -cvf "$RELEASE_TAR_FILE_NAME"
python3 "$BASE_DIR/distribution/misc/add_tar_exec.py" "$RELEASE_TAR_FILE_NAME" "Ryujinx.app/Contents/MacOS/Ryujinx" "Ryujinx.app/Contents/MacOS/Ryujinx"
gzip -9 < "$RELEASE_TAR_FILE_NAME" > "$RELEASE_TAR_FILE_NAME.gz"
rm "$RELEASE_TAR_FILE_NAME"
# Create legacy update package for Avalonia to not left behind old testers.
if [ "$VERSION" != "1.1.0" ];
then
cp $RELEASE_TAR_FILE_NAME.gz test-ava-ryujinx-$VERSION-macos_universal.app.tar.gz
fi
popd
echo "Done"

View File

@ -0,0 +1,8 @@
#!/bin/sh
launch_arch="$(uname -m)"
if [ "$(sysctl -in sysctl.proc_translated)" = "1" ]
then
launch_arch="arm64"
fi
arch -$launch_arch {0} {1}

View File

@ -33,8 +33,3 @@ Project Docs
=================
To be added. Many project files will contain basic XML docs for key functions and classes in the meantime.
Other Information
=================
- N/A

View File

@ -1,6 +1,6 @@
{
"sdk": {
"version": "8.0.100",
"version": "9.0.100-preview.6.24328.19",
"rollForward": "latestFeature"
}
}

View File

@ -2,6 +2,7 @@
<configuration>
<packageSources>
<clear />
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
<add key="nuget"
value="https://api.nuget.org/v3/index.json" />
</packageSources>
</configuration>

View File

@ -237,7 +237,7 @@ namespace ARMeilleure.CodeGen.Arm64
long originalPosition = _stream.Position;
_stream.Seek(0, SeekOrigin.Begin);
_stream.Read(code, 0, code.Length);
_stream.ReadExactly(code, 0, code.Length);
_stream.Seek(originalPosition, SeekOrigin.Begin);
RelocInfo relocInfo;

View File

@ -124,7 +124,7 @@ namespace ARMeilleure.CodeGen.Arm64
#endregion
#region macOS
#region Darwin
[LibraryImport("libSystem.dylib", SetLastError = true)]
private static unsafe partial int sysctlbyname([MarshalAs(UnmanagedType.LPStr)] string name, out int oldValue, ref ulong oldSize, IntPtr newValue, ulong newValueSize);

View File

@ -251,7 +251,20 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
}
}
int selectedReg = GetHighestValueIndex(freePositions);
// If this is a copy destination variable, we prefer the register used for the copy source.
// If the register is available, then the copy can be eliminated later as both source
// and destination will use the same register.
int selectedReg;
if (current.TryGetCopySourceRegister(out int preferredReg) && freePositions[preferredReg] >= current.GetEnd())
{
selectedReg = preferredReg;
}
else
{
selectedReg = GetHighestValueIndex(freePositions);
}
int selectedNextUse = freePositions[selectedReg];
// Intervals starts and ends at odd positions, unless they span an entire
@ -431,7 +444,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
}
}
private static int GetHighestValueIndex(Span<int> span)
private static int GetHighestValueIndex(ReadOnlySpan<int> span)
{
int highest = int.MinValue;
@ -798,12 +811,12 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
// The "visited" state is stored in the MSB of the local's value.
const ulong VisitedMask = 1ul << 63;
bool IsVisited(Operand local)
static bool IsVisited(Operand local)
{
return (local.GetValueUnsafe() & VisitedMask) != 0;
}
void SetVisited(Operand local)
static void SetVisited(Operand local)
{
local.GetValueUnsafe() |= VisitedMask;
}
@ -826,9 +839,25 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{
dest.NumberLocal(_intervals.Count);
_intervals.Add(new LiveInterval(dest));
LiveInterval interval = new LiveInterval(dest);
_intervals.Add(interval);
SetVisited(dest);
// If this is a copy (or copy-like operation), set the copy source interval as well.
// This is used for register preferencing later on, which allows the copy to be eliminated
// in some cases.
if (node.Instruction == Instruction.Copy || node.Instruction == Instruction.ZeroExtend32)
{
Operand source = node.GetSource(0);
if (source.Kind == OperandKind.LocalVariable &&
source.GetLocalNumber() > 0 &&
(node.Instruction == Instruction.Copy || source.Type == OperandType.I32))
{
interval.SetCopySource(_intervals[source.GetLocalNumber()]);
}
}
}
}
}

View File

@ -19,6 +19,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
public LiveRange CurrRange;
public LiveInterval Parent;
public LiveInterval CopySource;
public UseList Uses;
public LiveIntervalList Children;
@ -37,6 +38,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
private ref LiveRange CurrRange => ref _data->CurrRange;
private ref LiveRange PrevRange => ref _data->PrevRange;
private ref LiveInterval Parent => ref _data->Parent;
private ref LiveInterval CopySource => ref _data->CopySource;
private ref UseList Uses => ref _data->Uses;
private ref LiveIntervalList Children => ref _data->Children;
@ -78,6 +80,25 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
Register = register;
}
public void SetCopySource(LiveInterval copySource)
{
CopySource = copySource;
}
public bool TryGetCopySourceRegister(out int copySourceRegIndex)
{
if (CopySource._data != null)
{
copySourceRegIndex = CopySource.Register.Index;
return true;
}
copySourceRegIndex = 0;
return false;
}
public void Reset()
{
PrevRange = default;

View File

@ -1444,7 +1444,7 @@ namespace ARMeilleure.CodeGen.X86
Span<byte> buffer = new byte[jump.JumpPosition - _stream.Position];
_stream.Read(buffer);
_stream.ReadExactly(buffer);
_stream.Seek(ReservedBytesForJump, SeekOrigin.Current);
codeStream.Write(buffer);

View File

@ -517,7 +517,10 @@ namespace ARMeilleure.Decoders
SetA64("0x00111100>>>xxx100111xxxxxxxxxx", InstName.Sqrshrn_V, InstEmit.Sqrshrn_V, OpCodeSimdShImm.Create);
SetA64("0111111100>>>xxx100011xxxxxxxxxx", InstName.Sqrshrun_S, InstEmit.Sqrshrun_S, OpCodeSimdShImm.Create);
SetA64("0x10111100>>>xxx100011xxxxxxxxxx", InstName.Sqrshrun_V, InstEmit.Sqrshrun_V, OpCodeSimdShImm.Create);
SetA64("010111110>>>>xxx011101xxxxxxxxxx", InstName.Sqshl_Si, InstEmit.Sqshl_Si, OpCodeSimdShImm.Create);
SetA64("0>001110<<1xxxxx010011xxxxxxxxxx", InstName.Sqshl_V, InstEmit.Sqshl_V, OpCodeSimdReg.Create);
SetA64("0000111100>>>xxx011101xxxxxxxxxx", InstName.Sqshl_Vi, InstEmit.Sqshl_Vi, OpCodeSimdShImm.Create);
SetA64("010011110>>>>xxx011101xxxxxxxxxx", InstName.Sqshl_Vi, InstEmit.Sqshl_Vi, OpCodeSimdShImm.Create);
SetA64("0101111100>>>xxx100101xxxxxxxxxx", InstName.Sqshrn_S, InstEmit.Sqshrn_S, OpCodeSimdShImm.Create);
SetA64("0x00111100>>>xxx100101xxxxxxxxxx", InstName.Sqshrn_V, InstEmit.Sqshrn_V, OpCodeSimdShImm.Create);
SetA64("0111111100>>>xxx100001xxxxxxxxxx", InstName.Sqshrun_S, InstEmit.Sqshrun_S, OpCodeSimdShImm.Create);
@ -819,6 +822,10 @@ namespace ARMeilleure.Decoders
SetA32("<<<<00000100xxxxxxxxxxxx1001xxxx", InstName.Umaal, InstEmit32.Umaal, OpCode32AluUmull.Create);
SetA32("<<<<0000101xxxxxxxxxxxxx1001xxxx", InstName.Umlal, InstEmit32.Umlal, OpCode32AluUmull.Create);
SetA32("<<<<0000100xxxxxxxxxxxxx1001xxxx", InstName.Umull, InstEmit32.Umull, OpCode32AluUmull.Create);
SetA32("<<<<01100110xxxxxxxx11110001xxxx", InstName.Uqadd16, InstEmit32.Uqadd16, OpCode32AluReg.Create);
SetA32("<<<<01100110xxxxxxxx11111001xxxx", InstName.Uqadd8, InstEmit32.Uqadd8, OpCode32AluReg.Create);
SetA32("<<<<01100110xxxxxxxx11110111xxxx", InstName.Uqsub16, InstEmit32.Uqsub16, OpCode32AluReg.Create);
SetA32("<<<<01100110xxxxxxxx11111111xxxx", InstName.Uqsub8, InstEmit32.Uqsub8, OpCode32AluReg.Create);
SetA32("<<<<0110111xxxxxxxxxxxxxxx01xxxx", InstName.Usat, InstEmit32.Usat, OpCode32Sat.Create);
SetA32("<<<<01101110xxxxxxxx11110011xxxx", InstName.Usat16, InstEmit32.Usat16, OpCode32Sat16.Create);
SetA32("<<<<01100101xxxxxxxx11111111xxxx", InstName.Usub8, InstEmit32.Usub8, OpCode32AluReg.Create);
@ -872,6 +879,7 @@ namespace ARMeilleure.Decoders
SetVfp("<<<<11100x10xxxxxxxx101xx1x0xxxx", InstName.Vnmul, InstEmit32.Vnmul_S, OpCode32SimdRegS.Create, OpCode32SimdRegS.CreateT32);
SetVfp("111111101x1110xxxxxx101x01x0xxxx", InstName.Vrint, InstEmit32.Vrint_RM, OpCode32SimdS.Create, OpCode32SimdS.CreateT32);
SetVfp("<<<<11101x110110xxxx101x11x0xxxx", InstName.Vrint, InstEmit32.Vrint_Z, OpCode32SimdS.Create, OpCode32SimdS.CreateT32);
SetVfp("<<<<11101x110110xxxx101x01x0xxxx", InstName.Vrintr, InstEmit32.Vrintr_S, OpCode32SimdS.Create, OpCode32SimdS.CreateT32);
SetVfp("<<<<11101x110111xxxx101x01x0xxxx", InstName.Vrintx, InstEmit32.Vrintx_S, OpCode32SimdS.Create, OpCode32SimdS.CreateT32);
SetVfp("<<<<11101x110001xxxx101x11x0xxxx", InstName.Vsqrt, InstEmit32.Vsqrt_S, OpCode32SimdS.Create, OpCode32SimdS.CreateT32);
SetVfp("111111100xxxxxxxxxxx101xx0x0xxxx", InstName.Vsel, InstEmit32.Vsel, OpCode32SimdSel.Create, OpCode32SimdSel.CreateT32);
@ -992,6 +1000,7 @@ namespace ARMeilleure.Decoders
SetAsimd("1111001x1x000xxxxxxx<<x10x01xxxx", InstName.Vorr, InstEmit32.Vorr_II, OpCode32SimdImm.Create, OpCode32SimdImm.CreateT32);
SetAsimd("111100100x<<xxxxxxxx1011x0x1xxxx", InstName.Vpadd, InstEmit32.Vpadd_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("111100110x00xxxxxxxx1101x0x0xxxx", InstName.Vpadd, InstEmit32.Vpadd_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("111100111x11<<00xxxx0110xxx0xxxx", InstName.Vpadal, InstEmit32.Vpadal, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
SetAsimd("111100111x11<<00xxxx0010xxx0xxxx", InstName.Vpaddl, InstEmit32.Vpaddl, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
SetAsimd("1111001x0x<<xxxxxxxx1010x0x0xxxx", InstName.Vpmax, InstEmit32.Vpmax_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("111100110x00xxxxxxxx1111x0x0xxxx", InstName.Vpmax, InstEmit32.Vpmax_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
@ -1002,6 +1011,8 @@ namespace ARMeilleure.Decoders
SetAsimd("111100100x10xxxxxxxx1011xxx0xxxx", InstName.Vqdmulh, InstEmit32.Vqdmulh, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("111100111x11<<10xxxx00101xx0xxx0", InstName.Vqmovn, InstEmit32.Vqmovn, OpCode32SimdMovn.Create, OpCode32SimdMovn.CreateT32);
SetAsimd("111100111x11<<10xxxx001001x0xxx0", InstName.Vqmovun, InstEmit32.Vqmovun, OpCode32SimdMovn.Create, OpCode32SimdMovn.CreateT32);
SetAsimd("111100110x01xxxxxxxx1011xxx0xxxx", InstName.Vqrdmulh, InstEmit32.Vqrdmulh, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("111100110x10xxxxxxxx1011xxx0xxxx", InstName.Vqrdmulh, InstEmit32.Vqrdmulh, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("1111001x1x>>>xxxxxxx100101x1xxx0", InstName.Vqrshrn, InstEmit32.Vqrshrn, OpCode32SimdShImmNarrow.Create, OpCode32SimdShImmNarrow.CreateT32);
SetAsimd("111100111x>>>xxxxxxx100001x1xxx0", InstName.Vqrshrun, InstEmit32.Vqrshrun, OpCode32SimdShImmNarrow.Create, OpCode32SimdShImmNarrow.CreateT32);
SetAsimd("1111001x1x>>>xxxxxxx100100x1xxx0", InstName.Vqshrn, InstEmit32.Vqshrn, OpCode32SimdShImmNarrow.Create, OpCode32SimdShImmNarrow.CreateT32);
@ -1025,6 +1036,7 @@ namespace ARMeilleure.Decoders
SetAsimd("1111001x1x>>>xxxxxxx101000x1xxxx", InstName.Vshll, InstEmit32.Vshll, OpCode32SimdShImmLong.Create, OpCode32SimdShImmLong.CreateT32); // A1 encoding.
SetAsimd("1111001x1x>>>xxxxxxx0000>xx1xxxx", InstName.Vshr, InstEmit32.Vshr, OpCode32SimdShImm.Create, OpCode32SimdShImm.CreateT32);
SetAsimd("111100101x>>>xxxxxxx100000x1xxx0", InstName.Vshrn, InstEmit32.Vshrn, OpCode32SimdShImmNarrow.Create, OpCode32SimdShImmNarrow.CreateT32);
SetAsimd("111100111x>>>xxxxxxx0101>xx1xxxx", InstName.Vsli, InstEmit32.Vsli_I, OpCode32SimdShImm.Create, OpCode32SimdShImm.CreateT32);
SetAsimd("1111001x1x>>>xxxxxxx0001>xx1xxxx", InstName.Vsra, InstEmit32.Vsra, OpCode32SimdShImm.Create, OpCode32SimdShImm.CreateT32);
SetAsimd("111101001x00xxxxxxxx0000xxx0xxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetAsimd("111101001x00xxxxxxxx0100xx0xxxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
@ -1049,6 +1061,7 @@ namespace ARMeilleure.Decoders
SetAsimd("111100100x10xxxxxxxx1101xxx0xxxx", InstName.Vsub, InstEmit32.Vsub_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("1111001x1x<<xxxxxxx00010x0x0xxxx", InstName.Vsubl, InstEmit32.Vsubl_I, OpCode32SimdRegLong.Create, OpCode32SimdRegLong.CreateT32);
SetAsimd("1111001x1x<<xxxxxxx00011x0x0xxxx", InstName.Vsubw, InstEmit32.Vsubw_I, OpCode32SimdRegWide.Create, OpCode32SimdRegWide.CreateT32);
SetAsimd("111100111x110010xxxx00000xx0xxxx", InstName.Vswp, InstEmit32.Vswp, OpCode32Simd.Create, OpCode32Simd.CreateT32);
SetAsimd("111100111x11xxxxxxxx10xxxxx0xxxx", InstName.Vtbl, InstEmit32.Vtbl, OpCode32SimdTbl.Create, OpCode32SimdTbl.CreateT32);
SetAsimd("111100111x11<<10xxxx00001xx0xxxx", InstName.Vtrn, InstEmit32.Vtrn, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
SetAsimd("111100100x<<xxxxxxxx1000xxx1xxxx", InstName.Vtst, InstEmit32.Vtst, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);

View File

@ -2,6 +2,8 @@ using ARMeilleure.Decoders;
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.State;
using ARMeilleure.Translation;
using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using static ARMeilleure.Instructions.InstEmitAluHelper;
using static ARMeilleure.Instructions.InstEmitHelper;
@ -19,6 +21,12 @@ namespace ARMeilleure.Instructions
Operand n = GetAluN(context);
Operand m = GetAluM(context, setCarry: false);
if (op.Rn == RegisterAlias.Aarch32Pc && op is OpCodeT32AluImm12)
{
// For ADR, PC is always 4 bytes aligned, even in Thumb mode.
n = context.BitwiseAnd(n, Const(~3u));
}
Operand res = context.Add(n, m);
if (ShouldSetFlags(context))
@ -467,6 +475,12 @@ namespace ARMeilleure.Instructions
Operand n = GetAluN(context);
Operand m = GetAluM(context, setCarry: false);
if (op.Rn == RegisterAlias.Aarch32Pc && op is OpCodeT32AluImm12)
{
// For ADR, PC is always 4 bytes aligned, even in Thumb mode.
n = context.BitwiseAnd(n, Const(~3u));
}
Operand res = context.Subtract(n, m);
if (ShouldSetFlags(context))
@ -546,6 +560,46 @@ namespace ARMeilleure.Instructions
EmitHsub8(context, unsigned: true);
}
public static void Uqadd16(ArmEmitterContext context)
{
OpCode32AluReg op = (OpCode32AluReg)context.CurrOp;
SetIntA32(context, op.Rd, EmitUnsigned16BitPair(context, GetIntA32(context, op.Rn), GetIntA32(context, op.Rm), (d, n, m) =>
{
EmitSaturateUqadd(context, d, context.Add(n, m), 16);
}));
}
public static void Uqadd8(ArmEmitterContext context)
{
OpCode32AluReg op = (OpCode32AluReg)context.CurrOp;
SetIntA32(context, op.Rd, EmitUnsigned8BitPair(context, GetIntA32(context, op.Rn), GetIntA32(context, op.Rm), (d, n, m) =>
{
EmitSaturateUqadd(context, d, context.Add(n, m), 8);
}));
}
public static void Uqsub16(ArmEmitterContext context)
{
OpCode32AluReg op = (OpCode32AluReg)context.CurrOp;
SetIntA32(context, op.Rd, EmitUnsigned16BitPair(context, GetIntA32(context, op.Rn), GetIntA32(context, op.Rm), (d, n, m) =>
{
EmitSaturateUqsub(context, d, context.Subtract(n, m), 16);
}));
}
public static void Uqsub8(ArmEmitterContext context)
{
OpCode32AluReg op = (OpCode32AluReg)context.CurrOp;
SetIntA32(context, op.Rd, EmitUnsigned8BitPair(context, GetIntA32(context, op.Rn), GetIntA32(context, op.Rm), (d, n, m) =>
{
EmitSaturateUqsub(context, d, context.Subtract(n, m), 8);
}));
}
public static void Usat(ArmEmitterContext context)
{
OpCode32Sat op = (OpCode32Sat)context.CurrOp;
@ -922,6 +976,148 @@ namespace ARMeilleure.Instructions
}
}
private static void EmitSaturateUqadd(ArmEmitterContext context, Operand result, Operand value, uint saturateTo)
{
Debug.Assert(saturateTo <= 32);
if (saturateTo == 32)
{
// No saturation possible for this case.
context.Copy(result, value);
return;
}
else if (saturateTo == 0)
{
// Result is always zero if we saturate 0 bits.
context.Copy(result, Const(0));
return;
}
// If the result is 0, the values are equal and we don't need saturation.
Operand lblNoSat = Label();
context.BranchIfFalse(lblNoSat, context.ShiftRightUI(value, Const((int)saturateTo)));
// Saturate.
context.Copy(result, Const(uint.MaxValue >> (32 - (int)saturateTo)));
Operand lblExit = Label();
context.Branch(lblExit);
context.MarkLabel(lblNoSat);
context.Copy(result, value);
context.MarkLabel(lblExit);
}
private static void EmitSaturateUqsub(ArmEmitterContext context, Operand result, Operand value, uint saturateTo)
{
Debug.Assert(saturateTo <= 32);
if (saturateTo == 32)
{
// No saturation possible for this case.
context.Copy(result, value);
return;
}
else if (saturateTo == 0)
{
// Result is always zero if we saturate 0 bits.
context.Copy(result, Const(0));
return;
}
// If the result is 0, the values are equal and we don't need saturation.
Operand lblNoSat = Label();
context.BranchIf(lblNoSat, value, Const(0), Comparison.GreaterOrEqual);
// Saturate.
// Assumes that the value can only underflow, since this is only used for unsigned subtraction.
context.Copy(result, Const(0));
Operand lblExit = Label();
context.Branch(lblExit);
context.MarkLabel(lblNoSat);
context.Copy(result, value);
context.MarkLabel(lblExit);
}
private static Operand EmitUnsigned16BitPair(ArmEmitterContext context, Operand rn, Operand rm, Action<Operand, Operand, Operand> elementAction)
{
Operand tempD = context.AllocateLocal(OperandType.I32);
Operand tempN = context.ZeroExtend16(OperandType.I32, rn);
Operand tempM = context.ZeroExtend16(OperandType.I32, rm);
elementAction(tempD, tempN, tempM);
Operand tempD2 = context.ZeroExtend16(OperandType.I32, tempD);
tempN = context.ShiftRightUI(rn, Const(16));
tempM = context.ShiftRightUI(rm, Const(16));
elementAction(tempD, tempN, tempM);
return context.BitwiseOr(tempD2, context.ShiftLeft(tempD, Const(16)));
}
private static Operand EmitSigned8BitPair(ArmEmitterContext context, Operand rn, Operand rm, Action<Operand, Operand, Operand> elementAction)
{
return Emit8BitPair(context, rn, rm, elementAction, unsigned: false);
}
private static Operand EmitUnsigned8BitPair(ArmEmitterContext context, Operand rn, Operand rm, Action<Operand, Operand, Operand> elementAction)
{
return Emit8BitPair(context, rn, rm, elementAction, unsigned: true);
}
private static Operand Emit8BitPair(ArmEmitterContext context, Operand rn, Operand rm, Action<Operand, Operand, Operand> elementAction, bool unsigned)
{
Operand tempD = context.AllocateLocal(OperandType.I32);
Operand result = default;
for (int b = 0; b < 4; b++)
{
Operand nByte = b != 0 ? context.ShiftRightUI(rn, Const(b * 8)) : rn;
Operand mByte = b != 0 ? context.ShiftRightUI(rm, Const(b * 8)) : rm;
if (unsigned)
{
nByte = context.ZeroExtend8(OperandType.I32, nByte);
mByte = context.ZeroExtend8(OperandType.I32, mByte);
}
else
{
nByte = context.SignExtend8(OperandType.I32, nByte);
mByte = context.SignExtend8(OperandType.I32, mByte);
}
elementAction(tempD, nByte, mByte);
if (b == 0)
{
result = context.ZeroExtend8(OperandType.I32, tempD);
}
else if (b < 3)
{
result = context.BitwiseOr(result, context.ShiftLeft(context.ZeroExtend8(OperandType.I32, tempD), Const(b * 8)));
}
else
{
result = context.BitwiseOr(result, context.ShiftLeft(tempD, Const(24)));
}
}
return result;
}
private static void EmitAluStore(ArmEmitterContext context, Operand value)
{
IOpCode32Alu op = (IOpCode32Alu)context.CurrOp;

View File

@ -403,19 +403,25 @@ namespace ARMeilleure.Instructions
{
return EmitHostMappedPointer(context, address);
}
else if (context.Memory.Type == MemoryManagerType.HostTracked)
else if (context.Memory.Type.IsHostTracked())
{
if (address.Type == OperandType.I32)
{
address = context.ZeroExtend32(OperandType.I64, address);
}
if (context.Memory.Type == MemoryManagerType.HostTracked)
{
Operand mask = Const(ulong.MaxValue >> (64 - context.Memory.AddressSpaceBits));
address = context.BitwiseAnd(address, mask);
}
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)))));
}

View File

@ -2426,7 +2426,11 @@ namespace ARMeilleure.Instructions
}
else if (Optimizations.FastFP && Optimizations.UseSse41 && sizeF == 0)
{
Operand res = EmitSse41Round32Exp8OpF(context, context.AddIntrinsic(Intrinsic.X86Rsqrtss, GetVec(op.Rn)), scalar: true);
// RSQRTSS handles subnormals as zero, which differs from Arm, so we can't use it here.
Operand res = context.AddIntrinsic(Intrinsic.X86Sqrtss, GetVec(op.Rn));
res = context.AddIntrinsic(Intrinsic.X86Rcpss, res);
res = EmitSse41Round32Exp8OpF(context, res, scalar: true);
context.Copy(GetVec(op.Rd), context.VectorZeroUpper96(res));
}
@ -2451,7 +2455,11 @@ namespace ARMeilleure.Instructions
}
else if (Optimizations.FastFP && Optimizations.UseSse41 && sizeF == 0)
{
Operand res = EmitSse41Round32Exp8OpF(context, context.AddIntrinsic(Intrinsic.X86Rsqrtps, GetVec(op.Rn)), scalar: false);
// RSQRTPS handles subnormals as zero, which differs from Arm, so we can't use it here.
Operand res = context.AddIntrinsic(Intrinsic.X86Sqrtps, GetVec(op.Rn));
res = context.AddIntrinsic(Intrinsic.X86Rcpps, res);
res = EmitSse41Round32Exp8OpF(context, res, scalar: false);
if (op.RegisterSize == RegisterSize.Simd64)
{

View File

@ -1115,6 +1115,13 @@ namespace ARMeilleure.Instructions
}
}
public static void Vpadal(ArmEmitterContext context)
{
OpCode32Simd op = (OpCode32Simd)context.CurrOp;
EmitVectorPairwiseTernaryLongOpI32(context, (op1, op2, op3) => context.Add(context.Add(op1, op2), op3), op.Opc != 1);
}
public static void Vpaddl(ArmEmitterContext context)
{
OpCode32Simd op = (OpCode32Simd)context.CurrOp;
@ -1239,6 +1246,33 @@ namespace ARMeilleure.Instructions
EmitVectorUnaryNarrowOp32(context, (op1) => EmitSatQ(context, op1, 8 << op.Size, signedSrc: true, signedDst: false), signed: true);
}
public static void Vqrdmulh(ArmEmitterContext context)
{
OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;
int eSize = 8 << op.Size;
EmitVectorBinaryOpI32(context, (op1, op2) =>
{
if (op.Size == 2)
{
op1 = context.SignExtend32(OperandType.I64, op1);
op2 = context.SignExtend32(OperandType.I64, op2);
}
Operand res = context.Multiply(op1, op2);
res = context.Add(res, Const(res.Type, 1L << (eSize - 2)));
res = context.ShiftRightSI(res, Const(eSize - 1));
res = EmitSatQ(context, res, eSize, signedSrc: true, signedDst: true);
if (op.Size == 2)
{
res = context.ConvertI64ToI32(res);
}
return res;
}, signed: true);
}
public static void Vqsub(ArmEmitterContext context)
{
OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;

View File

@ -578,6 +578,22 @@ namespace ARMeilleure.Instructions
}
}
// VRINTR (floating-point).
public static void Vrintr_S(ArmEmitterContext context)
{
if (Optimizations.UseAdvSimd)
{
InstEmitSimdHelper32Arm64.EmitScalarUnaryOpF32(context, Intrinsic.Arm64FrintiS);
}
else
{
EmitScalarUnaryOpF32(context, (op1) =>
{
return EmitRoundByRMode(context, op1);
});
}
}
// VRINTZ (floating-point).
public static void Vrint_Z(ArmEmitterContext context)
{

View File

@ -673,6 +673,35 @@ namespace ARMeilleure.Instructions
context.Copy(GetVecA32(op.Qd), res);
}
public static void EmitVectorPairwiseTernaryLongOpI32(ArmEmitterContext context, Func3I emit, bool signed)
{
OpCode32Simd op = (OpCode32Simd)context.CurrOp;
int elems = op.GetBytesCount() >> op.Size;
int pairs = elems >> 1;
Operand res = GetVecA32(op.Qd);
for (int index = 0; index < pairs; index++)
{
int pairIndex = index * 2;
Operand m1 = EmitVectorExtract32(context, op.Qm, op.Im + pairIndex, op.Size, signed);
Operand m2 = EmitVectorExtract32(context, op.Qm, op.Im + pairIndex + 1, op.Size, signed);
if (op.Size == 2)
{
m1 = signed ? context.SignExtend32(OperandType.I64, m1) : context.ZeroExtend32(OperandType.I64, m1);
m2 = signed ? context.SignExtend32(OperandType.I64, m2) : context.ZeroExtend32(OperandType.I64, m2);
}
Operand d1 = EmitVectorExtract32(context, op.Qd, op.Id + index, op.Size + 1, signed);
res = EmitVectorInsert(context, res, emit(m1, m2, d1), op.Id + index, op.Size + 1);
}
context.Copy(GetVecA32(op.Qd), res);
}
// Narrow
public static void EmitVectorUnaryNarrowOp32(ArmEmitterContext context, Func1I emit, bool signed = false)

View File

@ -191,6 +191,26 @@ namespace ARMeilleure.Instructions
context.Copy(GetVecA32(op.Qd), res);
}
public static void Vswp(ArmEmitterContext context)
{
OpCode32Simd op = (OpCode32Simd)context.CurrOp;
if (op.Q)
{
Operand temp = context.Copy(GetVecA32(op.Qd));
context.Copy(GetVecA32(op.Qd), GetVecA32(op.Qm));
context.Copy(GetVecA32(op.Qm), temp);
}
else
{
Operand temp = ExtractScalar(context, OperandType.I64, op.Vd);
InsertScalar(context, op.Vd, ExtractScalar(context, OperandType.I64, op.Vm));
InsertScalar(context, op.Vm, temp);
}
}
public static void Vtbl(ArmEmitterContext context)
{
OpCode32SimdTbl op = (OpCode32SimdTbl)context.CurrOp;

View File

@ -116,7 +116,7 @@ namespace ARMeilleure.Instructions
}
else if (shift >= eSize)
{
if ((op.RegisterSize == RegisterSize.Simd64))
if (op.RegisterSize == RegisterSize.Simd64)
{
Operand res = context.VectorZeroUpper64(GetVec(op.Rd));
@ -359,6 +359,16 @@ namespace ARMeilleure.Instructions
}
}
public static void Sqshl_Si(ArmEmitterContext context)
{
EmitShlImmOp(context, signedDst: true, ShlRegFlags.Signed | ShlRegFlags.Scalar | ShlRegFlags.Saturating);
}
public static void Sqshl_Vi(ArmEmitterContext context)
{
EmitShlImmOp(context, signedDst: true, ShlRegFlags.Signed | ShlRegFlags.Saturating);
}
public static void Sqshrn_S(ArmEmitterContext context)
{
if (Optimizations.UseAdvSimd)
@ -1593,6 +1603,99 @@ namespace ARMeilleure.Instructions
Saturating = 1 << 3,
}
private static void EmitShlImmOp(ArmEmitterContext context, bool signedDst, ShlRegFlags flags = ShlRegFlags.None)
{
bool scalar = flags.HasFlag(ShlRegFlags.Scalar);
bool signed = flags.HasFlag(ShlRegFlags.Signed);
bool saturating = flags.HasFlag(ShlRegFlags.Saturating);
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
Operand res = context.VectorZero();
int elems = !scalar ? op.GetBytesCount() >> op.Size : 1;
for (int index = 0; index < elems; index++)
{
Operand ne = EmitVectorExtract(context, op.Rn, index, op.Size, signed);
Operand e = !saturating
? EmitShlImm(context, ne, GetImmShl(op), op.Size)
: EmitShlImmSatQ(context, ne, GetImmShl(op), op.Size, signed, signedDst);
res = EmitVectorInsert(context, res, e, index, op.Size);
}
context.Copy(GetVec(op.Rd), res);
}
private static Operand EmitShlImm(ArmEmitterContext context, Operand op, int shiftLsB, int size)
{
int eSize = 8 << size;
Debug.Assert(op.Type == OperandType.I64);
Debug.Assert(eSize == 8 || eSize == 16 || eSize == 32 || eSize == 64);
Operand res = context.AllocateLocal(OperandType.I64);
if (shiftLsB >= eSize)
{
Operand shl = context.ShiftLeft(op, Const(shiftLsB));
context.Copy(res, shl);
}
else
{
Operand zeroL = Const(0L);
context.Copy(res, zeroL);
}
return res;
}
private static Operand EmitShlImmSatQ(ArmEmitterContext context, Operand op, int shiftLsB, int size, bool signedSrc, bool signedDst)
{
int eSize = 8 << size;
Debug.Assert(op.Type == OperandType.I64);
Debug.Assert(eSize == 8 || eSize == 16 || eSize == 32 || eSize == 64);
Operand lblEnd = Label();
Operand res = context.Copy(context.AllocateLocal(OperandType.I64), op);
if (shiftLsB >= eSize)
{
context.Copy(res, signedSrc
? EmitSignedSignSatQ(context, op, size)
: EmitUnsignedSignSatQ(context, op, size));
}
else
{
Operand shl = context.ShiftLeft(op, Const(shiftLsB));
if (eSize == 64)
{
Operand sarOrShr = signedSrc
? context.ShiftRightSI(shl, Const(shiftLsB))
: context.ShiftRightUI(shl, Const(shiftLsB));
context.Copy(res, shl);
context.BranchIf(lblEnd, sarOrShr, op, Comparison.Equal);
context.Copy(res, signedSrc
? EmitSignedSignSatQ(context, op, size)
: EmitUnsignedSignSatQ(context, op, size));
}
else
{
context.Copy(res, signedSrc
? EmitSignedSrcSatQ(context, shl, size, signedDst)
: EmitUnsignedSrcSatQ(context, shl, size, signedDst));
}
}
context.MarkLabel(lblEnd);
return res;
}
private static void EmitShlRegOp(ArmEmitterContext context, ShlRegFlags flags = ShlRegFlags.None)
{
bool scalar = flags.HasFlag(ShlRegFlags.Scalar);

View File

@ -130,6 +130,36 @@ namespace ARMeilleure.Instructions
EmitVectorUnaryNarrowOp32(context, (op1) => context.ShiftRightUI(op1, Const(shift)));
}
public static void Vsli_I(ArmEmitterContext context)
{
OpCode32SimdShImm op = (OpCode32SimdShImm)context.CurrOp;
int shift = op.Shift;
int eSize = 8 << op.Size;
ulong mask = shift != 0 ? ulong.MaxValue >> (64 - shift) : 0UL;
Operand res = GetVec(op.Qd);
int elems = op.GetBytesCount() >> op.Size;
for (int index = 0; index < elems; index++)
{
Operand me = EmitVectorExtractZx(context, op.Qm, op.Im + index, op.Size);
Operand neShifted = context.ShiftLeft(me, Const(shift));
Operand de = EmitVectorExtractZx(context, op.Qd, op.Id + index, op.Size);
Operand deMasked = context.BitwiseAnd(de, Const(mask));
Operand e = context.BitwiseOr(neShifted, deMasked);
res = EmitVectorInsert(context, res, e, op.Id + index, op.Size);
}
context.Copy(GetVec(op.Qd), res);
}
public static void Vsra(ArmEmitterContext context)
{
OpCode32SimdShImm op = (OpCode32SimdShImm)context.CurrOp;

View File

@ -384,7 +384,9 @@ namespace ARMeilleure.Instructions
Sqrshrn_V,
Sqrshrun_S,
Sqrshrun_V,
Sqshl_Si,
Sqshl_V,
Sqshl_Vi,
Sqshrn_S,
Sqshrn_V,
Sqshrun_S,
@ -569,6 +571,10 @@ namespace ARMeilleure.Instructions
Umaal,
Umlal,
Umull,
Uqadd16,
Uqadd8,
Uqsub16,
Uqsub8,
Usat,
Usat16,
Usub8,
@ -635,6 +641,7 @@ namespace ARMeilleure.Instructions
Vorn,
Vorr,
Vpadd,
Vpadal,
Vpaddl,
Vpmax,
Vpmin,
@ -642,6 +649,7 @@ namespace ARMeilleure.Instructions
Vqdmulh,
Vqmovn,
Vqmovun,
Vqrdmulh,
Vqrshrn,
Vqrshrun,
Vqshrn,
@ -654,6 +662,7 @@ namespace ARMeilleure.Instructions
Vrintm,
Vrintn,
Vrintp,
Vrintr,
Vrintx,
Vrshr,
Vrshrn,
@ -662,6 +671,7 @@ namespace ARMeilleure.Instructions
Vshll,
Vshr,
Vshrn,
Vsli,
Vst1,
Vst2,
Vst3,
@ -678,6 +688,7 @@ namespace ARMeilleure.Instructions
Vsub,
Vsubl,
Vsubw,
Vswp,
Vtbl,
Vtrn,
Vtst,

View File

@ -91,54 +91,54 @@ namespace ARMeilleure.Instructions
#region "Read"
public static byte ReadByte(ulong address)
{
return GetMemoryManager().ReadTracked<byte>(address);
return GetMemoryManager().ReadGuest<byte>(address);
}
public static ushort ReadUInt16(ulong address)
{
return GetMemoryManager().ReadTracked<ushort>(address);
return GetMemoryManager().ReadGuest<ushort>(address);
}
public static uint ReadUInt32(ulong address)
{
return GetMemoryManager().ReadTracked<uint>(address);
return GetMemoryManager().ReadGuest<uint>(address);
}
public static ulong ReadUInt64(ulong address)
{
return GetMemoryManager().ReadTracked<ulong>(address);
return GetMemoryManager().ReadGuest<ulong>(address);
}
public static V128 ReadVector128(ulong address)
{
return GetMemoryManager().ReadTracked<V128>(address);
return GetMemoryManager().ReadGuest<V128>(address);
}
#endregion
#region "Write"
public static void WriteByte(ulong address, byte value)
{
GetMemoryManager().Write(address, value);
GetMemoryManager().WriteGuest(address, value);
}
public static void WriteUInt16(ulong address, ushort value)
{
GetMemoryManager().Write(address, value);
GetMemoryManager().WriteGuest(address, value);
}
public static void WriteUInt32(ulong address, uint value)
{
GetMemoryManager().Write(address, value);
GetMemoryManager().WriteGuest(address, value);
}
public static void WriteUInt64(ulong address, ulong value)
{
GetMemoryManager().Write(address, value);
GetMemoryManager().WriteGuest(address, value);
}
public static void WriteVector128(ulong address, V128 value)
{
GetMemoryManager().Write(address, value);
GetMemoryManager().WriteGuest(address, value);
}
#endregion

View File

@ -4,7 +4,5 @@ namespace ARMeilleure.Memory
{
IJitMemoryBlock Allocate(ulong size);
IJitMemoryBlock Reserve(ulong size);
ulong GetPageSize();
}
}

View File

@ -28,6 +28,17 @@ namespace ARMeilleure.Memory
/// <returns>The data</returns>
T ReadTracked<T>(ulong va) where T : unmanaged;
/// <summary>
/// Reads data from CPU mapped memory, from guest code. (with read tracking)
/// </summary>
/// <typeparam name="T">Type of the data being read</typeparam>
/// <param name="va">Virtual address of the data in memory</param>
/// <returns>The data</returns>
T ReadGuest<T>(ulong va) where T : unmanaged
{
return ReadTracked<T>(va);
}
/// <summary>
/// Writes data to CPU mapped memory.
/// </summary>
@ -36,6 +47,17 @@ namespace ARMeilleure.Memory
/// <param name="value">Data to be written</param>
void Write<T>(ulong va, T value) where T : unmanaged;
/// <summary>
/// Writes data to CPU mapped memory, from guest code.
/// </summary>
/// <typeparam name="T">Type of the data being written</typeparam>
/// <param name="va">Virtual address to write the data into</param>
/// <param name="value">Data to be written</param>
void WriteGuest<T>(ulong va, T value) where T : unmanaged
{
Write(va, value);
}
/// <summary>
/// Gets a read-only span of data from CPU mapped memory.
/// </summary>

View File

@ -35,18 +35,35 @@ namespace ARMeilleure.Memory
/// Allows invalid access from JIT code to the rest of the program, but is faster.
/// </summary>
HostMappedUnsafe,
/// <summary>
/// High level implementation using a software flat page table for address translation
/// with no support for handling invalid or non-contiguous memory access.
/// </summary>
HostTracked,
/// <summary>
/// High level implementation using a software flat page table for address translation
/// without masking the address and no support for handling invalid or non-contiguous memory access.
/// </summary>
HostTrackedUnsafe,
}
static class MemoryManagerTypeExtensions
public static class MemoryManagerTypeExtensions
{
public static bool IsHostMapped(this MemoryManagerType type)
{
return type == MemoryManagerType.HostMapped || type == MemoryManagerType.HostMappedUnsafe;
}
public static bool IsHostTracked(this MemoryManagerType type)
{
return type == MemoryManagerType.HostTracked || type == MemoryManagerType.HostTrackedUnsafe;
}
public static bool IsHostMappedOrTracked(this MemoryManagerType type)
{
return type == MemoryManagerType.HostTracked || type == MemoryManagerType.HostMapped || type == MemoryManagerType.HostMappedUnsafe;
return type.IsHostMapped() || type.IsHostTracked();
}
}
}

View File

@ -7,6 +7,7 @@ namespace ARMeilleure.Memory
public const int DefaultGranularity = 65536; // Mapping granularity in Windows.
public IJitMemoryBlock Block { get; }
public IJitMemoryAllocator Allocator { get; }
public IntPtr Pointer => Block.Pointer;
@ -21,6 +22,7 @@ namespace ARMeilleure.Memory
granularity = DefaultGranularity;
}
Allocator = allocator;
Block = allocator.Reserve(maxSize);
_maxSize = maxSize;
_sizeGranularity = granularity;

View File

@ -1,63 +1,14 @@
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Memory;
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation;
using ARMeilleure.Translation.Cache;
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
namespace ARMeilleure.Signal
{
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct SignalHandlerRange
public static class NativeSignalHandlerGenerator
{
public int IsActive;
public nuint RangeAddress;
public nuint RangeEndAddress;
public IntPtr ActionPointer;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct SignalHandlerConfig
{
/// <summary>
/// The byte offset of the faulting address in the SigInfo or ExceptionRecord struct.
/// </summary>
public int StructAddressOffset;
/// <summary>
/// The byte offset of the write flag in the SigInfo or ExceptionRecord struct.
/// </summary>
public int StructWriteOffset;
/// <summary>
/// The sigaction handler that was registered before this one. (unix only)
/// </summary>
public nuint UnixOldSigaction;
/// <summary>
/// The type of the previous sigaction. True for the 3 argument variant. (unix only)
/// </summary>
public int UnixOldSigaction3Arg;
public SignalHandlerRange Range0;
public SignalHandlerRange Range1;
public SignalHandlerRange Range2;
public SignalHandlerRange Range3;
public SignalHandlerRange Range4;
public SignalHandlerRange Range5;
public SignalHandlerRange Range6;
public SignalHandlerRange Range7;
}
public static class NativeSignalHandler
{
private delegate void UnixExceptionHandler(int sig, IntPtr info, IntPtr ucontext);
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
private delegate int VectoredExceptionHandler(IntPtr exceptionInfo);
private const int MaxTrackedRanges = 8;
public const int MaxTrackedRanges = 8;
private const int StructAddressOffset = 0;
private const int StructWriteOffset = 4;
@ -70,124 +21,7 @@ namespace ARMeilleure.Signal
private const uint EXCEPTION_ACCESS_VIOLATION = 0xc0000005;
private static ulong _pageSize;
private static ulong _pageMask;
private static readonly IntPtr _handlerConfig;
private static IntPtr _signalHandlerPtr;
private static IntPtr _signalHandlerHandle;
private static readonly object _lock = new();
private static bool _initialized;
static NativeSignalHandler()
{
_handlerConfig = Marshal.AllocHGlobal(Unsafe.SizeOf<SignalHandlerConfig>());
ref SignalHandlerConfig config = ref GetConfigRef();
config = new SignalHandlerConfig();
}
public static void Initialize(IJitMemoryAllocator allocator)
{
JitCache.Initialize(allocator);
}
public static void InitializeSignalHandler(ulong pageSize, Func<IntPtr, IntPtr, IntPtr> customSignalHandlerFactory = null)
{
if (_initialized)
{
return;
}
lock (_lock)
{
if (_initialized)
{
return;
}
_pageSize = pageSize;
_pageMask = pageSize - 1;
ref SignalHandlerConfig config = ref GetConfigRef();
if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
{
_signalHandlerPtr = Marshal.GetFunctionPointerForDelegate(GenerateUnixSignalHandler(_handlerConfig));
if (customSignalHandlerFactory != null)
{
_signalHandlerPtr = customSignalHandlerFactory(UnixSignalHandlerRegistration.GetSegfaultExceptionHandler().sa_handler, _signalHandlerPtr);
}
var old = UnixSignalHandlerRegistration.RegisterExceptionHandler(_signalHandlerPtr);
config.UnixOldSigaction = (nuint)(ulong)old.sa_handler;
config.UnixOldSigaction3Arg = old.sa_flags & 4;
}
else
{
config.StructAddressOffset = 40; // ExceptionInformation1
config.StructWriteOffset = 32; // ExceptionInformation0
_signalHandlerPtr = Marshal.GetFunctionPointerForDelegate(GenerateWindowsSignalHandler(_handlerConfig));
if (customSignalHandlerFactory != null)
{
_signalHandlerPtr = customSignalHandlerFactory(IntPtr.Zero, _signalHandlerPtr);
}
_signalHandlerHandle = WindowsSignalHandlerRegistration.RegisterExceptionHandler(_signalHandlerPtr);
}
_initialized = true;
}
}
private static unsafe ref SignalHandlerConfig GetConfigRef()
{
return ref Unsafe.AsRef<SignalHandlerConfig>((void*)_handlerConfig);
}
public static unsafe bool AddTrackedRegion(nuint address, nuint endAddress, IntPtr action)
{
var ranges = &((SignalHandlerConfig*)_handlerConfig)->Range0;
for (int i = 0; i < MaxTrackedRanges; i++)
{
if (ranges[i].IsActive == 0)
{
ranges[i].RangeAddress = address;
ranges[i].RangeEndAddress = endAddress;
ranges[i].ActionPointer = action;
ranges[i].IsActive = 1;
return true;
}
}
return false;
}
public static unsafe bool RemoveTrackedRegion(nuint address)
{
var ranges = &((SignalHandlerConfig*)_handlerConfig)->Range0;
for (int i = 0; i < MaxTrackedRanges; i++)
{
if (ranges[i].IsActive == 1 && ranges[i].RangeAddress == address)
{
ranges[i].IsActive = 0;
return true;
}
}
return false;
}
private static Operand EmitGenericRegionCheck(EmitterContext context, IntPtr signalStructPtr, Operand faultAddress, Operand isWrite)
private static Operand EmitGenericRegionCheck(EmitterContext context, IntPtr signalStructPtr, Operand faultAddress, Operand isWrite, int rangeStructSize)
{
Operand inRegionLocal = context.AllocateLocal(OperandType.I32);
context.Copy(inRegionLocal, Const(0));
@ -196,7 +30,7 @@ namespace ARMeilleure.Signal
for (int i = 0; i < MaxTrackedRanges; i++)
{
ulong rangeBaseOffset = (ulong)(RangeOffset + i * Unsafe.SizeOf<SignalHandlerRange>());
ulong rangeBaseOffset = (ulong)(RangeOffset + i * rangeStructSize);
Operand nextLabel = Label();
@ -210,13 +44,12 @@ namespace ARMeilleure.Signal
// Is the fault address within this tracked region?
Operand inRange = context.BitwiseAnd(
context.ICompare(faultAddress, rangeAddress, Comparison.GreaterOrEqualUI),
context.ICompare(faultAddress, rangeEndAddress, Comparison.LessUI)
);
context.ICompare(faultAddress, rangeEndAddress, Comparison.LessUI));
// Only call tracking if in range.
context.BranchIfFalse(nextLabel, inRange, BasicBlockFrequency.Cold);
Operand offset = context.BitwiseAnd(context.Subtract(faultAddress, rangeAddress), Const(~_pageMask));
Operand offset = context.Subtract(faultAddress, rangeAddress);
// Call the tracking action, with the pointer's relative offset to the base address.
Operand trackingActionPtr = context.Load(OperandType.I64, Const((ulong)signalStructPtr + rangeBaseOffset + 20));
@ -227,8 +60,10 @@ namespace ARMeilleure.Signal
// Tracking action should be non-null to call it, otherwise assume false return.
context.BranchIfFalse(skipActionLabel, trackingActionPtr);
Operand result = context.Call(trackingActionPtr, OperandType.I32, offset, Const(_pageSize), isWrite);
context.Copy(inRegionLocal, result);
Operand result = context.Call(trackingActionPtr, OperandType.I64, offset, Const(1UL), isWrite);
context.Copy(inRegionLocal, context.ICompareNotEqual(result, Const(0UL)));
GenerateFaultAddressPatchCode(context, faultAddress, result);
context.MarkLabel(skipActionLabel);
@ -269,8 +104,7 @@ namespace ARMeilleure.Signal
Operand esr = context.Load(OperandType.I64, context.Add(ctxPtr, Const(EsrOffset)));
return context.BitwiseAnd(esr, Const(0x40ul));
}
if (RuntimeInformation.ProcessArchitecture == Architecture.X64)
else if (RuntimeInformation.ProcessArchitecture == Architecture.X64)
{
const ulong ErrOffset = 4; // __es.__err
Operand err = context.Load(OperandType.I64, context.Add(ctxPtr, Const(ErrOffset)));
@ -310,8 +144,7 @@ namespace ARMeilleure.Signal
Operand esr = context.Load(OperandType.I64, context.Add(auxPtr, Const(8ul)));
return context.BitwiseAnd(esr, Const(0x40ul));
}
if (RuntimeInformation.ProcessArchitecture == Architecture.X64)
else if (RuntimeInformation.ProcessArchitecture == Architecture.X64)
{
const int ErrOffset = 192; // uc_mcontext.gregs[REG_ERR]
Operand err = context.Load(OperandType.I64, context.Add(ucontextPtr, Const(ErrOffset)));
@ -322,7 +155,7 @@ namespace ARMeilleure.Signal
throw new PlatformNotSupportedException();
}
private static UnixExceptionHandler GenerateUnixSignalHandler(IntPtr signalStructPtr)
public static byte[] GenerateUnixSignalHandler(IntPtr signalStructPtr, int rangeStructSize)
{
EmitterContext context = new();
@ -335,7 +168,7 @@ namespace ARMeilleure.Signal
Operand isWrite = context.ICompareNotEqual(writeFlag, Const(0L)); // Normalize to 0/1.
Operand isInRegion = EmitGenericRegionCheck(context, signalStructPtr, faultAddress, isWrite);
Operand isInRegion = EmitGenericRegionCheck(context, signalStructPtr, faultAddress, isWrite, rangeStructSize);
Operand endLabel = Label();
@ -367,10 +200,10 @@ namespace ARMeilleure.Signal
OperandType[] argTypes = new OperandType[] { OperandType.I32, OperandType.I64, OperandType.I64 };
return Compiler.Compile(cfg, argTypes, OperandType.None, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<UnixExceptionHandler>();
return Compiler.Compile(cfg, argTypes, OperandType.None, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Code;
}
private static VectoredExceptionHandler GenerateWindowsSignalHandler(IntPtr signalStructPtr)
public static byte[] GenerateWindowsSignalHandler(IntPtr signalStructPtr, int rangeStructSize)
{
EmitterContext context = new();
@ -399,7 +232,7 @@ namespace ARMeilleure.Signal
Operand isWrite = context.ICompareNotEqual(writeFlag, Const(0L)); // Normalize to 0/1.
Operand isInRegion = EmitGenericRegionCheck(context, signalStructPtr, faultAddress, isWrite);
Operand isInRegion = EmitGenericRegionCheck(context, signalStructPtr, faultAddress, isWrite, rangeStructSize);
Operand endLabel = Label();
@ -421,7 +254,88 @@ namespace ARMeilleure.Signal
OperandType[] argTypes = new OperandType[] { OperandType.I64 };
return Compiler.Compile(cfg, argTypes, OperandType.I32, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<VectoredExceptionHandler>();
return Compiler.Compile(cfg, argTypes, OperandType.I32, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Code;
}
private static void GenerateFaultAddressPatchCode(EmitterContext context, Operand faultAddress, Operand newAddress)
{
if (RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
{
if (SupportsFaultAddressPatchingForHostOs())
{
Operand lblSkip = Label();
context.BranchIf(lblSkip, faultAddress, newAddress, Comparison.Equal);
Operand ucontextPtr = context.LoadArgument(OperandType.I64, 2);
Operand pcCtxAddress = default;
ulong baseRegsOffset = 0;
if (OperatingSystem.IsLinux())
{
pcCtxAddress = context.Add(ucontextPtr, Const(440UL));
baseRegsOffset = 184UL;
}
else if (OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
{
ucontextPtr = context.Load(OperandType.I64, context.Add(ucontextPtr, Const(48UL)));
pcCtxAddress = context.Add(ucontextPtr, Const(272UL));
baseRegsOffset = 16UL;
}
Operand pc = context.Load(OperandType.I64, pcCtxAddress);
Operand reg = GetAddressRegisterFromArm64Instruction(context, pc);
Operand reg64 = context.ZeroExtend32(OperandType.I64, reg);
Operand regCtxAddress = context.Add(ucontextPtr, context.Add(context.ShiftLeft(reg64, Const(3)), Const(baseRegsOffset)));
Operand regAddress = context.Load(OperandType.I64, regCtxAddress);
Operand addressDelta = context.Subtract(regAddress, faultAddress);
context.Store(regCtxAddress, context.Add(newAddress, addressDelta));
context.MarkLabel(lblSkip);
}
}
}
private static Operand GetAddressRegisterFromArm64Instruction(EmitterContext context, Operand pc)
{
Operand inst = context.Load(OperandType.I32, pc);
Operand reg = context.AllocateLocal(OperandType.I32);
Operand isSysInst = context.ICompareEqual(context.BitwiseAnd(inst, Const(0xFFF80000)), Const(0xD5080000));
Operand lblSys = Label();
Operand lblEnd = Label();
context.BranchIfTrue(lblSys, isSysInst, BasicBlockFrequency.Cold);
context.Copy(reg, context.BitwiseAnd(context.ShiftRightUI(inst, Const(5)), Const(0x1F)));
context.Branch(lblEnd);
context.MarkLabel(lblSys);
context.Copy(reg, context.BitwiseAnd(inst, Const(0x1F)));
context.MarkLabel(lblEnd);
return reg;
}
public static bool SupportsFaultAddressPatchingForHost()
{
return SupportsFaultAddressPatchingForHostArch() && SupportsFaultAddressPatchingForHostOs();
}
private static bool SupportsFaultAddressPatchingForHostArch()
{
return RuntimeInformation.ProcessArchitecture == Architecture.Arm64;
}
private static bool SupportsFaultAddressPatchingForHostOs()
{
return OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() || OperatingSystem.IsIOS();
}
}
}

View File

@ -2,7 +2,7 @@ using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation;
using Ryujinx.Common.Memory.PartialUnmaps;
using System;
using System.Runtime.InteropServices;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
namespace ARMeilleure.Signal
@ -10,8 +10,28 @@ namespace ARMeilleure.Signal
/// <summary>
/// Methods to handle signals caused by partial unmaps. See the structs for C# implementations of the methods.
/// </summary>
internal static class WindowsPartialUnmapHandler
internal static partial class WindowsPartialUnmapHandler
{
[LibraryImport("kernel32.dll", SetLastError = true, EntryPoint = "LoadLibraryA")]
private static partial IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string lpFileName);
[LibraryImport("kernel32.dll", SetLastError = true)]
private static partial IntPtr GetProcAddress(IntPtr hModule, [MarshalAs(UnmanagedType.LPStr)] string procName);
private static IntPtr _getCurrentThreadIdPtr;
public static IntPtr GetCurrentThreadIdFunc()
{
if (_getCurrentThreadIdPtr == IntPtr.Zero)
{
IntPtr handle = LoadLibrary("kernel32.dll");
_getCurrentThreadIdPtr = GetProcAddress(handle, "GetCurrentThreadId");
}
return _getCurrentThreadIdPtr;
}
public static Operand EmitRetryFromAccessViolation(EmitterContext context)
{
IntPtr partialRemapStatePtr = PartialUnmapState.GlobalState;
@ -20,7 +40,7 @@ namespace ARMeilleure.Signal
// Get the lock first.
EmitNativeReaderLockAcquire(context, IntPtr.Add(partialRemapStatePtr, PartialUnmapState.PartialUnmapLockOffset));
IntPtr getCurrentThreadId = WindowsSignalHandlerRegistration.GetCurrentThreadIdFunc();
IntPtr getCurrentThreadId = GetCurrentThreadIdFunc();
Operand threadId = context.Call(Const((ulong)getCurrentThreadId), OperandType.I32);
Operand threadIndex = EmitThreadLocalMapIntGetOrReserve(context, localCountsPtr, threadId, Const(0));
@ -137,17 +157,6 @@ namespace ARMeilleure.Signal
return context.Add(structsPtr, context.SignExtend32(OperandType.I64, offset));
}
#pragma warning disable IDE0051 // Remove unused private member
private static void EmitThreadLocalMapIntRelease(EmitterContext context, IntPtr threadLocalMapPtr, Operand threadId, Operand index)
{
Operand offset = context.Multiply(index, Const(sizeof(int)));
Operand idsPtr = Const((ulong)IntPtr.Add(threadLocalMapPtr, ThreadLocalMap<int>.ThreadIdsOffset));
Operand idPtr = context.Add(idsPtr, context.SignExtend32(OperandType.I64, offset));
context.CompareAndSwap(idPtr, threadId, Const(0));
}
#pragma warning restore IDE0051
private static void EmitAtomicAddI32(EmitterContext context, Operand ptr, Operand additive)
{
Operand loop = Label();

View File

@ -1,44 +0,0 @@
using System;
using System.Runtime.InteropServices;
namespace ARMeilleure.Signal
{
unsafe partial class WindowsSignalHandlerRegistration
{
[LibraryImport("kernel32.dll")]
private static partial IntPtr AddVectoredExceptionHandler(uint first, IntPtr handler);
[LibraryImport("kernel32.dll")]
private static partial ulong RemoveVectoredExceptionHandler(IntPtr handle);
[LibraryImport("kernel32.dll", SetLastError = true, EntryPoint = "LoadLibraryA")]
private static partial IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string lpFileName);
[LibraryImport("kernel32.dll", SetLastError = true)]
private static partial IntPtr GetProcAddress(IntPtr hModule, [MarshalAs(UnmanagedType.LPStr)] string procName);
private static IntPtr _getCurrentThreadIdPtr;
public static IntPtr RegisterExceptionHandler(IntPtr action)
{
return AddVectoredExceptionHandler(1, action);
}
public static bool RemoveExceptionHandler(IntPtr handle)
{
return RemoveVectoredExceptionHandler(handle) != 0;
}
public static IntPtr GetCurrentThreadIdFunc()
{
if (_getCurrentThreadIdPtr == IntPtr.Zero)
{
IntPtr handle = LoadLibrary("kernel32.dll");
_getCurrentThreadIdPtr = GetProcAddress(handle, "GetCurrentThreadId");
}
return _getCurrentThreadIdPtr;
}
}
}

View File

@ -3,6 +3,7 @@ using ARMeilleure.CodeGen.Unwinding;
using ARMeilleure.Memory;
using ARMeilleure.Native;
using Ryujinx.Memory;
using Ryujinx.Common.Logging;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
@ -18,7 +19,7 @@ namespace ARMeilleure.Translation.Cache
private static readonly int _pageMask = _pageSize - 4;
private const int CodeAlignment = 4; // Bytes.
private const int CacheSize = 1024 * 1024 * 1024;
private const int CacheSize = 128 * 1024 * 1024;
private const int CacheSizeIOS = 128 * 1024 * 1024;
private static ReservedRegion _jitRegion;
@ -31,6 +32,10 @@ namespace ARMeilleure.Translation.Cache
private static readonly object _lock = new();
private static bool _initialized;
private static readonly List<ReservedRegion> _jitRegions = new();
private static int _activeRegionIndex = 0;
[SupportedOSPlatform("windows")]
[LibraryImport("kernel32.dll", SetLastError = true)]
public static partial IntPtr FlushInstructionCache(IntPtr hProcess, IntPtr lpAddress, UIntPtr dwSize);
@ -49,7 +54,11 @@ namespace ARMeilleure.Translation.Cache
return;
}
_jitRegion = new ReservedRegion(allocator, (ulong)(OperatingSystem.IsIOS() ? CacheSizeIOS : CacheSize));
var firstRegion = new ReservedRegion(allocator, CacheSize);
_jitRegions.Add(firstRegion);
_activeRegionIndex = 0;
if (!OperatingSystem.IsWindows() && !OperatingSystem.IsMacOS() && !OperatingSystem.IsIOS())
{
@ -60,7 +69,9 @@ namespace ARMeilleure.Translation.Cache
if (OperatingSystem.IsWindows())
{
JitUnwindWindows.InstallFunctionTableHandler(_jitRegion.Pointer, CacheSize, _jitRegion.Pointer + Allocate(_pageSize));
JitUnwindWindows.InstallFunctionTableHandler(
firstRegion.Pointer, CacheSize, firstRegion.Pointer + Allocate(_pageSize)
);
}
_initialized = true;
@ -73,7 +84,9 @@ namespace ARMeilleure.Translation.Cache
{
while (_deferredRxProtect.TryDequeue(out var result))
{
ReprotectAsExecutable(result.funcOffset, result.length);
ReservedRegion targetRegion = _jitRegions[_activeRegionIndex];
ReprotectAsExecutable(targetRegion, result.funcOffset, result.length);
}
}
@ -87,21 +100,14 @@ namespace ARMeilleure.Translation.Cache
int funcOffset = Allocate(code.Length, deferProtect);
IntPtr funcPtr = _jitRegion.Pointer + funcOffset;
ReservedRegion targetRegion = _jitRegions[_activeRegionIndex];
IntPtr funcPtr = targetRegion.Pointer + funcOffset;
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);
}
ReprotectAsExecutable(targetRegion, funcOffset, code.Length);
JitSupportDarwinAot.Invalidate(funcPtr, (ulong)code.Length);
}
else if (OperatingSystem.IsMacOS()&& RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
{
@ -115,9 +121,9 @@ namespace ARMeilleure.Translation.Cache
}
else
{
ReprotectAsWritable(funcOffset, code.Length);
ReprotectAsWritable(targetRegion, funcOffset, code.Length);
Marshal.Copy(code, 0, funcPtr, code.Length);
ReprotectAsExecutable(funcOffset, code.Length);
ReprotectAsExecutable(targetRegion, funcOffset, code.Length);
if (OperatingSystem.IsWindows() && RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
{
@ -139,41 +145,50 @@ namespace ARMeilleure.Translation.Cache
{
if (OperatingSystem.IsIOS())
{
return;
// return;
}
lock (_lock)
{
Debug.Assert(_initialized);
int funcOffset = (int)(pointer.ToInt64() - _jitRegion.Pointer.ToInt64());
if (TryFind(funcOffset, out CacheEntry entry, out int entryIndex) && entry.Offset == funcOffset)
foreach (var region in _jitRegions)
{
_cacheAllocator.Free(funcOffset, AlignCodeSize(entry.Size));
_cacheEntries.RemoveAt(entryIndex);
if (pointer.ToInt64() < region.Pointer.ToInt64() ||
pointer.ToInt64() >= (region.Pointer + CacheSize).ToInt64())
{
continue;
}
int funcOffset = (int)(pointer.ToInt64() - region.Pointer.ToInt64());
if (TryFind(funcOffset, out CacheEntry entry, out int entryIndex) && entry.Offset == funcOffset)
{
_cacheAllocator.Free(funcOffset, AlignCodeSize(entry.Size));
_cacheEntries.RemoveAt(entryIndex);
}
return;
}
}
}
private static void ReprotectAsWritable(int offset, int size)
private static void ReprotectAsWritable(ReservedRegion region, int offset, int size)
{
int endOffs = offset + size;
int regionStart = offset & ~_pageMask;
int regionEnd = (endOffs + _pageMask) & ~_pageMask;
_jitRegion.Block.MapAsRwx((ulong)regionStart, (ulong)(regionEnd - regionStart));
region.Block.MapAsRwx((ulong)regionStart, (ulong)(regionEnd - regionStart));
}
private static void ReprotectAsExecutable(int offset, int size)
private static void ReprotectAsExecutable(ReservedRegion region, int offset, int size)
{
int endOffs = offset + size;
int regionStart = offset & ~_pageMask;
int regionEnd = (endOffs + _pageMask) & ~_pageMask;
_jitRegion.Block.MapAsRx((ulong)regionStart, (ulong)(regionEnd - regionStart));
region.Block.MapAsRx((ulong)regionStart, (ulong)(regionEnd - regionStart));
}
private static int Allocate(int codeSize, bool deferProtect = false)
@ -187,20 +202,35 @@ namespace ARMeilleure.Translation.Cache
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)
for (int i = _activeRegionIndex; i < _jitRegions.Count; i++)
{
throw new OutOfMemoryException("JIT Cache exhausted.");
int allocOffset = _cacheAllocator.Allocate(ref codeSize, alignment);
if (allocOffset >= 0)
{
_jitRegions[i].ExpandIfNeeded((ulong)allocOffset + (ulong)codeSize);
_activeRegionIndex = i;
return allocOffset;
}
}
_jitRegion.ExpandIfNeeded((ulong)allocOffset + (ulong)codeSize);
int exhaustedRegion = _activeRegionIndex;
var newRegion = new ReservedRegion(_jitRegions[0].Allocator, CacheSize);
_jitRegions.Add(newRegion);
_activeRegionIndex = _jitRegions.Count - 1;
return allocOffset;
int newRegionNumber = _activeRegionIndex;
_cacheAllocator = new CacheMemoryAllocator(CacheSize);
int allocOffsetNew = _cacheAllocator.Allocate(ref codeSize, alignment);
if (allocOffsetNew < 0)
{
throw new OutOfMemoryException("Failed to allocate in new Cache Region!");
}
newRegion.ExpandIfNeeded((ulong)allocOffsetNew + (ulong)codeSize);
return allocOffsetNew;
}
private static int AlignCodeSize(int codeSize, bool deferProtect = false)

View File

@ -11,7 +11,7 @@ namespace ARMeilleure.Translation
private int[] _postOrderMap;
public int LocalsCount { get; private set; }
public BasicBlock Entry { get; }
public BasicBlock Entry { get; private set; }
public IntrusiveList<BasicBlock> Blocks { get; }
public BasicBlock[] PostOrderBlocks => _postOrderBlocks;
public int[] PostOrderMap => _postOrderMap;
@ -34,6 +34,15 @@ namespace ARMeilleure.Translation
return result;
}
public void UpdateEntry(BasicBlock newEntry)
{
newEntry.AddSuccessor(Entry);
Entry = newEntry;
Blocks.AddFirst(newEntry);
Update();
}
public void Update()
{
RemoveUnreachableBlocks(Blocks);

View File

@ -30,7 +30,7 @@ namespace ARMeilleure.Translation.PTC
private const string OuterHeaderMagicString = "PTCohd\0\0";
private const string InnerHeaderMagicString = "PTCihd\0\0";
private const uint InternalVersion = 5518; //! To be incremented manually for each change to the ARMeilleure project.
private const uint InternalVersion = 6950; //! To be incremented manually for each change to the ARMeilleure project.
private const string ActualDir = "0";
private const string BackupDir = "1";
@ -414,8 +414,6 @@ namespace ARMeilleure.Translation.PTC
finally
{
ResetCarriersIfNeeded();
GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
}
_waitEvent.Set();
@ -791,8 +789,6 @@ namespace ARMeilleure.Translation.PTC
{
ResetCarriersIfNeeded();
GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
return;
}
@ -858,8 +854,14 @@ namespace ARMeilleure.Translation.PTC
Stopwatch sw = Stopwatch.StartNew();
threads.ForEach((thread) => thread.Start());
threads.ForEach((thread) => thread.Join());
foreach (var thread in threads)
{
thread.Start();
}
foreach (var thread in threads)
{
thread.Join();
}
threads.Clear();
@ -1005,7 +1007,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;
osPlatform |= (OperatingSystem.IsIOS() || Ryujinx.Common.PlatformInfo.IsBionic ? 1u : 0u) << 4;
#pragma warning restore IDE0055
return osPlatform;

View File

@ -89,6 +89,17 @@ namespace ARMeilleure.Translation
public static void RunPass(ControlFlowGraph cfg, ExecutionMode mode)
{
if (cfg.Entry.Predecessors.Count != 0)
{
// We expect the entry block to have no predecessors.
// This is required because we have a implicit context load at the start of the function,
// but if there is a jump to the start of the function, the context load would trash the modified values.
// Here we insert a new entry block that will jump to the existing entry block.
BasicBlock newEntry = new BasicBlock(cfg.Blocks.Count);
cfg.UpdateEntry(newEntry);
}
// Compute local register inputs and outputs used inside blocks.
RegisterMask[] localInputs = new RegisterMask[cfg.Blocks.Count];
RegisterMask[] localOutputs = new RegisterMask[cfg.Blocks.Count];
@ -201,7 +212,7 @@ namespace ARMeilleure.Translation
// The only block without any predecessor should be the entry block.
// It always needs a context load as it is the first block to run.
if (block.Predecessors.Count == 0 || hasContextLoad)
if (block == cfg.Entry || hasContextLoad)
{
long vecMask = globalInputs[block.Index].VecMask;
long intMask = globalInputs[block.Index].IntMask;

View File

@ -57,9 +57,6 @@ namespace ARMeilleure.Translation
private Thread[] _backgroundTranslationThreads;
private volatile int _threadCount;
// FIXME: Remove this once the init logic of the emulator will be redone.
public static readonly ManualResetEvent IsReadyForTranslation = new(false);
public Translator(IJitMemoryAllocator allocator, IMemoryManager memory, bool for64Bits)
{
_allocator = allocator;
@ -105,8 +102,6 @@ namespace ARMeilleure.Translation
{
if (Interlocked.Increment(ref _threadCount) == 1)
{
IsReadyForTranslation.WaitOne();
if (_ptc.State == PtcState.Enabled)
{
Debug.Assert(Functions.Count == 0);

View File

@ -80,7 +80,10 @@ namespace ARMeilleure.Translation
return true;
}
Monitor.Wait(Sync);
if (!_disposed)
{
Monitor.Wait(Sync);
}
}
}

View File

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Platforms>AnyCPU</Platforms>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="OpenTK" />
<PackageReference Include="Ryujinx.SDL2-CS" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,228 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace LibRyujinx.Sample
{
internal static class LibRyujinxInterop
{
private const string dll = "LibRyujinx.dll";
[DllImport(dll, EntryPoint = "initialize")]
public extern static bool Initialize(IntPtr path);
[DllImport(dll, EntryPoint = "graphics_initialize")]
public extern static bool InitializeGraphics(GraphicsConfiguration graphicsConfiguration);
[DllImport(dll, EntryPoint = "device_initialize")]
internal extern static bool InitializeDevice(bool isHostMapped,
bool useHypervisor,
SystemLanguage systemLanguage,
RegionCode regionCode,
bool enableVsync,
bool enableDockedMode,
bool enablePtc,
bool enableInternetAccess,
IntPtr timeZone,
bool ignoreMissingServices);
[DllImport(dll, EntryPoint = "graphics_initialize_renderer")]
internal extern static bool InitializeGraphicsRenderer(GraphicsBackend backend, NativeGraphicsInterop nativeGraphicsInterop);
[DllImport(dll, EntryPoint = "device_load")]
internal extern static bool LoadApplication(IntPtr pathPtr);
[DllImport(dll, EntryPoint = "graphics_renderer_run_loop")]
internal extern static void RunLoop();
[DllImport(dll, EntryPoint = "graphics_renderer_set_size")]
internal extern static void SetRendererSize(int width, int height);
[DllImport(dll, EntryPoint = "graphics_renderer_set_swap_buffer_callback")]
internal extern static void SetSwapBuffersCallback(IntPtr swapBuffers);
[DllImport(dll, EntryPoint = "graphics_renderer_set_vsync")]
internal extern static void SetVsyncState(bool enabled);
[DllImport(dll, EntryPoint = "input_initialize")]
internal extern static void InitializeInput(int width, int height);
[DllImport(dll, EntryPoint = "input_set_client_size")]
internal extern static void SetClientSize(int width, int height);
[DllImport(dll, EntryPoint = "input_set_touch_point")]
internal extern static void SetTouchPoint(int x, int y);
[DllImport(dll, EntryPoint = "input_release_touch_point")]
internal extern static void ReleaseTouchPoint();
[DllImport(dll, EntryPoint = "input_update")]
internal extern static void UpdateInput();
[DllImport(dll, EntryPoint = "input_set_button_pressed")]
public extern static void SetButtonPressed(GamepadButtonInputId button, IntPtr idPtr);
[DllImport(dll, EntryPoint = "input_set_button_released")]
public extern static void SetButtonReleased(GamepadButtonInputId button, IntPtr idPtr);
[DllImport(dll, EntryPoint = "input_set_stick_axis")]
public extern static void SetStickAxis(StickInputId stick, Vector2 axes, IntPtr idPtr);
[DllImport(dll, EntryPoint = "input_connect_gamepad")]
public extern static IntPtr ConnectGamepad(int index);
}
public enum GraphicsBackend
{
Vulkan,
OpenGl
}
public enum BackendThreading
{
Auto,
Off,
On
}
[StructLayout(LayoutKind.Sequential)]
public struct GraphicsConfiguration
{
public float ResScale = 1f;
public float MaxAnisotropy = -1;
public bool FastGpuTime = true;
public bool Fast2DCopy = true;
public bool EnableMacroJit = false;
public bool EnableMacroHLE = true;
public bool EnableShaderCache = true;
public bool EnableTextureRecompression = false;
public BackendThreading BackendThreading = BackendThreading.Auto;
public AspectRatio AspectRatio = AspectRatio.Fixed16x9;
public GraphicsConfiguration()
{
}
}
public enum SystemLanguage
{
Japanese,
AmericanEnglish,
French,
German,
Italian,
Spanish,
Chinese,
Korean,
Dutch,
Portuguese,
Russian,
Taiwanese,
BritishEnglish,
CanadianFrench,
LatinAmericanSpanish,
SimplifiedChinese,
TraditionalChinese,
BrazilianPortuguese,
}
public enum RegionCode
{
Japan,
USA,
Europe,
Australia,
China,
Korea,
Taiwan,
Min = Japan,
Max = Taiwan,
}
public struct NativeGraphicsInterop
{
public IntPtr GlGetProcAddress;
public IntPtr VkNativeContextLoader;
public IntPtr VkCreateSurface;
public IntPtr VkRequiredExtensions;
public int VkRequiredExtensionsCount;
}
public enum AspectRatio
{
Fixed4x3,
Fixed16x9,
Fixed16x10,
Fixed21x9,
Fixed32x9,
Stretched
}
/// <summary>
/// Represent a button from a gamepad.
/// </summary>
public enum GamepadButtonInputId : byte
{
Unbound,
A,
B,
X,
Y,
LeftStick,
RightStick,
LeftShoulder,
RightShoulder,
// Likely axis
LeftTrigger,
// Likely axis
RightTrigger,
DpadUp,
DpadDown,
DpadLeft,
DpadRight,
// Special buttons
Minus,
Plus,
Back = Minus,
Start = Plus,
Guide,
Misc1,
// Xbox Elite paddle
Paddle1,
Paddle2,
Paddle3,
Paddle4,
// PS5 touchpad button
Touchpad,
// Virtual buttons for single joycon
SingleLeftTrigger0,
SingleRightTrigger0,
SingleLeftTrigger1,
SingleRightTrigger1,
Count
}
public enum StickInputId : byte
{
Unbound,
Left,
Right,
Count
}
}

View File

@ -0,0 +1,260 @@
using LibRyujinx.Sample;
using OpenTK.Graphics.OpenGL;
using OpenTK.Mathematics;
using OpenTK.Windowing.Common;
using OpenTK.Windowing.Desktop;
using OpenTK.Windowing.GraphicsLibraryFramework;
using System.Runtime.InteropServices;
namespace LibRyujinx.NativeSample
{
internal class NativeWindow : OpenTK.Windowing.Desktop.NativeWindow
{
private nint del;
public delegate void SwapBuffersCallback();
public delegate IntPtr GetProcAddress(string name);
public delegate IntPtr CreateSurface(IntPtr instance);
private bool _run;
private bool _isVulkan;
private Vector2 _lastPosition;
private bool _mousePressed;
private nint _gamepadIdPtr;
private string? _gamepadId;
public NativeWindow(NativeWindowSettings nativeWindowSettings) : base(nativeWindowSettings)
{
_isVulkan = true;
}
internal unsafe void Start(string gamePath)
{
if (!_isVulkan)
{
MakeCurrent();
}
var getProcAddress = Marshal.GetFunctionPointerForDelegate<GetProcAddress>(x => GLFW.GetProcAddress(x));
var createSurface = Marshal.GetFunctionPointerForDelegate<CreateSurface>( x =>
{
VkHandle surface;
GLFW.CreateWindowSurface(new VkHandle(x) ,this.WindowPtr, null, out surface);
return surface.Handle;
});
var vkExtensions = GLFW.GetRequiredInstanceExtensions();
var pointers = new IntPtr[vkExtensions.Length];
for (int i = 0; i < vkExtensions.Length; i++)
{
pointers[i] = Marshal.StringToHGlobalAnsi(vkExtensions[i]);
}
fixed (IntPtr* ptr = pointers)
{
var nativeGraphicsInterop = new NativeGraphicsInterop()
{
GlGetProcAddress = getProcAddress,
VkRequiredExtensions = (nint)ptr,
VkRequiredExtensionsCount = pointers.Length,
VkCreateSurface = createSurface
};
var success = LibRyujinxInterop.InitializeGraphicsRenderer(_isVulkan ? GraphicsBackend.Vulkan : GraphicsBackend.OpenGl, nativeGraphicsInterop);
var timeZone = Marshal.StringToHGlobalAnsi("UTC");
success = LibRyujinxInterop.InitializeDevice(true,
false,
SystemLanguage.AmericanEnglish,
RegionCode.USA,
true,
true,
true,
false,
timeZone,
false);
LibRyujinxInterop.InitializeInput(ClientSize.X, ClientSize.Y);
Marshal.FreeHGlobal(timeZone);
var path = Marshal.StringToHGlobalAnsi(gamePath);
var loaded = LibRyujinxInterop.LoadApplication(path);
LibRyujinxInterop.SetRendererSize(Size.X, Size.Y);
Marshal.FreeHGlobal(path);
}
_gamepadIdPtr = LibRyujinxInterop.ConnectGamepad(0);
_gamepadId = Marshal.PtrToStringAnsi(_gamepadIdPtr);
if (!_isVulkan)
{
Context.MakeNoneCurrent();
}
_run = true;
var thread = new Thread(new ThreadStart(RunLoop));
thread.Start();
UpdateLoop();
thread.Join();
foreach(var ptr in pointers)
{
Marshal.FreeHGlobal(ptr);
}
Marshal.FreeHGlobal(_gamepadIdPtr);
}
public void RunLoop()
{
del = Marshal.GetFunctionPointerForDelegate<SwapBuffersCallback>(SwapBuffers);
LibRyujinxInterop.SetSwapBuffersCallback(del);
if (!_isVulkan)
{
MakeCurrent();
Context.SwapInterval = 0;
}
/* Task.Run(async () =>
{
await Task.Delay(1000);
LibRyujinxInterop.SetVsyncState(true);
});*/
LibRyujinxInterop.RunLoop();
_run = false;
if (!_isVulkan)
{
Context.MakeNoneCurrent();
}
}
private void SwapBuffers()
{
if (!_isVulkan)
{
this.Context.SwapBuffers();
}
}
protected override void OnMouseMove(MouseMoveEventArgs e)
{
base.OnMouseMove(e);
_lastPosition = e.Position;
}
protected override void OnMouseDown(MouseButtonEventArgs e)
{
base.OnMouseDown(e);
if(e.Button == MouseButton.Left)
{
_mousePressed = true;
}
}
protected override void OnResize(ResizeEventArgs e)
{
base.OnResize(e);
if (_run)
{
LibRyujinxInterop.SetRendererSize(e.Width, e.Height);
LibRyujinxInterop.SetClientSize(e.Width, e.Height);
}
}
protected override void OnMouseUp(MouseButtonEventArgs e)
{
base.OnMouseUp(e);
if (e.Button == MouseButton.Left)
{
_mousePressed = false;
}
}
protected override void OnKeyUp(KeyboardKeyEventArgs e)
{
base.OnKeyUp(e);
if (_gamepadIdPtr != IntPtr.Zero)
{
var key = GetKeyMapping(e.Key);
LibRyujinxInterop.SetButtonReleased(key, _gamepadIdPtr);
}
}
protected override void OnKeyDown(KeyboardKeyEventArgs e)
{
base.OnKeyDown(e);
if (_gamepadIdPtr != IntPtr.Zero)
{
var key = GetKeyMapping(e.Key);
LibRyujinxInterop.SetButtonPressed(key, _gamepadIdPtr);
}
}
public void UpdateLoop()
{
while(_run)
{
ProcessWindowEvents(true);
NewInputFrame();
ProcessWindowEvents(IsEventDriven);
if (_mousePressed)
{
LibRyujinxInterop.SetTouchPoint((int)_lastPosition.X, (int)_lastPosition.Y);
}
else
{
LibRyujinxInterop.ReleaseTouchPoint();
}
LibRyujinxInterop.UpdateInput();
Thread.Sleep(1);
}
}
public GamepadButtonInputId GetKeyMapping(Keys key)
{
if(_keyMapping.TryGetValue(key, out var mapping))
{
return mapping;
}
return GamepadButtonInputId.Unbound;
}
private Dictionary<Keys, GamepadButtonInputId> _keyMapping = new Dictionary<Keys, GamepadButtonInputId>()
{
{Keys.A, GamepadButtonInputId.A },
{Keys.S, GamepadButtonInputId.B },
{Keys.Z, GamepadButtonInputId.X },
{Keys.X, GamepadButtonInputId.Y },
{Keys.Equal, GamepadButtonInputId.Plus },
{Keys.Minus, GamepadButtonInputId.Minus },
{Keys.Q, GamepadButtonInputId.LeftShoulder },
{Keys.D1, GamepadButtonInputId.LeftTrigger },
{Keys.W, GamepadButtonInputId.RightShoulder },
{Keys.D2, GamepadButtonInputId.RightTrigger },
{Keys.E, GamepadButtonInputId.LeftStick },
{Keys.R, GamepadButtonInputId.RightStick },
{Keys.Up, GamepadButtonInputId.DpadUp },
{Keys.Down, GamepadButtonInputId.DpadDown },
{Keys.Left, GamepadButtonInputId.DpadLeft },
{Keys.Right, GamepadButtonInputId.DpadRight },
{Keys.U, GamepadButtonInputId.SingleLeftTrigger0 },
{Keys.D7, GamepadButtonInputId.SingleLeftTrigger1 },
{Keys.O, GamepadButtonInputId.SingleRightTrigger0 },
{Keys.D9, GamepadButtonInputId.SingleRightTrigger1 }
};
}
}

View File

@ -0,0 +1,33 @@
using LibRyujinx.Sample;
using OpenTK.Mathematics;
using OpenTK.Windowing.Common;
using OpenTK.Windowing.Desktop;
namespace LibRyujinx.NativeSample
{
internal class Program
{
static void Main(string[] args)
{
if (args.Length > 0)
{
var success = LibRyujinxInterop.Initialize(IntPtr.Zero);
success = LibRyujinxInterop.InitializeGraphics(new GraphicsConfiguration());
var nativeWindowSettings = new NativeWindowSettings()
{
ClientSize = new Vector2i(800, 600),
Title = "Ryujinx Native",
API = ContextAPI.NoAPI,
IsEventDriven = false,
// This is needed to run on macos
Flags = ContextFlags.ForwardCompatible,
};
using var window = new NativeWindow(nativeWindowSettings);
window.IsVisible = true;
window.Start(args[0]);
}
}
}
}

View File

@ -0,0 +1,49 @@
using Ryujinx.Common.Logging;
using Ryujinx.Common.Logging.Formatters;
using Ryujinx.Common.Logging.Targets;
using System;
namespace LibRyujinx
{
public class AndroidLogTarget : ILogTarget
{
private readonly string _name;
private readonly DefaultLogFormatter _formatter;
string ILogTarget.Name { get => _name; }
public AndroidLogTarget(string name)
{
_name = name;
_formatter = new DefaultLogFormatter();
}
public void Log(object sender, LogEventArgs args)
{
Logcat.AndroidLogPrint(GetLogLevel(args.Level), _name, _formatter.Format(args));
}
private static Logcat.LogLevel GetLogLevel(LogLevel logLevel)
{
return logLevel switch
{
LogLevel.Debug => Logcat.LogLevel.Debug,
LogLevel.Stub => Logcat.LogLevel.Info,
LogLevel.Info => Logcat.LogLevel.Info,
LogLevel.Warning => Logcat.LogLevel.Warn,
LogLevel.Error => Logcat.LogLevel.Error,
LogLevel.Guest => Logcat.LogLevel.Info,
LogLevel.AccessLog => Logcat.LogLevel.Info,
LogLevel.Notice => Logcat.LogLevel.Info,
LogLevel.Trace => Logcat.LogLevel.Verbose,
_ => throw new NotImplementedException(),
};
}
public void Dispose()
{
GC.SuppressFinalize(this);
}
}
}

View File

@ -0,0 +1,114 @@
using LibHac.Tools.Fs;
using Ryujinx.Common.Logging;
using Ryujinx.HLE;
using Ryujinx.HLE.HOS.Applets;
using Ryujinx.HLE.HOS.Applets.SoftwareKeyboard;
using Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.ApplicationProxy.Types;
using Ryujinx.HLE.UI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace LibRyujinx.Android
{
internal class AndroidUIHandler : IHostUIHandler, IDisposable
{
private bool _isDisposed;
private bool _isOkPressed;
private string? _input;
private ManualResetEvent _resetEvent = new ManualResetEvent(false);
public IHostUITheme HostUITheme => throw new NotImplementedException();
public IDynamicTextInputHandler CreateDynamicTextInputHandler()
{
throw new NotImplementedException();
}
public bool DisplayErrorAppletDialog(string title, string message, string[] buttonsText)
{
Interop.UpdateUiHandler(title ?? "",
message ?? "",
"",
1,
0,
0,
KeyboardMode.Default,
"",
"");
return _isOkPressed;
}
public bool DisplayInputDialog(SoftwareKeyboardUIArgs args, out string userText)
{
_input = null;
_resetEvent.Reset();
Interop.UpdateUiHandler("Software Keyboard",
args.HeaderText ?? "",
args.GuideText ?? "",
2,
args.StringLengthMin,
args.StringLengthMax,
args.KeyboardMode,
args.SubtitleText ?? "",
args.InitialText ?? "");
_resetEvent.WaitOne();
userText = _input ?? "";
return _isOkPressed;
}
public bool DisplayMessageDialog(string title, string message)
{
Interop.UpdateUiHandler(title ?? "",
message ?? "",
"",
1,
0,
0,
KeyboardMode.Default,
"",
"");
return _isOkPressed;
}
public bool DisplayMessageDialog(ControllerAppletUIArgs args)
{
string playerCount = args.PlayerCountMin == args.PlayerCountMax ? $"exactly {args.PlayerCountMin}" : $"{args.PlayerCountMin}-{args.PlayerCountMax}";
string message = $"Application requests **{playerCount}** player(s) with:\n\n"
+ $"**TYPES:** {args.SupportedStyles}\n\n"
+ $"**PLAYERS:** {string.Join(", ", args.SupportedPlayers)}\n\n"
+ (args.IsDocked ? "Docked mode set. `Handheld` is also invalid.\n\n" : "")
+ "_Please reconfigure Input now and then press OK._";
return DisplayMessageDialog("Controller Applet", message);
}
public void ExecuteProgram(Switch device, ProgramSpecifyKind kind, ulong value)
{
// throw new NotImplementedException();
}
internal void SetResponse(bool isOkPressed, string input)
{
if (_isDisposed)
return;
_isOkPressed = isOkPressed;
_input = input;
_resetEvent.Set();
}
public void Dispose()
{
_isDisposed = true;
}
}
}

View File

@ -0,0 +1,232 @@
using LibRyujinx.Jni;
using LibRyujinx.Jni.Identifiers;
using LibRyujinx.Jni.Pointers;
using LibRyujinx.Jni.Primitives;
using LibRyujinx.Jni.References;
using LibRyujinx.Jni.Values;
using Rxmxnx.PInvoke;
using Ryujinx.Common.Logging;
using Ryujinx.Common.Memory;
using Ryujinx.HLE.HOS.Applets.SoftwareKeyboard;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace LibRyujinx.Android
{
internal unsafe static class Interop
{
internal const string BaseClassName = "org/ryujinx/android/RyujinxNative";
private static JGlobalRef? _classId;
private static ConcurrentDictionary<(string method, string descriptor), JMethodId> _methodCache = new ConcurrentDictionary<(string method, string descriptor), JMethodId>();
private static (string name, string descriptor)[] _methods = new[]
{
("test", "()V"),
("updateUiHandler", "(JJJIIIIJJ)V"),
("frameEnded", "()V"),
("updateProgress", "(JF)V"),
("getSurfacePtr", "()J"),
("getWindowHandle", "()J")
};
internal static void Initialize(JEnvRef jniEnv)
{
var vm = JniHelper.GetVirtualMachine(jniEnv);
if (_classId == null)
{
var className = new ReadOnlySpan<Byte>(Encoding.UTF8.GetBytes(BaseClassName));
using (IReadOnlyFixedMemory<Byte>.IDisposable cName = className.GetUnsafeValPtr()
.GetUnsafeFixedContext(className.Length))
{
_classId = JniHelper.GetGlobalClass(jniEnv, cName);
if (_classId == null)
{
Logger.Info?.Print(LogClass.Application, $"Class Id {BaseClassName} not found");
return;
}
}
}
foreach (var x in _methods)
{
CacheMethod(jniEnv, x.name, x.descriptor);
}
JniEnv._jvm = vm;
}
private static void CacheMethod(JEnvRef jEnv, string name, string descriptor)
{
if (!_methodCache.TryGetValue((name, descriptor), out var method))
{
var methodName = new ReadOnlySpan<Byte>(Encoding.UTF8.GetBytes(name));
var descriptorId = new ReadOnlySpan<Byte>(Encoding.UTF8.GetBytes(descriptor));
using (IReadOnlyFixedMemory<Byte>.IDisposable mName = methodName.GetUnsafeValPtr()
.GetUnsafeFixedContext(methodName.Length))
using (IReadOnlyFixedMemory<Byte>.IDisposable dName = descriptorId.GetUnsafeValPtr()
.GetUnsafeFixedContext(descriptorId.Length))
{
var methodId = JniHelper.GetStaticMethodId(jEnv, (JClassLocalRef)(_classId.Value.Value), mName, dName);
if (methodId == null)
{
Logger.Warning?.Print(LogClass.Application, $"Java Method Id {name} not found");
return;
}
method = methodId.Value;
_methodCache[(name, descriptor)] = method;
}
}
}
private static void CallVoidMethod(string name, string descriptor, params JValue[] values)
{
using var env = JniEnv.Create();
if (_methodCache.TryGetValue((name, descriptor), out var method))
{
if (descriptor.EndsWith("V"))
{
JniHelper.CallStaticVoidMethod(env.Env, (JClassLocalRef)(_classId.Value.Value), method, values);
}
}
}
private static JLong CallLongMethod(string name, string descriptor, params JValue[] values)
{
using var env = JniEnv.Create();
if (_methodCache.TryGetValue((name, descriptor), out var method))
{
if (descriptor.EndsWith("J"))
return JniHelper.CallStaticLongMethod(env.Env, (JClassLocalRef)(_classId.Value.Value), method, values) ?? (JLong)(-1);
}
return (JLong)(-1);
}
public static void Test()
{
CallVoidMethod("test", "()V");
}
public static void FrameEnded(double time)
{
CallVoidMethod("frameEnded", "()V");
}
public static void UpdateProgress(string info, float progress)
{
using var infoPtr = new TempNativeString(info);
CallVoidMethod("updateProgress", "(JF)V", new JValue[]
{
JValue.Create(infoPtr.AsBytes()),
JValue.Create(progress.AsBytes())
});
}
public static JLong GetSurfacePtr()
{
return CallLongMethod("getSurfacePtr", "()J");
}
public static JLong GetWindowsHandle()
{
return CallLongMethod("getWindowHandle", "()J");
}
public static void UpdateUiHandler(string newTitle,
string newMessage,
string newWatermark,
int newType,
int min,
int max,
KeyboardMode nMode,
string newSubtitle,
string newInitialText)
{
using var titlePointer = new TempNativeString(newTitle);
using var messagePointer = new TempNativeString(newMessage);
using var watermarkPointer = new TempNativeString(newWatermark);
using var subtitlePointer = new TempNativeString(newSubtitle);
using var newInitialPointer = new TempNativeString(newInitialText);
CallVoidMethod("updateUiHandler", "(JJJIIIIJJ)V", new JValue[]
{
JValue.Create(titlePointer.AsBytes()),
JValue.Create(messagePointer.AsBytes()),
JValue.Create(watermarkPointer.AsBytes()),
JValue.Create(newType.AsBytes()),
JValue.Create(min.AsBytes()),
JValue.Create(max.AsBytes()),
JValue.Create(nMode.AsBytes()),
JValue.Create(subtitlePointer.AsBytes()),
JValue.Create(newInitialPointer.AsBytes())
});
}
private class TempNativeString : IDisposable
{
private JLong _jPointer;
public TempNativeString(string value)
{
Pointer = Marshal.StringToHGlobalAuto(value);
JPointer = (JLong)Pointer;
}
public nint Pointer { get; private set; }
public JLong JPointer { get => _jPointer; private set => _jPointer = value; }
public Span<byte> AsBytes()
{
return _jPointer.AsBytes();
}
public void Dispose()
{
if (Pointer != IntPtr.Zero)
{
Marshal.FreeHGlobal(Pointer);
}
Pointer = IntPtr.Zero;
}
}
private class JniEnv : IDisposable
{
internal static JavaVMRef? _jvm;
private readonly JEnvRef _env;
private readonly bool _newAttach;
public JEnvRef Env => _env;
private JniEnv(JEnvRef env, bool newAttach)
{
_env = env;
_newAttach = newAttach;
}
public void Dispose()
{
if(_newAttach)
{
JniHelper.Detach(_jvm!.Value);
}
}
public static JniEnv? Create()
{
bool newAttach = false;
ReadOnlySpan<Byte> threadName = "JvmCall"u8;
var env = _jvm == null ? default : JniHelper.Attach(_jvm.Value, threadName.GetUnsafeValPtr().GetUnsafeFixedContext(threadName.Length),
out newAttach);
return env != null ? new JniEnv(env.Value, newAttach) : null;
}
}
}
}

View File

@ -0,0 +1,357 @@
using LibRyujinx.Jni.Identifiers;
using LibRyujinx.Jni.Pointers;
using LibRyujinx.Jni.Primitives;
using LibRyujinx.Jni.References;
using LibRyujinx.Jni.Values;
using System;
using Rxmxnx.PInvoke;
namespace LibRyujinx.Jni;
internal delegate Int32 GetVersionDelegate(JEnvRef env);
internal delegate JResult RegisterNativesDelegate(JEnvRef env, JClassLocalRef jClass,
ReadOnlyValPtr<JNativeMethod> methods0, Int32 nMethods);
internal delegate JResult UnregisterNativesDelegate(JEnvRef env, JClassLocalRef jClass);
internal delegate JResult MonitorEnterDelegate(JEnvRef env, JObjectLocalRef jClass);
internal delegate JResult MonitorExitDelegate(JEnvRef env, JObjectLocalRef jClass);
internal delegate JResult GetVirtualMachineDelegate(JEnvRef env, out JavaVMRef jvm);
internal delegate JResult DestroyVirtualMachineDelegate(JavaVMRef vm);
internal delegate JResult AttachCurrentThreadDelegate(JavaVMRef vm, out JEnvRef env, in JavaVMAttachArgs args);
internal delegate JResult DetachCurrentThreadDelegate(JavaVMRef vm);
internal delegate JResult GetEnvDelegate(JavaVMRef vm, out JEnvRef env, Int32 version);
internal delegate JResult AttachCurrentThreadAsDaemonDelegate(JavaVMRef vm, out JEnvRef env, in JavaVMAttachArgs args);
internal delegate JResult GetCreatedVirtualMachinesDelegate(ValPtr<JavaVMRef> buffer0, Int32 bufferLength,
out Int32 totalVms);
internal delegate JStringLocalRef NewStringDelegate(JEnvRef env, ReadOnlyValPtr<Char> chars0, Int32 length);
internal delegate Int32 GetStringLengthDelegate(JEnvRef env, JStringLocalRef jString);
internal delegate ReadOnlyValPtr<Char>
GetStringCharsDelegate(JEnvRef env, JStringLocalRef jString, out JBoolean isCopy);
internal delegate void ReleaseStringCharsDelegate(JEnvRef env, JStringLocalRef jString, ReadOnlyValPtr<Char> chars0);
internal delegate JStringLocalRef NewStringUtfDelegate(JEnvRef env, ReadOnlyValPtr<Byte> utf8Chars0);
internal delegate Int32 GetStringUtfLengthDelegate(JEnvRef env, JStringLocalRef jString);
internal delegate ReadOnlyValPtr<Byte> GetStringUtfCharsDelegate(JEnvRef env, JStringLocalRef jString,
out JBoolean isCopy);
internal delegate void ReleaseStringUtfCharsDelegate(JEnvRef env, JStringLocalRef jString,
ReadOnlyValPtr<Byte> utf8Chars0);
internal delegate void GetStringRegionDelegate(JEnvRef env, JStringLocalRef jString, Int32 startIndex, Int32 length,
ValPtr<Char> buffer0);
internal delegate void GetStringUtfRegionDelegate(JEnvRef env, JStringLocalRef jString, Int32 startIndex, Int32 length,
ValPtr<Byte> buffer0);
internal delegate ReadOnlyValPtr<Char> GetStringCriticalDelegate(JEnvRef env, JStringLocalRef jString,
out JBoolean isCopy);
internal delegate void ReleaseStringCriticalDelegate(JEnvRef env, JStringLocalRef jString, ReadOnlyValPtr<Char> chars0);
internal delegate JObjectLocalRef CallStaticObjectMethodADelegate(JEnvRef env, JClassLocalRef jClass, JMethodId jMethod,
ReadOnlyValPtr<JValue> args0);
internal delegate JBoolean CallStaticBooleanMethodADelegate(JEnvRef env, JClassLocalRef jClass, JMethodId jMethod,
ReadOnlyValPtr<JValue> args0);
internal delegate JByte CallStaticByteMethodADelegate(JEnvRef env, JClassLocalRef jClass, JMethodId jMethod,
ReadOnlyValPtr<JValue> args0);
internal delegate JChar CallStaticCharMethodADelegate(JEnvRef env, JClassLocalRef jClass, JMethodId jMethod,
ReadOnlyValPtr<JValue> args0);
internal delegate JShort CallStaticShortMethodADelegate(JEnvRef env, JClassLocalRef jClass, JMethodId jMethod,
ReadOnlyValPtr<JValue> args0);
internal delegate JInt CallStaticIntMethodADelegate(JEnvRef env, JClassLocalRef jClass, JMethodId jMethod,
ReadOnlyValPtr<JValue> args0);
internal delegate JLong CallStaticLongMethodADelegate(JEnvRef env, JClassLocalRef jClass, JMethodId jMethod,
ReadOnlyValPtr<JValue> args0);
internal delegate JFloat CallStaticFloatMethodADelegate(JEnvRef env, JClassLocalRef jClass, JMethodId jMethod,
ReadOnlyValPtr<JValue> args0);
internal delegate JDouble CallStaticDoubleMethodADelegate(JEnvRef env, JClassLocalRef jClass, JMethodId jMethod,
ReadOnlyValPtr<JValue> args0);
internal delegate void CallStaticVoidMethodADelegate(JEnvRef env, JClassLocalRef jClass, JMethodId jMethod,
ReadOnlyValPtr<JValue> args0);
internal delegate JObjectLocalRef GetStaticObjectFieldDelegate(JEnvRef env, JClassLocalRef jClass, JFieldId jField);
internal delegate JBoolean GetStaticBooleanFieldDelegate(JEnvRef env, JClassLocalRef jClass, JFieldId jField);
internal delegate JByte GetStaticByteFieldDelegate(JEnvRef env, JClassLocalRef jClass, JFieldId jField);
internal delegate JChar GetStaticCharFieldDelegate(JEnvRef env, JClassLocalRef jClass, JFieldId jField);
internal delegate JShort GetStaticShortFieldDelegate(JEnvRef env, JClassLocalRef jClass, JFieldId jField);
internal delegate JInt GetStaticIntFieldDelegate(JEnvRef env, JClassLocalRef jClass, JFieldId jField);
internal delegate JLong GetStaticLongFieldDelegate(JEnvRef env, JClassLocalRef jClass, JFieldId jField);
internal delegate JFloat GetStaticFloatFieldDelegate(JEnvRef env, JClassLocalRef jClass, JFieldId jField);
internal delegate JDouble GetStaticDoubleFieldDelegate(JEnvRef env, JClassLocalRef jClass, JFieldId jField);
internal delegate void SetStaticObjectFieldDelegate(JEnvRef env, JClassLocalRef jClass, JFieldId jField,
JObjectLocalRef value);
internal delegate void SetStaticBooleanFieldDelegate(JEnvRef env, JClassLocalRef jClass, JFieldId jField,
JBoolean value);
internal delegate void SetStaticByteFieldDelegate(JEnvRef env, JClassLocalRef jClass, JFieldId jField, JByte value);
internal delegate void SetStaticCharFieldDelegate(JEnvRef env, JClassLocalRef jClass, JFieldId jField, JChar value);
internal delegate void SetStaticShortFieldDelegate(JEnvRef env, JClassLocalRef jClass, JFieldId jField, JShort value);
internal delegate void SetStaticIntFieldDelegate(JEnvRef env, JClassLocalRef jClass, JFieldId jField, JInt value);
internal delegate void SetStaticLongFieldDelegate(JEnvRef env, JClassLocalRef jClass, JFieldId jField, JLong value);
internal delegate void SetStaticFloatFieldDelegate(JEnvRef env, JClassLocalRef jClass, JFieldId jField, JFloat value);
internal delegate void SetStaticDoubleFieldDelegate(JEnvRef env, JClassLocalRef jClass, JFieldId jField, JDouble value);
internal delegate JMethodId FromReflectedMethodDelegate(JEnvRef env, JObjectLocalRef method);
internal delegate JFieldId FromReflectedFieldDelegate(JEnvRef env, JObjectLocalRef field);
internal delegate JResult PushLocalFrameDelegate(JEnvRef env, Int32 capacity);
internal delegate JObjectLocalRef PopLocalFrameDelegate(JEnvRef env, JObjectLocalRef result);
internal delegate JGlobalRef NewGlobalRefDelegate(JEnvRef env, JObjectLocalRef localRef);
internal delegate void DeleteGlobalRefDelegate(JEnvRef env, JGlobalRef globalRef);
internal delegate void DeleteLocalRefDelegate(JEnvRef env, JObjectLocalRef localRef);
internal delegate JBoolean IsSameObjectDelegate(JEnvRef env, JObjectLocalRef obj1, JObjectLocalRef obj2);
internal delegate JObjectLocalRef NewLocalRefDelegate(JEnvRef env, JObjectLocalRef objRef);
internal delegate JResult EnsureLocalCapacityDelegate(JEnvRef env, Int32 capacity);
internal delegate JWeakRef NewWeakGlobalRefDelegate(JEnvRef env, JObjectLocalRef obj);
internal delegate void DeleteWeakGlobalRefDelegate(JEnvRef env, JWeakRef jWeak);
internal delegate JReferenceType GetObjectRefTypeDelegate(JEnvRef env, JObjectLocalRef obj);
internal delegate JObjectLocalRef CallNonVirtualObjectMethodADelegate(JEnvRef env, JObjectLocalRef obj,
JClassLocalRef jClass, JMethodId jMethod, ReadOnlyValPtr<JValue> args0);
internal delegate JBoolean CallNonVirtualBooleanMethodADelegate(JEnvRef env, JObjectLocalRef obj, JClassLocalRef jClass,
JMethodId jMethod, ReadOnlyValPtr<JValue> args0);
internal delegate JByte CallNonVirtualByteMethodADelegate(JEnvRef env, JObjectLocalRef obj, JClassLocalRef jClass,
JMethodId jMethod, ReadOnlyValPtr<JValue> args0);
internal delegate JChar CallNonVirtualCharMethodADelegate(JEnvRef env, JObjectLocalRef obj, JClassLocalRef jClass,
JMethodId jMethod, ReadOnlyValPtr<JValue> args0);
internal delegate JShort CallNonVirtualShortMethodADelegate(JEnvRef env, JObjectLocalRef obj, JClassLocalRef jClass,
JMethodId jMethod, ReadOnlyValPtr<JValue> args0);
internal delegate JInt CallNonVirtualIntMethodADelegate(JEnvRef env, JObjectLocalRef obj, JClassLocalRef jClass,
JMethodId jMethod, ReadOnlyValPtr<JValue> args0);
internal delegate JLong CallNonVirtualLongMethodADelegate(JEnvRef env, JObjectLocalRef obj, JClassLocalRef jClass,
JMethodId jMethod, ReadOnlyValPtr<JValue> args0);
internal delegate JFloat CallNonVirtualFloatMethodADelegate(JEnvRef env, JObjectLocalRef obj, JClassLocalRef jClass,
JMethodId jMethod, ReadOnlyValPtr<JValue> args0);
internal delegate JDouble CallNonVirtualDoubleMethodADelegate(JEnvRef env, JObjectLocalRef obj, JClassLocalRef jClass,
JMethodId jMethod, ReadOnlyValPtr<JValue> args0);
internal delegate void CallNonVirtualVoidMethodADelegate(JEnvRef env, JObjectLocalRef obj, JClassLocalRef jClass,
JMethodId jMethod, ReadOnlyValPtr<JValue> args0);
internal delegate JObjectLocalRef CallObjectMethodADelegate(JEnvRef env, JObjectLocalRef obj, JMethodId jMethod,
ReadOnlyValPtr<JValue> args0);
internal delegate JBoolean CallBooleanMethodADelegate(JEnvRef env, JObjectLocalRef obj, JMethodId jMethod,
ReadOnlyValPtr<JValue> args0);
internal delegate JByte CallByteMethodADelegate(JEnvRef env, JObjectLocalRef obj, JMethodId jMethod,
ReadOnlyValPtr<JValue> args0);
internal delegate JChar CallCharMethodADelegate(JEnvRef env, JObjectLocalRef obj, JMethodId jMethod,
ReadOnlyValPtr<JValue> args0);
internal delegate JShort CallShortMethodADelegate(JEnvRef env, JObjectLocalRef obj, JMethodId jMethod,
ReadOnlyValPtr<JValue> args0);
internal delegate JInt CallIntMethodADelegate(JEnvRef env, JObjectLocalRef obj, JMethodId jMethod,
ReadOnlyValPtr<JValue> args0);
internal delegate JLong CallLongMethodADelegate(JEnvRef env, JObjectLocalRef obj, JMethodId jMethod,
ReadOnlyValPtr<JValue> args0);
internal delegate JFloat CallFloatMethodADelegate(JEnvRef env, JObjectLocalRef obj, JMethodId jMethod,
ReadOnlyValPtr<JValue> args0);
internal delegate JDouble CallDoubleMethodADelegate(JEnvRef env, JObjectLocalRef obj, JMethodId jMethod,
ReadOnlyValPtr<JValue> args0);
internal delegate void CallVoidMethodADelegate(JEnvRef env, JObjectLocalRef obj, JMethodId jMethod,
ReadOnlyValPtr<JValue> args0);
internal delegate JObjectLocalRef GetObjectFieldDelegate(JEnvRef env, JObjectLocalRef obj, JFieldId jField);
internal delegate JBoolean GetBooleanFieldDelegate(JEnvRef env, JObjectLocalRef obj, JFieldId jField);
internal delegate JByte GetByteFieldDelegate(JEnvRef env, JObjectLocalRef obj, JFieldId jField);
internal delegate JChar GetCharFieldDelegate(JEnvRef env, JObjectLocalRef obj, JFieldId jField);
internal delegate JShort GetShortFieldDelegate(JEnvRef env, JObjectLocalRef obj, JFieldId jField);
internal delegate JInt GetIntFieldDelegate(JEnvRef env, JObjectLocalRef obj, JFieldId jField);
internal delegate JLong GetLongFieldDelegate(JEnvRef env, JObjectLocalRef obj, JFieldId jField);
internal delegate JFloat GetFloatFieldDelegate(JEnvRef env, JObjectLocalRef obj, JFieldId jField);
internal delegate JDouble GetDoubleFieldDelegate(JEnvRef env, JObjectLocalRef obj, JFieldId jField);
internal delegate void SetObjectFieldDelegate(JEnvRef env, JObjectLocalRef obj, JFieldId jField, JObjectLocalRef value);
internal delegate void SetBooleanFieldDelegate(JEnvRef env, JObjectLocalRef obj, JFieldId jField, JBoolean value);
internal delegate void SetByteFieldDelegate(JEnvRef env, JObjectLocalRef obj, JFieldId jField, JByte value);
internal delegate void SetCharFieldDelegate(JEnvRef env, JObjectLocalRef obj, JFieldId jField, JChar value);
internal delegate void SetShortFieldDelegate(JEnvRef env, JObjectLocalRef obj, JFieldId jField, JShort value);
internal delegate void SetIntFieldDelegate(JEnvRef env, JObjectLocalRef obj, JFieldId jField, JInt value);
internal delegate void SetLongFieldDelegate(JEnvRef env, JObjectLocalRef obj, JFieldId jField, JLong value);
internal delegate void SetFloatFieldDelegate(JEnvRef env, JObjectLocalRef obj, JFieldId jField, JFloat value);
internal delegate void SetDoubleFieldDelegate(JEnvRef env, JObjectLocalRef obj, JFieldId jField, JDouble value);
internal delegate JResult ThrowDelegate(JEnvRef env, JThrowableLocalRef obj);
internal delegate JResult ThrowNewDelegate(JEnvRef env, JClassLocalRef jClass, ReadOnlyValPtr<Byte> messageChars0);
internal delegate JThrowableLocalRef ExceptionOccurredDelegate(JEnvRef env);
internal delegate void ExceptionDescribeDelegate(JEnvRef env);
internal delegate void ExceptionClearDelegate(JEnvRef env);
internal delegate void FatalErrorDelegate(JEnvRef env, ReadOnlyValPtr<Byte> messageChars0);
internal delegate JBoolean ExceptionCheckDelegate(JEnvRef env);
internal delegate JObjectLocalRef NewDirectByteBufferDelegate(JEnvRef env, IntPtr address, Int64 capacity);
internal delegate IntPtr GetDirectBufferAddressDelegate(JEnvRef env, JObjectLocalRef buffObj);
internal delegate Int64 GetDirectBufferCapacityDelegate(JEnvRef env, JObjectLocalRef buffObj);
internal delegate JClassLocalRef DefineClassDelegate(JEnvRef env, ReadOnlyValPtr<Byte> nameChars0,
JObjectLocalRef loader, IntPtr binaryData, Int32 len);
internal delegate JClassLocalRef FindClassDelegate(JEnvRef env, ReadOnlyValPtr<Byte> nameChars0);
internal delegate JObjectLocalRef ToReflectedMethodDelegate(JEnvRef env, JClassLocalRef jClass, JMethodId methodId,
JBoolean isStatic);
internal delegate JClassLocalRef GetSuperclassDelegate(JEnvRef env, JClassLocalRef sub);
internal delegate JBoolean IsAssignableFromDelegate(JEnvRef env, JClassLocalRef sub, JClassLocalRef sup);
internal delegate JClassLocalRef GetObjectClassDelegate(JEnvRef env, JObjectLocalRef obj);
internal delegate JBoolean IsInstanceOfDelegate(JEnvRef env, JObjectLocalRef obj, JClassLocalRef jClass);
internal delegate JObjectLocalRef ToReflectedFieldDelegate(JEnvRef env, JClassLocalRef jClass, JFieldId fieldId,
JBoolean isStatic);
internal delegate JMethodId GetMethodIdDelegate(JEnvRef env, JClassLocalRef jClass, ReadOnlyValPtr<Byte> nameChars0,
ReadOnlyValPtr<Byte> signatureChars0);
internal delegate JFieldId GetFieldIdDelegate(JEnvRef env, JClassLocalRef jClass, ReadOnlyValPtr<Byte> nameChars0,
ReadOnlyValPtr<Byte> signatureChars0);
internal delegate JMethodId GetStaticMethodIdDelegate(JEnvRef env, JClassLocalRef jClass,
ReadOnlyValPtr<Byte> nameChars0, ReadOnlyValPtr<Byte> signatureChars0);
internal delegate JFieldId GetStaticFieldIdDelegate(JEnvRef env, JClassLocalRef jClass, ReadOnlyValPtr<Byte> nameChars0,
ReadOnlyValPtr<Byte> signatureChars0);
internal delegate Int32 GetArrayLengthDelegate(JEnvRef env, JArrayLocalRef array);
internal delegate JArrayLocalRef NewObjectArrayDelegate(JEnvRef env, Int32 length, JClassLocalRef jClass,
JObjectLocalRef init);
internal delegate JObjectLocalRef GetObjectArrayElementDelegate(JEnvRef env, JArrayLocalRef arrayRef, Int32 index);
internal delegate void SetObjectArrayElementDelegate(JEnvRef env, JArrayLocalRef arrayRef, Int32 index,
JObjectLocalRef obj);
internal delegate JArrayLocalRef NewBooleanArrayDelegate(JEnvRef env, Int32 length);
internal delegate JArrayLocalRef NewByteArrayDelegate(JEnvRef env, Int32 length);
internal delegate JArrayLocalRef NewCharArrayDelegate(JEnvRef env, Int32 length);
internal delegate JArrayLocalRef NewShortArrayDelegate(JEnvRef env, Int32 length);
internal delegate JArrayLocalRef NewIntArrayDelegate(JEnvRef env, Int32 length);
internal delegate JArrayLocalRef NewLongArrayDelegate(JEnvRef env, Int32 length);
internal delegate JArrayLocalRef NewFloatArrayDelegate(JEnvRef env, Int32 length);
internal delegate JArrayLocalRef NewDoubleArrayDelegate(JEnvRef env, Int32 length);
internal delegate ValPtr<JBoolean> GetBooleanArrayElementsDelegate(JEnvRef env, JArrayLocalRef arrayRef,
out JBoolean isCopy);
internal delegate ValPtr<JByte> GetByteArrayElementsDelegate(JEnvRef env, JArrayLocalRef arrayRef, out JBoolean isCopy);
internal delegate ValPtr<JChar> GetCharArrayElementsDelegate(JEnvRef env, JArrayLocalRef arrayRef, out JBoolean isCopy);
internal delegate ValPtr<JShort> GetShortArrayElementsDelegate(JEnvRef env, JArrayLocalRef arrayRef,
out JBoolean isCopy);
internal delegate ValPtr<JInt> GetIntArrayElementsDelegate(JEnvRef env, JArrayLocalRef arrayRef, out JBoolean isCopy);
internal delegate ValPtr<JLong> GetLongArrayElementsDelegate(JEnvRef env, JArrayLocalRef arrayRef, out JBoolean isCopy);
internal delegate ValPtr<JFloat> GetFloatArrayElementsDelegate(JEnvRef env, JArrayLocalRef arrayRef,
out JBoolean isCopy);
internal delegate ValPtr<JDouble> GetDoubleArrayElementsDelegate(JEnvRef env, JArrayLocalRef arrayRef,
out JBoolean isCopy);
internal delegate void ReleaseBooleanArrayElementsDelegate(JEnvRef env, JArrayLocalRef arrayRef,
ReadOnlyValPtr<JBoolean> elements0, JReleaseMode mode);
internal delegate void ReleaseByteArrayElementsDelegate(JEnvRef env, JArrayLocalRef arrayRef,
ReadOnlyValPtr<JByte> elements0, JReleaseMode mode);
internal delegate void ReleaseCharArrayElementsDelegate(JEnvRef env, JArrayLocalRef arrayRef,
ReadOnlyValPtr<JChar> elements0, JReleaseMode mode);
internal delegate void ReleaseShortArrayElementsDelegate(JEnvRef env, JArrayLocalRef arrayRef,
ReadOnlyValPtr<JShort> elements0, JReleaseMode mode);
internal delegate void ReleaseIntArrayElementsDelegate(JEnvRef env, JArrayLocalRef arrayRef,
ReadOnlyValPtr<JInt> elements0, JReleaseMode mode);
internal delegate void ReleaseLongArrayElementsDelegate(JEnvRef env, JArrayLocalRef arrayRef,
ReadOnlyValPtr<JLong> elements0, JReleaseMode mode);
internal delegate void ReleaseFloatArrayElementsDelegate(JEnvRef env, JArrayLocalRef arrayRef,
ReadOnlyValPtr<JFloat> elements0, JReleaseMode mode);
internal delegate void ReleaseDoubleArrayElementsDelegate(JEnvRef env, JArrayLocalRef arrayRef,
ReadOnlyValPtr<JDouble> elements0, JReleaseMode mode);
internal delegate void GetBooleanArrayRegionDelegate(JEnvRef env, JArrayLocalRef arrayRef, Int32 startIndex,
Int32 length, ValPtr<JBoolean> buffer0);
internal delegate void GetByteArrayRegionDelegate(JEnvRef env, JArrayLocalRef arrayRef, Int32 startIndex, Int32 length,
ValPtr<JByte> buffer0);
internal delegate void GetCharArrayRegionDelegate(JEnvRef env, JArrayLocalRef arrayRef, Int32 startIndex, Int32 length,
ValPtr<JChar> buffer0);
internal delegate void GetShortArrayRegionDelegate(JEnvRef env, JArrayLocalRef arrayRef, Int32 startIndex, Int32 length,
ValPtr<JShort> buffer0);
internal delegate void GetIntArrayRegionDelegate(JEnvRef env, JArrayLocalRef arrayRef, Int32 startIndex, Int32 length,
ValPtr<JInt> buffer0);
internal delegate void GetLongArrayRegionDelegate(JEnvRef env, JArrayLocalRef arrayRef, Int32 startIndex, Int32 length,
ValPtr<JLong> buffer0);
internal delegate void GetFloatArrayRegionDelegate(JEnvRef env, JArrayLocalRef arrayRef, Int32 startIndex, Int32 length,
ValPtr<JFloat> buffer0);
internal delegate void GetDoubleArrayRegionDelegate(JEnvRef env, JArrayLocalRef arrayRef, Int32 startIndex,
Int32 length, ValPtr<JDouble> buffer0);
internal delegate void SetBooleanArrayRegionDelegate(JEnvRef env, JArrayLocalRef arrayRef, Int32 startIndex,
Int32 length, ReadOnlyValPtr<JBoolean> buffer0);
internal delegate void SetByteArrayRegionDelegate(JEnvRef env, JArrayLocalRef arrayRef, Int32 startIndex, Int32 length,
ReadOnlyValPtr<JByte> buffer0);
internal delegate void SetCharArrayRegionDelegate(JEnvRef env, JArrayLocalRef arrayRef, Int32 startIndex, Int32 length,
ReadOnlyValPtr<JChar> buffer0);
internal delegate void SetShortArrayRegionDelegate(JEnvRef env, JArrayLocalRef arrayRef, Int32 startIndex, Int32 length,
ReadOnlyValPtr<JShort> buffer0);
internal delegate void SetIntArrayRegionDelegate(JEnvRef env, JArrayLocalRef arrayRef, Int32 startIndex, Int32 length,
ReadOnlyValPtr<JInt> buffer0);
internal delegate void SetLongArrayRegionDelegate(JEnvRef env, JArrayLocalRef arrayRef, Int32 startIndex, Int32 length,
ReadOnlyValPtr<JLong> buffer0);
internal delegate void SetFloatArrayRegionDelegate(JEnvRef env, JArrayLocalRef arrayRef, Int32 startIndex, Int32 length,
ReadOnlyValPtr<JFloat> buffer0);
internal delegate void SetDoubleArrayRegionDelegate(JEnvRef env, JArrayLocalRef arrayRef, Int32 startIndex,
Int32 length, ReadOnlyValPtr<JDouble> buffer0);
internal delegate ValPtr<Byte> GetPrimitiveArrayCriticalDelegate(JEnvRef env, JArrayLocalRef arrayRef,
out JBoolean isCopy);
internal delegate void ReleasePrimitiveArrayCriticalDelegate(JEnvRef env, JArrayLocalRef arrayRef,
ValPtr<Byte> elements, JReleaseMode mode);
internal delegate JObjectLocalRef NewObjectADelegate(JEnvRef env, JClassLocalRef jClass, JMethodId jMethod,
ReadOnlyValPtr<JValue> arg0);

View File

@ -0,0 +1,28 @@
using System;
using System.Diagnostics.CodeAnalysis;
namespace LibRyujinx.Jni.Identifiers
{
public readonly struct JFieldId : IEquatable<JFieldId>
{
#pragma warning disable 0649
private readonly IntPtr _value;
#pragma warning restore 0649
#region Public Methods
public Boolean Equals(JFieldId other)
=> this._value.Equals(other._value);
#endregion
#region Override Methods
public override Boolean Equals([NotNullWhen(true)] Object obj)
=> obj is JFieldId other && this.Equals(other);
public override Int32 GetHashCode() => this._value.GetHashCode();
#endregion
#region Operators
public static Boolean operator ==(JFieldId a, JFieldId b) => a.Equals(b);
public static Boolean operator !=(JFieldId a, JFieldId b) => !a.Equals(b);
#endregion
}
}

View File

@ -0,0 +1,28 @@
using System;
using System.Diagnostics.CodeAnalysis;
namespace LibRyujinx.Jni.Identifiers
{
public readonly struct JMethodId : IEquatable<JMethodId>
{
#pragma warning disable 0649
private readonly IntPtr _value;
#pragma warning restore 0649
#region Public Methods
public Boolean Equals(JMethodId other)
=> this._value.Equals(other._value);
#endregion
#region Override Methods
public override Boolean Equals([NotNullWhen(true)] Object obj)
=> obj is JMethodId other && this.Equals(other);
public override Int32 GetHashCode() => this._value.GetHashCode();
#endregion
#region Operators
public static Boolean operator ==(JMethodId a, JMethodId b) => a.Equals(b);
public static Boolean operator !=(JMethodId a, JMethodId b) => !a.Equals(b);
#endregion
}
}

View File

@ -0,0 +1,12 @@
using System;
namespace LibRyujinx.Jni
{
public enum JReferenceType : Int32
{
InvalidRefType = 0,
LocalRefType = 1,
GlobalRefType = 2,
WeakGlobalRefType = 3
}
}

View File

@ -0,0 +1,11 @@
using System;
namespace LibRyujinx.Jni
{
public enum JReleaseMode : Int32
{
Free = 0,
Commit = 1,
Abort = 2,
}
}

View File

@ -0,0 +1,15 @@
using System;
namespace LibRyujinx.Jni
{
public enum JResult : Int32
{
Ok = 0,
Error = -1,
DetachedThreadError = -2,
VersionError = -3,
MemoryError = -4,
ExitingVMError = -5,
InvalidArgumentsError = -6,
}
}

View File

@ -0,0 +1,251 @@
using LibRyujinx.Jni.Identifiers;
using LibRyujinx.Jni.Pointers;
using LibRyujinx.Jni.Primitives;
using LibRyujinx.Jni.References;
using LibRyujinx.Jni.Values;
using System;
using Rxmxnx.PInvoke;
namespace LibRyujinx.Jni
{
internal static class JniHelper
{
public const Int32 JniVersion = 0x00010006; //JNI_VERSION_1_6;
public static JEnvRef? Attach(JavaVMRef javaVm, IReadOnlyFixedMemory<Byte> threadName, out Boolean newAttach)
{
ref JavaVMValue value = ref javaVm.VirtualMachine;
ref JInvokeInterface jInvoke = ref value.Functions;
IntPtr getEnvPtr = jInvoke.GetEnvPointer;
GetEnvDelegate getEnv = getEnvPtr.GetUnsafeDelegate<GetEnvDelegate>()!;
if (getEnv(javaVm, out JEnvRef jEnv, JniHelper.JniVersion) == JResult.Ok)
{
newAttach = false;
return jEnv;
}
JavaVMAttachArgs args = new() { Version = JniHelper.JniVersion, Name = threadName.ValuePointer, };
IntPtr attachCurrentThreadPtr = jInvoke.AttachCurrentThreadPointer;
AttachCurrentThreadDelegate attachCurrentThread =
attachCurrentThreadPtr.GetUnsafeDelegate<AttachCurrentThreadDelegate>()!;
newAttach = true;
return attachCurrentThread(javaVm, out jEnv, in args) == JResult.Ok ? jEnv : null;
}
public static JEnvRef? AttachDaemon(JavaVMRef javaVm, IReadOnlyFixedMemory<Byte> daemonName)
{
ref JavaVMValue value = ref javaVm.VirtualMachine;
ref JInvokeInterface jInvoke = ref value.Functions;
JavaVMAttachArgs args = new() { Version = JniHelper.JniVersion, Name = daemonName.ValuePointer, };
IntPtr attachCurrentThreadAsDaemonPtr = jInvoke.AttachCurrentThreadAsDaemonPointer;
AttachCurrentThreadAsDaemonDelegate attachCurrentThreadAsDaemon =
attachCurrentThreadAsDaemonPtr.GetUnsafeDelegate<AttachCurrentThreadAsDaemonDelegate>()!;
return attachCurrentThreadAsDaemon(javaVm, out JEnvRef jEnv, in args) == JResult.Ok ? jEnv : null;
}
public static void Detach(JavaVMRef javaVm)
{
ref JavaVMValue value = ref javaVm.VirtualMachine;
ref JInvokeInterface jInvoke = ref value.Functions;
IntPtr detachCurrentThreadPtr = jInvoke.DetachCurrentThreadPointer;
DetachCurrentThreadDelegate detachCurrentThread =
detachCurrentThreadPtr.GetUnsafeDelegate<DetachCurrentThreadDelegate>()!;
detachCurrentThread(javaVm);
}
public static JGlobalRef? GetGlobalClass(JEnvRef jEnv, IReadOnlyFixedMemory<Byte> className)
{
ref readonly JEnvValue value = ref jEnv.Environment;
ref JNativeInterface jInterface = ref value.Functions;
IntPtr findClassPtr = jInterface.FindClassPointer;
FindClassDelegate findClass = findClassPtr.GetUnsafeDelegate<FindClassDelegate>()!;
JClassLocalRef jClass = findClass(jEnv, className.ValuePointer);
if (JniHelper.ExceptionCheck(jEnv))
return default;
IntPtr newGlobalRefPtr = jInterface.NewGlobalRefPointer;
NewGlobalRefDelegate newGlobalRef = newGlobalRefPtr.GetUnsafeDelegate<NewGlobalRefDelegate>()!;
JGlobalRef jGlobal = newGlobalRef(jEnv, (JObjectLocalRef)jClass);
JniHelper.RemoveLocal(jEnv, (JObjectLocalRef)jClass);
return !JniHelper.ExceptionCheck(jEnv) ? jGlobal : null;
}
public static void RemoveLocal(JEnvRef jEnv, JObjectLocalRef jObject)
{
ref readonly JEnvValue value = ref jEnv.Environment;
ref JNativeInterface jInterface = ref value.Functions;
IntPtr deleteLocalRefPtr = jInterface.DeleteLocalRefPointer;
DeleteLocalRefDelegate deleteLocalRef = deleteLocalRefPtr.GetUnsafeDelegate<DeleteLocalRefDelegate>()!;
deleteLocalRef(jEnv, jObject);
}
public static void RemoveGlobal(JEnvRef jEnv, JGlobalRef jObject)
{
ref readonly JEnvValue value = ref jEnv.Environment;
ref JNativeInterface jInterface = ref value.Functions;
IntPtr deleteGlobalRefPtr = jInterface.DeleteGlobalRefPointer;
DeleteGlobalRefDelegate deleteGlobalRef = deleteGlobalRefPtr.GetUnsafeDelegate<DeleteGlobalRefDelegate>()!;
deleteGlobalRef(jEnv, jObject);
}
public static void RemoveWeakGlobal(JEnvRef jEnv, JWeakRef jObject)
{
ref readonly JEnvValue value = ref jEnv.Environment;
ref JNativeInterface jInterface = ref value.Functions;
IntPtr deleteWeakGlobalRefPtr = jInterface.DeleteWeakGlobalRefPointer;
DeleteWeakGlobalRefDelegate deleteWeakGlobalRef =
deleteWeakGlobalRefPtr.GetUnsafeDelegate<DeleteWeakGlobalRefDelegate>()!;
deleteWeakGlobalRef(jEnv, jObject);
}
public static JStringLocalRef? CreateString(JEnvRef jEnv, String textValue)
{
ref readonly JEnvValue value = ref jEnv.Environment;
ref JNativeInterface jInterface = ref value.Functions;
IntPtr newStringPtr = jInterface.NewStringPointer;
NewStringDelegate newString = newStringPtr.GetUnsafeDelegate<NewStringDelegate>()!;
using IReadOnlyFixedMemory<Char>.IDisposable ctx = textValue.AsMemory().GetFixedContext();
JStringLocalRef jString = newString(jEnv, ctx.ValuePointer, ctx.Values.Length);
return !JniHelper.ExceptionCheck(jEnv) ? jString : null;
}
public static JWeakRef? CreateWeakGlobal(JEnvRef jEnv, JObjectLocalRef jObject)
{
ref readonly JEnvValue value = ref jEnv.Environment;
ref JNativeInterface jInterface = ref value.Functions;
IntPtr newWeakGlobalRefPtr = jInterface.NewWeakGlobalRefPointer;
NewWeakGlobalRefDelegate newWeakGlobalRef = newWeakGlobalRefPtr.GetUnsafeDelegate<NewWeakGlobalRefDelegate>()!;
JWeakRef jWeak = newWeakGlobalRef(jEnv, jObject);
return !JniHelper.ExceptionCheck(jEnv) ? jWeak : null;
}
private static Boolean ExceptionCheck(JEnvRef jEnv)
{
ref readonly JEnvValue value = ref jEnv.Environment;
ref JNativeInterface jInterface = ref value.Functions;
IntPtr exceptionCheckPtr = jInterface.ExceptionCheckPointer;
ExceptionCheckDelegate exceptionCheck = exceptionCheckPtr.GetUnsafeDelegate<ExceptionCheckDelegate>()!;
if (!exceptionCheck(jEnv))
return false;
IntPtr exceptionDescribePtr = jInterface.ExceptionDescribePointer;
IntPtr exceptionClearPtr = jInterface.ExceptionClearPointer;
ExceptionDescribeDelegate exceptionDescribe =
exceptionDescribePtr.GetUnsafeDelegate<ExceptionDescribeDelegate>()!;
ExceptionClearDelegate exceptionClear = exceptionClearPtr.GetUnsafeDelegate<ExceptionClearDelegate>()!;
exceptionDescribe(jEnv);
exceptionClear(jEnv);
return true;
}
public static JavaVMRef? GetVirtualMachine(JEnvRef jEnv)
{
ref readonly JEnvValue value = ref jEnv.Environment;
ref JNativeInterface jInterface = ref value.Functions;
IntPtr getJavaVmPtr = jInterface.GetJavaVMPointer;
GetVirtualMachineDelegate getJavaVm = getJavaVmPtr.GetUnsafeDelegate<GetVirtualMachineDelegate>()!;
return getJavaVm(jEnv, out JavaVMRef javaVm) == JResult.Ok ? javaVm : null;
}
public static Boolean? IsValidGlobalWeak(JEnvRef jEnv, JWeakRef jWeak)
{
ref readonly JEnvValue value = ref jEnv.Environment;
ref JNativeInterface jInterface = ref value.Functions;
IntPtr isSameObjectPtr = jInterface.IsSameObjectPointer;
IsSameObjectDelegate isSameObject = isSameObjectPtr.GetUnsafeDelegate<IsSameObjectDelegate>()!;
JBoolean result = isSameObject(jEnv, (JObjectLocalRef)jWeak, default);
return !JniHelper.ExceptionCheck(jEnv) ? !result : null;
}
public static JMethodId? GetMethodId(JEnvRef jEnv, JClassLocalRef jClass, IReadOnlyFixedMemory<Byte> methodName,
IReadOnlyFixedMemory<Byte> descriptor)
{
ref readonly JEnvValue value = ref jEnv.Environment;
ref JNativeInterface jInterface = ref value.Functions;
IntPtr getMethodIdPtr = jInterface.GetMethodIdPointer;
GetMethodIdDelegate getMethodId = getMethodIdPtr.GetUnsafeDelegate<GetMethodIdDelegate>()!;
JMethodId methodId = getMethodId(jEnv, jClass, methodName.ValuePointer, descriptor.ValuePointer);
return !JniHelper.ExceptionCheck(jEnv) ? methodId : null;
}
public static JMethodId? GetStaticMethodId(JEnvRef jEnv, JClassLocalRef jClass,
IReadOnlyFixedMemory<Byte> methodName, IReadOnlyFixedMemory<Byte> descriptor)
{
ref readonly JEnvValue value = ref jEnv.Environment;
ref JNativeInterface jInterface = ref value.Functions;
IntPtr getStaticMethodIdPtr = jInterface.GetStaticMethodIdPointer;
GetStaticMethodIdDelegate getStaticMethodId =
getStaticMethodIdPtr.GetUnsafeDelegate<GetStaticMethodIdDelegate>()!;
JMethodId jMethodId = getStaticMethodId(jEnv, jClass, methodName.ValuePointer, descriptor.ValuePointer);
return !JniHelper.ExceptionCheck(jEnv) ? jMethodId : null;
}
public static void CallStaticVoidMethod(JEnvRef jEnv, JClassLocalRef jClass, JMethodId jMethodId,
params JValue[] args)
{
ref readonly JEnvValue value = ref jEnv.Environment;
ref JNativeInterface jInterface = ref value.Functions;
IntPtr callStaticVoidMethodPtr = jInterface.CallStaticVoidMethodAPointer;
CallStaticVoidMethodADelegate callStaticVoidMethod =
callStaticVoidMethodPtr.GetUnsafeDelegate<CallStaticVoidMethodADelegate>()!;
using IReadOnlyFixedMemory<JValue>.IDisposable fArgs = args.AsMemory().GetFixedContext();
callStaticVoidMethod(jEnv, jClass, jMethodId, fArgs.ValuePointer);
}
public static JObjectLocalRef? CallStaticObjectMethod(JEnvRef jEnv, JClassLocalRef jClass, JMethodId jMethodId,
params JValue[] args)
{
ref readonly JEnvValue value = ref jEnv.Environment;
ref JNativeInterface jInterface = ref value.Functions;
IntPtr callStaticObjectMethodPtr = jInterface.CallStaticObjectMethodAPointer;
CallStaticObjectMethodADelegate callStaticObjectMethod =
callStaticObjectMethodPtr.GetUnsafeDelegate<CallStaticObjectMethodADelegate>()!;
using IReadOnlyFixedMemory<JValue>.IDisposable fArgs = args.AsMemory().GetFixedContext();
JObjectLocalRef jObject = callStaticObjectMethod(jEnv, jClass, jMethodId, fArgs.ValuePointer);
return !JniHelper.ExceptionCheck(jEnv) ? jObject : null;
}
public static JLong? CallStaticLongMethod(JEnvRef jEnv, JClassLocalRef jClass, JMethodId jMethodId,
params JValue[] args)
{
ref readonly JEnvValue value = ref jEnv.Environment;
ref JNativeInterface jInterface = ref value.Functions;
IntPtr callStaticLongMethodPtr = jInterface.CallStaticLongMethodAPointer;
CallStaticLongMethodADelegate callStaticLongMethod =
callStaticLongMethodPtr.GetUnsafeDelegate<CallStaticLongMethodADelegate>()!;
using IReadOnlyFixedMemory<JValue>.IDisposable fArgs = args.AsMemory().GetFixedContext();
JLong jLong = callStaticLongMethod(jEnv, jClass, jMethodId, fArgs.ValuePointer);
return !JniHelper.ExceptionCheck(jEnv) ? jLong : null;
}
public static void CallVoidMethod(JEnvRef jEnv, JObjectLocalRef jObject, JMethodId jMethodId, params JValue[] args)
{
ref readonly JEnvValue value = ref jEnv.Environment;
ref JNativeInterface jInterface = ref value.Functions;
IntPtr callVoidMethodPtr = jInterface.CallVoidMethodAPointer;
CallVoidMethodADelegate callVoidMethod = callVoidMethodPtr.GetUnsafeDelegate<CallVoidMethodADelegate>()!;
using IReadOnlyFixedMemory<JValue>.IDisposable fArgs = args.AsMemory().GetFixedContext();
callVoidMethod(jEnv, jObject, jMethodId, fArgs.ValuePointer);
}
}
}

View File

@ -0,0 +1,37 @@
using LibRyujinx.Jni.Values;
using Rxmxnx.PInvoke;
using System;
namespace LibRyujinx.Jni.Pointers
{
public readonly struct JEnvRef : IEquatable<JEnvRef>
{
#pragma warning disable 0649
private readonly IntPtr _value;
#pragma warning restore 0649
public JEnvRef(IntPtr val)
{
_value = val;
}
#region Operators
public static Boolean operator ==(JEnvRef a, JEnvRef b) => a._value.Equals(b._value);
public static Boolean operator !=(JEnvRef a, JEnvRef b) => !a._value.Equals(b._value);
#endregion
#region Public Properties
internal readonly ref JEnvValue Environment => ref this._value.GetUnsafeReference<JEnvValue>();
#endregion
#region Public Methods
public Boolean Equals(JEnvRef other) => this._value.Equals(other._value);
#endregion
#region Overrided Methods
public override Boolean Equals(Object obj) => obj is JEnvRef other && this.Equals(other);
public override Int32 GetHashCode() => this._value.GetHashCode();
#endregion
}
}

View File

@ -0,0 +1,31 @@
using LibRyujinx.Jni.Values;
using Rxmxnx.PInvoke;
using System;
namespace LibRyujinx.Jni.Pointers;
public readonly struct JavaVMRef : IEquatable<JavaVMRef>
{
#pragma warning disable 0649
private readonly IntPtr _value;
#pragma warning restore 0649
#region Operators
public static Boolean operator ==(JavaVMRef a, JavaVMRef b) => a._value.Equals(b._value);
public static Boolean operator !=(JavaVMRef a, JavaVMRef b) => !a._value.Equals(b._value);
#endregion
#region Public Properties
internal readonly ref JavaVMValue VirtualMachine => ref this._value.GetUnsafeReference<JavaVMValue>();
#endregion
#region Public Methods
public Boolean Equals(JavaVMRef other) => this._value.Equals(other._value);
#endregion
#region Overrided Methods
public override Boolean Equals(Object obj) => obj is JavaVMRef other && this.Equals(other);
public override Int32 GetHashCode() => this._value.GetHashCode();
#endregion
}

View File

@ -0,0 +1,67 @@
using Rxmxnx.PInvoke;
using System;
namespace LibRyujinx.Jni.Primitives;
public readonly struct JBoolean : IComparable<Boolean>, IEquatable<Boolean>
{
internal static readonly Type Type = typeof(JBoolean);
private const Byte trueByte = 1;
private const Byte falseByte = 0;
public static readonly CString Signature = (CString)"Z";
private readonly Byte _value;
private Boolean Value => this._value == JBoolean.trueByte;
private JBoolean(Boolean value) => this._value = value ? JBoolean.trueByte : JBoolean.falseByte;
#region Operators
public static implicit operator JBoolean(Boolean value) => new(value);
public static implicit operator Boolean(JBoolean jValue) => jValue._value == 1;
public static JBoolean operator !(JBoolean a) => new(!a.Value);
public static JBoolean operator |(JBoolean a, JBoolean b) => new(a.Value || b.Value);
public static JBoolean operator |(Boolean a, JBoolean b) => new(a || b.Value);
public static JBoolean operator |(JBoolean a, Boolean b) => new(a.Value || b);
public static JBoolean operator &(JBoolean a, JBoolean b) => new(a.Value && b.Value);
public static JBoolean operator &(Boolean a, JBoolean b) => new(a && b.Value);
public static JBoolean operator &(JBoolean a, Boolean b) => new(a.Value && b);
public static Boolean operator ==(JBoolean a, JBoolean b) => a._value.Equals(b._value);
public static Boolean operator ==(Boolean a, JBoolean b) => a.Equals(b._value);
public static Boolean operator ==(JBoolean a, Boolean b) => a._value.Equals(b);
public static Boolean operator !=(JBoolean a, JBoolean b) => !a._value.Equals(b._value);
public static Boolean operator !=(Boolean a, JBoolean b) => !a.Equals(b._value);
public static Boolean operator !=(JBoolean a, Boolean b) => !a._value.Equals(b);
public static Boolean operator >(JBoolean a, JBoolean b) => a._value.CompareTo(b._value) > 0;
public static Boolean operator >(Boolean a, JBoolean b) => a.CompareTo(b._value) > 0;
public static Boolean operator >(JBoolean a, Boolean b) => a._value.CompareTo(b) > 0;
public static Boolean operator <(JBoolean a, JBoolean b) => a._value.CompareTo(b._value) < 0;
public static Boolean operator <(Boolean a, JBoolean b) => a.CompareTo(b._value) < 0;
public static Boolean operator <(JBoolean a, Boolean b) => a._value.CompareTo(b) < 0;
public static Boolean operator >=(JBoolean a, JBoolean b) => a._value.CompareTo(b._value) > 0 || a.Equals(b._value);
public static Boolean operator >=(Boolean a, JBoolean b) => a.CompareTo(b._value) > 0 || a.Equals(b._value);
public static Boolean operator >=(JBoolean a, Boolean b) => a._value.CompareTo(b) > 0 || a._value.Equals(b);
public static Boolean operator <=(JBoolean a, JBoolean b) => a._value.CompareTo(b._value) < 0 || a.Equals(b._value);
public static Boolean operator <=(Boolean a, JBoolean b) => a.CompareTo(b._value) < 0 || a.Equals(b._value);
public static Boolean operator <=(JBoolean a, Boolean b) => a._value.CompareTo(b) < 0 || a._value.Equals(b);
#endregion
#region Public Methods
public Int32 CompareTo(Boolean other) => this._value.CompareTo(other);
public Int32 CompareTo(JBoolean other) => this._value.CompareTo(other._value);
public Int32 CompareTo(Object obj)
=> obj is JBoolean jvalue ? this.CompareTo(jvalue) :
obj is Boolean value ? this.CompareTo(value) : this._value.CompareTo(obj);
public Boolean Equals(Boolean other) => this._value.Equals(other);
public Boolean Equals(JBoolean other) => this._value.Equals(other._value);
public String ToString(IFormatProvider formatProvider) => this._value.ToString(formatProvider);
#endregion
#region Overrided Methods
public override String ToString() => this._value.ToString();
public override Boolean Equals(Object obj)
=> obj is JBoolean jvalue ? this.Equals(jvalue) :
obj is Boolean value ? this.Equals(value) : this._value.Equals(obj);
public override Int32 GetHashCode() => this._value.GetHashCode();
#endregion
}

View File

@ -0,0 +1,74 @@
using Rxmxnx.PInvoke;
using System;
namespace LibRyujinx.Jni.Primitives
{
public readonly struct JByte : IComparable<SByte>, IEquatable<SByte>, IFormattable
{
internal static readonly Type Type = typeof(JByte);
public static readonly CString Signature = (CString)"B";
private readonly SByte _value;
private JByte(SByte value) => this._value = value;
private JByte(Int32 value) => this._value = Convert.ToSByte(value);
#region Operators
public static implicit operator JByte(SByte value) => new(value);
public static implicit operator SByte(JByte jValue) => jValue._value;
public static JByte operator +(JByte a) => a;
public static JByte operator ++(JByte a) => new(a._value + 1);
public static JByte operator -(JByte a) => new(-a._value);
public static JByte operator --(JByte a) => new(a._value - 1);
public static JByte operator +(JByte a, JByte b) => new(a._value + b._value);
public static JByte operator +(SByte a, JByte b) => new(a + b._value);
public static JByte operator +(JByte a, SByte b) => new(a._value + b);
public static JByte operator -(JByte a, JByte b) => new(a._value - b._value);
public static JByte operator -(SByte a, JByte b) => new(a - b._value);
public static JByte operator -(JByte a, SByte b) => new(a._value - b);
public static JByte operator *(JByte a, JByte b) => new(a._value * b._value);
public static JByte operator *(SByte a, JByte b) => new(a * b._value);
public static JByte operator *(JByte a, SByte b) => new(a._value * b);
public static JByte operator /(JByte a, JByte b) => new(a._value / b._value);
public static JByte operator /(SByte a, JByte b) => new(a / b._value);
public static JByte operator /(JByte a, SByte b) => new(a._value / b);
public static JByte operator %(JByte a, JByte b) => new(a._value % b._value);
public static JByte operator %(SByte a, JByte b) => new(a % b._value);
public static JByte operator %(JByte a, SByte b) => new(a._value % b);
public static Boolean operator ==(JByte a, JByte b) => a._value.Equals(b._value);
public static Boolean operator ==(SByte a, JByte b) => a.Equals(b._value);
public static Boolean operator ==(JByte a, SByte b) => a._value.Equals(b);
public static Boolean operator !=(JByte a, JByte b) => !a._value.Equals(b._value);
public static Boolean operator !=(SByte a, JByte b) => !a.Equals(b._value);
public static Boolean operator !=(JByte a, SByte b) => !a._value.Equals(b);
public static Boolean operator >(JByte a, JByte b) => a._value.CompareTo(b._value) > 0;
public static Boolean operator >(SByte a, JByte b) => a.CompareTo(b._value) > 0;
public static Boolean operator >(JByte a, SByte b) => a._value.CompareTo(b) > 0;
public static Boolean operator <(JByte a, JByte b) => a._value.CompareTo(b._value) < 0;
public static Boolean operator <(SByte a, JByte b) => a.CompareTo(b._value) < 0;
public static Boolean operator <(JByte a, SByte b) => a._value.CompareTo(b) < 0;
public static Boolean operator >=(JByte a, JByte b) => a._value.CompareTo(b._value) > 0 || a.Equals(b._value);
public static Boolean operator >=(SByte a, JByte b) => a.CompareTo(b._value) > 0 || a.Equals(b._value);
public static Boolean operator >=(JByte a, SByte b) => a._value.CompareTo(b) > 0 || a._value.Equals(b);
public static Boolean operator <=(JByte a, JByte b) => a._value.CompareTo(b._value) < 0 || a.Equals(b._value);
public static Boolean operator <=(SByte a, JByte b) => a.CompareTo(b._value) < 0 || a.Equals(b._value);
public static Boolean operator <=(JByte a, SByte b) => a._value.CompareTo(b) < 0 || a._value.Equals(b);
#endregion
#region Public Methods
public Int32 CompareTo(SByte other) => this._value.CompareTo(other);
public Int32 CompareTo(JByte other) => this._value.CompareTo(other._value);
public Int32 CompareTo(Object obj) => obj is JByte jValue ? this.CompareTo(jValue) : obj is SByte value ? this.CompareTo(value) : this._value.CompareTo(obj);
public Boolean Equals(SByte other) => this._value.Equals(other);
public Boolean Equals(JByte other) => this._value.Equals(other._value);
public String ToString(String format, IFormatProvider formatProvider) => this._value.ToString(format, formatProvider);
#endregion
#region Overrided Methods
public override String ToString() => this._value.ToString();
public override Boolean Equals(Object obj) => obj is JByte jvalue ? this.Equals(jvalue) : obj is SByte value ? this.Equals(value) : this._value.Equals(obj);
public override Int32 GetHashCode() => this._value.GetHashCode();
#endregion
}
}

View File

@ -0,0 +1,56 @@
using Rxmxnx.PInvoke;
using System;
namespace LibRyujinx.Jni.Primitives
{
public readonly struct JChar : IComparable<Char>, IEquatable<Char>
{
internal static readonly Type Type = typeof(JChar);
public static readonly CString Signature = (CString)"C";
private readonly Char _value;
private JChar(Char value) => this._value = value;
#region Operators
public static implicit operator JChar(Char value) => new(value);
public static explicit operator JChar(Int16 value) => new((Char)value);
public static implicit operator Char(JChar jValue) => jValue._value;
public static explicit operator Int16(JChar jValue) => (Int16)jValue._value;
public static Boolean operator ==(JChar a, JChar b) => a._value.Equals(b._value);
public static Boolean operator ==(Char a, JChar b) => a.Equals(b._value);
public static Boolean operator ==(JChar a, Char b) => a._value.Equals(b);
public static Boolean operator !=(JChar a, JChar b) => !a._value.Equals(b._value);
public static Boolean operator !=(Char a, JChar b) => !a.Equals(b._value);
public static Boolean operator !=(JChar a, Char b) => !a._value.Equals(b);
public static Boolean operator >(JChar a, JChar b) => a._value.CompareTo(b._value) > 0;
public static Boolean operator >(Char a, JChar b) => a.CompareTo(b._value) > 0;
public static Boolean operator >(JChar a, Char b) => a._value.CompareTo(b) > 0;
public static Boolean operator <(JChar a, JChar b) => a._value.CompareTo(b._value) < 0;
public static Boolean operator <(Char a, JChar b) => a.CompareTo(b._value) < 0;
public static Boolean operator <(JChar a, Char b) => a._value.CompareTo(b) < 0;
public static Boolean operator >=(JChar a, JChar b) => a._value.CompareTo(b._value) > 0 || a.Equals(b._value);
public static Boolean operator >=(Char a, JChar b) => a.CompareTo(b._value) > 0 || a.Equals(b._value);
public static Boolean operator >=(JChar a, Char b) => a._value.CompareTo(b) > 0 || a._value.Equals(b);
public static Boolean operator <=(JChar a, JChar b) => a._value.CompareTo(b._value) < 0 || a.Equals(b._value);
public static Boolean operator <=(Char a, JChar b) => a.CompareTo(b._value) < 0 || a.Equals(b._value);
public static Boolean operator <=(JChar a, Char b) => a._value.CompareTo(b) < 0 || a._value.Equals(b);
#endregion
#region Public Methods
public Int32 CompareTo(Char other) => this._value.CompareTo(other);
public Int32 CompareTo(JChar other) => this._value.CompareTo(other._value);
public Int32 CompareTo(Object obj) => obj is JChar jvalue ? this.CompareTo(jvalue) : obj is Char value ? this.CompareTo(value) : this._value.CompareTo(obj);
public Boolean Equals(Char other) => this._value.Equals(other);
public Boolean Equals(JChar other) => this._value.Equals(other._value);
public String ToString(IFormatProvider formatProvider) => this._value.ToString(formatProvider);
#endregion
#region Overrided Methods
public override String ToString() => this._value.ToString();
public override Boolean Equals(Object obj) => obj is JChar jvalue ? this.Equals(jvalue) : obj is Char value ? this.Equals(value) : this._value.Equals(obj);
public override Int32 GetHashCode() => this._value.GetHashCode();
#endregion
}
}

View File

@ -0,0 +1,70 @@
using Rxmxnx.PInvoke;
using System;
namespace LibRyujinx.Jni.Primitives
{
public readonly struct JDouble : IComparable<Double>, IEquatable<Double>, IFormattable
{
internal static readonly Type Type = typeof(JDouble);
public static readonly CString Signature = (CString)"D";
private readonly Double _value;
private JDouble(Double value) => this._value = value;
#region Operators
public static implicit operator JDouble(Double value) => new(value);
public static implicit operator Double(JDouble jValue) => jValue._value;
public static JDouble operator +(JDouble a) => a;
public static JDouble operator ++(JDouble a) => new(a._value + 1);
public static JDouble operator -(JDouble a) => new(-a._value);
public static JDouble operator --(JDouble a) => new(a._value - 1);
public static JDouble operator +(JDouble a, JDouble b) => new(a._value + b._value);
public static JDouble operator +(Double a, JDouble b) => new(a + b._value);
public static JDouble operator +(JDouble a, Double b) => new(a._value + b);
public static JDouble operator -(JDouble a, JDouble b) => new(a._value - b._value);
public static JDouble operator -(Double a, JDouble b) => new(a - b._value);
public static JDouble operator -(JDouble a, Double b) => new(a._value - b);
public static JDouble operator *(JDouble a, JDouble b) => new(a._value * b._value);
public static JDouble operator *(Double a, JDouble b) => new(a * b._value);
public static JDouble operator *(JDouble a, Double b) => new(a._value * b);
public static JDouble operator /(JDouble a, JDouble b) => new(a._value / b._value);
public static JDouble operator /(Double a, JDouble b) => new(a / b._value);
public static JDouble operator /(JDouble a, Double b) => new(a._value / b);
public static Boolean operator ==(JDouble a, JDouble b) => a._value.Equals(b._value);
public static Boolean operator ==(Double a, JDouble b) => a.Equals(b._value);
public static Boolean operator ==(JDouble a, Double b) => a._value.Equals(b);
public static Boolean operator !=(JDouble a, JDouble b) => !a._value.Equals(b._value);
public static Boolean operator !=(Double a, JDouble b) => !a.Equals(b._value);
public static Boolean operator !=(JDouble a, Double b) => !a._value.Equals(b);
public static Boolean operator >(JDouble a, JDouble b) => a._value.CompareTo(b._value) > 0;
public static Boolean operator >(Double a, JDouble b) => a.CompareTo(b._value) > 0;
public static Boolean operator >(JDouble a, Double b) => a._value.CompareTo(b) > 0;
public static Boolean operator <(JDouble a, JDouble b) => a._value.CompareTo(b._value) < 0;
public static Boolean operator <(Double a, JDouble b) => a.CompareTo(b._value) < 0;
public static Boolean operator <(JDouble a, Double b) => a._value.CompareTo(b) < 0;
public static Boolean operator >=(JDouble a, JDouble b) => a._value.CompareTo(b._value) > 0 || a.Equals(b._value);
public static Boolean operator >=(Double a, JDouble b) => a.CompareTo(b._value) > 0 || a.Equals(b._value);
public static Boolean operator >=(JDouble a, Double b) => a._value.CompareTo(b) > 0 || a._value.Equals(b);
public static Boolean operator <=(JDouble a, JDouble b) => a._value.CompareTo(b._value) < 0 || a.Equals(b._value);
public static Boolean operator <=(Double a, JDouble b) => a.CompareTo(b._value) < 0 || a.Equals(b._value);
public static Boolean operator <=(JDouble a, Double b) => a._value.CompareTo(b) < 0 || a._value.Equals(b);
#endregion
#region Public Methods
public Int32 CompareTo(Double other) => this._value.CompareTo(other);
public Int32 CompareTo(JDouble other) => this._value.CompareTo(other._value);
public Int32 CompareTo(Object obj) => obj is JDouble jvalue ? this.CompareTo(jvalue) : obj is Double value ? this.CompareTo(value) : this._value.CompareTo(obj);
public Boolean Equals(Double other) => this._value.Equals(other);
public Boolean Equals(JDouble other) => this._value.Equals(other._value);
public String ToString(String format, IFormatProvider formatProvider) => this._value.ToString(format, formatProvider);
#endregion
#region Overrided Methods
public override String ToString() => this._value.ToString();
public override Boolean Equals(Object obj) => obj is JDouble jvalue ? this.Equals(jvalue) : obj is Double value ? this.Equals(value) : this._value.Equals(obj);
public override Int32 GetHashCode() => this._value.GetHashCode();
#endregion
}
}

View File

@ -0,0 +1,70 @@
using Rxmxnx.PInvoke;
using System;
namespace LibRyujinx.Jni.Primitives
{
public readonly struct JFloat : IComparable<Single>, IEquatable<Single>, IFormattable
{
internal static readonly Type Type = typeof(JFloat);
public static readonly CString Signature = (CString)"F";
private readonly Single _value;
private JFloat(Single value) => this._value = value;
#region Operators
public static implicit operator JFloat(Single value) => new(value);
public static implicit operator Single(JFloat jValue) => jValue._value;
public static JFloat operator +(JFloat a) => a;
public static JFloat operator ++(JFloat a) => new(a._value + 1);
public static JFloat operator -(JFloat a) => new(-a._value);
public static JFloat operator --(JFloat a) => new(a._value - 1);
public static JFloat operator +(JFloat a, JFloat b) => new(a._value + b._value);
public static JFloat operator +(Single a, JFloat b) => new(a + b._value);
public static JFloat operator +(JFloat a, Single b) => new(a._value + b);
public static JFloat operator -(JFloat a, JFloat b) => new(a._value - b._value);
public static JFloat operator -(Single a, JFloat b) => new(a - b._value);
public static JFloat operator -(JFloat a, Single b) => new(a._value - b);
public static JFloat operator *(JFloat a, JFloat b) => new(a._value * b._value);
public static JFloat operator *(Single a, JFloat b) => new(a * b._value);
public static JFloat operator *(JFloat a, Single b) => new(a._value * b);
public static JFloat operator /(JFloat a, JFloat b) => new(a._value / b._value);
public static JFloat operator /(Single a, JFloat b) => new(a / b._value);
public static JFloat operator /(JFloat a, Single b) => new(a._value / b);
public static Boolean operator ==(JFloat a, JFloat b) => a._value.Equals(b._value);
public static Boolean operator ==(Single a, JFloat b) => a.Equals(b._value);
public static Boolean operator ==(JFloat a, Single b) => a._value.Equals(b);
public static Boolean operator !=(JFloat a, JFloat b) => !a._value.Equals(b._value);
public static Boolean operator !=(Single a, JFloat b) => !a.Equals(b._value);
public static Boolean operator !=(JFloat a, Single b) => !a._value.Equals(b);
public static Boolean operator >(JFloat a, JFloat b) => a._value.CompareTo(b._value) > 0;
public static Boolean operator >(Single a, JFloat b) => a.CompareTo(b._value) > 0;
public static Boolean operator >(JFloat a, Single b) => a._value.CompareTo(b) > 0;
public static Boolean operator <(JFloat a, JFloat b) => a._value.CompareTo(b._value) < 0;
public static Boolean operator <(Single a, JFloat b) => a.CompareTo(b._value) < 0;
public static Boolean operator <(JFloat a, Single b) => a._value.CompareTo(b) < 0;
public static Boolean operator >=(JFloat a, JFloat b) => a._value.CompareTo(b._value) > 0 || a.Equals(b._value);
public static Boolean operator >=(Single a, JFloat b) => a.CompareTo(b._value) > 0 || a.Equals(b._value);
public static Boolean operator >=(JFloat a, Single b) => a._value.CompareTo(b) > 0 || a._value.Equals(b);
public static Boolean operator <=(JFloat a, JFloat b) => a._value.CompareTo(b._value) < 0 || a.Equals(b._value);
public static Boolean operator <=(Single a, JFloat b) => a.CompareTo(b._value) < 0 || a.Equals(b._value);
public static Boolean operator <=(JFloat a, Single b) => a._value.CompareTo(b) < 0 || a._value.Equals(b);
#endregion
#region Public Methods
public Int32 CompareTo(Single other) => this._value.CompareTo(other);
public Int32 CompareTo(JFloat other) => this._value.CompareTo(other._value);
public Int32 CompareTo(Object obj) => obj is JFloat jvalue ? this.CompareTo(jvalue) : obj is Single value ? this.CompareTo(value) : this._value.CompareTo(obj);
public Boolean Equals(Single other) => this._value.Equals(other);
public Boolean Equals(JFloat other) => this._value.Equals(other._value);
public String ToString(String format, IFormatProvider formatProvider) => this._value.ToString(format, formatProvider);
#endregion
#region Overrided Methods
public override String ToString() => this._value.ToString();
public override Boolean Equals(Object obj) => obj is JFloat jvalue ? this.Equals(jvalue) : obj is Single value ? this.Equals(value) : this._value.Equals(obj);
public override Int32 GetHashCode() => this._value.GetHashCode();
#endregion
}
}

View File

@ -0,0 +1,73 @@
using Rxmxnx.PInvoke;
using System;
namespace LibRyujinx.Jni.Primitives
{
public readonly struct JInt : IComparable<Int32>, IEquatable<Int32>, IFormattable
{
internal static readonly Type Type = typeof(JInt);
public static readonly CString Signature = (CString)"I";
private readonly Int32 _value;
private JInt(Int32 value) => this._value = value;
#region Operators
public static implicit operator JInt(Int32 value) => new(value);
public static implicit operator Int32(JInt jValue) => jValue._value;
public static JInt operator +(JInt a) => a;
public static JInt operator ++(JInt a) => new(a._value + 1);
public static JInt operator -(JInt a) => new(-a._value);
public static JInt operator --(JInt a) => new(a._value - 1);
public static JInt operator +(JInt a, JInt b) => new(a._value + b._value);
public static JInt operator +(Int32 a, JInt b) => new(a + b._value);
public static JInt operator +(JInt a, Int32 b) => new(a._value + b);
public static JInt operator -(JInt a, JInt b) => new(a._value - b._value);
public static JInt operator -(Int32 a, JInt b) => new(a - b._value);
public static JInt operator -(JInt a, Int32 b) => new(a._value - b);
public static JInt operator *(JInt a, JInt b) => new(a._value * b._value);
public static JInt operator *(Int32 a, JInt b) => new(a * b._value);
public static JInt operator *(JInt a, Int32 b) => new(a._value * b);
public static JInt operator /(JInt a, JInt b) => new(a._value / b._value);
public static JInt operator /(Int32 a, JInt b) => new(a / b._value);
public static JInt operator /(JInt a, Int32 b) => new(a._value / b);
public static JInt operator %(JInt a, JInt b) => new(a._value % b._value);
public static JInt operator %(Int32 a, JInt b) => new(a % b._value);
public static JInt operator %(JInt a, Int32 b) => new(a._value % b);
public static Boolean operator ==(JInt a, JInt b) => a._value.Equals(b._value);
public static Boolean operator ==(Int32 a, JInt b) => a.Equals(b._value);
public static Boolean operator ==(JInt a, Int32 b) => a._value.Equals(b);
public static Boolean operator !=(JInt a, JInt b) => !a._value.Equals(b._value);
public static Boolean operator !=(Int32 a, JInt b) => !a.Equals(b._value);
public static Boolean operator !=(JInt a, Int32 b) => !a._value.Equals(b);
public static Boolean operator >(JInt a, JInt b) => a._value.CompareTo(b._value) > 0;
public static Boolean operator >(Int32 a, JInt b) => a.CompareTo(b._value) > 0;
public static Boolean operator >(JInt a, Int32 b) => a._value.CompareTo(b) > 0;
public static Boolean operator <(JInt a, JInt b) => a._value.CompareTo(b._value) < 0;
public static Boolean operator <(Int32 a, JInt b) => a.CompareTo(b._value) < 0;
public static Boolean operator <(JInt a, Int32 b) => a._value.CompareTo(b) < 0;
public static Boolean operator >=(JInt a, JInt b) => a._value.CompareTo(b._value) > 0 || a.Equals(b._value);
public static Boolean operator >=(Int32 a, JInt b) => a.CompareTo(b._value) > 0 || a.Equals(b._value);
public static Boolean operator >=(JInt a, Int32 b) => a._value.CompareTo(b) > 0 || a._value.Equals(b);
public static Boolean operator <=(JInt a, JInt b) => a._value.CompareTo(b._value) < 0 || a.Equals(b._value);
public static Boolean operator <=(Int32 a, JInt b) => a.CompareTo(b._value) < 0 || a.Equals(b._value);
public static Boolean operator <=(JInt a, Int32 b) => a._value.CompareTo(b) < 0 || a._value.Equals(b);
#endregion
#region Public Methods
public Int32 CompareTo(Int32 other) => this._value.CompareTo(other);
public Int32 CompareTo(JInt other) => this._value.CompareTo(other._value);
public Int32 CompareTo(Object obj) => obj is JInt jValue ? this.CompareTo(jValue) : obj is Int32 value ? this.CompareTo(value) : this._value.CompareTo(obj);
public Boolean Equals(Int32 other) => this._value.Equals(other);
public Boolean Equals(JInt other) => this._value.Equals(other._value);
public String ToString(String format, IFormatProvider formatProvider) => this._value.ToString(format, formatProvider);
#endregion
#region Overrided Methods
public override String ToString() => this._value.ToString();
public override Boolean Equals(Object obj) => obj is JInt jvalue ? this.Equals(jvalue) : obj is Int32 value ? this.Equals(value) : this._value.Equals(obj);
public override Int32 GetHashCode() => this._value.GetHashCode();
#endregion
}
}

View File

@ -0,0 +1,73 @@
using Rxmxnx.PInvoke;
using System;
namespace LibRyujinx.Jni.Primitives
{
public readonly struct JLong : IComparable<Int64>, IEquatable<Int64>, IFormattable
{
internal static readonly Type Type = typeof(JLong);
public static readonly CString Signature = (CString)"J";
private readonly Int64 _value;
private JLong(Int64 value) => this._value = value;
#region Operators
public static implicit operator JLong(Int64 value) => new(value);
public static implicit operator Int64(JLong jValue) => jValue._value;
public static JLong operator +(JLong a) => a;
public static JLong operator ++(JLong a) => new(a._value + 1);
public static JLong operator -(JLong a) => new(-a._value);
public static JLong operator --(JLong a) => new(a._value - 1);
public static JLong operator +(JLong a, JLong b) => new(a._value + b._value);
public static JLong operator +(Int64 a, JLong b) => new(a + b._value);
public static JLong operator +(JLong a, Int64 b) => new(a._value + b);
public static JLong operator -(JLong a, JLong b) => new(a._value - b._value);
public static JLong operator -(Int64 a, JLong b) => new(a - b._value);
public static JLong operator -(JLong a, Int64 b) => new(a._value - b);
public static JLong operator *(JLong a, JLong b) => new(a._value * b._value);
public static JLong operator *(Int64 a, JLong b) => new(a * b._value);
public static JLong operator *(JLong a, Int64 b) => new(a._value * b);
public static JLong operator /(JLong a, JLong b) => new(a._value / b._value);
public static JLong operator /(Int64 a, JLong b) => new(a / b._value);
public static JLong operator /(JLong a, Int64 b) => new(a._value / b);
public static JLong operator %(JLong a, JLong b) => new(a._value % b._value);
public static JLong operator %(Int64 a, JLong b) => new(a % b._value);
public static JLong operator %(JLong a, Int64 b) => new(a._value % b);
public static Boolean operator ==(JLong a, JLong b) => a._value.Equals(b._value);
public static Boolean operator ==(Int64 a, JLong b) => a.Equals(b._value);
public static Boolean operator ==(JLong a, Int64 b) => a._value.Equals(b);
public static Boolean operator !=(JLong a, JLong b) => !a._value.Equals(b._value);
public static Boolean operator !=(Int64 a, JLong b) => !a.Equals(b._value);
public static Boolean operator !=(JLong a, Int64 b) => !a._value.Equals(b);
public static Boolean operator >(JLong a, JLong b) => a._value.CompareTo(b._value) > 0;
public static Boolean operator >(Int64 a, JLong b) => a.CompareTo(b._value) > 0;
public static Boolean operator >(JLong a, Int64 b) => a._value.CompareTo(b) > 0;
public static Boolean operator <(JLong a, JLong b) => a._value.CompareTo(b._value) < 0;
public static Boolean operator <(Int64 a, JLong b) => a.CompareTo(b._value) < 0;
public static Boolean operator <(JLong a, Int64 b) => a._value.CompareTo(b) < 0;
public static Boolean operator >=(JLong a, JLong b) => a._value.CompareTo(b._value) > 0 || a.Equals(b._value);
public static Boolean operator >=(Int64 a, JLong b) => a.CompareTo(b._value) > 0 || a.Equals(b._value);
public static Boolean operator >=(JLong a, Int64 b) => a._value.CompareTo(b) > 0 || a._value.Equals(b);
public static Boolean operator <=(JLong a, JLong b) => a._value.CompareTo(b._value) < 0 || a.Equals(b._value);
public static Boolean operator <=(Int64 a, JLong b) => a.CompareTo(b._value) < 0 || a.Equals(b._value);
public static Boolean operator <=(JLong a, Int64 b) => a._value.CompareTo(b) < 0 || a._value.Equals(b);
#endregion
#region Public Methods
public Int32 CompareTo(Int64 other) => this._value.CompareTo(other);
public Int32 CompareTo(JLong other) => this._value.CompareTo(other._value);
public Int32 CompareTo(Object obj) => obj is JLong jvalue ? this.CompareTo(jvalue) : obj is Int64 value ? this.CompareTo(value) : this._value.CompareTo(obj);
public Boolean Equals(Int64 other) => this._value.Equals(other);
public Boolean Equals(JLong other) => this._value.Equals(other._value);
public String ToString(String format, IFormatProvider formatProvider) => this._value.ToString(format, formatProvider);
#endregion
#region Overrided Methods
public override String ToString() => this._value.ToString();
public override Boolean Equals(Object obj) => obj is JLong jvalue ? this.Equals(jvalue) : obj is Int64 value ? this.Equals(value) : this._value.Equals(obj);
public override Int32 GetHashCode() => this._value.GetHashCode();
#endregion
}
}

View File

@ -0,0 +1,74 @@
using Rxmxnx.PInvoke;
using System;
namespace LibRyujinx.Jni.Primitives
{
public readonly struct JShort : IComparable<Int16>, IEquatable<Int16>, IFormattable
{
internal static readonly Type Type = typeof(JShort);
public static readonly CString Signature = (CString)"S";
private readonly Int16 _value;
private JShort(Int16 value) => this._value = value;
private JShort(Int32 value) => this._value = Convert.ToInt16(value);
#region Operators
public static implicit operator JShort(Int16 value) => new(value);
public static implicit operator Int16(JShort jValue) => jValue._value;
public static JShort operator +(JShort a) => a;
public static JShort operator ++(JShort a) => new(a._value + 1);
public static JShort operator -(JShort a) => new(-a._value);
public static JShort operator --(JShort a) => new(a._value - 1);
public static JShort operator +(JShort a, JShort b) => new(a._value + b._value);
public static JShort operator +(Int16 a, JShort b) => new(a + b._value);
public static JShort operator +(JShort a, Int16 b) => new(a._value + b);
public static JShort operator -(JShort a, JShort b) => new(a._value - b._value);
public static JShort operator -(Int16 a, JShort b) => new(a - b._value);
public static JShort operator -(JShort a, Int16 b) => new(a._value - b);
public static JShort operator *(JShort a, JShort b) => new(a._value * b._value);
public static JShort operator *(Int16 a, JShort b) => new(a * b._value);
public static JShort operator *(JShort a, Int16 b) => new(a._value * b);
public static JShort operator /(JShort a, JShort b) => new(a._value / b._value);
public static JShort operator /(Int16 a, JShort b) => new(a / b._value);
public static JShort operator /(JShort a, Int16 b) => new(a._value / b);
public static JShort operator %(JShort a, JShort b) => new(a._value % b._value);
public static JShort operator %(Int16 a, JShort b) => new(a % b._value);
public static JShort operator %(JShort a, Int16 b) => new(a._value % b);
public static Boolean operator ==(JShort a, JShort b) => a._value.Equals(b._value);
public static Boolean operator ==(Int16 a, JShort b) => a.Equals(b._value);
public static Boolean operator ==(JShort a, Int16 b) => a._value.Equals(b);
public static Boolean operator !=(JShort a, JShort b) => !a._value.Equals(b._value);
public static Boolean operator !=(Int16 a, JShort b) => !a.Equals(b._value);
public static Boolean operator !=(JShort a, Int16 b) => !a._value.Equals(b);
public static Boolean operator >(JShort a, JShort b) => a._value.CompareTo(b._value) > 0;
public static Boolean operator >(Int16 a, JShort b) => a.CompareTo(b._value) > 0;
public static Boolean operator >(JShort a, Int16 b) => a._value.CompareTo(b) > 0;
public static Boolean operator <(JShort a, JShort b) => a._value.CompareTo(b._value) < 0;
public static Boolean operator <(Int16 a, JShort b) => a.CompareTo(b._value) < 0;
public static Boolean operator <(JShort a, Int16 b) => a._value.CompareTo(b) < 0;
public static Boolean operator >=(JShort a, JShort b) => a._value.CompareTo(b._value) > 0 || a.Equals(b._value);
public static Boolean operator >=(Int16 a, JShort b) => a.CompareTo(b._value) > 0 || a.Equals(b._value);
public static Boolean operator >=(JShort a, Int16 b) => a._value.CompareTo(b) > 0 || a._value.Equals(b);
public static Boolean operator <=(JShort a, JShort b) => a._value.CompareTo(b._value) < 0 || a.Equals(b._value);
public static Boolean operator <=(Int16 a, JShort b) => a.CompareTo(b._value) < 0 || a.Equals(b._value);
public static Boolean operator <=(JShort a, Int16 b) => a._value.CompareTo(b) < 0 || a._value.Equals(b);
#endregion
#region Public Methods
public Int32 CompareTo(Int16 other) => this._value.CompareTo(other);
public Int32 CompareTo(JShort other) => this._value.CompareTo(other._value);
public Int32 CompareTo(Object obj) => obj is JShort jvalue ? this.CompareTo(jvalue) : obj is Int16 value ? this.CompareTo(value) : this._value.CompareTo(obj);
public Boolean Equals(Int16 other) => this._value.Equals(other);
public Boolean Equals(JShort other) => this._value.Equals(other._value);
public String ToString(String format, IFormatProvider formatProvider) => this._value.ToString(format, formatProvider);
#endregion
#region Overrided Methods
public override String ToString() => this._value.ToString();
public override Boolean Equals(Object obj) => obj is JShort jvalue ? this.Equals(jvalue) : obj is Int16 value ? this.Equals(value) : this._value.Equals(obj);
public override Int32 GetHashCode() => this._value.GetHashCode();
#endregion
}
}

View File

@ -0,0 +1,26 @@
using System;
using System.Diagnostics.CodeAnalysis;
namespace LibRyujinx.Jni.References;
public readonly struct JArrayLocalRef : IEquatable<JArrayLocalRef>
{
#pragma warning disable 0649
private readonly JObjectLocalRef _value;
#pragma warning restore 0649
#region Public Methods
public Boolean Equals(JArrayLocalRef other) => this._value.Equals(other._value);
#endregion
#region Override Methods
public override Boolean Equals([NotNullWhen(true)] Object obj) => obj is JArrayLocalRef other && this.Equals(other);
public override Int32 GetHashCode() => this._value.GetHashCode();
#endregion
#region Operators
public static explicit operator JObjectLocalRef(JArrayLocalRef a) => a._value;
public static Boolean operator ==(JArrayLocalRef a, JArrayLocalRef b) => a.Equals(b);
public static Boolean operator !=(JArrayLocalRef a, JArrayLocalRef b) => !a.Equals(b);
#endregion
}

View File

@ -0,0 +1,29 @@
using System;
using System.Diagnostics.CodeAnalysis;
namespace LibRyujinx.Jni.References;
public readonly struct JClassLocalRef : IEquatable<JClassLocalRef>
{
#pragma warning disable 0649
private readonly JObjectLocalRef _value;
#pragma warning restore 0649
private JClassLocalRef(JObjectLocalRef value) => this._value = value;
#region Public Methods
public Boolean Equals(JClassLocalRef other) => this._value.Equals(other._value);
#endregion
#region Override Methods
public override Boolean Equals([NotNullWhen(true)] Object obj) => obj is JClassLocalRef other && this.Equals(other);
public override Int32 GetHashCode() => this._value.GetHashCode();
#endregion
#region Operators
public static explicit operator JObjectLocalRef(JClassLocalRef a) => a._value;
public static explicit operator JClassLocalRef(JObjectLocalRef a) => new(a);
public static Boolean operator ==(JClassLocalRef a, JClassLocalRef b) => a.Equals(b);
public static Boolean operator !=(JClassLocalRef a, JClassLocalRef b) => !a.Equals(b);
#endregion
}

View File

@ -0,0 +1,28 @@
using System;
using System.Diagnostics.CodeAnalysis;
namespace LibRyujinx.Jni.References;
public readonly struct JGlobalRef : IEquatable<JGlobalRef>
{
#pragma warning disable 0649
private readonly JObjectLocalRef _value;
public JObjectLocalRef Value => _value;
#pragma warning restore 0649
#region Public Methods
public Boolean Equals(JGlobalRef other) => this._value.Equals(other._value);
#endregion
#region Override Methods
public override Boolean Equals([NotNullWhen(true)] Object obj) => obj is JGlobalRef other && this.Equals(other);
public override Int32 GetHashCode() => this._value.GetHashCode();
#endregion
#region Operators
public static explicit operator JObjectLocalRef(JGlobalRef a) => a._value;
public static Boolean operator ==(JGlobalRef a, JGlobalRef b) => a.Equals(b);
public static Boolean operator !=(JGlobalRef a, JGlobalRef b) => !a.Equals(b);
#endregion
}

View File

@ -0,0 +1,28 @@
using System;
using System.Diagnostics.CodeAnalysis;
namespace LibRyujinx.Jni.References
{
public readonly struct JObjectLocalRef : IEquatable<JObjectLocalRef>
{
#pragma warning disable 0649
private readonly IntPtr _value;
#pragma warning restore 0649
#region Public Methods
public Boolean Equals(JObjectLocalRef other)
=> this._value.Equals(other._value);
#endregion
#region Override Methods
public override Boolean Equals([NotNullWhen(true)] Object obj)
=> obj is JObjectLocalRef other && this.Equals(other);
public override Int32 GetHashCode() => this._value.GetHashCode();
#endregion
#region Operators
public static Boolean operator ==(JObjectLocalRef a, JObjectLocalRef b) => a.Equals(b);
public static Boolean operator !=(JObjectLocalRef a, JObjectLocalRef b) => !a.Equals(b);
#endregion
}
}

View File

@ -0,0 +1,27 @@
using System;
using System.Diagnostics.CodeAnalysis;
namespace LibRyujinx.Jni.References;
public readonly struct JStringLocalRef : IEquatable<JStringLocalRef>
{
#pragma warning disable 0649
private readonly JObjectLocalRef _value;
#pragma warning restore 0649
#region Public Methods
public Boolean Equals(JStringLocalRef other) => this._value.Equals(other._value);
#endregion
#region Override Methods
public override Boolean Equals([NotNullWhen(true)] Object obj)
=> obj is JStringLocalRef other && this.Equals(other);
public override Int32 GetHashCode() => this._value.GetHashCode();
#endregion
#region Operators
public static explicit operator JObjectLocalRef(JStringLocalRef a) => a._value;
public static Boolean operator ==(JStringLocalRef a, JStringLocalRef b) => a.Equals(b);
public static Boolean operator !=(JStringLocalRef a, JStringLocalRef b) => !a.Equals(b);
#endregion
}

View File

@ -0,0 +1,27 @@
using System;
using System.Diagnostics.CodeAnalysis;
namespace LibRyujinx.Jni.References;
public readonly struct JThrowableLocalRef : IEquatable<JThrowableLocalRef>
{
#pragma warning disable 0649
private readonly JObjectLocalRef _value;
#pragma warning restore 0649
#region Public Methods
public Boolean Equals(JThrowableLocalRef other) => this._value.Equals(other._value);
#endregion
#region Override Methods
public override Boolean Equals([NotNullWhen(true)] Object obj)
=> obj is JThrowableLocalRef other && this.Equals(other);
public override Int32 GetHashCode() => this._value.GetHashCode();
#endregion
#region Operators
public static explicit operator JObjectLocalRef(JThrowableLocalRef a) => a._value;
public static Boolean operator ==(JThrowableLocalRef a, JThrowableLocalRef b) => a.Equals(b);
public static Boolean operator !=(JThrowableLocalRef a, JThrowableLocalRef b) => !a.Equals(b);
#endregion
}

View File

@ -0,0 +1,26 @@
using System;
using System.Diagnostics.CodeAnalysis;
namespace LibRyujinx.Jni.References;
public readonly struct JWeakRef : IEquatable<JWeakRef>
{
#pragma warning disable 0649
private readonly JObjectLocalRef _value;
#pragma warning restore 0649
#region Public Methods
public Boolean Equals(JWeakRef other) => this._value.Equals(other._value);
#endregion
#region Override Methods
public override Boolean Equals([NotNullWhen(true)] Object obj) => obj is JWeakRef other && this.Equals(other);
public override Int32 GetHashCode() => this._value.GetHashCode();
#endregion
#region Operators
public static explicit operator JObjectLocalRef(JWeakRef a) => a._value;
public static Boolean operator ==(JWeakRef a, JWeakRef b) => a.Equals(b);
public static Boolean operator !=(JWeakRef a, JWeakRef b) => !a.Equals(b);
#endregion
}

View File

@ -0,0 +1,30 @@
using Rxmxnx.PInvoke;
using System;
namespace LibRyujinx.Jni.Values
{
internal readonly struct JEnvValue : IEquatable<JEnvValue>
{
#pragma warning disable 0649
private readonly IntPtr _value;
#pragma warning restore 0649
#region Operators
public static Boolean operator ==(JEnvValue a, JEnvValue b) => a._value.Equals(b._value);
public static Boolean operator !=(JEnvValue a, JEnvValue b) => !a._value.Equals(b._value);
#endregion
#region Public Properties
internal readonly ref JNativeInterface Functions => ref this._value.GetUnsafeReference<JNativeInterface>();
#endregion
#region Public Methods
public Boolean Equals(JEnvValue other) => this._value.Equals(other._value);
#endregion
#region Overrided Methods
public override Boolean Equals(Object obj) => obj is JEnvValue other && this.Equals(other);
public override Int32 GetHashCode() => this._value.GetHashCode();
#endregion
}
}

View File

@ -0,0 +1,20 @@
using System;
using System.Diagnostics.CodeAnalysis;
namespace LibRyujinx.Jni.Values
{
[SuppressMessage("CodeQuality", "IDE0051:Remove unused private members", Justification = "This struct is created only by binary operations.")]
public readonly struct JInvokeInterface
{
#pragma warning disable 0169
private readonly IntPtr _reserved0;
private readonly IntPtr _reserved1;
private readonly IntPtr _reserved2;
#pragma warning restore 0169
internal IntPtr DestroyJavaVMPointer { get; init; }
internal IntPtr AttachCurrentThreadPointer { get; init; }
internal IntPtr DetachCurrentThreadPointer { get; init; }
internal IntPtr GetEnvPointer { get; init; }
internal IntPtr AttachCurrentThreadAsDaemonPointer { get; init; }
}
}

View File

@ -0,0 +1,247 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
namespace LibRyujinx.Jni.Values;
[SuppressMessage("CodeQuality", "IDE0051:Remove unused private members",
Justification = "This struct is created only by binary operations.")]
[StructLayout(LayoutKind.Sequential)]
public readonly struct JNativeInterface
{
#pragma warning disable 0169
private readonly IntPtr _reserved0;
private readonly IntPtr _reserved1;
private readonly IntPtr _reserved2;
private readonly IntPtr _reserved3;
#pragma warning restore 0169
internal readonly IntPtr GetVersionPointer { get; init; }
internal readonly IntPtr DefineClassPointer { get; init; }
internal readonly IntPtr FindClassPointer { get; init; }
internal readonly IntPtr FromReflectedMethodPointer { get; init; }
internal readonly IntPtr FromReflectedFieldPointer { get; init; }
internal readonly IntPtr ToReflectedMethodPointer { get; init; }
internal readonly IntPtr GetSuperclassPointer { get; init; }
internal readonly IntPtr IsAssignableFromPointer { get; init; }
internal readonly IntPtr ToReflectedFieldPointer { get; init; }
internal readonly IntPtr ThrowPointer { get; init; }
internal readonly IntPtr ThrowNewPointer { get; init; }
internal readonly IntPtr ExceptionOccurredPointer { get; init; }
internal readonly IntPtr ExceptionDescribePointer { get; init; }
internal readonly IntPtr ExceptionClearPointer { get; init; }
internal readonly IntPtr FatalErrorPointer { get; init; }
internal readonly IntPtr PushLocalFramePointer { get; init; }
internal readonly IntPtr PopLocalFramePointer { get; init; }
internal readonly IntPtr NewGlobalRefPointer { get; init; }
internal readonly IntPtr DeleteGlobalRefPointer { get; init; }
internal readonly IntPtr DeleteLocalRefPointer { get; init; }
internal readonly IntPtr IsSameObjectPointer { get; init; }
internal readonly IntPtr NewLocalRefPointer { get; init; }
internal readonly IntPtr EnsureLocalCapacityPointer { get; init; }
internal readonly IntPtr AllocObjectPointer { get; init; }
internal readonly IntPtr NewObjectPointer { get; init; }
internal readonly IntPtr NewObjectVPointer { get; init; }
internal readonly IntPtr NewObjectAPointer { get; init; }
internal readonly IntPtr GetObjectClassPointer { get; init; }
internal readonly IntPtr IsInstanceOfPointer { get; init; }
internal readonly IntPtr GetMethodIdPointer { get; init; }
private readonly IntPtr CallObjectMethodPointer { get; init; }
private readonly IntPtr CallObjectMethodVPointer { get; init; }
internal readonly IntPtr CallObjectMethodAPointer { get; init; }
private readonly IntPtr CallBooleanMethodPointer { get; init; }
private readonly IntPtr CallBooleanMethodVPointer { get; init; }
internal readonly IntPtr CallBooleanMethodAPointer { get; init; }
private readonly IntPtr CallByteMethodPointer { get; init; }
private readonly IntPtr CallByteMethodVPointer { get; init; }
internal readonly IntPtr CallByteMethodAPointer { get; init; }
private readonly IntPtr CallCharMethodPointer { get; init; }
private readonly IntPtr CallCharMethodVPointer { get; init; }
internal readonly IntPtr CallCharMethodAPointer { get; init; }
private readonly IntPtr CallShortMethodPointer { get; init; }
private readonly IntPtr CallShortMethodVPointer { get; init; }
internal readonly IntPtr CallShortMethodAPointer { get; init; }
private readonly IntPtr CallIntMethodPointer { get; init; }
private readonly IntPtr CallIntMethodVPointer { get; init; }
internal readonly IntPtr CallIntMethodAPointer { get; init; }
private readonly IntPtr CallLongMethodPointer { get; init; }
private readonly IntPtr CallLongMethodVPointer { get; init; }
internal readonly IntPtr CallLongMethodAPointer { get; init; }
private readonly IntPtr CallFloatMethodPointer { get; init; }
private readonly IntPtr CallFloatMethodVPointer { get; init; }
internal readonly IntPtr CallFloatMethodAPointer { get; init; }
private readonly IntPtr CallDoubleMethodPointer { get; init; }
private readonly IntPtr CallDoubleMethodVPointer { get; init; }
internal readonly IntPtr CallDoubleMethodAPointer { get; init; }
private readonly IntPtr CallVoidMethodPointer { get; init; }
private readonly IntPtr CallVoidMethodVPointer { get; init; }
internal readonly IntPtr CallVoidMethodAPointer { get; init; }
private readonly IntPtr CallNonVirtualObjectMethodPointer { get; init; }
private readonly IntPtr CallNonVirtualObjectMethodVPointer { get; init; }
internal readonly IntPtr CallNonVirtualObjectMethodAPointer { get; init; }
private readonly IntPtr CallNonVirtualBooleanMethodPointer { get; init; }
private readonly IntPtr CallNonVirtualBooleanMethodVPointer { get; init; }
internal readonly IntPtr CallNonVirtualBooleanMethodAPointer { get; init; }
private readonly IntPtr CallNonVirtualByteMethodPointer { get; init; }
private readonly IntPtr CallNonVirtualByteMethodVPointer { get; init; }
internal readonly IntPtr CallNonVirtualByteMethodAPointer { get; init; }
private readonly IntPtr CallNonVirtualCharMethodPointer { get; init; }
private readonly IntPtr CallNonVirtualCharMethodVPointer { get; init; }
internal readonly IntPtr CallNonVirtualCharMethodAPointer { get; init; }
private readonly IntPtr CallNonVirtualShortMethodPointer { get; init; }
private readonly IntPtr CallNonVirtualShortMethodVPointer { get; init; }
internal readonly IntPtr CallNonVirtualShortMethodAPointer { get; init; }
private readonly IntPtr CallNonVirtualIntMethodPointer { get; init; }
private readonly IntPtr CallNonVirtualIntMethodVPointer { get; init; }
internal readonly IntPtr CallNonVirtualIntMethodAPointer { get; init; }
private readonly IntPtr CallNonVirtualLongMethodPointer { get; init; }
private readonly IntPtr CallNonVirtualLongMethodVPointer { get; init; }
internal readonly IntPtr CallNonVirtualLongMethodAPointer { get; init; }
private readonly IntPtr CallNonVirtualFloatMethodPointer { get; init; }
private readonly IntPtr CallNonVirtualFloatMethodVPointer { get; init; }
internal readonly IntPtr CallNonVirtualFloatMethodAPointer { get; init; }
private readonly IntPtr CallNonVirtualDoubleMethodPointer { get; init; }
private readonly IntPtr CallNonVirtualDoubleMethodVPointer { get; init; }
internal readonly IntPtr CallNonVirtualDoubleMethodAPointer { get; init; }
private readonly IntPtr CallNonVirtualVoidMethodPointer { get; init; }
private readonly IntPtr CallNonVirtualVoidMethodVPointer { get; init; }
internal readonly IntPtr CallNonVirtualVoidMethodAPointer { get; init; }
internal readonly IntPtr GetFieldIdPointer { get; init; }
internal readonly IntPtr GetObjectFieldPointer { get; init; }
internal readonly IntPtr GetBooleanFieldPointer { get; init; }
internal readonly IntPtr GetByteFieldPointer { get; init; }
internal readonly IntPtr GetCharFieldPointer { get; init; }
internal readonly IntPtr GetShortFieldPointer { get; init; }
internal readonly IntPtr GetIntFieldPointer { get; init; }
internal readonly IntPtr GetLongFieldPointer { get; init; }
internal readonly IntPtr GetFloatFieldPointer { get; init; }
internal readonly IntPtr GetDoubleFieldPointer { get; init; }
internal readonly IntPtr SetObjectFieldPointer { get; init; }
internal readonly IntPtr SetBooleanFieldPointer { get; init; }
internal readonly IntPtr SetByteFieldPointer { get; init; }
internal readonly IntPtr SetCharFieldPointer { get; init; }
internal readonly IntPtr SetShortFieldPointer { get; init; }
internal readonly IntPtr SetIntFieldPointer { get; init; }
internal readonly IntPtr SetLongFieldPointer { get; init; }
internal readonly IntPtr SetFloatFieldPointer { get; init; }
internal readonly IntPtr SetDoubleFieldPointer { get; init; }
internal readonly IntPtr GetStaticMethodIdPointer { get; init; }
private readonly IntPtr CallStaticObjectMethodPointer { get; init; }
private readonly IntPtr CallStaticObjectMethodVPointer { get; init; }
internal readonly IntPtr CallStaticObjectMethodAPointer { get; init; }
private readonly IntPtr CallStaticBooleanMethodPointer { get; init; }
private readonly IntPtr CallStaticBooleanMethodVPointer { get; init; }
internal readonly IntPtr CallStaticBooleanMethodAPointer { get; init; }
private readonly IntPtr CallStaticByteMethodPointer { get; init; }
private readonly IntPtr CallStaticByteMethodVPointer { get; init; }
internal readonly IntPtr CallStaticByteMethodAPointer { get; init; }
private readonly IntPtr CallStaticCharMethodPointer { get; init; }
private readonly IntPtr CallStaticCharMethodVPointer { get; init; }
internal readonly IntPtr CallStaticCharMethodAPointer { get; init; }
private readonly IntPtr CallStaticShortMethodPointer { get; init; }
private readonly IntPtr CallStaticShortMethodVPointer { get; init; }
internal readonly IntPtr CallStaticShortMethodAPointer { get; init; }
private readonly IntPtr CallStaticIntMethodPointer { get; init; }
private readonly IntPtr CallStaticIntMethodVPointer { get; init; }
internal readonly IntPtr CallStaticIntMethodAPointer { get; init; }
private readonly IntPtr CallStaticLongMethodPointer { get; init; }
private readonly IntPtr CallStaticLongMethodVPointer { get; init; }
internal readonly IntPtr CallStaticLongMethodAPointer { get; init; }
private readonly IntPtr CallStaticFloatMethodPointer { get; init; }
private readonly IntPtr CallStaticFloatMethodVPointer { get; init; }
internal readonly IntPtr CallStaticFloatMethodAPointer { get; init; }
private readonly IntPtr CallStaticDoubleMethodPointer { get; init; }
private readonly IntPtr CallStaticDoubleMethodVPointer { get; init; }
internal readonly IntPtr CallStaticDoubleMethodAPointer { get; init; }
private readonly IntPtr CallStaticVoidMethodPointer { get; init; }
private readonly IntPtr CallStaticVoidMethodVPointer { get; init; }
internal readonly IntPtr CallStaticVoidMethodAPointer { get; init; }
internal readonly IntPtr GetStaticFieldIdPointer { get; init; }
internal readonly IntPtr GetStaticObjectFieldPointer { get; init; }
internal readonly IntPtr GetStaticBooleanFieldPointer { get; init; }
internal readonly IntPtr GetStaticByteFieldPointer { get; init; }
internal readonly IntPtr GetStaticCharFieldPointer { get; init; }
internal readonly IntPtr GetStaticShortFieldPointer { get; init; }
internal readonly IntPtr GetStaticIntFieldPointer { get; init; }
internal readonly IntPtr GetStaticLongFieldPointer { get; init; }
internal readonly IntPtr GetStaticFloatFieldPointer { get; init; }
internal readonly IntPtr GetStaticDoubleFieldPointer { get; init; }
internal readonly IntPtr SetStaticObjectFieldPointer { get; init; }
internal readonly IntPtr SetStaticBooleanFieldPointer { get; init; }
internal readonly IntPtr SetStaticByteFieldPointer { get; init; }
internal readonly IntPtr SetStaticCharFieldPointer { get; init; }
internal readonly IntPtr SetStaticShortFieldPointer { get; init; }
internal readonly IntPtr SetStaticIntFieldPointer { get; init; }
internal readonly IntPtr SetStaticLongFieldPointer { get; init; }
internal readonly IntPtr SetStaticFloatFieldPointer { get; init; }
internal readonly IntPtr SetStaticDoubleFieldPointer { get; init; }
internal readonly IntPtr NewStringPointer { get; init; }
internal readonly IntPtr GetStringLengthPointer { get; init; }
internal readonly IntPtr GetStringCharsPointer { get; init; }
internal readonly IntPtr ReleaseStringCharsPointer { get; init; }
internal readonly IntPtr NewStringUtfPointer { get; init; }
internal readonly IntPtr GetStringUtfLengthPointer { get; init; }
internal readonly IntPtr GetStringUtfCharsPointer { get; init; }
internal readonly IntPtr ReleaseStringUtfCharsPointer { get; init; }
internal readonly IntPtr GetArrayLengthPointer { get; init; }
internal readonly IntPtr NewObjectArrayPointer { get; init; }
internal readonly IntPtr GetObjectArrayElementPointer { get; init; }
internal readonly IntPtr SetObjectArrayElementPointer { get; init; }
internal readonly IntPtr NewBooleanArrayPointer { get; init; }
internal readonly IntPtr NewByteArrayPointer { get; init; }
internal readonly IntPtr NewCharArrayPointer { get; init; }
internal readonly IntPtr NewShortArrayPointer { get; init; }
internal readonly IntPtr NewIntArrayPointer { get; init; }
internal readonly IntPtr NewLongArrayPointer { get; init; }
internal readonly IntPtr NewFloatArrayPointer { get; init; }
internal readonly IntPtr NewDoubleArrayPointer { get; init; }
internal readonly IntPtr GetBooleanArrayElementsPointer { get; init; }
internal readonly IntPtr GetByteArrayElementsPointer { get; init; }
internal readonly IntPtr GetCharArrayElementsPointer { get; init; }
internal readonly IntPtr GetShortArrayElementsPointer { get; init; }
internal readonly IntPtr GetIntArrayElementsPointer { get; init; }
internal readonly IntPtr GetLongArrayElementsPointer { get; init; }
internal readonly IntPtr GetFloatArrayElementsPointer { get; init; }
internal readonly IntPtr GetDoubleArrayElementsPointer { get; init; }
internal readonly IntPtr ReleaseBooleanArrayElementsPointer { get; init; }
internal readonly IntPtr ReleaseByteArrayElementsPointer { get; init; }
internal readonly IntPtr ReleaseCharArrayElementsPointer { get; init; }
internal readonly IntPtr ReleaseShortArrayElementsPointer { get; init; }
internal readonly IntPtr ReleaseIntArrayElementsPointer { get; init; }
internal readonly IntPtr ReleaseLongArrayElementsPointer { get; init; }
internal readonly IntPtr ReleaseFloatArrayElementsPointer { get; init; }
internal readonly IntPtr ReleaseDoubleArrayElementsPointer { get; init; }
internal readonly IntPtr GetBooleanArrayRegionPointer { get; init; }
internal readonly IntPtr GetByteArrayRegionPointer { get; init; }
internal readonly IntPtr GetCharArrayRegionPointer { get; init; }
internal readonly IntPtr GetShortArrayRegionPointer { get; init; }
internal readonly IntPtr GetIntArrayRegionPointer { get; init; }
internal readonly IntPtr GetLongArrayRegionPointer { get; init; }
internal readonly IntPtr GetFloatArrayRegionPointer { get; init; }
internal readonly IntPtr GetDoubleArrayRegionPointer { get; init; }
internal readonly IntPtr SetBooleanArrayRegionPointer { get; init; }
internal readonly IntPtr SetByteArrayRegionPointer { get; init; }
internal readonly IntPtr SetCharArrayRegionPointer { get; init; }
internal readonly IntPtr SetShortArrayRegionPointer { get; init; }
internal readonly IntPtr SetIntArrayRegionPointer { get; init; }
internal readonly IntPtr SetLongArrayRegionPointer { get; init; }
internal readonly IntPtr SetFloatArrayRegionPointer { get; init; }
internal readonly IntPtr SetDoubleArrayRegionPointer { get; init; }
internal readonly IntPtr RegisterNativesPointer { get; init; }
internal readonly IntPtr UnregisterNativesPointer { get; init; }
internal readonly IntPtr MonitorEnterPointer { get; init; }
internal readonly IntPtr MonitorExitPointer { get; init; }
internal readonly IntPtr GetJavaVMPointer { get; init; }
internal readonly IntPtr GetStringRegionPointer { get; init; }
internal readonly IntPtr GetStringUtfRegionPointer { get; init; }
internal readonly IntPtr GetPrimitiveArrayCriticalPointer { get; init; }
internal readonly IntPtr ReleasePrimitiveArrayCriticalPointer { get; init; }
internal readonly IntPtr GetStringCriticalPointer { get; init; }
internal readonly IntPtr ReleaseStringCriticalPointer { get; init; }
internal readonly IntPtr NewWeakGlobalRefPointer { get; init; }
internal readonly IntPtr DeleteWeakGlobalRefPointer { get; init; }
internal readonly IntPtr ExceptionCheckPointer { get; init; }
internal readonly IntPtr NewDirectByteBufferPointer { get; init; }
internal readonly IntPtr GetDirectBufferAddressPointer { get; init; }
internal readonly IntPtr GetDirectBufferCapacityPointer { get; init; }
internal readonly IntPtr GetObjectRefTypePointer { get; init; }
}

View File

@ -0,0 +1,11 @@
using Rxmxnx.PInvoke;
using System;
namespace LibRyujinx.Jni.Values;
public readonly struct JNativeMethod
{
internal ReadOnlyValPtr<Byte> Name { get; init; }
internal ReadOnlyValPtr<Byte> Signature { get; init; }
internal IntPtr Pointer { get; init; }
}

View File

@ -0,0 +1,46 @@
using System;
using System.Runtime.CompilerServices;
using LibRyujinx.Jni.References;
using Rxmxnx.PInvoke;
namespace LibRyujinx.Jni.Values;
internal readonly struct JValue
{
private delegate Boolean IsDefaultDelegate(in JValue value);
private static readonly Int32 size = NativeUtilities.SizeOf<JValue>();
private static readonly IsDefaultDelegate isDefault = JValue.GetIsDefault();
#pragma warning disable 0649
#pragma warning disable 0169
private readonly Byte _value1;
private readonly Byte _value2;
private readonly Int16 _value3;
private readonly Int32 _value4;
#pragma warning restore 0169
#pragma warning restore 0649
public Boolean IsDefault => JValue.isDefault(this);
public static JValue Create(in ReadOnlySpan<Byte> source)
{
Byte[] result = new Byte[JValue.size];
for (Int32 i = 0; i < source.Length; i++)
result[i] = source[i];
return result.ToValue<JValue>();
}
private static IsDefaultDelegate GetIsDefault() => Environment.Is64BitProcess ? JValue.DefaultLong : JValue.Default;
private static Boolean Default(in JValue jValue)
=> jValue._value1 + jValue._value2 + jValue._value3 == default && jValue._value4 == default;
private static Boolean DefaultLong(in JValue jValue)
=> Unsafe.AsRef(in jValue).Transform<JValue, Int64>() == default;
public static explicit operator JValue(JObjectLocalRef a) => JValue.Create(NativeUtilities.AsBytes(in a));
}

View File

@ -0,0 +1,13 @@
using LibRyujinx.Jni.References;
using Rxmxnx.PInvoke;
using System;
namespace LibRyujinx.Jni.Values;
public readonly struct JavaVMAttachArgs
{
internal Int32 Version { get; init; }
internal ReadOnlyValPtr<Byte> Name { get; init; }
internal JObjectLocalRef Group { get; init; }
}

View File

@ -0,0 +1,12 @@
using System;
namespace LibRyujinx.Jni.Values
{
public readonly struct JavaVMInitArgs
{
internal Int32 Version { get; init; }
internal Int32 OptionsLenght { get; init; }
internal IntPtr Options { get; init; }
internal Boolean IgnoreUnrecognized { get; init; }
}
}

View File

@ -0,0 +1,10 @@
using Rxmxnx.PInvoke;
using System;
namespace LibRyujinx.Jni.Values;
public readonly struct JavaVMOption
{
internal ReadOnlyValPtr<Byte> Name { get; init; }
internal IntPtr ExtraInfo { get; init; }
}

View File

@ -0,0 +1,29 @@
using Rxmxnx.PInvoke;
using System;
namespace LibRyujinx.Jni.Values;
internal readonly struct JavaVMValue : IEquatable<JavaVMValue>
{
#pragma warning disable 0649
private readonly IntPtr _value;
#pragma warning restore 0649
#region Operators
public static Boolean operator ==(JavaVMValue a, JavaVMValue b) => a._value.Equals(b._value);
public static Boolean operator !=(JavaVMValue a, JavaVMValue b) => !a._value.Equals(b._value);
#endregion
#region Public Properties
internal readonly ref JInvokeInterface Functions => ref this._value.GetUnsafeReference<JInvokeInterface>();
#endregion
#region Public Methods
public Boolean Equals(JavaVMValue other) => this._value.Equals(other._value);
#endregion
#region Overrided Methods
public override Boolean Equals(Object obj) => obj is JavaVMValue other && this.Equals(other);
public override Int32 GetHashCode() => this._value.GetHashCode();
#endregion
}

View File

@ -0,0 +1,566 @@
using LibRyujinx.Android;
using LibRyujinx.Jni.Pointers;
using Ryujinx.Audio.Backends.OpenAL;
using Ryujinx.Common;
using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging;
using Ryujinx.Common.Logging.Targets;
using Ryujinx.HLE.HOS.SystemState;
using Ryujinx.Input;
using Silk.NET.Core.Loader;
using Silk.NET.Vulkan;
using Silk.NET.Vulkan.Extensions.KHR;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Runtime.InteropServices;
using System.Threading;
namespace LibRyujinx
{
public static partial class LibRyujinx
{
private static long _surfacePtr;
private static long _window = 0;
public static VulkanLoader? VulkanLoader { get; private set; }
[DllImport("libryujinxjni")]
internal extern static void setRenderingThread();
[DllImport("libryujinxjni")]
internal extern static void debug_break(int code);
[DllImport("libryujinxjni")]
internal extern static void setCurrentTransform(long native_window, int transform);
public delegate IntPtr JniCreateSurface(IntPtr native_surface, IntPtr instance);
[UnmanagedCallersOnly(EntryPoint = "javaInitialize")]
public unsafe static bool JniInitialize(IntPtr jpathId, IntPtr jniEnv)
{
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
PlatformInfo.IsBionic = true;
Logger.AddTarget(
new AsyncLogTargetWrapper(
new AndroidLogTarget("RyujinxLog"),
1000,
AsyncLogTargetOverflowAction.Block
));
var path = Marshal.PtrToStringAnsi(jpathId);
var init = Initialize(path);
Interop.Initialize(new JEnvRef(jniEnv));
Interop.Test();
return init;
}
[UnmanagedCallersOnly(EntryPoint = "deviceReloadFilesystem")]
public static void JnaReloadFileSystem()
{
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
SwitchDevice?.ReloadFileSystem();
}
[UnmanagedCallersOnly(EntryPoint = "deviceInitialize")]
public static bool JnaDeviceInitialize(bool isHostMapped,
bool useNce,
int systemLanguage,
int regionCode,
bool enableVsync,
bool enableDockedMode,
bool enablePtc,
bool enableInternetAccess,
IntPtr timeZonePtr,
bool ignoreMissingServices)
{
debug_break(4);
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
AudioDriver = new OpenALHardwareDeviceDriver();
var timezone = Marshal.PtrToStringAnsi(timeZonePtr);
return InitializeDevice(isHostMapped,
useNce,
(SystemLanguage)systemLanguage,
(RegionCode)regionCode,
enableVsync,
enableDockedMode,
enablePtc,
enableInternetAccess,
timezone,
ignoreMissingServices);
}
[UnmanagedCallersOnly(EntryPoint = "deviceGetGameFifo")]
public static double JnaGetGameFifo()
{
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
var stats = SwitchDevice?.EmulationContext?.Statistics.GetFifoPercent() ?? 0;
return stats;
}
[UnmanagedCallersOnly(EntryPoint = "deviceGetGameFrameTime")]
public static double JnaGetGameFrameTime()
{
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
var stats = SwitchDevice?.EmulationContext?.Statistics.GetGameFrameTime() ?? 0;
return stats;
}
[UnmanagedCallersOnly(EntryPoint = "deviceGetGameFrameRate")]
public static double JnaGetGameFrameRate()
{
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
var stats = SwitchDevice?.EmulationContext?.Statistics.GetGameFrameRate() ?? 0;
return stats;
}
[UnmanagedCallersOnly(EntryPoint = "deviceLaunchMiiEditor")]
public static bool JNALaunchMiiEditApplet()
{
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
if (SwitchDevice?.EmulationContext == null)
{
return false;
}
return LaunchMiiEditApplet();
}
[UnmanagedCallersOnly(EntryPoint = "deviceGetDlcContentList")]
public static IntPtr JniGetDlcContentListNative(IntPtr pathPtr, long titleId)
{
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
var list = GetDlcContentList(Marshal.PtrToStringAnsi(pathPtr) ?? "", (ulong)titleId);
return CreateStringArray(list);
}
[UnmanagedCallersOnly(EntryPoint = "deviceGetDlcTitleId")]
public static long JniGetDlcTitleIdNative(IntPtr pathPtr, IntPtr ncaPath)
{
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
return Marshal.StringToHGlobalAnsi(GetDlcTitleId(Marshal.PtrToStringAnsi(pathPtr) ?? "", Marshal.PtrToStringAnsi(ncaPath) ?? ""));
}
[UnmanagedCallersOnly(EntryPoint = "deviceSignalEmulationClose")]
public static void JniSignalEmulationCloseNative()
{
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
SignalEmulationClose();
}
[UnmanagedCallersOnly(EntryPoint = "deviceCloseEmulation")]
public static void JniCloseEmulationNative()
{
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
CloseEmulation();
}
[UnmanagedCallersOnly(EntryPoint = "deviceLoadDescriptor")]
public static bool JnaLoadApplicationNative(int descriptor, int type, int updateDescriptor)
{
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
if (SwitchDevice?.EmulationContext == null)
{
return false;
}
var stream = OpenFile(descriptor);
var update = updateDescriptor == -1 ? null : OpenFile(updateDescriptor);
return LoadApplication(stream, (FileType)type, update);
}
[UnmanagedCallersOnly(EntryPoint = "deviceVerifyFirmware")]
public static IntPtr JniVerifyFirmware(int descriptor, bool isXci)
{
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
var stream = OpenFile(descriptor);
IntPtr stringHandle = 0;
string? version = "0.0";
try
{
version = VerifyFirmware(stream, isXci)?.VersionString;
}
catch (Exception _)
{
Logger.Error?.Print(LogClass.Service, $"Unable to verify firmware. Exception: {_}");
}
if (version != null)
{
stringHandle = Marshal.StringToHGlobalAnsi(version);
}
return stringHandle;
}
[UnmanagedCallersOnly(EntryPoint = "deviceInstallFirmware")]
public static void JniInstallFirmware(int descriptor, bool isXci)
{
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
var stream = OpenFile(descriptor);
InstallFirmware(stream, isXci);
}
[UnmanagedCallersOnly(EntryPoint = "deviceGetInstalledFirmwareVersion")]
public static IntPtr JniGetInstalledFirmwareVersion()
{
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
var version = GetInstalledFirmwareVersion() ?? "0.0";
return Marshal.StringToHGlobalAnsi(version);
}
[UnmanagedCallersOnly(EntryPoint = "graphicsInitialize")]
public static bool JnaGraphicsInitialize(float resScale,
float maxAnisotropy,
bool fastGpuTime,
bool fast2DCopy,
bool enableMacroJit,
bool enableMacroHLE,
bool enableShaderCache,
bool enableTextureRecompression,
int backendThreading)
{
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
SearchPathContainer.Platform = UnderlyingPlatform.Android;
return InitializeGraphics(new GraphicsConfiguration()
{
ResScale = resScale,
MaxAnisotropy = maxAnisotropy,
FastGpuTime = fastGpuTime,
Fast2DCopy = fast2DCopy,
EnableMacroJit = enableMacroJit,
EnableMacroHLE = enableMacroHLE,
EnableShaderCache = enableShaderCache,
EnableTextureRecompression = enableTextureRecompression,
BackendThreading = (BackendThreading)backendThreading
});
}
[UnmanagedCallersOnly(EntryPoint = "graphicsInitializeRenderer")]
public unsafe static bool JnaGraphicsInitializeRenderer(char** extensionsArray,
int extensionsLength,
long driverHandle)
{
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
if (Renderer != null)
{
return false;
}
List<string?> extensions = new();
for (int i = 0; i < extensionsLength; i++)
{
extensions.Add(Marshal.PtrToStringAnsi((IntPtr)extensionsArray[i]));
}
if (driverHandle != 0)
{
VulkanLoader = new VulkanLoader((IntPtr)driverHandle);
}
CreateSurface createSurfaceFunc = instance =>
{
_surfacePtr = Interop.GetSurfacePtr();
_window = Interop.GetWindowsHandle();
var api = VulkanLoader?.GetApi() ?? Vk.GetApi();
if (api.TryGetInstanceExtension(new Instance(instance), out KhrAndroidSurface surfaceExtension))
{
var createInfo = new AndroidSurfaceCreateInfoKHR
{
SType = StructureType.AndroidSurfaceCreateInfoKhr,
Window = (nint*)_surfacePtr,
};
var result = surfaceExtension.CreateAndroidSurface(new Instance(instance), createInfo, null, out var surface);
return (nint)surface.Handle;
}
return IntPtr.Zero;
};
return InitializeGraphicsRenderer(GraphicsBackend.Vulkan, createSurfaceFunc, extensions.ToArray());
}
[UnmanagedCallersOnly(EntryPoint = "graphicsRendererSetSize")]
public static void JnaSetRendererSizeNative(int width, int height)
{
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
Renderer?.Window?.SetSize(width, height);
}
[UnmanagedCallersOnly(EntryPoint = "graphicsRendererRunLoop")]
public static void JniRunLoopNative()
{
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
SetSwapBuffersCallback(() =>
{
var time = SwitchDevice.EmulationContext.Statistics.GetGameFrameTime();
Interop.FrameEnded(time);
});
RunLoop();
}
[UnmanagedCallersOnly(EntryPoint = "loggingSetEnabled")]
public static void JniSetLoggingEnabledNative(int logLevel, bool enabled)
{
Logger.SetEnable((LogLevel)logLevel, enabled);
}
[UnmanagedCallersOnly(EntryPoint = "loggingEnabledGraphicsLog")]
public static void JniSetLoggingEnabledGraphicsLog(bool enabled)
{
_enableGraphicsLogging = enabled;
}
[UnmanagedCallersOnly(EntryPoint = "deviceGetGameInfo")]
public unsafe static void JniGetGameInfo(int fileDescriptor, IntPtr extension, IntPtr infoPtr)
{
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
using var stream = OpenFile(fileDescriptor);
var ext = Marshal.PtrToStringAnsi(extension);
var info = GetGameInfo(stream, ext.ToLower()) ?? GetDefaultInfo(stream);
var i = (GameInfoNative*)infoPtr;
var n = new GameInfoNative(info);
i->TitleId = n.TitleId;
i->TitleName = n.TitleName;
i->Version = n.Version;
i->FileSize = n.FileSize;
i->Icon = n.Icon;
i->Version = n.Version;
i->Developer = n.Developer;
}
[UnmanagedCallersOnly(EntryPoint = "graphicsRendererSetVsync")]
public static void JnaSetVsyncStateNative(bool enabled)
{
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
SetVsyncState(enabled);
}
[UnmanagedCallersOnly(EntryPoint = "inputInitialize")]
public static void JnaInitializeInput(int width, int height)
{
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
InitializeInput(width, height);
}
[UnmanagedCallersOnly(EntryPoint = "inputSetClientSize")]
public static void JnaSetClientSize(int width, int height)
{
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
SetClientSize(width, height);
}
[UnmanagedCallersOnly(EntryPoint = "inputSetTouchPoint")]
public static void JnaSetTouchPoint(int x, int y)
{
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
SetTouchPoint(x, y);
}
[UnmanagedCallersOnly(EntryPoint = "inputReleaseTouchPoint")]
public static void JnaReleaseTouchPoint()
{
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
ReleaseTouchPoint();
}
[UnmanagedCallersOnly(EntryPoint = "inputUpdate")]
public static void JniUpdateInput()
{
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
UpdateInput();
}
[UnmanagedCallersOnly(EntryPoint = "inputSetButtonPressed")]
public static void JnaSetButtonPressed(int button, int id)
{
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
SetButtonPressed((GamepadButtonInputId)button, id);
}
[UnmanagedCallersOnly(EntryPoint = "inputSetButtonReleased")]
public static void JnaSetButtonReleased(int button, int id)
{
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
SetButtonReleased((GamepadButtonInputId)button, id);
}
[UnmanagedCallersOnly(EntryPoint = "inputSetAccelerometerData")]
public static void JniSetAccelerometerData(float x, float y, float z, int id)
{
var accel = new Vector3(x, y, z);
SetAccelerometerData(accel, id);
}
[UnmanagedCallersOnly(EntryPoint = "inputSetGyroData")]
public static void JniSetGyroData(float x, float y, float z, int id)
{
var gryo = new Vector3(x, y, z);
SetGryoData(gryo, id);
}
[UnmanagedCallersOnly(EntryPoint = "inputSetStickAxis")]
public static void JnaSetStickAxis(int stick, float x, float y, int id)
{
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
SetStickAxis((StickInputId)stick, new Vector2(float.IsNaN(x) ? 0 : x, float.IsNaN(y) ? 0 : y), id);
}
[UnmanagedCallersOnly(EntryPoint = "inputConnectGamepad")]
public static int JnaConnectGamepad(int index)
{
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
return ConnectGamepad(index);
}
[UnmanagedCallersOnly(EntryPoint = "userGetOpenedUser")]
public static IntPtr JniGetOpenedUser()
{
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
var userId = GetOpenedUser();
var ptr = Marshal.StringToHGlobalAnsi(userId);
return ptr;
}
[UnmanagedCallersOnly(EntryPoint = "userGetUserPicture")]
public static IntPtr JniGetUserPicture(IntPtr userIdPtr)
{
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
var userId = Marshal.PtrToStringAnsi(userIdPtr) ?? "";
return Marshal.StringToHGlobalAnsi(GetUserPicture(userId));
}
[UnmanagedCallersOnly(EntryPoint = "userSetUserPicture")]
public static void JniGetUserPicture(IntPtr userIdPtr, IntPtr picturePtr)
{
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
var userId = Marshal.PtrToStringAnsi(userIdPtr) ?? "";
var picture = Marshal.PtrToStringAnsi(picturePtr) ?? "";
SetUserPicture(userId, picture);
}
[UnmanagedCallersOnly(EntryPoint = "userGetUserName")]
public static IntPtr JniGetUserName(IntPtr userIdPtr)
{
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
var userId = Marshal.PtrToStringAnsi(userIdPtr) ?? "";
return Marshal.StringToHGlobalAnsi(GetUserName(userId));
}
[UnmanagedCallersOnly(EntryPoint = "userSetUserName")]
public static void JniSetUserName(IntPtr userIdPtr, IntPtr userNamePtr)
{
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
var userId = Marshal.PtrToStringAnsi(userIdPtr) ?? "";
var userName = Marshal.PtrToStringAnsi(userNamePtr) ?? "";
SetUserName(userId, userName);
}
[UnmanagedCallersOnly(EntryPoint = "userGetAllUsers")]
public static IntPtr JniGetAllUsers()
{
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
var users = GetAllUsers();
return CreateStringArray(users.ToList());
}
[UnmanagedCallersOnly(EntryPoint = "userAddUser")]
public static void JniAddUser(IntPtr userNamePtr, IntPtr picturePtr)
{
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
var userName = Marshal.PtrToStringAnsi(userNamePtr) ?? "";
var picture = Marshal.PtrToStringAnsi(picturePtr) ?? "";
AddUser(userName, picture);
}
[UnmanagedCallersOnly(EntryPoint = "userDeleteUser")]
public static void JniDeleteUser(IntPtr userIdPtr)
{
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
var userId = Marshal.PtrToStringAnsi(userIdPtr) ?? "";
DeleteUser(userId);
}
[UnmanagedCallersOnly(EntryPoint = "uiHandlerSetup")]
public static void JniSetupUiHandler()
{
SetupUiHandler();
}
[UnmanagedCallersOnly(EntryPoint = "uiHandlerSetResponse")]
public static void JniSetUiHandlerResponse(bool isOkPressed, IntPtr input)
{
SetUiHandlerResponse(isOkPressed, Marshal.PtrToStringAnsi(input) ?? "");
}
[UnmanagedCallersOnly(EntryPoint = "userOpenUser")]
public static void JniOpenUser(IntPtr userIdPtr)
{
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
var userId = Marshal.PtrToStringAnsi(userIdPtr) ?? "";
OpenUser(userId);
}
[UnmanagedCallersOnly(EntryPoint = "userCloseUser")]
public static void JniCloseUser(IntPtr userIdPtr)
{
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
var userId = Marshal.PtrToStringAnsi(userIdPtr) ?? "";
CloseUser(userId);
}
}
internal static partial class Logcat
{
[LibraryImport("liblog", StringMarshalling = StringMarshalling.Utf8)]
private static partial void __android_log_print(LogLevel level, string? tag, string format, string args, IntPtr ptr);
internal static void AndroidLogPrint(LogLevel level, string? tag, string message) =>
__android_log_print(level, tag, "%s", message, IntPtr.Zero);
internal enum LogLevel
{
Unknown = 0x00,
Default = 0x01,
Verbose = 0x02,
Debug = 0x03,
Info = 0x04,
Warn = 0x05,
Error = 0x06,
Fatal = 0x07,
Silent = 0x08,
}
}
}

View File

@ -0,0 +1,235 @@
using LibHac.Ncm;
using LibHac.Tools.FsSystem.NcaUtils;
using Microsoft.Win32.SafeHandles;
using Ryujinx.Common.Logging;
using Ryujinx.HLE.FileSystem;
using Ryujinx.HLE.HOS.SystemState;
using System;
using System.IO;
using System.Runtime.InteropServices;
namespace LibRyujinx
{
public static partial class LibRyujinx
{
public static bool InitializeDevice(bool isHostMapped,
bool useHypervisor,
SystemLanguage systemLanguage,
RegionCode regionCode,
bool enableVsync,
bool enableDockedMode,
bool enablePtc,
bool enableInternetAccess,
string? timeZone,
bool ignoreMissingServices)
{
if (SwitchDevice == null)
{
return false;
}
return SwitchDevice.InitializeContext(isHostMapped,
useHypervisor,
systemLanguage,
regionCode,
enableVsync,
enableDockedMode,
enablePtc,
enableInternetAccess,
timeZone,
ignoreMissingServices);
}
public static void InstallFirmware(Stream stream, bool isXci)
{
SwitchDevice?.ContentManager.InstallFirmware(stream, isXci);
}
public static string GetInstalledFirmwareVersion()
{
var version = SwitchDevice?.ContentManager.GetCurrentFirmwareVersion();
if (version != null)
{
return version.VersionString;
}
return String.Empty;
}
public static SystemVersion? VerifyFirmware(Stream stream, bool isXci)
{
return SwitchDevice?.ContentManager?.VerifyFirmwarePackage(stream, isXci) ?? null;
}
public static bool LoadApplication(Stream stream, FileType type, Stream? updateStream = null)
{
var emulationContext = SwitchDevice.EmulationContext;
return type switch
{
FileType.None => false,
FileType.Nsp => emulationContext?.LoadNsp(stream, 0, updateStream) ?? false,
FileType.Xci => emulationContext?.LoadXci(stream, 0, updateStream) ?? false,
FileType.Nro => emulationContext?.LoadProgram(stream, true, "") ?? false,
};
}
public static bool LaunchMiiEditApplet()
{
string contentPath = SwitchDevice.ContentManager.GetInstalledContentPath(0x0100000000001009, StorageId.BuiltInSystem, NcaContentType.Program);
return LoadApplication(contentPath);
}
public static bool LoadApplication(string? path)
{
var emulationContext = SwitchDevice.EmulationContext;
if (Directory.Exists(path))
{
string[] romFsFiles = Directory.GetFiles(path, "*.istorage");
if (romFsFiles.Length == 0)
{
romFsFiles = Directory.GetFiles(path, "*.romfs");
}
if (romFsFiles.Length > 0)
{
Logger.Info?.Print(LogClass.Application, "Loading as cart with RomFS.");
if (!emulationContext.LoadCart(path, romFsFiles[0]))
{
SwitchDevice.DisposeContext();
return false;
}
}
else
{
Logger.Info?.Print(LogClass.Application, "Loading as cart WITHOUT RomFS.");
if (!emulationContext.LoadCart(path))
{
SwitchDevice.DisposeContext();
return false;
}
}
}
else if (File.Exists(path))
{
switch (Path.GetExtension(path).ToLowerInvariant())
{
case ".xci":
Logger.Info?.Print(LogClass.Application, "Loading as XCI.");
if (!emulationContext.LoadXci(path))
{
SwitchDevice.DisposeContext();
return false;
}
break;
case ".nca":
Logger.Info?.Print(LogClass.Application, "Loading as NCA.");
if (!emulationContext.LoadNca(path))
{
SwitchDevice.DisposeContext();
return false;
}
break;
case ".nsp":
case ".pfs0":
Logger.Info?.Print(LogClass.Application, "Loading as NSP.");
if (!emulationContext.LoadNsp(path))
{
SwitchDevice.DisposeContext();
return false;
}
break;
default:
Logger.Info?.Print(LogClass.Application, "Loading as Homebrew.");
try
{
if (!emulationContext.LoadProgram(path))
{
SwitchDevice.DisposeContext();
return false;
}
}
catch (ArgumentOutOfRangeException)
{
Logger.Error?.Print(LogClass.Application, "The specified file is not supported by Ryujinx.");
SwitchDevice.DisposeContext();
return false;
}
break;
}
}
else
{
Logger.Warning?.Print(LogClass.Application, $"Couldn't load '{path}'. Please specify a valid XCI/NCA/NSP/PFS0/NRO file.");
SwitchDevice.DisposeContext();
return false;
}
return true;
}
public static void SignalEmulationClose()
{
_isStopped = true;
_isActive = false;
}
public static void CloseEmulation()
{
if (SwitchDevice == null)
return;
_npadManager?.Dispose();
_npadManager = null;
_touchScreenManager?.Dispose();
_touchScreenManager = null;
SwitchDevice!.InputManager?.Dispose();
SwitchDevice!.InputManager = null;
_inputManager = null;
if (Renderer != null)
{
_gpuDoneEvent.WaitOne();
_gpuDoneEvent.Dispose();
_gpuDoneEvent = null;
SwitchDevice?.DisposeContext();
Renderer = null;
}
}
private static FileStream OpenFile(int descriptor)
{
var safeHandle = new SafeFileHandle(descriptor, false);
return new FileStream(safeHandle, FileAccess.ReadWrite);
}
public enum FileType
{
None,
Nsp,
Xci,
Nro
}
}
}

View File

@ -0,0 +1,248 @@
using LibRyujinx.Android;
using LibRyujinx.Shared;
using OpenTK.Graphics.OpenGL;
using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging;
using Ryujinx.Cpu;
using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.GAL.Multithreading;
using Ryujinx.Graphics.Gpu;
using Ryujinx.Graphics.Gpu.Shader;
using Ryujinx.Graphics.OpenGL;
using Ryujinx.Graphics.Vulkan;
using Silk.NET.Vulkan;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Threading;
namespace LibRyujinx
{
public static partial class LibRyujinx
{
private static bool _isActive;
private static bool _isStopped;
private static CancellationTokenSource _gpuCancellationTokenSource;
private static SwapBuffersCallback? _swapBuffersCallback;
private static NativeGraphicsInterop _nativeGraphicsInterop;
private static ManualResetEvent _gpuDoneEvent;
private static bool _enableGraphicsLogging;
public delegate void SwapBuffersCallback();
public delegate IntPtr GetProcAddress(string name);
public delegate IntPtr CreateSurface(IntPtr instance);
public static IRenderer? Renderer { get; set; }
public static GraphicsConfiguration GraphicsConfiguration { get; private set; }
public static bool InitializeGraphics(GraphicsConfiguration graphicsConfiguration)
{
GraphicsConfig.ResScale = graphicsConfiguration.ResScale;
GraphicsConfig.MaxAnisotropy = graphicsConfiguration.MaxAnisotropy;
GraphicsConfig.FastGpuTime = graphicsConfiguration.FastGpuTime;
GraphicsConfig.Fast2DCopy = graphicsConfiguration.Fast2DCopy;
GraphicsConfig.EnableMacroJit = graphicsConfiguration.EnableMacroJit;
GraphicsConfig.EnableMacroHLE = graphicsConfiguration.EnableMacroHLE;
GraphicsConfig.EnableShaderCache = graphicsConfiguration.EnableShaderCache;
GraphicsConfig.EnableTextureRecompression = graphicsConfiguration.EnableTextureRecompression;
GraphicsConfiguration = graphicsConfiguration;
return true;
}
public static bool InitializeGraphicsRenderer(GraphicsBackend graphicsBackend, CreateSurface? createSurfaceFunc, string?[] requiredExtensions)
{
if (Renderer != null)
{
return false;
}
if (graphicsBackend == GraphicsBackend.OpenGl)
{
Renderer = new OpenGLRenderer();
}
else if (graphicsBackend == GraphicsBackend.Vulkan)
{
Renderer = new VulkanRenderer(Vk.GetApi(), (instance, vk) => new SurfaceKHR(createSurfaceFunc == null ? null : (ulong?)createSurfaceFunc(instance.Handle)),
() => requiredExtensions,
null);
}
else
{
return false;
}
return true;
}
public static void SetRendererSize(int width, int height)
{
Renderer?.Window?.SetSize(width, height);
}
public static void SetVsyncState(bool enabled)
{
var device = SwitchDevice!.EmulationContext!;
device.EnableDeviceVsync = enabled;
device.Gpu.Renderer.Window.ChangeVSyncMode(enabled);
}
public static void RunLoop()
{
if (Renderer == null)
{
return;
}
var device = SwitchDevice!.EmulationContext!;
_gpuDoneEvent = new ManualResetEvent(true);
device.Gpu.Renderer.Initialize(_enableGraphicsLogging ? GraphicsDebugLevel.All : GraphicsDebugLevel.None);
_gpuCancellationTokenSource = new CancellationTokenSource();
device.Gpu.ShaderCacheStateChanged += LoadProgressStateChangedHandler;
device.Processes.ActiveApplication.DiskCacheLoadState.StateChanged += LoadProgressStateChangedHandler;
try
{
device.Gpu.Renderer.RunLoop(() =>
{
_gpuDoneEvent.Reset();
device.Gpu.SetGpuThread();
device.Gpu.InitializeShaderCache(_gpuCancellationTokenSource.Token);
_isActive = true;
if (Ryujinx.Common.PlatformInfo.IsBionic)
{
setRenderingThread();
}
while (_isActive)
{
if (_isStopped)
{
break;
}
if (device.WaitFifo())
{
device.Statistics.RecordFifoStart();
device.ProcessFrame();
device.Statistics.RecordFifoEnd();
}
while (device.ConsumeFrameAvailable())
{
device.PresentFrame(() =>
{
if (device.Gpu.Renderer is ThreadedRenderer threaded && threaded.BaseRenderer is VulkanRenderer vulkanRenderer)
{
setCurrentTransform(_window, (int)vulkanRenderer.CurrentTransform);
}
_swapBuffersCallback?.Invoke();
});
}
}
if (device.Gpu.Renderer is ThreadedRenderer threaded)
{
threaded.FlushThreadedCommands();
}
_gpuDoneEvent.Set();
});
}
finally
{
device.Gpu.ShaderCacheStateChanged -= LoadProgressStateChangedHandler;
device.Processes.ActiveApplication.DiskCacheLoadState.StateChanged -= LoadProgressStateChangedHandler;
}
}
private static void LoadProgressStateChangedHandler<T>(T state, int current, int total) where T : Enum
{
void SetInfo(string status, float value)
{
if(Ryujinx.Common.PlatformInfo.IsBionic)
{
Interop.UpdateProgress(status, value);
}
}
var status = $"{current} / {total}";
var progress = current / (float)total;
if (float.IsNaN(progress))
progress = 0;
switch (state)
{
case LoadState ptcState:
if (float.IsNaN((progress)))
progress = 0;
switch (ptcState)
{
case LoadState.Unloaded:
case LoadState.Loading:
SetInfo($"Loading PTC {status}", progress);
break;
case LoadState.Loaded:
SetInfo($"PTC Loaded", -1);
break;
}
break;
case ShaderCacheState shaderCacheState:
switch (shaderCacheState)
{
case ShaderCacheState.Start:
case ShaderCacheState.Loading:
SetInfo($"Compiling Shaders {status}", progress);
break;
case ShaderCacheState.Packaging:
SetInfo($"Packaging Shaders {status}", progress);
break;
case ShaderCacheState.Loaded:
SetInfo($"Shaders Loaded", -1);
break;
}
break;
default:
throw new ArgumentException($"Unknown Progress Handler type {typeof(T)}");
}
}
public static void SetSwapBuffersCallback(SwapBuffersCallback swapBuffersCallback)
{
_swapBuffersCallback = swapBuffersCallback;
}
}
[StructLayout(LayoutKind.Sequential)]
public struct GraphicsConfiguration
{
public float ResScale = 1f;
public float MaxAnisotropy = -1;
public bool FastGpuTime = true;
public bool Fast2DCopy = true;
public bool EnableMacroJit = false;
public bool EnableMacroHLE = true;
public bool EnableShaderCache = true;
public bool EnableTextureRecompression = false;
public BackendThreading BackendThreading = BackendThreading.Auto;
public AspectRatio AspectRatio = AspectRatio.Fixed16x9;
public GraphicsConfiguration()
{
}
}
public struct NativeGraphicsInterop
{
public IntPtr GlGetProcAddress;
public IntPtr VkNativeContextLoader;
public IntPtr VkCreateSurface;
public IntPtr VkRequiredExtensions;
public int VkRequiredExtensionsCount;
}
}

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