Compare commits

..

369 Commits

Author SHA1 Message Date
Evan Husted 61303032f1 Silence compile warnings 2024-12-24 00:31:49 -06:00
Evan Husted bff884a89c UI: Change backend text based on used Window type rather than configured value 2024-12-24 00:18:47 -06:00
Evan Husted 89f3c8235c misc: More places need to factor in Auto, oops 2024-12-23 23:53:58 -06:00
Evan Husted f3545f5eae UI: Auto graphics backend 2024-12-23 23:26:47 -06:00
Evan Husted a335c8ff2b UI: Collapse IsHypervisorAvailable and IsMetalAvailable into IsAppleSiliconMac 2024-12-23 22:37:15 -06:00
Evan Husted 3aaeaf3540 UI: Only allow ARM macs to select Metal backend 2024-12-23 22:35:28 -06:00
Evan Husted e82a90993c UI: Properly disable selecting Metal on non-Mac platforms 2024-12-23 22:32:37 -06:00
Evan Husted f3dcb80a60 GAL changes 2024-12-23 21:52:39 -06:00
Evan Husted d4b9e06522 .NET 9 2024-12-23 21:44:45 -06:00
Isaac Marovitz 0945ea68fe Make resource encoding less stupid 2024-12-23 21:44:34 -06:00
Isaac Marovitz d3c0971acf Set correct maximum supported anisotropy 2024-12-23 21:44:31 -06:00
Isaac Marovitz 7bdae9e552 GAL Changes 2024-12-23 21:44:29 -06:00
Isaac Marovitz 567b0a5027 Updates 2024-12-23 21:44:26 -06:00
Isaac Marovitz a5f82a99a3 GAL Changes 2024-12-23 21:44:23 -06:00
Isaac Marovitz 89c05ac239 Check for null resources before declaring them resident 2024-12-23 21:44:17 -06:00
Isaac Marovitz fe4c77788f Fix null sampler crash 2024-12-23 21:44:11 -06:00
Isaac Marovitz d23de14812 Fix counted indirect draws
Fixes Monster Hunter Rise and Apollo Justice
2024-12-23 21:44:07 -06:00
Isaac Marovitz 216261931e Program hash set 2024-12-23 21:44:04 -06:00
Isaac Marovitz 8c2f3ae8d2 Auto-backed samplers 2024-12-23 21:44:02 -06:00
Isaac Marovitz a710bcd874 Refactor binding logic + Bind image arrays 2024-12-23 21:43:49 -06:00
Isaac Marovitz b941ef6bde Fix primitive id in shader gen
Fixes Dark Souls
2024-12-23 21:43:47 -06:00
Isaac Marovitz b5e6f26296 Fix cubemap array length
Fixes crash in Sonic Frontiers
2024-12-23 21:43:45 -06:00
Isaac Marovitz c0d20f8689 Properly create stencil views of combined formats
Fixes Link’s Awakening
2024-12-23 21:43:42 -06:00
Isaac Marovitz 4a81d9edc4 Add missing set texture for depth stencil blit
Mostly fixes Sonic Frontiers & Link’s Awakening
2024-12-23 21:43:38 -06:00
Isaac Marovitz a05a9a33f1 Fix typo in stride change shader
Fixes Castlevania Dominus Collection
2024-12-23 21:43:35 -06:00
Isaac Marovitz b1e5262893 Fix invalid depth stencil state when no depth stencil is present
Partially fixes Sonic Frontiers and Castlevania Dominus Collection
2024-12-23 21:43:32 -06:00
Isaac Marovitz dce6b94841 Style 2024-12-23 21:43:30 -06:00
Isaac Marovitz 51e85ed38b Metal: Unsupported topology indexed draw conversion (#40)
* Convert unsupported indexed buffer topologies

* Fix index count and dispatch size

* Cleanup

* Fix typos
2024-12-23 21:43:23 -06:00
Isaac Marovitz 38b2cf9b83 Fix null resources breaking arg buffer alignment 2024-12-23 21:43:16 -06:00
Isaac Marovitz e406b67690 Remove RenderPipelineDescriptorResult 2024-12-23 21:43:13 -06:00
Isaac Marovitz 2d522b1675 D32FS8 to D24S8 Conversion 2024-12-23 21:43:10 -06:00
Isaac Marovitz 967887d050 Upstream changes 2024-12-23 21:43:04 -06:00
Isaac Marovitz 3258a4bad1 Logic Operations 2024-12-23 21:43:00 -06:00
Isaac Marovitz 058ce78d31 Fix array size query 2024-12-23 21:42:56 -06:00
Isaac Marovitz b988c0bc3d Debug Groups 2024-12-23 21:42:51 -06:00
Isaac Marovitz 1fc96128fa IaIndexing
Fixes shader problems in Donkey Kong Country Tropical Freeze, and Fire Emblem: Three Houses
2024-12-23 21:42:49 -06:00
Isaac Marovitz 4a11cc9c7a Rasterizer Discard + Multisample State 2024-12-23 21:42:47 -06:00
Isaac Marovitz 782299c123 Metal: Argument Buffer Pre-Pass (#38)
* Init

* Fix missing flags

* Cleanup
2024-12-23 21:42:44 -06:00
riperiperi e8de1156eb Patch some leaks and only perform copies on valid textures (#37) 2024-12-23 21:42:42 -06:00
Isaac Marovitz ceaa174859 Get render command encoder after finalising buffers
Fixes crash in Fire Emblem: Houses
2024-12-23 21:42:40 -06:00
Isaac Marovitz 7eaaeea999 Format 2024-12-23 21:42:38 -06:00
Isaac Marovitz d707273671 Fix non atomic image loads again 2024-12-23 21:42:23 -06:00
Isaac Marovitz 2a7375209e Finally fix (most) image atomics 2024-12-23 21:42:22 -06:00
Isaac Marovitz 2e5ae70b91 Precise Float Fixes
Fixes artifacts in TOTK
2024-12-23 21:42:19 -06:00
Isaac Marovitz 6f24b88e88 Fix image atomics 2024-12-23 21:42:17 -06:00
Isaac Marovitz 5d59c552e7 Fix Non-Float Textures + Image Read + FSI Buffers
Fixes Mario Party Superstars
2024-12-23 21:42:15 -06:00
Isaac Marovitz 341e4e5fb1 Image Constant Fixes
Allows Mario Party Superstars to boot
2024-12-23 21:42:10 -06:00
Isaac Marovitz 68146fa285 Helper Shader fixes for non float formats 2024-12-23 21:41:44 -06:00
Isaac Marovitz 80bb95dfb9 Shader Extra Set Support + Cleanup (#36)
Separate samplers are now supported and arrays in constant sets are bound
2024-12-23 21:41:39 -06:00
Isaac Marovitz 5b88ea66ba InstGenMemory Refactor + Bindless Support 2024-12-23 21:41:35 -06:00
Isaac Marovitz 9d3fc82484 TextureArray & ImageArray Creation + State 2024-12-23 21:41:33 -06:00
Isaac Marovitz 8f6eceaa1f Fix hex number type ambiguity
Fixes cutscenes in Super Mario Sunshine
2024-12-23 21:41:30 -06:00
Isaac Marovitz 04bd1fa1ca Use RGBA8Unorm for R4G4B4A4Unorm
Gets SM64 to boot
2024-12-23 21:41:28 -06:00
Isaac Marovitz c0dcb6c4f2 Dual Source Blend Support in Shader
Fixes Super Mario Galaxy and The Legend of Zelda: Skyward Sword HD
2024-12-23 21:41:26 -06:00
Isaac Marovitz 8bbfa86538 Get Tomb Raider working 2024-12-23 21:41:23 -06:00
Isaac Marovitz a0c67cab44 Remove DummyBufferTextures
Mostly gets VTG on Compute working again
2024-12-23 21:41:19 -06:00
Isaac Marovitz 421ba5448a Properly register TextureBuffer usage + Store Auto ref 2024-12-23 21:41:12 -06:00
Isaac Marovitz 45c99dbfa8 Partial indirect draw support 2024-12-23 21:41:05 -06:00
Gabriel A a84ed6af0d Fixes 2024-12-23 21:40:57 -06:00
Gabriel A 0642df4909 Start building more accurate vertex as compute usage info 2024-12-23 21:40:55 -06:00
Isaac Marovitz d650538138 Bind TextureBuffers 2024-12-23 21:40:53 -06:00
Isaac Marovitz eeadf17f5c Remove ClearSegments for now
Currently unimplemented and issues are arising with building BindingSegments in general.
2024-12-23 21:40:51 -06:00
Isaac Marovitz 7bf0625075 Fix compute generation failure in NieR 2024-12-23 21:40:49 -06:00
Isaac Marovitz 5220ee1dc8 Some debug improvements 2024-12-23 21:40:46 -06:00
Isaac Marovitz cb0a1ce48a Stop complaining about clip distance 2024-12-23 21:40:44 -06:00
Isaac Marovitz ffb9040b3b Shader Gen Fixes
Fixes Luigi’s Mansion 2 HD
2024-12-23 21:40:42 -06:00
Isaac Marovitz 40ea153616 DepthStencil Blits 2024-12-23 21:40:40 -06:00
Isaac Marovitz 4373610790 Multisample Blits
Partially fixes Sonic Colors Ultimate
2024-12-23 21:40:38 -06:00
Isaac Marovitz f5b82cd6dc Fix image bindings 2024-12-23 21:40:36 -06:00
Isaac Marovitz 0064afeb6a FSI (with raster order groups) 2024-12-23 21:40:34 -06:00
Isaac Marovitz 69bee52a89 SwizzleAdd (NOT TESTED) 2024-12-23 21:40:32 -06:00
Isaac Marovitz 159afd5d03 Consolodate barriers 2024-12-23 21:40:30 -06:00
Isaac Marovitz 6229f3bb4c Shader Memory Barriers
Fixes some of the shader generation failures in Sonic Frontiers
2024-12-23 21:40:26 -06:00
Isaac Marovitz d42f0e5945 Image binding support
Kirby still has a problem with NaN 3D Texture
2024-12-23 21:40:22 -06:00
Isaac Marovitz 015f5d00b4 Image shader gen support 2024-12-23 21:39:56 -06:00
Isaac Marovitz d9b322688c Shader cache support 2024-12-23 21:39:54 -06:00
Isaac Marovitz 5e72eb8362 Make dotnet format happy 2024-12-23 21:39:51 -06:00
Isaac Marovitz e0cd935c28 GAL ResourceUsage Changes
TODO: Guest Barrier Defer
2024-12-23 21:39:49 -06:00
Isaac Marovitz 1f133040bd Better vertex buffer management 2024-12-23 21:39:47 -06:00
Isaac Marovitz c399868ddf Fix LOD 2024-12-23 21:39:45 -06:00
Isaac Marovitz fcd2adecc5 Better index buffer management 2024-12-23 21:39:43 -06:00
Isaac Marovitz b468569665 Formatting cleanup 2024-12-23 21:39:36 -06:00
Isaac Marovitz 353a6ca4bb Formatting 2024-12-23 21:39:31 -06:00
Isaac Marovitz 6188872a7c Update binding model description comment 2024-12-23 21:39:16 -06:00
riperiperi 8411f69899 Fix preload cbs optimization (for real) (#34)
* Mostly fix preload cbs. There seems to be some random flickering...

* fix index buffer usage range

* fix missing preflush submit before present
2024-12-23 21:39:13 -06:00
Isaac Marovitz 0bb0ecb599 Fix invariant position not doing its job 2024-12-23 21:39:11 -06:00
riperiperi 8cbd44aecb implement compressed/uncompressed copy, fix other copies, fix int/uint output shaders (#33) 2024-12-23 21:39:09 -06:00
Isaac Marovitz d2f965885a Fix blend state optimisation breaking attachments
Fixes SM3DW
2024-12-23 21:39:07 -06:00
riperiperi 29b6e8ac53 Fix warnings 2024-12-23 21:39:05 -06:00
riperiperi 26da57cccd Maintain identity swizzle view of textures for rendering 2024-12-23 21:39:03 -06:00
riperiperi 82b5f8e681 Fix a bunch of issues with texture copy and flush (#32)
* Fix a bunch of issues with texture copy and flush

* TextureCopy helper class, fix clear bug
2024-12-23 21:38:59 -06:00
Isaac Marovitz 58527e02ee Cleanup + Format 2024-12-23 21:38:54 -06:00
Isaac Marovitz 4d5b128a81 Fix trying to reserve size 0 in staging buffer 2024-12-23 21:38:46 -06:00
Isaac Marovitz 49a814a400 Fix zero buff not being reset 2024-12-23 21:38:42 -06:00
Isaac Marovitz 09546205b5 Dirty Arg Buffers on Program Change 2024-12-23 21:38:39 -06:00
Isaac Marovitz d2a4a9e9a7 Least allocations in the west 2024-12-23 21:38:37 -06:00
Isaac Marovitz d3f273cad1 Don’t use Enum.HasFlag 2024-12-23 21:38:35 -06:00
Isaac Marovitz 60722a1837 Metal: Better Bindings (#29)
* Tell GAL to use Vk model (and break everything)

* ResourceBindingSegments

* Set information on backend caps

* Get ready to break everything

* Refactor EncoderStateManager

* Remove padding from helper shaders

* Fix ref array sizes

* Seperate vert & frag buffers

* Shader-side changes

* Fixes

* Fix some helper shader resource layouts

* Sort by binding id

* Fix helper shader layouts

* Don’t do inline vertex buffer updates

* Check for null storage
2024-12-23 21:38:32 -06:00
Isaac Marovitz 549938e2b1 Update comment for Metal 2024-12-23 21:38:20 -06:00
Isaac Marovitz 144397c3da Don’t do inline vertex buffer updates
Somehow broke zero buff MTLVertexDescriptor, but fixes broken geoemtry so I’m pushing anyway
2024-12-23 21:38:17 -06:00
riperiperi 2fb3c6975e Create command buffers when rented rather than in advance (#31)
* Make it less likely to freeze, but the creation of the command buffer should probably be moved

* Create command buffers as they're rented rather than in advance
2024-12-23 21:38:15 -06:00
riperiperi 879c93cf73 Preload command speedup, Texture/buffer data flush, blit shader fix (#30)
* Move encoder state to be tied to command buffer, so preload and background cbs have their own encoder state

* Texture buffer/data flush, blit shader fix
2024-12-23 21:38:13 -06:00
Isaac Marovitz 7d5b4c5d1d Dont bind images in texture slots 2024-12-23 21:38:11 -06:00
Isaac Marovitz 2860db198c Stop depth/stencil blits from crashing everything 2024-12-23 21:38:04 -06:00
riperiperi 4b53d18bef Fix Geometry/TFB on compute, Buffer Textures, add Window Resizing (#28) 2024-12-23 21:38:00 -06:00
riperiperi bbbc9e529d State and cache optimization (#27)
* WIP pipeline/depth state cache rework

* Fix some issues

* Fix some more default values

* Reduce allocations for state changes

* fix helpershader stuff

* explanation comment

* fix depth bias
2024-12-23 21:37:58 -06:00
Isaac Marovitz c160810bfc Fragment input interpolation qualifiers
Fixes Mario’s shadow in SMO
2024-12-23 21:37:55 -06:00
Isaac Marovitz 4f7b3fa058 CommandBufferBarrier 2024-12-23 21:37:52 -06:00
riperiperi 36de337ac2 Add constrained border colours to samplers (#26) 2024-12-23 21:37:50 -06:00
Isaac Marovitz 3b2beda27f Don’t bind byte format converted index buffers at requested index 2024-12-23 21:37:48 -06:00
Isaac Marovitz de8e03c350 Render target deduplication
not sure if this is working
2024-12-23 21:37:45 -06:00
Isaac Marovitz 0b6bc12a65 Fix CBP not doing its job
Thanks peri (again)
2024-12-23 21:37:43 -06:00
Isaac Marovitz 16bc02ea2a Fix blend descriptors not dirting render pipeline
Thanks peri
2024-12-23 21:37:41 -06:00
Isaac Marovitz 97814b2852 Support non-index quad draws
Fixes Deltarune
2024-12-23 21:37:38 -06:00
Isaac Marovitz a9633981a8 Be better about memory 2024-12-23 21:37:36 -06:00
Isaac Marovitz 1af7dc4b68 Fix stencil clears 2024-12-23 21:37:14 -06:00
Isaac Marovitz d6dcc39131 Enable Alpha Test workaround on Metal 2024-12-23 21:37:10 -06:00
Isaac Marovitz 4f699ef96a Fix Cull FrontAndBack 2024-12-23 21:37:07 -06:00
Isaac Marovitz 30f194e5c0 Warning about host map buffer creation 2024-12-23 21:37:05 -06:00
Isaac Marovitz f1086afcdf Fix fragment point_coord in 2024-12-23 21:37:03 -06:00
Isaac Marovitz dae0f3cded Argument Buffers (#24)
* Stuff

* More arg buffer stuff

* Fixes

* Rebase

* Pass storage buffers to inline functions

* Fix binding

* Fix typo + Fix a couple shaders

* Enforce ids

* Dispose

* Mark used buffers as resident

* Update depth clear shader

* Fix non-contiguous struct defs

* Update ChangeBufferStride

* Fix StorageBuffer assignments

* Fix odyssey crash

* Retain buffer bindings

* Pad Std140

* Set texture data with safe buffers

* Clone buffers

* Always declare vert in

* Stop clears from breaking OpenGL games

* Fix depth clear

* Use invariant position

* Horribly inefficient texture & sampler arg buffers

* Fix missing struct access

* Minimise rebinds as much as possible

* Build arg buffers on staging buffer
2024-12-23 21:37:01 -06:00
Isaac Marovitz a1ab7fe6a2 VoteAllEqual, FindLSB/MSB 2024-12-23 21:36:58 -06:00
Isaac Marovitz fac2cbbbbf Fix vertex “built-ins”
Only declare main func out in main

Fix simd_ballot

Fix thread_index_in_simdgroup outside of compute

Fix atomic operations

instance_index
2024-12-23 21:36:56 -06:00
Isaac Marovitz 9b138a413c Actually clear the right render target 2024-12-23 21:36:54 -06:00
Isaac Marovitz 58eefa8bdf Big GetData()
Co-authored-by: riperiperi <rhy3756547@hotmail.com>
2024-12-23 21:36:52 -06:00
Isaac Marovitz 0ebc8bd1b8 Fix Animal Crossing Crash 2024-12-23 21:36:50 -06:00
Isaac Marovitz becf828d0a Instruction.Barrier
Whoops

Fix inline functions in compute stage

Fix regression

Declare SharedMemories + Only Declare Memories on Main Func

Lowecase struct

Avoid magic strings

Make function signatures readable

Change how unsized arrays are indexed

Use string builder

Fix shuffle instructions

Cleanup NumberFormater

Bunch of Subgroup I/O Vars

Will probably need further refinement

Fix point_coord type

Fix support buffer declaration

Fix point_coord
2024-12-23 21:36:48 -06:00
Isaac Marovitz d0e4adac36 PreloadCbs + FlushCommandsIfWeightExceeding 2024-12-23 21:36:46 -06:00
Isaac Marovitz 197184657f Cleanup Pipeline
Housekeeping

More housekeeping
2024-12-23 21:36:44 -06:00
Isaac Marovitz 74083083cd PersistentFlushBuffer + BackgroundResources 2024-12-23 21:36:42 -06:00
Isaac Marovitz 175cded85d Match S8UintD24Unorm to Depth24UnormStencil8
Kind of works for es2gears
2024-12-23 21:36:40 -06:00
Isaac Marovitz c911db8309 Fix FEZ not showing anything
Does not fix the underlying shortcomings of the cache system
2024-12-23 21:35:50 -06:00
Isaac Marovitz 3451fbbbad Clear cached converted buffers on signaled write 2024-12-23 21:35:47 -06:00
Isaac Marovitz 98ae46ba70 FIx regression 2024-12-23 21:35:45 -06:00
Isaac Marovitz bf4232a35b Helper shader cleanup 2024-12-23 21:35:43 -06:00
Isaac Marovitz c3e39a9c91 Use buffer manager for color blit 2024-12-23 21:35:41 -06:00
Isaac Marovitz b8779c6e09 Buffer Conversions (#23)
* Why is this not working

* Revert helper shader changes for now

* Byte Index Buffer Restride
2024-12-23 21:35:38 -06:00
riperiperi 20cf1a08c1 don't recreate render pipeline unless we're about to draw, pass view depth properly (#22) 2024-12-23 21:35:36 -06:00
Isaac Marovitz dda746c0fb Metal: Buffers Take 2 (#21)
* Basic BufferManager

* Start Scoped Command Buffers

* Fences stuff

* Remember to cleanup sync manager

* Auto, Command Buffer Dependants

* Cleanup

* Cleanup + Fix Texture->Buffer Copies

* Slow buffer upload

* Cleanup + Rework TextureBuffer

* Don’t get unsafe

* Cleanup

* Goddamn it

* Staging Buffer + Interrupt Action + Flush
2024-12-23 21:35:33 -06:00
Isaac Marovitz 585bdc2b54 Log failed format conversions 2024-12-23 21:35:31 -06:00
Isaac Marovitz e49702965f Print shader code involved in failed linking 2024-12-23 21:35:21 -06:00
Isaac Marovitz 8b5392ce9b Don’t use DidModifyRange 2024-12-23 21:35:17 -06:00
Isaac Marovitz 9e61294671 Fix sample compare 2024-12-23 21:35:15 -06:00
Isaac Marovitz 5423ad9ae1 Depth Bias 2024-12-23 21:35:13 -06:00
Isaac Marovitz 65bddcd475 Map R5G5B5A1Unorm 2024-12-23 21:35:11 -06:00
Samuliak 36ac0414e2 override Equals for render pipeline hash 2024-12-23 21:35:09 -06:00
Isaac Marovitz 51b4ffeb6c Disable scaled vertex formats 2024-12-23 21:35:07 -06:00
Isaac Marovitz 39bfd55958 Disable Vector Indexing Bug Workaround 2024-12-23 21:35:04 -06:00
Isaac Marovitz e615d7d849 Fix modulo operator
Support sample offsets

Include FragmentIn as additional arg

Always declare frag output struct

SubgroupLaneId
2024-12-23 21:35:02 -06:00
Isaac Marovitz c883ebb645 Workaround for Wonder 2024-12-23 21:35:00 -06:00
Isaac Marovitz 24ab7788d8 Fix 3D -> 3D Texture Copies 2024-12-23 21:34:57 -06:00
Isaac Marovitz 9ab2cd94c1 Fix Clear Viewport 2024-12-23 21:34:55 -06:00
Isaac Marovitz 4ee4e09358 Fix sample-less reads with lod 2024-12-23 21:34:52 -06:00
Isaac Marovitz a07975afec Fix Pack and UnpackHalf2x16 2024-12-23 21:34:50 -06:00
Isaac Marovitz 746c897206 Handle Array Format SetData 2024-12-23 21:34:48 -06:00
Isaac Marovitz fe4fa6f4db Cleanup 2024-12-23 21:33:31 -06:00
Isaac Marovitz db24e0f6fe Implement IoVariable.FrontFacing 2024-12-23 21:33:24 -06:00
Isaac Marovitz e9aee16a27 Fix LOD sample typo 2024-12-23 21:33:21 -06:00
Isaac Marovitz 02f1e289e2 Rebase Changes 2024-12-23 21:33:19 -06:00
Isaac Marovitz 9ebf82f184 More cleanup 2024-12-23 21:33:17 -06:00
Isaac Marovitz 49e83335d1 Cleanup + Format 2024-12-23 21:33:14 -06:00
Isaac Marovitz f00cf8704f Metal: Compute Shaders (#19)
* check for too bix texture bindings

* implement lod query

* print shader stage name

* always have fragment input

* resolve merge conflicts

* fix: lod query

* fix: casting texture coords

* support non-array memories

* use structure types for buffers

* implement compute pipeline cache

* compute dispatch

* improve error message

* rebind compute state

* bind compute textures

* pass local size as an argument to dispatch

* implement texture buffers

* hack: change vertex index to vertex id

* pass support buffer as an argument to every function

* return at the end of function

* fix: certain missing compute bindings

* implement texture base

* improve texture binding system

* remove useless exception

* move texture handle to texture base

* fix: segfault when using disposed textures

---------

Co-authored-by: Samuliak <samuliak77@gmail.com>
Co-authored-by: SamoZ256 <96914946+SamoZ256@users.noreply.github.com>
2024-12-23 21:33:12 -06:00
Isaac Marovitz 65da0569a3 Handle stride 0 on regular buffers 2024-12-23 21:33:09 -06:00
Isaac Marovitz d811532a9f Buffer Descriptor Step Functions 2024-12-23 21:33:07 -06:00
Isaac Marovitz a42c66e6d5 Sample LOD Level 2024-12-23 21:33:01 -06:00
Isaac Marovitz 8be6b671b8 Fix FragmentOutputColor Type 2024-12-23 21:32:59 -06:00
Isaac Marovitz 2e99df371f Stencil Ref Value 2024-12-23 21:32:56 -06:00
Isaac Marovitz ac8af32744 Stencil Fixes 2024-12-23 21:32:54 -06:00
Isaac Marovitz a58568d036 RenderTargetColorMasks 2024-12-23 21:32:52 -06:00
Isaac Marovitz 7ed45d12db Make dotnet format happy 2024-12-23 21:32:50 -06:00
SamoZ256 505f830556 Zero vertex buffer (#17)
* cast src size to float

* implement zero buffers
2024-12-23 21:32:47 -06:00
Isaac Marovitz 43ad627d4f Implement Texture CopyTo 2024-12-23 21:32:45 -06:00
Isaac Marovitz c5cca8a1a3 Cleanup present 2024-12-23 21:32:43 -06:00
Isaac Marovitz f7941a0a8b Metal: Advanced Present (#6)
* Initial DrawTexture support & Advanced Present

* TODO: Get Scissors Working

* Chnage scissor state management

* Rebase problems…

* Rebase fixes again

* Update DrawTexture + Fix Topology

* Fix flipping

* Add clear action support

* Cleanup
2024-12-23 21:32:40 -06:00
SamoZ256 6cc4d46e8c Clone the state & flip viewport vertically (#16)
* implement texture get data

* reset all state before blit & clone state

* format

* support blit regions

* implement source region for blit

* replace bottom with top

* account for 0 size

* support image flipping

* revert presentation fixes & y flip

* revert

* flip viewport vertically

* switch face winding

* comment

* use SetBytes for texture clear

* implement missing compute builtins

* change storage and texture buffer alignment

* correct compute builtins

* don't use nullable for textures and samplers

* remove incorrect texture get data implementation

* Cleanup IntPtrs

---------

Co-authored-by: Isaac Marovitz <isaacryu@icloud.com>
2024-12-23 21:32:34 -06:00
SamoZ256 18b852e05d Fix Scott Pilgrim (#15)
* check for null vertex functions

* format

* Format

---------

Co-authored-by: Isaac Marovitz <isaacryu@icloud.com>
2024-12-23 21:32:02 -06:00
Isaac Marovitz 41e6a04a23 Suppress GC Finalize on StateCache 2024-12-23 21:31:59 -06:00
Isaac Marovitz 881ab59177 Use Stack instead of List 2024-12-23 21:31:57 -06:00
Isaac Marovitz 327c1576f7 Whitespace formatting 2024-12-23 21:31:54 -06:00
Samuliak 60ece6d9a1 dispose all temporary buffers 2024-12-23 21:31:52 -06:00
Samuliak 58b42a1143 dispose temporary metal buffer 2024-12-23 21:31:47 -06:00
Samuliak 3be47ae4a9 dispose drawable texture view 2024-12-23 21:31:41 -06:00
Samuliak 6ab989ac54 implement texture get data 2024-12-23 21:31:36 -06:00
Samuliak 9f01cce95f fix: don't dispose stencil state before using 2024-12-23 21:31:30 -06:00
Samuliak 0abbbdc277 allow null depth stencil render targets 2024-12-23 21:31:28 -06:00
Samuliak eb7ec713ec reset certain state before doing blit or clear 2024-12-23 21:31:26 -06:00
Samuliak d5437f3dbf reset viewport before blit 2024-12-23 21:31:24 -06:00
Samuliak 1c4e527ac2 dispose encoder state manager 2024-12-23 21:31:01 -06:00
Samuliak af341f88df dispose all objects in encoder state manager 2024-12-23 21:30:58 -06:00
Samuliak 1ff81393be dispose caches 2024-12-23 21:30:55 -06:00
Samuliak 2cb5265c8e warn about barriers 2024-12-23 21:30:53 -06:00
Samuliak 78553f31d9 do memory barriers 2024-12-23 21:30:50 -06:00
Samuliak 60084f826e remove useless parameters 2024-12-23 21:30:48 -06:00
Samuliak 280efb2ed6 set the inline state after restoring state 2024-12-23 21:30:46 -06:00
Samuliak 14607f4471 make states private 2024-12-23 21:30:41 -06:00
Samuliak fd4fe01348 fix: incorrect merge stuff 2024-12-23 21:30:39 -06:00
Samuliak 8f91b556af don't interrupt render pass before color clear 2024-12-23 21:30:29 -06:00
Samuliak 305a703d4a implement save and restore state system 2024-12-23 21:30:22 -06:00
Samuliak a2c0c11380 revert deferred clears 2024-12-23 21:30:02 -06:00
Samuliak 016df3b050 prepare for deferred clears 2024-12-23 21:29:58 -06:00
Samuliak 084b75a398 resolve merge conflicts 2024-12-23 21:29:56 -06:00
Isaac Marovitz 91aed4d0dd Rebase 2024-12-23 21:29:54 -06:00
Isaac Marovitz bea46ff9ce Cleanup + Format 2024-12-23 21:29:50 -06:00
Isaac Marovitz 58fb8564a8 Start Proper Dispose 2024-12-23 21:29:47 -06:00
Samuliak 94e077ca27 do texture barrier tiled 2024-12-23 21:29:44 -06:00
Samuliak a10b0230c3 do texture barrier 2024-12-23 21:29:42 -06:00
Samuliak c7dc9ba34e implement depth stencil cache 2024-12-23 21:29:40 -06:00
Isaac Marovitz ad4db6b242 Fix typo in SamplerType.TextureBuffer 2024-12-23 21:29:37 -06:00
Isaac Marovitz 11c596a18a Fix StoreActions & Don’t Clamp Scissor for Now 2024-12-23 21:29:35 -06:00
Isaac Marovitz 7f8d54d6dc Depth Clear 2024-12-23 21:29:33 -06:00
Isaac Marovitz 90e3899c23 Shitty Clears + Inline Buffer Improvements? 2024-12-23 21:29:24 -06:00
Isaac Marovitz 381f4ec091 FragmentOutputDepth Fixes 2024-12-23 21:29:20 -06:00
Isaac Marovitz b76f9105c8 Depth Sampler Fixes 2024-12-23 21:29:09 -06:00
Isaac Marovitz 486fd78eba Revert position changes 2024-12-23 21:29:06 -06:00
Isaac Marovitz 38385bad30 Nvm it should be in.position 2024-12-23 21:29:04 -06:00
Isaac Marovitz 27ece39dbe More shader fixes 2024-12-23 21:29:02 -06:00
Samuliak 7a6c7196c8 fix: incorrect layer count of texture view 2024-12-23 21:28:59 -06:00
Samuliak 765ca8e6c0 don't use mask on size query 2024-12-23 21:28:57 -06:00
Samuliak d5b98d6187 declare local memory 2024-12-23 21:28:51 -06:00
Samuliak 913f25b2a0 support multiple render targets & fix: incorrect texture name 2024-12-23 21:28:41 -06:00
Samuliak 5d0ae23a0b put render pipeline cache into a separate file 2024-12-23 21:28:38 -06:00
Samuliak dd5fb8bed9 implement pipeline cache 2024-12-23 21:28:36 -06:00
Isaac Marovitz 2316f30de1 Use return value of BeginRenderPass 2024-12-23 21:28:33 -06:00
Isaac Marovitz 96eea9de23 Cleanup 2024-12-23 21:28:31 -06:00
Samuliak 9c5917912b remove outdated comment 2024-12-23 21:28:29 -06:00
Isaac Marovitz efe575c9b2 Fix table 2024-12-23 21:28:27 -06:00
Isaac Marovitz ba4d6815ea Dont hardcode Vertex Format 2024-12-23 21:28:20 -06:00
Samuliak 9b99f55c4f style 2024-12-23 21:28:17 -06:00
Samuliak 5a6169b19d bring back inline updates for some state 2024-12-23 21:28:15 -06:00
Samuliak f30aa98ce5 fix: don't rebind pipeline unless dirty 2024-12-23 21:28:12 -06:00
Samuliak 149141594f don't bind null vertex buffers 2024-12-23 21:28:09 -06:00
Samuliak b5f15de64f mark state as dirty 2024-12-23 21:28:07 -06:00
Samuliak bc9a26bbf2 add todo notice 2024-12-23 21:28:04 -06:00
Samuliak f3d314104f don't end render pass when not neccessary 2024-12-23 21:28:01 -06:00
Isaac Marovitz 6324569dd2 Remove rebase garbage 2024-12-23 21:27:30 -06:00
Isaac Marovitz 2c474050f8 Be smart and use a bitmask not a list 2024-12-23 21:27:18 -06:00
Isaac Marovitz 46cc993f9a Cleanup 2024-12-23 21:27:15 -06:00
Isaac Marovitz c51c8bdae6 Fix Vertex Attributes in Wonder & Kirby 2024-12-23 21:27:13 -06:00
Isaac Marovitz 4f356b4117 Implement SetDepthClamp 2024-12-23 21:27:10 -06:00
Isaac Marovitz 15051d6e56 Implement SetBlendState 2024-12-23 21:27:08 -06:00
Isaac Marovitz 2587e1ff22 Be consistent with things that lack support 2024-12-23 21:27:06 -06:00
Isaac Marovitz 0d5292ff8c Ignore SetDepthMode 2024-12-23 21:27:04 -06:00
Isaac Marovitz 401ad1f983 Make Texture Volatile on dispose 2024-12-23 21:26:57 -06:00
Isaac Marovitz 3c1ef06151 Format 2024-12-23 21:26:49 -06:00
Isaac Marovitz 95af212cfc Fix present 2024-12-23 21:26:46 -06:00
Isaac Marovitz 4190abbbf5 Fix Depth/Stencil attachments 2024-12-23 21:25:27 -06:00
Isaac Marovitz c7b6e4cf80 Break everything :D 2024-12-23 21:25:24 -06:00
Isaac Marovitz 96d884a15b Clamp ScissorRect 2024-12-23 21:25:21 -06:00
Isaac Marovitz f79ebd1141 Set DepthAttachmentPixelFormat 2024-12-23 21:25:19 -06:00
Isaac Marovitz 7f65ec0b8c Set Depth Attachment Texture 2024-12-23 21:25:17 -06:00
Isaac Marovitz 824321c88a Clamp Viewport ZNear & ZFar 2024-12-23 21:25:08 -06:00
Samuliak 91d1bb6c08 format 2024-12-23 21:24:50 -06:00
Samuliak 22d3fa068d use 0 instead of undef 2024-12-23 21:24:45 -06:00
Samuliak d08218a809 fix: pass array index as an additional argument to sample 2024-12-23 21:24:42 -06:00
Samuliak b7414c1e4d don't declare samplers for separate textures 2024-12-23 21:24:40 -06:00
Samuliak a66ab905a9 don't hardcode texture type 2024-12-23 21:24:37 -06:00
Samuliak 2bef29b200 offset storage buffer bindings by 15 2024-12-23 21:24:35 -06:00
Samuliak 72eb47513c fix: incorrect abs instruction 2024-12-23 21:24:32 -06:00
Samuliak 6095f14646 add: vertex and instance id arguments 2024-12-23 21:24:29 -06:00
Samuliak c3a9a0d625 determine type of buffer by its field types 2024-12-23 21:24:03 -06:00
Isaac Marovitz 18e1569941 Rebase + Format 2024-12-23 21:23:59 -06:00
Samuliak 362dc6eaea use unknown texture usage 2024-12-23 21:23:47 -06:00
Samuliak d66c39b64b don't hardcode render pipeline attachments 2024-12-23 21:23:42 -06:00
Samuliak de23abcf90 create GetSwizzle helper function 2024-12-23 21:23:32 -06:00
Samuliak b2a0ca0e2b add: textures and samplers as shader arguments & fix: issue with casting 2024-12-23 21:23:28 -06:00
Samuliak e3364b0fcc support fragment coord as an input to a shader 2024-12-23 21:23:24 -06:00
Samuliak 8a0dd491b9 support texture views 2024-12-23 21:23:20 -06:00
Isaac Marovitz ba05ed9552 Format 2024-12-23 21:23:14 -06:00
Isaac Marovitz b85721b738 Rebase + GAL Changes 2024-12-23 21:23:06 -06:00
Isaac Marovitz 9d7164a329 Remove TODOs 2024-12-23 21:21:51 -06:00
Isaac Marovitz 2f70337dca Fix Scissor/Viewport state & Validation Error 2024-12-23 21:21:47 -06:00
Isaac Marovitz 60c99e32b0 Require Argument Buffers Tier 2 2024-12-23 21:21:42 -06:00
Isaac Marovitz ebd2d82ff3 Buffer bindings in shader…
Will need to be reworked
2024-12-23 21:21:36 -06:00
Isaac Marovitz 44bd12104b Bind Uniform & Storage Buffers 2024-12-23 21:21:31 -06:00
Evan Husted 0df70db73c remnant 2024-12-23 21:21:14 -06:00
Isaac Marovitz 64e9dcee3d Fix buffer access syntax 2024-12-23 21:19:39 -06:00
Isaac Marovitz e353e3d3fc Dispose pipeline before window 2024-12-23 21:19:33 -06:00
Isaac Marovitz 6a67822b3b Set scissors & viewports 2024-12-23 21:19:26 -06:00
Isaac Marovitz 65b7af6308 Format 2024-12-23 21:19:22 -06:00
Isaac Marovitz 36fe41bffd Format 2024-12-23 21:19:19 -06:00
Isaac Marovitz e758e531c5 Fix some crashes 2024-12-23 21:19:16 -06:00
Isaac Marovitz efa9d56a56 Fix Cubemap & Array Texture Creation 2024-12-23 21:19:08 -06:00
Isaac Marovitz b95e1d288b Properly check for 3D 2024-12-23 21:17:32 -06:00
Isaac Marovitz 48aba086e1 Fix swizzle for certain formats 2024-12-23 21:17:28 -06:00
Isaac Marovitz 44f4d41cf8 Blit at the end of the render 2024-12-23 21:17:25 -06:00
Isaac Marovitz b4f468c653 Load attachments 2024-12-23 21:17:21 -06:00
Isaac Marovitz 3117aeca7f Cleanup Shader I/O 2024-12-23 21:17:17 -06:00
Isaac Marovitz 987a42ce30 Fix fragment shader bindings 2024-12-23 21:17:09 -06:00
Isaac Marovitz fc7f09624c Fix VertexBuffers
Naive non-managed approach
2024-12-23 21:16:57 -06:00
Isaac Marovitz e2445990a5 Fix some shader gen problems… 2024-12-23 21:16:52 -06:00
Isaac Marovitz dc4305f1cf Formatting 2024-12-23 21:16:48 -06:00
Isaac Marovitz b7a0aefa80 Make TypeConversion failure an error 2024-12-23 21:16:42 -06:00
Isaac Marovitz 7a99143a8a Fix MSL Reinterpret Casts 2024-12-23 21:16:39 -06:00
Isaac Marovitz 89d1caf30f Dont set Vertex Attributes for now 2024-12-23 21:16:35 -06:00
Isaac Marovitz de7b3e7dac Remove capture code 2024-12-23 21:16:31 -06:00
Isaac Marovitz 94e15aa662 Bind Textures & Samplers 2024-12-23 21:16:27 -06:00
Isaac Marovitz b157a8e549 Revise ISampler 2024-12-23 21:16:20 -06:00
Isaac Marovitz 6685041545 Try again 2024-12-23 21:16:15 -06:00
Isaac Marovitz b8630b5c45 Resolve warning 2024-12-23 21:16:12 -06:00
Isaac Marovitz c0da3d68ca Formatting 2024-12-23 21:16:07 -06:00
Isaac Marovitz 76bafe75f4 FIx build 2024-12-23 21:15:56 -06:00
Isaac Marovitz 3c562d8906 Fix some rebase errors 2024-12-23 21:15:36 -06:00
Isaac Marovitz df0dc4454b End Pass on Dispose 2024-12-23 21:15:33 -06:00
Isaac Marovitz 26ea1e6d37 Don’t change Render State if Vertex Function is Invalid 2024-12-23 21:15:26 -06:00
Isaac Marovitz e8d0212ec6 “Report” Driver 2024-12-23 21:15:18 -06:00
Isaac Marovitz e7197877a2 Adjust function signature 2024-12-23 21:15:14 -06:00
Isaac Marovitz dff9046f55 Get it building again 2024-12-23 21:15:07 -06:00
Isaac Marovitz cb36036faa Render Targets 2024-12-23 21:15:01 -06:00
Isaac Marovitz c4cf4895d8 format 2024-12-23 21:14:55 -06:00
Isaac Marovitz b6116da940 Formatting 2024-12-23 21:14:50 -06:00
Isaac Marovitz fbcd9994c8 smh 2024-12-23 21:14:18 -06:00
Isaac Marovitz 5d90932277 Dont specify [[stage_in]] on fragment 2024-12-23 21:14:06 -06:00
Isaac Marovitz 037157135e If one shader fails, whole program fails 2024-12-23 21:12:41 -06:00
Isaac Marovitz d45c7711ba Fix fragment shaders (and fuck everything up) 2024-12-23 21:09:35 -06:00
Isaac Marovitz b3629e3a8b Vertex buffer data 2024-12-23 21:09:25 -06:00
Isaac Marovitz c216028d00 Dont be stupid 2024-12-23 21:09:18 -06:00
Isaac Marovitz 02fbcfbadb Dont set 0 attributes 2024-12-23 21:09:07 -06:00
Isaac Marovitz a5c1b6a255 Reset Descriptor instead of making a new object 2024-12-23 21:09:00 -06:00
Isaac Marovitz be1d099879 Set Vertex Descriptor properly 2024-12-23 21:08:54 -06:00
Isaac Marovitz 3529fcd592 Start vertex descriptor work 2024-12-23 21:08:44 -06:00
Isaac Marovitz 3398977c97 Implement CreateProgram 2024-12-23 21:08:35 -06:00
Isaac Marovitz fe62c794b9 Fix fragment output color 2024-12-23 21:08:21 -06:00
Isaac Marovitz 2e3509f8e8 Set TargetLanguage for Metal to MSL 2024-12-23 21:08:06 -06:00
Isaac Marovitz d65858be25 Fix IoMap variable names
Output struct

Lazy Vertex IO

Output fixes

Fix output struct definition

MSL Binding Model description

Might need tweaks/adjustments

Cleanup

Typo + Format
2024-12-23 21:07:58 -06:00
Isaac Marovitz 2a28950739 Fix ETC2 PTA formats
Format
2024-12-23 21:07:52 -06:00
Isaac Marovitz 4587905cd8 Partial TextureQuerySamples 2024-12-23 21:07:07 -06:00
Isaac Marovitz 9cc56a3bca Fix instructions 2024-12-23 21:06:58 -06:00
Isaac Marovitz b06afd1a1f LDR ASTC 2024-12-23 21:06:52 -06:00
Isaac Marovitz 7182ac7233 Get build working again (values likely wrong) 2024-12-23 21:06:45 -06:00
Isaac Marovitz 398b6cb60e dotnet format 2024-12-23 21:06:31 -06:00
Isaac Marovitz c5522e3694 Back to where we were
First special instruction

Start Load/Store implementation

Start TextureSample

Sample progress

I/O Load/Store Progress

Rest of load/store

TODO: Currently, the generator still assumes the GLSL style of I/O attributres. On MSL, the vertex function should output a struct which contains a float4 with the required position attribute.

TextureSize and VectorExtract

Fix UserDefined IO Vars

Fix stage input struct names
2024-12-23 21:05:34 -06:00
Isaac Marovitz a3da70edc2 Boot TOTK 2024-12-23 21:05:28 -06:00
Evan Husted 14999a1d51 Merge branch 'master' into new-metal 2024-12-23 21:04:54 -06:00
Isaac Marovitz 94e699eeba Boot Sonic Mania 2024-12-23 21:01:19 -06:00
Isaac Marovitz b1785c0b14 Update for new Shader IR format 2024-12-23 21:01:10 -06:00
Isaac Marovitz 84c90f8895 Update src/Ryujinx.Graphics.Metal/Pipeline.cs
Co-authored-by: gdkchan <gab.dark.100@gmail.com>
2024-12-23 21:00:54 -06:00
Isaac Marovitz dc4d3078ef Vertex Input Attributes 2024-12-23 21:00:45 -06:00
Isaac Marovitz 4b5c3d7fc6 More Shader Gen Stuff
Mostly copied from GLSL since in terms of syntax within blocks they’re pretty similar. Likely the result will need tweaking…

Isn’t that conveniant?

“Do the simd_shuffle”

atomics

Remaining instructions

Remove removed special instructions

Getting somewhere…
2024-12-23 21:00:23 -06:00
Isaac Marovitz 5a802a550b Fix Metal Validation Error 2024-12-23 21:00:16 -06:00
Isaac Marovitz 7c31a411df SDL2 Headless Metal Backend support 2024-12-23 20:59:56 -06:00
Isaac Marovitz 8b9d6ffc94 Easier capture stuff 2024-12-23 20:58:47 -06:00
Isaac Marovitz 4cde7a4125 Define MaxFramesPerCapture 2024-12-23 20:58:39 -06:00
Isaac Marovitz c1ef270b9d Cleanup encoder getting + Fix capture overflow 2024-12-23 20:58:32 -06:00
Evan Husted 2812f01643 merge leftovers 2024-12-23 20:58:17 -06:00
Isaac Marovitz 7441d94f10 Formatting 2024-12-23 20:57:31 -06:00
Isaac Marovitz a8b4e643d0 Start of MSL instructions
Remaining functions
2024-12-23 20:55:40 -06:00
Isaac Marovitz a7908c187d Warn when generating unsupported shader 2024-12-23 20:55:27 -06:00
Isaac Marovitz 25dba8da7c Pass sampler to Blit shader 2024-12-23 20:55:21 -06:00
Isaac Marovitz 0edec0d3ff Shader comments 2024-12-23 20:55:12 -06:00
Isaac Marovitz fb8749ce4e HelperShaders class 2024-12-23 20:53:42 -06:00
Isaac Marovitz d36c285b79 Undertale boots 2024-12-23 20:53:33 -06:00
Isaac Marovitz 179482e9cb Check if packed depth is supported 2024-12-23 20:53:19 -06:00
Isaac Marovitz 671aff68a6 Fix RGB Seizure 2024-12-23 20:53:06 -06:00
Isaac Marovitz 8bf33b3098 Barry is here mashallah 2024-12-23 20:52:40 -06:00
Isaac Marovitz 6a115becef Seizure my beloved is working 2024-12-23 20:52:32 -06:00
Isaac Marovitz ed445e001a SetData 2024-12-23 20:52:22 -06:00
Isaac Marovitz 93f31bd08a Look ma no crash 2024-12-23 20:44:22 -06:00
Isaac Marovitz a60ecea4c3 Whitespace 2024-12-23 20:44:19 -06:00
Isaac Marovitz ff0362063a TODO 2024-12-23 20:44:13 -06:00
Isaac Marovitz e0ea464c40 BeginComputePass 2024-12-23 20:44:01 -06:00
Isaac Marovitz 05002ae234 SetDepthTest 2024-12-23 20:43:52 -06:00
Isaac Marovitz dc60b76748 SetStencilTest 2024-12-23 20:43:43 -06:00
Isaac Marovitz cc3c7901b6 Forgot depth 2024-12-23 20:43:37 -06:00
Isaac Marovitz 15ad03bc04 Texture usage 2024-12-23 20:43:32 -06:00
Isaac Marovitz 1d01fbf6b1 CopyBuffer to Buffer 2024-12-23 20:43:10 -06:00
Isaac Marovitz 1e835aa56f CopyTo Buffer 2024-12-23 20:42:50 -06:00
Evan Husted 93e5ff0137 up to date with 08126b26b1 2024-12-23 20:41:07 -06:00
Evan Husted 6d513cad1e merging leftovers 2024-12-23 20:36:29 -06:00
Evan Husted cbad43b003 some initial metal commits cherry-picked 2024-12-23 20:35:49 -06:00
210 changed files with 1893 additions and 3504 deletions
+23
View File
@@ -64,9 +64,14 @@ jobs:
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 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
if: github.event_name == 'pull_request' && matrix.platform.os != 'macos-13' if: github.event_name == 'pull_request' && matrix.platform.os != 'macos-13'
- name: Publish Ryujinx.Headless.SDL2
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
if: github.event_name == 'pull_request' && matrix.platform.os != 'macos-13'
- name: Set executable bit - name: Set executable bit
run: | run: |
chmod +x ./publish/Ryujinx ./publish/Ryujinx.sh chmod +x ./publish/Ryujinx ./publish/Ryujinx.sh
chmod +x ./publish_sdl2_headless/Ryujinx.Headless.SDL2 ./publish_sdl2_headless/Ryujinx.sh
if: github.event_name == 'pull_request' && matrix.platform.os == 'ubuntu-latest' if: github.event_name == 'pull_request' && matrix.platform.os == 'ubuntu-latest'
- name: Build AppImage - name: Build AppImage
@@ -114,6 +119,13 @@ jobs:
name: ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.platform.zip_os_name }}-AppImage name: ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.platform.zip_os_name }}-AppImage
path: publish_appimage path: publish_appimage
- name: Upload Ryujinx.Headless.SDL2 artifact
uses: actions/upload-artifact@v4
with:
name: nogui-ryujinx-${{ 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.platform.os != 'macos-13'
build_macos: build_macos:
name: macOS Universal (${{ matrix.configuration }}) name: macOS Universal (${{ matrix.configuration }})
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -159,9 +171,20 @@ jobs:
run: | run: |
./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" ./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 artifact - name: Upload Ryujinx artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-macos_universal name: ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-macos_universal
path: "publish/*.tar.gz" path: "publish/*.tar.gz"
if: github.event_name == 'pull_request' if: github.event_name == 'pull_request'
- name: Upload Ryujinx.Headless.SDL2 artifact
uses: actions/upload-artifact@v4
with:
name: nogui-ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-macos_universal
path: "publish_headless/*.tar.gz"
if: github.event_name == 'pull_request'
+30 -14
View File
@@ -21,9 +21,9 @@ env:
DOTNET_CLI_TELEMETRY_OPTOUT: 1 DOTNET_CLI_TELEMETRY_OPTOUT: 1
RYUJINX_BASE_VERSION: "1.2" RYUJINX_BASE_VERSION: "1.2"
RYUJINX_TARGET_RELEASE_CHANNEL_NAME: "canary" RYUJINX_TARGET_RELEASE_CHANNEL_NAME: "canary"
RYUJINX_TARGET_RELEASE_CHANNEL_OWNER: "Ryubing" RYUJINX_TARGET_RELEASE_CHANNEL_OWNER: "GreemDev"
RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO: "Ryujinx" RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO: "Ryujinx"
RYUJINX_TARGET_RELEASE_CHANNEL_REPO: "Canary-Releases" RYUJINX_TARGET_RELEASE_CHANNEL_REPO: "Ryujinx-Canary"
RELEASE: 1 RELEASE: 1
jobs: jobs:
@@ -43,8 +43,8 @@ jobs:
with: with:
script: | script: |
github.rest.git.createRef({ github.rest.git.createRef({
owner: "${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}", owner: context.repo.owner,
repo: "${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO }}", repo: context.repo.repo,
ref: 'refs/tags/Canary-${{ steps.version_info.outputs.build_version }}', ref: 'refs/tags/Canary-${{ steps.version_info.outputs.build_version }}',
sha: context.sha sha: context.sha
}) })
@@ -64,7 +64,7 @@ jobs:
| Windows 64-bit | [Canary Windows Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-win_x64.zip) | | Windows 64-bit | [Canary Windows Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-win_x64.zip) |
| Linux 64-bit | [Canary Linux Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz) | | Linux 64-bit | [Canary Linux Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz) |
| Linux ARM 64-bit | [Canary Linux ARM Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz) | | Linux ARM 64-bit | [Canary Linux ARM Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz) |
| macOS | [Canary macOS Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz) | | macOS | [Canary macOS artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz) |
**Full Changelog**: https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO }}/compare/Canary-${{ steps.version_info.outputs.prev_build_version }}...Canary-${{ steps.version_info.outputs.build_version }} **Full Changelog**: https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO }}/compare/Canary-${{ steps.version_info.outputs.prev_build_version }}...Canary-${{ steps.version_info.outputs.build_version }}
omitBodyDuringUpdate: true omitBodyDuringUpdate: true
@@ -116,6 +116,7 @@ jobs:
- name: Publish - name: Publish
run: | run: |
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 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
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
- name: Packing Windows builds - name: Packing Windows builds
if: matrix.platform.os == 'windows-latest' if: matrix.platform.os == 'windows-latest'
@@ -124,6 +125,11 @@ jobs:
rm publish/libarmeilleure-jitsupport.dylib rm publish/libarmeilleure-jitsupport.dylib
7z a ../release_output/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip publish 7z a ../release_output/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip publish
popd popd
pushd publish_sdl2_headless
rm publish/libarmeilleure-jitsupport.dylib
7z a ../release_output/nogui-ryujinx-canary-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip publish
popd
shell: bash shell: bash
- name: Packing Linux builds - name: Packing Linux builds
@@ -134,6 +140,12 @@ jobs:
chmod +x publish/Ryujinx.sh publish/Ryujinx chmod +x publish/Ryujinx.sh publish/Ryujinx
tar -czvf ../release_output/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz publish tar -czvf ../release_output/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz publish
popd popd
pushd publish_sdl2_headless
rm publish/libarmeilleure-jitsupport.dylib
chmod +x publish/Ryujinx.sh publish/Ryujinx.Headless.SDL2
tar -czvf ../release_output/nogui-ryujinx-canary-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz publish
popd
shell: bash shell: bash
#- name: Build AppImage (Linux) #- name: Build AppImage (Linux)
@@ -179,21 +191,21 @@ jobs:
with: with:
name: ${{ steps.version_info.outputs.build_version }} name: ${{ steps.version_info.outputs.build_version }}
artifacts: "release_output/*.tar.gz,release_output/*.zip" artifacts: "release_output/*.tar.gz,release_output/*.zip"
#artifacts: "release_output/*.tar.gz,release_output/*.zip,release_output/*AppImage*" #artifacts: "release_output/*.tar.gz,release_output/*.zip/*AppImage*"
tag: ${{ steps.version_info.outputs.build_version }} tag: ${{ steps.version_info.outputs.build_version }}
body: | body: |
# Canary builds: # Canary builds:
These builds are experimental and may sometimes not work, use [regular builds](https://github.com/${{ github.repository }}/releases/latest) instead if that sounds like something you don't want to deal with. These builds are experimental and may sometimes not work, use [regular builds](https://github.com/GreemDev/Ryujinx/releases/latest) instead if that sounds like something you don't want to deal with.
| Platform | Artifact | | Platform | Artifact |
|--|--| |--|--|
| Windows 64-bit | [Canary Windows Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-win_x64.zip) | | Windows 64-bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-win_x64.zip |
| Linux 64-bit | [Canary Linux Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz) | | Linux 64-bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz |
| Linux ARM 64-bit | [Canary Linux ARM Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz) | | Linux ARM 64-bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz |
| macOS | [Canary macOS Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz) | | macOS | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz |
**Full Changelog**: https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO }}/compare/Canary-${{ steps.version_info.outputs.prev_build_version }}...Canary-${{ steps.version_info.outputs.build_version }} "**Full Changelog**: https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO }}/compare/Canary-${{ steps.version_info.outputs.prev_build_version }}...Canary-${{ steps.version_info.outputs.build_version }}"
omitBodyDuringUpdate: true omitBodyDuringUpdate: true
allowUpdates: true allowUpdates: true
replacesArtifacts: true replacesArtifacts: true
@@ -250,11 +262,15 @@ jobs:
run: | 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 1 ./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 1
- 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 1
- name: Pushing new release - name: Pushing new release
uses: ncipollo/release-action@v1 uses: ncipollo/release-action@v1
with: with:
name: "Canary ${{ steps.version_info.outputs.build_version }}" name: "Canary ${{ steps.version_info.outputs.build_version }}"
artifacts: "publish_ava/*.tar.gz" artifacts: "publish_ava/*.tar.gz, publish_headless/*.tar.gz"
tag: ${{ steps.version_info.outputs.build_version }} tag: ${{ steps.version_info.outputs.build_version }}
body: "" body: ""
omitBodyDuringUpdate: true omitBodyDuringUpdate: true
+8 -4
View File
@@ -37,17 +37,21 @@ jobs:
if (!artifacts.length) { if (!artifacts.length) {
return core.error(`No artifacts found`); return core.error(`No artifacts found`);
} }
let body = `*You need to be logged into GitHub to download these files.*\n\nDownload the artifacts for this pull request:\n`; let body = `Download the artifacts for this pull request:\n`;
let hidden_headless_artifacts = `\n\n <details><summary>GUI-less</summary>\n`;
let hidden_debug_artifacts = `\n\n <details><summary>Only for Developers</summary>\n`; let hidden_debug_artifacts = `\n\n <details><summary>Only for Developers</summary>\n`;
for (const art of artifacts) { for (const art of artifacts) {
const url = `https://github.com/Ryubing/Ryujinx/actions/runs/${run_id}/artifacts/${art.id}`;
if(art.name.includes('Debug')) { if(art.name.includes('Debug')) {
hidden_debug_artifacts += `\n* [${art.name}](${url})`; hidden_debug_artifacts += `\n* [${art.name}](https://nightly.link/${owner}/${repo}/actions/artifacts/${art.id}.zip)`;
} else if(art.name.includes('nogui-ryujinx')) {
hidden_headless_artifacts += `\n* [${art.name}](https://nightly.link/${owner}/${repo}/actions/artifacts/${art.id}.zip)`;
} else { } else {
body += `\n* [${art.name}](${url})`; body += `\n* [${art.name}](https://nightly.link/${owner}/${repo}/actions/artifacts/${art.id}.zip)`;
} }
} }
hidden_headless_artifacts += `\n</details>`;
hidden_debug_artifacts += `\n</details>`; hidden_debug_artifacts += `\n</details>`;
body += hidden_headless_artifacts;
body += hidden_debug_artifacts; body += hidden_debug_artifacts;
const {data: comments} = await github.rest.issues.listComments({repo, owner, issue_number}); const {data: comments} = await github.rest.issues.listComments({repo, owner, issue_number});
+31 -16
View File
@@ -21,7 +21,7 @@ env:
DOTNET_CLI_TELEMETRY_OPTOUT: 1 DOTNET_CLI_TELEMETRY_OPTOUT: 1
RYUJINX_BASE_VERSION: "1.2" RYUJINX_BASE_VERSION: "1.2"
RYUJINX_TARGET_RELEASE_CHANNEL_NAME: "release" RYUJINX_TARGET_RELEASE_CHANNEL_NAME: "release"
RYUJINX_TARGET_RELEASE_CHANNEL_OWNER: "Ryubing" RYUJINX_TARGET_RELEASE_CHANNEL_OWNER: "GreemDev"
RYUJINX_TARGET_RELEASE_CHANNEL_REPO: "Ryujinx" RYUJINX_TARGET_RELEASE_CHANNEL_REPO: "Ryujinx"
RELEASE: 1 RELEASE: 1
@@ -42,8 +42,8 @@ jobs:
with: with:
script: | script: |
github.rest.git.createRef({ github.rest.git.createRef({
owner: "${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}", owner: context.repo.owner,
repo: "${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}", repo: context.repo.repo,
ref: 'refs/tags/${{ steps.version_info.outputs.build_version }}', ref: 'refs/tags/${{ steps.version_info.outputs.build_version }}',
sha: context.sha sha: context.sha
}) })
@@ -54,13 +54,13 @@ jobs:
name: ${{ steps.version_info.outputs.build_version }} name: ${{ steps.version_info.outputs.build_version }}
tag: ${{ steps.version_info.outputs.build_version }} tag: ${{ steps.version_info.outputs.build_version }}
body: | body: |
# Stable builds: # Regular builds:
| Platform | Artifact | | Platform | Artifact |
|--|--| |--|--|
| Windows 64-bit | [Stable Windows Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-win_x64.zip) | | Windows 64-bit | [Release Windows Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-win_x64.zip) |
| Linux 64-bit | [Stable Linux Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz) | | Linux 64-bit | [Release Linux Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz) |
| Linux ARM 64-bit | [Stable Linux ARM Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz) | | Linux ARM 64-bit | [Release Linux ARM Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz) |
| macOS | [Stable macOS Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz) | | macOS | [Release macOS Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz) |
**Full Changelog**: https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/compare/${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }} **Full Changelog**: https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/compare/${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }}
omitBodyDuringUpdate: true omitBodyDuringUpdate: true
@@ -112,6 +112,7 @@ jobs:
- name: Publish - name: Publish
run: | run: |
dotnet publish -c Release -r "${{ matrix.platform.name }}" -o ./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 dotnet publish -c Release -r "${{ matrix.platform.name }}" -o ./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
dotnet publish -c Release -r "${{ matrix.platform.name }}" -o ./publish_sdl2_headless -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
- name: Packing Windows builds - name: Packing Windows builds
if: matrix.platform.os == 'windows-latest' if: matrix.platform.os == 'windows-latest'
@@ -120,6 +121,11 @@ jobs:
rm libarmeilleure-jitsupport.dylib rm libarmeilleure-jitsupport.dylib
7z a ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip ../publish 7z a ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip ../publish
popd popd
pushd publish_sdl2_headless
rm libarmeilleure-jitsupport.dylib
7z a ../release_output/nogui-ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip ../publish
popd
shell: bash shell: bash
- name: Build AppImage (Linux) - name: Build AppImage (Linux)
@@ -166,6 +172,11 @@ jobs:
chmod +x Ryujinx.sh Ryujinx chmod +x Ryujinx.sh Ryujinx
tar -czvf ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz ../publish tar -czvf ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz ../publish
popd popd
pushd publish_sdl2_headless
chmod +x Ryujinx.sh Ryujinx.Headless.SDL2
tar -czvf ../release_output/nogui-ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz ../publish
popd
shell: bash shell: bash
- name: Pushing new release - name: Pushing new release
@@ -175,15 +186,15 @@ jobs:
artifacts: "release_output/*.tar.gz,release_output/*.zip,release_output/*AppImage*" artifacts: "release_output/*.tar.gz,release_output/*.zip,release_output/*AppImage*"
tag: ${{ steps.version_info.outputs.build_version }} tag: ${{ steps.version_info.outputs.build_version }}
body: | body: |
# Stable builds: # Regular builds:
| Platform | Artifact | | Platform | Artifact |
|--|--| |--|--|
| Windows 64-bit | [Stable Windows Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-win_x64.zip) | | Windows 64-bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-win_x64.zip |
| Linux 64-bit | [Stable Linux Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz) | | Linux 64-bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz |
| Linux ARM 64-bit | [Stable Linux ARM Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz) | | Linux ARM 64-bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz |
| macOS | [Stable macOS Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz) | | macOS | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz |
**Full Changelog**: https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/compare/${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }} "**Full Changelog**: https://github.com/${{ github.repository }}/compare/${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }}"
omitBodyDuringUpdate: true omitBodyDuringUpdate: true
allowUpdates: true allowUpdates: true
replacesArtifacts: true replacesArtifacts: true
@@ -240,11 +251,15 @@ jobs:
run: | run: |
./distribution/macos/create_macos_build_ava.sh . publish_tmp_ava publish ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.build_version }}" "${{ steps.version_info.outputs.git_short_hash }}" Release 0 ./distribution/macos/create_macos_build_ava.sh . publish_tmp_ava publish ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.build_version }}" "${{ steps.version_info.outputs.git_short_hash }}" Release 0
- 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 0
- name: Pushing new release - name: Pushing new release
uses: ncipollo/release-action@v1 uses: ncipollo/release-action@v1
with: with:
name: ${{ steps.version_info.outputs.build_version }} name: ${{ steps.version_info.outputs.build_version }}
artifacts: "publish/*.tar.gz" artifacts: "publish/*.tar.gz, publish_headless/*.tar.gz"
tag: ${{ steps.version_info.outputs.build_version }} tag: ${{ steps.version_info.outputs.build_version }}
body: "" body: ""
omitBodyDuringUpdate: true omitBodyDuringUpdate: true
+2 -2
View File
@@ -41,10 +41,10 @@
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.3-build14" /> <PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.3-build14" />
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" /> <PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
<PackageVersion Include="Ryujinx.SDL2-CS" Version="2.30.0-build32" /> <PackageVersion Include="Ryujinx.SDL2-CS" Version="2.30.0-build32" />
<PackageVersion Include="Gommon" Version="2.7.0" /> <PackageVersion Include="Gommon" Version="2.6.8" />
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" /> <PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
<PackageVersion Include="shaderc.net" Version="0.1.0" /> <PackageVersion Include="shaderc.net" Version="0.1.0" />
<PackageVersion Include="SharpMetal" Version="1.0.0-preview21" /> <PackageVersion Include="SharpMetal" Version="1.0.0-preview20" />
<PackageVersion Include="SharpZipLib" Version="1.4.2" /> <PackageVersion Include="SharpZipLib" Version="1.4.2" />
<PackageVersion Include="Silk.NET.Vulkan" Version="2.21.0" /> <PackageVersion Include="Silk.NET.Vulkan" Version="2.21.0" />
<PackageVersion Include="Silk.NET.Vulkan.Extensions.EXT" Version="2.21.0" /> <PackageVersion Include="Silk.NET.Vulkan.Extensions.EXT" Version="2.21.0" />
+17 -11
View File
@@ -57,10 +57,14 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.SDL2.Common", "src\
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Audio.Backends.SDL2", "src\Ryujinx.Audio.Backends.SDL2\Ryujinx.Audio.Backends.SDL2.csproj", "{D99A395A-8569-4DB0-B336-900647890052}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Audio.Backends.SDL2", "src\Ryujinx.Audio.Backends.SDL2\Ryujinx.Audio.Backends.SDL2.csproj", "{D99A395A-8569-4DB0-B336-900647890052}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Headless.SDL2", "src\Ryujinx.Headless.SDL2\Ryujinx.Headless.SDL2.csproj", "{390DC343-5CB4-4C79-A5DD-E3ED235E4C49}"
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}" 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 EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx", "src\Ryujinx\Ryujinx.csproj", "{7C1B2721-13DA-4B62-B046-C626605ECCE6}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx", "src\Ryujinx\Ryujinx.csproj", "{7C1B2721-13DA-4B62-B046-C626605ECCE6}"
EndProject EndProject
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}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon.Generators", "src\Ryujinx.Horizon.Generators\Ryujinx.Horizon.Generators.csproj", "{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Vulkan", "src\Ryujinx.Graphics.Vulkan\Ryujinx.Graphics.Vulkan.csproj", "{D4D09B08-D580-4D69-B886-C35D2853F6C8}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Vulkan", "src\Ryujinx.Graphics.Vulkan\Ryujinx.Graphics.Vulkan.csproj", "{D4D09B08-D580-4D69-B886-C35D2853F6C8}"
@@ -76,16 +80,11 @@ 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}" 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 EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.HLE.Generators", "src\Ryujinx.HLE.Generators\Ryujinx.HLE.Generators.csproj", "{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.HLE.Generators", "src\Ryujinx.HLE.Generators\Ryujinx.HLE.Generators.csproj", "{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ryujinx.Graphics.Metal", "src\Ryujinx.Graphics.Metal\Ryujinx.Graphics.Metal.csproj", "{C08931FA-1191-417A-864F-3882D93E683B}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ryujinx.Graphics.Metal", "src\Ryujinx.Graphics.Metal\Ryujinx.Graphics.Metal.csproj", "{C08931FA-1191-417A-864F-3882D93E683B}"
ProjectSection(ProjectDependencies) = postProject ProjectSection(ProjectDependencies) = postProject
{A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E} = {A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E} {A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E} = {A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E}
EndProjectSection EndProjectSection
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ryujinx.BuildValidationTasks", "src\Ryujinx.BuildValidationTasks\Ryujinx.BuildValidationTasks.csproj", "{4A89A234-4F19-497D-A576-DDE8CDFC5B22}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ryujinx.Graphics.Metal.SharpMetalExtensions", "src/Ryujinx.Graphics.Metal.SharpMetalExtensions\Ryujinx.Graphics.Metal.SharpMetalExtensions.csproj", "{81EA598C-DBA1-40B0-8DA4-4796B78F2037}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{36F870C1-3E5F-485F-B426-F0645AF78751}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{36F870C1-3E5F-485F-B426-F0645AF78751}"
ProjectSection(SolutionItems) = preProject ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig .editorconfig = .editorconfig
@@ -95,6 +94,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
.github\workflows\release.yml = .github\workflows\release.yml .github\workflows\release.yml = .github\workflows\release.yml
EndProjectSection EndProjectSection
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ryujinx.BuildValidationTasks", "src\Ryujinx.BuildValidationTasks\Ryujinx.BuildValidationTasks.csproj", "{4A89A234-4F19-497D-A576-DDE8CDFC5B22}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@@ -209,6 +210,10 @@ Global
{D99A395A-8569-4DB0-B336-900647890052}.Debug|Any CPU.Build.0 = Debug|Any CPU {D99A395A-8569-4DB0-B336-900647890052}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D99A395A-8569-4DB0-B336-900647890052}.Release|Any CPU.ActiveCfg = Release|Any CPU {D99A395A-8569-4DB0-B336-900647890052}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D99A395A-8569-4DB0-B336-900647890052}.Release|Any CPU.Build.0 = Release|Any CPU {D99A395A-8569-4DB0-B336-900647890052}.Release|Any CPU.Build.0 = Release|Any CPU
{390DC343-5CB4-4C79-A5DD-E3ED235E4C49}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{390DC343-5CB4-4C79-A5DD-E3ED235E4C49}.Debug|Any CPU.Build.0 = Debug|Any CPU
{390DC343-5CB4-4C79-A5DD-E3ED235E4C49}.Release|Any CPU.ActiveCfg = Release|Any CPU
{390DC343-5CB4-4C79-A5DD-E3ED235E4C49}.Release|Any CPU.Build.0 = Release|Any CPU
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Debug|Any CPU.Build.0 = Debug|Any CPU {BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Release|Any CPU.ActiveCfg = Release|Any CPU {BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -217,6 +222,10 @@ Global
{7C1B2721-13DA-4B62-B046-C626605ECCE6}.Debug|Any CPU.Build.0 = Debug|Any CPU {7C1B2721-13DA-4B62-B046-C626605ECCE6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7C1B2721-13DA-4B62-B046-C626605ECCE6}.Release|Any CPU.ActiveCfg = Release|Any CPU {7C1B2721-13DA-4B62-B046-C626605ECCE6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7C1B2721-13DA-4B62-B046-C626605ECCE6}.Release|Any CPU.Build.0 = Release|Any CPU {7C1B2721-13DA-4B62-B046-C626605ECCE6}.Release|Any CPU.Build.0 = Release|Any CPU
{BA161CA0-CD65-4E6E-B644-51C8D1E542DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BA161CA0-CD65-4E6E-B644-51C8D1E542DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BA161CA0-CD65-4E6E-B644-51C8D1E542DC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BA161CA0-CD65-4E6E-B644-51C8D1E542DC}.Release|Any CPU.Build.0 = Release|Any CPU
{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Debug|Any CPU.Build.0 = Debug|Any CPU {6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Release|Any CPU.ActiveCfg = Release|Any CPU {6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -249,16 +258,13 @@ Global
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Debug|Any CPU.Build.0 = 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.ActiveCfg = Release|Any CPU
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Release|Any CPU.Build.0 = Release|Any CPU {B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Release|Any CPU.Build.0 = Release|Any CPU
{4A89A234-4F19-497D-A576-DDE8CDFC5B22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4A89A234-4F19-497D-A576-DDE8CDFC5B22}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4A89A234-4F19-497D-A576-DDE8CDFC5B22}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C08931FA-1191-417A-864F-3882D93E683B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C08931FA-1191-417A-864F-3882D93E683B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C08931FA-1191-417A-864F-3882D93E683B}.Debug|Any CPU.Build.0 = Debug|Any CPU {C08931FA-1191-417A-864F-3882D93E683B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C08931FA-1191-417A-864F-3882D93E683B}.Release|Any CPU.ActiveCfg = Release|Any CPU {C08931FA-1191-417A-864F-3882D93E683B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C08931FA-1191-417A-864F-3882D93E683B}.Release|Any CPU.Build.0 = Release|Any CPU {C08931FA-1191-417A-864F-3882D93E683B}.Release|Any CPU.Build.0 = Release|Any CPU
{4A89A234-4F19-497D-A576-DDE8CDFC5B22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4A89A234-4F19-497D-A576-DDE8CDFC5B22}.Release|Any CPU.ActiveCfg = Release|Any CPU
{81EA598C-DBA1-40B0-8DA4-4796B78F2037}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{81EA598C-DBA1-40B0-8DA4-4796B78F2037}.Debug|Any CPU.Build.0 = Debug|Any CPU
{81EA598C-DBA1-40B0-8DA4-4796B78F2037}.Release|Any CPU.ActiveCfg = Release|Any CPU
{81EA598C-DBA1-40B0-8DA4-4796B78F2037}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@@ -13,7 +13,7 @@ mkdir -p AppDir/usr/bin
cp distribution/linux/Ryujinx.desktop AppDir/Ryujinx.desktop cp distribution/linux/Ryujinx.desktop AppDir/Ryujinx.desktop
cp distribution/linux/appimage/AppRun AppDir/AppRun cp distribution/linux/appimage/AppRun AppDir/AppRun
cp distribution/misc/Logo.svg AppDir/Ryujinx.svg cp src/Ryujinx.UI.Common/Resources/Logo_Ryujinx.png AppDir/Ryujinx.svg
cp -r "$BUILDDIR"/* AppDir/usr/bin/ cp -r "$BUILDDIR"/* AppDir/usr/bin/
@@ -1,5 +1,4 @@
using ARMeilleure.State; using ARMeilleure.State;
using Humanizer;
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Common.Memory; using Ryujinx.Common.Memory;
@@ -59,8 +58,8 @@ namespace ARMeilleure.Translation.PTC
{ {
_ptc = ptc; _ptc = ptc;
_timer = new Timer(SaveInterval.Seconds()); _timer = new Timer(SaveInterval * 1000d);
_timer.Elapsed += TimerElapsed; _timer.Elapsed += PreSave;
_outerHeaderMagic = BinaryPrimitives.ReadUInt64LittleEndian(EncodingCache.UTF8NoBOM.GetBytes(OuterHeaderMagicString).AsSpan()); _outerHeaderMagic = BinaryPrimitives.ReadUInt64LittleEndian(EncodingCache.UTF8NoBOM.GetBytes(OuterHeaderMagicString).AsSpan());
@@ -73,9 +72,6 @@ namespace ARMeilleure.Translation.PTC
Enabled = false; Enabled = false;
} }
private void TimerElapsed(object _, ElapsedEventArgs __)
=> new Thread(PreSave) { Name = "Ptc.DiskWriter" }.Start();
public void AddEntry(ulong address, ExecutionMode mode, bool highCq) public void AddEntry(ulong address, ExecutionMode mode, bool highCq)
{ {
if (IsAddressInStaticCodeRange(address)) if (IsAddressInStaticCodeRange(address))
@@ -266,7 +262,7 @@ namespace ARMeilleure.Translation.PTC
compressedStream.SetLength(0L); compressedStream.SetLength(0L);
} }
private void PreSave() private void PreSave(object source, ElapsedEventArgs e)
{ {
_waitEvent.Reset(); _waitEvent.Reset();
@@ -432,7 +428,7 @@ namespace ARMeilleure.Translation.PTC
{ {
_disposed = true; _disposed = true;
_timer.Elapsed -= TimerElapsed; _timer.Elapsed -= PreSave;
_timer.Dispose(); _timer.Dispose();
Wait(); Wait();
@@ -9,12 +9,20 @@ namespace Ryujinx.Audio.Backends.Dummy
{ {
public class DummyHardwareDeviceDriver : IHardwareDeviceDriver public class DummyHardwareDeviceDriver : IHardwareDeviceDriver
{ {
private readonly ManualResetEvent _updateRequiredEvent = new(false); private readonly ManualResetEvent _updateRequiredEvent;
private readonly ManualResetEvent _pauseEvent = new(true); private readonly ManualResetEvent _pauseEvent;
public static bool IsSupported => true; public static bool IsSupported => true;
public float Volume { get; set; } = 1f; public float Volume { get; set; }
public DummyHardwareDeviceDriver()
{
_updateRequiredEvent = new ManualResetEvent(false);
_pauseEvent = new ManualResetEvent(true);
Volume = 1f;
}
public IHardwareDeviceSession OpenDeviceSession(Direction direction, IVirtualMemoryManager memoryManager, SampleFormat sampleFormat, uint sampleRate, uint channelCount) public IHardwareDeviceSession OpenDeviceSession(Direction direction, IVirtualMemoryManager memoryManager, SampleFormat sampleFormat, uint sampleRate, uint channelCount)
{ {
@@ -52,7 +60,7 @@ namespace Ryujinx.Audio.Backends.Dummy
Dispose(true); Dispose(true);
} }
private void Dispose(bool disposing) protected virtual void Dispose(bool disposing)
{ {
if (disposing) if (disposing)
{ {
@@ -1,7 +0,0 @@
namespace Ryujinx.BuildValidationTasks
{
public interface IValidationTask
{
public bool Execute(string projectPath, bool isGitRunner);
}
}
@@ -0,0 +1,73 @@
using System;
using Microsoft.Build.Utilities;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using Newtonsoft.Json;
using Microsoft.Build.Framework;
namespace Ryujinx.BuildValidationTasks
{
public class LocaleValidationTask : Task
{
public override bool Execute()
{
string path = System.Reflection.Assembly.GetExecutingAssembly().Location;
if (path.Split(["src"], StringSplitOptions.None).Length == 1)
{
//i assume that we are in a build directory in the solution dir
path = new FileInfo(path).Directory!.Parent!.GetDirectories("src")[0].GetDirectories("Ryujinx")[0].GetDirectories("Assets")[0].GetFiles("locales.json")[0].FullName;
}
else
{
path = path.Split(["src"], StringSplitOptions.None)[0];
path = new FileInfo(path).Directory!.GetDirectories("src")[0].GetDirectories("Ryujinx")[0].GetDirectories("Assets")[0].GetFiles("locales.json")[0].FullName;
}
string data;
using (StreamReader sr = new(path))
{
data = sr.ReadToEnd();
}
LocalesJson json = JsonConvert.DeserializeObject<LocalesJson>(data);
for (int i = 0; i < json.Locales.Count; i++)
{
LocalesEntry locale = json.Locales[i];
foreach (string langCode in json.Languages.Where(it => !locale.Translations.ContainsKey(it)))
{
locale.Translations.Add(langCode, string.Empty);
Log.LogMessage(MessageImportance.High, $"Added '{langCode}' to Locale '{locale.ID}'");
}
locale.Translations = locale.Translations.OrderBy(pair => pair.Key).ToDictionary(pair => pair.Key, pair => pair.Value);
json.Locales[i] = locale;
}
string jsonString = JsonConvert.SerializeObject(json, Formatting.Indented);
using (StreamWriter sw = new(path))
{
sw.Write(jsonString);
}
return true;
}
struct LocalesJson
{
public List<string> Languages { get; set; }
public List<LocalesEntry> Locales { get; set; }
}
struct LocalesEntry
{
public string ID { get; set; }
public Dictionary<string, string> Translations { get; set; }
}
}
}
@@ -1,117 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Text.Json;
using System.Text.Encodings.Web;
namespace Ryujinx.BuildValidationTasks
{
public class LocalesValidationTask : IValidationTask
{
public LocalesValidationTask() { }
public bool Execute(string projectPath, bool isGitRunner)
{
Console.WriteLine("Running Locale Validation Task...");
string path = projectPath + "src/Ryujinx/Assets/locales.json";
string data;
using (StreamReader sr = new(path))
{
data = sr.ReadToEnd();
}
LocalesJson json;
if (isGitRunner && data.Contains("\r\n"))
throw new FormatException("locales.json is using CRLF line endings! It should be using LF line endings, build locally to fix...");
try
{
json = JsonSerializer.Deserialize<LocalesJson>(data);
}
catch (JsonException e)
{
throw new JsonException(e.Message); //shorter and easier stacktrace
}
bool encounteredIssue = false;
for (int i = 0; i < json.Locales.Count; i++)
{
LocalesEntry locale = json.Locales[i];
foreach (string langCode in json.Languages.Where(lang => !locale.Translations.ContainsKey(lang)))
{
encounteredIssue = true;
if (!isGitRunner)
{
locale.Translations.Add(langCode, string.Empty);
Console.WriteLine($"Added '{langCode}' to Locale '{locale.ID}'");
}
else
{
Console.WriteLine($"Missing '{langCode}' in Locale '{locale.ID}'!");
}
}
foreach (string langCode in json.Languages.Where(lang => locale.Translations.ContainsKey(lang) && lang != "en_US" && locale.Translations[lang] == locale.Translations["en_US"]))
{
encounteredIssue = true;
if (!isGitRunner)
{
locale.Translations[langCode] = string.Empty;
Console.WriteLine($"Lanugage '{langCode}' is a duplicate of en_US in Locale '{locale.ID}'! Resetting it...");
}
else
{
Console.WriteLine($"Lanugage '{langCode}' is a duplicate of en_US in Locale '{locale.ID}'!");
}
}
locale.Translations = locale.Translations.OrderBy(pair => pair.Key).ToDictionary(pair => pair.Key, pair => pair.Value);
json.Locales[i] = locale;
}
if (isGitRunner && encounteredIssue)
throw new JsonException("1 or more locales are invalid!");
JsonSerializerOptions jsonOptions = new JsonSerializerOptions()
{
WriteIndented = true,
NewLine = "\n",
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
};
string jsonString = JsonSerializer.Serialize(json, jsonOptions);
using (StreamWriter sw = new(path))
{
sw.Write(jsonString);
}
Console.WriteLine("Finished Locale Validation Task!");
return true;
}
struct LocalesJson
{
public List<string> Languages { get; set; }
public List<LocalesEntry> Locales { get; set; }
}
struct LocalesEntry
{
public string ID { get; set; }
public Dictionary<string, string> Translations { get; set; }
}
}
}
@@ -1,37 +0,0 @@
using System;
using System.IO;
using System.Linq;
namespace Ryujinx.BuildValidationTasks
{
public class Program
{
static void Main(string[] args)
{
// Display the number of command line arguments.
if (args.Length == 0)
throw new ArgumentException("Error: too few arguments!");
string path = args[0];
if (string.IsNullOrEmpty(path))
throw new ArgumentException("Error: path is null or empty!");
if (!Path.Exists(path))
throw new FileLoadException($"path {{{path}}} does not exist!");
path = Path.GetFullPath(path);
if (!Directory.GetDirectories(path).Contains($"{path}src"))
throw new FileLoadException($"path {{{path}}} is not a valid ryujinx project!");
bool isGitRunner = path.Contains("runner") || path.Contains("D:\\a\\Ryujinx\\Ryujinx");
if (isGitRunner)
Console.WriteLine("Is Git Runner!");
// Run tasks
// Pass extra info needed in the task constructors
new LocalesValidationTask().Execute(path, isGitRunner);
}
}
}
@@ -1,17 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <TargetFramework>netstandard2.0</TargetFramework>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
</PropertyGroup> </PropertyGroup>
<Target Name="PostBuildTarget" AfterTargets="AfterBuild"> <ItemGroup>
<Message Text="Running Validation Project" Importance="high" /> <PackageReference Include="Microsoft.Build.Utilities.Core" />
<PackageReference Include="Newtonsoft.Json" />
</ItemGroup>
<Exec WorkingDirectory="$(ProjectDir)bin\Debug\$(TargetFramework)\" <UsingTask TaskName="Ryujinx.BuildValidationTasks.LocaleValidationTask" TaskFactory="TaskHostFactory" AssemblyFile="$(OutDir)Ryujinx.BuildValidationTasks.dll" />
Command="dotnet Ryujinx.BuildValidationTasks.dll &quot;$(ProjectDir)..\..\\&quot;"
ConsoleToMsBuild="true" <Target Name="LocalesJsonValidation" AfterTargets="AfterRebuild">
Condition="'$(RuntimeIdentifier)' == ''" <LocaleValidationTask />
/>
</Target> </Target>
</Project> </Project>
@@ -35,8 +35,6 @@ namespace Ryujinx.Common.Configuration
#pragma warning restore IDE0055 #pragma warning restore IDE0055
}; };
} }
public static float ToFloatY(this AspectRatio aspectRatio) public static float ToFloatY(this AspectRatio aspectRatio)
{ {
@@ -1,55 +0,0 @@
using Gommon;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Ryujinx.Common.Configuration
{
[Flags]
public enum DirtyHacks : byte
{
Xc2MenuSoftlockFix = 1,
ShaderCompilationThreadSleep = 2
}
public record EnabledDirtyHack(DirtyHacks Hack, int Value)
{
public static readonly byte[] PackedFormat = [8, 32];
private uint[] Raw => [(uint)Hack, (uint)Value.CoerceAtLeast(0)];
public ulong Pack() => Raw.PackBitFields(PackedFormat);
public static EnabledDirtyHack Unpack(ulong packedHack)
{
var unpackedFields = packedHack.UnpackBitFields(PackedFormat);
if (unpackedFields is not [var hack, var value])
throw new ArgumentException(nameof(packedHack));
return new EnabledDirtyHack((DirtyHacks)hack, (int)value);
}
}
public class DirtyHackCollection : Dictionary<DirtyHacks, int>
{
public DirtyHackCollection(IEnumerable<EnabledDirtyHack> hacks)
=> hacks.ForEach(edh => Add(edh.Hack, edh.Value));
public DirtyHackCollection(ulong[] packedHacks) : this(packedHacks.Select(EnabledDirtyHack.Unpack)) {}
public ulong[] PackEntries()
=> Entries.Select(it => it.Pack()).ToArray();
public EnabledDirtyHack[] Entries
=> this
.Select(it => new EnabledDirtyHack(it.Key, it.Value))
.ToArray();
public static implicit operator DirtyHackCollection(EnabledDirtyHack[] hacks) => new(hacks);
public static implicit operator DirtyHackCollection(ulong[] packedHacks) => new(packedHacks);
public new int this[DirtyHacks hack] => TryGetValue(hack, out var value) ? value : -1;
public bool IsEnabled(DirtyHacks hack) => ContainsKey(hack);
}
}
@@ -9,6 +9,5 @@ namespace Ryujinx.Common.Configuration
Bilinear, Bilinear,
Nearest, Nearest,
Fsr, Fsr,
Area,
} }
} }
@@ -8,10 +8,10 @@ namespace Ryujinx.Common
public static class StreamExtensions public static class StreamExtensions
{ {
/// <summary> /// <summary>
/// Writes an int span to this stream. /// Writes a <see cref="ReadOnlySpan{int}" /> to this stream.
/// ///
/// This default implementation converts each buffer value to a stack-allocated /// This default implementation converts each buffer value to a stack-allocated
/// byte array, then writes it to the Stream using <see cref="Stream.Write(ReadOnlySpan{byte})" />. /// byte array, then writes it to the Stream using <cref="System.Stream.Write(byte[])" />.
/// </summary> /// </summary>
/// <param name="stream">The stream to be written to</param> /// <param name="stream">The stream to be written to</param>
/// <param name="buffer">The buffer of values to be written</param> /// <param name="buffer">The buffer of values to be written</param>
+12 -8
View File
@@ -4,7 +4,6 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Threading; using System.Threading;
@@ -158,16 +157,21 @@ namespace Ryujinx.Common.Logging
_time.Restart(); _time.Restart();
} }
private static ILogTarget GetTarget(string targetName) private static ILogTarget GetTarget(string targetName)
=> _logTargets.FirstOrDefault(target => target.Name.Equals(targetName)); {
foreach (var target in _logTargets)
{
if (target.Name.Equals(targetName))
{
return target;
}
}
return null;
}
public static void AddTarget(ILogTarget target) public static void AddTarget(ILogTarget target)
{ {
if (_logTargets.Any(t => t.Name == target.Name))
{
return;
}
_logTargets.Add(target); _logTargets.Add(target);
Updated += target.Log; Updated += target.Log;
@@ -27,7 +27,11 @@ namespace Ryujinx.Common.Logging.Targets
private readonly int _overflowTimeout; private readonly int _overflowTimeout;
string ILogTarget.Name => _target.Name; string ILogTarget.Name { get => _target.Name; }
public AsyncLogTargetWrapper(ILogTarget target)
: this(target, -1)
{ }
public AsyncLogTargetWrapper(ILogTarget target, int queueLimit = -1, AsyncLogTargetOverflowAction overflowAction = AsyncLogTargetOverflowAction.Block) public AsyncLogTargetWrapper(ILogTarget target, int queueLimit = -1, AsyncLogTargetOverflowAction overflowAction = AsyncLogTargetOverflowAction.Block)
{ {
-30
View File
@@ -40,35 +40,5 @@ namespace Ryujinx.Common
return (value >> 32) | (value << 32); return (value >> 32) | (value << 32);
} }
// Never actually written bit packing logic before, so I looked it up.
// This code is from https://gist.github.com/Alan-FGR/04938e93e2bffdf5802ceb218a37c195
public static ulong PackBitFields(this uint[] values, byte[] bitFields)
{
ulong retVal = values[0]; //we set the first value right away
for (int f = 1; f < values.Length; f++)
{
retVal <<= bitFields[f]; // we shift the previous value
retVal += values[f];// and add our current value
}
return retVal;
}
public static uint[] UnpackBitFields(this ulong packed, byte[] bitFields)
{
int fields = bitFields.Length - 1; // number of fields to unpack
uint[] retArr = new uint[fields + 1]; // init return array
int curPos = 0; // current field bit position (start)
int lastEnd; // position where last field ended
for (int f = fields; f >= 0; f--) // loop from last
{
lastEnd = curPos; // we store where the last value ended
curPos += bitFields[f]; // we get where the current value starts
int leftShift = 64 - curPos; // we figure how much left shift we gotta apply for the other numbers to overflow into oblivion
retArr[f] = (uint)((packed << leftShift) >> leftShift + lastEnd); // we do magic
}
return retArr;
}
} }
} }
+12
View File
@@ -0,0 +1,12 @@
namespace Ryujinx.Graphics.GAL
{
public enum AntiAliasing
{
None,
Fxaa,
SmaaLow,
SmaaMedium,
SmaaHigh,
SmaaUltra,
}
}
-1
View File
@@ -1,4 +1,3 @@
using Ryujinx.Common.Configuration;
using System; using System;
namespace Ryujinx.Graphics.GAL namespace Ryujinx.Graphics.GAL
@@ -1,4 +1,3 @@
using Ryujinx.Common.Configuration;
using Ryujinx.Graphics.GAL.Multithreading.Commands.Window; using Ryujinx.Graphics.GAL.Multithreading.Commands.Window;
using Ryujinx.Graphics.GAL.Multithreading.Model; using Ryujinx.Graphics.GAL.Multithreading.Model;
using Ryujinx.Graphics.GAL.Multithreading.Resources; using Ryujinx.Graphics.GAL.Multithreading.Resources;
+10
View File
@@ -0,0 +1,10 @@
namespace Ryujinx.Graphics.GAL
{
public enum ScalingFilter
{
Bilinear,
Nearest,
Fsr,
Area,
}
}
+9
View File
@@ -0,0 +1,9 @@
namespace Ryujinx.Graphics.GAL
{
public enum VSyncMode
{
Switch,
Unbounded,
Custom
}
}
+1 -7
View File
@@ -1,5 +1,4 @@
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Common.Configuration;
using Ryujinx.Graphics.Device; using Ryujinx.Graphics.Device;
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Gpu.Engine.GPFifo; using Ryujinx.Graphics.Gpu.Engine.GPFifo;
@@ -91,9 +90,6 @@ namespace Ryujinx.Graphics.Gpu
/// Support buffer updater. /// Support buffer updater.
/// </summary> /// </summary>
internal SupportBufferUpdater SupportBufferUpdater { get; } internal SupportBufferUpdater SupportBufferUpdater { get; }
internal DirtyHackCollection DirtyHacks { get; }
/// <summary> /// <summary>
/// Host hardware capabilities. /// Host hardware capabilities.
@@ -117,7 +113,7 @@ namespace Ryujinx.Graphics.Gpu
/// Creates a new instance of the GPU emulation context. /// Creates a new instance of the GPU emulation context.
/// </summary> /// </summary>
/// <param name="renderer">Host renderer</param> /// <param name="renderer">Host renderer</param>
public GpuContext(IRenderer renderer, DirtyHackCollection hackCollection) public GpuContext(IRenderer renderer)
{ {
Renderer = renderer; Renderer = renderer;
@@ -140,8 +136,6 @@ namespace Ryujinx.Graphics.Gpu
SupportBufferUpdater = new SupportBufferUpdater(renderer); SupportBufferUpdater = new SupportBufferUpdater(renderer);
DirtyHacks = hackCollection;
_firstTimestamp = ConvertNanosecondsToTicks((ulong)PerformanceCounter.ElapsedNanoseconds); _firstTimestamp = ConvertNanosecondsToTicks((ulong)PerformanceCounter.ElapsedNanoseconds);
} }
+1 -1
View File
@@ -46,7 +46,7 @@ namespace Ryujinx.Graphics.Gpu
/// Enables or disables high-level emulation of common GPU Macro code. /// Enables or disables high-level emulation of common GPU Macro code.
/// </summary> /// </summary>
public static bool EnableMacroHLE = true; public static bool EnableMacroHLE = true;
/// <summary> /// <summary>
/// Title id of the current running game. /// Title id of the current running game.
/// Used by the shader cache. /// Used by the shader cache.
@@ -1,4 +1,3 @@
using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Shader; using Ryujinx.Graphics.Shader;
@@ -367,9 +366,6 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
{ {
try try
{ {
if (_context.DirtyHacks.IsEnabled(DirtyHacks.ShaderCompilationThreadSleep))
Thread.Sleep(_context.DirtyHacks[DirtyHacks.ShaderCompilationThreadSleep]);
AsyncProgramTranslation asyncTranslation = new(guestShaders, specState, programIndex, isCompute); AsyncProgramTranslation asyncTranslation = new(guestShaders, specState, programIndex, isCompute);
_asyncTranslationQueue.Add(asyncTranslation, _cancellationToken); _asyncTranslationQueue.Add(asyncTranslation, _cancellationToken);
} }
@@ -1,4 +1,3 @@
using Ryujinx.Common;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
@@ -839,7 +838,6 @@ namespace Ryujinx.Graphics.Gpu.Shader
TargetApi.OpenGL => TargetLanguage.Glsl, TargetApi.OpenGL => TargetLanguage.Glsl,
TargetApi.Vulkan => GraphicsConfig.EnableSpirvCompilationOnVulkan ? TargetLanguage.Spirv : TargetLanguage.Glsl, TargetApi.Vulkan => GraphicsConfig.EnableSpirvCompilationOnVulkan ? TargetLanguage.Spirv : TargetLanguage.Glsl,
TargetApi.Metal => TargetLanguage.Msl, TargetApi.Metal => TargetLanguage.Msl,
_ => throw new NotImplementedException()
}; };
return new TranslationOptions(lang, api, flags); return new TranslationOptions(lang, api, flags);
@@ -1,22 +0,0 @@
using SharpMetal;
using SharpMetal.Foundation;
using SharpMetal.ObjectiveCCore;
using SharpMetal.QuartzCore;
using System.Runtime.Versioning;
// ReSharper disable InconsistentNaming
namespace Ryujinx.Graphics.Metal.SharpMetalExtensions
{
[SupportedOSPlatform("macOS")]
public static class CAMetalLayerExtensions
{
private static readonly Selector sel_developerHUDProperties = "developerHUDProperties";
private static readonly Selector sel_setDeveloperHUDProperties = "setDeveloperHUDProperties:";
public static NSDictionary GetDeveloperHudProperties(this CAMetalLayer metalLayer)
=> new(ObjectiveCRuntime.IntPtr_objc_msgSend(metalLayer.NativePtr, sel_developerHUDProperties));
public static void SetDeveloperHudProperties(this CAMetalLayer metalLayer, NSDictionary dictionary)
=> ObjectiveCRuntime.objc_msgSend(metalLayer.NativePtr, sel_setDeveloperHUDProperties, dictionary);
}
}
@@ -1,32 +0,0 @@
using SharpMetal.Foundation;
using SharpMetal.ObjectiveCCore;
using System.Runtime.Versioning;
// ReSharper disable InconsistentNaming
namespace Ryujinx.Graphics.Metal.SharpMetalExtensions
{
[SupportedOSPlatform("macOS")]
public static class NSHelper
{
private static readonly Selector sel_getCStringMaxLengthEncoding = "getCString:maxLength:encoding:";
private static readonly Selector sel_stringWithUTF8String = "stringWithUTF8String:";
public static unsafe string ToDotNetString(this NSString source)
{
char[] sourceBuffer = new char[source.Length];
fixed (char* pSourceBuffer = sourceBuffer)
{
ObjectiveC.bool_objc_msgSend(source,
sel_getCStringMaxLengthEncoding,
pSourceBuffer,
source.MaximumLengthOfBytes(NSStringEncoding.UTF16) + 1,
(ulong)NSStringEncoding.UTF16);
}
return new string(sourceBuffer);
}
public static NSString ToNSString(this string source)
=> new(ObjectiveC.IntPtr_objc_msgSend(new ObjectiveCClass(nameof(NSString)), sel_stringWithUTF8String, source));
}
}
@@ -1,11 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="SharpMetal" />
</ItemGroup>
</Project>
@@ -1767,7 +1767,6 @@ namespace Ryujinx.Graphics.Metal
Constants.StorageBuffersSetIndex => Constants.StorageBuffersIndex, Constants.StorageBuffersSetIndex => Constants.StorageBuffersIndex,
Constants.TexturesSetIndex => Constants.TexturesIndex, Constants.TexturesSetIndex => Constants.TexturesIndex,
Constants.ImagesSetIndex => Constants.ImagesIndex, Constants.ImagesSetIndex => Constants.ImagesIndex,
_ => throw new NotImplementedException()
}; };
} }
+1 -4
View File
@@ -21,12 +21,9 @@ namespace Ryujinx.Graphics.Metal
private Pipeline _pipeline; private Pipeline _pipeline;
private Window _window; private Window _window;
public uint ProgramCount { get; set; } public uint ProgramCount { get; set; } = 0;
#pragma warning disable CS0067 // The event is never used
public event EventHandler<ScreenCaptureImageInfo> ScreenCaptured; public event EventHandler<ScreenCaptureImageInfo> ScreenCaptured;
#pragma warning restore CS0067
public bool PreferThreading => true; public bool PreferThreading => true;
public IPipeline Pipeline => _pipeline; public IPipeline Pipeline => _pipeline;
public IWindow Window => _window; public IWindow Window => _window;
@@ -5,9 +5,12 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Ryujinx.Common\Ryujinx.Common.csproj" /> <ProjectReference Include="..\Ryujinx.Common\Ryujinx.Common.csproj" />
<ProjectReference Include="..\Ryujinx.Graphics.GAL\Ryujinx.Graphics.GAL.csproj" /> <ProjectReference Include="..\Ryujinx.Graphics.GAL\Ryujinx.Graphics.GAL.csproj" />
<ProjectReference Include="..\Ryujinx.Graphics.Metal.SharpMetalExtensions\Ryujinx.Graphics.Metal.SharpMetalExtensions.csproj" /> </ItemGroup>
<ItemGroup>
<PackageReference Include="SharpMetal" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
+6 -9
View File
@@ -1,4 +1,3 @@
using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Metal.Effects; using Ryujinx.Graphics.Metal.Effects;
@@ -15,22 +14,20 @@ namespace Ryujinx.Graphics.Metal
public bool ScreenCaptureRequested { get; set; } public bool ScreenCaptureRequested { get; set; }
private readonly MetalRenderer _renderer; private readonly MetalRenderer _renderer;
private CAMetalLayer _metalLayer; private readonly CAMetalLayer _metalLayer;
private int _width; private int _width;
private int _height; private int _height;
private int _requestedWidth; private int _requestedWidth;
private int _requestedHeight; private int _requestedHeight;
// private bool _vsyncEnabled;
private AntiAliasing _currentAntiAliasing; private AntiAliasing _currentAntiAliasing;
private bool _updateEffect; private bool _updateEffect;
private IPostProcessingEffect _effect; private IPostProcessingEffect _effect;
private IScalingFilter _scalingFilter; private IScalingFilter _scalingFilter;
private bool _isLinear; private bool _isLinear;
public bool IsVSyncEnabled => _metalLayer.DisplaySyncEnabled;
// private float _scalingFilterLevel; // private float _scalingFilterLevel;
private bool _updateScalingFilter; private bool _updateScalingFilter;
private ScalingFilter _currentScalingFilter; private ScalingFilter _currentScalingFilter;
@@ -42,7 +39,7 @@ namespace Ryujinx.Graphics.Metal
_metalLayer = metalLayer; _metalLayer = metalLayer;
} }
private void ResizeIfNeeded() private unsafe void ResizeIfNeeded()
{ {
if (_requestedWidth != 0 && _requestedHeight != 0) if (_requestedWidth != 0 && _requestedHeight != 0)
{ {
@@ -56,7 +53,7 @@ namespace Ryujinx.Graphics.Metal
} }
} }
public void Present(ITexture texture, ImageCrop crop, Action swapBuffersCallback) public unsafe void Present(ITexture texture, ImageCrop crop, Action swapBuffersCallback)
{ {
if (_renderer.Pipeline is Pipeline pipeline && texture is Texture tex) if (_renderer.Pipeline is Pipeline pipeline && texture is Texture tex)
{ {
@@ -143,7 +140,7 @@ namespace Ryujinx.Graphics.Metal
public void ChangeVSyncMode(VSyncMode vSyncMode) public void ChangeVSyncMode(VSyncMode vSyncMode)
{ {
_metalLayer.DisplaySyncEnabled = vSyncMode is VSyncMode.Switch; //_vSyncMode = vSyncMode;
} }
public void SetAntiAliasing(AntiAliasing effect) public void SetAntiAliasing(AntiAliasing effect)
+3 -3
View File
@@ -2,8 +2,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{ {
internal enum BitDepth internal enum BitDepth
{ {
Bits8 = 8, // < 8 bits Bits8 = 8, /**< 8 bits */
Bits10 = 10, // < 10 bits Bits10 = 10, /**< 10 bits */
Bits12 = 12, // < 12 bits Bits12 = 12, /**< 12 bits */
} }
} }
@@ -42,7 +42,7 @@ namespace Ryujinx.Graphics.OpenGL.Queries
_current = new CounterQueueEvent(this, glType, 0); _current = new CounterQueueEvent(this, glType, 0);
_consumerThread = new Thread(EventConsumer) { Name = "CPU.CounterQueue." + (int)type }; _consumerThread = new Thread(EventConsumer);
_consumerThread.Start(); _consumerThread.Start();
} }
-1
View File
@@ -1,5 +1,4 @@
using OpenTK.Graphics.OpenGL; using OpenTK.Graphics.OpenGL;
using Ryujinx.Common.Configuration;
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.OpenGL.Effects; using Ryujinx.Graphics.OpenGL.Effects;
using Ryujinx.Graphics.OpenGL.Effects.Smaa; using Ryujinx.Graphics.OpenGL.Effects.Smaa;
@@ -125,7 +125,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Msl.Instructions
Instruction.Add => "PreciseFAdd", Instruction.Add => "PreciseFAdd",
Instruction.Subtract => "PreciseFSub", Instruction.Subtract => "PreciseFSub",
Instruction.Multiply => "PreciseFMul", Instruction.Multiply => "PreciseFMul",
_ => throw new NotImplementedException()
}; };
return $"{func}({expr[0]}, {expr[1]})"; return $"{func}({expr[0]}, {expr[1]})";
@@ -52,7 +52,7 @@ namespace Ryujinx.Graphics.Vulkan.Queries
_current = new CounterQueueEvent(this, type, 0); _current = new CounterQueueEvent(this, type, 0);
_consumerThread = new Thread(EventConsumer) { Name = "CPU.CounterQueue." + (int)type }; _consumerThread = new Thread(EventConsumer);
_consumerThread.Start(); _consumerThread.Start();
} }
@@ -1,4 +1,3 @@
using Gommon;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
@@ -891,12 +890,7 @@ namespace Ryujinx.Graphics.Vulkan
private void PrintGpuInformation() private void PrintGpuInformation()
{ {
string gpuInfoMessage = $"{GpuRenderer} ({GpuVersion})"; Logger.Notice.Print(LogClass.Gpu, $"{GpuVendor} {GpuRenderer} ({GpuVersion})");
if (!GpuRenderer.StartsWithIgnoreCase(GpuVendor))
gpuInfoMessage = gpuInfoMessage.Prepend(GpuVendor);
Logger.Notice.Print(LogClass.Gpu, gpuInfoMessage);
Logger.Notice.Print(LogClass.Gpu, $"GPU Memory: {GetTotalGPUMemory() / (1024 * 1024)} MiB"); Logger.Notice.Print(LogClass.Gpu, $"GPU Memory: {GetTotalGPUMemory() / (1024 * 1024)} MiB");
} }
-1
View File
@@ -1,4 +1,3 @@
using Ryujinx.Common.Configuration;
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Vulkan.Effects; using Ryujinx.Graphics.Vulkan.Effects;
using Silk.NET.Vulkan; using Silk.NET.Vulkan;
@@ -1,4 +1,3 @@
using Ryujinx.Common.Configuration;
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
using System; using System;
+17 -19
View File
@@ -1034,16 +1034,16 @@ namespace Ryujinx.HLE.FileSystem
switch (fileName) switch (fileName)
{ {
case "prod.keys": case "prod.keys":
verified = VerifyKeys(lines, genericPattern); verified = verifyKeys(lines, genericPattern);
break; break;
case "title.keys": case "title.keys":
verified = VerifyKeys(lines, titlePattern); verified = verifyKeys(lines, titlePattern);
break; break;
case "console.keys": case "console.keys":
verified = VerifyKeys(lines, genericPattern); verified = verifyKeys(lines, genericPattern);
break; break;
case "dev.keys": case "dev.keys":
verified = VerifyKeys(lines, genericPattern); verified = verifyKeys(lines, genericPattern);
break; break;
default: default:
throw new FormatException($"Keys file name \"{fileName}\" not supported. Only \"prod.keys\", \"title.keys\", \"console.keys\", \"dev.keys\" are supported."); throw new FormatException($"Keys file name \"{fileName}\" not supported. Only \"prod.keys\", \"title.keys\", \"console.keys\", \"dev.keys\" are supported.");
@@ -1056,22 +1056,20 @@ namespace Ryujinx.HLE.FileSystem
{ {
throw new FileNotFoundException($"Keys file not found at \"{filePath}\"."); throw new FileNotFoundException($"Keys file not found at \"{filePath}\".");
} }
return;
bool VerifyKeys(string[] lines, string regex)
{
foreach (string line in lines)
{
if (!Regex.IsMatch(line, regex))
{
return false;
}
}
return true;
}
} }
private bool verifyKeys(string[] lines, string regex)
{
foreach (string line in lines)
{
if (!Regex.IsMatch(line, regex))
{
return false;
}
}
return true;
}
public bool AreKeysAlredyPresent(string pathToCheck) public bool AreKeysAlredyPresent(string pathToCheck)
{ {
string[] fileNames = { "prod.keys", "title.keys", "console.keys", "dev.keys" }; string[] fileNames = { "prod.keys", "title.keys", "console.keys", "dev.keys" };
+2 -8
View File
@@ -9,6 +9,7 @@ using Ryujinx.HLE.HOS.Services.Account.Acc;
using Ryujinx.HLE.HOS.SystemState; using Ryujinx.HLE.HOS.SystemState;
using Ryujinx.HLE.UI; using Ryujinx.HLE.UI;
using System; using System;
using VSyncMode = Ryujinx.Common.Configuration.VSyncMode;
namespace Ryujinx.HLE namespace Ryujinx.HLE
{ {
@@ -188,11 +189,6 @@ namespace Ryujinx.HLE
/// An action called when HLE force a refresh of output after docked mode changed. /// An action called when HLE force a refresh of output after docked mode changed.
/// </summary> /// </summary>
public Action RefreshInputConfig { internal get; set; } public Action RefreshInputConfig { internal get; set; }
/// <summary>
/// The desired hacky workarounds.
/// </summary>
public EnabledDirtyHack[] Hacks { internal get; set; }
public HLEConfiguration(VirtualFileSystem virtualFileSystem, public HLEConfiguration(VirtualFileSystem virtualFileSystem,
LibHacHorizonManager libHacHorizonManager, LibHacHorizonManager libHacHorizonManager,
@@ -223,8 +219,7 @@ namespace Ryujinx.HLE
bool multiplayerDisableP2p, bool multiplayerDisableP2p,
string multiplayerLdnPassphrase, string multiplayerLdnPassphrase,
string multiplayerLdnServer, string multiplayerLdnServer,
int customVSyncInterval, int customVSyncInterval)
EnabledDirtyHack[] dirtyHacks = null)
{ {
VirtualFileSystem = virtualFileSystem; VirtualFileSystem = virtualFileSystem;
LibHacHorizonManager = libHacHorizonManager; LibHacHorizonManager = libHacHorizonManager;
@@ -256,7 +251,6 @@ namespace Ryujinx.HLE
MultiplayerDisableP2p = multiplayerDisableP2p; MultiplayerDisableP2p = multiplayerDisableP2p;
MultiplayerLdnPassphrase = multiplayerLdnPassphrase; MultiplayerLdnPassphrase = multiplayerLdnPassphrase;
MultiplayerLdnServer = multiplayerLdnServer; MultiplayerLdnServer = multiplayerLdnServer;
Hacks = dirtyHacks ?? [];
} }
} }
} }
@@ -181,7 +181,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
is64Bits = true; is64Bits = true;
} }
HostThread = new Thread(ThreadStart) { Name = "HLE.KThread" }; HostThread = new Thread(ThreadStart);
Context = owner?.CreateExecutionContext() ?? new ProcessExecutionContext(); Context = owner?.CreateExecutionContext() ?? new ProcessExecutionContext();
@@ -1,4 +1,3 @@
using Gommon;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Common.Utilities; using Ryujinx.Common.Utilities;
@@ -7,13 +6,12 @@ using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq;
namespace Ryujinx.HLE.HOS.Services.Account.Acc namespace Ryujinx.HLE.HOS.Services.Account.Acc
{ {
public class AccountSaveDataManager class AccountSaveDataManager
{ {
private static readonly string _profilesJsonPath = Path.Join(AppDataManager.BaseDirPath, "system", "Profiles.json"); private readonly string _profilesJsonPath = Path.Join(AppDataManager.BaseDirPath, "system", "Profiles.json");
private static readonly ProfilesJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions()); private static readonly ProfilesJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
@@ -51,16 +49,6 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc
} }
} }
public static Optional<UserProfile> GetLastUsedUser()
{
ProfilesJson profilesJson = JsonHelper.DeserializeFromFile(_profilesJsonPath, _serializerContext.ProfilesJson);
return profilesJson.Profiles
.FindFirst(profile => profile.AccountState == AccountState.Open)
.Convert(profileJson => new UserProfile(new UserId(profileJson.UserId), profileJson.Name,
profileJson.Image, profileJson.LastModifiedTimestamp));
}
public void Save(ConcurrentDictionary<string, UserProfile> profiles) public void Save(ConcurrentDictionary<string, UserProfile> profiles)
{ {
ProfilesJson profilesJson = new() ProfilesJson profilesJson = new()
@@ -1,9 +1,6 @@
using LibHac; using LibHac;
using LibHac.Common; using LibHac.Common;
using LibHac.Sf; using LibHac.Sf;
using Ryujinx.Common;
using Ryujinx.Common.Configuration;
using System.Threading;
namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy
{ {
@@ -16,8 +13,6 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy
_baseStorage = SharedRef<LibHac.FsSrv.Sf.IStorage>.CreateMove(ref baseStorage); _baseStorage = SharedRef<LibHac.FsSrv.Sf.IStorage>.CreateMove(ref baseStorage);
} }
private const string Xc2TitleId = "0100e95004038000";
[CommandCmif(0)] [CommandCmif(0)]
// Read(u64 offset, u64 length) -> buffer<u8, 0x46, 0> buffer // Read(u64 offset, u64 length) -> buffer<u8, 0x46, 0> buffer
public ResultCode Read(ServiceCtx context) public ResultCode Read(ServiceCtx context)
@@ -38,13 +33,6 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy
using var region = context.Memory.GetWritableRegion(bufferAddress, (int)bufferLen, true); using var region = context.Memory.GetWritableRegion(bufferAddress, (int)bufferLen, true);
Result result = _baseStorage.Get.Read((long)offset, new OutBuffer(region.Memory.Span), (long)size); Result result = _baseStorage.Get.Read((long)offset, new OutBuffer(region.Memory.Span), (long)size);
if (context.Device.DirtyHacks.IsEnabled(DirtyHacks.Xc2MenuSoftlockFix) && TitleIDs.CurrentApplication.Value == Xc2TitleId)
{
// Add a load-bearing sleep to avoid XC2 softlock
// https://web.archive.org/web/20240728045136/https://github.com/Ryujinx/Ryujinx/issues/2357
Thread.Sleep(2);
}
return (ResultCode)result.Value; return (ResultCode)result.Value;
} }
@@ -114,10 +114,10 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption
} }
} }
string usedCharacterStr = Convert.ToHexString(usedCharacter); string usedCharacterStr = BitConverter.ToString(usedCharacter).Replace("-", "");
string variationStr = Convert.ToHexString(variation); string variationStr = BitConverter.ToString(variation).Replace("-", "");
string amiiboIDStr = Convert.ToHexString(amiiboID); string amiiboIDStr = BitConverter.ToString(amiiboID).Replace("-", "");
string setIDStr = Convert.ToHexString(setID); string setIDStr = BitConverter.ToString(setID).Replace("-", "");
string head = usedCharacterStr + variationStr; string head = usedCharacterStr + variationStr;
string tail = amiiboIDStr + setIDStr + "02"; string tail = amiiboIDStr + setIDStr + "02";
string finalID = head + tail; string finalID = head + tail;
@@ -289,8 +289,8 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption
private static void LogFinalData(byte[] titleId, byte[] appId, string head, string tail, string finalID, string nickName, DateTime initDateTime, DateTime writeDateTime, ushort settingsValue, ushort writeCounterValue, byte[] applicationAreas) private static void LogFinalData(byte[] titleId, byte[] appId, string head, string tail, string finalID, string nickName, DateTime initDateTime, DateTime writeDateTime, ushort settingsValue, ushort writeCounterValue, byte[] applicationAreas)
{ {
Logger.Debug?.Print(LogClass.ServiceNfp, $"Title ID: 0x{Convert.ToHexString(titleId)}"); Logger.Debug?.Print(LogClass.ServiceNfp, $"Title ID: 0x{BitConverter.ToString(titleId).Replace("-", "")}");
Logger.Debug?.Print(LogClass.ServiceNfp, $"Application Program ID: 0x{Convert.ToHexString(appId)}"); Logger.Debug?.Print(LogClass.ServiceNfp, $"Application Program ID: 0x{BitConverter.ToString(appId).Replace("-", "")}");
Logger.Debug?.Print(LogClass.ServiceNfp, $"Head: {head}"); Logger.Debug?.Print(LogClass.ServiceNfp, $"Head: {head}");
Logger.Debug?.Print(LogClass.ServiceNfp, $"Tail: {tail}"); Logger.Debug?.Print(LogClass.ServiceNfp, $"Tail: {tail}");
Logger.Debug?.Print(LogClass.ServiceNfp, $"Final ID: {finalID}"); Logger.Debug?.Print(LogClass.ServiceNfp, $"Final ID: {finalID}");
@@ -10,6 +10,7 @@ using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using VSyncMode = Ryujinx.Common.Configuration.VSyncMode;
namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
{ {
@@ -4,10 +4,8 @@ using LibHac.Fs.Fsa;
using LibHac.Loader; using LibHac.Loader;
using LibHac.Ns; using LibHac.Ns;
using LibHac.Tools.FsSystem; using LibHac.Tools.FsSystem;
using Ryujinx.Common;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Graphics.Gpu;
using Ryujinx.HLE.Loaders.Executables; using Ryujinx.HLE.Loaders.Executables;
using Ryujinx.Memory; using Ryujinx.Memory;
using System; using System;
@@ -104,7 +102,7 @@ namespace Ryujinx.HLE.Loaders.Processes.Extensions
} }
// Initialize GPU. // Initialize GPU.
GraphicsConfig.TitleId = programId.ToString("X16"); Graphics.Gpu.GraphicsConfig.TitleId = $"{programId:x16}";
device.Gpu.HostInitalized.Set(); device.Gpu.HostInitalized.Set();
if (!MemoryBlock.SupportsFlags(MemoryAllocationFlags.ViewCompatible)) if (!MemoryBlock.SupportsFlags(MemoryAllocationFlags.ViewCompatible))
@@ -6,9 +6,7 @@ using LibHac.Ns;
using LibHac.Tools.Fs; using LibHac.Tools.Fs;
using LibHac.Tools.FsSystem; using LibHac.Tools.FsSystem;
using LibHac.Tools.FsSystem.NcaUtils; using LibHac.Tools.FsSystem.NcaUtils;
using Ryujinx.Common;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Graphics.Gpu;
using Ryujinx.HLE.Loaders.Executables; using Ryujinx.HLE.Loaders.Executables;
using Ryujinx.HLE.Loaders.Processes.Extensions; using Ryujinx.HLE.Loaders.Processes.Extensions;
using System; using System;
@@ -61,8 +59,6 @@ namespace Ryujinx.HLE.Loaders.Processes
{ {
_latestPid = processResult.ProcessId; _latestPid = processResult.ProcessId;
TitleIDs.CurrentApplication.Value = processResult.ProgramIdText;
return true; return true;
} }
} }
@@ -90,8 +86,6 @@ namespace Ryujinx.HLE.Loaders.Processes
{ {
_latestPid = processResult.ProcessId; _latestPid = processResult.ProcessId;
TitleIDs.CurrentApplication.Value = processResult.ProgramIdText;
return true; return true;
} }
} }
@@ -119,8 +113,6 @@ namespace Ryujinx.HLE.Loaders.Processes
if (processResult.ProgramId > 0x01000000000007FF) if (processResult.ProgramId > 0x01000000000007FF)
{ {
_latestPid = processResult.ProcessId; _latestPid = processResult.ProcessId;
TitleIDs.CurrentApplication.Value = processResult.ProgramIdText;
} }
return true; return true;
@@ -140,8 +132,6 @@ namespace Ryujinx.HLE.Loaders.Processes
{ {
_latestPid = processResult.ProcessId; _latestPid = processResult.ProcessId;
TitleIDs.CurrentApplication.Value = processResult.ProgramIdText;
return true; return true;
} }
} }
@@ -193,17 +183,14 @@ namespace Ryujinx.HLE.Loaders.Processes
if (nacpData.Value.PresenceGroupId != 0) if (nacpData.Value.PresenceGroupId != 0)
{ {
programId = nacpData.Value.PresenceGroupId; programId = nacpData.Value.PresenceGroupId;
TitleIDs.CurrentApplication.Value = programId.ToString("X16");
} }
else if (nacpData.Value.SaveDataOwnerId != 0) else if (nacpData.Value.SaveDataOwnerId != 0)
{ {
programId = nacpData.Value.SaveDataOwnerId; programId = nacpData.Value.SaveDataOwnerId;
TitleIDs.CurrentApplication.Value = programId.ToString("X16");
} }
else if (nacpData.Value.AddOnContentBaseId != 0) else if (nacpData.Value.AddOnContentBaseId != 0)
{ {
programId = nacpData.Value.AddOnContentBaseId - 0x1000; programId = nacpData.Value.AddOnContentBaseId - 0x1000;
TitleIDs.CurrentApplication.Value = programId.ToString("X16");
} }
} }
@@ -217,7 +204,7 @@ namespace Ryujinx.HLE.Loaders.Processes
} }
// Explicitly null TitleId to disable the shader cache. // Explicitly null TitleId to disable the shader cache.
GraphicsConfig.TitleId = null; Graphics.Gpu.GraphicsConfig.TitleId = null;
_device.Gpu.HostInitalized.Set(); _device.Gpu.HostInitalized.Set();
ProcessResult processResult = ProcessLoaderHelper.LoadNsos(_device, ProcessResult processResult = ProcessLoaderHelper.LoadNsos(_device,
+1 -13
View File
@@ -2,7 +2,6 @@ using LibHac.Common;
using LibHac.Ns; using LibHac.Ns;
using Ryujinx.Audio.Backends.CompatLayer; using Ryujinx.Audio.Backends.CompatLayer;
using Ryujinx.Audio.Integration; using Ryujinx.Audio.Integration;
using Ryujinx.Common;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Graphics.Gpu; using Ryujinx.Graphics.Gpu;
using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.FileSystem;
@@ -18,8 +17,6 @@ namespace Ryujinx.HLE
{ {
public class Switch : IDisposable public class Switch : IDisposable
{ {
public static Switch Shared { get; private set; }
public HLEConfiguration Configuration { get; } public HLEConfiguration Configuration { get; }
public IHardwareDeviceDriver AudioDeviceDriver { get; } public IHardwareDeviceDriver AudioDeviceDriver { get; }
public MemoryBlock Memory { get; } public MemoryBlock Memory { get; }
@@ -40,8 +37,6 @@ namespace Ryujinx.HLE
public bool IsFrameAvailable => Gpu.Window.IsFrameAvailable; public bool IsFrameAvailable => Gpu.Window.IsFrameAvailable;
public DirtyHackCollection DirtyHacks { get; }
public Switch(HLEConfiguration configuration) public Switch(HLEConfiguration configuration)
{ {
ArgumentNullException.ThrowIfNull(configuration.GpuRenderer); ArgumentNullException.ThrowIfNull(configuration.GpuRenderer);
@@ -57,10 +52,9 @@ namespace Ryujinx.HLE
: MemoryAllocationFlags.Reserve | MemoryAllocationFlags.Mirrorable; : MemoryAllocationFlags.Reserve | MemoryAllocationFlags.Mirrorable;
#pragma warning disable IDE0055 // Disable formatting #pragma warning disable IDE0055 // Disable formatting
DirtyHacks = new DirtyHackCollection(Configuration.Hacks);
AudioDeviceDriver = new CompatLayerHardwareDeviceDriver(Configuration.AudioDeviceDriver); AudioDeviceDriver = new CompatLayerHardwareDeviceDriver(Configuration.AudioDeviceDriver);
Memory = new MemoryBlock(Configuration.MemoryConfiguration.ToDramSize(), memoryAllocationFlags); Memory = new MemoryBlock(Configuration.MemoryConfiguration.ToDramSize(), memoryAllocationFlags);
Gpu = new GpuContext(Configuration.GpuRenderer, DirtyHacks); Gpu = new GpuContext(Configuration.GpuRenderer);
System = new HOS.Horizon(this); System = new HOS.Horizon(this);
Statistics = new PerformanceStatistics(); Statistics = new PerformanceStatistics();
Hid = new Hid(this, System.HidStorage); Hid = new Hid(this, System.HidStorage);
@@ -78,11 +72,8 @@ namespace Ryujinx.HLE
System.EnablePtc = Configuration.EnablePtc; System.EnablePtc = Configuration.EnablePtc;
System.FsIntegrityCheckLevel = Configuration.FsIntegrityCheckLevel; System.FsIntegrityCheckLevel = Configuration.FsIntegrityCheckLevel;
System.GlobalAccessLogMode = Configuration.FsGlobalAccessLogMode; System.GlobalAccessLogMode = Configuration.FsGlobalAccessLogMode;
UpdateVSyncInterval(); UpdateVSyncInterval();
#pragma warning restore IDE0055 #pragma warning restore IDE0055
Shared = this;
} }
public void ProcessFrame() public void ProcessFrame()
@@ -151,9 +142,6 @@ namespace Ryujinx.HLE
AudioDeviceDriver.Dispose(); AudioDeviceDriver.Dispose();
FileSystem.Dispose(); FileSystem.Dispose();
Memory.Dispose(); Memory.Dispose();
TitleIDs.CurrentApplication.Value = null;
Shared = null;
} }
} }
} }
@@ -2,7 +2,7 @@ using Ryujinx.HLE.UI;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Ryujinx.Headless namespace Ryujinx.Headless.SDL2
{ {
/// <summary> /// <summary>
/// Headless text processing class, right now there is no way to forward the input to it. /// Headless text processing class, right now there is no way to forward the input to it.
@@ -1,6 +1,6 @@
using Ryujinx.HLE.UI; using Ryujinx.HLE.UI;
namespace Ryujinx.Headless namespace Ryujinx.Headless.SDL2
{ {
internal class HeadlessHostUiTheme : IHostUITheme internal class HeadlessHostUiTheme : IHostUITheme
{ {
@@ -5,7 +5,7 @@ using SharpMetal.QuartzCore;
using System.Runtime.Versioning; using System.Runtime.Versioning;
using static SDL2.SDL; using static SDL2.SDL;
namespace Ryujinx.Headless namespace Ryujinx.Headless.SDL2.Metal
{ {
[SupportedOSPlatform("macos")] [SupportedOSPlatform("macos")]
class MetalWindow : WindowBase class MetalWindow : WindowBase
@@ -7,7 +7,7 @@ using Ryujinx.Input.HLE;
using System; using System;
using static SDL2.SDL; using static SDL2.SDL;
namespace Ryujinx.Headless namespace Ryujinx.Headless.SDL2.OpenGL
{ {
class OpenGLWindow : WindowBase class OpenGLWindow : WindowBase
{ {
@@ -1,168 +1,13 @@
using CommandLine; using CommandLine;
using Gommon;
using Ryujinx.Ava.Utilities.Configuration;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Configuration.Hid;
using Ryujinx.HLE; using Ryujinx.HLE;
using Ryujinx.HLE.HOS.Services.Account.Acc;
using Ryujinx.HLE.HOS.SystemState; using Ryujinx.HLE.HOS.SystemState;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace Ryujinx.Headless namespace Ryujinx.Headless.SDL2
{ {
public class Options public class Options
{ {
public void InheritMainConfig(string[] originalArgs, ConfigurationState configurationState, out bool needsProfileSet)
{
needsProfileSet = NeedsOverride(nameof(UserProfile));
if (NeedsOverride(nameof(IsFullscreen)))
IsFullscreen = configurationState.UI.StartFullscreen;
if (NeedsOverride(nameof(EnableKeyboard)))
EnableKeyboard = configurationState.Hid.EnableKeyboard;
if (NeedsOverride(nameof(EnableMouse)))
EnableMouse = configurationState.Hid.EnableMouse;
if (NeedsOverride(nameof(HideCursorMode)))
HideCursorMode = configurationState.HideCursor;
if (NeedsOverride(nameof(DisablePTC)))
DisablePTC = !configurationState.System.EnablePtc;
if (NeedsOverride(nameof(EnableInternetAccess)))
EnableInternetAccess = configurationState.System.EnableInternetAccess;
if (NeedsOverride(nameof(DisableFsIntegrityChecks)))
DisableFsIntegrityChecks = configurationState.System.EnableFsIntegrityChecks;
if (NeedsOverride(nameof(FsGlobalAccessLogMode)))
FsGlobalAccessLogMode = configurationState.System.FsGlobalAccessLogMode;
if (NeedsOverride(nameof(VSyncMode)))
VSyncMode = configurationState.Graphics.VSyncMode;
if (NeedsOverride(nameof(CustomVSyncInterval)))
CustomVSyncInterval = configurationState.Graphics.CustomVSyncInterval;
if (NeedsOverride(nameof(DisableShaderCache)))
DisableShaderCache = !configurationState.Graphics.EnableShaderCache;
if (NeedsOverride(nameof(EnableTextureRecompression)))
EnableTextureRecompression = configurationState.Graphics.EnableTextureRecompression;
if (NeedsOverride(nameof(DisableDockedMode)))
DisableDockedMode = !configurationState.System.EnableDockedMode;
if (NeedsOverride(nameof(SystemLanguage)))
SystemLanguage = (SystemLanguage)(int)configurationState.System.Language.Value;
if (NeedsOverride(nameof(SystemRegion)))
SystemRegion = (RegionCode)(int)configurationState.System.Region.Value;
if (NeedsOverride(nameof(SystemTimeZone)))
SystemTimeZone = configurationState.System.TimeZone;
if (NeedsOverride(nameof(SystemTimeOffset)))
SystemTimeOffset = configurationState.System.SystemTimeOffset;
if (NeedsOverride(nameof(MemoryManagerMode)))
MemoryManagerMode = configurationState.System.MemoryManagerMode;
if (NeedsOverride(nameof(AudioVolume)))
AudioVolume = configurationState.System.AudioVolume;
if (NeedsOverride(nameof(UseHypervisor)) && OperatingSystem.IsMacOS())
UseHypervisor = configurationState.System.UseHypervisor;
if (NeedsOverride(nameof(MultiplayerLanInterfaceId)))
MultiplayerLanInterfaceId = configurationState.Multiplayer.LanInterfaceId;
if (NeedsOverride(nameof(DisableFileLog)))
DisableFileLog = !configurationState.Logger.EnableFileLog;
if (NeedsOverride(nameof(LoggingEnableDebug)))
LoggingEnableDebug = configurationState.Logger.EnableDebug;
if (NeedsOverride(nameof(LoggingDisableStub)))
LoggingDisableStub = !configurationState.Logger.EnableStub;
if (NeedsOverride(nameof(LoggingDisableInfo)))
LoggingDisableInfo = !configurationState.Logger.EnableInfo;
if (NeedsOverride(nameof(LoggingDisableWarning)))
LoggingDisableWarning = !configurationState.Logger.EnableWarn;
if (NeedsOverride(nameof(LoggingDisableError)))
LoggingDisableError = !configurationState.Logger.EnableError;
if (NeedsOverride(nameof(LoggingEnableTrace)))
LoggingEnableTrace = configurationState.Logger.EnableTrace;
if (NeedsOverride(nameof(LoggingDisableGuest)))
LoggingDisableGuest = !configurationState.Logger.EnableGuest;
if (NeedsOverride(nameof(LoggingEnableFsAccessLog)))
LoggingEnableFsAccessLog = configurationState.Logger.EnableFsAccessLog;
if (NeedsOverride(nameof(LoggingGraphicsDebugLevel)))
LoggingGraphicsDebugLevel = configurationState.Logger.GraphicsDebugLevel;
if (NeedsOverride(nameof(ResScale)))
ResScale = configurationState.Graphics.ResScale;
if (NeedsOverride(nameof(MaxAnisotropy)))
MaxAnisotropy = configurationState.Graphics.MaxAnisotropy;
if (NeedsOverride(nameof(AspectRatio)))
AspectRatio = configurationState.Graphics.AspectRatio;
if (NeedsOverride(nameof(BackendThreading)))
BackendThreading = configurationState.Graphics.BackendThreading;
if (NeedsOverride(nameof(DisableMacroHLE)))
DisableMacroHLE = !configurationState.Graphics.EnableMacroHLE;
if (NeedsOverride(nameof(GraphicsShadersDumpPath)))
GraphicsShadersDumpPath = configurationState.Graphics.ShadersDumpPath;
if (NeedsOverride(nameof(GraphicsBackend)))
GraphicsBackend = configurationState.Graphics.GraphicsBackend;
if (NeedsOverride(nameof(AntiAliasing)))
AntiAliasing = configurationState.Graphics.AntiAliasing;
if (NeedsOverride(nameof(ScalingFilter)))
ScalingFilter = configurationState.Graphics.ScalingFilter;
if (NeedsOverride(nameof(ScalingFilterLevel)))
ScalingFilterLevel = configurationState.Graphics.ScalingFilterLevel;
if (NeedsOverride(nameof(DramSize)))
DramSize = configurationState.System.DramSize;
if (NeedsOverride(nameof(IgnoreMissingServices)))
IgnoreMissingServices = configurationState.System.IgnoreMissingServices;
if (NeedsOverride(nameof(IgnoreControllerApplet)))
IgnoreControllerApplet = configurationState.IgnoreApplet;
return;
bool NeedsOverride(string argKey) => originalArgs.None(arg => arg.TrimStart('-').EqualsIgnoreCase(OptionName(argKey)));
string OptionName(string propertyName) =>
typeof(Options)!.GetProperty(propertyName)!.GetCustomAttribute<OptionAttribute>()!.LongName;
}
// General // General
[Option("use-main-config", Required = false, Default = false, HelpText = "Use the settings from what was configured via the UI.")]
public bool InheritConfig { get; set; }
[Option("root-data-dir", Required = false, HelpText = "Set the custom folder path for Ryujinx data.")] [Option("root-data-dir", Required = false, HelpText = "Set the custom folder path for Ryujinx data.")]
public string BaseDataDir { get; set; } public string BaseDataDir { get; set; }
@@ -250,10 +95,10 @@ namespace Ryujinx.Headless
[Option("hide-cursor", Required = false, Default = HideCursorMode.OnIdle, HelpText = "Change when the cursor gets hidden.")] [Option("hide-cursor", Required = false, Default = HideCursorMode.OnIdle, HelpText = "Change when the cursor gets hidden.")]
public HideCursorMode HideCursorMode { get; set; } public HideCursorMode HideCursorMode { get; set; }
[Option("list-input-profiles", Required = false, HelpText = "List input profiles.")] [Option("list-input-profiles", Required = false, HelpText = "List inputs profiles.")]
public bool ListInputProfiles { get; set; } public bool ListInputProfiles { get; set; }
[Option("list-input-ids", Required = false, HelpText = "List input IDs.")] [Option("list-inputs-ids", Required = false, HelpText = "List inputs ids.")]
public bool ListInputIds { get; set; } public bool ListInputIds { get; set; }
// System // System
@@ -327,7 +172,7 @@ namespace Ryujinx.Headless
public bool LoggingDisableWarning { get; set; } public bool LoggingDisableWarning { get; set; }
[Option("disable-error-logs", Required = false, HelpText = "Disables printing error log messages.")] [Option("disable-error-logs", Required = false, HelpText = "Disables printing error log messages.")]
public bool LoggingDisableError { get; set; } public bool LoggingEnableError { get; set; }
[Option("enable-trace-logs", Required = false, Default = false, HelpText = "Enables printing trace log messages.")] [Option("enable-trace-logs", Required = false, Default = false, HelpText = "Enables printing trace log messages.")]
public bool LoggingEnableTrace { get; set; } public bool LoggingEnableTrace { get; set; }
@@ -370,7 +215,7 @@ namespace Ryujinx.Headless
[Option("anti-aliasing", Required = false, Default = AntiAliasing.None, HelpText = "Set the type of anti aliasing being used. [None|Fxaa|SmaaLow|SmaaMedium|SmaaHigh|SmaaUltra]")] [Option("anti-aliasing", Required = false, Default = AntiAliasing.None, HelpText = "Set the type of anti aliasing being used. [None|Fxaa|SmaaLow|SmaaMedium|SmaaHigh|SmaaUltra]")]
public AntiAliasing AntiAliasing { get; set; } public AntiAliasing AntiAliasing { get; set; }
[Option("scaling-filter", Required = false, Default = ScalingFilter.Bilinear, HelpText = "Set the scaling filter. [Bilinear|Nearest|Fsr|Area]")] [Option("scaling-filter", Required = false, Default = ScalingFilter.Bilinear, HelpText = "Set the scaling filter. [Bilinear|Nearest|Fsr]")]
public ScalingFilter ScalingFilter { get; set; } public ScalingFilter ScalingFilter { get; set; }
[Option("scaling-filter-level", Required = false, Default = 0, HelpText = "Set the scaling filter intensity (currently only applies to FSR). [0-100]")] [Option("scaling-filter-level", Required = false, Default = 0, HelpText = "Set the scaling filter intensity (currently only applies to FSR). [0-100]")]
@@ -1,10 +1,13 @@
using CommandLine; using CommandLine;
using Gommon; using Gommon;
using Ryujinx.Ava; using LibHac.Tools.FsSystem;
using Ryujinx.Ava.Utilities.Configuration; using Ryujinx.Audio.Backends.SDL2;
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Configuration.Hid; using Ryujinx.Common.Configuration.Hid;
using Ryujinx.Common.Configuration.Hid.Controller;
using Ryujinx.Common.Configuration.Hid.Controller.Motion;
using Ryujinx.Common.Configuration.Hid.Keyboard;
using Ryujinx.Common.GraphicsDriver; using Ryujinx.Common.GraphicsDriver;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Common.Logging.Targets; using Ryujinx.Common.Logging.Targets;
@@ -12,9 +15,16 @@ using Ryujinx.Common.SystemInterop;
using Ryujinx.Common.Utilities; using Ryujinx.Common.Utilities;
using Ryujinx.Cpu; using Ryujinx.Cpu;
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.GAL.Multithreading;
using Ryujinx.Graphics.Gpu; using Ryujinx.Graphics.Gpu;
using Ryujinx.Graphics.Gpu.Shader; using Ryujinx.Graphics.Gpu.Shader;
using Ryujinx.Graphics.Metal;
using Ryujinx.Graphics.OpenGL;
using Ryujinx.Graphics.Vulkan;
using Ryujinx.Graphics.Vulkan.MoltenVK; using Ryujinx.Graphics.Vulkan.MoltenVK;
using Ryujinx.Headless.SDL2.Metal;
using Ryujinx.Headless.SDL2.OpenGL;
using Ryujinx.Headless.SDL2.Vulkan;
using Ryujinx.HLE; using Ryujinx.HLE;
using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.FileSystem;
using Ryujinx.HLE.HOS; using Ryujinx.HLE.HOS;
@@ -23,15 +33,22 @@ using Ryujinx.Input;
using Ryujinx.Input.HLE; using Ryujinx.Input.HLE;
using Ryujinx.Input.SDL2; using Ryujinx.Input.SDL2;
using Ryujinx.SDL2.Common; using Ryujinx.SDL2.Common;
using Silk.NET.Vulkan;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Text.Json;
using System.Threading; using System.Threading;
using ConfigGamepadInputId = Ryujinx.Common.Configuration.Hid.Controller.GamepadInputId;
using ConfigStickInputId = Ryujinx.Common.Configuration.Hid.Controller.StickInputId;
using Key = Ryujinx.Common.Configuration.Hid.Key;
namespace Ryujinx.Headless namespace Ryujinx.Headless.SDL2
{ {
public partial class HeadlessRyujinx class Program
{ {
public static string Version { get; private set; }
private static VirtualFileSystem _virtualFileSystem; private static VirtualFileSystem _virtualFileSystem;
private static ContentManager _contentManager; private static ContentManager _contentManager;
private static AccountManager _accountManager; private static AccountManager _accountManager;
@@ -41,18 +58,20 @@ namespace Ryujinx.Headless
private static Switch _emulationContext; private static Switch _emulationContext;
private static WindowBase _window; private static WindowBase _window;
private static WindowsMultimediaTimerResolution _windowsMultimediaTimerResolution; private static WindowsMultimediaTimerResolution _windowsMultimediaTimerResolution;
private static List<InputConfig> _inputConfiguration = []; private static List<InputConfig> _inputConfiguration;
private static bool _enableKeyboard; private static bool _enableKeyboard;
private static bool _enableMouse; private static bool _enableMouse;
private static readonly InputConfigJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions()); private static readonly InputConfigJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
public static void Entrypoint(string[] args) static void Main(string[] args)
{ {
Version = ReleaseInformation.Version;
// Make process DPI aware for proper window sizing on high-res screens. // Make process DPI aware for proper window sizing on high-res screens.
ForceDpiAware.Windows(); ForceDpiAware.Windows();
Console.Title = $"Ryujinx Console {Program.Version} (Headless)"; Console.Title = $"Ryujinx Console {Version} (Headless SDL2)";
if (OperatingSystem.IsMacOS() || OperatingSystem.IsLinux()) if (OperatingSystem.IsMacOS() || OperatingSystem.IsLinux())
{ {
@@ -80,7 +99,7 @@ namespace Ryujinx.Headless
} }
Parser.Default.ParseArguments<Options>(args) Parser.Default.ParseArguments<Options>(args)
.WithParsed(options => Load(args, options)) .WithParsed(Load)
.WithNotParsed(errors => .WithNotParsed(errors =>
{ {
Logger.Error?.PrintMsg(LogClass.Application, "Error parsing command-line arguments:"); Logger.Error?.PrintMsg(LogClass.Application, "Error parsing command-line arguments:");
@@ -88,81 +107,239 @@ namespace Ryujinx.Headless
errors.ForEach(err => Logger.Error?.PrintMsg(LogClass.Application, $" - {err.Tag}")); errors.ForEach(err => Logger.Error?.PrintMsg(LogClass.Application, $" - {err.Tag}"));
}); });
} }
public static void ReloadConfig(string customConfigPath = null) private static InputConfig HandlePlayerConfiguration(string inputProfileName, string inputId, PlayerIndex index)
{ {
string localConfigurationPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ReleaseInformation.ConfigName); if (inputId == null)
string appDataConfigurationPath = Path.Combine(AppDataManager.BaseDirPath, ReleaseInformation.ConfigName);
string configurationPath = null;
// Now load the configuration as the other subsystems are now registered
if (customConfigPath != null && File.Exists(customConfigPath))
{ {
configurationPath = customConfigPath; if (index == PlayerIndex.Player1)
}
else if (File.Exists(localConfigurationPath))
{
configurationPath = localConfigurationPath;
}
else if (File.Exists(appDataConfigurationPath))
{
configurationPath = appDataConfigurationPath;
}
if (configurationPath == null)
{
// No configuration, we load the default values and save it to disk
configurationPath = appDataConfigurationPath;
Logger.Notice.Print(LogClass.Application, $"No configuration file found. Saving default configuration to: {configurationPath}");
ConfigurationState.Instance.LoadDefault();
ConfigurationState.Instance.ToFileFormat().SaveConfig(configurationPath);
}
else
{
Logger.Notice.Print(LogClass.Application, $"Loading configuration from: {configurationPath}");
if (ConfigurationFileFormat.TryLoad(configurationPath, out ConfigurationFileFormat configurationFileFormat))
{ {
ConfigurationState.Instance.Load(configurationFileFormat, configurationPath); Logger.Info?.Print(LogClass.Application, $"{index} not configured, defaulting to default keyboard.");
// Default to keyboard
inputId = "0";
} }
else else
{ {
Logger.Warning?.PrintMsg(LogClass.Application, $"Failed to load config! Loading the default config instead.\nFailed config location: {configurationPath}"); Logger.Info?.Print(LogClass.Application, $"{index} not configured");
ConfigurationState.Instance.LoadDefault(); return null;
} }
} }
IGamepad gamepad = _inputManager.KeyboardDriver.GetGamepad(inputId);
bool isKeyboard = true;
if (gamepad == null)
{
gamepad = _inputManager.GamepadDriver.GetGamepad(inputId);
isKeyboard = false;
if (gamepad == null)
{
Logger.Error?.Print(LogClass.Application, $"{index} gamepad not found (\"{inputId}\")");
return null;
}
}
string gamepadName = gamepad.Name;
gamepad.Dispose();
InputConfig config;
if (inputProfileName == null || inputProfileName.Equals("default"))
{
if (isKeyboard)
{
config = new StandardKeyboardInputConfig
{
Version = InputConfig.CurrentVersion,
Backend = InputBackendType.WindowKeyboard,
Id = null,
ControllerType = ControllerType.JoyconPair,
LeftJoycon = new LeftJoyconCommonConfig<Key>
{
DpadUp = Key.Up,
DpadDown = Key.Down,
DpadLeft = Key.Left,
DpadRight = Key.Right,
ButtonMinus = Key.Minus,
ButtonL = Key.E,
ButtonZl = Key.Q,
ButtonSl = Key.Unbound,
ButtonSr = Key.Unbound,
},
LeftJoyconStick = new JoyconConfigKeyboardStick<Key>
{
StickUp = Key.W,
StickDown = Key.S,
StickLeft = Key.A,
StickRight = Key.D,
StickButton = Key.F,
},
RightJoycon = new RightJoyconCommonConfig<Key>
{
ButtonA = Key.Z,
ButtonB = Key.X,
ButtonX = Key.C,
ButtonY = Key.V,
ButtonPlus = Key.Plus,
ButtonR = Key.U,
ButtonZr = Key.O,
ButtonSl = Key.Unbound,
ButtonSr = Key.Unbound,
},
RightJoyconStick = new JoyconConfigKeyboardStick<Key>
{
StickUp = Key.I,
StickDown = Key.K,
StickLeft = Key.J,
StickRight = Key.L,
StickButton = Key.H,
},
};
}
else
{
bool isNintendoStyle = gamepadName.Contains("Nintendo");
config = new StandardControllerInputConfig
{
Version = InputConfig.CurrentVersion,
Backend = InputBackendType.GamepadSDL2,
Id = null,
ControllerType = ControllerType.JoyconPair,
DeadzoneLeft = 0.1f,
DeadzoneRight = 0.1f,
RangeLeft = 1.0f,
RangeRight = 1.0f,
TriggerThreshold = 0.5f,
LeftJoycon = new LeftJoyconCommonConfig<ConfigGamepadInputId>
{
DpadUp = ConfigGamepadInputId.DpadUp,
DpadDown = ConfigGamepadInputId.DpadDown,
DpadLeft = ConfigGamepadInputId.DpadLeft,
DpadRight = ConfigGamepadInputId.DpadRight,
ButtonMinus = ConfigGamepadInputId.Minus,
ButtonL = ConfigGamepadInputId.LeftShoulder,
ButtonZl = ConfigGamepadInputId.LeftTrigger,
ButtonSl = ConfigGamepadInputId.Unbound,
ButtonSr = ConfigGamepadInputId.Unbound,
},
LeftJoyconStick = new JoyconConfigControllerStick<ConfigGamepadInputId, ConfigStickInputId>
{
Joystick = ConfigStickInputId.Left,
StickButton = ConfigGamepadInputId.LeftStick,
InvertStickX = false,
InvertStickY = false,
Rotate90CW = false,
},
RightJoycon = new RightJoyconCommonConfig<ConfigGamepadInputId>
{
ButtonA = isNintendoStyle ? ConfigGamepadInputId.A : ConfigGamepadInputId.B,
ButtonB = isNintendoStyle ? ConfigGamepadInputId.B : ConfigGamepadInputId.A,
ButtonX = isNintendoStyle ? ConfigGamepadInputId.X : ConfigGamepadInputId.Y,
ButtonY = isNintendoStyle ? ConfigGamepadInputId.Y : ConfigGamepadInputId.X,
ButtonPlus = ConfigGamepadInputId.Plus,
ButtonR = ConfigGamepadInputId.RightShoulder,
ButtonZr = ConfigGamepadInputId.RightTrigger,
ButtonSl = ConfigGamepadInputId.Unbound,
ButtonSr = ConfigGamepadInputId.Unbound,
},
RightJoyconStick = new JoyconConfigControllerStick<ConfigGamepadInputId, ConfigStickInputId>
{
Joystick = ConfigStickInputId.Right,
StickButton = ConfigGamepadInputId.RightStick,
InvertStickX = false,
InvertStickY = false,
Rotate90CW = false,
},
Motion = new StandardMotionConfigController
{
MotionBackend = MotionInputBackendType.GamepadDriver,
EnableMotion = true,
Sensitivity = 100,
GyroDeadzone = 1,
},
Rumble = new RumbleConfigController
{
StrongRumble = 1f,
WeakRumble = 1f,
EnableRumble = false,
},
};
}
}
else
{
string profileBasePath;
if (isKeyboard)
{
profileBasePath = Path.Combine(AppDataManager.ProfilesDirPath, "keyboard");
}
else
{
profileBasePath = Path.Combine(AppDataManager.ProfilesDirPath, "controller");
}
string path = Path.Combine(profileBasePath, inputProfileName + ".json");
if (!File.Exists(path))
{
Logger.Error?.Print(LogClass.Application, $"Input profile \"{inputProfileName}\" not found for \"{inputId}\"");
return null;
}
try
{
config = JsonHelper.DeserializeFromFile(path, _serializerContext.InputConfig);
}
catch (JsonException)
{
Logger.Error?.Print(LogClass.Application, $"Input profile \"{inputProfileName}\" parsing failed for \"{inputId}\"");
return null;
}
}
config.Id = inputId;
config.PlayerIndex = index;
string inputTypeName = isKeyboard ? "Keyboard" : "Gamepad";
Logger.Info?.Print(LogClass.Application, $"{config.PlayerIndex} configured with {inputTypeName} \"{config.Id}\"");
// If both stick ranges are 0 (usually indicative of an outdated profile load) then both sticks will be set to 1.0.
if (config is StandardControllerInputConfig controllerConfig)
{
if (controllerConfig.RangeLeft <= 0.0f && controllerConfig.RangeRight <= 0.0f)
{
controllerConfig.RangeLeft = 1.0f;
controllerConfig.RangeRight = 1.0f;
Logger.Info?.Print(LogClass.Application, $"{config.PlayerIndex} stick range reset. Save the profile now to update your configuration");
}
}
return config;
} }
static void Load(string[] originalArgs, Options option) static void Load(Options option)
{ {
Initialize();
bool useLastUsedProfile = false;
if (option.InheritConfig)
{
option.InheritMainConfig(originalArgs, ConfigurationState.Instance, out useLastUsedProfile);
}
AppDataManager.Initialize(option.BaseDataDir); AppDataManager.Initialize(option.BaseDataDir);
if (useLastUsedProfile && AccountSaveDataManager.GetLastUsedUser().TryGet(out var profile))
option.UserProfile = profile.Name;
// Check if keys exists.
if (!File.Exists(Path.Combine(AppDataManager.KeysDirPath, "prod.keys")))
{
if (!(AppDataManager.Mode == AppDataManager.LaunchMode.UserProfile && File.Exists(Path.Combine(AppDataManager.KeysDirPathUser, "prod.keys"))))
{
Logger.Error?.Print(LogClass.Application, "Keys not found");
}
}
ReloadConfig();
_virtualFileSystem = VirtualFileSystem.CreateInstance(); _virtualFileSystem = VirtualFileSystem.CreateInstance();
_libHacHorizonManager = new LibHacHorizonManager(); _libHacHorizonManager = new LibHacHorizonManager();
@@ -177,7 +354,7 @@ namespace Ryujinx.Headless
_inputManager = new InputManager(new SDL2KeyboardDriver(), new SDL2GamepadDriver()); _inputManager = new InputManager(new SDL2KeyboardDriver(), new SDL2GamepadDriver());
GraphicsConfig.EnableShaderCache = !option.DisableShaderCache; GraphicsConfig.EnableShaderCache = true;
if (OperatingSystem.IsMacOS()) if (OperatingSystem.IsMacOS())
{ {
@@ -188,13 +365,15 @@ namespace Ryujinx.Headless
} }
} }
IGamepad gamepad;
if (option.ListInputIds) if (option.ListInputIds)
{ {
Logger.Info?.Print(LogClass.Application, "Input Ids:"); Logger.Info?.Print(LogClass.Application, "Input Ids:");
foreach (string id in _inputManager.KeyboardDriver.GamepadsIds) foreach (string id in _inputManager.KeyboardDriver.GamepadsIds)
{ {
IGamepad gamepad = _inputManager.KeyboardDriver.GetGamepad(id); gamepad = _inputManager.KeyboardDriver.GetGamepad(id);
Logger.Info?.Print(LogClass.Application, $"- {id} (\"{gamepad.Name}\")"); Logger.Info?.Print(LogClass.Application, $"- {id} (\"{gamepad.Name}\")");
@@ -203,7 +382,7 @@ namespace Ryujinx.Headless
foreach (string id in _inputManager.GamepadDriver.GamepadsIds) foreach (string id in _inputManager.GamepadDriver.GamepadsIds)
{ {
IGamepad gamepad = _inputManager.GamepadDriver.GetGamepad(id); gamepad = _inputManager.GamepadDriver.GetGamepad(id);
Logger.Info?.Print(LogClass.Application, $"- {id} (\"{gamepad.Name}\")"); Logger.Info?.Print(LogClass.Application, $"- {id} (\"{gamepad.Name}\")");
@@ -220,7 +399,7 @@ namespace Ryujinx.Headless
return; return;
} }
_inputConfiguration ??= []; _inputConfiguration = new List<InputConfig>();
_enableKeyboard = option.EnableKeyboard; _enableKeyboard = option.EnableKeyboard;
_enableMouse = option.EnableMouse; _enableMouse = option.EnableMouse;
@@ -233,9 +412,9 @@ namespace Ryujinx.Headless
_inputConfiguration.Add(inputConfig); _inputConfiguration.Add(inputConfig);
} }
} }
LoadPlayerConfiguration(option.InputProfile1Name, option.InputId1, PlayerIndex.Player1); LoadPlayerConfiguration(option.InputProfile1Name, option.InputId1, PlayerIndex.Player1);
LoadPlayerConfiguration(option.InputProfile2Name, option.InputId2, PlayerIndex.Player2); LoadPlayerConfiguration(option.InputProfile2Name, option.InputId2, PlayerIndex.Player2);
LoadPlayerConfiguration(option.InputProfile3Name, option.InputId3, PlayerIndex.Player3); LoadPlayerConfiguration(option.InputProfile3Name, option.InputId3, PlayerIndex.Player3);
LoadPlayerConfiguration(option.InputProfile4Name, option.InputId4, PlayerIndex.Player4); LoadPlayerConfiguration(option.InputProfile4Name, option.InputId4, PlayerIndex.Player4);
LoadPlayerConfiguration(option.InputProfile5Name, option.InputId5, PlayerIndex.Player5); LoadPlayerConfiguration(option.InputProfile5Name, option.InputId5, PlayerIndex.Player5);
@@ -243,7 +422,6 @@ namespace Ryujinx.Headless
LoadPlayerConfiguration(option.InputProfile7Name, option.InputId7, PlayerIndex.Player7); LoadPlayerConfiguration(option.InputProfile7Name, option.InputId7, PlayerIndex.Player7);
LoadPlayerConfiguration(option.InputProfile8Name, option.InputId8, PlayerIndex.Player8); LoadPlayerConfiguration(option.InputProfile8Name, option.InputId8, PlayerIndex.Player8);
LoadPlayerConfiguration(option.InputProfileHandheldName, option.InputIdHandheld, PlayerIndex.Handheld); LoadPlayerConfiguration(option.InputProfileHandheldName, option.InputIdHandheld, PlayerIndex.Handheld);
if (_inputConfiguration.Count == 0) if (_inputConfiguration.Count == 0)
{ {
@@ -255,7 +433,7 @@ namespace Ryujinx.Headless
Logger.SetEnable(LogLevel.Stub, !option.LoggingDisableStub); Logger.SetEnable(LogLevel.Stub, !option.LoggingDisableStub);
Logger.SetEnable(LogLevel.Info, !option.LoggingDisableInfo); Logger.SetEnable(LogLevel.Info, !option.LoggingDisableInfo);
Logger.SetEnable(LogLevel.Warning, !option.LoggingDisableWarning); Logger.SetEnable(LogLevel.Warning, !option.LoggingDisableWarning);
Logger.SetEnable(LogLevel.Error, !option.LoggingDisableError); Logger.SetEnable(LogLevel.Error, option.LoggingEnableError);
Logger.SetEnable(LogLevel.Trace, option.LoggingEnableTrace); Logger.SetEnable(LogLevel.Trace, option.LoggingEnableTrace);
Logger.SetEnable(LogLevel.Guest, !option.LoggingDisableGuest); Logger.SetEnable(LogLevel.Guest, !option.LoggingDisableGuest);
Logger.SetEnable(LogLevel.AccessLog, option.LoggingEnableFsAccessLog); Logger.SetEnable(LogLevel.AccessLog, option.LoggingEnableFsAccessLog);
@@ -344,6 +522,88 @@ namespace Ryujinx.Headless
}; };
} }
private static IRenderer CreateRenderer(Options options, WindowBase window)
{
if (options.GraphicsBackend == GraphicsBackend.Vulkan && window is VulkanWindow vulkanWindow)
{
string preferredGpuId = string.Empty;
Vk api = Vk.GetApi();
if (!string.IsNullOrEmpty(options.PreferredGPUVendor))
{
string preferredGpuVendor = options.PreferredGPUVendor.ToLowerInvariant();
var devices = VulkanRenderer.GetPhysicalDevices(api);
foreach (var device in devices)
{
if (device.Vendor.ToLowerInvariant() == preferredGpuVendor)
{
preferredGpuId = device.Id;
break;
}
}
}
return new VulkanRenderer(
api,
(instance, vk) => new SurfaceKHR((ulong)(vulkanWindow.CreateWindowSurface(instance.Handle))),
vulkanWindow.GetRequiredInstanceExtensions,
preferredGpuId);
}
if (options.GraphicsBackend == GraphicsBackend.Metal && window is MetalWindow metalWindow && OperatingSystem.IsMacOS())
{
return new MetalRenderer(metalWindow.GetLayer);
}
return new OpenGLRenderer();
}
private static Switch InitializeEmulationContext(WindowBase window, IRenderer renderer, Options options)
{
BackendThreading threadingMode = options.BackendThreading;
bool threadedGAL = threadingMode == BackendThreading.On || (threadingMode == BackendThreading.Auto && renderer.PreferThreading);
if (threadedGAL)
{
renderer = new ThreadedRenderer(renderer);
}
HLEConfiguration configuration = new(_virtualFileSystem,
_libHacHorizonManager,
_contentManager,
_accountManager,
_userChannelPersistence,
renderer,
new SDL2HardwareDeviceDriver(),
options.DramSize,
window,
options.SystemLanguage,
options.SystemRegion,
options.VSyncMode,
!options.DisableDockedMode,
!options.DisablePTC,
options.EnableInternetAccess,
!options.DisableFsIntegrityChecks ? IntegrityCheckLevel.ErrorOnInvalid : IntegrityCheckLevel.None,
options.FsGlobalAccessLogMode,
options.SystemTimeOffset,
options.SystemTimeZone,
options.MemoryManagerMode,
options.IgnoreMissingServices,
options.AspectRatio,
options.AudioVolume,
options.UseHypervisor ?? true,
options.MultiplayerLanInterfaceId,
Common.Configuration.Multiplayer.MultiplayerMode.Disabled,
false,
string.Empty,
string.Empty,
options.CustomVSyncInterval);
return new Switch(configuration);
}
private static void ExecutionEntrypoint() private static void ExecutionEntrypoint()
{ {
if (OperatingSystem.IsWindows()) if (OperatingSystem.IsWindows())
@@ -0,0 +1,73 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<RuntimeIdentifiers>win-x64;osx-x64;linux-x64</RuntimeIdentifiers>
<OutputType>Exe</OutputType>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Version>1.0.0-dirty</Version>
<DefineConstants Condition=" '$(ExtraDefineConstants)' != '' ">$(DefineConstants);$(ExtraDefineConstants)</DefineConstants>
<SigningCertificate Condition=" '$(SigningCertificate)' == '' ">-</SigningCertificate>
<TieredPGO>true</TieredPGO>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="OpenTK.Core" />
<PackageReference Include="Ryujinx.Graphics.Nvdec.Dependencies" />
</ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent" Condition="$([MSBuild]::IsOSPlatform('OSX'))">
<Exec Command="codesign --entitlements '$(ProjectDir)..\..\distribution\macos\entitlements.xml' -f -s $(SigningCertificate) '$(TargetDir)$(TargetName)'" />
</Target>
<ItemGroup>
<ProjectReference Include="..\Ryujinx.Graphics.Vulkan\Ryujinx.Graphics.Vulkan.csproj" />
<ProjectReference Include="..\Ryujinx.Input\Ryujinx.Input.csproj" />
<ProjectReference Include="..\Ryujinx.Input.SDL2\Ryujinx.Input.SDL2.csproj" />
<ProjectReference Include="..\Ryujinx.Audio.Backends.SDL2\Ryujinx.Audio.Backends.SDL2.csproj" />
<ProjectReference Include="..\Ryujinx.Common\Ryujinx.Common.csproj" />
<ProjectReference Include="..\Ryujinx.HLE\Ryujinx.HLE.csproj" />
<ProjectReference Include="..\ARMeilleure\ARMeilleure.csproj" />
<ProjectReference Include="..\Ryujinx.Graphics.OpenGL\Ryujinx.Graphics.OpenGL.csproj" />
<ProjectReference Include="..\Ryujinx.Graphics.Metal\Ryujinx.Graphics.Metal.csproj" />
<ProjectReference Include="..\Ryujinx.Graphics.Gpu\Ryujinx.Graphics.Gpu.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="CommandLineParser" />
<PackageReference Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'win-x64'" />
</ItemGroup>
<ItemGroup>
<Content Include="..\..\distribution\legal\THIRDPARTY.md">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<TargetPath>THIRDPARTY.md</TargetPath>
</Content>
<Content Include="..\..\LICENSE.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<TargetPath>LICENSE.txt</TargetPath>
</Content>
</ItemGroup>
<ItemGroup Condition="'$(RuntimeIdentifier)' == 'linux-x64' OR '$(RuntimeIdentifier)' == 'linux-arm64' OR ('$(RuntimeIdentifier)' == '' AND $([MSBuild]::IsOSPlatform('Linux')))">
<Content Include="..\..\distribution\linux\Ryujinx.sh">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Ryujinx.bmp" />
</ItemGroup>
<!-- Due to .net core 3.1 embedded resource loading -->
<PropertyGroup>
<EmbeddedResourceUseDependentUponConvention>false</EmbeddedResourceUseDependentUponConvention>
<ApplicationIcon>..\Ryujinx\Ryujinx.ico</ApplicationIcon>
</PropertyGroup>
<PropertyGroup Condition="'$(RuntimeIdentifier)' != ''">
<PublishSingleFile>true</PublishSingleFile>
<PublishTrimmed>true</PublishTrimmed>
<TrimMode>partial</TrimMode>
</PropertyGroup>
</Project>
Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

@@ -1,6 +1,6 @@
using System; using System;
namespace Ryujinx.Headless namespace Ryujinx.Headless.SDL2
{ {
class StatusUpdatedEventArgs( class StatusUpdatedEventArgs(
string vSyncMode, string vSyncMode,
@@ -6,7 +6,7 @@ using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using static SDL2.SDL; using static SDL2.SDL;
namespace Ryujinx.Headless namespace Ryujinx.Headless.SDL2.Vulkan
{ {
class VulkanWindow : WindowBase class VulkanWindow : WindowBase
{ {
@@ -1,6 +1,5 @@
using Humanizer; using Humanizer;
using LibHac.Tools.Fs; using LibHac.Tools.Fs;
using Ryujinx.Ava;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Configuration.Hid; using Ryujinx.Common.Configuration.Hid;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
@@ -27,7 +26,7 @@ using AntiAliasing = Ryujinx.Common.Configuration.AntiAliasing;
using ScalingFilter = Ryujinx.Common.Configuration.ScalingFilter; using ScalingFilter = Ryujinx.Common.Configuration.ScalingFilter;
using Switch = Ryujinx.HLE.Switch; using Switch = Ryujinx.HLE.Switch;
namespace Ryujinx.Headless namespace Ryujinx.Headless.SDL2
{ {
abstract partial class WindowBase : IHostUIHandler, IDisposable abstract partial class WindowBase : IHostUIHandler, IDisposable
{ {
@@ -137,7 +136,7 @@ namespace Ryujinx.Headless
private void SetWindowIcon() private void SetWindowIcon()
{ {
Stream iconStream = typeof(Program).Assembly.GetManifestResourceStream("HeadlessLogo"); Stream iconStream = typeof(WindowBase).Assembly.GetManifestResourceStream("Ryujinx.Headless.SDL2.Ryujinx.bmp");
byte[] iconBytes = new byte[iconStream!.Length]; byte[] iconBytes = new byte[iconStream!.Length];
if (iconStream.Read(iconBytes, 0, iconBytes.Length) != iconBytes.Length) if (iconStream.Read(iconBytes, 0, iconBytes.Length) != iconBytes.Length)
@@ -255,12 +254,12 @@ namespace Ryujinx.Headless
private void SetAntiAliasing() private void SetAntiAliasing()
{ {
Renderer?.Window.SetAntiAliasing(AntiAliasing); Renderer?.Window.SetAntiAliasing((Graphics.GAL.AntiAliasing)AntiAliasing);
} }
private void SetScalingFilter() private void SetScalingFilter()
{ {
Renderer?.Window.SetScalingFilter(ScalingFilter); Renderer?.Window.SetScalingFilter((Graphics.GAL.ScalingFilter)ScalingFilter);
Renderer?.Window.SetScalingFilterLevel(ScalingFilterLevel); Renderer?.Window.SetScalingFilterLevel(ScalingFilterLevel);
} }
@@ -319,7 +318,7 @@ namespace Ryujinx.Headless
Device.VSyncMode.ToString(), Device.VSyncMode.ToString(),
dockedMode, dockedMode,
Device.Configuration.AspectRatio.ToText(), Device.Configuration.AspectRatio.ToText(),
$"{Device.Statistics.GetGameFrameRate():00.00} FPS ({Device.Statistics.GetGameFrameTime():00.00} ms)", $"Game: {Device.Statistics.GetGameFrameRate():00.00} FPS ({Device.Statistics.GetGameFrameTime():00.00} ms)",
$"FIFO: {Device.Statistics.GetFifoPercent():0.00} %", $"FIFO: {Device.Statistics.GetFifoPercent():0.00} %",
$"GPU: {_gpuDriverName}")); $"GPU: {_gpuDriverName}"));
@@ -1,6 +1,6 @@
using System; using System;
namespace Ryujinx.Ava.Utilities.AppLibrary namespace Ryujinx.UI.App.Common
{ {
public class ApplicationCountUpdatedEventArgs : EventArgs public class ApplicationCountUpdatedEventArgs : EventArgs
{ {
@@ -10,14 +10,17 @@ using LibHac.Tools.FsSystem.NcaUtils;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.FileSystem;
using Ryujinx.HLE.Loaders.Processes.Extensions; using Ryujinx.HLE.Loaders.Processes.Extensions;
using Ryujinx.UI.Common.Helper;
using System; using System;
using System.IO; using System.IO;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace Ryujinx.Ava.Utilities.AppLibrary namespace Ryujinx.UI.App.Common
{ {
public class ApplicationData public class ApplicationData
{ {
public static Func<string> LocalizedNever { get; set; } = () => "Never";
public bool Favorite { get; set; } public bool Favorite { get; set; }
public byte[] Icon { get; set; } public byte[] Icon { get; set; }
public string Name { get; set; } = "Unknown"; public string Name { get; set; } = "Unknown";
@@ -33,11 +36,9 @@ namespace Ryujinx.Ava.Utilities.AppLibrary
public string Path { get; set; } public string Path { get; set; }
public BlitStruct<ApplicationControlProperty> ControlHolder { get; set; } public BlitStruct<ApplicationControlProperty> ControlHolder { get; set; }
public bool HasControlHolder => ControlHolder.ByteSpan.Length > 0;
public string TimePlayedString => ValueFormatUtils.FormatTimeSpan(TimePlayed); public string TimePlayedString => ValueFormatUtils.FormatTimeSpan(TimePlayed);
public string LastPlayedString => ValueFormatUtils.FormatDateTime(LastPlayed)?.Replace(" ", "\n"); public string LastPlayedString => ValueFormatUtils.FormatDateTime(LastPlayed)?.Replace(" ", "\n") ?? LocalizedNever();
public string FileSizeString => ValueFormatUtils.FormatFileSize(FileSize); public string FileSizeString => ValueFormatUtils.FormatFileSize(FileSize);
@@ -1,6 +1,6 @@
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace Ryujinx.Ava.Utilities.AppLibrary namespace Ryujinx.UI.App.Common
{ {
[JsonSourceGenerationOptions(WriteIndented = true)] [JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(ApplicationMetadata))] [JsonSerializable(typeof(ApplicationMetadata))]
@@ -10,10 +10,6 @@ using LibHac.Ns;
using LibHac.Tools.Fs; using LibHac.Tools.Fs;
using LibHac.Tools.FsSystem; using LibHac.Tools.FsSystem;
using LibHac.Tools.FsSystem.NcaUtils; using LibHac.Tools.FsSystem.NcaUtils;
using Ryujinx.Ava.Common.Models;
using Ryujinx.Ava.Utilities.Configuration;
using Ryujinx.Ava.Utilities.Configuration.System;
using Ryujinx.Common;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Configuration.Multiplayer; using Ryujinx.Common.Configuration.Multiplayer;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
@@ -23,11 +19,16 @@ using Ryujinx.HLE.HOS.SystemState;
using Ryujinx.HLE.Loaders.Npdm; using Ryujinx.HLE.Loaders.Npdm;
using Ryujinx.HLE.Loaders.Processes.Extensions; using Ryujinx.HLE.Loaders.Processes.Extensions;
using Ryujinx.HLE.Utilities; using Ryujinx.HLE.Utilities;
using Ryujinx.UI.Common.Configuration;
using Ryujinx.UI.Common.Configuration.System;
using Ryujinx.UI.Common.Helper;
using Ryujinx.UI.Common.Models;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Net.Http; using System.Net.Http;
using System.Reflection;
using System.Text; using System.Text;
using System.Text.Json; using System.Text.Json;
using System.Threading; using System.Threading;
@@ -37,7 +38,7 @@ using MissingKeyException = LibHac.Common.Keys.MissingKeyException;
using Path = System.IO.Path; using Path = System.IO.Path;
using TimeSpan = System.TimeSpan; using TimeSpan = System.TimeSpan;
namespace Ryujinx.Ava.Utilities.AppLibrary namespace Ryujinx.UI.App.Common
{ {
public class ApplicationLibrary public class ApplicationLibrary
{ {
@@ -75,11 +76,21 @@ namespace Ryujinx.Ava.Utilities.AppLibrary
TitleUpdates = _titleUpdates.AsObservableCache(); TitleUpdates = _titleUpdates.AsObservableCache();
DownloadableContents = _downloadableContents.AsObservableCache(); DownloadableContents = _downloadableContents.AsObservableCache();
_nspIcon = EmbeddedResources.Read("Ryujinx/Assets.UIImages.Icon_NSP.png"); _nspIcon = GetResourceBytes("Ryujinx.UI.Common.Resources.Icon_NSP.png");
_xciIcon = EmbeddedResources.Read("Ryujinx/Assets.UIImages.Icon_XCI.png"); _xciIcon = GetResourceBytes("Ryujinx.UI.Common.Resources.Icon_XCI.png");
_ncaIcon = EmbeddedResources.Read("Ryujinx/Assets.UIImages.Icon_NCA.png"); _ncaIcon = GetResourceBytes("Ryujinx.UI.Common.Resources.Icon_NCA.png");
_nroIcon = EmbeddedResources.Read("Ryujinx/Assets.UIImages.Icon_NRO.png"); _nroIcon = GetResourceBytes("Ryujinx.UI.Common.Resources.Icon_NRO.png");
_nsoIcon = EmbeddedResources.Read("Ryujinx/Assets.UIImages.Icon_NSO.png"); _nsoIcon = GetResourceBytes("Ryujinx.UI.Common.Resources.Icon_NSO.png");
}
private static byte[] GetResourceBytes(string resourceName)
{
Stream resourceStream = Assembly.GetCallingAssembly().GetManifestResourceStream(resourceName)!;
byte[] resourceByteArray = new byte[resourceStream.Length];
resourceStream.ReadExactly(resourceByteArray);
return resourceByteArray;
} }
/// <exception cref="Ryujinx.HLE.Exceptions.InvalidNpdmException">The npdm file doesn't contain valid data.</exception> /// <exception cref="Ryujinx.HLE.Exceptions.InvalidNpdmException">The npdm file doesn't contain valid data.</exception>
@@ -778,15 +789,16 @@ namespace Ryujinx.Ava.Utilities.AppLibrary
using HttpClient httpClient = new HttpClient(); using HttpClient httpClient = new HttpClient();
string ldnGameDataArrayString = await httpClient.GetStringAsync($"https://{ldnWebHost}/api/public_games"); string ldnGameDataArrayString = await httpClient.GetStringAsync($"https://{ldnWebHost}/api/public_games");
ldnGameDataArray = JsonHelper.Deserialize(ldnGameDataArrayString, _ldnDataSerializerContext.IEnumerableLdnGameData); ldnGameDataArray = JsonHelper.Deserialize(ldnGameDataArrayString, _ldnDataSerializerContext.IEnumerableLdnGameData);
LdnGameDataReceived?.Invoke(null, new LdnGameDataReceivedEventArgs var evt = new LdnGameDataReceivedEventArgs
{ {
LdnData = ldnGameDataArray LdnData = ldnGameDataArray
}); };
LdnGameDataReceived?.Invoke(null, evt);
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Warning?.Print(LogClass.Application, $"Failed to fetch the public games JSON from the API. Player and game count in the game list will be unavailable.\n{ex.Message}"); Logger.Warning?.Print(LogClass.Application, $"Failed to fetch the public games JSON from the API. Player and game count in the game list will be unavailable.\n{ex.Message}");
LdnGameDataReceived?.Invoke(null, new LdnGameDataReceivedEventArgs LdnGameDataReceived?.Invoke(null, new LdnGameDataReceivedEventArgs()
{ {
LdnData = Array.Empty<LdnGameData>() LdnData = Array.Empty<LdnGameData>()
}); });
@@ -794,7 +806,7 @@ namespace Ryujinx.Ava.Utilities.AppLibrary
} }
else else
{ {
LdnGameDataReceived?.Invoke(null, new LdnGameDataReceivedEventArgs LdnGameDataReceived?.Invoke(null, new LdnGameDataReceivedEventArgs()
{ {
LdnData = Array.Empty<LdnGameData>() LdnData = Array.Empty<LdnGameData>()
}); });
@@ -1,7 +1,7 @@
using System; using System;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace Ryujinx.Ava.Utilities.AppLibrary namespace Ryujinx.UI.App.Common
{ {
public class ApplicationMetadata public class ApplicationMetadata
{ {
+16
View File
@@ -0,0 +1,16 @@
using System.Collections.Generic;
namespace Ryujinx.UI.App.Common
{
public struct LdnGameData
{
public string Id { get; set; }
public int PlayerCount { get; set; }
public int MaxPlayerCount { get; set; }
public string GameName { get; set; }
public string TitleId { get; set; }
public string Mode { get; set; }
public string Status { get; set; }
public IEnumerable<string> Players { get; set; }
}
}
@@ -1,7 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace Ryujinx.Ava.Utilities.AppLibrary namespace Ryujinx.UI.App.Common
{ {
public class LdnGameDataReceivedEventArgs : EventArgs public class LdnGameDataReceivedEventArgs : EventArgs
{ {
@@ -1,8 +1,11 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace Ryujinx.Ava.Utilities.AppLibrary namespace Ryujinx.UI.App.Common
{ {
[JsonSerializable(typeof(IEnumerable<LdnGameData>))] [JsonSerializable(typeof(IEnumerable<LdnGameData>))]
internal partial class LdnGameDataSerializerContext : JsonSerializerContext; internal partial class LdnGameDataSerializerContext : JsonSerializerContext
{
}
} }
@@ -1,7 +1,7 @@
using Ryujinx.Common.Utilities; using Ryujinx.Common.Utilities;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace Ryujinx.Ava.Utilities.Configuration namespace Ryujinx.UI.Common.Configuration
{ {
[JsonConverter(typeof(TypedStringEnumConverter<AudioBackend>))] [JsonConverter(typeof(TypedStringEnumConverter<AudioBackend>))]
public enum AudioBackend public enum AudioBackend
@@ -1,5 +1,3 @@
using Ryujinx.Ava.Utilities.Configuration.System;
using Ryujinx.Ava.Utilities.Configuration.UI;
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Configuration.Hid; using Ryujinx.Common.Configuration.Hid;
@@ -7,17 +5,19 @@ using Ryujinx.Common.Configuration.Multiplayer;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Common.Utilities; using Ryujinx.Common.Utilities;
using Ryujinx.HLE; using Ryujinx.HLE;
using Ryujinx.UI.Common.Configuration.System;
using Ryujinx.UI.Common.Configuration.UI;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text.Json.Nodes; using System.Text.Json.Nodes;
namespace Ryujinx.Ava.Utilities.Configuration namespace Ryujinx.UI.Common.Configuration
{ {
public class ConfigurationFileFormat public class ConfigurationFileFormat
{ {
/// <summary> /// <summary>
/// The current version of the file format /// The current version of the file format
/// </summary> /// </summary>
public const int CurrentVersion = 59; public const int CurrentVersion = 57;
/// <summary> /// <summary>
/// Version of the configuration file format /// Version of the configuration file format
@@ -429,17 +429,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
/// Uses Hypervisor over JIT if available /// Uses Hypervisor over JIT if available
/// </summary> /// </summary>
public bool UseHypervisor { get; set; } public bool UseHypervisor { get; set; }
/// <summary>
/// Show toggles for dirty hacks in the UI.
/// </summary>
public bool ShowDirtyHacks { get; set; }
/// <summary>
/// The packed values of the enabled dirty hacks.
/// </summary>
public ulong[] DirtyHacks { get; set; }
/// <summary> /// <summary>
/// Loads a configuration file from disk /// Loads a configuration file from disk
/// </summary> /// </summary>
@@ -1,6 +1,6 @@
using Ryujinx.Common.Utilities; using Ryujinx.Common.Utilities;
namespace Ryujinx.Ava.Utilities.Configuration namespace Ryujinx.UI.Common.Configuration
{ {
internal static class ConfigurationFileFormatSettings internal static class ConfigurationFileFormatSettings
{ {
@@ -1,8 +1,10 @@
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace Ryujinx.Ava.Utilities.Configuration namespace Ryujinx.UI.Common.Configuration
{ {
[JsonSourceGenerationOptions(WriteIndented = true)] [JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(ConfigurationFileFormat))] [JsonSerializable(typeof(ConfigurationFileFormat))]
internal partial class ConfigurationJsonSerializerContext : JsonSerializerContext; internal partial class ConfigurationJsonSerializerContext : JsonSerializerContext
{
}
} }
@@ -1,6 +1,3 @@
using Gommon;
using Ryujinx.Ava.Utilities.Configuration.System;
using Ryujinx.Ava.Utilities.Configuration.UI;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Configuration.Hid; using Ryujinx.Common.Configuration.Hid;
using Ryujinx.Common.Configuration.Hid.Controller; using Ryujinx.Common.Configuration.Hid.Controller;
@@ -8,10 +5,12 @@ using Ryujinx.Common.Configuration.Hid.Keyboard;
using Ryujinx.Common.Configuration.Multiplayer; using Ryujinx.Common.Configuration.Multiplayer;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.HLE; using Ryujinx.HLE;
using Ryujinx.UI.Common.Configuration.System;
using Ryujinx.UI.Common.Configuration.UI;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace Ryujinx.Ava.Utilities.Configuration namespace Ryujinx.UI.Common.Configuration
{ {
public partial class ConfigurationState public partial class ConfigurationState
{ {
@@ -638,18 +637,6 @@ namespace Ryujinx.Ava.Utilities.Configuration
configurationFileUpdated = true; configurationFileUpdated = true;
} }
// 58 migration accidentally got skipped but it worked with no issues somehow lol
if (configurationFileFormat.Version < 59)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 59.");
configurationFileFormat.ShowDirtyHacks = false;
configurationFileFormat.DirtyHacks = [];
configurationFileUpdated = true;
}
Logger.EnableFileLog.Value = configurationFileFormat.EnableFileLog; Logger.EnableFileLog.Value = configurationFileFormat.EnableFileLog;
Graphics.ResScale.Value = configurationFileFormat.ResScale; Graphics.ResScale.Value = configurationFileFormat.ResScale;
@@ -748,17 +735,6 @@ namespace Ryujinx.Ava.Utilities.Configuration
Multiplayer.DisableP2p.Value = configurationFileFormat.MultiplayerDisableP2p; Multiplayer.DisableP2p.Value = configurationFileFormat.MultiplayerDisableP2p;
Multiplayer.LdnPassphrase.Value = configurationFileFormat.MultiplayerLdnPassphrase; Multiplayer.LdnPassphrase.Value = configurationFileFormat.MultiplayerLdnPassphrase;
Multiplayer.LdnServer.Value = configurationFileFormat.LdnServer; Multiplayer.LdnServer.Value = configurationFileFormat.LdnServer;
Hacks.ShowDirtyHacks.Value = configurationFileFormat.ShowDirtyHacks;
{
DirtyHackCollection hacks = new (configurationFileFormat.DirtyHacks ?? []);
Hacks.Xc2MenuSoftlockFix.Value = hacks.IsEnabled(DirtyHacks.Xc2MenuSoftlockFix);
Hacks.EnableShaderTranslationDelay.Value = hacks.IsEnabled(DirtyHacks.ShaderCompilationThreadSleep);
Hacks.ShaderTranslationDelay.Value = hacks[DirtyHacks.ShaderCompilationThreadSleep].CoerceAtLeast(0);
}
if (configurationFileUpdated) if (configurationFileUpdated)
{ {
@@ -1,18 +1,15 @@
using ARMeilleure; using ARMeilleure;
using Gommon;
using Ryujinx.Ava.Utilities.Configuration.System;
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Configuration.Hid; using Ryujinx.Common.Configuration.Hid;
using Ryujinx.Common.Configuration.Multiplayer; using Ryujinx.Common.Configuration.Multiplayer;
using Ryujinx.Common.Helper;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.HLE; using Ryujinx.HLE;
using Ryujinx.UI.Common.Configuration.System;
using Ryujinx.UI.Common.Helper;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using RyuLogger = Ryujinx.Common.Logging.Logger;
namespace Ryujinx.Ava.Utilities.Configuration namespace Ryujinx.UI.Common.Configuration
{ {
public partial class ConfigurationState public partial class ConfigurationState
{ {
@@ -620,67 +617,6 @@ namespace Ryujinx.Ava.Utilities.Configuration
} }
} }
public class HacksSection
{
/// <summary>
/// Show toggles for dirty hacks in the UI.
/// </summary>
public ReactiveObject<bool> ShowDirtyHacks { get; private set; }
public ReactiveObject<bool> Xc2MenuSoftlockFix { get; private set; }
public ReactiveObject<bool> EnableShaderTranslationDelay { get; private set; }
public ReactiveObject<int> ShaderTranslationDelay { get; private set; }
public HacksSection()
{
ShowDirtyHacks = new ReactiveObject<bool>();
Xc2MenuSoftlockFix = new ReactiveObject<bool>();
Xc2MenuSoftlockFix.Event += HackChanged;
EnableShaderTranslationDelay = new ReactiveObject<bool>();
EnableShaderTranslationDelay.Event += HackChanged;
ShaderTranslationDelay = new ReactiveObject<int>();
}
private void HackChanged(object sender, ReactiveEventArgs<bool> rxe)
{
var newHacks = EnabledHacks.Select(x => x.Hack)
.JoinToString(", ");
if (newHacks != _lastHackCollection)
{
RyuLogger.Info?.Print(LogClass.Configuration,
$"EnabledDirtyHacks set to: [{newHacks}]", "LogValueChange");
_lastHackCollection = newHacks;
}
}
private static string _lastHackCollection;
public EnabledDirtyHack[] EnabledHacks
{
get
{
List<EnabledDirtyHack> enabledHacks = [];
if (Xc2MenuSoftlockFix)
Apply(DirtyHacks.Xc2MenuSoftlockFix);
if (EnableShaderTranslationDelay)
Apply(DirtyHacks.ShaderCompilationThreadSleep, ShaderTranslationDelay);
return enabledHacks.ToArray();
void Apply(DirtyHacks hack, int value = 0)
{
enabledHacks.Add(new EnabledDirtyHack(hack, value));
}
}
}
}
/// <summary> /// <summary>
/// The default configuration instance /// The default configuration instance
/// </summary> /// </summary>
@@ -715,11 +651,6 @@ namespace Ryujinx.Ava.Utilities.Configuration
/// The Multiplayer section /// The Multiplayer section
/// </summary> /// </summary>
public MultiplayerSection Multiplayer { get; private set; } public MultiplayerSection Multiplayer { get; private set; }
/// <summary>
/// The Dirty Hacks section
/// </summary>
public HacksSection Hacks { get; private set; }
/// <summary> /// <summary>
/// Enables or disables Discord Rich Presence /// Enables or disables Discord Rich Presence
@@ -769,7 +700,6 @@ namespace Ryujinx.Ava.Utilities.Configuration
Graphics = new GraphicsSection(); Graphics = new GraphicsSection();
Hid = new HidSection(); Hid = new HidSection();
Multiplayer = new MultiplayerSection(); Multiplayer = new MultiplayerSection();
Hacks = new HacksSection();
EnableDiscordIntegration = new ReactiveObject<bool>(); EnableDiscordIntegration = new ReactiveObject<bool>();
CheckUpdatesOnStart = new ReactiveObject<bool>(); CheckUpdatesOnStart = new ReactiveObject<bool>();
ShowConfirmExit = new ReactiveObject<bool>(); ShowConfirmExit = new ReactiveObject<bool>();
@@ -1,15 +1,14 @@
using Ryujinx.Ava.Utilities.Configuration.System;
using Ryujinx.Ava.Utilities.Configuration.UI;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Configuration.Hid; using Ryujinx.Common.Configuration.Hid;
using Ryujinx.Common.Configuration.Hid.Keyboard; using Ryujinx.Common.Configuration.Hid.Keyboard;
using Ryujinx.Common.Configuration.Multiplayer; using Ryujinx.Common.Configuration.Multiplayer;
using Ryujinx.Graphics.Vulkan; using Ryujinx.Graphics.Vulkan;
using Ryujinx.HLE; using Ryujinx.HLE;
using Ryujinx.UI.Common.Configuration.System;
using Ryujinx.UI.Common.Configuration.UI;
using System; using System;
using System.Linq;
namespace Ryujinx.Ava.Utilities.Configuration namespace Ryujinx.UI.Common.Configuration
{ {
public partial class ConfigurationState public partial class ConfigurationState
{ {
@@ -139,8 +138,6 @@ namespace Ryujinx.Ava.Utilities.Configuration
MultiplayerDisableP2p = Multiplayer.DisableP2p, MultiplayerDisableP2p = Multiplayer.DisableP2p,
MultiplayerLdnPassphrase = Multiplayer.LdnPassphrase, MultiplayerLdnPassphrase = Multiplayer.LdnPassphrase,
LdnServer = Multiplayer.LdnServer, LdnServer = Multiplayer.LdnServer,
ShowDirtyHacks = Hacks.ShowDirtyHacks,
DirtyHacks = Hacks.EnabledHacks.Select(it => it.Pack()).ToArray(),
}; };
return configurationFile; return configurationFile;
@@ -0,0 +1,12 @@
namespace Ryujinx.UI.Common
{
public enum FileTypes
{
NSP,
PFS0,
XCI,
NCA,
NRO,
NSO
}
}
@@ -4,7 +4,7 @@ using Ryujinx.Common.Logging.Targets;
using System; using System;
using System.IO; using System.IO;
namespace Ryujinx.Ava.Utilities.Configuration namespace Ryujinx.UI.Common.Configuration
{ {
public static class LoggerModule public static class LoggerModule
{ {
@@ -1,7 +1,7 @@
using Ryujinx.Common.Utilities; using Ryujinx.Common.Utilities;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace Ryujinx.Ava.Utilities.Configuration.System namespace Ryujinx.UI.Common.Configuration.System
{ {
[JsonConverter(typeof(TypedStringEnumConverter<Language>))] [JsonConverter(typeof(TypedStringEnumConverter<Language>))]
public enum Language public enum Language
@@ -1,7 +1,7 @@
using Ryujinx.Common.Utilities; using Ryujinx.Common.Utilities;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace Ryujinx.Ava.Utilities.Configuration.System namespace Ryujinx.UI.Common.Configuration.System
{ {
[JsonConverter(typeof(TypedStringEnumConverter<Region>))] [JsonConverter(typeof(TypedStringEnumConverter<Region>))]
public enum Region public enum Region
@@ -1,4 +1,4 @@
namespace Ryujinx.Ava.Utilities.Configuration.UI namespace Ryujinx.UI.Common.Configuration.UI
{ {
public struct ColumnSort public struct ColumnSort
{ {
@@ -1,4 +1,4 @@
namespace Ryujinx.Ava.Utilities.Configuration.UI namespace Ryujinx.UI.Common.Configuration.UI
{ {
public struct GuiColumns public struct GuiColumns
{ {
@@ -1,4 +1,4 @@
namespace Ryujinx.Ava.Utilities.Configuration.UI namespace Ryujinx.UI.Common.Configuration.UI
{ {
public struct ShownFileTypes public struct ShownFileTypes
{ {
@@ -1,4 +1,4 @@
namespace Ryujinx.Ava.Utilities.Configuration.UI namespace Ryujinx.UI.Common.Configuration.UI
{ {
public struct WindowStartup public struct WindowStartup
{ {
@@ -1,51 +1,129 @@
using Gommon; using DiscordRPC;
using Ryujinx.Common.Configuration; using Humanizer;
using System; using Humanizer.Localisation;
using Ryujinx.Common;
using Ryujinx.HLE.Loaders.Processes;
using Ryujinx.UI.App.Common;
using Ryujinx.UI.Common.Configuration;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices; using System.Text;
namespace Ryujinx.Common namespace Ryujinx.UI.Common
{ {
public static class TitleIDs public static class DiscordIntegrationModule
{ {
public static ReactiveObject<Optional<string>> CurrentApplication { get; set; } = new(); public static Timestamps StartedAt { get; set; }
public static GraphicsBackend SelectGraphicsBackend(string titleId, GraphicsBackend currentBackend) private static string VersionString
=> (ReleaseInformation.IsCanaryBuild ? "Canary " : string.Empty) + $"v{ReleaseInformation.Version}";
private static readonly string _description =
ReleaseInformation.IsValid
? $"{VersionString} {ReleaseInformation.ReleaseChannelOwner}/{ReleaseInformation.ReleaseChannelSourceRepo}@{ReleaseInformation.BuildGitHash}"
: "dev build";
private const string ApplicationId = "1293250299716173864";
private const int ApplicationByteLimit = 128;
private const string Ellipsis = "…";
private static DiscordRpcClient _discordClient;
private static RichPresence _discordPresenceMain;
public static void Initialize()
{ {
switch (currentBackend) _discordPresenceMain = new RichPresence
{ {
case GraphicsBackend.OpenGl when OperatingSystem.IsMacOS(): Assets = new Assets
return GraphicsBackend.Vulkan; {
case GraphicsBackend.Vulkan or GraphicsBackend.OpenGl or GraphicsBackend.Metal: LargeImageKey = "ryujinx",
return currentBackend; LargeImageText = TruncateToByteLength(_description)
},
Details = "Main Menu",
State = "Idling",
Timestamps = StartedAt
};
ConfigurationState.Instance.EnableDiscordIntegration.Event += Update;
}
private static void Update(object sender, ReactiveEventArgs<bool> evnt)
{
if (evnt.OldValue != evnt.NewValue)
{
// If the integration was active, disable it and unload everything
if (evnt.OldValue)
{
_discordClient?.Dispose();
_discordClient = null;
}
// If we need to activate it and the client isn't active, initialize it
if (evnt.NewValue && _discordClient == null)
{
_discordClient = new DiscordRpcClient(ApplicationId);
_discordClient.Initialize();
_discordClient.SetPresence(_discordPresenceMain);
}
}
}
public static void SwitchToPlayingState(ApplicationMetadata appMeta, ProcessResult procRes)
{
_discordClient?.SetPresence(new RichPresence
{
Assets = new Assets
{
LargeImageKey = _discordGameAssetKeys.Contains(procRes.ProgramIdText) ? procRes.ProgramIdText : "game",
LargeImageText = TruncateToByteLength($"{appMeta.Title} (v{procRes.DisplayVersion})"),
SmallImageKey = "ryujinx",
SmallImageText = TruncateToByteLength(_description)
},
Details = TruncateToByteLength($"Playing {appMeta.Title}"),
State = appMeta.LastPlayed.HasValue && appMeta.TimePlayed.TotalSeconds > 5
? $"Total play time: {appMeta.TimePlayed.Humanize(2, false, maxUnit: TimeUnit.Hour)}"
: "Never played",
Timestamps = Timestamps.Now
});
}
public static void SwitchToMainState() => _discordClient?.SetPresence(_discordPresenceMain);
private static string TruncateToByteLength(string input)
{
if (Encoding.UTF8.GetByteCount(input) <= ApplicationByteLimit)
{
return input;
} }
if (!(OperatingSystem.IsMacOS() && RuntimeInformation.ProcessArchitecture is Architecture.Arm64)) // Find the length to trim the string to guarantee we have space for the trailing ellipsis.
return GraphicsBackend.Vulkan; int trimLimit = ApplicationByteLimit - Encoding.UTF8.GetByteCount(Ellipsis);
return GreatMetalTitles.ContainsIgnoreCase(titleId) ? GraphicsBackend.Metal : GraphicsBackend.Vulkan; // Make sure the string is long enough to perform the basic trim.
// Amount of bytes != Length of the string
if (input.Length > trimLimit)
{
// Basic trim to best case scenario of 1 byte characters.
input = input[..trimLimit];
}
while (Encoding.UTF8.GetByteCount(input) > trimLimit)
{
// Remove one character from the end of the string at a time.
input = input[..^1];
}
return input.TrimEnd() + Ellipsis;
} }
public static readonly string[] GreatMetalTitles =
[
"01006f8002326000", // Animal Crossings: New Horizons
"01009bf0072d4000", // Captain Toad: Treasure Tracker
"0100a5c00d162000", // Cuphead
"010023800d64a000", // Deltarune
"010028600EBDA000", // Mario 3D World
"0100152000022000", // Mario Kart 8 Deluxe
"01005CA01580E000", // Persona 5
"0100187003A36000", // Pokémon: Let's Go, Evoli!
"010003f003a34000", // Pokémon: Let's Go, Pikachu!
"01008C0016544000", // Sea of Stars
"01006A800016E000", // Smash Ultimate
"0100000000010000", // Super Mario Odyessy
];
public static string GetDiscordGameAsset(string titleId)
=> DiscordGameAssetKeys.Contains(titleId) ? titleId : "game";
public static readonly string[] DiscordGameAssetKeys = public static void Exit()
{
_discordClient?.Dispose();
}
private static readonly string[] _discordGameAssetKeys =
[ [
"010055d009f78000", // Fire Emblem: Three Houses "010055d009f78000", // Fire Emblem: Three Houses
"0100a12011cc8000", // Fire Emblem: Shadow Dragon "0100a12011cc8000", // Fire Emblem: Shadow Dragon
@@ -1,19 +1,8 @@
using System; using System;
using static Ryujinx.UI.Common.Configuration.ConfigurationState.UISection;
using static Ryujinx.Ava.Utilities.Configuration.ConfigurationState.UISection; namespace Ryujinx.UI.Common
namespace Ryujinx.Ava.Utilities.Configuration
{ {
public enum FileTypes
{
NSP,
PFS0,
XCI,
NCA,
NRO,
NSO
}
public static class FileTypesExtensions public static class FileTypesExtensions
{ {
/// <summary> /// <summary>
@@ -21,7 +10,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
/// </summary> /// </summary>
/// <param name="type">The name of the <see cref="ShownFileTypeSettings"/> parameter to get the value of.</param> /// <param name="type">The name of the <see cref="ShownFileTypeSettings"/> parameter to get the value of.</param>
/// <param name="config">The config instance to get the value from.</param> /// <param name="config">The config instance to get the value from.</param>
/// <returns>The current value of the setting. Value is <see langword="true"/> if the file type is to be shown on the games list, <see langword="false"/> otherwise.</returns> /// <returns>The current value of the setting. Value is <see langword="true"/> if the file type is the be shown on the games list, <see langword="false"/> otherwise.</returns>
public static bool GetConfigValue(this FileTypes type, ShownFileTypeSettings config) => type switch public static bool GetConfigValue(this FileTypes type, ShownFileTypeSettings config) => type switch
{ {
FileTypes.NSP => config.NSP.Value, FileTypes.NSP => config.NSP.Value,
@@ -1,7 +1,7 @@
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using System.Collections.Generic; using System.Collections.Generic;
namespace Ryujinx.Ava.Utilities namespace Ryujinx.UI.Common.Helper
{ {
public static class CommandLineState public static class CommandLineState
{ {
@@ -3,7 +3,7 @@ using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Runtime.Versioning; using System.Runtime.Versioning;
namespace Ryujinx.Common.Helper namespace Ryujinx.UI.Common.Helper
{ {
public static partial class ConsoleHelper public static partial class ConsoleHelper
{ {
@@ -3,18 +3,18 @@ using LibHac.Fs;
using LibHac.Fs.Fsa; using LibHac.Fs.Fsa;
using LibHac.Tools.FsSystem; using LibHac.Tools.FsSystem;
using LibHac.Tools.FsSystem.NcaUtils; using LibHac.Tools.FsSystem.NcaUtils;
using Ryujinx.Ava.Common.Models;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Common.Utilities; using Ryujinx.Common.Utilities;
using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.FileSystem;
using Ryujinx.HLE.Utilities; using Ryujinx.HLE.Utilities;
using Ryujinx.UI.Common.Models;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using Path = System.IO.Path; using Path = System.IO.Path;
namespace Ryujinx.Ava.Utilities namespace Ryujinx.UI.Common.Helper
{ {
public static class DownloadableContentsHelper public static class DownloadableContentsHelper
{ {
@@ -8,7 +8,7 @@ using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Runtime.Versioning; using System.Runtime.Versioning;
namespace Ryujinx.Common.Helper namespace Ryujinx.UI.Common.Helper
{ {
public static partial class FileAssociationHelper public static partial class FileAssociationHelper
{ {
@@ -132,7 +132,7 @@ namespace Ryujinx.Common.Helper
if (uninstall) if (uninstall)
{ {
// If the types don't already exist, there's nothing to do, and we can call this operation successful. // If the types don't already exist, there's nothing to do and we can call this operation successful.
if (!AreMimeTypesRegisteredWindows()) if (!AreMimeTypesRegisteredWindows())
{ {
return true; return true;
@@ -3,7 +3,7 @@ using System.Diagnostics;
using System.IO; using System.IO;
using System.Runtime.Versioning; using System.Runtime.Versioning;
namespace Ryujinx.Common.Helper namespace Ryujinx.UI.Common.Helper
{ {
[SupportedOSPlatform("linux")] [SupportedOSPlatform("linux")]
public static class LinuxHelper public static class LinuxHelper
@@ -2,7 +2,7 @@ using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Runtime.Versioning; using System.Runtime.Versioning;
namespace Ryujinx.Common.Helper namespace Ryujinx.UI.Common.Helper
{ {
[SupportedOSPlatform("macos")] [SupportedOSPlatform("macos")]
public static partial class ObjectiveC public static partial class ObjectiveC
@@ -5,7 +5,7 @@ using System.Diagnostics;
using System.IO; using System.IO;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace Ryujinx.Common.Helper namespace Ryujinx.UI.Common.Helper
{ {
public static partial class OpenHelper public static partial class OpenHelper
{ {
@@ -1,10 +1,9 @@
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Common.UI;
using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.FileSystem;
using System; using System;
using System.IO; using System.IO;
namespace Ryujinx.Ava.Utilities namespace Ryujinx.UI.Common.Helper
{ {
/// <summary> /// <summary>
/// Ensure installation validity /// Ensure installation validity
@@ -7,7 +7,7 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Runtime.Versioning; using System.Runtime.Versioning;
namespace Ryujinx.Ava.Utilities namespace Ryujinx.UI.Common.Helper
{ {
public static class ShortcutHelper public static class ShortcutHelper
{ {
@@ -31,7 +31,7 @@ namespace Ryujinx.Ava.Utilities
private static void CreateShortcutLinux(string applicationFilePath, string applicationId, byte[] iconData, string iconPath, string desktopPath, string cleanedAppName) private static void CreateShortcutLinux(string applicationFilePath, string applicationId, byte[] iconData, string iconPath, string desktopPath, string cleanedAppName)
{ {
string basePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Ryujinx.sh"); string basePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Ryujinx.sh");
var desktopFile = EmbeddedResources.ReadAllText("Ryujinx/Assets/ShortcutFiles/shortcut-template.desktop"); var desktopFile = EmbeddedResources.ReadAllText("Ryujinx.UI.Common/shortcut-template.desktop");
iconPath += ".png"; iconPath += ".png";
var image = SKBitmap.Decode(iconData); var image = SKBitmap.Decode(iconData);
@@ -47,8 +47,8 @@ namespace Ryujinx.Ava.Utilities
private static void CreateShortcutMacos(string appFilePath, string applicationId, byte[] iconData, string desktopPath, string cleanedAppName) private static void CreateShortcutMacos(string appFilePath, string applicationId, byte[] iconData, string desktopPath, string cleanedAppName)
{ {
string basePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Ryujinx"); string basePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Ryujinx");
var plistFile = EmbeddedResources.ReadAllText("Ryujinx/Assets/ShortcutFiles/shortcut-template.plist"); var plistFile = EmbeddedResources.ReadAllText("Ryujinx.UI.Common/shortcut-template.plist");
var shortcutScript = EmbeddedResources.ReadAllText("Ryujinx/Assets/ShortcutFiles/shortcut-launch-script.sh"); var shortcutScript = EmbeddedResources.ReadAllText("Ryujinx.UI.Common/shortcut-launch-script.sh");
// Macos .App folder // Macos .App folder
string contentFolderPath = Path.Combine("/Applications", cleanedAppName + ".app", "Contents"); string contentFolderPath = Path.Combine("/Applications", cleanedAppName + ".app", "Contents");
string scriptFolderPath = Path.Combine(contentFolderPath, "MacOS"); string scriptFolderPath = Path.Combine(contentFolderPath, "MacOS");

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